root/drivers/net/wireless/ath/ath9k/ar9002_hw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ar9002_hw_init_mode_regs
  2. ar9280_20_hw_init_rxgain_ini
  3. ar9280_20_hw_init_txgain_ini
  4. ar9271_hw_init_txgain_ini
  5. ar9002_hw_init_mode_gain_regs
  6. ar9002_hw_configpcipowersave
  7. ar9002_hw_get_radiorev
  8. ar9002_hw_rf_claim
  9. ar9002_hw_enable_async_fifo
  10. ar9002_hw_init_hang_checks
  11. ar9002_hw_attach_ops
  12. ar9002_hw_load_ani_reg

   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 <linux/moduleparam.h>
  18 #include "hw.h"
  19 #include "ar5008_initvals.h"
  20 #include "ar9001_initvals.h"
  21 #include "ar9002_initvals.h"
  22 #include "ar9002_phy.h"
  23 
  24 /* General hardware code for the A5008/AR9001/AR9002 hadware families */
  25 
  26 static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
  27 {
  28         if (AR_SREV_9271(ah)) {
  29                 INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271);
  30                 INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271);
  31                 INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg);
  32                 return 0;
  33         }
  34 
  35         INIT_INI_ARRAY(&ah->iniPcieSerdes,
  36                        ar9280PciePhy_clkreq_always_on_L1_9280);
  37 
  38         if (AR_SREV_9287_11_OR_LATER(ah)) {
  39                 INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
  40                 INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1);
  41         } else if (AR_SREV_9285_12_OR_LATER(ah)) {
  42                 INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2);
  43                 INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2);
  44         } else if (AR_SREV_9280_20_OR_LATER(ah)) {
  45                 INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2);
  46                 INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2);
  47 
  48                 INIT_INI_ARRAY(&ah->iniModesFastClock,
  49                                ar9280Modes_fast_clock_9280_2);
  50         } else if (AR_SREV_9160_10_OR_LATER(ah)) {
  51                 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160);
  52                 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160);
  53                 if (AR_SREV_9160_11(ah)) {
  54                         INIT_INI_ARRAY(&ah->iniAddac,
  55                                        ar5416Addac_9160_1_1);
  56                 } else {
  57                         INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160);
  58                 }
  59         } else if (AR_SREV_9100_OR_LATER(ah)) {
  60                 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
  61                 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
  62                 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
  63         } else {
  64                 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
  65                 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
  66                 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
  67         }
  68 
  69         if (!AR_SREV_9280_20_OR_LATER(ah)) {
  70                 /* Common for AR5416, AR913x, AR9160 */
  71                 INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
  72 
  73                 /* Common for AR913x, AR9160 */
  74                 if (!AR_SREV_5416(ah))
  75                         INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
  76                 else
  77                         INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
  78         }
  79 
  80         /* iniAddac needs to be modified for these chips */
  81         if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
  82                 struct ar5416IniArray *addac = &ah->iniAddac;
  83                 u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
  84                 u32 *data;
  85 
  86                 data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
  87                 if (!data)
  88                         return -ENOMEM;
  89 
  90                 memcpy(data, addac->ia_array, size);
  91                 addac->ia_array = data;
  92 
  93                 if (!AR_SREV_5416_22_OR_LATER(ah)) {
  94                         /* override CLKDRV value */
  95                         INI_RA(addac, 31,1) = 0;
  96                 }
  97         }
  98         if (AR_SREV_9287_11_OR_LATER(ah)) {
  99                 INIT_INI_ARRAY(&ah->iniCckfirNormal,
 100                        ar9287Common_normal_cck_fir_coeff_9287_1_1);
 101                 INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
 102                        ar9287Common_japan_2484_cck_fir_coeff_9287_1_1);
 103         }
 104         return 0;
 105 }
 106 
 107 static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
 108 {
 109         u32 rxgain_type;
 110 
 111         if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_17) {
 112                 rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
 113 
 114                 if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
 115                         INIT_INI_ARRAY(&ah->iniModesRxGain,
 116                                        ar9280Modes_backoff_13db_rxgain_9280_2);
 117                 else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
 118                         INIT_INI_ARRAY(&ah->iniModesRxGain,
 119                                        ar9280Modes_backoff_23db_rxgain_9280_2);
 120                 else
 121                         INIT_INI_ARRAY(&ah->iniModesRxGain,
 122                                        ar9280Modes_original_rxgain_9280_2);
 123         } else {
 124                 INIT_INI_ARRAY(&ah->iniModesRxGain,
 125                                ar9280Modes_original_rxgain_9280_2);
 126         }
 127 }
 128 
 129 static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
 130 {
 131         if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) {
 132                 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
 133                         INIT_INI_ARRAY(&ah->iniModesTxGain,
 134                                        ar9280Modes_high_power_tx_gain_9280_2);
 135                 else
 136                         INIT_INI_ARRAY(&ah->iniModesTxGain,
 137                                        ar9280Modes_original_tx_gain_9280_2);
 138         } else {
 139                 INIT_INI_ARRAY(&ah->iniModesTxGain,
 140                                ar9280Modes_original_tx_gain_9280_2);
 141         }
 142 }
 143 
 144 static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
 145 {
 146         if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
 147                 INIT_INI_ARRAY(&ah->iniModesTxGain,
 148                                ar9271Modes_high_power_tx_gain_9271);
 149         else
 150                 INIT_INI_ARRAY(&ah->iniModesTxGain,
 151                                ar9271Modes_normal_power_tx_gain_9271);
 152 }
 153 
 154 static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
 155 {
 156         u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
 157 
 158         if (AR_SREV_9287_11_OR_LATER(ah))
 159                 INIT_INI_ARRAY(&ah->iniModesRxGain,
 160                                ar9287Modes_rx_gain_9287_1_1);
 161         else if (AR_SREV_9280_20(ah))
 162                 ar9280_20_hw_init_rxgain_ini(ah);
 163 
 164         if (AR_SREV_9271(ah)) {
 165                 ar9271_hw_init_txgain_ini(ah, txgain_type);
 166         } else if (AR_SREV_9287_11_OR_LATER(ah)) {
 167                 INIT_INI_ARRAY(&ah->iniModesTxGain,
 168                                ar9287Modes_tx_gain_9287_1_1);
 169         } else if (AR_SREV_9280_20(ah)) {
 170                 ar9280_20_hw_init_txgain_ini(ah, txgain_type);
 171         } else if (AR_SREV_9285_12_OR_LATER(ah)) {
 172                 /* txgain table */
 173                 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
 174                         if (AR_SREV_9285E_20(ah)) {
 175                                 INIT_INI_ARRAY(&ah->iniModesTxGain,
 176                                                ar9285Modes_XE2_0_high_power);
 177                         } else {
 178                                 INIT_INI_ARRAY(&ah->iniModesTxGain,
 179                                         ar9285Modes_high_power_tx_gain_9285_1_2);
 180                         }
 181                 } else {
 182                         if (AR_SREV_9285E_20(ah)) {
 183                                 INIT_INI_ARRAY(&ah->iniModesTxGain,
 184                                                ar9285Modes_XE2_0_normal_power);
 185                         } else {
 186                                 INIT_INI_ARRAY(&ah->iniModesTxGain,
 187                                         ar9285Modes_original_tx_gain_9285_1_2);
 188                         }
 189                 }
 190         }
 191 }
 192 
 193 /*
 194  * Helper for ASPM support.
 195  *
 196  * Disable PLL when in L0s as well as receiver clock when in L1.
 197  * This power saving option must be enabled through the SerDes.
 198  *
 199  * Programming the SerDes must go through the same 288 bit serial shift
 200  * register as the other analog registers.  Hence the 9 writes.
 201  */
 202 static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
 203                                          bool power_off)
 204 {
 205         u8 i;
 206         u32 val;
 207 
 208         /* Nothing to do on restore for 11N */
 209         if (!power_off /* !restore */) {
 210                 if (AR_SREV_9280_20_OR_LATER(ah)) {
 211                         /*
 212                          * AR9280 2.0 or later chips use SerDes values from the
 213                          * initvals.h initialized depending on chipset during
 214                          * __ath9k_hw_init()
 215                          */
 216                         for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
 217                                 REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
 218                                           INI_RA(&ah->iniPcieSerdes, i, 1));
 219                         }
 220                 } else {
 221                         ENABLE_REGWRITE_BUFFER(ah);
 222 
 223                         REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
 224                         REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
 225 
 226                         /* RX shut off when elecidle is asserted */
 227                         REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
 228                         REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
 229                         REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
 230 
 231                         /*
 232                          * Ignore ah->ah_config.pcie_clock_req setting for
 233                          * pre-AR9280 11n
 234                          */
 235                         REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
 236 
 237                         REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
 238                         REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
 239                         REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
 240 
 241                         /* Load the new settings */
 242                         REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 243 
 244                         REGWRITE_BUFFER_FLUSH(ah);
 245                 }
 246 
 247                 udelay(1000);
 248         }
 249 
 250         if (power_off) {
 251                 /* clear bit 19 to disable L1 */
 252                 REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
 253 
 254                 val = REG_READ(ah, AR_WA);
 255 
 256                 /*
 257                  * Set PCIe workaround bits
 258                  * In AR9280 and AR9285, bit 14 in WA register (disable L1)
 259                  * should only  be set when device enters D3 and be
 260                  * cleared when device comes back to D0.
 261                  */
 262                 if (ah->config.pcie_waen) {
 263                         if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
 264                                 val |= AR_WA_D3_L1_DISABLE;
 265                 } else {
 266                         if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
 267                                 if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
 268                                         val |= AR_WA_D3_L1_DISABLE;
 269                         } else if (AR_SREV_9280(ah)) {
 270                                 if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
 271                                         val |= AR_WA_D3_L1_DISABLE;
 272                         }
 273                 }
 274 
 275                 if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
 276                         /*
 277                          * Disable bit 6 and 7 before entering D3 to
 278                          * prevent system hang.
 279                          */
 280                         val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
 281                 }
 282 
 283                 if (AR_SREV_9280(ah))
 284                         val |= AR_WA_BIT22;
 285 
 286                 if (AR_SREV_9285E_20(ah))
 287                         val |= AR_WA_BIT23;
 288 
 289                 REG_WRITE(ah, AR_WA, val);
 290         } else {
 291                 if (ah->config.pcie_waen) {
 292                         val = ah->config.pcie_waen;
 293                         val &= (~AR_WA_D3_L1_DISABLE);
 294                 } else {
 295                         if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
 296                                 val = AR9285_WA_DEFAULT;
 297                                 val &= (~AR_WA_D3_L1_DISABLE);
 298                         } else if (AR_SREV_9280(ah)) {
 299                                 /*
 300                                  * For AR9280 chips, bit 22 of 0x4004
 301                                  * needs to be set.
 302                                  */
 303                                 val = AR9280_WA_DEFAULT;
 304                                 val &= (~AR_WA_D3_L1_DISABLE);
 305                         } else {
 306                                 val = AR_WA_DEFAULT;
 307                         }
 308                 }
 309 
 310                 /* WAR for ASPM system hang */
 311                 if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
 312                         val |= (AR_WA_BIT6 | AR_WA_BIT7);
 313 
 314                 if (AR_SREV_9285E_20(ah))
 315                         val |= AR_WA_BIT23;
 316 
 317                 REG_WRITE(ah, AR_WA, val);
 318 
 319                 /* set bit 19 to allow forcing of pcie core into L1 state */
 320                 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
 321         }
 322 }
 323 
 324 static int ar9002_hw_get_radiorev(struct ath_hw *ah)
 325 {
 326         u32 val;
 327         int i;
 328 
 329         ENABLE_REGWRITE_BUFFER(ah);
 330 
 331         REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
 332         for (i = 0; i < 8; i++)
 333                 REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
 334 
 335         REGWRITE_BUFFER_FLUSH(ah);
 336 
 337         val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
 338         val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
 339 
 340         return ath9k_hw_reverse_bits(val, 8);
 341 }
 342 
 343 int ar9002_hw_rf_claim(struct ath_hw *ah)
 344 {
 345         u32 val;
 346 
 347         REG_WRITE(ah, AR_PHY(0), 0x00000007);
 348 
 349         val = ar9002_hw_get_radiorev(ah);
 350         switch (val & AR_RADIO_SREV_MAJOR) {
 351         case 0:
 352                 val = AR_RAD5133_SREV_MAJOR;
 353                 break;
 354         case AR_RAD5133_SREV_MAJOR:
 355         case AR_RAD5122_SREV_MAJOR:
 356         case AR_RAD2133_SREV_MAJOR:
 357         case AR_RAD2122_SREV_MAJOR:
 358                 break;
 359         default:
 360                 ath_err(ath9k_hw_common(ah),
 361                         "Radio Chip Rev 0x%02X not supported\n",
 362                         val & AR_RADIO_SREV_MAJOR);
 363                 return -EOPNOTSUPP;
 364         }
 365 
 366         ah->hw_version.analog5GhzRev = val;
 367 
 368         return 0;
 369 }
 370 
 371 void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
 372 {
 373         if (AR_SREV_9287_13_OR_LATER(ah)) {
 374                 REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
 375                                 AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
 376                 REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
 377                 REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
 378                                 AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
 379                 REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
 380                                 AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
 381         }
 382 }
 383 
 384 static void ar9002_hw_init_hang_checks(struct ath_hw *ah)
 385 {
 386         if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
 387                 ah->config.hw_hang_checks |= HW_BB_RIFS_HANG;
 388                 ah->config.hw_hang_checks |= HW_BB_DFS_HANG;
 389         }
 390 
 391         if (AR_SREV_9280(ah))
 392                 ah->config.hw_hang_checks |= HW_BB_RX_CLEAR_STUCK_HANG;
 393 
 394         if (AR_SREV_5416(ah) || AR_SREV_9100(ah) || AR_SREV_9160(ah))
 395                 ah->config.hw_hang_checks |= HW_MAC_HANG;
 396 }
 397 
 398 /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
 399 int ar9002_hw_attach_ops(struct ath_hw *ah)
 400 {
 401         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
 402         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
 403         int ret;
 404 
 405         ret = ar9002_hw_init_mode_regs(ah);
 406         if (ret)
 407                 return ret;
 408 
 409         priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
 410         priv_ops->init_hang_checks = ar9002_hw_init_hang_checks;
 411 
 412         ops->config_pci_powersave = ar9002_hw_configpcipowersave;
 413 
 414         ret = ar5008_hw_attach_phy_ops(ah);
 415         if (ret)
 416                 return ret;
 417 
 418         if (AR_SREV_9280_20_OR_LATER(ah))
 419                 ar9002_hw_attach_phy_ops(ah);
 420 
 421         ar9002_hw_attach_calib_ops(ah);
 422         ar9002_hw_attach_mac_ops(ah);
 423         return 0;
 424 }
 425 
 426 void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
 427 {
 428         u32 modesIndex;
 429         int i;
 430 
 431         if (IS_CHAN_5GHZ(chan))
 432                 modesIndex = IS_CHAN_HT40(chan) ? 2 : 1;
 433         else
 434                 modesIndex = IS_CHAN_HT40(chan) ? 3 : 4;
 435 
 436         ENABLE_REGWRITE_BUFFER(ah);
 437 
 438         for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
 439                 u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
 440                 u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
 441                 u32 val_orig;
 442 
 443                 if (reg == AR_PHY_CCK_DETECT) {
 444                         val_orig = REG_READ(ah, reg);
 445                         val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
 446                         val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
 447 
 448                         REG_WRITE(ah, reg, val|val_orig);
 449                 } else
 450                         REG_WRITE(ah, reg, val);
 451         }
 452 
 453         REGWRITE_BUFFER_FLUSH(ah);
 454 }

/* [<][>][^][v][top][bottom][index][help] */