Thara Gopinath <[email protected]> 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 <[email protected]>
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html