Update ppp TX restart patch to avoid race condition
[openwrt.git] / target / linux / generic / patches-3.2 / 020-ssb_update.patch
1 --- a/drivers/ssb/driver_chipcommon_pmu.c
2 +++ b/drivers/ssb/driver_chipcommon_pmu.c
3 @@ -13,6 +13,9 @@
4  #include <linux/ssb/ssb_driver_chipcommon.h>
5  #include <linux/delay.h>
6  #include <linux/export.h>
7 +#ifdef CONFIG_BCM47XX
8 +#include <asm/mach-bcm47xx/nvram.h>
9 +#endif
10  
11  #include "ssb_private.h"
12  
13 @@ -92,10 +95,6 @@ static void ssb_pmu0_pllinit_r0(struct s
14         u32 pmuctl, tmp, pllctl;
15         unsigned int i;
16  
17 -       if ((bus->chip_id == 0x5354) && !crystalfreq) {
18 -               /* The 5354 crystal freq is 25MHz */
19 -               crystalfreq = 25000;
20 -       }
21         if (crystalfreq)
22                 e = pmu0_plltab_find_entry(crystalfreq);
23         if (!e)
24 @@ -321,7 +320,11 @@ static void ssb_pmu_pll_init(struct ssb_
25         u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */
26  
27         if (bus->bustype == SSB_BUSTYPE_SSB) {
28 -               /* TODO: The user may override the crystal frequency. */
29 +#ifdef CONFIG_BCM47XX
30 +               char buf[20];
31 +               if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
32 +                       crystalfreq = simple_strtoul(buf, NULL, 0);
33 +#endif
34         }
35  
36         switch (bus->chip_id) {
37 @@ -330,7 +333,11 @@ static void ssb_pmu_pll_init(struct ssb_
38                 ssb_pmu1_pllinit_r0(cc, crystalfreq);
39                 break;
40         case 0x4328:
41 +               ssb_pmu0_pllinit_r0(cc, crystalfreq);
42 +               break;
43         case 0x5354:
44 +               if (crystalfreq == 0)
45 +                       crystalfreq = 25000;
46                 ssb_pmu0_pllinit_r0(cc, crystalfreq);
47                 break;
48         case 0x4322:
49 @@ -607,3 +614,34 @@ void ssb_pmu_set_ldo_paref(struct ssb_ch
50  
51  EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
52  EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
53 +
54 +u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
55 +{
56 +       struct ssb_bus *bus = cc->dev->bus;
57 +
58 +       switch (bus->chip_id) {
59 +       case 0x5354:
60 +               /* 5354 chip uses a non programmable PLL of frequency 240MHz */
61 +               return 240000000;
62 +       default:
63 +               ssb_printk(KERN_ERR PFX
64 +                          "ERROR: PMU cpu clock unknown for device %04X\n",
65 +                          bus->chip_id);
66 +               return 0;
67 +       }
68 +}
69 +
70 +u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
71 +{
72 +       struct ssb_bus *bus = cc->dev->bus;
73 +
74 +       switch (bus->chip_id) {
75 +       case 0x5354:
76 +               return 120000000;
77 +       default:
78 +               ssb_printk(KERN_ERR PFX
79 +                          "ERROR: PMU controlclock unknown for device %04X\n",
80 +                          bus->chip_id);
81 +               return 0;
82 +       }
83 +}
84 --- a/drivers/ssb/driver_mipscore.c
85 +++ b/drivers/ssb/driver_mipscore.c
86 @@ -208,6 +208,9 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m
87         struct ssb_bus *bus = mcore->dev->bus;
88         u32 pll_type, n, m, rate = 0;
89  
90 +       if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
91 +               return ssb_pmu_get_cpu_clock(&bus->chipco);
92 +
93         if (bus->extif.dev) {
94                 ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
95         } else if (bus->chipco.dev) {
96 --- a/drivers/ssb/driver_pcicore.c
97 +++ b/drivers/ssb/driver_pcicore.c
98 @@ -75,7 +75,7 @@ static u32 get_cfgspace_addr(struct ssb_
99         u32 tmp;
100  
101         /* We do only have one cardbus device behind the bridge. */
102 -       if (pc->cardbusmode && (dev >= 1))
103 +       if (pc->cardbusmode && (dev > 1))
104                 goto out;
105  
106         if (bus == 0) {
107 --- a/drivers/ssb/main.c
108 +++ b/drivers/ssb/main.c
109 @@ -140,19 +140,6 @@ static void ssb_device_put(struct ssb_de
110                 put_device(dev->dev);
111  }
112  
113 -static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv)
114 -{
115 -       if (drv)
116 -               get_driver(&drv->drv);
117 -       return drv;
118 -}
119 -
120 -static inline void ssb_driver_put(struct ssb_driver *drv)
121 -{
122 -       if (drv)
123 -               put_driver(&drv->drv);
124 -}
125 -
126  static int ssb_device_resume(struct device *dev)
127  {
128         struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
129 @@ -250,11 +237,9 @@ int ssb_devices_freeze(struct ssb_bus *b
130                         ssb_device_put(sdev);
131                         continue;
132                 }
133 -               sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver));
134 -               if (!sdrv || SSB_WARN_ON(!sdrv->remove)) {
135 -                       ssb_device_put(sdev);
136 +               sdrv = drv_to_ssb_drv(sdev->dev->driver);
137 +               if (SSB_WARN_ON(!sdrv->remove))
138                         continue;
139 -               }
140                 sdrv->remove(sdev);
141                 ctx->device_frozen[i] = 1;
142         }
143 @@ -293,7 +278,6 @@ int ssb_devices_thaw(struct ssb_freeze_c
144                                    dev_name(sdev->dev));
145                         result = err;
146                 }
147 -               ssb_driver_put(sdrv);
148                 ssb_device_put(sdev);
149         }
150  
151 @@ -1094,6 +1078,9 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
152         u32 plltype;
153         u32 clkctl_n, clkctl_m;
154  
155 +       if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
156 +               return ssb_pmu_get_controlclock(&bus->chipco);
157 +
158         if (ssb_extif_available(&bus->extif))
159                 ssb_extif_get_clockcontrol(&bus->extif, &plltype,
160                                            &clkctl_n, &clkctl_m);
161 --- a/drivers/ssb/pci.c
162 +++ b/drivers/ssb/pci.c
163 @@ -331,7 +331,6 @@ static void sprom_extract_r123(struct ss
164  {
165         int i;
166         u16 v;
167 -       s8 gain;
168         u16 loc[3];
169  
170         if (out->revision == 3)                 /* rev 3 moved MAC */
171 @@ -390,20 +389,12 @@ static void sprom_extract_r123(struct ss
172                 SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
173  
174         /* Extract the antenna gain values. */
175 -       gain = r123_extract_antgain(out->revision, in,
176 -                                   SSB_SPROM1_AGAIN_BG,
177 -                                   SSB_SPROM1_AGAIN_BG_SHIFT);
178 -       out->antenna_gain.ghz24.a0 = gain;
179 -       out->antenna_gain.ghz24.a1 = gain;
180 -       out->antenna_gain.ghz24.a2 = gain;
181 -       out->antenna_gain.ghz24.a3 = gain;
182 -       gain = r123_extract_antgain(out->revision, in,
183 -                                   SSB_SPROM1_AGAIN_A,
184 -                                   SSB_SPROM1_AGAIN_A_SHIFT);
185 -       out->antenna_gain.ghz5.a0 = gain;
186 -       out->antenna_gain.ghz5.a1 = gain;
187 -       out->antenna_gain.ghz5.a2 = gain;
188 -       out->antenna_gain.ghz5.a3 = gain;
189 +       out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
190 +                                                   SSB_SPROM1_AGAIN_BG,
191 +                                                   SSB_SPROM1_AGAIN_BG_SHIFT);
192 +       out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
193 +                                                   SSB_SPROM1_AGAIN_A,
194 +                                                   SSB_SPROM1_AGAIN_A_SHIFT);
195  }
196  
197  /* Revs 4 5 and 8 have partially shared layout */
198 @@ -504,16 +495,14 @@ static void sprom_extract_r45(struct ssb
199         }
200  
201         /* Extract the antenna gain values. */
202 -       SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
203 +       SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
204              SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
205 -       SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
206 +       SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
207              SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
208 -       SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
209 +       SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
210              SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
211 -       SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
212 +       SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
213              SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
214 -       memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
215 -              sizeof(out->antenna_gain.ghz5));
216  
217         sprom_extract_r458(out, in);
218  
219 @@ -523,7 +512,13 @@ static void sprom_extract_r45(struct ssb
220  static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
221  {
222         int i;
223 -       u16 v;
224 +       u16 v, o;
225 +       u16 pwr_info_offset[] = {
226 +               SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
227 +               SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
228 +       };
229 +       BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
230 +                       ARRAY_SIZE(out->core_pwr_info));
231  
232         /* extract the MAC address */
233         for (i = 0; i < 3; i++) {
234 @@ -596,16 +591,69 @@ static void sprom_extract_r8(struct ssb_
235         SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
236  
237         /* Extract the antenna gain values. */
238 -       SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
239 +       SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
240              SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
241 -       SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
242 +       SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
243              SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
244 -       SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
245 +       SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
246              SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
247 -       SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
248 +       SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
249              SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
250 -       memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
251 -              sizeof(out->antenna_gain.ghz5));
252 +
253 +       /* Extract cores power info info */
254 +       for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
255 +               o = pwr_info_offset[i];
256 +               SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
257 +                       SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
258 +               SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
259 +                       SSB_SPROM8_2G_MAXP, 0);
260 +
261 +               SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
262 +               SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
263 +               SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
264 +
265 +               SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
266 +                       SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
267 +               SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
268 +                       SSB_SPROM8_5G_MAXP, 0);
269 +               SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
270 +                       SSB_SPROM8_5GH_MAXP, 0);
271 +               SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
272 +                       SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
273 +
274 +               SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
275 +               SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
276 +               SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
277 +               SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
278 +               SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
279 +               SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
280 +               SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
281 +               SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
282 +               SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
283 +       }
284 +
285 +       /* Extract FEM info */
286 +       SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
287 +               SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
288 +       SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G,
289 +               SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
290 +       SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G,
291 +               SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
292 +       SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G,
293 +               SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
294 +       SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G,
295 +               SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
296 +
297 +       SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G,
298 +               SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT);
299 +       SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G,
300 +               SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
301 +       SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G,
302 +               SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT);
303 +       SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G,
304 +               SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT);
305 +       SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
306 +               SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
307  
308         sprom_extract_r458(out, in);
309  
310 --- a/drivers/ssb/pcmcia.c
311 +++ b/drivers/ssb/pcmcia.c
312 @@ -676,14 +676,10 @@ static int ssb_pcmcia_do_get_invariants(
313         case SSB_PCMCIA_CIS_ANTGAIN:
314                 GOTO_ERROR_ON(tuple->TupleDataLen != 2,
315                         "antg tpl size");
316 -               sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1];
317 -               sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1];
318 -               sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1];
319 -               sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1];
320 -               sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1];
321 -               sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1];
322 -               sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1];
323 -               sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1];
324 +               sprom->antenna_gain.a0 = tuple->TupleData[1];
325 +               sprom->antenna_gain.a1 = tuple->TupleData[1];
326 +               sprom->antenna_gain.a2 = tuple->TupleData[1];
327 +               sprom->antenna_gain.a3 = tuple->TupleData[1];
328                 break;
329         case SSB_PCMCIA_CIS_BFLAGS:
330                 GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
331 --- a/drivers/ssb/scan.c
332 +++ b/drivers/ssb/scan.c
333 @@ -318,6 +318,9 @@ int ssb_bus_scan(struct ssb_bus *bus,
334                         bus->chip_package = 0;
335                 }
336         }
337 +       ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and "
338 +                  "package 0x%02X\n", bus->chip_id, bus->chip_rev,
339 +                  bus->chip_package);
340         if (!bus->nr_devices)
341                 bus->nr_devices = chipid_to_nrcores(bus->chip_id);
342         if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
343 --- a/drivers/ssb/sdio.c
344 +++ b/drivers/ssb/sdio.c
345 @@ -551,14 +551,10 @@ int ssb_sdio_get_invariants(struct ssb_b
346                         case SSB_SDIO_CIS_ANTGAIN:
347                                 GOTO_ERROR_ON(tuple->size != 2,
348                                               "antg tpl size");
349 -                               sprom->antenna_gain.ghz24.a0 = tuple->data[1];
350 -                               sprom->antenna_gain.ghz24.a1 = tuple->data[1];
351 -                               sprom->antenna_gain.ghz24.a2 = tuple->data[1];
352 -                               sprom->antenna_gain.ghz24.a3 = tuple->data[1];
353 -                               sprom->antenna_gain.ghz5.a0 = tuple->data[1];
354 -                               sprom->antenna_gain.ghz5.a1 = tuple->data[1];
355 -                               sprom->antenna_gain.ghz5.a2 = tuple->data[1];
356 -                               sprom->antenna_gain.ghz5.a3 = tuple->data[1];
357 +                               sprom->antenna_gain.a0 = tuple->data[1];
358 +                               sprom->antenna_gain.a1 = tuple->data[1];
359 +                               sprom->antenna_gain.a2 = tuple->data[1];
360 +                               sprom->antenna_gain.a3 = tuple->data[1];
361                                 break;
362                         case SSB_SDIO_CIS_BFLAGS:
363                                 GOTO_ERROR_ON((tuple->size != 3) &&
364 --- a/drivers/ssb/ssb_private.h
365 +++ b/drivers/ssb/ssb_private.h
366 @@ -207,4 +207,8 @@ static inline void b43_pci_ssb_bridge_ex
367  }
368  #endif /* CONFIG_SSB_B43_PCI_BRIDGE */
369  
370 +/* driver_chipcommon_pmu.c */
371 +extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
372 +extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
373 +
374  #endif /* LINUX_SSB_PRIVATE_H_ */
375 --- a/include/linux/ssb/ssb.h
376 +++ b/include/linux/ssb/ssb.h
377 @@ -16,6 +16,12 @@ struct pcmcia_device;
378  struct ssb_bus;
379  struct ssb_driver;
380  
381 +struct ssb_sprom_core_pwr_info {
382 +       u8 itssi_2g, itssi_5g;
383 +       u8 maxpwr_2g, maxpwr_5gl, maxpwr_5g, maxpwr_5gh;
384 +       u16 pa_2g[4], pa_5gl[4], pa_5g[4], pa_5gh[4];
385 +};
386 +
387  struct ssb_sprom {
388         u8 revision;
389         u8 il0mac[6];           /* MAC address for 802.11b/g */
390 @@ -26,9 +32,12 @@ struct ssb_sprom {
391         u8 et0mdcport;          /* MDIO for enet0 */
392         u8 et1mdcport;          /* MDIO for enet1 */
393         u16 board_rev;          /* Board revision number from SPROM. */
394 +       u16 board_num;          /* Board number from SPROM. */
395 +       u16 board_type;         /* Board type from SPROM. */
396         u8 country_code;        /* Country Code */
397 -       u16 leddc_on_time;      /* LED Powersave Duty Cycle On Count */
398 -       u16 leddc_off_time;     /* LED Powersave Duty Cycle Off Count */
399 +       char alpha2[2];         /* Country Code as two chars like EU or US */
400 +       u8 leddc_on_time;       /* LED Powersave Duty Cycle On Count */
401 +       u8 leddc_off_time;      /* LED Powersave Duty Cycle Off Count */
402         u8 ant_available_a;     /* 2GHz antenna available bits (up to 4) */
403         u8 ant_available_bg;    /* 5GHz antenna available bits (up to 4) */
404         u16 pa0b0;
405 @@ -47,10 +56,10 @@ struct ssb_sprom {
406         u8 gpio1;               /* GPIO pin 1 */
407         u8 gpio2;               /* GPIO pin 2 */
408         u8 gpio3;               /* GPIO pin 3 */
409 -       u16 maxpwr_bg;          /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
410 -       u16 maxpwr_al;          /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
411 -       u16 maxpwr_a;           /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
412 -       u16 maxpwr_ah;          /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
413 +       u8 maxpwr_bg;           /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
414 +       u8 maxpwr_al;           /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
415 +       u8 maxpwr_a;            /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
416 +       u8 maxpwr_ah;           /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
417         u8 itssi_a;             /* Idle TSSI Target for A-PHY */
418         u8 itssi_bg;            /* Idle TSSI Target for B/G-PHY */
419         u8 tri2g;               /* 2.4GHz TX isolation */
420 @@ -61,8 +70,8 @@ struct ssb_sprom {
421         u8 txpid5gl[4];         /* 4.9 - 5.1GHz TX power index */
422         u8 txpid5g[4];          /* 5.1 - 5.5GHz TX power index */
423         u8 txpid5gh[4];         /* 5.5 - ...GHz TX power index */
424 -       u8 rxpo2g;              /* 2GHz RX power offset */
425 -       u8 rxpo5g;              /* 5GHz RX power offset */
426 +       s8 rxpo2g;              /* 2GHz RX power offset */
427 +       s8 rxpo5g;              /* 5GHz RX power offset */
428         u8 rssisav2g;           /* 2GHz RSSI params */
429         u8 rssismc2g;
430         u8 rssismf2g;
431 @@ -82,19 +91,97 @@ struct ssb_sprom {
432         u16 boardflags2_hi;     /* Board flags (bits 48-63) */
433         /* TODO store board flags in a single u64 */
434  
435 +       struct ssb_sprom_core_pwr_info core_pwr_info[4];
436 +
437         /* Antenna gain values for up to 4 antennas
438          * on each band. Values in dBm/4 (Q5.2). Negative gain means the
439          * loss in the connectors is bigger than the gain. */
440         struct {
441 +               s8 a0, a1, a2, a3;
442 +       } antenna_gain;
443 +
444 +       struct {
445                 struct {
446 -                       s8 a0, a1, a2, a3;
447 -               } ghz24;        /* 2.4GHz band */
448 +                       u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut;
449 +               } ghz2;
450                 struct {
451 -                       s8 a0, a1, a2, a3;
452 -               } ghz5;         /* 5GHz band */
453 -       } antenna_gain;
454 +                       u8 tssipos, extpa_gain, pdet_range, tr_iso, antswlut;
455 +               } ghz5;
456 +       } fem;
457 +
458 +       u16 mcs2gpo[8];
459 +       u16 mcs5gpo[8];
460 +       u16 mcs5glpo[8];
461 +       u16 mcs5ghpo[8];
462 +       u8 opo;
463 +
464 +       u8 rxgainerr2ga[3];
465 +       u8 rxgainerr5gla[3];
466 +       u8 rxgainerr5gma[3];
467 +       u8 rxgainerr5gha[3];
468 +       u8 rxgainerr5gua[3];
469 +
470 +       u8 noiselvl2ga[3];
471 +       u8 noiselvl5gla[3];
472 +       u8 noiselvl5gma[3];
473 +       u8 noiselvl5gha[3];
474 +       u8 noiselvl5gua[3];
475 +
476 +       u8 regrev;
477 +       u8 txchain;
478 +       u8 rxchain;
479 +       u8 antswitch;
480 +       u16 cddpo;
481 +       u16 stbcpo;
482 +       u16 bw40po;
483 +       u16 bwduppo;
484 +
485 +       u8 tempthresh;
486 +       u8 tempoffset;
487 +       u16 rawtempsense;
488 +       u8 measpower;
489 +       u8 tempsense_slope;
490 +       u8 tempcorrx;
491 +       u8 tempsense_option;
492 +       u8 freqoffset_corr;
493 +       u8 iqcal_swp_dis;
494 +       u8 hw_iqcal_en;
495 +       u8 elna2g;
496 +       u8 elna5g;
497 +       u8 phycal_tempdelta;
498 +       u8 temps_period;
499 +       u8 temps_hysteresis;
500 +       u8 measpower1;
501 +       u8 measpower2;
502 +       u8 pcieingress_war;
503  
504 -       /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
505 +       /* power per rate from sromrev 9 */
506 +       u16 cckbw202gpo;
507 +       u16 cckbw20ul2gpo;
508 +       u32 legofdmbw202gpo;
509 +       u32 legofdmbw20ul2gpo;
510 +       u32 legofdmbw205glpo;
511 +       u32 legofdmbw20ul5glpo;
512 +       u32 legofdmbw205gmpo;
513 +       u32 legofdmbw20ul5gmpo;
514 +       u32 legofdmbw205ghpo;
515 +       u32 legofdmbw20ul5ghpo;
516 +       u32 mcsbw202gpo;
517 +       u32 mcsbw20ul2gpo;
518 +       u32 mcsbw402gpo;
519 +       u32 mcsbw205glpo;
520 +       u32 mcsbw20ul5glpo;
521 +       u32 mcsbw405glpo;
522 +       u32 mcsbw205gmpo;
523 +       u32 mcsbw20ul5gmpo;
524 +       u32 mcsbw405gmpo;
525 +       u32 mcsbw205ghpo;
526 +       u32 mcsbw20ul5ghpo;
527 +       u32 mcsbw405ghpo;
528 +       u16 mcs32po;
529 +       u16 legofdm40duppo;
530 +       u8 sar2g;
531 +       u8 sar5g;
532  };
533  
534  /* Information about the PCB the circuitry is soldered on. */
535 --- a/include/linux/ssb/ssb_driver_gige.h
536 +++ b/include/linux/ssb/ssb_driver_gige.h
537 @@ -2,6 +2,7 @@
538  #define LINUX_SSB_DRIVER_GIGE_H_
539  
540  #include <linux/ssb/ssb.h>
541 +#include <linux/bug.h>
542  #include <linux/pci.h>
543  #include <linux/spinlock.h>
544  
545 --- a/include/linux/ssb/ssb_regs.h
546 +++ b/include/linux/ssb/ssb_regs.h
547 @@ -432,6 +432,56 @@
548  #define  SSB_SPROM8_RXPO2G             0x00FF  /* 2GHz RX power offset */
549  #define  SSB_SPROM8_RXPO5G             0xFF00  /* 5GHz RX power offset */
550  #define  SSB_SPROM8_RXPO5G_SHIFT       8
551 +#define SSB_SPROM8_FEM2G               0x00AE
552 +#define SSB_SPROM8_FEM5G               0x00B0
553 +#define  SSB_SROM8_FEM_TSSIPOS         0x0001
554 +#define  SSB_SROM8_FEM_TSSIPOS_SHIFT   0
555 +#define  SSB_SROM8_FEM_EXTPA_GAIN      0x0006
556 +#define  SSB_SROM8_FEM_EXTPA_GAIN_SHIFT        1
557 +#define  SSB_SROM8_FEM_PDET_RANGE      0x00F8
558 +#define  SSB_SROM8_FEM_PDET_RANGE_SHIFT        3
559 +#define  SSB_SROM8_FEM_TR_ISO          0x0700
560 +#define  SSB_SROM8_FEM_TR_ISO_SHIFT    8
561 +#define  SSB_SROM8_FEM_ANTSWLUT                0xF800
562 +#define  SSB_SROM8_FEM_ANTSWLUT_SHIFT  11
563 +#define SSB_SPROM8_THERMAL             0x00B2
564 +#define SSB_SPROM8_MPWR_RAWTS          0x00B4
565 +#define SSB_SPROM8_TS_SLP_OPT_CORRX    0x00B6
566 +#define SSB_SPROM8_FOC_HWIQ_IQSWP      0x00B8
567 +#define SSB_SPROM8_PHYCAL_TEMPDELTA    0x00BA
568 +
569 +/* There are 4 blocks with power info sharing the same layout */
570 +#define SSB_SROM8_PWR_INFO_CORE0       0x00C0
571 +#define SSB_SROM8_PWR_INFO_CORE1       0x00E0
572 +#define SSB_SROM8_PWR_INFO_CORE2       0x0100
573 +#define SSB_SROM8_PWR_INFO_CORE3       0x0120
574 +
575 +#define SSB_SROM8_2G_MAXP_ITSSI                0x00
576 +#define  SSB_SPROM8_2G_MAXP            0x00FF
577 +#define  SSB_SPROM8_2G_ITSSI           0xFF00
578 +#define  SSB_SPROM8_2G_ITSSI_SHIFT     8
579 +#define SSB_SROM8_2G_PA_0              0x02    /* 2GHz power amp settings */
580 +#define SSB_SROM8_2G_PA_1              0x04
581 +#define SSB_SROM8_2G_PA_2              0x06
582 +#define SSB_SROM8_5G_MAXP_ITSSI                0x08    /* 5GHz ITSSI and 5.3GHz Max Power */
583 +#define  SSB_SPROM8_5G_MAXP            0x00FF
584 +#define  SSB_SPROM8_5G_ITSSI           0xFF00
585 +#define  SSB_SPROM8_5G_ITSSI_SHIFT     8
586 +#define SSB_SPROM8_5GHL_MAXP           0x0A    /* 5.2GHz and 5.8GHz Max Power */
587 +#define  SSB_SPROM8_5GH_MAXP           0x00FF
588 +#define  SSB_SPROM8_5GL_MAXP           0xFF00
589 +#define  SSB_SPROM8_5GL_MAXP_SHIFT     8
590 +#define SSB_SROM8_5G_PA_0              0x0C    /* 5.3GHz power amp settings */
591 +#define SSB_SROM8_5G_PA_1              0x0E
592 +#define SSB_SROM8_5G_PA_2              0x10
593 +#define SSB_SROM8_5GL_PA_0             0x12    /* 5.2GHz power amp settings */
594 +#define SSB_SROM8_5GL_PA_1             0x14
595 +#define SSB_SROM8_5GL_PA_2             0x16
596 +#define SSB_SROM8_5GH_PA_0             0x18    /* 5.8GHz power amp settings */
597 +#define SSB_SROM8_5GH_PA_1             0x1A
598 +#define SSB_SROM8_5GH_PA_2             0x1C
599 +
600 +/* TODO: Make it deprecated */
601  #define SSB_SPROM8_MAXP_BG             0x00C0  /* Max Power 2GHz in path 1 */
602  #define  SSB_SPROM8_MAXP_BG_MASK       0x00FF  /* Mask for Max Power 2GHz */
603  #define  SSB_SPROM8_ITSSI_BG           0xFF00  /* Mask for path 1 itssi_bg */
604 @@ -456,6 +506,7 @@
605  #define SSB_SPROM8_PA1HIB0             0x00D8  /* 5.8GHz power amp settings */
606  #define SSB_SPROM8_PA1HIB1             0x00DA
607  #define SSB_SPROM8_PA1HIB2             0x00DC
608 +
609  #define SSB_SPROM8_CCK2GPO             0x0140  /* CCK power offset */
610  #define SSB_SPROM8_OFDM2GPO            0x0142  /* 2.4GHz OFDM power offset */
611  #define SSB_SPROM8_OFDM5GPO            0x0146  /* 5.3GHz OFDM power offset */