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