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