Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75f10b46 authored by Dmitry Eremin-Solenikov's avatar Dmitry Eremin-Solenikov Committed by Russell King
Browse files

[ARM] 5047/2: Support resetting by asserting GPIO pin



This adds support for resetting via assertion of GPIO pin.
This e.g. is used on Sharp Zaurus SL-6000.

Signed-off-by: default avatarDmitry Baryshkov <dbaryshkov@gmail.com>
Acked-by: default avatarEric Miao <eric.miao@marvell.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent b8291ad0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@

# Common support (must be linked before board specific support)
obj-y				+= clock.o devices.o generic.o irq.o dma.o \
				   time.o gpio.o
				   time.o gpio.o reset.o
obj-$(CONFIG_PM)		+= pm.o sleep.o standby.o
obj-$(CONFIG_CPU_FREQ)		+= cpu-pxa.o

+95 −0
Original line number Diff line number Diff line
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <asm/io.h>
#include <asm/proc-fns.h>

#include <asm/arch/pxa-regs.h>

static void do_hw_reset(void);

static int reset_gpio = -1;

int init_gpio_reset(int gpio)
{
	int rc;

	rc = gpio_request(gpio, "reset generator");
	if (rc) {
		printk(KERN_ERR "Can't request reset_gpio\n");
		goto out;
	}

	rc = gpio_direction_input(gpio);
	if (rc) {
		printk(KERN_ERR "Can't configure reset_gpio for input\n");
		gpio_free(gpio);
		goto out;
	}

out:
	if (!rc)
		reset_gpio = gpio;

	return rc;
}

/*
 * Trigger GPIO reset.
 * This covers various types of logic connecting gpio pin
 * to RESET pins (nRESET or GPIO_RESET):
 */
static void do_gpio_reset(void)
{
	BUG_ON(reset_gpio == -1);

	/* drive it low */
	gpio_direction_output(reset_gpio, 0);
	mdelay(2);
	/* rising edge or drive high */
	gpio_set_value(reset_gpio, 1);
	mdelay(2);
	/* falling edge */
	gpio_set_value(reset_gpio, 0);

	/* give it some time */
	mdelay(10);

	WARN_ON(1);
	/* fallback */
	do_hw_reset();
}

static void do_hw_reset(void)
{
	/* Initialize the watchdog and let it fire */
	OWER = OWER_WME;
	OSSR = OSSR_M3;
	OSMR3 = OSCR + 368640;	/* ... in 100 ms */
}

void arch_reset(char mode)
{
	if (cpu_is_pxa2xx())
		RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;

	switch (mode) {
	case 's':
		/* Jump into ROM at address 0 */
		cpu_reset(0);
		break;
	case 'h':
		do_hw_reset();
		break;
	case 'g':
		do_gpio_reset();
		break;
	}
}
+5 −0
Original line number Diff line number Diff line
@@ -205,6 +205,11 @@ static inline void __deprecated pxa_set_cken(int clock, int enable)
 */
extern unsigned int get_memclk_frequency_10khz(void);

/*
 * register GPIO as reset generator
 */
extern int init_gpio_reset(int gpio);

#endif

#if defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
+1 −16
Original line number Diff line number Diff line
@@ -20,19 +20,4 @@ static inline void arch_idle(void)
}


static inline void arch_reset(char mode)
{
	if (cpu_is_pxa2xx())
		RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;

	if (mode == 's') {
		/* Jump into ROM at address 0 */
		cpu_reset(0);
	} else {
		/* Initialize the watchdog and let it fire */
		OWER = OWER_WME;
		OSSR = OSSR_M3;
		OSMR3 = OSCR + 368640;	/* ... in 100 ms */
	}
}
void arch_reset(char mode);