Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c
48526 views
1
/*
2
* Copyright (c) 2013 Qualcomm Atheros, 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 WITH
9
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14
* PERFORMANCE OF THIS SOFTWARE.
15
*/
16
17
#include "opt_ah.h"
18
19
#include "ah.h"
20
#include "ah_internal.h"
21
#include "ah_devid.h"
22
#ifdef AH_DEBUG
23
#include "ah_desc.h" /* NB: for HAL_PHYERR* */
24
#endif
25
#include "ar9300/ar9300.h"
26
#include "ar9300/ar9300eep.h"
27
#include "ar9300/ar9300template_generic.h"
28
#include "ar9300/ar9300template_xb112.h"
29
#include "ar9300/ar9300template_hb116.h"
30
#include "ar9300/ar9300template_xb113.h"
31
#include "ar9300/ar9300template_hb112.h"
32
#include "ar9300/ar9300template_ap121.h"
33
#include "ar9300/ar9300template_osprey_k31.h"
34
#include "ar9300/ar9300template_wasp_2.h"
35
#include "ar9300/ar9300template_wasp_k31.h"
36
#include "ar9300/ar9300template_aphrodite.h"
37
#include "ar9300/ar9300reg.h"
38
#include "ar9300/ar9300phy.h"
39
40
41
42
#if AH_BYTE_ORDER == AH_BIG_ENDIAN
43
void ar9300_swap_eeprom(ar9300_eeprom_t *eep);
44
void ar9300_eeprom_template_swap(void);
45
#endif
46
47
static u_int16_t ar9300_eeprom_get_spur_chan(struct ath_hal *ah,
48
int spur_chan, HAL_BOOL is_2ghz);
49
#ifdef UNUSED
50
static inline HAL_BOOL ar9300_fill_eeprom(struct ath_hal *ah);
51
static inline HAL_STATUS ar9300_check_eeprom(struct ath_hal *ah);
52
#endif
53
54
static ar9300_eeprom_t *default9300[] =
55
{
56
&ar9300_template_generic,
57
&ar9300_template_xb112,
58
&ar9300_template_hb116,
59
&ar9300_template_hb112,
60
&ar9300_template_xb113,
61
&ar9300_template_ap121,
62
&ar9300_template_wasp_2,
63
&ar9300_template_wasp_k31,
64
&ar9300_template_osprey_k31,
65
&ar9300_template_aphrodite,
66
};
67
68
/*
69
* Different types of memory where the calibration data might be stored.
70
* All types are searched in ar9300_eeprom_restore()
71
* in the order flash, eeprom, otp.
72
* To disable searching a type, set its parameter to 0.
73
*/
74
75
/*
76
* This is where we look for the calibration data.
77
* must be set before ath_attach() is called
78
*/
79
static int calibration_data_try = calibration_data_none;
80
static int calibration_data_try_address = 0;
81
82
/*
83
* Set the type of memory used to store calibration data.
84
* Used by nart to force reading/writing of a specific type.
85
* The driver can normally allow autodetection
86
* by setting source to calibration_data_none=0.
87
*/
88
void ar9300_calibration_data_set(struct ath_hal *ah, int32_t source)
89
{
90
if (ah != 0) {
91
AH9300(ah)->calibration_data_source = source;
92
} else {
93
calibration_data_try = source;
94
}
95
}
96
97
int32_t ar9300_calibration_data_get(struct ath_hal *ah)
98
{
99
if (ah != 0) {
100
return AH9300(ah)->calibration_data_source;
101
} else {
102
return calibration_data_try;
103
}
104
}
105
106
/*
107
* Set the address of first byte used to store calibration data.
108
* Used by nart to force reading/writing at a specific address.
109
* The driver can normally allow autodetection by setting size=0.
110
*/
111
void ar9300_calibration_data_address_set(struct ath_hal *ah, int32_t size)
112
{
113
if (ah != 0) {
114
AH9300(ah)->calibration_data_source_address = size;
115
} else {
116
calibration_data_try_address = size;
117
}
118
}
119
120
int32_t ar9300_calibration_data_address_get(struct ath_hal *ah)
121
{
122
if (ah != 0) {
123
return AH9300(ah)->calibration_data_source_address;
124
} else {
125
return calibration_data_try_address;
126
}
127
}
128
129
/*
130
* This is the template that is loaded if ar9300_eeprom_restore()
131
* can't find valid data in the memory.
132
*/
133
static int Ar9300_eeprom_template_preference = ar9300_eeprom_template_generic;
134
135
void ar9300_eeprom_template_preference(int32_t value)
136
{
137
Ar9300_eeprom_template_preference = value;
138
}
139
140
/*
141
* Install the specified default template.
142
* Overwrites any existing calibration and configuration information in memory.
143
*/
144
int32_t ar9300_eeprom_template_install(struct ath_hal *ah, int32_t value)
145
{
146
struct ath_hal_9300 *ahp = AH9300(ah);
147
ar9300_eeprom_t *mptr, *dptr;
148
int mdata_size;
149
150
mptr = &ahp->ah_eeprom;
151
mdata_size = ar9300_eeprom_struct_size();
152
if (mptr != 0) {
153
#if 0
154
calibration_data_source = calibration_data_none;
155
calibration_data_source_address = 0;
156
#endif
157
dptr = ar9300_eeprom_struct_default_find_by_id(value);
158
if (dptr != 0) {
159
OS_MEMCPY(mptr, dptr, mdata_size);
160
return 0;
161
}
162
}
163
return -1;
164
}
165
166
static int
167
ar9300_eeprom_restore_something(struct ath_hal *ah, ar9300_eeprom_t *mptr,
168
int mdata_size)
169
{
170
int it;
171
ar9300_eeprom_t *dptr;
172
int nptr;
173
174
nptr = -1;
175
/*
176
* if we didn't find any blocks in the memory,
177
* put the prefered template in place
178
*/
179
if (nptr < 0) {
180
AH9300(ah)->calibration_data_source = calibration_data_none;
181
AH9300(ah)->calibration_data_source_address = 0;
182
dptr = ar9300_eeprom_struct_default_find_by_id(
183
Ar9300_eeprom_template_preference);
184
if (dptr != 0) {
185
OS_MEMCPY(mptr, dptr, mdata_size);
186
nptr = 0;
187
}
188
}
189
/*
190
* if we didn't find the prefered one,
191
* put the normal default template in place
192
*/
193
if (nptr < 0) {
194
AH9300(ah)->calibration_data_source = calibration_data_none;
195
AH9300(ah)->calibration_data_source_address = 0;
196
dptr = ar9300_eeprom_struct_default_find_by_id(
197
ar9300_eeprom_template_default);
198
if (dptr != 0) {
199
OS_MEMCPY(mptr, dptr, mdata_size);
200
nptr = 0;
201
}
202
}
203
/*
204
* if we can't find the best template, put any old template in place
205
* presume that newer ones are better, so search backwards
206
*/
207
if (nptr < 0) {
208
AH9300(ah)->calibration_data_source = calibration_data_none;
209
AH9300(ah)->calibration_data_source_address = 0;
210
for (it = ar9300_eeprom_struct_default_many() - 1; it >= 0; it--) {
211
dptr = ar9300_eeprom_struct_default(it);
212
if (dptr != 0) {
213
OS_MEMCPY(mptr, dptr, mdata_size);
214
nptr = 0;
215
break;
216
}
217
}
218
}
219
return nptr;
220
}
221
222
/*
223
* Read 16 bits of data from offset into *data
224
*/
225
HAL_BOOL
226
ar9300_eeprom_read_word(struct ath_hal *ah, u_int off, u_int16_t *data)
227
{
228
if (AR_SREV_OSPREY(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_JUPITER(ah))
229
{
230
(void) OS_REG_READ(ah, AR9300_EEPROM_OFFSET + (off << AR9300_EEPROM_S));
231
if (!ath_hal_wait(ah,
232
AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA),
233
AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS,
234
0))
235
{
236
return AH_FALSE;
237
}
238
*data = MS(OS_REG_READ(ah,
239
AR_HOSTIF_REG(ah, AR_EEPROM_STATUS_DATA)), AR_EEPROM_STATUS_DATA_VAL);
240
return AH_TRUE;
241
}
242
else
243
{
244
*data = 0;
245
return AH_FALSE;
246
}
247
}
248
249
250
HAL_BOOL
251
ar9300_otp_read(struct ath_hal *ah, u_int off, u_int32_t *data, HAL_BOOL is_wifi)
252
{
253
int time_out = 1000;
254
int status = 0;
255
u_int32_t addr;
256
257
if (AR_SREV_HONEYBEE(ah)){ /* no OTP for Honeybee */
258
return false;
259
}
260
addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah))?
261
OTP_MEM_START_ADDRESS_WASP : OTP_MEM_START_ADDRESS;
262
if (!is_wifi) {
263
addr = BTOTP_MEM_START_ADDRESS;
264
}
265
addr += off * 4; /* OTP is 32 bit addressable */
266
(void) OS_REG_READ(ah, addr);
267
268
addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) ?
269
OTP_STATUS0_OTP_SM_BUSY_WASP : OTP_STATUS0_OTP_SM_BUSY;
270
if (!is_wifi) {
271
addr = BTOTP_STATUS0_OTP_SM_BUSY;
272
}
273
while ((time_out > 0) && (!status)) { /* wait for access complete */
274
/* Read data valid, access not busy, sm not busy */
275
status = ((OS_REG_READ(ah, addr) & 0x7) == 0x4) ? 1 : 0;
276
time_out--;
277
}
278
if (time_out == 0) {
279
HALDEBUG(ah, HAL_DEBUG_EEPROM,
280
"%s: Timed out during OTP Status0 validation\n", __func__);
281
return AH_FALSE;
282
}
283
284
addr = (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) ?
285
OTP_STATUS1_EFUSE_READ_DATA_WASP : OTP_STATUS1_EFUSE_READ_DATA;
286
if (!is_wifi) {
287
addr = BTOTP_STATUS1_EFUSE_READ_DATA;
288
}
289
*data = OS_REG_READ(ah, addr);
290
return AH_TRUE;
291
}
292
293
294
295
296
static HAL_STATUS
297
ar9300_flash_map(struct ath_hal *ah)
298
{
299
/* XXX disable flash remapping for now (ie, SoC support) */
300
ath_hal_printf(ah, "%s: unimplemented for now\n", __func__);
301
#if 0
302
struct ath_hal_9300 *ahp = AH9300(ah);
303
#if defined(AR9100) || defined(__NetBSD__)
304
ahp->ah_cal_mem = OS_REMAP(ah, AR9300_EEPROM_START_ADDR, AR9300_EEPROM_MAX);
305
#else
306
ahp->ah_cal_mem = OS_REMAP((uintptr_t)(AH_PRIVATE(ah)->ah_st),
307
(AR9300_EEPROM_MAX + AR9300_FLASH_CAL_START_OFFSET));
308
#endif
309
if (!ahp->ah_cal_mem) {
310
HALDEBUG(ah, HAL_DEBUG_EEPROM,
311
"%s: cannot remap eeprom region \n", __func__);
312
return HAL_EIO;
313
}
314
#endif
315
return HAL_OK;
316
}
317
318
HAL_BOOL
319
ar9300_flash_read(struct ath_hal *ah, u_int off, u_int16_t *data)
320
{
321
struct ath_hal_9300 *ahp = AH9300(ah);
322
323
*data = ((u_int16_t *)ahp->ah_cal_mem)[off];
324
return AH_TRUE;
325
}
326
327
HAL_BOOL
328
ar9300_flash_write(struct ath_hal *ah, u_int off, u_int16_t data)
329
{
330
struct ath_hal_9300 *ahp = AH9300(ah);
331
332
((u_int16_t *)ahp->ah_cal_mem)[off] = data;
333
return AH_TRUE;
334
}
335
336
HAL_STATUS
337
ar9300_eeprom_attach(struct ath_hal *ah)
338
{
339
struct ath_hal_9300 *ahp = AH9300(ah);
340
ahp->try_dram = 1;
341
ahp->try_eeprom = 1;
342
ahp->try_otp = 1;
343
#ifdef ATH_CAL_NAND_FLASH
344
ahp->try_nand = 1;
345
#else
346
ahp->try_flash = 1;
347
#endif
348
ahp->calibration_data_source = calibration_data_none;
349
ahp->calibration_data_source_address = 0;
350
ahp->calibration_data_try = calibration_data_try;
351
ahp->calibration_data_try_address = 0;
352
353
/*
354
* In case flash will be used for EEPROM. Otherwise ahp->ah_cal_mem
355
* must be set to NULL or the real EEPROM address.
356
*/
357
ar9300_flash_map(ah);
358
/*
359
* ###### This function always return NO SPUR.
360
* This is not true for many board designs.
361
* Does anyone use this?
362
*/
363
AH_PRIVATE(ah)->ah_getSpurChan = ar9300_eeprom_get_spur_chan;
364
365
#ifdef OLDCODE
366
/* XXX Needs to be moved for dynamic selection */
367
ahp->ah_eeprom = *(default9300[ar9300_eeprom_template_default]);
368
369
370
if (AR_SREV_HORNET(ah)) {
371
/* Set default values for Hornet. */
372
ahp->ah_eeprom.base_eep_header.op_cap_flags.op_flags =
373
AR9300_OPFLAGS_11G;
374
ahp->ah_eeprom.base_eep_header.txrx_mask = 0x11;
375
} else if (AR_SREV_POSEIDON(ah)) {
376
/* Set default values for Poseidon. */
377
ahp->ah_eeprom.base_eep_header.op_cap_flags.op_flags =
378
AR9300_OPFLAGS_11G;
379
ahp->ah_eeprom.base_eep_header.txrx_mask = 0x11;
380
}
381
382
if (AH_PRIVATE(ah)->ah_config.ath_hal_skip_eeprom_read) {
383
ahp->ah_emu_eeprom = 1;
384
return HAL_OK;
385
}
386
387
ahp->ah_emu_eeprom = 1;
388
389
#ifdef UNUSED
390
#endif
391
392
if (!ar9300_fill_eeprom(ah)) {
393
return HAL_EIO;
394
}
395
396
return HAL_OK;
397
/* return ar9300_check_eeprom(ah); */
398
#else
399
ahp->ah_emu_eeprom = 1;
400
401
#if 0
402
/*#ifdef MDK_AP*/ /* MDK_AP is defined only in NART AP build */
403
u_int8_t buffer[10];
404
int caldata_check = 0;
405
406
ar9300_calibration_data_read_flash(
407
ah, FLASH_BASE_CALDATA_OFFSET, buffer, 4);
408
printf("flash caldata:: %x\n", buffer[0]);
409
if (buffer[0] != 0xff) {
410
caldata_check = 1;
411
}
412
if (!caldata_check) {
413
ar9300_eeprom_t *mptr;
414
int mdata_size;
415
if (AR_SREV_HORNET(ah)) {
416
/* XXX: For initial testing */
417
mptr = &ahp->ah_eeprom;
418
mdata_size = ar9300_eeprom_struct_size();
419
ahp->ah_eeprom = ar9300_template_ap121;
420
ahp->ah_emu_eeprom = 1;
421
/* need it to let art save in to flash ????? */
422
calibration_data_source = calibration_data_flash;
423
} else if (AR_SREV_WASP(ah)) {
424
/* XXX: For initial testing */
425
ath_hal_printf(ah, " wasp eep attach\n");
426
mptr = &ahp->ah_eeprom;
427
mdata_size = ar9300_eeprom_struct_size();
428
ahp->ah_eeprom = ar9300_template_generic;
429
ahp->ah_eeprom.mac_addr[0] = 0x00;
430
ahp->ah_eeprom.mac_addr[1] = 0x03;
431
ahp->ah_eeprom.mac_addr[2] = 0x7F;
432
ahp->ah_eeprom.mac_addr[3] = 0xBA;
433
ahp->ah_eeprom.mac_addr[4] = 0xD0;
434
ahp->ah_eeprom.mac_addr[5] = 0x00;
435
ahp->ah_emu_eeprom = 1;
436
ahp->ah_eeprom.base_eep_header.txrx_mask = 0x33;
437
ahp->ah_eeprom.base_eep_header.txrxgain = 0x10;
438
/* need it to let art save in to flash ????? */
439
calibration_data_source = calibration_data_flash;
440
}
441
return HAL_OK;
442
}
443
#endif
444
if (AR_SREV_HORNET(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)
445
|| AR_SREV_HONEYBEE(ah)) {
446
ahp->try_eeprom = 0;
447
}
448
449
if (AR_SREV_HONEYBEE(ah)) {
450
ahp->try_otp = 0;
451
}
452
453
if (!ar9300_eeprom_restore(ah)) {
454
return HAL_EIO;
455
}
456
return HAL_OK;
457
#endif
458
}
459
460
u_int32_t
461
ar9300_eeprom_get(struct ath_hal_9300 *ahp, EEPROM_PARAM param)
462
{
463
ar9300_eeprom_t *eep = &ahp->ah_eeprom;
464
OSPREY_BASE_EEP_HEADER *p_base = &eep->base_eep_header;
465
OSPREY_BASE_EXTENSION_1 *base_ext1 = &eep->base_ext1;
466
467
switch (param) {
468
#ifdef NOTYET
469
case EEP_NFTHRESH_5:
470
return p_modal[0].noise_floor_thresh_ch[0];
471
case EEP_NFTHRESH_2:
472
return p_modal[1].noise_floor_thresh_ch[0];
473
#endif
474
case EEP_MAC_LSW:
475
return eep->mac_addr[0] << 8 | eep->mac_addr[1];
476
case EEP_MAC_MID:
477
return eep->mac_addr[2] << 8 | eep->mac_addr[3];
478
case EEP_MAC_MSW:
479
return eep->mac_addr[4] << 8 | eep->mac_addr[5];
480
case EEP_REG_0:
481
return p_base->reg_dmn[0];
482
case EEP_REG_1:
483
return p_base->reg_dmn[1];
484
case EEP_OP_CAP:
485
return p_base->device_cap;
486
case EEP_OP_MODE:
487
return p_base->op_cap_flags.op_flags;
488
case EEP_RF_SILENT:
489
return p_base->rf_silent;
490
#ifdef NOTYET
491
case EEP_OB_5:
492
return p_modal[0].ob;
493
case EEP_DB_5:
494
return p_modal[0].db;
495
case EEP_OB_2:
496
return p_modal[1].ob;
497
case EEP_DB_2:
498
return p_modal[1].db;
499
case EEP_MINOR_REV:
500
return p_base->eeprom_version & AR9300_EEP_VER_MINOR_MASK;
501
#endif
502
case EEP_TX_MASK:
503
return (p_base->txrx_mask >> 4) & 0xf;
504
case EEP_RX_MASK:
505
return p_base->txrx_mask & 0xf;
506
#ifdef NOTYET
507
case EEP_FSTCLK_5G:
508
return p_base->fast_clk5g;
509
case EEP_RXGAIN_TYPE:
510
return p_base->rx_gain_type;
511
#endif
512
case EEP_DRIVE_STRENGTH:
513
#define AR9300_EEP_BASE_DRIVE_STRENGTH 0x1
514
return p_base->misc_configuration & AR9300_EEP_BASE_DRIVE_STRENGTH;
515
case EEP_INTERNAL_REGULATOR:
516
/* Bit 4 is internal regulator flag */
517
return ((p_base->feature_enable & 0x10) >> 4);
518
case EEP_SWREG:
519
return (p_base->swreg);
520
case EEP_PAPRD_ENABLED:
521
/* Bit 5 is paprd flag */
522
return ((p_base->feature_enable & 0x20) >> 5);
523
case EEP_ANTDIV_control:
524
return (u_int32_t)(base_ext1->ant_div_control);
525
case EEP_CHAIN_MASK_REDUCE:
526
return ((p_base->misc_configuration >> 3) & 0x1);
527
case EEP_OL_PWRCTRL:
528
return 0;
529
case EEP_DEV_TYPE:
530
return p_base->device_type;
531
default:
532
HALASSERT(0);
533
return 0;
534
}
535
}
536
537
538
539
/******************************************************************************/
540
/*!
541
** \brief EEPROM fixup code for INI values
542
**
543
** This routine provides a place to insert "fixup" code for specific devices
544
** that need to modify INI values based on EEPROM values, BEFORE the INI values
545
** are written.
546
** Certain registers in the INI file can only be written once without
547
** undesired side effects, and this provides a place for EEPROM overrides
548
** in these cases.
549
**
550
** This is called at attach time once. It should not affect run time
551
** performance at all
552
**
553
** \param ah Pointer to HAL object (this)
554
** \param p_eep_data Pointer to (filled in) eeprom data structure
555
** \param reg register being inspected on this call
556
** \param value value in INI file
557
**
558
** \return Updated value for INI file.
559
*/
560
u_int32_t
561
ar9300_ini_fixup(struct ath_hal *ah, ar9300_eeprom_t *p_eep_data,
562
u_int32_t reg, u_int32_t value)
563
{
564
HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
565
"ar9300_eeprom_def_ini_fixup: FIXME\n");
566
#if 0
567
BASE_EEPDEF_HEADER *p_base = &(p_eep_data->base_eep_header);
568
569
switch (AH_PRIVATE(ah)->ah_devid)
570
{
571
case AR9300_DEVID_AR9300_PCI:
572
/*
573
** Need to set the external/internal regulator bit to the proper value.
574
** Can only write this ONCE.
575
*/
576
577
if ( reg == 0x7894 )
578
{
579
/*
580
** Check for an EEPROM data structure of "0x0b" or better
581
*/
582
583
HALDEBUG(ah, HAL_DEBUG_EEPROM, "ini VAL: %x EEPROM: %x\n",
584
value, (p_base->version & 0xff));
585
586
if ( (p_base->version & 0xff) > 0x0a) {
587
HALDEBUG(ah, HAL_DEBUG_EEPROM,
588
"PWDCLKIND: %d\n", p_base->pwdclkind);
589
value &= ~AR_AN_TOP2_PWDCLKIND;
590
value |=
591
AR_AN_TOP2_PWDCLKIND &
592
(p_base->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
593
} else {
594
HALDEBUG(ah, HAL_DEBUG_EEPROM, "PWDCLKIND Earlier Rev\n");
595
}
596
597
HALDEBUG(ah, HAL_DEBUG_EEPROM, "final ini VAL: %x\n", value);
598
}
599
break;
600
601
}
602
603
return (value);
604
#else
605
return 0;
606
#endif
607
}
608
609
/*
610
* Returns the interpolated y value corresponding to the specified x value
611
* from the np ordered pairs of data (px,py).
612
* The pairs do not have to be in any order.
613
* If the specified x value is less than any of the px,
614
* the returned y value is equal to the py for the lowest px.
615
* If the specified x value is greater than any of the px,
616
* the returned y value is equal to the py for the highest px.
617
*/
618
static int
619
interpolate(int32_t x, int32_t *px, int32_t *py, u_int16_t np)
620
{
621
int ip = 0;
622
int lx = 0, ly = 0, lhave = 0;
623
int hx = 0, hy = 0, hhave = 0;
624
int dx = 0;
625
int y = 0;
626
int bf, factor, plus;
627
628
lhave = 0;
629
hhave = 0;
630
/*
631
* identify best lower and higher x calibration measurement
632
*/
633
for (ip = 0; ip < np; ip++) {
634
dx = x - px[ip];
635
/* this measurement is higher than our desired x */
636
if (dx <= 0) {
637
if (!hhave || dx > (x - hx)) {
638
/* new best higher x measurement */
639
hx = px[ip];
640
hy = py[ip];
641
hhave = 1;
642
}
643
}
644
/* this measurement is lower than our desired x */
645
if (dx >= 0) {
646
if (!lhave || dx < (x - lx)) {
647
/* new best lower x measurement */
648
lx = px[ip];
649
ly = py[ip];
650
lhave = 1;
651
}
652
}
653
}
654
/* the low x is good */
655
if (lhave) {
656
/* so is the high x */
657
if (hhave) {
658
/* they're the same, so just pick one */
659
if (hx == lx) {
660
y = ly;
661
} else {
662
/* interpolate with round off */
663
bf = (2 * (hy - ly) * (x - lx)) / (hx - lx);
664
plus = (bf % 2);
665
factor = bf / 2;
666
y = ly + factor + plus;
667
}
668
} else {
669
/* only low is good, use it */
670
y = ly;
671
}
672
} else if (hhave) {
673
/* only high is good, use it */
674
y = hy;
675
} else {
676
/* nothing is good,this should never happen unless np=0, ???? */
677
y = -(1 << 30);
678
}
679
680
return y;
681
}
682
683
u_int8_t
684
ar9300_eeprom_get_legacy_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index,
685
u_int16_t freq, HAL_BOOL is_2ghz)
686
{
687
u_int16_t num_piers, i;
688
int32_t target_power_array[OSPREY_NUM_5G_20_TARGET_POWERS];
689
int32_t freq_array[OSPREY_NUM_5G_20_TARGET_POWERS];
690
u_int8_t *p_freq_bin;
691
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
692
CAL_TARGET_POWER_LEG *p_eeprom_target_pwr;
693
694
if (is_2ghz) {
695
num_piers = OSPREY_NUM_2G_20_TARGET_POWERS;
696
p_eeprom_target_pwr = eep->cal_target_power_2g;
697
p_freq_bin = eep->cal_target_freqbin_2g;
698
} else {
699
num_piers = OSPREY_NUM_5G_20_TARGET_POWERS;
700
p_eeprom_target_pwr = eep->cal_target_power_5g;
701
p_freq_bin = eep->cal_target_freqbin_5g;
702
}
703
704
/*
705
* create array of channels and targetpower from
706
* targetpower piers stored on eeprom
707
*/
708
for (i = 0; i < num_piers; i++) {
709
freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz);
710
target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index];
711
}
712
713
/* interpolate to get target power for given frequency */
714
return
715
((u_int8_t)interpolate(
716
(int32_t)freq, freq_array, target_power_array, num_piers));
717
}
718
719
u_int8_t
720
ar9300_eeprom_get_ht20_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index,
721
u_int16_t freq, HAL_BOOL is_2ghz)
722
{
723
u_int16_t num_piers, i;
724
int32_t target_power_array[OSPREY_NUM_5G_20_TARGET_POWERS];
725
int32_t freq_array[OSPREY_NUM_5G_20_TARGET_POWERS];
726
u_int8_t *p_freq_bin;
727
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
728
OSP_CAL_TARGET_POWER_HT *p_eeprom_target_pwr;
729
730
if (is_2ghz) {
731
num_piers = OSPREY_NUM_2G_20_TARGET_POWERS;
732
p_eeprom_target_pwr = eep->cal_target_power_2g_ht20;
733
p_freq_bin = eep->cal_target_freqbin_2g_ht20;
734
} else {
735
num_piers = OSPREY_NUM_5G_20_TARGET_POWERS;
736
p_eeprom_target_pwr = eep->cal_target_power_5g_ht20;
737
p_freq_bin = eep->cal_target_freqbin_5g_ht20;
738
}
739
740
/*
741
* create array of channels and targetpower from
742
* targetpower piers stored on eeprom
743
*/
744
for (i = 0; i < num_piers; i++) {
745
freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz);
746
target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index];
747
}
748
749
/* interpolate to get target power for given frequency */
750
return
751
((u_int8_t)interpolate(
752
(int32_t)freq, freq_array, target_power_array, num_piers));
753
}
754
755
u_int8_t
756
ar9300_eeprom_get_ht40_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index,
757
u_int16_t freq, HAL_BOOL is_2ghz)
758
{
759
u_int16_t num_piers, i;
760
int32_t target_power_array[OSPREY_NUM_5G_40_TARGET_POWERS];
761
int32_t freq_array[OSPREY_NUM_5G_40_TARGET_POWERS];
762
u_int8_t *p_freq_bin;
763
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
764
OSP_CAL_TARGET_POWER_HT *p_eeprom_target_pwr;
765
766
if (is_2ghz) {
767
num_piers = OSPREY_NUM_2G_40_TARGET_POWERS;
768
p_eeprom_target_pwr = eep->cal_target_power_2g_ht40;
769
p_freq_bin = eep->cal_target_freqbin_2g_ht40;
770
} else {
771
num_piers = OSPREY_NUM_5G_40_TARGET_POWERS;
772
p_eeprom_target_pwr = eep->cal_target_power_5g_ht40;
773
p_freq_bin = eep->cal_target_freqbin_5g_ht40;
774
}
775
776
/*
777
* create array of channels and targetpower from
778
* targetpower piers stored on eeprom
779
*/
780
for (i = 0; i < num_piers; i++) {
781
freq_array[i] = FBIN2FREQ(p_freq_bin[i], is_2ghz);
782
target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index];
783
}
784
785
/* interpolate to get target power for given frequency */
786
return
787
((u_int8_t)interpolate(
788
(int32_t)freq, freq_array, target_power_array, num_piers));
789
}
790
791
u_int8_t
792
ar9300_eeprom_get_cck_trgt_pwr(struct ath_hal *ah, u_int16_t rate_index,
793
u_int16_t freq)
794
{
795
u_int16_t num_piers = OSPREY_NUM_2G_CCK_TARGET_POWERS, i;
796
int32_t target_power_array[OSPREY_NUM_2G_CCK_TARGET_POWERS];
797
int32_t freq_array[OSPREY_NUM_2G_CCK_TARGET_POWERS];
798
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
799
u_int8_t *p_freq_bin = eep->cal_target_freqbin_cck;
800
CAL_TARGET_POWER_LEG *p_eeprom_target_pwr = eep->cal_target_power_cck;
801
802
/*
803
* create array of channels and targetpower from
804
* targetpower piers stored on eeprom
805
*/
806
for (i = 0; i < num_piers; i++) {
807
freq_array[i] = FBIN2FREQ(p_freq_bin[i], 1);
808
target_power_array[i] = p_eeprom_target_pwr[i].t_pow2x[rate_index];
809
}
810
811
/* interpolate to get target power for given frequency */
812
return
813
((u_int8_t)interpolate(
814
(int32_t)freq, freq_array, target_power_array, num_piers));
815
}
816
817
/*
818
* Set tx power registers to array of values passed in
819
*/
820
int
821
ar9300_transmit_power_reg_write(struct ath_hal *ah, u_int8_t *p_pwr_array)
822
{
823
#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
824
/* make sure forced gain is not set */
825
#if 0
826
field_write("force_dac_gain", 0);
827
OS_REG_WRITE(ah, 0xa3f8, 0);
828
field_write("force_tx_gain", 0);
829
#endif
830
831
OS_REG_WRITE(ah, 0xa458, 0);
832
833
/* Write the OFDM power per rate set */
834
/* 6 (LSB), 9, 12, 18 (MSB) */
835
OS_REG_WRITE(ah, 0xa3c0,
836
POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24)
837
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 16)
838
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8)
839
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0)
840
);
841
/* 24 (LSB), 36, 48, 54 (MSB) */
842
OS_REG_WRITE(ah, 0xa3c4,
843
POW_SM(p_pwr_array[ALL_TARGET_LEGACY_54], 24)
844
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_48], 16)
845
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_36], 8)
846
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 0)
847
);
848
849
/* Write the CCK power per rate set */
850
/* 1L (LSB), reserved, 2L, 2S (MSB) */
851
OS_REG_WRITE(ah, 0xa3c8,
852
POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 24)
853
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16)
854
/* | POW_SM(tx_power_times2, 8)*/ /* this is reserved for Osprey */
855
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0)
856
);
857
/* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
858
OS_REG_WRITE(ah, 0xa3cc,
859
POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11S], 24)
860
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_11L], 16)
861
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_5S], 8)
862
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0)
863
);
864
865
/* write the power for duplicated frames - HT40 */
866
/* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */
867
OS_REG_WRITE(ah, 0xa3e0,
868
POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 24)
869
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 16)
870
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], 8)
871
| POW_SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], 0)
872
);
873
874
/* Write the HT20 power per rate set */
875
/* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
876
OS_REG_WRITE(ah, 0xa3d0,
877
POW_SM(p_pwr_array[ALL_TARGET_HT20_5], 24)
878
| POW_SM(p_pwr_array[ALL_TARGET_HT20_4], 16)
879
| POW_SM(p_pwr_array[ALL_TARGET_HT20_1_3_9_11_17_19], 8)
880
| POW_SM(p_pwr_array[ALL_TARGET_HT20_0_8_16], 0)
881
);
882
883
/* 6 (LSB), 7, 12, 13 (MSB) */
884
OS_REG_WRITE(ah, 0xa3d4,
885
POW_SM(p_pwr_array[ALL_TARGET_HT20_13], 24)
886
| POW_SM(p_pwr_array[ALL_TARGET_HT20_12], 16)
887
| POW_SM(p_pwr_array[ALL_TARGET_HT20_7], 8)
888
| POW_SM(p_pwr_array[ALL_TARGET_HT20_6], 0)
889
);
890
891
/* 14 (LSB), 15, 20, 21 */
892
OS_REG_WRITE(ah, 0xa3e4,
893
POW_SM(p_pwr_array[ALL_TARGET_HT20_21], 24)
894
| POW_SM(p_pwr_array[ALL_TARGET_HT20_20], 16)
895
| POW_SM(p_pwr_array[ALL_TARGET_HT20_15], 8)
896
| POW_SM(p_pwr_array[ALL_TARGET_HT20_14], 0)
897
);
898
899
/* Mixed HT20 and HT40 rates */
900
/* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
901
OS_REG_WRITE(ah, 0xa3e8,
902
POW_SM(p_pwr_array[ALL_TARGET_HT40_23], 24)
903
| POW_SM(p_pwr_array[ALL_TARGET_HT40_22], 16)
904
| POW_SM(p_pwr_array[ALL_TARGET_HT20_23], 8)
905
| POW_SM(p_pwr_array[ALL_TARGET_HT20_22], 0)
906
);
907
908
/* Write the HT40 power per rate set */
909
/* correct PAR difference between HT40 and HT20/LEGACY */
910
/* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
911
OS_REG_WRITE(ah, 0xa3d8,
912
POW_SM(p_pwr_array[ALL_TARGET_HT40_5], 24)
913
| POW_SM(p_pwr_array[ALL_TARGET_HT40_4], 16)
914
| POW_SM(p_pwr_array[ALL_TARGET_HT40_1_3_9_11_17_19], 8)
915
| POW_SM(p_pwr_array[ALL_TARGET_HT40_0_8_16], 0)
916
);
917
918
/* 6 (LSB), 7, 12, 13 (MSB) */
919
OS_REG_WRITE(ah, 0xa3dc,
920
POW_SM(p_pwr_array[ALL_TARGET_HT40_13], 24)
921
| POW_SM(p_pwr_array[ALL_TARGET_HT40_12], 16)
922
| POW_SM(p_pwr_array[ALL_TARGET_HT40_7], 8)
923
| POW_SM(p_pwr_array[ALL_TARGET_HT40_6], 0)
924
);
925
926
/* 14 (LSB), 15, 20, 21 */
927
OS_REG_WRITE(ah, 0xa3ec,
928
POW_SM(p_pwr_array[ALL_TARGET_HT40_21], 24)
929
| POW_SM(p_pwr_array[ALL_TARGET_HT40_20], 16)
930
| POW_SM(p_pwr_array[ALL_TARGET_HT40_15], 8)
931
| POW_SM(p_pwr_array[ALL_TARGET_HT40_14], 0)
932
);
933
934
return 0;
935
#undef POW_SM
936
}
937
938
static void
939
ar9300_selfgen_tpc_reg_write(struct ath_hal *ah, const struct ieee80211_channel *chan,
940
u_int8_t *p_pwr_array)
941
{
942
u_int32_t tpc_reg_val;
943
944
/* Set the target power values for self generated frames (ACK,RTS/CTS) to
945
* be within limits. This is just a safety measure.With per packet TPC mode
946
* enabled the target power value used with self generated frames will be
947
* MIN( TPC reg, BB_powertx_rate register)
948
*/
949
950
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
951
tpc_reg_val = (SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_ACK) |
952
SM(p_pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_CTS) |
953
SM(0x3f, AR_TPC_CHIRP) |
954
SM(0x3f, AR_TPC_RPT));
955
} else {
956
tpc_reg_val = (SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_ACK) |
957
SM(p_pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_CTS) |
958
SM(0x3f, AR_TPC_CHIRP) |
959
SM(0x3f, AR_TPC_RPT));
960
}
961
OS_REG_WRITE(ah, AR_TPC, tpc_reg_val);
962
}
963
964
void
965
ar9300_set_target_power_from_eeprom(struct ath_hal *ah, u_int16_t freq,
966
u_int8_t *target_power_val_t2)
967
{
968
/* hard code for now, need to get from eeprom struct */
969
u_int8_t ht40_power_inc_for_pdadc = 0;
970
HAL_BOOL is_2ghz = 0;
971
972
if (freq < 4000) {
973
is_2ghz = 1;
974
}
975
976
target_power_val_t2[ALL_TARGET_LEGACY_6_24] =
977
ar9300_eeprom_get_legacy_trgt_pwr(
978
ah, LEGACY_TARGET_RATE_6_24, freq, is_2ghz);
979
target_power_val_t2[ALL_TARGET_LEGACY_36] =
980
ar9300_eeprom_get_legacy_trgt_pwr(
981
ah, LEGACY_TARGET_RATE_36, freq, is_2ghz);
982
target_power_val_t2[ALL_TARGET_LEGACY_48] =
983
ar9300_eeprom_get_legacy_trgt_pwr(
984
ah, LEGACY_TARGET_RATE_48, freq, is_2ghz);
985
target_power_val_t2[ALL_TARGET_LEGACY_54] =
986
ar9300_eeprom_get_legacy_trgt_pwr(
987
ah, LEGACY_TARGET_RATE_54, freq, is_2ghz);
988
target_power_val_t2[ALL_TARGET_LEGACY_1L_5L] =
989
ar9300_eeprom_get_cck_trgt_pwr(
990
ah, LEGACY_TARGET_RATE_1L_5L, freq);
991
target_power_val_t2[ALL_TARGET_LEGACY_5S] =
992
ar9300_eeprom_get_cck_trgt_pwr(
993
ah, LEGACY_TARGET_RATE_5S, freq);
994
target_power_val_t2[ALL_TARGET_LEGACY_11L] =
995
ar9300_eeprom_get_cck_trgt_pwr(
996
ah, LEGACY_TARGET_RATE_11L, freq);
997
target_power_val_t2[ALL_TARGET_LEGACY_11S] =
998
ar9300_eeprom_get_cck_trgt_pwr(
999
ah, LEGACY_TARGET_RATE_11S, freq);
1000
target_power_val_t2[ALL_TARGET_HT20_0_8_16] =
1001
ar9300_eeprom_get_ht20_trgt_pwr(
1002
ah, HT_TARGET_RATE_0_8_16, freq, is_2ghz);
1003
target_power_val_t2[ALL_TARGET_HT20_1_3_9_11_17_19] =
1004
ar9300_eeprom_get_ht20_trgt_pwr(
1005
ah, HT_TARGET_RATE_1_3_9_11_17_19, freq, is_2ghz);
1006
target_power_val_t2[ALL_TARGET_HT20_4] =
1007
ar9300_eeprom_get_ht20_trgt_pwr(
1008
ah, HT_TARGET_RATE_4, freq, is_2ghz);
1009
target_power_val_t2[ALL_TARGET_HT20_5] =
1010
ar9300_eeprom_get_ht20_trgt_pwr(
1011
ah, HT_TARGET_RATE_5, freq, is_2ghz);
1012
target_power_val_t2[ALL_TARGET_HT20_6] =
1013
ar9300_eeprom_get_ht20_trgt_pwr(
1014
ah, HT_TARGET_RATE_6, freq, is_2ghz);
1015
target_power_val_t2[ALL_TARGET_HT20_7] =
1016
ar9300_eeprom_get_ht20_trgt_pwr(
1017
ah, HT_TARGET_RATE_7, freq, is_2ghz);
1018
target_power_val_t2[ALL_TARGET_HT20_12] =
1019
ar9300_eeprom_get_ht20_trgt_pwr(
1020
ah, HT_TARGET_RATE_12, freq, is_2ghz);
1021
target_power_val_t2[ALL_TARGET_HT20_13] =
1022
ar9300_eeprom_get_ht20_trgt_pwr(
1023
ah, HT_TARGET_RATE_13, freq, is_2ghz);
1024
target_power_val_t2[ALL_TARGET_HT20_14] =
1025
ar9300_eeprom_get_ht20_trgt_pwr(
1026
ah, HT_TARGET_RATE_14, freq, is_2ghz);
1027
target_power_val_t2[ALL_TARGET_HT20_15] =
1028
ar9300_eeprom_get_ht20_trgt_pwr(
1029
ah, HT_TARGET_RATE_15, freq, is_2ghz);
1030
target_power_val_t2[ALL_TARGET_HT20_20] =
1031
ar9300_eeprom_get_ht20_trgt_pwr(
1032
ah, HT_TARGET_RATE_20, freq, is_2ghz);
1033
target_power_val_t2[ALL_TARGET_HT20_21] =
1034
ar9300_eeprom_get_ht20_trgt_pwr(
1035
ah, HT_TARGET_RATE_21, freq, is_2ghz);
1036
target_power_val_t2[ALL_TARGET_HT20_22] =
1037
ar9300_eeprom_get_ht20_trgt_pwr(
1038
ah, HT_TARGET_RATE_22, freq, is_2ghz);
1039
target_power_val_t2[ALL_TARGET_HT20_23] =
1040
ar9300_eeprom_get_ht20_trgt_pwr(
1041
ah, HT_TARGET_RATE_23, freq, is_2ghz);
1042
target_power_val_t2[ALL_TARGET_HT40_0_8_16] =
1043
ar9300_eeprom_get_ht40_trgt_pwr(
1044
ah, HT_TARGET_RATE_0_8_16, freq, is_2ghz) +
1045
ht40_power_inc_for_pdadc;
1046
target_power_val_t2[ALL_TARGET_HT40_1_3_9_11_17_19] =
1047
ar9300_eeprom_get_ht40_trgt_pwr(
1048
ah, HT_TARGET_RATE_1_3_9_11_17_19, freq, is_2ghz) +
1049
ht40_power_inc_for_pdadc;
1050
target_power_val_t2[ALL_TARGET_HT40_4] =
1051
ar9300_eeprom_get_ht40_trgt_pwr(
1052
ah, HT_TARGET_RATE_4, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1053
target_power_val_t2[ALL_TARGET_HT40_5] =
1054
ar9300_eeprom_get_ht40_trgt_pwr(
1055
ah, HT_TARGET_RATE_5, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1056
target_power_val_t2[ALL_TARGET_HT40_6] =
1057
ar9300_eeprom_get_ht40_trgt_pwr(
1058
ah, HT_TARGET_RATE_6, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1059
target_power_val_t2[ALL_TARGET_HT40_7] =
1060
ar9300_eeprom_get_ht40_trgt_pwr(
1061
ah, HT_TARGET_RATE_7, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1062
target_power_val_t2[ALL_TARGET_HT40_12] =
1063
ar9300_eeprom_get_ht40_trgt_pwr(
1064
ah, HT_TARGET_RATE_12, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1065
target_power_val_t2[ALL_TARGET_HT40_13] =
1066
ar9300_eeprom_get_ht40_trgt_pwr(
1067
ah, HT_TARGET_RATE_13, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1068
target_power_val_t2[ALL_TARGET_HT40_14] =
1069
ar9300_eeprom_get_ht40_trgt_pwr(
1070
ah, HT_TARGET_RATE_14, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1071
target_power_val_t2[ALL_TARGET_HT40_15] =
1072
ar9300_eeprom_get_ht40_trgt_pwr(
1073
ah, HT_TARGET_RATE_15, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1074
target_power_val_t2[ALL_TARGET_HT40_20] =
1075
ar9300_eeprom_get_ht40_trgt_pwr(
1076
ah, HT_TARGET_RATE_20, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1077
target_power_val_t2[ALL_TARGET_HT40_21] =
1078
ar9300_eeprom_get_ht40_trgt_pwr(
1079
ah, HT_TARGET_RATE_21, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1080
target_power_val_t2[ALL_TARGET_HT40_22] =
1081
ar9300_eeprom_get_ht40_trgt_pwr(
1082
ah, HT_TARGET_RATE_22, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1083
target_power_val_t2[ALL_TARGET_HT40_23] =
1084
ar9300_eeprom_get_ht40_trgt_pwr(
1085
ah, HT_TARGET_RATE_23, freq, is_2ghz) + ht40_power_inc_for_pdadc;
1086
1087
#ifdef AH_DEBUG
1088
{
1089
int i = 0;
1090
1091
HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: APPLYING TARGET POWERS\n", __func__);
1092
while (i < ar9300_rate_size) {
1093
HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ",
1094
__func__, i, target_power_val_t2[i]);
1095
i++;
1096
if (i == ar9300_rate_size) {
1097
break;
1098
}
1099
HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ",
1100
__func__, i, target_power_val_t2[i]);
1101
i++;
1102
if (i == ar9300_rate_size) {
1103
break;
1104
}
1105
HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x ",
1106
__func__, i, target_power_val_t2[i]);
1107
i++;
1108
if (i == ar9300_rate_size) {
1109
break;
1110
}
1111
HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: TPC[%02d] 0x%08x \n",
1112
__func__, i, target_power_val_t2[i]);
1113
i++;
1114
}
1115
}
1116
#endif
1117
}
1118
1119
u_int16_t *ar9300_regulatory_domain_get(struct ath_hal *ah)
1120
{
1121
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1122
return eep->base_eep_header.reg_dmn;
1123
}
1124
1125
1126
int32_t
1127
ar9300_eeprom_write_enable_gpio_get(struct ath_hal *ah)
1128
{
1129
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1130
return eep->base_eep_header.eeprom_write_enable_gpio;
1131
}
1132
1133
int32_t
1134
ar9300_wlan_disable_gpio_get(struct ath_hal *ah)
1135
{
1136
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1137
return eep->base_eep_header.wlan_disable_gpio;
1138
}
1139
1140
int32_t
1141
ar9300_wlan_led_gpio_get(struct ath_hal *ah)
1142
{
1143
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1144
return eep->base_eep_header.wlan_led_gpio;
1145
}
1146
1147
int32_t
1148
ar9300_rx_band_select_gpio_get(struct ath_hal *ah)
1149
{
1150
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1151
return eep->base_eep_header.rx_band_select_gpio;
1152
}
1153
1154
/*
1155
* since valid noise floor values are negative, returns 1 on error
1156
*/
1157
int32_t
1158
ar9300_noise_floor_cal_or_power_get(struct ath_hal *ah, int32_t frequency,
1159
int32_t ichain, HAL_BOOL use_cal)
1160
{
1161
int nf_use = 1; /* start with an error return value */
1162
int32_t fx[OSPREY_NUM_5G_CAL_PIERS + OSPREY_NUM_2G_CAL_PIERS];
1163
int32_t nf[OSPREY_NUM_5G_CAL_PIERS + OSPREY_NUM_2G_CAL_PIERS];
1164
int nnf;
1165
int is_2ghz;
1166
int ipier, npier;
1167
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1168
u_int8_t *p_cal_pier;
1169
OSP_CAL_DATA_PER_FREQ_OP_LOOP *p_cal_pier_struct;
1170
1171
/*
1172
* check chain value
1173
*/
1174
if (ichain < 0 || ichain >= OSPREY_MAX_CHAINS) {
1175
return 1;
1176
}
1177
1178
/* figure out which band we're using */
1179
is_2ghz = (frequency < 4000);
1180
if (is_2ghz) {
1181
npier = OSPREY_NUM_2G_CAL_PIERS;
1182
p_cal_pier = eep->cal_freq_pier_2g;
1183
p_cal_pier_struct = eep->cal_pier_data_2g[ichain];
1184
} else {
1185
npier = OSPREY_NUM_5G_CAL_PIERS;
1186
p_cal_pier = eep->cal_freq_pier_5g;
1187
p_cal_pier_struct = eep->cal_pier_data_5g[ichain];
1188
}
1189
/* look for valid noise floor values */
1190
nnf = 0;
1191
for (ipier = 0; ipier < npier; ipier++) {
1192
fx[nnf] = FBIN2FREQ(p_cal_pier[ipier], is_2ghz);
1193
nf[nnf] = use_cal ?
1194
p_cal_pier_struct[ipier].rx_noisefloor_cal :
1195
p_cal_pier_struct[ipier].rx_noisefloor_power;
1196
if (nf[nnf] < 0) {
1197
nnf++;
1198
}
1199
}
1200
/*
1201
* If we have some valid values, interpolate to find the value
1202
* at the desired frequency.
1203
*/
1204
if (nnf > 0) {
1205
nf_use = interpolate(frequency, fx, nf, nnf);
1206
}
1207
1208
return nf_use;
1209
}
1210
1211
/*
1212
* Return the Rx NF offset for specific channel.
1213
* The values saved in EEPROM/OTP/Flash is converted through the following way:
1214
* ((_p) - NOISE_PWR_DATA_OFFSET) << 2
1215
* So we need to convert back to the original values.
1216
*/
1217
int ar9300_get_rx_nf_offset(struct ath_hal *ah, struct ieee80211_channel *chan, int8_t *nf_pwr, int8_t *nf_cal) {
1218
HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
1219
int8_t rx_nf_pwr, rx_nf_cal;
1220
int i;
1221
//HALASSERT(ichan);
1222
1223
/* Fill 0 if valid internal channel is not found */
1224
if (ichan == AH_NULL) {
1225
OS_MEMZERO(nf_pwr, sizeof(nf_pwr[0])*OSPREY_MAX_CHAINS);
1226
OS_MEMZERO(nf_cal, sizeof(nf_cal[0])*OSPREY_MAX_CHAINS);
1227
return -1;
1228
}
1229
1230
for (i = 0; i < OSPREY_MAX_CHAINS; i++) {
1231
if ((rx_nf_pwr = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 0)) == 1) {
1232
nf_pwr[i] = 0;
1233
} else {
1234
//printk("%s: raw nf_pwr[%d] = %d\n", __func__, i, rx_nf_pwr);
1235
nf_pwr[i] = NOISE_PWR_DBM_2_INT(rx_nf_pwr);
1236
}
1237
1238
if ((rx_nf_cal = ar9300_noise_floor_cal_or_power_get(ah, ichan->channel, i, 1)) == 1) {
1239
nf_cal[i] = 0;
1240
} else {
1241
//printk("%s: raw nf_cal[%d] = %d\n", __func__, i, rx_nf_cal);
1242
nf_cal[i] = NOISE_PWR_DBM_2_INT(rx_nf_cal);
1243
}
1244
}
1245
1246
return 0;
1247
}
1248
1249
int32_t ar9300_rx_gain_index_get(struct ath_hal *ah)
1250
{
1251
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1252
1253
return (eep->base_eep_header.txrxgain) & 0xf; /* bits 3:0 */
1254
}
1255
1256
1257
int32_t ar9300_tx_gain_index_get(struct ath_hal *ah)
1258
{
1259
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1260
1261
return (eep->base_eep_header.txrxgain >> 4) & 0xf; /* bits 7:4 */
1262
}
1263
1264
HAL_BOOL ar9300_internal_regulator_apply(struct ath_hal *ah)
1265
{
1266
struct ath_hal_9300 *ahp = AH9300(ah);
1267
int internal_regulator = ar9300_eeprom_get(ahp, EEP_INTERNAL_REGULATOR);
1268
int reg_pmu1, reg_pmu2, reg_pmu1_set, reg_pmu2_set;
1269
u_int32_t reg_PMU1, reg_PMU2;
1270
unsigned long eep_addr;
1271
u_int32_t reg_val, reg_usb = 0, reg_pmu = 0;
1272
int usb_valid = 0, pmu_valid = 0;
1273
unsigned char pmu_refv;
1274
1275
if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
1276
reg_PMU1 = AR_PHY_PMU1_JUPITER;
1277
reg_PMU2 = AR_PHY_PMU2_JUPITER;
1278
}
1279
else {
1280
reg_PMU1 = AR_PHY_PMU1;
1281
reg_PMU2 = AR_PHY_PMU2;
1282
}
1283
1284
if (internal_regulator) {
1285
if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) {
1286
if (AR_SREV_HORNET(ah)) {
1287
/* Read OTP first */
1288
for (eep_addr = 0x14; ; eep_addr -= 0x10) {
1289
1290
ar9300_otp_read(ah, eep_addr / 4, &reg_val, 1);
1291
1292
if ((reg_val & 0x80) == 0x80){
1293
usb_valid = 1;
1294
reg_usb = reg_val & 0x000000ff;
1295
}
1296
1297
if ((reg_val & 0x80000000) == 0x80000000){
1298
pmu_valid = 1;
1299
reg_pmu = (reg_val & 0xff000000) >> 24;
1300
}
1301
1302
if (eep_addr == 0x4) {
1303
break;
1304
}
1305
}
1306
1307
if (pmu_valid) {
1308
pmu_refv = reg_pmu & 0xf;
1309
} else {
1310
pmu_refv = 0x8;
1311
}
1312
1313
/*
1314
* If (valid) {
1315
* Usb_phy_ctrl2_tx_cal_en -> 0
1316
* Usb_phy_ctrl2_tx_cal_sel -> 0
1317
* Usb_phy_ctrl2_tx_man_cal -> 0, 1, 3, 7 or 15 from OTP
1318
* }
1319
*/
1320
if (usb_valid) {
1321
OS_REG_RMW_FIELD(ah, 0x16c88, AR_PHY_CTRL2_TX_CAL_EN, 0x0);
1322
OS_REG_RMW_FIELD(ah, 0x16c88, AR_PHY_CTRL2_TX_CAL_SEL, 0x0);
1323
OS_REG_RMW_FIELD(ah, 0x16c88,
1324
AR_PHY_CTRL2_TX_MAN_CAL, (reg_usb & 0xf));
1325
}
1326
1327
} else {
1328
pmu_refv = 0x8;
1329
}
1330
/*#ifndef USE_HIF*/
1331
/* Follow the MDK settings for Hornet PMU.
1332
* my $pwd = 0x0;
1333
* my $Nfdiv = 0x3; # xtal_freq = 25MHz
1334
* my $Nfdiv = 0x4; # xtal_freq = 40MHz
1335
* my $Refv = 0x7; # 0x5:1.22V; 0x8:1.29V
1336
* my $Gm1 = 0x3; #Poseidon $Gm1=1
1337
* my $classb = 0x0;
1338
* my $Cc = 0x1; #Poseidon $Cc=7
1339
* my $Rc = 0x6;
1340
* my $ramp_slope = 0x1;
1341
* my $Segm = 0x3;
1342
* my $use_local_osc = 0x0;
1343
* my $force_xosc_stable = 0x0;
1344
* my $Selfb = 0x0; #Poseidon $Selfb=1
1345
* my $Filterfb = 0x3; #Poseidon $Filterfb=0
1346
* my $Filtervc = 0x0;
1347
* my $disc = 0x0;
1348
* my $discdel = 0x4;
1349
* my $spare = 0x0;
1350
* $reg_PMU1 =
1351
* $pwd | ($Nfdiv<<1) | ($Refv<<4) | ($Gm1<<8) |
1352
* ($classb<<11) | ($Cc<<14) | ($Rc<<17) | ($ramp_slope<<20) |
1353
* ($Segm<<24) | ($use_local_osc<<26) |
1354
* ($force_xosc_stable<<27) | ($Selfb<<28) | ($Filterfb<<29);
1355
* $reg_PMU2 = $handle->reg_rd("ch0_PMU2");
1356
* $reg_PMU2 = ($reg_PMU2 & 0xfe3fffff) | ($Filtervc<<22);
1357
* $reg_PMU2 = ($reg_PMU2 & 0xe3ffffff) | ($discdel<<26);
1358
* $reg_PMU2 = ($reg_PMU2 & 0x1fffffff) | ($spare<<29);
1359
*/
1360
if (ahp->clk_25mhz) {
1361
reg_pmu1_set = 0 |
1362
(3 << 1) | (pmu_refv << 4) | (3 << 8) | (0 << 11) |
1363
(1 << 14) | (6 << 17) | (1 << 20) | (3 << 24) |
1364
(0 << 26) | (0 << 27) | (0 << 28) | (0 << 29);
1365
} else {
1366
if (AR_SREV_POSEIDON(ah)) {
1367
reg_pmu1_set = 0 |
1368
(5 << 1) | (7 << 4) | (2 << 8) | (0 << 11) |
1369
(2 << 14) | (6 << 17) | (1 << 20) | (3 << 24) |
1370
(0 << 26) | (0 << 27) | (1 << 28) | (0 << 29) ;
1371
} else {
1372
reg_pmu1_set = 0 |
1373
(4 << 1) | (7 << 4) | (3 << 8) | (0 << 11) |
1374
(1 << 14) | (6 << 17) | (1 << 20) | (3 << 24) |
1375
(0 << 26) | (0 << 27) | (0 << 28) | (0 << 29) ;
1376
}
1377
}
1378
OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x0);
1379
1380
OS_REG_WRITE(ah, reg_PMU1, reg_pmu1_set); /* 0x638c8376 */
1381
reg_pmu1 = OS_REG_READ(ah, reg_PMU1);
1382
while (reg_pmu1 != reg_pmu1_set) {
1383
OS_REG_WRITE(ah, reg_PMU1, reg_pmu1_set); /* 0x638c8376 */
1384
OS_DELAY(10);
1385
reg_pmu1 = OS_REG_READ(ah, reg_PMU1);
1386
}
1387
1388
reg_pmu2_set =
1389
(OS_REG_READ(ah, reg_PMU2) & (~0xFFC00000)) | (4 << 26);
1390
OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set);
1391
reg_pmu2 = OS_REG_READ(ah, reg_PMU2);
1392
while (reg_pmu2 != reg_pmu2_set) {
1393
OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set);
1394
OS_DELAY(10);
1395
reg_pmu2 = OS_REG_READ(ah, reg_PMU2);
1396
}
1397
reg_pmu2_set =
1398
(OS_REG_READ(ah, reg_PMU2) & (~0x00200000)) | (1 << 21);
1399
OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set);
1400
reg_pmu2 = OS_REG_READ(ah, reg_PMU2);
1401
while (reg_pmu2 != reg_pmu2_set) {
1402
OS_REG_WRITE(ah, reg_PMU2, reg_pmu2_set);
1403
OS_DELAY(10);
1404
reg_pmu2 = OS_REG_READ(ah, reg_PMU2);
1405
}
1406
/*#endif*/
1407
} else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
1408
/* Internal regulator is ON. Write swreg register. */
1409
int swreg = ar9300_eeprom_get(ahp, EEP_SWREG);
1410
OS_REG_WRITE(ah, reg_PMU1, swreg);
1411
} else {
1412
/* Internal regulator is ON. Write swreg register. */
1413
int swreg = ar9300_eeprom_get(ahp, EEP_SWREG);
1414
OS_REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1415
OS_REG_READ(ah, AR_RTC_REG_CONTROL1) &
1416
(~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
1417
OS_REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
1418
/* Set REG_CONTROL1.SWREG_PROGRAM */
1419
OS_REG_WRITE(ah, AR_RTC_REG_CONTROL1,
1420
OS_REG_READ(ah, AR_RTC_REG_CONTROL1) |
1421
AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
1422
}
1423
} else {
1424
if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah)) {
1425
OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x0);
1426
reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM);
1427
while (reg_pmu2) {
1428
OS_DELAY(10);
1429
reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM);
1430
}
1431
OS_REG_RMW_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD, 0x1);
1432
reg_pmu1 = OS_REG_READ_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD);
1433
while (!reg_pmu1) {
1434
OS_DELAY(10);
1435
reg_pmu1 = OS_REG_READ_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD);
1436
}
1437
OS_REG_RMW_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM, 0x1);
1438
reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM);
1439
while (!reg_pmu2) {
1440
OS_DELAY(10);
1441
reg_pmu2 = OS_REG_READ_FIELD(ah, reg_PMU2, AR_PHY_PMU2_PGM);
1442
}
1443
} else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
1444
OS_REG_RMW_FIELD(ah, reg_PMU1, AR_PHY_PMU1_PWD, 0x1);
1445
} else {
1446
OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK,
1447
(OS_REG_READ(ah, AR_RTC_SLEEP_CLK) |
1448
AR_RTC_FORCE_SWREG_PRD | AR_RTC_PCIE_RST_PWDN_EN));
1449
}
1450
}
1451
1452
return 0;
1453
}
1454
1455
HAL_BOOL ar9300_drive_strength_apply(struct ath_hal *ah)
1456
{
1457
struct ath_hal_9300 *ahp = AH9300(ah);
1458
int drive_strength;
1459
unsigned long reg;
1460
1461
drive_strength = ar9300_eeprom_get(ahp, EEP_DRIVE_STRENGTH);
1462
if (drive_strength) {
1463
reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS1);
1464
reg &= ~0x00ffffc0;
1465
reg |= 0x5 << 21;
1466
reg |= 0x5 << 18;
1467
reg |= 0x5 << 15;
1468
reg |= 0x5 << 12;
1469
reg |= 0x5 << 9;
1470
reg |= 0x5 << 6;
1471
OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg);
1472
1473
reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS2);
1474
reg &= ~0xffffffe0;
1475
reg |= 0x5 << 29;
1476
reg |= 0x5 << 26;
1477
reg |= 0x5 << 23;
1478
reg |= 0x5 << 20;
1479
reg |= 0x5 << 17;
1480
reg |= 0x5 << 14;
1481
reg |= 0x5 << 11;
1482
reg |= 0x5 << 8;
1483
reg |= 0x5 << 5;
1484
OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg);
1485
1486
reg = OS_REG_READ(ah, AR_PHY_65NM_CH0_BIAS4);
1487
reg &= ~0xff800000;
1488
reg |= 0x5 << 29;
1489
reg |= 0x5 << 26;
1490
reg |= 0x5 << 23;
1491
OS_REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
1492
}
1493
return 0;
1494
}
1495
1496
int32_t ar9300_xpa_bias_level_get(struct ath_hal *ah, HAL_BOOL is_2ghz)
1497
{
1498
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1499
if (is_2ghz) {
1500
return eep->modal_header_2g.xpa_bias_lvl;
1501
} else {
1502
return eep->modal_header_5g.xpa_bias_lvl;
1503
}
1504
}
1505
1506
HAL_BOOL ar9300_xpa_bias_level_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
1507
{
1508
/*
1509
* In ar9330 emu, we can't access radio registers,
1510
* merlin is used for radio part.
1511
*/
1512
int bias;
1513
bias = ar9300_xpa_bias_level_get(ah, is_2ghz);
1514
1515
if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah)) {
1516
OS_REG_RMW_FIELD(ah,
1517
AR_HORNET_CH0_TOP2, AR_HORNET_CH0_TOP2_XPABIASLVL, bias);
1518
} else if (AR_SREV_SCORPION(ah)) {
1519
OS_REG_RMW_FIELD(ah,
1520
AR_SCORPION_CH0_TOP, AR_SCORPION_CH0_TOP_XPABIASLVL, bias);
1521
} else if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
1522
OS_REG_RMW_FIELD(ah,
1523
AR_PHY_65NM_CH0_TOP_JUPITER, AR_PHY_65NM_CH0_TOP_XPABIASLVL, bias);
1524
} else {
1525
OS_REG_RMW_FIELD(ah,
1526
AR_PHY_65NM_CH0_TOP, AR_PHY_65NM_CH0_TOP_XPABIASLVL, bias);
1527
OS_REG_RMW_FIELD(ah,
1528
AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_XPABIASLVL_MSB,
1529
bias >> 2);
1530
OS_REG_RMW_FIELD(ah,
1531
AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_XPASHORT2GND, 1);
1532
}
1533
return 0;
1534
}
1535
1536
u_int32_t ar9300_ant_ctrl_common_get(struct ath_hal *ah, HAL_BOOL is_2ghz)
1537
{
1538
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1539
if (is_2ghz) {
1540
return eep->modal_header_2g.ant_ctrl_common;
1541
} else {
1542
return eep->modal_header_5g.ant_ctrl_common;
1543
}
1544
}
1545
static u_int16_t
1546
ar9300_switch_com_spdt_get(struct ath_hal *ah, HAL_BOOL is_2ghz)
1547
{
1548
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1549
if (is_2ghz) {
1550
return eep->modal_header_2g.switchcomspdt;
1551
} else {
1552
return eep->modal_header_5g.switchcomspdt;
1553
}
1554
}
1555
u_int32_t ar9300_ant_ctrl_common2_get(struct ath_hal *ah, HAL_BOOL is_2ghz)
1556
{
1557
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1558
if (is_2ghz) {
1559
return eep->modal_header_2g.ant_ctrl_common2;
1560
} else {
1561
return eep->modal_header_5g.ant_ctrl_common2;
1562
}
1563
}
1564
1565
u_int16_t ar9300_ant_ctrl_chain_get(struct ath_hal *ah, int chain,
1566
HAL_BOOL is_2ghz)
1567
{
1568
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1569
if (chain >= 0 && chain < OSPREY_MAX_CHAINS) {
1570
if (is_2ghz) {
1571
return eep->modal_header_2g.ant_ctrl_chain[chain];
1572
} else {
1573
return eep->modal_header_5g.ant_ctrl_chain[chain];
1574
}
1575
}
1576
return 0;
1577
}
1578
1579
/*
1580
* Select the usage of antenna via the RF switch.
1581
* Default values are loaded from eeprom.
1582
*/
1583
HAL_BOOL ar9300_ant_swcom_sel(struct ath_hal *ah, u_int8_t ops,
1584
u_int32_t *common_tbl1, u_int32_t *common_tbl2)
1585
{
1586
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1587
struct ath_hal_private *ap = AH_PRIVATE(ah);
1588
const struct ieee80211_channel *curchan = ap->ah_curchan;
1589
enum {
1590
ANT_SELECT_OPS_GET,
1591
ANT_SELECT_OPS_SET,
1592
};
1593
1594
if (AR_SREV_JUPITER(ah) || AR_SREV_SCORPION(ah))
1595
return AH_FALSE;
1596
1597
if (!curchan)
1598
return AH_FALSE;
1599
1600
#define AR_SWITCH_TABLE_COM_ALL (0xffff)
1601
#define AR_SWITCH_TABLE_COM_ALL_S (0)
1602
#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
1603
#define AR_SWITCH_TABLE_COM2_ALL_S (0)
1604
switch (ops) {
1605
case ANT_SELECT_OPS_GET:
1606
*common_tbl1 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM,
1607
AR_SWITCH_TABLE_COM_ALL);
1608
*common_tbl2 = OS_REG_READ_FIELD(ah, AR_PHY_SWITCH_COM_2,
1609
AR_SWITCH_TABLE_COM2_ALL);
1610
break;
1611
case ANT_SELECT_OPS_SET:
1612
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
1613
AR_SWITCH_TABLE_COM_ALL, *common_tbl1);
1614
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2,
1615
AR_SWITCH_TABLE_COM2_ALL, *common_tbl2);
1616
1617
/* write back to eeprom */
1618
if (IEEE80211_IS_CHAN_2GHZ(curchan)) {
1619
eep->modal_header_2g.ant_ctrl_common = *common_tbl1;
1620
eep->modal_header_2g.ant_ctrl_common2 = *common_tbl2;
1621
} else {
1622
eep->modal_header_5g.ant_ctrl_common = *common_tbl1;
1623
eep->modal_header_5g.ant_ctrl_common2 = *common_tbl2;
1624
}
1625
1626
break;
1627
default:
1628
break;
1629
}
1630
1631
return AH_TRUE;
1632
}
1633
1634
HAL_BOOL ar9300_ant_ctrl_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
1635
{
1636
u_int32_t value;
1637
struct ath_hal_9300 *ahp = AH9300(ah);
1638
u_int32_t regval;
1639
struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
1640
#if ATH_ANT_DIV_COMB
1641
HAL_CAPABILITIES *pcap = &ahpriv->ah_caps;
1642
#endif /* ATH_ANT_DIV_COMB */
1643
u_int32_t xlan_gpio_cfg;
1644
u_int8_t i;
1645
1646
HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: use_bt_ant_enable=%d\n",
1647
__func__, ahp->ah_lna_div_use_bt_ant_enable);
1648
1649
/* XXX TODO: only if rx_gain_idx == 0 */
1650
if (AR_SREV_POSEIDON(ah)) {
1651
xlan_gpio_cfg = ah->ah_config.ath_hal_ext_lna_ctl_gpio;
1652
if (xlan_gpio_cfg) {
1653
for (i = 0; i < 32; i++) {
1654
if (xlan_gpio_cfg & (1 << i)) {
1655
ath_hal_gpioCfgOutput(ah, i,
1656
HAL_GPIO_OUTPUT_MUX_PCIE_ATTENTION_LED);
1657
}
1658
}
1659
}
1660
}
1661
#define AR_SWITCH_TABLE_COM_ALL (0xffff)
1662
#define AR_SWITCH_TABLE_COM_ALL_S (0)
1663
#define AR_SWITCH_TABLE_COM_JUPITER_ALL (0xffffff)
1664
#define AR_SWITCH_TABLE_COM_JUPITER_ALL_S (0)
1665
#define AR_SWITCH_TABLE_COM_SCORPION_ALL (0xffffff)
1666
#define AR_SWITCH_TABLE_COM_SCORPION_ALL_S (0)
1667
#define AR_SWITCH_TABLE_COM_HONEYBEE_ALL (0xffffff)
1668
#define AR_SWITCH_TABLE_COM_HONEYBEE_ALL_S (0)
1669
#define AR_SWITCH_TABLE_COM_SPDT (0x00f00000)
1670
value = ar9300_ant_ctrl_common_get(ah, is_2ghz);
1671
if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
1672
if (AR_SREV_JUPITER_10(ah)) {
1673
/* Force SPDT setting for Jupiter 1.0 chips. */
1674
value &= ~AR_SWITCH_TABLE_COM_SPDT;
1675
value |= 0x00100000;
1676
}
1677
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
1678
AR_SWITCH_TABLE_COM_JUPITER_ALL, value);
1679
}
1680
else if (AR_SREV_SCORPION(ah)) {
1681
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
1682
AR_SWITCH_TABLE_COM_SCORPION_ALL, value);
1683
}
1684
else if (AR_SREV_HONEYBEE(ah)) {
1685
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
1686
AR_SWITCH_TABLE_COM_HONEYBEE_ALL, value);
1687
}
1688
else {
1689
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
1690
AR_SWITCH_TABLE_COM_ALL, value);
1691
}
1692
/*
1693
* Jupiter2.0 defines new switch table for BT/WLAN,
1694
* here's new field name in WB222.ref for both 2G and 5G.
1695
* Register: [GLB_CONTROL] GLB_CONTROL (@0x20044)
1696
* 15:12 R/W SWITCH_TABLE_COM_SPDT_WLAN_RX SWITCH_TABLE_COM_SPDT_WLAN_RX
1697
* 11:8 R/W SWITCH_TABLE_COM_SPDT_WLAN_TX SWITCH_TABLE_COM_SPDT_WLAN_TX
1698
* 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE SWITCH_TABLE_COM_SPDT_WLAN_IDLE
1699
*/
1700
#define AR_SWITCH_TABLE_COM_SPDT_ALL (0x0000fff0)
1701
#define AR_SWITCH_TABLE_COM_SPDT_ALL_S (4)
1702
if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
1703
value = ar9300_switch_com_spdt_get(ah, is_2ghz);
1704
OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL,
1705
AR_SWITCH_TABLE_COM_SPDT_ALL, value);
1706
1707
OS_REG_SET_BIT(ah, AR_GLB_CONTROL,
1708
AR_BTCOEX_CTRL_SPDT_ENABLE);
1709
//OS_REG_SET_BIT(ah, AR_GLB_CONTROL,
1710
// AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
1711
}
1712
1713
#define AR_SWITCH_TABLE_COM2_ALL (0xffffff)
1714
#define AR_SWITCH_TABLE_COM2_ALL_S (0)
1715
value = ar9300_ant_ctrl_common2_get(ah, is_2ghz);
1716
#if ATH_ANT_DIV_COMB
1717
if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
1718
value &= ~AR_SWITCH_TABLE_COM2_ALL;
1719
value |= ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable;
1720
HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__, value)
1721
}
1722
#endif /* ATH_ANT_DIV_COMB */
1723
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
1724
1725
#define AR_SWITCH_TABLE_ALL (0xfff)
1726
#define AR_SWITCH_TABLE_ALL_S (0)
1727
value = ar9300_ant_ctrl_chain_get(ah, 0, is_2ghz);
1728
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value);
1729
1730
if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah) && !AR_SREV_APHRODITE(ah)) {
1731
value = ar9300_ant_ctrl_chain_get(ah, 1, is_2ghz);
1732
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value);
1733
1734
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah)) {
1735
value = ar9300_ant_ctrl_chain_get(ah, 2, is_2ghz);
1736
OS_REG_RMW_FIELD(ah,
1737
AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value);
1738
}
1739
}
1740
if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
1741
value = ar9300_eeprom_get(ahp, EEP_ANTDIV_control);
1742
/* main_lnaconf, alt_lnaconf, main_tb, alt_tb */
1743
regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
1744
regval &= (~ANT_DIV_CONTROL_ALL); /* clear bit 25~30 */
1745
regval |= (value & 0x3f) << ANT_DIV_CONTROL_ALL_S;
1746
/* enable_lnadiv */
1747
regval &= (~MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__MASK);
1748
regval |= ((value >> 6) & 0x1) <<
1749
MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__SHIFT;
1750
#if ATH_ANT_DIV_COMB
1751
if ( AR_SREV_POSEIDON(ah) && (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
1752
regval |= ANT_DIV_ENABLE;
1753
}
1754
if (AR_SREV_APHRODITE(ah)) {
1755
if (ahp->ah_lna_div_use_bt_ant_enable) {
1756
regval |= (1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT);
1757
1758
OS_REG_SET_BIT(ah, AR_PHY_RESTART,
1759
RESTART__ENABLE_ANT_FAST_DIV_M2FLAG__MASK);
1760
1761
/* Force WLAN LNA diversity ON */
1762
OS_REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV,
1763
AR_BTCOEX_WL_LNADIV_FORCE_ON);
1764
} else {
1765
regval &= ~(1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_DIV_LNADIV__SHIFT);
1766
regval &= ~(1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT);
1767
1768
OS_REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
1769
(1 << MULTICHAIN_GAIN_CTRL__ENABLE_ANT_SW_RX_PROT__SHIFT));
1770
1771
/* Force WLAN LNA diversity OFF */
1772
OS_REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV,
1773
AR_BTCOEX_WL_LNADIV_FORCE_ON);
1774
}
1775
}
1776
1777
#endif /* ATH_ANT_DIV_COMB */
1778
OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
1779
1780
/* enable fast_div */
1781
regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
1782
regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK);
1783
regval |= ((value >> 7) & 0x1) <<
1784
BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__SHIFT;
1785
#if ATH_ANT_DIV_COMB
1786
if ((AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah))
1787
&& (ahp->ah_lna_div_use_bt_ant_enable == TRUE) ) {
1788
regval |= FAST_DIV_ENABLE;
1789
}
1790
#endif /* ATH_ANT_DIV_COMB */
1791
OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
1792
}
1793
1794
#if ATH_ANT_DIV_COMB
1795
if (AR_SREV_HORNET(ah) || AR_SREV_POSEIDON_11_OR_LATER(ah)) {
1796
if (pcap->halAntDivCombSupport) {
1797
/* If support DivComb, set MAIN to LNA1, ALT to LNA2 at beginning */
1798
regval = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
1799
/* clear bit 25~30 main_lnaconf, alt_lnaconf, main_tb, alt_tb */
1800
regval &= (~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK |
1801
MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK |
1802
MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK |
1803
MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK));
1804
regval |= (HAL_ANT_DIV_COMB_LNA1 <<
1805
MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT);
1806
regval |= (HAL_ANT_DIV_COMB_LNA2 <<
1807
MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT);
1808
OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
1809
}
1810
1811
}
1812
#endif /* ATH_ANT_DIV_COMB */
1813
if (AR_SREV_POSEIDON(ah) && ( ahp->ah_diversity_control == HAL_ANT_FIXED_A
1814
|| ahp->ah_diversity_control == HAL_ANT_FIXED_B))
1815
{
1816
u_int32_t reg_val = OS_REG_READ(ah, AR_PHY_MC_GAIN_CTRL);
1817
reg_val &= ~(MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__MASK |
1818
MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__MASK |
1819
MULTICHAIN_GAIN_CTRL__ANT_FAST_DIV_BIAS__MASK |
1820
MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_GAINTB__MASK |
1821
MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_GAINTB__MASK );
1822
1823
switch (ahp->ah_diversity_control) {
1824
case HAL_ANT_FIXED_A:
1825
/* Enable first antenna only */
1826
reg_val |= (HAL_ANT_DIV_COMB_LNA1 <<
1827
MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT);
1828
reg_val |= (HAL_ANT_DIV_COMB_LNA2 <<
1829
MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT);
1830
/* main/alt gain table and Fast Div Bias all set to 0 */
1831
OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, reg_val);
1832
regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
1833
regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK);
1834
OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
1835
break;
1836
case HAL_ANT_FIXED_B:
1837
/* Enable second antenna only, after checking capability */
1838
reg_val |= (HAL_ANT_DIV_COMB_LNA2 <<
1839
MULTICHAIN_GAIN_CTRL__ANT_DIV_MAIN_LNACONF__SHIFT);
1840
reg_val |= (HAL_ANT_DIV_COMB_LNA1 <<
1841
MULTICHAIN_GAIN_CTRL__ANT_DIV_ALT_LNACONF__SHIFT);
1842
/* main/alt gain table and Fast Div all set to 0 */
1843
OS_REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, reg_val);
1844
regval = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
1845
regval &= (~BBB_SIG_DETECT__ENABLE_ANT_FAST_DIV__MASK);
1846
OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
1847
/* For WB225, need to swith ANT2 from BT to Wifi
1848
* This will not affect HB125 LNA diversity feature.
1849
*/
1850
HALDEBUG(ah, HAL_DEBUG_RESET, "%s: com2=0x%08x\n", __func__,
1851
ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable)
1852
OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL,
1853
ah->ah_config.ath_hal_ant_ctrl_comm2g_switch_enable);
1854
break;
1855
default:
1856
break;
1857
}
1858
}
1859
return 0;
1860
}
1861
1862
static u_int16_t
1863
ar9300_attenuation_chain_get(struct ath_hal *ah, int chain, u_int16_t channel)
1864
{
1865
int32_t f[3], t[3];
1866
u_int16_t value;
1867
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1868
if (chain >= 0 && chain < OSPREY_MAX_CHAINS) {
1869
if (channel < 4000) {
1870
return eep->modal_header_2g.xatten1_db[chain];
1871
} else {
1872
if (eep->base_ext2.xatten1_db_low[chain] != 0) {
1873
t[0] = eep->base_ext2.xatten1_db_low[chain];
1874
f[0] = 5180;
1875
t[1] = eep->modal_header_5g.xatten1_db[chain];
1876
f[1] = 5500;
1877
t[2] = eep->base_ext2.xatten1_db_high[chain];
1878
f[2] = 5785;
1879
value = interpolate(channel, f, t, 3);
1880
return value;
1881
} else {
1882
return eep->modal_header_5g.xatten1_db[chain];
1883
}
1884
}
1885
}
1886
return 0;
1887
}
1888
1889
static u_int16_t
1890
ar9300_attenuation_margin_chain_get(struct ath_hal *ah, int chain,
1891
u_int16_t channel)
1892
{
1893
int32_t f[3], t[3];
1894
u_int16_t value;
1895
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
1896
if (chain >= 0 && chain < OSPREY_MAX_CHAINS) {
1897
if (channel < 4000) {
1898
return eep->modal_header_2g.xatten1_margin[chain];
1899
} else {
1900
if (eep->base_ext2.xatten1_margin_low[chain] != 0) {
1901
t[0] = eep->base_ext2.xatten1_margin_low[chain];
1902
f[0] = 5180;
1903
t[1] = eep->modal_header_5g.xatten1_margin[chain];
1904
f[1] = 5500;
1905
t[2] = eep->base_ext2.xatten1_margin_high[chain];
1906
f[2] = 5785;
1907
value = interpolate(channel, f, t, 3);
1908
return value;
1909
} else {
1910
return eep->modal_header_5g.xatten1_margin[chain];
1911
}
1912
}
1913
}
1914
return 0;
1915
}
1916
1917
#if 0
1918
HAL_BOOL ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel)
1919
{
1920
u_int32_t value;
1921
// struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
1922
1923
/* Test value. if 0 then attenuation is unused. Don't load anything. */
1924
value = ar9300_attenuation_chain_get(ah, 0, channel);
1925
OS_REG_RMW_FIELD(ah,
1926
AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
1927
value = ar9300_attenuation_margin_chain_get(ah, 0, channel);
1928
if (ar9300_rx_gain_index_get(ah) == 0
1929
&& ah->ah_config.ath_hal_ext_atten_margin_cfg)
1930
{
1931
value = 5;
1932
}
1933
OS_REG_RMW_FIELD(ah,
1934
AR_PHY_EXT_ATTEN_CTL_0, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value);
1935
1936
if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
1937
value = ar9300_attenuation_chain_get(ah, 1, channel);
1938
OS_REG_RMW_FIELD(ah,
1939
AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
1940
value = ar9300_attenuation_margin_chain_get(ah, 1, channel);
1941
OS_REG_RMW_FIELD(ah,
1942
AR_PHY_EXT_ATTEN_CTL_1, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
1943
value);
1944
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah)&& !AR_SREV_HONEYBEE(ah) ) {
1945
value = ar9300_attenuation_chain_get(ah, 2, channel);
1946
OS_REG_RMW_FIELD(ah,
1947
AR_PHY_EXT_ATTEN_CTL_2, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
1948
value = ar9300_attenuation_margin_chain_get(ah, 2, channel);
1949
OS_REG_RMW_FIELD(ah,
1950
AR_PHY_EXT_ATTEN_CTL_2, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
1951
value);
1952
}
1953
}
1954
return 0;
1955
}
1956
#endif
1957
HAL_BOOL
1958
ar9300_attenuation_apply(struct ath_hal *ah, u_int16_t channel)
1959
{
1960
int i;
1961
uint32_t value;
1962
uint32_t ext_atten_reg[3] = {
1963
AR_PHY_EXT_ATTEN_CTL_0,
1964
AR_PHY_EXT_ATTEN_CTL_1,
1965
AR_PHY_EXT_ATTEN_CTL_2
1966
};
1967
1968
/*
1969
* If it's an AR9462 and we're receiving on the second
1970
* chain only, set the chain 0 details from chain 1
1971
* calibration.
1972
*
1973
* This is from ath9k.
1974
*/
1975
if (AR_SREV_JUPITER(ah) && (AH9300(ah)->ah_rx_chainmask == 0x2)) {
1976
value = ar9300_attenuation_chain_get(ah, 1, channel);
1977
OS_REG_RMW_FIELD(ah, ext_atten_reg[0],
1978
AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
1979
value = ar9300_attenuation_margin_chain_get(ah, 1, channel);
1980
OS_REG_RMW_FIELD(ah, ext_atten_reg[0],
1981
AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value);
1982
}
1983
1984
/*
1985
* Now, loop over the configured transmit chains and
1986
* load in the attenuation/margin settings as appropriate.
1987
*/
1988
for (i = 0; i < 3; i++) {
1989
if ((AH9300(ah)->ah_tx_chainmask & (1 << i)) == 0)
1990
continue;
1991
1992
value = ar9300_attenuation_chain_get(ah, i, channel);
1993
OS_REG_RMW_FIELD(ah, ext_atten_reg[i],
1994
AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB,
1995
value);
1996
1997
if (AR_SREV_POSEIDON(ah) &&
1998
(ar9300_rx_gain_index_get(ah) == 0) &&
1999
ah->ah_config.ath_hal_ext_atten_margin_cfg) {
2000
value = 5;
2001
} else {
2002
value = ar9300_attenuation_margin_chain_get(ah, 0,
2003
channel);
2004
}
2005
2006
/*
2007
* I'm not sure why it's loading in this setting into
2008
* the chain 0 margin regardless of the current chain.
2009
*/
2010
if (ah->ah_config.ath_hal_min_gainidx)
2011
OS_REG_RMW_FIELD(ah,
2012
AR_PHY_EXT_ATTEN_CTL_0,
2013
AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
2014
value);
2015
2016
OS_REG_RMW_FIELD(ah,
2017
ext_atten_reg[i],
2018
AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
2019
value);
2020
}
2021
2022
return (0);
2023
}
2024
2025
2026
static u_int16_t ar9300_quick_drop_get(struct ath_hal *ah,
2027
int chain, u_int16_t channel)
2028
{
2029
int32_t f[3], t[3];
2030
u_int16_t value;
2031
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
2032
2033
if (channel < 4000) {
2034
return eep->modal_header_2g.quick_drop;
2035
} else {
2036
t[0] = eep->base_ext1.quick_drop_low;
2037
f[0] = 5180;
2038
t[1] = eep->modal_header_5g.quick_drop;
2039
f[1] = 5500;
2040
t[2] = eep->base_ext1.quick_drop_high;
2041
f[2] = 5785;
2042
value = interpolate(channel, f, t, 3);
2043
return value;
2044
}
2045
}
2046
2047
2048
static HAL_BOOL ar9300_quick_drop_apply(struct ath_hal *ah, u_int16_t channel)
2049
{
2050
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
2051
u_int32_t value;
2052
//
2053
// Test value. if 0 then quickDrop is unused. Don't load anything.
2054
//
2055
if (eep->base_eep_header.misc_configuration & 0x10)
2056
{
2057
if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah))
2058
{
2059
value = ar9300_quick_drop_get(ah, 0, channel);
2060
OS_REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, value);
2061
}
2062
}
2063
return 0;
2064
}
2065
2066
static u_int16_t ar9300_tx_end_to_xpa_off_get(struct ath_hal *ah, u_int16_t channel)
2067
{
2068
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
2069
2070
if (channel < 4000) {
2071
return eep->modal_header_2g.tx_end_to_xpa_off;
2072
} else {
2073
return eep->modal_header_5g.tx_end_to_xpa_off;
2074
}
2075
}
2076
2077
static HAL_BOOL ar9300_tx_end_to_xpab_off_apply(struct ath_hal *ah, u_int16_t channel)
2078
{
2079
u_int32_t value;
2080
2081
value = ar9300_tx_end_to_xpa_off_get(ah, channel);
2082
/* Apply to both xpaa and xpab */
2083
if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah))
2084
{
2085
OS_REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
2086
AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF, value);
2087
OS_REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
2088
AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF, value);
2089
}
2090
return 0;
2091
}
2092
2093
static int
2094
ar9300_eeprom_cal_pier_get(struct ath_hal *ah, int mode, int ipier, int ichain,
2095
int *pfrequency, int *pcorrection, int *ptemperature, int *pvoltage)
2096
{
2097
u_int8_t *p_cal_pier;
2098
OSP_CAL_DATA_PER_FREQ_OP_LOOP *p_cal_pier_struct;
2099
int is_2ghz;
2100
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
2101
2102
if (ichain >= OSPREY_MAX_CHAINS) {
2103
HALDEBUG(ah, HAL_DEBUG_EEPROM,
2104
"%s: Invalid chain index, must be less than %d\n",
2105
__func__, OSPREY_MAX_CHAINS);
2106
return -1;
2107
}
2108
2109
if (mode) {/* 5GHz */
2110
if (ipier >= OSPREY_NUM_5G_CAL_PIERS){
2111
HALDEBUG(ah, HAL_DEBUG_EEPROM,
2112
"%s: Invalid 5GHz cal pier index, must be less than %d\n",
2113
__func__, OSPREY_NUM_5G_CAL_PIERS);
2114
return -1;
2115
}
2116
p_cal_pier = &(eep->cal_freq_pier_5g[ipier]);
2117
p_cal_pier_struct = &(eep->cal_pier_data_5g[ichain][ipier]);
2118
is_2ghz = 0;
2119
} else {
2120
if (ipier >= OSPREY_NUM_2G_CAL_PIERS){
2121
HALDEBUG(ah, HAL_DEBUG_EEPROM,
2122
"%s: Invalid 2GHz cal pier index, must be less than %d\n",
2123
__func__, OSPREY_NUM_2G_CAL_PIERS);
2124
return -1;
2125
}
2126
2127
p_cal_pier = &(eep->cal_freq_pier_2g[ipier]);
2128
p_cal_pier_struct = &(eep->cal_pier_data_2g[ichain][ipier]);
2129
is_2ghz = 1;
2130
}
2131
*pfrequency = FBIN2FREQ(*p_cal_pier, is_2ghz);
2132
*pcorrection = p_cal_pier_struct->ref_power;
2133
*ptemperature = p_cal_pier_struct->temp_meas;
2134
*pvoltage = p_cal_pier_struct->volt_meas;
2135
return 0;
2136
}
2137
2138
/*
2139
* Apply the recorded correction values.
2140
*/
2141
static int
2142
ar9300_calibration_apply(struct ath_hal *ah, int frequency)
2143
{
2144
struct ath_hal_9300 *ahp = AH9300(ah);
2145
2146
int ichain, ipier, npier;
2147
int mode;
2148
int fdiff;
2149
int pfrequency, pcorrection, ptemperature, pvoltage;
2150
int bf, factor, plus;
2151
2152
int lfrequency[AR9300_MAX_CHAINS];
2153
int hfrequency[AR9300_MAX_CHAINS];
2154
2155
int lcorrection[AR9300_MAX_CHAINS];
2156
int hcorrection[AR9300_MAX_CHAINS];
2157
int correction[AR9300_MAX_CHAINS];
2158
2159
int ltemperature[AR9300_MAX_CHAINS];
2160
int htemperature[AR9300_MAX_CHAINS];
2161
int temperature[AR9300_MAX_CHAINS];
2162
2163
int lvoltage[AR9300_MAX_CHAINS];
2164
int hvoltage[AR9300_MAX_CHAINS];
2165
int voltage[AR9300_MAX_CHAINS];
2166
2167
mode = (frequency >= 4000);
2168
npier = (mode) ? OSPREY_NUM_5G_CAL_PIERS : OSPREY_NUM_2G_CAL_PIERS;
2169
2170
for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
2171
lfrequency[ichain] = 0;
2172
hfrequency[ichain] = 100000;
2173
}
2174
/*
2175
* identify best lower and higher frequency calibration measurement
2176
*/
2177
for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
2178
for (ipier = 0; ipier < npier; ipier++) {
2179
if (ar9300_eeprom_cal_pier_get(
2180
ah, mode, ipier, ichain,
2181
&pfrequency, &pcorrection, &ptemperature, &pvoltage) == 0)
2182
{
2183
fdiff = frequency - pfrequency;
2184
/*
2185
* this measurement is higher than our desired frequency
2186
*/
2187
if (fdiff <= 0) {
2188
if (hfrequency[ichain] <= 0 ||
2189
hfrequency[ichain] >= 100000 ||
2190
fdiff > (frequency - hfrequency[ichain]))
2191
{
2192
/*
2193
* new best higher frequency measurement
2194
*/
2195
hfrequency[ichain] = pfrequency;
2196
hcorrection[ichain] = pcorrection;
2197
htemperature[ichain] = ptemperature;
2198
hvoltage[ichain] = pvoltage;
2199
}
2200
}
2201
if (fdiff >= 0) {
2202
if (lfrequency[ichain] <= 0 ||
2203
fdiff < (frequency - lfrequency[ichain]))
2204
{
2205
/*
2206
* new best lower frequency measurement
2207
*/
2208
lfrequency[ichain] = pfrequency;
2209
lcorrection[ichain] = pcorrection;
2210
ltemperature[ichain] = ptemperature;
2211
lvoltage[ichain] = pvoltage;
2212
}
2213
}
2214
}
2215
}
2216
}
2217
/* interpolate */
2218
for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) {
2219
HALDEBUG(ah, HAL_DEBUG_EEPROM,
2220
"%s: ch=%d f=%d low=%d %d h=%d %d\n",
2221
__func__, ichain, frequency,
2222
lfrequency[ichain], lcorrection[ichain],
2223
hfrequency[ichain], hcorrection[ichain]);
2224
/*
2225
* they're the same, so just pick one
2226
*/
2227
if (hfrequency[ichain] == lfrequency[ichain]) {
2228
correction[ichain] = lcorrection[ichain];
2229
voltage[ichain] = lvoltage[ichain];
2230
temperature[ichain] = ltemperature[ichain];
2231
} else if (frequency - lfrequency[ichain] < 1000) {
2232
/* the low frequency is good */
2233
if (hfrequency[ichain] - frequency < 1000) {
2234
/*
2235
* The high frequency is good too -
2236
* interpolate with round off.
2237
*/
2238
int mult, div, diff;
2239
mult = frequency - lfrequency[ichain];
2240
div = hfrequency[ichain] - lfrequency[ichain];
2241
2242
diff = hcorrection[ichain] - lcorrection[ichain];
2243
bf = 2 * diff * mult / div;
2244
plus = (bf % 2);
2245
factor = bf / 2;
2246
correction[ichain] = lcorrection[ichain] + factor + plus;
2247
2248
diff = htemperature[ichain] - ltemperature[ichain];
2249
bf = 2 * diff * mult / div;
2250
plus = (bf % 2);
2251
factor = bf / 2;
2252
temperature[ichain] = ltemperature[ichain] + factor + plus;
2253
2254
diff = hvoltage[ichain] - lvoltage[ichain];
2255
bf = 2 * diff * mult / div;
2256
plus = (bf % 2);
2257
factor = bf / 2;
2258
voltage[ichain] = lvoltage[ichain] + factor + plus;
2259
} else {
2260
/* only low is good, use it */
2261
correction[ichain] = lcorrection[ichain];
2262
temperature[ichain] = ltemperature[ichain];
2263
voltage[ichain] = lvoltage[ichain];
2264
}
2265
} else if (hfrequency[ichain] - frequency < 1000) {
2266
/* only high is good, use it */
2267
correction[ichain] = hcorrection[ichain];
2268
temperature[ichain] = htemperature[ichain];
2269
voltage[ichain] = hvoltage[ichain];
2270
} else {
2271
/* nothing is good, presume 0???? */
2272
correction[ichain] = 0;
2273
temperature[ichain] = 0;
2274
voltage[ichain] = 0;
2275
}
2276
}
2277
2278
/* GreenTx isn't currently supported */
2279
/* GreenTx */
2280
if (ah->ah_config.ath_hal_sta_update_tx_pwr_enable) {
2281
if (AR_SREV_POSEIDON(ah)) {
2282
/* Get calibrated OLPC gain delta value for GreenTx */
2283
ahp->ah_db2[POSEIDON_STORED_REG_G2_OLPC_OFFSET] =
2284
(u_int32_t) correction[0];
2285
}
2286
}
2287
2288
ar9300_power_control_override(
2289
ah, frequency, correction, voltage, temperature);
2290
HALDEBUG(ah, HAL_DEBUG_EEPROM,
2291
"%s: for frequency=%d, calibration correction = %d %d %d\n",
2292
__func__, frequency, correction[0], correction[1], correction[2]);
2293
2294
return 0;
2295
}
2296
2297
int
2298
ar9300_power_control_override(struct ath_hal *ah, int frequency,
2299
int *correction, int *voltage, int *temperature)
2300
{
2301
int temp_slope = 0;
2302
int temp_slope_1 = 0;
2303
int temp_slope_2 = 0;
2304
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
2305
int32_t f[8], t[8],t1[3], t2[3];
2306
int i;
2307
2308
OS_REG_RMW(ah, AR_PHY_TPC_11_B0,
2309
(correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
2310
AR_PHY_TPC_OLPC_GAIN_DELTA);
2311
if (!AR_SREV_POSEIDON(ah)) {
2312
OS_REG_RMW(ah, AR_PHY_TPC_11_B1,
2313
(correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
2314
AR_PHY_TPC_OLPC_GAIN_DELTA);
2315
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) {
2316
OS_REG_RMW(ah, AR_PHY_TPC_11_B2,
2317
(correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
2318
AR_PHY_TPC_OLPC_GAIN_DELTA);
2319
}
2320
}
2321
/*
2322
* enable open loop power control on chip
2323
*/
2324
OS_REG_RMW(ah, AR_PHY_TPC_6_B0,
2325
(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE);
2326
if (!AR_SREV_POSEIDON(ah)) {
2327
OS_REG_RMW(ah, AR_PHY_TPC_6_B1,
2328
(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), AR_PHY_TPC_6_ERROR_EST_MODE);
2329
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) {
2330
OS_REG_RMW(ah, AR_PHY_TPC_6_B2,
2331
(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S),
2332
AR_PHY_TPC_6_ERROR_EST_MODE);
2333
}
2334
}
2335
2336
/*
2337
* Enable temperature compensation
2338
* Need to use register names
2339
*/
2340
if (frequency < 4000) {
2341
temp_slope = eep->modal_header_2g.temp_slope;
2342
} else {
2343
if ((eep->base_eep_header.misc_configuration & 0x20) != 0)
2344
{
2345
for(i=0;i<8;i++)
2346
{
2347
t[i]=eep->base_ext1.tempslopextension[i];
2348
f[i]=FBIN2FREQ(eep->cal_freq_pier_5g[i], 0);
2349
}
2350
temp_slope=interpolate(frequency,f,t,8);
2351
}
2352
else
2353
{
2354
if(!AR_SREV_SCORPION(ah)) {
2355
if (eep->base_ext2.temp_slope_low != 0) {
2356
t[0] = eep->base_ext2.temp_slope_low;
2357
f[0] = 5180;
2358
t[1] = eep->modal_header_5g.temp_slope;
2359
f[1] = 5500;
2360
t[2] = eep->base_ext2.temp_slope_high;
2361
f[2] = 5785;
2362
temp_slope = interpolate(frequency, f, t, 3);
2363
} else {
2364
temp_slope = eep->modal_header_5g.temp_slope;
2365
}
2366
} else {
2367
/*
2368
* Scorpion has individual chain tempslope values
2369
*/
2370
t[0] = eep->base_ext1.tempslopextension[2];
2371
t1[0]= eep->base_ext1.tempslopextension[3];
2372
t2[0]= eep->base_ext1.tempslopextension[4];
2373
f[0] = 5180;
2374
t[1] = eep->modal_header_5g.temp_slope;
2375
t1[1]= eep->base_ext1.tempslopextension[0];
2376
t2[1]= eep->base_ext1.tempslopextension[1];
2377
f[1] = 5500;
2378
t[2] = eep->base_ext1.tempslopextension[5];
2379
t1[2]= eep->base_ext1.tempslopextension[6];
2380
t2[2]= eep->base_ext1.tempslopextension[7];
2381
f[2] = 5785;
2382
temp_slope = interpolate(frequency, f, t, 3);
2383
temp_slope_1=interpolate(frequency, f, t1,3);
2384
temp_slope_2=interpolate(frequency, f, t2,3);
2385
}
2386
}
2387
}
2388
2389
if (!AR_SREV_SCORPION(ah) && !AR_SREV_HONEYBEE(ah)) {
2390
OS_REG_RMW_FIELD(ah,
2391
AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, temp_slope);
2392
} else {
2393
/*Scorpion and Honeybee has tempSlope register for each chain*/
2394
/*Check whether temp_compensation feature is enabled or not*/
2395
if (eep->base_eep_header.feature_enable & 0x1){
2396
if(frequency < 4000) {
2397
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) {
2398
OS_REG_RMW_FIELD(ah,
2399
AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM,
2400
eep->base_ext2.temp_slope_low);
2401
}
2402
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) {
2403
OS_REG_RMW_FIELD(ah,
2404
AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM,
2405
temp_slope);
2406
}
2407
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) {
2408
OS_REG_RMW_FIELD(ah,
2409
AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM,
2410
eep->base_ext2.temp_slope_high);
2411
}
2412
} else {
2413
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) {
2414
OS_REG_RMW_FIELD(ah,
2415
AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM,
2416
temp_slope);
2417
}
2418
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) {
2419
OS_REG_RMW_FIELD(ah,
2420
AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM,
2421
temp_slope_1);
2422
}
2423
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) {
2424
OS_REG_RMW_FIELD(ah,
2425
AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM,
2426
temp_slope_2);
2427
}
2428
}
2429
}else {
2430
/* If temp compensation is not enabled, set all registers to 0*/
2431
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x1) {
2432
OS_REG_RMW_FIELD(ah,
2433
AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, 0);
2434
}
2435
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x2) {
2436
OS_REG_RMW_FIELD(ah,
2437
AR_SCORPION_PHY_TPC_19_B1, AR_PHY_TPC_19_ALPHA_THERM, 0);
2438
}
2439
if (((eep->base_eep_header.txrx_mask & 0xf0) >> 4) & 0x4) {
2440
OS_REG_RMW_FIELD(ah,
2441
AR_SCORPION_PHY_TPC_19_B2, AR_PHY_TPC_19_ALPHA_THERM, 0);
2442
}
2443
}
2444
}
2445
OS_REG_RMW_FIELD(ah,
2446
AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, temperature[0]);
2447
2448
return 0;
2449
}
2450
2451
/**************************************************************
2452
* ar9300_eep_def_get_max_edge_power
2453
*
2454
* Find the maximum conformance test limit for the given channel and CTL info
2455
*/
2456
static inline u_int16_t
2457
ar9300_eep_def_get_max_edge_power(ar9300_eeprom_t *p_eep_data, u_int16_t freq,
2458
int idx, HAL_BOOL is_2ghz)
2459
{
2460
u_int16_t twice_max_edge_power = AR9300_MAX_RATE_POWER;
2461
u_int8_t *ctl_freqbin = is_2ghz ?
2462
&p_eep_data->ctl_freqbin_2G[idx][0] :
2463
&p_eep_data->ctl_freqbin_5G[idx][0];
2464
u_int16_t num_edges = is_2ghz ?
2465
OSPREY_NUM_BAND_EDGES_2G : OSPREY_NUM_BAND_EDGES_5G;
2466
int i;
2467
2468
/* Get the edge power */
2469
for (i = 0; (i < num_edges) && (ctl_freqbin[i] != AR9300_BCHAN_UNUSED); i++)
2470
{
2471
/*
2472
* If there's an exact channel match or an inband flag set
2473
* on the lower channel use the given rd_edge_power
2474
*/
2475
if (freq == fbin2freq(ctl_freqbin[i], is_2ghz)) {
2476
if (is_2ghz) {
2477
twice_max_edge_power =
2478
p_eep_data->ctl_power_data_2g[idx].ctl_edges[i].t_power;
2479
} else {
2480
twice_max_edge_power =
2481
p_eep_data->ctl_power_data_5g[idx].ctl_edges[i].t_power;
2482
}
2483
break;
2484
} else if ((i > 0) && (freq < fbin2freq(ctl_freqbin[i], is_2ghz))) {
2485
if (is_2ghz) {
2486
if (fbin2freq(ctl_freqbin[i - 1], 1) < freq &&
2487
p_eep_data->ctl_power_data_2g[idx].ctl_edges[i - 1].flag)
2488
{
2489
twice_max_edge_power =
2490
p_eep_data->ctl_power_data_2g[idx].
2491
ctl_edges[i - 1].t_power;
2492
}
2493
} else {
2494
if (fbin2freq(ctl_freqbin[i - 1], 0) < freq &&
2495
p_eep_data->ctl_power_data_5g[idx].ctl_edges[i - 1].flag)
2496
{
2497
twice_max_edge_power =
2498
p_eep_data->ctl_power_data_5g[idx].
2499
ctl_edges[i - 1].t_power;
2500
}
2501
}
2502
/*
2503
* Leave loop - no more affecting edges possible
2504
* in this monotonic increasing list
2505
*/
2506
break;
2507
}
2508
}
2509
/*
2510
* EV89475: EEPROM might contain 0 txpower in CTL table for certain
2511
* 2.4GHz channels. We workaround it by overwriting 60 (30 dBm) here.
2512
*/
2513
if (is_2ghz && (twice_max_edge_power == 0)) {
2514
twice_max_edge_power = 60;
2515
}
2516
2517
HALASSERT(twice_max_edge_power > 0);
2518
return twice_max_edge_power;
2519
}
2520
2521
HAL_BOOL
2522
ar9300_eeprom_set_power_per_rate_table(
2523
struct ath_hal *ah,
2524
ar9300_eeprom_t *p_eep_data,
2525
const struct ieee80211_channel *chan,
2526
u_int8_t *p_pwr_array,
2527
u_int16_t cfg_ctl,
2528
u_int16_t antenna_reduction,
2529
u_int16_t twice_max_regulatory_power,
2530
u_int16_t power_limit,
2531
u_int8_t chainmask)
2532
{
2533
/* Local defines to distinguish between extension and control CTL's */
2534
#define EXT_ADDITIVE (0x8000)
2535
#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
2536
#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
2537
#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
2538
#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
2539
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
2540
#define PWRINCR_3_TO_1_CHAIN 9 /* 10*log(3)*2 */
2541
#define PWRINCR_3_TO_2_CHAIN 3 /* floor(10*log(3/2)*2) */
2542
#define PWRINCR_2_TO_1_CHAIN 6 /* 10*log(2)*2 */
2543
2544
static const u_int16_t tp_scale_reduction_table[5] =
2545
{ 0, 3, 6, 9, AR9300_MAX_RATE_POWER };
2546
int i;
2547
int16_t twice_largest_antenna;
2548
u_int16_t twice_antenna_reduction = 2*antenna_reduction ;
2549
int16_t scaled_power = 0, min_ctl_power, max_reg_allowed_power;
2550
#define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */
2551
#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */
2552
u_int16_t ctl_modes_for11a[] =
2553
{CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40};
2554
u_int16_t ctl_modes_for11g[] =
2555
{CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40};
2556
u_int16_t num_ctl_modes, *p_ctl_mode, ctl_mode, freq;
2557
CHAN_CENTERS centers;
2558
int tx_chainmask;
2559
struct ath_hal_9300 *ahp = AH9300(ah);
2560
u_int8_t *ctl_index;
2561
u_int8_t ctl_num;
2562
u_int16_t twice_min_edge_power;
2563
u_int16_t twice_max_edge_power = AR9300_MAX_RATE_POWER;
2564
#ifdef AH_DEBUG
2565
HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
2566
#endif
2567
2568
if (chainmask)
2569
tx_chainmask = chainmask;
2570
else
2571
tx_chainmask = ahp->ah_tx_chainmaskopt ?
2572
ahp->ah_tx_chainmaskopt :ahp->ah_tx_chainmask;
2573
2574
ar9300_get_channel_centers(ah, chan, &centers);
2575
2576
#if 1
2577
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
2578
ahp->twice_antenna_gain = p_eep_data->modal_header_2g.antenna_gain;
2579
} else {
2580
ahp->twice_antenna_gain = p_eep_data->modal_header_5g.antenna_gain;
2581
}
2582
2583
#else
2584
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
2585
ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_2g.antenna_gain,
2586
AH_PRIVATE(ah)->ah_antenna_gain_2g);
2587
} else {
2588
ahp->twice_antenna_gain = AH_MAX(p_eep_data->modal_header_5g.antenna_gain,
2589
AH_PRIVATE(ah)->ah_antenna_gain_5g);
2590
}
2591
#endif
2592
2593
/* Save max allowed antenna gain to ease future lookups */
2594
ahp->twice_antenna_reduction = twice_antenna_reduction;
2595
2596
/* Deduct antenna gain from EIRP to get the upper limit */
2597
twice_largest_antenna = (int16_t)AH_MIN((twice_antenna_reduction -
2598
ahp->twice_antenna_gain), 0);
2599
max_reg_allowed_power = twice_max_regulatory_power + twice_largest_antenna;
2600
2601
/* Use ah_tp_scale - see bug 30070. */
2602
if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) {
2603
max_reg_allowed_power -=
2604
(tp_scale_reduction_table[(AH_PRIVATE(ah)->ah_tpScale)] * 2);
2605
}
2606
2607
scaled_power = AH_MIN(power_limit, max_reg_allowed_power);
2608
2609
/*
2610
* Reduce scaled Power by number of chains active to get to
2611
* per chain tx power level
2612
*/
2613
/* TODO: better value than these? */
2614
switch (ar9300_get_ntxchains(tx_chainmask)) {
2615
case 1:
2616
ahp->upper_limit[0] = AH_MAX(0, scaled_power);
2617
break;
2618
case 2:
2619
scaled_power -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
2620
ahp->upper_limit[1] = AH_MAX(0, scaled_power);
2621
break;
2622
case 3:
2623
scaled_power -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
2624
ahp->upper_limit[2] = AH_MAX(0, scaled_power);
2625
break;
2626
default:
2627
HALASSERT(0); /* Unsupported number of chains */
2628
}
2629
2630
scaled_power = AH_MAX(0, scaled_power);
2631
2632
/* Get target powers from EEPROM - our baseline for TX Power */
2633
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
2634
/* Setup for CTL modes */
2635
/* CTL_11B, CTL_11G, CTL_2GHT20 */
2636
num_ctl_modes =
2637
ARRAY_LENGTH(ctl_modes_for11g) - SUB_NUM_CTL_MODES_AT_2G_40;
2638
p_ctl_mode = ctl_modes_for11g;
2639
2640
if (IEEE80211_IS_CHAN_HT40(chan)) {
2641
num_ctl_modes = ARRAY_LENGTH(ctl_modes_for11g); /* All 2G CTL's */
2642
}
2643
} else {
2644
/* Setup for CTL modes */
2645
/* CTL_11A, CTL_5GHT20 */
2646
num_ctl_modes =
2647
ARRAY_LENGTH(ctl_modes_for11a) - SUB_NUM_CTL_MODES_AT_5G_40;
2648
p_ctl_mode = ctl_modes_for11a;
2649
2650
if (IEEE80211_IS_CHAN_HT40(chan)) {
2651
num_ctl_modes = ARRAY_LENGTH(ctl_modes_for11a); /* All 5G CTL's */
2652
}
2653
}
2654
2655
/*
2656
* For MIMO, need to apply regulatory caps individually across dynamically
2657
* running modes: CCK, OFDM, HT20, HT40
2658
*
2659
* The outer loop walks through each possible applicable runtime mode.
2660
* The inner loop walks through each ctl_index entry in EEPROM.
2661
* The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
2662
*
2663
*/
2664
for (ctl_mode = 0; ctl_mode < num_ctl_modes; ctl_mode++) {
2665
HAL_BOOL is_ht40_ctl_mode =
2666
(p_ctl_mode[ctl_mode] == CTL_5GHT40) ||
2667
(p_ctl_mode[ctl_mode] == CTL_2GHT40);
2668
if (is_ht40_ctl_mode) {
2669
freq = centers.synth_center;
2670
} else if (p_ctl_mode[ctl_mode] & EXT_ADDITIVE) {
2671
freq = centers.ext_center;
2672
} else {
2673
freq = centers.ctl_center;
2674
}
2675
2676
HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
2677
"LOOP-Mode ctl_mode %d < %d, "
2678
"is_ht40_ctl_mode %d, EXT_ADDITIVE %d\n",
2679
ctl_mode, num_ctl_modes, is_ht40_ctl_mode,
2680
(p_ctl_mode[ctl_mode] & EXT_ADDITIVE));
2681
/* walk through each CTL index stored in EEPROM */
2682
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
2683
ctl_index = p_eep_data->ctl_index_2g;
2684
ctl_num = OSPREY_NUM_CTLS_2G;
2685
} else {
2686
ctl_index = p_eep_data->ctl_index_5g;
2687
ctl_num = OSPREY_NUM_CTLS_5G;
2688
}
2689
2690
for (i = 0; (i < ctl_num) && ctl_index[i]; i++) {
2691
HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
2692
" LOOP-Ctlidx %d: cfg_ctl 0x%2.2x p_ctl_mode 0x%2.2x "
2693
"ctl_index 0x%2.2x chan %d chanctl 0x%x\n",
2694
i, cfg_ctl, p_ctl_mode[ctl_mode], ctl_index[i],
2695
ichan->channel, ath_hal_getctl(ah, chan));
2696
2697
2698
/*
2699
* compare test group from regulatory channel list
2700
* with test mode from p_ctl_mode list
2701
*/
2702
if ((((cfg_ctl & ~CTL_MODE_M) |
2703
(p_ctl_mode[ctl_mode] & CTL_MODE_M)) == ctl_index[i]) ||
2704
(((cfg_ctl & ~CTL_MODE_M) |
2705
(p_ctl_mode[ctl_mode] & CTL_MODE_M)) ==
2706
((ctl_index[i] & CTL_MODE_M) | SD_NO_CTL)))
2707
{
2708
twice_min_edge_power =
2709
ar9300_eep_def_get_max_edge_power(
2710
p_eep_data, freq, i, IEEE80211_IS_CHAN_2GHZ(chan));
2711
2712
HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
2713
" MATCH-EE_IDX %d: ch %d is2 %d "
2714
"2xMinEdge %d chainmask %d chains %d\n",
2715
i, freq, IEEE80211_IS_CHAN_2GHZ(chan),
2716
twice_min_edge_power, tx_chainmask,
2717
ar9300_get_ntxchains(tx_chainmask));
2718
2719
if ((cfg_ctl & ~CTL_MODE_M) == SD_NO_CTL) {
2720
/*
2721
* Find the minimum of all CTL edge powers
2722
* that apply to this channel
2723
*/
2724
twice_max_edge_power =
2725
AH_MIN(twice_max_edge_power, twice_min_edge_power);
2726
} else {
2727
/* specific */
2728
twice_max_edge_power = twice_min_edge_power;
2729
break;
2730
}
2731
}
2732
}
2733
2734
min_ctl_power = (u_int8_t)AH_MIN(twice_max_edge_power, scaled_power);
2735
2736
HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
2737
" SEL-Min ctl_mode %d p_ctl_mode %d "
2738
"2xMaxEdge %d sP %d min_ctl_pwr %d\n",
2739
ctl_mode, p_ctl_mode[ctl_mode],
2740
twice_max_edge_power, scaled_power, min_ctl_power);
2741
2742
/* Apply ctl mode to correct target power set */
2743
switch (p_ctl_mode[ctl_mode]) {
2744
case CTL_11B:
2745
for (i = ALL_TARGET_LEGACY_1L_5L; i <= ALL_TARGET_LEGACY_11S; i++) {
2746
p_pwr_array[i] =
2747
(u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power);
2748
}
2749
break;
2750
case CTL_11A:
2751
case CTL_11G:
2752
for (i = ALL_TARGET_LEGACY_6_24; i <= ALL_TARGET_LEGACY_54; i++) {
2753
p_pwr_array[i] =
2754
(u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power);
2755
#ifdef ATH_BT_COEX
2756
if ((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) ||
2757
(ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI))
2758
{
2759
if ((ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR)
2760
&& (ahp->ah_bt_wlan_isolation
2761
< HAL_BT_COEX_ISOLATION_FOR_NO_COEX))
2762
{
2763
2764
u_int8_t reduce_pow;
2765
2766
reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX
2767
- ahp->ah_bt_wlan_isolation) << 1;
2768
2769
if (reduce_pow <= p_pwr_array[i]) {
2770
p_pwr_array[i] -= reduce_pow;
2771
}
2772
}
2773
if ((ahp->ah_bt_coex_flag &
2774
HAL_BT_COEX_FLAG_LOW_ACK_PWR) &&
2775
(i != ALL_TARGET_LEGACY_36) &&
2776
(i != ALL_TARGET_LEGACY_48) &&
2777
(i != ALL_TARGET_LEGACY_54) &&
2778
(p_ctl_mode[ctl_mode] == CTL_11G))
2779
{
2780
p_pwr_array[i] = 0;
2781
}
2782
}
2783
#endif
2784
}
2785
break;
2786
case CTL_5GHT20:
2787
case CTL_2GHT20:
2788
for (i = ALL_TARGET_HT20_0_8_16; i <= ALL_TARGET_HT20_23; i++) {
2789
p_pwr_array[i] =
2790
(u_int8_t)AH_MIN(p_pwr_array[i], min_ctl_power);
2791
#ifdef ATH_BT_COEX
2792
if (((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) ||
2793
(ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) &&
2794
(ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) &&
2795
(ahp->ah_bt_wlan_isolation
2796
< HAL_BT_COEX_ISOLATION_FOR_NO_COEX)) {
2797
2798
u_int8_t reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX
2799
- ahp->ah_bt_wlan_isolation) << 1;
2800
2801
if (reduce_pow <= p_pwr_array[i]) {
2802
p_pwr_array[i] -= reduce_pow;
2803
}
2804
}
2805
#if ATH_SUPPORT_MCI
2806
else if ((ahp->ah_bt_coex_flag &
2807
HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) &&
2808
(p_ctl_mode[ctl_mode] == CTL_2GHT20) &&
2809
(ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI))
2810
{
2811
u_int8_t max_pwr;
2812
2813
max_pwr = MS(mci_concur_tx_max_pwr[2][1],
2814
ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK);
2815
if (p_pwr_array[i] > max_pwr) {
2816
p_pwr_array[i] = max_pwr;
2817
}
2818
}
2819
#endif
2820
#endif
2821
}
2822
break;
2823
case CTL_11B_EXT:
2824
#ifdef NOT_YET
2825
target_power_cck_ext.t_pow2x[0] = (u_int8_t)
2826
AH_MIN(target_power_cck_ext.t_pow2x[0], min_ctl_power);
2827
#endif /* NOT_YET */
2828
break;
2829
case CTL_11A_EXT:
2830
case CTL_11G_EXT:
2831
#ifdef NOT_YET
2832
target_power_ofdm_ext.t_pow2x[0] = (u_int8_t)
2833
AH_MIN(target_power_ofdm_ext.t_pow2x[0], min_ctl_power);
2834
#endif /* NOT_YET */
2835
break;
2836
case CTL_5GHT40:
2837
case CTL_2GHT40:
2838
for (i = ALL_TARGET_HT40_0_8_16; i <= ALL_TARGET_HT40_23; i++) {
2839
p_pwr_array[i] = (u_int8_t)
2840
AH_MIN(p_pwr_array[i], min_ctl_power);
2841
#ifdef ATH_BT_COEX
2842
if (((ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_3WIRE) ||
2843
(ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI)) &&
2844
(ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) &&
2845
(ahp->ah_bt_wlan_isolation
2846
< HAL_BT_COEX_ISOLATION_FOR_NO_COEX)) {
2847
2848
u_int8_t reduce_pow = (HAL_BT_COEX_ISOLATION_FOR_NO_COEX
2849
- ahp->ah_bt_wlan_isolation) << 1;
2850
2851
if (reduce_pow <= p_pwr_array[i]) {
2852
p_pwr_array[i] -= reduce_pow;
2853
}
2854
}
2855
#if ATH_SUPPORT_MCI
2856
else if ((ahp->ah_bt_coex_flag &
2857
HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) &&
2858
(p_ctl_mode[ctl_mode] == CTL_2GHT40) &&
2859
(ahp->ah_bt_coex_config_type == HAL_BT_COEX_CFG_MCI))
2860
{
2861
u_int8_t max_pwr;
2862
2863
max_pwr = MS(mci_concur_tx_max_pwr[3][1],
2864
ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK);
2865
if (p_pwr_array[i] > max_pwr) {
2866
p_pwr_array[i] = max_pwr;
2867
}
2868
}
2869
#endif
2870
#endif
2871
}
2872
break;
2873
default:
2874
HALASSERT(0);
2875
break;
2876
}
2877
} /* end ctl mode checking */
2878
2879
return AH_TRUE;
2880
#undef EXT_ADDITIVE
2881
#undef CTL_11A_EXT
2882
#undef CTL_11G_EXT
2883
#undef CTL_11B_EXT
2884
#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
2885
#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN
2886
}
2887
2888
/**************************************************************
2889
* ar9300_eeprom_set_transmit_power
2890
*
2891
* Set the transmit power in the baseband for the given
2892
* operating channel and mode.
2893
*/
2894
HAL_STATUS
2895
ar9300_eeprom_set_transmit_power(struct ath_hal *ah,
2896
ar9300_eeprom_t *p_eep_data, const struct ieee80211_channel *chan, u_int16_t cfg_ctl,
2897
u_int16_t antenna_reduction, u_int16_t twice_max_regulatory_power,
2898
u_int16_t power_limit)
2899
{
2900
#define ABS(_x, _y) ((int)_x > (int)_y ? (int)_x - (int)_y : (int)_y - (int)_x)
2901
#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
2902
#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
2903
u_int8_t target_power_val_t2[ar9300_rate_size];
2904
u_int8_t target_power_val_t2_eep[ar9300_rate_size];
2905
int16_t twice_array_gain = 0, max_power_level = 0;
2906
struct ath_hal_9300 *ahp = AH9300(ah);
2907
int i = 0;
2908
u_int32_t tmp_paprd_rate_mask = 0, *tmp_ptr = NULL;
2909
int paprd_scale_factor = 5;
2910
HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
2911
2912
u_int8_t *ptr_mcs_rate2power_table_index;
2913
u_int8_t mcs_rate2power_table_index_ht20[24] =
2914
{
2915
ALL_TARGET_HT20_0_8_16,
2916
ALL_TARGET_HT20_1_3_9_11_17_19,
2917
ALL_TARGET_HT20_1_3_9_11_17_19,
2918
ALL_TARGET_HT20_1_3_9_11_17_19,
2919
ALL_TARGET_HT20_4,
2920
ALL_TARGET_HT20_5,
2921
ALL_TARGET_HT20_6,
2922
ALL_TARGET_HT20_7,
2923
ALL_TARGET_HT20_0_8_16,
2924
ALL_TARGET_HT20_1_3_9_11_17_19,
2925
ALL_TARGET_HT20_1_3_9_11_17_19,
2926
ALL_TARGET_HT20_1_3_9_11_17_19,
2927
ALL_TARGET_HT20_12,
2928
ALL_TARGET_HT20_13,
2929
ALL_TARGET_HT20_14,
2930
ALL_TARGET_HT20_15,
2931
ALL_TARGET_HT20_0_8_16,
2932
ALL_TARGET_HT20_1_3_9_11_17_19,
2933
ALL_TARGET_HT20_1_3_9_11_17_19,
2934
ALL_TARGET_HT20_1_3_9_11_17_19,
2935
ALL_TARGET_HT20_20,
2936
ALL_TARGET_HT20_21,
2937
ALL_TARGET_HT20_22,
2938
ALL_TARGET_HT20_23
2939
};
2940
2941
u_int8_t mcs_rate2power_table_index_ht40[24] =
2942
{
2943
ALL_TARGET_HT40_0_8_16,
2944
ALL_TARGET_HT40_1_3_9_11_17_19,
2945
ALL_TARGET_HT40_1_3_9_11_17_19,
2946
ALL_TARGET_HT40_1_3_9_11_17_19,
2947
ALL_TARGET_HT40_4,
2948
ALL_TARGET_HT40_5,
2949
ALL_TARGET_HT40_6,
2950
ALL_TARGET_HT40_7,
2951
ALL_TARGET_HT40_0_8_16,
2952
ALL_TARGET_HT40_1_3_9_11_17_19,
2953
ALL_TARGET_HT40_1_3_9_11_17_19,
2954
ALL_TARGET_HT40_1_3_9_11_17_19,
2955
ALL_TARGET_HT40_12,
2956
ALL_TARGET_HT40_13,
2957
ALL_TARGET_HT40_14,
2958
ALL_TARGET_HT40_15,
2959
ALL_TARGET_HT40_0_8_16,
2960
ALL_TARGET_HT40_1_3_9_11_17_19,
2961
ALL_TARGET_HT40_1_3_9_11_17_19,
2962
ALL_TARGET_HT40_1_3_9_11_17_19,
2963
ALL_TARGET_HT40_20,
2964
ALL_TARGET_HT40_21,
2965
ALL_TARGET_HT40_22,
2966
ALL_TARGET_HT40_23,
2967
};
2968
2969
HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
2970
"%s[%d] +++chan %d,cfgctl 0x%04x "
2971
"antenna_reduction 0x%04x, twice_max_regulatory_power 0x%04x "
2972
"power_limit 0x%04x\n",
2973
__func__, __LINE__, ichan->channel, cfg_ctl,
2974
antenna_reduction, twice_max_regulatory_power, power_limit);
2975
ar9300_set_target_power_from_eeprom(ah, ichan->channel, target_power_val_t2);
2976
2977
if (ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED)) {
2978
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
2979
if (IEEE80211_IS_CHAN_HT40(chan)) {
2980
tmp_paprd_rate_mask =
2981
p_eep_data->modal_header_2g.paprd_rate_mask_ht40;
2982
tmp_ptr = &AH9300(ah)->ah_2g_paprd_rate_mask_ht40;
2983
} else {
2984
tmp_paprd_rate_mask =
2985
p_eep_data->modal_header_2g.paprd_rate_mask_ht20;
2986
tmp_ptr = &AH9300(ah)->ah_2g_paprd_rate_mask_ht20;
2987
}
2988
} else {
2989
if (IEEE80211_IS_CHAN_HT40(chan)) {
2990
tmp_paprd_rate_mask =
2991
p_eep_data->modal_header_5g.paprd_rate_mask_ht40;
2992
tmp_ptr = &AH9300(ah)->ah_5g_paprd_rate_mask_ht40;
2993
} else {
2994
tmp_paprd_rate_mask =
2995
p_eep_data->modal_header_5g.paprd_rate_mask_ht20;
2996
tmp_ptr = &AH9300(ah)->ah_5g_paprd_rate_mask_ht20;
2997
}
2998
}
2999
AH_PAPRD_GET_SCALE_FACTOR(
3000
paprd_scale_factor, p_eep_data, IEEE80211_IS_CHAN_2GHZ(chan), ichan->channel);
3001
HALDEBUG(ah, HAL_DEBUG_CALIBRATE, "%s[%d] paprd_scale_factor %d\n",
3002
__func__, __LINE__, paprd_scale_factor);
3003
/* PAPRD is not done yet, Scale down the EEP power */
3004
if (IEEE80211_IS_CHAN_HT40(chan)) {
3005
ptr_mcs_rate2power_table_index =
3006
&mcs_rate2power_table_index_ht40[0];
3007
} else {
3008
ptr_mcs_rate2power_table_index =
3009
&mcs_rate2power_table_index_ht20[0];
3010
}
3011
if (! ichan->paprd_table_write_done) {
3012
for (i = 0; i < 24; i++) {
3013
/* PAPRD is done yet, so Scale down Power for PAPRD Rates*/
3014
if (tmp_paprd_rate_mask & (1 << i)) {
3015
target_power_val_t2[ptr_mcs_rate2power_table_index[i]] -=
3016
paprd_scale_factor;
3017
HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3018
"%s[%d]: Chan %d "
3019
"Scale down target_power_val_t2[%d] = 0x%04x\n",
3020
__func__, __LINE__,
3021
ichan->channel, i, target_power_val_t2[i]);
3022
}
3023
}
3024
} else {
3025
HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3026
"%s[%d]: PAPRD Done No TGT PWR Scaling\n", __func__, __LINE__);
3027
}
3028
}
3029
3030
/* Save the Target power for future use */
3031
OS_MEMCPY(target_power_val_t2_eep, target_power_val_t2,
3032
sizeof(target_power_val_t2));
3033
ar9300_eeprom_set_power_per_rate_table(ah, p_eep_data, chan,
3034
target_power_val_t2, cfg_ctl,
3035
antenna_reduction,
3036
twice_max_regulatory_power,
3037
power_limit, 0);
3038
3039
/* Save this for quick lookup */
3040
ahp->reg_dmn = ath_hal_getctl(ah, chan);
3041
3042
/*
3043
* After reading FCC/OET 13TR1003 (Directional Gain of IEEE 802.11
3044
* MIMO devices employing cyclic delay diversity) and looking at what
3045
* ath9k does, let's disable the CDD check until it's clearer exactly
3046
* how the maximum cap should be applied here.
3047
*
3048
* Right now the CDD check is simply unconditionally reducing the
3049
* gain of legacy and 1/2 stream rates depending upon the chainmask.
3050
* (CDD is used when transmitting rates that don't already use up the
3051
* full set of streams - eg OFDM or MCS0-7 on a 2 or 3 chain TX path.)
3052
*
3053
* It's dropping the 2-chain TX by 3dB and 3-chain by 5dB to "meet"
3054
* power spectral density requirements but it's not currently taking
3055
* into account how close to the regulatory limit the hardware/antenna
3056
* system is already at. It doesn't help that the conductive testing
3057
* limits have the array gain at 0dB for all AR9300/derivative
3058
* configurations.
3059
*
3060
* It also doesn't let us do single chain transmit at the full allowed
3061
* power for the regulatory/CTL limits as it subtracts it from what's
3062
* programmed into the hardware.
3063
*
3064
* ath9k doesn't factor any of the CDD stuff into account, so I'm going
3065
* to disable it here and in the TPC path until I get a better idea
3066
* of what to really do here.
3067
*/
3068
#if 0
3069
/*
3070
* Always use CDD/direct per rate power table for register based approach.
3071
* For FCC, CDD calculations should factor in the array gain, hence
3072
* this adjust call. ETSI and MKK does not have this requirement.
3073
*/
3074
if (is_reg_dmn_fcc(ahp->reg_dmn)) {
3075
HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3076
"%s: FCC regdomain, calling reg_txpower_cdd\n",
3077
__func__);
3078
ar9300_adjust_reg_txpower_cdd(ah, target_power_val_t2);
3079
}
3080
#endif
3081
3082
if (ar9300_eeprom_get(ahp, EEP_PAPRD_ENABLED)) {
3083
for (i = 0; i < ar9300_rate_size; i++) {
3084
/*
3085
* EEPROM TGT PWR is not same as current TGT PWR,
3086
* so Disable PAPRD for this rate.
3087
* Some of APs might ask to reduce Target Power,
3088
* if target power drops significantly,
3089
* disable PAPRD for that rate.
3090
*/
3091
if (tmp_paprd_rate_mask & (1 << i)) {
3092
if (ABS(target_power_val_t2_eep[i], target_power_val_t2[i]) >
3093
paprd_scale_factor)
3094
{
3095
tmp_paprd_rate_mask &= ~(1 << i);
3096
HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3097
"%s: EEP TPC[%02d] 0x%08x "
3098
"Curr TPC[%02d] 0x%08x mask = 0x%08x\n",
3099
__func__, i, target_power_val_t2_eep[i], i,
3100
target_power_val_t2[i], tmp_paprd_rate_mask);
3101
}
3102
}
3103
3104
}
3105
HALDEBUG(ah, HAL_DEBUG_CALIBRATE,
3106
"%s: Chan %d After tmp_paprd_rate_mask = 0x%08x\n",
3107
__func__, ichan->channel, tmp_paprd_rate_mask);
3108
if (tmp_ptr) {
3109
*tmp_ptr = tmp_paprd_rate_mask;
3110
}
3111
}
3112
3113
/* Write target power array to registers */
3114
ar9300_transmit_power_reg_write(ah, target_power_val_t2);
3115
3116
/* Write target power for self generated frames to the TPC register */
3117
ar9300_selfgen_tpc_reg_write(ah, chan, target_power_val_t2);
3118
3119
/* GreenTx or Paprd */
3120
if (ah->ah_config.ath_hal_sta_update_tx_pwr_enable ||
3121
AH_PRIVATE(ah)->ah_caps.halPaprdEnabled)
3122
{
3123
if (AR_SREV_POSEIDON(ah)) {
3124
/*For HAL_RSSI_TX_POWER_NONE array*/
3125
OS_MEMCPY(ahp->ah_default_tx_power,
3126
target_power_val_t2,
3127
sizeof(target_power_val_t2));
3128
/* Get defautl tx related register setting for GreenTx */
3129
/* Record OB/DB */
3130
ahp->ah_ob_db1[POSEIDON_STORED_REG_OBDB] =
3131
OS_REG_READ(ah, AR_PHY_65NM_CH0_TXRF2);
3132
/* Record TPC settting */
3133
ahp->ah_ob_db1[POSEIDON_STORED_REG_TPC] =
3134
OS_REG_READ(ah, AR_TPC);
3135
/* Record BB_powertx_rate9 setting */
3136
ahp->ah_ob_db1[POSEIDON_STORED_REG_BB_PWRTX_RATE9] =
3137
OS_REG_READ(ah, AR_PHY_BB_POWERTX_RATE9);
3138
}
3139
}
3140
3141
/*
3142
* Return tx power used to iwconfig.
3143
* Since power is rate dependent, use one of the indices from the
3144
* AR9300_Rates enum to select an entry from target_power_val_t2[]
3145
* to report.
3146
* Currently returns the power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
3147
* as CCK power is less interesting (?).
3148
*/
3149
i = ALL_TARGET_LEGACY_6_24; /* legacy */
3150
if (IEEE80211_IS_CHAN_HT40(chan)) {
3151
i = ALL_TARGET_HT40_0_8_16; /* ht40 */
3152
} else if (IEEE80211_IS_CHAN_HT20(chan)) {
3153
i = ALL_TARGET_HT20_0_8_16; /* ht20 */
3154
}
3155
max_power_level = target_power_val_t2[i];
3156
/* Adjusting the ah_max_power_level based on chains and antennaGain*/
3157
switch (ar9300_get_ntxchains(((ahp->ah_tx_chainmaskopt > 0) ?
3158
ahp->ah_tx_chainmaskopt : ahp->ah_tx_chainmask)))
3159
{
3160
case 1:
3161
break;
3162
case 2:
3163
twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 0:
3164
((int16_t)AH_MIN((ahp->twice_antenna_reduction -
3165
(ahp->twice_antenna_gain + INCREASE_MAXPOW_BY_TWO_CHAIN)), 0));
3166
/* Adjusting maxpower with antennaGain */
3167
max_power_level -= twice_array_gain;
3168
/* Adjusting maxpower based on chain */
3169
max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
3170
break;
3171
case 3:
3172
twice_array_gain = (ahp->twice_antenna_gain >= ahp->twice_antenna_reduction)? 0:
3173
((int16_t)AH_MIN((ahp->twice_antenna_reduction -
3174
(ahp->twice_antenna_gain + INCREASE_MAXPOW_BY_THREE_CHAIN)), 0));
3175
3176
/* Adjusting maxpower with antennaGain */
3177
max_power_level -= twice_array_gain;
3178
/* Adjusting maxpower based on chain */
3179
max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
3180
break;
3181
default:
3182
HALASSERT(0); /* Unsupported number of chains */
3183
}
3184
AH_PRIVATE(ah)->ah_maxPowerLevel = (int8_t)max_power_level;
3185
3186
ar9300_calibration_apply(ah, ichan->channel);
3187
#undef ABS
3188
3189
/* Handle per packet TPC initializations */
3190
if (ah->ah_config.ath_hal_desc_tpc) {
3191
/* Transmit Power per-rate per-chain are computed here. A separate
3192
* power table is maintained for different MIMO modes (i.e. TXBF ON,
3193
* STBC) to enable easy lookup during packet transmit.
3194
* The reason for maintaing each of these tables per chain is that
3195
* the transmit power used for different number of chains is different
3196
* depending on whether the power has been limited by the target power,
3197
* the regulatory domain or the CTL limits.
3198
*/
3199
u_int mode = ath_hal_get_curmode(ah, chan);
3200
u_int32_t val = 0;
3201
u_int8_t chainmasks[AR9300_MAX_CHAINS] =
3202
{OSPREY_1_CHAINMASK, OSPREY_2LOHI_CHAINMASK, OSPREY_3_CHAINMASK};
3203
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
3204
OS_MEMCPY(target_power_val_t2, target_power_val_t2_eep,
3205
sizeof(target_power_val_t2_eep));
3206
ar9300_eeprom_set_power_per_rate_table(ah, p_eep_data, chan,
3207
target_power_val_t2, cfg_ctl,
3208
antenna_reduction,
3209
twice_max_regulatory_power,
3210
power_limit, chainmasks[i]);
3211
HALDEBUG(ah, HAL_DEBUG_POWER_MGMT,
3212
" Channel = %d Chainmask = %d, Upper Limit = [%2d.%1d dBm]\n",
3213
ichan->channel, i, ahp->upper_limit[i]/2,
3214
ahp->upper_limit[i]%2 * 5);
3215
ar9300_init_rate_txpower(ah, mode, chan, target_power_val_t2,
3216
chainmasks[i]);
3217
3218
}
3219
3220
/* Enable TPC */
3221
OS_REG_WRITE(ah, AR_PHY_PWRTX_MAX, AR_PHY_PWRTX_MAX_TPC_ENABLE);
3222
/*
3223
* Disable per chain power reduction since we are already
3224
* accounting for this in our calculations
3225
*/
3226
val = OS_REG_READ(ah, AR_PHY_POWER_TX_SUB);
3227
if (AR_SREV_WASP(ah)) {
3228
OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
3229
val & AR_PHY_POWER_TX_SUB_2_DISABLE);
3230
} else {
3231
OS_REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
3232
val & AR_PHY_POWER_TX_SUB_3_DISABLE);
3233
}
3234
}
3235
3236
return HAL_OK;
3237
}
3238
3239
/**************************************************************
3240
* ar9300_eeprom_set_addac
3241
*
3242
* Set the ADDAC from eeprom.
3243
*/
3244
void
3245
ar9300_eeprom_set_addac(struct ath_hal *ah, struct ieee80211_channel *chan)
3246
{
3247
3248
HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
3249
"FIXME: ar9300_eeprom_def_set_addac called\n");
3250
#if 0
3251
MODAL_EEPDEF_HEADER *p_modal;
3252
struct ath_hal_9300 *ahp = AH9300(ah);
3253
ar9300_eeprom_t *eep = &ahp->ah_eeprom.def;
3254
u_int8_t biaslevel;
3255
3256
if (AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_SOWL) {
3257
return;
3258
}
3259
3260
HALASSERT(owl_get_eepdef_ver(ahp) == AR9300_EEP_VER);
3261
3262
/* Xpa bias levels in eeprom are valid from rev 14.7 */
3263
if (owl_get_eepdef_rev(ahp) < AR9300_EEP_MINOR_VER_7) {
3264
return;
3265
}
3266
3267
if (ahp->ah_emu_eeprom) {
3268
return;
3269
}
3270
3271
p_modal = &(eep->modal_header[IEEE80211_IS_CHAN_2GHZ(chan)]);
3272
3273
if (p_modal->xpa_bias_lvl != 0xff) {
3274
biaslevel = p_modal->xpa_bias_lvl;
3275
} else {
3276
/* Use freqeuncy specific xpa bias level */
3277
u_int16_t reset_freq_bin, freq_bin, freq_count = 0;
3278
CHAN_CENTERS centers;
3279
3280
ar9300_get_channel_centers(ah, chan, &centers);
3281
3282
reset_freq_bin = FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan));
3283
freq_bin = p_modal->xpa_bias_lvl_freq[0] & 0xff;
3284
biaslevel = (u_int8_t)(p_modal->xpa_bias_lvl_freq[0] >> 14);
3285
3286
freq_count++;
3287
3288
while (freq_count < 3) {
3289
if (p_modal->xpa_bias_lvl_freq[freq_count] == 0x0) {
3290
break;
3291
}
3292
3293
freq_bin = p_modal->xpa_bias_lvl_freq[freq_count] & 0xff;
3294
if (reset_freq_bin >= freq_bin) {
3295
biaslevel =
3296
(u_int8_t)(p_modal->xpa_bias_lvl_freq[freq_count] >> 14);
3297
} else {
3298
break;
3299
}
3300
freq_count++;
3301
}
3302
}
3303
3304
/* Apply bias level to the ADDAC values in the INI array */
3305
if (IEEE80211_IS_CHAN_2GHZ(chan)) {
3306
INI_RA(&ahp->ah_ini_addac, 7, 1) =
3307
(INI_RA(&ahp->ah_ini_addac, 7, 1) & (~0x18)) | biaslevel << 3;
3308
} else {
3309
INI_RA(&ahp->ah_ini_addac, 6, 1) =
3310
(INI_RA(&ahp->ah_ini_addac, 6, 1) & (~0xc0)) | biaslevel << 6;
3311
}
3312
#endif
3313
}
3314
3315
u_int
3316
ar9300_eeprom_dump_support(struct ath_hal *ah, void **pp_e)
3317
{
3318
*pp_e = &(AH9300(ah)->ah_eeprom);
3319
return sizeof(ar9300_eeprom_t);
3320
}
3321
3322
u_int8_t
3323
ar9300_eeprom_get_num_ant_config(struct ath_hal_9300 *ahp,
3324
HAL_FREQ_BAND freq_band)
3325
{
3326
#if 0
3327
ar9300_eeprom_t *eep = &ahp->ah_eeprom.def;
3328
MODAL_EEPDEF_HEADER *p_modal =
3329
&(eep->modal_header[HAL_FREQ_BAND_2GHZ == freq_band]);
3330
BASE_EEPDEF_HEADER *p_base = &eep->base_eep_header;
3331
u_int8_t num_ant_config;
3332
3333
num_ant_config = 1; /* default antenna configuration */
3334
3335
if (p_base->version >= 0x0E0D) {
3336
if (p_modal->use_ant1) {
3337
num_ant_config += 1;
3338
}
3339
}
3340
3341
return num_ant_config;
3342
#else
3343
return 1;
3344
#endif
3345
}
3346
3347
HAL_STATUS
3348
ar9300_eeprom_get_ant_cfg(struct ath_hal_9300 *ahp,
3349
const struct ieee80211_channel *chan,
3350
u_int8_t index, u_int16_t *config)
3351
{
3352
#if 0
3353
ar9300_eeprom_t *eep = &ahp->ah_eeprom.def;
3354
MODAL_EEPDEF_HEADER *p_modal = &(eep->modal_header[IEEE80211_IS_CHAN_2GHZ(chan)]);
3355
BASE_EEPDEF_HEADER *p_base = &eep->base_eep_header;
3356
3357
switch (index) {
3358
case 0:
3359
*config = p_modal->ant_ctrl_common & 0xFFFF;
3360
return HAL_OK;
3361
case 1:
3362
if (p_base->version >= 0x0E0D) {
3363
if (p_modal->use_ant1) {
3364
*config = ((p_modal->ant_ctrl_common & 0xFFFF0000) >> 16);
3365
return HAL_OK;
3366
}
3367
}
3368
break;
3369
default:
3370
break;
3371
}
3372
#endif
3373
return HAL_EINVAL;
3374
}
3375
3376
u_int8_t*
3377
ar9300_eeprom_get_cust_data(struct ath_hal_9300 *ahp)
3378
{
3379
return (u_int8_t *)ahp;
3380
}
3381
3382
#ifdef UNUSED
3383
static inline HAL_STATUS
3384
ar9300_check_eeprom(struct ath_hal *ah)
3385
{
3386
#if 0
3387
u_int32_t sum = 0, el;
3388
u_int16_t *eepdata;
3389
int i;
3390
struct ath_hal_9300 *ahp = AH9300(ah);
3391
HAL_BOOL need_swap = AH_FALSE;
3392
ar9300_eeprom_t *eep = (ar9300_eeprom_t *)&ahp->ah_eeprom.def;
3393
u_int16_t magic, magic2;
3394
int addr;
3395
u_int16_t temp;
3396
3397
/*
3398
** We need to check the EEPROM data regardless of if it's in flash or
3399
** in EEPROM.
3400
*/
3401
3402
if (!ahp->ah_priv.priv.ah_eeprom_read(
3403
ah, AR9300_EEPROM_MAGIC_OFFSET, &magic))
3404
{
3405
HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Reading Magic # failed\n", __func__);
3406
return AH_FALSE;
3407
}
3408
3409
HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Read Magic = 0x%04X\n", __func__, magic);
3410
3411
if (!ar9300_eep_data_in_flash(ah)) {
3412
3413
if (magic != AR9300_EEPROM_MAGIC) {
3414
magic2 = SWAP16(magic);
3415
3416
if (magic2 == AR9300_EEPROM_MAGIC) {
3417
need_swap = AH_TRUE;
3418
eepdata = (u_int16_t *)(&ahp->ah_eeprom);
3419
3420
for (addr = 0;
3421
addr < sizeof(ar9300_eeprom_t) / sizeof(u_int16_t);
3422
addr++)
3423
{
3424
temp = SWAP16(*eepdata);
3425
*eepdata = temp;
3426
eepdata++;
3427
3428
HALDEBUG(ah, HAL_DEBUG_EEPROM_DUMP, "0x%04X ", *eepdata);
3429
if (((addr + 1) % 6) == 0) {
3430
HALDEBUG(ah, HAL_DEBUG_EEPROM_DUMP, "\n");
3431
}
3432
}
3433
} else {
3434
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3435
"Invalid EEPROM Magic. endianness missmatch.\n");
3436
return HAL_EEBADSUM;
3437
}
3438
}
3439
} else {
3440
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3441
"EEPROM being read from flash @0x%p\n", AH_PRIVATE(ah)->ah_st);
3442
}
3443
3444
HALDEBUG(ah, HAL_DEBUG_EEPROM, "need_swap = %s.\n", need_swap?"True":"False");
3445
3446
if (need_swap) {
3447
el = SWAP16(ahp->ah_eeprom.def.base_eep_header.length);
3448
} else {
3449
el = ahp->ah_eeprom.def.base_eep_header.length;
3450
}
3451
3452
eepdata = (u_int16_t *)(&ahp->ah_eeprom.def);
3453
for (i = 0;
3454
i < AH_MIN(el, sizeof(ar9300_eeprom_t)) / sizeof(u_int16_t);
3455
i++) {
3456
sum ^= *eepdata++;
3457
}
3458
3459
if (need_swap) {
3460
/*
3461
* preddy: EEPROM endianness does not match. So change it
3462
* 8bit values in eeprom data structure does not need to be swapped
3463
* Only >8bits (16 & 32) values need to be swapped
3464
* If a new 16 or 32 bit field is added to the EEPROM contents,
3465
* please make sure to swap the field here
3466
*/
3467
u_int32_t integer, j;
3468
u_int16_t word;
3469
3470
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3471
"EEPROM Endianness is not native.. Changing \n");
3472
3473
/* convert Base Eep header */
3474
word = SWAP16(eep->base_eep_header.length);
3475
eep->base_eep_header.length = word;
3476
3477
word = SWAP16(eep->base_eep_header.checksum);
3478
eep->base_eep_header.checksum = word;
3479
3480
word = SWAP16(eep->base_eep_header.version);
3481
eep->base_eep_header.version = word;
3482
3483
word = SWAP16(eep->base_eep_header.reg_dmn[0]);
3484
eep->base_eep_header.reg_dmn[0] = word;
3485
3486
word = SWAP16(eep->base_eep_header.reg_dmn[1]);
3487
eep->base_eep_header.reg_dmn[1] = word;
3488
3489
word = SWAP16(eep->base_eep_header.rf_silent);
3490
eep->base_eep_header.rf_silent = word;
3491
3492
word = SWAP16(eep->base_eep_header.blue_tooth_options);
3493
eep->base_eep_header.blue_tooth_options = word;
3494
3495
word = SWAP16(eep->base_eep_header.device_cap);
3496
eep->base_eep_header.device_cap = word;
3497
3498
/* convert Modal Eep header */
3499
for (j = 0; j < ARRAY_LENGTH(eep->modal_header); j++) {
3500
MODAL_EEPDEF_HEADER *p_modal = &eep->modal_header[j];
3501
integer = SWAP32(p_modal->ant_ctrl_common);
3502
p_modal->ant_ctrl_common = integer;
3503
3504
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
3505
integer = SWAP32(p_modal->ant_ctrl_chain[i]);
3506
p_modal->ant_ctrl_chain[i] = integer;
3507
}
3508
3509
for (i = 0; i < AR9300_EEPROM_MODAL_SPURS; i++) {
3510
word = SWAP16(p_modal->spur_chans[i].spur_chan);
3511
p_modal->spur_chans[i].spur_chan = word;
3512
}
3513
}
3514
}
3515
3516
/* Check CRC - Attach should fail on a bad checksum */
3517
if (sum != 0xffff || owl_get_eepdef_ver(ahp) != AR9300_EEP_VER ||
3518
owl_get_eepdef_rev(ahp) < AR9300_EEP_NO_BACK_VER) {
3519
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3520
"Bad EEPROM checksum 0x%x or revision 0x%04x\n",
3521
sum, owl_get_eepdef_ver(ahp));
3522
return HAL_EEBADSUM;
3523
}
3524
#ifdef EEPROM_DUMP
3525
ar9300_eeprom_def_dump(ah, eep);
3526
#endif
3527
3528
#if 0
3529
#ifdef AH_AR9300_OVRD_TGT_PWR
3530
3531
/*
3532
* 14.4 EEPROM contains low target powers.
3533
* Hardcode until EEPROM > 14.4
3534
*/
3535
if (owl_get_eepdef_ver(ahp) == 14 && owl_get_eepdef_rev(ahp) <= 4) {
3536
MODAL_EEPDEF_HEADER *p_modal;
3537
3538
#ifdef EEPROM_DUMP
3539
HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE, "Original Target Powers\n");
3540
ar9300_eep_def_dump_tgt_power(ah, eep);
3541
#endif
3542
HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE,
3543
"Override Target Powers. EEPROM Version is %d.%d, "
3544
"Device Type %d\n",
3545
owl_get_eepdef_ver(ahp),
3546
owl_get_eepdef_rev(ahp),
3547
eep->base_eep_header.device_type);
3548
3549
3550
ar9300_eep_def_override_tgt_power(ah, eep);
3551
3552
if (eep->base_eep_header.device_type == 5) {
3553
/* for xb72 only: improve transmit EVM for interop */
3554
p_modal = &eep->modal_header[1];
3555
p_modal->tx_frame_to_data_start = 0x23;
3556
p_modal->tx_frame_to_xpa_on = 0x23;
3557
p_modal->tx_frame_to_pa_on = 0x23;
3558
}
3559
3560
#ifdef EEPROM_DUMP
3561
HALDEBUG(ah, HAL_DEBUG_POWER_OVERRIDE, "Modified Target Powers\n");
3562
ar9300_eep_def_dump_tgt_power(ah, eep);
3563
#endif
3564
}
3565
#endif /* AH_AR9300_OVRD_TGT_PWR */
3566
#endif
3567
#endif
3568
return HAL_OK;
3569
}
3570
#endif
3571
3572
static u_int16_t
3573
ar9300_eeprom_get_spur_chan(struct ath_hal *ah, int i, HAL_BOOL is_2ghz)
3574
{
3575
u_int16_t spur_val = AR_NO_SPUR;
3576
#if 0
3577
struct ath_hal_9300 *ahp = AH9300(ah);
3578
ar9300_eeprom_t *eep = (ar9300_eeprom_t *)&ahp->ah_eeprom;
3579
3580
HALASSERT(i < AR_EEPROM_MODAL_SPURS );
3581
3582
HALDEBUG(ah, HAL_DEBUG_ANI,
3583
"Getting spur idx %d is2Ghz. %d val %x\n",
3584
i, is_2ghz,
3585
AH_PRIVATE(ah)->ah_config.ath_hal_spur_chans[i][is_2ghz]);
3586
3587
switch (AH_PRIVATE(ah)->ah_config.ath_hal_spur_mode) {
3588
case SPUR_DISABLE:
3589
/* returns AR_NO_SPUR */
3590
break;
3591
case SPUR_ENABLE_IOCTL:
3592
spur_val = AH_PRIVATE(ah)->ah_config.ath_hal_spur_chans[i][is_2ghz];
3593
HALDEBUG(ah, HAL_DEBUG_ANI,
3594
"Getting spur val from new loc. %d\n", spur_val);
3595
break;
3596
case SPUR_ENABLE_EEPROM:
3597
spur_val = eep->modal_header[is_2ghz].spur_chans[i].spur_chan;
3598
break;
3599
3600
}
3601
#endif
3602
return spur_val;
3603
}
3604
3605
#ifdef UNUSED
3606
static inline HAL_BOOL
3607
ar9300_fill_eeprom(struct ath_hal *ah)
3608
{
3609
return ar9300_eeprom_restore(ah);
3610
}
3611
#endif
3612
3613
u_int16_t
3614
ar9300_eeprom_struct_size(void)
3615
{
3616
return sizeof(ar9300_eeprom_t);
3617
}
3618
3619
int ar9300_eeprom_struct_default_many(void)
3620
{
3621
return ARRAY_LENGTH(default9300);
3622
}
3623
3624
3625
ar9300_eeprom_t *
3626
ar9300_eeprom_struct_default(int default_index)
3627
{
3628
if (default_index >= 0 &&
3629
default_index < ARRAY_LENGTH(default9300))
3630
{
3631
return default9300[default_index];
3632
} else {
3633
return 0;
3634
}
3635
}
3636
3637
ar9300_eeprom_t *
3638
ar9300_eeprom_struct_default_find_by_id(int id)
3639
{
3640
int it;
3641
3642
for (it = 0; it < ARRAY_LENGTH(default9300); it++) {
3643
if (default9300[it] != 0 && default9300[it]->template_version == id) {
3644
return default9300[it];
3645
}
3646
}
3647
return 0;
3648
}
3649
3650
3651
HAL_BOOL
3652
ar9300_calibration_data_read_flash(struct ath_hal *ah, long address,
3653
u_int8_t *buffer, int many)
3654
{
3655
3656
if (((address) < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) {
3657
return AH_FALSE;
3658
}
3659
return AH_FALSE;
3660
}
3661
3662
HAL_BOOL
3663
ar9300_calibration_data_read_eeprom(struct ath_hal *ah, long address,
3664
u_int8_t *buffer, int many)
3665
{
3666
int i;
3667
u_int8_t value[2];
3668
unsigned long eep_addr;
3669
unsigned long byte_addr;
3670
u_int16_t *svalue;
3671
3672
if (((address) < 0) || ((address + many) > AR9300_EEPROM_SIZE)) {
3673
return AH_FALSE;
3674
}
3675
3676
for (i = 0; i < many; i++) {
3677
eep_addr = (u_int16_t) (address + i) / 2;
3678
byte_addr = (u_int16_t) (address + i) % 2;
3679
svalue = (u_int16_t *) value;
3680
if (! ath_hal_eepromRead(ah, eep_addr, svalue)) {
3681
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3682
"%s: Unable to read eeprom region \n", __func__);
3683
return AH_FALSE;
3684
}
3685
buffer[i] = (*svalue >> (8 * byte_addr)) & 0xff;
3686
}
3687
return AH_TRUE;
3688
}
3689
3690
HAL_BOOL
3691
ar9300_calibration_data_read_otp(struct ath_hal *ah, long address,
3692
u_int8_t *buffer, int many, HAL_BOOL is_wifi)
3693
{
3694
int i;
3695
unsigned long eep_addr;
3696
unsigned long byte_addr;
3697
u_int32_t svalue;
3698
3699
if (((address) < 0) || ((address + many) > 0x400)) {
3700
return AH_FALSE;
3701
}
3702
3703
for (i = 0; i < many; i++) {
3704
eep_addr = (u_int16_t) (address + i) / 4; /* otp is 4 bytes long???? */
3705
byte_addr = (u_int16_t) (address + i) % 4;
3706
if (!ar9300_otp_read(ah, eep_addr, &svalue, is_wifi)) {
3707
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3708
"%s: Unable to read otp region \n", __func__);
3709
return AH_FALSE;
3710
}
3711
buffer[i] = (svalue >> (8 * byte_addr)) & 0xff;
3712
}
3713
return AH_TRUE;
3714
}
3715
3716
#ifdef ATH_CAL_NAND_FLASH
3717
HAL_BOOL
3718
ar9300_calibration_data_read_nand(struct ath_hal *ah, long address,
3719
u_int8_t *buffer, int many)
3720
{
3721
int ret_len;
3722
int ret_val = 1;
3723
3724
/* Calling OS based API to read NAND */
3725
ret_val = OS_NAND_FLASH_READ(ATH_CAL_NAND_PARTITION, address, many, &ret_len, buffer);
3726
3727
return (ret_val ? AH_FALSE: AH_TRUE);
3728
}
3729
#endif
3730
3731
HAL_BOOL
3732
ar9300_calibration_data_read(struct ath_hal *ah, long address,
3733
u_int8_t *buffer, int many)
3734
{
3735
switch (AH9300(ah)->calibration_data_source) {
3736
case calibration_data_flash:
3737
return ar9300_calibration_data_read_flash(ah, address, buffer, many);
3738
case calibration_data_eeprom:
3739
return ar9300_calibration_data_read_eeprom(ah, address, buffer, many);
3740
case calibration_data_otp:
3741
return ar9300_calibration_data_read_otp(ah, address, buffer, many, 1);
3742
#ifdef ATH_CAL_NAND_FLASH
3743
case calibration_data_nand:
3744
return ar9300_calibration_data_read_nand(ah,address,buffer,many);
3745
#endif
3746
3747
}
3748
return AH_FALSE;
3749
}
3750
3751
3752
HAL_BOOL
3753
ar9300_calibration_data_read_array(struct ath_hal *ah, int address,
3754
u_int8_t *buffer, int many)
3755
{
3756
int it;
3757
3758
for (it = 0; it < many; it++) {
3759
(void)ar9300_calibration_data_read(ah, address - it, buffer + it, 1);
3760
}
3761
return AH_TRUE;
3762
}
3763
3764
3765
/*
3766
* the address where the first configuration block is written
3767
*/
3768
static const int base_address = 0x3ff; /* 1KB */
3769
static const int base_address_512 = 0x1ff; /* 512Bytes */
3770
3771
/*
3772
* the address where the NAND first configuration block is written
3773
*/
3774
#ifdef ATH_CAL_NAND_FLASH
3775
static const int base_address_nand = AR9300_FLASH_CAL_START_OFFSET;
3776
#endif
3777
3778
3779
/*
3780
* the lower limit on configuration data
3781
*/
3782
static const int low_limit = 0x040;
3783
3784
/*
3785
* returns size of the physical eeprom in bytes.
3786
* 1024 and 2048 are normal sizes.
3787
* 0 means there is no eeprom.
3788
*/
3789
int32_t
3790
ar9300_eeprom_size(struct ath_hal *ah)
3791
{
3792
u_int16_t data;
3793
/*
3794
* first we'll try for 4096 bytes eeprom
3795
*/
3796
if (ar9300_eeprom_read_word(ah, 2047, &data)) {
3797
if (data != 0) {
3798
return 4096;
3799
}
3800
}
3801
/*
3802
* then we'll try for 2048 bytes eeprom
3803
*/
3804
if (ar9300_eeprom_read_word(ah, 1023, &data)) {
3805
if (data != 0) {
3806
return 2048;
3807
}
3808
}
3809
/*
3810
* then we'll try for 1024 bytes eeprom
3811
*/
3812
if (ar9300_eeprom_read_word(ah, 511, &data)) {
3813
if (data != 0) {
3814
return 1024;
3815
}
3816
}
3817
return 0;
3818
}
3819
3820
/*
3821
* returns size of the physical otp in bytes.
3822
* 1024 and 2048 are normal sizes.
3823
* 0 means there is no eeprom.
3824
*/
3825
int32_t
3826
ar9300_otp_size(struct ath_hal *ah)
3827
{
3828
if (AR_SREV_POSEIDON(ah) || AR_SREV_HORNET(ah)) {
3829
return base_address_512+1;
3830
} else {
3831
return base_address+1;
3832
}
3833
}
3834
3835
3836
/*
3837
* find top of memory
3838
*/
3839
int
3840
ar9300_eeprom_base_address(struct ath_hal *ah)
3841
{
3842
int size;
3843
3844
if (AH9300(ah)->calibration_data_source == calibration_data_otp) {
3845
return ar9300_otp_size(ah)-1;
3846
}
3847
else
3848
{
3849
size = ar9300_eeprom_size(ah);
3850
if (size > 0) {
3851
return size - 1;
3852
} else {
3853
return ar9300_otp_size(ah)-1;
3854
}
3855
}
3856
}
3857
3858
int
3859
ar9300_eeprom_volatile(struct ath_hal *ah)
3860
{
3861
if (AH9300(ah)->calibration_data_source == calibration_data_otp) {
3862
return 0; /* no eeprom, use otp */
3863
} else {
3864
return 1; /* board has eeprom or flash */
3865
}
3866
}
3867
3868
/*
3869
* need to change this to look for the pcie data in the low parts of memory
3870
* cal data needs to stop a few locations above
3871
*/
3872
int
3873
ar9300_eeprom_low_limit(struct ath_hal *ah)
3874
{
3875
return low_limit;
3876
}
3877
3878
u_int16_t
3879
ar9300_compression_checksum(u_int8_t *data, int dsize)
3880
{
3881
int it;
3882
int checksum = 0;
3883
3884
for (it = 0; it < dsize; it++) {
3885
checksum += data[it];
3886
checksum &= 0xffff;
3887
}
3888
3889
return checksum;
3890
}
3891
3892
int
3893
ar9300_compression_header_unpack(u_int8_t *best, int *code, int *reference,
3894
int *length, int *major, int *minor)
3895
{
3896
unsigned long value[4];
3897
3898
value[0] = best[0];
3899
value[1] = best[1];
3900
value[2] = best[2];
3901
value[3] = best[3];
3902
*code = ((value[0] >> 5) & 0x0007);
3903
*reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020);
3904
*length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f);
3905
*major = (value[2] & 0x000f);
3906
*minor = (value[3] & 0x00ff);
3907
3908
return 4;
3909
}
3910
3911
3912
static HAL_BOOL
3913
ar9300_uncompress_block(struct ath_hal *ah, u_int8_t *mptr, int mdata_size,
3914
u_int8_t *block, int size)
3915
{
3916
int it;
3917
int spot;
3918
int offset;
3919
int length;
3920
3921
spot = 0;
3922
for (it = 0; it < size; it += (length + 2)) {
3923
offset = block[it];
3924
offset &= 0xff;
3925
spot += offset;
3926
length = block[it + 1];
3927
length &= 0xff;
3928
if (length > 0 && spot >= 0 && spot + length <= mdata_size) {
3929
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3930
"%s: Restore at %d: spot=%d offset=%d length=%d\n",
3931
__func__, it, spot, offset, length);
3932
OS_MEMCPY(&mptr[spot], &block[it + 2], length);
3933
spot += length;
3934
} else if (length > 0) {
3935
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3936
"%s: Bad restore at %d: spot=%d offset=%d length=%d\n",
3937
__func__, it, spot, offset, length);
3938
return AH_FALSE;
3939
}
3940
}
3941
return AH_TRUE;
3942
}
3943
3944
static int
3945
ar9300_eeprom_restore_internal_address(struct ath_hal *ah,
3946
ar9300_eeprom_t *mptr, int mdata_size, int cptr, u_int8_t blank)
3947
{
3948
u_int8_t word[MOUTPUT];
3949
ar9300_eeprom_t *dptr; /* was uint8 */
3950
int code;
3951
int reference, length, major, minor;
3952
int osize;
3953
int it;
3954
int restored;
3955
u_int16_t checksum, mchecksum;
3956
3957
restored = 0;
3958
for (it = 0; it < MSTATE; it++) {
3959
(void) ar9300_calibration_data_read_array(
3960
ah, cptr, word, compression_header_length);
3961
if (word[0] == blank && word[1] == blank && word[2] == blank && word[3] == blank)
3962
{
3963
break;
3964
}
3965
ar9300_compression_header_unpack(
3966
word, &code, &reference, &length, &major, &minor);
3967
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3968
"%s: Found block at %x: "
3969
"code=%d ref=%d length=%d major=%d minor=%d\n",
3970
__func__, cptr, code, reference, length, major, minor);
3971
#ifdef DONTUSE
3972
if (length >= 1024) {
3973
HALDEBUG(ah, HAL_DEBUG_EEPROM, "%s: Skipping bad header\n", __func__);
3974
cptr -= compression_header_length;
3975
continue;
3976
}
3977
#endif
3978
osize = length;
3979
(void) ar9300_calibration_data_read_array(
3980
ah, cptr, word,
3981
compression_header_length + osize + compression_checksum_length);
3982
checksum = ar9300_compression_checksum(
3983
&word[compression_header_length], length);
3984
mchecksum =
3985
word[compression_header_length + osize] |
3986
(word[compression_header_length + osize + 1] << 8);
3987
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3988
"%s: checksum %x %x\n", __func__, checksum, mchecksum);
3989
if (checksum == mchecksum) {
3990
switch (code) {
3991
case _compress_none:
3992
if (length != mdata_size) {
3993
HALDEBUG(ah, HAL_DEBUG_EEPROM,
3994
"%s: EEPROM structure size mismatch "
3995
"memory=%d eeprom=%d\n", __func__, mdata_size, length);
3996
return -1;
3997
}
3998
OS_MEMCPY((u_int8_t *)mptr,
3999
(u_int8_t *)(word + compression_header_length), length);
4000
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4001
"%s: restored eeprom %d: uncompressed, length %d\n",
4002
__func__, it, length);
4003
restored = 1;
4004
break;
4005
#ifdef UNUSED
4006
case _compress_lzma:
4007
if (reference == reference_current) {
4008
dptr = mptr;
4009
} else {
4010
dptr = (u_int8_t *)ar9300_eeprom_struct_default_find_by_id(
4011
reference);
4012
if (dptr == 0) {
4013
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4014
"%s: Can't find reference eeprom struct %d\n",
4015
__func__, reference);
4016
goto done;
4017
}
4018
}
4019
usize = -1;
4020
if (usize != mdata_size) {
4021
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4022
"%s: uncompressed data is wrong size %d %d\n",
4023
__func__, usize, mdata_size);
4024
goto done;
4025
}
4026
4027
for (ib = 0; ib < mdata_size; ib++) {
4028
mptr[ib] = dptr[ib] ^ word[ib + overhead];
4029
}
4030
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4031
"%s: restored eeprom %d: compressed, "
4032
"reference %d, length %d\n",
4033
__func__, it, reference, length);
4034
break;
4035
case _compress_pairs:
4036
if (reference == reference_current) {
4037
dptr = mptr;
4038
} else {
4039
dptr = (u_int8_t *)ar9300_eeprom_struct_default_find_by_id(
4040
reference);
4041
if (dptr == 0) {
4042
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4043
"%s: Can't find the reference "
4044
"eeprom structure %d\n",
4045
__func__, reference);
4046
goto done;
4047
}
4048
}
4049
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4050
"%s: restored eeprom %d: "
4051
"pairs, reference %d, length %d,\n",
4052
__func__, it, reference, length);
4053
break;
4054
#endif
4055
case _compress_block:
4056
if (reference == reference_current) {
4057
dptr = mptr;
4058
} else {
4059
dptr = ar9300_eeprom_struct_default_find_by_id(reference);
4060
if (dptr == 0) {
4061
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4062
"%s: cant find reference eeprom struct %d\n",
4063
__func__, reference);
4064
break;
4065
}
4066
OS_MEMCPY(mptr, dptr, mdata_size);
4067
}
4068
4069
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4070
"%s: restore eeprom %d: block, reference %d, length %d\n",
4071
__func__, it, reference, length);
4072
(void) ar9300_uncompress_block(ah,
4073
(u_int8_t *) mptr, mdata_size,
4074
(u_int8_t *) (word + compression_header_length), length);
4075
restored = 1;
4076
break;
4077
default:
4078
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4079
"%s: unknown compression code %d\n", __func__, code);
4080
break;
4081
}
4082
} else {
4083
HALDEBUG(ah, HAL_DEBUG_EEPROM,
4084
"%s: skipping block with bad checksum\n", __func__);
4085
}
4086
cptr -= compression_header_length + osize + compression_checksum_length;
4087
}
4088
4089
if (!restored) {
4090
cptr = -1;
4091
}
4092
return cptr;
4093
}
4094
4095
static int
4096
ar9300_eeprom_restore_from_dram(struct ath_hal *ah, ar9300_eeprom_t *mptr,
4097
int mdata_size)
4098
{
4099
struct ath_hal_9300 *ahp = AH9300(ah);
4100
#if !defined(USE_PLATFORM_FRAMEWORK)
4101
char *cal_ptr;
4102
#endif
4103
4104
HALASSERT(mdata_size > 0);
4105
4106
/* if cal_in_flash is AH_TRUE, the address sent by LMAC to HAL
4107
(i.e. ah->ah_st) is corresponding to Flash. so return from
4108
here if ar9300_eep_data_in_flash(ah) returns AH_TRUE */
4109
if(ar9300_eep_data_in_flash(ah))
4110
return -1;
4111
4112
#if 0
4113
/* check if LMAC sent DRAM address is valid */
4114
if (!(uintptr_t)(AH_PRIVATE(ah)->ah_st)) {
4115
return -1;
4116
}
4117
#endif
4118
4119
/* When calibration data is from host, Host will copy the
4120
compressed data to the predefined DRAM location saved at ah->ah_st */
4121
#if 0
4122
ath_hal_printf(ah, "Restoring Cal data from DRAM\n");
4123
ahp->ah_cal_mem = OS_REMAP((uintptr_t)(AH_PRIVATE(ah)->ah_st),
4124
HOST_CALDATA_SIZE);
4125
#endif
4126
if (!ahp->ah_cal_mem)
4127
{
4128
HALDEBUG(ah, HAL_DEBUG_EEPROM,"%s: can't remap dram region\n", __func__);
4129
return -1;
4130
}
4131
#if !defined(USE_PLATFORM_FRAMEWORK)
4132
cal_ptr = &((char *)(ahp->ah_cal_mem))[AR9300_FLASH_CAL_START_OFFSET];
4133
OS_MEMCPY(mptr, cal_ptr, mdata_size);
4134
#else
4135
OS_MEMCPY(mptr, ahp->ah_cal_mem, mdata_size);
4136
#endif
4137
4138
if (mptr->eeprom_version == 0xff ||
4139
mptr->template_version == 0xff ||
4140
mptr->eeprom_version == 0 ||
4141
mptr->template_version == 0)
4142
{
4143
/* The board is uncalibrated */
4144
return -1;
4145
}
4146
if (mptr->eeprom_version != 0x2)
4147
{
4148
return -1;
4149
}
4150
4151
return mdata_size;
4152
4153
}
4154
4155
static int
4156
ar9300_eeprom_restore_from_flash(struct ath_hal *ah, ar9300_eeprom_t *mptr,
4157
int mdata_size)
4158
{
4159
struct ath_hal_9300 *ahp = AH9300(ah);
4160
char *cal_ptr;
4161
4162
HALASSERT(mdata_size > 0);
4163
4164
if (!ahp->ah_cal_mem) {
4165
return -1;
4166
}
4167
4168
ath_hal_printf(ah, "Restoring Cal data from Flash\n");
4169
/*
4170
* When calibration data is saved in flash, read
4171
* uncompressed eeprom structure from flash and return
4172
*/
4173
cal_ptr = &((char *)(ahp->ah_cal_mem))[AR9300_FLASH_CAL_START_OFFSET];
4174
OS_MEMCPY(mptr, cal_ptr, mdata_size);
4175
#if 0
4176
ar9300_swap_eeprom((ar9300_eeprom_t *)mptr); DONE IN ar9300_restore()
4177
#endif
4178
if (mptr->eeprom_version == 0xff ||
4179
mptr->template_version == 0xff ||
4180
mptr->eeprom_version == 0 ||
4181
mptr->template_version == 0)
4182
{
4183
/* The board is uncalibrated */
4184
return -1;
4185
}
4186
if (mptr->eeprom_version != 0x2)
4187
{
4188
return -1;
4189
}
4190
return mdata_size;
4191
}
4192
4193
/*
4194
* Read the configuration data from the storage. We try the order with:
4195
* EEPROM, Flash, OTP. If all of above failed, use the default template.
4196
* The data can be put in any specified memory buffer.
4197
*
4198
* Returns -1 on error.
4199
* Returns address of next memory location on success.
4200
*/
4201
int
4202
ar9300_eeprom_restore_internal(struct ath_hal *ah, ar9300_eeprom_t *mptr,
4203
int mdata_size)
4204
{
4205
int nptr;
4206
4207
nptr = -1;
4208
4209
if ((AH9300(ah)->calibration_data_try == calibration_data_none ||
4210
AH9300(ah)->calibration_data_try == calibration_data_dram) &&
4211
AH9300(ah)->try_dram && nptr < 0)
4212
{
4213
ath_hal_printf(ah, "Restoring Cal data from DRAM\n");
4214
AH9300(ah)->calibration_data_source = calibration_data_dram;
4215
AH9300(ah)->calibration_data_source_address = 0;
4216
nptr = ar9300_eeprom_restore_from_dram(ah, mptr, mdata_size);
4217
if (nptr < 0) {
4218
AH9300(ah)->calibration_data_source = calibration_data_none;
4219
AH9300(ah)->calibration_data_source_address = 0;
4220
}
4221
}
4222
4223
if ((AH9300(ah)->calibration_data_try == calibration_data_none ||
4224
AH9300(ah)->calibration_data_try == calibration_data_eeprom) &&
4225
AH9300(ah)->try_eeprom && nptr < 0)
4226
{
4227
/*
4228
* need to look at highest eeprom address as well as at
4229
* base_address=0x3ff where we used to write the data
4230
*/
4231
ath_hal_printf(ah, "Restoring Cal data from EEPROM\n");
4232
AH9300(ah)->calibration_data_source = calibration_data_eeprom;
4233
if (AH9300(ah)->calibration_data_try_address != 0) {
4234
AH9300(ah)->calibration_data_source_address =
4235
AH9300(ah)->calibration_data_try_address;
4236
nptr = ar9300_eeprom_restore_internal_address(
4237
ah, mptr, mdata_size,
4238
AH9300(ah)->calibration_data_source_address, 0xff);
4239
} else {
4240
AH9300(ah)->calibration_data_source_address =
4241
ar9300_eeprom_base_address(ah);
4242
nptr = ar9300_eeprom_restore_internal_address(
4243
ah, mptr, mdata_size,
4244
AH9300(ah)->calibration_data_source_address, 0xff);
4245
if (nptr < 0 &&
4246
AH9300(ah)->calibration_data_source_address != base_address)
4247
{
4248
AH9300(ah)->calibration_data_source_address = base_address;
4249
nptr = ar9300_eeprom_restore_internal_address(
4250
ah, mptr, mdata_size,
4251
AH9300(ah)->calibration_data_source_address, 0xff);
4252
}
4253
}
4254
if (nptr < 0) {
4255
AH9300(ah)->calibration_data_source = calibration_data_none;
4256
AH9300(ah)->calibration_data_source_address = 0;
4257
}
4258
}
4259
4260
/*
4261
* ##### should be an ifdef test for any AP usage,
4262
* either in driver or in nart
4263
*/
4264
if ((AH9300(ah)->calibration_data_try == calibration_data_none ||
4265
AH9300(ah)->calibration_data_try == calibration_data_flash) &&
4266
AH9300(ah)->try_flash && nptr < 0)
4267
{
4268
ath_hal_printf(ah, "Restoring Cal data from Flash\n");
4269
AH9300(ah)->calibration_data_source = calibration_data_flash;
4270
/* how are we supposed to set this for flash? */
4271
AH9300(ah)->calibration_data_source_address = 0;
4272
nptr = ar9300_eeprom_restore_from_flash(ah, mptr, mdata_size);
4273
if (nptr < 0) {
4274
AH9300(ah)->calibration_data_source = calibration_data_none;
4275
AH9300(ah)->calibration_data_source_address = 0;
4276
}
4277
}
4278
4279
if ((AH9300(ah)->calibration_data_try == calibration_data_none ||
4280
AH9300(ah)->calibration_data_try == calibration_data_otp) &&
4281
AH9300(ah)->try_otp && nptr < 0)
4282
{
4283
ath_hal_printf(ah, "Restoring Cal data from OTP\n");
4284
AH9300(ah)->calibration_data_source = calibration_data_otp;
4285
if (AH9300(ah)->calibration_data_try_address != 0) {
4286
AH9300(ah)->calibration_data_source_address =
4287
AH9300(ah)->calibration_data_try_address;
4288
} else {
4289
AH9300(ah)->calibration_data_source_address =
4290
ar9300_eeprom_base_address(ah);
4291
}
4292
nptr = ar9300_eeprom_restore_internal_address(
4293
ah, mptr, mdata_size, AH9300(ah)->calibration_data_source_address, 0);
4294
if (nptr < 0) {
4295
AH9300(ah)->calibration_data_source = calibration_data_none;
4296
AH9300(ah)->calibration_data_source_address = 0;
4297
}
4298
}
4299
4300
#ifdef ATH_CAL_NAND_FLASH
4301
if ((AH9300(ah)->calibration_data_try == calibration_data_none ||
4302
AH9300(ah)->calibration_data_try == calibration_data_nand) &&
4303
AH9300(ah)->try_nand && nptr < 0)
4304
{
4305
AH9300(ah)->calibration_data_source = calibration_data_nand;
4306
AH9300(ah)->calibration_data_source_address = ((unsigned int)(AH_PRIVATE(ah)->ah_st)) + base_address_nand;
4307
if(ar9300_calibration_data_read(
4308
ah, AH9300(ah)->calibration_data_source_address,
4309
(u_int8_t *)mptr, mdata_size) == AH_TRUE)
4310
{
4311
nptr = mdata_size;
4312
}
4313
/*nptr=ar9300EepromRestoreInternalAddress(ah, mptr, mdataSize, CalibrationDataSourceAddress);*/
4314
if(nptr < 0)
4315
{
4316
AH9300(ah)->calibration_data_source = calibration_data_none;
4317
AH9300(ah)->calibration_data_source_address = 0;
4318
}
4319
}
4320
#endif
4321
if (nptr < 0) {
4322
ath_hal_printf(ah, "%s[%d] No valid CAL, calling default template\n",
4323
__func__, __LINE__);
4324
nptr = ar9300_eeprom_restore_something(ah, mptr, mdata_size);
4325
}
4326
4327
return nptr;
4328
}
4329
4330
/******************************************************************************/
4331
/*!
4332
** \brief Eeprom Swapping Function
4333
**
4334
** This function will swap the contents of the "longer" EEPROM data items
4335
** to ensure they are consistent with the endian requirements for the platform
4336
** they are being compiled for
4337
**
4338
** \param eh Pointer to the EEPROM data structure
4339
** \return N/A
4340
*/
4341
#if AH_BYTE_ORDER == AH_BIG_ENDIAN
4342
void
4343
ar9300_swap_eeprom(ar9300_eeprom_t *eep)
4344
{
4345
u_int32_t dword;
4346
u_int16_t word;
4347
int i;
4348
4349
word = __bswap16(eep->base_eep_header.reg_dmn[0]);
4350
eep->base_eep_header.reg_dmn[0] = word;
4351
4352
word = __bswap16(eep->base_eep_header.reg_dmn[1]);
4353
eep->base_eep_header.reg_dmn[1] = word;
4354
4355
dword = __bswap32(eep->base_eep_header.swreg);
4356
eep->base_eep_header.swreg = dword;
4357
4358
dword = __bswap32(eep->modal_header_2g.ant_ctrl_common);
4359
eep->modal_header_2g.ant_ctrl_common = dword;
4360
4361
dword = __bswap32(eep->modal_header_2g.ant_ctrl_common2);
4362
eep->modal_header_2g.ant_ctrl_common2 = dword;
4363
4364
dword = __bswap32(eep->modal_header_2g.paprd_rate_mask_ht20);
4365
eep->modal_header_2g.paprd_rate_mask_ht20 = dword;
4366
4367
dword = __bswap32(eep->modal_header_2g.paprd_rate_mask_ht40);
4368
eep->modal_header_2g.paprd_rate_mask_ht40 = dword;
4369
4370
dword = __bswap32(eep->modal_header_5g.ant_ctrl_common);
4371
eep->modal_header_5g.ant_ctrl_common = dword;
4372
4373
dword = __bswap32(eep->modal_header_5g.ant_ctrl_common2);
4374
eep->modal_header_5g.ant_ctrl_common2 = dword;
4375
4376
dword = __bswap32(eep->modal_header_5g.paprd_rate_mask_ht20);
4377
eep->modal_header_5g.paprd_rate_mask_ht20 = dword;
4378
4379
dword = __bswap32(eep->modal_header_5g.paprd_rate_mask_ht40);
4380
eep->modal_header_5g.paprd_rate_mask_ht40 = dword;
4381
4382
for (i = 0; i < OSPREY_MAX_CHAINS; i++) {
4383
word = __bswap16(eep->modal_header_2g.ant_ctrl_chain[i]);
4384
eep->modal_header_2g.ant_ctrl_chain[i] = word;
4385
4386
word = __bswap16(eep->modal_header_5g.ant_ctrl_chain[i]);
4387
eep->modal_header_5g.ant_ctrl_chain[i] = word;
4388
}
4389
}
4390
4391
void ar9300_eeprom_template_swap(void)
4392
{
4393
int it;
4394
ar9300_eeprom_t *dptr;
4395
4396
for (it = 0; it < ARRAY_LENGTH(default9300); it++) {
4397
dptr = ar9300_eeprom_struct_default(it);
4398
if (dptr != 0) {
4399
ar9300_swap_eeprom(dptr);
4400
}
4401
}
4402
}
4403
#endif
4404
4405
4406
/*
4407
* Restore the configuration structure by reading the eeprom.
4408
* This function destroys any existing in-memory structure content.
4409
*/
4410
HAL_BOOL
4411
ar9300_eeprom_restore(struct ath_hal *ah)
4412
{
4413
struct ath_hal_9300 *ahp = AH9300(ah);
4414
ar9300_eeprom_t *mptr;
4415
int mdata_size;
4416
HAL_BOOL status = AH_FALSE;
4417
4418
mptr = &ahp->ah_eeprom;
4419
mdata_size = ar9300_eeprom_struct_size();
4420
4421
if (mptr != 0 && mdata_size > 0) {
4422
#if AH_BYTE_ORDER == AH_BIG_ENDIAN
4423
ar9300_eeprom_template_swap();
4424
ar9300_swap_eeprom(mptr);
4425
#endif
4426
/*
4427
* At this point, mptr points to the eeprom data structure
4428
* in its "default" state. If this is big endian, swap the
4429
* data structures back to "little endian" form.
4430
*/
4431
if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0) {
4432
status = AH_TRUE;
4433
}
4434
4435
#if AH_BYTE_ORDER == AH_BIG_ENDIAN
4436
/* Second Swap, back to Big Endian */
4437
ar9300_eeprom_template_swap();
4438
ar9300_swap_eeprom(mptr);
4439
#endif
4440
4441
}
4442
ahp->ah_2g_paprd_rate_mask_ht40 =
4443
mptr->modal_header_2g.paprd_rate_mask_ht40;
4444
ahp->ah_2g_paprd_rate_mask_ht20 =
4445
mptr->modal_header_2g.paprd_rate_mask_ht20;
4446
ahp->ah_5g_paprd_rate_mask_ht40 =
4447
mptr->modal_header_5g.paprd_rate_mask_ht40;
4448
ahp->ah_5g_paprd_rate_mask_ht20 =
4449
mptr->modal_header_5g.paprd_rate_mask_ht20;
4450
return status;
4451
}
4452
4453
int32_t ar9300_thermometer_get(struct ath_hal *ah)
4454
{
4455
struct ath_hal_9300 *ahp = AH9300(ah);
4456
int thermometer;
4457
thermometer =
4458
(ahp->ah_eeprom.base_eep_header.misc_configuration >> 1) & 0x3;
4459
thermometer--;
4460
return thermometer;
4461
}
4462
4463
HAL_BOOL ar9300_thermometer_apply(struct ath_hal *ah)
4464
{
4465
int thermometer = ar9300_thermometer_get(ah);
4466
4467
/* ch0_RXTX4 */
4468
/*#define AR_PHY_65NM_CH0_RXTX4 AR_PHY_65NM(ch0_RXTX4)*/
4469
#define AR_PHY_65NM_CH1_RXTX4 AR_PHY_65NM(ch1_RXTX4)
4470
#define AR_PHY_65NM_CH2_RXTX4 AR_PHY_65NM(ch2_RXTX4)
4471
/*#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000*/
4472
/*#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28*/
4473
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR_S 29
4474
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR \
4475
(0x1<<AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR_S)
4476
4477
if (thermometer < 0) {
4478
OS_REG_RMW_FIELD(ah,
4479
AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0);
4480
if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
4481
OS_REG_RMW_FIELD(ah,
4482
AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0);
4483
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) {
4484
OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
4485
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 0);
4486
}
4487
}
4488
OS_REG_RMW_FIELD(ah,
4489
AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4490
if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
4491
OS_REG_RMW_FIELD(ah,
4492
AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4493
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) {
4494
OS_REG_RMW_FIELD(ah,
4495
AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4496
}
4497
}
4498
} else {
4499
OS_REG_RMW_FIELD(ah,
4500
AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1);
4501
if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
4502
OS_REG_RMW_FIELD(ah,
4503
AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1);
4504
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) {
4505
OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
4506
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, 1);
4507
}
4508
}
4509
if (thermometer == 0) {
4510
OS_REG_RMW_FIELD(ah,
4511
AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1);
4512
if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
4513
OS_REG_RMW_FIELD(ah,
4514
AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4515
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) {
4516
OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
4517
AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4518
}
4519
}
4520
} else if (thermometer == 1) {
4521
OS_REG_RMW_FIELD(ah,
4522
AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4523
if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
4524
OS_REG_RMW_FIELD(ah,
4525
AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1);
4526
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) {
4527
OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
4528
AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4529
}
4530
}
4531
} else if (thermometer == 2) {
4532
OS_REG_RMW_FIELD(ah,
4533
AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4534
if (!AR_SREV_HORNET(ah) && !AR_SREV_POSEIDON(ah)) {
4535
OS_REG_RMW_FIELD(ah,
4536
AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_CH0_RXTX4_THERM_ON, 0);
4537
if (!AR_SREV_WASP(ah) && !AR_SREV_JUPITER(ah) && !AR_SREV_HONEYBEE(ah) ) {
4538
OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
4539
AR_PHY_65NM_CH0_RXTX4_THERM_ON, 1);
4540
}
4541
}
4542
}
4543
}
4544
return AH_TRUE;
4545
}
4546
4547
static int32_t ar9300_tuning_caps_params_get(struct ath_hal *ah)
4548
{
4549
int tuning_caps_params;
4550
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
4551
tuning_caps_params = eep->base_eep_header.params_for_tuning_caps[0];
4552
return tuning_caps_params;
4553
}
4554
4555
/*
4556
* Read the tuning caps params from eeprom and set to correct register.
4557
* To regulation the frequency accuracy.
4558
*/
4559
HAL_BOOL ar9300_tuning_caps_apply(struct ath_hal *ah)
4560
{
4561
int tuning_caps_params;
4562
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
4563
tuning_caps_params = ar9300_tuning_caps_params_get(ah);
4564
if ((eep->base_eep_header.feature_enable & 0x40) >> 6) {
4565
tuning_caps_params &= 0x7f;
4566
4567
if (AR_SREV_POSEIDON(ah) || AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) {
4568
return true;
4569
} else if (AR_SREV_HORNET(ah)) {
4570
OS_REG_RMW_FIELD(ah,
4571
AR_HORNET_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC,
4572
tuning_caps_params);
4573
OS_REG_RMW_FIELD(ah,
4574
AR_HORNET_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC,
4575
tuning_caps_params);
4576
} else if (AR_SREV_SCORPION(ah)) {
4577
OS_REG_RMW_FIELD(ah,
4578
AR_SCORPION_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC,
4579
tuning_caps_params);
4580
OS_REG_RMW_FIELD(ah,
4581
AR_SCORPION_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC,
4582
tuning_caps_params);
4583
} else {
4584
OS_REG_RMW_FIELD(ah,
4585
AR_OSPREY_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPINDAC,
4586
tuning_caps_params);
4587
OS_REG_RMW_FIELD(ah,
4588
AR_OSPREY_CH0_XTAL, AR_OSPREY_CHO_XTAL_CAPOUTDAC,
4589
tuning_caps_params);
4590
}
4591
4592
}
4593
return AH_TRUE;
4594
}
4595
4596
/*
4597
* Read the tx_frame_to_xpa_on param from eeprom and apply the value to
4598
* correct register.
4599
*/
4600
HAL_BOOL ar9300_xpa_timing_control_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
4601
{
4602
u_int8_t xpa_timing_control;
4603
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
4604
if ((eep->base_eep_header.feature_enable & 0x80) >> 7) {
4605
if (AR_SREV_OSPREY(ah) || AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) {
4606
if (is_2ghz) {
4607
xpa_timing_control = eep->modal_header_2g.tx_frame_to_xpa_on;
4608
OS_REG_RMW_FIELD(ah,
4609
AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON,
4610
xpa_timing_control);
4611
} else {
4612
xpa_timing_control = eep->modal_header_5g.tx_frame_to_xpa_on;
4613
OS_REG_RMW_FIELD(ah,
4614
AR_PHY_XPA_TIMING_CTL, AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON,
4615
xpa_timing_control);
4616
}
4617
}
4618
}
4619
return AH_TRUE;
4620
}
4621
4622
4623
/*
4624
* Read the xLNA_bias_strength param from eeprom and apply the value to
4625
* correct register.
4626
*/
4627
HAL_BOOL ar9300_x_lNA_bias_strength_apply(struct ath_hal *ah, HAL_BOOL is_2ghz)
4628
{
4629
u_int8_t x_lNABias;
4630
u_int32_t value = 0;
4631
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
4632
4633
if ((eep->base_eep_header.misc_configuration & 0x40) >> 6) {
4634
if (AR_SREV_OSPREY(ah)) {
4635
if (is_2ghz) {
4636
x_lNABias = eep->modal_header_2g.xLNA_bias_strength;
4637
} else {
4638
x_lNABias = eep->modal_header_5g.xLNA_bias_strength;
4639
}
4640
value = x_lNABias & ( 0x03 ); // bit0,1 for chain0
4641
OS_REG_RMW_FIELD(ah,
4642
AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value);
4643
value = (x_lNABias >> 2) & ( 0x03 ); // bit2,3 for chain1
4644
OS_REG_RMW_FIELD(ah,
4645
AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value);
4646
value = (x_lNABias >> 4) & ( 0x03 ); // bit4,5 for chain2
4647
OS_REG_RMW_FIELD(ah,
4648
AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS, value);
4649
}
4650
}
4651
return AH_TRUE;
4652
}
4653
4654
4655
/*
4656
* Read EEPROM header info and program the device for correct operation
4657
* given the channel value.
4658
*/
4659
HAL_BOOL
4660
ar9300_eeprom_set_board_values(struct ath_hal *ah, const struct ieee80211_channel *chan)
4661
{
4662
HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
4663
4664
ar9300_xpa_bias_level_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan));
4665
4666
ar9300_xpa_timing_control_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan));
4667
4668
ar9300_ant_ctrl_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan));
4669
ar9300_drive_strength_apply(ah);
4670
4671
ar9300_x_lNA_bias_strength_apply(ah, IEEE80211_IS_CHAN_2GHZ(chan));
4672
4673
/* wait for Poseidon internal regular turnning */
4674
/* for Hornet we move it before initPLL to avoid an access issue */
4675
/* Function not used when EMULATION. */
4676
if (!AR_SREV_HORNET(ah) && !AR_SREV_WASP(ah) && !AR_SREV_HONEYBEE(ah)) {
4677
ar9300_internal_regulator_apply(ah);
4678
}
4679
4680
ar9300_attenuation_apply(ah, ichan->channel);
4681
ar9300_quick_drop_apply(ah, ichan->channel);
4682
ar9300_thermometer_apply(ah);
4683
if(!AR_SREV_WASP(ah))
4684
{
4685
ar9300_tuning_caps_apply(ah);
4686
}
4687
4688
ar9300_tx_end_to_xpab_off_apply(ah, ichan->channel);
4689
4690
return AH_TRUE;
4691
}
4692
4693
u_int8_t *
4694
ar9300_eeprom_get_spur_chans_ptr(struct ath_hal *ah, HAL_BOOL is_2ghz)
4695
{
4696
ar9300_eeprom_t *eep = &AH9300(ah)->ah_eeprom;
4697
4698
if (is_2ghz) {
4699
return &(eep->modal_header_2g.spur_chans[0]);
4700
} else {
4701
return &(eep->modal_header_5g.spur_chans[0]);
4702
}
4703
}
4704
4705
static u_int8_t ar9300_eeprom_get_tx_gain_table_number_max(struct ath_hal *ah)
4706
{
4707
unsigned long tx_gain_table_max;
4708
tx_gain_table_max = OS_REG_READ_FIELD(ah,
4709
AR_PHY_TPC_7, AR_PHY_TPC_7_TX_GAIN_TABLE_MAX);
4710
return tx_gain_table_max;
4711
}
4712
4713
u_int8_t ar9300_eeprom_tx_gain_table_index_max_apply(struct ath_hal *ah, u_int16_t channel)
4714
{
4715
unsigned int index;
4716
ar9300_eeprom_t *ahp_Eeprom;
4717
struct ath_hal_9300 *ahp = AH9300(ah);
4718
4719
ahp_Eeprom = &ahp->ah_eeprom;
4720
4721
if (ahp_Eeprom->base_ext1.misc_enable == 0)
4722
return AH_FALSE;
4723
4724
if (channel < 4000)
4725
{
4726
index = ahp_Eeprom->modal_header_2g.tx_gain_cap;
4727
}
4728
else
4729
{
4730
index = ahp_Eeprom->modal_header_5g.tx_gain_cap;
4731
}
4732
4733
OS_REG_RMW_FIELD(ah,
4734
AR_PHY_TPC_7, AR_PHY_TPC_7_TX_GAIN_TABLE_MAX, index);
4735
return AH_TRUE;
4736
}
4737
4738
static u_int8_t ar9300_eeprom_get_pcdac_tx_gain_table_i(struct ath_hal *ah,
4739
int i, u_int8_t *pcdac)
4740
{
4741
unsigned long tx_gain;
4742
u_int8_t tx_gain_table_max;
4743
tx_gain_table_max = ar9300_eeprom_get_tx_gain_table_number_max(ah);
4744
if (i <= 0 || i > tx_gain_table_max) {
4745
*pcdac = 0;
4746
return AH_FALSE;
4747
}
4748
4749
tx_gain = OS_REG_READ(ah, AR_PHY_TXGAIN_TAB(1) + i * 4);
4750
*pcdac = ((tx_gain >> 24) & 0xff);
4751
return AH_TRUE;
4752
}
4753
4754
u_int8_t ar9300_eeprom_set_tx_gain_cap(struct ath_hal *ah,
4755
int *tx_gain_max)
4756
// pcdac read back from reg, read back value depends on reset 2GHz/5GHz ini
4757
// tx_gain_table, this function will be called twice after each
4758
// band's calibration.
4759
// after 2GHz cal, tx_gain_max[0] has 2GHz, calibration max txgain,
4760
// tx_gain_max[1]=-100
4761
// after 5GHz cal, tx_gain_max[0],tx_gain_max[1] have calibration
4762
// value for both band
4763
// reset is on 5GHz, reg reading from tx_gain_table is for 5GHz,
4764
// so program can't recalculate 2g.tx_gain_cap at this point.
4765
{
4766
int i = 0, ig, im = 0;
4767
u_int8_t pcdac = 0;
4768
u_int8_t tx_gain_table_max;
4769
ar9300_eeprom_t *ahp_Eeprom;
4770
struct ath_hal_9300 *ahp = AH9300(ah);
4771
4772
ahp_Eeprom = &ahp->ah_eeprom;
4773
4774
if (ahp_Eeprom->base_ext1.misc_enable == 0)
4775
return AH_FALSE;
4776
4777
tx_gain_table_max = ar9300_eeprom_get_tx_gain_table_number_max(ah);
4778
4779
for (i = 0; i < 2; i++) {
4780
if (tx_gain_max[i]>-100) { // -100 didn't cal that band.
4781
if ( i== 0) {
4782
if (tx_gain_max[1]>-100) {
4783
continue;
4784
// both band are calibrated, skip 2GHz 2g.tx_gain_cap reset
4785
}
4786
}
4787
for (ig = 1; ig <= tx_gain_table_max; ig++) {
4788
if (ah != 0 && ah->ah_reset != 0)
4789
{
4790
ar9300_eeprom_get_pcdac_tx_gain_table_i(ah, ig, &pcdac);
4791
if (pcdac >= tx_gain_max[i])
4792
break;
4793
}
4794
}
4795
if (ig+1 <= tx_gain_table_max) {
4796
if (pcdac == tx_gain_max[i])
4797
im = ig;
4798
else
4799
im = ig + 1;
4800
if (i == 0) {
4801
ahp_Eeprom->modal_header_2g.tx_gain_cap = im;
4802
} else {
4803
ahp_Eeprom->modal_header_5g.tx_gain_cap = im;
4804
}
4805
} else {
4806
if (i == 0) {
4807
ahp_Eeprom->modal_header_2g.tx_gain_cap = ig;
4808
} else {
4809
ahp_Eeprom->modal_header_5g.tx_gain_cap = ig;
4810
}
4811
}
4812
}
4813
}
4814
return AH_TRUE;
4815
}
4816
4817