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