phy_n.c revision 5ecab603c75efafaa2604725efe0afc3da4bd55b
1/*
2
3  Broadcom B43 wireless driver
4  IEEE 802.11n PHY support
5
6  Copyright (c) 2008 Michael Buesch <m@bues.ch>
7  Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
8
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with this program; see the file COPYING.  If not, write to
21  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22  Boston, MA 02110-1301, USA.
23
24*/
25
26#include <linux/delay.h>
27#include <linux/slab.h>
28#include <linux/types.h>
29
30#include "b43.h"
31#include "phy_n.h"
32#include "tables_nphy.h"
33#include "radio_2055.h"
34#include "radio_2056.h"
35#include "main.h"
36
37struct nphy_txgains {
38	u16 txgm[2];
39	u16 pga[2];
40	u16 pad[2];
41	u16 ipa[2];
42};
43
44struct nphy_iqcal_params {
45	u16 txgm;
46	u16 pga;
47	u16 pad;
48	u16 ipa;
49	u16 cal_gain;
50	u16 ncorr[5];
51};
52
53struct nphy_iq_est {
54	s32 iq0_prod;
55	u32 i0_pwr;
56	u32 q0_pwr;
57	s32 iq1_prod;
58	u32 i1_pwr;
59	u32 q1_pwr;
60};
61
62enum b43_nphy_rf_sequence {
63	B43_RFSEQ_RX2TX,
64	B43_RFSEQ_TX2RX,
65	B43_RFSEQ_RESET2RX,
66	B43_RFSEQ_UPDATE_GAINH,
67	B43_RFSEQ_UPDATE_GAINL,
68	B43_RFSEQ_UPDATE_GAINU,
69};
70
71enum b43_nphy_rssi_type {
72	B43_NPHY_RSSI_X = 0,
73	B43_NPHY_RSSI_Y,
74	B43_NPHY_RSSI_Z,
75	B43_NPHY_RSSI_PWRDET,
76	B43_NPHY_RSSI_TSSI_I,
77	B43_NPHY_RSSI_TSSI_Q,
78	B43_NPHY_RSSI_TBD,
79};
80
81static inline bool b43_nphy_ipa(struct b43_wldev *dev)
82{
83	enum ieee80211_band band = b43_current_band(dev->wl);
84	return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
85		(dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ));
86}
87
88/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
89static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
90{
91	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
92		if (dev->phy.rev >= 6) {
93			if (dev->dev->chip_id == 47162)
94				return txpwrctrl_tx_gain_ipa_rev5;
95			return txpwrctrl_tx_gain_ipa_rev6;
96		} else if (dev->phy.rev >= 5) {
97			return txpwrctrl_tx_gain_ipa_rev5;
98		} else {
99			return txpwrctrl_tx_gain_ipa;
100		}
101	} else {
102		return txpwrctrl_tx_gain_ipa_5g;
103	}
104}
105
106/**************************************************
107 * RF (just without b43_nphy_rf_control_intc_override)
108 **************************************************/
109
110/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
111static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
112				       enum b43_nphy_rf_sequence seq)
113{
114	static const u16 trigger[] = {
115		[B43_RFSEQ_RX2TX]		= B43_NPHY_RFSEQTR_RX2TX,
116		[B43_RFSEQ_TX2RX]		= B43_NPHY_RFSEQTR_TX2RX,
117		[B43_RFSEQ_RESET2RX]		= B43_NPHY_RFSEQTR_RST2RX,
118		[B43_RFSEQ_UPDATE_GAINH]	= B43_NPHY_RFSEQTR_UPGH,
119		[B43_RFSEQ_UPDATE_GAINL]	= B43_NPHY_RFSEQTR_UPGL,
120		[B43_RFSEQ_UPDATE_GAINU]	= B43_NPHY_RFSEQTR_UPGU,
121	};
122	int i;
123	u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
124
125	B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
126
127	b43_phy_set(dev, B43_NPHY_RFSEQMODE,
128		    B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
129	b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
130	for (i = 0; i < 200; i++) {
131		if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
132			goto ok;
133		msleep(1);
134	}
135	b43err(dev->wl, "RF sequence status timeout\n");
136ok:
137	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
138}
139
140/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
141static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
142						u16 value, u8 core, bool off)
143{
144	int i;
145	u8 index = fls(field);
146	u8 addr, en_addr, val_addr;
147	/* we expect only one bit set */
148	B43_WARN_ON(field & (~(1 << (index - 1))));
149
150	if (dev->phy.rev >= 3) {
151		const struct nphy_rf_control_override_rev3 *rf_ctrl;
152		for (i = 0; i < 2; i++) {
153			if (index == 0 || index == 16) {
154				b43err(dev->wl,
155					"Unsupported RF Ctrl Override call\n");
156				return;
157			}
158
159			rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
160			en_addr = B43_PHY_N((i == 0) ?
161				rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
162			val_addr = B43_PHY_N((i == 0) ?
163				rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
164
165			if (off) {
166				b43_phy_mask(dev, en_addr, ~(field));
167				b43_phy_mask(dev, val_addr,
168						~(rf_ctrl->val_mask));
169			} else {
170				if (core == 0 || ((1 << core) & i) != 0) {
171					b43_phy_set(dev, en_addr, field);
172					b43_phy_maskset(dev, val_addr,
173						~(rf_ctrl->val_mask),
174						(value << rf_ctrl->val_shift));
175				}
176			}
177		}
178	} else {
179		const struct nphy_rf_control_override_rev2 *rf_ctrl;
180		if (off) {
181			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
182			value = 0;
183		} else {
184			b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
185		}
186
187		for (i = 0; i < 2; i++) {
188			if (index <= 1 || index == 16) {
189				b43err(dev->wl,
190					"Unsupported RF Ctrl Override call\n");
191				return;
192			}
193
194			if (index == 2 || index == 10 ||
195			    (index >= 13 && index <= 15)) {
196				core = 1;
197			}
198
199			rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
200			addr = B43_PHY_N((i == 0) ?
201				rf_ctrl->addr0 : rf_ctrl->addr1);
202
203			if ((core & (1 << i)) != 0)
204				b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
205						(value << rf_ctrl->shift));
206
207			b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
208			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
209					B43_NPHY_RFCTL_CMD_START);
210			udelay(1);
211			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
212		}
213	}
214}
215
216/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
217static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
218						u16 value, u8 core)
219{
220	u8 i, j;
221	u16 reg, tmp, val;
222
223	B43_WARN_ON(dev->phy.rev < 3);
224	B43_WARN_ON(field > 4);
225
226	for (i = 0; i < 2; i++) {
227		if ((core == 1 && i == 1) || (core == 2 && !i))
228			continue;
229
230		reg = (i == 0) ?
231			B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
232		b43_phy_mask(dev, reg, 0xFBFF);
233
234		switch (field) {
235		case 0:
236			b43_phy_write(dev, reg, 0);
237			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
238			break;
239		case 1:
240			if (!i) {
241				b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
242						0xFC3F, (value << 6));
243				b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
244						0xFFFE, 1);
245				b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
246						B43_NPHY_RFCTL_CMD_START);
247				for (j = 0; j < 100; j++) {
248					if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) {
249						j = 0;
250						break;
251					}
252					udelay(10);
253				}
254				if (j)
255					b43err(dev->wl,
256						"intc override timeout\n");
257				b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
258						0xFFFE);
259			} else {
260				b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
261						0xFC3F, (value << 6));
262				b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
263						0xFFFE, 1);
264				b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
265						B43_NPHY_RFCTL_CMD_RXTX);
266				for (j = 0; j < 100; j++) {
267					if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) {
268						j = 0;
269						break;
270					}
271					udelay(10);
272				}
273				if (j)
274					b43err(dev->wl,
275						"intc override timeout\n");
276				b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
277						0xFFFE);
278			}
279			break;
280		case 2:
281			if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
282				tmp = 0x0020;
283				val = value << 5;
284			} else {
285				tmp = 0x0010;
286				val = value << 4;
287			}
288			b43_phy_maskset(dev, reg, ~tmp, val);
289			break;
290		case 3:
291			if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
292				tmp = 0x0001;
293				val = value;
294			} else {
295				tmp = 0x0004;
296				val = value << 2;
297			}
298			b43_phy_maskset(dev, reg, ~tmp, val);
299			break;
300		case 4:
301			if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
302				tmp = 0x0002;
303				val = value << 1;
304			} else {
305				tmp = 0x0008;
306				val = value << 3;
307			}
308			b43_phy_maskset(dev, reg, ~tmp, val);
309			break;
310		}
311	}
312}
313
314/**************************************************
315 * Various PHY ops
316 **************************************************/
317
318/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
319static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
320					  const u16 *clip_st)
321{
322	b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
323	b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
324}
325
326/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
327static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
328{
329	clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
330	clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
331}
332
333/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
334static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
335{
336	u16 tmp;
337
338	if (dev->dev->core_rev == 16)
339		b43_mac_suspend(dev);
340
341	tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
342	tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
343		B43_NPHY_CLASSCTL_WAITEDEN);
344	tmp &= ~mask;
345	tmp |= (val & mask);
346	b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
347
348	if (dev->dev->core_rev == 16)
349		b43_mac_enable(dev);
350
351	return tmp;
352}
353
354/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
355static void b43_nphy_reset_cca(struct b43_wldev *dev)
356{
357	u16 bbcfg;
358
359	b43_phy_force_clock(dev, 1);
360	bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
361	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
362	udelay(1);
363	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
364	b43_phy_force_clock(dev, 0);
365	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
366}
367
368/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
369static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
370{
371	struct b43_phy *phy = &dev->phy;
372	struct b43_phy_n *nphy = phy->n;
373
374	if (enable) {
375		static const u16 clip[] = { 0xFFFF, 0xFFFF };
376		if (nphy->deaf_count++ == 0) {
377			nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
378			b43_nphy_classifier(dev, 0x7, 0);
379			b43_nphy_read_clip_detection(dev, nphy->clip_state);
380			b43_nphy_write_clip_detection(dev, clip);
381		}
382		b43_nphy_reset_cca(dev);
383	} else {
384		if (--nphy->deaf_count == 0) {
385			b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
386			b43_nphy_write_clip_detection(dev, nphy->clip_state);
387		}
388	}
389}
390
391/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
392static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
393{
394	struct b43_phy_n *nphy = dev->phy.n;
395
396	u8 i;
397	s16 tmp;
398	u16 data[4];
399	s16 gain[2];
400	u16 minmax[2];
401	static const u16 lna_gain[4] = { -2, 10, 19, 25 };
402
403	if (nphy->hang_avoid)
404		b43_nphy_stay_in_carrier_search(dev, 1);
405
406	if (nphy->gain_boost) {
407		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
408			gain[0] = 6;
409			gain[1] = 6;
410		} else {
411			tmp = 40370 - 315 * dev->phy.channel;
412			gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
413			tmp = 23242 - 224 * dev->phy.channel;
414			gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
415		}
416	} else {
417		gain[0] = 0;
418		gain[1] = 0;
419	}
420
421	for (i = 0; i < 2; i++) {
422		if (nphy->elna_gain_config) {
423			data[0] = 19 + gain[i];
424			data[1] = 25 + gain[i];
425			data[2] = 25 + gain[i];
426			data[3] = 25 + gain[i];
427		} else {
428			data[0] = lna_gain[0] + gain[i];
429			data[1] = lna_gain[1] + gain[i];
430			data[2] = lna_gain[2] + gain[i];
431			data[3] = lna_gain[3] + gain[i];
432		}
433		b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
434
435		minmax[i] = 23 + gain[i];
436	}
437
438	b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
439				minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
440	b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
441				minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
442
443	if (nphy->hang_avoid)
444		b43_nphy_stay_in_carrier_search(dev, 0);
445}
446
447/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
448static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
449					u8 *events, u8 *delays, u8 length)
450{
451	struct b43_phy_n *nphy = dev->phy.n;
452	u8 i;
453	u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
454	u16 offset1 = cmd << 4;
455	u16 offset2 = offset1 + 0x80;
456
457	if (nphy->hang_avoid)
458		b43_nphy_stay_in_carrier_search(dev, true);
459
460	b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
461	b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
462
463	for (i = length; i < 16; i++) {
464		b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
465		b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
466	}
467
468	if (nphy->hang_avoid)
469		b43_nphy_stay_in_carrier_search(dev, false);
470}
471
472/**************************************************
473 * Radio 0x2056
474 **************************************************/
475
476static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
477				const struct b43_nphy_channeltab_entry_rev3 *e)
478{
479	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
480	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
481	b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
482	b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
483	b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
484	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
485					e->radio_syn_pll_loopfilter1);
486	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
487					e->radio_syn_pll_loopfilter2);
488	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
489					e->radio_syn_pll_loopfilter3);
490	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
491					e->radio_syn_pll_loopfilter4);
492	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
493					e->radio_syn_pll_loopfilter5);
494	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
495					e->radio_syn_reserved_addr27);
496	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
497					e->radio_syn_reserved_addr28);
498	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
499					e->radio_syn_reserved_addr29);
500	b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
501					e->radio_syn_logen_vcobuf1);
502	b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
503	b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
504	b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
505
506	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
507					e->radio_rx0_lnaa_tune);
508	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
509					e->radio_rx0_lnag_tune);
510
511	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
512					e->radio_tx0_intpaa_boost_tune);
513	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
514					e->radio_tx0_intpag_boost_tune);
515	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
516					e->radio_tx0_pada_boost_tune);
517	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
518					e->radio_tx0_padg_boost_tune);
519	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
520					e->radio_tx0_pgaa_boost_tune);
521	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
522					e->radio_tx0_pgag_boost_tune);
523	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
524					e->radio_tx0_mixa_boost_tune);
525	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
526					e->radio_tx0_mixg_boost_tune);
527
528	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
529					e->radio_rx1_lnaa_tune);
530	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
531					e->radio_rx1_lnag_tune);
532
533	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
534					e->radio_tx1_intpaa_boost_tune);
535	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
536					e->radio_tx1_intpag_boost_tune);
537	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
538					e->radio_tx1_pada_boost_tune);
539	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
540					e->radio_tx1_padg_boost_tune);
541	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
542					e->radio_tx1_pgaa_boost_tune);
543	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
544					e->radio_tx1_pgag_boost_tune);
545	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
546					e->radio_tx1_mixa_boost_tune);
547	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
548					e->radio_tx1_mixg_boost_tune);
549}
550
551/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
552static void b43_radio_2056_setup(struct b43_wldev *dev,
553				const struct b43_nphy_channeltab_entry_rev3 *e)
554{
555	struct ssb_sprom *sprom = dev->dev->bus_sprom;
556	enum ieee80211_band band = b43_current_band(dev->wl);
557	u16 offset;
558	u8 i;
559	u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost;
560
561	B43_WARN_ON(dev->phy.rev < 3);
562
563	b43_chantab_radio_2056_upload(dev, e);
564	b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ);
565
566	if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
567	    b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
568		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
569		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
570		if (dev->dev->chip_id == 0x4716) {
571			b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
572			b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
573		} else {
574			b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
575			b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
576		}
577	}
578	if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
579	    b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
580		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
581		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
582		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
583		b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
584	}
585
586	if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) {
587		for (i = 0; i < 2; i++) {
588			offset = i ? B2056_TX1 : B2056_TX0;
589			if (dev->phy.rev >= 5) {
590				b43_radio_write(dev,
591					offset | B2056_TX_PADG_IDAC, 0xcc);
592
593				if (dev->dev->chip_id == 0x4716) {
594					bias = 0x40;
595					cbias = 0x45;
596					pag_boost = 0x5;
597					pgag_boost = 0x33;
598					mixg_boost = 0x55;
599				} else {
600					bias = 0x25;
601					cbias = 0x20;
602					pag_boost = 0x4;
603					pgag_boost = 0x03;
604					mixg_boost = 0x65;
605				}
606				padg_boost = 0x77;
607
608				b43_radio_write(dev,
609					offset | B2056_TX_INTPAG_IMAIN_STAT,
610					bias);
611				b43_radio_write(dev,
612					offset | B2056_TX_INTPAG_IAUX_STAT,
613					bias);
614				b43_radio_write(dev,
615					offset | B2056_TX_INTPAG_CASCBIAS,
616					cbias);
617				b43_radio_write(dev,
618					offset | B2056_TX_INTPAG_BOOST_TUNE,
619					pag_boost);
620				b43_radio_write(dev,
621					offset | B2056_TX_PGAG_BOOST_TUNE,
622					pgag_boost);
623				b43_radio_write(dev,
624					offset | B2056_TX_PADG_BOOST_TUNE,
625					padg_boost);
626				b43_radio_write(dev,
627					offset | B2056_TX_MIXG_BOOST_TUNE,
628					mixg_boost);
629			} else {
630				bias = dev->phy.is_40mhz ? 0x40 : 0x20;
631				b43_radio_write(dev,
632					offset | B2056_TX_INTPAG_IMAIN_STAT,
633					bias);
634				b43_radio_write(dev,
635					offset | B2056_TX_INTPAG_IAUX_STAT,
636					bias);
637				b43_radio_write(dev,
638					offset | B2056_TX_INTPAG_CASCBIAS,
639					0x30);
640			}
641			b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
642		}
643	} else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
644		/* TODO */
645	}
646
647	udelay(50);
648	/* VCO calibration */
649	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
650	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
651	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
652	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
653	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
654	udelay(300);
655}
656
657static void b43_radio_init2056_pre(struct b43_wldev *dev)
658{
659	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
660		     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
661	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
662	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
663		     B43_NPHY_RFCTL_CMD_OEPORFORCE);
664	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
665		    ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
666	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
667		    B43_NPHY_RFCTL_CMD_CHIP0PU);
668}
669
670static void b43_radio_init2056_post(struct b43_wldev *dev)
671{
672	b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
673	b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
674	b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
675	msleep(1);
676	b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
677	b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
678	b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
679	/*
680	if (nphy->init_por)
681		Call Radio 2056 Recalibrate
682	*/
683}
684
685/*
686 * Initialize a Broadcom 2056 N-radio
687 * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
688 */
689static void b43_radio_init2056(struct b43_wldev *dev)
690{
691	b43_radio_init2056_pre(dev);
692	b2056_upload_inittabs(dev, 0, 0);
693	b43_radio_init2056_post(dev);
694}
695
696/**************************************************
697 * Radio 0x2055
698 **************************************************/
699
700static void b43_chantab_radio_upload(struct b43_wldev *dev,
701				const struct b43_nphy_channeltab_entry_rev2 *e)
702{
703	b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
704	b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
705	b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
706	b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
707	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
708
709	b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
710	b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
711	b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
712	b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
713	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
714
715	b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
716	b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
717	b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
718	b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
719	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
720
721	b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
722	b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
723	b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
724	b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
725	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
726
727	b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
728	b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
729	b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
730	b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
731	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
732
733	b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
734	b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
735}
736
737/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
738static void b43_radio_2055_setup(struct b43_wldev *dev,
739				const struct b43_nphy_channeltab_entry_rev2 *e)
740{
741	B43_WARN_ON(dev->phy.rev >= 3);
742
743	b43_chantab_radio_upload(dev, e);
744	udelay(50);
745	b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
746	b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
747	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
748	b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
749	udelay(300);
750}
751
752static void b43_radio_init2055_pre(struct b43_wldev *dev)
753{
754	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
755		     ~B43_NPHY_RFCTL_CMD_PORFORCE);
756	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
757		    B43_NPHY_RFCTL_CMD_CHIP0PU |
758		    B43_NPHY_RFCTL_CMD_OEPORFORCE);
759	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
760		    B43_NPHY_RFCTL_CMD_PORFORCE);
761}
762
763static void b43_radio_init2055_post(struct b43_wldev *dev)
764{
765	struct b43_phy_n *nphy = dev->phy.n;
766	struct ssb_sprom *sprom = dev->dev->bus_sprom;
767	int i;
768	u16 val;
769	bool workaround = false;
770
771	if (sprom->revision < 4)
772		workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
773			      && dev->dev->board_type == 0x46D
774			      && dev->dev->board_rev >= 0x41);
775	else
776		workaround =
777			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
778
779	b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
780	if (workaround) {
781		b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
782		b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
783	}
784	b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
785	b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
786	b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
787	b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
788	b43_radio_set(dev, B2055_CAL_MISC, 0x1);
789	msleep(1);
790	b43_radio_set(dev, B2055_CAL_MISC, 0x40);
791	for (i = 0; i < 200; i++) {
792		val = b43_radio_read(dev, B2055_CAL_COUT2);
793		if (val & 0x80) {
794			i = 0;
795			break;
796		}
797		udelay(10);
798	}
799	if (i)
800		b43err(dev->wl, "radio post init timeout\n");
801	b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
802	b43_switch_channel(dev, dev->phy.channel);
803	b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
804	b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
805	b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
806	b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
807	b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
808	b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
809	if (!nphy->gain_boost) {
810		b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
811		b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
812	} else {
813		b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
814		b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
815	}
816	udelay(2);
817}
818
819/*
820 * Initialize a Broadcom 2055 N-radio
821 * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
822 */
823static void b43_radio_init2055(struct b43_wldev *dev)
824{
825	b43_radio_init2055_pre(dev);
826	if (b43_status(dev) < B43_STAT_INITIALIZED) {
827		/* Follow wl, not specs. Do not force uploading all regs */
828		b2055_upload_inittab(dev, 0, 0);
829	} else {
830		bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
831		b2055_upload_inittab(dev, ghz5, 0);
832	}
833	b43_radio_init2055_post(dev);
834}
835
836/**************************************************
837 * Samples
838 **************************************************/
839
840/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
841static int b43_nphy_load_samples(struct b43_wldev *dev,
842					struct b43_c32 *samples, u16 len) {
843	struct b43_phy_n *nphy = dev->phy.n;
844	u16 i;
845	u32 *data;
846
847	data = kzalloc(len * sizeof(u32), GFP_KERNEL);
848	if (!data) {
849		b43err(dev->wl, "allocation for samples loading failed\n");
850		return -ENOMEM;
851	}
852	if (nphy->hang_avoid)
853		b43_nphy_stay_in_carrier_search(dev, 1);
854
855	for (i = 0; i < len; i++) {
856		data[i] = (samples[i].i & 0x3FF << 10);
857		data[i] |= samples[i].q & 0x3FF;
858	}
859	b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
860
861	kfree(data);
862	if (nphy->hang_avoid)
863		b43_nphy_stay_in_carrier_search(dev, 0);
864	return 0;
865}
866
867/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
868static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
869					bool test)
870{
871	int i;
872	u16 bw, len, rot, angle;
873	struct b43_c32 *samples;
874
875
876	bw = (dev->phy.is_40mhz) ? 40 : 20;
877	len = bw << 3;
878
879	if (test) {
880		if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
881			bw = 82;
882		else
883			bw = 80;
884
885		if (dev->phy.is_40mhz)
886			bw <<= 1;
887
888		len = bw << 1;
889	}
890
891	samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL);
892	if (!samples) {
893		b43err(dev->wl, "allocation for samples generation failed\n");
894		return 0;
895	}
896	rot = (((freq * 36) / bw) << 16) / 100;
897	angle = 0;
898
899	for (i = 0; i < len; i++) {
900		samples[i] = b43_cordic(angle);
901		angle += rot;
902		samples[i].q = CORDIC_CONVERT(samples[i].q * max);
903		samples[i].i = CORDIC_CONVERT(samples[i].i * max);
904	}
905
906	i = b43_nphy_load_samples(dev, samples, len);
907	kfree(samples);
908	return (i < 0) ? 0 : len;
909}
910
911/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
912static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
913					u16 wait, bool iqmode, bool dac_test)
914{
915	struct b43_phy_n *nphy = dev->phy.n;
916	int i;
917	u16 seq_mode;
918	u32 tmp;
919
920	if (nphy->hang_avoid)
921		b43_nphy_stay_in_carrier_search(dev, true);
922
923	if ((nphy->bb_mult_save & 0x80000000) == 0) {
924		tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
925		nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
926	}
927
928	if (!dev->phy.is_40mhz)
929		tmp = 0x6464;
930	else
931		tmp = 0x4747;
932	b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
933
934	if (nphy->hang_avoid)
935		b43_nphy_stay_in_carrier_search(dev, false);
936
937	b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
938
939	if (loops != 0xFFFF)
940		b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
941	else
942		b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
943
944	b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
945
946	seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
947
948	b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
949	if (iqmode) {
950		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
951		b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
952	} else {
953		if (dac_test)
954			b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
955		else
956			b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
957	}
958	for (i = 0; i < 100; i++) {
959		if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) {
960			i = 0;
961			break;
962		}
963		udelay(10);
964	}
965	if (i)
966		b43err(dev->wl, "run samples timeout\n");
967
968	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
969}
970
971/**************************************************
972 * RSSI
973 **************************************************/
974
975/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
976static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
977					s8 offset, u8 core, u8 rail,
978					enum b43_nphy_rssi_type type)
979{
980	u16 tmp;
981	bool core1or5 = (core == 1) || (core == 5);
982	bool core2or5 = (core == 2) || (core == 5);
983
984	offset = clamp_val(offset, -32, 31);
985	tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
986
987	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
988		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
989	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
990		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
991	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
992		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
993	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
994		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
995
996	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
997		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
998	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
999		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
1000	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
1001		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
1002	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
1003		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
1004
1005	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
1006		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
1007	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
1008		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
1009	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
1010		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
1011	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
1012		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
1013
1014	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
1015		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
1016	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
1017		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
1018	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
1019		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
1020	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
1021		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
1022
1023	if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
1024		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
1025	if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
1026		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
1027	if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
1028		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
1029	if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
1030		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
1031
1032	if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
1033		b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
1034	if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
1035		b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
1036
1037	if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
1038		b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
1039	if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
1040		b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
1041}
1042
1043static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1044{
1045	u8 i;
1046	u16 reg, val;
1047
1048	if (code == 0) {
1049		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
1050		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
1051		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
1052		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
1053		b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
1054		b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
1055		b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
1056		b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
1057	} else {
1058		for (i = 0; i < 2; i++) {
1059			if ((code == 1 && i == 1) || (code == 2 && !i))
1060				continue;
1061
1062			reg = (i == 0) ?
1063				B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
1064			b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
1065
1066			if (type < 3) {
1067				reg = (i == 0) ?
1068					B43_NPHY_AFECTL_C1 :
1069					B43_NPHY_AFECTL_C2;
1070				b43_phy_maskset(dev, reg, 0xFCFF, 0);
1071
1072				reg = (i == 0) ?
1073					B43_NPHY_RFCTL_LUT_TRSW_UP1 :
1074					B43_NPHY_RFCTL_LUT_TRSW_UP2;
1075				b43_phy_maskset(dev, reg, 0xFFC3, 0);
1076
1077				if (type == 0)
1078					val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
1079				else if (type == 1)
1080					val = 16;
1081				else
1082					val = 32;
1083				b43_phy_set(dev, reg, val);
1084
1085				reg = (i == 0) ?
1086					B43_NPHY_TXF_40CO_B1S0 :
1087					B43_NPHY_TXF_40CO_B32S1;
1088				b43_phy_set(dev, reg, 0x0020);
1089			} else {
1090				if (type == 6)
1091					val = 0x0100;
1092				else if (type == 3)
1093					val = 0x0200;
1094				else
1095					val = 0x0300;
1096
1097				reg = (i == 0) ?
1098					B43_NPHY_AFECTL_C1 :
1099					B43_NPHY_AFECTL_C2;
1100
1101				b43_phy_maskset(dev, reg, 0xFCFF, val);
1102				b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
1103
1104				if (type != 3 && type != 6) {
1105					enum ieee80211_band band =
1106						b43_current_band(dev->wl);
1107
1108					if (b43_nphy_ipa(dev))
1109						val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
1110					else
1111						val = 0x11;
1112					reg = (i == 0) ? 0x2000 : 0x3000;
1113					reg |= B2055_PADDRV;
1114					b43_radio_write16(dev, reg, val);
1115
1116					reg = (i == 0) ?
1117						B43_NPHY_AFECTL_OVER1 :
1118						B43_NPHY_AFECTL_OVER;
1119					b43_phy_set(dev, reg, 0x0200);
1120				}
1121			}
1122		}
1123	}
1124}
1125
1126static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1127{
1128	u16 val;
1129
1130	if (type < 3)
1131		val = 0;
1132	else if (type == 6)
1133		val = 1;
1134	else if (type == 3)
1135		val = 2;
1136	else
1137		val = 3;
1138
1139	val = (val << 12) | (val << 14);
1140	b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
1141	b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
1142
1143	if (type < 3) {
1144		b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
1145				(type + 1) << 4);
1146		b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
1147				(type + 1) << 4);
1148	}
1149
1150	if (code == 0) {
1151		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
1152		if (type < 3) {
1153			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
1154				~(B43_NPHY_RFCTL_CMD_RXEN |
1155				  B43_NPHY_RFCTL_CMD_CORESEL));
1156			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
1157				~(0x1 << 12 |
1158				  0x1 << 5 |
1159				  0x1 << 1 |
1160				  0x1));
1161			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
1162				~B43_NPHY_RFCTL_CMD_START);
1163			udelay(20);
1164			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
1165		}
1166	} else {
1167		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
1168		if (type < 3) {
1169			b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
1170				~(B43_NPHY_RFCTL_CMD_RXEN |
1171				  B43_NPHY_RFCTL_CMD_CORESEL),
1172				(B43_NPHY_RFCTL_CMD_RXEN |
1173				 code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
1174			b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
1175				(0x1 << 12 |
1176				  0x1 << 5 |
1177				  0x1 << 1 |
1178				  0x1));
1179			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
1180				B43_NPHY_RFCTL_CMD_START);
1181			udelay(20);
1182			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
1183		}
1184	}
1185}
1186
1187/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
1188static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1189{
1190	if (dev->phy.rev >= 3)
1191		b43_nphy_rev3_rssi_select(dev, code, type);
1192	else
1193		b43_nphy_rev2_rssi_select(dev, code, type);
1194}
1195
1196/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
1197static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
1198{
1199	int i;
1200	for (i = 0; i < 2; i++) {
1201		if (type == 2) {
1202			if (i == 0) {
1203				b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
1204						  0xFC, buf[0]);
1205				b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
1206						  0xFC, buf[1]);
1207			} else {
1208				b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
1209						  0xFC, buf[2 * i]);
1210				b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
1211						  0xFC, buf[2 * i + 1]);
1212			}
1213		} else {
1214			if (i == 0)
1215				b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
1216						  0xF3, buf[0] << 2);
1217			else
1218				b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
1219						  0xF3, buf[2 * i + 1] << 2);
1220		}
1221	}
1222}
1223
1224/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
1225static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
1226				u8 nsamp)
1227{
1228	int i;
1229	int out;
1230	u16 save_regs_phy[9];
1231	u16 s[2];
1232
1233	if (dev->phy.rev >= 3) {
1234		save_regs_phy[0] = b43_phy_read(dev,
1235						B43_NPHY_RFCTL_LUT_TRSW_UP1);
1236		save_regs_phy[1] = b43_phy_read(dev,
1237						B43_NPHY_RFCTL_LUT_TRSW_UP2);
1238		save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
1239		save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
1240		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
1241		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
1242		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
1243		save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
1244		save_regs_phy[8] = 0;
1245	} else {
1246		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
1247		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
1248		save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
1249		save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
1250		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
1251		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
1252		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
1253		save_regs_phy[7] = 0;
1254		save_regs_phy[8] = 0;
1255	}
1256
1257	b43_nphy_rssi_select(dev, 5, type);
1258
1259	if (dev->phy.rev < 2) {
1260		save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
1261		b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
1262	}
1263
1264	for (i = 0; i < 4; i++)
1265		buf[i] = 0;
1266
1267	for (i = 0; i < nsamp; i++) {
1268		if (dev->phy.rev < 2) {
1269			s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
1270			s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
1271		} else {
1272			s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
1273			s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
1274		}
1275
1276		buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
1277		buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
1278		buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
1279		buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
1280	}
1281	out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
1282		(buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
1283
1284	if (dev->phy.rev < 2)
1285		b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
1286
1287	if (dev->phy.rev >= 3) {
1288		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
1289				save_regs_phy[0]);
1290		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
1291				save_regs_phy[1]);
1292		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
1293		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]);
1294		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
1295		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
1296		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
1297		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
1298	} else {
1299		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
1300		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
1301		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
1302		b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
1303		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
1304		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
1305		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
1306	}
1307
1308	return out;
1309}
1310
1311/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
1312static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
1313{
1314	int i, j;
1315	u8 state[4];
1316	u8 code, val;
1317	u16 class, override;
1318	u8 regs_save_radio[2];
1319	u16 regs_save_phy[2];
1320
1321	s8 offset[4];
1322	u8 core;
1323	u8 rail;
1324
1325	u16 clip_state[2];
1326	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
1327	s32 results_min[4] = { };
1328	u8 vcm_final[4] = { };
1329	s32 results[4][4] = { };
1330	s32 miniq[4][2] = { };
1331
1332	if (type == 2) {
1333		code = 0;
1334		val = 6;
1335	} else if (type < 2) {
1336		code = 25;
1337		val = 4;
1338	} else {
1339		B43_WARN_ON(1);
1340		return;
1341	}
1342
1343	class = b43_nphy_classifier(dev, 0, 0);
1344	b43_nphy_classifier(dev, 7, 4);
1345	b43_nphy_read_clip_detection(dev, clip_state);
1346	b43_nphy_write_clip_detection(dev, clip_off);
1347
1348	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
1349		override = 0x140;
1350	else
1351		override = 0x110;
1352
1353	regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
1354	regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
1355	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
1356	b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
1357
1358	regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
1359	regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
1360	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
1361	b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
1362
1363	state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
1364	state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
1365	b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
1366	b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
1367	state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
1368	state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
1369
1370	b43_nphy_rssi_select(dev, 5, type);
1371	b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
1372	b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
1373
1374	for (i = 0; i < 4; i++) {
1375		u8 tmp[4];
1376		for (j = 0; j < 4; j++)
1377			tmp[j] = i;
1378		if (type != 1)
1379			b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
1380		b43_nphy_poll_rssi(dev, type, results[i], 8);
1381		if (type < 2)
1382			for (j = 0; j < 2; j++)
1383				miniq[i][j] = min(results[i][2 * j],
1384						results[i][2 * j + 1]);
1385	}
1386
1387	for (i = 0; i < 4; i++) {
1388		s32 mind = 40;
1389		u8 minvcm = 0;
1390		s32 minpoll = 249;
1391		s32 curr;
1392		for (j = 0; j < 4; j++) {
1393			if (type == 2)
1394				curr = abs(results[j][i]);
1395			else
1396				curr = abs(miniq[j][i / 2] - code * 8);
1397
1398			if (curr < mind) {
1399				mind = curr;
1400				minvcm = j;
1401			}
1402
1403			if (results[j][i] < minpoll)
1404				minpoll = results[j][i];
1405		}
1406		results_min[i] = minpoll;
1407		vcm_final[i] = minvcm;
1408	}
1409
1410	if (type != 1)
1411		b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
1412
1413	for (i = 0; i < 4; i++) {
1414		offset[i] = (code * 8) - results[vcm_final[i]][i];
1415
1416		if (offset[i] < 0)
1417			offset[i] = -((abs(offset[i]) + 4) / 8);
1418		else
1419			offset[i] = (offset[i] + 4) / 8;
1420
1421		if (results_min[i] == 248)
1422			offset[i] = code - 32;
1423
1424		core = (i / 2) ? 2 : 1;
1425		rail = (i % 2) ? 1 : 0;
1426
1427		b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
1428						type);
1429	}
1430
1431	b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
1432	b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
1433
1434	switch (state[2]) {
1435	case 1:
1436		b43_nphy_rssi_select(dev, 1, 2);
1437		break;
1438	case 4:
1439		b43_nphy_rssi_select(dev, 1, 0);
1440		break;
1441	case 2:
1442		b43_nphy_rssi_select(dev, 1, 1);
1443		break;
1444	default:
1445		b43_nphy_rssi_select(dev, 1, 1);
1446		break;
1447	}
1448
1449	switch (state[3]) {
1450	case 1:
1451		b43_nphy_rssi_select(dev, 2, 2);
1452		break;
1453	case 4:
1454		b43_nphy_rssi_select(dev, 2, 0);
1455		break;
1456	default:
1457		b43_nphy_rssi_select(dev, 2, 1);
1458		break;
1459	}
1460
1461	b43_nphy_rssi_select(dev, 0, type);
1462
1463	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
1464	b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
1465	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
1466	b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
1467
1468	b43_nphy_classifier(dev, 7, class);
1469	b43_nphy_write_clip_detection(dev, clip_state);
1470	/* Specs don't say about reset here, but it makes wl and b43 dumps
1471	   identical, it really seems wl performs this */
1472	b43_nphy_reset_cca(dev);
1473}
1474
1475/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
1476static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1477{
1478	/* TODO */
1479}
1480
1481/*
1482 * RSSI Calibration
1483 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
1484 */
1485static void b43_nphy_rssi_cal(struct b43_wldev *dev)
1486{
1487	if (dev->phy.rev >= 3) {
1488		b43_nphy_rev3_rssi_cal(dev);
1489	} else {
1490		b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
1491		b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
1492		b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
1493	}
1494}
1495
1496/**************************************************
1497 * Workarounds
1498 **************************************************/
1499
1500static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
1501{
1502	struct ssb_sprom *sprom = dev->dev->bus_sprom;
1503
1504	bool ghz5;
1505	bool ext_lna;
1506	u16 rssi_gain;
1507	struct nphy_gain_ctl_workaround_entry *e;
1508	u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
1509	u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
1510
1511	/* Prepare values */
1512	ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
1513		& B43_NPHY_BANDCTL_5GHZ;
1514	ext_lna = sprom->boardflags_lo & B43_BFL_EXTLNA;
1515	e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
1516	if (ghz5 && dev->phy.rev >= 5)
1517		rssi_gain = 0x90;
1518	else
1519		rssi_gain = 0x50;
1520
1521	b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
1522
1523	/* Set Clip 2 detect */
1524	b43_phy_set(dev, B43_NPHY_C1_CGAINI,
1525			B43_NPHY_C1_CGAINI_CL2DETECT);
1526	b43_phy_set(dev, B43_NPHY_C2_CGAINI,
1527			B43_NPHY_C2_CGAINI_CL2DETECT);
1528
1529	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
1530			0x17);
1531	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
1532			0x17);
1533	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
1534	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
1535	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
1536	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
1537	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
1538			rssi_gain);
1539	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
1540			rssi_gain);
1541	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
1542			0x17);
1543	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
1544			0x17);
1545	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
1546	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
1547
1548	b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
1549	b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
1550	b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
1551	b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
1552	b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
1553	b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
1554	b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
1555	b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
1556	b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
1557	b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
1558	b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
1559	b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
1560
1561	b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
1562	b43_phy_write(dev, 0x2A7, e->init_gain);
1563	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
1564				e->rfseq_init);
1565	b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
1566
1567	/* TODO: check defines. Do not match variables names */
1568	b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain);
1569	b43_phy_write(dev, 0x2A9, e->cliphi_gain);
1570	b43_phy_write(dev, B43_NPHY_C1_CLIP2_GAIN, e->clipmd_gain);
1571	b43_phy_write(dev, 0x2AB, e->clipmd_gain);
1572	b43_phy_write(dev, B43_NPHY_C2_CLIP1_HIGAIN, e->cliplo_gain);
1573	b43_phy_write(dev, 0x2AD, e->cliplo_gain);
1574
1575	b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
1576	b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
1577	b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
1578	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
1579	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
1580	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
1581			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
1582	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
1583			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
1584	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
1585}
1586
1587static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
1588{
1589	struct b43_phy_n *nphy = dev->phy.n;
1590
1591	u8 i, j;
1592	u8 code;
1593	u16 tmp;
1594	u8 rfseq_events[3] = { 6, 8, 7 };
1595	u8 rfseq_delays[3] = { 10, 30, 1 };
1596
1597	/* Set Clip 2 detect */
1598	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
1599	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
1600
1601	/* Set narrowband clip threshold */
1602	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
1603	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
1604
1605	if (!dev->phy.is_40mhz) {
1606		/* Set dwell lengths */
1607		b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
1608		b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
1609		b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
1610		b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
1611	}
1612
1613	/* Set wideband clip 2 threshold */
1614	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
1615			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 21);
1616	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
1617			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
1618
1619	if (!dev->phy.is_40mhz) {
1620		b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
1621			~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
1622		b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
1623			~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
1624		b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
1625			~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
1626		b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
1627			~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
1628	}
1629
1630	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
1631
1632	if (nphy->gain_boost) {
1633		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
1634			dev->phy.is_40mhz)
1635			code = 4;
1636		else
1637			code = 5;
1638	} else {
1639		code = dev->phy.is_40mhz ? 6 : 7;
1640	}
1641
1642	/* Set HPVGA2 index */
1643	b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, ~B43_NPHY_C1_INITGAIN_HPVGA2,
1644			code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
1645	b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, ~B43_NPHY_C2_INITGAIN_HPVGA2,
1646			code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
1647
1648	b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
1649	/* specs say about 2 loops, but wl does 4 */
1650	for (i = 0; i < 4; i++)
1651		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C));
1652
1653	b43_nphy_adjust_lna_gain_table(dev);
1654
1655	if (nphy->elna_gain_config) {
1656		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
1657		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
1658		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1659		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1660		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1661
1662		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
1663		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
1664		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1665		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1666		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1667
1668		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
1669		/* specs say about 2 loops, but wl does 4 */
1670		for (i = 0; i < 4; i++)
1671			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
1672						(code << 8 | 0x74));
1673	}
1674
1675	if (dev->phy.rev == 2) {
1676		for (i = 0; i < 4; i++) {
1677			b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
1678					(0x0400 * i) + 0x0020);
1679			for (j = 0; j < 21; j++) {
1680				tmp = j * (i < 2 ? 3 : 1);
1681				b43_phy_write(dev,
1682					B43_NPHY_TABLE_DATALO, tmp);
1683			}
1684		}
1685	}
1686
1687	b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3);
1688	b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
1689		~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
1690		0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
1691
1692	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
1693		b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4);
1694}
1695
1696/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
1697static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
1698{
1699	if (dev->phy.rev >= 3)
1700		b43_nphy_gain_ctl_workarounds_rev3plus(dev);
1701	else
1702		b43_nphy_gain_ctl_workarounds_rev1_2(dev);
1703}
1704
1705/**************************************************
1706 * Others
1707 **************************************************/
1708
1709void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
1710{//TODO
1711}
1712
1713static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
1714{//TODO
1715}
1716
1717static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
1718							bool ignore_tssi)
1719{//TODO
1720	return B43_TXPWR_RES_DONE;
1721}
1722
1723static void b43_chantab_phy_upload(struct b43_wldev *dev,
1724				   const struct b43_phy_n_sfo_cfg *e)
1725{
1726	b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
1727	b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
1728	b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
1729	b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
1730	b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
1731	b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
1732}
1733
1734/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
1735static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
1736{
1737	struct b43_phy_n *nphy = dev->phy.n;
1738	u8 i;
1739	u16 bmask, val, tmp;
1740	enum ieee80211_band band = b43_current_band(dev->wl);
1741
1742	if (nphy->hang_avoid)
1743		b43_nphy_stay_in_carrier_search(dev, 1);
1744
1745	nphy->txpwrctrl = enable;
1746	if (!enable) {
1747		if (dev->phy.rev >= 3 &&
1748		    (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
1749		     (B43_NPHY_TXPCTL_CMD_COEFF |
1750		      B43_NPHY_TXPCTL_CMD_HWPCTLEN |
1751		      B43_NPHY_TXPCTL_CMD_PCTLEN))) {
1752			/* We disable enabled TX pwr ctl, save it's state */
1753			nphy->tx_pwr_idx[0] = b43_phy_read(dev,
1754						B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
1755			nphy->tx_pwr_idx[1] = b43_phy_read(dev,
1756						B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
1757		}
1758
1759		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
1760		for (i = 0; i < 84; i++)
1761			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
1762
1763		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
1764		for (i = 0; i < 84; i++)
1765			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
1766
1767		tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
1768		if (dev->phy.rev >= 3)
1769			tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;
1770		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
1771
1772		if (dev->phy.rev >= 3) {
1773			b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
1774			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
1775		} else {
1776			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
1777		}
1778
1779		if (dev->phy.rev == 2)
1780			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
1781				~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
1782		else if (dev->phy.rev < 2)
1783			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
1784				~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
1785
1786		if (dev->phy.rev < 2 && dev->phy.is_40mhz)
1787			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
1788	} else {
1789		b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
1790				    nphy->adj_pwr_tbl);
1791		b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
1792				    nphy->adj_pwr_tbl);
1793
1794		bmask = B43_NPHY_TXPCTL_CMD_COEFF |
1795			B43_NPHY_TXPCTL_CMD_HWPCTLEN;
1796		/* wl does useless check for "enable" param here */
1797		val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
1798		if (dev->phy.rev >= 3) {
1799			bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
1800			if (val)
1801				val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
1802		}
1803		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
1804
1805		if (band == IEEE80211_BAND_5GHZ) {
1806			b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
1807					~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
1808			if (dev->phy.rev > 1)
1809				b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
1810						~B43_NPHY_TXPCTL_INIT_PIDXI1,
1811						0x64);
1812		}
1813
1814		if (dev->phy.rev >= 3) {
1815			if (nphy->tx_pwr_idx[0] != 128 &&
1816			    nphy->tx_pwr_idx[1] != 128) {
1817				/* Recover TX pwr ctl state */
1818				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
1819						~B43_NPHY_TXPCTL_CMD_INIT,
1820						nphy->tx_pwr_idx[0]);
1821				if (dev->phy.rev > 1)
1822					b43_phy_maskset(dev,
1823						B43_NPHY_TXPCTL_INIT,
1824						~0xff, nphy->tx_pwr_idx[1]);
1825			}
1826		}
1827
1828		if (dev->phy.rev >= 3) {
1829			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
1830			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
1831		} else {
1832			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
1833		}
1834
1835		if (dev->phy.rev == 2)
1836			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
1837		else if (dev->phy.rev < 2)
1838			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
1839
1840		if (dev->phy.rev < 2 && dev->phy.is_40mhz)
1841			b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
1842
1843		if (b43_nphy_ipa(dev)) {
1844			b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
1845			b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
1846		}
1847	}
1848
1849	if (nphy->hang_avoid)
1850		b43_nphy_stay_in_carrier_search(dev, 0);
1851}
1852
1853/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
1854static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
1855{
1856	struct b43_phy_n *nphy = dev->phy.n;
1857	struct ssb_sprom *sprom = dev->dev->bus_sprom;
1858
1859	u8 txpi[2], bbmult, i;
1860	u16 tmp, radio_gain, dac_gain;
1861	u16 freq = dev->phy.channel_freq;
1862	u32 txgain;
1863	/* u32 gaintbl; rev3+ */
1864
1865	if (nphy->hang_avoid)
1866		b43_nphy_stay_in_carrier_search(dev, 1);
1867
1868	if (dev->phy.rev >= 7) {
1869		txpi[0] = txpi[1] = 30;
1870	} else if (dev->phy.rev >= 3) {
1871		txpi[0] = 40;
1872		txpi[1] = 40;
1873	} else if (sprom->revision < 4) {
1874		txpi[0] = 72;
1875		txpi[1] = 72;
1876	} else {
1877		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1878			txpi[0] = sprom->txpid2g[0];
1879			txpi[1] = sprom->txpid2g[1];
1880		} else if (freq >= 4900 && freq < 5100) {
1881			txpi[0] = sprom->txpid5gl[0];
1882			txpi[1] = sprom->txpid5gl[1];
1883		} else if (freq >= 5100 && freq < 5500) {
1884			txpi[0] = sprom->txpid5g[0];
1885			txpi[1] = sprom->txpid5g[1];
1886		} else if (freq >= 5500) {
1887			txpi[0] = sprom->txpid5gh[0];
1888			txpi[1] = sprom->txpid5gh[1];
1889		} else {
1890			txpi[0] = 91;
1891			txpi[1] = 91;
1892		}
1893	}
1894	if (dev->phy.rev < 7 &&
1895	    (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 10))
1896		txpi[0] = txpi[1] = 91;
1897
1898	/*
1899	for (i = 0; i < 2; i++) {
1900		nphy->txpwrindex[i].index_internal = txpi[i];
1901		nphy->txpwrindex[i].index_internal_save = txpi[i];
1902	}
1903	*/
1904
1905	for (i = 0; i < 2; i++) {
1906		if (dev->phy.rev >= 3) {
1907			if (b43_nphy_ipa(dev)) {
1908				txgain = *(b43_nphy_get_ipa_gain_table(dev) +
1909						txpi[i]);
1910			} else if (b43_current_band(dev->wl) ==
1911				   IEEE80211_BAND_5GHZ) {
1912				/* FIXME: use 5GHz tables */
1913				txgain =
1914					b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
1915			} else {
1916				if (dev->phy.rev >= 5 &&
1917				    sprom->fem.ghz5.extpa_gain == 3)
1918					; /* FIXME: 5GHz_txgain_HiPwrEPA */
1919				txgain =
1920					b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
1921			}
1922			radio_gain = (txgain >> 16) & 0x1FFFF;
1923		} else {
1924			txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]];
1925			radio_gain = (txgain >> 16) & 0x1FFF;
1926		}
1927
1928		if (dev->phy.rev >= 7)
1929			dac_gain = (txgain >> 8) & 0x7;
1930		else
1931			dac_gain = (txgain >> 8) & 0x3F;
1932		bbmult = txgain & 0xFF;
1933
1934		if (dev->phy.rev >= 3) {
1935			if (i == 0)
1936				b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
1937			else
1938				b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
1939		} else {
1940			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
1941		}
1942
1943		if (i == 0)
1944			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
1945		else
1946			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
1947
1948		b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
1949
1950		tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
1951		if (i == 0)
1952			tmp = (tmp & 0x00FF) | (bbmult << 8);
1953		else
1954			tmp = (tmp & 0xFF00) | bbmult;
1955		b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
1956
1957		if (b43_nphy_ipa(dev)) {
1958			u32 tmp32;
1959			u16 reg = (i == 0) ?
1960				B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
1961			tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
1962							      576 + txpi[i]));
1963			b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
1964			b43_phy_set(dev, reg, 0x4);
1965		}
1966	}
1967
1968	b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
1969
1970	if (nphy->hang_avoid)
1971		b43_nphy_stay_in_carrier_search(dev, 0);
1972}
1973
1974static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
1975{
1976	struct b43_phy *phy = &dev->phy;
1977
1978	const u32 *table = NULL;
1979#if 0
1980	TODO: b43_ntab_papd_pga_gain_delta_ipa_2*
1981	u32 rfpwr_offset;
1982	u8 pga_gain;
1983	int i;
1984#endif
1985
1986	if (phy->rev >= 3) {
1987		if (b43_nphy_ipa(dev)) {
1988			table = b43_nphy_get_ipa_gain_table(dev);
1989		} else {
1990			if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
1991				if (phy->rev == 3)
1992					table = b43_ntab_tx_gain_rev3_5ghz;
1993				if (phy->rev == 4)
1994					table = b43_ntab_tx_gain_rev4_5ghz;
1995				else
1996					table = b43_ntab_tx_gain_rev5plus_5ghz;
1997			} else {
1998				table = b43_ntab_tx_gain_rev3plus_2ghz;
1999			}
2000		}
2001	} else {
2002		table = b43_ntab_tx_gain_rev0_1_2;
2003	}
2004	b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
2005	b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
2006
2007	if (phy->rev >= 3) {
2008#if 0
2009		nphy->gmval = (table[0] >> 16) & 0x7000;
2010
2011		for (i = 0; i < 128; i++) {
2012			pga_gain = (table[i] >> 24) & 0xF;
2013			if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2014				rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
2015			else
2016				rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain];
2017			b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
2018				       rfpwr_offset);
2019			b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
2020				       rfpwr_offset);
2021		}
2022#endif
2023	}
2024}
2025
2026/*
2027 * Upload the N-PHY tables.
2028 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
2029 */
2030static void b43_nphy_tables_init(struct b43_wldev *dev)
2031{
2032	if (dev->phy.rev < 3)
2033		b43_nphy_rev0_1_2_tables_init(dev);
2034	else
2035		b43_nphy_rev3plus_tables_init(dev);
2036}
2037
2038/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
2039static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
2040{
2041	struct b43_phy_n *nphy = dev->phy.n;
2042	enum ieee80211_band band;
2043	u16 tmp;
2044
2045	if (!enable) {
2046		nphy->rfctrl_intc1_save = b43_phy_read(dev,
2047						       B43_NPHY_RFCTL_INTC1);
2048		nphy->rfctrl_intc2_save = b43_phy_read(dev,
2049						       B43_NPHY_RFCTL_INTC2);
2050		band = b43_current_band(dev->wl);
2051		if (dev->phy.rev >= 3) {
2052			if (band == IEEE80211_BAND_5GHZ)
2053				tmp = 0x600;
2054			else
2055				tmp = 0x480;
2056		} else {
2057			if (band == IEEE80211_BAND_5GHZ)
2058				tmp = 0x180;
2059			else
2060				tmp = 0x120;
2061		}
2062		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
2063		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
2064	} else {
2065		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
2066				nphy->rfctrl_intc1_save);
2067		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
2068				nphy->rfctrl_intc2_save);
2069	}
2070}
2071
2072/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
2073static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
2074{
2075	u16 tmp;
2076
2077	if (dev->phy.rev >= 3) {
2078		if (b43_nphy_ipa(dev)) {
2079			tmp = 4;
2080			b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
2081			      (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
2082		}
2083
2084		tmp = 1;
2085		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
2086			      (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
2087	}
2088}
2089
2090/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
2091static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
2092{
2093	u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
2094
2095	mimocfg |= B43_NPHY_MIMOCFG_AUTO;
2096	if (preamble == 1)
2097		mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
2098	else
2099		mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
2100
2101	b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
2102}
2103
2104/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
2105static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
2106{
2107	struct b43_phy_n *nphy = dev->phy.n;
2108
2109	bool override = false;
2110	u16 chain = 0x33;
2111
2112	if (nphy->txrx_chain == 0) {
2113		chain = 0x11;
2114		override = true;
2115	} else if (nphy->txrx_chain == 1) {
2116		chain = 0x22;
2117		override = true;
2118	}
2119
2120	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
2121			~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
2122			chain);
2123
2124	if (override)
2125		b43_phy_set(dev, B43_NPHY_RFSEQMODE,
2126				B43_NPHY_RFSEQMODE_CAOVER);
2127	else
2128		b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
2129				~B43_NPHY_RFSEQMODE_CAOVER);
2130}
2131
2132/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
2133static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
2134				u16 samps, u8 time, bool wait)
2135{
2136	int i;
2137	u16 tmp;
2138
2139	b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
2140	b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
2141	if (wait)
2142		b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
2143	else
2144		b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
2145
2146	b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
2147
2148	for (i = 1000; i; i--) {
2149		tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
2150		if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
2151			est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
2152					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
2153			est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
2154					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
2155			est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
2156					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
2157
2158			est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
2159					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
2160			est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
2161					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
2162			est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
2163					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
2164			return;
2165		}
2166		udelay(10);
2167	}
2168	memset(est, 0, sizeof(*est));
2169}
2170
2171/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
2172static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
2173					struct b43_phy_n_iq_comp *pcomp)
2174{
2175	if (write) {
2176		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
2177		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
2178		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
2179		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
2180	} else {
2181		pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
2182		pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
2183		pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
2184		pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
2185	}
2186}
2187
2188#if 0
2189/* Ready but not used anywhere */
2190/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
2191static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
2192{
2193	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
2194
2195	b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
2196	if (core == 0) {
2197		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
2198		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
2199	} else {
2200		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
2201		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
2202	}
2203	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
2204	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
2205	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
2206	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
2207	b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
2208	b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
2209	b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
2210	b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
2211}
2212
2213/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
2214static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
2215{
2216	u8 rxval, txval;
2217	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
2218
2219	regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
2220	if (core == 0) {
2221		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
2222		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
2223	} else {
2224		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
2225		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
2226	}
2227	regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
2228	regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
2229	regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
2230	regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
2231	regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
2232	regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
2233	regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
2234	regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
2235
2236	b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
2237	b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
2238
2239	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
2240			~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
2241			((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
2242	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
2243			((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
2244	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
2245			(core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
2246	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
2247			(core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
2248
2249	if (core == 0) {
2250		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
2251		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
2252	} else {
2253		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
2254		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
2255	}
2256
2257	b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
2258	b43_nphy_rf_control_override(dev, 8, 0, 3, false);
2259	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
2260
2261	if (core == 0) {
2262		rxval = 1;
2263		txval = 8;
2264	} else {
2265		rxval = 4;
2266		txval = 2;
2267	}
2268	b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
2269	b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
2270}
2271#endif
2272
2273/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
2274static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
2275{
2276	int i;
2277	s32 iq;
2278	u32 ii;
2279	u32 qq;
2280	int iq_nbits, qq_nbits;
2281	int arsh, brsh;
2282	u16 tmp, a, b;
2283
2284	struct nphy_iq_est est;
2285	struct b43_phy_n_iq_comp old;
2286	struct b43_phy_n_iq_comp new = { };
2287	bool error = false;
2288
2289	if (mask == 0)
2290		return;
2291
2292	b43_nphy_rx_iq_coeffs(dev, false, &old);
2293	b43_nphy_rx_iq_coeffs(dev, true, &new);
2294	b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
2295	new = old;
2296
2297	for (i = 0; i < 2; i++) {
2298		if (i == 0 && (mask & 1)) {
2299			iq = est.iq0_prod;
2300			ii = est.i0_pwr;
2301			qq = est.q0_pwr;
2302		} else if (i == 1 && (mask & 2)) {
2303			iq = est.iq1_prod;
2304			ii = est.i1_pwr;
2305			qq = est.q1_pwr;
2306		} else {
2307			continue;
2308		}
2309
2310		if (ii + qq < 2) {
2311			error = true;
2312			break;
2313		}
2314
2315		iq_nbits = fls(abs(iq));
2316		qq_nbits = fls(qq);
2317
2318		arsh = iq_nbits - 20;
2319		if (arsh >= 0) {
2320			a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
2321			tmp = ii >> arsh;
2322		} else {
2323			a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
2324			tmp = ii << -arsh;
2325		}
2326		if (tmp == 0) {
2327			error = true;
2328			break;
2329		}
2330		a /= tmp;
2331
2332		brsh = qq_nbits - 11;
2333		if (brsh >= 0) {
2334			b = (qq << (31 - qq_nbits));
2335			tmp = ii >> brsh;
2336		} else {
2337			b = (qq << (31 - qq_nbits));
2338			tmp = ii << -brsh;
2339		}
2340		if (tmp == 0) {
2341			error = true;
2342			break;
2343		}
2344		b = int_sqrt(b / tmp - a * a) - (1 << 10);
2345
2346		if (i == 0 && (mask & 0x1)) {
2347			if (dev->phy.rev >= 3) {
2348				new.a0 = a & 0x3FF;
2349				new.b0 = b & 0x3FF;
2350			} else {
2351				new.a0 = b & 0x3FF;
2352				new.b0 = a & 0x3FF;
2353			}
2354		} else if (i == 1 && (mask & 0x2)) {
2355			if (dev->phy.rev >= 3) {
2356				new.a1 = a & 0x3FF;
2357				new.b1 = b & 0x3FF;
2358			} else {
2359				new.a1 = b & 0x3FF;
2360				new.b1 = a & 0x3FF;
2361			}
2362		}
2363	}
2364
2365	if (error)
2366		new = old;
2367
2368	b43_nphy_rx_iq_coeffs(dev, true, &new);
2369}
2370
2371/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
2372static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
2373{
2374	u16 array[4];
2375	b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
2376
2377	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
2378	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
2379	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
2380	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
2381}
2382
2383/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
2384static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
2385{
2386	if (dev->phy.rev >= 3) {
2387		if (!init)
2388			return;
2389		if (0 /* FIXME */) {
2390			b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
2391			b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
2392			b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
2393			b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
2394		}
2395	} else {
2396		b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
2397		b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
2398
2399		switch (dev->dev->bus_type) {
2400#ifdef CONFIG_B43_BCMA
2401		case B43_BUS_BCMA:
2402			bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
2403						 0xFC00, 0xFC00);
2404			break;
2405#endif
2406#ifdef CONFIG_B43_SSB
2407		case B43_BUS_SSB:
2408			ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
2409						0xFC00, 0xFC00);
2410			break;
2411#endif
2412		}
2413
2414		b43_write32(dev, B43_MMIO_MACCTL,
2415			b43_read32(dev, B43_MMIO_MACCTL) &
2416			~B43_MACCTL_GPOUTSMSK);
2417		b43_write16(dev, B43_MMIO_GPIO_MASK,
2418			b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00);
2419		b43_write16(dev, B43_MMIO_GPIO_CONTROL,
2420			b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00);
2421
2422		if (init) {
2423			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
2424			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
2425			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
2426			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
2427		}
2428	}
2429}
2430
2431/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
2432static void b43_nphy_stop_playback(struct b43_wldev *dev)
2433{
2434	struct b43_phy_n *nphy = dev->phy.n;
2435	u16 tmp;
2436
2437	if (nphy->hang_avoid)
2438		b43_nphy_stay_in_carrier_search(dev, 1);
2439
2440	tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
2441	if (tmp & 0x1)
2442		b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
2443	else if (tmp & 0x2)
2444		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
2445
2446	b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
2447
2448	if (nphy->bb_mult_save & 0x80000000) {
2449		tmp = nphy->bb_mult_save & 0xFFFF;
2450		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
2451		nphy->bb_mult_save = 0;
2452	}
2453
2454	if (nphy->hang_avoid)
2455		b43_nphy_stay_in_carrier_search(dev, 0);
2456}
2457
2458/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
2459static void b43_nphy_spur_workaround(struct b43_wldev *dev)
2460{
2461	struct b43_phy_n *nphy = dev->phy.n;
2462
2463	u8 channel = dev->phy.channel;
2464	int tone[2] = { 57, 58 };
2465	u32 noise[2] = { 0x3FF, 0x3FF };
2466
2467	B43_WARN_ON(dev->phy.rev < 3);
2468
2469	if (nphy->hang_avoid)
2470		b43_nphy_stay_in_carrier_search(dev, 1);
2471
2472	if (nphy->gband_spurwar_en) {
2473		/* TODO: N PHY Adjust Analog Pfbw (7) */
2474		if (channel == 11 && dev->phy.is_40mhz)
2475			; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
2476		else
2477			; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
2478		/* TODO: N PHY Adjust CRS Min Power (0x1E) */
2479	}
2480
2481	if (nphy->aband_spurwar_en) {
2482		if (channel == 54) {
2483			tone[0] = 0x20;
2484			noise[0] = 0x25F;
2485		} else if (channel == 38 || channel == 102 || channel == 118) {
2486			if (0 /* FIXME */) {
2487				tone[0] = 0x20;
2488				noise[0] = 0x21F;
2489			} else {
2490				tone[0] = 0;
2491				noise[0] = 0;
2492			}
2493		} else if (channel == 134) {
2494			tone[0] = 0x20;
2495			noise[0] = 0x21F;
2496		} else if (channel == 151) {
2497			tone[0] = 0x10;
2498			noise[0] = 0x23F;
2499		} else if (channel == 153 || channel == 161) {
2500			tone[0] = 0x30;
2501			noise[0] = 0x23F;
2502		} else {
2503			tone[0] = 0;
2504			noise[0] = 0;
2505		}
2506
2507		if (!tone[0] && !noise[0])
2508			; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
2509		else
2510			; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
2511	}
2512
2513	if (nphy->hang_avoid)
2514		b43_nphy_stay_in_carrier_search(dev, 0);
2515}
2516
2517static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
2518{
2519	struct b43_phy_n *nphy = dev->phy.n;
2520	struct ssb_sprom *sprom = dev->dev->bus_sprom;
2521
2522	/* TX to RX */
2523	u8 tx2rx_events[8] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
2524	u8 tx2rx_delays[8] = { 8, 4, 2, 2, 4, 4, 6, 1 };
2525	/* RX to TX */
2526	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
2527					0x1F };
2528	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
2529	u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
2530	u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
2531
2532	u16 tmp16;
2533	u32 tmp32;
2534
2535	b43_phy_write(dev, 0x23f, 0x1f8);
2536	b43_phy_write(dev, 0x240, 0x1f8);
2537
2538	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
2539	tmp32 &= 0xffffff;
2540	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
2541
2542	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
2543	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
2544	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
2545	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
2546	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
2547	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
2548
2549	b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
2550	b43_phy_write(dev, 0x2AE, 0x000C);
2551
2552	/* TX to RX */
2553	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
2554				 ARRAY_SIZE(tx2rx_events));
2555
2556	/* RX to TX */
2557	if (b43_nphy_ipa(dev))
2558		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
2559				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
2560	if (nphy->hw_phyrxchain != 3 &&
2561	    nphy->hw_phyrxchain != nphy->hw_phytxchain) {
2562		if (b43_nphy_ipa(dev)) {
2563			rx2tx_delays[5] = 59;
2564			rx2tx_delays[6] = 1;
2565			rx2tx_events[7] = 0x1F;
2566		}
2567		b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays,
2568					 ARRAY_SIZE(rx2tx_events));
2569	}
2570
2571	tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
2572		0x2 : 0x9C40;
2573	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
2574
2575	b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
2576
2577	b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
2578	b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
2579
2580	b43_nphy_gain_ctl_workarounds(dev);
2581
2582	b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
2583	b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
2584
2585	/* TODO */
2586
2587	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
2588	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
2589	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
2590	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
2591	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
2592	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
2593	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
2594	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
2595	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
2596	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
2597	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
2598	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
2599
2600	/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
2601
2602	if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
2603	     b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
2604	    (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
2605	     b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
2606		tmp32 = 0x00088888;
2607	else
2608		tmp32 = 0x88888888;
2609	b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
2610	b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
2611	b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
2612
2613	if (dev->phy.rev == 4 &&
2614		b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2615		b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
2616				0x70);
2617		b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
2618				0x70);
2619	}
2620
2621	b43_phy_write(dev, 0x224, 0x03eb);
2622	b43_phy_write(dev, 0x225, 0x03eb);
2623	b43_phy_write(dev, 0x226, 0x0341);
2624	b43_phy_write(dev, 0x227, 0x0341);
2625	b43_phy_write(dev, 0x228, 0x042b);
2626	b43_phy_write(dev, 0x229, 0x042b);
2627	b43_phy_write(dev, 0x22a, 0x0381);
2628	b43_phy_write(dev, 0x22b, 0x0381);
2629	b43_phy_write(dev, 0x22c, 0x042b);
2630	b43_phy_write(dev, 0x22d, 0x042b);
2631	b43_phy_write(dev, 0x22e, 0x0381);
2632	b43_phy_write(dev, 0x22f, 0x0381);
2633}
2634
2635static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
2636{
2637	struct ssb_sprom *sprom = dev->dev->bus_sprom;
2638	struct b43_phy *phy = &dev->phy;
2639	struct b43_phy_n *nphy = phy->n;
2640
2641	u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
2642	u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
2643
2644	u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
2645	u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
2646
2647	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
2648	    nphy->band5g_pwrgain) {
2649		b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
2650		b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
2651	} else {
2652		b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
2653		b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
2654	}
2655
2656	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
2657	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
2658	b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
2659	b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
2660
2661	if (dev->phy.rev < 2) {
2662		b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
2663		b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
2664		b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
2665		b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
2666		b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
2667		b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
2668	}
2669
2670	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
2671	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
2672	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
2673	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
2674
2675	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD &&
2676	    dev->dev->board_type == 0x8B) {
2677		delays1[0] = 0x1;
2678		delays1[5] = 0x14;
2679	}
2680	b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
2681	b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
2682
2683	b43_nphy_gain_ctl_workarounds(dev);
2684
2685	if (dev->phy.rev < 2) {
2686		if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
2687			b43_hf_write(dev, b43_hf_read(dev) |
2688					B43_HF_MLADVW);
2689	} else if (dev->phy.rev == 2) {
2690		b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
2691		b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
2692	}
2693
2694	if (dev->phy.rev < 2)
2695		b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
2696				~B43_NPHY_SCRAM_SIGCTL_SCM);
2697
2698	/* Set phase track alpha and beta */
2699	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
2700	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
2701	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
2702	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
2703	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
2704	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
2705
2706	b43_phy_mask(dev, B43_NPHY_PIL_DW1,
2707			~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
2708	b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
2709	b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
2710	b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
2711
2712	if (dev->phy.rev == 2)
2713		b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
2714				B43_NPHY_FINERX2_CGC_DECGC);
2715}
2716
2717/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
2718static void b43_nphy_workarounds(struct b43_wldev *dev)
2719{
2720	struct b43_phy *phy = &dev->phy;
2721	struct b43_phy_n *nphy = phy->n;
2722
2723	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
2724		b43_nphy_classifier(dev, 1, 0);
2725	else
2726		b43_nphy_classifier(dev, 1, 1);
2727
2728	if (nphy->hang_avoid)
2729		b43_nphy_stay_in_carrier_search(dev, 1);
2730
2731	b43_phy_set(dev, B43_NPHY_IQFLIP,
2732		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
2733
2734	if (dev->phy.rev >= 3)
2735		b43_nphy_workarounds_rev3plus(dev);
2736	else
2737		b43_nphy_workarounds_rev1_2(dev);
2738
2739	if (nphy->hang_avoid)
2740		b43_nphy_stay_in_carrier_search(dev, 0);
2741}
2742
2743/*
2744 * Transmits a known value for LO calibration
2745 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
2746 */
2747static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
2748				bool iqmode, bool dac_test)
2749{
2750	u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
2751	if (samp == 0)
2752		return -1;
2753	b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
2754	return 0;
2755}
2756
2757/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
2758static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
2759{
2760	struct b43_phy_n *nphy = dev->phy.n;
2761	int i, j;
2762	u32 tmp;
2763	u32 cur_real, cur_imag, real_part, imag_part;
2764
2765	u16 buffer[7];
2766
2767	if (nphy->hang_avoid)
2768		b43_nphy_stay_in_carrier_search(dev, true);
2769
2770	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
2771
2772	for (i = 0; i < 2; i++) {
2773		tmp = ((buffer[i * 2] & 0x3FF) << 10) |
2774			(buffer[i * 2 + 1] & 0x3FF);
2775		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
2776				(((i + 26) << 10) | 320));
2777		for (j = 0; j < 128; j++) {
2778			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
2779					((tmp >> 16) & 0xFFFF));
2780			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
2781					(tmp & 0xFFFF));
2782		}
2783	}
2784
2785	for (i = 0; i < 2; i++) {
2786		tmp = buffer[5 + i];
2787		real_part = (tmp >> 8) & 0xFF;
2788		imag_part = (tmp & 0xFF);
2789		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
2790				(((i + 26) << 10) | 448));
2791
2792		if (dev->phy.rev >= 3) {
2793			cur_real = real_part;
2794			cur_imag = imag_part;
2795			tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
2796		}
2797
2798		for (j = 0; j < 128; j++) {
2799			if (dev->phy.rev < 3) {
2800				cur_real = (real_part * loscale[j] + 128) >> 8;
2801				cur_imag = (imag_part * loscale[j] + 128) >> 8;
2802				tmp = ((cur_real & 0xFF) << 8) |
2803					(cur_imag & 0xFF);
2804			}
2805			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
2806					((tmp >> 16) & 0xFFFF));
2807			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
2808					(tmp & 0xFFFF));
2809		}
2810	}
2811
2812	if (dev->phy.rev >= 3) {
2813		b43_shm_write16(dev, B43_SHM_SHARED,
2814				B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
2815		b43_shm_write16(dev, B43_SHM_SHARED,
2816				B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
2817	}
2818
2819	if (nphy->hang_avoid)
2820		b43_nphy_stay_in_carrier_search(dev, false);
2821}
2822
2823/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
2824static void b43_nphy_bphy_init(struct b43_wldev *dev)
2825{
2826	unsigned int i;
2827	u16 val;
2828
2829	val = 0x1E1F;
2830	for (i = 0; i < 16; i++) {
2831		b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
2832		val -= 0x202;
2833	}
2834	val = 0x3E3F;
2835	for (i = 0; i < 16; i++) {
2836		b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
2837		val -= 0x202;
2838	}
2839	b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
2840}
2841
2842/*
2843 * Restore RSSI Calibration
2844 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
2845 */
2846static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
2847{
2848	struct b43_phy_n *nphy = dev->phy.n;
2849
2850	u16 *rssical_radio_regs = NULL;
2851	u16 *rssical_phy_regs = NULL;
2852
2853	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2854		if (!nphy->rssical_chanspec_2G.center_freq)
2855			return;
2856		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
2857		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
2858	} else {
2859		if (!nphy->rssical_chanspec_5G.center_freq)
2860			return;
2861		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
2862		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
2863	}
2864
2865	/* TODO use some definitions */
2866	b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
2867	b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
2868
2869	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
2870	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
2871	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
2872	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
2873
2874	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
2875	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
2876	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
2877	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
2878
2879	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
2880	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
2881	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
2882	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
2883}
2884
2885/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
2886static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
2887{
2888	struct b43_phy_n *nphy = dev->phy.n;
2889	u16 *save = nphy->tx_rx_cal_radio_saveregs;
2890	u16 tmp;
2891	u8 offset, i;
2892
2893	if (dev->phy.rev >= 3) {
2894	    for (i = 0; i < 2; i++) {
2895		tmp = (i == 0) ? 0x2000 : 0x3000;
2896		offset = i * 11;
2897
2898		save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
2899		save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
2900		save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
2901		save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
2902		save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
2903		save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
2904		save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
2905		save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
2906		save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
2907		save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
2908		save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
2909
2910		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2911			b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
2912			b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
2913			b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
2914			b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
2915			b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
2916			if (nphy->ipa5g_on) {
2917				b43_radio_write16(dev, tmp | B2055_PADDRV, 4);
2918				b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
2919			} else {
2920				b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
2921				b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
2922			}
2923			b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
2924		} else {
2925			b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
2926			b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
2927			b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
2928			b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
2929			b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
2930			b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
2931			if (nphy->ipa2g_on) {
2932				b43_radio_write16(dev, tmp | B2055_PADDRV, 6);
2933				b43_radio_write16(dev, tmp | B2055_XOCTL2,
2934					(dev->phy.rev < 5) ? 0x11 : 0x01);
2935			} else {
2936				b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
2937				b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
2938			}
2939		}
2940		b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
2941		b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
2942		b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0);
2943	    }
2944	} else {
2945		save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
2946		b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
2947
2948		save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2);
2949		b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
2950
2951		save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1);
2952		b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
2953
2954		save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2);
2955		b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
2956
2957		save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX);
2958		save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
2959
2960		if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
2961		    B43_NPHY_BANDCTL_5GHZ)) {
2962			b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04);
2963			b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04);
2964		} else {
2965			b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20);
2966			b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20);
2967		}
2968
2969		if (dev->phy.rev < 2) {
2970			b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
2971			b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
2972		} else {
2973			b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
2974			b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
2975		}
2976	}
2977}
2978
2979/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
2980static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
2981					struct nphy_txgains target,
2982					struct nphy_iqcal_params *params)
2983{
2984	int i, j, indx;
2985	u16 gain;
2986
2987	if (dev->phy.rev >= 3) {
2988		params->txgm = target.txgm[core];
2989		params->pga = target.pga[core];
2990		params->pad = target.pad[core];
2991		params->ipa = target.ipa[core];
2992		params->cal_gain = (params->txgm << 12) | (params->pga << 8) |
2993					(params->pad << 4) | (params->ipa);
2994		for (j = 0; j < 5; j++)
2995			params->ncorr[j] = 0x79;
2996	} else {
2997		gain = (target.pad[core]) | (target.pga[core] << 4) |
2998			(target.txgm[core] << 8);
2999
3000		indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ?
3001			1 : 0;
3002		for (i = 0; i < 9; i++)
3003			if (tbl_iqcal_gainparams[indx][i][0] == gain)
3004				break;
3005		i = min(i, 8);
3006
3007		params->txgm = tbl_iqcal_gainparams[indx][i][1];
3008		params->pga = tbl_iqcal_gainparams[indx][i][2];
3009		params->pad = tbl_iqcal_gainparams[indx][i][3];
3010		params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
3011					(params->pad << 2);
3012		for (j = 0; j < 4; j++)
3013			params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
3014	}
3015}
3016
3017/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
3018static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
3019{
3020	struct b43_phy_n *nphy = dev->phy.n;
3021	int i;
3022	u16 scale, entry;
3023
3024	u16 tmp = nphy->txcal_bbmult;
3025	if (core == 0)
3026		tmp >>= 8;
3027	tmp &= 0xff;
3028
3029	for (i = 0; i < 18; i++) {
3030		scale = (ladder_lo[i].percent * tmp) / 100;
3031		entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
3032		b43_ntab_write(dev, B43_NTAB16(15, i), entry);
3033
3034		scale = (ladder_iq[i].percent * tmp) / 100;
3035		entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
3036		b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
3037	}
3038}
3039
3040/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
3041static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
3042{
3043	int i;
3044	for (i = 0; i < 15; i++)
3045		b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
3046				tbl_tx_filter_coef_rev4[2][i]);
3047}
3048
3049/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
3050static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
3051{
3052	int i, j;
3053	/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
3054	static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
3055
3056	for (i = 0; i < 3; i++)
3057		for (j = 0; j < 15; j++)
3058			b43_phy_write(dev, B43_PHY_N(offset[i] + j),
3059					tbl_tx_filter_coef_rev4[i][j]);
3060
3061	if (dev->phy.is_40mhz) {
3062		for (j = 0; j < 15; j++)
3063			b43_phy_write(dev, B43_PHY_N(offset[0] + j),
3064					tbl_tx_filter_coef_rev4[3][j]);
3065	} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
3066		for (j = 0; j < 15; j++)
3067			b43_phy_write(dev, B43_PHY_N(offset[0] + j),
3068					tbl_tx_filter_coef_rev4[5][j]);
3069	}
3070
3071	if (dev->phy.channel == 14)
3072		for (j = 0; j < 15; j++)
3073			b43_phy_write(dev, B43_PHY_N(offset[0] + j),
3074					tbl_tx_filter_coef_rev4[6][j]);
3075}
3076
3077/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
3078static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
3079{
3080	struct b43_phy_n *nphy = dev->phy.n;
3081
3082	u16 curr_gain[2];
3083	struct nphy_txgains target;
3084	const u32 *table = NULL;
3085
3086	if (!nphy->txpwrctrl) {
3087		int i;
3088
3089		if (nphy->hang_avoid)
3090			b43_nphy_stay_in_carrier_search(dev, true);
3091		b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
3092		if (nphy->hang_avoid)
3093			b43_nphy_stay_in_carrier_search(dev, false);
3094
3095		for (i = 0; i < 2; ++i) {
3096			if (dev->phy.rev >= 3) {
3097				target.ipa[i] = curr_gain[i] & 0x000F;
3098				target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
3099				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
3100				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
3101			} else {
3102				target.ipa[i] = curr_gain[i] & 0x0003;
3103				target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
3104				target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
3105				target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
3106			}
3107		}
3108	} else {
3109		int i;
3110		u16 index[2];
3111		index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
3112			B43_NPHY_TXPCTL_STAT_BIDX) >>
3113			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
3114		index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
3115			B43_NPHY_TXPCTL_STAT_BIDX) >>
3116			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
3117
3118		for (i = 0; i < 2; ++i) {
3119			if (dev->phy.rev >= 3) {
3120				enum ieee80211_band band =
3121					b43_current_band(dev->wl);
3122
3123				if (b43_nphy_ipa(dev)) {
3124					table = b43_nphy_get_ipa_gain_table(dev);
3125				} else {
3126					if (band == IEEE80211_BAND_5GHZ) {
3127						if (dev->phy.rev == 3)
3128							table = b43_ntab_tx_gain_rev3_5ghz;
3129						else if (dev->phy.rev == 4)
3130							table = b43_ntab_tx_gain_rev4_5ghz;
3131						else
3132							table = b43_ntab_tx_gain_rev5plus_5ghz;
3133					} else {
3134						table = b43_ntab_tx_gain_rev3plus_2ghz;
3135					}
3136				}
3137
3138				target.ipa[i] = (table[index[i]] >> 16) & 0xF;
3139				target.pad[i] = (table[index[i]] >> 20) & 0xF;
3140				target.pga[i] = (table[index[i]] >> 24) & 0xF;
3141				target.txgm[i] = (table[index[i]] >> 28) & 0xF;
3142			} else {
3143				table = b43_ntab_tx_gain_rev0_1_2;
3144
3145				target.ipa[i] = (table[index[i]] >> 16) & 0x3;
3146				target.pad[i] = (table[index[i]] >> 18) & 0x3;
3147				target.pga[i] = (table[index[i]] >> 20) & 0x7;
3148				target.txgm[i] = (table[index[i]] >> 23) & 0x7;
3149			}
3150		}
3151	}
3152
3153	return target;
3154}
3155
3156/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
3157static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
3158{
3159	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
3160
3161	if (dev->phy.rev >= 3) {
3162		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
3163		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
3164		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
3165		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
3166		b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
3167		b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
3168		b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
3169		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
3170		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
3171		b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
3172		b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
3173		b43_nphy_reset_cca(dev);
3174	} else {
3175		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
3176		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
3177		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
3178		b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
3179		b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
3180		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
3181		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
3182	}
3183}
3184
3185/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
3186static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
3187{
3188	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
3189	u16 tmp;
3190
3191	regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
3192	regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
3193	if (dev->phy.rev >= 3) {
3194		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
3195		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
3196
3197		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
3198		regs[2] = tmp;
3199		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
3200
3201		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
3202		regs[3] = tmp;
3203		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
3204
3205		regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
3206		b43_phy_mask(dev, B43_NPHY_BBCFG,
3207			     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
3208
3209		tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
3210		regs[5] = tmp;
3211		b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
3212
3213		tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
3214		regs[6] = tmp;
3215		b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
3216		regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
3217		regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
3218
3219		b43_nphy_rf_control_intc_override(dev, 2, 1, 3);
3220		b43_nphy_rf_control_intc_override(dev, 1, 2, 1);
3221		b43_nphy_rf_control_intc_override(dev, 1, 8, 2);
3222
3223		regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
3224		regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
3225		b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
3226		b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
3227	} else {
3228		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
3229		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
3230		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
3231		regs[2] = tmp;
3232		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
3233		tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
3234		regs[3] = tmp;
3235		tmp |= 0x2000;
3236		b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
3237		tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
3238		regs[4] = tmp;
3239		tmp |= 0x2000;
3240		b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
3241		regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
3242		regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
3243		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
3244			tmp = 0x0180;
3245		else
3246			tmp = 0x0120;
3247		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
3248		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
3249	}
3250}
3251
3252/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
3253static void b43_nphy_save_cal(struct b43_wldev *dev)
3254{
3255	struct b43_phy_n *nphy = dev->phy.n;
3256
3257	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
3258	u16 *txcal_radio_regs = NULL;
3259	struct b43_chanspec *iqcal_chanspec;
3260	u16 *table = NULL;
3261
3262	if (nphy->hang_avoid)
3263		b43_nphy_stay_in_carrier_search(dev, 1);
3264
3265	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3266		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
3267		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
3268		iqcal_chanspec = &nphy->iqcal_chanspec_2G;
3269		table = nphy->cal_cache.txcal_coeffs_2G;
3270	} else {
3271		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
3272		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
3273		iqcal_chanspec = &nphy->iqcal_chanspec_5G;
3274		table = nphy->cal_cache.txcal_coeffs_5G;
3275	}
3276
3277	b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
3278	/* TODO use some definitions */
3279	if (dev->phy.rev >= 3) {
3280		txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
3281		txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
3282		txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
3283		txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);
3284		txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);
3285		txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);
3286		txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);
3287		txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);
3288	} else {
3289		txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);
3290		txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);
3291		txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
3292		txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
3293	}
3294	iqcal_chanspec->center_freq = dev->phy.channel_freq;
3295	iqcal_chanspec->channel_type = dev->phy.channel_type;
3296	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
3297
3298	if (nphy->hang_avoid)
3299		b43_nphy_stay_in_carrier_search(dev, 0);
3300}
3301
3302/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
3303static void b43_nphy_restore_cal(struct b43_wldev *dev)
3304{
3305	struct b43_phy_n *nphy = dev->phy.n;
3306
3307	u16 coef[4];
3308	u16 *loft = NULL;
3309	u16 *table = NULL;
3310
3311	int i;
3312	u16 *txcal_radio_regs = NULL;
3313	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
3314
3315	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3316		if (!nphy->iqcal_chanspec_2G.center_freq)
3317			return;
3318		table = nphy->cal_cache.txcal_coeffs_2G;
3319		loft = &nphy->cal_cache.txcal_coeffs_2G[5];
3320	} else {
3321		if (!nphy->iqcal_chanspec_5G.center_freq)
3322			return;
3323		table = nphy->cal_cache.txcal_coeffs_5G;
3324		loft = &nphy->cal_cache.txcal_coeffs_5G[5];
3325	}
3326
3327	b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
3328
3329	for (i = 0; i < 4; i++) {
3330		if (dev->phy.rev >= 3)
3331			table[i] = coef[i];
3332		else
3333			coef[i] = 0;
3334	}
3335
3336	b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
3337	b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
3338	b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
3339
3340	if (dev->phy.rev < 2)
3341		b43_nphy_tx_iq_workaround(dev);
3342
3343	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3344		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
3345		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
3346	} else {
3347		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
3348		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
3349	}
3350
3351	/* TODO use some definitions */
3352	if (dev->phy.rev >= 3) {
3353		b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
3354		b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
3355		b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
3356		b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
3357		b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
3358		b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
3359		b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
3360		b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
3361	} else {
3362		b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
3363		b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
3364		b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
3365		b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
3366	}
3367	b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
3368}
3369
3370/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
3371static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
3372				struct nphy_txgains target,
3373				bool full, bool mphase)
3374{
3375	struct b43_phy_n *nphy = dev->phy.n;
3376	int i;
3377	int error = 0;
3378	int freq;
3379	bool avoid = false;
3380	u8 length;
3381	u16 tmp, core, type, count, max, numb, last = 0, cmd;
3382	const u16 *table;
3383	bool phy6or5x;
3384
3385	u16 buffer[11];
3386	u16 diq_start = 0;
3387	u16 save[2];
3388	u16 gain[2];
3389	struct nphy_iqcal_params params[2];
3390	bool updated[2] = { };
3391
3392	b43_nphy_stay_in_carrier_search(dev, true);
3393
3394	if (dev->phy.rev >= 4) {
3395		avoid = nphy->hang_avoid;
3396		nphy->hang_avoid = 0;
3397	}
3398
3399	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
3400
3401	for (i = 0; i < 2; i++) {
3402		b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
3403		gain[i] = params[i].cal_gain;
3404	}
3405
3406	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
3407
3408	b43_nphy_tx_cal_radio_setup(dev);
3409	b43_nphy_tx_cal_phy_setup(dev);
3410
3411	phy6or5x = dev->phy.rev >= 6 ||
3412		(dev->phy.rev == 5 && nphy->ipa2g_on &&
3413		b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
3414	if (phy6or5x) {
3415		if (dev->phy.is_40mhz) {
3416			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
3417					tbl_tx_iqlo_cal_loft_ladder_40);
3418			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
3419					tbl_tx_iqlo_cal_iqimb_ladder_40);
3420		} else {
3421			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
3422					tbl_tx_iqlo_cal_loft_ladder_20);
3423			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
3424					tbl_tx_iqlo_cal_iqimb_ladder_20);
3425		}
3426	}
3427
3428	b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
3429
3430	if (!dev->phy.is_40mhz)
3431		freq = 2500;
3432	else
3433		freq = 5000;
3434
3435	if (nphy->mphase_cal_phase_id > 2)
3436		b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8,
3437					0xFFFF, 0, true, false);
3438	else
3439		error = b43_nphy_tx_tone(dev, freq, 250, true, false);
3440
3441	if (error == 0) {
3442		if (nphy->mphase_cal_phase_id > 2) {
3443			table = nphy->mphase_txcal_bestcoeffs;
3444			length = 11;
3445			if (dev->phy.rev < 3)
3446				length -= 2;
3447		} else {
3448			if (!full && nphy->txiqlocal_coeffsvalid) {
3449				table = nphy->txiqlocal_bestc;
3450				length = 11;
3451				if (dev->phy.rev < 3)
3452					length -= 2;
3453			} else {
3454				full = true;
3455				if (dev->phy.rev >= 3) {
3456					table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
3457					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
3458				} else {
3459					table = tbl_tx_iqlo_cal_startcoefs;
3460					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;
3461				}
3462			}
3463		}
3464
3465		b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
3466
3467		if (full) {
3468			if (dev->phy.rev >= 3)
3469				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
3470			else
3471				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
3472		} else {
3473			if (dev->phy.rev >= 3)
3474				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
3475			else
3476				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;
3477		}
3478
3479		if (mphase) {
3480			count = nphy->mphase_txcal_cmdidx;
3481			numb = min(max,
3482				(u16)(count + nphy->mphase_txcal_numcmds));
3483		} else {
3484			count = 0;
3485			numb = max;
3486		}
3487
3488		for (; count < numb; count++) {
3489			if (full) {
3490				if (dev->phy.rev >= 3)
3491					cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
3492				else
3493					cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
3494			} else {
3495				if (dev->phy.rev >= 3)
3496					cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
3497				else
3498					cmd = tbl_tx_iqlo_cal_cmds_recal[count];
3499			}
3500
3501			core = (cmd & 0x3000) >> 12;
3502			type = (cmd & 0x0F00) >> 8;
3503
3504			if (phy6or5x && updated[core] == 0) {
3505				b43_nphy_update_tx_cal_ladder(dev, core);
3506				updated[core] = 1;
3507			}
3508
3509			tmp = (params[core].ncorr[type] << 8) | 0x66;
3510			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
3511
3512			if (type == 1 || type == 3 || type == 4) {
3513				buffer[0] = b43_ntab_read(dev,
3514						B43_NTAB16(15, 69 + core));
3515				diq_start = buffer[0];
3516				buffer[0] = 0;
3517				b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
3518						0);
3519			}
3520
3521			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
3522			for (i = 0; i < 2000; i++) {
3523				tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
3524				if (tmp & 0xC000)
3525					break;
3526				udelay(10);
3527			}
3528
3529			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
3530						buffer);
3531			b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
3532						buffer);
3533
3534			if (type == 1 || type == 3 || type == 4)
3535				buffer[0] = diq_start;
3536		}
3537
3538		if (mphase)
3539			nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
3540
3541		last = (dev->phy.rev < 3) ? 6 : 7;
3542
3543		if (!mphase || nphy->mphase_cal_phase_id == last) {
3544			b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
3545			b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
3546			if (dev->phy.rev < 3) {
3547				buffer[0] = 0;
3548				buffer[1] = 0;
3549				buffer[2] = 0;
3550				buffer[3] = 0;
3551			}
3552			b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
3553						buffer);
3554			b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,
3555						buffer);
3556			b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
3557						buffer);
3558			b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
3559						buffer);
3560			length = 11;
3561			if (dev->phy.rev < 3)
3562				length -= 2;
3563			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
3564						nphy->txiqlocal_bestc);
3565			nphy->txiqlocal_coeffsvalid = true;
3566			nphy->txiqlocal_chanspec.center_freq =
3567							dev->phy.channel_freq;
3568			nphy->txiqlocal_chanspec.channel_type =
3569							dev->phy.channel_type;
3570		} else {
3571			length = 11;
3572			if (dev->phy.rev < 3)
3573				length -= 2;
3574			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
3575						nphy->mphase_txcal_bestcoeffs);
3576		}
3577
3578		b43_nphy_stop_playback(dev);
3579		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
3580	}
3581
3582	b43_nphy_tx_cal_phy_cleanup(dev);
3583	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
3584
3585	if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
3586		b43_nphy_tx_iq_workaround(dev);
3587
3588	if (dev->phy.rev >= 4)
3589		nphy->hang_avoid = avoid;
3590
3591	b43_nphy_stay_in_carrier_search(dev, false);
3592
3593	return error;
3594}
3595
3596/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
3597static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
3598{
3599	struct b43_phy_n *nphy = dev->phy.n;
3600	u8 i;
3601	u16 buffer[7];
3602	bool equal = true;
3603
3604	if (!nphy->txiqlocal_coeffsvalid ||
3605	    nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
3606	    nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
3607		return;
3608
3609	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
3610	for (i = 0; i < 4; i++) {
3611		if (buffer[i] != nphy->txiqlocal_bestc[i]) {
3612			equal = false;
3613			break;
3614		}
3615	}
3616
3617	if (!equal) {
3618		b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,
3619					nphy->txiqlocal_bestc);
3620		for (i = 0; i < 4; i++)
3621			buffer[i] = 0;
3622		b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
3623					buffer);
3624		b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
3625					&nphy->txiqlocal_bestc[5]);
3626		b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
3627					&nphy->txiqlocal_bestc[5]);
3628	}
3629}
3630
3631/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
3632static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
3633			struct nphy_txgains target, u8 type, bool debug)
3634{
3635	struct b43_phy_n *nphy = dev->phy.n;
3636	int i, j, index;
3637	u8 rfctl[2];
3638	u8 afectl_core;
3639	u16 tmp[6];
3640	u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna;
3641	u32 real, imag;
3642	enum ieee80211_band band;
3643
3644	u8 use;
3645	u16 cur_hpf;
3646	u16 lna[3] = { 3, 3, 1 };
3647	u16 hpf1[3] = { 7, 2, 0 };
3648	u16 hpf2[3] = { 2, 0, 0 };
3649	u32 power[3] = { };
3650	u16 gain_save[2];
3651	u16 cal_gain[2];
3652	struct nphy_iqcal_params cal_params[2];
3653	struct nphy_iq_est est;
3654	int ret = 0;
3655	bool playtone = true;
3656	int desired = 13;
3657
3658	b43_nphy_stay_in_carrier_search(dev, 1);
3659
3660	if (dev->phy.rev < 2)
3661		b43_nphy_reapply_tx_cal_coeffs(dev);
3662	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
3663	for (i = 0; i < 2; i++) {
3664		b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
3665		cal_gain[i] = cal_params[i].cal_gain;
3666	}
3667	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
3668
3669	for (i = 0; i < 2; i++) {
3670		if (i == 0) {
3671			rfctl[0] = B43_NPHY_RFCTL_INTC1;
3672			rfctl[1] = B43_NPHY_RFCTL_INTC2;
3673			afectl_core = B43_NPHY_AFECTL_C1;
3674		} else {
3675			rfctl[0] = B43_NPHY_RFCTL_INTC2;
3676			rfctl[1] = B43_NPHY_RFCTL_INTC1;
3677			afectl_core = B43_NPHY_AFECTL_C2;
3678		}
3679
3680		tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
3681		tmp[2] = b43_phy_read(dev, afectl_core);
3682		tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
3683		tmp[4] = b43_phy_read(dev, rfctl[0]);
3684		tmp[5] = b43_phy_read(dev, rfctl[1]);
3685
3686		b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
3687				~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
3688				((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
3689		b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
3690				(1 - i));
3691		b43_phy_set(dev, afectl_core, 0x0006);
3692		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
3693
3694		band = b43_current_band(dev->wl);
3695
3696		if (nphy->rxcalparams & 0xFF000000) {
3697			if (band == IEEE80211_BAND_5GHZ)
3698				b43_phy_write(dev, rfctl[0], 0x140);
3699			else
3700				b43_phy_write(dev, rfctl[0], 0x110);
3701		} else {
3702			if (band == IEEE80211_BAND_5GHZ)
3703				b43_phy_write(dev, rfctl[0], 0x180);
3704			else
3705				b43_phy_write(dev, rfctl[0], 0x120);
3706		}
3707
3708		if (band == IEEE80211_BAND_5GHZ)
3709			b43_phy_write(dev, rfctl[1], 0x148);
3710		else
3711			b43_phy_write(dev, rfctl[1], 0x114);
3712
3713		if (nphy->rxcalparams & 0x10000) {
3714			b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
3715					(i + 1));
3716			b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
3717					(2 - i));
3718		}
3719
3720		for (j = 0; j < 4; j++) {
3721			if (j < 3) {
3722				cur_lna = lna[j];
3723				cur_hpf1 = hpf1[j];
3724				cur_hpf2 = hpf2[j];
3725			} else {
3726				if (power[1] > 10000) {
3727					use = 1;
3728					cur_hpf = cur_hpf1;
3729					index = 2;
3730				} else {
3731					if (power[0] > 10000) {
3732						use = 1;
3733						cur_hpf = cur_hpf1;
3734						index = 1;
3735					} else {
3736						index = 0;
3737						use = 2;
3738						cur_hpf = cur_hpf2;
3739					}
3740				}
3741				cur_lna = lna[index];
3742				cur_hpf1 = hpf1[index];
3743				cur_hpf2 = hpf2[index];
3744				cur_hpf += desired - hweight32(power[index]);
3745				cur_hpf = clamp_val(cur_hpf, 0, 10);
3746				if (use == 1)
3747					cur_hpf1 = cur_hpf;
3748				else
3749					cur_hpf2 = cur_hpf;
3750			}
3751
3752			tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
3753					(cur_lna << 2));
3754			b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
3755									false);
3756			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3757			b43_nphy_stop_playback(dev);
3758
3759			if (playtone) {
3760				ret = b43_nphy_tx_tone(dev, 4000,
3761						(nphy->rxcalparams & 0xFFFF),
3762						false, false);
3763				playtone = false;
3764			} else {
3765				b43_nphy_run_samples(dev, 160, 0xFFFF, 0,
3766							false, false);
3767			}
3768
3769			if (ret == 0) {
3770				if (j < 3) {
3771					b43_nphy_rx_iq_est(dev, &est, 1024, 32,
3772									false);
3773					if (i == 0) {
3774						real = est.i0_pwr;
3775						imag = est.q0_pwr;
3776					} else {
3777						real = est.i1_pwr;
3778						imag = est.q1_pwr;
3779					}
3780					power[i] = ((real + imag) / 1024) + 1;
3781				} else {
3782					b43_nphy_calc_rx_iq_comp(dev, 1 << i);
3783				}
3784				b43_nphy_stop_playback(dev);
3785			}
3786
3787			if (ret != 0)
3788				break;
3789		}
3790
3791		b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
3792		b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
3793		b43_phy_write(dev, rfctl[1], tmp[5]);
3794		b43_phy_write(dev, rfctl[0], tmp[4]);
3795		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
3796		b43_phy_write(dev, afectl_core, tmp[2]);
3797		b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
3798
3799		if (ret != 0)
3800			break;
3801	}
3802
3803	b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
3804	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3805	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
3806
3807	b43_nphy_stay_in_carrier_search(dev, 0);
3808
3809	return ret;
3810}
3811
3812static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
3813			struct nphy_txgains target, u8 type, bool debug)
3814{
3815	return -1;
3816}
3817
3818/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
3819static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
3820			struct nphy_txgains target, u8 type, bool debug)
3821{
3822	if (dev->phy.rev >= 3)
3823		return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
3824	else
3825		return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
3826}
3827
3828/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
3829static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
3830{
3831	struct b43_phy *phy = &dev->phy;
3832	struct b43_phy_n *nphy = phy->n;
3833	/* u16 buf[16]; it's rev3+ */
3834
3835	nphy->phyrxchain = mask;
3836
3837	if (0 /* FIXME clk */)
3838		return;
3839
3840	b43_mac_suspend(dev);
3841
3842	if (nphy->hang_avoid)
3843		b43_nphy_stay_in_carrier_search(dev, true);
3844
3845	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
3846			(mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);
3847
3848	if ((mask & 0x3) != 0x3) {
3849		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1);
3850		if (dev->phy.rev >= 3) {
3851			/* TODO */
3852		}
3853	} else {
3854		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E);
3855		if (dev->phy.rev >= 3) {
3856			/* TODO */
3857		}
3858	}
3859
3860	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3861
3862	if (nphy->hang_avoid)
3863		b43_nphy_stay_in_carrier_search(dev, false);
3864
3865	b43_mac_enable(dev);
3866}
3867
3868/*
3869 * Init N-PHY
3870 * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
3871 */
3872int b43_phy_initn(struct b43_wldev *dev)
3873{
3874	struct ssb_sprom *sprom = dev->dev->bus_sprom;
3875	struct b43_phy *phy = &dev->phy;
3876	struct b43_phy_n *nphy = phy->n;
3877	u8 tx_pwr_state;
3878	struct nphy_txgains target;
3879	u16 tmp;
3880	enum ieee80211_band tmp2;
3881	bool do_rssi_cal;
3882
3883	u16 clip[2];
3884	bool do_cal = false;
3885
3886	if ((dev->phy.rev >= 3) &&
3887	   (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
3888	   (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
3889		switch (dev->dev->bus_type) {
3890#ifdef CONFIG_B43_BCMA
3891		case B43_BUS_BCMA:
3892			bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
3893				      BCMA_CC_CHIPCTL, 0x40);
3894			break;
3895#endif
3896#ifdef CONFIG_B43_SSB
3897		case B43_BUS_SSB:
3898			chipco_set32(&dev->dev->sdev->bus->chipco,
3899				     SSB_CHIPCO_CHIPCTL, 0x40);
3900			break;
3901#endif
3902		}
3903	}
3904	nphy->deaf_count = 0;
3905	b43_nphy_tables_init(dev);
3906	nphy->crsminpwr_adjusted = false;
3907	nphy->noisevars_adjusted = false;
3908
3909	/* Clear all overrides */
3910	if (dev->phy.rev >= 3) {
3911		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
3912		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
3913		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
3914		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
3915	} else {
3916		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
3917	}
3918	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
3919	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
3920	if (dev->phy.rev < 6) {
3921		b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
3922		b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
3923	}
3924	b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
3925		     ~(B43_NPHY_RFSEQMODE_CAOVER |
3926		       B43_NPHY_RFSEQMODE_TROVER));
3927	if (dev->phy.rev >= 3)
3928		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
3929	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
3930
3931	if (dev->phy.rev <= 2) {
3932		tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
3933		b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
3934				~B43_NPHY_BPHY_CTL3_SCALE,
3935				tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
3936	}
3937	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
3938	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
3939
3940	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
3941	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
3942	     dev->dev->board_type == 0x8B))
3943		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
3944	else
3945		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
3946	b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
3947	b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
3948	b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
3949
3950	b43_nphy_update_mimo_config(dev, nphy->preamble_override);
3951	b43_nphy_update_txrx_chain(dev);
3952
3953	if (phy->rev < 2) {
3954		b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
3955		b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
3956	}
3957
3958	tmp2 = b43_current_band(dev->wl);
3959	if (b43_nphy_ipa(dev)) {
3960		b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
3961		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
3962				nphy->papd_epsilon_offset[0] << 7);
3963		b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
3964		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
3965				nphy->papd_epsilon_offset[1] << 7);
3966		b43_nphy_int_pa_set_tx_dig_filters(dev);
3967	} else if (phy->rev >= 5) {
3968		b43_nphy_ext_pa_set_tx_dig_filters(dev);
3969	}
3970
3971	b43_nphy_workarounds(dev);
3972
3973	/* Reset CCA, in init code it differs a little from standard way */
3974	b43_phy_force_clock(dev, 1);
3975	tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
3976	b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
3977	b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
3978	b43_phy_force_clock(dev, 0);
3979
3980	b43_mac_phy_clock_set(dev, true);
3981
3982	b43_nphy_pa_override(dev, false);
3983	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
3984	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3985	b43_nphy_pa_override(dev, true);
3986
3987	b43_nphy_classifier(dev, 0, 0);
3988	b43_nphy_read_clip_detection(dev, clip);
3989	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3990		b43_nphy_bphy_init(dev);
3991
3992	tx_pwr_state = nphy->txpwrctrl;
3993	b43_nphy_tx_power_ctrl(dev, false);
3994	b43_nphy_tx_power_fix(dev);
3995	/* TODO N PHY TX Power Control Idle TSSI */
3996	/* TODO N PHY TX Power Control Setup */
3997	b43_nphy_tx_gain_table_upload(dev);
3998
3999	if (nphy->phyrxchain != 3)
4000		b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
4001	if (nphy->mphase_cal_phase_id > 0)
4002		;/* TODO PHY Periodic Calibration Multi-Phase Restart */
4003
4004	do_rssi_cal = false;
4005	if (phy->rev >= 3) {
4006		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
4007			do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
4008		else
4009			do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
4010
4011		if (do_rssi_cal)
4012			b43_nphy_rssi_cal(dev);
4013		else
4014			b43_nphy_restore_rssi_cal(dev);
4015	} else {
4016		b43_nphy_rssi_cal(dev);
4017	}
4018
4019	if (!((nphy->measure_hold & 0x6) != 0)) {
4020		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
4021			do_cal = !nphy->iqcal_chanspec_2G.center_freq;
4022		else
4023			do_cal = !nphy->iqcal_chanspec_5G.center_freq;
4024
4025		if (nphy->mute)
4026			do_cal = false;
4027
4028		if (do_cal) {
4029			target = b43_nphy_get_tx_gains(dev);
4030
4031			if (nphy->antsel_type == 2)
4032				b43_nphy_superswitch_init(dev, true);
4033			if (nphy->perical != 2) {
4034				b43_nphy_rssi_cal(dev);
4035				if (phy->rev >= 3) {
4036					nphy->cal_orig_pwr_idx[0] =
4037					    nphy->txpwrindex[0].index_internal;
4038					nphy->cal_orig_pwr_idx[1] =
4039					    nphy->txpwrindex[1].index_internal;
4040					/* TODO N PHY Pre Calibrate TX Gain */
4041					target = b43_nphy_get_tx_gains(dev);
4042				}
4043				if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false))
4044					if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
4045						b43_nphy_save_cal(dev);
4046			} else if (nphy->mphase_cal_phase_id == 0)
4047				;/* N PHY Periodic Calibration with arg 3 */
4048		} else {
4049			b43_nphy_restore_cal(dev);
4050		}
4051	}
4052
4053	b43_nphy_tx_pwr_ctrl_coef_setup(dev);
4054	b43_nphy_tx_power_ctrl(dev, tx_pwr_state);
4055	b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
4056	b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
4057	if (phy->rev >= 3 && phy->rev <= 6)
4058		b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014);
4059	b43_nphy_tx_lp_fbw(dev);
4060	if (phy->rev >= 3)
4061		b43_nphy_spur_workaround(dev);
4062
4063	return 0;
4064}
4065
4066/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
4067static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
4068{
4069	struct bcma_drv_cc __maybe_unused *cc;
4070	u32 __maybe_unused pmu_ctl;
4071
4072	switch (dev->dev->bus_type) {
4073#ifdef CONFIG_B43_BCMA
4074	case B43_BUS_BCMA:
4075		cc = &dev->dev->bdev->bus->drv_cc;
4076		if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
4077			if (avoid) {
4078				bcma_chipco_pll_write(cc, 0x0, 0x11500010);
4079				bcma_chipco_pll_write(cc, 0x1, 0x000C0C06);
4080				bcma_chipco_pll_write(cc, 0x2, 0x0F600a08);
4081				bcma_chipco_pll_write(cc, 0x3, 0x00000000);
4082				bcma_chipco_pll_write(cc, 0x4, 0x2001E920);
4083				bcma_chipco_pll_write(cc, 0x5, 0x88888815);
4084			} else {
4085				bcma_chipco_pll_write(cc, 0x0, 0x11100010);
4086				bcma_chipco_pll_write(cc, 0x1, 0x000c0c06);
4087				bcma_chipco_pll_write(cc, 0x2, 0x03000a08);
4088				bcma_chipco_pll_write(cc, 0x3, 0x00000000);
4089				bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
4090				bcma_chipco_pll_write(cc, 0x5, 0x88888815);
4091			}
4092			pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
4093		} else if (dev->dev->chip_id == 0x4716) {
4094			if (avoid) {
4095				bcma_chipco_pll_write(cc, 0x0, 0x11500060);
4096				bcma_chipco_pll_write(cc, 0x1, 0x080C0C06);
4097				bcma_chipco_pll_write(cc, 0x2, 0x0F600000);
4098				bcma_chipco_pll_write(cc, 0x3, 0x00000000);
4099				bcma_chipco_pll_write(cc, 0x4, 0x2001E924);
4100				bcma_chipco_pll_write(cc, 0x5, 0x88888815);
4101			} else {
4102				bcma_chipco_pll_write(cc, 0x0, 0x11100060);
4103				bcma_chipco_pll_write(cc, 0x1, 0x080c0c06);
4104				bcma_chipco_pll_write(cc, 0x2, 0x03000000);
4105				bcma_chipco_pll_write(cc, 0x3, 0x00000000);
4106				bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
4107				bcma_chipco_pll_write(cc, 0x5, 0x88888815);
4108			}
4109			pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD |
4110				  BCMA_CC_PMU_CTL_NOILPONW;
4111		} else if (dev->dev->chip_id == 0x4322 ||
4112			   dev->dev->chip_id == 0x4340 ||
4113			   dev->dev->chip_id == 0x4341) {
4114			bcma_chipco_pll_write(cc, 0x0, 0x11100070);
4115			bcma_chipco_pll_write(cc, 0x1, 0x1014140a);
4116			bcma_chipco_pll_write(cc, 0x5, 0x88888854);
4117			if (avoid)
4118				bcma_chipco_pll_write(cc, 0x2, 0x05201828);
4119			else
4120				bcma_chipco_pll_write(cc, 0x2, 0x05001828);
4121			pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
4122		} else {
4123			return;
4124		}
4125		bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl);
4126		break;
4127#endif
4128#ifdef CONFIG_B43_SSB
4129	case B43_BUS_SSB:
4130		/* FIXME */
4131		break;
4132#endif
4133	}
4134}
4135
4136/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
4137static void b43_nphy_channel_setup(struct b43_wldev *dev,
4138				const struct b43_phy_n_sfo_cfg *e,
4139				struct ieee80211_channel *new_channel)
4140{
4141	struct b43_phy *phy = &dev->phy;
4142	struct b43_phy_n *nphy = dev->phy.n;
4143	int ch = new_channel->hw_value;
4144
4145	u16 old_band_5ghz;
4146	u32 tmp32;
4147
4148	old_band_5ghz =
4149		b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
4150	if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
4151		tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
4152		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
4153		b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
4154		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
4155		b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
4156	} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
4157		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
4158		tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
4159		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
4160		b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
4161		b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
4162	}
4163
4164	b43_chantab_phy_upload(dev, e);
4165
4166	if (new_channel->hw_value == 14) {
4167		b43_nphy_classifier(dev, 2, 0);
4168		b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
4169	} else {
4170		b43_nphy_classifier(dev, 2, 2);
4171		if (new_channel->band == IEEE80211_BAND_2GHZ)
4172			b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
4173	}
4174
4175	if (!nphy->txpwrctrl)
4176		b43_nphy_tx_power_fix(dev);
4177
4178	if (dev->phy.rev < 3)
4179		b43_nphy_adjust_lna_gain_table(dev);
4180
4181	b43_nphy_tx_lp_fbw(dev);
4182
4183	if (dev->phy.rev >= 3 &&
4184	    dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
4185		bool avoid = false;
4186		if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
4187			avoid = true;
4188		} else if (!b43_channel_type_is_40mhz(phy->channel_type)) {
4189			if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
4190				avoid = true;
4191		} else { /* 40MHz */
4192			if (nphy->aband_spurwar_en &&
4193			    (ch == 38 || ch == 102 || ch == 118))
4194				avoid = dev->dev->chip_id == 0x4716;
4195		}
4196
4197		b43_nphy_pmu_spur_avoid(dev, avoid);
4198
4199		if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 ||
4200		    dev->dev->chip_id == 43225) {
4201			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
4202				    avoid ? 0x5341 : 0x8889);
4203			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
4204		}
4205
4206		if (dev->phy.rev == 3 || dev->phy.rev == 4)
4207			; /* TODO: reset PLL */
4208
4209		if (avoid)
4210			b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
4211		else
4212			b43_phy_mask(dev, B43_NPHY_BBCFG,
4213				     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
4214
4215		b43_nphy_reset_cca(dev);
4216
4217		/* wl sets useless phy_isspuravoid here */
4218	}
4219
4220	b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
4221
4222	if (phy->rev >= 3)
4223		b43_nphy_spur_workaround(dev);
4224}
4225
4226/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
4227static int b43_nphy_set_channel(struct b43_wldev *dev,
4228				struct ieee80211_channel *channel,
4229				enum nl80211_channel_type channel_type)
4230{
4231	struct b43_phy *phy = &dev->phy;
4232
4233	const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
4234	const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
4235
4236	u8 tmp;
4237
4238	if (dev->phy.rev >= 3) {
4239		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
4240							channel->center_freq);
4241		if (!tabent_r3)
4242			return -ESRCH;
4243	} else {
4244		tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
4245							channel->hw_value);
4246		if (!tabent_r2)
4247			return -ESRCH;
4248	}
4249
4250	/* Channel is set later in common code, but we need to set it on our
4251	   own to let this function's subcalls work properly. */
4252	phy->channel = channel->hw_value;
4253	phy->channel_freq = channel->center_freq;
4254
4255	if (b43_channel_type_is_40mhz(phy->channel_type) !=
4256		b43_channel_type_is_40mhz(channel_type))
4257		; /* TODO: BMAC BW Set (channel_type) */
4258
4259	if (channel_type == NL80211_CHAN_HT40PLUS)
4260		b43_phy_set(dev, B43_NPHY_RXCTL,
4261				B43_NPHY_RXCTL_BSELU20);
4262	else if (channel_type == NL80211_CHAN_HT40MINUS)
4263		b43_phy_mask(dev, B43_NPHY_RXCTL,
4264				~B43_NPHY_RXCTL_BSELU20);
4265
4266	if (dev->phy.rev >= 3) {
4267		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
4268		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
4269		b43_radio_2056_setup(dev, tabent_r3);
4270		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
4271	} else {
4272		tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
4273		b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
4274		b43_radio_2055_setup(dev, tabent_r2);
4275		b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
4276	}
4277
4278	return 0;
4279}
4280
4281static int b43_nphy_op_allocate(struct b43_wldev *dev)
4282{
4283	struct b43_phy_n *nphy;
4284
4285	nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
4286	if (!nphy)
4287		return -ENOMEM;
4288	dev->phy.n = nphy;
4289
4290	return 0;
4291}
4292
4293static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
4294{
4295	struct b43_phy *phy = &dev->phy;
4296	struct b43_phy_n *nphy = phy->n;
4297	struct ssb_sprom *sprom = dev->dev->bus_sprom;
4298
4299	memset(nphy, 0, sizeof(*nphy));
4300
4301	nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
4302	nphy->spur_avoid = (phy->rev >= 3) ?
4303				B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
4304	nphy->gain_boost = true; /* this way we follow wl, assume it is true */
4305	nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
4306	nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
4307	nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
4308	/* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
4309	 * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
4310	nphy->tx_pwr_idx[0] = 128;
4311	nphy->tx_pwr_idx[1] = 128;
4312
4313	/* Hardware TX power control and 5GHz power gain */
4314	nphy->txpwrctrl = false;
4315	nphy->pwg_gain_5ghz = false;
4316	if (dev->phy.rev >= 3 ||
4317	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
4318	     (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {
4319		nphy->txpwrctrl = true;
4320		nphy->pwg_gain_5ghz = true;
4321	} else if (sprom->revision >= 4) {
4322		if (dev->phy.rev >= 2 &&
4323		    (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) {
4324			nphy->txpwrctrl = true;
4325#ifdef CONFIG_B43_SSB
4326			if (dev->dev->bus_type == B43_BUS_SSB &&
4327			    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {
4328				struct pci_dev *pdev =
4329					dev->dev->sdev->bus->host_pci;
4330				if (pdev->device == 0x4328 ||
4331				    pdev->device == 0x432a)
4332					nphy->pwg_gain_5ghz = true;
4333			}
4334#endif
4335		} else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {
4336			nphy->pwg_gain_5ghz = true;
4337		}
4338	}
4339
4340	if (dev->phy.rev >= 3) {
4341		nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
4342		nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
4343	}
4344}
4345
4346static void b43_nphy_op_free(struct b43_wldev *dev)
4347{
4348	struct b43_phy *phy = &dev->phy;
4349	struct b43_phy_n *nphy = phy->n;
4350
4351	kfree(nphy);
4352	phy->n = NULL;
4353}
4354
4355static int b43_nphy_op_init(struct b43_wldev *dev)
4356{
4357	return b43_phy_initn(dev);
4358}
4359
4360static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
4361{
4362#if B43_DEBUG
4363	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
4364		/* OFDM registers are onnly available on A/G-PHYs */
4365		b43err(dev->wl, "Invalid OFDM PHY access at "
4366		       "0x%04X on N-PHY\n", offset);
4367		dump_stack();
4368	}
4369	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
4370		/* Ext-G registers are only available on G-PHYs */
4371		b43err(dev->wl, "Invalid EXT-G PHY access at "
4372		       "0x%04X on N-PHY\n", offset);
4373		dump_stack();
4374	}
4375#endif /* B43_DEBUG */
4376}
4377
4378static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
4379{
4380	check_phyreg(dev, reg);
4381	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
4382	return b43_read16(dev, B43_MMIO_PHY_DATA);
4383}
4384
4385static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
4386{
4387	check_phyreg(dev, reg);
4388	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
4389	b43_write16(dev, B43_MMIO_PHY_DATA, value);
4390}
4391
4392static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
4393				 u16 set)
4394{
4395	check_phyreg(dev, reg);
4396	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
4397	b43_write16(dev, B43_MMIO_PHY_DATA,
4398		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
4399}
4400
4401static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
4402{
4403	/* Register 1 is a 32-bit register. */
4404	B43_WARN_ON(reg == 1);
4405	/* N-PHY needs 0x100 for read access */
4406	reg |= 0x100;
4407
4408	b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
4409	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
4410}
4411
4412static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
4413{
4414	/* Register 1 is a 32-bit register. */
4415	B43_WARN_ON(reg == 1);
4416
4417	b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
4418	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
4419}
4420
4421/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
4422static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
4423					bool blocked)
4424{
4425	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
4426		b43err(dev->wl, "MAC not suspended\n");
4427
4428	if (blocked) {
4429		b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
4430				~B43_NPHY_RFCTL_CMD_CHIP0PU);
4431		if (dev->phy.rev >= 3) {
4432			b43_radio_mask(dev, 0x09, ~0x2);
4433
4434			b43_radio_write(dev, 0x204D, 0);
4435			b43_radio_write(dev, 0x2053, 0);
4436			b43_radio_write(dev, 0x2058, 0);
4437			b43_radio_write(dev, 0x205E, 0);
4438			b43_radio_mask(dev, 0x2062, ~0xF0);
4439			b43_radio_write(dev, 0x2064, 0);
4440
4441			b43_radio_write(dev, 0x304D, 0);
4442			b43_radio_write(dev, 0x3053, 0);
4443			b43_radio_write(dev, 0x3058, 0);
4444			b43_radio_write(dev, 0x305E, 0);
4445			b43_radio_mask(dev, 0x3062, ~0xF0);
4446			b43_radio_write(dev, 0x3064, 0);
4447		}
4448	} else {
4449		if (dev->phy.rev >= 3) {
4450			b43_radio_init2056(dev);
4451			b43_switch_channel(dev, dev->phy.channel);
4452		} else {
4453			b43_radio_init2055(dev);
4454		}
4455	}
4456}
4457
4458/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
4459static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
4460{
4461	u16 override = on ? 0x0 : 0x7FFF;
4462	u16 core = on ? 0xD : 0x00FD;
4463
4464	if (dev->phy.rev >= 3) {
4465		if (on) {
4466			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
4467			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
4468			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
4469			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
4470		} else {
4471			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
4472			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
4473			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
4474			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
4475		}
4476	} else {
4477		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
4478	}
4479}
4480
4481static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
4482				      unsigned int new_channel)
4483{
4484	struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
4485	enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
4486
4487	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
4488		if ((new_channel < 1) || (new_channel > 14))
4489			return -EINVAL;
4490	} else {
4491		if (new_channel > 200)
4492			return -EINVAL;
4493	}
4494
4495	return b43_nphy_set_channel(dev, channel, channel_type);
4496}
4497
4498static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
4499{
4500	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
4501		return 1;
4502	return 36;
4503}
4504
4505const struct b43_phy_operations b43_phyops_n = {
4506	.allocate		= b43_nphy_op_allocate,
4507	.free			= b43_nphy_op_free,
4508	.prepare_structs	= b43_nphy_op_prepare_structs,
4509	.init			= b43_nphy_op_init,
4510	.phy_read		= b43_nphy_op_read,
4511	.phy_write		= b43_nphy_op_write,
4512	.phy_maskset		= b43_nphy_op_maskset,
4513	.radio_read		= b43_nphy_op_radio_read,
4514	.radio_write		= b43_nphy_op_radio_write,
4515	.software_rfkill	= b43_nphy_op_software_rfkill,
4516	.switch_analog		= b43_nphy_op_switch_analog,
4517	.switch_channel		= b43_nphy_op_switch_channel,
4518	.get_default_chan	= b43_nphy_op_get_default_chan,
4519	.recalc_txpower		= b43_nphy_op_recalc_txpower,
4520	.adjust_txpower		= b43_nphy_op_adjust_txpower,
4521};
4522