Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / arch / arm / mach-shark / leds.c
1 /*
2  * arch/arm/mach-shark/leds.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/kernel.h>
19 #include <linux/module.h>
20 #include <linux/init.h>
21 #include <linux/spinlock.h>
22 #include <linux/ioport.h>
23 #include <linux/io.h>
24
25 #include <asm/leds.h>
26 #include <asm/system.h>
27
28 #define LED_STATE_ENABLED       1
29 #define LED_STATE_CLAIMED       2
30
31 #define SEQUOIA_LED_GREEN       (1<<6)
32 #define SEQUOIA_LED_AMBER       (1<<5)
33 #define SEQUOIA_LED_BACK        (1<<7)
34
35 static char led_state;
36 static short hw_led_state;
37 static short saved_state;
38
39 static DEFINE_SPINLOCK(leds_lock);
40
41 short sequoia_read(int addr) {
42   outw(addr,0x24);
43   return inw(0x26);
44 }
45
46 void sequoia_write(short value,short addr) {
47   outw(addr,0x24);
48   outw(value,0x26);
49 }
50
51 static void sequoia_leds_event(led_event_t evt)
52 {
53         unsigned long flags;
54
55         spin_lock_irqsave(&leds_lock, flags);
56
57         hw_led_state = sequoia_read(0x09);
58
59         switch (evt) {
60         case led_start:
61                 hw_led_state |= SEQUOIA_LED_GREEN;
62                 hw_led_state |= SEQUOIA_LED_AMBER;
63 #ifdef CONFIG_LEDS_CPU
64                 hw_led_state |= SEQUOIA_LED_BACK;
65 #else
66                 hw_led_state &= ~SEQUOIA_LED_BACK;
67 #endif
68                 led_state |= LED_STATE_ENABLED;
69                 break;
70
71         case led_stop:
72                 hw_led_state &= ~SEQUOIA_LED_BACK;
73                 hw_led_state |= SEQUOIA_LED_GREEN;
74                 hw_led_state |= SEQUOIA_LED_AMBER;
75                 led_state &= ~LED_STATE_ENABLED;
76                 break;
77
78         case led_claim:
79                 led_state |= LED_STATE_CLAIMED;
80                 saved_state = hw_led_state;
81                 hw_led_state &= ~SEQUOIA_LED_BACK;
82                 hw_led_state |= SEQUOIA_LED_GREEN;
83                 hw_led_state |= SEQUOIA_LED_AMBER;
84                 break;
85
86         case led_release:
87                 led_state &= ~LED_STATE_CLAIMED;
88                 hw_led_state = saved_state;
89                 break;
90
91 #ifdef CONFIG_LEDS_TIMER
92         case led_timer:
93                 if (!(led_state & LED_STATE_CLAIMED))
94                         hw_led_state ^= SEQUOIA_LED_GREEN;
95                 break;
96 #endif
97
98 #ifdef CONFIG_LEDS_CPU
99         case led_idle_start:
100                 if (!(led_state & LED_STATE_CLAIMED))
101                         hw_led_state &= ~SEQUOIA_LED_BACK;
102                 break;
103
104         case led_idle_end:
105                 if (!(led_state & LED_STATE_CLAIMED))
106                         hw_led_state |= SEQUOIA_LED_BACK;
107                 break;
108 #endif
109
110         case led_green_on:
111                 if (led_state & LED_STATE_CLAIMED)
112                         hw_led_state &= ~SEQUOIA_LED_GREEN;
113                 break;
114
115         case led_green_off:
116                 if (led_state & LED_STATE_CLAIMED)
117                         hw_led_state |= SEQUOIA_LED_GREEN;
118                 break;
119
120         case led_amber_on:
121                 if (led_state & LED_STATE_CLAIMED)
122                         hw_led_state &= ~SEQUOIA_LED_AMBER;
123                 break;
124
125         case led_amber_off:
126                 if (led_state & LED_STATE_CLAIMED)
127                         hw_led_state |= SEQUOIA_LED_AMBER;
128                 break;
129
130         case led_red_on:
131                 if (led_state & LED_STATE_CLAIMED)
132                         hw_led_state |= SEQUOIA_LED_BACK;
133                 break;
134
135         case led_red_off:
136                 if (led_state & LED_STATE_CLAIMED)
137                         hw_led_state &= ~SEQUOIA_LED_BACK;
138                 break;
139
140         default:
141                 break;
142         }
143
144         if  (led_state & LED_STATE_ENABLED)
145                 sequoia_write(hw_led_state,0x09);
146
147         spin_unlock_irqrestore(&leds_lock, flags);
148 }
149
150 static int __init leds_init(void)
151 {
152         extern void (*leds_event)(led_event_t);
153         short temp;
154         
155         leds_event = sequoia_leds_event;
156
157         /* Make LEDs independent of power-state */
158         request_region(0x24,4,"sequoia");
159         temp = sequoia_read(0x09);
160         temp |= 1<<10;
161         sequoia_write(temp,0x09);
162         leds_event(led_start);
163         return 0;
164 }
165
166 __initcall(leds_init);