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