pcmcia.c revision 1d5cc192d431bce2ebe9fde64054ce903200e179
1/*
2 * Sonics Silicon Backplane
3 * PCMCIA-Hostbus related functions
4 *
5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
7 *
8 * Licensed under the GNU/GPL. See COPYING for details.
9 */
10
11#include <linux/ssb/ssb.h>
12#include <linux/delay.h>
13#include <linux/io.h>
14#include <linux/etherdevice.h>
15
16#include <pcmcia/cs.h>
17#include <pcmcia/cistpl.h>
18#include <pcmcia/ciscode.h>
19#include <pcmcia/ds.h>
20#include <pcmcia/cisreg.h>
21
22#include "ssb_private.h"
23
24
25/* Define the following to 1 to enable a printk on each coreswitch. */
26#define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG		0
27
28
29/* PCMCIA configuration registers */
30#define SSB_PCMCIA_ADDRESS0		0x2E
31#define SSB_PCMCIA_ADDRESS1		0x30
32#define SSB_PCMCIA_ADDRESS2		0x32
33#define SSB_PCMCIA_MEMSEG		0x34
34#define SSB_PCMCIA_SPROMCTL		0x36
35#define  SSB_PCMCIA_SPROMCTL_IDLE	0
36#define  SSB_PCMCIA_SPROMCTL_WRITE	1
37#define  SSB_PCMCIA_SPROMCTL_READ	2
38#define  SSB_PCMCIA_SPROMCTL_WRITEEN	4
39#define  SSB_PCMCIA_SPROMCTL_WRITEDIS	7
40#define  SSB_PCMCIA_SPROMCTL_DONE	8
41#define SSB_PCMCIA_SPROM_DATALO		0x38
42#define SSB_PCMCIA_SPROM_DATAHI		0x3A
43#define SSB_PCMCIA_SPROM_ADDRLO		0x3C
44#define SSB_PCMCIA_SPROM_ADDRHI		0x3E
45
46/* Hardware invariants CIS tuples */
47#define SSB_PCMCIA_CIS			0x80
48#define  SSB_PCMCIA_CIS_ID		0x01
49#define  SSB_PCMCIA_CIS_BOARDREV	0x02
50#define  SSB_PCMCIA_CIS_PA		0x03
51#define   SSB_PCMCIA_CIS_PA_PA0B0_LO	0
52#define   SSB_PCMCIA_CIS_PA_PA0B0_HI	1
53#define   SSB_PCMCIA_CIS_PA_PA0B1_LO	2
54#define   SSB_PCMCIA_CIS_PA_PA0B1_HI	3
55#define   SSB_PCMCIA_CIS_PA_PA0B2_LO	4
56#define   SSB_PCMCIA_CIS_PA_PA0B2_HI	5
57#define   SSB_PCMCIA_CIS_PA_ITSSI	6
58#define   SSB_PCMCIA_CIS_PA_MAXPOW	7
59#define  SSB_PCMCIA_CIS_OEMNAME		0x04
60#define  SSB_PCMCIA_CIS_CCODE		0x05
61#define  SSB_PCMCIA_CIS_ANTENNA		0x06
62#define  SSB_PCMCIA_CIS_ANTGAIN		0x07
63#define  SSB_PCMCIA_CIS_BFLAGS		0x08
64#define  SSB_PCMCIA_CIS_LEDS		0x09
65
66/* PCMCIA SPROM size. */
67#define SSB_PCMCIA_SPROM_SIZE		256
68#define SSB_PCMCIA_SPROM_SIZE_BYTES	(SSB_PCMCIA_SPROM_SIZE * sizeof(u16))
69
70
71/* Write to a PCMCIA configuration register. */
72static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
73{
74	int res;
75
76	res = pcmcia_write_config_byte(bus->host_pcmcia, offset, value);
77	if (unlikely(res != 0))
78		return -EBUSY;
79
80	return 0;
81}
82
83/* Read from a PCMCIA configuration register. */
84static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
85{
86	int res;
87
88	res = pcmcia_read_config_byte(bus->host_pcmcia, offset, value);
89	if (unlikely(res != 0))
90		return -EBUSY;
91
92	return 0;
93}
94
95int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
96			      u8 coreidx)
97{
98	int err;
99	int attempts = 0;
100	u32 cur_core;
101	u32 addr;
102	u32 read_addr;
103	u8 val;
104
105	addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
106	while (1) {
107		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS0,
108					   (addr & 0x0000F000) >> 12);
109		if (err)
110			goto error;
111		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS1,
112					   (addr & 0x00FF0000) >> 16);
113		if (err)
114			goto error;
115		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS2,
116					   (addr & 0xFF000000) >> 24);
117		if (err)
118			goto error;
119
120		read_addr = 0;
121
122		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS0, &val);
123		if (err)
124			goto error;
125		read_addr |= ((u32)(val & 0x0F)) << 12;
126		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS1, &val);
127		if (err)
128			goto error;
129		read_addr |= ((u32)val) << 16;
130		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS2, &val);
131		if (err)
132			goto error;
133		read_addr |= ((u32)val) << 24;
134
135		cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
136		if (cur_core == coreidx)
137			break;
138
139		err = -ETIMEDOUT;
140		if (attempts++ > SSB_BAR0_MAX_RETRIES)
141			goto error;
142		udelay(10);
143	}
144
145	return 0;
146error:
147	ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
148	return err;
149}
150
151int ssb_pcmcia_switch_core(struct ssb_bus *bus,
152			   struct ssb_device *dev)
153{
154	int err;
155
156#if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG
157	ssb_printk(KERN_INFO PFX
158		   "Switching to %s core, index %d\n",
159		   ssb_core_name(dev->id.coreid),
160		   dev->core_index);
161#endif
162
163	err = ssb_pcmcia_switch_coreidx(bus, dev->core_index);
164	if (!err)
165		bus->mapped_device = dev;
166
167	return err;
168}
169
170int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
171{
172	int attempts = 0;
173	int err;
174	u8 val;
175
176	SSB_WARN_ON((seg != 0) && (seg != 1));
177	while (1) {
178		err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg);
179		if (err)
180			goto error;
181		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_MEMSEG, &val);
182		if (err)
183			goto error;
184		if (val == seg)
185			break;
186
187		err = -ETIMEDOUT;
188		if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))
189			goto error;
190		udelay(10);
191	}
192	bus->mapped_pcmcia_seg = seg;
193
194	return 0;
195error:
196	ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
197	return err;
198}
199
200static int select_core_and_segment(struct ssb_device *dev,
201				   u16 *offset)
202{
203	struct ssb_bus *bus = dev->bus;
204	int err;
205	u8 need_segment;
206
207	if (*offset >= 0x800) {
208		*offset -= 0x800;
209		need_segment = 1;
210	} else
211		need_segment = 0;
212
213	if (unlikely(dev != bus->mapped_device)) {
214		err = ssb_pcmcia_switch_core(bus, dev);
215		if (unlikely(err))
216			return err;
217	}
218	if (unlikely(need_segment != bus->mapped_pcmcia_seg)) {
219		err = ssb_pcmcia_switch_segment(bus, need_segment);
220		if (unlikely(err))
221			return err;
222	}
223
224	return 0;
225}
226
227static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)
228{
229	struct ssb_bus *bus = dev->bus;
230	unsigned long flags;
231	int err;
232	u8 value = 0xFF;
233
234	spin_lock_irqsave(&bus->bar_lock, flags);
235	err = select_core_and_segment(dev, &offset);
236	if (likely(!err))
237		value = readb(bus->mmio + offset);
238	spin_unlock_irqrestore(&bus->bar_lock, flags);
239
240	return value;
241}
242
243static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
244{
245	struct ssb_bus *bus = dev->bus;
246	unsigned long flags;
247	int err;
248	u16 value = 0xFFFF;
249
250	spin_lock_irqsave(&bus->bar_lock, flags);
251	err = select_core_and_segment(dev, &offset);
252	if (likely(!err))
253		value = readw(bus->mmio + offset);
254	spin_unlock_irqrestore(&bus->bar_lock, flags);
255
256	return value;
257}
258
259static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
260{
261	struct ssb_bus *bus = dev->bus;
262	unsigned long flags;
263	int err;
264	u32 lo = 0xFFFFFFFF, hi = 0xFFFFFFFF;
265
266	spin_lock_irqsave(&bus->bar_lock, flags);
267	err = select_core_and_segment(dev, &offset);
268	if (likely(!err)) {
269		lo = readw(bus->mmio + offset);
270		hi = readw(bus->mmio + offset + 2);
271	}
272	spin_unlock_irqrestore(&bus->bar_lock, flags);
273
274	return (lo | (hi << 16));
275}
276
277#ifdef CONFIG_SSB_BLOCKIO
278static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,
279				  size_t count, u16 offset, u8 reg_width)
280{
281	struct ssb_bus *bus = dev->bus;
282	unsigned long flags;
283	void __iomem *addr = bus->mmio + offset;
284	int err;
285
286	spin_lock_irqsave(&bus->bar_lock, flags);
287	err = select_core_and_segment(dev, &offset);
288	if (unlikely(err)) {
289		memset(buffer, 0xFF, count);
290		goto unlock;
291	}
292	switch (reg_width) {
293	case sizeof(u8): {
294		u8 *buf = buffer;
295
296		while (count) {
297			*buf = __raw_readb(addr);
298			buf++;
299			count--;
300		}
301		break;
302	}
303	case sizeof(u16): {
304		__le16 *buf = buffer;
305
306		SSB_WARN_ON(count & 1);
307		while (count) {
308			*buf = (__force __le16)__raw_readw(addr);
309			buf++;
310			count -= 2;
311		}
312		break;
313	}
314	case sizeof(u32): {
315		__le16 *buf = buffer;
316
317		SSB_WARN_ON(count & 3);
318		while (count) {
319			*buf = (__force __le16)__raw_readw(addr);
320			buf++;
321			*buf = (__force __le16)__raw_readw(addr + 2);
322			buf++;
323			count -= 4;
324		}
325		break;
326	}
327	default:
328		SSB_WARN_ON(1);
329	}
330unlock:
331	spin_unlock_irqrestore(&bus->bar_lock, flags);
332}
333#endif /* CONFIG_SSB_BLOCKIO */
334
335static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
336{
337	struct ssb_bus *bus = dev->bus;
338	unsigned long flags;
339	int err;
340
341	spin_lock_irqsave(&bus->bar_lock, flags);
342	err = select_core_and_segment(dev, &offset);
343	if (likely(!err))
344		writeb(value, bus->mmio + offset);
345	mmiowb();
346	spin_unlock_irqrestore(&bus->bar_lock, flags);
347}
348
349static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
350{
351	struct ssb_bus *bus = dev->bus;
352	unsigned long flags;
353	int err;
354
355	spin_lock_irqsave(&bus->bar_lock, flags);
356	err = select_core_and_segment(dev, &offset);
357	if (likely(!err))
358		writew(value, bus->mmio + offset);
359	mmiowb();
360	spin_unlock_irqrestore(&bus->bar_lock, flags);
361}
362
363static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
364{
365	struct ssb_bus *bus = dev->bus;
366	unsigned long flags;
367	int err;
368
369	spin_lock_irqsave(&bus->bar_lock, flags);
370	err = select_core_and_segment(dev, &offset);
371	if (likely(!err)) {
372		writew((value & 0x0000FFFF), bus->mmio + offset);
373		writew(((value & 0xFFFF0000) >> 16), bus->mmio + offset + 2);
374	}
375	mmiowb();
376	spin_unlock_irqrestore(&bus->bar_lock, flags);
377}
378
379#ifdef CONFIG_SSB_BLOCKIO
380static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
381				   size_t count, u16 offset, u8 reg_width)
382{
383	struct ssb_bus *bus = dev->bus;
384	unsigned long flags;
385	void __iomem *addr = bus->mmio + offset;
386	int err;
387
388	spin_lock_irqsave(&bus->bar_lock, flags);
389	err = select_core_and_segment(dev, &offset);
390	if (unlikely(err))
391		goto unlock;
392	switch (reg_width) {
393	case sizeof(u8): {
394		const u8 *buf = buffer;
395
396		while (count) {
397			__raw_writeb(*buf, addr);
398			buf++;
399			count--;
400		}
401		break;
402	}
403	case sizeof(u16): {
404		const __le16 *buf = buffer;
405
406		SSB_WARN_ON(count & 1);
407		while (count) {
408			__raw_writew((__force u16)(*buf), addr);
409			buf++;
410			count -= 2;
411		}
412		break;
413	}
414	case sizeof(u32): {
415		const __le16 *buf = buffer;
416
417		SSB_WARN_ON(count & 3);
418		while (count) {
419			__raw_writew((__force u16)(*buf), addr);
420			buf++;
421			__raw_writew((__force u16)(*buf), addr + 2);
422			buf++;
423			count -= 4;
424		}
425		break;
426	}
427	default:
428		SSB_WARN_ON(1);
429	}
430unlock:
431	mmiowb();
432	spin_unlock_irqrestore(&bus->bar_lock, flags);
433}
434#endif /* CONFIG_SSB_BLOCKIO */
435
436/* Not "static", as it's used in main.c */
437const struct ssb_bus_ops ssb_pcmcia_ops = {
438	.read8		= ssb_pcmcia_read8,
439	.read16		= ssb_pcmcia_read16,
440	.read32		= ssb_pcmcia_read32,
441	.write8		= ssb_pcmcia_write8,
442	.write16	= ssb_pcmcia_write16,
443	.write32	= ssb_pcmcia_write32,
444#ifdef CONFIG_SSB_BLOCKIO
445	.block_read	= ssb_pcmcia_block_read,
446	.block_write	= ssb_pcmcia_block_write,
447#endif
448};
449
450static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
451{
452	unsigned int i;
453	int err;
454	u8 value;
455
456	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
457	if (err)
458		return err;
459	for (i = 0; i < 1000; i++) {
460		err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
461		if (err)
462			return err;
463		if (value & SSB_PCMCIA_SPROMCTL_DONE)
464			return 0;
465		udelay(10);
466	}
467
468	return -ETIMEDOUT;
469}
470
471/* offset is the 16bit word offset */
472static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
473{
474	int err;
475	u8 lo, hi;
476
477	offset *= 2; /* Make byte offset */
478
479	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
480				   (offset & 0x00FF));
481	if (err)
482		return err;
483	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
484				   (offset & 0xFF00) >> 8);
485	if (err)
486		return err;
487	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
488	if (err)
489		return err;
490	err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
491	if (err)
492		return err;
493	err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
494	if (err)
495		return err;
496	*value = (lo | (((u16)hi) << 8));
497
498	return 0;
499}
500
501/* offset is the 16bit word offset */
502static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
503{
504	int err;
505
506	offset *= 2; /* Make byte offset */
507
508	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
509				   (offset & 0x00FF));
510	if (err)
511		return err;
512	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
513				   (offset & 0xFF00) >> 8);
514	if (err)
515		return err;
516	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
517				   (value & 0x00FF));
518	if (err)
519		return err;
520	err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
521				   (value & 0xFF00) >> 8);
522	if (err)
523		return err;
524	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
525	if (err)
526		return err;
527	msleep(20);
528
529	return 0;
530}
531
532/* Read the SPROM image. bufsize is in 16bit words. */
533static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
534{
535	int err, i;
536
537	for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
538		err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
539		if (err)
540			return err;
541	}
542
543	return 0;
544}
545
546/* Write the SPROM image. size is in 16bit words. */
547static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
548{
549	int i, err;
550	bool failed = 0;
551	size_t size = SSB_PCMCIA_SPROM_SIZE;
552
553	ssb_printk(KERN_NOTICE PFX
554		   "Writing SPROM. Do NOT turn off the power! "
555		   "Please stand by...\n");
556	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
557	if (err) {
558		ssb_printk(KERN_NOTICE PFX
559			   "Could not enable SPROM write access.\n");
560		return -EBUSY;
561	}
562	ssb_printk(KERN_NOTICE PFX "[ 0%%");
563	msleep(500);
564	for (i = 0; i < size; i++) {
565		if (i == size / 4)
566			ssb_printk("25%%");
567		else if (i == size / 2)
568			ssb_printk("50%%");
569		else if (i == (size * 3) / 4)
570			ssb_printk("75%%");
571		else if (i % 2)
572			ssb_printk(".");
573		err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
574		if (err) {
575			ssb_printk(KERN_NOTICE PFX
576				   "Failed to write to SPROM.\n");
577			failed = 1;
578			break;
579		}
580	}
581	err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
582	if (err) {
583		ssb_printk(KERN_NOTICE PFX
584			   "Could not disable SPROM write access.\n");
585		failed = 1;
586	}
587	msleep(500);
588	if (!failed) {
589		ssb_printk("100%% ]\n");
590		ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
591	}
592
593	return failed ? -EBUSY : 0;
594}
595
596static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
597{
598	//TODO
599	return 0;
600}
601
602#define GOTO_ERROR_ON(condition, description) do {	\
603	if (unlikely(condition)) {			\
604		error_description = description;	\
605		goto error;				\
606	}						\
607  } while (0)
608
609static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev,
610			tuple_t *tuple,
611			void *priv)
612{
613	struct ssb_sprom *sprom = priv;
614
615	if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID)
616		return -EINVAL;
617	if (tuple->TupleDataLen != ETH_ALEN + 2)
618		return -EINVAL;
619	if (tuple->TupleData[1] != ETH_ALEN)
620		return -EINVAL;
621	memcpy(sprom->il0mac, &tuple->TupleData[2], ETH_ALEN);
622	return 0;
623};
624
625static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,
626					tuple_t *tuple,
627					void *priv)
628{
629	struct ssb_init_invariants *iv = priv;
630	struct ssb_sprom *sprom = &iv->sprom;
631	struct ssb_boardinfo *bi = &iv->boardinfo;
632	const char *error_description;
633
634	GOTO_ERROR_ON(tuple->TupleDataLen < 1, "VEN tpl < 1");
635	switch (tuple->TupleData[0]) {
636	case SSB_PCMCIA_CIS_ID:
637		GOTO_ERROR_ON((tuple->TupleDataLen != 5) &&
638			      (tuple->TupleDataLen != 7),
639			      "id tpl size");
640		bi->vendor = tuple->TupleData[1] |
641			((u16)tuple->TupleData[2] << 8);
642		break;
643	case SSB_PCMCIA_CIS_BOARDREV:
644		GOTO_ERROR_ON(tuple->TupleDataLen != 2,
645			"boardrev tpl size");
646		sprom->board_rev = tuple->TupleData[1];
647		break;
648	case SSB_PCMCIA_CIS_PA:
649		GOTO_ERROR_ON((tuple->TupleDataLen != 9) &&
650			(tuple->TupleDataLen != 10),
651			"pa tpl size");
652		sprom->pa0b0 = tuple->TupleData[1] |
653			((u16)tuple->TupleData[2] << 8);
654		sprom->pa0b1 = tuple->TupleData[3] |
655			((u16)tuple->TupleData[4] << 8);
656		sprom->pa0b2 = tuple->TupleData[5] |
657			((u16)tuple->TupleData[6] << 8);
658		sprom->itssi_a = tuple->TupleData[7];
659		sprom->itssi_bg = tuple->TupleData[7];
660		sprom->maxpwr_a = tuple->TupleData[8];
661		sprom->maxpwr_bg = tuple->TupleData[8];
662		break;
663	case SSB_PCMCIA_CIS_OEMNAME:
664		/* We ignore this. */
665		break;
666	case SSB_PCMCIA_CIS_CCODE:
667		GOTO_ERROR_ON(tuple->TupleDataLen != 2,
668			"ccode tpl size");
669		sprom->country_code = tuple->TupleData[1];
670		break;
671	case SSB_PCMCIA_CIS_ANTENNA:
672		GOTO_ERROR_ON(tuple->TupleDataLen != 2,
673			"ant tpl size");
674		sprom->ant_available_a = tuple->TupleData[1];
675		sprom->ant_available_bg = tuple->TupleData[1];
676		break;
677	case SSB_PCMCIA_CIS_ANTGAIN:
678		GOTO_ERROR_ON(tuple->TupleDataLen != 2,
679			"antg tpl size");
680		sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1];
681		sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1];
682		sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1];
683		sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1];
684		sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1];
685		sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1];
686		sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1];
687		sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1];
688		break;
689	case SSB_PCMCIA_CIS_BFLAGS:
690		GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
691			(tuple->TupleDataLen != 5),
692			"bfl tpl size");
693		sprom->boardflags_lo = tuple->TupleData[1] |
694			((u16)tuple->TupleData[2] << 8);
695		break;
696	case SSB_PCMCIA_CIS_LEDS:
697		GOTO_ERROR_ON(tuple->TupleDataLen != 5,
698			"leds tpl size");
699		sprom->gpio0 = tuple->TupleData[1];
700		sprom->gpio1 = tuple->TupleData[2];
701		sprom->gpio2 = tuple->TupleData[3];
702		sprom->gpio3 = tuple->TupleData[4];
703		break;
704	}
705	return -ENOSPC; /* continue with next entry */
706
707error:
708	ssb_printk(KERN_ERR PFX
709		   "PCMCIA: Failed to fetch device invariants: %s\n",
710		   error_description);
711	return -ENODEV;
712}
713
714
715int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
716			      struct ssb_init_invariants *iv)
717{
718	struct ssb_sprom *sprom = &iv->sprom;
719	int res;
720
721	memset(sprom, 0xFF, sizeof(*sprom));
722	sprom->revision = 1;
723	sprom->boardflags_lo = 0;
724	sprom->boardflags_hi = 0;
725
726	/* First fetch the MAC address. */
727	res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE,
728				ssb_pcmcia_get_mac, sprom);
729	if (res != 0) {
730		ssb_printk(KERN_ERR PFX
731			"PCMCIA: Failed to fetch MAC address\n");
732		return -ENODEV;
733	}
734
735	/* Fetch the vendor specific tuples. */
736	res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS,
737				ssb_pcmcia_do_get_invariants, sprom);
738	if ((res == 0) || (res == -ENOSPC))
739		return 0;
740
741	ssb_printk(KERN_ERR PFX
742			"PCMCIA: Failed to fetch device invariants\n");
743	return -ENODEV;
744}
745
746static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev,
747					  struct device_attribute *attr,
748					  char *buf)
749{
750	struct pcmcia_device *pdev =
751		container_of(pcmciadev, struct pcmcia_device, dev);
752	struct ssb_bus *bus;
753
754	bus = ssb_pcmcia_dev_to_bus(pdev);
755	if (!bus)
756		return -ENODEV;
757
758	return ssb_attr_sprom_show(bus, buf,
759				   ssb_pcmcia_sprom_read_all);
760}
761
762static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
763					   struct device_attribute *attr,
764					   const char *buf, size_t count)
765{
766	struct pcmcia_device *pdev =
767		container_of(pcmciadev, struct pcmcia_device, dev);
768	struct ssb_bus *bus;
769
770	bus = ssb_pcmcia_dev_to_bus(pdev);
771	if (!bus)
772		return -ENODEV;
773
774	return ssb_attr_sprom_store(bus, buf, count,
775				    ssb_pcmcia_sprom_check_crc,
776				    ssb_pcmcia_sprom_write_all);
777}
778
779static DEVICE_ATTR(ssb_sprom, 0600,
780		   ssb_pcmcia_attr_sprom_show,
781		   ssb_pcmcia_attr_sprom_store);
782
783static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
784{
785	u8 val;
786	int err;
787
788	err = ssb_pcmcia_cfg_read(bus, cor, &val);
789	if (err)
790		return err;
791	val &= ~COR_SOFT_RESET;
792	val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
793	err = ssb_pcmcia_cfg_write(bus, cor, val);
794	if (err)
795		return err;
796	msleep(40);
797
798	return 0;
799}
800
801/* Initialize the PCMCIA hardware. This is called on Init and Resume. */
802int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
803{
804	int err;
805
806	if (bus->bustype != SSB_BUSTYPE_PCMCIA)
807		return 0;
808
809	/* Switch segment to a known state and sync
810	 * bus->mapped_pcmcia_seg with hardware state. */
811	ssb_pcmcia_switch_segment(bus, 0);
812	/* Init the COR register. */
813	err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
814	if (err)
815		return err;
816	/* Some cards also need this register to get poked. */
817	err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
818	if (err)
819		return err;
820
821	return 0;
822}
823
824void ssb_pcmcia_exit(struct ssb_bus *bus)
825{
826	if (bus->bustype != SSB_BUSTYPE_PCMCIA)
827		return;
828
829	device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
830}
831
832int ssb_pcmcia_init(struct ssb_bus *bus)
833{
834	int err;
835
836	if (bus->bustype != SSB_BUSTYPE_PCMCIA)
837		return 0;
838
839	err = ssb_pcmcia_hardware_setup(bus);
840	if (err)
841		goto error;
842
843	bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
844	mutex_init(&bus->sprom_mutex);
845	err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
846	if (err)
847		goto error;
848
849	return 0;
850error:
851	ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
852	return err;
853}
854