/* * omap-pm-interface.c - OMAP power management interface * * This code implements the OMAP power management interface to * drivers, CPUIdle, CPUFreq, and DSP Bridge. * * Copyright (C) 2008-2011 Texas Instruments, Inc. * Copyright (C) 2008-2009 Nokia Corporation * Paul Walmsley * * Interface developed by (in alphabetical order): * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff */ #undef DEBUG #include #include #include #include #include /* Interface documentation is in mach/omap-pm.h */ #include #include #include "omap-pm-helper.h" #include "../mach-omap2/prm44xx.h" bool off_mode_enabled; /* * Device-driver-originated constraints (via board-*.c files) * WARNING: Device drivers need to now use pm_qos directly. */ int omap_pm_set_max_mpu_wakeup_lat(struct pm_qos_request_list **pmqos_req, long t) { WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", __func__); return -EINVAL; } int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, long r) { int ret; if (!dev || (agent_id != OCP_INITIATOR_AGENT && agent_id != OCP_TARGET_AGENT)) { WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); return -EINVAL; }; if (r == -1) pr_debug("OMAP PM: remove min bus tput constraint: " "dev %s for agent_id %d\n", dev_name(dev), agent_id); else pr_debug("OMAP PM: add min bus tput constraint: " "dev %s for agent_id %d: rate %ld KiB\n", dev_name(dev), agent_id, r); ret = omap_pm_set_min_bus_tput_helper(dev, agent_id, r); return ret; } int omap_pm_apply_min_bus_tput(void) { return omap_pm_apply_min_bus_tput_helper(); } int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, long t) { int ret; if (!req_dev || !dev || t < -1) { WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); return -EINVAL; }; if (t == -1) pr_debug("OMAP PM: remove max device latency constraint: " "dev %s\n", dev_name(dev)); else pr_debug("OMAP PM: add max device latency constraint: " "dev %s, t = %ld usec\n", dev_name(dev), t); ret = omap_pm_set_max_dev_wakeup_lat_helper(req_dev, dev, t); return ret; } /* WARNING: Device drivers need to now use pm_qos directly. */ int omap_pm_set_max_sdma_lat(struct pm_qos_request_list **qos_request, long t) { WARN(1, "Deprecated %s: Driver should use pm_qos to add request\n", __func__); return -EINVAL; } int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", __func__); return -EINVAL; } /* * DSP Bridge-specific constraints * WARNING: Device drivers need to now use opp layer/omap_device_scale directly. */ const struct omap_opp *omap_pm_dsp_get_opp_table(void) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", __func__); return ERR_PTR(-EINVAL); } void omap_pm_dsp_set_min_opp(u8 opp_id) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", __func__); return; } int omap_pm_set_min_mpu_freq(struct device *dev, unsigned long f) { WARN(1, "Deprecated %s: Driver should NOT use this function\n", __func__); return -EINVAL; } EXPORT_SYMBOL(omap_pm_set_min_mpu_freq); u8 omap_pm_dsp_get_opp(void) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", __func__); return 0; } /* * CPUFreq-originated constraint * * In the future, this should be handled by custom OPP clocktype * functions. */ struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", __func__); return ERR_PTR(-EINVAL); } void omap_pm_cpu_set_freq(unsigned long f) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", __func__); return; } unsigned long omap_pm_cpu_get_freq(void) { WARN(1, "Deprecated %s: Driver should use omap_device_scale/opp\n", __func__); return 0; } /** * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled * * Intended for use only by OMAP PM core code to notify this layer * that off mode has been enabled. */ void omap_pm_enable_off_mode(void) { off_mode_enabled = true; } /** * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled * * Intended for use only by OMAP PM core code to notify this layer * that off mode has been disabled. */ void omap_pm_disable_off_mode(void) { off_mode_enabled = false; } bool omap_pm_was_context_lost(struct device *dev) { struct platform_device *pdev; struct omap_device *od; struct omap_hwmod *oh; if (!dev) goto save_ctx; pdev = container_of(dev, struct platform_device, dev); od = container_of(pdev, struct omap_device, pdev); oh = od->hwmods[0]; if (!oh || !cpu_is_omap44xx()) goto save_ctx; if (oh->prcm.omap4.context_reg) { u32 context_reg_val = 0; /*Read what context was lost.*/ context_reg_val = __raw_readl(oh->prcm.omap4.context_reg); /*clear context lost bits after read*/ __raw_writel(context_reg_val, oh->prcm.omap4.context_reg); /* ABE special case, only report ctx lost when we loose * mem, otherwise, constant firmware reload causes problems. */ if (oh->prcm.omap4.context_reg == OMAP4430_RM_ABE_AESS_CONTEXT) context_reg_val &= (1 << 8); return (context_reg_val != 0); } save_ctx: /* by default return true so that driver will restore context*/ return true; } /* Should be called before clk framework init */ int __init omap_pm_if_early_init(void) { return 0; } /* Must be called after clock framework is initialized */ int __init omap_pm_if_init(void) { return omap_pm_if_init_helper(); } void omap_pm_if_exit(void) { /* Deallocate CPUFreq frequency table here */ }