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/bwiphy.c,v 1.5 2008/01/15 09:01:13 sephe Exp $ 35191762Simp */ 36191762Simp 37191762Simp#include <sys/cdefs.h> 38191762Simp__FBSDID("$FreeBSD: releng/10.2/sys/dev/bwi/bwiphy.c 235338 2012-05-12 15:11:53Z adrian $"); 39191762Simp 40191762Simp#include "opt_inet.h" 41235338Sadrian#include "opt_wlan.h" 42191762Simp 43191762Simp#include <sys/param.h> 44191762Simp#include <sys/endian.h> 45191762Simp#include <sys/kernel.h> 46191762Simp#include <sys/bus.h> 47191762Simp#include <sys/malloc.h> 48191762Simp#include <sys/proc.h> 49191762Simp#include <sys/rman.h> 50191762Simp#include <sys/socket.h> 51191762Simp#include <sys/sockio.h> 52191762Simp#include <sys/sysctl.h> 53191762Simp#include <sys/systm.h> 54191762Simp 55191762Simp#include <net/if.h> 56191762Simp#include <net/if_dl.h> 57191762Simp#include <net/if_media.h> 58191762Simp#include <net/if_types.h> 59191762Simp#include <net/if_arp.h> 60191762Simp#include <net/ethernet.h> 61191762Simp#include <net/if_llc.h> 62191762Simp 63191762Simp#include <net80211/ieee80211_var.h> 64191762Simp#include <net80211/ieee80211_radiotap.h> 65191762Simp#include <net80211/ieee80211_amrr.h> 66191762Simp 67191762Simp#include <machine/bus.h> 68191762Simp 69191762Simp#include <dev/bwi/bitops.h> 70191762Simp#include <dev/bwi/if_bwireg.h> 71191762Simp#include <dev/bwi/if_bwivar.h> 72191762Simp#include <dev/bwi/bwimac.h> 73191762Simp#include <dev/bwi/bwirf.h> 74191762Simp#include <dev/bwi/bwiphy.h> 75191762Simp 76191762Simpstatic void bwi_phy_init_11a(struct bwi_mac *); 77191762Simpstatic void bwi_phy_init_11g(struct bwi_mac *); 78191762Simpstatic void bwi_phy_init_11b_rev2(struct bwi_mac *); 79191762Simpstatic void bwi_phy_init_11b_rev4(struct bwi_mac *); 80191762Simpstatic void bwi_phy_init_11b_rev5(struct bwi_mac *); 81191762Simpstatic void bwi_phy_init_11b_rev6(struct bwi_mac *); 82191762Simp 83191762Simpstatic void bwi_phy_config_11g(struct bwi_mac *); 84191762Simpstatic void bwi_phy_config_agc(struct bwi_mac *); 85191762Simp 86191762Simpstatic void bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t); 87191762Simpstatic void bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t); 88191762Simp 89191762Simp#define SUP_BPHY(num) { .rev = num, .init = bwi_phy_init_11b_rev##num } 90191762Simp 91191762Simpstatic const struct { 92191762Simp uint8_t rev; 93191762Simp void (*init)(struct bwi_mac *); 94191762Simp} bwi_sup_bphy[] = { 95191762Simp SUP_BPHY(2), 96191762Simp SUP_BPHY(4), 97191762Simp SUP_BPHY(5), 98191762Simp SUP_BPHY(6) 99191762Simp}; 100191762Simp 101191762Simp#undef SUP_BPHY 102191762Simp 103191762Simp#define BWI_PHYTBL_WRSSI 0x1000 104191762Simp#define BWI_PHYTBL_NOISE_SCALE 0x1400 105191762Simp#define BWI_PHYTBL_NOISE 0x1800 106191762Simp#define BWI_PHYTBL_ROTOR 0x2000 107191762Simp#define BWI_PHYTBL_DELAY 0x2400 108191762Simp#define BWI_PHYTBL_RSSI 0x4000 109191762Simp#define BWI_PHYTBL_SIGMA_SQ 0x5000 110191762Simp#define BWI_PHYTBL_WRSSI_REV1 0x5400 111191762Simp#define BWI_PHYTBL_FREQ 0x5800 112191762Simp 113191762Simpstatic const uint16_t bwi_phy_freq_11g_rev1[] = 114191762Simp { BWI_PHY_FREQ_11G_REV1 }; 115191762Simpstatic const uint16_t bwi_phy_noise_11g_rev1[] = 116191762Simp { BWI_PHY_NOISE_11G_REV1 }; 117191762Simpstatic const uint16_t bwi_phy_noise_11g[] = 118191762Simp { BWI_PHY_NOISE_11G }; 119191762Simpstatic const uint32_t bwi_phy_rotor_11g_rev1[] = 120191762Simp { BWI_PHY_ROTOR_11G_REV1 }; 121191762Simpstatic const uint16_t bwi_phy_noise_scale_11g_rev2[] = 122191762Simp { BWI_PHY_NOISE_SCALE_11G_REV2 }; 123191762Simpstatic const uint16_t bwi_phy_noise_scale_11g_rev7[] = 124191762Simp { BWI_PHY_NOISE_SCALE_11G_REV7 }; 125191762Simpstatic const uint16_t bwi_phy_noise_scale_11g[] = 126191762Simp { BWI_PHY_NOISE_SCALE_11G }; 127191762Simpstatic const uint16_t bwi_phy_sigma_sq_11g_rev2[] = 128191762Simp { BWI_PHY_SIGMA_SQ_11G_REV2 }; 129191762Simpstatic const uint16_t bwi_phy_sigma_sq_11g_rev7[] = 130191762Simp { BWI_PHY_SIGMA_SQ_11G_REV7 }; 131191762Simpstatic const uint32_t bwi_phy_delay_11g_rev1[] = 132191762Simp { BWI_PHY_DELAY_11G_REV1 }; 133191762Simp 134191762Simpvoid 135191762Simpbwi_phy_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data) 136191762Simp{ 137191762Simp struct bwi_softc *sc = mac->mac_sc; 138191762Simp 139191762Simp CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl); 140191762Simp CSR_WRITE_2(sc, BWI_PHY_DATA, data); 141191762Simp} 142191762Simp 143191762Simpuint16_t 144191762Simpbwi_phy_read(struct bwi_mac *mac, uint16_t ctrl) 145191762Simp{ 146191762Simp struct bwi_softc *sc = mac->mac_sc; 147191762Simp 148191762Simp CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl); 149191762Simp return CSR_READ_2(sc, BWI_PHY_DATA); 150191762Simp} 151191762Simp 152191762Simpint 153191762Simpbwi_phy_attach(struct bwi_mac *mac) 154191762Simp{ 155191762Simp struct bwi_softc *sc = mac->mac_sc; 156191762Simp struct bwi_phy *phy = &mac->mac_phy; 157191762Simp uint8_t phyrev, phytype, phyver; 158191762Simp uint16_t val; 159191762Simp int i; 160191762Simp 161191762Simp /* Get PHY type/revision/version */ 162191762Simp val = CSR_READ_2(sc, BWI_PHYINFO); 163191762Simp phyrev = __SHIFTOUT(val, BWI_PHYINFO_REV_MASK); 164191762Simp phytype = __SHIFTOUT(val, BWI_PHYINFO_TYPE_MASK); 165191762Simp phyver = __SHIFTOUT(val, BWI_PHYINFO_VER_MASK); 166191762Simp device_printf(sc->sc_dev, "PHY: type %d, rev %d, ver %d\n", 167191762Simp phytype, phyrev, phyver); 168191762Simp 169191762Simp /* 170191762Simp * Verify whether the revision of the PHY type is supported 171191762Simp * Convert PHY type to ieee80211_phymode 172191762Simp */ 173191762Simp switch (phytype) { 174191762Simp case BWI_PHYINFO_TYPE_11A: 175191762Simp if (phyrev >= 4) { 176191762Simp device_printf(sc->sc_dev, "unsupported 11A PHY, " 177191762Simp "rev %u\n", phyrev); 178191762Simp return ENXIO; 179191762Simp } 180191762Simp phy->phy_init = bwi_phy_init_11a; 181191762Simp phy->phy_mode = IEEE80211_MODE_11A; 182191762Simp phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11A; 183191762Simp phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11A; 184191762Simp phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11A; 185191762Simp break; 186191762Simp case BWI_PHYINFO_TYPE_11B: 187191762Simp#define N(arr) (int)(sizeof(arr) / sizeof(arr[0])) 188191762Simp for (i = 0; i < N(bwi_sup_bphy); ++i) { 189191762Simp if (phyrev == bwi_sup_bphy[i].rev) { 190191762Simp phy->phy_init = bwi_sup_bphy[i].init; 191191762Simp break; 192191762Simp } 193191762Simp } 194191762Simp if (i == N(bwi_sup_bphy)) { 195191762Simp device_printf(sc->sc_dev, "unsupported 11B PHY, " 196191762Simp "rev %u\n", phyrev); 197191762Simp return ENXIO; 198191762Simp } 199191762Simp#undef N 200191762Simp phy->phy_mode = IEEE80211_MODE_11B; 201191762Simp break; 202191762Simp case BWI_PHYINFO_TYPE_11G: 203191762Simp if (phyrev > 8) { 204191762Simp device_printf(sc->sc_dev, "unsupported 11G PHY, " 205191762Simp "rev %u\n", phyrev); 206191762Simp return ENXIO; 207191762Simp } 208191762Simp phy->phy_init = bwi_phy_init_11g; 209191762Simp phy->phy_mode = IEEE80211_MODE_11G; 210191762Simp phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11G; 211191762Simp phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11G; 212191762Simp phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11G; 213191762Simp break; 214191762Simp default: 215191762Simp device_printf(sc->sc_dev, "unsupported PHY type %d\n", 216191762Simp phytype); 217191762Simp return ENXIO; 218191762Simp } 219191762Simp phy->phy_rev = phyrev; 220191762Simp phy->phy_version = phyver; 221191762Simp return 0; 222191762Simp} 223191762Simp 224191762Simpvoid 225191762Simpbwi_phy_set_bbp_atten(struct bwi_mac *mac, uint16_t bbp_atten) 226191762Simp{ 227191762Simp struct bwi_phy *phy = &mac->mac_phy; 228191762Simp uint16_t mask = __BITS(3, 0); 229191762Simp 230191762Simp if (phy->phy_version == 0) { 231191762Simp CSR_FILT_SETBITS_2(mac->mac_sc, BWI_BBP_ATTEN, ~mask, 232191762Simp __SHIFTIN(bbp_atten, mask)); 233191762Simp } else { 234191762Simp if (phy->phy_version > 1) 235191762Simp mask <<= 2; 236191762Simp else 237191762Simp mask <<= 3; 238191762Simp PHY_FILT_SETBITS(mac, BWI_PHYR_BBP_ATTEN, ~mask, 239191762Simp __SHIFTIN(bbp_atten, mask)); 240191762Simp } 241191762Simp} 242191762Simp 243191762Simpint 244191762Simpbwi_phy_calibrate(struct bwi_mac *mac) 245191762Simp{ 246191762Simp struct bwi_phy *phy = &mac->mac_phy; 247191762Simp 248191762Simp /* Dummy read */ 249191762Simp CSR_READ_4(mac->mac_sc, BWI_MAC_STATUS); 250191762Simp 251191762Simp /* Don't re-init */ 252191762Simp if (phy->phy_flags & BWI_PHY_F_CALIBRATED) 253191762Simp return 0; 254191762Simp 255191762Simp if (phy->phy_mode == IEEE80211_MODE_11G && phy->phy_rev == 1) { 256191762Simp bwi_mac_reset(mac, 0); 257191762Simp bwi_phy_init_11g(mac); 258191762Simp bwi_mac_reset(mac, 1); 259191762Simp } 260191762Simp 261191762Simp phy->phy_flags |= BWI_PHY_F_CALIBRATED; 262191762Simp return 0; 263191762Simp} 264191762Simp 265191762Simpstatic void 266191762Simpbwi_tbl_write_2(struct bwi_mac *mac, uint16_t ofs, uint16_t data) 267191762Simp{ 268191762Simp struct bwi_phy *phy = &mac->mac_phy; 269191762Simp 270191762Simp KASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0, 271191762Simp ("phy_tbl_ctrl %d phy_tbl_data_lo %d", 272191762Simp phy->phy_tbl_ctrl, phy->phy_tbl_data_lo)); 273191762Simp PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs); 274191762Simp PHY_WRITE(mac, phy->phy_tbl_data_lo, data); 275191762Simp} 276191762Simp 277191762Simpstatic void 278191762Simpbwi_tbl_write_4(struct bwi_mac *mac, uint16_t ofs, uint32_t data) 279191762Simp{ 280191762Simp struct bwi_phy *phy = &mac->mac_phy; 281191762Simp 282191762Simp KASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 && 283191762Simp phy->phy_tbl_ctrl != 0, 284191762Simp ("phy_tbl_data_lo %d phy_tbl_data_hi %d phy_tbl_ctrl %d", 285191762Simp phy->phy_tbl_data_lo, phy->phy_tbl_data_hi, phy->phy_tbl_ctrl)); 286191762Simp 287191762Simp PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs); 288191762Simp PHY_WRITE(mac, phy->phy_tbl_data_hi, data >> 16); 289191762Simp PHY_WRITE(mac, phy->phy_tbl_data_lo, data & 0xffff); 290191762Simp} 291191762Simp 292191762Simpvoid 293191762Simpbwi_nrssi_write(struct bwi_mac *mac, uint16_t ofs, int16_t data) 294191762Simp{ 295191762Simp PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs); 296191762Simp PHY_WRITE(mac, BWI_PHYR_NRSSI_DATA, (uint16_t)data); 297191762Simp} 298191762Simp 299191762Simpint16_t 300191762Simpbwi_nrssi_read(struct bwi_mac *mac, uint16_t ofs) 301191762Simp{ 302191762Simp PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs); 303191762Simp return (int16_t)PHY_READ(mac, BWI_PHYR_NRSSI_DATA); 304191762Simp} 305191762Simp 306191762Simpstatic void 307191762Simpbwi_phy_init_11a(struct bwi_mac *mac) 308191762Simp{ 309191762Simp /* TODO:11A */ 310191762Simp} 311191762Simp 312191762Simpstatic void 313191762Simpbwi_phy_init_11g(struct bwi_mac *mac) 314191762Simp{ 315191762Simp struct bwi_softc *sc = mac->mac_sc; 316191762Simp struct bwi_phy *phy = &mac->mac_phy; 317191762Simp struct bwi_rf *rf = &mac->mac_rf; 318191762Simp const struct bwi_tpctl *tpctl = &mac->mac_tpctl; 319191762Simp 320191762Simp if (phy->phy_rev == 1) 321191762Simp bwi_phy_init_11b_rev5(mac); 322191762Simp else 323191762Simp bwi_phy_init_11b_rev6(mac); 324191762Simp 325191762Simp if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED)) 326191762Simp bwi_phy_config_11g(mac); 327191762Simp 328191762Simp if (phy->phy_rev >= 2) { 329191762Simp PHY_WRITE(mac, 0x814, 0); 330191762Simp PHY_WRITE(mac, 0x815, 0); 331191762Simp 332191762Simp if (phy->phy_rev == 2) { 333191762Simp PHY_WRITE(mac, 0x811, 0); 334191762Simp PHY_WRITE(mac, 0x15, 0xc0); 335191762Simp } else if (phy->phy_rev > 5) { 336191762Simp PHY_WRITE(mac, 0x811, 0x400); 337191762Simp PHY_WRITE(mac, 0x15, 0xc0); 338191762Simp } 339191762Simp } 340191762Simp 341191762Simp if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED)) { 342191762Simp uint16_t val; 343191762Simp 344191762Simp val = PHY_READ(mac, 0x400) & 0xff; 345191762Simp if (val == 3 || val == 5) { 346191762Simp PHY_WRITE(mac, 0x4c2, 0x1816); 347191762Simp PHY_WRITE(mac, 0x4c3, 0x8006); 348191762Simp if (val == 5) { 349191762Simp PHY_FILT_SETBITS(mac, 0x4cc, 350191762Simp 0xff, 0x1f00); 351191762Simp } 352191762Simp } 353191762Simp } 354191762Simp 355191762Simp if ((phy->phy_rev <= 2 && (phy->phy_flags & BWI_PHY_F_LINKED)) || 356191762Simp phy->phy_rev >= 2) 357191762Simp PHY_WRITE(mac, 0x47e, 0x78); 358191762Simp 359191762Simp if (rf->rf_rev == 8) { 360191762Simp PHY_SETBITS(mac, 0x801, 0x80); 361191762Simp PHY_SETBITS(mac, 0x43e, 0x4); 362191762Simp } 363191762Simp 364191762Simp if (phy->phy_rev >= 2 && (phy->phy_flags & BWI_PHY_F_LINKED)) 365191762Simp bwi_rf_get_gains(mac); 366191762Simp 367191762Simp if (rf->rf_rev != 8) 368191762Simp bwi_rf_init(mac); 369191762Simp 370191762Simp if (tpctl->tp_ctrl2 == 0xffff) { 371191762Simp bwi_rf_lo_update(mac); 372191762Simp } else { 373191762Simp if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 8) { 374191762Simp RF_WRITE(mac, 0x52, 375191762Simp (tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2); 376191762Simp } else { 377192306Simp RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl2); 378191762Simp } 379191762Simp 380191762Simp if (phy->phy_rev >= 6) { 381191762Simp PHY_FILT_SETBITS(mac, 0x36, 0xfff, 382191762Simp tpctl->tp_ctrl2 << 12); 383191762Simp } 384191762Simp 385191762Simp if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) 386191762Simp PHY_WRITE(mac, 0x2e, 0x8075); 387191762Simp else 388191762Simp PHY_WRITE(mac, 0x2e, 0x807f); 389191762Simp 390191762Simp if (phy->phy_rev < 2) 391191762Simp PHY_WRITE(mac, 0x2f, 0x101); 392191762Simp else 393191762Simp PHY_WRITE(mac, 0x2f, 0x202); 394191762Simp } 395191762Simp 396191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 397191762Simp bwi_rf_lo_adjust(mac, tpctl); 398191762Simp PHY_WRITE(mac, 0x80f, 0x8078); 399191762Simp } 400191762Simp 401191762Simp if ((sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) { 402191762Simp bwi_rf_init_hw_nrssi_table(mac, 0xffff /* XXX */); 403191762Simp bwi_rf_set_nrssi_thr(mac); 404191762Simp } else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 405191762Simp if (rf->rf_nrssi[0] == BWI_INVALID_NRSSI) { 406191762Simp KASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI, 407191762Simp ("rf_nrssi[1] %d", rf->rf_nrssi[1])); 408191762Simp bwi_rf_calc_nrssi_slope(mac); 409191762Simp } else { 410191762Simp KASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI, 411191762Simp ("rf_nrssi[1] %d", rf->rf_nrssi[1])); 412191762Simp bwi_rf_set_nrssi_thr(mac); 413191762Simp } 414191762Simp } 415191762Simp 416191762Simp if (rf->rf_rev == 8) 417191762Simp PHY_WRITE(mac, 0x805, 0x3230); 418191762Simp 419191762Simp bwi_mac_init_tpctl_11bg(mac); 420191762Simp 421191762Simp if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_pkg == 2) { 422191762Simp PHY_CLRBITS(mac, 0x429, 0x4000); 423191762Simp PHY_CLRBITS(mac, 0x4c3, 0x8000); 424191762Simp } 425191762Simp} 426191762Simp 427191762Simpstatic void 428191762Simpbwi_phy_init_11b_rev2(struct bwi_mac *mac) 429191762Simp{ 430191762Simp /* TODO:11B */ 431191762Simp if_printf(mac->mac_sc->sc_ifp, 432191762Simp "%s is not implemented yet\n", __func__); 433191762Simp} 434191762Simp 435191762Simpstatic void 436191762Simpbwi_phy_init_11b_rev4(struct bwi_mac *mac) 437191762Simp{ 438191762Simp struct bwi_softc *sc = mac->mac_sc; 439191762Simp struct bwi_rf *rf = &mac->mac_rf; 440191762Simp uint16_t val, ofs; 441191762Simp u_int chan; 442191762Simp 443191762Simp CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT); 444191762Simp 445191762Simp PHY_WRITE(mac, 0x20, 0x301c); 446191762Simp PHY_WRITE(mac, 0x26, 0); 447191762Simp PHY_WRITE(mac, 0x30, 0xc6); 448191762Simp PHY_WRITE(mac, 0x88, 0x3e00); 449191762Simp 450191762Simp for (ofs = 0, val = 0x3c3d; ofs < 30; ++ofs, val -= 0x202) 451191762Simp PHY_WRITE(mac, 0x89 + ofs, val); 452191762Simp 453191762Simp CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1); 454191762Simp 455191762Simp chan = rf->rf_curchan; 456191762Simp if (chan == IEEE80211_CHAN_ANY) 457191762Simp chan = 6; /* Force to channel 6 */ 458191762Simp bwi_rf_set_chan(mac, chan, 0); 459191762Simp 460191762Simp if (rf->rf_type != BWI_RF_T_BCM2050) { 461191762Simp RF_WRITE(mac, 0x75, 0x80); 462191762Simp RF_WRITE(mac, 0x79, 0x81); 463191762Simp } 464191762Simp 465191762Simp RF_WRITE(mac, 0x50, 0x20); 466191762Simp RF_WRITE(mac, 0x50, 0x23); 467191762Simp 468191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 469191762Simp RF_WRITE(mac, 0x50, 0x20); 470191762Simp RF_WRITE(mac, 0x5a, 0x70); 471191762Simp RF_WRITE(mac, 0x5b, 0x7b); 472191762Simp RF_WRITE(mac, 0x5c, 0xb0); 473191762Simp RF_WRITE(mac, 0x7a, 0xf); 474191762Simp PHY_WRITE(mac, 0x38, 0x677); 475191762Simp bwi_rf_init_bcm2050(mac); 476191762Simp } 477191762Simp 478191762Simp PHY_WRITE(mac, 0x14, 0x80); 479191762Simp PHY_WRITE(mac, 0x32, 0xca); 480191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) 481191762Simp PHY_WRITE(mac, 0x32, 0xe0); 482191762Simp PHY_WRITE(mac, 0x35, 0x7c2); 483191762Simp 484191762Simp bwi_rf_lo_update(mac); 485191762Simp 486191762Simp PHY_WRITE(mac, 0x26, 0xcc00); 487191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) 488191762Simp PHY_WRITE(mac, 0x26, 0xce00); 489191762Simp 490191762Simp CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0x1100); 491191762Simp 492191762Simp PHY_WRITE(mac, 0x2a, 0x88a3); 493191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) 494191762Simp PHY_WRITE(mac, 0x2a, 0x88c2); 495191762Simp 496191762Simp bwi_mac_set_tpctl_11bg(mac, NULL); 497191762Simp if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { 498191762Simp bwi_rf_calc_nrssi_slope(mac); 499191762Simp bwi_rf_set_nrssi_thr(mac); 500191762Simp } 501191762Simp bwi_mac_init_tpctl_11bg(mac); 502191762Simp} 503191762Simp 504191762Simpstatic void 505191762Simpbwi_phy_init_11b_rev5(struct bwi_mac *mac) 506191762Simp{ 507191762Simp struct bwi_softc *sc = mac->mac_sc; 508191762Simp struct bwi_rf *rf = &mac->mac_rf; 509191762Simp struct bwi_phy *phy = &mac->mac_phy; 510191762Simp u_int orig_chan; 511191762Simp 512191762Simp if (phy->phy_version == 1) 513191762Simp RF_SETBITS(mac, 0x7a, 0x50); 514191762Simp 515191762Simp if (sc->sc_pci_subvid != PCI_VENDOR_BROADCOM && 516191762Simp sc->sc_pci_subdid != BWI_PCI_SUBDEVICE_BU4306) { 517191762Simp uint16_t ofs, val; 518191762Simp 519191762Simp val = 0x2120; 520191762Simp for (ofs = 0xa8; ofs < 0xc7; ++ofs) { 521191762Simp PHY_WRITE(mac, ofs, val); 522191762Simp val += 0x202; 523191762Simp } 524191762Simp } 525191762Simp 526191762Simp PHY_FILT_SETBITS(mac, 0x35, 0xf0ff, 0x700); 527191762Simp 528191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) 529191762Simp PHY_WRITE(mac, 0x38, 0x667); 530191762Simp 531191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) { 532191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 533191762Simp RF_SETBITS(mac, 0x7a, 0x20); 534191762Simp RF_SETBITS(mac, 0x51, 0x4); 535191762Simp } 536191762Simp 537191762Simp CSR_WRITE_2(sc, BWI_RF_ANTDIV, 0); 538191762Simp 539191762Simp PHY_SETBITS(mac, 0x802, 0x100); 540191762Simp PHY_SETBITS(mac, 0x42b, 0x2000); 541191762Simp PHY_WRITE(mac, 0x1c, 0x186a); 542191762Simp 543191762Simp PHY_FILT_SETBITS(mac, 0x13, 0xff, 0x1900); 544191762Simp PHY_FILT_SETBITS(mac, 0x35, 0xffc0, 0x64); 545191762Simp PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0xa); 546191762Simp } 547191762Simp 548191762Simp /* TODO: bad_frame_preempt? */ 549191762Simp 550191762Simp if (phy->phy_version == 1) { 551191762Simp PHY_WRITE(mac, 0x26, 0xce00); 552191762Simp PHY_WRITE(mac, 0x21, 0x3763); 553191762Simp PHY_WRITE(mac, 0x22, 0x1bc3); 554191762Simp PHY_WRITE(mac, 0x23, 0x6f9); 555191762Simp PHY_WRITE(mac, 0x24, 0x37e); 556191762Simp } else { 557191762Simp PHY_WRITE(mac, 0x26, 0xcc00); 558191762Simp } 559191762Simp PHY_WRITE(mac, 0x30, 0xc6); 560191762Simp 561191762Simp CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT); 562191762Simp 563191762Simp if (phy->phy_version == 1) 564191762Simp PHY_WRITE(mac, 0x20, 0x3e1c); 565191762Simp else 566191762Simp PHY_WRITE(mac, 0x20, 0x301c); 567191762Simp 568191762Simp if (phy->phy_version == 0) 569191762Simp CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1); 570191762Simp 571191762Simp /* Force to channel 7 */ 572191762Simp orig_chan = rf->rf_curchan; 573191762Simp bwi_rf_set_chan(mac, 7, 0); 574191762Simp 575191762Simp if (rf->rf_type != BWI_RF_T_BCM2050) { 576191762Simp RF_WRITE(mac, 0x75, 0x80); 577191762Simp RF_WRITE(mac, 0x79, 0x81); 578191762Simp } 579191762Simp 580191762Simp RF_WRITE(mac, 0x50, 0x20); 581191762Simp RF_WRITE(mac, 0x50, 0x23); 582191762Simp 583191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 584191762Simp RF_WRITE(mac, 0x50, 0x20); 585191762Simp RF_WRITE(mac, 0x5a, 0x70); 586191762Simp } 587191762Simp 588191762Simp RF_WRITE(mac, 0x5b, 0x7b); 589191762Simp RF_WRITE(mac, 0x5c, 0xb0); 590191762Simp RF_SETBITS(mac, 0x7a, 0x7); 591191762Simp 592191762Simp bwi_rf_set_chan(mac, orig_chan, 0); 593191762Simp 594191762Simp PHY_WRITE(mac, 0x14, 0x80); 595191762Simp PHY_WRITE(mac, 0x32, 0xca); 596191762Simp PHY_WRITE(mac, 0x2a, 0x88a3); 597191762Simp 598191762Simp bwi_mac_set_tpctl_11bg(mac, NULL); 599191762Simp 600191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) 601191762Simp RF_WRITE(mac, 0x5d, 0xd); 602191762Simp 603191762Simp CSR_FILT_SETBITS_2(sc, BWI_PHY_MAGIC_REG1, 0xffc0, 0x4); 604191762Simp} 605191762Simp 606191762Simpstatic void 607191762Simpbwi_phy_init_11b_rev6(struct bwi_mac *mac) 608191762Simp{ 609191762Simp struct bwi_softc *sc = mac->mac_sc; 610191762Simp struct bwi_rf *rf = &mac->mac_rf; 611191762Simp struct bwi_phy *phy = &mac->mac_phy; 612191762Simp uint16_t val, ofs; 613191762Simp u_int orig_chan; 614191762Simp 615191762Simp PHY_WRITE(mac, 0x3e, 0x817a); 616191762Simp RF_SETBITS(mac, 0x7a, 0x58); 617191762Simp 618191762Simp if (rf->rf_rev == 4 || rf->rf_rev == 5) { 619191762Simp RF_WRITE(mac, 0x51, 0x37); 620191762Simp RF_WRITE(mac, 0x52, 0x70); 621191762Simp RF_WRITE(mac, 0x53, 0xb3); 622191762Simp RF_WRITE(mac, 0x54, 0x9b); 623191762Simp RF_WRITE(mac, 0x5a, 0x88); 624191762Simp RF_WRITE(mac, 0x5b, 0x88); 625191762Simp RF_WRITE(mac, 0x5d, 0x88); 626191762Simp RF_WRITE(mac, 0x5e, 0x88); 627191762Simp RF_WRITE(mac, 0x7d, 0x88); 628191762Simp HFLAGS_SETBITS(mac, BWI_HFLAG_MAGIC1); 629191762Simp } else if (rf->rf_rev == 8) { 630191762Simp RF_WRITE(mac, 0x51, 0); 631191762Simp RF_WRITE(mac, 0x52, 0x40); 632191762Simp RF_WRITE(mac, 0x53, 0xb7); 633191762Simp RF_WRITE(mac, 0x54, 0x98); 634191762Simp RF_WRITE(mac, 0x5a, 0x88); 635191762Simp RF_WRITE(mac, 0x5b, 0x6b); 636191762Simp RF_WRITE(mac, 0x5c, 0xf); 637191762Simp if (sc->sc_card_flags & BWI_CARD_F_ALT_IQ) { 638191762Simp RF_WRITE(mac, 0x5d, 0xfa); 639191762Simp RF_WRITE(mac, 0x5e, 0xd8); 640191762Simp } else { 641191762Simp RF_WRITE(mac, 0x5d, 0xf5); 642191762Simp RF_WRITE(mac, 0x5e, 0xb8); 643191762Simp } 644191762Simp RF_WRITE(mac, 0x73, 0x3); 645191762Simp RF_WRITE(mac, 0x7d, 0xa8); 646191762Simp RF_WRITE(mac, 0x7c, 0x1); 647191762Simp RF_WRITE(mac, 0x7e, 0x8); 648191762Simp } 649191762Simp 650191762Simp val = 0x1e1f; 651191762Simp for (ofs = 0x88; ofs < 0x98; ++ofs) { 652191762Simp PHY_WRITE(mac, ofs, val); 653191762Simp val -= 0x202; 654191762Simp } 655191762Simp 656191762Simp val = 0x3e3f; 657191762Simp for (ofs = 0x98; ofs < 0xa8; ++ofs) { 658191762Simp PHY_WRITE(mac, ofs, val); 659191762Simp val -= 0x202; 660191762Simp } 661191762Simp 662191762Simp val = 0x2120; 663191762Simp for (ofs = 0xa8; ofs < 0xc8; ++ofs) { 664191762Simp PHY_WRITE(mac, ofs, (val & 0x3f3f)); 665191762Simp val += 0x202; 666192046Snwhitehorn 667192046Snwhitehorn /* XXX: delay 10 us to avoid PCI parity errors with BCM4318 */ 668192042Snwhitehorn DELAY(10); 669191762Simp } 670191762Simp 671191762Simp if (phy->phy_mode == IEEE80211_MODE_11G) { 672191762Simp RF_SETBITS(mac, 0x7a, 0x20); 673191762Simp RF_SETBITS(mac, 0x51, 0x4); 674191762Simp PHY_SETBITS(mac, 0x802, 0x100); 675191762Simp PHY_SETBITS(mac, 0x42b, 0x2000); 676191762Simp PHY_WRITE(mac, 0x5b, 0); 677191762Simp PHY_WRITE(mac, 0x5c, 0); 678191762Simp } 679191762Simp 680191762Simp /* Force to channel 7 */ 681191762Simp orig_chan = rf->rf_curchan; 682191762Simp if (orig_chan >= 8) 683191762Simp bwi_rf_set_chan(mac, 1, 0); 684191762Simp else 685191762Simp bwi_rf_set_chan(mac, 13, 0); 686191762Simp 687191762Simp RF_WRITE(mac, 0x50, 0x20); 688191762Simp RF_WRITE(mac, 0x50, 0x23); 689191762Simp 690191762Simp DELAY(40); 691191762Simp 692191762Simp if (rf->rf_rev < 6 || rf->rf_rev == 8) { 693191762Simp RF_SETBITS(mac, 0x7c, 0x2); 694191762Simp RF_WRITE(mac, 0x50, 0x20); 695191762Simp } 696191762Simp if (rf->rf_rev <= 2) { 697191762Simp RF_WRITE(mac, 0x7c, 0x20); 698191762Simp RF_WRITE(mac, 0x5a, 0x70); 699191762Simp RF_WRITE(mac, 0x5b, 0x7b); 700191762Simp RF_WRITE(mac, 0x5c, 0xb0); 701191762Simp } 702191762Simp 703191762Simp RF_FILT_SETBITS(mac, 0x7a, 0xf8, 0x7); 704191762Simp 705191762Simp bwi_rf_set_chan(mac, orig_chan, 0); 706191762Simp 707191762Simp PHY_WRITE(mac, 0x14, 0x200); 708191762Simp if (rf->rf_rev >= 6) 709191762Simp PHY_WRITE(mac, 0x2a, 0x88c2); 710191762Simp else 711191762Simp PHY_WRITE(mac, 0x2a, 0x8ac0); 712191762Simp PHY_WRITE(mac, 0x38, 0x668); 713191762Simp 714191762Simp bwi_mac_set_tpctl_11bg(mac, NULL); 715191762Simp 716191762Simp if (rf->rf_rev <= 5) { 717191762Simp PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0x3); 718191762Simp if (rf->rf_rev <= 2) 719191762Simp RF_WRITE(mac, 0x5d, 0xd); 720191762Simp } 721191762Simp 722191762Simp if (phy->phy_version == 4) { 723191762Simp CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL2); 724191762Simp PHY_CLRBITS(mac, 0x61, 0xf000); 725191762Simp } else { 726191762Simp PHY_FILT_SETBITS(mac, 0x2, 0xffc0, 0x4); 727191762Simp } 728191762Simp 729191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) { 730191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC2); 731191762Simp PHY_WRITE(mac, 0x16, 0x410); 732191762Simp PHY_WRITE(mac, 0x17, 0x820); 733191762Simp PHY_WRITE(mac, 0x62, 0x7); 734191762Simp 735191762Simp bwi_rf_init_bcm2050(mac); 736191762Simp bwi_rf_lo_update(mac); 737191762Simp if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) { 738191762Simp bwi_rf_calc_nrssi_slope(mac); 739191762Simp bwi_rf_set_nrssi_thr(mac); 740191762Simp } 741191762Simp bwi_mac_init_tpctl_11bg(mac); 742191762Simp } else { 743191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0); 744191762Simp } 745191762Simp} 746191762Simp 747191762Simp#define N(arr) (int)(sizeof(arr) / sizeof(arr[0])) 748191762Simp 749191762Simpstatic void 750191762Simpbwi_phy_config_11g(struct bwi_mac *mac) 751191762Simp{ 752191762Simp struct bwi_softc *sc = mac->mac_sc; 753191762Simp struct bwi_phy *phy = &mac->mac_phy; 754191762Simp const uint16_t *tbl; 755191762Simp uint16_t wrd_ofs1, wrd_ofs2; 756191762Simp int i, n; 757191762Simp 758191762Simp if (phy->phy_rev == 1) { 759191762Simp PHY_WRITE(mac, 0x406, 0x4f19); 760191762Simp PHY_FILT_SETBITS(mac, 0x429, 0xfc3f, 0x340); 761191762Simp PHY_WRITE(mac, 0x42c, 0x5a); 762191762Simp PHY_WRITE(mac, 0x427, 0x1a); 763191762Simp 764191762Simp /* Fill frequency table */ 765191762Simp for (i = 0; i < N(bwi_phy_freq_11g_rev1); ++i) { 766191762Simp bwi_tbl_write_2(mac, BWI_PHYTBL_FREQ + i, 767191762Simp bwi_phy_freq_11g_rev1[i]); 768191762Simp } 769191762Simp 770191762Simp /* Fill noise table */ 771191762Simp for (i = 0; i < N(bwi_phy_noise_11g_rev1); ++i) { 772191762Simp bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i, 773191762Simp bwi_phy_noise_11g_rev1[i]); 774191762Simp } 775191762Simp 776191762Simp /* Fill rotor table */ 777191762Simp for (i = 0; i < N(bwi_phy_rotor_11g_rev1); ++i) { 778191762Simp /* NB: data length is 4 bytes */ 779191762Simp bwi_tbl_write_4(mac, BWI_PHYTBL_ROTOR + i, 780191762Simp bwi_phy_rotor_11g_rev1[i]); 781191762Simp } 782191762Simp } else { 783191762Simp bwi_nrssi_write(mac, 0xba98, (int16_t)0x7654); /* XXX */ 784191762Simp 785191762Simp if (phy->phy_rev == 2) { 786191762Simp PHY_WRITE(mac, 0x4c0, 0x1861); 787191762Simp PHY_WRITE(mac, 0x4c1, 0x271); 788191762Simp } else if (phy->phy_rev > 2) { 789191762Simp PHY_WRITE(mac, 0x4c0, 0x98); 790191762Simp PHY_WRITE(mac, 0x4c1, 0x70); 791191762Simp PHY_WRITE(mac, 0x4c9, 0x80); 792191762Simp } 793191762Simp PHY_SETBITS(mac, 0x42b, 0x800); 794191762Simp 795191762Simp /* Fill RSSI table */ 796191762Simp for (i = 0; i < 64; ++i) 797191762Simp bwi_tbl_write_2(mac, BWI_PHYTBL_RSSI + i, i); 798191762Simp 799191762Simp /* Fill noise table */ 800226182Sadrian for (i = 0; i < N(bwi_phy_noise_11g); ++i) { 801191762Simp bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i, 802191762Simp bwi_phy_noise_11g[i]); 803191762Simp } 804191762Simp } 805191762Simp 806191762Simp /* 807191762Simp * Fill noise scale table 808191762Simp */ 809191762Simp if (phy->phy_rev <= 2) { 810191762Simp tbl = bwi_phy_noise_scale_11g_rev2; 811191762Simp n = N(bwi_phy_noise_scale_11g_rev2); 812191762Simp } else if (phy->phy_rev >= 7 && (PHY_READ(mac, 0x449) & 0x200)) { 813191762Simp tbl = bwi_phy_noise_scale_11g_rev7; 814191762Simp n = N(bwi_phy_noise_scale_11g_rev7); 815191762Simp } else { 816191762Simp tbl = bwi_phy_noise_scale_11g; 817191762Simp n = N(bwi_phy_noise_scale_11g); 818191762Simp } 819191762Simp for (i = 0; i < n; ++i) 820191762Simp bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE_SCALE + i, tbl[i]); 821191762Simp 822191762Simp /* 823191762Simp * Fill sigma square table 824191762Simp */ 825191762Simp if (phy->phy_rev == 2) { 826191762Simp tbl = bwi_phy_sigma_sq_11g_rev2; 827191762Simp n = N(bwi_phy_sigma_sq_11g_rev2); 828191762Simp } else if (phy->phy_rev > 2 && phy->phy_rev <= 8) { 829191762Simp tbl = bwi_phy_sigma_sq_11g_rev7; 830191762Simp n = N(bwi_phy_sigma_sq_11g_rev7); 831191762Simp } else { 832191762Simp tbl = NULL; 833191762Simp n = 0; 834191762Simp } 835191762Simp for (i = 0; i < n; ++i) 836191762Simp bwi_tbl_write_2(mac, BWI_PHYTBL_SIGMA_SQ + i, tbl[i]); 837191762Simp 838191762Simp if (phy->phy_rev == 1) { 839191762Simp /* Fill delay table */ 840191762Simp for (i = 0; i < N(bwi_phy_delay_11g_rev1); ++i) { 841191762Simp bwi_tbl_write_4(mac, BWI_PHYTBL_DELAY + i, 842191762Simp bwi_phy_delay_11g_rev1[i]); 843191762Simp } 844191762Simp 845191762Simp /* Fill WRSSI (Wide-Band RSSI) table */ 846191762Simp for (i = 4; i < 20; ++i) 847191762Simp bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI_REV1 + i, 0x20); 848191762Simp 849191762Simp bwi_phy_config_agc(mac); 850191762Simp 851191762Simp wrd_ofs1 = 0x5001; 852191762Simp wrd_ofs2 = 0x5002; 853191762Simp } else { 854191762Simp /* Fill WRSSI (Wide-Band RSSI) table */ 855191762Simp for (i = 0; i < 0x20; ++i) 856191762Simp bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI + i, 0x820); 857191762Simp 858191762Simp bwi_phy_config_agc(mac); 859191762Simp 860191762Simp PHY_READ(mac, 0x400); /* Dummy read */ 861191762Simp PHY_WRITE(mac, 0x403, 0x1000); 862191762Simp bwi_tbl_write_2(mac, 0x3c02, 0xf); 863191762Simp bwi_tbl_write_2(mac, 0x3c03, 0x14); 864191762Simp 865191762Simp wrd_ofs1 = 0x401; 866191762Simp wrd_ofs2 = 0x402; 867191762Simp } 868191762Simp 869191762Simp if (!(BWI_IS_BRCM_BU4306(sc) && sc->sc_pci_revid == 0x17)) { 870191762Simp bwi_tbl_write_2(mac, wrd_ofs1, 0x2); 871191762Simp bwi_tbl_write_2(mac, wrd_ofs2, 0x1); 872191762Simp } 873191762Simp 874191762Simp /* phy->phy_flags & BWI_PHY_F_LINKED ? */ 875191762Simp if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) 876191762Simp PHY_WRITE(mac, 0x46e, 0x3cf); 877191762Simp} 878191762Simp 879191762Simp#undef N 880191762Simp 881191762Simp/* 882191762Simp * Configure Automatic Gain Controller 883191762Simp */ 884191762Simpstatic void 885191762Simpbwi_phy_config_agc(struct bwi_mac *mac) 886191762Simp{ 887191762Simp struct bwi_phy *phy = &mac->mac_phy; 888191762Simp uint16_t ofs; 889191762Simp 890191762Simp ofs = phy->phy_rev == 1 ? 0x4c00 : 0; 891191762Simp 892191762Simp bwi_tbl_write_2(mac, ofs, 0xfe); 893191762Simp bwi_tbl_write_2(mac, ofs + 1, 0xd); 894191762Simp bwi_tbl_write_2(mac, ofs + 2, 0x13); 895191762Simp bwi_tbl_write_2(mac, ofs + 3, 0x19); 896191762Simp 897191762Simp if (phy->phy_rev == 1) { 898191762Simp bwi_tbl_write_2(mac, 0x1800, 0x2710); 899191762Simp bwi_tbl_write_2(mac, 0x1801, 0x9b83); 900191762Simp bwi_tbl_write_2(mac, 0x1802, 0x9b83); 901191762Simp bwi_tbl_write_2(mac, 0x1803, 0xf8d); 902191762Simp PHY_WRITE(mac, 0x455, 0x4); 903191762Simp } 904191762Simp 905191762Simp PHY_FILT_SETBITS(mac, 0x4a5, 0xff, 0x5700); 906191762Simp PHY_FILT_SETBITS(mac, 0x41a, 0xff80, 0xf); 907191762Simp PHY_FILT_SETBITS(mac, 0x41a, 0xc07f, 0x2b80); 908191762Simp PHY_FILT_SETBITS(mac, 0x48c, 0xf0ff, 0x300); 909191762Simp 910191762Simp RF_SETBITS(mac, 0x7a, 0x8); 911191762Simp 912191762Simp PHY_FILT_SETBITS(mac, 0x4a0, 0xfff0, 0x8); 913191762Simp PHY_FILT_SETBITS(mac, 0x4a1, 0xf0ff, 0x600); 914191762Simp PHY_FILT_SETBITS(mac, 0x4a2, 0xf0ff, 0x700); 915191762Simp PHY_FILT_SETBITS(mac, 0x4a0, 0xf0ff, 0x100); 916191762Simp 917191762Simp if (phy->phy_rev == 1) 918191762Simp PHY_FILT_SETBITS(mac, 0x4a2, 0xfff0, 0x7); 919191762Simp 920191762Simp PHY_FILT_SETBITS(mac, 0x488, 0xff00, 0x1c); 921191762Simp PHY_FILT_SETBITS(mac, 0x488, 0xc0ff, 0x200); 922191762Simp PHY_FILT_SETBITS(mac, 0x496, 0xff00, 0x1c); 923191762Simp PHY_FILT_SETBITS(mac, 0x489, 0xff00, 0x20); 924191762Simp PHY_FILT_SETBITS(mac, 0x489, 0xc0ff, 0x200); 925191762Simp PHY_FILT_SETBITS(mac, 0x482, 0xff00, 0x2e); 926191762Simp PHY_FILT_SETBITS(mac, 0x496, 0xff, 0x1a00); 927191762Simp PHY_FILT_SETBITS(mac, 0x481, 0xff00, 0x28); 928191762Simp PHY_FILT_SETBITS(mac, 0x481, 0xff, 0x2c00); 929191762Simp 930191762Simp if (phy->phy_rev == 1) { 931191762Simp PHY_WRITE(mac, 0x430, 0x92b); 932191762Simp PHY_FILT_SETBITS(mac, 0x41b, 0xffe1, 0x2); 933191762Simp } else { 934191762Simp PHY_CLRBITS(mac, 0x41b, 0x1e); 935191762Simp PHY_WRITE(mac, 0x41f, 0x287a); 936191762Simp PHY_FILT_SETBITS(mac, 0x420, 0xfff0, 0x4); 937191762Simp 938191762Simp if (phy->phy_rev >= 6) { 939191762Simp PHY_WRITE(mac, 0x422, 0x287a); 940191762Simp PHY_FILT_SETBITS(mac, 0x420, 0xfff, 0x3000); 941191762Simp } 942191762Simp } 943191762Simp 944191762Simp PHY_FILT_SETBITS(mac, 0x4a8, 0x8080, 0x7874); 945191762Simp PHY_WRITE(mac, 0x48e, 0x1c00); 946191762Simp 947191762Simp if (phy->phy_rev == 1) { 948191762Simp PHY_FILT_SETBITS(mac, 0x4ab, 0xf0ff, 0x600); 949191762Simp PHY_WRITE(mac, 0x48b, 0x5e); 950191762Simp PHY_FILT_SETBITS(mac, 0x48c, 0xff00, 0x1e); 951191762Simp PHY_WRITE(mac, 0x48d, 0x2); 952191762Simp } 953191762Simp 954191762Simp bwi_tbl_write_2(mac, ofs + 0x800, 0); 955191762Simp bwi_tbl_write_2(mac, ofs + 0x801, 7); 956191762Simp bwi_tbl_write_2(mac, ofs + 0x802, 16); 957191762Simp bwi_tbl_write_2(mac, ofs + 0x803, 28); 958191762Simp 959191762Simp if (phy->phy_rev >= 6) { 960191762Simp PHY_CLRBITS(mac, 0x426, 0x3); 961191762Simp PHY_CLRBITS(mac, 0x426, 0x1000); 962191762Simp } 963191762Simp} 964191762Simp 965191762Simpvoid 966191762Simpbwi_set_gains(struct bwi_mac *mac, const struct bwi_gains *gains) 967191762Simp{ 968191762Simp struct bwi_phy *phy = &mac->mac_phy; 969191762Simp uint16_t tbl_gain_ofs1, tbl_gain_ofs2, tbl_gain; 970191762Simp int i; 971191762Simp 972191762Simp if (phy->phy_rev <= 1) { 973191762Simp tbl_gain_ofs1 = 0x5000; 974191762Simp tbl_gain_ofs2 = tbl_gain_ofs1 + 16; 975191762Simp } else { 976191762Simp tbl_gain_ofs1 = 0x400; 977191762Simp tbl_gain_ofs2 = tbl_gain_ofs1 + 8; 978191762Simp } 979191762Simp 980191762Simp for (i = 0; i < 4; ++i) { 981191762Simp if (gains != NULL) { 982191762Simp tbl_gain = gains->tbl_gain1; 983191762Simp } else { 984191762Simp /* Bit swap */ 985191762Simp tbl_gain = (i & 0x1) << 1; 986191762Simp tbl_gain |= (i & 0x2) >> 1; 987191762Simp } 988191762Simp bwi_tbl_write_2(mac, tbl_gain_ofs1 + i, tbl_gain); 989191762Simp } 990191762Simp 991191762Simp for (i = 0; i < 16; ++i) { 992191762Simp if (gains != NULL) 993191762Simp tbl_gain = gains->tbl_gain2; 994191762Simp else 995191762Simp tbl_gain = i; 996191762Simp bwi_tbl_write_2(mac, tbl_gain_ofs2 + i, tbl_gain); 997191762Simp } 998191762Simp 999191762Simp if (gains == NULL || (gains != NULL && gains->phy_gain != -1)) { 1000191762Simp uint16_t phy_gain1, phy_gain2; 1001191762Simp 1002191762Simp if (gains != NULL) { 1003191762Simp phy_gain1 = 1004191762Simp ((uint16_t)gains->phy_gain << 14) | 1005191762Simp ((uint16_t)gains->phy_gain << 6); 1006191762Simp phy_gain2 = phy_gain1; 1007191762Simp } else { 1008191762Simp phy_gain1 = 0x4040; 1009191762Simp phy_gain2 = 0x4000; 1010191762Simp } 1011191762Simp PHY_FILT_SETBITS(mac, 0x4a0, 0xbfbf, phy_gain1); 1012191762Simp PHY_FILT_SETBITS(mac, 0x4a1, 0xbfbf, phy_gain1); 1013191762Simp PHY_FILT_SETBITS(mac, 0x4a2, 0xbfbf, phy_gain2); 1014191762Simp } 1015191762Simp bwi_mac_dummy_xmit(mac); 1016191762Simp} 1017191762Simp 1018191762Simpvoid 1019191762Simpbwi_phy_clear_state(struct bwi_phy *phy) 1020191762Simp{ 1021191762Simp phy->phy_flags &= ~BWI_CLEAR_PHY_FLAGS; 1022191762Simp} 1023