2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
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.
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.
17 * $Id: ar5416_attach.c,v 1.1.1.1 2008/12/11 04:46:47 alc Exp $
22 #include "ah_internal.h"
25 #include "ar5416/ar5416.h"
26 #include "ar5416/ar5416reg.h"
27 #include "ar5416/ar5416phy.h"
29 #include "ar5416/ar5416.ini"
32 ar5416AniSetup(struct ath_hal
*ah
)
34 static const struct ar5212AniParams aniparams
= {
35 .maxNoiseImmunityLevel
= 4, /* levels 0..4 */
36 .totalSizeDesired
= { -55, -55, -55, -55, -62 },
37 .coarseHigh
= { -14, -14, -14, -14, -12 },
38 .coarseLow
= { -64, -64, -64, -64, -70 },
39 .firpwr
= { -78, -78, -78, -78, -80 },
40 .maxSpurImmunityLevel
= 2,
41 .cycPwrThr1
= { 2, 4, 6 },
42 .maxFirstepLevel
= 2, /* levels 0..2 */
43 .firstep
= { 0, 4, 8 },
52 /* NB: ANI is not enabled yet */
53 ar5212AniAttach(ah
, &aniparams
, &aniparams
, AH_FALSE
);
57 * Attach for an AR5416 part.
60 ar5416InitState(struct ath_hal_5416
*ahp5416
, uint16_t devid
, HAL_SOFTC sc
,
61 HAL_BUS_TAG st
, HAL_BUS_HANDLE sh
, HAL_STATUS
*status
)
63 struct ath_hal_5212
*ahp
;
66 ahp
= &ahp5416
->ah_5212
;
67 ar5212InitState(ahp
, devid
, sc
, st
, sh
, status
);
70 /* override 5212 methods for our needs */
71 ah
->ah_magic
= AR5416_MAGIC
;
72 ah
->ah_getRateTable
= ar5416GetRateTable
;
73 ah
->ah_detach
= ar5416Detach
;
76 ah
->ah_reset
= ar5416Reset
;
77 ah
->ah_phyDisable
= ar5416PhyDisable
;
78 ah
->ah_disable
= ar5416Disable
;
79 ah
->ah_perCalibration
= ar5416PerCalibration
;
80 ah
->ah_perCalibrationN
= ar5416PerCalibrationN
,
81 ah
->ah_resetCalValid
= ar5416ResetCalValid
,
82 ah
->ah_setTxPowerLimit
= ar5416SetTxPowerLimit
;
84 /* Transmit functions */
85 ah
->ah_stopTxDma
= ar5416StopTxDma
;
86 ah
->ah_setupTxDesc
= ar5416SetupTxDesc
;
87 ah
->ah_setupXTxDesc
= ar5416SetupXTxDesc
;
88 ah
->ah_fillTxDesc
= ar5416FillTxDesc
;
89 ah
->ah_procTxDesc
= ar5416ProcTxDesc
;
91 /* Receive Functions */
92 ah
->ah_startPcuReceive
= ar5416StartPcuReceive
;
93 ah
->ah_stopPcuReceive
= ar5416StopPcuReceive
;
94 ah
->ah_setupRxDesc
= ar5416SetupRxDesc
;
95 ah
->ah_procRxDesc
= ar5416ProcRxDesc
;
96 ah
->ah_rxMonitor
= ar5416AniPoll
,
97 ah
->ah_procMibEvent
= ar5416ProcessMibIntr
,
100 ah
->ah_getDiagState
= ar5416GetDiagState
;
101 ah
->ah_setLedState
= ar5416SetLedState
;
102 ah
->ah_gpioCfgOutput
= ar5416GpioCfgOutput
;
103 ah
->ah_gpioCfgInput
= ar5416GpioCfgInput
;
104 ah
->ah_gpioGet
= ar5416GpioGet
;
105 ah
->ah_gpioSet
= ar5416GpioSet
;
106 ah
->ah_gpioSetIntr
= ar5416GpioSetIntr
;
107 ah
->ah_resetTsf
= ar5416ResetTsf
;
108 ah
->ah_getRfGain
= ar5416GetRfgain
;
109 ah
->ah_setAntennaSwitch
= ar5416SetAntennaSwitch
;
110 ah
->ah_setDecompMask
= ar5416SetDecompMask
;
111 ah
->ah_setCoverageClass
= ar5416SetCoverageClass
;
113 ah
->ah_resetKeyCacheEntry
= ar5416ResetKeyCacheEntry
;
114 ah
->ah_setKeyCacheEntry
= ar5416SetKeyCacheEntry
;
116 /* Power Management Functions */
117 ah
->ah_setPowerMode
= ar5416SetPowerMode
;
119 /* Beacon Management Functions */
120 ah
->ah_setBeaconTimers
= ar5416SetBeaconTimers
;
121 ah
->ah_beaconInit
= ar5416BeaconInit
;
122 ah
->ah_setStationBeaconTimers
= ar5416SetStaBeaconTimers
;
123 ah
->ah_resetStationBeaconTimers
= ar5416ResetStaBeaconTimers
;
125 /* XXX 802.11n Functions */
127 ah
->ah_chainTxDesc
= ar5416ChainTxDesc
;
128 ah
->ah_setupFirstTxDesc
= ar5416SetupFirstTxDesc
;
129 ah
->ah_setupLastTxDesc
= ar5416SetupLastTxDesc
;
130 ah
->ah_set11nRateScenario
= ar5416Set11nRateScenario
;
131 ah
->ah_set11nAggrMiddle
= ar5416Set11nAggrMiddle
;
132 ah
->ah_clr11nAggr
= ar5416Clr11nAggr
;
133 ah
->ah_set11nBurstDuration
= ar5416Set11nBurstDuration
;
134 ah
->ah_get11nExtBusy
= ar5416Get11nExtBusy
;
135 ah
->ah_set11nMac2040
= ar5416Set11nMac2040
;
136 ah
->ah_get11nRxClear
= ar5416Get11nRxClear
;
137 ah
->ah_set11nRxClear
= ar5416Set11nRxClear
;
140 /* Interrupt functions */
141 ah
->ah_isInterruptPending
= ar5416IsInterruptPending
;
142 ah
->ah_getPendingInterrupts
= ar5416GetPendingInterrupts
;
143 ah
->ah_setInterrupts
= ar5416SetInterrupts
;
145 ahp
->ah_priv
.ah_getWirelessModes
= ar5416GetWirelessModes
;
146 ahp
->ah_priv
.ah_eepromRead
= ar5416EepromRead
;
147 #ifdef AH_SUPPORT_WRITE_EEPROM
148 ahp
->ah_priv
.ah_eepromWrite
= ar5416EepromWrite
;
150 ahp
->ah_priv
.ah_gpioCfgOutput
= ar5416GpioCfgOutput
;
151 ahp
->ah_priv
.ah_gpioCfgInput
= ar5416GpioCfgInput
;
152 ahp
->ah_priv
.ah_gpioGet
= ar5416GpioGet
;
153 ahp
->ah_priv
.ah_gpioSet
= ar5416GpioSet
;
154 ahp
->ah_priv
.ah_gpioSetIntr
= ar5416GpioSetIntr
;
155 ahp
->ah_priv
.ah_getChipPowerLimits
= ar5416GetChipPowerLimits
;
158 * Start by setting all Owl devices to 2x2
160 AH5416(ah
)->ah_rx_chainmask
= AR5416_DEFAULT_RXCHAINMASK
;
161 AH5416(ah
)->ah_tx_chainmask
= AR5416_DEFAULT_TXCHAINMASK
;
165 * Attach for an AR5416 part.
168 ar5416Attach(uint16_t devid
, HAL_SOFTC sc
,
169 HAL_BUS_TAG st
, HAL_BUS_HANDLE sh
, HAL_STATUS
*status
)
171 struct ath_hal_5416
*ahp5416
;
172 struct ath_hal_5212
*ahp
;
178 HALDEBUG(AH_NULL
, HAL_DEBUG_ATTACH
, "%s: sc %p st %p sh %p\n",
179 __func__
, sc
, (void*) st
, (void*) sh
);
181 /* NB: memory is returned zero'd */
182 ahp5416
= ath_hal_malloc(sizeof (struct ath_hal_5416
) +
183 /* extra space for Owl 2.1/2.2 WAR */
186 if (ahp5416
== AH_NULL
) {
187 HALDEBUG(AH_NULL
, HAL_DEBUG_ANY
,
188 "%s: cannot allocate memory for state block\n", __func__
);
189 *status
= HAL_ENOMEM
;
192 ar5416InitState(ahp5416
, devid
, sc
, st
, sh
, status
);
193 ahp
= &ahp5416
->ah_5212
;
194 ah
= &ahp
->ah_priv
.h
;
196 if (!ar5416SetResetReg(ah
, HAL_RESET_POWER_ON
)) {
198 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: couldn't reset chip\n", __func__
);
203 if (!ar5416SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
)) {
204 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: couldn't wakeup chip\n", __func__
);
208 /* Read Revisions from Chips before taking out of reset */
209 val
= OS_REG_READ(ah
, AR_SREV
) & AR_SREV_ID
;
210 AH_PRIVATE(ah
)->ah_macVersion
= val
>> AR_SREV_ID_S
;
211 AH_PRIVATE(ah
)->ah_macRev
= val
& AR_SREV_REVISION
;
213 /* setup common ini data; rf backends handle remainder */
214 HAL_INI_INIT(&ahp
->ah_ini_modes
, ar5416Modes
, 6);
215 HAL_INI_INIT(&ahp
->ah_ini_common
, ar5416Common
, 2);
217 HAL_INI_INIT(&AH5416(ah
)->ah_ini_bb_rfgain
, ar5416BB_RfGain
, 3);
218 HAL_INI_INIT(&AH5416(ah
)->ah_ini_bank0
, ar5416Bank0
, 2);
219 HAL_INI_INIT(&AH5416(ah
)->ah_ini_bank1
, ar5416Bank1
, 2);
220 HAL_INI_INIT(&AH5416(ah
)->ah_ini_bank2
, ar5416Bank2
, 2);
221 HAL_INI_INIT(&AH5416(ah
)->ah_ini_bank3
, ar5416Bank3
, 3);
222 HAL_INI_INIT(&AH5416(ah
)->ah_ini_bank6
, ar5416Bank6
, 3);
223 HAL_INI_INIT(&AH5416(ah
)->ah_ini_bank7
, ar5416Bank7
, 2);
224 HAL_INI_INIT(&AH5416(ah
)->ah_ini_addac
, ar5416Addac
, 2);
226 if (!IS_5416V2_2(ah
)) { /* Owl 2.1/2.0 */
228 uint32_t *data
; /* NB: !const */
231 /* override CLKDRV value */
232 OS_MEMCPY(&AH5416(ah
)[1], ar5416Addac
, sizeof(ar5416Addac
));
233 AH5416(ah
)->ah_ini_addac
.data
= (uint32_t *) &AH5416(ah
)[1];
234 HAL_INI_VAL((struct ini
*)&AH5416(ah
)->ah_ini_addac
, 31, 1) = 0;
237 if (!ar5416ChipReset(ah
, AH_NULL
)) { /* reset chip */
238 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip reset failed\n",
244 AH_PRIVATE(ah
)->ah_phyRev
= OS_REG_READ(ah
, AR_PHY_CHIP_ID
);
246 if (!ar5212ChipTest(ah
)) {
247 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: hardware self-test failed\n",
249 ecode
= HAL_ESELFTEST
;
254 * Set correct Baseband to analog shift
255 * setting to access analog chips.
257 OS_REG_WRITE(ah
, AR_PHY(0), 0x00000007);
259 /* Read Radio Chip Rev Extract */
260 AH_PRIVATE(ah
)->ah_analog5GhzRev
= ar5212GetRadioRev(ah
);
261 switch (AH_PRIVATE(ah
)->ah_analog5GhzRev
& AR_RADIO_SREV_MAJOR
) {
262 case AR_RAD5122_SREV_MAJOR
: /* Fowl: 5G/2x2 */
263 case AR_RAD2122_SREV_MAJOR
: /* Fowl: 2+5G/2x2 */
264 case AR_RAD2133_SREV_MAJOR
: /* Fowl: 2G/3x3 */
265 case AR_RAD5133_SREV_MAJOR
: /* Fowl: 2+5G/3x3 */
268 if (AH_PRIVATE(ah
)->ah_analog5GhzRev
== 0) {
270 * When RF_Silen is used the analog chip is reset.
271 * So when the system boots with radio switch off
272 * the RF chip rev reads back as zero and we need
273 * to use the mac+phy revs to set the radio rev.
275 AH_PRIVATE(ah
)->ah_analog5GhzRev
=
276 AR_RAD5133_SREV_MAJOR
;
279 /* NB: silently accept anything in release code per Atheros */
281 HALDEBUG(ah
, HAL_DEBUG_ANY
,
282 "%s: 5G Radio Chip Rev 0x%02X is not supported by "
283 "this driver\n", __func__
,
284 AH_PRIVATE(ah
)->ah_analog5GhzRev
);
285 ecode
= HAL_ENOTSUPP
;
290 ecode
= ath_hal_v14EepromAttach(ah
);
295 * Got everything we need now to setup the capabilities.
297 if (!ar5416FillCapabilityInfo(ah
)) {
302 ecode
= ath_hal_eepromGet(ah
, AR_EEP_MACADDR
, ahp
->ah_macaddr
);
303 if (ecode
!= HAL_OK
) {
304 HALDEBUG(ah
, HAL_DEBUG_ANY
,
305 "%s: error getting mac address from EEPROM\n", __func__
);
308 /* XXX How about the serial number ? */
309 /* Read Reg Domain */
310 AH_PRIVATE(ah
)->ah_currentRD
=
311 ath_hal_eepromGet(ah
, AR_EEP_REGDMN_0
, AH_NULL
);
314 * ah_miscMode is populated by ar5416FillCapabilityInfo()
315 * starting from griffin. Set here to make sure that
316 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
317 * placed into hardware.
319 if (ahp
->ah_miscMode
!= 0)
320 OS_REG_WRITE(ah
, AR_MISC_MODE
, ahp
->ah_miscMode
);
322 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s: Attaching AR2133 radio\n",
324 rfStatus
= ar2133RfAttach(ah
, &ecode
);
326 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: RF setup failed, status %u\n",
331 ar5416AniSetup(ah
); /* Anti Noise Immunity */
332 ar5416InitNfHistBuff(AH5416(ah
)->ah_cal
.nfCalHist
);
334 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s: return\n", __func__
);
339 ar5416Detach((struct ath_hal
*) ahp
);
346 ar5416Detach(struct ath_hal
*ah
)
348 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s:\n", __func__
);
350 HALASSERT(ah
!= AH_NULL
);
351 HALASSERT(ah
->ah_magic
== AR5416_MAGIC
);
356 ar5416SetPowerMode(ah
, HAL_PM_FULL_SLEEP
, AH_TRUE
);
357 ath_hal_eepromDetach(ah
);
362 * Fill all software cached or static hardware state information.
363 * Return failure if capabilities are to come from EEPROM and
367 ar5416FillCapabilityInfo(struct ath_hal
*ah
)
369 struct ath_hal_private
*ahpriv
= AH_PRIVATE(ah
);
370 HAL_CAPABILITIES
*pCap
= &ahpriv
->ah_caps
;
373 /* Construct wireless mode from EEPROM */
374 pCap
->halWirelessModes
= 0;
375 if (ath_hal_eepromGetFlag(ah
, AR_EEP_AMODE
)) {
376 pCap
->halWirelessModes
|= HAL_MODE_11A
378 | HAL_MODE_11NA_HT40PLUS
379 | HAL_MODE_11NA_HT40MINUS
382 if (ath_hal_eepromGetFlag(ah
, AR_EEP_GMODE
)) {
383 pCap
->halWirelessModes
|= HAL_MODE_11G
385 | HAL_MODE_11NG_HT40PLUS
386 | HAL_MODE_11NG_HT40MINUS
388 pCap
->halWirelessModes
|= HAL_MODE_11A
390 | HAL_MODE_11NA_HT40PLUS
391 | HAL_MODE_11NA_HT40MINUS
395 pCap
->halLow2GhzChan
= 2312;
396 pCap
->halHigh2GhzChan
= 2732;
398 pCap
->halLow5GhzChan
= 4915;
399 pCap
->halHigh5GhzChan
= 6100;
401 pCap
->halCipherCkipSupport
= AH_FALSE
;
402 pCap
->halCipherTkipSupport
= AH_TRUE
;
403 pCap
->halCipherAesCcmSupport
= ath_hal_eepromGetFlag(ah
, AR_EEP_AES
);
405 pCap
->halMicCkipSupport
= AH_FALSE
;
406 pCap
->halMicTkipSupport
= AH_TRUE
;
407 pCap
->halMicAesCcmSupport
= ath_hal_eepromGetFlag(ah
, AR_EEP_AES
);
409 * Starting with Griffin TX+RX mic keys can be combined
410 * in one key cache slot.
412 pCap
->halTkipMicTxRxKeySupport
= AH_TRUE
;
413 pCap
->halChanSpreadSupport
= AH_TRUE
;
414 pCap
->halSleepAfterBeaconBroken
= AH_TRUE
;
416 pCap
->halCompressSupport
= AH_FALSE
;
417 pCap
->halBurstSupport
= AH_TRUE
;
418 pCap
->halFastFramesSupport
= AH_FALSE
; /* XXX? */
419 pCap
->halChapTuningSupport
= AH_TRUE
;
420 pCap
->halTurboPrimeSupport
= AH_TRUE
;
422 pCap
->halTurboGSupport
= pCap
->halWirelessModes
& HAL_MODE_108G
;
424 pCap
->halPSPollBroken
= AH_TRUE
; /* XXX fixed in later revs? */
425 pCap
->halVEOLSupport
= AH_TRUE
;
426 pCap
->halBssIdMaskSupport
= AH_TRUE
;
427 pCap
->halMcastKeySrchSupport
= AH_FALSE
;
428 pCap
->halTsfAddSupport
= AH_TRUE
;
430 if (ath_hal_eepromGet(ah
, AR_EEP_MAXQCU
, &val
) == HAL_OK
)
431 pCap
->halTotalQueues
= val
;
433 pCap
->halTotalQueues
= HAL_NUM_TX_QUEUES
;
435 if (ath_hal_eepromGet(ah
, AR_EEP_KCENTRIES
, &val
) == HAL_OK
)
436 pCap
->halKeyCacheSize
= val
;
438 pCap
->halKeyCacheSize
= AR5416_KEYTABLE_SIZE
;
441 pCap
->halChanHalfRate
= AH_FALSE
; /* XXX ? */
442 pCap
->halChanQuarterRate
= AH_FALSE
; /* XXX ? */
444 pCap
->halTstampPrecision
= 32;
445 pCap
->halHwPhyCounterSupport
= AH_TRUE
;
447 pCap
->halFastCCSupport
= AH_TRUE
;
448 pCap
->halNumGpioPins
= 6;
449 pCap
->halWowSupport
= AH_FALSE
;
450 pCap
->halWowMatchPatternExact
= AH_FALSE
;
451 pCap
->halBtCoexSupport
= AH_FALSE
; /* XXX need support */
452 pCap
->halAutoSleepSupport
= AH_FALSE
;
453 #if 0 /* XXX not yet */
454 pCap
->halNumAntCfg2GHz
= ar5416GetNumAntConfig(ahp
, HAL_FREQ_BAND_2GHZ
);
455 pCap
->halNumAntCfg5GHz
= ar5416GetNumAntConfig(ahp
, HAL_FREQ_BAND_5GHZ
);
457 pCap
->halHTSupport
= AH_TRUE
;
458 pCap
->halTxChainMask
= ath_hal_eepromGet(ah
, AR_EEP_TXMASK
, AH_NULL
);
459 /* XXX CB71 uses GPIO 0 to indicate 3 rx chains */
460 pCap
->halRxChainMask
= ath_hal_eepromGet(ah
, AR_EEP_RXMASK
, AH_NULL
);
461 pCap
->halRtsAggrLimit
= 8*1024; /* Owl 2.0 limit */
462 pCap
->halMbssidAggrSupport
= AH_TRUE
;
463 pCap
->halForcePpmSupport
= AH_TRUE
;
464 pCap
->halEnhancedPmSupport
= AH_TRUE
;
466 if (ath_hal_eepromGetFlag(ah
, AR_EEP_RFKILL
) &&
467 ath_hal_eepromGet(ah
, AR_EEP_RFSILENT
, &ahpriv
->ah_rfsilent
) == HAL_OK
) {
468 /* NB: enabled by default */
469 ahpriv
->ah_rfkillEnabled
= AH_TRUE
;
470 pCap
->halRfSilentSupport
= AH_TRUE
;
473 ahpriv
->ah_rxornIsFatal
= AH_FALSE
;
479 ar5416Probe(uint16_t vendorid
, uint16_t devid
)
481 if (vendorid
== ATHEROS_VENDOR_ID
&&
482 (devid
== AR5416_DEVID_PCI
|| devid
== AR5416_DEVID_PCIE
))
483 return "Atheros 5416";
486 AH_CHIP(AR5416
, ar5416Probe
, ar5416Attach
);