diff options
author | Scott Wood <scottwood@freescale.com> | 2007-10-09 13:37:13 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2008-07-16 18:57:30 -0400 |
commit | d49747bdfb2ddebea24d1580da55b79d093d48a9 (patch) | |
tree | cb2ae6ea03bab0ff7901c9997ef50131bba6b511 /arch/powerpc/sysdev/ipic.c | |
parent | 7e72063c9aaeb618815589cd4d57f26186e6fcad (diff) |
powerpc/mpc83xx: Power Management support
Basic PM support for 83xx. Standby is implemented as sleep.
Suspend-to-RAM is implemented as "deep sleep" (with the processor
turned off) on 831x.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev/ipic.c')
-rw-r--r-- | arch/powerpc/sysdev/ipic.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index caba1c0be5a7..88a983ece5c9 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/fsl_devices.h> | ||
25 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
27 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
@@ -889,8 +890,78 @@ unsigned int ipic_get_irq(void) | |||
889 | return irq_linear_revmap(primary_ipic->irqhost, irq); | 890 | return irq_linear_revmap(primary_ipic->irqhost, irq); |
890 | } | 891 | } |
891 | 892 | ||
893 | #ifdef CONFIG_PM | ||
894 | static struct { | ||
895 | u32 sicfr; | ||
896 | u32 siprr[2]; | ||
897 | u32 simsr[2]; | ||
898 | u32 sicnr; | ||
899 | u32 smprr[2]; | ||
900 | u32 semsr; | ||
901 | u32 secnr; | ||
902 | u32 sermr; | ||
903 | u32 sercr; | ||
904 | } ipic_saved_state; | ||
905 | |||
906 | static int ipic_suspend(struct sys_device *sdev, pm_message_t state) | ||
907 | { | ||
908 | struct ipic *ipic = primary_ipic; | ||
909 | |||
910 | ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR); | ||
911 | ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A); | ||
912 | ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D); | ||
913 | ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H); | ||
914 | ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L); | ||
915 | ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR); | ||
916 | ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A); | ||
917 | ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B); | ||
918 | ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR); | ||
919 | ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR); | ||
920 | ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR); | ||
921 | ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR); | ||
922 | |||
923 | if (fsl_deep_sleep()) { | ||
924 | /* In deep sleep, make sure there can be no | ||
925 | * pending interrupts, as this can cause | ||
926 | * problems on 831x. | ||
927 | */ | ||
928 | ipic_write(ipic->regs, IPIC_SIMSR_H, 0); | ||
929 | ipic_write(ipic->regs, IPIC_SIMSR_L, 0); | ||
930 | ipic_write(ipic->regs, IPIC_SEMSR, 0); | ||
931 | ipic_write(ipic->regs, IPIC_SERMR, 0); | ||
932 | } | ||
933 | |||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | static int ipic_resume(struct sys_device *sdev) | ||
938 | { | ||
939 | struct ipic *ipic = primary_ipic; | ||
940 | |||
941 | ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr); | ||
942 | ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]); | ||
943 | ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]); | ||
944 | ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]); | ||
945 | ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]); | ||
946 | ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr); | ||
947 | ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]); | ||
948 | ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]); | ||
949 | ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr); | ||
950 | ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr); | ||
951 | ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr); | ||
952 | ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr); | ||
953 | |||
954 | return 0; | ||
955 | } | ||
956 | #else | ||
957 | #define ipic_suspend NULL | ||
958 | #define ipic_resume NULL | ||
959 | #endif | ||
960 | |||
892 | static struct sysdev_class ipic_sysclass = { | 961 | static struct sysdev_class ipic_sysclass = { |
893 | .name = "ipic", | 962 | .name = "ipic", |
963 | .suspend = ipic_suspend, | ||
964 | .resume = ipic_resume, | ||
894 | }; | 965 | }; |
895 | 966 | ||
896 | static struct sys_device device_ipic = { | 967 | static struct sys_device device_ipic = { |