1 | /* |
2 | * Copyright (c) 2008 Sam Leffler, Errno Consulting |
3 | * Copyright (c) 2008 Atheros Communications, Inc. |
4 | * |
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. |
8 | * |
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. |
16 | * |
17 | * $Id: ar9160_attach.c,v 1.2 2011/02/20 11:21:04 jmcneill Exp $ |
18 | */ |
19 | #include "opt_ah.h" |
20 | |
21 | #include "ah.h" |
22 | #include "ah_internal.h" |
23 | #include "ah_devid.h" |
24 | |
25 | #include "ar5416/ar5416.h" |
26 | #include "ar5416/ar5416reg.h" |
27 | #include "ar5416/ar5416phy.h" |
28 | |
29 | #include "ar5416/ar9160.ini" |
30 | |
31 | static const HAL_PERCAL_DATA ar9160_iq_cal = { /* multi sample */ |
32 | .calName = "IQ" , .calType = IQ_MISMATCH_CAL, |
33 | .calNumSamples = MAX_CAL_SAMPLES, |
34 | .calCountMax = PER_MIN_LOG_COUNT, |
35 | .calCollect = ar5416IQCalCollect, |
36 | .calPostProc = ar5416IQCalibration |
37 | }; |
38 | static const HAL_PERCAL_DATA ar9160_adc_gain_cal = { /* multi sample */ |
39 | .calName = "ADC Gain" , .calType = ADC_GAIN_CAL, |
40 | .calNumSamples = MAX_CAL_SAMPLES, |
41 | .calCountMax = PER_MIN_LOG_COUNT, |
42 | .calCollect = ar5416AdcGainCalCollect, |
43 | .calPostProc = ar5416AdcGainCalibration |
44 | }; |
45 | static const HAL_PERCAL_DATA ar9160_adc_dc_cal = { /* multi sample */ |
46 | .calName = "ADC DC" , .calType = ADC_DC_CAL, |
47 | .calNumSamples = MAX_CAL_SAMPLES, |
48 | .calCountMax = PER_MIN_LOG_COUNT, |
49 | .calCollect = ar5416AdcDcCalCollect, |
50 | .calPostProc = ar5416AdcDcCalibration |
51 | }; |
52 | static const HAL_PERCAL_DATA ar9160_adc_init_dc_cal = { |
53 | .calName = "ADC Init DC" , .calType = ADC_DC_INIT_CAL, |
54 | .calNumSamples = MIN_CAL_SAMPLES, |
55 | .calCountMax = INIT_LOG_COUNT, |
56 | .calCollect = ar5416AdcDcCalCollect, |
57 | .calPostProc = ar5416AdcDcCalibration |
58 | }; |
59 | |
60 | struct ath_hal *ar9160Attach(uint16_t devid, HAL_SOFTC sc, |
61 | HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status); |
62 | static void ar9160Detach(struct ath_hal *); |
63 | static HAL_BOOL ar9160FillCapabilityInfo(struct ath_hal *ah); |
64 | |
65 | static void |
66 | ar9160AniSetup(struct ath_hal *ah) |
67 | { |
68 | static const struct ar5212AniParams aniparams = { |
69 | .maxNoiseImmunityLevel = 4, /* levels 0..4 */ |
70 | .totalSizeDesired = { -55, -55, -55, -55, -62 }, |
71 | .coarseHigh = { -14, -14, -14, -14, -12 }, |
72 | .coarseLow = { -64, -64, -64, -64, -70 }, |
73 | .firpwr = { -78, -78, -78, -78, -80 }, |
74 | .maxSpurImmunityLevel = 2, |
75 | .cycPwrThr1 = { 2, 4, 6 }, |
76 | .maxFirstepLevel = 2, /* levels 0..2 */ |
77 | .firstep = { 0, 4, 8 }, |
78 | .ofdmTrigHigh = 500, |
79 | .ofdmTrigLow = 200, |
80 | .cckTrigHigh = 200, |
81 | .cckTrigLow = 100, |
82 | .rssiThrHigh = 40, |
83 | .rssiThrLow = 7, |
84 | .period = 100, |
85 | }; |
86 | /* NB: ANI is not enabled yet */ |
87 | ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE); |
88 | } |
89 | |
90 | /* |
91 | * Attach for an AR9160 part. |
92 | */ |
93 | struct ath_hal * |
94 | ar9160Attach(uint16_t devid, HAL_SOFTC sc, |
95 | HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) |
96 | { |
97 | struct ath_hal_5416 *ahp5416; |
98 | struct ath_hal_5212 *ahp; |
99 | struct ath_hal *ah; |
100 | uint32_t val; |
101 | HAL_STATUS ecode; |
102 | HAL_BOOL rfStatus; |
103 | |
104 | HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n" , |
105 | __func__, sc, (void*) st, (void*) sh); |
106 | |
107 | /* NB: memory is returned zero'd */ |
108 | ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); |
109 | if (ahp5416 == AH_NULL) { |
110 | HALDEBUG(AH_NULL, HAL_DEBUG_ANY, |
111 | "%s: cannot allocate memory for state block\n" , __func__); |
112 | *status = HAL_ENOMEM; |
113 | return AH_NULL; |
114 | } |
115 | ar5416InitState(ahp5416, devid, sc, st, sh, status); |
116 | ahp = &ahp5416->ah_5212; |
117 | ah = &ahp->ah_priv.h; |
118 | |
119 | /* XXX override with 9160 specific state */ |
120 | /* override 5416 methods for our needs */ |
121 | ah->ah_detach = ar9160Detach; |
122 | |
123 | AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal; |
124 | AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal; |
125 | AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9160_adc_dc_cal; |
126 | AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9160_adc_init_dc_cal; |
127 | AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; |
128 | |
129 | if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { |
130 | /* reset chip */ |
131 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n" , |
132 | __func__); |
133 | ecode = HAL_EIO; |
134 | goto bad; |
135 | } |
136 | |
137 | if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { |
138 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n" , |
139 | __func__); |
140 | ecode = HAL_EIO; |
141 | goto bad; |
142 | } |
143 | /* Read Revisions from Chips before taking out of reset */ |
144 | val = OS_REG_READ(ah, AR_SREV); |
145 | HALDEBUG(ah, HAL_DEBUG_ATTACH, |
146 | "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n" , |
147 | __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), |
148 | MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); |
149 | /* NB: include chip type to differentiate from pre-Sowl versions */ |
150 | AH_PRIVATE(ah)->ah_macVersion = |
151 | (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; |
152 | AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); |
153 | AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; |
154 | |
155 | /* setup common ini data; rf backends handle remainder */ |
156 | HAL_INI_INIT(&ahp->ah_ini_modes, ar9160Modes, 6); |
157 | HAL_INI_INIT(&ahp->ah_ini_common, ar9160Common, 2); |
158 | |
159 | HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar9160BB_RfGain, 3); |
160 | HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar9160Bank0, 2); |
161 | HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar9160Bank1, 2); |
162 | HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar9160Bank2, 2); |
163 | HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar9160Bank3, 3); |
164 | HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar9160Bank6, 3); |
165 | HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar9160Bank7, 2); |
166 | if (AR_SREV_SOWL_11(ah)) |
167 | HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac_1_1, 2); |
168 | else |
169 | HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar9160Addac, 2); |
170 | |
171 | HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar9160PciePhy, 2); |
172 | ar5416AttachPCIE(ah); |
173 | |
174 | if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ |
175 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n" , __func__); |
176 | ecode = HAL_EIO; |
177 | goto bad; |
178 | } |
179 | |
180 | AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); |
181 | |
182 | if (!ar5212ChipTest(ah)) { |
183 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n" , |
184 | __func__); |
185 | ecode = HAL_ESELFTEST; |
186 | goto bad; |
187 | } |
188 | |
189 | /* |
190 | * Set correct Baseband to analog shift |
191 | * setting to access analog chips. |
192 | */ |
193 | OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); |
194 | |
195 | /* Read Radio Chip Rev Extract */ |
196 | AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); |
197 | switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { |
198 | case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ |
199 | case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ |
200 | break; |
201 | default: |
202 | if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { |
203 | AH_PRIVATE(ah)->ah_analog5GhzRev = |
204 | AR_RAD5133_SREV_MAJOR; |
205 | break; |
206 | } |
207 | #ifdef AH_DEBUG |
208 | HALDEBUG(ah, HAL_DEBUG_ANY, |
209 | "%s: 5G Radio Chip Rev 0x%02X is not supported by " |
210 | "this driver\n" , __func__, |
211 | AH_PRIVATE(ah)->ah_analog5GhzRev); |
212 | ecode = HAL_ENOTSUPP; |
213 | goto bad; |
214 | #endif |
215 | } |
216 | HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: Attaching AR2133 radio\n" , |
217 | __func__); |
218 | rfStatus = ar2133RfAttach(ah, &ecode); |
219 | if (!rfStatus) { |
220 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n" , |
221 | __func__, ecode); |
222 | goto bad; |
223 | } |
224 | |
225 | ecode = ath_hal_v14EepromAttach(ah); |
226 | if (ecode != HAL_OK) |
227 | goto bad; |
228 | |
229 | /* |
230 | * Got everything we need now to setup the capabilities. |
231 | */ |
232 | if (!ar9160FillCapabilityInfo(ah)) { |
233 | ecode = HAL_EEREAD; |
234 | goto bad; |
235 | } |
236 | |
237 | ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); |
238 | if (ecode != HAL_OK) { |
239 | HALDEBUG(ah, HAL_DEBUG_ANY, |
240 | "%s: error getting mac address from EEPROM\n" , __func__); |
241 | goto bad; |
242 | } |
243 | /* XXX How about the serial number ? */ |
244 | /* Read Reg Domain */ |
245 | AH_PRIVATE(ah)->ah_currentRD = |
246 | ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); |
247 | |
248 | /* |
249 | * ah_miscMode is populated by ar5416FillCapabilityInfo() |
250 | * starting from griffin. Set here to make sure that |
251 | * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is |
252 | * placed into hardware. |
253 | */ |
254 | if (ahp->ah_miscMode != 0) |
255 | OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); |
256 | |
257 | ar9160AniSetup(ah); /* Anti Noise Immunity */ |
258 | ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); |
259 | |
260 | HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n" , __func__); |
261 | |
262 | return ah; |
263 | bad: |
264 | if (ahp) |
265 | ar9160Detach((struct ath_hal *) ahp); |
266 | if (status) |
267 | *status = ecode; |
268 | return AH_NULL; |
269 | } |
270 | |
271 | void |
272 | ar9160Detach(struct ath_hal *ah) |
273 | { |
274 | HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n" , __func__); |
275 | |
276 | HALASSERT(ah != AH_NULL); |
277 | HALASSERT(ah->ah_magic == AR5416_MAGIC); |
278 | |
279 | ar5416Detach(ah); |
280 | } |
281 | |
282 | /* |
283 | * Fill all software cached or static hardware state information. |
284 | * Return failure if capabilities are to come from EEPROM and |
285 | * cannot be read. |
286 | */ |
287 | static HAL_BOOL |
288 | ar9160FillCapabilityInfo(struct ath_hal *ah) |
289 | { |
290 | HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; |
291 | |
292 | if (!ar5416FillCapabilityInfo(ah)) |
293 | return AH_FALSE; |
294 | pCap->halCSTSupport = AH_TRUE; |
295 | pCap->halRifsRxSupport = AH_TRUE; |
296 | pCap->halRifsTxSupport = AH_TRUE; |
297 | pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ |
298 | pCap->halExtChanDfsSupport = AH_TRUE; |
299 | pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ |
300 | return AH_TRUE; |
301 | } |
302 | |
303 | static const char* |
304 | ar9160Probe(uint16_t vendorid, uint16_t devid) |
305 | { |
306 | if (vendorid == ATHEROS_VENDOR_ID && devid == AR9160_DEVID_PCI) |
307 | return "Atheros 9160" ; |
308 | return AH_NULL; |
309 | } |
310 | AH_CHIP(AR9160, ar9160Probe, ar9160Attach); |
311 | |