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.
21 #ifdef AH_SUPPORT_AR5312
23 #if !defined(AH_SUPPORT_5112) && \
24 !defined(AH_SUPPORT_5111) && \
25 !defined(AH_SUPPORT_2316) && \
26 !defined(AH_SUPPORT_2317)
27 #error "No 5312 RF support defined"
31 #include "ah_internal.h"
34 #include "ar5312/ar5312.h"
35 #include "ar5312/ar5312reg.h"
36 #include "ar5312/ar5312phy.h"
38 /* Add static register initialization vectors */
39 #define AH_5212_COMMON
40 #include "ar5212/ar5212.ini"
43 * These are not valid 2.4 channels, either we change these
44 * or we need to change the coding to accept these
46 static const uint16_t channels11b
[] = { 2412, 2447, 2484 };
47 static const uint16_t channels11g
[] = { 2312, 2412, 2484 };
49 static HAL_BOOL
ar5312GetMacAddr(struct ath_hal
*ah
);
52 ar5312AniSetup(struct ath_hal
*ah
)
54 static const struct ar5212AniParams aniparams
= {
55 .maxNoiseImmunityLevel
= 4, /* levels 0..4 */
56 .totalSizeDesired
= { -41, -41, -48, -48, -48 },
57 .coarseHigh
= { -18, -18, -16, -14, -12 },
58 .coarseLow
= { -56, -56, -60, -60, -60 },
59 .firpwr
= { -72, -72, -75, -78, -80 },
60 .maxSpurImmunityLevel
= 2,
61 .cycPwrThr1
= { 2, 4, 6 },
62 .maxFirstepLevel
= 2, /* levels 0..2 */
63 .firstep
= { 0, 4, 8 },
72 ar5212AniAttach(ah
, &aniparams
, &aniparams
, AH_TRUE
);
76 * Attach for an AR3212 part.
79 ar5312Attach(uint16_t devid
, HAL_SOFTC sc
,
80 HAL_BUS_TAG st
, HAL_BUS_HANDLE sh
, HAL_STATUS
*status
)
82 struct ath_hal_5212
*ahp
= AH_NULL
;
89 HALDEBUG(AH_NULL
, HAL_DEBUG_ATTACH
, "%s: sc %p st %p sh %p\n",
90 __func__
, sc
, st
, (void*) sh
);
92 /* NB: memory is returned zero'd */
93 ahp
= ath_hal_malloc(sizeof (struct ath_hal_5212
));
95 HALDEBUG(AH_NULL
, HAL_DEBUG_ANY
,
96 "%s: cannot allocate memory for state block\n", __func__
);
100 ar5212InitState(ahp
, devid
, sc
, st
, sh
, status
);
101 ah
= &ahp
->ah_priv
.h
;
103 /* override 5212 methods for our needs */
104 ah
->ah_reset
= ar5312Reset
;
105 ah
->ah_phyDisable
= ar5312PhyDisable
;
106 ah
->ah_setLedState
= ar5312SetLedState
;
107 ah
->ah_detectCardPresent
= ar5312DetectCardPresent
;
108 ah
->ah_setPowerMode
= ar5312SetPowerMode
;
109 ah
->ah_getPowerMode
= ar5312GetPowerMode
;
110 ah
->ah_isInterruptPending
= ar5312IsInterruptPending
;
112 ahp
->ah_priv
.ah_eepromRead
= ar5312EepromRead
;
113 #ifdef AH_SUPPORT_WRITE_EEPROM
114 ahp
->ah_priv
.ah_eepromWrite
= ar5312EepromWrite
;
116 #if ( AH_SUPPORT_2316 || AH_SUPPORT_2317)
118 ahp
->ah_priv
.ah_gpioCfgOutput
= ar5315GpioCfgOutput
;
119 ahp
->ah_priv
.ah_gpioCfgInput
= ar5315GpioCfgInput
;
120 ahp
->ah_priv
.ah_gpioGet
= ar5315GpioGet
;
121 ahp
->ah_priv
.ah_gpioSet
= ar5315GpioSet
;
122 ahp
->ah_priv
.ah_gpioSetIntr
= ar5315GpioSetIntr
;
126 ahp
->ah_priv
.ah_gpioCfgOutput
= ar5312GpioCfgOutput
;
127 ahp
->ah_priv
.ah_gpioCfgInput
= ar5312GpioCfgInput
;
128 ahp
->ah_priv
.ah_gpioGet
= ar5312GpioGet
;
129 ahp
->ah_priv
.ah_gpioSet
= ar5312GpioSet
;
130 ahp
->ah_priv
.ah_gpioSetIntr
= ar5312GpioSetIntr
;
133 ah
->ah_gpioCfgInput
= ahp
->ah_priv
.ah_gpioCfgInput
;
134 ah
->ah_gpioCfgOutput
= ahp
->ah_priv
.ah_gpioCfgOutput
;
135 ah
->ah_gpioGet
= ahp
->ah_priv
.ah_gpioGet
;
136 ah
->ah_gpioSet
= ahp
->ah_priv
.ah_gpioSet
;
137 ah
->ah_gpioSetIntr
= ahp
->ah_priv
.ah_gpioSetIntr
;
139 /* setup common ini data; rf backends handle remainder */
140 HAL_INI_INIT(&ahp
->ah_ini_modes
, ar5212Modes
, 6);
141 HAL_INI_INIT(&ahp
->ah_ini_common
, ar5212Common
, 6);
143 if (!ar5312ChipReset(ah
, AH_NULL
)) { /* reset chip */
144 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: chip reset failed\n", __func__
);
149 #if ( AH_SUPPORT_2316 || AH_SUPPORT_2317)
150 if ((devid
== AR5212_AR2315_REV6
) ||
151 (devid
== AR5212_AR2315_REV7
) ||
152 (devid
== AR5212_AR2317_REV1
) ||
153 (devid
== AR5212_AR2317_REV2
) ) {
154 val
= ((OS_REG_READ(ah
, (AR5315_RSTIMER_BASE
-((uint32_t) sh
)) + AR5315_WREV
)) >> AR5315_WREV_S
)
156 AH_PRIVATE(ah
)->ah_macVersion
= val
>> AR5315_WREV_ID_S
;
157 AH_PRIVATE(ah
)->ah_macRev
= val
& AR5315_WREV_REVISION
;
158 HALDEBUG(ah
, HAL_DEBUG_ATTACH
,
159 "%s: Mac Chip Rev 0x%02x.%x\n" , __func__
,
160 AH_PRIVATE(ah
)->ah_macVersion
, AH_PRIVATE(ah
)->ah_macRev
);
164 val
= OS_REG_READ(ah
, (AR5312_RSTIMER_BASE
- ((uint32_t) sh
)) + 0x0020);
165 val
= OS_REG_READ(ah
, (AR5312_RSTIMER_BASE
- ((uint32_t) sh
)) + 0x0080);
166 /* Read Revisions from Chips */
167 val
= ((OS_REG_READ(ah
, (AR5312_RSTIMER_BASE
- ((uint32_t) sh
)) + AR5312_WREV
)) >> AR5312_WREV_S
) & AR5312_WREV_ID
;
168 AH_PRIVATE(ah
)->ah_macVersion
= val
>> AR5312_WREV_ID_S
;
169 AH_PRIVATE(ah
)->ah_macRev
= val
& AR5312_WREV_REVISION
;
171 /* XXX - THIS IS WRONG. NEEDS TO BE FIXED */
172 if (((AH_PRIVATE(ah
)->ah_macVersion
!= AR_SREV_VERSION_VENICE
&&
173 AH_PRIVATE(ah
)->ah_macVersion
!= AR_SREV_VERSION_VENICE
) ||
174 AH_PRIVATE(ah
)->ah_macRev
< AR_SREV_D2PLUS
) &&
175 AH_PRIVATE(ah
)->ah_macVersion
!= AR_SREV_VERSION_COBRA
) {
177 ath_hal_printf(ah
, "%s: Mac Chip Rev 0x%02x.%x is not supported by "
178 "this driver\n", __func__
,
179 AH_PRIVATE(ah
)->ah_macVersion
,
180 AH_PRIVATE(ah
)->ah_macRev
);
182 ecode
= HAL_ENOTSUPP
;
186 AH_PRIVATE(ah
)->ah_phyRev
= OS_REG_READ(ah
, AR_PHY_CHIP_ID
);
188 if (!ar5212ChipTest(ah
)) {
189 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: hardware self-test failed\n",
191 ecode
= HAL_ESELFTEST
;
196 * Set correct Baseband to analog shift
197 * setting to access analog chips.
199 OS_REG_WRITE(ah
, AR_PHY(0), 0x00000007);
201 /* Read Radio Chip Rev Extract */
202 AH_PRIVATE(ah
)->ah_analog5GhzRev
= ar5212GetRadioRev(ah
);
204 /* NB: silently accept anything in release code per Atheros */
205 if ((AH_PRIVATE(ah
)->ah_analog5GhzRev
& 0xF0) !=
206 AR_RAD5111_SREV_MAJOR
&&
207 (AH_PRIVATE(ah
)->ah_analog5GhzRev
& 0xF0) !=
208 AR_RAD5112_SREV_MAJOR
&&
209 (AH_PRIVATE(ah
)->ah_analog5GhzRev
& 0xF0) !=
210 AR_RAD2111_SREV_MAJOR
&&
211 (AH_PRIVATE(ah
)->ah_analog5GhzRev
& 0xF0) !=
212 AR_RAD2112_SREV_MAJOR
) {
213 ath_hal_printf(ah
, "%s: 5G Radio Chip Rev 0x%02X is not supported by "
214 "this driver\n", __func__
,
215 AH_PRIVATE(ah
)->ah_analog5GhzRev
);
216 ecode
= HAL_ENOTSUPP
;
220 if (IS_5112(ah
) && !IS_RADX112_REV2(ah
)) {
222 ath_hal_printf(ah
, "%s: 5112 Rev 1 is not supported by this "
223 "driver (analog5GhzRev 0x%x)\n", __func__
,
224 AH_PRIVATE(ah
)->ah_analog5GhzRev
);
226 ecode
= HAL_ENOTSUPP
;
230 ecode
= ath_hal_legacyEepromAttach(ah
);
231 if (ecode
!= HAL_OK
) {
236 * If Bmode and AR5212, verify 2.4 analog exists
238 if (ath_hal_eepromGetFlag(ah
, AR_EEP_BMODE
) &&
239 (AH_PRIVATE(ah
)->ah_analog5GhzRev
& 0xF0) == AR_RAD5111_SREV_MAJOR
) {
241 * Set correct Baseband to analog shift
242 * setting to access analog chips.
244 OS_REG_WRITE(ah
, AR_PHY(0), 0x00004007);
246 AH_PRIVATE(ah
)->ah_analog2GhzRev
= ar5212GetRadioRev(ah
);
248 /* Set baseband for 5GHz chip */
249 OS_REG_WRITE(ah
, AR_PHY(0), 0x00000007);
251 if ((AH_PRIVATE(ah
)->ah_analog2GhzRev
& 0xF0) != AR_RAD2111_SREV_MAJOR
) {
253 ath_hal_printf(ah
, "%s: 2G Radio Chip Rev 0x%02X is not "
254 "supported by this driver\n", __func__
,
255 AH_PRIVATE(ah
)->ah_analog2GhzRev
);
257 ecode
= HAL_ENOTSUPP
;
262 ecode
= ath_hal_eepromGet(ah
, AR_EEP_REGDMN_0
, &eeval
);
263 if (ecode
!= HAL_OK
) {
264 HALDEBUG(ah
, HAL_DEBUG_ANY
,
265 "%s: cannot read regulatory domain from EEPROM\n",
269 AH_PRIVATE(ah
)->ah_currentRD
= eeval
;
270 /* XXX record serial number */
272 /* XXX other capabilities */
274 * Got everything we need now to setup the capabilities.
276 if (!ar5212FillCapabilityInfo(ah
)) {
277 HALDEBUG(ah
, HAL_DEBUG_ANY
,
278 "%s: failed ar5212FillCapabilityInfo\n", __func__
);
285 #if defined AH_SUPPORT_2317
286 rfStatus
= ar2317RfAttach(ah
, &ecode
);
288 ecode
= HAL_ENOTSUPP
;
290 else if (IS_2316(ah
))
291 #if defined AH_SUPPORT_2316
292 rfStatus
= ar2316RfAttach(ah
, &ecode
);
294 ecode
= HAL_ENOTSUPP
;
296 else if (IS_5112(ah
))
297 #ifdef AH_SUPPORT_5112
298 rfStatus
= ar5112RfAttach(ah
, &ecode
);
300 ecode
= HAL_ENOTSUPP
;
303 #ifdef AH_SUPPORT_5111
304 rfStatus
= ar5111RfAttach(ah
, &ecode
);
306 ecode
= HAL_ENOTSUPP
;
309 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: RF setup failed, status %u\n",
313 /* arrange a direct call instead of thunking */
314 AH_PRIVATE(ah
)->ah_getNfAdjust
= ahp
->ah_rfHal
->getNfAdjust
;
316 /* Initialize gain ladder thermal calibration structure */
317 ar5212InitializeGainValues(ah
);
319 /* BSP specific call for MAC address of this WMAC device */
320 if (!ar5312GetMacAddr(ah
)) {
321 ecode
= HAL_EEBADMAC
;
326 ar5212InitNfCalHistBuffer(ah
);
328 /* XXX EAR stuff goes here */
333 ar5212Detach((struct ath_hal
*) ahp
);
340 ar5312GetMacAddr(struct ath_hal
*ah
)
342 const struct ar531x_boarddata
*board
= AR5312_BOARDCONFIG(ah
);
343 int wlanNum
= AR5312_UNIT(ah
);
344 const uint8_t *macAddr
;
348 macAddr
= board
->wlan0Mac
;
351 macAddr
= board
->wlan1Mac
;
355 ath_hal_printf(ah
, "Invalid WLAN wmac index (%d)\n",
360 OS_MEMCPY(AH5212(ah
)->ah_macaddr
, macAddr
, 6);
363 #endif /* AH_SUPPORT_AR5312 */