Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2008-2011 Atheros Communications Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #include <linux/moduleparam.h>
0018 #include "hw.h"
0019 #include "ar5008_initvals.h"
0020 #include "ar9001_initvals.h"
0021 #include "ar9002_initvals.h"
0022 #include "ar9002_phy.h"
0023 
0024 /* General hardware code for the A5008/AR9001/AR9002 hadware families */
0025 
0026 static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
0027 {
0028     if (AR_SREV_9271(ah)) {
0029         INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271);
0030         INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271);
0031         INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg);
0032         return 0;
0033     }
0034 
0035     INIT_INI_ARRAY(&ah->iniPcieSerdes,
0036                ar9280PciePhy_clkreq_always_on_L1_9280);
0037 
0038     if (AR_SREV_9287_11_OR_LATER(ah)) {
0039         INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
0040         INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1);
0041     } else if (AR_SREV_9285_12_OR_LATER(ah)) {
0042         INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2);
0043         INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2);
0044     } else if (AR_SREV_9280_20_OR_LATER(ah)) {
0045         INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2);
0046         INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2);
0047 
0048         INIT_INI_ARRAY(&ah->iniModesFastClock,
0049                    ar9280Modes_fast_clock_9280_2);
0050     } else if (AR_SREV_9160_10_OR_LATER(ah)) {
0051         INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160);
0052         INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160);
0053         if (AR_SREV_9160_11(ah)) {
0054             INIT_INI_ARRAY(&ah->iniAddac,
0055                        ar5416Addac_9160_1_1);
0056         } else {
0057             INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160);
0058         }
0059     } else if (AR_SREV_9100_OR_LATER(ah)) {
0060         INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
0061         INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
0062         INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
0063     } else {
0064         INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
0065         INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
0066         INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
0067     }
0068 
0069     if (!AR_SREV_9280_20_OR_LATER(ah)) {
0070         /* Common for AR5416, AR913x, AR9160 */
0071         INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
0072 
0073         /* Common for AR913x, AR9160 */
0074         if (!AR_SREV_5416(ah))
0075             INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
0076         else
0077             INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
0078     }
0079 
0080     /* iniAddac needs to be modified for these chips */
0081     if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
0082         struct ar5416IniArray *addac = &ah->iniAddac;
0083         u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
0084         u32 *data;
0085 
0086         data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
0087         if (!data)
0088             return -ENOMEM;
0089 
0090         memcpy(data, addac->ia_array, size);
0091         addac->ia_array = data;
0092 
0093         if (!AR_SREV_5416_22_OR_LATER(ah)) {
0094             /* override CLKDRV value */
0095             INI_RA(addac, 31,1) = 0;
0096         }
0097     }
0098     if (AR_SREV_9287_11_OR_LATER(ah)) {
0099         INIT_INI_ARRAY(&ah->iniCckfirNormal,
0100                ar9287Common_normal_cck_fir_coeff_9287_1_1);
0101         INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
0102                ar9287Common_japan_2484_cck_fir_coeff_9287_1_1);
0103     }
0104     return 0;
0105 }
0106 
0107 static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
0108 {
0109     u32 rxgain_type;
0110 
0111     if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_17) {
0112         rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
0113 
0114         if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
0115             INIT_INI_ARRAY(&ah->iniModesRxGain,
0116                        ar9280Modes_backoff_13db_rxgain_9280_2);
0117         else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
0118             INIT_INI_ARRAY(&ah->iniModesRxGain,
0119                        ar9280Modes_backoff_23db_rxgain_9280_2);
0120         else
0121             INIT_INI_ARRAY(&ah->iniModesRxGain,
0122                        ar9280Modes_original_rxgain_9280_2);
0123     } else {
0124         INIT_INI_ARRAY(&ah->iniModesRxGain,
0125                    ar9280Modes_original_rxgain_9280_2);
0126     }
0127 }
0128 
0129 static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
0130 {
0131     if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) {
0132         if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
0133             INIT_INI_ARRAY(&ah->iniModesTxGain,
0134                        ar9280Modes_high_power_tx_gain_9280_2);
0135         else
0136             INIT_INI_ARRAY(&ah->iniModesTxGain,
0137                        ar9280Modes_original_tx_gain_9280_2);
0138     } else {
0139         INIT_INI_ARRAY(&ah->iniModesTxGain,
0140                    ar9280Modes_original_tx_gain_9280_2);
0141     }
0142 }
0143 
0144 static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
0145 {
0146     if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
0147         INIT_INI_ARRAY(&ah->iniModesTxGain,
0148                    ar9271Modes_high_power_tx_gain_9271);
0149     else
0150         INIT_INI_ARRAY(&ah->iniModesTxGain,
0151                    ar9271Modes_normal_power_tx_gain_9271);
0152 }
0153 
0154 static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
0155 {
0156     u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
0157 
0158     if (AR_SREV_9287_11_OR_LATER(ah))
0159         INIT_INI_ARRAY(&ah->iniModesRxGain,
0160                    ar9287Modes_rx_gain_9287_1_1);
0161     else if (AR_SREV_9280_20(ah))
0162         ar9280_20_hw_init_rxgain_ini(ah);
0163 
0164     if (AR_SREV_9271(ah)) {
0165         ar9271_hw_init_txgain_ini(ah, txgain_type);
0166     } else if (AR_SREV_9287_11_OR_LATER(ah)) {
0167         INIT_INI_ARRAY(&ah->iniModesTxGain,
0168                    ar9287Modes_tx_gain_9287_1_1);
0169     } else if (AR_SREV_9280_20(ah)) {
0170         ar9280_20_hw_init_txgain_ini(ah, txgain_type);
0171     } else if (AR_SREV_9285_12_OR_LATER(ah)) {
0172         /* txgain table */
0173         if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
0174             if (AR_SREV_9285E_20(ah)) {
0175                 INIT_INI_ARRAY(&ah->iniModesTxGain,
0176                            ar9285Modes_XE2_0_high_power);
0177             } else {
0178                 INIT_INI_ARRAY(&ah->iniModesTxGain,
0179                     ar9285Modes_high_power_tx_gain_9285_1_2);
0180             }
0181         } else {
0182             if (AR_SREV_9285E_20(ah)) {
0183                 INIT_INI_ARRAY(&ah->iniModesTxGain,
0184                            ar9285Modes_XE2_0_normal_power);
0185             } else {
0186                 INIT_INI_ARRAY(&ah->iniModesTxGain,
0187                     ar9285Modes_original_tx_gain_9285_1_2);
0188             }
0189         }
0190     }
0191 }
0192 
0193 /*
0194  * Helper for ASPM support.
0195  *
0196  * Disable PLL when in L0s as well as receiver clock when in L1.
0197  * This power saving option must be enabled through the SerDes.
0198  *
0199  * Programming the SerDes must go through the same 288 bit serial shift
0200  * register as the other analog registers.  Hence the 9 writes.
0201  */
0202 static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
0203                      bool power_off)
0204 {
0205     u8 i;
0206     u32 val;
0207 
0208     /* Nothing to do on restore for 11N */
0209     if (!power_off /* !restore */) {
0210         if (AR_SREV_9280_20_OR_LATER(ah)) {
0211             /*
0212              * AR9280 2.0 or later chips use SerDes values from the
0213              * initvals.h initialized depending on chipset during
0214              * __ath9k_hw_init()
0215              */
0216             for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
0217                 REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
0218                       INI_RA(&ah->iniPcieSerdes, i, 1));
0219             }
0220         } else {
0221             ENABLE_REGWRITE_BUFFER(ah);
0222 
0223             REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
0224             REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
0225 
0226             /* RX shut off when elecidle is asserted */
0227             REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
0228             REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
0229             REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
0230 
0231             /*
0232              * Ignore ah->ah_config.pcie_clock_req setting for
0233              * pre-AR9280 11n
0234              */
0235             REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
0236 
0237             REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
0238             REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
0239             REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
0240 
0241             /* Load the new settings */
0242             REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
0243 
0244             REGWRITE_BUFFER_FLUSH(ah);
0245         }
0246 
0247         udelay(1000);
0248     }
0249 
0250     if (power_off) {
0251         /* clear bit 19 to disable L1 */
0252         REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
0253 
0254         val = REG_READ(ah, AR_WA);
0255 
0256         /*
0257          * Set PCIe workaround bits
0258          * In AR9280 and AR9285, bit 14 in WA register (disable L1)
0259          * should only  be set when device enters D3 and be
0260          * cleared when device comes back to D0.
0261          */
0262         if (ah->config.pcie_waen) {
0263             if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
0264                 val |= AR_WA_D3_L1_DISABLE;
0265         } else {
0266             if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
0267                 if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
0268                     val |= AR_WA_D3_L1_DISABLE;
0269             } else if (AR_SREV_9280(ah)) {
0270                 if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
0271                     val |= AR_WA_D3_L1_DISABLE;
0272             }
0273         }
0274 
0275         if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
0276             /*
0277              * Disable bit 6 and 7 before entering D3 to
0278              * prevent system hang.
0279              */
0280             val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
0281         }
0282 
0283         if (AR_SREV_9280(ah))
0284             val |= AR_WA_BIT22;
0285 
0286         if (AR_SREV_9285E_20(ah))
0287             val |= AR_WA_BIT23;
0288 
0289         REG_WRITE(ah, AR_WA, val);
0290     } else {
0291         if (ah->config.pcie_waen) {
0292             val = ah->config.pcie_waen;
0293             val &= (~AR_WA_D3_L1_DISABLE);
0294         } else {
0295             if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
0296                 val = AR9285_WA_DEFAULT;
0297                 val &= (~AR_WA_D3_L1_DISABLE);
0298             } else if (AR_SREV_9280(ah)) {
0299                 /*
0300                  * For AR9280 chips, bit 22 of 0x4004
0301                  * needs to be set.
0302                  */
0303                 val = AR9280_WA_DEFAULT;
0304                 val &= (~AR_WA_D3_L1_DISABLE);
0305             } else {
0306                 val = AR_WA_DEFAULT;
0307             }
0308         }
0309 
0310         /* WAR for ASPM system hang */
0311         if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
0312             val |= (AR_WA_BIT6 | AR_WA_BIT7);
0313 
0314         if (AR_SREV_9285E_20(ah))
0315             val |= AR_WA_BIT23;
0316 
0317         REG_WRITE(ah, AR_WA, val);
0318 
0319         /* set bit 19 to allow forcing of pcie core into L1 state */
0320         REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
0321     }
0322 }
0323 
0324 static int ar9002_hw_get_radiorev(struct ath_hw *ah)
0325 {
0326     u32 val;
0327     int i;
0328 
0329     ENABLE_REGWRITE_BUFFER(ah);
0330 
0331     REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
0332     for (i = 0; i < 8; i++)
0333         REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
0334 
0335     REGWRITE_BUFFER_FLUSH(ah);
0336 
0337     val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
0338     val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
0339 
0340     return ath9k_hw_reverse_bits(val, 8);
0341 }
0342 
0343 int ar9002_hw_rf_claim(struct ath_hw *ah)
0344 {
0345     u32 val;
0346 
0347     REG_WRITE(ah, AR_PHY(0), 0x00000007);
0348 
0349     val = ar9002_hw_get_radiorev(ah);
0350     switch (val & AR_RADIO_SREV_MAJOR) {
0351     case 0:
0352         val = AR_RAD5133_SREV_MAJOR;
0353         break;
0354     case AR_RAD5133_SREV_MAJOR:
0355     case AR_RAD5122_SREV_MAJOR:
0356     case AR_RAD2133_SREV_MAJOR:
0357     case AR_RAD2122_SREV_MAJOR:
0358         break;
0359     default:
0360         ath_err(ath9k_hw_common(ah),
0361             "Radio Chip Rev 0x%02X not supported\n",
0362             val & AR_RADIO_SREV_MAJOR);
0363         return -EOPNOTSUPP;
0364     }
0365 
0366     ah->hw_version.analog5GhzRev = val;
0367 
0368     return 0;
0369 }
0370 
0371 void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
0372 {
0373     if (AR_SREV_9287_13_OR_LATER(ah)) {
0374         REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
0375                 AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
0376         REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
0377         REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
0378                 AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
0379         REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
0380                 AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
0381     }
0382 }
0383 
0384 static void ar9002_hw_init_hang_checks(struct ath_hw *ah)
0385 {
0386     if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
0387         ah->config.hw_hang_checks |= HW_BB_RIFS_HANG;
0388         ah->config.hw_hang_checks |= HW_BB_DFS_HANG;
0389     }
0390 
0391     if (AR_SREV_9280(ah))
0392         ah->config.hw_hang_checks |= HW_BB_RX_CLEAR_STUCK_HANG;
0393 
0394     if (AR_SREV_5416(ah) || AR_SREV_9100(ah) || AR_SREV_9160(ah))
0395         ah->config.hw_hang_checks |= HW_MAC_HANG;
0396 }
0397 
0398 /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
0399 int ar9002_hw_attach_ops(struct ath_hw *ah)
0400 {
0401     struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
0402     struct ath_hw_ops *ops = ath9k_hw_ops(ah);
0403     int ret;
0404 
0405     ret = ar9002_hw_init_mode_regs(ah);
0406     if (ret)
0407         return ret;
0408 
0409     priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
0410     priv_ops->init_hang_checks = ar9002_hw_init_hang_checks;
0411 
0412     ops->config_pci_powersave = ar9002_hw_configpcipowersave;
0413 
0414     ret = ar5008_hw_attach_phy_ops(ah);
0415     if (ret)
0416         return ret;
0417 
0418     if (AR_SREV_9280_20_OR_LATER(ah))
0419         ar9002_hw_attach_phy_ops(ah);
0420 
0421     ar9002_hw_attach_calib_ops(ah);
0422     ar9002_hw_attach_mac_ops(ah);
0423     return 0;
0424 }
0425 
0426 void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
0427 {
0428     u32 modesIndex;
0429     int i;
0430 
0431     if (IS_CHAN_5GHZ(chan))
0432         modesIndex = IS_CHAN_HT40(chan) ? 2 : 1;
0433     else
0434         modesIndex = IS_CHAN_HT40(chan) ? 3 : 4;
0435 
0436     ENABLE_REGWRITE_BUFFER(ah);
0437 
0438     for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
0439         u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
0440         u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
0441         u32 val_orig;
0442 
0443         if (reg == AR_PHY_CCK_DETECT) {
0444             val_orig = REG_READ(ah, reg);
0445             val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
0446             val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
0447 
0448             REG_WRITE(ah, reg, val|val_orig);
0449         } else
0450             REG_WRITE(ah, reg, val);
0451     }
0452 
0453     REGWRITE_BUFFER_FLUSH(ah);
0454 }