1 #include <linux/init.h>
2 #include <linux/suspend.h>
5 #include <asm/mpc52xx.h>
6 #include "mpc52xx_pic.h"
8 /* defined in lite5200_sleep.S and only used here */
9 extern void lite5200_low_power(void __iomem
*sram
, void __iomem
*mbar
);
11 static struct mpc52xx_cdm __iomem
*cdm
;
12 static struct mpc52xx_intr __iomem
*pic
;
13 static struct mpc52xx_sdma __iomem
*bes
;
14 static struct mpc52xx_xlb __iomem
*xlb
;
15 static struct mpc52xx_gpio __iomem
*gps
;
16 static struct mpc52xx_gpio_wkup __iomem
*gpw
;
17 static void __iomem
*sram
;
18 static const int sram_size
= 0x4000; /* 16 kBytes */
19 static void __iomem
*mbar
;
21 static suspend_state_t lite5200_pm_target_state
;
23 static int lite5200_pm_valid(suspend_state_t state
)
26 case PM_SUSPEND_STANDBY
:
34 static int lite5200_pm_begin(suspend_state_t state
)
36 if (lite5200_pm_valid(state
)) {
37 lite5200_pm_target_state
= state
;
43 static int lite5200_pm_prepare(void)
45 struct device_node
*np
;
46 const struct of_device_id immr_ids
[] = {
47 { .compatible
= "fsl,mpc5200-immr", },
48 { .compatible
= "fsl,mpc5200b-immr", },
49 { .type
= "soc", .compatible
= "mpc5200", }, /* lite5200 */
50 { .type
= "builtin", .compatible
= "mpc5200", }, /* efika */
54 /* deep sleep? let mpc52xx code handle that */
55 if (lite5200_pm_target_state
== PM_SUSPEND_STANDBY
)
56 return mpc52xx_pm_prepare();
58 if (lite5200_pm_target_state
!= PM_SUSPEND_MEM
)
62 np
= of_find_matching_node(NULL
, immr_ids
);
63 mbar
= of_iomap(np
, 0);
66 printk(KERN_ERR
"%s:%i Error mapping registers\n", __func__
, __LINE__
);
81 /* save and restore registers not bound to any real devices */
82 static struct mpc52xx_cdm scdm
;
83 static struct mpc52xx_intr spic
;
84 static struct mpc52xx_sdma sbes
;
85 static struct mpc52xx_xlb sxlb
;
86 static struct mpc52xx_gpio sgps
;
87 static struct mpc52xx_gpio_wkup sgpw
;
89 static void lite5200_save_regs(void)
91 _memcpy_fromio(&spic
, pic
, sizeof(*pic
));
92 _memcpy_fromio(&sbes
, bes
, sizeof(*bes
));
93 _memcpy_fromio(&scdm
, cdm
, sizeof(*cdm
));
94 _memcpy_fromio(&sxlb
, xlb
, sizeof(*xlb
));
95 _memcpy_fromio(&sgps
, gps
, sizeof(*gps
));
96 _memcpy_fromio(&sgpw
, gpw
, sizeof(*gpw
));
98 _memcpy_fromio(saved_sram
, sram
, sram_size
);
101 static void lite5200_restore_regs(void)
104 _memcpy_toio(sram
, saved_sram
, sram_size
);
108 * GPIOs. Interrupt Master Enable has higher address then other
109 * registers, so just memcpy is ok.
111 _memcpy_toio(gpw
, &sgpw
, sizeof(*gpw
));
112 _memcpy_toio(gps
, &sgps
, sizeof(*gps
));
116 out_be32(&xlb
->snoop_window
, sxlb
.snoop_window
);
117 out_be32(&xlb
->master_priority
, sxlb
.master_priority
);
118 out_be32(&xlb
->master_pri_enable
, sxlb
.master_pri_enable
);
121 out_be32(&xlb
->int_enable
, sxlb
.int_enable
);
122 out_be32(&xlb
->config
, sxlb
.config
);
125 /* CDM - Clock Distribution Module */
126 out_8(&cdm
->ipb_clk_sel
, scdm
.ipb_clk_sel
);
127 out_8(&cdm
->pci_clk_sel
, scdm
.pci_clk_sel
);
129 out_8(&cdm
->ext_48mhz_en
, scdm
.ext_48mhz_en
);
130 out_8(&cdm
->fd_enable
, scdm
.fd_enable
);
131 out_be16(&cdm
->fd_counters
, scdm
.fd_counters
);
133 out_be32(&cdm
->clk_enables
, scdm
.clk_enables
);
135 out_8(&cdm
->osc_disable
, scdm
.osc_disable
);
137 out_be16(&cdm
->mclken_div_psc1
, scdm
.mclken_div_psc1
);
138 out_be16(&cdm
->mclken_div_psc2
, scdm
.mclken_div_psc2
);
139 out_be16(&cdm
->mclken_div_psc3
, scdm
.mclken_div_psc3
);
140 out_be16(&cdm
->mclken_div_psc6
, scdm
.mclken_div_psc6
);
144 out_be32(&bes
->taskBar
, sbes
.taskBar
);
145 out_be32(&bes
->currentPointer
, sbes
.currentPointer
);
146 out_be32(&bes
->endPointer
, sbes
.endPointer
);
147 out_be32(&bes
->variablePointer
, sbes
.variablePointer
);
149 out_8(&bes
->IntVect1
, sbes
.IntVect1
);
150 out_8(&bes
->IntVect2
, sbes
.IntVect2
);
151 out_be16(&bes
->PtdCntrl
, sbes
.PtdCntrl
);
154 out_8(&bes
->ipr
[i
], sbes
.ipr
[i
]);
156 out_be32(&bes
->cReqSelect
, sbes
.cReqSelect
);
157 out_be32(&bes
->task_size0
, sbes
.task_size0
);
158 out_be32(&bes
->task_size1
, sbes
.task_size1
);
159 out_be32(&bes
->MDEDebug
, sbes
.MDEDebug
);
160 out_be32(&bes
->ADSDebug
, sbes
.ADSDebug
);
161 out_be32(&bes
->Value1
, sbes
.Value1
);
162 out_be32(&bes
->Value2
, sbes
.Value2
);
163 out_be32(&bes
->Control
, sbes
.Control
);
164 out_be32(&bes
->Status
, sbes
.Status
);
165 out_be32(&bes
->PTDDebug
, sbes
.PTDDebug
);
169 out_be16(&bes
->tcr
[i
], sbes
.tcr
[i
]);
171 /* enable interrupts */
172 out_be32(&bes
->IntPend
, sbes
.IntPend
);
173 out_be32(&bes
->IntMask
, sbes
.IntMask
);
177 out_be32(&pic
->per_pri1
, spic
.per_pri1
);
178 out_be32(&pic
->per_pri2
, spic
.per_pri2
);
179 out_be32(&pic
->per_pri3
, spic
.per_pri3
);
181 out_be32(&pic
->main_pri1
, spic
.main_pri1
);
182 out_be32(&pic
->main_pri2
, spic
.main_pri2
);
184 out_be32(&pic
->enc_status
, spic
.enc_status
);
186 /* unmask and enable interrupts */
187 out_be32(&pic
->per_mask
, spic
.per_mask
);
188 out_be32(&pic
->main_mask
, spic
.main_mask
);
189 out_be32(&pic
->ctrl
, spic
.ctrl
);
192 static int lite5200_pm_enter(suspend_state_t state
)
194 /* deep sleep? let mpc52xx code handle that */
195 if (state
== PM_SUSPEND_STANDBY
) {
196 return mpc52xx_pm_enter(state
);
199 lite5200_save_regs();
201 /* effectively save FP regs */
204 lite5200_low_power(sram
, mbar
);
206 lite5200_restore_regs();
208 /* restart jiffies */
209 wakeup_decrementer();
215 static void lite5200_pm_finish(void)
217 /* deep sleep? let mpc52xx code handle that */
218 if (lite5200_pm_target_state
== PM_SUSPEND_STANDBY
)
222 static void lite5200_pm_end(void)
224 lite5200_pm_target_state
= PM_SUSPEND_ON
;
227 static struct platform_suspend_ops lite5200_pm_ops
= {
228 .valid
= lite5200_pm_valid
,
229 .begin
= lite5200_pm_begin
,
230 .prepare
= lite5200_pm_prepare
,
231 .enter
= lite5200_pm_enter
,
232 .finish
= lite5200_pm_finish
,
233 .end
= lite5200_pm_end
,
236 int __init
lite5200_pm_init(void)
238 suspend_set_ops(&lite5200_pm_ops
);