1 
2 /*
3 
4   Broadcom B43 wireless driver
5   IEEE 802.11n PHY data tables
6 
7   Copyright (c) 2008 Michael Buesch <m@bues.ch>
8   Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
9 
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of the GNU General Public License as published by
12   the Free Software Foundation; either version 2 of the License, or
13   (at your option) any later version.
14 
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19 
20   You should have received a copy of the GNU General Public License
21   along with this program; see the file COPYING.  If not, write to
22   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
23   Boston, MA 02110-1301, USA.
24 
25 */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 /*
31  * The Broadcom Wireless LAN controller driver.
32  */
33 
34 #include "opt_wlan.h"
35 #include "opt_bwn.h"
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/endian.h>
43 #include <sys/errno.h>
44 #include <sys/firmware.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <machine/bus.h>
48 #include <machine/resource.h>
49 #include <sys/bus.h>
50 #include <sys/rman.h>
51 #include <sys/socket.h>
52 #include <sys/sockio.h>
53 
54 #include <net/ethernet.h>
55 #include <net/if.h>
56 #include <net/if_var.h>
57 #include <net/if_arp.h>
58 #include <net/if_dl.h>
59 #include <net/if_llc.h>
60 #include <net/if_media.h>
61 #include <net/if_types.h>
62 
63 #include <dev/pci/pcivar.h>
64 #include <dev/pci/pcireg.h>
65 #include <dev/siba/siba_ids.h>
66 #include <dev/siba/sibareg.h>
67 #include <dev/siba/sibavar.h>
68 
69 #include <net80211/ieee80211_var.h>
70 #include <net80211/ieee80211_radiotap.h>
71 #include <net80211/ieee80211_regdomain.h>
72 #include <net80211/ieee80211_phy.h>
73 #include <net80211/ieee80211_ratectl.h>
74 
75 #include <dev/bwn/if_bwnreg.h>
76 #include <dev/bwn/if_bwnvar.h>
77 #include <dev/bwn/if_bwn_misc.h>
78 #include <dev/bwn/if_bwn_util.h>
79 #include <dev/bwn/if_bwn_debug.h>
80 #include <dev/bwn/if_bwn_phy_common.h>
81 #include <dev/bwn/if_bwn_chipid.h>
82 #include <dev/bwn/if_bwn_cordic.h>
83 
84 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_regs.h>
85 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.h>
86 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_tables.h>
87 #include <gnu/dev/bwn/phy_n/if_bwn_radio_2055.h>
88 #include <gnu/dev/bwn/phy_n/if_bwn_radio_2056.h>
89 #include <gnu/dev/bwn/phy_n/if_bwn_radio_2057.h>
90 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_core.h>
91 
92 struct bwn_nphy_txgains {
93 	uint16_t tx_lpf[2];
94 	uint16_t txgm[2];
95 	uint16_t pga[2];
96 	uint16_t pad[2];
97 	uint16_t ipa[2];
98 };
99 
100 struct bwn_nphy_iqcal_params {
101 	uint16_t tx_lpf;
102 	uint16_t txgm;
103 	uint16_t pga;
104 	uint16_t pad;
105 	uint16_t ipa;
106 	uint16_t cal_gain;
107 	uint16_t ncorr[5];
108 };
109 
110 struct bwn_nphy_iq_est {
111 	int32_t iq0_prod;
112 	uint32_t i0_pwr;
113 	uint32_t q0_pwr;
114 	int32_t iq1_prod;
115 	uint32_t i1_pwr;
116 	uint32_t q1_pwr;
117 };
118 
119 enum bwn_nphy_rf_sequence {
120 	BWN_RFSEQ_RX2TX,
121 	BWN_RFSEQ_TX2RX,
122 	BWN_RFSEQ_RESET2RX,
123 	BWN_RFSEQ_UPDATE_GAINH,
124 	BWN_RFSEQ_UPDATE_GAINL,
125 	BWN_RFSEQ_UPDATE_GAINU,
126 };
127 
128 enum n_rf_ctl_over_cmd {
129 	N_RF_CTL_OVER_CMD_RXRF_PU = 0,
130 	N_RF_CTL_OVER_CMD_RX_PU = 1,
131 	N_RF_CTL_OVER_CMD_TX_PU = 2,
132 	N_RF_CTL_OVER_CMD_RX_GAIN = 3,
133 	N_RF_CTL_OVER_CMD_TX_GAIN = 4,
134 };
135 
136 enum n_intc_override {
137 	N_INTC_OVERRIDE_OFF = 0,
138 	N_INTC_OVERRIDE_TRSW = 1,
139 	N_INTC_OVERRIDE_PA = 2,
140 	N_INTC_OVERRIDE_EXT_LNA_PU = 3,
141 	N_INTC_OVERRIDE_EXT_LNA_GAIN = 4,
142 };
143 
144 enum n_rssi_type {
145 	N_RSSI_W1 = 0,
146 	N_RSSI_W2,
147 	N_RSSI_NB,
148 	N_RSSI_IQ,
149 	N_RSSI_TSSI_2G,
150 	N_RSSI_TSSI_5G,
151 	N_RSSI_TBD,
152 };
153 
154 enum n_rail_type {
155 	N_RAIL_I = 0,
156 	N_RAIL_Q = 1,
157 };
158 
159 static inline bool bwn_nphy_ipa(struct bwn_mac *mac)
160 {
161 	bwn_band_t band = bwn_current_band(mac);
162 	return ((mac->mac_phy.phy_n->ipa2g_on && band == BWN_BAND_2G) ||
163 		(mac->mac_phy.phy_n->ipa5g_on && band == BWN_BAND_5G));
164 }
165 
166 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */
167 static uint8_t bwn_nphy_get_rx_core_state(struct bwn_mac *mac)
168 {
169 	return (BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA) & BWN_NPHY_RFSEQCA_RXEN) >>
170 		BWN_NPHY_RFSEQCA_RXEN_SHIFT;
171 }
172 
173 /**************************************************
174  * RF (just without bwn_nphy_rf_ctl_intc_override)
175  **************************************************/
176 
177 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
178 static void bwn_nphy_force_rf_sequence(struct bwn_mac *mac,
179 				       enum bwn_nphy_rf_sequence seq)
180 {
181 	static const uint16_t trigger[] = {
182 		[BWN_RFSEQ_RX2TX]		= BWN_NPHY_RFSEQTR_RX2TX,
183 		[BWN_RFSEQ_TX2RX]		= BWN_NPHY_RFSEQTR_TX2RX,
184 		[BWN_RFSEQ_RESET2RX]		= BWN_NPHY_RFSEQTR_RST2RX,
185 		[BWN_RFSEQ_UPDATE_GAINH]	= BWN_NPHY_RFSEQTR_UPGH,
186 		[BWN_RFSEQ_UPDATE_GAINL]	= BWN_NPHY_RFSEQTR_UPGL,
187 		[BWN_RFSEQ_UPDATE_GAINU]	= BWN_NPHY_RFSEQTR_UPGU,
188 	};
189 	int i;
190 	uint16_t seq_mode = BWN_PHY_READ(mac, BWN_NPHY_RFSEQMODE);
191 
192 	if (seq >= nitems(trigger)) {
193 		BWN_WARNPRINTF(mac->mac_sc, "%s: seq %d > max", __func__, seq);
194 	}
195 
196 	BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE,
197 		    BWN_NPHY_RFSEQMODE_CAOVER | BWN_NPHY_RFSEQMODE_TROVER);
198 	BWN_PHY_SET(mac, BWN_NPHY_RFSEQTR, trigger[seq]);
199 	for (i = 0; i < 200; i++) {
200 		if (!(BWN_PHY_READ(mac, BWN_NPHY_RFSEQST) & trigger[seq]))
201 			goto ok;
202 		DELAY(1000);
203 	}
204 	BWN_ERRPRINTF(mac->mac_sc, "RF sequence status timeout\n");
205 ok:
206 	BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQMODE, seq_mode);
207 }
208 
209 static void bwn_nphy_rf_ctl_override_rev19(struct bwn_mac *mac, uint16_t field,
210 					   uint16_t value, uint8_t core, bool off,
211 					   uint8_t override_id)
212 {
213 	/* TODO */
214 }
215 
216 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
217 static void bwn_nphy_rf_ctl_override_rev7(struct bwn_mac *mac, uint16_t field,
218 					  uint16_t value, uint8_t core, bool off,
219 					  uint8_t override)
220 {
221 	struct bwn_phy *phy = &mac->mac_phy;
222 	const struct bwn_nphy_rf_control_override_rev7 *e;
223 	uint16_t en_addrs[3][2] = {
224 		{ 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
225 	};
226 	uint16_t en_addr;
227 	uint16_t en_mask = field;
228 	uint16_t val_addr;
229 	uint8_t i;
230 
231 	if (phy->rev >= 19 || phy->rev < 3) {
232 		BWN_WARNPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n",
233 		    __func__,
234 		    phy->rev);
235 		return;
236 	}
237 
238 	/* Remember: we can get NULL! */
239 	e = bwn_nphy_get_rf_ctl_over_rev7(mac, field, override);
240 
241 	for (i = 0; i < 2; i++) {
242 		if (override >= nitems(en_addrs)) {
243 			BWN_ERRPRINTF(mac->mac_sc, "Invalid override value %d\n", override);
244 			return;
245 		}
246 		en_addr = en_addrs[override][i];
247 
248 		if (e)
249 			val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
250 
251 		if (off) {
252 			BWN_PHY_MASK(mac, en_addr, ~en_mask);
253 			if (e) /* Do it safer, better than wl */
254 				BWN_PHY_MASK(mac, val_addr, ~e->val_mask);
255 		} else {
256 			if (!core || (core & (1 << i))) {
257 				BWN_PHY_SET(mac, en_addr, en_mask);
258 				if (e)
259 					BWN_PHY_SETMASK(mac, val_addr, ~e->val_mask, (value << e->val_shift));
260 			}
261 		}
262 	}
263 }
264 
265 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
266 static void bwn_nphy_rf_ctl_override_one_to_many(struct bwn_mac *mac,
267 						 enum n_rf_ctl_over_cmd cmd,
268 						 uint16_t value, uint8_t core, bool off)
269 {
270 	struct bwn_phy *phy = &mac->mac_phy;
271 	uint16_t tmp;
272 
273 	if (phy->rev < 7) {
274 		BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n",
275 		    __func__,
276 		    phy->rev);
277 	}
278 
279 	switch (cmd) {
280 	case N_RF_CTL_OVER_CMD_RXRF_PU:
281 		bwn_nphy_rf_ctl_override_rev7(mac, 0x20, value, core, off, 1);
282 		bwn_nphy_rf_ctl_override_rev7(mac, 0x10, value, core, off, 1);
283 		bwn_nphy_rf_ctl_override_rev7(mac, 0x08, value, core, off, 1);
284 		break;
285 	case N_RF_CTL_OVER_CMD_RX_PU:
286 		bwn_nphy_rf_ctl_override_rev7(mac, 0x4, value, core, off, 1);
287 		bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 1);
288 		bwn_nphy_rf_ctl_override_rev7(mac, 0x1, value, core, off, 1);
289 		bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 2);
290 		bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, 0, core, off, 1);
291 		break;
292 	case N_RF_CTL_OVER_CMD_TX_PU:
293 		bwn_nphy_rf_ctl_override_rev7(mac, 0x4, value, core, off, 0);
294 		bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 1);
295 		bwn_nphy_rf_ctl_override_rev7(mac, 0x1, value, core, off, 2);
296 		bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, 1, core, off, 1);
297 		break;
298 	case N_RF_CTL_OVER_CMD_RX_GAIN:
299 		tmp = value & 0xFF;
300 		bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, tmp, core, off, 0);
301 		tmp = value >> 8;
302 		bwn_nphy_rf_ctl_override_rev7(mac, 0x6000, tmp, core, off, 0);
303 		break;
304 	case N_RF_CTL_OVER_CMD_TX_GAIN:
305 		tmp = value & 0x7FFF;
306 		bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, tmp, core, off, 0);
307 		tmp = value >> 14;
308 		bwn_nphy_rf_ctl_override_rev7(mac, 0x4000, tmp, core, off, 0);
309 		break;
310 	}
311 }
312 
313 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
314 static void bwn_nphy_rf_ctl_override(struct bwn_mac *mac, uint16_t field,
315 				     uint16_t value, uint8_t core, bool off)
316 {
317 	int i;
318 	uint8_t index = fls(field);
319 	uint8_t addr, en_addr, val_addr;
320 
321 	/* we expect only one bit set */
322 	if (field & (~(1 << (index - 1)))) {
323 		BWN_ERRPRINTF(mac->mac_sc, "%s: field 0x%04x has >1 bit set\n",
324 		    __func__,
325 		    field);
326 	}
327 
328 	if (mac->mac_phy.rev >= 3) {
329 		const struct bwn_nphy_rf_control_override_rev3 *rf_ctrl;
330 		for (i = 0; i < 2; i++) {
331 			if (index == 0 || index == 16) {
332 				BWN_ERRPRINTF(mac->mac_sc,
333 					"Unsupported RF Ctrl Override call\n");
334 				return;
335 			}
336 
337 			rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
338 			en_addr = BWN_PHY_N((i == 0) ?
339 				rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
340 			val_addr = BWN_PHY_N((i == 0) ?
341 				rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
342 
343 			if (off) {
344 				BWN_PHY_MASK(mac, en_addr, ~(field));
345 				BWN_PHY_MASK(mac, val_addr,
346 						~(rf_ctrl->val_mask));
347 			} else {
348 				if (core == 0 || ((1 << i) & core)) {
349 					BWN_PHY_SET(mac, en_addr, field);
350 					BWN_PHY_SETMASK(mac, val_addr,
351 						~(rf_ctrl->val_mask),
352 						(value << rf_ctrl->val_shift));
353 				}
354 			}
355 		}
356 	} else {
357 		const struct bwn_nphy_rf_control_override_rev2 *rf_ctrl;
358 		if (off) {
359 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~(field));
360 			value = 0;
361 		} else {
362 			BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, field);
363 		}
364 
365 		for (i = 0; i < 2; i++) {
366 			if (index <= 1 || index == 16) {
367 				BWN_ERRPRINTF(mac->mac_sc,
368 					"Unsupported RF Ctrl Override call\n");
369 				return;
370 			}
371 
372 			if (index == 2 || index == 10 ||
373 			    (index >= 13 && index <= 15)) {
374 				core = 1;
375 			}
376 
377 			rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
378 			addr = BWN_PHY_N((i == 0) ?
379 				rf_ctrl->addr0 : rf_ctrl->addr1);
380 
381 			if ((1 << i) & core)
382 				BWN_PHY_SETMASK(mac, addr, ~(rf_ctrl->bmask),
383 						(value << rf_ctrl->shift));
384 
385 			BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 0x1);
386 			BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD,
387 					BWN_NPHY_RFCTL_CMD_START);
388 			DELAY(1);
389 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, 0xFFFE);
390 		}
391 	}
392 }
393 
394 static void bwn_nphy_rf_ctl_intc_override_rev7(struct bwn_mac *mac,
395 					       enum n_intc_override intc_override,
396 					       uint16_t value, uint8_t core_sel)
397 {
398 	uint16_t reg, tmp, tmp2, val;
399 	int core;
400 
401 	/* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */
402 
403 	for (core = 0; core < 2; core++) {
404 		if ((core_sel == 1 && core != 0) ||
405 		    (core_sel == 2 && core != 1))
406 			continue;
407 
408 		reg = (core == 0) ? BWN_NPHY_RFCTL_INTC1 : BWN_NPHY_RFCTL_INTC2;
409 
410 		switch (intc_override) {
411 		case N_INTC_OVERRIDE_OFF:
412 			BWN_PHY_WRITE(mac, reg, 0);
413 			BWN_PHY_MASK(mac, 0x2ff, ~0x2000);
414 			bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX);
415 			break;
416 		case N_INTC_OVERRIDE_TRSW:
417 			BWN_PHY_SETMASK(mac, reg, ~0xC0, value << 6);
418 			BWN_PHY_SET(mac, reg, 0x400);
419 
420 			BWN_PHY_MASK(mac, 0x2ff, ~0xC000 & 0xFFFF);
421 			BWN_PHY_SET(mac, 0x2ff, 0x2000);
422 			BWN_PHY_SET(mac, 0x2ff, 0x0001);
423 			break;
424 		case N_INTC_OVERRIDE_PA:
425 			tmp = 0x0030;
426 			if (bwn_current_band(mac) == BWN_BAND_5G)
427 				val = value << 5;
428 			else
429 				val = value << 4;
430 			BWN_PHY_SETMASK(mac, reg, ~tmp, val);
431 			BWN_PHY_SET(mac, reg, 0x1000);
432 			break;
433 		case N_INTC_OVERRIDE_EXT_LNA_PU:
434 			if (bwn_current_band(mac) == BWN_BAND_5G) {
435 				tmp = 0x0001;
436 				tmp2 = 0x0004;
437 				val = value;
438 			} else {
439 				tmp = 0x0004;
440 				tmp2 = 0x0001;
441 				val = value << 2;
442 			}
443 			BWN_PHY_SETMASK(mac, reg, ~tmp, val);
444 			BWN_PHY_MASK(mac, reg, ~tmp2);
445 			break;
446 		case N_INTC_OVERRIDE_EXT_LNA_GAIN:
447 			if (bwn_current_band(mac) == BWN_BAND_5G) {
448 				tmp = 0x0002;
449 				tmp2 = 0x0008;
450 				val = value << 1;
451 			} else {
452 				tmp = 0x0008;
453 				tmp2 = 0x0002;
454 				val = value << 3;
455 			}
456 			BWN_PHY_SETMASK(mac, reg, ~tmp, val);
457 			BWN_PHY_MASK(mac, reg, ~tmp2);
458 			break;
459 		}
460 	}
461 }
462 
463 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
464 static void bwn_nphy_rf_ctl_intc_override(struct bwn_mac *mac,
465 					  enum n_intc_override intc_override,
466 					  uint16_t value, uint8_t core)
467 {
468 	uint8_t i, j;
469 	uint16_t reg, tmp, val;
470 
471 	if (mac->mac_phy.rev >= 7) {
472 		bwn_nphy_rf_ctl_intc_override_rev7(mac, intc_override, value,
473 						   core);
474 		return;
475 	}
476 
477 	if (mac->mac_phy.rev < 3) {
478 		BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n",
479 		    __func__,
480 		    mac->mac_phy.rev);
481 	}
482 
483 	for (i = 0; i < 2; i++) {
484 		if ((core == 1 && i == 1) || (core == 2 && !i))
485 			continue;
486 
487 		reg = (i == 0) ?
488 			BWN_NPHY_RFCTL_INTC1 : BWN_NPHY_RFCTL_INTC2;
489 		BWN_PHY_SET(mac, reg, 0x400);
490 
491 		switch (intc_override) {
492 		case N_INTC_OVERRIDE_OFF:
493 			BWN_PHY_WRITE(mac, reg, 0);
494 			bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX);
495 			break;
496 		case N_INTC_OVERRIDE_TRSW:
497 			if (!i) {
498 				BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_INTC1,
499 						0xFC3F, (value << 6));
500 				BWN_PHY_SETMASK(mac, BWN_NPHY_TXF_40CO_B1S1,
501 						0xFFFE, 1);
502 				BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD,
503 						BWN_NPHY_RFCTL_CMD_START);
504 				for (j = 0; j < 100; j++) {
505 					if (!(BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD) & BWN_NPHY_RFCTL_CMD_START)) {
506 						j = 0;
507 						break;
508 					}
509 					DELAY(10);
510 				}
511 				if (j)
512 					BWN_ERRPRINTF(mac->mac_sc,
513 						"intc override timeout\n");
514 				BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S1,
515 						0xFFFE);
516 			} else {
517 				BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_INTC2,
518 						0xFC3F, (value << 6));
519 				BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_OVER,
520 						0xFFFE, 1);
521 				BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD,
522 						BWN_NPHY_RFCTL_CMD_RXTX);
523 				for (j = 0; j < 100; j++) {
524 					if (!(BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD) & BWN_NPHY_RFCTL_CMD_RXTX)) {
525 						j = 0;
526 						break;
527 					}
528 					DELAY(10);
529 				}
530 				if (j)
531 					BWN_ERRPRINTF(mac->mac_sc,
532 						"intc override timeout\n");
533 				BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER,
534 						0xFFFE);
535 			}
536 			break;
537 		case N_INTC_OVERRIDE_PA:
538 			if (bwn_current_band(mac) == BWN_BAND_5G) {
539 				tmp = 0x0020;
540 				val = value << 5;
541 			} else {
542 				tmp = 0x0010;
543 				val = value << 4;
544 			}
545 			BWN_PHY_SETMASK(mac, reg, ~tmp, val);
546 			break;
547 		case N_INTC_OVERRIDE_EXT_LNA_PU:
548 			if (bwn_current_band(mac) == BWN_BAND_5G) {
549 				tmp = 0x0001;
550 				val = value;
551 			} else {
552 				tmp = 0x0004;
553 				val = value << 2;
554 			}
555 			BWN_PHY_SETMASK(mac, reg, ~tmp, val);
556 			break;
557 		case N_INTC_OVERRIDE_EXT_LNA_GAIN:
558 			if (bwn_current_band(mac) == BWN_BAND_5G) {
559 				tmp = 0x0002;
560 				val = value << 1;
561 			} else {
562 				tmp = 0x0008;
563 				val = value << 3;
564 			}
565 			BWN_PHY_SETMASK(mac, reg, ~tmp, val);
566 			break;
567 		}
568 	}
569 }
570 
571 /**************************************************
572  * Various PHY ops
573  **************************************************/
574 
575 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
576 static void bwn_nphy_write_clip_detection(struct bwn_mac *mac,
577 					  const uint16_t *clip_st)
578 {
579 	BWN_PHY_WRITE(mac, BWN_NPHY_C1_CLIP1THRES, clip_st[0]);
580 	BWN_PHY_WRITE(mac, BWN_NPHY_C2_CLIP1THRES, clip_st[1]);
581 }
582 
583 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
584 static void bwn_nphy_read_clip_detection(struct bwn_mac *mac, uint16_t *clip_st)
585 {
586 	clip_st[0] = BWN_PHY_READ(mac, BWN_NPHY_C1_CLIP1THRES);
587 	clip_st[1] = BWN_PHY_READ(mac, BWN_NPHY_C2_CLIP1THRES);
588 }
589 
590 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
591 static uint16_t bwn_nphy_classifier(struct bwn_mac *mac, uint16_t mask, uint16_t val)
592 {
593 	struct bwn_softc *sc = mac->mac_sc;
594 	uint16_t tmp;
595 
596 	if (siba_get_revid(sc->sc_dev) == 16)
597 		bwn_mac_suspend(mac);
598 
599 	tmp = BWN_PHY_READ(mac, BWN_NPHY_CLASSCTL);
600 	tmp &= (BWN_NPHY_CLASSCTL_CCKEN | BWN_NPHY_CLASSCTL_OFDMEN |
601 		BWN_NPHY_CLASSCTL_WAITEDEN);
602 	tmp &= ~mask;
603 	tmp |= (val & mask);
604 	BWN_PHY_SETMASK(mac, BWN_NPHY_CLASSCTL, 0xFFF8, tmp);
605 
606 	if (siba_get_revid(sc->sc_dev) == 16)
607 		bwn_mac_enable(mac);
608 
609 	return tmp;
610 }
611 
612 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
613 static void bwn_nphy_reset_cca(struct bwn_mac *mac)
614 {
615 	uint16_t bbcfg;
616 
617 	bwn_phy_force_clock(mac, 1);
618 	bbcfg = BWN_PHY_READ(mac, BWN_NPHY_BBCFG);
619 	BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, bbcfg | BWN_NPHY_BBCFG_RSTCCA);
620 	DELAY(1);
621 	BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, bbcfg & ~BWN_NPHY_BBCFG_RSTCCA);
622 	bwn_phy_force_clock(mac, 0);
623 	bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX);
624 }
625 
626 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
627 static void bwn_nphy_stay_in_carrier_search(struct bwn_mac *mac, bool enable)
628 {
629 	struct bwn_phy *phy = &mac->mac_phy;
630 	struct bwn_phy_n *nphy = phy->phy_n;
631 
632 	if (enable) {
633 		static const uint16_t clip[] = { 0xFFFF, 0xFFFF };
634 		if (nphy->deaf_count++ == 0) {
635 			nphy->classifier_state = bwn_nphy_classifier(mac, 0, 0);
636 			bwn_nphy_classifier(mac, 0x7,
637 					    BWN_NPHY_CLASSCTL_WAITEDEN);
638 			bwn_nphy_read_clip_detection(mac, nphy->clip_state);
639 			bwn_nphy_write_clip_detection(mac, clip);
640 		}
641 		bwn_nphy_reset_cca(mac);
642 	} else {
643 		if (--nphy->deaf_count == 0) {
644 			bwn_nphy_classifier(mac, 0x7, nphy->classifier_state);
645 			bwn_nphy_write_clip_detection(mac, nphy->clip_state);
646 		}
647 	}
648 }
649 
650 /* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
651 static uint16_t bwn_nphy_read_lpf_ctl(struct bwn_mac *mac, uint16_t offset)
652 {
653 	if (!offset)
654 		offset = bwn_is_40mhz(mac) ? 0x159 : 0x154;
655 	return bwn_ntab_read(mac, BWN_NTAB16(7, offset)) & 0x7;
656 }
657 
658 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
659 static void bwn_nphy_adjust_lna_gain_table(struct bwn_mac *mac)
660 {
661 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
662 
663 	uint8_t i;
664 	int16_t tmp;
665 	uint16_t data[4];
666 	int16_t gain[2];
667 	uint16_t minmax[2];
668 	static const uint16_t lna_gain[4] = { -2, 10, 19, 25 };
669 
670 	if (nphy->hang_avoid)
671 		bwn_nphy_stay_in_carrier_search(mac, 1);
672 
673 	if (nphy->gain_boost) {
674 		if (bwn_current_band(mac) == BWN_BAND_2G) {
675 			gain[0] = 6;
676 			gain[1] = 6;
677 		} else {
678 			tmp = 40370 - 315 * bwn_get_chan(mac);
679 			gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
680 			tmp = 23242 - 224 * bwn_get_chan(mac);
681 			gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
682 		}
683 	} else {
684 		gain[0] = 0;
685 		gain[1] = 0;
686 	}
687 
688 	for (i = 0; i < 2; i++) {
689 		if (nphy->elna_gain_config) {
690 			data[0] = 19 + gain[i];
691 			data[1] = 25 + gain[i];
692 			data[2] = 25 + gain[i];
693 			data[3] = 25 + gain[i];
694 		} else {
695 			data[0] = lna_gain[0] + gain[i];
696 			data[1] = lna_gain[1] + gain[i];
697 			data[2] = lna_gain[2] + gain[i];
698 			data[3] = lna_gain[3] + gain[i];
699 		}
700 		bwn_ntab_write_bulk(mac, BWN_NTAB16(i, 8), 4, data);
701 
702 		minmax[i] = 23 + gain[i];
703 	}
704 
705 	BWN_PHY_SETMASK(mac, BWN_NPHY_C1_MINMAX_GAIN, ~BWN_NPHY_C1_MINGAIN,
706 				minmax[0] << BWN_NPHY_C1_MINGAIN_SHIFT);
707 	BWN_PHY_SETMASK(mac, BWN_NPHY_C2_MINMAX_GAIN, ~BWN_NPHY_C2_MINGAIN,
708 				minmax[1] << BWN_NPHY_C2_MINGAIN_SHIFT);
709 
710 	if (nphy->hang_avoid)
711 		bwn_nphy_stay_in_carrier_search(mac, 0);
712 }
713 
714 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
715 static void bwn_nphy_set_rf_sequence(struct bwn_mac *mac, uint8_t cmd,
716 					uint8_t *events, uint8_t *delays, uint8_t length)
717 {
718 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
719 	uint8_t i;
720 	uint8_t end = (mac->mac_phy.rev >= 3) ? 0x1F : 0x0F;
721 	uint16_t offset1 = cmd << 4;
722 	uint16_t offset2 = offset1 + 0x80;
723 
724 	if (nphy->hang_avoid)
725 		bwn_nphy_stay_in_carrier_search(mac, true);
726 
727 	bwn_ntab_write_bulk(mac, BWN_NTAB8(7, offset1), length, events);
728 	bwn_ntab_write_bulk(mac, BWN_NTAB8(7, offset2), length, delays);
729 
730 	for (i = length; i < 16; i++) {
731 		bwn_ntab_write(mac, BWN_NTAB8(7, offset1 + i), end);
732 		bwn_ntab_write(mac, BWN_NTAB8(7, offset2 + i), 1);
733 	}
734 
735 	if (nphy->hang_avoid)
736 		bwn_nphy_stay_in_carrier_search(mac, false);
737 }
738 
739 /**************************************************
740  * Radio 0x2057
741  **************************************************/
742 
743 static void bwn_radio_2057_chantab_upload(struct bwn_mac *mac,
744 					  const struct bwn_nphy_chantabent_rev7 *e_r7,
745 					  const struct bwn_nphy_chantabent_rev7_2g *e_r7_2g)
746 {
747 	if (e_r7_2g) {
748 		BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0);
749 		BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1);
750 		BWN_RF_WRITE(mac, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize);
751 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1);
752 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2);
753 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1);
754 		BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac);
755 		BWN_RF_WRITE(mac, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0);
756 		BWN_RF_WRITE(mac, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1);
757 		BWN_RF_WRITE(mac, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune);
758 		BWN_RF_WRITE(mac, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune);
759 		BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune);
760 		BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0);
761 		BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0);
762 		BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0);
763 		BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1);
764 		BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1);
765 		BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1);
766 
767 	} else {
768 		BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0);
769 		BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1);
770 		BWN_RF_WRITE(mac, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize);
771 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1);
772 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2);
773 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1);
774 		BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac);
775 		BWN_RF_WRITE(mac, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0);
776 		BWN_RF_WRITE(mac, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1);
777 		BWN_RF_WRITE(mac, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune);
778 		BWN_RF_WRITE(mac, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune);
779 		BWN_RF_WRITE(mac, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune);
780 		BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune);
781 		BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune);
782 		BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0);
783 		BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0);
784 		BWN_RF_WRITE(mac, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0);
785 		BWN_RF_WRITE(mac, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0);
786 		BWN_RF_WRITE(mac, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0);
787 		BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0);
788 		BWN_RF_WRITE(mac, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0);
789 		BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1);
790 		BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1);
791 		BWN_RF_WRITE(mac, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1);
792 		BWN_RF_WRITE(mac, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1);
793 		BWN_RF_WRITE(mac, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1);
794 		BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1);
795 		BWN_RF_WRITE(mac, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1);
796 	}
797 }
798 
799 static void bwn_radio_2057_setup(struct bwn_mac *mac,
800 				 const struct bwn_nphy_chantabent_rev7 *tabent_r7,
801 				 const struct bwn_nphy_chantabent_rev7_2g *tabent_r7_2g)
802 {
803 	struct bwn_phy *phy = &mac->mac_phy;
804 
805 	bwn_radio_2057_chantab_upload(mac, tabent_r7, tabent_r7_2g);
806 
807 	switch (phy->rf_rev) {
808 	case 0 ... 4:
809 	case 6:
810 		if (bwn_current_band(mac) == BWN_BAND_2G) {
811 			BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x3f);
812 			BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f);
813 			BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x8);
814 			BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x8);
815 		} else {
816 			BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x1f);
817 			BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f);
818 			BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x8);
819 			BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x8);
820 		}
821 		break;
822 	case 9: /* e.g. PHY rev 16 */
823 		BWN_RF_WRITE(mac, R2057_LOGEN_PTAT_RESETS, 0x20);
824 		BWN_RF_WRITE(mac, R2057_VCOBUF_IDACS, 0x18);
825 		if (bwn_current_band(mac) == BWN_BAND_5G) {
826 			BWN_RF_WRITE(mac, R2057_LOGEN_PTAT_RESETS, 0x38);
827 			BWN_RF_WRITE(mac, R2057_VCOBUF_IDACS, 0x0f);
828 
829 			if (bwn_is_40mhz(mac)) {
830 				/* TODO */
831 			} else {
832 				BWN_RF_WRITE(mac,
833 						R2057_PAD_BIAS_FILTER_BWS_CORE0,
834 						0x3c);
835 				BWN_RF_WRITE(mac,
836 						R2057_PAD_BIAS_FILTER_BWS_CORE1,
837 						0x3c);
838 			}
839 		}
840 		break;
841 	case 14: /* 2 GHz only */
842 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x1b);
843 		BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f);
844 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x1f);
845 		BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x1f);
846 		break;
847 	}
848 
849 	if (bwn_current_band(mac) == BWN_BAND_2G) {
850 		uint16_t txmix2g_tune_boost_pu = 0;
851 		uint16_t pad2g_tune_pus = 0;
852 
853 		if (bwn_nphy_ipa(mac)) {
854 			switch (phy->rf_rev) {
855 			case 9:
856 				txmix2g_tune_boost_pu = 0x0041;
857 				/* TODO */
858 				break;
859 			case 14:
860 				txmix2g_tune_boost_pu = 0x21;
861 				pad2g_tune_pus = 0x23;
862 				break;
863 			}
864 		}
865 
866 		if (txmix2g_tune_boost_pu)
867 			BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
868 					txmix2g_tune_boost_pu);
869 		if (pad2g_tune_pus)
870 			BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0,
871 					pad2g_tune_pus);
872 		if (txmix2g_tune_boost_pu)
873 			BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
874 					txmix2g_tune_boost_pu);
875 		if (pad2g_tune_pus)
876 			BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1,
877 					pad2g_tune_pus);
878 	}
879 
880 	/* 50..100 */
881 	DELAY(100);
882 
883 	/* VCO calibration */
884 	BWN_RF_MASK(mac, R2057_RFPLL_MISC_EN, ~0x01);
885 	BWN_RF_MASK(mac, R2057_RFPLL_MISC_CAL_RESETN, ~0x04);
886 	BWN_RF_SET(mac, R2057_RFPLL_MISC_CAL_RESETN, 0x4);
887 	BWN_RF_SET(mac, R2057_RFPLL_MISC_EN, 0x01);
888 	/* 300..600 */
889 	DELAY(600);
890 }
891 
892 /* Calibrate resistors in LPF of PLL?
893  * http://bcm-v4.sipsolutions.net/PHY/radio205x_rcal
894  */
895 static uint8_t bwn_radio_2057_rcal(struct bwn_mac *mac)
896 {
897 	struct bwn_phy *phy = &mac->mac_phy;
898 	uint16_t saved_regs_phy[12];
899 	uint16_t saved_regs_phy_rf[6];
900 	uint16_t saved_regs_radio[2] = { };
901 	static const uint16_t phy_to_store[] = {
902 		BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2,
903 		BWN_NPHY_RFCTL_LUT_TRSW_LO1, BWN_NPHY_RFCTL_LUT_TRSW_LO2,
904 		BWN_NPHY_RFCTL_RXG1, BWN_NPHY_RFCTL_RXG2,
905 		BWN_NPHY_RFCTL_TXG1, BWN_NPHY_RFCTL_TXG2,
906 		BWN_NPHY_REV7_RF_CTL_MISC_REG3, BWN_NPHY_REV7_RF_CTL_MISC_REG4,
907 		BWN_NPHY_REV7_RF_CTL_MISC_REG5, BWN_NPHY_REV7_RF_CTL_MISC_REG6,
908 	};
909 	static const uint16_t phy_to_store_rf[] = {
910 		BWN_NPHY_REV3_RFCTL_OVER0, BWN_NPHY_REV3_RFCTL_OVER1,
911 		BWN_NPHY_REV7_RF_CTL_OVER3, BWN_NPHY_REV7_RF_CTL_OVER4,
912 		BWN_NPHY_REV7_RF_CTL_OVER5, BWN_NPHY_REV7_RF_CTL_OVER6,
913 	};
914 	uint16_t tmp;
915 	int i;
916 
917 	/* Save */
918 	for (i = 0; i < nitems(phy_to_store); i++)
919 		saved_regs_phy[i] = BWN_PHY_READ(mac, phy_to_store[i]);
920 	for (i = 0; i < nitems(phy_to_store_rf); i++)
921 		saved_regs_phy_rf[i] = BWN_PHY_READ(mac, phy_to_store_rf[i]);
922 
923 	/* Set */
924 	for (i = 0; i < nitems(phy_to_store); i++)
925 		BWN_PHY_WRITE(mac, phy_to_store[i], 0);
926 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_RFCTL_OVER0, 0x07ff);
927 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_RFCTL_OVER1, 0x07ff);
928 	BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x07ff);
929 	BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER4, 0x07ff);
930 	BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER5, 0x007f);
931 	BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER6, 0x007f);
932 
933 	switch (phy->rf_rev) {
934 	case 5:
935 		BWN_PHY_MASK(mac, BWN_NPHY_REV7_RF_CTL_OVER3, ~0x2);
936 		DELAY(10);
937 		BWN_RF_SET(mac, R2057_IQTEST_SEL_PU, 0x1);
938 		BWN_RF_SETMASK(mac, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1);
939 		break;
940 	case 9:
941 		BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x2);
942 		BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
943 		saved_regs_radio[0] = BWN_RF_READ(mac, R2057_IQTEST_SEL_PU);
944 		BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, 0x11);
945 		break;
946 	case 14:
947 		saved_regs_radio[0] = BWN_RF_READ(mac, R2057_IQTEST_SEL_PU);
948 		saved_regs_radio[1] = BWN_RF_READ(mac, R2057v7_IQTEST_SEL_PU2);
949 		BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
950 		BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x2);
951 		BWN_RF_WRITE(mac, R2057v7_IQTEST_SEL_PU2, 0x2);
952 		BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, 0x1);
953 		break;
954 	}
955 
956 	/* Enable */
957 	BWN_RF_SET(mac, R2057_RCAL_CONFIG, 0x1);
958 	DELAY(10);
959 
960 	/* Start */
961 	BWN_RF_SET(mac, R2057_RCAL_CONFIG, 0x2);
962 	/* 100..200 */
963 	DELAY(200);
964 
965 	/* Stop */
966 	BWN_RF_MASK(mac, R2057_RCAL_CONFIG, ~0x2);
967 
968 	/* Wait and check for result */
969 	if (!bwn_radio_wait_value(mac, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) {
970 		BWN_ERRPRINTF(mac->mac_sc, "Radio 0x2057 rcal timeout\n");
971 		return 0;
972 	}
973 	tmp = BWN_RF_READ(mac, R2057_RCAL_STATUS) & 0x3E;
974 
975 	/* Disable */
976 	BWN_RF_MASK(mac, R2057_RCAL_CONFIG, ~0x1);
977 
978 	/* Restore */
979 	for (i = 0; i < nitems(phy_to_store_rf); i++)
980 		BWN_PHY_WRITE(mac, phy_to_store_rf[i], saved_regs_phy_rf[i]);
981 	for (i = 0; i < nitems(phy_to_store); i++)
982 		BWN_PHY_WRITE(mac, phy_to_store[i], saved_regs_phy[i]);
983 
984 	switch (phy->rf_rev) {
985 	case 0 ... 4:
986 	case 6:
987 		BWN_RF_SETMASK(mac, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
988 		BWN_RF_SETMASK(mac, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
989 				  tmp << 2);
990 		break;
991 	case 5:
992 		BWN_RF_MASK(mac, R2057_IPA2G_CASCONV_CORE0, ~0x1);
993 		BWN_RF_MASK(mac, R2057v7_IQTEST_SEL_PU2, ~0x2);
994 		break;
995 	case 9:
996 		BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
997 		break;
998 	case 14:
999 		BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
1000 		BWN_RF_WRITE(mac, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]);
1001 		break;
1002 	}
1003 
1004 	return tmp & 0x3e;
1005 }
1006 
1007 /* Calibrate the internal RC oscillator?
1008  * http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal
1009  */
1010 static uint16_t bwn_radio_2057_rccal(struct bwn_mac *mac)
1011 {
1012 	struct bwn_phy *phy = &mac->mac_phy;
1013 	bool special = (phy->rf_rev == 3 || phy->rf_rev == 4 ||
1014 			phy->rf_rev == 6);
1015 	uint16_t tmp;
1016 
1017 	/* Setup cal */
1018 	if (special) {
1019 		BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x61);
1020 		BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xC0);
1021 	} else {
1022 		BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x61);
1023 		BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xE9);
1024 	}
1025 	BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E);
1026 
1027 	/* Start, wait, stop */
1028 	BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55);
1029 	if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
1030 				  5000000))
1031 		BWN_DBGPRINTF(mac, "Radio 0x2057 rccal timeout\n");
1032 	/* 35..70 */
1033 	DELAY(70);
1034 	BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15);
1035 	/* 70..140 */
1036 	DELAY(140);
1037 
1038 	/* Setup cal */
1039 	if (special) {
1040 		BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x69);
1041 		BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xB0);
1042 	} else {
1043 		BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x69);
1044 		BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xD5);
1045 	}
1046 	BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E);
1047 
1048 	/* Start, wait, stop */
1049 	/* 35..70 */
1050 	DELAY(70);
1051 	BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55);
1052 	/* 70..140 */
1053 	DELAY(140);
1054 	if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
1055 				  5000000))
1056 		BWN_DBGPRINTF(mac, "Radio 0x2057 rccal timeout\n");
1057 	/* 35..70 */
1058 	DELAY(70);
1059 	BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15);
1060 	/* 70..140 */
1061 	DELAY(140);
1062 
1063 	/* Setup cal */
1064 	if (special) {
1065 		BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x73);
1066 		BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x28);
1067 		BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xB0);
1068 	} else {
1069 		BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x73);
1070 		BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E);
1071 		BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0x99);
1072 	}
1073 
1074 	/* Start, wait, stop */
1075 	/* 35..70 */
1076 	DELAY(70);
1077 	BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55);
1078 	/* 70..140 */
1079 	DELAY(140);
1080 	if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
1081 				  5000000)) {
1082 		BWN_ERRPRINTF(mac->mac_sc, "Radio 0x2057 rcal timeout\n");
1083 		return 0;
1084 	}
1085 	tmp = BWN_RF_READ(mac, R2057_RCCAL_DONE_OSCCAP);
1086 	/* 35..70 */
1087 	DELAY(70);
1088 	BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15);
1089 	/* 70..140 */
1090 	DELAY(140);
1091 
1092 	if (special)
1093 		BWN_RF_MASK(mac, R2057_RCCAL_MASTER, ~0x1);
1094 	else
1095 		BWN_RF_MASK(mac, R2057v7_RCCAL_MASTER, ~0x1);
1096 
1097 	return tmp;
1098 }
1099 
1100 static void bwn_radio_2057_init_pre(struct bwn_mac *mac)
1101 {
1102 	BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, ~BWN_NPHY_RFCTL_CMD_CHIP0PU);
1103 	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
1104 	BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_OEPORFORCE);
1105 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, ~BWN_NPHY_RFCTL_CMD_OEPORFORCE);
1106 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_CHIP0PU);
1107 }
1108 
1109 static void bwn_radio_2057_init_post(struct bwn_mac *mac)
1110 {
1111 	BWN_RF_SET(mac, R2057_XTALPUOVR_PINCTRL, 0x1);
1112 
1113 	if (0) /* FIXME: Is this BCM43217 specific? */
1114 		BWN_RF_SET(mac, R2057_XTALPUOVR_PINCTRL, 0x2);
1115 
1116 	BWN_RF_SET(mac, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
1117 	BWN_RF_SET(mac, R2057_XTAL_CONFIG2, 0x80);
1118 	DELAY(2000);
1119 	BWN_RF_MASK(mac, R2057_RFPLL_MISC_CAL_RESETN, ~0x78);
1120 	BWN_RF_MASK(mac, R2057_XTAL_CONFIG2, ~0x80);
1121 
1122 	if (mac->mac_phy.phy_do_full_init) {
1123 		bwn_radio_2057_rcal(mac);
1124 		bwn_radio_2057_rccal(mac);
1125 	}
1126 	BWN_RF_MASK(mac, R2057_RFPLL_MASTER, ~0x8);
1127 }
1128 
1129 /* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
1130 static void bwn_radio_2057_init(struct bwn_mac *mac)
1131 {
1132 	bwn_radio_2057_init_pre(mac);
1133 	r2057_upload_inittabs(mac);
1134 	bwn_radio_2057_init_post(mac);
1135 }
1136 
1137 /**************************************************
1138  * Radio 0x2056
1139  **************************************************/
1140 
1141 static void bwn_chantab_radio_2056_upload(struct bwn_mac *mac,
1142 				const struct bwn_nphy_channeltab_entry_rev3 *e)
1143 {
1144 	BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
1145 	BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
1146 	BWN_RF_WRITE(mac, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
1147 	BWN_RF_WRITE(mac, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
1148 	BWN_RF_WRITE(mac, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
1149 	BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1,
1150 					e->radio_syn_pll_loopfilter1);
1151 	BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2,
1152 					e->radio_syn_pll_loopfilter2);
1153 	BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER3,
1154 					e->radio_syn_pll_loopfilter3);
1155 	BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4,
1156 					e->radio_syn_pll_loopfilter4);
1157 	BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER5,
1158 					e->radio_syn_pll_loopfilter5);
1159 	BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR27,
1160 					e->radio_syn_reserved_addr27);
1161 	BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR28,
1162 					e->radio_syn_reserved_addr28);
1163 	BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR29,
1164 					e->radio_syn_reserved_addr29);
1165 	BWN_RF_WRITE(mac, B2056_SYN_LOGEN_VCOBUF1,
1166 					e->radio_syn_logen_vcobuf1);
1167 	BWN_RF_WRITE(mac, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
1168 	BWN_RF_WRITE(mac, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
1169 	BWN_RF_WRITE(mac, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
1170 
1171 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAA_TUNE,
1172 					e->radio_rx0_lnaa_tune);
1173 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAG_TUNE,
1174 					e->radio_rx0_lnag_tune);
1175 
1176 	BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
1177 					e->radio_tx0_intpaa_boost_tune);
1178 	BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
1179 					e->radio_tx0_intpag_boost_tune);
1180 	BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
1181 					e->radio_tx0_pada_boost_tune);
1182 	BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
1183 					e->radio_tx0_padg_boost_tune);
1184 	BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
1185 					e->radio_tx0_pgaa_boost_tune);
1186 	BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
1187 					e->radio_tx0_pgag_boost_tune);
1188 	BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
1189 					e->radio_tx0_mixa_boost_tune);
1190 	BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
1191 					e->radio_tx0_mixg_boost_tune);
1192 
1193 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAA_TUNE,
1194 					e->radio_rx1_lnaa_tune);
1195 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAG_TUNE,
1196 					e->radio_rx1_lnag_tune);
1197 
1198 	BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
1199 					e->radio_tx1_intpaa_boost_tune);
1200 	BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
1201 					e->radio_tx1_intpag_boost_tune);
1202 	BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
1203 					e->radio_tx1_pada_boost_tune);
1204 	BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
1205 					e->radio_tx1_padg_boost_tune);
1206 	BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
1207 					e->radio_tx1_pgaa_boost_tune);
1208 	BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
1209 					e->radio_tx1_pgag_boost_tune);
1210 	BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
1211 					e->radio_tx1_mixa_boost_tune);
1212 	BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
1213 					e->radio_tx1_mixg_boost_tune);
1214 }
1215 
1216 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
1217 static void bwn_radio_2056_setup(struct bwn_mac *mac,
1218 				const struct bwn_nphy_channeltab_entry_rev3 *e)
1219 {
1220 	struct bwn_softc *sc = mac->mac_sc;
1221 	bwn_band_t band = bwn_current_band(mac);
1222 	uint16_t offset;
1223 	uint8_t i;
1224 	uint16_t bias, cbias;
1225 	uint16_t pag_boost, padg_boost, pgag_boost, mixg_boost;
1226 	uint16_t paa_boost, pada_boost, pgaa_boost, mixa_boost;
1227 	bool is_pkg_fab_smic;
1228 
1229 	DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__);
1230 
1231 	if (mac->mac_phy.rev < 3) {
1232 		BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n",
1233 		    __func__,
1234 		    mac->mac_phy.rev);
1235 	}
1236 
1237 	is_pkg_fab_smic =
1238 		((siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM43224 ||
1239 		  siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM43225 ||
1240 		  siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM43421) &&
1241 		 siba_get_chippkg(sc->sc_dev) == BCMA_PKG_ID_BCM43224_FAB_SMIC);
1242 
1243 	bwn_chantab_radio_2056_upload(mac, e);
1244 	b2056_upload_syn_pll_cp2(mac, band == BWN_BAND_5G);
1245 
1246 	if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_GPLL_WAR &&
1247 	    bwn_current_band(mac) == BWN_BAND_2G) {
1248 		BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
1249 		BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
1250 		if (siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM4716 ||
1251 		    siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM47162) {
1252 			BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x14);
1253 			BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0);
1254 		} else {
1255 			BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
1256 			BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x14);
1257 		}
1258 	}
1259 	if (siba_sprom_get_bf2_hi(sc->sc_dev) & BWN_BFH2_GPLL_WAR2 &&
1260 	    bwn_current_band(mac) == BWN_BAND_2G) {
1261 		BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1f);
1262 		BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1f);
1263 		BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x0b);
1264 		BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x20);
1265 	}
1266 	if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_APLL_WAR &&
1267 	    bwn_current_band(mac) == BWN_BAND_5G) {
1268 		BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
1269 		BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
1270 		BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x05);
1271 		BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x0C);
1272 	}
1273 
1274 	if (mac->mac_phy.phy_n->ipa2g_on && band == BWN_BAND_2G) {
1275 		for (i = 0; i < 2; i++) {
1276 			offset = i ? B2056_TX1 : B2056_TX0;
1277 			if (mac->mac_phy.rev >= 5) {
1278 				BWN_RF_WRITE(mac,
1279 					offset | B2056_TX_PADG_IDAC, 0xcc);
1280 
1281 				if (siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM4716 ||
1282 				    siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM47162) {
1283 					bias = 0x40;
1284 					cbias = 0x45;
1285 					pag_boost = 0x5;
1286 					pgag_boost = 0x33;
1287 					mixg_boost = 0x55;
1288 				} else {
1289 					bias = 0x25;
1290 					cbias = 0x20;
1291 					if (is_pkg_fab_smic) {
1292 						bias = 0x2a;
1293 						cbias = 0x38;
1294 					}
1295 					pag_boost = 0x4;
1296 					pgag_boost = 0x03;
1297 					mixg_boost = 0x65;
1298 				}
1299 				padg_boost = 0x77;
1300 
1301 				BWN_RF_WRITE(mac,
1302 					offset | B2056_TX_INTPAG_IMAIN_STAT,
1303 					bias);
1304 				BWN_RF_WRITE(mac,
1305 					offset | B2056_TX_INTPAG_IAUX_STAT,
1306 					bias);
1307 				BWN_RF_WRITE(mac,
1308 					offset | B2056_TX_INTPAG_CASCBIAS,
1309 					cbias);
1310 				BWN_RF_WRITE(mac,
1311 					offset | B2056_TX_INTPAG_BOOST_TUNE,
1312 					pag_boost);
1313 				BWN_RF_WRITE(mac,
1314 					offset | B2056_TX_PGAG_BOOST_TUNE,
1315 					pgag_boost);
1316 				BWN_RF_WRITE(mac,
1317 					offset | B2056_TX_PADG_BOOST_TUNE,
1318 					padg_boost);
1319 				BWN_RF_WRITE(mac,
1320 					offset | B2056_TX_MIXG_BOOST_TUNE,
1321 					mixg_boost);
1322 			} else {
1323 				bias = bwn_is_40mhz(mac) ? 0x40 : 0x20;
1324 				BWN_RF_WRITE(mac,
1325 					offset | B2056_TX_INTPAG_IMAIN_STAT,
1326 					bias);
1327 				BWN_RF_WRITE(mac,
1328 					offset | B2056_TX_INTPAG_IAUX_STAT,
1329 					bias);
1330 				BWN_RF_WRITE(mac,
1331 					offset | B2056_TX_INTPAG_CASCBIAS,
1332 					0x30);
1333 			}
1334 			BWN_RF_WRITE(mac, offset | B2056_TX_PA_SPARE1, 0xee);
1335 		}
1336 	} else if (mac->mac_phy.phy_n->ipa5g_on && band == BWN_BAND_5G) {
1337 		uint16_t freq = bwn_get_centre_freq(mac);
1338 		/* XXX 5g low/med/high? */
1339 		if (freq < 5100) {
1340 			paa_boost = 0xA;
1341 			pada_boost = 0x77;
1342 			pgaa_boost = 0xF;
1343 			mixa_boost = 0xF;
1344 		} else if (freq < 5340) {
1345 			paa_boost = 0x8;
1346 			pada_boost = 0x77;
1347 			pgaa_boost = 0xFB;
1348 			mixa_boost = 0xF;
1349 		} else if (freq < 5650) {
1350 			paa_boost = 0x0;
1351 			pada_boost = 0x77;
1352 			pgaa_boost = 0xB;
1353 			mixa_boost = 0xF;
1354 		} else {
1355 			paa_boost = 0x0;
1356 			pada_boost = 0x77;
1357 			if (freq != 5825)
1358 				pgaa_boost = -(freq - 18) / 36 + 168;
1359 			else
1360 				pgaa_boost = 6;
1361 			mixa_boost = 0xF;
1362 		}
1363 
1364 		cbias = is_pkg_fab_smic ? 0x35 : 0x30;
1365 
1366 		for (i = 0; i < 2; i++) {
1367 			offset = i ? B2056_TX1 : B2056_TX0;
1368 
1369 			BWN_RF_WRITE(mac,
1370 				offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost);
1371 			BWN_RF_WRITE(mac,
1372 				offset | B2056_TX_PADA_BOOST_TUNE, pada_boost);
1373 			BWN_RF_WRITE(mac,
1374 				offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost);
1375 			BWN_RF_WRITE(mac,
1376 				offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost);
1377 			BWN_RF_WRITE(mac,
1378 				offset | B2056_TX_TXSPARE1, 0x30);
1379 			BWN_RF_WRITE(mac,
1380 				offset | B2056_TX_PA_SPARE2, 0xee);
1381 			BWN_RF_WRITE(mac,
1382 				offset | B2056_TX_PADA_CASCBIAS, 0x03);
1383 			BWN_RF_WRITE(mac,
1384 				offset | B2056_TX_INTPAA_IAUX_STAT, 0x30);
1385 			BWN_RF_WRITE(mac,
1386 				offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30);
1387 			BWN_RF_WRITE(mac,
1388 				offset | B2056_TX_INTPAA_CASCBIAS, cbias);
1389 		}
1390 	}
1391 
1392 	DELAY(50);
1393 	/* VCO calibration */
1394 	BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL12, 0x00);
1395 	BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x38);
1396 	BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x18);
1397 	BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x38);
1398 	BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x39);
1399 	DELAY(300);
1400 }
1401 
1402 static uint8_t bwn_radio_2056_rcal(struct bwn_mac *mac)
1403 {
1404 	struct bwn_phy *phy = &mac->mac_phy;
1405 	uint16_t mast2, tmp;
1406 
1407 	if (phy->rev != 3)
1408 		return 0;
1409 	DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__);
1410 
1411 	mast2 = BWN_RF_READ(mac, B2056_SYN_PLL_MAST2);
1412 	BWN_RF_WRITE(mac, B2056_SYN_PLL_MAST2, mast2 | 0x7);
1413 
1414 	DELAY(10);
1415 	BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x01);
1416 	DELAY(10);
1417 	BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x09);
1418 
1419 	if (!bwn_radio_wait_value(mac, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100,
1420 				  1000000)) {
1421 		BWN_ERRPRINTF(mac->mac_sc, "Radio recalibration timeout\n");
1422 		return 0;
1423 	}
1424 
1425 	BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x01);
1426 	tmp = BWN_RF_READ(mac, B2056_SYN_RCAL_CODE_OUT);
1427 	BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x00);
1428 
1429 	BWN_RF_WRITE(mac, B2056_SYN_PLL_MAST2, mast2);
1430 
1431 	return tmp & 0x1f;
1432 }
1433 
1434 static void bwn_radio_init2056_pre(struct bwn_mac *mac)
1435 {
1436 	DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__);
1437 
1438 	BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD,
1439 		     ~BWN_NPHY_RFCTL_CMD_CHIP0PU);
1440 	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
1441 	BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD,
1442 		     BWN_NPHY_RFCTL_CMD_OEPORFORCE);
1443 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD,
1444 		    ~BWN_NPHY_RFCTL_CMD_OEPORFORCE);
1445 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD,
1446 		    BWN_NPHY_RFCTL_CMD_CHIP0PU);
1447 }
1448 
1449 static void bwn_radio_init2056_post(struct bwn_mac *mac)
1450 {
1451 	DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__);
1452 
1453 	BWN_RF_SET(mac, B2056_SYN_COM_CTRL, 0xB);
1454 	BWN_RF_SET(mac, B2056_SYN_COM_PU, 0x2);
1455 	BWN_RF_SET(mac, B2056_SYN_COM_RESET, 0x2);
1456 	DELAY(1000);
1457 	BWN_RF_MASK(mac, B2056_SYN_COM_RESET, ~0x2);
1458 	BWN_RF_MASK(mac, B2056_SYN_PLL_MAST2, ~0xFC);
1459 	BWN_RF_MASK(mac, B2056_SYN_RCCAL_CTRL0, ~0x1);
1460 	if (mac->mac_phy.phy_do_full_init)
1461 		bwn_radio_2056_rcal(mac);
1462 }
1463 
1464 /*
1465  * Initialize a Broadcom 2056 N-radio
1466  * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
1467  */
1468 static void bwn_radio_init2056(struct bwn_mac *mac)
1469 {
1470 	DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__);
1471 
1472 	bwn_radio_init2056_pre(mac);
1473 	b2056_upload_inittabs(mac, 0, 0);
1474 	bwn_radio_init2056_post(mac);
1475 }
1476 
1477 /**************************************************
1478  * Radio 0x2055
1479  **************************************************/
1480 
1481 static void bwn_chantab_radio_upload(struct bwn_mac *mac,
1482 				const struct bwn_nphy_channeltab_entry_rev2 *e)
1483 {
1484 	BWN_RF_WRITE(mac, B2055_PLL_REF, e->radio_pll_ref);
1485 	BWN_RF_WRITE(mac, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
1486 	BWN_RF_WRITE(mac, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
1487 	BWN_RF_WRITE(mac, B2055_VCO_CAPTAIL, e->radio_vco_captail);
1488 	BWN_READ_4(mac, BWN_MACCTL); /* flush writes */
1489 
1490 	BWN_RF_WRITE(mac, B2055_VCO_CAL1, e->radio_vco_cal1);
1491 	BWN_RF_WRITE(mac, B2055_VCO_CAL2, e->radio_vco_cal2);
1492 	BWN_RF_WRITE(mac, B2055_PLL_LFC1, e->radio_pll_lfc1);
1493 	BWN_RF_WRITE(mac, B2055_PLL_LFR1, e->radio_pll_lfr1);
1494 	BWN_READ_4(mac, BWN_MACCTL); /* flush writes */
1495 
1496 	BWN_RF_WRITE(mac, B2055_PLL_LFC2, e->radio_pll_lfc2);
1497 	BWN_RF_WRITE(mac, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
1498 	BWN_RF_WRITE(mac, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
1499 	BWN_RF_WRITE(mac, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
1500 	BWN_READ_4(mac, BWN_MACCTL); /* flush writes */
1501 
1502 	BWN_RF_WRITE(mac, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
1503 	BWN_RF_WRITE(mac, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
1504 	BWN_RF_WRITE(mac, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
1505 	BWN_RF_WRITE(mac, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
1506 	BWN_READ_4(mac, BWN_MACCTL); /* flush writes */
1507 
1508 	BWN_RF_WRITE(mac, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
1509 	BWN_RF_WRITE(mac, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
1510 	BWN_RF_WRITE(mac, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
1511 	BWN_RF_WRITE(mac, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
1512 	BWN_READ_4(mac, BWN_MACCTL); /* flush writes */
1513 
1514 	BWN_RF_WRITE(mac, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
1515 	BWN_RF_WRITE(mac, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
1516 }
1517 
1518 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
1519 static void bwn_radio_2055_setup(struct bwn_mac *mac,
1520 				const struct bwn_nphy_channeltab_entry_rev2 *e)
1521 {
1522 
1523 	if (mac->mac_phy.rev >= 3) {
1524 		BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n",
1525 		    __func__,
1526 		    mac->mac_phy.rev);
1527 	}
1528 
1529 	DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__);
1530 
1531 	bwn_chantab_radio_upload(mac, e);
1532 	DELAY(50);
1533 	BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x05);
1534 	BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x45);
1535 	BWN_READ_4(mac, BWN_MACCTL); /* flush writes */
1536 	BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x65);
1537 	DELAY(300);
1538 }
1539 
1540 static void bwn_radio_init2055_pre(struct bwn_mac *mac)
1541 {
1542 	BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD,
1543 		     ~BWN_NPHY_RFCTL_CMD_PORFORCE);
1544 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD,
1545 		    BWN_NPHY_RFCTL_CMD_CHIP0PU |
1546 		    BWN_NPHY_RFCTL_CMD_OEPORFORCE);
1547 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD,
1548 		    BWN_NPHY_RFCTL_CMD_PORFORCE);
1549 }
1550 
1551 static void bwn_radio_init2055_post(struct bwn_mac *mac)
1552 {
1553 	struct bwn_softc *sc = mac->mac_sc;
1554 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
1555 	bool workaround = false;
1556 
1557 	if (siba_get_revid(sc->sc_dev) < 4)
1558 		workaround =
1559 		    (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM)
1560 		    && (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4321)
1561 		      && (siba_sprom_get_brev(sc->sc_dev) >= 0x41);
1562 	else
1563 		workaround =
1564 			!(siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_RXBB_INT_REG_DIS);
1565 
1566 	BWN_RF_MASK(mac, B2055_MASTER1, 0xFFF3);
1567 	if (workaround) {
1568 		BWN_RF_MASK(mac, B2055_C1_RX_BB_REG, 0x7F);
1569 		BWN_RF_MASK(mac, B2055_C2_RX_BB_REG, 0x7F);
1570 	}
1571 	BWN_RF_SETMASK(mac, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
1572 	BWN_RF_WRITE(mac, B2055_CAL_MISC, 0x3C);
1573 	BWN_RF_MASK(mac, B2055_CAL_MISC, 0xFFBE);
1574 	BWN_RF_SET(mac, B2055_CAL_LPOCTL, 0x80);
1575 	BWN_RF_SET(mac, B2055_CAL_MISC, 0x1);
1576 	DELAY(1000);
1577 	BWN_RF_SET(mac, B2055_CAL_MISC, 0x40);
1578 	if (!bwn_radio_wait_value(mac, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000))
1579 		BWN_ERRPRINTF(mac->mac_sc, "radio post init timeout\n");
1580 	BWN_RF_MASK(mac, B2055_CAL_LPOCTL, 0xFF7F);
1581 	bwn_switch_channel(mac, bwn_get_chan(mac));
1582 	BWN_RF_WRITE(mac, B2055_C1_RX_BB_LPF, 0x9);
1583 	BWN_RF_WRITE(mac, B2055_C2_RX_BB_LPF, 0x9);
1584 	BWN_RF_WRITE(mac, B2055_C1_RX_BB_MIDACHP, 0x83);
1585 	BWN_RF_WRITE(mac, B2055_C2_RX_BB_MIDACHP, 0x83);
1586 	BWN_RF_SETMASK(mac, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
1587 	BWN_RF_SETMASK(mac, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
1588 	if (!nphy->gain_boost) {
1589 		BWN_RF_SET(mac, B2055_C1_RX_RFSPC1, 0x2);
1590 		BWN_RF_SET(mac, B2055_C2_RX_RFSPC1, 0x2);
1591 	} else {
1592 		BWN_RF_MASK(mac, B2055_C1_RX_RFSPC1, 0xFFFD);
1593 		BWN_RF_MASK(mac, B2055_C2_RX_RFSPC1, 0xFFFD);
1594 	}
1595 	DELAY(2);
1596 }
1597 
1598 /*
1599  * Initialize a Broadcom 2055 N-radio
1600  * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
1601  */
1602 static void bwn_radio_init2055(struct bwn_mac *mac)
1603 {
1604 	bwn_radio_init2055_pre(mac);
1605 	if (mac->mac_status < BWN_MAC_STATUS_INITED) {
1606 		/* Follow wl, not specs. Do not force uploading all regs */
1607 		b2055_upload_inittab(mac, 0, 0);
1608 	} else {
1609 		bool ghz5 = bwn_current_band(mac) == BWN_BAND_5G;
1610 		b2055_upload_inittab(mac, ghz5, 0);
1611 	}
1612 	bwn_radio_init2055_post(mac);
1613 }
1614 
1615 /**************************************************
1616  * Samples
1617  **************************************************/
1618 
1619 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
1620 static int bwn_nphy_load_samples(struct bwn_mac *mac,
1621 					struct bwn_c32 *samples, uint16_t len) {
1622 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
1623 	uint16_t i;
1624 	uint32_t *data;
1625 
1626 	data = malloc(len * sizeof(uint32_t), M_DEVBUF, M_NOWAIT | M_ZERO);
1627 	if (!data) {
1628 		BWN_ERRPRINTF(mac->mac_sc, "allocation for samples loading failed\n");
1629 		return -ENOMEM;
1630 	}
1631 	if (nphy->hang_avoid)
1632 		bwn_nphy_stay_in_carrier_search(mac, 1);
1633 
1634 	for (i = 0; i < len; i++) {
1635 		data[i] = (samples[i].i & 0x3FF << 10);
1636 		data[i] |= samples[i].q & 0x3FF;
1637 	}
1638 	bwn_ntab_write_bulk(mac, BWN_NTAB32(17, 0), len, data);
1639 
1640 	free(data, M_DEVBUF);
1641 	if (nphy->hang_avoid)
1642 		bwn_nphy_stay_in_carrier_search(mac, 0);
1643 	return 0;
1644 }
1645 
1646 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
1647 static uint16_t bwn_nphy_gen_load_samples(struct bwn_mac *mac, uint32_t freq, uint16_t max,
1648 					bool test)
1649 {
1650 	int i;
1651 	uint16_t bw, len, rot, angle;
1652 	struct bwn_c32 *samples;
1653 
1654 	bw = bwn_is_40mhz(mac) ? 40 : 20;
1655 	len = bw << 3;
1656 
1657 	if (test) {
1658 		if (BWN_PHY_READ(mac, BWN_NPHY_BBCFG) & BWN_NPHY_BBCFG_RSTRX)
1659 			bw = 82;
1660 		else
1661 			bw = 80;
1662 
1663 		if (bwn_is_40mhz(mac))
1664 			bw <<= 1;
1665 
1666 		len = bw << 1;
1667 	}
1668 
1669 	samples = malloc(len * sizeof(struct bwn_c32), M_DEVBUF, M_NOWAIT | M_ZERO);
1670 	if (!samples) {
1671 		BWN_ERRPRINTF(mac->mac_sc, "allocation for samples generation failed\n");
1672 		return 0;
1673 	}
1674 	rot = (((freq * 36) / bw) << 16) / 100;
1675 	angle = 0;
1676 
1677 	for (i = 0; i < len; i++) {
1678 		samples[i] = bwn_cordic(angle);
1679 		angle += rot;
1680 		samples[i].q = CORDIC_CONVERT(samples[i].q * max);
1681 		samples[i].i = CORDIC_CONVERT(samples[i].i * max);
1682 	}
1683 
1684 	i = bwn_nphy_load_samples(mac, samples, len);
1685 	free(samples, M_DEVBUF);
1686 	return (i < 0) ? 0 : len;
1687 }
1688 
1689 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
1690 static void bwn_nphy_run_samples(struct bwn_mac *mac, uint16_t samps, uint16_t loops,
1691 				 uint16_t wait, bool iqmode, bool dac_test,
1692 				 bool modify_bbmult)
1693 {
1694 	struct bwn_phy *phy = &mac->mac_phy;
1695 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
1696 	int i;
1697 	uint16_t seq_mode;
1698 	uint32_t tmp;
1699 
1700 	bwn_nphy_stay_in_carrier_search(mac, true);
1701 
1702 	if (phy->rev >= 7) {
1703 		bool lpf_bw3, lpf_bw4;
1704 
1705 		lpf_bw3 = BWN_PHY_READ(mac, BWN_NPHY_REV7_RF_CTL_OVER3) & 0x80;
1706 		lpf_bw4 = BWN_PHY_READ(mac, BWN_NPHY_REV7_RF_CTL_OVER4) & 0x80;
1707 
1708 		if (lpf_bw3 || lpf_bw4) {
1709 			/* TODO */
1710 		} else {
1711 			uint16_t value = bwn_nphy_read_lpf_ctl(mac, 0);
1712 			if (phy->rev >= 19)
1713 				bwn_nphy_rf_ctl_override_rev19(mac, 0x80, value,
1714 							       0, false, 1);
1715 			else
1716 				bwn_nphy_rf_ctl_override_rev7(mac, 0x80, value,
1717 							      0, false, 1);
1718 			nphy->lpf_bw_overrode_for_sample_play = true;
1719 		}
1720 	}
1721 
1722 	if ((nphy->bb_mult_save & 0x80000000) == 0) {
1723 		tmp = bwn_ntab_read(mac, BWN_NTAB16(15, 87));
1724 		nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
1725 	}
1726 
1727 	if (modify_bbmult) {
1728 		tmp = !bwn_is_40mhz(mac) ? 0x6464 : 0x4747;
1729 		bwn_ntab_write(mac, BWN_NTAB16(15, 87), tmp);
1730 	}
1731 
1732 	BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_DEPCNT, (samps - 1));
1733 
1734 	if (loops != 0xFFFF)
1735 		BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_LOOPCNT, (loops - 1));
1736 	else
1737 		BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_LOOPCNT, loops);
1738 
1739 	BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_WAITCNT, wait);
1740 
1741 	seq_mode = BWN_PHY_READ(mac, BWN_NPHY_RFSEQMODE);
1742 
1743 	BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, BWN_NPHY_RFSEQMODE_CAOVER);
1744 	if (iqmode) {
1745 		BWN_PHY_MASK(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
1746 		BWN_PHY_SET(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8000);
1747 	} else {
1748 		tmp = dac_test ? 5 : 1;
1749 		BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_CMD, tmp);
1750 	}
1751 	for (i = 0; i < 100; i++) {
1752 		if (!(BWN_PHY_READ(mac, BWN_NPHY_RFSEQST) & 1)) {
1753 			i = 0;
1754 			break;
1755 		}
1756 		DELAY(10);
1757 	}
1758 	if (i)
1759 		BWN_ERRPRINTF(mac->mac_sc, "run samples timeout\n");
1760 
1761 	BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQMODE, seq_mode);
1762 
1763 	bwn_nphy_stay_in_carrier_search(mac, false);
1764 }
1765 
1766 /**************************************************
1767  * RSSI
1768  **************************************************/
1769 
1770 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
1771 static void bwn_nphy_scale_offset_rssi(struct bwn_mac *mac, uint16_t scale,
1772 					int8_t offset, uint8_t core,
1773 					enum n_rail_type rail,
1774 					enum n_rssi_type rssi_type)
1775 {
1776 	uint16_t tmp;
1777 	bool core1or5 = (core == 1) || (core == 5);
1778 	bool core2or5 = (core == 2) || (core == 5);
1779 
1780 	offset = bwn_clamp_val(offset, -32, 31);
1781 	tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
1782 
1783 	switch (rssi_type) {
1784 	case N_RSSI_NB:
1785 		if (core1or5 && rail == N_RAIL_I)
1786 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z, tmp);
1787 		if (core1or5 && rail == N_RAIL_Q)
1788 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
1789 		if (core2or5 && rail == N_RAIL_I)
1790 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z, tmp);
1791 		if (core2or5 && rail == N_RAIL_Q)
1792 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
1793 		break;
1794 	case N_RSSI_W1:
1795 		if (core1or5 && rail == N_RAIL_I)
1796 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_X, tmp);
1797 		if (core1or5 && rail == N_RAIL_Q)
1798 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X, tmp);
1799 		if (core2or5 && rail == N_RAIL_I)
1800 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_X, tmp);
1801 		if (core2or5 && rail == N_RAIL_Q)
1802 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X, tmp);
1803 		break;
1804 	case N_RSSI_W2:
1805 		if (core1or5 && rail == N_RAIL_I)
1806 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y, tmp);
1807 		if (core1or5 && rail == N_RAIL_Q)
1808 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
1809 		if (core2or5 && rail == N_RAIL_I)
1810 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y, tmp);
1811 		if (core2or5 && rail == N_RAIL_Q)
1812 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
1813 		break;
1814 	case N_RSSI_TBD:
1815 		if (core1or5 && rail == N_RAIL_I)
1816 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_TBD, tmp);
1817 		if (core1or5 && rail == N_RAIL_Q)
1818 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_TBD, tmp);
1819 		if (core2or5 && rail == N_RAIL_I)
1820 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_TBD, tmp);
1821 		if (core2or5 && rail == N_RAIL_Q)
1822 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_TBD, tmp);
1823 		break;
1824 	case N_RSSI_IQ:
1825 		if (core1or5 && rail == N_RAIL_I)
1826 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_PWRDET, tmp);
1827 		if (core1or5 && rail == N_RAIL_Q)
1828 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_PWRDET, tmp);
1829 		if (core2or5 && rail == N_RAIL_I)
1830 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_PWRDET, tmp);
1831 		if (core2or5 && rail == N_RAIL_Q)
1832 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_PWRDET, tmp);
1833 		break;
1834 	case N_RSSI_TSSI_2G:
1835 		if (core1or5)
1836 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_TSSI, tmp);
1837 		if (core2or5)
1838 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_TSSI, tmp);
1839 		break;
1840 	case N_RSSI_TSSI_5G:
1841 		if (core1or5)
1842 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_TSSI, tmp);
1843 		if (core2or5)
1844 			BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_TSSI, tmp);
1845 		break;
1846 	}
1847 }
1848 
1849 static void bwn_nphy_rssi_select_rev19(struct bwn_mac *mac, uint8_t code,
1850 				       enum n_rssi_type rssi_type)
1851 {
1852 	/* TODO */
1853 }
1854 
1855 static void bwn_nphy_rev3_rssi_select(struct bwn_mac *mac, uint8_t code,
1856 				      enum n_rssi_type rssi_type)
1857 {
1858 	uint8_t i;
1859 	uint16_t reg, val;
1860 
1861 	if (code == 0) {
1862 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, 0xFDFF);
1863 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, 0xFDFF);
1864 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, 0xFCFF);
1865 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, 0xFCFF);
1866 		BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S0, 0xFFDF);
1867 		BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B32S1, 0xFFDF);
1868 		BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
1869 		BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
1870 	} else {
1871 		for (i = 0; i < 2; i++) {
1872 			if ((code == 1 && i == 1) || (code == 2 && !i))
1873 				continue;
1874 
1875 			reg = (i == 0) ?
1876 				BWN_NPHY_AFECTL_OVER1 : BWN_NPHY_AFECTL_OVER;
1877 			BWN_PHY_SETMASK(mac, reg, 0xFDFF, 0x0200);
1878 
1879 			if (rssi_type == N_RSSI_W1 ||
1880 			    rssi_type == N_RSSI_W2 ||
1881 			    rssi_type == N_RSSI_NB) {
1882 				reg = (i == 0) ?
1883 					BWN_NPHY_AFECTL_C1 :
1884 					BWN_NPHY_AFECTL_C2;
1885 				BWN_PHY_SETMASK(mac, reg, 0xFCFF, 0);
1886 
1887 				reg = (i == 0) ?
1888 					BWN_NPHY_RFCTL_LUT_TRSW_UP1 :
1889 					BWN_NPHY_RFCTL_LUT_TRSW_UP2;
1890 				BWN_PHY_SETMASK(mac, reg, 0xFFC3, 0);
1891 
1892 				if (rssi_type == N_RSSI_W1)
1893 					val = (bwn_current_band(mac) == BWN_BAND_5G) ? 4 : 8;
1894 				else if (rssi_type == N_RSSI_W2)
1895 					val = 16;
1896 				else
1897 					val = 32;
1898 				BWN_PHY_SET(mac, reg, val);
1899 
1900 				reg = (i == 0) ?
1901 					BWN_NPHY_TXF_40CO_B1S0 :
1902 					BWN_NPHY_TXF_40CO_B32S1;
1903 				BWN_PHY_SET(mac, reg, 0x0020);
1904 			} else {
1905 				if (rssi_type == N_RSSI_TBD)
1906 					val = 0x0100;
1907 				else if (rssi_type == N_RSSI_IQ)
1908 					val = 0x0200;
1909 				else
1910 					val = 0x0300;
1911 
1912 				reg = (i == 0) ?
1913 					BWN_NPHY_AFECTL_C1 :
1914 					BWN_NPHY_AFECTL_C2;
1915 
1916 				BWN_PHY_SETMASK(mac, reg, 0xFCFF, val);
1917 				BWN_PHY_SETMASK(mac, reg, 0xF3FF, val << 2);
1918 
1919 				if (rssi_type != N_RSSI_IQ &&
1920 				    rssi_type != N_RSSI_TBD) {
1921 					bwn_band_t band =
1922 						bwn_current_band(mac);
1923 
1924 					if (mac->mac_phy.rev < 7) {
1925 						if (bwn_nphy_ipa(mac))
1926 							val = (band == BWN_BAND_5G) ? 0xC : 0xE;
1927 						else
1928 							val = 0x11;
1929 						reg = (i == 0) ? B2056_TX0 : B2056_TX1;
1930 						reg |= B2056_TX_TX_SSI_MUX;
1931 						BWN_RF_WRITE(mac, reg, val);
1932 					}
1933 
1934 					reg = (i == 0) ?
1935 						BWN_NPHY_AFECTL_OVER1 :
1936 						BWN_NPHY_AFECTL_OVER;
1937 					BWN_PHY_SET(mac, reg, 0x0200);
1938 				}
1939 			}
1940 		}
1941 	}
1942 }
1943 
1944 static void bwn_nphy_rev2_rssi_select(struct bwn_mac *mac, uint8_t code,
1945 				      enum n_rssi_type rssi_type)
1946 {
1947 	uint16_t val;
1948 	bool rssi_w1_w2_nb = false;
1949 
1950 	switch (rssi_type) {
1951 	case N_RSSI_W1:
1952 	case N_RSSI_W2:
1953 	case N_RSSI_NB:
1954 		val = 0;
1955 		rssi_w1_w2_nb = true;
1956 		break;
1957 	case N_RSSI_TBD:
1958 		val = 1;
1959 		break;
1960 	case N_RSSI_IQ:
1961 		val = 2;
1962 		break;
1963 	default:
1964 		val = 3;
1965 	}
1966 
1967 	val = (val << 12) | (val << 14);
1968 	BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, val);
1969 	BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, val);
1970 
1971 	if (rssi_w1_w2_nb) {
1972 		BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_RSSIO1, 0xFFCF,
1973 				(rssi_type + 1) << 4);
1974 		BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_RSSIO2, 0xFFCF,
1975 				(rssi_type + 1) << 4);
1976 	}
1977 
1978 	if (code == 0) {
1979 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x3000);
1980 		if (rssi_w1_w2_nb) {
1981 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD,
1982 				~(BWN_NPHY_RFCTL_CMD_RXEN |
1983 				  BWN_NPHY_RFCTL_CMD_CORESEL));
1984 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER,
1985 				~(0x1 << 12 |
1986 				  0x1 << 5 |
1987 				  0x1 << 1 |
1988 				  0x1));
1989 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD,
1990 				~BWN_NPHY_RFCTL_CMD_START);
1991 			DELAY(20);
1992 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1);
1993 		}
1994 	} else {
1995 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x3000);
1996 		if (rssi_w1_w2_nb) {
1997 			BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_CMD,
1998 				~(BWN_NPHY_RFCTL_CMD_RXEN |
1999 				  BWN_NPHY_RFCTL_CMD_CORESEL),
2000 				(BWN_NPHY_RFCTL_CMD_RXEN |
2001 				 code << BWN_NPHY_RFCTL_CMD_CORESEL_SHIFT));
2002 			BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER,
2003 				(0x1 << 12 |
2004 				  0x1 << 5 |
2005 				  0x1 << 1 |
2006 				  0x1));
2007 			BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD,
2008 				BWN_NPHY_RFCTL_CMD_START);
2009 			DELAY(20);
2010 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1);
2011 		}
2012 	}
2013 }
2014 
2015 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
2016 static void bwn_nphy_rssi_select(struct bwn_mac *mac, uint8_t code,
2017 				 enum n_rssi_type type)
2018 {
2019 	if (mac->mac_phy.rev >= 19)
2020 		bwn_nphy_rssi_select_rev19(mac, code, type);
2021 	else if (mac->mac_phy.rev >= 3)
2022 		bwn_nphy_rev3_rssi_select(mac, code, type);
2023 	else
2024 		bwn_nphy_rev2_rssi_select(mac, code, type);
2025 }
2026 
2027 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
2028 static void bwn_nphy_set_rssi_2055_vcm(struct bwn_mac *mac,
2029 				       enum n_rssi_type rssi_type, uint8_t *buf)
2030 {
2031 	int i;
2032 	for (i = 0; i < 2; i++) {
2033 		if (rssi_type == N_RSSI_NB) {
2034 			if (i == 0) {
2035 				BWN_RF_SETMASK(mac, B2055_C1_B0NB_RSSIVCM,
2036 						  0xFC, buf[0]);
2037 				BWN_RF_SETMASK(mac, B2055_C1_RX_BB_RSSICTL5,
2038 						  0xFC, buf[1]);
2039 			} else {
2040 				BWN_RF_SETMASK(mac, B2055_C2_B0NB_RSSIVCM,
2041 						  0xFC, buf[2 * i]);
2042 				BWN_RF_SETMASK(mac, B2055_C2_RX_BB_RSSICTL5,
2043 						  0xFC, buf[2 * i + 1]);
2044 			}
2045 		} else {
2046 			if (i == 0)
2047 				BWN_RF_SETMASK(mac, B2055_C1_RX_BB_RSSICTL5,
2048 						  0xF3, buf[0] << 2);
2049 			else
2050 				BWN_RF_SETMASK(mac, B2055_C2_RX_BB_RSSICTL5,
2051 						  0xF3, buf[2 * i + 1] << 2);
2052 		}
2053 	}
2054 }
2055 
2056 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
2057 static int bwn_nphy_poll_rssi(struct bwn_mac *mac, enum n_rssi_type rssi_type,
2058 			      int32_t *buf, uint8_t nsamp)
2059 {
2060 	int i;
2061 	int out;
2062 	uint16_t save_regs_phy[9];
2063 	uint16_t s[2];
2064 
2065 	/* TODO: rev7+ is treated like rev3+, what about rev19+? */
2066 
2067 	if (mac->mac_phy.rev >= 3) {
2068 		save_regs_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1);
2069 		save_regs_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2);
2070 		save_regs_phy[2] = BWN_PHY_READ(mac,
2071 						BWN_NPHY_RFCTL_LUT_TRSW_UP1);
2072 		save_regs_phy[3] = BWN_PHY_READ(mac,
2073 						BWN_NPHY_RFCTL_LUT_TRSW_UP2);
2074 		save_regs_phy[4] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1);
2075 		save_regs_phy[5] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER);
2076 		save_regs_phy[6] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B1S0);
2077 		save_regs_phy[7] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B32S1);
2078 		save_regs_phy[8] = 0;
2079 	} else {
2080 		save_regs_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1);
2081 		save_regs_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2);
2082 		save_regs_phy[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER);
2083 		save_regs_phy[3] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD);
2084 		save_regs_phy[4] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_OVER);
2085 		save_regs_phy[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO1);
2086 		save_regs_phy[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO2);
2087 		save_regs_phy[7] = 0;
2088 		save_regs_phy[8] = 0;
2089 	}
2090 
2091 	bwn_nphy_rssi_select(mac, 5, rssi_type);
2092 
2093 	if (mac->mac_phy.rev < 2) {
2094 		save_regs_phy[8] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_SEL);
2095 		BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_SEL, 5);
2096 	}
2097 
2098 	for (i = 0; i < 4; i++)
2099 		buf[i] = 0;
2100 
2101 	for (i = 0; i < nsamp; i++) {
2102 		if (mac->mac_phy.rev < 2) {
2103 			s[0] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_LOOUT);
2104 			s[1] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_HIOUT);
2105 		} else {
2106 			s[0] = BWN_PHY_READ(mac, BWN_NPHY_RSSI1);
2107 			s[1] = BWN_PHY_READ(mac, BWN_NPHY_RSSI2);
2108 		}
2109 
2110 		buf[0] += ((int8_t)((s[0] & 0x3F) << 2)) >> 2;
2111 		buf[1] += ((int8_t)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
2112 		buf[2] += ((int8_t)((s[1] & 0x3F) << 2)) >> 2;
2113 		buf[3] += ((int8_t)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
2114 	}
2115 	out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
2116 		(buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
2117 
2118 	if (mac->mac_phy.rev < 2)
2119 		BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_SEL, save_regs_phy[8]);
2120 
2121 	if (mac->mac_phy.rev >= 3) {
2122 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, save_regs_phy[0]);
2123 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, save_regs_phy[1]);
2124 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1,
2125 				save_regs_phy[2]);
2126 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2,
2127 				save_regs_phy[3]);
2128 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, save_regs_phy[4]);
2129 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, save_regs_phy[5]);
2130 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
2131 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
2132 	} else {
2133 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, save_regs_phy[0]);
2134 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, save_regs_phy[1]);
2135 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, save_regs_phy[2]);
2136 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_CMD, save_regs_phy[3]);
2137 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, save_regs_phy[4]);
2138 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
2139 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
2140 	}
2141 
2142 	return out;
2143 }
2144 
2145 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
2146 static void bwn_nphy_rev3_rssi_cal(struct bwn_mac *mac)
2147 {
2148 	//struct bwn_phy *phy = &mac->mac_phy;
2149 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
2150 
2151 	uint16_t saved_regs_phy_rfctl[2];
2152 	uint16_t saved_regs_phy[22];
2153 	uint16_t regs_to_store_rev3[] = {
2154 		BWN_NPHY_AFECTL_OVER1, BWN_NPHY_AFECTL_OVER,
2155 		BWN_NPHY_AFECTL_C1, BWN_NPHY_AFECTL_C2,
2156 		BWN_NPHY_TXF_40CO_B1S1, BWN_NPHY_RFCTL_OVER,
2157 		BWN_NPHY_TXF_40CO_B1S0, BWN_NPHY_TXF_40CO_B32S1,
2158 		BWN_NPHY_RFCTL_CMD,
2159 		BWN_NPHY_RFCTL_LUT_TRSW_UP1, BWN_NPHY_RFCTL_LUT_TRSW_UP2,
2160 		BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2
2161 	};
2162 	uint16_t regs_to_store_rev7[] = {
2163 		BWN_NPHY_AFECTL_OVER1, BWN_NPHY_AFECTL_OVER,
2164 		BWN_NPHY_AFECTL_C1, BWN_NPHY_AFECTL_C2,
2165 		BWN_NPHY_TXF_40CO_B1S1, BWN_NPHY_RFCTL_OVER,
2166 		BWN_NPHY_REV7_RF_CTL_OVER3, BWN_NPHY_REV7_RF_CTL_OVER4,
2167 		BWN_NPHY_REV7_RF_CTL_OVER5, BWN_NPHY_REV7_RF_CTL_OVER6,
2168 		0x2ff,
2169 		BWN_NPHY_TXF_40CO_B1S0, BWN_NPHY_TXF_40CO_B32S1,
2170 		BWN_NPHY_RFCTL_CMD,
2171 		BWN_NPHY_RFCTL_LUT_TRSW_UP1, BWN_NPHY_RFCTL_LUT_TRSW_UP2,
2172 		BWN_NPHY_REV7_RF_CTL_MISC_REG3, BWN_NPHY_REV7_RF_CTL_MISC_REG4,
2173 		BWN_NPHY_REV7_RF_CTL_MISC_REG5, BWN_NPHY_REV7_RF_CTL_MISC_REG6,
2174 		BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2
2175 	};
2176 	uint16_t *regs_to_store;
2177 	int regs_amount;
2178 
2179 	uint16_t class;
2180 
2181 	uint16_t clip_state[2];
2182 	uint16_t clip_off[2] = { 0xFFFF, 0xFFFF };
2183 
2184 	uint8_t vcm_final = 0;
2185 	int32_t offset[4];
2186 	int32_t results[8][4] = { };
2187 	int32_t results_min[4] = { };
2188 	int32_t poll_results[4] = { };
2189 
2190 	uint16_t *rssical_radio_regs = NULL;
2191 	uint16_t *rssical_phy_regs = NULL;
2192 
2193 	uint16_t r; /* routing */
2194 	uint8_t rx_core_state;
2195 	int core, i, j, vcm;
2196 
2197 	if (mac->mac_phy.rev >= 7) {
2198 		regs_to_store = regs_to_store_rev7;
2199 		regs_amount = nitems(regs_to_store_rev7);
2200 	} else {
2201 		regs_to_store = regs_to_store_rev3;
2202 		regs_amount = nitems(regs_to_store_rev3);
2203 	}
2204 	KASSERT((regs_amount <= nitems(saved_regs_phy)),
2205 	    ("%s: reg_amount (%d) too large\n",
2206 	    __func__,
2207 	    regs_amount));
2208 
2209 	class = bwn_nphy_classifier(mac, 0, 0);
2210 	bwn_nphy_classifier(mac, 7, 4);
2211 	bwn_nphy_read_clip_detection(mac, clip_state);
2212 	bwn_nphy_write_clip_detection(mac, clip_off);
2213 
2214 	saved_regs_phy_rfctl[0] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1);
2215 	saved_regs_phy_rfctl[1] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2);
2216 	for (i = 0; i < regs_amount; i++)
2217 		saved_regs_phy[i] = BWN_PHY_READ(mac, regs_to_store[i]);
2218 
2219 	bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_OFF, 0, 7);
2220 	bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 1, 7);
2221 
2222 	if (mac->mac_phy.rev >= 7) {
2223 		bwn_nphy_rf_ctl_override_one_to_many(mac,
2224 						     N_RF_CTL_OVER_CMD_RXRF_PU,
2225 						     0, 0, false);
2226 		bwn_nphy_rf_ctl_override_one_to_many(mac,
2227 						     N_RF_CTL_OVER_CMD_RX_PU,
2228 						     1, 0, false);
2229 		bwn_nphy_rf_ctl_override_rev7(mac, 0x80, 1, 0, false, 0);
2230 		bwn_nphy_rf_ctl_override_rev7(mac, 0x40, 1, 0, false, 0);
2231 		if (bwn_current_band(mac) == BWN_BAND_5G) {
2232 			bwn_nphy_rf_ctl_override_rev7(mac, 0x20, 0, 0, false,
2233 						      0);
2234 			bwn_nphy_rf_ctl_override_rev7(mac, 0x10, 1, 0, false,
2235 						      0);
2236 		} else {
2237 			bwn_nphy_rf_ctl_override_rev7(mac, 0x10, 0, 0, false,
2238 						      0);
2239 			bwn_nphy_rf_ctl_override_rev7(mac, 0x20, 1, 0, false,
2240 						      0);
2241 		}
2242 	} else {
2243 		bwn_nphy_rf_ctl_override(mac, 0x1, 0, 0, false);
2244 		bwn_nphy_rf_ctl_override(mac, 0x2, 1, 0, false);
2245 		bwn_nphy_rf_ctl_override(mac, 0x80, 1, 0, false);
2246 		bwn_nphy_rf_ctl_override(mac, 0x40, 1, 0, false);
2247 		if (bwn_current_band(mac) == BWN_BAND_5G) {
2248 			bwn_nphy_rf_ctl_override(mac, 0x20, 0, 0, false);
2249 			bwn_nphy_rf_ctl_override(mac, 0x10, 1, 0, false);
2250 		} else {
2251 			bwn_nphy_rf_ctl_override(mac, 0x10, 0, 0, false);
2252 			bwn_nphy_rf_ctl_override(mac, 0x20, 1, 0, false);
2253 		}
2254 	}
2255 
2256 	rx_core_state = bwn_nphy_get_rx_core_state(mac);
2257 	for (core = 0; core < 2; core++) {
2258 		if (!(rx_core_state & (1 << core)))
2259 			continue;
2260 		r = core ? B2056_RX1 : B2056_RX0;
2261 		bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, N_RAIL_I,
2262 					   N_RSSI_NB);
2263 		bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, N_RAIL_Q,
2264 					   N_RSSI_NB);
2265 
2266 		/* Grab RSSI results for every possible VCM */
2267 		for (vcm = 0; vcm < 8; vcm++) {
2268 			if (mac->mac_phy.rev >= 7)
2269 				BWN_RF_SETMASK(mac,
2270 						  core ? R2057_NB_MASTER_CORE1 :
2271 							 R2057_NB_MASTER_CORE0,
2272 						  ~R2057_VCM_MASK, vcm);
2273 			else
2274 				BWN_RF_SETMASK(mac, r | B2056_RX_RSSI_MISC,
2275 						  0xE3, vcm << 2);
2276 			bwn_nphy_poll_rssi(mac, N_RSSI_NB, results[vcm], 8);
2277 		}
2278 
2279 		/* Find out which VCM got the best results */
2280 		for (i = 0; i < 4; i += 2) {
2281 			int32_t currd;
2282 			int32_t mind = 0x100000;
2283 			int32_t minpoll = 249;
2284 			uint8_t minvcm = 0;
2285 			if (2 * core != i)
2286 				continue;
2287 			for (vcm = 0; vcm < 8; vcm++) {
2288 				currd = results[vcm][i] * results[vcm][i] +
2289 					results[vcm][i + 1] * results[vcm][i];
2290 				if (currd < mind) {
2291 					mind = currd;
2292 					minvcm = vcm;
2293 				}
2294 				if (results[vcm][i] < minpoll)
2295 					minpoll = results[vcm][i];
2296 			}
2297 			vcm_final = minvcm;
2298 			results_min[i] = minpoll;
2299 		}
2300 
2301 		/* Select the best VCM */
2302 		if (mac->mac_phy.rev >= 7)
2303 			BWN_RF_SETMASK(mac,
2304 					  core ? R2057_NB_MASTER_CORE1 :
2305 						 R2057_NB_MASTER_CORE0,
2306 					  ~R2057_VCM_MASK, vcm);
2307 		else
2308 			BWN_RF_SETMASK(mac, r | B2056_RX_RSSI_MISC,
2309 					  0xE3, vcm_final << 2);
2310 
2311 		for (i = 0; i < 4; i++) {
2312 			if (core != i / 2)
2313 				continue;
2314 			offset[i] = -results[vcm_final][i];
2315 			if (offset[i] < 0)
2316 				offset[i] = -((abs(offset[i]) + 4) / 8);
2317 			else
2318 				offset[i] = (offset[i] + 4) / 8;
2319 			if (results_min[i] == 248)
2320 				offset[i] = -32;
2321 			bwn_nphy_scale_offset_rssi(mac, 0, offset[i],
2322 						   (i / 2 == 0) ? 1 : 2,
2323 						   (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q,
2324 						   N_RSSI_NB);
2325 		}
2326 	}
2327 
2328 	for (core = 0; core < 2; core++) {
2329 		if (!(rx_core_state & (1 << core)))
2330 			continue;
2331 		for (i = 0; i < 2; i++) {
2332 			bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1,
2333 						   N_RAIL_I, i);
2334 			bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1,
2335 						   N_RAIL_Q, i);
2336 			bwn_nphy_poll_rssi(mac, i, poll_results, 8);
2337 			for (j = 0; j < 4; j++) {
2338 				if (j / 2 == core) {
2339 					offset[j] = 232 - poll_results[j];
2340 					if (offset[j] < 0)
2341 						offset[j] = -(abs(offset[j] + 4) / 8);
2342 					else
2343 						offset[j] = (offset[j] + 4) / 8;
2344 					bwn_nphy_scale_offset_rssi(mac, 0,
2345 						offset[2 * core], core + 1, j % 2, i);
2346 				}
2347 			}
2348 		}
2349 	}
2350 
2351 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]);
2352 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]);
2353 
2354 	bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX);
2355 
2356 	BWN_PHY_SET(mac, BWN_NPHY_TXF_40CO_B1S1, 0x1);
2357 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_START);
2358 	BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S1, ~0x1);
2359 
2360 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 0x1);
2361 	BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_RXTX);
2362 	BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1);
2363 
2364 	for (i = 0; i < regs_amount; i++)
2365 		BWN_PHY_WRITE(mac, regs_to_store[i], saved_regs_phy[i]);
2366 
2367 	/* Store for future configuration */
2368 	if (bwn_current_band(mac) == BWN_BAND_2G) {
2369 		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
2370 		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
2371 	} else {
2372 		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
2373 		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
2374 	}
2375 	if (mac->mac_phy.rev >= 7) {
2376 		rssical_radio_regs[0] = BWN_RF_READ(mac,
2377 						       R2057_NB_MASTER_CORE0);
2378 		rssical_radio_regs[1] = BWN_RF_READ(mac,
2379 						       R2057_NB_MASTER_CORE1);
2380 	} else {
2381 		rssical_radio_regs[0] = BWN_RF_READ(mac, B2056_RX0 |
2382 						       B2056_RX_RSSI_MISC);
2383 		rssical_radio_regs[1] = BWN_RF_READ(mac, B2056_RX1 |
2384 						       B2056_RX_RSSI_MISC);
2385 	}
2386 	rssical_phy_regs[0] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z);
2387 	rssical_phy_regs[1] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z);
2388 	rssical_phy_regs[2] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z);
2389 	rssical_phy_regs[3] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z);
2390 	rssical_phy_regs[4] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_X);
2391 	rssical_phy_regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X);
2392 	rssical_phy_regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_X);
2393 	rssical_phy_regs[7] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X);
2394 	rssical_phy_regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y);
2395 	rssical_phy_regs[9] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y);
2396 	rssical_phy_regs[10] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y);
2397 	rssical_phy_regs[11] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y);
2398 
2399 	/* Remember for which channel we store configuration */
2400 	if (bwn_current_band(mac) == BWN_BAND_2G)
2401 		nphy->rssical_chanspec_2G.center_freq = bwn_get_centre_freq(mac);
2402 	else
2403 		nphy->rssical_chanspec_5G.center_freq = bwn_get_centre_freq(mac);
2404 
2405 	/* End of calibration, restore configuration */
2406 	bwn_nphy_classifier(mac, 7, class);
2407 	bwn_nphy_write_clip_detection(mac, clip_state);
2408 }
2409 
2410 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
2411 static void bwn_nphy_rev2_rssi_cal(struct bwn_mac *mac, enum n_rssi_type type)
2412 {
2413 	int i, j, vcm;
2414 	uint8_t state[4];
2415 	uint8_t code, val;
2416 	uint16_t class, override;
2417 	uint8_t regs_save_radio[2];
2418 	uint16_t regs_save_phy[2];
2419 
2420 	int32_t offset[4];
2421 	uint8_t core;
2422 	uint8_t rail;
2423 
2424 	uint16_t clip_state[2];
2425 	uint16_t clip_off[2] = { 0xFFFF, 0xFFFF };
2426 	int32_t results_min[4] = { };
2427 	uint8_t vcm_final[4] = { };
2428 	int32_t results[4][4] = { };
2429 	int32_t miniq[4][2] = { };
2430 
2431 	if (type == N_RSSI_NB) {
2432 		code = 0;
2433 		val = 6;
2434 	} else if (type == N_RSSI_W1 || type == N_RSSI_W2) {
2435 		code = 25;
2436 		val = 4;
2437 	} else {
2438 		BWN_ERRPRINTF(mac->mac_sc, "%s: RSSI type %d invalid\n",
2439 		    __func__,
2440 		    type);
2441 		return;
2442 	}
2443 
2444 	class = bwn_nphy_classifier(mac, 0, 0);
2445 	bwn_nphy_classifier(mac, 7, 4);
2446 	bwn_nphy_read_clip_detection(mac, clip_state);
2447 	bwn_nphy_write_clip_detection(mac, clip_off);
2448 
2449 	if (bwn_current_band(mac) == BWN_BAND_5G)
2450 		override = 0x140;
2451 	else
2452 		override = 0x110;
2453 
2454 	regs_save_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1);
2455 	regs_save_radio[0] = BWN_RF_READ(mac, B2055_C1_PD_RXTX);
2456 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, override);
2457 	BWN_RF_WRITE(mac, B2055_C1_PD_RXTX, val);
2458 
2459 	regs_save_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2);
2460 	regs_save_radio[1] = BWN_RF_READ(mac, B2055_C2_PD_RXTX);
2461 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, override);
2462 	BWN_RF_WRITE(mac, B2055_C2_PD_RXTX, val);
2463 
2464 	state[0] = BWN_RF_READ(mac, B2055_C1_PD_RSSIMISC) & 0x07;
2465 	state[1] = BWN_RF_READ(mac, B2055_C2_PD_RSSIMISC) & 0x07;
2466 	BWN_RF_MASK(mac, B2055_C1_PD_RSSIMISC, 0xF8);
2467 	BWN_RF_MASK(mac, B2055_C2_PD_RSSIMISC, 0xF8);
2468 	state[2] = BWN_RF_READ(mac, B2055_C1_SP_RSSI) & 0x07;
2469 	state[3] = BWN_RF_READ(mac, B2055_C2_SP_RSSI) & 0x07;
2470 
2471 	bwn_nphy_rssi_select(mac, 5, type);
2472 	bwn_nphy_scale_offset_rssi(mac, 0, 0, 5, N_RAIL_I, type);
2473 	bwn_nphy_scale_offset_rssi(mac, 0, 0, 5, N_RAIL_Q, type);
2474 
2475 	for (vcm = 0; vcm < 4; vcm++) {
2476 		uint8_t tmp[4];
2477 		for (j = 0; j < 4; j++)
2478 			tmp[j] = vcm;
2479 		if (type != N_RSSI_W2)
2480 			bwn_nphy_set_rssi_2055_vcm(mac, type, tmp);
2481 		bwn_nphy_poll_rssi(mac, type, results[vcm], 8);
2482 		if (type == N_RSSI_W1 || type == N_RSSI_W2)
2483 			for (j = 0; j < 2; j++)
2484 				miniq[vcm][j] = min(results[vcm][2 * j],
2485 						    results[vcm][2 * j + 1]);
2486 	}
2487 
2488 	for (i = 0; i < 4; i++) {
2489 		int32_t mind = 0x100000;
2490 		uint8_t minvcm = 0;
2491 		int32_t minpoll = 249;
2492 		int32_t currd;
2493 		for (vcm = 0; vcm < 4; vcm++) {
2494 			if (type == N_RSSI_NB)
2495 				currd = abs(results[vcm][i] - code * 8);
2496 			else
2497 				currd = abs(miniq[vcm][i / 2] - code * 8);
2498 
2499 			if (currd < mind) {
2500 				mind = currd;
2501 				minvcm = vcm;
2502 			}
2503 
2504 			if (results[vcm][i] < minpoll)
2505 				minpoll = results[vcm][i];
2506 		}
2507 		results_min[i] = minpoll;
2508 		vcm_final[i] = minvcm;
2509 	}
2510 
2511 	if (type != N_RSSI_W2)
2512 		bwn_nphy_set_rssi_2055_vcm(mac, type, vcm_final);
2513 
2514 	for (i = 0; i < 4; i++) {
2515 		offset[i] = (code * 8) - results[vcm_final[i]][i];
2516 
2517 		if (offset[i] < 0)
2518 			offset[i] = -((abs(offset[i]) + 4) / 8);
2519 		else
2520 			offset[i] = (offset[i] + 4) / 8;
2521 
2522 		if (results_min[i] == 248)
2523 			offset[i] = code - 32;
2524 
2525 		core = (i / 2) ? 2 : 1;
2526 		rail = (i % 2) ? N_RAIL_Q : N_RAIL_I;
2527 
2528 		bwn_nphy_scale_offset_rssi(mac, 0, offset[i], core, rail,
2529 						type);
2530 	}
2531 
2532 	BWN_RF_SETMASK(mac, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
2533 	BWN_RF_SETMASK(mac, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
2534 
2535 	switch (state[2]) {
2536 	case 1:
2537 		bwn_nphy_rssi_select(mac, 1, N_RSSI_NB);
2538 		break;
2539 	case 4:
2540 		bwn_nphy_rssi_select(mac, 1, N_RSSI_W1);
2541 		break;
2542 	case 2:
2543 		bwn_nphy_rssi_select(mac, 1, N_RSSI_W2);
2544 		break;
2545 	default:
2546 		bwn_nphy_rssi_select(mac, 1, N_RSSI_W2);
2547 		break;
2548 	}
2549 
2550 	switch (state[3]) {
2551 	case 1:
2552 		bwn_nphy_rssi_select(mac, 2, N_RSSI_NB);
2553 		break;
2554 	case 4:
2555 		bwn_nphy_rssi_select(mac, 2, N_RSSI_W1);
2556 		break;
2557 	default:
2558 		bwn_nphy_rssi_select(mac, 2, N_RSSI_W2);
2559 		break;
2560 	}
2561 
2562 	bwn_nphy_rssi_select(mac, 0, type);
2563 
2564 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs_save_phy[0]);
2565 	BWN_RF_WRITE(mac, B2055_C1_PD_RXTX, regs_save_radio[0]);
2566 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs_save_phy[1]);
2567 	BWN_RF_WRITE(mac, B2055_C2_PD_RXTX, regs_save_radio[1]);
2568 
2569 	bwn_nphy_classifier(mac, 7, class);
2570 	bwn_nphy_write_clip_detection(mac, clip_state);
2571 	/* Specs don't say about reset here, but it makes wl and b43 dumps
2572 	   identical, it really seems wl performs this */
2573 	bwn_nphy_reset_cca(mac);
2574 }
2575 
2576 /*
2577  * RSSI Calibration
2578  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
2579  */
2580 static void bwn_nphy_rssi_cal(struct bwn_mac *mac)
2581 {
2582 	if (mac->mac_phy.rev >= 19) {
2583 		/* TODO */
2584 	} else if (mac->mac_phy.rev >= 3) {
2585 		bwn_nphy_rev3_rssi_cal(mac);
2586 	} else {
2587 		bwn_nphy_rev2_rssi_cal(mac, N_RSSI_NB);
2588 		bwn_nphy_rev2_rssi_cal(mac, N_RSSI_W1);
2589 		bwn_nphy_rev2_rssi_cal(mac, N_RSSI_W2);
2590 	}
2591 }
2592 
2593 /**************************************************
2594  * Workarounds
2595  **************************************************/
2596 
2597 static void bwn_nphy_gain_ctl_workarounds_rev19(struct bwn_mac *mac)
2598 {
2599 	/* TODO */
2600 }
2601 
2602 static void bwn_nphy_gain_ctl_workarounds_rev7(struct bwn_mac *mac)
2603 {
2604 	struct bwn_phy *phy = &mac->mac_phy;
2605 
2606 	switch (phy->rev) {
2607 	/* TODO */
2608 	}
2609 }
2610 
2611 static void bwn_nphy_gain_ctl_workarounds_rev3(struct bwn_mac *mac)
2612 {
2613 	struct bwn_softc *sc = mac->mac_sc;
2614 	bool ghz5;
2615 	bool ext_lna;
2616 	uint16_t rssi_gain;
2617 	struct bwn_nphy_gain_ctl_workaround_entry *e;
2618 	uint8_t lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
2619 	uint8_t lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
2620 
2621 	/* Prepare values */
2622 	ghz5 = BWN_PHY_READ(mac, BWN_NPHY_BANDCTL)
2623 		& BWN_NPHY_BANDCTL_5GHZ;
2624 	ext_lna = ghz5 ? siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_EXTLNA_5GHZ :
2625 		siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA;
2626 	e = bwn_nphy_get_gain_ctl_workaround_ent(mac, ghz5, ext_lna);
2627 	if (ghz5 && mac->mac_phy.rev >= 5)
2628 		rssi_gain = 0x90;
2629 	else
2630 		rssi_gain = 0x50;
2631 
2632 	BWN_PHY_SET(mac, BWN_NPHY_RXCTL, 0x0040);
2633 
2634 	/* Set Clip 2 detect */
2635 	BWN_PHY_SET(mac, BWN_NPHY_C1_CGAINI, BWN_NPHY_C1_CGAINI_CL2DETECT);
2636 	BWN_PHY_SET(mac, BWN_NPHY_C2_CGAINI, BWN_NPHY_C2_CGAINI_CL2DETECT);
2637 
2638 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
2639 			0x17);
2640 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
2641 			0x17);
2642 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
2643 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
2644 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
2645 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
2646 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_RSSI_GAIN,
2647 			rssi_gain);
2648 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_RSSI_GAIN,
2649 			rssi_gain);
2650 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
2651 			0x17);
2652 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
2653 			0x17);
2654 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
2655 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
2656 
2657 	bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 8), 4, e->lna1_gain);
2658 	bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 8), 4, e->lna1_gain);
2659 	bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 16), 4, e->lna2_gain);
2660 	bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 16), 4, e->lna2_gain);
2661 	bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 32), 10, e->gain_db);
2662 	bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 32), 10, e->gain_db);
2663 	bwn_ntab_write_bulk(mac, BWN_NTAB8(2, 32), 10, e->gain_bits);
2664 	bwn_ntab_write_bulk(mac, BWN_NTAB8(3, 32), 10, e->gain_bits);
2665 	bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 0x40), 6, lpf_gain);
2666 	bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 0x40), 6, lpf_gain);
2667 	bwn_ntab_write_bulk(mac, BWN_NTAB8(2, 0x40), 6, lpf_bits);
2668 	bwn_ntab_write_bulk(mac, BWN_NTAB8(3, 0x40), 6, lpf_bits);
2669 
2670 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_INITGAIN_A, e->init_gain);
2671 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_INITGAIN_A, e->init_gain);
2672 
2673 	bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x106), 2,
2674 				e->rfseq_init);
2675 
2676 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain);
2677 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain);
2678 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain);
2679 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain);
2680 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain);
2681 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain);
2682 
2683 	BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin);
2684 	BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl);
2685 	BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu);
2686 	BWN_PHY_WRITE(mac, BWN_NPHY_C1_NBCLIPTHRES, e->nbclip);
2687 	BWN_PHY_WRITE(mac, BWN_NPHY_C2_NBCLIPTHRES, e->nbclip);
2688 	BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CLIPWBTHRES,
2689 			~BWN_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
2690 	BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CLIPWBTHRES,
2691 			~BWN_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
2692 	BWN_PHY_WRITE(mac, BWN_NPHY_CCK_SHIFTB_REF, 0x809C);
2693 }
2694 
2695 static void bwn_nphy_gain_ctl_workarounds_rev1_2(struct bwn_mac *mac)
2696 {
2697 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
2698 
2699 	uint8_t i, j;
2700 	uint8_t code;
2701 	uint16_t tmp;
2702 	uint8_t rfseq_events[3] = { 6, 8, 7 };
2703 	uint8_t rfseq_delays[3] = { 10, 30, 1 };
2704 
2705 	/* Set Clip 2 detect */
2706 	BWN_PHY_SET(mac, BWN_NPHY_C1_CGAINI, BWN_NPHY_C1_CGAINI_CL2DETECT);
2707 	BWN_PHY_SET(mac, BWN_NPHY_C2_CGAINI, BWN_NPHY_C2_CGAINI_CL2DETECT);
2708 
2709 	/* Set narrowband clip threshold */
2710 	BWN_PHY_WRITE(mac, BWN_NPHY_C1_NBCLIPTHRES, 0x84);
2711 	BWN_PHY_WRITE(mac, BWN_NPHY_C2_NBCLIPTHRES, 0x84);
2712 
2713 	if (!bwn_is_40mhz(mac)) {
2714 		/* Set dwell lengths */
2715 		BWN_PHY_WRITE(mac, BWN_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
2716 		BWN_PHY_WRITE(mac, BWN_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
2717 		BWN_PHY_WRITE(mac, BWN_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
2718 		BWN_PHY_WRITE(mac, BWN_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
2719 	}
2720 
2721 	/* Set wideband clip 2 threshold */
2722 	BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CLIPWBTHRES,
2723 			~BWN_NPHY_C1_CLIPWBTHRES_CLIP2, 21);
2724 	BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CLIPWBTHRES,
2725 			~BWN_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
2726 
2727 	if (!bwn_is_40mhz(mac)) {
2728 		BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CGAINI,
2729 			~BWN_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
2730 		BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CGAINI,
2731 			~BWN_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
2732 		BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CCK_CGAINI,
2733 			~BWN_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
2734 		BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CCK_CGAINI,
2735 			~BWN_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
2736 	}
2737 
2738 	BWN_PHY_WRITE(mac, BWN_NPHY_CCK_SHIFTB_REF, 0x809C);
2739 
2740 	if (nphy->gain_boost) {
2741 		if (bwn_current_band(mac) == BWN_BAND_2G &&
2742 		    bwn_is_40mhz(mac))
2743 			code = 4;
2744 		else
2745 			code = 5;
2746 	} else {
2747 		code = bwn_is_40mhz(mac) ? 6 : 7;
2748 	}
2749 
2750 	/* Set HPVGA2 index */
2751 	BWN_PHY_SETMASK(mac, BWN_NPHY_C1_INITGAIN, ~BWN_NPHY_C1_INITGAIN_HPVGA2,
2752 			code << BWN_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
2753 	BWN_PHY_SETMASK(mac, BWN_NPHY_C2_INITGAIN, ~BWN_NPHY_C2_INITGAIN_HPVGA2,
2754 			code << BWN_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
2755 
2756 	BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x1D06);
2757 	/* specs say about 2 loops, but wl does 4 */
2758 	for (i = 0; i < 4; i++)
2759 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, (code << 8 | 0x7C));
2760 
2761 	bwn_nphy_adjust_lna_gain_table(mac);
2762 
2763 	if (nphy->elna_gain_config) {
2764 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x0808);
2765 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x0);
2766 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1);
2767 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1);
2768 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1);
2769 
2770 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x0C08);
2771 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x0);
2772 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1);
2773 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1);
2774 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1);
2775 
2776 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x1D06);
2777 		/* specs say about 2 loops, but wl does 4 */
2778 		for (i = 0; i < 4; i++)
2779 			BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO,
2780 						(code << 8 | 0x74));
2781 	}
2782 
2783 	if (mac->mac_phy.rev == 2) {
2784 		for (i = 0; i < 4; i++) {
2785 			BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR,
2786 					(0x0400 * i) + 0x0020);
2787 			for (j = 0; j < 21; j++) {
2788 				tmp = j * (i < 2 ? 3 : 1);
2789 				BWN_PHY_WRITE(mac,
2790 					BWN_NPHY_TABLE_DATALO, tmp);
2791 			}
2792 		}
2793 	}
2794 
2795 	bwn_nphy_set_rf_sequence(mac, 5, rfseq_events, rfseq_delays, 3);
2796 	BWN_PHY_SETMASK(mac, BWN_NPHY_OVER_DGAIN1,
2797 		~BWN_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
2798 		0x5A << BWN_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
2799 
2800 	if (bwn_current_band(mac) == BWN_BAND_2G)
2801 		BWN_PHY_SETMASK(mac, BWN_PHY_N(0xC5D), 0xFF80, 4);
2802 }
2803 
2804 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
2805 static void bwn_nphy_gain_ctl_workarounds(struct bwn_mac *mac)
2806 {
2807 	if (mac->mac_phy.rev >= 19)
2808 		bwn_nphy_gain_ctl_workarounds_rev19(mac);
2809 	else if (mac->mac_phy.rev >= 7)
2810 		bwn_nphy_gain_ctl_workarounds_rev7(mac);
2811 	else if (mac->mac_phy.rev >= 3)
2812 		bwn_nphy_gain_ctl_workarounds_rev3(mac);
2813 	else
2814 		bwn_nphy_gain_ctl_workarounds_rev1_2(mac);
2815 }
2816 
2817 static void bwn_nphy_workarounds_rev7plus(struct bwn_mac *mac)
2818 {
2819 	struct bwn_softc *sc = mac->mac_sc;
2820 	struct bwn_phy *phy = &mac->mac_phy;
2821 
2822 	/* TX to RX */
2823 	uint8_t tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };
2824 	uint8_t tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };
2825 	/* RX to TX */
2826 	uint8_t rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
2827 					0x1F };
2828 	uint8_t rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
2829 
2830 	static const uint16_t ntab7_15e_16e[] = { 0, 0x10f, 0x10f };
2831 	uint8_t ntab7_138_146[] = { 0x11, 0x11 };
2832 	uint8_t ntab7_133[] = { 0x77, 0x11, 0x11 };
2833 
2834 	uint16_t lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];
2835 	uint16_t bcap_val;
2836 	int16_t bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];
2837 	uint16_t scap_val;
2838 	int16_t scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];
2839 	bool rccal_ovrd = false;
2840 
2841 	uint16_t bias, conv, filt;
2842 
2843 	uint32_t noise_tbl[2];
2844 
2845 	uint32_t tmp32;
2846 	uint8_t core;
2847 
2848 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x0125);
2849 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x01b3);
2850 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x0105);
2851 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x016e);
2852 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0x00cd);
2853 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x0020);
2854 
2855 	if (phy->rev == 7) {
2856 		BWN_PHY_SET(mac, BWN_NPHY_FINERX2_CGC, 0x10);
2857 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN0, 0xFF80, 0x0020);
2858 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN0, 0x80FF, 0x2700);
2859 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN1, 0xFF80, 0x002E);
2860 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN1, 0x80FF, 0x3300);
2861 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN2, 0xFF80, 0x0037);
2862 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN2, 0x80FF, 0x3A00);
2863 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN3, 0xFF80, 0x003C);
2864 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN3, 0x80FF, 0x3E00);
2865 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN4, 0xFF80, 0x003E);
2866 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN4, 0x80FF, 0x3F00);
2867 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN5, 0xFF80, 0x0040);
2868 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN5, 0x80FF, 0x4000);
2869 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN6, 0xFF80, 0x0040);
2870 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN6, 0x80FF, 0x4000);
2871 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN7, 0xFF80, 0x0040);
2872 		BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN7, 0x80FF, 0x4000);
2873 	}
2874 
2875 	if (phy->rev >= 16) {
2876 		BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x7ff);
2877 		BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x7ff);
2878 	} else if (phy->rev <= 8) {
2879 		BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x1B0);
2880 		BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x1B0);
2881 	}
2882 
2883 	if (phy->rev >= 16)
2884 		BWN_PHY_SETMASK(mac, BWN_NPHY_TXTAILCNT, ~0xFF, 0xa0);
2885 	else if (phy->rev >= 8)
2886 		BWN_PHY_SETMASK(mac, BWN_NPHY_TXTAILCNT, ~0xFF, 0x72);
2887 
2888 	bwn_ntab_write(mac, BWN_NTAB16(8, 0x00), 2);
2889 	bwn_ntab_write(mac, BWN_NTAB16(8, 0x10), 2);
2890 	tmp32 = bwn_ntab_read(mac, BWN_NTAB32(30, 0));
2891 	tmp32 &= 0xffffff;
2892 	bwn_ntab_write(mac, BWN_NTAB32(30, 0), tmp32);
2893 	bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x15d), 3, ntab7_15e_16e);
2894 	bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x16d), 3, ntab7_15e_16e);
2895 
2896 	bwn_nphy_set_rf_sequence(mac, 1, tx2rx_events, tx2rx_delays,
2897 				 nitems(tx2rx_events));
2898 	if (bwn_nphy_ipa(mac))
2899 		bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events_ipa,
2900 				rx2tx_delays_ipa, nitems(rx2tx_events_ipa));
2901 
2902 	BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
2903 	BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
2904 
2905 	for (core = 0; core < 2; core++) {
2906 		lpf_ofdm_20mhz[core] = bwn_nphy_read_lpf_ctl(mac, 0x154 + core * 0x10);
2907 		lpf_ofdm_40mhz[core] = bwn_nphy_read_lpf_ctl(mac, 0x159 + core * 0x10);
2908 		lpf_11b[core] = bwn_nphy_read_lpf_ctl(mac, 0x152 + core * 0x10);
2909 	}
2910 
2911 	bcap_val = BWN_RF_READ(mac, R2057_RCCAL_BCAP_VAL);
2912 	scap_val = BWN_RF_READ(mac, R2057_RCCAL_SCAP_VAL);
2913 
2914 	if (bwn_nphy_ipa(mac)) {
2915 		bool ghz2 = bwn_current_band(mac) == BWN_BAND_2G;
2916 
2917 		switch (phy->rf_rev) {
2918 		case 5:
2919 			/* Check radio version (to be 0) by PHY rev for now */
2920 			if (phy->rev == 8 && bwn_is_40mhz(mac)) {
2921 				for (core = 0; core < 2; core++) {
2922 					scap_val_11b[core] = scap_val;
2923 					bcap_val_11b[core] = bcap_val;
2924 					scap_val_11n_20[core] = scap_val;
2925 					bcap_val_11n_20[core] = bcap_val;
2926 					scap_val_11n_40[core] = 0xc;
2927 					bcap_val_11n_40[core] = 0xc;
2928 				}
2929 
2930 				rccal_ovrd = true;
2931 			}
2932 			if (phy->rev == 9) {
2933 				/* TODO: Radio version 1 (e.g. BCM5357B0) */
2934 			}
2935 			break;
2936 		case 7:
2937 		case 8:
2938 			for (core = 0; core < 2; core++) {
2939 				scap_val_11b[core] = scap_val;
2940 				bcap_val_11b[core] = bcap_val;
2941 				lpf_ofdm_20mhz[core] = 4;
2942 				lpf_11b[core] = 1;
2943 				if (bwn_current_band(mac) == BWN_BAND_2G) {
2944 					scap_val_11n_20[core] = 0xc;
2945 					bcap_val_11n_20[core] = 0xc;
2946 					scap_val_11n_40[core] = 0xa;
2947 					bcap_val_11n_40[core] = 0xa;
2948 				} else {
2949 					scap_val_11n_20[core] = 0x14;
2950 					bcap_val_11n_20[core] = 0x14;
2951 					scap_val_11n_40[core] = 0xf;
2952 					bcap_val_11n_40[core] = 0xf;
2953 				}
2954 			}
2955 
2956 			rccal_ovrd = true;
2957 			break;
2958 		case 9:
2959 			for (core = 0; core < 2; core++) {
2960 				bcap_val_11b[core] = bcap_val;
2961 				scap_val_11b[core] = scap_val;
2962 				lpf_11b[core] = 1;
2963 
2964 				if (ghz2) {
2965 					bcap_val_11n_20[core] = bcap_val + 13;
2966 					scap_val_11n_20[core] = scap_val + 15;
2967 				} else {
2968 					bcap_val_11n_20[core] = bcap_val + 14;
2969 					scap_val_11n_20[core] = scap_val + 15;
2970 				}
2971 				lpf_ofdm_20mhz[core] = 4;
2972 
2973 				if (ghz2) {
2974 					bcap_val_11n_40[core] = bcap_val - 7;
2975 					scap_val_11n_40[core] = scap_val - 5;
2976 				} else {
2977 					bcap_val_11n_40[core] = bcap_val + 2;
2978 					scap_val_11n_40[core] = scap_val + 4;
2979 				}
2980 				lpf_ofdm_40mhz[core] = 4;
2981 			}
2982 
2983 			rccal_ovrd = true;
2984 			break;
2985 		case 14:
2986 			for (core = 0; core < 2; core++) {
2987 				bcap_val_11b[core] = bcap_val;
2988 				scap_val_11b[core] = scap_val;
2989 				lpf_11b[core] = 1;
2990 			}
2991 
2992 			bcap_val_11n_20[0] = bcap_val + 20;
2993 			scap_val_11n_20[0] = scap_val + 20;
2994 			lpf_ofdm_20mhz[0] = 3;
2995 
2996 			bcap_val_11n_20[1] = bcap_val + 16;
2997 			scap_val_11n_20[1] = scap_val + 16;
2998 			lpf_ofdm_20mhz[1] = 3;
2999 
3000 			bcap_val_11n_40[0] = bcap_val + 20;
3001 			scap_val_11n_40[0] = scap_val + 20;
3002 			lpf_ofdm_40mhz[0] = 4;
3003 
3004 			bcap_val_11n_40[1] = bcap_val + 10;
3005 			scap_val_11n_40[1] = scap_val + 10;
3006 			lpf_ofdm_40mhz[1] = 4;
3007 
3008 			rccal_ovrd = true;
3009 			break;
3010 		}
3011 	} else {
3012 		if (phy->rf_rev == 5) {
3013 			for (core = 0; core < 2; core++) {
3014 				lpf_ofdm_20mhz[core] = 1;
3015 				lpf_ofdm_40mhz[core] = 3;
3016 				scap_val_11b[core] = scap_val;
3017 				bcap_val_11b[core] = bcap_val;
3018 				scap_val_11n_20[core] = 0x11;
3019 				scap_val_11n_40[core] = 0x11;
3020 				bcap_val_11n_20[core] = 0x13;
3021 				bcap_val_11n_40[core] = 0x13;
3022 			}
3023 
3024 			rccal_ovrd = true;
3025 		}
3026 	}
3027 	if (rccal_ovrd) {
3028 		uint16_t rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];
3029 		uint8_t rx2tx_lut_extra = 1;
3030 
3031 		for (core = 0; core < 2; core++) {
3032 			bcap_val_11b[core] = bwn_clamp_val(bcap_val_11b[core], 0, 0x1f);
3033 			scap_val_11b[core] = bwn_clamp_val(scap_val_11b[core], 0, 0x1f);
3034 			bcap_val_11n_20[core] = bwn_clamp_val(bcap_val_11n_20[core], 0, 0x1f);
3035 			scap_val_11n_20[core] = bwn_clamp_val(scap_val_11n_20[core], 0, 0x1f);
3036 			bcap_val_11n_40[core] = bwn_clamp_val(bcap_val_11n_40[core], 0, 0x1f);
3037 			scap_val_11n_40[core] = bwn_clamp_val(scap_val_11n_40[core], 0, 0x1f);
3038 
3039 			rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |
3040 						 (bcap_val_11b[core] << 8) |
3041 						 (scap_val_11b[core] << 3) |
3042 						 lpf_11b[core];
3043 			rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |
3044 						 (bcap_val_11n_20[core] << 8) |
3045 						 (scap_val_11n_20[core] << 3) |
3046 						 lpf_ofdm_20mhz[core];
3047 			rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |
3048 						 (bcap_val_11n_40[core] << 8) |
3049 						 (scap_val_11n_40[core] << 3) |
3050 						 lpf_ofdm_40mhz[core];
3051 		}
3052 
3053 		for (core = 0; core < 2; core++) {
3054 			bwn_ntab_write(mac, BWN_NTAB16(7, 0x152 + core * 16),
3055 				       rx2tx_lut_20_11b[core]);
3056 			bwn_ntab_write(mac, BWN_NTAB16(7, 0x153 + core * 16),
3057 				       rx2tx_lut_20_11n[core]);
3058 			bwn_ntab_write(mac, BWN_NTAB16(7, 0x154 + core * 16),
3059 				       rx2tx_lut_20_11n[core]);
3060 			bwn_ntab_write(mac, BWN_NTAB16(7, 0x155 + core * 16),
3061 				       rx2tx_lut_40_11n[core]);
3062 			bwn_ntab_write(mac, BWN_NTAB16(7, 0x156 + core * 16),
3063 				       rx2tx_lut_40_11n[core]);
3064 			bwn_ntab_write(mac, BWN_NTAB16(7, 0x157 + core * 16),
3065 				       rx2tx_lut_40_11n[core]);
3066 			bwn_ntab_write(mac, BWN_NTAB16(7, 0x158 + core * 16),
3067 				       rx2tx_lut_40_11n[core]);
3068 			bwn_ntab_write(mac, BWN_NTAB16(7, 0x159 + core * 16),
3069 				       rx2tx_lut_40_11n[core]);
3070 		}
3071 	}
3072 
3073 	BWN_PHY_WRITE(mac, 0x32F, 0x3);
3074 
3075 	if (phy->rf_rev == 4 || phy->rf_rev == 6)
3076 		bwn_nphy_rf_ctl_override_rev7(mac, 4, 1, 3, false, 0);
3077 
3078 	if (phy->rf_rev == 3 || phy->rf_rev == 4 || phy->rf_rev == 6) {
3079 		if (siba_sprom_get_rev(sc->sc_dev) &&
3080 		    siba_sprom_get_bf2_hi(sc->sc_dev) & BWN_BFH2_IPALVLSHIFT_3P3) {
3081 			BWN_RF_WRITE(mac, 0x5, 0x05);
3082 			BWN_RF_WRITE(mac, 0x6, 0x30);
3083 			BWN_RF_WRITE(mac, 0x7, 0x00);
3084 			BWN_RF_SET(mac, 0x4f, 0x1);
3085 			BWN_RF_SET(mac, 0xd4, 0x1);
3086 			bias = 0x1f;
3087 			conv = 0x6f;
3088 			filt = 0xaa;
3089 		} else {
3090 			bias = 0x2b;
3091 			conv = 0x7f;
3092 			filt = 0xee;
3093 		}
3094 		if (bwn_current_band(mac) == BWN_BAND_2G) {
3095 			for (core = 0; core < 2; core++) {
3096 				if (core == 0) {
3097 					BWN_RF_WRITE(mac, 0x5F, bias);
3098 					BWN_RF_WRITE(mac, 0x64, conv);
3099 					BWN_RF_WRITE(mac, 0x66, filt);
3100 				} else {
3101 					BWN_RF_WRITE(mac, 0xE8, bias);
3102 					BWN_RF_WRITE(mac, 0xE9, conv);
3103 					BWN_RF_WRITE(mac, 0xEB, filt);
3104 				}
3105 			}
3106 		}
3107 	}
3108 
3109 	if (bwn_nphy_ipa(mac)) {
3110 		if (bwn_current_band(mac) == BWN_BAND_2G) {
3111 			if (phy->rf_rev == 3 || phy->rf_rev == 4 ||
3112 			    phy->rf_rev == 6) {
3113 				for (core = 0; core < 2; core++) {
3114 					if (core == 0)
3115 						BWN_RF_WRITE(mac, 0x51,
3116 								0x7f);
3117 					else
3118 						BWN_RF_WRITE(mac, 0xd6,
3119 								0x7f);
3120 				}
3121 			}
3122 			switch (phy->rf_rev) {
3123 			case 3:
3124 				for (core = 0; core < 2; core++) {
3125 					if (core == 0) {
3126 						BWN_RF_WRITE(mac, 0x64,
3127 								0x13);
3128 						BWN_RF_WRITE(mac, 0x5F,
3129 								0x1F);
3130 						BWN_RF_WRITE(mac, 0x66,
3131 								0xEE);
3132 						BWN_RF_WRITE(mac, 0x59,
3133 								0x8A);
3134 						BWN_RF_WRITE(mac, 0x80,
3135 								0x3E);
3136 					} else {
3137 						BWN_RF_WRITE(mac, 0x69,
3138 								0x13);
3139 						BWN_RF_WRITE(mac, 0xE8,
3140 								0x1F);
3141 						BWN_RF_WRITE(mac, 0xEB,
3142 								0xEE);
3143 						BWN_RF_WRITE(mac, 0xDE,
3144 								0x8A);
3145 						BWN_RF_WRITE(mac, 0x105,
3146 								0x3E);
3147 					}
3148 				}
3149 				break;
3150 			case 7:
3151 			case 8:
3152 				if (!bwn_is_40mhz(mac)) {
3153 					BWN_RF_WRITE(mac, 0x5F, 0x14);
3154 					BWN_RF_WRITE(mac, 0xE8, 0x12);
3155 				} else {
3156 					BWN_RF_WRITE(mac, 0x5F, 0x16);
3157 					BWN_RF_WRITE(mac, 0xE8, 0x16);
3158 				}
3159 				break;
3160 			case 14:
3161 				for (core = 0; core < 2; core++) {
3162 					int o = core ? 0x85 : 0;
3163 
3164 					BWN_RF_WRITE(mac, o + R2057_IPA2G_CASCONV_CORE0, 0x13);
3165 					BWN_RF_WRITE(mac, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);
3166 					BWN_RF_WRITE(mac, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);
3167 					BWN_RF_WRITE(mac, o + R2057_PAD2G_IDACS_CORE0, 0x88);
3168 					BWN_RF_WRITE(mac, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);
3169 					BWN_RF_WRITE(mac, o + R2057_IPA2G_IMAIN_CORE0, 0x16);
3170 					BWN_RF_WRITE(mac, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);
3171 					BWN_RF_WRITE(mac, o + R2057_BACKUP1_CORE0, 0x10);
3172 				}
3173 				break;
3174 			}
3175 		} else {
3176 			uint16_t freq = bwn_get_centre_freq(mac);
3177 			if ((freq >= 5180 && freq <= 5230) ||
3178 			    (freq >= 5745 && freq <= 5805)) {
3179 				BWN_RF_WRITE(mac, 0x7D, 0xFF);
3180 				BWN_RF_WRITE(mac, 0xFE, 0xFF);
3181 			}
3182 		}
3183 	} else {
3184 		if (phy->rf_rev != 5) {
3185 			for (core = 0; core < 2; core++) {
3186 				if (core == 0) {
3187 					BWN_RF_WRITE(mac, 0x5c, 0x61);
3188 					BWN_RF_WRITE(mac, 0x51, 0x70);
3189 				} else {
3190 					BWN_RF_WRITE(mac, 0xe1, 0x61);
3191 					BWN_RF_WRITE(mac, 0xd6, 0x70);
3192 				}
3193 			}
3194 		}
3195 	}
3196 
3197 	if (phy->rf_rev == 4) {
3198 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x05), 0x20);
3199 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x15), 0x20);
3200 		for (core = 0; core < 2; core++) {
3201 			if (core == 0) {
3202 				BWN_RF_WRITE(mac, 0x1a1, 0x00);
3203 				BWN_RF_WRITE(mac, 0x1a2, 0x3f);
3204 				BWN_RF_WRITE(mac, 0x1a6, 0x3f);
3205 			} else {
3206 				BWN_RF_WRITE(mac, 0x1a7, 0x00);
3207 				BWN_RF_WRITE(mac, 0x1ab, 0x3f);
3208 				BWN_RF_WRITE(mac, 0x1ac, 0x3f);
3209 			}
3210 		}
3211 	} else {
3212 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_C1, 0x4);
3213 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x4);
3214 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_C2, 0x4);
3215 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4);
3216 
3217 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x1);
3218 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x1);
3219 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x1);
3220 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x1);
3221 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x05), 0);
3222 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x15), 0);
3223 
3224 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x4);
3225 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, ~0x4);
3226 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x4);
3227 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x4);
3228 	}
3229 
3230 	BWN_PHY_WRITE(mac, BWN_NPHY_ENDROP_TLEN, 0x2);
3231 
3232 	bwn_ntab_write(mac, BWN_NTAB32(16, 0x100), 20);
3233 	bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x138), 2, ntab7_138_146);
3234 	bwn_ntab_write(mac, BWN_NTAB16(7, 0x141), 0x77);
3235 	bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x133), 3, ntab7_133);
3236 	bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x146), 2, ntab7_138_146);
3237 	bwn_ntab_write(mac, BWN_NTAB16(7, 0x123), 0x77);
3238 	bwn_ntab_write(mac, BWN_NTAB16(7, 0x12A), 0x77);
3239 
3240 	bwn_ntab_read_bulk(mac, BWN_NTAB32(16, 0x02), 1, noise_tbl);
3241 	noise_tbl[1] = bwn_is_40mhz(mac) ? 0x14D : 0x18D;
3242 	bwn_ntab_write_bulk(mac, BWN_NTAB32(16, 0x02), 2, noise_tbl);
3243 
3244 	bwn_ntab_read_bulk(mac, BWN_NTAB32(16, 0x7E), 1, noise_tbl);
3245 	noise_tbl[1] = bwn_is_40mhz(mac) ? 0x14D : 0x18D;
3246 	bwn_ntab_write_bulk(mac, BWN_NTAB32(16, 0x7E), 2, noise_tbl);
3247 
3248 	bwn_nphy_gain_ctl_workarounds(mac);
3249 
3250 	/* TODO
3251 	bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4,
3252 			    aux_adc_vmid_rev7_core0);
3253 	bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4,
3254 			    aux_adc_vmid_rev7_core1);
3255 	bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0C), 4,
3256 			    aux_adc_gain_rev7);
3257 	bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1C), 4,
3258 			    aux_adc_gain_rev7);
3259 	*/
3260 }
3261 
3262 static void bwn_nphy_workarounds_rev3plus(struct bwn_mac *mac)
3263 {
3264 	struct bwn_softc *sc = mac->mac_sc;
3265 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
3266 
3267 	/* TX to RX */
3268 	uint8_t tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F };
3269 	uint8_t tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 };
3270 	/* RX to TX */
3271 	uint8_t rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
3272 					0x1F };
3273 	uint8_t rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
3274 	uint8_t rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
3275 	uint8_t rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
3276 
3277 	uint16_t vmids[5][4] = {
3278 		{ 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */
3279 		{ 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */
3280 		{ 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */
3281 		{ 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */
3282 		{ 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */
3283 	};
3284 	uint16_t gains[5][4] = {
3285 		{ 0x02, 0x02, 0x02, 0x00, }, /* 0 */
3286 		{ 0x02, 0x02, 0x02, 0x02, }, /* 1 */
3287 		{ 0x02, 0x02, 0x02, 0x04, }, /* 2 */
3288 		{ 0x02, 0x02, 0x02, 0x00, }, /* 3 */
3289 		{ 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */
3290 	};
3291 	uint16_t *vmid, *gain;
3292 
3293 	uint8_t pdet_range;
3294 	uint16_t tmp16;
3295 	uint32_t tmp32;
3296 
3297 	BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x1f8);
3298 	BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x1f8);
3299 
3300 	tmp32 = bwn_ntab_read(mac, BWN_NTAB32(30, 0));
3301 	tmp32 &= 0xffffff;
3302 	bwn_ntab_write(mac, BWN_NTAB32(30, 0), tmp32);
3303 
3304 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x0125);
3305 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x01B3);
3306 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x0105);
3307 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x016E);
3308 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0x00CD);
3309 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x0020);
3310 
3311 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C);
3312 	BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C);
3313 
3314 	/* TX to RX */
3315 	bwn_nphy_set_rf_sequence(mac, 1, tx2rx_events, tx2rx_delays,
3316 				 nitems(tx2rx_events));
3317 
3318 	/* RX to TX */
3319 	if (bwn_nphy_ipa(mac))
3320 		bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events_ipa,
3321 				rx2tx_delays_ipa, nitems(rx2tx_events_ipa));
3322 	if (nphy->hw_phyrxchain != 3 &&
3323 	    nphy->hw_phyrxchain != nphy->hw_phytxchain) {
3324 		if (bwn_nphy_ipa(mac)) {
3325 			rx2tx_delays[5] = 59;
3326 			rx2tx_delays[6] = 1;
3327 			rx2tx_events[7] = 0x1F;
3328 		}
3329 		bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events, rx2tx_delays,
3330 					 nitems(rx2tx_events));
3331 	}
3332 
3333 	tmp16 = (bwn_current_band(mac) == BWN_BAND_2G) ?
3334 		0x2 : 0x9C40;
3335 	BWN_PHY_WRITE(mac, BWN_NPHY_ENDROP_TLEN, tmp16);
3336 
3337 	BWN_PHY_SETMASK(mac, BWN_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
3338 
3339 	if (!bwn_is_40mhz(mac)) {
3340 		bwn_ntab_write(mac, BWN_NTAB32(16, 3), 0x18D);
3341 		bwn_ntab_write(mac, BWN_NTAB32(16, 127), 0x18D);
3342 	} else {
3343 		bwn_ntab_write(mac, BWN_NTAB32(16, 3), 0x14D);
3344 		bwn_ntab_write(mac, BWN_NTAB32(16, 127), 0x14D);
3345 	}
3346 
3347 	bwn_nphy_gain_ctl_workarounds(mac);
3348 
3349 	bwn_ntab_write(mac, BWN_NTAB16(8, 0), 2);
3350 	bwn_ntab_write(mac, BWN_NTAB16(8, 16), 2);
3351 
3352 	if (bwn_current_band(mac) == BWN_BAND_2G)
3353 		pdet_range = siba_sprom_get_fem_2ghz_pdet_range(sc->sc_dev);
3354 	else
3355 		pdet_range = siba_sprom_get_fem_5ghz_pdet_range(sc->sc_dev);
3356 	/* uint16_t min() */
3357 	vmid = vmids[min(pdet_range, 4)];
3358 	gain = gains[min(pdet_range, 4)];
3359 	switch (pdet_range) {
3360 	case 3:
3361 		if (!(mac->mac_phy.rev >= 4 &&
3362 		      bwn_current_band(mac) == BWN_BAND_2G))
3363 			break;
3364 		/* FALL THROUGH */
3365 	case 0:
3366 	case 1:
3367 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid);
3368 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid);
3369 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain);
3370 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain);
3371 		break;
3372 	case 2:
3373 		if (mac->mac_phy.rev >= 6) {
3374 			if (bwn_current_band(mac) == BWN_BAND_2G)
3375 				vmid[3] = 0x94;
3376 			else
3377 				vmid[3] = 0x8e;
3378 			gain[3] = 3;
3379 		} else if (mac->mac_phy.rev == 5) {
3380 			vmid[3] = 0x84;
3381 			gain[3] = 2;
3382 		}
3383 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid);
3384 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid);
3385 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain);
3386 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain);
3387 		break;
3388 	case 4:
3389 	case 5:
3390 		if (bwn_current_band(mac) != BWN_BAND_2G) {
3391 			if (pdet_range == 4) {
3392 				vmid[3] = 0x8e;
3393 				tmp16 = 0x96;
3394 				gain[3] = 0x2;
3395 			} else {
3396 				vmid[3] = 0x89;
3397 				tmp16 = 0x89;
3398 				gain[3] = 0;
3399 			}
3400 		} else {
3401 			if (pdet_range == 4) {
3402 				vmid[3] = 0x89;
3403 				tmp16 = 0x8b;
3404 				gain[3] = 0x2;
3405 			} else {
3406 				vmid[3] = 0x74;
3407 				tmp16 = 0x70;
3408 				gain[3] = 0;
3409 			}
3410 		}
3411 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid);
3412 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain);
3413 		vmid[3] = tmp16;
3414 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid);
3415 		bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain);
3416 		break;
3417 	}
3418 
3419 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
3420 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
3421 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
3422 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
3423 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
3424 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
3425 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
3426 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
3427 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
3428 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
3429 	BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
3430 	BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
3431 
3432 	/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
3433 
3434 	if ((siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_APLL_WAR &&
3435 	     bwn_current_band(mac) == BWN_BAND_5G) ||
3436 	    (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_GPLL_WAR &&
3437 	     bwn_current_band(mac) == BWN_BAND_2G))
3438 		tmp32 = 0x00088888;
3439 	else
3440 		tmp32 = 0x88888888;
3441 	bwn_ntab_write(mac, BWN_NTAB32(30, 1), tmp32);
3442 	bwn_ntab_write(mac, BWN_NTAB32(30, 2), tmp32);
3443 	bwn_ntab_write(mac, BWN_NTAB32(30, 3), tmp32);
3444 
3445 	if (mac->mac_phy.rev == 4 &&
3446 	    bwn_current_band(mac) == BWN_BAND_5G) {
3447 		BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_GMBB_IDAC,
3448 				0x70);
3449 		BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_GMBB_IDAC,
3450 				0x70);
3451 	}
3452 
3453 	/* Dropped probably-always-true condition */
3454 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb);
3455 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb);
3456 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341);
3457 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);
3458 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b);
3459 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b);
3460 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381);
3461 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381);
3462 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b);
3463 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b);
3464 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381);
3465 	BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381);
3466 
3467 	if (mac->mac_phy.rev >= 6 && siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SINGLEANT_CCK)
3468 		; /* TODO: 0x0080000000000000 HF */
3469 }
3470 
3471 static void bwn_nphy_workarounds_rev1_2(struct bwn_mac *mac)
3472 {
3473 	struct bwn_softc *sc = mac->mac_sc;
3474 	struct bwn_phy *phy = &mac->mac_phy;
3475 	struct bwn_phy_n *nphy = phy->phy_n;
3476 
3477 	uint8_t events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
3478 	uint8_t delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
3479 
3480 	uint8_t events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
3481 	uint8_t delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
3482 
3483 	if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SKWRKFEM_BRD ||
3484 	    siba_get_pci_subdevice(sc->sc_dev)== BCMA_BOARD_TYPE_BCM943224M93) {
3485 		delays1[0] = 0x1;
3486 		delays1[5] = 0x14;
3487 	}
3488 
3489 	if (bwn_current_band(mac) == BWN_BAND_5G &&
3490 	    nphy->band5g_pwrgain) {
3491 		BWN_RF_MASK(mac, B2055_C1_TX_RF_SPARE, ~0x8);
3492 		BWN_RF_MASK(mac, B2055_C2_TX_RF_SPARE, ~0x8);
3493 	} else {
3494 		BWN_RF_SET(mac, B2055_C1_TX_RF_SPARE, 0x8);
3495 		BWN_RF_SET(mac, B2055_C2_TX_RF_SPARE, 0x8);
3496 	}
3497 
3498 	bwn_ntab_write(mac, BWN_NTAB16(8, 0x00), 0x000A);
3499 	bwn_ntab_write(mac, BWN_NTAB16(8, 0x10), 0x000A);
3500 	if (mac->mac_phy.rev < 3) {
3501 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x02), 0xCDAA);
3502 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x12), 0xCDAA);
3503 	}
3504 
3505 	if (mac->mac_phy.rev < 2) {
3506 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x08), 0x0000);
3507 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x18), 0x0000);
3508 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x07), 0x7AAB);
3509 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x17), 0x7AAB);
3510 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x06), 0x0800);
3511 		bwn_ntab_write(mac, BWN_NTAB16(8, 0x16), 0x0800);
3512 	}
3513 
3514 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
3515 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
3516 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
3517 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
3518 
3519 	bwn_nphy_set_rf_sequence(mac, 0, events1, delays1, 7);
3520 	bwn_nphy_set_rf_sequence(mac, 1, events2, delays2, 7);
3521 
3522 	bwn_nphy_gain_ctl_workarounds(mac);
3523 
3524 	if (mac->mac_phy.rev < 2) {
3525 		if (BWN_PHY_READ(mac, BWN_NPHY_RXCTL) & 0x2)
3526 			bwn_hf_write(mac, bwn_hf_read(mac) |
3527 					BWN_HF_MLADVW);
3528 	} else if (mac->mac_phy.rev == 2) {
3529 		BWN_PHY_WRITE(mac, BWN_NPHY_CRSCHECK2, 0);
3530 		BWN_PHY_WRITE(mac, BWN_NPHY_CRSCHECK3, 0);
3531 	}
3532 
3533 	if (mac->mac_phy.rev < 2)
3534 		BWN_PHY_MASK(mac, BWN_NPHY_SCRAM_SIGCTL,
3535 				~BWN_NPHY_SCRAM_SIGCTL_SCM);
3536 
3537 	/* Set phase track alpha and beta */
3538 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x125);
3539 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x1B3);
3540 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x105);
3541 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x16E);
3542 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0xCD);
3543 	BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x20);
3544 
3545 	if (mac->mac_phy.rev < 3) {
3546 		BWN_PHY_MASK(mac, BWN_NPHY_PIL_DW1,
3547 			     ~BWN_NPHY_PIL_DW_64QAM & 0xFFFF);
3548 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B1, 0xB5);
3549 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B2, 0xA4);
3550 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B3, 0x00);
3551 	}
3552 
3553 	if (mac->mac_phy.rev == 2)
3554 		BWN_PHY_SET(mac, BWN_NPHY_FINERX2_CGC,
3555 				BWN_NPHY_FINERX2_CGC_DECGC);
3556 }
3557 
3558 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
3559 static void bwn_nphy_workarounds(struct bwn_mac *mac)
3560 {
3561 	struct bwn_phy *phy = &mac->mac_phy;
3562 	struct bwn_phy_n *nphy = phy->phy_n;
3563 
3564 	if (bwn_current_band(mac) == BWN_BAND_5G)
3565 		bwn_nphy_classifier(mac, 1, 0);
3566 	else
3567 		bwn_nphy_classifier(mac, 1, 1);
3568 
3569 	if (nphy->hang_avoid)
3570 		bwn_nphy_stay_in_carrier_search(mac, 1);
3571 
3572 	BWN_PHY_SET(mac, BWN_NPHY_IQFLIP,
3573 		    BWN_NPHY_IQFLIP_ADC1 | BWN_NPHY_IQFLIP_ADC2);
3574 
3575 	/* TODO: rev19+ */
3576 	if (mac->mac_phy.rev >= 7)
3577 		bwn_nphy_workarounds_rev7plus(mac);
3578 	else if (mac->mac_phy.rev >= 3)
3579 		bwn_nphy_workarounds_rev3plus(mac);
3580 	else
3581 		bwn_nphy_workarounds_rev1_2(mac);
3582 
3583 	if (nphy->hang_avoid)
3584 		bwn_nphy_stay_in_carrier_search(mac, 0);
3585 }
3586 
3587 /**************************************************
3588  * Tx/Rx common
3589  **************************************************/
3590 
3591 /*
3592  * Transmits a known value for LO calibration
3593  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
3594  */
3595 static int bwn_nphy_tx_tone(struct bwn_mac *mac, uint32_t freq, uint16_t max_val,
3596 			    bool iqmode, bool dac_test, bool modify_bbmult)
3597 {
3598 	uint16_t samp = bwn_nphy_gen_load_samples(mac, freq, max_val, dac_test);
3599 	if (samp == 0)
3600 		return -1;
3601 	bwn_nphy_run_samples(mac, samp, 0xFFFF, 0, iqmode, dac_test,
3602 			     modify_bbmult);
3603 	return 0;
3604 }
3605 
3606 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
3607 static void bwn_nphy_update_txrx_chain(struct bwn_mac *mac)
3608 {
3609 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
3610 
3611 	bool override = false;
3612 	uint16_t chain = 0x33;
3613 
3614 	if (nphy->txrx_chain == 0) {
3615 		chain = 0x11;
3616 		override = true;
3617 	} else if (nphy->txrx_chain == 1) {
3618 		chain = 0x22;
3619 		override = true;
3620 	}
3621 
3622 	BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA,
3623 			~(BWN_NPHY_RFSEQCA_TXEN | BWN_NPHY_RFSEQCA_RXEN),
3624 			chain);
3625 
3626 	if (override)
3627 		BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE,
3628 				BWN_NPHY_RFSEQMODE_CAOVER);
3629 	else
3630 		BWN_PHY_MASK(mac, BWN_NPHY_RFSEQMODE,
3631 				~BWN_NPHY_RFSEQMODE_CAOVER);
3632 }
3633 
3634 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
3635 static void bwn_nphy_stop_playback(struct bwn_mac *mac)
3636 {
3637 	struct bwn_phy *phy = &mac->mac_phy;
3638 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
3639 	uint16_t tmp;
3640 
3641 	if (nphy->hang_avoid)
3642 		bwn_nphy_stay_in_carrier_search(mac, 1);
3643 
3644 	tmp = BWN_PHY_READ(mac, BWN_NPHY_SAMP_STAT);
3645 	if (tmp & 0x1)
3646 		BWN_PHY_SET(mac, BWN_NPHY_SAMP_CMD, BWN_NPHY_SAMP_CMD_STOP);
3647 	else if (tmp & 0x2)
3648 		BWN_PHY_MASK(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
3649 
3650 	BWN_PHY_MASK(mac, BWN_NPHY_SAMP_CMD, ~0x0004);
3651 
3652 	if (nphy->bb_mult_save & 0x80000000) {
3653 		tmp = nphy->bb_mult_save & 0xFFFF;
3654 		bwn_ntab_write(mac, BWN_NTAB16(15, 87), tmp);
3655 		nphy->bb_mult_save = 0;
3656 	}
3657 
3658 	if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) {
3659 		if (phy->rev >= 19)
3660 			bwn_nphy_rf_ctl_override_rev19(mac, 0x80, 0, 0, true,
3661 						       1);
3662 		else
3663 			bwn_nphy_rf_ctl_override_rev7(mac, 0x80, 0, 0, true, 1);
3664 		nphy->lpf_bw_overrode_for_sample_play = false;
3665 	}
3666 
3667 	if (nphy->hang_avoid)
3668 		bwn_nphy_stay_in_carrier_search(mac, 0);
3669 }
3670 
3671 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
3672 static void bwn_nphy_iq_cal_gain_params(struct bwn_mac *mac, uint16_t core,
3673 					struct bwn_nphy_txgains target,
3674 					struct bwn_nphy_iqcal_params *params)
3675 {
3676 	struct bwn_phy *phy = &mac->mac_phy;
3677 	int i, j, indx;
3678 	uint16_t gain;
3679 
3680 	if (mac->mac_phy.rev >= 3) {
3681 		params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */
3682 		params->txgm = target.txgm[core];
3683 		params->pga = target.pga[core];
3684 		params->pad = target.pad[core];
3685 		params->ipa = target.ipa[core];
3686 		if (phy->rev >= 19) {
3687 			/* TODO */
3688 		} else if (phy->rev >= 7) {
3689 			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15);
3690 		} else {
3691 			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa);
3692 		}
3693 		for (j = 0; j < 5; j++)
3694 			params->ncorr[j] = 0x79;
3695 	} else {
3696 		gain = (target.pad[core]) | (target.pga[core] << 4) |
3697 			(target.txgm[core] << 8);
3698 
3699 		indx = (bwn_current_band(mac) == BWN_BAND_5G) ?
3700 			1 : 0;
3701 		for (i = 0; i < 9; i++)
3702 			if (tbl_iqcal_gainparams[indx][i][0] == gain)
3703 				break;
3704 		i = min(i, 8);
3705 
3706 		params->txgm = tbl_iqcal_gainparams[indx][i][1];
3707 		params->pga = tbl_iqcal_gainparams[indx][i][2];
3708 		params->pad = tbl_iqcal_gainparams[indx][i][3];
3709 		params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
3710 					(params->pad << 2);
3711 		for (j = 0; j < 4; j++)
3712 			params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
3713 	}
3714 }
3715 
3716 /**************************************************
3717  * Tx and Rx
3718  **************************************************/
3719 
3720 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
3721 static void bwn_nphy_tx_power_ctrl(struct bwn_mac *mac, bool enable)
3722 {
3723 	struct bwn_phy *phy = &mac->mac_phy;
3724 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
3725 	uint8_t i;
3726 	uint16_t bmask, val, tmp;
3727 	bwn_band_t band = bwn_current_band(mac);
3728 
3729 	if (nphy->hang_avoid)
3730 		bwn_nphy_stay_in_carrier_search(mac, 1);
3731 
3732 	nphy->txpwrctrl = enable;
3733 	if (!enable) {
3734 		if (mac->mac_phy.rev >= 3 &&
3735 		    (BWN_PHY_READ(mac, BWN_NPHY_TXPCTL_CMD) &
3736 		     (BWN_NPHY_TXPCTL_CMD_COEFF |
3737 		      BWN_NPHY_TXPCTL_CMD_HWPCTLEN |
3738 		      BWN_NPHY_TXPCTL_CMD_PCTLEN))) {
3739 			/* We disable enabled TX pwr ctl, save it's state */
3740 			nphy->tx_pwr_idx[0] = BWN_PHY_READ(mac,
3741 						BWN_NPHY_C1_TXPCTL_STAT) & 0x7f;
3742 			nphy->tx_pwr_idx[1] = BWN_PHY_READ(mac,
3743 						BWN_NPHY_C2_TXPCTL_STAT) & 0x7f;
3744 		}
3745 
3746 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x6840);
3747 		for (i = 0; i < 84; i++)
3748 			BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0);
3749 
3750 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x6C40);
3751 		for (i = 0; i < 84; i++)
3752 			BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0);
3753 
3754 		tmp = BWN_NPHY_TXPCTL_CMD_COEFF | BWN_NPHY_TXPCTL_CMD_HWPCTLEN;
3755 		if (mac->mac_phy.rev >= 3)
3756 			tmp |= BWN_NPHY_TXPCTL_CMD_PCTLEN;
3757 		BWN_PHY_MASK(mac, BWN_NPHY_TXPCTL_CMD, ~tmp);
3758 
3759 		if (mac->mac_phy.rev >= 3) {
3760 			BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0100);
3761 			BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0100);
3762 		} else {
3763 			BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4000);
3764 		}
3765 
3766 		if (mac->mac_phy.rev == 2)
3767 			BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3,
3768 				~BWN_NPHY_BPHY_CTL3_SCALE, 0x53);
3769 		else if (mac->mac_phy.rev < 2)
3770 			BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3,
3771 				~BWN_NPHY_BPHY_CTL3_SCALE, 0x5A);
3772 
3773 		if (mac->mac_phy.rev < 2 && bwn_is_40mhz(mac))
3774 			bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
3775 	} else {
3776 		bwn_ntab_write_bulk(mac, BWN_NTAB16(26, 64), 84,
3777 				    nphy->adj_pwr_tbl);
3778 		bwn_ntab_write_bulk(mac, BWN_NTAB16(27, 64), 84,
3779 				    nphy->adj_pwr_tbl);
3780 
3781 		bmask = BWN_NPHY_TXPCTL_CMD_COEFF |
3782 			BWN_NPHY_TXPCTL_CMD_HWPCTLEN;
3783 		/* wl does useless check for "enable" param here */
3784 		val = BWN_NPHY_TXPCTL_CMD_COEFF | BWN_NPHY_TXPCTL_CMD_HWPCTLEN;
3785 		if (mac->mac_phy.rev >= 3) {
3786 			bmask |= BWN_NPHY_TXPCTL_CMD_PCTLEN;
3787 			if (val)
3788 				val |= BWN_NPHY_TXPCTL_CMD_PCTLEN;
3789 		}
3790 		BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, ~(bmask), val);
3791 
3792 		if (band == BWN_BAND_5G) {
3793 			if (phy->rev >= 19) {
3794 				/* TODO */
3795 			} else if (phy->rev >= 7) {
3796 				BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD,
3797 						~BWN_NPHY_TXPCTL_CMD_INIT,
3798 						0x32);
3799 				BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT,
3800 						~BWN_NPHY_TXPCTL_INIT_PIDXI1,
3801 						0x32);
3802 			} else {
3803 				BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD,
3804 						~BWN_NPHY_TXPCTL_CMD_INIT,
3805 						0x64);
3806 				if (phy->rev > 1)
3807 					BWN_PHY_SETMASK(mac,
3808 							BWN_NPHY_TXPCTL_INIT,
3809 							~BWN_NPHY_TXPCTL_INIT_PIDXI1,
3810 							0x64);
3811 			}
3812 		}
3813 
3814 		if (mac->mac_phy.rev >= 3) {
3815 			if (nphy->tx_pwr_idx[0] != 128 &&
3816 			    nphy->tx_pwr_idx[1] != 128) {
3817 				/* Recover TX pwr ctl state */
3818 				BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD,
3819 						~BWN_NPHY_TXPCTL_CMD_INIT,
3820 						nphy->tx_pwr_idx[0]);
3821 				if (mac->mac_phy.rev > 1)
3822 					BWN_PHY_SETMASK(mac,
3823 						BWN_NPHY_TXPCTL_INIT,
3824 						~0xff, nphy->tx_pwr_idx[1]);
3825 			}
3826 		}
3827 
3828 		if (phy->rev >= 7) {
3829 			/* TODO */
3830 		}
3831 
3832 		if (mac->mac_phy.rev >= 3) {
3833 			BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, ~0x100);
3834 			BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x100);
3835 		} else {
3836 			BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x4000);
3837 		}
3838 
3839 		if (mac->mac_phy.rev == 2)
3840 			BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
3841 		else if (mac->mac_phy.rev < 2)
3842 			BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, ~0xFF, 0x40);
3843 
3844 		if (mac->mac_phy.rev < 2 && bwn_is_40mhz(mac))
3845 			bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_TSSI_RESET_PSM_WORKAROUN);
3846 
3847 		if (bwn_nphy_ipa(mac)) {
3848 			BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x4);
3849 			BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x4);
3850 		}
3851 	}
3852 
3853 	if (nphy->hang_avoid)
3854 		bwn_nphy_stay_in_carrier_search(mac, 0);
3855 }
3856 
3857 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
3858 static void bwn_nphy_tx_power_fix(struct bwn_mac *mac)
3859 {
3860 	struct bwn_softc *sc = mac->mac_sc;
3861 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
3862 
3863 	uint8_t txpi[2], bbmult, i;
3864 	uint16_t tmp, radio_gain, dac_gain;
3865 	uint16_t freq = bwn_get_centre_freq(mac);
3866 	uint32_t txgain;
3867 	/* uint32_t gaintbl; rev3+ */
3868 
3869 	if (nphy->hang_avoid)
3870 		bwn_nphy_stay_in_carrier_search(mac, 1);
3871 
3872 	/* TODO: rev19+ */
3873 	if (mac->mac_phy.rev >= 7) {
3874 		txpi[0] = txpi[1] = 30;
3875 	} else if (mac->mac_phy.rev >= 3) {
3876 		txpi[0] = 40;
3877 		txpi[1] = 40;
3878 	} else if (siba_sprom_get_rev(sc->sc_dev) < 4) {
3879 		txpi[0] = 72;
3880 		txpi[1] = 72;
3881 	} else {
3882 		if (bwn_current_band(mac) == BWN_BAND_2G) {
3883 			txpi[0] = siba_sprom_get_txpid_2g_0(sc->sc_dev);
3884 			txpi[1] = siba_sprom_get_txpid_2g_1(sc->sc_dev);
3885 		} else if (freq >= 4900 && freq < 5100) {
3886 			txpi[0] = siba_sprom_get_txpid_5gl_0(sc->sc_dev);
3887 			txpi[1] = siba_sprom_get_txpid_5gl_1(sc->sc_dev);
3888 		} else if (freq >= 5100 && freq < 5500) {
3889 			txpi[0] = siba_sprom_get_txpid_5g_0(sc->sc_dev);
3890 			txpi[1] = siba_sprom_get_txpid_5g_1(sc->sc_dev);
3891 		} else if (freq >= 5500) {
3892 			txpi[0] = siba_sprom_get_txpid_5gh_0(sc->sc_dev);
3893 			txpi[1] = siba_sprom_get_txpid_5gh_1(sc->sc_dev);
3894 		} else {
3895 			txpi[0] = 91;
3896 			txpi[1] = 91;
3897 		}
3898 	}
3899 	if (mac->mac_phy.rev < 7 &&
3900 	    (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100))
3901 		txpi[0] = txpi[1] = 91;
3902 
3903 	/*
3904 	for (i = 0; i < 2; i++) {
3905 		nphy->txpwrindex[i].index_internal = txpi[i];
3906 		nphy->txpwrindex[i].index_internal_save = txpi[i];
3907 	}
3908 	*/
3909 
3910 	for (i = 0; i < 2; i++) {
3911 		const uint32_t *table = bwn_nphy_get_tx_gain_table(mac);
3912 
3913 		if (!table)
3914 			break;
3915 		txgain = *(table + txpi[i]);
3916 
3917 		if (mac->mac_phy.rev >= 3)
3918 			radio_gain = (txgain >> 16) & 0x1FFFF;
3919 		else
3920 			radio_gain = (txgain >> 16) & 0x1FFF;
3921 
3922 		if (mac->mac_phy.rev >= 7)
3923 			dac_gain = (txgain >> 8) & 0x7;
3924 		else
3925 			dac_gain = (txgain >> 8) & 0x3F;
3926 		bbmult = txgain & 0xFF;
3927 
3928 		if (mac->mac_phy.rev >= 3) {
3929 			if (i == 0)
3930 				BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0100);
3931 			else
3932 				BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0100);
3933 		} else {
3934 			BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4000);
3935 		}
3936 
3937 		if (i == 0)
3938 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_DACGAIN1, dac_gain);
3939 		else
3940 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_DACGAIN2, dac_gain);
3941 
3942 		bwn_ntab_write(mac, BWN_NTAB16(0x7, 0x110 + i), radio_gain);
3943 
3944 		tmp = bwn_ntab_read(mac, BWN_NTAB16(0xF, 0x57));
3945 		if (i == 0)
3946 			tmp = (tmp & 0x00FF) | (bbmult << 8);
3947 		else
3948 			tmp = (tmp & 0xFF00) | bbmult;
3949 		bwn_ntab_write(mac, BWN_NTAB16(0xF, 0x57), tmp);
3950 
3951 		if (bwn_nphy_ipa(mac)) {
3952 			uint32_t tmp32;
3953 			uint16_t reg = (i == 0) ?
3954 				BWN_NPHY_PAPD_EN0 : BWN_NPHY_PAPD_EN1;
3955 			tmp32 = bwn_ntab_read(mac, BWN_NTAB32(26 + i,
3956 							      576 + txpi[i]));
3957 			BWN_PHY_SETMASK(mac, reg, 0xE00F, (uint32_t) tmp32 << 4);
3958 			BWN_PHY_SET(mac, reg, 0x4);
3959 		}
3960 	}
3961 
3962 	BWN_PHY_MASK(mac, BWN_NPHY_BPHY_CTL2, ~BWN_NPHY_BPHY_CTL2_LUT);
3963 
3964 	if (nphy->hang_avoid)
3965 		bwn_nphy_stay_in_carrier_search(mac, 0);
3966 }
3967 
3968 static void bwn_nphy_ipa_internal_tssi_setup(struct bwn_mac *mac)
3969 {
3970 	struct bwn_phy *phy = &mac->mac_phy;
3971 
3972 	uint8_t core;
3973 	uint16_t r; /* routing */
3974 
3975 	if (phy->rev >= 19) {
3976 		/* TODO */
3977 	} else if (phy->rev >= 7) {
3978 		for (core = 0; core < 2; core++) {
3979 			r = core ? 0x190 : 0x170;
3980 			if (bwn_current_band(mac) == BWN_BAND_2G) {
3981 				BWN_RF_WRITE(mac, r + 0x5, 0x5);
3982 				BWN_RF_WRITE(mac, r + 0x9, 0xE);
3983 				if (phy->rev != 5)
3984 					BWN_RF_WRITE(mac, r + 0xA, 0);
3985 				if (phy->rev != 7)
3986 					BWN_RF_WRITE(mac, r + 0xB, 1);
3987 				else
3988 					BWN_RF_WRITE(mac, r + 0xB, 0x31);
3989 			} else {
3990 				BWN_RF_WRITE(mac, r + 0x5, 0x9);
3991 				BWN_RF_WRITE(mac, r + 0x9, 0xC);
3992 				BWN_RF_WRITE(mac, r + 0xB, 0x0);
3993 				if (phy->rev != 5)
3994 					BWN_RF_WRITE(mac, r + 0xA, 1);
3995 				else
3996 					BWN_RF_WRITE(mac, r + 0xA, 0x31);
3997 			}
3998 			BWN_RF_WRITE(mac, r + 0x6, 0);
3999 			BWN_RF_WRITE(mac, r + 0x7, 0);
4000 			BWN_RF_WRITE(mac, r + 0x8, 3);
4001 			BWN_RF_WRITE(mac, r + 0xC, 0);
4002 		}
4003 	} else {
4004 		if (bwn_current_band(mac) == BWN_BAND_2G)
4005 			BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR31, 0x128);
4006 		else
4007 			BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR31, 0x80);
4008 		BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR30, 0);
4009 		BWN_RF_WRITE(mac, B2056_SYN_GPIO_MASTER1, 0x29);
4010 
4011 		for (core = 0; core < 2; core++) {
4012 			r = core ? B2056_TX1 : B2056_TX0;
4013 
4014 			BWN_RF_WRITE(mac, r | B2056_TX_IQCAL_VCM_HG, 0);
4015 			BWN_RF_WRITE(mac, r | B2056_TX_IQCAL_IDAC, 0);
4016 			BWN_RF_WRITE(mac, r | B2056_TX_TSSI_VCM, 3);
4017 			BWN_RF_WRITE(mac, r | B2056_TX_TX_AMP_DET, 0);
4018 			BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC1, 8);
4019 			BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC2, 0);
4020 			BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC3, 0);
4021 			if (bwn_current_band(mac) == BWN_BAND_2G) {
4022 				BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MASTER,
4023 						0x5);
4024 				if (phy->rev != 5)
4025 					BWN_RF_WRITE(mac, r | B2056_TX_TSSIA,
4026 							0x00);
4027 				if (phy->rev >= 5)
4028 					BWN_RF_WRITE(mac, r | B2056_TX_TSSIG,
4029 							0x31);
4030 				else
4031 					BWN_RF_WRITE(mac, r | B2056_TX_TSSIG,
4032 							0x11);
4033 				BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MUX,
4034 						0xE);
4035 			} else {
4036 				BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MASTER,
4037 						0x9);
4038 				BWN_RF_WRITE(mac, r | B2056_TX_TSSIA, 0x31);
4039 				BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 0x0);
4040 				BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MUX,
4041 						0xC);
4042 			}
4043 		}
4044 	}
4045 }
4046 
4047 /*
4048  * Stop radio and transmit known signal. Then check received signal strength to
4049  * get TSSI (Transmit Signal Strength Indicator).
4050  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi
4051  */
4052 static void bwn_nphy_tx_power_ctl_idle_tssi(struct bwn_mac *mac)
4053 {
4054 	struct bwn_phy *phy = &mac->mac_phy;
4055 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4056 
4057 	uint32_t tmp;
4058 	int32_t rssi[4] = { };
4059 
4060 	if (bwn_is_chan_passive(mac))
4061 		return;
4062 
4063 	if (bwn_nphy_ipa(mac))
4064 		bwn_nphy_ipa_internal_tssi_setup(mac);
4065 
4066 	if (phy->rev >= 19)
4067 		bwn_nphy_rf_ctl_override_rev19(mac, 0x1000, 0, 3, false, 0);
4068 	else if (phy->rev >= 7)
4069 		bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, 0, 3, false, 0);
4070 	else if (phy->rev >= 3)
4071 		bwn_nphy_rf_ctl_override(mac, 0x2000, 0, 3, false);
4072 
4073 	bwn_nphy_stop_playback(mac);
4074 	bwn_nphy_tx_tone(mac, 4000, 0, false, false, false);
4075 	DELAY(20);
4076 	tmp = bwn_nphy_poll_rssi(mac, N_RSSI_TSSI_2G, rssi, 1);
4077 	bwn_nphy_stop_playback(mac);
4078 
4079 	bwn_nphy_rssi_select(mac, 0, N_RSSI_W1);
4080 
4081 	if (phy->rev >= 19)
4082 		bwn_nphy_rf_ctl_override_rev19(mac, 0x1000, 0, 3, true, 0);
4083 	else if (phy->rev >= 7)
4084 		bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, 0, 3, true, 0);
4085 	else if (phy->rev >= 3)
4086 		bwn_nphy_rf_ctl_override(mac, 0x2000, 0, 3, true);
4087 
4088 	if (phy->rev >= 19) {
4089 		/* TODO */
4090 		return;
4091 	} else if (phy->rev >= 3) {
4092 		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
4093 		nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
4094 	} else {
4095 		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF;
4096 		nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF;
4097 	}
4098 	nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF;
4099 	nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF;
4100 }
4101 
4102 /* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */
4103 static void bwn_nphy_tx_prepare_adjusted_power_table(struct bwn_mac *mac)
4104 {
4105 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4106 
4107 	uint8_t idx, delta;
4108 	uint8_t i, stf_mode;
4109 
4110 	/* Array adj_pwr_tbl corresponds to the hardware table. It consists of
4111 	 * 21 groups, each containing 4 entries.
4112 	 *
4113 	 * First group has entries for CCK modulation.
4114 	 * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM).
4115 	 *
4116 	 * Group 0 is for CCK
4117 	 * Groups 1..4 use BPSK (group per coding rate)
4118 	 * Groups 5..8 use QPSK (group per coding rate)
4119 	 * Groups 9..12 use 16-QAM (group per coding rate)
4120 	 * Groups 13..16 use 64-QAM (group per coding rate)
4121 	 * Groups 17..20 are unknown
4122 	 */
4123 
4124 	for (i = 0; i < 4; i++)
4125 		nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i];
4126 
4127 	for (stf_mode = 0; stf_mode < 4; stf_mode++) {
4128 		delta = 0;
4129 		switch (stf_mode) {
4130 		case 0:
4131 			if (bwn_is_40mhz(mac) && mac->mac_phy.rev >= 5) {
4132 				idx = 68;
4133 			} else {
4134 				delta = 1;
4135 				idx = bwn_is_40mhz(mac) ? 52 : 4;
4136 			}
4137 			break;
4138 		case 1:
4139 			idx = bwn_is_40mhz(mac) ? 76 : 28;
4140 			break;
4141 		case 2:
4142 			idx = bwn_is_40mhz(mac) ? 84 : 36;
4143 			break;
4144 		case 3:
4145 			idx = bwn_is_40mhz(mac) ? 92 : 44;
4146 			break;
4147 		}
4148 
4149 		for (i = 0; i < 20; i++) {
4150 			nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] =
4151 				nphy->tx_power_offset[idx];
4152 			if (i == 0)
4153 				idx += delta;
4154 			if (i == 14)
4155 				idx += 1 - delta;
4156 			if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 ||
4157 			    i == 13)
4158 				idx += 1;
4159 		}
4160 	}
4161 }
4162 
4163 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
4164 static void bwn_nphy_tx_power_ctl_setup(struct bwn_mac *mac)
4165 {
4166 	struct bwn_softc *sc = mac->mac_sc;
4167 	struct bwn_phy *phy = &mac->mac_phy;
4168 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4169 	struct siba_sprom_core_pwr_info core_pwr_info[4];
4170 	int n;
4171 
4172 	int16_t a1[2], b0[2], b1[2];
4173 	uint8_t idle[2];
4174 	uint8_t ppr_max;
4175 	int8_t target[2];
4176 	int32_t num, den, pwr;
4177 	uint32_t regval[64];
4178 
4179 	uint16_t freq = bwn_get_centre_freq(mac);
4180 	uint16_t tmp;
4181 	uint16_t r; /* routing */
4182 	uint8_t i, c;
4183 
4184 	for (n = 0; n < 4; n++) {
4185 		bzero(&core_pwr_info[n], sizeof(core_pwr_info[n]));
4186 		if (siba_sprom_get_core_power_info(sc->sc_dev, n,
4187 		    &core_pwr_info[n]) != 0) {
4188 			BWN_ERRPRINTF(mac->mac_sc,
4189 			    "%s: failed to get core_pwr_info for core %d\n",
4190 			    __func__,
4191 			    n);
4192 		}
4193 	}
4194 
4195 	if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) {
4196 		BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, 0x200000);
4197 		BWN_READ_4(mac, BWN_MACCTL);
4198 		DELAY(1);
4199 	}
4200 
4201 	if (nphy->hang_avoid)
4202 		bwn_nphy_stay_in_carrier_search(mac, true);
4203 
4204 	BWN_PHY_SET(mac, BWN_NPHY_TSSIMODE, BWN_NPHY_TSSIMODE_EN);
4205 	if (mac->mac_phy.rev >= 3)
4206 		BWN_PHY_MASK(mac, BWN_NPHY_TXPCTL_CMD,
4207 			     ~BWN_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF);
4208 	else
4209 		BWN_PHY_SET(mac, BWN_NPHY_TXPCTL_CMD,
4210 			    BWN_NPHY_TXPCTL_CMD_PCTLEN);
4211 
4212 	if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12)
4213 		BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0x200000, 0);
4214 
4215 	/*
4216 	 * XXX TODO: see if those bandsbelow map to 5g-lo, 5g-mid, 5g-hi in
4217 	 * any way.
4218 	 */
4219 	if (siba_sprom_get_rev(sc->sc_dev) < 4) {
4220 		idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g;
4221 		idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g;
4222 		target[0] = target[1] = 52;
4223 		a1[0] = a1[1] = -424;
4224 		b0[0] = b0[1] = 5612;
4225 		b1[0] = b1[1] = -1393;
4226 	} else {
4227 		if (bwn_current_band(mac) == BWN_BAND_2G) {
4228 			for (c = 0; c < 2; c++) {
4229 				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g;
4230 				target[c] = core_pwr_info[c].maxpwr_2g;
4231 				a1[c] = core_pwr_info[c].pa_2g[0];
4232 				b0[c] = core_pwr_info[c].pa_2g[1];
4233 				b1[c] = core_pwr_info[c].pa_2g[2];
4234 			}
4235 		} else if (freq >= 4900 && freq < 5100) {
4236 			for (c = 0; c < 2; c++) {
4237 				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
4238 				target[c] = core_pwr_info[c].maxpwr_5gl;
4239 				a1[c] = core_pwr_info[c].pa_5gl[0];
4240 				b0[c] = core_pwr_info[c].pa_5gl[1];
4241 				b1[c] = core_pwr_info[c].pa_5gl[2];
4242 			}
4243 		} else if (freq >= 5100 && freq < 5500) {
4244 			for (c = 0; c < 2; c++) {
4245 				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
4246 				target[c] = core_pwr_info[c].maxpwr_5g;
4247 				a1[c] = core_pwr_info[c].pa_5g[0];
4248 				b0[c] = core_pwr_info[c].pa_5g[1];
4249 				b1[c] = core_pwr_info[c].pa_5g[2];
4250 			}
4251 		} else if (freq >= 5500) {
4252 			for (c = 0; c < 2; c++) {
4253 				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
4254 				target[c] = core_pwr_info[c].maxpwr_5gh;
4255 				a1[c] = core_pwr_info[c].pa_5gh[0];
4256 				b0[c] = core_pwr_info[c].pa_5gh[1];
4257 				b1[c] = core_pwr_info[c].pa_5gh[2];
4258 			}
4259 		} else {
4260 			idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g;
4261 			idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g;
4262 			target[0] = target[1] = 52;
4263 			a1[0] = a1[1] = -424;
4264 			b0[0] = b0[1] = 5612;
4265 			b1[0] = b1[1] = -1393;
4266 		}
4267 	}
4268 
4269 	ppr_max = bwn_ppr_get_max(mac, &nphy->tx_pwr_max_ppr);
4270 	if (ppr_max) {
4271 		target[0] = ppr_max;
4272 		target[1] = ppr_max;
4273 	}
4274 
4275 	if (mac->mac_phy.rev >= 3) {
4276 		if (siba_sprom_get_fem_2ghz_tssipos(sc->sc_dev))
4277 			BWN_PHY_SET(mac, BWN_NPHY_TXPCTL_ITSSI, 0x4000);
4278 		if (mac->mac_phy.rev >= 7) {
4279 			for (c = 0; c < 2; c++) {
4280 				r = c ? 0x190 : 0x170;
4281 				if (bwn_nphy_ipa(mac))
4282 					BWN_RF_WRITE(mac, r + 0x9, (bwn_current_band(mac) == BWN_BAND_2G) ? 0xE : 0xC);
4283 			}
4284 		} else {
4285 			if (bwn_nphy_ipa(mac)) {
4286 				tmp = (bwn_current_band(mac) == BWN_BAND_5G) ? 0xC : 0xE;
4287 				BWN_RF_WRITE(mac,
4288 					B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp);
4289 				BWN_RF_WRITE(mac,
4290 					B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp);
4291 			} else {
4292 				BWN_RF_WRITE(mac,
4293 					B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11);
4294 				BWN_RF_WRITE(mac,
4295 					B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11);
4296 			}
4297 		}
4298 	}
4299 
4300 	if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) {
4301 		BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, 0x200000);
4302 		BWN_READ_4(mac, BWN_MACCTL);
4303 		DELAY(1);
4304 	}
4305 
4306 	if (phy->rev >= 19) {
4307 		/* TODO */
4308 	} else if (phy->rev >= 7) {
4309 		BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD,
4310 				~BWN_NPHY_TXPCTL_CMD_INIT, 0x19);
4311 		BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT,
4312 				~BWN_NPHY_TXPCTL_INIT_PIDXI1, 0x19);
4313 	} else {
4314 		BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD,
4315 				~BWN_NPHY_TXPCTL_CMD_INIT, 0x40);
4316 		if (mac->mac_phy.rev > 1)
4317 			BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT,
4318 				~BWN_NPHY_TXPCTL_INIT_PIDXI1, 0x40);
4319 	}
4320 
4321 	if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12)
4322 		BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0x200000, 0);
4323 
4324 	BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_N,
4325 		      0xF0 << BWN_NPHY_TXPCTL_N_TSSID_SHIFT |
4326 		      3 << BWN_NPHY_TXPCTL_N_NPTIL2_SHIFT);
4327 	BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_ITSSI,
4328 		      idle[0] << BWN_NPHY_TXPCTL_ITSSI_0_SHIFT |
4329 		      idle[1] << BWN_NPHY_TXPCTL_ITSSI_1_SHIFT |
4330 		      BWN_NPHY_TXPCTL_ITSSI_BINF);
4331 	BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_TPWR,
4332 		      target[0] << BWN_NPHY_TXPCTL_TPWR_0_SHIFT |
4333 		      target[1] << BWN_NPHY_TXPCTL_TPWR_1_SHIFT);
4334 
4335 	for (c = 0; c < 2; c++) {
4336 		for (i = 0; i < 64; i++) {
4337 			num = 8 * (16 * b0[c] + b1[c] * i);
4338 			den = 32768 + a1[c] * i;
4339 			pwr = max((4 * num + den / 2) / den, -8);
4340 			if (mac->mac_phy.rev < 3 && (i <= (31 - idle[c] + 1)))
4341 				pwr = max(pwr, target[c] + 1);
4342 			regval[i] = pwr;
4343 		}
4344 		bwn_ntab_write_bulk(mac, BWN_NTAB32(26 + c, 0), 64, regval);
4345 	}
4346 
4347 	bwn_nphy_tx_prepare_adjusted_power_table(mac);
4348 	bwn_ntab_write_bulk(mac, BWN_NTAB16(26, 64), 84, nphy->adj_pwr_tbl);
4349 	bwn_ntab_write_bulk(mac, BWN_NTAB16(27, 64), 84, nphy->adj_pwr_tbl);
4350 
4351 	if (nphy->hang_avoid)
4352 		bwn_nphy_stay_in_carrier_search(mac, false);
4353 }
4354 
4355 static void bwn_nphy_tx_gain_table_upload(struct bwn_mac *mac)
4356 {
4357 	struct bwn_phy *phy = &mac->mac_phy;
4358 
4359 	const uint32_t *table = NULL;
4360 	uint32_t rfpwr_offset;
4361 	uint8_t pga_gain, pad_gain;
4362 	int i;
4363 	const int16_t *rf_pwr_offset_table = NULL;
4364 
4365 	table = bwn_nphy_get_tx_gain_table(mac);
4366 	if (!table)
4367 		return;
4368 
4369 	bwn_ntab_write_bulk(mac, BWN_NTAB32(26, 192), 128, table);
4370 	bwn_ntab_write_bulk(mac, BWN_NTAB32(27, 192), 128, table);
4371 
4372 	if (phy->rev < 3)
4373 		return;
4374 
4375 #if 0
4376 	nphy->gmval = (table[0] >> 16) & 0x7000;
4377 #endif
4378 
4379 	if (phy->rev >= 19) {
4380 		return;
4381 	} else if (phy->rev >= 7) {
4382 		rf_pwr_offset_table = bwn_ntab_get_rf_pwr_offset_table(mac);
4383 		if (!rf_pwr_offset_table)
4384 			return;
4385 		/* TODO: Enable this once we have gains configured */
4386 		return;
4387 	}
4388 
4389 	for (i = 0; i < 128; i++) {
4390 		if (phy->rev >= 19) {
4391 			/* TODO */
4392 			return;
4393 		} else if (phy->rev >= 7) {
4394 			pga_gain = (table[i] >> 24) & 0xf;
4395 			pad_gain = (table[i] >> 19) & 0x1f;
4396 			if (bwn_current_band(mac) == BWN_BAND_2G)
4397 				rfpwr_offset = rf_pwr_offset_table[pad_gain];
4398 			else
4399 				rfpwr_offset = rf_pwr_offset_table[pga_gain];
4400 		} else {
4401 			pga_gain = (table[i] >> 24) & 0xF;
4402 			if (bwn_current_band(mac) == BWN_BAND_2G)
4403 				rfpwr_offset = bwn_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
4404 			else
4405 				rfpwr_offset = 0; /* FIXME */
4406 		}
4407 
4408 		bwn_ntab_write(mac, BWN_NTAB32(26, 576 + i), rfpwr_offset);
4409 		bwn_ntab_write(mac, BWN_NTAB32(27, 576 + i), rfpwr_offset);
4410 	}
4411 }
4412 
4413 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
4414 static void bwn_nphy_pa_override(struct bwn_mac *mac, bool enable)
4415 {
4416 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4417 	bwn_band_t band;
4418 	uint16_t tmp;
4419 
4420 	if (!enable) {
4421 		nphy->rfctrl_intc1_save = BWN_PHY_READ(mac,
4422 						       BWN_NPHY_RFCTL_INTC1);
4423 		nphy->rfctrl_intc2_save = BWN_PHY_READ(mac,
4424 						       BWN_NPHY_RFCTL_INTC2);
4425 		band = bwn_current_band(mac);
4426 		if (mac->mac_phy.rev >= 7) {
4427 			tmp = 0x1480;
4428 		} else if (mac->mac_phy.rev >= 3) {
4429 			if (band == BWN_BAND_5G)
4430 				tmp = 0x600;
4431 			else
4432 				tmp = 0x480;
4433 		} else {
4434 			if (band == BWN_BAND_5G)
4435 				tmp = 0x180;
4436 			else
4437 				tmp = 0x120;
4438 		}
4439 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, tmp);
4440 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, tmp);
4441 	} else {
4442 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1,
4443 				nphy->rfctrl_intc1_save);
4444 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2,
4445 				nphy->rfctrl_intc2_save);
4446 	}
4447 }
4448 
4449 /*
4450  * TX low-pass filter bandwidth setup
4451  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw
4452  */
4453 static void bwn_nphy_tx_lpf_bw(struct bwn_mac *mac)
4454 {
4455 	uint16_t tmp;
4456 
4457 	if (mac->mac_phy.rev < 3 || mac->mac_phy.rev >= 7)
4458 		return;
4459 
4460 	if (bwn_nphy_ipa(mac))
4461 		tmp = bwn_is_40mhz(mac) ? 5 : 4;
4462 	else
4463 		tmp = bwn_is_40mhz(mac) ? 3 : 1;
4464 	BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S2,
4465 		      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
4466 
4467 	if (bwn_nphy_ipa(mac)) {
4468 		tmp = bwn_is_40mhz(mac) ? 4 : 1;
4469 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S2,
4470 			      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
4471 	}
4472 }
4473 
4474 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
4475 static void bwn_nphy_rx_iq_est(struct bwn_mac *mac, struct bwn_nphy_iq_est *est,
4476 				uint16_t samps, uint8_t time, bool wait)
4477 {
4478 	int i;
4479 	uint16_t tmp;
4480 
4481 	BWN_PHY_WRITE(mac, BWN_NPHY_IQEST_SAMCNT, samps);
4482 	BWN_PHY_SETMASK(mac, BWN_NPHY_IQEST_WT, ~BWN_NPHY_IQEST_WT_VAL, time);
4483 	if (wait)
4484 		BWN_PHY_SET(mac, BWN_NPHY_IQEST_CMD, BWN_NPHY_IQEST_CMD_MODE);
4485 	else
4486 		BWN_PHY_MASK(mac, BWN_NPHY_IQEST_CMD, ~BWN_NPHY_IQEST_CMD_MODE);
4487 
4488 	BWN_PHY_SET(mac, BWN_NPHY_IQEST_CMD, BWN_NPHY_IQEST_CMD_START);
4489 
4490 	for (i = 1000; i; i--) {
4491 		tmp = BWN_PHY_READ(mac, BWN_NPHY_IQEST_CMD);
4492 		if (!(tmp & BWN_NPHY_IQEST_CMD_START)) {
4493 			est->i0_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_HI0) << 16) |
4494 					BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_LO0);
4495 			est->q0_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_HI0) << 16) |
4496 					BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_LO0);
4497 			est->iq0_prod = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_HI0) << 16) |
4498 					BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_LO0);
4499 
4500 			est->i1_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_HI1) << 16) |
4501 					BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_LO1);
4502 			est->q1_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_HI1) << 16) |
4503 					BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_LO1);
4504 			est->iq1_prod = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_HI1) << 16) |
4505 					BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_LO1);
4506 			return;
4507 		}
4508 		DELAY(10);
4509 	}
4510 	memset(est, 0, sizeof(*est));
4511 }
4512 
4513 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
4514 static void bwn_nphy_rx_iq_coeffs(struct bwn_mac *mac, bool write,
4515 					struct bwn_phy_n_iq_comp *pcomp)
4516 {
4517 	if (write) {
4518 		BWN_PHY_WRITE(mac, BWN_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
4519 		BWN_PHY_WRITE(mac, BWN_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
4520 		BWN_PHY_WRITE(mac, BWN_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
4521 		BWN_PHY_WRITE(mac, BWN_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
4522 	} else {
4523 		pcomp->a0 = BWN_PHY_READ(mac, BWN_NPHY_C1_RXIQ_COMPA0);
4524 		pcomp->b0 = BWN_PHY_READ(mac, BWN_NPHY_C1_RXIQ_COMPB0);
4525 		pcomp->a1 = BWN_PHY_READ(mac, BWN_NPHY_C2_RXIQ_COMPA1);
4526 		pcomp->b1 = BWN_PHY_READ(mac, BWN_NPHY_C2_RXIQ_COMPB1);
4527 	}
4528 }
4529 
4530 #if 0
4531 /* Ready but not used anywhere */
4532 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
4533 static void bwn_nphy_rx_cal_phy_cleanup(struct bwn_mac *mac, uint8_t core)
4534 {
4535 	uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs;
4536 
4537 	BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQCA, regs[0]);
4538 	if (core == 0) {
4539 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, regs[1]);
4540 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, regs[2]);
4541 	} else {
4542 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, regs[1]);
4543 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[2]);
4544 	}
4545 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[3]);
4546 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[4]);
4547 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO1, regs[5]);
4548 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO2, regs[6]);
4549 	BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S1, regs[7]);
4550 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, regs[8]);
4551 	BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN0, regs[9]);
4552 	BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN1, regs[10]);
4553 }
4554 
4555 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
4556 static void bwn_nphy_rx_cal_phy_setup(struct bwn_mac *mac, uint8_t core)
4557 {
4558 	uint8_t rxval, txval;
4559 	uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs;
4560 
4561 	regs[0] = BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA);
4562 	if (core == 0) {
4563 		regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1);
4564 		regs[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1);
4565 	} else {
4566 		regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2);
4567 		regs[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER);
4568 	}
4569 	regs[3] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1);
4570 	regs[4] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2);
4571 	regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO1);
4572 	regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO2);
4573 	regs[7] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B1S1);
4574 	regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_OVER);
4575 	regs[9] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN0);
4576 	regs[10] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN1);
4577 
4578 	BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x0001);
4579 	BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x0001);
4580 
4581 	BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA,
4582 			~BWN_NPHY_RFSEQCA_RXDIS & 0xFFFF,
4583 			((1 - core) << BWN_NPHY_RFSEQCA_RXDIS_SHIFT));
4584 	BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXEN,
4585 			((1 - core) << BWN_NPHY_RFSEQCA_TXEN_SHIFT));
4586 	BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_RXEN,
4587 			(core << BWN_NPHY_RFSEQCA_RXEN_SHIFT));
4588 	BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXDIS,
4589 			(core << BWN_NPHY_RFSEQCA_TXDIS_SHIFT));
4590 
4591 	if (core == 0) {
4592 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x0007);
4593 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0007);
4594 	} else {
4595 		BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x0007);
4596 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0007);
4597 	}
4598 
4599 	bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 0, 3);
4600 	bwn_nphy_rf_ctl_override(mac, 8, 0, 3, false);
4601 	bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RX2TX);
4602 
4603 	if (core == 0) {
4604 		rxval = 1;
4605 		txval = 8;
4606 	} else {
4607 		rxval = 4;
4608 		txval = 2;
4609 	}
4610 	bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, rxval,
4611 				      core + 1);
4612 	bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, txval,
4613 				      2 - core);
4614 }
4615 #endif
4616 
4617 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
4618 static void bwn_nphy_calc_rx_iq_comp(struct bwn_mac *mac, uint8_t mask)
4619 {
4620 	int i;
4621 	int32_t iq;
4622 	uint32_t ii;
4623 	uint32_t qq;
4624 	int iq_nbits, qq_nbits;
4625 	int arsh, brsh;
4626 	uint16_t tmp, a, b;
4627 
4628 	struct bwn_nphy_iq_est est;
4629 	struct bwn_phy_n_iq_comp old;
4630 	struct bwn_phy_n_iq_comp new = { };
4631 	bool error = false;
4632 
4633 	if (mask == 0)
4634 		return;
4635 
4636 	bwn_nphy_rx_iq_coeffs(mac, false, &old);
4637 	bwn_nphy_rx_iq_coeffs(mac, true, &new);
4638 	bwn_nphy_rx_iq_est(mac, &est, 0x4000, 32, false);
4639 	new = old;
4640 
4641 	for (i = 0; i < 2; i++) {
4642 		if (i == 0 && (mask & 1)) {
4643 			iq = est.iq0_prod;
4644 			ii = est.i0_pwr;
4645 			qq = est.q0_pwr;
4646 		} else if (i == 1 && (mask & 2)) {
4647 			iq = est.iq1_prod;
4648 			ii = est.i1_pwr;
4649 			qq = est.q1_pwr;
4650 		} else {
4651 			continue;
4652 		}
4653 
4654 		if (ii + qq < 2) {
4655 			error = true;
4656 			break;
4657 		}
4658 
4659 		iq_nbits = fls(abs(iq));
4660 		qq_nbits = fls(qq);
4661 
4662 		arsh = iq_nbits - 20;
4663 		if (arsh >= 0) {
4664 			a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
4665 			tmp = ii >> arsh;
4666 		} else {
4667 			a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
4668 			tmp = ii << -arsh;
4669 		}
4670 		if (tmp == 0) {
4671 			error = true;
4672 			break;
4673 		}
4674 		a /= tmp;
4675 
4676 		brsh = qq_nbits - 11;
4677 		if (brsh >= 0) {
4678 			b = (qq << (31 - qq_nbits));
4679 			tmp = ii >> brsh;
4680 		} else {
4681 			b = (qq << (31 - qq_nbits));
4682 			tmp = ii << -brsh;
4683 		}
4684 		if (tmp == 0) {
4685 			error = true;
4686 			break;
4687 		}
4688 		b = bwn_sqrt(mac, b / tmp - a * a) - (1 << 10);
4689 
4690 		if (i == 0 && (mask & 0x1)) {
4691 			if (mac->mac_phy.rev >= 3) {
4692 				new.a0 = a & 0x3FF;
4693 				new.b0 = b & 0x3FF;
4694 			} else {
4695 				new.a0 = b & 0x3FF;
4696 				new.b0 = a & 0x3FF;
4697 			}
4698 		} else if (i == 1 && (mask & 0x2)) {
4699 			if (mac->mac_phy.rev >= 3) {
4700 				new.a1 = a & 0x3FF;
4701 				new.b1 = b & 0x3FF;
4702 			} else {
4703 				new.a1 = b & 0x3FF;
4704 				new.b1 = a & 0x3FF;
4705 			}
4706 		}
4707 	}
4708 
4709 	if (error)
4710 		new = old;
4711 
4712 	bwn_nphy_rx_iq_coeffs(mac, true, &new);
4713 }
4714 
4715 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
4716 static void bwn_nphy_tx_iq_workaround(struct bwn_mac *mac)
4717 {
4718 	uint16_t array[4];
4719 	bwn_ntab_read_bulk(mac, BWN_NTAB16(0xF, 0x50), 4, array);
4720 
4721 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW0, array[0]);
4722 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW1, array[1]);
4723 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW2, array[2]);
4724 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW3, array[3]);
4725 }
4726 
4727 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
4728 static void bwn_nphy_spur_workaround(struct bwn_mac *mac)
4729 {
4730 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4731 
4732 	uint8_t channel = bwn_get_chan(mac);
4733 	int tone[2] = { 57, 58 };
4734 	uint32_t noise[2] = { 0x3FF, 0x3FF };
4735 
4736 	if (mac->mac_phy.rev < 3) {
4737 		BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n",
4738 		    __func__,
4739 		    mac->mac_phy.rev);
4740 	}
4741 
4742 	if (nphy->hang_avoid)
4743 		bwn_nphy_stay_in_carrier_search(mac, 1);
4744 
4745 	if (nphy->gband_spurwar_en) {
4746 		/* TODO: N PHY Adjust Analog Pfbw (7) */
4747 		if (channel == 11 && bwn_is_40mhz(mac))
4748 			; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
4749 		else
4750 			; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
4751 		/* TODO: N PHY Adjust CRS Min Power (0x1E) */
4752 	}
4753 
4754 	if (nphy->aband_spurwar_en) {
4755 		if (channel == 54) {
4756 			tone[0] = 0x20;
4757 			noise[0] = 0x25F;
4758 		} else if (channel == 38 || channel == 102 || channel == 118) {
4759 			if (0 /* FIXME */) {
4760 				tone[0] = 0x20;
4761 				noise[0] = 0x21F;
4762 			} else {
4763 				tone[0] = 0;
4764 				noise[0] = 0;
4765 			}
4766 		} else if (channel == 134) {
4767 			tone[0] = 0x20;
4768 			noise[0] = 0x21F;
4769 		} else if (channel == 151) {
4770 			tone[0] = 0x10;
4771 			noise[0] = 0x23F;
4772 		} else if (channel == 153 || channel == 161) {
4773 			tone[0] = 0x30;
4774 			noise[0] = 0x23F;
4775 		} else {
4776 			tone[0] = 0;
4777 			noise[0] = 0;
4778 		}
4779 
4780 		if (!tone[0] && !noise[0])
4781 			; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
4782 		else
4783 			; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
4784 	}
4785 
4786 	if (nphy->hang_avoid)
4787 		bwn_nphy_stay_in_carrier_search(mac, 0);
4788 }
4789 
4790 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
4791 static void bwn_nphy_tx_pwr_ctrl_coef_setup(struct bwn_mac *mac)
4792 {
4793 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4794 	int i, j;
4795 	uint32_t tmp;
4796 	uint32_t cur_real, cur_imag, real_part, imag_part;
4797 
4798 	uint16_t buffer[7];
4799 
4800 	if (nphy->hang_avoid)
4801 		bwn_nphy_stay_in_carrier_search(mac, true);
4802 
4803 	bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 7, buffer);
4804 
4805 	for (i = 0; i < 2; i++) {
4806 		tmp = ((buffer[i * 2] & 0x3FF) << 10) |
4807 			(buffer[i * 2 + 1] & 0x3FF);
4808 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR,
4809 				(((i + 26) << 10) | 320));
4810 		for (j = 0; j < 128; j++) {
4811 			BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATAHI,
4812 					((tmp >> 16) & 0xFFFF));
4813 			BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO,
4814 					(tmp & 0xFFFF));
4815 		}
4816 	}
4817 
4818 	for (i = 0; i < 2; i++) {
4819 		tmp = buffer[5 + i];
4820 		real_part = (tmp >> 8) & 0xFF;
4821 		imag_part = (tmp & 0xFF);
4822 		BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR,
4823 				(((i + 26) << 10) | 448));
4824 
4825 		if (mac->mac_phy.rev >= 3) {
4826 			cur_real = real_part;
4827 			cur_imag = imag_part;
4828 			tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
4829 		}
4830 
4831 		for (j = 0; j < 128; j++) {
4832 			if (mac->mac_phy.rev < 3) {
4833 				cur_real = (real_part * loscale[j] + 128) >> 8;
4834 				cur_imag = (imag_part * loscale[j] + 128) >> 8;
4835 				tmp = ((cur_real & 0xFF) << 8) |
4836 					(cur_imag & 0xFF);
4837 			}
4838 			BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATAHI,
4839 					((tmp >> 16) & 0xFFFF));
4840 			BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO,
4841 					(tmp & 0xFFFF));
4842 		}
4843 	}
4844 
4845 	if (mac->mac_phy.rev >= 3) {
4846 		bwn_shm_write_2(mac, BWN_SHARED,
4847 				BWN_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
4848 		bwn_shm_write_2(mac, BWN_SHARED,
4849 				BWN_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
4850 	}
4851 
4852 	if (nphy->hang_avoid)
4853 		bwn_nphy_stay_in_carrier_search(mac, false);
4854 }
4855 
4856 /*
4857  * Restore RSSI Calibration
4858  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
4859  */
4860 static void bwn_nphy_restore_rssi_cal(struct bwn_mac *mac)
4861 {
4862 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4863 
4864 	uint16_t *rssical_radio_regs = NULL;
4865 	uint16_t *rssical_phy_regs = NULL;
4866 
4867 	if (bwn_current_band(mac) == BWN_BAND_2G) {
4868 		if (!nphy->rssical_chanspec_2G.center_freq)
4869 			return;
4870 		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
4871 		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
4872 	} else {
4873 		if (!nphy->rssical_chanspec_5G.center_freq)
4874 			return;
4875 		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
4876 		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
4877 	}
4878 
4879 	if (mac->mac_phy.rev >= 19) {
4880 		/* TODO */
4881 	} else if (mac->mac_phy.rev >= 7) {
4882 		BWN_RF_SETMASK(mac, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK,
4883 				  rssical_radio_regs[0]);
4884 		BWN_RF_SETMASK(mac, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK,
4885 				  rssical_radio_regs[1]);
4886 	} else {
4887 		BWN_RF_SETMASK(mac, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
4888 				  rssical_radio_regs[0]);
4889 		BWN_RF_SETMASK(mac, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3,
4890 				  rssical_radio_regs[1]);
4891 	}
4892 
4893 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
4894 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
4895 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
4896 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
4897 
4898 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
4899 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
4900 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
4901 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
4902 
4903 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
4904 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
4905 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
4906 	BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
4907 }
4908 
4909 static void bwn_nphy_tx_cal_radio_setup_rev19(struct bwn_mac *mac)
4910 {
4911 	/* TODO */
4912 }
4913 
4914 static void bwn_nphy_tx_cal_radio_setup_rev7(struct bwn_mac *mac)
4915 {
4916 	struct bwn_phy *phy = &mac->mac_phy;
4917 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4918 	uint16_t *save = nphy->tx_rx_cal_radio_saveregs;
4919 	int core, off;
4920 	uint16_t r, tmp;
4921 
4922 	for (core = 0; core < 2; core++) {
4923 		r = core ? 0x20 : 0;
4924 		off = core * 11;
4925 
4926 		save[off + 0] = BWN_RF_READ(mac, r + R2057_TX0_TX_SSI_MASTER);
4927 		save[off + 1] = BWN_RF_READ(mac, r + R2057_TX0_IQCAL_VCM_HG);
4928 		save[off + 2] = BWN_RF_READ(mac, r + R2057_TX0_IQCAL_IDAC);
4929 		save[off + 3] = BWN_RF_READ(mac, r + R2057_TX0_TSSI_VCM);
4930 		save[off + 4] = 0;
4931 		save[off + 5] = BWN_RF_READ(mac, r + R2057_TX0_TX_SSI_MUX);
4932 		if (phy->rf_rev != 5)
4933 			save[off + 6] = BWN_RF_READ(mac, r + R2057_TX0_TSSIA);
4934 		save[off + 7] = BWN_RF_READ(mac, r + R2057_TX0_TSSIG);
4935 		save[off + 8] = BWN_RF_READ(mac, r + R2057_TX0_TSSI_MISC1);
4936 
4937 		if (bwn_current_band(mac) == BWN_BAND_5G) {
4938 			BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MASTER, 0xA);
4939 			BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
4940 			BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_IDAC, 0x55);
4941 			BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_VCM, 0);
4942 			BWN_RF_WRITE(mac, r + R2057_TX0_TSSIG, 0);
4943 			if (nphy->use_int_tx_iq_lo_cal) {
4944 				BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MUX, 0x4);
4945 				tmp = true ? 0x31 : 0x21; /* TODO */
4946 				BWN_RF_WRITE(mac, r + R2057_TX0_TSSIA, tmp);
4947 			}
4948 			BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_MISC1, 0x00);
4949 		} else {
4950 			BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MASTER, 0x6);
4951 			BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
4952 			BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_IDAC, 0x55);
4953 			BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_VCM, 0);
4954 
4955 			if (phy->rf_rev != 5)
4956 				BWN_RF_WRITE(mac, r + R2057_TX0_TSSIA, 0);
4957 			if (nphy->use_int_tx_iq_lo_cal) {
4958 				BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MUX, 0x6);
4959 				tmp = true ? 0x31 : 0x21; /* TODO */
4960 				BWN_RF_WRITE(mac, r + R2057_TX0_TSSIG, tmp);
4961 			}
4962 			BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_MISC1, 0);
4963 		}
4964 	}
4965 }
4966 
4967 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
4968 static void bwn_nphy_tx_cal_radio_setup(struct bwn_mac *mac)
4969 {
4970 	struct bwn_phy *phy = &mac->mac_phy;
4971 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
4972 	uint16_t *save = nphy->tx_rx_cal_radio_saveregs;
4973 	uint16_t tmp;
4974 	uint8_t offset, i;
4975 
4976 	if (phy->rev >= 19) {
4977 		bwn_nphy_tx_cal_radio_setup_rev19(mac);
4978 	} else if (phy->rev >= 7) {
4979 		bwn_nphy_tx_cal_radio_setup_rev7(mac);
4980 	} else if (phy->rev >= 3) {
4981 	    for (i = 0; i < 2; i++) {
4982 		tmp = (i == 0) ? 0x2000 : 0x3000;
4983 		offset = i * 11;
4984 
4985 		save[offset + 0] = BWN_RF_READ(mac, B2055_CAL_RVARCTL);
4986 		save[offset + 1] = BWN_RF_READ(mac, B2055_CAL_LPOCTL);
4987 		save[offset + 2] = BWN_RF_READ(mac, B2055_CAL_TS);
4988 		save[offset + 3] = BWN_RF_READ(mac, B2055_CAL_RCCALRTS);
4989 		save[offset + 4] = BWN_RF_READ(mac, B2055_CAL_RCALRTS);
4990 		save[offset + 5] = BWN_RF_READ(mac, B2055_PADDRV);
4991 		save[offset + 6] = BWN_RF_READ(mac, B2055_XOCTL1);
4992 		save[offset + 7] = BWN_RF_READ(mac, B2055_XOCTL2);
4993 		save[offset + 8] = BWN_RF_READ(mac, B2055_XOREGUL);
4994 		save[offset + 9] = BWN_RF_READ(mac, B2055_XOMISC);
4995 		save[offset + 10] = BWN_RF_READ(mac, B2055_PLL_LFC1);
4996 
4997 		if (bwn_current_band(mac) == BWN_BAND_5G) {
4998 			BWN_RF_WRITE(mac, tmp | B2055_CAL_RVARCTL, 0x0A);
4999 			BWN_RF_WRITE(mac, tmp | B2055_CAL_LPOCTL, 0x40);
5000 			BWN_RF_WRITE(mac, tmp | B2055_CAL_TS, 0x55);
5001 			BWN_RF_WRITE(mac, tmp | B2055_CAL_RCCALRTS, 0);
5002 			BWN_RF_WRITE(mac, tmp | B2055_CAL_RCALRTS, 0);
5003 			if (nphy->ipa5g_on) {
5004 				BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 4);
5005 				BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 1);
5006 			} else {
5007 				BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 0);
5008 				BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 0x2F);
5009 			}
5010 			BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 0);
5011 		} else {
5012 			BWN_RF_WRITE(mac, tmp | B2055_CAL_RVARCTL, 0x06);
5013 			BWN_RF_WRITE(mac, tmp | B2055_CAL_LPOCTL, 0x40);
5014 			BWN_RF_WRITE(mac, tmp | B2055_CAL_TS, 0x55);
5015 			BWN_RF_WRITE(mac, tmp | B2055_CAL_RCCALRTS, 0);
5016 			BWN_RF_WRITE(mac, tmp | B2055_CAL_RCALRTS, 0);
5017 			BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 0);
5018 			if (nphy->ipa2g_on) {
5019 				BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 6);
5020 				BWN_RF_WRITE(mac, tmp | B2055_XOCTL2,
5021 					(mac->mac_phy.rev < 5) ? 0x11 : 0x01);
5022 			} else {
5023 				BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 0);
5024 				BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 0);
5025 			}
5026 		}
5027 		BWN_RF_WRITE(mac, tmp | B2055_XOREGUL, 0);
5028 		BWN_RF_WRITE(mac, tmp | B2055_XOMISC, 0);
5029 		BWN_RF_WRITE(mac, tmp | B2055_PLL_LFC1, 0);
5030 	    }
5031 	} else {
5032 		save[0] = BWN_RF_READ(mac, B2055_C1_TX_RF_IQCAL1);
5033 		BWN_RF_WRITE(mac, B2055_C1_TX_RF_IQCAL1, 0x29);
5034 
5035 		save[1] = BWN_RF_READ(mac, B2055_C1_TX_RF_IQCAL2);
5036 		BWN_RF_WRITE(mac, B2055_C1_TX_RF_IQCAL2, 0x54);
5037 
5038 		save[2] = BWN_RF_READ(mac, B2055_C2_TX_RF_IQCAL1);
5039 		BWN_RF_WRITE(mac, B2055_C2_TX_RF_IQCAL1, 0x29);
5040 
5041 		save[3] = BWN_RF_READ(mac, B2055_C2_TX_RF_IQCAL2);
5042 		BWN_RF_WRITE(mac, B2055_C2_TX_RF_IQCAL2, 0x54);
5043 
5044 		save[3] = BWN_RF_READ(mac, B2055_C1_PWRDET_RXTX);
5045 		save[4] = BWN_RF_READ(mac, B2055_C2_PWRDET_RXTX);
5046 
5047 		if (!(BWN_PHY_READ(mac, BWN_NPHY_BANDCTL) &
5048 		    BWN_NPHY_BANDCTL_5GHZ)) {
5049 			BWN_RF_WRITE(mac, B2055_C1_PWRDET_RXTX, 0x04);
5050 			BWN_RF_WRITE(mac, B2055_C2_PWRDET_RXTX, 0x04);
5051 		} else {
5052 			BWN_RF_WRITE(mac, B2055_C1_PWRDET_RXTX, 0x20);
5053 			BWN_RF_WRITE(mac, B2055_C2_PWRDET_RXTX, 0x20);
5054 		}
5055 
5056 		if (mac->mac_phy.rev < 2) {
5057 			BWN_RF_SET(mac, B2055_C1_TX_BB_MXGM, 0x20);
5058 			BWN_RF_SET(mac, B2055_C2_TX_BB_MXGM, 0x20);
5059 		} else {
5060 			BWN_RF_MASK(mac, B2055_C1_TX_BB_MXGM, ~0x20);
5061 			BWN_RF_MASK(mac, B2055_C2_TX_BB_MXGM, ~0x20);
5062 		}
5063 	}
5064 }
5065 
5066 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
5067 static void bwn_nphy_update_tx_cal_ladder(struct bwn_mac *mac, uint16_t core)
5068 {
5069 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
5070 	int i;
5071 	uint16_t scale, entry;
5072 
5073 	uint16_t tmp = nphy->txcal_bbmult;
5074 	if (core == 0)
5075 		tmp >>= 8;
5076 	tmp &= 0xff;
5077 
5078 	for (i = 0; i < 18; i++) {
5079 		scale = (ladder_lo[i].percent * tmp) / 100;
5080 		entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
5081 		bwn_ntab_write(mac, BWN_NTAB16(15, i), entry);
5082 
5083 		scale = (ladder_iq[i].percent * tmp) / 100;
5084 		entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
5085 		bwn_ntab_write(mac, BWN_NTAB16(15, i + 32), entry);
5086 	}
5087 }
5088 
5089 static void bwn_nphy_pa_set_tx_dig_filter(struct bwn_mac *mac, uint16_t offset,
5090 					  const int16_t *filter)
5091 {
5092 	int i;
5093 
5094 	offset = BWN_PHY_N(offset);
5095 
5096 	for (i = 0; i < 15; i++, offset++)
5097 		BWN_PHY_WRITE(mac, offset, filter[i]);
5098 }
5099 
5100 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
5101 static void bwn_nphy_ext_pa_set_tx_dig_filters(struct bwn_mac *mac)
5102 {
5103 	bwn_nphy_pa_set_tx_dig_filter(mac, 0x2C5,
5104 				      tbl_tx_filter_coef_rev4[2]);
5105 }
5106 
5107 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
5108 static void bwn_nphy_int_pa_set_tx_dig_filters(struct bwn_mac *mac)
5109 {
5110 	/* BWN_NPHY_TXF_20CO_S0A1, BWN_NPHY_TXF_40CO_S0A1, unknown */
5111 	static const uint16_t offset[] = { 0x186, 0x195, 0x2C5 };
5112 	static const int16_t dig_filter_phy_rev16[] = {
5113 		-375, 136, -407, 208, -1527,
5114 		956, 93, 186, 93, 230,
5115 		-44, 230, 201, -191, 201,
5116 	};
5117 	int i;
5118 
5119 	for (i = 0; i < 3; i++)
5120 		bwn_nphy_pa_set_tx_dig_filter(mac, offset[i],
5121 					      tbl_tx_filter_coef_rev4[i]);
5122 
5123 	/* Verified with BCM43227 and BCM43228 */
5124 	if (mac->mac_phy.rev == 16)
5125 		bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, dig_filter_phy_rev16);
5126 
5127 	/* Verified with BCM43131 and BCM43217 */
5128 	if (mac->mac_phy.rev == 17) {
5129 		bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, dig_filter_phy_rev16);
5130 		bwn_nphy_pa_set_tx_dig_filter(mac, 0x195,
5131 					      tbl_tx_filter_coef_rev4[1]);
5132 	}
5133 
5134 	if (bwn_is_40mhz(mac)) {
5135 		bwn_nphy_pa_set_tx_dig_filter(mac, 0x186,
5136 					      tbl_tx_filter_coef_rev4[3]);
5137 	} else {
5138 		if (bwn_current_band(mac) == BWN_BAND_5G)
5139 			bwn_nphy_pa_set_tx_dig_filter(mac, 0x186,
5140 						      tbl_tx_filter_coef_rev4[5]);
5141 		if (bwn_get_chan(mac) == 14)
5142 			bwn_nphy_pa_set_tx_dig_filter(mac, 0x186,
5143 						      tbl_tx_filter_coef_rev4[6]);
5144 	}
5145 }
5146 
5147 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
5148 static struct bwn_nphy_txgains bwn_nphy_get_tx_gains(struct bwn_mac *mac)
5149 {
5150 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
5151 
5152 	uint16_t curr_gain[2];
5153 	struct bwn_nphy_txgains target;
5154 	const uint32_t *table = NULL;
5155 
5156 	if (!nphy->txpwrctrl) {
5157 		int i;
5158 
5159 		if (nphy->hang_avoid)
5160 			bwn_nphy_stay_in_carrier_search(mac, true);
5161 		bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, curr_gain);
5162 		if (nphy->hang_avoid)
5163 			bwn_nphy_stay_in_carrier_search(mac, false);
5164 
5165 		for (i = 0; i < 2; ++i) {
5166 			if (mac->mac_phy.rev >= 7) {
5167 				target.ipa[i] = curr_gain[i] & 0x0007;
5168 				target.pad[i] = (curr_gain[i] & 0x00F8) >> 3;
5169 				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
5170 				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
5171 				target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15;
5172 			} else if (mac->mac_phy.rev >= 3) {
5173 				target.ipa[i] = curr_gain[i] & 0x000F;
5174 				target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
5175 				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
5176 				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
5177 			} else {
5178 				target.ipa[i] = curr_gain[i] & 0x0003;
5179 				target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
5180 				target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
5181 				target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
5182 			}
5183 		}
5184 	} else {
5185 		int i;
5186 		uint16_t index[2];
5187 		index[0] = (BWN_PHY_READ(mac, BWN_NPHY_C1_TXPCTL_STAT) &
5188 			BWN_NPHY_TXPCTL_STAT_BIDX) >>
5189 			BWN_NPHY_TXPCTL_STAT_BIDX_SHIFT;
5190 		index[1] = (BWN_PHY_READ(mac, BWN_NPHY_C2_TXPCTL_STAT) &
5191 			BWN_NPHY_TXPCTL_STAT_BIDX) >>
5192 			BWN_NPHY_TXPCTL_STAT_BIDX_SHIFT;
5193 
5194 		for (i = 0; i < 2; ++i) {
5195 			table = bwn_nphy_get_tx_gain_table(mac);
5196 			if (!table)
5197 				break;
5198 
5199 			if (mac->mac_phy.rev >= 7) {
5200 				target.ipa[i] = (table[index[i]] >> 16) & 0x7;
5201 				target.pad[i] = (table[index[i]] >> 19) & 0x1F;
5202 				target.pga[i] = (table[index[i]] >> 24) & 0xF;
5203 				target.txgm[i] = (table[index[i]] >> 28) & 0x7;
5204 				target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1;
5205 			} else if (mac->mac_phy.rev >= 3) {
5206 				target.ipa[i] = (table[index[i]] >> 16) & 0xF;
5207 				target.pad[i] = (table[index[i]] >> 20) & 0xF;
5208 				target.pga[i] = (table[index[i]] >> 24) & 0xF;
5209 				target.txgm[i] = (table[index[i]] >> 28) & 0xF;
5210 			} else {
5211 				target.ipa[i] = (table[index[i]] >> 16) & 0x3;
5212 				target.pad[i] = (table[index[i]] >> 18) & 0x3;
5213 				target.pga[i] = (table[index[i]] >> 20) & 0x7;
5214 				target.txgm[i] = (table[index[i]] >> 23) & 0x7;
5215 			}
5216 		}
5217 	}
5218 
5219 	return target;
5220 }
5221 
5222 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
5223 static void bwn_nphy_tx_cal_phy_cleanup(struct bwn_mac *mac)
5224 {
5225 	uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs;
5226 
5227 	if (mac->mac_phy.rev >= 3) {
5228 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, regs[0]);
5229 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, regs[1]);
5230 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, regs[2]);
5231 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[3]);
5232 		BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, regs[4]);
5233 		bwn_ntab_write(mac, BWN_NTAB16(8, 3), regs[5]);
5234 		bwn_ntab_write(mac, BWN_NTAB16(8, 19), regs[6]);
5235 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[7]);
5236 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[8]);
5237 		BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN0, regs[9]);
5238 		BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN1, regs[10]);
5239 		bwn_nphy_reset_cca(mac);
5240 	} else {
5241 		BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
5242 		BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
5243 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[2]);
5244 		bwn_ntab_write(mac, BWN_NTAB16(8, 2), regs[3]);
5245 		bwn_ntab_write(mac, BWN_NTAB16(8, 18), regs[4]);
5246 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[5]);
5247 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[6]);
5248 	}
5249 }
5250 
5251 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
5252 static void bwn_nphy_tx_cal_phy_setup(struct bwn_mac *mac)
5253 {
5254 	struct bwn_phy *phy = &mac->mac_phy;
5255 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
5256 	uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs;
5257 	uint16_t tmp;
5258 
5259 	regs[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1);
5260 	regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2);
5261 	if (mac->mac_phy.rev >= 3) {
5262 		BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
5263 		BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
5264 
5265 		tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1);
5266 		regs[2] = tmp;
5267 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, tmp | 0x0600);
5268 
5269 		tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER);
5270 		regs[3] = tmp;
5271 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp | 0x0600);
5272 
5273 		regs[4] = BWN_PHY_READ(mac, BWN_NPHY_BBCFG);
5274 		BWN_PHY_MASK(mac, BWN_NPHY_BBCFG,
5275 			     ~BWN_NPHY_BBCFG_RSTRX & 0xFFFF);
5276 
5277 		tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 3));
5278 		regs[5] = tmp;
5279 		bwn_ntab_write(mac, BWN_NTAB16(8, 3), 0);
5280 
5281 		tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 19));
5282 		regs[6] = tmp;
5283 		bwn_ntab_write(mac, BWN_NTAB16(8, 19), 0);
5284 		regs[7] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1);
5285 		regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2);
5286 
5287 		if (!nphy->use_int_tx_iq_lo_cal)
5288 			bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA,
5289 						      1, 3);
5290 		else
5291 			bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA,
5292 						      0, 3);
5293 		bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 2, 1);
5294 		bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 8, 2);
5295 
5296 		regs[9] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN0);
5297 		regs[10] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN1);
5298 		BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x0001);
5299 		BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x0001);
5300 
5301 		tmp = bwn_nphy_read_lpf_ctl(mac, 0);
5302 		if (phy->rev >= 19)
5303 			bwn_nphy_rf_ctl_override_rev19(mac, 0x80, tmp, 0, false,
5304 						       1);
5305 		else if (phy->rev >= 7)
5306 			bwn_nphy_rf_ctl_override_rev7(mac, 0x80, tmp, 0, false,
5307 						      1);
5308 
5309 		if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) {
5310 			if (phy->rev >= 19) {
5311 				bwn_nphy_rf_ctl_override_rev19(mac, 0x8, 0, 0x3,
5312 							       false, 0);
5313 			} else if (phy->rev >= 8) {
5314 				bwn_nphy_rf_ctl_override_rev7(mac, 0x8, 0, 0x3,
5315 							      false, 0);
5316 			} else if (phy->rev == 7) {
5317 				BWN_RF_SETMASK(mac, R2057_OVR_REG0, 1 << 4, 1 << 4);
5318 				if (bwn_current_band(mac) == BWN_BAND_2G) {
5319 					BWN_RF_SETMASK(mac, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0);
5320 					BWN_RF_SETMASK(mac, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0);
5321 				} else {
5322 					BWN_RF_SETMASK(mac, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0);
5323 					BWN_RF_SETMASK(mac, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0);
5324 				}
5325 			}
5326 		}
5327 	} else {
5328 		BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
5329 		BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
5330 		tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER);
5331 		regs[2] = tmp;
5332 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp | 0x3000);
5333 		tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 2));
5334 		regs[3] = tmp;
5335 		tmp |= 0x2000;
5336 		bwn_ntab_write(mac, BWN_NTAB16(8, 2), tmp);
5337 		tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 18));
5338 		regs[4] = tmp;
5339 		tmp |= 0x2000;
5340 		bwn_ntab_write(mac, BWN_NTAB16(8, 18), tmp);
5341 		regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1);
5342 		regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2);
5343 		if (bwn_current_band(mac) == BWN_BAND_5G)
5344 			tmp = 0x0180;
5345 		else
5346 			tmp = 0x0120;
5347 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, tmp);
5348 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, tmp);
5349 	}
5350 }
5351 
5352 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
5353 static void bwn_nphy_save_cal(struct bwn_mac *mac)
5354 {
5355 	struct bwn_phy *phy = &mac->mac_phy;
5356 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
5357 
5358 	struct bwn_phy_n_iq_comp *rxcal_coeffs = NULL;
5359 	uint16_t *txcal_radio_regs = NULL;
5360 	struct bwn_chanspec *iqcal_chanspec;
5361 	uint16_t *table = NULL;
5362 
5363 	if (nphy->hang_avoid)
5364 		bwn_nphy_stay_in_carrier_search(mac, 1);
5365 
5366 	if (bwn_current_band(mac) == BWN_BAND_2G) {
5367 		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
5368 		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
5369 		iqcal_chanspec = &nphy->iqcal_chanspec_2G;
5370 		table = nphy->cal_cache.txcal_coeffs_2G;
5371 	} else {
5372 		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
5373 		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
5374 		iqcal_chanspec = &nphy->iqcal_chanspec_5G;
5375 		table = nphy->cal_cache.txcal_coeffs_5G;
5376 	}
5377 
5378 	bwn_nphy_rx_iq_coeffs(mac, false, rxcal_coeffs);
5379 	/* TODO use some definitions */
5380 	if (phy->rev >= 19) {
5381 		/* TODO */
5382 	} else if (phy->rev >= 7) {
5383 		txcal_radio_regs[0] = BWN_RF_READ(mac,
5384 						     R2057_TX0_LOFT_FINE_I);
5385 		txcal_radio_regs[1] = BWN_RF_READ(mac,
5386 						     R2057_TX0_LOFT_FINE_Q);
5387 		txcal_radio_regs[4] = BWN_RF_READ(mac,
5388 						     R2057_TX0_LOFT_COARSE_I);
5389 		txcal_radio_regs[5] = BWN_RF_READ(mac,
5390 						     R2057_TX0_LOFT_COARSE_Q);
5391 		txcal_radio_regs[2] = BWN_RF_READ(mac,
5392 						     R2057_TX1_LOFT_FINE_I);
5393 		txcal_radio_regs[3] = BWN_RF_READ(mac,
5394 						     R2057_TX1_LOFT_FINE_Q);
5395 		txcal_radio_regs[6] = BWN_RF_READ(mac,
5396 						     R2057_TX1_LOFT_COARSE_I);
5397 		txcal_radio_regs[7] = BWN_RF_READ(mac,
5398 						     R2057_TX1_LOFT_COARSE_Q);
5399 	} else if (phy->rev >= 3) {
5400 		txcal_radio_regs[0] = BWN_RF_READ(mac, 0x2021);
5401 		txcal_radio_regs[1] = BWN_RF_READ(mac, 0x2022);
5402 		txcal_radio_regs[2] = BWN_RF_READ(mac, 0x3021);
5403 		txcal_radio_regs[3] = BWN_RF_READ(mac, 0x3022);
5404 		txcal_radio_regs[4] = BWN_RF_READ(mac, 0x2023);
5405 		txcal_radio_regs[5] = BWN_RF_READ(mac, 0x2024);
5406 		txcal_radio_regs[6] = BWN_RF_READ(mac, 0x3023);
5407 		txcal_radio_regs[7] = BWN_RF_READ(mac, 0x3024);
5408 	} else {
5409 		txcal_radio_regs[0] = BWN_RF_READ(mac, 0x8B);
5410 		txcal_radio_regs[1] = BWN_RF_READ(mac, 0xBA);
5411 		txcal_radio_regs[2] = BWN_RF_READ(mac, 0x8D);
5412 		txcal_radio_regs[3] = BWN_RF_READ(mac, 0xBC);
5413 	}
5414 	iqcal_chanspec->center_freq = bwn_get_centre_freq(mac);
5415 	iqcal_chanspec->channel_type = bwn_get_chan_type(mac, NULL);
5416 	bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 8, table);
5417 
5418 	if (nphy->hang_avoid)
5419 		bwn_nphy_stay_in_carrier_search(mac, 0);
5420 }
5421 
5422 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
5423 static void bwn_nphy_restore_cal(struct bwn_mac *mac)
5424 {
5425 	struct bwn_phy *phy = &mac->mac_phy;
5426 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
5427 
5428 	uint16_t coef[4];
5429 	uint16_t *loft = NULL;
5430 	uint16_t *table = NULL;
5431 
5432 	int i;
5433 	uint16_t *txcal_radio_regs = NULL;
5434 	struct bwn_phy_n_iq_comp *rxcal_coeffs = NULL;
5435 
5436 	if (bwn_current_band(mac) == BWN_BAND_2G) {
5437 		if (!nphy->iqcal_chanspec_2G.center_freq)
5438 			return;
5439 		table = nphy->cal_cache.txcal_coeffs_2G;
5440 		loft = &nphy->cal_cache.txcal_coeffs_2G[5];
5441 	} else {
5442 		if (!nphy->iqcal_chanspec_5G.center_freq)
5443 			return;
5444 		table = nphy->cal_cache.txcal_coeffs_5G;
5445 		loft = &nphy->cal_cache.txcal_coeffs_5G[5];
5446 	}
5447 
5448 	bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 80), 4, table);
5449 
5450 	for (i = 0; i < 4; i++) {
5451 		if (mac->mac_phy.rev >= 3)
5452 			table[i] = coef[i];
5453 		else
5454 			coef[i] = 0;
5455 	}
5456 
5457 	bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, coef);
5458 	bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, loft);
5459 	bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, loft);
5460 
5461 	if (mac->mac_phy.rev < 2)
5462 		bwn_nphy_tx_iq_workaround(mac);
5463 
5464 	if (bwn_current_band(mac) == BWN_BAND_2G) {
5465 		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
5466 		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
5467 	} else {
5468 		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
5469 		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
5470 	}
5471 
5472 	/* TODO use some definitions */
5473 	if (phy->rev >= 19) {
5474 		/* TODO */
5475 	} else if (phy->rev >= 7) {
5476 		BWN_RF_WRITE(mac, R2057_TX0_LOFT_FINE_I,
5477 				txcal_radio_regs[0]);
5478 		BWN_RF_WRITE(mac, R2057_TX0_LOFT_FINE_Q,
5479 				txcal_radio_regs[1]);
5480 		BWN_RF_WRITE(mac, R2057_TX0_LOFT_COARSE_I,
5481 				txcal_radio_regs[4]);
5482 		BWN_RF_WRITE(mac, R2057_TX0_LOFT_COARSE_Q,
5483 				txcal_radio_regs[5]);
5484 		BWN_RF_WRITE(mac, R2057_TX1_LOFT_FINE_I,
5485 				txcal_radio_regs[2]);
5486 		BWN_RF_WRITE(mac, R2057_TX1_LOFT_FINE_Q,
5487 				txcal_radio_regs[3]);
5488 		BWN_RF_WRITE(mac, R2057_TX1_LOFT_COARSE_I,
5489 				txcal_radio_regs[6]);
5490 		BWN_RF_WRITE(mac, R2057_TX1_LOFT_COARSE_Q,
5491 				txcal_radio_regs[7]);
5492 	} else if (phy->rev >= 3) {
5493 		BWN_RF_WRITE(mac, 0x2021, txcal_radio_regs[0]);
5494 		BWN_RF_WRITE(mac, 0x2022, txcal_radio_regs[1]);
5495 		BWN_RF_WRITE(mac, 0x3021, txcal_radio_regs[2]);
5496 		BWN_RF_WRITE(mac, 0x3022, txcal_radio_regs[3]);
5497 		BWN_RF_WRITE(mac, 0x2023, txcal_radio_regs[4]);
5498 		BWN_RF_WRITE(mac, 0x2024, txcal_radio_regs[5]);
5499 		BWN_RF_WRITE(mac, 0x3023, txcal_radio_regs[6]);
5500 		BWN_RF_WRITE(mac, 0x3024, txcal_radio_regs[7]);
5501 	} else {
5502 		BWN_RF_WRITE(mac, 0x8B, txcal_radio_regs[0]);
5503 		BWN_RF_WRITE(mac, 0xBA, txcal_radio_regs[1]);
5504 		BWN_RF_WRITE(mac, 0x8D, txcal_radio_regs[2]);
5505 		BWN_RF_WRITE(mac, 0xBC, txcal_radio_regs[3]);
5506 	}
5507 	bwn_nphy_rx_iq_coeffs(mac, true, rxcal_coeffs);
5508 }
5509 
5510 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
5511 static int bwn_nphy_cal_tx_iq_lo(struct bwn_mac *mac,
5512 				struct bwn_nphy_txgains target,
5513 				bool full, bool mphase)
5514 {
5515 	struct bwn_phy *phy = &mac->mac_phy;
5516 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
5517 	int i;
5518 	int error = 0;
5519 	int freq;
5520 	bool avoid = false;
5521 	uint8_t length;
5522 	uint16_t tmp, core, type, count, max, numb, last = 0, cmd;
5523 	const uint16_t *table;
5524 	bool phy6or5x;
5525 
5526 	uint16_t buffer[11];
5527 	uint16_t diq_start = 0;
5528 	uint16_t save[2];
5529 	uint16_t gain[2];
5530 	struct bwn_nphy_iqcal_params params[2];
5531 	bool updated[2] = { };
5532 
5533 	bwn_nphy_stay_in_carrier_search(mac, true);
5534 
5535 	if (mac->mac_phy.rev >= 4) {
5536 		avoid = nphy->hang_avoid;
5537 		nphy->hang_avoid = false;
5538 	}
5539 
5540 	bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, save);
5541 
5542 	for (i = 0; i < 2; i++) {
5543 		bwn_nphy_iq_cal_gain_params(mac, i, target, &params[i]);
5544 		gain[i] = params[i].cal_gain;
5545 	}
5546 
5547 	bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain);
5548 
5549 	bwn_nphy_tx_cal_radio_setup(mac);
5550 	bwn_nphy_tx_cal_phy_setup(mac);
5551 
5552 	phy6or5x = mac->mac_phy.rev >= 6 ||
5553 		(mac->mac_phy.rev == 5 && nphy->ipa2g_on &&
5554 		bwn_current_band(mac) == BWN_BAND_2G);
5555 	if (phy6or5x) {
5556 		if (bwn_is_40mhz(mac)) {
5557 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 0), 18,
5558 					tbl_tx_iqlo_cal_loft_ladder_40);
5559 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 32), 18,
5560 					tbl_tx_iqlo_cal_iqimb_ladder_40);
5561 		} else {
5562 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 0), 18,
5563 					tbl_tx_iqlo_cal_loft_ladder_20);
5564 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 32), 18,
5565 					tbl_tx_iqlo_cal_iqimb_ladder_20);
5566 		}
5567 	}
5568 
5569 	if (phy->rev >= 19) {
5570 		/* TODO */
5571 	} else if (phy->rev >= 7) {
5572 		BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8AD9);
5573 	} else {
5574 		BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
5575 	}
5576 
5577 	if (!bwn_is_40mhz(mac))
5578 		freq = 2500;
5579 	else
5580 		freq = 5000;
5581 
5582 	if (nphy->mphase_cal_phase_id > 2)
5583 		bwn_nphy_run_samples(mac, (bwn_is_40mhz(mac) ? 40 : 20) * 8,
5584 				     0xFFFF, 0, true, false, false);
5585 	else
5586 		error = bwn_nphy_tx_tone(mac, freq, 250, true, false, false);
5587 
5588 	if (error == 0) {
5589 		if (nphy->mphase_cal_phase_id > 2) {
5590 			table = nphy->mphase_txcal_bestcoeffs;
5591 			length = 11;
5592 			if (mac->mac_phy.rev < 3)
5593 				length -= 2;
5594 		} else {
5595 			if (!full && nphy->txiqlocal_coeffsvalid) {
5596 				table = nphy->txiqlocal_bestc;
5597 				length = 11;
5598 				if (mac->mac_phy.rev < 3)
5599 					length -= 2;
5600 			} else {
5601 				full = true;
5602 				if (mac->mac_phy.rev >= 3) {
5603 					table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
5604 					length = BWN_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
5605 				} else {
5606 					table = tbl_tx_iqlo_cal_startcoefs;
5607 					length = BWN_NTAB_TX_IQLO_CAL_STARTCOEFS;
5608 				}
5609 			}
5610 		}
5611 
5612 		bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 64), length, table);
5613 
5614 		if (full) {
5615 			if (mac->mac_phy.rev >= 3)
5616 				max = BWN_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
5617 			else
5618 				max = BWN_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
5619 		} else {
5620 			if (mac->mac_phy.rev >= 3)
5621 				max = BWN_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
5622 			else
5623 				max = BWN_NTAB_TX_IQLO_CAL_CMDS_RECAL;
5624 		}
5625 
5626 		if (mphase) {
5627 			count = nphy->mphase_txcal_cmdidx;
5628 			numb = min(max,
5629 				(uint16_t)(count + nphy->mphase_txcal_numcmds));
5630 		} else {
5631 			count = 0;
5632 			numb = max;
5633 		}
5634 
5635 		for (; count < numb; count++) {
5636 			if (full) {
5637 				if (mac->mac_phy.rev >= 3)
5638 					cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
5639 				else
5640 					cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
5641 			} else {
5642 				if (mac->mac_phy.rev >= 3)
5643 					cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
5644 				else
5645 					cmd = tbl_tx_iqlo_cal_cmds_recal[count];
5646 			}
5647 
5648 			core = (cmd & 0x3000) >> 12;
5649 			type = (cmd & 0x0F00) >> 8;
5650 
5651 			if (phy6or5x && updated[core] == 0) {
5652 				bwn_nphy_update_tx_cal_ladder(mac, core);
5653 				updated[core] = true;
5654 			}
5655 
5656 			tmp = (params[core].ncorr[type] << 8) | 0x66;
5657 			BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDNNUM, tmp);
5658 
5659 			if (type == 1 || type == 3 || type == 4) {
5660 				buffer[0] = bwn_ntab_read(mac,
5661 						BWN_NTAB16(15, 69 + core));
5662 				diq_start = buffer[0];
5663 				buffer[0] = 0;
5664 				bwn_ntab_write(mac, BWN_NTAB16(15, 69 + core),
5665 						0);
5666 			}
5667 
5668 			BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMD, cmd);
5669 			for (i = 0; i < 2000; i++) {
5670 				tmp = BWN_PHY_READ(mac, BWN_NPHY_IQLOCAL_CMD);
5671 				if (tmp & 0xC000)
5672 					break;
5673 				DELAY(10);
5674 			}
5675 
5676 			bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length,
5677 						buffer);
5678 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 64), length,
5679 						buffer);
5680 
5681 			if (type == 1 || type == 3 || type == 4)
5682 				buffer[0] = diq_start;
5683 		}
5684 
5685 		if (mphase)
5686 			nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
5687 
5688 		last = (mac->mac_phy.rev < 3) ? 6 : 7;
5689 
5690 		if (!mphase || nphy->mphase_cal_phase_id == last) {
5691 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 96), 4, buffer);
5692 			bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 4, buffer);
5693 			if (mac->mac_phy.rev < 3) {
5694 				buffer[0] = 0;
5695 				buffer[1] = 0;
5696 				buffer[2] = 0;
5697 				buffer[3] = 0;
5698 			}
5699 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4,
5700 						buffer);
5701 			bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 101), 2,
5702 						buffer);
5703 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2,
5704 						buffer);
5705 			bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2,
5706 						buffer);
5707 			length = 11;
5708 			if (mac->mac_phy.rev < 3)
5709 				length -= 2;
5710 			bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length,
5711 						nphy->txiqlocal_bestc);
5712 			nphy->txiqlocal_coeffsvalid = true;
5713 			nphy->txiqlocal_chanspec.center_freq =
5714 						bwn_get_centre_freq(mac);
5715 			nphy->txiqlocal_chanspec.channel_type = bwn_get_chan_type(mac, NULL);
5716 		} else {
5717 			length = 11;
5718 			if (mac->mac_phy.rev < 3)
5719 				length -= 2;
5720 			bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length,
5721 						nphy->mphase_txcal_bestcoeffs);
5722 		}
5723 
5724 		bwn_nphy_stop_playback(mac);
5725 		BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0);
5726 	}
5727 
5728 	bwn_nphy_tx_cal_phy_cleanup(mac);
5729 	bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, save);
5730 
5731 	if (mac->mac_phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
5732 		bwn_nphy_tx_iq_workaround(mac);
5733 
5734 	if (mac->mac_phy.rev >= 4)
5735 		nphy->hang_avoid = avoid;
5736 
5737 	bwn_nphy_stay_in_carrier_search(mac, false);
5738 
5739 	return error;
5740 }
5741 
5742 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
5743 static void bwn_nphy_reapply_tx_cal_coeffs(struct bwn_mac *mac)
5744 {
5745 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
5746 	uint8_t i;
5747 	uint16_t buffer[7];
5748 	bool equal = true;
5749 
5750 	if (!nphy->txiqlocal_coeffsvalid ||
5751 	    nphy->txiqlocal_chanspec.center_freq != bwn_get_centre_freq(mac) ||
5752 	    nphy->txiqlocal_chanspec.channel_type != bwn_get_chan_type(mac, NULL))
5753 		return;
5754 
5755 	bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 7, buffer);
5756 	for (i = 0; i < 4; i++) {
5757 		if (buffer[i] != nphy->txiqlocal_bestc[i]) {
5758 			equal = false;
5759 			break;
5760 		}
5761 	}
5762 
5763 	if (!equal) {
5764 		bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 80), 4,
5765 					nphy->txiqlocal_bestc);
5766 		for (i = 0; i < 4; i++)
5767 			buffer[i] = 0;
5768 		bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4,
5769 					buffer);
5770 		bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2,
5771 					&nphy->txiqlocal_bestc[5]);
5772 		bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2,
5773 					&nphy->txiqlocal_bestc[5]);
5774 	}
5775 }
5776 
5777 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
5778 static int bwn_nphy_rev2_cal_rx_iq(struct bwn_mac *mac,
5779 			struct bwn_nphy_txgains target, uint8_t type, bool debug)
5780 {
5781 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
5782 	int i, j, index;
5783 	uint8_t rfctl[2];
5784 	uint8_t afectl_core;
5785 	uint16_t tmp[6];
5786 	uint16_t cur_hpf1, cur_hpf2, cur_lna;
5787 	uint32_t real, imag;
5788 	bwn_band_t band;
5789 
5790 	uint8_t use;
5791 	uint16_t cur_hpf;
5792 	uint16_t lna[3] = { 3, 3, 1 };
5793 	uint16_t hpf1[3] = { 7, 2, 0 };
5794 	uint16_t hpf2[3] = { 2, 0, 0 };
5795 	uint32_t power[3] = { };
5796 	uint16_t gain_save[2];
5797 	uint16_t cal_gain[2];
5798 	struct bwn_nphy_iqcal_params cal_params[2];
5799 	struct bwn_nphy_iq_est est;
5800 	int ret = 0;
5801 	bool playtone = true;
5802 	int desired = 13;
5803 
5804 	bwn_nphy_stay_in_carrier_search(mac, 1);
5805 
5806 	if (mac->mac_phy.rev < 2)
5807 		bwn_nphy_reapply_tx_cal_coeffs(mac);
5808 	bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain_save);
5809 	for (i = 0; i < 2; i++) {
5810 		bwn_nphy_iq_cal_gain_params(mac, i, target, &cal_params[i]);
5811 		cal_gain[i] = cal_params[i].cal_gain;
5812 	}
5813 	bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, cal_gain);
5814 
5815 	for (i = 0; i < 2; i++) {
5816 		if (i == 0) {
5817 			rfctl[0] = BWN_NPHY_RFCTL_INTC1;
5818 			rfctl[1] = BWN_NPHY_RFCTL_INTC2;
5819 			afectl_core = BWN_NPHY_AFECTL_C1;
5820 		} else {
5821 			rfctl[0] = BWN_NPHY_RFCTL_INTC2;
5822 			rfctl[1] = BWN_NPHY_RFCTL_INTC1;
5823 			afectl_core = BWN_NPHY_AFECTL_C2;
5824 		}
5825 
5826 		tmp[1] = BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA);
5827 		tmp[2] = BWN_PHY_READ(mac, afectl_core);
5828 		tmp[3] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER);
5829 		tmp[4] = BWN_PHY_READ(mac, rfctl[0]);
5830 		tmp[5] = BWN_PHY_READ(mac, rfctl[1]);
5831 
5832 		BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA,
5833 				~BWN_NPHY_RFSEQCA_RXDIS & 0xFFFF,
5834 				((1 - i) << BWN_NPHY_RFSEQCA_RXDIS_SHIFT));
5835 		BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXEN,
5836 				(1 - i));
5837 		BWN_PHY_SET(mac, afectl_core, 0x0006);
5838 		BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0006);
5839 
5840 		band = bwn_current_band(mac);
5841 
5842 		if (nphy->rxcalparams & 0xFF000000) {
5843 			if (band == BWN_BAND_5G)
5844 				BWN_PHY_WRITE(mac, rfctl[0], 0x140);
5845 			else
5846 				BWN_PHY_WRITE(mac, rfctl[0], 0x110);
5847 		} else {
5848 			if (band == BWN_BAND_5G)
5849 				BWN_PHY_WRITE(mac, rfctl[0], 0x180);
5850 			else
5851 				BWN_PHY_WRITE(mac, rfctl[0], 0x120);
5852 		}
5853 
5854 		if (band == BWN_BAND_5G)
5855 			BWN_PHY_WRITE(mac, rfctl[1], 0x148);
5856 		else
5857 			BWN_PHY_WRITE(mac, rfctl[1], 0x114);
5858 
5859 		if (nphy->rxcalparams & 0x10000) {
5860 			BWN_RF_SETMASK(mac, B2055_C1_GENSPARE2, 0xFC,
5861 					(i + 1));
5862 			BWN_RF_SETMASK(mac, B2055_C2_GENSPARE2, 0xFC,
5863 					(2 - i));
5864 		}
5865 
5866 		for (j = 0; j < 4; j++) {
5867 			if (j < 3) {
5868 				cur_lna = lna[j];
5869 				cur_hpf1 = hpf1[j];
5870 				cur_hpf2 = hpf2[j];
5871 			} else {
5872 				if (power[1] > 10000) {
5873 					use = 1;
5874 					cur_hpf = cur_hpf1;
5875 					index = 2;
5876 				} else {
5877 					if (power[0] > 10000) {
5878 						use = 1;
5879 						cur_hpf = cur_hpf1;
5880 						index = 1;
5881 					} else {
5882 						index = 0;
5883 						use = 2;
5884 						cur_hpf = cur_hpf2;
5885 					}
5886 				}
5887 				cur_lna = lna[index];
5888 				cur_hpf1 = hpf1[index];
5889 				cur_hpf2 = hpf2[index];
5890 				cur_hpf += desired - bwn_hweight32(power[index]);
5891 				cur_hpf = bwn_clamp_val(cur_hpf, 0, 10);
5892 				if (use == 1)
5893 					cur_hpf1 = cur_hpf;
5894 				else
5895 					cur_hpf2 = cur_hpf;
5896 			}
5897 
5898 			tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
5899 					(cur_lna << 2));
5900 			bwn_nphy_rf_ctl_override(mac, 0x400, tmp[0], 3,
5901 									false);
5902 			bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX);
5903 			bwn_nphy_stop_playback(mac);
5904 
5905 			if (playtone) {
5906 				ret = bwn_nphy_tx_tone(mac, 4000,
5907 						(nphy->rxcalparams & 0xFFFF),
5908 						false, false, true);
5909 				playtone = false;
5910 			} else {
5911 				bwn_nphy_run_samples(mac, 160, 0xFFFF, 0, false,
5912 						     false, true);
5913 			}
5914 
5915 			if (ret == 0) {
5916 				if (j < 3) {
5917 					bwn_nphy_rx_iq_est(mac, &est, 1024, 32,
5918 									false);
5919 					if (i == 0) {
5920 						real = est.i0_pwr;
5921 						imag = est.q0_pwr;
5922 					} else {
5923 						real = est.i1_pwr;
5924 						imag = est.q1_pwr;
5925 					}
5926 					power[i] = ((real + imag) / 1024) + 1;
5927 				} else {
5928 					bwn_nphy_calc_rx_iq_comp(mac, 1 << i);
5929 				}
5930 				bwn_nphy_stop_playback(mac);
5931 			}
5932 
5933 			if (ret != 0)
5934 				break;
5935 		}
5936 
5937 		BWN_RF_MASK(mac, B2055_C1_GENSPARE2, 0xFC);
5938 		BWN_RF_MASK(mac, B2055_C2_GENSPARE2, 0xFC);
5939 		BWN_PHY_WRITE(mac, rfctl[1], tmp[5]);
5940 		BWN_PHY_WRITE(mac, rfctl[0], tmp[4]);
5941 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp[3]);
5942 		BWN_PHY_WRITE(mac, afectl_core, tmp[2]);
5943 		BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQCA, tmp[1]);
5944 
5945 		if (ret != 0)
5946 			break;
5947 	}
5948 
5949 	bwn_nphy_rf_ctl_override(mac, 0x400, 0, 3, true);
5950 	bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX);
5951 	bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain_save);
5952 
5953 	bwn_nphy_stay_in_carrier_search(mac, 0);
5954 
5955 	return ret;
5956 }
5957 
5958 static int bwn_nphy_rev3_cal_rx_iq(struct bwn_mac *mac,
5959 			struct bwn_nphy_txgains target, uint8_t type, bool debug)
5960 {
5961 	return -1;
5962 }
5963 
5964 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
5965 static int bwn_nphy_cal_rx_iq(struct bwn_mac *mac,
5966 			struct bwn_nphy_txgains target, uint8_t type, bool debug)
5967 {
5968 	if (mac->mac_phy.rev >= 7)
5969 		type = 0;
5970 
5971 	if (mac->mac_phy.rev >= 3)
5972 		return bwn_nphy_rev3_cal_rx_iq(mac, target, type, debug);
5973 	else
5974 		return bwn_nphy_rev2_cal_rx_iq(mac, target, type, debug);
5975 }
5976 
5977 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
5978 static void bwn_nphy_set_rx_core_state(struct bwn_mac *mac, uint8_t mask)
5979 {
5980 	struct bwn_phy *phy = &mac->mac_phy;
5981 	struct bwn_phy_n *nphy = phy->phy_n;
5982 	/* uint16_t buf[16]; it's rev3+ */
5983 
5984 	nphy->phyrxchain = mask;
5985 
5986 	if (0 /* FIXME clk */)
5987 		return;
5988 
5989 	bwn_mac_suspend(mac);
5990 
5991 	if (nphy->hang_avoid)
5992 		bwn_nphy_stay_in_carrier_search(mac, true);
5993 
5994 	BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_RXEN,
5995 			(mask & 0x3) << BWN_NPHY_RFSEQCA_RXEN_SHIFT);
5996 
5997 	if ((mask & 0x3) != 0x3) {
5998 		BWN_PHY_WRITE(mac, BWN_NPHY_HPANT_SWTHRES, 1);
5999 		if (mac->mac_phy.rev >= 3) {
6000 			/* TODO */
6001 		}
6002 	} else {
6003 		BWN_PHY_WRITE(mac, BWN_NPHY_HPANT_SWTHRES, 0x1E);
6004 		if (mac->mac_phy.rev >= 3) {
6005 			/* TODO */
6006 		}
6007 	}
6008 
6009 	bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX);
6010 
6011 	if (nphy->hang_avoid)
6012 		bwn_nphy_stay_in_carrier_search(mac, false);
6013 
6014 	bwn_mac_enable(mac);
6015 }
6016 
6017 bwn_txpwr_result_t
6018 bwn_nphy_op_recalc_txpower(struct bwn_mac *mac, bool ignore_tssi)
6019 {
6020 	struct bwn_phy *phy = &mac->mac_phy;
6021 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
6022 	struct ieee80211_channel *channel = bwn_get_channel(mac);
6023 	struct bwn_softc *sc = mac->mac_sc;
6024 	struct bwn_ppr *ppr = &nphy->tx_pwr_max_ppr;
6025 	uint8_t max; /* qdBm */
6026 	bool tx_pwr_state;
6027 
6028 	if (nphy->tx_pwr_last_recalc_freq == bwn_get_centre_freq(mac) &&
6029 	    nphy->tx_pwr_last_recalc_limit == phy->txpower)
6030 		return BWN_TXPWR_RES_DONE;
6031 
6032 	/* Make sure we have a clean PPR */
6033 	bwn_ppr_clear(mac, ppr);
6034 
6035 	/* HW limitations */
6036 	bwn_ppr_load_max_from_sprom(mac, ppr, BWN_PHY_BAND_2G);
6037 	/* XXX TODO: other bands? */
6038 
6039 	/* Regulatory & user settings */
6040 	max = INT_TO_Q52(bwn_get_chan_power(mac, channel));
6041 	/* uint8_t */
6042 	if (phy->txpower)
6043 		max = min(max, INT_TO_Q52(phy->txpower));
6044 	bwn_ppr_apply_max(mac, ppr, max);
6045 	DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT_POWER,
6046 	    "Calculated TX power: " Q52_FMT "\n",
6047 	     Q52_ARG(bwn_ppr_get_max(mac, ppr)));
6048 
6049 	/* TODO: Enable this once we get gains working */
6050 #if 0
6051 	/* Some extra gains */
6052 	hw_gain = 6; /* N-PHY specific */
6053 	if (bwn_current_band(mac) == BWN_BAND_2G)
6054 		hw_gain += sprom->antenna_gain.a0;
6055 	else
6056 		hw_gain += sprom->antenna_gain.a1;
6057 	bwn_ppr_add(mac, ppr, -hw_gain);
6058 #endif
6059 
6060 	/* Make sure we didn't go too low */
6061 	bwn_ppr_apply_min(mac, ppr, INT_TO_Q52(8));
6062 
6063 	/* Apply */
6064 	tx_pwr_state = nphy->txpwrctrl;
6065 	bwn_mac_suspend(mac);
6066 	bwn_nphy_tx_power_ctl_setup(mac);
6067 	if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) {
6068 		BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, BWN_MACCTL_PHY_LOCK);
6069 		BWN_READ_4(mac, BWN_MACCTL);
6070 		DELAY(1);
6071 	}
6072 	bwn_nphy_tx_power_ctrl(mac, nphy->txpwrctrl);
6073 	if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12)
6074 		BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~BWN_MACCTL_PHY_LOCK, 0);
6075 	bwn_mac_enable(mac);
6076 
6077 	nphy->tx_pwr_last_recalc_freq = bwn_get_centre_freq(mac);
6078 	nphy->tx_pwr_last_recalc_limit = phy->txpower;
6079 
6080 	return BWN_TXPWR_RES_DONE;
6081 }
6082 
6083 /**************************************************
6084  * N-PHY init
6085  **************************************************/
6086 
6087 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
6088 static void bwn_nphy_update_mimo_config(struct bwn_mac *mac, int32_t preamble)
6089 {
6090 	uint16_t mimocfg = BWN_PHY_READ(mac, BWN_NPHY_MIMOCFG);
6091 
6092 	mimocfg |= BWN_NPHY_MIMOCFG_AUTO;
6093 	if (preamble == 1)
6094 		mimocfg |= BWN_NPHY_MIMOCFG_GFMIX;
6095 	else
6096 		mimocfg &= ~BWN_NPHY_MIMOCFG_GFMIX;
6097 
6098 	BWN_PHY_WRITE(mac, BWN_NPHY_MIMOCFG, mimocfg);
6099 }
6100 
6101 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
6102 static void bwn_nphy_bphy_init(struct bwn_mac *mac)
6103 {
6104 	unsigned int i;
6105 	uint16_t val;
6106 
6107 	val = 0x1E1F;
6108 	for (i = 0; i < 16; i++) {
6109 		BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x88 + i), val);
6110 		val -= 0x202;
6111 	}
6112 	val = 0x3E3F;
6113 	for (i = 0; i < 16; i++) {
6114 		BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x98 + i), val);
6115 		val -= 0x202;
6116 	}
6117 	BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x38), 0x668);
6118 }
6119 
6120 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
6121 static void bwn_nphy_superswitch_init(struct bwn_mac *mac, bool init)
6122 {
6123 	struct bwn_softc *sc = mac->mac_sc;
6124 
6125 	if (mac->mac_phy.rev >= 7)
6126 		return;
6127 
6128 	if (mac->mac_phy.rev >= 3) {
6129 		if (!init)
6130 			return;
6131 		if (0 /* FIXME */) {
6132 			bwn_ntab_write(mac, BWN_NTAB16(9, 2), 0x211);
6133 			bwn_ntab_write(mac, BWN_NTAB16(9, 3), 0x222);
6134 			bwn_ntab_write(mac, BWN_NTAB16(9, 8), 0x144);
6135 			bwn_ntab_write(mac, BWN_NTAB16(9, 12), 0x188);
6136 		}
6137 	} else {
6138 		BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_LOOEN, 0);
6139 		BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_HIOEN, 0);
6140 
6141 		/* XXX handle bhnd bus */
6142 		if (bwn_is_bus_siba(mac)) {
6143 			siba_gpio_set(sc->sc_dev, 0xfc00);
6144 		}
6145 
6146 		BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~BWN_MACCTL_GPOUT_MASK, 0);
6147 		BWN_WRITE_SETMASK2(mac, BWN_GPIO_MASK, ~0, 0xFC00);
6148 		BWN_WRITE_SETMASK2(mac, BWN_GPIO_CONTROL, (~0xFC00 & 0xFFFF),
6149 			      0);
6150 
6151 		if (init) {
6152 			BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
6153 			BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
6154 			BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
6155 			BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
6156 		}
6157 	}
6158 }
6159 
6160 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
6161 static int bwn_phy_initn(struct bwn_mac *mac)
6162 {
6163 	struct bwn_softc *sc = mac->mac_sc;
6164 	struct bwn_phy *phy = &mac->mac_phy;
6165 	struct bwn_phy_n *nphy = phy->phy_n;
6166 	uint8_t tx_pwr_state;
6167 	struct bwn_nphy_txgains target;
6168 	uint16_t tmp;
6169 	bwn_band_t tmp2;
6170 	bool do_rssi_cal;
6171 
6172 	uint16_t clip[2];
6173 	bool do_cal = false;
6174 
6175 	if ((mac->mac_phy.rev >= 3) &&
6176 	   (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
6177 	   (bwn_current_band(mac) == BWN_BAND_2G)) {
6178 		/* XXX bhnd bus */
6179 		if (bwn_is_bus_siba(mac)) {
6180 			siba_cc_set32(sc->sc_dev, SIBA_CC_CHIPCTL, 0x40);
6181 		}
6182 	}
6183 	nphy->use_int_tx_iq_lo_cal = bwn_nphy_ipa(mac) ||
6184 		phy->rev >= 7 ||
6185 		(phy->rev >= 5 &&
6186 		 siba_sprom_get_bf2_hi(sc->sc_dev) & BWN_BFH2_INTERNDET_TXIQCAL);
6187 	nphy->deaf_count = 0;
6188 	bwn_nphy_tables_init(mac);
6189 	nphy->crsminpwr_adjusted = false;
6190 	nphy->noisevars_adjusted = false;
6191 
6192 	/* Clear all overrides */
6193 	if (mac->mac_phy.rev >= 3) {
6194 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S1, 0);
6195 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, 0);
6196 		if (phy->rev >= 7) {
6197 			BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0);
6198 			BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER4, 0);
6199 			BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER5, 0);
6200 			BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER6, 0);
6201 		}
6202 		if (phy->rev >= 19) {
6203 			/* TODO */
6204 		}
6205 
6206 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S0, 0);
6207 		BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S1, 0);
6208 	} else {
6209 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, 0);
6210 	}
6211 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, 0);
6212 	BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, 0);
6213 	if (mac->mac_phy.rev < 6) {
6214 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC3, 0);
6215 		BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC4, 0);
6216 	}
6217 	BWN_PHY_MASK(mac, BWN_NPHY_RFSEQMODE,
6218 		     ~(BWN_NPHY_RFSEQMODE_CAOVER |
6219 		       BWN_NPHY_RFSEQMODE_TROVER));
6220 	if (mac->mac_phy.rev >= 3)
6221 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, 0);
6222 	BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, 0);
6223 
6224 	if (mac->mac_phy.rev <= 2) {
6225 		tmp = (mac->mac_phy.rev == 2) ? 0x3B : 0x40;
6226 		BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3,
6227 				~BWN_NPHY_BPHY_CTL3_SCALE,
6228 				tmp << BWN_NPHY_BPHY_CTL3_SCALE_SHIFT);
6229 	}
6230 	BWN_PHY_WRITE(mac, BWN_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
6231 	BWN_PHY_WRITE(mac, BWN_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
6232 
6233 	if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SKWRKFEM_BRD ||
6234 	    (siba_get_pci_subvendor(sc->sc_dev) == PCI_VENDOR_APPLE &&
6235 	     siba_get_pci_subdevice(sc->sc_dev) == BCMA_BOARD_TYPE_BCM943224M93))
6236 		BWN_PHY_WRITE(mac, BWN_NPHY_TXREALFD, 0xA0);
6237 	else
6238 		BWN_PHY_WRITE(mac, BWN_NPHY_TXREALFD, 0xB8);
6239 	BWN_PHY_WRITE(mac, BWN_NPHY_MIMO_CRSTXEXT, 0xC8);
6240 	BWN_PHY_WRITE(mac, BWN_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
6241 	BWN_PHY_WRITE(mac, BWN_NPHY_TXRIFS_FRDEL, 0x30);
6242 
6243 	if (phy->rev < 8)
6244 		bwn_nphy_update_mimo_config(mac, nphy->preamble_override);
6245 
6246 	bwn_nphy_update_txrx_chain(mac);
6247 
6248 	if (phy->rev < 2) {
6249 		BWN_PHY_WRITE(mac, BWN_NPHY_DUP40_GFBL, 0xAA8);
6250 		BWN_PHY_WRITE(mac, BWN_NPHY_DUP40_BL, 0x9A4);
6251 	}
6252 
6253 	tmp2 = bwn_current_band(mac);
6254 	if (bwn_nphy_ipa(mac)) {
6255 		BWN_PHY_SET(mac, BWN_NPHY_PAPD_EN0, 0x1);
6256 		BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_TABLE_ADJ0, 0x007F,
6257 				nphy->papd_epsilon_offset[0] << 7);
6258 		BWN_PHY_SET(mac, BWN_NPHY_PAPD_EN1, 0x1);
6259 		BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_TABLE_ADJ1, 0x007F,
6260 				nphy->papd_epsilon_offset[1] << 7);
6261 		bwn_nphy_int_pa_set_tx_dig_filters(mac);
6262 	} else if (phy->rev >= 5) {
6263 		bwn_nphy_ext_pa_set_tx_dig_filters(mac);
6264 	}
6265 
6266 	bwn_nphy_workarounds(mac);
6267 
6268 	/* Reset CCA, in init code it differs a little from standard way */
6269 	bwn_phy_force_clock(mac, 1);
6270 	tmp = BWN_PHY_READ(mac, BWN_NPHY_BBCFG);
6271 	BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, tmp | BWN_NPHY_BBCFG_RSTCCA);
6272 	BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, tmp & ~BWN_NPHY_BBCFG_RSTCCA);
6273 	bwn_phy_force_clock(mac, 0);
6274 
6275 	bwn_mac_phy_clock_set(mac, true);
6276 
6277 	if (phy->rev < 7) {
6278 		bwn_nphy_pa_override(mac, false);
6279 		bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RX2TX);
6280 		bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX);
6281 		bwn_nphy_pa_override(mac, true);
6282 	}
6283 
6284 	bwn_nphy_classifier(mac, 0, 0);
6285 	bwn_nphy_read_clip_detection(mac, clip);
6286 	if (bwn_current_band(mac) == BWN_BAND_2G)
6287 		bwn_nphy_bphy_init(mac);
6288 
6289 	tx_pwr_state = nphy->txpwrctrl;
6290 	bwn_nphy_tx_power_ctrl(mac, false);
6291 	bwn_nphy_tx_power_fix(mac);
6292 	bwn_nphy_tx_power_ctl_idle_tssi(mac);
6293 	bwn_nphy_tx_power_ctl_setup(mac);
6294 	bwn_nphy_tx_gain_table_upload(mac);
6295 
6296 	if (nphy->phyrxchain != 3)
6297 		bwn_nphy_set_rx_core_state(mac, nphy->phyrxchain);
6298 	if (nphy->mphase_cal_phase_id > 0)
6299 		;/* TODO PHY Periodic Calibration Multi-Phase Restart */
6300 
6301 	do_rssi_cal = false;
6302 	if (phy->rev >= 3) {
6303 		if (bwn_current_band(mac) == BWN_BAND_2G)
6304 			do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
6305 		else
6306 			do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
6307 
6308 		if (do_rssi_cal)
6309 			bwn_nphy_rssi_cal(mac);
6310 		else
6311 			bwn_nphy_restore_rssi_cal(mac);
6312 	} else {
6313 		bwn_nphy_rssi_cal(mac);
6314 	}
6315 
6316 	if (!((nphy->measure_hold & 0x6) != 0)) {
6317 		if (bwn_current_band(mac) == BWN_BAND_2G)
6318 			do_cal = !nphy->iqcal_chanspec_2G.center_freq;
6319 		else
6320 			do_cal = !nphy->iqcal_chanspec_5G.center_freq;
6321 
6322 		if (nphy->mute)
6323 			do_cal = false;
6324 
6325 		if (do_cal) {
6326 			target = bwn_nphy_get_tx_gains(mac);
6327 
6328 			if (nphy->antsel_type == 2)
6329 				bwn_nphy_superswitch_init(mac, true);
6330 			if (nphy->perical != 2) {
6331 				bwn_nphy_rssi_cal(mac);
6332 				if (phy->rev >= 3) {
6333 					nphy->cal_orig_pwr_idx[0] =
6334 					    nphy->txpwrindex[0].index_internal;
6335 					nphy->cal_orig_pwr_idx[1] =
6336 					    nphy->txpwrindex[1].index_internal;
6337 					/* TODO N PHY Pre Calibrate TX Gain */
6338 					target = bwn_nphy_get_tx_gains(mac);
6339 				}
6340 				if (!bwn_nphy_cal_tx_iq_lo(mac, target, true, false))
6341 					if (bwn_nphy_cal_rx_iq(mac, target, 2, 0) == 0)
6342 						bwn_nphy_save_cal(mac);
6343 			} else if (nphy->mphase_cal_phase_id == 0)
6344 				;/* N PHY Periodic Calibration with arg 3 */
6345 		} else {
6346 			bwn_nphy_restore_cal(mac);
6347 		}
6348 	}
6349 
6350 	bwn_nphy_tx_pwr_ctrl_coef_setup(mac);
6351 	bwn_nphy_tx_power_ctrl(mac, tx_pwr_state);
6352 	BWN_PHY_WRITE(mac, BWN_NPHY_TXMACIF_HOLDOFF, 0x0015);
6353 	BWN_PHY_WRITE(mac, BWN_NPHY_TXMACDELAY, 0x0320);
6354 	if (phy->rev >= 3 && phy->rev <= 6)
6355 		BWN_PHY_WRITE(mac, BWN_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032);
6356 	bwn_nphy_tx_lpf_bw(mac);
6357 	if (phy->rev >= 3)
6358 		bwn_nphy_spur_workaround(mac);
6359 
6360 	return 0;
6361 }
6362 
6363 /**************************************************
6364  * Channel switching ops.
6365  **************************************************/
6366 
6367 static void bwn_chantab_phy_upload(struct bwn_mac *mac,
6368 				   const struct bwn_phy_n_sfo_cfg *e)
6369 {
6370 	BWN_PHY_WRITE(mac, BWN_NPHY_BW1A, e->phy_bw1a);
6371 	BWN_PHY_WRITE(mac, BWN_NPHY_BW2, e->phy_bw2);
6372 	BWN_PHY_WRITE(mac, BWN_NPHY_BW3, e->phy_bw3);
6373 	BWN_PHY_WRITE(mac, BWN_NPHY_BW4, e->phy_bw4);
6374 	BWN_PHY_WRITE(mac, BWN_NPHY_BW5, e->phy_bw5);
6375 	BWN_PHY_WRITE(mac, BWN_NPHY_BW6, e->phy_bw6);
6376 }
6377 
6378 /* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
6379 static void bwn_nphy_pmu_spur_avoid(struct bwn_mac *mac, bool avoid)
6380 {
6381 	struct bwn_softc *sc = mac->mac_sc;
6382 
6383 	/* XXX bhnd */
6384 	if (bwn_is_bus_siba(mac)) {
6385 		DPRINTF(sc, BWN_DEBUG_RESET, "%s: spuravoid %d\n", __func__, avoid);
6386 		siba_pmu_spuravoid_pllupdate(sc->sc_dev, avoid);
6387 	}
6388 }
6389 
6390 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
6391 static void bwn_nphy_channel_setup(struct bwn_mac *mac,
6392 				const struct bwn_phy_n_sfo_cfg *e,
6393 				struct ieee80211_channel *new_channel)
6394 {
6395 	struct bwn_softc *sc = mac->mac_sc;
6396 	struct bwn_phy *phy = &mac->mac_phy;
6397 	struct bwn_phy_n *nphy = mac->mac_phy.phy_n;
6398 	int ch = new_channel->ic_ieee;
6399 	uint16_t tmp16;
6400 
6401 	if (bwn_channel_band(mac, new_channel) == BWN_BAND_5G) {
6402 		DPRINTF(sc, BWN_DEBUG_RESET, "%s: BAND_5G; chan=%d\n", __func__, ch);
6403 		/* Switch to 2 GHz for a moment to access BWN_PHY_B_BBCFG */
6404 		BWN_PHY_MASK(mac, BWN_NPHY_BANDCTL, ~BWN_NPHY_BANDCTL_5GHZ);
6405 
6406 		tmp16 = BWN_READ_2(mac, BWN_PSM_PHY_HDR);
6407 		BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16 | 4);
6408 		/* Put BPHY in the reset */
6409 		BWN_PHY_SET(mac, BWN_PHY_B_BBCFG,
6410 			    BWN_PHY_B_BBCFG_RSTCCA | BWN_PHY_B_BBCFG_RSTRX);
6411 		BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16);
6412 		BWN_PHY_SET(mac, BWN_NPHY_BANDCTL, BWN_NPHY_BANDCTL_5GHZ);
6413 	} else if (bwn_channel_band(mac, new_channel) == BWN_BAND_2G) {
6414 		DPRINTF(sc, BWN_DEBUG_RESET, "%s: BAND_2G; chan=%d\n", __func__, ch);
6415 		BWN_PHY_MASK(mac, BWN_NPHY_BANDCTL, ~BWN_NPHY_BANDCTL_5GHZ);
6416 		tmp16 = BWN_READ_2(mac, BWN_PSM_PHY_HDR);
6417 		BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16 | 4);
6418 		/* Take BPHY out of the reset */
6419 		BWN_PHY_MASK(mac, BWN_PHY_B_BBCFG,
6420 			     (uint16_t)~(BWN_PHY_B_BBCFG_RSTCCA | BWN_PHY_B_BBCFG_RSTRX));
6421 		BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16);
6422 	} else {
6423 		BWN_ERRPRINTF(mac->mac_sc, "%s: unknown band?\n", __func__);
6424 	}
6425 
6426 	bwn_chantab_phy_upload(mac, e);
6427 
6428 	if (new_channel->ic_ieee == 14) {
6429 		bwn_nphy_classifier(mac, 2, 0);
6430 		BWN_PHY_SET(mac, BWN_PHY_B_TEST, 0x0800);
6431 	} else {
6432 		bwn_nphy_classifier(mac, 2, 2);
6433 		if (bwn_channel_band(mac, new_channel) == BWN_BAND_2G)
6434 			BWN_PHY_MASK(mac, BWN_PHY_B_TEST, ~0x840);
6435 	}
6436 
6437 	if (!nphy->txpwrctrl)
6438 		bwn_nphy_tx_power_fix(mac);
6439 
6440 	if (mac->mac_phy.rev < 3)
6441 		bwn_nphy_adjust_lna_gain_table(mac);
6442 
6443 	bwn_nphy_tx_lpf_bw(mac);
6444 
6445 	if (mac->mac_phy.rev >= 3 &&
6446 	    mac->mac_phy.phy_n->spur_avoid != BWN_SPUR_AVOID_DISABLE) {
6447 		uint8_t spuravoid = 0;
6448 
6449 		if (mac->mac_phy.phy_n->spur_avoid == BWN_SPUR_AVOID_FORCE) {
6450 			spuravoid = 1;
6451 		} else if (phy->rev >= 19) {
6452 			/* TODO */
6453 		} else if (phy->rev >= 18) {
6454 			/* TODO */
6455 		} else if (phy->rev >= 17) {
6456 			/* TODO: Off for channels 1-11, but check 12-14! */
6457 		} else if (phy->rev >= 16) {
6458 			/* TODO: Off for 2 GHz, but check 5 GHz! */
6459 		} else if (phy->rev >= 7) {
6460 			if (!bwn_is_40mhz(mac)) { /* 20MHz */
6461 				if (ch == 13 || ch == 14 || ch == 153)
6462 					spuravoid = 1;
6463 			} else { /* 40 MHz */
6464 				if (ch == 54)
6465 					spuravoid = 1;
6466 			}
6467 		} else {
6468 			if (!bwn_is_40mhz(mac)) { /* 20MHz */
6469 				if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
6470 					spuravoid = 1;
6471 			} else { /* 40MHz */
6472 				if (nphy->aband_spurwar_en &&
6473 				    (ch == 38 || ch == 102 || ch == 118))
6474 					spuravoid = siba_get_chipid(sc->sc_dev) == 0x4716;
6475 			}
6476 		}
6477 
6478 		bwn_nphy_pmu_spur_avoid(mac, spuravoid);
6479 
6480 		bwn_mac_switch_freq(mac, spuravoid);
6481 
6482 		if (mac->mac_phy.rev == 3 || mac->mac_phy.rev == 4)
6483 			bwn_wireless_core_phy_pll_reset(mac);
6484 
6485 		if (spuravoid)
6486 			BWN_PHY_SET(mac, BWN_NPHY_BBCFG, BWN_NPHY_BBCFG_RSTRX);
6487 		else
6488 			BWN_PHY_MASK(mac, BWN_NPHY_BBCFG,
6489 				     ~BWN_NPHY_BBCFG_RSTRX & 0xFFFF);
6490 
6491 		bwn_nphy_reset_cca(mac);
6492 
6493 		/* wl sets useless phy_isspuravoid here */
6494 	}
6495 
6496 	BWN_PHY_WRITE(mac, BWN_NPHY_NDATAT_DUP40, 0x3830);
6497 
6498 	if (phy->rev >= 3)
6499 		bwn_nphy_spur_workaround(mac);
6500 }
6501 
6502 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
6503 static int bwn_nphy_set_channel(struct bwn_mac *mac,
6504 				struct ieee80211_channel *channel,
6505 				bwn_chan_type_t channel_type)
6506 {
6507 	struct bwn_phy *phy = &mac->mac_phy;
6508 
6509 	const struct bwn_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
6510 	const struct bwn_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
6511 	const struct bwn_nphy_chantabent_rev7 *tabent_r7 = NULL;
6512 	const struct bwn_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL;
6513 
6514 	uint8_t tmp;
6515 
6516 	if (phy->rev >= 19) {
6517 		return -ESRCH;
6518 		/* TODO */
6519 	} else if (phy->rev >= 7) {
6520 		r2057_get_chantabent_rev7(mac, bwn_get_chan_centre_freq(mac, channel),
6521 					  &tabent_r7, &tabent_r7_2g);
6522 		if (!tabent_r7 && !tabent_r7_2g)
6523 			return -ESRCH;
6524 	} else if (phy->rev >= 3) {
6525 		tabent_r3 = bwn_nphy_get_chantabent_rev3(mac,
6526 		    bwn_get_chan_centre_freq(mac, channel));
6527 		if (!tabent_r3)
6528 			return -ESRCH;
6529 	} else {
6530 		tabent_r2 = bwn_nphy_get_chantabent_rev2(mac,
6531 		    channel->ic_ieee);
6532 		if (!tabent_r2)
6533 			return -ESRCH;
6534 	}
6535 
6536 	/* Channel is set later in common code, but we need to set it on our
6537 	   own to let this function's subcalls work properly. */
6538 #if 0
6539 	phy->channel = channel->ic_ieee;
6540 #endif
6541 
6542 #if 0
6543 	if (bwn_channel_type_is_40mhz(phy->channel_type) !=
6544 		bwn_channel_type_is_40mhz(channel_type))
6545 		; /* TODO: BMAC BW Set (channel_type) */
6546 #endif
6547 
6548 	if (channel_type == BWN_CHAN_TYPE_40_HT_U) {
6549 		BWN_PHY_SET(mac, BWN_NPHY_RXCTL, BWN_NPHY_RXCTL_BSELU20);
6550 		if (phy->rev >= 7)
6551 			BWN_PHY_SET(mac, 0x310, 0x8000);
6552 	} else if (channel_type == BWN_CHAN_TYPE_40_HT_D) {
6553 		BWN_PHY_MASK(mac, BWN_NPHY_RXCTL, ~BWN_NPHY_RXCTL_BSELU20);
6554 		if (phy->rev >= 7)
6555 			BWN_PHY_MASK(mac, 0x310, (uint16_t)~0x8000);
6556 	}
6557 
6558 	if (phy->rev >= 19) {
6559 		/* TODO */
6560 	} else if (phy->rev >= 7) {
6561 		const struct bwn_phy_n_sfo_cfg *phy_regs = tabent_r7 ?
6562 			&(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs);
6563 
6564 		if (phy->rf_rev <= 4 || phy->rf_rev == 6) {
6565 			tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 2 : 0;
6566 			BWN_RF_SETMASK(mac, R2057_TIA_CONFIG_CORE0, ~2, tmp);
6567 			BWN_RF_SETMASK(mac, R2057_TIA_CONFIG_CORE1, ~2, tmp);
6568 		}
6569 
6570 		bwn_radio_2057_setup(mac, tabent_r7, tabent_r7_2g);
6571 		bwn_nphy_channel_setup(mac, phy_regs, channel);
6572 	} else if (phy->rev >= 3) {
6573 		tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 4 : 0;
6574 		BWN_RF_SETMASK(mac, 0x08, 0xFFFB, tmp);
6575 		bwn_radio_2056_setup(mac, tabent_r3);
6576 		bwn_nphy_channel_setup(mac, &(tabent_r3->phy_regs), channel);
6577 	} else {
6578 		tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 0x0020 : 0x0050;
6579 		BWN_RF_SETMASK(mac, B2055_MASTER1, 0xFF8F, tmp);
6580 		bwn_radio_2055_setup(mac, tabent_r2);
6581 		bwn_nphy_channel_setup(mac, &(tabent_r2->phy_regs), channel);
6582 	}
6583 
6584 	return 0;
6585 }
6586 
6587 /**************************************************
6588  * Basic PHY ops.
6589  **************************************************/
6590 
6591 int
6592 bwn_nphy_op_allocate(struct bwn_mac *mac)
6593 {
6594 	struct bwn_phy_n *nphy;
6595 
6596 	nphy = malloc(sizeof(*nphy), M_DEVBUF, M_ZERO | M_NOWAIT);
6597 	if (!nphy)
6598 		return -ENOMEM;
6599 
6600 	mac->mac_phy.phy_n = nphy;
6601 
6602 	return 0;
6603 }
6604 
6605 void
6606 bwn_nphy_op_prepare_structs(struct bwn_mac *mac)
6607 {
6608 	struct bwn_softc *sc = mac->mac_sc;
6609 	struct bwn_phy *phy = &mac->mac_phy;
6610 	struct bwn_phy_n *nphy = phy->phy_n;
6611 
6612 	memset(nphy, 0, sizeof(*nphy));
6613 
6614 	nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
6615 	nphy->spur_avoid = (phy->rev >= 3) ?
6616 				BWN_SPUR_AVOID_AUTO : BWN_SPUR_AVOID_DISABLE;
6617 	nphy->gain_boost = true; /* this way we follow wl, assume it is true */
6618 	nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
6619 	nphy->phyrxchain = 3; /* to avoid bwn_nphy_set_rx_core_state like wl */
6620 	nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
6621 	/* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
6622 	 * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
6623 	nphy->tx_pwr_idx[0] = 128;
6624 	nphy->tx_pwr_idx[1] = 128;
6625 
6626 	/* Hardware TX power control and 5GHz power gain */
6627 	nphy->txpwrctrl = false;
6628 	nphy->pwg_gain_5ghz = false;
6629 	if (mac->mac_phy.rev >= 3 ||
6630 	    (siba_get_pci_subvendor(sc->sc_dev) == PCI_VENDOR_APPLE &&
6631 	     (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12))) {
6632 		nphy->txpwrctrl = true;
6633 		nphy->pwg_gain_5ghz = true;
6634 	} else if (siba_sprom_get_rev(sc->sc_dev) >= 4) {
6635 		if (mac->mac_phy.rev >= 2 &&
6636 		    (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_TXPWRCTRL_EN)) {
6637 			nphy->txpwrctrl = true;
6638 			if (bwn_is_bus_siba(mac) &&
6639 			    (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI)) {
6640 				if ((siba_get_pci_device(sc->sc_dev) == 0x4328) ||
6641 				    (siba_get_pci_device(sc->sc_dev) == 0x432a))
6642 					nphy->pwg_gain_5ghz = true;
6643 			}
6644 		} else if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_5G_PWRGAIN) {
6645 			nphy->pwg_gain_5ghz = true;
6646 		}
6647 	}
6648 
6649 	if (mac->mac_phy.rev >= 3) {
6650 		nphy->ipa2g_on = siba_sprom_get_fem_2ghz_extpa_gain(sc->sc_dev) == 2;
6651 		nphy->ipa5g_on = siba_sprom_get_fem_5ghz_extpa_gain(sc->sc_dev) == 2;
6652 	}
6653 }
6654 
6655 void
6656 bwn_nphy_op_free(struct bwn_mac *mac)
6657 {
6658 	struct bwn_phy *phy = &mac->mac_phy;
6659 	struct bwn_phy_n *nphy = phy->phy_n;
6660 
6661 	free(nphy, M_DEVBUF);
6662 	phy->phy_n = NULL;
6663 }
6664 
6665 int
6666 bwn_nphy_op_init(struct bwn_mac *mac)
6667 {
6668 	return bwn_phy_initn(mac);
6669 }
6670 
6671 static inline void check_phyreg(struct bwn_mac *mac, uint16_t offset)
6672 {
6673 #ifdef	BWN_DEBUG
6674 	if ((offset & BWN_PHYROUTE_MASK) == BWN_PHYROUTE_OFDM_GPHY) {
6675 		/* OFDM registers are onnly available on A/G-PHYs */
6676 		BWN_ERRPRINTF(mac->mac_sc, "Invalid OFDM PHY access at "
6677 		       "0x%04X on N-PHY\n", offset);
6678 	}
6679 	if ((offset & BWN_PHYROUTE_MASK) == BWN_PHYROUTE_EXT_GPHY) {
6680 		/* Ext-G registers are only available on G-PHYs */
6681 		BWN_ERRPRINTF(mac->mac_sc, "Invalid EXT-G PHY access at "
6682 		       "0x%04X on N-PHY\n", offset);
6683 	}
6684 #endif /* BWN_DEBUG */
6685 }
6686 
6687 void
6688 bwn_nphy_op_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
6689     uint16_t set)
6690 {
6691 	check_phyreg(mac, reg);
6692 	BWN_WRITE_2_F(mac, BWN_PHYCTL, reg);
6693 	BWN_WRITE_SETMASK2(mac, BWN_PHYDATA, mask, set);
6694 }
6695 
6696 #if 0
6697 uint16_t
6698 bwn_nphy_op_radio_read(struct bwn_mac *mac, uint16_t reg)
6699 {
6700 	/* Register 1 is a 32-bit register. */
6701 	if (mac->mac_phy.rev < 7 && reg == 1) {
6702 		BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__);
6703 	}
6704 
6705 	if (mac->mac_phy.rev >= 7)
6706 		reg |= 0x200; /* Radio 0x2057 */
6707 	else
6708 		reg |= 0x100;
6709 
6710 	BWN_WRITE_2_F(mac, BWN_RFCTL, reg);
6711 	return BWN_READ_2(mac, BWN_RFDATALO);
6712 }
6713 #endif
6714 
6715 #if 0
6716 void
6717 bwn_nphy_op_radio_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
6718 {
6719 	/* Register 1 is a 32-bit register. */
6720 	if (mac->mac_phy.rev < 7 && reg == 1) {
6721 		BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__);
6722 	}
6723 
6724 	BWN_WRITE_2_F(mac, BWN_RFCTL, reg);
6725 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
6726 }
6727 #endif
6728 
6729 /* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
6730 void
6731 bwn_nphy_op_software_rfkill(struct bwn_mac *mac, bool active)
6732 {
6733 	struct bwn_phy *phy = &mac->mac_phy;
6734 
6735 	if (BWN_READ_4(mac, BWN_MACCTL) & BWN_MACCTL_ON)
6736 		BWN_ERRPRINTF(mac->mac_sc, "MAC not suspended\n");
6737 
6738 	DPRINTF(mac->mac_sc, BWN_DEBUG_RESET | BWN_DEBUG_PHY,
6739 	    "%s: called; rev=%d, rf_on=%d, active=%d\n", __func__,
6740 	    phy->rev, mac->mac_phy.rf_on, active);
6741 
6742 	/*
6743 	 * XXX TODO: don't bother doing RF programming if it's
6744 	 * already done.  But, bwn(4) currently sets rf_on in the
6745 	 * PHY setup and leaves it on after startup, which causes
6746 	 * the below to not init the 2056/2057 radios.
6747 	 */
6748 	if (active) {
6749 		if (phy->rev >= 19) {
6750 			/* TODO */
6751 		} else if (phy->rev >= 7) {
6752 //			if (!mac->mac_phy.rf_on)
6753 				bwn_radio_2057_init(mac);
6754 			bwn_switch_channel(mac, bwn_get_chan(mac));
6755 		} else if (phy->rev >= 3) {
6756 //			if (!mac->mac_phy.rf_on)
6757 				bwn_radio_init2056(mac);
6758 			bwn_switch_channel(mac, bwn_get_chan(mac));
6759 		} else {
6760 			bwn_radio_init2055(mac);
6761 		}
6762 	} else {
6763 		if (phy->rev >= 19) {
6764 			/* TODO */
6765 		} else if (phy->rev >= 8) {
6766 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD,
6767 				     ~BWN_NPHY_RFCTL_CMD_CHIP0PU);
6768 		} else if (phy->rev >= 7) {
6769 			/* Nothing needed */
6770 		} else if (phy->rev >= 3) {
6771 			BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD,
6772 				     ~BWN_NPHY_RFCTL_CMD_CHIP0PU);
6773 
6774 			BWN_RF_MASK(mac, 0x09, ~0x2);
6775 
6776 			BWN_RF_WRITE(mac, 0x204D, 0);
6777 			BWN_RF_WRITE(mac, 0x2053, 0);
6778 			BWN_RF_WRITE(mac, 0x2058, 0);
6779 			BWN_RF_WRITE(mac, 0x205E, 0);
6780 			BWN_RF_MASK(mac, 0x2062, ~0xF0);
6781 			BWN_RF_WRITE(mac, 0x2064, 0);
6782 
6783 			BWN_RF_WRITE(mac, 0x304D, 0);
6784 			BWN_RF_WRITE(mac, 0x3053, 0);
6785 			BWN_RF_WRITE(mac, 0x3058, 0);
6786 			BWN_RF_WRITE(mac, 0x305E, 0);
6787 			BWN_RF_MASK(mac, 0x3062, ~0xF0);
6788 			BWN_RF_WRITE(mac, 0x3064, 0);
6789 		}
6790 	}
6791 }
6792 
6793 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
6794 void
6795 bwn_nphy_op_switch_analog(struct bwn_mac *mac, bool on)
6796 {
6797 	struct bwn_phy *phy = &mac->mac_phy;
6798 	uint16_t override = on ? 0x0 : 0x7FFF;
6799 	uint16_t core = on ? 0xD : 0x00FD;
6800 
6801 	if (phy->rev >= 19) {
6802 		/* TODO */
6803 		device_printf(mac->mac_sc->sc_dev, "%s: TODO\n", __func__);
6804 	} else if (phy->rev >= 3) {
6805 		if (on) {
6806 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, core);
6807 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, override);
6808 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, core);
6809 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override);
6810 		} else {
6811 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, override);
6812 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, core);
6813 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override);
6814 			BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, core);
6815 		}
6816 	} else {
6817 		BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override);
6818 	}
6819 }
6820 
6821 int
6822 bwn_nphy_op_switch_channel(struct bwn_mac *mac, unsigned int new_channel)
6823 {
6824 	struct ieee80211_channel *channel = bwn_get_channel(mac);
6825 	bwn_chan_type_t channel_type = bwn_get_chan_type(mac, NULL);
6826 
6827 	if (bwn_current_band(mac) == BWN_BAND_2G) {
6828 		if ((new_channel < 1) || (new_channel > 14))
6829 			return -EINVAL;
6830 	} else {
6831 		if (new_channel > 200)
6832 			return -EINVAL;
6833 	}
6834 
6835 	return bwn_nphy_set_channel(mac, channel, channel_type);
6836 }
6837 
6838 #if 0
6839 unsigned int
6840 bwn_nphy_op_get_default_chan(struct bwn_mac *mac)
6841 {
6842 	if (bwn_current_band(mac) == BWN_BAND_2G)
6843 		return 1;
6844 	return 36;
6845 }
6846 #endif
6847