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