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