if_bwn_phy_common.c revision 299758
1/*- 2 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org> 3 * Copyright (c) 2016 Adrian Chadd <adrian@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer, 11 * without modification. 12 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 13 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 14 * redistribution must be conditioned upon including a substantially 15 * similar Disclaimer requirement for further binary redistribution. 16 * 17 * NO WARRANTY 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 23 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 26 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGES. 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD: head/sys/dev/bwn/if_bwn_phy_common.c 299758 2016-05-14 20:11:48Z adrian $"); 33 34/* 35 * The Broadcom Wireless LAN controller driver. 36 */ 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/malloc.h> 42#include <sys/module.h> 43#include <sys/endian.h> 44#include <sys/errno.h> 45#include <sys/firmware.h> 46#include <sys/lock.h> 47#include <sys/mutex.h> 48#include <machine/bus.h> 49#include <machine/resource.h> 50#include <sys/bus.h> 51#include <sys/rman.h> 52#include <sys/socket.h> 53#include <sys/sockio.h> 54 55#include <net/ethernet.h> 56#include <net/if.h> 57#include <net/if_var.h> 58#include <net/if_arp.h> 59#include <net/if_dl.h> 60#include <net/if_llc.h> 61#include <net/if_media.h> 62#include <net/if_types.h> 63 64#include <dev/pci/pcivar.h> 65#include <dev/pci/pcireg.h> 66#include <dev/siba/siba_ids.h> 67#include <dev/siba/sibareg.h> 68#include <dev/siba/sibavar.h> 69 70#include <net80211/ieee80211_var.h> 71#include <net80211/ieee80211_radiotap.h> 72#include <net80211/ieee80211_regdomain.h> 73#include <net80211/ieee80211_phy.h> 74#include <net80211/ieee80211_ratectl.h> 75 76#include <dev/bwn/if_bwnreg.h> 77#include <dev/bwn/if_bwnvar.h> 78 79#include <dev/bwn/if_bwn_chipid.h> 80#include <dev/bwn/if_bwn_debug.h> 81#include <dev/bwn/if_bwn_misc.h> 82#include <dev/bwn/if_bwn_phy_common.h> 83 84void 85bwn_mac_switch_freq(struct bwn_mac *mac, int spurmode) 86{ 87 struct bwn_softc *sc = mac->mac_sc; 88 uint16_t chip_id = siba_get_chipid(sc->sc_dev); 89 90 if (chip_id == BCMA_CHIP_ID_BCM4331) { 91 switch (spurmode) { 92 case 2: /* 168 Mhz: 2^26/168 = 0x61862 */ 93 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x1862); 94 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x6); 95 break; 96 case 1: /* 164 Mhz: 2^26/164 = 0x63e70 */ 97 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x3e70); 98 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x6); 99 break; 100 default: /* 160 Mhz: 2^26/160 = 0x66666 */ 101 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x6666); 102 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x6); 103 break; 104 } 105 } else if (chip_id == BCMA_CHIP_ID_BCM43131 || 106 chip_id == BCMA_CHIP_ID_BCM43217 || 107 chip_id == BCMA_CHIP_ID_BCM43222 || 108 chip_id == BCMA_CHIP_ID_BCM43224 || 109 chip_id == BCMA_CHIP_ID_BCM43225 || 110 chip_id == BCMA_CHIP_ID_BCM43227 || 111 chip_id == BCMA_CHIP_ID_BCM43228) { 112 switch (spurmode) { 113 case 2: /* 126 Mhz */ 114 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x2082); 115 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x8); 116 break; 117 case 1: /* 123 Mhz */ 118 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x5341); 119 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x8); 120 break; 121 default: /* 120 Mhz */ 122 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x8889); 123 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0x8); 124 break; 125 } 126 } else if (mac->mac_phy.type == BWN_PHYTYPE_LCN) { 127 switch (spurmode) { 128 case 1: /* 82 Mhz */ 129 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0x7CE0); 130 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0xC); 131 break; 132 default: /* 80 Mhz */ 133 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_LOW, 0xCCCD); 134 BWN_WRITE_2(mac, BWN_TSF_CLK_FRAC_HIGH, 0xC); 135 break; 136 } 137 } 138} 139 140/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ 141void 142bwn_phy_force_clock(struct bwn_mac *mac, int force) 143{ 144 struct bwn_softc *sc = mac->mac_sc; 145 uint32_t tmp; 146 147 /* XXX Only for N, HT and AC PHYs */ 148 149 /* XXX bhnd bus */ 150 if (bwn_is_bus_siba(mac)) { 151 tmp = siba_read_4(sc->sc_dev, SIBA_TGSLOW); 152 if (force) 153 tmp |= SIBA_TGSLOW_FGC; 154 else 155 tmp &= ~SIBA_TGSLOW_FGC; 156 siba_write_4(sc->sc_dev, SIBA_TGSLOW, tmp); 157 } 158} 159 160int 161bwn_radio_wait_value(struct bwn_mac *mac, uint16_t offset, uint16_t mask, 162 uint16_t value, int delay, int timeout) 163{ 164 uint16_t val; 165 int i; 166 167 for (i = 0; i < timeout; i += delay) { 168 val = BWN_RF_READ(mac, offset); 169 if ((val & mask) == value) 170 return (1); 171 DELAY(delay); 172 } 173 return (0); 174} 175 176void 177bwn_mac_phy_clock_set(struct bwn_mac *mac, int enabled) 178{ 179 struct bwn_softc *sc = mac->mac_sc; 180 uint32_t val; 181 182 /* XXX bhnd bus */ 183 if (bwn_is_bus_siba(mac)) { 184 val = siba_read_4(sc->sc_dev, SIBA_TGSLOW); 185 if (enabled) 186 val |= BWN_TMSLOW_MACPHYCLKEN; 187 else 188 val &= ~BWN_TMSLOW_MACPHYCLKEN; 189 siba_write_4(sc->sc_dev, SIBA_TGSLOW, val); 190 } 191} 192 193/* http://bcm-v4.sipsolutions.net/802.11/PHY/BmacCorePllReset */ 194void 195bwn_wireless_core_phy_pll_reset(struct bwn_mac *mac) 196{ 197 struct bwn_softc *sc = mac->mac_sc; 198 199 /* XXX bhnd bus */ 200 if (bwn_is_bus_siba(mac)) { 201 siba_cc_write32(sc->sc_dev, SIBA_CC_CHIPCTL_ADDR, 0); 202 siba_cc_mask32(sc->sc_dev, SIBA_CC_CHIPCTL_DATA, ~0x4); 203 siba_cc_set32(sc->sc_dev, SIBA_CC_CHIPCTL_DATA, 0x4); 204 siba_cc_mask32(sc->sc_dev, SIBA_CC_CHIPCTL_DATA, ~0x4); 205 } 206} 207