aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRod Whitby <rod@whitby.id.au>2008-01-28 18:29:38 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-02-04 08:15:23 -0500
commit14645ebabd96d29f3050ea78a6417b6653bc48cf (patch)
tree3843617246ee0bad21e1aa88fa81e64d1d240069
parent8e93675e5b235291d9dec91af78e01dd4f73629a (diff)
[ARM] 4768/2: ixp4xx: Button and LED updates for the nas100d board
* Convert GPIO and IRQ handling to use the <asm/gpio.h> api. * Perform the reset only after the power button has been held down for at least two seconds. Do the reset on the release of the power button, so that NAS devices which have been set to auto-power-on (by solder bridging the power button) do not continuously power cycle. * Remove all superflous constants from nas100d.h * Add LED constants to nas100d.h while we're there. * Update the board LED setup code to use those constants. Signed-off-by: Rod Whitby <rod@whitby.id.au> Acked-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-power.c75
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c14
-rw-r--r--include/asm-arm/arch-ixp4xx/nas100d.h18
3 files changed, 83 insertions, 24 deletions
diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c
index 29aa98d3a7fa..4c1c01bb3fe2 100644
--- a/arch/arm/mach-ixp4xx/nas100d-power.c
+++ b/arch/arm/mach-ixp4xx/nas100d-power.c
@@ -21,15 +21,59 @@
21#include <linux/irq.h> 21#include <linux/irq.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/reboot.h> 23#include <linux/reboot.h>
24#include <linux/jiffies.h>
25#include <linux/timer.h>
24 26
27#include <asm/gpio.h>
25#include <asm/mach-types.h> 28#include <asm/mach-types.h>
26 29
27static irqreturn_t nas100d_reset_handler(int irq, void *dev_id) 30/* This is used to make sure the power-button pusher is serious. The button
31 * must be held until the value of this counter reaches zero.
32 */
33static int power_button_countdown;
34
35/* Must hold the button down for at least this many counts to be processed */
36#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
37
38static void nas100d_power_handler(unsigned long data);
39static DEFINE_TIMER(nas100d_power_timer, nas100d_power_handler, 0, 0);
40
41static void nas100d_power_handler(unsigned long data)
28{ 42{
29 /* Signal init to do the ctrlaltdel action, this will bypass init if 43 /* This routine is called twice per second to check the
30 * it hasn't started and do a kernel_restart. 44 * state of the power button.
31 */ 45 */
32 ctrl_alt_del(); 46
47 if (gpio_get_value(NAS100D_PB_GPIO)) {
48
49 /* IO Pin is 1 (button pushed) */
50 if (power_button_countdown > 0)
51 power_button_countdown--;
52
53 } else {
54
55 /* Done on button release, to allow for auto-power-on mods. */
56 if (power_button_countdown == 0) {
57 /* Signal init to do the ctrlaltdel action,
58 * this will bypass init if it hasn't started
59 * and do a kernel_restart.
60 */
61 ctrl_alt_del();
62
63 /* Change the state of the power LED to "blink" */
64 gpio_line_set(NAS100D_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
65 } else {
66 power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
67 }
68 }
69
70 mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
71}
72
73static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
74{
75 /* This is the paper-clip reset, it shuts the machine down directly. */
76 machine_power_off();
33 77
34 return IRQ_HANDLED; 78 return IRQ_HANDLED;
35} 79}
@@ -39,17 +83,30 @@ static int __init nas100d_power_init(void)
39 if (!(machine_is_nas100d())) 83 if (!(machine_is_nas100d()))
40 return 0; 84 return 0;
41 85
42 set_irq_type(NAS100D_RB_IRQ, IRQT_LOW); 86 set_irq_type(gpio_to_irq(NAS100D_RB_GPIO), IRQT_LOW);
43 87
44 if (request_irq(NAS100D_RB_IRQ, &nas100d_reset_handler, 88 if (request_irq(gpio_to_irq(NAS100D_RB_GPIO), &nas100d_reset_handler,
45 IRQF_DISABLED, "NAS100D reset button", NULL) < 0) { 89 IRQF_DISABLED, "NAS100D reset button", NULL) < 0) {
46 90
47 printk(KERN_DEBUG "Reset Button IRQ %d not available\n", 91 printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
48 NAS100D_RB_IRQ); 92 gpio_to_irq(NAS100D_RB_GPIO));
49 93
50 return -EIO; 94 return -EIO;
51 } 95 }
52 96
97 /* The power button on the Iomega NAS100d is on GPIO 14, but
98 * it cannot handle interrupts on that GPIO line. So we'll
99 * have to poll it with a kernel timer.
100 */
101
102 /* Make sure that the power button GPIO is set up as an input */
103 gpio_line_config(NAS100D_PB_GPIO, IXP4XX_GPIO_IN);
104
105 /* Set the initial value for the power button IRQ handler */
106 power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
107
108 mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
109
53 return 0; 110 return 0;
54} 111}
55 112
@@ -58,7 +115,9 @@ static void __exit nas100d_power_exit(void)
58 if (!(machine_is_nas100d())) 115 if (!(machine_is_nas100d()))
59 return; 116 return;
60 117
61 free_irq(NAS100D_RB_IRQ, NULL); 118 del_timer_sync(&nas100d_power_timer);
119
120 free_irq(gpio_to_irq(NAS100D_RB_GPIO), NULL);
62} 121}
63 122
64module_init(nas100d_power_init); 123module_init(nas100d_power_init);
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 54d884fb2517..213a4cea9117 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -43,20 +43,20 @@ static struct platform_device nas100d_flash = {
43static struct resource nas100d_led_resources[] = { 43static struct resource nas100d_led_resources[] = {
44 { 44 {
45 .name = "wlan", /* green led */ 45 .name = "wlan", /* green led */
46 .start = 0, 46 .start = NAS100D_LED_WLAN_GPIO,
47 .end = 0, 47 .end = NAS100D_LED_WLAN_GPIO,
48 .flags = IXP4XX_GPIO_LOW, 48 .flags = IXP4XX_GPIO_LOW,
49 }, 49 },
50 { 50 {
51 .name = "ready", /* blue power led (off is flashing!) */ 51 .name = "power", /* blue power led (off=flashing) */
52 .start = 15, 52 .start = NAS100D_LED_PWR_GPIO,
53 .end = 15, 53 .end = NAS100D_LED_PWR_GPIO,
54 .flags = IXP4XX_GPIO_LOW, 54 .flags = IXP4XX_GPIO_LOW,
55 }, 55 },
56 { 56 {
57 .name = "disk", /* yellow led */ 57 .name = "disk", /* yellow led */
58 .start = 3, 58 .start = NAS100D_LED_DISK_GPIO,
59 .end = 3, 59 .end = NAS100D_LED_DISK_GPIO,
60 .flags = IXP4XX_GPIO_LOW, 60 .flags = IXP4XX_GPIO_LOW,
61 }, 61 },
62}; 62};
diff --git a/include/asm-arm/arch-ixp4xx/nas100d.h b/include/asm-arm/arch-ixp4xx/nas100d.h
index 131e0a1d0df3..98d937897bce 100644
--- a/include/asm-arm/arch-ixp4xx/nas100d.h
+++ b/include/asm-arm/arch-ixp4xx/nas100d.h
@@ -38,15 +38,15 @@
38 38
39/* Buttons */ 39/* Buttons */
40 40
41#define NAS100D_PB_GPIO 14 41#define NAS100D_PB_GPIO 14 /* power button */
42#define NAS100D_RB_GPIO 4 42#define NAS100D_RB_GPIO 4 /* reset button */
43
44/* Power control */
45
43#define NAS100D_PO_GPIO 12 /* power off */ 46#define NAS100D_PO_GPIO 12 /* power off */
44 47
45#define NAS100D_PB_IRQ IRQ_IXP4XX_GPIO14 48/* LEDs */
46#define NAS100D_RB_IRQ IRQ_IXP4XX_GPIO4
47 49
48/* 50#define NAS100D_LED_WLAN_GPIO 0
49#define NAS100D_PB_BM (1L << NAS100D_PB_GPIO) 51#define NAS100D_LED_DISK_GPIO 3
50#define NAS100D_PO_BM (1L << NAS100D_PO_GPIO) 52#define NAS100D_LED_PWR_GPIO 15
51#define NAS100D_RB_BM (1L << NAS100D_RB_GPIO)
52*/