root/arch/powerpc/platforms/52xx/lite5200_pm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lite5200_pm_valid
  2. lite5200_pm_begin
  3. lite5200_pm_prepare
  4. lite5200_save_regs
  5. lite5200_restore_regs
  6. lite5200_pm_enter
  7. lite5200_pm_finish
  8. lite5200_pm_end
  9. lite5200_pm_init

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

/* [<][>][^][v][top][bottom][index][help] */