linux/drivers/leds/leds-versatile.c
<<
>>
Prefs
   1/*
   2 * Driver for the 8 user LEDs found on the RealViews and Versatiles
   3 * Based on DaVinci's DM365 board code
   4 *
   5 * License terms: GNU General Public License (GPL) version 2
   6 * Author: Linus Walleij <triad@df.lth.se>
   7 */
   8#include <linux/kernel.h>
   9#include <linux/init.h>
  10#include <linux/module.h>
  11#include <linux/io.h>
  12#include <linux/slab.h>
  13#include <linux/leds.h>
  14#include <linux/platform_device.h>
  15
  16struct versatile_led {
  17        void __iomem            *base;
  18        struct led_classdev     cdev;
  19        u8                      mask;
  20};
  21
  22/*
  23 * The triggers lines up below will only be used if the
  24 * LED triggers are compiled in.
  25 */
  26static const struct {
  27        const char *name;
  28        const char *trigger;
  29} versatile_leds[] = {
  30        { "versatile:0", "heartbeat", },
  31        { "versatile:1", "mmc0", },
  32        { "versatile:2", "cpu0" },
  33        { "versatile:3", "cpu1" },
  34        { "versatile:4", "cpu2" },
  35        { "versatile:5", "cpu3" },
  36        { "versatile:6", },
  37        { "versatile:7", },
  38};
  39
  40static void versatile_led_set(struct led_classdev *cdev,
  41                              enum led_brightness b)
  42{
  43        struct versatile_led *led = container_of(cdev,
  44                                                 struct versatile_led, cdev);
  45        u32 reg = readl(led->base);
  46
  47        if (b != LED_OFF)
  48                reg |= led->mask;
  49        else
  50                reg &= ~led->mask;
  51        writel(reg, led->base);
  52}
  53
  54static enum led_brightness versatile_led_get(struct led_classdev *cdev)
  55{
  56        struct versatile_led *led = container_of(cdev,
  57                                                 struct versatile_led, cdev);
  58        u32 reg = readl(led->base);
  59
  60        return (reg & led->mask) ? LED_FULL : LED_OFF;
  61}
  62
  63static int versatile_leds_probe(struct platform_device *dev)
  64{
  65        int i;
  66        struct resource *res;
  67        void __iomem *base;
  68
  69        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
  70        base = devm_ioremap_resource(&dev->dev, res);
  71        if (IS_ERR(base))
  72                return PTR_ERR(base);
  73
  74        /* All off */
  75        writel(0, base);
  76        for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) {
  77                struct versatile_led *led;
  78
  79                led = kzalloc(sizeof(*led), GFP_KERNEL);
  80                if (!led)
  81                        break;
  82
  83                led->base = base;
  84                led->cdev.name = versatile_leds[i].name;
  85                led->cdev.brightness_set = versatile_led_set;
  86                led->cdev.brightness_get = versatile_led_get;
  87                led->cdev.default_trigger = versatile_leds[i].trigger;
  88                led->mask = BIT(i);
  89
  90                if (led_classdev_register(NULL, &led->cdev) < 0) {
  91                        kfree(led);
  92                        break;
  93                }
  94        }
  95
  96        return 0;
  97}
  98
  99static struct platform_driver versatile_leds_driver = {
 100        .driver = {
 101                .name   = "versatile-leds",
 102        },
 103        .probe = versatile_leds_probe,
 104};
 105
 106module_platform_driver(versatile_leds_driver);
 107
 108MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 109MODULE_DESCRIPTION("ARM Versatile LED driver");
 110MODULE_LICENSE("GPL v2");
 111