root/arch/arm/mach-mmp/pm-mmp2.c

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

DEFINITIONS

This source file includes following definitions.
  1. mmp2_set_wake
  2. pm_scu_clk_disable
  3. pm_scu_clk_enable
  4. pm_mpmu_clk_disable
  5. pm_mpmu_clk_enable
  6. mmp2_pm_enter_lowpower_mode
  7. mmp2_pm_enter
  8. mmp2_pm_prepare
  9. mmp2_pm_finish
  10. mmp2_pm_valid
  11. mmp2_pm_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * MMP2 Power Management Routines
   4  *
   5  * (C) Copyright 2012 Marvell International Ltd.
   6  * All Rights Reserved
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/errno.h>
  11 #include <linux/err.h>
  12 #include <linux/time.h>
  13 #include <linux/delay.h>
  14 #include <linux/suspend.h>
  15 #include <linux/irq.h>
  16 #include <linux/io.h>
  17 #include <linux/interrupt.h>
  18 #include <asm/mach-types.h>
  19 
  20 #include "cputype.h"
  21 #include "addr-map.h"
  22 #include "pm-mmp2.h"
  23 #include "regs-icu.h"
  24 #include "irqs.h"
  25 
  26 int mmp2_set_wake(struct irq_data *d, unsigned int on)
  27 {
  28         unsigned long data = 0;
  29         int irq = d->irq;
  30 
  31         /* enable wakeup sources */
  32         switch (irq) {
  33         case IRQ_MMP2_RTC:
  34         case IRQ_MMP2_RTC_ALARM:
  35                 data = MPMU_WUCRM_PJ_WAKEUP(4) | MPMU_WUCRM_PJ_RTC_ALARM;
  36                 break;
  37         case IRQ_MMP2_PMIC:
  38                 data = MPMU_WUCRM_PJ_WAKEUP(7);
  39                 break;
  40         case IRQ_MMP2_MMC2:
  41                 /* mmc use WAKEUP2, same as GPIO wakeup source */
  42                 data = MPMU_WUCRM_PJ_WAKEUP(2);
  43                 break;
  44         }
  45         if (on) {
  46                 if (data) {
  47                         data |= __raw_readl(MPMU_WUCRM_PJ);
  48                         __raw_writel(data, MPMU_WUCRM_PJ);
  49                 }
  50         } else {
  51                 if (data) {
  52                         data = ~data & __raw_readl(MPMU_WUCRM_PJ);
  53                         __raw_writel(data, MPMU_WUCRM_PJ);
  54                 }
  55         }
  56         return 0;
  57 }
  58 
  59 static void pm_scu_clk_disable(void)
  60 {
  61         unsigned int val;
  62 
  63         /* close AXI fabric clock gate */
  64         __raw_writel(0x0, CIU_REG(0x64));
  65         __raw_writel(0x0, CIU_REG(0x68));
  66 
  67         /* close MCB master clock gate */
  68         val = __raw_readl(CIU_REG(0x1c));
  69         val |= 0xf0;
  70         __raw_writel(val, CIU_REG(0x1c));
  71 
  72         return ;
  73 }
  74 
  75 static void pm_scu_clk_enable(void)
  76 {
  77         unsigned int val;
  78 
  79         /* open AXI fabric clock gate */
  80         __raw_writel(0x03003003, CIU_REG(0x64));
  81         __raw_writel(0x00303030, CIU_REG(0x68));
  82 
  83         /* open MCB master clock gate */
  84         val = __raw_readl(CIU_REG(0x1c));
  85         val &= ~(0xf0);
  86         __raw_writel(val, CIU_REG(0x1c));
  87 
  88         return ;
  89 }
  90 
  91 static void pm_mpmu_clk_disable(void)
  92 {
  93         /*
  94          * disable clocks in MPMU_CGR_PJ register
  95          * except clock for APMU_PLL1, APMU_PLL1_2 and AP_26M
  96          */
  97         __raw_writel(0x0000a010, MPMU_CGR_PJ);
  98 }
  99 
 100 static void pm_mpmu_clk_enable(void)
 101 {
 102         unsigned int val;
 103 
 104         __raw_writel(0xdffefffe, MPMU_CGR_PJ);
 105         val = __raw_readl(MPMU_PLL2_CTRL1);
 106         val |= (1 << 29);
 107         __raw_writel(val, MPMU_PLL2_CTRL1);
 108 
 109         return ;
 110 }
 111 
 112 void mmp2_pm_enter_lowpower_mode(int state)
 113 {
 114         uint32_t idle_cfg, apcr;
 115 
 116         idle_cfg = __raw_readl(APMU_PJ_IDLE_CFG);
 117         apcr = __raw_readl(MPMU_PCR_PJ);
 118         apcr &= ~(MPMU_PCR_PJ_SLPEN | MPMU_PCR_PJ_DDRCORSD | MPMU_PCR_PJ_APBSD
 119                  | MPMU_PCR_PJ_AXISD | MPMU_PCR_PJ_VCTCXOSD | (1 << 13));
 120         idle_cfg &= ~APMU_PJ_IDLE_CFG_PJ_IDLE;
 121 
 122         switch (state) {
 123         case POWER_MODE_SYS_SLEEP:
 124                 apcr |= MPMU_PCR_PJ_SLPEN;              /* set the SLPEN bit */
 125                 apcr |= MPMU_PCR_PJ_VCTCXOSD;           /* set VCTCXOSD */
 126                 /* fall through */
 127         case POWER_MODE_CHIP_SLEEP:
 128                 apcr |= MPMU_PCR_PJ_SLPEN;
 129                 /* fall through */
 130         case POWER_MODE_APPS_SLEEP:
 131                 apcr |= MPMU_PCR_PJ_APBSD;              /* set APBSD */
 132                 /* fall through */
 133         case POWER_MODE_APPS_IDLE:
 134                 apcr |= MPMU_PCR_PJ_AXISD;              /* set AXISDD bit */
 135                 apcr |= MPMU_PCR_PJ_DDRCORSD;           /* set DDRCORSD bit */
 136                 idle_cfg |= APMU_PJ_IDLE_CFG_PJ_PWRDWN; /* PJ power down */
 137                 apcr |= MPMU_PCR_PJ_SPSD;
 138                 /* fall through */
 139         case POWER_MODE_CORE_EXTIDLE:
 140                 idle_cfg |= APMU_PJ_IDLE_CFG_PJ_IDLE;   /* set the IDLE bit */
 141                 idle_cfg &= ~APMU_PJ_IDLE_CFG_ISO_MODE_CNTRL_MASK;
 142                 idle_cfg |= APMU_PJ_IDLE_CFG_PWR_SW(3)
 143                         | APMU_PJ_IDLE_CFG_L2_PWR_SW;
 144                 break;
 145         case POWER_MODE_CORE_INTIDLE:
 146                 apcr &= ~MPMU_PCR_PJ_SPSD;
 147                 break;
 148         }
 149 
 150         /* set reserve bits */
 151         apcr |= (1 << 30) | (1 << 25);
 152 
 153         /* finally write the registers back */
 154         __raw_writel(idle_cfg, APMU_PJ_IDLE_CFG);
 155         __raw_writel(apcr, MPMU_PCR_PJ);        /* 0xfe086000 */
 156 }
 157 
 158 static int mmp2_pm_enter(suspend_state_t state)
 159 {
 160         int temp;
 161 
 162         temp = __raw_readl(MMP2_ICU_INT4_MASK);
 163         if (temp & (1 << 1)) {
 164                 printk(KERN_ERR "%s: PMIC interrupt is handling\n", __func__);
 165                 return -EAGAIN;
 166         }
 167 
 168         temp = __raw_readl(APMU_SRAM_PWR_DWN);
 169         temp |= ((1 << 19) | (1 << 18));
 170         __raw_writel(temp, APMU_SRAM_PWR_DWN);
 171         pm_mpmu_clk_disable();
 172         pm_scu_clk_disable();
 173 
 174         printk(KERN_INFO "%s: before suspend\n", __func__);
 175         cpu_do_idle();
 176         printk(KERN_INFO "%s: after suspend\n", __func__);
 177 
 178         pm_mpmu_clk_enable();           /* enable clocks in MPMU */
 179         pm_scu_clk_enable();            /* enable clocks in SCU */
 180 
 181         return 0;
 182 }
 183 
 184 /*
 185  * Called after processes are frozen, but before we shut down devices.
 186  */
 187 static int mmp2_pm_prepare(void)
 188 {
 189         mmp2_pm_enter_lowpower_mode(POWER_MODE_SYS_SLEEP);
 190 
 191         return 0;
 192 }
 193 
 194 /*
 195  * Called after devices are re-setup, but before processes are thawed.
 196  */
 197 static void mmp2_pm_finish(void)
 198 {
 199         mmp2_pm_enter_lowpower_mode(POWER_MODE_CORE_INTIDLE);
 200 }
 201 
 202 static int mmp2_pm_valid(suspend_state_t state)
 203 {
 204         return ((state == PM_SUSPEND_STANDBY) || (state == PM_SUSPEND_MEM));
 205 }
 206 
 207 /*
 208  * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
 209  */
 210 static const struct platform_suspend_ops mmp2_pm_ops = {
 211         .valid          = mmp2_pm_valid,
 212         .prepare        = mmp2_pm_prepare,
 213         .enter          = mmp2_pm_enter,
 214         .finish         = mmp2_pm_finish,
 215 };
 216 
 217 static int __init mmp2_pm_init(void)
 218 {
 219         uint32_t apcr;
 220 
 221         if (!cpu_is_mmp2())
 222                 return -EIO;
 223 
 224         suspend_set_ops(&mmp2_pm_ops);
 225 
 226         /*
 227          * Set bit 0, Slow clock Select 32K clock input instead of VCXO
 228          * VCXO is chosen by default, which would be disabled in suspend
 229          */
 230         __raw_writel(0x5, MPMU_SCCR);
 231 
 232         /*
 233          * Clear bit 23 of CIU_CPU_CONF
 234          * direct PJ4 to DDR access through Memory Controller slow queue
 235          * fast queue has issue and cause lcd will flick
 236          */
 237         __raw_writel(__raw_readl(CIU_REG(0x8)) & ~(0x1 << 23), CIU_REG(0x8));
 238 
 239         /* Clear default low power control bit */
 240         apcr = __raw_readl(MPMU_PCR_PJ);
 241         apcr &= ~(MPMU_PCR_PJ_SLPEN | MPMU_PCR_PJ_DDRCORSD
 242                         | MPMU_PCR_PJ_APBSD | MPMU_PCR_PJ_AXISD | 1 << 13);
 243         __raw_writel(apcr, MPMU_PCR_PJ);
 244 
 245         return 0;
 246 }
 247 
 248 late_initcall(mmp2_pm_init);

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