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#include <asm/system_misc.h> 13 14#include <mach/regs-ost.h> 15#include <mach/reset.h> 16#include <mach/smemc.h> 17 18unsigned int reset_status; 19EXPORT_SYMBOL(reset_status); 20 21static void do_hw_reset(void); 22 23static int reset_gpio = -1; 24 25int init_gpio_reset(int gpio, int output, int level) 26{ 27 int rc; 28 29 rc = gpio_request(gpio, "reset generator"); 30 if (rc) { 31 printk(KERN_ERR "Can't request reset_gpio\n"); 32 goto out; 33 } 34 35 if (output) 36 rc = gpio_direction_output(gpio, level); 37 else 38 rc = gpio_direction_input(gpio); 39 if (rc) { 40 printk(KERN_ERR "Can't configure reset_gpio\n"); 41 gpio_free(gpio); 42 goto out; 43 } 44 45out: 46 if (!rc) 47 reset_gpio = gpio; 48 49 return rc; 50} 51 52/* 53 * Trigger GPIO reset. 54 * This covers various types of logic connecting gpio pin 55 * to RESET pins (nRESET or GPIO_RESET): 56 */ 57static void do_gpio_reset(void) 58{ 59 BUG_ON(reset_gpio == -1); 60 61 /* drive it low */ 62 gpio_direction_output(reset_gpio, 0); 63 mdelay(2); 64 /* rising edge or drive high */ 65 gpio_set_value(reset_gpio, 1); 66 mdelay(2); 67 /* falling edge */ 68 gpio_set_value(reset_gpio, 0); 69 70 /* give it some time */ 71 mdelay(10); 72 73 WARN_ON(1); 74 /* fallback */ 75 do_hw_reset(); 76} 77 78static void do_hw_reset(void) 79{ 80 /* Initialize the watchdog and let it fire */ 81 writel_relaxed(OWER_WME, OWER); 82 writel_relaxed(OSSR_M3, OSSR); 83 /* ... in 100 ms */ 84 writel_relaxed(readl_relaxed(OSCR) + 368640, OSMR3); 85 /* 86 * SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71) 87 * we put SDRAM into self-refresh to prevent that 88 */ 89 while (1) 90 writel_relaxed(MDREFR_SLFRSH, MDREFR); 91} 92 93void pxa_restart(enum reboot_mode mode, const char *cmd) 94{ 95 local_irq_disable(); 96 local_fiq_disable(); 97 98 clear_reset_status(RESET_STATUS_ALL); 99 100 switch (mode) { 101 case REBOOT_SOFT: 102 /* Jump into ROM at address 0 */ 103 soft_restart(0); 104 break; 105 case REBOOT_GPIO: 106 do_gpio_reset(); 107 break; 108 case REBOOT_HARD: 109 default: 110 do_hw_reset(); 111 break; 112 } 113} 114