blob: f01c2891f7c359f11d9b667a0c7dfa739ed37731 [file] [log] [blame]
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -04001/*
2 * Copyright (c) 2008-2010 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 "hw.h"
Luis R. Rodriguezb622a722010-04-15 17:39:28 -040018#include "ar9003_mac.h"
Luis R. Rodriguez72846352010-05-12 21:15:05 -040019#include "ar9003_2p2_initvals.h"
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080020#include "ar9485_initvals.h"
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040021
22/* General hardware code for the AR9003 hadware family */
23
24static bool ar9003_hw_macversion_supported(u32 macversion)
25{
26 switch (macversion) {
27 case AR_SREV_VERSION_9300:
Vasanthakumar Thiagarajan3050c912010-12-06 04:27:36 -080028 case AR_SREV_VERSION_9485:
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -040029 return true;
30 default:
31 break;
32 }
33 return false;
34}
35
Luis R. Rodriguez886b42b2010-10-14 11:44:27 -070036/*
37 * The AR9003 family uses a new INI format (pre, core, post
38 * arrays per subsystem). This provides support for the
39 * AR9003 2.2 chipsets.
40 */
41static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
Luis R. Rodriguez72846352010-05-12 21:15:05 -040042{
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080043 if (AR_SREV_9485(ah)) {
44 /* mac */
45 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
46 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
47 ar9485_1_0_mac_core,
48 ARRAY_SIZE(ar9485_1_0_mac_core), 2);
49 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
50 ar9485_1_0_mac_postamble,
51 ARRAY_SIZE(ar9485_1_0_mac_postamble), 5);
Luis R. Rodriguez72846352010-05-12 21:15:05 -040052
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080053 /* bb */
54 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_0,
55 ARRAY_SIZE(ar9485_1_0), 2);
56 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
57 ar9485_1_0_baseband_core,
58 ARRAY_SIZE(ar9485_1_0_baseband_core), 2);
59 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
60 ar9485_1_0_baseband_postamble,
61 ARRAY_SIZE(ar9485_1_0_baseband_postamble), 5);
Luis R. Rodriguez72846352010-05-12 21:15:05 -040062
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080063 /* radio */
64 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
65 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
66 ar9485_1_0_radio_core,
67 ARRAY_SIZE(ar9485_1_0_radio_core), 2);
68 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
69 ar9485_1_0_radio_postamble,
70 ARRAY_SIZE(ar9485_1_0_radio_postamble), 2);
Luis R. Rodriguez72846352010-05-12 21:15:05 -040071
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080072 /* soc */
73 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
74 ar9485_1_0_soc_preamble,
75 ARRAY_SIZE(ar9485_1_0_soc_preamble), 2);
76 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
77 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
Luis R. Rodriguez72846352010-05-12 21:15:05 -040078
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080079 /* rx/tx gain */
80 INIT_INI_ARRAY(&ah->iniModesRxGain,
81 ar9485Common_rx_gain_1_0,
82 ARRAY_SIZE(ar9485Common_rx_gain_1_0), 2);
83 INIT_INI_ARRAY(&ah->iniModesTxGain,
84 ar9485Modes_lowest_ob_db_tx_gain_1_0,
85 ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
86 5);
Luis R. Rodriguez72846352010-05-12 21:15:05 -040087
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080088 /* Load PCIE SERDES settings from INI */
Luis R. Rodriguez72846352010-05-12 21:15:05 -040089
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080090 /* Awake Setting */
Luis R. Rodriguez72846352010-05-12 21:15:05 -040091
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080092 INIT_INI_ARRAY(&ah->iniPcieSerdes,
93 ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1,
94 ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1),
95 2);
Luis R. Rodriguez72846352010-05-12 21:15:05 -040096
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080097 /* Sleep Setting */
Luis R. Rodriguez72846352010-05-12 21:15:05 -040098
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -080099 INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
100 ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1,
101 ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1),
102 2);
103 } else {
104 /* mac */
105 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
106 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
107 ar9300_2p2_mac_core,
108 ARRAY_SIZE(ar9300_2p2_mac_core), 2);
109 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
110 ar9300_2p2_mac_postamble,
111 ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
Luis R. Rodriguez72846352010-05-12 21:15:05 -0400112
Vasanthakumar Thiagarajanc88457e2010-12-06 04:27:37 -0800113 /* bb */
114 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
115 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
116 ar9300_2p2_baseband_core,
117 ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
118 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
119 ar9300_2p2_baseband_postamble,
120 ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
121
122 /* radio */
123 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
124 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
125 ar9300_2p2_radio_core,
126 ARRAY_SIZE(ar9300_2p2_radio_core), 2);
127 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
128 ar9300_2p2_radio_postamble,
129 ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
130
131 /* soc */
132 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
133 ar9300_2p2_soc_preamble,
134 ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
135 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
136 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
137 ar9300_2p2_soc_postamble,
138 ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
139
140 /* rx/tx gain */
141 INIT_INI_ARRAY(&ah->iniModesRxGain,
142 ar9300Common_rx_gain_table_2p2,
143 ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
144 INIT_INI_ARRAY(&ah->iniModesTxGain,
145 ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
146 ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
147 5);
148
149 /* Load PCIE SERDES settings from INI */
150
151 /* Awake Setting */
152
153 INIT_INI_ARRAY(&ah->iniPcieSerdes,
154 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
155 ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
156 2);
157
158 /* Sleep Setting */
159
160 INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
161 ar9300PciePhy_clkreq_enable_L1_2p2,
162 ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2),
163 2);
164
165 /* Fast clock modal settings */
166 INIT_INI_ARRAY(&ah->iniModesAdditional,
167 ar9300Modes_fast_clock_2p2,
168 ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
169 3);
170 }
Luis R. Rodriguez72846352010-05-12 21:15:05 -0400171}
172
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -0400173static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
174{
175 switch (ar9003_hw_get_tx_gain_idx(ah)) {
176 case 0:
177 default:
Luis R. Rodriguez886b42b2010-10-14 11:44:27 -0700178 INIT_INI_ARRAY(&ah->iniModesTxGain,
179 ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
180 ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
181 5);
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -0400182 break;
183 case 1:
Luis R. Rodriguez886b42b2010-10-14 11:44:27 -0700184 INIT_INI_ARRAY(&ah->iniModesTxGain,
185 ar9300Modes_high_ob_db_tx_gain_table_2p2,
186 ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
187 5);
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -0400188 break;
189 case 2:
Luis R. Rodriguez886b42b2010-10-14 11:44:27 -0700190 INIT_INI_ARRAY(&ah->iniModesTxGain,
191 ar9300Modes_low_ob_db_tx_gain_table_2p2,
192 ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
193 5);
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -0400194 break;
195 }
196}
197
198static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
199{
200 switch (ar9003_hw_get_rx_gain_idx(ah)) {
201 case 0:
202 default:
Luis R. Rodriguez886b42b2010-10-14 11:44:27 -0700203 INIT_INI_ARRAY(&ah->iniModesRxGain,
204 ar9300Common_rx_gain_table_2p2,
205 ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
206 2);
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -0400207 break;
208 case 1:
Luis R. Rodriguez886b42b2010-10-14 11:44:27 -0700209 INIT_INI_ARRAY(&ah->iniModesRxGain,
210 ar9300Common_wo_xlna_rx_gain_table_2p2,
211 ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
212 2);
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -0400213 break;
214 }
215}
216
217/* set gain table pointers according to values read from the eeprom */
218static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
219{
220 ar9003_tx_gain_table_apply(ah);
221 ar9003_rx_gain_table_apply(ah);
222}
223
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400224/*
225 * Helper for ASPM support.
226 *
227 * Disable PLL when in L0s as well as receiver clock when in L1.
228 * This power saving option must be enabled through the SerDes.
229 *
230 * Programming the SerDes must go through the same 288 bit serial shift
231 * register as the other analog registers. Hence the 9 writes.
232 */
233static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
234 int restore,
235 int power_off)
236{
237 if (ah->is_pciexpress != true)
238 return;
239
240 /* Do not touch SerDes registers */
241 if (ah->config.pcie_powersave_enable == 2)
242 return;
243
244 /* Nothing to do on restore for 11N */
245 if (!restore) {
246 /* set bit 19 to allow forcing of pcie core into L1 state */
247 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
248
249 /* Several PCIe massages to ensure proper behaviour */
250 if (ah->config.pcie_waen)
251 REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
Luis R. Rodriguez9a658d22010-06-21 18:38:47 -0400252 else
253 REG_WRITE(ah, AR_WA, ah->WARegVal);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400254 }
Luis R. Rodriguez653fe372010-06-21 18:38:48 -0400255
256 /*
257 * Configire PCIE after Ini init. SERDES values now come from ini file
258 * This enables PCIe low power mode.
259 */
Luis R. Rodriguez6a0ec302010-06-21 18:38:49 -0400260 if (ah->config.pcieSerDesWrite) {
Luis R. Rodriguez653fe372010-06-21 18:38:48 -0400261 unsigned int i;
Luis R. Rodriguezd5c4d192010-06-21 18:38:50 -0400262 struct ar5416IniArray *array;
Luis R. Rodriguez653fe372010-06-21 18:38:48 -0400263
Luis R. Rodriguezd5c4d192010-06-21 18:38:50 -0400264 array = power_off ? &ah->iniPcieSerdes :
265 &ah->iniPcieSerdesLowPower;
266
267 for (i = 0; i < array->ia_rows; i++) {
Luis R. Rodriguez653fe372010-06-21 18:38:48 -0400268 REG_WRITE(ah,
Luis R. Rodriguezd5c4d192010-06-21 18:38:50 -0400269 INI_RA(array, i, 0),
270 INI_RA(array, i, 1));
Luis R. Rodriguez653fe372010-06-21 18:38:48 -0400271 }
272 }
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400273}
274
275/* Sets up the AR9003 hardware familiy callbacks */
276void ar9003_hw_attach_ops(struct ath_hw *ah)
277{
278 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
279 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
280
281 priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
Luis R. Rodriguezc14a85d2010-04-15 17:39:21 -0400282 priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400283 priv_ops->macversion_supported = ar9003_hw_macversion_supported;
284
285 ops->config_pci_powersave = ar9003_hw_configpcipowersave;
286
287 ar9003_hw_attach_phy_ops(ah);
288 ar9003_hw_attach_calib_ops(ah);
289 ar9003_hw_attach_mac_ops(ah);
Luis R. Rodriguezb3950e62010-04-15 17:39:03 -0400290}