Commit | Line | Data |
---|---|---|
b5417019 LW |
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", }, | |
e031cd51 BW |
40 | { "versatile:2", "cpu0" }, |
41 | { "versatile:3", "cpu1" }, | |
42 | { "versatile:4", "cpu2" }, | |
43 | { "versatile:5", "cpu3" }, | |
b5417019 LW |
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); |