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