Merge branches 'irq-core-for-linus' and 'core-locking-for-linus' of git://git.kernel...
[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
21 /* General hardware code for the AR9003 hadware family */
22
23 static bool ar9003_hw_macversion_supported(u32 macversion)
24 {
25         switch (macversion) {
26         case AR_SREV_VERSION_9300:
27                 return true;
28         default:
29                 break;
30         }
31         return false;
32 }
33
34 /*
35  * The AR9003 family uses a new INI format (pre, core, post
36  * arrays per subsystem). This provides support for the
37  * AR9003 2.2 chipsets.
38  */
39 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
40 {
41         /* mac */
42         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
43         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
44                        ar9300_2p2_mac_core,
45                        ARRAY_SIZE(ar9300_2p2_mac_core), 2);
46         INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
47                        ar9300_2p2_mac_postamble,
48                        ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
49
50         /* bb */
51         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
52         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
53                        ar9300_2p2_baseband_core,
54                        ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
55         INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
56                        ar9300_2p2_baseband_postamble,
57                        ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
58
59         /* radio */
60         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
61         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
62                        ar9300_2p2_radio_core,
63                        ARRAY_SIZE(ar9300_2p2_radio_core), 2);
64         INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
65                        ar9300_2p2_radio_postamble,
66                        ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
67
68         /* soc */
69         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
70                        ar9300_2p2_soc_preamble,
71                        ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
72         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
73         INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
74                        ar9300_2p2_soc_postamble,
75                        ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
76
77         /* rx/tx gain */
78         INIT_INI_ARRAY(&ah->iniModesRxGain,
79                        ar9300Common_rx_gain_table_2p2,
80                        ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
81         INIT_INI_ARRAY(&ah->iniModesTxGain,
82                        ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
83                        ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
84                        5);
85
86         /* Load PCIE SERDES settings from INI */
87
88         /* Awake Setting */
89
90         INIT_INI_ARRAY(&ah->iniPcieSerdes,
91                        ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
92                        ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
93                        2);
94
95         /* Sleep Setting */
96
97         INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
98                        ar9300PciePhy_clkreq_enable_L1_2p2,
99                        ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2),
100                        2);
101
102         /* Fast clock modal settings */
103         INIT_INI_ARRAY(&ah->iniModesAdditional,
104                        ar9300Modes_fast_clock_2p2,
105                        ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
106                        3);
107 }
108
109 static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
110 {
111         switch (ar9003_hw_get_tx_gain_idx(ah)) {
112         case 0:
113         default:
114                 INIT_INI_ARRAY(&ah->iniModesTxGain,
115                                ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
116                                ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
117                                5);
118                 break;
119         case 1:
120                 INIT_INI_ARRAY(&ah->iniModesTxGain,
121                                ar9300Modes_high_ob_db_tx_gain_table_2p2,
122                                ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
123                                5);
124                 break;
125         case 2:
126                 INIT_INI_ARRAY(&ah->iniModesTxGain,
127                                ar9300Modes_low_ob_db_tx_gain_table_2p2,
128                                ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
129                                5);
130                 break;
131         }
132 }
133
134 static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
135 {
136         switch (ar9003_hw_get_rx_gain_idx(ah)) {
137         case 0:
138         default:
139                 INIT_INI_ARRAY(&ah->iniModesRxGain,
140                                ar9300Common_rx_gain_table_2p2,
141                                ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
142                                2);
143                 break;
144         case 1:
145                 INIT_INI_ARRAY(&ah->iniModesRxGain,
146                                ar9300Common_wo_xlna_rx_gain_table_2p2,
147                                ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
148                                2);
149                 break;
150         }
151 }
152
153 /* set gain table pointers according to values read from the eeprom */
154 static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
155 {
156         ar9003_tx_gain_table_apply(ah);
157         ar9003_rx_gain_table_apply(ah);
158 }
159
160 /*
161  * Helper for ASPM support.
162  *
163  * Disable PLL when in L0s as well as receiver clock when in L1.
164  * This power saving option must be enabled through the SerDes.
165  *
166  * Programming the SerDes must go through the same 288 bit serial shift
167  * register as the other analog registers.  Hence the 9 writes.
168  */
169 static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
170                                          int restore,
171                                          int power_off)
172 {
173         if (ah->is_pciexpress != true)
174                 return;
175
176         /* Do not touch SerDes registers */
177         if (ah->config.pcie_powersave_enable == 2)
178                 return;
179
180         /* Nothing to do on restore for 11N */
181         if (!restore) {
182                 /* set bit 19 to allow forcing of pcie core into L1 state */
183                 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
184
185                 /* Several PCIe massages to ensure proper behaviour */
186                 if (ah->config.pcie_waen)
187                         REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
188                 else
189                         REG_WRITE(ah, AR_WA, ah->WARegVal);
190         }
191
192         /*
193          * Configire PCIE after Ini init. SERDES values now come from ini file
194          * This enables PCIe low power mode.
195          */
196         if (ah->config.pcieSerDesWrite) {
197                 unsigned int i;
198                 struct ar5416IniArray *array;
199
200                 array = power_off ? &ah->iniPcieSerdes :
201                                     &ah->iniPcieSerdesLowPower;
202
203                 for (i = 0; i < array->ia_rows; i++) {
204                         REG_WRITE(ah,
205                                   INI_RA(array, i, 0),
206                                   INI_RA(array, i, 1));
207                 }
208         }
209 }
210
211 /* Sets up the AR9003 hardware familiy callbacks */
212 void ar9003_hw_attach_ops(struct ath_hw *ah)
213 {
214         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
215         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
216
217         priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
218         priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
219         priv_ops->macversion_supported = ar9003_hw_macversion_supported;
220
221         ops->config_pci_powersave = ar9003_hw_configpcipowersave;
222
223         ar9003_hw_attach_phy_ops(ah);
224         ar9003_hw_attach_calib_ops(ah);
225         ar9003_hw_attach_mac_ops(ah);
226 }