1 /*
2  * linux/arch/arm/mach-omap1/leds-osk.c
3  *
4  * LED driver for OSK with optional Mistral QVGA board
5  */
6 #include <linux/gpio.h>
7 #include <linux/init.h>
8 
9 #include <mach/hardware.h>
10 #include <asm/leds.h>
11 
12 #include "leds.h"
13 
14 
15 #define LED_STATE_ENABLED	(1 << 0)
16 #define LED_STATE_CLAIMED	(1 << 1)
17 static u8 led_state;
18 
19 #define	TIMER_LED		(1 << 3)	/* Mistral board */
20 #define	IDLE_LED		(1 << 4)	/* Mistral board */
21 static u8 hw_led_state;
22 
23 
24 #ifdef	CONFIG_OMAP_OSK_MISTRAL
25 
26 /* For now, all system indicators require the Mistral board, since that
27  * LED can be manipulated without a task context.  This LED is either red,
28  * or green, but not both; it can't give the full "disco led" effect.
29  */
30 
31 #define GPIO_LED_RED		3
32 #define GPIO_LED_GREEN		OMAP_MPUIO(4)
33 
mistral_setled(void)34 static void mistral_setled(void)
35 {
36 	int	red = 0;
37 	int	green = 0;
38 
39 	if (hw_led_state & TIMER_LED)
40 		red = 1;
41 	else if (hw_led_state & IDLE_LED)
42 		green = 1;
43 	/* else both sides are disabled */
44 
45 	gpio_set_value(GPIO_LED_GREEN, green);
46 	gpio_set_value(GPIO_LED_RED, red);
47 }
48 
49 #endif
50 
osk_leds_event(led_event_t evt)51 void osk_leds_event(led_event_t evt)
52 {
53 	unsigned long	flags;
54 	u16		leds;
55 
56 	local_irq_save(flags);
57 
58 	if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
59 		goto done;
60 
61 	leds = hw_led_state;
62 	switch (evt) {
63 	case led_start:
64 		led_state |= LED_STATE_ENABLED;
65 		hw_led_state = 0;
66 		leds = ~0;
67 		break;
68 
69 	case led_halted:
70 	case led_stop:
71 		led_state &= ~LED_STATE_ENABLED;
72 		hw_led_state = 0;
73 		break;
74 
75 	case led_claim:
76 		led_state |= LED_STATE_CLAIMED;
77 		hw_led_state = 0;
78 		leds = ~0;
79 		break;
80 
81 	case led_release:
82 		led_state &= ~LED_STATE_CLAIMED;
83 		hw_led_state = 0;
84 		break;
85 
86 #ifdef	CONFIG_OMAP_OSK_MISTRAL
87 
88 	case led_timer:
89 		hw_led_state ^= TIMER_LED;
90 		mistral_setled();
91 		break;
92 
93 	case led_idle_start:	/* idle == off */
94 		hw_led_state &= ~IDLE_LED;
95 		mistral_setled();
96 		break;
97 
98 	case led_idle_end:
99 		hw_led_state |= IDLE_LED;
100 		mistral_setled();
101 		break;
102 
103 #endif	/* CONFIG_OMAP_OSK_MISTRAL */
104 
105 	default:
106 		break;
107 	}
108 
109 	leds ^= hw_led_state;
110 
111 done:
112 	local_irq_restore(flags);
113 }
114