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