diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2009-08-07 00:15:15 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:13:34 -0400 |
commit | b5aec950eeb433d4850c1e5fcf14b666048e647d (patch) | |
tree | 4d38f9f64c0ff9bbededed207a5c92c1646ebdd6 /drivers/net/wireless/ath/ath9k/eeprom_4k.c | |
parent | 6780ccf5652a04493f72fafd9af0d9964ee977ad (diff) |
ath9k: Split eeprom.c into manageable pieces
Add eeprom_def.c, eeprom_4k.c and eeprom_9287.c
This improves maintainability.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/eeprom_4k.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom_4k.c | 1181 |
1 files changed, 1181 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c new file mode 100644 index 00000000000..111f4d72092 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -0,0 +1,1181 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "ath9k.h" | ||
18 | |||
19 | static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) | ||
20 | { | ||
21 | return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF); | ||
22 | } | ||
23 | |||
24 | static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) | ||
25 | { | ||
26 | return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); | ||
27 | } | ||
28 | |||
29 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
30 | { | ||
31 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | ||
32 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; | ||
33 | int addr, eep_start_loc = 0; | ||
34 | |||
35 | eep_start_loc = 64; | ||
36 | |||
37 | if (!ath9k_hw_use_flash(ah)) { | ||
38 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
39 | "Reading from EEPROM, not flash\n"); | ||
40 | } | ||
41 | |||
42 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { | ||
43 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | ||
44 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
45 | "Unable to read eeprom region \n"); | ||
46 | return false; | ||
47 | } | ||
48 | eep_data++; | ||
49 | } | ||
50 | |||
51 | return true; | ||
52 | #undef SIZE_EEPROM_4K | ||
53 | } | ||
54 | |||
55 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | ||
56 | { | ||
57 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | ||
58 | struct ar5416_eeprom_4k *eep = | ||
59 | (struct ar5416_eeprom_4k *) &ah->eeprom.map4k; | ||
60 | u16 *eepdata, temp, magic, magic2; | ||
61 | u32 sum = 0, el; | ||
62 | bool need_swap = false; | ||
63 | int i, addr; | ||
64 | |||
65 | |||
66 | if (!ath9k_hw_use_flash(ah)) { | ||
67 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | ||
68 | &magic)) { | ||
69 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
70 | "Reading Magic # failed\n"); | ||
71 | return false; | ||
72 | } | ||
73 | |||
74 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
75 | "Read Magic = 0x%04X\n", magic); | ||
76 | |||
77 | if (magic != AR5416_EEPROM_MAGIC) { | ||
78 | magic2 = swab16(magic); | ||
79 | |||
80 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
81 | need_swap = true; | ||
82 | eepdata = (u16 *) (&ah->eeprom); | ||
83 | |||
84 | for (addr = 0; addr < EEPROM_4K_SIZE; addr++) { | ||
85 | temp = swab16(*eepdata); | ||
86 | *eepdata = temp; | ||
87 | eepdata++; | ||
88 | } | ||
89 | } else { | ||
90 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
91 | "Invalid EEPROM Magic. " | ||
92 | "endianness mismatch.\n"); | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | |||
98 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", | ||
99 | need_swap ? "True" : "False"); | ||
100 | |||
101 | if (need_swap) | ||
102 | el = swab16(ah->eeprom.map4k.baseEepHeader.length); | ||
103 | else | ||
104 | el = ah->eeprom.map4k.baseEepHeader.length; | ||
105 | |||
106 | if (el > sizeof(struct ar5416_eeprom_4k)) | ||
107 | el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); | ||
108 | else | ||
109 | el = el / sizeof(u16); | ||
110 | |||
111 | eepdata = (u16 *)(&ah->eeprom); | ||
112 | |||
113 | for (i = 0; i < el; i++) | ||
114 | sum ^= *eepdata++; | ||
115 | |||
116 | if (need_swap) { | ||
117 | u32 integer; | ||
118 | u16 word; | ||
119 | |||
120 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
121 | "EEPROM Endianness is not native.. Changing\n"); | ||
122 | |||
123 | word = swab16(eep->baseEepHeader.length); | ||
124 | eep->baseEepHeader.length = word; | ||
125 | |||
126 | word = swab16(eep->baseEepHeader.checksum); | ||
127 | eep->baseEepHeader.checksum = word; | ||
128 | |||
129 | word = swab16(eep->baseEepHeader.version); | ||
130 | eep->baseEepHeader.version = word; | ||
131 | |||
132 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
133 | eep->baseEepHeader.regDmn[0] = word; | ||
134 | |||
135 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
136 | eep->baseEepHeader.regDmn[1] = word; | ||
137 | |||
138 | word = swab16(eep->baseEepHeader.rfSilent); | ||
139 | eep->baseEepHeader.rfSilent = word; | ||
140 | |||
141 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
142 | eep->baseEepHeader.blueToothOptions = word; | ||
143 | |||
144 | word = swab16(eep->baseEepHeader.deviceCap); | ||
145 | eep->baseEepHeader.deviceCap = word; | ||
146 | |||
147 | integer = swab32(eep->modalHeader.antCtrlCommon); | ||
148 | eep->modalHeader.antCtrlCommon = integer; | ||
149 | |||
150 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { | ||
151 | integer = swab32(eep->modalHeader.antCtrlChain[i]); | ||
152 | eep->modalHeader.antCtrlChain[i] = integer; | ||
153 | } | ||
154 | |||
155 | for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { | ||
156 | word = swab16(eep->modalHeader.spurChans[i].spurChan); | ||
157 | eep->modalHeader.spurChans[i].spurChan = word; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | ||
162 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | ||
163 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
164 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
165 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | return 0; | ||
170 | #undef EEPROM_4K_SIZE | ||
171 | } | ||
172 | |||
173 | static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | ||
174 | enum eeprom_param param) | ||
175 | { | ||
176 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
177 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | ||
178 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | ||
179 | |||
180 | switch (param) { | ||
181 | case EEP_NFTHRESH_2: | ||
182 | return pModal->noiseFloorThreshCh[0]; | ||
183 | case AR_EEPROM_MAC(0): | ||
184 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
185 | case AR_EEPROM_MAC(1): | ||
186 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
187 | case AR_EEPROM_MAC(2): | ||
188 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
189 | case EEP_REG_0: | ||
190 | return pBase->regDmn[0]; | ||
191 | case EEP_REG_1: | ||
192 | return pBase->regDmn[1]; | ||
193 | case EEP_OP_CAP: | ||
194 | return pBase->deviceCap; | ||
195 | case EEP_OP_MODE: | ||
196 | return pBase->opCapFlags; | ||
197 | case EEP_RF_SILENT: | ||
198 | return pBase->rfSilent; | ||
199 | case EEP_OB_2: | ||
200 | return pModal->ob_01; | ||
201 | case EEP_DB_2: | ||
202 | return pModal->db1_01; | ||
203 | case EEP_MINOR_REV: | ||
204 | return pBase->version & AR5416_EEP_VER_MINOR_MASK; | ||
205 | case EEP_TX_MASK: | ||
206 | return pBase->txMask; | ||
207 | case EEP_RX_MASK: | ||
208 | return pBase->rxMask; | ||
209 | case EEP_FRAC_N_5G: | ||
210 | return 0; | ||
211 | default: | ||
212 | return 0; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
217 | struct ath9k_channel *chan, | ||
218 | struct cal_data_per_freq_4k *pRawDataSet, | ||
219 | u8 *bChans, u16 availPiers, | ||
220 | u16 tPdGainOverlap, int16_t *pMinCalPower, | ||
221 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
222 | u16 numXpdGains) | ||
223 | { | ||
224 | #define TMP_VAL_VPD_TABLE \ | ||
225 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | ||
226 | int i, j, k; | ||
227 | int16_t ss; | ||
228 | u16 idxL = 0, idxR = 0, numPiers; | ||
229 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | ||
230 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
231 | static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] | ||
232 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
233 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | ||
234 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
235 | |||
236 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
237 | u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; | ||
238 | u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; | ||
239 | int16_t vpdStep; | ||
240 | int16_t tmpVal; | ||
241 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
242 | bool match; | ||
243 | int16_t minDelta = 0; | ||
244 | struct chan_centers centers; | ||
245 | #define PD_GAIN_BOUNDARY_DEFAULT 58; | ||
246 | |||
247 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
248 | |||
249 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
250 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
251 | break; | ||
252 | } | ||
253 | |||
254 | match = ath9k_hw_get_lower_upper_index( | ||
255 | (u8)FREQ2FBIN(centers.synth_center, | ||
256 | IS_CHAN_2GHZ(chan)), bChans, numPiers, | ||
257 | &idxL, &idxR); | ||
258 | |||
259 | if (match) { | ||
260 | for (i = 0; i < numXpdGains; i++) { | ||
261 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
262 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
263 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
264 | pRawDataSet[idxL].pwrPdg[i], | ||
265 | pRawDataSet[idxL].vpdPdg[i], | ||
266 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
267 | vpdTableI[i]); | ||
268 | } | ||
269 | } else { | ||
270 | for (i = 0; i < numXpdGains; i++) { | ||
271 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
272 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
273 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
274 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
275 | |||
276 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
277 | |||
278 | maxPwrT4[i] = | ||
279 | min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1], | ||
280 | pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]); | ||
281 | |||
282 | |||
283 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
284 | pPwrL, pVpdL, | ||
285 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
286 | vpdTableL[i]); | ||
287 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
288 | pPwrR, pVpdR, | ||
289 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
290 | vpdTableR[i]); | ||
291 | |||
292 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
293 | vpdTableI[i][j] = | ||
294 | (u8)(ath9k_hw_interpolate((u16) | ||
295 | FREQ2FBIN(centers. | ||
296 | synth_center, | ||
297 | IS_CHAN_2GHZ | ||
298 | (chan)), | ||
299 | bChans[idxL], bChans[idxR], | ||
300 | vpdTableL[i][j], vpdTableR[i][j])); | ||
301 | } | ||
302 | } | ||
303 | } | ||
304 | |||
305 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
306 | |||
307 | k = 0; | ||
308 | |||
309 | for (i = 0; i < numXpdGains; i++) { | ||
310 | if (i == (numXpdGains - 1)) | ||
311 | pPdGainBoundaries[i] = | ||
312 | (u16)(maxPwrT4[i] / 2); | ||
313 | else | ||
314 | pPdGainBoundaries[i] = | ||
315 | (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); | ||
316 | |||
317 | pPdGainBoundaries[i] = | ||
318 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | ||
319 | |||
320 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
321 | minDelta = pPdGainBoundaries[0] - 23; | ||
322 | pPdGainBoundaries[0] = 23; | ||
323 | } else { | ||
324 | minDelta = 0; | ||
325 | } | ||
326 | |||
327 | if (i == 0) { | ||
328 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
329 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
330 | else | ||
331 | ss = 0; | ||
332 | } else { | ||
333 | ss = (int16_t)((pPdGainBoundaries[i - 1] - | ||
334 | (minPwrT4[i] / 2)) - | ||
335 | tPdGainOverlap + 1 + minDelta); | ||
336 | } | ||
337 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
338 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
339 | |||
340 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
341 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
342 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
343 | ss++; | ||
344 | } | ||
345 | |||
346 | sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
347 | tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - | ||
348 | (minPwrT4[i] / 2)); | ||
349 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
350 | tgtIndex : sizeCurrVpdTable; | ||
351 | |||
352 | while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) | ||
353 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
354 | |||
355 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
356 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
357 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
358 | |||
359 | if (tgtIndex >= maxIndex) { | ||
360 | while ((ss <= tgtIndex) && | ||
361 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
362 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | ||
363 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
364 | 255 : tmpVal); | ||
365 | ss++; | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | |||
370 | while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) { | ||
371 | pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT; | ||
372 | i++; | ||
373 | } | ||
374 | |||
375 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
376 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
377 | k++; | ||
378 | } | ||
379 | |||
380 | return; | ||
381 | #undef TMP_VAL_VPD_TABLE | ||
382 | } | ||
383 | |||
384 | static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | ||
385 | struct ath9k_channel *chan, | ||
386 | int16_t *pTxPowerIndexOffset) | ||
387 | { | ||
388 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
389 | struct cal_data_per_freq_4k *pRawDataset; | ||
390 | u8 *pCalBChans = NULL; | ||
391 | u16 pdGainOverlap_t2; | ||
392 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | ||
393 | u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; | ||
394 | u16 numPiers, i, j; | ||
395 | int16_t tMinCalPower; | ||
396 | u16 numXpdGain, xpdMask; | ||
397 | u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; | ||
398 | u32 reg32, regOffset, regChainOffset; | ||
399 | |||
400 | xpdMask = pEepData->modalHeader.xpdGain; | ||
401 | |||
402 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
403 | AR5416_EEP_MINOR_VER_2) { | ||
404 | pdGainOverlap_t2 = | ||
405 | pEepData->modalHeader.pdGainOverlap; | ||
406 | } else { | ||
407 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | ||
408 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
409 | } | ||
410 | |||
411 | pCalBChans = pEepData->calFreqPier2G; | ||
412 | numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; | ||
413 | |||
414 | numXpdGain = 0; | ||
415 | |||
416 | for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { | ||
417 | if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { | ||
418 | if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) | ||
419 | break; | ||
420 | xpdGainValues[numXpdGain] = | ||
421 | (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); | ||
422 | numXpdGain++; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
427 | (numXpdGain - 1) & 0x3); | ||
428 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
429 | xpdGainValues[0]); | ||
430 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
431 | xpdGainValues[1]); | ||
432 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); | ||
433 | |||
434 | for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { | ||
435 | if (AR_SREV_5416_20_OR_LATER(ah) && | ||
436 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && | ||
437 | (i != 0)) { | ||
438 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | ||
439 | } else | ||
440 | regChainOffset = i * 0x1000; | ||
441 | |||
442 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
443 | pRawDataset = pEepData->calPierData2G[i]; | ||
444 | |||
445 | ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, | ||
446 | pRawDataset, pCalBChans, | ||
447 | numPiers, pdGainOverlap_t2, | ||
448 | &tMinCalPower, gainBoundaries, | ||
449 | pdadcValues, numXpdGain); | ||
450 | |||
451 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | ||
452 | REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, | ||
453 | SM(pdGainOverlap_t2, | ||
454 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | ||
455 | | SM(gainBoundaries[0], | ||
456 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | ||
457 | | SM(gainBoundaries[1], | ||
458 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | ||
459 | | SM(gainBoundaries[2], | ||
460 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | ||
461 | | SM(gainBoundaries[3], | ||
462 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
463 | } | ||
464 | |||
465 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | ||
466 | for (j = 0; j < 32; j++) { | ||
467 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | | ||
468 | ((pdadcValues[4 * j + 1] & 0xFF) << 8) | | ||
469 | ((pdadcValues[4 * j + 2] & 0xFF) << 16)| | ||
470 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | ||
471 | REG_WRITE(ah, regOffset, reg32); | ||
472 | |||
473 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
474 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
475 | i, regChainOffset, regOffset, | ||
476 | reg32); | ||
477 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
478 | "PDADC: Chain %d | " | ||
479 | "PDADC %3d Value %3d | " | ||
480 | "PDADC %3d Value %3d | " | ||
481 | "PDADC %3d Value %3d | " | ||
482 | "PDADC %3d Value %3d |\n", | ||
483 | i, 4 * j, pdadcValues[4 * j], | ||
484 | 4 * j + 1, pdadcValues[4 * j + 1], | ||
485 | 4 * j + 2, pdadcValues[4 * j + 2], | ||
486 | 4 * j + 3, | ||
487 | pdadcValues[4 * j + 3]); | ||
488 | |||
489 | regOffset += 4; | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | |||
494 | *pTxPowerIndexOffset = 0; | ||
495 | } | ||
496 | |||
497 | static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | ||
498 | struct ath9k_channel *chan, | ||
499 | int16_t *ratesArray, | ||
500 | u16 cfgCtl, | ||
501 | u16 AntennaReduction, | ||
502 | u16 twiceMaxRegulatoryPower, | ||
503 | u16 powerLimit) | ||
504 | { | ||
505 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
506 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
507 | static const u16 tpScaleReductionTable[5] = | ||
508 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | ||
509 | |||
510 | int i; | ||
511 | int16_t twiceLargestAntenna; | ||
512 | struct cal_ctl_data_4k *rep; | ||
513 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | ||
514 | 0, { 0, 0, 0, 0} | ||
515 | }; | ||
516 | struct cal_target_power_leg targetPowerOfdmExt = { | ||
517 | 0, { 0, 0, 0, 0} }, targetPowerCckExt = { | ||
518 | 0, { 0, 0, 0, 0 } | ||
519 | }; | ||
520 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { | ||
521 | 0, {0, 0, 0, 0} | ||
522 | }; | ||
523 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
524 | u16 ctlModesFor11g[] = | ||
525 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | ||
526 | CTL_2GHT40 | ||
527 | }; | ||
528 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | ||
529 | struct chan_centers centers; | ||
530 | int tx_chainmask; | ||
531 | u16 twiceMinEdgePower; | ||
532 | |||
533 | tx_chainmask = ah->txchainmask; | ||
534 | |||
535 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
536 | |||
537 | twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; | ||
538 | |||
539 | twiceLargestAntenna = (int16_t)min(AntennaReduction - | ||
540 | twiceLargestAntenna, 0); | ||
541 | |||
542 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
543 | |||
544 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { | ||
545 | maxRegAllowedPower -= | ||
546 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | ||
547 | } | ||
548 | |||
549 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
550 | scaledPower = max((u16)0, scaledPower); | ||
551 | |||
552 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; | ||
553 | pCtlMode = ctlModesFor11g; | ||
554 | |||
555 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
556 | pEepData->calTargetPowerCck, | ||
557 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
558 | &targetPowerCck, 4, false); | ||
559 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
560 | pEepData->calTargetPower2G, | ||
561 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
562 | &targetPowerOfdm, 4, false); | ||
563 | ath9k_hw_get_target_powers(ah, chan, | ||
564 | pEepData->calTargetPower2GHT20, | ||
565 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
566 | &targetPowerHt20, 8, false); | ||
567 | |||
568 | if (IS_CHAN_HT40(chan)) { | ||
569 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
570 | ath9k_hw_get_target_powers(ah, chan, | ||
571 | pEepData->calTargetPower2GHT40, | ||
572 | AR5416_NUM_2G_40_TARGET_POWERS, | ||
573 | &targetPowerHt40, 8, true); | ||
574 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
575 | pEepData->calTargetPowerCck, | ||
576 | AR5416_NUM_2G_CCK_TARGET_POWERS, | ||
577 | &targetPowerCckExt, 4, true); | ||
578 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
579 | pEepData->calTargetPower2G, | ||
580 | AR5416_NUM_2G_20_TARGET_POWERS, | ||
581 | &targetPowerOfdmExt, 4, true); | ||
582 | } | ||
583 | |||
584 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
585 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
586 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
587 | if (isHt40CtlMode) | ||
588 | freq = centers.synth_center; | ||
589 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
590 | freq = centers.ext_center; | ||
591 | else | ||
592 | freq = centers.ctl_center; | ||
593 | |||
594 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | ||
595 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
596 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
597 | |||
598 | for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && | ||
599 | pEepData->ctlIndex[i]; i++) { | ||
600 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
601 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
602 | pEepData->ctlIndex[i]) || | ||
603 | (((cfgCtl & ~CTL_MODE_M) | | ||
604 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
605 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | | ||
606 | SD_NO_CTL))) { | ||
607 | rep = &(pEepData->ctlData[i]); | ||
608 | |||
609 | twiceMinEdgePower = | ||
610 | ath9k_hw_get_max_edge_power(freq, | ||
611 | rep->ctlEdges[ar5416_get_ntxchains | ||
612 | (tx_chainmask) - 1], | ||
613 | IS_CHAN_2GHZ(chan), | ||
614 | AR5416_EEP4K_NUM_BAND_EDGES); | ||
615 | |||
616 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { | ||
617 | twiceMaxEdgePower = | ||
618 | min(twiceMaxEdgePower, | ||
619 | twiceMinEdgePower); | ||
620 | } else { | ||
621 | twiceMaxEdgePower = twiceMinEdgePower; | ||
622 | break; | ||
623 | } | ||
624 | } | ||
625 | } | ||
626 | |||
627 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | ||
628 | |||
629 | switch (pCtlMode[ctlMode]) { | ||
630 | case CTL_11B: | ||
631 | for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); | ||
632 | i++) { | ||
633 | targetPowerCck.tPow2x[i] = | ||
634 | min((u16)targetPowerCck.tPow2x[i], | ||
635 | minCtlPower); | ||
636 | } | ||
637 | break; | ||
638 | case CTL_11G: | ||
639 | for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | ||
640 | i++) { | ||
641 | targetPowerOfdm.tPow2x[i] = | ||
642 | min((u16)targetPowerOfdm.tPow2x[i], | ||
643 | minCtlPower); | ||
644 | } | ||
645 | break; | ||
646 | case CTL_2GHT20: | ||
647 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); | ||
648 | i++) { | ||
649 | targetPowerHt20.tPow2x[i] = | ||
650 | min((u16)targetPowerHt20.tPow2x[i], | ||
651 | minCtlPower); | ||
652 | } | ||
653 | break; | ||
654 | case CTL_11B_EXT: | ||
655 | targetPowerCckExt.tPow2x[0] = min((u16) | ||
656 | targetPowerCckExt.tPow2x[0], | ||
657 | minCtlPower); | ||
658 | break; | ||
659 | case CTL_11G_EXT: | ||
660 | targetPowerOfdmExt.tPow2x[0] = min((u16) | ||
661 | targetPowerOfdmExt.tPow2x[0], | ||
662 | minCtlPower); | ||
663 | break; | ||
664 | case CTL_2GHT40: | ||
665 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); | ||
666 | i++) { | ||
667 | targetPowerHt40.tPow2x[i] = | ||
668 | min((u16)targetPowerHt40.tPow2x[i], | ||
669 | minCtlPower); | ||
670 | } | ||
671 | break; | ||
672 | default: | ||
673 | break; | ||
674 | } | ||
675 | } | ||
676 | |||
677 | ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = | ||
678 | ratesArray[rate18mb] = ratesArray[rate24mb] = | ||
679 | targetPowerOfdm.tPow2x[0]; | ||
680 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
681 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
682 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
683 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
684 | |||
685 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
686 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
687 | |||
688 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
689 | ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; | ||
690 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; | ||
691 | ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; | ||
692 | |||
693 | if (IS_CHAN_HT40(chan)) { | ||
694 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { | ||
695 | ratesArray[rateHt40_0 + i] = | ||
696 | targetPowerHt40.tPow2x[i]; | ||
697 | } | ||
698 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
699 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
700 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
701 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | ||
702 | } | ||
703 | } | ||
704 | |||
705 | static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | ||
706 | struct ath9k_channel *chan, | ||
707 | u16 cfgCtl, | ||
708 | u8 twiceAntennaReduction, | ||
709 | u8 twiceMaxRegulatoryPower, | ||
710 | u8 powerLimit) | ||
711 | { | ||
712 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | ||
713 | struct modal_eep_4k_header *pModal = &pEepData->modalHeader; | ||
714 | int16_t ratesArray[Ar5416RateSize]; | ||
715 | int16_t txPowerIndexOffset = 0; | ||
716 | u8 ht40PowerIncForPdadc = 2; | ||
717 | int i; | ||
718 | |||
719 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
720 | |||
721 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
722 | AR5416_EEP_MINOR_VER_2) { | ||
723 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
724 | } | ||
725 | |||
726 | ath9k_hw_set_4k_power_per_rate_table(ah, chan, | ||
727 | &ratesArray[0], cfgCtl, | ||
728 | twiceAntennaReduction, | ||
729 | twiceMaxRegulatoryPower, | ||
730 | powerLimit); | ||
731 | |||
732 | ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); | ||
733 | |||
734 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
735 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | ||
736 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | ||
737 | ratesArray[i] = AR5416_MAX_RATE_POWER; | ||
738 | } | ||
739 | |||
740 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
741 | for (i = 0; i < Ar5416RateSize; i++) | ||
742 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | ||
743 | } | ||
744 | |||
745 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
746 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
747 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
748 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
749 | | ATH9K_POW_SM(ratesArray[rate6mb], 0)); | ||
750 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
751 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
752 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
753 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
754 | | ATH9K_POW_SM(ratesArray[rate24mb], 0)); | ||
755 | |||
756 | if (IS_CHAN_2GHZ(chan)) { | ||
757 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
758 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
759 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
760 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
761 | | ATH9K_POW_SM(ratesArray[rate1l], 0)); | ||
762 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
763 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
764 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
765 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
766 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); | ||
767 | } | ||
768 | |||
769 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
770 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
771 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
772 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
773 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); | ||
774 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
775 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
776 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
777 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
778 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); | ||
779 | |||
780 | if (IS_CHAN_HT40(chan)) { | ||
781 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
782 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
783 | ht40PowerIncForPdadc, 24) | ||
784 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
785 | ht40PowerIncForPdadc, 16) | ||
786 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
787 | ht40PowerIncForPdadc, 8) | ||
788 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
789 | ht40PowerIncForPdadc, 0)); | ||
790 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
791 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
792 | ht40PowerIncForPdadc, 24) | ||
793 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
794 | ht40PowerIncForPdadc, 16) | ||
795 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
796 | ht40PowerIncForPdadc, 8) | ||
797 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
798 | ht40PowerIncForPdadc, 0)); | ||
799 | |||
800 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
801 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
802 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
803 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
804 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | ||
805 | } | ||
806 | |||
807 | i = rate6mb; | ||
808 | |||
809 | if (IS_CHAN_HT40(chan)) | ||
810 | i = rateHt40_0; | ||
811 | else if (IS_CHAN_HT20(chan)) | ||
812 | i = rateHt20_0; | ||
813 | |||
814 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
815 | ah->regulatory.max_power_level = | ||
816 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | ||
817 | else | ||
818 | ah->regulatory.max_power_level = ratesArray[i]; | ||
819 | |||
820 | } | ||
821 | |||
822 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, | ||
823 | struct ath9k_channel *chan) | ||
824 | { | ||
825 | struct modal_eep_4k_header *pModal; | ||
826 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
827 | u8 biaslevel; | ||
828 | |||
829 | if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) | ||
830 | return; | ||
831 | |||
832 | if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) | ||
833 | return; | ||
834 | |||
835 | pModal = &eep->modalHeader; | ||
836 | |||
837 | if (pModal->xpaBiasLvl != 0xff) { | ||
838 | biaslevel = pModal->xpaBiasLvl; | ||
839 | INI_RA(&ah->iniAddac, 7, 1) = | ||
840 | (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3; | ||
841 | } | ||
842 | } | ||
843 | |||
844 | static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | ||
845 | struct modal_eep_4k_header *pModal, | ||
846 | struct ar5416_eeprom_4k *eep, | ||
847 | u8 txRxAttenLocal, int regChainOffset) | ||
848 | { | ||
849 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | ||
850 | pModal->antCtrlChain[0]); | ||
851 | |||
852 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | ||
853 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & | ||
854 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
855 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
856 | SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
857 | SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
858 | |||
859 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
860 | AR5416_EEP_MINOR_VER_3) { | ||
861 | txRxAttenLocal = pModal->txRxAttenCh[0]; | ||
862 | |||
863 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
864 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); | ||
865 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
866 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); | ||
867 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
868 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
869 | pModal->xatten2Margin[0]); | ||
870 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
871 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); | ||
872 | |||
873 | /* Set the block 1 value to block 0 value */ | ||
874 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
875 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
876 | pModal->bswMargin[0]); | ||
877 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
878 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); | ||
879 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
880 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
881 | pModal->xatten2Margin[0]); | ||
882 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, | ||
883 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
884 | pModal->xatten2Db[0]); | ||
885 | } | ||
886 | |||
887 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
888 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
889 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
890 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | ||
891 | |||
892 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | ||
893 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
894 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | ||
895 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | ||
896 | |||
897 | if (AR_SREV_9285_11(ah)) | ||
898 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | ||
899 | } | ||
900 | |||
901 | /* | ||
902 | * Read EEPROM header info and program the device for correct operation | ||
903 | * given the channel value. | ||
904 | */ | ||
905 | static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | ||
906 | struct ath9k_channel *chan) | ||
907 | { | ||
908 | struct modal_eep_4k_header *pModal; | ||
909 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
910 | u8 txRxAttenLocal; | ||
911 | u8 ob[5], db1[5], db2[5]; | ||
912 | u8 ant_div_control1, ant_div_control2; | ||
913 | u32 regVal; | ||
914 | |||
915 | pModal = &eep->modalHeader; | ||
916 | txRxAttenLocal = 23; | ||
917 | |||
918 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
919 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
920 | |||
921 | /* Single chain for 4K EEPROM*/ | ||
922 | ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); | ||
923 | |||
924 | /* Initialize Ant Diversity settings from EEPROM */ | ||
925 | if (pModal->version >= 3) { | ||
926 | ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf); | ||
927 | ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf); | ||
928 | regVal = REG_READ(ah, 0x99ac); | ||
929 | regVal &= (~(0x7f000000)); | ||
930 | regVal |= ((ant_div_control1 & 0x1) << 24); | ||
931 | regVal |= (((ant_div_control1 >> 1) & 0x1) << 29); | ||
932 | regVal |= (((ant_div_control1 >> 2) & 0x1) << 30); | ||
933 | regVal |= ((ant_div_control2 & 0x3) << 25); | ||
934 | regVal |= (((ant_div_control2 >> 2) & 0x3) << 27); | ||
935 | REG_WRITE(ah, 0x99ac, regVal); | ||
936 | regVal = REG_READ(ah, 0x99ac); | ||
937 | regVal = REG_READ(ah, 0xa208); | ||
938 | regVal &= (~(0x1 << 13)); | ||
939 | regVal |= (((ant_div_control1 >> 3) & 0x1) << 13); | ||
940 | REG_WRITE(ah, 0xa208, regVal); | ||
941 | regVal = REG_READ(ah, 0xa208); | ||
942 | } | ||
943 | |||
944 | if (pModal->version >= 2) { | ||
945 | ob[0] = (pModal->ob_01 & 0xf); | ||
946 | ob[1] = (pModal->ob_01 >> 4) & 0xf; | ||
947 | ob[2] = (pModal->ob_234 & 0xf); | ||
948 | ob[3] = ((pModal->ob_234 >> 4) & 0xf); | ||
949 | ob[4] = ((pModal->ob_234 >> 8) & 0xf); | ||
950 | |||
951 | db1[0] = (pModal->db1_01 & 0xf); | ||
952 | db1[1] = ((pModal->db1_01 >> 4) & 0xf); | ||
953 | db1[2] = (pModal->db1_234 & 0xf); | ||
954 | db1[3] = ((pModal->db1_234 >> 4) & 0xf); | ||
955 | db1[4] = ((pModal->db1_234 >> 8) & 0xf); | ||
956 | |||
957 | db2[0] = (pModal->db2_01 & 0xf); | ||
958 | db2[1] = ((pModal->db2_01 >> 4) & 0xf); | ||
959 | db2[2] = (pModal->db2_234 & 0xf); | ||
960 | db2[3] = ((pModal->db2_234 >> 4) & 0xf); | ||
961 | db2[4] = ((pModal->db2_234 >> 8) & 0xf); | ||
962 | |||
963 | } else if (pModal->version == 1) { | ||
964 | ob[0] = (pModal->ob_01 & 0xf); | ||
965 | ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf; | ||
966 | db1[0] = (pModal->db1_01 & 0xf); | ||
967 | db1[1] = db1[2] = db1[3] = | ||
968 | db1[4] = ((pModal->db1_01 >> 4) & 0xf); | ||
969 | db2[0] = (pModal->db2_01 & 0xf); | ||
970 | db2[1] = db2[2] = db2[3] = | ||
971 | db2[4] = ((pModal->db2_01 >> 4) & 0xf); | ||
972 | } else { | ||
973 | int i; | ||
974 | for (i = 0; i < 5; i++) { | ||
975 | ob[i] = pModal->ob_01; | ||
976 | db1[i] = pModal->db1_01; | ||
977 | db2[i] = pModal->db1_01; | ||
978 | } | ||
979 | } | ||
980 | |||
981 | if (AR_SREV_9271(ah)) { | ||
982 | ath9k_hw_analog_shift_rmw(ah, | ||
983 | AR9285_AN_RF2G3, | ||
984 | AR9271_AN_RF2G3_OB_cck, | ||
985 | AR9271_AN_RF2G3_OB_cck_S, | ||
986 | ob[0]); | ||
987 | ath9k_hw_analog_shift_rmw(ah, | ||
988 | AR9285_AN_RF2G3, | ||
989 | AR9271_AN_RF2G3_OB_psk, | ||
990 | AR9271_AN_RF2G3_OB_psk_S, | ||
991 | ob[1]); | ||
992 | ath9k_hw_analog_shift_rmw(ah, | ||
993 | AR9285_AN_RF2G3, | ||
994 | AR9271_AN_RF2G3_OB_qam, | ||
995 | AR9271_AN_RF2G3_OB_qam_S, | ||
996 | ob[2]); | ||
997 | ath9k_hw_analog_shift_rmw(ah, | ||
998 | AR9285_AN_RF2G3, | ||
999 | AR9271_AN_RF2G3_DB_1, | ||
1000 | AR9271_AN_RF2G3_DB_1_S, | ||
1001 | db1[0]); | ||
1002 | ath9k_hw_analog_shift_rmw(ah, | ||
1003 | AR9285_AN_RF2G4, | ||
1004 | AR9271_AN_RF2G4_DB_2, | ||
1005 | AR9271_AN_RF2G4_DB_2_S, | ||
1006 | db2[0]); | ||
1007 | } else { | ||
1008 | ath9k_hw_analog_shift_rmw(ah, | ||
1009 | AR9285_AN_RF2G3, | ||
1010 | AR9285_AN_RF2G3_OB_0, | ||
1011 | AR9285_AN_RF2G3_OB_0_S, | ||
1012 | ob[0]); | ||
1013 | ath9k_hw_analog_shift_rmw(ah, | ||
1014 | AR9285_AN_RF2G3, | ||
1015 | AR9285_AN_RF2G3_OB_1, | ||
1016 | AR9285_AN_RF2G3_OB_1_S, | ||
1017 | ob[1]); | ||
1018 | ath9k_hw_analog_shift_rmw(ah, | ||
1019 | AR9285_AN_RF2G3, | ||
1020 | AR9285_AN_RF2G3_OB_2, | ||
1021 | AR9285_AN_RF2G3_OB_2_S, | ||
1022 | ob[2]); | ||
1023 | ath9k_hw_analog_shift_rmw(ah, | ||
1024 | AR9285_AN_RF2G3, | ||
1025 | AR9285_AN_RF2G3_OB_3, | ||
1026 | AR9285_AN_RF2G3_OB_3_S, | ||
1027 | ob[3]); | ||
1028 | ath9k_hw_analog_shift_rmw(ah, | ||
1029 | AR9285_AN_RF2G3, | ||
1030 | AR9285_AN_RF2G3_OB_4, | ||
1031 | AR9285_AN_RF2G3_OB_4_S, | ||
1032 | ob[4]); | ||
1033 | |||
1034 | ath9k_hw_analog_shift_rmw(ah, | ||
1035 | AR9285_AN_RF2G3, | ||
1036 | AR9285_AN_RF2G3_DB1_0, | ||
1037 | AR9285_AN_RF2G3_DB1_0_S, | ||
1038 | db1[0]); | ||
1039 | ath9k_hw_analog_shift_rmw(ah, | ||
1040 | AR9285_AN_RF2G3, | ||
1041 | AR9285_AN_RF2G3_DB1_1, | ||
1042 | AR9285_AN_RF2G3_DB1_1_S, | ||
1043 | db1[1]); | ||
1044 | ath9k_hw_analog_shift_rmw(ah, | ||
1045 | AR9285_AN_RF2G3, | ||
1046 | AR9285_AN_RF2G3_DB1_2, | ||
1047 | AR9285_AN_RF2G3_DB1_2_S, | ||
1048 | db1[2]); | ||
1049 | ath9k_hw_analog_shift_rmw(ah, | ||
1050 | AR9285_AN_RF2G4, | ||
1051 | AR9285_AN_RF2G4_DB1_3, | ||
1052 | AR9285_AN_RF2G4_DB1_3_S, | ||
1053 | db1[3]); | ||
1054 | ath9k_hw_analog_shift_rmw(ah, | ||
1055 | AR9285_AN_RF2G4, | ||
1056 | AR9285_AN_RF2G4_DB1_4, | ||
1057 | AR9285_AN_RF2G4_DB1_4_S, db1[4]); | ||
1058 | |||
1059 | ath9k_hw_analog_shift_rmw(ah, | ||
1060 | AR9285_AN_RF2G4, | ||
1061 | AR9285_AN_RF2G4_DB2_0, | ||
1062 | AR9285_AN_RF2G4_DB2_0_S, | ||
1063 | db2[0]); | ||
1064 | ath9k_hw_analog_shift_rmw(ah, | ||
1065 | AR9285_AN_RF2G4, | ||
1066 | AR9285_AN_RF2G4_DB2_1, | ||
1067 | AR9285_AN_RF2G4_DB2_1_S, | ||
1068 | db2[1]); | ||
1069 | ath9k_hw_analog_shift_rmw(ah, | ||
1070 | AR9285_AN_RF2G4, | ||
1071 | AR9285_AN_RF2G4_DB2_2, | ||
1072 | AR9285_AN_RF2G4_DB2_2_S, | ||
1073 | db2[2]); | ||
1074 | ath9k_hw_analog_shift_rmw(ah, | ||
1075 | AR9285_AN_RF2G4, | ||
1076 | AR9285_AN_RF2G4_DB2_3, | ||
1077 | AR9285_AN_RF2G4_DB2_3_S, | ||
1078 | db2[3]); | ||
1079 | ath9k_hw_analog_shift_rmw(ah, | ||
1080 | AR9285_AN_RF2G4, | ||
1081 | AR9285_AN_RF2G4_DB2_4, | ||
1082 | AR9285_AN_RF2G4_DB2_4_S, | ||
1083 | db2[4]); | ||
1084 | } | ||
1085 | |||
1086 | |||
1087 | if (AR_SREV_9285_11(ah)) | ||
1088 | REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); | ||
1089 | |||
1090 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | ||
1091 | pModal->switchSettling); | ||
1092 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | ||
1093 | pModal->adcDesiredSize); | ||
1094 | |||
1095 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
1096 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | | ||
1097 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | | ||
1098 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | | ||
1099 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
1100 | |||
1101 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | ||
1102 | pModal->txEndToRxOn); | ||
1103 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, | ||
1104 | pModal->thresh62); | ||
1105 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, | ||
1106 | pModal->thresh62); | ||
1107 | |||
1108 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1109 | AR5416_EEP_MINOR_VER_2) { | ||
1110 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, | ||
1111 | pModal->txFrameToDataStart); | ||
1112 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, | ||
1113 | pModal->txFrameToPaOn); | ||
1114 | } | ||
1115 | |||
1116 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | ||
1117 | AR5416_EEP_MINOR_VER_3) { | ||
1118 | if (IS_CHAN_HT40(chan)) | ||
1119 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
1120 | AR_PHY_SETTLING_SWITCH, | ||
1121 | pModal->swSettleHt40); | ||
1122 | } | ||
1123 | } | ||
1124 | |||
1125 | static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
1126 | struct ath9k_channel *chan) | ||
1127 | { | ||
1128 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
1129 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | ||
1130 | |||
1131 | return pModal->antCtrlCommon & 0xFFFF; | ||
1132 | } | ||
1133 | |||
1134 | static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, | ||
1135 | enum ieee80211_band freq_band) | ||
1136 | { | ||
1137 | return 1; | ||
1138 | } | ||
1139 | |||
1140 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | ||
1141 | { | ||
1142 | #define EEP_MAP4K_SPURCHAN \ | ||
1143 | (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) | ||
1144 | |||
1145 | u16 spur_val = AR_NO_SPUR; | ||
1146 | |||
1147 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1148 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
1149 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
1150 | |||
1151 | switch (ah->config.spurmode) { | ||
1152 | case SPUR_DISABLE: | ||
1153 | break; | ||
1154 | case SPUR_ENABLE_IOCTL: | ||
1155 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
1156 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
1157 | "Getting spur val from new loc. %d\n", spur_val); | ||
1158 | break; | ||
1159 | case SPUR_ENABLE_EEPROM: | ||
1160 | spur_val = EEP_MAP4K_SPURCHAN; | ||
1161 | break; | ||
1162 | } | ||
1163 | |||
1164 | return spur_val; | ||
1165 | |||
1166 | #undef EEP_MAP4K_SPURCHAN | ||
1167 | } | ||
1168 | |||
1169 | const struct eeprom_ops eep_4k_ops = { | ||
1170 | .check_eeprom = ath9k_hw_4k_check_eeprom, | ||
1171 | .get_eeprom = ath9k_hw_4k_get_eeprom, | ||
1172 | .fill_eeprom = ath9k_hw_4k_fill_eeprom, | ||
1173 | .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, | ||
1174 | .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, | ||
1175 | .get_num_ant_config = ath9k_hw_4k_get_num_ant_config, | ||
1176 | .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg, | ||
1177 | .set_board_values = ath9k_hw_4k_set_board_values, | ||
1178 | .set_addac = ath9k_hw_4k_set_addac, | ||
1179 | .set_txpower = ath9k_hw_4k_set_txpower, | ||
1180 | .get_spur_channel = ath9k_hw_4k_get_spur_channel | ||
1181 | }; | ||