Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[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 <asm/io.h>
11 #include <asm/proc-fns.h>
12
13 #include <asm/arch/pxa-regs.h>
14 #include <asm/arch/pxa2xx-regs.h>
15
16 static void do_hw_reset(void);
17
18 static int reset_gpio = -1;
19
20 int init_gpio_reset(int gpio)
21 {
22         int rc;
23
24         rc = gpio_request(gpio, "reset generator");
25         if (rc) {
26                 printk(KERN_ERR "Can't request reset_gpio\n");
27                 goto out;
28         }
29
30         rc = gpio_direction_input(gpio);
31         if (rc) {
32                 printk(KERN_ERR "Can't configure reset_gpio for input\n");
33                 gpio_free(gpio);
34                 goto out;
35         }
36
37 out:
38         if (!rc)
39                 reset_gpio = gpio;
40
41         return rc;
42 }
43
44 /*
45  * Trigger GPIO reset.
46  * This covers various types of logic connecting gpio pin
47  * to RESET pins (nRESET or GPIO_RESET):
48  */
49 static void do_gpio_reset(void)
50 {
51         BUG_ON(reset_gpio == -1);
52
53         /* drive it low */
54         gpio_direction_output(reset_gpio, 0);
55         mdelay(2);
56         /* rising edge or drive high */
57         gpio_set_value(reset_gpio, 1);
58         mdelay(2);
59         /* falling edge */
60         gpio_set_value(reset_gpio, 0);
61
62         /* give it some time */
63         mdelay(10);
64
65         WARN_ON(1);
66         /* fallback */
67         do_hw_reset();
68 }
69
70 static void do_hw_reset(void)
71 {
72         /* Initialize the watchdog and let it fire */
73         OWER = OWER_WME;
74         OSSR = OSSR_M3;
75         OSMR3 = OSCR + 368640;  /* ... in 100 ms */
76 }
77
78 void arch_reset(char mode)
79 {
80         if (cpu_is_pxa2xx())
81                 RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
82
83         switch (mode) {
84         case 's':
85                 /* Jump into ROM at address 0 */
86                 cpu_reset(0);
87                 break;
88         case 'h':
89                 do_hw_reset();
90                 break;
91         case 'g':
92                 do_gpio_reset();
93                 break;
94         }
95 }
96