Merge branches 'softirq-for-linus', 'x86-debug-for-linus', 'x86-numa-for-linus',...
[cascardo/linux.git] / drivers / net / wireless / ath / ath9k / ar9003_hw.c
1 /*
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"
18 #include "ar9003_mac.h"
19 #include "ar9003_2p0_initvals.h"
20 #include "ar9003_2p2_initvals.h"
21
22 /* General hardware code for the AR9003 hadware family */
23
24 static bool ar9003_hw_macversion_supported(u32 macversion)
25 {
26         switch (macversion) {
27         case AR_SREV_VERSION_9300:
28                 return true;
29         default:
30                 break;
31         }
32         return false;
33 }
34
35 /* AR9003 2.0 */
36 static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah)
37 {
38         /* mac */
39         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
40         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
41                        ar9300_2p0_mac_core,
42                        ARRAY_SIZE(ar9300_2p0_mac_core), 2);
43         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
44                        ar9300_2p0_mac_postamble,
45                        ARRAY_SIZE(ar9300_2p0_mac_postamble), 5);
46
47         /* bb */
48         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
49         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
50                        ar9300_2p0_baseband_core,
51                        ARRAY_SIZE(ar9300_2p0_baseband_core), 2);
52         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
53                        ar9300_2p0_baseband_postamble,
54                        ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5);
55
56         /* radio */
57         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
58         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
59                        ar9300_2p0_radio_core,
60                        ARRAY_SIZE(ar9300_2p0_radio_core), 2);
61         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
62                        ar9300_2p0_radio_postamble,
63                        ARRAY_SIZE(ar9300_2p0_radio_postamble), 5);
64
65         /* soc */
66         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
67                        ar9300_2p0_soc_preamble,
68                        ARRAY_SIZE(ar9300_2p0_soc_preamble), 2);
69         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
70         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
71                        ar9300_2p0_soc_postamble,
72                        ARRAY_SIZE(ar9300_2p0_soc_postamble), 5);
73
74         /* rx/tx gain */
75         INIT_INI_ARRAY(&ah->iniModesRxGain,
76                        ar9300Common_rx_gain_table_2p0,
77                        ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2);
78         INIT_INI_ARRAY(&ah->iniModesTxGain,
79                        ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
80                        ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
81                        5);
82
83         /* Load PCIE SERDES settings from INI */
84
85         /* Awake Setting */
86
87         INIT_INI_ARRAY(&ah->iniPcieSerdes,
88                        ar9300PciePhy_pll_on_clkreq_disable_L1_2p0,
89                        ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0),
90                        2);
91
92         /* Sleep Setting */
93
94         INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
95                        ar9300PciePhy_clkreq_enable_L1_2p0,
96                        ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0),
97                        2);
98
99         /* Fast clock modal settings */
100         INIT_INI_ARRAY(&ah->iniModesAdditional,
101                        ar9300Modes_fast_clock_2p0,
102                        ARRAY_SIZE(ar9300Modes_fast_clock_2p0),
103                        3);
104 }
105
106 /* AR9003 2.2 */
107 static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah)
108 {
109         /* mac */
110         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
111         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
112                        ar9300_2p2_mac_core,
113                        ARRAY_SIZE(ar9300_2p2_mac_core), 2);
114         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
115                        ar9300_2p2_mac_postamble,
116                        ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
117
118         /* bb */
119         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
120         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
121                        ar9300_2p2_baseband_core,
122                        ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
123         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
124                        ar9300_2p2_baseband_postamble,
125                        ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
126
127         /* radio */
128         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
129         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
130                        ar9300_2p2_radio_core,
131                        ARRAY_SIZE(ar9300_2p2_radio_core), 2);
132         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
133                        ar9300_2p2_radio_postamble,
134                        ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
135
136         /* soc */
137         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
138                        ar9300_2p2_soc_preamble,
139                        ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
140         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
141         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
142                        ar9300_2p2_soc_postamble,
143                        ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
144
145         /* rx/tx gain */
146         INIT_INI_ARRAY(&ah->iniModesRxGain,
147                        ar9300Common_rx_gain_table_2p2,
148                        ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
149         INIT_INI_ARRAY(&ah->iniModesTxGain,
150                        ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
151                        ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
152                        5);
153
154         /* Load PCIE SERDES settings from INI */
155
156         /* Awake Setting */
157
158         INIT_INI_ARRAY(&ah->iniPcieSerdes,
159                        ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
160                        ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
161                        2);
162
163         /* Sleep Setting */
164
165         INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
166                        ar9300PciePhy_clkreq_enable_L1_2p2,
167                        ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2),
168                        2);
169
170         /* Fast clock modal settings */
171         INIT_INI_ARRAY(&ah->iniModesAdditional,
172                        ar9300Modes_fast_clock_2p2,
173                        ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
174                        3);
175 }
176
177 /*
178  * The AR9003 family uses a new INI format (pre, core, post
179  * arrays per subsystem).
180  */
181 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
182 {
183         if (AR_SREV_9300_20(ah))
184                 ar9003_2p0_hw_init_mode_regs(ah);
185         else
186                 ar9003_2p2_hw_init_mode_regs(ah);
187 }
188
189 static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
190 {
191         switch (ar9003_hw_get_tx_gain_idx(ah)) {
192         case 0:
193         default:
194                 if (AR_SREV_9300_20(ah))
195                         INIT_INI_ARRAY(&ah->iniModesTxGain,
196                                        ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
197                                        ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
198                                        5);
199                 else
200                         INIT_INI_ARRAY(&ah->iniModesTxGain,
201                                        ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
202                                        ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
203                                        5);
204                 break;
205         case 1:
206                 if (AR_SREV_9300_20(ah))
207                         INIT_INI_ARRAY(&ah->iniModesTxGain,
208                                        ar9300Modes_high_ob_db_tx_gain_table_2p0,
209                                        ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0),
210                                        5);
211                 else
212                         INIT_INI_ARRAY(&ah->iniModesTxGain,
213                                        ar9300Modes_high_ob_db_tx_gain_table_2p2,
214                                        ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
215                                        5);
216                 break;
217         case 2:
218                 if (AR_SREV_9300_20(ah))
219                         INIT_INI_ARRAY(&ah->iniModesTxGain,
220                                        ar9300Modes_low_ob_db_tx_gain_table_2p0,
221                                        ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0),
222                                        5);
223                 else
224                         INIT_INI_ARRAY(&ah->iniModesTxGain,
225                                        ar9300Modes_low_ob_db_tx_gain_table_2p2,
226                                        ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
227                                        5);
228                 break;
229         }
230 }
231
232 static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
233 {
234         switch (ar9003_hw_get_rx_gain_idx(ah)) {
235         case 0:
236         default:
237                 if (AR_SREV_9300_20(ah))
238                         INIT_INI_ARRAY(&ah->iniModesRxGain,
239                                        ar9300Common_rx_gain_table_2p0,
240                                        ARRAY_SIZE(ar9300Common_rx_gain_table_2p0),
241                                        2);
242                 else
243                         INIT_INI_ARRAY(&ah->iniModesRxGain,
244                                        ar9300Common_rx_gain_table_2p2,
245                                        ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
246                                        2);
247                 break;
248         case 1:
249                 if (AR_SREV_9300_20(ah))
250                         INIT_INI_ARRAY(&ah->iniModesRxGain,
251                                        ar9300Common_wo_xlna_rx_gain_table_2p0,
252                                        ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0),
253                                        2);
254                 else
255                         INIT_INI_ARRAY(&ah->iniModesRxGain,
256                                        ar9300Common_wo_xlna_rx_gain_table_2p2,
257                                        ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
258                                        2);
259                 break;
260         }
261 }
262
263 /* set gain table pointers according to values read from the eeprom */
264 static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
265 {
266         ar9003_tx_gain_table_apply(ah);
267         ar9003_rx_gain_table_apply(ah);
268 }
269
270 /*
271  * Helper for ASPM support.
272  *
273  * Disable PLL when in L0s as well as receiver clock when in L1.
274  * This power saving option must be enabled through the SerDes.
275  *
276  * Programming the SerDes must go through the same 288 bit serial shift
277  * register as the other analog registers.  Hence the 9 writes.
278  */
279 static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
280                                          int restore,
281                                          int power_off)
282 {
283         if (ah->is_pciexpress != true)
284                 return;
285
286         /* Do not touch SerDes registers */
287         if (ah->config.pcie_powersave_enable == 2)
288                 return;
289
290         /* Nothing to do on restore for 11N */
291         if (!restore) {
292                 /* set bit 19 to allow forcing of pcie core into L1 state */
293                 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
294
295                 /* Several PCIe massages to ensure proper behaviour */
296                 if (ah->config.pcie_waen)
297                         REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
298                 else
299                         REG_WRITE(ah, AR_WA, ah->WARegVal);
300         }
301
302         /*
303          * Configire PCIE after Ini init. SERDES values now come from ini file
304          * This enables PCIe low power mode.
305          */
306         if (ah->config.pcieSerDesWrite) {
307                 unsigned int i;
308                 struct ar5416IniArray *array;
309
310                 array = power_off ? &ah->iniPcieSerdes :
311                                     &ah->iniPcieSerdesLowPower;
312
313                 for (i = 0; i < array->ia_rows; i++) {
314                         REG_WRITE(ah,
315                                   INI_RA(array, i, 0),
316                                   INI_RA(array, i, 1));
317                 }
318         }
319 }
320
321 /* Sets up the AR9003 hardware familiy callbacks */
322 void ar9003_hw_attach_ops(struct ath_hw *ah)
323 {
324         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
325         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
326
327         priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
328         priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
329         priv_ops->macversion_supported = ar9003_hw_macversion_supported;
330
331         ops->config_pci_powersave = ar9003_hw_configpcipowersave;
332
333         ar9003_hw_attach_phy_ops(ah);
334         ar9003_hw_attach_calib_ops(ah);
335         ar9003_hw_attach_mac_ops(ah);
336
337         ath9k_hw_attach_ani_ops_new(ah);
338 }