ath9k: simplify hw reset locking
[linux-2.6-block.git] / drivers / net / wireless / ath / ath9k / ar9003_hw.c
CommitLineData
b3950e6a
LR
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"
b622a720 18#include "ar9003_mac.h"
7284635d 19#include "ar9003_2p2_initvals.h"
b3950e6a
LR
20
21/* General hardware code for the AR9003 hadware family */
22
23static 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
886b42bf
LR
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 */
39static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
7284635d
LR
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
c14a85da
LR
109static 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:
886b42bf
LR
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);
c14a85da
LR
118 break;
119 case 1:
886b42bf
LR
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);
c14a85da
LR
124 break;
125 case 2:
886b42bf
LR
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);
c14a85da
LR
130 break;
131 }
132}
133
134static 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:
886b42bf
LR
139 INIT_INI_ARRAY(&ah->iniModesRxGain,
140 ar9300Common_rx_gain_table_2p2,
141 ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
142 2);
c14a85da
LR
143 break;
144 case 1:
886b42bf
LR
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);
c14a85da
LR
149 break;
150 }
151}
152
153/* set gain table pointers according to values read from the eeprom */
154static 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
b3950e6a
LR
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 */
169static 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);
9a658d2b
LR
188 else
189 REG_WRITE(ah, AR_WA, ah->WARegVal);
b3950e6a 190 }
653fe371
LR
191
192 /*
193 * Configire PCIE after Ini init. SERDES values now come from ini file
194 * This enables PCIe low power mode.
195 */
6a0ec30a 196 if (ah->config.pcieSerDesWrite) {
653fe371 197 unsigned int i;
d5c4d193 198 struct ar5416IniArray *array;
653fe371 199
d5c4d193
LR
200 array = power_off ? &ah->iniPcieSerdes :
201 &ah->iniPcieSerdesLowPower;
202
203 for (i = 0; i < array->ia_rows; i++) {
653fe371 204 REG_WRITE(ah,
d5c4d193
LR
205 INI_RA(array, i, 0),
206 INI_RA(array, i, 1));
653fe371
LR
207 }
208 }
b3950e6a
LR
209}
210
211/* Sets up the AR9003 hardware familiy callbacks */
212void 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;
c14a85da 218 priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
b3950e6a
LR
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}