1298948Sadrian/*- 2298948Sadrian * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org> 3298948Sadrian * All rights reserved. 4298948Sadrian * 5298948Sadrian * Redistribution and use in source and binary forms, with or without 6298948Sadrian * modification, are permitted provided that the following conditions 7298948Sadrian * are met: 8298948Sadrian * 1. Redistributions of source code must retain the above copyright 9298948Sadrian * notice, this list of conditions and the following disclaimer, 10298948Sadrian * without modification. 11298948Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12298948Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13298948Sadrian * redistribution must be conditioned upon including a substantially 14298948Sadrian * similar Disclaimer requirement for further binary redistribution. 15298948Sadrian * 16298948Sadrian * NO WARRANTY 17298948Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18298948Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19298948Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20298948Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21298948Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22298948Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23298948Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24298948Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25298948Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26298948Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27298948Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 28298948Sadrian */ 29298948Sadrian 30298948Sadrian#include <sys/cdefs.h> 31298948Sadrian__FBSDID("$FreeBSD$"); 32298948Sadrian 33299984Sadrian#include "opt_bwn.h" 34299984Sadrian#include "opt_wlan.h" 35299984Sadrian 36298948Sadrian/* 37298948Sadrian * The Broadcom Wireless LAN controller driver. 38298948Sadrian */ 39298948Sadrian 40298948Sadrian#include <sys/param.h> 41298948Sadrian#include <sys/systm.h> 42298948Sadrian#include <sys/kernel.h> 43298948Sadrian#include <sys/malloc.h> 44298948Sadrian#include <sys/module.h> 45298948Sadrian#include <sys/endian.h> 46298948Sadrian#include <sys/errno.h> 47298948Sadrian#include <sys/firmware.h> 48298948Sadrian#include <sys/lock.h> 49298948Sadrian#include <sys/mutex.h> 50298948Sadrian#include <machine/bus.h> 51298948Sadrian#include <machine/resource.h> 52298948Sadrian#include <sys/bus.h> 53298948Sadrian#include <sys/rman.h> 54298948Sadrian#include <sys/socket.h> 55298948Sadrian#include <sys/sockio.h> 56298948Sadrian 57298948Sadrian#include <net/ethernet.h> 58298948Sadrian#include <net/if.h> 59298948Sadrian#include <net/if_var.h> 60298948Sadrian#include <net/if_arp.h> 61298948Sadrian#include <net/if_dl.h> 62298948Sadrian#include <net/if_llc.h> 63298948Sadrian#include <net/if_media.h> 64298948Sadrian#include <net/if_types.h> 65298948Sadrian 66298948Sadrian#include <dev/pci/pcivar.h> 67298948Sadrian#include <dev/pci/pcireg.h> 68298948Sadrian#include <dev/siba/siba_ids.h> 69298948Sadrian#include <dev/siba/sibareg.h> 70298948Sadrian#include <dev/siba/sibavar.h> 71298948Sadrian 72298948Sadrian#include <net80211/ieee80211_var.h> 73298948Sadrian#include <net80211/ieee80211_radiotap.h> 74298948Sadrian#include <net80211/ieee80211_regdomain.h> 75298948Sadrian#include <net80211/ieee80211_phy.h> 76298948Sadrian#include <net80211/ieee80211_ratectl.h> 77298948Sadrian 78298948Sadrian#include <dev/bwn/if_bwnreg.h> 79298948Sadrian#include <dev/bwn/if_bwnvar.h> 80298948Sadrian 81298948Sadrian#include <dev/bwn/if_bwn_debug.h> 82298948Sadrian#include <dev/bwn/if_bwn_misc.h> 83298948Sadrian#include <dev/bwn/if_bwn_phy_g.h> 84298948Sadrian 85298948Sadrianstatic void bwn_phy_g_init_sub(struct bwn_mac *); 86298948Sadrianstatic uint8_t bwn_has_hwpctl(struct bwn_mac *); 87298948Sadrianstatic void bwn_phy_init_b5(struct bwn_mac *); 88298948Sadrianstatic void bwn_phy_init_b6(struct bwn_mac *); 89298948Sadrianstatic void bwn_phy_init_a(struct bwn_mac *); 90298948Sadrianstatic void bwn_loopback_calcgain(struct bwn_mac *); 91298948Sadrianstatic uint16_t bwn_rf_init_bcm2050(struct bwn_mac *); 92298948Sadrianstatic void bwn_lo_g_init(struct bwn_mac *); 93298948Sadrianstatic void bwn_lo_g_adjust(struct bwn_mac *); 94298948Sadrianstatic void bwn_lo_get_powervector(struct bwn_mac *); 95298948Sadrianstatic struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *, 96298948Sadrian const struct bwn_bbatt *, const struct bwn_rfatt *); 97298948Sadrianstatic void bwn_lo_write(struct bwn_mac *, struct bwn_loctl *); 98298948Sadrianstatic void bwn_phy_hwpctl_init(struct bwn_mac *); 99298948Sadrianstatic void bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t); 100298948Sadrianstatic void bwn_phy_g_set_txpwr_sub(struct bwn_mac *, 101298948Sadrian const struct bwn_bbatt *, const struct bwn_rfatt *, 102298948Sadrian uint8_t); 103298948Sadrianstatic void bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t); 104298948Sadrianstatic uint16_t bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t); 105298948Sadrianstatic void bwn_spu_workaround(struct bwn_mac *, uint8_t); 106298948Sadrianstatic void bwn_wa_init(struct bwn_mac *); 107298948Sadrianstatic void bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t, 108298948Sadrian uint16_t); 109298948Sadrianstatic void bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t, 110298948Sadrian uint32_t); 111298948Sadrianstatic void bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t, 112298948Sadrian uint16_t); 113298948Sadrianstatic int16_t bwn_nrssi_read(struct bwn_mac *, uint16_t); 114298948Sadrianstatic void bwn_nrssi_offset(struct bwn_mac *); 115298948Sadrianstatic void bwn_nrssi_threshold(struct bwn_mac *); 116298948Sadrianstatic void bwn_nrssi_slope_11g(struct bwn_mac *); 117298948Sadrianstatic void bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t, 118298948Sadrian int16_t); 119298948Sadrianstatic void bwn_set_original_gains(struct bwn_mac *); 120298948Sadrianstatic void bwn_hwpctl_early_init(struct bwn_mac *); 121298948Sadrianstatic void bwn_hwpctl_init_gphy(struct bwn_mac *); 122298948Sadrianstatic uint16_t bwn_phy_g_chan2freq(uint8_t); 123298948Sadrianstatic void bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t); 124298948Sadrian 125298948Sadrian/* Stuff we need */ 126298948Sadrian 127298948Sadrianstatic uint16_t bwn_phy_g_txctl(struct bwn_mac *mac); 128298948Sadrianstatic int bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset); 129298948Sadrianstatic void bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp); 130298948Sadrianstatic void bwn_phy_lock(struct bwn_mac *mac); 131298948Sadrianstatic void bwn_phy_unlock(struct bwn_mac *mac); 132298948Sadrianstatic void bwn_rf_lock(struct bwn_mac *mac); 133298948Sadrianstatic void bwn_rf_unlock(struct bwn_mac *mac); 134298948Sadrian 135298948Sadrianstatic const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1; 136298948Sadrianstatic const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2; 137298948Sadrianstatic const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1; 138298948Sadrianstatic const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2; 139298948Sadrianstatic const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3; 140298948Sadrianconst uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE; 141298948Sadrian 142298948Sadrianstatic uint8_t 143298948Sadrianbwn_has_hwpctl(struct bwn_mac *mac) 144298948Sadrian{ 145298948Sadrian 146298948Sadrian if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL) 147298948Sadrian return (0); 148298948Sadrian return (mac->mac_phy.use_hwpctl(mac)); 149298948Sadrian} 150298948Sadrian 151298948Sadrianint 152298948Sadrianbwn_phy_g_attach(struct bwn_mac *mac) 153298948Sadrian{ 154298948Sadrian struct bwn_softc *sc = mac->mac_sc; 155298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 156298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 157298948Sadrian unsigned int i; 158298948Sadrian int16_t pab0, pab1, pab2; 159298948Sadrian static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE; 160298948Sadrian int8_t bg; 161298948Sadrian 162298948Sadrian bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev); 163298948Sadrian pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev); 164298948Sadrian pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev); 165298948Sadrian pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev); 166298948Sadrian 167298948Sadrian if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050)) 168298948Sadrian device_printf(sc->sc_dev, "not supported anymore\n"); 169298948Sadrian 170298948Sadrian pg->pg_flags = 0; 171298948Sadrian if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 || 172298948Sadrian pab2 == -1) { 173298948Sadrian pg->pg_idletssi = 52; 174298948Sadrian pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table; 175298948Sadrian return (0); 176298948Sadrian } 177298948Sadrian 178298948Sadrian pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg; 179298948Sadrian pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO); 180298948Sadrian if (pg->pg_tssi2dbm == NULL) { 181298948Sadrian device_printf(sc->sc_dev, "failed to allocate buffer\n"); 182298948Sadrian return (ENOMEM); 183298948Sadrian } 184298948Sadrian for (i = 0; i < 64; i++) { 185298948Sadrian int32_t m1, m2, f, q, delta; 186298948Sadrian int8_t j = 0; 187298948Sadrian 188298948Sadrian m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32); 189298948Sadrian m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1); 190298948Sadrian f = 256; 191298948Sadrian 192298948Sadrian do { 193298948Sadrian if (j > 15) { 194298948Sadrian device_printf(sc->sc_dev, 195298948Sadrian "failed to generate tssi2dBm\n"); 196298948Sadrian free(pg->pg_tssi2dbm, M_DEVBUF); 197298948Sadrian return (ENOMEM); 198298948Sadrian } 199298948Sadrian q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) * 200298948Sadrian f, 2048); 201298948Sadrian delta = abs(q - f); 202298948Sadrian f = q; 203298948Sadrian j++; 204298948Sadrian } while (delta >= 2); 205298948Sadrian 206298948Sadrian pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127), 207298948Sadrian 128); 208298948Sadrian } 209298948Sadrian 210298948Sadrian pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC; 211298948Sadrian return (0); 212298948Sadrian} 213298948Sadrian 214298948Sadrianvoid 215298948Sadrianbwn_phy_g_detach(struct bwn_mac *mac) 216298948Sadrian{ 217298948Sadrian struct bwn_phy_g *pg = &mac->mac_phy.phy_g; 218298948Sadrian 219298948Sadrian if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) { 220298948Sadrian free(pg->pg_tssi2dbm, M_DEVBUF); 221298948Sadrian pg->pg_tssi2dbm = NULL; 222298948Sadrian } 223298948Sadrian pg->pg_flags = 0; 224298948Sadrian} 225298948Sadrian 226298948Sadrianvoid 227298948Sadrianbwn_phy_g_init_pre(struct bwn_mac *mac) 228298948Sadrian{ 229298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 230298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 231298948Sadrian void *tssi2dbm; 232298948Sadrian int idletssi; 233298948Sadrian unsigned int i; 234298948Sadrian 235298948Sadrian tssi2dbm = pg->pg_tssi2dbm; 236298948Sadrian idletssi = pg->pg_idletssi; 237298948Sadrian 238298948Sadrian memset(pg, 0, sizeof(*pg)); 239298948Sadrian 240298948Sadrian pg->pg_tssi2dbm = tssi2dbm; 241298948Sadrian pg->pg_idletssi = idletssi; 242298948Sadrian 243298948Sadrian memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig)); 244298948Sadrian 245298948Sadrian for (i = 0; i < N(pg->pg_nrssi); i++) 246298948Sadrian pg->pg_nrssi[i] = -1000; 247298948Sadrian for (i = 0; i < N(pg->pg_nrssi_lt); i++) 248298948Sadrian pg->pg_nrssi_lt[i] = i; 249298948Sadrian pg->pg_lofcal = 0xffff; 250298948Sadrian pg->pg_initval = 0xffff; 251298948Sadrian pg->pg_immode = BWN_IMMODE_NONE; 252298948Sadrian pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN; 253298948Sadrian pg->pg_avgtssi = 0xff; 254298948Sadrian 255298948Sadrian pg->pg_loctl.tx_bias = 0xff; 256298948Sadrian TAILQ_INIT(&pg->pg_loctl.calib_list); 257298948Sadrian} 258298948Sadrian 259298948Sadrianint 260298948Sadrianbwn_phy_g_prepare_hw(struct bwn_mac *mac) 261298948Sadrian{ 262298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 263298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 264298948Sadrian struct bwn_softc *sc = mac->mac_sc; 265298948Sadrian struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 266298948Sadrian static const struct bwn_rfatt rfatt0[] = { 267298948Sadrian { 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 }, { 9, 0 }, { 2, 0 }, 268298948Sadrian { 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 }, 269298948Sadrian { 3, 1 }, { 4, 1 } 270298948Sadrian }; 271298948Sadrian static const struct bwn_rfatt rfatt1[] = { 272298948Sadrian { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 }, 273298948Sadrian { 14, 1 } 274298948Sadrian }; 275298948Sadrian static const struct bwn_rfatt rfatt2[] = { 276298948Sadrian { 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 }, 277298948Sadrian { 9, 1 } 278298948Sadrian }; 279298948Sadrian static const struct bwn_bbatt bbatt_0[] = { 280298948Sadrian { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 } 281298948Sadrian }; 282298948Sadrian 283298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__)); 284298948Sadrian 285298948Sadrian if (phy->rf_ver == 0x2050 && phy->rf_rev < 6) 286298948Sadrian pg->pg_bbatt.att = 0; 287298948Sadrian else 288298948Sadrian pg->pg_bbatt.att = 2; 289298948Sadrian 290298948Sadrian /* prepare Radio Attenuation */ 291298948Sadrian pg->pg_rfatt.padmix = 0; 292298948Sadrian 293298948Sadrian if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM && 294298948Sadrian siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) { 295298948Sadrian if (siba_get_pci_revid(sc->sc_dev) < 0x43) { 296298948Sadrian pg->pg_rfatt.att = 2; 297298948Sadrian goto done; 298298948Sadrian } else if (siba_get_pci_revid(sc->sc_dev) < 0x51) { 299298948Sadrian pg->pg_rfatt.att = 3; 300298948Sadrian goto done; 301298948Sadrian } 302298948Sadrian } 303298948Sadrian 304298948Sadrian if (phy->type == BWN_PHYTYPE_A) { 305298948Sadrian pg->pg_rfatt.att = 0x60; 306298948Sadrian goto done; 307298948Sadrian } 308298948Sadrian 309298948Sadrian switch (phy->rf_ver) { 310298948Sadrian case 0x2050: 311298948Sadrian switch (phy->rf_rev) { 312298948Sadrian case 0: 313298948Sadrian pg->pg_rfatt.att = 5; 314298948Sadrian goto done; 315298948Sadrian case 1: 316298948Sadrian if (phy->type == BWN_PHYTYPE_G) { 317298948Sadrian if (siba_get_pci_subvendor(sc->sc_dev) == 318298948Sadrian SIBA_BOARDVENDOR_BCM && 319298948Sadrian siba_get_pci_subdevice(sc->sc_dev) == 320298948Sadrian SIBA_BOARD_BCM4309G && 321298948Sadrian siba_get_pci_revid(sc->sc_dev) >= 30) 322298948Sadrian pg->pg_rfatt.att = 3; 323298948Sadrian else if (siba_get_pci_subvendor(sc->sc_dev) == 324298948Sadrian SIBA_BOARDVENDOR_BCM && 325298948Sadrian siba_get_pci_subdevice(sc->sc_dev) == 326298948Sadrian SIBA_BOARD_BU4306) 327298948Sadrian pg->pg_rfatt.att = 3; 328298948Sadrian else 329298948Sadrian pg->pg_rfatt.att = 1; 330298948Sadrian } else { 331298948Sadrian if (siba_get_pci_subvendor(sc->sc_dev) == 332298948Sadrian SIBA_BOARDVENDOR_BCM && 333298948Sadrian siba_get_pci_subdevice(sc->sc_dev) == 334298948Sadrian SIBA_BOARD_BCM4309G && 335298948Sadrian siba_get_pci_revid(sc->sc_dev) >= 30) 336298948Sadrian pg->pg_rfatt.att = 7; 337298948Sadrian else 338298948Sadrian pg->pg_rfatt.att = 6; 339298948Sadrian } 340298948Sadrian goto done; 341298948Sadrian case 2: 342298948Sadrian if (phy->type == BWN_PHYTYPE_G) { 343298948Sadrian if (siba_get_pci_subvendor(sc->sc_dev) == 344298948Sadrian SIBA_BOARDVENDOR_BCM && 345298948Sadrian siba_get_pci_subdevice(sc->sc_dev) == 346298948Sadrian SIBA_BOARD_BCM4309G && 347298948Sadrian siba_get_pci_revid(sc->sc_dev) >= 30) 348298948Sadrian pg->pg_rfatt.att = 3; 349298948Sadrian else if (siba_get_pci_subvendor(sc->sc_dev) == 350298948Sadrian SIBA_BOARDVENDOR_BCM && 351298948Sadrian siba_get_pci_subdevice(sc->sc_dev) == 352298948Sadrian SIBA_BOARD_BU4306) 353298948Sadrian pg->pg_rfatt.att = 5; 354298948Sadrian else if (siba_get_chipid(sc->sc_dev) == 0x4320) 355298948Sadrian pg->pg_rfatt.att = 4; 356298948Sadrian else 357298948Sadrian pg->pg_rfatt.att = 3; 358298948Sadrian } else 359298948Sadrian pg->pg_rfatt.att = 6; 360298948Sadrian goto done; 361298948Sadrian case 3: 362298948Sadrian pg->pg_rfatt.att = 5; 363298948Sadrian goto done; 364298948Sadrian case 4: 365298948Sadrian case 5: 366298948Sadrian pg->pg_rfatt.att = 1; 367298948Sadrian goto done; 368298948Sadrian case 6: 369298948Sadrian case 7: 370298948Sadrian pg->pg_rfatt.att = 5; 371298948Sadrian goto done; 372298948Sadrian case 8: 373298948Sadrian pg->pg_rfatt.att = 0xa; 374298948Sadrian pg->pg_rfatt.padmix = 1; 375298948Sadrian goto done; 376298948Sadrian case 9: 377298948Sadrian default: 378298948Sadrian pg->pg_rfatt.att = 5; 379298948Sadrian goto done; 380298948Sadrian } 381298948Sadrian break; 382298948Sadrian case 0x2053: 383298948Sadrian switch (phy->rf_rev) { 384298948Sadrian case 1: 385298948Sadrian pg->pg_rfatt.att = 6; 386298948Sadrian goto done; 387298948Sadrian } 388298948Sadrian break; 389298948Sadrian } 390298948Sadrian pg->pg_rfatt.att = 5; 391298948Sadriandone: 392298948Sadrian pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4); 393298948Sadrian 394298948Sadrian if (!bwn_has_hwpctl(mac)) { 395298948Sadrian lo->rfatt.array = rfatt0; 396298948Sadrian lo->rfatt.len = N(rfatt0); 397298948Sadrian lo->rfatt.min = 0; 398298948Sadrian lo->rfatt.max = 9; 399298948Sadrian goto genbbatt; 400298948Sadrian } 401298948Sadrian if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) { 402298948Sadrian lo->rfatt.array = rfatt1; 403298948Sadrian lo->rfatt.len = N(rfatt1); 404298948Sadrian lo->rfatt.min = 0; 405298948Sadrian lo->rfatt.max = 14; 406298948Sadrian goto genbbatt; 407298948Sadrian } 408298948Sadrian lo->rfatt.array = rfatt2; 409298948Sadrian lo->rfatt.len = N(rfatt2); 410298948Sadrian lo->rfatt.min = 0; 411298948Sadrian lo->rfatt.max = 9; 412298948Sadriangenbbatt: 413298948Sadrian lo->bbatt.array = bbatt_0; 414298948Sadrian lo->bbatt.len = N(bbatt_0); 415298948Sadrian lo->bbatt.min = 0; 416298948Sadrian lo->bbatt.max = 8; 417298948Sadrian 418298948Sadrian BWN_READ_4(mac, BWN_MACCTL); 419298948Sadrian if (phy->rev == 1) { 420298948Sadrian phy->gmode = 0; 421298948Sadrian bwn_reset_core(mac, 0); 422298948Sadrian bwn_phy_g_init_sub(mac); 423298948Sadrian phy->gmode = 1; 424299776Sadrian bwn_reset_core(mac, 1); 425298948Sadrian } 426298948Sadrian return (0); 427298948Sadrian} 428298948Sadrian 429298948Sadrianstatic uint16_t 430298948Sadrianbwn_phy_g_txctl(struct bwn_mac *mac) 431298948Sadrian{ 432298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 433298948Sadrian 434298948Sadrian if (phy->rf_ver != 0x2050) 435298948Sadrian return (0); 436298948Sadrian if (phy->rf_rev == 1) 437298948Sadrian return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX); 438298948Sadrian if (phy->rf_rev < 6) 439298948Sadrian return (BWN_TXCTL_PA2DB); 440298948Sadrian if (phy->rf_rev == 8) 441298948Sadrian return (BWN_TXCTL_TXMIX); 442298948Sadrian return (0); 443298948Sadrian} 444298948Sadrian 445298948Sadrianint 446298948Sadrianbwn_phy_g_init(struct bwn_mac *mac) 447298948Sadrian{ 448298948Sadrian 449298948Sadrian bwn_phy_g_init_sub(mac); 450298948Sadrian return (0); 451298948Sadrian} 452298948Sadrian 453298948Sadrianvoid 454298948Sadrianbwn_phy_g_exit(struct bwn_mac *mac) 455298948Sadrian{ 456298948Sadrian struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl; 457298948Sadrian struct bwn_lo_calib *cal, *tmp; 458298948Sadrian 459298948Sadrian if (lo == NULL) 460298948Sadrian return; 461298948Sadrian TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) { 462298948Sadrian TAILQ_REMOVE(&lo->calib_list, cal, list); 463298948Sadrian free(cal, M_DEVBUF); 464298948Sadrian } 465298948Sadrian} 466298948Sadrian 467298948Sadrianuint16_t 468298948Sadrianbwn_phy_g_read(struct bwn_mac *mac, uint16_t reg) 469298948Sadrian{ 470298948Sadrian 471298948Sadrian BWN_WRITE_2(mac, BWN_PHYCTL, reg); 472298948Sadrian return (BWN_READ_2(mac, BWN_PHYDATA)); 473298948Sadrian} 474298948Sadrian 475298948Sadrianvoid 476298948Sadrianbwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 477298948Sadrian{ 478298948Sadrian 479298948Sadrian BWN_WRITE_2(mac, BWN_PHYCTL, reg); 480298948Sadrian BWN_WRITE_2(mac, BWN_PHYDATA, value); 481298948Sadrian} 482298948Sadrian 483298948Sadrianuint16_t 484298948Sadrianbwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg) 485298948Sadrian{ 486298948Sadrian 487298948Sadrian KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__)); 488298948Sadrian BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80); 489298948Sadrian return (BWN_READ_2(mac, BWN_RFDATALO)); 490298948Sadrian} 491298948Sadrian 492298948Sadrianvoid 493298948Sadrianbwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 494298948Sadrian{ 495298948Sadrian 496298948Sadrian KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__)); 497298948Sadrian BWN_WRITE_2(mac, BWN_RFCTL, reg); 498298948Sadrian BWN_WRITE_2(mac, BWN_RFDATALO, value); 499298948Sadrian} 500298948Sadrian 501298948Sadrianint 502298948Sadrianbwn_phy_g_hwpctl(struct bwn_mac *mac) 503298948Sadrian{ 504298948Sadrian 505298948Sadrian return (mac->mac_phy.rev >= 6); 506298948Sadrian} 507298948Sadrian 508298948Sadrianvoid 509298948Sadrianbwn_phy_g_rf_onoff(struct bwn_mac *mac, int on) 510298948Sadrian{ 511298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 512298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 513298948Sadrian unsigned int channel; 514298948Sadrian uint16_t rfover, rfoverval; 515298948Sadrian 516298948Sadrian if (on) { 517298948Sadrian if (phy->rf_on) 518298948Sadrian return; 519298948Sadrian 520298948Sadrian BWN_PHY_WRITE(mac, 0x15, 0x8000); 521298948Sadrian BWN_PHY_WRITE(mac, 0x15, 0xcc00); 522298948Sadrian BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0)); 523298948Sadrian if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) { 524298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 525298948Sadrian pg->pg_radioctx_over); 526298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 527298948Sadrian pg->pg_radioctx_overval); 528298948Sadrian pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID; 529298948Sadrian } 530298948Sadrian channel = phy->chan; 531298948Sadrian bwn_phy_g_switch_chan(mac, 6, 1); 532298948Sadrian bwn_phy_g_switch_chan(mac, channel, 0); 533298948Sadrian return; 534298948Sadrian } 535298948Sadrian 536298948Sadrian rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER); 537298948Sadrian rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL); 538298948Sadrian pg->pg_radioctx_over = rfover; 539298948Sadrian pg->pg_radioctx_overval = rfoverval; 540298948Sadrian pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID; 541298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c); 542298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73); 543298948Sadrian} 544298948Sadrian 545298948Sadrianint 546298948Sadrianbwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan) 547298948Sadrian{ 548298948Sadrian 549298948Sadrian if ((newchan < 1) || (newchan > 14)) 550298948Sadrian return (EINVAL); 551298948Sadrian bwn_phy_g_switch_chan(mac, newchan, 0); 552298948Sadrian 553298948Sadrian return (0); 554298948Sadrian} 555298948Sadrian 556298948Sadrianuint32_t 557298948Sadrianbwn_phy_g_get_default_chan(struct bwn_mac *mac) 558298948Sadrian{ 559298948Sadrian 560298948Sadrian return (1); 561298948Sadrian} 562298948Sadrian 563298948Sadrianvoid 564298948Sadrianbwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna) 565298948Sadrian{ 566298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 567298948Sadrian uint64_t hf; 568298948Sadrian int autodiv = 0; 569298948Sadrian uint16_t tmp; 570298948Sadrian 571298948Sadrian if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1) 572298948Sadrian autodiv = 1; 573298948Sadrian 574298948Sadrian hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER; 575298948Sadrian bwn_hf_write(mac, hf); 576298948Sadrian 577298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG, 578298948Sadrian (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) | 579298948Sadrian ((autodiv ? BWN_ANTAUTO1 : antenna) 580298948Sadrian << BWN_PHY_BBANDCFG_RXANT_SHIFT)); 581298948Sadrian 582298948Sadrian if (autodiv) { 583298948Sadrian tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL); 584298948Sadrian if (antenna == BWN_ANTAUTO1) 585298948Sadrian tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1; 586298948Sadrian else 587298948Sadrian tmp |= BWN_PHY_ANTDWELL_AUTODIV1; 588298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp); 589298948Sadrian } 590298948Sadrian tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT); 591298948Sadrian if (autodiv) 592298948Sadrian tmp |= BWN_PHY_ANTWRSETT_ARXDIV; 593298948Sadrian else 594298948Sadrian tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV; 595298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp); 596298948Sadrian if (phy->rev >= 2) { 597298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM61, 598298948Sadrian BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10); 599298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK, 600298948Sadrian (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) | 601298948Sadrian 0x15); 602298948Sadrian if (phy->rev == 2) 603298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8); 604298948Sadrian else 605298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 606298948Sadrian (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) | 607298948Sadrian 8); 608298948Sadrian } 609298948Sadrian if (phy->rev >= 6) 610298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc); 611298948Sadrian 612298948Sadrian hf |= BWN_HF_UCODE_ANTDIV_HELPER; 613298948Sadrian bwn_hf_write(mac, hf); 614298948Sadrian} 615298948Sadrian 616298948Sadrianint 617298948Sadrianbwn_phy_g_im(struct bwn_mac *mac, int mode) 618298948Sadrian{ 619298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 620298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 621298948Sadrian 622298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__)); 623298948Sadrian KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__)); 624298948Sadrian 625298948Sadrian if (phy->rev == 0 || !phy->gmode) 626298948Sadrian return (ENODEV); 627298948Sadrian 628298948Sadrian pg->pg_aci_wlan_automatic = 0; 629298948Sadrian return (0); 630298948Sadrian} 631298948Sadrian 632299791Sadrianbwn_txpwr_result_t 633298948Sadrianbwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi) 634298948Sadrian{ 635298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 636298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 637298948Sadrian struct bwn_softc *sc = mac->mac_sc; 638298948Sadrian unsigned int tssi; 639298948Sadrian int cck, ofdm; 640298948Sadrian int power; 641298948Sadrian int rfatt, bbatt; 642298948Sadrian unsigned int max; 643298948Sadrian 644298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__)); 645298948Sadrian 646298948Sadrian cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK); 647298948Sadrian ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G); 648298948Sadrian if (cck < 0 && ofdm < 0) { 649298948Sadrian if (ignore_tssi == 0) 650298948Sadrian return (BWN_TXPWR_RES_DONE); 651298948Sadrian cck = 0; 652298948Sadrian ofdm = 0; 653298948Sadrian } 654298948Sadrian tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2); 655298948Sadrian if (pg->pg_avgtssi != 0xff) 656298948Sadrian tssi = (tssi + pg->pg_avgtssi) / 2; 657298948Sadrian pg->pg_avgtssi = tssi; 658298948Sadrian KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__)); 659298948Sadrian 660298948Sadrian max = siba_sprom_get_maxpwr_bg(sc->sc_dev); 661298948Sadrian if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) 662298948Sadrian max -= 3; 663298948Sadrian if (max >= 120) { 664298948Sadrian device_printf(sc->sc_dev, "invalid max TX-power value\n"); 665298948Sadrian max = 80; 666298948Sadrian siba_sprom_set_maxpwr_bg(sc->sc_dev, max); 667298948Sadrian } 668298948Sadrian 669298948Sadrian power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) - 670298948Sadrian (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi + 671298948Sadrian tssi, 0x00), 0x3f)]); 672298948Sadrian if (power == 0) 673298948Sadrian return (BWN_TXPWR_RES_DONE); 674298948Sadrian 675298948Sadrian rfatt = -((power + 7) / 8); 676298948Sadrian bbatt = (-(power / 2)) - (4 * rfatt); 677298948Sadrian if ((rfatt == 0) && (bbatt == 0)) 678298948Sadrian return (BWN_TXPWR_RES_DONE); 679298948Sadrian pg->pg_bbatt_delta = bbatt; 680298948Sadrian pg->pg_rfatt_delta = rfatt; 681298948Sadrian return (BWN_TXPWR_RES_NEED_ADJUST); 682298948Sadrian} 683298948Sadrian 684298948Sadrianvoid 685298948Sadrianbwn_phy_g_set_txpwr(struct bwn_mac *mac) 686298948Sadrian{ 687298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 688298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 689298948Sadrian struct bwn_softc *sc = mac->mac_sc; 690298948Sadrian int rfatt, bbatt; 691298948Sadrian uint8_t txctl; 692298948Sadrian 693298948Sadrian bwn_mac_suspend(mac); 694298948Sadrian 695298948Sadrian BWN_ASSERT_LOCKED(sc); 696298948Sadrian 697298948Sadrian bbatt = pg->pg_bbatt.att; 698298948Sadrian bbatt += pg->pg_bbatt_delta; 699298948Sadrian rfatt = pg->pg_rfatt.att; 700298948Sadrian rfatt += pg->pg_rfatt_delta; 701298948Sadrian 702298948Sadrian bwn_phy_g_setatt(mac, &bbatt, &rfatt); 703298948Sadrian txctl = pg->pg_txctl; 704298948Sadrian if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) { 705298948Sadrian if (rfatt <= 1) { 706298948Sadrian if (txctl == 0) { 707298948Sadrian txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX; 708298948Sadrian rfatt += 2; 709298948Sadrian bbatt += 2; 710298948Sadrian } else if (siba_sprom_get_bf_lo(sc->sc_dev) & 711298948Sadrian BWN_BFL_PACTRL) { 712298948Sadrian bbatt += 4 * (rfatt - 2); 713298948Sadrian rfatt = 2; 714298948Sadrian } 715298948Sadrian } else if (rfatt > 4 && txctl) { 716298948Sadrian txctl = 0; 717298948Sadrian if (bbatt < 3) { 718298948Sadrian rfatt -= 3; 719298948Sadrian bbatt += 2; 720298948Sadrian } else { 721298948Sadrian rfatt -= 2; 722298948Sadrian bbatt -= 2; 723298948Sadrian } 724298948Sadrian } 725298948Sadrian } 726298948Sadrian pg->pg_txctl = txctl; 727298948Sadrian bwn_phy_g_setatt(mac, &bbatt, &rfatt); 728298948Sadrian pg->pg_rfatt.att = rfatt; 729298948Sadrian pg->pg_bbatt.att = bbatt; 730298948Sadrian 731298948Sadrian DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__); 732298948Sadrian 733298948Sadrian bwn_phy_lock(mac); 734298948Sadrian bwn_rf_lock(mac); 735298948Sadrian bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt, 736298948Sadrian pg->pg_txctl); 737298948Sadrian bwn_rf_unlock(mac); 738298948Sadrian bwn_phy_unlock(mac); 739298948Sadrian 740298948Sadrian bwn_mac_enable(mac); 741298948Sadrian} 742298948Sadrian 743298948Sadrianvoid 744298948Sadrianbwn_phy_g_task_15s(struct bwn_mac *mac) 745298948Sadrian{ 746298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 747298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 748298948Sadrian struct bwn_softc *sc = mac->mac_sc; 749298948Sadrian struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 750298948Sadrian unsigned long expire, now; 751298948Sadrian struct bwn_lo_calib *cal, *tmp; 752298948Sadrian uint8_t expired = 0; 753298948Sadrian 754298948Sadrian bwn_mac_suspend(mac); 755298948Sadrian 756298948Sadrian if (lo == NULL) 757298948Sadrian goto fail; 758298948Sadrian 759298948Sadrian BWN_GETTIME(now); 760298948Sadrian if (bwn_has_hwpctl(mac)) { 761298948Sadrian expire = now - BWN_LO_PWRVEC_EXPIRE; 762298948Sadrian if (ieee80211_time_before(lo->pwr_vec_read_time, expire)) { 763298948Sadrian bwn_lo_get_powervector(mac); 764298948Sadrian bwn_phy_g_dc_lookup_init(mac, 0); 765298948Sadrian } 766298948Sadrian goto fail; 767298948Sadrian } 768298948Sadrian 769298948Sadrian expire = now - BWN_LO_CALIB_EXPIRE; 770298948Sadrian TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) { 771298948Sadrian if (!ieee80211_time_before(cal->calib_time, expire)) 772298948Sadrian continue; 773298948Sadrian if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) && 774298948Sadrian BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) { 775298948Sadrian KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__)); 776298948Sadrian expired = 1; 777298948Sadrian } 778298948Sadrian 779298948Sadrian DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n", 780298948Sadrian cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix, 781298948Sadrian cal->ctl.i, cal->ctl.q); 782298948Sadrian 783298948Sadrian TAILQ_REMOVE(&lo->calib_list, cal, list); 784298948Sadrian free(cal, M_DEVBUF); 785298948Sadrian } 786298948Sadrian if (expired || TAILQ_EMPTY(&lo->calib_list)) { 787298948Sadrian cal = bwn_lo_calibset(mac, &pg->pg_bbatt, 788298948Sadrian &pg->pg_rfatt); 789298948Sadrian if (cal == NULL) { 790298948Sadrian device_printf(sc->sc_dev, 791298948Sadrian "failed to recalibrate LO\n"); 792298948Sadrian goto fail; 793298948Sadrian } 794298948Sadrian TAILQ_INSERT_TAIL(&lo->calib_list, cal, list); 795298948Sadrian bwn_lo_write(mac, &cal->ctl); 796298948Sadrian } 797298948Sadrian 798298948Sadrianfail: 799298948Sadrian bwn_mac_enable(mac); 800298948Sadrian} 801298948Sadrian 802298948Sadrianvoid 803298948Sadrianbwn_phy_g_task_60s(struct bwn_mac *mac) 804298948Sadrian{ 805298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 806298948Sadrian struct bwn_softc *sc = mac->mac_sc; 807298948Sadrian uint8_t old = phy->chan; 808298948Sadrian 809298948Sadrian if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) 810298948Sadrian return; 811298948Sadrian 812298948Sadrian bwn_mac_suspend(mac); 813298948Sadrian bwn_nrssi_slope_11g(mac); 814298948Sadrian if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) { 815298948Sadrian bwn_switch_channel(mac, (old >= 8) ? 1 : 13); 816298948Sadrian bwn_switch_channel(mac, old); 817298948Sadrian } 818298948Sadrian bwn_mac_enable(mac); 819298948Sadrian} 820298948Sadrian 821298948Sadrianvoid 822298948Sadrianbwn_phy_switch_analog(struct bwn_mac *mac, int on) 823298948Sadrian{ 824298948Sadrian 825298948Sadrian BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4); 826298948Sadrian} 827298948Sadrian 828298948Sadrianstatic void 829298948Sadrianbwn_phy_g_init_sub(struct bwn_mac *mac) 830298948Sadrian{ 831298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 832298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 833298948Sadrian struct bwn_softc *sc = mac->mac_sc; 834298948Sadrian uint16_t i, tmp; 835298948Sadrian 836298948Sadrian if (phy->rev == 1) 837298948Sadrian bwn_phy_init_b5(mac); 838298948Sadrian else 839298948Sadrian bwn_phy_init_b6(mac); 840298948Sadrian 841298948Sadrian if (phy->rev >= 2 || phy->gmode) 842298948Sadrian bwn_phy_init_a(mac); 843298948Sadrian 844298948Sadrian if (phy->rev >= 2) { 845298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0); 846298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0); 847298948Sadrian } 848298948Sadrian if (phy->rev == 2) { 849298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0); 850298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0); 851298948Sadrian } 852298948Sadrian if (phy->rev > 5) { 853298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400); 854298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0); 855298948Sadrian } 856298948Sadrian if (phy->gmode || phy->rev >= 2) { 857298948Sadrian tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM); 858298948Sadrian tmp &= BWN_PHYVER_VERSION; 859298948Sadrian if (tmp == 3 || tmp == 5) { 860298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816); 861298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006); 862298948Sadrian } 863298948Sadrian if (tmp == 5) { 864298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff, 865298948Sadrian 0x1f00); 866298948Sadrian } 867298948Sadrian } 868298948Sadrian if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2) 869298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78); 870298948Sadrian if (phy->rf_rev == 8) { 871298948Sadrian BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80); 872298948Sadrian BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4); 873298948Sadrian } 874298948Sadrian if (BWN_HAS_LOOPBACK(phy)) 875298948Sadrian bwn_loopback_calcgain(mac); 876298948Sadrian 877298948Sadrian if (phy->rf_rev != 8) { 878298948Sadrian if (pg->pg_initval == 0xffff) 879298948Sadrian pg->pg_initval = bwn_rf_init_bcm2050(mac); 880298948Sadrian else 881298948Sadrian BWN_RF_WRITE(mac, 0x0078, pg->pg_initval); 882298948Sadrian } 883298948Sadrian bwn_lo_g_init(mac); 884298948Sadrian if (BWN_HAS_TXMAG(phy)) { 885298948Sadrian BWN_RF_WRITE(mac, 0x52, 886298948Sadrian (BWN_RF_READ(mac, 0x52) & 0xff00) 887298948Sadrian | pg->pg_loctl.tx_bias | 888298948Sadrian pg->pg_loctl.tx_magn); 889298948Sadrian } else { 890298948Sadrian BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias); 891298948Sadrian } 892298948Sadrian if (phy->rev >= 6) { 893298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff, 894298948Sadrian (pg->pg_loctl.tx_bias << 12)); 895298948Sadrian } 896298948Sadrian if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) 897298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075); 898298948Sadrian else 899298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f); 900298948Sadrian if (phy->rev < 2) 901298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101); 902298948Sadrian else 903298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202); 904298948Sadrian if (phy->gmode || phy->rev >= 2) { 905298948Sadrian bwn_lo_g_adjust(mac); 906298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078); 907298948Sadrian } 908298948Sadrian 909298948Sadrian if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) { 910298948Sadrian for (i = 0; i < 64; i++) { 911298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i); 912298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA, 913298948Sadrian (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff, 914298948Sadrian -32), 31)); 915298948Sadrian } 916298948Sadrian bwn_nrssi_threshold(mac); 917298948Sadrian } else if (phy->gmode || phy->rev >= 2) { 918298948Sadrian if (pg->pg_nrssi[0] == -1000) { 919298948Sadrian KASSERT(pg->pg_nrssi[1] == -1000, 920298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 921298948Sadrian bwn_nrssi_slope_11g(mac); 922298948Sadrian } else 923298948Sadrian bwn_nrssi_threshold(mac); 924298948Sadrian } 925298948Sadrian if (phy->rf_rev == 8) 926298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230); 927298948Sadrian bwn_phy_hwpctl_init(mac); 928298948Sadrian if ((siba_get_chipid(sc->sc_dev) == 0x4306 929298948Sadrian && siba_get_chippkg(sc->sc_dev) == 2) || 0) { 930298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff); 931298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff); 932298948Sadrian } 933298948Sadrian} 934298948Sadrian 935298948Sadrianstatic void 936298948Sadrianbwn_phy_init_b5(struct bwn_mac *mac) 937298948Sadrian{ 938298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 939298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 940298948Sadrian struct bwn_softc *sc = mac->mac_sc; 941298948Sadrian uint16_t offset, value; 942298948Sadrian uint8_t old_channel; 943298948Sadrian 944298948Sadrian if (phy->analog == 1) 945298948Sadrian BWN_RF_SET(mac, 0x007a, 0x0050); 946298948Sadrian if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) && 947298948Sadrian (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) { 948298948Sadrian value = 0x2120; 949298948Sadrian for (offset = 0x00a8; offset < 0x00c7; offset++) { 950298948Sadrian BWN_PHY_WRITE(mac, offset, value); 951298948Sadrian value += 0x202; 952298948Sadrian } 953298948Sadrian } 954298948Sadrian BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700); 955298948Sadrian if (phy->rf_ver == 0x2050) 956298948Sadrian BWN_PHY_WRITE(mac, 0x0038, 0x0667); 957298948Sadrian 958298948Sadrian if (phy->gmode || phy->rev >= 2) { 959298948Sadrian if (phy->rf_ver == 0x2050) { 960298948Sadrian BWN_RF_SET(mac, 0x007a, 0x0020); 961298948Sadrian BWN_RF_SET(mac, 0x0051, 0x0004); 962298948Sadrian } 963298948Sadrian BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000); 964298948Sadrian 965298948Sadrian BWN_PHY_SET(mac, 0x0802, 0x0100); 966298948Sadrian BWN_PHY_SET(mac, 0x042b, 0x2000); 967298948Sadrian 968298948Sadrian BWN_PHY_WRITE(mac, 0x001c, 0x186a); 969298948Sadrian 970298948Sadrian BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900); 971298948Sadrian BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064); 972298948Sadrian BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a); 973298948Sadrian } 974298948Sadrian 975298948Sadrian if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP) 976298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11)); 977298948Sadrian 978298948Sadrian if (phy->analog == 1) { 979298948Sadrian BWN_PHY_WRITE(mac, 0x0026, 0xce00); 980298948Sadrian BWN_PHY_WRITE(mac, 0x0021, 0x3763); 981298948Sadrian BWN_PHY_WRITE(mac, 0x0022, 0x1bc3); 982298948Sadrian BWN_PHY_WRITE(mac, 0x0023, 0x06f9); 983298948Sadrian BWN_PHY_WRITE(mac, 0x0024, 0x037e); 984298948Sadrian } else 985298948Sadrian BWN_PHY_WRITE(mac, 0x0026, 0xcc00); 986298948Sadrian BWN_PHY_WRITE(mac, 0x0030, 0x00c6); 987298948Sadrian BWN_WRITE_2(mac, 0x03ec, 0x3f22); 988298948Sadrian 989298948Sadrian if (phy->analog == 1) 990298948Sadrian BWN_PHY_WRITE(mac, 0x0020, 0x3e1c); 991298948Sadrian else 992298948Sadrian BWN_PHY_WRITE(mac, 0x0020, 0x301c); 993298948Sadrian 994298948Sadrian if (phy->analog == 0) 995298948Sadrian BWN_WRITE_2(mac, 0x03e4, 0x3000); 996298948Sadrian 997298948Sadrian old_channel = phy->chan; 998298948Sadrian bwn_phy_g_switch_chan(mac, 7, 0); 999298948Sadrian 1000298948Sadrian if (phy->rf_ver != 0x2050) { 1001298948Sadrian BWN_RF_WRITE(mac, 0x0075, 0x0080); 1002298948Sadrian BWN_RF_WRITE(mac, 0x0079, 0x0081); 1003298948Sadrian } 1004298948Sadrian 1005298948Sadrian BWN_RF_WRITE(mac, 0x0050, 0x0020); 1006298948Sadrian BWN_RF_WRITE(mac, 0x0050, 0x0023); 1007298948Sadrian 1008298948Sadrian if (phy->rf_ver == 0x2050) { 1009298948Sadrian BWN_RF_WRITE(mac, 0x0050, 0x0020); 1010298948Sadrian BWN_RF_WRITE(mac, 0x005a, 0x0070); 1011298948Sadrian } 1012298948Sadrian 1013298948Sadrian BWN_RF_WRITE(mac, 0x005b, 0x007b); 1014298948Sadrian BWN_RF_WRITE(mac, 0x005c, 0x00b0); 1015298948Sadrian BWN_RF_SET(mac, 0x007a, 0x0007); 1016298948Sadrian 1017298948Sadrian bwn_phy_g_switch_chan(mac, old_channel, 0); 1018298948Sadrian BWN_PHY_WRITE(mac, 0x0014, 0x0080); 1019298948Sadrian BWN_PHY_WRITE(mac, 0x0032, 0x00ca); 1020298948Sadrian BWN_PHY_WRITE(mac, 0x002a, 0x88a3); 1021298948Sadrian 1022298948Sadrian bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt, 1023298948Sadrian pg->pg_txctl); 1024298948Sadrian 1025298948Sadrian if (phy->rf_ver == 0x2050) 1026298948Sadrian BWN_RF_WRITE(mac, 0x005d, 0x000d); 1027298948Sadrian 1028298948Sadrian BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004); 1029298948Sadrian} 1030298948Sadrian 1031298948Sadrianstatic void 1032298948Sadrianbwn_loopback_calcgain(struct bwn_mac *mac) 1033298948Sadrian{ 1034298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1035298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 1036298948Sadrian struct bwn_softc *sc = mac->mac_sc; 1037298948Sadrian uint16_t backup_phy[16] = { 0 }; 1038298948Sadrian uint16_t backup_radio[3]; 1039298948Sadrian uint16_t backup_bband; 1040298948Sadrian uint16_t i, j, loop_i_max; 1041298948Sadrian uint16_t trsw_rx; 1042298948Sadrian uint16_t loop1_outer_done, loop1_inner_done; 1043298948Sadrian 1044298948Sadrian backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0); 1045298948Sadrian backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG); 1046298948Sadrian backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER); 1047298948Sadrian backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL); 1048298948Sadrian if (phy->rev != 1) { 1049298948Sadrian backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER); 1050298948Sadrian backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL); 1051298948Sadrian } 1052298948Sadrian backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a)); 1053298948Sadrian backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59)); 1054298948Sadrian backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58)); 1055298948Sadrian backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a)); 1056298948Sadrian backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03)); 1057298948Sadrian backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK); 1058298948Sadrian backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL); 1059298948Sadrian backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b)); 1060298948Sadrian backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL); 1061298948Sadrian backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE); 1062298948Sadrian backup_bband = pg->pg_bbatt.att; 1063298948Sadrian backup_radio[0] = BWN_RF_READ(mac, 0x52); 1064298948Sadrian backup_radio[1] = BWN_RF_READ(mac, 0x43); 1065298948Sadrian backup_radio[2] = BWN_RF_READ(mac, 0x7a); 1066298948Sadrian 1067298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff); 1068298948Sadrian BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000); 1069298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002); 1070298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd); 1071298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001); 1072298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe); 1073298948Sadrian if (phy->rev != 1) { 1074298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001); 1075298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe); 1076298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002); 1077298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd); 1078298948Sadrian } 1079298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c); 1080298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c); 1081298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030); 1082298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10); 1083298948Sadrian 1084298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780); 1085298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810); 1086298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d); 1087298948Sadrian 1088298948Sadrian BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000); 1089298948Sadrian if (phy->rev != 1) { 1090298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004); 1091298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb); 1092298948Sadrian } 1093298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40); 1094298948Sadrian 1095298948Sadrian if (phy->rf_rev == 8) 1096298948Sadrian BWN_RF_WRITE(mac, 0x43, 0x000f); 1097298948Sadrian else { 1098298948Sadrian BWN_RF_WRITE(mac, 0x52, 0); 1099298948Sadrian BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9); 1100298948Sadrian } 1101298948Sadrian bwn_phy_g_set_bbatt(mac, 11); 1102298948Sadrian 1103298948Sadrian if (phy->rev >= 3) 1104298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020); 1105298948Sadrian else 1106298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020); 1107298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0); 1108298948Sadrian 1109298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01); 1110298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800); 1111298948Sadrian 1112298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100); 1113298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff); 1114298948Sadrian 1115298948Sadrian if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) { 1116298948Sadrian if (phy->rev >= 7) { 1117298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800); 1118298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000); 1119298948Sadrian } 1120298948Sadrian } 1121298948Sadrian BWN_RF_MASK(mac, 0x7a, 0x00f7); 1122298948Sadrian 1123298948Sadrian j = 0; 1124298948Sadrian loop_i_max = (phy->rf_rev == 8) ? 15 : 9; 1125298948Sadrian for (i = 0; i < loop_i_max; i++) { 1126298948Sadrian for (j = 0; j < 16; j++) { 1127298948Sadrian BWN_RF_WRITE(mac, 0x43, i); 1128298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, 1129298948Sadrian (j << 8)); 1130298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000); 1131298948Sadrian BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000); 1132298948Sadrian DELAY(20); 1133298948Sadrian if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc) 1134298948Sadrian goto done0; 1135298948Sadrian } 1136298948Sadrian } 1137298948Sadriandone0: 1138298948Sadrian loop1_outer_done = i; 1139298948Sadrian loop1_inner_done = j; 1140298948Sadrian if (j >= 8) { 1141298948Sadrian BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30); 1142298948Sadrian trsw_rx = 0x1b; 1143298948Sadrian for (j = j - 8; j < 16; j++) { 1144298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8); 1145298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000); 1146298948Sadrian BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000); 1147298948Sadrian DELAY(20); 1148298948Sadrian trsw_rx -= 3; 1149298948Sadrian if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc) 1150298948Sadrian goto done1; 1151298948Sadrian } 1152298948Sadrian } else 1153298948Sadrian trsw_rx = 0x18; 1154298948Sadriandone1: 1155298948Sadrian 1156298948Sadrian if (phy->rev != 1) { 1157298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]); 1158298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]); 1159298948Sadrian } 1160298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]); 1161298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]); 1162298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]); 1163298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]); 1164298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]); 1165298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]); 1166298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]); 1167298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]); 1168298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]); 1169298948Sadrian 1170298948Sadrian bwn_phy_g_set_bbatt(mac, backup_bband); 1171298948Sadrian 1172298948Sadrian BWN_RF_WRITE(mac, 0x52, backup_radio[0]); 1173298948Sadrian BWN_RF_WRITE(mac, 0x43, backup_radio[1]); 1174298948Sadrian BWN_RF_WRITE(mac, 0x7a, backup_radio[2]); 1175298948Sadrian 1176298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003); 1177298948Sadrian DELAY(10); 1178298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]); 1179298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]); 1180298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]); 1181298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]); 1182298948Sadrian 1183298948Sadrian pg->pg_max_lb_gain = 1184298948Sadrian ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11; 1185298948Sadrian pg->pg_trsw_rx_gain = trsw_rx * 2; 1186298948Sadrian} 1187298948Sadrian 1188298948Sadrianstatic uint16_t 1189298948Sadrianbwn_rf_init_bcm2050(struct bwn_mac *mac) 1190298948Sadrian{ 1191298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1192298948Sadrian uint32_t tmp1 = 0, tmp2 = 0; 1193298948Sadrian uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval, 1194298948Sadrian analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl, 1195298948Sadrian radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index; 1196298948Sadrian static const uint8_t rcc_table[] = { 1197298948Sadrian 0x02, 0x03, 0x01, 0x0f, 1198298948Sadrian 0x06, 0x07, 0x05, 0x0f, 1199298948Sadrian 0x0a, 0x0b, 0x09, 0x0f, 1200298948Sadrian 0x0e, 0x0f, 0x0d, 0x0f, 1201298948Sadrian }; 1202298948Sadrian 1203298948Sadrian loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover = 1204298948Sadrian rfoverval = rfover = cck3 = 0; 1205298948Sadrian radio0 = BWN_RF_READ(mac, 0x43); 1206298948Sadrian radio1 = BWN_RF_READ(mac, 0x51); 1207298948Sadrian radio2 = BWN_RF_READ(mac, 0x52); 1208298948Sadrian pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL); 1209298948Sadrian cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a)); 1210298948Sadrian cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59)); 1211298948Sadrian cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58)); 1212298948Sadrian 1213298948Sadrian if (phy->type == BWN_PHYTYPE_B) { 1214298948Sadrian cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30)); 1215298948Sadrian reg0 = BWN_READ_2(mac, 0x3ec); 1216298948Sadrian 1217298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff); 1218298948Sadrian BWN_WRITE_2(mac, 0x3ec, 0x3f3f); 1219298948Sadrian } else if (phy->gmode || phy->rev >= 2) { 1220298948Sadrian rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER); 1221298948Sadrian rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL); 1222298948Sadrian analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER); 1223298948Sadrian analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL); 1224298948Sadrian crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0); 1225298948Sadrian classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL); 1226298948Sadrian 1227298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003); 1228298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc); 1229298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff); 1230298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc); 1231298948Sadrian if (BWN_HAS_LOOPBACK(phy)) { 1232298948Sadrian lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK); 1233298948Sadrian loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL); 1234298948Sadrian if (phy->rev >= 3) 1235298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020); 1236298948Sadrian else 1237298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020); 1238298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0); 1239298948Sadrian } 1240298948Sadrian 1241298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1242298948Sadrian bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL, 1243298948Sadrian BWN_LPD(0, 1, 1))); 1244298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 1245298948Sadrian bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0)); 1246298948Sadrian } 1247298948Sadrian BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000); 1248298948Sadrian 1249298948Sadrian syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL); 1250298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f); 1251298948Sadrian reg1 = BWN_READ_2(mac, 0x3e6); 1252298948Sadrian reg2 = BWN_READ_2(mac, 0x3f4); 1253298948Sadrian 1254298948Sadrian if (phy->analog == 0) 1255298948Sadrian BWN_WRITE_2(mac, 0x03e6, 0x0122); 1256298948Sadrian else { 1257298948Sadrian if (phy->analog >= 2) 1258298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40); 1259298948Sadrian BWN_WRITE_2(mac, BWN_CHANNEL_EXT, 1260298948Sadrian (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000)); 1261298948Sadrian } 1262298948Sadrian 1263298948Sadrian reg = BWN_RF_READ(mac, 0x60); 1264298948Sadrian index = (reg & 0x001e) >> 1; 1265298948Sadrian rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020); 1266298948Sadrian 1267298948Sadrian if (phy->type == BWN_PHYTYPE_B) 1268298948Sadrian BWN_RF_WRITE(mac, 0x78, 0x26); 1269298948Sadrian if (phy->gmode || phy->rev >= 2) { 1270298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1271298948Sadrian bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL, 1272298948Sadrian BWN_LPD(0, 1, 1))); 1273298948Sadrian } 1274298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf); 1275298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403); 1276298948Sadrian if (phy->gmode || phy->rev >= 2) { 1277298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1278298948Sadrian bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL, 1279298948Sadrian BWN_LPD(0, 0, 1))); 1280298948Sadrian } 1281298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0); 1282298948Sadrian BWN_RF_SET(mac, 0x51, 0x0004); 1283298948Sadrian if (phy->rf_rev == 8) 1284298948Sadrian BWN_RF_WRITE(mac, 0x43, 0x1f); 1285298948Sadrian else { 1286298948Sadrian BWN_RF_WRITE(mac, 0x52, 0); 1287298948Sadrian BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009); 1288298948Sadrian } 1289298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0); 1290298948Sadrian 1291298948Sadrian for (i = 0; i < 16; i++) { 1292298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480); 1293298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810); 1294298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d); 1295298948Sadrian if (phy->gmode || phy->rev >= 2) { 1296298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1297298948Sadrian bwn_rf_2050_rfoverval(mac, 1298298948Sadrian BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1299298948Sadrian } 1300298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0); 1301298948Sadrian DELAY(10); 1302298948Sadrian if (phy->gmode || phy->rev >= 2) { 1303298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1304298948Sadrian bwn_rf_2050_rfoverval(mac, 1305298948Sadrian BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1306298948Sadrian } 1307298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0); 1308298948Sadrian DELAY(10); 1309298948Sadrian if (phy->gmode || phy->rev >= 2) { 1310298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1311298948Sadrian bwn_rf_2050_rfoverval(mac, 1312298948Sadrian BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0))); 1313298948Sadrian } 1314298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0); 1315298948Sadrian DELAY(20); 1316298948Sadrian tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE); 1317298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0); 1318298948Sadrian if (phy->gmode || phy->rev >= 2) { 1319298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1320298948Sadrian bwn_rf_2050_rfoverval(mac, 1321298948Sadrian BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1322298948Sadrian } 1323298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0); 1324298948Sadrian } 1325298948Sadrian DELAY(10); 1326298948Sadrian 1327298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0); 1328298948Sadrian tmp1++; 1329298948Sadrian tmp1 >>= 9; 1330298948Sadrian 1331298948Sadrian for (i = 0; i < 16; i++) { 1332298948Sadrian radio78 = (BWN_BITREV4(i) << 1) | 0x0020; 1333298948Sadrian BWN_RF_WRITE(mac, 0x78, radio78); 1334298948Sadrian DELAY(10); 1335298948Sadrian for (j = 0; j < 16; j++) { 1336298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80); 1337298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810); 1338298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d); 1339298948Sadrian if (phy->gmode || phy->rev >= 2) { 1340298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1341298948Sadrian bwn_rf_2050_rfoverval(mac, 1342298948Sadrian BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1343298948Sadrian } 1344298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0); 1345298948Sadrian DELAY(10); 1346298948Sadrian if (phy->gmode || phy->rev >= 2) { 1347298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1348298948Sadrian bwn_rf_2050_rfoverval(mac, 1349298948Sadrian BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1350298948Sadrian } 1351298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0); 1352298948Sadrian DELAY(10); 1353298948Sadrian if (phy->gmode || phy->rev >= 2) { 1354298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1355298948Sadrian bwn_rf_2050_rfoverval(mac, 1356298948Sadrian BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0))); 1357298948Sadrian } 1358298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0); 1359298948Sadrian DELAY(10); 1360298948Sadrian tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE); 1361298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0); 1362298948Sadrian if (phy->gmode || phy->rev >= 2) { 1363298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1364298948Sadrian bwn_rf_2050_rfoverval(mac, 1365298948Sadrian BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1366298948Sadrian } 1367298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0); 1368298948Sadrian } 1369298948Sadrian tmp2++; 1370298948Sadrian tmp2 >>= 8; 1371298948Sadrian if (tmp1 < tmp2) 1372298948Sadrian break; 1373298948Sadrian } 1374298948Sadrian 1375298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl); 1376298948Sadrian BWN_RF_WRITE(mac, 0x51, radio1); 1377298948Sadrian BWN_RF_WRITE(mac, 0x52, radio2); 1378298948Sadrian BWN_RF_WRITE(mac, 0x43, radio0); 1379298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0); 1380298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1); 1381298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2); 1382298948Sadrian BWN_WRITE_2(mac, 0x3e6, reg1); 1383298948Sadrian if (phy->analog != 0) 1384298948Sadrian BWN_WRITE_2(mac, 0x3f4, reg2); 1385298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl); 1386298948Sadrian bwn_spu_workaround(mac, phy->chan); 1387298948Sadrian if (phy->type == BWN_PHYTYPE_B) { 1388298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3); 1389298948Sadrian BWN_WRITE_2(mac, 0x3ec, reg0); 1390298948Sadrian } else if (phy->gmode) { 1391298948Sadrian BWN_WRITE_2(mac, BWN_PHY_RADIO, 1392298948Sadrian BWN_READ_2(mac, BWN_PHY_RADIO) 1393298948Sadrian & 0x7fff); 1394298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover); 1395298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval); 1396298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover); 1397298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 1398298948Sadrian analogoverval); 1399298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0); 1400298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl); 1401298948Sadrian if (BWN_HAS_LOOPBACK(phy)) { 1402298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask); 1403298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl); 1404298948Sadrian } 1405298948Sadrian } 1406298948Sadrian 1407298948Sadrian return ((i > 15) ? radio78 : rcc); 1408298948Sadrian} 1409298948Sadrian 1410298948Sadrianstatic void 1411298948Sadrianbwn_phy_init_b6(struct bwn_mac *mac) 1412298948Sadrian{ 1413298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1414298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 1415298948Sadrian struct bwn_softc *sc = mac->mac_sc; 1416298948Sadrian uint16_t offset, val; 1417298948Sadrian uint8_t old_channel; 1418298948Sadrian 1419298948Sadrian KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7), 1420298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 1421298948Sadrian 1422298948Sadrian BWN_PHY_WRITE(mac, 0x003e, 0x817a); 1423298948Sadrian BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058); 1424298948Sadrian if (phy->rf_rev == 4 || phy->rf_rev == 5) { 1425298948Sadrian BWN_RF_WRITE(mac, 0x51, 0x37); 1426298948Sadrian BWN_RF_WRITE(mac, 0x52, 0x70); 1427298948Sadrian BWN_RF_WRITE(mac, 0x53, 0xb3); 1428298948Sadrian BWN_RF_WRITE(mac, 0x54, 0x9b); 1429298948Sadrian BWN_RF_WRITE(mac, 0x5a, 0x88); 1430298948Sadrian BWN_RF_WRITE(mac, 0x5b, 0x88); 1431298948Sadrian BWN_RF_WRITE(mac, 0x5d, 0x88); 1432298948Sadrian BWN_RF_WRITE(mac, 0x5e, 0x88); 1433298948Sadrian BWN_RF_WRITE(mac, 0x7d, 0x88); 1434298948Sadrian bwn_hf_write(mac, 1435298948Sadrian bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN); 1436298948Sadrian } 1437298948Sadrian if (phy->rf_rev == 8) { 1438298948Sadrian BWN_RF_WRITE(mac, 0x51, 0); 1439298948Sadrian BWN_RF_WRITE(mac, 0x52, 0x40); 1440298948Sadrian BWN_RF_WRITE(mac, 0x53, 0xb7); 1441298948Sadrian BWN_RF_WRITE(mac, 0x54, 0x98); 1442298948Sadrian BWN_RF_WRITE(mac, 0x5a, 0x88); 1443298948Sadrian BWN_RF_WRITE(mac, 0x5b, 0x6b); 1444298948Sadrian BWN_RF_WRITE(mac, 0x5c, 0x0f); 1445298948Sadrian if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) { 1446298948Sadrian BWN_RF_WRITE(mac, 0x5d, 0xfa); 1447298948Sadrian BWN_RF_WRITE(mac, 0x5e, 0xd8); 1448298948Sadrian } else { 1449298948Sadrian BWN_RF_WRITE(mac, 0x5d, 0xf5); 1450298948Sadrian BWN_RF_WRITE(mac, 0x5e, 0xb8); 1451298948Sadrian } 1452298948Sadrian BWN_RF_WRITE(mac, 0x0073, 0x0003); 1453298948Sadrian BWN_RF_WRITE(mac, 0x007d, 0x00a8); 1454298948Sadrian BWN_RF_WRITE(mac, 0x007c, 0x0001); 1455298948Sadrian BWN_RF_WRITE(mac, 0x007e, 0x0008); 1456298948Sadrian } 1457298948Sadrian for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) { 1458298948Sadrian BWN_PHY_WRITE(mac, offset, val); 1459298948Sadrian val -= 0x0202; 1460298948Sadrian } 1461298948Sadrian for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) { 1462298948Sadrian BWN_PHY_WRITE(mac, offset, val); 1463298948Sadrian val -= 0x0202; 1464298948Sadrian } 1465298948Sadrian for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) { 1466298948Sadrian BWN_PHY_WRITE(mac, offset, (val & 0x3f3f)); 1467298948Sadrian val += 0x0202; 1468298948Sadrian } 1469298948Sadrian if (phy->type == BWN_PHYTYPE_G) { 1470298948Sadrian BWN_RF_SET(mac, 0x007a, 0x0020); 1471298948Sadrian BWN_RF_SET(mac, 0x0051, 0x0004); 1472298948Sadrian BWN_PHY_SET(mac, 0x0802, 0x0100); 1473298948Sadrian BWN_PHY_SET(mac, 0x042b, 0x2000); 1474298948Sadrian BWN_PHY_WRITE(mac, 0x5b, 0); 1475298948Sadrian BWN_PHY_WRITE(mac, 0x5c, 0); 1476298948Sadrian } 1477298948Sadrian 1478298948Sadrian old_channel = phy->chan; 1479298948Sadrian bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0); 1480298948Sadrian 1481298948Sadrian BWN_RF_WRITE(mac, 0x0050, 0x0020); 1482298948Sadrian BWN_RF_WRITE(mac, 0x0050, 0x0023); 1483298948Sadrian DELAY(40); 1484298948Sadrian if (phy->rf_rev < 6 || phy->rf_rev == 8) { 1485298948Sadrian BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002); 1486298948Sadrian BWN_RF_WRITE(mac, 0x50, 0x20); 1487298948Sadrian } 1488298948Sadrian if (phy->rf_rev <= 2) { 1489298948Sadrian BWN_RF_WRITE(mac, 0x7c, 0x20); 1490298948Sadrian BWN_RF_WRITE(mac, 0x5a, 0x70); 1491298948Sadrian BWN_RF_WRITE(mac, 0x5b, 0x7b); 1492298948Sadrian BWN_RF_WRITE(mac, 0x5c, 0xb0); 1493298948Sadrian } 1494298948Sadrian BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007); 1495298948Sadrian 1496298948Sadrian bwn_phy_g_switch_chan(mac, old_channel, 0); 1497298948Sadrian 1498298948Sadrian BWN_PHY_WRITE(mac, 0x0014, 0x0200); 1499298948Sadrian if (phy->rf_rev >= 6) 1500298948Sadrian BWN_PHY_WRITE(mac, 0x2a, 0x88c2); 1501298948Sadrian else 1502298948Sadrian BWN_PHY_WRITE(mac, 0x2a, 0x8ac0); 1503298948Sadrian BWN_PHY_WRITE(mac, 0x0038, 0x0668); 1504298948Sadrian bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt, 1505298948Sadrian pg->pg_txctl); 1506298948Sadrian if (phy->rf_rev <= 5) 1507298948Sadrian BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003); 1508298948Sadrian if (phy->rf_rev <= 2) 1509298948Sadrian BWN_RF_WRITE(mac, 0x005d, 0x000d); 1510298948Sadrian 1511298948Sadrian if (phy->analog == 4) { 1512298948Sadrian BWN_WRITE_2(mac, 0x3e4, 9); 1513298948Sadrian BWN_PHY_MASK(mac, 0x61, 0x0fff); 1514298948Sadrian } else 1515298948Sadrian BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004); 1516298948Sadrian if (phy->type == BWN_PHYTYPE_B) 1517298948Sadrian KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 1518298948Sadrian else if (phy->type == BWN_PHYTYPE_G) 1519298948Sadrian BWN_WRITE_2(mac, 0x03e6, 0x0); 1520298948Sadrian} 1521298948Sadrian 1522298948Sadrianstatic void 1523298948Sadrianbwn_phy_init_a(struct bwn_mac *mac) 1524298948Sadrian{ 1525298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1526298948Sadrian struct bwn_softc *sc = mac->mac_sc; 1527298948Sadrian 1528298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G, 1529298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 1530298948Sadrian 1531298948Sadrian if (phy->rev >= 6) { 1532298948Sadrian if (phy->type == BWN_PHYTYPE_A) 1533298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000); 1534298948Sadrian if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN) 1535298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010); 1536298948Sadrian else 1537298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010); 1538298948Sadrian } 1539298948Sadrian 1540298948Sadrian bwn_wa_init(mac); 1541298948Sadrian 1542298948Sadrian if (phy->type == BWN_PHYTYPE_G && 1543298948Sadrian (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)) 1544298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf); 1545298948Sadrian} 1546298948Sadrian 1547298948Sadrianstatic void 1548298948Sadrianbwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst) 1549298948Sadrian{ 1550298948Sadrian int i; 1551298948Sadrian 1552298948Sadrian for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++) 1553298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]); 1554298948Sadrian} 1555298948Sadrian 1556298948Sadrianstatic void 1557298948Sadrianbwn_wa_agc(struct bwn_mac *mac) 1558298948Sadrian{ 1559298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1560298948Sadrian 1561298948Sadrian if (phy->rev == 1) { 1562298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254); 1563298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13); 1564298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19); 1565298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25); 1566298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710); 1567298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83); 1568298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83); 1569298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d); 1570298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4); 1571298948Sadrian } else { 1572298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254); 1573298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13); 1574298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19); 1575298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25); 1576298948Sadrian } 1577298948Sadrian 1578298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00, 1579298948Sadrian 0x5700); 1580298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f); 1581298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80); 1582298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300); 1583298948Sadrian BWN_RF_SET(mac, 0x7a, 0x0008); 1584298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008); 1585298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600); 1586298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700); 1587298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100); 1588298948Sadrian if (phy->rev == 1) 1589298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007); 1590298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c); 1591298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200); 1592298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c); 1593298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020); 1594298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200); 1595298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e); 1596298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00); 1597298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028); 1598298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00); 1599298948Sadrian if (phy->rev == 1) { 1600298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b); 1601298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002); 1602298948Sadrian } else { 1603298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e); 1604298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a); 1605298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004); 1606298948Sadrian if (phy->rev >= 6) { 1607298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a); 1608298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, 1609298948Sadrian (uint16_t)~0xf000, 0x3000); 1610298948Sadrian } 1611298948Sadrian } 1612298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874); 1613298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00); 1614298948Sadrian if (phy->rev == 1) { 1615298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600); 1616298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e); 1617298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e); 1618298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002); 1619298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0); 1620298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7); 1621298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16); 1622298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28); 1623298948Sadrian } else { 1624298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0); 1625298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7); 1626298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16); 1627298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28); 1628298948Sadrian } 1629298948Sadrian if (phy->rev >= 6) { 1630298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003); 1631298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000); 1632298948Sadrian } 1633298948Sadrian BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM); 1634298948Sadrian} 1635298948Sadrian 1636298948Sadrianstatic void 1637298948Sadrianbwn_wa_grev1(struct bwn_mac *mac) 1638298948Sadrian{ 1639298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1640298948Sadrian int i; 1641298948Sadrian static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G; 1642298948Sadrian static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD; 1643298948Sadrian static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR; 1644298948Sadrian 1645298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__)); 1646298948Sadrian 1647298948Sadrian /* init CRSTHRES and ANTDWELL */ 1648298948Sadrian if (phy->rev == 1) { 1649298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19); 1650298948Sadrian } else if (phy->rev == 2) { 1651298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861); 1652298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271); 1653298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800); 1654298948Sadrian } else { 1655298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098); 1656298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070); 1657298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080); 1658298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800); 1659298948Sadrian } 1660298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000); 1661298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a); 1662298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026); 1663298948Sadrian 1664298948Sadrian /* XXX support PHY-A??? */ 1665298948Sadrian for (i = 0; i < N(bwn_tab_finefreqg); i++) 1666298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i, 1667298948Sadrian bwn_tab_finefreqg[i]); 1668298948Sadrian 1669298948Sadrian /* XXX support PHY-A??? */ 1670298948Sadrian if (phy->rev == 1) 1671298948Sadrian for (i = 0; i < N(bwn_tab_noise_g1); i++) 1672298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, 1673298948Sadrian bwn_tab_noise_g1[i]); 1674298948Sadrian else 1675298948Sadrian for (i = 0; i < N(bwn_tab_noise_g2); i++) 1676298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, 1677298948Sadrian bwn_tab_noise_g2[i]); 1678298948Sadrian 1679298948Sadrian 1680298948Sadrian for (i = 0; i < N(bwn_tab_rotor); i++) 1681298948Sadrian bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i, 1682298948Sadrian bwn_tab_rotor[i]); 1683298948Sadrian 1684298948Sadrian /* XXX support PHY-A??? */ 1685298948Sadrian if (phy->rev >= 6) { 1686298948Sadrian if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & 1687298948Sadrian BWN_PHY_ENCORE_EN) 1688298948Sadrian bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3); 1689298948Sadrian else 1690298948Sadrian bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2); 1691298948Sadrian } else 1692298948Sadrian bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1); 1693298948Sadrian 1694298948Sadrian for (i = 0; i < N(bwn_tab_retard); i++) 1695298948Sadrian bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i, 1696298948Sadrian bwn_tab_retard[i]); 1697298948Sadrian 1698298948Sadrian if (phy->rev == 1) { 1699298948Sadrian for (i = 0; i < 16; i++) 1700298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, 1701298948Sadrian i, 0x0020); 1702298948Sadrian } else { 1703298948Sadrian for (i = 0; i < 32; i++) 1704298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820); 1705298948Sadrian } 1706298948Sadrian 1707298948Sadrian bwn_wa_agc(mac); 1708298948Sadrian} 1709298948Sadrian 1710298948Sadrianstatic void 1711298948Sadrianbwn_wa_grev26789(struct bwn_mac *mac) 1712298948Sadrian{ 1713298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1714298948Sadrian int i; 1715298948Sadrian static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2; 1716298948Sadrian uint16_t ofdmrev; 1717298948Sadrian 1718298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__)); 1719298948Sadrian 1720298948Sadrian bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480); 1721298948Sadrian 1722298948Sadrian /* init CRSTHRES and ANTDWELL */ 1723298948Sadrian if (phy->rev == 1) 1724298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19); 1725298948Sadrian else if (phy->rev == 2) { 1726298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861); 1727298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271); 1728298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800); 1729298948Sadrian } else { 1730298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098); 1731298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070); 1732298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080); 1733298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800); 1734298948Sadrian } 1735298948Sadrian 1736298948Sadrian for (i = 0; i < 64; i++) 1737298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i); 1738298948Sadrian 1739298948Sadrian /* XXX support PHY-A??? */ 1740298948Sadrian if (phy->rev == 1) 1741298948Sadrian for (i = 0; i < N(bwn_tab_noise_g1); i++) 1742298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, 1743298948Sadrian bwn_tab_noise_g1[i]); 1744298948Sadrian else 1745298948Sadrian for (i = 0; i < N(bwn_tab_noise_g2); i++) 1746298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, 1747298948Sadrian bwn_tab_noise_g2[i]); 1748298948Sadrian 1749298948Sadrian /* XXX support PHY-A??? */ 1750298948Sadrian if (phy->rev >= 6) { 1751298948Sadrian if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & 1752298948Sadrian BWN_PHY_ENCORE_EN) 1753298948Sadrian bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3); 1754298948Sadrian else 1755298948Sadrian bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2); 1756298948Sadrian } else 1757298948Sadrian bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1); 1758298948Sadrian 1759298948Sadrian for (i = 0; i < N(bwn_tab_sigmasqr2); i++) 1760298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i, 1761298948Sadrian bwn_tab_sigmasqr2[i]); 1762298948Sadrian 1763298948Sadrian if (phy->rev == 1) { 1764298948Sadrian for (i = 0; i < 16; i++) 1765298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i, 1766298948Sadrian 0x0020); 1767298948Sadrian } else { 1768298948Sadrian for (i = 0; i < 32; i++) 1769298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820); 1770298948Sadrian } 1771298948Sadrian 1772298948Sadrian bwn_wa_agc(mac); 1773298948Sadrian 1774298948Sadrian ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION; 1775298948Sadrian if (ofdmrev > 2) { 1776298948Sadrian if (phy->type == BWN_PHYTYPE_A) 1777298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808); 1778298948Sadrian else 1779298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000); 1780298948Sadrian } else { 1781298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044); 1782298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201); 1783298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040); 1784298948Sadrian } 1785298948Sadrian 1786298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15); 1787298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20); 1788298948Sadrian} 1789298948Sadrian 1790298948Sadrianstatic void 1791298948Sadrianbwn_wa_init(struct bwn_mac *mac) 1792298948Sadrian{ 1793298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1794298948Sadrian struct bwn_softc *sc = mac->mac_sc; 1795298948Sadrian 1796298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__)); 1797298948Sadrian 1798298948Sadrian switch (phy->rev) { 1799298948Sadrian case 1: 1800298948Sadrian bwn_wa_grev1(mac); 1801298948Sadrian break; 1802298948Sadrian case 2: 1803298948Sadrian case 6: 1804298948Sadrian case 7: 1805298948Sadrian case 8: 1806298948Sadrian case 9: 1807298948Sadrian bwn_wa_grev26789(mac); 1808298948Sadrian break; 1809298948Sadrian default: 1810298948Sadrian KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 1811298948Sadrian } 1812298948Sadrian 1813298948Sadrian if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM || 1814298948Sadrian siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 || 1815298948Sadrian siba_get_pci_revid(sc->sc_dev) != 0x17) { 1816298948Sadrian if (phy->rev < 2) { 1817298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1, 1818298948Sadrian 0x0002); 1819298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2, 1820298948Sadrian 0x0001); 1821298948Sadrian } else { 1822298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002); 1823298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001); 1824298948Sadrian if ((siba_sprom_get_bf_lo(sc->sc_dev) & 1825298948Sadrian BWN_BFL_EXTLNA) && 1826298948Sadrian (phy->rev >= 7)) { 1827298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff); 1828298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1829298948Sadrian 0x0020, 0x0001); 1830298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1831298948Sadrian 0x0021, 0x0001); 1832298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1833298948Sadrian 0x0022, 0x0001); 1834298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1835298948Sadrian 0x0023, 0x0000); 1836298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1837298948Sadrian 0x0000, 0x0000); 1838298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1839298948Sadrian 0x0003, 0x0002); 1840298948Sadrian } 1841298948Sadrian } 1842298948Sadrian } 1843298948Sadrian if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) { 1844298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120); 1845298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480); 1846298948Sadrian } 1847298948Sadrian 1848298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0); 1849298948Sadrian bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0); 1850298948Sadrian} 1851298948Sadrian 1852298948Sadrianstatic void 1853298948Sadrianbwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset, 1854298948Sadrian uint16_t value) 1855298948Sadrian{ 1856298948Sadrian struct bwn_phy_g *pg = &mac->mac_phy.phy_g; 1857298948Sadrian uint16_t addr; 1858298948Sadrian 1859298948Sadrian addr = table + offset; 1860298948Sadrian if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) || 1861298948Sadrian (addr - 1 != pg->pg_ofdmtab_addr)) { 1862298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr); 1863298948Sadrian pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE; 1864298948Sadrian } 1865298948Sadrian pg->pg_ofdmtab_addr = addr; 1866298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value); 1867298948Sadrian} 1868298948Sadrian 1869298948Sadrianstatic void 1870298948Sadrianbwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset, 1871298948Sadrian uint32_t value) 1872298948Sadrian{ 1873298948Sadrian struct bwn_phy_g *pg = &mac->mac_phy.phy_g; 1874298948Sadrian uint16_t addr; 1875298948Sadrian 1876298948Sadrian addr = table + offset; 1877298948Sadrian if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) || 1878298948Sadrian (addr - 1 != pg->pg_ofdmtab_addr)) { 1879298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr); 1880298948Sadrian pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE; 1881298948Sadrian } 1882298948Sadrian pg->pg_ofdmtab_addr = addr; 1883298948Sadrian 1884298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value); 1885298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16)); 1886298948Sadrian} 1887298948Sadrian 1888298948Sadrianstatic void 1889298948Sadrianbwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset, 1890298948Sadrian uint16_t value) 1891298948Sadrian{ 1892298948Sadrian 1893298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset); 1894298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value); 1895298948Sadrian} 1896298948Sadrian 1897298948Sadrianstatic void 1898298948Sadrianbwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl) 1899298948Sadrian{ 1900298948Sadrian uint16_t value; 1901298948Sadrian 1902298948Sadrian KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G, 1903298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 1904298948Sadrian 1905298948Sadrian value = (uint8_t) (ctl->q); 1906298948Sadrian value |= ((uint8_t) (ctl->i)) << 8; 1907298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value); 1908298948Sadrian} 1909298948Sadrian 1910298948Sadrianstatic uint16_t 1911298948Sadrianbwn_lo_calcfeed(struct bwn_mac *mac, 1912298948Sadrian uint16_t lna, uint16_t pga, uint16_t trsw_rx) 1913298948Sadrian{ 1914298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1915298948Sadrian struct bwn_softc *sc = mac->mac_sc; 1916298948Sadrian uint16_t rfover; 1917298948Sadrian uint16_t feedthrough; 1918298948Sadrian 1919298948Sadrian if (phy->gmode) { 1920298948Sadrian lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT; 1921298948Sadrian pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT; 1922298948Sadrian 1923298948Sadrian KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0, 1924298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 1925298948Sadrian KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0, 1926298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 1927298948Sadrian 1928298948Sadrian trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW); 1929298948Sadrian 1930298948Sadrian rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx; 1931298948Sadrian if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) && 1932298948Sadrian phy->rev > 6) 1933298948Sadrian rfover |= BWN_PHY_RFOVERVAL_EXTLNA; 1934298948Sadrian 1935298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300); 1936298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover); 1937298948Sadrian DELAY(10); 1938298948Sadrian rfover |= BWN_PHY_RFOVERVAL_BW_LBW; 1939298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover); 1940298948Sadrian DELAY(10); 1941298948Sadrian rfover |= BWN_PHY_RFOVERVAL_BW_LPF; 1942298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover); 1943298948Sadrian DELAY(10); 1944298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300); 1945298948Sadrian } else { 1946298948Sadrian pga |= BWN_PHY_PGACTL_UNKNOWN; 1947298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga); 1948298948Sadrian DELAY(10); 1949298948Sadrian pga |= BWN_PHY_PGACTL_LOWBANDW; 1950298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga); 1951298948Sadrian DELAY(10); 1952298948Sadrian pga |= BWN_PHY_PGACTL_LPF; 1953298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga); 1954298948Sadrian } 1955298948Sadrian DELAY(21); 1956298948Sadrian feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE); 1957298948Sadrian 1958298948Sadrian return (feedthrough); 1959298948Sadrian} 1960298948Sadrian 1961298948Sadrianstatic uint16_t 1962298948Sadrianbwn_lo_txctl_regtable(struct bwn_mac *mac, 1963298948Sadrian uint16_t *value, uint16_t *pad_mix_gain) 1964298948Sadrian{ 1965298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 1966298948Sadrian uint16_t reg, v, padmix; 1967298948Sadrian 1968298948Sadrian if (phy->type == BWN_PHYTYPE_B) { 1969298948Sadrian v = 0x30; 1970298948Sadrian if (phy->rf_rev <= 5) { 1971298948Sadrian reg = 0x43; 1972298948Sadrian padmix = 0; 1973298948Sadrian } else { 1974298948Sadrian reg = 0x52; 1975298948Sadrian padmix = 5; 1976298948Sadrian } 1977298948Sadrian } else { 1978298948Sadrian if (phy->rev >= 2 && phy->rf_rev == 8) { 1979298948Sadrian reg = 0x43; 1980298948Sadrian v = 0x10; 1981298948Sadrian padmix = 2; 1982298948Sadrian } else { 1983298948Sadrian reg = 0x52; 1984298948Sadrian v = 0x30; 1985298948Sadrian padmix = 5; 1986298948Sadrian } 1987298948Sadrian } 1988298948Sadrian if (value) 1989298948Sadrian *value = v; 1990298948Sadrian if (pad_mix_gain) 1991298948Sadrian *pad_mix_gain = padmix; 1992298948Sadrian 1993298948Sadrian return (reg); 1994298948Sadrian} 1995298948Sadrian 1996298948Sadrianstatic void 1997298948Sadrianbwn_lo_measure_txctl_values(struct bwn_mac *mac) 1998298948Sadrian{ 1999298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2000298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2001298948Sadrian struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 2002298948Sadrian uint16_t reg, mask; 2003298948Sadrian uint16_t trsw_rx, pga; 2004298948Sadrian uint16_t rf_pctl_reg; 2005298948Sadrian 2006298948Sadrian static const uint8_t tx_bias_values[] = { 2007298948Sadrian 0x09, 0x08, 0x0a, 0x01, 0x00, 2008298948Sadrian 0x02, 0x05, 0x04, 0x06, 2009298948Sadrian }; 2010298948Sadrian static const uint8_t tx_magn_values[] = { 2011298948Sadrian 0x70, 0x40, 2012298948Sadrian }; 2013298948Sadrian 2014298948Sadrian if (!BWN_HAS_LOOPBACK(phy)) { 2015298948Sadrian rf_pctl_reg = 6; 2016298948Sadrian trsw_rx = 2; 2017298948Sadrian pga = 0; 2018298948Sadrian } else { 2019298948Sadrian int lb_gain; 2020298948Sadrian 2021298948Sadrian trsw_rx = 0; 2022298948Sadrian lb_gain = pg->pg_max_lb_gain / 2; 2023298948Sadrian if (lb_gain > 10) { 2024298948Sadrian rf_pctl_reg = 0; 2025298948Sadrian pga = abs(10 - lb_gain) / 6; 2026298948Sadrian pga = MIN(MAX(pga, 0), 15); 2027298948Sadrian } else { 2028298948Sadrian int cmp_val; 2029298948Sadrian int tmp; 2030298948Sadrian 2031298948Sadrian pga = 0; 2032298948Sadrian cmp_val = 0x24; 2033298948Sadrian if ((phy->rev >= 2) && 2034298948Sadrian (phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) 2035298948Sadrian cmp_val = 0x3c; 2036298948Sadrian tmp = lb_gain; 2037298948Sadrian if ((10 - lb_gain) < cmp_val) 2038298948Sadrian tmp = (10 - lb_gain); 2039298948Sadrian if (tmp < 0) 2040298948Sadrian tmp += 6; 2041298948Sadrian else 2042298948Sadrian tmp += 3; 2043298948Sadrian cmp_val /= 4; 2044298948Sadrian tmp /= 4; 2045298948Sadrian if (tmp >= cmp_val) 2046298948Sadrian rf_pctl_reg = cmp_val; 2047298948Sadrian else 2048298948Sadrian rf_pctl_reg = tmp; 2049298948Sadrian } 2050298948Sadrian } 2051298948Sadrian BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg); 2052298948Sadrian bwn_phy_g_set_bbatt(mac, 2); 2053298948Sadrian 2054298948Sadrian reg = bwn_lo_txctl_regtable(mac, &mask, NULL); 2055298948Sadrian mask = ~mask; 2056298948Sadrian BWN_RF_MASK(mac, reg, mask); 2057298948Sadrian 2058298948Sadrian if (BWN_HAS_TXMAG(phy)) { 2059298948Sadrian int i, j; 2060298948Sadrian int feedthrough; 2061298948Sadrian int min_feedth = 0xffff; 2062298948Sadrian uint8_t tx_magn, tx_bias; 2063298948Sadrian 2064298948Sadrian for (i = 0; i < N(tx_magn_values); i++) { 2065298948Sadrian tx_magn = tx_magn_values[i]; 2066298948Sadrian BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn); 2067298948Sadrian for (j = 0; j < N(tx_bias_values); j++) { 2068298948Sadrian tx_bias = tx_bias_values[j]; 2069298948Sadrian BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias); 2070298948Sadrian feedthrough = bwn_lo_calcfeed(mac, 0, pga, 2071298948Sadrian trsw_rx); 2072298948Sadrian if (feedthrough < min_feedth) { 2073298948Sadrian lo->tx_bias = tx_bias; 2074298948Sadrian lo->tx_magn = tx_magn; 2075298948Sadrian min_feedth = feedthrough; 2076298948Sadrian } 2077298948Sadrian if (lo->tx_bias == 0) 2078298948Sadrian break; 2079298948Sadrian } 2080298948Sadrian BWN_RF_WRITE(mac, 0x52, 2081298948Sadrian (BWN_RF_READ(mac, 0x52) 2082298948Sadrian & 0xff00) | lo->tx_bias | lo-> 2083298948Sadrian tx_magn); 2084298948Sadrian } 2085298948Sadrian } else { 2086298948Sadrian lo->tx_magn = 0; 2087298948Sadrian lo->tx_bias = 0; 2088298948Sadrian BWN_RF_MASK(mac, 0x52, 0xfff0); 2089298948Sadrian } 2090298948Sadrian 2091298948Sadrian BWN_GETTIME(lo->txctl_measured_time); 2092298948Sadrian} 2093298948Sadrian 2094298948Sadrianstatic void 2095298948Sadrianbwn_lo_get_powervector(struct bwn_mac *mac) 2096298948Sadrian{ 2097298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2098298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2099298948Sadrian struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 2100298948Sadrian int i; 2101298948Sadrian uint64_t tmp; 2102298948Sadrian uint64_t power_vector = 0; 2103298948Sadrian 2104298948Sadrian for (i = 0; i < 8; i += 2) { 2105298948Sadrian tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i); 2106298948Sadrian power_vector |= (tmp << (i * 8)); 2107298948Sadrian bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0); 2108298948Sadrian } 2109298948Sadrian if (power_vector) 2110298948Sadrian lo->power_vector = power_vector; 2111298948Sadrian 2112298948Sadrian BWN_GETTIME(lo->pwr_vec_read_time); 2113298948Sadrian} 2114298948Sadrian 2115298948Sadrianstatic void 2116298948Sadrianbwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain, 2117298948Sadrian int use_trsw_rx) 2118298948Sadrian{ 2119298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2120298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2121298948Sadrian uint16_t tmp; 2122298948Sadrian 2123298948Sadrian if (max_rx_gain < 0) 2124298948Sadrian max_rx_gain = 0; 2125298948Sadrian 2126298948Sadrian if (BWN_HAS_LOOPBACK(phy)) { 2127298948Sadrian int trsw_rx = 0; 2128298948Sadrian int trsw_rx_gain; 2129298948Sadrian 2130298948Sadrian if (use_trsw_rx) { 2131298948Sadrian trsw_rx_gain = pg->pg_trsw_rx_gain / 2; 2132298948Sadrian if (max_rx_gain >= trsw_rx_gain) { 2133298948Sadrian trsw_rx_gain = max_rx_gain - trsw_rx_gain; 2134298948Sadrian trsw_rx = 0x20; 2135298948Sadrian } 2136298948Sadrian } else 2137298948Sadrian trsw_rx_gain = max_rx_gain; 2138298948Sadrian if (trsw_rx_gain < 9) { 2139298948Sadrian pg->pg_lna_lod_gain = 0; 2140298948Sadrian } else { 2141298948Sadrian pg->pg_lna_lod_gain = 1; 2142298948Sadrian trsw_rx_gain -= 8; 2143298948Sadrian } 2144298948Sadrian trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d); 2145298948Sadrian pg->pg_pga_gain = trsw_rx_gain / 3; 2146298948Sadrian if (pg->pg_pga_gain >= 5) { 2147298948Sadrian pg->pg_pga_gain -= 5; 2148298948Sadrian pg->pg_lna_gain = 2; 2149298948Sadrian } else 2150298948Sadrian pg->pg_lna_gain = 0; 2151298948Sadrian } else { 2152298948Sadrian pg->pg_lna_gain = 0; 2153298948Sadrian pg->pg_trsw_rx_gain = 0x20; 2154298948Sadrian if (max_rx_gain >= 0x14) { 2155298948Sadrian pg->pg_lna_lod_gain = 1; 2156298948Sadrian pg->pg_pga_gain = 2; 2157298948Sadrian } else if (max_rx_gain >= 0x12) { 2158298948Sadrian pg->pg_lna_lod_gain = 1; 2159298948Sadrian pg->pg_pga_gain = 1; 2160298948Sadrian } else if (max_rx_gain >= 0xf) { 2161298948Sadrian pg->pg_lna_lod_gain = 1; 2162298948Sadrian pg->pg_pga_gain = 0; 2163298948Sadrian } else { 2164298948Sadrian pg->pg_lna_lod_gain = 0; 2165298948Sadrian pg->pg_pga_gain = 0; 2166298948Sadrian } 2167298948Sadrian } 2168298948Sadrian 2169298948Sadrian tmp = BWN_RF_READ(mac, 0x7a); 2170298948Sadrian if (pg->pg_lna_lod_gain == 0) 2171298948Sadrian tmp &= ~0x0008; 2172298948Sadrian else 2173298948Sadrian tmp |= 0x0008; 2174298948Sadrian BWN_RF_WRITE(mac, 0x7a, tmp); 2175298948Sadrian} 2176298948Sadrian 2177298948Sadrianstatic void 2178298948Sadrianbwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav) 2179298948Sadrian{ 2180298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2181298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2182298948Sadrian struct bwn_softc *sc = mac->mac_sc; 2183298948Sadrian struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 2184298948Sadrian struct timespec ts; 2185298948Sadrian uint16_t tmp; 2186298948Sadrian 2187298948Sadrian if (bwn_has_hwpctl(mac)) { 2188298948Sadrian sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK); 2189298948Sadrian sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01)); 2190298948Sadrian sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL); 2191298948Sadrian sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14)); 2192298948Sadrian sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL); 2193298948Sadrian 2194298948Sadrian BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100); 2195298948Sadrian BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40); 2196298948Sadrian BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40); 2197298948Sadrian BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200); 2198298948Sadrian } 2199298948Sadrian if (phy->type == BWN_PHYTYPE_B && 2200298948Sadrian phy->rf_ver == 0x2050 && phy->rf_rev < 6) { 2201298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410); 2202298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820); 2203298948Sadrian } 2204298948Sadrian if (phy->rev >= 2) { 2205298948Sadrian sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER); 2206298948Sadrian sav->phy_analogoverval = 2207298948Sadrian BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL); 2208298948Sadrian sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER); 2209298948Sadrian sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL); 2210298948Sadrian sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL); 2211298948Sadrian sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e)); 2212298948Sadrian sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0); 2213298948Sadrian 2214298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc); 2215298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff); 2216298948Sadrian BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003); 2217298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc); 2218298948Sadrian if (phy->type == BWN_PHYTYPE_G) { 2219298948Sadrian if ((phy->rev >= 7) && 2220298948Sadrian (siba_sprom_get_bf_lo(sc->sc_dev) & 2221298948Sadrian BWN_BFL_EXTLNA)) { 2222298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933); 2223298948Sadrian } else { 2224298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133); 2225298948Sadrian } 2226298948Sadrian } else { 2227298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0); 2228298948Sadrian } 2229298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0); 2230298948Sadrian } 2231298948Sadrian sav->reg0 = BWN_READ_2(mac, 0x3f4); 2232298948Sadrian sav->reg1 = BWN_READ_2(mac, 0x3e2); 2233298948Sadrian sav->rf0 = BWN_RF_READ(mac, 0x43); 2234298948Sadrian sav->rf1 = BWN_RF_READ(mac, 0x7a); 2235298948Sadrian sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL); 2236298948Sadrian sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a)); 2237298948Sadrian sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL); 2238298948Sadrian sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL); 2239298948Sadrian 2240298948Sadrian if (!BWN_HAS_TXMAG(phy)) { 2241298948Sadrian sav->rf2 = BWN_RF_READ(mac, 0x52); 2242298948Sadrian sav->rf2 &= 0x00f0; 2243298948Sadrian } 2244298948Sadrian if (phy->type == BWN_PHYTYPE_B) { 2245298948Sadrian sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30)); 2246298948Sadrian sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06)); 2247298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff); 2248298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f); 2249298948Sadrian } else { 2250298948Sadrian BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) 2251298948Sadrian | 0x8000); 2252298948Sadrian } 2253298948Sadrian BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4) 2254298948Sadrian & 0xf000); 2255298948Sadrian 2256298948Sadrian tmp = 2257298948Sadrian (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e); 2258298948Sadrian BWN_PHY_WRITE(mac, tmp, 0x007f); 2259298948Sadrian 2260298948Sadrian tmp = sav->phy_syncctl; 2261298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f); 2262298948Sadrian tmp = sav->rf1; 2263298948Sadrian BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0); 2264298948Sadrian 2265298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3); 2266298948Sadrian if (phy->type == BWN_PHYTYPE_G || 2267298948Sadrian (phy->type == BWN_PHYTYPE_B && 2268298948Sadrian phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) { 2269298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003); 2270298948Sadrian } else 2271298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802); 2272298948Sadrian if (phy->rev >= 2) 2273298948Sadrian bwn_dummy_transmission(mac, 0, 1); 2274298948Sadrian bwn_phy_g_switch_chan(mac, 6, 0); 2275298948Sadrian BWN_RF_READ(mac, 0x51); 2276298948Sadrian if (phy->type == BWN_PHYTYPE_G) 2277298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0); 2278298948Sadrian 2279298948Sadrian nanouptime(&ts); 2280298948Sadrian if (ieee80211_time_before(lo->txctl_measured_time, 2281298948Sadrian (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE)) 2282298948Sadrian bwn_lo_measure_txctl_values(mac); 2283298948Sadrian 2284298948Sadrian if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3) 2285298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078); 2286298948Sadrian else { 2287298948Sadrian if (phy->type == BWN_PHYTYPE_B) 2288298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078); 2289298948Sadrian else 2290298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078); 2291298948Sadrian } 2292298948Sadrian} 2293298948Sadrian 2294298948Sadrianstatic void 2295298948Sadrianbwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav) 2296298948Sadrian{ 2297298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2298298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2299298948Sadrian uint16_t tmp; 2300298948Sadrian 2301298948Sadrian if (phy->rev >= 2) { 2302298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300); 2303298948Sadrian tmp = (pg->pg_pga_gain << 8); 2304298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0); 2305298948Sadrian DELAY(5); 2306298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2); 2307298948Sadrian DELAY(2); 2308298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3); 2309298948Sadrian } else { 2310298948Sadrian tmp = (pg->pg_pga_gain | 0xefa0); 2311298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp); 2312298948Sadrian } 2313298948Sadrian if (phy->type == BWN_PHYTYPE_G) { 2314298948Sadrian if (phy->rev >= 3) 2315298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078); 2316298948Sadrian else 2317298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078); 2318298948Sadrian if (phy->rev >= 2) 2319298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202); 2320298948Sadrian else 2321298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101); 2322298948Sadrian } 2323298948Sadrian BWN_WRITE_2(mac, 0x3f4, sav->reg0); 2324298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl); 2325298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2); 2326298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl); 2327298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl); 2328298948Sadrian BWN_RF_WRITE(mac, 0x43, sav->rf0); 2329298948Sadrian BWN_RF_WRITE(mac, 0x7a, sav->rf1); 2330298948Sadrian if (!BWN_HAS_TXMAG(phy)) { 2331298948Sadrian tmp = sav->rf2; 2332298948Sadrian BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp); 2333298948Sadrian } 2334298948Sadrian BWN_WRITE_2(mac, 0x3e2, sav->reg1); 2335298948Sadrian if (phy->type == BWN_PHYTYPE_B && 2336298948Sadrian phy->rf_ver == 0x2050 && phy->rf_rev <= 5) { 2337298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0); 2338298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1); 2339298948Sadrian } 2340298948Sadrian if (phy->rev >= 2) { 2341298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover); 2342298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 2343298948Sadrian sav->phy_analogoverval); 2344298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl); 2345298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover); 2346298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval); 2347298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3); 2348298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0); 2349298948Sadrian } 2350298948Sadrian if (bwn_has_hwpctl(mac)) { 2351298948Sadrian tmp = (sav->phy_lomask & 0xbfff); 2352298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp); 2353298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg); 2354298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl); 2355298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4); 2356298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl); 2357298948Sadrian } 2358298948Sadrian bwn_phy_g_switch_chan(mac, sav->old_channel, 1); 2359298948Sadrian} 2360298948Sadrian 2361298948Sadrianstatic int 2362298948Sadrianbwn_lo_probe_loctl(struct bwn_mac *mac, 2363298948Sadrian struct bwn_loctl *probe, struct bwn_lo_g_sm *d) 2364298948Sadrian{ 2365298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2366298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2367298948Sadrian struct bwn_loctl orig, test; 2368298948Sadrian struct bwn_loctl prev = { -100, -100 }; 2369298948Sadrian static const struct bwn_loctl modifiers[] = { 2370298948Sadrian { 1, 1,}, { 1, 0,}, { 1, -1,}, { 0, -1,}, 2371298948Sadrian { -1, -1,}, { -1, 0,}, { -1, 1,}, { 0, 1,} 2372298948Sadrian }; 2373298948Sadrian int begin, end, lower = 0, i; 2374298948Sadrian uint16_t feedth; 2375298948Sadrian 2376298948Sadrian if (d->curstate == 0) { 2377298948Sadrian begin = 1; 2378298948Sadrian end = 8; 2379298948Sadrian } else if (d->curstate % 2 == 0) { 2380298948Sadrian begin = d->curstate - 1; 2381298948Sadrian end = d->curstate + 1; 2382298948Sadrian } else { 2383298948Sadrian begin = d->curstate - 2; 2384298948Sadrian end = d->curstate + 2; 2385298948Sadrian } 2386298948Sadrian if (begin < 1) 2387298948Sadrian begin += 8; 2388298948Sadrian if (end > 8) 2389298948Sadrian end -= 8; 2390298948Sadrian 2391298948Sadrian memcpy(&orig, probe, sizeof(struct bwn_loctl)); 2392298948Sadrian i = begin; 2393298948Sadrian d->curstate = i; 2394298948Sadrian while (1) { 2395298948Sadrian KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__)); 2396298948Sadrian memcpy(&test, &orig, sizeof(struct bwn_loctl)); 2397298948Sadrian test.i += modifiers[i - 1].i * d->multipler; 2398298948Sadrian test.q += modifiers[i - 1].q * d->multipler; 2399298948Sadrian if ((test.i != prev.i || test.q != prev.q) && 2400298948Sadrian (abs(test.i) <= 16 && abs(test.q) <= 16)) { 2401298948Sadrian bwn_lo_write(mac, &test); 2402298948Sadrian feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain, 2403298948Sadrian pg->pg_pga_gain, pg->pg_trsw_rx_gain); 2404298948Sadrian if (feedth < d->feedth) { 2405298948Sadrian memcpy(probe, &test, 2406298948Sadrian sizeof(struct bwn_loctl)); 2407298948Sadrian lower = 1; 2408298948Sadrian d->feedth = feedth; 2409298948Sadrian if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy)) 2410298948Sadrian break; 2411298948Sadrian } 2412298948Sadrian } 2413298948Sadrian memcpy(&prev, &test, sizeof(prev)); 2414298948Sadrian if (i == end) 2415298948Sadrian break; 2416298948Sadrian if (i == 8) 2417298948Sadrian i = 1; 2418298948Sadrian else 2419298948Sadrian i++; 2420298948Sadrian d->curstate = i; 2421298948Sadrian } 2422298948Sadrian 2423298948Sadrian return (lower); 2424298948Sadrian} 2425298948Sadrian 2426298948Sadrianstatic void 2427298948Sadrianbwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain) 2428298948Sadrian{ 2429298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2430298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2431298948Sadrian struct bwn_lo_g_sm d; 2432298948Sadrian struct bwn_loctl probe; 2433298948Sadrian int lower, repeat, cnt = 0; 2434298948Sadrian uint16_t feedth; 2435298948Sadrian 2436298948Sadrian d.nmeasure = 0; 2437298948Sadrian d.multipler = 1; 2438298948Sadrian if (BWN_HAS_LOOPBACK(phy)) 2439298948Sadrian d.multipler = 3; 2440298948Sadrian 2441298948Sadrian memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl)); 2442298948Sadrian repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1; 2443298948Sadrian 2444298948Sadrian do { 2445298948Sadrian bwn_lo_write(mac, &d.loctl); 2446298948Sadrian feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain, 2447298948Sadrian pg->pg_pga_gain, pg->pg_trsw_rx_gain); 2448298948Sadrian if (feedth < 0x258) { 2449298948Sadrian if (feedth >= 0x12c) 2450298948Sadrian *rxgain += 6; 2451298948Sadrian else 2452298948Sadrian *rxgain += 3; 2453298948Sadrian feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain, 2454298948Sadrian pg->pg_pga_gain, pg->pg_trsw_rx_gain); 2455298948Sadrian } 2456298948Sadrian d.feedth = feedth; 2457298948Sadrian d.curstate = 0; 2458298948Sadrian do { 2459298948Sadrian KASSERT(d.curstate >= 0 && d.curstate <= 8, 2460298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 2461298948Sadrian memcpy(&probe, &d.loctl, 2462298948Sadrian sizeof(struct bwn_loctl)); 2463298948Sadrian lower = bwn_lo_probe_loctl(mac, &probe, &d); 2464298948Sadrian if (!lower) 2465298948Sadrian break; 2466298948Sadrian if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q)) 2467298948Sadrian break; 2468298948Sadrian memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl)); 2469298948Sadrian d.nmeasure++; 2470298948Sadrian } while (d.nmeasure < 24); 2471298948Sadrian memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl)); 2472298948Sadrian 2473298948Sadrian if (BWN_HAS_LOOPBACK(phy)) { 2474298948Sadrian if (d.feedth > 0x1194) 2475298948Sadrian *rxgain -= 6; 2476298948Sadrian else if (d.feedth < 0x5dc) 2477298948Sadrian *rxgain += 3; 2478298948Sadrian if (cnt == 0) { 2479298948Sadrian if (d.feedth <= 0x5dc) { 2480298948Sadrian d.multipler = 1; 2481298948Sadrian cnt++; 2482298948Sadrian } else 2483298948Sadrian d.multipler = 2; 2484298948Sadrian } else if (cnt == 2) 2485298948Sadrian d.multipler = 1; 2486298948Sadrian } 2487298948Sadrian bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy)); 2488298948Sadrian } while (++cnt < repeat); 2489298948Sadrian} 2490298948Sadrian 2491298948Sadrianstatic struct bwn_lo_calib * 2492298948Sadrianbwn_lo_calibset(struct bwn_mac *mac, 2493298948Sadrian const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt) 2494298948Sadrian{ 2495298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2496298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2497298948Sadrian struct bwn_loctl loctl = { 0, 0 }; 2498298948Sadrian struct bwn_lo_calib *cal; 2499298948Sadrian struct bwn_lo_g_value sval = { 0 }; 2500298948Sadrian int rxgain; 2501298948Sadrian uint16_t pad, reg, value; 2502298948Sadrian 2503298948Sadrian sval.old_channel = phy->chan; 2504298948Sadrian bwn_mac_suspend(mac); 2505298948Sadrian bwn_lo_save(mac, &sval); 2506298948Sadrian 2507298948Sadrian reg = bwn_lo_txctl_regtable(mac, &value, &pad); 2508298948Sadrian BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att); 2509298948Sadrian BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0)); 2510298948Sadrian 2511298948Sadrian rxgain = (rfatt->att * 2) + (bbatt->att / 2); 2512298948Sadrian if (rfatt->padmix) 2513298948Sadrian rxgain -= pad; 2514298948Sadrian if (BWN_HAS_LOOPBACK(phy)) 2515298948Sadrian rxgain += pg->pg_max_lb_gain; 2516298948Sadrian bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy)); 2517298948Sadrian bwn_phy_g_set_bbatt(mac, bbatt->att); 2518298948Sadrian bwn_lo_probe_sm(mac, &loctl, &rxgain); 2519298948Sadrian 2520298948Sadrian bwn_lo_restore(mac, &sval); 2521298948Sadrian bwn_mac_enable(mac); 2522298948Sadrian 2523298948Sadrian cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO); 2524298948Sadrian if (!cal) { 2525298948Sadrian device_printf(mac->mac_sc->sc_dev, "out of memory\n"); 2526298948Sadrian return (NULL); 2527298948Sadrian } 2528298948Sadrian memcpy(&cal->bbatt, bbatt, sizeof(*bbatt)); 2529298948Sadrian memcpy(&cal->rfatt, rfatt, sizeof(*rfatt)); 2530298948Sadrian memcpy(&cal->ctl, &loctl, sizeof(loctl)); 2531298948Sadrian 2532298948Sadrian BWN_GETTIME(cal->calib_time); 2533298948Sadrian 2534298948Sadrian return (cal); 2535298948Sadrian} 2536298948Sadrian 2537298948Sadrianstatic struct bwn_lo_calib * 2538298948Sadrianbwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt, 2539298948Sadrian const struct bwn_rfatt *rfatt) 2540298948Sadrian{ 2541298948Sadrian struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl; 2542298948Sadrian struct bwn_lo_calib *c; 2543298948Sadrian 2544298948Sadrian TAILQ_FOREACH(c, &lo->calib_list, list) { 2545298948Sadrian if (!BWN_BBATTCMP(&c->bbatt, bbatt)) 2546298948Sadrian continue; 2547298948Sadrian if (!BWN_RFATTCMP(&c->rfatt, rfatt)) 2548298948Sadrian continue; 2549298948Sadrian return (c); 2550298948Sadrian } 2551298948Sadrian 2552298948Sadrian c = bwn_lo_calibset(mac, bbatt, rfatt); 2553298948Sadrian if (!c) 2554298948Sadrian return (NULL); 2555298948Sadrian TAILQ_INSERT_TAIL(&lo->calib_list, c, list); 2556298948Sadrian 2557298948Sadrian return (c); 2558298948Sadrian} 2559298948Sadrian 2560298948Sadrianstatic void 2561298948Sadrianbwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update) 2562298948Sadrian{ 2563298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2564298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2565298948Sadrian struct bwn_softc *sc = mac->mac_sc; 2566298948Sadrian struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 2567298948Sadrian const struct bwn_rfatt *rfatt; 2568298948Sadrian const struct bwn_bbatt *bbatt; 2569298948Sadrian uint64_t pvector; 2570298948Sadrian int i; 2571298948Sadrian int rf_offset, bb_offset; 2572298948Sadrian uint8_t changed = 0; 2573298948Sadrian 2574298948Sadrian KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__)); 2575298948Sadrian KASSERT(lo->rfatt.len * lo->bbatt.len <= 64, 2576298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 2577298948Sadrian 2578298948Sadrian pvector = lo->power_vector; 2579298948Sadrian if (!update && !pvector) 2580298948Sadrian return; 2581298948Sadrian 2582298948Sadrian bwn_mac_suspend(mac); 2583298948Sadrian 2584298948Sadrian for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) { 2585298948Sadrian struct bwn_lo_calib *cal; 2586298948Sadrian int idx; 2587298948Sadrian uint16_t val; 2588298948Sadrian 2589298948Sadrian if (!update && !(pvector & (((uint64_t)1ULL) << i))) 2590298948Sadrian continue; 2591298948Sadrian bb_offset = i / lo->rfatt.len; 2592298948Sadrian rf_offset = i % lo->rfatt.len; 2593298948Sadrian bbatt = &(lo->bbatt.array[bb_offset]); 2594298948Sadrian rfatt = &(lo->rfatt.array[rf_offset]); 2595298948Sadrian 2596298948Sadrian cal = bwn_lo_calibset(mac, bbatt, rfatt); 2597298948Sadrian if (!cal) { 2598298948Sadrian device_printf(sc->sc_dev, "LO: Could not " 2599298948Sadrian "calibrate DC table entry\n"); 2600298948Sadrian continue; 2601298948Sadrian } 2602298948Sadrian val = (uint8_t)(cal->ctl.q); 2603298948Sadrian val |= ((uint8_t)(cal->ctl.i)) << 4; 2604298948Sadrian free(cal, M_DEVBUF); 2605298948Sadrian 2606298948Sadrian idx = i / 2; 2607298948Sadrian if (i % 2) 2608298948Sadrian lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff) 2609298948Sadrian | ((val & 0x00ff) << 8); 2610298948Sadrian else 2611298948Sadrian lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00) 2612298948Sadrian | (val & 0x00ff); 2613298948Sadrian changed = 1; 2614298948Sadrian } 2615298948Sadrian if (changed) { 2616298948Sadrian for (i = 0; i < BWN_DC_LT_SIZE; i++) 2617298948Sadrian BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]); 2618298948Sadrian } 2619298948Sadrian bwn_mac_enable(mac); 2620298948Sadrian} 2621298948Sadrian 2622298948Sadrianstatic void 2623298948Sadrianbwn_lo_fixup_rfatt(struct bwn_rfatt *rf) 2624298948Sadrian{ 2625298948Sadrian 2626298948Sadrian if (!rf->padmix) 2627298948Sadrian return; 2628298948Sadrian if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3)) 2629298948Sadrian rf->att = 4; 2630298948Sadrian} 2631298948Sadrian 2632298948Sadrianstatic void 2633298948Sadrianbwn_lo_g_adjust(struct bwn_mac *mac) 2634298948Sadrian{ 2635298948Sadrian struct bwn_phy_g *pg = &mac->mac_phy.phy_g; 2636298948Sadrian struct bwn_lo_calib *cal; 2637298948Sadrian struct bwn_rfatt rf; 2638298948Sadrian 2639298948Sadrian memcpy(&rf, &pg->pg_rfatt, sizeof(rf)); 2640298948Sadrian bwn_lo_fixup_rfatt(&rf); 2641298948Sadrian 2642298948Sadrian cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf); 2643298948Sadrian if (!cal) 2644298948Sadrian return; 2645298948Sadrian bwn_lo_write(mac, &cal->ctl); 2646298948Sadrian} 2647298948Sadrian 2648298948Sadrianstatic void 2649298948Sadrianbwn_lo_g_init(struct bwn_mac *mac) 2650298948Sadrian{ 2651298948Sadrian 2652298948Sadrian if (!bwn_has_hwpctl(mac)) 2653298948Sadrian return; 2654298948Sadrian 2655298948Sadrian bwn_lo_get_powervector(mac); 2656298948Sadrian bwn_phy_g_dc_lookup_init(mac, 1); 2657298948Sadrian} 2658298948Sadrian 2659298948Sadrianstatic int16_t 2660298948Sadrianbwn_nrssi_read(struct bwn_mac *mac, uint16_t offset) 2661298948Sadrian{ 2662298948Sadrian 2663298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset); 2664298948Sadrian return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA)); 2665298948Sadrian} 2666298948Sadrian 2667298948Sadrianstatic void 2668298948Sadrianbwn_nrssi_threshold(struct bwn_mac *mac) 2669298948Sadrian{ 2670298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2671298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2672298948Sadrian struct bwn_softc *sc = mac->mac_sc; 2673298948Sadrian int32_t a, b; 2674298948Sadrian int16_t tmp16; 2675298948Sadrian uint16_t tmpu16; 2676298948Sadrian 2677298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__)); 2678298948Sadrian 2679298948Sadrian if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) { 2680298948Sadrian if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) { 2681298948Sadrian a = 0x13; 2682298948Sadrian b = 0x12; 2683298948Sadrian } else { 2684298948Sadrian a = 0xe; 2685298948Sadrian b = 0x11; 2686298948Sadrian } 2687298948Sadrian 2688298948Sadrian a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]); 2689298948Sadrian a += (pg->pg_nrssi[0] << 6); 2690298948Sadrian a += (a < 32) ? 31 : 32; 2691298948Sadrian a = a >> 6; 2692298948Sadrian a = MIN(MAX(a, -31), 31); 2693298948Sadrian 2694298948Sadrian b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]); 2695298948Sadrian b += (pg->pg_nrssi[0] << 6); 2696298948Sadrian if (b < 32) 2697298948Sadrian b += 31; 2698298948Sadrian else 2699298948Sadrian b += 32; 2700298948Sadrian b = b >> 6; 2701298948Sadrian b = MIN(MAX(b, -31), 31); 2702298948Sadrian 2703298948Sadrian tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000; 2704298948Sadrian tmpu16 |= ((uint32_t)b & 0x0000003f); 2705298948Sadrian tmpu16 |= (((uint32_t)a & 0x0000003f) << 6); 2706298948Sadrian BWN_PHY_WRITE(mac, 0x048a, tmpu16); 2707298948Sadrian return; 2708298948Sadrian } 2709298948Sadrian 2710298948Sadrian tmp16 = bwn_nrssi_read(mac, 0x20); 2711298948Sadrian if (tmp16 >= 0x20) 2712298948Sadrian tmp16 -= 0x40; 2713298948Sadrian BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed); 2714298948Sadrian} 2715298948Sadrian 2716298948Sadrianstatic void 2717298948Sadrianbwn_nrssi_slope_11g(struct bwn_mac *mac) 2718298948Sadrian{ 2719298948Sadrian#define SAVE_RF_MAX 3 2720298948Sadrian#define SAVE_PHY_COMM_MAX 4 2721298948Sadrian#define SAVE_PHY3_MAX 8 2722298948Sadrian static const uint16_t save_rf_regs[SAVE_RF_MAX] = 2723298948Sadrian { 0x7a, 0x52, 0x43 }; 2724298948Sadrian static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = 2725298948Sadrian { 0x15, 0x5a, 0x59, 0x58 }; 2726298948Sadrian static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = { 2727298948Sadrian 0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL, 2728298948Sadrian 0x0801, 0x0060, 0x0014, 0x0478 2729298948Sadrian }; 2730298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2731298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 2732298948Sadrian int32_t i, tmp32, phy3_idx = 0; 2733298948Sadrian uint16_t delta, tmp; 2734298948Sadrian uint16_t save_rf[SAVE_RF_MAX]; 2735298948Sadrian uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 2736298948Sadrian uint16_t save_phy3[SAVE_PHY3_MAX]; 2737298948Sadrian uint16_t ant_div, phy0, chan_ex; 2738298948Sadrian int16_t nrssi0, nrssi1; 2739298948Sadrian 2740298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, 2741298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 2742298948Sadrian 2743298948Sadrian if (phy->rf_rev >= 9) 2744298948Sadrian return; 2745298948Sadrian if (phy->rf_rev == 8) 2746298948Sadrian bwn_nrssi_offset(mac); 2747298948Sadrian 2748298948Sadrian BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff); 2749298948Sadrian BWN_PHY_MASK(mac, 0x0802, 0xfffc); 2750298948Sadrian 2751298948Sadrian /* 2752298948Sadrian * Save RF/PHY registers for later restoration 2753298948Sadrian */ 2754298948Sadrian ant_div = BWN_READ_2(mac, 0x03e2); 2755298948Sadrian BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000); 2756298948Sadrian for (i = 0; i < SAVE_RF_MAX; ++i) 2757298948Sadrian save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]); 2758298948Sadrian for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 2759298948Sadrian save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]); 2760298948Sadrian 2761298948Sadrian phy0 = BWN_READ_2(mac, BWN_PHY0); 2762298948Sadrian chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT); 2763298948Sadrian if (phy->rev >= 3) { 2764298948Sadrian for (i = 0; i < SAVE_PHY3_MAX; ++i) 2765298948Sadrian save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]); 2766298948Sadrian BWN_PHY_WRITE(mac, 0x002e, 0); 2767298948Sadrian BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0); 2768298948Sadrian switch (phy->rev) { 2769298948Sadrian case 4: 2770298948Sadrian case 6: 2771298948Sadrian case 7: 2772298948Sadrian BWN_PHY_SET(mac, 0x0478, 0x0100); 2773298948Sadrian BWN_PHY_SET(mac, 0x0801, 0x0040); 2774298948Sadrian break; 2775298948Sadrian case 3: 2776298948Sadrian case 5: 2777298948Sadrian BWN_PHY_MASK(mac, 0x0801, 0xffbf); 2778298948Sadrian break; 2779298948Sadrian } 2780298948Sadrian BWN_PHY_SET(mac, 0x0060, 0x0040); 2781298948Sadrian BWN_PHY_SET(mac, 0x0014, 0x0200); 2782298948Sadrian } 2783298948Sadrian /* 2784298948Sadrian * Calculate nrssi0 2785298948Sadrian */ 2786298948Sadrian BWN_RF_SET(mac, 0x007a, 0x0070); 2787298948Sadrian bwn_set_all_gains(mac, 0, 8, 0); 2788298948Sadrian BWN_RF_MASK(mac, 0x007a, 0x00f7); 2789298948Sadrian if (phy->rev >= 2) { 2790298948Sadrian BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030); 2791298948Sadrian BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010); 2792298948Sadrian } 2793298948Sadrian BWN_RF_SET(mac, 0x007a, 0x0080); 2794298948Sadrian DELAY(20); 2795298948Sadrian 2796298948Sadrian nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f); 2797298948Sadrian if (nrssi0 >= 0x0020) 2798298948Sadrian nrssi0 -= 0x0040; 2799298948Sadrian 2800298948Sadrian /* 2801298948Sadrian * Calculate nrssi1 2802298948Sadrian */ 2803298948Sadrian BWN_RF_MASK(mac, 0x007a, 0x007f); 2804298948Sadrian if (phy->rev >= 2) 2805298948Sadrian BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040); 2806298948Sadrian 2807298948Sadrian BWN_WRITE_2(mac, BWN_CHANNEL_EXT, 2808298948Sadrian BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000); 2809298948Sadrian BWN_RF_SET(mac, 0x007a, 0x000f); 2810298948Sadrian BWN_PHY_WRITE(mac, 0x0015, 0xf330); 2811298948Sadrian if (phy->rev >= 2) { 2812298948Sadrian BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020); 2813298948Sadrian BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020); 2814298948Sadrian } 2815298948Sadrian 2816298948Sadrian bwn_set_all_gains(mac, 3, 0, 1); 2817298948Sadrian if (phy->rf_rev == 8) { 2818298948Sadrian BWN_RF_WRITE(mac, 0x0043, 0x001f); 2819298948Sadrian } else { 2820298948Sadrian tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f; 2821298948Sadrian BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060); 2822298948Sadrian tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0; 2823298948Sadrian BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009); 2824298948Sadrian } 2825298948Sadrian BWN_PHY_WRITE(mac, 0x005a, 0x0480); 2826298948Sadrian BWN_PHY_WRITE(mac, 0x0059, 0x0810); 2827298948Sadrian BWN_PHY_WRITE(mac, 0x0058, 0x000d); 2828298948Sadrian DELAY(20); 2829298948Sadrian nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f); 2830298948Sadrian 2831298948Sadrian /* 2832298948Sadrian * Install calculated narrow RSSI values 2833298948Sadrian */ 2834298948Sadrian if (nrssi1 >= 0x0020) 2835298948Sadrian nrssi1 -= 0x0040; 2836298948Sadrian if (nrssi0 == nrssi1) 2837298948Sadrian pg->pg_nrssi_slope = 0x00010000; 2838298948Sadrian else 2839298948Sadrian pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1); 2840298948Sadrian if (nrssi0 >= -4) { 2841298948Sadrian pg->pg_nrssi[0] = nrssi1; 2842298948Sadrian pg->pg_nrssi[1] = nrssi0; 2843298948Sadrian } 2844298948Sadrian 2845298948Sadrian /* 2846298948Sadrian * Restore saved RF/PHY registers 2847298948Sadrian */ 2848298948Sadrian if (phy->rev >= 3) { 2849298948Sadrian for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) { 2850298948Sadrian BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx], 2851298948Sadrian save_phy3[phy3_idx]); 2852298948Sadrian } 2853298948Sadrian } 2854298948Sadrian if (phy->rev >= 2) { 2855298948Sadrian BWN_PHY_MASK(mac, 0x0812, 0xffcf); 2856298948Sadrian BWN_PHY_MASK(mac, 0x0811, 0xffcf); 2857298948Sadrian } 2858298948Sadrian 2859298948Sadrian for (i = 0; i < SAVE_RF_MAX; ++i) 2860298948Sadrian BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 2861298948Sadrian 2862298948Sadrian BWN_WRITE_2(mac, 0x03e2, ant_div); 2863298948Sadrian BWN_WRITE_2(mac, 0x03e6, phy0); 2864298948Sadrian BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex); 2865298948Sadrian 2866298948Sadrian for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 2867298948Sadrian BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); 2868298948Sadrian 2869298948Sadrian bwn_spu_workaround(mac, phy->chan); 2870298948Sadrian BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002)); 2871298948Sadrian bwn_set_original_gains(mac); 2872298948Sadrian BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000); 2873298948Sadrian if (phy->rev >= 3) { 2874298948Sadrian for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) { 2875298948Sadrian BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx], 2876298948Sadrian save_phy3[phy3_idx]); 2877298948Sadrian } 2878298948Sadrian } 2879298948Sadrian 2880298948Sadrian delta = 0x1f - pg->pg_nrssi[0]; 2881298948Sadrian for (i = 0; i < 64; i++) { 2882298948Sadrian tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a; 2883298948Sadrian tmp32 = MIN(MAX(tmp32, 0), 0x3f); 2884298948Sadrian pg->pg_nrssi_lt[i] = tmp32; 2885298948Sadrian } 2886298948Sadrian 2887298948Sadrian bwn_nrssi_threshold(mac); 2888298948Sadrian#undef SAVE_RF_MAX 2889298948Sadrian#undef SAVE_PHY_COMM_MAX 2890298948Sadrian#undef SAVE_PHY3_MAX 2891298948Sadrian} 2892298948Sadrian 2893298948Sadrianstatic void 2894298948Sadrianbwn_nrssi_offset(struct bwn_mac *mac) 2895298948Sadrian{ 2896298948Sadrian#define SAVE_RF_MAX 2 2897298948Sadrian#define SAVE_PHY_COMM_MAX 10 2898298948Sadrian#define SAVE_PHY6_MAX 8 2899298948Sadrian static const uint16_t save_rf_regs[SAVE_RF_MAX] = 2900298948Sadrian { 0x7a, 0x43 }; 2901298948Sadrian static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = { 2902298948Sadrian 0x0001, 0x0811, 0x0812, 0x0814, 2903298948Sadrian 0x0815, 0x005a, 0x0059, 0x0058, 2904298948Sadrian 0x000a, 0x0003 2905298948Sadrian }; 2906298948Sadrian static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = { 2907298948Sadrian 0x002e, 0x002f, 0x080f, 0x0810, 2908298948Sadrian 0x0801, 0x0060, 0x0014, 0x0478 2909298948Sadrian }; 2910298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 2911298948Sadrian int i, phy6_idx = 0; 2912298948Sadrian uint16_t save_rf[SAVE_RF_MAX]; 2913298948Sadrian uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 2914298948Sadrian uint16_t save_phy6[SAVE_PHY6_MAX]; 2915298948Sadrian int16_t nrssi; 2916298948Sadrian uint16_t saved = 0xffff; 2917298948Sadrian 2918298948Sadrian for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 2919298948Sadrian save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]); 2920298948Sadrian for (i = 0; i < SAVE_RF_MAX; ++i) 2921298948Sadrian save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]); 2922298948Sadrian 2923298948Sadrian BWN_PHY_MASK(mac, 0x0429, 0x7fff); 2924298948Sadrian BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000); 2925298948Sadrian BWN_PHY_SET(mac, 0x0811, 0x000c); 2926298948Sadrian BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004); 2927298948Sadrian BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2)); 2928298948Sadrian if (phy->rev >= 6) { 2929298948Sadrian for (i = 0; i < SAVE_PHY6_MAX; ++i) 2930298948Sadrian save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]); 2931298948Sadrian 2932298948Sadrian BWN_PHY_WRITE(mac, 0x002e, 0); 2933298948Sadrian BWN_PHY_WRITE(mac, 0x002f, 0); 2934298948Sadrian BWN_PHY_WRITE(mac, 0x080f, 0); 2935298948Sadrian BWN_PHY_WRITE(mac, 0x0810, 0); 2936298948Sadrian BWN_PHY_SET(mac, 0x0478, 0x0100); 2937298948Sadrian BWN_PHY_SET(mac, 0x0801, 0x0040); 2938298948Sadrian BWN_PHY_SET(mac, 0x0060, 0x0040); 2939298948Sadrian BWN_PHY_SET(mac, 0x0014, 0x0200); 2940298948Sadrian } 2941298948Sadrian BWN_RF_SET(mac, 0x007a, 0x0070); 2942298948Sadrian BWN_RF_SET(mac, 0x007a, 0x0080); 2943298948Sadrian DELAY(30); 2944298948Sadrian 2945298948Sadrian nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f); 2946298948Sadrian if (nrssi >= 0x20) 2947298948Sadrian nrssi -= 0x40; 2948298948Sadrian if (nrssi == 31) { 2949298948Sadrian for (i = 7; i >= 4; i--) { 2950298948Sadrian BWN_RF_WRITE(mac, 0x007b, i); 2951298948Sadrian DELAY(20); 2952298948Sadrian nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 2953298948Sadrian 0x003f); 2954298948Sadrian if (nrssi >= 0x20) 2955298948Sadrian nrssi -= 0x40; 2956298948Sadrian if (nrssi < 31 && saved == 0xffff) 2957298948Sadrian saved = i; 2958298948Sadrian } 2959298948Sadrian if (saved == 0xffff) 2960298948Sadrian saved = 4; 2961298948Sadrian } else { 2962298948Sadrian BWN_RF_MASK(mac, 0x007a, 0x007f); 2963298948Sadrian if (phy->rev != 1) { 2964298948Sadrian BWN_PHY_SET(mac, 0x0814, 0x0001); 2965298948Sadrian BWN_PHY_MASK(mac, 0x0815, 0xfffe); 2966298948Sadrian } 2967298948Sadrian BWN_PHY_SET(mac, 0x0811, 0x000c); 2968298948Sadrian BWN_PHY_SET(mac, 0x0812, 0x000c); 2969298948Sadrian BWN_PHY_SET(mac, 0x0811, 0x0030); 2970298948Sadrian BWN_PHY_SET(mac, 0x0812, 0x0030); 2971298948Sadrian BWN_PHY_WRITE(mac, 0x005a, 0x0480); 2972298948Sadrian BWN_PHY_WRITE(mac, 0x0059, 0x0810); 2973298948Sadrian BWN_PHY_WRITE(mac, 0x0058, 0x000d); 2974298948Sadrian if (phy->rev == 0) 2975298948Sadrian BWN_PHY_WRITE(mac, 0x0003, 0x0122); 2976298948Sadrian else 2977298948Sadrian BWN_PHY_SET(mac, 0x000a, 0x2000); 2978298948Sadrian if (phy->rev != 1) { 2979298948Sadrian BWN_PHY_SET(mac, 0x0814, 0x0004); 2980298948Sadrian BWN_PHY_MASK(mac, 0x0815, 0xfffb); 2981298948Sadrian } 2982298948Sadrian BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040); 2983298948Sadrian BWN_RF_SET(mac, 0x007a, 0x000f); 2984298948Sadrian bwn_set_all_gains(mac, 3, 0, 1); 2985298948Sadrian BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f); 2986298948Sadrian DELAY(30); 2987298948Sadrian nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f); 2988298948Sadrian if (nrssi >= 0x20) 2989298948Sadrian nrssi -= 0x40; 2990298948Sadrian if (nrssi == -32) { 2991298948Sadrian for (i = 0; i < 4; i++) { 2992298948Sadrian BWN_RF_WRITE(mac, 0x007b, i); 2993298948Sadrian DELAY(20); 2994298948Sadrian nrssi = (int16_t)((BWN_PHY_READ(mac, 2995298948Sadrian 0x047f) >> 8) & 0x003f); 2996298948Sadrian if (nrssi >= 0x20) 2997298948Sadrian nrssi -= 0x40; 2998298948Sadrian if (nrssi > -31 && saved == 0xffff) 2999298948Sadrian saved = i; 3000298948Sadrian } 3001298948Sadrian if (saved == 0xffff) 3002298948Sadrian saved = 3; 3003298948Sadrian } else 3004298948Sadrian saved = 0; 3005298948Sadrian } 3006298948Sadrian BWN_RF_WRITE(mac, 0x007b, saved); 3007298948Sadrian 3008298948Sadrian /* 3009298948Sadrian * Restore saved RF/PHY registers 3010298948Sadrian */ 3011298948Sadrian if (phy->rev >= 6) { 3012298948Sadrian for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) { 3013298948Sadrian BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx], 3014298948Sadrian save_phy6[phy6_idx]); 3015298948Sadrian } 3016298948Sadrian } 3017298948Sadrian if (phy->rev != 1) { 3018298948Sadrian for (i = 3; i < 5; i++) 3019298948Sadrian BWN_PHY_WRITE(mac, save_phy_comm_regs[i], 3020298948Sadrian save_phy_comm[i]); 3021298948Sadrian } 3022298948Sadrian for (i = 5; i < SAVE_PHY_COMM_MAX; i++) 3023298948Sadrian BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); 3024298948Sadrian 3025298948Sadrian for (i = SAVE_RF_MAX - 1; i >= 0; --i) 3026298948Sadrian BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 3027298948Sadrian 3028298948Sadrian BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2); 3029298948Sadrian BWN_PHY_SET(mac, 0x0429, 0x8000); 3030298948Sadrian bwn_set_original_gains(mac); 3031298948Sadrian if (phy->rev >= 6) { 3032298948Sadrian for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) { 3033298948Sadrian BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx], 3034298948Sadrian save_phy6[phy6_idx]); 3035298948Sadrian } 3036298948Sadrian } 3037298948Sadrian 3038298948Sadrian BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]); 3039298948Sadrian BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]); 3040298948Sadrian BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]); 3041298948Sadrian} 3042298948Sadrian 3043298948Sadrianstatic void 3044298948Sadrianbwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second, 3045298948Sadrian int16_t third) 3046298948Sadrian{ 3047298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 3048298948Sadrian uint16_t i; 3049298948Sadrian uint16_t start = 0x08, end = 0x18; 3050298948Sadrian uint16_t tmp; 3051298948Sadrian uint16_t table; 3052298948Sadrian 3053298948Sadrian if (phy->rev <= 1) { 3054298948Sadrian start = 0x10; 3055298948Sadrian end = 0x20; 3056298948Sadrian } 3057298948Sadrian 3058298948Sadrian table = BWN_OFDMTAB_GAINX; 3059298948Sadrian if (phy->rev <= 1) 3060298948Sadrian table = BWN_OFDMTAB_GAINX_R1; 3061298948Sadrian for (i = 0; i < 4; i++) 3062298948Sadrian bwn_ofdmtab_write_2(mac, table, i, first); 3063298948Sadrian 3064298948Sadrian for (i = start; i < end; i++) 3065298948Sadrian bwn_ofdmtab_write_2(mac, table, i, second); 3066298948Sadrian 3067298948Sadrian if (third != -1) { 3068298948Sadrian tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6); 3069298948Sadrian BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp); 3070298948Sadrian BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp); 3071298948Sadrian BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp); 3072298948Sadrian } 3073298948Sadrian bwn_dummy_transmission(mac, 0, 1); 3074298948Sadrian} 3075298948Sadrian 3076298948Sadrianstatic void 3077298948Sadrianbwn_set_original_gains(struct bwn_mac *mac) 3078298948Sadrian{ 3079298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 3080298948Sadrian uint16_t i, tmp; 3081298948Sadrian uint16_t table; 3082298948Sadrian uint16_t start = 0x0008, end = 0x0018; 3083298948Sadrian 3084298948Sadrian if (phy->rev <= 1) { 3085298948Sadrian start = 0x0010; 3086298948Sadrian end = 0x0020; 3087298948Sadrian } 3088298948Sadrian 3089298948Sadrian table = BWN_OFDMTAB_GAINX; 3090298948Sadrian if (phy->rev <= 1) 3091298948Sadrian table = BWN_OFDMTAB_GAINX_R1; 3092298948Sadrian for (i = 0; i < 4; i++) { 3093298948Sadrian tmp = (i & 0xfffc); 3094298948Sadrian tmp |= (i & 0x0001) << 1; 3095298948Sadrian tmp |= (i & 0x0002) >> 1; 3096298948Sadrian 3097298948Sadrian bwn_ofdmtab_write_2(mac, table, i, tmp); 3098298948Sadrian } 3099298948Sadrian 3100298948Sadrian for (i = start; i < end; i++) 3101298948Sadrian bwn_ofdmtab_write_2(mac, table, i, i - start); 3102298948Sadrian 3103298948Sadrian BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040); 3104298948Sadrian BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040); 3105298948Sadrian BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000); 3106298948Sadrian bwn_dummy_transmission(mac, 0, 1); 3107298948Sadrian} 3108298948Sadrian 3109298948Sadrianstatic void 3110298948Sadrianbwn_phy_hwpctl_init(struct bwn_mac *mac) 3111298948Sadrian{ 3112298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 3113298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 3114298948Sadrian struct bwn_rfatt old_rfatt, rfatt; 3115298948Sadrian struct bwn_bbatt old_bbatt, bbatt; 3116298948Sadrian struct bwn_softc *sc = mac->mac_sc; 3117298948Sadrian uint8_t old_txctl = 0; 3118298948Sadrian 3119298948Sadrian KASSERT(phy->type == BWN_PHYTYPE_G, 3120298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 3121298948Sadrian 3122298948Sadrian if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) && 3123298948Sadrian (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)) 3124298948Sadrian return; 3125298948Sadrian 3126298948Sadrian BWN_PHY_WRITE(mac, 0x0028, 0x8018); 3127298948Sadrian 3128298948Sadrian BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf); 3129298948Sadrian 3130298948Sadrian if (!phy->gmode) 3131298948Sadrian return; 3132298948Sadrian bwn_hwpctl_early_init(mac); 3133298948Sadrian if (pg->pg_curtssi == 0) { 3134298948Sadrian if (phy->rf_ver == 0x2050 && phy->analog == 0) { 3135298948Sadrian BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084); 3136298948Sadrian } else { 3137298948Sadrian memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt)); 3138298948Sadrian memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt)); 3139298948Sadrian old_txctl = pg->pg_txctl; 3140298948Sadrian 3141298948Sadrian bbatt.att = 11; 3142298948Sadrian if (phy->rf_rev == 8) { 3143298948Sadrian rfatt.att = 15; 3144298948Sadrian rfatt.padmix = 1; 3145298948Sadrian } else { 3146298948Sadrian rfatt.att = 9; 3147298948Sadrian rfatt.padmix = 0; 3148298948Sadrian } 3149298948Sadrian bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0); 3150298948Sadrian } 3151298948Sadrian bwn_dummy_transmission(mac, 0, 1); 3152298948Sadrian pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI); 3153298948Sadrian if (phy->rf_ver == 0x2050 && phy->analog == 0) 3154298948Sadrian BWN_RF_MASK(mac, 0x0076, 0xff7b); 3155298948Sadrian else 3156298948Sadrian bwn_phy_g_set_txpwr_sub(mac, &old_bbatt, 3157298948Sadrian &old_rfatt, old_txctl); 3158298948Sadrian } 3159298948Sadrian bwn_hwpctl_init_gphy(mac); 3160298948Sadrian 3161298948Sadrian /* clear TSSI */ 3162298948Sadrian bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f); 3163298948Sadrian bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f); 3164298948Sadrian bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f); 3165298948Sadrian bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f); 3166298948Sadrian} 3167298948Sadrian 3168298948Sadrianstatic void 3169298948Sadrianbwn_hwpctl_early_init(struct bwn_mac *mac) 3170298948Sadrian{ 3171298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 3172298948Sadrian 3173298948Sadrian if (!bwn_has_hwpctl(mac)) { 3174298948Sadrian BWN_PHY_WRITE(mac, 0x047a, 0xc111); 3175298948Sadrian return; 3176298948Sadrian } 3177298948Sadrian 3178298948Sadrian BWN_PHY_MASK(mac, 0x0036, 0xfeff); 3179298948Sadrian BWN_PHY_WRITE(mac, 0x002f, 0x0202); 3180298948Sadrian BWN_PHY_SET(mac, 0x047c, 0x0002); 3181298948Sadrian BWN_PHY_SET(mac, 0x047a, 0xf000); 3182298948Sadrian if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) { 3183298948Sadrian BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010); 3184298948Sadrian BWN_PHY_SET(mac, 0x005d, 0x8000); 3185298948Sadrian BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010); 3186298948Sadrian BWN_PHY_WRITE(mac, 0x002e, 0xc07f); 3187298948Sadrian BWN_PHY_SET(mac, 0x0036, 0x0400); 3188298948Sadrian } else { 3189298948Sadrian BWN_PHY_SET(mac, 0x0036, 0x0200); 3190298948Sadrian BWN_PHY_SET(mac, 0x0036, 0x0400); 3191298948Sadrian BWN_PHY_MASK(mac, 0x005d, 0x7fff); 3192298948Sadrian BWN_PHY_MASK(mac, 0x004f, 0xfffe); 3193298948Sadrian BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010); 3194298948Sadrian BWN_PHY_WRITE(mac, 0x002e, 0xc07f); 3195298948Sadrian BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010); 3196298948Sadrian } 3197298948Sadrian} 3198298948Sadrian 3199298948Sadrianstatic void 3200298948Sadrianbwn_hwpctl_init_gphy(struct bwn_mac *mac) 3201298948Sadrian{ 3202298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 3203298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 3204298948Sadrian struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 3205298948Sadrian int i; 3206298948Sadrian uint16_t nr_written = 0, tmp, value; 3207298948Sadrian uint8_t rf, bb; 3208298948Sadrian 3209298948Sadrian if (!bwn_has_hwpctl(mac)) { 3210298948Sadrian bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL); 3211298948Sadrian return; 3212298948Sadrian } 3213298948Sadrian 3214298948Sadrian BWN_PHY_SETMASK(mac, 0x0036, 0xffc0, 3215298948Sadrian (pg->pg_idletssi - pg->pg_curtssi)); 3216298948Sadrian BWN_PHY_SETMASK(mac, 0x0478, 0xff00, 3217298948Sadrian (pg->pg_idletssi - pg->pg_curtssi)); 3218298948Sadrian 3219298948Sadrian for (i = 0; i < 32; i++) 3220298948Sadrian bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]); 3221298948Sadrian for (i = 32; i < 64; i++) 3222298948Sadrian bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]); 3223298948Sadrian for (i = 0; i < 64; i += 2) { 3224298948Sadrian value = (uint16_t) pg->pg_tssi2dbm[i]; 3225298948Sadrian value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8; 3226298948Sadrian BWN_PHY_WRITE(mac, 0x380 + (i / 2), value); 3227298948Sadrian } 3228298948Sadrian 3229298948Sadrian for (rf = 0; rf < lo->rfatt.len; rf++) { 3230298948Sadrian for (bb = 0; bb < lo->bbatt.len; bb++) { 3231298948Sadrian if (nr_written >= 0x40) 3232298948Sadrian return; 3233298948Sadrian tmp = lo->bbatt.array[bb].att; 3234298948Sadrian tmp <<= 8; 3235298948Sadrian if (phy->rf_rev == 8) 3236298948Sadrian tmp |= 0x50; 3237298948Sadrian else 3238298948Sadrian tmp |= 0x40; 3239298948Sadrian tmp |= lo->rfatt.array[rf].att; 3240298948Sadrian BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp); 3241298948Sadrian nr_written++; 3242298948Sadrian } 3243298948Sadrian } 3244298948Sadrian 3245298948Sadrian BWN_PHY_MASK(mac, 0x0060, 0xffbf); 3246298948Sadrian BWN_PHY_WRITE(mac, 0x0014, 0x0000); 3247298948Sadrian 3248298948Sadrian KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__)); 3249298948Sadrian BWN_PHY_SET(mac, 0x0478, 0x0800); 3250298948Sadrian BWN_PHY_MASK(mac, 0x0478, 0xfeff); 3251298948Sadrian BWN_PHY_MASK(mac, 0x0801, 0xffbf); 3252298948Sadrian 3253298948Sadrian bwn_phy_g_dc_lookup_init(mac, 1); 3254298948Sadrian bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL); 3255298948Sadrian} 3256298948Sadrian 3257298948Sadrianstatic void 3258298948Sadrianbwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu) 3259298948Sadrian{ 3260298948Sadrian struct bwn_softc *sc = mac->mac_sc; 3261298948Sadrian 3262298948Sadrian if (spu != 0) 3263298948Sadrian bwn_spu_workaround(mac, channel); 3264298948Sadrian 3265298948Sadrian BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel)); 3266298948Sadrian 3267298948Sadrian if (channel == 14) { 3268298948Sadrian if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN) 3269298948Sadrian bwn_hf_write(mac, 3270298948Sadrian bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF); 3271298948Sadrian else 3272298948Sadrian bwn_hf_write(mac, 3273298948Sadrian bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF); 3274298948Sadrian BWN_WRITE_2(mac, BWN_CHANNEL_EXT, 3275298948Sadrian BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11)); 3276298948Sadrian return; 3277298948Sadrian } 3278298948Sadrian 3279298948Sadrian BWN_WRITE_2(mac, BWN_CHANNEL_EXT, 3280298948Sadrian BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf); 3281298948Sadrian} 3282298948Sadrian 3283298948Sadrianstatic uint16_t 3284298948Sadrianbwn_phy_g_chan2freq(uint8_t channel) 3285298948Sadrian{ 3286298948Sadrian static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS; 3287298948Sadrian 3288298948Sadrian KASSERT(channel >= 1 && channel <= 14, 3289298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 3290298948Sadrian 3291298948Sadrian return (bwn_phy_g_rf_channels[channel - 1]); 3292298948Sadrian} 3293298948Sadrian 3294298948Sadrianstatic void 3295298948Sadrianbwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt, 3296298948Sadrian const struct bwn_rfatt *rfatt, uint8_t txctl) 3297298948Sadrian{ 3298298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 3299298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 3300298948Sadrian struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 3301298948Sadrian uint16_t bb, rf; 3302298948Sadrian uint16_t tx_bias, tx_magn; 3303298948Sadrian 3304298948Sadrian bb = bbatt->att; 3305298948Sadrian rf = rfatt->att; 3306298948Sadrian tx_bias = lo->tx_bias; 3307298948Sadrian tx_magn = lo->tx_magn; 3308298948Sadrian if (tx_bias == 0xff) 3309298948Sadrian tx_bias = 0; 3310298948Sadrian 3311298948Sadrian pg->pg_txctl = txctl; 3312298948Sadrian memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt)); 3313298948Sadrian pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0; 3314298948Sadrian memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt)); 3315298948Sadrian bwn_phy_g_set_bbatt(mac, bb); 3316298948Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf); 3317298948Sadrian if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) 3318298948Sadrian BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070)); 3319298948Sadrian else { 3320298948Sadrian BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f)); 3321298948Sadrian BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070)); 3322298948Sadrian } 3323298948Sadrian if (BWN_HAS_TXMAG(phy)) 3324298948Sadrian BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias); 3325298948Sadrian else 3326298948Sadrian BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f)); 3327298948Sadrian bwn_lo_g_adjust(mac); 3328298948Sadrian} 3329298948Sadrian 3330298948Sadrianstatic void 3331298948Sadrianbwn_phy_g_set_bbatt(struct bwn_mac *mac, 3332298948Sadrian uint16_t bbatt) 3333298948Sadrian{ 3334298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 3335298948Sadrian 3336298948Sadrian if (phy->analog == 0) { 3337298948Sadrian BWN_WRITE_2(mac, BWN_PHY0, 3338298948Sadrian (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt); 3339298948Sadrian return; 3340298948Sadrian } 3341298948Sadrian if (phy->analog > 1) { 3342298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2); 3343298948Sadrian return; 3344298948Sadrian } 3345298948Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3); 3346298948Sadrian} 3347298948Sadrian 3348298948Sadrianstatic uint16_t 3349298948Sadrianbwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd) 3350298948Sadrian{ 3351298948Sadrian struct bwn_phy *phy = &mac->mac_phy; 3352298948Sadrian struct bwn_phy_g *pg = &phy->phy_g; 3353298948Sadrian struct bwn_softc *sc = mac->mac_sc; 3354298948Sadrian int max_lb_gain; 3355298948Sadrian uint16_t extlna; 3356298948Sadrian uint16_t i; 3357298948Sadrian 3358298948Sadrian if (phy->gmode == 0) 3359298948Sadrian return (0); 3360298948Sadrian 3361298948Sadrian if (BWN_HAS_LOOPBACK(phy)) { 3362298948Sadrian max_lb_gain = pg->pg_max_lb_gain; 3363298948Sadrian max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26; 3364298948Sadrian if (max_lb_gain >= 0x46) { 3365298948Sadrian extlna = 0x3000; 3366298948Sadrian max_lb_gain -= 0x46; 3367298948Sadrian } else if (max_lb_gain >= 0x3a) { 3368298948Sadrian extlna = 0x1000; 3369298948Sadrian max_lb_gain -= 0x3a; 3370298948Sadrian } else if (max_lb_gain >= 0x2e) { 3371298948Sadrian extlna = 0x2000; 3372298948Sadrian max_lb_gain -= 0x2e; 3373298948Sadrian } else { 3374298948Sadrian extlna = 0; 3375298948Sadrian max_lb_gain -= 0x10; 3376298948Sadrian } 3377298948Sadrian 3378298948Sadrian for (i = 0; i < 16; i++) { 3379298948Sadrian max_lb_gain -= (i * 6); 3380298948Sadrian if (max_lb_gain < 6) 3381298948Sadrian break; 3382298948Sadrian } 3383298948Sadrian 3384298948Sadrian if ((phy->rev < 7) || 3385298948Sadrian !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) { 3386298948Sadrian if (reg == BWN_PHY_RFOVER) { 3387298948Sadrian return (0x1b3); 3388298948Sadrian } else if (reg == BWN_PHY_RFOVERVAL) { 3389298948Sadrian extlna |= (i << 8); 3390298948Sadrian switch (lpd) { 3391298948Sadrian case BWN_LPD(0, 1, 1): 3392298948Sadrian return (0x0f92); 3393298948Sadrian case BWN_LPD(0, 0, 1): 3394298948Sadrian case BWN_LPD(1, 0, 1): 3395298948Sadrian return (0x0092 | extlna); 3396298948Sadrian case BWN_LPD(1, 0, 0): 3397298948Sadrian return (0x0093 | extlna); 3398298948Sadrian } 3399298948Sadrian KASSERT(0 == 1, 3400298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 3401298948Sadrian } 3402298948Sadrian KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 3403298948Sadrian } else { 3404298948Sadrian if (reg == BWN_PHY_RFOVER) 3405298948Sadrian return (0x9b3); 3406298948Sadrian if (reg == BWN_PHY_RFOVERVAL) { 3407298948Sadrian if (extlna) 3408298948Sadrian extlna |= 0x8000; 3409298948Sadrian extlna |= (i << 8); 3410298948Sadrian switch (lpd) { 3411298948Sadrian case BWN_LPD(0, 1, 1): 3412298948Sadrian return (0x8f92); 3413298948Sadrian case BWN_LPD(0, 0, 1): 3414298948Sadrian return (0x8092 | extlna); 3415298948Sadrian case BWN_LPD(1, 0, 1): 3416298948Sadrian return (0x2092 | extlna); 3417298948Sadrian case BWN_LPD(1, 0, 0): 3418298948Sadrian return (0x2093 | extlna); 3419298948Sadrian } 3420298948Sadrian KASSERT(0 == 1, 3421298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 3422298948Sadrian } 3423298948Sadrian KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 3424298948Sadrian } 3425298948Sadrian return (0); 3426298948Sadrian } 3427298948Sadrian 3428298948Sadrian if ((phy->rev < 7) || 3429298948Sadrian !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) { 3430298948Sadrian if (reg == BWN_PHY_RFOVER) { 3431298948Sadrian return (0x1b3); 3432298948Sadrian } else if (reg == BWN_PHY_RFOVERVAL) { 3433298948Sadrian switch (lpd) { 3434298948Sadrian case BWN_LPD(0, 1, 1): 3435298948Sadrian return (0x0fb2); 3436298948Sadrian case BWN_LPD(0, 0, 1): 3437298948Sadrian return (0x00b2); 3438298948Sadrian case BWN_LPD(1, 0, 1): 3439298948Sadrian return (0x30b2); 3440298948Sadrian case BWN_LPD(1, 0, 0): 3441298948Sadrian return (0x30b3); 3442298948Sadrian } 3443298948Sadrian KASSERT(0 == 1, 3444298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 3445298948Sadrian } 3446298948Sadrian KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 3447298948Sadrian } else { 3448298948Sadrian if (reg == BWN_PHY_RFOVER) { 3449298948Sadrian return (0x9b3); 3450298948Sadrian } else if (reg == BWN_PHY_RFOVERVAL) { 3451298948Sadrian switch (lpd) { 3452298948Sadrian case BWN_LPD(0, 1, 1): 3453298948Sadrian return (0x8fb2); 3454298948Sadrian case BWN_LPD(0, 0, 1): 3455298948Sadrian return (0x80b2); 3456298948Sadrian case BWN_LPD(1, 0, 1): 3457298948Sadrian return (0x20b2); 3458298948Sadrian case BWN_LPD(1, 0, 0): 3459298948Sadrian return (0x20b3); 3460298948Sadrian } 3461298948Sadrian KASSERT(0 == 1, 3462298948Sadrian ("%s:%d: fail", __func__, __LINE__)); 3463298948Sadrian } 3464298948Sadrian KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 3465298948Sadrian } 3466298948Sadrian return (0); 3467298948Sadrian} 3468298948Sadrian 3469298948Sadrianstatic void 3470298948Sadrianbwn_spu_workaround(struct bwn_mac *mac, uint8_t channel) 3471298948Sadrian{ 3472298948Sadrian 3473298948Sadrian if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6) 3474298948Sadrian return; 3475298948Sadrian BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ? 3476298948Sadrian bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1)); 3477298948Sadrian DELAY(1000); 3478298948Sadrian BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel)); 3479298948Sadrian} 3480298948Sadrian 3481298948Sadrianstatic int 3482298948Sadrianbwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset) 3483298948Sadrian{ 3484298948Sadrian const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK); 3485298948Sadrian unsigned int a, b, c, d; 3486298948Sadrian unsigned int avg; 3487298948Sadrian uint32_t tmp; 3488298948Sadrian 3489298948Sadrian tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset); 3490298948Sadrian a = tmp & 0xff; 3491298948Sadrian b = (tmp >> 8) & 0xff; 3492298948Sadrian c = (tmp >> 16) & 0xff; 3493298948Sadrian d = (tmp >> 24) & 0xff; 3494298948Sadrian if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX || 3495298948Sadrian c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX) 3496298948Sadrian return (ENOENT); 3497298948Sadrian bwn_shm_write_4(mac, BWN_SHARED, shm_offset, 3498298948Sadrian BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) | 3499298948Sadrian (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24)); 3500298948Sadrian 3501298948Sadrian if (ofdm) { 3502298948Sadrian a = (a + 32) & 0x3f; 3503298948Sadrian b = (b + 32) & 0x3f; 3504298948Sadrian c = (c + 32) & 0x3f; 3505298948Sadrian d = (d + 32) & 0x3f; 3506298948Sadrian } 3507298948Sadrian 3508298948Sadrian avg = (a + b + c + d + 2) / 4; 3509298948Sadrian if (ofdm) { 3510298948Sadrian if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO) 3511298948Sadrian & BWN_HF_4DB_CCK_POWERBOOST) 3512298948Sadrian avg = (avg >= 13) ? (avg - 13) : 0; 3513298948Sadrian } 3514298948Sadrian return (avg); 3515298948Sadrian} 3516298948Sadrian 3517298948Sadrianstatic void 3518298948Sadrianbwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp) 3519298948Sadrian{ 3520298948Sadrian struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl; 3521298948Sadrian int rfatt = *rfattp; 3522298948Sadrian int bbatt = *bbattp; 3523298948Sadrian 3524298948Sadrian while (1) { 3525298948Sadrian if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4) 3526298948Sadrian break; 3527298948Sadrian if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4) 3528298948Sadrian break; 3529298948Sadrian if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1) 3530298948Sadrian break; 3531298948Sadrian if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1) 3532298948Sadrian break; 3533298948Sadrian if (bbatt > lo->bbatt.max) { 3534298948Sadrian bbatt -= 4; 3535298948Sadrian rfatt += 1; 3536298948Sadrian continue; 3537298948Sadrian } 3538298948Sadrian if (bbatt < lo->bbatt.min) { 3539298948Sadrian bbatt += 4; 3540298948Sadrian rfatt -= 1; 3541298948Sadrian continue; 3542298948Sadrian } 3543298948Sadrian if (rfatt > lo->rfatt.max) { 3544298948Sadrian rfatt -= 1; 3545298948Sadrian bbatt += 4; 3546298948Sadrian continue; 3547298948Sadrian } 3548298948Sadrian if (rfatt < lo->rfatt.min) { 3549298948Sadrian rfatt += 1; 3550298948Sadrian bbatt -= 4; 3551298948Sadrian continue; 3552298948Sadrian } 3553298948Sadrian break; 3554298948Sadrian } 3555298948Sadrian 3556298948Sadrian *rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max); 3557298948Sadrian *bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max); 3558298948Sadrian} 3559298948Sadrian 3560298948Sadrianstatic void 3561298948Sadrianbwn_phy_lock(struct bwn_mac *mac) 3562298948Sadrian{ 3563298948Sadrian struct bwn_softc *sc = mac->mac_sc; 3564298948Sadrian struct ieee80211com *ic = &sc->sc_ic; 3565298948Sadrian 3566298948Sadrian KASSERT(siba_get_revid(sc->sc_dev) >= 3, 3567298948Sadrian ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev))); 3568298948Sadrian 3569298948Sadrian if (ic->ic_opmode != IEEE80211_M_HOSTAP) 3570298948Sadrian bwn_psctl(mac, BWN_PS_AWAKE); 3571298948Sadrian} 3572298948Sadrian 3573298948Sadrianstatic void 3574298948Sadrianbwn_phy_unlock(struct bwn_mac *mac) 3575298948Sadrian{ 3576298948Sadrian struct bwn_softc *sc = mac->mac_sc; 3577298948Sadrian struct ieee80211com *ic = &sc->sc_ic; 3578298948Sadrian 3579298948Sadrian KASSERT(siba_get_revid(sc->sc_dev) >= 3, 3580298948Sadrian ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev))); 3581298948Sadrian 3582298948Sadrian if (ic->ic_opmode != IEEE80211_M_HOSTAP) 3583298948Sadrian bwn_psctl(mac, 0); 3584298948Sadrian} 3585298948Sadrian 3586298948Sadrianstatic void 3587298948Sadrianbwn_rf_lock(struct bwn_mac *mac) 3588298948Sadrian{ 3589298948Sadrian 3590298948Sadrian BWN_WRITE_4(mac, BWN_MACCTL, 3591298948Sadrian BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK); 3592298948Sadrian BWN_READ_4(mac, BWN_MACCTL); 3593298948Sadrian DELAY(10); 3594298948Sadrian} 3595298948Sadrian 3596298948Sadrianstatic void 3597298948Sadrianbwn_rf_unlock(struct bwn_mac *mac) 3598298948Sadrian{ 3599298948Sadrian 3600298948Sadrian BWN_READ_2(mac, BWN_PHYVER); 3601298948Sadrian BWN_WRITE_4(mac, BWN_MACCTL, 3602298948Sadrian BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK); 3603298948Sadrian} 3604