linux/drivers/net/wireless/ath/ath9k/eeprom_9287.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2008-2011 Atheros Communications Inc.
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include <asm/unaligned.h>
  18#include "hw.h"
  19#include "ar9002_phy.h"
  20
  21#define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16))
  22
  23static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah)
  24{
  25        u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version);
  26
  27        return (version & AR5416_EEP_VER_MAJOR_MASK) >>
  28                AR5416_EEP_VER_MAJOR_SHIFT;
  29}
  30
  31static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah)
  32{
  33        u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version);
  34
  35        return version & AR5416_EEP_VER_MINOR_MASK;
  36}
  37
  38static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
  39{
  40        struct ar9287_eeprom *eep = &ah->eeprom.map9287;
  41        u16 *eep_data;
  42        int addr, eep_start_loc = AR9287_EEP_START_LOC;
  43        eep_data = (u16 *)eep;
  44
  45        for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
  46                if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data))
  47                        return false;
  48                eep_data++;
  49        }
  50
  51        return true;
  52}
  53
  54static bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah)
  55{
  56        u16 *eep_data = (u16 *)&ah->eeprom.map9287;
  57
  58        ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
  59                                     AR9287_HTC_EEP_START_LOC,
  60                                     SIZE_EEPROM_AR9287);
  61        return true;
  62}
  63
  64static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
  65{
  66        struct ath_common *common = ath9k_hw_common(ah);
  67
  68        if (!ath9k_hw_use_flash(ah)) {
  69                ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
  70        }
  71
  72        if (common->bus_ops->ath_bus_type == ATH_USB)
  73                return __ath9k_hw_usb_ar9287_fill_eeprom(ah);
  74        else
  75                return __ath9k_hw_ar9287_fill_eeprom(ah);
  76}
  77
  78#ifdef CONFIG_ATH9K_COMMON_DEBUG
  79static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
  80                                    struct modal_eep_ar9287_header *modal_hdr)
  81{
  82        PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
  83        PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
  84        PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
  85        PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
  86        PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
  87        PR_EEP("Switch Settle", modal_hdr->switchSettling);
  88        PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
  89        PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
  90        PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
  91        PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
  92        PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
  93        PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
  94        PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
  95        PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
  96        PR_EEP("CCA Threshold)", modal_hdr->thresh62);
  97        PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
  98        PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
  99        PR_EEP("xpdGain", modal_hdr->xpdGain);
 100        PR_EEP("External PD", modal_hdr->xpd);
 101        PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
 102        PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
 103        PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
 104        PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
 105        PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
 106        PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
 107        PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
 108        PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
 109        PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
 110        PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
 111        PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
 112        PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
 113        PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
 114        PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
 115        PR_EEP("AR92x7 Version", modal_hdr->version);
 116        PR_EEP("DriverBias1", modal_hdr->db1);
 117        PR_EEP("DriverBias2", modal_hdr->db1);
 118        PR_EEP("CCK OutputBias", modal_hdr->ob_cck);
 119        PR_EEP("PSK OutputBias", modal_hdr->ob_psk);
 120        PR_EEP("QAM OutputBias", modal_hdr->ob_qam);
 121        PR_EEP("PAL_OFF OutputBias", modal_hdr->ob_pal_off);
 122
 123        return len;
 124}
 125
 126static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
 127                                       u8 *buf, u32 len, u32 size)
 128{
 129        struct ar9287_eeprom *eep = &ah->eeprom.map9287;
 130        struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
 131        u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);
 132
 133        if (!dump_base_hdr) {
 134                len += scnprintf(buf + len, size - len,
 135                                 "%20s :\n", "2GHz modal Header");
 136                len = ar9287_dump_modal_eeprom(buf, len, size,
 137                                                &eep->modalHeader);
 138                goto out;
 139        }
 140
 141        PR_EEP("Major Version", ath9k_hw_ar9287_get_eeprom_ver(ah));
 142        PR_EEP("Minor Version", ath9k_hw_ar9287_get_eeprom_rev(ah));
 143        PR_EEP("Checksum", le16_to_cpu(pBase->checksum));
 144        PR_EEP("Length", le16_to_cpu(pBase->length));
 145        PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
 146        PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
 147        PR_EEP("TX Mask", pBase->txMask);
 148        PR_EEP("RX Mask", pBase->rxMask);
 149        PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
 150        PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
 151        PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
 152                                        AR5416_OPFLAGS_N_2G_HT20));
 153        PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
 154                                        AR5416_OPFLAGS_N_2G_HT40));
 155        PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
 156                                        AR5416_OPFLAGS_N_5G_HT20));
 157        PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
 158                                        AR5416_OPFLAGS_N_5G_HT40));
 159        PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));
 160        PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);
 161        PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);
 162        PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);
 163        PR_EEP("Power Table Offset", pBase->pwrTableOffset);
 164        PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
 165
 166        len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
 167                         pBase->macAddr);
 168
 169out:
 170        if (len > size)
 171                len = size;
 172
 173        return len;
 174}
 175#else
 176static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
 177                                       u8 *buf, u32 len, u32 size)
 178{
 179        return 0;
 180}
 181#endif
 182
 183
 184static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
 185{
 186        u32 el;
 187        int i, err;
 188        bool need_swap;
 189        struct ar9287_eeprom *eep = &ah->eeprom.map9287;
 190
 191        err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287);
 192        if (err)
 193                return err;
 194
 195        if (need_swap)
 196                el = swab16((__force u16)eep->baseEepHeader.length);
 197        else
 198                el = le16_to_cpu(eep->baseEepHeader.length);
 199
 200        el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
 201        if (!ath9k_hw_nvram_validate_checksum(ah, el))
 202                return -EINVAL;
 203
 204        if (need_swap) {
 205                EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
 206                EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);
 207                EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);
 208                EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]);
 209                EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]);
 210                EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent);
 211                EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);
 212                EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);
 213                EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon);
 214
 215                for (i = 0; i < AR9287_MAX_CHAINS; i++)
 216                        EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);
 217
 218                for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
 219                        EEPROM_FIELD_SWAB16(
 220                                eep->modalHeader.spurChans[i].spurChan);
 221        }
 222
 223        if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER,
 224            AR5416_EEP_NO_BACK_VER))
 225                return -EINVAL;
 226
 227        return 0;
 228}
 229
 230#undef SIZE_EEPROM_AR9287
 231
 232static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
 233                                      enum eeprom_param param)
 234{
 235        struct ar9287_eeprom *eep = &ah->eeprom.map9287;
 236        struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
 237        struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
 238        u16 ver_minor = ath9k_hw_ar9287_get_eeprom_rev(ah);
 239
 240        switch (param) {
 241        case EEP_NFTHRESH_2:
 242                return pModal->noiseFloorThreshCh[0];
 243        case EEP_MAC_LSW:
 244                return get_unaligned_be16(pBase->macAddr);
 245        case EEP_MAC_MID:
 246                return get_unaligned_be16(pBase->macAddr + 2);
 247        case EEP_MAC_MSW:
 248                return get_unaligned_be16(pBase->macAddr + 4);
 249        case EEP_REG_0:
 250                return le16_to_cpu(pBase->regDmn[0]);
 251        case EEP_OP_CAP:
 252                return le16_to_cpu(pBase->deviceCap);
 253        case EEP_OP_MODE:
 254                return pBase->opCapFlags;
 255        case EEP_RF_SILENT:
 256                return le16_to_cpu(pBase->rfSilent);
 257        case EEP_TX_MASK:
 258                return pBase->txMask;
 259        case EEP_RX_MASK:
 260                return pBase->rxMask;
 261        case EEP_DEV_TYPE:
 262                return pBase->deviceType;
 263        case EEP_OL_PWRCTRL:
 264                return pBase->openLoopPwrCntl;
 265        case EEP_TEMPSENSE_SLOPE:
 266                if (ver_minor >= AR9287_EEP_MINOR_VER_2)
 267                        return pBase->tempSensSlope;
 268                else
 269                        return 0;
 270        case EEP_TEMPSENSE_SLOPE_PAL_ON:
 271                if (ver_minor >= AR9287_EEP_MINOR_VER_3)
 272                        return pBase->tempSensSlopePalOn;
 273                else
 274                        return 0;
 275        case EEP_ANTENNA_GAIN_2G:
 276                return max_t(u8, pModal->antennaGainCh[0],
 277                                 pModal->antennaGainCh[1]);
 278        default:
 279                return 0;
 280        }
 281}
 282
 283static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
 284                            struct ath9k_channel *chan,
 285                            struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
 286                            u8 *pCalChans,  u16 availPiers, int8_t *pPwr)
 287{
 288        u16 idxL = 0, idxR = 0, numPiers;
 289        bool match;
 290        struct chan_centers centers;
 291
 292        ath9k_hw_get_channel_centers(ah, chan, &centers);
 293
 294        for (numPiers = 0; numPiers < availPiers; numPiers++) {
 295                if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED)
 296                        break;
 297        }
 298
 299        match = ath9k_hw_get_lower_upper_index(
 300                (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
 301                pCalChans, numPiers, &idxL, &idxR);
 302
 303        if (match) {
 304                *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
 305        } else {
 306                *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
 307                         (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
 308        }
 309
 310}
 311
 312static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
 313                                          int32_t txPower, u16 chain)
 314{
 315        u32 tmpVal;
 316        u32 a;
 317
 318        /* Enable OLPC for chain 0 */
 319
 320        tmpVal = REG_READ(ah, 0xa270);
 321        tmpVal = tmpVal & 0xFCFFFFFF;
 322        tmpVal = tmpVal | (0x3 << 24);
 323        REG_WRITE(ah, 0xa270, tmpVal);
 324
 325        /* Enable OLPC for chain 1 */
 326
 327        tmpVal = REG_READ(ah, 0xb270);
 328        tmpVal = tmpVal & 0xFCFFFFFF;
 329        tmpVal = tmpVal | (0x3 << 24);
 330        REG_WRITE(ah, 0xb270, tmpVal);
 331
 332        /* Write the OLPC ref power for chain 0 */
 333
 334        if (chain == 0) {
 335                tmpVal = REG_READ(ah, 0xa398);
 336                tmpVal = tmpVal & 0xff00ffff;
 337                a = (txPower)&0xff;
 338                tmpVal = tmpVal | (a << 16);
 339                REG_WRITE(ah, 0xa398, tmpVal);
 340        }
 341
 342        /* Write the OLPC ref power for chain 1 */
 343
 344        if (chain == 1) {
 345                tmpVal = REG_READ(ah, 0xb398);
 346                tmpVal = tmpVal & 0xff00ffff;
 347                a = (txPower)&0xff;
 348                tmpVal = tmpVal | (a << 16);
 349                REG_WRITE(ah, 0xb398, tmpVal);
 350        }
 351}
 352
 353static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
 354                                                struct ath9k_channel *chan)
 355{
 356        struct cal_data_per_freq_ar9287 *pRawDataset;
 357        struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
 358        u8 *pCalBChans = NULL;
 359        u16 pdGainOverlap_t2;
 360        u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
 361        u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
 362        u16 numPiers = 0, i, j;
 363        u16 numXpdGain, xpdMask;
 364        u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0};
 365        u32 reg32, regOffset, regChainOffset, regval;
 366        int16_t diff = 0;
 367        struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
 368
 369        xpdMask = pEepData->modalHeader.xpdGain;
 370
 371        if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
 372                pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
 373        else
 374                pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
 375                                            AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
 376
 377        if (IS_CHAN_2GHZ(chan)) {
 378                pCalBChans = pEepData->calFreqPier2G;
 379                numPiers = AR9287_NUM_2G_CAL_PIERS;
 380                if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
 381                        pRawDatasetOpenLoop =
 382                        (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0];
 383                        ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
 384                }
 385        }
 386
 387        numXpdGain = 0;
 388
 389        /* Calculate the value of xpdgains from the xpdGain Mask */
 390        for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
 391                if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
 392                        if (numXpdGain >= AR5416_NUM_PD_GAINS)
 393                                break;
 394                        xpdGainValues[numXpdGain] =
 395                                (u16)(AR5416_PD_GAINS_IN_MASK-i);
 396                        numXpdGain++;
 397                }
 398        }
 399
 400        REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
 401                      (numXpdGain - 1) & 0x3);
 402        REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
 403                      xpdGainValues[0]);
 404        REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
 405                      xpdGainValues[1]);
 406        REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
 407                      xpdGainValues[2]);
 408
 409        for (i = 0; i < AR9287_MAX_CHAINS; i++) {
 410                regChainOffset = i * 0x1000;
 411
 412                if (pEepData->baseEepHeader.txMask & (1 << i)) {
 413                        pRawDatasetOpenLoop =
 414                        (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i];
 415
 416                        if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
 417                                int8_t txPower;
 418                                ar9287_eeprom_get_tx_gain_index(ah, chan,
 419                                                        pRawDatasetOpenLoop,
 420                                                        pCalBChans, numPiers,
 421                                                        &txPower);
 422                                ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
 423                        } else {
 424                                pRawDataset =
 425                                        (struct cal_data_per_freq_ar9287 *)
 426                                        pEepData->calPierData2G[i];
 427
 428                                ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
 429                                                           pRawDataset,
 430                                                           pCalBChans, numPiers,
 431                                                           pdGainOverlap_t2,
 432                                                           gainBoundaries,
 433                                                           pdadcValues,
 434                                                           numXpdGain);
 435                        }
 436
 437                        ENABLE_REGWRITE_BUFFER(ah);
 438
 439                        if (i == 0) {
 440                                if (!ath9k_hw_ar9287_get_eeprom(ah,
 441                                                        EEP_OL_PWRCTRL)) {
 442
 443                                        regval = SM(pdGainOverlap_t2,
 444                                                    AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
 445                                                | SM(gainBoundaries[0],
 446                                                     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
 447                                                | SM(gainBoundaries[1],
 448                                                     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
 449                                                | SM(gainBoundaries[2],
 450                                                     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
 451                                                | SM(gainBoundaries[3],
 452                                                     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4);
 453
 454                                        REG_WRITE(ah,
 455                                                  AR_PHY_TPCRG5 + regChainOffset,
 456                                                  regval);
 457                                }
 458                        }
 459
 460                        if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
 461                            pEepData->baseEepHeader.pwrTableOffset) {
 462                                diff = (u16)(pEepData->baseEepHeader.pwrTableOffset -
 463                                             (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
 464                                diff *= 2;
 465
 466                                for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++)
 467                                        pdadcValues[j] = pdadcValues[j+diff];
 468
 469                                for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff);
 470                                     j < AR5416_NUM_PDADC_VALUES; j++)
 471                                        pdadcValues[j] =
 472                                          pdadcValues[AR5416_NUM_PDADC_VALUES-diff];
 473                        }
 474
 475                        if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
 476                                regOffset = AR_PHY_BASE +
 477                                        (672 << 2) + regChainOffset;
 478
 479                                for (j = 0; j < 32; j++) {
 480                                        reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
 481
 482                                        REG_WRITE(ah, regOffset, reg32);
 483                                        regOffset += 4;
 484                                }
 485                        }
 486                        REGWRITE_BUFFER_FLUSH(ah);
 487                }
 488        }
 489}
 490
 491static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
 492                                                     struct ath9k_channel *chan,
 493                                                     int16_t *ratesArray,
 494                                                     u16 cfgCtl,
 495                                                     u16 antenna_reduction,
 496                                                     u16 powerLimit)
 497{
 498#define CMP_CTL \
 499        (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
 500         pEepData->ctlIndex[i])
 501
 502#define CMP_NO_CTL \
 503        (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
 504         ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
 505
 506        u16 twiceMaxEdgePower;
 507        int i;
 508        struct cal_ctl_data_ar9287 *rep;
 509        struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
 510                                    targetPowerCck = {0, {0, 0, 0, 0} };
 511        struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
 512                                    targetPowerCckExt = {0, {0, 0, 0, 0} };
 513        struct cal_target_power_ht targetPowerHt20,
 514                                    targetPowerHt40 = {0, {0, 0, 0, 0} };
 515        u16 scaledPower = 0, minCtlPower;
 516        static const u16 ctlModesFor11g[] = {
 517                CTL_11B, CTL_11G, CTL_2GHT20,
 518                CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
 519        };
 520        u16 numCtlModes = 0;
 521        const u16 *pCtlMode = NULL;
 522        u16 ctlMode, freq;
 523        struct chan_centers centers;
 524        int tx_chainmask;
 525        u16 twiceMinEdgePower;
 526        struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
 527        tx_chainmask = ah->txchainmask;
 528
 529        ath9k_hw_get_channel_centers(ah, chan, &centers);
 530        scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit,
 531                                                antenna_reduction);
 532
 533        /*
 534         * Get TX power from EEPROM.
 535         */
 536        if (IS_CHAN_2GHZ(chan)) {
 537                /* CTL_11B, CTL_11G, CTL_2GHT20 */
 538                numCtlModes =
 539                        ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
 540
 541                pCtlMode = ctlModesFor11g;
 542
 543                ath9k_hw_get_legacy_target_powers(ah, chan,
 544                                                  pEepData->calTargetPowerCck,
 545                                                  AR9287_NUM_2G_CCK_TARGET_POWERS,
 546                                                  &targetPowerCck, 4, false);
 547                ath9k_hw_get_legacy_target_powers(ah, chan,
 548                                                  pEepData->calTargetPower2G,
 549                                                  AR9287_NUM_2G_20_TARGET_POWERS,
 550                                                  &targetPowerOfdm, 4, false);
 551                ath9k_hw_get_target_powers(ah, chan,
 552                                           pEepData->calTargetPower2GHT20,
 553                                           AR9287_NUM_2G_20_TARGET_POWERS,
 554                                           &targetPowerHt20, 8, false);
 555
 556                if (IS_CHAN_HT40(chan)) {
 557                        /* All 2G CTLs */
 558                        numCtlModes = ARRAY_SIZE(ctlModesFor11g);
 559                        ath9k_hw_get_target_powers(ah, chan,
 560                                                   pEepData->calTargetPower2GHT40,
 561                                                   AR9287_NUM_2G_40_TARGET_POWERS,
 562                                                   &targetPowerHt40, 8, true);
 563                        ath9k_hw_get_legacy_target_powers(ah, chan,
 564                                                  pEepData->calTargetPowerCck,
 565                                                  AR9287_NUM_2G_CCK_TARGET_POWERS,
 566                                                  &targetPowerCckExt, 4, true);
 567                        ath9k_hw_get_legacy_target_powers(ah, chan,
 568                                                  pEepData->calTargetPower2G,
 569                                                  AR9287_NUM_2G_20_TARGET_POWERS,
 570                                                  &targetPowerOfdmExt, 4, true);
 571                }
 572        }
 573
 574        for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
 575                bool isHt40CtlMode =
 576                        (pCtlMode[ctlMode] == CTL_2GHT40) ? true : false;
 577
 578                if (isHt40CtlMode)
 579                        freq = centers.synth_center;
 580                else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
 581                        freq = centers.ext_center;
 582                else
 583                        freq = centers.ctl_center;
 584
 585                twiceMaxEdgePower = MAX_RATE_POWER;
 586                /* Walk through the CTL indices stored in EEPROM */
 587                for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
 588                        struct cal_ctl_edges *pRdEdgesPower;
 589
 590                        /*
 591                         * Compare test group from regulatory channel list
 592                         * with test mode from pCtlMode list
 593                         */
 594                        if (CMP_CTL || CMP_NO_CTL) {
 595                                rep = &(pEepData->ctlData[i]);
 596                                pRdEdgesPower =
 597                                rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1];
 598
 599                                twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
 600                                                                pRdEdgesPower,
 601                                                                IS_CHAN_2GHZ(chan),
 602                                                                AR5416_NUM_BAND_EDGES);
 603
 604                                if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
 605                                        twiceMaxEdgePower = min(twiceMaxEdgePower,
 606                                                                twiceMinEdgePower);
 607                                } else {
 608                                        twiceMaxEdgePower = twiceMinEdgePower;
 609                                        break;
 610                                }
 611                        }
 612                }
 613
 614                minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
 615
 616                /* Apply ctl mode to correct target power set */
 617                switch (pCtlMode[ctlMode]) {
 618                case CTL_11B:
 619                        for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
 620                                targetPowerCck.tPow2x[i] =
 621                                        (u8)min((u16)targetPowerCck.tPow2x[i],
 622                                                minCtlPower);
 623                        }
 624                        break;
 625                case CTL_11A:
 626                case CTL_11G:
 627                        for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
 628                                targetPowerOfdm.tPow2x[i] =
 629                                        (u8)min((u16)targetPowerOfdm.tPow2x[i],
 630                                                minCtlPower);
 631                        }
 632                        break;
 633                case CTL_5GHT20:
 634                case CTL_2GHT20:
 635                        for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
 636                                targetPowerHt20.tPow2x[i] =
 637                                        (u8)min((u16)targetPowerHt20.tPow2x[i],
 638                                                minCtlPower);
 639                        }
 640                        break;
 641                case CTL_11B_EXT:
 642                        targetPowerCckExt.tPow2x[0] =
 643                                (u8)min((u16)targetPowerCckExt.tPow2x[0],
 644                                        minCtlPower);
 645                        break;
 646                case CTL_11A_EXT:
 647                case CTL_11G_EXT:
 648                        targetPowerOfdmExt.tPow2x[0] =
 649                                (u8)min((u16)targetPowerOfdmExt.tPow2x[0],
 650                                        minCtlPower);
 651                        break;
 652                case CTL_5GHT40:
 653                case CTL_2GHT40:
 654                        for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
 655                                targetPowerHt40.tPow2x[i] =
 656                                        (u8)min((u16)targetPowerHt40.tPow2x[i],
 657                                                minCtlPower);
 658                        }
 659                        break;
 660                default:
 661                        break;
 662                }
 663        }
 664
 665        /* Now set the rates array */
 666
 667        ratesArray[rate6mb] =
 668        ratesArray[rate9mb] =
 669        ratesArray[rate12mb] =
 670        ratesArray[rate18mb] =
 671        ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0];
 672
 673        ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
 674        ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
 675        ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
 676        ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
 677
 678        for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
 679                ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
 680
 681        if (IS_CHAN_2GHZ(chan)) {
 682                ratesArray[rate1l] = targetPowerCck.tPow2x[0];
 683                ratesArray[rate2s] =
 684                ratesArray[rate2l] = targetPowerCck.tPow2x[1];
 685                ratesArray[rate5_5s] =
 686                ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
 687                ratesArray[rate11s] =
 688                ratesArray[rate11l] = targetPowerCck.tPow2x[3];
 689        }
 690        if (IS_CHAN_HT40(chan)) {
 691                for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
 692                        ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
 693
 694                ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
 695                ratesArray[rateDupCck]  = targetPowerHt40.tPow2x[0];
 696                ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
 697
 698                if (IS_CHAN_2GHZ(chan))
 699                        ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
 700        }
 701
 702#undef CMP_CTL
 703#undef CMP_NO_CTL
 704}
 705
 706static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
 707                                        struct ath9k_channel *chan, u16 cfgCtl,
 708                                        u8 twiceAntennaReduction,
 709                                        u8 powerLimit, bool test)
 710{
 711        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 712        struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
 713        struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
 714        int16_t ratesArray[Ar5416RateSize];
 715        u8 ht40PowerIncForPdadc = 2;
 716        int i;
 717
 718        memset(ratesArray, 0, sizeof(ratesArray));
 719
 720        if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
 721                ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
 722
 723        ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
 724                                                 &ratesArray[0], cfgCtl,
 725                                                 twiceAntennaReduction,
 726                                                 powerLimit);
 727
 728        ath9k_hw_set_ar9287_power_cal_table(ah, chan);
 729
 730        regulatory->max_power_level = 0;
 731        for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 732                if (ratesArray[i] > MAX_RATE_POWER)
 733                        ratesArray[i] = MAX_RATE_POWER;
 734
 735                if (ratesArray[i] > regulatory->max_power_level)
 736                        regulatory->max_power_level = ratesArray[i];
 737        }
 738
 739        ath9k_hw_update_regulatory_maxpower(ah);
 740
 741        if (test)
 742                return;
 743
 744        for (i = 0; i < Ar5416RateSize; i++)
 745                ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
 746
 747        ENABLE_REGWRITE_BUFFER(ah);
 748
 749        /* OFDM power per rate */
 750        REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
 751                  ATH9K_POW_SM(ratesArray[rate18mb], 24)
 752                  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
 753                  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
 754                  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
 755
 756        REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
 757                  ATH9K_POW_SM(ratesArray[rate54mb], 24)
 758                  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
 759                  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
 760                  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
 761
 762        /* CCK power per rate */
 763        if (IS_CHAN_2GHZ(chan)) {
 764                REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
 765                          ATH9K_POW_SM(ratesArray[rate2s], 24)
 766                          | ATH9K_POW_SM(ratesArray[rate2l], 16)
 767                          | ATH9K_POW_SM(ratesArray[rateXr], 8)
 768                          | ATH9K_POW_SM(ratesArray[rate1l], 0));
 769                REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
 770                          ATH9K_POW_SM(ratesArray[rate11s], 24)
 771                          | ATH9K_POW_SM(ratesArray[rate11l], 16)
 772                          | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
 773                          | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
 774        }
 775
 776        /* HT20 power per rate */
 777        REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
 778                  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
 779                  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
 780                  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
 781                  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
 782
 783        REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
 784                  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
 785                  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
 786                  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
 787                  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
 788
 789        /* HT40 power per rate */
 790        if (IS_CHAN_HT40(chan)) {
 791                if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
 792                        REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
 793                                  ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
 794                                  | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
 795                                  | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
 796                                  | ATH9K_POW_SM(ratesArray[rateHt40_0], 0));
 797
 798                        REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
 799                                  ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
 800                                  | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
 801                                  | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
 802                                  | ATH9K_POW_SM(ratesArray[rateHt40_4], 0));
 803                } else {
 804                        REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
 805                                  ATH9K_POW_SM(ratesArray[rateHt40_3] +
 806                                               ht40PowerIncForPdadc, 24)
 807                                  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
 808                                                 ht40PowerIncForPdadc, 16)
 809                                  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
 810                                                 ht40PowerIncForPdadc, 8)
 811                                  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
 812                                                 ht40PowerIncForPdadc, 0));
 813
 814                        REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
 815                                  ATH9K_POW_SM(ratesArray[rateHt40_7] +
 816                                               ht40PowerIncForPdadc, 24)
 817                                  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
 818                                                 ht40PowerIncForPdadc, 16)
 819                                  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
 820                                                 ht40PowerIncForPdadc, 8)
 821                                  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
 822                                                 ht40PowerIncForPdadc, 0));
 823                }
 824
 825                /* Dup/Ext power per rate */
 826                REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
 827                          ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
 828                          | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
 829                          | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
 830                          | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
 831        }
 832
 833        /* TPC initializations */
 834        if (ah->tpc_enabled) {
 835                int ht40_delta;
 836
 837                ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;
 838                ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);
 839                /* Enable TPC */
 840                REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,
 841                        MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
 842        } else {
 843                /* Disable TPC */
 844                REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);
 845        }
 846
 847        REGWRITE_BUFFER_FLUSH(ah);
 848}
 849
 850static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
 851                                             struct ath9k_channel *chan)
 852{
 853        struct ar9287_eeprom *eep = &ah->eeprom.map9287;
 854        struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
 855        u32 regChainOffset, regval;
 856        u8 txRxAttenLocal;
 857        int i;
 858
 859        pModal = &eep->modalHeader;
 860
 861        REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon));
 862
 863        for (i = 0; i < AR9287_MAX_CHAINS; i++) {
 864                regChainOffset = i * 0x1000;
 865
 866                REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
 867                          le32_to_cpu(pModal->antCtrlChain[i]));
 868
 869                REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
 870                          (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
 871                           & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
 872                               AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
 873                          SM(pModal->iqCalICh[i],
 874                             AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
 875                          SM(pModal->iqCalQCh[i],
 876                             AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
 877
 878                txRxAttenLocal = pModal->txRxAttenCh[i];
 879
 880                REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
 881                              AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
 882                              pModal->bswMargin[i]);
 883                REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
 884                              AR_PHY_GAIN_2GHZ_XATTEN1_DB,
 885                              pModal->bswAtten[i]);
 886                REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
 887                              AR9280_PHY_RXGAIN_TXRX_ATTEN,
 888                              txRxAttenLocal);
 889                REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
 890                              AR9280_PHY_RXGAIN_TXRX_MARGIN,
 891                              pModal->rxTxMarginCh[i]);
 892        }
 893
 894
 895        if (IS_CHAN_HT40(chan))
 896                REG_RMW_FIELD(ah, AR_PHY_SETTLING,
 897                              AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
 898        else
 899                REG_RMW_FIELD(ah, AR_PHY_SETTLING,
 900                              AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
 901
 902        REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
 903                      AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
 904
 905        REG_WRITE(ah, AR_PHY_RF_CTL4,
 906                  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
 907                  | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
 908                  | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
 909                  | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
 910
 911        REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
 912                      AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
 913
 914        REG_RMW_FIELD(ah, AR_PHY_CCA,
 915                      AR9280_PHY_CCA_THRESH62, pModal->thresh62);
 916        REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
 917                      AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
 918
 919        regval = REG_READ(ah, AR9287_AN_RF2G3_CH0);
 920        regval &= ~(AR9287_AN_RF2G3_DB1 |
 921                    AR9287_AN_RF2G3_DB2 |
 922                    AR9287_AN_RF2G3_OB_CCK |
 923                    AR9287_AN_RF2G3_OB_PSK |
 924                    AR9287_AN_RF2G3_OB_QAM |
 925                    AR9287_AN_RF2G3_OB_PAL_OFF);
 926        regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
 927                   SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
 928                   SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
 929                   SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
 930                   SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
 931                   SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
 932
 933        ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval);
 934
 935        regval = REG_READ(ah, AR9287_AN_RF2G3_CH1);
 936        regval &= ~(AR9287_AN_RF2G3_DB1 |
 937                    AR9287_AN_RF2G3_DB2 |
 938                    AR9287_AN_RF2G3_OB_CCK |
 939                    AR9287_AN_RF2G3_OB_PSK |
 940                    AR9287_AN_RF2G3_OB_QAM |
 941                    AR9287_AN_RF2G3_OB_PAL_OFF);
 942        regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
 943                   SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
 944                   SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
 945                   SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
 946                   SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
 947                   SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
 948
 949        ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval);
 950
 951        REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
 952                      AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
 953        REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
 954                      AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
 955
 956        ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
 957                                  AR9287_AN_TOP2_XPABIAS_LVL,
 958                                  AR9287_AN_TOP2_XPABIAS_LVL_S,
 959                                  pModal->xpaBiasLvl);
 960}
 961
 962static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
 963                                            u16 i, bool is2GHz)
 964{
 965        __le16 spur_ch = ah->eeprom.map9287.modalHeader.spurChans[i].spurChan;
 966
 967        return le16_to_cpu(spur_ch);
 968}
 969
 970static u8 ath9k_hw_ar9287_get_eepmisc(struct ath_hw *ah)
 971{
 972        return ah->eeprom.map9287.baseEepHeader.eepMisc;
 973}
 974
 975const struct eeprom_ops eep_ar9287_ops = {
 976        .check_eeprom           = ath9k_hw_ar9287_check_eeprom,
 977        .get_eeprom             = ath9k_hw_ar9287_get_eeprom,
 978        .fill_eeprom            = ath9k_hw_ar9287_fill_eeprom,
 979        .dump_eeprom            = ath9k_hw_ar9287_dump_eeprom,
 980        .get_eeprom_ver         = ath9k_hw_ar9287_get_eeprom_ver,
 981        .get_eeprom_rev         = ath9k_hw_ar9287_get_eeprom_rev,
 982        .set_board_values       = ath9k_hw_ar9287_set_board_values,
 983        .set_txpower            = ath9k_hw_ar9287_set_txpower,
 984        .get_spur_channel       = ath9k_hw_ar9287_get_spur_channel,
 985        .get_eepmisc            = ath9k_hw_ar9287_get_eepmisc
 986};
 987