1 /*-
2 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include "opt_bwn.h"
34 #include "opt_wlan.h"
35
36 /*
37 * The Broadcom Wireless LAN controller driver.
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/module.h>
45 #include <sys/endian.h>
46 #include <sys/errno.h>
47 #include <sys/firmware.h>
48 #include <sys/lock.h>
49 #include <sys/mutex.h>
50 #include <machine/bus.h>
51 #include <machine/resource.h>
52 #include <sys/bus.h>
53 #include <sys/rman.h>
54 #include <sys/socket.h>
55 #include <sys/sockio.h>
56
57 #include <net/ethernet.h>
58 #include <net/if.h>
59 #include <net/if_var.h>
60 #include <net/if_arp.h>
61 #include <net/if_dl.h>
62 #include <net/if_llc.h>
63 #include <net/if_media.h>
64 #include <net/if_types.h>
65
66 #include <dev/pci/pcivar.h>
67 #include <dev/pci/pcireg.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
78 #include <dev/bwn/if_bwn_debug.h>
79 #include <dev/bwn/if_bwn_misc.h>
80 #include <dev/bwn/if_bwn_phy_g.h>
81
82 #include "bhnd_nvram_map.h"
83
84 static void bwn_phy_g_init_sub(struct bwn_mac *);
85 static uint8_t bwn_has_hwpctl(struct bwn_mac *);
86 static void bwn_phy_init_b5(struct bwn_mac *);
87 static void bwn_phy_init_b6(struct bwn_mac *);
88 static void bwn_phy_init_a(struct bwn_mac *);
89 static void bwn_loopback_calcgain(struct bwn_mac *);
90 static uint16_t bwn_rf_init_bcm2050(struct bwn_mac *);
91 static void bwn_lo_g_init(struct bwn_mac *);
92 static void bwn_lo_g_adjust(struct bwn_mac *);
93 static void bwn_lo_get_powervector(struct bwn_mac *);
94 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *,
95 const struct bwn_bbatt *, const struct bwn_rfatt *);
96 static void bwn_lo_write(struct bwn_mac *, struct bwn_loctl *);
97 static void bwn_phy_hwpctl_init(struct bwn_mac *);
98 static void bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t);
99 static void bwn_phy_g_set_txpwr_sub(struct bwn_mac *,
100 const struct bwn_bbatt *, const struct bwn_rfatt *,
101 uint8_t);
102 static void bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t);
103 static uint16_t bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t);
104 static void bwn_spu_workaround(struct bwn_mac *, uint8_t);
105 static void bwn_wa_init(struct bwn_mac *);
106 static void bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t,
107 uint16_t);
108 static void bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t,
109 uint32_t);
110 static void bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t,
111 uint16_t);
112 static int16_t bwn_nrssi_read(struct bwn_mac *, uint16_t);
113 static void bwn_nrssi_offset(struct bwn_mac *);
114 static void bwn_nrssi_threshold(struct bwn_mac *);
115 static void bwn_nrssi_slope_11g(struct bwn_mac *);
116 static void bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t,
117 int16_t);
118 static void bwn_set_original_gains(struct bwn_mac *);
119 static void bwn_hwpctl_early_init(struct bwn_mac *);
120 static void bwn_hwpctl_init_gphy(struct bwn_mac *);
121 static uint16_t bwn_phy_g_chan2freq(uint8_t);
122 static void bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
123
124 /* Stuff we need */
125
126 static uint16_t bwn_phy_g_txctl(struct bwn_mac *mac);
127 static int bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset);
128 static void bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp);
129 static void bwn_phy_lock(struct bwn_mac *mac);
130 static void bwn_phy_unlock(struct bwn_mac *mac);
131 static void bwn_rf_lock(struct bwn_mac *mac);
132 static void bwn_rf_unlock(struct bwn_mac *mac);
133
134 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
135 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
136 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
137 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
138 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
139 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
140
141 static uint8_t
142 bwn_has_hwpctl(struct bwn_mac *mac)
143 {
144
145 if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
146 return (0);
147 return (mac->mac_phy.use_hwpctl(mac));
148 }
149
150 int
151 bwn_phy_g_attach(struct bwn_mac *mac)
152 {
153 struct bwn_softc *sc = mac->mac_sc;
154 struct bwn_phy *phy = &mac->mac_phy;
155 struct bwn_phy_g *pg = &phy->phy_g;
156 unsigned int i;
157 int16_t pab0, pab1, pab2;
158 static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
159 int8_t bg;
160 int error;
161
162 /* Fetch SPROM configuration */
163 #define BWN_PHY_G_READVAR(_dev, _type, _name, _result) \
164 do { \
165 error = bhnd_nvram_getvar_ ##_type((_dev), (_name), (_result)); \
166 if (error) { \
167 device_printf((_dev), "NVRAM variable %s unreadable: " \
168 "%d\n", (_name), error); \
169 return (error); \
170 } \
171 } while(0)
172
173 BWN_PHY_G_READVAR(sc->sc_dev, int8, BHND_NVAR_PA0ITSSIT, &bg);
174 BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B0, &pab0);
175 BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B1, &pab1);
176 BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B2, &pab2);
177 BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0MAXPWR,
178 &pg->pg_pa0maxpwr);
179
180 #undef BWN_PHY_G_READVAR
181
182 pg->pg_flags = 0;
183 if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
184 pab2 == -1) {
185 pg->pg_idletssi = 52;
186 pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
187 return (0);
188 }
189
190 pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
191 pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
192 if (pg->pg_tssi2dbm == NULL) {
193 device_printf(sc->sc_dev, "failed to allocate buffer\n");
194 return (ENOMEM);
195 }
196 for (i = 0; i < 64; i++) {
197 int32_t m1, m2, f, q, delta;
198 int8_t j = 0;
199
200 m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
201 m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
202 f = 256;
203
204 do {
205 if (j > 15) {
206 device_printf(sc->sc_dev,
207 "failed to generate tssi2dBm\n");
208 free(pg->pg_tssi2dbm, M_DEVBUF);
209 return (ENOMEM);
210 }
211 q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
212 f, 2048);
213 delta = abs(q - f);
214 f = q;
215 j++;
216 } while (delta >= 2);
217
218 pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
219 127);
220 }
221
222 pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
223 return (0);
224 }
225
226 void
227 bwn_phy_g_detach(struct bwn_mac *mac)
228 {
229 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
230
231 if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
232 free(pg->pg_tssi2dbm, M_DEVBUF);
233 pg->pg_tssi2dbm = NULL;
234 }
235 pg->pg_flags = 0;
236 }
237
238 void
239 bwn_phy_g_init_pre(struct bwn_mac *mac)
240 {
241 struct bwn_phy *phy = &mac->mac_phy;
242 struct bwn_phy_g *pg = &phy->phy_g;
243 void *tssi2dbm;
244 int idletssi;
245 unsigned int i;
246
247 tssi2dbm = pg->pg_tssi2dbm;
248 idletssi = pg->pg_idletssi;
249
250 memset(pg, 0, sizeof(*pg));
251
252 pg->pg_tssi2dbm = tssi2dbm;
253 pg->pg_idletssi = idletssi;
254
255 memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
256
257 for (i = 0; i < N(pg->pg_nrssi); i++)
258 pg->pg_nrssi[i] = -1000;
259 for (i = 0; i < N(pg->pg_nrssi_lt); i++)
260 pg->pg_nrssi_lt[i] = i;
261 pg->pg_lofcal = 0xffff;
262 pg->pg_initval = 0xffff;
263 pg->pg_immode = BWN_IMMODE_NONE;
264 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
265 pg->pg_avgtssi = 0xff;
266
267 pg->pg_loctl.tx_bias = 0xff;
268 TAILQ_INIT(&pg->pg_loctl.calib_list);
269 }
270
271 int
272 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
273 {
274 struct bwn_phy *phy = &mac->mac_phy;
275 struct bwn_phy_g *pg = &phy->phy_g;
276 struct bwn_softc *sc = mac->mac_sc;
277 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
278 static const struct bwn_rfatt rfatt0[] = {
279 { 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 }, { 9, 0 }, { 2, 0 },
280 { 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
281 { 3, 1 }, { 4, 1 }
282 };
283 static const struct bwn_rfatt rfatt1[] = {
284 { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
285 { 14, 1 }
286 };
287 static const struct bwn_rfatt rfatt2[] = {
288 { 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
289 { 9, 1 }
290 };
291 static const struct bwn_bbatt bbatt_0[] = {
292 { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
293 };
294
295 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
296
297 if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
298 pg->pg_bbatt.att = 0;
299 else
300 pg->pg_bbatt.att = 2;
301
302 /* prepare Radio Attenuation */
303 pg->pg_rfatt.padmix = 0;
304
305 if (sc->sc_board_info.board_vendor == PCI_VENDOR_BROADCOM &&
306 sc->sc_board_info.board_type == BHND_BOARD_BCM94309G) {
307 if (sc->sc_board_info.board_rev < 0x43) {
308 pg->pg_rfatt.att = 2;
309 goto done;
310 } else if (sc->sc_board_info.board_rev < 0x51) {
311 pg->pg_rfatt.att = 3;
312 goto done;
313 }
314 }
315
316 if (phy->type == BWN_PHYTYPE_A) {
317 pg->pg_rfatt.att = 0x60;
318 goto done;
319 }
320
321 switch (phy->rf_ver) {
322 case 0x2050:
323 switch (phy->rf_rev) {
324 case 0:
325 pg->pg_rfatt.att = 5;
326 goto done;
327 case 1:
328 if (phy->type == BWN_PHYTYPE_G) {
329 if (sc->sc_board_info.board_vendor ==
330 PCI_VENDOR_BROADCOM &&
331 sc->sc_board_info.board_type ==
332 BHND_BOARD_BCM94309G &&
333 sc->sc_board_info.board_rev >= 30)
334 pg->pg_rfatt.att = 3;
335 else if (sc->sc_board_info.board_vendor ==
336 PCI_VENDOR_BROADCOM &&
337 sc->sc_board_info.board_type ==
338 BHND_BOARD_BU4306)
339 pg->pg_rfatt.att = 3;
340 else
341 pg->pg_rfatt.att = 1;
342 } else {
343 if (sc->sc_board_info.board_vendor ==
344 PCI_VENDOR_BROADCOM &&
345 sc->sc_board_info.board_type ==
346 BHND_BOARD_BCM94309G &&
347 sc->sc_board_info.board_rev >= 30)
348 pg->pg_rfatt.att = 7;
349 else
350 pg->pg_rfatt.att = 6;
351 }
352 goto done;
353 case 2:
354 if (phy->type == BWN_PHYTYPE_G) {
355 if (sc->sc_board_info.board_vendor ==
356 PCI_VENDOR_BROADCOM &&
357 sc->sc_board_info.board_type ==
358 BHND_BOARD_BCM94309G &&
359 sc->sc_board_info.board_rev >= 30)
360 pg->pg_rfatt.att = 3;
361 else if (sc->sc_board_info.board_vendor ==
362 PCI_VENDOR_BROADCOM &&
363 sc->sc_board_info.board_type ==
364 BHND_BOARD_BU4306)
365 pg->pg_rfatt.att = 5;
366 else if (sc->sc_cid.chip_id ==
367 BHND_CHIPID_BCM4320)
368 pg->pg_rfatt.att = 4;
369 else
370 pg->pg_rfatt.att = 3;
371 } else
372 pg->pg_rfatt.att = 6;
373 goto done;
374 case 3:
375 pg->pg_rfatt.att = 5;
376 goto done;
377 case 4:
378 case 5:
379 pg->pg_rfatt.att = 1;
380 goto done;
381 case 6:
382 case 7:
383 pg->pg_rfatt.att = 5;
384 goto done;
385 case 8:
386 pg->pg_rfatt.att = 0xa;
387 pg->pg_rfatt.padmix = 1;
388 goto done;
389 case 9:
390 default:
391 pg->pg_rfatt.att = 5;
392 goto done;
393 }
394 break;
395 case 0x2053:
396 switch (phy->rf_rev) {
397 case 1:
398 pg->pg_rfatt.att = 6;
399 goto done;
400 }
401 break;
402 }
403 pg->pg_rfatt.att = 5;
404 done:
405 pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
406
407 if (!bwn_has_hwpctl(mac)) {
408 lo->rfatt.array = rfatt0;
409 lo->rfatt.len = N(rfatt0);
410 lo->rfatt.min = 0;
411 lo->rfatt.max = 9;
412 goto genbbatt;
413 }
414 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
415 lo->rfatt.array = rfatt1;
416 lo->rfatt.len = N(rfatt1);
417 lo->rfatt.min = 0;
418 lo->rfatt.max = 14;
419 goto genbbatt;
420 }
421 lo->rfatt.array = rfatt2;
422 lo->rfatt.len = N(rfatt2);
423 lo->rfatt.min = 0;
424 lo->rfatt.max = 9;
425 genbbatt:
426 lo->bbatt.array = bbatt_0;
427 lo->bbatt.len = N(bbatt_0);
428 lo->bbatt.min = 0;
429 lo->bbatt.max = 8;
430
431 BWN_READ_4(mac, BWN_MACCTL);
432 if (phy->rev == 1) {
433 phy->gmode = 0;
434 bwn_reset_core(mac, 0);
435 bwn_phy_g_init_sub(mac);
436 phy->gmode = 1;
437 bwn_reset_core(mac, 1);
438 }
439 return (0);
440 }
441
442 static uint16_t
443 bwn_phy_g_txctl(struct bwn_mac *mac)
444 {
445 struct bwn_phy *phy = &mac->mac_phy;
446
447 if (phy->rf_ver != 0x2050)
448 return (0);
449 if (phy->rf_rev == 1)
450 return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
451 if (phy->rf_rev < 6)
452 return (BWN_TXCTL_PA2DB);
453 if (phy->rf_rev == 8)
454 return (BWN_TXCTL_TXMIX);
455 return (0);
456 }
457
458 int
459 bwn_phy_g_init(struct bwn_mac *mac)
460 {
461
462 bwn_phy_g_init_sub(mac);
463 return (0);
464 }
465
466 void
467 bwn_phy_g_exit(struct bwn_mac *mac)
468 {
469 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
470 struct bwn_lo_calib *cal, *tmp;
471
472 if (lo == NULL)
473 return;
474 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
475 TAILQ_REMOVE(&lo->calib_list, cal, list);
476 free(cal, M_DEVBUF);
477 }
478 }
479
480 uint16_t
481 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
482 {
483
484 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
485 return (BWN_READ_2(mac, BWN_PHYDATA));
486 }
487
488 void
489 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
490 {
491
492 BWN_WRITE_2(mac, BWN_PHYCTL, reg);
493 BWN_WRITE_2(mac, BWN_PHYDATA, value);
494 }
495
496 uint16_t
497 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
498 {
499
500 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
501 BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
502 return (BWN_READ_2(mac, BWN_RFDATALO));
503 }
504
505 void
506 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
507 {
508
509 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
510 BWN_WRITE_2(mac, BWN_RFCTL, reg);
511 BWN_WRITE_2(mac, BWN_RFDATALO, value);
512 }
513
514 int
515 bwn_phy_g_hwpctl(struct bwn_mac *mac)
516 {
517
518 return (mac->mac_phy.rev >= 6);
519 }
520
521 void
522 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
523 {
524 struct bwn_phy *phy = &mac->mac_phy;
525 struct bwn_phy_g *pg = &phy->phy_g;
526 unsigned int channel;
527 uint16_t rfover, rfoverval;
528
529 if (on) {
530 if (phy->rf_on)
531 return;
532
533 BWN_PHY_WRITE(mac, 0x15, 0x8000);
534 BWN_PHY_WRITE(mac, 0x15, 0xcc00);
535 BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
536 if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
537 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
538 pg->pg_radioctx_over);
539 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
540 pg->pg_radioctx_overval);
541 pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
542 }
543 channel = phy->chan;
544 bwn_phy_g_switch_chan(mac, 6, 1);
545 bwn_phy_g_switch_chan(mac, channel, 0);
546 return;
547 }
548
549 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
550 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
551 pg->pg_radioctx_over = rfover;
552 pg->pg_radioctx_overval = rfoverval;
553 pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
554 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
555 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
556 }
557
558 int
559 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
560 {
561
562 if ((newchan < 1) || (newchan > 14))
563 return (EINVAL);
564 bwn_phy_g_switch_chan(mac, newchan, 0);
565
566 return (0);
567 }
568
569 uint32_t
570 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
571 {
572
573 return (1);
574 }
575
576 void
577 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
578 {
579 struct bwn_phy *phy = &mac->mac_phy;
580 uint64_t hf;
581 int autodiv = 0;
582 uint16_t tmp;
583
584 if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
585 autodiv = 1;
586
587 hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
588 bwn_hf_write(mac, hf);
589
590 BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
591 (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
592 ((autodiv ? BWN_ANTAUTO1 : antenna)
593 << BWN_PHY_BBANDCFG_RXANT_SHIFT));
594
595 if (autodiv) {
596 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
597 if (antenna == BWN_ANTAUTO1)
598 tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
599 else
600 tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
601 BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
602 }
603 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
604 if (autodiv)
605 tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
606 else
607 tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
608 BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
609 if (phy->rev >= 2) {
610 BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
611 BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
612 BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
613 (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
614 0x15);
615 if (phy->rev == 2)
616 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
617 else
618 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
619 (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
620 8);
621 }
622 if (phy->rev >= 6)
623 BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
624
625 hf |= BWN_HF_UCODE_ANTDIV_HELPER;
626 bwn_hf_write(mac, hf);
627 }
628
629 int
630 bwn_phy_g_im(struct bwn_mac *mac, int mode)
631 {
632 struct bwn_phy *phy = &mac->mac_phy;
633 struct bwn_phy_g *pg = &phy->phy_g;
634
635 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
636 KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
637
638 if (phy->rev == 0 || !phy->gmode)
639 return (ENODEV);
640
641 pg->pg_aci_wlan_automatic = 0;
642 return (0);
643 }
644
645 bwn_txpwr_result_t
646 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
647 {
648 struct bwn_phy *phy = &mac->mac_phy;
649 struct bwn_phy_g *pg = &phy->phy_g;
650 struct bwn_softc *sc = mac->mac_sc;
651 unsigned int tssi;
652 int cck, ofdm;
653 int power;
654 int rfatt, bbatt;
655 unsigned int max;
656
657 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
658
659 cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
660 ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
661 if (cck < 0 && ofdm < 0) {
662 if (ignore_tssi == 0)
663 return (BWN_TXPWR_RES_DONE);
664 cck = 0;
665 ofdm = 0;
666 }
667 tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
668 if (pg->pg_avgtssi != 0xff)
669 tssi = (tssi + pg->pg_avgtssi) / 2;
670 pg->pg_avgtssi = tssi;
671 KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
672
673 max = pg->pg_pa0maxpwr;
674 if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL)
675 max -= 3;
676 if (max >= 120) {
677 device_printf(sc->sc_dev, "invalid max TX-power value\n");
678 max = 80;
679 pg->pg_pa0maxpwr = max;
680 }
681
682 power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
683 (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
684 tssi, 0x00), 0x3f)]);
685 if (power == 0)
686 return (BWN_TXPWR_RES_DONE);
687
688 rfatt = -((power + 7) / 8);
689 bbatt = (-(power / 2)) - (4 * rfatt);
690 if ((rfatt == 0) && (bbatt == 0))
691 return (BWN_TXPWR_RES_DONE);
692 pg->pg_bbatt_delta = bbatt;
693 pg->pg_rfatt_delta = rfatt;
694 return (BWN_TXPWR_RES_NEED_ADJUST);
695 }
696
697 void
698 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
699 {
700 struct bwn_phy *phy = &mac->mac_phy;
701 struct bwn_phy_g *pg = &phy->phy_g;
702 struct bwn_softc *sc = mac->mac_sc;
703 int rfatt, bbatt;
704 uint8_t txctl;
705
706 bwn_mac_suspend(mac);
707
708 BWN_ASSERT_LOCKED(sc);
709
710 bbatt = pg->pg_bbatt.att;
711 bbatt += pg->pg_bbatt_delta;
712 rfatt = pg->pg_rfatt.att;
713 rfatt += pg->pg_rfatt_delta;
714
715 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
716 txctl = pg->pg_txctl;
717 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
718 if (rfatt <= 1) {
719 if (txctl == 0) {
720 txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
721 rfatt += 2;
722 bbatt += 2;
723 } else if (sc->sc_board_info.board_flags &
724 BHND_BFL_PACTRL) {
725 bbatt += 4 * (rfatt - 2);
726 rfatt = 2;
727 }
728 } else if (rfatt > 4 && txctl) {
729 txctl = 0;
730 if (bbatt < 3) {
731 rfatt -= 3;
732 bbatt += 2;
733 } else {
734 rfatt -= 2;
735 bbatt -= 2;
736 }
737 }
738 }
739 pg->pg_txctl = txctl;
740 bwn_phy_g_setatt(mac, &bbatt, &rfatt);
741 pg->pg_rfatt.att = rfatt;
742 pg->pg_bbatt.att = bbatt;
743
744 DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
745
746 bwn_phy_lock(mac);
747 bwn_rf_lock(mac);
748 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
749 pg->pg_txctl);
750 bwn_rf_unlock(mac);
751 bwn_phy_unlock(mac);
752
753 bwn_mac_enable(mac);
754 }
755
756 void
757 bwn_phy_g_task_15s(struct bwn_mac *mac)
758 {
759 struct bwn_phy *phy = &mac->mac_phy;
760 struct bwn_phy_g *pg = &phy->phy_g;
761 struct bwn_softc *sc = mac->mac_sc;
762 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
763 unsigned long expire, now;
764 struct bwn_lo_calib *cal, *tmp;
765 uint8_t expired = 0;
766
767 bwn_mac_suspend(mac);
768
769 if (lo == NULL)
770 goto fail;
771
772 BWN_GETTIME(now);
773 if (bwn_has_hwpctl(mac)) {
774 expire = now - BWN_LO_PWRVEC_EXPIRE;
775 if (ieee80211_time_before(lo->pwr_vec_read_time, expire)) {
776 bwn_lo_get_powervector(mac);
777 bwn_phy_g_dc_lookup_init(mac, 0);
778 }
779 goto fail;
780 }
781
782 expire = now - BWN_LO_CALIB_EXPIRE;
783 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
784 if (!ieee80211_time_before(cal->calib_time, expire))
785 continue;
786 if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
787 BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
788 KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
789 expired = 1;
790 }
791
792 DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
793 cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
794 cal->ctl.i, cal->ctl.q);
795
796 TAILQ_REMOVE(&lo->calib_list, cal, list);
797 free(cal, M_DEVBUF);
798 }
799 if (expired || TAILQ_EMPTY(&lo->calib_list)) {
800 cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
801 &pg->pg_rfatt);
802 if (cal == NULL) {
803 device_printf(sc->sc_dev,
804 "failed to recalibrate LO\n");
805 goto fail;
806 }
807 TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
808 bwn_lo_write(mac, &cal->ctl);
809 }
810
811 fail:
812 bwn_mac_enable(mac);
813 }
814
815 void
816 bwn_phy_g_task_60s(struct bwn_mac *mac)
817 {
818 struct bwn_phy *phy = &mac->mac_phy;
819 struct bwn_softc *sc = mac->mac_sc;
820 uint8_t old = phy->chan;
821
822 if (!(sc->sc_board_info.board_flags & BHND_BFL_ADCDIV))
823 return;
824
825 bwn_mac_suspend(mac);
826 bwn_nrssi_slope_11g(mac);
827 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
828 bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
829 bwn_switch_channel(mac, old);
830 }
831 bwn_mac_enable(mac);
832 }
833
834 void
835 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
836 {
837
838 BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
839 }
840
841 static void
842 bwn_phy_g_init_sub(struct bwn_mac *mac)
843 {
844 struct bwn_phy *phy = &mac->mac_phy;
845 struct bwn_phy_g *pg = &phy->phy_g;
846 struct bwn_softc *sc = mac->mac_sc;
847 uint16_t i, tmp;
848
849 if (phy->rev == 1)
850 bwn_phy_init_b5(mac);
851 else
852 bwn_phy_init_b6(mac);
853
854 if (phy->rev >= 2 || phy->gmode)
855 bwn_phy_init_a(mac);
856
857 if (phy->rev >= 2) {
858 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
859 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
860 }
861 if (phy->rev == 2) {
862 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
863 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
864 }
865 if (phy->rev > 5) {
866 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
867 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
868 }
869 if (phy->gmode || phy->rev >= 2) {
870 tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
871 tmp &= BWN_PHYVER_VERSION;
872 if (tmp == 3 || tmp == 5) {
873 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
874 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
875 }
876 if (tmp == 5) {
877 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
878 0x1f00);
879 }
880 }
881 if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
882 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
883 if (phy->rf_rev == 8) {
884 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
885 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
886 }
887 if (BWN_HAS_LOOPBACK(phy))
888 bwn_loopback_calcgain(mac);
889
890 if (phy->rf_rev != 8) {
891 if (pg->pg_initval == 0xffff)
892 pg->pg_initval = bwn_rf_init_bcm2050(mac);
893 else
894 BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
895 }
896 bwn_lo_g_init(mac);
897 if (BWN_HAS_TXMAG(phy)) {
898 BWN_RF_WRITE(mac, 0x52,
899 (BWN_RF_READ(mac, 0x52) & 0xff00)
900 | pg->pg_loctl.tx_bias |
901 pg->pg_loctl.tx_magn);
902 } else {
903 BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
904 }
905 if (phy->rev >= 6) {
906 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
907 (pg->pg_loctl.tx_bias << 12));
908 }
909 if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL)
910 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
911 else
912 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
913 if (phy->rev < 2)
914 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
915 else
916 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
917 if (phy->gmode || phy->rev >= 2) {
918 bwn_lo_g_adjust(mac);
919 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
920 }
921
922 if (!(sc->sc_board_info.board_flags & BHND_BFL_ADCDIV)) {
923 for (i = 0; i < 64; i++) {
924 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
925 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
926 (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
927 -32), 31));
928 }
929 bwn_nrssi_threshold(mac);
930 } else if (phy->gmode || phy->rev >= 2) {
931 if (pg->pg_nrssi[0] == -1000) {
932 KASSERT(pg->pg_nrssi[1] == -1000,
933 ("%s:%d: fail", __func__, __LINE__));
934 bwn_nrssi_slope_11g(mac);
935 } else
936 bwn_nrssi_threshold(mac);
937 }
938 if (phy->rf_rev == 8)
939 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
940 bwn_phy_hwpctl_init(mac);
941 if ((sc->sc_cid.chip_id == BHND_CHIPID_BCM4306
942 && sc->sc_cid.chip_pkg == 2) || 0) {
943 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
944 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
945 }
946 }
947
948 static void
949 bwn_phy_init_b5(struct bwn_mac *mac)
950 {
951 struct bwn_phy *phy = &mac->mac_phy;
952 struct bwn_phy_g *pg = &phy->phy_g;
953 struct bwn_softc *sc = mac->mac_sc;
954 uint16_t offset, value;
955 uint8_t old_channel;
956
957 if (phy->analog == 1)
958 BWN_RF_SET(mac, 0x007a, 0x0050);
959 if ((sc->sc_board_info.board_vendor != PCI_VENDOR_BROADCOM) &&
960 (sc->sc_board_info.board_type != BHND_BOARD_BU4306)) {
961 value = 0x2120;
962 for (offset = 0x00a8; offset < 0x00c7; offset++) {
963 BWN_PHY_WRITE(mac, offset, value);
964 value += 0x202;
965 }
966 }
967 BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
968 if (phy->rf_ver == 0x2050)
969 BWN_PHY_WRITE(mac, 0x0038, 0x0667);
970
971 if (phy->gmode || phy->rev >= 2) {
972 if (phy->rf_ver == 0x2050) {
973 BWN_RF_SET(mac, 0x007a, 0x0020);
974 BWN_RF_SET(mac, 0x0051, 0x0004);
975 }
976 BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
977
978 BWN_PHY_SET(mac, 0x0802, 0x0100);
979 BWN_PHY_SET(mac, 0x042b, 0x2000);
980
981 BWN_PHY_WRITE(mac, 0x001c, 0x186a);
982
983 BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
984 BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
985 BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
986 }
987
988 if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
989 BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
990
991 if (phy->analog == 1) {
992 BWN_PHY_WRITE(mac, 0x0026, 0xce00);
993 BWN_PHY_WRITE(mac, 0x0021, 0x3763);
994 BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
995 BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
996 BWN_PHY_WRITE(mac, 0x0024, 0x037e);
997 } else
998 BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
999 BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
1000 BWN_WRITE_2(mac, 0x03ec, 0x3f22);
1001
1002 if (phy->analog == 1)
1003 BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
1004 else
1005 BWN_PHY_WRITE(mac, 0x0020, 0x301c);
1006
1007 if (phy->analog == 0)
1008 BWN_WRITE_2(mac, 0x03e4, 0x3000);
1009
1010 old_channel = phy->chan;
1011 bwn_phy_g_switch_chan(mac, 7, 0);
1012
1013 if (phy->rf_ver != 0x2050) {
1014 BWN_RF_WRITE(mac, 0x0075, 0x0080);
1015 BWN_RF_WRITE(mac, 0x0079, 0x0081);
1016 }
1017
1018 BWN_RF_WRITE(mac, 0x0050, 0x0020);
1019 BWN_RF_WRITE(mac, 0x0050, 0x0023);
1020
1021 if (phy->rf_ver == 0x2050) {
1022 BWN_RF_WRITE(mac, 0x0050, 0x0020);
1023 BWN_RF_WRITE(mac, 0x005a, 0x0070);
1024 }
1025
1026 BWN_RF_WRITE(mac, 0x005b, 0x007b);
1027 BWN_RF_WRITE(mac, 0x005c, 0x00b0);
1028 BWN_RF_SET(mac, 0x007a, 0x0007);
1029
1030 bwn_phy_g_switch_chan(mac, old_channel, 0);
1031 BWN_PHY_WRITE(mac, 0x0014, 0x0080);
1032 BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
1033 BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
1034
1035 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
1036 pg->pg_txctl);
1037
1038 if (phy->rf_ver == 0x2050)
1039 BWN_RF_WRITE(mac, 0x005d, 0x000d);
1040
1041 BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
1042 }
1043
1044 static void
1045 bwn_loopback_calcgain(struct bwn_mac *mac)
1046 {
1047 struct bwn_phy *phy = &mac->mac_phy;
1048 struct bwn_phy_g *pg = &phy->phy_g;
1049 struct bwn_softc *sc = mac->mac_sc;
1050 uint16_t backup_phy[16] = { 0 };
1051 uint16_t backup_radio[3];
1052 uint16_t backup_bband;
1053 uint16_t i, j, loop_i_max;
1054 uint16_t trsw_rx;
1055 uint16_t loop1_outer_done, loop1_inner_done;
1056
1057 backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
1058 backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
1059 backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
1060 backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
1061 if (phy->rev != 1) {
1062 backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
1063 backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
1064 }
1065 backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
1066 backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
1067 backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
1068 backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
1069 backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
1070 backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
1071 backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
1072 backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
1073 backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
1074 backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1075 backup_bband = pg->pg_bbatt.att;
1076 backup_radio[0] = BWN_RF_READ(mac, 0x52);
1077 backup_radio[1] = BWN_RF_READ(mac, 0x43);
1078 backup_radio[2] = BWN_RF_READ(mac, 0x7a);
1079
1080 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
1081 BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
1082 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
1083 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
1084 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
1085 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
1086 if (phy->rev != 1) {
1087 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
1088 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
1089 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
1090 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
1091 }
1092 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
1093 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
1094 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
1095 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
1096
1097 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
1098 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1099 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1100
1101 BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
1102 if (phy->rev != 1) {
1103 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
1104 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
1105 }
1106 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
1107
1108 if (phy->rf_rev == 8)
1109 BWN_RF_WRITE(mac, 0x43, 0x000f);
1110 else {
1111 BWN_RF_WRITE(mac, 0x52, 0);
1112 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
1113 }
1114 bwn_phy_g_set_bbatt(mac, 11);
1115
1116 if (phy->rev >= 3)
1117 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
1118 else
1119 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
1120 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
1121
1122 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
1123 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
1124
1125 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
1126 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
1127
1128 if (sc->sc_board_info.board_flags & BHND_BFL_EXTLNA) {
1129 if (phy->rev >= 7) {
1130 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
1131 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
1132 }
1133 }
1134 BWN_RF_MASK(mac, 0x7a, 0x00f7);
1135
1136 j = 0;
1137 loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
1138 for (i = 0; i < loop_i_max; i++) {
1139 for (j = 0; j < 16; j++) {
1140 BWN_RF_WRITE(mac, 0x43, i);
1141 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
1142 (j << 8));
1143 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
1144 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
1145 DELAY(20);
1146 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
1147 goto done0;
1148 }
1149 }
1150 done0:
1151 loop1_outer_done = i;
1152 loop1_inner_done = j;
1153 if (j >= 8) {
1154 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
1155 trsw_rx = 0x1b;
1156 for (j = j - 8; j < 16; j++) {
1157 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
1158 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
1159 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
1160 DELAY(20);
1161 trsw_rx -= 3;
1162 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
1163 goto done1;
1164 }
1165 } else
1166 trsw_rx = 0x18;
1167 done1:
1168
1169 if (phy->rev != 1) {
1170 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
1171 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
1172 }
1173 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
1174 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
1175 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
1176 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
1177 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
1178 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
1179 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
1180 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
1181 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
1182
1183 bwn_phy_g_set_bbatt(mac, backup_bband);
1184
1185 BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
1186 BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
1187 BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
1188
1189 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
1190 DELAY(10);
1191 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
1192 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
1193 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
1194 BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
1195
1196 pg->pg_max_lb_gain =
1197 ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
1198 pg->pg_trsw_rx_gain = trsw_rx * 2;
1199 }
1200
1201 static uint16_t
1202 bwn_rf_init_bcm2050(struct bwn_mac *mac)
1203 {
1204 struct bwn_phy *phy = &mac->mac_phy;
1205 uint32_t tmp1 = 0, tmp2 = 0;
1206 uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
1207 analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
1208 radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
1209 static const uint8_t rcc_table[] = {
1210 0x02, 0x03, 0x01, 0x0f,
1211 0x06, 0x07, 0x05, 0x0f,
1212 0x0a, 0x0b, 0x09, 0x0f,
1213 0x0e, 0x0f, 0x0d, 0x0f,
1214 };
1215
1216 loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
1217 rfoverval = rfover = cck3 = 0;
1218 radio0 = BWN_RF_READ(mac, 0x43);
1219 radio1 = BWN_RF_READ(mac, 0x51);
1220 radio2 = BWN_RF_READ(mac, 0x52);
1221 pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
1222 cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
1223 cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
1224 cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
1225
1226 if (phy->type == BWN_PHYTYPE_B) {
1227 cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
1228 reg0 = BWN_READ_2(mac, 0x3ec);
1229
1230 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
1231 BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
1232 } else if (phy->gmode || phy->rev >= 2) {
1233 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
1234 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
1235 analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
1236 analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
1237 crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
1238 classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
1239
1240 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
1241 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
1242 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
1243 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
1244 if (BWN_HAS_LOOPBACK(phy)) {
1245 lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
1246 loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
1247 if (phy->rev >= 3)
1248 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
1249 else
1250 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
1251 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
1252 }
1253
1254 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1255 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1256 BWN_LPD(0, 1, 1)));
1257 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
1258 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
1259 }
1260 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
1261
1262 syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
1263 BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
1264 reg1 = BWN_READ_2(mac, 0x3e6);
1265 reg2 = BWN_READ_2(mac, 0x3f4);
1266
1267 if (phy->analog == 0)
1268 BWN_WRITE_2(mac, 0x03e6, 0x0122);
1269 else {
1270 if (phy->analog >= 2)
1271 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
1272 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
1273 (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
1274 }
1275
1276 reg = BWN_RF_READ(mac, 0x60);
1277 index = (reg & 0x001e) >> 1;
1278 rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
1279
1280 if (phy->type == BWN_PHYTYPE_B)
1281 BWN_RF_WRITE(mac, 0x78, 0x26);
1282 if (phy->gmode || phy->rev >= 2) {
1283 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1284 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1285 BWN_LPD(0, 1, 1)));
1286 }
1287 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
1288 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
1289 if (phy->gmode || phy->rev >= 2) {
1290 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1291 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
1292 BWN_LPD(0, 0, 1)));
1293 }
1294 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
1295 BWN_RF_SET(mac, 0x51, 0x0004);
1296 if (phy->rf_rev == 8)
1297 BWN_RF_WRITE(mac, 0x43, 0x1f);
1298 else {
1299 BWN_RF_WRITE(mac, 0x52, 0);
1300 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
1301 }
1302 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1303
1304 for (i = 0; i < 16; i++) {
1305 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
1306 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1307 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1308 if (phy->gmode || phy->rev >= 2) {
1309 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1310 bwn_rf_2050_rfoverval(mac,
1311 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1312 }
1313 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1314 DELAY(10);
1315 if (phy->gmode || phy->rev >= 2) {
1316 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1317 bwn_rf_2050_rfoverval(mac,
1318 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1319 }
1320 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
1321 DELAY(10);
1322 if (phy->gmode || phy->rev >= 2) {
1323 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1324 bwn_rf_2050_rfoverval(mac,
1325 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
1326 }
1327 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
1328 DELAY(20);
1329 tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1330 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1331 if (phy->gmode || phy->rev >= 2) {
1332 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1333 bwn_rf_2050_rfoverval(mac,
1334 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1335 }
1336 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1337 }
1338 DELAY(10);
1339
1340 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1341 tmp1++;
1342 tmp1 >>= 9;
1343
1344 for (i = 0; i < 16; i++) {
1345 radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
1346 BWN_RF_WRITE(mac, 0x78, radio78);
1347 DELAY(10);
1348 for (j = 0; j < 16; j++) {
1349 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
1350 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
1351 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
1352 if (phy->gmode || phy->rev >= 2) {
1353 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1354 bwn_rf_2050_rfoverval(mac,
1355 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1356 }
1357 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1358 DELAY(10);
1359 if (phy->gmode || phy->rev >= 2) {
1360 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1361 bwn_rf_2050_rfoverval(mac,
1362 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1363 }
1364 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
1365 DELAY(10);
1366 if (phy->gmode || phy->rev >= 2) {
1367 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1368 bwn_rf_2050_rfoverval(mac,
1369 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
1370 }
1371 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
1372 DELAY(10);
1373 tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1374 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
1375 if (phy->gmode || phy->rev >= 2) {
1376 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
1377 bwn_rf_2050_rfoverval(mac,
1378 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
1379 }
1380 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
1381 }
1382 tmp2++;
1383 tmp2 >>= 8;
1384 if (tmp1 < tmp2)
1385 break;
1386 }
1387
1388 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
1389 BWN_RF_WRITE(mac, 0x51, radio1);
1390 BWN_RF_WRITE(mac, 0x52, radio2);
1391 BWN_RF_WRITE(mac, 0x43, radio0);
1392 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
1393 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
1394 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
1395 BWN_WRITE_2(mac, 0x3e6, reg1);
1396 if (phy->analog != 0)
1397 BWN_WRITE_2(mac, 0x3f4, reg2);
1398 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
1399 bwn_spu_workaround(mac, phy->chan);
1400 if (phy->type == BWN_PHYTYPE_B) {
1401 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
1402 BWN_WRITE_2(mac, 0x3ec, reg0);
1403 } else if (phy->gmode) {
1404 BWN_WRITE_2(mac, BWN_PHY_RADIO,
1405 BWN_READ_2(mac, BWN_PHY_RADIO)
1406 & 0x7fff);
1407 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
1408 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
1409 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
1410 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
1411 analogoverval);
1412 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
1413 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
1414 if (BWN_HAS_LOOPBACK(phy)) {
1415 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
1416 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
1417 }
1418 }
1419
1420 return ((i > 15) ? radio78 : rcc);
1421 }
1422
1423 static void
1424 bwn_phy_init_b6(struct bwn_mac *mac)
1425 {
1426 struct bwn_phy *phy = &mac->mac_phy;
1427 struct bwn_phy_g *pg = &phy->phy_g;
1428 struct bwn_softc *sc = mac->mac_sc;
1429 uint16_t offset, val;
1430 uint8_t old_channel;
1431
1432 KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
1433 ("%s:%d: fail", __func__, __LINE__));
1434
1435 BWN_PHY_WRITE(mac, 0x003e, 0x817a);
1436 BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
1437 if (phy->rf_rev == 4 || phy->rf_rev == 5) {
1438 BWN_RF_WRITE(mac, 0x51, 0x37);
1439 BWN_RF_WRITE(mac, 0x52, 0x70);
1440 BWN_RF_WRITE(mac, 0x53, 0xb3);
1441 BWN_RF_WRITE(mac, 0x54, 0x9b);
1442 BWN_RF_WRITE(mac, 0x5a, 0x88);
1443 BWN_RF_WRITE(mac, 0x5b, 0x88);
1444 BWN_RF_WRITE(mac, 0x5d, 0x88);
1445 BWN_RF_WRITE(mac, 0x5e, 0x88);
1446 BWN_RF_WRITE(mac, 0x7d, 0x88);
1447 bwn_hf_write(mac,
1448 bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
1449 }
1450 if (phy->rf_rev == 8) {
1451 BWN_RF_WRITE(mac, 0x51, 0);
1452 BWN_RF_WRITE(mac, 0x52, 0x40);
1453 BWN_RF_WRITE(mac, 0x53, 0xb7);
1454 BWN_RF_WRITE(mac, 0x54, 0x98);
1455 BWN_RF_WRITE(mac, 0x5a, 0x88);
1456 BWN_RF_WRITE(mac, 0x5b, 0x6b);
1457 BWN_RF_WRITE(mac, 0x5c, 0x0f);
1458 if (sc->sc_board_info.board_flags & BHND_BFL_ALTIQ) {
1459 BWN_RF_WRITE(mac, 0x5d, 0xfa);
1460 BWN_RF_WRITE(mac, 0x5e, 0xd8);
1461 } else {
1462 BWN_RF_WRITE(mac, 0x5d, 0xf5);
1463 BWN_RF_WRITE(mac, 0x5e, 0xb8);
1464 }
1465 BWN_RF_WRITE(mac, 0x0073, 0x0003);
1466 BWN_RF_WRITE(mac, 0x007d, 0x00a8);
1467 BWN_RF_WRITE(mac, 0x007c, 0x0001);
1468 BWN_RF_WRITE(mac, 0x007e, 0x0008);
1469 }
1470 for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
1471 BWN_PHY_WRITE(mac, offset, val);
1472 val -= 0x0202;
1473 }
1474 for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
1475 BWN_PHY_WRITE(mac, offset, val);
1476 val -= 0x0202;
1477 }
1478 for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
1479 BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
1480 val += 0x0202;
1481 }
1482 if (phy->type == BWN_PHYTYPE_G) {
1483 BWN_RF_SET(mac, 0x007a, 0x0020);
1484 BWN_RF_SET(mac, 0x0051, 0x0004);
1485 BWN_PHY_SET(mac, 0x0802, 0x0100);
1486 BWN_PHY_SET(mac, 0x042b, 0x2000);
1487 BWN_PHY_WRITE(mac, 0x5b, 0);
1488 BWN_PHY_WRITE(mac, 0x5c, 0);
1489 }
1490
1491 old_channel = phy->chan;
1492 bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
1493
1494 BWN_RF_WRITE(mac, 0x0050, 0x0020);
1495 BWN_RF_WRITE(mac, 0x0050, 0x0023);
1496 DELAY(40);
1497 if (phy->rf_rev < 6 || phy->rf_rev == 8) {
1498 BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
1499 BWN_RF_WRITE(mac, 0x50, 0x20);
1500 }
1501 if (phy->rf_rev <= 2) {
1502 BWN_RF_WRITE(mac, 0x7c, 0x20);
1503 BWN_RF_WRITE(mac, 0x5a, 0x70);
1504 BWN_RF_WRITE(mac, 0x5b, 0x7b);
1505 BWN_RF_WRITE(mac, 0x5c, 0xb0);
1506 }
1507 BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
1508
1509 bwn_phy_g_switch_chan(mac, old_channel, 0);
1510
1511 BWN_PHY_WRITE(mac, 0x0014, 0x0200);
1512 if (phy->rf_rev >= 6)
1513 BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
1514 else
1515 BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
1516 BWN_PHY_WRITE(mac, 0x0038, 0x0668);
1517 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
1518 pg->pg_txctl);
1519 if (phy->rf_rev <= 5)
1520 BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
1521 if (phy->rf_rev <= 2)
1522 BWN_RF_WRITE(mac, 0x005d, 0x000d);
1523
1524 if (phy->analog == 4) {
1525 BWN_WRITE_2(mac, 0x3e4, 9);
1526 BWN_PHY_MASK(mac, 0x61, 0x0fff);
1527 } else
1528 BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
1529 if (phy->type == BWN_PHYTYPE_B)
1530 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1531 else if (phy->type == BWN_PHYTYPE_G)
1532 BWN_WRITE_2(mac, 0x03e6, 0x0);
1533 }
1534
1535 static void
1536 bwn_phy_init_a(struct bwn_mac *mac)
1537 {
1538 struct bwn_phy *phy = &mac->mac_phy;
1539 struct bwn_softc *sc = mac->mac_sc;
1540
1541 KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
1542 ("%s:%d: fail", __func__, __LINE__));
1543
1544 if (phy->rev >= 6) {
1545 if (phy->type == BWN_PHYTYPE_A)
1546 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
1547 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
1548 BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
1549 else
1550 BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
1551 }
1552
1553 bwn_wa_init(mac);
1554
1555 if (phy->type == BWN_PHYTYPE_G &&
1556 (sc->sc_board_info.board_flags & BHND_BFL_PACTRL))
1557 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
1558 }
1559
1560 static void
1561 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
1562 {
1563 int i;
1564
1565 for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
1566 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
1567 }
1568
1569 static void
1570 bwn_wa_agc(struct bwn_mac *mac)
1571 {
1572 struct bwn_phy *phy = &mac->mac_phy;
1573
1574 if (phy->rev == 1) {
1575 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
1576 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
1577 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
1578 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
1579 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
1580 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
1581 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
1582 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
1583 BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
1584 } else {
1585 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
1586 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
1587 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
1588 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
1589 }
1590
1591 BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
1592 0x5700);
1593 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
1594 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
1595 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
1596 BWN_RF_SET(mac, 0x7a, 0x0008);
1597 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
1598 BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
1599 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
1600 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
1601 if (phy->rev == 1)
1602 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
1603 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
1604 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
1605 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
1606 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
1607 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
1608 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
1609 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
1610 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
1611 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
1612 if (phy->rev == 1) {
1613 BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
1614 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
1615 } else {
1616 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
1617 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
1618 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
1619 if (phy->rev >= 6) {
1620 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
1621 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
1622 (uint16_t)~0xf000, 0x3000);
1623 }
1624 }
1625 BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
1626 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
1627 if (phy->rev == 1) {
1628 BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
1629 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
1630 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
1631 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
1632 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
1633 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
1634 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
1635 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
1636 } else {
1637 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
1638 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
1639 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
1640 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
1641 }
1642 if (phy->rev >= 6) {
1643 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
1644 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
1645 }
1646 BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
1647 }
1648
1649 static void
1650 bwn_wa_grev1(struct bwn_mac *mac)
1651 {
1652 struct bwn_phy *phy = &mac->mac_phy;
1653 int i;
1654 static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
1655 static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
1656 static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
1657
1658 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1659
1660 /* init CRSTHRES and ANTDWELL */
1661 if (phy->rev == 1) {
1662 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
1663 } else if (phy->rev == 2) {
1664 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
1665 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
1666 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1667 } else {
1668 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
1669 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
1670 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
1671 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1672 }
1673 BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
1674 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
1675 BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
1676
1677 /* XXX support PHY-A??? */
1678 for (i = 0; i < N(bwn_tab_finefreqg); i++)
1679 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
1680 bwn_tab_finefreqg[i]);
1681
1682 /* XXX support PHY-A??? */
1683 if (phy->rev == 1)
1684 for (i = 0; i < N(bwn_tab_noise_g1); i++)
1685 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1686 bwn_tab_noise_g1[i]);
1687 else
1688 for (i = 0; i < N(bwn_tab_noise_g2); i++)
1689 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1690 bwn_tab_noise_g2[i]);
1691
1692 for (i = 0; i < N(bwn_tab_rotor); i++)
1693 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
1694 bwn_tab_rotor[i]);
1695
1696 /* XXX support PHY-A??? */
1697 if (phy->rev >= 6) {
1698 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
1699 BWN_PHY_ENCORE_EN)
1700 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
1701 else
1702 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
1703 } else
1704 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
1705
1706 for (i = 0; i < N(bwn_tab_retard); i++)
1707 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
1708 bwn_tab_retard[i]);
1709
1710 if (phy->rev == 1) {
1711 for (i = 0; i < 16; i++)
1712 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
1713 i, 0x0020);
1714 } else {
1715 for (i = 0; i < 32; i++)
1716 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
1717 }
1718
1719 bwn_wa_agc(mac);
1720 }
1721
1722 static void
1723 bwn_wa_grev26789(struct bwn_mac *mac)
1724 {
1725 struct bwn_phy *phy = &mac->mac_phy;
1726 int i;
1727 static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
1728 uint16_t ofdmrev;
1729
1730 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1731
1732 bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
1733
1734 /* init CRSTHRES and ANTDWELL */
1735 if (phy->rev == 1)
1736 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
1737 else if (phy->rev == 2) {
1738 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
1739 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
1740 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1741 } else {
1742 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
1743 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
1744 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
1745 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
1746 }
1747
1748 for (i = 0; i < 64; i++)
1749 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
1750
1751 /* XXX support PHY-A??? */
1752 if (phy->rev == 1)
1753 for (i = 0; i < N(bwn_tab_noise_g1); i++)
1754 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1755 bwn_tab_noise_g1[i]);
1756 else
1757 for (i = 0; i < N(bwn_tab_noise_g2); i++)
1758 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
1759 bwn_tab_noise_g2[i]);
1760
1761 /* XXX support PHY-A??? */
1762 if (phy->rev >= 6) {
1763 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
1764 BWN_PHY_ENCORE_EN)
1765 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
1766 else
1767 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
1768 } else
1769 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
1770
1771 for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
1772 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
1773 bwn_tab_sigmasqr2[i]);
1774
1775 if (phy->rev == 1) {
1776 for (i = 0; i < 16; i++)
1777 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
1778 0x0020);
1779 } else {
1780 for (i = 0; i < 32; i++)
1781 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
1782 }
1783
1784 bwn_wa_agc(mac);
1785
1786 ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
1787 if (ofdmrev > 2) {
1788 if (phy->type == BWN_PHYTYPE_A)
1789 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
1790 else
1791 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
1792 } else {
1793 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
1794 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
1795 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
1796 }
1797
1798 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
1799 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
1800 }
1801
1802 static void
1803 bwn_wa_init(struct bwn_mac *mac)
1804 {
1805 struct bwn_phy *phy = &mac->mac_phy;
1806 struct bwn_softc *sc = mac->mac_sc;
1807
1808 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
1809
1810 switch (phy->rev) {
1811 case 1:
1812 bwn_wa_grev1(mac);
1813 break;
1814 case 2:
1815 case 6:
1816 case 7:
1817 case 8:
1818 case 9:
1819 bwn_wa_grev26789(mac);
1820 break;
1821 default:
1822 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1823 }
1824
1825 if (sc->sc_board_info.board_vendor != PCI_VENDOR_BROADCOM ||
1826 sc->sc_board_info.board_type != BHND_BOARD_BU4306 ||
1827 sc->sc_board_info.board_rev != 0x17) {
1828 if (phy->rev < 2) {
1829 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
1830 0x0002);
1831 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
1832 0x0001);
1833 } else {
1834 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
1835 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
1836 if ((sc->sc_board_info.board_flags &
1837 BHND_BFL_EXTLNA) &&
1838 (phy->rev >= 7)) {
1839 BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
1840 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1841 0x0020, 0x0001);
1842 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1843 0x0021, 0x0001);
1844 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1845 0x0022, 0x0001);
1846 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1847 0x0023, 0x0000);
1848 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1849 0x0000, 0x0000);
1850 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
1851 0x0003, 0x0002);
1852 }
1853 }
1854 }
1855 if (sc->sc_board_info.board_flags & BHND_BFL_FEM) {
1856 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
1857 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
1858 }
1859
1860 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
1861 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
1862 }
1863
1864 static void
1865 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1866 uint16_t value)
1867 {
1868 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
1869 uint16_t addr;
1870
1871 addr = table + offset;
1872 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
1873 (addr - 1 != pg->pg_ofdmtab_addr)) {
1874 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
1875 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
1876 }
1877 pg->pg_ofdmtab_addr = addr;
1878 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
1879 }
1880
1881 static void
1882 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1883 uint32_t value)
1884 {
1885 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
1886 uint16_t addr;
1887
1888 addr = table + offset;
1889 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
1890 (addr - 1 != pg->pg_ofdmtab_addr)) {
1891 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
1892 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
1893 }
1894 pg->pg_ofdmtab_addr = addr;
1895
1896 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
1897 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
1898 }
1899
1900 static void
1901 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
1902 uint16_t value)
1903 {
1904
1905 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
1906 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
1907 }
1908
1909 static void
1910 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
1911 {
1912 uint16_t value;
1913
1914 KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
1915 ("%s:%d: fail", __func__, __LINE__));
1916
1917 value = (uint8_t) (ctl->q);
1918 value |= ((uint8_t) (ctl->i)) << 8;
1919 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
1920 }
1921
1922 static uint16_t
1923 bwn_lo_calcfeed(struct bwn_mac *mac,
1924 uint16_t lna, uint16_t pga, uint16_t trsw_rx)
1925 {
1926 struct bwn_phy *phy = &mac->mac_phy;
1927 struct bwn_softc *sc = mac->mac_sc;
1928 uint16_t rfover;
1929 uint16_t feedthrough;
1930
1931 if (phy->gmode) {
1932 lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
1933 pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
1934
1935 KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
1936 ("%s:%d: fail", __func__, __LINE__));
1937 KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
1938 ("%s:%d: fail", __func__, __LINE__));
1939
1940 trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
1941
1942 rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
1943 if ((sc->sc_board_info.board_flags & BHND_BFL_EXTLNA) &&
1944 phy->rev > 6)
1945 rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
1946
1947 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
1948 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1949 DELAY(10);
1950 rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
1951 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1952 DELAY(10);
1953 rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
1954 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
1955 DELAY(10);
1956 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
1957 } else {
1958 pga |= BWN_PHY_PGACTL_UNKNOWN;
1959 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1960 DELAY(10);
1961 pga |= BWN_PHY_PGACTL_LOWBANDW;
1962 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1963 DELAY(10);
1964 pga |= BWN_PHY_PGACTL_LPF;
1965 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
1966 }
1967 DELAY(21);
1968 feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
1969
1970 return (feedthrough);
1971 }
1972
1973 static uint16_t
1974 bwn_lo_txctl_regtable(struct bwn_mac *mac,
1975 uint16_t *value, uint16_t *pad_mix_gain)
1976 {
1977 struct bwn_phy *phy = &mac->mac_phy;
1978 uint16_t reg, v, padmix;
1979
1980 if (phy->type == BWN_PHYTYPE_B) {
1981 v = 0x30;
1982 if (phy->rf_rev <= 5) {
1983 reg = 0x43;
1984 padmix = 0;
1985 } else {
1986 reg = 0x52;
1987 padmix = 5;
1988 }
1989 } else {
1990 if (phy->rev >= 2 && phy->rf_rev == 8) {
1991 reg = 0x43;
1992 v = 0x10;
1993 padmix = 2;
1994 } else {
1995 reg = 0x52;
1996 v = 0x30;
1997 padmix = 5;
1998 }
1999 }
2000 if (value)
2001 *value = v;
2002 if (pad_mix_gain)
2003 *pad_mix_gain = padmix;
2004
2005 return (reg);
2006 }
2007
2008 static void
2009 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
2010 {
2011 struct bwn_phy *phy = &mac->mac_phy;
2012 struct bwn_phy_g *pg = &phy->phy_g;
2013 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2014 uint16_t reg, mask;
2015 uint16_t trsw_rx, pga;
2016 uint16_t rf_pctl_reg;
2017
2018 static const uint8_t tx_bias_values[] = {
2019 0x09, 0x08, 0x0a, 0x01, 0x00,
2020 0x02, 0x05, 0x04, 0x06,
2021 };
2022 static const uint8_t tx_magn_values[] = {
2023 0x70, 0x40,
2024 };
2025
2026 if (!BWN_HAS_LOOPBACK(phy)) {
2027 rf_pctl_reg = 6;
2028 trsw_rx = 2;
2029 pga = 0;
2030 } else {
2031 int lb_gain;
2032
2033 trsw_rx = 0;
2034 lb_gain = pg->pg_max_lb_gain / 2;
2035 if (lb_gain > 10) {
2036 rf_pctl_reg = 0;
2037 pga = abs(10 - lb_gain) / 6;
2038 pga = MIN(MAX(pga, 0), 15);
2039 } else {
2040 int cmp_val;
2041 int tmp;
2042
2043 pga = 0;
2044 cmp_val = 0x24;
2045 if ((phy->rev >= 2) &&
2046 (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
2047 cmp_val = 0x3c;
2048 tmp = lb_gain;
2049 if ((10 - lb_gain) < cmp_val)
2050 tmp = (10 - lb_gain);
2051 if (tmp < 0)
2052 tmp += 6;
2053 else
2054 tmp += 3;
2055 cmp_val /= 4;
2056 tmp /= 4;
2057 if (tmp >= cmp_val)
2058 rf_pctl_reg = cmp_val;
2059 else
2060 rf_pctl_reg = tmp;
2061 }
2062 }
2063 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
2064 bwn_phy_g_set_bbatt(mac, 2);
2065
2066 reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
2067 mask = ~mask;
2068 BWN_RF_MASK(mac, reg, mask);
2069
2070 if (BWN_HAS_TXMAG(phy)) {
2071 int i, j;
2072 int feedthrough;
2073 int min_feedth = 0xffff;
2074 uint8_t tx_magn, tx_bias;
2075
2076 for (i = 0; i < N(tx_magn_values); i++) {
2077 tx_magn = tx_magn_values[i];
2078 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
2079 for (j = 0; j < N(tx_bias_values); j++) {
2080 tx_bias = tx_bias_values[j];
2081 BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
2082 feedthrough = bwn_lo_calcfeed(mac, 0, pga,
2083 trsw_rx);
2084 if (feedthrough < min_feedth) {
2085 lo->tx_bias = tx_bias;
2086 lo->tx_magn = tx_magn;
2087 min_feedth = feedthrough;
2088 }
2089 if (lo->tx_bias == 0)
2090 break;
2091 }
2092 BWN_RF_WRITE(mac, 0x52,
2093 (BWN_RF_READ(mac, 0x52)
2094 & 0xff00) | lo->tx_bias | lo->
2095 tx_magn);
2096 }
2097 } else {
2098 lo->tx_magn = 0;
2099 lo->tx_bias = 0;
2100 BWN_RF_MASK(mac, 0x52, 0xfff0);
2101 }
2102
2103 BWN_GETTIME(lo->txctl_measured_time);
2104 }
2105
2106 static void
2107 bwn_lo_get_powervector(struct bwn_mac *mac)
2108 {
2109 struct bwn_phy *phy = &mac->mac_phy;
2110 struct bwn_phy_g *pg = &phy->phy_g;
2111 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2112 int i;
2113 uint64_t tmp;
2114 uint64_t power_vector = 0;
2115
2116 for (i = 0; i < 8; i += 2) {
2117 tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
2118 power_vector |= (tmp << (i * 8));
2119 bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
2120 }
2121 if (power_vector)
2122 lo->power_vector = power_vector;
2123
2124 BWN_GETTIME(lo->pwr_vec_read_time);
2125 }
2126
2127 static void
2128 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
2129 int use_trsw_rx)
2130 {
2131 struct bwn_phy *phy = &mac->mac_phy;
2132 struct bwn_phy_g *pg = &phy->phy_g;
2133 uint16_t tmp;
2134
2135 if (max_rx_gain < 0)
2136 max_rx_gain = 0;
2137
2138 if (BWN_HAS_LOOPBACK(phy)) {
2139 int trsw_rx_gain;
2140
2141 if (use_trsw_rx) {
2142 trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
2143 if (max_rx_gain >= trsw_rx_gain) {
2144 trsw_rx_gain = max_rx_gain - trsw_rx_gain;
2145 }
2146 } else
2147 trsw_rx_gain = max_rx_gain;
2148 if (trsw_rx_gain < 9) {
2149 pg->pg_lna_lod_gain = 0;
2150 } else {
2151 pg->pg_lna_lod_gain = 1;
2152 trsw_rx_gain -= 8;
2153 }
2154 trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
2155 pg->pg_pga_gain = trsw_rx_gain / 3;
2156 if (pg->pg_pga_gain >= 5) {
2157 pg->pg_pga_gain -= 5;
2158 pg->pg_lna_gain = 2;
2159 } else
2160 pg->pg_lna_gain = 0;
2161 } else {
2162 pg->pg_lna_gain = 0;
2163 pg->pg_trsw_rx_gain = 0x20;
2164 if (max_rx_gain >= 0x14) {
2165 pg->pg_lna_lod_gain = 1;
2166 pg->pg_pga_gain = 2;
2167 } else if (max_rx_gain >= 0x12) {
2168 pg->pg_lna_lod_gain = 1;
2169 pg->pg_pga_gain = 1;
2170 } else if (max_rx_gain >= 0xf) {
2171 pg->pg_lna_lod_gain = 1;
2172 pg->pg_pga_gain = 0;
2173 } else {
2174 pg->pg_lna_lod_gain = 0;
2175 pg->pg_pga_gain = 0;
2176 }
2177 }
2178
2179 tmp = BWN_RF_READ(mac, 0x7a);
2180 if (pg->pg_lna_lod_gain == 0)
2181 tmp &= ~0x0008;
2182 else
2183 tmp |= 0x0008;
2184 BWN_RF_WRITE(mac, 0x7a, tmp);
2185 }
2186
2187 static void
2188 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
2189 {
2190 struct bwn_phy *phy = &mac->mac_phy;
2191 struct bwn_phy_g *pg = &phy->phy_g;
2192 struct bwn_softc *sc = mac->mac_sc;
2193 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2194 struct timespec ts;
2195 uint16_t tmp;
2196
2197 if (bwn_has_hwpctl(mac)) {
2198 sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
2199 sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
2200 sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
2201 sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
2202 sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
2203
2204 BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
2205 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
2206 BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
2207 BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
2208 }
2209 if (phy->type == BWN_PHYTYPE_B &&
2210 phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
2211 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
2212 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
2213 }
2214 if (phy->rev >= 2) {
2215 sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
2216 sav->phy_analogoverval =
2217 BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
2218 sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2219 sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2220 sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
2221 sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
2222 sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
2223
2224 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
2225 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
2226 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
2227 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
2228 if (phy->type == BWN_PHYTYPE_G) {
2229 if ((phy->rev >= 7) &&
2230 (sc->sc_board_info.board_flags &
2231 BHND_BFL_EXTLNA)) {
2232 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
2233 } else {
2234 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
2235 }
2236 } else {
2237 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
2238 }
2239 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
2240 }
2241 sav->reg0 = BWN_READ_2(mac, 0x3f4);
2242 sav->reg1 = BWN_READ_2(mac, 0x3e2);
2243 sav->rf0 = BWN_RF_READ(mac, 0x43);
2244 sav->rf1 = BWN_RF_READ(mac, 0x7a);
2245 sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
2246 sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
2247 sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
2248 sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
2249
2250 if (!BWN_HAS_TXMAG(phy)) {
2251 sav->rf2 = BWN_RF_READ(mac, 0x52);
2252 sav->rf2 &= 0x00f0;
2253 }
2254 if (phy->type == BWN_PHYTYPE_B) {
2255 sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
2256 sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
2257 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
2258 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
2259 } else {
2260 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
2261 | 0x8000);
2262 }
2263 BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
2264 & 0xf000);
2265
2266 tmp =
2267 (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
2268 BWN_PHY_WRITE(mac, tmp, 0x007f);
2269
2270 tmp = sav->phy_syncctl;
2271 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
2272 tmp = sav->rf1;
2273 BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
2274
2275 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
2276 if (phy->type == BWN_PHYTYPE_G ||
2277 (phy->type == BWN_PHYTYPE_B &&
2278 phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
2279 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
2280 } else
2281 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
2282 if (phy->rev >= 2)
2283 bwn_dummy_transmission(mac, 0, 1);
2284 bwn_phy_g_switch_chan(mac, 6, 0);
2285 BWN_RF_READ(mac, 0x51);
2286 if (phy->type == BWN_PHYTYPE_G)
2287 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
2288
2289 nanouptime(&ts);
2290 if (ieee80211_time_before(lo->txctl_measured_time,
2291 (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
2292 bwn_lo_measure_txctl_values(mac);
2293
2294 if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
2295 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
2296 else {
2297 if (phy->type == BWN_PHYTYPE_B)
2298 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
2299 else
2300 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
2301 }
2302 }
2303
2304 static void
2305 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
2306 {
2307 struct bwn_phy *phy = &mac->mac_phy;
2308 struct bwn_phy_g *pg = &phy->phy_g;
2309 uint16_t tmp;
2310
2311 if (phy->rev >= 2) {
2312 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
2313 tmp = (pg->pg_pga_gain << 8);
2314 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
2315 DELAY(5);
2316 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
2317 DELAY(2);
2318 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
2319 } else {
2320 tmp = (pg->pg_pga_gain | 0xefa0);
2321 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
2322 }
2323 if (phy->type == BWN_PHYTYPE_G) {
2324 if (phy->rev >= 3)
2325 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
2326 else
2327 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
2328 if (phy->rev >= 2)
2329 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
2330 else
2331 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
2332 }
2333 BWN_WRITE_2(mac, 0x3f4, sav->reg0);
2334 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
2335 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
2336 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
2337 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
2338 BWN_RF_WRITE(mac, 0x43, sav->rf0);
2339 BWN_RF_WRITE(mac, 0x7a, sav->rf1);
2340 if (!BWN_HAS_TXMAG(phy)) {
2341 tmp = sav->rf2;
2342 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
2343 }
2344 BWN_WRITE_2(mac, 0x3e2, sav->reg1);
2345 if (phy->type == BWN_PHYTYPE_B &&
2346 phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
2347 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
2348 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
2349 }
2350 if (phy->rev >= 2) {
2351 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
2352 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
2353 sav->phy_analogoverval);
2354 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
2355 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
2356 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
2357 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
2358 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
2359 }
2360 if (bwn_has_hwpctl(mac)) {
2361 tmp = (sav->phy_lomask & 0xbfff);
2362 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
2363 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
2364 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
2365 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
2366 BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
2367 }
2368 bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
2369 }
2370
2371 static int
2372 bwn_lo_probe_loctl(struct bwn_mac *mac,
2373 struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
2374 {
2375 struct bwn_phy *phy = &mac->mac_phy;
2376 struct bwn_phy_g *pg = &phy->phy_g;
2377 struct bwn_loctl orig, test;
2378 struct bwn_loctl prev = { -100, -100 };
2379 static const struct bwn_loctl modifiers[] = {
2380 { 1, 1,}, { 1, 0,}, { 1, -1,}, { 0, -1,},
2381 { -1, -1,}, { -1, 0,}, { -1, 1,}, { 0, 1,}
2382 };
2383 int begin, end, lower = 0, i;
2384 uint16_t feedth;
2385
2386 if (d->curstate == 0) {
2387 begin = 1;
2388 end = 8;
2389 } else if (d->curstate % 2 == 0) {
2390 begin = d->curstate - 1;
2391 end = d->curstate + 1;
2392 } else {
2393 begin = d->curstate - 2;
2394 end = d->curstate + 2;
2395 }
2396 if (begin < 1)
2397 begin += 8;
2398 if (end > 8)
2399 end -= 8;
2400
2401 memcpy(&orig, probe, sizeof(struct bwn_loctl));
2402 i = begin;
2403 d->curstate = i;
2404 while (1) {
2405 KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
2406 memcpy(&test, &orig, sizeof(struct bwn_loctl));
2407 test.i += modifiers[i - 1].i * d->multipler;
2408 test.q += modifiers[i - 1].q * d->multipler;
2409 if ((test.i != prev.i || test.q != prev.q) &&
2410 (abs(test.i) <= 16 && abs(test.q) <= 16)) {
2411 bwn_lo_write(mac, &test);
2412 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2413 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2414 if (feedth < d->feedth) {
2415 memcpy(probe, &test,
2416 sizeof(struct bwn_loctl));
2417 lower = 1;
2418 d->feedth = feedth;
2419 if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
2420 break;
2421 }
2422 }
2423 memcpy(&prev, &test, sizeof(prev));
2424 if (i == end)
2425 break;
2426 if (i == 8)
2427 i = 1;
2428 else
2429 i++;
2430 d->curstate = i;
2431 }
2432
2433 return (lower);
2434 }
2435
2436 static void
2437 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
2438 {
2439 struct bwn_phy *phy = &mac->mac_phy;
2440 struct bwn_phy_g *pg = &phy->phy_g;
2441 struct bwn_lo_g_sm d;
2442 struct bwn_loctl probe;
2443 int lower, repeat, cnt = 0;
2444 uint16_t feedth;
2445
2446 d.nmeasure = 0;
2447 d.multipler = 1;
2448 if (BWN_HAS_LOOPBACK(phy))
2449 d.multipler = 3;
2450
2451 memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
2452 repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
2453
2454 do {
2455 bwn_lo_write(mac, &d.loctl);
2456 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2457 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2458 if (feedth < 0x258) {
2459 if (feedth >= 0x12c)
2460 *rxgain += 6;
2461 else
2462 *rxgain += 3;
2463 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
2464 pg->pg_pga_gain, pg->pg_trsw_rx_gain);
2465 }
2466 d.feedth = feedth;
2467 d.curstate = 0;
2468 do {
2469 KASSERT(d.curstate >= 0 && d.curstate <= 8,
2470 ("%s:%d: fail", __func__, __LINE__));
2471 memcpy(&probe, &d.loctl,
2472 sizeof(struct bwn_loctl));
2473 lower = bwn_lo_probe_loctl(mac, &probe, &d);
2474 if (!lower)
2475 break;
2476 if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
2477 break;
2478 memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
2479 d.nmeasure++;
2480 } while (d.nmeasure < 24);
2481 memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
2482
2483 if (BWN_HAS_LOOPBACK(phy)) {
2484 if (d.feedth > 0x1194)
2485 *rxgain -= 6;
2486 else if (d.feedth < 0x5dc)
2487 *rxgain += 3;
2488 if (cnt == 0) {
2489 if (d.feedth <= 0x5dc) {
2490 d.multipler = 1;
2491 cnt++;
2492 } else
2493 d.multipler = 2;
2494 } else if (cnt == 2)
2495 d.multipler = 1;
2496 }
2497 bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
2498 } while (++cnt < repeat);
2499 }
2500
2501 static struct bwn_lo_calib *
2502 bwn_lo_calibset(struct bwn_mac *mac,
2503 const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
2504 {
2505 struct bwn_phy *phy = &mac->mac_phy;
2506 struct bwn_phy_g *pg = &phy->phy_g;
2507 struct bwn_loctl loctl = { 0, 0 };
2508 struct bwn_lo_calib *cal;
2509 struct bwn_lo_g_value sval = { 0 };
2510 int rxgain;
2511 uint16_t pad, reg, value;
2512
2513 sval.old_channel = phy->chan;
2514 bwn_mac_suspend(mac);
2515 bwn_lo_save(mac, &sval);
2516
2517 reg = bwn_lo_txctl_regtable(mac, &value, &pad);
2518 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
2519 BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
2520
2521 rxgain = (rfatt->att * 2) + (bbatt->att / 2);
2522 if (rfatt->padmix)
2523 rxgain -= pad;
2524 if (BWN_HAS_LOOPBACK(phy))
2525 rxgain += pg->pg_max_lb_gain;
2526 bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
2527 bwn_phy_g_set_bbatt(mac, bbatt->att);
2528 bwn_lo_probe_sm(mac, &loctl, &rxgain);
2529
2530 bwn_lo_restore(mac, &sval);
2531 bwn_mac_enable(mac);
2532
2533 cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
2534 if (!cal) {
2535 device_printf(mac->mac_sc->sc_dev, "out of memory\n");
2536 return (NULL);
2537 }
2538 memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
2539 memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
2540 memcpy(&cal->ctl, &loctl, sizeof(loctl));
2541
2542 BWN_GETTIME(cal->calib_time);
2543
2544 return (cal);
2545 }
2546
2547 static struct bwn_lo_calib *
2548 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
2549 const struct bwn_rfatt *rfatt)
2550 {
2551 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2552 struct bwn_lo_calib *c;
2553
2554 TAILQ_FOREACH(c, &lo->calib_list, list) {
2555 if (!BWN_BBATTCMP(&c->bbatt, bbatt))
2556 continue;
2557 if (!BWN_RFATTCMP(&c->rfatt, rfatt))
2558 continue;
2559 return (c);
2560 }
2561
2562 c = bwn_lo_calibset(mac, bbatt, rfatt);
2563 if (!c)
2564 return (NULL);
2565 TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
2566
2567 return (c);
2568 }
2569
2570 static void
2571 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
2572 {
2573 struct bwn_phy *phy = &mac->mac_phy;
2574 struct bwn_phy_g *pg = &phy->phy_g;
2575 struct bwn_softc *sc = mac->mac_sc;
2576 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2577 const struct bwn_rfatt *rfatt;
2578 const struct bwn_bbatt *bbatt;
2579 uint64_t pvector;
2580 int i;
2581 int rf_offset, bb_offset;
2582 uint8_t changed = 0;
2583
2584 KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
2585 KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
2586 ("%s:%d: fail", __func__, __LINE__));
2587
2588 pvector = lo->power_vector;
2589 if (!update && !pvector)
2590 return;
2591
2592 bwn_mac_suspend(mac);
2593
2594 for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
2595 struct bwn_lo_calib *cal;
2596 int idx;
2597 uint16_t val;
2598
2599 if (!update && !(pvector & (((uint64_t)1ULL) << i)))
2600 continue;
2601 bb_offset = i / lo->rfatt.len;
2602 rf_offset = i % lo->rfatt.len;
2603 bbatt = &(lo->bbatt.array[bb_offset]);
2604 rfatt = &(lo->rfatt.array[rf_offset]);
2605
2606 cal = bwn_lo_calibset(mac, bbatt, rfatt);
2607 if (!cal) {
2608 device_printf(sc->sc_dev, "LO: Could not "
2609 "calibrate DC table entry\n");
2610 continue;
2611 }
2612 val = (uint8_t)(cal->ctl.q);
2613 val |= ((uint8_t)(cal->ctl.i)) << 4;
2614 free(cal, M_DEVBUF);
2615
2616 idx = i / 2;
2617 if (i % 2)
2618 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
2619 | ((val & 0x00ff) << 8);
2620 else
2621 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
2622 | (val & 0x00ff);
2623 changed = 1;
2624 }
2625 if (changed) {
2626 for (i = 0; i < BWN_DC_LT_SIZE; i++)
2627 BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
2628 }
2629 bwn_mac_enable(mac);
2630 }
2631
2632 static void
2633 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
2634 {
2635
2636 if (!rf->padmix)
2637 return;
2638 if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
2639 rf->att = 4;
2640 }
2641
2642 static void
2643 bwn_lo_g_adjust(struct bwn_mac *mac)
2644 {
2645 struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2646 struct bwn_lo_calib *cal;
2647 struct bwn_rfatt rf;
2648
2649 memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
2650 bwn_lo_fixup_rfatt(&rf);
2651
2652 cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
2653 if (!cal)
2654 return;
2655 bwn_lo_write(mac, &cal->ctl);
2656 }
2657
2658 static void
2659 bwn_lo_g_init(struct bwn_mac *mac)
2660 {
2661
2662 if (!bwn_has_hwpctl(mac))
2663 return;
2664
2665 bwn_lo_get_powervector(mac);
2666 bwn_phy_g_dc_lookup_init(mac, 1);
2667 }
2668
2669 static int16_t
2670 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
2671 {
2672
2673 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
2674 return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
2675 }
2676
2677 static void
2678 bwn_nrssi_threshold(struct bwn_mac *mac)
2679 {
2680 struct bwn_phy *phy = &mac->mac_phy;
2681 struct bwn_phy_g *pg = &phy->phy_g;
2682 struct bwn_softc *sc = mac->mac_sc;
2683 int32_t a, b;
2684 int16_t tmp16;
2685 uint16_t tmpu16;
2686
2687 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2688
2689 if (phy->gmode && (sc->sc_board_info.board_flags & BHND_BFL_ADCDIV)) {
2690 if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
2691 a = 0x13;
2692 b = 0x12;
2693 } else {
2694 a = 0xe;
2695 b = 0x11;
2696 }
2697
2698 a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
2699 a += (pg->pg_nrssi[0] << 6);
2700 a += (a < 32) ? 31 : 32;
2701 a = a >> 6;
2702 a = MIN(MAX(a, -31), 31);
2703
2704 b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
2705 b += (pg->pg_nrssi[0] << 6);
2706 if (b < 32)
2707 b += 31;
2708 else
2709 b += 32;
2710 b = b >> 6;
2711 b = MIN(MAX(b, -31), 31);
2712
2713 tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
2714 tmpu16 |= ((uint32_t)b & 0x0000003f);
2715 tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
2716 BWN_PHY_WRITE(mac, 0x048a, tmpu16);
2717 return;
2718 }
2719
2720 tmp16 = bwn_nrssi_read(mac, 0x20);
2721 if (tmp16 >= 0x20)
2722 tmp16 -= 0x40;
2723 BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
2724 }
2725
2726 static void
2727 bwn_nrssi_slope_11g(struct bwn_mac *mac)
2728 {
2729 #define SAVE_RF_MAX 3
2730 #define SAVE_PHY_COMM_MAX 4
2731 #define SAVE_PHY3_MAX 8
2732 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
2733 { 0x7a, 0x52, 0x43 };
2734 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
2735 { 0x15, 0x5a, 0x59, 0x58 };
2736 static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
2737 0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
2738 0x0801, 0x0060, 0x0014, 0x0478
2739 };
2740 struct bwn_phy *phy = &mac->mac_phy;
2741 struct bwn_phy_g *pg = &phy->phy_g;
2742 int32_t i, tmp32, phy3_idx = 0;
2743 uint16_t delta, tmp;
2744 uint16_t save_rf[SAVE_RF_MAX];
2745 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
2746 uint16_t save_phy3[SAVE_PHY3_MAX];
2747 uint16_t ant_div, phy0, chan_ex;
2748 int16_t nrssi0, nrssi1;
2749
2750 KASSERT(phy->type == BWN_PHYTYPE_G,
2751 ("%s:%d: fail", __func__, __LINE__));
2752
2753 if (phy->rf_rev >= 9)
2754 return;
2755 if (phy->rf_rev == 8)
2756 bwn_nrssi_offset(mac);
2757
2758 BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
2759 BWN_PHY_MASK(mac, 0x0802, 0xfffc);
2760
2761 /*
2762 * Save RF/PHY registers for later restoration
2763 */
2764 ant_div = BWN_READ_2(mac, 0x03e2);
2765 BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
2766 for (i = 0; i < SAVE_RF_MAX; ++i)
2767 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
2768 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2769 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
2770
2771 phy0 = BWN_READ_2(mac, BWN_PHY0);
2772 chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
2773 if (phy->rev >= 3) {
2774 for (i = 0; i < SAVE_PHY3_MAX; ++i)
2775 save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
2776 BWN_PHY_WRITE(mac, 0x002e, 0);
2777 BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
2778 switch (phy->rev) {
2779 case 4:
2780 case 6:
2781 case 7:
2782 BWN_PHY_SET(mac, 0x0478, 0x0100);
2783 BWN_PHY_SET(mac, 0x0801, 0x0040);
2784 break;
2785 case 3:
2786 case 5:
2787 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
2788 break;
2789 }
2790 BWN_PHY_SET(mac, 0x0060, 0x0040);
2791 BWN_PHY_SET(mac, 0x0014, 0x0200);
2792 }
2793 /*
2794 * Calculate nrssi0
2795 */
2796 BWN_RF_SET(mac, 0x007a, 0x0070);
2797 bwn_set_all_gains(mac, 0, 8, 0);
2798 BWN_RF_MASK(mac, 0x007a, 0x00f7);
2799 if (phy->rev >= 2) {
2800 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
2801 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
2802 }
2803 BWN_RF_SET(mac, 0x007a, 0x0080);
2804 DELAY(20);
2805
2806 nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2807 if (nrssi0 >= 0x0020)
2808 nrssi0 -= 0x0040;
2809
2810 /*
2811 * Calculate nrssi1
2812 */
2813 BWN_RF_MASK(mac, 0x007a, 0x007f);
2814 if (phy->rev >= 2)
2815 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
2816
2817 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
2818 BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
2819 BWN_RF_SET(mac, 0x007a, 0x000f);
2820 BWN_PHY_WRITE(mac, 0x0015, 0xf330);
2821 if (phy->rev >= 2) {
2822 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
2823 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
2824 }
2825
2826 bwn_set_all_gains(mac, 3, 0, 1);
2827 if (phy->rf_rev == 8) {
2828 BWN_RF_WRITE(mac, 0x0043, 0x001f);
2829 } else {
2830 tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
2831 BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
2832 tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
2833 BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
2834 }
2835 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
2836 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
2837 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
2838 DELAY(20);
2839 nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2840
2841 /*
2842 * Install calculated narrow RSSI values
2843 */
2844 if (nrssi1 >= 0x0020)
2845 nrssi1 -= 0x0040;
2846 if (nrssi0 == nrssi1)
2847 pg->pg_nrssi_slope = 0x00010000;
2848 else
2849 pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
2850 if (nrssi0 >= -4) {
2851 pg->pg_nrssi[0] = nrssi1;
2852 pg->pg_nrssi[1] = nrssi0;
2853 }
2854
2855 /*
2856 * Restore saved RF/PHY registers
2857 */
2858 if (phy->rev >= 3) {
2859 for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
2860 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
2861 save_phy3[phy3_idx]);
2862 }
2863 }
2864 if (phy->rev >= 2) {
2865 BWN_PHY_MASK(mac, 0x0812, 0xffcf);
2866 BWN_PHY_MASK(mac, 0x0811, 0xffcf);
2867 }
2868
2869 for (i = 0; i < SAVE_RF_MAX; ++i)
2870 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
2871
2872 BWN_WRITE_2(mac, 0x03e2, ant_div);
2873 BWN_WRITE_2(mac, 0x03e6, phy0);
2874 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
2875
2876 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2877 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
2878
2879 bwn_spu_workaround(mac, phy->chan);
2880 BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
2881 bwn_set_original_gains(mac);
2882 BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
2883 if (phy->rev >= 3) {
2884 for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
2885 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
2886 save_phy3[phy3_idx]);
2887 }
2888 }
2889
2890 delta = 0x1f - pg->pg_nrssi[0];
2891 for (i = 0; i < 64; i++) {
2892 tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
2893 tmp32 = MIN(MAX(tmp32, 0), 0x3f);
2894 pg->pg_nrssi_lt[i] = tmp32;
2895 }
2896
2897 bwn_nrssi_threshold(mac);
2898 #undef SAVE_RF_MAX
2899 #undef SAVE_PHY_COMM_MAX
2900 #undef SAVE_PHY3_MAX
2901 }
2902
2903 static void
2904 bwn_nrssi_offset(struct bwn_mac *mac)
2905 {
2906 #define SAVE_RF_MAX 2
2907 #define SAVE_PHY_COMM_MAX 10
2908 #define SAVE_PHY6_MAX 8
2909 static const uint16_t save_rf_regs[SAVE_RF_MAX] =
2910 { 0x7a, 0x43 };
2911 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
2912 0x0001, 0x0811, 0x0812, 0x0814,
2913 0x0815, 0x005a, 0x0059, 0x0058,
2914 0x000a, 0x0003
2915 };
2916 static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
2917 0x002e, 0x002f, 0x080f, 0x0810,
2918 0x0801, 0x0060, 0x0014, 0x0478
2919 };
2920 struct bwn_phy *phy = &mac->mac_phy;
2921 int i, phy6_idx = 0;
2922 uint16_t save_rf[SAVE_RF_MAX];
2923 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
2924 uint16_t save_phy6[SAVE_PHY6_MAX];
2925 int16_t nrssi;
2926 uint16_t saved = 0xffff;
2927
2928 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
2929 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
2930 for (i = 0; i < SAVE_RF_MAX; ++i)
2931 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
2932
2933 BWN_PHY_MASK(mac, 0x0429, 0x7fff);
2934 BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
2935 BWN_PHY_SET(mac, 0x0811, 0x000c);
2936 BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
2937 BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
2938 if (phy->rev >= 6) {
2939 for (i = 0; i < SAVE_PHY6_MAX; ++i)
2940 save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
2941
2942 BWN_PHY_WRITE(mac, 0x002e, 0);
2943 BWN_PHY_WRITE(mac, 0x002f, 0);
2944 BWN_PHY_WRITE(mac, 0x080f, 0);
2945 BWN_PHY_WRITE(mac, 0x0810, 0);
2946 BWN_PHY_SET(mac, 0x0478, 0x0100);
2947 BWN_PHY_SET(mac, 0x0801, 0x0040);
2948 BWN_PHY_SET(mac, 0x0060, 0x0040);
2949 BWN_PHY_SET(mac, 0x0014, 0x0200);
2950 }
2951 BWN_RF_SET(mac, 0x007a, 0x0070);
2952 BWN_RF_SET(mac, 0x007a, 0x0080);
2953 DELAY(30);
2954
2955 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2956 if (nrssi >= 0x20)
2957 nrssi -= 0x40;
2958 if (nrssi == 31) {
2959 for (i = 7; i >= 4; i--) {
2960 BWN_RF_WRITE(mac, 0x007b, i);
2961 DELAY(20);
2962 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
2963 0x003f);
2964 if (nrssi >= 0x20)
2965 nrssi -= 0x40;
2966 if (nrssi < 31 && saved == 0xffff)
2967 saved = i;
2968 }
2969 if (saved == 0xffff)
2970 saved = 4;
2971 } else {
2972 BWN_RF_MASK(mac, 0x007a, 0x007f);
2973 if (phy->rev != 1) {
2974 BWN_PHY_SET(mac, 0x0814, 0x0001);
2975 BWN_PHY_MASK(mac, 0x0815, 0xfffe);
2976 }
2977 BWN_PHY_SET(mac, 0x0811, 0x000c);
2978 BWN_PHY_SET(mac, 0x0812, 0x000c);
2979 BWN_PHY_SET(mac, 0x0811, 0x0030);
2980 BWN_PHY_SET(mac, 0x0812, 0x0030);
2981 BWN_PHY_WRITE(mac, 0x005a, 0x0480);
2982 BWN_PHY_WRITE(mac, 0x0059, 0x0810);
2983 BWN_PHY_WRITE(mac, 0x0058, 0x000d);
2984 if (phy->rev == 0)
2985 BWN_PHY_WRITE(mac, 0x0003, 0x0122);
2986 else
2987 BWN_PHY_SET(mac, 0x000a, 0x2000);
2988 if (phy->rev != 1) {
2989 BWN_PHY_SET(mac, 0x0814, 0x0004);
2990 BWN_PHY_MASK(mac, 0x0815, 0xfffb);
2991 }
2992 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
2993 BWN_RF_SET(mac, 0x007a, 0x000f);
2994 bwn_set_all_gains(mac, 3, 0, 1);
2995 BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
2996 DELAY(30);
2997 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
2998 if (nrssi >= 0x20)
2999 nrssi -= 0x40;
3000 if (nrssi == -32) {
3001 for (i = 0; i < 4; i++) {
3002 BWN_RF_WRITE(mac, 0x007b, i);
3003 DELAY(20);
3004 nrssi = (int16_t)((BWN_PHY_READ(mac,
3005 0x047f) >> 8) & 0x003f);
3006 if (nrssi >= 0x20)
3007 nrssi -= 0x40;
3008 if (nrssi > -31 && saved == 0xffff)
3009 saved = i;
3010 }
3011 if (saved == 0xffff)
3012 saved = 3;
3013 } else
3014 saved = 0;
3015 }
3016 BWN_RF_WRITE(mac, 0x007b, saved);
3017
3018 /*
3019 * Restore saved RF/PHY registers
3020 */
3021 if (phy->rev >= 6) {
3022 for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
3023 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
3024 save_phy6[phy6_idx]);
3025 }
3026 }
3027 if (phy->rev != 1) {
3028 for (i = 3; i < 5; i++)
3029 BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
3030 save_phy_comm[i]);
3031 }
3032 for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
3033 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
3034
3035 for (i = SAVE_RF_MAX - 1; i >= 0; --i)
3036 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
3037
3038 BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
3039 BWN_PHY_SET(mac, 0x0429, 0x8000);
3040 bwn_set_original_gains(mac);
3041 if (phy->rev >= 6) {
3042 for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
3043 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
3044 save_phy6[phy6_idx]);
3045 }
3046 }
3047
3048 BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
3049 BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
3050 BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
3051 }
3052
3053 static void
3054 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
3055 int16_t third)
3056 {
3057 struct bwn_phy *phy = &mac->mac_phy;
3058 uint16_t i;
3059 uint16_t start = 0x08, end = 0x18;
3060 uint16_t tmp;
3061 uint16_t table;
3062
3063 if (phy->rev <= 1) {
3064 start = 0x10;
3065 end = 0x20;
3066 }
3067
3068 table = BWN_OFDMTAB_GAINX;
3069 if (phy->rev <= 1)
3070 table = BWN_OFDMTAB_GAINX_R1;
3071 for (i = 0; i < 4; i++)
3072 bwn_ofdmtab_write_2(mac, table, i, first);
3073
3074 for (i = start; i < end; i++)
3075 bwn_ofdmtab_write_2(mac, table, i, second);
3076
3077 if (third != -1) {
3078 tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
3079 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
3080 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
3081 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
3082 }
3083 bwn_dummy_transmission(mac, 0, 1);
3084 }
3085
3086 static void
3087 bwn_set_original_gains(struct bwn_mac *mac)
3088 {
3089 struct bwn_phy *phy = &mac->mac_phy;
3090 uint16_t i, tmp;
3091 uint16_t table;
3092 uint16_t start = 0x0008, end = 0x0018;
3093
3094 if (phy->rev <= 1) {
3095 start = 0x0010;
3096 end = 0x0020;
3097 }
3098
3099 table = BWN_OFDMTAB_GAINX;
3100 if (phy->rev <= 1)
3101 table = BWN_OFDMTAB_GAINX_R1;
3102 for (i = 0; i < 4; i++) {
3103 tmp = (i & 0xfffc);
3104 tmp |= (i & 0x0001) << 1;
3105 tmp |= (i & 0x0002) >> 1;
3106
3107 bwn_ofdmtab_write_2(mac, table, i, tmp);
3108 }
3109
3110 for (i = start; i < end; i++)
3111 bwn_ofdmtab_write_2(mac, table, i, i - start);
3112
3113 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
3114 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
3115 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
3116 bwn_dummy_transmission(mac, 0, 1);
3117 }
3118
3119 static void
3120 bwn_phy_hwpctl_init(struct bwn_mac *mac)
3121 {
3122 struct bwn_phy *phy = &mac->mac_phy;
3123 struct bwn_phy_g *pg = &phy->phy_g;
3124 struct bwn_rfatt old_rfatt, rfatt;
3125 struct bwn_bbatt old_bbatt, bbatt;
3126 struct bwn_softc *sc = mac->mac_sc;
3127 uint8_t old_txctl = 0;
3128
3129 KASSERT(phy->type == BWN_PHYTYPE_G,
3130 ("%s:%d: fail", __func__, __LINE__));
3131
3132 if ((sc->sc_board_info.board_vendor == PCI_VENDOR_BROADCOM) &&
3133 (sc->sc_board_info.board_type == BHND_BOARD_BU4306))
3134 return;
3135
3136 BWN_PHY_WRITE(mac, 0x0028, 0x8018);
3137
3138 BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
3139
3140 if (!phy->gmode)
3141 return;
3142 bwn_hwpctl_early_init(mac);
3143 if (pg->pg_curtssi == 0) {
3144 if (phy->rf_ver == 0x2050 && phy->analog == 0) {
3145 BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
3146 } else {
3147 memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
3148 memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
3149 old_txctl = pg->pg_txctl;
3150
3151 bbatt.att = 11;
3152 if (phy->rf_rev == 8) {
3153 rfatt.att = 15;
3154 rfatt.padmix = 1;
3155 } else {
3156 rfatt.att = 9;
3157 rfatt.padmix = 0;
3158 }
3159 bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
3160 }
3161 bwn_dummy_transmission(mac, 0, 1);
3162 pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
3163 if (phy->rf_ver == 0x2050 && phy->analog == 0)
3164 BWN_RF_MASK(mac, 0x0076, 0xff7b);
3165 else
3166 bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
3167 &old_rfatt, old_txctl);
3168 }
3169 bwn_hwpctl_init_gphy(mac);
3170
3171 /* clear TSSI */
3172 bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
3173 bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
3174 bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
3175 bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
3176 }
3177
3178 static void
3179 bwn_hwpctl_early_init(struct bwn_mac *mac)
3180 {
3181 struct bwn_phy *phy = &mac->mac_phy;
3182
3183 if (!bwn_has_hwpctl(mac)) {
3184 BWN_PHY_WRITE(mac, 0x047a, 0xc111);
3185 return;
3186 }
3187
3188 BWN_PHY_MASK(mac, 0x0036, 0xfeff);
3189 BWN_PHY_WRITE(mac, 0x002f, 0x0202);
3190 BWN_PHY_SET(mac, 0x047c, 0x0002);
3191 BWN_PHY_SET(mac, 0x047a, 0xf000);
3192 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
3193 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
3194 BWN_PHY_SET(mac, 0x005d, 0x8000);
3195 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
3196 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
3197 BWN_PHY_SET(mac, 0x0036, 0x0400);
3198 } else {
3199 BWN_PHY_SET(mac, 0x0036, 0x0200);
3200 BWN_PHY_SET(mac, 0x0036, 0x0400);
3201 BWN_PHY_MASK(mac, 0x005d, 0x7fff);
3202 BWN_PHY_MASK(mac, 0x004f, 0xfffe);
3203 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
3204 BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
3205 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
3206 }
3207 }
3208
3209 static void
3210 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
3211 {
3212 struct bwn_phy *phy = &mac->mac_phy;
3213 struct bwn_phy_g *pg = &phy->phy_g;
3214 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
3215 int i;
3216 uint16_t nr_written = 0, tmp, value;
3217 uint8_t rf, bb;
3218
3219 if (!bwn_has_hwpctl(mac)) {
3220 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
3221 return;
3222 }
3223
3224 BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
3225 (pg->pg_idletssi - pg->pg_curtssi));
3226 BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
3227 (pg->pg_idletssi - pg->pg_curtssi));
3228
3229 for (i = 0; i < 32; i++)
3230 bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
3231 for (i = 32; i < 64; i++)
3232 bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
3233 for (i = 0; i < 64; i += 2) {
3234 value = (uint16_t) pg->pg_tssi2dbm[i];
3235 value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
3236 BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
3237 }
3238
3239 for (rf = 0; rf < lo->rfatt.len; rf++) {
3240 for (bb = 0; bb < lo->bbatt.len; bb++) {
3241 if (nr_written >= 0x40)
3242 return;
3243 tmp = lo->bbatt.array[bb].att;
3244 tmp <<= 8;
3245 if (phy->rf_rev == 8)
3246 tmp |= 0x50;
3247 else
3248 tmp |= 0x40;
3249 tmp |= lo->rfatt.array[rf].att;
3250 BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
3251 nr_written++;
3252 }
3253 }
3254
3255 BWN_PHY_MASK(mac, 0x0060, 0xffbf);
3256 BWN_PHY_WRITE(mac, 0x0014, 0x0000);
3257
3258 KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
3259 BWN_PHY_SET(mac, 0x0478, 0x0800);
3260 BWN_PHY_MASK(mac, 0x0478, 0xfeff);
3261 BWN_PHY_MASK(mac, 0x0801, 0xffbf);
3262
3263 bwn_phy_g_dc_lookup_init(mac, 1);
3264 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
3265 }
3266
3267 static void
3268 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
3269 {
3270 struct bwn_softc *sc = mac->mac_sc;
3271 int error;
3272
3273 if (spu != 0)
3274 bwn_spu_workaround(mac, channel);
3275
3276 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
3277
3278 if (channel == 14) {
3279 uint8_t cc;
3280
3281 error = bhnd_nvram_getvar_uint8(sc->sc_dev, BHND_NVAR_CC, &cc);
3282 if (error) {
3283 device_printf(sc->sc_dev, "error reading country code "
3284 "from NVRAM, assuming channel 14 unavailable: %d\n",
3285 error);
3286 cc = BWN_SPROM1_CC_WORLDWIDE;
3287 }
3288
3289 if (cc == BWN_SPROM1_CC_JP)
3290 bwn_hf_write(mac,
3291 bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
3292 else
3293 bwn_hf_write(mac,
3294 bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
3295 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
3296 BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
3297 return;
3298 }
3299
3300 BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
3301 BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
3302 }
3303
3304 static uint16_t
3305 bwn_phy_g_chan2freq(uint8_t channel)
3306 {
3307 static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
3308
3309 KASSERT(channel >= 1 && channel <= 14,
3310 ("%s:%d: fail", __func__, __LINE__));
3311
3312 return (bwn_phy_g_rf_channels[channel - 1]);
3313 }
3314
3315 static void
3316 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
3317 const struct bwn_rfatt *rfatt, uint8_t txctl)
3318 {
3319 struct bwn_phy *phy = &mac->mac_phy;
3320 struct bwn_phy_g *pg = &phy->phy_g;
3321 struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
3322 uint16_t bb, rf;
3323 uint16_t tx_bias, tx_magn;
3324
3325 bb = bbatt->att;
3326 rf = rfatt->att;
3327 tx_bias = lo->tx_bias;
3328 tx_magn = lo->tx_magn;
3329 if (tx_bias == 0xff)
3330 tx_bias = 0;
3331
3332 pg->pg_txctl = txctl;
3333 memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
3334 pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
3335 memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
3336 bwn_phy_g_set_bbatt(mac, bb);
3337 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
3338 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
3339 BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
3340 else {
3341 BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
3342 BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
3343 }
3344 if (BWN_HAS_TXMAG(phy))
3345 BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
3346 else
3347 BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
3348 bwn_lo_g_adjust(mac);
3349 }
3350
3351 static void
3352 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
3353 uint16_t bbatt)
3354 {
3355 struct bwn_phy *phy = &mac->mac_phy;
3356
3357 if (phy->analog == 0) {
3358 BWN_WRITE_2(mac, BWN_PHY0,
3359 (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
3360 return;
3361 }
3362 if (phy->analog > 1) {
3363 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
3364 return;
3365 }
3366 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
3367 }
3368
3369 static uint16_t
3370 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
3371 {
3372 struct bwn_phy *phy = &mac->mac_phy;
3373 struct bwn_phy_g *pg = &phy->phy_g;
3374 struct bwn_softc *sc = mac->mac_sc;
3375 int max_lb_gain;
3376 uint16_t extlna;
3377 uint16_t i;
3378
3379 if (phy->gmode == 0)
3380 return (0);
3381
3382 if (BWN_HAS_LOOPBACK(phy)) {
3383 max_lb_gain = pg->pg_max_lb_gain;
3384 max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
3385 if (max_lb_gain >= 0x46) {
3386 extlna = 0x3000;
3387 max_lb_gain -= 0x46;
3388 } else if (max_lb_gain >= 0x3a) {
3389 extlna = 0x1000;
3390 max_lb_gain -= 0x3a;
3391 } else if (max_lb_gain >= 0x2e) {
3392 extlna = 0x2000;
3393 max_lb_gain -= 0x2e;
3394 } else {
3395 extlna = 0;
3396 max_lb_gain -= 0x10;
3397 }
3398
3399 for (i = 0; i < 16; i++) {
3400 max_lb_gain -= (i * 6);
3401 if (max_lb_gain < 6)
3402 break;
3403 }
3404
3405 if ((phy->rev < 7) ||
3406 !(sc->sc_board_info.board_flags & BHND_BFL_EXTLNA)) {
3407 if (reg == BWN_PHY_RFOVER) {
3408 return (0x1b3);
3409 } else if (reg == BWN_PHY_RFOVERVAL) {
3410 extlna |= (i << 8);
3411 switch (lpd) {
3412 case BWN_LPD(0, 1, 1):
3413 return (0x0f92);
3414 case BWN_LPD(0, 0, 1):
3415 case BWN_LPD(1, 0, 1):
3416 return (0x0092 | extlna);
3417 case BWN_LPD(1, 0, 0):
3418 return (0x0093 | extlna);
3419 }
3420 KASSERT(0 == 1,
3421 ("%s:%d: fail", __func__, __LINE__));
3422 }
3423 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3424 } else {
3425 if (reg == BWN_PHY_RFOVER)
3426 return (0x9b3);
3427 if (reg == BWN_PHY_RFOVERVAL) {
3428 if (extlna)
3429 extlna |= 0x8000;
3430 extlna |= (i << 8);
3431 switch (lpd) {
3432 case BWN_LPD(0, 1, 1):
3433 return (0x8f92);
3434 case BWN_LPD(0, 0, 1):
3435 return (0x8092 | extlna);
3436 case BWN_LPD(1, 0, 1):
3437 return (0x2092 | extlna);
3438 case BWN_LPD(1, 0, 0):
3439 return (0x2093 | extlna);
3440 }
3441 KASSERT(0 == 1,
3442 ("%s:%d: fail", __func__, __LINE__));
3443 }
3444 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3445 }
3446 return (0);
3447 }
3448
3449 if ((phy->rev < 7) ||
3450 !(sc->sc_board_info.board_flags & BHND_BFL_EXTLNA)) {
3451 if (reg == BWN_PHY_RFOVER) {
3452 return (0x1b3);
3453 } else if (reg == BWN_PHY_RFOVERVAL) {
3454 switch (lpd) {
3455 case BWN_LPD(0, 1, 1):
3456 return (0x0fb2);
3457 case BWN_LPD(0, 0, 1):
3458 return (0x00b2);
3459 case BWN_LPD(1, 0, 1):
3460 return (0x30b2);
3461 case BWN_LPD(1, 0, 0):
3462 return (0x30b3);
3463 }
3464 KASSERT(0 == 1,
3465 ("%s:%d: fail", __func__, __LINE__));
3466 }
3467 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3468 } else {
3469 if (reg == BWN_PHY_RFOVER) {
3470 return (0x9b3);
3471 } else if (reg == BWN_PHY_RFOVERVAL) {
3472 switch (lpd) {
3473 case BWN_LPD(0, 1, 1):
3474 return (0x8fb2);
3475 case BWN_LPD(0, 0, 1):
3476 return (0x80b2);
3477 case BWN_LPD(1, 0, 1):
3478 return (0x20b2);
3479 case BWN_LPD(1, 0, 0):
3480 return (0x20b3);
3481 }
3482 KASSERT(0 == 1,
3483 ("%s:%d: fail", __func__, __LINE__));
3484 }
3485 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3486 }
3487 return (0);
3488 }
3489
3490 static void
3491 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
3492 {
3493
3494 if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
3495 return;
3496 BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
3497 bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
3498 DELAY(1000);
3499 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
3500 }
3501
3502 static int
3503 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
3504 {
3505 const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
3506 unsigned int a, b, c, d;
3507 unsigned int avg;
3508 uint32_t tmp;
3509
3510 tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
3511 a = tmp & 0xff;
3512 b = (tmp >> 8) & 0xff;
3513 c = (tmp >> 16) & 0xff;
3514 d = (tmp >> 24) & 0xff;
3515 if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
3516 c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
3517 return (ENOENT);
3518 bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
3519 BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
3520 (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
3521
3522 if (ofdm) {
3523 a = (a + 32) & 0x3f;
3524 b = (b + 32) & 0x3f;
3525 c = (c + 32) & 0x3f;
3526 d = (d + 32) & 0x3f;
3527 }
3528
3529 avg = (a + b + c + d + 2) / 4;
3530 if (ofdm) {
3531 if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
3532 & BWN_HF_4DB_CCK_POWERBOOST)
3533 avg = (avg >= 13) ? (avg - 13) : 0;
3534 }
3535 return (avg);
3536 }
3537
3538 static void
3539 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
3540 {
3541 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
3542 int rfatt = *rfattp;
3543 int bbatt = *bbattp;
3544
3545 while (1) {
3546 if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
3547 break;
3548 if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
3549 break;
3550 if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
3551 break;
3552 if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
3553 break;
3554 if (bbatt > lo->bbatt.max) {
3555 bbatt -= 4;
3556 rfatt += 1;
3557 continue;
3558 }
3559 if (bbatt < lo->bbatt.min) {
3560 bbatt += 4;
3561 rfatt -= 1;
3562 continue;
3563 }
3564 if (rfatt > lo->rfatt.max) {
3565 rfatt -= 1;
3566 bbatt += 4;
3567 continue;
3568 }
3569 if (rfatt < lo->rfatt.min) {
3570 rfatt += 1;
3571 bbatt -= 4;
3572 continue;
3573 }
3574 break;
3575 }
3576
3577 *rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
3578 *bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
3579 }
3580
3581 static void
3582 bwn_phy_lock(struct bwn_mac *mac)
3583 {
3584 struct bwn_softc *sc = mac->mac_sc;
3585 struct ieee80211com *ic = &sc->sc_ic;
3586
3587 KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 3,
3588 ("%s: unsupported rev %d", __func__, bhnd_get_hwrev(sc->sc_dev)));
3589
3590 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
3591 bwn_psctl(mac, BWN_PS_AWAKE);
3592 }
3593
3594 static void
3595 bwn_phy_unlock(struct bwn_mac *mac)
3596 {
3597 struct bwn_softc *sc = mac->mac_sc;
3598 struct ieee80211com *ic = &sc->sc_ic;
3599
3600 KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 3,
3601 ("%s: unsupported rev %d", __func__, bhnd_get_hwrev(sc->sc_dev)));
3602
3603 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
3604 bwn_psctl(mac, 0);
3605 }
3606
3607 static void
3608 bwn_rf_lock(struct bwn_mac *mac)
3609 {
3610
3611 BWN_WRITE_4(mac, BWN_MACCTL,
3612 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
3613 BWN_READ_4(mac, BWN_MACCTL);
3614 DELAY(10);
3615 }
3616
3617 static void
3618 bwn_rf_unlock(struct bwn_mac *mac)
3619 {
3620
3621 BWN_READ_2(mac, BWN_PHYVER);
3622 BWN_WRITE_4(mac, BWN_MACCTL,
3623 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
3624 }
Cache object: cd6e2c39913111a327ee8fd33c3bcce7
|