diff options
author | Bryan Wu <bryan.wu@canonical.com> | 2012-03-13 14:14:39 -0400 |
---|---|---|
committer | Bryan Wu <bryan.wu@canonical.com> | 2012-07-31 23:22:13 -0400 |
commit | dafbeadf4a9e1b2765641b687e3343be76d2eacd (patch) | |
tree | 81eb2fd9b19d1e3d70cc0af4c3c414500fcf7469 /arch/arm/plat-omap | |
parent | 4ad541901e5ba7aa18b46d7badf8a54eb7f174fe (diff) |
ARM: mach-omap1: retire custom LED code
Signed-off-by: Bryan Wu <bryan.wu@canonical.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm/plat-omap/debug-leds.c | 293 |
2 files changed, 68 insertions, 228 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index ad95c7a5d00..aa8e66857ed 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig | |||
@@ -41,9 +41,8 @@ config OMAP_DEBUG_DEVICES | |||
41 | For debug cards on TI reference boards. | 41 | For debug cards on TI reference boards. |
42 | 42 | ||
43 | config OMAP_DEBUG_LEDS | 43 | config OMAP_DEBUG_LEDS |
44 | bool | 44 | def_bool y if NEW_LEDS |
45 | depends on OMAP_DEBUG_DEVICES | 45 | depends on OMAP_DEBUG_DEVICES |
46 | default y if LEDS_CLASS | ||
47 | 46 | ||
48 | config OMAP_SMARTREFLEX | 47 | config OMAP_SMARTREFLEX |
49 | bool "SmartReflex support" | 48 | bool "SmartReflex support" |
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c index 39407cbe34c..24e23f3dd6a 100644 --- a/arch/arm/plat-omap/debug-leds.c +++ b/arch/arm/plat-omap/debug-leds.c | |||
@@ -1,279 +1,118 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/plat-omap/debug-leds.c | 2 | * linux/arch/arm/plat-omap/debug-leds.c |
3 | * | 3 | * |
4 | * Copyright 2011 by Bryan Wu <bryan.wu@canonical.com> | ||
4 | * Copyright 2003 by Texas Instruments Incorporated | 5 | * Copyright 2003 by Texas Instruments Incorporated |
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
9 | */ | 10 | */ |
10 | #include <linux/gpio.h> | 11 | |
12 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | 13 | #include <linux/init.h> |
12 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
13 | #include <linux/leds.h> | 15 | #include <linux/leds.h> |
14 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/slab.h> | ||
15 | 18 | ||
16 | #include <mach/hardware.h> | 19 | #include <mach/hardware.h> |
17 | #include <asm/leds.h> | ||
18 | #include <asm/mach-types.h> | 20 | #include <asm/mach-types.h> |
19 | 21 | ||
20 | #include <plat/fpga.h> | 22 | #include <plat/fpga.h> |
21 | 23 | ||
22 | |||
23 | /* Many OMAP development platforms reuse the same "debug board"; these | 24 | /* Many OMAP development platforms reuse the same "debug board"; these |
24 | * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the | 25 | * platforms include H2, H3, H4, and Perseus2. There are 16 LEDs on the |
25 | * debug board (all green), accessed through FPGA registers. | 26 | * debug board (all green), accessed through FPGA registers. |
26 | * | ||
27 | * The "surfer" expansion board and H2 sample board also have two-color | ||
28 | * green+red LEDs (in parallel), used here for timer and idle indicators | ||
29 | * in preference to the ones on the debug board, for a "Disco LED" effect. | ||
30 | * | ||
31 | * This driver exports either the original ARM LED API, the new generic | ||
32 | * one, or both. | ||
33 | */ | ||
34 | |||
35 | static spinlock_t lock; | ||
36 | static struct h2p2_dbg_fpga __iomem *fpga; | ||
37 | static u16 led_state, hw_led_state; | ||
38 | |||
39 | |||
40 | #ifdef CONFIG_OMAP_DEBUG_LEDS | ||
41 | #define new_led_api() 1 | ||
42 | #else | ||
43 | #define new_led_api() 0 | ||
44 | #endif | ||
45 | |||
46 | |||
47 | /*-------------------------------------------------------------------------*/ | ||
48 | |||
49 | /* original ARM debug LED API: | ||
50 | * - timer and idle leds (some boards use non-FPGA leds here); | ||
51 | * - up to 4 generic leds, easily accessed in-kernel (any context) | ||
52 | */ | 27 | */ |
53 | 28 | ||
54 | #define GPIO_LED_RED 3 | 29 | static struct h2p2_dbg_fpga __iomem *fpga; |
55 | #define GPIO_LED_GREEN OMAP_MPUIO(4) | ||
56 | |||
57 | #define LED_STATE_ENABLED 0x01 | ||
58 | #define LED_STATE_CLAIMED 0x02 | ||
59 | #define LED_TIMER_ON 0x04 | ||
60 | |||
61 | #define GPIO_IDLE GPIO_LED_GREEN | ||
62 | #define GPIO_TIMER GPIO_LED_RED | ||
63 | |||
64 | static void h2p2_dbg_leds_event(led_event_t evt) | ||
65 | { | ||
66 | unsigned long flags; | ||
67 | |||
68 | spin_lock_irqsave(&lock, flags); | ||
69 | |||
70 | if (!(led_state & LED_STATE_ENABLED) && evt != led_start) | ||
71 | goto done; | ||
72 | |||
73 | switch (evt) { | ||
74 | case led_start: | ||
75 | if (fpga) | ||
76 | led_state |= LED_STATE_ENABLED; | ||
77 | break; | ||
78 | |||
79 | case led_stop: | ||
80 | case led_halted: | ||
81 | /* all leds off during suspend or shutdown */ | ||
82 | |||
83 | if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) { | ||
84 | gpio_set_value(GPIO_TIMER, 0); | ||
85 | gpio_set_value(GPIO_IDLE, 0); | ||
86 | } | ||
87 | |||
88 | __raw_writew(~0, &fpga->leds); | ||
89 | led_state &= ~LED_STATE_ENABLED; | ||
90 | goto done; | ||
91 | |||
92 | case led_claim: | ||
93 | led_state |= LED_STATE_CLAIMED; | ||
94 | hw_led_state = 0; | ||
95 | break; | ||
96 | |||
97 | case led_release: | ||
98 | led_state &= ~LED_STATE_CLAIMED; | ||
99 | break; | ||
100 | |||
101 | #ifdef CONFIG_LEDS_TIMER | ||
102 | case led_timer: | ||
103 | led_state ^= LED_TIMER_ON; | ||
104 | |||
105 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
106 | hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER; | ||
107 | else { | ||
108 | gpio_set_value(GPIO_TIMER, | ||
109 | led_state & LED_TIMER_ON); | ||
110 | goto done; | ||
111 | } | ||
112 | |||
113 | break; | ||
114 | #endif | ||
115 | |||
116 | #ifdef CONFIG_LEDS_CPU | ||
117 | /* LED lit iff busy */ | ||
118 | case led_idle_start: | ||
119 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
120 | hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE; | ||
121 | else { | ||
122 | gpio_set_value(GPIO_IDLE, 1); | ||
123 | goto done; | ||
124 | } | ||
125 | |||
126 | break; | ||
127 | 30 | ||
128 | case led_idle_end: | 31 | static u16 fpga_led_state; |
129 | if (machine_is_omap_perseus2() || machine_is_omap_h4()) | ||
130 | hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE; | ||
131 | else { | ||
132 | gpio_set_value(GPIO_IDLE, 0); | ||
133 | goto done; | ||
134 | } | ||
135 | |||
136 | break; | ||
137 | #endif | ||
138 | |||
139 | case led_green_on: | ||
140 | hw_led_state |= H2P2_DBG_FPGA_LED_GREEN; | ||
141 | break; | ||
142 | case led_green_off: | ||
143 | hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN; | ||
144 | break; | ||
145 | |||
146 | case led_amber_on: | ||
147 | hw_led_state |= H2P2_DBG_FPGA_LED_AMBER; | ||
148 | break; | ||
149 | case led_amber_off: | ||
150 | hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER; | ||
151 | break; | ||
152 | |||
153 | case led_red_on: | ||
154 | hw_led_state |= H2P2_DBG_FPGA_LED_RED; | ||
155 | break; | ||
156 | case led_red_off: | ||
157 | hw_led_state &= ~H2P2_DBG_FPGA_LED_RED; | ||
158 | break; | ||
159 | |||
160 | case led_blue_on: | ||
161 | hw_led_state |= H2P2_DBG_FPGA_LED_BLUE; | ||
162 | break; | ||
163 | case led_blue_off: | ||
164 | hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE; | ||
165 | break; | ||
166 | |||
167 | default: | ||
168 | break; | ||
169 | } | ||
170 | |||
171 | |||
172 | /* | ||
173 | * Actually burn the LEDs | ||
174 | */ | ||
175 | if (led_state & LED_STATE_ENABLED) | ||
176 | __raw_writew(~hw_led_state, &fpga->leds); | ||
177 | |||
178 | done: | ||
179 | spin_unlock_irqrestore(&lock, flags); | ||
180 | } | ||
181 | |||
182 | /*-------------------------------------------------------------------------*/ | ||
183 | |||
184 | /* "new" LED API | ||
185 | * - with syfs access and generic triggering | ||
186 | * - not readily accessible to in-kernel drivers | ||
187 | */ | ||
188 | 32 | ||
189 | struct dbg_led { | 33 | struct dbg_led { |
190 | struct led_classdev cdev; | 34 | struct led_classdev cdev; |
191 | u16 mask; | 35 | u16 mask; |
192 | }; | 36 | }; |
193 | 37 | ||
194 | static struct dbg_led dbg_leds[] = { | 38 | static const struct { |
195 | /* REVISIT at least H2 uses different timer & cpu leds... */ | 39 | const char *name; |
196 | #ifndef CONFIG_LEDS_TIMER | 40 | const char *trigger; |
197 | { .mask = 1 << 0, .cdev.name = "d4:green", | 41 | } dbg_leds[] = { |
198 | .cdev.default_trigger = "heartbeat", }, | 42 | { "dbg:d4", "heartbeat", }, |
199 | #endif | 43 | { "dbg:d5", "cpu0", }, |
200 | #ifndef CONFIG_LEDS_CPU | 44 | { "dbg:d6", "default-on", }, |
201 | { .mask = 1 << 1, .cdev.name = "d5:green", }, /* !idle */ | 45 | { "dbg:d7", }, |
202 | #endif | 46 | { "dbg:d8", }, |
203 | { .mask = 1 << 2, .cdev.name = "d6:green", }, | 47 | { "dbg:d9", }, |
204 | { .mask = 1 << 3, .cdev.name = "d7:green", }, | 48 | { "dbg:d10", }, |
205 | 49 | { "dbg:d11", }, | |
206 | { .mask = 1 << 4, .cdev.name = "d8:green", }, | 50 | { "dbg:d12", }, |
207 | { .mask = 1 << 5, .cdev.name = "d9:green", }, | 51 | { "dbg:d13", }, |
208 | { .mask = 1 << 6, .cdev.name = "d10:green", }, | 52 | { "dbg:d14", }, |
209 | { .mask = 1 << 7, .cdev.name = "d11:green", }, | 53 | { "dbg:d15", }, |
210 | 54 | { "dbg:d16", }, | |
211 | { .mask = 1 << 8, .cdev.name = "d12:green", }, | 55 | { "dbg:d17", }, |
212 | { .mask = 1 << 9, .cdev.name = "d13:green", }, | 56 | { "dbg:d18", }, |
213 | { .mask = 1 << 10, .cdev.name = "d14:green", }, | 57 | { "dbg:d19", }, |
214 | { .mask = 1 << 11, .cdev.name = "d15:green", }, | ||
215 | |||
216 | #ifndef CONFIG_LEDS | ||
217 | { .mask = 1 << 12, .cdev.name = "d16:green", }, | ||
218 | { .mask = 1 << 13, .cdev.name = "d17:green", }, | ||
219 | { .mask = 1 << 14, .cdev.name = "d18:green", }, | ||
220 | { .mask = 1 << 15, .cdev.name = "d19:green", }, | ||
221 | #endif | ||
222 | }; | 58 | }; |
223 | 59 | ||
224 | static void | 60 | /* |
225 | fpga_led_set(struct led_classdev *cdev, enum led_brightness value) | 61 | * The triggers lines up below will only be used if the |
62 | * LED triggers are compiled in. | ||
63 | */ | ||
64 | static void dbg_led_set(struct led_classdev *cdev, | ||
65 | enum led_brightness b) | ||
226 | { | 66 | { |
227 | struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); | 67 | struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); |
228 | unsigned long flags; | 68 | u16 reg; |
229 | 69 | ||
230 | spin_lock_irqsave(&lock, flags); | 70 | reg = __raw_readw(&fpga->leds); |
231 | if (value == LED_OFF) | 71 | if (b != LED_OFF) |
232 | hw_led_state &= ~led->mask; | 72 | reg |= led->mask; |
233 | else | 73 | else |
234 | hw_led_state |= led->mask; | 74 | reg &= ~led->mask; |
235 | __raw_writew(~hw_led_state, &fpga->leds); | 75 | __raw_writew(reg, &fpga->leds); |
236 | spin_unlock_irqrestore(&lock, flags); | ||
237 | } | 76 | } |
238 | 77 | ||
239 | static void __init newled_init(struct device *dev) | 78 | static enum led_brightness dbg_led_get(struct led_classdev *cdev) |
240 | { | 79 | { |
241 | unsigned i; | 80 | struct dbg_led *led = container_of(cdev, struct dbg_led, cdev); |
242 | struct dbg_led *led; | 81 | u16 reg; |
243 | int status; | ||
244 | 82 | ||
245 | for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) { | 83 | reg = __raw_readw(&fpga->leds); |
246 | led->cdev.brightness_set = fpga_led_set; | 84 | return (reg & led->mask) ? LED_FULL : LED_OFF; |
247 | status = led_classdev_register(dev, &led->cdev); | ||
248 | if (status < 0) | ||
249 | break; | ||
250 | } | ||
251 | return; | ||
252 | } | 85 | } |
253 | 86 | ||
254 | 87 | static int fpga_probe(struct platform_device *pdev) | |
255 | /*-------------------------------------------------------------------------*/ | ||
256 | |||
257 | static int /* __init */ fpga_probe(struct platform_device *pdev) | ||
258 | { | 88 | { |
259 | struct resource *iomem; | 89 | struct resource *iomem; |
260 | 90 | int i; | |
261 | spin_lock_init(&lock); | ||
262 | 91 | ||
263 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 92 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
264 | if (!iomem) | 93 | if (!iomem) |
265 | return -ENODEV; | 94 | return -ENODEV; |
266 | 95 | ||
267 | fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); | 96 | fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE); |
268 | __raw_writew(~0, &fpga->leds); | 97 | __raw_writew(0xff, &fpga->leds); |
98 | |||
99 | for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) { | ||
100 | struct dbg_led *led; | ||
101 | |||
102 | led = kzalloc(sizeof(*led), GFP_KERNEL); | ||
103 | if (!led) | ||
104 | break; | ||
269 | 105 | ||
270 | #ifdef CONFIG_LEDS | 106 | led->cdev.name = dbg_leds[i].name; |
271 | leds_event = h2p2_dbg_leds_event; | 107 | led->cdev.brightness_set = dbg_led_set; |
272 | leds_event(led_start); | 108 | led->cdev.brightness_get = dbg_led_get; |
273 | #endif | 109 | led->cdev.default_trigger = dbg_leds[i].trigger; |
110 | led->mask = BIT(i); | ||
274 | 111 | ||
275 | if (new_led_api()) { | 112 | if (led_classdev_register(NULL, &led->cdev) < 0) { |
276 | newled_init(&pdev->dev); | 113 | kfree(led); |
114 | break; | ||
115 | } | ||
277 | } | 116 | } |
278 | 117 | ||
279 | return 0; | 118 | return 0; |
@@ -281,13 +120,15 @@ static int /* __init */ fpga_probe(struct platform_device *pdev) | |||
281 | 120 | ||
282 | static int fpga_suspend_noirq(struct device *dev) | 121 | static int fpga_suspend_noirq(struct device *dev) |
283 | { | 122 | { |
284 | __raw_writew(~0, &fpga->leds); | 123 | fpga_led_state = __raw_readw(&fpga->leds); |
124 | __raw_writew(0xff, &fpga->leds); | ||
125 | |||
285 | return 0; | 126 | return 0; |
286 | } | 127 | } |
287 | 128 | ||
288 | static int fpga_resume_noirq(struct device *dev) | 129 | static int fpga_resume_noirq(struct device *dev) |
289 | { | 130 | { |
290 | __raw_writew(~hw_led_state, &fpga->leds); | 131 | __raw_writew(~fpga_led_state, &fpga->leds); |
291 | return 0; | 132 | return 0; |
292 | } | 133 | } |
293 | 134 | ||