2 * carl9170 firmware - used by the ar9170 wireless device
6 * Copyright (c) 2000-2005 ZyDAS Technology Corporation
7 * Copyright (c) 2007-2009 Atheros Communications, Inc.
8 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
9 * Copyright 2009, 2010 Christian Lamparter <chunkeey@googlemail.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "shared/phy.h"
32 #ifdef CONFIG_CARL9170FW_RADIO_FUNCTIONS
33 static void set_channel_start(void)
35 /* Manipulate CCA threshold to stop transmission */
36 set(AR9170_PHY_REG_CCA_THRESHOLD, 0x300);
37 /* Enable Virtual CCA */
38 orl(AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA,
39 AR9170_MAC_VIRTUAL_CCA_ALL);
42 static void set_channel_end(void)
44 /* Manipulate CCA threshold to resume transmission */
45 set(AR9170_PHY_REG_CCA_THRESHOLD, 0x0);
46 /* Disable Virtual CCA */
47 andl(AR9170_MAC_REG_QOS_PRIORITY_VIRTUAL_CCA,
48 ~AR9170_MAC_VIRTUAL_CCA_ALL);
51 void rf_notify_set_channel(void)
57 * Update delta slope coeff man and exp
59 static void hw_turn_off_dyn(const uint32_t delta_slope_coeff_exp,
60 const uint32_t delta_slope_coeff_man,
61 const uint32_t delta_slope_coeff_exp_shgi,
62 const uint32_t delta_slope_coeff_man_shgi)
66 tmp = get_async(AR9170_PHY_REG_TIMING3) & 0x00001fff;
67 tmp |= (delta_slope_coeff_man << AR9170_PHY_TIMING3_DSC_MAN_S) &
68 AR9170_PHY_TIMING3_DSC_MAN;
69 tmp |= (delta_slope_coeff_exp << AR9170_PHY_TIMING3_DSC_EXP_S) &
70 AR9170_PHY_TIMING3_DSC_EXP;
72 set(AR9170_PHY_REG_TIMING3, tmp);
74 tmp = (delta_slope_coeff_man_shgi << AR9170_PHY_HALFGI_DSC_MAN_S) &
75 AR9170_PHY_HALFGI_DSC_MAN;
77 tmp |= (delta_slope_coeff_exp_shgi << AR9170_PHY_HALFGI_DSC_EXP_S) &
78 AR9170_PHY_HALFGI_DSC_EXP;
80 set(AR9170_PHY_REG_HALFGI, tmp);
83 static void program_ADDAC(void)
85 /* ??? Select Internal ADDAC ??? (is external radio) */
86 set(AR9170_PHY_REG_ADC_SERIAL_CTL, AR9170_PHY_ADC_SCTL_SEL_EXTERNAL_RADIO);
90 set(0x1c589c, 0x00000000); /*# 7-0 */
91 set(0x1c589c, 0x00000000); /*# 15-8 */
92 set(0x1c589c, 0x00000000); /*# 23-16 */
93 set(0x1c589c, 0x00000000); /*# 31- */
95 set(0x1c589c, 0x00000000); /*# 39- */
96 set(0x1c589c, 0x00000000); /*# 47- */
97 set(0x1c589c, 0x00000000); /*# 55- [48]:doubles the xtalosc bias current */
98 set(0x1c589c, 0x00000000); /*# 63- */
100 set(0x1c589c, 0x00000000); /*# 71- */
101 set(0x1c589c, 0x00000000); /*# 79- */
102 set(0x1c589c, 0x00000000); /*# 87- */
103 set(0x1c589c, 0x00000000); /*# 95- */
105 set(0x1c589c, 0x00000000); /*# 103- */
106 set(0x1c589c, 0x00000000); /*# 111- */
107 set(0x1c589c, 0x00000000); /*# 119- */
108 set(0x1c589c, 0x00000000); /*# 127- */
110 set(0x1c589c, 0x00000000); /*# 135- */
111 set(0x1c589c, 0x00000000); /*# 143- */
112 set(0x1c589c, 0x00000000); /*# 151- */
113 set(0x1c589c, 0x00000030); /*# 159- #[158:156]=xlnabufmode */
115 set(0x1c589c, 0x00000004); /*# 167- [162]:disable clkp_driver to flow */
116 set(0x1c589c, 0x00000000); /*# 175- */
117 set(0x1c589c, 0x00000000); /*# 183-176 */
118 set(0x1c589c, 0x00000000); /*# 191-184 */
120 set(0x1c589c, 0x00000000); /*# 199- */
121 set(0x1c589c, 0x00000000); /*# 207- */
122 set(0x1c589c, 0x00000000); /*# 215- */
123 set(0x1c589c, 0x00000000); /*# 223- */
125 set(0x1c589c, 0x00000000); /*# 231- */
126 set(0x1c58c4, 0x00000000); /*# 233-232 */
130 /* Select External Flow ???? (is internal addac??) */
131 set(AR9170_PHY_REG_ADC_SERIAL_CTL, AR9170_PHY_ADC_SCTL_SEL_INTERNAL_ADDAC);
134 static uint32_t AGC_calibration(uint32_t loop)
139 #define AGC_CAL_NF (AR9170_PHY_AGC_CONTROL_CAL | AR9170_PHY_AGC_CONTROL_NF);
141 wrdata = get_async(AR9170_PHY_REG_AGC_CONTROL) | AGC_CAL_NF;
142 set(AR9170_PHY_REG_AGC_CONTROL, wrdata);
144 ret = get_async(AR9170_PHY_REG_AGC_CONTROL) & AGC_CAL_NF;
146 /* sitesurvey : 100 ms / current connected 200 ms */
147 while (loop && ret != 0x0) {
148 ret = get_async(AR9170_PHY_REG_AGC_CONTROL) & AGC_CAL_NF;
157 /* return the AGC/Noise calibration state to the driver */
161 #define EIGHTY_FLAG (CARL9170FW_PHY_HT_ENABLE | CARL9170FW_PHY_HT_DYN2040)
163 static uint32_t rf_init(const uint32_t delta_slope_coeff_exp,
164 const uint32_t delta_slope_coeff_man,
165 const uint32_t delta_slope_coeff_exp_shgi,
166 const uint32_t delta_slope_coeff_man_shgi,
167 const uint32_t finiteLoopCount,
168 const bool initialize)
172 hw_turn_off_dyn(delta_slope_coeff_exp,
173 delta_slope_coeff_man,
174 delta_slope_coeff_exp_shgi,
175 delta_slope_coeff_man_shgi);
181 /* inverse chain 0 <-> chain 2 */
182 set(AR9170_PHY_REG_ANALOG_SWAP, AR9170_PHY_ANALOG_SWAP_AB);
184 /* swap chain 0 and chain 2 */
185 set(AR9170_PHY_REG_ANALOG_SWAP, AR9170_PHY_ANALOG_SWAP_AB |
186 AR9170_PHY_ANALOG_SWAP_ALT_CHAIN);
189 set(AR9170_PHY_REG_RX_CHAINMASK, 0x5); /* chain 0 + chain 2 */
190 set(AR9170_PHY_REG_CAL_CHAINMASK, 0x5); /* chain 0 + chain 2 */
193 set(AR9170_PHY_REG_ACTIVE, AR9170_PHY_ACTIVE_EN);
197 ret = AGC_calibration(finiteLoopCount);
203 void rf_cmd(const struct carl9170_cmd *cmd, struct carl9170_rsp *resp)
207 fw.phy.ht_settings = cmd->rf_init.ht_settings;
208 fw.phy.frequency = cmd->rf_init.freq;
210 if ((fw.phy.ht_settings & EIGHTY_FLAG) == EIGHTY_FLAG)
211 clock_set(true, AHB_80_88MHZ);
213 clock_set(true, AHB_40_44MHZ);
215 ret = rf_init(le32_to_cpu(cmd->rf_init.delta_slope_coeff_exp),
216 le32_to_cpu(cmd->rf_init.delta_slope_coeff_man),
217 le32_to_cpu(cmd->rf_init.delta_slope_coeff_exp_shgi),
218 le32_to_cpu(cmd->rf_init.delta_slope_coeff_man_shgi),
219 le32_to_cpu(cmd->rf_init.finiteLoopCount),
220 cmd->hdr.cmd == CARL9170_CMD_RF_INIT);
222 resp->hdr.len = sizeof(struct carl9170_rf_init_result);
223 resp->rf_init_res.ret = cpu_to_le32(ret);
225 resp->rf_init_res.regs[0] = get(AR9170_PHY_REG_CCA);
226 resp->rf_init_res.regs[3] = get(AR9170_PHY_REG_EXT_CCA);
228 resp->rf_init_res.regs[1] = get(AR9170_PHY_REG_CH1_CCA);
229 resp->rf_init_res.regs[4] = get(AR9170_PHY_REG_CH1_EXT_CCA);
231 resp->rf_init_res.regs[2] = get(AR9170_PHY_REG_CH2_CCA);
232 resp->rf_init_res.regs[5] = get(AR9170_PHY_REG_CH2_EXT_CCA);
235 #ifdef CONFIG_CARL9170FW_PSM
241 * FIXME: Does not work on 5GHz band!
244 if (fw.phy.psm.state == CARL9170_PSM_SOFTWARE) {
245 /* not enabled by the driver */
249 if (fw.phy.psm.state & CARL9170_PSM_SLEEP) {
250 fw.phy.psm.state &= ~CARL9170_PSM_SLEEP;
252 /* disable all agc gain and offset updates to a2 */
253 set(AR9170_PHY_REG_TEST2, 0x8000000);
255 /* power down ADDAC */
256 set(AR9170_PHY_REG_ADC_CTL,
257 AR9170_PHY_ADC_CTL_OFF_PWDDAC |
258 AR9170_PHY_ADC_CTL_OFF_PWDADC |
261 /* Synthesizer off + RX off */
264 clock_set(true, AHB_20_22MHZ);
266 /* advance to the next PSM step */
269 if (fw.phy.psm.state == CARL9170_PSM_WAKE) {
271 set(AR9170_PHY_REG_ADC_CTL,
272 AR9170_PHY_ADC_CTL_OFF_PWDDAC |
273 AR9170_PHY_ADC_CTL_OFF_PWDADC);
275 /* enable all agc gain and offset updates to a2 */
276 set(AR9170_PHY_REG_TEST2, 0x0);
278 /* Synthesizer on + RX on */
281 if ((fw.phy.ht_settings & EIGHTY_FLAG) == EIGHTY_FLAG)
282 clock_set(true, AHB_80_88MHZ);
284 clock_set(true, AHB_40_44MHZ);
290 if (fw.phy.frequency < 30000000)
293 set(0x1c58f0, bank3);
295 #endif /* CONFIG_CARL9170FW_PSM */
297 #endif /* CONFIG_CARL9170FW_RADIO_FUNCTIONS */