1 /* 2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * $FreeBSD$ 18 */ 19 #include "opt_ah.h" 20 21 #include "ah.h" 22 #include "ah_internal.h" 23 #include "ah_devid.h" 24 25 #include "ar5312/ar5312.h" 26 #include "ar5312/ar5312reg.h" 27 #include "ar5312/ar5312phy.h" 28 29 /* Add static register initialization vectors */ 30 #define AH_5212_COMMON 31 #include "ar5212/ar5212.ini" 32 33 static HAL_BOOL ar5312GetMacAddr(struct ath_hal *ah); 34 35 static void 36 ar5312AniSetup(struct ath_hal *ah) 37 { 38 static const struct ar5212AniParams aniparams = { 39 .maxNoiseImmunityLevel = 4, /* levels 0..4 */ 40 .totalSizeDesired = { -41, -41, -48, -48, -48 }, 41 .coarseHigh = { -18, -18, -16, -14, -12 }, 42 .coarseLow = { -56, -56, -60, -60, -60 }, 43 .firpwr = { -72, -72, -75, -78, -80 }, 44 .maxSpurImmunityLevel = 2, 45 .cycPwrThr1 = { 2, 4, 6 }, 46 .maxFirstepLevel = 2, /* levels 0..2 */ 47 .firstep = { 0, 4, 8 }, 48 .ofdmTrigHigh = 500, 49 .ofdmTrigLow = 200, 50 .cckTrigHigh = 200, 51 .cckTrigLow = 100, 52 .rssiThrHigh = 40, 53 .rssiThrLow = 7, 54 .period = 100, 55 }; 56 ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE); 57 } 58 59 /* 60 * Attach for an AR5312 part. 61 */ 62 static struct ath_hal * 63 ar5312Attach(uint16_t devid, HAL_SOFTC sc, 64 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 65 HAL_OPS_CONFIG *ah_config, HAL_STATUS *status) 66 { 67 struct ath_hal_5212 *ahp = AH_NULL; 68 struct ath_hal *ah; 69 struct ath_hal_rf *rf; 70 uint32_t val; 71 uint16_t eeval; 72 HAL_STATUS ecode; 73 74 HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 75 __func__, sc, st, (void*) sh); 76 77 /* NB: memory is returned zero'd */ 78 ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); 79 if (ahp == AH_NULL) { 80 HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 81 "%s: cannot allocate memory for state block\n", __func__); 82 *status = HAL_ENOMEM; 83 return AH_NULL; 84 } 85 ar5212InitState(ahp, devid, sc, st, sh, status); 86 ah = &ahp->ah_priv.h; 87 88 /* override 5212 methods for our needs */ 89 ah->ah_reset = ar5312Reset; 90 ah->ah_phyDisable = ar5312PhyDisable; 91 ah->ah_setLedState = ar5312SetLedState; 92 ah->ah_detectCardPresent = ar5312DetectCardPresent; 93 ah->ah_setPowerMode = ar5312SetPowerMode; 94 ah->ah_getPowerMode = ar5312GetPowerMode; 95 ah->ah_isInterruptPending = ar5312IsInterruptPending; 96 97 ahp->ah_priv.ah_eepromRead = ar5312EepromRead; 98 #ifdef AH_SUPPORT_WRITE_EEPROM 99 ahp->ah_priv.ah_eepromWrite = ar5312EepromWrite; 100 #endif 101 #if ( AH_SUPPORT_2316 || AH_SUPPORT_2317) 102 if (IS_5315(ah)) { 103 ahp->ah_priv.ah_gpioCfgOutput = ar5315GpioCfgOutput; 104 ahp->ah_priv.ah_gpioCfgInput = ar5315GpioCfgInput; 105 ahp->ah_priv.ah_gpioGet = ar5315GpioGet; 106 ahp->ah_priv.ah_gpioSet = ar5315GpioSet; 107 ahp->ah_priv.ah_gpioSetIntr = ar5315GpioSetIntr; 108 } else 109 #endif 110 { 111 ahp->ah_priv.ah_gpioCfgOutput = ar5312GpioCfgOutput; 112 ahp->ah_priv.ah_gpioCfgInput = ar5312GpioCfgInput; 113 ahp->ah_priv.ah_gpioGet = ar5312GpioGet; 114 ahp->ah_priv.ah_gpioSet = ar5312GpioSet; 115 ahp->ah_priv.ah_gpioSetIntr = ar5312GpioSetIntr; 116 } 117 118 ah->ah_gpioCfgInput = ahp->ah_priv.ah_gpioCfgInput; 119 ah->ah_gpioCfgOutput = ahp->ah_priv.ah_gpioCfgOutput; 120 ah->ah_gpioGet = ahp->ah_priv.ah_gpioGet; 121 ah->ah_gpioSet = ahp->ah_priv.ah_gpioSet; 122 ah->ah_gpioSetIntr = ahp->ah_priv.ah_gpioSetIntr; 123 124 /* setup common ini data; rf backends handle remainder */ 125 HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6); 126 HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2); 127 128 if (!ar5312ChipReset(ah, AH_NULL)) { /* reset chip */ 129 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); 130 ecode = HAL_EIO; 131 goto bad; 132 } 133 134 #if ( AH_SUPPORT_2316 || AH_SUPPORT_2317) 135 if ((devid == AR5212_AR2315_REV6) || 136 (devid == AR5212_AR2315_REV7) || 137 (devid == AR5212_AR2317_REV1) || 138 (devid == AR5212_AR2317_REV2) ) { 139 val = ((OS_REG_READ(ah, (AR5315_RSTIMER_BASE -((uint32_t) sh)) + AR5315_WREV)) >> AR5315_WREV_S) 140 & AR5315_WREV_ID; 141 AH_PRIVATE(ah)->ah_macVersion = val >> AR5315_WREV_ID_S; 142 AH_PRIVATE(ah)->ah_macRev = val & AR5315_WREV_REVISION; 143 HALDEBUG(ah, HAL_DEBUG_ATTACH, 144 "%s: Mac Chip Rev 0x%02x.%x\n" , __func__, 145 AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev); 146 } else 147 #endif 148 { 149 val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0020); 150 val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0080); 151 /* Read Revisions from Chips */ 152 val = ((OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + AR5312_WREV)) >> AR5312_WREV_S) & AR5312_WREV_ID; 153 AH_PRIVATE(ah)->ah_macVersion = val >> AR5312_WREV_ID_S; 154 AH_PRIVATE(ah)->ah_macRev = val & AR5312_WREV_REVISION; 155 } 156 /* XXX - THIS IS WRONG. NEEDS TO BE FIXED */ 157 if (((AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE && 158 AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE) || 159 AH_PRIVATE(ah)->ah_macRev < AR_SREV_D2PLUS) && 160 AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_COBRA) { 161 #ifdef AH_DEBUG 162 ath_hal_printf(ah, "%s: Mac Chip Rev 0x%02x.%x is not supported by " 163 "this driver\n", __func__, 164 AH_PRIVATE(ah)->ah_macVersion, 165 AH_PRIVATE(ah)->ah_macRev); 166 #endif 167 ecode = HAL_ENOTSUPP; 168 goto bad; 169 } 170 171 AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 172 173 if (!ar5212ChipTest(ah)) { 174 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 175 __func__); 176 ecode = HAL_ESELFTEST; 177 goto bad; 178 } 179 180 /* 181 * Set correct Baseband to analog shift 182 * setting to access analog chips. 183 */ 184 OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 185 186 /* Read Radio Chip Rev Extract */ 187 AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); 188 189 rf = ath_hal_rfprobe(ah, &ecode); 190 if (rf == AH_NULL) 191 goto bad; 192 if (IS_RAD5112(ah) && !IS_RADX112_REV2(ah)) { 193 #ifdef AH_DEBUG 194 ath_hal_printf(ah, "%s: 5112 Rev 1 is not supported by this " 195 "driver (analog5GhzRev 0x%x)\n", __func__, 196 AH_PRIVATE(ah)->ah_analog5GhzRev); 197 #endif 198 ecode = HAL_ENOTSUPP; 199 goto bad; 200 } 201 202 ecode = ath_hal_legacyEepromAttach(ah); 203 if (ecode != HAL_OK) { 204 goto bad; 205 } 206 207 /* 208 * If Bmode and AR5212, verify 2.4 analog exists 209 */ 210 if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) && 211 (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) { 212 /* 213 * Set correct Baseband to analog shift 214 * setting to access analog chips. 215 */ 216 OS_REG_WRITE(ah, AR_PHY(0), 0x00004007); 217 OS_DELAY(2000); 218 AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah); 219 220 /* Set baseband for 5GHz chip */ 221 OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 222 OS_DELAY(2000); 223 if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) { 224 #ifdef AH_DEBUG 225 ath_hal_printf(ah, "%s: 2G Radio Chip Rev 0x%02X is not " 226 "supported by this driver\n", __func__, 227 AH_PRIVATE(ah)->ah_analog2GhzRev); 228 #endif 229 ecode = HAL_ENOTSUPP; 230 goto bad; 231 } 232 } 233 234 ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); 235 if (ecode != HAL_OK) { 236 HALDEBUG(ah, HAL_DEBUG_ANY, 237 "%s: cannot read regulatory domain from EEPROM\n", 238 __func__); 239 goto bad; 240 } 241 AH_PRIVATE(ah)->ah_currentRD = eeval; 242 /* XXX record serial number */ 243 244 /* XXX other capabilities */ 245 /* 246 * Got everything we need now to setup the capabilities. 247 */ 248 if (!ar5212FillCapabilityInfo(ah)) { 249 HALDEBUG(ah, HAL_DEBUG_ANY, 250 "%s: failed ar5212FillCapabilityInfo\n", __func__); 251 ecode = HAL_EEREAD; 252 goto bad; 253 } 254 255 if (!rf->attach(ah, &ecode)) { 256 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 257 __func__, ecode); 258 goto bad; 259 } 260 /* arrange a direct call instead of thunking */ 261 AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust; 262 263 /* Initialize gain ladder thermal calibration structure */ 264 ar5212InitializeGainValues(ah); 265 266 /* BSP specific call for MAC address of this WMAC device */ 267 if (!ar5312GetMacAddr(ah)) { 268 ecode = HAL_EEBADMAC; 269 goto bad; 270 } 271 272 ar5312AniSetup(ah); 273 ar5212InitNfCalHistBuffer(ah); 274 275 /* XXX EAR stuff goes here */ 276 return ah; 277 278 bad: 279 if (ahp) 280 ar5212Detach((struct ath_hal *) ahp); 281 if (status) 282 *status = ecode; 283 return AH_NULL; 284 } 285 286 static HAL_BOOL 287 ar5312GetMacAddr(struct ath_hal *ah) 288 { 289 const struct ar531x_boarddata *board = AR5312_BOARDCONFIG(ah); 290 int wlanNum = AR5312_UNIT(ah); 291 const uint8_t *macAddr; 292 293 switch (wlanNum) { 294 case 0: 295 macAddr = board->wlan0Mac; 296 break; 297 case 1: 298 macAddr = board->wlan1Mac; 299 break; 300 default: 301 #ifdef AH_DEBUG 302 ath_hal_printf(ah, "Invalid WLAN wmac index (%d)\n", 303 wlanNum); 304 #endif 305 return AH_FALSE; 306 } 307 OS_MEMCPY(AH5212(ah)->ah_macaddr, macAddr, 6); 308 return AH_TRUE; 309 } 310 311 static const char* 312 ar5312Probe(uint16_t vendorid, uint16_t devid) 313 { 314 if (vendorid == ATHEROS_VENDOR_ID) { 315 switch (devid) { 316 case AR5212_AR5312_REV2: 317 case AR5212_AR5312_REV7: 318 return "Atheros 5312 WiSoC"; 319 case AR5212_AR2313_REV8: 320 return "Atheros 2313 WiSoC"; 321 case AR5212_AR2315_REV6: 322 case AR5212_AR2315_REV7: 323 return "Atheros 2315 WiSoC"; 324 case AR5212_AR2317_REV1: 325 case AR5212_AR2317_REV2: 326 return "Atheros 2317 WiSoC"; 327 case AR5212_AR2413: 328 return "Atheros 2413"; 329 case AR5212_AR2417: 330 return "Atheros 2417"; 331 } 332 } 333 return AH_NULL; 334 } 335 AH_CHIP(AR5312, ar5312Probe, ar5312Attach); 336