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

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. led_turn_on
  2. led_turn_off
  3. rtl8187_led_brightness_set
  4. rtl8187_register_led
  5. rtl8187_unregister_led
  6. rtl8187_leds_init
  7. rtl8187_leds_exit

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

/* [<][>][^][v][top][bottom][index][help] */