]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/net/wireless/b43/phy_n.c
a0e84c428e79a7951d6b859259372ed977026f8d
[mv-sheeva.git] / 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 void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
59 {//TODO
60 }
61
62 static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
63 {//TODO
64 }
65
66 static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
67                                                         bool ignore_tssi)
68 {//TODO
69         return B43_TXPWR_RES_DONE;
70 }
71
72 static void b43_chantab_radio_upload(struct b43_wldev *dev,
73                                      const struct b43_nphy_channeltab_entry *e)
74 {
75         b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref);
76         b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
77         b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
78         b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
79         b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
80         b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
81         b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
82         b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
83         b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
84         b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
85         b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
86         b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
87         b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
88         b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
89         b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
90         b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
91         b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
92         b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
93         b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
94         b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
95         b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
96         b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
97 }
98
99 static void b43_chantab_phy_upload(struct b43_wldev *dev,
100                                    const struct b43_nphy_channeltab_entry *e)
101 {
102         b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
103         b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
104         b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
105         b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
106         b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
107         b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
108 }
109
110 static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
111 {
112         //TODO
113 }
114
115 /* Tune the hardware to a new channel. */
116 static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
117 {
118         const struct b43_nphy_channeltab_entry *tabent;
119
120         tabent = b43_nphy_get_chantabent(dev, channel);
121         if (!tabent)
122                 return -ESRCH;
123
124         //FIXME enable/disable band select upper20 in RXCTL
125         if (0 /*FIXME 5Ghz*/)
126                 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20);
127         else
128                 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50);
129         b43_chantab_radio_upload(dev, tabent);
130         udelay(50);
131         b43_radio_write16(dev, B2055_VCO_CAL10, 5);
132         b43_radio_write16(dev, B2055_VCO_CAL10, 45);
133         b43_radio_write16(dev, B2055_VCO_CAL10, 65);
134         udelay(300);
135         if (0 /*FIXME 5Ghz*/)
136                 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
137         else
138                 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
139         b43_chantab_phy_upload(dev, tabent);
140         b43_nphy_tx_power_fix(dev);
141
142         return 0;
143 }
144
145 static void b43_radio_init2055_pre(struct b43_wldev *dev)
146 {
147         b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
148                      ~B43_NPHY_RFCTL_CMD_PORFORCE);
149         b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
150                     B43_NPHY_RFCTL_CMD_CHIP0PU |
151                     B43_NPHY_RFCTL_CMD_OEPORFORCE);
152         b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
153                     B43_NPHY_RFCTL_CMD_PORFORCE);
154 }
155
156 static void b43_radio_init2055_post(struct b43_wldev *dev)
157 {
158         struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
159         struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo);
160         int i;
161         u16 val;
162
163         b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
164         msleep(1);
165         if ((sprom->revision != 4) ||
166            !(sprom->boardflags_hi & B43_BFH_RSSIINV)) {
167                 if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) ||
168                     (binfo->type != 0x46D) ||
169                     (binfo->rev < 0x41)) {
170                         b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
171                         b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
172                         msleep(1);
173                 }
174         }
175         b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C);
176         msleep(1);
177         b43_radio_write16(dev, B2055_CAL_MISC, 0x3C);
178         msleep(1);
179         b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
180         msleep(1);
181         b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
182         msleep(1);
183         b43_radio_set(dev, B2055_CAL_MISC, 0x1);
184         msleep(1);
185         b43_radio_set(dev, B2055_CAL_MISC, 0x40);
186         msleep(1);
187         for (i = 0; i < 100; i++) {
188                 val = b43_radio_read16(dev, B2055_CAL_COUT2);
189                 if (val & 0x80)
190                         break;
191                 udelay(10);
192         }
193         msleep(1);
194         b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
195         msleep(1);
196         nphy_channel_switch(dev, dev->phy.channel);
197         b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9);
198         b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9);
199         b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
200         b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
201 }
202
203 /* Initialize a Broadcom 2055 N-radio */
204 static void b43_radio_init2055(struct b43_wldev *dev)
205 {
206         b43_radio_init2055_pre(dev);
207         if (b43_status(dev) < B43_STAT_INITIALIZED)
208                 b2055_upload_inittab(dev, 0, 1);
209         else
210                 b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0);
211         b43_radio_init2055_post(dev);
212 }
213
214 void b43_nphy_radio_turn_on(struct b43_wldev *dev)
215 {
216         b43_radio_init2055(dev);
217 }
218
219 void b43_nphy_radio_turn_off(struct b43_wldev *dev)
220 {
221         b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
222                      ~B43_NPHY_RFCTL_CMD_EN);
223 }
224
225 #define ntab_upload(dev, offset, data) do { \
226                 unsigned int i;                                         \
227                 for (i = 0; i < (offset##_SIZE); i++)                   \
228                         b43_ntab_write(dev, (offset) + i, (data)[i]);   \
229         } while (0)
230
231 /*
232  * Upload the N-PHY tables.
233  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
234  */
235 static void b43_nphy_tables_init(struct b43_wldev *dev)
236 {
237         if (dev->phy.rev < 3)
238                 b43_nphy_rev0_1_2_tables_init(dev);
239         else
240                 b43_nphy_rev3plus_tables_init(dev);
241 }
242
243 static void b43_nphy_workarounds(struct b43_wldev *dev)
244 {
245         struct b43_phy *phy = &dev->phy;
246         unsigned int i;
247
248         b43_phy_set(dev, B43_NPHY_IQFLIP,
249                     B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
250         if (1 /* FIXME band is 2.4GHz */) {
251                 b43_phy_set(dev, B43_NPHY_CLASSCTL,
252                             B43_NPHY_CLASSCTL_CCKEN);
253         } else {
254                 b43_phy_mask(dev, B43_NPHY_CLASSCTL,
255                              ~B43_NPHY_CLASSCTL_CCKEN);
256         }
257         b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
258         b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8);
259
260         /* Fixup some tables */
261         b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA);
262         b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA);
263         b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
264         b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
265         b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0);
266         b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0);
267         b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
268         b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
269         b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800);
270         b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800);
271
272         b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
273         b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
274         b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
275         b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
276
277         //TODO set RF sequence
278
279         /* Set narrowband clip threshold */
280         b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66);
281         b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66);
282
283         /* Set wideband clip 2 threshold */
284         b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
285                         ~B43_NPHY_C1_CLIPWBTHRES_CLIP2,
286                         21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT);
287         b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
288                         ~B43_NPHY_C2_CLIPWBTHRES_CLIP2,
289                         21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT);
290
291         /* Set Clip 2 detect */
292         b43_phy_set(dev, B43_NPHY_C1_CGAINI,
293                     B43_NPHY_C1_CGAINI_CL2DETECT);
294         b43_phy_set(dev, B43_NPHY_C2_CGAINI,
295                     B43_NPHY_C2_CGAINI_CL2DETECT);
296
297         if (0 /*FIXME*/) {
298                 /* Set dwell lengths */
299                 b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43);
300                 b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43);
301                 b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9);
302                 b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9);
303
304                 /* Set gain backoff */
305                 b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
306                                 ~B43_NPHY_C1_CGAINI_GAINBKOFF,
307                                 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT);
308                 b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
309                                 ~B43_NPHY_C2_CGAINI_GAINBKOFF,
310                                 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT);
311
312                 /* Set HPVGA2 index */
313                 b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN,
314                                 ~B43_NPHY_C1_INITGAIN_HPVGA2,
315                                 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
316                 b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN,
317                                 ~B43_NPHY_C2_INITGAIN_HPVGA2,
318                                 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
319
320                 //FIXME verify that the specs really mean to use autoinc here.
321                 for (i = 0; i < 3; i++)
322                         b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673);
323         }
324
325         /* Set minimum gain value */
326         b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN,
327                         ~B43_NPHY_C1_MINGAIN,
328                         23 << B43_NPHY_C1_MINGAIN_SHIFT);
329         b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN,
330                         ~B43_NPHY_C2_MINGAIN,
331                         23 << B43_NPHY_C2_MINGAIN_SHIFT);
332
333         if (phy->rev < 2) {
334                 b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
335                              ~B43_NPHY_SCRAM_SIGCTL_SCM);
336         }
337
338         /* Set phase track alpha and beta */
339         b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
340         b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
341         b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
342         b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
343         b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
344         b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
345 }
346
347 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
348 static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
349 {
350         u32 tmslow;
351
352         if (dev->phy.type != B43_PHYTYPE_N)
353                 return;
354
355         tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
356         if (force)
357                 tmslow |= SSB_TMSLOW_FGC;
358         else
359                 tmslow &= ~SSB_TMSLOW_FGC;
360         ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
361 }
362
363 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
364 static void b43_nphy_reset_cca(struct b43_wldev *dev)
365 {
366         u16 bbcfg;
367
368         b43_nphy_bmac_clock_fgc(dev, 1);
369         bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
370         b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
371         udelay(1);
372         b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
373         b43_nphy_bmac_clock_fgc(dev, 0);
374         /* TODO: N PHY Force RF Seq with argument 2 */
375 }
376
377 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
378 static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st)
379 {
380         b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
381         b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
382 }
383
384 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
385 static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
386 {
387         clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
388         clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
389 }
390
391 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
392 static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
393 {
394         u16 tmp;
395
396         if (dev->dev->id.revision == 16)
397                 b43_mac_suspend(dev);
398
399         tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
400         tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
401                 B43_NPHY_CLASSCTL_WAITEDEN);
402         tmp &= ~mask;
403         tmp |= (val & mask);
404         b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
405
406         if (dev->dev->id.revision == 16)
407                 b43_mac_enable(dev);
408
409         return tmp;
410 }
411
412 enum b43_nphy_rf_sequence {
413         B43_RFSEQ_RX2TX,
414         B43_RFSEQ_TX2RX,
415         B43_RFSEQ_RESET2RX,
416         B43_RFSEQ_UPDATE_GAINH,
417         B43_RFSEQ_UPDATE_GAINL,
418         B43_RFSEQ_UPDATE_GAINU,
419 };
420
421 static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
422                                        enum b43_nphy_rf_sequence seq)
423 {
424         static const u16 trigger[] = {
425                 [B43_RFSEQ_RX2TX]               = B43_NPHY_RFSEQTR_RX2TX,
426                 [B43_RFSEQ_TX2RX]               = B43_NPHY_RFSEQTR_TX2RX,
427                 [B43_RFSEQ_RESET2RX]            = B43_NPHY_RFSEQTR_RST2RX,
428                 [B43_RFSEQ_UPDATE_GAINH]        = B43_NPHY_RFSEQTR_UPGH,
429                 [B43_RFSEQ_UPDATE_GAINL]        = B43_NPHY_RFSEQTR_UPGL,
430                 [B43_RFSEQ_UPDATE_GAINU]        = B43_NPHY_RFSEQTR_UPGU,
431         };
432         int i;
433
434         B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
435
436         b43_phy_set(dev, B43_NPHY_RFSEQMODE,
437                     B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
438         b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
439         for (i = 0; i < 200; i++) {
440                 if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
441                         goto ok;
442                 msleep(1);
443         }
444         b43err(dev->wl, "RF sequence status timeout\n");
445 ok:
446         b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
447                      ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER));
448 }
449
450 static void b43_nphy_bphy_init(struct b43_wldev *dev)
451 {
452         unsigned int i;
453         u16 val;
454
455         val = 0x1E1F;
456         for (i = 0; i < 14; i++) {
457                 b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
458                 val -= 0x202;
459         }
460         val = 0x3E3F;
461         for (i = 0; i < 16; i++) {
462                 b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val);
463                 val -= 0x202;
464         }
465         b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
466 }
467
468 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
469 static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
470                                        s8 offset, u8 core, u8 rail, u8 type)
471 {
472         u16 tmp;
473         bool core1or5 = (core == 1) || (core == 5);
474         bool core2or5 = (core == 2) || (core == 5);
475
476         offset = clamp_val(offset, -32, 31);
477         tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
478
479         if (core1or5 && (rail == 0) && (type == 2))
480                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
481         if (core1or5 && (rail == 1) && (type == 2))
482                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
483         if (core2or5 && (rail == 0) && (type == 2))
484                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
485         if (core2or5 && (rail == 1) && (type == 2))
486                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
487         if (core1or5 && (rail == 0) && (type == 0))
488                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
489         if (core1or5 && (rail == 1) && (type == 0))
490                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
491         if (core2or5 && (rail == 0) && (type == 0))
492                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
493         if (core2or5 && (rail == 1) && (type == 0))
494                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
495         if (core1or5 && (rail == 0) && (type == 1))
496                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
497         if (core1or5 && (rail == 1) && (type == 1))
498                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
499         if (core2or5 && (rail == 0) && (type == 1))
500                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
501         if (core2or5 && (rail == 1) && (type == 1))
502                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
503         if (core1or5 && (rail == 0) && (type == 6))
504                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
505         if (core1or5 && (rail == 1) && (type == 6))
506                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
507         if (core2or5 && (rail == 0) && (type == 6))
508                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
509         if (core2or5 && (rail == 1) && (type == 6))
510                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
511         if (core1or5 && (rail == 0) && (type == 3))
512                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
513         if (core1or5 && (rail == 1) && (type == 3))
514                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
515         if (core2or5 && (rail == 0) && (type == 3))
516                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
517         if (core2or5 && (rail == 1) && (type == 3))
518                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
519         if (core1or5 && (type == 4))
520                 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
521         if (core2or5 && (type == 4))
522                 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
523         if (core1or5 && (type == 5))
524                 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
525         if (core2or5 && (type == 5))
526                 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
527 }
528
529 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
530 static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
531 {
532         u16 val;
533
534         if (dev->phy.rev >= 3) {
535                 /* TODO */
536         } else {
537                 if (type < 3)
538                         val = 0;
539                 else if (type == 6)
540                         val = 1;
541                 else if (type == 3)
542                         val = 2;
543                 else
544                         val = 3;
545
546                 val = (val << 12) | (val << 14);
547                 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
548                 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
549
550                 if (type < 3) {
551                         b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
552                                         (type + 1) << 4);
553                         b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
554                                         (type + 1) << 4);
555                 }
556
557                 /* TODO use some definitions */
558                 if (code == 0) {
559                         b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0);
560                         if (type < 3) {
561                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
562                                                 0xFEC7, 0);
563                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
564                                                 0xEFDC, 0);
565                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
566                                                 0xFFFE, 0);
567                                 udelay(20);
568                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
569                                                 0xFFFE, 0);
570                         }
571                 } else {
572                         b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF,
573                                         0x3000);
574                         if (type < 3) {
575                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
576                                                 0xFEC7, 0x0180);
577                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
578                                                 0xEFDC, (code << 1 | 0x1021));
579                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
580                                                 0xFFFE, 0x0001);
581                                 udelay(20);
582                                 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
583                                                 0xFFFE, 0);
584                         }
585                 }
586         }
587 }
588
589 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
590 static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
591 {
592         int i;
593         for (i = 0; i < 2; i++) {
594                 if (type == 2) {
595                         if (i == 0) {
596                                 b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
597                                                   0xFC, buf[0]);
598                                 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
599                                                   0xFC, buf[1]);
600                         } else {
601                                 b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
602                                                   0xFC, buf[2 * i]);
603                                 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
604                                                   0xFC, buf[2 * i + 1]);
605                         }
606                 } else {
607                         if (i == 0)
608                                 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
609                                                   0xF3, buf[0] << 2);
610                         else
611                                 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
612                                                   0xF3, buf[2 * i + 1] << 2);
613                 }
614         }
615 }
616
617 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
618 static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
619                                 u8 nsamp)
620 {
621         int i;
622         int out;
623         u16 save_regs_phy[9];
624         u16 s[2];
625
626         if (dev->phy.rev >= 3) {
627                 save_regs_phy[0] = b43_phy_read(dev,
628                                                 B43_NPHY_RFCTL_LUT_TRSW_UP1);
629                 save_regs_phy[1] = b43_phy_read(dev,
630                                                 B43_NPHY_RFCTL_LUT_TRSW_UP2);
631                 save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
632                 save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
633                 save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
634                 save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
635                 save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
636                 save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
637         }
638
639         b43_nphy_rssi_select(dev, 5, type);
640
641         if (dev->phy.rev < 2) {
642                 save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
643                 b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
644         }
645
646         for (i = 0; i < 4; i++)
647                 buf[i] = 0;
648
649         for (i = 0; i < nsamp; i++) {
650                 if (dev->phy.rev < 2) {
651                         s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
652                         s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
653                 } else {
654                         s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
655                         s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
656                 }
657
658                 buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
659                 buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
660                 buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
661                 buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
662         }
663         out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
664                 (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
665
666         if (dev->phy.rev < 2)
667                 b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
668
669         if (dev->phy.rev >= 3) {
670                 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
671                                 save_regs_phy[0]);
672                 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
673                                 save_regs_phy[1]);
674                 b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
675                 b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]);
676                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
677                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
678                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
679                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
680         }
681
682         return out;
683 }
684
685 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
686 static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
687 {
688         /* TODO */
689 }
690
691 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
692 static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
693 {
694         /* TODO */
695 }
696
697 /*
698  * RSSI Calibration
699  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
700  */
701 static void b43_nphy_rssi_cal(struct b43_wldev *dev)
702 {
703         if (dev->phy.rev >= 3) {
704                 b43_nphy_rev3_rssi_cal(dev);
705         } else {
706                 b43_nphy_rev2_rssi_cal(dev, 2);
707                 b43_nphy_rev2_rssi_cal(dev, 0);
708                 b43_nphy_rev2_rssi_cal(dev, 1);
709         }
710 }
711
712 /*
713  * Init N-PHY
714  * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
715  */
716 int b43_phy_initn(struct b43_wldev *dev)
717 {
718         struct ssb_bus *bus = dev->dev->bus;
719         struct b43_phy *phy = &dev->phy;
720         struct b43_phy_n *nphy = phy->n;
721         u8 tx_pwr_state;
722         struct nphy_txgains target;
723         u16 tmp;
724         enum ieee80211_band tmp2;
725         bool do_rssi_cal;
726
727         u16 clip[2];
728         bool do_cal = false;
729
730         if ((dev->phy.rev >= 3) &&
731            (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
732            (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
733                 chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
734         }
735         nphy->deaf_count = 0;
736         b43_nphy_tables_init(dev);
737         nphy->crsminpwr_adjusted = false;
738         nphy->noisevars_adjusted = false;
739
740         /* Clear all overrides */
741         if (dev->phy.rev >= 3) {
742                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
743                 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
744                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
745                 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
746         } else {
747                 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
748         }
749         b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
750         b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
751         if (dev->phy.rev < 6) {
752                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
753                 b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
754         }
755         b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
756                      ~(B43_NPHY_RFSEQMODE_CAOVER |
757                        B43_NPHY_RFSEQMODE_TROVER));
758         if (dev->phy.rev >= 3)
759                 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
760         b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
761
762         if (dev->phy.rev <= 2) {
763                 tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
764                 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
765                                 ~B43_NPHY_BPHY_CTL3_SCALE,
766                                 tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
767         }
768         b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
769         b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
770
771         if (bus->sprom.boardflags2_lo & 0x100 ||
772             (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
773              bus->boardinfo.type == 0x8B))
774                 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
775         else
776                 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
777         b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
778         b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
779         b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
780
781         /* TODO MIMO-Config */
782         /* TODO Update TX/RX chain */
783
784         if (phy->rev < 2) {
785                 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
786                 b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
787         }
788
789         tmp2 = b43_current_band(dev->wl);
790         if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
791             (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
792                 b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
793                 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
794                                 nphy->papd_epsilon_offset[0] << 7);
795                 b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
796                 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
797                                 nphy->papd_epsilon_offset[1] << 7);
798                 /* TODO N PHY IPA Set TX Dig Filters */
799         } else if (phy->rev >= 5) {
800                 /* TODO N PHY Ext PA Set TX Dig Filters */
801         }
802
803         b43_nphy_workarounds(dev);
804
805         /* Reset CCA, in init code it differs a little from standard way */
806         /* b43_nphy_bmac_clock_fgc(dev, 1); */
807         tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
808         b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
809         b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
810         /* b43_nphy_bmac_clock_fgc(dev, 0); */
811
812         /* TODO N PHY MAC PHY Clock Set with argument 1 */
813
814         /* b43_nphy_pa_override(dev, false); */
815         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
816         b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
817         /* b43_nphy_pa_override(dev, true); */
818
819         b43_nphy_classifier(dev, 0, 0);
820         b43_nphy_read_clip_detection(dev, clip);
821         tx_pwr_state = nphy->txpwrctrl;
822         /* TODO N PHY TX power control with argument 0
823                 (turning off power control) */
824         /* TODO Fix the TX Power Settings */
825         /* TODO N PHY TX Power Control Idle TSSI */
826         /* TODO N PHY TX Power Control Setup */
827
828         if (phy->rev >= 3) {
829                 /* TODO */
830         } else {
831                 /* TODO Write an N PHY table with ID 26, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */
832                 /* TODO Write an N PHY table with ID 27, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */
833         }
834
835         if (nphy->phyrxchain != 3)
836                 ;/* TODO N PHY RX Core Set State with phyrxchain as argument */
837         if (nphy->mphase_cal_phase_id > 0)
838                 ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
839
840         do_rssi_cal = false;
841         if (phy->rev >= 3) {
842                 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
843                         do_rssi_cal = (nphy->rssical_chanspec_2G == 0);
844                 else
845                         do_rssi_cal = (nphy->rssical_chanspec_5G == 0);
846
847                 if (do_rssi_cal)
848                         b43_nphy_rssi_cal(dev);
849                 else
850                         ;/* b43_nphy_restore_rssi_cal(dev); */
851         } else {
852                 b43_nphy_rssi_cal(dev);
853         }
854
855         if (!((nphy->measure_hold & 0x6) != 0)) {
856                 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
857                         do_cal = (nphy->iqcal_chanspec_2G == 0);
858                 else
859                         do_cal = (nphy->iqcal_chanspec_5G == 0);
860
861                 if (nphy->mute)
862                         do_cal = false;
863
864                 if (do_cal) {
865                         /* target = b43_nphy_get_tx_gains(dev); */
866
867                         if (nphy->antsel_type == 2)
868                                 ;/*TODO NPHY Superswitch Init with argument 1*/
869                         if (nphy->perical != 2) {
870                                 /* b43_nphy_rssi_cal(dev); */
871                                 if (phy->rev >= 3) {
872                                         nphy->cal_orig_pwr_idx[0] =
873                                             nphy->txpwrindex[0].index_internal;
874                                         nphy->cal_orig_pwr_idx[1] =
875                                             nphy->txpwrindex[1].index_internal;
876                                         /* TODO N PHY Pre Calibrate TX Gain */
877                                         /*target = b43_nphy_get_tx_gains(dev)*/
878                                 }
879                         }
880                 }
881         }
882
883         /*
884         if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) {
885                 if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
886                         Call N PHY Save Cal
887                 else if (nphy->mphase_cal_phase_id == 0)
888                         N PHY Periodic Calibration with argument 3
889         } else {
890                 b43_nphy_restore_cal(dev);
891         }
892         */
893
894         /* b43_nphy_tx_pwr_ctrl_coef_setup(dev); */
895         /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */
896         b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
897         b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
898         if (phy->rev >= 3 && phy->rev <= 6)
899                 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014);
900         /* b43_nphy_tx_lp_fbw(dev); */
901         /* TODO N PHY Spur Workaround */
902
903         b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
904         return 0;
905 }
906
907 static int b43_nphy_op_allocate(struct b43_wldev *dev)
908 {
909         struct b43_phy_n *nphy;
910
911         nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
912         if (!nphy)
913                 return -ENOMEM;
914         dev->phy.n = nphy;
915
916         return 0;
917 }
918
919 static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
920 {
921         struct b43_phy *phy = &dev->phy;
922         struct b43_phy_n *nphy = phy->n;
923
924         memset(nphy, 0, sizeof(*nphy));
925
926         //TODO init struct b43_phy_n
927 }
928
929 static void b43_nphy_op_free(struct b43_wldev *dev)
930 {
931         struct b43_phy *phy = &dev->phy;
932         struct b43_phy_n *nphy = phy->n;
933
934         kfree(nphy);
935         phy->n = NULL;
936 }
937
938 static int b43_nphy_op_init(struct b43_wldev *dev)
939 {
940         return b43_phy_initn(dev);
941 }
942
943 static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
944 {
945 #if B43_DEBUG
946         if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
947                 /* OFDM registers are onnly available on A/G-PHYs */
948                 b43err(dev->wl, "Invalid OFDM PHY access at "
949                        "0x%04X on N-PHY\n", offset);
950                 dump_stack();
951         }
952         if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
953                 /* Ext-G registers are only available on G-PHYs */
954                 b43err(dev->wl, "Invalid EXT-G PHY access at "
955                        "0x%04X on N-PHY\n", offset);
956                 dump_stack();
957         }
958 #endif /* B43_DEBUG */
959 }
960
961 static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
962 {
963         check_phyreg(dev, reg);
964         b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
965         return b43_read16(dev, B43_MMIO_PHY_DATA);
966 }
967
968 static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
969 {
970         check_phyreg(dev, reg);
971         b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
972         b43_write16(dev, B43_MMIO_PHY_DATA, value);
973 }
974
975 static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
976 {
977         /* Register 1 is a 32-bit register. */
978         B43_WARN_ON(reg == 1);
979         /* N-PHY needs 0x100 for read access */
980         reg |= 0x100;
981
982         b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
983         return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
984 }
985
986 static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
987 {
988         /* Register 1 is a 32-bit register. */
989         B43_WARN_ON(reg == 1);
990
991         b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
992         b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
993 }
994
995 static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
996                                         bool blocked)
997 {//TODO
998 }
999
1000 static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
1001 {
1002         b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
1003                       on ? 0 : 0x7FFF);
1004 }
1005
1006 static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
1007                                       unsigned int new_channel)
1008 {
1009         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1010                 if ((new_channel < 1) || (new_channel > 14))
1011                         return -EINVAL;
1012         } else {
1013                 if (new_channel > 200)
1014                         return -EINVAL;
1015         }
1016
1017         return nphy_channel_switch(dev, new_channel);
1018 }
1019
1020 static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
1021 {
1022         if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
1023                 return 1;
1024         return 36;
1025 }
1026
1027 const struct b43_phy_operations b43_phyops_n = {
1028         .allocate               = b43_nphy_op_allocate,
1029         .free                   = b43_nphy_op_free,
1030         .prepare_structs        = b43_nphy_op_prepare_structs,
1031         .init                   = b43_nphy_op_init,
1032         .phy_read               = b43_nphy_op_read,
1033         .phy_write              = b43_nphy_op_write,
1034         .radio_read             = b43_nphy_op_radio_read,
1035         .radio_write            = b43_nphy_op_radio_write,
1036         .software_rfkill        = b43_nphy_op_software_rfkill,
1037         .switch_analog          = b43_nphy_op_switch_analog,
1038         .switch_channel         = b43_nphy_op_switch_channel,
1039         .get_default_chan       = b43_nphy_op_get_default_chan,
1040         .recalc_txpower         = b43_nphy_op_recalc_txpower,
1041         .adjust_txpower         = b43_nphy_op_adjust_txpower,
1042 };