linux/arch/arm/mach-omap2/pm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * pm.c - Common OMAP2+ power management-related code
   4 *
   5 * Copyright (C) 2010 Texas Instruments, Inc.
   6 * Copyright (C) 2010 Nokia Corporation
   7 */
   8
   9#include <linux/kernel.h>
  10#include <linux/init.h>
  11#include <linux/io.h>
  12#include <linux/err.h>
  13#include <linux/pm_opp.h>
  14#include <linux/export.h>
  15#include <linux/suspend.h>
  16#include <linux/clk.h>
  17#include <linux/cpu.h>
  18
  19#include <asm/system_misc.h>
  20
  21#include "omap_device.h"
  22#include "common.h"
  23
  24#include "soc.h"
  25#include "prcm-common.h"
  26#include "voltage.h"
  27#include "powerdomain.h"
  28#include "clockdomain.h"
  29#include "pm.h"
  30
  31#ifdef CONFIG_SUSPEND
  32/*
  33 * omap_pm_suspend: points to a function that does the SoC-specific
  34 * suspend work
  35 */
  36static int (*omap_pm_suspend)(void);
  37#endif
  38
  39#ifdef CONFIG_PM
  40/**
  41 * struct omap2_oscillator - Describe the board main oscillator latencies
  42 * @startup_time: oscillator startup latency
  43 * @shutdown_time: oscillator shutdown latency
  44 */
  45struct omap2_oscillator {
  46        u32 startup_time;
  47        u32 shutdown_time;
  48};
  49
  50static struct omap2_oscillator oscillator = {
  51        .startup_time = ULONG_MAX,
  52        .shutdown_time = ULONG_MAX,
  53};
  54
  55void omap_pm_setup_oscillator(u32 tstart, u32 tshut)
  56{
  57        oscillator.startup_time = tstart;
  58        oscillator.shutdown_time = tshut;
  59}
  60
  61void omap_pm_get_oscillator(u32 *tstart, u32 *tshut)
  62{
  63        if (!tstart || !tshut)
  64                return;
  65
  66        *tstart = oscillator.startup_time;
  67        *tshut = oscillator.shutdown_time;
  68}
  69#endif
  70
  71int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
  72{
  73        clkdm_allow_idle(clkdm);
  74        return 0;
  75}
  76
  77#ifdef CONFIG_SUSPEND
  78static int omap_pm_enter(suspend_state_t suspend_state)
  79{
  80        int ret = 0;
  81
  82        if (!omap_pm_suspend)
  83                return -ENOENT; /* XXX doublecheck */
  84
  85        switch (suspend_state) {
  86        case PM_SUSPEND_MEM:
  87                ret = omap_pm_suspend();
  88                break;
  89        default:
  90                ret = -EINVAL;
  91        }
  92
  93        return ret;
  94}
  95
  96static int omap_pm_begin(suspend_state_t state)
  97{
  98        cpu_idle_poll_ctrl(true);
  99        if (soc_is_omap34xx())
 100                omap_prcm_irq_prepare();
 101        return 0;
 102}
 103
 104static void omap_pm_end(void)
 105{
 106        cpu_idle_poll_ctrl(false);
 107}
 108
 109static void omap_pm_wake(void)
 110{
 111        if (soc_is_omap34xx())
 112                omap_prcm_irq_complete();
 113}
 114
 115static const struct platform_suspend_ops omap_pm_ops = {
 116        .begin          = omap_pm_begin,
 117        .end            = omap_pm_end,
 118        .enter          = omap_pm_enter,
 119        .wake           = omap_pm_wake,
 120        .valid          = suspend_valid_only_mem,
 121};
 122
 123/**
 124 * omap_common_suspend_init - Set common suspend routines for OMAP SoCs
 125 * @pm_suspend: function pointer to SoC specific suspend function
 126 */
 127void omap_common_suspend_init(void *pm_suspend)
 128{
 129        omap_pm_suspend = pm_suspend;
 130        suspend_set_ops(&omap_pm_ops);
 131}
 132#endif /* CONFIG_SUSPEND */
 133
 134int __maybe_unused omap_pm_nop_init(void)
 135{
 136        return 0;
 137}
 138
 139int (*omap_pm_soc_init)(void);
 140
 141int __init omap2_common_pm_late_init(void)
 142{
 143        int error;
 144
 145        if (!omap_pm_soc_init)
 146                return 0;
 147
 148        /* Init the voltage layer */
 149        omap3_twl_init();
 150        omap4_twl_init();
 151        omap4_cpcap_init();
 152        omap_voltage_late_init();
 153
 154        /* Smartreflex device init */
 155        omap_devinit_smartreflex();
 156
 157        error = omap_pm_soc_init();
 158        if (error)
 159                pr_warn("%s: pm soc init failed: %i\n", __func__, error);
 160
 161        omap2_clk_enable_autoidle_all();
 162
 163        return 0;
 164}
 165omap_late_initcall(omap2_common_pm_late_init);
 166