linux/arch/arm/mach-integrator/leds.c
<<
>>
Prefs
   1/*
   2 * Driver for the 4 user LEDs found on the Integrator AP/CP baseboard
   3 * Based on Versatile and RealView machine LED code
   4 *
   5 * License terms: GNU General Public License (GPL) version 2
   6 * Author: Bryan Wu <bryan.wu@canonical.com>
   7 */
   8#include <linux/kernel.h>
   9#include <linux/init.h>
  10#include <linux/io.h>
  11#include <linux/slab.h>
  12#include <linux/leds.h>
  13
  14#include <mach/cm.h>
  15#include <mach/hardware.h>
  16#include <mach/platform.h>
  17
  18#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
  19
  20#define ALPHA_REG __io_address(INTEGRATOR_DBG_BASE)
  21#define LEDREG  (__io_address(INTEGRATOR_DBG_BASE) + INTEGRATOR_DBG_LEDS_OFFSET)
  22
  23struct integrator_led {
  24        struct led_classdev     cdev;
  25        u8                      mask;
  26};
  27
  28/*
  29 * The triggers lines up below will only be used if the
  30 * LED triggers are compiled in.
  31 */
  32static const struct {
  33        const char *name;
  34        const char *trigger;
  35} integrator_leds[] = {
  36        { "integrator:green0", "heartbeat", },
  37        { "integrator:yellow", },
  38        { "integrator:red", },
  39        { "integrator:green1", },
  40        { "integrator:core_module", "cpu0", },
  41};
  42
  43static void integrator_led_set(struct led_classdev *cdev,
  44                              enum led_brightness b)
  45{
  46        struct integrator_led *led = container_of(cdev,
  47                                                 struct integrator_led, cdev);
  48        u32 reg = __raw_readl(LEDREG);
  49
  50        if (b != LED_OFF)
  51                reg |= led->mask;
  52        else
  53                reg &= ~led->mask;
  54
  55        while (__raw_readl(ALPHA_REG) & 1)
  56                cpu_relax();
  57
  58        __raw_writel(reg, LEDREG);
  59}
  60
  61static enum led_brightness integrator_led_get(struct led_classdev *cdev)
  62{
  63        struct integrator_led *led = container_of(cdev,
  64                                                 struct integrator_led, cdev);
  65        u32 reg = __raw_readl(LEDREG);
  66
  67        return (reg & led->mask) ? LED_FULL : LED_OFF;
  68}
  69
  70static void cm_led_set(struct led_classdev *cdev,
  71                              enum led_brightness b)
  72{
  73        if (b != LED_OFF)
  74                cm_control(CM_CTRL_LED, CM_CTRL_LED);
  75        else
  76                cm_control(CM_CTRL_LED, 0);
  77}
  78
  79static enum led_brightness cm_led_get(struct led_classdev *cdev)
  80{
  81        u32 reg = readl(CM_CTRL);
  82
  83        return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF;
  84}
  85
  86static int __init integrator_leds_init(void)
  87{
  88        int i;
  89
  90        for (i = 0; i < ARRAY_SIZE(integrator_leds); i++) {
  91                struct integrator_led *led;
  92
  93                led = kzalloc(sizeof(*led), GFP_KERNEL);
  94                if (!led)
  95                        break;
  96
  97
  98                led->cdev.name = integrator_leds[i].name;
  99
 100                if (i == 4) { /* Setting for LED in core module */
 101                        led->cdev.brightness_set = cm_led_set;
 102                        led->cdev.brightness_get = cm_led_get;
 103                } else {
 104                        led->cdev.brightness_set = integrator_led_set;
 105                        led->cdev.brightness_get = integrator_led_get;
 106                }
 107
 108                led->cdev.default_trigger = integrator_leds[i].trigger;
 109                led->mask = BIT(i);
 110
 111                if (led_classdev_register(NULL, &led->cdev) < 0) {
 112                        kfree(led);
 113                        break;
 114                }
 115        }
 116
 117        return 0;
 118}
 119
 120/*
 121 * Since we may have triggers on any subsystem, defer registration
 122 * until after subsystem_init.
 123 */
 124fs_initcall(integrator_leds_init);
 125#endif
 126