[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: Dmitry Baryshkov <dbaryshkov@gmail.com> Acked-by: Eric Miao <eric.miao@marvell.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
b8291ad07a
commit
75f10b465a
4 changed files with 102 additions and 17 deletions
|
@ -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
arch/arm/mach-pxa/reset.c
Normal file
95
arch/arm/mach-pxa/reset.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue