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 (0x300)
26 #define AR_CH0_TOP_XPABIASLVL_S (8)
28 #define AR_CH0_THERM (0x00016290)
29 #define AR_CH0_THERM_XPABIASLVL_MSB 0x3
30 #define AR_CH0_THERM_XPABIASLVL_MSB_S 0
31 #define AR_CH0_THERM_XPASHORT2GND 0x4
32 #define AR_CH0_THERM_XPASHORT2GND_S 2
34 #define AR_SWITCH_TABLE_COM_ALL (0xffff)
35 #define AR_SWITCH_TABLE_COM_ALL_S (0)
37 #define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
38 #define AR_SWITCH_TABLE_COM2_ALL_S (0)
40 #define AR_SWITCH_TABLE_ALL (0xfff)
41 #define AR_SWITCH_TABLE_ALL_S (0)
43 #define LE16(x) __constant_cpu_to_le16(x)
44 #define LE32(x) __constant_cpu_to_le32(x)
46 /* Local defines to distinguish between extension and control CTL's */
47 #define EXT_ADDITIVE (0x8000)
48 #define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
49 #define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
50 #define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
51 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
52 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
53 #define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */
54 #define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */
55 #define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */
57 #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */
58 #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
60 #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
62 static const struct ar9300_eeprom ar9300_default = {
65 .macAddr = {1, 2, 3, 4, 5, 6},
66 .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
69 .regDmn = { LE16(0), LE16(0x1f) },
70 .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
72 .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
76 .blueToothOptions = 0,
78 .deviceType = 5, /* takes lower byte in eeprom location */
79 .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
80 .params_for_tuning_caps = {0, 0},
81 .featureEnable = 0x0c,
83 * bit0 - enable tx temp comp - disabled
84 * bit1 - enable tx volt comp - disabled
85 * bit2 - enable fastClock - enabled
86 * bit3 - enable doubling - enabled
87 * bit4 - enable internal regulator - disabled
88 * bit5 - enable pa predistortion - disabled
90 .miscConfiguration = 0, /* bit0 - turn down drivestrength */
91 .eepromWriteEnableGpio = 3,
94 .rxBandSelectGpio = 0xff,
99 /* ar9300_modal_eep_header 2g */
100 /* 4 idle,t1,t2,b(4 bits per setting) */
101 .antCtrlCommon = LE32(0x110),
102 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
103 .antCtrlCommon2 = LE32(0x22222),
106 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
107 * rx1, rx12, b (2 bits each)
109 .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
112 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
113 * for ar9280 (0xa20c/b20c 5:0)
115 .xatten1DB = {0, 0, 0},
118 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
119 * for ar9280 (0xa20c/b20c 16:12
121 .xatten1Margin = {0, 0, 0},
126 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
127 * channels in usual fbin coding format
129 .spurChans = {0, 0, 0, 0, 0},
132 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
133 * if the register is per chain
135 .noiseFloorThreshCh = {-1, 0, 0},
136 .ob = {1, 1, 1},/* 3 chain */
137 .db_stage2 = {1, 1, 1}, /* 3 chain */
138 .db_stage3 = {0, 0, 0},
139 .db_stage4 = {0, 0, 0},
141 .txFrameToDataStart = 0x0e,
142 .txFrameToPaOn = 0x0e,
143 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
145 .switchSettling = 0x2c,
146 .adcDesiredSize = -30,
149 .txFrameToXpaOn = 0xe,
151 .papdRateMaskHt20 = LE32(0x80c080),
152 .papdRateMaskHt40 = LE32(0x80c080),
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
155 0, 0, 0, 0, 0, 0, 0, 0
163 /* ar9300_cal_data_per_freq_op_loop 2g */
165 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
166 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
167 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
169 .calTarget_freqbin_Cck = {
173 .calTarget_freqbin_2G = {
178 .calTarget_freqbin_2GHT20 = {
183 .calTarget_freqbin_2GHT40 = {
188 .calTargetPowerCck = {
189 /* 1L-5L,5S,11L,11S */
190 { {36, 36, 36, 36} },
191 { {36, 36, 36, 36} },
193 .calTargetPower2G = {
195 { {32, 32, 28, 24} },
196 { {32, 32, 28, 24} },
197 { {32, 32, 28, 24} },
199 .calTargetPower2GHT20 = {
200 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
201 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
202 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
204 .calTargetPower2GHT40 = {
205 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
206 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
207 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
210 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
211 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
241 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
242 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
243 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
244 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
248 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
249 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
250 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
255 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
256 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
262 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
263 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
264 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
265 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
269 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
270 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
271 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
275 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
276 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
277 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
282 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
283 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
284 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
289 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
290 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
291 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
292 /* Data[11].ctlEdges[3].bChannel */
297 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
298 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
299 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
301 { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
302 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
303 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
305 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
306 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
307 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
309 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
310 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
311 { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
314 /* 4 idle,t1,t2,b (4 bits per setting) */
315 .antCtrlCommon = LE32(0x110),
316 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
317 .antCtrlCommon2 = LE32(0x22222),
318 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
320 LE16(0x000), LE16(0x000), LE16(0x000),
322 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
323 .xatten1DB = {0, 0, 0},
326 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
327 * for merlin (0xa20c/b20c 16:12
329 .xatten1Margin = {0, 0, 0},
332 /* spurChans spur channels in usual fbin coding format */
333 .spurChans = {0, 0, 0, 0, 0},
334 /* noiseFloorThreshCh Check if the register is per chain */
335 .noiseFloorThreshCh = {-1, 0, 0},
336 .ob = {3, 3, 3}, /* 3 chain */
337 .db_stage2 = {3, 3, 3}, /* 3 chain */
338 .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
339 .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
341 .txFrameToDataStart = 0x0e,
342 .txFrameToPaOn = 0x0e,
343 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
345 .switchSettling = 0x2d,
346 .adcDesiredSize = -30,
349 .txFrameToXpaOn = 0xe,
351 .papdRateMaskHt20 = LE32(0xf0e0e0),
352 .papdRateMaskHt40 = LE32(0xf0e0e0),
354 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
355 0, 0, 0, 0, 0, 0, 0, 0
401 .calTarget_freqbin_5G = {
411 .calTarget_freqbin_5GHT20 = {
421 .calTarget_freqbin_5GHT40 = {
431 .calTargetPower5G = {
433 { {20, 20, 20, 10} },
434 { {20, 20, 20, 10} },
435 { {20, 20, 20, 10} },
436 { {20, 20, 20, 10} },
437 { {20, 20, 20, 10} },
438 { {20, 20, 20, 10} },
439 { {20, 20, 20, 10} },
440 { {20, 20, 20, 10} },
442 .calTargetPower5GHT20 = {
444 * 0_8_16,1-3_9-11_17-19,
445 * 4,5,6,7,12,13,14,15,20,21,22,23
447 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
448 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
449 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
450 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
451 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
452 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
453 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
454 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
456 .calTargetPower5GHT40 = {
458 * 0_8_16,1-3_9-11_17-19,
459 * 4,5,6,7,12,13,14,15,20,21,22,23
461 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
462 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
463 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
464 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
465 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
466 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
467 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
468 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
471 0x10, 0x16, 0x18, 0x40, 0x46,
472 0x48, 0x30, 0x36, 0x38
476 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
477 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
478 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
479 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
480 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
481 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
482 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
483 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
486 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
487 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
488 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
489 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
490 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
491 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
492 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
493 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
497 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
498 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
499 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
500 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
501 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
502 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
503 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
504 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
508 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
509 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
510 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
511 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
512 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
513 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
514 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
515 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
519 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
520 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
521 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
522 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
523 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
524 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
525 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
526 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
530 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
531 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
532 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
533 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
534 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
535 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
536 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
537 /* Data[5].ctlEdges[7].bChannel */ 0xFF
541 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
542 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
543 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
544 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
545 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
546 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
547 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
548 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
552 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
553 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
554 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
555 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
556 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
557 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
558 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
559 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
563 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
564 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
565 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
566 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
567 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
568 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
569 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
570 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
576 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
577 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
582 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
583 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
588 CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
589 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
594 CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
595 CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
600 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
601 CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
606 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
607 CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
612 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
613 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
618 CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
619 CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
624 CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
625 CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
631 static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
633 if (fbin == AR9300_BCHAN_UNUSED)
636 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
639 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
644 static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
645 enum eeprom_param param)
647 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
648 struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
652 return eep->macAddr[0] << 8 | eep->macAddr[1];
654 return eep->macAddr[2] << 8 | eep->macAddr[3];
656 return eep->macAddr[4] << 8 | eep->macAddr[5];
658 return le16_to_cpu(pBase->regDmn[0]);
660 return le16_to_cpu(pBase->regDmn[1]);
662 return pBase->deviceCap;
664 return pBase->opCapFlags.opFlags;
666 return pBase->rfSilent;
668 return (pBase->txrxMask >> 4) & 0xf;
670 return pBase->txrxMask & 0xf;
671 case EEP_DRIVE_STRENGTH:
672 #define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
673 return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
674 case EEP_INTERNAL_REGULATOR:
675 /* Bit 4 is internal regulator flag */
676 return (pBase->featureEnable & 0x10) >> 4;
678 return le32_to_cpu(pBase->swreg);
680 return !!(pBase->featureEnable & BIT(5));
686 static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
691 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
694 *buffer = (val >> (8 * (address % 2))) & 0xff;
698 static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
703 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
706 buffer[0] = val >> 8;
707 buffer[1] = val & 0xff;
712 static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
715 struct ath_common *common = ath9k_hw_common(ah);
718 if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
719 ath_print(common, ATH_DBG_EEPROM,
720 "eeprom address not in range\n");
725 * Since we're reading the bytes in reverse order from a little-endian
726 * word stream, an even address means we only use the lower half of
727 * the 16-bit word at that address
729 if (address % 2 == 0) {
730 if (!ar9300_eeprom_read_byte(common, address--, buffer++))
736 for (i = 0; i < count / 2; i++) {
737 if (!ar9300_eeprom_read_word(common, address, buffer))
745 if (!ar9300_eeprom_read_byte(common, address, buffer))
751 ath_print(common, ATH_DBG_EEPROM,
752 "unable to read eeprom region at offset %d\n", address);
756 static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
757 int *length, int *major, int *minor)
759 unsigned long value[4];
765 *code = ((value[0] >> 5) & 0x0007);
766 *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
767 *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
768 *major = (value[2] & 0x000f);
769 *minor = (value[3] & 0x00ff);
772 static u16 ar9300_comp_cksum(u8 *data, int dsize)
774 int it, checksum = 0;
776 for (it = 0; it < dsize; it++) {
777 checksum += data[it];
784 static bool ar9300_uncompress_block(struct ath_hw *ah,
794 struct ath_common *common = ath9k_hw_common(ah);
798 for (it = 0; it < size; it += (length+2)) {
802 length = block[it+1];
805 if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
806 ath_print(common, ATH_DBG_EEPROM,
807 "Restore at %d: spot=%d "
808 "offset=%d length=%d\n",
809 it, spot, offset, length);
810 memcpy(&mptr[spot], &block[it+2], length);
812 } else if (length > 0) {
813 ath_print(common, ATH_DBG_EEPROM,
814 "Bad restore at %d: spot=%d "
815 "offset=%d length=%d\n",
816 it, spot, offset, length);
823 static int ar9300_compress_decision(struct ath_hw *ah,
828 u8 *word, int length, int mdata_size)
830 struct ath_common *common = ath9k_hw_common(ah);
835 if (length != mdata_size) {
836 ath_print(common, ATH_DBG_EEPROM,
837 "EEPROM structure size mismatch"
838 "memory=%d eeprom=%d\n", mdata_size, length);
841 memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
842 ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:"
843 " uncompressed, length %d\n", it, length);
846 if (reference == 0) {
849 if (reference != 2) {
850 ath_print(common, ATH_DBG_EEPROM,
851 "cant find reference eeprom"
852 "struct %d\n", reference);
855 memcpy(mptr, &ar9300_default, mdata_size);
857 ath_print(common, ATH_DBG_EEPROM,
858 "restore eeprom %d: block, reference %d,"
859 " length %d\n", it, reference, length);
860 ar9300_uncompress_block(ah, mptr, mdata_size,
861 (u8 *) (word + COMP_HDR_LEN), length);
864 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
872 * Read the configuration data from the eeprom.
873 * The data can be put in any specified memory buffer.
875 * Returns -1 on error.
876 * Returns address of next memory location on success.
878 static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
879 u8 *mptr, int mdata_size)
886 int reference, length, major, minor;
889 u16 checksum, mchecksum;
890 struct ath_common *common = ath9k_hw_common(ah);
892 word = kzalloc(2048, GFP_KERNEL);
896 memcpy(mptr, &ar9300_default, mdata_size);
898 cptr = AR9300_BASE_ADDR;
899 for (it = 0; it < MSTATE; it++) {
900 if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
903 if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
904 word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
905 && word[2] == 0xff && word[3] == 0xff))
908 ar9300_comp_hdr_unpack(word, &code, &reference,
909 &length, &major, &minor);
910 ath_print(common, ATH_DBG_EEPROM,
911 "Found block at %x: code=%d ref=%d"
912 "length=%d major=%d minor=%d\n", cptr, code,
913 reference, length, major, minor);
914 if (length >= 1024) {
915 ath_print(common, ATH_DBG_EEPROM,
916 "Skipping bad header\n");
917 cptr -= COMP_HDR_LEN;
922 ar9300_read_eeprom(ah, cptr, word,
923 COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
924 checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
925 mchecksum = word[COMP_HDR_LEN + osize] |
926 (word[COMP_HDR_LEN + osize + 1] << 8);
927 ath_print(common, ATH_DBG_EEPROM,
928 "checksum %x %x\n", checksum, mchecksum);
929 if (checksum == mchecksum) {
930 ar9300_compress_decision(ah, it, code, reference, mptr,
931 word, length, mdata_size);
933 ath_print(common, ATH_DBG_EEPROM,
934 "skipping block with bad checksum\n");
936 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
948 * Restore the configuration structure by reading the eeprom.
949 * This function destroys any existing in-memory structure
952 static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
954 u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
956 if (ar9300_eeprom_restore_internal(ah, mptr,
957 sizeof(struct ar9300_eeprom)) < 0)
963 /* XXX: review hardware docs */
964 static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
966 return ah->eeprom.ar9300_eep.eepromVersion;
969 /* XXX: could be read from the eepromVersion, not sure yet */
970 static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
975 static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
976 enum ieee80211_band freq_band)
981 static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
982 struct ath9k_channel *chan)
987 static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
989 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
992 return eep->modalHeader2G.xpaBiasLvl;
994 return eep->modalHeader5G.xpaBiasLvl;
997 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
999 int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
1000 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
1001 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, bias >> 2);
1002 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1);
1005 static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
1007 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1011 val = eep->modalHeader2G.antCtrlCommon;
1013 val = eep->modalHeader5G.antCtrlCommon;
1014 return le32_to_cpu(val);
1017 static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
1019 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1023 val = eep->modalHeader2G.antCtrlCommon2;
1025 val = eep->modalHeader5G.antCtrlCommon2;
1026 return le32_to_cpu(val);
1029 static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1033 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1036 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1038 val = eep->modalHeader2G.antCtrlChain[chain];
1040 val = eep->modalHeader5G.antCtrlChain[chain];
1043 return le16_to_cpu(val);
1046 static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1048 u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
1049 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
1051 value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
1052 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1054 value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
1055 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1057 value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
1058 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1060 value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
1061 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1064 static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1069 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1071 if (!drive_strength)
1074 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1082 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1084 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1095 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1097 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1102 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1105 static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1107 int internal_regulator =
1108 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1110 if (internal_regulator) {
1111 /* Internal regulator is ON. Write swreg register. */
1112 int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
1113 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1114 REG_READ(ah, AR_RTC_REG_CONTROL1) &
1115 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1116 REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1117 /* Set REG_CONTROL1.SWREG_PROGRAM */
1118 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1120 AR_RTC_REG_CONTROL1) |
1121 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1123 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1126 AR_RTC_FORCE_SWREG_PRD));
1130 static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1131 struct ath9k_channel *chan)
1133 ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
1134 ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
1135 ar9003_hw_drive_strength_apply(ah);
1136 ar9003_hw_internal_regulator_apply(ah);
1139 static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1140 struct ath9k_channel *chan)
1145 * Returns the interpolated y value corresponding to the specified x value
1146 * from the np ordered pairs of data (px,py).
1147 * The pairs do not have to be in any order.
1148 * If the specified x value is less than any of the px,
1149 * the returned y value is equal to the py for the lowest px.
1150 * If the specified x value is greater than any of the px,
1151 * the returned y value is equal to the py for the highest px.
1153 static int ar9003_hw_power_interpolate(int32_t x,
1154 int32_t *px, int32_t *py, u_int16_t np)
1157 int lx = 0, ly = 0, lhave = 0;
1158 int hx = 0, hy = 0, hhave = 0;
1165 /* identify best lower and higher x calibration measurement */
1166 for (ip = 0; ip < np; ip++) {
1169 /* this measurement is higher than our desired x */
1171 if (!hhave || dx > (x - hx)) {
1172 /* new best higher x measurement */
1178 /* this measurement is lower than our desired x */
1180 if (!lhave || dx < (x - lx)) {
1181 /* new best lower x measurement */
1189 /* the low x is good */
1191 /* so is the high x */
1193 /* they're the same, so just pick one */
1196 else /* interpolate */
1197 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1198 } else /* only low is good, use it */
1200 } else if (hhave) /* only high is good, use it */
1202 else /* nothing is good,this should never happen unless np=0, ???? */
1207 static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1208 u16 rateIndex, u16 freq, bool is2GHz)
1211 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1212 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1213 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1214 struct cal_tgt_pow_legacy *pEepromTargetPwr;
1218 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1219 pEepromTargetPwr = eep->calTargetPower2G;
1220 pFreqBin = eep->calTarget_freqbin_2G;
1222 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1223 pEepromTargetPwr = eep->calTargetPower5G;
1224 pFreqBin = eep->calTarget_freqbin_5G;
1228 * create array of channels and targetpower from
1229 * targetpower piers stored on eeprom
1231 for (i = 0; i < numPiers; i++) {
1232 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1233 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1236 /* interpolate to get target power for given frequency */
1237 return (u8) ar9003_hw_power_interpolate((s32) freq,
1239 targetPowerArray, numPiers);
1242 static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1244 u16 freq, bool is2GHz)
1247 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1248 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1249 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1250 struct cal_tgt_pow_ht *pEepromTargetPwr;
1254 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1255 pEepromTargetPwr = eep->calTargetPower2GHT20;
1256 pFreqBin = eep->calTarget_freqbin_2GHT20;
1258 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1259 pEepromTargetPwr = eep->calTargetPower5GHT20;
1260 pFreqBin = eep->calTarget_freqbin_5GHT20;
1264 * create array of channels and targetpower
1265 * from targetpower piers stored on eeprom
1267 for (i = 0; i < numPiers; i++) {
1268 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1269 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1272 /* interpolate to get target power for given frequency */
1273 return (u8) ar9003_hw_power_interpolate((s32) freq,
1275 targetPowerArray, numPiers);
1278 static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1280 u16 freq, bool is2GHz)
1283 s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
1284 s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
1285 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1286 struct cal_tgt_pow_ht *pEepromTargetPwr;
1290 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1291 pEepromTargetPwr = eep->calTargetPower2GHT40;
1292 pFreqBin = eep->calTarget_freqbin_2GHT40;
1294 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1295 pEepromTargetPwr = eep->calTargetPower5GHT40;
1296 pFreqBin = eep->calTarget_freqbin_5GHT40;
1300 * create array of channels and targetpower from
1301 * targetpower piers stored on eeprom
1303 for (i = 0; i < numPiers; i++) {
1304 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1305 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1308 /* interpolate to get target power for given frequency */
1309 return (u8) ar9003_hw_power_interpolate((s32) freq,
1311 targetPowerArray, numPiers);
1314 static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1315 u16 rateIndex, u16 freq)
1317 u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
1318 s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1319 s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1320 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1321 struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
1322 u8 *pFreqBin = eep->calTarget_freqbin_Cck;
1325 * create array of channels and targetpower from
1326 * targetpower piers stored on eeprom
1328 for (i = 0; i < numPiers; i++) {
1329 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1330 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1333 /* interpolate to get target power for given frequency */
1334 return (u8) ar9003_hw_power_interpolate((s32) freq,
1336 targetPowerArray, numPiers);
1339 /* Set tx power registers to array of values passed in */
1340 static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1342 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1343 /* make sure forced gain is not set */
1344 REG_WRITE(ah, 0xa458, 0);
1346 /* Write the OFDM power per rate set */
1348 /* 6 (LSB), 9, 12, 18 (MSB) */
1349 REG_WRITE(ah, 0xa3c0,
1350 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
1351 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
1352 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
1353 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1355 /* 24 (LSB), 36, 48, 54 (MSB) */
1356 REG_WRITE(ah, 0xa3c4,
1357 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
1358 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
1359 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
1360 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1362 /* Write the CCK power per rate set */
1364 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1365 REG_WRITE(ah, 0xa3c8,
1366 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
1367 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
1368 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1369 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
1371 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1372 REG_WRITE(ah, 0xa3cc,
1373 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
1374 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
1375 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
1376 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
1379 /* Write the HT20 power per rate set */
1381 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1382 REG_WRITE(ah, 0xa3d0,
1383 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
1384 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
1385 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
1386 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
1389 /* 6 (LSB), 7, 12, 13 (MSB) */
1390 REG_WRITE(ah, 0xa3d4,
1391 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
1392 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
1393 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
1394 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
1397 /* 14 (LSB), 15, 20, 21 */
1398 REG_WRITE(ah, 0xa3e4,
1399 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
1400 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
1401 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
1402 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
1405 /* Mixed HT20 and HT40 rates */
1407 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1408 REG_WRITE(ah, 0xa3e8,
1409 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
1410 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
1411 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
1412 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
1416 * Write the HT40 power per rate set
1417 * correct PAR difference between HT40 and HT20/LEGACY
1418 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1420 REG_WRITE(ah, 0xa3d8,
1421 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
1422 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
1423 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
1424 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
1427 /* 6 (LSB), 7, 12, 13 (MSB) */
1428 REG_WRITE(ah, 0xa3dc,
1429 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
1430 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
1431 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
1432 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
1435 /* 14 (LSB), 15, 20, 21 */
1436 REG_WRITE(ah, 0xa3ec,
1437 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
1438 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
1439 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
1440 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
1447 static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
1448 u8 *targetPowerValT2)
1450 /* XXX: hard code for now, need to get from eeprom struct */
1451 u8 ht40PowerIncForPdadc = 0;
1452 bool is2GHz = false;
1454 struct ath_common *common = ath9k_hw_common(ah);
1459 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1460 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1462 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1463 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1465 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1466 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1468 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1469 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1471 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1472 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1474 targetPowerValT2[ALL_TARGET_LEGACY_5S] =
1475 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
1476 targetPowerValT2[ALL_TARGET_LEGACY_11L] =
1477 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
1478 targetPowerValT2[ALL_TARGET_LEGACY_11S] =
1479 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
1480 targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
1481 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1483 targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1484 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1486 targetPowerValT2[ALL_TARGET_HT20_4] =
1487 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1489 targetPowerValT2[ALL_TARGET_HT20_5] =
1490 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1492 targetPowerValT2[ALL_TARGET_HT20_6] =
1493 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1495 targetPowerValT2[ALL_TARGET_HT20_7] =
1496 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1498 targetPowerValT2[ALL_TARGET_HT20_12] =
1499 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1501 targetPowerValT2[ALL_TARGET_HT20_13] =
1502 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1504 targetPowerValT2[ALL_TARGET_HT20_14] =
1505 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1507 targetPowerValT2[ALL_TARGET_HT20_15] =
1508 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1510 targetPowerValT2[ALL_TARGET_HT20_20] =
1511 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1513 targetPowerValT2[ALL_TARGET_HT20_21] =
1514 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1516 targetPowerValT2[ALL_TARGET_HT20_22] =
1517 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1519 targetPowerValT2[ALL_TARGET_HT20_23] =
1520 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1522 targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
1523 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1524 is2GHz) + ht40PowerIncForPdadc;
1525 targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1526 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1528 is2GHz) + ht40PowerIncForPdadc;
1529 targetPowerValT2[ALL_TARGET_HT40_4] =
1530 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1531 is2GHz) + ht40PowerIncForPdadc;
1532 targetPowerValT2[ALL_TARGET_HT40_5] =
1533 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1534 is2GHz) + ht40PowerIncForPdadc;
1535 targetPowerValT2[ALL_TARGET_HT40_6] =
1536 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1537 is2GHz) + ht40PowerIncForPdadc;
1538 targetPowerValT2[ALL_TARGET_HT40_7] =
1539 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1540 is2GHz) + ht40PowerIncForPdadc;
1541 targetPowerValT2[ALL_TARGET_HT40_12] =
1542 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1543 is2GHz) + ht40PowerIncForPdadc;
1544 targetPowerValT2[ALL_TARGET_HT40_13] =
1545 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1546 is2GHz) + ht40PowerIncForPdadc;
1547 targetPowerValT2[ALL_TARGET_HT40_14] =
1548 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1549 is2GHz) + ht40PowerIncForPdadc;
1550 targetPowerValT2[ALL_TARGET_HT40_15] =
1551 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1552 is2GHz) + ht40PowerIncForPdadc;
1553 targetPowerValT2[ALL_TARGET_HT40_20] =
1554 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1555 is2GHz) + ht40PowerIncForPdadc;
1556 targetPowerValT2[ALL_TARGET_HT40_21] =
1557 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1558 is2GHz) + ht40PowerIncForPdadc;
1559 targetPowerValT2[ALL_TARGET_HT40_22] =
1560 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1561 is2GHz) + ht40PowerIncForPdadc;
1562 targetPowerValT2[ALL_TARGET_HT40_23] =
1563 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1564 is2GHz) + ht40PowerIncForPdadc;
1566 while (i < ar9300RateSize) {
1567 ath_print(common, ATH_DBG_EEPROM,
1568 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1571 ath_print(common, ATH_DBG_EEPROM,
1572 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1575 ath_print(common, ATH_DBG_EEPROM,
1576 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1579 ath_print(common, ATH_DBG_EEPROM,
1580 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1585 static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1591 int *ptemperature, int *pvoltage)
1594 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1596 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1597 struct ath_common *common = ath9k_hw_common(ah);
1599 if (ichain >= AR9300_MAX_CHAINS) {
1600 ath_print(common, ATH_DBG_EEPROM,
1601 "Invalid chain index, must be less than %d\n",
1606 if (mode) { /* 5GHz */
1607 if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
1608 ath_print(common, ATH_DBG_EEPROM,
1609 "Invalid 5GHz cal pier index, must "
1610 "be less than %d\n",
1611 AR9300_NUM_5G_CAL_PIERS);
1614 pCalPier = &(eep->calFreqPier5G[ipier]);
1615 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1618 if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
1619 ath_print(common, ATH_DBG_EEPROM,
1620 "Invalid 2GHz cal pier index, must "
1621 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
1625 pCalPier = &(eep->calFreqPier2G[ipier]);
1626 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1630 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1631 *pcorrection = pCalPierStruct->refPower;
1632 *ptemperature = pCalPierStruct->tempMeas;
1633 *pvoltage = pCalPierStruct->voltMeas;
1638 static int ar9003_hw_power_control_override(struct ath_hw *ah,
1641 int *voltage, int *temperature)
1644 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1646 REG_RMW(ah, AR_PHY_TPC_11_B0,
1647 (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1648 AR_PHY_TPC_OLPC_GAIN_DELTA);
1649 REG_RMW(ah, AR_PHY_TPC_11_B1,
1650 (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1651 AR_PHY_TPC_OLPC_GAIN_DELTA);
1652 REG_RMW(ah, AR_PHY_TPC_11_B2,
1653 (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1654 AR_PHY_TPC_OLPC_GAIN_DELTA);
1656 /* enable open loop power control on chip */
1657 REG_RMW(ah, AR_PHY_TPC_6_B0,
1658 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1659 AR_PHY_TPC_6_ERROR_EST_MODE);
1660 REG_RMW(ah, AR_PHY_TPC_6_B1,
1661 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1662 AR_PHY_TPC_6_ERROR_EST_MODE);
1663 REG_RMW(ah, AR_PHY_TPC_6_B2,
1664 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1665 AR_PHY_TPC_6_ERROR_EST_MODE);
1668 * enable temperature compensation
1669 * Need to use register names
1671 if (frequency < 4000)
1672 tempSlope = eep->modalHeader2G.tempSlope;
1674 tempSlope = eep->modalHeader5G.tempSlope;
1676 REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
1677 REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
1683 /* Apply the recorded correction values. */
1684 static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1686 int ichain, ipier, npier;
1688 int lfrequency[AR9300_MAX_CHAINS],
1689 lcorrection[AR9300_MAX_CHAINS],
1690 ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
1691 int hfrequency[AR9300_MAX_CHAINS],
1692 hcorrection[AR9300_MAX_CHAINS],
1693 htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
1695 int correction[AR9300_MAX_CHAINS],
1696 voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
1697 int pfrequency, pcorrection, ptemperature, pvoltage;
1698 struct ath_common *common = ath9k_hw_common(ah);
1700 mode = (frequency >= 4000);
1702 npier = AR9300_NUM_5G_CAL_PIERS;
1704 npier = AR9300_NUM_2G_CAL_PIERS;
1706 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1707 lfrequency[ichain] = 0;
1708 hfrequency[ichain] = 100000;
1710 /* identify best lower and higher frequency calibration measurement */
1711 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1712 for (ipier = 0; ipier < npier; ipier++) {
1713 if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
1714 &pfrequency, &pcorrection,
1715 &ptemperature, &pvoltage)) {
1716 fdiff = frequency - pfrequency;
1719 * this measurement is higher than
1720 * our desired frequency
1723 if (hfrequency[ichain] <= 0 ||
1724 hfrequency[ichain] >= 100000 ||
1726 (frequency - hfrequency[ichain])) {
1729 * frequency measurement
1731 hfrequency[ichain] = pfrequency;
1732 hcorrection[ichain] =
1734 htemperature[ichain] =
1736 hvoltage[ichain] = pvoltage;
1740 if (lfrequency[ichain] <= 0
1742 (frequency - lfrequency[ichain])) {
1745 * frequency measurement
1747 lfrequency[ichain] = pfrequency;
1748 lcorrection[ichain] =
1750 ltemperature[ichain] =
1752 lvoltage[ichain] = pvoltage;
1760 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1761 ath_print(common, ATH_DBG_EEPROM,
1762 "ch=%d f=%d low=%d %d h=%d %d\n",
1763 ichain, frequency, lfrequency[ichain],
1764 lcorrection[ichain], hfrequency[ichain],
1765 hcorrection[ichain]);
1766 /* they're the same, so just pick one */
1767 if (hfrequency[ichain] == lfrequency[ichain]) {
1768 correction[ichain] = lcorrection[ichain];
1769 voltage[ichain] = lvoltage[ichain];
1770 temperature[ichain] = ltemperature[ichain];
1772 /* the low frequency is good */
1773 else if (frequency - lfrequency[ichain] < 1000) {
1774 /* so is the high frequency, interpolate */
1775 if (hfrequency[ichain] - frequency < 1000) {
1777 correction[ichain] = lcorrection[ichain] +
1778 (((frequency - lfrequency[ichain]) *
1779 (hcorrection[ichain] -
1780 lcorrection[ichain])) /
1781 (hfrequency[ichain] - lfrequency[ichain]));
1783 temperature[ichain] = ltemperature[ichain] +
1784 (((frequency - lfrequency[ichain]) *
1785 (htemperature[ichain] -
1786 ltemperature[ichain])) /
1787 (hfrequency[ichain] - lfrequency[ichain]));
1792 lfrequency[ichain]) * (hvoltage[ichain] -
1794 / (hfrequency[ichain] -
1795 lfrequency[ichain]));
1797 /* only low is good, use it */
1799 correction[ichain] = lcorrection[ichain];
1800 temperature[ichain] = ltemperature[ichain];
1801 voltage[ichain] = lvoltage[ichain];
1804 /* only high is good, use it */
1805 else if (hfrequency[ichain] - frequency < 1000) {
1806 correction[ichain] = hcorrection[ichain];
1807 temperature[ichain] = htemperature[ichain];
1808 voltage[ichain] = hvoltage[ichain];
1809 } else { /* nothing is good, presume 0???? */
1810 correction[ichain] = 0;
1811 temperature[ichain] = 0;
1812 voltage[ichain] = 0;
1816 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1819 ath_print(common, ATH_DBG_EEPROM,
1820 "for frequency=%d, calibration correction = %d %d %d\n",
1821 frequency, correction[0], correction[1], correction[2]);
1826 static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
1831 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1832 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1835 return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge]);
1837 return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge]);
1840 static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
1846 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1847 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1849 u8 *ctl_freqbin = is2GHz ?
1850 &eep->ctl_freqbin_2G[idx][0] :
1851 &eep->ctl_freqbin_5G[idx][0];
1854 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
1855 CTL_EDGE_FLAGS(ctl_2g[idx].ctlEdges[edge - 1]))
1856 return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge - 1]);
1858 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
1859 CTL_EDGE_FLAGS(ctl_5g[idx].ctlEdges[edge - 1]))
1860 return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
1863 return AR9300_MAX_RATE_POWER;
1867 * Find the maximum conformance test limit for the given channel and CTL info
1869 static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
1870 u16 freq, int idx, bool is2GHz)
1872 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1873 u8 *ctl_freqbin = is2GHz ?
1874 &eep->ctl_freqbin_2G[idx][0] :
1875 &eep->ctl_freqbin_5G[idx][0];
1876 u16 num_edges = is2GHz ?
1877 AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G;
1880 /* Get the edge power */
1882 (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
1885 * If there's an exact channel match or an inband flag set
1886 * on the lower channel use the given rdEdgePower
1888 if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
1890 ar9003_hw_get_direct_edge_power(eep, idx,
1893 } else if ((edge > 0) &&
1894 (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
1897 ar9003_hw_get_indirect_edge_power(eep, idx,
1901 * Leave loop - no more affecting edges possible in
1902 * this monotonic increasing list
1907 return twiceMaxEdgePower;
1910 static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
1911 struct ath9k_channel *chan,
1912 u8 *pPwrArray, u16 cfgCtl,
1913 u8 twiceAntennaReduction,
1914 u8 twiceMaxRegulatoryPower,
1917 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
1918 struct ath_common *common = ath9k_hw_common(ah);
1919 struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
1920 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1921 static const u16 tpScaleReductionTable[5] = {
1922 0, 3, 6, 9, AR9300_MAX_RATE_POWER
1925 int16_t twiceLargestAntenna;
1926 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
1927 u16 ctlModesFor11a[] = {
1928 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
1930 u16 ctlModesFor11g[] = {
1931 CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
1932 CTL_11G_EXT, CTL_2GHT40
1934 u16 numCtlModes, *pCtlMode, ctlMode, freq;
1935 struct chan_centers centers;
1938 u16 twiceMinEdgePower;
1939 bool is2ghz = IS_CHAN_2GHZ(chan);
1941 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
1943 /* Compute TxPower reduction due to Antenna Gain */
1945 twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
1947 twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
1949 twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
1950 twiceLargestAntenna, 0);
1953 * scaledPower is the minimum of the user input power level
1954 * and the regulatory allowed power level
1956 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
1958 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
1959 maxRegAllowedPower -=
1960 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
1963 scaledPower = min(powerLimit, maxRegAllowedPower);
1966 * Reduce scaled Power by number of chains active to get
1967 * to per chain tx power level
1969 switch (ar5416_get_ntxchains(ah->txchainmask)) {
1973 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1976 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1980 scaledPower = max((u16)0, scaledPower);
1983 * Get target powers from EEPROM - our baseline for TX Power
1986 /* Setup for CTL modes */
1987 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1989 ARRAY_SIZE(ctlModesFor11g) -
1990 SUB_NUM_CTL_MODES_AT_2G_40;
1991 pCtlMode = ctlModesFor11g;
1992 if (IS_CHAN_HT40(chan))
1994 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
1996 /* Setup for CTL modes */
1997 /* CTL_11A, CTL_5GHT20 */
1998 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
1999 SUB_NUM_CTL_MODES_AT_5G_40;
2000 pCtlMode = ctlModesFor11a;
2001 if (IS_CHAN_HT40(chan))
2003 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
2007 * For MIMO, need to apply regulatory caps individually across
2008 * dynamically running modes: CCK, OFDM, HT20, HT40
2010 * The outer loop walks through each possible applicable runtime mode.
2011 * The inner loop walks through each ctlIndex entry in EEPROM.
2012 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2014 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2015 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2016 (pCtlMode[ctlMode] == CTL_2GHT40);
2018 freq = centers.synth_center;
2019 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2020 freq = centers.ext_center;
2022 freq = centers.ctl_center;
2024 ath_print(common, ATH_DBG_REGULATORY,
2025 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2026 "EXT_ADDITIVE %d\n",
2027 ctlMode, numCtlModes, isHt40CtlMode,
2028 (pCtlMode[ctlMode] & EXT_ADDITIVE));
2030 /* walk through each CTL index stored in EEPROM */
2032 ctlIndex = pEepData->ctlIndex_2G;
2033 ctlNum = AR9300_NUM_CTLS_2G;
2035 ctlIndex = pEepData->ctlIndex_5G;
2036 ctlNum = AR9300_NUM_CTLS_5G;
2039 for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
2040 ath_print(common, ATH_DBG_REGULATORY,
2041 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2042 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2044 i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
2048 * compare test group from regulatory
2049 * channel list with test mode from pCtlMode
2052 if ((((cfgCtl & ~CTL_MODE_M) |
2053 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2055 (((cfgCtl & ~CTL_MODE_M) |
2056 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2057 ((ctlIndex[i] & CTL_MODE_M) |
2060 ar9003_hw_get_max_edge_power(pEepData,
2064 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
2066 * Find the minimum of all CTL
2067 * edge powers that apply to
2071 min(twiceMaxEdgePower,
2082 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
2084 ath_print(common, ATH_DBG_REGULATORY,
2085 "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
2086 "sP %d minCtlPwr %d\n",
2087 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
2088 scaledPower, minCtlPower);
2090 /* Apply ctl mode to correct target power set */
2091 switch (pCtlMode[ctlMode]) {
2093 for (i = ALL_TARGET_LEGACY_1L_5L;
2094 i <= ALL_TARGET_LEGACY_11S; i++)
2096 (u8)min((u16)pPwrArray[i],
2101 for (i = ALL_TARGET_LEGACY_6_24;
2102 i <= ALL_TARGET_LEGACY_54; i++)
2104 (u8)min((u16)pPwrArray[i],
2109 for (i = ALL_TARGET_HT20_0_8_16;
2110 i <= ALL_TARGET_HT20_21; i++)
2112 (u8)min((u16)pPwrArray[i],
2114 pPwrArray[ALL_TARGET_HT20_22] =
2115 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
2117 pPwrArray[ALL_TARGET_HT20_23] =
2118 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
2123 for (i = ALL_TARGET_HT40_0_8_16;
2124 i <= ALL_TARGET_HT40_23; i++)
2126 (u8)min((u16)pPwrArray[i],
2132 } /* end ctl mode checking */
2135 static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
2136 struct ath9k_channel *chan, u16 cfgCtl,
2137 u8 twiceAntennaReduction,
2138 u8 twiceMaxRegulatoryPower,
2141 struct ath_common *common = ath9k_hw_common(ah);
2142 u8 targetPowerValT2[ar9300RateSize];
2145 ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
2146 ar9003_hw_set_power_per_rate_table(ah, chan,
2147 targetPowerValT2, cfgCtl,
2148 twiceAntennaReduction,
2149 twiceMaxRegulatoryPower,
2152 while (i < ar9300RateSize) {
2153 ath_print(common, ATH_DBG_EEPROM,
2154 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2156 ath_print(common, ATH_DBG_EEPROM,
2157 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2159 ath_print(common, ATH_DBG_EEPROM,
2160 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2162 ath_print(common, ATH_DBG_EEPROM,
2163 "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
2167 /* Write target power array to registers */
2168 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
2171 * This is the TX power we send back to driver core,
2172 * and it can use to pass to userspace to display our
2173 * currently configured TX power setting.
2175 * Since power is rate dependent, use one of the indices
2176 * from the AR9300_Rates enum to select an entry from
2177 * targetPowerValT2[] to report. Currently returns the
2178 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
2179 * as CCK power is less interesting (?).
2181 i = ALL_TARGET_LEGACY_6_24; /* legacy */
2182 if (IS_CHAN_HT40(chan))
2183 i = ALL_TARGET_HT40_0_8_16; /* ht40 */
2184 else if (IS_CHAN_HT20(chan))
2185 i = ALL_TARGET_HT20_0_8_16; /* ht20 */
2187 ah->txpower_limit = targetPowerValT2[i];
2189 ar9003_hw_calibration_apply(ah, chan->channel);
2192 static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
2198 s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
2200 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2202 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
2205 s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
2207 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2209 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
2212 const struct eeprom_ops eep_ar9300_ops = {
2213 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
2214 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
2215 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
2216 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
2217 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
2218 .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
2219 .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
2220 .set_board_values = ath9k_hw_ar9300_set_board_values,
2221 .set_addac = ath9k_hw_ar9300_set_addac,
2222 .set_txpower = ath9k_hw_ar9300_set_txpower,
2223 .get_spur_channel = ath9k_hw_ar9300_get_spur_channel