1 #include <linux/init.h> 2 #include <linux/pm.h> 3 #include <asm/io.h> 4 #include <asm/time.h> 5 #include <asm/mpc52xx.h> 6 #include "mpc52xx_pic.h" 7 8 /* defined in lite5200_sleep.S and only used here */ 9 extern void lite5200_low_power(void __iomem *sram, void __iomem *mbar); 10 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; 20 21 static int lite5200_pm_valid(suspend_state_t state) 22 { 23 switch (state) { 24 case PM_SUSPEND_STANDBY: 25 case PM_SUSPEND_MEM: 26 return 1; 27 default: 28 return 0; 29 } 30 } 31 32 static int lite5200_pm_prepare(suspend_state_t state) 33 { 34 /* deep sleep? let mpc52xx code handle that */ 35 if (state == PM_SUSPEND_STANDBY) 36 return mpc52xx_pm_prepare(state); 37 38 if (state != PM_SUSPEND_MEM) 39 return -EINVAL; 40 41 /* map registers */ 42 mbar = mpc52xx_find_and_map("mpc5200"); 43 if (!mbar) { 44 printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__); 45 return -ENOSYS; 46 } 47 48 cdm = mbar + 0x200; 49 pic = mbar + 0x500; 50 gps = mbar + 0xb00; 51 gpw = mbar + 0xc00; 52 bes = mbar + 0x1200; 53 xlb = mbar + 0x1f00; 54 sram = mbar + 0x8000; 55 56 return 0; 57 } 58 59 /* save and restore registers not bound to any real devices */ 60 static struct mpc52xx_cdm scdm; 61 static struct mpc52xx_intr spic; 62 static struct mpc52xx_sdma sbes; 63 static struct mpc52xx_xlb sxlb; 64 static struct mpc52xx_gpio sgps; 65 static struct mpc52xx_gpio_wkup sgpw; 66 67 static void lite5200_save_regs(void) 68 { 69 _memcpy_fromio(&spic, pic, sizeof(*pic)); 70 _memcpy_fromio(&sbes, bes, sizeof(*bes)); 71 _memcpy_fromio(&scdm, cdm, sizeof(*cdm)); 72 _memcpy_fromio(&sxlb, xlb, sizeof(*xlb)); 73 _memcpy_fromio(&sgps, gps, sizeof(*gps)); 74 _memcpy_fromio(&sgpw, gpw, sizeof(*gpw)); 75 76 _memcpy_fromio(saved_sram, sram, sram_size); 77 } 78 79 static void lite5200_restore_regs(void) 80 { 81 int i; 82 _memcpy_toio(sram, saved_sram, sram_size); 83 84 85 /* 86 * GPIOs. Interrupt Master Enable has higher address then other 87 * registers, so just memcpy is ok. 88 */ 89 _memcpy_toio(gpw, &sgpw, sizeof(*gpw)); 90 _memcpy_toio(gps, &sgps, sizeof(*gps)); 91 92 93 /* XLB Arbitrer */ 94 out_be32(&xlb->snoop_window, sxlb.snoop_window); 95 out_be32(&xlb->master_priority, sxlb.master_priority); 96 out_be32(&xlb->master_pri_enable, sxlb.master_pri_enable); 97 98 /* enable */ 99 out_be32(&xlb->int_enable, sxlb.int_enable); 100 out_be32(&xlb->config, sxlb.config); 101 102 103 /* CDM - Clock Distribution Module */ 104 out_8(&cdm->ipb_clk_sel, scdm.ipb_clk_sel); 105 out_8(&cdm->pci_clk_sel, scdm.pci_clk_sel); 106 107 out_8(&cdm->ext_48mhz_en, scdm.ext_48mhz_en); 108 out_8(&cdm->fd_enable, scdm.fd_enable); 109 out_be16(&cdm->fd_counters, scdm.fd_counters); 110 111 out_be32(&cdm->clk_enables, scdm.clk_enables); 112 113 out_8(&cdm->osc_disable, scdm.osc_disable); 114 115 out_be16(&cdm->mclken_div_psc1, scdm.mclken_div_psc1); 116 out_be16(&cdm->mclken_div_psc2, scdm.mclken_div_psc2); 117 out_be16(&cdm->mclken_div_psc3, scdm.mclken_div_psc3); 118 out_be16(&cdm->mclken_div_psc6, scdm.mclken_div_psc6); 119 120 121 /* BESTCOMM */ 122 out_be32(&bes->taskBar, sbes.taskBar); 123 out_be32(&bes->currentPointer, sbes.currentPointer); 124 out_be32(&bes->endPointer, sbes.endPointer); 125 out_be32(&bes->variablePointer, sbes.variablePointer); 126 127 out_8(&bes->IntVect1, sbes.IntVect1); 128 out_8(&bes->IntVect2, sbes.IntVect2); 129 out_be16(&bes->PtdCntrl, sbes.PtdCntrl); 130 131 for (i=0; i<32; i++) 132 out_8(&bes->ipr[i], sbes.ipr[i]); 133 134 out_be32(&bes->cReqSelect, sbes.cReqSelect); 135 out_be32(&bes->task_size0, sbes.task_size0); 136 out_be32(&bes->task_size1, sbes.task_size1); 137 out_be32(&bes->MDEDebug, sbes.MDEDebug); 138 out_be32(&bes->ADSDebug, sbes.ADSDebug); 139 out_be32(&bes->Value1, sbes.Value1); 140 out_be32(&bes->Value2, sbes.Value2); 141 out_be32(&bes->Control, sbes.Control); 142 out_be32(&bes->Status, sbes.Status); 143 out_be32(&bes->PTDDebug, sbes.PTDDebug); 144 145 /* restore tasks */ 146 for (i=0; i<16; i++) 147 out_be16(&bes->tcr[i], sbes.tcr[i]); 148 149 /* enable interrupts */ 150 out_be32(&bes->IntPend, sbes.IntPend); 151 out_be32(&bes->IntMask, sbes.IntMask); 152 153 154 /* PIC */ 155 out_be32(&pic->per_pri1, spic.per_pri1); 156 out_be32(&pic->per_pri2, spic.per_pri2); 157 out_be32(&pic->per_pri3, spic.per_pri3); 158 159 out_be32(&pic->main_pri1, spic.main_pri1); 160 out_be32(&pic->main_pri2, spic.main_pri2); 161 162 out_be32(&pic->enc_status, spic.enc_status); 163 164 /* unmask and enable interrupts */ 165 out_be32(&pic->per_mask, spic.per_mask); 166 out_be32(&pic->main_mask, spic.main_mask); 167 out_be32(&pic->ctrl, spic.ctrl); 168 } 169 170 static int lite5200_pm_enter(suspend_state_t state) 171 { 172 /* deep sleep? let mpc52xx code handle that */ 173 if (state == PM_SUSPEND_STANDBY) { 174 return mpc52xx_pm_enter(state); 175 } 176 177 lite5200_save_regs(); 178 179 /* effectively save FP regs */ 180 enable_kernel_fp(); 181 182 lite5200_low_power(sram, mbar); 183 184 lite5200_restore_regs(); 185 186 /* restart jiffies */ 187 wakeup_decrementer(); 188 189 iounmap(mbar); 190 return 0; 191 } 192 193 static int lite5200_pm_finish(suspend_state_t state) 194 { 195 /* deep sleep? let mpc52xx code handle that */ 196 if (state == PM_SUSPEND_STANDBY) { 197 return mpc52xx_pm_finish(state); 198 } 199 return 0; 200 } 201 202 static struct pm_ops lite5200_pm_ops = { 203 .valid = lite5200_pm_valid, 204 .prepare = lite5200_pm_prepare, 205 .enter = lite5200_pm_enter, 206 .finish = lite5200_pm_finish, 207 }; 208 209 int __init lite5200_pm_init(void) 210 { 211 pm_set_ops(&lite5200_pm_ops); 212 return 0; 213 } 214