linux/drivers/leds/leds-ot200.c
<<
>>
Prefs
   1/*
   2 * Bachmann ot200 leds driver.
   3 *
   4 * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
   5 *         Christian Gmeiner <christian.gmeiner@gmail.com>
   6 *
   7 * License: GPL as published by the FSF.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/init.h>
  12#include <linux/platform_device.h>
  13#include <linux/slab.h>
  14#include <linux/leds.h>
  15#include <linux/io.h>
  16#include <linux/module.h>
  17
  18
  19struct ot200_led {
  20        struct led_classdev cdev;
  21        const char *name;
  22        unsigned long port;
  23        u8 mask;
  24};
  25
  26/*
  27 * The device has three leds on the back panel (led_err, led_init and led_run)
  28 * and can handle up to seven leds on the front panel.
  29 */
  30
  31static struct ot200_led leds[] = {
  32        {
  33                .name = "led_run",
  34                .port = 0x5a,
  35                .mask = BIT(0),
  36        },
  37        {
  38                .name = "led_init",
  39                .port = 0x5a,
  40                .mask = BIT(1),
  41        },
  42        {
  43                .name = "led_err",
  44                .port = 0x5a,
  45                .mask = BIT(2),
  46        },
  47        {
  48                .name = "led_1",
  49                .port = 0x49,
  50                .mask = BIT(7),
  51        },
  52        {
  53                .name = "led_2",
  54                .port = 0x49,
  55                .mask = BIT(6),
  56        },
  57        {
  58                .name = "led_3",
  59                .port = 0x49,
  60                .mask = BIT(5),
  61        },
  62        {
  63                .name = "led_4",
  64                .port = 0x49,
  65                .mask = BIT(4),
  66        },
  67        {
  68                .name = "led_5",
  69                .port = 0x49,
  70                .mask = BIT(3),
  71        },
  72        {
  73                .name = "led_6",
  74                .port = 0x49,
  75                .mask = BIT(2),
  76        },
  77        {
  78                .name = "led_7",
  79                .port = 0x49,
  80                .mask = BIT(1),
  81        }
  82};
  83
  84static DEFINE_SPINLOCK(value_lock);
  85
  86/*
  87 * we need to store the current led states, as it is not
  88 * possible to read the current led state via inb().
  89 */
  90static u8 leds_back;
  91static u8 leds_front;
  92
  93static void ot200_led_brightness_set(struct led_classdev *led_cdev,
  94                enum led_brightness value)
  95{
  96        struct ot200_led *led = container_of(led_cdev, struct ot200_led, cdev);
  97        u8 *val;
  98        unsigned long flags;
  99
 100        spin_lock_irqsave(&value_lock, flags);
 101
 102        if (led->port == 0x49)
 103                val = &leds_front;
 104        else if (led->port == 0x5a)
 105                val = &leds_back;
 106        else
 107                BUG();
 108
 109        if (value == LED_OFF)
 110                *val &= ~led->mask;
 111        else
 112                *val |= led->mask;
 113
 114        outb(*val, led->port);
 115        spin_unlock_irqrestore(&value_lock, flags);
 116}
 117
 118static int ot200_led_probe(struct platform_device *pdev)
 119{
 120        int i;
 121        int ret;
 122
 123        for (i = 0; i < ARRAY_SIZE(leds); i++) {
 124
 125                leds[i].cdev.name = leds[i].name;
 126                leds[i].cdev.brightness_set = ot200_led_brightness_set;
 127
 128                ret = led_classdev_register(&pdev->dev, &leds[i].cdev);
 129                if (ret < 0)
 130                        goto err;
 131        }
 132
 133        leds_front = 0;         /* turn off all front leds */
 134        leds_back = BIT(1);     /* turn on init led */
 135        outb(leds_front, 0x49);
 136        outb(leds_back, 0x5a);
 137
 138        return 0;
 139
 140err:
 141        for (i = i - 1; i >= 0; i--)
 142                led_classdev_unregister(&leds[i].cdev);
 143
 144        return ret;
 145}
 146
 147static int ot200_led_remove(struct platform_device *pdev)
 148{
 149        int i;
 150
 151        for (i = 0; i < ARRAY_SIZE(leds); i++)
 152                led_classdev_unregister(&leds[i].cdev);
 153
 154        return 0;
 155}
 156
 157static struct platform_driver ot200_led_driver = {
 158        .probe          = ot200_led_probe,
 159        .remove         = ot200_led_remove,
 160        .driver         = {
 161                .name   = "leds-ot200",
 162                .owner  = THIS_MODULE,
 163        },
 164};
 165
 166module_platform_driver(ot200_led_driver);
 167
 168MODULE_AUTHOR("Sebastian A. Siewior <bigeasy@linutronix.de>");
 169MODULE_DESCRIPTION("ot200 LED driver");
 170MODULE_LICENSE("GPL");
 171MODULE_ALIAS("platform:leds-ot200");
 172
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.