xref: /openbmc/linux/drivers/net/wireless/ath/ath9k/ar9002_hw.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1b3950e6aSLuis R. Rodriguez /*
25b68138eSSujith Manoharan  * Copyright (c) 2008-2011 Atheros Communications Inc.
3b3950e6aSLuis R. Rodriguez  *
4b3950e6aSLuis R. Rodriguez  * Permission to use, copy, modify, and/or distribute this software for any
5b3950e6aSLuis R. Rodriguez  * purpose with or without fee is hereby granted, provided that the above
6b3950e6aSLuis R. Rodriguez  * copyright notice and this permission notice appear in all copies.
7b3950e6aSLuis R. Rodriguez  *
8b3950e6aSLuis R. Rodriguez  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9b3950e6aSLuis R. Rodriguez  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10b3950e6aSLuis R. Rodriguez  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11b3950e6aSLuis R. Rodriguez  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12b3950e6aSLuis R. Rodriguez  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13b3950e6aSLuis R. Rodriguez  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14b3950e6aSLuis R. Rodriguez  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15b3950e6aSLuis R. Rodriguez  */
16b3950e6aSLuis R. Rodriguez 
176eb07cafSPaul Gortmaker #include <linux/moduleparam.h>
18b3950e6aSLuis R. Rodriguez #include "hw.h"
19b3950e6aSLuis R. Rodriguez #include "ar5008_initvals.h"
20b3950e6aSLuis R. Rodriguez #include "ar9001_initvals.h"
21b3950e6aSLuis R. Rodriguez #include "ar9002_initvals.h"
22e9141f71SSujith #include "ar9002_phy.h"
23b3950e6aSLuis R. Rodriguez 
24b3950e6aSLuis R. Rodriguez /* General hardware code for the A5008/AR9001/AR9002 hadware families */
25b3950e6aSLuis R. Rodriguez 
ar9002_hw_init_mode_regs(struct ath_hw * ah)266aaacd86SFelix Fietkau static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
27b3950e6aSLuis R. Rodriguez {
28b3950e6aSLuis R. Rodriguez 	if (AR_SREV_9271(ah)) {
29a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271);
30a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271);
31a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg);
326aaacd86SFelix Fietkau 		return 0;
33b3950e6aSLuis R. Rodriguez 	}
34b3950e6aSLuis R. Rodriguez 
3514fec8d9SFelix Fietkau 	INIT_INI_ARRAY(&ah->iniPcieSerdes,
36a364517bSFelix Fietkau 		       ar9280PciePhy_clkreq_always_on_L1_9280);
3714fec8d9SFelix Fietkau 
38b3950e6aSLuis R. Rodriguez 	if (AR_SREV_9287_11_OR_LATER(ah)) {
39a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
40a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1);
41b3950e6aSLuis R. Rodriguez 	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
42a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2);
43a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2);
44b3950e6aSLuis R. Rodriguez 	} else if (AR_SREV_9280_20_OR_LATER(ah)) {
45a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2);
46a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2);
47b3950e6aSLuis R. Rodriguez 
48c7d36f9fSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModesFastClock,
49a364517bSFelix Fietkau 			       ar9280Modes_fast_clock_9280_2);
50b3950e6aSLuis R. Rodriguez 	} else if (AR_SREV_9160_10_OR_LATER(ah)) {
51a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160);
52a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160);
53b3950e6aSLuis R. Rodriguez 		if (AR_SREV_9160_11(ah)) {
54b3950e6aSLuis R. Rodriguez 			INIT_INI_ARRAY(&ah->iniAddac,
55a364517bSFelix Fietkau 				       ar5416Addac_9160_1_1);
56b3950e6aSLuis R. Rodriguez 		} else {
57a364517bSFelix Fietkau 			INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160);
58b3950e6aSLuis R. Rodriguez 		}
59b3950e6aSLuis R. Rodriguez 	} else if (AR_SREV_9100_OR_LATER(ah)) {
60a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
61a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
62a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
63b3950e6aSLuis R. Rodriguez 	} else {
64a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
65a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
66a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
6714fec8d9SFelix Fietkau 	}
6814fec8d9SFelix Fietkau 
6914fec8d9SFelix Fietkau 	if (!AR_SREV_9280_20_OR_LATER(ah)) {
7014fec8d9SFelix Fietkau 		/* Common for AR5416, AR913x, AR9160 */
71a364517bSFelix Fietkau 		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
7214fec8d9SFelix Fietkau 
7314fec8d9SFelix Fietkau 		/* Common for AR913x, AR9160 */
7414fec8d9SFelix Fietkau 		if (!AR_SREV_5416(ah))
7537c62fecSFelix Fietkau 			INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
7637c62fecSFelix Fietkau 		else
7737c62fecSFelix Fietkau 			INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
78b3950e6aSLuis R. Rodriguez 	}
799bbb8168SFelix Fietkau 
809bbb8168SFelix Fietkau 	/* iniAddac needs to be modified for these chips */
819bbb8168SFelix Fietkau 	if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
829bbb8168SFelix Fietkau 		struct ar5416IniArray *addac = &ah->iniAddac;
839bbb8168SFelix Fietkau 		u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
849bbb8168SFelix Fietkau 		u32 *data;
859bbb8168SFelix Fietkau 
86c1b976d2SFelix Fietkau 		data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
879bbb8168SFelix Fietkau 		if (!data)
886aaacd86SFelix Fietkau 			return -ENOMEM;
899bbb8168SFelix Fietkau 
909bbb8168SFelix Fietkau 		memcpy(data, addac->ia_array, size);
919bbb8168SFelix Fietkau 		addac->ia_array = data;
929bbb8168SFelix Fietkau 
939bbb8168SFelix Fietkau 		if (!AR_SREV_5416_22_OR_LATER(ah)) {
949bbb8168SFelix Fietkau 			/* override CLKDRV value */
959bbb8168SFelix Fietkau 			INI_RA(addac, 31,1) = 0;
969bbb8168SFelix Fietkau 		}
979bbb8168SFelix Fietkau 	}
98d8f492b7SLuis R. Rodriguez 	if (AR_SREV_9287_11_OR_LATER(ah)) {
99d8f492b7SLuis R. Rodriguez 		INIT_INI_ARRAY(&ah->iniCckfirNormal,
100a364517bSFelix Fietkau 		       ar9287Common_normal_cck_fir_coeff_9287_1_1);
101d8f492b7SLuis R. Rodriguez 		INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
102a364517bSFelix Fietkau 		       ar9287Common_japan_2484_cck_fir_coeff_9287_1_1);
103d8f492b7SLuis R. Rodriguez 	}
1046aaacd86SFelix Fietkau 	return 0;
105d8f492b7SLuis R. Rodriguez }
106d8f492b7SLuis R. Rodriguez 
ar9280_20_hw_init_rxgain_ini(struct ath_hw * ah)107991312d8SLuis R. Rodriguez static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
108991312d8SLuis R. Rodriguez {
109991312d8SLuis R. Rodriguez 	u32 rxgain_type;
110991312d8SLuis R. Rodriguez 
1117d7dc538SMartin Blumenstingl 	if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_17) {
112991312d8SLuis R. Rodriguez 		rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
113991312d8SLuis R. Rodriguez 
114991312d8SLuis R. Rodriguez 		if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
115991312d8SLuis R. Rodriguez 			INIT_INI_ARRAY(&ah->iniModesRxGain,
116a364517bSFelix Fietkau 				       ar9280Modes_backoff_13db_rxgain_9280_2);
117991312d8SLuis R. Rodriguez 		else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
118991312d8SLuis R. Rodriguez 			INIT_INI_ARRAY(&ah->iniModesRxGain,
119a364517bSFelix Fietkau 				       ar9280Modes_backoff_23db_rxgain_9280_2);
120991312d8SLuis R. Rodriguez 		else
121991312d8SLuis R. Rodriguez 			INIT_INI_ARRAY(&ah->iniModesRxGain,
122a364517bSFelix Fietkau 				       ar9280Modes_original_rxgain_9280_2);
123991312d8SLuis R. Rodriguez 	} else {
124991312d8SLuis R. Rodriguez 		INIT_INI_ARRAY(&ah->iniModesRxGain,
125a364517bSFelix Fietkau 			       ar9280Modes_original_rxgain_9280_2);
126991312d8SLuis R. Rodriguez 	}
127991312d8SLuis R. Rodriguez }
128991312d8SLuis R. Rodriguez 
ar9280_20_hw_init_txgain_ini(struct ath_hw * ah,u32 txgain_type)129aa0e5786SFelix Fietkau static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
130991312d8SLuis R. Rodriguez {
1317d7dc538SMartin Blumenstingl 	if (ah->eep_ops->get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) {
132991312d8SLuis R. Rodriguez 		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
133991312d8SLuis R. Rodriguez 			INIT_INI_ARRAY(&ah->iniModesTxGain,
134a364517bSFelix Fietkau 				       ar9280Modes_high_power_tx_gain_9280_2);
135991312d8SLuis R. Rodriguez 		else
136991312d8SLuis R. Rodriguez 			INIT_INI_ARRAY(&ah->iniModesTxGain,
137a364517bSFelix Fietkau 				       ar9280Modes_original_tx_gain_9280_2);
138991312d8SLuis R. Rodriguez 	} else {
139991312d8SLuis R. Rodriguez 		INIT_INI_ARRAY(&ah->iniModesTxGain,
140a364517bSFelix Fietkau 			       ar9280Modes_original_tx_gain_9280_2);
141991312d8SLuis R. Rodriguez 	}
142991312d8SLuis R. Rodriguez }
143991312d8SLuis R. Rodriguez 
ar9271_hw_init_txgain_ini(struct ath_hw * ah,u32 txgain_type)144aa0e5786SFelix Fietkau static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
145aa0e5786SFelix Fietkau {
146aa0e5786SFelix Fietkau 	if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
147aa0e5786SFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModesTxGain,
148a364517bSFelix Fietkau 			       ar9271Modes_high_power_tx_gain_9271);
149aa0e5786SFelix Fietkau 	else
150aa0e5786SFelix Fietkau 		INIT_INI_ARRAY(&ah->iniModesTxGain,
151a364517bSFelix Fietkau 			       ar9271Modes_normal_power_tx_gain_9271);
152aa0e5786SFelix Fietkau }
153aa0e5786SFelix Fietkau 
ar9002_hw_init_mode_gain_regs(struct ath_hw * ah)154991312d8SLuis R. Rodriguez static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
155991312d8SLuis R. Rodriguez {
156aa0e5786SFelix Fietkau 	u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
157aa0e5786SFelix Fietkau 
158991312d8SLuis R. Rodriguez 	if (AR_SREV_9287_11_OR_LATER(ah))
159991312d8SLuis R. Rodriguez 		INIT_INI_ARRAY(&ah->iniModesRxGain,
160a364517bSFelix Fietkau 			       ar9287Modes_rx_gain_9287_1_1);
161991312d8SLuis R. Rodriguez 	else if (AR_SREV_9280_20(ah))
162991312d8SLuis R. Rodriguez 		ar9280_20_hw_init_rxgain_ini(ah);
163991312d8SLuis R. Rodriguez 
164aa0e5786SFelix Fietkau 	if (AR_SREV_9271(ah)) {
165aa0e5786SFelix Fietkau 		ar9271_hw_init_txgain_ini(ah, txgain_type);
166aa0e5786SFelix Fietkau 	} else if (AR_SREV_9287_11_OR_LATER(ah)) {
167991312d8SLuis R. Rodriguez 		INIT_INI_ARRAY(&ah->iniModesTxGain,
168a364517bSFelix Fietkau 			       ar9287Modes_tx_gain_9287_1_1);
169991312d8SLuis R. Rodriguez 	} else if (AR_SREV_9280_20(ah)) {
170aa0e5786SFelix Fietkau 		ar9280_20_hw_init_txgain_ini(ah, txgain_type);
171991312d8SLuis R. Rodriguez 	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
172991312d8SLuis R. Rodriguez 		/* txgain table */
173991312d8SLuis R. Rodriguez 		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
174991312d8SLuis R. Rodriguez 			if (AR_SREV_9285E_20(ah)) {
175991312d8SLuis R. Rodriguez 				INIT_INI_ARRAY(&ah->iniModesTxGain,
176a364517bSFelix Fietkau 					       ar9285Modes_XE2_0_high_power);
177991312d8SLuis R. Rodriguez 			} else {
178991312d8SLuis R. Rodriguez 				INIT_INI_ARRAY(&ah->iniModesTxGain,
179a364517bSFelix Fietkau 					ar9285Modes_high_power_tx_gain_9285_1_2);
180991312d8SLuis R. Rodriguez 			}
181991312d8SLuis R. Rodriguez 		} else {
182991312d8SLuis R. Rodriguez 			if (AR_SREV_9285E_20(ah)) {
183991312d8SLuis R. Rodriguez 				INIT_INI_ARRAY(&ah->iniModesTxGain,
184a364517bSFelix Fietkau 					       ar9285Modes_XE2_0_normal_power);
185991312d8SLuis R. Rodriguez 			} else {
186991312d8SLuis R. Rodriguez 				INIT_INI_ARRAY(&ah->iniModesTxGain,
187a364517bSFelix Fietkau 					ar9285Modes_original_tx_gain_9285_1_2);
188991312d8SLuis R. Rodriguez 			}
189991312d8SLuis R. Rodriguez 		}
190991312d8SLuis R. Rodriguez 	}
191991312d8SLuis R. Rodriguez }
192991312d8SLuis R. Rodriguez 
193b3950e6aSLuis R. Rodriguez /*
194b3950e6aSLuis R. Rodriguez  * Helper for ASPM support.
195b3950e6aSLuis R. Rodriguez  *
196b3950e6aSLuis R. Rodriguez  * Disable PLL when in L0s as well as receiver clock when in L1.
197b3950e6aSLuis R. Rodriguez  * This power saving option must be enabled through the SerDes.
198b3950e6aSLuis R. Rodriguez  *
199b3950e6aSLuis R. Rodriguez  * Programming the SerDes must go through the same 288 bit serial shift
200b3950e6aSLuis R. Rodriguez  * register as the other analog registers.  Hence the 9 writes.
201b3950e6aSLuis R. Rodriguez  */
ar9002_hw_configpcipowersave(struct ath_hw * ah,bool power_off)202b3950e6aSLuis R. Rodriguez static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
20384c87dc8SStanislaw Gruszka 					 bool power_off)
204b3950e6aSLuis R. Rodriguez {
205b3950e6aSLuis R. Rodriguez 	u8 i;
206b3950e6aSLuis R. Rodriguez 	u32 val;
207b3950e6aSLuis R. Rodriguez 
208b3950e6aSLuis R. Rodriguez 	/* Nothing to do on restore for 11N */
20984c87dc8SStanislaw Gruszka 	if (!power_off /* !restore */) {
210b3950e6aSLuis R. Rodriguez 		if (AR_SREV_9280_20_OR_LATER(ah)) {
211b3950e6aSLuis R. Rodriguez 			/*
212b3950e6aSLuis R. Rodriguez 			 * AR9280 2.0 or later chips use SerDes values from the
213b3950e6aSLuis R. Rodriguez 			 * initvals.h initialized depending on chipset during
214b3950e6aSLuis R. Rodriguez 			 * __ath9k_hw_init()
215b3950e6aSLuis R. Rodriguez 			 */
216b3950e6aSLuis R. Rodriguez 			for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
217b3950e6aSLuis R. Rodriguez 				REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
218b3950e6aSLuis R. Rodriguez 					  INI_RA(&ah->iniPcieSerdes, i, 1));
219b3950e6aSLuis R. Rodriguez 			}
220b3950e6aSLuis R. Rodriguez 		} else {
221d5e347bfSSujith 			ENABLE_REGWRITE_BUFFER(ah);
222d5e347bfSSujith 
223b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
224b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
225b3950e6aSLuis R. Rodriguez 
226b3950e6aSLuis R. Rodriguez 			/* RX shut off when elecidle is asserted */
227b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
228b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
229b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
230b3950e6aSLuis R. Rodriguez 
231b3950e6aSLuis R. Rodriguez 			/*
232b3950e6aSLuis R. Rodriguez 			 * Ignore ah->ah_config.pcie_clock_req setting for
233b3950e6aSLuis R. Rodriguez 			 * pre-AR9280 11n
234b3950e6aSLuis R. Rodriguez 			 */
235b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
236b3950e6aSLuis R. Rodriguez 
237b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
238b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
239b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
240b3950e6aSLuis R. Rodriguez 
241b3950e6aSLuis R. Rodriguez 			/* Load the new settings */
242b3950e6aSLuis R. Rodriguez 			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
243d5e347bfSSujith 
244d5e347bfSSujith 			REGWRITE_BUFFER_FLUSH(ah);
245b3950e6aSLuis R. Rodriguez 		}
246b3950e6aSLuis R. Rodriguez 
247b3950e6aSLuis R. Rodriguez 		udelay(1000);
24815ae733bSSujith 	}
249b3950e6aSLuis R. Rodriguez 
25015ae733bSSujith 	if (power_off) {
25115ae733bSSujith 		/* clear bit 19 to disable L1 */
252*b3a663f0SWenli Looi 		REG_CLR_BIT(ah, AR_PCIE_PM_CTRL(ah), AR_PCIE_PM_CTRL_ENA);
253b3950e6aSLuis R. Rodriguez 
254*b3a663f0SWenli Looi 		val = REG_READ(ah, AR_WA(ah));
25515ae733bSSujith 
25615ae733bSSujith 		/*
25715ae733bSSujith 		 * Set PCIe workaround bits
25815ae733bSSujith 		 * In AR9280 and AR9285, bit 14 in WA register (disable L1)
25915ae733bSSujith 		 * should only  be set when device enters D3 and be
26015ae733bSSujith 		 * cleared when device comes back to D0.
26115ae733bSSujith 		 */
26215ae733bSSujith 		if (ah->config.pcie_waen) {
26315ae733bSSujith 			if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
26415ae733bSSujith 				val |= AR_WA_D3_L1_DISABLE;
26515ae733bSSujith 		} else {
266d1ae25a0SSujith Manoharan 			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
267d1ae25a0SSujith Manoharan 				if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
268d1ae25a0SSujith Manoharan 					val |= AR_WA_D3_L1_DISABLE;
269d1ae25a0SSujith Manoharan 			} else if (AR_SREV_9280(ah)) {
270d1ae25a0SSujith Manoharan 				if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
27115ae733bSSujith 					val |= AR_WA_D3_L1_DISABLE;
27215ae733bSSujith 			}
27315ae733bSSujith 		}
27415ae733bSSujith 
27515ae733bSSujith 		if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
27615ae733bSSujith 			/*
27715ae733bSSujith 			 * Disable bit 6 and 7 before entering D3 to
27815ae733bSSujith 			 * prevent system hang.
27915ae733bSSujith 			 */
28015ae733bSSujith 			val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
28115ae733bSSujith 		}
28215ae733bSSujith 
283f119da30SVasanthakumar Thiagarajan 		if (AR_SREV_9280(ah))
284f119da30SVasanthakumar Thiagarajan 			val |= AR_WA_BIT22;
285f119da30SVasanthakumar Thiagarajan 
28615ae733bSSujith 		if (AR_SREV_9285E_20(ah))
28715ae733bSSujith 			val |= AR_WA_BIT23;
28815ae733bSSujith 
289*b3a663f0SWenli Looi 		REG_WRITE(ah, AR_WA(ah), val);
29015ae733bSSujith 	} else {
291b3950e6aSLuis R. Rodriguez 		if (ah->config.pcie_waen) {
292b3950e6aSLuis R. Rodriguez 			val = ah->config.pcie_waen;
293b3950e6aSLuis R. Rodriguez 			val &= (~AR_WA_D3_L1_DISABLE);
294b3950e6aSLuis R. Rodriguez 		} else {
295d1ae25a0SSujith Manoharan 			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
296b3950e6aSLuis R. Rodriguez 				val = AR9285_WA_DEFAULT;
297b3950e6aSLuis R. Rodriguez 				val &= (~AR_WA_D3_L1_DISABLE);
298d1ae25a0SSujith Manoharan 			} else if (AR_SREV_9280(ah)) {
299b3950e6aSLuis R. Rodriguez 				/*
30015ae733bSSujith 				 * For AR9280 chips, bit 22 of 0x4004
30115ae733bSSujith 				 * needs to be set.
302b3950e6aSLuis R. Rodriguez 				 */
303b3950e6aSLuis R. Rodriguez 				val = AR9280_WA_DEFAULT;
304b3950e6aSLuis R. Rodriguez 				val &= (~AR_WA_D3_L1_DISABLE);
30515ae733bSSujith 			} else {
306b3950e6aSLuis R. Rodriguez 				val = AR_WA_DEFAULT;
307b3950e6aSLuis R. Rodriguez 			}
30815ae733bSSujith 		}
30915ae733bSSujith 
31015ae733bSSujith 		/* WAR for ASPM system hang */
3115b64aa72SRajkumar Manoharan 		if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
31215ae733bSSujith 			val |= (AR_WA_BIT6 | AR_WA_BIT7);
31315ae733bSSujith 
31415ae733bSSujith 		if (AR_SREV_9285E_20(ah))
31515ae733bSSujith 			val |= AR_WA_BIT23;
316b3950e6aSLuis R. Rodriguez 
317*b3a663f0SWenli Looi 		REG_WRITE(ah, AR_WA(ah), val);
318b3950e6aSLuis R. Rodriguez 
31915ae733bSSujith 		/* set bit 19 to allow forcing of pcie core into L1 state */
320*b3a663f0SWenli Looi 		REG_SET_BIT(ah, AR_PCIE_PM_CTRL(ah), AR_PCIE_PM_CTRL_ENA);
321b3950e6aSLuis R. Rodriguez 	}
322b3950e6aSLuis R. Rodriguez }
323b3950e6aSLuis R. Rodriguez 
ar9002_hw_get_radiorev(struct ath_hw * ah)324ebd5a14aSLuis R. Rodriguez static int ar9002_hw_get_radiorev(struct ath_hw *ah)
325ebd5a14aSLuis R. Rodriguez {
326ebd5a14aSLuis R. Rodriguez 	u32 val;
327ebd5a14aSLuis R. Rodriguez 	int i;
328ebd5a14aSLuis R. Rodriguez 
3297d0d0df0SSujith 	ENABLE_REGWRITE_BUFFER(ah);
330ebd5a14aSLuis R. Rodriguez 
3317d0d0df0SSujith 	REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
332ebd5a14aSLuis R. Rodriguez 	for (i = 0; i < 8; i++)
333ebd5a14aSLuis R. Rodriguez 		REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
3347d0d0df0SSujith 
3357d0d0df0SSujith 	REGWRITE_BUFFER_FLUSH(ah);
3367d0d0df0SSujith 
337ebd5a14aSLuis R. Rodriguez 	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
338ebd5a14aSLuis R. Rodriguez 	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
339ebd5a14aSLuis R. Rodriguez 
340ebd5a14aSLuis R. Rodriguez 	return ath9k_hw_reverse_bits(val, 8);
341ebd5a14aSLuis R. Rodriguez }
342ebd5a14aSLuis R. Rodriguez 
ar9002_hw_rf_claim(struct ath_hw * ah)343ebd5a14aSLuis R. Rodriguez int ar9002_hw_rf_claim(struct ath_hw *ah)
344ebd5a14aSLuis R. Rodriguez {
345ebd5a14aSLuis R. Rodriguez 	u32 val;
346ebd5a14aSLuis R. Rodriguez 
347ebd5a14aSLuis R. Rodriguez 	REG_WRITE(ah, AR_PHY(0), 0x00000007);
348ebd5a14aSLuis R. Rodriguez 
349ebd5a14aSLuis R. Rodriguez 	val = ar9002_hw_get_radiorev(ah);
350ebd5a14aSLuis R. Rodriguez 	switch (val & AR_RADIO_SREV_MAJOR) {
351ebd5a14aSLuis R. Rodriguez 	case 0:
352ebd5a14aSLuis R. Rodriguez 		val = AR_RAD5133_SREV_MAJOR;
353ebd5a14aSLuis R. Rodriguez 		break;
354ebd5a14aSLuis R. Rodriguez 	case AR_RAD5133_SREV_MAJOR:
355ebd5a14aSLuis R. Rodriguez 	case AR_RAD5122_SREV_MAJOR:
356ebd5a14aSLuis R. Rodriguez 	case AR_RAD2133_SREV_MAJOR:
357ebd5a14aSLuis R. Rodriguez 	case AR_RAD2122_SREV_MAJOR:
358ebd5a14aSLuis R. Rodriguez 		break;
359ebd5a14aSLuis R. Rodriguez 	default:
3603800276aSJoe Perches 		ath_err(ath9k_hw_common(ah),
361ebd5a14aSLuis R. Rodriguez 			"Radio Chip Rev 0x%02X not supported\n",
362ebd5a14aSLuis R. Rodriguez 			val & AR_RADIO_SREV_MAJOR);
363ebd5a14aSLuis R. Rodriguez 		return -EOPNOTSUPP;
364ebd5a14aSLuis R. Rodriguez 	}
365ebd5a14aSLuis R. Rodriguez 
366ebd5a14aSLuis R. Rodriguez 	ah->hw_version.analog5GhzRev = val;
367ebd5a14aSLuis R. Rodriguez 
368ebd5a14aSLuis R. Rodriguez 	return 0;
369ebd5a14aSLuis R. Rodriguez }
370ebd5a14aSLuis R. Rodriguez 
ar9002_hw_enable_async_fifo(struct ath_hw * ah)371e9141f71SSujith void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
372e9141f71SSujith {
373e9141f71SSujith 	if (AR_SREV_9287_13_OR_LATER(ah)) {
374e9141f71SSujith 		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
375e9141f71SSujith 				AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
376e9141f71SSujith 		REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
377e9141f71SSujith 		REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
378e9141f71SSujith 				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
379e9141f71SSujith 		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
380e9141f71SSujith 				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
381e9141f71SSujith 	}
382e9141f71SSujith }
383e9141f71SSujith 
ar9002_hw_init_hang_checks(struct ath_hw * ah)3844598702dSSujith Manoharan static void ar9002_hw_init_hang_checks(struct ath_hw *ah)
3854598702dSSujith Manoharan {
3864598702dSSujith Manoharan 	if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
3874598702dSSujith Manoharan 		ah->config.hw_hang_checks |= HW_BB_RIFS_HANG;
3884598702dSSujith Manoharan 		ah->config.hw_hang_checks |= HW_BB_DFS_HANG;
3894598702dSSujith Manoharan 	}
3904598702dSSujith Manoharan 
3914598702dSSujith Manoharan 	if (AR_SREV_9280(ah))
3924598702dSSujith Manoharan 		ah->config.hw_hang_checks |= HW_BB_RX_CLEAR_STUCK_HANG;
3934598702dSSujith Manoharan 
3944598702dSSujith Manoharan 	if (AR_SREV_5416(ah) || AR_SREV_9100(ah) || AR_SREV_9160(ah))
3954598702dSSujith Manoharan 		ah->config.hw_hang_checks |= HW_MAC_HANG;
3964598702dSSujith Manoharan }
3974598702dSSujith Manoharan 
398b3950e6aSLuis R. Rodriguez /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
ar9002_hw_attach_ops(struct ath_hw * ah)399c1b976d2SFelix Fietkau int ar9002_hw_attach_ops(struct ath_hw *ah)
400b3950e6aSLuis R. Rodriguez {
401b3950e6aSLuis R. Rodriguez 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
402b3950e6aSLuis R. Rodriguez 	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
403c1b976d2SFelix Fietkau 	int ret;
404b3950e6aSLuis R. Rodriguez 
4056aaacd86SFelix Fietkau 	ret = ar9002_hw_init_mode_regs(ah);
4066aaacd86SFelix Fietkau 	if (ret)
4076aaacd86SFelix Fietkau 		return ret;
4086aaacd86SFelix Fietkau 
409991312d8SLuis R. Rodriguez 	priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
4104598702dSSujith Manoharan 	priv_ops->init_hang_checks = ar9002_hw_init_hang_checks;
411b3950e6aSLuis R. Rodriguez 
412b3950e6aSLuis R. Rodriguez 	ops->config_pci_powersave = ar9002_hw_configpcipowersave;
413b3950e6aSLuis R. Rodriguez 
414c1b976d2SFelix Fietkau 	ret = ar5008_hw_attach_phy_ops(ah);
415c1b976d2SFelix Fietkau 	if (ret)
416c1b976d2SFelix Fietkau 		return ret;
417c1b976d2SFelix Fietkau 
4187a37081eSFelix Fietkau 	if (AR_SREV_9280_20_OR_LATER(ah))
419b3950e6aSLuis R. Rodriguez 		ar9002_hw_attach_phy_ops(ah);
420b3950e6aSLuis R. Rodriguez 
421b3950e6aSLuis R. Rodriguez 	ar9002_hw_attach_calib_ops(ah);
422b3950e6aSLuis R. Rodriguez 	ar9002_hw_attach_mac_ops(ah);
423c1b976d2SFelix Fietkau 	return 0;
424b3950e6aSLuis R. Rodriguez }
425c2ba3342SRajkumar Manoharan 
ar9002_hw_load_ani_reg(struct ath_hw * ah,struct ath9k_channel * chan)426c2ba3342SRajkumar Manoharan void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
427c2ba3342SRajkumar Manoharan {
428c2ba3342SRajkumar Manoharan 	u32 modesIndex;
429c2ba3342SRajkumar Manoharan 	int i;
430c2ba3342SRajkumar Manoharan 
4318896934cSFelix Fietkau 	if (IS_CHAN_5GHZ(chan))
4328896934cSFelix Fietkau 		modesIndex = IS_CHAN_HT40(chan) ? 2 : 1;
4338896934cSFelix Fietkau 	else
4348896934cSFelix Fietkau 		modesIndex = IS_CHAN_HT40(chan) ? 3 : 4;
435c2ba3342SRajkumar Manoharan 
436c2ba3342SRajkumar Manoharan 	ENABLE_REGWRITE_BUFFER(ah);
437c2ba3342SRajkumar Manoharan 
438c2ba3342SRajkumar Manoharan 	for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
439c2ba3342SRajkumar Manoharan 		u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
440c2ba3342SRajkumar Manoharan 		u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
441c2ba3342SRajkumar Manoharan 		u32 val_orig;
442c2ba3342SRajkumar Manoharan 
443c2ba3342SRajkumar Manoharan 		if (reg == AR_PHY_CCK_DETECT) {
444c2ba3342SRajkumar Manoharan 			val_orig = REG_READ(ah, reg);
445c2ba3342SRajkumar Manoharan 			val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
446c2ba3342SRajkumar Manoharan 			val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
447c2ba3342SRajkumar Manoharan 
448c2ba3342SRajkumar Manoharan 			REG_WRITE(ah, reg, val|val_orig);
449c2ba3342SRajkumar Manoharan 		} else
450c2ba3342SRajkumar Manoharan 			REG_WRITE(ah, reg, val);
451c2ba3342SRajkumar Manoharan 	}
452c2ba3342SRajkumar Manoharan 
453c2ba3342SRajkumar Manoharan 	REGWRITE_BUFFER_FLUSH(ah);
454c2ba3342SRajkumar Manoharan }
455