htc_drv_gpio.c revision d2182b69dcb6a68b1ef6070b2efd094e13dea3f1
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
11821cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
11921cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
12021cb987914cb5334af78378141efed77505ea987Vivek Natarajan		btcoex->btcoex_period / 100;
12121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
12221cb987914cb5334af78378141efed77505ea987Vivek Natarajan				   btcoex->btcoex_period / 100;
12321cb987914cb5334af78378141efed77505ea987Vivek Natarajan	INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work);
12421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work);
12521cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
12621cb987914cb5334af78378141efed77505ea987Vivek Natarajan
12721cb987914cb5334af78378141efed77505ea987Vivek Natarajan/*
12821cb987914cb5334af78378141efed77505ea987Vivek Natarajan * (Re)start btcoex work
12921cb987914cb5334af78378141efed77505ea987Vivek Natarajan */
13021cb987914cb5334af78378141efed77505ea987Vivek Natarajan
13121cb987914cb5334af78378141efed77505ea987Vivek Natarajanvoid ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
13221cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
13321cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_btcoex *btcoex = &priv->btcoex;
13421cb987914cb5334af78378141efed77505ea987Vivek Natarajan	struct ath_hw *ah = priv->ah;
13521cb987914cb5334af78378141efed77505ea987Vivek Natarajan
136d2182b69dcb6a68b1ef6070b2efd094e13dea3f1Joe Perches	ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex work\n");
13721cb987914cb5334af78378141efed77505ea987Vivek Natarajan
13821cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->bt_priority_cnt = 0;
13921cb987914cb5334af78378141efed77505ea987Vivek Natarajan	btcoex->bt_priority_time = jiffies;
14021cb987914cb5334af78378141efed77505ea987Vivek Natarajan	priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
14121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
14221cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
14321cb987914cb5334af78378141efed77505ea987Vivek Natarajan
14421cb987914cb5334af78378141efed77505ea987Vivek Natarajan
14521cb987914cb5334af78378141efed77505ea987Vivek Natarajan/*
14621cb987914cb5334af78378141efed77505ea987Vivek Natarajan * Cancel btcoex and bt duty cycle work.
14721cb987914cb5334af78378141efed77505ea987Vivek Natarajan */
14821cb987914cb5334af78378141efed77505ea987Vivek Natarajanvoid ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
14921cb987914cb5334af78378141efed77505ea987Vivek Natarajan{
15021cb987914cb5334af78378141efed77505ea987Vivek Natarajan	cancel_delayed_work_sync(&priv->coex_period_work);
15121cb987914cb5334af78378141efed77505ea987Vivek Natarajan	cancel_delayed_work_sync(&priv->duty_cycle_work);
15221cb987914cb5334af78378141efed77505ea987Vivek Natarajan}
1531e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1541e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*******/
1551e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/* LED */
1561e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*******/
1571e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
158d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan#ifdef CONFIG_MAC80211_LEDS
159d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharanvoid ath9k_led_work(struct work_struct *work)
1601e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
161d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	struct ath9k_htc_priv *priv = container_of(work,
162d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan						   struct ath9k_htc_priv,
163d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan						   led_work);
1641e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
165d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
166d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan			  (priv->brightness == LED_OFF));
1671e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
1681e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1691e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanstatic void ath9k_led_brightness(struct led_classdev *led_cdev,
1701e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan				 enum led_brightness brightness)
1711e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
172d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	struct ath9k_htc_priv *priv = container_of(led_cdev,
173d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan						   struct ath9k_htc_priv,
174d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan						   led_cdev);
1751e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
176d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	/* Not locked, but it's just a tiny green light..*/
177d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	priv->brightness = brightness;
178d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	ieee80211_queue_work(priv->hw, &priv->led_work);
1791e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
1801e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1811e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_deinit_leds(struct ath9k_htc_priv *priv)
1821e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
183d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	if (!priv->led_registered)
184d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan		return;
185d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan
186d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	ath9k_led_brightness(&priv->led_cdev, LED_OFF);
187d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	led_classdev_unregister(&priv->led_cdev);
188d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	cancel_work_sync(&priv->led_work);
1891e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
1901e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1911e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_init_leds(struct ath9k_htc_priv *priv)
1921e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
1931e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	int ret;
1941e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
1951e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (AR_SREV_9287(priv->ah))
1961e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		priv->ah->led_pin = ATH_LED_PIN_9287;
1971e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	else if (AR_SREV_9271(priv->ah))
1981e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		priv->ah->led_pin = ATH_LED_PIN_9271;
1991e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	else if (AR_DEVID_7010(priv->ah))
2001e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		priv->ah->led_pin = ATH_LED_PIN_7010;
2011e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	else
2021e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		priv->ah->led_pin = ATH_LED_PIN_DEF;
2031e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2041e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Configure gpio 1 for output */
2051e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
2061e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
2071e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* LED off, active low */
2081e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
2091e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
210d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	snprintf(priv->led_name, sizeof(priv->led_name),
211d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan		"ath9k_htc-%s", wiphy_name(priv->hw->wiphy));
212d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	priv->led_cdev.name = priv->led_name;
213d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	priv->led_cdev.brightness_set = ath9k_led_brightness;
2141e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
215d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &priv->led_cdev);
216d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	if (ret < 0)
217d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan		return;
2181e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
219d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	INIT_WORK(&priv->led_work, ath9k_led_work);
220d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	priv->led_registered = true;
221d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan
222d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan	return;
2231e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
224d244f21e79162b829c9af09845421d9b4fac4253Sujith Manoharan#endif
2251e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2261e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*******************/
2271e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*	Rfkill	   */
2281e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan/*******************/
2291e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2301e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanstatic bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
2311e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
23290826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	bool is_blocked;
23390826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan
23490826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	ath9k_htc_ps_wakeup(priv);
23590826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	is_blocked = ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
23690826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan						 priv->ah->rfkill_polarity;
23790826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	ath9k_htc_ps_restore(priv);
23890826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan
23990826313fd69d198da7574779460f793765abfa5Mohammed Shafi Shajakhan	return is_blocked;
2401e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
2411e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2421e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
2431e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
2441e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath9k_htc_priv *priv = hw->priv;
2451e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	bool blocked = !!ath_is_rfkill_set(priv);
2461e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2471e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
2481e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
2491e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2501e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
2511e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
2521e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
2531e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		wiphy_rfkill_start_polling(priv->hw->wiphy);
2541e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
2551e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2561e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_htc_radio_enable(struct ieee80211_hw *hw)
2571e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
2581e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath9k_htc_priv *priv = hw->priv;
2591e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath_hw *ah = priv->ah;
2601e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath_common *common = ath9k_hw_common(ah);
2611e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	int ret;
2621e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	u8 cmd_rsp;
2631e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2641e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (!ah->curchan)
2651e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
2661e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2671e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Reset the HW */
2681e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
2691e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (ret) {
2701e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		ath_err(common,
2711e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
2721e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			ret, ah->curchan->channel);
2731e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	}
2741e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
275b2a5c3dfecf3d0e1db08ac7cd94ee4c1cf9bc998Rajkumar Manoharan	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
276b2a5c3dfecf3d0e1db08ac7cd94ee4c1cf9bc998Rajkumar Manoharan			       &priv->curtxpow);
2771e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2781e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Start RX */
2791e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_START_RECV_CMDID);
2801e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_host_rx_init(priv);
2811e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2821e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Start TX */
2831e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	htc_start(priv->htc);
284658ef04fd42a587b17a379ad9208023473442dddSujith Manoharan	spin_lock_bh(&priv->tx.tx_lock);
2858e86a54715c4102a8ed697939de9ebd9715dc59cSujith Manoharan	priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP;
286658ef04fd42a587b17a379ad9208023473442dddSujith Manoharan	spin_unlock_bh(&priv->tx.tx_lock);
2871e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ieee80211_wake_queues(hw);
2881e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2891e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_ENABLE_INTR_CMDID);
2901e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2911e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Enable LED */
2921e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_cfg_output(ah, ah->led_pin,
2931e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
2941e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
2951e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
2961e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
2971e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharanvoid ath9k_htc_radio_disable(struct ieee80211_hw *hw)
2981e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan{
2991e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath9k_htc_priv *priv = hw->priv;
3001e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath_hw *ah = priv->ah;
3011e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	struct ath_common *common = ath9k_hw_common(ah);
3021e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	int ret;
3031e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	u8 cmd_rsp;
3041e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3051e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_htc_ps_wakeup(priv);
3061e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3071e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Disable LED */
3081e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
3091e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
3101e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3111e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_DISABLE_INTR_CMDID);
3121e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3131e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Stop TX */
3141e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ieee80211_stop_queues(hw);
315b587fc81a80b9656f64e89fe0a106ffa4b35abcaSujith Manoharan	ath9k_htc_tx_drain(priv);
3161e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
3171e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3181e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Stop RX */
3191e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	WMI_CMD(WMI_STOP_RECV_CMDID);
3201e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
321f4c88991f51e097b6541f998fd23d477999e5886Sujith Manoharan	/* Clear the WMI event queue */
322f4c88991f51e097b6541f998fd23d477999e5886Sujith Manoharan	ath9k_wmi_event_drain(priv);
323f4c88991f51e097b6541f998fd23d477999e5886Sujith Manoharan
3241e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/*
3251e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	 * The MIB counters have to be disabled here,
3261e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	 * since the target doesn't do it.
3271e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	 */
3281e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_disable_mib_counters(ah);
3291e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3301e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (!ah->curchan)
3311e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
3321e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3331e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Reset the HW */
3341e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
3351e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	if (ret) {
3361e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan		ath_err(common,
3371e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
3381e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan			ret, ah->curchan->channel);
3391e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	}
3401e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3411e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	/* Disable the PHY */
3421e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_hw_phy_disable(ah);
3431e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan
3441e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_htc_ps_restore(priv);
3451e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
3461e1f4ad25fab29ca48b1166e74a81e9c89ddf0fbSujith Manoharan}
347