Merge branch 'for-rmk' of git://pasiphae.extern.pengutronix.de/git/imx/linux-2.6.git
[linux-2.6] / arch / arm / mach-pxa / reset.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License version 2 as
4  * published by the Free Software Foundation.
5  */
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/delay.h>
9 #include <linux/gpio.h>
10 #include <linux/io.h>
11 #include <asm/proc-fns.h>
12
13 #include <mach/pxa-regs.h>
14 #include <mach/reset.h>
15
16 unsigned int reset_status;
17 EXPORT_SYMBOL(reset_status);
18
19 static void do_hw_reset(void);
20
21 static int reset_gpio = -1;
22
23 int init_gpio_reset(int gpio)
24 {
25         int rc;
26
27         rc = gpio_request(gpio, "reset generator");
28         if (rc) {
29                 printk(KERN_ERR "Can't request reset_gpio\n");
30                 goto out;
31         }
32
33         rc = gpio_direction_input(gpio);
34         if (rc) {
35                 printk(KERN_ERR "Can't configure reset_gpio for input\n");
36                 gpio_free(gpio);
37                 goto out;
38         }
39
40 out:
41         if (!rc)
42                 reset_gpio = gpio;
43
44         return rc;
45 }
46
47 /*
48  * Trigger GPIO reset.
49  * This covers various types of logic connecting gpio pin
50  * to RESET pins (nRESET or GPIO_RESET):
51  */
52 static void do_gpio_reset(void)
53 {
54         BUG_ON(reset_gpio == -1);
55
56         /* drive it low */
57         gpio_direction_output(reset_gpio, 0);
58         mdelay(2);
59         /* rising edge or drive high */
60         gpio_set_value(reset_gpio, 1);
61         mdelay(2);
62         /* falling edge */
63         gpio_set_value(reset_gpio, 0);
64
65         /* give it some time */
66         mdelay(10);
67
68         WARN_ON(1);
69         /* fallback */
70         do_hw_reset();
71 }
72
73 static void do_hw_reset(void)
74 {
75         /* Initialize the watchdog and let it fire */
76         OWER = OWER_WME;
77         OSSR = OSSR_M3;
78         OSMR3 = OSCR + 368640;  /* ... in 100 ms */
79 }
80
81 void arch_reset(char mode)
82 {
83         clear_reset_status(RESET_STATUS_ALL);
84
85         switch (mode) {
86         case 's':
87                 /* Jump into ROM at address 0 */
88                 cpu_reset(0);
89                 break;
90         case 'h':
91                 do_hw_reset();
92                 break;
93         case 'g':
94                 do_gpio_reset();
95                 break;
96         }
97 }
98