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: ar5212_attach.c,v 1.1.1.1 2008/12/11 04:46:40 alc Exp $
22 #include "ah_internal.h"
25 #include "ar5212/ar5212.h"
26 #include "ar5212/ar5212reg.h"
27 #include "ar5212/ar5212phy.h"
29 #define AH_5212_COMMON
30 #include "ar5212/ar5212.ini"
32 static const struct ath_hal_private ar5212hal
= {{
33 .ah_magic
= AR5212_MAGIC
,
34 .ah_abi
= HAL_ABI_VERSION
,
35 .ah_countryCode
= CTRY_DEFAULT
,
37 .ah_getRateTable
= ar5212GetRateTable
,
38 .ah_detach
= ar5212Detach
,
41 .ah_reset
= ar5212Reset
,
42 .ah_phyDisable
= ar5212PhyDisable
,
43 .ah_disable
= ar5212Disable
,
44 .ah_setPCUConfig
= ar5212SetPCUConfig
,
45 .ah_perCalibration
= ar5212PerCalibration
,
46 .ah_perCalibrationN
= ar5212PerCalibrationN
,
47 .ah_resetCalValid
= ar5212ResetCalValid
,
48 .ah_setTxPowerLimit
= ar5212SetTxPowerLimit
,
49 .ah_getChanNoise
= ath_hal_getChanNoise
,
51 /* Transmit functions */
52 .ah_updateTxTrigLevel
= ar5212UpdateTxTrigLevel
,
53 .ah_setupTxQueue
= ar5212SetupTxQueue
,
54 .ah_setTxQueueProps
= ar5212SetTxQueueProps
,
55 .ah_getTxQueueProps
= ar5212GetTxQueueProps
,
56 .ah_releaseTxQueue
= ar5212ReleaseTxQueue
,
57 .ah_resetTxQueue
= ar5212ResetTxQueue
,
58 .ah_getTxDP
= ar5212GetTxDP
,
59 .ah_setTxDP
= ar5212SetTxDP
,
60 .ah_numTxPending
= ar5212NumTxPending
,
61 .ah_startTxDma
= ar5212StartTxDma
,
62 .ah_stopTxDma
= ar5212StopTxDma
,
63 .ah_setupTxDesc
= ar5212SetupTxDesc
,
64 .ah_setupXTxDesc
= ar5212SetupXTxDesc
,
65 .ah_fillTxDesc
= ar5212FillTxDesc
,
66 .ah_procTxDesc
= ar5212ProcTxDesc
,
67 .ah_getTxIntrQueue
= ar5212GetTxIntrQueue
,
68 .ah_reqTxIntrDesc
= ar5212IntrReqTxDesc
,
71 .ah_getRxDP
= ar5212GetRxDP
,
72 .ah_setRxDP
= ar5212SetRxDP
,
73 .ah_enableReceive
= ar5212EnableReceive
,
74 .ah_stopDmaReceive
= ar5212StopDmaReceive
,
75 .ah_startPcuReceive
= ar5212StartPcuReceive
,
76 .ah_stopPcuReceive
= ar5212StopPcuReceive
,
77 .ah_setMulticastFilter
= ar5212SetMulticastFilter
,
78 .ah_setMulticastFilterIndex
= ar5212SetMulticastFilterIndex
,
79 .ah_clrMulticastFilterIndex
= ar5212ClrMulticastFilterIndex
,
80 .ah_getRxFilter
= ar5212GetRxFilter
,
81 .ah_setRxFilter
= ar5212SetRxFilter
,
82 .ah_setupRxDesc
= ar5212SetupRxDesc
,
83 .ah_procRxDesc
= ar5212ProcRxDesc
,
84 .ah_rxMonitor
= ar5212AniPoll
,
85 .ah_procMibEvent
= ar5212ProcessMibIntr
,
88 .ah_getCapability
= ar5212GetCapability
,
89 .ah_setCapability
= ar5212SetCapability
,
90 .ah_getDiagState
= ar5212GetDiagState
,
91 .ah_getMacAddress
= ar5212GetMacAddress
,
92 .ah_setMacAddress
= ar5212SetMacAddress
,
93 .ah_getBssIdMask
= ar5212GetBssIdMask
,
94 .ah_setBssIdMask
= ar5212SetBssIdMask
,
95 .ah_setRegulatoryDomain
= ar5212SetRegulatoryDomain
,
96 .ah_setLedState
= ar5212SetLedState
,
97 .ah_writeAssocid
= ar5212WriteAssocid
,
98 .ah_gpioCfgInput
= ar5212GpioCfgInput
,
99 .ah_gpioCfgOutput
= ar5212GpioCfgOutput
,
100 .ah_gpioGet
= ar5212GpioGet
,
101 .ah_gpioSet
= ar5212GpioSet
,
102 .ah_gpioSetIntr
= ar5212GpioSetIntr
,
103 .ah_getTsf32
= ar5212GetTsf32
,
104 .ah_getTsf64
= ar5212GetTsf64
,
105 .ah_resetTsf
= ar5212ResetTsf
,
106 .ah_detectCardPresent
= ar5212DetectCardPresent
,
107 .ah_updateMibCounters
= ar5212UpdateMibCounters
,
108 .ah_getRfGain
= ar5212GetRfgain
,
109 .ah_getDefAntenna
= ar5212GetDefAntenna
,
110 .ah_setDefAntenna
= ar5212SetDefAntenna
,
111 .ah_getAntennaSwitch
= ar5212GetAntennaSwitch
,
112 .ah_setAntennaSwitch
= ar5212SetAntennaSwitch
,
113 .ah_setSifsTime
= ar5212SetSifsTime
,
114 .ah_getSifsTime
= ar5212GetSifsTime
,
115 .ah_setSlotTime
= ar5212SetSlotTime
,
116 .ah_getSlotTime
= ar5212GetSlotTime
,
117 .ah_setAckTimeout
= ar5212SetAckTimeout
,
118 .ah_getAckTimeout
= ar5212GetAckTimeout
,
119 .ah_setAckCTSRate
= ar5212SetAckCTSRate
,
120 .ah_getAckCTSRate
= ar5212GetAckCTSRate
,
121 .ah_setCTSTimeout
= ar5212SetCTSTimeout
,
122 .ah_getCTSTimeout
= ar5212GetCTSTimeout
,
123 .ah_setDecompMask
= ar5212SetDecompMask
,
124 .ah_setCoverageClass
= ar5212SetCoverageClass
,
126 /* Key Cache Functions */
127 .ah_getKeyCacheSize
= ar5212GetKeyCacheSize
,
128 .ah_resetKeyCacheEntry
= ar5212ResetKeyCacheEntry
,
129 .ah_isKeyCacheEntryValid
= ar5212IsKeyCacheEntryValid
,
130 .ah_setKeyCacheEntry
= ar5212SetKeyCacheEntry
,
131 .ah_setKeyCacheEntryMac
= ar5212SetKeyCacheEntryMac
,
133 /* Power Management Functions */
134 .ah_setPowerMode
= ar5212SetPowerMode
,
135 .ah_getPowerMode
= ar5212GetPowerMode
,
137 /* Beacon Functions */
138 .ah_setBeaconTimers
= ar5212SetBeaconTimers
,
139 .ah_beaconInit
= ar5212BeaconInit
,
140 .ah_setStationBeaconTimers
= ar5212SetStaBeaconTimers
,
141 .ah_resetStationBeaconTimers
= ar5212ResetStaBeaconTimers
,
143 /* Interrupt Functions */
144 .ah_isInterruptPending
= ar5212IsInterruptPending
,
145 .ah_getPendingInterrupts
= ar5212GetPendingInterrupts
,
146 .ah_getInterrupts
= ar5212GetInterrupts
,
147 .ah_setInterrupts
= ar5212SetInterrupts
},
149 .ah_getChannelEdges
= ar5212GetChannelEdges
,
150 .ah_getWirelessModes
= ar5212GetWirelessModes
,
151 .ah_eepromRead
= ar5212EepromRead
,
152 #ifdef AH_SUPPORT_WRITE_EEPROM
153 .ah_eepromWrite
= ar5212EepromWrite
,
155 .ah_gpioCfgOutput
= ar5212GpioCfgOutput
,
156 .ah_gpioCfgInput
= ar5212GpioCfgInput
,
157 .ah_gpioGet
= ar5212GpioGet
,
158 .ah_gpioSet
= ar5212GpioSet
,
159 .ah_gpioSetIntr
= ar5212GpioSetIntr
,
160 .ah_getChipPowerLimits
= ar5212GetChipPowerLimits
,
164 * Disable PLL when in L0s as well as receiver clock when in L1.
165 * This power saving option must be enabled through the Serdes.
167 * Programming the Serdes must go through the same 288 bit serial shift
168 * register as the other analog registers. Hence the 9 writes.
170 * XXX Clean up the magic numbers.
173 configurePciePowerSave(struct ath_hal
*ah
)
175 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0x9248fc00);
176 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0x24924924);
178 /* RX shut off when elecidle is asserted */
179 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0x28000039);
180 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0x53160824);
181 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0xe5980579);
183 /* Shut off PLL and CLKREQ active in L1 */
184 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0x001defff);
185 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0x1aaabe40);
186 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0xbe105554);
187 OS_REG_WRITE(ah
, AR_PCIE_SERDES
, 0x000e3007);
189 /* Load the new settings */
190 OS_REG_WRITE(ah
, AR_PCIE_SERDES2
, 0x00000000);
194 ar5212GetRadioRev(struct ath_hal
*ah
)
199 /* Read Radio Chip Rev Extract */
200 OS_REG_WRITE(ah
, AR_PHY(0x34), 0x00001c16);
201 for (i
= 0; i
< 8; i
++)
202 OS_REG_WRITE(ah
, AR_PHY(0x20), 0x00010000);
203 val
= (OS_REG_READ(ah
, AR_PHY(256)) >> 24) & 0xff;
204 val
= ((val
& 0xf0) >> 4) | ((val
& 0x0f) << 4);
205 return ath_hal_reverseBits(val
, 8);
209 ar5212AniSetup(struct ath_hal
*ah
)
211 static const struct ar5212AniParams aniparams
= {
212 .maxNoiseImmunityLevel
= 4, /* levels 0..4 */
213 .totalSizeDesired
= { -55, -55, -55, -55, -62 },
214 .coarseHigh
= { -14, -14, -14, -14, -12 },
215 .coarseLow
= { -64, -64, -64, -64, -70 },
216 .firpwr
= { -78, -78, -78, -78, -80 },
217 .maxSpurImmunityLevel
= 2, /* NB: depends on chip rev */
218 .cycPwrThr1
= { 2, 4, 6, 8, 10, 12, 14, 16 },
219 .maxFirstepLevel
= 2, /* levels 0..2 */
220 .firstep
= { 0, 4, 8 },
229 if (AH_PRIVATE(ah
)->ah_macVersion
< AR_SREV_VERSION_GRIFFIN
) {
230 struct ar5212AniParams tmp
;
231 OS_MEMCPY(&tmp
, &aniparams
, sizeof(struct ar5212AniParams
));
232 tmp
.maxSpurImmunityLevel
= 7; /* Venice and earlier */
233 ar5212AniAttach(ah
, &tmp
, &tmp
, AH_TRUE
);
235 ar5212AniAttach(ah
, &aniparams
, &aniparams
, AH_TRUE
);
239 * Attach for an AR5212 part.
242 ar5212InitState(struct ath_hal_5212
*ahp
, uint16_t devid
, HAL_SOFTC sc
,
243 HAL_BUS_TAG st
, HAL_BUS_HANDLE sh
, HAL_STATUS
*status
)
245 #define N(a) (sizeof(a)/sizeof(a[0]))
246 static const uint8_t defbssidmask
[IEEE80211_ADDR_LEN
] =
247 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
250 ah
= &ahp
->ah_priv
.h
;
251 /* set initial values */
252 OS_MEMCPY(&ahp
->ah_priv
, &ar5212hal
, sizeof(struct ath_hal_private
));
257 ah
->ah_devid
= devid
; /* NB: for alq */
258 AH_PRIVATE(ah
)->ah_devid
= devid
;
259 AH_PRIVATE(ah
)->ah_subvendorid
= 0; /* XXX */
261 AH_PRIVATE(ah
)->ah_powerLimit
= MAX_RATE_POWER
;
262 AH_PRIVATE(ah
)->ah_tpScale
= HAL_TP_SCALE_MAX
; /* no scaling */
264 ahp
->ah_antControl
= HAL_ANT_VARIABLE
;
265 ahp
->ah_diversity
= AH_TRUE
;
266 ahp
->ah_bIQCalibration
= AH_FALSE
;
268 * Enable MIC handling.
270 ahp
->ah_staId1Defaults
= AR_STA_ID1_CRPT_MIC_ENABLE
;
271 ahp
->ah_rssiThr
= INIT_RSSI_THR
;
272 ahp
->ah_tpcEnabled
= AH_FALSE
; /* disabled by default */
273 ahp
->ah_phyPowerOn
= AH_FALSE
;
274 ahp
->ah_macTPC
= SM(MAX_RATE_POWER
, AR_TPC_ACK
)
275 | SM(MAX_RATE_POWER
, AR_TPC_CTS
)
276 | SM(MAX_RATE_POWER
, AR_TPC_CHIRP
);
277 ahp
->ah_beaconInterval
= 100; /* XXX [20..1000] */
278 ahp
->ah_enable32kHzClock
= DONT_USE_32KHZ
;/* XXX */
279 ahp
->ah_slottime
= (u_int
) -1;
280 ahp
->ah_acktimeout
= (u_int
) -1;
281 ahp
->ah_ctstimeout
= (u_int
) -1;
282 ahp
->ah_sifstime
= (u_int
) -1;
283 OS_MEMCPY(&ahp
->ah_bssidmask
, defbssidmask
, IEEE80211_ADDR_LEN
);
288 * Validate MAC version and revision.
291 ar5212IsMacSupported(uint8_t macVersion
, uint8_t macRev
)
293 #define N(a) (sizeof(a)/sizeof(a[0]))
294 static const struct {
296 uint8_t revMin
, revMax
;
298 { AR_SREV_VERSION_VENICE
,
299 AR_SREV_D2PLUS
, AR_SREV_REVISION_MAX
},
300 { AR_SREV_VERSION_GRIFFIN
,
301 AR_SREV_D2PLUS
, AR_SREV_REVISION_MAX
},
303 AR_SREV_REVISION_MIN
, AR_SREV_REVISION_MAX
},
305 AR_SREV_REVISION_MIN
, AR_SREV_REVISION_MAX
},
307 AR_SREV_REVISION_MIN
, AR_SREV_REVISION_MAX
},
309 AR_SREV_REVISION_MIN
, AR_SREV_REVISION_MAX
},
313 for (i
= 0; i
< N(macs
); i
++)
314 if (macs
[i
].version
== macVersion
&&
315 macs
[i
].revMin
<= macRev
&& macRev
<= macs
[i
].revMax
)
322 * Attach for an AR5212 part.
324 static struct ath_hal
*
325 ar5212Attach(uint16_t devid
, HAL_SOFTC sc
,
326 HAL_BUS_TAG st
, HAL_BUS_HANDLE sh
, HAL_STATUS
*status
)
328 #define AH_EEPROM_PROTECT(ah) \
329 (IS_PCIE(ah) ? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT)
330 struct ath_hal_5212
*ahp
;
332 struct ath_hal_rf
*rf
;
337 HALDEBUG(AH_NULL
, HAL_DEBUG_ATTACH
, "%s: sc %p st %p sh %p\n",
338 __func__
, sc
, (void*) st
, (void*) sh
);
340 /* NB: memory is returned zero'd */
341 ahp
= ath_hal_malloc(sizeof (struct ath_hal_5212
));
342 if (ahp
== AH_NULL
) {
343 HALDEBUG(AH_NULL
, HAL_DEBUG_ANY
,
344 "%s: cannot allocate memory for state block\n", __func__
);
345 *status
= HAL_ENOMEM
;
348 ar5212InitState(ahp
, devid
, sc
, st
, sh
, status
);
349 ah
= &ahp
->ah_priv
.h
;
351 if (!ar5212SetPowerMode(ah
, HAL_PM_AWAKE
, AH_TRUE
)) {
352 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: couldn't wakeup chip\n",
357 /* Read Revisions from Chips before taking out of reset */
358 val
= OS_REG_READ(ah
, AR_SREV
) & AR_SREV_ID
;
359 AH_PRIVATE(ah
)->ah_macVersion
= val
>> AR_SREV_ID_S
;
360 AH_PRIVATE(ah
)->ah_macRev
= val
& AR_SREV_REVISION
;
362 if (!ar5212IsMacSupported(AH_PRIVATE(ah
)->ah_macVersion
, AH_PRIVATE(ah
)->ah_macRev
)) {
363 HALDEBUG(ah
, HAL_DEBUG_ANY
,
364 "%s: Mac Chip Rev 0x%02x.%x not supported\n" ,
365 __func__
, AH_PRIVATE(ah
)->ah_macVersion
,
366 AH_PRIVATE(ah
)->ah_macRev
);
367 ecode
= HAL_ENOTSUPP
;
371 /* setup common ini data; rf backends handle remainder */
372 HAL_INI_INIT(&ahp
->ah_ini_modes
, ar5212Modes
, 6);
373 HAL_INI_INIT(&ahp
->ah_ini_common
, ar5212Common
, 2);
375 if (!ar5212ChipReset(ah
, AH_NULL
)) { /* reset chip */
376 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip reset failed\n", __func__
);
381 AH_PRIVATE(ah
)->ah_phyRev
= OS_REG_READ(ah
, AR_PHY_CHIP_ID
);
384 /* XXX: build flag to disable this? */
385 configurePciePowerSave(ah
);
388 if (!ar5212ChipTest(ah
)) {
389 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: hardware self-test failed\n",
391 ecode
= HAL_ESELFTEST
;
395 /* Enable PCI core retry fix in software for Hainan and up */
396 if (AH_PRIVATE(ah
)->ah_macVersion
>= AR_SREV_VERSION_VENICE
)
397 OS_REG_SET_BIT(ah
, AR_PCICFG
, AR_PCICFG_RETRYFIXEN
);
400 * Set correct Baseband to analog shift
401 * setting to access analog chips.
403 OS_REG_WRITE(ah
, AR_PHY(0), 0x00000007);
405 /* Read Radio Chip Rev Extract */
406 AH_PRIVATE(ah
)->ah_analog5GhzRev
= ar5212GetRadioRev(ah
);
408 rf
= ath_hal_rfprobe(ah
, &ecode
);
412 /* NB: silently accept anything in release code per Atheros */
413 switch (AH_PRIVATE(ah
)->ah_analog5GhzRev
& AR_RADIO_SREV_MAJOR
) {
414 case AR_RAD5111_SREV_MAJOR
:
415 case AR_RAD5112_SREV_MAJOR
:
416 case AR_RAD2112_SREV_MAJOR
:
417 case AR_RAD2111_SREV_MAJOR
:
418 case AR_RAD2413_SREV_MAJOR
:
419 case AR_RAD5413_SREV_MAJOR
:
420 case AR_RAD5424_SREV_MAJOR
:
423 if (AH_PRIVATE(ah
)->ah_analog5GhzRev
== 0) {
425 * When RF_Silent is used, the
426 * analog chip is reset. So when the system boots
427 * up with the radio switch off we cannot determine
428 * the RF chip rev. To workaround this check the
429 * mac+phy revs and if Hainan, set the radio rev
432 if (AH_PRIVATE(ah
)->ah_macVersion
== AR_SREV_VERSION_VENICE
&&
433 AH_PRIVATE(ah
)->ah_macRev
== AR_SREV_HAINAN
&&
434 AH_PRIVATE(ah
)->ah_phyRev
== AR_PHYREV_HAINAN
) {
435 AH_PRIVATE(ah
)->ah_analog5GhzRev
= AR_ANALOG5REV_HAINAN
;
438 if (IS_2413(ah
)) { /* Griffin */
439 AH_PRIVATE(ah
)->ah_analog5GhzRev
=
440 AR_RAD2413_SREV_MAJOR
| 0x1;
443 if (IS_5413(ah
)) { /* Eagle */
444 AH_PRIVATE(ah
)->ah_analog5GhzRev
=
445 AR_RAD5413_SREV_MAJOR
| 0x2;
448 if (IS_2425(ah
) || IS_2417(ah
)) {/* Swan or Nala */
449 AH_PRIVATE(ah
)->ah_analog5GhzRev
=
450 AR_RAD5424_SREV_MAJOR
| 0x2;
455 HALDEBUG(ah
, HAL_DEBUG_ANY
,
456 "%s: 5G Radio Chip Rev 0x%02X is not supported by "
458 __func__
, AH_PRIVATE(ah
)->ah_analog5GhzRev
);
459 ecode
= HAL_ENOTSUPP
;
463 if (IS_RAD5112_REV1(ah
)) {
464 HALDEBUG(ah
, HAL_DEBUG_ANY
,
465 "%s: 5112 Rev 1 is not supported by this "
466 "driver (analog5GhzRev 0x%x)\n", __func__
,
467 AH_PRIVATE(ah
)->ah_analog5GhzRev
);
468 ecode
= HAL_ENOTSUPP
;
472 val
= OS_REG_READ(ah
, AR_PCICFG
);
473 val
= MS(val
, AR_PCICFG_EEPROM_SIZE
);
476 HALDEBUG(ah
, HAL_DEBUG_ANY
,
477 "%s: unsupported EEPROM size %u (0x%x) found\n",
482 /* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */
483 } else if (val
!= AR_PCICFG_EEPROM_SIZE_16K
) {
484 if (AR_PCICFG_EEPROM_SIZE_FAILED
== val
) {
485 HALDEBUG(ah
, HAL_DEBUG_ANY
,
486 "%s: unsupported EEPROM size %u (0x%x) found\n",
491 HALDEBUG(ah
, HAL_DEBUG_ANY
,
492 "%s: EEPROM size = %d. Must be %d (16k).\n",
493 __func__
, val
, AR_PCICFG_EEPROM_SIZE_16K
);
497 ecode
= ath_hal_legacyEepromAttach(ah
);
498 if (ecode
!= HAL_OK
) {
501 ahp
->ah_isHb63
= IS_2425(ah
) && ath_hal_eepromGetFlag(ah
, AR_EEP_ISTALON
);
504 * If Bmode and AR5212, verify 2.4 analog exists
506 if (ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
) &&
507 (AH_PRIVATE(ah
)->ah_analog5GhzRev
& 0xF0) == AR_RAD5111_SREV_MAJOR
) {
509 * Set correct Baseband to analog shift
510 * setting to access analog chips.
512 OS_REG_WRITE(ah
, AR_PHY(0), 0x00004007);
514 AH_PRIVATE(ah
)->ah_analog2GhzRev
= ar5212GetRadioRev(ah
);
516 /* Set baseband for 5GHz chip */
517 OS_REG_WRITE(ah
, AR_PHY(0), 0x00000007);
519 if ((AH_PRIVATE(ah
)->ah_analog2GhzRev
& 0xF0) != AR_RAD2111_SREV_MAJOR
) {
520 HALDEBUG(ah
, HAL_DEBUG_ANY
,
521 "%s: 2G Radio Chip Rev 0x%02X is not "
522 "supported by this driver\n", __func__
,
523 AH_PRIVATE(ah
)->ah_analog2GhzRev
);
524 ecode
= HAL_ENOTSUPP
;
529 ecode
= ath_hal_eepromGet(ah
, AR_EEP_REGDMN_0
, &eeval
);
530 if (ecode
!= HAL_OK
) {
531 HALDEBUG(ah
, HAL_DEBUG_ANY
,
532 "%s: cannot read regulatory domain from EEPROM\n",
536 AH_PRIVATE(ah
)->ah_currentRD
= eeval
;
537 /* XXX record serial number */
540 * Got everything we need now to setup the capabilities.
542 if (!ar5212FillCapabilityInfo(ah
)) {
543 HALDEBUG(ah
, HAL_DEBUG_ANY
,
544 "%s: failed ar5212FillCapabilityInfo\n", __func__
);
549 if (!rf
->attach(ah
, &ecode
)) {
550 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: RF setup failed, status %u\n",
555 * Set noise floor adjust method; we arrange a
556 * direct call instead of thunking.
558 AH_PRIVATE(ah
)->ah_getNfAdjust
= ahp
->ah_rfHal
->getNfAdjust
;
560 /* Initialize gain ladder thermal calibration structure */
561 ar5212InitializeGainValues(ah
);
563 ecode
= ath_hal_eepromGet(ah
, AR_EEP_MACADDR
, ahp
->ah_macaddr
);
564 if (ecode
!= HAL_OK
) {
565 HALDEBUG(ah
, HAL_DEBUG_ANY
,
566 "%s: error getting mac address from EEPROM\n", __func__
);
571 /* Setup of Radar/AR structures happens in ath_hal_initchannels*/
572 ar5212InitNfCalHistBuffer(ah
);
574 /* XXX EAR stuff goes here */
576 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s: return\n", __func__
);
582 ar5212Detach((struct ath_hal
*) ahp
);
586 #undef AH_EEPROM_PROTECT
590 ar5212Detach(struct ath_hal
*ah
)
592 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s:\n", __func__
);
594 HALASSERT(ah
!= AH_NULL
);
595 HALASSERT(ah
->ah_magic
== AR5212_MAGIC
);
600 ar5212SetPowerMode(ah
, HAL_PM_FULL_SLEEP
, AH_TRUE
);
602 ath_hal_eepromDetach(ah
);
607 ar5212ChipTest(struct ath_hal
*ah
)
609 uint32_t regAddr
[2] = { AR_STA_ID0
, AR_PHY_BASE
+(8 << 2) };
611 uint32_t patternData
[4] =
612 { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };
615 /* Test PHY & MAC registers */
616 for (i
= 0; i
< 2; i
++) {
617 uint32_t addr
= regAddr
[i
];
618 uint32_t wrData
, rdData
;
620 regHold
[i
] = OS_REG_READ(ah
, addr
);
621 for (j
= 0; j
< 0x100; j
++) {
622 wrData
= (j
<< 16) | j
;
623 OS_REG_WRITE(ah
, addr
, wrData
);
624 rdData
= OS_REG_READ(ah
, addr
);
625 if (rdData
!= wrData
) {
626 HALDEBUG(ah
, HAL_DEBUG_ANY
,
627 "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
628 __func__
, addr
, wrData
, rdData
);
632 for (j
= 0; j
< 4; j
++) {
633 wrData
= patternData
[j
];
634 OS_REG_WRITE(ah
, addr
, wrData
);
635 rdData
= OS_REG_READ(ah
, addr
);
636 if (wrData
!= rdData
) {
637 HALDEBUG(ah
, HAL_DEBUG_ANY
,
638 "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
639 __func__
, addr
, wrData
, rdData
);
643 OS_REG_WRITE(ah
, regAddr
[i
], regHold
[i
]);
650 * Store the channel edges for the requested operational mode
653 ar5212GetChannelEdges(struct ath_hal
*ah
,
654 uint16_t flags
, uint16_t *low
, uint16_t *high
)
656 if (flags
& CHANNEL_5GHZ
) {
661 if ((flags
& CHANNEL_2GHZ
) &&
662 (ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
) ||
663 ath_hal_eepromGetFlag(ah
, AR_EEP_GMODE
))) {
672 * Fill all software cached or static hardware state information.
673 * Return failure if capabilities are to come from EEPROM and
677 ar5212FillCapabilityInfo(struct ath_hal
*ah
)
679 #define AR_KEYTABLE_SIZE 128
680 #define IS_GRIFFIN_LITE(ah) \
681 (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \
682 AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE)
683 #define IS_COBRA(ah) \
684 (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA)
685 #define IS_2112(ah) \
686 ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR)
688 struct ath_hal_private
*ahpriv
= AH_PRIVATE(ah
);
689 HAL_CAPABILITIES
*pCap
= &ahpriv
->ah_caps
;
690 uint16_t capField
, val
;
692 /* Read the capability EEPROM location */
693 if (ath_hal_eepromGet(ah
, AR_EEP_OPCAP
, &capField
) != HAL_OK
) {
694 HALDEBUG(ah
, HAL_DEBUG_ANY
,
695 "%s: unable to read caps from eeprom\n", __func__
);
699 ath_hal_eepromSet(ah
, AR_EEP_AMODE
, AH_FALSE
);
700 if (capField
== 0 && IS_GRIFFIN_LITE(ah
)) {
702 * For griffin-lite cards with unprogrammed capabilities.
704 ath_hal_eepromSet(ah
, AR_EEP_COMPRESS
, AH_FALSE
);
705 ath_hal_eepromSet(ah
, AR_EEP_FASTFRAME
, AH_FALSE
);
706 ath_hal_eepromSet(ah
, AR_EEP_TURBO5DISABLE
, AH_TRUE
);
707 ath_hal_eepromSet(ah
, AR_EEP_TURBO2DISABLE
, AH_TRUE
);
708 HALDEBUG(ah
, HAL_DEBUG_ATTACH
,
709 "%s: override caps for griffin-lite, now 0x%x (+!turbo)\n",
713 /* Modify reg domain on newer cards that need to work with older sw */
714 if (ahpriv
->ah_opmode
!= HAL_M_HOSTAP
&&
715 ahpriv
->ah_subvendorid
== AR_SUBVENDOR_ID_NEW_A
) {
716 if (ahpriv
->ah_currentRD
== 0x64 ||
717 ahpriv
->ah_currentRD
== 0x65)
718 ahpriv
->ah_currentRD
+= 5;
719 else if (ahpriv
->ah_currentRD
== 0x41)
720 ahpriv
->ah_currentRD
= 0x43;
721 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s: regdomain mapped to 0x%x\n",
722 __func__
, ahpriv
->ah_currentRD
);
725 if (AH_PRIVATE(ah
)->ah_macVersion
== AR_SREV_2417
||
726 AH_PRIVATE(ah
)->ah_macVersion
== AR_SREV_2425
) {
727 HALDEBUG(ah
, HAL_DEBUG_ATTACH
,
728 "%s: enable Bmode and disable turbo for Swan/Nala\n",
730 ath_hal_eepromSet(ah
, AR_EEP_BMODE
, AH_TRUE
);
731 ath_hal_eepromSet(ah
, AR_EEP_COMPRESS
, AH_FALSE
);
732 ath_hal_eepromSet(ah
, AR_EEP_FASTFRAME
, AH_FALSE
);
733 ath_hal_eepromSet(ah
, AR_EEP_TURBO5DISABLE
, AH_TRUE
);
734 ath_hal_eepromSet(ah
, AR_EEP_TURBO2DISABLE
, AH_TRUE
);
737 /* Construct wireless mode from EEPROM */
738 pCap
->halWirelessModes
= 0;
739 if (ath_hal_eepromGetFlag(ah
, AR_EEP_AMODE
)) {
740 pCap
->halWirelessModes
|= HAL_MODE_11A
;
741 if (!ath_hal_eepromGetFlag(ah
, AR_EEP_TURBO5DISABLE
))
742 pCap
->halWirelessModes
|= HAL_MODE_TURBO
;
744 if (ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
))
745 pCap
->halWirelessModes
|= HAL_MODE_11B
;
746 if (ath_hal_eepromGetFlag(ah
, AR_EEP_GMODE
) &&
747 ahpriv
->ah_subvendorid
!= AR_SUBVENDOR_ID_NOG
) {
748 pCap
->halWirelessModes
|= HAL_MODE_11G
;
749 if (!ath_hal_eepromGetFlag(ah
, AR_EEP_TURBO2DISABLE
))
750 pCap
->halWirelessModes
|= HAL_MODE_108G
;
753 pCap
->halLow2GhzChan
= 2312;
755 if (IS_RAD5112_ANY(ah
) || IS_5413(ah
) || IS_2425(ah
) || IS_2417(ah
))
756 pCap
->halHigh2GhzChan
= 2500;
758 pCap
->halHigh2GhzChan
= 2732;
760 pCap
->halLow5GhzChan
= 4915;
761 pCap
->halHigh5GhzChan
= 6100;
763 pCap
->halCipherCkipSupport
= AH_FALSE
;
764 pCap
->halCipherTkipSupport
= AH_TRUE
;
765 pCap
->halCipherAesCcmSupport
=
766 (ath_hal_eepromGetFlag(ah
, AR_EEP_AES
) &&
767 ((AH_PRIVATE(ah
)->ah_macVersion
> AR_SREV_VERSION_VENICE
) ||
768 ((AH_PRIVATE(ah
)->ah_macVersion
== AR_SREV_VERSION_VENICE
) &&
769 (AH_PRIVATE(ah
)->ah_macRev
>= AR_SREV_VERSION_OAHU
))));
771 pCap
->halMicCkipSupport
= AH_FALSE
;
772 pCap
->halMicTkipSupport
= AH_TRUE
;
773 pCap
->halMicAesCcmSupport
= ath_hal_eepromGetFlag(ah
, AR_EEP_AES
);
775 * Starting with Griffin TX+RX mic keys can be combined
776 * in one key cache slot.
778 if (AH_PRIVATE(ah
)->ah_macVersion
>= AR_SREV_VERSION_GRIFFIN
)
779 pCap
->halTkipMicTxRxKeySupport
= AH_TRUE
;
781 pCap
->halTkipMicTxRxKeySupport
= AH_FALSE
;
782 pCap
->halChanSpreadSupport
= AH_TRUE
;
783 pCap
->halSleepAfterBeaconBroken
= AH_TRUE
;
785 if (ahpriv
->ah_macRev
> 1 || IS_COBRA(ah
)) {
786 pCap
->halCompressSupport
=
787 ath_hal_eepromGetFlag(ah
, AR_EEP_COMPRESS
) &&
788 (pCap
->halWirelessModes
& (HAL_MODE_11A
|HAL_MODE_11G
)) != 0;
789 pCap
->halBurstSupport
= ath_hal_eepromGetFlag(ah
, AR_EEP_BURST
);
790 pCap
->halFastFramesSupport
=
791 ath_hal_eepromGetFlag(ah
, AR_EEP_FASTFRAME
) &&
792 (pCap
->halWirelessModes
& (HAL_MODE_11A
|HAL_MODE_11G
)) != 0;
793 pCap
->halChapTuningSupport
= AH_TRUE
;
794 pCap
->halTurboPrimeSupport
= AH_TRUE
;
796 pCap
->halTurboGSupport
= pCap
->halWirelessModes
& HAL_MODE_108G
;
798 pCap
->halPSPollBroken
= AH_TRUE
; /* XXX fixed in later revs? */
799 pCap
->halVEOLSupport
= AH_TRUE
;
800 pCap
->halBssIdMaskSupport
= AH_TRUE
;
801 pCap
->halMcastKeySrchSupport
= AH_TRUE
;
802 if ((ahpriv
->ah_macVersion
== AR_SREV_VERSION_VENICE
&&
803 ahpriv
->ah_macRev
== 8) ||
804 ahpriv
->ah_macVersion
> AR_SREV_VERSION_VENICE
)
805 pCap
->halTsfAddSupport
= AH_TRUE
;
807 if (ath_hal_eepromGet(ah
, AR_EEP_MAXQCU
, &val
) == HAL_OK
)
808 pCap
->halTotalQueues
= val
;
810 pCap
->halTotalQueues
= HAL_NUM_TX_QUEUES
;
812 if (ath_hal_eepromGet(ah
, AR_EEP_KCENTRIES
, &val
) == HAL_OK
)
813 pCap
->halKeyCacheSize
= val
;
815 pCap
->halKeyCacheSize
= AR_KEYTABLE_SIZE
;
817 pCap
->halChanHalfRate
= AH_TRUE
;
818 pCap
->halChanQuarterRate
= AH_TRUE
;
820 if (ath_hal_eepromGetFlag(ah
, AR_EEP_RFKILL
) &&
821 ath_hal_eepromGet(ah
, AR_EEP_RFSILENT
, &ahpriv
->ah_rfsilent
) == HAL_OK
) {
822 /* NB: enabled by default */
823 ahpriv
->ah_rfkillEnabled
= AH_TRUE
;
824 pCap
->halRfSilentSupport
= AH_TRUE
;
827 /* NB: this is a guess, noone seems to know the answer */
828 ahpriv
->ah_rxornIsFatal
=
829 (AH_PRIVATE(ah
)->ah_macVersion
< AR_SREV_VERSION_VENICE
);
831 /* h/w phy counters first appeared in Hainan */
832 pCap
->halHwPhyCounterSupport
=
833 (AH_PRIVATE(ah
)->ah_macVersion
== AR_SREV_VERSION_VENICE
&&
834 AH_PRIVATE(ah
)->ah_macRev
== AR_SREV_HAINAN
) ||
835 AH_PRIVATE(ah
)->ah_macVersion
> AR_SREV_VERSION_VENICE
;
837 pCap
->halTstampPrecision
= 15;
841 #undef IS_GRIFFIN_LITE
842 #undef AR_KEYTABLE_SIZE
846 ar5212Probe(uint16_t vendorid
, uint16_t devid
)
848 if (vendorid
== ATHEROS_VENDOR_ID
||
849 vendorid
== ATHEROS_3COM_VENDOR_ID
||
850 vendorid
== ATHEROS_3COM2_VENDOR_ID
) {
853 return "Atheros 5212 (FPGA)";
855 case AR5212_DEVID_IBM
:
857 return "Atheros 5212";
859 return "Atheros 2413";
861 return "Atheros 2417";
863 return "Atheros 5413";
865 return "Atheros 5424/2424";
870 AH_CHIP(AR5212
, ar5212Probe
, ar5212Attach
);