aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-shark/leds.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-shark/leds.c')
-rw-r--r--arch/arm/mach-shark/leds.c220
1 files changed, 86 insertions, 134 deletions
diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c
index 25609076921f..081c778a10ac 100644
--- a/arch/arm/mach-shark/leds.c
+++ b/arch/arm/mach-shark/leds.c
@@ -1,165 +1,117 @@
1/* 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. 2 * DIGITAL Shark LED control routines.
10 * 3 *
11 * The leds use is as follows: 4 * Driver for the 3 user LEDs found on the Shark
12 * - Green front - toggles state every 50 timer interrupts 5 * Based on Versatile and RealView machine LED code
13 * - Amber front - Unused, this is a dual color led (Amber/Green)
14 * - Amber back - On if system is not idle
15 * 6 *
16 * Changelog: 7 * License terms: GNU General Public License (GPL) version 2
8 * Author: Bryan Wu <bryan.wu@canonical.com>
17 */ 9 */
18#include <linux/kernel.h> 10#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/init.h> 11#include <linux/init.h>
21#include <linux/spinlock.h>
22#include <linux/ioport.h>
23#include <linux/io.h> 12#include <linux/io.h>
13#include <linux/ioport.h>
14#include <linux/slab.h>
15#include <linux/leds.h>
24 16
25#include <asm/leds.h> 17#include <asm/mach-types.h>
26 18
27#define LED_STATE_ENABLED 1 19#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
28#define LED_STATE_CLAIMED 2 20struct shark_led {
21 struct led_classdev cdev;
22 u8 mask;
23};
29 24
30#define SEQUOIA_LED_GREEN (1<<6) 25/*
31#define SEQUOIA_LED_AMBER (1<<5) 26 * The triggers lines up below will only be used if the
32#define SEQUOIA_LED_BACK (1<<7) 27 * LED triggers are compiled in.
28 */
29static const struct {
30 const char *name;
31 const char *trigger;
32} shark_leds[] = {
33 { "shark:amber0", "default-on", }, /* Bit 5 */
34 { "shark:green", "heartbeat", }, /* Bit 6 */
35 { "shark:amber1", "cpu0" }, /* Bit 7 */
36};
37
38static u16 led_reg_read(void)
39{
40 outw(0x09, 0x24);
41 return inw(0x26);
42}
33 43
34static char led_state; 44static void led_reg_write(u16 value)
35static short hw_led_state; 45{
36static short saved_state; 46 outw(0x09, 0x24);
47 outw(value, 0x26);
48}
37 49
38static DEFINE_RAW_SPINLOCK(leds_lock); 50static void shark_led_set(struct led_classdev *cdev,
51 enum led_brightness b)
52{
53 struct shark_led *led = container_of(cdev,
54 struct shark_led, cdev);
55 u16 reg = led_reg_read();
39 56
40short sequoia_read(int addr) { 57 if (b != LED_OFF)
41 outw(addr,0x24); 58 reg |= led->mask;
42 return inw(0x26); 59 else
43} 60 reg &= ~led->mask;
44 61
45void sequoia_write(short value,short addr) { 62 led_reg_write(reg);
46 outw(addr,0x24);
47 outw(value,0x26);
48} 63}
49 64
50static void sequoia_leds_event(led_event_t evt) 65static enum led_brightness shark_led_get(struct led_classdev *cdev)
51{ 66{
52 unsigned long flags; 67 struct shark_led *led = container_of(cdev,
53 68 struct shark_led, cdev);
54 raw_spin_lock_irqsave(&leds_lock, flags); 69 u16 reg = led_reg_read();
55 70
56 hw_led_state = sequoia_read(0x09); 71 return (reg & led->mask) ? LED_FULL : LED_OFF;
72}
57 73
58 switch (evt) { 74static int __init shark_leds_init(void)
59 case led_start: 75{
60 hw_led_state |= SEQUOIA_LED_GREEN; 76 int i;
61 hw_led_state |= SEQUOIA_LED_AMBER; 77 u16 reg;
62#ifdef CONFIG_LEDS_CPU
63 hw_led_state |= SEQUOIA_LED_BACK;
64#else
65 hw_led_state &= ~SEQUOIA_LED_BACK;
66#endif
67 led_state |= LED_STATE_ENABLED;
68 break;
69
70 case led_stop:
71 hw_led_state &= ~SEQUOIA_LED_BACK;
72 hw_led_state |= SEQUOIA_LED_GREEN;
73 hw_led_state |= SEQUOIA_LED_AMBER;
74 led_state &= ~LED_STATE_ENABLED;
75 break;
76
77 case led_claim:
78 led_state |= LED_STATE_CLAIMED;
79 saved_state = hw_led_state;
80 hw_led_state &= ~SEQUOIA_LED_BACK;
81 hw_led_state |= SEQUOIA_LED_GREEN;
82 hw_led_state |= SEQUOIA_LED_AMBER;
83 break;
84
85 case led_release:
86 led_state &= ~LED_STATE_CLAIMED;
87 hw_led_state = saved_state;
88 break;
89
90#ifdef CONFIG_LEDS_TIMER
91 case led_timer:
92 if (!(led_state & LED_STATE_CLAIMED))
93 hw_led_state ^= SEQUOIA_LED_GREEN;
94 break;
95#endif
96 78
97#ifdef CONFIG_LEDS_CPU 79 if (!machine_is_shark())
98 case led_idle_start: 80 return -ENODEV;
99 if (!(led_state & LED_STATE_CLAIMED))
100 hw_led_state &= ~SEQUOIA_LED_BACK;
101 break;
102 81
103 case led_idle_end: 82 for (i = 0; i < ARRAY_SIZE(shark_leds); i++) {
104 if (!(led_state & LED_STATE_CLAIMED)) 83 struct shark_led *led;
105 hw_led_state |= SEQUOIA_LED_BACK;
106 break;
107#endif
108 84
109 case led_green_on: 85 led = kzalloc(sizeof(*led), GFP_KERNEL);
110 if (led_state & LED_STATE_CLAIMED) 86 if (!led)
111 hw_led_state &= ~SEQUOIA_LED_GREEN; 87 break;
112 break;
113
114 case led_green_off:
115 if (led_state & LED_STATE_CLAIMED)
116 hw_led_state |= SEQUOIA_LED_GREEN;
117 break;
118
119 case led_amber_on:
120 if (led_state & LED_STATE_CLAIMED)
121 hw_led_state &= ~SEQUOIA_LED_AMBER;
122 break;
123
124 case led_amber_off:
125 if (led_state & LED_STATE_CLAIMED)
126 hw_led_state |= SEQUOIA_LED_AMBER;
127 break;
128
129 case led_red_on:
130 if (led_state & LED_STATE_CLAIMED)
131 hw_led_state |= SEQUOIA_LED_BACK;
132 break;
133
134 case led_red_off:
135 if (led_state & LED_STATE_CLAIMED)
136 hw_led_state &= ~SEQUOIA_LED_BACK;
137 break;
138
139 default:
140 break;
141 }
142 88
143 if (led_state & LED_STATE_ENABLED) 89 led->cdev.name = shark_leds[i].name;
144 sequoia_write(hw_led_state,0x09); 90 led->cdev.brightness_set = shark_led_set;
91 led->cdev.brightness_get = shark_led_get;
92 led->cdev.default_trigger = shark_leds[i].trigger;
145 93
146 raw_spin_unlock_irqrestore(&leds_lock, flags); 94 /* Count in 5 bits offset */
147} 95 led->mask = BIT(i + 5);
148 96
149static int __init leds_init(void) 97 if (led_classdev_register(NULL, &led->cdev) < 0) {
150{ 98 kfree(led);
151 extern void (*leds_event)(led_event_t); 99 break;
152 short temp; 100 }
153 101 }
154 leds_event = sequoia_leds_event;
155 102
156 /* Make LEDs independent of power-state */ 103 /* Make LEDs independent of power-state */
157 request_region(0x24,4,"sequoia"); 104 request_region(0x24, 4, "led_reg");
158 temp = sequoia_read(0x09); 105 reg = led_reg_read();
159 temp |= 1<<10; 106 reg |= 1 << 10;
160 sequoia_write(temp,0x09); 107 led_reg_write(reg);
161 leds_event(led_start); 108
162 return 0; 109 return 0;
163} 110}
164 111
165__initcall(leds_init); 112/*
113 * Since we may have triggers on any subsystem, defer registration
114 * until after subsystem_init.
115 */
116fs_initcall(shark_leds_init);
117#endif