7154 arn(7D) walks out of bounds when byteswapping the 4K eeprom
7152 weird condition in arn(7D) needs clarification
7153 delete unused code in arn(7D)
7155 arn(7D) should include the mac fields in the eeprom enumeration
1 /*
2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /*
7 * Copyright (c) 2008 Atheros Communications Inc.
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22 #include <sys/param.h>
23 #include <sys/types.h>
24 #include <sys/signal.h>
25 #include <sys/stream.h>
26 #include <sys/termio.h>
27 #include <sys/errno.h>
28 #include <sys/file.h>
29 #include <sys/cmn_err.h>
30 #include <sys/stropts.h>
31 #include <sys/strsubr.h>
32 #include <sys/strtty.h>
33 #include <sys/kbio.h>
34 #include <sys/cred.h>
35 #include <sys/stat.h>
36 #include <sys/consdev.h>
37 #include <sys/kmem.h>
38 #include <sys/modctl.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/pci.h>
42 #include <sys/errno.h>
43 #include <sys/gld.h>
44 #include <sys/dlpi.h>
45 #include <sys/ethernet.h>
46 #include <sys/list.h>
47 #include <sys/byteorder.h>
48 #include <sys/strsun.h>
49 #include <inet/common.h>
50 #include <inet/nd.h>
51 #include <inet/mi.h>
52 #include <inet/wifi_ioctl.h>
53
54 #include "arn_core.h"
55 #include "arn_hw.h"
56 #include "arn_reg.h"
57 #include "arn_phy.h"
58
59 static void
60 ath9k_hw_analog_shift_rmw(struct ath_hal *ah,
61 uint32_t reg, uint32_t mask,
62 uint32_t shift, uint32_t val)
63 {
64 uint32_t regVal;
65
66 regVal = REG_READ(ah, reg) & ~mask;
67 regVal |= (val << shift) & mask;
68
69 REG_WRITE(ah, reg, regVal);
70
71 if (ah->ah_config.analog_shiftreg)
72 drv_usecwait(100);
73 }
74
75 static inline uint16_t
76 ath9k_hw_fbin2freq(uint8_t fbin, boolean_t is2GHz)
77 {
78
79 if (fbin == AR5416_BCHAN_UNUSED)
80 return (fbin);
81
82 return ((uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)));
83 }
84
85 static inline int16_t
86 ath9k_hw_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
87 int16_t targetLeft, int16_t targetRight)
88 {
89 int16_t rv;
90
91 if (srcRight == srcLeft) {
92 rv = targetLeft;
93 } else {
94 rv = (int16_t)(((target - srcLeft) * targetRight +
95 (srcRight - target) * targetLeft) /
96 (srcRight - srcLeft));
97 }
98 return (rv);
99 }
100
101 static inline boolean_t
102 ath9k_hw_get_lower_upper_index(uint8_t target, uint8_t *pList,
103 uint16_t listSize, uint16_t *indexL, uint16_t *indexR)
104 {
105 uint16_t i;
106
107 if (target <= pList[0]) {
108 *indexL = *indexR = 0;
109 return (B_TRUE);
110 }
111 if (target >= pList[listSize - 1]) {
112 *indexL = *indexR = (uint16_t)(listSize - 1);
113 return (B_TRUE);
114 }
115
116 for (i = 0; i < listSize - 1; i++) {
117 if (pList[i] == target) {
118 *indexL = *indexR = i;
119 return (B_TRUE);
120 }
121 if (target < pList[i + 1]) {
122 *indexL = i;
123 *indexR = (uint16_t)(i + 1);
124 return (B_FALSE);
125 }
126 }
127 return (B_FALSE);
128 }
129
130 static boolean_t
131 ath9k_hw_eeprom_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
132 {
133 (void) REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
134
135 if (!ath9k_hw_wait(ah, AR_EEPROM_STATUS_DATA,
136 AR_EEPROM_STATUS_DATA_BUSY |
137 AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
138 return (B_FALSE);
139 }
140
141 *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
142 AR_EEPROM_STATUS_DATA_VAL);
143
144 return (B_TRUE);
145 }
146
147 /* ARGSUSED */
148 static int
149 ath9k_hw_flash_map(struct ath_hal *ah)
150 {
151 ARN_DBG((ARN_DBG_EEPROM, "arn: ath9k_hw_flash_map(): "
152 "using flash but eepom\n"));
153
154 return (0);
155 }
156
157 static boolean_t
158 ath9k_hw_flash_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
159 {
160 *data = FLASH_READ(ah, off);
161
162 return (B_TRUE);
163 }
164
165 static inline boolean_t
166 ath9k_hw_nvram_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
167 {
168 if (ath9k_hw_use_flash(ah))
169 return (ath9k_hw_flash_read(ah, off, data));
170 else
171 return (ath9k_hw_eeprom_read(ah, off, data));
172 }
173
174 static boolean_t
175 ath9k_hw_fill_4k_eeprom(struct ath_hal *ah)
176 {
177 #define SIZE_EEPROM_4K (sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t))
178 struct ath_hal_5416 *ahp = AH5416(ah);
179 struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
180 uint16_t *eep_data;
181 int addr, eep_start_loc = 0;
182
183 eep_start_loc = 64;
184
185 if (!ath9k_hw_use_flash(ah)) {
186 ARN_DBG((ARN_DBG_EEPROM,
187 "Reading from EEPROM, not flash\n"));
188 }
189
190 eep_data = (uint16_t *)eep;
191
192 for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
193 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
194 ARN_DBG((ARN_DBG_EEPROM,
195 "Unable to read eeprom region \n"));
196 return (B_FALSE);
197 }
198 eep_data++;
199 }
200 return (B_TRUE);
201 #undef SIZE_EEPROM_4K
202 }
203
204 static boolean_t
205 ath9k_hw_fill_def_eeprom(struct ath_hal *ah)
206 {
207 #define SIZE_EEPROM_DEF (sizeof (struct ar5416_eeprom_def) / sizeof (uint16_t))
208 struct ath_hal_5416 *ahp = AH5416(ah);
209 struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
210 uint16_t *eep_data;
211 int addr, ar5416_eep_start_loc = 0x100;
212
213 eep_data = (uint16_t *)eep;
214
215 for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
216 if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
217 eep_data)) {
218 ARN_DBG((ARN_DBG_EEPROM,
219 "Unable to read eeprom region\n"));
220 return (B_FALSE);
221 }
222 eep_data++;
223 }
224 return (B_TRUE);
225 #undef SIZE_EEPROM_DEF
226 }
227
228 static boolean_t (*ath9k_fill_eeprom[]) (struct ath_hal *) = {
229 ath9k_hw_fill_def_eeprom,
230 ath9k_hw_fill_4k_eeprom
231 };
232
233 static inline boolean_t
234 ath9k_hw_fill_eeprom(struct ath_hal *ah)
235 {
236 struct ath_hal_5416 *ahp = AH5416(ah);
237
238 return (ath9k_fill_eeprom[ahp->ah_eep_map](ah));
239 }
240
241 static int
242 ath9k_hw_check_def_eeprom(struct ath_hal *ah)
243 {
244 struct ath_hal_5416 *ahp = AH5416(ah);
245 struct ar5416_eeprom_def *eep =
246 (struct ar5416_eeprom_def *)&ahp->ah_eeprom.def;
247 uint16_t *eepdata, temp, magic, magic2;
248 uint32_t sum = 0, el;
249 boolean_t need_swap = B_FALSE;
250 int i, addr, size;
251 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
252 ARN_DBG((ARN_DBG_EEPROM, "arn: "
253 "%s: Reading Magic # failed\n", __func__));
254 return (B_FALSE);
255 }
256
257 if (!ath9k_hw_use_flash(ah)) {
258 ARN_DBG((ARN_DBG_EEPROM, "ath9k: "
259 "%s: Read Magic = 0x%04X\n", __func__, magic));
260
261 if (magic != AR5416_EEPROM_MAGIC) {
262 magic2 = swab16(magic);
263
264 if (magic2 == AR5416_EEPROM_MAGIC) {
265 size = sizeof (struct ar5416_eeprom_def);
266 need_swap = B_TRUE;
267 eepdata = (uint16_t *)(&ahp->ah_eeprom);
268
269 for (addr = 0; addr < size / sizeof (uint16_t);
270 addr++) {
271 temp = swab16(*eepdata);
272 *eepdata = temp;
273 eepdata++;
274
275 ARN_DBG((ARN_DBG_EEPROM,
276 "0x%04X ", *eepdata));
277
278 if (((addr + 1) % 6) == 0)
279 ARN_DBG((ARN_DBG_EEPROM,
280 "arn: "
281 "%s\n", __func__));
282 }
283 } else {
284 ARN_DBG((ARN_DBG_EEPROM,
285 "Invalid EEPROM Magic. "
286 "endianness mismatch.\n"));
287 return (EINVAL);
288 }
289 }
290 }
291
292 ARN_DBG((ARN_DBG_EEPROM, "need_swap = %s.\n",
293 need_swap ? "TRUE" : "FALSE"));
294
295 if (need_swap)
296 el = swab16(ahp->ah_eeprom.def.baseEepHeader.length);
297 else
298 el = ahp->ah_eeprom.def.baseEepHeader.length;
299
300 if (el > sizeof (struct ar5416_eeprom_def))
301 el = sizeof (struct ar5416_eeprom_def) / sizeof (uint16_t);
302 else
303 el = el / sizeof (uint16_t);
304
305 eepdata = (uint16_t *)(&ahp->ah_eeprom);
306
307 for (i = 0; i < el; i++)
308 sum ^= *eepdata++;
309
310 if (need_swap) {
311 uint32_t integer, j;
312 uint16_t word;
313
314 ARN_DBG((ARN_DBG_EEPROM,
315 "EEPROM Endianness is not native.. Changing \n"));
316
317 word = swab16(eep->baseEepHeader.length);
318 eep->baseEepHeader.length = word;
319
320 word = swab16(eep->baseEepHeader.checksum);
321 eep->baseEepHeader.checksum = word;
322
323 word = swab16(eep->baseEepHeader.version);
324 eep->baseEepHeader.version = word;
325
326 word = swab16(eep->baseEepHeader.regDmn[0]);
327 eep->baseEepHeader.regDmn[0] = word;
328
329 word = swab16(eep->baseEepHeader.regDmn[1]);
330 eep->baseEepHeader.regDmn[1] = word;
331
332 word = swab16(eep->baseEepHeader.rfSilent);
333 eep->baseEepHeader.rfSilent = word;
334
335 word = swab16(eep->baseEepHeader.blueToothOptions);
336 eep->baseEepHeader.blueToothOptions = word;
337
338 word = swab16(eep->baseEepHeader.deviceCap);
339 eep->baseEepHeader.deviceCap = word;
340
341 for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
342 struct modal_eep_header *pModal =
343 &eep->modalHeader[j];
344 integer = swab32(pModal->antCtrlCommon);
345 pModal->antCtrlCommon = integer;
346
347 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
348 integer = swab32(pModal->antCtrlChain[i]);
349 pModal->antCtrlChain[i] = integer;
350 }
351
352 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
353 word = swab16(pModal->spurChans[i].spurChan);
354 pModal->spurChans[i].spurChan = word;
355 }
356 }
357 }
358
359 if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER ||
360 ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
361 ARN_DBG((ARN_DBG_EEPROM,
362 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
363 sum, ar5416_get_eep_ver(ahp)));
364 return (EINVAL);
365 }
366
367 return (0);
368 }
369
370 static int
371 ath9k_hw_check_4k_eeprom(struct ath_hal *ah)
372 {
373 #define EEPROM_4K_SIZE (sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t))
374 struct ath_hal_5416 *ahp = AH5416(ah);
375 struct ar5416_eeprom_4k *eep =
376 (struct ar5416_eeprom_4k *)&ahp->ah_eeprom.map4k;
377 uint16_t *eepdata, temp, magic, magic2;
378 uint32_t sum = 0, el;
379 boolean_t need_swap = B_FALSE;
380 int i, addr;
381
382
383 if (!ath9k_hw_use_flash(ah)) {
384
385 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
386 &magic)) {
387 ARN_DBG((ARN_DBG_EEPROM,
388 "Reading Magic # failed\n"));
389 return (B_FALSE);
390 }
391
392 ARN_DBG((ARN_DBG_EEPROM,
393 "Read Magic = 0x%04X\n", magic));
394
395 if (magic != AR5416_EEPROM_MAGIC) {
396 magic2 = swab16(magic);
397
398 if (magic2 == AR5416_EEPROM_MAGIC) {
399 need_swap = B_TRUE;
400 eepdata = (uint16_t *)(&ahp->ah_eeprom);
401
402 for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
403 temp = swab16(*eepdata);
404 *eepdata = temp;
405 eepdata++;
406
407 ARN_DBG((ARN_DBG_EEPROM,
408 "0x%04X ", *eepdata));
409
410 if (((addr + 1) % 6) == 0)
411 ARN_DBG((ARN_DBG_EEPROM, "\n"));
412 }
413 } else {
414 ARN_DBG((ARN_DBG_EEPROM,
415 "Invalid EEPROM Magic. "
416 "endianness mismatch.\n"));
417 return (EINVAL);
418 }
419 }
420 }
421
422 ARN_DBG((ARN_DBG_EEPROM, "need_swap = %s.\n",
423 need_swap ? "True" : "False"));
424
425 if (need_swap)
426 el = swab16(ahp->ah_eeprom.map4k.baseEepHeader.length);
427 else
428 el = ahp->ah_eeprom.map4k.baseEepHeader.length;
429
430 if (el > sizeof (struct ar5416_eeprom_def))
431 el = sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t);
432 else
433 el = el / sizeof (uint16_t);
434
435 eepdata = (uint16_t *)(&ahp->ah_eeprom);
436
437 for (i = 0; i < el; i++)
438 sum ^= *eepdata++;
439
440 if (need_swap) {
441 uint32_t integer;
442 uint16_t word;
443
444 ARN_DBG((ARN_DBG_EEPROM,
445 "EEPROM Endianness is not native.. Changing \n"));
446
447 word = swab16(eep->baseEepHeader.length);
448 eep->baseEepHeader.length = word;
449
450 word = swab16(eep->baseEepHeader.checksum);
451 eep->baseEepHeader.checksum = word;
452
453 word = swab16(eep->baseEepHeader.version);
454 eep->baseEepHeader.version = word;
455
456 word = swab16(eep->baseEepHeader.regDmn[0]);
457 eep->baseEepHeader.regDmn[0] = word;
458
459 word = swab16(eep->baseEepHeader.regDmn[1]);
460 eep->baseEepHeader.regDmn[1] = word;
461
462 word = swab16(eep->baseEepHeader.rfSilent);
463 eep->baseEepHeader.rfSilent = word;
464
465 word = swab16(eep->baseEepHeader.blueToothOptions);
466 eep->baseEepHeader.blueToothOptions = word;
467
468 word = swab16(eep->baseEepHeader.deviceCap);
469 eep->baseEepHeader.deviceCap = word;
470
471 integer = swab32(eep->modalHeader.antCtrlCommon);
472 eep->modalHeader.antCtrlCommon = integer;
473
474 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
475 integer = swab32(eep->modalHeader.antCtrlChain[i]);
476 eep->modalHeader.antCtrlChain[i] = integer;
477 }
478
479 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
480 word = swab16(eep->modalHeader.spurChans[i].spurChan);
481 eep->modalHeader.spurChans[i].spurChan = word;
482 }
483 }
484
485 if (sum != 0xffff || ar5416_get_eep4k_ver(ahp) != AR5416_EEP_VER ||
486 ar5416_get_eep4k_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
487 ARN_DBG((ARN_DBG_EEPROM,
488 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
489 sum, ar5416_get_eep4k_ver(ahp)));
490 return (EINVAL);
491 }
492
493 return (0);
494 #undef EEPROM_4K_SIZE
495 }
496
497 static int
498 (*ath9k_check_eeprom[]) (struct ath_hal *) = {
499 ath9k_hw_check_def_eeprom,
500 ath9k_hw_check_4k_eeprom
501 };
502
503 static inline int
504 ath9k_hw_check_eeprom(struct ath_hal *ah)
505 {
506 struct ath_hal_5416 *ahp = AH5416(ah);
507
508 return (ath9k_check_eeprom[ahp->ah_eep_map](ah));
509 }
510
511 static inline boolean_t
512 ath9k_hw_fill_vpd_table(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
513 uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
514 {
515 uint16_t i, k;
516 uint8_t currPwr = pwrMin;
517 uint16_t idxL = 0, idxR = 0;
518
519 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
520 (void) ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
521 numIntercepts, &(idxL), &(idxR));
522 if (idxR < 1)
523 idxR = 1;
524 if (idxL == numIntercepts - 1)
525 idxL = (uint16_t)(numIntercepts - 2);
526 if (pPwrList[idxL] == pPwrList[idxR])
527 k = pVpdList[idxL];
528 else
529 k = (uint16_t)
530 (((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
531 (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
532 (pPwrList[idxR] - pPwrList[idxL]));
533 pRetVpdList[i] = (uint8_t)k;
534 currPwr += 2;
535 }
536
537 return (B_TRUE);
538 }
539
540 static void
541 ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hal *ah,
542 struct ath9k_channel *chan,
543 struct cal_data_per_freq_4k *pRawDataSet,
544 uint8_t *bChans, uint16_t availPiers,
545 uint16_t tPdGainOverlap, int16_t *pMinCalPower,
546 uint16_t *pPdGainBoundaries, uint8_t *pPDADCValues,
547 uint16_t numXpdGains)
548 {
549 #define TMP_VAL_VPD_TABLE \
550 ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
551 int i, j, k;
552 int16_t ss;
553 uint16_t idxL = 0, idxR = 0, numPiers;
554 static uint8_t vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
555 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
556 static uint8_t vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
557 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
558 static uint8_t vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
559 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
560
561 uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR;
562 uint8_t minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
563 uint8_t maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
564 int16_t vpdStep;
565 int16_t tmpVal;
566 uint16_t sizeCurrVpdTable, maxIndex, tgtIndex;
567 boolean_t match;
568 int16_t minDelta = 0;
569 struct chan_centers centers;
570 #define PD_GAIN_BOUNDARY_DEFAULT 58;
571
572 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
573
574 for (numPiers = 0; numPiers < availPiers; numPiers++) {
575 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
576 break;
577 }
578
579 match = ath9k_hw_get_lower_upper_index(
580 (uint8_t)FREQ2FBIN(centers.synth_center,
581 IS_CHAN_2GHZ(chan)), bChans, numPiers,
582 &idxL, &idxR);
583
584 if (match) {
585 for (i = 0; i < numXpdGains; i++) {
586 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
587 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
588 (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
589 pRawDataSet[idxL].pwrPdg[i],
590 pRawDataSet[idxL].vpdPdg[i],
591 AR5416_EEP4K_PD_GAIN_ICEPTS,
592 vpdTableI[i]);
593 }
594 } else {
595 for (i = 0; i < numXpdGains; i++) {
596 pVpdL = pRawDataSet[idxL].vpdPdg[i];
597 pPwrL = pRawDataSet[idxL].pwrPdg[i];
598 pVpdR = pRawDataSet[idxR].vpdPdg[i];
599 pPwrR = pRawDataSet[idxR].pwrPdg[i];
600
601 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
602
603 maxPwrT4[i] =
604 min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
605 pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
606
607
608 (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
609 pPwrL, pVpdL,
610 AR5416_EEP4K_PD_GAIN_ICEPTS,
611 vpdTableL[i]);
612 (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
613 pPwrR, pVpdR,
614 AR5416_EEP4K_PD_GAIN_ICEPTS,
615 vpdTableR[i]);
616
617 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
618 vpdTableI[i][j] =
619 (uint8_t)(ath9k_hw_interpolate((uint16_t)
620 FREQ2FBIN(centers.
621 synth_center,
622 IS_CHAN_2GHZ
623 (chan)),
624 bChans[idxL], bChans[idxR],
625 vpdTableL[i][j], vpdTableR[i][j]));
626 }
627 }
628 }
629
630 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
631
632 k = 0;
633
634 for (i = 0; i < numXpdGains; i++) {
635 if (i == (numXpdGains - 1))
636 pPdGainBoundaries[i] =
637 (uint16_t)(maxPwrT4[i] / 2);
638 else
639 pPdGainBoundaries[i] =
640 (uint16_t)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
641
642 pPdGainBoundaries[i] =
643 min((uint16_t)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
644
645 if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
646 minDelta = pPdGainBoundaries[0] - 23;
647 pPdGainBoundaries[0] = 23;
648 } else {
649 minDelta = 0;
650 }
651
652 if (i == 0) {
653 if (AR_SREV_9280_10_OR_LATER(ah))
654 ss = (int16_t)(0 - (minPwrT4[i] / 2));
655 else
656 ss = 0;
657 } else {
658 ss = (int16_t)((pPdGainBoundaries[i - 1] -
659 (minPwrT4[i] / 2)) -
660 tPdGainOverlap + 1 + minDelta);
661 }
662 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
663 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
664
665 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
666 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
667 pPDADCValues[k++] =
668 (uint8_t)((tmpVal < 0) ? 0 : tmpVal);
669 ss++;
670 }
671
672 sizeCurrVpdTable =
673 (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
674 tgtIndex = (uint8_t)
675 (pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2));
676 maxIndex =
677 (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
678
679 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
680 pPDADCValues[k++] = vpdTableI[i][ss++];
681
682 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
683 vpdTableI[i][sizeCurrVpdTable - 2]);
684 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
685
686 if (tgtIndex > maxIndex) {
687 while ((ss <= tgtIndex) &&
688 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
689 tmpVal = (int16_t)TMP_VAL_VPD_TABLE;
690 pPDADCValues[k++] = (uint8_t)
691 ((tmpVal > 255) ? 255 : tmpVal);
692 ss++;
693 }
694 }
695 }
696
697 while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
698 pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
699 i++;
700 }
701
702 while (k < AR5416_NUM_PDADC_VALUES) {
703 pPDADCValues[k] = pPDADCValues[k - 1];
704 k++;
705 }
706
707 return;
708 #undef TMP_VAL_VPD_TABLE
709 }
710
711 static void
712 ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hal *ah,
713 struct ath9k_channel *chan,
714 struct cal_data_per_freq *pRawDataSet,
715 uint8_t *bChans, uint16_t availPiers,
716 uint16_t tPdGainOverlap, int16_t *pMinCalPower,
717 uint16_t *pPdGainBoundaries, uint8_t *pPDADCValues,
718 uint16_t numXpdGains)
719 {
720 int i, j, k;
721 int16_t ss;
722 uint16_t idxL = 0, idxR = 0, numPiers;
723 static uint8_t vpdTableL[AR5416_NUM_PD_GAINS]
724 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
725 static uint8_t vpdTableR[AR5416_NUM_PD_GAINS]
726 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
727 static uint8_t vpdTableI[AR5416_NUM_PD_GAINS]
728 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
729
730 uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR;
731 uint8_t minPwrT4[AR5416_NUM_PD_GAINS];
732 uint8_t maxPwrT4[AR5416_NUM_PD_GAINS];
733 int16_t vpdStep;
734 int16_t tmpVal;
735 uint16_t sizeCurrVpdTable, maxIndex, tgtIndex;
736 boolean_t match;
737 int16_t minDelta = 0;
738 struct chan_centers centers;
739
740 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
741
742 for (numPiers = 0; numPiers < availPiers; numPiers++) {
743 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
744 break;
745 }
746
747 match =
748 ath9k_hw_get_lower_upper_index(
749 (uint8_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
750 bChans, numPiers, &idxL, &idxR);
751
752 if (match) {
753 for (i = 0; i < numXpdGains; i++) {
754 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
755 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
756 (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
757 pRawDataSet[idxL].pwrPdg[i],
758 pRawDataSet[idxL].vpdPdg[i],
759 AR5416_PD_GAIN_ICEPTS,
760 vpdTableI[i]);
761 }
762 } else {
763 for (i = 0; i < numXpdGains; i++) {
764 pVpdL = pRawDataSet[idxL].vpdPdg[i];
765 pPwrL = pRawDataSet[idxL].pwrPdg[i];
766 pVpdR = pRawDataSet[idxR].vpdPdg[i];
767 pPwrR = pRawDataSet[idxR].pwrPdg[i];
768
769 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
770
771 maxPwrT4[i] =
772 min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
773 pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
774
775
776 (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
777 pPwrL, pVpdL,
778 AR5416_PD_GAIN_ICEPTS,
779 vpdTableL[i]);
780 (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
781 pPwrR, pVpdR,
782 AR5416_PD_GAIN_ICEPTS,
783 vpdTableR[i]);
784
785 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
786 vpdTableI[i][j] =
787 (uint8_t)(ath9k_hw_interpolate((uint16_t)
788 FREQ2FBIN(centers.
789 synth_center,
790 IS_CHAN_2GHZ
791 (chan)),
792 bChans[idxL], bChans[idxR],
793 vpdTableL[i][j], vpdTableR[i][j]));
794 }
795 }
796 }
797
798 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
799
800 k = 0;
801
802 for (i = 0; i < numXpdGains; i++) {
803 if (i == (numXpdGains - 1))
804 pPdGainBoundaries[i] =
805 (uint16_t)(maxPwrT4[i] / 2);
806 else
807 pPdGainBoundaries[i] =
808 (uint16_t)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
809
810 pPdGainBoundaries[i] =
811 min((uint16_t)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
812
813 if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
814 minDelta = pPdGainBoundaries[0] - 23;
815 pPdGainBoundaries[0] = 23;
816 } else {
817 minDelta = 0;
818 }
819
820 if (i == 0) {
821 if (AR_SREV_9280_10_OR_LATER(ah))
822 ss = (int16_t)(0 - (minPwrT4[i] / 2));
823 else
824 ss = 0;
825 } else {
826 ss = (int16_t)((pPdGainBoundaries[i - 1] -
827 (minPwrT4[i] / 2)) -
828 tPdGainOverlap + 1 + minDelta);
829 }
830 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
831 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
832
833 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
834 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
835 pPDADCValues[k++] =
836 (uint8_t)((tmpVal < 0) ? 0 : tmpVal);
837 ss++;
838 }
839
840 sizeCurrVpdTable =
841 (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
842 tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap -
843 (minPwrT4[i] / 2));
844 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
845 tgtIndex : sizeCurrVpdTable;
846
847 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
848 pPDADCValues[k++] = vpdTableI[i][ss++];
849 }
850
851 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
852 vpdTableI[i][sizeCurrVpdTable - 2]);
853 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
854
855 if (tgtIndex > maxIndex) {
856 while ((ss <= tgtIndex) &&
857 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
858 tmpVal =
859 (int16_t)
860 ((vpdTableI[i][sizeCurrVpdTable - 1] +
861 (ss - maxIndex + 1) * vpdStep));
862 pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ?
863 255 : tmpVal);
864 ss++;
865 }
866 }
867 }
868
869 while (i < AR5416_PD_GAINS_IN_MASK) {
870 pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
871 i++;
872 }
873
874 while (k < AR5416_NUM_PDADC_VALUES) {
875 pPDADCValues[k] = pPDADCValues[k - 1];
876 k++;
877 }
878 }
879
880 static void
881 ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
882 struct ath9k_channel *chan,
883 struct cal_target_power_leg *powInfo,
884 uint16_t numChannels,
885 struct cal_target_power_leg *pNewPower,
886 uint16_t numRates, boolean_t isExtTarget)
887 {
888 struct chan_centers centers;
889 uint16_t clo, chi;
890 int i;
891 int matchIndex = -1, lowIndex = -1;
892 uint16_t freq;
893
894 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
895 freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
896
897 if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
898 IS_CHAN_2GHZ(chan))) {
899 matchIndex = 0;
900 } else {
901 for (i = 0; (i < numChannels) &&
902 (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
903 if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
904 IS_CHAN_2GHZ(chan))) {
905 matchIndex = i;
906 break;
907 } else if ((freq <
908 ath9k_hw_fbin2freq(powInfo[i].bChannel,
909 IS_CHAN_2GHZ(chan))) &&
910 (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
911 IS_CHAN_2GHZ(chan)))) {
912 lowIndex = i - 1;
913 break;
914 }
915 }
916 if ((matchIndex == -1) && (lowIndex == -1))
917 matchIndex = i - 1;
918 }
919
920 if (matchIndex != -1) {
921 *pNewPower = powInfo[matchIndex];
922 } else {
923 clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
924 IS_CHAN_2GHZ(chan));
925 chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
926 IS_CHAN_2GHZ(chan));
927
928 for (i = 0; i < numRates; i++) {
929 pNewPower->tPow2x[i] =
930 (uint8_t)ath9k_hw_interpolate(freq, clo, chi,
931 powInfo[lowIndex].tPow2x[i],
932 powInfo[lowIndex + 1].tPow2x[i]);
933 }
934 }
935 }
936
937 static void
938 ath9k_hw_get_target_powers(struct ath_hal *ah,
939 struct ath9k_channel *chan,
940 struct cal_target_power_ht *powInfo,
941 uint16_t numChannels,
942 struct cal_target_power_ht *pNewPower,
943 uint16_t numRates, boolean_t isHt40Target)
944 {
945 struct chan_centers centers;
946 uint16_t clo, chi;
947 int i;
948 int matchIndex = -1, lowIndex = -1;
949 uint16_t freq;
950
951 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
952 freq = isHt40Target ? centers.synth_center : centers.ctl_center;
953
954 if (freq <=
955 ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
956 matchIndex = 0;
957 } else {
958 for (i = 0; (i < numChannels) &&
959 (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
960 if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
961 IS_CHAN_2GHZ(chan))) {
962 matchIndex = i;
963 break;
964 } else
965 if ((freq <
966 ath9k_hw_fbin2freq(powInfo[i].bChannel,
967 IS_CHAN_2GHZ(chan))) &&
968 (freq > ath9k_hw_fbin2freq
969 (powInfo[i - 1].bChannel,
970 IS_CHAN_2GHZ(chan)))) {
971 lowIndex = i - 1;
972 break;
973 }
974 }
975 if ((matchIndex == -1) && (lowIndex == -1))
976 matchIndex = i - 1;
977 }
978
979 if (matchIndex != -1) {
980 *pNewPower = powInfo[matchIndex];
981 } else {
982 clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
983 IS_CHAN_2GHZ(chan));
984 chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
985 IS_CHAN_2GHZ(chan));
986
987 for (i = 0; i < numRates; i++) {
988 pNewPower->tPow2x[i] =
989 (uint8_t)ath9k_hw_interpolate(freq,
990 clo, chi,
991 powInfo[lowIndex].tPow2x[i],
992 powInfo[lowIndex + 1].tPow2x[i]);
993 }
994 }
995 }
996
997 static uint16_t
998 ath9k_hw_get_max_edge_power(uint16_t freq,
999 struct cal_ctl_edges *pRdEdgesPower,
1000 boolean_t is2GHz, int num_band_edges)
1001 {
1002 uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
1003 int i;
1004
1005 for (i = 0; (i < num_band_edges) &&
1006 (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
1007 if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
1008 is2GHz)) {
1009 twiceMaxEdgePower = pRdEdgesPower[i].tPower;
1010 break;
1011 } else if ((i > 0) &&
1012 (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
1013 is2GHz))) {
1014 if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
1015 is2GHz) < freq &&
1016 pRdEdgesPower[i - 1].flag) {
1017 twiceMaxEdgePower =
1018 pRdEdgesPower[i - 1].tPower;
1019 }
1020 break;
1021 }
1022 }
1023
1024 return (twiceMaxEdgePower);
1025 }
1026
1027 static boolean_t
1028 ath9k_hw_set_def_power_cal_table(struct ath_hal *ah,
1029 struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset)
1030 {
1031 struct ath_hal_5416 *ahp = AH5416(ah);
1032 struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
1033 struct cal_data_per_freq *pRawDataset;
1034 uint8_t *pCalBChans = NULL;
1035 uint16_t pdGainOverlap_t2;
1036 static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES];
1037 uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
1038 uint16_t numPiers, i, j;
1039 int16_t tMinCalPower;
1040 uint16_t numXpdGain, xpdMask;
1041 uint16_t xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
1042 uint32_t reg32, regOffset, regChainOffset;
1043 int16_t modalIdx;
1044
1045 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
1046 xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
1047
1048 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1049 AR5416_EEP_MINOR_VER_2) {
1050 pdGainOverlap_t2 =
1051 pEepData->modalHeader[modalIdx].pdGainOverlap;
1052 } else {
1053 pdGainOverlap_t2 =
1054 (uint16_t)(MS(REG_READ(ah, AR_PHY_TPCRG5),
1055 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
1056 }
1057
1058 if (IS_CHAN_2GHZ(chan)) {
1059 pCalBChans = pEepData->calFreqPier2G;
1060 numPiers = AR5416_NUM_2G_CAL_PIERS;
1061 } else {
1062 pCalBChans = pEepData->calFreqPier5G;
1063 numPiers = AR5416_NUM_5G_CAL_PIERS;
1064 }
1065
1066 numXpdGain = 0;
1067
1068 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
1069 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
1070 if (numXpdGain >= AR5416_NUM_PD_GAINS)
1071 break;
1072 xpdGainValues[numXpdGain] =
1073 (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
1074 numXpdGain++;
1075 }
1076 }
1077
1078 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
1079 (numXpdGain - 1) & 0x3);
1080 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
1081 xpdGainValues[0]);
1082 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
1083 xpdGainValues[1]);
1084 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
1085 xpdGainValues[2]);
1086
1087 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1088 if (AR_SREV_5416_V20_OR_LATER(ah) &&
1089 (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
1090 (i != 0)) {
1091 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
1092 } else
1093 regChainOffset = i * 0x1000;
1094
1095 if (pEepData->baseEepHeader.txMask & (1 << i)) {
1096 if (IS_CHAN_2GHZ(chan))
1097 pRawDataset = pEepData->calPierData2G[i];
1098 else
1099 pRawDataset = pEepData->calPierData5G[i];
1100
1101 ath9k_hw_get_def_gain_boundaries_pdadcs(ah, chan,
1102 pRawDataset, pCalBChans,
1103 numPiers, pdGainOverlap_t2,
1104 &tMinCalPower, gainBoundaries,
1105 pdadcValues, numXpdGain);
1106
1107 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
1108 REG_WRITE(ah,
1109 AR_PHY_TPCRG5 + regChainOffset,
1110 SM(pdGainOverlap_t2,
1111 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
1112 SM(gainBoundaries[0],
1113 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
1114 SM(gainBoundaries[1],
1115 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
1116 SM(gainBoundaries[2],
1117 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
1118 SM(gainBoundaries[3],
1119 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
1120 }
1121
1122 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
1123 for (j = 0; j < 32; j++) {
1124 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
1125 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
1126 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
1127 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
1128 REG_WRITE(ah, regOffset, reg32);
1129
1130 ARN_DBG((ARN_DBG_REG_IO,
1131 "PDADC (%d,%4x): %4.4x %8.8x\n",
1132 i, regChainOffset, regOffset,
1133 reg32));
1134 ARN_DBG((ARN_DBG_REG_IO,
1135 "PDADC: Chain %d | PDADC %3d "
1136 "Value %3d | PDADC %3d Value %3d | "
1137 "PDADC %3d Value %3d | PDADC %3d "
1138 "Value %3d |\n",
1139 i, 4 * j, pdadcValues[4 * j],
1140 4 * j + 1, pdadcValues[4 * j + 1],
1141 4 * j + 2, pdadcValues[4 * j + 2],
1142 4 * j + 3,
1143 pdadcValues[4 * j + 3]));
1144
1145 regOffset += 4;
1146 }
1147 }
1148 }
1149
1150 *pTxPowerIndexOffset = 0;
1151
1152 return (B_TRUE);
1153 }
1154
1155 static boolean_t
1156 ath9k_hw_set_4k_power_cal_table(struct ath_hal *ah,
1157 struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset)
1158 {
1159 struct ath_hal_5416 *ahp = AH5416(ah);
1160 struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
1161 struct cal_data_per_freq_4k *pRawDataset;
1162 uint8_t *pCalBChans = NULL;
1163 uint16_t pdGainOverlap_t2;
1164 static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES];
1165 uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
1166 uint16_t numPiers, i, j;
1167 int16_t tMinCalPower;
1168 uint16_t numXpdGain, xpdMask;
1169 uint16_t xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
1170 uint32_t reg32, regOffset, regChainOffset;
1171
1172 xpdMask = pEepData->modalHeader.xpdGain;
1173
1174 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1175 AR5416_EEP_MINOR_VER_2) {
1176 pdGainOverlap_t2 =
1177 pEepData->modalHeader.pdGainOverlap;
1178 } else {
1179 pdGainOverlap_t2 = (uint16_t)(MS(REG_READ(ah, AR_PHY_TPCRG5),
1180 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
1181 }
1182
1183 pCalBChans = pEepData->calFreqPier2G;
1184 numPiers = AR5416_NUM_2G_CAL_PIERS;
1185
1186 numXpdGain = 0;
1187
1188 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
1189 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
1190 if (numXpdGain >= AR5416_NUM_PD_GAINS)
1191 break;
1192 xpdGainValues[numXpdGain] =
1193 (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
1194 numXpdGain++;
1195 }
1196 }
1197
1198 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
1199 (numXpdGain - 1) & 0x3);
1200 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
1201 xpdGainValues[0]);
1202 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
1203 xpdGainValues[1]);
1204 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
1205 xpdGainValues[2]);
1206
1207 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1208 if (AR_SREV_5416_V20_OR_LATER(ah) &&
1209 (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
1210 (i != 0)) {
1211 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
1212 } else
1213 regChainOffset = i * 0x1000;
1214
1215 if (pEepData->baseEepHeader.txMask & (1 << i)) {
1216 pRawDataset = pEepData->calPierData2G[i];
1217
1218 ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
1219 pRawDataset, pCalBChans,
1220 numPiers, pdGainOverlap_t2,
1221 &tMinCalPower, gainBoundaries,
1222 pdadcValues, numXpdGain);
1223
1224 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
1225 REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
1226 SM(pdGainOverlap_t2,
1227 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
1228 SM(gainBoundaries[0],
1229 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
1230 SM(gainBoundaries[1],
1231 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
1232 SM(gainBoundaries[2],
1233 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
1234 SM(gainBoundaries[3],
1235 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
1236 }
1237
1238 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
1239 for (j = 0; j < 32; j++) {
1240 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
1241 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
1242 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
1243 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
1244 REG_WRITE(ah, regOffset, reg32);
1245
1246 ARN_DBG((ARN_DBG_REG_IO,
1247 "PDADC (%d,%4x): %4.4x %8.8x\n",
1248 i, regChainOffset, regOffset,
1249 reg32));
1250 ARN_DBG((ARN_DBG_REG_IO,
1251 "PDADC: Chain %d | "
1252 "PDADC %3d Value %3d | "
1253 "PDADC %3d Value %3d | "
1254 "PDADC %3d Value %3d | "
1255 "PDADC %3d Value %3d |\n",
1256 i, 4 * j, pdadcValues[4 * j],
1257 4 * j + 1, pdadcValues[4 * j + 1],
1258 4 * j + 2, pdadcValues[4 * j + 2],
1259 4 * j + 3,
1260 pdadcValues[4 * j + 3]));
1261
1262 regOffset += 4;
1263 }
1264 }
1265 }
1266
1267 *pTxPowerIndexOffset = 0;
1268
1269 return (B_TRUE);
1270 }
1271
1272 static boolean_t
1273 ath9k_hw_set_def_power_per_rate_table(struct ath_hal *ah,
1274 struct ath9k_channel *chan,
1275 int16_t *ratesArray,
1276 uint16_t cfgCtl,
1277 uint16_t AntennaReduction,
1278 uint16_t twiceMaxRegulatoryPower,
1279 uint16_t powerLimit)
1280 {
1281 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
1282 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
1283 struct ath_hal_5416 *ahp = AH5416(ah);
1284 struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
1285 uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
1286 static const uint16_t tpScaleReductionTable[5] =
1287 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
1288
1289 int i;
1290 int8_t twiceLargestAntenna;
1291 struct cal_ctl_data *rep;
1292 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
1293 0, { 0, 0, 0, 0}
1294 };
1295 struct cal_target_power_leg targetPowerOfdmExt = {
1296 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
1297 0, { 0, 0, 0, 0 }
1298 };
1299 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
1300 0, {0, 0, 0, 0}
1301 };
1302 uint16_t scaledPower = 0, minCtlPower, maxRegAllowedPower;
1303 uint16_t ctlModesFor11a[] =
1304 { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
1305 uint16_t ctlModesFor11g[] =
1306 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
1307 CTL_2GHT40
1308 };
1309 uint16_t numCtlModes, *pCtlMode, ctlMode, freq;
1310 struct chan_centers centers;
1311 int tx_chainmask;
1312 uint16_t twiceMinEdgePower;
1313
1314 tx_chainmask = ahp->ah_txchainmask;
1315
1316 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
1317
1318 twiceLargestAntenna = max(
1319 pEepData->modalHeader
1320 [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
1321 pEepData->modalHeader
1322 [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
1323
1324 twiceLargestAntenna =
1325 max((uint8_t)twiceLargestAntenna,
1326 pEepData->modalHeader
1327 [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
1328
1329 twiceLargestAntenna =
1330 (int16_t)min(AntennaReduction - twiceLargestAntenna, 0);
1331
1332 maxRegAllowedPower =
1333 twiceMaxRegulatoryPower + twiceLargestAntenna;
1334
1335 if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
1336 maxRegAllowedPower -=
1337 (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
1338 }
1339
1340 scaledPower = min(powerLimit, maxRegAllowedPower);
1341
1342 switch (ar5416_get_ntxchains(tx_chainmask)) {
1343 case 1:
1344 break;
1345 case 2:
1346 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1347 break;
1348 case 3:
1349 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1350 break;
1351 }
1352
1353 scaledPower = max((uint16_t)0, scaledPower);
1354
1355 if (IS_CHAN_2GHZ(chan)) {
1356 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
1357 SUB_NUM_CTL_MODES_AT_2G_40;
1358 pCtlMode = ctlModesFor11g;
1359
1360 ath9k_hw_get_legacy_target_powers(ah, chan,
1361 pEepData->calTargetPowerCck,
1362 AR5416_NUM_2G_CCK_TARGET_POWERS,
1363 &targetPowerCck, 4, B_FALSE);
1364 ath9k_hw_get_legacy_target_powers(ah, chan,
1365 pEepData->calTargetPower2G,
1366 AR5416_NUM_2G_20_TARGET_POWERS,
1367 &targetPowerOfdm, 4, B_FALSE);
1368 ath9k_hw_get_target_powers(ah, chan,
1369 pEepData->calTargetPower2GHT20,
1370 AR5416_NUM_2G_20_TARGET_POWERS,
1371 &targetPowerHt20, 8, B_FALSE);
1372
1373 if (IS_CHAN_HT40(chan)) {
1374 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
1375 ath9k_hw_get_target_powers(ah, chan,
1376 pEepData->calTargetPower2GHT40,
1377 AR5416_NUM_2G_40_TARGET_POWERS,
1378 &targetPowerHt40, 8, B_TRUE);
1379 ath9k_hw_get_legacy_target_powers(ah, chan,
1380 pEepData->calTargetPowerCck,
1381 AR5416_NUM_2G_CCK_TARGET_POWERS,
1382 &targetPowerCckExt, 4, B_TRUE);
1383 ath9k_hw_get_legacy_target_powers(ah, chan,
1384 pEepData->calTargetPower2G,
1385 AR5416_NUM_2G_20_TARGET_POWERS,
1386 &targetPowerOfdmExt, 4, B_TRUE);
1387 }
1388 } else {
1389 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
1390 SUB_NUM_CTL_MODES_AT_5G_40;
1391 pCtlMode = ctlModesFor11a;
1392
1393 ath9k_hw_get_legacy_target_powers(ah, chan,
1394 pEepData->calTargetPower5G,
1395 AR5416_NUM_5G_20_TARGET_POWERS,
1396 &targetPowerOfdm, 4, B_FALSE);
1397 ath9k_hw_get_target_powers(ah, chan,
1398 pEepData->calTargetPower5GHT20,
1399 AR5416_NUM_5G_20_TARGET_POWERS,
1400 &targetPowerHt20, 8, B_FALSE);
1401
1402 if (IS_CHAN_HT40(chan)) {
1403 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
1404 ath9k_hw_get_target_powers(ah, chan,
1405 pEepData->calTargetPower5GHT40,
1406 AR5416_NUM_5G_40_TARGET_POWERS,
1407 &targetPowerHt40, 8, B_TRUE);
1408 ath9k_hw_get_legacy_target_powers(ah, chan,
1409 pEepData->calTargetPower5G,
1410 AR5416_NUM_5G_20_TARGET_POWERS,
1411 &targetPowerOfdmExt, 4, B_TRUE);
1412 }
1413 }
1414
1415 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
1416 boolean_t isHt40CtlMode =
1417 (pCtlMode[ctlMode] == CTL_5GHT40) ||
1418 (pCtlMode[ctlMode] == CTL_2GHT40);
1419 if (isHt40CtlMode)
1420 freq = centers.synth_center;
1421 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
1422 freq = centers.ext_center;
1423 else
1424 freq = centers.ctl_center;
1425
1426 if (ar5416_get_eep_ver(ahp) == 14 &&
1427 ar5416_get_eep_rev(ahp) <= 2)
1428 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
1429
1430 ARN_DBG((ARN_DBG_EEPROM, "arn: "
1431 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
1432 "EXT_ADDITIVE %d\n",
1433 ctlMode, numCtlModes, isHt40CtlMode,
1434 (pCtlMode[ctlMode] & EXT_ADDITIVE)));
1435
1436 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i];
1437 i++) {
1438
1439 ARN_DBG((ARN_DBG_EEPROM, "arn: "
1440 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
1441 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
1442 "chan %d\n",
1443 i, cfgCtl, pCtlMode[ctlMode],
1444 pEepData->ctlIndex[i], chan->channel));
1445
1446 if ((((cfgCtl & ~CTL_MODE_M) |
1447 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
1448 pEepData->ctlIndex[i]) ||
1449 (((cfgCtl & ~CTL_MODE_M) |
1450 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
1451 ((pEepData->ctlIndex[i] & CTL_MODE_M) |
1452 SD_NO_CTL))) {
1453 rep = &(pEepData->ctlData[i]);
1454
1455 twiceMinEdgePower =
1456 ath9k_hw_get_max_edge_power(freq,
1457 rep->ctlEdges[ar5416_get_ntxchains
1458 (tx_chainmask) - 1],
1459 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
1460
1461 ARN_DBG((ARN_DBG_EEPROM, "arn: "
1462 "MATCH-EE_IDX %d: ch %d is2 %d "
1463 "2xMinEdge %d chainmask %d chains %d\n",
1464 i, freq, IS_CHAN_2GHZ(chan),
1465 twiceMinEdgePower, tx_chainmask,
1466 ar5416_get_ntxchains(tx_chainmask)));
1467
1468 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
1469 twiceMaxEdgePower =
1470 min(twiceMaxEdgePower,
1471 twiceMinEdgePower);
1472 } else {
1473 twiceMaxEdgePower = twiceMinEdgePower;
1474 break;
1475 }
1476 }
1477 }
1478
1479 minCtlPower = min(twiceMaxEdgePower, scaledPower);
1480
1481 ARN_DBG((ARN_DBG_EEPROM, "arn: "
1482 "SEL-Min ctlMode %d pCtlMode %d "
1483 "2xMaxEdge %d sP %d minCtlPwr %d\n",
1484 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
1485 scaledPower, minCtlPower));
1486
1487 switch (pCtlMode[ctlMode]) {
1488 case CTL_11B:
1489 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
1490 i++) {
1491 targetPowerCck.tPow2x[i] =
1492 min((uint16_t)targetPowerCck.tPow2x[i],
1493 minCtlPower);
1494 }
1495 break;
1496 case CTL_11A:
1497 case CTL_11G:
1498 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
1499 i++) {
1500 targetPowerOfdm.tPow2x[i] =
1501 min((uint16_t)targetPowerOfdm.tPow2x[i],
1502 minCtlPower);
1503 }
1504 break;
1505 case CTL_5GHT20:
1506 case CTL_2GHT20:
1507 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
1508 i++) {
1509 targetPowerHt20.tPow2x[i] =
1510 min((uint16_t)targetPowerHt20.tPow2x[i],
1511 minCtlPower);
1512 }
1513 break;
1514 case CTL_11B_EXT:
1515 targetPowerCckExt.tPow2x[0] =
1516 min((uint16_t)targetPowerCckExt.tPow2x[0],
1517 minCtlPower);
1518 break;
1519 case CTL_11A_EXT:
1520 case CTL_11G_EXT:
1521 targetPowerOfdmExt.tPow2x[0] =
1522 min((uint16_t)targetPowerOfdmExt.tPow2x[0],
1523 minCtlPower);
1524 break;
1525 case CTL_5GHT40:
1526 case CTL_2GHT40:
1527 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
1528 i++) {
1529 targetPowerHt40.tPow2x[i] =
1530 min((uint16_t)targetPowerHt40.tPow2x[i],
1531 minCtlPower);
1532 }
1533 break;
1534 default:
1535 break;
1536 }
1537 }
1538
1539 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
1540 ratesArray[rate18mb] = ratesArray[rate24mb] =
1541 targetPowerOfdm.tPow2x[0];
1542 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
1543 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
1544 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
1545 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
1546
1547 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
1548 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
1549
1550 if (IS_CHAN_2GHZ(chan)) {
1551 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
1552 ratesArray[rate2s] = ratesArray[rate2l] =
1553 targetPowerCck.tPow2x[1];
1554 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
1555 targetPowerCck.tPow2x[2];
1556 ;
1557 ratesArray[rate11s] = ratesArray[rate11l] =
1558 targetPowerCck.tPow2x[3];
1559 ;
1560 }
1561 if (IS_CHAN_HT40(chan)) {
1562 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
1563 ratesArray[rateHt40_0 + i] =
1564 targetPowerHt40.tPow2x[i];
1565 }
1566 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
1567 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
1568 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
1569 if (IS_CHAN_2GHZ(chan)) {
1570 ratesArray[rateExtCck] =
1571 targetPowerCckExt.tPow2x[0];
1572 }
1573 }
1574 return (B_TRUE);
1575 }
1576
1577 static boolean_t
1578 ath9k_hw_set_4k_power_per_rate_table(struct ath_hal *ah,
1579 struct ath9k_channel *chan,
1580 int16_t *ratesArray,
1581 uint16_t cfgCtl,
1582 uint16_t AntennaReduction,
1583 uint16_t twiceMaxRegulatoryPower,
1584 uint16_t powerLimit)
1585 {
1586 struct ath_hal_5416 *ahp = AH5416(ah);
1587 struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
1588 uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
1589 static const uint16_t tpScaleReductionTable[5] =
1590 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
1591
1592 int i;
1593 int16_t twiceLargestAntenna;
1594 struct cal_ctl_data_4k *rep;
1595 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
1596 0, { 0, 0, 0, 0}
1597 };
1598 struct cal_target_power_leg targetPowerOfdmExt = {
1599 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
1600 0, { 0, 0, 0, 0 }
1601 };
1602 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
1603 0, {0, 0, 0, 0}
1604 };
1605 uint16_t scaledPower = 0, minCtlPower, maxRegAllowedPower;
1606 uint16_t ctlModesFor11g[] =
1607 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
1608 CTL_2GHT40
1609 };
1610 uint16_t numCtlModes, *pCtlMode, ctlMode, freq;
1611 struct chan_centers centers;
1612 int tx_chainmask;
1613 uint16_t twiceMinEdgePower;
1614
1615 tx_chainmask = ahp->ah_txchainmask;
1616
1617 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
1618
1619 twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
1620
1621 twiceLargestAntenna =
1622 (int16_t)min(AntennaReduction - twiceLargestAntenna, 0);
1623
1624 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
1625
1626 if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
1627 maxRegAllowedPower -=
1628 (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
1629 }
1630
1631 scaledPower = min(powerLimit, maxRegAllowedPower);
1632 scaledPower = max((uint16_t)0, scaledPower);
1633
1634 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
1635 pCtlMode = ctlModesFor11g;
1636
1637 ath9k_hw_get_legacy_target_powers(ah, chan,
1638 pEepData->calTargetPowerCck,
1639 AR5416_NUM_2G_CCK_TARGET_POWERS,
1640 &targetPowerCck, 4, B_FALSE);
1641 ath9k_hw_get_legacy_target_powers(ah, chan,
1642 pEepData->calTargetPower2G,
1643 AR5416_NUM_2G_20_TARGET_POWERS,
1644 &targetPowerOfdm, 4, B_FALSE);
1645 ath9k_hw_get_target_powers(ah, chan,
1646 pEepData->calTargetPower2GHT20,
1647 AR5416_NUM_2G_20_TARGET_POWERS,
1648 &targetPowerHt20, 8, B_FALSE);
1649
1650 if (IS_CHAN_HT40(chan)) {
1651 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
1652 ath9k_hw_get_target_powers(ah, chan,
1653 pEepData->calTargetPower2GHT40,
1654 AR5416_NUM_2G_40_TARGET_POWERS,
1655 &targetPowerHt40, 8, B_TRUE);
1656 ath9k_hw_get_legacy_target_powers(ah, chan,
1657 pEepData->calTargetPowerCck,
1658 AR5416_NUM_2G_CCK_TARGET_POWERS,
1659 &targetPowerCckExt, 4, B_TRUE);
1660 ath9k_hw_get_legacy_target_powers(ah, chan,
1661 pEepData->calTargetPower2G,
1662 AR5416_NUM_2G_20_TARGET_POWERS,
1663 &targetPowerOfdmExt, 4, B_TRUE);
1664 }
1665
1666 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
1667 boolean_t isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
1668 (pCtlMode[ctlMode] == CTL_2GHT40);
1669 if (isHt40CtlMode)
1670 freq = centers.synth_center;
1671 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
1672 freq = centers.ext_center;
1673 else
1674 freq = centers.ctl_center;
1675
1676 if (ar5416_get_eep_ver(ahp) == 14 &&
1677 ar5416_get_eep_rev(ahp) <= 2)
1678 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
1679
1680 ARN_DBG((ARN_DBG_POWER_MGMT,
1681 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
1682 "EXT_ADDITIVE %d\n",
1683 ctlMode, numCtlModes, isHt40CtlMode,
1684 (pCtlMode[ctlMode] & EXT_ADDITIVE)));
1685
1686 for (i = 0; (i < AR5416_NUM_CTLS) &&
1687 pEepData->ctlIndex[i]; i++) {
1688 ARN_DBG((ARN_DBG_POWER_MGMT,
1689 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
1690 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
1691 "chan %d\n",
1692 i, cfgCtl, pCtlMode[ctlMode],
1693 pEepData->ctlIndex[i], chan->channel));
1694
1695 if ((((cfgCtl & ~CTL_MODE_M) |
1696 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
1697 pEepData->ctlIndex[i]) ||
1698 (((cfgCtl & ~CTL_MODE_M) |
1699 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
1700 ((pEepData->ctlIndex[i] & CTL_MODE_M) |
1701 SD_NO_CTL))) {
1702 rep = &(pEepData->ctlData[i]);
1703
1704 twiceMinEdgePower =
1705 ath9k_hw_get_max_edge_power(freq,
1706 rep->ctlEdges[ar5416_get_ntxchains
1707 (tx_chainmask) - 1],
1708 IS_CHAN_2GHZ(chan),
1709 AR5416_EEP4K_NUM_BAND_EDGES);
1710
1711 ARN_DBG((ARN_DBG_POWER_MGMT,
1712 " MATCH-EE_IDX %d: ch %d is2 %d "
1713 "2xMinEdge %d chainmask %d chains %d\n",
1714 i, freq, IS_CHAN_2GHZ(chan),
1715 twiceMinEdgePower, tx_chainmask,
1716 ar5416_get_ntxchains
1717 (tx_chainmask)));
1718 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
1719 twiceMaxEdgePower =
1720 min(twiceMaxEdgePower,
1721 twiceMinEdgePower);
1722 } else {
1723 twiceMaxEdgePower = twiceMinEdgePower;
1724 break;
1725 }
1726 }
1727 }
1728
1729 minCtlPower = (uint8_t)min(twiceMaxEdgePower, scaledPower);
1730
1731 ARN_DBG((ARN_DBG_POWER_MGMT,
1732 " SEL-Min ctlMode %d pCtlMode %d "
1733 "2xMaxEdge %d sP %d minCtlPwr %d\n",
1734 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
1735 scaledPower, minCtlPower));
1736
1737 switch (pCtlMode[ctlMode]) {
1738 case CTL_11B:
1739 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
1740 i++) {
1741 targetPowerCck.tPow2x[i] =
1742 min((uint16_t)targetPowerCck.tPow2x[i],
1743 minCtlPower);
1744 }
1745 break;
1746 case CTL_11G:
1747 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
1748 i++) {
1749 targetPowerOfdm.tPow2x[i] =
1750 min((uint16_t)targetPowerOfdm.tPow2x[i],
1751 minCtlPower);
1752 }
1753 break;
1754 case CTL_2GHT20:
1755 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
1756 i++) {
1757 targetPowerHt20.tPow2x[i] =
1758 min((uint16_t)targetPowerHt20.tPow2x[i],
1759 minCtlPower);
1760 }
1761 break;
1762 case CTL_11B_EXT:
1763 targetPowerCckExt.tPow2x[0] = min((uint16_t)
1764 targetPowerCckExt.tPow2x[0],
1765 minCtlPower);
1766 break;
1767 case CTL_11G_EXT:
1768 targetPowerOfdmExt.tPow2x[0] = min((uint16_t)
1769 targetPowerOfdmExt.tPow2x[0],
1770 minCtlPower);
1771 break;
1772 case CTL_2GHT40:
1773 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
1774 i++) {
1775 targetPowerHt40.tPow2x[i] =
1776 min((uint16_t)targetPowerHt40.tPow2x[i],
1777 minCtlPower);
1778 }
1779 break;
1780 default:
1781 break;
1782 }
1783 }
1784
1785 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
1786 ratesArray[rate18mb] = ratesArray[rate24mb] =
1787 targetPowerOfdm.tPow2x[0];
1788 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
1789 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
1790 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
1791 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
1792
1793 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
1794 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
1795
1796 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
1797 ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
1798 ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
1799 ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
1800
1801 if (IS_CHAN_HT40(chan)) {
1802 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
1803 ratesArray[rateHt40_0 + i] =
1804 targetPowerHt40.tPow2x[i];
1805 }
1806 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
1807 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
1808 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
1809 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
1810 }
1811 return (B_TRUE);
1812 }
1813
1814 static int
1815 ath9k_hw_def_set_txpower(struct ath_hal *ah, struct ath9k_channel *chan,
1816 uint16_t cfgCtl, uint8_t twiceAntennaReduction,
1817 uint8_t twiceMaxRegulatoryPower, uint8_t powerLimit)
1818 {
1819 struct ath_hal_5416 *ahp = AH5416(ah);
1820 struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
1821 struct modal_eep_header *pModal =
1822 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
1823 int16_t ratesArray[Ar5416RateSize];
1824 int16_t txPowerIndexOffset = 0;
1825 uint8_t ht40PowerIncForPdadc = 2;
1826 int i;
1827
1828 (void) memset(ratesArray, 0, sizeof (ratesArray));
1829
1830 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1831 AR5416_EEP_MINOR_VER_2) {
1832 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
1833 }
1834
1835 if (!ath9k_hw_set_def_power_per_rate_table(ah, chan,
1836 &ratesArray[0], cfgCtl,
1837 twiceAntennaReduction,
1838 twiceMaxRegulatoryPower,
1839 powerLimit)) {
1840
1841 ARN_DBG((ARN_DBG_EEPROM,
1842 "ath9k_hw_set_txpower: unable to set "
1843 "tx power per rate table\n"));
1844
1845 return (EIO);
1846 }
1847
1848 if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) {
1849 ARN_DBG((ARN_DBG_EEPROM, "ath9k: "
1850 "ath9k_hw_set_txpower: unable to set power table\n"));
1851 return (EIO);
1852 }
1853
1854 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
1855 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
1856 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
1857 ratesArray[i] = AR5416_MAX_RATE_POWER;
1858 }
1859
1860 if (AR_SREV_9280_10_OR_LATER(ah)) {
1861 for (i = 0; i < Ar5416RateSize; i++)
1862 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
1863 }
1864
1865 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
1866 ATH9K_POW_SM(ratesArray[rate18mb], 24) |
1867 ATH9K_POW_SM(ratesArray[rate12mb], 16) |
1868 ATH9K_POW_SM(ratesArray[rate9mb], 8) |
1869 ATH9K_POW_SM(ratesArray[rate6mb], 0));
1870 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
1871 ATH9K_POW_SM(ratesArray[rate54mb], 24) |
1872 ATH9K_POW_SM(ratesArray[rate48mb], 16) |
1873 ATH9K_POW_SM(ratesArray[rate36mb], 8) |
1874 ATH9K_POW_SM(ratesArray[rate24mb], 0));
1875
1876 if (IS_CHAN_2GHZ(chan)) {
1877 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
1878 ATH9K_POW_SM(ratesArray[rate2s], 24) |
1879 ATH9K_POW_SM(ratesArray[rate2l], 16) |
1880 ATH9K_POW_SM(ratesArray[rateXr], 8) |
1881 ATH9K_POW_SM(ratesArray[rate1l], 0));
1882 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
1883 ATH9K_POW_SM(ratesArray[rate11s], 24) |
1884 ATH9K_POW_SM(ratesArray[rate11l], 16) |
1885 ATH9K_POW_SM(ratesArray[rate5_5s], 8) |
1886 ATH9K_POW_SM(ratesArray[rate5_5l], 0));
1887 }
1888
1889 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
1890 ATH9K_POW_SM(ratesArray[rateHt20_3], 24) |
1891 ATH9K_POW_SM(ratesArray[rateHt20_2], 16) |
1892 ATH9K_POW_SM(ratesArray[rateHt20_1], 8) |
1893 ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
1894 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
1895 ATH9K_POW_SM(ratesArray[rateHt20_7], 24) |
1896 ATH9K_POW_SM(ratesArray[rateHt20_6], 16) |
1897 ATH9K_POW_SM(ratesArray[rateHt20_5], 8) |
1898 ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
1899
1900 if (IS_CHAN_HT40(chan)) {
1901 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
1902 ATH9K_POW_SM(ratesArray[rateHt40_3] +
1903 ht40PowerIncForPdadc, 24) |
1904 ATH9K_POW_SM(ratesArray[rateHt40_2] +
1905 ht40PowerIncForPdadc, 16) |
1906 ATH9K_POW_SM(ratesArray[rateHt40_1] +
1907 ht40PowerIncForPdadc, 8) |
1908 ATH9K_POW_SM(ratesArray[rateHt40_0] +
1909 ht40PowerIncForPdadc, 0));
1910 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
1911 ATH9K_POW_SM(ratesArray[rateHt40_7] +
1912 ht40PowerIncForPdadc, 24) |
1913 ATH9K_POW_SM(ratesArray[rateHt40_6] +
1914 ht40PowerIncForPdadc, 16) |
1915 ATH9K_POW_SM(ratesArray[rateHt40_5] +
1916 ht40PowerIncForPdadc, 8) |
1917 ATH9K_POW_SM(ratesArray[rateHt40_4] +
1918 ht40PowerIncForPdadc, 0));
1919
1920 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
1921 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
1922 ATH9K_POW_SM(ratesArray[rateExtCck], 16) |
1923 ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
1924 ATH9K_POW_SM(ratesArray[rateDupCck], 0));
1925 }
1926
1927 REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
1928 ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) |
1929 ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
1930
1931 i = rate6mb;
1932
1933 if (IS_CHAN_HT40(chan))
1934 i = rateHt40_0;
1935 else if (IS_CHAN_HT20(chan))
1936 i = rateHt20_0;
1937
1938 if (AR_SREV_9280_10_OR_LATER(ah))
1939 ah->ah_maxPowerLevel =
1940 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
1941 else
1942 ah->ah_maxPowerLevel = ratesArray[i];
1943
1944 return (0);
1945 }
1946
1947 static int
1948 ath9k_hw_4k_set_txpower(struct ath_hal *ah,
1949 struct ath9k_channel *chan,
1950 uint16_t cfgCtl,
1951 uint8_t twiceAntennaReduction,
1952 uint8_t twiceMaxRegulatoryPower,
1953 uint8_t powerLimit)
1954 {
1955 struct ath_hal_5416 *ahp = AH5416(ah);
1956 struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
1957 struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
1958 int16_t ratesArray[Ar5416RateSize];
1959 int16_t txPowerIndexOffset = 0;
1960 uint8_t ht40PowerIncForPdadc = 2;
1961 int i;
1962
1963 (void) memset(ratesArray, 0, sizeof (ratesArray));
1964
1965 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1966 AR5416_EEP_MINOR_VER_2) {
1967 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
1968 }
1969
1970 if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan,
1971 &ratesArray[0], cfgCtl,
1972 twiceAntennaReduction,
1973 twiceMaxRegulatoryPower,
1974 powerLimit)) {
1975 ARN_DBG((ARN_DBG_EEPROM,
1976 "ath9k_hw_set_txpower: unable to set "
1977 "tx power per rate table\n"));
1978 return (EIO);
1979 }
1980
1981 if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) {
1982 ARN_DBG((ARN_DBG_EEPROM,
1983 "ath9k_hw_set_txpower: unable to set power table\n"));
1984 return (EIO);
1985 }
1986
1987 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
1988 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
1989 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
1990 ratesArray[i] = AR5416_MAX_RATE_POWER;
1991 }
1992
1993 if (AR_SREV_9280_10_OR_LATER(ah)) {
1994 for (i = 0; i < Ar5416RateSize; i++)
1995 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
1996 }
1997
1998 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
1999 ATH9K_POW_SM(ratesArray[rate18mb], 24) |
2000 ATH9K_POW_SM(ratesArray[rate12mb], 16) |
2001 ATH9K_POW_SM(ratesArray[rate9mb], 8) |
2002 ATH9K_POW_SM(ratesArray[rate6mb], 0));
2003 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
2004 ATH9K_POW_SM(ratesArray[rate54mb], 24) |
2005 ATH9K_POW_SM(ratesArray[rate48mb], 16) |
2006 ATH9K_POW_SM(ratesArray[rate36mb], 8) |
2007 ATH9K_POW_SM(ratesArray[rate24mb], 0));
2008
2009 if (IS_CHAN_2GHZ(chan)) {
2010 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2011 ATH9K_POW_SM(ratesArray[rate2s], 24) |
2012 ATH9K_POW_SM(ratesArray[rate2l], 16) |
2013 ATH9K_POW_SM(ratesArray[rateXr], 8) |
2014 ATH9K_POW_SM(ratesArray[rate1l], 0));
2015 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2016 ATH9K_POW_SM(ratesArray[rate11s], 24) |
2017 ATH9K_POW_SM(ratesArray[rate11l], 16) |
2018 ATH9K_POW_SM(ratesArray[rate5_5s], 8) |
2019 ATH9K_POW_SM(ratesArray[rate5_5l], 0));
2020 }
2021
2022 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
2023 ATH9K_POW_SM(ratesArray[rateHt20_3], 24) |
2024 ATH9K_POW_SM(ratesArray[rateHt20_2], 16) |
2025 ATH9K_POW_SM(ratesArray[rateHt20_1], 8) |
2026 ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
2027 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
2028 ATH9K_POW_SM(ratesArray[rateHt20_7], 24) |
2029 ATH9K_POW_SM(ratesArray[rateHt20_6], 16) |
2030 ATH9K_POW_SM(ratesArray[rateHt20_5], 8) |
2031 ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
2032
2033 if (IS_CHAN_HT40(chan)) {
2034 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
2035 ATH9K_POW_SM(ratesArray[rateHt40_3] +
2036 ht40PowerIncForPdadc, 24) |
2037 ATH9K_POW_SM(ratesArray[rateHt40_2] +
2038 ht40PowerIncForPdadc, 16) |
2039 ATH9K_POW_SM(ratesArray[rateHt40_1] +
2040 ht40PowerIncForPdadc, 8) |
2041 ATH9K_POW_SM(ratesArray[rateHt40_0] +
2042 ht40PowerIncForPdadc, 0));
2043
2044 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
2045 ATH9K_POW_SM(ratesArray[rateHt40_7] +
2046 ht40PowerIncForPdadc, 24) |
2047 ATH9K_POW_SM(ratesArray[rateHt40_6] +
2048 ht40PowerIncForPdadc, 16) |
2049 ATH9K_POW_SM(ratesArray[rateHt40_5] +
2050 ht40PowerIncForPdadc, 8) |
2051 ATH9K_POW_SM(ratesArray[rateHt40_4] +
2052 ht40PowerIncForPdadc, 0));
2053
2054 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2055 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
2056 ATH9K_POW_SM(ratesArray[rateExtCck], 16) |
2057 ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
2058 ATH9K_POW_SM(ratesArray[rateDupCck], 0));
2059 }
2060
2061 i = rate6mb;
2062
2063 if (IS_CHAN_HT40(chan))
2064 i = rateHt40_0;
2065 else if (IS_CHAN_HT20(chan))
2066 i = rateHt20_0;
2067
2068 if (AR_SREV_9280_10_OR_LATER(ah))
2069 ah->ah_maxPowerLevel =
2070 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
2071 else
2072 ah->ah_maxPowerLevel = ratesArray[i];
2073
2074 return (0);
2075 }
2076
2077 int
2078 ath9k_hw_set_txpower(struct ath_hal *ah,
2079 struct ath9k_channel *chan,
2080 uint16_t cfgCtl,
2081 uint8_t twiceAntennaReduction,
2082 uint8_t twiceMaxRegulatoryPower,
2083 uint8_t powerLimit)
2084 {
2085 struct ath_hal_5416 *ahp = AH5416(ah);
2086 int val;
2087
2088 if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
2089 val = ath9k_hw_def_set_txpower(ah, chan, cfgCtl,
2090 twiceAntennaReduction, twiceMaxRegulatoryPower,
2091 powerLimit);
2092 else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
2093 val = ath9k_hw_4k_set_txpower(ah, chan, cfgCtl,
2094 twiceAntennaReduction, twiceMaxRegulatoryPower,
2095 powerLimit);
2096 return (val);
2097 }
2098
2099 static void
2100 ath9k_hw_set_def_addac(struct ath_hal *ah, struct ath9k_channel *chan)
2101 {
2102 #define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
2103 struct modal_eep_header *pModal;
2104 struct ath_hal_5416 *ahp = AH5416(ah);
2105 struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
2106 uint8_t biaslevel;
2107
2108 if (ah->ah_macVersion != AR_SREV_VERSION_9160)
2109 return;
2110
2111 if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
2112 return;
2113
2114 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
2115
2116 if (pModal->xpaBiasLvl != 0xff) {
2117 biaslevel = pModal->xpaBiasLvl;
2118 } else {
2119 uint16_t resetFreqBin, freqBin, freqCount = 0;
2120 struct chan_centers centers;
2121
2122 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
2123
2124 resetFreqBin =
2125 FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan));
2126 freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
2127 biaslevel = (uint8_t)(XPA_LVL_FREQ(0) >> 14);
2128
2129 freqCount++;
2130
2131 while (freqCount < 3) {
2132 if (XPA_LVL_FREQ(freqCount) == 0x0)
2133 break;
2134
2135 freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
2136 if (resetFreqBin >= freqBin) {
2137 biaslevel =
2138 (uint8_t)
2139 (XPA_LVL_FREQ(freqCount) >> 14);
2140 } else {
2141 break;
2142 }
2143 freqCount++;
2144 }
2145 }
2146
2147 if (IS_CHAN_2GHZ(chan)) {
2148 INI_RA(&ahp->ah_iniAddac, 7, 1) =
2149 (INI_RA(&ahp->ah_iniAddac, 7, 1) &
2150 (~0x18)) | biaslevel << 3;
2151 } else {
2152 INI_RA(&ahp->ah_iniAddac, 6, 1) =
2153 (INI_RA(&ahp->ah_iniAddac, 6, 1) &
2154 (~0xc0)) | biaslevel << 6;
2155 }
2156 #undef XPA_LVL_FREQ
2157 }
2158
2159 /* ARGSUSED */
2160 static void
2161 ath9k_hw_set_4k_addac(struct ath_hal *ah, struct ath9k_channel *chan)
2162 {
2163 struct modal_eep_4k_header *pModal;
2164 struct ath_hal_5416 *ahp = AH5416(ah);
2165 struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
2166 uint8_t biaslevel;
2167
2168 if (ah->ah_macVersion != AR_SREV_VERSION_9160)
2169 return;
2170
2171 if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
2172 return;
2173
2174 pModal = &eep->modalHeader;
2175
2176 if (pModal->xpaBiasLvl != 0xff) {
2177 biaslevel = pModal->xpaBiasLvl;
2178 INI_RA(&ahp->ah_iniAddac, 7, 1) =
2179 (INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) |
2180 biaslevel << 3;
2181 }
2182 }
2183
2184 void
2185 ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan)
2186 {
2187 struct ath_hal_5416 *ahp = AH5416(ah);
2188
2189 if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
2190 ath9k_hw_set_def_addac(ah, chan);
2191 else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
2192 ath9k_hw_set_4k_addac(ah, chan);
2193 }
2194
2195 /* XXX: Clean me up, make me more legible */
2196 static boolean_t
2197 ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
2198 struct ath9k_channel *chan)
2199 {
2200 struct modal_eep_header *pModal;
2201 struct ath_hal_5416 *ahp = AH5416(ah);
2202 struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
2203 int i, regChainOffset;
2204 uint8_t txRxAttenLocal;
2205 uint16_t ant_config;
2206
2207 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
2208
2209 txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
2210
2211 (void) ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
2212 REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
2213
2214 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
2215 if (AR_SREV_9280(ah)) {
2216 if (i >= 2)
2217 break;
2218 }
2219
2220 if (AR_SREV_5416_V20_OR_LATER(ah) &&
2221 (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
2222 (i != 0))
2223 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
2224 else
2225 regChainOffset = i * 0x1000;
2226
2227 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
2228 pModal->antCtrlChain[i]);
2229
2230 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
2231 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
2232 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
2233 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
2234 SM(pModal->iqCalICh[i],
2235 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
2236 SM(pModal->iqCalQCh[i],
2237 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
2238
2239 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
2240 if ((eep->baseEepHeader.version &
2241 AR5416_EEP_VER_MINOR_MASK) >=
2242 AR5416_EEP_MINOR_VER_3) {
2243 txRxAttenLocal = pModal->txRxAttenCh[i];
2244 if (AR_SREV_9280_10_OR_LATER(ah)) {
2245 REG_RMW_FIELD(ah,
2246 AR_PHY_GAIN_2GHZ +
2247 regChainOffset,
2248 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
2249 pModal->
2250 bswMargin[i]);
2251 REG_RMW_FIELD(ah,
2252 AR_PHY_GAIN_2GHZ +
2253 regChainOffset,
2254 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
2255 pModal->
2256 bswAtten[i]);
2257 REG_RMW_FIELD(ah,
2258 AR_PHY_GAIN_2GHZ +
2259 regChainOffset,
2260 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
2261 pModal->
2262 xatten2Margin[i]);
2263 REG_RMW_FIELD(ah,
2264 AR_PHY_GAIN_2GHZ +
2265 regChainOffset,
2266 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
2267 pModal->
2268 xatten2Db[i]);
2269 } else {
2270 REG_WRITE(ah,
2271 AR_PHY_GAIN_2GHZ +
2272 regChainOffset,
2273 (REG_READ(ah,
2274 AR_PHY_GAIN_2GHZ +
2275 regChainOffset) &
2276 ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
2277 | SM(pModal->
2278 bswMargin[i],
2279 AR_PHY_GAIN_2GHZ_BSW_MARGIN));
2280 REG_WRITE(ah,
2281 AR_PHY_GAIN_2GHZ +
2282 regChainOffset,
2283 (REG_READ(ah,
2284 AR_PHY_GAIN_2GHZ +
2285 regChainOffset) &
2286 ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
2287 | SM(pModal->bswAtten[i],
2288 AR_PHY_GAIN_2GHZ_BSW_ATTEN));
2289 }
2290 }
2291 if (AR_SREV_9280_10_OR_LATER(ah)) {
2292 REG_RMW_FIELD(ah,
2293 AR_PHY_RXGAIN +
2294 regChainOffset,
2295 AR9280_PHY_RXGAIN_TXRX_ATTEN,
2296 txRxAttenLocal);
2297 REG_RMW_FIELD(ah,
2298 AR_PHY_RXGAIN +
2299 regChainOffset,
2300 AR9280_PHY_RXGAIN_TXRX_MARGIN,
2301 pModal->rxTxMarginCh[i]);
2302 } else {
2303 REG_WRITE(ah,
2304 AR_PHY_RXGAIN + regChainOffset,
2305 (REG_READ(ah,
2306 AR_PHY_RXGAIN +
2307 regChainOffset) &
2308 ~AR_PHY_RXGAIN_TXRX_ATTEN) |
2309 SM(txRxAttenLocal,
2310 AR_PHY_RXGAIN_TXRX_ATTEN));
2311 REG_WRITE(ah,
2312 AR_PHY_GAIN_2GHZ +
2313 regChainOffset,
2314 (REG_READ(ah,
2315 AR_PHY_GAIN_2GHZ +
2316 regChainOffset) &
2317 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
2318 SM(pModal->rxTxMarginCh[i],
2319 AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
2320 }
2321 }
2322 }
2323
2324 if (AR_SREV_9280_10_OR_LATER(ah)) {
2325 if (IS_CHAN_2GHZ(chan)) {
2326 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
2327 AR_AN_RF2G1_CH0_OB,
2328 AR_AN_RF2G1_CH0_OB_S,
2329 pModal->ob);
2330 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
2331 AR_AN_RF2G1_CH0_DB,
2332 AR_AN_RF2G1_CH0_DB_S,
2333 pModal->db);
2334 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
2335 AR_AN_RF2G1_CH1_OB,
2336 AR_AN_RF2G1_CH1_OB_S,
2337 pModal->ob_ch1);
2338 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
2339 AR_AN_RF2G1_CH1_DB,
2340 AR_AN_RF2G1_CH1_DB_S,
2341 pModal->db_ch1);
2342 } else {
2343 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
2344 AR_AN_RF5G1_CH0_OB5,
2345 AR_AN_RF5G1_CH0_OB5_S,
2346 pModal->ob);
2347 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
2348 AR_AN_RF5G1_CH0_DB5,
2349 AR_AN_RF5G1_CH0_DB5_S,
2350 pModal->db);
2351 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
2352 AR_AN_RF5G1_CH1_OB5,
2353 AR_AN_RF5G1_CH1_OB5_S,
2354 pModal->ob_ch1);
2355 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
2356 AR_AN_RF5G1_CH1_DB5,
2357 AR_AN_RF5G1_CH1_DB5_S,
2358 pModal->db_ch1);
2359 }
2360 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
2361 AR_AN_TOP2_XPABIAS_LVL,
2362 AR_AN_TOP2_XPABIAS_LVL_S,
2363 pModal->xpaBiasLvl);
2364 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
2365 AR_AN_TOP2_LOCALBIAS,
2366 AR_AN_TOP2_LOCALBIAS_S,
2367 pModal->local_bias);
2368
2369 ARN_DBG((ARN_DBG_EEPROM, "arn: "
2370 "ForceXPAon: %d\n", pModal->force_xpaon));
2371
2372 REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
2373 pModal->force_xpaon);
2374 }
2375
2376 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
2377 pModal->switchSettling);
2378 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
2379 pModal->adcDesiredSize);
2380
2381 if (!AR_SREV_9280_10_OR_LATER(ah))
2382 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
2383 AR_PHY_DESIRED_SZ_PGA,
2384 pModal->pgaDesiredSize);
2385
2386 REG_WRITE(ah, AR_PHY_RF_CTL4,
2387 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
2388 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
2389 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
2390 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
2391
2392 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
2393 pModal->txEndToRxOn);
2394 if (AR_SREV_9280_10_OR_LATER(ah)) {
2395 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
2396 pModal->thresh62);
2397 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
2398 AR_PHY_EXT_CCA0_THRESH62,
2399 pModal->thresh62);
2400 } else {
2401 REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
2402 pModal->thresh62);
2403 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
2404 AR_PHY_EXT_CCA_THRESH62,
2405 pModal->thresh62);
2406 }
2407
2408 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2409 AR5416_EEP_MINOR_VER_2) {
2410 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
2411 AR_PHY_TX_END_DATA_START,
2412 pModal->txFrameToDataStart);
2413 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
2414 pModal->txFrameToPaOn);
2415 }
2416
2417 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2418 AR5416_EEP_MINOR_VER_3) {
2419 if (IS_CHAN_HT40(chan))
2420 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
2421 AR_PHY_SETTLING_SWITCH,
2422 pModal->swSettleHt40);
2423 }
2424
2425 return (B_TRUE);
2426 }
2427
2428 static boolean_t
2429 ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
2430 struct ath9k_channel *chan)
2431 {
2432 struct modal_eep_4k_header *pModal;
2433 struct ath_hal_5416 *ahp = AH5416(ah);
2434 struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
2435 int regChainOffset;
2436 uint8_t txRxAttenLocal;
2437 uint16_t ant_config = 0;
2438 uint8_t ob[5], db1[5], db2[5];
2439 uint8_t ant_div_control1, ant_div_control2;
2440 uint32_t regVal;
2441
2442
2443 pModal = &eep->modalHeader;
2444
2445 txRxAttenLocal = 23;
2446
2447 (void) ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
2448 REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
2449
2450 regChainOffset = 0;
2451 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
2452 pModal->antCtrlChain[0]);
2453
2454 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
2455 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
2456 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
2457 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
2458 SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
2459 SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
2460
2461 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2462 AR5416_EEP_MINOR_VER_3) {
2463 txRxAttenLocal = pModal->txRxAttenCh[0];
2464 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
2465 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
2466 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
2467 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
2468 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
2469 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
2470 pModal->xatten2Margin[0]);
2471 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
2472 AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
2473 }
2474
2475 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
2476 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
2477 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
2478 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
2479
2480 if (AR_SREV_9285_11(ah))
2481 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
2482
2483 /* Initialize Ant Diversity settings from EEPROM */
2484 if (pModal->version == 3) {
2485 ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
2486 ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
2487 regVal = REG_READ(ah, 0x99ac);
2488 regVal &= (~(0x7f000000));
2489 regVal |= ((ant_div_control1 & 0x1) << 24);
2490 regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
2491 regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
2492 regVal |= ((ant_div_control2 & 0x3) << 25);
2493 regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
2494 REG_WRITE(ah, 0x99ac, regVal);
2495 regVal = REG_READ(ah, 0x99ac);
2496 regVal = REG_READ(ah, 0xa208);
2497 regVal &= (~(0x1 << 13));
2498 regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
2499 REG_WRITE(ah, 0xa208, regVal);
2500 regVal = REG_READ(ah, 0xa208);
2501 }
2502
2503 if (pModal->version >= 2) {
2504 ob[0] = (pModal->ob_01 & 0xf);
2505 ob[1] = (pModal->ob_01 >> 4) & 0xf;
2506 ob[2] = (pModal->ob_234 & 0xf);
2507 ob[3] = ((pModal->ob_234 >> 4) & 0xf);
2508 ob[4] = ((pModal->ob_234 >> 8) & 0xf);
2509
2510 db1[0] = (pModal->db1_01 & 0xf);
2511 db1[1] = ((pModal->db1_01 >> 4) & 0xf);
2512 db1[2] = (pModal->db1_234 & 0xf);
2513 db1[3] = ((pModal->db1_234 >> 4) & 0xf);
2514 db1[4] = ((pModal->db1_234 >> 8) & 0xf);
2515
2516 db2[0] = (pModal->db2_01 & 0xf);
2517 db2[1] = ((pModal->db2_01 >> 4) & 0xf);
2518 db2[2] = (pModal->db2_234 & 0xf);
2519 db2[3] = ((pModal->db2_234 >> 4) & 0xf);
2520 db2[4] = ((pModal->db2_234 >> 8) & 0xf);
2521
2522 } else if (pModal->version == 1) {
2523
2524 ARN_DBG((ARN_DBG_EEPROM,
2525 "EEPROM Model version is set to 1 \n"));
2526 ob[0] = (pModal->ob_01 & 0xf);
2527 ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
2528 db1[0] = (pModal->db1_01 & 0xf);
2529 db1[1] = db1[2] = db1[3] = db1[4] =
2530 ((pModal->db1_01 >> 4) & 0xf);
2531 db2[0] = (pModal->db2_01 & 0xf);
2532 db2[1] = db2[2] = db2[3] = db2[4] =
2533 ((pModal->db2_01 >> 4) & 0xf);
2534 } else {
2535 int i;
2536 for (i = 0; i < 5; i++) {
2537 ob[i] = pModal->ob_01;
2538 db1[i] = pModal->db1_01;
2539 db2[i] = pModal->db1_01;
2540 }
2541 }
2542
2543 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
2544 AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
2545 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
2546 AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
2547 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
2548 AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
2549 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
2550 AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
2551 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
2552 AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
2553
2554 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
2555 AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
2556 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
2557 AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
2558 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
2559 AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
2560 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
2561 AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
2562 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
2563 AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
2564
2565 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
2566 AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
2567 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
2568 AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
2569 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
2570 AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
2571 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
2572 AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
2573 ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
2574 AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
2575
2576
2577 if (AR_SREV_9285_11(ah))
2578 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
2579
2580 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
2581 pModal->switchSettling);
2582 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
2583 pModal->adcDesiredSize);
2584
2585 REG_WRITE(ah, AR_PHY_RF_CTL4,
2586 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
2587 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
2588 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
2589 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
2590
2591 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
2592 pModal->txEndToRxOn);
2593 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
2594 pModal->thresh62);
2595 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
2596 pModal->thresh62);
2597
2598 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2599 AR5416_EEP_MINOR_VER_2) {
2600 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
2601 pModal->txFrameToDataStart);
2602 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
2603 pModal->txFrameToPaOn);
2604 }
2605
2606 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2607 AR5416_EEP_MINOR_VER_3) {
2608 if (IS_CHAN_HT40(chan))
2609 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
2610 AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
2611 }
2612
2613 return (B_TRUE);
2614 }
2615
2616 boolean_t
2617 ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, struct ath9k_channel *chan)
2618 {
2619 struct ath_hal_5416 *ahp = AH5416(ah);
2620 boolean_t val;
2621
2622 if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
2623 val = ath9k_hw_eeprom_set_def_board_values(ah, chan);
2624 else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
2625 val = ath9k_hw_eeprom_set_4k_board_values(ah, chan);
2626
2627 return (val);
2628 }
2629
2630 static int
2631 ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah,
2632 struct ath9k_channel *chan,
2633 uint8_t index, uint16_t *config)
2634 {
2635 struct ath_hal_5416 *ahp = AH5416(ah);
2636 struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
2637 struct modal_eep_header *pModal =
2638 &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
2639 struct base_eep_header *pBase = &eep->baseEepHeader;
2640
2641 switch (index) {
2642 case 0:
2643 *config = pModal->antCtrlCommon & 0xFFFF;
2644 return (0);
2645 case 1:
2646 if (pBase->version >= 0x0E0D) {
2647 if (pModal->useAnt1) {
2648 *config =
2649 ((pModal->antCtrlCommon & 0xFFFF0000)
2650 >> 16);
2651 return (0);
2652 }
2653 }
2654 break;
2655 default:
2656 break;
2657 }
2658
2659 return (-EINVAL);
2660 }
2661
2662 /* ARGSUSED */
2663 static int
2664 ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah,
2665 struct ath9k_channel *chan,
2666 uint8_t index, uint16_t *config)
2667 {
2668 struct ath_hal_5416 *ahp = AH5416(ah);
2669 struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
2670 struct modal_eep_4k_header *pModal = &eep->modalHeader;
2671
2672 switch (index) {
2673 case 0:
2674 *config = pModal->antCtrlCommon & 0xFFFF;
2675 return (0);
2676 default:
2677 break;
2678 }
2679
2680 return (EINVAL);
2681 }
2682
2683 int
2684 ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
2685 struct ath9k_channel *chan,
2686 uint8_t index, uint16_t *config)
2687 {
2688 struct ath_hal_5416 *ahp = AH5416(ah);
2689 int val;
2690
2691 if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
2692 val = ath9k_hw_get_def_eeprom_antenna_cfg(ah, chan,
2693 index, config);
2694 else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
2695 val = ath9k_hw_get_4k_eeprom_antenna_cfg(ah, chan,
2696 index, config);
2697
2698 return (val);
2699 }
2700
2701 /* ARGSUSED */
2702 static uint8_t
2703 ath9k_hw_get_4k_num_ant_config(struct ath_hal *ah,
2704 enum ath9k_band freq_band)
2705 {
2706 return (1);
2707 }
2708
2709 static uint8_t
2710 ath9k_hw_get_def_num_ant_config(struct ath_hal *ah,
2711 enum ath9k_band freq_band)
2712 {
2713 struct ath_hal_5416 *ahp = AH5416(ah);
2714 struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
2715
2716 struct modal_eep_header *pModal =
2717 &(eep->modalHeader[ATH9K_BAND_5GHZ == freq_band]);
2718 struct base_eep_header *pBase = &eep->baseEepHeader;
2719 uint8_t num_ant_config;
2720
2721 num_ant_config = 1;
2722
2723 if (pBase->version >= 0x0E0D)
2724 if (pModal->useAnt1)
2725 num_ant_config += 1;
2726
2727 return (num_ant_config);
2728 }
2729
2730 uint8_t
2731 ath9k_hw_get_num_ant_config(struct ath_hal *ah,
2732 enum ath9k_band freq_band)
2733 {
2734 struct ath_hal_5416 *ahp = AH5416(ah);
2735 uint8_t val;
2736
2737 if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
2738 val = ath9k_hw_get_def_num_ant_config(ah, freq_band);
2739 else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
2740 val = ath9k_hw_get_4k_num_ant_config(ah, freq_band);
2741
2742 return (val);
2743 }
2744
2745 uint16_t
2746 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, uint16_t i, boolean_t is2GHz)
2747 {
2748 #define EEP_MAP4K_SPURCHAN \
2749 (ahp->ah_eeprom.map4k.modalHeader.spurChans[i].spurChan)
2750 #define EEP_DEF_SPURCHAN \
2751 (ahp->ah_eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
2752
2753 struct ath_hal_5416 *ahp = AH5416(ah);
2754 uint16_t spur_val = AR_NO_SPUR;
2755
2756 ARN_DBG((ARN_DBG_ANI, "arn: "
2757 "Getting spur idx %d is2Ghz. %d val %x\n",
2758 i, is2GHz, ah->ah_config.spurchans[i][is2GHz]));
2759
2760 switch (ah->ah_config.spurmode) {
2761 case SPUR_DISABLE:
2762 break;
2763 case SPUR_ENABLE_IOCTL:
2764 spur_val = ah->ah_config.spurchans[i][is2GHz];
2765 ARN_DBG((ARN_DBG_ANI, "arn: "
2766 "Getting spur val from new loc. %d\n", spur_val));
2767 break;
2768 case SPUR_ENABLE_EEPROM:
2769 if (ahp->ah_eep_map == EEP_MAP_4KBITS)
2770 spur_val = EEP_MAP4K_SPURCHAN;
2771 else
2772 spur_val = EEP_DEF_SPURCHAN;
2773 break;
2774
2775 }
2776
2777 return (spur_val);
2778 #undef EEP_DEF_SPURCHAN
2779 #undef EEP_MAP4K_SPURCHAN
2780 }
2781
2782 static uint32_t
2783 ath9k_hw_get_eeprom_4k(struct ath_hal *ah,
2784 enum eeprom_param param)
2785 {
2786 struct ath_hal_5416 *ahp = AH5416(ah);
2787 struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
2788 struct modal_eep_4k_header *pModal = &eep->modalHeader;
2789 struct base_eep_header_4k *pBase = &eep->baseEepHeader;
2790
2791 switch (param) {
2792 case EEP_NFTHRESH_2:
2793 return (pModal[1].noiseFloorThreshCh[0]);
2794 case AR_EEPROM_MAC(0):
2795 return (pBase->macAddr[0] << 8 | pBase->macAddr[1]);
2796 case AR_EEPROM_MAC(1):
2797 return (pBase->macAddr[2] << 8 | pBase->macAddr[3]);
2798 case AR_EEPROM_MAC(2):
2799 return (pBase->macAddr[4] << 8 | pBase->macAddr[5]);
2800 case EEP_REG_0:
2801 return (pBase->regDmn[0]);
2802 case EEP_REG_1:
2803 return (pBase->regDmn[1]);
2804 case EEP_OP_CAP:
2805 return (pBase->deviceCap);
2806 case EEP_OP_MODE:
2807 return (pBase->opCapFlags);
2808 case EEP_RF_SILENT:
2809 return (pBase->rfSilent);
2810 case EEP_OB_2:
2811 return (pModal->ob_01);
2812 case EEP_DB_2:
2813 return (pModal->db1_01);
2814 case EEP_MINOR_REV:
2815 return (pBase->version & AR5416_EEP_VER_MINOR_MASK);
2816 case EEP_TX_MASK:
2817 return (pBase->txMask);
2818 case EEP_RX_MASK:
2819 return (pBase->rxMask);
2820 /* 2.6.30 */
2821 case EEP_FRAC_N_5G:
2822 return (0);
2823 default:
2824 return (0);
2825 }
2826 }
2827
2828 uint32_t
2829 ath9k_hw_get_eeprom_def(struct ath_hal *ah, enum eeprom_param param)
2830 {
2831 struct ath_hal_5416 *ahp = AH5416(ah);
2832 struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
2833 struct modal_eep_header *pModal = eep->modalHeader;
2834 struct base_eep_header *pBase = &eep->baseEepHeader;
2835
2836 switch (param) {
2837 case EEP_NFTHRESH_5:
2838 return (pModal[0].noiseFloorThreshCh[0]);
2839 case EEP_NFTHRESH_2:
2840 return (pModal[1].noiseFloorThreshCh[0]);
2841 case AR_EEPROM_MAC(0):
2842 return (pBase->macAddr[0] << 8 | pBase->macAddr[1]);
2843 case AR_EEPROM_MAC(1):
2844 return (pBase->macAddr[2] << 8 | pBase->macAddr[3]);
2845 case AR_EEPROM_MAC(2):
2846 return (pBase->macAddr[4] << 8 | pBase->macAddr[5]);
2847 case EEP_REG_0:
2848 return (pBase->regDmn[0]);
2849 case EEP_REG_1:
2850 return (pBase->regDmn[1]);
2851 case EEP_OP_CAP:
2852 return (pBase->deviceCap);
2853 case EEP_OP_MODE:
2854 return (pBase->opCapFlags);
2855 case EEP_RF_SILENT:
2856 return (pBase->rfSilent);
2857 case EEP_OB_5:
2858 return (pModal[0].ob);
2859 case EEP_DB_5:
2860 return (pModal[0].db);
2861 case EEP_OB_2:
2862 return (pModal[1].ob);
2863 case EEP_DB_2:
2864 return (pModal[1].db);
2865 case EEP_MINOR_REV:
2866 return (pBase->version & AR5416_EEP_VER_MINOR_MASK);
2867 case EEP_TX_MASK:
2868 return (pBase->txMask);
2869 case EEP_RX_MASK:
2870 return (pBase->rxMask);
2871 case EEP_RXGAIN_TYPE:
2872 return (pBase->rxGainType);
2873 case EEP_TXGAIN_TYPE:
2874 return (pBase->txGainType);
2875 /* 2.6.30 */
2876 case EEP_OL_PWRCTRL:
2877 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
2878 return (pBase->openLoopPwrCntl ? B_TRUE: B_FALSE);
2879 else
2880 return (B_FALSE);
2881 case EEP_RC_CHAIN_MASK:
2882 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
2883 return (pBase->rcChainMask);
2884 else
2885 return (0);
2886 case EEP_DAC_HPWR_5G:
2887 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
2888 return (pBase->dacHiPwrMode_5G);
2889 else
2890 return (0);
2891 case EEP_FRAC_N_5G:
2892 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
2893 return (pBase->frac_n_5g);
2894 else
2895 return (0);
2896
2897 default:
2898 return (0);
2899 }
2900 }
2901
2902 uint32_t
2903 ath9k_hw_get_eeprom(struct ath_hal *ah, enum eeprom_param param)
2904 {
2905 struct ath_hal_5416 *ahp = AH5416(ah);
2906 uint32_t val;
2907
2908 if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
2909 val = ath9k_hw_get_eeprom_def(ah, param);
2910 else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
2911 val = ath9k_hw_get_eeprom_4k(ah, param);
2912
2913 return (val);
2914 }
2915
2916 int
2917 ath9k_hw_eeprom_attach(struct ath_hal *ah)
2918 {
2919 int status;
2920 struct ath_hal_5416 *ahp = AH5416(ah);
2921
2922 if (ath9k_hw_use_flash(ah))
2923 (void) ath9k_hw_flash_map(ah);
2924
2925 if (AR_SREV_9285(ah))
2926 ahp->ah_eep_map = EEP_MAP_4KBITS;
2927 else
2928 ahp->ah_eep_map = EEP_MAP_DEFAULT;
2929
2930 if (!ath9k_hw_fill_eeprom(ah))
2931 return (EIO);
2932
2933 status = ath9k_hw_check_eeprom(ah);
2934
2935 return (status);
2936 }
--- EOF ---