2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2006 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.
21 #ifdef AH_SUPPORT_AR5211
24 #include "ah_internal.h"
27 #include "ar5211/ar5211.h"
28 #include "ar5211/ar5211reg.h"
29 #include "ar5211/ar5211phy.h"
31 #include "ah_eeprom_v3.h"
33 static HAL_BOOL
ar5211GetChannelEdges(struct ath_hal
*ah
,
34 uint16_t flags
, uint16_t *low
, uint16_t *high
);
35 static HAL_BOOL
ar5211GetChipPowerLimits(struct ath_hal
*ah
,
36 HAL_CHANNEL
*chans
, uint32_t nchans
);
38 static const struct ath_hal_private ar5211hal
= {{
39 .ah_magic
= AR5211_MAGIC
,
40 .ah_abi
= HAL_ABI_VERSION
,
41 .ah_countryCode
= CTRY_DEFAULT
,
43 .ah_getRateTable
= ar5211GetRateTable
,
44 .ah_detach
= ar5211Detach
,
47 .ah_reset
= ar5211Reset
,
48 .ah_phyDisable
= ar5211PhyDisable
,
49 .ah_disable
= ar5211Disable
,
50 .ah_setPCUConfig
= ar5211SetPCUConfig
,
51 .ah_perCalibration
= ar5211PerCalibration
,
52 .ah_setTxPowerLimit
= ar5211SetTxPowerLimit
,
53 .ah_getChanNoise
= ath_hal_getChanNoise
,
55 /* Transmit functions */
56 .ah_updateTxTrigLevel
= ar5211UpdateTxTrigLevel
,
57 .ah_setupTxQueue
= ar5211SetupTxQueue
,
58 .ah_setTxQueueProps
= ar5211SetTxQueueProps
,
59 .ah_getTxQueueProps
= ar5211GetTxQueueProps
,
60 .ah_releaseTxQueue
= ar5211ReleaseTxQueue
,
61 .ah_resetTxQueue
= ar5211ResetTxQueue
,
62 .ah_getTxDP
= ar5211GetTxDP
,
63 .ah_setTxDP
= ar5211SetTxDP
,
64 .ah_numTxPending
= ar5211NumTxPending
,
65 .ah_startTxDma
= ar5211StartTxDma
,
66 .ah_stopTxDma
= ar5211StopTxDma
,
67 .ah_setupTxDesc
= ar5211SetupTxDesc
,
68 .ah_setupXTxDesc
= ar5211SetupXTxDesc
,
69 .ah_fillTxDesc
= ar5211FillTxDesc
,
70 .ah_procTxDesc
= ar5211ProcTxDesc
,
71 .ah_getTxIntrQueue
= ar5211GetTxIntrQueue
,
72 .ah_reqTxIntrDesc
= ar5211IntrReqTxDesc
,
75 .ah_getRxDP
= ar5211GetRxDP
,
76 .ah_setRxDP
= ar5211SetRxDP
,
77 .ah_enableReceive
= ar5211EnableReceive
,
78 .ah_stopDmaReceive
= ar5211StopDmaReceive
,
79 .ah_startPcuReceive
= ar5211StartPcuReceive
,
80 .ah_stopPcuReceive
= ar5211StopPcuReceive
,
81 .ah_setMulticastFilter
= ar5211SetMulticastFilter
,
82 .ah_setMulticastFilterIndex
= ar5211SetMulticastFilterIndex
,
83 .ah_clrMulticastFilterIndex
= ar5211ClrMulticastFilterIndex
,
84 .ah_getRxFilter
= ar5211GetRxFilter
,
85 .ah_setRxFilter
= ar5211SetRxFilter
,
86 .ah_setupRxDesc
= ar5211SetupRxDesc
,
87 .ah_procRxDesc
= ar5211ProcRxDesc
,
88 .ah_rxMonitor
= ar5211AniPoll
,
89 .ah_procMibEvent
= ar5211MibEvent
,
92 .ah_getCapability
= ar5211GetCapability
,
93 .ah_setCapability
= ar5211SetCapability
,
94 .ah_getDiagState
= ar5211GetDiagState
,
95 .ah_getMacAddress
= ar5211GetMacAddress
,
96 .ah_setMacAddress
= ar5211SetMacAddress
,
97 .ah_getBssIdMask
= ar5211GetBssIdMask
,
98 .ah_setBssIdMask
= ar5211SetBssIdMask
,
99 .ah_setLedState
= ar5211SetLedState
,
100 .ah_writeAssocid
= ar5211WriteAssocid
,
101 .ah_gpioCfgInput
= ar5211GpioCfgInput
,
102 .ah_gpioCfgOutput
= ar5211GpioCfgOutput
,
103 .ah_gpioGet
= ar5211GpioGet
,
104 .ah_gpioSet
= ar5211GpioSet
,
105 .ah_gpioSetIntr
= ar5211GpioSetIntr
,
106 .ah_getTsf32
= ar5211GetTsf32
,
107 .ah_getTsf64
= ar5211GetTsf64
,
108 .ah_resetTsf
= ar5211ResetTsf
,
109 .ah_detectCardPresent
= ar5211DetectCardPresent
,
110 .ah_updateMibCounters
= ar5211UpdateMibCounters
,
111 .ah_getRfGain
= ar5211GetRfgain
,
112 .ah_getDefAntenna
= ar5211GetDefAntenna
,
113 .ah_setDefAntenna
= ar5211SetDefAntenna
,
114 .ah_getAntennaSwitch
= ar5211GetAntennaSwitch
,
115 .ah_setAntennaSwitch
= ar5211SetAntennaSwitch
,
116 .ah_setSifsTime
= ar5211SetSifsTime
,
117 .ah_getSifsTime
= ar5211GetSifsTime
,
118 .ah_setSlotTime
= ar5211SetSlotTime
,
119 .ah_getSlotTime
= ar5211GetSlotTime
,
120 .ah_setAckTimeout
= ar5211SetAckTimeout
,
121 .ah_getAckTimeout
= ar5211GetAckTimeout
,
122 .ah_setAckCTSRate
= ar5211SetAckCTSRate
,
123 .ah_getAckCTSRate
= ar5211GetAckCTSRate
,
124 .ah_setCTSTimeout
= ar5211SetCTSTimeout
,
125 .ah_getCTSTimeout
= ar5211GetCTSTimeout
,
126 .ah_setDecompMask
= ar5211SetDecompMask
,
127 .ah_setCoverageClass
= ar5211SetCoverageClass
,
129 /* Key Cache Functions */
130 .ah_getKeyCacheSize
= ar5211GetKeyCacheSize
,
131 .ah_resetKeyCacheEntry
= ar5211ResetKeyCacheEntry
,
132 .ah_isKeyCacheEntryValid
= ar5211IsKeyCacheEntryValid
,
133 .ah_setKeyCacheEntry
= ar5211SetKeyCacheEntry
,
134 .ah_setKeyCacheEntryMac
= ar5211SetKeyCacheEntryMac
,
136 /* Power Management Functions */
137 .ah_setPowerMode
= ar5211SetPowerMode
,
138 .ah_getPowerMode
= ar5211GetPowerMode
,
140 /* Beacon Functions */
141 .ah_setBeaconTimers
= ar5211SetBeaconTimers
,
142 .ah_beaconInit
= ar5211BeaconInit
,
143 .ah_setStationBeaconTimers
= ar5211SetStaBeaconTimers
,
144 .ah_resetStationBeaconTimers
= ar5211ResetStaBeaconTimers
,
146 /* Interrupt Functions */
147 .ah_isInterruptPending
= ar5211IsInterruptPending
,
148 .ah_getPendingInterrupts
= ar5211GetPendingInterrupts
,
149 .ah_getInterrupts
= ar5211GetInterrupts
,
150 .ah_setInterrupts
= ar5211SetInterrupts
},
152 .ah_getChannelEdges
= ar5211GetChannelEdges
,
153 .ah_getWirelessModes
= ar5211GetWirelessModes
,
154 .ah_eepromRead
= ar5211EepromRead
,
155 #ifdef AH_SUPPORT_WRITE_EEPROM
156 .ah_eepromWrite
= ar5211EepromWrite
,
158 .ah_gpioCfgInput
= ar5211GpioCfgInput
,
159 .ah_gpioCfgOutput
= ar5211GpioCfgOutput
,
160 .ah_gpioGet
= ar5211GpioGet
,
161 .ah_gpioSet
= ar5211GpioSet
,
162 .ah_gpioSetIntr
= ar5211GpioSetIntr
,
163 .ah_getChipPowerLimits
= ar5211GetChipPowerLimits
,
166 static HAL_BOOL
ar5211ChipTest(struct ath_hal
*);
167 static HAL_BOOL
ar5211FillCapabilityInfo(struct ath_hal
*ah
);
170 * Return the revsion id for the radio chip. This
171 * fetched via the PHY.
174 ar5211GetRadioRev(struct ath_hal
*ah
)
179 OS_REG_WRITE(ah
, (AR_PHY_BASE
+ (0x34 << 2)), 0x00001c16);
180 for (i
= 0; i
< 8; i
++)
181 OS_REG_WRITE(ah
, (AR_PHY_BASE
+ (0x20 << 2)), 0x00010000);
182 val
= (OS_REG_READ(ah
, AR_PHY_BASE
+ (256 << 2)) >> 24) & 0xff;
183 val
= ((val
& 0xf0) >> 4) | ((val
& 0x0f) << 4);
184 return ath_hal_reverseBits(val
, 8);
188 * Attach for an AR5211 part.
191 ar5211Attach(uint16_t devid
, HAL_SOFTC sc
,
192 HAL_BUS_TAG st
, HAL_BUS_HANDLE sh
, HAL_STATUS
*status
)
194 #define N(a) (sizeof(a)/sizeof(a[0]))
195 struct ath_hal_5211
*ahp
;
201 HALDEBUG(AH_NULL
, HAL_DEBUG_ATTACH
, "%s: sc %p st %p sh %p\n",
202 __func__
, sc
, (void*) st
, (void*) sh
);
204 /* NB: memory is returned zero'd */
205 ahp
= ath_hal_malloc(sizeof (struct ath_hal_5211
));
206 if (ahp
== AH_NULL
) {
207 HALDEBUG(AH_NULL
, HAL_DEBUG_ANY
,
208 "%s: cannot allocate memory for state block\n", __func__
);
212 ah
= &ahp
->ah_priv
.h
;
213 /* set initial values */
214 OS_MEMCPY(&ahp
->ah_priv
, &ar5211hal
, sizeof(struct ath_hal_private
));
219 ah
->ah_devid
= devid
; /* NB: for AH_DEBUG_ALQ */
220 AH_PRIVATE(ah
)->ah_devid
= devid
;
221 AH_PRIVATE(ah
)->ah_subvendorid
= 0; /* XXX */
223 AH_PRIVATE(ah
)->ah_powerLimit
= MAX_RATE_POWER
;
224 AH_PRIVATE(ah
)->ah_tpScale
= HAL_TP_SCALE_MAX
; /* no scaling */
226 ahp
->ah_diversityControl
= HAL_ANT_VARIABLE
;
227 ahp
->ah_staId1Defaults
= 0;
228 ahp
->ah_rssiThr
= INIT_RSSI_THR
;
229 ahp
->ah_sifstime
= (u_int
) -1;
230 ahp
->ah_slottime
= (u_int
) -1;
231 ahp
->ah_acktimeout
= (u_int
) -1;
232 ahp
->ah_ctstimeout
= (u_int
) -1;
234 if (!ar5211ChipReset(ah
, AH_FALSE
)) { /* reset chip */
235 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip reset failed\n", __func__
);
239 if (AH_PRIVATE(ah
)->ah_devid
== AR5211_FPGA11B
) {
240 /* set it back to OFDM mode to be able to read analog rev id */
241 OS_REG_WRITE(ah
, AR5211_PHY_MODE
, AR5211_PHY_MODE_OFDM
);
242 OS_REG_WRITE(ah
, AR_PHY_PLL_CTL
, AR_PHY_PLL_CTL_44
);
246 /* Read Revisions from Chips */
247 val
= OS_REG_READ(ah
, AR_SREV
) & AR_SREV_ID_M
;
248 AH_PRIVATE(ah
)->ah_macVersion
= val
>> AR_SREV_ID_S
;
249 AH_PRIVATE(ah
)->ah_macRev
= val
& AR_SREV_REVISION_M
;
251 if (AH_PRIVATE(ah
)->ah_macVersion
< AR_SREV_VERSION_MAUI_2
||
252 AH_PRIVATE(ah
)->ah_macVersion
> AR_SREV_VERSION_OAHU
) {
253 HALDEBUG(ah
, HAL_DEBUG_ANY
,
254 "%s: Mac Chip Rev 0x%x is not supported by this driver\n",
255 __func__
, AH_PRIVATE(ah
)->ah_macVersion
);
256 ecode
= HAL_ENOTSUPP
;
260 AH_PRIVATE(ah
)->ah_phyRev
= OS_REG_READ(ah
, AR_PHY_CHIP_ID
);
262 if (!ar5211ChipTest(ah
)) {
263 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: hardware self-test failed\n",
265 ecode
= HAL_ESELFTEST
;
269 /* Set correct Baseband to analog shift setting to access analog chips. */
270 if (AH_PRIVATE(ah
)->ah_macVersion
>= AR_SREV_VERSION_OAHU
) {
271 OS_REG_WRITE(ah
, AR_PHY_BASE
, 0x00000007);
273 OS_REG_WRITE(ah
, AR_PHY_BASE
, 0x00000047);
277 /* Read Radio Chip Rev Extract */
278 AH_PRIVATE(ah
)->ah_analog5GhzRev
= ar5211GetRadioRev(ah
);
279 if ((AH_PRIVATE(ah
)->ah_analog5GhzRev
& 0xf0) != RAD5_SREV_MAJOR
) {
280 HALDEBUG(ah
, HAL_DEBUG_ANY
,
281 "%s: 5G Radio Chip Rev 0x%02X is not supported by this "
282 "driver\n", __func__
, AH_PRIVATE(ah
)->ah_analog5GhzRev
);
283 ecode
= HAL_ENOTSUPP
;
287 val
= (OS_REG_READ(ah
, AR_PCICFG
) & AR_PCICFG_EEPROM_SIZE_M
) >>
288 AR_PCICFG_EEPROM_SIZE_S
;
289 if (val
!= AR_PCICFG_EEPROM_SIZE_16K
) {
290 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: unsupported EEPROM size "
291 "%u (0x%x) found\n", __func__
, val
, val
);
295 ecode
= ath_hal_legacyEepromAttach(ah
);
296 if (ecode
!= HAL_OK
) {
300 /* If Bmode and AR5211, verify 2.4 analog exists */
301 if (AH_PRIVATE(ah
)->ah_macVersion
>= AR_SREV_VERSION_OAHU
&&
302 ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
)) {
303 /* Set correct Baseband to analog shift setting to access analog chips. */
304 OS_REG_WRITE(ah
, AR_PHY_BASE
, 0x00004007);
306 AH_PRIVATE(ah
)->ah_analog2GhzRev
= ar5211GetRadioRev(ah
);
308 /* Set baseband for 5GHz chip */
309 OS_REG_WRITE(ah
, AR_PHY_BASE
, 0x00000007);
311 if ((AH_PRIVATE(ah
)->ah_analog2GhzRev
& 0xF0) != RAD2_SREV_MAJOR
) {
312 HALDEBUG(ah
, HAL_DEBUG_ANY
,
313 "%s: 2G Radio Chip Rev 0x%x is not supported by "
314 "this driver\n", __func__
,
315 AH_PRIVATE(ah
)->ah_analog2GhzRev
);
316 ecode
= HAL_ENOTSUPP
;
320 ath_hal_eepromSet(ah
, AR_EEP_BMODE
, AH_FALSE
);
323 ecode
= ath_hal_eepromGet(ah
, AR_EEP_REGDMN_0
, &eeval
);
324 if (ecode
!= HAL_OK
) {
325 HALDEBUG(ah
, HAL_DEBUG_ANY
,
326 "%s: cannot read regulatory domain from EEPROM\n",
330 AH_PRIVATE(ah
)->ah_currentRD
= eeval
;
331 AH_PRIVATE(ah
)->ah_getNfAdjust
= ar5211GetNfAdjust
;
334 * Got everything we need now to setup the capabilities.
336 (void) ar5211FillCapabilityInfo(ah
);
338 /* Initialize gain ladder thermal calibration structure */
339 ar5211InitializeGainValues(ah
);
341 ecode
= ath_hal_eepromGet(ah
, AR_EEP_MACADDR
, ahp
->ah_macaddr
);
342 if (ecode
!= HAL_OK
) {
343 HALDEBUG(ah
, HAL_DEBUG_ANY
,
344 "%s: error getting mac address from EEPROM\n", __func__
);
348 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s: return\n", __func__
);
353 ar5211Detach((struct ath_hal
*) ahp
);
361 ar5211Detach(struct ath_hal
*ah
)
363 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s:\n", __func__
);
365 HALASSERT(ah
!= AH_NULL
);
366 HALASSERT(ah
->ah_magic
== AR5211_MAGIC
);
368 ath_hal_eepromDetach(ah
);
373 ar5211ChipTest(struct ath_hal
*ah
)
375 uint32_t regAddr
[2] = { AR_STA_ID0
, AR_PHY_BASE
+(8 << 2) };
377 uint32_t patternData
[4] =
378 { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };
381 /* Test PHY & MAC registers */
382 for (i
= 0; i
< 2; i
++) {
383 uint32_t addr
= regAddr
[i
];
384 uint32_t wrData
, rdData
;
386 regHold
[i
] = OS_REG_READ(ah
, addr
);
387 for (j
= 0; j
< 0x100; j
++) {
388 wrData
= (j
<< 16) | j
;
389 OS_REG_WRITE(ah
, addr
, wrData
);
390 rdData
= OS_REG_READ(ah
, addr
);
391 if (rdData
!= wrData
) {
392 HALDEBUG(ah
, HAL_DEBUG_ANY
,
393 "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
394 __func__
, addr
, wrData
, rdData
);
398 for (j
= 0; j
< 4; j
++) {
399 wrData
= patternData
[j
];
400 OS_REG_WRITE(ah
, addr
, wrData
);
401 rdData
= OS_REG_READ(ah
, addr
);
402 if (wrData
!= rdData
) {
403 HALDEBUG(ah
, HAL_DEBUG_ANY
,
404 "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
405 __func__
, addr
, wrData
, rdData
);
409 OS_REG_WRITE(ah
, regAddr
[i
], regHold
[i
]);
416 * Store the channel edges for the requested operational mode
419 ar5211GetChannelEdges(struct ath_hal
*ah
,
420 uint16_t flags
, uint16_t *low
, uint16_t *high
)
422 if (flags
& CHANNEL_5GHZ
) {
427 if (flags
& CHANNEL_2GHZ
&& ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
)) {
436 ar5211GetChipPowerLimits(struct ath_hal
*ah
, HAL_CHANNEL
*chans
, uint32_t nchans
)
441 /* XXX fill in, this is just a placeholder */
442 for (i
= 0; i
< nchans
; i
++) {
444 HALDEBUG(ah
, HAL_DEBUG_ATTACH
,
445 "%s: no min/max power for %u/0x%x\n",
446 __func__
, chan
->channel
, chan
->channelFlags
);
447 chan
->maxTxPower
= MAX_RATE_POWER
;
448 chan
->minTxPower
= 0;
454 * Fill all software cached or static hardware state information.
457 ar5211FillCapabilityInfo(struct ath_hal
*ah
)
459 struct ath_hal_private
*ahpriv
= AH_PRIVATE(ah
);
460 HAL_CAPABILITIES
*pCap
= &ahpriv
->ah_caps
;
462 if (AH_PRIVATE(ah
)->ah_currentRD
== 1)
465 /* Construct wireless mode from EEPROM */
466 pCap
->halWirelessModes
= 0;
467 if (ath_hal_eepromGetFlag(ah
, AR_EEP_AMODE
)) {
468 pCap
->halWirelessModes
|= HAL_MODE_11A
;
469 if (!ath_hal_eepromGetFlag(ah
, AR_EEP_TURBO5DISABLE
))
470 pCap
->halWirelessModes
|= HAL_MODE_TURBO
;
472 if (ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
))
473 pCap
->halWirelessModes
|= HAL_MODE_11B
;
475 pCap
->halLow2GhzChan
= 2312;
476 pCap
->halHigh2GhzChan
= 2732;
477 pCap
->halLow5GhzChan
= 4920;
478 pCap
->halHigh5GhzChan
= 6100;
480 pCap
->halChanSpreadSupport
= AH_TRUE
;
481 pCap
->halSleepAfterBeaconBroken
= AH_TRUE
;
482 pCap
->halPSPollBroken
= AH_TRUE
;
483 pCap
->halVEOLSupport
= AH_TRUE
;
485 pCap
->halTotalQueues
= HAL_NUM_TX_QUEUES
;
486 pCap
->halKeyCacheSize
= 128;
489 pCap
->halChanHalfRate
= AH_FALSE
;
490 pCap
->halChanQuarterRate
= AH_FALSE
;
492 if (ath_hal_eepromGetFlag(ah
, AR_EEP_RFKILL
) &&
493 ath_hal_eepromGet(ah
, AR_EEP_RFSILENT
, &ahpriv
->ah_rfsilent
) == HAL_OK
) {
494 /* NB: enabled by default */
495 ahpriv
->ah_rfkillEnabled
= AH_TRUE
;
496 pCap
->halRfSilentSupport
= AH_TRUE
;
499 pCap
->halTstampPrecision
= 13;
501 /* XXX might be ok w/ some chip revs */
502 ahpriv
->ah_rxornIsFatal
= AH_TRUE
;
505 #endif /* AH_SUPPORT_AR5211 */