1 /*
2  * LED driver for Atmel AT91-based boards.
3  *
4  *  Copyright (C) SAN People (Pty) Ltd
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10 */
11 
12 #include <linux/gpio.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/platform_device.h>
17 
18 #include <mach/board.h>
19 
20 
21 /* ------------------------------------------------------------------------- */
22 
23 #if defined(CONFIG_NEW_LEDS)
24 
25 /*
26  * New cross-platform LED support.
27  */
28 
29 static struct gpio_led_platform_data led_data;
30 
31 static struct platform_device at91_gpio_leds_device = {
32 	.name			= "leds-gpio",
33 	.id			= -1,
34 	.dev.platform_data	= &led_data,
35 };
36 
at91_gpio_leds(struct gpio_led * leds,int nr)37 void __init at91_gpio_leds(struct gpio_led *leds, int nr)
38 {
39 	int i;
40 
41 	if (!nr)
42 		return;
43 
44 	for (i = 0; i < nr; i++)
45 		at91_set_gpio_output(leds[i].gpio, leds[i].active_low);
46 
47 	led_data.leds = leds;
48 	led_data.num_leds = nr;
49 	platform_device_register(&at91_gpio_leds_device);
50 }
51 
52 #else
at91_gpio_leds(struct gpio_led * leds,int nr)53 void __init at91_gpio_leds(struct gpio_led *leds, int nr) {}
54 #endif
55 
56 
57 /* ------------------------------------------------------------------------- */
58 
59 #if defined (CONFIG_LEDS_ATMEL_PWM)
60 
61 /*
62  * PWM Leds
63  */
64 
65 static struct gpio_led_platform_data pwm_led_data;
66 
67 static struct platform_device at91_pwm_leds_device = {
68 	.name			= "leds-atmel-pwm",
69 	.id			= -1,
70 	.dev.platform_data	= &pwm_led_data,
71 };
72 
at91_pwm_leds(struct gpio_led * leds,int nr)73 void __init at91_pwm_leds(struct gpio_led *leds, int nr)
74 {
75 	int i;
76 	u32 pwm_mask = 0;
77 
78 	if (!nr)
79 		return;
80 
81 	for (i = 0; i < nr; i++)
82 		pwm_mask |= (1 << leds[i].gpio);
83 
84 	pwm_led_data.leds = leds;
85 	pwm_led_data.num_leds = nr;
86 
87 	at91_add_device_pwm(pwm_mask);
88 	platform_device_register(&at91_pwm_leds_device);
89 }
90 #else
at91_pwm_leds(struct gpio_led * leds,int nr)91 void __init at91_pwm_leds(struct gpio_led *leds, int nr){}
92 #endif
93 
94 
95 /* ------------------------------------------------------------------------- */
96 
97 #if defined(CONFIG_LEDS)
98 
99 #include <asm/leds.h>
100 
101 /*
102  * Old ARM-specific LED framework; not fully functional when generic time is
103  * in use.
104  */
105 
106 static u8 at91_leds_cpu;
107 static u8 at91_leds_timer;
108 
at91_led_on(unsigned int led)109 static inline void at91_led_on(unsigned int led)
110 {
111 	at91_set_gpio_value(led, 0);
112 }
113 
at91_led_off(unsigned int led)114 static inline void at91_led_off(unsigned int led)
115 {
116 	at91_set_gpio_value(led, 1);
117 }
118 
at91_led_toggle(unsigned int led)119 static inline void at91_led_toggle(unsigned int led)
120 {
121 	unsigned long is_off = at91_get_gpio_value(led);
122 	if (is_off)
123 		at91_led_on(led);
124 	else
125 		at91_led_off(led);
126 }
127 
128 
129 /*
130  * Handle LED events.
131  */
at91_leds_event(led_event_t evt)132 static void at91_leds_event(led_event_t evt)
133 {
134 	unsigned long flags;
135 
136 	local_irq_save(flags);
137 
138 	switch(evt) {
139 	case led_start:		/* System startup */
140 		at91_led_on(at91_leds_cpu);
141 		break;
142 
143 	case led_stop:		/* System stop / suspend */
144 		at91_led_off(at91_leds_cpu);
145 		break;
146 
147 #ifdef CONFIG_LEDS_TIMER
148 	case led_timer:		/* Every 50 timer ticks */
149 		at91_led_toggle(at91_leds_timer);
150 		break;
151 #endif
152 
153 #ifdef CONFIG_LEDS_CPU
154 	case led_idle_start:	/* Entering idle state */
155 		at91_led_off(at91_leds_cpu);
156 		break;
157 
158 	case led_idle_end:	/* Exit idle state */
159 		at91_led_on(at91_leds_cpu);
160 		break;
161 #endif
162 
163 	default:
164 		break;
165 	}
166 
167 	local_irq_restore(flags);
168 }
169 
170 
leds_init(void)171 static int __init leds_init(void)
172 {
173 	if (!at91_leds_timer || !at91_leds_cpu)
174 		return -ENODEV;
175 
176 	leds_event = at91_leds_event;
177 
178 	leds_event(led_start);
179 	return 0;
180 }
181 
182 __initcall(leds_init);
183 
184 
at91_init_leds(u8 cpu_led,u8 timer_led)185 void __init at91_init_leds(u8 cpu_led, u8 timer_led)
186 {
187 	/* Enable GPIO to access the LEDs */
188 	at91_set_gpio_output(cpu_led, 1);
189 	at91_set_gpio_output(timer_led, 1);
190 
191 	at91_leds_cpu	= cpu_led;
192 	at91_leds_timer	= timer_led;
193 }
194 
195 #else
at91_init_leds(u8 cpu_led,u8 timer_led)196 void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
197 #endif
198