Thara Gopinath <thara@xxxxxx> writes: > OMAP3 smartreflex modules are capable of two different classes > of implementaion - > Class-2: Continuous Software Calibration > Class-3: Continuous Hardware Calibration. > OMAP3 along with T2/Gaia supports the Class 3 implementaion. > With a different PMIC it can support Class 2 implementaion also. > > The idea behind this patch is that smartreflex.c should be able > to support both the classes of Smartreflex and the class specific > details for smartreflex should stay out of this file in a separate > class file. > This patch introduces smartreflex class specific hooks in > smartreflex.c. This patch only takes care of smartreflex enable > disable hooks which differ between Class 2 and Class 3. There > are some register setting changes between both the classes which > will be taken care of in a later patch. > This will form the base for adding class specific > drivers in later patches. > > Signed-off-by: Thara Gopinath <thara@xxxxxx> Minor nit: the name change for omap_smartreflex_[enable|disable] is unrelated to this change and should be a separate patch to go early in the series. Kevin > --- > arch/arm/mach-omap2/pm34xx.c | 8 +- > arch/arm/mach-omap2/smartreflex.c | 251 ++++++++++++++++++++---------------- > arch/arm/mach-omap2/smartreflex.h | 48 ++++++-- > 3 files changed, 182 insertions(+), 125 deletions(-) > > diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c > index cf9ca23..ece5195 100644 > --- a/arch/arm/mach-omap2/pm34xx.c > +++ b/arch/arm/mach-omap2/pm34xx.c > @@ -430,9 +430,9 @@ void omap_sram_idle(void) > * Only needed if we are going to enter retention or off. > */ > if (mpu_next_state <= PWRDM_POWER_RET) > - disable_smartreflex(SR1); > + omap_smartreflex_disable(SR1); > if (core_next_state <= PWRDM_POWER_RET) > - disable_smartreflex(SR2); > + omap_smartreflex_disable(SR2); > > /* CORE */ > if (core_next_state < PWRDM_POWER_ON) { > @@ -531,9 +531,9 @@ void omap_sram_idle(void) > * retention or off > */ > if (mpu_next_state <= PWRDM_POWER_RET) > - enable_smartreflex(SR1); > + omap_smartreflex_enable(SR1); > if (core_next_state <= PWRDM_POWER_RET) > - enable_smartreflex(SR2); > + omap_smartreflex_enable(SR2); > > /* PER */ > if (per_next_state < PWRDM_POWER_ON) { > diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c > index c00925d..ba9f899 100644 > --- a/arch/arm/mach-omap2/smartreflex.c > +++ b/arch/arm/mach-omap2/smartreflex.c > @@ -55,6 +55,7 @@ struct omap_sr { > > /* sr_list contains all the instances of smartreflex module */ > static LIST_HEAD(sr_list); > +static struct omap_smartreflex_class_data *sr_class; > > #define SR_REGADDR(offs) (sr->srbase_addr + offset) > > @@ -388,14 +389,86 @@ static int sr_reset_voltage(int srid) > return 0; > } > > -static int sr_enable(struct omap_sr *sr, u32 target_opp_no) > +static void sr_start_vddautocomap(int srid) > +{ > + struct omap_sr *sr = _sr_lookup(srid); > + > + if (!sr) { > + pr_warning("omap_sr struct corresponding to SR%d not found\n", > + srid); > + return; > + } > + > + if (!sr_class || !(sr_class->enable)) { > + pr_warning("smartreflex class driver not registered\n"); > + return; > + } > + > + if (sr->is_sr_reset == 1) { > + sr_clk_enable(sr); > + sr_configure(sr); > + } > + > + sr->is_autocomp_active = 1; > + if (!sr_class->enable(srid)) { > + sr->is_autocomp_active = 0; > + if (sr->is_sr_reset == 1) > + sr_clk_disable(sr); > + } > +} > + > +static void sr_stop_vddautocomap(int srid) > +{ > + struct omap_sr *sr = _sr_lookup(srid); > + > + if (!sr) { > + pr_warning("omap_sr struct corresponding to SR%d not found\n", > + srid); > + return; > + } > + if (!sr_class || !(sr_class->disable)) { > + pr_warning("smartreflex class driver not registered\n"); > + return; > + } > + > + if (sr->is_autocomp_active == 1) { > + sr_class->disable(srid); > + sr_clk_disable(sr); > + sr->is_autocomp_active = 0; > + /* Reset the volatage for current OPP */ > + sr_reset_voltage(srid); > + } > + > +} > + > +/* Public Functions */ > + > +/** > + * sr_enable : Enables the smartreflex module. > + * @srid - The id of the sr module to be enabled. > + * @target_opp_no - The OPP at which the Voltage domain associated with > + * the smartreflex module is operating at. This is required only to program > + * the correct Ntarget value. > + * > + * This API is to be called from the smartreflex class driver to > + * enable a smartreflex module. Returns true on success.Returns false if the > + * target opp id passed is wrong or if ntarget value is wrong. > + */ > +int sr_enable(int srid, u32 target_opp_no) > { > u32 nvalue_reciprocal, v; > + struct omap_sr *sr = _sr_lookup(srid); > struct omap_opp *opp; > struct omap_smartreflex_data *pdata = sr->pdev->dev.platform_data; > int uvdc; > char vsel; > > + if (!sr) { > + pr_warning("omap_sr struct corresponding to SR%d not found\n", > + srid); > + return false; > + } > + > if (sr->srid == SR1) { > opp = opp_find_by_opp_id(OPP_MPU, target_opp_no); > if (!opp) > @@ -477,8 +550,16 @@ static int sr_enable(struct omap_sr *sr, u32 target_opp_no) > return true; > } > > -static void sr_disable(struct omap_sr *sr) > +/** > + * sr_disable : Disables the smartreflex module. > + * @srid - The id of the sr module to be disabled. > + * > + * This API is to be called from the smartreflex class driver to > + * disable a smartreflex module. > + */ > +void sr_disable(int srid) > { > + struct omap_sr *sr = _sr_lookup(srid); > u32 i = 0; > > sr->is_sr_reset = 1; > @@ -518,9 +599,19 @@ static void sr_disable(struct omap_sr *sr) > } > } > > - > -void sr_start_vddautocomap(int srid, u32 target_opp_no) > +/** > + * omap_smartreflex_enable : API to enable SR clocks and to call into the > + * registered smartreflex class enable API. > + * @srid - The id of the sr module to be enabled. > + * > + * This API is to be called from the kernel in order to enable > + * a particular smartreflex module. This API will do the initial > + * configurations to turn on the smartreflex module and in turn call > + * into the registered smartreflex class enable API. > + */ > +void omap_smartreflex_enable(int srid) > { > + u32 target_opp_no = 0; > struct omap_sr *sr = _sr_lookup(srid); > > if (!sr) { > @@ -528,52 +619,8 @@ void sr_start_vddautocomap(int srid, u32 target_opp_no) > srid); > return; > } > - > - if (sr->is_sr_reset == 1) { > - sr_clk_enable(sr); > - sr_configure(sr); > - } > - > - sr->is_autocomp_active = 1; > - if (!sr_enable(sr, target_opp_no)) { > - sr->is_autocomp_active = 0; > - if (sr->is_sr_reset == 1) > - sr_clk_disable(sr); > - } > -} > -EXPORT_SYMBOL(sr_start_vddautocomap); > - > -int sr_stop_vddautocomap(int srid) > -{ > - struct omap_sr *sr = _sr_lookup(srid); > - > - if (!sr) { > - pr_warning("omap_sr struct corresponding to SR%d not found\n", > - srid); > - return false; > - } > - > - if (sr->is_autocomp_active == 1) { > - sr_disable(sr); > - sr_clk_disable(sr); > - sr->is_autocomp_active = 0; > - /* Reset the volatage for current OPP */ > - sr_reset_voltage(srid); > - return true; > - } else > - return false; > - > -} > -EXPORT_SYMBOL(sr_stop_vddautocomap); > - > -void enable_smartreflex(int srid) > -{ > - u32 target_opp_no = 0; > - struct omap_sr *sr = _sr_lookup(srid); > - > - if (!sr) { > - pr_warning("omap_sr struct corresponding to SR%d not found\n", > - srid); > + if (!sr_class || !(sr_class->enable)) { > + pr_warning("smartreflex class driver not registered\n"); > return; > } > > @@ -581,26 +628,24 @@ void enable_smartreflex(int srid) > if (sr->is_sr_reset == 1) { > /* Enable SR clks */ > sr_clk_enable(sr); > - > - if (srid == SR1) > - target_opp_no = get_vdd1_opp(); > - else if (srid == SR2) > - target_opp_no = get_vdd2_opp(); > - > - if (!target_opp_no) { > - pr_info("Current OPP unknown \ > - Cannot configure SR\n"); > - } > - > sr_configure(sr); > > - if (!sr_enable(sr, target_opp_no)) > + if (!sr_class->enable(srid)) > sr_clk_disable(sr); > } > } > } > > -void disable_smartreflex(int srid) > +/** > + * omap_smartreflex_disable : API to disable SR clocks and to call into the > + * registered smartreflex class disable API. > + * @srid - The id of the sr module to be disabled. > + * > + * This API is to be called from the kernel in order to disable > + * a particular smartreflex module. This API will in turn call > + * into the registered smartreflex class disable API. > + */ > +void omap_smartreflex_disable(int srid) > { > u32 i = 0; > struct omap_sr *sr = _sr_lookup(srid); > @@ -610,54 +655,43 @@ void disable_smartreflex(int srid) > srid); > return; > } > + if (!sr_class || !(sr_class->disable)) { > + pr_warning("smartreflex class driver not registered\n"); > + return; > + } > > if (sr->is_autocomp_active == 1) { > if (sr->is_sr_reset == 0) { > - > - sr->is_sr_reset = 1; > - /* SRCONFIG - disable SR */ > - sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, > - ~SRCONFIG_SRENABLE); > - > + sr_class->disable(srid); > /* Disable SR clk */ > sr_clk_disable(sr); > - if (sr->srid == SR1) { > - /* Wait for VP idle before disabling VP */ > - while ((!prm_read_mod_reg(OMAP3430_GR_MOD, > - OMAP3_PRM_VP1_STATUS_OFFSET)) > - && i++ < MAX_TRIES) > - udelay(1); > - > - if (i >= MAX_TRIES) > - pr_warning("VP1 not idle, still going \ > - ahead with VP1 disable\n"); > - > - /* Disable VP1 */ > - prm_clear_mod_reg_bits(PRM_VP1_CONFIG_VPENABLE, > - OMAP3430_GR_MOD, > - OMAP3_PRM_VP1_CONFIG_OFFSET); > - } else if (sr->srid == SR2) { > - /* Wait for VP idle before disabling VP */ > - while ((!prm_read_mod_reg(OMAP3430_GR_MOD, > - OMAP3_PRM_VP2_STATUS_OFFSET)) > - && i++ < MAX_TRIES) > - udelay(1); > - > - if (i >= MAX_TRIES) > - pr_warning("VP2 not idle, still going \ > - ahead with VP2 disable\n"); > - > - /* Disable VP2 */ > - prm_clear_mod_reg_bits(PRM_VP2_CONFIG_VPENABLE, > - OMAP3430_GR_MOD, > - OMAP3_PRM_VP2_CONFIG_OFFSET); > - } > /* Reset the volatage for current OPP */ > sr_reset_voltage(srid); > } > } > } > > +/** > + * omap_sr_register_class : API to register a smartreflex class parameters. > + * @class_data - The structure containing various sr class specific data. > + * > + * This API is to be called by the smartreflex class driver to register itself > + * with the smartreflex driver during init. > + */ > +void omap_sr_register_class(struct omap_smartreflex_class_data *class_data) > +{ > + if (!class_data) { > + pr_warning("Smartreflex class data passed is NULL\n"); > + return; > + } > + > + if (sr_class) { > + pr_warning("Smartreflex class driver already registered\n"); > + return; > + } > + sr_class = class_data; > +} > + > /* Voltage Scaling using SR VCBYPASS */ > int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp, > u8 target_vsel, u8 current_vsel) > @@ -730,9 +764,9 @@ int sr_voltagescale_vcbypass(u32 target_opp, u32 current_opp, > > if (sr_status) { > if (vdd == VDD1_OPP) > - sr_start_vddautocomap(SR1, target_opp_no); > + sr_start_vddautocomap(SR1); > else if (vdd == VDD2_OPP) > - sr_start_vddautocomap(SR2, target_opp_no); > + sr_start_vddautocomap(SR2); > } > > return 0; > @@ -762,17 +796,10 @@ static int omap_sr_autocomp_store(void *data, u64 val) > sr_info->srid); > return 0; > } > - if (val == 0) { > + if (val == 0) > sr_stop_vddautocomap(sr_info->srid); > - } else { > - u32 current_opp; > - > - if (sr_info->srid == SR1) > - current_opp = get_vdd1_opp(); > - else > - current_opp = get_vdd2_opp(); > - sr_start_vddautocomap(sr_info->srid, current_opp); > - } > + else > + sr_start_vddautocomap(sr_info->srid); > return 0; > } > > diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h > index 572cdca..a59a073 100644 > --- a/arch/arm/mach-omap2/smartreflex.h > +++ b/arch/arm/mach-omap2/smartreflex.h > @@ -243,12 +243,27 @@ extern u32 current_vdd2_opp; > #define SR_TESTING_NVALUES 0 > #endif > > -/* > - * Smartreflex module enable/disable interface. > - * NOTE: if smartreflex is not enabled from sysfs, these functions will not > - * do anything. > - */ > #ifdef CONFIG_OMAP_SMARTREFLEX > +/** > + * omap_smartreflex_class_data : Structure to be populated by > + * Smartreflex class driver with corresponding class enable disable API's > + * > + * @enable - API to enable a particular class smaartreflex. > + * @disable - API to disable a particular class smartreflex. > + * @notify - API to notify the class driver about an event in SR. Not needed > + * for class3. > + * @notify_flags - specify the events to be notified to the class driver > + * @class_type - specify which smartreflex class. Can be used by the SR driver > + * to tkae any class based decisions. > + */ > +struct omap_smartreflex_class_data { > + int (*enable)(int sr_id); > + int (*disable)(int sr_id); > + int (*notify)(int sr_id, u32 status); > + u8 notify_flags; > + u8 class_type; > +}; > + > /* > * omap_smartreflex_data - Smartreflex platform data > * > @@ -274,11 +289,26 @@ struct omap_smartreflex_data { > int (*device_idle)(struct platform_device *pdev); > }; > > -void enable_smartreflex(int srid); > -void disable_smartreflex(int srid); > +/* > + * Smartreflex module enable/disable interface. > + * NOTE: if smartreflex is not enabled from sysfs, these functions will not > + * do anything. > + */ > +void omap_smartreflex_enable(int srid); > +void omap_smartreflex_disable(int srid); > + > +/** > + * Smartreflex driver hooks to be called from Smartreflex class driver > + */ > +int sr_enable(int srid, u32 target_opp_no); > +void sr_disable(int srid); > + > +/** > + * API to register the smartreflex class driver with the smartreflex driver > + */ > +void omap_sr_register_class(struct omap_smartreflex_class_data *class_data); > + > int sr_voltagescale_vcbypass(u32 t_opp, u32 c_opp, u8 t_vsel, u8 c_vsel); > -void sr_start_vddautocomap(int srid, u32 target_opp_no); > -int sr_stop_vddautocomap(int srid); > #else > static inline void enable_smartreflex(int srid) {} > static inline void disable_smartreflex(int srid) {} > -- > 1.7.0.rc1.33.g07cf0f -- 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