/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c

https://github.com/srikard/linux · C · 242 lines · 188 code · 27 blank · 27 comment · 27 complexity · 3f34d0aa45c7c651b77d653b9c2ac0aa MD5 · raw file

  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Linux LED driver for RTL8187
  4. *
  5. * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
  6. *
  7. * Based on the LED handling in the r8187 driver, which is:
  8. * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
  9. *
  10. * Thanks to Realtek for their support!
  11. */
  12. #ifdef CONFIG_RTL8187_LEDS
  13. #include <net/mac80211.h>
  14. #include <linux/usb.h>
  15. #include <linux/eeprom_93cx6.h>
  16. #include "rtl8187.h"
  17. #include "leds.h"
  18. static void led_turn_on(struct work_struct *work)
  19. {
  20. /* As this routine does read/write operations on the hardware, it must
  21. * be run from a work queue.
  22. */
  23. u8 reg;
  24. struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
  25. led_on.work);
  26. struct rtl8187_led *led = &priv->led_tx;
  27. /* Don't change the LED, when the device is down. */
  28. if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
  29. return ;
  30. /* Skip if the LED is not registered. */
  31. if (!led->dev)
  32. return;
  33. mutex_lock(&priv->conf_mutex);
  34. switch (led->ledpin) {
  35. case LED_PIN_GPIO0:
  36. rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
  37. rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00);
  38. break;
  39. case LED_PIN_LED0:
  40. reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4);
  41. rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
  42. break;
  43. case LED_PIN_LED1:
  44. reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5);
  45. rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
  46. break;
  47. case LED_PIN_HW:
  48. default:
  49. break;
  50. }
  51. mutex_unlock(&priv->conf_mutex);
  52. }
  53. static void led_turn_off(struct work_struct *work)
  54. {
  55. /* As this routine does read/write operations on the hardware, it must
  56. * be run from a work queue.
  57. */
  58. u8 reg;
  59. struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
  60. led_off.work);
  61. struct rtl8187_led *led = &priv->led_tx;
  62. /* Don't change the LED, when the device is down. */
  63. if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
  64. return ;
  65. /* Skip if the LED is not registered. */
  66. if (!led->dev)
  67. return;
  68. mutex_lock(&priv->conf_mutex);
  69. switch (led->ledpin) {
  70. case LED_PIN_GPIO0:
  71. rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
  72. rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01);
  73. break;
  74. case LED_PIN_LED0:
  75. reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4);
  76. rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
  77. break;
  78. case LED_PIN_LED1:
  79. reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5);
  80. rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
  81. break;
  82. case LED_PIN_HW:
  83. default:
  84. break;
  85. }
  86. mutex_unlock(&priv->conf_mutex);
  87. }
  88. /* Callback from the LED subsystem. */
  89. static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
  90. enum led_brightness brightness)
  91. {
  92. struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led,
  93. led_dev);
  94. struct ieee80211_hw *hw = led->dev;
  95. struct rtl8187_priv *priv;
  96. static bool radio_on;
  97. if (!hw)
  98. return;
  99. priv = hw->priv;
  100. if (led->is_radio) {
  101. if (brightness == LED_FULL) {
  102. ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
  103. radio_on = true;
  104. } else if (radio_on) {
  105. radio_on = false;
  106. cancel_delayed_work(&priv->led_on);
  107. ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
  108. }
  109. } else if (radio_on) {
  110. if (brightness == LED_OFF) {
  111. ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
  112. /* The LED is off for 1/20 sec - it just blinks. */
  113. ieee80211_queue_delayed_work(hw, &priv->led_on,
  114. HZ / 20);
  115. } else
  116. ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
  117. }
  118. }
  119. static int rtl8187_register_led(struct ieee80211_hw *dev,
  120. struct rtl8187_led *led, const char *name,
  121. const char *default_trigger, u8 ledpin,
  122. bool is_radio)
  123. {
  124. int err;
  125. struct rtl8187_priv *priv = dev->priv;
  126. if (led->dev)
  127. return -EEXIST;
  128. if (!default_trigger)
  129. return -EINVAL;
  130. led->dev = dev;
  131. led->ledpin = ledpin;
  132. led->is_radio = is_radio;
  133. strlcpy(led->name, name, sizeof(led->name));
  134. led->led_dev.name = led->name;
  135. led->led_dev.default_trigger = default_trigger;
  136. led->led_dev.brightness_set = rtl8187_led_brightness_set;
  137. err = led_classdev_register(&priv->udev->dev, &led->led_dev);
  138. if (err) {
  139. printk(KERN_INFO "LEDs: Failed to register %s\n", name);
  140. led->dev = NULL;
  141. return err;
  142. }
  143. return 0;
  144. }
  145. static void rtl8187_unregister_led(struct rtl8187_led *led)
  146. {
  147. struct ieee80211_hw *hw = led->dev;
  148. struct rtl8187_priv *priv = hw->priv;
  149. led_classdev_unregister(&led->led_dev);
  150. flush_delayed_work(&priv->led_off);
  151. led->dev = NULL;
  152. }
  153. void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
  154. {
  155. struct rtl8187_priv *priv = dev->priv;
  156. char name[RTL8187_LED_MAX_NAME_LEN + 1];
  157. u8 ledpin;
  158. int err;
  159. /* According to the vendor driver, the LED operation depends on the
  160. * customer ID encoded in the EEPROM
  161. */
  162. printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid);
  163. switch (custid) {
  164. case EEPROM_CID_RSVD0:
  165. case EEPROM_CID_RSVD1:
  166. case EEPROM_CID_SERCOMM_PS:
  167. case EEPROM_CID_QMI:
  168. case EEPROM_CID_DELL:
  169. case EEPROM_CID_TOSHIBA:
  170. ledpin = LED_PIN_GPIO0;
  171. break;
  172. case EEPROM_CID_ALPHA0:
  173. ledpin = LED_PIN_LED0;
  174. break;
  175. case EEPROM_CID_HW:
  176. ledpin = LED_PIN_HW;
  177. break;
  178. default:
  179. ledpin = LED_PIN_GPIO0;
  180. }
  181. INIT_DELAYED_WORK(&priv->led_on, led_turn_on);
  182. INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
  183. snprintf(name, sizeof(name),
  184. "rtl8187-%s::radio", wiphy_name(dev->wiphy));
  185. err = rtl8187_register_led(dev, &priv->led_radio, name,
  186. ieee80211_get_radio_led_name(dev), ledpin, true);
  187. if (err)
  188. return;
  189. snprintf(name, sizeof(name),
  190. "rtl8187-%s::tx", wiphy_name(dev->wiphy));
  191. err = rtl8187_register_led(dev, &priv->led_tx, name,
  192. ieee80211_get_tx_led_name(dev), ledpin, false);
  193. if (err)
  194. goto err_tx;
  195. snprintf(name, sizeof(name),
  196. "rtl8187-%s::rx", wiphy_name(dev->wiphy));
  197. err = rtl8187_register_led(dev, &priv->led_rx, name,
  198. ieee80211_get_rx_led_name(dev), ledpin, false);
  199. if (!err)
  200. return;
  201. /* registration of RX LED failed - unregister */
  202. rtl8187_unregister_led(&priv->led_tx);
  203. err_tx:
  204. rtl8187_unregister_led(&priv->led_radio);
  205. }
  206. void rtl8187_leds_exit(struct ieee80211_hw *dev)
  207. {
  208. struct rtl8187_priv *priv = dev->priv;
  209. rtl8187_unregister_led(&priv->led_radio);
  210. rtl8187_unregister_led(&priv->led_rx);
  211. rtl8187_unregister_led(&priv->led_tx);
  212. cancel_delayed_work_sync(&priv->led_off);
  213. cancel_delayed_work_sync(&priv->led_on);
  214. }
  215. #endif /* def CONFIG_RTL8187_LEDS */