19999SWang.Lin@Sun.COM /*
2*11729SWang.Lin@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
39999SWang.Lin@Sun.COM * Use is subject to license terms.
49999SWang.Lin@Sun.COM */
59999SWang.Lin@Sun.COM
69999SWang.Lin@Sun.COM /*
79999SWang.Lin@Sun.COM * Copyright (c) 2008 Atheros Communications Inc.
89999SWang.Lin@Sun.COM *
99999SWang.Lin@Sun.COM * Permission to use, copy, modify, and/or distribute this software for any
109999SWang.Lin@Sun.COM * purpose with or without fee is hereby granted, provided that the above
119999SWang.Lin@Sun.COM * copyright notice and this permission notice appear in all copies.
129999SWang.Lin@Sun.COM *
139999SWang.Lin@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
149999SWang.Lin@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
159999SWang.Lin@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
169999SWang.Lin@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
179999SWang.Lin@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
189999SWang.Lin@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
199999SWang.Lin@Sun.COM * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
209999SWang.Lin@Sun.COM */
219999SWang.Lin@Sun.COM
229999SWang.Lin@Sun.COM #include <sys/param.h>
239999SWang.Lin@Sun.COM #include <sys/types.h>
249999SWang.Lin@Sun.COM #include <sys/signal.h>
259999SWang.Lin@Sun.COM #include <sys/stream.h>
269999SWang.Lin@Sun.COM #include <sys/termio.h>
279999SWang.Lin@Sun.COM #include <sys/errno.h>
289999SWang.Lin@Sun.COM #include <sys/file.h>
299999SWang.Lin@Sun.COM #include <sys/cmn_err.h>
309999SWang.Lin@Sun.COM #include <sys/stropts.h>
319999SWang.Lin@Sun.COM #include <sys/strsubr.h>
329999SWang.Lin@Sun.COM #include <sys/strtty.h>
339999SWang.Lin@Sun.COM #include <sys/kbio.h>
349999SWang.Lin@Sun.COM #include <sys/cred.h>
359999SWang.Lin@Sun.COM #include <sys/stat.h>
369999SWang.Lin@Sun.COM #include <sys/consdev.h>
379999SWang.Lin@Sun.COM #include <sys/kmem.h>
389999SWang.Lin@Sun.COM #include <sys/modctl.h>
399999SWang.Lin@Sun.COM #include <sys/ddi.h>
409999SWang.Lin@Sun.COM #include <sys/sunddi.h>
419999SWang.Lin@Sun.COM #include <sys/pci.h>
429999SWang.Lin@Sun.COM #include <sys/errno.h>
439999SWang.Lin@Sun.COM #include <sys/gld.h>
449999SWang.Lin@Sun.COM #include <sys/dlpi.h>
459999SWang.Lin@Sun.COM #include <sys/ethernet.h>
469999SWang.Lin@Sun.COM #include <sys/list.h>
479999SWang.Lin@Sun.COM #include <sys/byteorder.h>
489999SWang.Lin@Sun.COM #include <sys/strsun.h>
499999SWang.Lin@Sun.COM #include <inet/common.h>
509999SWang.Lin@Sun.COM #include <inet/nd.h>
519999SWang.Lin@Sun.COM #include <inet/mi.h>
529999SWang.Lin@Sun.COM #include <inet/wifi_ioctl.h>
539999SWang.Lin@Sun.COM
549999SWang.Lin@Sun.COM #include "arn_core.h"
559999SWang.Lin@Sun.COM #include "arn_hw.h"
569999SWang.Lin@Sun.COM #include "arn_reg.h"
579999SWang.Lin@Sun.COM #include "arn_phy.h"
589999SWang.Lin@Sun.COM
599999SWang.Lin@Sun.COM static void
ath9k_hw_analog_shift_rmw(struct ath_hal * ah,uint32_t reg,uint32_t mask,uint32_t shift,uint32_t val)609999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(struct ath_hal *ah,
619999SWang.Lin@Sun.COM uint32_t reg, uint32_t mask,
629999SWang.Lin@Sun.COM uint32_t shift, uint32_t val)
639999SWang.Lin@Sun.COM {
649999SWang.Lin@Sun.COM uint32_t regVal;
659999SWang.Lin@Sun.COM
669999SWang.Lin@Sun.COM regVal = REG_READ(ah, reg) & ~mask;
679999SWang.Lin@Sun.COM regVal |= (val << shift) & mask;
689999SWang.Lin@Sun.COM
699999SWang.Lin@Sun.COM REG_WRITE(ah, reg, regVal);
709999SWang.Lin@Sun.COM
719999SWang.Lin@Sun.COM if (ah->ah_config.analog_shiftreg)
729999SWang.Lin@Sun.COM drv_usecwait(100);
739999SWang.Lin@Sun.COM }
749999SWang.Lin@Sun.COM
759999SWang.Lin@Sun.COM static inline uint16_t
ath9k_hw_fbin2freq(uint8_t fbin,boolean_t is2GHz)769999SWang.Lin@Sun.COM ath9k_hw_fbin2freq(uint8_t fbin, boolean_t is2GHz)
779999SWang.Lin@Sun.COM {
789999SWang.Lin@Sun.COM
799999SWang.Lin@Sun.COM if (fbin == AR5416_BCHAN_UNUSED)
809999SWang.Lin@Sun.COM return (fbin);
819999SWang.Lin@Sun.COM
829999SWang.Lin@Sun.COM return ((uint16_t)((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)));
839999SWang.Lin@Sun.COM }
849999SWang.Lin@Sun.COM
859999SWang.Lin@Sun.COM static inline int16_t
ath9k_hw_interpolate(uint16_t target,uint16_t srcLeft,uint16_t srcRight,int16_t targetLeft,int16_t targetRight)869999SWang.Lin@Sun.COM ath9k_hw_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
879999SWang.Lin@Sun.COM int16_t targetLeft, int16_t targetRight)
889999SWang.Lin@Sun.COM {
899999SWang.Lin@Sun.COM int16_t rv;
909999SWang.Lin@Sun.COM
919999SWang.Lin@Sun.COM if (srcRight == srcLeft) {
929999SWang.Lin@Sun.COM rv = targetLeft;
939999SWang.Lin@Sun.COM } else {
949999SWang.Lin@Sun.COM rv = (int16_t)(((target - srcLeft) * targetRight +
959999SWang.Lin@Sun.COM (srcRight - target) * targetLeft) /
969999SWang.Lin@Sun.COM (srcRight - srcLeft));
979999SWang.Lin@Sun.COM }
989999SWang.Lin@Sun.COM return (rv);
999999SWang.Lin@Sun.COM }
1009999SWang.Lin@Sun.COM
1019999SWang.Lin@Sun.COM static inline boolean_t
ath9k_hw_get_lower_upper_index(uint8_t target,uint8_t * pList,uint16_t listSize,uint16_t * indexL,uint16_t * indexR)1029999SWang.Lin@Sun.COM ath9k_hw_get_lower_upper_index(uint8_t target, uint8_t *pList,
1039999SWang.Lin@Sun.COM uint16_t listSize, uint16_t *indexL, uint16_t *indexR)
1049999SWang.Lin@Sun.COM {
1059999SWang.Lin@Sun.COM uint16_t i;
1069999SWang.Lin@Sun.COM
1079999SWang.Lin@Sun.COM if (target <= pList[0]) {
1089999SWang.Lin@Sun.COM *indexL = *indexR = 0;
1099999SWang.Lin@Sun.COM return (B_TRUE);
1109999SWang.Lin@Sun.COM }
1119999SWang.Lin@Sun.COM if (target >= pList[listSize - 1]) {
1129999SWang.Lin@Sun.COM *indexL = *indexR = (uint16_t)(listSize - 1);
1139999SWang.Lin@Sun.COM return (B_TRUE);
1149999SWang.Lin@Sun.COM }
1159999SWang.Lin@Sun.COM
1169999SWang.Lin@Sun.COM for (i = 0; i < listSize - 1; i++) {
1179999SWang.Lin@Sun.COM if (pList[i] == target) {
1189999SWang.Lin@Sun.COM *indexL = *indexR = i;
1199999SWang.Lin@Sun.COM return (B_TRUE);
1209999SWang.Lin@Sun.COM }
1219999SWang.Lin@Sun.COM if (target < pList[i + 1]) {
1229999SWang.Lin@Sun.COM *indexL = i;
1239999SWang.Lin@Sun.COM *indexR = (uint16_t)(i + 1);
1249999SWang.Lin@Sun.COM return (B_FALSE);
1259999SWang.Lin@Sun.COM }
1269999SWang.Lin@Sun.COM }
1279999SWang.Lin@Sun.COM return (B_FALSE);
1289999SWang.Lin@Sun.COM }
1299999SWang.Lin@Sun.COM
1309999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_eeprom_read(struct ath_hal * ah,uint32_t off,uint16_t * data)1319999SWang.Lin@Sun.COM ath9k_hw_eeprom_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
1329999SWang.Lin@Sun.COM {
1339999SWang.Lin@Sun.COM (void) REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
1349999SWang.Lin@Sun.COM
1359999SWang.Lin@Sun.COM if (!ath9k_hw_wait(ah, AR_EEPROM_STATUS_DATA,
1369999SWang.Lin@Sun.COM AR_EEPROM_STATUS_DATA_BUSY |
1379999SWang.Lin@Sun.COM AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
1389999SWang.Lin@Sun.COM return (B_FALSE);
1399999SWang.Lin@Sun.COM }
1409999SWang.Lin@Sun.COM
1419999SWang.Lin@Sun.COM *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
1429999SWang.Lin@Sun.COM AR_EEPROM_STATUS_DATA_VAL);
1439999SWang.Lin@Sun.COM
1449999SWang.Lin@Sun.COM return (B_TRUE);
1459999SWang.Lin@Sun.COM }
1469999SWang.Lin@Sun.COM
1479999SWang.Lin@Sun.COM /* ARGSUSED */
1489999SWang.Lin@Sun.COM static int
ath9k_hw_flash_map(struct ath_hal * ah)1499999SWang.Lin@Sun.COM ath9k_hw_flash_map(struct ath_hal *ah)
1509999SWang.Lin@Sun.COM {
1519999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "arn: ath9k_hw_flash_map(): "
1529999SWang.Lin@Sun.COM "using flash but eepom\n"));
1539999SWang.Lin@Sun.COM
1549999SWang.Lin@Sun.COM return (0);
1559999SWang.Lin@Sun.COM }
1569999SWang.Lin@Sun.COM
1579999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_flash_read(struct ath_hal * ah,uint32_t off,uint16_t * data)1589999SWang.Lin@Sun.COM ath9k_hw_flash_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
1599999SWang.Lin@Sun.COM {
1609999SWang.Lin@Sun.COM *data = FLASH_READ(ah, off);
1619999SWang.Lin@Sun.COM
1629999SWang.Lin@Sun.COM return (B_TRUE);
1639999SWang.Lin@Sun.COM }
1649999SWang.Lin@Sun.COM
1659999SWang.Lin@Sun.COM static inline boolean_t
ath9k_hw_nvram_read(struct ath_hal * ah,uint32_t off,uint16_t * data)1669999SWang.Lin@Sun.COM ath9k_hw_nvram_read(struct ath_hal *ah, uint32_t off, uint16_t *data)
1679999SWang.Lin@Sun.COM {
1689999SWang.Lin@Sun.COM if (ath9k_hw_use_flash(ah))
1699999SWang.Lin@Sun.COM return (ath9k_hw_flash_read(ah, off, data));
1709999SWang.Lin@Sun.COM else
1719999SWang.Lin@Sun.COM return (ath9k_hw_eeprom_read(ah, off, data));
1729999SWang.Lin@Sun.COM }
1739999SWang.Lin@Sun.COM
1749999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_fill_4k_eeprom(struct ath_hal * ah)1759999SWang.Lin@Sun.COM ath9k_hw_fill_4k_eeprom(struct ath_hal *ah)
1769999SWang.Lin@Sun.COM {
1779999SWang.Lin@Sun.COM #define SIZE_EEPROM_4K (sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t))
1789999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
1799999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
1809999SWang.Lin@Sun.COM uint16_t *eep_data;
1819999SWang.Lin@Sun.COM int addr, eep_start_loc = 0;
1829999SWang.Lin@Sun.COM
1839999SWang.Lin@Sun.COM eep_start_loc = 64;
1849999SWang.Lin@Sun.COM
1859999SWang.Lin@Sun.COM if (!ath9k_hw_use_flash(ah)) {
1869999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
1879999SWang.Lin@Sun.COM "Reading from EEPROM, not flash\n"));
1889999SWang.Lin@Sun.COM }
1899999SWang.Lin@Sun.COM
1909999SWang.Lin@Sun.COM eep_data = (uint16_t *)eep;
1919999SWang.Lin@Sun.COM
1929999SWang.Lin@Sun.COM for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
1939999SWang.Lin@Sun.COM if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
1949999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
1959999SWang.Lin@Sun.COM "Unable to read eeprom region \n"));
1969999SWang.Lin@Sun.COM return (B_FALSE);
1979999SWang.Lin@Sun.COM }
1989999SWang.Lin@Sun.COM eep_data++;
1999999SWang.Lin@Sun.COM }
2009999SWang.Lin@Sun.COM return (B_TRUE);
2019999SWang.Lin@Sun.COM #undef SIZE_EEPROM_4K
2029999SWang.Lin@Sun.COM }
2039999SWang.Lin@Sun.COM
2049999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_fill_def_eeprom(struct ath_hal * ah)2059999SWang.Lin@Sun.COM ath9k_hw_fill_def_eeprom(struct ath_hal *ah)
2069999SWang.Lin@Sun.COM {
2079999SWang.Lin@Sun.COM #define SIZE_EEPROM_DEF (sizeof (struct ar5416_eeprom_def) / sizeof (uint16_t))
2089999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
2099999SWang.Lin@Sun.COM struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
2109999SWang.Lin@Sun.COM uint16_t *eep_data;
2119999SWang.Lin@Sun.COM int addr, ar5416_eep_start_loc = 0x100;
2129999SWang.Lin@Sun.COM
2139999SWang.Lin@Sun.COM eep_data = (uint16_t *)eep;
2149999SWang.Lin@Sun.COM
2159999SWang.Lin@Sun.COM for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
2169999SWang.Lin@Sun.COM if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
2179999SWang.Lin@Sun.COM eep_data)) {
2189999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
2199999SWang.Lin@Sun.COM "Unable to read eeprom region\n"));
2209999SWang.Lin@Sun.COM return (B_FALSE);
2219999SWang.Lin@Sun.COM }
2229999SWang.Lin@Sun.COM eep_data++;
2239999SWang.Lin@Sun.COM }
2249999SWang.Lin@Sun.COM return (B_TRUE);
2259999SWang.Lin@Sun.COM #undef SIZE_EEPROM_DEF
2269999SWang.Lin@Sun.COM }
2279999SWang.Lin@Sun.COM
2289999SWang.Lin@Sun.COM static boolean_t (*ath9k_fill_eeprom[]) (struct ath_hal *) = {
2299999SWang.Lin@Sun.COM ath9k_hw_fill_def_eeprom,
2309999SWang.Lin@Sun.COM ath9k_hw_fill_4k_eeprom
2319999SWang.Lin@Sun.COM };
2329999SWang.Lin@Sun.COM
2339999SWang.Lin@Sun.COM static inline boolean_t
ath9k_hw_fill_eeprom(struct ath_hal * ah)2349999SWang.Lin@Sun.COM ath9k_hw_fill_eeprom(struct ath_hal *ah)
2359999SWang.Lin@Sun.COM {
2369999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
2379999SWang.Lin@Sun.COM
2389999SWang.Lin@Sun.COM return (ath9k_fill_eeprom[ahp->ah_eep_map](ah));
2399999SWang.Lin@Sun.COM }
2409999SWang.Lin@Sun.COM
2419999SWang.Lin@Sun.COM static int
ath9k_hw_check_def_eeprom(struct ath_hal * ah)2429999SWang.Lin@Sun.COM ath9k_hw_check_def_eeprom(struct ath_hal *ah)
2439999SWang.Lin@Sun.COM {
2449999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
2459999SWang.Lin@Sun.COM struct ar5416_eeprom_def *eep =
2469999SWang.Lin@Sun.COM (struct ar5416_eeprom_def *)&ahp->ah_eeprom.def;
2479999SWang.Lin@Sun.COM uint16_t *eepdata, temp, magic, magic2;
2489999SWang.Lin@Sun.COM uint32_t sum = 0, el;
2499999SWang.Lin@Sun.COM boolean_t need_swap = B_FALSE;
2509999SWang.Lin@Sun.COM int i, addr, size;
2519999SWang.Lin@Sun.COM if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
2529999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "arn: "
2539999SWang.Lin@Sun.COM "%s: Reading Magic # failed\n", __func__));
2549999SWang.Lin@Sun.COM return (B_FALSE);
2559999SWang.Lin@Sun.COM }
2569999SWang.Lin@Sun.COM
2579999SWang.Lin@Sun.COM if (!ath9k_hw_use_flash(ah)) {
2589999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "ath9k: "
2599999SWang.Lin@Sun.COM "%s: Read Magic = 0x%04X\n", __func__, magic));
2609999SWang.Lin@Sun.COM
2619999SWang.Lin@Sun.COM if (magic != AR5416_EEPROM_MAGIC) {
2629999SWang.Lin@Sun.COM magic2 = swab16(magic);
2639999SWang.Lin@Sun.COM
2649999SWang.Lin@Sun.COM if (magic2 == AR5416_EEPROM_MAGIC) {
2659999SWang.Lin@Sun.COM size = sizeof (struct ar5416_eeprom_def);
2669999SWang.Lin@Sun.COM need_swap = B_TRUE;
2679999SWang.Lin@Sun.COM eepdata = (uint16_t *)(&ahp->ah_eeprom);
2689999SWang.Lin@Sun.COM
2699999SWang.Lin@Sun.COM for (addr = 0; addr < size / sizeof (uint16_t);
2709999SWang.Lin@Sun.COM addr++) {
2719999SWang.Lin@Sun.COM temp = swab16(*eepdata);
2729999SWang.Lin@Sun.COM *eepdata = temp;
2739999SWang.Lin@Sun.COM eepdata++;
2749999SWang.Lin@Sun.COM
2759999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
2769999SWang.Lin@Sun.COM "0x%04X ", *eepdata));
2779999SWang.Lin@Sun.COM
2789999SWang.Lin@Sun.COM if (((addr + 1) % 6) == 0)
2799999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
2809999SWang.Lin@Sun.COM "arn: "
2819999SWang.Lin@Sun.COM "%s\n", __func__));
2829999SWang.Lin@Sun.COM }
2839999SWang.Lin@Sun.COM } else {
2849999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
2859999SWang.Lin@Sun.COM "Invalid EEPROM Magic. "
2869999SWang.Lin@Sun.COM "endianness mismatch.\n"));
2879999SWang.Lin@Sun.COM return (EINVAL);
2889999SWang.Lin@Sun.COM }
2899999SWang.Lin@Sun.COM }
2909999SWang.Lin@Sun.COM }
2919999SWang.Lin@Sun.COM
2929999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "need_swap = %s.\n",
2939999SWang.Lin@Sun.COM need_swap ? "TRUE" : "FALSE"));
2949999SWang.Lin@Sun.COM
2959999SWang.Lin@Sun.COM if (need_swap)
2969999SWang.Lin@Sun.COM el = swab16(ahp->ah_eeprom.def.baseEepHeader.length);
2979999SWang.Lin@Sun.COM else
2989999SWang.Lin@Sun.COM el = ahp->ah_eeprom.def.baseEepHeader.length;
2999999SWang.Lin@Sun.COM
3009999SWang.Lin@Sun.COM if (el > sizeof (struct ar5416_eeprom_def))
3019999SWang.Lin@Sun.COM el = sizeof (struct ar5416_eeprom_def) / sizeof (uint16_t);
3029999SWang.Lin@Sun.COM else
3039999SWang.Lin@Sun.COM el = el / sizeof (uint16_t);
3049999SWang.Lin@Sun.COM
3059999SWang.Lin@Sun.COM eepdata = (uint16_t *)(&ahp->ah_eeprom);
3069999SWang.Lin@Sun.COM
3079999SWang.Lin@Sun.COM for (i = 0; i < el; i++)
3089999SWang.Lin@Sun.COM sum ^= *eepdata++;
3099999SWang.Lin@Sun.COM
3109999SWang.Lin@Sun.COM if (need_swap) {
3119999SWang.Lin@Sun.COM uint32_t integer, j;
3129999SWang.Lin@Sun.COM uint16_t word;
3139999SWang.Lin@Sun.COM
3149999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
3159999SWang.Lin@Sun.COM "EEPROM Endianness is not native.. Changing \n"));
3169999SWang.Lin@Sun.COM
3179999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.length);
3189999SWang.Lin@Sun.COM eep->baseEepHeader.length = word;
3199999SWang.Lin@Sun.COM
3209999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.checksum);
3219999SWang.Lin@Sun.COM eep->baseEepHeader.checksum = word;
3229999SWang.Lin@Sun.COM
3239999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.version);
3249999SWang.Lin@Sun.COM eep->baseEepHeader.version = word;
3259999SWang.Lin@Sun.COM
3269999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.regDmn[0]);
3279999SWang.Lin@Sun.COM eep->baseEepHeader.regDmn[0] = word;
3289999SWang.Lin@Sun.COM
3299999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.regDmn[1]);
3309999SWang.Lin@Sun.COM eep->baseEepHeader.regDmn[1] = word;
3319999SWang.Lin@Sun.COM
3329999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.rfSilent);
3339999SWang.Lin@Sun.COM eep->baseEepHeader.rfSilent = word;
3349999SWang.Lin@Sun.COM
3359999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.blueToothOptions);
3369999SWang.Lin@Sun.COM eep->baseEepHeader.blueToothOptions = word;
3379999SWang.Lin@Sun.COM
3389999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.deviceCap);
3399999SWang.Lin@Sun.COM eep->baseEepHeader.deviceCap = word;
3409999SWang.Lin@Sun.COM
3419999SWang.Lin@Sun.COM for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
3429999SWang.Lin@Sun.COM struct modal_eep_header *pModal =
3439999SWang.Lin@Sun.COM &eep->modalHeader[j];
3449999SWang.Lin@Sun.COM integer = swab32(pModal->antCtrlCommon);
3459999SWang.Lin@Sun.COM pModal->antCtrlCommon = integer;
3469999SWang.Lin@Sun.COM
3479999SWang.Lin@Sun.COM for (i = 0; i < AR5416_MAX_CHAINS; i++) {
3489999SWang.Lin@Sun.COM integer = swab32(pModal->antCtrlChain[i]);
3499999SWang.Lin@Sun.COM pModal->antCtrlChain[i] = integer;
3509999SWang.Lin@Sun.COM }
3519999SWang.Lin@Sun.COM
3529999SWang.Lin@Sun.COM for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
3539999SWang.Lin@Sun.COM word = swab16(pModal->spurChans[i].spurChan);
3549999SWang.Lin@Sun.COM pModal->spurChans[i].spurChan = word;
3559999SWang.Lin@Sun.COM }
3569999SWang.Lin@Sun.COM }
3579999SWang.Lin@Sun.COM }
3589999SWang.Lin@Sun.COM
3599999SWang.Lin@Sun.COM if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER ||
3609999SWang.Lin@Sun.COM ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
3619999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
3629999SWang.Lin@Sun.COM "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
3639999SWang.Lin@Sun.COM sum, ar5416_get_eep_ver(ahp)));
3649999SWang.Lin@Sun.COM return (EINVAL);
3659999SWang.Lin@Sun.COM }
3669999SWang.Lin@Sun.COM
3679999SWang.Lin@Sun.COM return (0);
3689999SWang.Lin@Sun.COM }
3699999SWang.Lin@Sun.COM
3709999SWang.Lin@Sun.COM static int
ath9k_hw_check_4k_eeprom(struct ath_hal * ah)3719999SWang.Lin@Sun.COM ath9k_hw_check_4k_eeprom(struct ath_hal *ah)
3729999SWang.Lin@Sun.COM {
3739999SWang.Lin@Sun.COM #define EEPROM_4K_SIZE (sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t))
3749999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
3759999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *eep =
3769999SWang.Lin@Sun.COM (struct ar5416_eeprom_4k *)&ahp->ah_eeprom.map4k;
3779999SWang.Lin@Sun.COM uint16_t *eepdata, temp, magic, magic2;
3789999SWang.Lin@Sun.COM uint32_t sum = 0, el;
3799999SWang.Lin@Sun.COM boolean_t need_swap = B_FALSE;
3809999SWang.Lin@Sun.COM int i, addr;
3819999SWang.Lin@Sun.COM
3829999SWang.Lin@Sun.COM
3839999SWang.Lin@Sun.COM if (!ath9k_hw_use_flash(ah)) {
3849999SWang.Lin@Sun.COM
3859999SWang.Lin@Sun.COM if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
3869999SWang.Lin@Sun.COM &magic)) {
3879999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
3889999SWang.Lin@Sun.COM "Reading Magic # failed\n"));
3899999SWang.Lin@Sun.COM return (B_FALSE);
3909999SWang.Lin@Sun.COM }
3919999SWang.Lin@Sun.COM
3929999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
3939999SWang.Lin@Sun.COM "Read Magic = 0x%04X\n", magic));
3949999SWang.Lin@Sun.COM
3959999SWang.Lin@Sun.COM if (magic != AR5416_EEPROM_MAGIC) {
3969999SWang.Lin@Sun.COM magic2 = swab16(magic);
3979999SWang.Lin@Sun.COM
3989999SWang.Lin@Sun.COM if (magic2 == AR5416_EEPROM_MAGIC) {
3999999SWang.Lin@Sun.COM need_swap = B_TRUE;
4009999SWang.Lin@Sun.COM eepdata = (uint16_t *)(&ahp->ah_eeprom);
4019999SWang.Lin@Sun.COM
4029999SWang.Lin@Sun.COM for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
4039999SWang.Lin@Sun.COM temp = swab16(*eepdata);
4049999SWang.Lin@Sun.COM *eepdata = temp;
4059999SWang.Lin@Sun.COM eepdata++;
4069999SWang.Lin@Sun.COM
4079999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
4089999SWang.Lin@Sun.COM "0x%04X ", *eepdata));
4099999SWang.Lin@Sun.COM
4109999SWang.Lin@Sun.COM if (((addr + 1) % 6) == 0)
4119999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "\n"));
4129999SWang.Lin@Sun.COM }
4139999SWang.Lin@Sun.COM } else {
4149999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
4159999SWang.Lin@Sun.COM "Invalid EEPROM Magic. "
4169999SWang.Lin@Sun.COM "endianness mismatch.\n"));
4179999SWang.Lin@Sun.COM return (EINVAL);
4189999SWang.Lin@Sun.COM }
4199999SWang.Lin@Sun.COM }
4209999SWang.Lin@Sun.COM }
4219999SWang.Lin@Sun.COM
4229999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "need_swap = %s.\n",
4239999SWang.Lin@Sun.COM need_swap ? "True" : "False"));
4249999SWang.Lin@Sun.COM
4259999SWang.Lin@Sun.COM if (need_swap)
4269999SWang.Lin@Sun.COM el = swab16(ahp->ah_eeprom.map4k.baseEepHeader.length);
4279999SWang.Lin@Sun.COM else
4289999SWang.Lin@Sun.COM el = ahp->ah_eeprom.map4k.baseEepHeader.length;
4299999SWang.Lin@Sun.COM
4309999SWang.Lin@Sun.COM if (el > sizeof (struct ar5416_eeprom_def))
4319999SWang.Lin@Sun.COM el = sizeof (struct ar5416_eeprom_4k) / sizeof (uint16_t);
4329999SWang.Lin@Sun.COM else
4339999SWang.Lin@Sun.COM el = el / sizeof (uint16_t);
4349999SWang.Lin@Sun.COM
4359999SWang.Lin@Sun.COM eepdata = (uint16_t *)(&ahp->ah_eeprom);
4369999SWang.Lin@Sun.COM
4379999SWang.Lin@Sun.COM for (i = 0; i < el; i++)
4389999SWang.Lin@Sun.COM sum ^= *eepdata++;
4399999SWang.Lin@Sun.COM
4409999SWang.Lin@Sun.COM if (need_swap) {
4419999SWang.Lin@Sun.COM uint32_t integer;
4429999SWang.Lin@Sun.COM uint16_t word;
4439999SWang.Lin@Sun.COM
4449999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
4459999SWang.Lin@Sun.COM "EEPROM Endianness is not native.. Changing \n"));
4469999SWang.Lin@Sun.COM
4479999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.length);
4489999SWang.Lin@Sun.COM eep->baseEepHeader.length = word;
4499999SWang.Lin@Sun.COM
4509999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.checksum);
4519999SWang.Lin@Sun.COM eep->baseEepHeader.checksum = word;
4529999SWang.Lin@Sun.COM
4539999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.version);
4549999SWang.Lin@Sun.COM eep->baseEepHeader.version = word;
4559999SWang.Lin@Sun.COM
4569999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.regDmn[0]);
4579999SWang.Lin@Sun.COM eep->baseEepHeader.regDmn[0] = word;
4589999SWang.Lin@Sun.COM
4599999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.regDmn[1]);
4609999SWang.Lin@Sun.COM eep->baseEepHeader.regDmn[1] = word;
4619999SWang.Lin@Sun.COM
4629999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.rfSilent);
4639999SWang.Lin@Sun.COM eep->baseEepHeader.rfSilent = word;
4649999SWang.Lin@Sun.COM
4659999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.blueToothOptions);
4669999SWang.Lin@Sun.COM eep->baseEepHeader.blueToothOptions = word;
4679999SWang.Lin@Sun.COM
4689999SWang.Lin@Sun.COM word = swab16(eep->baseEepHeader.deviceCap);
4699999SWang.Lin@Sun.COM eep->baseEepHeader.deviceCap = word;
4709999SWang.Lin@Sun.COM
4719999SWang.Lin@Sun.COM integer = swab32(eep->modalHeader.antCtrlCommon);
4729999SWang.Lin@Sun.COM eep->modalHeader.antCtrlCommon = integer;
4739999SWang.Lin@Sun.COM
4749999SWang.Lin@Sun.COM for (i = 0; i < AR5416_MAX_CHAINS; i++) {
4759999SWang.Lin@Sun.COM integer = swab32(eep->modalHeader.antCtrlChain[i]);
4769999SWang.Lin@Sun.COM eep->modalHeader.antCtrlChain[i] = integer;
4779999SWang.Lin@Sun.COM }
4789999SWang.Lin@Sun.COM
4799999SWang.Lin@Sun.COM for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
4809999SWang.Lin@Sun.COM word = swab16(eep->modalHeader.spurChans[i].spurChan);
4819999SWang.Lin@Sun.COM eep->modalHeader.spurChans[i].spurChan = word;
4829999SWang.Lin@Sun.COM }
4839999SWang.Lin@Sun.COM }
4849999SWang.Lin@Sun.COM
4859999SWang.Lin@Sun.COM if (sum != 0xffff || ar5416_get_eep4k_ver(ahp) != AR5416_EEP_VER ||
4869999SWang.Lin@Sun.COM ar5416_get_eep4k_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
4879999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
4889999SWang.Lin@Sun.COM "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
4899999SWang.Lin@Sun.COM sum, ar5416_get_eep4k_ver(ahp)));
4909999SWang.Lin@Sun.COM return (EINVAL);
4919999SWang.Lin@Sun.COM }
4929999SWang.Lin@Sun.COM
4939999SWang.Lin@Sun.COM return (0);
4949999SWang.Lin@Sun.COM #undef EEPROM_4K_SIZE
4959999SWang.Lin@Sun.COM }
4969999SWang.Lin@Sun.COM
4979999SWang.Lin@Sun.COM static int
4989999SWang.Lin@Sun.COM (*ath9k_check_eeprom[]) (struct ath_hal *) = {
4999999SWang.Lin@Sun.COM ath9k_hw_check_def_eeprom,
5009999SWang.Lin@Sun.COM ath9k_hw_check_4k_eeprom
5019999SWang.Lin@Sun.COM };
5029999SWang.Lin@Sun.COM
5039999SWang.Lin@Sun.COM static inline int
ath9k_hw_check_eeprom(struct ath_hal * ah)5049999SWang.Lin@Sun.COM ath9k_hw_check_eeprom(struct ath_hal *ah)
5059999SWang.Lin@Sun.COM {
5069999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
5079999SWang.Lin@Sun.COM
5089999SWang.Lin@Sun.COM return (ath9k_check_eeprom[ahp->ah_eep_map](ah));
5099999SWang.Lin@Sun.COM }
5109999SWang.Lin@Sun.COM
5119999SWang.Lin@Sun.COM static inline boolean_t
ath9k_hw_fill_vpd_table(uint8_t pwrMin,uint8_t pwrMax,uint8_t * pPwrList,uint8_t * pVpdList,uint16_t numIntercepts,uint8_t * pRetVpdList)5129999SWang.Lin@Sun.COM ath9k_hw_fill_vpd_table(uint8_t pwrMin, uint8_t pwrMax, uint8_t *pPwrList,
5139999SWang.Lin@Sun.COM uint8_t *pVpdList, uint16_t numIntercepts, uint8_t *pRetVpdList)
5149999SWang.Lin@Sun.COM {
5159999SWang.Lin@Sun.COM uint16_t i, k;
5169999SWang.Lin@Sun.COM uint8_t currPwr = pwrMin;
5179999SWang.Lin@Sun.COM uint16_t idxL = 0, idxR = 0;
5189999SWang.Lin@Sun.COM
5199999SWang.Lin@Sun.COM for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
5209999SWang.Lin@Sun.COM (void) ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
5219999SWang.Lin@Sun.COM numIntercepts, &(idxL), &(idxR));
5229999SWang.Lin@Sun.COM if (idxR < 1)
5239999SWang.Lin@Sun.COM idxR = 1;
5249999SWang.Lin@Sun.COM if (idxL == numIntercepts - 1)
5259999SWang.Lin@Sun.COM idxL = (uint16_t)(numIntercepts - 2);
5269999SWang.Lin@Sun.COM if (pPwrList[idxL] == pPwrList[idxR])
5279999SWang.Lin@Sun.COM k = pVpdList[idxL];
5289999SWang.Lin@Sun.COM else
5299999SWang.Lin@Sun.COM k = (uint16_t)
5309999SWang.Lin@Sun.COM (((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
5319999SWang.Lin@Sun.COM (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
5329999SWang.Lin@Sun.COM (pPwrList[idxR] - pPwrList[idxL]));
5339999SWang.Lin@Sun.COM pRetVpdList[i] = (uint8_t)k;
5349999SWang.Lin@Sun.COM currPwr += 2;
5359999SWang.Lin@Sun.COM }
5369999SWang.Lin@Sun.COM
5379999SWang.Lin@Sun.COM return (B_TRUE);
5389999SWang.Lin@Sun.COM }
5399999SWang.Lin@Sun.COM
5409999SWang.Lin@Sun.COM static void
ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hal * ah,struct ath9k_channel * chan,struct cal_data_per_freq_4k * pRawDataSet,uint8_t * bChans,uint16_t availPiers,uint16_t tPdGainOverlap,int16_t * pMinCalPower,uint16_t * pPdGainBoundaries,uint8_t * pPDADCValues,uint16_t numXpdGains)5419999SWang.Lin@Sun.COM ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hal *ah,
5429999SWang.Lin@Sun.COM struct ath9k_channel *chan,
5439999SWang.Lin@Sun.COM struct cal_data_per_freq_4k *pRawDataSet,
5449999SWang.Lin@Sun.COM uint8_t *bChans, uint16_t availPiers,
5459999SWang.Lin@Sun.COM uint16_t tPdGainOverlap, int16_t *pMinCalPower,
5469999SWang.Lin@Sun.COM uint16_t *pPdGainBoundaries, uint8_t *pPDADCValues,
5479999SWang.Lin@Sun.COM uint16_t numXpdGains)
5489999SWang.Lin@Sun.COM {
5499999SWang.Lin@Sun.COM #define TMP_VAL_VPD_TABLE \
5509999SWang.Lin@Sun.COM ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
5519999SWang.Lin@Sun.COM int i, j, k;
5529999SWang.Lin@Sun.COM int16_t ss;
5539999SWang.Lin@Sun.COM uint16_t idxL = 0, idxR = 0, numPiers;
5549999SWang.Lin@Sun.COM static uint8_t vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
5559999SWang.Lin@Sun.COM [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
5569999SWang.Lin@Sun.COM static uint8_t vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
5579999SWang.Lin@Sun.COM [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
5589999SWang.Lin@Sun.COM static uint8_t vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
5599999SWang.Lin@Sun.COM [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
5609999SWang.Lin@Sun.COM
5619999SWang.Lin@Sun.COM uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR;
5629999SWang.Lin@Sun.COM uint8_t minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
5639999SWang.Lin@Sun.COM uint8_t maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
5649999SWang.Lin@Sun.COM int16_t vpdStep;
5659999SWang.Lin@Sun.COM int16_t tmpVal;
5669999SWang.Lin@Sun.COM uint16_t sizeCurrVpdTable, maxIndex, tgtIndex;
5679999SWang.Lin@Sun.COM boolean_t match;
5689999SWang.Lin@Sun.COM int16_t minDelta = 0;
5699999SWang.Lin@Sun.COM struct chan_centers centers;
5709999SWang.Lin@Sun.COM #define PD_GAIN_BOUNDARY_DEFAULT 58;
5719999SWang.Lin@Sun.COM
5729999SWang.Lin@Sun.COM ath9k_hw_get_channel_centers(ah, chan, ¢ers);
5739999SWang.Lin@Sun.COM
5749999SWang.Lin@Sun.COM for (numPiers = 0; numPiers < availPiers; numPiers++) {
5759999SWang.Lin@Sun.COM if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
5769999SWang.Lin@Sun.COM break;
5779999SWang.Lin@Sun.COM }
5789999SWang.Lin@Sun.COM
5799999SWang.Lin@Sun.COM match = ath9k_hw_get_lower_upper_index(
5809999SWang.Lin@Sun.COM (uint8_t)FREQ2FBIN(centers.synth_center,
5819999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan)), bChans, numPiers,
5829999SWang.Lin@Sun.COM &idxL, &idxR);
5839999SWang.Lin@Sun.COM
5849999SWang.Lin@Sun.COM if (match) {
5859999SWang.Lin@Sun.COM for (i = 0; i < numXpdGains; i++) {
5869999SWang.Lin@Sun.COM minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
5879999SWang.Lin@Sun.COM maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
5889999SWang.Lin@Sun.COM (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
5899999SWang.Lin@Sun.COM pRawDataSet[idxL].pwrPdg[i],
5909999SWang.Lin@Sun.COM pRawDataSet[idxL].vpdPdg[i],
5919999SWang.Lin@Sun.COM AR5416_EEP4K_PD_GAIN_ICEPTS,
5929999SWang.Lin@Sun.COM vpdTableI[i]);
5939999SWang.Lin@Sun.COM }
5949999SWang.Lin@Sun.COM } else {
5959999SWang.Lin@Sun.COM for (i = 0; i < numXpdGains; i++) {
5969999SWang.Lin@Sun.COM pVpdL = pRawDataSet[idxL].vpdPdg[i];
5979999SWang.Lin@Sun.COM pPwrL = pRawDataSet[idxL].pwrPdg[i];
5989999SWang.Lin@Sun.COM pVpdR = pRawDataSet[idxR].vpdPdg[i];
5999999SWang.Lin@Sun.COM pPwrR = pRawDataSet[idxR].pwrPdg[i];
6009999SWang.Lin@Sun.COM
6019999SWang.Lin@Sun.COM minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
6029999SWang.Lin@Sun.COM
6039999SWang.Lin@Sun.COM maxPwrT4[i] =
6049999SWang.Lin@Sun.COM min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
6059999SWang.Lin@Sun.COM pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
6069999SWang.Lin@Sun.COM
6079999SWang.Lin@Sun.COM
6089999SWang.Lin@Sun.COM (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
6099999SWang.Lin@Sun.COM pPwrL, pVpdL,
6109999SWang.Lin@Sun.COM AR5416_EEP4K_PD_GAIN_ICEPTS,
6119999SWang.Lin@Sun.COM vpdTableL[i]);
6129999SWang.Lin@Sun.COM (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
6139999SWang.Lin@Sun.COM pPwrR, pVpdR,
6149999SWang.Lin@Sun.COM AR5416_EEP4K_PD_GAIN_ICEPTS,
6159999SWang.Lin@Sun.COM vpdTableR[i]);
6169999SWang.Lin@Sun.COM
6179999SWang.Lin@Sun.COM for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
6189999SWang.Lin@Sun.COM vpdTableI[i][j] =
6199999SWang.Lin@Sun.COM (uint8_t)(ath9k_hw_interpolate((uint16_t)
6209999SWang.Lin@Sun.COM FREQ2FBIN(centers.
6219999SWang.Lin@Sun.COM synth_center,
6229999SWang.Lin@Sun.COM IS_CHAN_2GHZ
6239999SWang.Lin@Sun.COM (chan)),
6249999SWang.Lin@Sun.COM bChans[idxL], bChans[idxR],
6259999SWang.Lin@Sun.COM vpdTableL[i][j], vpdTableR[i][j]));
6269999SWang.Lin@Sun.COM }
6279999SWang.Lin@Sun.COM }
6289999SWang.Lin@Sun.COM }
6299999SWang.Lin@Sun.COM
6309999SWang.Lin@Sun.COM *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
6319999SWang.Lin@Sun.COM
6329999SWang.Lin@Sun.COM k = 0;
6339999SWang.Lin@Sun.COM
6349999SWang.Lin@Sun.COM for (i = 0; i < numXpdGains; i++) {
6359999SWang.Lin@Sun.COM if (i == (numXpdGains - 1))
6369999SWang.Lin@Sun.COM pPdGainBoundaries[i] =
6379999SWang.Lin@Sun.COM (uint16_t)(maxPwrT4[i] / 2);
6389999SWang.Lin@Sun.COM else
6399999SWang.Lin@Sun.COM pPdGainBoundaries[i] =
6409999SWang.Lin@Sun.COM (uint16_t)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
6419999SWang.Lin@Sun.COM
6429999SWang.Lin@Sun.COM pPdGainBoundaries[i] =
6439999SWang.Lin@Sun.COM min((uint16_t)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
6449999SWang.Lin@Sun.COM
6459999SWang.Lin@Sun.COM if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
6469999SWang.Lin@Sun.COM minDelta = pPdGainBoundaries[0] - 23;
6479999SWang.Lin@Sun.COM pPdGainBoundaries[0] = 23;
6489999SWang.Lin@Sun.COM } else {
6499999SWang.Lin@Sun.COM minDelta = 0;
6509999SWang.Lin@Sun.COM }
6519999SWang.Lin@Sun.COM
6529999SWang.Lin@Sun.COM if (i == 0) {
6539999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah))
6549999SWang.Lin@Sun.COM ss = (int16_t)(0 - (minPwrT4[i] / 2));
6559999SWang.Lin@Sun.COM else
6569999SWang.Lin@Sun.COM ss = 0;
6579999SWang.Lin@Sun.COM } else {
6589999SWang.Lin@Sun.COM ss = (int16_t)((pPdGainBoundaries[i - 1] -
6599999SWang.Lin@Sun.COM (minPwrT4[i] / 2)) -
6609999SWang.Lin@Sun.COM tPdGainOverlap + 1 + minDelta);
6619999SWang.Lin@Sun.COM }
6629999SWang.Lin@Sun.COM vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
6639999SWang.Lin@Sun.COM vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
6649999SWang.Lin@Sun.COM
6659999SWang.Lin@Sun.COM while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
6669999SWang.Lin@Sun.COM tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
6679999SWang.Lin@Sun.COM pPDADCValues[k++] =
6689999SWang.Lin@Sun.COM (uint8_t)((tmpVal < 0) ? 0 : tmpVal);
6699999SWang.Lin@Sun.COM ss++;
6709999SWang.Lin@Sun.COM }
6719999SWang.Lin@Sun.COM
6729999SWang.Lin@Sun.COM sizeCurrVpdTable =
6739999SWang.Lin@Sun.COM (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
6749999SWang.Lin@Sun.COM tgtIndex = (uint8_t)
6759999SWang.Lin@Sun.COM (pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2));
6769999SWang.Lin@Sun.COM maxIndex =
6779999SWang.Lin@Sun.COM (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
6789999SWang.Lin@Sun.COM
6799999SWang.Lin@Sun.COM while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
6809999SWang.Lin@Sun.COM pPDADCValues[k++] = vpdTableI[i][ss++];
6819999SWang.Lin@Sun.COM
6829999SWang.Lin@Sun.COM vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
6839999SWang.Lin@Sun.COM vpdTableI[i][sizeCurrVpdTable - 2]);
6849999SWang.Lin@Sun.COM vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
6859999SWang.Lin@Sun.COM
6869999SWang.Lin@Sun.COM if (tgtIndex > maxIndex) {
6879999SWang.Lin@Sun.COM while ((ss <= tgtIndex) &&
6889999SWang.Lin@Sun.COM (k < (AR5416_NUM_PDADC_VALUES - 1))) {
6899999SWang.Lin@Sun.COM tmpVal = (int16_t)TMP_VAL_VPD_TABLE;
6909999SWang.Lin@Sun.COM pPDADCValues[k++] = (uint8_t)
6919999SWang.Lin@Sun.COM ((tmpVal > 255) ? 255 : tmpVal);
6929999SWang.Lin@Sun.COM ss++;
6939999SWang.Lin@Sun.COM }
6949999SWang.Lin@Sun.COM }
6959999SWang.Lin@Sun.COM }
6969999SWang.Lin@Sun.COM
6979999SWang.Lin@Sun.COM while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
6989999SWang.Lin@Sun.COM pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
6999999SWang.Lin@Sun.COM i++;
7009999SWang.Lin@Sun.COM }
7019999SWang.Lin@Sun.COM
7029999SWang.Lin@Sun.COM while (k < AR5416_NUM_PDADC_VALUES) {
7039999SWang.Lin@Sun.COM pPDADCValues[k] = pPDADCValues[k - 1];
7049999SWang.Lin@Sun.COM k++;
7059999SWang.Lin@Sun.COM }
7069999SWang.Lin@Sun.COM
7079999SWang.Lin@Sun.COM return;
7089999SWang.Lin@Sun.COM #undef TMP_VAL_VPD_TABLE
7099999SWang.Lin@Sun.COM }
7109999SWang.Lin@Sun.COM
7119999SWang.Lin@Sun.COM static void
ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hal * ah,struct ath9k_channel * chan,struct cal_data_per_freq * pRawDataSet,uint8_t * bChans,uint16_t availPiers,uint16_t tPdGainOverlap,int16_t * pMinCalPower,uint16_t * pPdGainBoundaries,uint8_t * pPDADCValues,uint16_t numXpdGains)7129999SWang.Lin@Sun.COM ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hal *ah,
7139999SWang.Lin@Sun.COM struct ath9k_channel *chan,
7149999SWang.Lin@Sun.COM struct cal_data_per_freq *pRawDataSet,
7159999SWang.Lin@Sun.COM uint8_t *bChans, uint16_t availPiers,
7169999SWang.Lin@Sun.COM uint16_t tPdGainOverlap, int16_t *pMinCalPower,
7179999SWang.Lin@Sun.COM uint16_t *pPdGainBoundaries, uint8_t *pPDADCValues,
7189999SWang.Lin@Sun.COM uint16_t numXpdGains)
7199999SWang.Lin@Sun.COM {
7209999SWang.Lin@Sun.COM int i, j, k;
7219999SWang.Lin@Sun.COM int16_t ss;
7229999SWang.Lin@Sun.COM uint16_t idxL = 0, idxR = 0, numPiers;
7239999SWang.Lin@Sun.COM static uint8_t vpdTableL[AR5416_NUM_PD_GAINS]
7249999SWang.Lin@Sun.COM [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
7259999SWang.Lin@Sun.COM static uint8_t vpdTableR[AR5416_NUM_PD_GAINS]
7269999SWang.Lin@Sun.COM [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
7279999SWang.Lin@Sun.COM static uint8_t vpdTableI[AR5416_NUM_PD_GAINS]
7289999SWang.Lin@Sun.COM [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
7299999SWang.Lin@Sun.COM
7309999SWang.Lin@Sun.COM uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR;
7319999SWang.Lin@Sun.COM uint8_t minPwrT4[AR5416_NUM_PD_GAINS];
7329999SWang.Lin@Sun.COM uint8_t maxPwrT4[AR5416_NUM_PD_GAINS];
7339999SWang.Lin@Sun.COM int16_t vpdStep;
7349999SWang.Lin@Sun.COM int16_t tmpVal;
7359999SWang.Lin@Sun.COM uint16_t sizeCurrVpdTable, maxIndex, tgtIndex;
7369999SWang.Lin@Sun.COM boolean_t match;
7379999SWang.Lin@Sun.COM int16_t minDelta = 0;
7389999SWang.Lin@Sun.COM struct chan_centers centers;
7399999SWang.Lin@Sun.COM
7409999SWang.Lin@Sun.COM ath9k_hw_get_channel_centers(ah, chan, ¢ers);
7419999SWang.Lin@Sun.COM
7429999SWang.Lin@Sun.COM for (numPiers = 0; numPiers < availPiers; numPiers++) {
7439999SWang.Lin@Sun.COM if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
7449999SWang.Lin@Sun.COM break;
7459999SWang.Lin@Sun.COM }
7469999SWang.Lin@Sun.COM
7479999SWang.Lin@Sun.COM match =
7489999SWang.Lin@Sun.COM ath9k_hw_get_lower_upper_index(
7499999SWang.Lin@Sun.COM (uint8_t)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
7509999SWang.Lin@Sun.COM bChans, numPiers, &idxL, &idxR);
7519999SWang.Lin@Sun.COM
7529999SWang.Lin@Sun.COM if (match) {
7539999SWang.Lin@Sun.COM for (i = 0; i < numXpdGains; i++) {
7549999SWang.Lin@Sun.COM minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
7559999SWang.Lin@Sun.COM maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
7569999SWang.Lin@Sun.COM (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
7579999SWang.Lin@Sun.COM pRawDataSet[idxL].pwrPdg[i],
7589999SWang.Lin@Sun.COM pRawDataSet[idxL].vpdPdg[i],
7599999SWang.Lin@Sun.COM AR5416_PD_GAIN_ICEPTS,
7609999SWang.Lin@Sun.COM vpdTableI[i]);
7619999SWang.Lin@Sun.COM }
7629999SWang.Lin@Sun.COM } else {
7639999SWang.Lin@Sun.COM for (i = 0; i < numXpdGains; i++) {
7649999SWang.Lin@Sun.COM pVpdL = pRawDataSet[idxL].vpdPdg[i];
7659999SWang.Lin@Sun.COM pPwrL = pRawDataSet[idxL].pwrPdg[i];
7669999SWang.Lin@Sun.COM pVpdR = pRawDataSet[idxR].vpdPdg[i];
7679999SWang.Lin@Sun.COM pPwrR = pRawDataSet[idxR].pwrPdg[i];
7689999SWang.Lin@Sun.COM
7699999SWang.Lin@Sun.COM minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
7709999SWang.Lin@Sun.COM
7719999SWang.Lin@Sun.COM maxPwrT4[i] =
7729999SWang.Lin@Sun.COM min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
7739999SWang.Lin@Sun.COM pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
7749999SWang.Lin@Sun.COM
7759999SWang.Lin@Sun.COM
7769999SWang.Lin@Sun.COM (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
7779999SWang.Lin@Sun.COM pPwrL, pVpdL,
7789999SWang.Lin@Sun.COM AR5416_PD_GAIN_ICEPTS,
7799999SWang.Lin@Sun.COM vpdTableL[i]);
7809999SWang.Lin@Sun.COM (void) ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
7819999SWang.Lin@Sun.COM pPwrR, pVpdR,
7829999SWang.Lin@Sun.COM AR5416_PD_GAIN_ICEPTS,
7839999SWang.Lin@Sun.COM vpdTableR[i]);
7849999SWang.Lin@Sun.COM
7859999SWang.Lin@Sun.COM for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
7869999SWang.Lin@Sun.COM vpdTableI[i][j] =
7879999SWang.Lin@Sun.COM (uint8_t)(ath9k_hw_interpolate((uint16_t)
7889999SWang.Lin@Sun.COM FREQ2FBIN(centers.
7899999SWang.Lin@Sun.COM synth_center,
7909999SWang.Lin@Sun.COM IS_CHAN_2GHZ
7919999SWang.Lin@Sun.COM (chan)),
7929999SWang.Lin@Sun.COM bChans[idxL], bChans[idxR],
7939999SWang.Lin@Sun.COM vpdTableL[i][j], vpdTableR[i][j]));
7949999SWang.Lin@Sun.COM }
7959999SWang.Lin@Sun.COM }
7969999SWang.Lin@Sun.COM }
7979999SWang.Lin@Sun.COM
7989999SWang.Lin@Sun.COM *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
7999999SWang.Lin@Sun.COM
8009999SWang.Lin@Sun.COM k = 0;
8019999SWang.Lin@Sun.COM
8029999SWang.Lin@Sun.COM for (i = 0; i < numXpdGains; i++) {
8039999SWang.Lin@Sun.COM if (i == (numXpdGains - 1))
8049999SWang.Lin@Sun.COM pPdGainBoundaries[i] =
8059999SWang.Lin@Sun.COM (uint16_t)(maxPwrT4[i] / 2);
8069999SWang.Lin@Sun.COM else
8079999SWang.Lin@Sun.COM pPdGainBoundaries[i] =
8089999SWang.Lin@Sun.COM (uint16_t)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
8099999SWang.Lin@Sun.COM
8109999SWang.Lin@Sun.COM pPdGainBoundaries[i] =
8119999SWang.Lin@Sun.COM min((uint16_t)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
8129999SWang.Lin@Sun.COM
8139999SWang.Lin@Sun.COM if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
8149999SWang.Lin@Sun.COM minDelta = pPdGainBoundaries[0] - 23;
8159999SWang.Lin@Sun.COM pPdGainBoundaries[0] = 23;
8169999SWang.Lin@Sun.COM } else {
8179999SWang.Lin@Sun.COM minDelta = 0;
8189999SWang.Lin@Sun.COM }
8199999SWang.Lin@Sun.COM
8209999SWang.Lin@Sun.COM if (i == 0) {
8219999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah))
8229999SWang.Lin@Sun.COM ss = (int16_t)(0 - (minPwrT4[i] / 2));
8239999SWang.Lin@Sun.COM else
8249999SWang.Lin@Sun.COM ss = 0;
8259999SWang.Lin@Sun.COM } else {
8269999SWang.Lin@Sun.COM ss = (int16_t)((pPdGainBoundaries[i - 1] -
8279999SWang.Lin@Sun.COM (minPwrT4[i] / 2)) -
8289999SWang.Lin@Sun.COM tPdGainOverlap + 1 + minDelta);
8299999SWang.Lin@Sun.COM }
8309999SWang.Lin@Sun.COM vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
8319999SWang.Lin@Sun.COM vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
8329999SWang.Lin@Sun.COM
8339999SWang.Lin@Sun.COM while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
8349999SWang.Lin@Sun.COM tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
8359999SWang.Lin@Sun.COM pPDADCValues[k++] =
8369999SWang.Lin@Sun.COM (uint8_t)((tmpVal < 0) ? 0 : tmpVal);
8379999SWang.Lin@Sun.COM ss++;
8389999SWang.Lin@Sun.COM }
8399999SWang.Lin@Sun.COM
8409999SWang.Lin@Sun.COM sizeCurrVpdTable =
8419999SWang.Lin@Sun.COM (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
8429999SWang.Lin@Sun.COM tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap -
8439999SWang.Lin@Sun.COM (minPwrT4[i] / 2));
8449999SWang.Lin@Sun.COM maxIndex = (tgtIndex < sizeCurrVpdTable) ?
8459999SWang.Lin@Sun.COM tgtIndex : sizeCurrVpdTable;
8469999SWang.Lin@Sun.COM
8479999SWang.Lin@Sun.COM while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
8489999SWang.Lin@Sun.COM pPDADCValues[k++] = vpdTableI[i][ss++];
8499999SWang.Lin@Sun.COM }
8509999SWang.Lin@Sun.COM
8519999SWang.Lin@Sun.COM vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
8529999SWang.Lin@Sun.COM vpdTableI[i][sizeCurrVpdTable - 2]);
8539999SWang.Lin@Sun.COM vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
8549999SWang.Lin@Sun.COM
8559999SWang.Lin@Sun.COM if (tgtIndex > maxIndex) {
8569999SWang.Lin@Sun.COM while ((ss <= tgtIndex) &&
8579999SWang.Lin@Sun.COM (k < (AR5416_NUM_PDADC_VALUES - 1))) {
8589999SWang.Lin@Sun.COM tmpVal =
8599999SWang.Lin@Sun.COM (int16_t)
8609999SWang.Lin@Sun.COM ((vpdTableI[i][sizeCurrVpdTable - 1] +
8619999SWang.Lin@Sun.COM (ss - maxIndex + 1) * vpdStep));
8629999SWang.Lin@Sun.COM pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ?
8639999SWang.Lin@Sun.COM 255 : tmpVal);
8649999SWang.Lin@Sun.COM ss++;
8659999SWang.Lin@Sun.COM }
8669999SWang.Lin@Sun.COM }
8679999SWang.Lin@Sun.COM }
8689999SWang.Lin@Sun.COM
8699999SWang.Lin@Sun.COM while (i < AR5416_PD_GAINS_IN_MASK) {
8709999SWang.Lin@Sun.COM pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
8719999SWang.Lin@Sun.COM i++;
8729999SWang.Lin@Sun.COM }
8739999SWang.Lin@Sun.COM
8749999SWang.Lin@Sun.COM while (k < AR5416_NUM_PDADC_VALUES) {
8759999SWang.Lin@Sun.COM pPDADCValues[k] = pPDADCValues[k - 1];
8769999SWang.Lin@Sun.COM k++;
8779999SWang.Lin@Sun.COM }
8789999SWang.Lin@Sun.COM }
8799999SWang.Lin@Sun.COM
8809999SWang.Lin@Sun.COM static void
ath9k_hw_get_legacy_target_powers(struct ath_hal * ah,struct ath9k_channel * chan,struct cal_target_power_leg * powInfo,uint16_t numChannels,struct cal_target_power_leg * pNewPower,uint16_t numRates,boolean_t isExtTarget)8819999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
8829999SWang.Lin@Sun.COM struct ath9k_channel *chan,
8839999SWang.Lin@Sun.COM struct cal_target_power_leg *powInfo,
8849999SWang.Lin@Sun.COM uint16_t numChannels,
8859999SWang.Lin@Sun.COM struct cal_target_power_leg *pNewPower,
8869999SWang.Lin@Sun.COM uint16_t numRates, boolean_t isExtTarget)
8879999SWang.Lin@Sun.COM {
8889999SWang.Lin@Sun.COM struct chan_centers centers;
8899999SWang.Lin@Sun.COM uint16_t clo, chi;
8909999SWang.Lin@Sun.COM int i;
8919999SWang.Lin@Sun.COM int matchIndex = -1, lowIndex = -1;
8929999SWang.Lin@Sun.COM uint16_t freq;
8939999SWang.Lin@Sun.COM
8949999SWang.Lin@Sun.COM ath9k_hw_get_channel_centers(ah, chan, ¢ers);
8959999SWang.Lin@Sun.COM freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
8969999SWang.Lin@Sun.COM
8979999SWang.Lin@Sun.COM if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
8989999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan))) {
8999999SWang.Lin@Sun.COM matchIndex = 0;
9009999SWang.Lin@Sun.COM } else {
9019999SWang.Lin@Sun.COM for (i = 0; (i < numChannels) &&
9029999SWang.Lin@Sun.COM (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
9039999SWang.Lin@Sun.COM if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
9049999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan))) {
9059999SWang.Lin@Sun.COM matchIndex = i;
9069999SWang.Lin@Sun.COM break;
9079999SWang.Lin@Sun.COM } else if ((freq <
9089999SWang.Lin@Sun.COM ath9k_hw_fbin2freq(powInfo[i].bChannel,
9099999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan))) &&
9109999SWang.Lin@Sun.COM (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
9119999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan)))) {
9129999SWang.Lin@Sun.COM lowIndex = i - 1;
9139999SWang.Lin@Sun.COM break;
9149999SWang.Lin@Sun.COM }
9159999SWang.Lin@Sun.COM }
9169999SWang.Lin@Sun.COM if ((matchIndex == -1) && (lowIndex == -1))
9179999SWang.Lin@Sun.COM matchIndex = i - 1;
9189999SWang.Lin@Sun.COM }
9199999SWang.Lin@Sun.COM
9209999SWang.Lin@Sun.COM if (matchIndex != -1) {
9219999SWang.Lin@Sun.COM *pNewPower = powInfo[matchIndex];
9229999SWang.Lin@Sun.COM } else {
9239999SWang.Lin@Sun.COM clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
9249999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan));
9259999SWang.Lin@Sun.COM chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
9269999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan));
9279999SWang.Lin@Sun.COM
9289999SWang.Lin@Sun.COM for (i = 0; i < numRates; i++) {
9299999SWang.Lin@Sun.COM pNewPower->tPow2x[i] =
9309999SWang.Lin@Sun.COM (uint8_t)ath9k_hw_interpolate(freq, clo, chi,
9319999SWang.Lin@Sun.COM powInfo[lowIndex].tPow2x[i],
9329999SWang.Lin@Sun.COM powInfo[lowIndex + 1].tPow2x[i]);
9339999SWang.Lin@Sun.COM }
9349999SWang.Lin@Sun.COM }
9359999SWang.Lin@Sun.COM }
9369999SWang.Lin@Sun.COM
9379999SWang.Lin@Sun.COM static void
ath9k_hw_get_target_powers(struct ath_hal * ah,struct ath9k_channel * chan,struct cal_target_power_ht * powInfo,uint16_t numChannels,struct cal_target_power_ht * pNewPower,uint16_t numRates,boolean_t isHt40Target)9389999SWang.Lin@Sun.COM ath9k_hw_get_target_powers(struct ath_hal *ah,
9399999SWang.Lin@Sun.COM struct ath9k_channel *chan,
9409999SWang.Lin@Sun.COM struct cal_target_power_ht *powInfo,
9419999SWang.Lin@Sun.COM uint16_t numChannels,
9429999SWang.Lin@Sun.COM struct cal_target_power_ht *pNewPower,
9439999SWang.Lin@Sun.COM uint16_t numRates, boolean_t isHt40Target)
9449999SWang.Lin@Sun.COM {
9459999SWang.Lin@Sun.COM struct chan_centers centers;
9469999SWang.Lin@Sun.COM uint16_t clo, chi;
9479999SWang.Lin@Sun.COM int i;
9489999SWang.Lin@Sun.COM int matchIndex = -1, lowIndex = -1;
9499999SWang.Lin@Sun.COM uint16_t freq;
9509999SWang.Lin@Sun.COM
9519999SWang.Lin@Sun.COM ath9k_hw_get_channel_centers(ah, chan, ¢ers);
9529999SWang.Lin@Sun.COM freq = isHt40Target ? centers.synth_center : centers.ctl_center;
9539999SWang.Lin@Sun.COM
9549999SWang.Lin@Sun.COM if (freq <=
9559999SWang.Lin@Sun.COM ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
9569999SWang.Lin@Sun.COM matchIndex = 0;
9579999SWang.Lin@Sun.COM } else {
9589999SWang.Lin@Sun.COM for (i = 0; (i < numChannels) &&
9599999SWang.Lin@Sun.COM (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
9609999SWang.Lin@Sun.COM if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
9619999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan))) {
9629999SWang.Lin@Sun.COM matchIndex = i;
9639999SWang.Lin@Sun.COM break;
9649999SWang.Lin@Sun.COM } else
9659999SWang.Lin@Sun.COM if ((freq <
9669999SWang.Lin@Sun.COM ath9k_hw_fbin2freq(powInfo[i].bChannel,
9679999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan))) &&
9689999SWang.Lin@Sun.COM (freq > ath9k_hw_fbin2freq
9699999SWang.Lin@Sun.COM (powInfo[i - 1].bChannel,
9709999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan)))) {
9719999SWang.Lin@Sun.COM lowIndex = i - 1;
9729999SWang.Lin@Sun.COM break;
9739999SWang.Lin@Sun.COM }
9749999SWang.Lin@Sun.COM }
9759999SWang.Lin@Sun.COM if ((matchIndex == -1) && (lowIndex == -1))
9769999SWang.Lin@Sun.COM matchIndex = i - 1;
9779999SWang.Lin@Sun.COM }
9789999SWang.Lin@Sun.COM
9799999SWang.Lin@Sun.COM if (matchIndex != -1) {
9809999SWang.Lin@Sun.COM *pNewPower = powInfo[matchIndex];
9819999SWang.Lin@Sun.COM } else {
9829999SWang.Lin@Sun.COM clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
9839999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan));
9849999SWang.Lin@Sun.COM chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
9859999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan));
9869999SWang.Lin@Sun.COM
9879999SWang.Lin@Sun.COM for (i = 0; i < numRates; i++) {
9889999SWang.Lin@Sun.COM pNewPower->tPow2x[i] =
9899999SWang.Lin@Sun.COM (uint8_t)ath9k_hw_interpolate(freq,
9909999SWang.Lin@Sun.COM clo, chi,
9919999SWang.Lin@Sun.COM powInfo[lowIndex].tPow2x[i],
9929999SWang.Lin@Sun.COM powInfo[lowIndex + 1].tPow2x[i]);
9939999SWang.Lin@Sun.COM }
9949999SWang.Lin@Sun.COM }
9959999SWang.Lin@Sun.COM }
9969999SWang.Lin@Sun.COM
9979999SWang.Lin@Sun.COM static uint16_t
ath9k_hw_get_max_edge_power(uint16_t freq,struct cal_ctl_edges * pRdEdgesPower,boolean_t is2GHz,int num_band_edges)9989999SWang.Lin@Sun.COM ath9k_hw_get_max_edge_power(uint16_t freq,
9999999SWang.Lin@Sun.COM struct cal_ctl_edges *pRdEdgesPower,
10009999SWang.Lin@Sun.COM boolean_t is2GHz, int num_band_edges)
10019999SWang.Lin@Sun.COM {
10029999SWang.Lin@Sun.COM uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
10039999SWang.Lin@Sun.COM int i;
10049999SWang.Lin@Sun.COM
10059999SWang.Lin@Sun.COM for (i = 0; (i < num_band_edges) &&
10069999SWang.Lin@Sun.COM (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
10079999SWang.Lin@Sun.COM if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
10089999SWang.Lin@Sun.COM is2GHz)) {
10099999SWang.Lin@Sun.COM twiceMaxEdgePower = pRdEdgesPower[i].tPower;
10109999SWang.Lin@Sun.COM break;
10119999SWang.Lin@Sun.COM } else if ((i > 0) &&
10129999SWang.Lin@Sun.COM (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
10139999SWang.Lin@Sun.COM is2GHz))) {
10149999SWang.Lin@Sun.COM if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
10159999SWang.Lin@Sun.COM is2GHz) < freq &&
10169999SWang.Lin@Sun.COM pRdEdgesPower[i - 1].flag) {
10179999SWang.Lin@Sun.COM twiceMaxEdgePower =
10189999SWang.Lin@Sun.COM pRdEdgesPower[i - 1].tPower;
10199999SWang.Lin@Sun.COM }
10209999SWang.Lin@Sun.COM break;
10219999SWang.Lin@Sun.COM }
10229999SWang.Lin@Sun.COM }
10239999SWang.Lin@Sun.COM
10249999SWang.Lin@Sun.COM return (twiceMaxEdgePower);
10259999SWang.Lin@Sun.COM }
10269999SWang.Lin@Sun.COM
10279999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_set_def_power_cal_table(struct ath_hal * ah,struct ath9k_channel * chan,int16_t * pTxPowerIndexOffset)10289999SWang.Lin@Sun.COM ath9k_hw_set_def_power_cal_table(struct ath_hal *ah,
10299999SWang.Lin@Sun.COM struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset)
10309999SWang.Lin@Sun.COM {
10319999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
10329999SWang.Lin@Sun.COM struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
10339999SWang.Lin@Sun.COM struct cal_data_per_freq *pRawDataset;
10349999SWang.Lin@Sun.COM uint8_t *pCalBChans = NULL;
10359999SWang.Lin@Sun.COM uint16_t pdGainOverlap_t2;
10369999SWang.Lin@Sun.COM static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES];
10379999SWang.Lin@Sun.COM uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
10389999SWang.Lin@Sun.COM uint16_t numPiers, i, j;
10399999SWang.Lin@Sun.COM int16_t tMinCalPower;
10409999SWang.Lin@Sun.COM uint16_t numXpdGain, xpdMask;
10419999SWang.Lin@Sun.COM uint16_t xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
10429999SWang.Lin@Sun.COM uint32_t reg32, regOffset, regChainOffset;
10439999SWang.Lin@Sun.COM int16_t modalIdx;
10449999SWang.Lin@Sun.COM
10459999SWang.Lin@Sun.COM modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
10469999SWang.Lin@Sun.COM xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
10479999SWang.Lin@Sun.COM
10489999SWang.Lin@Sun.COM if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
10499999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_2) {
10509999SWang.Lin@Sun.COM pdGainOverlap_t2 =
10519999SWang.Lin@Sun.COM pEepData->modalHeader[modalIdx].pdGainOverlap;
10529999SWang.Lin@Sun.COM } else {
10539999SWang.Lin@Sun.COM pdGainOverlap_t2 =
10549999SWang.Lin@Sun.COM (uint16_t)(MS(REG_READ(ah, AR_PHY_TPCRG5),
10559999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
10569999SWang.Lin@Sun.COM }
10579999SWang.Lin@Sun.COM
10589999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan)) {
10599999SWang.Lin@Sun.COM pCalBChans = pEepData->calFreqPier2G;
10609999SWang.Lin@Sun.COM numPiers = AR5416_NUM_2G_CAL_PIERS;
10619999SWang.Lin@Sun.COM } else {
10629999SWang.Lin@Sun.COM pCalBChans = pEepData->calFreqPier5G;
10639999SWang.Lin@Sun.COM numPiers = AR5416_NUM_5G_CAL_PIERS;
10649999SWang.Lin@Sun.COM }
10659999SWang.Lin@Sun.COM
10669999SWang.Lin@Sun.COM numXpdGain = 0;
10679999SWang.Lin@Sun.COM
10689999SWang.Lin@Sun.COM for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
10699999SWang.Lin@Sun.COM if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
10709999SWang.Lin@Sun.COM if (numXpdGain >= AR5416_NUM_PD_GAINS)
10719999SWang.Lin@Sun.COM break;
10729999SWang.Lin@Sun.COM xpdGainValues[numXpdGain] =
10739999SWang.Lin@Sun.COM (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
10749999SWang.Lin@Sun.COM numXpdGain++;
10759999SWang.Lin@Sun.COM }
10769999SWang.Lin@Sun.COM }
10779999SWang.Lin@Sun.COM
10789999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
10799999SWang.Lin@Sun.COM (numXpdGain - 1) & 0x3);
10809999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
10819999SWang.Lin@Sun.COM xpdGainValues[0]);
10829999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
10839999SWang.Lin@Sun.COM xpdGainValues[1]);
10849999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
10859999SWang.Lin@Sun.COM xpdGainValues[2]);
10869999SWang.Lin@Sun.COM
10879999SWang.Lin@Sun.COM for (i = 0; i < AR5416_MAX_CHAINS; i++) {
10889999SWang.Lin@Sun.COM if (AR_SREV_5416_V20_OR_LATER(ah) &&
10899999SWang.Lin@Sun.COM (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
10909999SWang.Lin@Sun.COM (i != 0)) {
10919999SWang.Lin@Sun.COM regChainOffset = (i == 1) ? 0x2000 : 0x1000;
10929999SWang.Lin@Sun.COM } else
10939999SWang.Lin@Sun.COM regChainOffset = i * 0x1000;
10949999SWang.Lin@Sun.COM
10959999SWang.Lin@Sun.COM if (pEepData->baseEepHeader.txMask & (1 << i)) {
10969999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan))
10979999SWang.Lin@Sun.COM pRawDataset = pEepData->calPierData2G[i];
10989999SWang.Lin@Sun.COM else
10999999SWang.Lin@Sun.COM pRawDataset = pEepData->calPierData5G[i];
11009999SWang.Lin@Sun.COM
11019999SWang.Lin@Sun.COM ath9k_hw_get_def_gain_boundaries_pdadcs(ah, chan,
11029999SWang.Lin@Sun.COM pRawDataset, pCalBChans,
11039999SWang.Lin@Sun.COM numPiers, pdGainOverlap_t2,
11049999SWang.Lin@Sun.COM &tMinCalPower, gainBoundaries,
11059999SWang.Lin@Sun.COM pdadcValues, numXpdGain);
11069999SWang.Lin@Sun.COM
11079999SWang.Lin@Sun.COM if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
11089999SWang.Lin@Sun.COM REG_WRITE(ah,
11099999SWang.Lin@Sun.COM AR_PHY_TPCRG5 + regChainOffset,
11109999SWang.Lin@Sun.COM SM(pdGainOverlap_t2,
11119999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
11129999SWang.Lin@Sun.COM SM(gainBoundaries[0],
11139999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
11149999SWang.Lin@Sun.COM SM(gainBoundaries[1],
11159999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
11169999SWang.Lin@Sun.COM SM(gainBoundaries[2],
11179999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
11189999SWang.Lin@Sun.COM SM(gainBoundaries[3],
11199999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
11209999SWang.Lin@Sun.COM }
11219999SWang.Lin@Sun.COM
11229999SWang.Lin@Sun.COM regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
11239999SWang.Lin@Sun.COM for (j = 0; j < 32; j++) {
11249999SWang.Lin@Sun.COM reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
11259999SWang.Lin@Sun.COM ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
11269999SWang.Lin@Sun.COM ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
11279999SWang.Lin@Sun.COM ((pdadcValues[4 * j + 3] & 0xFF) << 24);
11289999SWang.Lin@Sun.COM REG_WRITE(ah, regOffset, reg32);
11299999SWang.Lin@Sun.COM
11309999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_REG_IO,
11319999SWang.Lin@Sun.COM "PDADC (%d,%4x): %4.4x %8.8x\n",
11329999SWang.Lin@Sun.COM i, regChainOffset, regOffset,
11339999SWang.Lin@Sun.COM reg32));
11349999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_REG_IO,
11359999SWang.Lin@Sun.COM "PDADC: Chain %d | PDADC %3d "
11369999SWang.Lin@Sun.COM "Value %3d | PDADC %3d Value %3d | "
11379999SWang.Lin@Sun.COM "PDADC %3d Value %3d | PDADC %3d "
11389999SWang.Lin@Sun.COM "Value %3d |\n",
11399999SWang.Lin@Sun.COM i, 4 * j, pdadcValues[4 * j],
11409999SWang.Lin@Sun.COM 4 * j + 1, pdadcValues[4 * j + 1],
11419999SWang.Lin@Sun.COM 4 * j + 2, pdadcValues[4 * j + 2],
11429999SWang.Lin@Sun.COM 4 * j + 3,
11439999SWang.Lin@Sun.COM pdadcValues[4 * j + 3]));
11449999SWang.Lin@Sun.COM
11459999SWang.Lin@Sun.COM regOffset += 4;
11469999SWang.Lin@Sun.COM }
11479999SWang.Lin@Sun.COM }
11489999SWang.Lin@Sun.COM }
11499999SWang.Lin@Sun.COM
11509999SWang.Lin@Sun.COM *pTxPowerIndexOffset = 0;
11519999SWang.Lin@Sun.COM
11529999SWang.Lin@Sun.COM return (B_TRUE);
11539999SWang.Lin@Sun.COM }
11549999SWang.Lin@Sun.COM
11559999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_set_4k_power_cal_table(struct ath_hal * ah,struct ath9k_channel * chan,int16_t * pTxPowerIndexOffset)11569999SWang.Lin@Sun.COM ath9k_hw_set_4k_power_cal_table(struct ath_hal *ah,
11579999SWang.Lin@Sun.COM struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset)
11589999SWang.Lin@Sun.COM {
11599999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
11609999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
11619999SWang.Lin@Sun.COM struct cal_data_per_freq_4k *pRawDataset;
11629999SWang.Lin@Sun.COM uint8_t *pCalBChans = NULL;
11639999SWang.Lin@Sun.COM uint16_t pdGainOverlap_t2;
11649999SWang.Lin@Sun.COM static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES];
11659999SWang.Lin@Sun.COM uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK];
11669999SWang.Lin@Sun.COM uint16_t numPiers, i, j;
11679999SWang.Lin@Sun.COM int16_t tMinCalPower;
11689999SWang.Lin@Sun.COM uint16_t numXpdGain, xpdMask;
11699999SWang.Lin@Sun.COM uint16_t xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
11709999SWang.Lin@Sun.COM uint32_t reg32, regOffset, regChainOffset;
11719999SWang.Lin@Sun.COM
11729999SWang.Lin@Sun.COM xpdMask = pEepData->modalHeader.xpdGain;
11739999SWang.Lin@Sun.COM
11749999SWang.Lin@Sun.COM if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
11759999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_2) {
11769999SWang.Lin@Sun.COM pdGainOverlap_t2 =
11779999SWang.Lin@Sun.COM pEepData->modalHeader.pdGainOverlap;
11789999SWang.Lin@Sun.COM } else {
11799999SWang.Lin@Sun.COM pdGainOverlap_t2 = (uint16_t)(MS(REG_READ(ah, AR_PHY_TPCRG5),
11809999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
11819999SWang.Lin@Sun.COM }
11829999SWang.Lin@Sun.COM
11839999SWang.Lin@Sun.COM pCalBChans = pEepData->calFreqPier2G;
11849999SWang.Lin@Sun.COM numPiers = AR5416_NUM_2G_CAL_PIERS;
11859999SWang.Lin@Sun.COM
11869999SWang.Lin@Sun.COM numXpdGain = 0;
11879999SWang.Lin@Sun.COM
11889999SWang.Lin@Sun.COM for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
11899999SWang.Lin@Sun.COM if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
11909999SWang.Lin@Sun.COM if (numXpdGain >= AR5416_NUM_PD_GAINS)
11919999SWang.Lin@Sun.COM break;
11929999SWang.Lin@Sun.COM xpdGainValues[numXpdGain] =
11939999SWang.Lin@Sun.COM (uint16_t)(AR5416_PD_GAINS_IN_MASK - i);
11949999SWang.Lin@Sun.COM numXpdGain++;
11959999SWang.Lin@Sun.COM }
11969999SWang.Lin@Sun.COM }
11979999SWang.Lin@Sun.COM
11989999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
11999999SWang.Lin@Sun.COM (numXpdGain - 1) & 0x3);
12009999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
12019999SWang.Lin@Sun.COM xpdGainValues[0]);
12029999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
12039999SWang.Lin@Sun.COM xpdGainValues[1]);
12049999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
12059999SWang.Lin@Sun.COM xpdGainValues[2]);
12069999SWang.Lin@Sun.COM
12079999SWang.Lin@Sun.COM for (i = 0; i < AR5416_MAX_CHAINS; i++) {
12089999SWang.Lin@Sun.COM if (AR_SREV_5416_V20_OR_LATER(ah) &&
12099999SWang.Lin@Sun.COM (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
12109999SWang.Lin@Sun.COM (i != 0)) {
12119999SWang.Lin@Sun.COM regChainOffset = (i == 1) ? 0x2000 : 0x1000;
12129999SWang.Lin@Sun.COM } else
12139999SWang.Lin@Sun.COM regChainOffset = i * 0x1000;
12149999SWang.Lin@Sun.COM
12159999SWang.Lin@Sun.COM if (pEepData->baseEepHeader.txMask & (1 << i)) {
12169999SWang.Lin@Sun.COM pRawDataset = pEepData->calPierData2G[i];
12179999SWang.Lin@Sun.COM
12189999SWang.Lin@Sun.COM ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
12199999SWang.Lin@Sun.COM pRawDataset, pCalBChans,
12209999SWang.Lin@Sun.COM numPiers, pdGainOverlap_t2,
12219999SWang.Lin@Sun.COM &tMinCalPower, gainBoundaries,
12229999SWang.Lin@Sun.COM pdadcValues, numXpdGain);
12239999SWang.Lin@Sun.COM
12249999SWang.Lin@Sun.COM if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
12259999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
12269999SWang.Lin@Sun.COM SM(pdGainOverlap_t2,
12279999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
12289999SWang.Lin@Sun.COM SM(gainBoundaries[0],
12299999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) |
12309999SWang.Lin@Sun.COM SM(gainBoundaries[1],
12319999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) |
12329999SWang.Lin@Sun.COM SM(gainBoundaries[2],
12339999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) |
12349999SWang.Lin@Sun.COM SM(gainBoundaries[3],
12359999SWang.Lin@Sun.COM AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
12369999SWang.Lin@Sun.COM }
12379999SWang.Lin@Sun.COM
12389999SWang.Lin@Sun.COM regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
12399999SWang.Lin@Sun.COM for (j = 0; j < 32; j++) {
12409999SWang.Lin@Sun.COM reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
12419999SWang.Lin@Sun.COM ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
12429999SWang.Lin@Sun.COM ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
12439999SWang.Lin@Sun.COM ((pdadcValues[4 * j + 3] & 0xFF) << 24);
12449999SWang.Lin@Sun.COM REG_WRITE(ah, regOffset, reg32);
12459999SWang.Lin@Sun.COM
12469999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_REG_IO,
12479999SWang.Lin@Sun.COM "PDADC (%d,%4x): %4.4x %8.8x\n",
12489999SWang.Lin@Sun.COM i, regChainOffset, regOffset,
12499999SWang.Lin@Sun.COM reg32));
12509999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_REG_IO,
12519999SWang.Lin@Sun.COM "PDADC: Chain %d | "
12529999SWang.Lin@Sun.COM "PDADC %3d Value %3d | "
12539999SWang.Lin@Sun.COM "PDADC %3d Value %3d | "
12549999SWang.Lin@Sun.COM "PDADC %3d Value %3d | "
12559999SWang.Lin@Sun.COM "PDADC %3d Value %3d |\n",
12569999SWang.Lin@Sun.COM i, 4 * j, pdadcValues[4 * j],
12579999SWang.Lin@Sun.COM 4 * j + 1, pdadcValues[4 * j + 1],
12589999SWang.Lin@Sun.COM 4 * j + 2, pdadcValues[4 * j + 2],
12599999SWang.Lin@Sun.COM 4 * j + 3,
12609999SWang.Lin@Sun.COM pdadcValues[4 * j + 3]));
12619999SWang.Lin@Sun.COM
12629999SWang.Lin@Sun.COM regOffset += 4;
12639999SWang.Lin@Sun.COM }
12649999SWang.Lin@Sun.COM }
12659999SWang.Lin@Sun.COM }
12669999SWang.Lin@Sun.COM
12679999SWang.Lin@Sun.COM *pTxPowerIndexOffset = 0;
12689999SWang.Lin@Sun.COM
12699999SWang.Lin@Sun.COM return (B_TRUE);
12709999SWang.Lin@Sun.COM }
12719999SWang.Lin@Sun.COM
12729999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_set_def_power_per_rate_table(struct ath_hal * ah,struct ath9k_channel * chan,int16_t * ratesArray,uint16_t cfgCtl,uint16_t AntennaReduction,uint16_t twiceMaxRegulatoryPower,uint16_t powerLimit)12739999SWang.Lin@Sun.COM ath9k_hw_set_def_power_per_rate_table(struct ath_hal *ah,
12749999SWang.Lin@Sun.COM struct ath9k_channel *chan,
12759999SWang.Lin@Sun.COM int16_t *ratesArray,
12769999SWang.Lin@Sun.COM uint16_t cfgCtl,
12779999SWang.Lin@Sun.COM uint16_t AntennaReduction,
12789999SWang.Lin@Sun.COM uint16_t twiceMaxRegulatoryPower,
12799999SWang.Lin@Sun.COM uint16_t powerLimit)
12809999SWang.Lin@Sun.COM {
12819999SWang.Lin@Sun.COM #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
12829999SWang.Lin@Sun.COM #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
12839999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
12849999SWang.Lin@Sun.COM struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
12859999SWang.Lin@Sun.COM uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
12869999SWang.Lin@Sun.COM static const uint16_t tpScaleReductionTable[5] =
12879999SWang.Lin@Sun.COM { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
12889999SWang.Lin@Sun.COM
12899999SWang.Lin@Sun.COM int i;
12909999SWang.Lin@Sun.COM int8_t twiceLargestAntenna;
12919999SWang.Lin@Sun.COM struct cal_ctl_data *rep;
12929999SWang.Lin@Sun.COM struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
12939999SWang.Lin@Sun.COM 0, { 0, 0, 0, 0}
12949999SWang.Lin@Sun.COM };
12959999SWang.Lin@Sun.COM struct cal_target_power_leg targetPowerOfdmExt = {
12969999SWang.Lin@Sun.COM 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
12979999SWang.Lin@Sun.COM 0, { 0, 0, 0, 0 }
12989999SWang.Lin@Sun.COM };
12999999SWang.Lin@Sun.COM struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
13009999SWang.Lin@Sun.COM 0, {0, 0, 0, 0}
13019999SWang.Lin@Sun.COM };
13029999SWang.Lin@Sun.COM uint16_t scaledPower = 0, minCtlPower, maxRegAllowedPower;
13039999SWang.Lin@Sun.COM uint16_t ctlModesFor11a[] =
13049999SWang.Lin@Sun.COM { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
13059999SWang.Lin@Sun.COM uint16_t ctlModesFor11g[] =
13069999SWang.Lin@Sun.COM { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
13079999SWang.Lin@Sun.COM CTL_2GHT40
13089999SWang.Lin@Sun.COM };
13099999SWang.Lin@Sun.COM uint16_t numCtlModes, *pCtlMode, ctlMode, freq;
13109999SWang.Lin@Sun.COM struct chan_centers centers;
13119999SWang.Lin@Sun.COM int tx_chainmask;
13129999SWang.Lin@Sun.COM uint16_t twiceMinEdgePower;
13139999SWang.Lin@Sun.COM
13149999SWang.Lin@Sun.COM tx_chainmask = ahp->ah_txchainmask;
13159999SWang.Lin@Sun.COM
13169999SWang.Lin@Sun.COM ath9k_hw_get_channel_centers(ah, chan, ¢ers);
13179999SWang.Lin@Sun.COM
13189999SWang.Lin@Sun.COM twiceLargestAntenna = max(
13199999SWang.Lin@Sun.COM pEepData->modalHeader
13209999SWang.Lin@Sun.COM [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
13219999SWang.Lin@Sun.COM pEepData->modalHeader
13229999SWang.Lin@Sun.COM [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
13239999SWang.Lin@Sun.COM
13249999SWang.Lin@Sun.COM twiceLargestAntenna =
13259999SWang.Lin@Sun.COM max((uint8_t)twiceLargestAntenna,
13269999SWang.Lin@Sun.COM pEepData->modalHeader
13279999SWang.Lin@Sun.COM [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
13289999SWang.Lin@Sun.COM
13299999SWang.Lin@Sun.COM twiceLargestAntenna =
13309999SWang.Lin@Sun.COM (int16_t)min(AntennaReduction - twiceLargestAntenna, 0);
13319999SWang.Lin@Sun.COM
13329999SWang.Lin@Sun.COM maxRegAllowedPower =
13339999SWang.Lin@Sun.COM twiceMaxRegulatoryPower + twiceLargestAntenna;
13349999SWang.Lin@Sun.COM
13359999SWang.Lin@Sun.COM if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
13369999SWang.Lin@Sun.COM maxRegAllowedPower -=
13379999SWang.Lin@Sun.COM (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
13389999SWang.Lin@Sun.COM }
13399999SWang.Lin@Sun.COM
13409999SWang.Lin@Sun.COM scaledPower = min(powerLimit, maxRegAllowedPower);
13419999SWang.Lin@Sun.COM
13429999SWang.Lin@Sun.COM switch (ar5416_get_ntxchains(tx_chainmask)) {
13439999SWang.Lin@Sun.COM case 1:
13449999SWang.Lin@Sun.COM break;
13459999SWang.Lin@Sun.COM case 2:
13469999SWang.Lin@Sun.COM scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
13479999SWang.Lin@Sun.COM break;
13489999SWang.Lin@Sun.COM case 3:
13499999SWang.Lin@Sun.COM scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
13509999SWang.Lin@Sun.COM break;
13519999SWang.Lin@Sun.COM }
13529999SWang.Lin@Sun.COM
13539999SWang.Lin@Sun.COM scaledPower = max((uint16_t)0, scaledPower);
13549999SWang.Lin@Sun.COM
13559999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan)) {
13569999SWang.Lin@Sun.COM numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
13579999SWang.Lin@Sun.COM SUB_NUM_CTL_MODES_AT_2G_40;
13589999SWang.Lin@Sun.COM pCtlMode = ctlModesFor11g;
13599999SWang.Lin@Sun.COM
13609999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
13619999SWang.Lin@Sun.COM pEepData->calTargetPowerCck,
13629999SWang.Lin@Sun.COM AR5416_NUM_2G_CCK_TARGET_POWERS,
13639999SWang.Lin@Sun.COM &targetPowerCck, 4, B_FALSE);
13649999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
13659999SWang.Lin@Sun.COM pEepData->calTargetPower2G,
13669999SWang.Lin@Sun.COM AR5416_NUM_2G_20_TARGET_POWERS,
13679999SWang.Lin@Sun.COM &targetPowerOfdm, 4, B_FALSE);
13689999SWang.Lin@Sun.COM ath9k_hw_get_target_powers(ah, chan,
13699999SWang.Lin@Sun.COM pEepData->calTargetPower2GHT20,
13709999SWang.Lin@Sun.COM AR5416_NUM_2G_20_TARGET_POWERS,
13719999SWang.Lin@Sun.COM &targetPowerHt20, 8, B_FALSE);
13729999SWang.Lin@Sun.COM
13739999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan)) {
13749999SWang.Lin@Sun.COM numCtlModes = ARRAY_SIZE(ctlModesFor11g);
13759999SWang.Lin@Sun.COM ath9k_hw_get_target_powers(ah, chan,
13769999SWang.Lin@Sun.COM pEepData->calTargetPower2GHT40,
13779999SWang.Lin@Sun.COM AR5416_NUM_2G_40_TARGET_POWERS,
13789999SWang.Lin@Sun.COM &targetPowerHt40, 8, B_TRUE);
13799999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
13809999SWang.Lin@Sun.COM pEepData->calTargetPowerCck,
13819999SWang.Lin@Sun.COM AR5416_NUM_2G_CCK_TARGET_POWERS,
13829999SWang.Lin@Sun.COM &targetPowerCckExt, 4, B_TRUE);
13839999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
13849999SWang.Lin@Sun.COM pEepData->calTargetPower2G,
13859999SWang.Lin@Sun.COM AR5416_NUM_2G_20_TARGET_POWERS,
13869999SWang.Lin@Sun.COM &targetPowerOfdmExt, 4, B_TRUE);
13879999SWang.Lin@Sun.COM }
13889999SWang.Lin@Sun.COM } else {
13899999SWang.Lin@Sun.COM numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
13909999SWang.Lin@Sun.COM SUB_NUM_CTL_MODES_AT_5G_40;
13919999SWang.Lin@Sun.COM pCtlMode = ctlModesFor11a;
13929999SWang.Lin@Sun.COM
13939999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
13949999SWang.Lin@Sun.COM pEepData->calTargetPower5G,
13959999SWang.Lin@Sun.COM AR5416_NUM_5G_20_TARGET_POWERS,
13969999SWang.Lin@Sun.COM &targetPowerOfdm, 4, B_FALSE);
13979999SWang.Lin@Sun.COM ath9k_hw_get_target_powers(ah, chan,
13989999SWang.Lin@Sun.COM pEepData->calTargetPower5GHT20,
13999999SWang.Lin@Sun.COM AR5416_NUM_5G_20_TARGET_POWERS,
14009999SWang.Lin@Sun.COM &targetPowerHt20, 8, B_FALSE);
14019999SWang.Lin@Sun.COM
14029999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan)) {
14039999SWang.Lin@Sun.COM numCtlModes = ARRAY_SIZE(ctlModesFor11a);
14049999SWang.Lin@Sun.COM ath9k_hw_get_target_powers(ah, chan,
14059999SWang.Lin@Sun.COM pEepData->calTargetPower5GHT40,
14069999SWang.Lin@Sun.COM AR5416_NUM_5G_40_TARGET_POWERS,
14079999SWang.Lin@Sun.COM &targetPowerHt40, 8, B_TRUE);
14089999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
14099999SWang.Lin@Sun.COM pEepData->calTargetPower5G,
14109999SWang.Lin@Sun.COM AR5416_NUM_5G_20_TARGET_POWERS,
14119999SWang.Lin@Sun.COM &targetPowerOfdmExt, 4, B_TRUE);
14129999SWang.Lin@Sun.COM }
14139999SWang.Lin@Sun.COM }
14149999SWang.Lin@Sun.COM
14159999SWang.Lin@Sun.COM for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
14169999SWang.Lin@Sun.COM boolean_t isHt40CtlMode =
14179999SWang.Lin@Sun.COM (pCtlMode[ctlMode] == CTL_5GHT40) ||
14189999SWang.Lin@Sun.COM (pCtlMode[ctlMode] == CTL_2GHT40);
14199999SWang.Lin@Sun.COM if (isHt40CtlMode)
14209999SWang.Lin@Sun.COM freq = centers.synth_center;
14219999SWang.Lin@Sun.COM else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
14229999SWang.Lin@Sun.COM freq = centers.ext_center;
14239999SWang.Lin@Sun.COM else
14249999SWang.Lin@Sun.COM freq = centers.ctl_center;
14259999SWang.Lin@Sun.COM
14269999SWang.Lin@Sun.COM if (ar5416_get_eep_ver(ahp) == 14 &&
14279999SWang.Lin@Sun.COM ar5416_get_eep_rev(ahp) <= 2)
14289999SWang.Lin@Sun.COM twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
14299999SWang.Lin@Sun.COM
14309999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "arn: "
14319999SWang.Lin@Sun.COM "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
14329999SWang.Lin@Sun.COM "EXT_ADDITIVE %d\n",
14339999SWang.Lin@Sun.COM ctlMode, numCtlModes, isHt40CtlMode,
14349999SWang.Lin@Sun.COM (pCtlMode[ctlMode] & EXT_ADDITIVE)));
14359999SWang.Lin@Sun.COM
14369999SWang.Lin@Sun.COM for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i];
14379999SWang.Lin@Sun.COM i++) {
14389999SWang.Lin@Sun.COM
14399999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "arn: "
14409999SWang.Lin@Sun.COM "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
14419999SWang.Lin@Sun.COM "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
14429999SWang.Lin@Sun.COM "chan %d\n",
14439999SWang.Lin@Sun.COM i, cfgCtl, pCtlMode[ctlMode],
14449999SWang.Lin@Sun.COM pEepData->ctlIndex[i], chan->channel));
14459999SWang.Lin@Sun.COM
14469999SWang.Lin@Sun.COM if ((((cfgCtl & ~CTL_MODE_M) |
14479999SWang.Lin@Sun.COM (pCtlMode[ctlMode] & CTL_MODE_M)) ==
14489999SWang.Lin@Sun.COM pEepData->ctlIndex[i]) ||
14499999SWang.Lin@Sun.COM (((cfgCtl & ~CTL_MODE_M) |
14509999SWang.Lin@Sun.COM (pCtlMode[ctlMode] & CTL_MODE_M)) ==
14519999SWang.Lin@Sun.COM ((pEepData->ctlIndex[i] & CTL_MODE_M) |
14529999SWang.Lin@Sun.COM SD_NO_CTL))) {
14539999SWang.Lin@Sun.COM rep = &(pEepData->ctlData[i]);
14549999SWang.Lin@Sun.COM
14559999SWang.Lin@Sun.COM twiceMinEdgePower =
14569999SWang.Lin@Sun.COM ath9k_hw_get_max_edge_power(freq,
14579999SWang.Lin@Sun.COM rep->ctlEdges[ar5416_get_ntxchains
14589999SWang.Lin@Sun.COM (tx_chainmask) - 1],
14599999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
14609999SWang.Lin@Sun.COM
14619999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "arn: "
14629999SWang.Lin@Sun.COM "MATCH-EE_IDX %d: ch %d is2 %d "
14639999SWang.Lin@Sun.COM "2xMinEdge %d chainmask %d chains %d\n",
14649999SWang.Lin@Sun.COM i, freq, IS_CHAN_2GHZ(chan),
14659999SWang.Lin@Sun.COM twiceMinEdgePower, tx_chainmask,
14669999SWang.Lin@Sun.COM ar5416_get_ntxchains(tx_chainmask)));
14679999SWang.Lin@Sun.COM
14689999SWang.Lin@Sun.COM if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
14699999SWang.Lin@Sun.COM twiceMaxEdgePower =
14709999SWang.Lin@Sun.COM min(twiceMaxEdgePower,
14719999SWang.Lin@Sun.COM twiceMinEdgePower);
14729999SWang.Lin@Sun.COM } else {
14739999SWang.Lin@Sun.COM twiceMaxEdgePower = twiceMinEdgePower;
14749999SWang.Lin@Sun.COM break;
14759999SWang.Lin@Sun.COM }
14769999SWang.Lin@Sun.COM }
14779999SWang.Lin@Sun.COM }
14789999SWang.Lin@Sun.COM
14799999SWang.Lin@Sun.COM minCtlPower = min(twiceMaxEdgePower, scaledPower);
14809999SWang.Lin@Sun.COM
14819999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "arn: "
14829999SWang.Lin@Sun.COM "SEL-Min ctlMode %d pCtlMode %d "
14839999SWang.Lin@Sun.COM "2xMaxEdge %d sP %d minCtlPwr %d\n",
14849999SWang.Lin@Sun.COM ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
14859999SWang.Lin@Sun.COM scaledPower, minCtlPower));
14869999SWang.Lin@Sun.COM
14879999SWang.Lin@Sun.COM switch (pCtlMode[ctlMode]) {
14889999SWang.Lin@Sun.COM case CTL_11B:
14899999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
14909999SWang.Lin@Sun.COM i++) {
14919999SWang.Lin@Sun.COM targetPowerCck.tPow2x[i] =
14929999SWang.Lin@Sun.COM min((uint16_t)targetPowerCck.tPow2x[i],
14939999SWang.Lin@Sun.COM minCtlPower);
14949999SWang.Lin@Sun.COM }
14959999SWang.Lin@Sun.COM break;
14969999SWang.Lin@Sun.COM case CTL_11A:
14979999SWang.Lin@Sun.COM case CTL_11G:
14989999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
14999999SWang.Lin@Sun.COM i++) {
15009999SWang.Lin@Sun.COM targetPowerOfdm.tPow2x[i] =
15019999SWang.Lin@Sun.COM min((uint16_t)targetPowerOfdm.tPow2x[i],
15029999SWang.Lin@Sun.COM minCtlPower);
15039999SWang.Lin@Sun.COM }
15049999SWang.Lin@Sun.COM break;
15059999SWang.Lin@Sun.COM case CTL_5GHT20:
15069999SWang.Lin@Sun.COM case CTL_2GHT20:
15079999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
15089999SWang.Lin@Sun.COM i++) {
15099999SWang.Lin@Sun.COM targetPowerHt20.tPow2x[i] =
15109999SWang.Lin@Sun.COM min((uint16_t)targetPowerHt20.tPow2x[i],
15119999SWang.Lin@Sun.COM minCtlPower);
15129999SWang.Lin@Sun.COM }
15139999SWang.Lin@Sun.COM break;
15149999SWang.Lin@Sun.COM case CTL_11B_EXT:
15159999SWang.Lin@Sun.COM targetPowerCckExt.tPow2x[0] =
15169999SWang.Lin@Sun.COM min((uint16_t)targetPowerCckExt.tPow2x[0],
15179999SWang.Lin@Sun.COM minCtlPower);
15189999SWang.Lin@Sun.COM break;
15199999SWang.Lin@Sun.COM case CTL_11A_EXT:
15209999SWang.Lin@Sun.COM case CTL_11G_EXT:
15219999SWang.Lin@Sun.COM targetPowerOfdmExt.tPow2x[0] =
15229999SWang.Lin@Sun.COM min((uint16_t)targetPowerOfdmExt.tPow2x[0],
15239999SWang.Lin@Sun.COM minCtlPower);
15249999SWang.Lin@Sun.COM break;
15259999SWang.Lin@Sun.COM case CTL_5GHT40:
15269999SWang.Lin@Sun.COM case CTL_2GHT40:
15279999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
15289999SWang.Lin@Sun.COM i++) {
15299999SWang.Lin@Sun.COM targetPowerHt40.tPow2x[i] =
15309999SWang.Lin@Sun.COM min((uint16_t)targetPowerHt40.tPow2x[i],
15319999SWang.Lin@Sun.COM minCtlPower);
15329999SWang.Lin@Sun.COM }
15339999SWang.Lin@Sun.COM break;
15349999SWang.Lin@Sun.COM default:
15359999SWang.Lin@Sun.COM break;
15369999SWang.Lin@Sun.COM }
15379999SWang.Lin@Sun.COM }
15389999SWang.Lin@Sun.COM
15399999SWang.Lin@Sun.COM ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
15409999SWang.Lin@Sun.COM ratesArray[rate18mb] = ratesArray[rate24mb] =
15419999SWang.Lin@Sun.COM targetPowerOfdm.tPow2x[0];
15429999SWang.Lin@Sun.COM ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
15439999SWang.Lin@Sun.COM ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
15449999SWang.Lin@Sun.COM ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
15459999SWang.Lin@Sun.COM ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
15469999SWang.Lin@Sun.COM
15479999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
15489999SWang.Lin@Sun.COM ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
15499999SWang.Lin@Sun.COM
15509999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan)) {
15519999SWang.Lin@Sun.COM ratesArray[rate1l] = targetPowerCck.tPow2x[0];
15529999SWang.Lin@Sun.COM ratesArray[rate2s] = ratesArray[rate2l] =
15539999SWang.Lin@Sun.COM targetPowerCck.tPow2x[1];
15549999SWang.Lin@Sun.COM ratesArray[rate5_5s] = ratesArray[rate5_5l] =
15559999SWang.Lin@Sun.COM targetPowerCck.tPow2x[2];
15569999SWang.Lin@Sun.COM ;
15579999SWang.Lin@Sun.COM ratesArray[rate11s] = ratesArray[rate11l] =
15589999SWang.Lin@Sun.COM targetPowerCck.tPow2x[3];
15599999SWang.Lin@Sun.COM ;
15609999SWang.Lin@Sun.COM }
15619999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan)) {
15629999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
15639999SWang.Lin@Sun.COM ratesArray[rateHt40_0 + i] =
15649999SWang.Lin@Sun.COM targetPowerHt40.tPow2x[i];
15659999SWang.Lin@Sun.COM }
15669999SWang.Lin@Sun.COM ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
15679999SWang.Lin@Sun.COM ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
15689999SWang.Lin@Sun.COM ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
15699999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan)) {
15709999SWang.Lin@Sun.COM ratesArray[rateExtCck] =
15719999SWang.Lin@Sun.COM targetPowerCckExt.tPow2x[0];
15729999SWang.Lin@Sun.COM }
15739999SWang.Lin@Sun.COM }
15749999SWang.Lin@Sun.COM return (B_TRUE);
15759999SWang.Lin@Sun.COM }
15769999SWang.Lin@Sun.COM
15779999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_set_4k_power_per_rate_table(struct ath_hal * ah,struct ath9k_channel * chan,int16_t * ratesArray,uint16_t cfgCtl,uint16_t AntennaReduction,uint16_t twiceMaxRegulatoryPower,uint16_t powerLimit)15789999SWang.Lin@Sun.COM ath9k_hw_set_4k_power_per_rate_table(struct ath_hal *ah,
15799999SWang.Lin@Sun.COM struct ath9k_channel *chan,
15809999SWang.Lin@Sun.COM int16_t *ratesArray,
15819999SWang.Lin@Sun.COM uint16_t cfgCtl,
15829999SWang.Lin@Sun.COM uint16_t AntennaReduction,
15839999SWang.Lin@Sun.COM uint16_t twiceMaxRegulatoryPower,
15849999SWang.Lin@Sun.COM uint16_t powerLimit)
15859999SWang.Lin@Sun.COM {
15869999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
15879999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
15889999SWang.Lin@Sun.COM uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
15899999SWang.Lin@Sun.COM static const uint16_t tpScaleReductionTable[5] =
15909999SWang.Lin@Sun.COM { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
15919999SWang.Lin@Sun.COM
15929999SWang.Lin@Sun.COM int i;
15939999SWang.Lin@Sun.COM int16_t twiceLargestAntenna;
15949999SWang.Lin@Sun.COM struct cal_ctl_data_4k *rep;
15959999SWang.Lin@Sun.COM struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
15969999SWang.Lin@Sun.COM 0, { 0, 0, 0, 0}
15979999SWang.Lin@Sun.COM };
15989999SWang.Lin@Sun.COM struct cal_target_power_leg targetPowerOfdmExt = {
15999999SWang.Lin@Sun.COM 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
16009999SWang.Lin@Sun.COM 0, { 0, 0, 0, 0 }
16019999SWang.Lin@Sun.COM };
16029999SWang.Lin@Sun.COM struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
16039999SWang.Lin@Sun.COM 0, {0, 0, 0, 0}
16049999SWang.Lin@Sun.COM };
16059999SWang.Lin@Sun.COM uint16_t scaledPower = 0, minCtlPower, maxRegAllowedPower;
16069999SWang.Lin@Sun.COM uint16_t ctlModesFor11g[] =
16079999SWang.Lin@Sun.COM { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
16089999SWang.Lin@Sun.COM CTL_2GHT40
16099999SWang.Lin@Sun.COM };
16109999SWang.Lin@Sun.COM uint16_t numCtlModes, *pCtlMode, ctlMode, freq;
16119999SWang.Lin@Sun.COM struct chan_centers centers;
16129999SWang.Lin@Sun.COM int tx_chainmask;
16139999SWang.Lin@Sun.COM uint16_t twiceMinEdgePower;
16149999SWang.Lin@Sun.COM
16159999SWang.Lin@Sun.COM tx_chainmask = ahp->ah_txchainmask;
16169999SWang.Lin@Sun.COM
16179999SWang.Lin@Sun.COM ath9k_hw_get_channel_centers(ah, chan, ¢ers);
16189999SWang.Lin@Sun.COM
16199999SWang.Lin@Sun.COM twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
16209999SWang.Lin@Sun.COM
16219999SWang.Lin@Sun.COM twiceLargestAntenna =
16229999SWang.Lin@Sun.COM (int16_t)min(AntennaReduction - twiceLargestAntenna, 0);
16239999SWang.Lin@Sun.COM
16249999SWang.Lin@Sun.COM maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
16259999SWang.Lin@Sun.COM
16269999SWang.Lin@Sun.COM if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
16279999SWang.Lin@Sun.COM maxRegAllowedPower -=
16289999SWang.Lin@Sun.COM (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
16299999SWang.Lin@Sun.COM }
16309999SWang.Lin@Sun.COM
16319999SWang.Lin@Sun.COM scaledPower = min(powerLimit, maxRegAllowedPower);
16329999SWang.Lin@Sun.COM scaledPower = max((uint16_t)0, scaledPower);
16339999SWang.Lin@Sun.COM
16349999SWang.Lin@Sun.COM numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
16359999SWang.Lin@Sun.COM pCtlMode = ctlModesFor11g;
16369999SWang.Lin@Sun.COM
16379999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
16389999SWang.Lin@Sun.COM pEepData->calTargetPowerCck,
16399999SWang.Lin@Sun.COM AR5416_NUM_2G_CCK_TARGET_POWERS,
16409999SWang.Lin@Sun.COM &targetPowerCck, 4, B_FALSE);
16419999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
16429999SWang.Lin@Sun.COM pEepData->calTargetPower2G,
16439999SWang.Lin@Sun.COM AR5416_NUM_2G_20_TARGET_POWERS,
16449999SWang.Lin@Sun.COM &targetPowerOfdm, 4, B_FALSE);
16459999SWang.Lin@Sun.COM ath9k_hw_get_target_powers(ah, chan,
16469999SWang.Lin@Sun.COM pEepData->calTargetPower2GHT20,
16479999SWang.Lin@Sun.COM AR5416_NUM_2G_20_TARGET_POWERS,
16489999SWang.Lin@Sun.COM &targetPowerHt20, 8, B_FALSE);
16499999SWang.Lin@Sun.COM
16509999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan)) {
16519999SWang.Lin@Sun.COM numCtlModes = ARRAY_SIZE(ctlModesFor11g);
16529999SWang.Lin@Sun.COM ath9k_hw_get_target_powers(ah, chan,
16539999SWang.Lin@Sun.COM pEepData->calTargetPower2GHT40,
16549999SWang.Lin@Sun.COM AR5416_NUM_2G_40_TARGET_POWERS,
16559999SWang.Lin@Sun.COM &targetPowerHt40, 8, B_TRUE);
16569999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
16579999SWang.Lin@Sun.COM pEepData->calTargetPowerCck,
16589999SWang.Lin@Sun.COM AR5416_NUM_2G_CCK_TARGET_POWERS,
16599999SWang.Lin@Sun.COM &targetPowerCckExt, 4, B_TRUE);
16609999SWang.Lin@Sun.COM ath9k_hw_get_legacy_target_powers(ah, chan,
16619999SWang.Lin@Sun.COM pEepData->calTargetPower2G,
16629999SWang.Lin@Sun.COM AR5416_NUM_2G_20_TARGET_POWERS,
16639999SWang.Lin@Sun.COM &targetPowerOfdmExt, 4, B_TRUE);
16649999SWang.Lin@Sun.COM }
16659999SWang.Lin@Sun.COM
16669999SWang.Lin@Sun.COM for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
16679999SWang.Lin@Sun.COM boolean_t isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
16689999SWang.Lin@Sun.COM (pCtlMode[ctlMode] == CTL_2GHT40);
16699999SWang.Lin@Sun.COM if (isHt40CtlMode)
16709999SWang.Lin@Sun.COM freq = centers.synth_center;
16719999SWang.Lin@Sun.COM else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
16729999SWang.Lin@Sun.COM freq = centers.ext_center;
16739999SWang.Lin@Sun.COM else
16749999SWang.Lin@Sun.COM freq = centers.ctl_center;
16759999SWang.Lin@Sun.COM
16769999SWang.Lin@Sun.COM if (ar5416_get_eep_ver(ahp) == 14 &&
16779999SWang.Lin@Sun.COM ar5416_get_eep_rev(ahp) <= 2)
16789999SWang.Lin@Sun.COM twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
16799999SWang.Lin@Sun.COM
16809999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_POWER_MGMT,
16819999SWang.Lin@Sun.COM "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
16829999SWang.Lin@Sun.COM "EXT_ADDITIVE %d\n",
16839999SWang.Lin@Sun.COM ctlMode, numCtlModes, isHt40CtlMode,
16849999SWang.Lin@Sun.COM (pCtlMode[ctlMode] & EXT_ADDITIVE)));
16859999SWang.Lin@Sun.COM
16869999SWang.Lin@Sun.COM for (i = 0; (i < AR5416_NUM_CTLS) &&
16879999SWang.Lin@Sun.COM pEepData->ctlIndex[i]; i++) {
16889999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_POWER_MGMT,
16899999SWang.Lin@Sun.COM " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
16909999SWang.Lin@Sun.COM "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
16919999SWang.Lin@Sun.COM "chan %d\n",
16929999SWang.Lin@Sun.COM i, cfgCtl, pCtlMode[ctlMode],
16939999SWang.Lin@Sun.COM pEepData->ctlIndex[i], chan->channel));
16949999SWang.Lin@Sun.COM
16959999SWang.Lin@Sun.COM if ((((cfgCtl & ~CTL_MODE_M) |
16969999SWang.Lin@Sun.COM (pCtlMode[ctlMode] & CTL_MODE_M)) ==
16979999SWang.Lin@Sun.COM pEepData->ctlIndex[i]) ||
16989999SWang.Lin@Sun.COM (((cfgCtl & ~CTL_MODE_M) |
16999999SWang.Lin@Sun.COM (pCtlMode[ctlMode] & CTL_MODE_M)) ==
17009999SWang.Lin@Sun.COM ((pEepData->ctlIndex[i] & CTL_MODE_M) |
17019999SWang.Lin@Sun.COM SD_NO_CTL))) {
17029999SWang.Lin@Sun.COM rep = &(pEepData->ctlData[i]);
17039999SWang.Lin@Sun.COM
17049999SWang.Lin@Sun.COM twiceMinEdgePower =
17059999SWang.Lin@Sun.COM ath9k_hw_get_max_edge_power(freq,
17069999SWang.Lin@Sun.COM rep->ctlEdges[ar5416_get_ntxchains
17079999SWang.Lin@Sun.COM (tx_chainmask) - 1],
17089999SWang.Lin@Sun.COM IS_CHAN_2GHZ(chan),
17099999SWang.Lin@Sun.COM AR5416_EEP4K_NUM_BAND_EDGES);
17109999SWang.Lin@Sun.COM
17119999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_POWER_MGMT,
17129999SWang.Lin@Sun.COM " MATCH-EE_IDX %d: ch %d is2 %d "
17139999SWang.Lin@Sun.COM "2xMinEdge %d chainmask %d chains %d\n",
17149999SWang.Lin@Sun.COM i, freq, IS_CHAN_2GHZ(chan),
17159999SWang.Lin@Sun.COM twiceMinEdgePower, tx_chainmask,
17169999SWang.Lin@Sun.COM ar5416_get_ntxchains
17179999SWang.Lin@Sun.COM (tx_chainmask)));
17189999SWang.Lin@Sun.COM if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
17199999SWang.Lin@Sun.COM twiceMaxEdgePower =
17209999SWang.Lin@Sun.COM min(twiceMaxEdgePower,
17219999SWang.Lin@Sun.COM twiceMinEdgePower);
17229999SWang.Lin@Sun.COM } else {
17239999SWang.Lin@Sun.COM twiceMaxEdgePower = twiceMinEdgePower;
17249999SWang.Lin@Sun.COM break;
17259999SWang.Lin@Sun.COM }
17269999SWang.Lin@Sun.COM }
17279999SWang.Lin@Sun.COM }
17289999SWang.Lin@Sun.COM
17299999SWang.Lin@Sun.COM minCtlPower = (uint8_t)min(twiceMaxEdgePower, scaledPower);
17309999SWang.Lin@Sun.COM
17319999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_POWER_MGMT,
17329999SWang.Lin@Sun.COM " SEL-Min ctlMode %d pCtlMode %d "
17339999SWang.Lin@Sun.COM "2xMaxEdge %d sP %d minCtlPwr %d\n",
17349999SWang.Lin@Sun.COM ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
17359999SWang.Lin@Sun.COM scaledPower, minCtlPower));
17369999SWang.Lin@Sun.COM
17379999SWang.Lin@Sun.COM switch (pCtlMode[ctlMode]) {
17389999SWang.Lin@Sun.COM case CTL_11B:
17399999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
17409999SWang.Lin@Sun.COM i++) {
17419999SWang.Lin@Sun.COM targetPowerCck.tPow2x[i] =
17429999SWang.Lin@Sun.COM min((uint16_t)targetPowerCck.tPow2x[i],
17439999SWang.Lin@Sun.COM minCtlPower);
17449999SWang.Lin@Sun.COM }
17459999SWang.Lin@Sun.COM break;
17469999SWang.Lin@Sun.COM case CTL_11G:
17479999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
17489999SWang.Lin@Sun.COM i++) {
17499999SWang.Lin@Sun.COM targetPowerOfdm.tPow2x[i] =
17509999SWang.Lin@Sun.COM min((uint16_t)targetPowerOfdm.tPow2x[i],
17519999SWang.Lin@Sun.COM minCtlPower);
17529999SWang.Lin@Sun.COM }
17539999SWang.Lin@Sun.COM break;
17549999SWang.Lin@Sun.COM case CTL_2GHT20:
17559999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
17569999SWang.Lin@Sun.COM i++) {
17579999SWang.Lin@Sun.COM targetPowerHt20.tPow2x[i] =
17589999SWang.Lin@Sun.COM min((uint16_t)targetPowerHt20.tPow2x[i],
17599999SWang.Lin@Sun.COM minCtlPower);
17609999SWang.Lin@Sun.COM }
17619999SWang.Lin@Sun.COM break;
17629999SWang.Lin@Sun.COM case CTL_11B_EXT:
17639999SWang.Lin@Sun.COM targetPowerCckExt.tPow2x[0] = min((uint16_t)
17649999SWang.Lin@Sun.COM targetPowerCckExt.tPow2x[0],
17659999SWang.Lin@Sun.COM minCtlPower);
17669999SWang.Lin@Sun.COM break;
17679999SWang.Lin@Sun.COM case CTL_11G_EXT:
17689999SWang.Lin@Sun.COM targetPowerOfdmExt.tPow2x[0] = min((uint16_t)
17699999SWang.Lin@Sun.COM targetPowerOfdmExt.tPow2x[0],
17709999SWang.Lin@Sun.COM minCtlPower);
17719999SWang.Lin@Sun.COM break;
17729999SWang.Lin@Sun.COM case CTL_2GHT40:
17739999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
17749999SWang.Lin@Sun.COM i++) {
17759999SWang.Lin@Sun.COM targetPowerHt40.tPow2x[i] =
17769999SWang.Lin@Sun.COM min((uint16_t)targetPowerHt40.tPow2x[i],
17779999SWang.Lin@Sun.COM minCtlPower);
17789999SWang.Lin@Sun.COM }
17799999SWang.Lin@Sun.COM break;
17809999SWang.Lin@Sun.COM default:
17819999SWang.Lin@Sun.COM break;
17829999SWang.Lin@Sun.COM }
17839999SWang.Lin@Sun.COM }
17849999SWang.Lin@Sun.COM
17859999SWang.Lin@Sun.COM ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
17869999SWang.Lin@Sun.COM ratesArray[rate18mb] = ratesArray[rate24mb] =
17879999SWang.Lin@Sun.COM targetPowerOfdm.tPow2x[0];
17889999SWang.Lin@Sun.COM ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
17899999SWang.Lin@Sun.COM ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
17909999SWang.Lin@Sun.COM ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
17919999SWang.Lin@Sun.COM ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
17929999SWang.Lin@Sun.COM
17939999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
17949999SWang.Lin@Sun.COM ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
17959999SWang.Lin@Sun.COM
17969999SWang.Lin@Sun.COM ratesArray[rate1l] = targetPowerCck.tPow2x[0];
17979999SWang.Lin@Sun.COM ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
17989999SWang.Lin@Sun.COM ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
17999999SWang.Lin@Sun.COM ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
18009999SWang.Lin@Sun.COM
18019999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan)) {
18029999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
18039999SWang.Lin@Sun.COM ratesArray[rateHt40_0 + i] =
18049999SWang.Lin@Sun.COM targetPowerHt40.tPow2x[i];
18059999SWang.Lin@Sun.COM }
18069999SWang.Lin@Sun.COM ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
18079999SWang.Lin@Sun.COM ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
18089999SWang.Lin@Sun.COM ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
18099999SWang.Lin@Sun.COM ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
18109999SWang.Lin@Sun.COM }
18119999SWang.Lin@Sun.COM return (B_TRUE);
18129999SWang.Lin@Sun.COM }
18139999SWang.Lin@Sun.COM
18149999SWang.Lin@Sun.COM static int
ath9k_hw_def_set_txpower(struct ath_hal * ah,struct ath9k_channel * chan,uint16_t cfgCtl,uint8_t twiceAntennaReduction,uint8_t twiceMaxRegulatoryPower,uint8_t powerLimit)18159999SWang.Lin@Sun.COM ath9k_hw_def_set_txpower(struct ath_hal *ah, struct ath9k_channel *chan,
18169999SWang.Lin@Sun.COM uint16_t cfgCtl, uint8_t twiceAntennaReduction,
18179999SWang.Lin@Sun.COM uint8_t twiceMaxRegulatoryPower, uint8_t powerLimit)
18189999SWang.Lin@Sun.COM {
18199999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
18209999SWang.Lin@Sun.COM struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
18219999SWang.Lin@Sun.COM struct modal_eep_header *pModal =
18229999SWang.Lin@Sun.COM &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
18239999SWang.Lin@Sun.COM int16_t ratesArray[Ar5416RateSize];
18249999SWang.Lin@Sun.COM int16_t txPowerIndexOffset = 0;
18259999SWang.Lin@Sun.COM uint8_t ht40PowerIncForPdadc = 2;
18269999SWang.Lin@Sun.COM int i;
18279999SWang.Lin@Sun.COM
18289999SWang.Lin@Sun.COM (void) memset(ratesArray, 0, sizeof (ratesArray));
18299999SWang.Lin@Sun.COM
18309999SWang.Lin@Sun.COM if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
18319999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_2) {
18329999SWang.Lin@Sun.COM ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
18339999SWang.Lin@Sun.COM }
18349999SWang.Lin@Sun.COM
18359999SWang.Lin@Sun.COM if (!ath9k_hw_set_def_power_per_rate_table(ah, chan,
18369999SWang.Lin@Sun.COM &ratesArray[0], cfgCtl,
18379999SWang.Lin@Sun.COM twiceAntennaReduction,
18389999SWang.Lin@Sun.COM twiceMaxRegulatoryPower,
18399999SWang.Lin@Sun.COM powerLimit)) {
18409999SWang.Lin@Sun.COM
18419999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
18429999SWang.Lin@Sun.COM "ath9k_hw_set_txpower: unable to set "
18439999SWang.Lin@Sun.COM "tx power per rate table\n"));
18449999SWang.Lin@Sun.COM
18459999SWang.Lin@Sun.COM return (EIO);
18469999SWang.Lin@Sun.COM }
18479999SWang.Lin@Sun.COM
18489999SWang.Lin@Sun.COM if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) {
18499999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "ath9k: "
18509999SWang.Lin@Sun.COM "ath9k_hw_set_txpower: unable to set power table\n"));
18519999SWang.Lin@Sun.COM return (EIO);
18529999SWang.Lin@Sun.COM }
18539999SWang.Lin@Sun.COM
18549999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
18559999SWang.Lin@Sun.COM ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
18569999SWang.Lin@Sun.COM if (ratesArray[i] > AR5416_MAX_RATE_POWER)
18579999SWang.Lin@Sun.COM ratesArray[i] = AR5416_MAX_RATE_POWER;
18589999SWang.Lin@Sun.COM }
18599999SWang.Lin@Sun.COM
18609999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah)) {
18619999SWang.Lin@Sun.COM for (i = 0; i < Ar5416RateSize; i++)
18629999SWang.Lin@Sun.COM ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
18639999SWang.Lin@Sun.COM }
18649999SWang.Lin@Sun.COM
18659999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
18669999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate18mb], 24) |
18679999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate12mb], 16) |
18689999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate9mb], 8) |
18699999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate6mb], 0));
18709999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
18719999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate54mb], 24) |
18729999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate48mb], 16) |
18739999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate36mb], 8) |
18749999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate24mb], 0));
18759999SWang.Lin@Sun.COM
18769999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan)) {
18779999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
18789999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate2s], 24) |
18799999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate2l], 16) |
18809999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateXr], 8) |
18819999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate1l], 0));
18829999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
18839999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate11s], 24) |
18849999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate11l], 16) |
18859999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate5_5s], 8) |
18869999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate5_5l], 0));
18879999SWang.Lin@Sun.COM }
18889999SWang.Lin@Sun.COM
18899999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
18909999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_3], 24) |
18919999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_2], 16) |
18929999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_1], 8) |
18939999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
18949999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
18959999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_7], 24) |
18969999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_6], 16) |
18979999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_5], 8) |
18989999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
18999999SWang.Lin@Sun.COM
19009999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan)) {
19019999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
19029999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_3] +
19039999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 24) |
19049999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_2] +
19059999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 16) |
19069999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_1] +
19079999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 8) |
19089999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_0] +
19099999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 0));
19109999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
19119999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_7] +
19129999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 24) |
19139999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_6] +
19149999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 16) |
19159999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_5] +
19169999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 8) |
19179999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_4] +
19189999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 0));
19199999SWang.Lin@Sun.COM
19209999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
19219999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
19229999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateExtCck], 16) |
19239999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
19249999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateDupCck], 0));
19259999SWang.Lin@Sun.COM }
19269999SWang.Lin@Sun.COM
19279999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
19289999SWang.Lin@Sun.COM ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) |
19299999SWang.Lin@Sun.COM ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
19309999SWang.Lin@Sun.COM
19319999SWang.Lin@Sun.COM i = rate6mb;
19329999SWang.Lin@Sun.COM
19339999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan))
19349999SWang.Lin@Sun.COM i = rateHt40_0;
19359999SWang.Lin@Sun.COM else if (IS_CHAN_HT20(chan))
19369999SWang.Lin@Sun.COM i = rateHt20_0;
19379999SWang.Lin@Sun.COM
19389999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah))
19399999SWang.Lin@Sun.COM ah->ah_maxPowerLevel =
19409999SWang.Lin@Sun.COM ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
19419999SWang.Lin@Sun.COM else
19429999SWang.Lin@Sun.COM ah->ah_maxPowerLevel = ratesArray[i];
19439999SWang.Lin@Sun.COM
19449999SWang.Lin@Sun.COM return (0);
19459999SWang.Lin@Sun.COM }
19469999SWang.Lin@Sun.COM
19479999SWang.Lin@Sun.COM static int
ath9k_hw_4k_set_txpower(struct ath_hal * ah,struct ath9k_channel * chan,uint16_t cfgCtl,uint8_t twiceAntennaReduction,uint8_t twiceMaxRegulatoryPower,uint8_t powerLimit)19489999SWang.Lin@Sun.COM ath9k_hw_4k_set_txpower(struct ath_hal *ah,
19499999SWang.Lin@Sun.COM struct ath9k_channel *chan,
19509999SWang.Lin@Sun.COM uint16_t cfgCtl,
19519999SWang.Lin@Sun.COM uint8_t twiceAntennaReduction,
19529999SWang.Lin@Sun.COM uint8_t twiceMaxRegulatoryPower,
19539999SWang.Lin@Sun.COM uint8_t powerLimit)
19549999SWang.Lin@Sun.COM {
19559999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
19569999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
19579999SWang.Lin@Sun.COM struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
19589999SWang.Lin@Sun.COM int16_t ratesArray[Ar5416RateSize];
19599999SWang.Lin@Sun.COM int16_t txPowerIndexOffset = 0;
19609999SWang.Lin@Sun.COM uint8_t ht40PowerIncForPdadc = 2;
19619999SWang.Lin@Sun.COM int i;
19629999SWang.Lin@Sun.COM
19639999SWang.Lin@Sun.COM (void) memset(ratesArray, 0, sizeof (ratesArray));
19649999SWang.Lin@Sun.COM
19659999SWang.Lin@Sun.COM if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
19669999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_2) {
19679999SWang.Lin@Sun.COM ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
19689999SWang.Lin@Sun.COM }
19699999SWang.Lin@Sun.COM
19709999SWang.Lin@Sun.COM if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan,
19719999SWang.Lin@Sun.COM &ratesArray[0], cfgCtl,
19729999SWang.Lin@Sun.COM twiceAntennaReduction,
19739999SWang.Lin@Sun.COM twiceMaxRegulatoryPower,
19749999SWang.Lin@Sun.COM powerLimit)) {
19759999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
19769999SWang.Lin@Sun.COM "ath9k_hw_set_txpower: unable to set "
19779999SWang.Lin@Sun.COM "tx power per rate table\n"));
19789999SWang.Lin@Sun.COM return (EIO);
19799999SWang.Lin@Sun.COM }
19809999SWang.Lin@Sun.COM
19819999SWang.Lin@Sun.COM if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) {
19829999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
19839999SWang.Lin@Sun.COM "ath9k_hw_set_txpower: unable to set power table\n"));
19849999SWang.Lin@Sun.COM return (EIO);
19859999SWang.Lin@Sun.COM }
19869999SWang.Lin@Sun.COM
19879999SWang.Lin@Sun.COM for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
19889999SWang.Lin@Sun.COM ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
19899999SWang.Lin@Sun.COM if (ratesArray[i] > AR5416_MAX_RATE_POWER)
19909999SWang.Lin@Sun.COM ratesArray[i] = AR5416_MAX_RATE_POWER;
19919999SWang.Lin@Sun.COM }
19929999SWang.Lin@Sun.COM
19939999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah)) {
19949999SWang.Lin@Sun.COM for (i = 0; i < Ar5416RateSize; i++)
19959999SWang.Lin@Sun.COM ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
19969999SWang.Lin@Sun.COM }
19979999SWang.Lin@Sun.COM
19989999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
19999999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate18mb], 24) |
20009999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate12mb], 16) |
20019999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate9mb], 8) |
20029999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate6mb], 0));
20039999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
20049999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate54mb], 24) |
20059999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate48mb], 16) |
20069999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate36mb], 8) |
20079999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate24mb], 0));
20089999SWang.Lin@Sun.COM
20099999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan)) {
20109999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
20119999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate2s], 24) |
20129999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate2l], 16) |
20139999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateXr], 8) |
20149999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate1l], 0));
20159999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
20169999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate11s], 24) |
20179999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate11l], 16) |
20189999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate5_5s], 8) |
20199999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rate5_5l], 0));
20209999SWang.Lin@Sun.COM }
20219999SWang.Lin@Sun.COM
20229999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
20239999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_3], 24) |
20249999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_2], 16) |
20259999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_1], 8) |
20269999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
20279999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
20289999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_7], 24) |
20299999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_6], 16) |
20309999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_5], 8) |
20319999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
20329999SWang.Lin@Sun.COM
20339999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan)) {
20349999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
20359999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_3] +
20369999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 24) |
20379999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_2] +
20389999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 16) |
20399999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_1] +
20409999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 8) |
20419999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_0] +
20429999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 0));
20439999SWang.Lin@Sun.COM
20449999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
20459999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_7] +
20469999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 24) |
20479999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_6] +
20489999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 16) |
20499999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_5] +
20509999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 8) |
20519999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateHt40_4] +
20529999SWang.Lin@Sun.COM ht40PowerIncForPdadc, 0));
20539999SWang.Lin@Sun.COM
20549999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
20559999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) |
20569999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateExtCck], 16) |
20579999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
20589999SWang.Lin@Sun.COM ATH9K_POW_SM(ratesArray[rateDupCck], 0));
20599999SWang.Lin@Sun.COM }
20609999SWang.Lin@Sun.COM
20619999SWang.Lin@Sun.COM i = rate6mb;
20629999SWang.Lin@Sun.COM
20639999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan))
20649999SWang.Lin@Sun.COM i = rateHt40_0;
20659999SWang.Lin@Sun.COM else if (IS_CHAN_HT20(chan))
20669999SWang.Lin@Sun.COM i = rateHt20_0;
20679999SWang.Lin@Sun.COM
20689999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah))
20699999SWang.Lin@Sun.COM ah->ah_maxPowerLevel =
20709999SWang.Lin@Sun.COM ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
20719999SWang.Lin@Sun.COM else
20729999SWang.Lin@Sun.COM ah->ah_maxPowerLevel = ratesArray[i];
20739999SWang.Lin@Sun.COM
20749999SWang.Lin@Sun.COM return (0);
20759999SWang.Lin@Sun.COM }
20769999SWang.Lin@Sun.COM
20779999SWang.Lin@Sun.COM int
ath9k_hw_set_txpower(struct ath_hal * ah,struct ath9k_channel * chan,uint16_t cfgCtl,uint8_t twiceAntennaReduction,uint8_t twiceMaxRegulatoryPower,uint8_t powerLimit)20789999SWang.Lin@Sun.COM ath9k_hw_set_txpower(struct ath_hal *ah,
20799999SWang.Lin@Sun.COM struct ath9k_channel *chan,
20809999SWang.Lin@Sun.COM uint16_t cfgCtl,
20819999SWang.Lin@Sun.COM uint8_t twiceAntennaReduction,
20829999SWang.Lin@Sun.COM uint8_t twiceMaxRegulatoryPower,
20839999SWang.Lin@Sun.COM uint8_t powerLimit)
20849999SWang.Lin@Sun.COM {
20859999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
20869999SWang.Lin@Sun.COM int val;
20879999SWang.Lin@Sun.COM
20889999SWang.Lin@Sun.COM if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
20899999SWang.Lin@Sun.COM val = ath9k_hw_def_set_txpower(ah, chan, cfgCtl,
20909999SWang.Lin@Sun.COM twiceAntennaReduction, twiceMaxRegulatoryPower,
20919999SWang.Lin@Sun.COM powerLimit);
20929999SWang.Lin@Sun.COM else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
20939999SWang.Lin@Sun.COM val = ath9k_hw_4k_set_txpower(ah, chan, cfgCtl,
20949999SWang.Lin@Sun.COM twiceAntennaReduction, twiceMaxRegulatoryPower,
20959999SWang.Lin@Sun.COM powerLimit);
20969999SWang.Lin@Sun.COM return (val);
20979999SWang.Lin@Sun.COM }
20989999SWang.Lin@Sun.COM
20999999SWang.Lin@Sun.COM static void
ath9k_hw_set_def_addac(struct ath_hal * ah,struct ath9k_channel * chan)21009999SWang.Lin@Sun.COM ath9k_hw_set_def_addac(struct ath_hal *ah, struct ath9k_channel *chan)
21019999SWang.Lin@Sun.COM {
21029999SWang.Lin@Sun.COM #define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
21039999SWang.Lin@Sun.COM struct modal_eep_header *pModal;
21049999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
21059999SWang.Lin@Sun.COM struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
21069999SWang.Lin@Sun.COM uint8_t biaslevel;
21079999SWang.Lin@Sun.COM
21089999SWang.Lin@Sun.COM if (ah->ah_macVersion != AR_SREV_VERSION_9160)
21099999SWang.Lin@Sun.COM return;
21109999SWang.Lin@Sun.COM
21119999SWang.Lin@Sun.COM if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
21129999SWang.Lin@Sun.COM return;
21139999SWang.Lin@Sun.COM
21149999SWang.Lin@Sun.COM pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
21159999SWang.Lin@Sun.COM
21169999SWang.Lin@Sun.COM if (pModal->xpaBiasLvl != 0xff) {
21179999SWang.Lin@Sun.COM biaslevel = pModal->xpaBiasLvl;
21189999SWang.Lin@Sun.COM } else {
21199999SWang.Lin@Sun.COM uint16_t resetFreqBin, freqBin, freqCount = 0;
21209999SWang.Lin@Sun.COM struct chan_centers centers;
21219999SWang.Lin@Sun.COM
21229999SWang.Lin@Sun.COM ath9k_hw_get_channel_centers(ah, chan, ¢ers);
21239999SWang.Lin@Sun.COM
21249999SWang.Lin@Sun.COM resetFreqBin =
21259999SWang.Lin@Sun.COM FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan));
21269999SWang.Lin@Sun.COM freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
21279999SWang.Lin@Sun.COM biaslevel = (uint8_t)(XPA_LVL_FREQ(0) >> 14);
21289999SWang.Lin@Sun.COM
21299999SWang.Lin@Sun.COM freqCount++;
21309999SWang.Lin@Sun.COM
21319999SWang.Lin@Sun.COM while (freqCount < 3) {
21329999SWang.Lin@Sun.COM if (XPA_LVL_FREQ(freqCount) == 0x0)
21339999SWang.Lin@Sun.COM break;
21349999SWang.Lin@Sun.COM
21359999SWang.Lin@Sun.COM freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
21369999SWang.Lin@Sun.COM if (resetFreqBin >= freqBin) {
21379999SWang.Lin@Sun.COM biaslevel =
21389999SWang.Lin@Sun.COM (uint8_t)
21399999SWang.Lin@Sun.COM (XPA_LVL_FREQ(freqCount) >> 14);
21409999SWang.Lin@Sun.COM } else {
21419999SWang.Lin@Sun.COM break;
21429999SWang.Lin@Sun.COM }
21439999SWang.Lin@Sun.COM freqCount++;
21449999SWang.Lin@Sun.COM }
21459999SWang.Lin@Sun.COM }
21469999SWang.Lin@Sun.COM
21479999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan)) {
21489999SWang.Lin@Sun.COM INI_RA(&ahp->ah_iniAddac, 7, 1) =
21499999SWang.Lin@Sun.COM (INI_RA(&ahp->ah_iniAddac, 7, 1) &
21509999SWang.Lin@Sun.COM (~0x18)) | biaslevel << 3;
21519999SWang.Lin@Sun.COM } else {
21529999SWang.Lin@Sun.COM INI_RA(&ahp->ah_iniAddac, 6, 1) =
21539999SWang.Lin@Sun.COM (INI_RA(&ahp->ah_iniAddac, 6, 1) &
21549999SWang.Lin@Sun.COM (~0xc0)) | biaslevel << 6;
21559999SWang.Lin@Sun.COM }
21569999SWang.Lin@Sun.COM #undef XPA_LVL_FREQ
21579999SWang.Lin@Sun.COM }
21589999SWang.Lin@Sun.COM
21599999SWang.Lin@Sun.COM /* ARGSUSED */
21609999SWang.Lin@Sun.COM static void
ath9k_hw_set_4k_addac(struct ath_hal * ah,struct ath9k_channel * chan)21619999SWang.Lin@Sun.COM ath9k_hw_set_4k_addac(struct ath_hal *ah, struct ath9k_channel *chan)
21629999SWang.Lin@Sun.COM {
21639999SWang.Lin@Sun.COM struct modal_eep_4k_header *pModal;
21649999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
21659999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
21669999SWang.Lin@Sun.COM uint8_t biaslevel;
21679999SWang.Lin@Sun.COM
21689999SWang.Lin@Sun.COM if (ah->ah_macVersion != AR_SREV_VERSION_9160)
21699999SWang.Lin@Sun.COM return;
21709999SWang.Lin@Sun.COM
21719999SWang.Lin@Sun.COM if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
21729999SWang.Lin@Sun.COM return;
21739999SWang.Lin@Sun.COM
21749999SWang.Lin@Sun.COM pModal = &eep->modalHeader;
21759999SWang.Lin@Sun.COM
21769999SWang.Lin@Sun.COM if (pModal->xpaBiasLvl != 0xff) {
21779999SWang.Lin@Sun.COM biaslevel = pModal->xpaBiasLvl;
21789999SWang.Lin@Sun.COM INI_RA(&ahp->ah_iniAddac, 7, 1) =
21799999SWang.Lin@Sun.COM (INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) |
21809999SWang.Lin@Sun.COM biaslevel << 3;
21819999SWang.Lin@Sun.COM }
21829999SWang.Lin@Sun.COM }
21839999SWang.Lin@Sun.COM
21849999SWang.Lin@Sun.COM void
ath9k_hw_set_addac(struct ath_hal * ah,struct ath9k_channel * chan)21859999SWang.Lin@Sun.COM ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan)
21869999SWang.Lin@Sun.COM {
21879999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
21889999SWang.Lin@Sun.COM
21899999SWang.Lin@Sun.COM if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
21909999SWang.Lin@Sun.COM ath9k_hw_set_def_addac(ah, chan);
21919999SWang.Lin@Sun.COM else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
21929999SWang.Lin@Sun.COM ath9k_hw_set_4k_addac(ah, chan);
21939999SWang.Lin@Sun.COM }
21949999SWang.Lin@Sun.COM
21959999SWang.Lin@Sun.COM /* XXX: Clean me up, make me more legible */
21969999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_eeprom_set_def_board_values(struct ath_hal * ah,struct ath9k_channel * chan)21979999SWang.Lin@Sun.COM ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
21989999SWang.Lin@Sun.COM struct ath9k_channel *chan)
21999999SWang.Lin@Sun.COM {
22009999SWang.Lin@Sun.COM struct modal_eep_header *pModal;
22019999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
22029999SWang.Lin@Sun.COM struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
22039999SWang.Lin@Sun.COM int i, regChainOffset;
22049999SWang.Lin@Sun.COM uint8_t txRxAttenLocal;
22059999SWang.Lin@Sun.COM uint16_t ant_config;
22069999SWang.Lin@Sun.COM
22079999SWang.Lin@Sun.COM pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
22089999SWang.Lin@Sun.COM
22099999SWang.Lin@Sun.COM txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
22109999SWang.Lin@Sun.COM
22119999SWang.Lin@Sun.COM (void) ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
22129999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
22139999SWang.Lin@Sun.COM
22149999SWang.Lin@Sun.COM for (i = 0; i < AR5416_MAX_CHAINS; i++) {
22159999SWang.Lin@Sun.COM if (AR_SREV_9280(ah)) {
22169999SWang.Lin@Sun.COM if (i >= 2)
22179999SWang.Lin@Sun.COM break;
22189999SWang.Lin@Sun.COM }
22199999SWang.Lin@Sun.COM
22209999SWang.Lin@Sun.COM if (AR_SREV_5416_V20_OR_LATER(ah) &&
22219999SWang.Lin@Sun.COM (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
22229999SWang.Lin@Sun.COM (i != 0))
22239999SWang.Lin@Sun.COM regChainOffset = (i == 1) ? 0x2000 : 0x1000;
22249999SWang.Lin@Sun.COM else
22259999SWang.Lin@Sun.COM regChainOffset = i * 0x1000;
22269999SWang.Lin@Sun.COM
22279999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
22289999SWang.Lin@Sun.COM pModal->antCtrlChain[i]);
22299999SWang.Lin@Sun.COM
22309999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
22319999SWang.Lin@Sun.COM (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
22329999SWang.Lin@Sun.COM ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
22339999SWang.Lin@Sun.COM AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
22349999SWang.Lin@Sun.COM SM(pModal->iqCalICh[i],
22359999SWang.Lin@Sun.COM AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
22369999SWang.Lin@Sun.COM SM(pModal->iqCalQCh[i],
22379999SWang.Lin@Sun.COM AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
22389999SWang.Lin@Sun.COM
22399999SWang.Lin@Sun.COM if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
22409999SWang.Lin@Sun.COM if ((eep->baseEepHeader.version &
22419999SWang.Lin@Sun.COM AR5416_EEP_VER_MINOR_MASK) >=
22429999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_3) {
22439999SWang.Lin@Sun.COM txRxAttenLocal = pModal->txRxAttenCh[i];
22449999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah)) {
22459999SWang.Lin@Sun.COM REG_RMW_FIELD(ah,
22469999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
22479999SWang.Lin@Sun.COM regChainOffset,
22489999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
22499999SWang.Lin@Sun.COM pModal->
22509999SWang.Lin@Sun.COM bswMargin[i]);
22519999SWang.Lin@Sun.COM REG_RMW_FIELD(ah,
22529999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
22539999SWang.Lin@Sun.COM regChainOffset,
22549999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_XATTEN1_DB,
22559999SWang.Lin@Sun.COM pModal->
22569999SWang.Lin@Sun.COM bswAtten[i]);
22579999SWang.Lin@Sun.COM REG_RMW_FIELD(ah,
22589999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
22599999SWang.Lin@Sun.COM regChainOffset,
22609999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
22619999SWang.Lin@Sun.COM pModal->
22629999SWang.Lin@Sun.COM xatten2Margin[i]);
22639999SWang.Lin@Sun.COM REG_RMW_FIELD(ah,
22649999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
22659999SWang.Lin@Sun.COM regChainOffset,
22669999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_XATTEN2_DB,
22679999SWang.Lin@Sun.COM pModal->
22689999SWang.Lin@Sun.COM xatten2Db[i]);
22699999SWang.Lin@Sun.COM } else {
22709999SWang.Lin@Sun.COM REG_WRITE(ah,
22719999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
22729999SWang.Lin@Sun.COM regChainOffset,
22739999SWang.Lin@Sun.COM (REG_READ(ah,
22749999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
22759999SWang.Lin@Sun.COM regChainOffset) &
22769999SWang.Lin@Sun.COM ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
22779999SWang.Lin@Sun.COM | SM(pModal->
22789999SWang.Lin@Sun.COM bswMargin[i],
22799999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_BSW_MARGIN));
22809999SWang.Lin@Sun.COM REG_WRITE(ah,
22819999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
22829999SWang.Lin@Sun.COM regChainOffset,
22839999SWang.Lin@Sun.COM (REG_READ(ah,
22849999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
22859999SWang.Lin@Sun.COM regChainOffset) &
22869999SWang.Lin@Sun.COM ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
22879999SWang.Lin@Sun.COM | SM(pModal->bswAtten[i],
22889999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_BSW_ATTEN));
22899999SWang.Lin@Sun.COM }
22909999SWang.Lin@Sun.COM }
22919999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah)) {
22929999SWang.Lin@Sun.COM REG_RMW_FIELD(ah,
22939999SWang.Lin@Sun.COM AR_PHY_RXGAIN +
22949999SWang.Lin@Sun.COM regChainOffset,
22959999SWang.Lin@Sun.COM AR9280_PHY_RXGAIN_TXRX_ATTEN,
22969999SWang.Lin@Sun.COM txRxAttenLocal);
22979999SWang.Lin@Sun.COM REG_RMW_FIELD(ah,
22989999SWang.Lin@Sun.COM AR_PHY_RXGAIN +
22999999SWang.Lin@Sun.COM regChainOffset,
23009999SWang.Lin@Sun.COM AR9280_PHY_RXGAIN_TXRX_MARGIN,
23019999SWang.Lin@Sun.COM pModal->rxTxMarginCh[i]);
23029999SWang.Lin@Sun.COM } else {
23039999SWang.Lin@Sun.COM REG_WRITE(ah,
23049999SWang.Lin@Sun.COM AR_PHY_RXGAIN + regChainOffset,
23059999SWang.Lin@Sun.COM (REG_READ(ah,
23069999SWang.Lin@Sun.COM AR_PHY_RXGAIN +
23079999SWang.Lin@Sun.COM regChainOffset) &
23089999SWang.Lin@Sun.COM ~AR_PHY_RXGAIN_TXRX_ATTEN) |
23099999SWang.Lin@Sun.COM SM(txRxAttenLocal,
23109999SWang.Lin@Sun.COM AR_PHY_RXGAIN_TXRX_ATTEN));
23119999SWang.Lin@Sun.COM REG_WRITE(ah,
23129999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
23139999SWang.Lin@Sun.COM regChainOffset,
23149999SWang.Lin@Sun.COM (REG_READ(ah,
23159999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ +
23169999SWang.Lin@Sun.COM regChainOffset) &
23179999SWang.Lin@Sun.COM ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
23189999SWang.Lin@Sun.COM SM(pModal->rxTxMarginCh[i],
23199999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
23209999SWang.Lin@Sun.COM }
23219999SWang.Lin@Sun.COM }
23229999SWang.Lin@Sun.COM }
23239999SWang.Lin@Sun.COM
23249999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah)) {
23259999SWang.Lin@Sun.COM if (IS_CHAN_2GHZ(chan)) {
23269999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
23279999SWang.Lin@Sun.COM AR_AN_RF2G1_CH0_OB,
23289999SWang.Lin@Sun.COM AR_AN_RF2G1_CH0_OB_S,
23299999SWang.Lin@Sun.COM pModal->ob);
23309999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
23319999SWang.Lin@Sun.COM AR_AN_RF2G1_CH0_DB,
23329999SWang.Lin@Sun.COM AR_AN_RF2G1_CH0_DB_S,
23339999SWang.Lin@Sun.COM pModal->db);
23349999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
23359999SWang.Lin@Sun.COM AR_AN_RF2G1_CH1_OB,
23369999SWang.Lin@Sun.COM AR_AN_RF2G1_CH1_OB_S,
23379999SWang.Lin@Sun.COM pModal->ob_ch1);
23389999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
23399999SWang.Lin@Sun.COM AR_AN_RF2G1_CH1_DB,
23409999SWang.Lin@Sun.COM AR_AN_RF2G1_CH1_DB_S,
23419999SWang.Lin@Sun.COM pModal->db_ch1);
23429999SWang.Lin@Sun.COM } else {
23439999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
23449999SWang.Lin@Sun.COM AR_AN_RF5G1_CH0_OB5,
23459999SWang.Lin@Sun.COM AR_AN_RF5G1_CH0_OB5_S,
23469999SWang.Lin@Sun.COM pModal->ob);
23479999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
23489999SWang.Lin@Sun.COM AR_AN_RF5G1_CH0_DB5,
23499999SWang.Lin@Sun.COM AR_AN_RF5G1_CH0_DB5_S,
23509999SWang.Lin@Sun.COM pModal->db);
23519999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
23529999SWang.Lin@Sun.COM AR_AN_RF5G1_CH1_OB5,
23539999SWang.Lin@Sun.COM AR_AN_RF5G1_CH1_OB5_S,
23549999SWang.Lin@Sun.COM pModal->ob_ch1);
23559999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
23569999SWang.Lin@Sun.COM AR_AN_RF5G1_CH1_DB5,
23579999SWang.Lin@Sun.COM AR_AN_RF5G1_CH1_DB5_S,
23589999SWang.Lin@Sun.COM pModal->db_ch1);
23599999SWang.Lin@Sun.COM }
23609999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
23619999SWang.Lin@Sun.COM AR_AN_TOP2_XPABIAS_LVL,
23629999SWang.Lin@Sun.COM AR_AN_TOP2_XPABIAS_LVL_S,
23639999SWang.Lin@Sun.COM pModal->xpaBiasLvl);
23649999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
23659999SWang.Lin@Sun.COM AR_AN_TOP2_LOCALBIAS,
23669999SWang.Lin@Sun.COM AR_AN_TOP2_LOCALBIAS_S,
23679999SWang.Lin@Sun.COM pModal->local_bias);
23689999SWang.Lin@Sun.COM
23699999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM, "arn: "
23709999SWang.Lin@Sun.COM "ForceXPAon: %d\n", pModal->force_xpaon));
23719999SWang.Lin@Sun.COM
23729999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
23739999SWang.Lin@Sun.COM pModal->force_xpaon);
23749999SWang.Lin@Sun.COM }
23759999SWang.Lin@Sun.COM
23769999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
23779999SWang.Lin@Sun.COM pModal->switchSettling);
23789999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
23799999SWang.Lin@Sun.COM pModal->adcDesiredSize);
23809999SWang.Lin@Sun.COM
23819999SWang.Lin@Sun.COM if (!AR_SREV_9280_10_OR_LATER(ah))
23829999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
23839999SWang.Lin@Sun.COM AR_PHY_DESIRED_SZ_PGA,
23849999SWang.Lin@Sun.COM pModal->pgaDesiredSize);
23859999SWang.Lin@Sun.COM
23869999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_RF_CTL4,
23879999SWang.Lin@Sun.COM SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
23889999SWang.Lin@Sun.COM SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
23899999SWang.Lin@Sun.COM SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
23909999SWang.Lin@Sun.COM SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
23919999SWang.Lin@Sun.COM
23929999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
23939999SWang.Lin@Sun.COM pModal->txEndToRxOn);
23949999SWang.Lin@Sun.COM if (AR_SREV_9280_10_OR_LATER(ah)) {
23959999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
23969999SWang.Lin@Sun.COM pModal->thresh62);
23979999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
23989999SWang.Lin@Sun.COM AR_PHY_EXT_CCA0_THRESH62,
23999999SWang.Lin@Sun.COM pModal->thresh62);
24009999SWang.Lin@Sun.COM } else {
24019999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
24029999SWang.Lin@Sun.COM pModal->thresh62);
24039999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
24049999SWang.Lin@Sun.COM AR_PHY_EXT_CCA_THRESH62,
24059999SWang.Lin@Sun.COM pModal->thresh62);
24069999SWang.Lin@Sun.COM }
24079999SWang.Lin@Sun.COM
24089999SWang.Lin@Sun.COM if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
24099999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_2) {
24109999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
24119999SWang.Lin@Sun.COM AR_PHY_TX_END_DATA_START,
24129999SWang.Lin@Sun.COM pModal->txFrameToDataStart);
24139999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
24149999SWang.Lin@Sun.COM pModal->txFrameToPaOn);
24159999SWang.Lin@Sun.COM }
24169999SWang.Lin@Sun.COM
24179999SWang.Lin@Sun.COM if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
24189999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_3) {
24199999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan))
24209999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SETTLING,
24219999SWang.Lin@Sun.COM AR_PHY_SETTLING_SWITCH,
24229999SWang.Lin@Sun.COM pModal->swSettleHt40);
24239999SWang.Lin@Sun.COM }
24249999SWang.Lin@Sun.COM
24259999SWang.Lin@Sun.COM return (B_TRUE);
24269999SWang.Lin@Sun.COM }
24279999SWang.Lin@Sun.COM
24289999SWang.Lin@Sun.COM static boolean_t
ath9k_hw_eeprom_set_4k_board_values(struct ath_hal * ah,struct ath9k_channel * chan)24299999SWang.Lin@Sun.COM ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
24309999SWang.Lin@Sun.COM struct ath9k_channel *chan)
24319999SWang.Lin@Sun.COM {
24329999SWang.Lin@Sun.COM struct modal_eep_4k_header *pModal;
24339999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
24349999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
24359999SWang.Lin@Sun.COM int regChainOffset;
24369999SWang.Lin@Sun.COM uint8_t txRxAttenLocal;
24379999SWang.Lin@Sun.COM uint16_t ant_config = 0;
24389999SWang.Lin@Sun.COM uint8_t ob[5], db1[5], db2[5];
24399999SWang.Lin@Sun.COM uint8_t ant_div_control1, ant_div_control2;
24409999SWang.Lin@Sun.COM uint32_t regVal;
24419999SWang.Lin@Sun.COM
24429999SWang.Lin@Sun.COM
24439999SWang.Lin@Sun.COM pModal = &eep->modalHeader;
24449999SWang.Lin@Sun.COM
24459999SWang.Lin@Sun.COM txRxAttenLocal = 23;
24469999SWang.Lin@Sun.COM
24479999SWang.Lin@Sun.COM (void) ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
24489999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
24499999SWang.Lin@Sun.COM
24509999SWang.Lin@Sun.COM regChainOffset = 0;
24519999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
24529999SWang.Lin@Sun.COM pModal->antCtrlChain[0]);
24539999SWang.Lin@Sun.COM
24549999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
24559999SWang.Lin@Sun.COM (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
24569999SWang.Lin@Sun.COM ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
24579999SWang.Lin@Sun.COM AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
24589999SWang.Lin@Sun.COM SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
24599999SWang.Lin@Sun.COM SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
24609999SWang.Lin@Sun.COM
24619999SWang.Lin@Sun.COM if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
24629999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_3) {
24639999SWang.Lin@Sun.COM txRxAttenLocal = pModal->txRxAttenCh[0];
24649999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
24659999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
24669999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
24679999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
24689999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
24699999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
24709999SWang.Lin@Sun.COM pModal->xatten2Margin[0]);
24719999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
24729999SWang.Lin@Sun.COM AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
24739999SWang.Lin@Sun.COM }
24749999SWang.Lin@Sun.COM
24759999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
24769999SWang.Lin@Sun.COM AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
24779999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
24789999SWang.Lin@Sun.COM AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
24799999SWang.Lin@Sun.COM
24809999SWang.Lin@Sun.COM if (AR_SREV_9285_11(ah))
24819999SWang.Lin@Sun.COM REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
24829999SWang.Lin@Sun.COM
24839999SWang.Lin@Sun.COM /* Initialize Ant Diversity settings from EEPROM */
24849999SWang.Lin@Sun.COM if (pModal->version == 3) {
24859999SWang.Lin@Sun.COM ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
24869999SWang.Lin@Sun.COM ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
24879999SWang.Lin@Sun.COM regVal = REG_READ(ah, 0x99ac);
24889999SWang.Lin@Sun.COM regVal &= (~(0x7f000000));
24899999SWang.Lin@Sun.COM regVal |= ((ant_div_control1 & 0x1) << 24);
24909999SWang.Lin@Sun.COM regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
24919999SWang.Lin@Sun.COM regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
24929999SWang.Lin@Sun.COM regVal |= ((ant_div_control2 & 0x3) << 25);
24939999SWang.Lin@Sun.COM regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
24949999SWang.Lin@Sun.COM REG_WRITE(ah, 0x99ac, regVal);
24959999SWang.Lin@Sun.COM regVal = REG_READ(ah, 0x99ac);
24969999SWang.Lin@Sun.COM regVal = REG_READ(ah, 0xa208);
24979999SWang.Lin@Sun.COM regVal &= (~(0x1 << 13));
24989999SWang.Lin@Sun.COM regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
24999999SWang.Lin@Sun.COM REG_WRITE(ah, 0xa208, regVal);
25009999SWang.Lin@Sun.COM regVal = REG_READ(ah, 0xa208);
25019999SWang.Lin@Sun.COM }
25029999SWang.Lin@Sun.COM
25039999SWang.Lin@Sun.COM if (pModal->version >= 2) {
25049999SWang.Lin@Sun.COM ob[0] = (pModal->ob_01 & 0xf);
25059999SWang.Lin@Sun.COM ob[1] = (pModal->ob_01 >> 4) & 0xf;
25069999SWang.Lin@Sun.COM ob[2] = (pModal->ob_234 & 0xf);
25079999SWang.Lin@Sun.COM ob[3] = ((pModal->ob_234 >> 4) & 0xf);
25089999SWang.Lin@Sun.COM ob[4] = ((pModal->ob_234 >> 8) & 0xf);
25099999SWang.Lin@Sun.COM
25109999SWang.Lin@Sun.COM db1[0] = (pModal->db1_01 & 0xf);
25119999SWang.Lin@Sun.COM db1[1] = ((pModal->db1_01 >> 4) & 0xf);
25129999SWang.Lin@Sun.COM db1[2] = (pModal->db1_234 & 0xf);
25139999SWang.Lin@Sun.COM db1[3] = ((pModal->db1_234 >> 4) & 0xf);
25149999SWang.Lin@Sun.COM db1[4] = ((pModal->db1_234 >> 8) & 0xf);
25159999SWang.Lin@Sun.COM
25169999SWang.Lin@Sun.COM db2[0] = (pModal->db2_01 & 0xf);
25179999SWang.Lin@Sun.COM db2[1] = ((pModal->db2_01 >> 4) & 0xf);
25189999SWang.Lin@Sun.COM db2[2] = (pModal->db2_234 & 0xf);
25199999SWang.Lin@Sun.COM db2[3] = ((pModal->db2_234 >> 4) & 0xf);
25209999SWang.Lin@Sun.COM db2[4] = ((pModal->db2_234 >> 8) & 0xf);
25219999SWang.Lin@Sun.COM
25229999SWang.Lin@Sun.COM } else if (pModal->version == 1) {
25239999SWang.Lin@Sun.COM
25249999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_EEPROM,
25259999SWang.Lin@Sun.COM "EEPROM Model version is set to 1 \n"));
25269999SWang.Lin@Sun.COM ob[0] = (pModal->ob_01 & 0xf);
25279999SWang.Lin@Sun.COM ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
25289999SWang.Lin@Sun.COM db1[0] = (pModal->db1_01 & 0xf);
25299999SWang.Lin@Sun.COM db1[1] = db1[2] = db1[3] = db1[4] =
25309999SWang.Lin@Sun.COM ((pModal->db1_01 >> 4) & 0xf);
25319999SWang.Lin@Sun.COM db2[0] = (pModal->db2_01 & 0xf);
25329999SWang.Lin@Sun.COM db2[1] = db2[2] = db2[3] = db2[4] =
25339999SWang.Lin@Sun.COM ((pModal->db2_01 >> 4) & 0xf);
25349999SWang.Lin@Sun.COM } else {
25359999SWang.Lin@Sun.COM int i;
25369999SWang.Lin@Sun.COM for (i = 0; i < 5; i++) {
25379999SWang.Lin@Sun.COM ob[i] = pModal->ob_01;
25389999SWang.Lin@Sun.COM db1[i] = pModal->db1_01;
25399999SWang.Lin@Sun.COM db2[i] = pModal->db1_01;
25409999SWang.Lin@Sun.COM }
25419999SWang.Lin@Sun.COM }
25429999SWang.Lin@Sun.COM
25439999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
25449999SWang.Lin@Sun.COM AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
25459999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
25469999SWang.Lin@Sun.COM AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
25479999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
25489999SWang.Lin@Sun.COM AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
25499999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
25509999SWang.Lin@Sun.COM AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
25519999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
25529999SWang.Lin@Sun.COM AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
25539999SWang.Lin@Sun.COM
25549999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
25559999SWang.Lin@Sun.COM AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
25569999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
25579999SWang.Lin@Sun.COM AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
25589999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
25599999SWang.Lin@Sun.COM AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
25609999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
25619999SWang.Lin@Sun.COM AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
25629999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
25639999SWang.Lin@Sun.COM AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
25649999SWang.Lin@Sun.COM
25659999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
25669999SWang.Lin@Sun.COM AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
25679999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
25689999SWang.Lin@Sun.COM AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
25699999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
25709999SWang.Lin@Sun.COM AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
25719999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
25729999SWang.Lin@Sun.COM AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
25739999SWang.Lin@Sun.COM ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
25749999SWang.Lin@Sun.COM AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
25759999SWang.Lin@Sun.COM
25769999SWang.Lin@Sun.COM
25779999SWang.Lin@Sun.COM if (AR_SREV_9285_11(ah))
25789999SWang.Lin@Sun.COM REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
25799999SWang.Lin@Sun.COM
25809999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
25819999SWang.Lin@Sun.COM pModal->switchSettling);
25829999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
25839999SWang.Lin@Sun.COM pModal->adcDesiredSize);
25849999SWang.Lin@Sun.COM
25859999SWang.Lin@Sun.COM REG_WRITE(ah, AR_PHY_RF_CTL4,
25869999SWang.Lin@Sun.COM SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
25879999SWang.Lin@Sun.COM SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
25889999SWang.Lin@Sun.COM SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
25899999SWang.Lin@Sun.COM SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
25909999SWang.Lin@Sun.COM
25919999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
25929999SWang.Lin@Sun.COM pModal->txEndToRxOn);
25939999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
25949999SWang.Lin@Sun.COM pModal->thresh62);
25959999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
25969999SWang.Lin@Sun.COM pModal->thresh62);
25979999SWang.Lin@Sun.COM
25989999SWang.Lin@Sun.COM if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
25999999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_2) {
26009999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
26019999SWang.Lin@Sun.COM pModal->txFrameToDataStart);
26029999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
26039999SWang.Lin@Sun.COM pModal->txFrameToPaOn);
26049999SWang.Lin@Sun.COM }
26059999SWang.Lin@Sun.COM
26069999SWang.Lin@Sun.COM if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
26079999SWang.Lin@Sun.COM AR5416_EEP_MINOR_VER_3) {
26089999SWang.Lin@Sun.COM if (IS_CHAN_HT40(chan))
26099999SWang.Lin@Sun.COM REG_RMW_FIELD(ah, AR_PHY_SETTLING,
26109999SWang.Lin@Sun.COM AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
26119999SWang.Lin@Sun.COM }
26129999SWang.Lin@Sun.COM
26139999SWang.Lin@Sun.COM return (B_TRUE);
26149999SWang.Lin@Sun.COM }
26159999SWang.Lin@Sun.COM
26169999SWang.Lin@Sun.COM boolean_t
ath9k_hw_eeprom_set_board_values(struct ath_hal * ah,struct ath9k_channel * chan)26179999SWang.Lin@Sun.COM ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, struct ath9k_channel *chan)
26189999SWang.Lin@Sun.COM {
26199999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
26209999SWang.Lin@Sun.COM boolean_t val;
26219999SWang.Lin@Sun.COM
26229999SWang.Lin@Sun.COM if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
26239999SWang.Lin@Sun.COM val = ath9k_hw_eeprom_set_def_board_values(ah, chan);
26249999SWang.Lin@Sun.COM else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
26259999SWang.Lin@Sun.COM val = ath9k_hw_eeprom_set_4k_board_values(ah, chan);
26269999SWang.Lin@Sun.COM
26279999SWang.Lin@Sun.COM return (val);
26289999SWang.Lin@Sun.COM }
26299999SWang.Lin@Sun.COM
26309999SWang.Lin@Sun.COM static int
ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal * ah,struct ath9k_channel * chan,uint8_t index,uint16_t * config)26319999SWang.Lin@Sun.COM ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah,
26329999SWang.Lin@Sun.COM struct ath9k_channel *chan,
26339999SWang.Lin@Sun.COM uint8_t index, uint16_t *config)
26349999SWang.Lin@Sun.COM {
26359999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
26369999SWang.Lin@Sun.COM struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
26379999SWang.Lin@Sun.COM struct modal_eep_header *pModal =
26389999SWang.Lin@Sun.COM &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
26399999SWang.Lin@Sun.COM struct base_eep_header *pBase = &eep->baseEepHeader;
26409999SWang.Lin@Sun.COM
26419999SWang.Lin@Sun.COM switch (index) {
26429999SWang.Lin@Sun.COM case 0:
26439999SWang.Lin@Sun.COM *config = pModal->antCtrlCommon & 0xFFFF;
26449999SWang.Lin@Sun.COM return (0);
26459999SWang.Lin@Sun.COM case 1:
26469999SWang.Lin@Sun.COM if (pBase->version >= 0x0E0D) {
26479999SWang.Lin@Sun.COM if (pModal->useAnt1) {
26489999SWang.Lin@Sun.COM *config =
26499999SWang.Lin@Sun.COM ((pModal->antCtrlCommon & 0xFFFF0000)
26509999SWang.Lin@Sun.COM >> 16);
26519999SWang.Lin@Sun.COM return (0);
26529999SWang.Lin@Sun.COM }
26539999SWang.Lin@Sun.COM }
26549999SWang.Lin@Sun.COM break;
26559999SWang.Lin@Sun.COM default:
26569999SWang.Lin@Sun.COM break;
26579999SWang.Lin@Sun.COM }
26589999SWang.Lin@Sun.COM
26599999SWang.Lin@Sun.COM return (-EINVAL);
26609999SWang.Lin@Sun.COM }
26619999SWang.Lin@Sun.COM
26629999SWang.Lin@Sun.COM /* ARGSUSED */
26639999SWang.Lin@Sun.COM static int
ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal * ah,struct ath9k_channel * chan,uint8_t index,uint16_t * config)26649999SWang.Lin@Sun.COM ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah,
26659999SWang.Lin@Sun.COM struct ath9k_channel *chan,
26669999SWang.Lin@Sun.COM uint8_t index, uint16_t *config)
26679999SWang.Lin@Sun.COM {
26689999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
26699999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
26709999SWang.Lin@Sun.COM struct modal_eep_4k_header *pModal = &eep->modalHeader;
26719999SWang.Lin@Sun.COM
26729999SWang.Lin@Sun.COM switch (index) {
26739999SWang.Lin@Sun.COM case 0:
26749999SWang.Lin@Sun.COM *config = pModal->antCtrlCommon & 0xFFFF;
26759999SWang.Lin@Sun.COM return (0);
26769999SWang.Lin@Sun.COM default:
26779999SWang.Lin@Sun.COM break;
26789999SWang.Lin@Sun.COM }
26799999SWang.Lin@Sun.COM
26809999SWang.Lin@Sun.COM return (EINVAL);
26819999SWang.Lin@Sun.COM }
26829999SWang.Lin@Sun.COM
26839999SWang.Lin@Sun.COM int
ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal * ah,struct ath9k_channel * chan,uint8_t index,uint16_t * config)26849999SWang.Lin@Sun.COM ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
26859999SWang.Lin@Sun.COM struct ath9k_channel *chan,
26869999SWang.Lin@Sun.COM uint8_t index, uint16_t *config)
26879999SWang.Lin@Sun.COM {
26889999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
26899999SWang.Lin@Sun.COM int val;
26909999SWang.Lin@Sun.COM
26919999SWang.Lin@Sun.COM if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
26929999SWang.Lin@Sun.COM val = ath9k_hw_get_def_eeprom_antenna_cfg(ah, chan,
26939999SWang.Lin@Sun.COM index, config);
26949999SWang.Lin@Sun.COM else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
26959999SWang.Lin@Sun.COM val = ath9k_hw_get_4k_eeprom_antenna_cfg(ah, chan,
26969999SWang.Lin@Sun.COM index, config);
26979999SWang.Lin@Sun.COM
26989999SWang.Lin@Sun.COM return (val);
26999999SWang.Lin@Sun.COM }
27009999SWang.Lin@Sun.COM
27019999SWang.Lin@Sun.COM /* ARGSUSED */
27029999SWang.Lin@Sun.COM static uint8_t
ath9k_hw_get_4k_num_ant_config(struct ath_hal * ah,enum ath9k_band freq_band)27039999SWang.Lin@Sun.COM ath9k_hw_get_4k_num_ant_config(struct ath_hal *ah,
27049999SWang.Lin@Sun.COM enum ath9k_band freq_band)
27059999SWang.Lin@Sun.COM {
27069999SWang.Lin@Sun.COM return (1);
27079999SWang.Lin@Sun.COM }
27089999SWang.Lin@Sun.COM
27099999SWang.Lin@Sun.COM static uint8_t
ath9k_hw_get_def_num_ant_config(struct ath_hal * ah,enum ath9k_band freq_band)27109999SWang.Lin@Sun.COM ath9k_hw_get_def_num_ant_config(struct ath_hal *ah,
27119999SWang.Lin@Sun.COM enum ath9k_band freq_band)
27129999SWang.Lin@Sun.COM {
27139999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
27149999SWang.Lin@Sun.COM struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
27159999SWang.Lin@Sun.COM
27169999SWang.Lin@Sun.COM struct modal_eep_header *pModal =
27179999SWang.Lin@Sun.COM &(eep->modalHeader[ATH9K_BAND_5GHZ == freq_band]);
27189999SWang.Lin@Sun.COM struct base_eep_header *pBase = &eep->baseEepHeader;
27199999SWang.Lin@Sun.COM uint8_t num_ant_config;
27209999SWang.Lin@Sun.COM
27219999SWang.Lin@Sun.COM num_ant_config = 1;
27229999SWang.Lin@Sun.COM
27239999SWang.Lin@Sun.COM if (pBase->version >= 0x0E0D)
27249999SWang.Lin@Sun.COM if (pModal->useAnt1)
27259999SWang.Lin@Sun.COM num_ant_config += 1;
27269999SWang.Lin@Sun.COM
27279999SWang.Lin@Sun.COM return (num_ant_config);
27289999SWang.Lin@Sun.COM }
27299999SWang.Lin@Sun.COM
27309999SWang.Lin@Sun.COM uint8_t
ath9k_hw_get_num_ant_config(struct ath_hal * ah,enum ath9k_band freq_band)27319999SWang.Lin@Sun.COM ath9k_hw_get_num_ant_config(struct ath_hal *ah,
27329999SWang.Lin@Sun.COM enum ath9k_band freq_band)
27339999SWang.Lin@Sun.COM {
27349999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
27359999SWang.Lin@Sun.COM uint8_t val;
27369999SWang.Lin@Sun.COM
27379999SWang.Lin@Sun.COM if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
27389999SWang.Lin@Sun.COM val = ath9k_hw_get_def_num_ant_config(ah, freq_band);
27399999SWang.Lin@Sun.COM else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
27409999SWang.Lin@Sun.COM val = ath9k_hw_get_4k_num_ant_config(ah, freq_band);
27419999SWang.Lin@Sun.COM
27429999SWang.Lin@Sun.COM return (val);
27439999SWang.Lin@Sun.COM }
27449999SWang.Lin@Sun.COM
27459999SWang.Lin@Sun.COM uint16_t
ath9k_hw_eeprom_get_spur_chan(struct ath_hal * ah,uint16_t i,boolean_t is2GHz)27469999SWang.Lin@Sun.COM ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, uint16_t i, boolean_t is2GHz)
27479999SWang.Lin@Sun.COM {
27489999SWang.Lin@Sun.COM #define EEP_MAP4K_SPURCHAN \
27499999SWang.Lin@Sun.COM (ahp->ah_eeprom.map4k.modalHeader.spurChans[i].spurChan)
27509999SWang.Lin@Sun.COM #define EEP_DEF_SPURCHAN \
27519999SWang.Lin@Sun.COM (ahp->ah_eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
27529999SWang.Lin@Sun.COM
27539999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
27549999SWang.Lin@Sun.COM uint16_t spur_val = AR_NO_SPUR;
27559999SWang.Lin@Sun.COM
27569999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
27579999SWang.Lin@Sun.COM "Getting spur idx %d is2Ghz. %d val %x\n",
27589999SWang.Lin@Sun.COM i, is2GHz, ah->ah_config.spurchans[i][is2GHz]));
27599999SWang.Lin@Sun.COM
27609999SWang.Lin@Sun.COM switch (ah->ah_config.spurmode) {
27619999SWang.Lin@Sun.COM case SPUR_DISABLE:
27629999SWang.Lin@Sun.COM break;
27639999SWang.Lin@Sun.COM case SPUR_ENABLE_IOCTL:
27649999SWang.Lin@Sun.COM spur_val = ah->ah_config.spurchans[i][is2GHz];
27659999SWang.Lin@Sun.COM ARN_DBG((ARN_DBG_ANI, "arn: "
27669999SWang.Lin@Sun.COM "Getting spur val from new loc. %d\n", spur_val));
27679999SWang.Lin@Sun.COM break;
27689999SWang.Lin@Sun.COM case SPUR_ENABLE_EEPROM:
27699999SWang.Lin@Sun.COM if (ahp->ah_eep_map == EEP_MAP_4KBITS)
27709999SWang.Lin@Sun.COM spur_val = EEP_MAP4K_SPURCHAN;
27719999SWang.Lin@Sun.COM else
27729999SWang.Lin@Sun.COM spur_val = EEP_DEF_SPURCHAN;
27739999SWang.Lin@Sun.COM break;
27749999SWang.Lin@Sun.COM
27759999SWang.Lin@Sun.COM }
27769999SWang.Lin@Sun.COM
27779999SWang.Lin@Sun.COM return (spur_val);
27789999SWang.Lin@Sun.COM #undef EEP_DEF_SPURCHAN
27799999SWang.Lin@Sun.COM #undef EEP_MAP4K_SPURCHAN
27809999SWang.Lin@Sun.COM }
27819999SWang.Lin@Sun.COM
27829999SWang.Lin@Sun.COM static uint32_t
ath9k_hw_get_eeprom_4k(struct ath_hal * ah,enum eeprom_param param)27839999SWang.Lin@Sun.COM ath9k_hw_get_eeprom_4k(struct ath_hal *ah,
27849999SWang.Lin@Sun.COM enum eeprom_param param)
27859999SWang.Lin@Sun.COM {
27869999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
27879999SWang.Lin@Sun.COM struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
27889999SWang.Lin@Sun.COM struct modal_eep_4k_header *pModal = &eep->modalHeader;
27899999SWang.Lin@Sun.COM struct base_eep_header_4k *pBase = &eep->baseEepHeader;
27909999SWang.Lin@Sun.COM
27919999SWang.Lin@Sun.COM switch (param) {
27929999SWang.Lin@Sun.COM case EEP_NFTHRESH_2:
27939999SWang.Lin@Sun.COM return (pModal[1].noiseFloorThreshCh[0]);
27949999SWang.Lin@Sun.COM case AR_EEPROM_MAC(0):
27959999SWang.Lin@Sun.COM return (pBase->macAddr[0] << 8 | pBase->macAddr[1]);
27969999SWang.Lin@Sun.COM case AR_EEPROM_MAC(1):
27979999SWang.Lin@Sun.COM return (pBase->macAddr[2] << 8 | pBase->macAddr[3]);
27989999SWang.Lin@Sun.COM case AR_EEPROM_MAC(2):
27999999SWang.Lin@Sun.COM return (pBase->macAddr[4] << 8 | pBase->macAddr[5]);
28009999SWang.Lin@Sun.COM case EEP_REG_0:
28019999SWang.Lin@Sun.COM return (pBase->regDmn[0]);
28029999SWang.Lin@Sun.COM case EEP_REG_1:
28039999SWang.Lin@Sun.COM return (pBase->regDmn[1]);
28049999SWang.Lin@Sun.COM case EEP_OP_CAP:
28059999SWang.Lin@Sun.COM return (pBase->deviceCap);
28069999SWang.Lin@Sun.COM case EEP_OP_MODE:
28079999SWang.Lin@Sun.COM return (pBase->opCapFlags);
28089999SWang.Lin@Sun.COM case EEP_RF_SILENT:
28099999SWang.Lin@Sun.COM return (pBase->rfSilent);
28109999SWang.Lin@Sun.COM case EEP_OB_2:
28119999SWang.Lin@Sun.COM return (pModal->ob_01);
28129999SWang.Lin@Sun.COM case EEP_DB_2:
28139999SWang.Lin@Sun.COM return (pModal->db1_01);
28149999SWang.Lin@Sun.COM case EEP_MINOR_REV:
28159999SWang.Lin@Sun.COM return (pBase->version & AR5416_EEP_VER_MINOR_MASK);
28169999SWang.Lin@Sun.COM case EEP_TX_MASK:
28179999SWang.Lin@Sun.COM return (pBase->txMask);
28189999SWang.Lin@Sun.COM case EEP_RX_MASK:
28199999SWang.Lin@Sun.COM return (pBase->rxMask);
2820*11729SWang.Lin@Sun.COM /* 2.6.30 */
2821*11729SWang.Lin@Sun.COM case EEP_FRAC_N_5G:
2822*11729SWang.Lin@Sun.COM return (0);
28239999SWang.Lin@Sun.COM default:
28249999SWang.Lin@Sun.COM return (0);
28259999SWang.Lin@Sun.COM }
28269999SWang.Lin@Sun.COM }
28279999SWang.Lin@Sun.COM
28289999SWang.Lin@Sun.COM uint32_t
ath9k_hw_get_eeprom_def(struct ath_hal * ah,enum eeprom_param param)28299999SWang.Lin@Sun.COM ath9k_hw_get_eeprom_def(struct ath_hal *ah, enum eeprom_param param)
28309999SWang.Lin@Sun.COM {
28319999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
28329999SWang.Lin@Sun.COM struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
28339999SWang.Lin@Sun.COM struct modal_eep_header *pModal = eep->modalHeader;
28349999SWang.Lin@Sun.COM struct base_eep_header *pBase = &eep->baseEepHeader;
28359999SWang.Lin@Sun.COM
28369999SWang.Lin@Sun.COM switch (param) {
28379999SWang.Lin@Sun.COM case EEP_NFTHRESH_5:
28389999SWang.Lin@Sun.COM return (pModal[0].noiseFloorThreshCh[0]);
28399999SWang.Lin@Sun.COM case EEP_NFTHRESH_2:
28409999SWang.Lin@Sun.COM return (pModal[1].noiseFloorThreshCh[0]);
28419999SWang.Lin@Sun.COM case AR_EEPROM_MAC(0):
28429999SWang.Lin@Sun.COM return (pBase->macAddr[0] << 8 | pBase->macAddr[1]);
28439999SWang.Lin@Sun.COM case AR_EEPROM_MAC(1):
28449999SWang.Lin@Sun.COM return (pBase->macAddr[2] << 8 | pBase->macAddr[3]);
28459999SWang.Lin@Sun.COM case AR_EEPROM_MAC(2):
28469999SWang.Lin@Sun.COM return (pBase->macAddr[4] << 8 | pBase->macAddr[5]);
28479999SWang.Lin@Sun.COM case EEP_REG_0:
28489999SWang.Lin@Sun.COM return (pBase->regDmn[0]);
28499999SWang.Lin@Sun.COM case EEP_REG_1:
28509999SWang.Lin@Sun.COM return (pBase->regDmn[1]);
28519999SWang.Lin@Sun.COM case EEP_OP_CAP:
28529999SWang.Lin@Sun.COM return (pBase->deviceCap);
28539999SWang.Lin@Sun.COM case EEP_OP_MODE:
28549999SWang.Lin@Sun.COM return (pBase->opCapFlags);
28559999SWang.Lin@Sun.COM case EEP_RF_SILENT:
28569999SWang.Lin@Sun.COM return (pBase->rfSilent);
28579999SWang.Lin@Sun.COM case EEP_OB_5:
28589999SWang.Lin@Sun.COM return (pModal[0].ob);
28599999SWang.Lin@Sun.COM case EEP_DB_5:
28609999SWang.Lin@Sun.COM return (pModal[0].db);
28619999SWang.Lin@Sun.COM case EEP_OB_2:
28629999SWang.Lin@Sun.COM return (pModal[1].ob);
28639999SWang.Lin@Sun.COM case EEP_DB_2:
28649999SWang.Lin@Sun.COM return (pModal[1].db);
28659999SWang.Lin@Sun.COM case EEP_MINOR_REV:
28669999SWang.Lin@Sun.COM return (pBase->version & AR5416_EEP_VER_MINOR_MASK);
28679999SWang.Lin@Sun.COM case EEP_TX_MASK:
28689999SWang.Lin@Sun.COM return (pBase->txMask);
28699999SWang.Lin@Sun.COM case EEP_RX_MASK:
28709999SWang.Lin@Sun.COM return (pBase->rxMask);
28719999SWang.Lin@Sun.COM case EEP_RXGAIN_TYPE:
28729999SWang.Lin@Sun.COM return (pBase->rxGainType);
28739999SWang.Lin@Sun.COM case EEP_TXGAIN_TYPE:
28749999SWang.Lin@Sun.COM return (pBase->txGainType);
2875*11729SWang.Lin@Sun.COM /* 2.6.30 */
2876*11729SWang.Lin@Sun.COM case EEP_OL_PWRCTRL:
2877*11729SWang.Lin@Sun.COM if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
2878*11729SWang.Lin@Sun.COM return (pBase->openLoopPwrCntl ? B_TRUE: B_FALSE);
2879*11729SWang.Lin@Sun.COM else
2880*11729SWang.Lin@Sun.COM return (B_FALSE);
2881*11729SWang.Lin@Sun.COM case EEP_RC_CHAIN_MASK:
2882*11729SWang.Lin@Sun.COM if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
2883*11729SWang.Lin@Sun.COM return (pBase->rcChainMask);
2884*11729SWang.Lin@Sun.COM else
2885*11729SWang.Lin@Sun.COM return (0);
2886*11729SWang.Lin@Sun.COM case EEP_DAC_HPWR_5G:
2887*11729SWang.Lin@Sun.COM if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
2888*11729SWang.Lin@Sun.COM return (pBase->dacHiPwrMode_5G);
2889*11729SWang.Lin@Sun.COM else
2890*11729SWang.Lin@Sun.COM return (0);
2891*11729SWang.Lin@Sun.COM case EEP_FRAC_N_5G:
2892*11729SWang.Lin@Sun.COM if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
2893*11729SWang.Lin@Sun.COM return (pBase->frac_n_5g);
2894*11729SWang.Lin@Sun.COM else
2895*11729SWang.Lin@Sun.COM return (0);
28969999SWang.Lin@Sun.COM
28979999SWang.Lin@Sun.COM default:
28989999SWang.Lin@Sun.COM return (0);
28999999SWang.Lin@Sun.COM }
29009999SWang.Lin@Sun.COM }
29019999SWang.Lin@Sun.COM
29029999SWang.Lin@Sun.COM uint32_t
ath9k_hw_get_eeprom(struct ath_hal * ah,enum eeprom_param param)29039999SWang.Lin@Sun.COM ath9k_hw_get_eeprom(struct ath_hal *ah, enum eeprom_param param)
29049999SWang.Lin@Sun.COM {
29059999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
29069999SWang.Lin@Sun.COM uint32_t val;
29079999SWang.Lin@Sun.COM
29089999SWang.Lin@Sun.COM if (ahp->ah_eep_map == EEP_MAP_DEFAULT)
29099999SWang.Lin@Sun.COM val = ath9k_hw_get_eeprom_def(ah, param);
29109999SWang.Lin@Sun.COM else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
29119999SWang.Lin@Sun.COM val = ath9k_hw_get_eeprom_4k(ah, param);
29129999SWang.Lin@Sun.COM
29139999SWang.Lin@Sun.COM return (val);
29149999SWang.Lin@Sun.COM }
29159999SWang.Lin@Sun.COM
29169999SWang.Lin@Sun.COM int
ath9k_hw_eeprom_attach(struct ath_hal * ah)29179999SWang.Lin@Sun.COM ath9k_hw_eeprom_attach(struct ath_hal *ah)
29189999SWang.Lin@Sun.COM {
29199999SWang.Lin@Sun.COM int status;
29209999SWang.Lin@Sun.COM struct ath_hal_5416 *ahp = AH5416(ah);
29219999SWang.Lin@Sun.COM
29229999SWang.Lin@Sun.COM if (ath9k_hw_use_flash(ah))
29239999SWang.Lin@Sun.COM (void) ath9k_hw_flash_map(ah);
29249999SWang.Lin@Sun.COM
29259999SWang.Lin@Sun.COM if (AR_SREV_9285(ah))
29269999SWang.Lin@Sun.COM ahp->ah_eep_map = EEP_MAP_4KBITS;
29279999SWang.Lin@Sun.COM else
29289999SWang.Lin@Sun.COM ahp->ah_eep_map = EEP_MAP_DEFAULT;
29299999SWang.Lin@Sun.COM
29309999SWang.Lin@Sun.COM if (!ath9k_hw_fill_eeprom(ah))
29319999SWang.Lin@Sun.COM return (EIO);
29329999SWang.Lin@Sun.COM
29339999SWang.Lin@Sun.COM status = ath9k_hw_check_eeprom(ah);
29349999SWang.Lin@Sun.COM
29359999SWang.Lin@Sun.COM return (status);
29369999SWang.Lin@Sun.COM }
2937