117d50d1dSVasanthakumar Thiagarajan /*
25b68138eSSujith Manoharan * Copyright (c) 2009-2011 Atheros Communications Inc.
317d50d1dSVasanthakumar Thiagarajan *
417d50d1dSVasanthakumar Thiagarajan * Permission to use, copy, modify, and/or distribute this software for any
517d50d1dSVasanthakumar Thiagarajan * purpose with or without fee is hereby granted, provided that the above
617d50d1dSVasanthakumar Thiagarajan * copyright notice and this permission notice appear in all copies.
717d50d1dSVasanthakumar Thiagarajan *
817d50d1dSVasanthakumar Thiagarajan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
917d50d1dSVasanthakumar Thiagarajan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1017d50d1dSVasanthakumar Thiagarajan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1117d50d1dSVasanthakumar Thiagarajan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1217d50d1dSVasanthakumar Thiagarajan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1317d50d1dSVasanthakumar Thiagarajan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1417d50d1dSVasanthakumar Thiagarajan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1517d50d1dSVasanthakumar Thiagarajan */
1617d50d1dSVasanthakumar Thiagarajan
17ee40fa06SPaul Gortmaker #include <linux/export.h>
18c8770bcfSMiaoqing Pan #include <linux/types.h>
19c8770bcfSMiaoqing Pan #include <linux/ath9k_platform.h>
20cfe8cba9SLuis R. Rodriguez #include "hw.h"
2117d50d1dSVasanthakumar Thiagarajan
228b4fc5baSLuis R. Rodriguez enum ath_bt_mode {
238b4fc5baSLuis R. Rodriguez ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */
248b4fc5baSLuis R. Rodriguez ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */
258b4fc5baSLuis R. Rodriguez ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */
2632b1076dSMohammed Shafi Shajakhan ATH_BT_COEX_MODE_DISABLED, /* coexistence disabled */
278b4fc5baSLuis R. Rodriguez };
288b4fc5baSLuis R. Rodriguez
298b4fc5baSLuis R. Rodriguez struct ath_btcoex_config {
308b4fc5baSLuis R. Rodriguez u8 bt_time_extend;
318b4fc5baSLuis R. Rodriguez bool bt_txstate_extend;
328b4fc5baSLuis R. Rodriguez bool bt_txframe_extend;
338b4fc5baSLuis R. Rodriguez enum ath_bt_mode bt_mode; /* coexistence mode */
348b4fc5baSLuis R. Rodriguez bool bt_quiet_collision;
358b4fc5baSLuis R. Rodriguez bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/
368b4fc5baSLuis R. Rodriguez u8 bt_priority_time;
378b4fc5baSLuis R. Rodriguez u8 bt_first_slot_time;
388b4fc5baSLuis R. Rodriguez bool bt_hold_rx_clear;
39c7212b71SMiaoqing Pan u8 wl_active_time;
40c7212b71SMiaoqing Pan u8 wl_qc_time;
418b4fc5baSLuis R. Rodriguez };
421773912bSVasanthakumar Thiagarajan
4354f10b05SRajkumar Manoharan static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX]
4454f10b05SRajkumar Manoharan [AR9300_NUM_WLAN_WEIGHTS] = {
4554f10b05SRajkumar Manoharan { 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0 }, /* STOMP_ALL */
4654f10b05SRajkumar Manoharan { 0x88888880, 0x88888880, 0x88888880, 0x88888880 }, /* STOMP_LOW */
4754f10b05SRajkumar Manoharan { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* STOMP_NONE */
4854f10b05SRajkumar Manoharan };
491773912bSVasanthakumar Thiagarajan
505160b46fSSujith Manoharan static const u32 mci_wlan_weights[ATH_BTCOEX_STOMP_MAX]
518227bf45SRajkumar Manoharan [AR9300_NUM_WLAN_WEIGHTS] = {
528227bf45SRajkumar Manoharan { 0x01017d01, 0x41414101, 0x41414101, 0x41414141 }, /* STOMP_ALL */
538227bf45SRajkumar Manoharan { 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */
548227bf45SRajkumar Manoharan { 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */
558227bf45SRajkumar Manoharan { 0x01017d01, 0x013b0101, 0x3b3b0101, 0x3b3b013b }, /* STOMP_LOW_FTP */
562884561aSRajkumar Manoharan { 0xffffff01, 0xffffffff, 0xffffff01, 0xffffffff }, /* STOMP_AUDIO */
578227bf45SRajkumar Manoharan };
588227bf45SRajkumar Manoharan
ath9k_hw_init_btcoex_hw(struct ath_hw * ah,int qnum)59766ec4a9SLuis R. Rodriguez void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
60af03abecSLuis R. Rodriguez {
61766ec4a9SLuis R. Rodriguez struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
628b4fc5baSLuis R. Rodriguez const struct ath_btcoex_config ath_bt_config = {
638b4fc5baSLuis R. Rodriguez .bt_time_extend = 0,
648b4fc5baSLuis R. Rodriguez .bt_txstate_extend = true,
658b4fc5baSLuis R. Rodriguez .bt_txframe_extend = true,
668b4fc5baSLuis R. Rodriguez .bt_mode = ATH_BT_COEX_MODE_SLOTTED,
678b4fc5baSLuis R. Rodriguez .bt_quiet_collision = true,
688b4fc5baSLuis R. Rodriguez .bt_rxclear_polarity = true,
698b4fc5baSLuis R. Rodriguez .bt_priority_time = 2,
708b4fc5baSLuis R. Rodriguez .bt_first_slot_time = 5,
718b4fc5baSLuis R. Rodriguez .bt_hold_rx_clear = true,
72c7212b71SMiaoqing Pan .wl_active_time = 0x20,
73c7212b71SMiaoqing Pan .wl_qc_time = 0x20,
748b4fc5baSLuis R. Rodriguez };
75a6ef530fSVivek Natarajan bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
76c7212b71SMiaoqing Pan u8 time_extend = ath_bt_config.bt_time_extend;
77c7212b71SMiaoqing Pan u8 first_slot_time = ath_bt_config.bt_first_slot_time;
78a6ef530fSVivek Natarajan
79a6ef530fSVivek Natarajan if (AR_SREV_9300_20_OR_LATER(ah))
80a6ef530fSVivek Natarajan rxclear_polarity = !ath_bt_config.bt_rxclear_polarity;
811773912bSVasanthakumar Thiagarajan
82c7212b71SMiaoqing Pan if (AR_SREV_SOC(ah)) {
83c7212b71SMiaoqing Pan first_slot_time = 0x1d;
84c7212b71SMiaoqing Pan time_extend = 0xa;
85c7212b71SMiaoqing Pan
86c7212b71SMiaoqing Pan btcoex_hw->bt_coex_mode3 =
87c7212b71SMiaoqing Pan SM(ath_bt_config.wl_active_time, AR_BT_WL_ACTIVE_TIME) |
88c7212b71SMiaoqing Pan SM(ath_bt_config.wl_qc_time, AR_BT_WL_QC_TIME);
89c7212b71SMiaoqing Pan
90c7212b71SMiaoqing Pan btcoex_hw->bt_coex_mode2 =
91c7212b71SMiaoqing Pan AR_BT_PROTECT_BT_AFTER_WAKEUP |
92c7212b71SMiaoqing Pan AR_BT_PHY_ERR_BT_COLL_ENABLE;
93c7212b71SMiaoqing Pan }
94c7212b71SMiaoqing Pan
95766ec4a9SLuis R. Rodriguez btcoex_hw->bt_coex_mode =
96766ec4a9SLuis R. Rodriguez (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) |
97c7212b71SMiaoqing Pan SM(time_extend, AR_BT_TIME_EXTEND) |
981773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
991773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
1001773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_mode, AR_BT_MODE) |
1011773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) |
102a6ef530fSVivek Natarajan SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) |
1031773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) |
104c7212b71SMiaoqing Pan SM(first_slot_time, AR_BT_FIRST_SLOT_TIME) |
1051773912bSVasanthakumar Thiagarajan SM(qnum, AR_BT_QCU_THRESH);
1061773912bSVasanthakumar Thiagarajan
107c7212b71SMiaoqing Pan btcoex_hw->bt_coex_mode2 |=
1081773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
1091773912bSVasanthakumar Thiagarajan SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
1101773912bSVasanthakumar Thiagarajan AR_BT_DISABLE_BT_ANT;
1111773912bSVasanthakumar Thiagarajan }
1127322fd19SLuis R. Rodriguez EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
1131773912bSVasanthakumar Thiagarajan
ath9k_hw_btcoex_pin_init(struct ath_hw * ah,u8 wlanactive_gpio,u8 btactive_gpio,u8 btpriority_gpio)114c8770bcfSMiaoqing Pan static void ath9k_hw_btcoex_pin_init(struct ath_hw *ah, u8 wlanactive_gpio,
115c8770bcfSMiaoqing Pan u8 btactive_gpio, u8 btpriority_gpio)
116c8770bcfSMiaoqing Pan {
117c8770bcfSMiaoqing Pan struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
118c8770bcfSMiaoqing Pan struct ath9k_platform_data *pdata = ah->dev->platform_data;
119c8770bcfSMiaoqing Pan
120c8770bcfSMiaoqing Pan if (btcoex_hw->scheme != ATH_BTCOEX_CFG_2WIRE &&
121c8770bcfSMiaoqing Pan btcoex_hw->scheme != ATH_BTCOEX_CFG_3WIRE)
122c8770bcfSMiaoqing Pan return;
123c8770bcfSMiaoqing Pan
124c8770bcfSMiaoqing Pan /* bt priority GPIO will be ignored by 2 wire scheme */
125c8770bcfSMiaoqing Pan if (pdata && (pdata->bt_active_pin || pdata->bt_priority_pin ||
126c8770bcfSMiaoqing Pan pdata->wlan_active_pin)) {
127c8770bcfSMiaoqing Pan btcoex_hw->btactive_gpio = pdata->bt_active_pin;
128c8770bcfSMiaoqing Pan btcoex_hw->wlanactive_gpio = pdata->wlan_active_pin;
129c8770bcfSMiaoqing Pan btcoex_hw->btpriority_gpio = pdata->bt_priority_pin;
130c8770bcfSMiaoqing Pan } else {
131c8770bcfSMiaoqing Pan btcoex_hw->btactive_gpio = btactive_gpio;
132c8770bcfSMiaoqing Pan btcoex_hw->wlanactive_gpio = wlanactive_gpio;
133c8770bcfSMiaoqing Pan btcoex_hw->btpriority_gpio = btpriority_gpio;
134c8770bcfSMiaoqing Pan }
135c8770bcfSMiaoqing Pan }
136c8770bcfSMiaoqing Pan
ath9k_hw_btcoex_init_scheme(struct ath_hw * ah)137d68475deSSujith Manoharan void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
138d68475deSSujith Manoharan {
139d68475deSSujith Manoharan struct ath_common *common = ath9k_hw_common(ah);
140d68475deSSujith Manoharan struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
141d68475deSSujith Manoharan
142d68475deSSujith Manoharan /*
143d68475deSSujith Manoharan * Check if BTCOEX is globally disabled.
144d68475deSSujith Manoharan */
145d68475deSSujith Manoharan if (!common->btcoex_enabled) {
146d68475deSSujith Manoharan btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE;
147d68475deSSujith Manoharan return;
148d68475deSSujith Manoharan }
149d68475deSSujith Manoharan
150e1ff147dSSujith Manoharan if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) {
151e1ff147dSSujith Manoharan btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI;
152e1ff147dSSujith Manoharan } else if (AR_SREV_9300_20_OR_LATER(ah)) {
153d68475deSSujith Manoharan btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
154d68475deSSujith Manoharan
155c8770bcfSMiaoqing Pan ath9k_hw_btcoex_pin_init(ah, ATH_WLANACTIVE_GPIO_9300,
156c8770bcfSMiaoqing Pan ATH_BTACTIVE_GPIO_9300,
157c8770bcfSMiaoqing Pan ATH_BTPRIORITY_GPIO_9300);
158c8770bcfSMiaoqing Pan } else if (AR_SREV_9280_20_OR_LATER(ah)) {
159c8770bcfSMiaoqing Pan if (AR_SREV_9285(ah))
160d68475deSSujith Manoharan btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
161c8770bcfSMiaoqing Pan else
162d68475deSSujith Manoharan btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE;
163c8770bcfSMiaoqing Pan
164c8770bcfSMiaoqing Pan ath9k_hw_btcoex_pin_init(ah, ATH_WLANACTIVE_GPIO_9280,
165c8770bcfSMiaoqing Pan ATH_BTACTIVE_GPIO_9280,
166c8770bcfSMiaoqing Pan ATH_BTPRIORITY_GPIO_9285);
167d68475deSSujith Manoharan }
168d68475deSSujith Manoharan }
169d68475deSSujith Manoharan EXPORT_SYMBOL(ath9k_hw_btcoex_init_scheme);
170d68475deSSujith Manoharan
ath9k_hw_btcoex_init_2wire(struct ath_hw * ah)17175d7839fSLuis R. Rodriguez void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
17217d50d1dSVasanthakumar Thiagarajan {
173766ec4a9SLuis R. Rodriguez struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
174f14462c6SVasanthakumar Thiagarajan
17517d50d1dSVasanthakumar Thiagarajan /* connect bt_active to baseband */
176*b3a663f0SWenli Looi REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL(ah),
17717d50d1dSVasanthakumar Thiagarajan (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
17817d50d1dSVasanthakumar Thiagarajan AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
17917d50d1dSVasanthakumar Thiagarajan
180*b3a663f0SWenli Looi REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL(ah),
18117d50d1dSVasanthakumar Thiagarajan AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
18217d50d1dSVasanthakumar Thiagarajan
18317d50d1dSVasanthakumar Thiagarajan /* Set input mux for bt_active to gpio pin */
184dfcf02cdSMiaoqing Pan if (!AR_SREV_SOC(ah))
185*b3a663f0SWenli Looi REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1(ah),
18617d50d1dSVasanthakumar Thiagarajan AR_GPIO_INPUT_MUX1_BT_ACTIVE,
187766ec4a9SLuis R. Rodriguez btcoex_hw->btactive_gpio);
18817d50d1dSVasanthakumar Thiagarajan
18917d50d1dSVasanthakumar Thiagarajan /* Configure the desired gpio port for input */
190b2d70d49SMiaoqing Pan ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio,
191b2d70d49SMiaoqing Pan "ath9k-btactive");
1927a2f0f58SLuis R. Rodriguez }
1937322fd19SLuis R. Rodriguez EXPORT_SYMBOL(ath9k_hw_btcoex_init_2wire);
1947a2f0f58SLuis R. Rodriguez
ath9k_hw_btcoex_init_3wire(struct ath_hw * ah)19575d7839fSLuis R. Rodriguez void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
1967a2f0f58SLuis R. Rodriguez {
197766ec4a9SLuis R. Rodriguez struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
1987a2f0f58SLuis R. Rodriguez
1991773912bSVasanthakumar Thiagarajan /* btcoex 3-wire */
200*b3a663f0SWenli Looi REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL(ah),
2011773912bSVasanthakumar Thiagarajan (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
2021773912bSVasanthakumar Thiagarajan AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));
2031773912bSVasanthakumar Thiagarajan
2041773912bSVasanthakumar Thiagarajan /* Set input mux for bt_prority_async and
2051773912bSVasanthakumar Thiagarajan * bt_active_async to GPIO pins */
206dfcf02cdSMiaoqing Pan if (!AR_SREV_SOC(ah)) {
207*b3a663f0SWenli Looi REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1(ah),
2081773912bSVasanthakumar Thiagarajan AR_GPIO_INPUT_MUX1_BT_ACTIVE,
209766ec4a9SLuis R. Rodriguez btcoex_hw->btactive_gpio);
210*b3a663f0SWenli Looi REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1(ah),
2111773912bSVasanthakumar Thiagarajan AR_GPIO_INPUT_MUX1_BT_PRIORITY,
212766ec4a9SLuis R. Rodriguez btcoex_hw->btpriority_gpio);
213dfcf02cdSMiaoqing Pan }
2141773912bSVasanthakumar Thiagarajan
2151773912bSVasanthakumar Thiagarajan /* Configure the desired GPIO ports for input */
216b2d70d49SMiaoqing Pan ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio,
217b2d70d49SMiaoqing Pan "ath9k-btactive");
218b2d70d49SMiaoqing Pan ath9k_hw_gpio_request_in(ah, btcoex_hw->btpriority_gpio,
219b2d70d49SMiaoqing Pan "ath9k-btpriority");
2207a2f0f58SLuis R. Rodriguez }
2217322fd19SLuis R. Rodriguez EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire);
2221773912bSVasanthakumar Thiagarajan
ath9k_hw_btcoex_deinit(struct ath_hw * ah)223db222190SMiaoqing Pan void ath9k_hw_btcoex_deinit(struct ath_hw *ah)
224db222190SMiaoqing Pan {
225db222190SMiaoqing Pan struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
226db222190SMiaoqing Pan
227db222190SMiaoqing Pan ath9k_hw_gpio_free(ah, btcoex_hw->btactive_gpio);
228db222190SMiaoqing Pan ath9k_hw_gpio_free(ah, btcoex_hw->btpriority_gpio);
229db222190SMiaoqing Pan ath9k_hw_gpio_free(ah, btcoex_hw->wlanactive_gpio);
230db222190SMiaoqing Pan }
231db222190SMiaoqing Pan EXPORT_SYMBOL(ath9k_hw_btcoex_deinit);
232db222190SMiaoqing Pan
ath9k_hw_btcoex_init_mci(struct ath_hw * ah)233d3c83ac1SSujith Manoharan void ath9k_hw_btcoex_init_mci(struct ath_hw *ah)
234d3c83ac1SSujith Manoharan {
235d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.ready = false;
236d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.bt_state = 0;
237d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.bt_ver_major = 3;
238d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.bt_ver_minor = 0;
239d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.bt_version_known = false;
240d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.update_2g5g = true;
241d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.is_2g = true;
242d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.wlan_channels_update = false;
243d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.wlan_channels[0] = 0x00000000;
244d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.wlan_channels[1] = 0xffffffff;
245d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.wlan_channels[2] = 0xffffffff;
246d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.wlan_channels[3] = 0x7fffffff;
247d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.query_bt = true;
248d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.unhalt_bt_gpm = true;
249d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.halted_bt_gpm = false;
250d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.need_flush_btinfo = false;
251d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.wlan_cal_seq = 0;
252d3c83ac1SSujith Manoharan ah->btcoex_hw.mci.wlan_cal_done = 0;
2533c5c9d04SRajkumar Manoharan ah->btcoex_hw.mci.config = (AR_SREV_9462(ah)) ? 0x2201 : 0xa4c1;
254d3c83ac1SSujith Manoharan }
255d3c83ac1SSujith Manoharan EXPORT_SYMBOL(ath9k_hw_btcoex_init_mci);
256d3c83ac1SSujith Manoharan
ath9k_hw_btcoex_enable_2wire(struct ath_hw * ah)257bc74bf8fSLuis R. Rodriguez static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah)
25817d50d1dSVasanthakumar Thiagarajan {
259766ec4a9SLuis R. Rodriguez struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
260f14462c6SVasanthakumar Thiagarajan
26117d50d1dSVasanthakumar Thiagarajan /* Configure the desired GPIO port for TX_FRAME output */
262b2d70d49SMiaoqing Pan ath9k_hw_gpio_request_out(ah, btcoex_hw->wlanactive_gpio,
263b2d70d49SMiaoqing Pan "ath9k-wlanactive",
26417d50d1dSVasanthakumar Thiagarajan AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
265bc74bf8fSLuis R. Rodriguez }
266bc74bf8fSLuis R. Rodriguez
2675160b46fSSujith Manoharan /*
2685160b46fSSujith Manoharan * For AR9002, bt_weight/wlan_weight are used.
2695160b46fSSujith Manoharan * For AR9003 and above, stomp_type is used.
2705160b46fSSujith Manoharan */
ath9k_hw_btcoex_set_weight(struct ath_hw * ah,u32 bt_weight,u32 wlan_weight,enum ath_stomp_type stomp_type)2715e197292SLuis R. Rodriguez void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
2725e197292SLuis R. Rodriguez u32 bt_weight,
2735160b46fSSujith Manoharan u32 wlan_weight,
2745160b46fSSujith Manoharan enum ath_stomp_type stomp_type)
2755e197292SLuis R. Rodriguez {
2765e197292SLuis R. Rodriguez struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
277db60428bSRajkumar Manoharan struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
278db60428bSRajkumar Manoharan u8 txprio_shift[] = { 24, 16, 16, 0 }; /* tx priority weight */
279db60428bSRajkumar Manoharan bool concur_tx = (mci_hw->concur_tx && btcoex_hw->tx_prio[stomp_type]);
2805160b46fSSujith Manoharan const u32 *weight = ar9003_wlan_weights[stomp_type];
2815160b46fSSujith Manoharan int i;
2825160b46fSSujith Manoharan
283db60428bSRajkumar Manoharan if (!AR_SREV_9300_20_OR_LATER(ah)) {
284db60428bSRajkumar Manoharan btcoex_hw->bt_coex_weights =
285db60428bSRajkumar Manoharan SM(bt_weight, AR_BTCOEX_BT_WGHT) |
286db60428bSRajkumar Manoharan SM(wlan_weight, AR_BTCOEX_WL_WGHT);
287db60428bSRajkumar Manoharan return;
288db60428bSRajkumar Manoharan }
289db60428bSRajkumar Manoharan
2905160b46fSSujith Manoharan if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
291db60428bSRajkumar Manoharan enum ath_stomp_type stype =
292db60428bSRajkumar Manoharan ((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
293db60428bSRajkumar Manoharan btcoex_hw->mci.stomp_ftp) ?
294db60428bSRajkumar Manoharan ATH_BTCOEX_STOMP_LOW_FTP : stomp_type;
295db60428bSRajkumar Manoharan weight = mci_wlan_weights[stype];
2965160b46fSSujith Manoharan }
2975160b46fSSujith Manoharan
2985160b46fSSujith Manoharan for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
2995160b46fSSujith Manoharan btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
3005160b46fSSujith Manoharan btcoex_hw->wlan_weight[i] = weight[i];
301db60428bSRajkumar Manoharan if (concur_tx && i) {
302db60428bSRajkumar Manoharan btcoex_hw->wlan_weight[i] &=
303db60428bSRajkumar Manoharan ~(0xff << txprio_shift[i-1]);
304db60428bSRajkumar Manoharan btcoex_hw->wlan_weight[i] |=
305db60428bSRajkumar Manoharan (btcoex_hw->tx_prio[stomp_type] <<
306db60428bSRajkumar Manoharan txprio_shift[i-1]);
3075160b46fSSujith Manoharan }
3085e197292SLuis R. Rodriguez }
309dfcf02cdSMiaoqing Pan
310db60428bSRajkumar Manoharan /* Last WLAN weight has to be adjusted wrt tx priority */
311db60428bSRajkumar Manoharan if (concur_tx) {
312db60428bSRajkumar Manoharan btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]);
313db60428bSRajkumar Manoharan btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type]
314db60428bSRajkumar Manoharan << txprio_shift[i-1]);
315db60428bSRajkumar Manoharan }
3165160b46fSSujith Manoharan }
3177322fd19SLuis R. Rodriguez EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
3185e197292SLuis R. Rodriguez
319a6ef530fSVivek Natarajan
ath9k_hw_btcoex_enable_3wire(struct ath_hw * ah)320bc74bf8fSLuis R. Rodriguez static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
321bc74bf8fSLuis R. Rodriguez {
32254f10b05SRajkumar Manoharan struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
32321cb9879SVivek Natarajan u32 val;
32454f10b05SRajkumar Manoharan int i;
325bc74bf8fSLuis R. Rodriguez
3261773912bSVasanthakumar Thiagarajan /*
3271773912bSVasanthakumar Thiagarajan * Program coex mode and weight registers to
3281773912bSVasanthakumar Thiagarajan * enable coex 3-wire
3291773912bSVasanthakumar Thiagarajan */
330c7212b71SMiaoqing Pan if (AR_SREV_SOC(ah))
331c7212b71SMiaoqing Pan REG_CLR_BIT(ah, AR_BT_COEX_MODE2, AR_BT_PHY_ERR_BT_COLL_ENABLE);
332c7212b71SMiaoqing Pan
33354f10b05SRajkumar Manoharan REG_WRITE(ah, AR_BT_COEX_MODE, btcoex->bt_coex_mode);
33454f10b05SRajkumar Manoharan REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
3351773912bSVasanthakumar Thiagarajan
336c7212b71SMiaoqing Pan if (AR_SREV_SOC(ah))
337c7212b71SMiaoqing Pan REG_WRITE(ah, AR_BT_COEX_MODE3, btcoex->bt_coex_mode3);
338c7212b71SMiaoqing Pan
339a6ef530fSVivek Natarajan if (AR_SREV_9300_20_OR_LATER(ah)) {
34054f10b05SRajkumar Manoharan REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, btcoex->wlan_weight[0]);
34154f10b05SRajkumar Manoharan REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, btcoex->wlan_weight[1]);
34254f10b05SRajkumar Manoharan for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
34354f10b05SRajkumar Manoharan REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS(i),
34454f10b05SRajkumar Manoharan btcoex->bt_weight[i]);
345a6ef530fSVivek Natarajan } else
34654f10b05SRajkumar Manoharan REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex->bt_coex_weights);
347a6ef530fSVivek Natarajan
34821cb9879SVivek Natarajan if (AR_SREV_9271(ah)) {
34921cb9879SVivek Natarajan val = REG_READ(ah, 0x50040);
35021cb9879SVivek Natarajan val &= 0xFFFFFEFF;
35121cb9879SVivek Natarajan REG_WRITE(ah, 0x50040, val);
35221cb9879SVivek Natarajan }
35321cb9879SVivek Natarajan
354bc74bf8fSLuis R. Rodriguez REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
355bc74bf8fSLuis R. Rodriguez REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
3561773912bSVasanthakumar Thiagarajan
357b2d70d49SMiaoqing Pan ath9k_hw_gpio_request_out(ah, btcoex->wlanactive_gpio,
358b2d70d49SMiaoqing Pan "ath9k-wlanactive",
3591773912bSVasanthakumar Thiagarajan AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
3601773912bSVasanthakumar Thiagarajan }
3611773912bSVasanthakumar Thiagarajan
ath9k_hw_btcoex_enable_mci(struct ath_hw * ah)3628227bf45SRajkumar Manoharan static void ath9k_hw_btcoex_enable_mci(struct ath_hw *ah)
3638227bf45SRajkumar Manoharan {
3648227bf45SRajkumar Manoharan struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
3658227bf45SRajkumar Manoharan int i;
3668227bf45SRajkumar Manoharan
3678227bf45SRajkumar Manoharan for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
3688227bf45SRajkumar Manoharan REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i),
3698227bf45SRajkumar Manoharan btcoex->wlan_weight[i]);
3708227bf45SRajkumar Manoharan
3718227bf45SRajkumar Manoharan REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
3728227bf45SRajkumar Manoharan btcoex->enabled = true;
3738227bf45SRajkumar Manoharan }
3748227bf45SRajkumar Manoharan
ath9k_hw_btcoex_disable_mci(struct ath_hw * ah)375e1ff147dSSujith Manoharan static void ath9k_hw_btcoex_disable_mci(struct ath_hw *ah)
376e1ff147dSSujith Manoharan {
377e1ff147dSSujith Manoharan struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
378e1ff147dSSujith Manoharan int i;
379e1ff147dSSujith Manoharan
380e1ff147dSSujith Manoharan ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
381e1ff147dSSujith Manoharan
382e1ff147dSSujith Manoharan for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
383e1ff147dSSujith Manoharan REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i),
384e1ff147dSSujith Manoharan btcoex_hw->wlan_weight[i]);
385e1ff147dSSujith Manoharan }
386e1ff147dSSujith Manoharan
ath9k_hw_btcoex_enable(struct ath_hw * ah)387bc74bf8fSLuis R. Rodriguez void ath9k_hw_btcoex_enable(struct ath_hw *ah)
388bc74bf8fSLuis R. Rodriguez {
389766ec4a9SLuis R. Rodriguez struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
390bc74bf8fSLuis R. Rodriguez
3918a309305SFelix Fietkau switch (ath9k_hw_get_btcoex_scheme(ah)) {
392bc74bf8fSLuis R. Rodriguez case ATH_BTCOEX_CFG_NONE:
3938a309305SFelix Fietkau return;
394bc74bf8fSLuis R. Rodriguez case ATH_BTCOEX_CFG_2WIRE:
395bc74bf8fSLuis R. Rodriguez ath9k_hw_btcoex_enable_2wire(ah);
396bc74bf8fSLuis R. Rodriguez break;
397bc74bf8fSLuis R. Rodriguez case ATH_BTCOEX_CFG_3WIRE:
3980466e254SRajkumar Manoharan ath9k_hw_btcoex_enable_3wire(ah);
3990466e254SRajkumar Manoharan break;
400e1ff147dSSujith Manoharan case ATH_BTCOEX_CFG_MCI:
401e1ff147dSSujith Manoharan ath9k_hw_btcoex_enable_mci(ah);
402e1ff147dSSujith Manoharan break;
4030466e254SRajkumar Manoharan }
404bc74bf8fSLuis R. Rodriguez
405dfcf02cdSMiaoqing Pan if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI &&
406dfcf02cdSMiaoqing Pan !AR_SREV_SOC(ah)) {
407*b3a663f0SWenli Looi REG_RMW(ah, AR_GPIO_PDPU(ah),
408766ec4a9SLuis R. Rodriguez (0x2 << (btcoex_hw->btactive_gpio * 2)),
409766ec4a9SLuis R. Rodriguez (0x3 << (btcoex_hw->btactive_gpio * 2)));
410e1ff147dSSujith Manoharan }
41117d50d1dSVasanthakumar Thiagarajan
412766ec4a9SLuis R. Rodriguez ah->btcoex_hw.enabled = true;
41317d50d1dSVasanthakumar Thiagarajan }
4147322fd19SLuis R. Rodriguez EXPORT_SYMBOL(ath9k_hw_btcoex_enable);
41517d50d1dSVasanthakumar Thiagarajan
ath9k_hw_btcoex_disable(struct ath_hw * ah)41617d50d1dSVasanthakumar Thiagarajan void ath9k_hw_btcoex_disable(struct ath_hw *ah)
41717d50d1dSVasanthakumar Thiagarajan {
418766ec4a9SLuis R. Rodriguez struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
41954f10b05SRajkumar Manoharan int i;
42017d50d1dSVasanthakumar Thiagarajan
4218227bf45SRajkumar Manoharan btcoex_hw->enabled = false;
422e1ff147dSSujith Manoharan
423e1ff147dSSujith Manoharan if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_MCI) {
424e1ff147dSSujith Manoharan ath9k_hw_btcoex_disable_mci(ah);
4250466e254SRajkumar Manoharan return;
4268227bf45SRajkumar Manoharan }
427e1ff147dSSujith Manoharan
42830b81898SSujith Manoharan if (!AR_SREV_9300_20_OR_LATER(ah))
429766ec4a9SLuis R. Rodriguez ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
430f14462c6SVasanthakumar Thiagarajan
431b2d70d49SMiaoqing Pan ath9k_hw_gpio_request_out(ah, btcoex_hw->wlanactive_gpio,
432b2d70d49SMiaoqing Pan NULL, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
43317d50d1dSVasanthakumar Thiagarajan
434766ec4a9SLuis R. Rodriguez if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) {
4351773912bSVasanthakumar Thiagarajan REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
4361773912bSVasanthakumar Thiagarajan REG_WRITE(ah, AR_BT_COEX_MODE2, 0);
437a6ef530fSVivek Natarajan
438a6ef530fSVivek Natarajan if (AR_SREV_9300_20_OR_LATER(ah)) {
439a6ef530fSVivek Natarajan REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0);
440a6ef530fSVivek Natarajan REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0);
44154f10b05SRajkumar Manoharan for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
44254f10b05SRajkumar Manoharan REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS(i), 0);
443a6ef530fSVivek Natarajan } else
444a6ef530fSVivek Natarajan REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
445a6ef530fSVivek Natarajan
4461773912bSVasanthakumar Thiagarajan }
44717d50d1dSVasanthakumar Thiagarajan }
4487322fd19SLuis R. Rodriguez EXPORT_SYMBOL(ath9k_hw_btcoex_disable);
449978f78bfSVivek Natarajan
450978f78bfSVivek Natarajan /*
451978f78bfSVivek Natarajan * Configures appropriate weight based on stomp type.
452978f78bfSVivek Natarajan */
ath9k_hw_btcoex_bt_stomp(struct ath_hw * ah,enum ath_stomp_type stomp_type)453978f78bfSVivek Natarajan void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
454978f78bfSVivek Natarajan enum ath_stomp_type stomp_type)
455978f78bfSVivek Natarajan {
456978f78bfSVivek Natarajan if (AR_SREV_9300_20_OR_LATER(ah)) {
4575160b46fSSujith Manoharan ath9k_hw_btcoex_set_weight(ah, 0, 0, stomp_type);
458978f78bfSVivek Natarajan return;
459978f78bfSVivek Natarajan }
460978f78bfSVivek Natarajan
461978f78bfSVivek Natarajan switch (stomp_type) {
462978f78bfSVivek Natarajan case ATH_BTCOEX_STOMP_ALL:
463978f78bfSVivek Natarajan ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
4645160b46fSSujith Manoharan AR_STOMP_ALL_WLAN_WGHT, 0);
465978f78bfSVivek Natarajan break;
466978f78bfSVivek Natarajan case ATH_BTCOEX_STOMP_LOW:
467978f78bfSVivek Natarajan ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
4685160b46fSSujith Manoharan AR_STOMP_LOW_WLAN_WGHT, 0);
469978f78bfSVivek Natarajan break;
470978f78bfSVivek Natarajan case ATH_BTCOEX_STOMP_NONE:
471978f78bfSVivek Natarajan ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
4725160b46fSSujith Manoharan AR_STOMP_NONE_WLAN_WGHT, 0);
473978f78bfSVivek Natarajan break;
474978f78bfSVivek Natarajan default:
475d2182b69SJoe Perches ath_dbg(ath9k_hw_common(ah), BTCOEX, "Invalid Stomptype\n");
476978f78bfSVivek Natarajan break;
477978f78bfSVivek Natarajan }
478978f78bfSVivek Natarajan }
479978f78bfSVivek Natarajan EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp);
480db60428bSRajkumar Manoharan
ath9k_hw_btcoex_set_concur_txprio(struct ath_hw * ah,u8 * stomp_txprio)481db60428bSRajkumar Manoharan void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio)
482db60428bSRajkumar Manoharan {
483db60428bSRajkumar Manoharan struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
484db60428bSRajkumar Manoharan int i;
485db60428bSRajkumar Manoharan
486db60428bSRajkumar Manoharan for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
487db60428bSRajkumar Manoharan btcoex->tx_prio[i] = stomp_txprio[i];
488db60428bSRajkumar Manoharan }
489db60428bSRajkumar Manoharan EXPORT_SYMBOL(ath9k_hw_btcoex_set_concur_txprio);
490