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