blob: bc3f49c5c5b47da6b9119177bc486d0592d65bfa [file] [log] [blame]
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001/*
2 * Copyright (c) 2010 Atheros Communications Inc.
3 *
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.
7 *
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.
15 */
16
17#include "hw.h"
18#include "ar9003_phy.h"
19#include "ar9003_eeprom.h"
20
21#define COMP_HDR_LEN 4
22#define COMP_CKSUM_LEN 2
23
24#define AR_CH0_TOP (0x00016288)
25#define AR_CH0_TOP_XPABIASLVL (0x3)
26#define AR_CH0_TOP_XPABIASLVL_S (8)
27
28#define AR_CH0_THERM (0x00016290)
29#define AR_CH0_THERM_SPARE (0x3f)
30#define AR_CH0_THERM_SPARE_S (0)
31
32#define AR_SWITCH_TABLE_COM_ALL (0xffff)
33#define AR_SWITCH_TABLE_COM_ALL_S (0)
34
35#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
36#define AR_SWITCH_TABLE_COM2_ALL_S (0)
37
38#define AR_SWITCH_TABLE_ALL (0xfff)
39#define AR_SWITCH_TABLE_ALL_S (0)
40
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020041#define LE16(x) __constant_cpu_to_le16(x)
42#define LE32(x) __constant_cpu_to_le32(x)
43
Luis R. Rodriguez824b1852010-08-01 02:25:16 -040044/* Local defines to distinguish between extension and control CTL's */
45#define EXT_ADDITIVE (0x8000)
46#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
47#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
48#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
49#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
50#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
51#define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */
52#define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */
53#define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */
54
55#define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */
56#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
57
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040058static const struct ar9300_eeprom ar9300_default = {
59 .eepromVersion = 2,
60 .templateVersion = 2,
61 .macAddr = {1, 2, 3, 4, 5, 6},
62 .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
64 .baseEepHeader = {
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020065 .regDmn = { LE16(0), LE16(0x1f) },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040066 .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
67 .opCapFlags = {
68 .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
69 .eepMisc = 0,
70 },
71 .rfSilent = 0,
72 .blueToothOptions = 0,
73 .deviceCap = 0,
74 .deviceType = 5, /* takes lower byte in eeprom location */
75 .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
76 .params_for_tuning_caps = {0, 0},
77 .featureEnable = 0x0c,
78 /*
79 * bit0 - enable tx temp comp - disabled
80 * bit1 - enable tx volt comp - disabled
81 * bit2 - enable fastClock - enabled
82 * bit3 - enable doubling - enabled
83 * bit4 - enable internal regulator - disabled
Felix Fietkau49352502010-06-12 00:33:59 -040084 * bit5 - enable pa predistortion - disabled
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040085 */
86 .miscConfiguration = 0, /* bit0 - turn down drivestrength */
87 .eepromWriteEnableGpio = 3,
88 .wlanDisableGpio = 0,
89 .wlanLedGpio = 8,
90 .rxBandSelectGpio = 0xff,
91 .txrxgain = 0,
92 .swreg = 0,
93 },
94 .modalHeader2G = {
95 /* ar9300_modal_eep_header 2g */
96 /* 4 idle,t1,t2,b(4 bits per setting) */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020097 .antCtrlCommon = LE32(0x110),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040098 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020099 .antCtrlCommon2 = LE32(0x22222),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400100
101 /*
102 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
103 * rx1, rx12, b (2 bits each)
104 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200105 .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400106
107 /*
108 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
109 * for ar9280 (0xa20c/b20c 5:0)
110 */
111 .xatten1DB = {0, 0, 0},
112
113 /*
114 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
115 * for ar9280 (0xa20c/b20c 16:12
116 */
117 .xatten1Margin = {0, 0, 0},
118 .tempSlope = 36,
119 .voltSlope = 0,
120
121 /*
122 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
123 * channels in usual fbin coding format
124 */
125 .spurChans = {0, 0, 0, 0, 0},
126
127 /*
128 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
129 * if the register is per chain
130 */
131 .noiseFloorThreshCh = {-1, 0, 0},
132 .ob = {1, 1, 1},/* 3 chain */
133 .db_stage2 = {1, 1, 1}, /* 3 chain */
134 .db_stage3 = {0, 0, 0},
135 .db_stage4 = {0, 0, 0},
136 .xpaBiasLvl = 0,
137 .txFrameToDataStart = 0x0e,
138 .txFrameToPaOn = 0x0e,
139 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
140 .antennaGain = 0,
141 .switchSettling = 0x2c,
142 .adcDesiredSize = -30,
143 .txEndToXpaOff = 0,
144 .txEndToRxOn = 0x2,
145 .txFrameToXpaOn = 0xe,
146 .thresh62 = 28,
Felix Fietkau49352502010-06-12 00:33:59 -0400147 .papdRateMaskHt20 = LE32(0x80c080),
148 .papdRateMaskHt40 = LE32(0x80c080),
149 .futureModal = {
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400151 },
152 },
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800153 .base_ext1 = {
154 .ant_div_control = 0,
155 .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
156 },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400157 .calFreqPier2G = {
158 FREQ2FBIN(2412, 1),
159 FREQ2FBIN(2437, 1),
160 FREQ2FBIN(2472, 1),
161 },
162 /* ar9300_cal_data_per_freq_op_loop 2g */
163 .calPierData2G = {
164 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
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 },
168 .calTarget_freqbin_Cck = {
169 FREQ2FBIN(2412, 1),
170 FREQ2FBIN(2484, 1),
171 },
172 .calTarget_freqbin_2G = {
173 FREQ2FBIN(2412, 1),
174 FREQ2FBIN(2437, 1),
175 FREQ2FBIN(2472, 1)
176 },
177 .calTarget_freqbin_2GHT20 = {
178 FREQ2FBIN(2412, 1),
179 FREQ2FBIN(2437, 1),
180 FREQ2FBIN(2472, 1)
181 },
182 .calTarget_freqbin_2GHT40 = {
183 FREQ2FBIN(2412, 1),
184 FREQ2FBIN(2437, 1),
185 FREQ2FBIN(2472, 1)
186 },
187 .calTargetPowerCck = {
188 /* 1L-5L,5S,11L,11S */
189 { {36, 36, 36, 36} },
190 { {36, 36, 36, 36} },
191 },
192 .calTargetPower2G = {
193 /* 6-24,36,48,54 */
194 { {32, 32, 28, 24} },
195 { {32, 32, 28, 24} },
196 { {32, 32, 28, 24} },
197 },
198 .calTargetPower2GHT20 = {
199 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
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 },
203 .calTargetPower2GHT40 = {
204 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
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 },
208 .ctlIndex_2G = {
209 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
210 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
211 },
212 .ctl_freqbin_2G = {
213 {
214 FREQ2FBIN(2412, 1),
215 FREQ2FBIN(2417, 1),
216 FREQ2FBIN(2457, 1),
217 FREQ2FBIN(2462, 1)
218 },
219 {
220 FREQ2FBIN(2412, 1),
221 FREQ2FBIN(2417, 1),
222 FREQ2FBIN(2462, 1),
223 0xFF,
224 },
225
226 {
227 FREQ2FBIN(2412, 1),
228 FREQ2FBIN(2417, 1),
229 FREQ2FBIN(2462, 1),
230 0xFF,
231 },
232 {
233 FREQ2FBIN(2422, 1),
234 FREQ2FBIN(2427, 1),
235 FREQ2FBIN(2447, 1),
236 FREQ2FBIN(2452, 1)
237 },
238
239 {
240 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
241 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
242 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
243 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
244 },
245
246 {
247 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
248 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
249 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
250 0,
251 },
252
253 {
254 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
255 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
256 FREQ2FBIN(2472, 1),
257 0,
258 },
259
260 {
261 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
262 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
263 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
264 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
265 },
266
267 {
268 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
269 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
270 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
271 },
272
273 {
274 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
275 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
276 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
277 0
278 },
279
280 {
281 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
282 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
283 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
284 0
285 },
286
287 {
288 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
289 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
290 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800291 /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400292 }
293 },
294 .ctlPowerData_2G = {
295 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
296 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
297 { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
298
299 { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
300 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
301 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
302
303 { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
304 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
305 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
306
307 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
308 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
309 },
310 .modalHeader5G = {
311 /* 4 idle,t1,t2,b (4 bits per setting) */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200312 .antCtrlCommon = LE32(0x110),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400313 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200314 .antCtrlCommon2 = LE32(0x22222),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400315 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
316 .antCtrlChain = {
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200317 LE16(0x000), LE16(0x000), LE16(0x000),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400318 },
319 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
320 .xatten1DB = {0, 0, 0},
321
322 /*
323 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
324 * for merlin (0xa20c/b20c 16:12
325 */
326 .xatten1Margin = {0, 0, 0},
327 .tempSlope = 68,
328 .voltSlope = 0,
329 /* spurChans spur channels in usual fbin coding format */
330 .spurChans = {0, 0, 0, 0, 0},
331 /* noiseFloorThreshCh Check if the register is per chain */
332 .noiseFloorThreshCh = {-1, 0, 0},
333 .ob = {3, 3, 3}, /* 3 chain */
334 .db_stage2 = {3, 3, 3}, /* 3 chain */
335 .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
336 .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
337 .xpaBiasLvl = 0,
338 .txFrameToDataStart = 0x0e,
339 .txFrameToPaOn = 0x0e,
340 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
341 .antennaGain = 0,
342 .switchSettling = 0x2d,
343 .adcDesiredSize = -30,
344 .txEndToXpaOff = 0,
345 .txEndToRxOn = 0x2,
346 .txFrameToXpaOn = 0xe,
347 .thresh62 = 28,
Felix Fietkau49352502010-06-12 00:33:59 -0400348 .papdRateMaskHt20 = LE32(0xf0e0e0),
349 .papdRateMaskHt40 = LE32(0xf0e0e0),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400350 .futureModal = {
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800351 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400352 },
353 },
Senthil Balasubramanianb3dd6bc2010-11-10 05:03:07 -0800354 .base_ext2 = {
355 .tempSlopeLow = 0,
356 .tempSlopeHigh = 0,
357 .xatten1DBLow = {0, 0, 0},
358 .xatten1MarginLow = {0, 0, 0},
359 .xatten1DBHigh = {0, 0, 0},
360 .xatten1MarginHigh = {0, 0, 0}
361 },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400362 .calFreqPier5G = {
363 FREQ2FBIN(5180, 0),
364 FREQ2FBIN(5220, 0),
365 FREQ2FBIN(5320, 0),
366 FREQ2FBIN(5400, 0),
367 FREQ2FBIN(5500, 0),
368 FREQ2FBIN(5600, 0),
369 FREQ2FBIN(5725, 0),
370 FREQ2FBIN(5825, 0)
371 },
372 .calPierData5G = {
373 {
374 {0, 0, 0, 0, 0},
375 {0, 0, 0, 0, 0},
376 {0, 0, 0, 0, 0},
377 {0, 0, 0, 0, 0},
378 {0, 0, 0, 0, 0},
379 {0, 0, 0, 0, 0},
380 {0, 0, 0, 0, 0},
381 {0, 0, 0, 0, 0},
382 },
383 {
384 {0, 0, 0, 0, 0},
385 {0, 0, 0, 0, 0},
386 {0, 0, 0, 0, 0},
387 {0, 0, 0, 0, 0},
388 {0, 0, 0, 0, 0},
389 {0, 0, 0, 0, 0},
390 {0, 0, 0, 0, 0},
391 {0, 0, 0, 0, 0},
392 },
393 {
394 {0, 0, 0, 0, 0},
395 {0, 0, 0, 0, 0},
396 {0, 0, 0, 0, 0},
397 {0, 0, 0, 0, 0},
398 {0, 0, 0, 0, 0},
399 {0, 0, 0, 0, 0},
400 {0, 0, 0, 0, 0},
401 {0, 0, 0, 0, 0},
402 },
403
404 },
405 .calTarget_freqbin_5G = {
406 FREQ2FBIN(5180, 0),
407 FREQ2FBIN(5220, 0),
408 FREQ2FBIN(5320, 0),
409 FREQ2FBIN(5400, 0),
410 FREQ2FBIN(5500, 0),
411 FREQ2FBIN(5600, 0),
412 FREQ2FBIN(5725, 0),
413 FREQ2FBIN(5825, 0)
414 },
415 .calTarget_freqbin_5GHT20 = {
416 FREQ2FBIN(5180, 0),
417 FREQ2FBIN(5240, 0),
418 FREQ2FBIN(5320, 0),
419 FREQ2FBIN(5500, 0),
420 FREQ2FBIN(5700, 0),
421 FREQ2FBIN(5745, 0),
422 FREQ2FBIN(5725, 0),
423 FREQ2FBIN(5825, 0)
424 },
425 .calTarget_freqbin_5GHT40 = {
426 FREQ2FBIN(5180, 0),
427 FREQ2FBIN(5240, 0),
428 FREQ2FBIN(5320, 0),
429 FREQ2FBIN(5500, 0),
430 FREQ2FBIN(5700, 0),
431 FREQ2FBIN(5745, 0),
432 FREQ2FBIN(5725, 0),
433 FREQ2FBIN(5825, 0)
434 },
435 .calTargetPower5G = {
436 /* 6-24,36,48,54 */
437 { {20, 20, 20, 10} },
438 { {20, 20, 20, 10} },
439 { {20, 20, 20, 10} },
440 { {20, 20, 20, 10} },
441 { {20, 20, 20, 10} },
442 { {20, 20, 20, 10} },
443 { {20, 20, 20, 10} },
444 { {20, 20, 20, 10} },
445 },
446 .calTargetPower5GHT20 = {
447 /*
448 * 0_8_16,1-3_9-11_17-19,
449 * 4,5,6,7,12,13,14,15,20,21,22,23
450 */
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} },
455 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
456 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
457 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
458 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
459 },
460 .calTargetPower5GHT40 = {
461 /*
462 * 0_8_16,1-3_9-11_17-19,
463 * 4,5,6,7,12,13,14,15,20,21,22,23
464 */
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} },
469 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
470 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
471 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
472 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
473 },
474 .ctlIndex_5G = {
475 0x10, 0x16, 0x18, 0x40, 0x46,
476 0x48, 0x30, 0x36, 0x38
477 },
478 .ctl_freqbin_5G = {
479 {
480 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
481 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
482 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
483 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
484 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
485 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
486 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
487 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
488 },
489 {
490 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
491 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
492 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
493 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
494 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
495 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
496 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
497 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
498 },
499
500 {
501 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
502 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
503 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
504 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
505 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
506 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
507 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
508 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
509 },
510
511 {
512 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
513 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
514 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
515 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
516 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
517 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
518 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
519 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
520 },
521
522 {
523 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
524 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
525 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
526 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
527 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
528 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
529 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
530 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
531 },
532
533 {
534 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
535 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
536 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
537 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
538 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
539 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
540 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
541 /* Data[5].ctlEdges[7].bChannel */ 0xFF
542 },
543
544 {
545 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
546 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
547 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
548 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
549 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
550 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
551 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
552 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
553 },
554
555 {
556 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
557 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
558 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
559 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
560 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
561 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
562 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
563 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
564 },
565
566 {
567 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
568 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
569 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
570 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
571 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
572 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
573 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
574 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
575 }
576 },
577 .ctlPowerData_5G = {
578 {
579 {
580 {60, 1}, {60, 1}, {60, 1}, {60, 1},
581 {60, 1}, {60, 1}, {60, 1}, {60, 0},
582 }
583 },
584 {
585 {
586 {60, 1}, {60, 1}, {60, 1}, {60, 1},
587 {60, 1}, {60, 1}, {60, 1}, {60, 0},
588 }
589 },
590 {
591 {
592 {60, 0}, {60, 1}, {60, 0}, {60, 1},
593 {60, 1}, {60, 1}, {60, 1}, {60, 1},
594 }
595 },
596 {
597 {
598 {60, 0}, {60, 1}, {60, 1}, {60, 0},
599 {60, 1}, {60, 0}, {60, 0}, {60, 0},
600 }
601 },
602 {
603 {
604 {60, 1}, {60, 1}, {60, 1}, {60, 0},
605 {60, 0}, {60, 0}, {60, 0}, {60, 0},
606 }
607 },
608 {
609 {
610 {60, 1}, {60, 1}, {60, 1}, {60, 1},
611 {60, 1}, {60, 0}, {60, 0}, {60, 0},
612 }
613 },
614 {
615 {
616 {60, 1}, {60, 1}, {60, 1}, {60, 1},
617 {60, 1}, {60, 1}, {60, 1}, {60, 1},
618 }
619 },
620 {
621 {
622 {60, 1}, {60, 1}, {60, 0}, {60, 1},
623 {60, 1}, {60, 1}, {60, 1}, {60, 0},
624 }
625 },
626 {
627 {
628 {60, 1}, {60, 0}, {60, 1}, {60, 1},
629 {60, 1}, {60, 1}, {60, 0}, {60, 1},
630 }
631 },
632 }
633};
634
Luis R. Rodriguez824b1852010-08-01 02:25:16 -0400635static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
636{
637 if (fbin == AR9300_BCHAN_UNUSED)
638 return fbin;
639
640 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
641}
642
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400643static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
644{
645 return 0;
646}
647
648static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
649 enum eeprom_param param)
650{
651 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
652 struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
653
654 switch (param) {
655 case EEP_MAC_LSW:
656 return eep->macAddr[0] << 8 | eep->macAddr[1];
657 case EEP_MAC_MID:
658 return eep->macAddr[2] << 8 | eep->macAddr[3];
659 case EEP_MAC_MSW:
660 return eep->macAddr[4] << 8 | eep->macAddr[5];
661 case EEP_REG_0:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200662 return le16_to_cpu(pBase->regDmn[0]);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400663 case EEP_REG_1:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200664 return le16_to_cpu(pBase->regDmn[1]);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400665 case EEP_OP_CAP:
666 return pBase->deviceCap;
667 case EEP_OP_MODE:
668 return pBase->opCapFlags.opFlags;
669 case EEP_RF_SILENT:
670 return pBase->rfSilent;
671 case EEP_TX_MASK:
672 return (pBase->txrxMask >> 4) & 0xf;
673 case EEP_RX_MASK:
674 return pBase->txrxMask & 0xf;
675 case EEP_DRIVE_STRENGTH:
676#define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
677 return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
678 case EEP_INTERNAL_REGULATOR:
679 /* Bit 4 is internal regulator flag */
680 return (pBase->featureEnable & 0x10) >> 4;
681 case EEP_SWREG:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200682 return le32_to_cpu(pBase->swreg);
Felix Fietkau49352502010-06-12 00:33:59 -0400683 case EEP_PAPRD:
684 return !!(pBase->featureEnable & BIT(5));
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400685 default:
686 return 0;
687 }
688}
689
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200690static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
691 u8 *buffer)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400692{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200693 u16 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400694
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200695 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
696 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400697
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200698 *buffer = (val >> (8 * (address % 2))) & 0xff;
699 return true;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400700}
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400701
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200702static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
703 u8 *buffer)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400704{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200705 u16 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400706
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200707 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
708 return false;
709
710 buffer[0] = val >> 8;
711 buffer[1] = val & 0xff;
712
713 return true;
714}
715
716static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
717 int count)
718{
719 struct ath_common *common = ath9k_hw_common(ah);
720 int i;
721
722 if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400723 ath_print(common, ATH_DBG_EEPROM,
724 "eeprom address not in range\n");
725 return false;
726 }
727
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200728 /*
729 * Since we're reading the bytes in reverse order from a little-endian
730 * word stream, an even address means we only use the lower half of
731 * the 16-bit word at that address
732 */
733 if (address % 2 == 0) {
734 if (!ar9300_eeprom_read_byte(common, address--, buffer++))
735 goto error;
736
737 count--;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400738 }
739
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200740 for (i = 0; i < count / 2; i++) {
741 if (!ar9300_eeprom_read_word(common, address, buffer))
742 goto error;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400743
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200744 address -= 2;
745 buffer += 2;
746 }
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400747
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200748 if (count % 2)
749 if (!ar9300_eeprom_read_byte(common, address, buffer))
750 goto error;
751
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400752 return true;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200753
754error:
755 ath_print(common, ATH_DBG_EEPROM,
756 "unable to read eeprom region at offset %d\n", address);
757 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400758}
759
760static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
761 int *length, int *major, int *minor)
762{
763 unsigned long value[4];
764
765 value[0] = best[0];
766 value[1] = best[1];
767 value[2] = best[2];
768 value[3] = best[3];
769 *code = ((value[0] >> 5) & 0x0007);
770 *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
771 *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
772 *major = (value[2] & 0x000f);
773 *minor = (value[3] & 0x00ff);
774}
775
776static u16 ar9300_comp_cksum(u8 *data, int dsize)
777{
778 int it, checksum = 0;
779
780 for (it = 0; it < dsize; it++) {
781 checksum += data[it];
782 checksum &= 0xffff;
783 }
784
785 return checksum;
786}
787
788static bool ar9300_uncompress_block(struct ath_hw *ah,
789 u8 *mptr,
790 int mdataSize,
791 u8 *block,
792 int size)
793{
794 int it;
795 int spot;
796 int offset;
797 int length;
798 struct ath_common *common = ath9k_hw_common(ah);
799
800 spot = 0;
801
802 for (it = 0; it < size; it += (length+2)) {
803 offset = block[it];
804 offset &= 0xff;
805 spot += offset;
806 length = block[it+1];
807 length &= 0xff;
808
Luis R. Rodriguez803288e2010-08-30 19:26:32 -0400809 if (length > 0 && spot >= 0 && spot+length <= mdataSize) {
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400810 ath_print(common, ATH_DBG_EEPROM,
811 "Restore at %d: spot=%d "
812 "offset=%d length=%d\n",
813 it, spot, offset, length);
814 memcpy(&mptr[spot], &block[it+2], length);
815 spot += length;
816 } else if (length > 0) {
817 ath_print(common, ATH_DBG_EEPROM,
818 "Bad restore at %d: spot=%d "
819 "offset=%d length=%d\n",
820 it, spot, offset, length);
821 return false;
822 }
823 }
824 return true;
825}
826
827static int ar9300_compress_decision(struct ath_hw *ah,
828 int it,
829 int code,
830 int reference,
831 u8 *mptr,
832 u8 *word, int length, int mdata_size)
833{
834 struct ath_common *common = ath9k_hw_common(ah);
835 u8 *dptr;
836
837 switch (code) {
838 case _CompressNone:
839 if (length != mdata_size) {
840 ath_print(common, ATH_DBG_EEPROM,
841 "EEPROM structure size mismatch"
842 "memory=%d eeprom=%d\n", mdata_size, length);
843 return -1;
844 }
845 memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
846 ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:"
847 " uncompressed, length %d\n", it, length);
848 break;
849 case _CompressBlock:
850 if (reference == 0) {
851 dptr = mptr;
852 } else {
853 if (reference != 2) {
854 ath_print(common, ATH_DBG_EEPROM,
855 "cant find reference eeprom"
856 "struct %d\n", reference);
857 return -1;
858 }
859 memcpy(mptr, &ar9300_default, mdata_size);
860 }
861 ath_print(common, ATH_DBG_EEPROM,
862 "restore eeprom %d: block, reference %d,"
863 " length %d\n", it, reference, length);
864 ar9300_uncompress_block(ah, mptr, mdata_size,
865 (u8 *) (word + COMP_HDR_LEN), length);
866 break;
867 default:
868 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
869 " code %d\n", code);
870 return -1;
871 }
872 return 0;
873}
874
875/*
876 * Read the configuration data from the eeprom.
877 * The data can be put in any specified memory buffer.
878 *
879 * Returns -1 on error.
880 * Returns address of next memory location on success.
881 */
882static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
883 u8 *mptr, int mdata_size)
884{
885#define MDEFAULT 15
886#define MSTATE 100
887 int cptr;
888 u8 *word;
889 int code;
890 int reference, length, major, minor;
891 int osize;
892 int it;
893 u16 checksum, mchecksum;
894 struct ath_common *common = ath9k_hw_common(ah);
895
896 word = kzalloc(2048, GFP_KERNEL);
897 if (!word)
898 return -1;
899
900 memcpy(mptr, &ar9300_default, mdata_size);
901
902 cptr = AR9300_BASE_ADDR;
903 for (it = 0; it < MSTATE; it++) {
904 if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
905 goto fail;
906
907 if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
908 word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
909 && word[2] == 0xff && word[3] == 0xff))
910 break;
911
912 ar9300_comp_hdr_unpack(word, &code, &reference,
913 &length, &major, &minor);
914 ath_print(common, ATH_DBG_EEPROM,
915 "Found block at %x: code=%d ref=%d"
916 "length=%d major=%d minor=%d\n", cptr, code,
917 reference, length, major, minor);
918 if (length >= 1024) {
919 ath_print(common, ATH_DBG_EEPROM,
920 "Skipping bad header\n");
921 cptr -= COMP_HDR_LEN;
922 continue;
923 }
924
925 osize = length;
926 ar9300_read_eeprom(ah, cptr, word,
927 COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
928 checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
929 mchecksum = word[COMP_HDR_LEN + osize] |
930 (word[COMP_HDR_LEN + osize + 1] << 8);
931 ath_print(common, ATH_DBG_EEPROM,
932 "checksum %x %x\n", checksum, mchecksum);
933 if (checksum == mchecksum) {
934 ar9300_compress_decision(ah, it, code, reference, mptr,
935 word, length, mdata_size);
936 } else {
937 ath_print(common, ATH_DBG_EEPROM,
938 "skipping block with bad checksum\n");
939 }
940 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
941 }
942
943 kfree(word);
944 return cptr;
945
946fail:
947 kfree(word);
948 return -1;
949}
950
951/*
952 * Restore the configuration structure by reading the eeprom.
953 * This function destroys any existing in-memory structure
954 * content.
955 */
956static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
957{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200958 u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400959
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200960 if (ar9300_eeprom_restore_internal(ah, mptr,
961 sizeof(struct ar9300_eeprom)) < 0)
962 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400963
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200964 return true;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400965}
966
967/* XXX: review hardware docs */
968static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
969{
970 return ah->eeprom.ar9300_eep.eepromVersion;
971}
972
973/* XXX: could be read from the eepromVersion, not sure yet */
974static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
975{
976 return 0;
977}
978
979static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
Rajkumar Manoharanf799a302010-09-16 11:40:06 +0530980 enum ath9k_hal_freq_band freq_band)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400981{
982 return 1;
983}
984
Felix Fietkau601e0cb2010-07-11 12:48:39 +0200985static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400986 struct ath9k_channel *chan)
987{
988 return -EINVAL;
989}
990
991static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
992{
993 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
994
995 if (is2ghz)
996 return eep->modalHeader2G.xpaBiasLvl;
997 else
998 return eep->modalHeader5G.xpaBiasLvl;
999}
1000
1001static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
1002{
1003 int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
1004 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3));
1005 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE,
1006 ((bias >> 2) & 0x3));
1007}
1008
1009static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
1010{
1011 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001012 __le32 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001013
1014 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001015 val = eep->modalHeader2G.antCtrlCommon;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001016 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001017 val = eep->modalHeader5G.antCtrlCommon;
1018 return le32_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001019}
1020
1021static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
1022{
1023 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001024 __le32 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001025
1026 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001027 val = eep->modalHeader2G.antCtrlCommon2;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001028 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001029 val = eep->modalHeader5G.antCtrlCommon2;
1030 return le32_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001031}
1032
1033static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1034 int chain,
1035 bool is2ghz)
1036{
1037 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001038 __le16 val = 0;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001039
1040 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1041 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001042 val = eep->modalHeader2G.antCtrlChain[chain];
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001043 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001044 val = eep->modalHeader5G.antCtrlChain[chain];
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001045 }
1046
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001047 return le16_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001048}
1049
1050static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1051{
1052 u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
1053 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
1054
1055 value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
1056 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1057
1058 value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
1059 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1060
1061 value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
1062 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1063
1064 value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
1065 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1066}
1067
1068static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1069{
1070 int drive_strength;
1071 unsigned long reg;
1072
1073 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1074
1075 if (!drive_strength)
1076 return;
1077
1078 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1079 reg &= ~0x00ffffc0;
1080 reg |= 0x5 << 21;
1081 reg |= 0x5 << 18;
1082 reg |= 0x5 << 15;
1083 reg |= 0x5 << 12;
1084 reg |= 0x5 << 9;
1085 reg |= 0x5 << 6;
1086 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1087
1088 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1089 reg &= ~0xffffffe0;
1090 reg |= 0x5 << 29;
1091 reg |= 0x5 << 26;
1092 reg |= 0x5 << 23;
1093 reg |= 0x5 << 20;
1094 reg |= 0x5 << 17;
1095 reg |= 0x5 << 14;
1096 reg |= 0x5 << 11;
1097 reg |= 0x5 << 8;
1098 reg |= 0x5 << 5;
1099 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1100
1101 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1102 reg &= ~0xff800000;
1103 reg |= 0x5 << 29;
1104 reg |= 0x5 << 26;
1105 reg |= 0x5 << 23;
1106 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1107}
1108
1109static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1110{
1111 int internal_regulator =
1112 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1113
1114 if (internal_regulator) {
1115 /* Internal regulator is ON. Write swreg register. */
1116 int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
1117 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1118 REG_READ(ah, AR_RTC_REG_CONTROL1) &
1119 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1120 REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1121 /* Set REG_CONTROL1.SWREG_PROGRAM */
1122 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1123 REG_READ(ah,
1124 AR_RTC_REG_CONTROL1) |
1125 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1126 } else {
1127 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1128 (REG_READ(ah,
1129 AR_RTC_SLEEP_CLK) |
1130 AR_RTC_FORCE_SWREG_PRD));
1131 }
1132}
1133
1134static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1135 struct ath9k_channel *chan)
1136{
1137 ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
1138 ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
1139 ar9003_hw_drive_strength_apply(ah);
1140 ar9003_hw_internal_regulator_apply(ah);
1141}
1142
1143static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1144 struct ath9k_channel *chan)
1145{
1146}
1147
1148/*
1149 * Returns the interpolated y value corresponding to the specified x value
1150 * from the np ordered pairs of data (px,py).
1151 * The pairs do not have to be in any order.
1152 * If the specified x value is less than any of the px,
1153 * the returned y value is equal to the py for the lowest px.
1154 * If the specified x value is greater than any of the px,
1155 * the returned y value is equal to the py for the highest px.
1156 */
1157static int ar9003_hw_power_interpolate(int32_t x,
1158 int32_t *px, int32_t *py, u_int16_t np)
1159{
1160 int ip = 0;
1161 int lx = 0, ly = 0, lhave = 0;
1162 int hx = 0, hy = 0, hhave = 0;
1163 int dx = 0;
1164 int y = 0;
1165
1166 lhave = 0;
1167 hhave = 0;
1168
1169 /* identify best lower and higher x calibration measurement */
1170 for (ip = 0; ip < np; ip++) {
1171 dx = x - px[ip];
1172
1173 /* this measurement is higher than our desired x */
1174 if (dx <= 0) {
1175 if (!hhave || dx > (x - hx)) {
1176 /* new best higher x measurement */
1177 hx = px[ip];
1178 hy = py[ip];
1179 hhave = 1;
1180 }
1181 }
1182 /* this measurement is lower than our desired x */
1183 if (dx >= 0) {
1184 if (!lhave || dx < (x - lx)) {
1185 /* new best lower x measurement */
1186 lx = px[ip];
1187 ly = py[ip];
1188 lhave = 1;
1189 }
1190 }
1191 }
1192
1193 /* the low x is good */
1194 if (lhave) {
1195 /* so is the high x */
1196 if (hhave) {
1197 /* they're the same, so just pick one */
1198 if (hx == lx)
1199 y = ly;
1200 else /* interpolate */
1201 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1202 } else /* only low is good, use it */
1203 y = ly;
1204 } else if (hhave) /* only high is good, use it */
1205 y = hy;
1206 else /* nothing is good,this should never happen unless np=0, ???? */
1207 y = -(1 << 30);
1208 return y;
1209}
1210
1211static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1212 u16 rateIndex, u16 freq, bool is2GHz)
1213{
1214 u16 numPiers, i;
1215 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1216 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1217 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1218 struct cal_tgt_pow_legacy *pEepromTargetPwr;
1219 u8 *pFreqBin;
1220
1221 if (is2GHz) {
Felix Fietkaud10baf92010-04-26 15:04:38 -04001222 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001223 pEepromTargetPwr = eep->calTargetPower2G;
1224 pFreqBin = eep->calTarget_freqbin_2G;
1225 } else {
1226 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1227 pEepromTargetPwr = eep->calTargetPower5G;
1228 pFreqBin = eep->calTarget_freqbin_5G;
1229 }
1230
1231 /*
1232 * create array of channels and targetpower from
1233 * targetpower piers stored on eeprom
1234 */
1235 for (i = 0; i < numPiers; i++) {
1236 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1237 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1238 }
1239
1240 /* interpolate to get target power for given frequency */
1241 return (u8) ar9003_hw_power_interpolate((s32) freq,
1242 freqArray,
1243 targetPowerArray, numPiers);
1244}
1245
1246static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1247 u16 rateIndex,
1248 u16 freq, bool is2GHz)
1249{
1250 u16 numPiers, i;
1251 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1252 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1253 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1254 struct cal_tgt_pow_ht *pEepromTargetPwr;
1255 u8 *pFreqBin;
1256
1257 if (is2GHz) {
Felix Fietkaud10baf92010-04-26 15:04:38 -04001258 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001259 pEepromTargetPwr = eep->calTargetPower2GHT20;
1260 pFreqBin = eep->calTarget_freqbin_2GHT20;
1261 } else {
1262 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1263 pEepromTargetPwr = eep->calTargetPower5GHT20;
1264 pFreqBin = eep->calTarget_freqbin_5GHT20;
1265 }
1266
1267 /*
1268 * create array of channels and targetpower
1269 * from targetpower piers stored on eeprom
1270 */
1271 for (i = 0; i < numPiers; i++) {
1272 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1273 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1274 }
1275
1276 /* interpolate to get target power for given frequency */
1277 return (u8) ar9003_hw_power_interpolate((s32) freq,
1278 freqArray,
1279 targetPowerArray, numPiers);
1280}
1281
1282static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1283 u16 rateIndex,
1284 u16 freq, bool is2GHz)
1285{
1286 u16 numPiers, i;
1287 s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
1288 s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
1289 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1290 struct cal_tgt_pow_ht *pEepromTargetPwr;
1291 u8 *pFreqBin;
1292
1293 if (is2GHz) {
1294 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1295 pEepromTargetPwr = eep->calTargetPower2GHT40;
1296 pFreqBin = eep->calTarget_freqbin_2GHT40;
1297 } else {
1298 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1299 pEepromTargetPwr = eep->calTargetPower5GHT40;
1300 pFreqBin = eep->calTarget_freqbin_5GHT40;
1301 }
1302
1303 /*
1304 * create array of channels and targetpower from
1305 * targetpower piers stored on eeprom
1306 */
1307 for (i = 0; i < numPiers; i++) {
1308 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1309 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1310 }
1311
1312 /* interpolate to get target power for given frequency */
1313 return (u8) ar9003_hw_power_interpolate((s32) freq,
1314 freqArray,
1315 targetPowerArray, numPiers);
1316}
1317
1318static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1319 u16 rateIndex, u16 freq)
1320{
1321 u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
1322 s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1323 s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1324 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1325 struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
1326 u8 *pFreqBin = eep->calTarget_freqbin_Cck;
1327
1328 /*
1329 * create array of channels and targetpower from
1330 * targetpower piers stored on eeprom
1331 */
1332 for (i = 0; i < numPiers; i++) {
1333 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1334 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1335 }
1336
1337 /* interpolate to get target power for given frequency */
1338 return (u8) ar9003_hw_power_interpolate((s32) freq,
1339 freqArray,
1340 targetPowerArray, numPiers);
1341}
1342
1343/* Set tx power registers to array of values passed in */
1344static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1345{
1346#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1347 /* make sure forced gain is not set */
1348 REG_WRITE(ah, 0xa458, 0);
1349
1350 /* Write the OFDM power per rate set */
1351
1352 /* 6 (LSB), 9, 12, 18 (MSB) */
1353 REG_WRITE(ah, 0xa3c0,
1354 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
1355 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
1356 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
1357 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1358
1359 /* 24 (LSB), 36, 48, 54 (MSB) */
1360 REG_WRITE(ah, 0xa3c4,
1361 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
1362 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
1363 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
1364 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1365
1366 /* Write the CCK power per rate set */
1367
1368 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1369 REG_WRITE(ah, 0xa3c8,
1370 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
1371 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
1372 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1373 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
1374
1375 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1376 REG_WRITE(ah, 0xa3cc,
1377 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
1378 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
1379 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
1380 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
1381 );
1382
1383 /* Write the HT20 power per rate set */
1384
1385 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1386 REG_WRITE(ah, 0xa3d0,
1387 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
1388 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
1389 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
1390 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
1391 );
1392
1393 /* 6 (LSB), 7, 12, 13 (MSB) */
1394 REG_WRITE(ah, 0xa3d4,
1395 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
1396 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
1397 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
1398 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
1399 );
1400
1401 /* 14 (LSB), 15, 20, 21 */
1402 REG_WRITE(ah, 0xa3e4,
1403 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
1404 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
1405 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
1406 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
1407 );
1408
1409 /* Mixed HT20 and HT40 rates */
1410
1411 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1412 REG_WRITE(ah, 0xa3e8,
1413 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
1414 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
1415 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
1416 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
1417 );
1418
1419 /*
1420 * Write the HT40 power per rate set
1421 * correct PAR difference between HT40 and HT20/LEGACY
1422 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1423 */
1424 REG_WRITE(ah, 0xa3d8,
1425 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
1426 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
1427 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
1428 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
1429 );
1430
1431 /* 6 (LSB), 7, 12, 13 (MSB) */
1432 REG_WRITE(ah, 0xa3dc,
1433 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
1434 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
1435 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
1436 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
1437 );
1438
1439 /* 14 (LSB), 15, 20, 21 */
1440 REG_WRITE(ah, 0xa3ec,
1441 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
1442 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
1443 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
1444 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
1445 );
1446
1447 return 0;
1448#undef POW_SM
1449}
1450
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04001451static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
1452 u8 *targetPowerValT2)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001453{
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001454 /* XXX: hard code for now, need to get from eeprom struct */
1455 u8 ht40PowerIncForPdadc = 0;
1456 bool is2GHz = false;
1457 unsigned int i = 0;
1458 struct ath_common *common = ath9k_hw_common(ah);
1459
1460 if (freq < 4000)
1461 is2GHz = true;
1462
1463 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1464 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1465 is2GHz);
1466 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1467 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1468 is2GHz);
1469 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1470 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1471 is2GHz);
1472 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1473 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1474 is2GHz);
1475 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1476 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1477 freq);
1478 targetPowerValT2[ALL_TARGET_LEGACY_5S] =
1479 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
1480 targetPowerValT2[ALL_TARGET_LEGACY_11L] =
1481 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
1482 targetPowerValT2[ALL_TARGET_LEGACY_11S] =
1483 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
1484 targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
1485 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1486 is2GHz);
1487 targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1488 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1489 freq, is2GHz);
1490 targetPowerValT2[ALL_TARGET_HT20_4] =
1491 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1492 is2GHz);
1493 targetPowerValT2[ALL_TARGET_HT20_5] =
1494 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1495 is2GHz);
1496 targetPowerValT2[ALL_TARGET_HT20_6] =
1497 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1498 is2GHz);
1499 targetPowerValT2[ALL_TARGET_HT20_7] =
1500 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1501 is2GHz);
1502 targetPowerValT2[ALL_TARGET_HT20_12] =
1503 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1504 is2GHz);
1505 targetPowerValT2[ALL_TARGET_HT20_13] =
1506 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1507 is2GHz);
1508 targetPowerValT2[ALL_TARGET_HT20_14] =
1509 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1510 is2GHz);
1511 targetPowerValT2[ALL_TARGET_HT20_15] =
1512 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1513 is2GHz);
1514 targetPowerValT2[ALL_TARGET_HT20_20] =
1515 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1516 is2GHz);
1517 targetPowerValT2[ALL_TARGET_HT20_21] =
1518 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1519 is2GHz);
1520 targetPowerValT2[ALL_TARGET_HT20_22] =
1521 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1522 is2GHz);
1523 targetPowerValT2[ALL_TARGET_HT20_23] =
1524 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1525 is2GHz);
1526 targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
1527 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1528 is2GHz) + ht40PowerIncForPdadc;
1529 targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1530 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1531 freq,
1532 is2GHz) + ht40PowerIncForPdadc;
1533 targetPowerValT2[ALL_TARGET_HT40_4] =
1534 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1535 is2GHz) + ht40PowerIncForPdadc;
1536 targetPowerValT2[ALL_TARGET_HT40_5] =
1537 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1538 is2GHz) + ht40PowerIncForPdadc;
1539 targetPowerValT2[ALL_TARGET_HT40_6] =
1540 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1541 is2GHz) + ht40PowerIncForPdadc;
1542 targetPowerValT2[ALL_TARGET_HT40_7] =
1543 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1544 is2GHz) + ht40PowerIncForPdadc;
1545 targetPowerValT2[ALL_TARGET_HT40_12] =
1546 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1547 is2GHz) + ht40PowerIncForPdadc;
1548 targetPowerValT2[ALL_TARGET_HT40_13] =
1549 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1550 is2GHz) + ht40PowerIncForPdadc;
1551 targetPowerValT2[ALL_TARGET_HT40_14] =
1552 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1553 is2GHz) + ht40PowerIncForPdadc;
1554 targetPowerValT2[ALL_TARGET_HT40_15] =
1555 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1556 is2GHz) + ht40PowerIncForPdadc;
1557 targetPowerValT2[ALL_TARGET_HT40_20] =
1558 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1559 is2GHz) + ht40PowerIncForPdadc;
1560 targetPowerValT2[ALL_TARGET_HT40_21] =
1561 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1562 is2GHz) + ht40PowerIncForPdadc;
1563 targetPowerValT2[ALL_TARGET_HT40_22] =
1564 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1565 is2GHz) + ht40PowerIncForPdadc;
1566 targetPowerValT2[ALL_TARGET_HT40_23] =
1567 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1568 is2GHz) + ht40PowerIncForPdadc;
1569
1570 while (i < ar9300RateSize) {
1571 ath_print(common, ATH_DBG_EEPROM,
1572 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1573 i++;
1574
1575 ath_print(common, ATH_DBG_EEPROM,
1576 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1577 i++;
1578
1579 ath_print(common, ATH_DBG_EEPROM,
1580 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1581 i++;
1582
1583 ath_print(common, ATH_DBG_EEPROM,
1584 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1585 i++;
1586 }
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001587}
1588
1589static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1590 int mode,
1591 int ipier,
1592 int ichain,
1593 int *pfrequency,
1594 int *pcorrection,
1595 int *ptemperature, int *pvoltage)
1596{
1597 u8 *pCalPier;
1598 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1599 int is2GHz;
1600 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1601 struct ath_common *common = ath9k_hw_common(ah);
1602
1603 if (ichain >= AR9300_MAX_CHAINS) {
1604 ath_print(common, ATH_DBG_EEPROM,
1605 "Invalid chain index, must be less than %d\n",
1606 AR9300_MAX_CHAINS);
1607 return -1;
1608 }
1609
1610 if (mode) { /* 5GHz */
1611 if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
1612 ath_print(common, ATH_DBG_EEPROM,
1613 "Invalid 5GHz cal pier index, must "
1614 "be less than %d\n",
1615 AR9300_NUM_5G_CAL_PIERS);
1616 return -1;
1617 }
1618 pCalPier = &(eep->calFreqPier5G[ipier]);
1619 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1620 is2GHz = 0;
1621 } else {
1622 if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
1623 ath_print(common, ATH_DBG_EEPROM,
1624 "Invalid 2GHz cal pier index, must "
1625 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
1626 return -1;
1627 }
1628
1629 pCalPier = &(eep->calFreqPier2G[ipier]);
1630 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1631 is2GHz = 1;
1632 }
1633
1634 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1635 *pcorrection = pCalPierStruct->refPower;
1636 *ptemperature = pCalPierStruct->tempMeas;
1637 *pvoltage = pCalPierStruct->voltMeas;
1638
1639 return 0;
1640}
1641
1642static int ar9003_hw_power_control_override(struct ath_hw *ah,
1643 int frequency,
1644 int *correction,
1645 int *voltage, int *temperature)
1646{
1647 int tempSlope = 0;
1648 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1649
1650 REG_RMW(ah, AR_PHY_TPC_11_B0,
1651 (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1652 AR_PHY_TPC_OLPC_GAIN_DELTA);
1653 REG_RMW(ah, AR_PHY_TPC_11_B1,
1654 (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1655 AR_PHY_TPC_OLPC_GAIN_DELTA);
1656 REG_RMW(ah, AR_PHY_TPC_11_B2,
1657 (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1658 AR_PHY_TPC_OLPC_GAIN_DELTA);
1659
1660 /* enable open loop power control on chip */
1661 REG_RMW(ah, AR_PHY_TPC_6_B0,
1662 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1663 AR_PHY_TPC_6_ERROR_EST_MODE);
1664 REG_RMW(ah, AR_PHY_TPC_6_B1,
1665 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1666 AR_PHY_TPC_6_ERROR_EST_MODE);
1667 REG_RMW(ah, AR_PHY_TPC_6_B2,
1668 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1669 AR_PHY_TPC_6_ERROR_EST_MODE);
1670
1671 /*
1672 * enable temperature compensation
1673 * Need to use register names
1674 */
1675 if (frequency < 4000)
1676 tempSlope = eep->modalHeader2G.tempSlope;
1677 else
1678 tempSlope = eep->modalHeader5G.tempSlope;
1679
1680 REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
1681 REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
1682 temperature[0]);
1683
1684 return 0;
1685}
1686
1687/* Apply the recorded correction values. */
1688static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1689{
1690 int ichain, ipier, npier;
1691 int mode;
1692 int lfrequency[AR9300_MAX_CHAINS],
1693 lcorrection[AR9300_MAX_CHAINS],
1694 ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
1695 int hfrequency[AR9300_MAX_CHAINS],
1696 hcorrection[AR9300_MAX_CHAINS],
1697 htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
1698 int fdiff;
1699 int correction[AR9300_MAX_CHAINS],
1700 voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
1701 int pfrequency, pcorrection, ptemperature, pvoltage;
1702 struct ath_common *common = ath9k_hw_common(ah);
1703
1704 mode = (frequency >= 4000);
1705 if (mode)
1706 npier = AR9300_NUM_5G_CAL_PIERS;
1707 else
1708 npier = AR9300_NUM_2G_CAL_PIERS;
1709
1710 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1711 lfrequency[ichain] = 0;
1712 hfrequency[ichain] = 100000;
1713 }
1714 /* identify best lower and higher frequency calibration measurement */
1715 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1716 for (ipier = 0; ipier < npier; ipier++) {
1717 if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
1718 &pfrequency, &pcorrection,
1719 &ptemperature, &pvoltage)) {
1720 fdiff = frequency - pfrequency;
1721
1722 /*
1723 * this measurement is higher than
1724 * our desired frequency
1725 */
1726 if (fdiff <= 0) {
1727 if (hfrequency[ichain] <= 0 ||
1728 hfrequency[ichain] >= 100000 ||
1729 fdiff >
1730 (frequency - hfrequency[ichain])) {
1731 /*
1732 * new best higher
1733 * frequency measurement
1734 */
1735 hfrequency[ichain] = pfrequency;
1736 hcorrection[ichain] =
1737 pcorrection;
1738 htemperature[ichain] =
1739 ptemperature;
1740 hvoltage[ichain] = pvoltage;
1741 }
1742 }
1743 if (fdiff >= 0) {
1744 if (lfrequency[ichain] <= 0
1745 || fdiff <
1746 (frequency - lfrequency[ichain])) {
1747 /*
1748 * new best lower
1749 * frequency measurement
1750 */
1751 lfrequency[ichain] = pfrequency;
1752 lcorrection[ichain] =
1753 pcorrection;
1754 ltemperature[ichain] =
1755 ptemperature;
1756 lvoltage[ichain] = pvoltage;
1757 }
1758 }
1759 }
1760 }
1761 }
1762
1763 /* interpolate */
1764 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1765 ath_print(common, ATH_DBG_EEPROM,
1766 "ch=%d f=%d low=%d %d h=%d %d\n",
1767 ichain, frequency, lfrequency[ichain],
1768 lcorrection[ichain], hfrequency[ichain],
1769 hcorrection[ichain]);
1770 /* they're the same, so just pick one */
1771 if (hfrequency[ichain] == lfrequency[ichain]) {
1772 correction[ichain] = lcorrection[ichain];
1773 voltage[ichain] = lvoltage[ichain];
1774 temperature[ichain] = ltemperature[ichain];
1775 }
1776 /* the low frequency is good */
1777 else if (frequency - lfrequency[ichain] < 1000) {
1778 /* so is the high frequency, interpolate */
1779 if (hfrequency[ichain] - frequency < 1000) {
1780
1781 correction[ichain] = lcorrection[ichain] +
1782 (((frequency - lfrequency[ichain]) *
1783 (hcorrection[ichain] -
1784 lcorrection[ichain])) /
1785 (hfrequency[ichain] - lfrequency[ichain]));
1786
1787 temperature[ichain] = ltemperature[ichain] +
1788 (((frequency - lfrequency[ichain]) *
1789 (htemperature[ichain] -
1790 ltemperature[ichain])) /
1791 (hfrequency[ichain] - lfrequency[ichain]));
1792
1793 voltage[ichain] =
1794 lvoltage[ichain] +
1795 (((frequency -
1796 lfrequency[ichain]) * (hvoltage[ichain] -
1797 lvoltage[ichain]))
1798 / (hfrequency[ichain] -
1799 lfrequency[ichain]));
1800 }
1801 /* only low is good, use it */
1802 else {
1803 correction[ichain] = lcorrection[ichain];
1804 temperature[ichain] = ltemperature[ichain];
1805 voltage[ichain] = lvoltage[ichain];
1806 }
1807 }
1808 /* only high is good, use it */
1809 else if (hfrequency[ichain] - frequency < 1000) {
1810 correction[ichain] = hcorrection[ichain];
1811 temperature[ichain] = htemperature[ichain];
1812 voltage[ichain] = hvoltage[ichain];
1813 } else { /* nothing is good, presume 0???? */
1814 correction[ichain] = 0;
1815 temperature[ichain] = 0;
1816 voltage[ichain] = 0;
1817 }
1818 }
1819
1820 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1821 temperature);
1822
1823 ath_print(common, ATH_DBG_EEPROM,
1824 "for frequency=%d, calibration correction = %d %d %d\n",
1825 frequency, correction[0], correction[1], correction[2]);
1826
1827 return 0;
1828}
1829
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04001830static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
1831 int idx,
1832 int edge,
1833 bool is2GHz)
1834{
1835 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1836 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1837
1838 if (is2GHz)
1839 return ctl_2g[idx].ctlEdges[edge].tPower;
1840 else
1841 return ctl_5g[idx].ctlEdges[edge].tPower;
1842}
1843
1844static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
1845 int idx,
1846 unsigned int edge,
1847 u16 freq,
1848 bool is2GHz)
1849{
1850 struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
1851 struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
1852
1853 u8 *ctl_freqbin = is2GHz ?
1854 &eep->ctl_freqbin_2G[idx][0] :
1855 &eep->ctl_freqbin_5G[idx][0];
1856
1857 if (is2GHz) {
1858 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
1859 ctl_2g[idx].ctlEdges[edge - 1].flag)
1860 return ctl_2g[idx].ctlEdges[edge - 1].tPower;
1861 } else {
1862 if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
1863 ctl_5g[idx].ctlEdges[edge - 1].flag)
1864 return ctl_5g[idx].ctlEdges[edge - 1].tPower;
1865 }
1866
1867 return AR9300_MAX_RATE_POWER;
1868}
1869
1870/*
1871 * Find the maximum conformance test limit for the given channel and CTL info
1872 */
1873static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
1874 u16 freq, int idx, bool is2GHz)
1875{
1876 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1877 u8 *ctl_freqbin = is2GHz ?
1878 &eep->ctl_freqbin_2G[idx][0] :
1879 &eep->ctl_freqbin_5G[idx][0];
1880 u16 num_edges = is2GHz ?
1881 AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G;
1882 unsigned int edge;
1883
1884 /* Get the edge power */
1885 for (edge = 0;
1886 (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
1887 edge++) {
1888 /*
1889 * If there's an exact channel match or an inband flag set
1890 * on the lower channel use the given rdEdgePower
1891 */
1892 if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
1893 twiceMaxEdgePower =
1894 ar9003_hw_get_direct_edge_power(eep, idx,
1895 edge, is2GHz);
1896 break;
1897 } else if ((edge > 0) &&
1898 (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
1899 is2GHz))) {
1900 twiceMaxEdgePower =
1901 ar9003_hw_get_indirect_edge_power(eep, idx,
1902 edge, freq,
1903 is2GHz);
1904 /*
1905 * Leave loop - no more affecting edges possible in
1906 * this monotonic increasing list
1907 */
1908 break;
1909 }
1910 }
1911 return twiceMaxEdgePower;
1912}
1913
1914static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
1915 struct ath9k_channel *chan,
1916 u8 *pPwrArray, u16 cfgCtl,
1917 u8 twiceAntennaReduction,
1918 u8 twiceMaxRegulatoryPower,
1919 u16 powerLimit)
1920{
1921 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
1922 struct ath_common *common = ath9k_hw_common(ah);
1923 struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
1924 u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
1925 static const u16 tpScaleReductionTable[5] = {
1926 0, 3, 6, 9, AR9300_MAX_RATE_POWER
1927 };
1928 int i;
1929 int16_t twiceLargestAntenna;
1930 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
1931 u16 ctlModesFor11a[] = {
1932 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
1933 };
1934 u16 ctlModesFor11g[] = {
1935 CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
1936 CTL_11G_EXT, CTL_2GHT40
1937 };
1938 u16 numCtlModes, *pCtlMode, ctlMode, freq;
1939 struct chan_centers centers;
1940 u8 *ctlIndex;
1941 u8 ctlNum;
1942 u16 twiceMinEdgePower;
1943 bool is2ghz = IS_CHAN_2GHZ(chan);
1944
1945 ath9k_hw_get_channel_centers(ah, chan, &centers);
1946
1947 /* Compute TxPower reduction due to Antenna Gain */
1948 if (is2ghz)
1949 twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
1950 else
1951 twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
1952
1953 twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
1954 twiceLargestAntenna, 0);
1955
1956 /*
1957 * scaledPower is the minimum of the user input power level
1958 * and the regulatory allowed power level
1959 */
1960 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
1961
1962 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
1963 maxRegAllowedPower -=
1964 (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
1965 }
1966
1967 scaledPower = min(powerLimit, maxRegAllowedPower);
1968
1969 /*
1970 * Reduce scaled Power by number of chains active to get
1971 * to per chain tx power level
1972 */
1973 switch (ar5416_get_ntxchains(ah->txchainmask)) {
1974 case 1:
1975 break;
1976 case 2:
1977 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
1978 break;
1979 case 3:
1980 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
1981 break;
1982 }
1983
1984 scaledPower = max((u16)0, scaledPower);
1985
1986 /*
1987 * Get target powers from EEPROM - our baseline for TX Power
1988 */
1989 if (is2ghz) {
1990 /* Setup for CTL modes */
1991 /* CTL_11B, CTL_11G, CTL_2GHT20 */
1992 numCtlModes =
1993 ARRAY_SIZE(ctlModesFor11g) -
1994 SUB_NUM_CTL_MODES_AT_2G_40;
1995 pCtlMode = ctlModesFor11g;
1996 if (IS_CHAN_HT40(chan))
1997 /* All 2G CTL's */
1998 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
1999 } else {
2000 /* Setup for CTL modes */
2001 /* CTL_11A, CTL_5GHT20 */
2002 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
2003 SUB_NUM_CTL_MODES_AT_5G_40;
2004 pCtlMode = ctlModesFor11a;
2005 if (IS_CHAN_HT40(chan))
2006 /* All 5G CTL's */
2007 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
2008 }
2009
2010 /*
2011 * For MIMO, need to apply regulatory caps individually across
2012 * dynamically running modes: CCK, OFDM, HT20, HT40
2013 *
2014 * The outer loop walks through each possible applicable runtime mode.
2015 * The inner loop walks through each ctlIndex entry in EEPROM.
2016 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2017 */
2018 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2019 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2020 (pCtlMode[ctlMode] == CTL_2GHT40);
2021 if (isHt40CtlMode)
2022 freq = centers.synth_center;
2023 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2024 freq = centers.ext_center;
2025 else
2026 freq = centers.ctl_center;
2027
2028 ath_print(common, ATH_DBG_REGULATORY,
2029 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2030 "EXT_ADDITIVE %d\n",
2031 ctlMode, numCtlModes, isHt40CtlMode,
2032 (pCtlMode[ctlMode] & EXT_ADDITIVE));
2033
2034 /* walk through each CTL index stored in EEPROM */
2035 if (is2ghz) {
2036 ctlIndex = pEepData->ctlIndex_2G;
2037 ctlNum = AR9300_NUM_CTLS_2G;
2038 } else {
2039 ctlIndex = pEepData->ctlIndex_5G;
2040 ctlNum = AR9300_NUM_CTLS_5G;
2041 }
2042
2043 for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
2044 ath_print(common, ATH_DBG_REGULATORY,
2045 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2046 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2047 "chan %dn",
2048 i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
2049 chan->channel);
2050
2051 /*
2052 * compare test group from regulatory
2053 * channel list with test mode from pCtlMode
2054 * list
2055 */
2056 if ((((cfgCtl & ~CTL_MODE_M) |
2057 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2058 ctlIndex[i]) ||
2059 (((cfgCtl & ~CTL_MODE_M) |
2060 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2061 ((ctlIndex[i] & CTL_MODE_M) |
2062 SD_NO_CTL))) {
2063 twiceMinEdgePower =
2064 ar9003_hw_get_max_edge_power(pEepData,
2065 freq, i,
2066 is2ghz);
2067
2068 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
2069 /*
2070 * Find the minimum of all CTL
2071 * edge powers that apply to
2072 * this channel
2073 */
2074 twiceMaxEdgePower =
2075 min(twiceMaxEdgePower,
2076 twiceMinEdgePower);
2077 else {
2078 /* specific */
2079 twiceMaxEdgePower =
2080 twiceMinEdgePower;
2081 break;
2082 }
2083 }
2084 }
2085
2086 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
2087
2088 ath_print(common, ATH_DBG_REGULATORY,
2089 "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
2090 "sP %d minCtlPwr %d\n",
2091 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
2092 scaledPower, minCtlPower);
2093
2094 /* Apply ctl mode to correct target power set */
2095 switch (pCtlMode[ctlMode]) {
2096 case CTL_11B:
2097 for (i = ALL_TARGET_LEGACY_1L_5L;
2098 i <= ALL_TARGET_LEGACY_11S; i++)
2099 pPwrArray[i] =
2100 (u8)min((u16)pPwrArray[i],
2101 minCtlPower);
2102 break;
2103 case CTL_11A:
2104 case CTL_11G:
2105 for (i = ALL_TARGET_LEGACY_6_24;
2106 i <= ALL_TARGET_LEGACY_54; i++)
2107 pPwrArray[i] =
2108 (u8)min((u16)pPwrArray[i],
2109 minCtlPower);
2110 break;
2111 case CTL_5GHT20:
2112 case CTL_2GHT20:
2113 for (i = ALL_TARGET_HT20_0_8_16;
2114 i <= ALL_TARGET_HT20_21; i++)
2115 pPwrArray[i] =
2116 (u8)min((u16)pPwrArray[i],
2117 minCtlPower);
2118 pPwrArray[ALL_TARGET_HT20_22] =
2119 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
2120 minCtlPower);
2121 pPwrArray[ALL_TARGET_HT20_23] =
2122 (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
2123 minCtlPower);
2124 break;
2125 case CTL_5GHT40:
2126 case CTL_2GHT40:
2127 for (i = ALL_TARGET_HT40_0_8_16;
2128 i <= ALL_TARGET_HT40_23; i++)
2129 pPwrArray[i] =
2130 (u8)min((u16)pPwrArray[i],
2131 minCtlPower);
2132 break;
2133 default:
2134 break;
2135 }
2136 } /* end ctl mode checking */
2137}
2138
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04002139static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
2140 struct ath9k_channel *chan, u16 cfgCtl,
2141 u8 twiceAntennaReduction,
2142 u8 twiceMaxRegulatoryPower,
Felix Fietkaude40f312010-10-20 03:08:53 +02002143 u8 powerLimit, bool test)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04002144{
Felix Fietkau6b7b6cf2010-10-20 02:09:44 +02002145 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04002146 struct ath_common *common = ath9k_hw_common(ah);
2147 u8 targetPowerValT2[ar9300RateSize];
2148 unsigned int i = 0;
2149
2150 ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
2151 ar9003_hw_set_power_per_rate_table(ah, chan,
2152 targetPowerValT2, cfgCtl,
2153 twiceAntennaReduction,
2154 twiceMaxRegulatoryPower,
2155 powerLimit);
2156
Felix Fietkaude40f312010-10-20 03:08:53 +02002157 regulatory->max_power_level = 0;
2158 for (i = 0; i < ar9300RateSize; i++) {
2159 if (targetPowerValT2[i] > regulatory->max_power_level)
2160 regulatory->max_power_level = targetPowerValT2[i];
2161 }
2162
2163 if (test)
2164 return;
2165
2166 for (i = 0; i < ar9300RateSize; i++) {
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04002167 ath_print(common, ATH_DBG_EEPROM,
2168 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2169 i++;
2170 ath_print(common, ATH_DBG_EEPROM,
2171 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2172 i++;
2173 ath_print(common, ATH_DBG_EEPROM,
2174 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
2175 i++;
2176 ath_print(common, ATH_DBG_EEPROM,
2177 "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
2178 i++;
2179 }
2180
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04002181 /*
2182 * This is the TX power we send back to driver core,
2183 * and it can use to pass to userspace to display our
2184 * currently configured TX power setting.
2185 *
2186 * Since power is rate dependent, use one of the indices
2187 * from the AR9300_Rates enum to select an entry from
2188 * targetPowerValT2[] to report. Currently returns the
2189 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
2190 * as CCK power is less interesting (?).
2191 */
2192 i = ALL_TARGET_LEGACY_6_24; /* legacy */
2193 if (IS_CHAN_HT40(chan))
2194 i = ALL_TARGET_HT40_0_8_16; /* ht40 */
2195 else if (IS_CHAN_HT20(chan))
2196 i = ALL_TARGET_HT20_0_8_16; /* ht20 */
2197
2198 ah->txpower_limit = targetPowerValT2[i];
Felix Fietkaude40f312010-10-20 03:08:53 +02002199 regulatory->max_power_level = targetPowerValT2[i];
Luis R. Rodriguez824b1852010-08-01 02:25:16 -04002200
Felix Fietkaude40f312010-10-20 03:08:53 +02002201 /* Write target power array to registers */
2202 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04002203 ar9003_hw_calibration_apply(ah, chan->channel);
2204}
2205
2206static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
2207 u16 i, bool is2GHz)
2208{
2209 return AR_NO_SPUR;
2210}
2211
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -04002212s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
2213{
2214 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2215
2216 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
2217}
2218
2219s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
2220{
2221 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
2222
2223 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
2224}
2225
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04002226const struct eeprom_ops eep_ar9300_ops = {
2227 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
2228 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
2229 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
2230 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
2231 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
2232 .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
2233 .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
2234 .set_board_values = ath9k_hw_ar9300_set_board_values,
2235 .set_addac = ath9k_hw_ar9300_set_addac,
2236 .set_txpower = ath9k_hw_ar9300_set_txpower,
2237 .get_spur_channel = ath9k_hw_ar9300_get_spur_channel
2238};