1191762Simp/* 2191762Simp * Copyright (c) 2007 The DragonFly Project. All rights reserved. 3191762Simp * 4191762Simp * This code is derived from software contributed to The DragonFly Project 5191762Simp * by Sepherosa Ziehau <sepherosa@gmail.com> 6191762Simp * 7191762Simp * Redistribution and use in source and binary forms, with or without 8191762Simp * modification, are permitted provided that the following conditions 9191762Simp * are met: 10191762Simp * 11191762Simp * 1. Redistributions of source code must retain the above copyright 12191762Simp * notice, this list of conditions and the following disclaimer. 13191762Simp * 2. Redistributions in binary form must reproduce the above copyright 14191762Simp * notice, this list of conditions and the following disclaimer in 15191762Simp * the documentation and/or other materials provided with the 16191762Simp * distribution. 17191762Simp * 3. Neither the name of The DragonFly Project nor the names of its 18191762Simp * contributors may be used to endorse or promote products derived 19191762Simp * from this software without specific, prior written permission. 20191762Simp * 21191762Simp * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22191762Simp * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23191762Simp * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24191762Simp * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25191762Simp * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26191762Simp * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27191762Simp * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28191762Simp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29191762Simp * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30191762Simp * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31191762Simp * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32191762Simp * SUCH DAMAGE. 33191762Simp * 34191762Simp * $DragonFly: src/sys/dev/netif/bwi/bwirf.c,v 1.9 2008/08/21 12:19:33 swildner Exp $ 35191762Simp */ 36191762Simp 37191762Simp#include <sys/cdefs.h> 38191762Simp__FBSDID("$FreeBSD$"); 39191762Simp 40191762Simp#include "opt_inet.h" 41191762Simp#include "opt_bwi.h" 42191762Simp 43191762Simp#include <sys/param.h> 44191762Simp#include <sys/endian.h> 45191762Simp#include <sys/kernel.h> 46191762Simp#include <sys/bus.h> 47191762Simp#include <sys/malloc.h> 48191762Simp#include <sys/proc.h> 49191762Simp#include <sys/rman.h> 50191762Simp#include <sys/socket.h> 51191762Simp#include <sys/sockio.h> 52191762Simp#include <sys/sysctl.h> 53191762Simp#include <sys/systm.h> 54191762Simp 55191762Simp#include <net/if.h> 56191762Simp#include <net/if_dl.h> 57191762Simp#include <net/if_media.h> 58191762Simp#include <net/if_types.h> 59191762Simp#include <net/if_arp.h> 60191762Simp#include <net/ethernet.h> 61191762Simp#include <net/if_llc.h> 62191762Simp 63191762Simp#include <net80211/ieee80211_var.h> 64191762Simp#include <net80211/ieee80211_radiotap.h> 65191762Simp#include <net80211/ieee80211_amrr.h> 66191762Simp 67191762Simp#include <machine/bus.h> 68191762Simp 69191762Simp#include <dev/bwi/bitops.h> 70191762Simp#include <dev/bwi/if_bwireg.h> 71191762Simp#include <dev/bwi/if_bwivar.h> 72191762Simp#include <dev/bwi/bwimac.h> 73191762Simp#include <dev/bwi/bwirf.h> 74191762Simp#include <dev/bwi/bwiphy.h> 75191762Simp 76191762Simp#define RF_LO_WRITE(mac, lo) bwi_rf_lo_write((mac), (lo)) 77191762Simp 78191762Simp#define BWI_RF_2GHZ_CHAN(chan) \ 79191762Simp (ieee80211_ieee2mhz((chan), IEEE80211_CHAN_2GHZ) - 2400) 80191762Simp 81191762Simp#define BWI_DEFAULT_IDLE_TSSI 52 82191762Simp 83191762Simpstruct rf_saveregs { 84191762Simp uint16_t phy_01; 85191762Simp uint16_t phy_03; 86191762Simp uint16_t phy_0a; 87191762Simp uint16_t phy_15; 88191762Simp uint16_t phy_2a; 89191762Simp uint16_t phy_30; 90191762Simp uint16_t phy_35; 91191762Simp uint16_t phy_60; 92191762Simp uint16_t phy_429; 93191762Simp uint16_t phy_802; 94191762Simp uint16_t phy_811; 95191762Simp uint16_t phy_812; 96191762Simp uint16_t phy_814; 97191762Simp uint16_t phy_815; 98191762Simp 99191762Simp uint16_t rf_43; 100191762Simp uint16_t rf_52; 101191762Simp uint16_t rf_7a; 102191762Simp}; 103191762Simp 104191762Simp#define SAVE_RF_REG(mac, regs, n) (regs)->rf_##n = RF_READ((mac), 0x##n) 105191762Simp#define RESTORE_RF_REG(mac, regs, n) RF_WRITE((mac), 0x##n, (regs)->rf_##n) 106191762Simp 107191762Simp#define SAVE_PHY_REG(mac, regs, n) (regs)->phy_##n = PHY_READ((mac), 0x##n) 108191762Simp#define RESTORE_PHY_REG(mac, regs, n) PHY_WRITE((mac), 0x##n, (regs)->phy_##n) 109191762Simp 110191762Simpstatic int bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]); 111191762Simpstatic void bwi_rf_work_around(struct bwi_mac *, u_int); 112191762Simpstatic int bwi_rf_gain_max_reached(struct bwi_mac *, int); 113191762Simpstatic uint16_t bwi_rf_calibval(struct bwi_mac *); 114191762Simpstatic uint16_t bwi_rf_get_tp_ctrl2(struct bwi_mac *); 115191762Simp 116191762Simpstatic void bwi_rf_lo_update_11b(struct bwi_mac *); 117191762Simpstatic uint16_t bwi_rf_lo_measure_11b(struct bwi_mac *); 118191762Simp 119191762Simpstatic void bwi_rf_lo_update_11g(struct bwi_mac *); 120191762Simpstatic uint32_t bwi_rf_lo_devi_measure(struct bwi_mac *, uint16_t); 121191762Simpstatic void bwi_rf_lo_measure_11g(struct bwi_mac *, 122191762Simp const struct bwi_rf_lo *, struct bwi_rf_lo *, uint8_t); 123191762Simpstatic uint8_t _bwi_rf_lo_update_11g(struct bwi_mac *, uint16_t); 124191762Simpstatic void bwi_rf_lo_write(struct bwi_mac *, const struct bwi_rf_lo *); 125191762Simp 126191762Simpstatic void bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *); 127191762Simpstatic void bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *); 128191762Simpstatic void bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *); 129191762Simpstatic void bwi_rf_set_nrssi_thr_11b(struct bwi_mac *); 130191762Simpstatic void bwi_rf_set_nrssi_thr_11g(struct bwi_mac *); 131191762Simp 132191762Simpstatic void bwi_rf_init_sw_nrssi_table(struct bwi_mac *); 133191762Simp 134191762Simpstatic int bwi_rf_calc_rssi_bcm2050(struct bwi_mac *, 135191762Simp const struct bwi_rxbuf_hdr *); 136191762Simpstatic int bwi_rf_calc_rssi_bcm2053(struct bwi_mac *, 137191762Simp const struct bwi_rxbuf_hdr *); 138191762Simpstatic int bwi_rf_calc_rssi_bcm2060(struct bwi_mac *, 139191762Simp const struct bwi_rxbuf_hdr *); 140191762Simpstatic int bwi_rf_calc_noise_bcm2050(struct bwi_mac *); 141191762Simpstatic int bwi_rf_calc_noise_bcm2053(struct bwi_mac *); 142191762Simpstatic int bwi_rf_calc_noise_bcm2060(struct bwi_mac *); 143191762Simp 144191762Simpstatic void bwi_rf_on_11a(struct bwi_mac *); 145191762Simpstatic void bwi_rf_on_11bg(struct bwi_mac *); 146191762Simp 147191762Simpstatic void bwi_rf_off_11a(struct bwi_mac *); 148191762Simpstatic void bwi_rf_off_11bg(struct bwi_mac *); 149191762Simpstatic void bwi_rf_off_11g_rev5(struct bwi_mac *); 150191762Simp 151191762Simpstatic const int8_t bwi_txpower_map_11b[BWI_TSSI_MAX] = 152191762Simp { BWI_TXPOWER_MAP_11B }; 153191762Simpstatic const int8_t bwi_txpower_map_11g[BWI_TSSI_MAX] = 154191762Simp { BWI_TXPOWER_MAP_11G }; 155191762Simp 156191762Simpstatic __inline int16_t 157191762Simpbwi_nrssi_11g(struct bwi_mac *mac) 158191762Simp{ 159191762Simp int16_t val; 160191762Simp 161191762Simp#define NRSSI_11G_MASK __BITS(13, 8) 162191762Simp 163191762Simp val = (int16_t)__SHIFTOUT(PHY_READ(mac, 0x47f), NRSSI_11G_MASK); 164191762Simp if (val >= 32) 165191762Simp val -= 64; 166191762Simp return val; 167191762Simp 168191762Simp#undef NRSSI_11G_MASK 169191762Simp} 170191762Simp 171191762Simpstatic __inline struct bwi_rf_lo * 172191762Simpbwi_get_rf_lo(struct bwi_mac *mac, uint16_t rf_atten, uint16_t bbp_atten) 173191762Simp{ 174191762Simp int n; 175191762Simp 176191762Simp n = rf_atten + (14 * (bbp_atten / 2)); 177191762Simp KASSERT(n < BWI_RFLO_MAX, ("n %d", n)); 178191762Simp 179191762Simp return &mac->mac_rf.rf_lo[n]; 180191762Simp} 181191762Simp 182191762Simpstatic __inline int 183191762Simpbwi_rf_lo_isused(struct bwi_mac *mac, const struct bwi_rf_lo *lo) 184191762Simp{ 185191762Simp struct bwi_rf *rf = &mac->mac_rf; 186191762Simp int idx; 187191762Simp 188191762Simp idx = lo - rf->rf_lo; 189191762Simp KASSERT(idx >= 0 && idx < BWI_RFLO_MAX, ("idx %d", idx)); 190191762Simp 191191762Simp return isset(rf->rf_lo_used, idx); 192191762Simp} 193191762Simp 194191762Simpvoid 195191762Simpbwi_rf_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data) 196191762Simp{ 197191762Simp struct bwi_softc *sc = mac->mac_sc; 198191762Simp 199191762Simp CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl); 200191762Simp CSR_WRITE_2(sc, BWI_RF_DATA_LO, data); 201191762Simp} 202191762Simp 203191762Simpuint16_t 204191762Simpbwi_rf_read(struct bwi_mac *mac, uint16_t ctrl) 205191762Simp{ 206191762Simp struct bwi_rf *rf = &mac->mac_rf; 207191762Simp struct bwi_softc *sc = mac->mac_sc; 208191762Simp 209191762Simp ctrl |= rf->rf_ctrl_rd; 210191762Simp if (rf->rf_ctrl_adj) { 211191762Simp /* XXX */ 212191762Simp if (ctrl < 0x70) 213191762Simp ctrl += 0x80; 214191762Simp else if (ctrl < 0x80) 215191762Simp ctrl += 0x70; 216191762Simp } 217191762Simp 218191762Simp CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl); 219191762Simp return CSR_READ_2(sc, BWI_RF_DATA_LO); 220191762Simp} 221191762Simp 222191762Simpint 223191762Simpbwi_rf_attach(struct bwi_mac *mac) 224191762Simp{ 225191762Simp struct bwi_softc *sc = mac->mac_sc; 226191762Simp struct bwi_phy *phy = &mac->mac_phy; 227191762Simp struct bwi_rf *rf = &mac->mac_rf; 228191762Simp uint16_t type, manu; 229191762Simp uint8_t rev; 230191762Simp 231191762Simp /* 232191762Simp * Get RF manufacture/type/revision 233191762Simp */ 234191762Simp if (sc->sc_bbp_id == BWI_BBPID_BCM4317) { 235191762Simp /* 236191762Simp * Fake a BCM2050 RF 237191762Simp */ 238191762Simp manu = BWI_RF_MANUFACT_BCM; 239191762Simp type = BWI_RF_T_BCM2050; 240191762Simp if (sc->sc_bbp_rev == 0) 241191762Simp rev = 3; 242191762Simp else if (sc->sc_bbp_rev == 1) 243191762Simp rev = 4; 244191762Simp else 245191762Simp rev = 5; 246191762Simp } else { 247191762Simp uint32_t val; 248191762Simp 249191762Simp CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO); 250191762Simp val = CSR_READ_2(sc, BWI_RF_DATA_HI); 251191762Simp val <<= 16; 252191762Simp 253191762Simp CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO); 254191762Simp val |= CSR_READ_2(sc, BWI_RF_DATA_LO); 255191762Simp 256191762Simp manu = __SHIFTOUT(val, BWI_RFINFO_MANUFACT_MASK); 257191762Simp type = __SHIFTOUT(val, BWI_RFINFO_TYPE_MASK); 258191762Simp rev = __SHIFTOUT(val, BWI_RFINFO_REV_MASK); 259191762Simp } 260191762Simp device_printf(sc->sc_dev, "RF: manu 0x%03x, type 0x%04x, rev %u\n", 261191762Simp manu, type, rev); 262191762Simp 263191762Simp /* 264191762Simp * Verify whether the RF is supported 265191762Simp */ 266191762Simp rf->rf_ctrl_rd = 0; 267191762Simp rf->rf_ctrl_adj = 0; 268191762Simp switch (phy->phy_mode) { 269191762Simp case IEEE80211_MODE_11A: 270191762Simp if (manu != BWI_RF_MANUFACT_BCM || 271191762Simp type != BWI_RF_T_BCM2060 || 272191762Simp rev != 1) { 273191762Simp device_printf(sc->sc_dev, "only BCM2060 rev 1 RF " 274191762Simp "is supported for 11A PHY\n"); 275191762Simp return ENXIO; 276191762Simp } 277191762Simp rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11A; 278191762Simp rf->rf_on = bwi_rf_on_11a; 279191762Simp rf->rf_off = bwi_rf_off_11a; 280191762Simp rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2060; 281191762Simp rf->rf_calc_noise = bwi_rf_calc_noise_bcm2060; 282191762Simp break; 283191762Simp case IEEE80211_MODE_11B: 284191762Simp if (type == BWI_RF_T_BCM2050) { 285191762Simp rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG; 286191762Simp rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050; 287191762Simp rf->rf_calc_noise = bwi_rf_calc_noise_bcm2050; 288191762Simp } else if (type == BWI_RF_T_BCM2053) { 289191762Simp rf->rf_ctrl_adj = 1; 290191762Simp rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2053; 291191762Simp rf->rf_calc_noise = bwi_rf_calc_noise_bcm2053; 292191762Simp } else { 293191762Simp device_printf(sc->sc_dev, "only BCM2050/BCM2053 RF " 294191762Simp "is supported for 11B PHY\n"); 295191762Simp return ENXIO; 296191762Simp } 297191762Simp rf->rf_on = bwi_rf_on_11bg; 298191762Simp rf->rf_off = bwi_rf_off_11bg; 299191762Simp rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11b; 300191762Simp rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11b; 301191762Simp if (phy->phy_rev == 6) 302191762Simp rf->rf_lo_update = bwi_rf_lo_update_11g; 303191762Simp else 304191762Simp rf->rf_lo_update = bwi_rf_lo_update_11b; 305191762Simp break; 306191762Simp case IEEE80211_MODE_11G: 307191762Simp if (type != BWI_RF_T_BCM2050) { 308191762Simp device_printf(sc->sc_dev, "only BCM2050 RF " 309191762Simp "is supported for 11G PHY\n"); 310191762Simp return ENXIO; 311191762Simp } 312191762Simp rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG; 313191762Simp rf->rf_on = bwi_rf_on_11bg; 314191762Simp if (mac->mac_rev >= 5) 315191762Simp rf->rf_off = bwi_rf_off_11g_rev5; 316191762Simp else 317191762Simp rf->rf_off = bwi_rf_off_11bg; 318191762Simp rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11g; 319191762Simp rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11g; 320191762Simp rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050; 321191762Simp rf->rf_calc_noise = bwi_rf_calc_noise_bcm2050; 322191762Simp rf->rf_lo_update = bwi_rf_lo_update_11g; 323191762Simp break; 324191762Simp default: 325191762Simp device_printf(sc->sc_dev, "unsupported PHY mode\n"); 326191762Simp return ENXIO; 327191762Simp } 328191762Simp 329191762Simp rf->rf_type = type; 330191762Simp rf->rf_rev = rev; 331191762Simp rf->rf_manu = manu; 332191762Simp rf->rf_curchan = IEEE80211_CHAN_ANY; 333191762Simp rf->rf_ant_mode = BWI_ANT_MODE_AUTO; 334191762Simp return 0; 335191762Simp} 336191762Simp 337191762Simpvoid 338191762Simpbwi_rf_set_chan(struct bwi_mac *mac, u_int chan, int work_around) 339191762Simp{ 340191762Simp struct bwi_softc *sc = mac->mac_sc; 341191762Simp 342191762Simp if (chan == IEEE80211_CHAN_ANY) 343191762Simp return; 344191762Simp 345191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_CHAN, chan); 346191762Simp 347191762Simp /* TODO: 11A */ 348191762Simp 349191762Simp if (work_around) 350191762Simp bwi_rf_work_around(mac, chan); 351191762Simp 352191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan)); 353191762Simp 354191762Simp if (chan == 14) { 355191762Simp if (sc->sc_locale == BWI_SPROM_LOCALE_JAPAN) 356191762Simp HFLAGS_CLRBITS(mac, BWI_HFLAG_NOT_JAPAN); 357191762Simp else 358191762Simp HFLAGS_SETBITS(mac, BWI_HFLAG_NOT_JAPAN); 359191762Simp CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, (1 << 11)); /* XXX */ 360191762Simp } else { 361191762Simp CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0x840); /* XXX */ 362191762Simp } 363191762Simp DELAY(8000); /* DELAY(2000); */ 364191762Simp 365191762Simp mac->mac_rf.rf_curchan = chan; 366191762Simp} 367191762Simp 368191762Simpvoid 369191762Simpbwi_rf_get_gains(struct bwi_mac *mac) 370191762Simp{ 371191762Simp#define SAVE_PHY_MAX 15 372191762Simp#define SAVE_RF_MAX 3 373191762Simp 374191762Simp static const uint16_t save_rf_regs[SAVE_RF_MAX] = 375191762Simp { 0x52, 0x43, 0x7a }; 376191762Simp static const uint16_t save_phy_regs[SAVE_PHY_MAX] = { 377191762Simp 0x0429, 0x0001, 0x0811, 0x0812, 378191762Simp 0x0814, 0x0815, 0x005a, 0x0059, 379191762Simp 0x0058, 0x000a, 0x0003, 0x080f, 380191762Simp 0x0810, 0x002b, 0x0015 381191762Simp }; 382191762Simp 383191762Simp struct bwi_softc *sc = mac->mac_sc; 384191762Simp struct bwi_phy *phy = &mac->mac_phy; 385191762Simp struct bwi_rf *rf = &mac->mac_rf; 386191762Simp uint16_t save_phy[SAVE_PHY_MAX]; 387191762Simp uint16_t save_rf[SAVE_RF_MAX]; 388191762Simp uint16_t trsw; 389191762Simp int i, j, loop1_max, loop1, loop2; 390191762Simp 391191762Simp /* 392191762Simp * Save PHY/RF registers for later restoration 393191762Simp */ 394191762Simp for (i = 0; i < SAVE_PHY_MAX; ++i) 395191762Simp save_phy[i] = PHY_READ(mac, save_phy_regs[i]); 396191762Simp PHY_READ(mac, 0x2d); /* dummy read */ 397191762Simp 398191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 399191762Simp save_rf[i] = RF_READ(mac, save_rf_regs[i]); 400191762Simp 401191762Simp PHY_CLRBITS(mac, 0x429, 0xc000); 402191762Simp PHY_SETBITS(mac, 0x1, 0x8000); 403191762Simp 404191762Simp PHY_SETBITS(mac, 0x811, 0x2); 405191762Simp PHY_CLRBITS(mac, 0x812, 0x2); 406191762Simp PHY_SETBITS(mac, 0x811, 0x1); 407191762Simp PHY_CLRBITS(mac, 0x812, 0x1); 408191762Simp 409191762Simp PHY_SETBITS(mac, 0x814, 0x1); 410191762Simp PHY_CLRBITS(mac, 0x815, 0x1); 411191762Simp PHY_SETBITS(mac, 0x814, 0x2); 412191762Simp PHY_CLRBITS(mac, 0x815, 0x2); 413191762Simp 414191762Simp PHY_SETBITS(mac, 0x811, 0xc); 415191762Simp PHY_SETBITS(mac, 0x812, 0xc); 416191762Simp PHY_SETBITS(mac, 0x811, 0x30); 417191762Simp PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10); 418191762Simp 419191762Simp PHY_WRITE(mac, 0x5a, 0x780); 420191762Simp PHY_WRITE(mac, 0x59, 0xc810); 421191762Simp PHY_WRITE(mac, 0x58, 0xd); 422191762Simp PHY_SETBITS(mac, 0xa, 0x2000); 423191762Simp 424191762Simp PHY_SETBITS(mac, 0x814, 0x4); 425191762Simp PHY_CLRBITS(mac, 0x815, 0x4); 426191762Simp 427191762Simp PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40); 428191762Simp 429191762Simp if (rf->rf_rev == 8) { 430191762Simp loop1_max = 15; 431191762Simp RF_WRITE(mac, 0x43, loop1_max); 432191762Simp } else { 433191762Simp loop1_max = 9; 434191762Simp RF_WRITE(mac, 0x52, 0x0); 435191762Simp RF_FILT_SETBITS(mac, 0x43, 0xfff0, loop1_max); 436191762Simp } 437191762Simp 438191762Simp bwi_phy_set_bbp_atten(mac, 11); 439191762Simp 440191762Simp if (phy->phy_rev >= 3) 441191762Simp PHY_WRITE(mac, 0x80f, 0xc020); 442191762Simp else 443191762Simp PHY_WRITE(mac, 0x80f, 0x8020); 444191762Simp PHY_WRITE(mac, 0x810, 0); 445191762Simp 446191762Simp PHY_FILT_SETBITS(mac, 0x2b, 0xffc0, 0x1); 447191762Simp PHY_FILT_SETBITS(mac, 0x2b, 0xc0ff, 0x800); 448191762Simp PHY_SETBITS(mac, 0x811, 0x100); 449191762Simp PHY_CLRBITS(mac, 0x812, 0x3000); 450191762Simp 451191762Simp if ((sc->sc_card_flags & BWI_CARD_F_EXT_LNA) && 452191762Simp phy->phy_rev >= 7) { 453191762Simp PHY_SETBITS(mac, 0x811, 0x800); 454191762Simp PHY_SETBITS(mac, 0x812, 0x8000); 455191762Simp } 456191762Simp RF_CLRBITS(mac, 0x7a, 0xff08); 457191762Simp 458191762Simp /* 459191762Simp * Find out 'loop1/loop2', which will be used to calculate 460191762Simp * max loopback gain later 461191762Simp */ 462191762Simp j = 0; 463191762Simp for (i = 0; i < loop1_max; ++i) { 464191762Simp for (j = 0; j < 16; ++j) { 465191762Simp RF_WRITE(mac, 0x43, i); 466191762Simp 467191762Simp if (bwi_rf_gain_max_reached(mac, j)) 468191762Simp goto loop1_exit; 469191762Simp } 470191762Simp } 471191762Simploop1_exit: 472191762Simp loop1 = i; 473191762Simp loop2 = j; 474191762Simp 475191762Simp /* 476191762Simp * Find out 'trsw', which will be used to calculate 477191762Simp * TRSW(TX/RX switch) RX gain later 478191762Simp */ 479191762Simp if (loop2 >= 8) { 480191762Simp PHY_SETBITS(mac, 0x812, 0x30); 481191762Simp trsw = 0x1b; 482191762Simp for (i = loop2 - 8; i < 16; ++i) { 483191762Simp trsw -= 3; 484191762Simp if (bwi_rf_gain_max_reached(mac, i)) 485191762Simp break; 486191762Simp } 487191762Simp } else { 488191762Simp trsw = 0x18; 489191762Simp } 490191762Simp 491191762Simp /* 492191762Simp * Restore saved PHY/RF registers 493191762Simp */ 494191762Simp /* First 4 saved PHY registers need special processing */ 495191762Simp for (i = 4; i < SAVE_PHY_MAX; ++i) 496191762Simp PHY_WRITE(mac, save_phy_regs[i], save_phy[i]); 497191762Simp 498191762Simp bwi_phy_set_bbp_atten(mac, mac->mac_tpctl.bbp_atten); 499191762Simp 500191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 501191762Simp RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 502191762Simp 503191762Simp PHY_WRITE(mac, save_phy_regs[2], save_phy[2] | 0x3); 504191762Simp DELAY(10); 505191762Simp PHY_WRITE(mac, save_phy_regs[2], save_phy[2]); 506191762Simp PHY_WRITE(mac, save_phy_regs[3], save_phy[3]); 507191762Simp PHY_WRITE(mac, save_phy_regs[0], save_phy[0]); 508191762Simp PHY_WRITE(mac, save_phy_regs[1], save_phy[1]); 509191762Simp 510191762Simp /* 511191762Simp * Calculate gains 512191762Simp */ 513191762Simp rf->rf_lo_gain = (loop2 * 6) - (loop1 * 4) - 11; 514191762Simp rf->rf_rx_gain = trsw * 2; 515191762Simp DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_INIT, 516191762Simp "lo gain: %u, rx gain: %u\n", 517191762Simp rf->rf_lo_gain, rf->rf_rx_gain); 518191762Simp 519191762Simp#undef SAVE_RF_MAX 520191762Simp#undef SAVE_PHY_MAX 521191762Simp} 522191762Simp 523191762Simpvoid 524191762Simpbwi_rf_init(struct bwi_mac *mac) 525191762Simp{ 526191762Simp struct bwi_rf *rf = &mac->mac_rf; 527191762Simp 528191762Simp if (rf->rf_type == BWI_RF_T_BCM2060) { 529191762Simp /* TODO: 11A */ 530191762Simp } else { 531191762Simp if (rf->rf_flags & BWI_RF_F_INITED) 532191762Simp RF_WRITE(mac, 0x78, rf->rf_calib); 533191762Simp else 534191762Simp bwi_rf_init_bcm2050(mac); 535191762Simp } 536191762Simp} 537191762Simp 538191762Simpstatic void 539191762Simpbwi_rf_off_11a(struct bwi_mac *mac) 540191762Simp{ 541191762Simp RF_WRITE(mac, 0x4, 0xff); 542191762Simp RF_WRITE(mac, 0x5, 0xfb); 543191762Simp 544191762Simp PHY_SETBITS(mac, 0x10, 0x8); 545191762Simp PHY_SETBITS(mac, 0x11, 0x8); 546191762Simp 547191762Simp PHY_WRITE(mac, 0x15, 0xaa00); 548191762Simp} 549191762Simp 550191762Simpstatic void 551191762Simpbwi_rf_off_11bg(struct bwi_mac *mac) 552191762Simp{ 553191762Simp PHY_WRITE(mac, 0x15, 0xaa00); 554191762Simp} 555191762Simp 556191762Simpstatic void 557191762Simpbwi_rf_off_11g_rev5(struct bwi_mac *mac) 558191762Simp{ 559191762Simp PHY_SETBITS(mac, 0x811, 0x8c); 560191762Simp PHY_CLRBITS(mac, 0x812, 0x8c); 561191762Simp} 562191762Simp 563191762Simpstatic void 564191762Simpbwi_rf_work_around(struct bwi_mac *mac, u_int chan) 565191762Simp{ 566191762Simp struct bwi_softc *sc = mac->mac_sc; 567191762Simp struct bwi_rf *rf = &mac->mac_rf; 568191762Simp 569191762Simp if (chan == IEEE80211_CHAN_ANY) { 570191762Simp device_printf(sc->sc_dev, "%s invalid channel!!\n", __func__); 571191762Simp return; 572191762Simp } 573191762Simp 574191762Simp if (rf->rf_type != BWI_RF_T_BCM2050 || rf->rf_rev >= 6) 575191762Simp return; 576191762Simp 577191762Simp if (chan <= 10) 578191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan + 4)); 579191762Simp else 580191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(1)); 581191762Simp DELAY(1000); 582191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan)); 583191762Simp} 584191762Simp 585191762Simpstatic __inline struct bwi_rf_lo * 586191762Simpbwi_rf_lo_find(struct bwi_mac *mac, const struct bwi_tpctl *tpctl) 587191762Simp{ 588191762Simp uint16_t rf_atten, bbp_atten; 589191762Simp int remap_rf_atten; 590191762Simp 591191762Simp remap_rf_atten = 1; 592191762Simp if (tpctl == NULL) { 593191762Simp bbp_atten = 2; 594191762Simp rf_atten = 3; 595191762Simp } else { 596191762Simp if (tpctl->tp_ctrl1 == 3) 597191762Simp remap_rf_atten = 0; 598191762Simp 599191762Simp bbp_atten = tpctl->bbp_atten; 600191762Simp rf_atten = tpctl->rf_atten; 601191762Simp 602191762Simp if (bbp_atten > 6) 603191762Simp bbp_atten = 6; 604191762Simp } 605191762Simp 606191762Simp if (remap_rf_atten) { 607191762Simp#define MAP_MAX 10 608191762Simp static const uint16_t map[MAP_MAX] = 609191762Simp { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; 610191762Simp 611191762Simp#if 0 612191762Simp KASSERT(rf_atten < MAP_MAX, ("rf_atten %d", rf_atten)); 613191762Simp rf_atten = map[rf_atten]; 614191762Simp#else 615191762Simp if (rf_atten >= MAP_MAX) { 616191762Simp rf_atten = 0; /* XXX */ 617191762Simp } else { 618191762Simp rf_atten = map[rf_atten]; 619191762Simp } 620191762Simp#endif 621191762Simp#undef MAP_MAX 622191762Simp } 623191762Simp 624191762Simp return bwi_get_rf_lo(mac, rf_atten, bbp_atten); 625191762Simp} 626191762Simp 627191762Simpvoid 628191762Simpbwi_rf_lo_adjust(struct bwi_mac *mac, const struct bwi_tpctl *tpctl) 629191762Simp{ 630191762Simp const struct bwi_rf_lo *lo; 631191762Simp 632191762Simp lo = bwi_rf_lo_find(mac, tpctl); 633191762Simp RF_LO_WRITE(mac, lo); 634191762Simp} 635191762Simp 636191762Simpstatic void 637191762Simpbwi_rf_lo_write(struct bwi_mac *mac, const struct bwi_rf_lo *lo) 638191762Simp{ 639191762Simp uint16_t val; 640191762Simp 641191762Simp val = (uint8_t)lo->ctrl_lo; 642191762Simp val |= ((uint8_t)lo->ctrl_hi) << 8; 643191762Simp 644191762Simp PHY_WRITE(mac, BWI_PHYR_RF_LO, val); 645191762Simp} 646191762Simp 647191762Simpstatic int 648191762Simpbwi_rf_gain_max_reached(struct bwi_mac *mac, int idx) 649191762Simp{ 650191762Simp PHY_FILT_SETBITS(mac, 0x812, 0xf0ff, idx << 8); 651191762Simp PHY_FILT_SETBITS(mac, 0x15, 0xfff, 0xa000); 652191762Simp PHY_SETBITS(mac, 0x15, 0xf000); 653191762Simp 654191762Simp DELAY(20); 655191762Simp 656191762Simp return (PHY_READ(mac, 0x2d) >= 0xdfc); 657191762Simp} 658191762Simp 659191762Simp/* XXX use bitmap array */ 660191762Simpstatic __inline uint16_t 661191762Simpbitswap4(uint16_t val) 662191762Simp{ 663191762Simp uint16_t ret; 664191762Simp 665191762Simp ret = (val & 0x8) >> 3; 666191762Simp ret |= (val & 0x4) >> 1; 667191762Simp ret |= (val & 0x2) << 1; 668191762Simp ret |= (val & 0x1) << 3; 669191762Simp return ret; 670191762Simp} 671191762Simp 672191762Simpstatic __inline uint16_t 673191762Simpbwi_phy812_value(struct bwi_mac *mac, uint16_t lpd) 674191762Simp{ 675191762Simp struct bwi_softc *sc = mac->mac_sc; 676191762Simp struct bwi_phy *phy = &mac->mac_phy; 677191762Simp struct bwi_rf *rf = &mac->mac_rf; 678191762Simp uint16_t lo_gain, ext_lna, loop; 679191762Simp 680191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0) 681191762Simp return 0; 682191762Simp 683191762Simp lo_gain = rf->rf_lo_gain; 684191762Simp if (rf->rf_rev == 8) 685191762Simp lo_gain += 0x3e; 686191762Simp else 687191762Simp lo_gain += 0x26; 688191762Simp 689191762Simp if (lo_gain >= 0x46) { 690191762Simp lo_gain -= 0x46; 691191762Simp ext_lna = 0x3000; 692191762Simp } else if (lo_gain >= 0x3a) { 693191762Simp lo_gain -= 0x3a; 694191762Simp ext_lna = 0x1000; 695191762Simp } else if (lo_gain >= 0x2e) { 696191762Simp lo_gain -= 0x2e; 697191762Simp ext_lna = 0x2000; 698191762Simp } else { 699191762Simp lo_gain -= 0x10; 700191762Simp ext_lna = 0; 701191762Simp } 702191762Simp 703191762Simp for (loop = 0; loop < 16; ++loop) { 704191762Simp lo_gain -= (6 * loop); 705191762Simp if (lo_gain < 6) 706191762Simp break; 707191762Simp } 708191762Simp 709191762Simp if (phy->phy_rev >= 7 && (sc->sc_card_flags & BWI_CARD_F_EXT_LNA)) { 710191762Simp if (ext_lna) 711191762Simp ext_lna |= 0x8000; 712191762Simp ext_lna |= (loop << 8); 713191762Simp switch (lpd) { 714191762Simp case 0x011: 715191762Simp return 0x8f92; 716191762Simp case 0x001: 717191762Simp return (0x8092 | ext_lna); 718191762Simp case 0x101: 719191762Simp return (0x2092 | ext_lna); 720191762Simp case 0x100: 721191762Simp return (0x2093 | ext_lna); 722191762Simp default: 723191762Simp panic("unsupported lpd\n"); 724191762Simp } 725191762Simp } else { 726191762Simp ext_lna |= (loop << 8); 727191762Simp switch (lpd) { 728191762Simp case 0x011: 729191762Simp return 0xf92; 730191762Simp case 0x001: 731191762Simp case 0x101: 732191762Simp return (0x92 | ext_lna); 733191762Simp case 0x100: 734191762Simp return (0x93 | ext_lna); 735191762Simp default: 736191762Simp panic("unsupported lpd\n"); 737191762Simp } 738191762Simp } 739191762Simp 740191762Simp panic("never reached\n"); 741191762Simp return 0; 742191762Simp} 743191762Simp 744191762Simpvoid 745191762Simpbwi_rf_init_bcm2050(struct bwi_mac *mac) 746191762Simp{ 747191762Simp#define SAVE_RF_MAX 3 748191762Simp#define SAVE_PHY_COMM_MAX 4 749191762Simp#define SAVE_PHY_11G_MAX 6 750191762Simp 751191762Simp static const uint16_t save_rf_regs[SAVE_RF_MAX] = 752191762Simp { 0x0043, 0x0051, 0x0052 }; 753191762Simp static const uint16_t save_phy_regs_comm[SAVE_PHY_COMM_MAX] = 754191762Simp { 0x0015, 0x005a, 0x0059, 0x0058 }; 755191762Simp static const uint16_t save_phy_regs_11g[SAVE_PHY_11G_MAX] = 756191762Simp { 0x0811, 0x0812, 0x0814, 0x0815, 0x0429, 0x0802 }; 757191762Simp 758191762Simp uint16_t save_rf[SAVE_RF_MAX]; 759191762Simp uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 760191762Simp uint16_t save_phy_11g[SAVE_PHY_11G_MAX]; 761191762Simp uint16_t phyr_35, phyr_30 = 0, rfr_78, phyr_80f = 0, phyr_810 = 0; 762191762Simp uint16_t bphy_ctrl = 0, bbp_atten, rf_chan_ex; 763191762Simp uint16_t phy812_val; 764191762Simp uint16_t calib; 765191762Simp uint32_t test_lim, test; 766191762Simp struct bwi_softc *sc = mac->mac_sc; 767191762Simp struct bwi_phy *phy = &mac->mac_phy; 768191762Simp struct bwi_rf *rf = &mac->mac_rf; 769191762Simp int i; 770191762Simp 771191762Simp /* 772191762Simp * Save registers for later restoring 773191762Simp */ 774191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 775191762Simp save_rf[i] = RF_READ(mac, save_rf_regs[i]); 776191762Simp for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 777191762Simp save_phy_comm[i] = PHY_READ(mac, save_phy_regs_comm[i]); 778191762Simp 779191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) { 780191762Simp phyr_30 = PHY_READ(mac, 0x30); 781191762Simp bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL); 782191762Simp 783191762Simp PHY_WRITE(mac, 0x30, 0xff); 784191762Simp CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x3f3f); 785191762Simp } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 786191762Simp for (i = 0; i < SAVE_PHY_11G_MAX; ++i) { 787191762Simp save_phy_11g[i] = 788191762Simp PHY_READ(mac, save_phy_regs_11g[i]); 789191762Simp } 790191762Simp 791191762Simp PHY_SETBITS(mac, 0x814, 0x3); 792191762Simp PHY_CLRBITS(mac, 0x815, 0x3); 793191762Simp PHY_CLRBITS(mac, 0x429, 0x8000); 794191762Simp PHY_CLRBITS(mac, 0x802, 0x3); 795191762Simp 796191762Simp phyr_80f = PHY_READ(mac, 0x80f); 797191762Simp phyr_810 = PHY_READ(mac, 0x810); 798191762Simp 799191762Simp if (phy->phy_rev >= 3) 800191762Simp PHY_WRITE(mac, 0x80f, 0xc020); 801191762Simp else 802191762Simp PHY_WRITE(mac, 0x80f, 0x8020); 803191762Simp PHY_WRITE(mac, 0x810, 0); 804191762Simp 805191762Simp phy812_val = bwi_phy812_value(mac, 0x011); 806191762Simp PHY_WRITE(mac, 0x812, phy812_val); 807191762Simp if (phy->phy_rev < 7 || 808191762Simp (sc->sc_card_flags & BWI_CARD_F_EXT_LNA) == 0) 809191762Simp PHY_WRITE(mac, 0x811, 0x1b3); 810191762Simp else 811191762Simp PHY_WRITE(mac, 0x811, 0x9b3); 812191762Simp } 813191762Simp CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000); 814191762Simp 815191762Simp phyr_35 = PHY_READ(mac, 0x35); 816191762Simp PHY_CLRBITS(mac, 0x35, 0x80); 817191762Simp 818191762Simp bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN); 819191762Simp rf_chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); 820191762Simp 821191762Simp if (phy->phy_version == 0) { 822191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122); 823191762Simp } else { 824191762Simp if (phy->phy_version >= 2) 825191762Simp PHY_FILT_SETBITS(mac, 0x3, 0xffbf, 0x40); 826191762Simp CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000); 827191762Simp } 828191762Simp 829191762Simp calib = bwi_rf_calibval(mac); 830191762Simp 831191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) 832191762Simp RF_WRITE(mac, 0x78, 0x26); 833191762Simp 834191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 835191762Simp phy812_val = bwi_phy812_value(mac, 0x011); 836191762Simp PHY_WRITE(mac, 0x812, phy812_val); 837191762Simp } 838191762Simp 839191762Simp PHY_WRITE(mac, 0x15, 0xbfaf); 840191762Simp PHY_WRITE(mac, 0x2b, 0x1403); 841191762Simp 842191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 843191762Simp phy812_val = bwi_phy812_value(mac, 0x001); 844191762Simp PHY_WRITE(mac, 0x812, phy812_val); 845191762Simp } 846191762Simp 847191762Simp PHY_WRITE(mac, 0x15, 0xbfa0); 848191762Simp 849191762Simp RF_SETBITS(mac, 0x51, 0x4); 850191762Simp if (rf->rf_rev == 8) { 851191762Simp RF_WRITE(mac, 0x43, 0x1f); 852191762Simp } else { 853191762Simp RF_WRITE(mac, 0x52, 0); 854191762Simp RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9); 855191762Simp } 856191762Simp 857191762Simp test_lim = 0; 858191762Simp PHY_WRITE(mac, 0x58, 0); 859191762Simp for (i = 0; i < 16; ++i) { 860191762Simp PHY_WRITE(mac, 0x5a, 0x480); 861191762Simp PHY_WRITE(mac, 0x59, 0xc810); 862191762Simp 863191762Simp PHY_WRITE(mac, 0x58, 0xd); 864191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 865191762Simp phy812_val = bwi_phy812_value(mac, 0x101); 866191762Simp PHY_WRITE(mac, 0x812, phy812_val); 867191762Simp } 868191762Simp PHY_WRITE(mac, 0x15, 0xafb0); 869191762Simp DELAY(10); 870191762Simp 871191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 872191762Simp phy812_val = bwi_phy812_value(mac, 0x101); 873191762Simp PHY_WRITE(mac, 0x812, phy812_val); 874191762Simp } 875191762Simp PHY_WRITE(mac, 0x15, 0xefb0); 876191762Simp DELAY(10); 877191762Simp 878191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 879191762Simp phy812_val = bwi_phy812_value(mac, 0x100); 880191762Simp PHY_WRITE(mac, 0x812, phy812_val); 881191762Simp } 882191762Simp PHY_WRITE(mac, 0x15, 0xfff0); 883191762Simp DELAY(20); 884191762Simp 885191762Simp test_lim += PHY_READ(mac, 0x2d); 886191762Simp 887191762Simp PHY_WRITE(mac, 0x58, 0); 888191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 889191762Simp phy812_val = bwi_phy812_value(mac, 0x101); 890191762Simp PHY_WRITE(mac, 0x812, phy812_val); 891191762Simp } 892191762Simp PHY_WRITE(mac, 0x15, 0xafb0); 893191762Simp } 894191762Simp ++test_lim; 895191762Simp test_lim >>= 9; 896191762Simp 897191762Simp DELAY(10); 898191762Simp 899191762Simp test = 0; 900191762Simp PHY_WRITE(mac, 0x58, 0); 901191762Simp for (i = 0; i < 16; ++i) { 902191762Simp int j; 903191762Simp 904191762Simp rfr_78 = (bitswap4(i) << 1) | 0x20; 905191762Simp RF_WRITE(mac, 0x78, rfr_78); 906191762Simp DELAY(10); 907191762Simp 908191762Simp /* NB: This block is slight different than the above one */ 909191762Simp for (j = 0; j < 16; ++j) { 910191762Simp PHY_WRITE(mac, 0x5a, 0xd80); 911191762Simp PHY_WRITE(mac, 0x59, 0xc810); 912191762Simp 913191762Simp PHY_WRITE(mac, 0x58, 0xd); 914191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || 915191762Simp phy->phy_rev >= 2) { 916191762Simp phy812_val = bwi_phy812_value(mac, 0x101); 917191762Simp PHY_WRITE(mac, 0x812, phy812_val); 918191762Simp } 919191762Simp PHY_WRITE(mac, 0x15, 0xafb0); 920191762Simp DELAY(10); 921191762Simp 922191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || 923191762Simp phy->phy_rev >= 2) { 924191762Simp phy812_val = bwi_phy812_value(mac, 0x101); 925191762Simp PHY_WRITE(mac, 0x812, phy812_val); 926191762Simp } 927191762Simp PHY_WRITE(mac, 0x15, 0xefb0); 928191762Simp DELAY(10); 929191762Simp 930191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || 931191762Simp phy->phy_rev >= 2) { 932191762Simp phy812_val = bwi_phy812_value(mac, 0x100); 933191762Simp PHY_WRITE(mac, 0x812, phy812_val); 934191762Simp } 935191762Simp PHY_WRITE(mac, 0x15, 0xfff0); 936191762Simp DELAY(10); 937191762Simp 938191762Simp test += PHY_READ(mac, 0x2d); 939191762Simp 940191762Simp PHY_WRITE(mac, 0x58, 0); 941191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || 942191762Simp phy->phy_rev >= 2) { 943191762Simp phy812_val = bwi_phy812_value(mac, 0x101); 944191762Simp PHY_WRITE(mac, 0x812, phy812_val); 945191762Simp } 946191762Simp PHY_WRITE(mac, 0x15, 0xafb0); 947191762Simp } 948191762Simp 949191762Simp ++test; 950191762Simp test >>= 8; 951191762Simp 952191762Simp if (test > test_lim) 953191762Simp break; 954191762Simp } 955191762Simp if (i > 15) 956191762Simp rf->rf_calib = rfr_78; 957191762Simp else 958191762Simp rf->rf_calib = calib; 959191762Simp if (rf->rf_calib != 0xffff) { 960191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, 961191762Simp "RF calibration value: 0x%04x\n", rf->rf_calib); 962191762Simp rf->rf_flags |= BWI_RF_F_INITED; 963191762Simp } 964191762Simp 965191762Simp /* 966191762Simp * Restore trashes registers 967191762Simp */ 968191762Simp PHY_WRITE(mac, save_phy_regs_comm[0], save_phy_comm[0]); 969191762Simp 970191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) { 971191762Simp int pos = (i + 1) % SAVE_RF_MAX; 972191762Simp 973191762Simp RF_WRITE(mac, save_rf_regs[pos], save_rf[pos]); 974191762Simp } 975191762Simp for (i = 1; i < SAVE_PHY_COMM_MAX; ++i) 976191762Simp PHY_WRITE(mac, save_phy_regs_comm[i], save_phy_comm[i]); 977191762Simp 978191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten); 979191762Simp if (phy->phy_version != 0) 980191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, rf_chan_ex); 981191762Simp 982191762Simp PHY_WRITE(mac, 0x35, phyr_35); 983191762Simp bwi_rf_work_around(mac, rf->rf_curchan); 984191762Simp 985191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) { 986191762Simp PHY_WRITE(mac, 0x30, phyr_30); 987191762Simp CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl); 988191762Simp } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 989191762Simp /* XXX Spec only says when PHY is linked (gmode) */ 990191762Simp CSR_CLRBITS_2(sc, BWI_RF_ANTDIV, 0x8000); 991191762Simp 992191762Simp for (i = 0; i < SAVE_PHY_11G_MAX; ++i) { 993191762Simp PHY_WRITE(mac, save_phy_regs_11g[i], 994191762Simp save_phy_11g[i]); 995191762Simp } 996191762Simp 997191762Simp PHY_WRITE(mac, 0x80f, phyr_80f); 998191762Simp PHY_WRITE(mac, 0x810, phyr_810); 999191762Simp } 1000191762Simp 1001191762Simp#undef SAVE_PHY_11G_MAX 1002191762Simp#undef SAVE_PHY_COMM_MAX 1003191762Simp#undef SAVE_RF_MAX 1004191762Simp} 1005191762Simp 1006191762Simpstatic uint16_t 1007191762Simpbwi_rf_calibval(struct bwi_mac *mac) 1008191762Simp{ 1009191762Simp /* http://bcm-specs.sipsolutions.net/RCCTable */ 1010191762Simp static const uint16_t rf_calibvals[] = { 1011191762Simp 0x2, 0x3, 0x1, 0xf, 0x6, 0x7, 0x5, 0xf, 1012191762Simp 0xa, 0xb, 0x9, 0xf, 0xe, 0xf, 0xd, 0xf 1013191762Simp }; 1014191762Simp uint16_t val, calib; 1015191762Simp int idx; 1016191762Simp 1017191762Simp val = RF_READ(mac, BWI_RFR_BBP_ATTEN); 1018191762Simp idx = __SHIFTOUT(val, BWI_RFR_BBP_ATTEN_CALIB_IDX); 1019191762Simp KASSERT(idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0])), 1020191762Simp ("idx %d", idx)); 1021191762Simp 1022191762Simp calib = rf_calibvals[idx] << 1; 1023191762Simp if (val & BWI_RFR_BBP_ATTEN_CALIB_BIT) 1024191762Simp calib |= 0x1; 1025191762Simp calib |= 0x20; 1026191762Simp 1027191762Simp return calib; 1028191762Simp} 1029191762Simp 1030191762Simpstatic __inline int32_t 1031191762Simp_bwi_adjust_devide(int32_t num, int32_t den) 1032191762Simp{ 1033191762Simp if (num < 0) 1034191762Simp return (num / den); 1035191762Simp else 1036191762Simp return (num + den / 2) / den; 1037191762Simp} 1038191762Simp 1039191762Simp/* 1040191762Simp * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table 1041191762Simp * "calculating table entries" 1042191762Simp */ 1043191762Simpstatic int 1044191762Simpbwi_rf_calc_txpower(int8_t *txpwr, uint8_t idx, const int16_t pa_params[]) 1045191762Simp{ 1046191762Simp int32_t m1, m2, f, dbm; 1047191762Simp int i; 1048191762Simp 1049191762Simp m1 = _bwi_adjust_devide(16 * pa_params[0] + idx * pa_params[1], 32); 1050191762Simp m2 = imax(_bwi_adjust_devide(32768 + idx * pa_params[2], 256), 1); 1051191762Simp 1052191762Simp#define ITER_MAX 16 1053191762Simp 1054191762Simp f = 256; 1055191762Simp for (i = 0; i < ITER_MAX; ++i) { 1056191762Simp int32_t q, d; 1057191762Simp 1058191762Simp q = _bwi_adjust_devide( 1059191762Simp f * 4096 - _bwi_adjust_devide(m2 * f, 16) * f, 2048); 1060191762Simp d = abs(q - f); 1061191762Simp f = q; 1062191762Simp 1063191762Simp if (d < 2) 1064191762Simp break; 1065191762Simp } 1066191762Simp if (i == ITER_MAX) 1067191762Simp return EINVAL; 1068191762Simp 1069191762Simp#undef ITER_MAX 1070191762Simp 1071191762Simp dbm = _bwi_adjust_devide(m1 * f, 8192); 1072191762Simp if (dbm < -127) 1073191762Simp dbm = -127; 1074191762Simp else if (dbm > 128) 1075191762Simp dbm = 128; 1076191762Simp 1077191762Simp *txpwr = dbm; 1078191762Simp return 0; 1079191762Simp} 1080191762Simp 1081191762Simpint 1082191762Simpbwi_rf_map_txpower(struct bwi_mac *mac) 1083191762Simp{ 1084191762Simp struct bwi_softc *sc = mac->mac_sc; 1085191762Simp struct bwi_rf *rf = &mac->mac_rf; 1086191762Simp struct bwi_phy *phy = &mac->mac_phy; 1087191762Simp uint16_t sprom_ofs, val, mask; 1088191762Simp int16_t pa_params[3]; 1089191762Simp int error = 0, i, ant_gain, reg_txpower_max; 1090191762Simp 1091191762Simp /* 1092191762Simp * Find out max TX power 1093191762Simp */ 1094191762Simp val = bwi_read_sprom(sc, BWI_SPROM_MAX_TXPWR); 1095191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) { 1096191762Simp rf->rf_txpower_max = __SHIFTOUT(val, 1097191762Simp BWI_SPROM_MAX_TXPWR_MASK_11A); 1098191762Simp } else { 1099191762Simp rf->rf_txpower_max = __SHIFTOUT(val, 1100191762Simp BWI_SPROM_MAX_TXPWR_MASK_11BG); 1101191762Simp 1102191762Simp if ((sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) && 1103191762Simp phy->phy_mode == IEEE80211_MODE_11G) 1104191762Simp rf->rf_txpower_max -= 3; 1105191762Simp } 1106191762Simp if (rf->rf_txpower_max <= 0) { 1107191762Simp device_printf(sc->sc_dev, "invalid max txpower in sprom\n"); 1108191762Simp rf->rf_txpower_max = 74; 1109191762Simp } 1110191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1111191762Simp "max txpower from sprom: %d dBm\n", rf->rf_txpower_max); 1112191762Simp 1113191762Simp /* 1114191762Simp * Find out region/domain max TX power, which is adjusted 1115191762Simp * by antenna gain and 1.5 dBm fluctuation as mentioned 1116191762Simp * in v3 spec. 1117191762Simp */ 1118191762Simp val = bwi_read_sprom(sc, BWI_SPROM_ANT_GAIN); 1119191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) 1120191762Simp ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11A); 1121191762Simp else 1122191762Simp ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11BG); 1123191762Simp if (ant_gain == 0xff) { 1124191762Simp device_printf(sc->sc_dev, "invalid antenna gain in sprom\n"); 1125191762Simp ant_gain = 2; 1126191762Simp } 1127191762Simp ant_gain *= 4; 1128191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1129191762Simp "ant gain %d dBm\n", ant_gain); 1130191762Simp 1131191762Simp reg_txpower_max = 90 - ant_gain - 6; /* XXX magic number */ 1132191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1133191762Simp "region/domain max txpower %d dBm\n", reg_txpower_max); 1134191762Simp 1135191762Simp /* 1136191762Simp * Force max TX power within region/domain TX power limit 1137191762Simp */ 1138191762Simp if (rf->rf_txpower_max > reg_txpower_max) 1139191762Simp rf->rf_txpower_max = reg_txpower_max; 1140191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1141191762Simp "max txpower %d dBm\n", rf->rf_txpower_max); 1142191762Simp 1143191762Simp /* 1144191762Simp * Create TSSI to TX power mapping 1145191762Simp */ 1146191762Simp 1147191762Simp if (sc->sc_bbp_id == BWI_BBPID_BCM4301 && 1148191762Simp rf->rf_type != BWI_RF_T_BCM2050) { 1149191762Simp rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI; 1150191762Simp bcopy(bwi_txpower_map_11b, rf->rf_txpower_map0, 1151191762Simp sizeof(rf->rf_txpower_map0)); 1152191762Simp goto back; 1153191762Simp } 1154191762Simp 1155191762Simp#define IS_VALID_PA_PARAM(p) ((p) != 0 && (p) != -1) 1156191762Simp#define N(arr) (int)(sizeof(arr) / sizeof(arr[0])) 1157191762Simp 1158191762Simp /* 1159191762Simp * Extract PA parameters 1160191762Simp */ 1161191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) 1162191762Simp sprom_ofs = BWI_SPROM_PA_PARAM_11A; 1163191762Simp else 1164191762Simp sprom_ofs = BWI_SPROM_PA_PARAM_11BG; 1165191762Simp for (i = 0; i < N(pa_params); ++i) 1166191762Simp pa_params[i] = (int16_t)bwi_read_sprom(sc, sprom_ofs + (i * 2)); 1167191762Simp 1168191762Simp for (i = 0; i < N(pa_params); ++i) { 1169191762Simp /* 1170191762Simp * If one of the PA parameters from SPROM is not valid, 1171191762Simp * fall back to the default values, if there are any. 1172191762Simp */ 1173191762Simp if (!IS_VALID_PA_PARAM(pa_params[i])) { 1174191762Simp const int8_t *txpower_map; 1175191762Simp 1176191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) { 1177191762Simp device_printf(sc->sc_dev, 1178191762Simp "no tssi2dbm table for 11a PHY\n"); 1179191762Simp return ENXIO; 1180191762Simp } 1181191762Simp 1182191762Simp if (phy->phy_mode == IEEE80211_MODE_11G) { 1183191762Simp DPRINTF(sc, 1184191762Simp BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1185191762Simp "%s\n", "use default 11g TSSI map"); 1186191762Simp txpower_map = bwi_txpower_map_11g; 1187191762Simp } else { 1188191762Simp DPRINTF(sc, 1189191762Simp BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1190191762Simp "%s\n", "use default 11b TSSI map"); 1191191762Simp txpower_map = bwi_txpower_map_11b; 1192191762Simp } 1193191762Simp 1194191762Simp rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI; 1195191762Simp bcopy(txpower_map, rf->rf_txpower_map0, 1196191762Simp sizeof(rf->rf_txpower_map0)); 1197191762Simp goto back; 1198191762Simp } 1199191762Simp } 1200191762Simp 1201191762Simp#undef N 1202191762Simp 1203191762Simp /* 1204191762Simp * All of the PA parameters from SPROM are valid. 1205191762Simp */ 1206191762Simp 1207191762Simp /* 1208191762Simp * Extract idle TSSI from SPROM. 1209191762Simp */ 1210191762Simp val = bwi_read_sprom(sc, BWI_SPROM_IDLE_TSSI); 1211191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1212191762Simp "sprom idle tssi: 0x%04x\n", val); 1213191762Simp 1214191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) 1215191762Simp mask = BWI_SPROM_IDLE_TSSI_MASK_11A; 1216191762Simp else 1217191762Simp mask = BWI_SPROM_IDLE_TSSI_MASK_11BG; 1218191762Simp 1219191762Simp rf->rf_idle_tssi0 = (int)__SHIFTOUT(val, mask); 1220191762Simp if (!IS_VALID_PA_PARAM(rf->rf_idle_tssi0)) 1221191762Simp rf->rf_idle_tssi0 = 62; 1222191762Simp 1223191762Simp#undef IS_VALID_PA_PARAM 1224191762Simp 1225191762Simp /* 1226191762Simp * Calculate TX power map, which is indexed by TSSI 1227191762Simp */ 1228191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, 1229191762Simp "%s\n", "TSSI-TX power map:"); 1230191762Simp for (i = 0; i < BWI_TSSI_MAX; ++i) { 1231191762Simp error = bwi_rf_calc_txpower(&rf->rf_txpower_map0[i], i, 1232191762Simp pa_params); 1233191762Simp if (error) { 1234191762Simp device_printf(sc->sc_dev, 1235191762Simp "bwi_rf_calc_txpower failed\n"); 1236191762Simp break; 1237191762Simp } 1238191762Simp 1239191762Simp#ifdef BWI_DEBUG 1240191762Simp if (i != 0 && i % 8 == 0) { 1241191762Simp _DPRINTF(sc, 1242191762Simp BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, 1243191762Simp "%s\n", ""); 1244191762Simp } 1245191762Simp#endif 1246191762Simp _DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, 1247191762Simp "%d ", rf->rf_txpower_map0[i]); 1248191762Simp } 1249191762Simp _DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, 1250191762Simp "%s\n", ""); 1251191762Simpback: 1252191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1253191762Simp "idle tssi0: %d\n", rf->rf_idle_tssi0); 1254191762Simp return error; 1255191762Simp} 1256191762Simp 1257191762Simpstatic void 1258191762Simpbwi_rf_lo_update_11g(struct bwi_mac *mac) 1259191762Simp{ 1260191762Simp struct bwi_softc *sc = mac->mac_sc; 1261191762Simp struct ifnet *ifp = sc->sc_ifp; 1262191762Simp struct bwi_rf *rf = &mac->mac_rf; 1263191762Simp struct bwi_phy *phy = &mac->mac_phy; 1264191762Simp struct bwi_tpctl *tpctl = &mac->mac_tpctl; 1265191762Simp struct rf_saveregs regs; 1266191762Simp uint16_t ant_div, chan_ex; 1267191762Simp uint8_t devi_ctrl; 1268191762Simp u_int orig_chan; 1269191762Simp 1270191762Simp /* 1271191762Simp * Save RF/PHY registers for later restoration 1272191762Simp */ 1273191762Simp orig_chan = rf->rf_curchan; 1274191762Simp bzero(®s, sizeof(regs)); 1275191762Simp 1276191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1277191762Simp SAVE_PHY_REG(mac, ®s, 429); 1278191762Simp SAVE_PHY_REG(mac, ®s, 802); 1279191762Simp 1280191762Simp PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff); 1281191762Simp PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc); 1282191762Simp } 1283191762Simp 1284191762Simp ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); 1285191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div | 0x8000); 1286191762Simp chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); 1287191762Simp 1288191762Simp SAVE_PHY_REG(mac, ®s, 15); 1289191762Simp SAVE_PHY_REG(mac, ®s, 2a); 1290191762Simp SAVE_PHY_REG(mac, ®s, 35); 1291191762Simp SAVE_PHY_REG(mac, ®s, 60); 1292191762Simp SAVE_RF_REG(mac, ®s, 43); 1293191762Simp SAVE_RF_REG(mac, ®s, 7a); 1294191762Simp SAVE_RF_REG(mac, ®s, 52); 1295191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1296191762Simp SAVE_PHY_REG(mac, ®s, 811); 1297191762Simp SAVE_PHY_REG(mac, ®s, 812); 1298191762Simp SAVE_PHY_REG(mac, ®s, 814); 1299191762Simp SAVE_PHY_REG(mac, ®s, 815); 1300191762Simp } 1301191762Simp 1302191762Simp /* Force to channel 6 */ 1303191762Simp bwi_rf_set_chan(mac, 6, 0); 1304191762Simp 1305191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1306191762Simp PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff); 1307191762Simp PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc); 1308191762Simp bwi_mac_dummy_xmit(mac); 1309191762Simp } 1310191762Simp RF_WRITE(mac, 0x43, 0x6); 1311191762Simp 1312191762Simp bwi_phy_set_bbp_atten(mac, 2); 1313191762Simp 1314191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0); 1315191762Simp 1316191762Simp PHY_WRITE(mac, 0x2e, 0x7f); 1317191762Simp PHY_WRITE(mac, 0x80f, 0x78); 1318191762Simp PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f); 1319191762Simp RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0); 1320191762Simp PHY_WRITE(mac, 0x2b, 0x203); 1321191762Simp PHY_WRITE(mac, 0x2a, 0x8a3); 1322191762Simp 1323191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1324191762Simp PHY_WRITE(mac, 0x814, regs.phy_814 | 0x3); 1325191762Simp PHY_WRITE(mac, 0x815, regs.phy_815 & 0xfffc); 1326191762Simp PHY_WRITE(mac, 0x811, 0x1b3); 1327191762Simp PHY_WRITE(mac, 0x812, 0xb2); 1328191762Simp } 1329191762Simp 1330191762Simp if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1331191762Simp tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac); 1332191762Simp PHY_WRITE(mac, 0x80f, 0x8078); 1333191762Simp 1334191762Simp /* 1335191762Simp * Measure all RF LO 1336191762Simp */ 1337191762Simp devi_ctrl = _bwi_rf_lo_update_11g(mac, regs.rf_7a); 1338191762Simp 1339191762Simp /* 1340191762Simp * Restore saved RF/PHY registers 1341191762Simp */ 1342191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1343191762Simp PHY_WRITE(mac, 0x15, 0xe300); 1344191762Simp PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa0); 1345191762Simp DELAY(5); 1346191762Simp PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa2); 1347191762Simp DELAY(2); 1348191762Simp PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa3); 1349191762Simp } else { 1350191762Simp PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0); 1351191762Simp } 1352191762Simp 1353191762Simp if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1354191762Simp tpctl = NULL; 1355191762Simp bwi_rf_lo_adjust(mac, tpctl); 1356191762Simp 1357191762Simp PHY_WRITE(mac, 0x2e, 0x807f); 1358191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) 1359191762Simp PHY_WRITE(mac, 0x2f, 0x202); 1360191762Simp else 1361191762Simp PHY_WRITE(mac, 0x2f, 0x101); 1362191762Simp 1363191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); 1364191762Simp 1365191762Simp RESTORE_PHY_REG(mac, ®s, 15); 1366191762Simp RESTORE_PHY_REG(mac, ®s, 2a); 1367191762Simp RESTORE_PHY_REG(mac, ®s, 35); 1368191762Simp RESTORE_PHY_REG(mac, ®s, 60); 1369191762Simp 1370191762Simp RESTORE_RF_REG(mac, ®s, 43); 1371191762Simp RESTORE_RF_REG(mac, ®s, 7a); 1372191762Simp 1373191762Simp regs.rf_52 &= 0xf0; 1374191762Simp regs.rf_52 |= (RF_READ(mac, 0x52) & 0xf); 1375191762Simp RF_WRITE(mac, 0x52, regs.rf_52); 1376191762Simp 1377191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); 1378191762Simp 1379191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1380191762Simp RESTORE_PHY_REG(mac, ®s, 811); 1381191762Simp RESTORE_PHY_REG(mac, ®s, 812); 1382191762Simp RESTORE_PHY_REG(mac, ®s, 814); 1383191762Simp RESTORE_PHY_REG(mac, ®s, 815); 1384191762Simp RESTORE_PHY_REG(mac, ®s, 429); 1385191762Simp RESTORE_PHY_REG(mac, ®s, 802); 1386191762Simp } 1387191762Simp 1388191762Simp bwi_rf_set_chan(mac, orig_chan, 1); 1389191762Simp} 1390191762Simp 1391191762Simpstatic uint32_t 1392191762Simpbwi_rf_lo_devi_measure(struct bwi_mac *mac, uint16_t ctrl) 1393191762Simp{ 1394191762Simp struct bwi_phy *phy = &mac->mac_phy; 1395191762Simp uint32_t devi = 0; 1396191762Simp int i; 1397191762Simp 1398191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) 1399191762Simp ctrl <<= 8; 1400191762Simp 1401191762Simp for (i = 0; i < 8; ++i) { 1402191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1403191762Simp PHY_WRITE(mac, 0x15, 0xe300); 1404191762Simp PHY_WRITE(mac, 0x812, ctrl | 0xb0); 1405191762Simp DELAY(5); 1406191762Simp PHY_WRITE(mac, 0x812, ctrl | 0xb2); 1407191762Simp DELAY(2); 1408191762Simp PHY_WRITE(mac, 0x812, ctrl | 0xb3); 1409191762Simp DELAY(4); 1410191762Simp PHY_WRITE(mac, 0x15, 0xf300); 1411191762Simp } else { 1412191762Simp PHY_WRITE(mac, 0x15, ctrl | 0xefa0); 1413191762Simp DELAY(2); 1414191762Simp PHY_WRITE(mac, 0x15, ctrl | 0xefe0); 1415191762Simp DELAY(4); 1416191762Simp PHY_WRITE(mac, 0x15, ctrl | 0xffe0); 1417191762Simp } 1418191762Simp DELAY(8); 1419191762Simp devi += PHY_READ(mac, 0x2d); 1420191762Simp } 1421191762Simp return devi; 1422191762Simp} 1423191762Simp 1424191762Simpstatic uint16_t 1425191762Simpbwi_rf_get_tp_ctrl2(struct bwi_mac *mac) 1426191762Simp{ 1427191762Simp uint32_t devi_min; 1428191762Simp uint16_t tp_ctrl2 = 0; 1429191762Simp int i; 1430191762Simp 1431191762Simp RF_WRITE(mac, 0x52, 0); 1432191762Simp DELAY(10); 1433191762Simp devi_min = bwi_rf_lo_devi_measure(mac, 0); 1434191762Simp 1435191762Simp for (i = 0; i < 16; ++i) { 1436191762Simp uint32_t devi; 1437191762Simp 1438191762Simp RF_WRITE(mac, 0x52, i); 1439191762Simp DELAY(10); 1440191762Simp devi = bwi_rf_lo_devi_measure(mac, 0); 1441191762Simp 1442191762Simp if (devi < devi_min) { 1443191762Simp devi_min = devi; 1444191762Simp tp_ctrl2 = i; 1445191762Simp } 1446191762Simp } 1447191762Simp return tp_ctrl2; 1448191762Simp} 1449191762Simp 1450191762Simpstatic uint8_t 1451191762Simp_bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a) 1452191762Simp{ 1453191762Simp#define RF_ATTEN_LISTSZ 14 1454191762Simp#define BBP_ATTEN_MAX 4 /* half */ 1455191762Simp 1456191762Simp static const int rf_atten_list[RF_ATTEN_LISTSZ] = 1457191762Simp { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 1, 2, 3, 4 }; 1458191762Simp static const int rf_atten_init_list[RF_ATTEN_LISTSZ] = 1459191762Simp { 0, 3, 1, 5, 7, 3, 2, 0, 4, 6, -1, -1, -1, -1 }; 1460191762Simp static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] = 1461191762Simp { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 }; 1462191762Simp 1463191762Simp struct ifnet *ifp = mac->mac_sc->sc_ifp; 1464191762Simp struct bwi_rf_lo lo_save, *lo; 1465191762Simp uint8_t devi_ctrl = 0; 1466191762Simp int idx, adj_rf7a = 0; 1467191762Simp 1468191762Simp bzero(&lo_save, sizeof(lo_save)); 1469191762Simp for (idx = 0; idx < RF_ATTEN_LISTSZ; ++idx) { 1470191762Simp int init_rf_atten = rf_atten_init_list[idx]; 1471191762Simp int rf_atten = rf_atten_list[idx]; 1472191762Simp int bbp_atten; 1473191762Simp 1474191762Simp for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) { 1475191762Simp uint16_t tp_ctrl2, rf7a; 1476191762Simp 1477191762Simp if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1478191762Simp if (idx == 0) { 1479191762Simp bzero(&lo_save, sizeof(lo_save)); 1480191762Simp } else if (init_rf_atten < 0) { 1481191762Simp lo = bwi_get_rf_lo(mac, 1482191762Simp rf_atten, 2 * bbp_atten); 1483191762Simp bcopy(lo, &lo_save, sizeof(lo_save)); 1484191762Simp } else { 1485191762Simp lo = bwi_get_rf_lo(mac, 1486191762Simp init_rf_atten, 0); 1487191762Simp bcopy(lo, &lo_save, sizeof(lo_save)); 1488191762Simp } 1489191762Simp 1490191762Simp devi_ctrl = 0; 1491191762Simp adj_rf7a = 0; 1492191762Simp 1493191762Simp /* 1494191762Simp * XXX 1495191762Simp * Linux driver overflows 'val' 1496191762Simp */ 1497191762Simp if (init_rf_atten >= 0) { 1498191762Simp int val; 1499191762Simp 1500191762Simp val = rf_atten * 2 + bbp_atten; 1501191762Simp if (val > 14) { 1502191762Simp adj_rf7a = 1; 1503191762Simp if (val > 17) 1504191762Simp devi_ctrl = 1; 1505191762Simp if (val > 19) 1506191762Simp devi_ctrl = 2; 1507191762Simp } 1508191762Simp } 1509191762Simp } else { 1510191762Simp lo = bwi_get_rf_lo(mac, 1511191762Simp rf_atten, 2 * bbp_atten); 1512191762Simp if (!bwi_rf_lo_isused(mac, lo)) 1513191762Simp continue; 1514191762Simp bcopy(lo, &lo_save, sizeof(lo_save)); 1515191762Simp 1516191762Simp devi_ctrl = 3; 1517191762Simp adj_rf7a = 0; 1518191762Simp } 1519191762Simp 1520191762Simp RF_WRITE(mac, BWI_RFR_ATTEN, rf_atten); 1521191762Simp 1522191762Simp tp_ctrl2 = mac->mac_tpctl.tp_ctrl2; 1523191762Simp if (init_rf_atten < 0) 1524191762Simp tp_ctrl2 |= (3 << 4); 1525191762Simp RF_WRITE(mac, BWI_RFR_TXPWR, tp_ctrl2); 1526191762Simp 1527191762Simp DELAY(10); 1528191762Simp 1529191762Simp bwi_phy_set_bbp_atten(mac, bbp_atten * 2); 1530191762Simp 1531191762Simp rf7a = orig_rf7a & 0xfff0; 1532191762Simp if (adj_rf7a) 1533191762Simp rf7a |= 0x8; 1534191762Simp RF_WRITE(mac, 0x7a, rf7a); 1535191762Simp 1536191762Simp lo = bwi_get_rf_lo(mac, 1537191762Simp rf_lo_measure_order[idx], bbp_atten * 2); 1538191762Simp bwi_rf_lo_measure_11g(mac, &lo_save, lo, devi_ctrl); 1539191762Simp } 1540191762Simp } 1541191762Simp return devi_ctrl; 1542191762Simp 1543191762Simp#undef RF_ATTEN_LISTSZ 1544191762Simp#undef BBP_ATTEN_MAX 1545191762Simp} 1546191762Simp 1547191762Simpstatic void 1548191762Simpbwi_rf_lo_measure_11g(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo, 1549191762Simp struct bwi_rf_lo *dst_lo, uint8_t devi_ctrl) 1550191762Simp{ 1551191762Simp#define LO_ADJUST_MIN 1 1552191762Simp#define LO_ADJUST_MAX 8 1553191762Simp#define LO_ADJUST(hi, lo) { .ctrl_hi = hi, .ctrl_lo = lo } 1554191762Simp static const struct bwi_rf_lo rf_lo_adjust[LO_ADJUST_MAX] = { 1555191762Simp LO_ADJUST(1, 1), 1556191762Simp LO_ADJUST(1, 0), 1557191762Simp LO_ADJUST(1, -1), 1558191762Simp LO_ADJUST(0, -1), 1559191762Simp LO_ADJUST(-1, -1), 1560191762Simp LO_ADJUST(-1, 0), 1561191762Simp LO_ADJUST(-1, 1), 1562191762Simp LO_ADJUST(0, 1) 1563191762Simp }; 1564191762Simp#undef LO_ADJUST 1565191762Simp 1566191762Simp struct bwi_rf_lo lo_min; 1567191762Simp uint32_t devi_min; 1568191762Simp int found, loop_count, adjust_state; 1569191762Simp 1570191762Simp bcopy(src_lo, &lo_min, sizeof(lo_min)); 1571191762Simp RF_LO_WRITE(mac, &lo_min); 1572191762Simp devi_min = bwi_rf_lo_devi_measure(mac, devi_ctrl); 1573191762Simp 1574191762Simp loop_count = 12; /* XXX */ 1575191762Simp adjust_state = 0; 1576191762Simp do { 1577191762Simp struct bwi_rf_lo lo_base; 1578191762Simp int i, fin; 1579191762Simp 1580191762Simp found = 0; 1581191762Simp if (adjust_state == 0) { 1582191762Simp i = LO_ADJUST_MIN; 1583191762Simp fin = LO_ADJUST_MAX; 1584191762Simp } else if (adjust_state % 2 == 0) { 1585191762Simp i = adjust_state - 1; 1586191762Simp fin = adjust_state + 1; 1587191762Simp } else { 1588191762Simp i = adjust_state - 2; 1589191762Simp fin = adjust_state + 2; 1590191762Simp } 1591191762Simp 1592191762Simp if (i < LO_ADJUST_MIN) 1593191762Simp i += LO_ADJUST_MAX; 1594191762Simp KASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN, ("i %d", i)); 1595191762Simp 1596191762Simp if (fin > LO_ADJUST_MAX) 1597191762Simp fin -= LO_ADJUST_MAX; 1598191762Simp KASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN, 1599191762Simp ("fin %d", fin)); 1600191762Simp 1601191762Simp bcopy(&lo_min, &lo_base, sizeof(lo_base)); 1602191762Simp for (;;) { 1603191762Simp struct bwi_rf_lo lo; 1604191762Simp 1605191762Simp lo.ctrl_hi = lo_base.ctrl_hi + 1606191762Simp rf_lo_adjust[i - 1].ctrl_hi; 1607191762Simp lo.ctrl_lo = lo_base.ctrl_lo + 1608191762Simp rf_lo_adjust[i - 1].ctrl_lo; 1609191762Simp 1610191762Simp if (abs(lo.ctrl_lo) < 9 && abs(lo.ctrl_hi) < 9) { 1611191762Simp uint32_t devi; 1612191762Simp 1613191762Simp RF_LO_WRITE(mac, &lo); 1614191762Simp devi = bwi_rf_lo_devi_measure(mac, devi_ctrl); 1615191762Simp if (devi < devi_min) { 1616191762Simp devi_min = devi; 1617191762Simp adjust_state = i; 1618191762Simp found = 1; 1619191762Simp bcopy(&lo, &lo_min, sizeof(lo_min)); 1620191762Simp } 1621191762Simp } 1622191762Simp if (i == fin) 1623191762Simp break; 1624191762Simp if (i == LO_ADJUST_MAX) 1625191762Simp i = LO_ADJUST_MIN; 1626191762Simp else 1627191762Simp ++i; 1628191762Simp } 1629191762Simp } while (loop_count-- && found); 1630191762Simp 1631191762Simp bcopy(&lo_min, dst_lo, sizeof(*dst_lo)); 1632191762Simp 1633191762Simp#undef LO_ADJUST_MIN 1634191762Simp#undef LO_ADJUST_MAX 1635191762Simp} 1636191762Simp 1637191762Simpstatic void 1638191762Simpbwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac) 1639191762Simp{ 1640191762Simp#define SAVE_RF_MAX 3 1641191762Simp#define SAVE_PHY_MAX 8 1642191762Simp 1643191762Simp static const uint16_t save_rf_regs[SAVE_RF_MAX] = 1644191762Simp { 0x7a, 0x52, 0x43 }; 1645191762Simp static const uint16_t save_phy_regs[SAVE_PHY_MAX] = 1646191762Simp { 0x30, 0x26, 0x15, 0x2a, 0x20, 0x5a, 0x59, 0x58 }; 1647191762Simp 1648191762Simp struct bwi_softc *sc = mac->mac_sc; 1649191762Simp struct bwi_rf *rf = &mac->mac_rf; 1650191762Simp struct bwi_phy *phy = &mac->mac_phy; 1651191762Simp uint16_t save_rf[SAVE_RF_MAX]; 1652191762Simp uint16_t save_phy[SAVE_PHY_MAX]; 1653191762Simp uint16_t ant_div, bbp_atten, chan_ex; 1654191762Simp int16_t nrssi[2]; 1655191762Simp int i; 1656191762Simp 1657191762Simp /* 1658191762Simp * Save RF/PHY registers for later restoration 1659191762Simp */ 1660191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 1661191762Simp save_rf[i] = RF_READ(mac, save_rf_regs[i]); 1662191762Simp for (i = 0; i < SAVE_PHY_MAX; ++i) 1663191762Simp save_phy[i] = PHY_READ(mac, save_phy_regs[i]); 1664191762Simp 1665191762Simp ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); 1666191762Simp bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN); 1667191762Simp chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); 1668191762Simp 1669191762Simp /* 1670191762Simp * Calculate nrssi0 1671191762Simp */ 1672191762Simp if (phy->phy_rev >= 5) 1673191762Simp RF_CLRBITS(mac, 0x7a, 0xff80); 1674191762Simp else 1675191762Simp RF_CLRBITS(mac, 0x7a, 0xfff0); 1676191762Simp PHY_WRITE(mac, 0x30, 0xff); 1677191762Simp 1678191762Simp CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x7f7f); 1679191762Simp 1680191762Simp PHY_WRITE(mac, 0x26, 0); 1681191762Simp PHY_SETBITS(mac, 0x15, 0x20); 1682191762Simp PHY_WRITE(mac, 0x2a, 0x8a3); 1683191762Simp RF_SETBITS(mac, 0x7a, 0x80); 1684191762Simp 1685191762Simp nrssi[0] = (int16_t)PHY_READ(mac, 0x27); 1686191762Simp 1687191762Simp /* 1688191762Simp * Calculate nrssi1 1689191762Simp */ 1690191762Simp RF_CLRBITS(mac, 0x7a, 0xff80); 1691191762Simp if (phy->phy_version >= 2) 1692191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x40); 1693191762Simp else if (phy->phy_version == 0) 1694191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122); 1695191762Simp else 1696191762Simp CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0xdfff); 1697191762Simp 1698191762Simp PHY_WRITE(mac, 0x20, 0x3f3f); 1699191762Simp PHY_WRITE(mac, 0x15, 0xf330); 1700191762Simp 1701191762Simp RF_WRITE(mac, 0x5a, 0x60); 1702191762Simp RF_CLRBITS(mac, 0x43, 0xff0f); 1703191762Simp 1704191762Simp PHY_WRITE(mac, 0x5a, 0x480); 1705191762Simp PHY_WRITE(mac, 0x59, 0x810); 1706191762Simp PHY_WRITE(mac, 0x58, 0xd); 1707191762Simp 1708191762Simp DELAY(20); 1709191762Simp 1710191762Simp nrssi[1] = (int16_t)PHY_READ(mac, 0x27); 1711191762Simp 1712191762Simp /* 1713191762Simp * Restore saved RF/PHY registers 1714191762Simp */ 1715191762Simp PHY_WRITE(mac, save_phy_regs[0], save_phy[0]); 1716191762Simp RF_WRITE(mac, save_rf_regs[0], save_rf[0]); 1717191762Simp 1718191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); 1719191762Simp 1720191762Simp for (i = 1; i < 4; ++i) 1721191762Simp PHY_WRITE(mac, save_phy_regs[i], save_phy[i]); 1722191762Simp 1723191762Simp bwi_rf_work_around(mac, rf->rf_curchan); 1724191762Simp 1725191762Simp if (phy->phy_version != 0) 1726191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); 1727191762Simp 1728191762Simp for (; i < SAVE_PHY_MAX; ++i) 1729191762Simp PHY_WRITE(mac, save_phy_regs[i], save_phy[i]); 1730191762Simp 1731191762Simp for (i = 1; i < SAVE_RF_MAX; ++i) 1732191762Simp RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 1733191762Simp 1734191762Simp /* 1735191762Simp * Install calculated narrow RSSI values 1736191762Simp */ 1737191762Simp if (nrssi[0] == nrssi[1]) 1738191762Simp rf->rf_nrssi_slope = 0x10000; 1739191762Simp else 1740191762Simp rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]); 1741191762Simp if (nrssi[0] <= -4) { 1742191762Simp rf->rf_nrssi[0] = nrssi[0]; 1743191762Simp rf->rf_nrssi[1] = nrssi[1]; 1744191762Simp } 1745191762Simp 1746191762Simp#undef SAVE_RF_MAX 1747191762Simp#undef SAVE_PHY_MAX 1748191762Simp} 1749191762Simp 1750191762Simpstatic void 1751191762Simpbwi_rf_set_nrssi_ofs_11g(struct bwi_mac *mac) 1752191762Simp{ 1753191762Simp#define SAVE_RF_MAX 2 1754191762Simp#define SAVE_PHY_COMM_MAX 10 1755191762Simp#define SAVE_PHY6_MAX 8 1756191762Simp 1757191762Simp static const uint16_t save_rf_regs[SAVE_RF_MAX] = 1758191762Simp { 0x7a, 0x43 }; 1759191762Simp static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = { 1760191762Simp 0x0001, 0x0811, 0x0812, 0x0814, 1761191762Simp 0x0815, 0x005a, 0x0059, 0x0058, 1762191762Simp 0x000a, 0x0003 1763191762Simp }; 1764191762Simp static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = { 1765191762Simp 0x002e, 0x002f, 0x080f, 0x0810, 1766191762Simp 0x0801, 0x0060, 0x0014, 0x0478 1767191762Simp }; 1768191762Simp 1769191762Simp struct bwi_phy *phy = &mac->mac_phy; 1770191762Simp uint16_t save_rf[SAVE_RF_MAX]; 1771191762Simp uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 1772191762Simp uint16_t save_phy6[SAVE_PHY6_MAX]; 1773191762Simp uint16_t rf7b = 0xffff; 1774191762Simp int16_t nrssi; 1775191762Simp int i, phy6_idx = 0; 1776191762Simp 1777191762Simp for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 1778191762Simp save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]); 1779191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 1780191762Simp save_rf[i] = RF_READ(mac, save_rf_regs[i]); 1781191762Simp 1782191762Simp PHY_CLRBITS(mac, 0x429, 0x8000); 1783191762Simp PHY_FILT_SETBITS(mac, 0x1, 0x3fff, 0x4000); 1784191762Simp PHY_SETBITS(mac, 0x811, 0xc); 1785191762Simp PHY_FILT_SETBITS(mac, 0x812, 0xfff3, 0x4); 1786191762Simp PHY_CLRBITS(mac, 0x802, 0x3); 1787191762Simp 1788191762Simp if (phy->phy_rev >= 6) { 1789191762Simp for (i = 0; i < SAVE_PHY6_MAX; ++i) 1790191762Simp save_phy6[i] = PHY_READ(mac, save_phy6_regs[i]); 1791191762Simp 1792191762Simp PHY_WRITE(mac, 0x2e, 0); 1793191762Simp PHY_WRITE(mac, 0x2f, 0); 1794191762Simp PHY_WRITE(mac, 0x80f, 0); 1795191762Simp PHY_WRITE(mac, 0x810, 0); 1796191762Simp PHY_SETBITS(mac, 0x478, 0x100); 1797191762Simp PHY_SETBITS(mac, 0x801, 0x40); 1798191762Simp PHY_SETBITS(mac, 0x60, 0x40); 1799191762Simp PHY_SETBITS(mac, 0x14, 0x200); 1800191762Simp } 1801191762Simp 1802191762Simp RF_SETBITS(mac, 0x7a, 0x70); 1803191762Simp RF_SETBITS(mac, 0x7a, 0x80); 1804191762Simp 1805191762Simp DELAY(30); 1806191762Simp 1807191762Simp nrssi = bwi_nrssi_11g(mac); 1808191762Simp if (nrssi == 31) { 1809191762Simp for (i = 7; i >= 4; --i) { 1810191762Simp RF_WRITE(mac, 0x7b, i); 1811191762Simp DELAY(20); 1812191762Simp nrssi = bwi_nrssi_11g(mac); 1813191762Simp if (nrssi < 31 && rf7b == 0xffff) 1814191762Simp rf7b = i; 1815191762Simp } 1816191762Simp if (rf7b == 0xffff) 1817191762Simp rf7b = 4; 1818191762Simp } else { 1819191762Simp struct bwi_gains gains; 1820191762Simp 1821191762Simp RF_CLRBITS(mac, 0x7a, 0xff80); 1822191762Simp 1823191762Simp PHY_SETBITS(mac, 0x814, 0x1); 1824191762Simp PHY_CLRBITS(mac, 0x815, 0x1); 1825191762Simp PHY_SETBITS(mac, 0x811, 0xc); 1826191762Simp PHY_SETBITS(mac, 0x812, 0xc); 1827191762Simp PHY_SETBITS(mac, 0x811, 0x30); 1828191762Simp PHY_SETBITS(mac, 0x812, 0x30); 1829191762Simp PHY_WRITE(mac, 0x5a, 0x480); 1830191762Simp PHY_WRITE(mac, 0x59, 0x810); 1831191762Simp PHY_WRITE(mac, 0x58, 0xd); 1832191762Simp if (phy->phy_version == 0) 1833191762Simp PHY_WRITE(mac, 0x3, 0x122); 1834191762Simp else 1835191762Simp PHY_SETBITS(mac, 0xa, 0x2000); 1836191762Simp PHY_SETBITS(mac, 0x814, 0x4); 1837191762Simp PHY_CLRBITS(mac, 0x815, 0x4); 1838191762Simp PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40); 1839191762Simp RF_SETBITS(mac, 0x7a, 0xf); 1840191762Simp 1841191762Simp bzero(&gains, sizeof(gains)); 1842191762Simp gains.tbl_gain1 = 3; 1843191762Simp gains.tbl_gain2 = 0; 1844191762Simp gains.phy_gain = 1; 1845191762Simp bwi_set_gains(mac, &gains); 1846191762Simp 1847191762Simp RF_FILT_SETBITS(mac, 0x43, 0xf0, 0xf); 1848191762Simp DELAY(30); 1849191762Simp 1850191762Simp nrssi = bwi_nrssi_11g(mac); 1851191762Simp if (nrssi == -32) { 1852191762Simp for (i = 0; i < 4; ++i) { 1853191762Simp RF_WRITE(mac, 0x7b, i); 1854191762Simp DELAY(20); 1855191762Simp nrssi = bwi_nrssi_11g(mac); 1856191762Simp if (nrssi > -31 && rf7b == 0xffff) 1857191762Simp rf7b = i; 1858191762Simp } 1859191762Simp if (rf7b == 0xffff) 1860191762Simp rf7b = 3; 1861191762Simp } else { 1862191762Simp rf7b = 0; 1863191762Simp } 1864191762Simp } 1865191762Simp RF_WRITE(mac, 0x7b, rf7b); 1866191762Simp 1867191762Simp /* 1868191762Simp * Restore saved RF/PHY registers 1869191762Simp */ 1870191762Simp if (phy->phy_rev >= 6) { 1871191762Simp for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) { 1872191762Simp PHY_WRITE(mac, save_phy6_regs[phy6_idx], 1873191762Simp save_phy6[phy6_idx]); 1874191762Simp } 1875191762Simp } 1876191762Simp 1877191762Simp /* Saved PHY registers 0, 1, 2 are handled later */ 1878191762Simp for (i = 3; i < SAVE_PHY_COMM_MAX; ++i) 1879191762Simp PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); 1880191762Simp 1881191762Simp for (i = SAVE_RF_MAX - 1; i >= 0; --i) 1882191762Simp RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 1883191762Simp 1884191762Simp PHY_SETBITS(mac, 0x802, 0x3); 1885191762Simp PHY_SETBITS(mac, 0x429, 0x8000); 1886191762Simp 1887191762Simp bwi_set_gains(mac, NULL); 1888191762Simp 1889191762Simp if (phy->phy_rev >= 6) { 1890191762Simp for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) { 1891191762Simp PHY_WRITE(mac, save_phy6_regs[phy6_idx], 1892191762Simp save_phy6[phy6_idx]); 1893191762Simp } 1894191762Simp } 1895191762Simp 1896191762Simp PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]); 1897191762Simp PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]); 1898191762Simp PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]); 1899191762Simp 1900191762Simp#undef SAVE_RF_MAX 1901191762Simp#undef SAVE_PHY_COMM_MAX 1902191762Simp#undef SAVE_PHY6_MAX 1903191762Simp} 1904191762Simp 1905191762Simpstatic void 1906191762Simpbwi_rf_calc_nrssi_slope_11g(struct bwi_mac *mac) 1907191762Simp{ 1908191762Simp#define SAVE_RF_MAX 3 1909191762Simp#define SAVE_PHY_COMM_MAX 4 1910191762Simp#define SAVE_PHY3_MAX 8 1911191762Simp 1912191762Simp static const uint16_t save_rf_regs[SAVE_RF_MAX] = 1913191762Simp { 0x7a, 0x52, 0x43 }; 1914191762Simp static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = 1915191762Simp { 0x15, 0x5a, 0x59, 0x58 }; 1916191762Simp static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = { 1917191762Simp 0x002e, 0x002f, 0x080f, 0x0810, 1918191762Simp 0x0801, 0x0060, 0x0014, 0x0478 1919191762Simp }; 1920191762Simp 1921191762Simp struct bwi_softc *sc = mac->mac_sc; 1922191762Simp struct bwi_phy *phy = &mac->mac_phy; 1923191762Simp struct bwi_rf *rf = &mac->mac_rf; 1924191762Simp uint16_t save_rf[SAVE_RF_MAX]; 1925191762Simp uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 1926191762Simp uint16_t save_phy3[SAVE_PHY3_MAX]; 1927191762Simp uint16_t ant_div, bbp_atten, chan_ex; 1928191762Simp struct bwi_gains gains; 1929191762Simp int16_t nrssi[2]; 1930191762Simp int i, phy3_idx = 0; 1931191762Simp 1932191762Simp if (rf->rf_rev >= 9) 1933191762Simp return; 1934191762Simp else if (rf->rf_rev == 8) 1935191762Simp bwi_rf_set_nrssi_ofs_11g(mac); 1936191762Simp 1937191762Simp PHY_CLRBITS(mac, 0x429, 0x8000); 1938191762Simp PHY_CLRBITS(mac, 0x802, 0x3); 1939191762Simp 1940191762Simp /* 1941191762Simp * Save RF/PHY registers for later restoration 1942191762Simp */ 1943191762Simp ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); 1944191762Simp CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000); 1945191762Simp 1946191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 1947191762Simp save_rf[i] = RF_READ(mac, save_rf_regs[i]); 1948191762Simp for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 1949191762Simp save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]); 1950191762Simp 1951191762Simp bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN); 1952191762Simp chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); 1953191762Simp 1954191762Simp if (phy->phy_rev >= 3) { 1955191762Simp for (i = 0; i < SAVE_PHY3_MAX; ++i) 1956191762Simp save_phy3[i] = PHY_READ(mac, save_phy3_regs[i]); 1957191762Simp 1958191762Simp PHY_WRITE(mac, 0x2e, 0); 1959191762Simp PHY_WRITE(mac, 0x810, 0); 1960191762Simp 1961191762Simp if (phy->phy_rev == 4 || phy->phy_rev == 6 || 1962191762Simp phy->phy_rev == 7) { 1963191762Simp PHY_SETBITS(mac, 0x478, 0x100); 1964191762Simp PHY_SETBITS(mac, 0x810, 0x40); 1965191762Simp } else if (phy->phy_rev == 3 || phy->phy_rev == 5) { 1966191762Simp PHY_CLRBITS(mac, 0x810, 0x40); 1967191762Simp } 1968191762Simp 1969191762Simp PHY_SETBITS(mac, 0x60, 0x40); 1970191762Simp PHY_SETBITS(mac, 0x14, 0x200); 1971191762Simp } 1972191762Simp 1973191762Simp /* 1974191762Simp * Calculate nrssi0 1975191762Simp */ 1976191762Simp RF_SETBITS(mac, 0x7a, 0x70); 1977191762Simp 1978191762Simp bzero(&gains, sizeof(gains)); 1979191762Simp gains.tbl_gain1 = 0; 1980191762Simp gains.tbl_gain2 = 8; 1981191762Simp gains.phy_gain = 0; 1982191762Simp bwi_set_gains(mac, &gains); 1983191762Simp 1984191762Simp RF_CLRBITS(mac, 0x7a, 0xff08); 1985191762Simp if (phy->phy_rev >= 2) { 1986191762Simp PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x30); 1987191762Simp PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10); 1988191762Simp } 1989191762Simp 1990191762Simp RF_SETBITS(mac, 0x7a, 0x80); 1991191762Simp DELAY(20); 1992191762Simp nrssi[0] = bwi_nrssi_11g(mac); 1993191762Simp 1994191762Simp /* 1995191762Simp * Calculate nrssi1 1996191762Simp */ 1997191762Simp RF_CLRBITS(mac, 0x7a, 0xff80); 1998191762Simp if (phy->phy_version >= 2) 1999191762Simp PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40); 2000191762Simp CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000); 2001191762Simp 2002191762Simp RF_SETBITS(mac, 0x7a, 0xf); 2003191762Simp PHY_WRITE(mac, 0x15, 0xf330); 2004191762Simp if (phy->phy_rev >= 2) { 2005191762Simp PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x20); 2006191762Simp PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x20); 2007191762Simp } 2008191762Simp 2009191762Simp bzero(&gains, sizeof(gains)); 2010191762Simp gains.tbl_gain1 = 3; 2011191762Simp gains.tbl_gain2 = 0; 2012191762Simp gains.phy_gain = 1; 2013191762Simp bwi_set_gains(mac, &gains); 2014191762Simp 2015191762Simp if (rf->rf_rev == 8) { 2016191762Simp RF_WRITE(mac, 0x43, 0x1f); 2017191762Simp } else { 2018191762Simp RF_FILT_SETBITS(mac, 0x52, 0xff0f, 0x60); 2019191762Simp RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9); 2020191762Simp } 2021191762Simp PHY_WRITE(mac, 0x5a, 0x480); 2022191762Simp PHY_WRITE(mac, 0x59, 0x810); 2023191762Simp PHY_WRITE(mac, 0x58, 0xd); 2024191762Simp DELAY(20); 2025191762Simp 2026191762Simp nrssi[1] = bwi_nrssi_11g(mac); 2027191762Simp 2028191762Simp /* 2029191762Simp * Install calculated narrow RSSI values 2030191762Simp */ 2031191762Simp if (nrssi[1] == nrssi[0]) 2032191762Simp rf->rf_nrssi_slope = 0x10000; 2033191762Simp else 2034191762Simp rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]); 2035191762Simp if (nrssi[0] >= -4) { 2036191762Simp rf->rf_nrssi[0] = nrssi[1]; 2037191762Simp rf->rf_nrssi[1] = nrssi[0]; 2038191762Simp } 2039191762Simp 2040191762Simp /* 2041191762Simp * Restore saved RF/PHY registers 2042191762Simp */ 2043191762Simp if (phy->phy_rev >= 3) { 2044191762Simp for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) { 2045191762Simp PHY_WRITE(mac, save_phy3_regs[phy3_idx], 2046191762Simp save_phy3[phy3_idx]); 2047191762Simp } 2048191762Simp } 2049191762Simp if (phy->phy_rev >= 2) { 2050191762Simp PHY_CLRBITS(mac, 0x812, 0x30); 2051191762Simp PHY_CLRBITS(mac, 0x811, 0x30); 2052191762Simp } 2053191762Simp 2054191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 2055191762Simp RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 2056191762Simp 2057191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); 2058191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten); 2059191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); 2060191762Simp 2061191762Simp for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 2062191762Simp PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); 2063191762Simp 2064191762Simp bwi_rf_work_around(mac, rf->rf_curchan); 2065191762Simp PHY_SETBITS(mac, 0x802, 0x3); 2066191762Simp bwi_set_gains(mac, NULL); 2067191762Simp PHY_SETBITS(mac, 0x429, 0x8000); 2068191762Simp 2069191762Simp if (phy->phy_rev >= 3) { 2070191762Simp for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) { 2071191762Simp PHY_WRITE(mac, save_phy3_regs[phy3_idx], 2072191762Simp save_phy3[phy3_idx]); 2073191762Simp } 2074191762Simp } 2075191762Simp 2076191762Simp bwi_rf_init_sw_nrssi_table(mac); 2077191762Simp bwi_rf_set_nrssi_thr_11g(mac); 2078191762Simp 2079191762Simp#undef SAVE_RF_MAX 2080191762Simp#undef SAVE_PHY_COMM_MAX 2081191762Simp#undef SAVE_PHY3_MAX 2082191762Simp} 2083191762Simp 2084191762Simpstatic void 2085191762Simpbwi_rf_init_sw_nrssi_table(struct bwi_mac *mac) 2086191762Simp{ 2087191762Simp struct bwi_rf *rf = &mac->mac_rf; 2088191762Simp int d, i; 2089191762Simp 2090191762Simp d = 0x1f - rf->rf_nrssi[0]; 2091191762Simp for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) { 2092191762Simp int val; 2093191762Simp 2094191762Simp val = (((i - d) * rf->rf_nrssi_slope) / 0x10000) + 0x3a; 2095191762Simp if (val < 0) 2096191762Simp val = 0; 2097191762Simp else if (val > 0x3f) 2098191762Simp val = 0x3f; 2099191762Simp 2100191762Simp rf->rf_nrssi_table[i] = val; 2101191762Simp } 2102191762Simp} 2103191762Simp 2104191762Simpvoid 2105191762Simpbwi_rf_init_hw_nrssi_table(struct bwi_mac *mac, uint16_t adjust) 2106191762Simp{ 2107191762Simp int i; 2108191762Simp 2109191762Simp for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) { 2110191762Simp int16_t val; 2111191762Simp 2112191762Simp val = bwi_nrssi_read(mac, i); 2113191762Simp 2114191762Simp val -= adjust; 2115191762Simp if (val < -32) 2116191762Simp val = -32; 2117191762Simp else if (val > 31) 2118191762Simp val = 31; 2119191762Simp 2120191762Simp bwi_nrssi_write(mac, i, val); 2121191762Simp } 2122191762Simp} 2123191762Simp 2124191762Simpstatic void 2125191762Simpbwi_rf_set_nrssi_thr_11b(struct bwi_mac *mac) 2126191762Simp{ 2127191762Simp struct bwi_rf *rf = &mac->mac_rf; 2128191762Simp int32_t thr; 2129191762Simp 2130191762Simp if (rf->rf_type != BWI_RF_T_BCM2050 || 2131191762Simp (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) 2132191762Simp return; 2133191762Simp 2134191762Simp /* 2135191762Simp * Calculate nrssi threshold 2136191762Simp */ 2137191762Simp if (rf->rf_rev >= 6) { 2138191762Simp thr = (rf->rf_nrssi[1] - rf->rf_nrssi[0]) * 32; 2139191762Simp thr += 20 * (rf->rf_nrssi[0] + 1); 2140191762Simp thr /= 40; 2141191762Simp } else { 2142191762Simp thr = rf->rf_nrssi[1] - 5; 2143191762Simp } 2144191762Simp if (thr < 0) 2145191762Simp thr = 0; 2146191762Simp else if (thr > 0x3e) 2147191762Simp thr = 0x3e; 2148191762Simp 2149191762Simp PHY_READ(mac, BWI_PHYR_NRSSI_THR_11B); /* dummy read */ 2150191762Simp PHY_WRITE(mac, BWI_PHYR_NRSSI_THR_11B, (((uint16_t)thr) << 8) | 0x1c); 2151191762Simp 2152191762Simp if (rf->rf_rev >= 6) { 2153191762Simp PHY_WRITE(mac, 0x87, 0xe0d); 2154191762Simp PHY_WRITE(mac, 0x86, 0xc0b); 2155191762Simp PHY_WRITE(mac, 0x85, 0xa09); 2156191762Simp PHY_WRITE(mac, 0x84, 0x808); 2157191762Simp PHY_WRITE(mac, 0x83, 0x808); 2158191762Simp PHY_WRITE(mac, 0x82, 0x604); 2159191762Simp PHY_WRITE(mac, 0x81, 0x302); 2160191762Simp PHY_WRITE(mac, 0x80, 0x100); 2161191762Simp } 2162191762Simp} 2163191762Simp 2164191762Simpstatic __inline int32_t 2165191762Simp_nrssi_threshold(const struct bwi_rf *rf, int32_t val) 2166191762Simp{ 2167191762Simp val *= (rf->rf_nrssi[1] - rf->rf_nrssi[0]); 2168191762Simp val += (rf->rf_nrssi[0] << 6); 2169191762Simp if (val < 32) 2170191762Simp val += 31; 2171191762Simp else 2172191762Simp val += 32; 2173191762Simp val >>= 6; 2174191762Simp if (val < -31) 2175191762Simp val = -31; 2176191762Simp else if (val > 31) 2177191762Simp val = 31; 2178191762Simp return val; 2179191762Simp} 2180191762Simp 2181191762Simpstatic void 2182191762Simpbwi_rf_set_nrssi_thr_11g(struct bwi_mac *mac) 2183191762Simp{ 2184191762Simp int32_t thr1, thr2; 2185191762Simp uint16_t thr; 2186191762Simp 2187191762Simp /* 2188191762Simp * Find the two nrssi thresholds 2189191762Simp */ 2190191762Simp if ((mac->mac_phy.phy_flags & BWI_PHY_F_LINKED) == 0 || 2191191762Simp (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) { 2192191762Simp int16_t nrssi; 2193191762Simp 2194191762Simp nrssi = bwi_nrssi_read(mac, 0x20); 2195191762Simp if (nrssi >= 32) 2196191762Simp nrssi -= 64; 2197191762Simp 2198191762Simp if (nrssi < 3) { 2199191762Simp thr1 = 0x2b; 2200191762Simp thr2 = 0x27; 2201191762Simp } else { 2202191762Simp thr1 = 0x2d; 2203191762Simp thr2 = 0x2b; 2204191762Simp } 2205191762Simp } else { 2206191762Simp /* TODO Interfere mode */ 2207191762Simp thr1 = _nrssi_threshold(&mac->mac_rf, 0x11); 2208191762Simp thr2 = _nrssi_threshold(&mac->mac_rf, 0xe); 2209191762Simp } 2210191762Simp 2211191762Simp#define NRSSI_THR1_MASK __BITS(5, 0) 2212191762Simp#define NRSSI_THR2_MASK __BITS(11, 6) 2213191762Simp 2214191762Simp thr = __SHIFTIN((uint32_t)thr1, NRSSI_THR1_MASK) | 2215191762Simp __SHIFTIN((uint32_t)thr2, NRSSI_THR2_MASK); 2216191762Simp PHY_FILT_SETBITS(mac, BWI_PHYR_NRSSI_THR_11G, 0xf000, thr); 2217191762Simp 2218191762Simp#undef NRSSI_THR1_MASK 2219191762Simp#undef NRSSI_THR2_MASK 2220191762Simp} 2221191762Simp 2222191762Simpvoid 2223191762Simpbwi_rf_clear_tssi(struct bwi_mac *mac) 2224191762Simp{ 2225191762Simp /* XXX use function pointer */ 2226191762Simp if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) { 2227191762Simp /* TODO:11A */ 2228191762Simp } else { 2229191762Simp uint16_t val; 2230191762Simp int i; 2231191762Simp 2232191762Simp val = __SHIFTIN(BWI_INVALID_TSSI, BWI_LO_TSSI_MASK) | 2233191762Simp __SHIFTIN(BWI_INVALID_TSSI, BWI_HI_TSSI_MASK); 2234191762Simp 2235191762Simp for (i = 0; i < 2; ++i) { 2236191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 2237191762Simp BWI_COMM_MOBJ_TSSI_DS + (i * 2), val); 2238191762Simp } 2239191762Simp 2240191762Simp for (i = 0; i < 2; ++i) { 2241191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 2242191762Simp BWI_COMM_MOBJ_TSSI_OFDM + (i * 2), val); 2243191762Simp } 2244191762Simp } 2245191762Simp} 2246191762Simp 2247191762Simpvoid 2248191762Simpbwi_rf_clear_state(struct bwi_rf *rf) 2249191762Simp{ 2250191762Simp int i; 2251191762Simp 2252191762Simp rf->rf_flags &= ~BWI_RF_CLEAR_FLAGS; 2253191762Simp bzero(rf->rf_lo, sizeof(rf->rf_lo)); 2254191762Simp bzero(rf->rf_lo_used, sizeof(rf->rf_lo_used)); 2255191762Simp 2256191762Simp rf->rf_nrssi_slope = 0; 2257191762Simp rf->rf_nrssi[0] = BWI_INVALID_NRSSI; 2258191762Simp rf->rf_nrssi[1] = BWI_INVALID_NRSSI; 2259191762Simp 2260191762Simp for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) 2261191762Simp rf->rf_nrssi_table[i] = i; 2262191762Simp 2263191762Simp rf->rf_lo_gain = 0; 2264191762Simp rf->rf_rx_gain = 0; 2265191762Simp 2266191762Simp bcopy(rf->rf_txpower_map0, rf->rf_txpower_map, 2267191762Simp sizeof(rf->rf_txpower_map)); 2268191762Simp rf->rf_idle_tssi = rf->rf_idle_tssi0; 2269191762Simp} 2270191762Simp 2271191762Simpstatic void 2272191762Simpbwi_rf_on_11a(struct bwi_mac *mac) 2273191762Simp{ 2274191762Simp /* TODO:11A */ 2275191762Simp} 2276191762Simp 2277191762Simpstatic void 2278191762Simpbwi_rf_on_11bg(struct bwi_mac *mac) 2279191762Simp{ 2280191762Simp struct bwi_phy *phy = &mac->mac_phy; 2281191762Simp 2282191762Simp PHY_WRITE(mac, 0x15, 0x8000); 2283191762Simp PHY_WRITE(mac, 0x15, 0xcc00); 2284191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) 2285191762Simp PHY_WRITE(mac, 0x15, 0xc0); 2286191762Simp else 2287191762Simp PHY_WRITE(mac, 0x15, 0); 2288191762Simp 2289191762Simp bwi_rf_set_chan(mac, 6 /* XXX */, 1); 2290191762Simp} 2291191762Simp 2292191762Simpvoid 2293191762Simpbwi_rf_set_ant_mode(struct bwi_mac *mac, int ant_mode) 2294191762Simp{ 2295191762Simp struct bwi_softc *sc = mac->mac_sc; 2296191762Simp struct bwi_phy *phy = &mac->mac_phy; 2297191762Simp uint16_t val; 2298191762Simp 2299191762Simp KASSERT(ant_mode == BWI_ANT_MODE_0 || 2300191762Simp ant_mode == BWI_ANT_MODE_1 || 2301191762Simp ant_mode == BWI_ANT_MODE_AUTO, ("ant_mode %d", ant_mode)); 2302191762Simp 2303191762Simp HFLAGS_CLRBITS(mac, BWI_HFLAG_AUTO_ANTDIV); 2304191762Simp 2305191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) { 2306191762Simp /* NOTE: v4/v3 conflicts, take v3 */ 2307191762Simp if (mac->mac_rev == 2) 2308191762Simp val = BWI_ANT_MODE_AUTO; 2309191762Simp else 2310191762Simp val = ant_mode; 2311191762Simp val <<= 7; 2312191762Simp PHY_FILT_SETBITS(mac, 0x3e2, 0xfe7f, val); 2313191762Simp } else { /* 11a/g */ 2314191762Simp /* XXX reg/value naming */ 2315191762Simp val = ant_mode << 7; 2316191762Simp PHY_FILT_SETBITS(mac, 0x401, 0x7e7f, val); 2317191762Simp 2318191762Simp if (ant_mode == BWI_ANT_MODE_AUTO) 2319191762Simp PHY_CLRBITS(mac, 0x42b, 0x100); 2320191762Simp 2321191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) { 2322191762Simp /* TODO:11A */ 2323191762Simp } else { /* 11g */ 2324191762Simp if (ant_mode == BWI_ANT_MODE_AUTO) 2325191762Simp PHY_SETBITS(mac, 0x48c, 0x2000); 2326191762Simp else 2327191762Simp PHY_CLRBITS(mac, 0x48c, 0x2000); 2328191762Simp 2329191762Simp if (phy->phy_rev >= 2) { 2330191762Simp PHY_SETBITS(mac, 0x461, 0x10); 2331191762Simp PHY_FILT_SETBITS(mac, 0x4ad, 0xff00, 0x15); 2332191762Simp if (phy->phy_rev == 2) { 2333191762Simp PHY_WRITE(mac, 0x427, 0x8); 2334191762Simp } else { 2335191762Simp PHY_FILT_SETBITS(mac, 0x427, 2336191762Simp 0xff00, 0x8); 2337191762Simp } 2338191762Simp 2339191762Simp if (phy->phy_rev >= 6) 2340191762Simp PHY_WRITE(mac, 0x49b, 0xdc); 2341191762Simp } 2342191762Simp } 2343191762Simp } 2344191762Simp 2345191762Simp /* XXX v4 set AUTO_ANTDIV unconditionally */ 2346191762Simp if (ant_mode == BWI_ANT_MODE_AUTO) 2347191762Simp HFLAGS_SETBITS(mac, BWI_HFLAG_AUTO_ANTDIV); 2348191762Simp 2349191762Simp val = ant_mode << 8; 2350191762Simp MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_BEACON, 2351191762Simp 0xfc3f, val); 2352191762Simp MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_ACK, 2353191762Simp 0xfc3f, val); 2354191762Simp MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_PROBE_RESP, 2355191762Simp 0xfc3f, val); 2356191762Simp 2357191762Simp /* XXX what's these */ 2358191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) 2359191762Simp CSR_SETBITS_2(sc, 0x5e, 0x4); 2360191762Simp 2361191762Simp CSR_WRITE_4(sc, 0x100, 0x1000000); 2362191762Simp if (mac->mac_rev < 5) 2363191762Simp CSR_WRITE_4(sc, 0x10c, 0x1000000); 2364191762Simp 2365191762Simp mac->mac_rf.rf_ant_mode = ant_mode; 2366191762Simp} 2367191762Simp 2368191762Simpint 2369191762Simpbwi_rf_get_latest_tssi(struct bwi_mac *mac, int8_t tssi[], uint16_t ofs) 2370191762Simp{ 2371191762Simp int i; 2372191762Simp 2373191762Simp for (i = 0; i < 4; ) { 2374191762Simp uint16_t val; 2375191762Simp 2376191762Simp val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs + i); 2377191762Simp tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_LO_TSSI_MASK); 2378191762Simp tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_HI_TSSI_MASK); 2379191762Simp } 2380191762Simp 2381191762Simp for (i = 0; i < 4; ++i) { 2382191762Simp if (tssi[i] == BWI_INVALID_TSSI) 2383191762Simp return EINVAL; 2384191762Simp } 2385191762Simp return 0; 2386191762Simp} 2387191762Simp 2388191762Simpint 2389191762Simpbwi_rf_tssi2dbm(struct bwi_mac *mac, int8_t tssi, int8_t *txpwr) 2390191762Simp{ 2391191762Simp struct bwi_rf *rf = &mac->mac_rf; 2392191762Simp int pwr_idx; 2393191762Simp 2394191762Simp pwr_idx = rf->rf_idle_tssi + (int)tssi - rf->rf_base_tssi; 2395191762Simp#if 0 2396191762Simp if (pwr_idx < 0 || pwr_idx >= BWI_TSSI_MAX) 2397191762Simp return EINVAL; 2398191762Simp#else 2399191762Simp if (pwr_idx < 0) 2400191762Simp pwr_idx = 0; 2401191762Simp else if (pwr_idx >= BWI_TSSI_MAX) 2402191762Simp pwr_idx = BWI_TSSI_MAX - 1; 2403191762Simp#endif 2404191762Simp 2405191762Simp *txpwr = rf->rf_txpower_map[pwr_idx]; 2406191762Simp return 0; 2407191762Simp} 2408191762Simp 2409191762Simpstatic int 2410191762Simpbwi_rf_calc_rssi_bcm2050(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) 2411191762Simp{ 2412191762Simp uint16_t flags1, flags3; 2413191762Simp int rssi, lna_gain; 2414191762Simp 2415191762Simp rssi = hdr->rxh_rssi; 2416191762Simp flags1 = le16toh(hdr->rxh_flags1); 2417191762Simp flags3 = le16toh(hdr->rxh_flags3); 2418191762Simp 2419191762Simp if (flags1 & BWI_RXH_F1_OFDM) { 2420191762Simp if (rssi > 127) 2421191762Simp rssi -= 256; 2422191762Simp if (flags3 & BWI_RXH_F3_BCM2050_RSSI) 2423191762Simp rssi += 17; 2424191762Simp else 2425191762Simp rssi -= 4; 2426191762Simp return rssi; 2427191762Simp } 2428191762Simp 2429191762Simp if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { 2430191762Simp struct bwi_rf *rf = &mac->mac_rf; 2431191762Simp 2432191762Simp if (rssi >= BWI_NRSSI_TBLSZ) 2433191762Simp rssi = BWI_NRSSI_TBLSZ - 1; 2434191762Simp 2435191762Simp rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128; 2436191762Simp rssi -= 67; 2437191762Simp } else { 2438191762Simp rssi = ((31 - rssi) * -149) / 128; 2439191762Simp rssi -= 68; 2440191762Simp } 2441191762Simp 2442191762Simp if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G) 2443191762Simp return rssi; 2444191762Simp 2445191762Simp if (flags3 & BWI_RXH_F3_BCM2050_RSSI) 2446191762Simp rssi += 20; 2447191762Simp 2448191762Simp lna_gain = __SHIFTOUT(le16toh(hdr->rxh_phyinfo), 2449191762Simp BWI_RXH_PHYINFO_LNAGAIN); 2450191762Simp DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_RX, 2451191762Simp "lna_gain %d, phyinfo 0x%04x\n", 2452191762Simp lna_gain, le16toh(hdr->rxh_phyinfo)); 2453191762Simp switch (lna_gain) { 2454191762Simp case 0: 2455191762Simp rssi += 27; 2456191762Simp break; 2457191762Simp case 1: 2458191762Simp rssi += 6; 2459191762Simp break; 2460191762Simp case 2: 2461191762Simp rssi += 12; 2462191762Simp break; 2463191762Simp case 3: 2464191762Simp /* 2465191762Simp * XXX 2466191762Simp * According to v3 spec, we should do _nothing_ here, 2467191762Simp * but it seems that the result RSSI will be too low 2468191762Simp * (relative to what ath(4) says). Raise it a little 2469191762Simp * bit. 2470191762Simp */ 2471191762Simp rssi += 5; 2472191762Simp break; 2473191762Simp default: 2474191762Simp panic("impossible lna gain %d", lna_gain); 2475191762Simp } 2476191762Simp return rssi; 2477191762Simp} 2478191762Simp 2479191762Simpstatic int 2480191762Simpbwi_rf_calc_rssi_bcm2053(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) 2481191762Simp{ 2482191762Simp uint16_t flags1; 2483191762Simp int rssi; 2484191762Simp 2485191762Simp rssi = (((int)hdr->rxh_rssi - 11) * 103) / 64; 2486191762Simp 2487191762Simp flags1 = le16toh(hdr->rxh_flags1); 2488191762Simp if (flags1 & BWI_RXH_F1_BCM2053_RSSI) 2489191762Simp rssi -= 109; 2490191762Simp else 2491191762Simp rssi -= 83; 2492191762Simp return rssi; 2493191762Simp} 2494191762Simp 2495191762Simpstatic int 2496191762Simpbwi_rf_calc_rssi_bcm2060(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) 2497191762Simp{ 2498191762Simp int rssi; 2499191762Simp 2500191762Simp rssi = hdr->rxh_rssi; 2501191762Simp if (rssi > 127) 2502191762Simp rssi -= 256; 2503191762Simp return rssi; 2504191762Simp} 2505191762Simp 2506191762Simpstatic int 2507191762Simpbwi_rf_calc_noise_bcm2050(struct bwi_mac *mac) 2508191762Simp{ 2509191762Simp uint16_t val; 2510191762Simp int noise; 2511191762Simp 2512191762Simp val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_NOISE); 2513191762Simp noise = (int)val; /* XXX check bounds? */ 2514191762Simp 2515191762Simp if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { 2516191762Simp struct bwi_rf *rf = &mac->mac_rf; 2517191762Simp 2518191762Simp if (noise >= BWI_NRSSI_TBLSZ) 2519191762Simp noise = BWI_NRSSI_TBLSZ - 1; 2520191762Simp 2521191762Simp noise = ((31 - (int)rf->rf_nrssi_table[noise]) * -131) / 128; 2522191762Simp noise -= 67; 2523191762Simp } else { 2524191762Simp noise = ((31 - noise) * -149) / 128; 2525191762Simp noise -= 68; 2526191762Simp } 2527191762Simp return noise; 2528191762Simp} 2529191762Simp 2530191762Simpstatic int 2531191762Simpbwi_rf_calc_noise_bcm2053(struct bwi_mac *mac) 2532191762Simp{ 2533191762Simp uint16_t val; 2534191762Simp int noise; 2535191762Simp 2536191762Simp val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_NOISE); 2537191762Simp noise = (int)val; /* XXX check bounds? */ 2538191762Simp 2539191762Simp noise = ((noise - 11) * 103) / 64; 2540191762Simp noise -= 109; 2541191762Simp return noise; 2542191762Simp} 2543191762Simp 2544191762Simpstatic int 2545191762Simpbwi_rf_calc_noise_bcm2060(struct bwi_mac *mac) 2546191762Simp{ 2547191762Simp /* XXX Dont know how to calc */ 2548191762Simp return (BWI_NOISE_FLOOR); 2549191762Simp} 2550191762Simp 2551191762Simpstatic uint16_t 2552191762Simpbwi_rf_lo_measure_11b(struct bwi_mac *mac) 2553191762Simp{ 2554191762Simp uint16_t val; 2555191762Simp int i; 2556191762Simp 2557191762Simp val = 0; 2558191762Simp for (i = 0; i < 10; ++i) { 2559191762Simp PHY_WRITE(mac, 0x15, 0xafa0); 2560191762Simp DELAY(1); 2561191762Simp PHY_WRITE(mac, 0x15, 0xefa0); 2562191762Simp DELAY(10); 2563191762Simp PHY_WRITE(mac, 0x15, 0xffa0); 2564191762Simp DELAY(40); 2565191762Simp 2566191762Simp val += PHY_READ(mac, 0x2c); 2567191762Simp } 2568191762Simp return val; 2569191762Simp} 2570191762Simp 2571191762Simpstatic void 2572191762Simpbwi_rf_lo_update_11b(struct bwi_mac *mac) 2573191762Simp{ 2574191762Simp struct bwi_softc *sc = mac->mac_sc; 2575191762Simp struct bwi_rf *rf = &mac->mac_rf; 2576191762Simp struct rf_saveregs regs; 2577191762Simp uint16_t rf_val, phy_val, min_val, val; 2578191762Simp uint16_t rf52, bphy_ctrl; 2579191762Simp int i; 2580191762Simp 2581191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__); 2582191762Simp 2583191762Simp bzero(®s, sizeof(regs)); 2584191762Simp bphy_ctrl = 0; 2585191762Simp 2586191762Simp /* 2587191762Simp * Save RF/PHY registers for later restoration 2588191762Simp */ 2589191762Simp SAVE_PHY_REG(mac, ®s, 15); 2590191762Simp rf52 = RF_READ(mac, 0x52) & 0xfff0; 2591191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 2592191762Simp SAVE_PHY_REG(mac, ®s, 0a); 2593191762Simp SAVE_PHY_REG(mac, ®s, 2a); 2594191762Simp SAVE_PHY_REG(mac, ®s, 35); 2595191762Simp SAVE_PHY_REG(mac, ®s, 03); 2596191762Simp SAVE_PHY_REG(mac, ®s, 01); 2597191762Simp SAVE_PHY_REG(mac, ®s, 30); 2598191762Simp 2599191762Simp SAVE_RF_REG(mac, ®s, 43); 2600191762Simp SAVE_RF_REG(mac, ®s, 7a); 2601191762Simp 2602191762Simp bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL); 2603191762Simp 2604191762Simp SAVE_RF_REG(mac, ®s, 52); 2605191762Simp regs.rf_52 &= 0xf0; 2606191762Simp 2607191762Simp PHY_WRITE(mac, 0x30, 0xff); 2608191762Simp CSR_WRITE_2(sc, BWI_PHY_CTRL, 0x3f3f); 2609191762Simp PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f); 2610191762Simp RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0); 2611191762Simp } 2612191762Simp 2613191762Simp PHY_WRITE(mac, 0x15, 0xb000); 2614191762Simp 2615191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 2616191762Simp PHY_WRITE(mac, 0x2b, 0x203); 2617191762Simp PHY_WRITE(mac, 0x2a, 0x8a3); 2618191762Simp } else { 2619191762Simp PHY_WRITE(mac, 0x2b, 0x1402); 2620191762Simp } 2621191762Simp 2622191762Simp /* 2623191762Simp * Setup RF signal 2624191762Simp */ 2625191762Simp rf_val = 0; 2626191762Simp min_val = UINT16_MAX; 2627191762Simp 2628191762Simp for (i = 0; i < 4; ++i) { 2629191762Simp RF_WRITE(mac, 0x52, rf52 | i); 2630191762Simp bwi_rf_lo_measure_11b(mac); /* Ignore return value */ 2631191762Simp } 2632191762Simp for (i = 0; i < 10; ++i) { 2633191762Simp RF_WRITE(mac, 0x52, rf52 | i); 2634191762Simp 2635191762Simp val = bwi_rf_lo_measure_11b(mac) / 10; 2636191762Simp if (val < min_val) { 2637191762Simp min_val = val; 2638191762Simp rf_val = i; 2639191762Simp } 2640191762Simp } 2641191762Simp RF_WRITE(mac, 0x52, rf52 | rf_val); 2642191762Simp 2643191762Simp /* 2644191762Simp * Setup PHY signal 2645191762Simp */ 2646191762Simp phy_val = 0; 2647191762Simp min_val = UINT16_MAX; 2648191762Simp 2649191762Simp for (i = -4; i < 5; i += 2) { 2650191762Simp int j; 2651191762Simp 2652191762Simp for (j = -4; j < 5; j += 2) { 2653191762Simp uint16_t phy2f; 2654191762Simp 2655191762Simp phy2f = (0x100 * i) + j; 2656191762Simp if (j < 0) 2657191762Simp phy2f += 0x100; 2658191762Simp PHY_WRITE(mac, 0x2f, phy2f); 2659191762Simp 2660191762Simp val = bwi_rf_lo_measure_11b(mac) / 10; 2661191762Simp if (val < min_val) { 2662191762Simp min_val = val; 2663191762Simp phy_val = phy2f; 2664191762Simp } 2665191762Simp } 2666191762Simp } 2667191762Simp PHY_WRITE(mac, 0x2f, phy_val + 0x101); 2668191762Simp 2669191762Simp /* 2670191762Simp * Restore saved RF/PHY registers 2671191762Simp */ 2672191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 2673191762Simp RESTORE_PHY_REG(mac, ®s, 0a); 2674191762Simp RESTORE_PHY_REG(mac, ®s, 2a); 2675191762Simp RESTORE_PHY_REG(mac, ®s, 35); 2676191762Simp RESTORE_PHY_REG(mac, ®s, 03); 2677191762Simp RESTORE_PHY_REG(mac, ®s, 01); 2678191762Simp RESTORE_PHY_REG(mac, ®s, 30); 2679191762Simp 2680191762Simp RESTORE_RF_REG(mac, ®s, 43); 2681191762Simp RESTORE_RF_REG(mac, ®s, 7a); 2682191762Simp 2683191762Simp RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52); 2684191762Simp 2685191762Simp CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl); 2686191762Simp } 2687191762Simp RESTORE_PHY_REG(mac, ®s, 15); 2688191762Simp 2689191762Simp bwi_rf_work_around(mac, rf->rf_curchan); 2690191762Simp} 2691