0001
0002 #include <linux/init.h>
0003 #include <linux/suspend.h>
0004 #include <linux/io.h>
0005 #include <linux/of_address.h>
0006
0007 #include <asm/time.h>
0008 #include <asm/cacheflush.h>
0009 #include <asm/mpc52xx.h>
0010
0011
0012 extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs,
0013 struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*);
0014 extern void mpc52xx_ds_sram(void);
0015 extern const long mpc52xx_ds_sram_size;
0016 extern void mpc52xx_ds_cached(void);
0017 extern const long mpc52xx_ds_cached_size;
0018
0019 static void __iomem *mbar;
0020 static void __iomem *sdram;
0021 static struct mpc52xx_cdm __iomem *cdm;
0022 static struct mpc52xx_intr __iomem *intr;
0023 static struct mpc52xx_gpio_wkup __iomem *gpiow;
0024 static void __iomem *sram;
0025 static int sram_size;
0026
0027 struct mpc52xx_suspend mpc52xx_suspend;
0028
0029 static int mpc52xx_pm_valid(suspend_state_t state)
0030 {
0031 switch (state) {
0032 case PM_SUSPEND_STANDBY:
0033 return 1;
0034 default:
0035 return 0;
0036 }
0037 }
0038
0039 int mpc52xx_set_wakeup_gpio(u8 pin, u8 level)
0040 {
0041 u16 tmp;
0042
0043
0044 out_8(&gpiow->wkup_gpioe, in_8(&gpiow->wkup_gpioe) | (1 << pin));
0045
0046 out_8(&gpiow->wkup_ddr, in_8(&gpiow->wkup_ddr) & ~(1 << pin));
0047
0048 out_8(&gpiow->wkup_inten, in_8(&gpiow->wkup_inten) | (1 << pin));
0049
0050 tmp = in_be16(&gpiow->wkup_itype);
0051 tmp &= ~(0x3 << (pin * 2));
0052 tmp |= (!level + 1) << (pin * 2);
0053 out_be16(&gpiow->wkup_itype, tmp);
0054
0055 out_8(&gpiow->wkup_maste, 1);
0056
0057 return 0;
0058 }
0059
0060 int mpc52xx_pm_prepare(void)
0061 {
0062 struct device_node *np;
0063 const struct of_device_id immr_ids[] = {
0064 { .compatible = "fsl,mpc5200-immr", },
0065 { .compatible = "fsl,mpc5200b-immr", },
0066 { .type = "soc", .compatible = "mpc5200", },
0067 { .type = "builtin", .compatible = "mpc5200", },
0068 {}
0069 };
0070 struct resource res;
0071
0072
0073 np = of_find_matching_node(NULL, immr_ids);
0074
0075 if (of_address_to_resource(np, 0, &res)) {
0076 pr_err("mpc52xx_pm_prepare(): could not get IMMR address\n");
0077 of_node_put(np);
0078 return -ENOSYS;
0079 }
0080
0081 mbar = ioremap(res.start, 0xc000);
0082
0083 of_node_put(np);
0084 if (!mbar) {
0085 pr_err("mpc52xx_pm_prepare(): could not map registers\n");
0086 return -ENOSYS;
0087 }
0088
0089 sdram = mbar + 0x100;
0090 cdm = mbar + 0x200;
0091 intr = mbar + 0x500;
0092 gpiow = mbar + 0xc00;
0093 sram = mbar + 0x8000;
0094 sram_size = 0x4000;
0095
0096
0097 if (mpc52xx_suspend.board_suspend_prepare)
0098 mpc52xx_suspend.board_suspend_prepare(mbar);
0099 else {
0100 printk(KERN_ALERT "%s: %i don't know how to wake up the board\n",
0101 __func__, __LINE__);
0102 goto out_unmap;
0103 }
0104
0105 return 0;
0106
0107 out_unmap:
0108 iounmap(mbar);
0109 return -ENOSYS;
0110 }
0111
0112
0113 char saved_sram[0x4000];
0114
0115 int mpc52xx_pm_enter(suspend_state_t state)
0116 {
0117 u32 clk_enables;
0118 u32 msr, hid0;
0119 u32 intr_main_mask;
0120 void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500;
0121 unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size;
0122 char saved_0x500[0x600-0x500];
0123
0124 if (WARN_ON(mpc52xx_ds_cached_size > sizeof(saved_0x500)))
0125 return -ENOMEM;
0126
0127
0128 intr_main_mask = in_be32(&intr->main_mask);
0129 out_be32(&intr->main_mask, intr_main_mask | 0x1ffff);
0130
0131
0132 mtspr(SPRN_DEC, 0x7fffffff);
0133
0134
0135 memcpy(saved_sram, sram, sram_size);
0136
0137
0138 memcpy(sram, mpc52xx_ds_sram, mpc52xx_ds_sram_size);
0139
0140 out_8(&cdm->ccs_sleep_enable, 1);
0141 out_8(&cdm->osc_sleep_enable, 1);
0142 out_8(&cdm->ccs_qreq_test, 1);
0143
0144
0145 clk_enables = in_be32(&cdm->clk_enables);
0146 out_be32(&cdm->clk_enables, clk_enables & 0x00088000);
0147
0148
0149 msr = mfmsr();
0150 mtmsr(msr & ~MSR_POW);
0151
0152
0153 hid0 = mfspr(SPRN_HID0);
0154 mtspr(SPRN_HID0, (hid0 & ~(HID0_DOZE | HID0_NAP | HID0_DPM)) | HID0_SLEEP);
0155
0156
0157 memcpy(saved_0x500, irq_0x500, mpc52xx_ds_cached_size);
0158 memcpy(irq_0x500, mpc52xx_ds_cached, mpc52xx_ds_cached_size);
0159 flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
0160
0161
0162 mpc52xx_deep_sleep(sram, sdram, cdm, intr);
0163
0164
0165 memcpy(irq_0x500, saved_0x500, mpc52xx_ds_cached_size);
0166 flush_icache_range((unsigned long)irq_0x500, irq_0x500_stop);
0167
0168
0169 mtmsr(msr & ~MSR_POW);
0170 mtspr(SPRN_HID0, hid0);
0171 mtmsr(msr);
0172
0173 out_be32(&cdm->clk_enables, clk_enables);
0174 out_8(&cdm->ccs_sleep_enable, 0);
0175 out_8(&cdm->osc_sleep_enable, 0);
0176
0177
0178 memcpy(sram, saved_sram, sram_size);
0179
0180
0181 out_be32(&intr->main_mask, intr_main_mask);
0182
0183 return 0;
0184 }
0185
0186 void mpc52xx_pm_finish(void)
0187 {
0188
0189 if (mpc52xx_suspend.board_resume_finish)
0190 mpc52xx_suspend.board_resume_finish(mbar);
0191
0192 iounmap(mbar);
0193 }
0194
0195 static const struct platform_suspend_ops mpc52xx_pm_ops = {
0196 .valid = mpc52xx_pm_valid,
0197 .prepare = mpc52xx_pm_prepare,
0198 .enter = mpc52xx_pm_enter,
0199 .finish = mpc52xx_pm_finish,
0200 };
0201
0202 int __init mpc52xx_pm_init(void)
0203 {
0204 suspend_set_ops(&mpc52xx_pm_ops);
0205 return 0;
0206 }