diff options
author | Linus Walleij <linus.walleij@stericsson.com> | 2010-07-20 17:32:00 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-07-26 05:48:29 -0400 |
commit | b5417019a6e614f5285f9eb8f9e5b2d62395965b (patch) | |
tree | 2e5a4f4b3c761367ac02435ebcf1deda8e87ee78 /arch/arm/plat-versatile | |
parent | ce8962455e902ffa08d59fd2b113942eaaffb0d6 (diff) |
ARM: 6235/2: driver for the LEDs found in the later ARM refdesigns
This adds a simple driver supporting the new LED framework with
triggers and all for the RealView and Versatile platforms. The
RealView and Versatile platform drivers were arranged to compile
for all-but-integrator as a side effect since the Integrator has
a different LED driver.
Signed-off-by: Linus Walleij <triad@df.lth.se>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/plat-versatile')
-rw-r--r-- | arch/arm/plat-versatile/Makefile | 7 | ||||
-rw-r--r-- | arch/arm/plat-versatile/leds.c | 103 |
2 files changed, 108 insertions, 2 deletions
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 9b1a66816aa6..505a8f89601c 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile | |||
@@ -1,4 +1,7 @@ | |||
1 | obj-y := clock.o | 1 | obj-y := clock.o |
2 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o | 2 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o |
3 | obj-$(CONFIG_ARCH_REALVIEW) += sched-clock.o | 3 | # For all but the Integrator, compile these |
4 | obj-$(CONFIG_ARCH_VERSATILE) += sched-clock.o | 4 | ifeq ($(CONFIG_ARCH_INTEGRATOR),) |
5 | obj-y += sched-clock.o | ||
6 | obj-$(CONFIG_LEDS_CLASS) += leds.o | ||
7 | endif | ||
diff --git a/arch/arm/plat-versatile/leds.c b/arch/arm/plat-versatile/leds.c new file mode 100644 index 000000000000..3169fa555ea6 --- /dev/null +++ b/arch/arm/plat-versatile/leds.c | |||
@@ -0,0 +1,103 @@ | |||
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/io.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/leds.h> | ||
13 | |||
14 | #include <mach/hardware.h> | ||
15 | #include <mach/platform.h> | ||
16 | |||
17 | #ifdef VERSATILE_SYS_BASE | ||
18 | #define LEDREG (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LED_OFFSET) | ||
19 | #endif | ||
20 | |||
21 | #ifdef REALVIEW_SYS_BASE | ||
22 | #define LEDREG (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET) | ||
23 | #endif | ||
24 | |||
25 | struct versatile_led { | ||
26 | struct led_classdev cdev; | ||
27 | u8 mask; | ||
28 | }; | ||
29 | |||
30 | /* | ||
31 | * The triggers lines up below will only be used if the | ||
32 | * LED triggers are compiled in. | ||
33 | */ | ||
34 | static const struct { | ||
35 | const char *name; | ||
36 | const char *trigger; | ||
37 | } versatile_leds[] = { | ||
38 | { "versatile:0", "heartbeat", }, | ||
39 | { "versatile:1", "mmc0", }, | ||
40 | { "versatile:2", }, | ||
41 | { "versatile:3", }, | ||
42 | { "versatile:4", }, | ||
43 | { "versatile:5", }, | ||
44 | { "versatile:6", }, | ||
45 | { "versatile:7", }, | ||
46 | }; | ||
47 | |||
48 | static void versatile_led_set(struct led_classdev *cdev, | ||
49 | enum led_brightness b) | ||
50 | { | ||
51 | struct versatile_led *led = container_of(cdev, | ||
52 | struct versatile_led, cdev); | ||
53 | u32 reg = readl(LEDREG); | ||
54 | |||
55 | if (b != LED_OFF) | ||
56 | reg |= led->mask; | ||
57 | else | ||
58 | reg &= ~led->mask; | ||
59 | writel(reg, LEDREG); | ||
60 | } | ||
61 | |||
62 | static enum led_brightness versatile_led_get(struct led_classdev *cdev) | ||
63 | { | ||
64 | struct versatile_led *led = container_of(cdev, | ||
65 | struct versatile_led, cdev); | ||
66 | u32 reg = readl(LEDREG); | ||
67 | |||
68 | return (reg & led->mask) ? LED_FULL : LED_OFF; | ||
69 | } | ||
70 | |||
71 | static int __init versatile_leds_init(void) | ||
72 | { | ||
73 | int i; | ||
74 | |||
75 | /* All ON */ | ||
76 | writel(0xff, LEDREG); | ||
77 | for (i = 0; i < ARRAY_SIZE(versatile_leds); i++) { | ||
78 | struct versatile_led *led; | ||
79 | |||
80 | led = kzalloc(sizeof(*led), GFP_KERNEL); | ||
81 | if (!led) | ||
82 | break; | ||
83 | |||
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 | |||
99 | /* | ||
100 | * Since we may have triggers on any subsystem, defer registration | ||
101 | * until after subsystem_init. | ||
102 | */ | ||
103 | fs_initcall(versatile_leds_init); | ||