bwirf.c revision 287197
1191762Simp/* 2191762Simp * Copyright (c) 2007 The DragonFly Project. All rights reserved. 3191762Simp * 4191762Simp * This code is derived from software contributed to The DragonFly Project 5191762Simp * by Sepherosa Ziehau <sepherosa@gmail.com> 6191762Simp * 7191762Simp * Redistribution and use in source and binary forms, with or without 8191762Simp * modification, are permitted provided that the following conditions 9191762Simp * are met: 10191762Simp * 11191762Simp * 1. Redistributions of source code must retain the above copyright 12191762Simp * notice, this list of conditions and the following disclaimer. 13191762Simp * 2. Redistributions in binary form must reproduce the above copyright 14191762Simp * notice, this list of conditions and the following disclaimer in 15191762Simp * the documentation and/or other materials provided with the 16191762Simp * distribution. 17191762Simp * 3. Neither the name of The DragonFly Project nor the names of its 18191762Simp * contributors may be used to endorse or promote products derived 19191762Simp * from this software without specific, prior written permission. 20191762Simp * 21191762Simp * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22191762Simp * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23191762Simp * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24191762Simp * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25191762Simp * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26191762Simp * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27191762Simp * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28191762Simp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29191762Simp * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30191762Simp * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31191762Simp * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32191762Simp * SUCH DAMAGE. 33191762Simp * 34191762Simp * $DragonFly: src/sys/dev/netif/bwi/bwirf.c,v 1.9 2008/08/21 12:19:33 swildner Exp $ 35191762Simp */ 36191762Simp 37191762Simp#include <sys/cdefs.h> 38191762Simp__FBSDID("$FreeBSD: head/sys/dev/bwi/bwirf.c 287197 2015-08-27 08:56:39Z glebius $"); 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); 1021191762Simp KASSERT(idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0])), 1022191762Simp ("idx %d", idx)); 1023191762Simp 1024191762Simp calib = rf_calibvals[idx] << 1; 1025191762Simp if (val & BWI_RFR_BBP_ATTEN_CALIB_BIT) 1026191762Simp calib |= 0x1; 1027191762Simp calib |= 0x20; 1028191762Simp 1029191762Simp return calib; 1030191762Simp} 1031191762Simp 1032191762Simpstatic __inline int32_t 1033191762Simp_bwi_adjust_devide(int32_t num, int32_t den) 1034191762Simp{ 1035191762Simp if (num < 0) 1036191762Simp return (num / den); 1037191762Simp else 1038191762Simp return (num + den / 2) / den; 1039191762Simp} 1040191762Simp 1041191762Simp/* 1042191762Simp * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table 1043191762Simp * "calculating table entries" 1044191762Simp */ 1045191762Simpstatic int 1046191762Simpbwi_rf_calc_txpower(int8_t *txpwr, uint8_t idx, const int16_t pa_params[]) 1047191762Simp{ 1048191762Simp int32_t m1, m2, f, dbm; 1049191762Simp int i; 1050191762Simp 1051191762Simp m1 = _bwi_adjust_devide(16 * pa_params[0] + idx * pa_params[1], 32); 1052191762Simp m2 = imax(_bwi_adjust_devide(32768 + idx * pa_params[2], 256), 1); 1053191762Simp 1054191762Simp#define ITER_MAX 16 1055191762Simp 1056191762Simp f = 256; 1057191762Simp for (i = 0; i < ITER_MAX; ++i) { 1058191762Simp int32_t q, d; 1059191762Simp 1060191762Simp q = _bwi_adjust_devide( 1061191762Simp f * 4096 - _bwi_adjust_devide(m2 * f, 16) * f, 2048); 1062191762Simp d = abs(q - f); 1063191762Simp f = q; 1064191762Simp 1065191762Simp if (d < 2) 1066191762Simp break; 1067191762Simp } 1068191762Simp if (i == ITER_MAX) 1069191762Simp return EINVAL; 1070191762Simp 1071191762Simp#undef ITER_MAX 1072191762Simp 1073191762Simp dbm = _bwi_adjust_devide(m1 * f, 8192); 1074191762Simp if (dbm < -127) 1075191762Simp dbm = -127; 1076191762Simp else if (dbm > 128) 1077191762Simp dbm = 128; 1078191762Simp 1079191762Simp *txpwr = dbm; 1080191762Simp return 0; 1081191762Simp} 1082191762Simp 1083191762Simpint 1084191762Simpbwi_rf_map_txpower(struct bwi_mac *mac) 1085191762Simp{ 1086191762Simp struct bwi_softc *sc = mac->mac_sc; 1087191762Simp struct bwi_rf *rf = &mac->mac_rf; 1088191762Simp struct bwi_phy *phy = &mac->mac_phy; 1089191762Simp uint16_t sprom_ofs, val, mask; 1090191762Simp int16_t pa_params[3]; 1091191762Simp int error = 0, i, ant_gain, reg_txpower_max; 1092191762Simp 1093191762Simp /* 1094191762Simp * Find out max TX power 1095191762Simp */ 1096191762Simp val = bwi_read_sprom(sc, BWI_SPROM_MAX_TXPWR); 1097191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) { 1098191762Simp rf->rf_txpower_max = __SHIFTOUT(val, 1099191762Simp BWI_SPROM_MAX_TXPWR_MASK_11A); 1100191762Simp } else { 1101191762Simp rf->rf_txpower_max = __SHIFTOUT(val, 1102191762Simp BWI_SPROM_MAX_TXPWR_MASK_11BG); 1103191762Simp 1104191762Simp if ((sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) && 1105191762Simp phy->phy_mode == IEEE80211_MODE_11G) 1106191762Simp rf->rf_txpower_max -= 3; 1107191762Simp } 1108191762Simp if (rf->rf_txpower_max <= 0) { 1109191762Simp device_printf(sc->sc_dev, "invalid max txpower in sprom\n"); 1110191762Simp rf->rf_txpower_max = 74; 1111191762Simp } 1112191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1113191762Simp "max txpower from sprom: %d dBm\n", rf->rf_txpower_max); 1114191762Simp 1115191762Simp /* 1116191762Simp * Find out region/domain max TX power, which is adjusted 1117191762Simp * by antenna gain and 1.5 dBm fluctuation as mentioned 1118191762Simp * in v3 spec. 1119191762Simp */ 1120191762Simp val = bwi_read_sprom(sc, BWI_SPROM_ANT_GAIN); 1121191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) 1122191762Simp ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11A); 1123191762Simp else 1124191762Simp ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11BG); 1125191762Simp if (ant_gain == 0xff) { 1126191762Simp device_printf(sc->sc_dev, "invalid antenna gain in sprom\n"); 1127191762Simp ant_gain = 2; 1128191762Simp } 1129191762Simp ant_gain *= 4; 1130191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1131191762Simp "ant gain %d dBm\n", ant_gain); 1132191762Simp 1133191762Simp reg_txpower_max = 90 - ant_gain - 6; /* XXX magic number */ 1134191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1135191762Simp "region/domain max txpower %d dBm\n", reg_txpower_max); 1136191762Simp 1137191762Simp /* 1138191762Simp * Force max TX power within region/domain TX power limit 1139191762Simp */ 1140191762Simp if (rf->rf_txpower_max > reg_txpower_max) 1141191762Simp rf->rf_txpower_max = reg_txpower_max; 1142191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1143191762Simp "max txpower %d dBm\n", rf->rf_txpower_max); 1144191762Simp 1145191762Simp /* 1146191762Simp * Create TSSI to TX power mapping 1147191762Simp */ 1148191762Simp 1149191762Simp if (sc->sc_bbp_id == BWI_BBPID_BCM4301 && 1150191762Simp rf->rf_type != BWI_RF_T_BCM2050) { 1151191762Simp rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI; 1152191762Simp bcopy(bwi_txpower_map_11b, rf->rf_txpower_map0, 1153191762Simp sizeof(rf->rf_txpower_map0)); 1154191762Simp goto back; 1155191762Simp } 1156191762Simp 1157191762Simp#define IS_VALID_PA_PARAM(p) ((p) != 0 && (p) != -1) 1158191762Simp#define N(arr) (int)(sizeof(arr) / sizeof(arr[0])) 1159191762Simp 1160191762Simp /* 1161191762Simp * Extract PA parameters 1162191762Simp */ 1163191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) 1164191762Simp sprom_ofs = BWI_SPROM_PA_PARAM_11A; 1165191762Simp else 1166191762Simp sprom_ofs = BWI_SPROM_PA_PARAM_11BG; 1167191762Simp for (i = 0; i < N(pa_params); ++i) 1168191762Simp pa_params[i] = (int16_t)bwi_read_sprom(sc, sprom_ofs + (i * 2)); 1169191762Simp 1170191762Simp for (i = 0; i < N(pa_params); ++i) { 1171191762Simp /* 1172191762Simp * If one of the PA parameters from SPROM is not valid, 1173191762Simp * fall back to the default values, if there are any. 1174191762Simp */ 1175191762Simp if (!IS_VALID_PA_PARAM(pa_params[i])) { 1176191762Simp const int8_t *txpower_map; 1177191762Simp 1178191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) { 1179191762Simp device_printf(sc->sc_dev, 1180191762Simp "no tssi2dbm table for 11a PHY\n"); 1181191762Simp return ENXIO; 1182191762Simp } 1183191762Simp 1184191762Simp if (phy->phy_mode == IEEE80211_MODE_11G) { 1185191762Simp DPRINTF(sc, 1186191762Simp BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1187191762Simp "%s\n", "use default 11g TSSI map"); 1188191762Simp txpower_map = bwi_txpower_map_11g; 1189191762Simp } else { 1190191762Simp DPRINTF(sc, 1191191762Simp BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1192191762Simp "%s\n", "use default 11b TSSI map"); 1193191762Simp txpower_map = bwi_txpower_map_11b; 1194191762Simp } 1195191762Simp 1196191762Simp rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI; 1197191762Simp bcopy(txpower_map, rf->rf_txpower_map0, 1198191762Simp sizeof(rf->rf_txpower_map0)); 1199191762Simp goto back; 1200191762Simp } 1201191762Simp } 1202191762Simp 1203191762Simp#undef N 1204191762Simp 1205191762Simp /* 1206191762Simp * All of the PA parameters from SPROM are valid. 1207191762Simp */ 1208191762Simp 1209191762Simp /* 1210191762Simp * Extract idle TSSI from SPROM. 1211191762Simp */ 1212191762Simp val = bwi_read_sprom(sc, BWI_SPROM_IDLE_TSSI); 1213191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1214191762Simp "sprom idle tssi: 0x%04x\n", val); 1215191762Simp 1216191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) 1217191762Simp mask = BWI_SPROM_IDLE_TSSI_MASK_11A; 1218191762Simp else 1219191762Simp mask = BWI_SPROM_IDLE_TSSI_MASK_11BG; 1220191762Simp 1221191762Simp rf->rf_idle_tssi0 = (int)__SHIFTOUT(val, mask); 1222191762Simp if (!IS_VALID_PA_PARAM(rf->rf_idle_tssi0)) 1223191762Simp rf->rf_idle_tssi0 = 62; 1224191762Simp 1225191762Simp#undef IS_VALID_PA_PARAM 1226191762Simp 1227191762Simp /* 1228191762Simp * Calculate TX power map, which is indexed by TSSI 1229191762Simp */ 1230191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, 1231191762Simp "%s\n", "TSSI-TX power map:"); 1232191762Simp for (i = 0; i < BWI_TSSI_MAX; ++i) { 1233191762Simp error = bwi_rf_calc_txpower(&rf->rf_txpower_map0[i], i, 1234191762Simp pa_params); 1235191762Simp if (error) { 1236191762Simp device_printf(sc->sc_dev, 1237191762Simp "bwi_rf_calc_txpower failed\n"); 1238191762Simp break; 1239191762Simp } 1240191762Simp 1241191762Simp#ifdef BWI_DEBUG 1242191762Simp if (i != 0 && i % 8 == 0) { 1243191762Simp _DPRINTF(sc, 1244191762Simp BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, 1245191762Simp "%s\n", ""); 1246191762Simp } 1247191762Simp#endif 1248191762Simp _DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, 1249191762Simp "%d ", rf->rf_txpower_map0[i]); 1250191762Simp } 1251191762Simp _DPRINTF(sc, BWI_DBG_RF | BWI_DBG_ATTACH | BWI_DBG_TXPOWER, 1252191762Simp "%s\n", ""); 1253191762Simpback: 1254191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH, 1255191762Simp "idle tssi0: %d\n", rf->rf_idle_tssi0); 1256191762Simp return error; 1257191762Simp} 1258191762Simp 1259191762Simpstatic void 1260191762Simpbwi_rf_lo_update_11g(struct bwi_mac *mac) 1261191762Simp{ 1262191762Simp struct bwi_softc *sc = mac->mac_sc; 1263191762Simp struct bwi_rf *rf = &mac->mac_rf; 1264191762Simp struct bwi_phy *phy = &mac->mac_phy; 1265191762Simp struct bwi_tpctl *tpctl = &mac->mac_tpctl; 1266191762Simp struct rf_saveregs regs; 1267191762Simp uint16_t ant_div, chan_ex; 1268191762Simp uint8_t devi_ctrl; 1269191762Simp u_int orig_chan; 1270191762Simp 1271191762Simp /* 1272191762Simp * Save RF/PHY registers for later restoration 1273191762Simp */ 1274191762Simp orig_chan = rf->rf_curchan; 1275191762Simp bzero(®s, sizeof(regs)); 1276191762Simp 1277191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1278191762Simp SAVE_PHY_REG(mac, ®s, 429); 1279191762Simp SAVE_PHY_REG(mac, ®s, 802); 1280191762Simp 1281191762Simp PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff); 1282191762Simp PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc); 1283191762Simp } 1284191762Simp 1285191762Simp ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); 1286191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div | 0x8000); 1287191762Simp chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); 1288191762Simp 1289191762Simp SAVE_PHY_REG(mac, ®s, 15); 1290191762Simp SAVE_PHY_REG(mac, ®s, 2a); 1291191762Simp SAVE_PHY_REG(mac, ®s, 35); 1292191762Simp SAVE_PHY_REG(mac, ®s, 60); 1293191762Simp SAVE_RF_REG(mac, ®s, 43); 1294191762Simp SAVE_RF_REG(mac, ®s, 7a); 1295191762Simp SAVE_RF_REG(mac, ®s, 52); 1296191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1297191762Simp SAVE_PHY_REG(mac, ®s, 811); 1298191762Simp SAVE_PHY_REG(mac, ®s, 812); 1299191762Simp SAVE_PHY_REG(mac, ®s, 814); 1300191762Simp SAVE_PHY_REG(mac, ®s, 815); 1301191762Simp } 1302191762Simp 1303191762Simp /* Force to channel 6 */ 1304191762Simp bwi_rf_set_chan(mac, 6, 0); 1305191762Simp 1306191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1307191762Simp PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff); 1308191762Simp PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc); 1309191762Simp bwi_mac_dummy_xmit(mac); 1310191762Simp } 1311191762Simp RF_WRITE(mac, 0x43, 0x6); 1312191762Simp 1313191762Simp bwi_phy_set_bbp_atten(mac, 2); 1314191762Simp 1315191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0); 1316191762Simp 1317191762Simp PHY_WRITE(mac, 0x2e, 0x7f); 1318191762Simp PHY_WRITE(mac, 0x80f, 0x78); 1319191762Simp PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f); 1320191762Simp RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0); 1321191762Simp PHY_WRITE(mac, 0x2b, 0x203); 1322191762Simp PHY_WRITE(mac, 0x2a, 0x8a3); 1323191762Simp 1324191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1325191762Simp PHY_WRITE(mac, 0x814, regs.phy_814 | 0x3); 1326191762Simp PHY_WRITE(mac, 0x815, regs.phy_815 & 0xfffc); 1327191762Simp PHY_WRITE(mac, 0x811, 0x1b3); 1328191762Simp PHY_WRITE(mac, 0x812, 0xb2); 1329191762Simp } 1330191762Simp 1331287197Sglebius if ((sc->sc_flags & BWI_F_RUNNING) == 0) 1332191762Simp tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac); 1333191762Simp PHY_WRITE(mac, 0x80f, 0x8078); 1334191762Simp 1335191762Simp /* 1336191762Simp * Measure all RF LO 1337191762Simp */ 1338191762Simp devi_ctrl = _bwi_rf_lo_update_11g(mac, regs.rf_7a); 1339191762Simp 1340191762Simp /* 1341191762Simp * Restore saved RF/PHY registers 1342191762Simp */ 1343191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1344191762Simp PHY_WRITE(mac, 0x15, 0xe300); 1345191762Simp PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa0); 1346191762Simp DELAY(5); 1347191762Simp PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa2); 1348191762Simp DELAY(2); 1349191762Simp PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa3); 1350191762Simp } else { 1351191762Simp PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0); 1352191762Simp } 1353191762Simp 1354287197Sglebius if ((sc->sc_flags & BWI_F_RUNNING) == 0) 1355191762Simp tpctl = NULL; 1356191762Simp bwi_rf_lo_adjust(mac, tpctl); 1357191762Simp 1358191762Simp PHY_WRITE(mac, 0x2e, 0x807f); 1359191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) 1360191762Simp PHY_WRITE(mac, 0x2f, 0x202); 1361191762Simp else 1362191762Simp PHY_WRITE(mac, 0x2f, 0x101); 1363191762Simp 1364191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); 1365191762Simp 1366191762Simp RESTORE_PHY_REG(mac, ®s, 15); 1367191762Simp RESTORE_PHY_REG(mac, ®s, 2a); 1368191762Simp RESTORE_PHY_REG(mac, ®s, 35); 1369191762Simp RESTORE_PHY_REG(mac, ®s, 60); 1370191762Simp 1371191762Simp RESTORE_RF_REG(mac, ®s, 43); 1372191762Simp RESTORE_RF_REG(mac, ®s, 7a); 1373191762Simp 1374191762Simp regs.rf_52 &= 0xf0; 1375191762Simp regs.rf_52 |= (RF_READ(mac, 0x52) & 0xf); 1376191762Simp RF_WRITE(mac, 0x52, regs.rf_52); 1377191762Simp 1378191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); 1379191762Simp 1380191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1381191762Simp RESTORE_PHY_REG(mac, ®s, 811); 1382191762Simp RESTORE_PHY_REG(mac, ®s, 812); 1383191762Simp RESTORE_PHY_REG(mac, ®s, 814); 1384191762Simp RESTORE_PHY_REG(mac, ®s, 815); 1385191762Simp RESTORE_PHY_REG(mac, ®s, 429); 1386191762Simp RESTORE_PHY_REG(mac, ®s, 802); 1387191762Simp } 1388191762Simp 1389191762Simp bwi_rf_set_chan(mac, orig_chan, 1); 1390191762Simp} 1391191762Simp 1392191762Simpstatic uint32_t 1393191762Simpbwi_rf_lo_devi_measure(struct bwi_mac *mac, uint16_t ctrl) 1394191762Simp{ 1395191762Simp struct bwi_phy *phy = &mac->mac_phy; 1396191762Simp uint32_t devi = 0; 1397191762Simp int i; 1398191762Simp 1399191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) 1400191762Simp ctrl <<= 8; 1401191762Simp 1402191762Simp for (i = 0; i < 8; ++i) { 1403191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) { 1404191762Simp PHY_WRITE(mac, 0x15, 0xe300); 1405191762Simp PHY_WRITE(mac, 0x812, ctrl | 0xb0); 1406191762Simp DELAY(5); 1407191762Simp PHY_WRITE(mac, 0x812, ctrl | 0xb2); 1408191762Simp DELAY(2); 1409191762Simp PHY_WRITE(mac, 0x812, ctrl | 0xb3); 1410191762Simp DELAY(4); 1411191762Simp PHY_WRITE(mac, 0x15, 0xf300); 1412191762Simp } else { 1413191762Simp PHY_WRITE(mac, 0x15, ctrl | 0xefa0); 1414191762Simp DELAY(2); 1415191762Simp PHY_WRITE(mac, 0x15, ctrl | 0xefe0); 1416191762Simp DELAY(4); 1417191762Simp PHY_WRITE(mac, 0x15, ctrl | 0xffe0); 1418191762Simp } 1419191762Simp DELAY(8); 1420191762Simp devi += PHY_READ(mac, 0x2d); 1421191762Simp } 1422191762Simp return devi; 1423191762Simp} 1424191762Simp 1425191762Simpstatic uint16_t 1426191762Simpbwi_rf_get_tp_ctrl2(struct bwi_mac *mac) 1427191762Simp{ 1428191762Simp uint32_t devi_min; 1429191762Simp uint16_t tp_ctrl2 = 0; 1430191762Simp int i; 1431191762Simp 1432191762Simp RF_WRITE(mac, 0x52, 0); 1433191762Simp DELAY(10); 1434191762Simp devi_min = bwi_rf_lo_devi_measure(mac, 0); 1435191762Simp 1436191762Simp for (i = 0; i < 16; ++i) { 1437191762Simp uint32_t devi; 1438191762Simp 1439191762Simp RF_WRITE(mac, 0x52, i); 1440191762Simp DELAY(10); 1441191762Simp devi = bwi_rf_lo_devi_measure(mac, 0); 1442191762Simp 1443191762Simp if (devi < devi_min) { 1444191762Simp devi_min = devi; 1445191762Simp tp_ctrl2 = i; 1446191762Simp } 1447191762Simp } 1448191762Simp return tp_ctrl2; 1449191762Simp} 1450191762Simp 1451191762Simpstatic uint8_t 1452191762Simp_bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a) 1453191762Simp{ 1454191762Simp#define RF_ATTEN_LISTSZ 14 1455191762Simp#define BBP_ATTEN_MAX 4 /* half */ 1456191762Simp 1457191762Simp static const int rf_atten_list[RF_ATTEN_LISTSZ] = 1458191762Simp { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 1, 2, 3, 4 }; 1459191762Simp static const int rf_atten_init_list[RF_ATTEN_LISTSZ] = 1460191762Simp { 0, 3, 1, 5, 7, 3, 2, 0, 4, 6, -1, -1, -1, -1 }; 1461191762Simp static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] = 1462191762Simp { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 }; 1463191762Simp 1464287197Sglebius struct bwi_softc *sc = mac->mac_sc; 1465191762Simp struct bwi_rf_lo lo_save, *lo; 1466191762Simp uint8_t devi_ctrl = 0; 1467191762Simp int idx, adj_rf7a = 0; 1468191762Simp 1469191762Simp bzero(&lo_save, sizeof(lo_save)); 1470191762Simp for (idx = 0; idx < RF_ATTEN_LISTSZ; ++idx) { 1471191762Simp int init_rf_atten = rf_atten_init_list[idx]; 1472191762Simp int rf_atten = rf_atten_list[idx]; 1473191762Simp int bbp_atten; 1474191762Simp 1475191762Simp for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) { 1476191762Simp uint16_t tp_ctrl2, rf7a; 1477191762Simp 1478287197Sglebius if ((sc->sc_flags & BWI_F_RUNNING) == 0) { 1479191762Simp if (idx == 0) { 1480191762Simp bzero(&lo_save, sizeof(lo_save)); 1481191762Simp } else if (init_rf_atten < 0) { 1482191762Simp lo = bwi_get_rf_lo(mac, 1483191762Simp rf_atten, 2 * bbp_atten); 1484191762Simp bcopy(lo, &lo_save, sizeof(lo_save)); 1485191762Simp } else { 1486191762Simp lo = bwi_get_rf_lo(mac, 1487191762Simp init_rf_atten, 0); 1488191762Simp bcopy(lo, &lo_save, sizeof(lo_save)); 1489191762Simp } 1490191762Simp 1491191762Simp devi_ctrl = 0; 1492191762Simp adj_rf7a = 0; 1493191762Simp 1494191762Simp /* 1495191762Simp * XXX 1496191762Simp * Linux driver overflows 'val' 1497191762Simp */ 1498191762Simp if (init_rf_atten >= 0) { 1499191762Simp int val; 1500191762Simp 1501191762Simp val = rf_atten * 2 + bbp_atten; 1502191762Simp if (val > 14) { 1503191762Simp adj_rf7a = 1; 1504191762Simp if (val > 17) 1505191762Simp devi_ctrl = 1; 1506191762Simp if (val > 19) 1507191762Simp devi_ctrl = 2; 1508191762Simp } 1509191762Simp } 1510191762Simp } else { 1511191762Simp lo = bwi_get_rf_lo(mac, 1512191762Simp rf_atten, 2 * bbp_atten); 1513191762Simp if (!bwi_rf_lo_isused(mac, lo)) 1514191762Simp continue; 1515191762Simp bcopy(lo, &lo_save, sizeof(lo_save)); 1516191762Simp 1517191762Simp devi_ctrl = 3; 1518191762Simp adj_rf7a = 0; 1519191762Simp } 1520191762Simp 1521191762Simp RF_WRITE(mac, BWI_RFR_ATTEN, rf_atten); 1522191762Simp 1523191762Simp tp_ctrl2 = mac->mac_tpctl.tp_ctrl2; 1524191762Simp if (init_rf_atten < 0) 1525191762Simp tp_ctrl2 |= (3 << 4); 1526191762Simp RF_WRITE(mac, BWI_RFR_TXPWR, tp_ctrl2); 1527191762Simp 1528191762Simp DELAY(10); 1529191762Simp 1530191762Simp bwi_phy_set_bbp_atten(mac, bbp_atten * 2); 1531191762Simp 1532191762Simp rf7a = orig_rf7a & 0xfff0; 1533191762Simp if (adj_rf7a) 1534191762Simp rf7a |= 0x8; 1535191762Simp RF_WRITE(mac, 0x7a, rf7a); 1536191762Simp 1537191762Simp lo = bwi_get_rf_lo(mac, 1538191762Simp rf_lo_measure_order[idx], bbp_atten * 2); 1539191762Simp bwi_rf_lo_measure_11g(mac, &lo_save, lo, devi_ctrl); 1540191762Simp } 1541191762Simp } 1542191762Simp return devi_ctrl; 1543191762Simp 1544191762Simp#undef RF_ATTEN_LISTSZ 1545191762Simp#undef BBP_ATTEN_MAX 1546191762Simp} 1547191762Simp 1548191762Simpstatic void 1549191762Simpbwi_rf_lo_measure_11g(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo, 1550191762Simp struct bwi_rf_lo *dst_lo, uint8_t devi_ctrl) 1551191762Simp{ 1552191762Simp#define LO_ADJUST_MIN 1 1553191762Simp#define LO_ADJUST_MAX 8 1554191762Simp#define LO_ADJUST(hi, lo) { .ctrl_hi = hi, .ctrl_lo = lo } 1555191762Simp static const struct bwi_rf_lo rf_lo_adjust[LO_ADJUST_MAX] = { 1556191762Simp LO_ADJUST(1, 1), 1557191762Simp LO_ADJUST(1, 0), 1558191762Simp LO_ADJUST(1, -1), 1559191762Simp LO_ADJUST(0, -1), 1560191762Simp LO_ADJUST(-1, -1), 1561191762Simp LO_ADJUST(-1, 0), 1562191762Simp LO_ADJUST(-1, 1), 1563191762Simp LO_ADJUST(0, 1) 1564191762Simp }; 1565191762Simp#undef LO_ADJUST 1566191762Simp 1567191762Simp struct bwi_rf_lo lo_min; 1568191762Simp uint32_t devi_min; 1569191762Simp int found, loop_count, adjust_state; 1570191762Simp 1571191762Simp bcopy(src_lo, &lo_min, sizeof(lo_min)); 1572191762Simp RF_LO_WRITE(mac, &lo_min); 1573191762Simp devi_min = bwi_rf_lo_devi_measure(mac, devi_ctrl); 1574191762Simp 1575191762Simp loop_count = 12; /* XXX */ 1576191762Simp adjust_state = 0; 1577191762Simp do { 1578191762Simp struct bwi_rf_lo lo_base; 1579191762Simp int i, fin; 1580191762Simp 1581191762Simp found = 0; 1582191762Simp if (adjust_state == 0) { 1583191762Simp i = LO_ADJUST_MIN; 1584191762Simp fin = LO_ADJUST_MAX; 1585191762Simp } else if (adjust_state % 2 == 0) { 1586191762Simp i = adjust_state - 1; 1587191762Simp fin = adjust_state + 1; 1588191762Simp } else { 1589191762Simp i = adjust_state - 2; 1590191762Simp fin = adjust_state + 2; 1591191762Simp } 1592191762Simp 1593191762Simp if (i < LO_ADJUST_MIN) 1594191762Simp i += LO_ADJUST_MAX; 1595191762Simp KASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN, ("i %d", i)); 1596191762Simp 1597191762Simp if (fin > LO_ADJUST_MAX) 1598191762Simp fin -= LO_ADJUST_MAX; 1599191762Simp KASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN, 1600191762Simp ("fin %d", fin)); 1601191762Simp 1602191762Simp bcopy(&lo_min, &lo_base, sizeof(lo_base)); 1603191762Simp for (;;) { 1604191762Simp struct bwi_rf_lo lo; 1605191762Simp 1606191762Simp lo.ctrl_hi = lo_base.ctrl_hi + 1607191762Simp rf_lo_adjust[i - 1].ctrl_hi; 1608191762Simp lo.ctrl_lo = lo_base.ctrl_lo + 1609191762Simp rf_lo_adjust[i - 1].ctrl_lo; 1610191762Simp 1611191762Simp if (abs(lo.ctrl_lo) < 9 && abs(lo.ctrl_hi) < 9) { 1612191762Simp uint32_t devi; 1613191762Simp 1614191762Simp RF_LO_WRITE(mac, &lo); 1615191762Simp devi = bwi_rf_lo_devi_measure(mac, devi_ctrl); 1616191762Simp if (devi < devi_min) { 1617191762Simp devi_min = devi; 1618191762Simp adjust_state = i; 1619191762Simp found = 1; 1620191762Simp bcopy(&lo, &lo_min, sizeof(lo_min)); 1621191762Simp } 1622191762Simp } 1623191762Simp if (i == fin) 1624191762Simp break; 1625191762Simp if (i == LO_ADJUST_MAX) 1626191762Simp i = LO_ADJUST_MIN; 1627191762Simp else 1628191762Simp ++i; 1629191762Simp } 1630191762Simp } while (loop_count-- && found); 1631191762Simp 1632191762Simp bcopy(&lo_min, dst_lo, sizeof(*dst_lo)); 1633191762Simp 1634191762Simp#undef LO_ADJUST_MIN 1635191762Simp#undef LO_ADJUST_MAX 1636191762Simp} 1637191762Simp 1638191762Simpstatic void 1639191762Simpbwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac) 1640191762Simp{ 1641191762Simp#define SAVE_RF_MAX 3 1642191762Simp#define SAVE_PHY_MAX 8 1643191762Simp 1644191762Simp static const uint16_t save_rf_regs[SAVE_RF_MAX] = 1645191762Simp { 0x7a, 0x52, 0x43 }; 1646191762Simp static const uint16_t save_phy_regs[SAVE_PHY_MAX] = 1647191762Simp { 0x30, 0x26, 0x15, 0x2a, 0x20, 0x5a, 0x59, 0x58 }; 1648191762Simp 1649191762Simp struct bwi_softc *sc = mac->mac_sc; 1650191762Simp struct bwi_rf *rf = &mac->mac_rf; 1651191762Simp struct bwi_phy *phy = &mac->mac_phy; 1652191762Simp uint16_t save_rf[SAVE_RF_MAX]; 1653191762Simp uint16_t save_phy[SAVE_PHY_MAX]; 1654191762Simp uint16_t ant_div, bbp_atten, chan_ex; 1655191762Simp int16_t nrssi[2]; 1656191762Simp int i; 1657191762Simp 1658191762Simp /* 1659191762Simp * Save RF/PHY registers for later restoration 1660191762Simp */ 1661191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 1662191762Simp save_rf[i] = RF_READ(mac, save_rf_regs[i]); 1663191762Simp for (i = 0; i < SAVE_PHY_MAX; ++i) 1664191762Simp save_phy[i] = PHY_READ(mac, save_phy_regs[i]); 1665191762Simp 1666191762Simp ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); 1667191762Simp bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN); 1668191762Simp chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); 1669191762Simp 1670191762Simp /* 1671191762Simp * Calculate nrssi0 1672191762Simp */ 1673191762Simp if (phy->phy_rev >= 5) 1674191762Simp RF_CLRBITS(mac, 0x7a, 0xff80); 1675191762Simp else 1676191762Simp RF_CLRBITS(mac, 0x7a, 0xfff0); 1677191762Simp PHY_WRITE(mac, 0x30, 0xff); 1678191762Simp 1679191762Simp CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x7f7f); 1680191762Simp 1681191762Simp PHY_WRITE(mac, 0x26, 0); 1682191762Simp PHY_SETBITS(mac, 0x15, 0x20); 1683191762Simp PHY_WRITE(mac, 0x2a, 0x8a3); 1684191762Simp RF_SETBITS(mac, 0x7a, 0x80); 1685191762Simp 1686191762Simp nrssi[0] = (int16_t)PHY_READ(mac, 0x27); 1687191762Simp 1688191762Simp /* 1689191762Simp * Calculate nrssi1 1690191762Simp */ 1691191762Simp RF_CLRBITS(mac, 0x7a, 0xff80); 1692191762Simp if (phy->phy_version >= 2) 1693191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x40); 1694191762Simp else if (phy->phy_version == 0) 1695191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122); 1696191762Simp else 1697191762Simp CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0xdfff); 1698191762Simp 1699191762Simp PHY_WRITE(mac, 0x20, 0x3f3f); 1700191762Simp PHY_WRITE(mac, 0x15, 0xf330); 1701191762Simp 1702191762Simp RF_WRITE(mac, 0x5a, 0x60); 1703191762Simp RF_CLRBITS(mac, 0x43, 0xff0f); 1704191762Simp 1705191762Simp PHY_WRITE(mac, 0x5a, 0x480); 1706191762Simp PHY_WRITE(mac, 0x59, 0x810); 1707191762Simp PHY_WRITE(mac, 0x58, 0xd); 1708191762Simp 1709191762Simp DELAY(20); 1710191762Simp 1711191762Simp nrssi[1] = (int16_t)PHY_READ(mac, 0x27); 1712191762Simp 1713191762Simp /* 1714191762Simp * Restore saved RF/PHY registers 1715191762Simp */ 1716191762Simp PHY_WRITE(mac, save_phy_regs[0], save_phy[0]); 1717191762Simp RF_WRITE(mac, save_rf_regs[0], save_rf[0]); 1718191762Simp 1719191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); 1720191762Simp 1721191762Simp for (i = 1; i < 4; ++i) 1722191762Simp PHY_WRITE(mac, save_phy_regs[i], save_phy[i]); 1723191762Simp 1724191762Simp bwi_rf_work_around(mac, rf->rf_curchan); 1725191762Simp 1726191762Simp if (phy->phy_version != 0) 1727191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); 1728191762Simp 1729191762Simp for (; i < SAVE_PHY_MAX; ++i) 1730191762Simp PHY_WRITE(mac, save_phy_regs[i], save_phy[i]); 1731191762Simp 1732191762Simp for (i = 1; i < SAVE_RF_MAX; ++i) 1733191762Simp RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 1734191762Simp 1735191762Simp /* 1736191762Simp * Install calculated narrow RSSI values 1737191762Simp */ 1738191762Simp if (nrssi[0] == nrssi[1]) 1739191762Simp rf->rf_nrssi_slope = 0x10000; 1740191762Simp else 1741191762Simp rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]); 1742191762Simp if (nrssi[0] <= -4) { 1743191762Simp rf->rf_nrssi[0] = nrssi[0]; 1744191762Simp rf->rf_nrssi[1] = nrssi[1]; 1745191762Simp } 1746191762Simp 1747191762Simp#undef SAVE_RF_MAX 1748191762Simp#undef SAVE_PHY_MAX 1749191762Simp} 1750191762Simp 1751191762Simpstatic void 1752191762Simpbwi_rf_set_nrssi_ofs_11g(struct bwi_mac *mac) 1753191762Simp{ 1754191762Simp#define SAVE_RF_MAX 2 1755191762Simp#define SAVE_PHY_COMM_MAX 10 1756191762Simp#define SAVE_PHY6_MAX 8 1757191762Simp 1758191762Simp static const uint16_t save_rf_regs[SAVE_RF_MAX] = 1759191762Simp { 0x7a, 0x43 }; 1760191762Simp static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = { 1761191762Simp 0x0001, 0x0811, 0x0812, 0x0814, 1762191762Simp 0x0815, 0x005a, 0x0059, 0x0058, 1763191762Simp 0x000a, 0x0003 1764191762Simp }; 1765191762Simp static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = { 1766191762Simp 0x002e, 0x002f, 0x080f, 0x0810, 1767191762Simp 0x0801, 0x0060, 0x0014, 0x0478 1768191762Simp }; 1769191762Simp 1770191762Simp struct bwi_phy *phy = &mac->mac_phy; 1771191762Simp uint16_t save_rf[SAVE_RF_MAX]; 1772191762Simp uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 1773191762Simp uint16_t save_phy6[SAVE_PHY6_MAX]; 1774191762Simp uint16_t rf7b = 0xffff; 1775191762Simp int16_t nrssi; 1776191762Simp int i, phy6_idx = 0; 1777191762Simp 1778191762Simp for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 1779191762Simp save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]); 1780191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 1781191762Simp save_rf[i] = RF_READ(mac, save_rf_regs[i]); 1782191762Simp 1783191762Simp PHY_CLRBITS(mac, 0x429, 0x8000); 1784191762Simp PHY_FILT_SETBITS(mac, 0x1, 0x3fff, 0x4000); 1785191762Simp PHY_SETBITS(mac, 0x811, 0xc); 1786191762Simp PHY_FILT_SETBITS(mac, 0x812, 0xfff3, 0x4); 1787191762Simp PHY_CLRBITS(mac, 0x802, 0x3); 1788191762Simp 1789191762Simp if (phy->phy_rev >= 6) { 1790191762Simp for (i = 0; i < SAVE_PHY6_MAX; ++i) 1791191762Simp save_phy6[i] = PHY_READ(mac, save_phy6_regs[i]); 1792191762Simp 1793191762Simp PHY_WRITE(mac, 0x2e, 0); 1794191762Simp PHY_WRITE(mac, 0x2f, 0); 1795191762Simp PHY_WRITE(mac, 0x80f, 0); 1796191762Simp PHY_WRITE(mac, 0x810, 0); 1797191762Simp PHY_SETBITS(mac, 0x478, 0x100); 1798191762Simp PHY_SETBITS(mac, 0x801, 0x40); 1799191762Simp PHY_SETBITS(mac, 0x60, 0x40); 1800191762Simp PHY_SETBITS(mac, 0x14, 0x200); 1801191762Simp } 1802191762Simp 1803191762Simp RF_SETBITS(mac, 0x7a, 0x70); 1804191762Simp RF_SETBITS(mac, 0x7a, 0x80); 1805191762Simp 1806191762Simp DELAY(30); 1807191762Simp 1808191762Simp nrssi = bwi_nrssi_11g(mac); 1809191762Simp if (nrssi == 31) { 1810191762Simp for (i = 7; i >= 4; --i) { 1811191762Simp RF_WRITE(mac, 0x7b, i); 1812191762Simp DELAY(20); 1813191762Simp nrssi = bwi_nrssi_11g(mac); 1814191762Simp if (nrssi < 31 && rf7b == 0xffff) 1815191762Simp rf7b = i; 1816191762Simp } 1817191762Simp if (rf7b == 0xffff) 1818191762Simp rf7b = 4; 1819191762Simp } else { 1820191762Simp struct bwi_gains gains; 1821191762Simp 1822191762Simp RF_CLRBITS(mac, 0x7a, 0xff80); 1823191762Simp 1824191762Simp PHY_SETBITS(mac, 0x814, 0x1); 1825191762Simp PHY_CLRBITS(mac, 0x815, 0x1); 1826191762Simp PHY_SETBITS(mac, 0x811, 0xc); 1827191762Simp PHY_SETBITS(mac, 0x812, 0xc); 1828191762Simp PHY_SETBITS(mac, 0x811, 0x30); 1829191762Simp PHY_SETBITS(mac, 0x812, 0x30); 1830191762Simp PHY_WRITE(mac, 0x5a, 0x480); 1831191762Simp PHY_WRITE(mac, 0x59, 0x810); 1832191762Simp PHY_WRITE(mac, 0x58, 0xd); 1833191762Simp if (phy->phy_version == 0) 1834191762Simp PHY_WRITE(mac, 0x3, 0x122); 1835191762Simp else 1836191762Simp PHY_SETBITS(mac, 0xa, 0x2000); 1837191762Simp PHY_SETBITS(mac, 0x814, 0x4); 1838191762Simp PHY_CLRBITS(mac, 0x815, 0x4); 1839191762Simp PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40); 1840191762Simp RF_SETBITS(mac, 0x7a, 0xf); 1841191762Simp 1842191762Simp bzero(&gains, sizeof(gains)); 1843191762Simp gains.tbl_gain1 = 3; 1844191762Simp gains.tbl_gain2 = 0; 1845191762Simp gains.phy_gain = 1; 1846191762Simp bwi_set_gains(mac, &gains); 1847191762Simp 1848191762Simp RF_FILT_SETBITS(mac, 0x43, 0xf0, 0xf); 1849191762Simp DELAY(30); 1850191762Simp 1851191762Simp nrssi = bwi_nrssi_11g(mac); 1852191762Simp if (nrssi == -32) { 1853191762Simp for (i = 0; i < 4; ++i) { 1854191762Simp RF_WRITE(mac, 0x7b, i); 1855191762Simp DELAY(20); 1856191762Simp nrssi = bwi_nrssi_11g(mac); 1857191762Simp if (nrssi > -31 && rf7b == 0xffff) 1858191762Simp rf7b = i; 1859191762Simp } 1860191762Simp if (rf7b == 0xffff) 1861191762Simp rf7b = 3; 1862191762Simp } else { 1863191762Simp rf7b = 0; 1864191762Simp } 1865191762Simp } 1866191762Simp RF_WRITE(mac, 0x7b, rf7b); 1867191762Simp 1868191762Simp /* 1869191762Simp * Restore saved RF/PHY registers 1870191762Simp */ 1871191762Simp if (phy->phy_rev >= 6) { 1872191762Simp for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) { 1873191762Simp PHY_WRITE(mac, save_phy6_regs[phy6_idx], 1874191762Simp save_phy6[phy6_idx]); 1875191762Simp } 1876191762Simp } 1877191762Simp 1878191762Simp /* Saved PHY registers 0, 1, 2 are handled later */ 1879191762Simp for (i = 3; i < SAVE_PHY_COMM_MAX; ++i) 1880191762Simp PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); 1881191762Simp 1882191762Simp for (i = SAVE_RF_MAX - 1; i >= 0; --i) 1883191762Simp RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 1884191762Simp 1885191762Simp PHY_SETBITS(mac, 0x802, 0x3); 1886191762Simp PHY_SETBITS(mac, 0x429, 0x8000); 1887191762Simp 1888191762Simp bwi_set_gains(mac, NULL); 1889191762Simp 1890191762Simp if (phy->phy_rev >= 6) { 1891191762Simp for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) { 1892191762Simp PHY_WRITE(mac, save_phy6_regs[phy6_idx], 1893191762Simp save_phy6[phy6_idx]); 1894191762Simp } 1895191762Simp } 1896191762Simp 1897191762Simp PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]); 1898191762Simp PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]); 1899191762Simp PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]); 1900191762Simp 1901191762Simp#undef SAVE_RF_MAX 1902191762Simp#undef SAVE_PHY_COMM_MAX 1903191762Simp#undef SAVE_PHY6_MAX 1904191762Simp} 1905191762Simp 1906191762Simpstatic void 1907191762Simpbwi_rf_calc_nrssi_slope_11g(struct bwi_mac *mac) 1908191762Simp{ 1909191762Simp#define SAVE_RF_MAX 3 1910191762Simp#define SAVE_PHY_COMM_MAX 4 1911191762Simp#define SAVE_PHY3_MAX 8 1912191762Simp 1913191762Simp static const uint16_t save_rf_regs[SAVE_RF_MAX] = 1914191762Simp { 0x7a, 0x52, 0x43 }; 1915191762Simp static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = 1916191762Simp { 0x15, 0x5a, 0x59, 0x58 }; 1917191762Simp static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = { 1918191762Simp 0x002e, 0x002f, 0x080f, 0x0810, 1919191762Simp 0x0801, 0x0060, 0x0014, 0x0478 1920191762Simp }; 1921191762Simp 1922191762Simp struct bwi_softc *sc = mac->mac_sc; 1923191762Simp struct bwi_phy *phy = &mac->mac_phy; 1924191762Simp struct bwi_rf *rf = &mac->mac_rf; 1925191762Simp uint16_t save_rf[SAVE_RF_MAX]; 1926191762Simp uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 1927191762Simp uint16_t save_phy3[SAVE_PHY3_MAX]; 1928191762Simp uint16_t ant_div, bbp_atten, chan_ex; 1929191762Simp struct bwi_gains gains; 1930191762Simp int16_t nrssi[2]; 1931191762Simp int i, phy3_idx = 0; 1932191762Simp 1933191762Simp if (rf->rf_rev >= 9) 1934191762Simp return; 1935191762Simp else if (rf->rf_rev == 8) 1936191762Simp bwi_rf_set_nrssi_ofs_11g(mac); 1937191762Simp 1938191762Simp PHY_CLRBITS(mac, 0x429, 0x8000); 1939191762Simp PHY_CLRBITS(mac, 0x802, 0x3); 1940191762Simp 1941191762Simp /* 1942191762Simp * Save RF/PHY registers for later restoration 1943191762Simp */ 1944191762Simp ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV); 1945191762Simp CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000); 1946191762Simp 1947191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 1948191762Simp save_rf[i] = RF_READ(mac, save_rf_regs[i]); 1949191762Simp for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 1950191762Simp save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]); 1951191762Simp 1952191762Simp bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN); 1953191762Simp chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX); 1954191762Simp 1955191762Simp if (phy->phy_rev >= 3) { 1956191762Simp for (i = 0; i < SAVE_PHY3_MAX; ++i) 1957191762Simp save_phy3[i] = PHY_READ(mac, save_phy3_regs[i]); 1958191762Simp 1959191762Simp PHY_WRITE(mac, 0x2e, 0); 1960191762Simp PHY_WRITE(mac, 0x810, 0); 1961191762Simp 1962191762Simp if (phy->phy_rev == 4 || phy->phy_rev == 6 || 1963191762Simp phy->phy_rev == 7) { 1964191762Simp PHY_SETBITS(mac, 0x478, 0x100); 1965191762Simp PHY_SETBITS(mac, 0x810, 0x40); 1966191762Simp } else if (phy->phy_rev == 3 || phy->phy_rev == 5) { 1967191762Simp PHY_CLRBITS(mac, 0x810, 0x40); 1968191762Simp } 1969191762Simp 1970191762Simp PHY_SETBITS(mac, 0x60, 0x40); 1971191762Simp PHY_SETBITS(mac, 0x14, 0x200); 1972191762Simp } 1973191762Simp 1974191762Simp /* 1975191762Simp * Calculate nrssi0 1976191762Simp */ 1977191762Simp RF_SETBITS(mac, 0x7a, 0x70); 1978191762Simp 1979191762Simp bzero(&gains, sizeof(gains)); 1980191762Simp gains.tbl_gain1 = 0; 1981191762Simp gains.tbl_gain2 = 8; 1982191762Simp gains.phy_gain = 0; 1983191762Simp bwi_set_gains(mac, &gains); 1984191762Simp 1985191762Simp RF_CLRBITS(mac, 0x7a, 0xff08); 1986191762Simp if (phy->phy_rev >= 2) { 1987191762Simp PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x30); 1988191762Simp PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10); 1989191762Simp } 1990191762Simp 1991191762Simp RF_SETBITS(mac, 0x7a, 0x80); 1992191762Simp DELAY(20); 1993191762Simp nrssi[0] = bwi_nrssi_11g(mac); 1994191762Simp 1995191762Simp /* 1996191762Simp * Calculate nrssi1 1997191762Simp */ 1998191762Simp RF_CLRBITS(mac, 0x7a, 0xff80); 1999191762Simp if (phy->phy_version >= 2) 2000191762Simp PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40); 2001191762Simp CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000); 2002191762Simp 2003191762Simp RF_SETBITS(mac, 0x7a, 0xf); 2004191762Simp PHY_WRITE(mac, 0x15, 0xf330); 2005191762Simp if (phy->phy_rev >= 2) { 2006191762Simp PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x20); 2007191762Simp PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x20); 2008191762Simp } 2009191762Simp 2010191762Simp bzero(&gains, sizeof(gains)); 2011191762Simp gains.tbl_gain1 = 3; 2012191762Simp gains.tbl_gain2 = 0; 2013191762Simp gains.phy_gain = 1; 2014191762Simp bwi_set_gains(mac, &gains); 2015191762Simp 2016191762Simp if (rf->rf_rev == 8) { 2017191762Simp RF_WRITE(mac, 0x43, 0x1f); 2018191762Simp } else { 2019191762Simp RF_FILT_SETBITS(mac, 0x52, 0xff0f, 0x60); 2020191762Simp RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9); 2021191762Simp } 2022191762Simp PHY_WRITE(mac, 0x5a, 0x480); 2023191762Simp PHY_WRITE(mac, 0x59, 0x810); 2024191762Simp PHY_WRITE(mac, 0x58, 0xd); 2025191762Simp DELAY(20); 2026191762Simp 2027191762Simp nrssi[1] = bwi_nrssi_11g(mac); 2028191762Simp 2029191762Simp /* 2030191762Simp * Install calculated narrow RSSI values 2031191762Simp */ 2032191762Simp if (nrssi[1] == nrssi[0]) 2033191762Simp rf->rf_nrssi_slope = 0x10000; 2034191762Simp else 2035191762Simp rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]); 2036191762Simp if (nrssi[0] >= -4) { 2037191762Simp rf->rf_nrssi[0] = nrssi[1]; 2038191762Simp rf->rf_nrssi[1] = nrssi[0]; 2039191762Simp } 2040191762Simp 2041191762Simp /* 2042191762Simp * Restore saved RF/PHY registers 2043191762Simp */ 2044191762Simp if (phy->phy_rev >= 3) { 2045191762Simp for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) { 2046191762Simp PHY_WRITE(mac, save_phy3_regs[phy3_idx], 2047191762Simp save_phy3[phy3_idx]); 2048191762Simp } 2049191762Simp } 2050191762Simp if (phy->phy_rev >= 2) { 2051191762Simp PHY_CLRBITS(mac, 0x812, 0x30); 2052191762Simp PHY_CLRBITS(mac, 0x811, 0x30); 2053191762Simp } 2054191762Simp 2055191762Simp for (i = 0; i < SAVE_RF_MAX; ++i) 2056191762Simp RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 2057191762Simp 2058191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div); 2059191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten); 2060191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex); 2061191762Simp 2062191762Simp for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 2063191762Simp PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); 2064191762Simp 2065191762Simp bwi_rf_work_around(mac, rf->rf_curchan); 2066191762Simp PHY_SETBITS(mac, 0x802, 0x3); 2067191762Simp bwi_set_gains(mac, NULL); 2068191762Simp PHY_SETBITS(mac, 0x429, 0x8000); 2069191762Simp 2070191762Simp if (phy->phy_rev >= 3) { 2071191762Simp for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) { 2072191762Simp PHY_WRITE(mac, save_phy3_regs[phy3_idx], 2073191762Simp save_phy3[phy3_idx]); 2074191762Simp } 2075191762Simp } 2076191762Simp 2077191762Simp bwi_rf_init_sw_nrssi_table(mac); 2078191762Simp bwi_rf_set_nrssi_thr_11g(mac); 2079191762Simp 2080191762Simp#undef SAVE_RF_MAX 2081191762Simp#undef SAVE_PHY_COMM_MAX 2082191762Simp#undef SAVE_PHY3_MAX 2083191762Simp} 2084191762Simp 2085191762Simpstatic void 2086191762Simpbwi_rf_init_sw_nrssi_table(struct bwi_mac *mac) 2087191762Simp{ 2088191762Simp struct bwi_rf *rf = &mac->mac_rf; 2089191762Simp int d, i; 2090191762Simp 2091191762Simp d = 0x1f - rf->rf_nrssi[0]; 2092191762Simp for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) { 2093191762Simp int val; 2094191762Simp 2095191762Simp val = (((i - d) * rf->rf_nrssi_slope) / 0x10000) + 0x3a; 2096191762Simp if (val < 0) 2097191762Simp val = 0; 2098191762Simp else if (val > 0x3f) 2099191762Simp val = 0x3f; 2100191762Simp 2101191762Simp rf->rf_nrssi_table[i] = val; 2102191762Simp } 2103191762Simp} 2104191762Simp 2105191762Simpvoid 2106191762Simpbwi_rf_init_hw_nrssi_table(struct bwi_mac *mac, uint16_t adjust) 2107191762Simp{ 2108191762Simp int i; 2109191762Simp 2110191762Simp for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) { 2111191762Simp int16_t val; 2112191762Simp 2113191762Simp val = bwi_nrssi_read(mac, i); 2114191762Simp 2115191762Simp val -= adjust; 2116191762Simp if (val < -32) 2117191762Simp val = -32; 2118191762Simp else if (val > 31) 2119191762Simp val = 31; 2120191762Simp 2121191762Simp bwi_nrssi_write(mac, i, val); 2122191762Simp } 2123191762Simp} 2124191762Simp 2125191762Simpstatic void 2126191762Simpbwi_rf_set_nrssi_thr_11b(struct bwi_mac *mac) 2127191762Simp{ 2128191762Simp struct bwi_rf *rf = &mac->mac_rf; 2129191762Simp int32_t thr; 2130191762Simp 2131191762Simp if (rf->rf_type != BWI_RF_T_BCM2050 || 2132191762Simp (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) 2133191762Simp return; 2134191762Simp 2135191762Simp /* 2136191762Simp * Calculate nrssi threshold 2137191762Simp */ 2138191762Simp if (rf->rf_rev >= 6) { 2139191762Simp thr = (rf->rf_nrssi[1] - rf->rf_nrssi[0]) * 32; 2140191762Simp thr += 20 * (rf->rf_nrssi[0] + 1); 2141191762Simp thr /= 40; 2142191762Simp } else { 2143191762Simp thr = rf->rf_nrssi[1] - 5; 2144191762Simp } 2145191762Simp if (thr < 0) 2146191762Simp thr = 0; 2147191762Simp else if (thr > 0x3e) 2148191762Simp thr = 0x3e; 2149191762Simp 2150191762Simp PHY_READ(mac, BWI_PHYR_NRSSI_THR_11B); /* dummy read */ 2151191762Simp PHY_WRITE(mac, BWI_PHYR_NRSSI_THR_11B, (((uint16_t)thr) << 8) | 0x1c); 2152191762Simp 2153191762Simp if (rf->rf_rev >= 6) { 2154191762Simp PHY_WRITE(mac, 0x87, 0xe0d); 2155191762Simp PHY_WRITE(mac, 0x86, 0xc0b); 2156191762Simp PHY_WRITE(mac, 0x85, 0xa09); 2157191762Simp PHY_WRITE(mac, 0x84, 0x808); 2158191762Simp PHY_WRITE(mac, 0x83, 0x808); 2159191762Simp PHY_WRITE(mac, 0x82, 0x604); 2160191762Simp PHY_WRITE(mac, 0x81, 0x302); 2161191762Simp PHY_WRITE(mac, 0x80, 0x100); 2162191762Simp } 2163191762Simp} 2164191762Simp 2165191762Simpstatic __inline int32_t 2166191762Simp_nrssi_threshold(const struct bwi_rf *rf, int32_t val) 2167191762Simp{ 2168191762Simp val *= (rf->rf_nrssi[1] - rf->rf_nrssi[0]); 2169191762Simp val += (rf->rf_nrssi[0] << 6); 2170191762Simp if (val < 32) 2171191762Simp val += 31; 2172191762Simp else 2173191762Simp val += 32; 2174191762Simp val >>= 6; 2175191762Simp if (val < -31) 2176191762Simp val = -31; 2177191762Simp else if (val > 31) 2178191762Simp val = 31; 2179191762Simp return val; 2180191762Simp} 2181191762Simp 2182191762Simpstatic void 2183191762Simpbwi_rf_set_nrssi_thr_11g(struct bwi_mac *mac) 2184191762Simp{ 2185191762Simp int32_t thr1, thr2; 2186191762Simp uint16_t thr; 2187191762Simp 2188191762Simp /* 2189191762Simp * Find the two nrssi thresholds 2190191762Simp */ 2191191762Simp if ((mac->mac_phy.phy_flags & BWI_PHY_F_LINKED) == 0 || 2192191762Simp (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) { 2193191762Simp int16_t nrssi; 2194191762Simp 2195191762Simp nrssi = bwi_nrssi_read(mac, 0x20); 2196191762Simp if (nrssi >= 32) 2197191762Simp nrssi -= 64; 2198191762Simp 2199191762Simp if (nrssi < 3) { 2200191762Simp thr1 = 0x2b; 2201191762Simp thr2 = 0x27; 2202191762Simp } else { 2203191762Simp thr1 = 0x2d; 2204191762Simp thr2 = 0x2b; 2205191762Simp } 2206191762Simp } else { 2207191762Simp /* TODO Interfere mode */ 2208191762Simp thr1 = _nrssi_threshold(&mac->mac_rf, 0x11); 2209191762Simp thr2 = _nrssi_threshold(&mac->mac_rf, 0xe); 2210191762Simp } 2211191762Simp 2212191762Simp#define NRSSI_THR1_MASK __BITS(5, 0) 2213191762Simp#define NRSSI_THR2_MASK __BITS(11, 6) 2214191762Simp 2215191762Simp thr = __SHIFTIN((uint32_t)thr1, NRSSI_THR1_MASK) | 2216191762Simp __SHIFTIN((uint32_t)thr2, NRSSI_THR2_MASK); 2217191762Simp PHY_FILT_SETBITS(mac, BWI_PHYR_NRSSI_THR_11G, 0xf000, thr); 2218191762Simp 2219191762Simp#undef NRSSI_THR1_MASK 2220191762Simp#undef NRSSI_THR2_MASK 2221191762Simp} 2222191762Simp 2223191762Simpvoid 2224191762Simpbwi_rf_clear_tssi(struct bwi_mac *mac) 2225191762Simp{ 2226191762Simp /* XXX use function pointer */ 2227191762Simp if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) { 2228191762Simp /* TODO:11A */ 2229191762Simp } else { 2230191762Simp uint16_t val; 2231191762Simp int i; 2232191762Simp 2233191762Simp val = __SHIFTIN(BWI_INVALID_TSSI, BWI_LO_TSSI_MASK) | 2234191762Simp __SHIFTIN(BWI_INVALID_TSSI, BWI_HI_TSSI_MASK); 2235191762Simp 2236191762Simp for (i = 0; i < 2; ++i) { 2237191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 2238191762Simp BWI_COMM_MOBJ_TSSI_DS + (i * 2), val); 2239191762Simp } 2240191762Simp 2241191762Simp for (i = 0; i < 2; ++i) { 2242191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 2243191762Simp BWI_COMM_MOBJ_TSSI_OFDM + (i * 2), val); 2244191762Simp } 2245191762Simp } 2246191762Simp} 2247191762Simp 2248191762Simpvoid 2249191762Simpbwi_rf_clear_state(struct bwi_rf *rf) 2250191762Simp{ 2251191762Simp int i; 2252191762Simp 2253191762Simp rf->rf_flags &= ~BWI_RF_CLEAR_FLAGS; 2254191762Simp bzero(rf->rf_lo, sizeof(rf->rf_lo)); 2255191762Simp bzero(rf->rf_lo_used, sizeof(rf->rf_lo_used)); 2256191762Simp 2257191762Simp rf->rf_nrssi_slope = 0; 2258191762Simp rf->rf_nrssi[0] = BWI_INVALID_NRSSI; 2259191762Simp rf->rf_nrssi[1] = BWI_INVALID_NRSSI; 2260191762Simp 2261191762Simp for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) 2262191762Simp rf->rf_nrssi_table[i] = i; 2263191762Simp 2264191762Simp rf->rf_lo_gain = 0; 2265191762Simp rf->rf_rx_gain = 0; 2266191762Simp 2267191762Simp bcopy(rf->rf_txpower_map0, rf->rf_txpower_map, 2268191762Simp sizeof(rf->rf_txpower_map)); 2269191762Simp rf->rf_idle_tssi = rf->rf_idle_tssi0; 2270191762Simp} 2271191762Simp 2272191762Simpstatic void 2273191762Simpbwi_rf_on_11a(struct bwi_mac *mac) 2274191762Simp{ 2275191762Simp /* TODO:11A */ 2276191762Simp} 2277191762Simp 2278191762Simpstatic void 2279191762Simpbwi_rf_on_11bg(struct bwi_mac *mac) 2280191762Simp{ 2281191762Simp struct bwi_phy *phy = &mac->mac_phy; 2282191762Simp 2283191762Simp PHY_WRITE(mac, 0x15, 0x8000); 2284191762Simp PHY_WRITE(mac, 0x15, 0xcc00); 2285191762Simp if (phy->phy_flags & BWI_PHY_F_LINKED) 2286191762Simp PHY_WRITE(mac, 0x15, 0xc0); 2287191762Simp else 2288191762Simp PHY_WRITE(mac, 0x15, 0); 2289191762Simp 2290191762Simp bwi_rf_set_chan(mac, 6 /* XXX */, 1); 2291191762Simp} 2292191762Simp 2293191762Simpvoid 2294191762Simpbwi_rf_set_ant_mode(struct bwi_mac *mac, int ant_mode) 2295191762Simp{ 2296191762Simp struct bwi_softc *sc = mac->mac_sc; 2297191762Simp struct bwi_phy *phy = &mac->mac_phy; 2298191762Simp uint16_t val; 2299191762Simp 2300191762Simp KASSERT(ant_mode == BWI_ANT_MODE_0 || 2301191762Simp ant_mode == BWI_ANT_MODE_1 || 2302191762Simp ant_mode == BWI_ANT_MODE_AUTO, ("ant_mode %d", ant_mode)); 2303191762Simp 2304191762Simp HFLAGS_CLRBITS(mac, BWI_HFLAG_AUTO_ANTDIV); 2305191762Simp 2306191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) { 2307191762Simp /* NOTE: v4/v3 conflicts, take v3 */ 2308191762Simp if (mac->mac_rev == 2) 2309191762Simp val = BWI_ANT_MODE_AUTO; 2310191762Simp else 2311191762Simp val = ant_mode; 2312191762Simp val <<= 7; 2313191762Simp PHY_FILT_SETBITS(mac, 0x3e2, 0xfe7f, val); 2314191762Simp } else { /* 11a/g */ 2315191762Simp /* XXX reg/value naming */ 2316191762Simp val = ant_mode << 7; 2317191762Simp PHY_FILT_SETBITS(mac, 0x401, 0x7e7f, val); 2318191762Simp 2319191762Simp if (ant_mode == BWI_ANT_MODE_AUTO) 2320191762Simp PHY_CLRBITS(mac, 0x42b, 0x100); 2321191762Simp 2322191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) { 2323191762Simp /* TODO:11A */ 2324191762Simp } else { /* 11g */ 2325191762Simp if (ant_mode == BWI_ANT_MODE_AUTO) 2326191762Simp PHY_SETBITS(mac, 0x48c, 0x2000); 2327191762Simp else 2328191762Simp PHY_CLRBITS(mac, 0x48c, 0x2000); 2329191762Simp 2330191762Simp if (phy->phy_rev >= 2) { 2331191762Simp PHY_SETBITS(mac, 0x461, 0x10); 2332191762Simp PHY_FILT_SETBITS(mac, 0x4ad, 0xff00, 0x15); 2333191762Simp if (phy->phy_rev == 2) { 2334191762Simp PHY_WRITE(mac, 0x427, 0x8); 2335191762Simp } else { 2336191762Simp PHY_FILT_SETBITS(mac, 0x427, 2337191762Simp 0xff00, 0x8); 2338191762Simp } 2339191762Simp 2340191762Simp if (phy->phy_rev >= 6) 2341191762Simp PHY_WRITE(mac, 0x49b, 0xdc); 2342191762Simp } 2343191762Simp } 2344191762Simp } 2345191762Simp 2346191762Simp /* XXX v4 set AUTO_ANTDIV unconditionally */ 2347191762Simp if (ant_mode == BWI_ANT_MODE_AUTO) 2348191762Simp HFLAGS_SETBITS(mac, BWI_HFLAG_AUTO_ANTDIV); 2349191762Simp 2350191762Simp val = ant_mode << 8; 2351191762Simp MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_BEACON, 2352191762Simp 0xfc3f, val); 2353191762Simp MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_ACK, 2354191762Simp 0xfc3f, val); 2355191762Simp MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_PROBE_RESP, 2356191762Simp 0xfc3f, val); 2357191762Simp 2358191762Simp /* XXX what's these */ 2359191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) 2360191762Simp CSR_SETBITS_2(sc, 0x5e, 0x4); 2361191762Simp 2362191762Simp CSR_WRITE_4(sc, 0x100, 0x1000000); 2363191762Simp if (mac->mac_rev < 5) 2364191762Simp CSR_WRITE_4(sc, 0x10c, 0x1000000); 2365191762Simp 2366191762Simp mac->mac_rf.rf_ant_mode = ant_mode; 2367191762Simp} 2368191762Simp 2369191762Simpint 2370191762Simpbwi_rf_get_latest_tssi(struct bwi_mac *mac, int8_t tssi[], uint16_t ofs) 2371191762Simp{ 2372191762Simp int i; 2373191762Simp 2374191762Simp for (i = 0; i < 4; ) { 2375191762Simp uint16_t val; 2376191762Simp 2377191762Simp val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs + i); 2378191762Simp tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_LO_TSSI_MASK); 2379191762Simp tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_HI_TSSI_MASK); 2380191762Simp } 2381191762Simp 2382191762Simp for (i = 0; i < 4; ++i) { 2383191762Simp if (tssi[i] == BWI_INVALID_TSSI) 2384191762Simp return EINVAL; 2385191762Simp } 2386191762Simp return 0; 2387191762Simp} 2388191762Simp 2389191762Simpint 2390191762Simpbwi_rf_tssi2dbm(struct bwi_mac *mac, int8_t tssi, int8_t *txpwr) 2391191762Simp{ 2392191762Simp struct bwi_rf *rf = &mac->mac_rf; 2393191762Simp int pwr_idx; 2394191762Simp 2395191762Simp pwr_idx = rf->rf_idle_tssi + (int)tssi - rf->rf_base_tssi; 2396191762Simp#if 0 2397191762Simp if (pwr_idx < 0 || pwr_idx >= BWI_TSSI_MAX) 2398191762Simp return EINVAL; 2399191762Simp#else 2400191762Simp if (pwr_idx < 0) 2401191762Simp pwr_idx = 0; 2402191762Simp else if (pwr_idx >= BWI_TSSI_MAX) 2403191762Simp pwr_idx = BWI_TSSI_MAX - 1; 2404191762Simp#endif 2405191762Simp 2406191762Simp *txpwr = rf->rf_txpower_map[pwr_idx]; 2407191762Simp return 0; 2408191762Simp} 2409191762Simp 2410191762Simpstatic int 2411191762Simpbwi_rf_calc_rssi_bcm2050(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) 2412191762Simp{ 2413191762Simp uint16_t flags1, flags3; 2414191762Simp int rssi, lna_gain; 2415191762Simp 2416191762Simp rssi = hdr->rxh_rssi; 2417191762Simp flags1 = le16toh(hdr->rxh_flags1); 2418191762Simp flags3 = le16toh(hdr->rxh_flags3); 2419191762Simp 2420191762Simp if (flags1 & BWI_RXH_F1_OFDM) { 2421191762Simp if (rssi > 127) 2422191762Simp rssi -= 256; 2423191762Simp if (flags3 & BWI_RXH_F3_BCM2050_RSSI) 2424191762Simp rssi += 17; 2425191762Simp else 2426191762Simp rssi -= 4; 2427191762Simp return rssi; 2428191762Simp } 2429191762Simp 2430191762Simp if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { 2431191762Simp struct bwi_rf *rf = &mac->mac_rf; 2432191762Simp 2433191762Simp if (rssi >= BWI_NRSSI_TBLSZ) 2434191762Simp rssi = BWI_NRSSI_TBLSZ - 1; 2435191762Simp 2436191762Simp rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128; 2437191762Simp rssi -= 67; 2438191762Simp } else { 2439191762Simp rssi = ((31 - rssi) * -149) / 128; 2440191762Simp rssi -= 68; 2441191762Simp } 2442191762Simp 2443191762Simp if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G) 2444191762Simp return rssi; 2445191762Simp 2446191762Simp if (flags3 & BWI_RXH_F3_BCM2050_RSSI) 2447191762Simp rssi += 20; 2448191762Simp 2449191762Simp lna_gain = __SHIFTOUT(le16toh(hdr->rxh_phyinfo), 2450191762Simp BWI_RXH_PHYINFO_LNAGAIN); 2451191762Simp DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_RX, 2452191762Simp "lna_gain %d, phyinfo 0x%04x\n", 2453191762Simp lna_gain, le16toh(hdr->rxh_phyinfo)); 2454191762Simp switch (lna_gain) { 2455191762Simp case 0: 2456191762Simp rssi += 27; 2457191762Simp break; 2458191762Simp case 1: 2459191762Simp rssi += 6; 2460191762Simp break; 2461191762Simp case 2: 2462191762Simp rssi += 12; 2463191762Simp break; 2464191762Simp case 3: 2465191762Simp /* 2466191762Simp * XXX 2467191762Simp * According to v3 spec, we should do _nothing_ here, 2468191762Simp * but it seems that the result RSSI will be too low 2469191762Simp * (relative to what ath(4) says). Raise it a little 2470191762Simp * bit. 2471191762Simp */ 2472191762Simp rssi += 5; 2473191762Simp break; 2474191762Simp default: 2475191762Simp panic("impossible lna gain %d", lna_gain); 2476191762Simp } 2477191762Simp return rssi; 2478191762Simp} 2479191762Simp 2480191762Simpstatic int 2481191762Simpbwi_rf_calc_rssi_bcm2053(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) 2482191762Simp{ 2483191762Simp uint16_t flags1; 2484191762Simp int rssi; 2485191762Simp 2486191762Simp rssi = (((int)hdr->rxh_rssi - 11) * 103) / 64; 2487191762Simp 2488191762Simp flags1 = le16toh(hdr->rxh_flags1); 2489191762Simp if (flags1 & BWI_RXH_F1_BCM2053_RSSI) 2490191762Simp rssi -= 109; 2491191762Simp else 2492191762Simp rssi -= 83; 2493191762Simp return rssi; 2494191762Simp} 2495191762Simp 2496191762Simpstatic int 2497191762Simpbwi_rf_calc_rssi_bcm2060(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) 2498191762Simp{ 2499191762Simp int rssi; 2500191762Simp 2501191762Simp rssi = hdr->rxh_rssi; 2502191762Simp if (rssi > 127) 2503191762Simp rssi -= 256; 2504191762Simp return rssi; 2505191762Simp} 2506191762Simp 2507191762Simpstatic int 2508191762Simpbwi_rf_calc_noise_bcm2050(struct bwi_mac *mac) 2509191762Simp{ 2510191762Simp uint16_t val; 2511191762Simp int noise; 2512191762Simp 2513191762Simp val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_NOISE); 2514191762Simp noise = (int)val; /* XXX check bounds? */ 2515191762Simp 2516191762Simp if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { 2517191762Simp struct bwi_rf *rf = &mac->mac_rf; 2518191762Simp 2519191762Simp if (noise >= BWI_NRSSI_TBLSZ) 2520191762Simp noise = BWI_NRSSI_TBLSZ - 1; 2521191762Simp 2522191762Simp noise = ((31 - (int)rf->rf_nrssi_table[noise]) * -131) / 128; 2523191762Simp noise -= 67; 2524191762Simp } else { 2525191762Simp noise = ((31 - noise) * -149) / 128; 2526191762Simp noise -= 68; 2527191762Simp } 2528191762Simp return noise; 2529191762Simp} 2530191762Simp 2531191762Simpstatic int 2532191762Simpbwi_rf_calc_noise_bcm2053(struct bwi_mac *mac) 2533191762Simp{ 2534191762Simp uint16_t val; 2535191762Simp int noise; 2536191762Simp 2537191762Simp val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_NOISE); 2538191762Simp noise = (int)val; /* XXX check bounds? */ 2539191762Simp 2540191762Simp noise = ((noise - 11) * 103) / 64; 2541191762Simp noise -= 109; 2542191762Simp return noise; 2543191762Simp} 2544191762Simp 2545191762Simpstatic int 2546191762Simpbwi_rf_calc_noise_bcm2060(struct bwi_mac *mac) 2547191762Simp{ 2548191762Simp /* XXX Dont know how to calc */ 2549191762Simp return (BWI_NOISE_FLOOR); 2550191762Simp} 2551191762Simp 2552191762Simpstatic uint16_t 2553191762Simpbwi_rf_lo_measure_11b(struct bwi_mac *mac) 2554191762Simp{ 2555191762Simp uint16_t val; 2556191762Simp int i; 2557191762Simp 2558191762Simp val = 0; 2559191762Simp for (i = 0; i < 10; ++i) { 2560191762Simp PHY_WRITE(mac, 0x15, 0xafa0); 2561191762Simp DELAY(1); 2562191762Simp PHY_WRITE(mac, 0x15, 0xefa0); 2563191762Simp DELAY(10); 2564191762Simp PHY_WRITE(mac, 0x15, 0xffa0); 2565191762Simp DELAY(40); 2566191762Simp 2567191762Simp val += PHY_READ(mac, 0x2c); 2568191762Simp } 2569191762Simp return val; 2570191762Simp} 2571191762Simp 2572191762Simpstatic void 2573191762Simpbwi_rf_lo_update_11b(struct bwi_mac *mac) 2574191762Simp{ 2575191762Simp struct bwi_softc *sc = mac->mac_sc; 2576191762Simp struct bwi_rf *rf = &mac->mac_rf; 2577191762Simp struct rf_saveregs regs; 2578191762Simp uint16_t rf_val, phy_val, min_val, val; 2579191762Simp uint16_t rf52, bphy_ctrl; 2580191762Simp int i; 2581191762Simp 2582191762Simp DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__); 2583191762Simp 2584191762Simp bzero(®s, sizeof(regs)); 2585191762Simp bphy_ctrl = 0; 2586191762Simp 2587191762Simp /* 2588191762Simp * Save RF/PHY registers for later restoration 2589191762Simp */ 2590191762Simp SAVE_PHY_REG(mac, ®s, 15); 2591191762Simp rf52 = RF_READ(mac, 0x52) & 0xfff0; 2592191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 2593191762Simp SAVE_PHY_REG(mac, ®s, 0a); 2594191762Simp SAVE_PHY_REG(mac, ®s, 2a); 2595191762Simp SAVE_PHY_REG(mac, ®s, 35); 2596191762Simp SAVE_PHY_REG(mac, ®s, 03); 2597191762Simp SAVE_PHY_REG(mac, ®s, 01); 2598191762Simp SAVE_PHY_REG(mac, ®s, 30); 2599191762Simp 2600191762Simp SAVE_RF_REG(mac, ®s, 43); 2601191762Simp SAVE_RF_REG(mac, ®s, 7a); 2602191762Simp 2603191762Simp bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL); 2604191762Simp 2605191762Simp SAVE_RF_REG(mac, ®s, 52); 2606191762Simp regs.rf_52 &= 0xf0; 2607191762Simp 2608191762Simp PHY_WRITE(mac, 0x30, 0xff); 2609191762Simp CSR_WRITE_2(sc, BWI_PHY_CTRL, 0x3f3f); 2610191762Simp PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f); 2611191762Simp RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0); 2612191762Simp } 2613191762Simp 2614191762Simp PHY_WRITE(mac, 0x15, 0xb000); 2615191762Simp 2616191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 2617191762Simp PHY_WRITE(mac, 0x2b, 0x203); 2618191762Simp PHY_WRITE(mac, 0x2a, 0x8a3); 2619191762Simp } else { 2620191762Simp PHY_WRITE(mac, 0x2b, 0x1402); 2621191762Simp } 2622191762Simp 2623191762Simp /* 2624191762Simp * Setup RF signal 2625191762Simp */ 2626191762Simp rf_val = 0; 2627191762Simp min_val = UINT16_MAX; 2628191762Simp 2629191762Simp for (i = 0; i < 4; ++i) { 2630191762Simp RF_WRITE(mac, 0x52, rf52 | i); 2631191762Simp bwi_rf_lo_measure_11b(mac); /* Ignore return value */ 2632191762Simp } 2633191762Simp for (i = 0; i < 10; ++i) { 2634191762Simp RF_WRITE(mac, 0x52, rf52 | i); 2635191762Simp 2636191762Simp val = bwi_rf_lo_measure_11b(mac) / 10; 2637191762Simp if (val < min_val) { 2638191762Simp min_val = val; 2639191762Simp rf_val = i; 2640191762Simp } 2641191762Simp } 2642191762Simp RF_WRITE(mac, 0x52, rf52 | rf_val); 2643191762Simp 2644191762Simp /* 2645191762Simp * Setup PHY signal 2646191762Simp */ 2647191762Simp phy_val = 0; 2648191762Simp min_val = UINT16_MAX; 2649191762Simp 2650191762Simp for (i = -4; i < 5; i += 2) { 2651191762Simp int j; 2652191762Simp 2653191762Simp for (j = -4; j < 5; j += 2) { 2654191762Simp uint16_t phy2f; 2655191762Simp 2656191762Simp phy2f = (0x100 * i) + j; 2657191762Simp if (j < 0) 2658191762Simp phy2f += 0x100; 2659191762Simp PHY_WRITE(mac, 0x2f, phy2f); 2660191762Simp 2661191762Simp val = bwi_rf_lo_measure_11b(mac) / 10; 2662191762Simp if (val < min_val) { 2663191762Simp min_val = val; 2664191762Simp phy_val = phy2f; 2665191762Simp } 2666191762Simp } 2667191762Simp } 2668191762Simp PHY_WRITE(mac, 0x2f, phy_val + 0x101); 2669191762Simp 2670191762Simp /* 2671191762Simp * Restore saved RF/PHY registers 2672191762Simp */ 2673191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 2674191762Simp RESTORE_PHY_REG(mac, ®s, 0a); 2675191762Simp RESTORE_PHY_REG(mac, ®s, 2a); 2676191762Simp RESTORE_PHY_REG(mac, ®s, 35); 2677191762Simp RESTORE_PHY_REG(mac, ®s, 03); 2678191762Simp RESTORE_PHY_REG(mac, ®s, 01); 2679191762Simp RESTORE_PHY_REG(mac, ®s, 30); 2680191762Simp 2681191762Simp RESTORE_RF_REG(mac, ®s, 43); 2682191762Simp RESTORE_RF_REG(mac, ®s, 7a); 2683191762Simp 2684191762Simp RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52); 2685191762Simp 2686191762Simp CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl); 2687191762Simp } 2688191762Simp RESTORE_PHY_REG(mac, ®s, 15); 2689191762Simp 2690191762Simp bwi_rf_work_around(mac, rf->rf_curchan); 2691191762Simp} 2692