diff options
| -rw-r--r-- | arch/powerpc/platforms/83xx/suspend.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c index b0c261936f3d..43805348b81e 100644 --- a/arch/powerpc/platforms/83xx/suspend.c +++ b/arch/powerpc/platforms/83xx/suspend.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ | 32 | #define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */ |
| 33 | #define PMCCR1_NEXT_STATE_SHIFT 2 | 33 | #define PMCCR1_NEXT_STATE_SHIFT 2 |
| 34 | #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ | 34 | #define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/ |
| 35 | #define IMMR_SYSCR_OFFSET 0x100 | ||
| 35 | #define IMMR_RCW_OFFSET 0x900 | 36 | #define IMMR_RCW_OFFSET 0x900 |
| 36 | #define RCW_PCI_HOST 0x80000000 | 37 | #define RCW_PCI_HOST 0x80000000 |
| 37 | 38 | ||
| @@ -78,6 +79,22 @@ struct mpc83xx_clock { | |||
| 78 | u32 sccr; | 79 | u32 sccr; |
| 79 | }; | 80 | }; |
| 80 | 81 | ||
| 82 | struct mpc83xx_syscr { | ||
| 83 | __be32 sgprl; | ||
| 84 | __be32 sgprh; | ||
| 85 | __be32 spridr; | ||
| 86 | __be32 :32; | ||
| 87 | __be32 spcr; | ||
| 88 | __be32 sicrl; | ||
| 89 | __be32 sicrh; | ||
| 90 | }; | ||
| 91 | |||
| 92 | struct mpc83xx_saved { | ||
| 93 | u32 sicrl; | ||
| 94 | u32 sicrh; | ||
| 95 | u32 sccr; | ||
| 96 | }; | ||
| 97 | |||
| 81 | struct pmc_type { | 98 | struct pmc_type { |
| 82 | int has_deep_sleep; | 99 | int has_deep_sleep; |
| 83 | }; | 100 | }; |
| @@ -87,6 +104,8 @@ static int has_deep_sleep, deep_sleeping; | |||
| 87 | static int pmc_irq; | 104 | static int pmc_irq; |
| 88 | static struct mpc83xx_pmc __iomem *pmc_regs; | 105 | static struct mpc83xx_pmc __iomem *pmc_regs; |
| 89 | static struct mpc83xx_clock __iomem *clock_regs; | 106 | static struct mpc83xx_clock __iomem *clock_regs; |
| 107 | static struct mpc83xx_syscr __iomem *syscr_regs; | ||
| 108 | static struct mpc83xx_saved saved_regs; | ||
| 90 | static int is_pci_agent, wake_from_pci; | 109 | static int is_pci_agent, wake_from_pci; |
| 91 | static phys_addr_t immrbase; | 110 | static phys_addr_t immrbase; |
| 92 | static int pci_pm_state; | 111 | static int pci_pm_state; |
| @@ -137,6 +156,20 @@ static irqreturn_t pmc_irq_handler(int irq, void *dev_id) | |||
| 137 | return ret; | 156 | return ret; |
| 138 | } | 157 | } |
| 139 | 158 | ||
| 159 | static void mpc83xx_suspend_restore_regs(void) | ||
| 160 | { | ||
| 161 | out_be32(&syscr_regs->sicrl, saved_regs.sicrl); | ||
| 162 | out_be32(&syscr_regs->sicrh, saved_regs.sicrh); | ||
| 163 | out_be32(&clock_regs->sccr, saved_regs.sccr); | ||
| 164 | } | ||
| 165 | |||
| 166 | static void mpc83xx_suspend_save_regs(void) | ||
| 167 | { | ||
| 168 | saved_regs.sicrl = in_be32(&syscr_regs->sicrl); | ||
| 169 | saved_regs.sicrh = in_be32(&syscr_regs->sicrh); | ||
| 170 | saved_regs.sccr = in_be32(&clock_regs->sccr); | ||
| 171 | } | ||
| 172 | |||
| 140 | static int mpc83xx_suspend_enter(suspend_state_t state) | 173 | static int mpc83xx_suspend_enter(suspend_state_t state) |
| 141 | { | 174 | { |
| 142 | int ret = -EAGAIN; | 175 | int ret = -EAGAIN; |
| @@ -166,6 +199,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) | |||
| 166 | */ | 199 | */ |
| 167 | 200 | ||
| 168 | if (deep_sleeping) { | 201 | if (deep_sleeping) { |
| 202 | mpc83xx_suspend_save_regs(); | ||
| 203 | |||
| 169 | out_be32(&pmc_regs->mask, PMCER_ALL); | 204 | out_be32(&pmc_regs->mask, PMCER_ALL); |
| 170 | 205 | ||
| 171 | out_be32(&pmc_regs->config1, | 206 | out_be32(&pmc_regs->config1, |
| @@ -179,6 +214,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state) | |||
| 179 | in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); | 214 | in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); |
| 180 | 215 | ||
| 181 | out_be32(&pmc_regs->mask, PMCER_PMCI); | 216 | out_be32(&pmc_regs->mask, PMCER_PMCI); |
| 217 | |||
| 218 | mpc83xx_suspend_restore_regs(); | ||
| 182 | } else { | 219 | } else { |
| 183 | out_be32(&pmc_regs->mask, PMCER_PMCI); | 220 | out_be32(&pmc_regs->mask, PMCER_PMCI); |
| 184 | 221 | ||
| @@ -333,12 +370,23 @@ static int pmc_probe(struct of_device *ofdev, | |||
| 333 | goto out_pmc; | 370 | goto out_pmc; |
| 334 | } | 371 | } |
| 335 | 372 | ||
| 373 | if (has_deep_sleep) { | ||
| 374 | syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET, | ||
| 375 | sizeof(*syscr_regs)); | ||
| 376 | if (!syscr_regs) { | ||
| 377 | ret = -ENOMEM; | ||
| 378 | goto out_syscr; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 336 | if (is_pci_agent) | 382 | if (is_pci_agent) |
| 337 | mpc83xx_set_agent(); | 383 | mpc83xx_set_agent(); |
| 338 | 384 | ||
| 339 | suspend_set_ops(&mpc83xx_suspend_ops); | 385 | suspend_set_ops(&mpc83xx_suspend_ops); |
| 340 | return 0; | 386 | return 0; |
| 341 | 387 | ||
| 388 | out_syscr: | ||
| 389 | iounmap(clock_regs); | ||
| 342 | out_pmc: | 390 | out_pmc: |
| 343 | iounmap(pmc_regs); | 391 | iounmap(pmc_regs); |
| 344 | out: | 392 | out: |
