xref: /openbmc/linux/arch/arm/mach-pxa/reset.c (revision 545e4006)
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 
97