Introduce notifier infrastructure for VDD voltage transitions. Users can register a notifier prior to a VDD's volt_scale function getting called (VOLTSCALE_PRECHANGE) or after the VDD has been scaled (VOLTSCALE_POSTCHANGE). Signed-off-by: Mike Turquette <mturquette@xxxxxx> --- All patches in this series based on PM branch (b6fb54b) plus Vishwa's 13 OMAP3 DVFS patches (http://marc.info/?l=linux-omap&m=129561825804975&w=2). Only validated on Zoom3 since OMAP4 DVFS patches were not available. arch/arm/mach-omap2/voltage.c | 47 ++++++++++++++++++++++++++++- arch/arm/plat-omap/include/plat/voltage.h | 30 ++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index a0bd73b..0cbc58a 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -729,6 +729,9 @@ static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd) return -EINVAL; } + /* initialize the voltage change notifier chain */ + srcu_init_notifier_head(&vdd->volt_change_notify_chain); + if (!strcmp(vdd->voltdm.name, "mpu")) { if (cpu_is_omap3630()) { vdd->volt_data = omap36xx_vddmpu_volt_data; @@ -912,6 +915,9 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd) return -EINVAL; } + /* initialize the voltage change notifier chain */ + srcu_init_notifier_head(&vdd->volt_change_notify_chain); + if (!strcmp(vdd->voltdm.name, "mpu")) { vdd->volt_data = omap44xx_vdd_mpu_volt_data; vdd->vp_reg.tranxdone_status = @@ -1201,7 +1207,9 @@ void omap_vp_disable(struct voltagedomain *voltdm) int omap_voltage_scale_vdd(struct voltagedomain *voltdm, unsigned long target_volt) { + int ret; struct omap_vdd_info *vdd; + struct omap_volt_change_info v_info; if (!voltdm || IS_ERR(voltdm)) { pr_warning("%s: VDD specified does not exist!\n", __func__); @@ -1216,7 +1224,20 @@ int omap_voltage_scale_vdd(struct voltagedomain *voltdm, return -ENODATA; } - return vdd->volt_scale(vdd, target_volt); + /* load notifier chain data */ + v_info.target_volt = target_volt; + v_info.vdd = vdd; + + srcu_notifier_call_chain(&vdd->volt_change_notify_chain, + VOLTSCALE_PRECHANGE, (void *)&v_info); + + ret = vdd->volt_scale(vdd, target_volt); + + if (!ret) + srcu_notifier_call_chain(&vdd->volt_change_notify_chain, + VOLTSCALE_POSTCHANGE, (void *)&v_info); + + return ret; } /** @@ -1437,6 +1458,30 @@ struct voltagedomain *omap_voltage_domain_lookup(char *name) return ERR_PTR(-EINVAL); } +int omap_voltage_register_notifier(struct omap_vdd_info *vdd, + struct notifier_block *nb) +{ + if (!vdd || IS_ERR(vdd)) { + pr_warning("%s: invalid VDD specified\n", __func__); + return -EINVAL; + } + + return srcu_notifier_chain_register(&vdd->volt_change_notify_chain, + nb); +} + +int omap_voltage_unregister_notifier(struct omap_vdd_info *vdd, + struct notifier_block *nb) +{ + if (!vdd || IS_ERR(vdd)) { + pr_warning("%s: invalid VDD specified\n", __func__); + return -EINVAL; + } + + return srcu_notifier_chain_unregister(&vdd->volt_change_notify_chain, + nb); +} + /** * omap_voltage_late_init() - Init the various voltage parameters * diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h index e0b7f22..017e65b 100644 --- a/arch/arm/plat-omap/include/plat/voltage.h +++ b/arch/arm/plat-omap/include/plat/voltage.h @@ -15,10 +15,14 @@ #define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H #include <linux/err.h> +#include <linux/notifier.h> #define VOLTSCALE_VPFORCEUPDATE 1 #define VOLTSCALE_VCBYPASS 2 +#define VOLTSCALE_PRECHANGE 0 +#define VOLTSCALE_POSTCHANGE 1 + /* * OMAP3 GENERIC setup times. Revisit to see if these needs to be * passed from board or PMIC file @@ -249,6 +253,7 @@ struct omap_vdd_info { struct vc_reg_info vc_reg; struct voltagedomain voltdm; struct omap_vdd_dep_info *dep_vdd_info; + struct srcu_notifier_head volt_change_notify_chain; int nr_dep_vdd; struct dentry *debug_dir; u32 curr_volt; @@ -261,6 +266,17 @@ struct omap_vdd_info { unsigned long target_volt); }; +/** + * omap_volt_change_info - container used by voltage notifier chain + * + * @vdd_info : the voltage domain affected by the transition + * @target_volt : voltage the affected domain is transitioning to + */ +struct omap_volt_change_info { + unsigned long target_volt; + struct omap_vdd_info *vdd; +}; + unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm); void omap_vp_enable(struct voltagedomain *voltdm); void omap_vp_disable(struct voltagedomain *voltdm); @@ -280,6 +296,10 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm, int voltscale_method); /* API to get the voltagedomain pointer */ struct voltagedomain *omap_voltage_domain_lookup(char *name); +int omap_voltage_register_notifier(struct omap_vdd_info *vdd, + struct notifier_block *nb); +int omap_voltage_unregister_notifier(struct omap_vdd_info *vdd, + struct notifier_block *nb); int omap_voltage_late_init(void); #else @@ -298,6 +318,16 @@ static inline struct voltagedomain *omap_voltage_domain_lookup(char *name) { return ERR_PTR(-EINVAL); } +static inline int omap_voltage_register_notifier(struct omap_vdd_info *vdd, + struct notifier block *nb) +{ + return 0; +} +static inline int omap_voltage_unregister_notifier(struct omap_vdd_info *vdd, + struct notifier block *nb) +{ + return 0; +} #endif #endif -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html