Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.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_2p2_initvals.h"
20 #include "ar9485_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         case AR_SREV_VERSION_9485:
29                 return true;
30         default:
31                 break;
32         }
33         return false;
34 }
35
36 /*
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  */
41 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
42 {
43         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);
52
53                 /* 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);
62
63                 /* 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);
71
72                 /* 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);
78
79                 /* 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);
87
88                 /* Load PCIE SERDES settings from INI */
89
90                 /* Awake Setting */
91
92                 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);
96
97                 /* Sleep Setting */
98
99                 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);
112
113                 /* 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         }
171 }
172
173 static 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:
178                 if (AR_SREV_9485(ah))
179                         INIT_INI_ARRAY(&ah->iniModesTxGain,
180                                        ar9485Modes_lowest_ob_db_tx_gain_1_0,
181                                        ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
182                                        5);
183                 else
184                         INIT_INI_ARRAY(&ah->iniModesTxGain,
185                                        ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
186                                        ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
187                                        5);
188                 break;
189         case 1:
190                 if (AR_SREV_9485(ah))
191                         INIT_INI_ARRAY(&ah->iniModesTxGain,
192                                        ar9485Modes_high_ob_db_tx_gain_1_0,
193                                        ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
194                                        5);
195                 else
196                         INIT_INI_ARRAY(&ah->iniModesTxGain,
197                                        ar9300Modes_high_ob_db_tx_gain_table_2p2,
198                                        ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
199                                        5);
200                 break;
201         case 2:
202                 if (AR_SREV_9485(ah))
203                         INIT_INI_ARRAY(&ah->iniModesTxGain,
204                                        ar9485Modes_low_ob_db_tx_gain_1_0,
205                                        ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
206                                        5);
207                 else
208                         INIT_INI_ARRAY(&ah->iniModesTxGain,
209                                        ar9300Modes_low_ob_db_tx_gain_table_2p2,
210                                        ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
211                                        5);
212                 break;
213         case 3:
214                 if (AR_SREV_9485(ah))
215                         INIT_INI_ARRAY(&ah->iniModesTxGain,
216                                        ar9485Modes_high_power_tx_gain_1_0,
217                                        ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0),
218                                        5);
219                 else
220                         INIT_INI_ARRAY(&ah->iniModesTxGain,
221                                        ar9300Modes_high_power_tx_gain_table_2p2,
222                                        ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
223                                        5);
224                 break;
225         }
226 }
227
228 static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
229 {
230         switch (ar9003_hw_get_rx_gain_idx(ah)) {
231         case 0:
232         default:
233                 if (AR_SREV_9485(ah))
234                         INIT_INI_ARRAY(&ah->iniModesRxGain,
235                                        ar9485Common_rx_gain_1_0,
236                                        ARRAY_SIZE(ar9485Common_rx_gain_1_0),
237                                        2);
238                 else
239                         INIT_INI_ARRAY(&ah->iniModesRxGain,
240                                        ar9300Common_rx_gain_table_2p2,
241                                        ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
242                                        2);
243                 break;
244         case 1:
245                 if (AR_SREV_9485(ah))
246                         INIT_INI_ARRAY(&ah->iniModesRxGain,
247                                        ar9485Common_wo_xlna_rx_gain_1_0,
248                                        ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0),
249                                        2);
250                 else
251                         INIT_INI_ARRAY(&ah->iniModesRxGain,
252                                        ar9300Common_wo_xlna_rx_gain_table_2p2,
253                                        ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
254                                        2);
255                 break;
256         }
257 }
258
259 /* set gain table pointers according to values read from the eeprom */
260 static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
261 {
262         ar9003_tx_gain_table_apply(ah);
263         ar9003_rx_gain_table_apply(ah);
264 }
265
266 /*
267  * Helper for ASPM support.
268  *
269  * Disable PLL when in L0s as well as receiver clock when in L1.
270  * This power saving option must be enabled through the SerDes.
271  *
272  * Programming the SerDes must go through the same 288 bit serial shift
273  * register as the other analog registers.  Hence the 9 writes.
274  */
275 static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
276                                          int restore,
277                                          int power_off)
278 {
279         if (ah->is_pciexpress != true)
280                 return;
281
282         /* Do not touch SerDes registers */
283         if (ah->config.pcie_powersave_enable == 2)
284                 return;
285
286         /* Nothing to do on restore for 11N */
287         if (!restore) {
288                 /* set bit 19 to allow forcing of pcie core into L1 state */
289                 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
290
291                 /* Several PCIe massages to ensure proper behaviour */
292                 if (ah->config.pcie_waen)
293                         REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
294                 else
295                         REG_WRITE(ah, AR_WA, ah->WARegVal);
296         }
297
298         /*
299          * Configire PCIE after Ini init. SERDES values now come from ini file
300          * This enables PCIe low power mode.
301          */
302         if (ah->config.pcieSerDesWrite) {
303                 unsigned int i;
304                 struct ar5416IniArray *array;
305
306                 array = power_off ? &ah->iniPcieSerdes :
307                                     &ah->iniPcieSerdesLowPower;
308
309                 for (i = 0; i < array->ia_rows; i++) {
310                         REG_WRITE(ah,
311                                   INI_RA(array, i, 0),
312                                   INI_RA(array, i, 1));
313                 }
314         }
315 }
316
317 /* Sets up the AR9003 hardware familiy callbacks */
318 void ar9003_hw_attach_ops(struct ath_hw *ah)
319 {
320         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
321         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
322
323         priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
324         priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
325         priv_ops->macversion_supported = ar9003_hw_macversion_supported;
326
327         ops->config_pci_powersave = ar9003_hw_configpcipowersave;
328
329         ar9003_hw_attach_phy_ops(ah);
330         ar9003_hw_attach_calib_ops(ah);
331         ar9003_hw_attach_mac_ops(ah);
332 }