1299758Sadrian/*- 2299758Sadrian * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org> 3299758Sadrian * Copyright (c) 2016 Adrian Chadd <adrian@freebsd.org> 4299758Sadrian * All rights reserved. 5299758Sadrian * 6299758Sadrian * Redistribution and use in source and binary forms, with or without 7299758Sadrian * modification, are permitted provided that the following conditions 8299758Sadrian * are met: 9299758Sadrian * 1. Redistributions of source code must retain the above copyright 10299758Sadrian * notice, this list of conditions and the following disclaimer, 11299758Sadrian * without modification. 12299758Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 13299758Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 14299758Sadrian * redistribution must be conditioned upon including a substantially 15299758Sadrian * similar Disclaimer requirement for further binary redistribution. 16299758Sadrian * 17299758Sadrian * NO WARRANTY 18299758Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19299758Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20299758Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 21299758Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22299758Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 23299758Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24299758Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25299758Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26299758Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27299758Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28299758Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 29299758Sadrian */ 30299758Sadrian 31299758Sadrian#include <sys/cdefs.h> 32299758Sadrian__FBSDID("$FreeBSD: releng/11.0/sys/dev/bwn/if_bwn_phy_common.c 300549 2016-05-24 01:20:30Z adrian $"); 33299758Sadrian 34299984Sadrian#include "opt_bwn.h" 35299984Sadrian#include "opt_wlan.h" 36299984Sadrian 37299758Sadrian/* 38299758Sadrian * The Broadcom Wireless LAN controller driver. 39299758Sadrian */ 40299758Sadrian 41299758Sadrian#include <sys/param.h> 42299758Sadrian#include <sys/systm.h> 43299758Sadrian#include <sys/kernel.h> 44299758Sadrian#include <sys/malloc.h> 45299758Sadrian#include <sys/module.h> 46299758Sadrian#include <sys/endian.h> 47299758Sadrian#include <sys/errno.h> 48299758Sadrian#include <sys/firmware.h> 49299758Sadrian#include <sys/lock.h> 50299758Sadrian#include <sys/mutex.h> 51299758Sadrian#include <machine/bus.h> 52299758Sadrian#include <machine/resource.h> 53299758Sadrian#include <sys/bus.h> 54299758Sadrian#include <sys/rman.h> 55299758Sadrian#include <sys/socket.h> 56299758Sadrian#include <sys/sockio.h> 57299758Sadrian 58299758Sadrian#include <net/ethernet.h> 59299758Sadrian#include <net/if.h> 60299758Sadrian#include <net/if_var.h> 61299758Sadrian#include <net/if_arp.h> 62299758Sadrian#include <net/if_dl.h> 63299758Sadrian#include <net/if_llc.h> 64299758Sadrian#include <net/if_media.h> 65299758Sadrian#include <net/if_types.h> 66299758Sadrian 67299758Sadrian#include <dev/pci/pcivar.h> 68299758Sadrian#include <dev/pci/pcireg.h> 69299758Sadrian#include <dev/siba/siba_ids.h> 70299758Sadrian#include <dev/siba/sibareg.h> 71299758Sadrian#include <dev/siba/sibavar.h> 72299758Sadrian 73299758Sadrian#include <net80211/ieee80211_var.h> 74299758Sadrian#include <net80211/ieee80211_radiotap.h> 75299758Sadrian#include <net80211/ieee80211_regdomain.h> 76299758Sadrian#include <net80211/ieee80211_phy.h> 77299758Sadrian#include <net80211/ieee80211_ratectl.h> 78299758Sadrian 79299758Sadrian#include <dev/bwn/if_bwnreg.h> 80299758Sadrian#include <dev/bwn/if_bwnvar.h> 81299758Sadrian 82299758Sadrian#include <dev/bwn/if_bwn_chipid.h> 83299758Sadrian#include <dev/bwn/if_bwn_debug.h> 84299758Sadrian#include <dev/bwn/if_bwn_misc.h> 85299758Sadrian#include <dev/bwn/if_bwn_phy_common.h> 86299758Sadrian 87299758Sadrianvoid 88299758Sadrianbwn_mac_switch_freq(struct bwn_mac *mac, int spurmode) 89299758Sadrian{ 90299758Sadrian struct bwn_softc *sc = mac->mac_sc; 91299758Sadrian uint16_t chip_id = siba_get_chipid(sc->sc_dev); 92299758Sadrian 93299758Sadrian if (chip_id == BCMA_CHIP_ID_BCM4331) { 94299758Sadrian switch (spurmode) { 95299758Sadrian case 2: /* 168 Mhz: 2^26/168 = 0x61862 */ 96299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x1862); 97299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x6); 98299758Sadrian break; 99299758Sadrian case 1: /* 164 Mhz: 2^26/164 = 0x63e70 */ 100299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x3e70); 101299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x6); 102299758Sadrian break; 103299758Sadrian default: /* 160 Mhz: 2^26/160 = 0x66666 */ 104299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x6666); 105299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x6); 106299758Sadrian break; 107299758Sadrian } 108299758Sadrian } else if (chip_id == BCMA_CHIP_ID_BCM43131 || 109299758Sadrian chip_id == BCMA_CHIP_ID_BCM43217 || 110299758Sadrian chip_id == BCMA_CHIP_ID_BCM43222 || 111299758Sadrian chip_id == BCMA_CHIP_ID_BCM43224 || 112299758Sadrian chip_id == BCMA_CHIP_ID_BCM43225 || 113299758Sadrian chip_id == BCMA_CHIP_ID_BCM43227 || 114299758Sadrian chip_id == BCMA_CHIP_ID_BCM43228) { 115299758Sadrian switch (spurmode) { 116299758Sadrian case 2: /* 126 Mhz */ 117299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x2082); 118299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x8); 119299758Sadrian break; 120299758Sadrian case 1: /* 123 Mhz */ 121299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x5341); 122299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x8); 123299758Sadrian break; 124299758Sadrian default: /* 120 Mhz */ 125299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x8889); 126299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x8); 127299758Sadrian break; 128299758Sadrian } 129299758Sadrian } else if (mac->mac_phy.type == BWN_PHYTYPE_LCN) { 130299758Sadrian switch (spurmode) { 131299758Sadrian case 1: /* 82 Mhz */ 132299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x7CE0); 133299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0xC); 134299758Sadrian break; 135299758Sadrian default: /* 80 Mhz */ 136299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0xCCCD); 137299758Sadrian BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0xC); 138299758Sadrian break; 139299758Sadrian } 140299758Sadrian } 141299758Sadrian} 142299758Sadrian 143299758Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ 144299758Sadrianvoid 145299758Sadrianbwn_phy_force_clock(struct bwn_mac *mac, int force) 146299758Sadrian{ 147299758Sadrian struct bwn_softc *sc = mac->mac_sc; 148299758Sadrian uint32_t tmp; 149299758Sadrian 150299758Sadrian /* XXX Only for N, HT and AC PHYs */ 151299758Sadrian 152299758Sadrian /* XXX bhnd bus */ 153299758Sadrian if (bwn_is_bus_siba(mac)) { 154299758Sadrian tmp = siba_read_4(sc->sc_dev, SIBA_TGSLOW); 155299758Sadrian if (force) 156299758Sadrian tmp |= SIBA_TGSLOW_FGC; 157299758Sadrian else 158299758Sadrian tmp &= ~SIBA_TGSLOW_FGC; 159299758Sadrian siba_write_4(sc->sc_dev, SIBA_TGSLOW, tmp); 160300549Sadrian } else { 161300549Sadrian BWN_ERRPRINTF(sc, "%s: unknown bus!\n", __func__); 162299758Sadrian } 163299758Sadrian} 164299758Sadrian 165299758Sadrianint 166299758Sadrianbwn_radio_wait_value(struct bwn_mac *mac, uint16_t offset, uint16_t mask, 167299758Sadrian uint16_t value, int delay, int timeout) 168299758Sadrian{ 169299758Sadrian uint16_t val; 170299758Sadrian int i; 171299758Sadrian 172299758Sadrian for (i = 0; i < timeout; i += delay) { 173299758Sadrian val = BWN_RF_READ(mac, offset); 174299758Sadrian if ((val & mask) == value) 175299758Sadrian return (1); 176299758Sadrian DELAY(delay); 177299758Sadrian } 178299758Sadrian return (0); 179299758Sadrian} 180299758Sadrian 181299758Sadrianvoid 182299758Sadrianbwn_mac_phy_clock_set(struct bwn_mac *mac, int enabled) 183299758Sadrian{ 184299758Sadrian struct bwn_softc *sc = mac->mac_sc; 185299758Sadrian uint32_t val; 186299758Sadrian 187299758Sadrian /* XXX bhnd bus */ 188299758Sadrian if (bwn_is_bus_siba(mac)) { 189299758Sadrian val = siba_read_4(sc->sc_dev, SIBA_TGSLOW); 190299758Sadrian if (enabled) 191300186Sadrian val |= BWN_TGSLOW_MACPHYCLKEN; 192299758Sadrian else 193300186Sadrian val &= ~BWN_TGSLOW_MACPHYCLKEN; 194299758Sadrian siba_write_4(sc->sc_dev, SIBA_TGSLOW, val); 195300549Sadrian } else { 196300549Sadrian BWN_ERRPRINTF(sc, "%s: unknown bus!\n", __func__); 197299758Sadrian } 198299758Sadrian} 199299758Sadrian 200299758Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/BmacCorePllReset */ 201299758Sadrianvoid 202299758Sadrianbwn_wireless_core_phy_pll_reset(struct bwn_mac *mac) 203299758Sadrian{ 204299758Sadrian struct bwn_softc *sc = mac->mac_sc; 205299758Sadrian 206299758Sadrian /* XXX bhnd bus */ 207299758Sadrian if (bwn_is_bus_siba(mac)) { 208299758Sadrian siba_cc_write32(sc->sc_dev, SIBA_CC_CHIPCTL_ADDR, 0); 209299758Sadrian siba_cc_mask32(sc->sc_dev, SIBA_CC_CHIPCTL_DATA, ~0x4); 210299758Sadrian siba_cc_set32(sc->sc_dev, SIBA_CC_CHIPCTL_DATA, 0x4); 211299758Sadrian siba_cc_mask32(sc->sc_dev, SIBA_CC_CHIPCTL_DATA, ~0x4); 212300549Sadrian } else { 213300549Sadrian BWN_ERRPRINTF(sc, "%s: unknown bus!\n", __func__); 214299758Sadrian } 215299758Sadrian} 216