xref: /openbmc/linux/arch/arm/mach-pxa/reset.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
275f10b46SDmitry Baryshkov #include <linux/kernel.h>
375f10b46SDmitry Baryshkov #include <linux/module.h>
475f10b46SDmitry Baryshkov #include <linux/delay.h>
575f10b46SDmitry Baryshkov #include <linux/gpio.h>
6fced80c7SRussell King #include <linux/io.h>
775f10b46SDmitry Baryshkov #include <asm/proc-fns.h>
89f97da78SDavid Howells #include <asm/system_misc.h>
975f10b46SDmitry Baryshkov 
10e6acc406SArnd Bergmann #include "regs-ost.h"
11e6acc406SArnd Bergmann #include "reset.h"
12e6acc406SArnd Bergmann #include "smemc.h"
13*a9ae9c52SArnd Bergmann #include "generic.h"
1475f10b46SDmitry Baryshkov 
1575f10b46SDmitry Baryshkov static void do_hw_reset(void);
1675f10b46SDmitry Baryshkov 
1775f10b46SDmitry Baryshkov static int reset_gpio = -1;
1875f10b46SDmitry Baryshkov 
init_gpio_reset(int gpio,int output,int level)19216e3b7aSDaniel Ribeiro int init_gpio_reset(int gpio, int output, int level)
2075f10b46SDmitry Baryshkov {
2175f10b46SDmitry Baryshkov 	int rc;
2275f10b46SDmitry Baryshkov 
2375f10b46SDmitry Baryshkov 	rc = gpio_request(gpio, "reset generator");
2475f10b46SDmitry Baryshkov 	if (rc) {
2575f10b46SDmitry Baryshkov 		printk(KERN_ERR "Can't request reset_gpio\n");
2675f10b46SDmitry Baryshkov 		goto out;
2775f10b46SDmitry Baryshkov 	}
2875f10b46SDmitry Baryshkov 
2969fc7eedSDmitry Baryshkov 	if (output)
30216e3b7aSDaniel Ribeiro 		rc = gpio_direction_output(gpio, level);
3169fc7eedSDmitry Baryshkov 	else
3275f10b46SDmitry Baryshkov 		rc = gpio_direction_input(gpio);
3375f10b46SDmitry Baryshkov 	if (rc) {
3469fc7eedSDmitry Baryshkov 		printk(KERN_ERR "Can't configure reset_gpio\n");
3575f10b46SDmitry Baryshkov 		gpio_free(gpio);
3675f10b46SDmitry Baryshkov 		goto out;
3775f10b46SDmitry Baryshkov 	}
3875f10b46SDmitry Baryshkov 
3975f10b46SDmitry Baryshkov out:
4075f10b46SDmitry Baryshkov 	if (!rc)
4175f10b46SDmitry Baryshkov 		reset_gpio = gpio;
4275f10b46SDmitry Baryshkov 
4375f10b46SDmitry Baryshkov 	return rc;
4475f10b46SDmitry Baryshkov }
4575f10b46SDmitry Baryshkov 
4675f10b46SDmitry Baryshkov /*
4775f10b46SDmitry Baryshkov  * Trigger GPIO reset.
4875f10b46SDmitry Baryshkov  * This covers various types of logic connecting gpio pin
4975f10b46SDmitry Baryshkov  * to RESET pins (nRESET or GPIO_RESET):
5075f10b46SDmitry Baryshkov  */
do_gpio_reset(void)5175f10b46SDmitry Baryshkov static void do_gpio_reset(void)
5275f10b46SDmitry Baryshkov {
5375f10b46SDmitry Baryshkov 	BUG_ON(reset_gpio == -1);
5475f10b46SDmitry Baryshkov 
5575f10b46SDmitry Baryshkov 	/* drive it low */
5675f10b46SDmitry Baryshkov 	gpio_direction_output(reset_gpio, 0);
5775f10b46SDmitry Baryshkov 	mdelay(2);
5875f10b46SDmitry Baryshkov 	/* rising edge or drive high */
5975f10b46SDmitry Baryshkov 	gpio_set_value(reset_gpio, 1);
6075f10b46SDmitry Baryshkov 	mdelay(2);
6175f10b46SDmitry Baryshkov 	/* falling edge */
6275f10b46SDmitry Baryshkov 	gpio_set_value(reset_gpio, 0);
6375f10b46SDmitry Baryshkov 
6475f10b46SDmitry Baryshkov 	/* give it some time */
6575f10b46SDmitry Baryshkov 	mdelay(10);
6675f10b46SDmitry Baryshkov 
6775f10b46SDmitry Baryshkov 	WARN_ON(1);
6875f10b46SDmitry Baryshkov 	/* fallback */
6975f10b46SDmitry Baryshkov 	do_hw_reset();
7075f10b46SDmitry Baryshkov }
7175f10b46SDmitry Baryshkov 
do_hw_reset(void)7275f10b46SDmitry Baryshkov static void do_hw_reset(void)
7375f10b46SDmitry Baryshkov {
7475f10b46SDmitry Baryshkov 	/* Initialize the watchdog and let it fire */
753169663aSRussell King 	writel_relaxed(OWER_WME, OWER);
763169663aSRussell King 	writel_relaxed(OSSR_M3, OSSR);
773169663aSRussell King 	/* ... in 100 ms */
783169663aSRussell King 	writel_relaxed(readl_relaxed(OSCR) + 368640, OSMR3);
79ff88b472SSergei Ianovich 	/*
80ff88b472SSergei Ianovich 	 * SDRAM hangs on watchdog reset on Marvell PXA270 (erratum 71)
81ff88b472SSergei Ianovich 	 * we put SDRAM into self-refresh to prevent that
82ff88b472SSergei Ianovich 	 */
83ff88b472SSergei Ianovich 	while (1)
84ff88b472SSergei Ianovich 		writel_relaxed(MDREFR_SLFRSH, MDREFR);
8575f10b46SDmitry Baryshkov }
8675f10b46SDmitry Baryshkov 
pxa_restart(enum reboot_mode mode,const char * cmd)877b6d864bSRobin Holt void pxa_restart(enum reboot_mode mode, const char *cmd)
8875f10b46SDmitry Baryshkov {
89271a74fcSRussell King 	local_irq_disable();
90271a74fcSRussell King 	local_fiq_disable();
91271a74fcSRussell King 
9204fef228SEric Miao 	clear_reset_status(RESET_STATUS_ALL);
9375f10b46SDmitry Baryshkov 
9475f10b46SDmitry Baryshkov 	switch (mode) {
957b6d864bSRobin Holt 	case REBOOT_SOFT:
9675f10b46SDmitry Baryshkov 		/* Jump into ROM at address 0 */
97e879c862SRussell King 		soft_restart(0);
9875f10b46SDmitry Baryshkov 		break;
997b6d864bSRobin Holt 	case REBOOT_GPIO:
10075f10b46SDmitry Baryshkov 		do_gpio_reset();
10175f10b46SDmitry Baryshkov 		break;
1027b6d864bSRobin Holt 	case REBOOT_HARD:
10328105fdaSJaya Kumar 	default:
10428105fdaSJaya Kumar 		do_hw_reset();
10528105fdaSJaya Kumar 		break;
10675f10b46SDmitry Baryshkov 	}
10775f10b46SDmitry Baryshkov }
108