From 3969406b1bc1d11ec362b61ee5c48d551e51fed3 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Thu, 25 Aug 2011 18:14:12 +0530 Subject: [PATCH] OMAP2+: DVFS: provide ability to know if dvfs is scaling for a domain Provide mechanism to know if DVFS is scaling on a specific domain. This API will allow us to detect transition and take appropriate measures in idle path Acked-by: Todd Poynor Acked-by: Santosh Shilimkar Signed-off-by: Nishanth Menon [vaibhav.bedia@ti.com: Pull in for AM33xx] Signed-off-by: Vaibhav Bedia --- arch/arm/mach-omap2/dvfs.c | 41 ++++++++++++++++++++++++++++++++++ arch/arm/plat-omap/include/plat/dvfs.h | 6 +++++ 2 files changed, 47 insertions(+) diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c index 6fdc380..5c5e436 100644 --- a/arch/arm/mach-omap2/dvfs.c +++ b/arch/arm/mach-omap2/dvfs.c @@ -174,6 +174,8 @@ struct omap_vdd_user_list { * @vdd_user_list: The vdd user list * @voltdm: Voltage domains for which dvfs info stored * @dev_list: Device list maintained per domain + * @is_scaling: flag to store information about scaling in progress or not + * this flag is already protected by the global mutex. * * This is a fundamental structure used to store all the required * DVFS related information for a vdd. @@ -185,6 +187,7 @@ struct omap_vdd_dvfs_info { struct plist_head vdd_user_list; struct voltagedomain *voltdm; struct list_head dev_list; + bool is_scaling; }; static LIST_HEAD(omap_dvfs_info_list); @@ -694,6 +697,11 @@ static int _dvfs_scale(struct device *req_dev, struct device *target_dev, } vdd = voltdm->vdd; + /* Mark that we are scaling for this device */ + tdvfs_info->is_scaling = true; + /* let the other CPU know as well */ + smp_wmb(); + /* Find the highest voltage being requested */ node = plist_last(&tdvfs_info->vdd_user_list); new_volt = node->prio; @@ -790,6 +798,11 @@ out: /* Re-enable Smartreflex module */ omap_sr_enable(voltdm); + /* Mark done */ + tdvfs_info->is_scaling = false; + /* let the other CPU know as well */ + smp_wmb(); + return ret; } @@ -882,6 +895,34 @@ out: } EXPORT_SYMBOL(omap_device_scale); +/** + * omap_dvfs_is_scaling() - Tells the caller if the domain is scaling + * @voltdm: voltage domain we are interested in + * + * Returns true if the domain is in the middle of scale operation, + * returns false if there is no scale operation is in progress or an + * invalid parameter was passed. + */ +bool omap_dvfs_is_scaling(struct voltagedomain *voltdm) +{ + struct omap_vdd_dvfs_info *dvfs_info; + + if (IS_ERR_OR_NULL(voltdm)) { + pr_err("%s: bad voltdm\n", __func__); + return false; + } + + dvfs_info = _voltdm_to_dvfs_info(voltdm); + if (IS_ERR_OR_NULL(dvfs_info)) { + pr_err("%s: no dvfsinfo for voltdm %s\n", + __func__, voltdm->name); + return false; + } + + return dvfs_info->is_scaling; +} +EXPORT_SYMBOL(omap_dvfs_is_scaling); + #ifdef CONFIG_PM_DEBUG static int dvfs_dump_vdd(struct seq_file *sf, void *unused) { diff --git a/arch/arm/plat-omap/include/plat/dvfs.h b/arch/arm/plat-omap/include/plat/dvfs.h index 5a73fe8..c84a61e 100644 --- a/arch/arm/plat-omap/include/plat/dvfs.h +++ b/arch/arm/plat-omap/include/plat/dvfs.h @@ -21,6 +21,8 @@ int omap_dvfs_register_device(struct device *dev, char *voltdm_name, char *clk_name); int omap_device_scale(struct device *req_dev, struct device *target_dev, unsigned long rate); + +bool omap_dvfs_is_scaling(struct voltagedomain *voltdm); #else static inline int omap_dvfs_register_device(struct omap_hwmod *oh, struct device *dev) @@ -34,5 +36,9 @@ static inline int omap_device_scale(struct device *req_dev, { return -EINVAL; } +static inline bool omap_dvfs_is_scaling(struct voltagedomain *voltdm) +{ + return false; +} #endif #endif -- 1.9.1