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 <asm/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
31static char led_state;
32static char hw_led_state;
33
34static DEFINE_SPINLOCK(leds_lock);
35extern spinlock_t gpio_lock;
36
37static void netwinder_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		led_state |= LED_STATE_ENABLED;
46		hw_led_state = GPIO_GREEN_LED;
47		break;
48
49	case led_stop:
50		led_state &= ~LED_STATE_ENABLED;
51		break;
52
53	case led_claim:
54		led_state |= LED_STATE_CLAIMED;
55		hw_led_state = 0;
56		break;
57
58	case led_release:
59		led_state &= ~LED_STATE_CLAIMED;
60		hw_led_state = 0;
61		break;
62
63#ifdef CONFIG_LEDS_TIMER
64	case led_timer:
65		if (!(led_state & LED_STATE_CLAIMED))
66			hw_led_state ^= GPIO_GREEN_LED;
67		break;
68#endif
69
70#ifdef CONFIG_LEDS_CPU
71	case led_idle_start:
72		if (!(led_state & LED_STATE_CLAIMED))
73			hw_led_state &= ~GPIO_RED_LED;
74		break;
75
76	case led_idle_end:
77		if (!(led_state & LED_STATE_CLAIMED))
78			hw_led_state |= GPIO_RED_LED;
79		break;
80#endif
81
82	case led_halted:
83		if (!(led_state & LED_STATE_CLAIMED))
84			hw_led_state |= GPIO_RED_LED;
85		break;
86
87	case led_green_on:
88		if (led_state & LED_STATE_CLAIMED)
89			hw_led_state |= GPIO_GREEN_LED;
90		break;
91
92	case led_green_off:
93		if (led_state & LED_STATE_CLAIMED)
94			hw_led_state &= ~GPIO_GREEN_LED;
95		break;
96
97	case led_amber_on:
98		if (led_state & LED_STATE_CLAIMED)
99			hw_led_state |= GPIO_GREEN_LED | GPIO_RED_LED;
100		break;
101
102	case led_amber_off:
103		if (led_state & LED_STATE_CLAIMED)
104			hw_led_state &= ~(GPIO_GREEN_LED | GPIO_RED_LED);
105		break;
106
107	case led_red_on:
108		if (led_state & LED_STATE_CLAIMED)
109			hw_led_state |= GPIO_RED_LED;
110		break;
111
112	case led_red_off:
113		if (led_state & LED_STATE_CLAIMED)
114			hw_led_state &= ~GPIO_RED_LED;
115		break;
116
117	default:
118		break;
119	}
120
121	spin_unlock_irqrestore(&leds_lock, flags);
122
123	if  (led_state & LED_STATE_ENABLED) {
124		spin_lock_irqsave(&gpio_lock, flags);
125		gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
126		spin_unlock_irqrestore(&gpio_lock, flags);
127	}
128}
129
130static int __init leds_init(void)
131{
132	if (machine_is_netwinder())
133		leds_event = netwinder_leds_event;
134
135	leds_event(led_start);
136
137	return 0;
138}
139
140__initcall(leds_init);
141