Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * MPC83xx suspend support
0004  *
0005  * Author: Scott Wood <scottwood@freescale.com>
0006  *
0007  * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
0008  */
0009 
0010 #include <linux/pm.h>
0011 #include <linux/types.h>
0012 #include <linux/ioport.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/wait.h>
0015 #include <linux/sched/signal.h>
0016 #include <linux/kthread.h>
0017 #include <linux/freezer.h>
0018 #include <linux/suspend.h>
0019 #include <linux/fsl_devices.h>
0020 #include <linux/of_address.h>
0021 #include <linux/of_irq.h>
0022 #include <linux/of_platform.h>
0023 #include <linux/export.h>
0024 
0025 #include <asm/reg.h>
0026 #include <asm/io.h>
0027 #include <asm/time.h>
0028 #include <asm/mpc6xx.h>
0029 #include <asm/switch_to.h>
0030 
0031 #include <sysdev/fsl_soc.h>
0032 
0033 #define PMCCR1_NEXT_STATE       0x0C /* Next state for power management */
0034 #define PMCCR1_NEXT_STATE_SHIFT 2
0035 #define PMCCR1_CURR_STATE       0x03 /* Current state for power management*/
0036 #define IMMR_SYSCR_OFFSET       0x100
0037 #define IMMR_RCW_OFFSET         0x900
0038 #define RCW_PCI_HOST            0x80000000
0039 
0040 void mpc83xx_enter_deep_sleep(phys_addr_t immrbase);
0041 
0042 struct mpc83xx_pmc {
0043     u32 config;
0044 #define PMCCR_DLPEN 2 /* DDR SDRAM low power enable */
0045 #define PMCCR_SLPEN 1 /* System low power enable */
0046 
0047     u32 event;
0048     u32 mask;
0049 /* All but PMCI are deep-sleep only */
0050 #define PMCER_GPIO   0x100
0051 #define PMCER_PCI    0x080
0052 #define PMCER_USB    0x040
0053 #define PMCER_ETSEC1 0x020
0054 #define PMCER_ETSEC2 0x010
0055 #define PMCER_TIMER  0x008
0056 #define PMCER_INT1   0x004
0057 #define PMCER_INT2   0x002
0058 #define PMCER_PMCI   0x001
0059 #define PMCER_ALL    0x1FF
0060 
0061     /* deep-sleep only */
0062     u32 config1;
0063 #define PMCCR1_USE_STATE  0x80000000
0064 #define PMCCR1_PME_EN     0x00000080
0065 #define PMCCR1_ASSERT_PME 0x00000040
0066 #define PMCCR1_POWER_OFF  0x00000020
0067 
0068     /* deep-sleep only */
0069     u32 config2;
0070 };
0071 
0072 struct mpc83xx_rcw {
0073     u32 rcwlr;
0074     u32 rcwhr;
0075 };
0076 
0077 struct mpc83xx_clock {
0078     u32 spmr;
0079     u32 occr;
0080     u32 sccr;
0081 };
0082 
0083 struct mpc83xx_syscr {
0084     __be32 sgprl;
0085     __be32 sgprh;
0086     __be32 spridr;
0087     __be32 :32;
0088     __be32 spcr;
0089     __be32 sicrl;
0090     __be32 sicrh;
0091 };
0092 
0093 struct mpc83xx_saved {
0094     u32 sicrl;
0095     u32 sicrh;
0096     u32 sccr;
0097 };
0098 
0099 struct pmc_type {
0100     int has_deep_sleep;
0101 };
0102 
0103 static int has_deep_sleep, deep_sleeping;
0104 static int pmc_irq;
0105 static struct mpc83xx_pmc __iomem *pmc_regs;
0106 static struct mpc83xx_clock __iomem *clock_regs;
0107 static struct mpc83xx_syscr __iomem *syscr_regs;
0108 static struct mpc83xx_saved saved_regs;
0109 static int is_pci_agent, wake_from_pci;
0110 static phys_addr_t immrbase;
0111 static int pci_pm_state;
0112 static DECLARE_WAIT_QUEUE_HEAD(agent_wq);
0113 
0114 int fsl_deep_sleep(void)
0115 {
0116     return deep_sleeping;
0117 }
0118 EXPORT_SYMBOL(fsl_deep_sleep);
0119 
0120 static int mpc83xx_change_state(void)
0121 {
0122     u32 curr_state;
0123     u32 reg_cfg1 = in_be32(&pmc_regs->config1);
0124 
0125     if (is_pci_agent) {
0126         pci_pm_state = (reg_cfg1 & PMCCR1_NEXT_STATE) >>
0127                        PMCCR1_NEXT_STATE_SHIFT;
0128         curr_state = reg_cfg1 & PMCCR1_CURR_STATE;
0129 
0130         if (curr_state != pci_pm_state) {
0131             reg_cfg1 &= ~PMCCR1_CURR_STATE;
0132             reg_cfg1 |= pci_pm_state;
0133             out_be32(&pmc_regs->config1, reg_cfg1);
0134 
0135             wake_up(&agent_wq);
0136             return 1;
0137         }
0138     }
0139 
0140     return 0;
0141 }
0142 
0143 static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
0144 {
0145     u32 event = in_be32(&pmc_regs->event);
0146     int ret = IRQ_NONE;
0147 
0148     if (mpc83xx_change_state())
0149         ret = IRQ_HANDLED;
0150 
0151     if (event) {
0152         out_be32(&pmc_regs->event, event);
0153         ret = IRQ_HANDLED;
0154     }
0155 
0156     return ret;
0157 }
0158 
0159 static void mpc83xx_suspend_restore_regs(void)
0160 {
0161     out_be32(&syscr_regs->sicrl, saved_regs.sicrl);
0162     out_be32(&syscr_regs->sicrh, saved_regs.sicrh);
0163     out_be32(&clock_regs->sccr, saved_regs.sccr);
0164 }
0165 
0166 static void mpc83xx_suspend_save_regs(void)
0167 {
0168     saved_regs.sicrl = in_be32(&syscr_regs->sicrl);
0169     saved_regs.sicrh = in_be32(&syscr_regs->sicrh);
0170     saved_regs.sccr = in_be32(&clock_regs->sccr);
0171 }
0172 
0173 static int mpc83xx_suspend_enter(suspend_state_t state)
0174 {
0175     int ret = -EAGAIN;
0176 
0177     /* Don't go to sleep if there's a race where pci_pm_state changes
0178      * between the agent thread checking it and the PM code disabling
0179      * interrupts.
0180      */
0181     if (wake_from_pci) {
0182         if (pci_pm_state != (deep_sleeping ? 3 : 2))
0183             goto out;
0184 
0185         out_be32(&pmc_regs->config1,
0186                  in_be32(&pmc_regs->config1) | PMCCR1_PME_EN);
0187     }
0188 
0189     /* Put the system into low-power mode and the RAM
0190      * into self-refresh mode once the core goes to
0191      * sleep.
0192      */
0193 
0194     out_be32(&pmc_regs->config, PMCCR_SLPEN | PMCCR_DLPEN);
0195 
0196     /* If it has deep sleep (i.e. it's an 831x or compatible),
0197      * disable power to the core upon entering sleep mode.  This will
0198      * require going through the boot firmware upon a wakeup event.
0199      */
0200 
0201     if (deep_sleeping) {
0202         mpc83xx_suspend_save_regs();
0203 
0204         out_be32(&pmc_regs->mask, PMCER_ALL);
0205 
0206         out_be32(&pmc_regs->config1,
0207                  in_be32(&pmc_regs->config1) | PMCCR1_POWER_OFF);
0208 
0209         enable_kernel_fp();
0210 
0211         mpc83xx_enter_deep_sleep(immrbase);
0212 
0213         out_be32(&pmc_regs->config1,
0214                  in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
0215 
0216         out_be32(&pmc_regs->mask, PMCER_PMCI);
0217 
0218         mpc83xx_suspend_restore_regs();
0219     } else {
0220         out_be32(&pmc_regs->mask, PMCER_PMCI);
0221 
0222         mpc6xx_enter_standby();
0223     }
0224 
0225     ret = 0;
0226 
0227 out:
0228     out_be32(&pmc_regs->config1,
0229              in_be32(&pmc_regs->config1) & ~PMCCR1_PME_EN);
0230 
0231     return ret;
0232 }
0233 
0234 static void mpc83xx_suspend_end(void)
0235 {
0236     deep_sleeping = 0;
0237 }
0238 
0239 static int mpc83xx_suspend_valid(suspend_state_t state)
0240 {
0241     return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
0242 }
0243 
0244 static int mpc83xx_suspend_begin(suspend_state_t state)
0245 {
0246     switch (state) {
0247         case PM_SUSPEND_STANDBY:
0248             deep_sleeping = 0;
0249             return 0;
0250 
0251         case PM_SUSPEND_MEM:
0252             if (has_deep_sleep)
0253                 deep_sleeping = 1;
0254 
0255             return 0;
0256 
0257         default:
0258             return -EINVAL;
0259     }
0260 }
0261 
0262 static int agent_thread_fn(void *data)
0263 {
0264     while (1) {
0265         wait_event_interruptible(agent_wq, pci_pm_state >= 2);
0266         try_to_freeze();
0267 
0268         if (signal_pending(current) || pci_pm_state < 2)
0269             continue;
0270 
0271         /* With a preemptible kernel (or SMP), this could race with
0272          * a userspace-driven suspend request.  It's probably best
0273          * to avoid mixing the two with such a configuration (or
0274          * else fix it by adding a mutex to state_store that we can
0275          * synchronize with).
0276          */
0277 
0278         wake_from_pci = 1;
0279 
0280         pm_suspend(pci_pm_state == 3 ? PM_SUSPEND_MEM :
0281                                        PM_SUSPEND_STANDBY);
0282 
0283         wake_from_pci = 0;
0284     }
0285 
0286     return 0;
0287 }
0288 
0289 static void mpc83xx_set_agent(void)
0290 {
0291     out_be32(&pmc_regs->config1, PMCCR1_USE_STATE);
0292     out_be32(&pmc_regs->mask, PMCER_PMCI);
0293 
0294     kthread_run(agent_thread_fn, NULL, "PCI power mgt");
0295 }
0296 
0297 static int mpc83xx_is_pci_agent(void)
0298 {
0299     struct mpc83xx_rcw __iomem *rcw_regs;
0300     int ret;
0301 
0302     rcw_regs = ioremap(get_immrbase() + IMMR_RCW_OFFSET,
0303                        sizeof(struct mpc83xx_rcw));
0304 
0305     if (!rcw_regs)
0306         return -ENOMEM;
0307 
0308     ret = !(in_be32(&rcw_regs->rcwhr) & RCW_PCI_HOST);
0309 
0310     iounmap(rcw_regs);
0311     return ret;
0312 }
0313 
0314 static const struct platform_suspend_ops mpc83xx_suspend_ops = {
0315     .valid = mpc83xx_suspend_valid,
0316     .begin = mpc83xx_suspend_begin,
0317     .enter = mpc83xx_suspend_enter,
0318     .end = mpc83xx_suspend_end,
0319 };
0320 
0321 static struct pmc_type pmc_types[] = {
0322     {
0323         .has_deep_sleep = 1,
0324     },
0325     {
0326         .has_deep_sleep = 0,
0327     }
0328 };
0329 
0330 static const struct of_device_id pmc_match[] = {
0331     {
0332         .compatible = "fsl,mpc8313-pmc",
0333         .data = &pmc_types[0],
0334     },
0335     {
0336         .compatible = "fsl,mpc8349-pmc",
0337         .data = &pmc_types[1],
0338     },
0339     {}
0340 };
0341 
0342 static int pmc_probe(struct platform_device *ofdev)
0343 {
0344     struct device_node *np = ofdev->dev.of_node;
0345     struct resource res;
0346     const struct pmc_type *type;
0347     int ret = 0;
0348 
0349     type = of_device_get_match_data(&ofdev->dev);
0350     if (!type)
0351         return -EINVAL;
0352 
0353     if (!of_device_is_available(np))
0354         return -ENODEV;
0355 
0356     has_deep_sleep = type->has_deep_sleep;
0357     immrbase = get_immrbase();
0358 
0359     is_pci_agent = mpc83xx_is_pci_agent();
0360     if (is_pci_agent < 0)
0361         return is_pci_agent;
0362 
0363     ret = of_address_to_resource(np, 0, &res);
0364     if (ret)
0365         return -ENODEV;
0366 
0367     pmc_irq = irq_of_parse_and_map(np, 0);
0368     if (pmc_irq) {
0369         ret = request_irq(pmc_irq, pmc_irq_handler, IRQF_SHARED,
0370                           "pmc", ofdev);
0371 
0372         if (ret)
0373             return -EBUSY;
0374     }
0375 
0376     pmc_regs = ioremap(res.start, sizeof(*pmc_regs));
0377 
0378     if (!pmc_regs) {
0379         ret = -ENOMEM;
0380         goto out;
0381     }
0382 
0383     ret = of_address_to_resource(np, 1, &res);
0384     if (ret) {
0385         ret = -ENODEV;
0386         goto out_pmc;
0387     }
0388 
0389     clock_regs = ioremap(res.start, sizeof(*clock_regs));
0390 
0391     if (!clock_regs) {
0392         ret = -ENOMEM;
0393         goto out_pmc;
0394     }
0395 
0396     if (has_deep_sleep) {
0397         syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET,
0398                      sizeof(*syscr_regs));
0399         if (!syscr_regs) {
0400             ret = -ENOMEM;
0401             goto out_syscr;
0402         }
0403     }
0404 
0405     if (is_pci_agent)
0406         mpc83xx_set_agent();
0407 
0408     suspend_set_ops(&mpc83xx_suspend_ops);
0409     return 0;
0410 
0411 out_syscr:
0412     iounmap(clock_regs);
0413 out_pmc:
0414     iounmap(pmc_regs);
0415 out:
0416     if (pmc_irq)
0417         free_irq(pmc_irq, ofdev);
0418 
0419     return ret;
0420 }
0421 
0422 static struct platform_driver pmc_driver = {
0423     .driver = {
0424         .name = "mpc83xx-pmc",
0425         .of_match_table = pmc_match,
0426         .suppress_bind_attrs = true,
0427     },
0428     .probe = pmc_probe,
0429 };
0430 
0431 builtin_platform_driver(pmc_driver);