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> --- 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