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