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