GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / net / wireless / ath / ath9k / ar9003_eeprom.c
blob275b7f575385cce007d7f6e1177da104f632a54d
1 /*
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.
17 #include "hw.h"
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 = {
63 .eepromVersion = 2,
64 .templateVersion = 2,
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},
68 .baseEepHeader = {
69 .regDmn = { LE16(0), LE16(0x1f) },
70 .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
71 .opCapFlags = {
72 .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
73 .eepMisc = 0,
75 .rfSilent = 0,
76 .blueToothOptions = 0,
77 .deviceCap = 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,
92 .wlanDisableGpio = 0,
93 .wlanLedGpio = 8,
94 .rxBandSelectGpio = 0xff,
95 .txrxgain = 0,
96 .swreg = 0,
98 .modalHeader2G = {
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},
122 .tempSlope = 36,
123 .voltSlope = 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},
140 .xpaBiasLvl = 0,
141 .txFrameToDataStart = 0x0e,
142 .txFrameToPaOn = 0x0e,
143 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
144 .antennaGain = 0,
145 .switchSettling = 0x2c,
146 .adcDesiredSize = -30,
147 .txEndToXpaOff = 0,
148 .txEndToRxOn = 0x2,
149 .txFrameToXpaOn = 0xe,
150 .thresh62 = 28,
151 .papdRateMaskHt20 = LE32(0x80c080),
152 .papdRateMaskHt40 = LE32(0x80c080),
153 .futureModal = {
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
158 .calFreqPier2G = {
159 FREQ2FBIN(2412, 1),
160 FREQ2FBIN(2437, 1),
161 FREQ2FBIN(2472, 1),
163 /* ar9300_cal_data_per_freq_op_loop 2g */
164 .calPierData2G = {
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 = {
170 FREQ2FBIN(2412, 1),
171 FREQ2FBIN(2484, 1),
173 .calTarget_freqbin_2G = {
174 FREQ2FBIN(2412, 1),
175 FREQ2FBIN(2437, 1),
176 FREQ2FBIN(2472, 1)
178 .calTarget_freqbin_2GHT20 = {
179 FREQ2FBIN(2412, 1),
180 FREQ2FBIN(2437, 1),
181 FREQ2FBIN(2472, 1)
183 .calTarget_freqbin_2GHT40 = {
184 FREQ2FBIN(2412, 1),
185 FREQ2FBIN(2437, 1),
186 FREQ2FBIN(2472, 1)
188 .calTargetPowerCck = {
189 /* 1L-5L,5S,11L,11S */
190 { {36, 36, 36, 36} },
191 { {36, 36, 36, 36} },
193 .calTargetPower2G = {
194 /* 6-24,36,48,54 */
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} },
209 .ctlIndex_2G = {
210 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
211 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
213 .ctl_freqbin_2G = {
215 FREQ2FBIN(2412, 1),
216 FREQ2FBIN(2417, 1),
217 FREQ2FBIN(2457, 1),
218 FREQ2FBIN(2462, 1)
221 FREQ2FBIN(2412, 1),
222 FREQ2FBIN(2417, 1),
223 FREQ2FBIN(2462, 1),
224 0xFF,
228 FREQ2FBIN(2412, 1),
229 FREQ2FBIN(2417, 1),
230 FREQ2FBIN(2462, 1),
231 0xFF,
234 FREQ2FBIN(2422, 1),
235 FREQ2FBIN(2427, 1),
236 FREQ2FBIN(2447, 1),
237 FREQ2FBIN(2452, 1)
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),
257 FREQ2FBIN(2472, 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 */
293 FREQ2FBIN(2462, 1),
296 .ctlPowerData_2G = {
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) } },
313 .modalHeader5G = {
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) */
319 .antCtrlChain = {
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},
330 .tempSlope = 68,
331 .voltSlope = 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 */
340 .xpaBiasLvl = 0,
341 .txFrameToDataStart = 0x0e,
342 .txFrameToPaOn = 0x0e,
343 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
344 .antennaGain = 0,
345 .switchSettling = 0x2d,
346 .adcDesiredSize = -30,
347 .txEndToXpaOff = 0,
348 .txEndToRxOn = 0x2,
349 .txFrameToXpaOn = 0xe,
350 .thresh62 = 28,
351 .papdRateMaskHt20 = LE32(0xf0e0e0),
352 .papdRateMaskHt40 = LE32(0xf0e0e0),
353 .futureModal = {
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
358 .calFreqPier5G = {
359 FREQ2FBIN(5180, 0),
360 FREQ2FBIN(5220, 0),
361 FREQ2FBIN(5320, 0),
362 FREQ2FBIN(5400, 0),
363 FREQ2FBIN(5500, 0),
364 FREQ2FBIN(5600, 0),
365 FREQ2FBIN(5725, 0),
366 FREQ2FBIN(5825, 0)
368 .calPierData5G = {
370 {0, 0, 0, 0, 0},
371 {0, 0, 0, 0, 0},
372 {0, 0, 0, 0, 0},
373 {0, 0, 0, 0, 0},
374 {0, 0, 0, 0, 0},
375 {0, 0, 0, 0, 0},
376 {0, 0, 0, 0, 0},
377 {0, 0, 0, 0, 0},
380 {0, 0, 0, 0, 0},
381 {0, 0, 0, 0, 0},
382 {0, 0, 0, 0, 0},
383 {0, 0, 0, 0, 0},
384 {0, 0, 0, 0, 0},
385 {0, 0, 0, 0, 0},
386 {0, 0, 0, 0, 0},
387 {0, 0, 0, 0, 0},
390 {0, 0, 0, 0, 0},
391 {0, 0, 0, 0, 0},
392 {0, 0, 0, 0, 0},
393 {0, 0, 0, 0, 0},
394 {0, 0, 0, 0, 0},
395 {0, 0, 0, 0, 0},
396 {0, 0, 0, 0, 0},
397 {0, 0, 0, 0, 0},
401 .calTarget_freqbin_5G = {
402 FREQ2FBIN(5180, 0),
403 FREQ2FBIN(5220, 0),
404 FREQ2FBIN(5320, 0),
405 FREQ2FBIN(5400, 0),
406 FREQ2FBIN(5500, 0),
407 FREQ2FBIN(5600, 0),
408 FREQ2FBIN(5725, 0),
409 FREQ2FBIN(5825, 0)
411 .calTarget_freqbin_5GHT20 = {
412 FREQ2FBIN(5180, 0),
413 FREQ2FBIN(5240, 0),
414 FREQ2FBIN(5320, 0),
415 FREQ2FBIN(5500, 0),
416 FREQ2FBIN(5700, 0),
417 FREQ2FBIN(5745, 0),
418 FREQ2FBIN(5725, 0),
419 FREQ2FBIN(5825, 0)
421 .calTarget_freqbin_5GHT40 = {
422 FREQ2FBIN(5180, 0),
423 FREQ2FBIN(5240, 0),
424 FREQ2FBIN(5320, 0),
425 FREQ2FBIN(5500, 0),
426 FREQ2FBIN(5700, 0),
427 FREQ2FBIN(5745, 0),
428 FREQ2FBIN(5725, 0),
429 FREQ2FBIN(5825, 0)
431 .calTargetPower5G = {
432 /* 6-24,36,48,54 */
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} },
470 .ctlIndex_5G = {
471 0x10, 0x16, 0x18, 0x40, 0x46,
472 0x48, 0x30, 0x36, 0x38
474 .ctl_freqbin_5G = {
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)
573 .ctlPowerData_5G = {
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)
634 return fbin;
636 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
639 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
641 return 0;
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;
650 switch (param) {
651 case EEP_MAC_LSW:
652 return eep->macAddr[0] << 8 | eep->macAddr[1];
653 case EEP_MAC_MID:
654 return eep->macAddr[2] << 8 | eep->macAddr[3];
655 case EEP_MAC_MSW:
656 return eep->macAddr[4] << 8 | eep->macAddr[5];
657 case EEP_REG_0:
658 return le16_to_cpu(pBase->regDmn[0]);
659 case EEP_REG_1:
660 return le16_to_cpu(pBase->regDmn[1]);
661 case EEP_OP_CAP:
662 return pBase->deviceCap;
663 case EEP_OP_MODE:
664 return pBase->opCapFlags.opFlags;
665 case EEP_RF_SILENT:
666 return pBase->rfSilent;
667 case EEP_TX_MASK:
668 return (pBase->txrxMask >> 4) & 0xf;
669 case EEP_RX_MASK:
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;
677 case EEP_SWREG:
678 return le32_to_cpu(pBase->swreg);
679 case EEP_PAPRD:
680 return !!(pBase->featureEnable & BIT(5));
681 default:
682 return 0;
686 static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
687 u8 *buffer)
689 u16 val;
691 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
692 return false;
694 *buffer = (val >> (8 * (address % 2))) & 0xff;
695 return true;
698 static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
699 u8 *buffer)
701 u16 val;
703 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
704 return false;
706 buffer[0] = val >> 8;
707 buffer[1] = val & 0xff;
709 return true;
712 static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
713 int count)
715 struct ath_common *common = ath9k_hw_common(ah);
716 int i;
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");
721 return false;
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++))
731 goto error;
733 count--;
736 for (i = 0; i < count / 2; i++) {
737 if (!ar9300_eeprom_read_word(common, address, buffer))
738 goto error;
740 address -= 2;
741 buffer += 2;
744 if (count % 2)
745 if (!ar9300_eeprom_read_byte(common, address, buffer))
746 goto error;
748 return true;
750 error:
751 ath_print(common, ATH_DBG_EEPROM,
752 "unable to read eeprom region at offset %d\n", address);
753 return false;
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];
761 value[0] = best[0];
762 value[1] = best[1];
763 value[2] = best[2];
764 value[3] = best[3];
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];
778 checksum &= 0xffff;
781 return checksum;
784 static bool ar9300_uncompress_block(struct ath_hw *ah,
785 u8 *mptr,
786 int mdataSize,
787 u8 *block,
788 int size)
790 int it;
791 int spot;
792 int offset;
793 int length;
794 struct ath_common *common = ath9k_hw_common(ah);
796 spot = 0;
798 for (it = 0; it < size; it += (length+2)) {
799 offset = block[it];
800 offset &= 0xff;
801 spot += offset;
802 length = block[it+1];
803 length &= 0xff;
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);
811 spot += 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);
817 return false;
820 return true;
823 static int ar9300_compress_decision(struct ath_hw *ah,
824 int it,
825 int code,
826 int reference,
827 u8 *mptr,
828 u8 *word, int length, int mdata_size)
830 struct ath_common *common = ath9k_hw_common(ah);
831 u8 *dptr;
833 switch (code) {
834 case _CompressNone:
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);
839 return -1;
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);
844 break;
845 case _CompressBlock:
846 if (reference == 0) {
847 dptr = mptr;
848 } else {
849 if (reference != 2) {
850 ath_print(common, ATH_DBG_EEPROM,
851 "cant find reference eeprom"
852 "struct %d\n", reference);
853 return -1;
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);
862 break;
863 default:
864 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
865 " code %d\n", code);
866 return -1;
868 return 0;
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)
881 #define MDEFAULT 15
882 #define MSTATE 100
883 int cptr;
884 u8 *word;
885 int code;
886 int reference, length, major, minor;
887 int osize;
888 int it;
889 u16 checksum, mchecksum;
890 struct ath_common *common = ath9k_hw_common(ah);
892 word = kzalloc(2048, GFP_KERNEL);
893 if (!word)
894 return -1;
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))
901 goto fail;
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))
906 break;
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;
918 continue;
921 osize = length;
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);
932 } else {
933 ath_print(common, ATH_DBG_EEPROM,
934 "skipping block with bad checksum\n");
936 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
939 kfree(word);
940 return cptr;
942 fail:
943 kfree(word);
944 return -1;
948 * Restore the configuration structure by reading the eeprom.
949 * This function destroys any existing in-memory structure
950 * content.
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)
958 return false;
960 return true;
963 static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
965 return ah->eeprom.ar9300_eep.eepromVersion;
968 static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
970 return 0;
973 static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
974 enum ieee80211_band freq_band)
976 return 1;
979 static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
980 struct ath9k_channel *chan)
982 return -EINVAL;
985 static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
987 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
989 if (is2ghz)
990 return eep->modalHeader2G.xpaBiasLvl;
991 else
992 return eep->modalHeader5G.xpaBiasLvl;
995 static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
997 int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
998 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
999 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, bias >> 2);
1000 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1);
1003 static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
1005 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1006 __le32 val;
1008 if (is2ghz)
1009 val = eep->modalHeader2G.antCtrlCommon;
1010 else
1011 val = eep->modalHeader5G.antCtrlCommon;
1012 return le32_to_cpu(val);
1015 static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
1017 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1018 __le32 val;
1020 if (is2ghz)
1021 val = eep->modalHeader2G.antCtrlCommon2;
1022 else
1023 val = eep->modalHeader5G.antCtrlCommon2;
1024 return le32_to_cpu(val);
1027 static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1028 int chain,
1029 bool is2ghz)
1031 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1032 __le16 val = 0;
1034 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1035 if (is2ghz)
1036 val = eep->modalHeader2G.antCtrlChain[chain];
1037 else
1038 val = eep->modalHeader5G.antCtrlChain[chain];
1041 return le16_to_cpu(val);
1044 static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1046 u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
1047 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
1049 value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
1050 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1052 value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
1053 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1055 value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
1056 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1058 value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
1059 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1062 static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1064 int drive_strength;
1065 unsigned long reg;
1067 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1069 if (!drive_strength)
1070 return;
1072 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1073 reg &= ~0x00ffffc0;
1074 reg |= 0x5 << 21;
1075 reg |= 0x5 << 18;
1076 reg |= 0x5 << 15;
1077 reg |= 0x5 << 12;
1078 reg |= 0x5 << 9;
1079 reg |= 0x5 << 6;
1080 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1082 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1083 reg &= ~0xffffffe0;
1084 reg |= 0x5 << 29;
1085 reg |= 0x5 << 26;
1086 reg |= 0x5 << 23;
1087 reg |= 0x5 << 20;
1088 reg |= 0x5 << 17;
1089 reg |= 0x5 << 14;
1090 reg |= 0x5 << 11;
1091 reg |= 0x5 << 8;
1092 reg |= 0x5 << 5;
1093 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1095 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1096 reg &= ~0xff800000;
1097 reg |= 0x5 << 29;
1098 reg |= 0x5 << 26;
1099 reg |= 0x5 << 23;
1100 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1103 static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1105 int internal_regulator =
1106 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1108 if (internal_regulator) {
1109 /* Internal regulator is ON. Write swreg register. */
1110 int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
1111 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1112 REG_READ(ah, AR_RTC_REG_CONTROL1) &
1113 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1114 REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1115 /* Set REG_CONTROL1.SWREG_PROGRAM */
1116 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1117 REG_READ(ah,
1118 AR_RTC_REG_CONTROL1) |
1119 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1120 } else {
1121 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1122 (REG_READ(ah,
1123 AR_RTC_SLEEP_CLK) |
1124 AR_RTC_FORCE_SWREG_PRD));
1128 static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1129 struct ath9k_channel *chan)
1131 ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
1132 ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
1133 ar9003_hw_drive_strength_apply(ah);
1134 ar9003_hw_internal_regulator_apply(ah);
1137 static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1138 struct ath9k_channel *chan)
1143 * Returns the interpolated y value corresponding to the specified x value
1144 * from the np ordered pairs of data (px,py).
1145 * The pairs do not have to be in any order.
1146 * If the specified x value is less than any of the px,
1147 * the returned y value is equal to the py for the lowest px.
1148 * If the specified x value is greater than any of the px,
1149 * the returned y value is equal to the py for the highest px.
1151 static int ar9003_hw_power_interpolate(int32_t x,
1152 int32_t *px, int32_t *py, u_int16_t np)
1154 int ip = 0;
1155 int lx = 0, ly = 0, lhave = 0;
1156 int hx = 0, hy = 0, hhave = 0;
1157 int dx = 0;
1158 int y = 0;
1160 lhave = 0;
1161 hhave = 0;
1163 /* identify best lower and higher x calibration measurement */
1164 for (ip = 0; ip < np; ip++) {
1165 dx = x - px[ip];
1167 /* this measurement is higher than our desired x */
1168 if (dx <= 0) {
1169 if (!hhave || dx > (x - hx)) {
1170 /* new best higher x measurement */
1171 hx = px[ip];
1172 hy = py[ip];
1173 hhave = 1;
1176 /* this measurement is lower than our desired x */
1177 if (dx >= 0) {
1178 if (!lhave || dx < (x - lx)) {
1179 /* new best lower x measurement */
1180 lx = px[ip];
1181 ly = py[ip];
1182 lhave = 1;
1187 /* the low x is good */
1188 if (lhave) {
1189 /* so is the high x */
1190 if (hhave) {
1191 /* they're the same, so just pick one */
1192 if (hx == lx)
1193 y = ly;
1194 else /* interpolate */
1195 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1196 } else /* only low is good, use it */
1197 y = ly;
1198 } else if (hhave) /* only high is good, use it */
1199 y = hy;
1200 else /* nothing is good,this should never happen unless np=0, ???? */
1201 y = -(1 << 30);
1202 return y;
1205 static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1206 u16 rateIndex, u16 freq, bool is2GHz)
1208 u16 numPiers, i;
1209 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1210 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1211 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1212 struct cal_tgt_pow_legacy *pEepromTargetPwr;
1213 u8 *pFreqBin;
1215 if (is2GHz) {
1216 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1217 pEepromTargetPwr = eep->calTargetPower2G;
1218 pFreqBin = eep->calTarget_freqbin_2G;
1219 } else {
1220 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1221 pEepromTargetPwr = eep->calTargetPower5G;
1222 pFreqBin = eep->calTarget_freqbin_5G;
1226 * create array of channels and targetpower from
1227 * targetpower piers stored on eeprom
1229 for (i = 0; i < numPiers; i++) {
1230 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1231 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1234 /* interpolate to get target power for given frequency */
1235 return (u8) ar9003_hw_power_interpolate((s32) freq,
1236 freqArray,
1237 targetPowerArray, numPiers);
1240 static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1241 u16 rateIndex,
1242 u16 freq, bool is2GHz)
1244 u16 numPiers, i;
1245 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1246 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1247 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1248 struct cal_tgt_pow_ht *pEepromTargetPwr;
1249 u8 *pFreqBin;
1251 if (is2GHz) {
1252 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
1253 pEepromTargetPwr = eep->calTargetPower2GHT20;
1254 pFreqBin = eep->calTarget_freqbin_2GHT20;
1255 } else {
1256 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1257 pEepromTargetPwr = eep->calTargetPower5GHT20;
1258 pFreqBin = eep->calTarget_freqbin_5GHT20;
1262 * create array of channels and targetpower
1263 * from targetpower piers stored on eeprom
1265 for (i = 0; i < numPiers; i++) {
1266 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1267 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1270 /* interpolate to get target power for given frequency */
1271 return (u8) ar9003_hw_power_interpolate((s32) freq,
1272 freqArray,
1273 targetPowerArray, numPiers);
1276 static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1277 u16 rateIndex,
1278 u16 freq, bool is2GHz)
1280 u16 numPiers, i;
1281 s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
1282 s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
1283 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1284 struct cal_tgt_pow_ht *pEepromTargetPwr;
1285 u8 *pFreqBin;
1287 if (is2GHz) {
1288 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1289 pEepromTargetPwr = eep->calTargetPower2GHT40;
1290 pFreqBin = eep->calTarget_freqbin_2GHT40;
1291 } else {
1292 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1293 pEepromTargetPwr = eep->calTargetPower5GHT40;
1294 pFreqBin = eep->calTarget_freqbin_5GHT40;
1298 * create array of channels and targetpower from
1299 * targetpower piers stored on eeprom
1301 for (i = 0; i < numPiers; i++) {
1302 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1303 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1306 /* interpolate to get target power for given frequency */
1307 return (u8) ar9003_hw_power_interpolate((s32) freq,
1308 freqArray,
1309 targetPowerArray, numPiers);
1312 static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1313 u16 rateIndex, u16 freq)
1315 u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
1316 s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1317 s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1318 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1319 struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
1320 u8 *pFreqBin = eep->calTarget_freqbin_Cck;
1323 * create array of channels and targetpower from
1324 * targetpower piers stored on eeprom
1326 for (i = 0; i < numPiers; i++) {
1327 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1328 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1331 /* interpolate to get target power for given frequency */
1332 return (u8) ar9003_hw_power_interpolate((s32) freq,
1333 freqArray,
1334 targetPowerArray, numPiers);
1337 /* Set tx power registers to array of values passed in */
1338 static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1340 #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1341 /* make sure forced gain is not set */
1342 REG_WRITE(ah, 0xa458, 0);
1344 /* Write the OFDM power per rate set */
1346 /* 6 (LSB), 9, 12, 18 (MSB) */
1347 REG_WRITE(ah, 0xa3c0,
1348 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
1349 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
1350 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
1351 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1353 /* 24 (LSB), 36, 48, 54 (MSB) */
1354 REG_WRITE(ah, 0xa3c4,
1355 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
1356 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
1357 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
1358 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1360 /* Write the CCK power per rate set */
1362 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1363 REG_WRITE(ah, 0xa3c8,
1364 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
1365 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
1366 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1367 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
1369 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1370 REG_WRITE(ah, 0xa3cc,
1371 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
1372 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
1373 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
1374 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
1377 /* Write the HT20 power per rate set */
1379 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1380 REG_WRITE(ah, 0xa3d0,
1381 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
1382 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
1383 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
1384 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
1387 /* 6 (LSB), 7, 12, 13 (MSB) */
1388 REG_WRITE(ah, 0xa3d4,
1389 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
1390 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
1391 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
1392 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
1395 /* 14 (LSB), 15, 20, 21 */
1396 REG_WRITE(ah, 0xa3e4,
1397 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
1398 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
1399 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
1400 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
1403 /* Mixed HT20 and HT40 rates */
1405 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1406 REG_WRITE(ah, 0xa3e8,
1407 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
1408 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
1409 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
1410 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
1414 * Write the HT40 power per rate set
1415 * correct PAR difference between HT40 and HT20/LEGACY
1416 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1418 REG_WRITE(ah, 0xa3d8,
1419 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
1420 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
1421 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
1422 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
1425 /* 6 (LSB), 7, 12, 13 (MSB) */
1426 REG_WRITE(ah, 0xa3dc,
1427 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
1428 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
1429 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
1430 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
1433 /* 14 (LSB), 15, 20, 21 */
1434 REG_WRITE(ah, 0xa3ec,
1435 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
1436 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
1437 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
1438 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
1441 return 0;
1442 #undef POW_SM
1445 static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
1446 u8 *targetPowerValT2)
1448 u8 ht40PowerIncForPdadc = 0;
1449 bool is2GHz = false;
1450 unsigned int i = 0;
1451 struct ath_common *common = ath9k_hw_common(ah);
1453 if (freq < 4000)
1454 is2GHz = true;
1456 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1457 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1458 is2GHz);
1459 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1460 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1461 is2GHz);
1462 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1463 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1464 is2GHz);
1465 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1466 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1467 is2GHz);
1468 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1469 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1470 freq);
1471 targetPowerValT2[ALL_TARGET_LEGACY_5S] =
1472 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
1473 targetPowerValT2[ALL_TARGET_LEGACY_11L] =
1474 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
1475 targetPowerValT2[ALL_TARGET_LEGACY_11S] =
1476 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
1477 targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
1478 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1479 is2GHz);
1480 targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1481 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1482 freq, is2GHz);
1483 targetPowerValT2[ALL_TARGET_HT20_4] =
1484 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1485 is2GHz);
1486 targetPowerValT2[ALL_TARGET_HT20_5] =
1487 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1488 is2GHz);
1489 targetPowerValT2[ALL_TARGET_HT20_6] =
1490 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1491 is2GHz);
1492 targetPowerValT2[ALL_TARGET_HT20_7] =
1493 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1494 is2GHz);
1495 targetPowerValT2[ALL_TARGET_HT20_12] =
1496 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1497 is2GHz);
1498 targetPowerValT2[ALL_TARGET_HT20_13] =
1499 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1500 is2GHz);
1501 targetPowerValT2[ALL_TARGET_HT20_14] =
1502 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1503 is2GHz);
1504 targetPowerValT2[ALL_TARGET_HT20_15] =
1505 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1506 is2GHz);
1507 targetPowerValT2[ALL_TARGET_HT20_20] =
1508 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1509 is2GHz);
1510 targetPowerValT2[ALL_TARGET_HT20_21] =
1511 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1512 is2GHz);
1513 targetPowerValT2[ALL_TARGET_HT20_22] =
1514 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1515 is2GHz);
1516 targetPowerValT2[ALL_TARGET_HT20_23] =
1517 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1518 is2GHz);
1519 targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
1520 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1521 is2GHz) + ht40PowerIncForPdadc;
1522 targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1523 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1524 freq,
1525 is2GHz) + ht40PowerIncForPdadc;
1526 targetPowerValT2[ALL_TARGET_HT40_4] =
1527 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1528 is2GHz) + ht40PowerIncForPdadc;
1529 targetPowerValT2[ALL_TARGET_HT40_5] =
1530 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1531 is2GHz) + ht40PowerIncForPdadc;
1532 targetPowerValT2[ALL_TARGET_HT40_6] =
1533 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1534 is2GHz) + ht40PowerIncForPdadc;
1535 targetPowerValT2[ALL_TARGET_HT40_7] =
1536 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1537 is2GHz) + ht40PowerIncForPdadc;
1538 targetPowerValT2[ALL_TARGET_HT40_12] =
1539 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1540 is2GHz) + ht40PowerIncForPdadc;
1541 targetPowerValT2[ALL_TARGET_HT40_13] =
1542 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1543 is2GHz) + ht40PowerIncForPdadc;
1544 targetPowerValT2[ALL_TARGET_HT40_14] =
1545 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1546 is2GHz) + ht40PowerIncForPdadc;
1547 targetPowerValT2[ALL_TARGET_HT40_15] =
1548 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1549 is2GHz) + ht40PowerIncForPdadc;
1550 targetPowerValT2[ALL_TARGET_HT40_20] =
1551 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1552 is2GHz) + ht40PowerIncForPdadc;
1553 targetPowerValT2[ALL_TARGET_HT40_21] =
1554 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1555 is2GHz) + ht40PowerIncForPdadc;
1556 targetPowerValT2[ALL_TARGET_HT40_22] =
1557 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1558 is2GHz) + ht40PowerIncForPdadc;
1559 targetPowerValT2[ALL_TARGET_HT40_23] =
1560 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1561 is2GHz) + ht40PowerIncForPdadc;
1563 while (i < ar9300RateSize) {
1564 ath_print(common, ATH_DBG_EEPROM,
1565 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1566 i++;
1568 ath_print(common, ATH_DBG_EEPROM,
1569 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1570 i++;
1572 ath_print(common, ATH_DBG_EEPROM,
1573 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1574 i++;
1576 ath_print(common, ATH_DBG_EEPROM,
1577 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1578 i++;
1582 static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1583 int mode,
1584 int ipier,
1585 int ichain,
1586 int *pfrequency,
1587 int *pcorrection,
1588 int *ptemperature, int *pvoltage)
1590 u8 *pCalPier;
1591 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1592 int is2GHz;
1593 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1594 struct ath_common *common = ath9k_hw_common(ah);
1596 if (ichain >= AR9300_MAX_CHAINS) {
1597 ath_print(common, ATH_DBG_EEPROM,
1598 "Invalid chain index, must be less than %d\n",
1599 AR9300_MAX_CHAINS);
1600 return -1;
1603 if (mode) { /* 5GHz */
1604 if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
1605 ath_print(common, ATH_DBG_EEPROM,
1606 "Invalid 5GHz cal pier index, must "
1607 "be less than %d\n",
1608 AR9300_NUM_5G_CAL_PIERS);
1609 return -1;
1611 pCalPier = &(eep->calFreqPier5G[ipier]);
1612 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1613 is2GHz = 0;
1614 } else {
1615 if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
1616 ath_print(common, ATH_DBG_EEPROM,
1617 "Invalid 2GHz cal pier index, must "
1618 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
1619 return -1;
1622 pCalPier = &(eep->calFreqPier2G[ipier]);
1623 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1624 is2GHz = 1;
1627 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1628 *pcorrection = pCalPierStruct->refPower;
1629 *ptemperature = pCalPierStruct->tempMeas;
1630 *pvoltage = pCalPierStruct->voltMeas;
1632 return 0;
1635 static int ar9003_hw_power_control_override(struct ath_hw *ah,
1636 int frequency,
1637 int *correction,
1638 int *voltage, int *temperature)
1640 int tempSlope = 0;
1641 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1643 REG_RMW(ah, AR_PHY_TPC_11_B0,
1644 (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1645 AR_PHY_TPC_OLPC_GAIN_DELTA);
1646 REG_RMW(ah, AR_PHY_TPC_11_B1,
1647 (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1648 AR_PHY_TPC_OLPC_GAIN_DELTA);
1649 REG_RMW(ah, AR_PHY_TPC_11_B2,
1650 (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1651 AR_PHY_TPC_OLPC_GAIN_DELTA);
1653 /* enable open loop power control on chip */
1654 REG_RMW(ah, AR_PHY_TPC_6_B0,
1655 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1656 AR_PHY_TPC_6_ERROR_EST_MODE);
1657 REG_RMW(ah, AR_PHY_TPC_6_B1,
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_B2,
1661 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1662 AR_PHY_TPC_6_ERROR_EST_MODE);
1665 * enable temperature compensation
1666 * Need to use register names
1668 if (frequency < 4000)
1669 tempSlope = eep->modalHeader2G.tempSlope;
1670 else
1671 tempSlope = eep->modalHeader5G.tempSlope;
1673 REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
1674 REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
1675 temperature[0]);
1677 return 0;
1680 /* Apply the recorded correction values. */
1681 static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1683 int ichain, ipier, npier;
1684 int mode;
1685 int lfrequency[AR9300_MAX_CHAINS],
1686 lcorrection[AR9300_MAX_CHAINS],
1687 ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
1688 int hfrequency[AR9300_MAX_CHAINS],
1689 hcorrection[AR9300_MAX_CHAINS],
1690 htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
1691 int fdiff;
1692 int correction[AR9300_MAX_CHAINS],
1693 voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
1694 int pfrequency, pcorrection, ptemperature, pvoltage;
1695 struct ath_common *common = ath9k_hw_common(ah);
1697 mode = (frequency >= 4000);
1698 if (mode)
1699 npier = AR9300_NUM_5G_CAL_PIERS;
1700 else
1701 npier = AR9300_NUM_2G_CAL_PIERS;
1703 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1704 lfrequency[ichain] = 0;
1705 hfrequency[ichain] = 100000;
1707 /* identify best lower and higher frequency calibration measurement */
1708 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1709 for (ipier = 0; ipier < npier; ipier++) {
1710 if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
1711 &pfrequency, &pcorrection,
1712 &ptemperature, &pvoltage)) {
1713 fdiff = frequency - pfrequency;
1716 * this measurement is higher than
1717 * our desired frequency
1719 if (fdiff <= 0) {
1720 if (hfrequency[ichain] <= 0 ||
1721 hfrequency[ichain] >= 100000 ||
1722 fdiff >
1723 (frequency - hfrequency[ichain])) {
1725 * new best higher
1726 * frequency measurement
1728 hfrequency[ichain] = pfrequency;
1729 hcorrection[ichain] =
1730 pcorrection;
1731 htemperature[ichain] =
1732 ptemperature;
1733 hvoltage[ichain] = pvoltage;
1736 if (fdiff >= 0) {
1737 if (lfrequency[ichain] <= 0
1738 || fdiff <
1739 (frequency - lfrequency[ichain])) {
1741 * new best lower
1742 * frequency measurement
1744 lfrequency[ichain] = pfrequency;
1745 lcorrection[ichain] =
1746 pcorrection;
1747 ltemperature[ichain] =
1748 ptemperature;
1749 lvoltage[ichain] = pvoltage;
1756 /* interpolate */
1757 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1758 ath_print(common, ATH_DBG_EEPROM,
1759 "ch=%d f=%d low=%d %d h=%d %d\n",
1760 ichain, frequency, lfrequency[ichain],
1761 lcorrection[ichain], hfrequency[ichain],
1762 hcorrection[ichain]);
1763 /* they're the same, so just pick one */
1764 if (hfrequency[ichain] == lfrequency[ichain]) {
1765 correction[ichain] = lcorrection[ichain];
1766 voltage[ichain] = lvoltage[ichain];
1767 temperature[ichain] = ltemperature[ichain];
1769 /* the low frequency is good */
1770 else if (frequency - lfrequency[ichain] < 1000) {
1771 /* so is the high frequency, interpolate */
1772 if (hfrequency[ichain] - frequency < 1000) {
1774 correction[ichain] = lcorrection[ichain] +
1775 (((frequency - lfrequency[ichain]) *
1776 (hcorrection[ichain] -
1777 lcorrection[ichain])) /
1778 (hfrequency[ichain] - lfrequency[ichain]));
1780 temperature[ichain] = ltemperature[ichain] +
1781 (((frequency - lfrequency[ichain]) *
1782 (htemperature[ichain] -
1783 ltemperature[ichain])) /
1784 (hfrequency[ichain] - lfrequency[ichain]));
1786 voltage[ichain] =
1787 lvoltage[ichain] +
1788 (((frequency -
1789 lfrequency[ichain]) * (hvoltage[ichain] -
1790 lvoltage[ichain]))
1791 / (hfrequency[ichain] -
1792 lfrequency[ichain]));
1794 /* only low is good, use it */
1795 else {
1796 correction[ichain] = lcorrection[ichain];
1797 temperature[ichain] = ltemperature[ichain];
1798 voltage[ichain] = lvoltage[ichain];
1801 /* only high is good, use it */
1802 else if (hfrequency[ichain] - frequency < 1000) {
1803 correction[ichain] = hcorrection[ichain];
1804 temperature[ichain] = htemperature[ichain];
1805 voltage[ichain] = hvoltage[ichain];
1806 } else { /* nothing is good, presume 0???? */
1807 correction[ichain] = 0;
1808 temperature[ichain] = 0;
1809 voltage[ichain] = 0;
1813 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1814 temperature);
1816 ath_print(common, ATH_DBG_EEPROM,
1817 "for frequency=%d, calibration correction = %d %d %d\n",
1818 frequency, correction[0], correction[1], correction[2]);
1820 return 0;
1823 static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
1824 int idx,
1825 int edge,
1826 bool is2GHz)
1828 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1829 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1831 if (is2GHz)
1832 return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge]);
1833 else
1834 return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge]);
1837 static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
1838 int idx,
1839 unsigned int edge,
1840 u16 freq,
1841 bool is2GHz)
1843 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1844 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1846 u8 *ctl_freqbin = is2GHz ?
1847 &eep->ctl_freqbin_2G[idx][0] :
1848 &eep->ctl_freqbin_5G[idx][0];
1850 if (is2GHz) {
1851 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
1852 CTL_EDGE_FLAGS(ctl_2g[idx].ctlEdges[edge - 1]))
1853 return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge - 1]);
1854 } else {
1855 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
1856 CTL_EDGE_FLAGS(ctl_5g[idx].ctlEdges[edge - 1]))
1857 return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
1860 return AR9300_MAX_RATE_POWER;
1864 * Find the maximum conformance test limit for the given channel and CTL info
1866 static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
1867 u16 freq, int idx, bool is2GHz)
1869 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1870 u8 *ctl_freqbin = is2GHz ?
1871 &eep->ctl_freqbin_2G[idx][0] :
1872 &eep->ctl_freqbin_5G[idx][0];
1873 u16 num_edges = is2GHz ?
1874 AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G;
1875 unsigned int edge;
1877 /* Get the edge power */
1878 for (edge = 0;
1879 (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
1880 edge++) {
1882 * If there's an exact channel match or an inband flag set
1883 * on the lower channel use the given rdEdgePower
1885 if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
1886 twiceMaxEdgePower =
1887 ar9003_hw_get_direct_edge_power(eep, idx,
1888 edge, is2GHz);
1889 break;
1890 } else if ((edge > 0) &&
1891 (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
1892 is2GHz))) {
1893 twiceMaxEdgePower =
1894 ar9003_hw_get_indirect_edge_power(eep, idx,
1895 edge, freq,
1896 is2GHz);
1898 * Leave loop - no more affecting edges possible in
1899 * this monotonic increasing list
1901 break;
1904 return twiceMaxEdgePower;
1907 static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
1908 struct ath9k_channel *chan,
1909 u8 *pPwrArray, u16 cfgCtl,
1910 u8 twiceAntennaReduction,
1911 u8 twiceMaxRegulatoryPower,
1912 u16 powerLimit)
1914 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
1915 struct ath_common *common = ath9k_hw_common(ah);
1916 struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
1917 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1918 static const u16 tpScaleReductionTable[5] = {
1919 0, 3, 6, 9, AR9300_MAX_RATE_POWER
1921 int i;
1922 int16_t twiceLargestAntenna;
1923 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
1924 u16 ctlModesFor11a[] = {
1925 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
1927 u16 ctlModesFor11g[] = {
1928 CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
1929 CTL_11G_EXT, CTL_2GHT40
1931 u16 numCtlModes, *pCtlMode, ctlMode, freq;
1932 struct chan_centers centers;
1933 u8 *ctlIndex;
1934 u8 ctlNum;
1935 u16 twiceMinEdgePower;
1936 bool is2ghz = IS_CHAN_2GHZ(chan);
1938 ath9k_hw_get_channel_centers(ah, chan, &centers);
1940 /* Compute TxPower reduction due to Antenna Gain */
1941 if (is2ghz)
1942 twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
1943 else
1944 twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
1946 twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
1947 twiceLargestAntenna, 0);
1950 * scaledPower is the minimum of the user input power level
1951 * and the regulatory allowed power level
1953 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
1955 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
1956 maxRegAllowedPower -=
1957 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
1960 scaledPower = min(powerLimit, maxRegAllowedPower);
1963 * Reduce scaled Power by number of chains active to get
1964 * to per chain tx power level
1966 switch (ar5416_get_ntxchains(ah->txchainmask)) {
1967 case 1:
1968 break;
1969 case 2:
1970 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1971 break;
1972 case 3:
1973 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1974 break;
1977 scaledPower = max((u16)0, scaledPower);
1980 * Get target powers from EEPROM - our baseline for TX Power
1982 if (is2ghz) {
1983 /* Setup for CTL modes */
1984 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1985 numCtlModes =
1986 ARRAY_SIZE(ctlModesFor11g) -
1987 SUB_NUM_CTL_MODES_AT_2G_40;
1988 pCtlMode = ctlModesFor11g;
1989 if (IS_CHAN_HT40(chan))
1990 /* All 2G CTL's */
1991 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
1992 } else {
1993 /* Setup for CTL modes */
1994 /* CTL_11A, CTL_5GHT20 */
1995 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
1996 SUB_NUM_CTL_MODES_AT_5G_40;
1997 pCtlMode = ctlModesFor11a;
1998 if (IS_CHAN_HT40(chan))
1999 /* All 5G CTL's */
2000 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
2004 * For MIMO, need to apply regulatory caps individually across
2005 * dynamically running modes: CCK, OFDM, HT20, HT40
2007 * The outer loop walks through each possible applicable runtime mode.
2008 * The inner loop walks through each ctlIndex entry in EEPROM.
2009 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2011 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2012 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2013 (pCtlMode[ctlMode] == CTL_2GHT40);
2014 if (isHt40CtlMode)
2015 freq = centers.synth_center;
2016 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2017 freq = centers.ext_center;
2018 else
2019 freq = centers.ctl_center;
2021 ath_print(common, ATH_DBG_REGULATORY,
2022 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2023 "EXT_ADDITIVE %d\n",
2024 ctlMode, numCtlModes, isHt40CtlMode,
2025 (pCtlMode[ctlMode] & EXT_ADDITIVE));
2027 /* walk through each CTL index stored in EEPROM */
2028 if (is2ghz) {
2029 ctlIndex = pEepData->ctlIndex_2G;
2030 ctlNum = AR9300_NUM_CTLS_2G;
2031 } else {
2032 ctlIndex = pEepData->ctlIndex_5G;
2033 ctlNum = AR9300_NUM_CTLS_5G;
2036 for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
2037 ath_print(common, ATH_DBG_REGULATORY,
2038 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2039 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2040 "chan %dn",
2041 i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
2042 chan->channel);
2045 * compare test group from regulatory
2046 * channel list with test mode from pCtlMode
2047 * list
2049 if ((((cfgCtl & ~CTL_MODE_M) |
2050 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2051 ctlIndex[i]) ||
2052 (((cfgCtl & ~CTL_MODE_M) |
2053 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2054 ((ctlIndex[i] & CTL_MODE_M) |
2055 SD_NO_CTL))) {
2056 twiceMinEdgePower =
2057 ar9003_hw_get_max_edge_power(pEepData,
2058 freq, i,
2059 is2ghz);
2061 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
2063 * Find the minimum of all CTL
2064 * edge powers that apply to
2065 * this channel
2067 twiceMaxEdgePower =
2068 min(twiceMaxEdgePower,
2069 twiceMinEdgePower);
2070 else {
2071 /* specific */
2072 twiceMaxEdgePower =
2073 twiceMinEdgePower;
2074 break;
2079 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
2081 ath_print(common, ATH_DBG_REGULATORY,
2082 "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
2083 "sP %d minCtlPwr %d\n",
2084 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
2085 scaledPower, minCtlPower);
2087 /* Apply ctl mode to correct target power set */
2088 switch (pCtlMode[ctlMode]) {
2089 case CTL_11B:
2090 for (i = ALL_TARGET_LEGACY_1L_5L;
2091 i <= ALL_TARGET_LEGACY_11S; i++)
2092 pPwrArray[i] =
2093 (u8)min((u16)pPwrArray[i],
2094 minCtlPower);
2095 break;
2096 case CTL_11A:
2097 case CTL_11G:
2098 for (i = ALL_TARGET_LEGACY_6_24;
2099 i <= ALL_TARGET_LEGACY_54; i++)
2100 pPwrArray[i] =
2101 (u8)min((u16)pPwrArray[i],
2102 minCtlPower);
2103 break;
2104 case CTL_5GHT20:
2105 case CTL_2GHT20:
2106 for (i = ALL_TARGET_HT20_0_8_16;
2107 i <= ALL_TARGET_HT20_21; i++)
2108 pPwrArray[i] =
2109 (u8)min((u16)pPwrArray[i],
2110 minCtlPower);
2111 pPwrArray[ALL_TARGET_HT20_22] =
2112 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
2113 minCtlPower);
2114 pPwrArray[ALL_TARGET_HT20_23] =
2115 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
2116 minCtlPower);
2117 break;
2118 case CTL_5GHT40:
2119 case CTL_2GHT40:
2120 for (i = ALL_TARGET_HT40_0_8_16;
2121 i <= ALL_TARGET_HT40_23; i++)
2122 pPwrArray[i] =
2123 (u8)min((u16)pPwrArray[i],
2124 minCtlPower);
2125 break;
2126 default:
2127 break;
2129 } /* end ctl mode checking */
2132 static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
2133 struct ath9k_channel *chan, u16 cfgCtl,
2134 u8 twiceAntennaReduction,
2135 u8 twiceMaxRegulatoryPower,
2136 u8 powerLimit)
2138 struct ath_common *common = ath9k_hw_common(ah);
2139 u8 targetPowerValT2[ar9300RateSize];
2140 unsigned int i = 0;
2142 ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
2143 ar9003_hw_set_power_per_rate_table(ah, chan,
2144 targetPowerValT2, cfgCtl,
2145 twiceAntennaReduction,
2146 twiceMaxRegulatoryPower,
2147 powerLimit);
2149 while (i < ar9300RateSize) {
2150 ath_print(common, ATH_DBG_EEPROM,
2151 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2152 i++;
2153 ath_print(common, ATH_DBG_EEPROM,
2154 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2155 i++;
2156 ath_print(common, ATH_DBG_EEPROM,
2157 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2158 i++;
2159 ath_print(common, ATH_DBG_EEPROM,
2160 "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
2161 i++;
2164 /* Write target power array to registers */
2165 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
2168 * This is the TX power we send back to driver core,
2169 * and it can use to pass to userspace to display our
2170 * currently configured TX power setting.
2172 * Since power is rate dependent, use one of the indices
2173 * from the AR9300_Rates enum to select an entry from
2174 * targetPowerValT2[] to report. Currently returns the
2175 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
2176 * as CCK power is less interesting (?).
2178 i = ALL_TARGET_LEGACY_6_24; /* legacy */
2179 if (IS_CHAN_HT40(chan))
2180 i = ALL_TARGET_HT40_0_8_16; /* ht40 */
2181 else if (IS_CHAN_HT20(chan))
2182 i = ALL_TARGET_HT20_0_8_16; /* ht20 */
2184 ah->txpower_limit = targetPowerValT2[i];
2186 ar9003_hw_calibration_apply(ah, chan->channel);
2189 static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
2190 u16 i, bool is2GHz)
2192 return AR_NO_SPUR;
2195 s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
2197 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2199 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
2202 s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
2204 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2206 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
2209 const struct eeprom_ops eep_ar9300_ops = {
2210 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
2211 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
2212 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
2213 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
2214 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
2215 .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
2216 .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
2217 .set_board_values = ath9k_hw_ar9300_set_board_values,
2218 .set_addac = ath9k_hw_ar9300_set_addac,
2219 .set_txpower = ath9k_hw_ar9300_set_txpower,
2220 .get_spur_channel = ath9k_hw_ar9300_get_spur_channel