ffe262270664a7d5406be385716ef4c896578564
[safe/jmp/linux-2.6] / drivers / net / wireless / b43 / phy_n.c
1 /*
2
3   Broadcom B43 wireless driver
4   IEEE 802.11n PHY support
5
6   Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; see the file COPYING.  If not, write to
20   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
21   Boston, MA 02110-1301, USA.
22
23 */
24
25 #include <linux/delay.h>
26 #include <linux/types.h>
27
28 #include "b43.h"
29 #include "phy_n.h"
30 #include "tables_nphy.h"
31 #include "main.h"
32
33 struct nphy_txgains {
34         u16 txgm[2];
35         u16 pga[2];
36         u16 pad[2];
37         u16 ipa[2];
38 };
39
40 struct nphy_iqcal_params {
41         u16 txgm;
42         u16 pga;
43         u16 pad;
44         u16 ipa;
45         u16 cal_gain;
46         u16 ncorr[5];
47 };
48
49 struct nphy_iq_est {
50         s32 iq0_prod;
51         u32 i0_pwr;
52         u32 q0_pwr;
53         s32 iq1_prod;
54         u32 i1_pwr;
55         u32 q1_pwr;
56 };
57
58 enum b43_nphy_rf_sequence {
59         B43_RFSEQ_RX2TX,
60         B43_RFSEQ_TX2RX,
61         B43_RFSEQ_RESET2RX,
62         B43_RFSEQ_UPDATE_GAINH,
63         B43_RFSEQ_UPDATE_GAINL,
64         B43_RFSEQ_UPDATE_GAINU,
65 };
66
67 static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
68                                         u8 *events, u8 *delays, u8 length);
69 static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
70                                        enum b43_nphy_rf_sequence seq);
71 static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
72                                                 u16 value, u8 core, bool off);
73 static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
74                                                 u16 value, u8 core);
75
76 static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec)
77 {
78         return !chanspec->channel && !chanspec->sideband &&
79                 !chanspec->b_width && !chanspec->b_freq;
80 }
81
82 static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1,
83                                         struct b43_chanspec *chanspec2)
84 {
85         return (chanspec1->channel == chanspec2->channel &&
86                 chanspec1->sideband == chanspec2->sideband &&
87                 chanspec1->b_width == chanspec2->b_width &&
88                 chanspec1->b_freq == chanspec2->b_freq);
89 }
90
91 void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
92 {//TODO
93 }
94
95 static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
96 {//TODO
97 }
98
99 static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
100                                                         bool ignore_tssi)
101 {//TODO
102         return B43_TXPWR_RES_DONE;
103 }
104
105 static void b43_chantab_radio_upload(struct b43_wldev *dev,
106                                      const struct b43_nphy_channeltab_entry *e)
107 {
108         b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
109         b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
110         b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
111         b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
112         b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
113
114         b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
115         b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
116         b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
117         b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
118         b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
119
120         b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
121         b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
122         b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
123         b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
124         b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
125
126         b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
127         b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
128         b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
129         b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
130         b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
131
132         b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
133         b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
134         b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
135         b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
136         b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
137
138         b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
139         b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
140 }
141
142 static void b43_chantab_phy_upload(struct b43_wldev *dev,
143                                    const struct b43_nphy_channeltab_entry *e)
144 {
145         b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
146         b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
147         b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
148         b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
149         b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
150         b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
151 }
152
153 static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
154 {
155         //TODO
156 }
157
158
159 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
160 static void b43_radio_2055_setup(struct b43_wldev *dev,
161                                 const struct b43_nphy_channeltab_entry *e)
162 {
163         B43_WARN_ON(dev->phy.rev >= 3);
164
165         b43_chantab_radio_upload(dev, e);
166         udelay(50);
167         b43_radio_write(dev, B2055_VCO_CAL10, 5);
168         b43_radio_write(dev, B2055_VCO_CAL10, 45);
169         b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
170         b43_radio_write(dev, B2055_VCO_CAL10, 65);
171         udelay(300);
172 }
173
174 /* Tune the hardware to a new channel. */
175 static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
176 {
177         const struct b43_nphy_channeltab_entry *tabent;
178
179         tabent = b43_nphy_get_chantabent(dev, channel);
180         if (!tabent)
181                 return -ESRCH;
182
183         //FIXME enable/disable band select upper20 in RXCTL
184         if (0 /*FIXME 5Ghz*/)
185                 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20);
186         else
187                 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50);
188         b43_radio_2055_setup(dev, tabent);
189         if (0 /*FIXME 5Ghz*/)
190                 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
191         else
192                 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
193         b43_chantab_phy_upload(dev, tabent);
194         b43_nphy_tx_power_fix(dev);
195
196         return 0;
197 }
198
199 static void b43_radio_init2055_pre(struct b43_wldev *dev)
200 {
201         b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
202                      ~B43_NPHY_RFCTL_CMD_PORFORCE);
203         b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
204                     B43_NPHY_RFCTL_CMD_CHIP0PU |
205                     B43_NPHY_RFCTL_CMD_OEPORFORCE);
206         b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
207                     B43_NPHY_RFCTL_CMD_PORFORCE);
208 }
209
210 static void b43_radio_init2055_post(struct b43_wldev *dev)
211 {
212         struct b43_phy_n *nphy = dev->phy.n;
213         struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
214         struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo);
215         int i;
216         u16 val;
217         bool workaround = false;
218
219         if (sprom->revision < 4)
220                 workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM ||
221                                 binfo->type != 0x46D ||
222                                 binfo->rev < 0x41);
223         else
224                 workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0);
225
226         b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
227         if (workaround) {
228                 b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
229                 b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
230         }
231         b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
232         b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
233         b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
234         b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
235         b43_radio_set(dev, B2055_CAL_MISC, 0x1);
236         msleep(1);
237         b43_radio_set(dev, B2055_CAL_MISC, 0x40);
238         for (i = 0; i < 200; i++) {
239                 val = b43_radio_read(dev, B2055_CAL_COUT2);
240                 if (val & 0x80) {
241                         i = 0;
242                         break;
243                 }
244                 udelay(10);
245         }
246         if (i)
247                 b43err(dev->wl, "radio post init timeout\n");
248         b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
249         nphy_channel_switch(dev, dev->phy.channel);
250         b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
251         b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
252         b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
253         b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
254         b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
255         b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
256         if (!nphy->gain_boost) {
257                 b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
258                 b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
259         } else {
260                 b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
261                 b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
262         }
263         udelay(2);
264 }
265
266 /*
267  * Initialize a Broadcom 2055 N-radio
268  * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
269  */
270 static void b43_radio_init2055(struct b43_wldev *dev)
271 {
272         b43_radio_init2055_pre(dev);
273         if (b43_status(dev) < B43_STAT_INITIALIZED)
274                 b2055_upload_inittab(dev, 0, 1);
275         else
276                 b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0);
277         b43_radio_init2055_post(dev);
278 }
279
280 /*
281  * Upload the N-PHY tables.
282  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
283  */
284 static void b43_nphy_tables_init(struct b43_wldev *dev)
285 {
286         if (dev->phy.rev < 3)
287                 b43_nphy_rev0_1_2_tables_init(dev);
288         else
289                 b43_nphy_rev3plus_tables_init(dev);
290 }
291
292 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
293 static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
294 {
295         struct b43_phy_n *nphy = dev->phy.n;
296         enum ieee80211_band band;
297         u16 tmp;
298
299         if (!enable) {
300                 nphy->rfctrl_intc1_save = b43_phy_read(dev,
301                                                        B43_NPHY_RFCTL_INTC1);
302                 nphy->rfctrl_intc2_save = b43_phy_read(dev,
303                                                        B43_NPHY_RFCTL_INTC2);
304                 band = b43_current_band(dev->wl);
305                 if (dev->phy.rev >= 3) {
306                         if (band == IEEE80211_BAND_5GHZ)
307                                 tmp = 0x600;
308                         else
309                                 tmp = 0x480;
310                 } else {
311                         if (band == IEEE80211_BAND_5GHZ)
312                                 tmp = 0x180;
313                         else
314                                 tmp = 0x120;
315                 }
316                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
317                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
318         } else {
319                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
320                                 nphy->rfctrl_intc1_save);
321                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
322                                 nphy->rfctrl_intc2_save);
323         }
324 }
325
326 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
327 static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
328 {
329         struct b43_phy_n *nphy = dev->phy.n;
330         u16 tmp;
331         enum ieee80211_band band = b43_current_band(dev->wl);
332         bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
333                         (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ);
334
335         if (dev->phy.rev >= 3) {
336                 if (ipa) {
337                         tmp = 4;
338                         b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
339                               (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
340                 }
341
342                 tmp = 1;
343                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
344                               (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
345         }
346 }
347
348 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
349 static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
350 {
351         u32 tmslow;
352
353         if (dev->phy.type != B43_PHYTYPE_N)
354                 return;
355
356         tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
357         if (force)
358                 tmslow |= SSB_TMSLOW_FGC;
359         else
360                 tmslow &= ~SSB_TMSLOW_FGC;
361         ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
362 }
363
364 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
365 static void b43_nphy_reset_cca(struct b43_wldev *dev)
366 {
367         u16 bbcfg;
368
369         b43_nphy_bmac_clock_fgc(dev, 1);
370         bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
371         b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
372         udelay(1);
373         b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
374         b43_nphy_bmac_clock_fgc(dev, 0);
375         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
376 }
377
378 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
379 static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
380 {
381         u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
382
383         mimocfg |= B43_NPHY_MIMOCFG_AUTO;
384         if (preamble == 1)
385                 mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
386         else
387                 mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
388
389         b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
390 }
391
392 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
393 static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
394 {
395         struct b43_phy_n *nphy = dev->phy.n;
396
397         bool override = false;
398         u16 chain = 0x33;
399
400         if (nphy->txrx_chain == 0) {
401                 chain = 0x11;
402                 override = true;
403         } else if (nphy->txrx_chain == 1) {
404                 chain = 0x22;
405                 override = true;
406         }
407
408         b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
409                         ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
410                         chain);
411
412         if (override)
413                 b43_phy_set(dev, B43_NPHY_RFSEQMODE,
414                                 B43_NPHY_RFSEQMODE_CAOVER);
415         else
416                 b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
417                                 ~B43_NPHY_RFSEQMODE_CAOVER);
418 }
419
420 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
421 static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
422                                 u16 samps, u8 time, bool wait)
423 {
424         int i;
425         u16 tmp;
426
427         b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
428         b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
429         if (wait)
430                 b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
431         else
432                 b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
433
434         b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
435
436         for (i = 1000; i; i--) {
437                 tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
438                 if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
439                         est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
440                                         b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
441                         est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
442                                         b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
443                         est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
444                                         b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
445
446                         est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
447                                         b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
448                         est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
449                                         b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
450                         est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
451                                         b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
452                         return;
453                 }
454                 udelay(10);
455         }
456         memset(est, 0, sizeof(*est));
457 }
458
459 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
460 static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
461                                         struct b43_phy_n_iq_comp *pcomp)
462 {
463         if (write) {
464                 b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
465                 b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
466                 b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
467                 b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
468         } else {
469                 pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
470                 pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
471                 pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
472                 pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
473         }
474 }
475
476 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
477 static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
478 {
479         u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
480
481         b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
482         if (core == 0) {
483                 b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
484                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
485         } else {
486                 b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
487                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
488         }
489         b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
490         b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
491         b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
492         b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
493         b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
494         b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
495         b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
496         b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
497 }
498
499 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
500 static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
501 {
502         u8 rxval, txval;
503         u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
504
505         regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
506         if (core == 0) {
507                 regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
508                 regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
509         } else {
510                 regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
511                 regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
512         }
513         regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
514         regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
515         regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
516         regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
517         regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
518         regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
519         regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
520         regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
521
522         b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
523         b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
524
525         b43_phy_maskset(dev, B43_NPHY_RFSEQCA, (u16)~B43_NPHY_RFSEQCA_RXDIS,
526                         ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
527         b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
528                         ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
529         b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
530                         (core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
531         b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
532                         (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
533
534         if (core == 0) {
535                 b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
536                 b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
537         } else {
538                 b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
539                 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
540         }
541
542         b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
543         b43_nphy_rf_control_override(dev, 8, 0, 3, false);
544         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
545
546         if (core == 0) {
547                 rxval = 1;
548                 txval = 8;
549         } else {
550                 rxval = 4;
551                 txval = 2;
552         }
553         b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
554         b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
555 }
556
557 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
558 static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
559 {
560         int i;
561         s32 iq;
562         u32 ii;
563         u32 qq;
564         int iq_nbits, qq_nbits;
565         int arsh, brsh;
566         u16 tmp, a, b;
567
568         struct nphy_iq_est est;
569         struct b43_phy_n_iq_comp old;
570         struct b43_phy_n_iq_comp new = { };
571         bool error = false;
572
573         if (mask == 0)
574                 return;
575
576         b43_nphy_rx_iq_coeffs(dev, false, &old);
577         b43_nphy_rx_iq_coeffs(dev, true, &new);
578         b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
579         new = old;
580
581         for (i = 0; i < 2; i++) {
582                 if (i == 0 && (mask & 1)) {
583                         iq = est.iq0_prod;
584                         ii = est.i0_pwr;
585                         qq = est.q0_pwr;
586                 } else if (i == 1 && (mask & 2)) {
587                         iq = est.iq1_prod;
588                         ii = est.i1_pwr;
589                         qq = est.q1_pwr;
590                 } else {
591                         B43_WARN_ON(1);
592                         continue;
593                 }
594
595                 if (ii + qq < 2) {
596                         error = true;
597                         break;
598                 }
599
600                 iq_nbits = fls(abs(iq));
601                 qq_nbits = fls(qq);
602
603                 arsh = iq_nbits - 20;
604                 if (arsh >= 0) {
605                         a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
606                         tmp = ii >> arsh;
607                 } else {
608                         a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
609                         tmp = ii << -arsh;
610                 }
611                 if (tmp == 0) {
612                         error = true;
613                         break;
614                 }
615                 a /= tmp;
616
617                 brsh = qq_nbits - 11;
618                 if (brsh >= 0) {
619                         b = (qq << (31 - qq_nbits));
620                         tmp = ii >> brsh;
621                 } else {
622                         b = (qq << (31 - qq_nbits));
623                         tmp = ii << -brsh;
624                 }
625                 if (tmp == 0) {
626                         error = true;
627                         break;
628                 }
629                 b = int_sqrt(b / tmp - a * a) - (1 << 10);
630
631                 if (i == 0 && (mask & 0x1)) {
632                         if (dev->phy.rev >= 3) {
633                                 new.a0 = a & 0x3FF;
634                                 new.b0 = b & 0x3FF;
635                         } else {
636                                 new.a0 = b & 0x3FF;
637                                 new.b0 = a & 0x3FF;
638                         }
639                 } else if (i == 1 && (mask & 0x2)) {
640                         if (dev->phy.rev >= 3) {
641                                 new.a1 = a & 0x3FF;
642                                 new.b1 = b & 0x3FF;
643                         } else {
644                                 new.a1 = b & 0x3FF;
645                                 new.b1 = a & 0x3FF;
646                         }
647                 }
648         }
649
650         if (error)
651                 new = old;
652
653         b43_nphy_rx_iq_coeffs(dev, true, &new);
654 }
655
656 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
657 static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
658 {
659         u16 array[4];
660         int i;
661
662         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50);
663         for (i = 0; i < 4; i++)
664                 array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
665
666         b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
667         b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
668         b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
669         b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
670 }
671
672 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
673 static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st)
674 {
675         b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
676         b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
677 }
678
679 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
680 static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
681 {
682         clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
683         clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
684 }
685
686 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
687 static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
688 {
689         if (dev->phy.rev >= 3) {
690                 if (!init)
691                         return;
692                 if (0 /* FIXME */) {
693                         b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
694                         b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
695                         b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
696                         b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
697                 }
698         } else {
699                 b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
700                 b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
701
702                 ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00,
703                                         0xFC00);
704                 b43_write32(dev, B43_MMIO_MACCTL,
705                         b43_read32(dev, B43_MMIO_MACCTL) &
706                         ~B43_MACCTL_GPOUTSMSK);
707                 b43_write16(dev, B43_MMIO_GPIO_MASK,
708                         b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00);
709                 b43_write16(dev, B43_MMIO_GPIO_CONTROL,
710                         b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00);
711
712                 if (init) {
713                         b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
714                         b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
715                         b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
716                         b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
717                 }
718         }
719 }
720
721 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
722 static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
723 {
724         u16 tmp;
725
726         if (dev->dev->id.revision == 16)
727                 b43_mac_suspend(dev);
728
729         tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
730         tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
731                 B43_NPHY_CLASSCTL_WAITEDEN);
732         tmp &= ~mask;
733         tmp |= (val & mask);
734         b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
735
736         if (dev->dev->id.revision == 16)
737                 b43_mac_enable(dev);
738
739         return tmp;
740 }
741
742 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
743 static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
744 {
745         struct b43_phy *phy = &dev->phy;
746         struct b43_phy_n *nphy = phy->n;
747
748         if (enable) {
749                 u16 clip[] = { 0xFFFF, 0xFFFF };
750                 if (nphy->deaf_count++ == 0) {
751                         nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
752                         b43_nphy_classifier(dev, 0x7, 0);
753                         b43_nphy_read_clip_detection(dev, nphy->clip_state);
754                         b43_nphy_write_clip_detection(dev, clip);
755                 }
756                 b43_nphy_reset_cca(dev);
757         } else {
758                 if (--nphy->deaf_count == 0) {
759                         b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
760                         b43_nphy_write_clip_detection(dev, nphy->clip_state);
761                 }
762         }
763 }
764
765 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
766 static void b43_nphy_stop_playback(struct b43_wldev *dev)
767 {
768         struct b43_phy_n *nphy = dev->phy.n;
769         u16 tmp;
770
771         if (nphy->hang_avoid)
772                 b43_nphy_stay_in_carrier_search(dev, 1);
773
774         tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
775         if (tmp & 0x1)
776                 b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
777         else if (tmp & 0x2)
778                 b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, (u16)~0x8000);
779
780         b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
781
782         if (nphy->bb_mult_save & 0x80000000) {
783                 tmp = nphy->bb_mult_save & 0xFFFF;
784                 b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
785                 nphy->bb_mult_save = 0;
786         }
787
788         if (nphy->hang_avoid)
789                 b43_nphy_stay_in_carrier_search(dev, 0);
790 }
791
792 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
793 static void b43_nphy_spur_workaround(struct b43_wldev *dev)
794 {
795         struct b43_phy_n *nphy = dev->phy.n;
796
797         u8 channel = nphy->radio_chanspec.channel;
798         int tone[2] = { 57, 58 };
799         u32 noise[2] = { 0x3FF, 0x3FF };
800
801         B43_WARN_ON(dev->phy.rev < 3);
802
803         if (nphy->hang_avoid)
804                 b43_nphy_stay_in_carrier_search(dev, 1);
805
806         if (nphy->gband_spurwar_en) {
807                 /* TODO: N PHY Adjust Analog Pfbw (7) */
808                 if (channel == 11 && dev->phy.is_40mhz)
809                         ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
810                 else
811                         ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
812                 /* TODO: N PHY Adjust CRS Min Power (0x1E) */
813         }
814
815         if (nphy->aband_spurwar_en) {
816                 if (channel == 54) {
817                         tone[0] = 0x20;
818                         noise[0] = 0x25F;
819                 } else if (channel == 38 || channel == 102 || channel == 118) {
820                         if (0 /* FIXME */) {
821                                 tone[0] = 0x20;
822                                 noise[0] = 0x21F;
823                         } else {
824                                 tone[0] = 0;
825                                 noise[0] = 0;
826                         }
827                 } else if (channel == 134) {
828                         tone[0] = 0x20;
829                         noise[0] = 0x21F;
830                 } else if (channel == 151) {
831                         tone[0] = 0x10;
832                         noise[0] = 0x23F;
833                 } else if (channel == 153 || channel == 161) {
834                         tone[0] = 0x30;
835                         noise[0] = 0x23F;
836                 } else {
837                         tone[0] = 0;
838                         noise[0] = 0;
839                 }
840
841                 if (!tone[0] && !noise[0])
842                         ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
843                 else
844                         ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
845         }
846
847         if (nphy->hang_avoid)
848                 b43_nphy_stay_in_carrier_search(dev, 0);
849 }
850
851 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
852 static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
853 {
854         struct b43_phy_n *nphy = dev->phy.n;
855
856         u8 i;
857         s16 tmp;
858         u16 data[4];
859         s16 gain[2];
860         u16 minmax[2];
861         u16 lna_gain[4] = { -2, 10, 19, 25 };
862
863         if (nphy->hang_avoid)
864                 b43_nphy_stay_in_carrier_search(dev, 1);
865
866         if (nphy->gain_boost) {
867                 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
868                         gain[0] = 6;
869                         gain[1] = 6;
870                 } else {
871                         tmp = 40370 - 315 * nphy->radio_chanspec.channel;
872                         gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
873                         tmp = 23242 - 224 * nphy->radio_chanspec.channel;
874                         gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
875                 }
876         } else {
877                 gain[0] = 0;
878                 gain[1] = 0;
879         }
880
881         for (i = 0; i < 2; i++) {
882                 if (nphy->elna_gain_config) {
883                         data[0] = 19 + gain[i];
884                         data[1] = 25 + gain[i];
885                         data[2] = 25 + gain[i];
886                         data[3] = 25 + gain[i];
887                 } else {
888                         data[0] = lna_gain[0] + gain[i];
889                         data[1] = lna_gain[1] + gain[i];
890                         data[2] = lna_gain[2] + gain[i];
891                         data[3] = lna_gain[3] + gain[i];
892                 }
893                 b43_ntab_write_bulk(dev, B43_NTAB16(10, 8), 4, data);
894
895                 minmax[i] = 23 + gain[i];
896         }
897
898         b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
899                                 minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
900         b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
901                                 minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
902
903         if (nphy->hang_avoid)
904                 b43_nphy_stay_in_carrier_search(dev, 0);
905 }
906
907 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
908 static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev)
909 {
910         struct b43_phy_n *nphy = dev->phy.n;
911         u8 i, j;
912         u8 code;
913
914         /* TODO: for PHY >= 3
915         s8 *lna1_gain, *lna2_gain;
916         u8 *gain_db, *gain_bits;
917         u16 *rfseq_init;
918         u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
919         u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
920         */
921
922         u8 rfseq_events[3] = { 6, 8, 7 };
923         u8 rfseq_delays[3] = { 10, 30, 1 };
924
925         if (dev->phy.rev >= 3) {
926                 /* TODO */
927         } else {
928                 /* Set Clip 2 detect */
929                 b43_phy_set(dev, B43_NPHY_C1_CGAINI,
930                                 B43_NPHY_C1_CGAINI_CL2DETECT);
931                 b43_phy_set(dev, B43_NPHY_C2_CGAINI,
932                                 B43_NPHY_C2_CGAINI_CL2DETECT);
933
934                 /* Set narrowband clip threshold */
935                 b43_phy_set(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
936                 b43_phy_set(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
937
938                 if (!dev->phy.is_40mhz) {
939                         /* Set dwell lengths */
940                         b43_phy_set(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
941                         b43_phy_set(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
942                         b43_phy_set(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
943                         b43_phy_set(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
944                 }
945
946                 /* Set wideband clip 2 threshold */
947                 b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
948                                 ~B43_NPHY_C1_CLIPWBTHRES_CLIP2,
949                                 21);
950                 b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
951                                 ~B43_NPHY_C2_CLIPWBTHRES_CLIP2,
952                                 21);
953
954                 if (!dev->phy.is_40mhz) {
955                         b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
956                                 ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
957                         b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
958                                 ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
959                         b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
960                                 ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
961                         b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
962                                 ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
963                 }
964
965                 b43_phy_set(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
966
967                 if (nphy->gain_boost) {
968                         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
969                             dev->phy.is_40mhz)
970                                 code = 4;
971                         else
972                                 code = 5;
973                 } else {
974                         code = dev->phy.is_40mhz ? 6 : 7;
975                 }
976
977                 /* Set HPVGA2 index */
978                 b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN,
979                                 ~B43_NPHY_C1_INITGAIN_HPVGA2,
980                                 code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
981                 b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN,
982                                 ~B43_NPHY_C2_INITGAIN_HPVGA2,
983                                 code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
984
985                 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
986                 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
987                                         (code << 8 | 0x7C));
988                 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
989                                         (code << 8 | 0x7C));
990
991                 b43_nphy_adjust_lna_gain_table(dev);
992
993                 if (nphy->elna_gain_config) {
994                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
995                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
996                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
997                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
998                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
999
1000                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
1001                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
1002                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1003                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1004                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1005
1006                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
1007                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
1008                                         (code << 8 | 0x74));
1009                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
1010                                         (code << 8 | 0x74));
1011                 }
1012
1013                 if (dev->phy.rev == 2) {
1014                         for (i = 0; i < 4; i++) {
1015                                 b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
1016                                                 (0x0400 * i) + 0x0020);
1017                                 for (j = 0; j < 21; j++)
1018                                         b43_phy_write(dev,
1019                                                 B43_NPHY_TABLE_DATALO, 3 * j);
1020                         }
1021
1022                         b43_nphy_set_rf_sequence(dev, 5,
1023                                         rfseq_events, rfseq_delays, 3);
1024                         b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
1025                                 (u16)~B43_NPHY_OVER_DGAIN_CCKDGECV,
1026                                 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
1027
1028                         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
1029                                 b43_phy_maskset(dev, B43_PHY_N(0xC5D),
1030                                                 0xFF80, 4);
1031                 }
1032         }
1033 }
1034
1035 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
1036 static void b43_nphy_workarounds(struct b43_wldev *dev)
1037 {
1038         struct ssb_bus *bus = dev->dev->bus;
1039         struct b43_phy *phy = &dev->phy;
1040         struct b43_phy_n *nphy = phy->n;
1041
1042         u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
1043         u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
1044
1045         u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
1046         u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
1047
1048         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
1049                 b43_nphy_classifier(dev, 1, 0);
1050         else
1051                 b43_nphy_classifier(dev, 1, 1);
1052
1053         if (nphy->hang_avoid)
1054                 b43_nphy_stay_in_carrier_search(dev, 1);
1055
1056         b43_phy_set(dev, B43_NPHY_IQFLIP,
1057                     B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
1058
1059         if (dev->phy.rev >= 3) {
1060                 /* TODO */
1061         } else {
1062                 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
1063                     nphy->band5g_pwrgain) {
1064                         b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
1065                         b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
1066                 } else {
1067                         b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
1068                         b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
1069                 }
1070
1071                 /* TODO: convert to b43_ntab_write? */
1072                 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000);
1073                 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
1074                 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010);
1075                 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
1076                 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002);
1077                 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
1078                 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012);
1079                 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
1080
1081                 if (dev->phy.rev < 2) {
1082                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008);
1083                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
1084                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018);
1085                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
1086                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007);
1087                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
1088                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017);
1089                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
1090                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006);
1091                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
1092                         b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016);
1093                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
1094                 }
1095
1096                 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
1097                 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
1098                 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
1099                 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
1100
1101                 if (bus->sprom.boardflags2_lo & 0x100 &&
1102                     bus->boardinfo.type == 0x8B) {
1103                         delays1[0] = 0x1;
1104                         delays1[5] = 0x14;
1105                 }
1106                 b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
1107                 b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
1108
1109                 b43_nphy_gain_crtl_workarounds(dev);
1110
1111                 if (dev->phy.rev < 2) {
1112                         if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
1113                                 ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/
1114                 } else if (dev->phy.rev == 2) {
1115                         b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
1116                         b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
1117                 }
1118
1119                 if (dev->phy.rev < 2)
1120                         b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
1121                                         ~B43_NPHY_SCRAM_SIGCTL_SCM);
1122
1123                 /* Set phase track alpha and beta */
1124                 b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
1125                 b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
1126                 b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
1127                 b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
1128                 b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
1129                 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
1130
1131                 b43_phy_mask(dev, B43_NPHY_PIL_DW1,
1132                                 (u16)~B43_NPHY_PIL_DW_64QAM);
1133                 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
1134                 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
1135                 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
1136
1137                 if (dev->phy.rev == 2)
1138                         b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
1139                                         B43_NPHY_FINERX2_CGC_DECGC);
1140         }
1141
1142         if (nphy->hang_avoid)
1143                 b43_nphy_stay_in_carrier_search(dev, 0);
1144 }
1145
1146 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
1147 static int b43_nphy_load_samples(struct b43_wldev *dev,
1148                                         struct b43_c32 *samples, u16 len) {
1149         struct b43_phy_n *nphy = dev->phy.n;
1150         u16 i;
1151         u32 *data;
1152
1153         data = kzalloc(len * sizeof(u32), GFP_KERNEL);
1154         if (!data) {
1155                 b43err(dev->wl, "allocation for samples loading failed\n");
1156                 return -ENOMEM;
1157         }
1158         if (nphy->hang_avoid)
1159                 b43_nphy_stay_in_carrier_search(dev, 1);
1160
1161         for (i = 0; i < len; i++) {
1162                 data[i] = (samples[i].i & 0x3FF << 10);
1163                 data[i] |= samples[i].q & 0x3FF;
1164         }
1165         b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
1166
1167         kfree(data);
1168         if (nphy->hang_avoid)
1169                 b43_nphy_stay_in_carrier_search(dev, 0);
1170         return 0;
1171 }
1172
1173 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
1174 static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
1175                                         bool test)
1176 {
1177         int i;
1178         u16 bw, len, rot, angle;
1179         struct b43_c32 *samples;
1180
1181
1182         bw = (dev->phy.is_40mhz) ? 40 : 20;
1183         len = bw << 3;
1184
1185         if (test) {
1186                 if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
1187                         bw = 82;
1188                 else
1189                         bw = 80;
1190
1191                 if (dev->phy.is_40mhz)
1192                         bw <<= 1;
1193
1194                 len = bw << 1;
1195         }
1196
1197         samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL);
1198         if (!samples) {
1199                 b43err(dev->wl, "allocation for samples generation failed\n");
1200                 return 0;
1201         }
1202         rot = (((freq * 36) / bw) << 16) / 100;
1203         angle = 0;
1204
1205         for (i = 0; i < len; i++) {
1206                 samples[i] = b43_cordic(angle);
1207                 angle += rot;
1208                 samples[i].q = CORDIC_CONVERT(samples[i].q * max);
1209                 samples[i].i = CORDIC_CONVERT(samples[i].i * max);
1210         }
1211
1212         i = b43_nphy_load_samples(dev, samples, len);
1213         kfree(samples);
1214         return (i < 0) ? 0 : len;
1215 }
1216
1217 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
1218 static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
1219                                         u16 wait, bool iqmode, bool dac_test)
1220 {
1221         struct b43_phy_n *nphy = dev->phy.n;
1222         int i;
1223         u16 seq_mode;
1224         u32 tmp;
1225
1226         if (nphy->hang_avoid)
1227                 b43_nphy_stay_in_carrier_search(dev, true);
1228
1229         if ((nphy->bb_mult_save & 0x80000000) == 0) {
1230                 tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
1231                 nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
1232         }
1233
1234         if (!dev->phy.is_40mhz)
1235                 tmp = 0x6464;
1236         else
1237                 tmp = 0x4747;
1238         b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
1239
1240         if (nphy->hang_avoid)
1241                 b43_nphy_stay_in_carrier_search(dev, false);
1242
1243         b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
1244
1245         if (loops != 0xFFFF)
1246                 b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
1247         else
1248                 b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
1249
1250         b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
1251
1252         seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
1253
1254         b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
1255         if (iqmode) {
1256                 b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
1257                 b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
1258         } else {
1259                 if (dac_test)
1260                         b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
1261                 else
1262                         b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
1263         }
1264         for (i = 0; i < 100; i++) {
1265                 if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) {
1266                         i = 0;
1267                         break;
1268                 }
1269                 udelay(10);
1270         }
1271         if (i)
1272                 b43err(dev->wl, "run samples timeout\n");
1273
1274         b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
1275 }
1276
1277 /*
1278  * Transmits a known value for LO calibration
1279  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
1280  */
1281 static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
1282                                 bool iqmode, bool dac_test)
1283 {
1284         u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
1285         if (samp == 0)
1286                 return -1;
1287         b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
1288         return 0;
1289 }
1290
1291 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
1292 static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
1293 {
1294         struct b43_phy_n *nphy = dev->phy.n;
1295         int i, j;
1296         u32 tmp;
1297         u32 cur_real, cur_imag, real_part, imag_part;
1298
1299         u16 buffer[7];
1300
1301         if (nphy->hang_avoid)
1302                 b43_nphy_stay_in_carrier_search(dev, true);
1303
1304         b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
1305
1306         for (i = 0; i < 2; i++) {
1307                 tmp = ((buffer[i * 2] & 0x3FF) << 10) |
1308                         (buffer[i * 2 + 1] & 0x3FF);
1309                 b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
1310                                 (((i + 26) << 10) | 320));
1311                 for (j = 0; j < 128; j++) {
1312                         b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
1313                                         ((tmp >> 16) & 0xFFFF));
1314                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
1315                                         (tmp & 0xFFFF));
1316                 }
1317         }
1318
1319         for (i = 0; i < 2; i++) {
1320                 tmp = buffer[5 + i];
1321                 real_part = (tmp >> 8) & 0xFF;
1322                 imag_part = (tmp & 0xFF);
1323                 b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
1324                                 (((i + 26) << 10) | 448));
1325
1326                 if (dev->phy.rev >= 3) {
1327                         cur_real = real_part;
1328                         cur_imag = imag_part;
1329                         tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
1330                 }
1331
1332                 for (j = 0; j < 128; j++) {
1333                         if (dev->phy.rev < 3) {
1334                                 cur_real = (real_part * loscale[j] + 128) >> 8;
1335                                 cur_imag = (imag_part * loscale[j] + 128) >> 8;
1336                                 tmp = ((cur_real & 0xFF) << 8) |
1337                                         (cur_imag & 0xFF);
1338                         }
1339                         b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
1340                                         ((tmp >> 16) & 0xFFFF));
1341                         b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
1342                                         (tmp & 0xFFFF));
1343                 }
1344         }
1345
1346         if (dev->phy.rev >= 3) {
1347                 b43_shm_write16(dev, B43_SHM_SHARED,
1348                                 B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
1349                 b43_shm_write16(dev, B43_SHM_SHARED,
1350                                 B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
1351         }
1352
1353         if (nphy->hang_avoid)
1354                 b43_nphy_stay_in_carrier_search(dev, false);
1355 }
1356
1357 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
1358 static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
1359                                         u8 *events, u8 *delays, u8 length)
1360 {
1361         struct b43_phy_n *nphy = dev->phy.n;
1362         u8 i;
1363         u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
1364         u16 offset1 = cmd << 4;
1365         u16 offset2 = offset1 + 0x80;
1366
1367         if (nphy->hang_avoid)
1368                 b43_nphy_stay_in_carrier_search(dev, true);
1369
1370         b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
1371         b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
1372
1373         for (i = length; i < 16; i++) {
1374                 b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
1375                 b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
1376         }
1377
1378         if (nphy->hang_avoid)
1379                 b43_nphy_stay_in_carrier_search(dev, false);
1380 }
1381
1382 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
1383 static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
1384                                        enum b43_nphy_rf_sequence seq)
1385 {
1386         static const u16 trigger[] = {
1387                 [B43_RFSEQ_RX2TX]               = B43_NPHY_RFSEQTR_RX2TX,
1388                 [B43_RFSEQ_TX2RX]               = B43_NPHY_RFSEQTR_TX2RX,
1389                 [B43_RFSEQ_RESET2RX]            = B43_NPHY_RFSEQTR_RST2RX,
1390                 [B43_RFSEQ_UPDATE_GAINH]        = B43_NPHY_RFSEQTR_UPGH,
1391                 [B43_RFSEQ_UPDATE_GAINL]        = B43_NPHY_RFSEQTR_UPGL,
1392                 [B43_RFSEQ_UPDATE_GAINU]        = B43_NPHY_RFSEQTR_UPGU,
1393         };
1394         int i;
1395         u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
1396
1397         B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
1398
1399         b43_phy_set(dev, B43_NPHY_RFSEQMODE,
1400                     B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
1401         b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
1402         for (i = 0; i < 200; i++) {
1403                 if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
1404                         goto ok;
1405                 msleep(1);
1406         }
1407         b43err(dev->wl, "RF sequence status timeout\n");
1408 ok:
1409         b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
1410 }
1411
1412 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
1413 static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
1414                                                 u16 value, u8 core, bool off)
1415 {
1416         int i;
1417         u8 index = fls(field);
1418         u8 addr, en_addr, val_addr;
1419         /* we expect only one bit set */
1420         B43_WARN_ON(field & (~(1 << (index - 1))));
1421
1422         if (dev->phy.rev >= 3) {
1423                 const struct nphy_rf_control_override_rev3 *rf_ctrl;
1424                 for (i = 0; i < 2; i++) {
1425                         if (index == 0 || index == 16) {
1426                                 b43err(dev->wl,
1427                                         "Unsupported RF Ctrl Override call\n");
1428                                 return;
1429                         }
1430
1431                         rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
1432                         en_addr = B43_PHY_N((i == 0) ?
1433                                 rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
1434                         val_addr = B43_PHY_N((i == 0) ?
1435                                 rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
1436
1437                         if (off) {
1438                                 b43_phy_mask(dev, en_addr, ~(field));
1439                                 b43_phy_mask(dev, val_addr,
1440                                                 ~(rf_ctrl->val_mask));
1441                         } else {
1442                                 if (core == 0 || ((1 << core) & i) != 0) {
1443                                         b43_phy_set(dev, en_addr, field);
1444                                         b43_phy_maskset(dev, val_addr,
1445                                                 ~(rf_ctrl->val_mask),
1446                                                 (value << rf_ctrl->val_shift));
1447                                 }
1448                         }
1449                 }
1450         } else {
1451                 const struct nphy_rf_control_override_rev2 *rf_ctrl;
1452                 if (off) {
1453                         b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
1454                         value = 0;
1455                 } else {
1456                         b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
1457                 }
1458
1459                 for (i = 0; i < 2; i++) {
1460                         if (index <= 1 || index == 16) {
1461                                 b43err(dev->wl,
1462                                         "Unsupported RF Ctrl Override call\n");
1463                                 return;
1464                         }
1465
1466                         if (index == 2 || index == 10 ||
1467                             (index >= 13 && index <= 15)) {
1468                                 core = 1;
1469                         }
1470
1471                         rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
1472                         addr = B43_PHY_N((i == 0) ?
1473                                 rf_ctrl->addr0 : rf_ctrl->addr1);
1474
1475                         if ((core & (1 << i)) != 0)
1476                                 b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
1477                                                 (value << rf_ctrl->shift));
1478
1479                         b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
1480                         b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
1481                                         B43_NPHY_RFCTL_CMD_START);
1482                         udelay(1);
1483                         b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
1484                 }
1485         }
1486 }
1487
1488 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
1489 static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
1490                                                 u16 value, u8 core)
1491 {
1492         u8 i, j;
1493         u16 reg, tmp, val;
1494
1495         B43_WARN_ON(dev->phy.rev < 3);
1496         B43_WARN_ON(field > 4);
1497
1498         for (i = 0; i < 2; i++) {
1499                 if ((core == 1 && i == 1) || (core == 2 && !i))
1500                         continue;
1501
1502                 reg = (i == 0) ?
1503                         B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
1504                 b43_phy_mask(dev, reg, 0xFBFF);
1505
1506                 switch (field) {
1507                 case 0:
1508                         b43_phy_write(dev, reg, 0);
1509                         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
1510                         break;
1511                 case 1:
1512                         if (!i) {
1513                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
1514                                                 0xFC3F, (value << 6));
1515                                 b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
1516                                                 0xFFFE, 1);
1517                                 b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
1518                                                 B43_NPHY_RFCTL_CMD_START);
1519                                 for (j = 0; j < 100; j++) {
1520                                         if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) {
1521                                                 j = 0;
1522                                                 break;
1523                                         }
1524                                         udelay(10);
1525                                 }
1526                                 if (j)
1527                                         b43err(dev->wl,
1528                                                 "intc override timeout\n");
1529                                 b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
1530                                                 0xFFFE);
1531                         } else {
1532                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
1533                                                 0xFC3F, (value << 6));
1534                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
1535                                                 0xFFFE, 1);
1536                                 b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
1537                                                 B43_NPHY_RFCTL_CMD_RXTX);
1538                                 for (j = 0; j < 100; j++) {
1539                                         if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) {
1540                                                 j = 0;
1541                                                 break;
1542                                         }
1543                                         udelay(10);
1544                                 }
1545                                 if (j)
1546                                         b43err(dev->wl,
1547                                                 "intc override timeout\n");
1548                                 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
1549                                                 0xFFFE);
1550                         }
1551                         break;
1552                 case 2:
1553                         if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
1554                                 tmp = 0x0020;
1555                                 val = value << 5;
1556                         } else {
1557                                 tmp = 0x0010;
1558                                 val = value << 4;
1559                         }
1560                         b43_phy_maskset(dev, reg, ~tmp, val);
1561                         break;
1562                 case 3:
1563                         if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
1564                                 tmp = 0x0001;
1565                                 val = value;
1566                         } else {
1567                                 tmp = 0x0004;
1568                                 val = value << 2;
1569                         }
1570                         b43_phy_maskset(dev, reg, ~tmp, val);
1571                         break;
1572                 case 4:
1573                         if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
1574                                 tmp = 0x0002;
1575                                 val = value << 1;
1576                         } else {
1577                                 tmp = 0x0008;
1578                                 val = value << 3;
1579                         }
1580                         b43_phy_maskset(dev, reg, ~tmp, val);
1581                         break;
1582                 }
1583         }
1584 }
1585
1586 static void b43_nphy_bphy_init(struct b43_wldev *dev)
1587 {
1588         unsigned int i;
1589         u16 val;
1590
1591         val = 0x1E1F;
1592         for (i = 0; i < 14; i++) {
1593                 b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
1594                 val -= 0x202;
1595         }
1596         val = 0x3E3F;
1597         for (i = 0; i < 16; i++) {
1598                 b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val);
1599                 val -= 0x202;
1600         }
1601         b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
1602 }
1603
1604 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
1605 static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
1606                                        s8 offset, u8 core, u8 rail, u8 type)
1607 {
1608         u16 tmp;
1609         bool core1or5 = (core == 1) || (core == 5);
1610         bool core2or5 = (core == 2) || (core == 5);
1611
1612         offset = clamp_val(offset, -32, 31);
1613         tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
1614
1615         if (core1or5 && (rail == 0) && (type == 2))
1616                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
1617         if (core1or5 && (rail == 1) && (type == 2))
1618                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
1619         if (core2or5 && (rail == 0) && (type == 2))
1620                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
1621         if (core2or5 && (rail == 1) && (type == 2))
1622                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
1623         if (core1or5 && (rail == 0) && (type == 0))
1624                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
1625         if (core1or5 && (rail == 1) && (type == 0))
1626                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
1627         if (core2or5 && (rail == 0) && (type == 0))
1628                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
1629         if (core2or5 && (rail == 1) && (type == 0))
1630                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
1631         if (core1or5 && (rail == 0) && (type == 1))
1632                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
1633         if (core1or5 && (rail == 1) && (type == 1))
1634                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
1635         if (core2or5 && (rail == 0) && (type == 1))
1636                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
1637         if (core2or5 && (rail == 1) && (type == 1))
1638                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
1639         if (core1or5 && (rail == 0) && (type == 6))
1640                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
1641         if (core1or5 && (rail == 1) && (type == 6))
1642                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
1643         if (core2or5 && (rail == 0) && (type == 6))
1644                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
1645         if (core2or5 && (rail == 1) && (type == 6))
1646                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
1647         if (core1or5 && (rail == 0) && (type == 3))
1648                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
1649         if (core1or5 && (rail == 1) && (type == 3))
1650                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
1651         if (core2or5 && (rail == 0) && (type == 3))
1652                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
1653         if (core2or5 && (rail == 1) && (type == 3))
1654                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
1655         if (core1or5 && (type == 4))
1656                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
1657         if (core2or5 && (type == 4))
1658                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
1659         if (core1or5 && (type == 5))
1660                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
1661         if (core2or5 && (type == 5))
1662                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
1663 }
1664
1665 static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1666 {
1667         u16 val;
1668
1669         if (type < 3)
1670                 val = 0;
1671         else if (type == 6)
1672                 val = 1;
1673         else if (type == 3)
1674                 val = 2;
1675         else
1676                 val = 3;
1677
1678         val = (val << 12) | (val << 14);
1679         b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
1680         b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
1681
1682         if (type < 3) {
1683                 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
1684                                 (type + 1) << 4);
1685                 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
1686                                 (type + 1) << 4);
1687         }
1688
1689         /* TODO use some definitions */
1690         if (code == 0) {
1691                 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0);
1692                 if (type < 3) {
1693                         b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFEC7, 0);
1694                         b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xEFDC, 0);
1695                         b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0);
1696                         udelay(20);
1697                         b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0);
1698                 }
1699         } else {
1700                 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF,
1701                                 0x3000);
1702                 if (type < 3) {
1703                         b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
1704                                         0xFEC7, 0x0180);
1705                         b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
1706                                         0xEFDC, (code << 1 | 0x1021));
1707                         b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0x1);
1708                         udelay(20);
1709                         b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0);
1710                 }
1711         }
1712 }
1713
1714 static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1715 {
1716         struct b43_phy_n *nphy = dev->phy.n;
1717         u8 i;
1718         u16 reg, val;
1719
1720         if (code == 0) {
1721                 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
1722                 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
1723                 b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
1724                 b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
1725                 b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
1726                 b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
1727                 b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
1728                 b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
1729         } else {
1730                 for (i = 0; i < 2; i++) {
1731                         if ((code == 1 && i == 1) || (code == 2 && !i))
1732                                 continue;
1733
1734                         reg = (i == 0) ?
1735                                 B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
1736                         b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
1737
1738                         if (type < 3) {
1739                                 reg = (i == 0) ?
1740                                         B43_NPHY_AFECTL_C1 :
1741                                         B43_NPHY_AFECTL_C2;
1742                                 b43_phy_maskset(dev, reg, 0xFCFF, 0);
1743
1744                                 reg = (i == 0) ?
1745                                         B43_NPHY_RFCTL_LUT_TRSW_UP1 :
1746                                         B43_NPHY_RFCTL_LUT_TRSW_UP2;
1747                                 b43_phy_maskset(dev, reg, 0xFFC3, 0);
1748
1749                                 if (type == 0)
1750                                         val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
1751                                 else if (type == 1)
1752                                         val = 16;
1753                                 else
1754                                         val = 32;
1755                                 b43_phy_set(dev, reg, val);
1756
1757                                 reg = (i == 0) ?
1758                                         B43_NPHY_TXF_40CO_B1S0 :
1759                                         B43_NPHY_TXF_40CO_B32S1;
1760                                 b43_phy_set(dev, reg, 0x0020);
1761                         } else {
1762                                 if (type == 6)
1763                                         val = 0x0100;
1764                                 else if (type == 3)
1765                                         val = 0x0200;
1766                                 else
1767                                         val = 0x0300;
1768
1769                                 reg = (i == 0) ?
1770                                         B43_NPHY_AFECTL_C1 :
1771                                         B43_NPHY_AFECTL_C2;
1772
1773                                 b43_phy_maskset(dev, reg, 0xFCFF, val);
1774                                 b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
1775
1776                                 if (type != 3 && type != 6) {
1777                                         enum ieee80211_band band =
1778                                                 b43_current_band(dev->wl);
1779
1780                                         if ((nphy->ipa2g_on &&
1781                                                 band == IEEE80211_BAND_2GHZ) ||
1782                                                 (nphy->ipa5g_on &&
1783                                                 band == IEEE80211_BAND_5GHZ))
1784                                                 val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
1785                                         else
1786                                                 val = 0x11;
1787                                         reg = (i == 0) ? 0x2000 : 0x3000;
1788                                         reg |= B2055_PADDRV;
1789                                         b43_radio_write16(dev, reg, val);
1790
1791                                         reg = (i == 0) ?
1792                                                 B43_NPHY_AFECTL_OVER1 :
1793                                                 B43_NPHY_AFECTL_OVER;
1794                                         b43_phy_set(dev, reg, 0x0200);
1795                                 }
1796                         }
1797                 }
1798         }
1799 }
1800
1801 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
1802 static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1803 {
1804         if (dev->phy.rev >= 3)
1805                 b43_nphy_rev3_rssi_select(dev, code, type);
1806         else
1807                 b43_nphy_rev2_rssi_select(dev, code, type);
1808 }
1809
1810 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
1811 static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
1812 {
1813         int i;
1814         for (i = 0; i < 2; i++) {
1815                 if (type == 2) {
1816                         if (i == 0) {
1817                                 b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
1818                                                   0xFC, buf[0]);
1819                                 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
1820                                                   0xFC, buf[1]);
1821                         } else {
1822                                 b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
1823                                                   0xFC, buf[2 * i]);
1824                                 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
1825                                                   0xFC, buf[2 * i + 1]);
1826                         }
1827                 } else {
1828                         if (i == 0)
1829                                 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
1830                                                   0xF3, buf[0] << 2);
1831                         else
1832                                 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
1833                                                   0xF3, buf[2 * i + 1] << 2);
1834                 }
1835         }
1836 }
1837
1838 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
1839 static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
1840                                 u8 nsamp)
1841 {
1842         int i;
1843         int out;
1844         u16 save_regs_phy[9];
1845         u16 s[2];
1846
1847         if (dev->phy.rev >= 3) {
1848                 save_regs_phy[0] = b43_phy_read(dev,
1849                                                 B43_NPHY_RFCTL_LUT_TRSW_UP1);
1850                 save_regs_phy[1] = b43_phy_read(dev,
1851                                                 B43_NPHY_RFCTL_LUT_TRSW_UP2);
1852                 save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
1853                 save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
1854                 save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
1855                 save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
1856                 save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
1857                 save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
1858         }
1859
1860         b43_nphy_rssi_select(dev, 5, type);
1861
1862         if (dev->phy.rev < 2) {
1863                 save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
1864                 b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
1865         }
1866
1867         for (i = 0; i < 4; i++)
1868                 buf[i] = 0;
1869
1870         for (i = 0; i < nsamp; i++) {
1871                 if (dev->phy.rev < 2) {
1872                         s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
1873                         s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
1874                 } else {
1875                         s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
1876                         s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
1877                 }
1878
1879                 buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
1880                 buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
1881                 buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
1882                 buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
1883         }
1884         out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
1885                 (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
1886
1887         if (dev->phy.rev < 2)
1888                 b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
1889
1890         if (dev->phy.rev >= 3) {
1891                 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
1892                                 save_regs_phy[0]);
1893                 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
1894                                 save_regs_phy[1]);
1895                 b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
1896                 b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]);
1897                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
1898                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
1899                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
1900                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
1901         }
1902
1903         return out;
1904 }
1905
1906 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
1907 static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
1908 {
1909         int i, j;
1910         u8 state[4];
1911         u8 code, val;
1912         u16 class, override;
1913         u8 regs_save_radio[2];
1914         u16 regs_save_phy[2];
1915         s8 offset[4];
1916
1917         u16 clip_state[2];
1918         u16 clip_off[2] = { 0xFFFF, 0xFFFF };
1919         s32 results_min[4] = { };
1920         u8 vcm_final[4] = { };
1921         s32 results[4][4] = { };
1922         s32 miniq[4][2] = { };
1923
1924         if (type == 2) {
1925                 code = 0;
1926                 val = 6;
1927         } else if (type < 2) {
1928                 code = 25;
1929                 val = 4;
1930         } else {
1931                 B43_WARN_ON(1);
1932                 return;
1933         }
1934
1935         class = b43_nphy_classifier(dev, 0, 0);
1936         b43_nphy_classifier(dev, 7, 4);
1937         b43_nphy_read_clip_detection(dev, clip_state);
1938         b43_nphy_write_clip_detection(dev, clip_off);
1939
1940         if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
1941                 override = 0x140;
1942         else
1943                 override = 0x110;
1944
1945         regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
1946         regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
1947         b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
1948         b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
1949
1950         regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
1951         regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
1952         b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
1953         b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
1954
1955         state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
1956         state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
1957         b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
1958         b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
1959         state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
1960         state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
1961
1962         b43_nphy_rssi_select(dev, 5, type);
1963         b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
1964         b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
1965
1966         for (i = 0; i < 4; i++) {
1967                 u8 tmp[4];
1968                 for (j = 0; j < 4; j++)
1969                         tmp[j] = i;
1970                 if (type != 1)
1971                         b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
1972                 b43_nphy_poll_rssi(dev, type, results[i], 8);
1973                 if (type < 2)
1974                         for (j = 0; j < 2; j++)
1975                                 miniq[i][j] = min(results[i][2 * j],
1976                                                 results[i][2 * j + 1]);
1977         }
1978
1979         for (i = 0; i < 4; i++) {
1980                 s32 mind = 40;
1981                 u8 minvcm = 0;
1982                 s32 minpoll = 249;
1983                 s32 curr;
1984                 for (j = 0; j < 4; j++) {
1985                         if (type == 2)
1986                                 curr = abs(results[j][i]);
1987                         else
1988                                 curr = abs(miniq[j][i / 2] - code * 8);
1989
1990                         if (curr < mind) {
1991                                 mind = curr;
1992                                 minvcm = j;
1993                         }
1994
1995                         if (results[j][i] < minpoll)
1996                                 minpoll = results[j][i];
1997                 }
1998                 results_min[i] = minpoll;
1999                 vcm_final[i] = minvcm;
2000         }
2001
2002         if (type != 1)
2003                 b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
2004
2005         for (i = 0; i < 4; i++) {
2006                 offset[i] = (code * 8) - results[vcm_final[i]][i];
2007
2008                 if (offset[i] < 0)
2009                         offset[i] = -((abs(offset[i]) + 4) / 8);
2010                 else
2011                         offset[i] = (offset[i] + 4) / 8;
2012
2013                 if (results_min[i] == 248)
2014                         offset[i] = code - 32;
2015
2016                 if (i % 2 == 0)
2017                         b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0,
2018                                                         type);
2019                 else
2020                         b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1,
2021                                                         type);
2022         }
2023
2024         b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
2025         b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]);
2026
2027         switch (state[2]) {
2028         case 1:
2029                 b43_nphy_rssi_select(dev, 1, 2);
2030                 break;
2031         case 4:
2032                 b43_nphy_rssi_select(dev, 1, 0);
2033                 break;
2034         case 2:
2035                 b43_nphy_rssi_select(dev, 1, 1);
2036                 break;
2037         default:
2038                 b43_nphy_rssi_select(dev, 1, 1);
2039                 break;
2040         }
2041
2042         switch (state[3]) {
2043         case 1:
2044                 b43_nphy_rssi_select(dev, 2, 2);
2045                 break;
2046         case 4:
2047                 b43_nphy_rssi_select(dev, 2, 0);
2048                 break;
2049         default:
2050                 b43_nphy_rssi_select(dev, 2, 1);
2051                 break;
2052         }
2053
2054         b43_nphy_rssi_select(dev, 0, type);
2055
2056         b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
2057         b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
2058         b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
2059         b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
2060
2061         b43_nphy_classifier(dev, 7, class);
2062         b43_nphy_write_clip_detection(dev, clip_state);
2063 }
2064
2065 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
2066 static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
2067 {
2068         /* TODO */
2069 }
2070
2071 /*
2072  * RSSI Calibration
2073  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
2074  */
2075 static void b43_nphy_rssi_cal(struct b43_wldev *dev)
2076 {
2077         if (dev->phy.rev >= 3) {
2078                 b43_nphy_rev3_rssi_cal(dev);
2079         } else {
2080                 b43_nphy_rev2_rssi_cal(dev, 2);
2081                 b43_nphy_rev2_rssi_cal(dev, 0);
2082                 b43_nphy_rev2_rssi_cal(dev, 1);
2083         }
2084 }
2085
2086 /*
2087  * Restore RSSI Calibration
2088  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
2089  */
2090 static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
2091 {
2092         struct b43_phy_n *nphy = dev->phy.n;
2093
2094         u16 *rssical_radio_regs = NULL;
2095         u16 *rssical_phy_regs = NULL;
2096
2097         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2098                 if (b43_empty_chanspec(&nphy->rssical_chanspec_2G))
2099                         return;
2100                 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
2101                 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
2102         } else {
2103                 if (b43_empty_chanspec(&nphy->rssical_chanspec_5G))
2104                         return;
2105                 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
2106                 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
2107         }
2108
2109         /* TODO use some definitions */
2110         b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
2111         b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
2112
2113         b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
2114         b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
2115         b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
2116         b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
2117
2118         b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
2119         b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
2120         b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
2121         b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
2122
2123         b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
2124         b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
2125         b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
2126         b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
2127 }
2128
2129 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
2130 static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
2131 {
2132         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2133                 if (dev->phy.rev >= 6) {
2134                         /* TODO If the chip is 47162
2135                                 return txpwrctrl_tx_gain_ipa_rev5 */
2136                         return txpwrctrl_tx_gain_ipa_rev6;
2137                 } else if (dev->phy.rev >= 5) {
2138                         return txpwrctrl_tx_gain_ipa_rev5;
2139                 } else {
2140                         return txpwrctrl_tx_gain_ipa;
2141                 }
2142         } else {
2143                 return txpwrctrl_tx_gain_ipa_5g;
2144         }
2145 }
2146
2147 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
2148 static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
2149 {
2150         struct b43_phy_n *nphy = dev->phy.n;
2151         u16 *save = nphy->tx_rx_cal_radio_saveregs;
2152         u16 tmp;
2153         u8 offset, i;
2154
2155         if (dev->phy.rev >= 3) {
2156             for (i = 0; i < 2; i++) {
2157                 tmp = (i == 0) ? 0x2000 : 0x3000;
2158                 offset = i * 11;
2159
2160                 save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
2161                 save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
2162                 save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
2163                 save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
2164                 save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
2165                 save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
2166                 save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
2167                 save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
2168                 save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
2169                 save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
2170                 save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
2171
2172                 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2173                         b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
2174                         b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
2175                         b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
2176                         b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
2177                         b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
2178                         if (nphy->ipa5g_on) {
2179                                 b43_radio_write16(dev, tmp | B2055_PADDRV, 4);
2180                                 b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
2181                         } else {
2182                                 b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
2183                                 b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
2184                         }
2185                         b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
2186                 } else {
2187                         b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
2188                         b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
2189                         b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
2190                         b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
2191                         b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
2192                         b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
2193                         if (nphy->ipa2g_on) {
2194                                 b43_radio_write16(dev, tmp | B2055_PADDRV, 6);
2195                                 b43_radio_write16(dev, tmp | B2055_XOCTL2,
2196                                         (dev->phy.rev < 5) ? 0x11 : 0x01);
2197                         } else {
2198                                 b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
2199                                 b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
2200                         }
2201                 }
2202                 b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
2203                 b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
2204                 b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0);
2205             }
2206         } else {
2207                 save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
2208                 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
2209
2210                 save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2);
2211                 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
2212
2213                 save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1);
2214                 b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
2215
2216                 save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2);
2217                 b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
2218
2219                 save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX);
2220                 save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
2221
2222                 if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
2223                     B43_NPHY_BANDCTL_5GHZ)) {
2224                         b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04);
2225                         b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04);
2226                 } else {
2227                         b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20);
2228                         b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20);
2229                 }
2230
2231                 if (dev->phy.rev < 2) {
2232                         b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
2233                         b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
2234                 } else {
2235                         b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
2236                         b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
2237                 }
2238         }
2239 }
2240
2241 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
2242 static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
2243                                         struct nphy_txgains target,
2244                                         struct nphy_iqcal_params *params)
2245 {
2246         int i, j, indx;
2247         u16 gain;
2248
2249         if (dev->phy.rev >= 3) {
2250                 params->txgm = target.txgm[core];
2251                 params->pga = target.pga[core];
2252                 params->pad = target.pad[core];
2253                 params->ipa = target.ipa[core];
2254                 params->cal_gain = (params->txgm << 12) | (params->pga << 8) |
2255                                         (params->pad << 4) | (params->ipa);
2256                 for (j = 0; j < 5; j++)
2257                         params->ncorr[j] = 0x79;
2258         } else {
2259                 gain = (target.pad[core]) | (target.pga[core] << 4) |
2260                         (target.txgm[core] << 8);
2261
2262                 indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ?
2263                         1 : 0;
2264                 for (i = 0; i < 9; i++)
2265                         if (tbl_iqcal_gainparams[indx][i][0] == gain)
2266                                 break;
2267                 i = min(i, 8);
2268
2269                 params->txgm = tbl_iqcal_gainparams[indx][i][1];
2270                 params->pga = tbl_iqcal_gainparams[indx][i][2];
2271                 params->pad = tbl_iqcal_gainparams[indx][i][3];
2272                 params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
2273                                         (params->pad << 2);
2274                 for (j = 0; j < 4; j++)
2275                         params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
2276         }
2277 }
2278
2279 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
2280 static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
2281 {
2282         struct b43_phy_n *nphy = dev->phy.n;
2283         int i;
2284         u16 scale, entry;
2285
2286         u16 tmp = nphy->txcal_bbmult;
2287         if (core == 0)
2288                 tmp >>= 8;
2289         tmp &= 0xff;
2290
2291         for (i = 0; i < 18; i++) {
2292                 scale = (ladder_lo[i].percent * tmp) / 100;
2293                 entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
2294                 b43_ntab_write(dev, B43_NTAB16(15, i), entry);
2295
2296                 scale = (ladder_iq[i].percent * tmp) / 100;
2297                 entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
2298                 b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
2299         }
2300 }
2301
2302 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
2303 static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
2304 {
2305         int i;
2306         for (i = 0; i < 15; i++)
2307                 b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
2308                                 tbl_tx_filter_coef_rev4[2][i]);
2309 }
2310
2311 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
2312 static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
2313 {
2314         int i, j;
2315         /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
2316         u16 offset[] = { 0x186, 0x195, 0x2C5 };
2317
2318         for (i = 0; i < 3; i++)
2319                 for (j = 0; j < 15; j++)
2320                         b43_phy_write(dev, B43_PHY_N(offset[i] + j),
2321                                         tbl_tx_filter_coef_rev4[i][j]);
2322
2323         if (dev->phy.is_40mhz) {
2324                 for (j = 0; j < 15; j++)
2325                         b43_phy_write(dev, B43_PHY_N(offset[0] + j),
2326                                         tbl_tx_filter_coef_rev4[3][j]);
2327         } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2328                 for (j = 0; j < 15; j++)
2329                         b43_phy_write(dev, B43_PHY_N(offset[0] + j),
2330                                         tbl_tx_filter_coef_rev4[5][j]);
2331         }
2332
2333         if (dev->phy.channel == 14)
2334                 for (j = 0; j < 15; j++)
2335                         b43_phy_write(dev, B43_PHY_N(offset[0] + j),
2336                                         tbl_tx_filter_coef_rev4[6][j]);
2337 }
2338
2339 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
2340 static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
2341 {
2342         struct b43_phy_n *nphy = dev->phy.n;
2343
2344         u16 curr_gain[2];
2345         struct nphy_txgains target;
2346         const u32 *table = NULL;
2347
2348         if (nphy->txpwrctrl == 0) {
2349                 int i;
2350
2351                 if (nphy->hang_avoid)
2352                         b43_nphy_stay_in_carrier_search(dev, true);
2353                 b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
2354                 if (nphy->hang_avoid)
2355                         b43_nphy_stay_in_carrier_search(dev, false);
2356
2357                 for (i = 0; i < 2; ++i) {
2358                         if (dev->phy.rev >= 3) {
2359                                 target.ipa[i] = curr_gain[i] & 0x000F;
2360                                 target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
2361                                 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
2362                                 target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
2363                         } else {
2364                                 target.ipa[i] = curr_gain[i] & 0x0003;
2365                                 target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
2366                                 target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
2367                                 target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
2368                         }
2369                 }
2370         } else {
2371                 int i;
2372                 u16 index[2];
2373                 index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
2374                         B43_NPHY_TXPCTL_STAT_BIDX) >>
2375                         B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
2376                 index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
2377                         B43_NPHY_TXPCTL_STAT_BIDX) >>
2378                         B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
2379
2380                 for (i = 0; i < 2; ++i) {
2381                         if (dev->phy.rev >= 3) {
2382                                 enum ieee80211_band band =
2383                                         b43_current_band(dev->wl);
2384
2385                                 if ((nphy->ipa2g_on &&
2386                                      band == IEEE80211_BAND_2GHZ) ||
2387                                     (nphy->ipa5g_on &&
2388                                      band == IEEE80211_BAND_5GHZ)) {
2389                                         table = b43_nphy_get_ipa_gain_table(dev);
2390                                 } else {
2391                                         if (band == IEEE80211_BAND_5GHZ) {
2392                                                 if (dev->phy.rev == 3)
2393                                                         table = b43_ntab_tx_gain_rev3_5ghz;
2394                                                 else if (dev->phy.rev == 4)
2395                                                         table = b43_ntab_tx_gain_rev4_5ghz;
2396                                                 else
2397                                                         table = b43_ntab_tx_gain_rev5plus_5ghz;
2398                                         } else {
2399                                                 table = b43_ntab_tx_gain_rev3plus_2ghz;
2400                                         }
2401                                 }
2402
2403                                 target.ipa[i] = (table[index[i]] >> 16) & 0xF;
2404                                 target.pad[i] = (table[index[i]] >> 20) & 0xF;
2405                                 target.pga[i] = (table[index[i]] >> 24) & 0xF;
2406                                 target.txgm[i] = (table[index[i]] >> 28) & 0xF;
2407                         } else {
2408                                 table = b43_ntab_tx_gain_rev0_1_2;
2409
2410                                 target.ipa[i] = (table[index[i]] >> 16) & 0x3;
2411                                 target.pad[i] = (table[index[i]] >> 18) & 0x3;
2412                                 target.pga[i] = (table[index[i]] >> 20) & 0x7;
2413                                 target.txgm[i] = (table[index[i]] >> 23) & 0x7;
2414                         }
2415                 }
2416         }
2417
2418         return target;
2419 }
2420
2421 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
2422 static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
2423 {
2424         u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
2425
2426         if (dev->phy.rev >= 3) {
2427                 b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
2428                 b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
2429                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
2430                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
2431                 b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
2432                 b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
2433                 b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
2434                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
2435                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
2436                 b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
2437                 b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
2438                 b43_nphy_reset_cca(dev);
2439         } else {
2440                 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
2441                 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
2442                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
2443                 b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
2444                 b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
2445                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
2446                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
2447         }
2448 }
2449
2450 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
2451 static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
2452 {
2453         u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
2454         u16 tmp;
2455
2456         regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
2457         regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
2458         if (dev->phy.rev >= 3) {
2459                 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
2460                 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
2461
2462                 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
2463                 regs[2] = tmp;
2464                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
2465
2466                 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
2467                 regs[3] = tmp;
2468                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
2469
2470                 regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
2471                 b43_phy_mask(dev, B43_NPHY_BBCFG, (u16)~B43_NPHY_BBCFG_RSTRX);
2472
2473                 tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
2474                 regs[5] = tmp;
2475                 b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
2476
2477                 tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
2478                 regs[6] = tmp;
2479                 b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
2480                 regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
2481                 regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
2482
2483                 b43_nphy_rf_control_intc_override(dev, 2, 1, 3);
2484                 b43_nphy_rf_control_intc_override(dev, 1, 2, 1);
2485                 b43_nphy_rf_control_intc_override(dev, 1, 8, 2);
2486
2487                 regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
2488                 regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
2489                 b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
2490                 b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
2491         } else {
2492                 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
2493                 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
2494                 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
2495                 regs[2] = tmp;
2496                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
2497                 tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
2498                 regs[3] = tmp;
2499                 tmp |= 0x2000;
2500                 b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
2501                 tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
2502                 regs[4] = tmp;
2503                 tmp |= 0x2000;
2504                 b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
2505                 regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
2506                 regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
2507                 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
2508                         tmp = 0x0180;
2509                 else
2510                         tmp = 0x0120;
2511                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
2512                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
2513         }
2514 }
2515
2516 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
2517 static void b43_nphy_save_cal(struct b43_wldev *dev)
2518 {
2519         struct b43_phy_n *nphy = dev->phy.n;
2520
2521         struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
2522         u16 *txcal_radio_regs = NULL;
2523         struct b43_chanspec *iqcal_chanspec;
2524         u16 *table = NULL;
2525
2526         if (nphy->hang_avoid)
2527                 b43_nphy_stay_in_carrier_search(dev, 1);
2528
2529         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2530                 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
2531                 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
2532                 iqcal_chanspec = &nphy->iqcal_chanspec_2G;
2533                 table = nphy->cal_cache.txcal_coeffs_2G;
2534         } else {
2535                 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
2536                 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
2537                 iqcal_chanspec = &nphy->iqcal_chanspec_5G;
2538                 table = nphy->cal_cache.txcal_coeffs_5G;
2539         }
2540
2541         b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
2542         /* TODO use some definitions */
2543         if (dev->phy.rev >= 3) {
2544                 txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
2545                 txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
2546                 txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
2547                 txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);
2548                 txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);
2549                 txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);
2550                 txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);
2551                 txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);
2552         } else {
2553                 txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);
2554                 txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);
2555                 txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
2556                 txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
2557         }
2558         *iqcal_chanspec = nphy->radio_chanspec;
2559         b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table);
2560
2561         if (nphy->hang_avoid)
2562                 b43_nphy_stay_in_carrier_search(dev, 0);
2563 }
2564
2565 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
2566 static void b43_nphy_restore_cal(struct b43_wldev *dev)
2567 {
2568         struct b43_phy_n *nphy = dev->phy.n;
2569
2570         u16 coef[4];
2571         u16 *loft = NULL;
2572         u16 *table = NULL;
2573
2574         int i;
2575         u16 *txcal_radio_regs = NULL;
2576         struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
2577
2578         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2579                 if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G))
2580                         return;
2581                 table = nphy->cal_cache.txcal_coeffs_2G;
2582                 loft = &nphy->cal_cache.txcal_coeffs_2G[5];
2583         } else {
2584                 if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G))
2585                         return;
2586                 table = nphy->cal_cache.txcal_coeffs_5G;
2587                 loft = &nphy->cal_cache.txcal_coeffs_5G[5];
2588         }
2589
2590         b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
2591
2592         for (i = 0; i < 4; i++) {
2593                 if (dev->phy.rev >= 3)
2594                         table[i] = coef[i];
2595                 else
2596                         coef[i] = 0;
2597         }
2598
2599         b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
2600         b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
2601         b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
2602
2603         if (dev->phy.rev < 2)
2604                 b43_nphy_tx_iq_workaround(dev);
2605
2606         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2607                 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
2608                 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
2609         } else {
2610                 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
2611                 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
2612         }
2613
2614         /* TODO use some definitions */
2615         if (dev->phy.rev >= 3) {
2616                 b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
2617                 b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
2618                 b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
2619                 b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
2620                 b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
2621                 b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
2622                 b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
2623                 b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
2624         } else {
2625                 b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
2626                 b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
2627                 b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
2628                 b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
2629         }
2630         b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
2631 }
2632
2633 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
2634 static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
2635                                 struct nphy_txgains target,
2636                                 bool full, bool mphase)
2637 {
2638         struct b43_phy_n *nphy = dev->phy.n;
2639         int i;
2640         int error = 0;
2641         int freq;
2642         bool avoid = false;
2643         u8 length;
2644         u16 tmp, core, type, count, max, numb, last, cmd;
2645         const u16 *table;
2646         bool phy6or5x;
2647
2648         u16 buffer[11];
2649         u16 diq_start = 0;
2650         u16 save[2];
2651         u16 gain[2];
2652         struct nphy_iqcal_params params[2];
2653         bool updated[2] = { };
2654
2655         b43_nphy_stay_in_carrier_search(dev, true);
2656
2657         if (dev->phy.rev >= 4) {
2658                 avoid = nphy->hang_avoid;
2659                 nphy->hang_avoid = 0;
2660         }
2661
2662         b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
2663
2664         for (i = 0; i < 2; i++) {
2665                 b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
2666                 gain[i] = params[i].cal_gain;
2667         }
2668
2669         b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
2670
2671         b43_nphy_tx_cal_radio_setup(dev);
2672         b43_nphy_tx_cal_phy_setup(dev);
2673
2674         phy6or5x = dev->phy.rev >= 6 ||
2675                 (dev->phy.rev == 5 && nphy->ipa2g_on &&
2676                 b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
2677         if (phy6or5x) {
2678                 if (dev->phy.is_40mhz) {
2679                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
2680                                         tbl_tx_iqlo_cal_loft_ladder_40);
2681                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
2682                                         tbl_tx_iqlo_cal_iqimb_ladder_40);
2683                 } else {
2684                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
2685                                         tbl_tx_iqlo_cal_loft_ladder_20);
2686                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
2687                                         tbl_tx_iqlo_cal_iqimb_ladder_20);
2688                 }
2689         }
2690
2691         b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
2692
2693         if (!dev->phy.is_40mhz)
2694                 freq = 2500;
2695         else
2696                 freq = 5000;
2697
2698         if (nphy->mphase_cal_phase_id > 2)
2699                 b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8,
2700                                         0xFFFF, 0, true, false);
2701         else
2702                 error = b43_nphy_tx_tone(dev, freq, 250, true, false);
2703
2704         if (error == 0) {
2705                 if (nphy->mphase_cal_phase_id > 2) {
2706                         table = nphy->mphase_txcal_bestcoeffs;
2707                         length = 11;
2708                         if (dev->phy.rev < 3)
2709                                 length -= 2;
2710                 } else {
2711                         if (!full && nphy->txiqlocal_coeffsvalid) {
2712                                 table = nphy->txiqlocal_bestc;
2713                                 length = 11;
2714                                 if (dev->phy.rev < 3)
2715                                         length -= 2;
2716                         } else {
2717                                 full = true;
2718                                 if (dev->phy.rev >= 3) {
2719                                         table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
2720                                         length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
2721                                 } else {
2722                                         table = tbl_tx_iqlo_cal_startcoefs;
2723                                         length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;
2724                                 }
2725                         }
2726                 }
2727
2728                 b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
2729
2730                 if (full) {
2731                         if (dev->phy.rev >= 3)
2732                                 max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
2733                         else
2734                                 max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
2735                 } else {
2736                         if (dev->phy.rev >= 3)
2737                                 max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
2738                         else
2739                                 max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;
2740                 }
2741
2742                 if (mphase) {
2743                         count = nphy->mphase_txcal_cmdidx;
2744                         numb = min(max,
2745                                 (u16)(count + nphy->mphase_txcal_numcmds));
2746                 } else {
2747                         count = 0;
2748                         numb = max;
2749                 }
2750
2751                 for (; count < numb; count++) {
2752                         if (full) {
2753                                 if (dev->phy.rev >= 3)
2754                                         cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
2755                                 else
2756                                         cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
2757                         } else {
2758                                 if (dev->phy.rev >= 3)
2759                                         cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
2760                                 else
2761                                         cmd = tbl_tx_iqlo_cal_cmds_recal[count];
2762                         }
2763
2764                         core = (cmd & 0x3000) >> 12;
2765                         type = (cmd & 0x0F00) >> 8;
2766
2767                         if (phy6or5x && updated[core] == 0) {
2768                                 b43_nphy_update_tx_cal_ladder(dev, core);
2769                                 updated[core] = 1;
2770                         }
2771
2772                         tmp = (params[core].ncorr[type] << 8) | 0x66;
2773                         b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
2774
2775                         if (type == 1 || type == 3 || type == 4) {
2776                                 buffer[0] = b43_ntab_read(dev,
2777                                                 B43_NTAB16(15, 69 + core));
2778                                 diq_start = buffer[0];
2779                                 buffer[0] = 0;
2780                                 b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
2781                                                 0);
2782                         }
2783
2784                         b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
2785                         for (i = 0; i < 2000; i++) {
2786                                 tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
2787                                 if (tmp & 0xC000)
2788                                         break;
2789                                 udelay(10);
2790                         }
2791
2792                         b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
2793                                                 buffer);
2794                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
2795                                                 buffer);
2796
2797                         if (type == 1 || type == 3 || type == 4)
2798                                 buffer[0] = diq_start;
2799                 }
2800
2801                 if (mphase)
2802                         nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
2803
2804                 last = (dev->phy.rev < 3) ? 6 : 7;
2805
2806                 if (!mphase || nphy->mphase_cal_phase_id == last) {
2807                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
2808                         b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
2809                         if (dev->phy.rev < 3) {
2810                                 buffer[0] = 0;
2811                                 buffer[1] = 0;
2812                                 buffer[2] = 0;
2813                                 buffer[3] = 0;
2814                         }
2815                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
2816                                                 buffer);
2817                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2,
2818                                                 buffer);
2819                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
2820                                                 buffer);
2821                         b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
2822                                                 buffer);
2823                         length = 11;
2824                         if (dev->phy.rev < 3)
2825                                 length -= 2;
2826                         b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
2827                                                 nphy->txiqlocal_bestc);
2828                         nphy->txiqlocal_coeffsvalid = true;
2829                         nphy->txiqlocal_chanspec = nphy->radio_chanspec;
2830                 } else {
2831                         length = 11;
2832                         if (dev->phy.rev < 3)
2833                                 length -= 2;
2834                         b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
2835                                                 nphy->mphase_txcal_bestcoeffs);
2836                 }
2837
2838                 b43_nphy_stop_playback(dev);
2839                 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
2840         }
2841
2842         b43_nphy_tx_cal_phy_cleanup(dev);
2843         b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
2844
2845         if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
2846                 b43_nphy_tx_iq_workaround(dev);
2847
2848         if (dev->phy.rev >= 4)
2849                 nphy->hang_avoid = avoid;
2850
2851         b43_nphy_stay_in_carrier_search(dev, false);
2852
2853         return error;
2854 }
2855
2856 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
2857 static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
2858 {
2859         struct b43_phy_n *nphy = dev->phy.n;
2860         u8 i;
2861         u16 buffer[7];
2862         bool equal = true;
2863
2864         if (!nphy->txiqlocal_coeffsvalid ||
2865             b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec))
2866                 return;
2867
2868         b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
2869         for (i = 0; i < 4; i++) {
2870                 if (buffer[i] != nphy->txiqlocal_bestc[i]) {
2871                         equal = false;
2872                         break;
2873                 }
2874         }
2875
2876         if (!equal) {
2877                 b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,
2878                                         nphy->txiqlocal_bestc);
2879                 for (i = 0; i < 4; i++)
2880                         buffer[i] = 0;
2881                 b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
2882                                         buffer);
2883                 b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
2884                                         &nphy->txiqlocal_bestc[5]);
2885                 b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
2886                                         &nphy->txiqlocal_bestc[5]);
2887         }
2888 }
2889
2890 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
2891 static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
2892                         struct nphy_txgains target, u8 type, bool debug)
2893 {
2894         struct b43_phy_n *nphy = dev->phy.n;
2895         int i, j, index;
2896         u8 rfctl[2];
2897         u8 afectl_core;
2898         u16 tmp[6];
2899         u16 cur_hpf1, cur_hpf2, cur_lna;
2900         u32 real, imag;
2901         enum ieee80211_band band;
2902
2903         u8 use;
2904         u16 cur_hpf;
2905         u16 lna[3] = { 3, 3, 1 };
2906         u16 hpf1[3] = { 7, 2, 0 };
2907         u16 hpf2[3] = { 2, 0, 0 };
2908         u32 power[3] = { };
2909         u16 gain_save[2];
2910         u16 cal_gain[2];
2911         struct nphy_iqcal_params cal_params[2];
2912         struct nphy_iq_est est;
2913         int ret = 0;
2914         bool playtone = true;
2915         int desired = 13;
2916
2917         b43_nphy_stay_in_carrier_search(dev, 1);
2918
2919         if (dev->phy.rev < 2)
2920                 b43_nphy_reapply_tx_cal_coeffs(dev);
2921         b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
2922         for (i = 0; i < 2; i++) {
2923                 b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
2924                 cal_gain[i] = cal_params[i].cal_gain;
2925         }
2926         b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
2927
2928         for (i = 0; i < 2; i++) {
2929                 if (i == 0) {
2930                         rfctl[0] = B43_NPHY_RFCTL_INTC1;
2931                         rfctl[1] = B43_NPHY_RFCTL_INTC2;
2932                         afectl_core = B43_NPHY_AFECTL_C1;
2933                 } else {
2934                         rfctl[0] = B43_NPHY_RFCTL_INTC2;
2935                         rfctl[1] = B43_NPHY_RFCTL_INTC1;
2936                         afectl_core = B43_NPHY_AFECTL_C2;
2937                 }
2938
2939                 tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
2940                 tmp[2] = b43_phy_read(dev, afectl_core);
2941                 tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
2942                 tmp[4] = b43_phy_read(dev, rfctl[0]);
2943                 tmp[5] = b43_phy_read(dev, rfctl[1]);
2944
2945                 b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
2946                                 (u16)~B43_NPHY_RFSEQCA_RXDIS,
2947                                 ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
2948                 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
2949                                 (1 - i));
2950                 b43_phy_set(dev, afectl_core, 0x0006);
2951                 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
2952
2953                 band = b43_current_band(dev->wl);
2954
2955                 if (nphy->rxcalparams & 0xFF000000) {
2956                         if (band == IEEE80211_BAND_5GHZ)
2957                                 b43_phy_write(dev, rfctl[0], 0x140);
2958                         else
2959                                 b43_phy_write(dev, rfctl[0], 0x110);
2960                 } else {
2961                         if (band == IEEE80211_BAND_5GHZ)
2962                                 b43_phy_write(dev, rfctl[0], 0x180);
2963                         else
2964                                 b43_phy_write(dev, rfctl[0], 0x120);
2965                 }
2966
2967                 if (band == IEEE80211_BAND_5GHZ)
2968                         b43_phy_write(dev, rfctl[1], 0x148);
2969                 else
2970                         b43_phy_write(dev, rfctl[1], 0x114);
2971
2972                 if (nphy->rxcalparams & 0x10000) {
2973                         b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
2974                                         (i + 1));
2975                         b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
2976                                         (2 - i));
2977                 }
2978
2979                 for (j = 0; i < 4; j++) {
2980                         if (j < 3) {
2981                                 cur_lna = lna[j];
2982                                 cur_hpf1 = hpf1[j];
2983                                 cur_hpf2 = hpf2[j];
2984                         } else {
2985                                 if (power[1] > 10000) {
2986                                         use = 1;
2987                                         cur_hpf = cur_hpf1;
2988                                         index = 2;
2989                                 } else {
2990                                         if (power[0] > 10000) {
2991                                                 use = 1;
2992                                                 cur_hpf = cur_hpf1;
2993                                                 index = 1;
2994                                         } else {
2995                                                 index = 0;
2996                                                 use = 2;
2997                                                 cur_hpf = cur_hpf2;
2998                                         }
2999                                 }
3000                                 cur_lna = lna[index];
3001                                 cur_hpf1 = hpf1[index];
3002                                 cur_hpf2 = hpf2[index];
3003                                 cur_hpf += desired - hweight32(power[index]);
3004                                 cur_hpf = clamp_val(cur_hpf, 0, 10);
3005                                 if (use == 1)
3006                                         cur_hpf1 = cur_hpf;
3007                                 else
3008                                         cur_hpf2 = cur_hpf;
3009                         }
3010
3011                         tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
3012                                         (cur_lna << 2));
3013                         b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
3014                                                                         false);
3015                         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3016                         b43_nphy_stop_playback(dev);
3017
3018                         if (playtone) {
3019                                 ret = b43_nphy_tx_tone(dev, 4000,
3020                                                 (nphy->rxcalparams & 0xFFFF),
3021                                                 false, false);
3022                                 playtone = false;
3023                         } else {
3024                                 b43_nphy_run_samples(dev, 160, 0xFFFF, 0,
3025                                                         false, false);
3026                         }
3027
3028                         if (ret == 0) {
3029                                 if (j < 3) {
3030                                         b43_nphy_rx_iq_est(dev, &est, 1024, 32,
3031                                                                         false);
3032                                         if (i == 0) {
3033                                                 real = est.i0_pwr;
3034                                                 imag = est.q0_pwr;
3035                                         } else {
3036                                                 real = est.i1_pwr;
3037                                                 imag = est.q1_pwr;
3038                                         }
3039                                         power[i] = ((real + imag) / 1024) + 1;
3040                                 } else {
3041                                         b43_nphy_calc_rx_iq_comp(dev, 1 << i);
3042                                 }
3043                                 b43_nphy_stop_playback(dev);
3044                         }
3045
3046                         if (ret != 0)
3047                                 break;
3048                 }
3049
3050                 b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
3051                 b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
3052                 b43_phy_write(dev, rfctl[1], tmp[5]);
3053                 b43_phy_write(dev, rfctl[0], tmp[4]);
3054                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
3055                 b43_phy_write(dev, afectl_core, tmp[2]);
3056                 b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
3057
3058                 if (ret != 0)
3059                         break;
3060         }
3061
3062         b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
3063         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3064         b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
3065
3066         b43_nphy_stay_in_carrier_search(dev, 0);
3067
3068         return ret;
3069 }
3070
3071 static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
3072                         struct nphy_txgains target, u8 type, bool debug)
3073 {
3074         return -1;
3075 }
3076
3077 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
3078 static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
3079                         struct nphy_txgains target, u8 type, bool debug)
3080 {
3081         if (dev->phy.rev >= 3)
3082                 return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
3083         else
3084                 return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
3085 }
3086
3087 /*
3088  * Init N-PHY
3089  * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
3090  */
3091 int b43_phy_initn(struct b43_wldev *dev)
3092 {
3093         struct ssb_bus *bus = dev->dev->bus;
3094         struct b43_phy *phy = &dev->phy;
3095         struct b43_phy_n *nphy = phy->n;
3096         u8 tx_pwr_state;
3097         struct nphy_txgains target;
3098         u16 tmp;
3099         enum ieee80211_band tmp2;
3100         bool do_rssi_cal;
3101
3102         u16 clip[2];
3103         bool do_cal = false;
3104
3105         if ((dev->phy.rev >= 3) &&
3106            (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
3107            (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
3108                 chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
3109         }
3110         nphy->deaf_count = 0;
3111         b43_nphy_tables_init(dev);
3112         nphy->crsminpwr_adjusted = false;
3113         nphy->noisevars_adjusted = false;
3114
3115         /* Clear all overrides */
3116         if (dev->phy.rev >= 3) {
3117                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
3118                 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
3119                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
3120                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
3121         } else {
3122                 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
3123         }
3124         b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
3125         b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
3126         if (dev->phy.rev < 6) {
3127                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
3128                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
3129         }
3130         b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
3131                      ~(B43_NPHY_RFSEQMODE_CAOVER |
3132                        B43_NPHY_RFSEQMODE_TROVER));
3133         if (dev->phy.rev >= 3)
3134                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
3135         b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
3136
3137         if (dev->phy.rev <= 2) {
3138                 tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
3139                 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
3140                                 ~B43_NPHY_BPHY_CTL3_SCALE,
3141                                 tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
3142         }
3143         b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
3144         b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
3145
3146         if (bus->sprom.boardflags2_lo & 0x100 ||
3147             (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
3148              bus->boardinfo.type == 0x8B))
3149                 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
3150         else
3151                 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
3152         b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
3153         b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
3154         b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
3155
3156         b43_nphy_update_mimo_config(dev, nphy->preamble_override);
3157         b43_nphy_update_txrx_chain(dev);
3158
3159         if (phy->rev < 2) {
3160                 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
3161                 b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
3162         }
3163
3164         tmp2 = b43_current_band(dev->wl);
3165         if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
3166             (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
3167                 b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
3168                 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
3169                                 nphy->papd_epsilon_offset[0] << 7);
3170                 b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
3171                 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
3172                                 nphy->papd_epsilon_offset[1] << 7);
3173                 b43_nphy_int_pa_set_tx_dig_filters(dev);
3174         } else if (phy->rev >= 5) {
3175                 b43_nphy_ext_pa_set_tx_dig_filters(dev);
3176         }
3177
3178         b43_nphy_workarounds(dev);
3179
3180         /* Reset CCA, in init code it differs a little from standard way */
3181         b43_nphy_bmac_clock_fgc(dev, 1);
3182         tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
3183         b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
3184         b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
3185         b43_nphy_bmac_clock_fgc(dev, 0);
3186
3187         /* TODO N PHY MAC PHY Clock Set with argument 1 */
3188
3189         b43_nphy_pa_override(dev, false);
3190         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
3191         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3192         b43_nphy_pa_override(dev, true);
3193
3194         b43_nphy_classifier(dev, 0, 0);
3195         b43_nphy_read_clip_detection(dev, clip);
3196         tx_pwr_state = nphy->txpwrctrl;
3197         /* TODO N PHY TX power control with argument 0
3198                 (turning off power control) */
3199         /* TODO Fix the TX Power Settings */
3200         /* TODO N PHY TX Power Control Idle TSSI */
3201         /* TODO N PHY TX Power Control Setup */
3202
3203         if (phy->rev >= 3) {
3204                 /* TODO */
3205         } else {
3206                 b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128,
3207                                         b43_ntab_tx_gain_rev0_1_2);
3208                 b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128,
3209                                         b43_ntab_tx_gain_rev0_1_2);
3210         }
3211
3212         if (nphy->phyrxchain != 3)
3213                 ;/* TODO N PHY RX Core Set State with phyrxchain as argument */
3214         if (nphy->mphase_cal_phase_id > 0)
3215                 ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
3216
3217         do_rssi_cal = false;
3218         if (phy->rev >= 3) {
3219                 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3220                         do_rssi_cal =
3221                                 b43_empty_chanspec(&nphy->rssical_chanspec_2G);
3222                 else
3223                         do_rssi_cal =
3224                                 b43_empty_chanspec(&nphy->rssical_chanspec_5G);
3225
3226                 if (do_rssi_cal)
3227                         b43_nphy_rssi_cal(dev);
3228                 else
3229                         b43_nphy_restore_rssi_cal(dev);
3230         } else {
3231                 b43_nphy_rssi_cal(dev);
3232         }
3233
3234         if (!((nphy->measure_hold & 0x6) != 0)) {
3235                 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3236                         do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G);
3237                 else
3238                         do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G);
3239
3240                 if (nphy->mute)
3241                         do_cal = false;
3242
3243                 if (do_cal) {
3244                         target = b43_nphy_get_tx_gains(dev);
3245
3246                         if (nphy->antsel_type == 2)
3247                                 b43_nphy_superswitch_init(dev, true);
3248                         if (nphy->perical != 2) {
3249                                 b43_nphy_rssi_cal(dev);
3250                                 if (phy->rev >= 3) {
3251                                         nphy->cal_orig_pwr_idx[0] =
3252                                             nphy->txpwrindex[0].index_internal;
3253                                         nphy->cal_orig_pwr_idx[1] =
3254                                             nphy->txpwrindex[1].index_internal;
3255                                         /* TODO N PHY Pre Calibrate TX Gain */
3256                                         target = b43_nphy_get_tx_gains(dev);
3257                                 }
3258                         }
3259                 }
3260         }
3261
3262         if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) {
3263                 if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
3264                         b43_nphy_save_cal(dev);
3265                 else if (nphy->mphase_cal_phase_id == 0)
3266                         ;/* N PHY Periodic Calibration with argument 3 */
3267         } else {
3268                 b43_nphy_restore_cal(dev);
3269         }
3270
3271         b43_nphy_tx_pwr_ctrl_coef_setup(dev);
3272         /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */
3273         b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
3274         b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
3275         if (phy->rev >= 3 && phy->rev <= 6)
3276                 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014);
3277         b43_nphy_tx_lp_fbw(dev);
3278         if (phy->rev >= 3)
3279                 b43_nphy_spur_workaround(dev);
3280
3281         b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
3282         return 0;
3283 }
3284
3285 static int b43_nphy_op_allocate(struct b43_wldev *dev)
3286 {
3287         struct b43_phy_n *nphy;
3288
3289         nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
3290         if (!nphy)
3291                 return -ENOMEM;
3292         dev->phy.n = nphy;
3293
3294         return 0;
3295 }
3296
3297 static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
3298 {
3299         struct b43_phy *phy = &dev->phy;
3300         struct b43_phy_n *nphy = phy->n;
3301
3302         memset(nphy, 0, sizeof(*nphy));
3303
3304         //TODO init struct b43_phy_n
3305 }
3306
3307 static void b43_nphy_op_free(struct b43_wldev *dev)
3308 {
3309         struct b43_phy *phy = &dev->phy;
3310         struct b43_phy_n *nphy = phy->n;
3311
3312         kfree(nphy);
3313         phy->n = NULL;
3314 }
3315
3316 static int b43_nphy_op_init(struct b43_wldev *dev)
3317 {
3318         return b43_phy_initn(dev);
3319 }
3320
3321 static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
3322 {
3323 #if B43_DEBUG
3324         if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
3325                 /* OFDM registers are onnly available on A/G-PHYs */
3326                 b43err(dev->wl, "Invalid OFDM PHY access at "
3327                        "0x%04X on N-PHY\n", offset);
3328                 dump_stack();
3329         }
3330         if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
3331                 /* Ext-G registers are only available on G-PHYs */
3332                 b43err(dev->wl, "Invalid EXT-G PHY access at "
3333                        "0x%04X on N-PHY\n", offset);
3334                 dump_stack();
3335         }
3336 #endif /* B43_DEBUG */
3337 }
3338
3339 static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
3340 {
3341         check_phyreg(dev, reg);
3342         b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
3343         return b43_read16(dev, B43_MMIO_PHY_DATA);
3344 }
3345
3346 static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
3347 {
3348         check_phyreg(dev, reg);
3349         b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
3350         b43_write16(dev, B43_MMIO_PHY_DATA, value);
3351 }
3352
3353 static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
3354 {
3355         /* Register 1 is a 32-bit register. */
3356         B43_WARN_ON(reg == 1);
3357         /* N-PHY needs 0x100 for read access */
3358         reg |= 0x100;
3359
3360         b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
3361         return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
3362 }
3363
3364 static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
3365 {
3366         /* Register 1 is a 32-bit register. */
3367         B43_WARN_ON(reg == 1);
3368
3369         b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
3370         b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
3371 }
3372
3373 /* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
3374 static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
3375                                         bool blocked)
3376 {
3377         if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
3378                 b43err(dev->wl, "MAC not suspended\n");
3379
3380         if (blocked) {
3381                 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
3382                                 ~B43_NPHY_RFCTL_CMD_CHIP0PU);
3383                 if (dev->phy.rev >= 3) {
3384                         b43_radio_mask(dev, 0x09, ~0x2);
3385
3386                         b43_radio_write(dev, 0x204D, 0);
3387                         b43_radio_write(dev, 0x2053, 0);
3388                         b43_radio_write(dev, 0x2058, 0);
3389                         b43_radio_write(dev, 0x205E, 0);
3390                         b43_radio_mask(dev, 0x2062, ~0xF0);
3391                         b43_radio_write(dev, 0x2064, 0);
3392
3393                         b43_radio_write(dev, 0x304D, 0);
3394                         b43_radio_write(dev, 0x3053, 0);
3395                         b43_radio_write(dev, 0x3058, 0);
3396                         b43_radio_write(dev, 0x305E, 0);
3397                         b43_radio_mask(dev, 0x3062, ~0xF0);
3398                         b43_radio_write(dev, 0x3064, 0);
3399                 }
3400         } else {
3401                 if (dev->phy.rev >= 3) {
3402                         /* TODO: b43_radio_init2056(dev); */
3403                         /* TODO: PHY Set Channel Spec (dev, radio_chanspec) */
3404                 } else {
3405                         b43_radio_init2055(dev);
3406                 }
3407         }
3408 }
3409
3410 static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
3411 {
3412         b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
3413                       on ? 0 : 0x7FFF);
3414 }
3415
3416 static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
3417                                       unsigned int new_channel)
3418 {
3419         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3420                 if ((new_channel < 1) || (new_channel > 14))
3421                         return -EINVAL;
3422         } else {
3423                 if (new_channel > 200)
3424                         return -EINVAL;
3425         }
3426
3427         return nphy_channel_switch(dev, new_channel);
3428 }
3429
3430 static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
3431 {
3432         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3433                 return 1;
3434         return 36;
3435 }
3436
3437 const struct b43_phy_operations b43_phyops_n = {
3438         .allocate               = b43_nphy_op_allocate,
3439         .free                   = b43_nphy_op_free,
3440         .prepare_structs        = b43_nphy_op_prepare_structs,
3441         .init                   = b43_nphy_op_init,
3442         .phy_read               = b43_nphy_op_read,
3443         .phy_write              = b43_nphy_op_write,
3444         .radio_read             = b43_nphy_op_radio_read,
3445         .radio_write            = b43_nphy_op_radio_write,
3446         .software_rfkill        = b43_nphy_op_software_rfkill,
3447         .switch_analog          = b43_nphy_op_switch_analog,
3448         .switch_channel         = b43_nphy_op_switch_channel,
3449         .get_default_chan       = b43_nphy_op_get_default_chan,
3450         .recalc_txpower         = b43_nphy_op_recalc_txpower,
3451         .adjust_txpower         = b43_nphy_op_adjust_txpower,
3452 };