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