From a7fe484e69fe95a7a9c8f47dc31e537e6b3e1888 Mon Sep 17 00:00:00 2001 From: Matt Reimer Date: Sun, 4 Jun 2006 19:46:42 +0000 Subject: handhelds-pxa-2.6_2.6.15-hh1: add a patch to fix resume on h2200. --- .../handhelds-pxa-2.6-2.6.15-hh1/.mtn2git_empty | 0 .../handhelds-pxa-2.6-2.6.15-hh1/h2200_pm.c.patch | 194 +++++++++++++++++++++ packages/linux/handhelds-pxa-2.6_2.6.15-hh1.bb | 1 + 3 files changed, 195 insertions(+) create mode 100644 packages/linux/handhelds-pxa-2.6-2.6.15-hh1/.mtn2git_empty create mode 100644 packages/linux/handhelds-pxa-2.6-2.6.15-hh1/h2200_pm.c.patch (limited to 'packages') diff --git a/packages/linux/handhelds-pxa-2.6-2.6.15-hh1/.mtn2git_empty b/packages/linux/handhelds-pxa-2.6-2.6.15-hh1/.mtn2git_empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/linux/handhelds-pxa-2.6-2.6.15-hh1/h2200_pm.c.patch b/packages/linux/handhelds-pxa-2.6-2.6.15-hh1/h2200_pm.c.patch new file mode 100644 index 0000000000..8ecc957848 --- /dev/null +++ b/packages/linux/handhelds-pxa-2.6-2.6.15-hh1/h2200_pm.c.patch @@ -0,0 +1,194 @@ +=================================================================== +RCS file: /home/cvs/linux/kernel26/arch/arm/mach-pxa/h2200/h2200_pm.c,v +retrieving revision 1.16 +retrieving revision 1.16.2.1 +diff -u -p -r1.16 -r1.16.2.1 +--- kernel26/arch/arm/mach-pxa/h2200/h2200_pm.c 2006/03/04 03:49:29 1.16 ++++ kernel26/arch/arm/mach-pxa/h2200/h2200_pm.c 2006/06/04 17:37:23 1.16.2.1 +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + + #include + #include +@@ -29,20 +28,19 @@ + must save the bootloader before it gets overwritten, and restore it at + suspend. + +- There is are two problems with using the HTC bootloader: +- 1) as it primes the memory system on resume, it overwrites 0xa0000000; +- 2) it does its initialization and then jumps to 0xa0040000, which on Linux +- is somewhere in kernel code. The solution to the first problem is simply +- to save and restore 0xa0000000 on suspend/resume. There are a couple of +- solutions to the second problem: ++ The problem with using the HTC bootloader is that it does its ++ initialization and then jumps to 0xa0040000, which on Linux ++ is somewhere in kernel code. There are a couple of solutions to this ++ problem: + + 1. Save/restore enough bytes at 0xa0040000 to insert code to jump to the + resume function. This is still a little risky depending on what's + at 0xa0040000. + +- 2. Store a relocatable code fragment into SRAM that jumps to the resume +- function. This is safer since we don't have to worry about stomping +- on the kernel; and we have to copy the bootloader into place anyway. ++ 2. Store a position-independent code fragment into SRAM that jumps to the ++ resume function. This is safer since we don't have to worry about ++ stomping on the kernel; and we have to copy the bootloader into place ++ anyway. + + Both methods have been tested to work. Method #2 seems safer so that is + what we're using. +@@ -63,13 +61,10 @@ + + static u8 *bootloader; + static int bootloader_valid = 0; +-static u32 *addr_a0000000; +-static u32 save_a0000000; + + #define BOOTLOADER_LOAD_DELAY (HZ * 30) + static struct work_struct fw_work; + +-struct pxa_ll_pm_ops *ll_ops_orig; + extern struct pm_ops pxa_pm_ops; + + static int (*pxa_pm_enter_orig)(suspend_state_t state); +@@ -85,8 +80,6 @@ static int h2200_pxa_pm_enter(suspend_st + } + + ret = pxa_pm_enter_orig(state); +- if (ret) +- return ret; + + MSC0 = 0x246c7ffc; + (void)MSC0; +@@ -95,35 +88,9 @@ static int h2200_pxa_pm_enter(suspend_st + MSC2 = 0x7ff07ff0; + (void)MSC2; + +- return 0; +-} +- +-static void h2200_pxa_ll_pm_suspend(unsigned long resume_addr) +-{ +- /* Save the value at 0xa0000000 phys because the HTC bootloader +- will overwrite it. */ +- save_a0000000 = *addr_a0000000; +- +- /* XXX Do we still need to flush the cache though we've mapped +- * the SRAM as uncacheable? */ +- +- return; +-} +- +-static void h2200_pxa_ll_pm_resume(void) +-{ +- /* Restore the value at 0xa0000000 phys. */ +- *addr_a0000000 = save_a0000000; +- +- /* XXX Do we still need to flush the cache though we've mapped +- * the SRAM as uncacheable? */ ++ return ret; + } + +-static struct pxa_ll_pm_ops h2200_ll_pm_ops = { +- .suspend = h2200_pxa_ll_pm_suspend, +- .resume = h2200_pxa_ll_pm_resume, +-}; +- + /* Return a pointer to the bootloader. */ + u8 * + get_hamcop_bootloader(void) +@@ -132,13 +99,23 @@ get_hamcop_bootloader(void) + } + EXPORT_SYMBOL(get_hamcop_bootloader); + ++/* Patch the bootloader so it resumes to the address in PSPR ++ * instead of 0xa0040000. */ ++static void h2200_patch_fw(void) ++{ ++ int i; ++ u32 *code = (u32 *)bootloader; ++ ++ i = 0x75c / sizeof(u32); ++ code[i++] = 0xe59f0000; /* ldr r0, [pc, #0] */ ++ code[i++] = 0xe590f000; /* ldr pc, [r0] */ ++ code[i++] = 0x40f00008; /* PSPR */ ++} + + #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) + static void h2200_load_bootloader(void *data) + { + const struct firmware *fw; +- u32 *code; +- int i; + + if (request_firmware(&fw, "h2200_bootloader.bin", &h2200_hamcop.dev)) { + printk(KERN_ERR "h2200_pm: request_firmware failed\n"); +@@ -154,20 +131,12 @@ static void h2200_load_bootloader(void * + memcpy(bootloader, fw->data, fw->size < HAMCOP_SRAM_Size ? + fw->size : HAMCOP_SRAM_Size); + release_firmware(fw); +- +- /* Patch the bootloader so it resumes to the address in PSPR +- * instead of 0xa0040000. */ +- code = (u32 *)bootloader; +- i = 0x75c / sizeof(u32); +- code[i++] = 0xe59f0000; /* ldr r0, [pc, #0] */ +- code[i++] = 0xe590f000; /* ldr pc, [r0] */ +- code[i++] = 0x40f00008; /* PSPR */ +- ++ h2200_patch_fw(); + bootloader_valid = 1; + } + #endif + +-static int __init h2200_ll_pm_init(void) { ++static int __init h2200_pm_init(void) { + + u8 *sram; + +@@ -175,8 +144,6 @@ static int __init h2200_ll_pm_init(void) + + printk("Initialising wince bootloader suspend workaround\n"); + +- addr_a0000000 = phys_to_virt(0xa0000000); +- ll_ops_orig = pxa_pm_set_ll_ops(&h2200_ll_pm_ops); + pxa_pm_enter_orig = pxa_pm_ops.enter; + pxa_pm_ops.enter = h2200_pxa_pm_enter; + +@@ -198,9 +165,11 @@ static int __init h2200_ll_pm_init(void) + * another. Check for the HTC bootloader by looking for + * 'b 0x80' at +0x0, and for 'ECEC' at +0x40. */ + if (((u32 *)bootloader)[0] == 0xea00001e && +- ((u32 *)bootloader)[0x10] == 0x43454345) ++ ((u32 *)bootloader)[0x10] == 0x43454345) { ++ ++ h2200_patch_fw(); + bootloader_valid = 1; +- else ++ } else + printk(KERN_ERR "h2200_pm: bootloader may be invalid; " + "resume may not work\n"); + +@@ -231,14 +200,13 @@ static int __init h2200_ll_pm_init(void) + return 0; + } + +-static void __exit h2200_ll_pm_exit(void) ++static void __exit h2200_pm_exit(void) + { + pxa_pm_ops.enter = pxa_pm_enter_orig; +- pxa_pm_set_ll_ops(ll_ops_orig); + } + +-module_init(h2200_ll_pm_init); +-module_exit(h2200_ll_pm_exit); ++module_init(h2200_pm_init); ++module_exit(h2200_pm_exit); + + MODULE_AUTHOR("Matt Reimer "); + MODULE_DESCRIPTION("HP iPAQ h2200 power management support for HTC bootloader"); diff --git a/packages/linux/handhelds-pxa-2.6_2.6.15-hh1.bb b/packages/linux/handhelds-pxa-2.6_2.6.15-hh1.bb index 77c99bed89..d30df741b1 100644 --- a/packages/linux/handhelds-pxa-2.6_2.6.15-hh1.bb +++ b/packages/linux/handhelds-pxa-2.6_2.6.15-hh1.bb @@ -9,6 +9,7 @@ COMPATIBLE_HOST = "arm.*-linux" FILESDIR = "${@os.path.dirname(bb.data.getVar('FILE',d,1))}/handhelds-pxa-${PV}" SRC_URI = "${HANDHELDS_CVS};module=linux/kernel26;tag=${@'K' + bb.data.getVar('PV',d,1).replace('.', '-')} \ + file://h2200_pm.c.patch;patch=1 \ file://defconfig" S = "${WORKDIR}/kernel26" -- cgit 1.2.3-korg