blob: ace8d2678b18a890c3d64b2756623ce0f29be9c4 [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
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040044static const struct ar9300_eeprom ar9300_default = {
45 .eepromVersion = 2,
46 .templateVersion = 2,
47 .macAddr = {1, 2, 3, 4, 5, 6},
48 .custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
50 .baseEepHeader = {
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020051 .regDmn = { LE16(0), LE16(0x1f) },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040052 .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
53 .opCapFlags = {
54 .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
55 .eepMisc = 0,
56 },
57 .rfSilent = 0,
58 .blueToothOptions = 0,
59 .deviceCap = 0,
60 .deviceType = 5, /* takes lower byte in eeprom location */
61 .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
62 .params_for_tuning_caps = {0, 0},
63 .featureEnable = 0x0c,
64 /*
65 * bit0 - enable tx temp comp - disabled
66 * bit1 - enable tx volt comp - disabled
67 * bit2 - enable fastClock - enabled
68 * bit3 - enable doubling - enabled
69 * bit4 - enable internal regulator - disabled
Felix Fietkau49352502010-06-12 00:33:59 -040070 * bit5 - enable pa predistortion - disabled
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040071 */
72 .miscConfiguration = 0, /* bit0 - turn down drivestrength */
73 .eepromWriteEnableGpio = 3,
74 .wlanDisableGpio = 0,
75 .wlanLedGpio = 8,
76 .rxBandSelectGpio = 0xff,
77 .txrxgain = 0,
78 .swreg = 0,
79 },
80 .modalHeader2G = {
81 /* ar9300_modal_eep_header 2g */
82 /* 4 idle,t1,t2,b(4 bits per setting) */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020083 .antCtrlCommon = LE32(0x110),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040084 /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020085 .antCtrlCommon2 = LE32(0x22222),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040086
87 /*
88 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
89 * rx1, rx12, b (2 bits each)
90 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +020091 .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -040092
93 /*
94 * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
95 * for ar9280 (0xa20c/b20c 5:0)
96 */
97 .xatten1DB = {0, 0, 0},
98
99 /*
100 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
101 * for ar9280 (0xa20c/b20c 16:12
102 */
103 .xatten1Margin = {0, 0, 0},
104 .tempSlope = 36,
105 .voltSlope = 0,
106
107 /*
108 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
109 * channels in usual fbin coding format
110 */
111 .spurChans = {0, 0, 0, 0, 0},
112
113 /*
114 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
115 * if the register is per chain
116 */
117 .noiseFloorThreshCh = {-1, 0, 0},
118 .ob = {1, 1, 1},/* 3 chain */
119 .db_stage2 = {1, 1, 1}, /* 3 chain */
120 .db_stage3 = {0, 0, 0},
121 .db_stage4 = {0, 0, 0},
122 .xpaBiasLvl = 0,
123 .txFrameToDataStart = 0x0e,
124 .txFrameToPaOn = 0x0e,
125 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
126 .antennaGain = 0,
127 .switchSettling = 0x2c,
128 .adcDesiredSize = -30,
129 .txEndToXpaOff = 0,
130 .txEndToRxOn = 0x2,
131 .txFrameToXpaOn = 0xe,
132 .thresh62 = 28,
Felix Fietkau49352502010-06-12 00:33:59 -0400133 .papdRateMaskHt20 = LE32(0x80c080),
134 .papdRateMaskHt40 = LE32(0x80c080),
135 .futureModal = {
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Felix Fietkau49352502010-06-12 00:33:59 -0400137 0, 0, 0, 0, 0, 0, 0, 0
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400138 },
139 },
140 .calFreqPier2G = {
141 FREQ2FBIN(2412, 1),
142 FREQ2FBIN(2437, 1),
143 FREQ2FBIN(2472, 1),
144 },
145 /* ar9300_cal_data_per_freq_op_loop 2g */
146 .calPierData2G = {
147 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
148 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
149 { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
150 },
151 .calTarget_freqbin_Cck = {
152 FREQ2FBIN(2412, 1),
153 FREQ2FBIN(2484, 1),
154 },
155 .calTarget_freqbin_2G = {
156 FREQ2FBIN(2412, 1),
157 FREQ2FBIN(2437, 1),
158 FREQ2FBIN(2472, 1)
159 },
160 .calTarget_freqbin_2GHT20 = {
161 FREQ2FBIN(2412, 1),
162 FREQ2FBIN(2437, 1),
163 FREQ2FBIN(2472, 1)
164 },
165 .calTarget_freqbin_2GHT40 = {
166 FREQ2FBIN(2412, 1),
167 FREQ2FBIN(2437, 1),
168 FREQ2FBIN(2472, 1)
169 },
170 .calTargetPowerCck = {
171 /* 1L-5L,5S,11L,11S */
172 { {36, 36, 36, 36} },
173 { {36, 36, 36, 36} },
174 },
175 .calTargetPower2G = {
176 /* 6-24,36,48,54 */
177 { {32, 32, 28, 24} },
178 { {32, 32, 28, 24} },
179 { {32, 32, 28, 24} },
180 },
181 .calTargetPower2GHT20 = {
182 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
183 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
184 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
185 },
186 .calTargetPower2GHT40 = {
187 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
188 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
189 { {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} },
190 },
191 .ctlIndex_2G = {
192 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
193 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
194 },
195 .ctl_freqbin_2G = {
196 {
197 FREQ2FBIN(2412, 1),
198 FREQ2FBIN(2417, 1),
199 FREQ2FBIN(2457, 1),
200 FREQ2FBIN(2462, 1)
201 },
202 {
203 FREQ2FBIN(2412, 1),
204 FREQ2FBIN(2417, 1),
205 FREQ2FBIN(2462, 1),
206 0xFF,
207 },
208
209 {
210 FREQ2FBIN(2412, 1),
211 FREQ2FBIN(2417, 1),
212 FREQ2FBIN(2462, 1),
213 0xFF,
214 },
215 {
216 FREQ2FBIN(2422, 1),
217 FREQ2FBIN(2427, 1),
218 FREQ2FBIN(2447, 1),
219 FREQ2FBIN(2452, 1)
220 },
221
222 {
223 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
224 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
225 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
226 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
227 },
228
229 {
230 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
231 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
232 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
233 0,
234 },
235
236 {
237 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
238 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
239 FREQ2FBIN(2472, 1),
240 0,
241 },
242
243 {
244 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
245 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
246 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
247 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
248 },
249
250 {
251 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
252 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
253 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
254 },
255
256 {
257 /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
258 /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
259 /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
260 0
261 },
262
263 {
264 /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
265 /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
266 /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
267 0
268 },
269
270 {
271 /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
272 /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
273 /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
274 /* Data[11].ctlEdges[3].bChannel */
275 FREQ2FBIN(2462, 1),
276 }
277 },
278 .ctlPowerData_2G = {
279 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
280 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
281 { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } },
282
283 { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } },
284 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
285 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
286
287 { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } },
288 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
289 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
290
291 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } },
292 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } },
293 },
294 .modalHeader5G = {
295 /* 4 idle,t1,t2,b (4 bits per setting) */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200296 .antCtrlCommon = LE32(0x110),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400297 /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200298 .antCtrlCommon2 = LE32(0x22222),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400299 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
300 .antCtrlChain = {
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200301 LE16(0x000), LE16(0x000), LE16(0x000),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400302 },
303 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
304 .xatten1DB = {0, 0, 0},
305
306 /*
307 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
308 * for merlin (0xa20c/b20c 16:12
309 */
310 .xatten1Margin = {0, 0, 0},
311 .tempSlope = 68,
312 .voltSlope = 0,
313 /* spurChans spur channels in usual fbin coding format */
314 .spurChans = {0, 0, 0, 0, 0},
315 /* noiseFloorThreshCh Check if the register is per chain */
316 .noiseFloorThreshCh = {-1, 0, 0},
317 .ob = {3, 3, 3}, /* 3 chain */
318 .db_stage2 = {3, 3, 3}, /* 3 chain */
319 .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
320 .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
321 .xpaBiasLvl = 0,
322 .txFrameToDataStart = 0x0e,
323 .txFrameToPaOn = 0x0e,
324 .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
325 .antennaGain = 0,
326 .switchSettling = 0x2d,
327 .adcDesiredSize = -30,
328 .txEndToXpaOff = 0,
329 .txEndToRxOn = 0x2,
330 .txFrameToXpaOn = 0xe,
331 .thresh62 = 28,
Felix Fietkau49352502010-06-12 00:33:59 -0400332 .papdRateMaskHt20 = LE32(0xf0e0e0),
333 .papdRateMaskHt40 = LE32(0xf0e0e0),
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400334 .futureModal = {
335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Felix Fietkau49352502010-06-12 00:33:59 -0400336 0, 0, 0, 0, 0, 0, 0, 0
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400337 },
338 },
339 .calFreqPier5G = {
340 FREQ2FBIN(5180, 0),
341 FREQ2FBIN(5220, 0),
342 FREQ2FBIN(5320, 0),
343 FREQ2FBIN(5400, 0),
344 FREQ2FBIN(5500, 0),
345 FREQ2FBIN(5600, 0),
346 FREQ2FBIN(5725, 0),
347 FREQ2FBIN(5825, 0)
348 },
349 .calPierData5G = {
350 {
351 {0, 0, 0, 0, 0},
352 {0, 0, 0, 0, 0},
353 {0, 0, 0, 0, 0},
354 {0, 0, 0, 0, 0},
355 {0, 0, 0, 0, 0},
356 {0, 0, 0, 0, 0},
357 {0, 0, 0, 0, 0},
358 {0, 0, 0, 0, 0},
359 },
360 {
361 {0, 0, 0, 0, 0},
362 {0, 0, 0, 0, 0},
363 {0, 0, 0, 0, 0},
364 {0, 0, 0, 0, 0},
365 {0, 0, 0, 0, 0},
366 {0, 0, 0, 0, 0},
367 {0, 0, 0, 0, 0},
368 {0, 0, 0, 0, 0},
369 },
370 {
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},
378 {0, 0, 0, 0, 0},
379 },
380
381 },
382 .calTarget_freqbin_5G = {
383 FREQ2FBIN(5180, 0),
384 FREQ2FBIN(5220, 0),
385 FREQ2FBIN(5320, 0),
386 FREQ2FBIN(5400, 0),
387 FREQ2FBIN(5500, 0),
388 FREQ2FBIN(5600, 0),
389 FREQ2FBIN(5725, 0),
390 FREQ2FBIN(5825, 0)
391 },
392 .calTarget_freqbin_5GHT20 = {
393 FREQ2FBIN(5180, 0),
394 FREQ2FBIN(5240, 0),
395 FREQ2FBIN(5320, 0),
396 FREQ2FBIN(5500, 0),
397 FREQ2FBIN(5700, 0),
398 FREQ2FBIN(5745, 0),
399 FREQ2FBIN(5725, 0),
400 FREQ2FBIN(5825, 0)
401 },
402 .calTarget_freqbin_5GHT40 = {
403 FREQ2FBIN(5180, 0),
404 FREQ2FBIN(5240, 0),
405 FREQ2FBIN(5320, 0),
406 FREQ2FBIN(5500, 0),
407 FREQ2FBIN(5700, 0),
408 FREQ2FBIN(5745, 0),
409 FREQ2FBIN(5725, 0),
410 FREQ2FBIN(5825, 0)
411 },
412 .calTargetPower5G = {
413 /* 6-24,36,48,54 */
414 { {20, 20, 20, 10} },
415 { {20, 20, 20, 10} },
416 { {20, 20, 20, 10} },
417 { {20, 20, 20, 10} },
418 { {20, 20, 20, 10} },
419 { {20, 20, 20, 10} },
420 { {20, 20, 20, 10} },
421 { {20, 20, 20, 10} },
422 },
423 .calTargetPower5GHT20 = {
424 /*
425 * 0_8_16,1-3_9-11_17-19,
426 * 4,5,6,7,12,13,14,15,20,21,22,23
427 */
428 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
429 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
430 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
431 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
432 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
433 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
434 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
435 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
436 },
437 .calTargetPower5GHT40 = {
438 /*
439 * 0_8_16,1-3_9-11_17-19,
440 * 4,5,6,7,12,13,14,15,20,21,22,23
441 */
442 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
443 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
444 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
445 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
446 { {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} },
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 },
451 .ctlIndex_5G = {
452 0x10, 0x16, 0x18, 0x40, 0x46,
453 0x48, 0x30, 0x36, 0x38
454 },
455 .ctl_freqbin_5G = {
456 {
457 /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
458 /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
459 /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
460 /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
461 /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
462 /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
463 /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
464 /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
465 },
466 {
467 /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
468 /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
469 /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
470 /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
471 /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
472 /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
473 /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
474 /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
475 },
476
477 {
478 /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
479 /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
480 /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
481 /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
482 /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
483 /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
484 /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
485 /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
486 },
487
488 {
489 /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
490 /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
491 /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
492 /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
493 /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
494 /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
495 /* Data[3].ctlEdges[6].bChannel */ 0xFF,
496 /* Data[3].ctlEdges[7].bChannel */ 0xFF,
497 },
498
499 {
500 /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
501 /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
502 /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
503 /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
504 /* Data[4].ctlEdges[4].bChannel */ 0xFF,
505 /* Data[4].ctlEdges[5].bChannel */ 0xFF,
506 /* Data[4].ctlEdges[6].bChannel */ 0xFF,
507 /* Data[4].ctlEdges[7].bChannel */ 0xFF,
508 },
509
510 {
511 /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
512 /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
513 /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
514 /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
515 /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
516 /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
517 /* Data[5].ctlEdges[6].bChannel */ 0xFF,
518 /* Data[5].ctlEdges[7].bChannel */ 0xFF
519 },
520
521 {
522 /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
523 /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
524 /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
525 /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
526 /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
527 /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
528 /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
529 /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
530 },
531
532 {
533 /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
534 /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
535 /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
536 /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
537 /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
538 /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
539 /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
540 /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
541 },
542
543 {
544 /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
545 /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
546 /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
547 /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
548 /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
549 /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
550 /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
551 /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
552 }
553 },
554 .ctlPowerData_5G = {
555 {
556 {
557 {60, 1}, {60, 1}, {60, 1}, {60, 1},
558 {60, 1}, {60, 1}, {60, 1}, {60, 0},
559 }
560 },
561 {
562 {
563 {60, 1}, {60, 1}, {60, 1}, {60, 1},
564 {60, 1}, {60, 1}, {60, 1}, {60, 0},
565 }
566 },
567 {
568 {
569 {60, 0}, {60, 1}, {60, 0}, {60, 1},
570 {60, 1}, {60, 1}, {60, 1}, {60, 1},
571 }
572 },
573 {
574 {
575 {60, 0}, {60, 1}, {60, 1}, {60, 0},
576 {60, 1}, {60, 0}, {60, 0}, {60, 0},
577 }
578 },
579 {
580 {
581 {60, 1}, {60, 1}, {60, 1}, {60, 0},
582 {60, 0}, {60, 0}, {60, 0}, {60, 0},
583 }
584 },
585 {
586 {
587 {60, 1}, {60, 1}, {60, 1}, {60, 1},
588 {60, 1}, {60, 0}, {60, 0}, {60, 0},
589 }
590 },
591 {
592 {
593 {60, 1}, {60, 1}, {60, 1}, {60, 1},
594 {60, 1}, {60, 1}, {60, 1}, {60, 1},
595 }
596 },
597 {
598 {
599 {60, 1}, {60, 1}, {60, 0}, {60, 1},
600 {60, 1}, {60, 1}, {60, 1}, {60, 0},
601 }
602 },
603 {
604 {
605 {60, 1}, {60, 0}, {60, 1}, {60, 1},
606 {60, 1}, {60, 1}, {60, 0}, {60, 1},
607 }
608 },
609 }
610};
611
612static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
613{
614 return 0;
615}
616
617static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
618 enum eeprom_param param)
619{
620 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
621 struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
622
623 switch (param) {
624 case EEP_MAC_LSW:
625 return eep->macAddr[0] << 8 | eep->macAddr[1];
626 case EEP_MAC_MID:
627 return eep->macAddr[2] << 8 | eep->macAddr[3];
628 case EEP_MAC_MSW:
629 return eep->macAddr[4] << 8 | eep->macAddr[5];
630 case EEP_REG_0:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200631 return le16_to_cpu(pBase->regDmn[0]);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400632 case EEP_REG_1:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200633 return le16_to_cpu(pBase->regDmn[1]);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400634 case EEP_OP_CAP:
635 return pBase->deviceCap;
636 case EEP_OP_MODE:
637 return pBase->opCapFlags.opFlags;
638 case EEP_RF_SILENT:
639 return pBase->rfSilent;
640 case EEP_TX_MASK:
641 return (pBase->txrxMask >> 4) & 0xf;
642 case EEP_RX_MASK:
643 return pBase->txrxMask & 0xf;
644 case EEP_DRIVE_STRENGTH:
645#define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
646 return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
647 case EEP_INTERNAL_REGULATOR:
648 /* Bit 4 is internal regulator flag */
649 return (pBase->featureEnable & 0x10) >> 4;
650 case EEP_SWREG:
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200651 return le32_to_cpu(pBase->swreg);
Felix Fietkau49352502010-06-12 00:33:59 -0400652 case EEP_PAPRD:
653 return !!(pBase->featureEnable & BIT(5));
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400654 default:
655 return 0;
656 }
657}
658
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200659static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
660 u8 *buffer)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400661{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200662 u16 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400663
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200664 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
665 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400666
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200667 *buffer = (val >> (8 * (address % 2))) & 0xff;
668 return true;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400669}
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400670
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200671static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
672 u8 *buffer)
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400673{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200674 u16 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400675
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200676 if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
677 return false;
678
679 buffer[0] = val >> 8;
680 buffer[1] = val & 0xff;
681
682 return true;
683}
684
685static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
686 int count)
687{
688 struct ath_common *common = ath9k_hw_common(ah);
689 int i;
690
691 if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400692 ath_print(common, ATH_DBG_EEPROM,
693 "eeprom address not in range\n");
694 return false;
695 }
696
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200697 /*
698 * Since we're reading the bytes in reverse order from a little-endian
699 * word stream, an even address means we only use the lower half of
700 * the 16-bit word at that address
701 */
702 if (address % 2 == 0) {
703 if (!ar9300_eeprom_read_byte(common, address--, buffer++))
704 goto error;
705
706 count--;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400707 }
708
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200709 for (i = 0; i < count / 2; i++) {
710 if (!ar9300_eeprom_read_word(common, address, buffer))
711 goto error;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400712
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200713 address -= 2;
714 buffer += 2;
715 }
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400716
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200717 if (count % 2)
718 if (!ar9300_eeprom_read_byte(common, address, buffer))
719 goto error;
720
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400721 return true;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200722
723error:
724 ath_print(common, ATH_DBG_EEPROM,
725 "unable to read eeprom region at offset %d\n", address);
726 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400727}
728
729static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
730 int *length, int *major, int *minor)
731{
732 unsigned long value[4];
733
734 value[0] = best[0];
735 value[1] = best[1];
736 value[2] = best[2];
737 value[3] = best[3];
738 *code = ((value[0] >> 5) & 0x0007);
739 *reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
740 *length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
741 *major = (value[2] & 0x000f);
742 *minor = (value[3] & 0x00ff);
743}
744
745static u16 ar9300_comp_cksum(u8 *data, int dsize)
746{
747 int it, checksum = 0;
748
749 for (it = 0; it < dsize; it++) {
750 checksum += data[it];
751 checksum &= 0xffff;
752 }
753
754 return checksum;
755}
756
757static bool ar9300_uncompress_block(struct ath_hw *ah,
758 u8 *mptr,
759 int mdataSize,
760 u8 *block,
761 int size)
762{
763 int it;
764 int spot;
765 int offset;
766 int length;
767 struct ath_common *common = ath9k_hw_common(ah);
768
769 spot = 0;
770
771 for (it = 0; it < size; it += (length+2)) {
772 offset = block[it];
773 offset &= 0xff;
774 spot += offset;
775 length = block[it+1];
776 length &= 0xff;
777
778 if (length > 0 && spot >= 0 && spot+length < mdataSize) {
779 ath_print(common, ATH_DBG_EEPROM,
780 "Restore at %d: spot=%d "
781 "offset=%d length=%d\n",
782 it, spot, offset, length);
783 memcpy(&mptr[spot], &block[it+2], length);
784 spot += length;
785 } else if (length > 0) {
786 ath_print(common, ATH_DBG_EEPROM,
787 "Bad restore at %d: spot=%d "
788 "offset=%d length=%d\n",
789 it, spot, offset, length);
790 return false;
791 }
792 }
793 return true;
794}
795
796static int ar9300_compress_decision(struct ath_hw *ah,
797 int it,
798 int code,
799 int reference,
800 u8 *mptr,
801 u8 *word, int length, int mdata_size)
802{
803 struct ath_common *common = ath9k_hw_common(ah);
804 u8 *dptr;
805
806 switch (code) {
807 case _CompressNone:
808 if (length != mdata_size) {
809 ath_print(common, ATH_DBG_EEPROM,
810 "EEPROM structure size mismatch"
811 "memory=%d eeprom=%d\n", mdata_size, length);
812 return -1;
813 }
814 memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length);
815 ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:"
816 " uncompressed, length %d\n", it, length);
817 break;
818 case _CompressBlock:
819 if (reference == 0) {
820 dptr = mptr;
821 } else {
822 if (reference != 2) {
823 ath_print(common, ATH_DBG_EEPROM,
824 "cant find reference eeprom"
825 "struct %d\n", reference);
826 return -1;
827 }
828 memcpy(mptr, &ar9300_default, mdata_size);
829 }
830 ath_print(common, ATH_DBG_EEPROM,
831 "restore eeprom %d: block, reference %d,"
832 " length %d\n", it, reference, length);
833 ar9300_uncompress_block(ah, mptr, mdata_size,
834 (u8 *) (word + COMP_HDR_LEN), length);
835 break;
836 default:
837 ath_print(common, ATH_DBG_EEPROM, "unknown compression"
838 " code %d\n", code);
839 return -1;
840 }
841 return 0;
842}
843
844/*
845 * Read the configuration data from the eeprom.
846 * The data can be put in any specified memory buffer.
847 *
848 * Returns -1 on error.
849 * Returns address of next memory location on success.
850 */
851static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
852 u8 *mptr, int mdata_size)
853{
854#define MDEFAULT 15
855#define MSTATE 100
856 int cptr;
857 u8 *word;
858 int code;
859 int reference, length, major, minor;
860 int osize;
861 int it;
862 u16 checksum, mchecksum;
863 struct ath_common *common = ath9k_hw_common(ah);
864
865 word = kzalloc(2048, GFP_KERNEL);
866 if (!word)
867 return -1;
868
869 memcpy(mptr, &ar9300_default, mdata_size);
870
871 cptr = AR9300_BASE_ADDR;
872 for (it = 0; it < MSTATE; it++) {
873 if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
874 goto fail;
875
876 if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
877 word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
878 && word[2] == 0xff && word[3] == 0xff))
879 break;
880
881 ar9300_comp_hdr_unpack(word, &code, &reference,
882 &length, &major, &minor);
883 ath_print(common, ATH_DBG_EEPROM,
884 "Found block at %x: code=%d ref=%d"
885 "length=%d major=%d minor=%d\n", cptr, code,
886 reference, length, major, minor);
887 if (length >= 1024) {
888 ath_print(common, ATH_DBG_EEPROM,
889 "Skipping bad header\n");
890 cptr -= COMP_HDR_LEN;
891 continue;
892 }
893
894 osize = length;
895 ar9300_read_eeprom(ah, cptr, word,
896 COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
897 checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
898 mchecksum = word[COMP_HDR_LEN + osize] |
899 (word[COMP_HDR_LEN + osize + 1] << 8);
900 ath_print(common, ATH_DBG_EEPROM,
901 "checksum %x %x\n", checksum, mchecksum);
902 if (checksum == mchecksum) {
903 ar9300_compress_decision(ah, it, code, reference, mptr,
904 word, length, mdata_size);
905 } else {
906 ath_print(common, ATH_DBG_EEPROM,
907 "skipping block with bad checksum\n");
908 }
909 cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
910 }
911
912 kfree(word);
913 return cptr;
914
915fail:
916 kfree(word);
917 return -1;
918}
919
920/*
921 * Restore the configuration structure by reading the eeprom.
922 * This function destroys any existing in-memory structure
923 * content.
924 */
925static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
926{
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200927 u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400928
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200929 if (ar9300_eeprom_restore_internal(ah, mptr,
930 sizeof(struct ar9300_eeprom)) < 0)
931 return false;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400932
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200933 return true;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400934}
935
936/* XXX: review hardware docs */
937static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
938{
939 return ah->eeprom.ar9300_eep.eepromVersion;
940}
941
942/* XXX: could be read from the eepromVersion, not sure yet */
943static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
944{
945 return 0;
946}
947
948static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
949 enum ieee80211_band freq_band)
950{
951 return 1;
952}
953
Felix Fietkau601e0cb2010-07-11 12:48:39 +0200954static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400955 struct ath9k_channel *chan)
956{
957 return -EINVAL;
958}
959
960static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
961{
962 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
963
964 if (is2ghz)
965 return eep->modalHeader2G.xpaBiasLvl;
966 else
967 return eep->modalHeader5G.xpaBiasLvl;
968}
969
970static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
971{
972 int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
973 REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3));
974 REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE,
975 ((bias >> 2) & 0x3));
976}
977
978static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
979{
980 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200981 __le32 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400982
983 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200984 val = eep->modalHeader2G.antCtrlCommon;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400985 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200986 val = eep->modalHeader5G.antCtrlCommon;
987 return le32_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400988}
989
990static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
991{
992 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200993 __le32 val;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400994
995 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200996 val = eep->modalHeader2G.antCtrlCommon2;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -0400997 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +0200998 val = eep->modalHeader5G.antCtrlCommon2;
999 return le32_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001000}
1001
1002static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
1003 int chain,
1004 bool is2ghz)
1005{
1006 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001007 __le16 val = 0;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001008
1009 if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
1010 if (is2ghz)
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001011 val = eep->modalHeader2G.antCtrlChain[chain];
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001012 else
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001013 val = eep->modalHeader5G.antCtrlChain[chain];
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001014 }
1015
Felix Fietkauffdc4cb2010-05-11 17:23:03 +02001016 return le16_to_cpu(val);
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001017}
1018
1019static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
1020{
1021 u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
1022 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value);
1023
1024 value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
1025 REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1026
1027 value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz);
1028 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1029
1030 value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
1031 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1032
1033 value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz);
1034 REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1035}
1036
1037static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
1038{
1039 int drive_strength;
1040 unsigned long reg;
1041
1042 drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
1043
1044 if (!drive_strength)
1045 return;
1046
1047 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1048 reg &= ~0x00ffffc0;
1049 reg |= 0x5 << 21;
1050 reg |= 0x5 << 18;
1051 reg |= 0x5 << 15;
1052 reg |= 0x5 << 12;
1053 reg |= 0x5 << 9;
1054 reg |= 0x5 << 6;
1055 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1056
1057 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1058 reg &= ~0xffffffe0;
1059 reg |= 0x5 << 29;
1060 reg |= 0x5 << 26;
1061 reg |= 0x5 << 23;
1062 reg |= 0x5 << 20;
1063 reg |= 0x5 << 17;
1064 reg |= 0x5 << 14;
1065 reg |= 0x5 << 11;
1066 reg |= 0x5 << 8;
1067 reg |= 0x5 << 5;
1068 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1069
1070 reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1071 reg &= ~0xff800000;
1072 reg |= 0x5 << 29;
1073 reg |= 0x5 << 26;
1074 reg |= 0x5 << 23;
1075 REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1076}
1077
1078static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
1079{
1080 int internal_regulator =
1081 ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
1082
1083 if (internal_regulator) {
1084 /* Internal regulator is ON. Write swreg register. */
1085 int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
1086 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1087 REG_READ(ah, AR_RTC_REG_CONTROL1) &
1088 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1089 REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1090 /* Set REG_CONTROL1.SWREG_PROGRAM */
1091 REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1092 REG_READ(ah,
1093 AR_RTC_REG_CONTROL1) |
1094 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1095 } else {
1096 REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1097 (REG_READ(ah,
1098 AR_RTC_SLEEP_CLK) |
1099 AR_RTC_FORCE_SWREG_PRD));
1100 }
1101}
1102
1103static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
1104 struct ath9k_channel *chan)
1105{
1106 ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
1107 ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
1108 ar9003_hw_drive_strength_apply(ah);
1109 ar9003_hw_internal_regulator_apply(ah);
1110}
1111
1112static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
1113 struct ath9k_channel *chan)
1114{
1115}
1116
1117/*
1118 * Returns the interpolated y value corresponding to the specified x value
1119 * from the np ordered pairs of data (px,py).
1120 * The pairs do not have to be in any order.
1121 * If the specified x value is less than any of the px,
1122 * the returned y value is equal to the py for the lowest px.
1123 * If the specified x value is greater than any of the px,
1124 * the returned y value is equal to the py for the highest px.
1125 */
1126static int ar9003_hw_power_interpolate(int32_t x,
1127 int32_t *px, int32_t *py, u_int16_t np)
1128{
1129 int ip = 0;
1130 int lx = 0, ly = 0, lhave = 0;
1131 int hx = 0, hy = 0, hhave = 0;
1132 int dx = 0;
1133 int y = 0;
1134
1135 lhave = 0;
1136 hhave = 0;
1137
1138 /* identify best lower and higher x calibration measurement */
1139 for (ip = 0; ip < np; ip++) {
1140 dx = x - px[ip];
1141
1142 /* this measurement is higher than our desired x */
1143 if (dx <= 0) {
1144 if (!hhave || dx > (x - hx)) {
1145 /* new best higher x measurement */
1146 hx = px[ip];
1147 hy = py[ip];
1148 hhave = 1;
1149 }
1150 }
1151 /* this measurement is lower than our desired x */
1152 if (dx >= 0) {
1153 if (!lhave || dx < (x - lx)) {
1154 /* new best lower x measurement */
1155 lx = px[ip];
1156 ly = py[ip];
1157 lhave = 1;
1158 }
1159 }
1160 }
1161
1162 /* the low x is good */
1163 if (lhave) {
1164 /* so is the high x */
1165 if (hhave) {
1166 /* they're the same, so just pick one */
1167 if (hx == lx)
1168 y = ly;
1169 else /* interpolate */
1170 y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
1171 } else /* only low is good, use it */
1172 y = ly;
1173 } else if (hhave) /* only high is good, use it */
1174 y = hy;
1175 else /* nothing is good,this should never happen unless np=0, ???? */
1176 y = -(1 << 30);
1177 return y;
1178}
1179
1180static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
1181 u16 rateIndex, u16 freq, bool is2GHz)
1182{
1183 u16 numPiers, i;
1184 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1185 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1186 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1187 struct cal_tgt_pow_legacy *pEepromTargetPwr;
1188 u8 *pFreqBin;
1189
1190 if (is2GHz) {
Felix Fietkaud10baf92010-04-26 15:04:38 -04001191 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001192 pEepromTargetPwr = eep->calTargetPower2G;
1193 pFreqBin = eep->calTarget_freqbin_2G;
1194 } else {
1195 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1196 pEepromTargetPwr = eep->calTargetPower5G;
1197 pFreqBin = eep->calTarget_freqbin_5G;
1198 }
1199
1200 /*
1201 * create array of channels and targetpower from
1202 * targetpower piers stored on eeprom
1203 */
1204 for (i = 0; i < numPiers; i++) {
1205 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1206 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1207 }
1208
1209 /* interpolate to get target power for given frequency */
1210 return (u8) ar9003_hw_power_interpolate((s32) freq,
1211 freqArray,
1212 targetPowerArray, numPiers);
1213}
1214
1215static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
1216 u16 rateIndex,
1217 u16 freq, bool is2GHz)
1218{
1219 u16 numPiers, i;
1220 s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS];
1221 s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS];
1222 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1223 struct cal_tgt_pow_ht *pEepromTargetPwr;
1224 u8 *pFreqBin;
1225
1226 if (is2GHz) {
Felix Fietkaud10baf92010-04-26 15:04:38 -04001227 numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001228 pEepromTargetPwr = eep->calTargetPower2GHT20;
1229 pFreqBin = eep->calTarget_freqbin_2GHT20;
1230 } else {
1231 numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
1232 pEepromTargetPwr = eep->calTargetPower5GHT20;
1233 pFreqBin = eep->calTarget_freqbin_5GHT20;
1234 }
1235
1236 /*
1237 * create array of channels and targetpower
1238 * from targetpower piers stored on eeprom
1239 */
1240 for (i = 0; i < numPiers; i++) {
1241 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1242 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1243 }
1244
1245 /* interpolate to get target power for given frequency */
1246 return (u8) ar9003_hw_power_interpolate((s32) freq,
1247 freqArray,
1248 targetPowerArray, numPiers);
1249}
1250
1251static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah,
1252 u16 rateIndex,
1253 u16 freq, bool is2GHz)
1254{
1255 u16 numPiers, i;
1256 s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS];
1257 s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS];
1258 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1259 struct cal_tgt_pow_ht *pEepromTargetPwr;
1260 u8 *pFreqBin;
1261
1262 if (is2GHz) {
1263 numPiers = AR9300_NUM_2G_40_TARGET_POWERS;
1264 pEepromTargetPwr = eep->calTargetPower2GHT40;
1265 pFreqBin = eep->calTarget_freqbin_2GHT40;
1266 } else {
1267 numPiers = AR9300_NUM_5G_40_TARGET_POWERS;
1268 pEepromTargetPwr = eep->calTargetPower5GHT40;
1269 pFreqBin = eep->calTarget_freqbin_5GHT40;
1270 }
1271
1272 /*
1273 * create array of channels and targetpower from
1274 * targetpower piers stored on eeprom
1275 */
1276 for (i = 0; i < numPiers; i++) {
1277 freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz);
1278 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1279 }
1280
1281 /* interpolate to get target power for given frequency */
1282 return (u8) ar9003_hw_power_interpolate((s32) freq,
1283 freqArray,
1284 targetPowerArray, numPiers);
1285}
1286
1287static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah,
1288 u16 rateIndex, u16 freq)
1289{
1290 u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i;
1291 s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1292 s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS];
1293 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1294 struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck;
1295 u8 *pFreqBin = eep->calTarget_freqbin_Cck;
1296
1297 /*
1298 * create array of channels and targetpower from
1299 * targetpower piers stored on eeprom
1300 */
1301 for (i = 0; i < numPiers; i++) {
1302 freqArray[i] = FBIN2FREQ(pFreqBin[i], 1);
1303 targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex];
1304 }
1305
1306 /* interpolate to get target power for given frequency */
1307 return (u8) ar9003_hw_power_interpolate((s32) freq,
1308 freqArray,
1309 targetPowerArray, numPiers);
1310}
1311
1312/* Set tx power registers to array of values passed in */
1313static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
1314{
1315#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
1316 /* make sure forced gain is not set */
1317 REG_WRITE(ah, 0xa458, 0);
1318
1319 /* Write the OFDM power per rate set */
1320
1321 /* 6 (LSB), 9, 12, 18 (MSB) */
1322 REG_WRITE(ah, 0xa3c0,
1323 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
1324 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
1325 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
1326 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1327
1328 /* 24 (LSB), 36, 48, 54 (MSB) */
1329 REG_WRITE(ah, 0xa3c4,
1330 POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
1331 POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
1332 POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
1333 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
1334
1335 /* Write the CCK power per rate set */
1336
1337 /* 1L (LSB), reserved, 2L, 2S (MSB) */
1338 REG_WRITE(ah, 0xa3c8,
1339 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
1340 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
1341 /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */
1342 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
1343
1344 /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
1345 REG_WRITE(ah, 0xa3cc,
1346 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
1347 POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
1348 POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
1349 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
1350 );
1351
1352 /* Write the HT20 power per rate set */
1353
1354 /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
1355 REG_WRITE(ah, 0xa3d0,
1356 POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
1357 POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
1358 POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
1359 POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0)
1360 );
1361
1362 /* 6 (LSB), 7, 12, 13 (MSB) */
1363 REG_WRITE(ah, 0xa3d4,
1364 POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
1365 POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
1366 POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
1367 POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0)
1368 );
1369
1370 /* 14 (LSB), 15, 20, 21 */
1371 REG_WRITE(ah, 0xa3e4,
1372 POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
1373 POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
1374 POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
1375 POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0)
1376 );
1377
1378 /* Mixed HT20 and HT40 rates */
1379
1380 /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
1381 REG_WRITE(ah, 0xa3e8,
1382 POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
1383 POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
1384 POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
1385 POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0)
1386 );
1387
1388 /*
1389 * Write the HT40 power per rate set
1390 * correct PAR difference between HT40 and HT20/LEGACY
1391 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
1392 */
1393 REG_WRITE(ah, 0xa3d8,
1394 POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
1395 POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
1396 POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
1397 POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0)
1398 );
1399
1400 /* 6 (LSB), 7, 12, 13 (MSB) */
1401 REG_WRITE(ah, 0xa3dc,
1402 POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
1403 POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
1404 POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
1405 POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0)
1406 );
1407
1408 /* 14 (LSB), 15, 20, 21 */
1409 REG_WRITE(ah, 0xa3ec,
1410 POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
1411 POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
1412 POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
1413 POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0)
1414 );
1415
1416 return 0;
1417#undef POW_SM
1418}
1419
1420static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq)
1421{
1422 u8 targetPowerValT2[ar9300RateSize];
1423 /* XXX: hard code for now, need to get from eeprom struct */
1424 u8 ht40PowerIncForPdadc = 0;
1425 bool is2GHz = false;
1426 unsigned int i = 0;
1427 struct ath_common *common = ath9k_hw_common(ah);
1428
1429 if (freq < 4000)
1430 is2GHz = true;
1431
1432 targetPowerValT2[ALL_TARGET_LEGACY_6_24] =
1433 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq,
1434 is2GHz);
1435 targetPowerValT2[ALL_TARGET_LEGACY_36] =
1436 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq,
1437 is2GHz);
1438 targetPowerValT2[ALL_TARGET_LEGACY_48] =
1439 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq,
1440 is2GHz);
1441 targetPowerValT2[ALL_TARGET_LEGACY_54] =
1442 ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq,
1443 is2GHz);
1444 targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] =
1445 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L,
1446 freq);
1447 targetPowerValT2[ALL_TARGET_LEGACY_5S] =
1448 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq);
1449 targetPowerValT2[ALL_TARGET_LEGACY_11L] =
1450 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq);
1451 targetPowerValT2[ALL_TARGET_LEGACY_11S] =
1452 ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq);
1453 targetPowerValT2[ALL_TARGET_HT20_0_8_16] =
1454 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1455 is2GHz);
1456 targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1457 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1458 freq, is2GHz);
1459 targetPowerValT2[ALL_TARGET_HT20_4] =
1460 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1461 is2GHz);
1462 targetPowerValT2[ALL_TARGET_HT20_5] =
1463 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1464 is2GHz);
1465 targetPowerValT2[ALL_TARGET_HT20_6] =
1466 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1467 is2GHz);
1468 targetPowerValT2[ALL_TARGET_HT20_7] =
1469 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1470 is2GHz);
1471 targetPowerValT2[ALL_TARGET_HT20_12] =
1472 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1473 is2GHz);
1474 targetPowerValT2[ALL_TARGET_HT20_13] =
1475 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1476 is2GHz);
1477 targetPowerValT2[ALL_TARGET_HT20_14] =
1478 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1479 is2GHz);
1480 targetPowerValT2[ALL_TARGET_HT20_15] =
1481 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1482 is2GHz);
1483 targetPowerValT2[ALL_TARGET_HT20_20] =
1484 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1485 is2GHz);
1486 targetPowerValT2[ALL_TARGET_HT20_21] =
1487 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1488 is2GHz);
1489 targetPowerValT2[ALL_TARGET_HT20_22] =
1490 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1491 is2GHz);
1492 targetPowerValT2[ALL_TARGET_HT20_23] =
1493 ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1494 is2GHz);
1495 targetPowerValT2[ALL_TARGET_HT40_0_8_16] =
1496 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq,
1497 is2GHz) + ht40PowerIncForPdadc;
1498 targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1499 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19,
1500 freq,
1501 is2GHz) + ht40PowerIncForPdadc;
1502 targetPowerValT2[ALL_TARGET_HT40_4] =
1503 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq,
1504 is2GHz) + ht40PowerIncForPdadc;
1505 targetPowerValT2[ALL_TARGET_HT40_5] =
1506 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq,
1507 is2GHz) + ht40PowerIncForPdadc;
1508 targetPowerValT2[ALL_TARGET_HT40_6] =
1509 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq,
1510 is2GHz) + ht40PowerIncForPdadc;
1511 targetPowerValT2[ALL_TARGET_HT40_7] =
1512 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq,
1513 is2GHz) + ht40PowerIncForPdadc;
1514 targetPowerValT2[ALL_TARGET_HT40_12] =
1515 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq,
1516 is2GHz) + ht40PowerIncForPdadc;
1517 targetPowerValT2[ALL_TARGET_HT40_13] =
1518 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq,
1519 is2GHz) + ht40PowerIncForPdadc;
1520 targetPowerValT2[ALL_TARGET_HT40_14] =
1521 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq,
1522 is2GHz) + ht40PowerIncForPdadc;
1523 targetPowerValT2[ALL_TARGET_HT40_15] =
1524 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq,
1525 is2GHz) + ht40PowerIncForPdadc;
1526 targetPowerValT2[ALL_TARGET_HT40_20] =
1527 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq,
1528 is2GHz) + ht40PowerIncForPdadc;
1529 targetPowerValT2[ALL_TARGET_HT40_21] =
1530 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq,
1531 is2GHz) + ht40PowerIncForPdadc;
1532 targetPowerValT2[ALL_TARGET_HT40_22] =
1533 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq,
1534 is2GHz) + ht40PowerIncForPdadc;
1535 targetPowerValT2[ALL_TARGET_HT40_23] =
1536 ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq,
1537 is2GHz) + ht40PowerIncForPdadc;
1538
1539 while (i < ar9300RateSize) {
1540 ath_print(common, ATH_DBG_EEPROM,
1541 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1542 i++;
1543
1544 ath_print(common, ATH_DBG_EEPROM,
1545 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1546 i++;
1547
1548 ath_print(common, ATH_DBG_EEPROM,
1549 "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
1550 i++;
1551
1552 ath_print(common, ATH_DBG_EEPROM,
1553 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
1554 i++;
1555 }
1556
1557 /* Write target power array to registers */
1558 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
1559}
1560
1561static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
1562 int mode,
1563 int ipier,
1564 int ichain,
1565 int *pfrequency,
1566 int *pcorrection,
1567 int *ptemperature, int *pvoltage)
1568{
1569 u8 *pCalPier;
1570 struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct;
1571 int is2GHz;
1572 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1573 struct ath_common *common = ath9k_hw_common(ah);
1574
1575 if (ichain >= AR9300_MAX_CHAINS) {
1576 ath_print(common, ATH_DBG_EEPROM,
1577 "Invalid chain index, must be less than %d\n",
1578 AR9300_MAX_CHAINS);
1579 return -1;
1580 }
1581
1582 if (mode) { /* 5GHz */
1583 if (ipier >= AR9300_NUM_5G_CAL_PIERS) {
1584 ath_print(common, ATH_DBG_EEPROM,
1585 "Invalid 5GHz cal pier index, must "
1586 "be less than %d\n",
1587 AR9300_NUM_5G_CAL_PIERS);
1588 return -1;
1589 }
1590 pCalPier = &(eep->calFreqPier5G[ipier]);
1591 pCalPierStruct = &(eep->calPierData5G[ichain][ipier]);
1592 is2GHz = 0;
1593 } else {
1594 if (ipier >= AR9300_NUM_2G_CAL_PIERS) {
1595 ath_print(common, ATH_DBG_EEPROM,
1596 "Invalid 2GHz cal pier index, must "
1597 "be less than %d\n", AR9300_NUM_2G_CAL_PIERS);
1598 return -1;
1599 }
1600
1601 pCalPier = &(eep->calFreqPier2G[ipier]);
1602 pCalPierStruct = &(eep->calPierData2G[ichain][ipier]);
1603 is2GHz = 1;
1604 }
1605
1606 *pfrequency = FBIN2FREQ(*pCalPier, is2GHz);
1607 *pcorrection = pCalPierStruct->refPower;
1608 *ptemperature = pCalPierStruct->tempMeas;
1609 *pvoltage = pCalPierStruct->voltMeas;
1610
1611 return 0;
1612}
1613
1614static int ar9003_hw_power_control_override(struct ath_hw *ah,
1615 int frequency,
1616 int *correction,
1617 int *voltage, int *temperature)
1618{
1619 int tempSlope = 0;
1620 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1621
1622 REG_RMW(ah, AR_PHY_TPC_11_B0,
1623 (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1624 AR_PHY_TPC_OLPC_GAIN_DELTA);
1625 REG_RMW(ah, AR_PHY_TPC_11_B1,
1626 (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1627 AR_PHY_TPC_OLPC_GAIN_DELTA);
1628 REG_RMW(ah, AR_PHY_TPC_11_B2,
1629 (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
1630 AR_PHY_TPC_OLPC_GAIN_DELTA);
1631
1632 /* enable open loop power control on chip */
1633 REG_RMW(ah, AR_PHY_TPC_6_B0,
1634 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1635 AR_PHY_TPC_6_ERROR_EST_MODE);
1636 REG_RMW(ah, AR_PHY_TPC_6_B1,
1637 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1638 AR_PHY_TPC_6_ERROR_EST_MODE);
1639 REG_RMW(ah, AR_PHY_TPC_6_B2,
1640 (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
1641 AR_PHY_TPC_6_ERROR_EST_MODE);
1642
1643 /*
1644 * enable temperature compensation
1645 * Need to use register names
1646 */
1647 if (frequency < 4000)
1648 tempSlope = eep->modalHeader2G.tempSlope;
1649 else
1650 tempSlope = eep->modalHeader5G.tempSlope;
1651
1652 REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
1653 REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
1654 temperature[0]);
1655
1656 return 0;
1657}
1658
1659/* Apply the recorded correction values. */
1660static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
1661{
1662 int ichain, ipier, npier;
1663 int mode;
1664 int lfrequency[AR9300_MAX_CHAINS],
1665 lcorrection[AR9300_MAX_CHAINS],
1666 ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS];
1667 int hfrequency[AR9300_MAX_CHAINS],
1668 hcorrection[AR9300_MAX_CHAINS],
1669 htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS];
1670 int fdiff;
1671 int correction[AR9300_MAX_CHAINS],
1672 voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS];
1673 int pfrequency, pcorrection, ptemperature, pvoltage;
1674 struct ath_common *common = ath9k_hw_common(ah);
1675
1676 mode = (frequency >= 4000);
1677 if (mode)
1678 npier = AR9300_NUM_5G_CAL_PIERS;
1679 else
1680 npier = AR9300_NUM_2G_CAL_PIERS;
1681
1682 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1683 lfrequency[ichain] = 0;
1684 hfrequency[ichain] = 100000;
1685 }
1686 /* identify best lower and higher frequency calibration measurement */
1687 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1688 for (ipier = 0; ipier < npier; ipier++) {
1689 if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain,
1690 &pfrequency, &pcorrection,
1691 &ptemperature, &pvoltage)) {
1692 fdiff = frequency - pfrequency;
1693
1694 /*
1695 * this measurement is higher than
1696 * our desired frequency
1697 */
1698 if (fdiff <= 0) {
1699 if (hfrequency[ichain] <= 0 ||
1700 hfrequency[ichain] >= 100000 ||
1701 fdiff >
1702 (frequency - hfrequency[ichain])) {
1703 /*
1704 * new best higher
1705 * frequency measurement
1706 */
1707 hfrequency[ichain] = pfrequency;
1708 hcorrection[ichain] =
1709 pcorrection;
1710 htemperature[ichain] =
1711 ptemperature;
1712 hvoltage[ichain] = pvoltage;
1713 }
1714 }
1715 if (fdiff >= 0) {
1716 if (lfrequency[ichain] <= 0
1717 || fdiff <
1718 (frequency - lfrequency[ichain])) {
1719 /*
1720 * new best lower
1721 * frequency measurement
1722 */
1723 lfrequency[ichain] = pfrequency;
1724 lcorrection[ichain] =
1725 pcorrection;
1726 ltemperature[ichain] =
1727 ptemperature;
1728 lvoltage[ichain] = pvoltage;
1729 }
1730 }
1731 }
1732 }
1733 }
1734
1735 /* interpolate */
1736 for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
1737 ath_print(common, ATH_DBG_EEPROM,
1738 "ch=%d f=%d low=%d %d h=%d %d\n",
1739 ichain, frequency, lfrequency[ichain],
1740 lcorrection[ichain], hfrequency[ichain],
1741 hcorrection[ichain]);
1742 /* they're the same, so just pick one */
1743 if (hfrequency[ichain] == lfrequency[ichain]) {
1744 correction[ichain] = lcorrection[ichain];
1745 voltage[ichain] = lvoltage[ichain];
1746 temperature[ichain] = ltemperature[ichain];
1747 }
1748 /* the low frequency is good */
1749 else if (frequency - lfrequency[ichain] < 1000) {
1750 /* so is the high frequency, interpolate */
1751 if (hfrequency[ichain] - frequency < 1000) {
1752
1753 correction[ichain] = lcorrection[ichain] +
1754 (((frequency - lfrequency[ichain]) *
1755 (hcorrection[ichain] -
1756 lcorrection[ichain])) /
1757 (hfrequency[ichain] - lfrequency[ichain]));
1758
1759 temperature[ichain] = ltemperature[ichain] +
1760 (((frequency - lfrequency[ichain]) *
1761 (htemperature[ichain] -
1762 ltemperature[ichain])) /
1763 (hfrequency[ichain] - lfrequency[ichain]));
1764
1765 voltage[ichain] =
1766 lvoltage[ichain] +
1767 (((frequency -
1768 lfrequency[ichain]) * (hvoltage[ichain] -
1769 lvoltage[ichain]))
1770 / (hfrequency[ichain] -
1771 lfrequency[ichain]));
1772 }
1773 /* only low is good, use it */
1774 else {
1775 correction[ichain] = lcorrection[ichain];
1776 temperature[ichain] = ltemperature[ichain];
1777 voltage[ichain] = lvoltage[ichain];
1778 }
1779 }
1780 /* only high is good, use it */
1781 else if (hfrequency[ichain] - frequency < 1000) {
1782 correction[ichain] = hcorrection[ichain];
1783 temperature[ichain] = htemperature[ichain];
1784 voltage[ichain] = hvoltage[ichain];
1785 } else { /* nothing is good, presume 0???? */
1786 correction[ichain] = 0;
1787 temperature[ichain] = 0;
1788 voltage[ichain] = 0;
1789 }
1790 }
1791
1792 ar9003_hw_power_control_override(ah, frequency, correction, voltage,
1793 temperature);
1794
1795 ath_print(common, ATH_DBG_EEPROM,
1796 "for frequency=%d, calibration correction = %d %d %d\n",
1797 frequency, correction[0], correction[1], correction[2]);
1798
1799 return 0;
1800}
1801
1802static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
1803 struct ath9k_channel *chan, u16 cfgCtl,
1804 u8 twiceAntennaReduction,
1805 u8 twiceMaxRegulatoryPower,
1806 u8 powerLimit)
1807{
Felix Fietkau597a94b2010-04-26 15:04:37 -04001808 ah->txpower_limit = powerLimit;
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001809 ar9003_hw_set_target_power_eeprom(ah, chan->channel);
1810 ar9003_hw_calibration_apply(ah, chan->channel);
1811}
1812
1813static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
1814 u16 i, bool is2GHz)
1815{
1816 return AR_NO_SPUR;
1817}
1818
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -04001819s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah)
1820{
1821 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1822
1823 return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */
1824}
1825
1826s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
1827{
1828 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
1829
1830 return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
1831}
1832
Senthil Balasubramanian15c9ee72010-04-15 17:39:14 -04001833const struct eeprom_ops eep_ar9300_ops = {
1834 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
1835 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
1836 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
1837 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
1838 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
1839 .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
1840 .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
1841 .set_board_values = ath9k_hw_ar9300_set_board_values,
1842 .set_addac = ath9k_hw_ar9300_set_addac,
1843 .set_txpower = ath9k_hw_ar9300_set_txpower,
1844 .get_spur_channel = ath9k_hw_ar9300_get_spur_channel
1845};