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->modalHeader2G.antCtrlCommon);
663 eep->modalHeader2G.antCtrlCommon = dword;
665 dword = swab32(eep->modalHeader2G.antCtrlCommon2);
666 eep->modalHeader2G.antCtrlCommon2 = dword;
668 dword = swab32(eep->modalHeader5G.antCtrlCommon);
669 eep->modalHeader5G.antCtrlCommon = dword;
671 dword = swab32(eep->modalHeader5G.antCtrlCommon2);
672 eep->modalHeader5G.antCtrlCommon2 = dword;
674 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
675 word = swab16(eep->modalHeader2G.antCtrlChain[i]);
676 eep->modalHeader2G.antCtrlChain[i] = word;
678 word = swab16(eep->modalHeader5G.antCtrlChain[i]);
679 eep->modalHeader5G.antCtrlChain[i] = word;
684 static bool ar9300_hw_read_eeprom(struct ath_hw *ah,
685 long address, u8 *buffer, int many)
689 unsigned long eepAddr;
690 unsigned long byteAddr;
692 struct ath_common *common = ath9k_hw_common(ah);
694 if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) {
695 ath_print(common, ATH_DBG_EEPROM,
696 "eeprom address not in range\n");
700 for (i = 0; i < many; i++) {
701 eepAddr = (u16) (address + i) / 2;
702 byteAddr = (u16) (address + i) % 2;
703 svalue = (u16 *) value;
704 if (!ath9k_hw_nvram_read(common, eepAddr, svalue)) {
705 ath_print(common, ATH_DBG_EEPROM,
706 "unable to read eeprom region\n");
709 *svalue = le16_to_cpu(*svalue);
710 buffer[i] = value[byteAddr];
716 static bool ar9300_read_eeprom(struct ath_hw *ah,
717 int address, u8 *buffer, int many)
721 for (it = 0; it < many; it++)
722 if (!ar9300_hw_read_eeprom(ah,
729 static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
730 int *length, int *major, int *minor)
732 unsigned long value[4];
738 *code = ((value[0] >> 5) & 0x0007);
739 *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
740 *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
741 *major = (value[2] & 0x000f);
742 *minor = (value[3] & 0x00ff);
745 static u16 ar9300_comp_cksum(u8 *data, int dsize)
747 int it, checksum = 0;
749 for (it = 0; it < dsize; it++) {
750 checksum += data[it];
757 static bool ar9300_uncompress_block(struct ath_hw *ah,
767 struct ath_common *common = ath9k_hw_common(ah);
771 for (it = 0; it < size; it += (length+2)) {
775 length = block[it+1];
778 if (length > 0 && spot >= 0 && spot+length < mdataSize) {
779 ath_print(common, ATH_DBG_EEPROM,
780 "Restore at %d: spot=%d "
781 "offset=%d length=%d\n",
782 it, spot, offset, length);
783 memcpy(&mptr[spot], &block[it+2], length);
785 } else if (length > 0) {
786 ath_print(common, ATH_DBG_EEPROM,
787 "Bad restore at %d: spot=%d "
788 "offset=%d length=%d\n",
789 it, spot, offset, length);
796 static int ar9300_compress_decision(struct ath_hw *ah,
801 u8 *word, int length, int mdata_size)
803 struct ath_common *common = ath9k_hw_common(ah);
808 if (length != mdata_size) {
809 ath_print(common, ATH_DBG_EEPROM,
810 "EEPROM structure size mismatch"
811 "memory=%d eeprom=%d\n", mdata_size, length);
814 memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
815 ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:"
816 " uncompressed, length %d\n", it, length);
819 if (reference == 0) {
822 if (reference != 2) {
823 ath_print(common, ATH_DBG_EEPROM,
824 "cant find reference eeprom"
825 "struct %d\n", reference);
828 memcpy(mptr, &ar9300_default, mdata_size);
830 ath_print(common, ATH_DBG_EEPROM,
831 "restore eeprom %d: block, reference %d,"
832 " length %d\n", it, reference, length);
833 ar9300_uncompress_block(ah, mptr, mdata_size,
834 (u8 *) (word + COMP_HDR_LEN), length);
837 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
845 * Read the configuration data from the eeprom.
846 * The data can be put in any specified memory buffer.
848 * Returns -1 on error.
849 * Returns address of next memory location on success.
851 static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
852 u8 *mptr, int mdata_size)
859 int reference, length, major, minor;
862 u16 checksum, mchecksum;
863 struct ath_common *common = ath9k_hw_common(ah);
865 word = kzalloc(2048, GFP_KERNEL);
869 memcpy(mptr, &ar9300_default, mdata_size);
871 cptr = AR9300_BASE_ADDR;
872 for (it = 0; it < MSTATE; it++) {
873 if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
876 if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
877 word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
878 && word[2] == 0xff && word[3] == 0xff))
881 ar9300_comp_hdr_unpack(word, &code, &reference,
882 &length, &major, &minor);
883 ath_print(common, ATH_DBG_EEPROM,
884 "Found block at %x: code=%d ref=%d"
885 "length=%d major=%d minor=%d\n", cptr, code,
886 reference, length, major, minor);
887 if (length >= 1024) {
888 ath_print(common, ATH_DBG_EEPROM,
889 "Skipping bad header\n");
890 cptr -= COMP_HDR_LEN;
895 ar9300_read_eeprom(ah, cptr, word,
896 COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
897 checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
898 mchecksum = word[COMP_HDR_LEN + osize] |
899 (word[COMP_HDR_LEN + osize + 1] << 8);
900 ath_print(common, ATH_DBG_EEPROM,
901 "checksum %x %x\n", checksum, mchecksum);
902 if (checksum == mchecksum) {
903 ar9300_compress_decision(ah, it, code, reference, mptr,
904 word, length, mdata_size);
906 ath_print(common, ATH_DBG_EEPROM,
907 "skipping block with bad checksum\n");
909 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
921 * Restore the configuration structure by reading the eeprom.
922 * This function destroys any existing in-memory structure
925 static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
930 mptr = (u8 *) &ah->eeprom.ar9300_eep;
931 mdata_size = sizeof(struct ar9300_eeprom);
933 if (mptr && mdata_size > 0) {
934 /* At this point, mptr points to the eeprom data structure
935 * in it's "default" state. If this is big endian, swap the
936 * data structures back to "little endian"
938 /* First swap, default to Little Endian */
940 ar9300_swap_eeprom((struct ar9300_eeprom *)mptr);
942 if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0)
945 /* Second Swap, back to Big Endian */
947 ar9300_swap_eeprom((struct ar9300_eeprom *)mptr);
953 /* XXX: review hardware docs */
954 static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
956 return ah->eeprom.ar9300_eep.eepromVersion;
959 /* XXX: could be read from the eepromVersion, not sure yet */
960 static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
965 static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
966 enum ieee80211_band freq_band)
971 static u16 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
972 struct ath9k_channel *chan)
977 static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
979 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
982 return eep->modalHeader2G.xpaBiasLvl;
984 return eep->modalHeader5G.xpaBiasLvl;
987 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
989 int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
990 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3));
991 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE,
992 ((bias >> 2) & 0x3));
995 static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
997 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1000 return eep->modalHeader2G.antCtrlCommon;
1002 return eep->modalHeader5G.antCtrlCommon;
1005 static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
1007 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1010 return eep->modalHeader2G.antCtrlCommon2;
1012 return eep->modalHeader5G.antCtrlCommon2;
1015 static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1019 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1021 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1023 return eep->modalHeader2G.antCtrlChain[chain];
1025 return eep->modalHeader5G.antCtrlChain[chain];
1031 static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1033 u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
1034 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
1036 value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
1037 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1039 value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
1040 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1042 value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
1043 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1045 value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
1046 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1049 static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1054 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1056 if (!drive_strength)
1059 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1067 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1069 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1080 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1082 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1087 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1090 static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1092 int internal_regulator =
1093 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1095 if (internal_regulator) {
1096 /* Internal regulator is ON. Write swreg register. */
1097 int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
1098 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1099 REG_READ(ah, AR_RTC_REG_CONTROL1) &
1100 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1101 REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1102 /* Set REG_CONTROL1.SWREG_PROGRAM */
1103 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1105 AR_RTC_REG_CONTROL1) |
1106 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1108 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1111 AR_RTC_FORCE_SWREG_PRD));
1115 static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1116 struct ath9k_channel *chan)
1118 ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
1119 ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
1120 ar9003_hw_drive_strength_apply(ah);
1121 ar9003_hw_internal_regulator_apply(ah);
1124 static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1125 struct ath9k_channel *chan)
1130 * Returns the interpolated y value corresponding to the specified x value
1131 * from the np ordered pairs of data (px,py).
1132 * The pairs do not have to be in any order.
1133 * If the specified x value is less than any of the px,
1134 * the returned y value is equal to the py for the lowest px.
1135 * If the specified x value is greater than any of the px,
1136 * the returned y value is equal to the py for the highest px.
1138 static int ar9003_hw_power_interpolate(int32_t x,
1139 int32_t *px, int32_t *py, u_int16_t np)
1142 int lx = 0, ly = 0, lhave = 0;
1143 int hx = 0, hy = 0, hhave = 0;
1150 /* identify best lower and higher x calibration measurement */
1151 for (ip = 0; ip < np; ip++) {
1154 /* this measurement is higher than our desired x */
1156 if (!hhave || dx > (x - hx)) {
1157 /* new best higher x measurement */
1163 /* this measurement is lower than our desired x */
1165 if (!lhave || dx < (x - lx)) {
1166 /* new best lower x measurement */
1174 /* the low x is good */
1176 /* so is the high x */
1178 /* they're the same, so just pick one */
1181 else /* interpolate */
1182 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1183 } else /* only low is good, use it */
1185 } else if (hhave) /* only high is good, use it */
1187 else /* nothing is good,this should never happen unless np=0, ???? */
1192 static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1193 u16 rateIndex, u16 freq, bool is2GHz)
1196 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1197 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1198 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1199 struct cal_tgt_pow_legacy *pEepromTargetPwr;
1203 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1204 pEepromTargetPwr = eep->calTargetPower2G;
1205 pFreqBin = eep->calTarget_freqbin_2G;
1207 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1208 pEepromTargetPwr = eep->calTargetPower5G;
1209 pFreqBin = eep->calTarget_freqbin_5G;
1213 * create array of channels and targetpower from
1214 * targetpower piers stored on eeprom
1216 for (i = 0; i < numPiers; i++) {
1217 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1218 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1221 /* interpolate to get target power for given frequency */
1222 return (u8) ar9003_hw_power_interpolate((s32) freq,
1224 targetPowerArray, numPiers);
1227 static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1229 u16 freq, bool is2GHz)
1232 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1233 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1234 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1235 struct cal_tgt_pow_ht *pEepromTargetPwr;
1239 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1240 pEepromTargetPwr = eep->calTargetPower2GHT20;
1241 pFreqBin = eep->calTarget_freqbin_2GHT20;
1243 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1244 pEepromTargetPwr = eep->calTargetPower5GHT20;
1245 pFreqBin = eep->calTarget_freqbin_5GHT20;
1249 * create array of channels and targetpower
1250 * from targetpower piers stored on eeprom
1252 for (i = 0; i < numPiers; i++) {
1253 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1254 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1257 /* interpolate to get target power for given frequency */
1258 return (u8) ar9003_hw_power_interpolate((s32) freq,
1260 targetPowerArray, numPiers);
1263 static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1265 u16 freq, bool is2GHz)
1268 s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
1269 s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
1270 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1271 struct cal_tgt_pow_ht *pEepromTargetPwr;
1275 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1276 pEepromTargetPwr = eep->calTargetPower2GHT40;
1277 pFreqBin = eep->calTarget_freqbin_2GHT40;
1279 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1280 pEepromTargetPwr = eep->calTargetPower5GHT40;
1281 pFreqBin = eep->calTarget_freqbin_5GHT40;
1285 * create array of channels and targetpower from
1286 * targetpower piers stored on eeprom
1288 for (i = 0; i < numPiers; i++) {
1289 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1290 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1293 /* interpolate to get target power for given frequency */
1294 return (u8) ar9003_hw_power_interpolate((s32) freq,
1296 targetPowerArray, numPiers);
1299 static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1300 u16 rateIndex, u16 freq)
1302 u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
1303 s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1304 s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1305 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1306 struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
1307 u8 *pFreqBin = eep->calTarget_freqbin_Cck;
1310 * create array of channels and targetpower from
1311 * targetpower piers stored on eeprom
1313 for (i = 0; i < numPiers; i++) {
1314 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1315 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1318 /* interpolate to get target power for given frequency */
1319 return (u8) ar9003_hw_power_interpolate((s32) freq,
1321 targetPowerArray, numPiers);
1324 /* Set tx power registers to array of values passed in */
1325 static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1327 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1328 /* make sure forced gain is not set */
1329 REG_WRITE(ah, 0xa458, 0);
1331 /* Write the OFDM power per rate set */
1333 /* 6 (LSB), 9, 12, 18 (MSB) */
1334 REG_WRITE(ah, 0xa3c0,
1335 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
1336 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
1337 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
1338 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1340 /* 24 (LSB), 36, 48, 54 (MSB) */
1341 REG_WRITE(ah, 0xa3c4,
1342 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
1343 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
1344 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
1345 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1347 /* Write the CCK power per rate set */
1349 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1350 REG_WRITE(ah, 0xa3c8,
1351 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
1352 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
1353 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1354 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
1356 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1357 REG_WRITE(ah, 0xa3cc,
1358 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
1359 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
1360 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
1361 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
1364 /* Write the HT20 power per rate set */
1366 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1367 REG_WRITE(ah, 0xa3d0,
1368 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
1369 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
1370 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
1371 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
1374 /* 6 (LSB), 7, 12, 13 (MSB) */
1375 REG_WRITE(ah, 0xa3d4,
1376 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
1377 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
1378 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
1379 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
1382 /* 14 (LSB), 15, 20, 21 */
1383 REG_WRITE(ah, 0xa3e4,
1384 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
1385 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
1386 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
1387 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
1390 /* Mixed HT20 and HT40 rates */
1392 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1393 REG_WRITE(ah, 0xa3e8,
1394 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
1395 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
1396 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
1397 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
1401 * Write the HT40 power per rate set
1402 * correct PAR difference between HT40 and HT20/LEGACY
1403 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1405 REG_WRITE(ah, 0xa3d8,
1406 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
1407 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
1408 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
1409 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
1412 /* 6 (LSB), 7, 12, 13 (MSB) */
1413 REG_WRITE(ah, 0xa3dc,
1414 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
1415 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
1416 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
1417 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
1420 /* 14 (LSB), 15, 20, 21 */
1421 REG_WRITE(ah, 0xa3ec,
1422 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
1423 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
1424 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
1425 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
1432 static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq)
1434 u8 targetPowerValT2[ar9300RateSize];
1435 /* XXX: hard code for now, need to get from eeprom struct */
1436 u8 ht40PowerIncForPdadc = 0;
1437 bool is2GHz = false;
1439 struct ath_common *common = ath9k_hw_common(ah);
1444 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1445 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1447 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1448 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1450 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1451 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1453 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1454 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1456 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1457 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1459 targetPowerValT2[ALL_TARGET_LEGACY_5S] =
1460 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
1461 targetPowerValT2[ALL_TARGET_LEGACY_11L] =
1462 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
1463 targetPowerValT2[ALL_TARGET_LEGACY_11S] =
1464 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
1465 targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
1466 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1468 targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1469 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1471 targetPowerValT2[ALL_TARGET_HT20_4] =
1472 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1474 targetPowerValT2[ALL_TARGET_HT20_5] =
1475 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1477 targetPowerValT2[ALL_TARGET_HT20_6] =
1478 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1480 targetPowerValT2[ALL_TARGET_HT20_7] =
1481 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1483 targetPowerValT2[ALL_TARGET_HT20_12] =
1484 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1486 targetPowerValT2[ALL_TARGET_HT20_13] =
1487 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1489 targetPowerValT2[ALL_TARGET_HT20_14] =
1490 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1492 targetPowerValT2[ALL_TARGET_HT20_15] =
1493 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1495 targetPowerValT2[ALL_TARGET_HT20_20] =
1496 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1498 targetPowerValT2[ALL_TARGET_HT20_21] =
1499 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1501 targetPowerValT2[ALL_TARGET_HT20_22] =
1502 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1504 targetPowerValT2[ALL_TARGET_HT20_23] =
1505 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1507 targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
1508 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1509 is2GHz) + ht40PowerIncForPdadc;
1510 targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1511 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1513 is2GHz) + ht40PowerIncForPdadc;
1514 targetPowerValT2[ALL_TARGET_HT40_4] =
1515 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1516 is2GHz) + ht40PowerIncForPdadc;
1517 targetPowerValT2[ALL_TARGET_HT40_5] =
1518 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1519 is2GHz) + ht40PowerIncForPdadc;
1520 targetPowerValT2[ALL_TARGET_HT40_6] =
1521 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1522 is2GHz) + ht40PowerIncForPdadc;
1523 targetPowerValT2[ALL_TARGET_HT40_7] =
1524 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1525 is2GHz) + ht40PowerIncForPdadc;
1526 targetPowerValT2[ALL_TARGET_HT40_12] =
1527 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1528 is2GHz) + ht40PowerIncForPdadc;
1529 targetPowerValT2[ALL_TARGET_HT40_13] =
1530 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1531 is2GHz) + ht40PowerIncForPdadc;
1532 targetPowerValT2[ALL_TARGET_HT40_14] =
1533 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1534 is2GHz) + ht40PowerIncForPdadc;
1535 targetPowerValT2[ALL_TARGET_HT40_15] =
1536 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1537 is2GHz) + ht40PowerIncForPdadc;
1538 targetPowerValT2[ALL_TARGET_HT40_20] =
1539 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1540 is2GHz) + ht40PowerIncForPdadc;
1541 targetPowerValT2[ALL_TARGET_HT40_21] =
1542 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1543 is2GHz) + ht40PowerIncForPdadc;
1544 targetPowerValT2[ALL_TARGET_HT40_22] =
1545 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1546 is2GHz) + ht40PowerIncForPdadc;
1547 targetPowerValT2[ALL_TARGET_HT40_23] =
1548 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1549 is2GHz) + ht40PowerIncForPdadc;
1551 while (i < ar9300RateSize) {
1552 ath_print(common, ATH_DBG_EEPROM,
1553 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1556 ath_print(common, ATH_DBG_EEPROM,
1557 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1560 ath_print(common, ATH_DBG_EEPROM,
1561 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1564 ath_print(common, ATH_DBG_EEPROM,
1565 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1569 /* Write target power array to registers */
1570 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
1573 static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1579 int *ptemperature, int *pvoltage)
1582 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1584 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1585 struct ath_common *common = ath9k_hw_common(ah);
1587 if (ichain >= AR9300_MAX_CHAINS) {
1588 ath_print(common, ATH_DBG_EEPROM,
1589 "Invalid chain index, must be less than %d\n",
1594 if (mode) { /* 5GHz */
1595 if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
1596 ath_print(common, ATH_DBG_EEPROM,
1597 "Invalid 5GHz cal pier index, must "
1598 "be less than %d\n",
1599 AR9300_NUM_5G_CAL_PIERS);
1602 pCalPier = &(eep->calFreqPier5G[ipier]);
1603 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1606 if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
1607 ath_print(common, ATH_DBG_EEPROM,
1608 "Invalid 2GHz cal pier index, must "
1609 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
1613 pCalPier = &(eep->calFreqPier2G[ipier]);
1614 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1618 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1619 *pcorrection = pCalPierStruct->refPower;
1620 *ptemperature = pCalPierStruct->tempMeas;
1621 *pvoltage = pCalPierStruct->voltMeas;
1626 static int ar9003_hw_power_control_override(struct ath_hw *ah,
1629 int *voltage, int *temperature)
1632 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1634 REG_RMW(ah, AR_PHY_TPC_11_B0,
1635 (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1636 AR_PHY_TPC_OLPC_GAIN_DELTA);
1637 REG_RMW(ah, AR_PHY_TPC_11_B1,
1638 (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1639 AR_PHY_TPC_OLPC_GAIN_DELTA);
1640 REG_RMW(ah, AR_PHY_TPC_11_B2,
1641 (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1642 AR_PHY_TPC_OLPC_GAIN_DELTA);
1644 /* enable open loop power control on chip */
1645 REG_RMW(ah, AR_PHY_TPC_6_B0,
1646 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1647 AR_PHY_TPC_6_ERROR_EST_MODE);
1648 REG_RMW(ah, AR_PHY_TPC_6_B1,
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_B2,
1652 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1653 AR_PHY_TPC_6_ERROR_EST_MODE);
1656 * enable temperature compensation
1657 * Need to use register names
1659 if (frequency < 4000)
1660 tempSlope = eep->modalHeader2G.tempSlope;
1662 tempSlope = eep->modalHeader5G.tempSlope;
1664 REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
1665 REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
1671 /* Apply the recorded correction values. */
1672 static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1674 int ichain, ipier, npier;
1676 int lfrequency[AR9300_MAX_CHAINS],
1677 lcorrection[AR9300_MAX_CHAINS],
1678 ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
1679 int hfrequency[AR9300_MAX_CHAINS],
1680 hcorrection[AR9300_MAX_CHAINS],
1681 htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
1683 int correction[AR9300_MAX_CHAINS],
1684 voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
1685 int pfrequency, pcorrection, ptemperature, pvoltage;
1686 struct ath_common *common = ath9k_hw_common(ah);
1688 mode = (frequency >= 4000);
1690 npier = AR9300_NUM_5G_CAL_PIERS;
1692 npier = AR9300_NUM_2G_CAL_PIERS;
1694 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1695 lfrequency[ichain] = 0;
1696 hfrequency[ichain] = 100000;
1698 /* identify best lower and higher frequency calibration measurement */
1699 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1700 for (ipier = 0; ipier < npier; ipier++) {
1701 if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
1702 &pfrequency, &pcorrection,
1703 &ptemperature, &pvoltage)) {
1704 fdiff = frequency - pfrequency;
1707 * this measurement is higher than
1708 * our desired frequency
1711 if (hfrequency[ichain] <= 0 ||
1712 hfrequency[ichain] >= 100000 ||
1714 (frequency - hfrequency[ichain])) {
1717 * frequency measurement
1719 hfrequency[ichain] = pfrequency;
1720 hcorrection[ichain] =
1722 htemperature[ichain] =
1724 hvoltage[ichain] = pvoltage;
1728 if (lfrequency[ichain] <= 0
1730 (frequency - lfrequency[ichain])) {
1733 * frequency measurement
1735 lfrequency[ichain] = pfrequency;
1736 lcorrection[ichain] =
1738 ltemperature[ichain] =
1740 lvoltage[ichain] = pvoltage;
1748 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1749 ath_print(common, ATH_DBG_EEPROM,
1750 "ch=%d f=%d low=%d %d h=%d %d\n",
1751 ichain, frequency, lfrequency[ichain],
1752 lcorrection[ichain], hfrequency[ichain],
1753 hcorrection[ichain]);
1754 /* they're the same, so just pick one */
1755 if (hfrequency[ichain] == lfrequency[ichain]) {
1756 correction[ichain] = lcorrection[ichain];
1757 voltage[ichain] = lvoltage[ichain];
1758 temperature[ichain] = ltemperature[ichain];
1760 /* the low frequency is good */
1761 else if (frequency - lfrequency[ichain] < 1000) {
1762 /* so is the high frequency, interpolate */
1763 if (hfrequency[ichain] - frequency < 1000) {
1765 correction[ichain] = lcorrection[ichain] +
1766 (((frequency - lfrequency[ichain]) *
1767 (hcorrection[ichain] -
1768 lcorrection[ichain])) /
1769 (hfrequency[ichain] - lfrequency[ichain]));
1771 temperature[ichain] = ltemperature[ichain] +
1772 (((frequency - lfrequency[ichain]) *
1773 (htemperature[ichain] -
1774 ltemperature[ichain])) /
1775 (hfrequency[ichain] - lfrequency[ichain]));
1780 lfrequency[ichain]) * (hvoltage[ichain] -
1782 / (hfrequency[ichain] -
1783 lfrequency[ichain]));
1785 /* only low is good, use it */
1787 correction[ichain] = lcorrection[ichain];
1788 temperature[ichain] = ltemperature[ichain];
1789 voltage[ichain] = lvoltage[ichain];
1792 /* only high is good, use it */
1793 else if (hfrequency[ichain] - frequency < 1000) {
1794 correction[ichain] = hcorrection[ichain];
1795 temperature[ichain] = htemperature[ichain];
1796 voltage[ichain] = hvoltage[ichain];
1797 } else { /* nothing is good, presume 0???? */
1798 correction[ichain] = 0;
1799 temperature[ichain] = 0;
1800 voltage[ichain] = 0;
1804 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1807 ath_print(common, ATH_DBG_EEPROM,
1808 "for frequency=%d, calibration correction = %d %d %d\n",
1809 frequency, correction[0], correction[1], correction[2]);
1814 static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
1815 struct ath9k_channel *chan, u16 cfgCtl,
1816 u8 twiceAntennaReduction,
1817 u8 twiceMaxRegulatoryPower,
1820 ar9003_hw_set_target_power_eeprom(ah, chan->channel);
1821 ar9003_hw_calibration_apply(ah, chan->channel);
1824 static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
1830 s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
1832 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1834 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
1837 s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
1839 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1841 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
1844 const struct eeprom_ops eep_ar9300_ops = {
1845 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
1846 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
1847 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
1848 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
1849 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
1850 .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
1851 .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
1852 .set_board_values = ath9k_hw_ar9300_set_board_values,
1853 .set_addac = ath9k_hw_ar9300_set_addac,
1854 .set_txpower = ath9k_hw_ar9300_set_txpower,
1855 .get_spur_channel = ath9k_hw_ar9300_get_spur_channel