aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/83xx/suspend.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/83xx/suspend.c')
-rw-r--r--arch/powerpc/platforms/83xx/suspend.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c
index 08e65fc8b98c..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
82struct 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
92struct mpc83xx_saved {
93 u32 sicrl;
94 u32 sicrh;
95 u32 sccr;
96};
97
81struct pmc_type { 98struct 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;
87static int pmc_irq; 104static int pmc_irq;
88static struct mpc83xx_pmc __iomem *pmc_regs; 105static struct mpc83xx_pmc __iomem *pmc_regs;
89static struct mpc83xx_clock __iomem *clock_regs; 106static struct mpc83xx_clock __iomem *clock_regs;
107static struct mpc83xx_syscr __iomem *syscr_regs;
108static struct mpc83xx_saved saved_regs;
90static int is_pci_agent, wake_from_pci; 109static int is_pci_agent, wake_from_pci;
91static phys_addr_t immrbase; 110static phys_addr_t immrbase;
92static int pci_pm_state; 111static int pci_pm_state;
@@ -96,6 +115,7 @@ int fsl_deep_sleep(void)
96{ 115{
97 return deep_sleeping; 116 return deep_sleeping;
98} 117}
118EXPORT_SYMBOL(fsl_deep_sleep);
99 119
100static int mpc83xx_change_state(void) 120static int mpc83xx_change_state(void)
101{ 121{
@@ -136,6 +156,20 @@ static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
136 return ret; 156 return ret;
137} 157}
138 158
159static 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
166static 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
139static int mpc83xx_suspend_enter(suspend_state_t state) 173static int mpc83xx_suspend_enter(suspend_state_t state)
140{ 174{
141 int ret = -EAGAIN; 175 int ret = -EAGAIN;
@@ -165,6 +199,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state)
165 */ 199 */
166 200
167 if (deep_sleeping) { 201 if (deep_sleeping) {
202 mpc83xx_suspend_save_regs();
203
168 out_be32(&pmc_regs->mask, PMCER_ALL); 204 out_be32(&pmc_regs->mask, PMCER_ALL);
169 205
170 out_be32(&pmc_regs->config1, 206 out_be32(&pmc_regs->config1,
@@ -178,6 +214,8 @@ static int mpc83xx_suspend_enter(suspend_state_t state)
178 in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF); 214 in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
179 215
180 out_be32(&pmc_regs->mask, PMCER_PMCI); 216 out_be32(&pmc_regs->mask, PMCER_PMCI);
217
218 mpc83xx_suspend_restore_regs();
181 } else { 219 } else {
182 out_be32(&pmc_regs->mask, PMCER_PMCI); 220 out_be32(&pmc_regs->mask, PMCER_PMCI);
183 221
@@ -193,7 +231,7 @@ out:
193 return ret; 231 return ret;
194} 232}
195 233
196static void mpc83xx_suspend_finish(void) 234static void mpc83xx_suspend_end(void)
197{ 235{
198 deep_sleeping = 0; 236 deep_sleeping = 0;
199} 237}
@@ -277,7 +315,7 @@ static struct platform_suspend_ops mpc83xx_suspend_ops = {
277 .valid = mpc83xx_suspend_valid, 315 .valid = mpc83xx_suspend_valid,
278 .begin = mpc83xx_suspend_begin, 316 .begin = mpc83xx_suspend_begin,
279 .enter = mpc83xx_suspend_enter, 317 .enter = mpc83xx_suspend_enter,
280 .finish = mpc83xx_suspend_finish, 318 .end = mpc83xx_suspend_end,
281}; 319};
282 320
283static int pmc_probe(struct of_device *ofdev, 321static int pmc_probe(struct of_device *ofdev,
@@ -332,12 +370,23 @@ static int pmc_probe(struct of_device *ofdev,
332 goto out_pmc; 370 goto out_pmc;
333 } 371 }
334 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
335 if (is_pci_agent) 382 if (is_pci_agent)
336 mpc83xx_set_agent(); 383 mpc83xx_set_agent();
337 384
338 suspend_set_ops(&mpc83xx_suspend_ops); 385 suspend_set_ops(&mpc83xx_suspend_ops);
339 return 0; 386 return 0;
340 387
388out_syscr:
389 iounmap(clock_regs);
341out_pmc: 390out_pmc:
342 iounmap(pmc_regs); 391 iounmap(pmc_regs);
343out: 392out: