1 /*
2  *  linux/arch/arm/mach-footbridge/netwinder-leds.c
3  *
4  *  Copyright (C) 1998-1999 Russell King
5  *
6  * 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  * published by the Free Software Foundation.
9  *
10  * NetWinder LED control routines.
11  *
12  * The Netwinder uses the leds as follows:
13  *  - Green - toggles state every 50 timer interrupts
14  *  - Red   - On if the system is not idle
15  *
16  * Changelog:
17  *   02-05-1999	RMK	Various cleanups
18  */
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/spinlock.h>
23 
24 #include <mach/hardware.h>
25 #include <asm/leds.h>
26 #include <asm/mach-types.h>
27 #include <asm/system.h>
28 
29 #define LED_STATE_ENABLED	1
30 #define LED_STATE_CLAIMED	2
31 static char led_state;
32 static char hw_led_state;
33 
34 static DEFINE_RAW_SPINLOCK(leds_lock);
35 
netwinder_leds_event(led_event_t evt)36 static void netwinder_leds_event(led_event_t evt)
37 {
38 	unsigned long flags;
39 
40 	raw_spin_lock_irqsave(&leds_lock, flags);
41 
42 	switch (evt) {
43 	case led_start:
44 		led_state |= LED_STATE_ENABLED;
45 		hw_led_state = GPIO_GREEN_LED;
46 		break;
47 
48 	case led_stop:
49 		led_state &= ~LED_STATE_ENABLED;
50 		break;
51 
52 	case led_claim:
53 		led_state |= LED_STATE_CLAIMED;
54 		hw_led_state = 0;
55 		break;
56 
57 	case led_release:
58 		led_state &= ~LED_STATE_CLAIMED;
59 		hw_led_state = 0;
60 		break;
61 
62 #ifdef CONFIG_LEDS_TIMER
63 	case led_timer:
64 		if (!(led_state & LED_STATE_CLAIMED))
65 			hw_led_state ^= GPIO_GREEN_LED;
66 		break;
67 #endif
68 
69 #ifdef CONFIG_LEDS_CPU
70 	case led_idle_start:
71 		if (!(led_state & LED_STATE_CLAIMED))
72 			hw_led_state &= ~GPIO_RED_LED;
73 		break;
74 
75 	case led_idle_end:
76 		if (!(led_state & LED_STATE_CLAIMED))
77 			hw_led_state |= GPIO_RED_LED;
78 		break;
79 #endif
80 
81 	case led_halted:
82 		if (!(led_state & LED_STATE_CLAIMED))
83 			hw_led_state |= GPIO_RED_LED;
84 		break;
85 
86 	case led_green_on:
87 		if (led_state & LED_STATE_CLAIMED)
88 			hw_led_state |= GPIO_GREEN_LED;
89 		break;
90 
91 	case led_green_off:
92 		if (led_state & LED_STATE_CLAIMED)
93 			hw_led_state &= ~GPIO_GREEN_LED;
94 		break;
95 
96 	case led_amber_on:
97 		if (led_state & LED_STATE_CLAIMED)
98 			hw_led_state |= GPIO_GREEN_LED | GPIO_RED_LED;
99 		break;
100 
101 	case led_amber_off:
102 		if (led_state & LED_STATE_CLAIMED)
103 			hw_led_state &= ~(GPIO_GREEN_LED | GPIO_RED_LED);
104 		break;
105 
106 	case led_red_on:
107 		if (led_state & LED_STATE_CLAIMED)
108 			hw_led_state |= GPIO_RED_LED;
109 		break;
110 
111 	case led_red_off:
112 		if (led_state & LED_STATE_CLAIMED)
113 			hw_led_state &= ~GPIO_RED_LED;
114 		break;
115 
116 	default:
117 		break;
118 	}
119 
120 	raw_spin_unlock_irqrestore(&leds_lock, flags);
121 
122 	if  (led_state & LED_STATE_ENABLED) {
123 		raw_spin_lock_irqsave(&nw_gpio_lock, flags);
124 		nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
125 		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
126 	}
127 }
128 
leds_init(void)129 static int __init leds_init(void)
130 {
131 	if (machine_is_netwinder())
132 		leds_event = netwinder_leds_event;
133 
134 	leds_event(led_start);
135 
136 	return 0;
137 }
138 
139 __initcall(leds_init);
140