root/arch/arm/mach-omap2/pm33xx-core.c

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

DEFINITIONS

This source file includes following definitions.
  1. am43xx_map_scu
  2. am33xx_check_off_mode_enable
  3. am43xx_check_off_mode_enable
  4. amx3_common_init
  5. am33xx_suspend_init
  6. am43xx_suspend_init
  7. amx3_pre_suspend_common
  8. amx3_post_suspend_common
  9. am33xx_suspend
  10. am43xx_suspend
  11. amx3_get_sram_addrs
  12. am43xx_get_rtc_base_addr
  13. am43xx_save_context
  14. am33xx_save_context
  15. am33xx_restore_context
  16. am43xx_restore_context
  17. am43xx_prepare_rtc_suspend
  18. am43xx_prepare_rtc_resume
  19. am33xx_pm_get_pdata
  20. amx3_common_pm_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * AM33XX Arch Power Management Routines
   4  *
   5  * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
   6  *      Dave Gerlach
   7  */
   8 
   9 #include <asm/smp_scu.h>
  10 #include <asm/suspend.h>
  11 #include <linux/errno.h>
  12 #include <linux/platform_data/pm33xx.h>
  13 #include <linux/clk.h>
  14 #include <linux/platform_data/gpio-omap.h>
  15 #include <linux/pinctrl/pinmux.h>
  16 #include <linux/wkup_m3_ipc.h>
  17 #include <linux/of.h>
  18 #include <linux/rtc.h>
  19 
  20 #include "cm33xx.h"
  21 #include "common.h"
  22 #include "control.h"
  23 #include "clockdomain.h"
  24 #include "iomap.h"
  25 #include "omap_hwmod.h"
  26 #include "pm.h"
  27 #include "powerdomain.h"
  28 #include "prm33xx.h"
  29 #include "soc.h"
  30 #include "sram.h"
  31 
  32 static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
  33 static struct clockdomain *gfx_l4ls_clkdm;
  34 static void __iomem *scu_base;
  35 static struct omap_hwmod *rtc_oh;
  36 
  37 static int am43xx_map_scu(void)
  38 {
  39         scu_base = ioremap(scu_a9_get_base(), SZ_256);
  40 
  41         if (!scu_base)
  42                 return -ENOMEM;
  43 
  44         return 0;
  45 }
  46 
  47 static int am33xx_check_off_mode_enable(void)
  48 {
  49         if (enable_off_mode)
  50                 pr_warn("WARNING: This platform does not support off-mode, entering DeepSleep suspend.\n");
  51 
  52         /* off mode not supported on am335x so return 0 always */
  53         return 0;
  54 }
  55 
  56 static int am43xx_check_off_mode_enable(void)
  57 {
  58         /*
  59          * Check for am437x-gp-evm which has the right Hardware design to
  60          * support this mode reliably.
  61          */
  62         if (of_machine_is_compatible("ti,am437x-gp-evm") && enable_off_mode)
  63                 return enable_off_mode;
  64         else if (enable_off_mode)
  65                 pr_warn("WARNING: This platform does not support off-mode, entering DeepSleep suspend.\n");
  66 
  67         return 0;
  68 }
  69 
  70 static int amx3_common_init(void)
  71 {
  72         gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
  73         per_pwrdm = pwrdm_lookup("per_pwrdm");
  74         mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
  75 
  76         if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm))
  77                 return -ENODEV;
  78 
  79         (void)clkdm_for_each(omap_pm_clkdms_setup, NULL);
  80 
  81         /* CEFUSE domain can be turned off post bootup */
  82         cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
  83         if (!cefuse_pwrdm)
  84                 pr_err("PM: Failed to get cefuse_pwrdm\n");
  85         else if (omap_type() != OMAP2_DEVICE_TYPE_GP)
  86                 pr_info("PM: Leaving EFUSE power domain active\n");
  87         else
  88                 omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
  89 
  90         return 0;
  91 }
  92 
  93 static int am33xx_suspend_init(void)
  94 {
  95         int ret;
  96 
  97         gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
  98 
  99         if (!gfx_l4ls_clkdm) {
 100                 pr_err("PM: Cannot lookup gfx_l4ls_clkdm clockdomains\n");
 101                 return -ENODEV;
 102         }
 103 
 104         ret = amx3_common_init();
 105 
 106         return ret;
 107 }
 108 
 109 static int am43xx_suspend_init(void)
 110 {
 111         int ret = 0;
 112 
 113         ret = am43xx_map_scu();
 114         if (ret) {
 115                 pr_err("PM: Could not ioremap SCU\n");
 116                 return ret;
 117         }
 118 
 119         ret = amx3_common_init();
 120 
 121         return ret;
 122 }
 123 
 124 static void amx3_pre_suspend_common(void)
 125 {
 126         omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
 127 }
 128 
 129 static void amx3_post_suspend_common(void)
 130 {
 131         int status;
 132         /*
 133          * Because gfx_pwrdm is the only one under MPU control,
 134          * comment on transition status
 135          */
 136         status = pwrdm_read_pwrst(gfx_pwrdm);
 137         if (status != PWRDM_POWER_OFF)
 138                 pr_err("PM: GFX domain did not transition: %x\n", status);
 139 }
 140 
 141 static int am33xx_suspend(unsigned int state, int (*fn)(unsigned long),
 142                           unsigned long args)
 143 {
 144         int ret = 0;
 145 
 146         amx3_pre_suspend_common();
 147         ret = cpu_suspend(args, fn);
 148         amx3_post_suspend_common();
 149 
 150         /*
 151          * BUG: GFX_L4LS clock domain needs to be woken up to
 152          * ensure thet L4LS clock domain does not get stuck in
 153          * transition. If that happens L3 module does not get
 154          * disabled, thereby leading to PER power domain
 155          * transition failing
 156          */
 157 
 158         clkdm_wakeup(gfx_l4ls_clkdm);
 159         clkdm_sleep(gfx_l4ls_clkdm);
 160 
 161         return ret;
 162 }
 163 
 164 static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long),
 165                           unsigned long args)
 166 {
 167         int ret = 0;
 168 
 169         amx3_pre_suspend_common();
 170         scu_power_mode(scu_base, SCU_PM_POWEROFF);
 171         ret = cpu_suspend(args, fn);
 172         scu_power_mode(scu_base, SCU_PM_NORMAL);
 173 
 174         if (!am43xx_check_off_mode_enable())
 175                 amx3_post_suspend_common();
 176 
 177         return ret;
 178 }
 179 
 180 static struct am33xx_pm_sram_addr *amx3_get_sram_addrs(void)
 181 {
 182         if (soc_is_am33xx())
 183                 return &am33xx_pm_sram;
 184         else if (soc_is_am437x())
 185                 return &am43xx_pm_sram;
 186         else
 187                 return NULL;
 188 }
 189 
 190 void __iomem *am43xx_get_rtc_base_addr(void)
 191 {
 192         rtc_oh = omap_hwmod_lookup("rtc");
 193 
 194         return omap_hwmod_get_mpu_rt_va(rtc_oh);
 195 }
 196 
 197 static void am43xx_save_context(void)
 198 {
 199 }
 200 
 201 static void am33xx_save_context(void)
 202 {
 203         omap_intc_save_context();
 204 }
 205 
 206 static void am33xx_restore_context(void)
 207 {
 208         omap_intc_restore_context();
 209 }
 210 
 211 static void am43xx_restore_context(void)
 212 {
 213         /*
 214          * HACK: restore dpll_per_clkdcoldo register contents, to avoid
 215          * breaking suspend-resume
 216          */
 217         writel_relaxed(0x0, AM33XX_L4_WK_IO_ADDRESS(0x44df2e14));
 218 }
 219 
 220 static void am43xx_prepare_rtc_suspend(void)
 221 {
 222         omap_hwmod_enable(rtc_oh);
 223 }
 224 
 225 static void am43xx_prepare_rtc_resume(void)
 226 {
 227         omap_hwmod_idle(rtc_oh);
 228 }
 229 
 230 static struct am33xx_pm_platform_data am33xx_ops = {
 231         .init = am33xx_suspend_init,
 232         .soc_suspend = am33xx_suspend,
 233         .get_sram_addrs = amx3_get_sram_addrs,
 234         .save_context = am33xx_save_context,
 235         .restore_context = am33xx_restore_context,
 236         .prepare_rtc_suspend = am43xx_prepare_rtc_suspend,
 237         .prepare_rtc_resume = am43xx_prepare_rtc_resume,
 238         .check_off_mode_enable = am33xx_check_off_mode_enable,
 239         .get_rtc_base_addr = am43xx_get_rtc_base_addr,
 240 };
 241 
 242 static struct am33xx_pm_platform_data am43xx_ops = {
 243         .init = am43xx_suspend_init,
 244         .soc_suspend = am43xx_suspend,
 245         .get_sram_addrs = amx3_get_sram_addrs,
 246         .save_context = am43xx_save_context,
 247         .restore_context = am43xx_restore_context,
 248         .prepare_rtc_suspend = am43xx_prepare_rtc_suspend,
 249         .prepare_rtc_resume = am43xx_prepare_rtc_resume,
 250         .check_off_mode_enable = am43xx_check_off_mode_enable,
 251         .get_rtc_base_addr = am43xx_get_rtc_base_addr,
 252 };
 253 
 254 static struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void)
 255 {
 256         if (soc_is_am33xx())
 257                 return &am33xx_ops;
 258         else if (soc_is_am437x())
 259                 return &am43xx_ops;
 260         else
 261                 return NULL;
 262 }
 263 
 264 int __init amx3_common_pm_init(void)
 265 {
 266         struct am33xx_pm_platform_data *pdata;
 267         struct platform_device_info devinfo;
 268 
 269         pdata = am33xx_pm_get_pdata();
 270 
 271         memset(&devinfo, 0, sizeof(devinfo));
 272         devinfo.name = "pm33xx";
 273         devinfo.data = pdata;
 274         devinfo.size_data = sizeof(*pdata);
 275         devinfo.id = -1;
 276         platform_device_register_full(&devinfo);
 277 
 278         return 0;
 279 }

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