MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / char / resetswitch.c
blob3d61158254c5b6b1c6f314715a347709324290ab
1 /***************************************************************************/
3 /*
4 * linux/drivers/char/resetswitch.c
6 * Basic driver to support the NETtel software reset button.
8 * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
9 */
11 /***************************************************************************/
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/sched.h>
17 #include <linux/param.h>
18 #include <linux/init.h>
19 #include <asm/irq.h>
20 #include <asm/traps.h>
21 #include <asm/machdep.h>
22 #include <asm/coldfire.h>
23 #include <asm/mcftimer.h>
24 #include <asm/mcfsim.h>
25 #include <asm/delay.h>
27 /***************************************************************************/
28 #ifdef CONFIG_M5272
29 /***************************************************************************/
32 * Off-course the 5272 would have to deal with setting up and
33 * acknowledging interrupts differently to all other ColdFIre's!
35 #define SWITCH_IRQ 65
37 static void __inline__ mcf_enablevector(int vecnr)
39 volatile unsigned long *icrp;
40 icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
41 *icrp = (*icrp & 0x07777777) | 0xf0000000;
44 static void __inline__ mcf_disablevector(void)
46 volatile unsigned long *icrp;
47 icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
48 *icrp = (*icrp & 0x07777777) | 0x80000000;
51 static void __inline__ mcf_ackvector(void)
53 volatile unsigned long *icrp;
54 icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
55 *icrp = (*icrp & 0x07777777) | 0xf0000000;
58 static __inline__ int mcf_isvector(void)
60 return((*((volatile unsigned long *) (MCF_MBAR + MCFSIM_ISR)) & 0x80000000) == 0);
63 /***************************************************************************/
64 #else
65 /***************************************************************************/
68 * Common vector setup for 5206e, 5307 and 5407.
70 #define SWITCH_IRQ 31
72 static void __inline__ mcf_enablevector(int vecnr)
76 static void __inline__ mcf_disablevec(void)
78 mcf_setimr(mcf_getimr() | MCFSIM_IMR_EINT7);
81 static void __inline__ mcf_ackvector(void)
83 mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7);
86 static __inline__ int mcf_isvector(void)
88 return(mcf_getipr() & MCFSIM_IMR_EINT7);
91 /***************************************************************************/
92 #endif /* !CONFIG_M5272 */
93 /***************************************************************************/
95 void resetswitch_button(int irq, void *dev_id, struct pt_regs *regs)
97 extern void flash_eraseconfig(void);
98 static int inbutton = 0;
101 * IRQ7 is not maskable by the CPU core. It is possible
102 * that switch bounce mey get us back here before we have
103 * really serviced the interrupt.
105 if (inbutton)
106 return;
107 inbutton = 1;
109 /* Disable interrupt at SIM - best we can do... */
110 #if 0
111 mcf_disablevec();
112 #endif
114 /* Try and de-bounce the switch a little... */
115 udelay(10000);
117 #ifdef CONFIG_BLK_DEV_BLKMEM
118 flash_eraseconfig();
119 #endif
121 /* Don't leave here 'till button is no longer pushed! */
122 for (;;) {
123 if (mcf_isvector() != 0)
124 break;
127 HARD_RESET_NOW();
128 /* Should never get here... */
130 inbutton = 0;
132 mcf_ackvector();
135 /***************************************************************************/
137 int resetswitch_init(void)
139 mcf_enablevector(SWITCH_IRQ);
140 mcf_autovector(SWITCH_IRQ);
141 request_irq(SWITCH_IRQ, resetswitch_button,
142 (SA_INTERRUPT | IRQ_FLG_FAST), "Reset Button", NULL);
143 return(0);
146 module_init(resetswitch_init);
148 /***************************************************************************/