blob: 149aba3c7298c3af99f8f4d54b37eaf10da606ef [file] [log] [blame]
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -04001/*
Sujith Manoharan5b681382011-05-17 13:36:18 +05302 * Copyright (c) 2008-2011 Atheros Communications Inc.
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -04003 *
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
Paul Gortmaker6eb07ca2011-09-15 19:46:05 -040017#include <linux/moduleparam.h>
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040018#include "hw.h"
19#include "ar5008_initvals.h"
20#include "ar9001_initvals.h"
21#include "ar9002_initvals.h"
Sujithe9141f72010-06-01 15:14:10 +053022#include "ar9002_phy.h"
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040023
24/* General hardware code for the A5008/AR9001/AR9002 hadware families */
25
Felix Fietkau6aaacd82013-01-13 19:54:58 +010026static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040027{
28 if (AR_SREV_9271(ah)) {
Felix Fietkaua3645172012-07-15 19:53:33 +020029 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);
Felix Fietkau6aaacd82013-01-13 19:54:58 +010032 return 0;
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040033 }
34
Felix Fietkau787e0532013-12-14 18:03:40 +010035 INIT_INI_ARRAY(&ah->iniPcieSerdes,
36 ar9280PciePhy_clkreq_always_on_L1_9280);
Felix Fietkau14fec8d2012-02-15 21:53:16 +010037
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040038 if (AR_SREV_9287_11_OR_LATER(ah)) {
Felix Fietkaua3645172012-07-15 19:53:33 +020039 INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
40 INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040041 } else if (AR_SREV_9285_12_OR_LATER(ah)) {
Felix Fietkaua3645172012-07-15 19:53:33 +020042 INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2);
43 INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040044 } else if (AR_SREV_9280_20_OR_LATER(ah)) {
Felix Fietkaua3645172012-07-15 19:53:33 +020045 INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2);
46 INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040047
Felix Fietkauc7d36f92012-03-14 16:40:31 +010048 INIT_INI_ARRAY(&ah->iniModesFastClock,
Felix Fietkaua3645172012-07-15 19:53:33 +020049 ar9280Modes_fast_clock_9280_2);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040050 } else if (AR_SREV_9160_10_OR_LATER(ah)) {
Felix Fietkaua3645172012-07-15 19:53:33 +020051 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160);
52 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040053 if (AR_SREV_9160_11(ah)) {
54 INIT_INI_ARRAY(&ah->iniAddac,
Felix Fietkaua3645172012-07-15 19:53:33 +020055 ar5416Addac_9160_1_1);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040056 } else {
Felix Fietkaua3645172012-07-15 19:53:33 +020057 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040058 }
59 } else if (AR_SREV_9100_OR_LATER(ah)) {
Felix Fietkaua3645172012-07-15 19:53:33 +020060 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
61 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
Felix Fietkaua3645172012-07-15 19:53:33 +020062 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040063 } else {
Felix Fietkaua3645172012-07-15 19:53:33 +020064 INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
65 INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
Felix Fietkaua3645172012-07-15 19:53:33 +020066 INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
Felix Fietkau14fec8d2012-02-15 21:53:16 +010067 }
68
69 if (!AR_SREV_9280_20_OR_LATER(ah)) {
70 /* Common for AR5416, AR913x, AR9160 */
Felix Fietkaua3645172012-07-15 19:53:33 +020071 INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
Felix Fietkau14fec8d2012-02-15 21:53:16 +010072
Felix Fietkau14fec8d2012-02-15 21:53:16 +010073 /* Common for AR913x, AR9160 */
74 if (!AR_SREV_5416(ah))
Felix Fietkau37c62fe2013-04-08 00:04:07 +020075 INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100);
76 else
77 INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040078 }
Felix Fietkau9bbb8162012-02-15 19:31:20 +010079
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
Felix Fietkauc1b976d2012-12-12 13:14:23 +010086 data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
Felix Fietkau9bbb8162012-02-15 19:31:20 +010087 if (!data)
Felix Fietkau6aaacd82013-01-13 19:54:58 +010088 return -ENOMEM;
Felix Fietkau9bbb8162012-02-15 19:31:20 +010089
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 }
Luis R. Rodriguezd8f492b2010-04-15 17:39:04 -040098 if (AR_SREV_9287_11_OR_LATER(ah)) {
99 INIT_INI_ARRAY(&ah->iniCckfirNormal,
Felix Fietkaua3645172012-07-15 19:53:33 +0200100 ar9287Common_normal_cck_fir_coeff_9287_1_1);
Luis R. Rodriguezd8f492b2010-04-15 17:39:04 -0400101 INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
Felix Fietkaua3645172012-07-15 19:53:33 +0200102 ar9287Common_japan_2484_cck_fir_coeff_9287_1_1);
Luis R. Rodriguezd8f492b2010-04-15 17:39:04 -0400103 }
Felix Fietkau6aaacd82013-01-13 19:54:58 +0100104 return 0;
Luis R. Rodriguezd8f492b2010-04-15 17:39:04 -0400105}
106
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400107static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
108{
109 u32 rxgain_type;
110
111 if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
112 AR5416_EEP_MINOR_VER_17) {
113 rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
114
115 if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
116 INIT_INI_ARRAY(&ah->iniModesRxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200117 ar9280Modes_backoff_13db_rxgain_9280_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400118 else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
119 INIT_INI_ARRAY(&ah->iniModesRxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200120 ar9280Modes_backoff_23db_rxgain_9280_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400121 else
122 INIT_INI_ARRAY(&ah->iniModesRxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200123 ar9280Modes_original_rxgain_9280_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400124 } else {
125 INIT_INI_ARRAY(&ah->iniModesRxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200126 ar9280Modes_original_rxgain_9280_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400127 }
128}
129
Felix Fietkauaa0e5782012-03-14 16:40:32 +0100130static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400131{
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400132 if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
133 AR5416_EEP_MINOR_VER_19) {
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400134 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
135 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200136 ar9280Modes_high_power_tx_gain_9280_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400137 else
138 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200139 ar9280Modes_original_tx_gain_9280_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400140 } else {
141 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200142 ar9280Modes_original_tx_gain_9280_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400143 }
144}
145
Felix Fietkauaa0e5782012-03-14 16:40:32 +0100146static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
147{
148 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
149 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200150 ar9271Modes_high_power_tx_gain_9271);
Felix Fietkauaa0e5782012-03-14 16:40:32 +0100151 else
152 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200153 ar9271Modes_normal_power_tx_gain_9271);
Felix Fietkauaa0e5782012-03-14 16:40:32 +0100154}
155
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400156static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
157{
Felix Fietkauaa0e5782012-03-14 16:40:32 +0100158 u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
159
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400160 if (AR_SREV_9287_11_OR_LATER(ah))
161 INIT_INI_ARRAY(&ah->iniModesRxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200162 ar9287Modes_rx_gain_9287_1_1);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400163 else if (AR_SREV_9280_20(ah))
164 ar9280_20_hw_init_rxgain_ini(ah);
165
Felix Fietkauaa0e5782012-03-14 16:40:32 +0100166 if (AR_SREV_9271(ah)) {
167 ar9271_hw_init_txgain_ini(ah, txgain_type);
168 } else if (AR_SREV_9287_11_OR_LATER(ah)) {
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400169 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200170 ar9287Modes_tx_gain_9287_1_1);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400171 } else if (AR_SREV_9280_20(ah)) {
Felix Fietkauaa0e5782012-03-14 16:40:32 +0100172 ar9280_20_hw_init_txgain_ini(ah, txgain_type);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400173 } else if (AR_SREV_9285_12_OR_LATER(ah)) {
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400174 /* txgain table */
175 if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
176 if (AR_SREV_9285E_20(ah)) {
177 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200178 ar9285Modes_XE2_0_high_power);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400179 } else {
180 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200181 ar9285Modes_high_power_tx_gain_9285_1_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400182 }
183 } else {
184 if (AR_SREV_9285E_20(ah)) {
185 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200186 ar9285Modes_XE2_0_normal_power);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400187 } else {
188 INIT_INI_ARRAY(&ah->iniModesTxGain,
Felix Fietkaua3645172012-07-15 19:53:33 +0200189 ar9285Modes_original_tx_gain_9285_1_2);
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400190 }
191 }
192 }
193}
194
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400195/*
196 * Helper for ASPM support.
197 *
198 * Disable PLL when in L0s as well as receiver clock when in L1.
199 * This power saving option must be enabled through the SerDes.
200 *
201 * Programming the SerDes must go through the same 288 bit serial shift
202 * register as the other analog registers. Hence the 9 writes.
203 */
204static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
Stanislaw Gruszka84c87dc2011-08-05 13:10:32 +0200205 bool power_off)
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400206{
207 u8 i;
208 u32 val;
209
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400210 /* Nothing to do on restore for 11N */
Stanislaw Gruszka84c87dc2011-08-05 13:10:32 +0200211 if (!power_off /* !restore */) {
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400212 if (AR_SREV_9280_20_OR_LATER(ah)) {
213 /*
214 * AR9280 2.0 or later chips use SerDes values from the
215 * initvals.h initialized depending on chipset during
216 * __ath9k_hw_init()
217 */
218 for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
219 REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
220 INI_RA(&ah->iniPcieSerdes, i, 1));
221 }
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400222 } else {
Sujithd5e347b2010-04-23 10:28:11 +0530223 ENABLE_REGWRITE_BUFFER(ah);
224
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400225 REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
226 REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
227
228 /* RX shut off when elecidle is asserted */
229 REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
230 REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
231 REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
232
233 /*
234 * Ignore ah->ah_config.pcie_clock_req setting for
235 * pre-AR9280 11n
236 */
237 REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
238
239 REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
240 REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
241 REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
242
243 /* Load the new settings */
244 REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
Sujithd5e347b2010-04-23 10:28:11 +0530245
246 REGWRITE_BUFFER_FLUSH(ah);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400247 }
248
249 udelay(1000);
Sujith15ae7332010-06-01 15:14:09 +0530250 }
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400251
Sujith15ae7332010-06-01 15:14:09 +0530252 if (power_off) {
253 /* clear bit 19 to disable L1 */
254 REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400255
Sujith15ae7332010-06-01 15:14:09 +0530256 val = REG_READ(ah, AR_WA);
257
258 /*
259 * Set PCIe workaround bits
260 * In AR9280 and AR9285, bit 14 in WA register (disable L1)
261 * should only be set when device enters D3 and be
262 * cleared when device comes back to D0.
263 */
264 if (ah->config.pcie_waen) {
265 if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
266 val |= AR_WA_D3_L1_DISABLE;
267 } else {
Sujith Manoharand1ae25a2013-08-25 16:30:40 +0530268 if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
269 if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
270 val |= AR_WA_D3_L1_DISABLE;
271 } else if (AR_SREV_9280(ah)) {
272 if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
273 val |= AR_WA_D3_L1_DISABLE;
Sujith15ae7332010-06-01 15:14:09 +0530274 }
275 }
276
277 if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
278 /*
279 * Disable bit 6 and 7 before entering D3 to
280 * prevent system hang.
281 */
282 val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
283 }
284
Vasanthakumar Thiagarajanf119da32010-11-04 17:41:25 -0700285 if (AR_SREV_9280(ah))
286 val |= AR_WA_BIT22;
287
Sujith15ae7332010-06-01 15:14:09 +0530288 if (AR_SREV_9285E_20(ah))
289 val |= AR_WA_BIT23;
290
291 REG_WRITE(ah, AR_WA, val);
292 } else {
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400293 if (ah->config.pcie_waen) {
294 val = ah->config.pcie_waen;
Sujith Manoharand1ae25a2013-08-25 16:30:40 +0530295 val &= (~AR_WA_D3_L1_DISABLE);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400296 } else {
Sujith Manoharand1ae25a2013-08-25 16:30:40 +0530297 if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) {
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400298 val = AR9285_WA_DEFAULT;
Sujith Manoharand1ae25a2013-08-25 16:30:40 +0530299 val &= (~AR_WA_D3_L1_DISABLE);
300 } else if (AR_SREV_9280(ah)) {
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400301 /*
Sujith15ae7332010-06-01 15:14:09 +0530302 * For AR9280 chips, bit 22 of 0x4004
303 * needs to be set.
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400304 */
305 val = AR9280_WA_DEFAULT;
Sujith Manoharand1ae25a2013-08-25 16:30:40 +0530306 val &= (~AR_WA_D3_L1_DISABLE);
Sujith15ae7332010-06-01 15:14:09 +0530307 } else {
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400308 val = AR_WA_DEFAULT;
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400309 }
310 }
Sujith15ae7332010-06-01 15:14:09 +0530311
312 /* WAR for ASPM system hang */
Rajkumar Manoharan5b64aa72011-01-27 18:39:37 +0530313 if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
Sujith15ae7332010-06-01 15:14:09 +0530314 val |= (AR_WA_BIT6 | AR_WA_BIT7);
Sujith15ae7332010-06-01 15:14:09 +0530315
316 if (AR_SREV_9285E_20(ah))
317 val |= AR_WA_BIT23;
318
319 REG_WRITE(ah, AR_WA, val);
320
321 /* set bit 19 to allow forcing of pcie core into L1 state */
322 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400323 }
324}
325
Luis R. Rodriguezebd5a142010-04-15 17:39:18 -0400326static int ar9002_hw_get_radiorev(struct ath_hw *ah)
327{
328 u32 val;
329 int i;
330
Sujith7d0d0df2010-04-16 11:53:57 +0530331 ENABLE_REGWRITE_BUFFER(ah);
Luis R. Rodriguezebd5a142010-04-15 17:39:18 -0400332
Sujith7d0d0df2010-04-16 11:53:57 +0530333 REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
Luis R. Rodriguezebd5a142010-04-15 17:39:18 -0400334 for (i = 0; i < 8; i++)
335 REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
Sujith7d0d0df2010-04-16 11:53:57 +0530336
337 REGWRITE_BUFFER_FLUSH(ah);
Sujith7d0d0df2010-04-16 11:53:57 +0530338
Luis R. Rodriguezebd5a142010-04-15 17:39:18 -0400339 val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
340 val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
341
342 return ath9k_hw_reverse_bits(val, 8);
343}
344
345int ar9002_hw_rf_claim(struct ath_hw *ah)
346{
347 u32 val;
348
349 REG_WRITE(ah, AR_PHY(0), 0x00000007);
350
351 val = ar9002_hw_get_radiorev(ah);
352 switch (val & AR_RADIO_SREV_MAJOR) {
353 case 0:
354 val = AR_RAD5133_SREV_MAJOR;
355 break;
356 case AR_RAD5133_SREV_MAJOR:
357 case AR_RAD5122_SREV_MAJOR:
358 case AR_RAD2133_SREV_MAJOR:
359 case AR_RAD2122_SREV_MAJOR:
360 break;
361 default:
Joe Perches38002762010-12-02 19:12:36 -0800362 ath_err(ath9k_hw_common(ah),
363 "Radio Chip Rev 0x%02X not supported\n",
364 val & AR_RADIO_SREV_MAJOR);
Luis R. Rodriguezebd5a142010-04-15 17:39:18 -0400365 return -EOPNOTSUPP;
366 }
367
368 ah->hw_version.analog5GhzRev = val;
369
370 return 0;
371}
372
Sujithe9141f72010-06-01 15:14:10 +0530373void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
374{
375 if (AR_SREV_9287_13_OR_LATER(ah)) {
376 REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
377 AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
378 REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
379 REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
380 AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
381 REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
382 AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
383 }
384}
385
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400386/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
Felix Fietkauc1b976d2012-12-12 13:14:23 +0100387int ar9002_hw_attach_ops(struct ath_hw *ah)
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400388{
389 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
390 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
Felix Fietkauc1b976d2012-12-12 13:14:23 +0100391 int ret;
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400392
Felix Fietkau6aaacd82013-01-13 19:54:58 +0100393 ret = ar9002_hw_init_mode_regs(ah);
394 if (ret)
395 return ret;
396
Luis R. Rodriguez991312d2010-04-15 17:39:05 -0400397 priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400398
399 ops->config_pci_powersave = ar9002_hw_configpcipowersave;
400
Felix Fietkauc1b976d2012-12-12 13:14:23 +0100401 ret = ar5008_hw_attach_phy_ops(ah);
402 if (ret)
403 return ret;
404
Felix Fietkau7a370812010-09-22 12:34:52 +0200405 if (AR_SREV_9280_20_OR_LATER(ah))
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400406 ar9002_hw_attach_phy_ops(ah);
407
408 ar9002_hw_attach_calib_ops(ah);
409 ar9002_hw_attach_mac_ops(ah);
Felix Fietkauc1b976d2012-12-12 13:14:23 +0100410 return 0;
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400411}
Rajkumar Manoharanc2ba3342010-09-03 16:00:00 +0530412
413void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
414{
415 u32 modesIndex;
416 int i;
417
Felix Fietkau88969342013-10-11 23:30:53 +0200418 if (IS_CHAN_5GHZ(chan))
419 modesIndex = IS_CHAN_HT40(chan) ? 2 : 1;
420 else
421 modesIndex = IS_CHAN_HT40(chan) ? 3 : 4;
Rajkumar Manoharanc2ba3342010-09-03 16:00:00 +0530422
423 ENABLE_REGWRITE_BUFFER(ah);
424
425 for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) {
426 u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0);
427 u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex);
428 u32 val_orig;
429
430 if (reg == AR_PHY_CCK_DETECT) {
431 val_orig = REG_READ(ah, reg);
432 val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
433 val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK;
434
435 REG_WRITE(ah, reg, val|val_orig);
436 } else
437 REG_WRITE(ah, reg, val);
438 }
439
440 REGWRITE_BUFFER_FLUSH(ah);
Rajkumar Manoharanc2ba3342010-09-03 16:00:00 +0530441}