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/regs-ost.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, int output, int level) 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 if (output) 34 rc = gpio_direction_output(gpio, level); 35 else 36 rc = gpio_direction_input(gpio); 37 if (rc) { 38 printk(KERN_ERR "Can't configure reset_gpio\n"); 39 gpio_free(gpio); 40 goto out; 41 } 42 43 out: 44 if (!rc) 45 reset_gpio = gpio; 46 47 return rc; 48 } 49 50 /* 51 * Trigger GPIO reset. 52 * This covers various types of logic connecting gpio pin 53 * to RESET pins (nRESET or GPIO_RESET): 54 */ 55 static void do_gpio_reset(void) 56 { 57 BUG_ON(reset_gpio == -1); 58 59 /* drive it low */ 60 gpio_direction_output(reset_gpio, 0); 61 mdelay(2); 62 /* rising edge or drive high */ 63 gpio_set_value(reset_gpio, 1); 64 mdelay(2); 65 /* falling edge */ 66 gpio_set_value(reset_gpio, 0); 67 68 /* give it some time */ 69 mdelay(10); 70 71 WARN_ON(1); 72 /* fallback */ 73 do_hw_reset(); 74 } 75 76 static void do_hw_reset(void) 77 { 78 /* Initialize the watchdog and let it fire */ 79 OWER = OWER_WME; 80 OSSR = OSSR_M3; 81 OSMR3 = OSCR + 368640; /* ... in 100 ms */ 82 } 83 84 void pxa_restart(char mode, const char *cmd) 85 { 86 local_irq_disable(); 87 local_fiq_disable(); 88 89 clear_reset_status(RESET_STATUS_ALL); 90 91 switch (mode) { 92 case 's': 93 /* Jump into ROM at address 0 */ 94 soft_restart(0); 95 break; 96 case 'g': 97 do_gpio_reset(); 98 break; 99 case 'h': 100 default: 101 do_hw_reset(); 102 break; 103 } 104 } 105 106