iPXE
ath9k_ar9002_hw.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008-2011 Atheros Communications Inc.
00003  *
00004  * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
00005  * Original from Linux kernel 3.0.1
00006  *
00007  * Permission to use, copy, modify, and/or distribute this software for any
00008  * purpose with or without fee is hereby granted, provided that the above
00009  * copyright notice and this permission notice appear in all copies.
00010  *
00011  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00012  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00013  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00014  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00015  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00016  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00017  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00018  */
00019 
00020 FILE_LICENCE ( BSD2 );
00021 
00022 #include "hw.h"
00023 #include "ar5008_initvals.h"
00024 #include "ar9001_initvals.h"
00025 #include "ar9002_initvals.h"
00026 #include "ar9002_phy.h"
00027 
00028 int modparam_force_new_ani;
00029 
00030 /* General hardware code for the A5008/AR9001/AR9002 hadware families */
00031 
00032 static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
00033 {
00034         if (AR_SREV_9271(ah)) {
00035                 INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
00036                                ARRAY_SIZE(ar9271Modes_9271), 6);
00037                 INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
00038                                ARRAY_SIZE(ar9271Common_9271), 2);
00039                 INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
00040                                ar9271Common_normal_cck_fir_coeff_9271,
00041                                ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2);
00042                 INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
00043                                ar9271Common_japan_2484_cck_fir_coeff_9271,
00044                                ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
00045                 INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
00046                                ar9271Modes_9271_1_0_only,
00047                                ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
00048                 INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
00049                                ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
00050                 INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
00051                                ar9271Modes_high_power_tx_gain_9271,
00052                                ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
00053                 INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
00054                                ar9271Modes_normal_power_tx_gain_9271,
00055                                ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
00056                 return;
00057         }
00058 
00059         if (AR_SREV_9287_11_OR_LATER(ah)) {
00060                 INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
00061                                 ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
00062                 INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
00063                                 ARRAY_SIZE(ar9287Common_9287_1_1), 2);
00064                 if (ah->config.pcie_clock_req)
00065                         INIT_INI_ARRAY(&ah->iniPcieSerdes,
00066                         ar9287PciePhy_clkreq_off_L1_9287_1_1,
00067                         ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2);
00068                 else
00069                         INIT_INI_ARRAY(&ah->iniPcieSerdes,
00070                         ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
00071                         ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
00072                                         2);
00073         } else if (AR_SREV_9285_12_OR_LATER(ah)) {
00074 
00075 
00076                 INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
00077                                ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
00078                 INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
00079                                ARRAY_SIZE(ar9285Common_9285_1_2), 2);
00080 
00081                 if (ah->config.pcie_clock_req) {
00082                         INIT_INI_ARRAY(&ah->iniPcieSerdes,
00083                         ar9285PciePhy_clkreq_off_L1_9285_1_2,
00084                         ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
00085                 } else {
00086                         INIT_INI_ARRAY(&ah->iniPcieSerdes,
00087                         ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
00088                         ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
00089                                   2);
00090                 }
00091         } else if (AR_SREV_9280_20_OR_LATER(ah)) {
00092                 INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
00093                                ARRAY_SIZE(ar9280Modes_9280_2), 6);
00094                 INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
00095                                ARRAY_SIZE(ar9280Common_9280_2), 2);
00096 
00097                 if (ah->config.pcie_clock_req) {
00098                         INIT_INI_ARRAY(&ah->iniPcieSerdes,
00099                                ar9280PciePhy_clkreq_off_L1_9280,
00100                                ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2);
00101                 } else {
00102                         INIT_INI_ARRAY(&ah->iniPcieSerdes,
00103                                ar9280PciePhy_clkreq_always_on_L1_9280,
00104                                ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
00105                 }
00106                 INIT_INI_ARRAY(&ah->iniModesAdditional,
00107                                ar9280Modes_fast_clock_9280_2,
00108                                ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
00109         } else if (AR_SREV_9160_10_OR_LATER(ah)) {
00110                 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
00111                                ARRAY_SIZE(ar5416Modes_9160), 6);
00112                 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
00113                                ARRAY_SIZE(ar5416Common_9160), 2);
00114                 INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
00115                                ARRAY_SIZE(ar5416Bank0_9160), 2);
00116                 INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
00117                                ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
00118                 INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
00119                                ARRAY_SIZE(ar5416Bank1_9160), 2);
00120                 INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
00121                                ARRAY_SIZE(ar5416Bank2_9160), 2);
00122                 INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
00123                                ARRAY_SIZE(ar5416Bank3_9160), 3);
00124                 INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
00125                                ARRAY_SIZE(ar5416Bank6_9160), 3);
00126                 INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
00127                                ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
00128                 INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
00129                                ARRAY_SIZE(ar5416Bank7_9160), 2);
00130                 if (AR_SREV_9160_11(ah)) {
00131                         INIT_INI_ARRAY(&ah->iniAddac,
00132                                        ar5416Addac_9160_1_1,
00133                                        ARRAY_SIZE(ar5416Addac_9160_1_1), 2);
00134                 } else {
00135                         INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
00136                                        ARRAY_SIZE(ar5416Addac_9160), 2);
00137                 }
00138         } else if (AR_SREV_9100_OR_LATER(ah)) {
00139                 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
00140                                ARRAY_SIZE(ar5416Modes_9100), 6);
00141                 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
00142                                ARRAY_SIZE(ar5416Common_9100), 2);
00143                 INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
00144                                ARRAY_SIZE(ar5416Bank0_9100), 2);
00145                 INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
00146                                ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
00147                 INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
00148                                ARRAY_SIZE(ar5416Bank1_9100), 2);
00149                 INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
00150                                ARRAY_SIZE(ar5416Bank2_9100), 2);
00151                 INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
00152                                ARRAY_SIZE(ar5416Bank3_9100), 3);
00153                 INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
00154                                ARRAY_SIZE(ar5416Bank6_9100), 3);
00155                 INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
00156                                ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
00157                 INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
00158                                ARRAY_SIZE(ar5416Bank7_9100), 2);
00159                 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
00160                                ARRAY_SIZE(ar5416Addac_9100), 2);
00161         } else {
00162                 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
00163                                ARRAY_SIZE(ar5416Modes), 6);
00164                 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
00165                                ARRAY_SIZE(ar5416Common), 2);
00166                 INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
00167                                ARRAY_SIZE(ar5416Bank0), 2);
00168                 INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
00169                                ARRAY_SIZE(ar5416BB_RfGain), 3);
00170                 INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
00171                                ARRAY_SIZE(ar5416Bank1), 2);
00172                 INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
00173                                ARRAY_SIZE(ar5416Bank2), 2);
00174                 INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
00175                                ARRAY_SIZE(ar5416Bank3), 3);
00176                 INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
00177                                ARRAY_SIZE(ar5416Bank6), 3);
00178                 INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
00179                                ARRAY_SIZE(ar5416Bank6TPC), 3);
00180                 INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
00181                                ARRAY_SIZE(ar5416Bank7), 2);
00182                 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
00183                                ARRAY_SIZE(ar5416Addac), 2);
00184         }
00185 }
00186 
00187 /* Support for Japan ch.14 (2484) spread */
00188 void ar9002_hw_cck_chan14_spread(struct ath_hw *ah)
00189 {
00190         if (AR_SREV_9287_11_OR_LATER(ah)) {
00191                 INIT_INI_ARRAY(&ah->iniCckfirNormal,
00192                        ar9287Common_normal_cck_fir_coeff_9287_1_1,
00193                        ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1),
00194                        2);
00195                 INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
00196                        ar9287Common_japan_2484_cck_fir_coeff_9287_1_1,
00197                        ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1),
00198                        2);
00199         }
00200 }
00201 
00202 static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
00203 {
00204         u32 rxgain_type;
00205 
00206         if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
00207             AR5416_EEP_MINOR_VER_17) {
00208                 rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
00209 
00210                 if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
00211                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00212                         ar9280Modes_backoff_13db_rxgain_9280_2,
00213                         ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
00214                 else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
00215                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00216                         ar9280Modes_backoff_23db_rxgain_9280_2,
00217                         ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
00218                 else
00219                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00220                         ar9280Modes_original_rxgain_9280_2,
00221                         ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
00222         } else {
00223                 INIT_INI_ARRAY(&ah->iniModesRxGain,
00224                         ar9280Modes_original_rxgain_9280_2,
00225                         ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
00226         }
00227 }
00228 
00229 static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
00230 {
00231         u32 txgain_type;
00232 
00233         if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
00234             AR5416_EEP_MINOR_VER_19) {
00235                 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
00236 
00237                 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
00238                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00239                         ar9280Modes_high_power_tx_gain_9280_2,
00240                         ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
00241                 else
00242                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00243                         ar9280Modes_original_tx_gain_9280_2,
00244                         ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
00245         } else {
00246                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00247                 ar9280Modes_original_tx_gain_9280_2,
00248                 ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
00249         }
00250 }
00251 
00252 static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
00253 {
00254         if (AR_SREV_9287_11_OR_LATER(ah))
00255                 INIT_INI_ARRAY(&ah->iniModesRxGain,
00256                 ar9287Modes_rx_gain_9287_1_1,
00257                 ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
00258         else if (AR_SREV_9280_20(ah))
00259                 ar9280_20_hw_init_rxgain_ini(ah);
00260 
00261         if (AR_SREV_9287_11_OR_LATER(ah)) {
00262                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00263                 ar9287Modes_tx_gain_9287_1_1,
00264                 ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
00265         } else if (AR_SREV_9280_20(ah)) {
00266                 ar9280_20_hw_init_txgain_ini(ah);
00267         } else if (AR_SREV_9285_12_OR_LATER(ah)) {
00268                 u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
00269 
00270                 /* txgain table */
00271                 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
00272                         if (AR_SREV_9285E_20(ah)) {
00273                                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00274                                 ar9285Modes_XE2_0_high_power,
00275                                 ARRAY_SIZE(
00276                                   ar9285Modes_XE2_0_high_power), 6);
00277                         } else {
00278                                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00279                                 ar9285Modes_high_power_tx_gain_9285_1_2,
00280                                 ARRAY_SIZE(
00281                                   ar9285Modes_high_power_tx_gain_9285_1_2), 6);
00282                         }
00283                 } else {
00284                         if (AR_SREV_9285E_20(ah)) {
00285                                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00286                                 ar9285Modes_XE2_0_normal_power,
00287                                 ARRAY_SIZE(
00288                                   ar9285Modes_XE2_0_normal_power), 6);
00289                         } else {
00290                                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00291                                 ar9285Modes_original_tx_gain_9285_1_2,
00292                                 ARRAY_SIZE(
00293                                   ar9285Modes_original_tx_gain_9285_1_2), 6);
00294                         }
00295                 }
00296         }
00297 }
00298 
00299 /*
00300  * Helper for ASPM support.
00301  *
00302  * Disable PLL when in L0s as well as receiver clock when in L1.
00303  * This power saving option must be enabled through the SerDes.
00304  *
00305  * Programming the SerDes must go through the same 288 bit serial shift
00306  * register as the other analog registers.  Hence the 9 writes.
00307  */
00308 static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
00309                                          int restore,
00310                                          int power_off)
00311 {
00312         u8 i;
00313         u32 val;
00314 
00315         if (ah->is_pciexpress != 1)
00316                 return;
00317 
00318         /* Do not touch SerDes registers */
00319         if (ah->config.pcie_powersave_enable == 2)
00320                 return;
00321 
00322         /* Nothing to do on restore for 11N */
00323         if (!restore) {
00324                 if (AR_SREV_9280_20_OR_LATER(ah)) {
00325                         /*
00326                          * AR9280 2.0 or later chips use SerDes values from the
00327                          * initvals.h initialized depending on chipset during
00328                          * __ath9k_hw_init()
00329                          */
00330                         for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
00331                                 REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
00332                                           INI_RA(&ah->iniPcieSerdes, i, 1));
00333                         }
00334                 } else {
00335                         ENABLE_REGWRITE_BUFFER(ah);
00336 
00337                         REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
00338                         REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
00339 
00340                         /* RX shut off when elecidle is asserted */
00341                         REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
00342                         REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
00343                         REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
00344 
00345                         /*
00346                          * Ignore ah->ah_config.pcie_clock_req setting for
00347                          * pre-AR9280 11n
00348                          */
00349                         REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
00350 
00351                         REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
00352                         REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
00353                         REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
00354 
00355                         /* Load the new settings */
00356                         REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
00357 
00358                         REGWRITE_BUFFER_FLUSH(ah);
00359                 }
00360 
00361                 udelay(1000);
00362         }
00363 
00364         if (power_off) {
00365                 /* clear bit 19 to disable L1 */
00366                 REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
00367 
00368                 val = REG_READ(ah, AR_WA);
00369 
00370                 /*
00371                  * Set PCIe workaround bits
00372                  * In AR9280 and AR9285, bit 14 in WA register (disable L1)
00373                  * should only  be set when device enters D3 and be
00374                  * cleared when device comes back to D0.
00375                  */
00376                 if (ah->config.pcie_waen) {
00377                         if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
00378                                 val |= AR_WA_D3_L1_DISABLE;
00379                 } else {
00380                         if (((AR_SREV_9285(ah) ||
00381                               AR_SREV_9271(ah) ||
00382                               AR_SREV_9287(ah)) &&
00383                              (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
00384                             (AR_SREV_9280(ah) &&
00385                              (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
00386                                 val |= AR_WA_D3_L1_DISABLE;
00387                         }
00388                 }
00389 
00390                 if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
00391                         /*
00392                          * Disable bit 6 and 7 before entering D3 to
00393                          * prevent system hang.
00394                          */
00395                         val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
00396                 }
00397 
00398                 if (AR_SREV_9280(ah))
00399                         val |= AR_WA_BIT22;
00400 
00401                 if (AR_SREV_9285E_20(ah))
00402                         val |= AR_WA_BIT23;
00403 
00404                 REG_WRITE(ah, AR_WA, val);
00405         } else {
00406                 if (ah->config.pcie_waen) {
00407                         val = ah->config.pcie_waen;
00408                         if (!power_off)
00409                                 val &= (~AR_WA_D3_L1_DISABLE);
00410                 } else {
00411                         if (AR_SREV_9285(ah) ||
00412                             AR_SREV_9271(ah) ||
00413                             AR_SREV_9287(ah)) {
00414                                 val = AR9285_WA_DEFAULT;
00415                                 if (!power_off)
00416                                         val &= (~AR_WA_D3_L1_DISABLE);
00417                         }
00418                         else if (AR_SREV_9280(ah)) {
00419                                 /*
00420                                  * For AR9280 chips, bit 22 of 0x4004
00421                                  * needs to be set.
00422                                  */
00423                                 val = AR9280_WA_DEFAULT;
00424                                 if (!power_off)
00425                                         val &= (~AR_WA_D3_L1_DISABLE);
00426                         } else {
00427                                 val = AR_WA_DEFAULT;
00428                         }
00429                 }
00430 
00431                 /* WAR for ASPM system hang */
00432                 if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
00433                         val |= (AR_WA_BIT6 | AR_WA_BIT7);
00434 
00435                 if (AR_SREV_9285E_20(ah))
00436                         val |= AR_WA_BIT23;
00437 
00438                 REG_WRITE(ah, AR_WA, val);
00439 
00440                 /* set bit 19 to allow forcing of pcie core into L1 state */
00441                 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
00442         }
00443 }
00444 
00445 static int ar9002_hw_get_radiorev(struct ath_hw *ah)
00446 {
00447         u32 val;
00448         int i;
00449 
00450         ENABLE_REGWRITE_BUFFER(ah);
00451 
00452         REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
00453         for (i = 0; i < 8; i++)
00454                 REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
00455 
00456         REGWRITE_BUFFER_FLUSH(ah);
00457 
00458         val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
00459         val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
00460 
00461         return ath9k_hw_reverse_bits(val, 8);
00462 }
00463 
00464 int ar9002_hw_rf_claim(struct ath_hw *ah)
00465 {
00466         u32 val;
00467 
00468         REG_WRITE(ah, AR_PHY(0), 0x00000007);
00469 
00470         val = ar9002_hw_get_radiorev(ah);
00471         switch (val & AR_RADIO_SREV_MAJOR) {
00472         case 0:
00473                 val = AR_RAD5133_SREV_MAJOR;
00474                 break;
00475         case AR_RAD5133_SREV_MAJOR:
00476         case AR_RAD5122_SREV_MAJOR:
00477         case AR_RAD2133_SREV_MAJOR:
00478         case AR_RAD2122_SREV_MAJOR:
00479                 break;
00480         default:
00481                 DBG("ath9k: "
00482                         "Radio Chip Rev 0x%02X not supported\n",
00483                         val & AR_RADIO_SREV_MAJOR);
00484                 return -EOPNOTSUPP;
00485         }
00486 
00487         ah->hw_version.analog5GhzRev = val;
00488 
00489         return 0;
00490 }
00491 
00492 void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
00493 {
00494         if (AR_SREV_9287_13_OR_LATER(ah)) {
00495                 REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
00496                                 AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
00497                 REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
00498                 REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
00499                                 AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
00500                 REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
00501                                 AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
00502         }
00503 }
00504 
00505 /*
00506  * If Async FIFO is enabled, the following counters change as MAC now runs
00507  * at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
00508  *
00509  * The values below tested for ht40 2 chain.
00510  * Overwrite the delay/timeouts initialized in process ini.
00511  */
00512 void ar9002_hw_update_async_fifo(struct ath_hw *ah)
00513 {
00514         if (AR_SREV_9287_13_OR_LATER(ah)) {
00515                 REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
00516                           AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
00517                 REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
00518                           AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
00519                 REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
00520                           AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
00521 
00522                 REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
00523                 REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
00524 
00525                 REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
00526                             AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
00527                 REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
00528                               AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
00529         }
00530 }
00531 
00532 /*
00533  * We don't enable WEP aggregation on mac80211 but we keep this
00534  * around for HAL unification purposes.
00535  */
00536 void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
00537 {
00538         if (AR_SREV_9287_13_OR_LATER(ah)) {
00539                 REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
00540                             AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
00541         }
00542 }
00543 
00544 /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
00545 void ar9002_hw_attach_ops(struct ath_hw *ah)
00546 {
00547         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
00548         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
00549 
00550         priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
00551         priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
00552 
00553         ops->config_pci_powersave = ar9002_hw_configpcipowersave;
00554 
00555         ar5008_hw_attach_phy_ops(ah);
00556         if (AR_SREV_9280_20_OR_LATER(ah))
00557                 ar9002_hw_attach_phy_ops(ah);
00558 
00559         ar9002_hw_attach_calib_ops(ah);
00560         ar9002_hw_attach_mac_ops(ah);
00561 }
00562 
00563 void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
00564 {
00565         u32 modesIndex;
00566         unsigned int i;
00567 
00568         switch (chan->chanmode) {
00569         case CHANNEL_A:
00570         case CHANNEL_A_HT20:
00571                 modesIndex = 1;
00572                 break;
00573         case CHANNEL_A_HT40PLUS:
00574         case CHANNEL_A_HT40MINUS:
00575                 modesIndex = 2;
00576                 break;
00577         case CHANNEL_G:
00578         case CHANNEL_G_HT20:
00579         case CHANNEL_B:
00580                 modesIndex = 4;
00581                 break;
00582         case CHANNEL_G_HT40PLUS:
00583         case CHANNEL_G_HT40MINUS:
00584                 modesIndex = 3;
00585                 break;
00586 
00587         default:
00588                 return;
00589         }
00590 
00591         ENABLE_REGWRITE_BUFFER(ah);
00592 
00593         for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
00594                 u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
00595                 u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
00596                 u32 val_orig;
00597 
00598                 if (reg == AR_PHY_CCK_DETECT) {
00599                         val_orig = REG_READ(ah, reg);
00600                         val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
00601                         val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
00602 
00603                         REG_WRITE(ah, reg, val|val_orig);
00604                 } else
00605                         REG_WRITE(ah, reg, val);
00606         }
00607 
00608         REGWRITE_BUFFER_FLUSH(ah);
00609 }