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