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