~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/platforms/52xx/lite5200_pm.c

Version: ~ [ linux-5.3 ] ~ [ linux-5.2.15 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.73 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.144 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.193 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.193 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.73 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp