diff options
Diffstat (limited to 'arch/arm/mach-shark/leds.c')
-rw-r--r-- | arch/arm/mach-shark/leds.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c new file mode 100644 index 000000000000..7bdeb70a0c10 --- /dev/null +++ b/arch/arm/mach-shark/leds.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/leds-shark.c | ||
3 | * by Alexander Schulz | ||
4 | * | ||
5 | * derived from: | ||
6 | * arch/arm/kernel/leds-footbridge.c | ||
7 | * Copyright (C) 1998-1999 Russell King | ||
8 | * | ||
9 | * DIGITAL Shark LED control routines. | ||
10 | * | ||
11 | * The leds use is as follows: | ||
12 | * - Green front - toggles state every 50 timer interrupts | ||
13 | * - Amber front - Unused, this is a dual color led (Amber/Green) | ||
14 | * - Amber back - On if system is not idle | ||
15 | * | ||
16 | * Changelog: | ||
17 | */ | ||
18 | #include <linux/config.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/ioport.h> | ||
24 | |||
25 | #include <asm/hardware.h> | ||
26 | #include <asm/leds.h> | ||
27 | #include <asm/io.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 short hw_led_state; | ||
34 | static short saved_state; | ||
35 | |||
36 | static DEFINE_SPINLOCK(leds_lock); | ||
37 | |||
38 | short sequoia_read(int addr) { | ||
39 | outw(addr,0x24); | ||
40 | return inw(0x26); | ||
41 | } | ||
42 | |||
43 | void sequoia_write(short value,short addr) { | ||
44 | outw(addr,0x24); | ||
45 | outw(value,0x26); | ||
46 | } | ||
47 | |||
48 | static void sequoia_leds_event(led_event_t evt) | ||
49 | { | ||
50 | unsigned long flags; | ||
51 | |||
52 | spin_lock_irqsave(&leds_lock, flags); | ||
53 | |||
54 | hw_led_state = sequoia_read(0x09); | ||
55 | |||
56 | switch (evt) { | ||
57 | case led_start: | ||
58 | hw_led_state |= SEQUOIA_LED_GREEN; | ||
59 | hw_led_state |= SEQUOIA_LED_AMBER; | ||
60 | #ifdef CONFIG_LEDS_CPU | ||
61 | hw_led_state |= SEQUOIA_LED_BACK; | ||
62 | #else | ||
63 | hw_led_state &= ~SEQUOIA_LED_BACK; | ||
64 | #endif | ||
65 | led_state |= LED_STATE_ENABLED; | ||
66 | break; | ||
67 | |||
68 | case led_stop: | ||
69 | hw_led_state &= ~SEQUOIA_LED_BACK; | ||
70 | hw_led_state |= SEQUOIA_LED_GREEN; | ||
71 | hw_led_state |= SEQUOIA_LED_AMBER; | ||
72 | led_state &= ~LED_STATE_ENABLED; | ||
73 | break; | ||
74 | |||
75 | case led_claim: | ||
76 | led_state |= LED_STATE_CLAIMED; | ||
77 | saved_state = hw_led_state; | ||
78 | hw_led_state &= ~SEQUOIA_LED_BACK; | ||
79 | hw_led_state |= SEQUOIA_LED_GREEN; | ||
80 | hw_led_state |= SEQUOIA_LED_AMBER; | ||
81 | break; | ||
82 | |||
83 | case led_release: | ||
84 | led_state &= ~LED_STATE_CLAIMED; | ||
85 | hw_led_state = saved_state; | ||
86 | break; | ||
87 | |||
88 | #ifdef CONFIG_LEDS_TIMER | ||
89 | case led_timer: | ||
90 | if (!(led_state & LED_STATE_CLAIMED)) | ||
91 | hw_led_state ^= SEQUOIA_LED_GREEN; | ||
92 | break; | ||
93 | #endif | ||
94 | |||
95 | #ifdef CONFIG_LEDS_CPU | ||
96 | case led_idle_start: | ||
97 | if (!(led_state & LED_STATE_CLAIMED)) | ||
98 | hw_led_state &= ~SEQUOIA_LED_BACK; | ||
99 | break; | ||
100 | |||
101 | case led_idle_end: | ||
102 | if (!(led_state & LED_STATE_CLAIMED)) | ||
103 | hw_led_state |= SEQUOIA_LED_BACK; | ||
104 | break; | ||
105 | #endif | ||
106 | |||
107 | case led_green_on: | ||
108 | if (led_state & LED_STATE_CLAIMED) | ||
109 | hw_led_state &= ~SEQUOIA_LED_GREEN; | ||
110 | break; | ||
111 | |||
112 | case led_green_off: | ||
113 | if (led_state & LED_STATE_CLAIMED) | ||
114 | hw_led_state |= SEQUOIA_LED_GREEN; | ||
115 | break; | ||
116 | |||
117 | case led_amber_on: | ||
118 | if (led_state & LED_STATE_CLAIMED) | ||
119 | hw_led_state &= ~SEQUOIA_LED_AMBER; | ||
120 | break; | ||
121 | |||
122 | case led_amber_off: | ||
123 | if (led_state & LED_STATE_CLAIMED) | ||
124 | hw_led_state |= SEQUOIA_LED_AMBER; | ||
125 | break; | ||
126 | |||
127 | case led_red_on: | ||
128 | if (led_state & LED_STATE_CLAIMED) | ||
129 | hw_led_state |= SEQUOIA_LED_BACK; | ||
130 | break; | ||
131 | |||
132 | case led_red_off: | ||
133 | if (led_state & LED_STATE_CLAIMED) | ||
134 | hw_led_state &= ~SEQUOIA_LED_BACK; | ||
135 | break; | ||
136 | |||
137 | default: | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | if (led_state & LED_STATE_ENABLED) | ||
142 | sequoia_write(hw_led_state,0x09); | ||
143 | |||
144 | spin_unlock_irqrestore(&leds_lock, flags); | ||
145 | } | ||
146 | |||
147 | static int __init leds_init(void) | ||
148 | { | ||
149 | extern void (*leds_event)(led_event_t); | ||
150 | short temp; | ||
151 | |||
152 | leds_event = sequoia_leds_event; | ||
153 | |||
154 | /* Make LEDs independent of power-state */ | ||
155 | request_region(0x24,4,"sequoia"); | ||
156 | temp = sequoia_read(0x09); | ||
157 | temp |= 1<<10; | ||
158 | sequoia_write(temp,0x09); | ||
159 | leds_event(led_start); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | __initcall(leds_init); | ||