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