162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2008-2011 Atheros Communications Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/moduleparam.h> 1862306a36Sopenharmony_ci#include "hw.h" 1962306a36Sopenharmony_ci#include "ar5008_initvals.h" 2062306a36Sopenharmony_ci#include "ar9001_initvals.h" 2162306a36Sopenharmony_ci#include "ar9002_initvals.h" 2262306a36Sopenharmony_ci#include "ar9002_phy.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* General hardware code for the A5008/AR9001/AR9002 hadware families */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic int ar9002_hw_init_mode_regs(struct ath_hw *ah) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci if (AR_SREV_9271(ah)) { 2962306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271); 3062306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271); 3162306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg); 3262306a36Sopenharmony_ci return 0; 3362306a36Sopenharmony_ci } 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniPcieSerdes, 3662306a36Sopenharmony_ci ar9280PciePhy_clkreq_always_on_L1_9280); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci if (AR_SREV_9287_11_OR_LATER(ah)) { 3962306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1); 4062306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1); 4162306a36Sopenharmony_ci } else if (AR_SREV_9285_12_OR_LATER(ah)) { 4262306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2); 4362306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2); 4462306a36Sopenharmony_ci } else if (AR_SREV_9280_20_OR_LATER(ah)) { 4562306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2); 4662306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2); 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesFastClock, 4962306a36Sopenharmony_ci ar9280Modes_fast_clock_9280_2); 5062306a36Sopenharmony_ci } else if (AR_SREV_9160_10_OR_LATER(ah)) { 5162306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160); 5262306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160); 5362306a36Sopenharmony_ci if (AR_SREV_9160_11(ah)) { 5462306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniAddac, 5562306a36Sopenharmony_ci ar5416Addac_9160_1_1); 5662306a36Sopenharmony_ci } else { 5762306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160); 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci } else if (AR_SREV_9100_OR_LATER(ah)) { 6062306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100); 6162306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100); 6262306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100); 6362306a36Sopenharmony_ci } else { 6462306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModes, ar5416Modes); 6562306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCommon, ar5416Common); 6662306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac); 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (!AR_SREV_9280_20_OR_LATER(ah)) { 7062306a36Sopenharmony_ci /* Common for AR5416, AR913x, AR9160 */ 7162306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* Common for AR913x, AR9160 */ 7462306a36Sopenharmony_ci if (!AR_SREV_5416(ah)) 7562306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100); 7662306a36Sopenharmony_ci else 7762306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC); 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* iniAddac needs to be modified for these chips */ 8162306a36Sopenharmony_ci if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) { 8262306a36Sopenharmony_ci struct ar5416IniArray *addac = &ah->iniAddac; 8362306a36Sopenharmony_ci u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns; 8462306a36Sopenharmony_ci u32 *data; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci data = devm_kzalloc(ah->dev, size, GFP_KERNEL); 8762306a36Sopenharmony_ci if (!data) 8862306a36Sopenharmony_ci return -ENOMEM; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci memcpy(data, addac->ia_array, size); 9162306a36Sopenharmony_ci addac->ia_array = data; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (!AR_SREV_5416_22_OR_LATER(ah)) { 9462306a36Sopenharmony_ci /* override CLKDRV value */ 9562306a36Sopenharmony_ci INI_RA(addac, 31,1) = 0; 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci if (AR_SREV_9287_11_OR_LATER(ah)) { 9962306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCckfirNormal, 10062306a36Sopenharmony_ci ar9287Common_normal_cck_fir_coeff_9287_1_1); 10162306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniCckfirJapan2484, 10262306a36Sopenharmony_ci ar9287Common_japan_2484_cck_fir_coeff_9287_1_1); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci return 0; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci u32 rxgain_type; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_17) { 11262306a36Sopenharmony_ci rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) 11562306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesRxGain, 11662306a36Sopenharmony_ci ar9280Modes_backoff_13db_rxgain_9280_2); 11762306a36Sopenharmony_ci else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) 11862306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesRxGain, 11962306a36Sopenharmony_ci ar9280Modes_backoff_23db_rxgain_9280_2); 12062306a36Sopenharmony_ci else 12162306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesRxGain, 12262306a36Sopenharmony_ci ar9280Modes_original_rxgain_9280_2); 12362306a36Sopenharmony_ci } else { 12462306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesRxGain, 12562306a36Sopenharmony_ci ar9280Modes_original_rxgain_9280_2); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) { 13262306a36Sopenharmony_ci if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) 13362306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 13462306a36Sopenharmony_ci ar9280Modes_high_power_tx_gain_9280_2); 13562306a36Sopenharmony_ci else 13662306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 13762306a36Sopenharmony_ci ar9280Modes_original_tx_gain_9280_2); 13862306a36Sopenharmony_ci } else { 13962306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 14062306a36Sopenharmony_ci ar9280Modes_original_tx_gain_9280_2); 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) 14762306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 14862306a36Sopenharmony_ci ar9271Modes_high_power_tx_gain_9271); 14962306a36Sopenharmony_ci else 15062306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 15162306a36Sopenharmony_ci ar9271Modes_normal_power_tx_gain_9271); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (AR_SREV_9287_11_OR_LATER(ah)) 15962306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesRxGain, 16062306a36Sopenharmony_ci ar9287Modes_rx_gain_9287_1_1); 16162306a36Sopenharmony_ci else if (AR_SREV_9280_20(ah)) 16262306a36Sopenharmony_ci ar9280_20_hw_init_rxgain_ini(ah); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (AR_SREV_9271(ah)) { 16562306a36Sopenharmony_ci ar9271_hw_init_txgain_ini(ah, txgain_type); 16662306a36Sopenharmony_ci } else if (AR_SREV_9287_11_OR_LATER(ah)) { 16762306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 16862306a36Sopenharmony_ci ar9287Modes_tx_gain_9287_1_1); 16962306a36Sopenharmony_ci } else if (AR_SREV_9280_20(ah)) { 17062306a36Sopenharmony_ci ar9280_20_hw_init_txgain_ini(ah, txgain_type); 17162306a36Sopenharmony_ci } else if (AR_SREV_9285_12_OR_LATER(ah)) { 17262306a36Sopenharmony_ci /* txgain table */ 17362306a36Sopenharmony_ci if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { 17462306a36Sopenharmony_ci if (AR_SREV_9285E_20(ah)) { 17562306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 17662306a36Sopenharmony_ci ar9285Modes_XE2_0_high_power); 17762306a36Sopenharmony_ci } else { 17862306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 17962306a36Sopenharmony_ci ar9285Modes_high_power_tx_gain_9285_1_2); 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci } else { 18262306a36Sopenharmony_ci if (AR_SREV_9285E_20(ah)) { 18362306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 18462306a36Sopenharmony_ci ar9285Modes_XE2_0_normal_power); 18562306a36Sopenharmony_ci } else { 18662306a36Sopenharmony_ci INIT_INI_ARRAY(&ah->iniModesTxGain, 18762306a36Sopenharmony_ci ar9285Modes_original_tx_gain_9285_1_2); 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/* 19462306a36Sopenharmony_ci * Helper for ASPM support. 19562306a36Sopenharmony_ci * 19662306a36Sopenharmony_ci * Disable PLL when in L0s as well as receiver clock when in L1. 19762306a36Sopenharmony_ci * This power saving option must be enabled through the SerDes. 19862306a36Sopenharmony_ci * 19962306a36Sopenharmony_ci * Programming the SerDes must go through the same 288 bit serial shift 20062306a36Sopenharmony_ci * register as the other analog registers. Hence the 9 writes. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_cistatic void ar9002_hw_configpcipowersave(struct ath_hw *ah, 20362306a36Sopenharmony_ci bool power_off) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci u8 i; 20662306a36Sopenharmony_ci u32 val; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* Nothing to do on restore for 11N */ 20962306a36Sopenharmony_ci if (!power_off /* !restore */) { 21062306a36Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 21162306a36Sopenharmony_ci /* 21262306a36Sopenharmony_ci * AR9280 2.0 or later chips use SerDes values from the 21362306a36Sopenharmony_ci * initvals.h initialized depending on chipset during 21462306a36Sopenharmony_ci * __ath9k_hw_init() 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_ci for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { 21762306a36Sopenharmony_ci REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), 21862306a36Sopenharmony_ci INI_RA(&ah->iniPcieSerdes, i, 1)); 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci } else { 22162306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); 22462306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* RX shut off when elecidle is asserted */ 22762306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); 22862306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); 22962306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* 23262306a36Sopenharmony_ci * Ignore ah->ah_config.pcie_clock_req setting for 23362306a36Sopenharmony_ci * pre-AR9280 11n 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); 23862306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); 23962306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci /* Load the new settings */ 24262306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci udelay(1000); 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (power_off) { 25162306a36Sopenharmony_ci /* clear bit 19 to disable L1 */ 25262306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_PCIE_PM_CTRL(ah), AR_PCIE_PM_CTRL_ENA); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci val = REG_READ(ah, AR_WA(ah)); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* 25762306a36Sopenharmony_ci * Set PCIe workaround bits 25862306a36Sopenharmony_ci * In AR9280 and AR9285, bit 14 in WA register (disable L1) 25962306a36Sopenharmony_ci * should only be set when device enters D3 and be 26062306a36Sopenharmony_ci * cleared when device comes back to D0. 26162306a36Sopenharmony_ci */ 26262306a36Sopenharmony_ci if (ah->config.pcie_waen) { 26362306a36Sopenharmony_ci if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) 26462306a36Sopenharmony_ci val |= AR_WA_D3_L1_DISABLE; 26562306a36Sopenharmony_ci } else { 26662306a36Sopenharmony_ci if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) { 26762306a36Sopenharmony_ci if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE) 26862306a36Sopenharmony_ci val |= AR_WA_D3_L1_DISABLE; 26962306a36Sopenharmony_ci } else if (AR_SREV_9280(ah)) { 27062306a36Sopenharmony_ci if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE) 27162306a36Sopenharmony_ci val |= AR_WA_D3_L1_DISABLE; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { 27662306a36Sopenharmony_ci /* 27762306a36Sopenharmony_ci * Disable bit 6 and 7 before entering D3 to 27862306a36Sopenharmony_ci * prevent system hang. 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ci val &= ~(AR_WA_BIT6 | AR_WA_BIT7); 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (AR_SREV_9280(ah)) 28462306a36Sopenharmony_ci val |= AR_WA_BIT22; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci if (AR_SREV_9285E_20(ah)) 28762306a36Sopenharmony_ci val |= AR_WA_BIT23; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), val); 29062306a36Sopenharmony_ci } else { 29162306a36Sopenharmony_ci if (ah->config.pcie_waen) { 29262306a36Sopenharmony_ci val = ah->config.pcie_waen; 29362306a36Sopenharmony_ci val &= (~AR_WA_D3_L1_DISABLE); 29462306a36Sopenharmony_ci } else { 29562306a36Sopenharmony_ci if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) { 29662306a36Sopenharmony_ci val = AR9285_WA_DEFAULT; 29762306a36Sopenharmony_ci val &= (~AR_WA_D3_L1_DISABLE); 29862306a36Sopenharmony_ci } else if (AR_SREV_9280(ah)) { 29962306a36Sopenharmony_ci /* 30062306a36Sopenharmony_ci * For AR9280 chips, bit 22 of 0x4004 30162306a36Sopenharmony_ci * needs to be set. 30262306a36Sopenharmony_ci */ 30362306a36Sopenharmony_ci val = AR9280_WA_DEFAULT; 30462306a36Sopenharmony_ci val &= (~AR_WA_D3_L1_DISABLE); 30562306a36Sopenharmony_ci } else { 30662306a36Sopenharmony_ci val = AR_WA_DEFAULT; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* WAR for ASPM system hang */ 31162306a36Sopenharmony_ci if (AR_SREV_9285(ah) || AR_SREV_9287(ah)) 31262306a36Sopenharmony_ci val |= (AR_WA_BIT6 | AR_WA_BIT7); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (AR_SREV_9285E_20(ah)) 31562306a36Sopenharmony_ci val |= AR_WA_BIT23; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), val); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* set bit 19 to allow forcing of pcie core into L1 state */ 32062306a36Sopenharmony_ci REG_SET_BIT(ah, AR_PCIE_PM_CTRL(ah), AR_PCIE_PM_CTRL_ENA); 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic int ar9002_hw_get_radiorev(struct ath_hw *ah) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci u32 val; 32762306a36Sopenharmony_ci int i; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY(0x36), 0x00007058); 33262306a36Sopenharmony_ci for (i = 0; i < 8; i++) 33362306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY(0x20), 0x00010000); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; 33862306a36Sopenharmony_ci val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci return ath9k_hw_reverse_bits(val, 8); 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ciint ar9002_hw_rf_claim(struct ath_hw *ah) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci u32 val; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY(0), 0x00000007); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci val = ar9002_hw_get_radiorev(ah); 35062306a36Sopenharmony_ci switch (val & AR_RADIO_SREV_MAJOR) { 35162306a36Sopenharmony_ci case 0: 35262306a36Sopenharmony_ci val = AR_RAD5133_SREV_MAJOR; 35362306a36Sopenharmony_ci break; 35462306a36Sopenharmony_ci case AR_RAD5133_SREV_MAJOR: 35562306a36Sopenharmony_ci case AR_RAD5122_SREV_MAJOR: 35662306a36Sopenharmony_ci case AR_RAD2133_SREV_MAJOR: 35762306a36Sopenharmony_ci case AR_RAD2122_SREV_MAJOR: 35862306a36Sopenharmony_ci break; 35962306a36Sopenharmony_ci default: 36062306a36Sopenharmony_ci ath_err(ath9k_hw_common(ah), 36162306a36Sopenharmony_ci "Radio Chip Rev 0x%02X not supported\n", 36262306a36Sopenharmony_ci val & AR_RADIO_SREV_MAJOR); 36362306a36Sopenharmony_ci return -EOPNOTSUPP; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci ah->hw_version.analog5GhzRev = val; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci return 0; 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_civoid ar9002_hw_enable_async_fifo(struct ath_hw *ah) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci if (AR_SREV_9287_13_OR_LATER(ah)) { 37462306a36Sopenharmony_ci REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, 37562306a36Sopenharmony_ci AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); 37662306a36Sopenharmony_ci REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); 37762306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, 37862306a36Sopenharmony_ci AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); 37962306a36Sopenharmony_ci REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, 38062306a36Sopenharmony_ci AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic void ar9002_hw_init_hang_checks(struct ath_hw *ah) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { 38762306a36Sopenharmony_ci ah->config.hw_hang_checks |= HW_BB_RIFS_HANG; 38862306a36Sopenharmony_ci ah->config.hw_hang_checks |= HW_BB_DFS_HANG; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (AR_SREV_9280(ah)) 39262306a36Sopenharmony_ci ah->config.hw_hang_checks |= HW_BB_RX_CLEAR_STUCK_HANG; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (AR_SREV_5416(ah) || AR_SREV_9100(ah) || AR_SREV_9160(ah)) 39562306a36Sopenharmony_ci ah->config.hw_hang_checks |= HW_MAC_HANG; 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ 39962306a36Sopenharmony_ciint ar9002_hw_attach_ops(struct ath_hw *ah) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 40262306a36Sopenharmony_ci struct ath_hw_ops *ops = ath9k_hw_ops(ah); 40362306a36Sopenharmony_ci int ret; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci ret = ar9002_hw_init_mode_regs(ah); 40662306a36Sopenharmony_ci if (ret) 40762306a36Sopenharmony_ci return ret; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; 41062306a36Sopenharmony_ci priv_ops->init_hang_checks = ar9002_hw_init_hang_checks; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci ops->config_pci_powersave = ar9002_hw_configpcipowersave; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci ret = ar5008_hw_attach_phy_ops(ah); 41562306a36Sopenharmony_ci if (ret) 41662306a36Sopenharmony_ci return ret; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) 41962306a36Sopenharmony_ci ar9002_hw_attach_phy_ops(ah); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci ar9002_hw_attach_calib_ops(ah); 42262306a36Sopenharmony_ci ar9002_hw_attach_mac_ops(ah); 42362306a36Sopenharmony_ci return 0; 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_civoid ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci u32 modesIndex; 42962306a36Sopenharmony_ci int i; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (IS_CHAN_5GHZ(chan)) 43262306a36Sopenharmony_ci modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; 43362306a36Sopenharmony_ci else 43462306a36Sopenharmony_ci modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) { 43962306a36Sopenharmony_ci u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0); 44062306a36Sopenharmony_ci u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex); 44162306a36Sopenharmony_ci u32 val_orig; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci if (reg == AR_PHY_CCK_DETECT) { 44462306a36Sopenharmony_ci val_orig = REG_READ(ah, reg); 44562306a36Sopenharmony_ci val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; 44662306a36Sopenharmony_ci val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci REG_WRITE(ah, reg, val|val_orig); 44962306a36Sopenharmony_ci } else 45062306a36Sopenharmony_ci REG_WRITE(ah, reg, val); 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 45462306a36Sopenharmony_ci} 455