ath9k_htc: Move LED/RFKILL code to htc_drv_gpio.c
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / htc_drv_gpio.c
1 /*
2  * Copyright (c) 2010 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include "htc.h"
18
19 /******************/
20 /*     BTCOEX     */
21 /******************/
22
23 /*
24  * Detects if there is any priority bt traffic
25  */
26 static void ath_detect_bt_priority(struct ath9k_htc_priv *priv)
27 {
28         struct ath_btcoex *btcoex = &priv->btcoex;
29         struct ath_hw *ah = priv->ah;
30
31         if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio))
32                 btcoex->bt_priority_cnt++;
33
34         if (time_after(jiffies, btcoex->bt_priority_time +
35                         msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
36                 priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
37                 /* Detect if colocated bt started scanning */
38                 if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
39                         ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
40                                 "BT scan detected\n");
41                         priv->op_flags |= (OP_BT_SCAN |
42                                          OP_BT_PRIORITY_DETECTED);
43                 } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
44                         ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
45                                 "BT priority traffic detected\n");
46                         priv->op_flags |= OP_BT_PRIORITY_DETECTED;
47                 }
48
49                 btcoex->bt_priority_cnt = 0;
50                 btcoex->bt_priority_time = jiffies;
51         }
52 }
53
54 /*
55  * This is the master bt coex work which runs for every
56  * 45ms, bt traffic will be given priority during 55% of this
57  * period while wlan gets remaining 45%
58  */
59 static void ath_btcoex_period_work(struct work_struct *work)
60 {
61         struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
62                                                    coex_period_work.work);
63         struct ath_btcoex *btcoex = &priv->btcoex;
64         struct ath_common *common = ath9k_hw_common(priv->ah);
65         u32 timer_period;
66         bool is_btscan;
67         int ret;
68         u8 cmd_rsp, aggr;
69
70         ath_detect_bt_priority(priv);
71
72         is_btscan = !!(priv->op_flags & OP_BT_SCAN);
73
74         aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED;
75
76         WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr);
77
78         ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL :
79                         btcoex->bt_stomp_type);
80
81         timer_period = is_btscan ? btcoex->btscan_no_stomp :
82                 btcoex->btcoex_no_stomp;
83         ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
84                                      msecs_to_jiffies(timer_period));
85         ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work,
86                                      msecs_to_jiffies(btcoex->btcoex_period));
87 }
88
89 /*
90  * Work to time slice between wlan and bt traffic and
91  * configure weight registers
92  */
93 static void ath_btcoex_duty_cycle_work(struct work_struct *work)
94 {
95         struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
96                                                    duty_cycle_work.work);
97         struct ath_hw *ah = priv->ah;
98         struct ath_btcoex *btcoex = &priv->btcoex;
99         struct ath_common *common = ath9k_hw_common(ah);
100         bool is_btscan = priv->op_flags & OP_BT_SCAN;
101
102         ath_dbg(common, ATH_DBG_BTCOEX,
103                 "time slice work for bt and wlan\n");
104
105         if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
106                 ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE);
107         else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
108                 ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW);
109 }
110
111 void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv)
112 {
113         struct ath_btcoex *btcoex = &priv->btcoex;
114
115         btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
116         btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
117                 btcoex->btcoex_period / 100;
118         btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
119                                    btcoex->btcoex_period / 100;
120         INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work);
121         INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work);
122 }
123
124 /*
125  * (Re)start btcoex work
126  */
127
128 void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
129 {
130         struct ath_btcoex *btcoex = &priv->btcoex;
131         struct ath_hw *ah = priv->ah;
132
133         ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, "Starting btcoex work\n");
134
135         btcoex->bt_priority_cnt = 0;
136         btcoex->bt_priority_time = jiffies;
137         priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN);
138         ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0);
139 }
140
141
142 /*
143  * Cancel btcoex and bt duty cycle work.
144  */
145 void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
146 {
147         cancel_delayed_work_sync(&priv->coex_period_work);
148         cancel_delayed_work_sync(&priv->duty_cycle_work);
149 }
150
151 /*******/
152 /* LED */
153 /*******/
154
155 static void ath9k_led_blink_work(struct work_struct *work)
156 {
157         struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
158                                                    ath9k_led_blink_work.work);
159
160         if (!(priv->op_flags & OP_LED_ASSOCIATED))
161                 return;
162
163         if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
164             (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
165                 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
166         else
167                 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
168                                   (priv->op_flags & OP_LED_ON) ? 1 : 0);
169
170         ieee80211_queue_delayed_work(priv->hw,
171                                      &priv->ath9k_led_blink_work,
172                                      (priv->op_flags & OP_LED_ON) ?
173                                      msecs_to_jiffies(priv->led_off_duration) :
174                                      msecs_to_jiffies(priv->led_on_duration));
175
176         priv->led_on_duration = priv->led_on_cnt ?
177                 max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
178                 ATH_LED_ON_DURATION_IDLE;
179         priv->led_off_duration = priv->led_off_cnt ?
180                 max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
181                 ATH_LED_OFF_DURATION_IDLE;
182         priv->led_on_cnt = priv->led_off_cnt = 0;
183
184         if (priv->op_flags & OP_LED_ON)
185                 priv->op_flags &= ~OP_LED_ON;
186         else
187                 priv->op_flags |= OP_LED_ON;
188 }
189
190 static void ath9k_led_brightness_work(struct work_struct *work)
191 {
192         struct ath_led *led = container_of(work, struct ath_led,
193                                            brightness_work.work);
194         struct ath9k_htc_priv *priv = led->priv;
195
196         switch (led->brightness) {
197         case LED_OFF:
198                 if (led->led_type == ATH_LED_ASSOC ||
199                     led->led_type == ATH_LED_RADIO) {
200                         ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
201                                           (led->led_type == ATH_LED_RADIO));
202                         priv->op_flags &= ~OP_LED_ASSOCIATED;
203                         if (led->led_type == ATH_LED_RADIO)
204                                 priv->op_flags &= ~OP_LED_ON;
205                 } else {
206                         priv->led_off_cnt++;
207                 }
208                 break;
209         case LED_FULL:
210                 if (led->led_type == ATH_LED_ASSOC) {
211                         priv->op_flags |= OP_LED_ASSOCIATED;
212                         ieee80211_queue_delayed_work(priv->hw,
213                                              &priv->ath9k_led_blink_work, 0);
214                 } else if (led->led_type == ATH_LED_RADIO) {
215                         ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
216                         priv->op_flags |= OP_LED_ON;
217                 } else {
218                         priv->led_on_cnt++;
219                 }
220                 break;
221         default:
222                 break;
223         }
224 }
225
226 static void ath9k_led_brightness(struct led_classdev *led_cdev,
227                                  enum led_brightness brightness)
228 {
229         struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
230         struct ath9k_htc_priv *priv = led->priv;
231
232         led->brightness = brightness;
233         if (!(priv->op_flags & OP_LED_DEINIT))
234                 ieee80211_queue_delayed_work(priv->hw,
235                                              &led->brightness_work, 0);
236 }
237
238 void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
239 {
240         cancel_delayed_work_sync(&priv->radio_led.brightness_work);
241         cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
242         cancel_delayed_work_sync(&priv->tx_led.brightness_work);
243         cancel_delayed_work_sync(&priv->rx_led.brightness_work);
244 }
245
246 static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
247                               char *trigger)
248 {
249         int ret;
250
251         led->priv = priv;
252         led->led_cdev.name = led->name;
253         led->led_cdev.default_trigger = trigger;
254         led->led_cdev.brightness_set = ath9k_led_brightness;
255
256         ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
257         if (ret)
258                 ath_err(ath9k_hw_common(priv->ah),
259                         "Failed to register led:%s", led->name);
260         else
261                 led->registered = 1;
262
263         INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
264
265         return ret;
266 }
267
268 static void ath9k_unregister_led(struct ath_led *led)
269 {
270         if (led->registered) {
271                 led_classdev_unregister(&led->led_cdev);
272                 led->registered = 0;
273         }
274 }
275
276 void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
277 {
278         priv->op_flags |= OP_LED_DEINIT;
279         ath9k_unregister_led(&priv->assoc_led);
280         priv->op_flags &= ~OP_LED_ASSOCIATED;
281         ath9k_unregister_led(&priv->tx_led);
282         ath9k_unregister_led(&priv->rx_led);
283         ath9k_unregister_led(&priv->radio_led);
284 }
285
286 void ath9k_init_leds(struct ath9k_htc_priv *priv)
287 {
288         char *trigger;
289         int ret;
290
291         if (AR_SREV_9287(priv->ah))
292                 priv->ah->led_pin = ATH_LED_PIN_9287;
293         else if (AR_SREV_9271(priv->ah))
294                 priv->ah->led_pin = ATH_LED_PIN_9271;
295         else if (AR_DEVID_7010(priv->ah))
296                 priv->ah->led_pin = ATH_LED_PIN_7010;
297         else
298                 priv->ah->led_pin = ATH_LED_PIN_DEF;
299
300         /* Configure gpio 1 for output */
301         ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
302                             AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
303         /* LED off, active low */
304         ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
305
306         INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
307
308         trigger = ieee80211_get_radio_led_name(priv->hw);
309         snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
310                 "ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
311         ret = ath9k_register_led(priv, &priv->radio_led, trigger);
312         priv->radio_led.led_type = ATH_LED_RADIO;
313         if (ret)
314                 goto fail;
315
316         trigger = ieee80211_get_assoc_led_name(priv->hw);
317         snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
318                 "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
319         ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
320         priv->assoc_led.led_type = ATH_LED_ASSOC;
321         if (ret)
322                 goto fail;
323
324         trigger = ieee80211_get_tx_led_name(priv->hw);
325         snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
326                 "ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
327         ret = ath9k_register_led(priv, &priv->tx_led, trigger);
328         priv->tx_led.led_type = ATH_LED_TX;
329         if (ret)
330                 goto fail;
331
332         trigger = ieee80211_get_rx_led_name(priv->hw);
333         snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
334                 "ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
335         ret = ath9k_register_led(priv, &priv->rx_led, trigger);
336         priv->rx_led.led_type = ATH_LED_RX;
337         if (ret)
338                 goto fail;
339
340         priv->op_flags &= ~OP_LED_DEINIT;
341
342         return;
343
344 fail:
345         cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
346         ath9k_deinit_leds(priv);
347 }
348
349 /*******************/
350 /*      Rfkill     */
351 /*******************/
352
353 static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
354 {
355         return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
356                 priv->ah->rfkill_polarity;
357 }
358
359 void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
360 {
361         struct ath9k_htc_priv *priv = hw->priv;
362         bool blocked = !!ath_is_rfkill_set(priv);
363
364         wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
365 }
366
367 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
368 {
369         if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
370                 wiphy_rfkill_start_polling(priv->hw->wiphy);
371 }
372
373 void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
374 {
375         struct ath9k_htc_priv *priv = hw->priv;
376         struct ath_hw *ah = priv->ah;
377         struct ath_common *common = ath9k_hw_common(ah);
378         int ret;
379         u8 cmd_rsp;
380
381         if (!ah->curchan)
382                 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
383
384         /* Reset the HW */
385         ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
386         if (ret) {
387                 ath_err(common,
388                         "Unable to reset hardware; reset status %d (freq %u MHz)\n",
389                         ret, ah->curchan->channel);
390         }
391
392         ath_update_txpow(priv);
393
394         /* Start RX */
395         WMI_CMD(WMI_START_RECV_CMDID);
396         ath9k_host_rx_init(priv);
397
398         /* Start TX */
399         htc_start(priv->htc);
400         spin_lock_bh(&priv->tx_lock);
401         priv->tx_queues_stop = false;
402         spin_unlock_bh(&priv->tx_lock);
403         ieee80211_wake_queues(hw);
404
405         WMI_CMD(WMI_ENABLE_INTR_CMDID);
406
407         /* Enable LED */
408         ath9k_hw_cfg_output(ah, ah->led_pin,
409                             AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
410         ath9k_hw_set_gpio(ah, ah->led_pin, 0);
411 }
412
413 void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
414 {
415         struct ath9k_htc_priv *priv = hw->priv;
416         struct ath_hw *ah = priv->ah;
417         struct ath_common *common = ath9k_hw_common(ah);
418         int ret;
419         u8 cmd_rsp;
420
421         ath9k_htc_ps_wakeup(priv);
422
423         /* Disable LED */
424         ath9k_hw_set_gpio(ah, ah->led_pin, 1);
425         ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
426
427         WMI_CMD(WMI_DISABLE_INTR_CMDID);
428
429         /* Stop TX */
430         ieee80211_stop_queues(hw);
431         htc_stop(priv->htc);
432         WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
433         skb_queue_purge(&priv->tx_queue);
434
435         /* Stop RX */
436         WMI_CMD(WMI_STOP_RECV_CMDID);
437
438         /*
439          * The MIB counters have to be disabled here,
440          * since the target doesn't do it.
441          */
442         ath9k_hw_disable_mib_counters(ah);
443
444         if (!ah->curchan)
445                 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
446
447         /* Reset the HW */
448         ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
449         if (ret) {
450                 ath_err(common,
451                         "Unable to reset hardware; reset status %d (freq %u MHz)\n",
452                         ret, ah->curchan->channel);
453         }
454
455         /* Disable the PHY */
456         ath9k_hw_phy_disable(ah);
457
458         ath9k_htc_ps_restore(priv);
459         ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
460 }