2 * Copyright (c) 2010 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include "ar9003_phy.h"
19 #include "ar9003_eeprom.h"
21 #define COMP_HDR_LEN 4
22 #define COMP_CKSUM_LEN 2
24 #define AR_CH0_TOP (0x00016288)
25 #define AR_CH0_TOP_XPABIASLVL (0x3)
26 #define AR_CH0_TOP_XPABIASLVL_S (8)
28 #define AR_CH0_THERM (0x00016290)
29 #define AR_CH0_THERM_SPARE (0x3f)
30 #define AR_CH0_THERM_SPARE_S (0)
32 #define AR_SWITCH_TABLE_COM_ALL (0xffff)
33 #define AR_SWITCH_TABLE_COM_ALL_S (0)
35 #define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
36 #define AR_SWITCH_TABLE_COM2_ALL_S (0)
38 #define AR_SWITCH_TABLE_ALL (0xfff)
39 #define AR_SWITCH_TABLE_ALL_S (0)
41 static const struct ar9300_eeprom ar9300_default = {
44 .macAddr = {1, 2, 3, 4, 5, 6},
45 .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
49 .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
51 .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
55 .blueToothOptions = 0,
57 .deviceType = 5, /* takes lower byte in eeprom location */
58 .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
59 .params_for_tuning_caps = {0, 0},
60 .featureEnable = 0x0c,
62 * bit0 - enable tx temp comp - disabled
63 * bit1 - enable tx volt comp - disabled
64 * bit2 - enable fastClock - enabled
65 * bit3 - enable doubling - enabled
66 * bit4 - enable internal regulator - disabled
68 .miscConfiguration = 0, /* bit0 - turn down drivestrength */
69 .eepromWriteEnableGpio = 3,
72 .rxBandSelectGpio = 0xff,
77 /* ar9300_modal_eep_header 2g */
78 /* 4 idle,t1,t2,b(4 bits per setting) */
79 .antCtrlCommon = 0x110,
80 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
81 .antCtrlCommon2 = 0x22222,
84 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
85 * rx1, rx12, b (2 bits each)
87 .antCtrlChain = {0x150, 0x150, 0x150},
90 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
91 * for ar9280 (0xa20c/b20c 5:0)
93 .xatten1DB = {0, 0, 0},
96 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
97 * for ar9280 (0xa20c/b20c 16:12
99 .xatten1Margin = {0, 0, 0},
104 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
105 * channels in usual fbin coding format
107 .spurChans = {0, 0, 0, 0, 0},
110 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
111 * if the register is per chain
113 .noiseFloorThreshCh = {-1, 0, 0},
114 .ob = {1, 1, 1},/* 3 chain */
115 .db_stage2 = {1, 1, 1}, /* 3 chain */
116 .db_stage3 = {0, 0, 0},
117 .db_stage4 = {0, 0, 0},
119 .txFrameToDataStart = 0x0e,
120 .txFrameToPaOn = 0x0e,
121 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
123 .switchSettling = 0x2c,
124 .adcDesiredSize = -30,
127 .txFrameToXpaOn = 0xe,
129 .futureModal = { /* [32] */
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
139 /* ar9300_cal_data_per_freq_op_loop 2g */
141 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
142 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
143 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
145 .calTarget_freqbin_Cck = {
149 .calTarget_freqbin_2G = {
154 .calTarget_freqbin_2GHT20 = {
159 .calTarget_freqbin_2GHT40 = {
164 .calTargetPowerCck = {
165 /* 1L-5L,5S,11L,11S */
166 { {36, 36, 36, 36} },
167 { {36, 36, 36, 36} },
169 .calTargetPower2G = {
171 { {32, 32, 28, 24} },
172 { {32, 32, 28, 24} },
173 { {32, 32, 28, 24} },
175 .calTargetPower2GHT20 = {
176 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
177 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
178 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
180 .calTargetPower2GHT40 = {
181 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
182 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
183 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
186 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
187 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
217 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
218 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
219 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
220 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
224 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
225 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
226 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
231 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
232 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
238 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
239 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
240 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
241 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
245 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
246 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
247 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
251 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
252 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
253 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
258 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
259 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
260 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
265 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
266 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
267 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
268 /* Data[11].ctlEdges[3].bChannel */
273 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
274 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
275 { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
277 { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
278 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
279 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
281 { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
282 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
283 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
285 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
286 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
289 /* 4 idle,t1,t2,b (4 bits per setting) */
290 .antCtrlCommon = 0x110,
291 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
292 .antCtrlCommon2 = 0x22222,
293 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
297 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
298 .xatten1DB = {0, 0, 0},
301 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
302 * for merlin (0xa20c/b20c 16:12
304 .xatten1Margin = {0, 0, 0},
307 /* spurChans spur channels in usual fbin coding format */
308 .spurChans = {0, 0, 0, 0, 0},
309 /* noiseFloorThreshCh Check if the register is per chain */
310 .noiseFloorThreshCh = {-1, 0, 0},
311 .ob = {3, 3, 3}, /* 3 chain */
312 .db_stage2 = {3, 3, 3}, /* 3 chain */
313 .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
314 .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
316 .txFrameToDataStart = 0x0e,
317 .txFrameToPaOn = 0x0e,
318 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
320 .switchSettling = 0x2d,
321 .adcDesiredSize = -30,
324 .txFrameToXpaOn = 0xe,
327 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
374 .calTarget_freqbin_5G = {
384 .calTarget_freqbin_5GHT20 = {
394 .calTarget_freqbin_5GHT40 = {
404 .calTargetPower5G = {
406 { {20, 20, 20, 10} },
407 { {20, 20, 20, 10} },
408 { {20, 20, 20, 10} },
409 { {20, 20, 20, 10} },
410 { {20, 20, 20, 10} },
411 { {20, 20, 20, 10} },
412 { {20, 20, 20, 10} },
413 { {20, 20, 20, 10} },
415 .calTargetPower5GHT20 = {
417 * 0_8_16,1-3_9-11_17-19,
418 * 4,5,6,7,12,13,14,15,20,21,22,23
420 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
421 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
422 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
423 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
424 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
425 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
426 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
427 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
429 .calTargetPower5GHT40 = {
431 * 0_8_16,1-3_9-11_17-19,
432 * 4,5,6,7,12,13,14,15,20,21,22,23
434 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
435 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
436 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
437 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
438 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
439 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
440 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
441 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
444 0x10, 0x16, 0x18, 0x40, 0x46,
445 0x48, 0x30, 0x36, 0x38
449 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
450 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
451 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
452 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
453 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
454 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
455 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
456 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
459 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
460 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
461 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
462 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
463 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
464 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
465 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
466 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
470 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
471 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
472 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
473 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
474 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
475 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
476 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
477 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
481 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
482 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
483 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
484 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
485 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
486 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
487 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
488 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
492 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
493 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
494 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
495 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
496 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
497 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
498 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
499 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
503 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
504 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
505 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
506 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
507 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
508 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
509 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
510 /* Data[5].ctlEdges[7].bChannel */ 0xFF
514 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
515 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
516 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
517 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
518 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
519 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
520 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
521 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
525 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
526 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
527 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
528 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
529 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
530 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
531 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
532 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
536 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
537 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
538 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
539 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
540 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
541 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
542 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
543 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
549 {60, 1}, {60, 1}, {60, 1}, {60, 1},
550 {60, 1}, {60, 1}, {60, 1}, {60, 0},
555 {60, 1}, {60, 1}, {60, 1}, {60, 1},
556 {60, 1}, {60, 1}, {60, 1}, {60, 0},
561 {60, 0}, {60, 1}, {60, 0}, {60, 1},
562 {60, 1}, {60, 1}, {60, 1}, {60, 1},
567 {60, 0}, {60, 1}, {60, 1}, {60, 0},
568 {60, 1}, {60, 0}, {60, 0}, {60, 0},
573 {60, 1}, {60, 1}, {60, 1}, {60, 0},
574 {60, 0}, {60, 0}, {60, 0}, {60, 0},
579 {60, 1}, {60, 1}, {60, 1}, {60, 1},
580 {60, 1}, {60, 0}, {60, 0}, {60, 0},
585 {60, 1}, {60, 1}, {60, 1}, {60, 1},
586 {60, 1}, {60, 1}, {60, 1}, {60, 1},
591 {60, 1}, {60, 1}, {60, 0}, {60, 1},
592 {60, 1}, {60, 1}, {60, 1}, {60, 0},
597 {60, 1}, {60, 0}, {60, 1}, {60, 1},
598 {60, 1}, {60, 1}, {60, 0}, {60, 1},
604 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
609 static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
610 enum eeprom_param param)
612 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
613 struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
617 return eep->macAddr[0] << 8 | eep->macAddr[1];
619 return eep->macAddr[2] << 8 | eep->macAddr[3];
621 return eep->macAddr[4] << 8 | eep->macAddr[5];
623 return pBase->regDmn[0];
625 return pBase->regDmn[1];
627 return pBase->deviceCap;
629 return pBase->opCapFlags.opFlags;
631 return pBase->rfSilent;
633 return (pBase->txrxMask >> 4) & 0xf;
635 return pBase->txrxMask & 0xf;
636 case EEP_DRIVE_STRENGTH:
637 #define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
638 return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
639 case EEP_INTERNAL_REGULATOR:
640 /* Bit 4 is internal regulator flag */
641 return (pBase->featureEnable & 0x10) >> 4;
650 static void ar9300_swap_eeprom(struct ar9300_eeprom *eep)
656 word = swab16(eep->baseEepHeader.regDmn[0]);
657 eep->baseEepHeader.regDmn[0] = word;
659 word = swab16(eep->baseEepHeader.regDmn[1]);
660 eep->baseEepHeader.regDmn[1] = word;
662 dword = swab32(eep->baseEepHeader.swreg);
663 eep->baseEepHeader.swreg = dword;
665 dword = swab32(eep->modalHeader2G.antCtrlCommon);
666 eep->modalHeader2G.antCtrlCommon = dword;
668 dword = swab32(eep->modalHeader2G.antCtrlCommon2);
669 eep->modalHeader2G.antCtrlCommon2 = dword;
671 dword = swab32(eep->modalHeader5G.antCtrlCommon);
672 eep->modalHeader5G.antCtrlCommon = dword;
674 dword = swab32(eep->modalHeader5G.antCtrlCommon2);
675 eep->modalHeader5G.antCtrlCommon2 = dword;
677 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
678 word = swab16(eep->modalHeader2G.antCtrlChain[i]);
679 eep->modalHeader2G.antCtrlChain[i] = word;
681 word = swab16(eep->modalHeader5G.antCtrlChain[i]);
682 eep->modalHeader5G.antCtrlChain[i] = word;
687 static bool ar9300_hw_read_eeprom(struct ath_hw *ah,
688 long address, u8 *buffer, int many)
692 unsigned long eepAddr;
693 unsigned long byteAddr;
695 struct ath_common *common = ath9k_hw_common(ah);
697 if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) {
698 ath_print(common, ATH_DBG_EEPROM,
699 "eeprom address not in range\n");
703 for (i = 0; i < many; i++) {
704 eepAddr = (u16) (address + i) / 2;
705 byteAddr = (u16) (address + i) % 2;
706 svalue = (u16 *) value;
707 if (!ath9k_hw_nvram_read(common, eepAddr, svalue)) {
708 ath_print(common, ATH_DBG_EEPROM,
709 "unable to read eeprom region\n");
712 *svalue = le16_to_cpu(*svalue);
713 buffer[i] = value[byteAddr];
719 static bool ar9300_read_eeprom(struct ath_hw *ah,
720 int address, u8 *buffer, int many)
724 for (it = 0; it < many; it++)
725 if (!ar9300_hw_read_eeprom(ah,
732 static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
733 int *length, int *major, int *minor)
735 unsigned long value[4];
741 *code = ((value[0] >> 5) & 0x0007);
742 *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
743 *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
744 *major = (value[2] & 0x000f);
745 *minor = (value[3] & 0x00ff);
748 static u16 ar9300_comp_cksum(u8 *data, int dsize)
750 int it, checksum = 0;
752 for (it = 0; it < dsize; it++) {
753 checksum += data[it];
760 static bool ar9300_uncompress_block(struct ath_hw *ah,
770 struct ath_common *common = ath9k_hw_common(ah);
774 for (it = 0; it < size; it += (length+2)) {
778 length = block[it+1];
781 if (length > 0 && spot >= 0 && spot+length < mdataSize) {
782 ath_print(common, ATH_DBG_EEPROM,
783 "Restore at %d: spot=%d "
784 "offset=%d length=%d\n",
785 it, spot, offset, length);
786 memcpy(&mptr[spot], &block[it+2], length);
788 } else if (length > 0) {
789 ath_print(common, ATH_DBG_EEPROM,
790 "Bad restore at %d: spot=%d "
791 "offset=%d length=%d\n",
792 it, spot, offset, length);
799 static int ar9300_compress_decision(struct ath_hw *ah,
804 u8 *word, int length, int mdata_size)
806 struct ath_common *common = ath9k_hw_common(ah);
811 if (length != mdata_size) {
812 ath_print(common, ATH_DBG_EEPROM,
813 "EEPROM structure size mismatch"
814 "memory=%d eeprom=%d\n", mdata_size, length);
817 memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
818 ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:"
819 " uncompressed, length %d\n", it, length);
822 if (reference == 0) {
825 if (reference != 2) {
826 ath_print(common, ATH_DBG_EEPROM,
827 "cant find reference eeprom"
828 "struct %d\n", reference);
831 memcpy(mptr, &ar9300_default, mdata_size);
833 ath_print(common, ATH_DBG_EEPROM,
834 "restore eeprom %d: block, reference %d,"
835 " length %d\n", it, reference, length);
836 ar9300_uncompress_block(ah, mptr, mdata_size,
837 (u8 *) (word + COMP_HDR_LEN), length);
840 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
848 * Read the configuration data from the eeprom.
849 * The data can be put in any specified memory buffer.
851 * Returns -1 on error.
852 * Returns address of next memory location on success.
854 static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
855 u8 *mptr, int mdata_size)
862 int reference, length, major, minor;
865 u16 checksum, mchecksum;
866 struct ath_common *common = ath9k_hw_common(ah);
868 word = kzalloc(2048, GFP_KERNEL);
872 memcpy(mptr, &ar9300_default, mdata_size);
874 cptr = AR9300_BASE_ADDR;
875 for (it = 0; it < MSTATE; it++) {
876 if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
879 if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
880 word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
881 && word[2] == 0xff && word[3] == 0xff))
884 ar9300_comp_hdr_unpack(word, &code, &reference,
885 &length, &major, &minor);
886 ath_print(common, ATH_DBG_EEPROM,
887 "Found block at %x: code=%d ref=%d"
888 "length=%d major=%d minor=%d\n", cptr, code,
889 reference, length, major, minor);
890 if (length >= 1024) {
891 ath_print(common, ATH_DBG_EEPROM,
892 "Skipping bad header\n");
893 cptr -= COMP_HDR_LEN;
898 ar9300_read_eeprom(ah, cptr, word,
899 COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
900 checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
901 mchecksum = word[COMP_HDR_LEN + osize] |
902 (word[COMP_HDR_LEN + osize + 1] << 8);
903 ath_print(common, ATH_DBG_EEPROM,
904 "checksum %x %x\n", checksum, mchecksum);
905 if (checksum == mchecksum) {
906 ar9300_compress_decision(ah, it, code, reference, mptr,
907 word, length, mdata_size);
909 ath_print(common, ATH_DBG_EEPROM,
910 "skipping block with bad checksum\n");
912 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
924 * Restore the configuration structure by reading the eeprom.
925 * This function destroys any existing in-memory structure
928 static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
933 mptr = (u8 *) &ah->eeprom.ar9300_eep;
934 mdata_size = sizeof(struct ar9300_eeprom);
936 if (mptr && mdata_size > 0) {
937 /* At this point, mptr points to the eeprom data structure
938 * in it's "default" state. If this is big endian, swap the
939 * data structures back to "little endian"
941 /* First swap, default to Little Endian */
943 ar9300_swap_eeprom((struct ar9300_eeprom *)mptr);
945 if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0)
948 /* Second Swap, back to Big Endian */
950 ar9300_swap_eeprom((struct ar9300_eeprom *)mptr);
956 /* XXX: review hardware docs */
957 static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
959 return ah->eeprom.ar9300_eep.eepromVersion;
962 /* XXX: could be read from the eepromVersion, not sure yet */
963 static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
968 static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
969 enum ieee80211_band freq_band)
974 static u16 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
975 struct ath9k_channel *chan)
980 static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
982 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
985 return eep->modalHeader2G.xpaBiasLvl;
987 return eep->modalHeader5G.xpaBiasLvl;
990 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
992 int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
993 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3));
994 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE,
995 ((bias >> 2) & 0x3));
998 static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
1000 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1003 return eep->modalHeader2G.antCtrlCommon;
1005 return eep->modalHeader5G.antCtrlCommon;
1008 static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
1010 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1013 return eep->modalHeader2G.antCtrlCommon2;
1015 return eep->modalHeader5G.antCtrlCommon2;
1018 static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1022 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1024 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1026 return eep->modalHeader2G.antCtrlChain[chain];
1028 return eep->modalHeader5G.antCtrlChain[chain];
1034 static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1036 u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
1037 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
1039 value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
1040 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1042 value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
1043 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1045 value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
1046 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1048 value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
1049 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1052 static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1057 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1059 if (!drive_strength)
1062 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1070 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1072 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1083 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1085 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1090 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1093 static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1095 int internal_regulator =
1096 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1098 if (internal_regulator) {
1099 /* Internal regulator is ON. Write swreg register. */
1100 int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
1101 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1102 REG_READ(ah, AR_RTC_REG_CONTROL1) &
1103 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1104 REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1105 /* Set REG_CONTROL1.SWREG_PROGRAM */
1106 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1108 AR_RTC_REG_CONTROL1) |
1109 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1111 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1114 AR_RTC_FORCE_SWREG_PRD));
1118 static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1119 struct ath9k_channel *chan)
1121 ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
1122 ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
1123 ar9003_hw_drive_strength_apply(ah);
1124 ar9003_hw_internal_regulator_apply(ah);
1127 static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1128 struct ath9k_channel *chan)
1133 * Returns the interpolated y value corresponding to the specified x value
1134 * from the np ordered pairs of data (px,py).
1135 * The pairs do not have to be in any order.
1136 * If the specified x value is less than any of the px,
1137 * the returned y value is equal to the py for the lowest px.
1138 * If the specified x value is greater than any of the px,
1139 * the returned y value is equal to the py for the highest px.
1141 static int ar9003_hw_power_interpolate(int32_t x,
1142 int32_t *px, int32_t *py, u_int16_t np)
1145 int lx = 0, ly = 0, lhave = 0;
1146 int hx = 0, hy = 0, hhave = 0;
1153 /* identify best lower and higher x calibration measurement */
1154 for (ip = 0; ip < np; ip++) {
1157 /* this measurement is higher than our desired x */
1159 if (!hhave || dx > (x - hx)) {
1160 /* new best higher x measurement */
1166 /* this measurement is lower than our desired x */
1168 if (!lhave || dx < (x - lx)) {
1169 /* new best lower x measurement */
1177 /* the low x is good */
1179 /* so is the high x */
1181 /* they're the same, so just pick one */
1184 else /* interpolate */
1185 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1186 } else /* only low is good, use it */
1188 } else if (hhave) /* only high is good, use it */
1190 else /* nothing is good,this should never happen unless np=0, ???? */
1195 static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1196 u16 rateIndex, u16 freq, bool is2GHz)
1199 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1200 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1201 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1202 struct cal_tgt_pow_legacy *pEepromTargetPwr;
1206 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1207 pEepromTargetPwr = eep->calTargetPower2G;
1208 pFreqBin = eep->calTarget_freqbin_2G;
1210 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1211 pEepromTargetPwr = eep->calTargetPower5G;
1212 pFreqBin = eep->calTarget_freqbin_5G;
1216 * create array of channels and targetpower from
1217 * targetpower piers stored on eeprom
1219 for (i = 0; i < numPiers; i++) {
1220 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1221 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1224 /* interpolate to get target power for given frequency */
1225 return (u8) ar9003_hw_power_interpolate((s32) freq,
1227 targetPowerArray, numPiers);
1230 static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1232 u16 freq, bool is2GHz)
1235 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1236 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1237 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1238 struct cal_tgt_pow_ht *pEepromTargetPwr;
1242 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1243 pEepromTargetPwr = eep->calTargetPower2GHT20;
1244 pFreqBin = eep->calTarget_freqbin_2GHT20;
1246 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1247 pEepromTargetPwr = eep->calTargetPower5GHT20;
1248 pFreqBin = eep->calTarget_freqbin_5GHT20;
1252 * create array of channels and targetpower
1253 * from targetpower piers stored on eeprom
1255 for (i = 0; i < numPiers; i++) {
1256 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1257 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1260 /* interpolate to get target power for given frequency */
1261 return (u8) ar9003_hw_power_interpolate((s32) freq,
1263 targetPowerArray, numPiers);
1266 static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1268 u16 freq, bool is2GHz)
1271 s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
1272 s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
1273 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1274 struct cal_tgt_pow_ht *pEepromTargetPwr;
1278 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1279 pEepromTargetPwr = eep->calTargetPower2GHT40;
1280 pFreqBin = eep->calTarget_freqbin_2GHT40;
1282 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1283 pEepromTargetPwr = eep->calTargetPower5GHT40;
1284 pFreqBin = eep->calTarget_freqbin_5GHT40;
1288 * create array of channels and targetpower from
1289 * targetpower piers stored on eeprom
1291 for (i = 0; i < numPiers; i++) {
1292 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1293 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1296 /* interpolate to get target power for given frequency */
1297 return (u8) ar9003_hw_power_interpolate((s32) freq,
1299 targetPowerArray, numPiers);
1302 static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1303 u16 rateIndex, u16 freq)
1305 u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
1306 s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1307 s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1308 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1309 struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
1310 u8 *pFreqBin = eep->calTarget_freqbin_Cck;
1313 * create array of channels and targetpower from
1314 * targetpower piers stored on eeprom
1316 for (i = 0; i < numPiers; i++) {
1317 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1318 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1321 /* interpolate to get target power for given frequency */
1322 return (u8) ar9003_hw_power_interpolate((s32) freq,
1324 targetPowerArray, numPiers);
1327 /* Set tx power registers to array of values passed in */
1328 static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1330 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1331 /* make sure forced gain is not set */
1332 REG_WRITE(ah, 0xa458, 0);
1334 /* Write the OFDM power per rate set */
1336 /* 6 (LSB), 9, 12, 18 (MSB) */
1337 REG_WRITE(ah, 0xa3c0,
1338 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
1339 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
1340 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
1341 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1343 /* 24 (LSB), 36, 48, 54 (MSB) */
1344 REG_WRITE(ah, 0xa3c4,
1345 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
1346 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
1347 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
1348 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1350 /* Write the CCK power per rate set */
1352 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1353 REG_WRITE(ah, 0xa3c8,
1354 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
1355 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
1356 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1357 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
1359 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1360 REG_WRITE(ah, 0xa3cc,
1361 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
1362 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
1363 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
1364 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
1367 /* Write the HT20 power per rate set */
1369 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1370 REG_WRITE(ah, 0xa3d0,
1371 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
1372 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
1373 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
1374 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
1377 /* 6 (LSB), 7, 12, 13 (MSB) */
1378 REG_WRITE(ah, 0xa3d4,
1379 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
1380 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
1381 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
1382 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
1385 /* 14 (LSB), 15, 20, 21 */
1386 REG_WRITE(ah, 0xa3e4,
1387 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
1388 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
1389 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
1390 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
1393 /* Mixed HT20 and HT40 rates */
1395 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1396 REG_WRITE(ah, 0xa3e8,
1397 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
1398 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
1399 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
1400 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
1404 * Write the HT40 power per rate set
1405 * correct PAR difference between HT40 and HT20/LEGACY
1406 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1408 REG_WRITE(ah, 0xa3d8,
1409 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
1410 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
1411 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
1412 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
1415 /* 6 (LSB), 7, 12, 13 (MSB) */
1416 REG_WRITE(ah, 0xa3dc,
1417 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
1418 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
1419 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
1420 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
1423 /* 14 (LSB), 15, 20, 21 */
1424 REG_WRITE(ah, 0xa3ec,
1425 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
1426 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
1427 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
1428 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
1435 static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq)
1437 u8 targetPowerValT2[ar9300RateSize];
1438 /* XXX: hard code for now, need to get from eeprom struct */
1439 u8 ht40PowerIncForPdadc = 0;
1440 bool is2GHz = false;
1442 struct ath_common *common = ath9k_hw_common(ah);
1447 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1448 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1450 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1451 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1453 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1454 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1456 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1457 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1459 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1460 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1462 targetPowerValT2[ALL_TARGET_LEGACY_5S] =
1463 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
1464 targetPowerValT2[ALL_TARGET_LEGACY_11L] =
1465 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
1466 targetPowerValT2[ALL_TARGET_LEGACY_11S] =
1467 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
1468 targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
1469 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1471 targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1472 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1474 targetPowerValT2[ALL_TARGET_HT20_4] =
1475 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1477 targetPowerValT2[ALL_TARGET_HT20_5] =
1478 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1480 targetPowerValT2[ALL_TARGET_HT20_6] =
1481 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1483 targetPowerValT2[ALL_TARGET_HT20_7] =
1484 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1486 targetPowerValT2[ALL_TARGET_HT20_12] =
1487 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1489 targetPowerValT2[ALL_TARGET_HT20_13] =
1490 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1492 targetPowerValT2[ALL_TARGET_HT20_14] =
1493 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1495 targetPowerValT2[ALL_TARGET_HT20_15] =
1496 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1498 targetPowerValT2[ALL_TARGET_HT20_20] =
1499 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1501 targetPowerValT2[ALL_TARGET_HT20_21] =
1502 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1504 targetPowerValT2[ALL_TARGET_HT20_22] =
1505 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1507 targetPowerValT2[ALL_TARGET_HT20_23] =
1508 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1510 targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
1511 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1512 is2GHz) + ht40PowerIncForPdadc;
1513 targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1514 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1516 is2GHz) + ht40PowerIncForPdadc;
1517 targetPowerValT2[ALL_TARGET_HT40_4] =
1518 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1519 is2GHz) + ht40PowerIncForPdadc;
1520 targetPowerValT2[ALL_TARGET_HT40_5] =
1521 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1522 is2GHz) + ht40PowerIncForPdadc;
1523 targetPowerValT2[ALL_TARGET_HT40_6] =
1524 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1525 is2GHz) + ht40PowerIncForPdadc;
1526 targetPowerValT2[ALL_TARGET_HT40_7] =
1527 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1528 is2GHz) + ht40PowerIncForPdadc;
1529 targetPowerValT2[ALL_TARGET_HT40_12] =
1530 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1531 is2GHz) + ht40PowerIncForPdadc;
1532 targetPowerValT2[ALL_TARGET_HT40_13] =
1533 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1534 is2GHz) + ht40PowerIncForPdadc;
1535 targetPowerValT2[ALL_TARGET_HT40_14] =
1536 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1537 is2GHz) + ht40PowerIncForPdadc;
1538 targetPowerValT2[ALL_TARGET_HT40_15] =
1539 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1540 is2GHz) + ht40PowerIncForPdadc;
1541 targetPowerValT2[ALL_TARGET_HT40_20] =
1542 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1543 is2GHz) + ht40PowerIncForPdadc;
1544 targetPowerValT2[ALL_TARGET_HT40_21] =
1545 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1546 is2GHz) + ht40PowerIncForPdadc;
1547 targetPowerValT2[ALL_TARGET_HT40_22] =
1548 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1549 is2GHz) + ht40PowerIncForPdadc;
1550 targetPowerValT2[ALL_TARGET_HT40_23] =
1551 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1552 is2GHz) + ht40PowerIncForPdadc;
1554 while (i < ar9300RateSize) {
1555 ath_print(common, ATH_DBG_EEPROM,
1556 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1559 ath_print(common, ATH_DBG_EEPROM,
1560 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1563 ath_print(common, ATH_DBG_EEPROM,
1564 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1567 ath_print(common, ATH_DBG_EEPROM,
1568 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1572 /* Write target power array to registers */
1573 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
1576 static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1582 int *ptemperature, int *pvoltage)
1585 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1587 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1588 struct ath_common *common = ath9k_hw_common(ah);
1590 if (ichain >= AR9300_MAX_CHAINS) {
1591 ath_print(common, ATH_DBG_EEPROM,
1592 "Invalid chain index, must be less than %d\n",
1597 if (mode) { /* 5GHz */
1598 if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
1599 ath_print(common, ATH_DBG_EEPROM,
1600 "Invalid 5GHz cal pier index, must "
1601 "be less than %d\n",
1602 AR9300_NUM_5G_CAL_PIERS);
1605 pCalPier = &(eep->calFreqPier5G[ipier]);
1606 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1609 if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
1610 ath_print(common, ATH_DBG_EEPROM,
1611 "Invalid 2GHz cal pier index, must "
1612 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
1616 pCalPier = &(eep->calFreqPier2G[ipier]);
1617 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1621 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1622 *pcorrection = pCalPierStruct->refPower;
1623 *ptemperature = pCalPierStruct->tempMeas;
1624 *pvoltage = pCalPierStruct->voltMeas;
1629 static int ar9003_hw_power_control_override(struct ath_hw *ah,
1632 int *voltage, int *temperature)
1635 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1637 REG_RMW(ah, AR_PHY_TPC_11_B0,
1638 (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1639 AR_PHY_TPC_OLPC_GAIN_DELTA);
1640 REG_RMW(ah, AR_PHY_TPC_11_B1,
1641 (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1642 AR_PHY_TPC_OLPC_GAIN_DELTA);
1643 REG_RMW(ah, AR_PHY_TPC_11_B2,
1644 (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1645 AR_PHY_TPC_OLPC_GAIN_DELTA);
1647 /* enable open loop power control on chip */
1648 REG_RMW(ah, AR_PHY_TPC_6_B0,
1649 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1650 AR_PHY_TPC_6_ERROR_EST_MODE);
1651 REG_RMW(ah, AR_PHY_TPC_6_B1,
1652 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1653 AR_PHY_TPC_6_ERROR_EST_MODE);
1654 REG_RMW(ah, AR_PHY_TPC_6_B2,
1655 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1656 AR_PHY_TPC_6_ERROR_EST_MODE);
1659 * enable temperature compensation
1660 * Need to use register names
1662 if (frequency < 4000)
1663 tempSlope = eep->modalHeader2G.tempSlope;
1665 tempSlope = eep->modalHeader5G.tempSlope;
1667 REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
1668 REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
1674 /* Apply the recorded correction values. */
1675 static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1677 int ichain, ipier, npier;
1679 int lfrequency[AR9300_MAX_CHAINS],
1680 lcorrection[AR9300_MAX_CHAINS],
1681 ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
1682 int hfrequency[AR9300_MAX_CHAINS],
1683 hcorrection[AR9300_MAX_CHAINS],
1684 htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
1686 int correction[AR9300_MAX_CHAINS],
1687 voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
1688 int pfrequency, pcorrection, ptemperature, pvoltage;
1689 struct ath_common *common = ath9k_hw_common(ah);
1691 mode = (frequency >= 4000);
1693 npier = AR9300_NUM_5G_CAL_PIERS;
1695 npier = AR9300_NUM_2G_CAL_PIERS;
1697 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1698 lfrequency[ichain] = 0;
1699 hfrequency[ichain] = 100000;
1701 /* identify best lower and higher frequency calibration measurement */
1702 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1703 for (ipier = 0; ipier < npier; ipier++) {
1704 if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
1705 &pfrequency, &pcorrection,
1706 &ptemperature, &pvoltage)) {
1707 fdiff = frequency - pfrequency;
1710 * this measurement is higher than
1711 * our desired frequency
1714 if (hfrequency[ichain] <= 0 ||
1715 hfrequency[ichain] >= 100000 ||
1717 (frequency - hfrequency[ichain])) {
1720 * frequency measurement
1722 hfrequency[ichain] = pfrequency;
1723 hcorrection[ichain] =
1725 htemperature[ichain] =
1727 hvoltage[ichain] = pvoltage;
1731 if (lfrequency[ichain] <= 0
1733 (frequency - lfrequency[ichain])) {
1736 * frequency measurement
1738 lfrequency[ichain] = pfrequency;
1739 lcorrection[ichain] =
1741 ltemperature[ichain] =
1743 lvoltage[ichain] = pvoltage;
1751 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1752 ath_print(common, ATH_DBG_EEPROM,
1753 "ch=%d f=%d low=%d %d h=%d %d\n",
1754 ichain, frequency, lfrequency[ichain],
1755 lcorrection[ichain], hfrequency[ichain],
1756 hcorrection[ichain]);
1757 /* they're the same, so just pick one */
1758 if (hfrequency[ichain] == lfrequency[ichain]) {
1759 correction[ichain] = lcorrection[ichain];
1760 voltage[ichain] = lvoltage[ichain];
1761 temperature[ichain] = ltemperature[ichain];
1763 /* the low frequency is good */
1764 else if (frequency - lfrequency[ichain] < 1000) {
1765 /* so is the high frequency, interpolate */
1766 if (hfrequency[ichain] - frequency < 1000) {
1768 correction[ichain] = lcorrection[ichain] +
1769 (((frequency - lfrequency[ichain]) *
1770 (hcorrection[ichain] -
1771 lcorrection[ichain])) /
1772 (hfrequency[ichain] - lfrequency[ichain]));
1774 temperature[ichain] = ltemperature[ichain] +
1775 (((frequency - lfrequency[ichain]) *
1776 (htemperature[ichain] -
1777 ltemperature[ichain])) /
1778 (hfrequency[ichain] - lfrequency[ichain]));
1783 lfrequency[ichain]) * (hvoltage[ichain] -
1785 / (hfrequency[ichain] -
1786 lfrequency[ichain]));
1788 /* only low is good, use it */
1790 correction[ichain] = lcorrection[ichain];
1791 temperature[ichain] = ltemperature[ichain];
1792 voltage[ichain] = lvoltage[ichain];
1795 /* only high is good, use it */
1796 else if (hfrequency[ichain] - frequency < 1000) {
1797 correction[ichain] = hcorrection[ichain];
1798 temperature[ichain] = htemperature[ichain];
1799 voltage[ichain] = hvoltage[ichain];
1800 } else { /* nothing is good, presume 0???? */
1801 correction[ichain] = 0;
1802 temperature[ichain] = 0;
1803 voltage[ichain] = 0;
1807 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1810 ath_print(common, ATH_DBG_EEPROM,
1811 "for frequency=%d, calibration correction = %d %d %d\n",
1812 frequency, correction[0], correction[1], correction[2]);
1817 static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
1818 struct ath9k_channel *chan, u16 cfgCtl,
1819 u8 twiceAntennaReduction,
1820 u8 twiceMaxRegulatoryPower,
1823 ah->txpower_limit = powerLimit;
1824 ar9003_hw_set_target_power_eeprom(ah, chan->channel);
1825 ar9003_hw_calibration_apply(ah, chan->channel);
1828 static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
1834 s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
1836 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1838 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
1841 s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
1843 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1845 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
1848 const struct eeprom_ops eep_ar9300_ops = {
1849 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
1850 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
1851 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
1852 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
1853 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
1854 .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
1855 .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
1856 .set_board_values = ath9k_hw_ar9300_set_board_values,
1857 .set_addac = ath9k_hw_ar9300_set_addac,
1858 .set_txpower = ath9k_hw_ar9300_set_txpower,
1859 .get_spur_channel = ath9k_hw_ar9300_get_spur_channel