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