diff options
Diffstat (limited to 'packages/linux/linux/acern30/n30-pm.patch')
-rw-r--r-- | packages/linux/linux/acern30/n30-pm.patch | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/packages/linux/linux/acern30/n30-pm.patch b/packages/linux/linux/acern30/n30-pm.patch new file mode 100644 index 0000000000..014043b55b --- /dev/null +++ b/packages/linux/linux/acern30/n30-pm.patch @@ -0,0 +1,296 @@ +Add suspend/resume support for the Acer N30. + +Index: linux-2.6.14/arch/arm/mach-s3c2410/mach-n30.c +=================================================================== +--- linux-2.6.14.orig/arch/arm/mach-s3c2410/mach-n30.c ++++ linux-2.6.14/arch/arm/mach-s3c2410/mach-n30.c +@@ -66,11 +66,46 @@ + #include "clock.h" + #include "devs.h" + #include "cpu.h" ++#include "pm.h" + + static struct map_desc n30_iodesc[] __initdata = { + /* nothing here yet */ + }; + ++/* This code is copied to physical address SDRAM_PA + 0x201000. The ++ * bootloader will jump there on a watchdog reset or when resuming ++ * from suspend to ram. */ ++ ++#define N30_RESUME_VA __va(S3C2410_SDRAM_PA + 0x201000) ++ ++static void __init n30_resume(void) __attribute__((naked)); ++static void __init n30_resume(void) ++{ ++ asm( ++ "mov r1, #0x56000000 \n\t" ++ ++ /* load GSTATUS2 and check for a wake from suspend */ ++ "ldr r0, [r1, #0xb4] \n\t" /* GSTATUS2 */ ++ "ands r0, r0, #2 \n\t" /* OFFRST */ ++ "beq 1f \n\t" ++ ++ /* it is a wake reset, so jump to the resume function ++ * pointed to by GSTATUS3 */ ++ "ldr pc, [r1, #0xb8] \n\t" /* GSTATUS3 */ ++ ++ /* Probably a watchdog reset, so fake a power on reset ++ * by writing PWRST to GSTATUS2 and then jump back to ++ * the bootloader. */ ++ "1: \n\t" ++ "mov r0, #1 \n\t" /* PWRST */ ++ "str r0, [r1, #0xb4] \n\t" /* GSTATUS2 */ ++ "mov pc, #0 \n\t" ++ ++ "n30_resume_end: \n\t" ++ ); ++} ++extern void n30_resume_end; ++ + static struct s3c2410_uartcfg n30_uartcfgs[] = { + /* Normal serial port */ + [0] = { +@@ -483,6 +518,154 @@ static void __init n30_hwinit(void) + __raw_writel(0x0000063f, S3C2410_GPHUP); + } + ++void n30_pm_gpio(void) ++{ ++ if (machine_is_n35()) { ++ /* Prepare for suspend to ram. This is what WinCE ++ * apparently does. I know where some of these pins ++ * are connected and ought to be moved to code related ++ * that hardware, but some stuff is magic so far. */ ++ ++ /* All this is magic. WinCE does this and it brings ++ * the power consumption in sleep mode down. */ ++ ++ /* Drive ADDR0, ADDR16..ADDR23, and ADDR26 low. ++ * ADDR24 and ADDR 25 are still working. ++ * nGCS1..nGCS5 are driven low. ++ * CLE, ALE, nFWE, nFRE, nRSTOUT and nFCW are working. */ ++ __raw_writel(0x007e0600, S3C2410_GPACON); ++ __raw_writel(0x00000000, S3C2410_GPADAT); ++ __raw_writel(0x00015556, S3C2410_GPBCON); ++ __raw_writel(0x00000011, S3C2410_GPBDAT); ++ __raw_writel(0x000007ff, S3C2410_GPBUP); ++ __raw_writel(0xaa950618, S3C2410_GPCCON); ++ __raw_writel(0x0000024c, S3C2410_GPCDAT); ++ __raw_writel(0x0000ffb6, S3C2410_GPCUP); ++ __raw_writel(0xaa95aaa5, S3C2410_GPDCON); ++ __raw_writel(0x00000202, S3C2410_GPDDAT); ++ __raw_writel(0x0000fffd, S3C2410_GPDUP); ++ __raw_writel(0xa56aaaaa, S3C2410_GPECON); ++ __raw_writel(0x0000c7c1, S3C2410_GPEDAT); ++ __raw_writel(0x0000ffff, S3C2410_GPEUP); ++ __raw_writel(0x0000aa22, S3C2410_GPFCON); ++ __raw_writel(0x000000f5, S3C2410_GPFDAT); ++ __raw_writel(0x000000fd, S3C2410_GPFUP); ++ __raw_writel(0xff40010a, S3C2410_GPGCON); ++ __raw_writel(0x0000abf5, S3C2410_GPGDAT); ++ __raw_writel(0x0000fcef, S3C2410_GPGUP); ++ __raw_writel(0x0014aaaa, S3C2410_GPHCON); ++ __raw_writel(0x0000062f, S3C2410_GPHDAT); ++ __raw_writel(0x000007ff, S3C2410_GPHUP); ++ ++ /* Turn GPB6 into an output and drive it low. */ ++ s3c2410_gpio_cfgpin(S3C2410_GPB6, S3C2410_GPB6_OUTP); ++ s3c2410_gpio_setpin(S3C2410_GPB6, 0); ++ ++ /* Turn off the pull up on GPB7. */ ++ s3c2410_gpio_pullup(S3C2410_GPB7, 1); ++ ++ /* Drive GPC8 low */ ++ s3c2410_gpio_cfgpin(S3C2410_GPC8, S3C2410_GPC8_OUTP); ++ s3c2410_gpio_setpin(S3C2410_GPC8, 0); ++ s3c2410_gpio_pullup(S3C2410_GPC8, 1); ++ ++ /* Drive GPC9/VD[1] high. */ ++ s3c2410_gpio_cfgpin(S3C2410_GPC9, S3C2410_GPC9_OUTP); ++ s3c2410_gpio_setpin(S3C2410_GPC9, 1); ++ ++ /* Drive GPC10/VD[2] low. */ ++ s3c2410_gpio_cfgpin(S3C2410_GPC10, S3C2410_GPC10_OUTP); ++ s3c2410_gpio_setpin(S3C2410_GPC10, 0); ++ ++ /* Disable pull up on RS232 DTR? */ ++ s3c2410_gpio_pullup(S3C2410_GPC2, 1); ++ ++ /* Enable pull up on GPC6. */ ++ s3c2410_gpio_pullup(S3C2410_GPC6, 0); ++ ++ /* Turn GPD0 into an output and drive it low. */ ++ s3c2410_gpio_cfgpin(S3C2410_GPD0, S3C2410_GPD0_OUTP); ++ s3c2410_gpio_setpin(S3C2410_GPD0, 0); ++ s3c2410_gpio_pullup(S3C2410_GPD0, 1); ++ ++ /* Drive VD[9] high and enable the pull up. */ ++ s3c2410_gpio_cfgpin(S3C2410_GPD1, S3C2410_GPD1_OUTP); ++ s3c2410_gpio_setpin(S3C2410_GPD1, 1); ++ s3c2410_gpio_pullup(S3C2410_GPD1, 0); ++ ++ /* Drive DPD10 low. */ ++ s3c2410_gpio_setpin(S3C2410_GPD10, 0); ++ s3c2410_gpio_pullup(S3C2410_GPD10, 1); ++ ++ /* This may do something about the power planes. */ ++ s3c2410_gpio_setpin(S3C2410_GPE11, 0); ++ s3c2410_gpio_setpin(S3C2410_GPE12, 0); ++ s3c2410_gpio_setpin(S3C2410_GPE13, 0); ++ ++ /* Disable pull ups on H8. Don't know why. */ ++ s3c2410_gpio_pullup(S3C2410_GPH8, 1); ++ ++ /* LCD stuff, ought to be moved to n30_lcd_power. ++ * GPB8 is still an output and drives 0. ++ * GPB9 and GPB10 are turned into inputs. ++ * All pull ups are disabled. */ ++ s3c2410_gpio_setpin(S3C2410_GPB8, 0); ++ s3c2410_gpio_pullup(S3C2410_GPB8, 1); ++ s3c2410_gpio_cfgpin(S3C2410_GPB9, S3C2410_GPB9_INP); ++ s3c2410_gpio_pullup(S3C2410_GPB9, 1); ++ s3c2410_gpio_cfgpin(S3C2410_GPB10, S3C2410_GPB10_INP); ++ s3c2410_gpio_pullup(S3C2410_GPB10, 1); ++ ++ /* Disable IrDA (not done by WinCE). */ ++ s3c2410_gpio_setpin(S3C2410_GPB2, 1); ++ ++ /* Disable the GPS. */ ++ s3c2410_gpio_setpin(S3C2410_GPB4, 1); ++ s3c2410_gpio_setpin(S3C2410_GPG11, 1); ++ ++ /* Turn on flash write protect. */ ++ s3c2410_gpio_setpin(S3C2410_GPC5, 0); ++ ++ /* Disable pull ups on the SD/MMC port. This should ++ * maybe be done after power has been removed from the ++ * SD/MMC port. */ ++ s3c2410_gpio_pullup(S3C2410_GPE5, 1); ++ s3c2410_gpio_pullup(S3C2410_GPE6, 1); ++ s3c2410_gpio_pullup(S3C2410_GPE7, 1); ++ s3c2410_gpio_pullup(S3C2410_GPE8, 1); ++ s3c2410_gpio_pullup(S3C2410_GPE9, 1); ++ s3c2410_gpio_pullup(S3C2410_GPE10, 1); ++ ++ /* Disable MMC? On the N30 this makes a difference, ++ * on the N35, maybe not. */ ++ s3c2410_gpio_setpin(S3C2410_GPG4, 1); ++ ++ /* Enable pull up on SD/MMC switch. */ ++ s3c2410_gpio_pullup(S3C2410_GPF1, 0); ++ ++ /* Disable pull up on thumbwheel. Why not on the ++ * other inputs too? */ ++ s3c2410_gpio_pullup(S3C2410_GPG7, 1); ++ ++ /* Disable pull up on SD write protect switch. */ ++ s3c2410_gpio_pullup(S3C2410_GPG10, 1); ++ ++ /* Disable pull ups on the bluetooth/gps port. */ ++ s3c2410_gpio_pullup(S3C2410_GPH6, 1); ++ s3c2410_gpio_pullup(S3C2410_GPH7, 1); ++ ++ /* Drive CLKOUT0 high while sleeping. */ ++ s3c2410_gpio_cfgpin(S3C2410_GPH9, S3C2410_GPH9_OUTP); ++ s3c2410_gpio_setpin(S3C2410_GPH9, 1); ++ ++ /* Drive CLKOUT1 high while sleeping. */ ++ s3c2410_gpio_cfgpin(S3C2410_GPH10, S3C2410_GPH10_OUTP); ++ s3c2410_gpio_setpin(S3C2410_GPH10, 1); ++ ++ s3c2410_capture_regs(); ++ } ++} ++ + static void __init n30_map_io(void) + { + s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc)); +@@ -569,6 +752,12 @@ static void __init n30_init(void) + s3c_device_sdi.dev.platform_data = &n30_mmc_cfg; + s3c_device_nand.dev.platform_data = &n30_nand_info; + ++ s3c2410_pm_init(); ++ enable_irq_wake(IRQ_EINT0); ++ ++ memcpy_toio(N30_RESUME_VA, (void *)n30_resume, ++ &n30_resume_end - (void *)n30_resume); ++ + /* Clear any locks and write protects on the flash. */ + s3c2410_gpio_setpin(S3C2410_GPC5, 1); + msleep(1); +Index: linux-2.6.14/arch/arm/mach-s3c2410/pm.c +=================================================================== +--- linux-2.6.14.orig/arch/arm/mach-s3c2410/pm.c ++++ linux-2.6.14/arch/arm/mach-s3c2410/pm.c +@@ -565,6 +565,8 @@ static int s3c2410_pm_enter(suspend_stat + s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save)); + s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save)); + ++ n30_pm_gpio(); ++ + /* set the irq configuration for wake */ + + s3c2410_pm_configure_extint(); +@@ -601,6 +603,8 @@ static int s3c2410_pm_enter(suspend_stat + tmp &= S3C2410_GSTATUS2_OFFRESET; + __raw_writel(tmp, S3C2410_GSTATUS2); + ++ s3c2410_capture_regs(); ++ + /* restore the system state */ + + s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save)); +Index: linux-2.6.14/arch/arm/mach-s3c2410/sleep.S +=================================================================== +--- linux-2.6.14.orig/arch/arm/mach-s3c2410/sleep.S ++++ linux-2.6.14/arch/arm/mach-s3c2410/sleep.S +@@ -80,6 +80,7 @@ ENTRY(s3c2410_cpu_suspend) + + orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command + orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals ++ orr r8, r8, #3 @ turn on data pull ups + orr r9, r9, #S3C2410_CLKCON_POWER @ power down command + + teq pc, #0 @ first as a trial-run to load cache +Index: linux-2.6.14/arch/arm/Makefile +=================================================================== +--- linux-2.6.14.orig/arch/arm/Makefile ++++ linux-2.6.14/arch/arm/Makefile +@@ -99,6 +99,10 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0x + machine-$(CONFIG_ARCH_IMX) := imx + machine-$(CONFIG_ARCH_H720X) := h720x + machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 ++# The Acer N30/N35 needs to put some code at 0xc0201000 to handle ++# the watchdog interrupt and resume from suspend. ++textaddr-$(CONFIG_MACH_N30) := 0xc0208000 ++textaddr-$(CONFIG_MACH_N35) := 0xc0208000 + + ifeq ($(CONFIG_ARCH_EBSA110),y) + # This is what happens if you forget the IOCS16 line. +Index: linux-2.6.14/arch/arm/mm/init.c +=================================================================== +--- linux-2.6.14.orig/arch/arm/mm/init.c ++++ linux-2.6.14/arch/arm/mm/init.c +@@ -230,6 +230,9 @@ static __init void reserve_node_zero(pg_ + #endif + if (res_size) + reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size); ++ ++ if (machine_is_n30() || machine_is_n35()) ++ reserve_bootmem_node(pgdat, 0x30201000, PAGE_SIZE); + } + + void __init build_mem_type_table(void); +Index: linux-2.6.14/arch/arm/mach-s3c2410/Makefile.boot +=================================================================== +--- linux-2.6.14.orig/arch/arm/mach-s3c2410/Makefile.boot ++++ linux-2.6.14/arch/arm/mach-s3c2410/Makefile.boot +@@ -1,3 +1,7 @@ + zreladdr-y := 0x30008000 + params_phys-y := 0x30000100 + ++# The N30/N35 needs 0x30201000 for the bootloader interface. So place ++# the kernel after that. ++zreladdr-$(CONFIG_MACH_N30) := 0x30208000 ++zreladdr-$(CONFIG_MACH_N35) := 0x30208000 |