2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2004 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: ar5210_attach.c,v 1.1.1.1 2008/12/11 04:46:27 alc Exp $
22 #include "ah_internal.h"
25 #include "ar5210/ar5210.h"
26 #include "ar5210/ar5210reg.h"
27 #include "ar5210/ar5210phy.h"
29 #include "ah_eeprom_v1.h"
31 static HAL_BOOL
ar5210GetChannelEdges(struct ath_hal
*,
32 uint16_t flags
, uint16_t *low
, uint16_t *high
);
33 static HAL_BOOL
ar5210GetChipPowerLimits(struct ath_hal
*ah
,
34 HAL_CHANNEL
*chans
, uint32_t nchans
);
36 static const struct ath_hal_private ar5210hal
= {{
37 .ah_magic
= AR5210_MAGIC
,
38 .ah_abi
= HAL_ABI_VERSION
,
39 .ah_countryCode
= CTRY_DEFAULT
,
41 .ah_getRateTable
= ar5210GetRateTable
,
42 .ah_detach
= ar5210Detach
,
45 .ah_reset
= ar5210Reset
,
46 .ah_phyDisable
= ar5210PhyDisable
,
47 .ah_disable
= ar5210Disable
,
48 .ah_setPCUConfig
= ar5210SetPCUConfig
,
49 .ah_perCalibration
= ar5210PerCalibration
,
50 .ah_perCalibrationN
= ar5210PerCalibrationN
,
51 .ah_resetCalValid
= ar5210ResetCalValid
,
52 .ah_setTxPowerLimit
= ar5210SetTxPowerLimit
,
53 .ah_getChanNoise
= ath_hal_getChanNoise
,
55 /* Transmit functions */
56 .ah_updateTxTrigLevel
= ar5210UpdateTxTrigLevel
,
57 .ah_setupTxQueue
= ar5210SetupTxQueue
,
58 .ah_setTxQueueProps
= ar5210SetTxQueueProps
,
59 .ah_getTxQueueProps
= ar5210GetTxQueueProps
,
60 .ah_releaseTxQueue
= ar5210ReleaseTxQueue
,
61 .ah_resetTxQueue
= ar5210ResetTxQueue
,
62 .ah_getTxDP
= ar5210GetTxDP
,
63 .ah_setTxDP
= ar5210SetTxDP
,
64 .ah_numTxPending
= ar5210NumTxPending
,
65 .ah_startTxDma
= ar5210StartTxDma
,
66 .ah_stopTxDma
= ar5210StopTxDma
,
67 .ah_setupTxDesc
= ar5210SetupTxDesc
,
68 .ah_setupXTxDesc
= ar5210SetupXTxDesc
,
69 .ah_fillTxDesc
= ar5210FillTxDesc
,
70 .ah_procTxDesc
= ar5210ProcTxDesc
,
71 .ah_getTxIntrQueue
= ar5210GetTxIntrQueue
,
72 .ah_reqTxIntrDesc
= ar5210IntrReqTxDesc
,
75 .ah_getRxDP
= ar5210GetRxDP
,
76 .ah_setRxDP
= ar5210SetRxDP
,
77 .ah_enableReceive
= ar5210EnableReceive
,
78 .ah_stopDmaReceive
= ar5210StopDmaReceive
,
79 .ah_startPcuReceive
= ar5210StartPcuReceive
,
80 .ah_stopPcuReceive
= ar5210StopPcuReceive
,
81 .ah_setMulticastFilter
= ar5210SetMulticastFilter
,
82 .ah_setMulticastFilterIndex
= ar5210SetMulticastFilterIndex
,
83 .ah_clrMulticastFilterIndex
= ar5210ClrMulticastFilterIndex
,
84 .ah_getRxFilter
= ar5210GetRxFilter
,
85 .ah_setRxFilter
= ar5210SetRxFilter
,
86 .ah_setupRxDesc
= ar5210SetupRxDesc
,
87 .ah_procRxDesc
= ar5210ProcRxDesc
,
88 .ah_rxMonitor
= ar5210AniPoll
,
89 .ah_procMibEvent
= ar5210MibEvent
,
92 .ah_getCapability
= ar5210GetCapability
,
93 .ah_setCapability
= ar5210SetCapability
,
94 .ah_getDiagState
= ar5210GetDiagState
,
95 .ah_getMacAddress
= ar5210GetMacAddress
,
96 .ah_setMacAddress
= ar5210SetMacAddress
,
97 .ah_getBssIdMask
= ar5210GetBssIdMask
,
98 .ah_setBssIdMask
= ar5210SetBssIdMask
,
99 .ah_setRegulatoryDomain
= ar5210SetRegulatoryDomain
,
100 .ah_setLedState
= ar5210SetLedState
,
101 .ah_writeAssocid
= ar5210WriteAssocid
,
102 .ah_gpioCfgInput
= ar5210GpioCfgInput
,
103 .ah_gpioCfgOutput
= ar5210GpioCfgOutput
,
104 .ah_gpioGet
= ar5210GpioGet
,
105 .ah_gpioSet
= ar5210GpioSet
,
106 .ah_gpioSetIntr
= ar5210Gpio0SetIntr
,
107 .ah_getTsf32
= ar5210GetTsf32
,
108 .ah_getTsf64
= ar5210GetTsf64
,
109 .ah_resetTsf
= ar5210ResetTsf
,
110 .ah_detectCardPresent
= ar5210DetectCardPresent
,
111 .ah_updateMibCounters
= ar5210UpdateMibCounters
,
112 .ah_getRfGain
= ar5210GetRfgain
,
113 .ah_getDefAntenna
= ar5210GetDefAntenna
,
114 .ah_setDefAntenna
= ar5210SetDefAntenna
,
115 .ah_getAntennaSwitch
= ar5210GetAntennaSwitch
,
116 .ah_setAntennaSwitch
= ar5210SetAntennaSwitch
,
117 .ah_setSifsTime
= ar5210SetSifsTime
,
118 .ah_getSifsTime
= ar5210GetSifsTime
,
119 .ah_setSlotTime
= ar5210SetSlotTime
,
120 .ah_getSlotTime
= ar5210GetSlotTime
,
121 .ah_setAckTimeout
= ar5210SetAckTimeout
,
122 .ah_getAckTimeout
= ar5210GetAckTimeout
,
123 .ah_setAckCTSRate
= ar5210SetAckCTSRate
,
124 .ah_getAckCTSRate
= ar5210GetAckCTSRate
,
125 .ah_setCTSTimeout
= ar5210SetCTSTimeout
,
126 .ah_getCTSTimeout
= ar5210GetCTSTimeout
,
127 .ah_setDecompMask
= ar5210SetDecompMask
,
128 .ah_setCoverageClass
= ar5210SetCoverageClass
,
130 /* Key Cache Functions */
131 .ah_getKeyCacheSize
= ar5210GetKeyCacheSize
,
132 .ah_resetKeyCacheEntry
= ar5210ResetKeyCacheEntry
,
133 .ah_isKeyCacheEntryValid
= ar5210IsKeyCacheEntryValid
,
134 .ah_setKeyCacheEntry
= ar5210SetKeyCacheEntry
,
135 .ah_setKeyCacheEntryMac
= ar5210SetKeyCacheEntryMac
,
137 /* Power Management Functions */
138 .ah_setPowerMode
= ar5210SetPowerMode
,
139 .ah_getPowerMode
= ar5210GetPowerMode
,
141 /* Beacon Functions */
142 .ah_setBeaconTimers
= ar5210SetBeaconTimers
,
143 .ah_beaconInit
= ar5210BeaconInit
,
144 .ah_setStationBeaconTimers
= ar5210SetStaBeaconTimers
,
145 .ah_resetStationBeaconTimers
= ar5210ResetStaBeaconTimers
,
147 /* Interrupt Functions */
148 .ah_isInterruptPending
= ar5210IsInterruptPending
,
149 .ah_getPendingInterrupts
= ar5210GetPendingInterrupts
,
150 .ah_getInterrupts
= ar5210GetInterrupts
,
151 .ah_setInterrupts
= ar5210SetInterrupts
},
153 .ah_getChannelEdges
= ar5210GetChannelEdges
,
154 .ah_getWirelessModes
= ar5210GetWirelessModes
,
155 .ah_eepromRead
= ar5210EepromRead
,
156 #ifdef AH_SUPPORT_WRITE_EEPROM
157 .ah_eepromWrite
= ar5210EepromWrite
,
159 .ah_gpioCfgInput
= ar5210GpioCfgInput
,
160 .ah_gpioCfgOutput
= ar5210GpioCfgOutput
,
161 .ah_gpioGet
= ar5210GpioGet
,
162 .ah_gpioSet
= ar5210GpioSet
,
163 .ah_gpioSetIntr
= ar5210Gpio0SetIntr
,
164 .ah_getChipPowerLimits
= ar5210GetChipPowerLimits
,
167 static HAL_BOOL
ar5210FillCapabilityInfo(struct ath_hal
*ah
);
170 * Attach for an AR5210 part.
172 static struct ath_hal
*
173 ar5210Attach(uint16_t devid
, HAL_SOFTC sc
, HAL_BUS_TAG st
, HAL_BUS_HANDLE sh
,
176 #define N(a) (sizeof(a)/sizeof(a[0]))
177 struct ath_hal_5210
*ahp
;
179 uint32_t revid
, pcicfg
;
184 HALDEBUG(AH_NULL
, HAL_DEBUG_ATTACH
,
185 "%s: devid 0x%x sc %p st %p sh %p\n", __func__
, devid
,
186 sc
, (void*) st
, (void*) sh
);
188 /* NB: memory is returned zero'd */
189 ahp
= ath_hal_malloc(sizeof (struct ath_hal_5210
));
190 if (ahp
== AH_NULL
) {
191 HALDEBUG(AH_NULL
, HAL_DEBUG_ANY
,
192 "%s: no memory for state block\n", __func__
);
196 ah
= &ahp
->ah_priv
.h
;
197 /* set initial values */
198 OS_MEMCPY(&ahp
->ah_priv
, &ar5210hal
, sizeof(struct ath_hal_private
));
203 ah
->ah_devid
= devid
; /* NB: for AH_DEBUG_ALQ */
204 AH_PRIVATE(ah
)->ah_devid
= devid
;
205 AH_PRIVATE(ah
)->ah_subvendorid
= 0; /* XXX */
207 AH_PRIVATE(ah
)->ah_powerLimit
= AR5210_MAX_RATE_POWER
;
208 AH_PRIVATE(ah
)->ah_tpScale
= HAL_TP_SCALE_MAX
; /* no scaling */
210 ahp
->ah_powerMode
= HAL_PM_UNDEFINED
;
211 ahp
->ah_staId1Defaults
= 0;
212 ahp
->ah_rssiThr
= INIT_RSSI_THR
;
213 ahp
->ah_sifstime
= (u_int
) -1;
214 ahp
->ah_slottime
= (u_int
) -1;
215 ahp
->ah_acktimeout
= (u_int
) -1;
216 ahp
->ah_ctstimeout
= (u_int
) -1;
218 if (!ar5210ChipReset(ah
, AH_NULL
)) { /* reset chip */
219 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip reset failed\n",
225 /* Read Revisions from Chips */
226 AH_PRIVATE(ah
)->ah_macVersion
= 1;
227 AH_PRIVATE(ah
)->ah_macRev
= OS_REG_READ(ah
, AR_SREV
) & 0xff;
228 AH_PRIVATE(ah
)->ah_phyRev
= OS_REG_READ(ah
, AR_PHY_CHIPID
);
229 AH_PRIVATE(ah
)->ah_analog2GhzRev
= 0;
231 /* Read Radio Chip Rev Extract */
232 OS_REG_WRITE(ah
, (AR_PHY_BASE
+ (0x34 << 2)), 0x00001c16);
233 for (i
= 0; i
< 4; i
++)
234 OS_REG_WRITE(ah
, (AR_PHY_BASE
+ (0x20 << 2)), 0x00010000);
235 revid
= (OS_REG_READ(ah
, AR_PHY_BASE
+ (256 << 2)) >> 28) & 0xf;
237 /* Chip labelling is 1 greater than revision register for AR5110 */
238 AH_PRIVATE(ah
)->ah_analog5GhzRev
= ath_hal_reverseBits(revid
, 4) + 1;
241 * Read all the settings from the EEPROM and stash
242 * ones we'll use later.
244 pcicfg
= OS_REG_READ(ah
, AR_PCICFG
);
245 OS_REG_WRITE(ah
, AR_PCICFG
, pcicfg
| AR_PCICFG_EEPROMSEL
);
246 ecode
= ath_hal_v1EepromAttach(ah
);
247 if (ecode
!= HAL_OK
) {
250 ecode
= ath_hal_eepromGet(ah
, AR_EEP_REGDMN_0
, &eeval
);
251 if (ecode
!= HAL_OK
) {
252 HALDEBUG(ah
, HAL_DEBUG_ANY
,
253 "%s: cannot read regulatory domain from EEPROM\n",
257 AH_PRIVATE(ah
)->ah_currentRD
= eeval
;
258 ecode
= ath_hal_eepromGet(ah
, AR_EEP_MACADDR
, ahp
->ah_macaddr
);
259 if (ecode
!= HAL_OK
) {
260 HALDEBUG(ah
, HAL_DEBUG_ANY
,
261 "%s: error getting mac address from EEPROM\n", __func__
);
264 OS_REG_WRITE(ah
, AR_PCICFG
, pcicfg
); /* disable EEPROM access */
266 AH_PRIVATE(ah
)->ah_getNfAdjust
= ar5210GetNfAdjust
;
269 * Got everything we need now to setup the capabilities.
271 (void) ar5210FillCapabilityInfo(ah
);
273 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s: return\n", __func__
);
277 OS_REG_WRITE(ah
, AR_PCICFG
, pcicfg
); /* disable EEPROM access */
288 ar5210Detach(struct ath_hal
*ah
)
290 HALDEBUG(ah
, HAL_DEBUG_ATTACH
, "%s:\n", __func__
);
292 HALASSERT(ah
!= AH_NULL
);
293 HALASSERT(ah
->ah_magic
== AR5210_MAGIC
);
295 ath_hal_eepromDetach(ah
);
300 * Store the channel edges for the requested operational mode
303 ar5210GetChannelEdges(struct ath_hal
*ah
,
304 uint16_t flags
, uint16_t *low
, uint16_t *high
)
306 if (flags
& CHANNEL_5GHZ
) {
316 ar5210GetChipPowerLimits(struct ath_hal
*ah
, HAL_CHANNEL
*chans
, uint32_t nchans
)
321 /* XXX fill in, this is just a placeholder */
322 for (i
= 0; i
< nchans
; i
++) {
324 HALDEBUG(ah
, HAL_DEBUG_ATTACH
,
325 "%s: no min/max power for %u/0x%x\n",
326 __func__
, chan
->channel
, chan
->channelFlags
);
327 chan
->maxTxPower
= AR5210_MAX_RATE_POWER
;
328 chan
->minTxPower
= 0;
334 * Fill all software cached or static hardware state information.
337 ar5210FillCapabilityInfo(struct ath_hal
*ah
)
339 struct ath_hal_private
*ahpriv
= AH_PRIVATE(ah
);
340 HAL_CAPABILITIES
*pCap
= &ahpriv
->ah_caps
;
342 pCap
->halWirelessModes
|= HAL_MODE_11A
;
344 pCap
->halLow5GhzChan
= 5120;
345 pCap
->halHigh5GhzChan
= 5430;
347 pCap
->halSleepAfterBeaconBroken
= AH_TRUE
;
348 pCap
->halPSPollBroken
= AH_FALSE
;
350 pCap
->halTotalQueues
= HAL_NUM_TX_QUEUES
;
351 pCap
->halKeyCacheSize
= 64;
354 pCap
->halChanHalfRate
= AH_FALSE
;
355 pCap
->halChanQuarterRate
= AH_FALSE
;
357 if (ath_hal_eepromGetFlag(ah
, AR_EEP_RFKILL
)) {
359 * Setup initial rfsilent settings based on the EEPROM
360 * contents. Pin 0, polarity 0 is fixed; record this
361 * using the EEPROM format found in later parts.
363 ahpriv
->ah_rfsilent
= SM(0, AR_EEPROM_RFSILENT_GPIO_SEL
)
364 | SM(0, AR_EEPROM_RFSILENT_POLARITY
);
365 ahpriv
->ah_rfkillEnabled
= AH_TRUE
;
366 pCap
->halRfSilentSupport
= AH_TRUE
;
369 pCap
->halTstampPrecision
= 15; /* NB: s/w extended from 13 */
371 ahpriv
->ah_rxornIsFatal
= AH_TRUE
;
376 ar5210Probe(uint16_t vendorid
, uint16_t devid
)
378 if (vendorid
== ATHEROS_VENDOR_ID
&&
379 (devid
== AR5210_PROD
|| devid
== AR5210_DEFAULT
))
380 return "Atheros 5210";
383 AH_CHIP(AR5210
, ar5210Probe
, ar5210Attach
);