aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/htc_drv_main.c
diff options
context:
space:
mode:
authorSujith Manoharan <Sujith.Manoharan@atheros.com>2010-12-28 03:58:52 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-04 14:43:00 -0500
commit1e1f4ad25fab29ca48b1166e74a81e9c89ddf0fb (patch)
tree64066131ba67cff6b4142e78aa8932fe4bad2078 /drivers/net/wireless/ath/ath9k/htc_drv_main.c
parent039a07215e0fca00c450f4bf1dc9b458bdfe8559 (diff)
ath9k_htc: Move LED/RFKILL code to htc_drv_gpio.c
And add the copyright/license header. Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c313
1 files changed, 1 insertions, 312 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 6da5e886730..ad3dd3186ad 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -24,7 +24,7 @@ static struct dentry *ath9k_debugfs_root;
24/* Utilities */ 24/* Utilities */
25/*************/ 25/*************/
26 26
27static void ath_update_txpow(struct ath9k_htc_priv *priv) 27void ath_update_txpow(struct ath9k_htc_priv *priv)
28{ 28{
29 struct ath_hw *ah = priv->ah; 29 struct ath_hw *ah = priv->ah;
30 30
@@ -840,317 +840,6 @@ set_timer:
840 msecs_to_jiffies(cal_interval)); 840 msecs_to_jiffies(cal_interval));
841} 841}
842 842
843/*******/
844/* LED */
845/*******/
846
847static void ath9k_led_blink_work(struct work_struct *work)
848{
849 struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
850 ath9k_led_blink_work.work);
851
852 if (!(priv->op_flags & OP_LED_ASSOCIATED))
853 return;
854
855 if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
856 (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
857 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
858 else
859 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
860 (priv->op_flags & OP_LED_ON) ? 1 : 0);
861
862 ieee80211_queue_delayed_work(priv->hw,
863 &priv->ath9k_led_blink_work,
864 (priv->op_flags & OP_LED_ON) ?
865 msecs_to_jiffies(priv->led_off_duration) :
866 msecs_to_jiffies(priv->led_on_duration));
867
868 priv->led_on_duration = priv->led_on_cnt ?
869 max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
870 ATH_LED_ON_DURATION_IDLE;
871 priv->led_off_duration = priv->led_off_cnt ?
872 max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
873 ATH_LED_OFF_DURATION_IDLE;
874 priv->led_on_cnt = priv->led_off_cnt = 0;
875
876 if (priv->op_flags & OP_LED_ON)
877 priv->op_flags &= ~OP_LED_ON;
878 else
879 priv->op_flags |= OP_LED_ON;
880}
881
882static void ath9k_led_brightness_work(struct work_struct *work)
883{
884 struct ath_led *led = container_of(work, struct ath_led,
885 brightness_work.work);
886 struct ath9k_htc_priv *priv = led->priv;
887
888 switch (led->brightness) {
889 case LED_OFF:
890 if (led->led_type == ATH_LED_ASSOC ||
891 led->led_type == ATH_LED_RADIO) {
892 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
893 (led->led_type == ATH_LED_RADIO));
894 priv->op_flags &= ~OP_LED_ASSOCIATED;
895 if (led->led_type == ATH_LED_RADIO)
896 priv->op_flags &= ~OP_LED_ON;
897 } else {
898 priv->led_off_cnt++;
899 }
900 break;
901 case LED_FULL:
902 if (led->led_type == ATH_LED_ASSOC) {
903 priv->op_flags |= OP_LED_ASSOCIATED;
904 ieee80211_queue_delayed_work(priv->hw,
905 &priv->ath9k_led_blink_work, 0);
906 } else if (led->led_type == ATH_LED_RADIO) {
907 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
908 priv->op_flags |= OP_LED_ON;
909 } else {
910 priv->led_on_cnt++;
911 }
912 break;
913 default:
914 break;
915 }
916}
917
918static void ath9k_led_brightness(struct led_classdev *led_cdev,
919 enum led_brightness brightness)
920{
921 struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
922 struct ath9k_htc_priv *priv = led->priv;
923
924 led->brightness = brightness;
925 if (!(priv->op_flags & OP_LED_DEINIT))
926 ieee80211_queue_delayed_work(priv->hw,
927 &led->brightness_work, 0);
928}
929
930static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
931{
932 cancel_delayed_work_sync(&priv->radio_led.brightness_work);
933 cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
934 cancel_delayed_work_sync(&priv->tx_led.brightness_work);
935 cancel_delayed_work_sync(&priv->rx_led.brightness_work);
936}
937
938static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
939 char *trigger)
940{
941 int ret;
942
943 led->priv = priv;
944 led->led_cdev.name = led->name;
945 led->led_cdev.default_trigger = trigger;
946 led->led_cdev.brightness_set = ath9k_led_brightness;
947
948 ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
949 if (ret)
950 ath_err(ath9k_hw_common(priv->ah),
951 "Failed to register led:%s", led->name);
952 else
953 led->registered = 1;
954
955 INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
956
957 return ret;
958}
959
960static void ath9k_unregister_led(struct ath_led *led)
961{
962 if (led->registered) {
963 led_classdev_unregister(&led->led_cdev);
964 led->registered = 0;
965 }
966}
967
968void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
969{
970 priv->op_flags |= OP_LED_DEINIT;
971 ath9k_unregister_led(&priv->assoc_led);
972 priv->op_flags &= ~OP_LED_ASSOCIATED;
973 ath9k_unregister_led(&priv->tx_led);
974 ath9k_unregister_led(&priv->rx_led);
975 ath9k_unregister_led(&priv->radio_led);
976}
977
978void ath9k_init_leds(struct ath9k_htc_priv *priv)
979{
980 char *trigger;
981 int ret;
982
983 if (AR_SREV_9287(priv->ah))
984 priv->ah->led_pin = ATH_LED_PIN_9287;
985 else if (AR_SREV_9271(priv->ah))
986 priv->ah->led_pin = ATH_LED_PIN_9271;
987 else if (AR_DEVID_7010(priv->ah))
988 priv->ah->led_pin = ATH_LED_PIN_7010;
989 else
990 priv->ah->led_pin = ATH_LED_PIN_DEF;
991
992 /* Configure gpio 1 for output */
993 ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
994 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
995 /* LED off, active low */
996 ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
997
998 INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
999
1000 trigger = ieee80211_get_radio_led_name(priv->hw);
1001 snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
1002 "ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
1003 ret = ath9k_register_led(priv, &priv->radio_led, trigger);
1004 priv->radio_led.led_type = ATH_LED_RADIO;
1005 if (ret)
1006 goto fail;
1007
1008 trigger = ieee80211_get_assoc_led_name(priv->hw);
1009 snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
1010 "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
1011 ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
1012 priv->assoc_led.led_type = ATH_LED_ASSOC;
1013 if (ret)
1014 goto fail;
1015
1016 trigger = ieee80211_get_tx_led_name(priv->hw);
1017 snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
1018 "ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
1019 ret = ath9k_register_led(priv, &priv->tx_led, trigger);
1020 priv->tx_led.led_type = ATH_LED_TX;
1021 if (ret)
1022 goto fail;
1023
1024 trigger = ieee80211_get_rx_led_name(priv->hw);
1025 snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
1026 "ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
1027 ret = ath9k_register_led(priv, &priv->rx_led, trigger);
1028 priv->rx_led.led_type = ATH_LED_RX;
1029 if (ret)
1030 goto fail;
1031
1032 priv->op_flags &= ~OP_LED_DEINIT;
1033
1034 return;
1035
1036fail:
1037 cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
1038 ath9k_deinit_leds(priv);
1039}
1040
1041/*******************/
1042/* Rfkill */
1043/*******************/
1044
1045static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
1046{
1047 return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
1048 priv->ah->rfkill_polarity;
1049}
1050
1051static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
1052{
1053 struct ath9k_htc_priv *priv = hw->priv;
1054 bool blocked = !!ath_is_rfkill_set(priv);
1055
1056 wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
1057}
1058
1059void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
1060{
1061 if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1062 wiphy_rfkill_start_polling(priv->hw->wiphy);
1063}
1064
1065static void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
1066{
1067 struct ath9k_htc_priv *priv = hw->priv;
1068 struct ath_hw *ah = priv->ah;
1069 struct ath_common *common = ath9k_hw_common(ah);
1070 int ret;
1071 u8 cmd_rsp;
1072
1073 if (!ah->curchan)
1074 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
1075
1076 /* Reset the HW */
1077 ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
1078 if (ret) {
1079 ath_err(common,
1080 "Unable to reset hardware; reset status %d (freq %u MHz)\n",
1081 ret, ah->curchan->channel);
1082 }
1083
1084 ath_update_txpow(priv);
1085
1086 /* Start RX */
1087 WMI_CMD(WMI_START_RECV_CMDID);
1088 ath9k_host_rx_init(priv);
1089
1090 /* Start TX */
1091 htc_start(priv->htc);
1092 spin_lock_bh(&priv->tx_lock);
1093 priv->tx_queues_stop = false;
1094 spin_unlock_bh(&priv->tx_lock);
1095 ieee80211_wake_queues(hw);
1096
1097 WMI_CMD(WMI_ENABLE_INTR_CMDID);
1098
1099 /* Enable LED */
1100 ath9k_hw_cfg_output(ah, ah->led_pin,
1101 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
1102 ath9k_hw_set_gpio(ah, ah->led_pin, 0);
1103}
1104
1105static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
1106{
1107 struct ath9k_htc_priv *priv = hw->priv;
1108 struct ath_hw *ah = priv->ah;
1109 struct ath_common *common = ath9k_hw_common(ah);
1110 int ret;
1111 u8 cmd_rsp;
1112
1113 ath9k_htc_ps_wakeup(priv);
1114
1115 /* Disable LED */
1116 ath9k_hw_set_gpio(ah, ah->led_pin, 1);
1117 ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
1118
1119 WMI_CMD(WMI_DISABLE_INTR_CMDID);
1120
1121 /* Stop TX */
1122 ieee80211_stop_queues(hw);
1123 htc_stop(priv->htc);
1124 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
1125 skb_queue_purge(&priv->tx_queue);
1126
1127 /* Stop RX */
1128 WMI_CMD(WMI_STOP_RECV_CMDID);
1129
1130 /*
1131 * The MIB counters have to be disabled here,
1132 * since the target doesn't do it.
1133 */
1134 ath9k_hw_disable_mib_counters(ah);
1135
1136 if (!ah->curchan)
1137 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
1138
1139 /* Reset the HW */
1140 ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
1141 if (ret) {
1142 ath_err(common,
1143 "Unable to reset hardware; reset status %d (freq %u MHz)\n",
1144 ret, ah->curchan->channel);
1145 }
1146
1147 /* Disable the PHY */
1148 ath9k_hw_phy_disable(ah);
1149
1150 ath9k_htc_ps_restore(priv);
1151 ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
1152}
1153
1154/**********************/ 843/**********************/
1155/* mac80211 Callbacks */ 844/* mac80211 Callbacks */
1156/**********************/ 845/**********************/