11e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*
25b68138e5659cbfd5df2879d17f9ba0b66477fecSujith Manoharan * Copyright (c) 2010-2011 Atheros Communications Inc.
31e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan *
41e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * Permission to use, copy, modify, and/or distribute this software for any
51e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * purpose with or without fee is hereby granted, provided that the above
61e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * copyright notice and this permission notice appear in all copies.
71e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan *
81e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
91e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
101e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
111e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
121e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
131e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
141e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
151e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan */
161e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1721cb987914cb5334af78378141efed77505ea987Vivek Natarajan#include "htc.h"
1821cb987914cb5334af78378141efed77505ea987Vivek Natarajan
1921cb987914cb5334af78378141efed77505ea987Vivek Natarajan/******************/
2021cb987914cb5334af78378141efed77505ea987Vivek Natarajan/*     BTCOEX     */
2121cb987914cb5334af78378141efed77505ea987Vivek Natarajan/******************/
2221cb987914cb5334af78378141efed77505ea987Vivek Natarajan
2321cb987914cb5334af78378141efed77505ea987Vivek Natarajan/*
2421cb987914cb5334af78378141efed77505ea987Vivek Natarajan * Detects if there is any priority bt traffic
2521cb987914cb5334af78378141efed77505ea987Vivek Natarajan */
2621cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
2721cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
2821cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_btcoex *btcoex = &priv->btcoex;
2921cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_hw *ah = priv->ah;
3021cb987914cb5334af78378141efed77505ea987Vivek Natarajan
3121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio))
3221cb987914cb5334af78378141efed77505ea987Vivek Natarajan		btcoex->bt_priority_cnt++;
3321cb987914cb5334af78378141efed77505ea987Vivek Natarajan
3421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	if (time_after(jiffies, btcoex->bt_priority_time +
3521cb987914cb5334af78378141efed77505ea987Vivek Natarajan			msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
3621cb987914cb5334af78378141efed77505ea987Vivek Natarajan		priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
3721cb987914cb5334af78378141efed77505ea987Vivek Natarajan		/* Detect if colocated bt started scanning */
3821cb987914cb5334af78378141efed77505ea987Vivek Natarajan		if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
39d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches			ath_dbg(ath9k_hw_common(ah), BTCOEX,
40226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches				"BT scan detected\n");
4121cb987914cb5334af78378141efed77505ea987Vivek Natarajan			priv->op_flags |= (OP_BT_SCAN |
4221cb987914cb5334af78378141efed77505ea987Vivek Natarajan					 OP_BT_PRIORITY_DETECTED);
4321cb987914cb5334af78378141efed77505ea987Vivek Natarajan		} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
44d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches			ath_dbg(ath9k_hw_common(ah), BTCOEX,
45226afe68fdbd1aa3680158aca0a3631cbd019626Joe Perches				"BT priority traffic detected\n");
4621cb987914cb5334af78378141efed77505ea987Vivek Natarajan			priv->op_flags |= OP_BT_PRIORITY_DETECTED;
4721cb987914cb5334af78378141efed77505ea987Vivek Natarajan		}
4821cb987914cb5334af78378141efed77505ea987Vivek Natarajan
4921cb987914cb5334af78378141efed77505ea987Vivek Natarajan		btcoex->bt_priority_cnt = 0;
5021cb987914cb5334af78378141efed77505ea987Vivek Natarajan		btcoex->bt_priority_time = jiffies;
5121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	}
5221cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
5321cb987914cb5334af78378141efed77505ea987Vivek Natarajan
5421cb987914cb5334af78378141efed77505ea987Vivek Natarajan/*
5521cb987914cb5334af78378141efed77505ea987Vivek Natarajan * This is the master bt coex work which runs for every
5621cb987914cb5334af78378141efed77505ea987Vivek Natarajan * 45ms, bt traffic will be given priority during 55% of this
5721cb987914cb5334af78378141efed77505ea987Vivek Natarajan * period while wlan gets remaining 45%
5821cb987914cb5334af78378141efed77505ea987Vivek Natarajan */
5921cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic void ath_btcoex_period_work(struct work_struct *work)
6021cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
6121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
6221cb987914cb5334af78378141efed77505ea987Vivek Natarajan						   coex_period_work.work);
6321cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_btcoex *btcoex = &priv->btcoex;
6421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_common *common = ath9k_hw_common(priv->ah);
6521cb987914cb5334af78378141efed77505ea987Vivek Natarajan	u32 timer_period;
6621cb987914cb5334af78378141efed77505ea987Vivek Natarajan	bool is_btscan;
6721cb987914cb5334af78378141efed77505ea987Vivek Natarajan	int ret;
6821cb987914cb5334af78378141efed77505ea987Vivek Natarajan
6921cb987914cb5334af78378141efed77505ea987Vivek Natarajan	ath_detect_bt_priority(priv);
7021cb987914cb5334af78378141efed77505ea987Vivek Natarajan
7121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	is_btscan = !!(priv->op_flags & OP_BT_SCAN);
7221cb987914cb5334af78378141efed77505ea987Vivek Natarajan
733a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan	ret = ath9k_htc_update_cap_target(priv,
743a0593efd191c7eb13c79179c4c5ddbc519b2510Sujith Manoharan				  !!(priv->op_flags & OP_BT_PRIORITY_DETECTED));
750ff2b5c05d4dd84222a8e163335c5b550e2ca195Sujith Manoharan	if (ret) {
760ff2b5c05d4dd84222a8e163335c5b550e2ca195Sujith Manoharan		ath_err(common, "Unable to set BTCOEX parameters\n");
770ff2b5c05d4dd84222a8e163335c5b550e2ca195Sujith Manoharan		return;
780ff2b5c05d4dd84222a8e163335c5b550e2ca195Sujith Manoharan	}
7921cb987914cb5334af78378141efed77505ea987Vivek Natarajan
80978f78bf71372a48785ac9407ebc10170f14f56cVivek Natarajan	ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
8121cb987914cb5334af78378141efed77505ea987Vivek Natarajan			btcoex->bt_stomp_type);
8221cb987914cb5334af78378141efed77505ea987Vivek Natarajan
83bc6d5c29afa724901c2feb7e4446c6eec7788cecRajkumar Manoharan	ath9k_hw_btcoex_enable(priv->ah);
8421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	timer_period = is_btscan ? btcoex->btscan_no_stomp :
8521cb987914cb5334af78378141efed77505ea987Vivek Natarajan		btcoex->btcoex_no_stomp;
8621cb987914cb5334af78378141efed77505ea987Vivek Natarajan	ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
8721cb987914cb5334af78378141efed77505ea987Vivek Natarajan				     msecs_to_jiffies(timer_period));
8821cb987914cb5334af78378141efed77505ea987Vivek Natarajan	ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work,
8921cb987914cb5334af78378141efed77505ea987Vivek Natarajan				     msecs_to_jiffies(btcoex->btcoex_period));
9021cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
9121cb987914cb5334af78378141efed77505ea987Vivek Natarajan
9221cb987914cb5334af78378141efed77505ea987Vivek Natarajan/*
9321cb987914cb5334af78378141efed77505ea987Vivek Natarajan * Work to time slice between wlan and bt traffic and
9421cb987914cb5334af78378141efed77505ea987Vivek Natarajan * configure weight registers
9521cb987914cb5334af78378141efed77505ea987Vivek Natarajan */
9621cb987914cb5334af78378141efed77505ea987Vivek Natarajanstatic void ath_btcoex_duty_cycle_work(struct work_struct *work)
9721cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
9821cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
9921cb987914cb5334af78378141efed77505ea987Vivek Natarajan						   duty_cycle_work.work);
10021cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_hw *ah = priv->ah;
10121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_btcoex *btcoex = &priv->btcoex;
10221cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_common *common = ath9k_hw_common(ah);
10321cb987914cb5334af78378141efed77505ea987Vivek Natarajan	bool is_btscan = priv->op_flags & OP_BT_SCAN;
10421cb987914cb5334af78378141efed77505ea987Vivek Natarajan
105d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches	ath_dbg(common, BTCOEX, "time slice work for bt and wlan\n");
10621cb987914cb5334af78378141efed77505ea987Vivek Natarajan
10721cb987914cb5334af78378141efed77505ea987Vivek Natarajan	if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
108978f78bf71372a48785ac9407ebc10170f14f56cVivek Natarajan		ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
10921cb987914cb5334af78378141efed77505ea987Vivek Natarajan	else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
110978f78bf71372a48785ac9407ebc10170f14f56cVivek Natarajan		ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
111bc6d5c29afa724901c2feb7e4446c6eec7788cecRajkumar Manoharan	ath9k_hw_btcoex_enable(priv->ah);
11221cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
11321cb987914cb5334af78378141efed77505ea987Vivek Natarajan
11421cb987914cb5334af78378141efed77505ea987Vivek Natarajanvoid ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv)
11521cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
11621cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_btcoex *btcoex = &priv->btcoex;
11721cb987914cb5334af78378141efed77505ea987Vivek Natarajan
1188a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau	if (ath9k_hw_get_btcoex_scheme(priv->ah) == ATH_BTCOEX_CFG_NONE)
1198a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau		return;
1208a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau
12121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
12221cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
12321cb987914cb5334af78378141efed77505ea987Vivek Natarajan		btcoex->btcoex_period / 100;
12421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
12521cb987914cb5334af78378141efed77505ea987Vivek Natarajan				   btcoex->btcoex_period / 100;
12621cb987914cb5334af78378141efed77505ea987Vivek Natarajan	INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work);
12721cb987914cb5334af78378141efed77505ea987Vivek Natarajan	INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work);
12821cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
12921cb987914cb5334af78378141efed77505ea987Vivek Natarajan
13021cb987914cb5334af78378141efed77505ea987Vivek Natarajan/*
13121cb987914cb5334af78378141efed77505ea987Vivek Natarajan * (Re)start btcoex work
13221cb987914cb5334af78378141efed77505ea987Vivek Natarajan */
13321cb987914cb5334af78378141efed77505ea987Vivek Natarajan
13421cb987914cb5334af78378141efed77505ea987Vivek Natarajanvoid ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
13521cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
13621cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_btcoex *btcoex = &priv->btcoex;
13721cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_hw *ah = priv->ah;
13821cb987914cb5334af78378141efed77505ea987Vivek Natarajan
1398a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau	if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
1408a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau		return;
1418a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau
142d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches	ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex work\n");
14321cb987914cb5334af78378141efed77505ea987Vivek Natarajan
14421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->bt_priority_cnt = 0;
14521cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->bt_priority_time = jiffies;
14621cb987914cb5334af78378141efed77505ea987Vivek Natarajan	priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
14721cb987914cb5334af78378141efed77505ea987Vivek Natarajan	ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
14821cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
14921cb987914cb5334af78378141efed77505ea987Vivek Natarajan
15021cb987914cb5334af78378141efed77505ea987Vivek Natarajan
15121cb987914cb5334af78378141efed77505ea987Vivek Natarajan/*
15221cb987914cb5334af78378141efed77505ea987Vivek Natarajan * Cancel btcoex and bt duty cycle work.
15321cb987914cb5334af78378141efed77505ea987Vivek Natarajan */
15421cb987914cb5334af78378141efed77505ea987Vivek Natarajanvoid ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
15521cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
1568a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau	if (ath9k_hw_get_btcoex_scheme(priv->ah) == ATH_BTCOEX_CFG_NONE)
1578a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau		return;
1588a30930563521c9dba73c93b5631be1d0993f78fFelix Fietkau
15921cb987914cb5334af78378141efed77505ea987Vivek Natarajan	cancel_delayed_work_sync(&priv->coex_period_work);
16021cb987914cb5334af78378141efed77505ea987Vivek Natarajan	cancel_delayed_work_sync(&priv->duty_cycle_work);
16121cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
1621e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1631e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*******/
1641e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/* LED */
1651e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*******/
1661e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
167d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan#ifdef CONFIG_MAC80211_LEDS
168d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharanvoid ath9k_led_work(struct work_struct *work)
1691e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
170d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	struct ath9k_htc_priv *priv = container_of(work,
171d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan						   struct ath9k_htc_priv,
172d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan						   led_work);
1731e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
174d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
175d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan			  (priv->brightness == LED_OFF));
1761e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
1771e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1781e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanstatic void ath9k_led_brightness(struct led_classdev *led_cdev,
1791e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan				 enum led_brightness brightness)
1801e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
181d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	struct ath9k_htc_priv *priv = container_of(led_cdev,
182d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan						   struct ath9k_htc_priv,
183d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan						   led_cdev);
1841e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
185d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	/* Not locked, but it's just a tiny green light..*/
186d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	priv->brightness = brightness;
187d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	ieee80211_queue_work(priv->hw, &priv->led_work);
1881e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
1891e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1901e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_deinit_leds(struct ath9k_htc_priv *priv)
1911e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
192d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	if (!priv->led_registered)
193d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan		return;
194d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan
195d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	ath9k_led_brightness(&priv->led_cdev, LED_OFF);
196d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	led_classdev_unregister(&priv->led_cdev);
197d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	cancel_work_sync(&priv->led_work);
1981e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
1991e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2001e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_init_leds(struct ath9k_htc_priv *priv)
2011e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
2021e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	int ret;
2031e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2041e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (AR_SREV_9287(priv->ah))
2051e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		priv->ah->led_pin = ATH_LED_PIN_9287;
2061e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	else if (AR_SREV_9271(priv->ah))
2071e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		priv->ah->led_pin = ATH_LED_PIN_9271;
2081e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	else if (AR_DEVID_7010(priv->ah))
2091e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		priv->ah->led_pin = ATH_LED_PIN_7010;
2101e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	else
2111e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		priv->ah->led_pin = ATH_LED_PIN_DEF;
2121e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2131e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Configure gpio 1 for output */
2141e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
2151e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
2161e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* LED off, active low */
2171e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
2181e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
219d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	snprintf(priv->led_name, sizeof(priv->led_name),
220d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan		"ath9k_htc-%s", wiphy_name(priv->hw->wiphy));
221d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	priv->led_cdev.name = priv->led_name;
222d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	priv->led_cdev.brightness_set = ath9k_led_brightness;
2231e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
224d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &priv->led_cdev);
225d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	if (ret < 0)
226d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan		return;
2271e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
228d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	INIT_WORK(&priv->led_work, ath9k_led_work);
229d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	priv->led_registered = true;
230d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan
231d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	return;
2321e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
233d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan#endif
2341e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2351e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*******************/
2361e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*	Rfkill	   */
2371e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*******************/
2381e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2391e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanstatic bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
2401e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
24190826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	bool is_blocked;
24290826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan
24390826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	ath9k_htc_ps_wakeup(priv);
24490826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	is_blocked = ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
24590826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan						 priv->ah->rfkill_polarity;
24690826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	ath9k_htc_ps_restore(priv);
24790826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan
24890826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	return is_blocked;
2491e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
2501e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2511e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
2521e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
2531e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath9k_htc_priv *priv = hw->priv;
2541e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	bool blocked = !!ath_is_rfkill_set(priv);
2551e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2561e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
2571e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
2581e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2591e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
2601e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
2611e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
2621e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		wiphy_rfkill_start_polling(priv->hw->wiphy);
2631e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
2641e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2651e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_htc_radio_enable(struct ieee80211_hw *hw)
2661e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
2671e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath9k_htc_priv *priv = hw->priv;
2681e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath_hw *ah = priv->ah;
2691e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath_common *common = ath9k_hw_common(ah);
2701e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	int ret;
2711e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	u8 cmd_rsp;
2721e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2731e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (!ah->curchan)
2741e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
2751e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2761e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Reset the HW */
2771e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
2781e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (ret) {
2791e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		ath_err(common,
2801e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
2811e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			ret, ah->curchan->channel);
2821e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	}
2831e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
284b2a5c3dfecf3d0e1db08ac7cd94ee4c1cf9bc998Rajkumar Manoharan	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
285b2a5c3dfecf3d0e1db08ac7cd94ee4c1cf9bc998Rajkumar Manoharan			       &priv->curtxpow);
2861e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2871e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Start RX */
2881e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_START_RECV_CMDID);
2891e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_host_rx_init(priv);
2901e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2911e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Start TX */
2921e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	htc_start(priv->htc);
293658ef04fd42a587b17a379ad9208023473442dddSujith Manoharan	spin_lock_bh(&priv->tx.tx_lock);
2948e86a54715c4102a8ed697939de9ebd9715dc59cSujith Manoharan	priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
295658ef04fd42a587b17a379ad9208023473442dddSujith Manoharan	spin_unlock_bh(&priv->tx.tx_lock);
2961e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ieee80211_wake_queues(hw);
2971e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2981e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_ENABLE_INTR_CMDID);
2991e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3001e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Enable LED */
3011e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_cfg_output(ah, ah->led_pin,
3021e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
3031e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
3041e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
3051e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3061e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_htc_radio_disable(struct ieee80211_hw *hw)
3071e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
3081e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath9k_htc_priv *priv = hw->priv;
3091e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath_hw *ah = priv->ah;
3101e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath_common *common = ath9k_hw_common(ah);
3111e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	int ret;
3121e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	u8 cmd_rsp;
3131e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3141e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_htc_ps_wakeup(priv);
3151e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3161e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Disable LED */
3171e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
3181e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
3191e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3201e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_DISABLE_INTR_CMDID);
3211e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3221e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Stop TX */
3231e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ieee80211_stop_queues(hw);
324b587fc81a80b9656f64e89fe0a106ffa4b35abcaSujith Manoharan	ath9k_htc_tx_drain(priv);
3251e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
3261e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3271e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Stop RX */
3281e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_STOP_RECV_CMDID);
3291e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
330f4c88991f51e097b6541f998fd23d477999e5886Sujith Manoharan	/* Clear the WMI event queue */
331f4c88991f51e097b6541f998fd23d477999e5886Sujith Manoharan	ath9k_wmi_event_drain(priv);
332f4c88991f51e097b6541f998fd23d477999e5886Sujith Manoharan
3331e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/*
3341e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	 * The MIB counters have to be disabled here,
3351e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	 * since the target doesn't do it.
3361e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	 */
3371e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_disable_mib_counters(ah);
3381e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3391e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (!ah->curchan)
3401e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
3411e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3421e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Reset the HW */
3431e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
3441e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (ret) {
3451e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		ath_err(common,
3461e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
3471e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			ret, ah->curchan->channel);
3481e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	}
3491e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3501e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Disable the PHY */
3511e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_phy_disable(ah);
3521e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3531e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_htc_ps_restore(priv);
3541e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
3551e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
356