hh.org updates
[hh.org.git] / arch / arm / mach-pxa / h3900 / h3900_pm.c
blob056ec68dc89742877edb00b98e3f3f478250216b
1 /*
2 * h3900 supsend/resume support for the original bootloader
4 * Use consistent with the GNU GPL is permitted, provided that this
5 * copyright notice is preserved in its entirety in all copies and
6 * derived works.
8 * Copyright (c) 2006 Paul Sokolovsky
10 * Based on code from hx4700_core.c
14 #include <linux/kernel.h>
15 #include <linux/module.h>
17 #include <asm/hardware.h>
18 #include <asm/arch/pxa-regs.h>
19 #include <asm/arch/pxa-pm_ll.h>
22 static u32 save[4];
23 static u32 save2[0xa * 4];
25 static void
26 h3900_pxa_ll_pm_suspend(unsigned long resume_addr)
28 int i;
29 u32 csum, tmp, *p;
31 for (p = phys_to_virt(0xa007a000), i = 0; i < ARRAY_SIZE(save2); i++)
32 save2[i] = p[i];
34 for (p = phys_to_virt(0xa0000000), i = 0; i < ARRAY_SIZE(save); i++)
35 save[i] = p[i];
37 /* Set the first four words at 0xa0000000 to:
38 * resume address; MMU control; TLB base addr; domain id */
39 p[0] = resume_addr;
41 asm( "mrc\tp15, 0, %0, c1, c0, 0" : "=r" (tmp) );
42 p[1] = tmp & ~(0x3987); /* mmu off */
44 asm( "mrc\tp15, 0, %0, c2, c0, 0" : "=r" (tmp) );
45 p[2] = tmp; /* Shouldn't matter, since MMU will be off. */
47 asm( "mrc\tp15, 0, %0, c3, c0, 0" : "=r" (tmp) );
48 p[3] = tmp; /* Shouldn't matter, since MMU will be off. */
50 /* Set PSPR to the checksum the HTC bootloader wants to see. */
51 for (csum = 0, i = 0; i < 0x30; i++) {
52 tmp = p[i] & 0x1;
53 tmp = tmp << 31;
54 tmp |= tmp >> 1;
55 csum += tmp;
58 PSPR = csum;
61 static void
62 h3900_pxa_ll_pm_resume(void)
64 int i;
65 u32 *p;
67 for (p = phys_to_virt(0xa0000000), i = 0; i < ARRAY_SIZE(save); i++)
68 p[i] = save[i];
70 for (p = phys_to_virt(0xa007a000), i = 0; i < ARRAY_SIZE(save2); i++)
71 p[i] = save2[i];
73 /* XXX Do we need to flush the cache? */
76 struct pxa_ll_pm_ops h3900_ll_pm_ops = {
77 .suspend = h3900_pxa_ll_pm_suspend,
78 .resume = h3900_pxa_ll_pm_resume,
81 void h3900_ll_pm_init(void) {
82 pxa_pm_set_ll_ops(&h3900_ll_pm_ops);