mac80211: Clear PS related flag on disabling power save.
[linux-2.6.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_11(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_1_mac_core,
36                                 ARRAY_SIZE(ar9485_1_1_mac_core), 2);
37                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
38                                 ar9485_1_1_mac_postamble,
39                                 ARRAY_SIZE(ar9485_1_1_mac_postamble), 5);
40
41                 /* bb */
42                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1,
43                                 ARRAY_SIZE(ar9485_1_1), 2);
44                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
45                                 ar9485_1_1_baseband_core,
46                                 ARRAY_SIZE(ar9485_1_1_baseband_core), 2);
47                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
48                                 ar9485_1_1_baseband_postamble,
49                                 ARRAY_SIZE(ar9485_1_1_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_1_radio_core,
55                                 ARRAY_SIZE(ar9485_1_1_radio_core), 2);
56                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
57                                 ar9485_1_1_radio_postamble,
58                                 ARRAY_SIZE(ar9485_1_1_radio_postamble), 2);
59
60                 /* soc */
61                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
62                                 ar9485_1_1_soc_preamble,
63                                 ARRAY_SIZE(ar9485_1_1_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                                 ar9485_common_rx_gain_1_1,
70                                 ARRAY_SIZE(ar9485_common_rx_gain_1_1), 2);
71                 INIT_INI_ARRAY(&ah->iniModesTxGain,
72                                 ar9485_modes_lowest_ob_db_tx_gain_1_1,
73                                 ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
74                                 5);
75
76                 /* Load PCIE SERDES settings from INI */
77
78                 /* Awake Setting */
79
80                 INIT_INI_ARRAY(&ah->iniPcieSerdes,
81                                 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1,
82                                 ARRAY_SIZE(ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1),
83                                 2);
84
85                 /* Sleep Setting */
86
87                 INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
88                                 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1,
89                                 ARRAY_SIZE(ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1),
90                                 2);
91         } else if (AR_SREV_9485(ah)) {
92                 /* mac */
93                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
94                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
95                                 ar9485_1_0_mac_core,
96                                 ARRAY_SIZE(ar9485_1_0_mac_core), 2);
97                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
98                                 ar9485_1_0_mac_postamble,
99                                 ARRAY_SIZE(ar9485_1_0_mac_postamble), 5);
100
101                 /* bb */
102                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_0,
103                                 ARRAY_SIZE(ar9485_1_0), 2);
104                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
105                                 ar9485_1_0_baseband_core,
106                                 ARRAY_SIZE(ar9485_1_0_baseband_core), 2);
107                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
108                                 ar9485_1_0_baseband_postamble,
109                                 ARRAY_SIZE(ar9485_1_0_baseband_postamble), 5);
110
111                 /* radio */
112                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
113                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
114                                 ar9485_1_0_radio_core,
115                                 ARRAY_SIZE(ar9485_1_0_radio_core), 2);
116                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
117                                 ar9485_1_0_radio_postamble,
118                                 ARRAY_SIZE(ar9485_1_0_radio_postamble), 2);
119
120                 /* soc */
121                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
122                                 ar9485_1_0_soc_preamble,
123                                 ARRAY_SIZE(ar9485_1_0_soc_preamble), 2);
124                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
125                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
126
127                 /* rx/tx gain */
128                 INIT_INI_ARRAY(&ah->iniModesRxGain,
129                                 ar9485Common_rx_gain_1_0,
130                                 ARRAY_SIZE(ar9485Common_rx_gain_1_0), 2);
131                 INIT_INI_ARRAY(&ah->iniModesTxGain,
132                                 ar9485Modes_lowest_ob_db_tx_gain_1_0,
133                                 ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
134                                 5);
135
136                 /* Load PCIE SERDES settings from INI */
137
138                 /* Awake Setting */
139
140                 INIT_INI_ARRAY(&ah->iniPcieSerdes,
141                                 ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1,
142                                 ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1),
143                                 2);
144
145                 /* Sleep Setting */
146
147                 INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
148                                 ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1,
149                                 ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1),
150                                 2);
151         } else {
152                 /* mac */
153                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
154                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
155                                 ar9300_2p2_mac_core,
156                                 ARRAY_SIZE(ar9300_2p2_mac_core), 2);
157                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
158                                 ar9300_2p2_mac_postamble,
159                                 ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
160
161                 /* bb */
162                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
163                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
164                                 ar9300_2p2_baseband_core,
165                                 ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
166                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
167                                 ar9300_2p2_baseband_postamble,
168                                 ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
169
170                 /* radio */
171                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
172                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
173                                 ar9300_2p2_radio_core,
174                                 ARRAY_SIZE(ar9300_2p2_radio_core), 2);
175                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
176                                 ar9300_2p2_radio_postamble,
177                                 ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
178
179                 /* soc */
180                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
181                                 ar9300_2p2_soc_preamble,
182                                 ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
183                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
184                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
185                                 ar9300_2p2_soc_postamble,
186                                 ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
187
188                 /* rx/tx gain */
189                 INIT_INI_ARRAY(&ah->iniModesRxGain,
190                                 ar9300Common_rx_gain_table_2p2,
191                                 ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
192                 INIT_INI_ARRAY(&ah->iniModesTxGain,
193                                 ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
194                                 ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
195                                 5);
196
197                 /* Load PCIE SERDES settings from INI */
198
199                 /* Awake Setting */
200
201                 INIT_INI_ARRAY(&ah->iniPcieSerdes,
202                                 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
203                                 ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
204                                 2);
205
206                 /* Sleep Setting */
207
208                 INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
209                                 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
210                                 ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
211                                 2);
212
213                 /* Fast clock modal settings */
214                 INIT_INI_ARRAY(&ah->iniModesAdditional,
215                                 ar9300Modes_fast_clock_2p2,
216                                 ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
217                                 3);
218         }
219 }
220
221 static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
222 {
223         switch (ar9003_hw_get_tx_gain_idx(ah)) {
224         case 0:
225         default:
226                 if (AR_SREV_9485_11(ah))
227                         INIT_INI_ARRAY(&ah->iniModesTxGain,
228                                        ar9485_modes_lowest_ob_db_tx_gain_1_1,
229                                        ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
230                                        5);
231                 else if (AR_SREV_9485(ah))
232                         INIT_INI_ARRAY(&ah->iniModesTxGain,
233                                        ar9485Modes_lowest_ob_db_tx_gain_1_0,
234                                        ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
235                                        5);
236                 else
237                         INIT_INI_ARRAY(&ah->iniModesTxGain,
238                                        ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
239                                        ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
240                                        5);
241                 break;
242         case 1:
243                 if (AR_SREV_9485_11(ah))
244                         INIT_INI_ARRAY(&ah->iniModesTxGain,
245                                        ar9485Modes_high_ob_db_tx_gain_1_1,
246                                        ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
247                                        5);
248                 else if (AR_SREV_9485(ah))
249                         INIT_INI_ARRAY(&ah->iniModesTxGain,
250                                        ar9485Modes_high_ob_db_tx_gain_1_0,
251                                        ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_0),
252                                        5);
253                 else
254                         INIT_INI_ARRAY(&ah->iniModesTxGain,
255                                        ar9300Modes_high_ob_db_tx_gain_table_2p2,
256                                        ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
257                                        5);
258                 break;
259         case 2:
260                 if (AR_SREV_9485_11(ah))
261                         INIT_INI_ARRAY(&ah->iniModesTxGain,
262                                        ar9485Modes_low_ob_db_tx_gain_1_1,
263                                        ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
264                                        5);
265                 else if (AR_SREV_9485(ah))
266                         INIT_INI_ARRAY(&ah->iniModesTxGain,
267                                        ar9485Modes_low_ob_db_tx_gain_1_0,
268                                        ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_0),
269                                        5);
270                 else
271                         INIT_INI_ARRAY(&ah->iniModesTxGain,
272                                        ar9300Modes_low_ob_db_tx_gain_table_2p2,
273                                        ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
274                                        5);
275                 break;
276         case 3:
277                 if (AR_SREV_9485_11(ah))
278                         INIT_INI_ARRAY(&ah->iniModesTxGain,
279                                        ar9485Modes_high_power_tx_gain_1_1,
280                                        ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
281                                        5);
282                 else if (AR_SREV_9485(ah))
283                         INIT_INI_ARRAY(&ah->iniModesTxGain,
284                                        ar9485Modes_high_power_tx_gain_1_0,
285                                        ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0),
286                                        5);
287                 else
288                         INIT_INI_ARRAY(&ah->iniModesTxGain,
289                                        ar9300Modes_high_power_tx_gain_table_2p2,
290                                        ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
291                                        5);
292                 break;
293         }
294 }
295
296 static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
297 {
298         switch (ar9003_hw_get_rx_gain_idx(ah)) {
299         case 0:
300         default:
301                 if (AR_SREV_9485_11(ah))
302                         INIT_INI_ARRAY(&ah->iniModesRxGain,
303                                        ar9485_common_rx_gain_1_1,
304                                        ARRAY_SIZE(ar9485_common_rx_gain_1_1),
305                                        2);
306                 else if (AR_SREV_9485(ah))
307                         INIT_INI_ARRAY(&ah->iniModesRxGain,
308                                        ar9485Common_rx_gain_1_0,
309                                        ARRAY_SIZE(ar9485Common_rx_gain_1_0),
310                                        2);
311                 else
312                         INIT_INI_ARRAY(&ah->iniModesRxGain,
313                                        ar9300Common_rx_gain_table_2p2,
314                                        ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
315                                        2);
316                 break;
317         case 1:
318                 if (AR_SREV_9485_11(ah))
319                         INIT_INI_ARRAY(&ah->iniModesRxGain,
320                                        ar9485Common_wo_xlna_rx_gain_1_1,
321                                        ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
322                                        2);
323                 else if (AR_SREV_9485(ah))
324                         INIT_INI_ARRAY(&ah->iniModesRxGain,
325                                        ar9485Common_wo_xlna_rx_gain_1_0,
326                                        ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0),
327                                        2);
328                 else
329                         INIT_INI_ARRAY(&ah->iniModesRxGain,
330                                        ar9300Common_wo_xlna_rx_gain_table_2p2,
331                                        ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
332                                        2);
333                 break;
334         }
335 }
336
337 /* set gain table pointers according to values read from the eeprom */
338 static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
339 {
340         ar9003_tx_gain_table_apply(ah);
341         ar9003_rx_gain_table_apply(ah);
342 }
343
344 /*
345  * Helper for ASPM support.
346  *
347  * Disable PLL when in L0s as well as receiver clock when in L1.
348  * This power saving option must be enabled through the SerDes.
349  *
350  * Programming the SerDes must go through the same 288 bit serial shift
351  * register as the other analog registers.  Hence the 9 writes.
352  */
353 static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
354                                          int restore,
355                                          int power_off)
356 {
357         if (ah->is_pciexpress != true)
358                 return;
359
360         /* Do not touch SerDes registers */
361         if (ah->config.pcie_powersave_enable == 2)
362                 return;
363
364         /* Nothing to do on restore for 11N */
365         if (!restore) {
366                 /* set bit 19 to allow forcing of pcie core into L1 state */
367                 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
368
369                 /* Several PCIe massages to ensure proper behaviour */
370                 if (ah->config.pcie_waen)
371                         REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
372                 else
373                         REG_WRITE(ah, AR_WA, ah->WARegVal);
374         }
375
376         /*
377          * Configire PCIE after Ini init. SERDES values now come from ini file
378          * This enables PCIe low power mode.
379          */
380         if (ah->config.pcieSerDesWrite) {
381                 unsigned int i;
382                 struct ar5416IniArray *array;
383
384                 array = power_off ? &ah->iniPcieSerdes :
385                                     &ah->iniPcieSerdesLowPower;
386
387                 for (i = 0; i < array->ia_rows; i++) {
388                         REG_WRITE(ah,
389                                   INI_RA(array, i, 0),
390                                   INI_RA(array, i, 1));
391                 }
392         }
393 }
394
395 /* Sets up the AR9003 hardware familiy callbacks */
396 void ar9003_hw_attach_ops(struct ath_hw *ah)
397 {
398         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
399         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
400
401         priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
402         priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
403
404         ops->config_pci_powersave = ar9003_hw_configpcipowersave;
405
406         ar9003_hw_attach_phy_ops(ah);
407         ar9003_hw_attach_calib_ops(ah);
408         ar9003_hw_attach_mac_ops(ah);
409 }