Re: [PATCH 4/4] OMAP: Voltage: Adaptive Body-Bias handlers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Fri, Feb 18, 2011 at 11:20 AM, Mike Turquette <mturquette@xxxxxx> wrote:
> Introduce voltage transition notification handlers for Adaptive Body-Bias
> LDOs. ÂThere is an ABB LDO for VDD_MPU on OMAP3630 and an ABB_LDO on VDD_MPU
> and VDD_IVA on OMAP4430.
>
> All of these LDOs are handled similary. ÂInitial configuration is to enable
> the possibility of going into Forward Body-Bias (which boosts voltage at
> high OPPs). ÂThis feature was designed for weak silicon, and eFuse values
> exist to control whether or not this feature should be turned on. ÂHowever
> recommendations from hardware folks always say to leave it on regardless of
> eFuse values, so we don't bother checking them. ÂFor all other OPPs the LDO
> is in bypass and will follow the voltage of it's corresponding VDD_xxx.
> Reverse Body-Bias exists but we never use this in practice (for saving power
> on strongly characterised silicon).
>
> Upon a DVFS transition the notifiers handle the sequencing of voltage
> scaling and ABB LDO transitions. ÂWhen moving to a higher OPP that needs
> FBB, raise voltage first and then enable FBB. ÂWhen moving down to an OPP
> that bypasses ABB, first bypass the LDO then lower voltage.
>
> Signed-off-by: Mike Turquette <mturquette@xxxxxx>
> ---
> Âarch/arm/mach-omap2/voltage.c       | Â379 ++++++++++++++++++++++++++++-
> Âarch/arm/plat-omap/include/plat/voltage.h | Â Â6 +-
> Â2 files changed, 370 insertions(+), 15 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
> index 6ede092..644a45f 100644
> --- a/arch/arm/mach-omap2/voltage.c
> +++ b/arch/arm/mach-omap2/voltage.c
> @@ -43,6 +43,16 @@
> Â#define FAST_OPP Â Â Â Â Â Â Â 0x1
> Â#define NOMINAL_OPP Â Â Â Â Â Â0x0
>
> +/* prototypes used by ABB function pointers */
> +static int omap_abb_notify_voltage(struct notifier_block *nb,
> + Â Â Â Â Â Â Â unsigned long val, void *data);
> +
> +static int omap3_abb_configure(struct omap_abb_info *abb);
> +static int omap3_abb_set_opp(struct omap_abb_info *abb, int opp_type);
> +
> +static int omap4_abb_configure(struct omap_abb_info *abb);
> +static int omap4_abb_set_opp(struct omap_abb_info *abb, int opp_type);
> +
> Âstatic struct omap_vdd_info *vdd_info;
> Â/*
> Â* Number of scalable voltage domains.
> @@ -70,9 +80,11 @@ static struct omap_vdd_info omap3_vdd_info[] = {
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â= OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
> Â Â Â Â Â Â Â Â Â Â Â Â.done_st_shift Â= OMAP3630_ABB_LDO_TRANXDONE_ST_SHIFT,
>            Â.done_st_mask  = OMAP3630_ABB_LDO_TRANXDONE_ST_MASK,
> -            .configure   Â= NULL,
> -            .nb_handler   = NULL,
> -            .set_opp    Â= NULL,
> +            .nb   = {
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â .notifier_call = omap_abb_notify_voltage,
> + Â Â Â Â Â Â Â Â Â Â Â },
> +            .configure   Â= omap3_abb_configure,
> +            .set_opp    Â= omap3_abb_set_opp,
> Â Â Â Â Â Â Â Â},
> Â Â Â Â},
> Â Â Â Â{
> @@ -113,9 +125,11 @@ static struct omap_vdd_info omap4_vdd_info[] = {
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â= OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
> Â Â Â Â Â Â Â Â Â Â Â Â.done_st_shift Â= OMAP4430_ABB_MPU_DONE_ST_SHIFT,
>            Â.done_st_mask  = OMAP4430_ABB_MPU_DONE_ST_MASK,
> -            .configure   Â= NULL,
> -            .nb_handler   = NULL,
> -            .set_opp    Â= NULL,
> +            .nb       = {
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â .notifier_call = omap_abb_notify_voltage,
> + Â Â Â Â Â Â Â Â Â Â Â },
> +            .configure   Â= omap4_abb_configure,
> +            .set_opp    Â= omap4_abb_set_opp,
> Â Â Â Â Â Â Â Â},
> Â Â Â Â},
> Â Â Â Â{
> @@ -137,9 +151,11 @@ static struct omap_vdd_info omap4_vdd_info[] = {
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â= OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
> Â Â Â Â Â Â Â Â Â Â Â Â.done_st_shift Â= OMAP4430_ABB_IVA_DONE_ST_SHIFT,
>            Â.done_st_mask  = OMAP4430_ABB_IVA_DONE_ST_MASK,
> -            .configure   Â= NULL,
> -            .nb_handler   = NULL,
> -            .set_opp    Â= NULL,
> +            .nb       = {
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â .notifier_call = omap_abb_notify_voltage,
> + Â Â Â Â Â Â Â Â Â Â Â },
> +            .configure   Â= omap4_abb_configure,
> +            .set_opp    Â= omap4_abb_set_opp,
> Â Â Â Â Â Â Â Â},
> Â Â Â Â},
> Â Â Â Â{
> @@ -194,7 +210,7 @@ static struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
> Â Â Â Â Â Â Â Â Â Â Â ÂNOMINAL_OPP),
> Â Â Â ÂVOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV,
> Â Â Â Â Â Â Â Â Â Â Â ÂOMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16,
> - Â Â Â Â Â Â Â Â Â Â Â NOMINAL_OPP),
> + Â Â Â Â Â Â Â Â Â Â Â FAST_OPP),
> Â Â Â ÂVOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV,
> Â Â Â Â Â Â Â Â Â Â Â ÂOMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23,
> Â Â Â Â Â Â Â Â Â Â Â ÂNOMINAL_OPP),
> @@ -493,6 +509,74 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â&nom_volt_debug_fops);
> Â}
>
> +/* voltage transition notification handlers */
> +
> +/**
> + * omap_abb_notify_voltage - voltage change notifier handler for ABB
> + * @nb     : notifier block
> + * @val        Â: VOLTSCALE_PRECHANGE or VOLTSCALE_POSTCHANGE
> + * @data    : struct omap_volt_change_info for a given voltage domain
> + *
> + * Sets ABB LDO to either bypass or Forward Body-Bias whenever a voltage
> + * change notification is generated. ÂVoltages marked as FAST will result in
> + * FBB operation of ABB LDO and voltages marked as NOMINAL will bypass the
> + * LDO. ÂDoes not handle Reverse Body-Bias since there is not benefit for it
> + * on any existing silicon. ÂReturns 0 upon success, negative error code
> + * otherwise.
> + */
> +static int omap_abb_notify_voltage(struct notifier_block *nb,
> + Â Â Â Â Â Â Â unsigned long val, void *data)
> +{
> + Â Â Â struct omap_volt_change_info *v_info;
> + Â Â Â struct omap_vdd_info *vdd;
> + Â Â Â struct omap_volt_data *curr_volt_data, *target_volt_data;
> + Â Â Â int ret = 0;

No need to initialize 'ret' here. Or, as we can see below, you might
not need 'ret' at all.

> +
> + Â Â Â if (!nb || IS_ERR(nb) || !data || IS_ERR(data)) {
> + Â Â Â Â Â Â Â pr_warning("%s: invalid data specified\n", __func__);
> + Â Â Â Â Â Â Â ret = -EINVAL;
> + Â Â Â Â Â Â Â goto out;

Why set 'ret' and jump to 'out' just to return 'ret'? You can already
return -EINVAL now.

> + Â Â Â }
> +
> + Â Â Â v_info = (struct omap_volt_change_info *)data;
> + Â Â Â vdd = v_info->vdd;
> +
> + Â Â Â /* get the voltdata structures for the current & target voltage */
> + Â Â Â target_volt_data = omap_voltage_get_voltdata(&vdd->voltdm,
> + Â Â Â Â Â Â Â Â Â Â Â v_info->target_volt);
> + Â Â Â curr_volt_data = omap_voltage_get_voltdata(&vdd->voltdm,
> + Â Â Â Â Â Â Â Â Â Â Â v_info->curr_volt);
> +
> + Â Â Â /* nothing to do here */
> + Â Â Â if (target_volt_data->abb_opp == curr_volt_data->abb_opp)
> + Â Â Â Â Â Â Â goto out;

No need to jump to 'out' just to return 0. Why not return 0 now?

> +
> + Â Â Â /*
> + Â Â Â Â* When the VDD drops from a voltage requiring the ABB LDO to be in
> + Â Â Â Â* FBB mode to a voltage requiring bypass mode, we must bypass the LDO
> + Â Â Â Â* before the voltage transition.
> + Â Â Â Â*/
> + Â Â Â if (val == VOLTSCALE_PRECHANGE &&
> + Â Â Â Â Â Â Â Â Â Â Â target_volt_data->abb_opp == NOMINAL_OPP) {
> + Â Â Â Â Â Â Â ret = vdd->abb.set_opp(&vdd->abb, NOMINAL_OPP);

return vdd->abb.set_opp(&vdd->abb, NOMINAL_OPP);

> +
> + Â Â Â /*
> + Â Â Â Â* When moving from a voltage requiring the ABB LDO to be bypassed to
> + Â Â Â Â* a voltage requiring FBB mode, we must change the LDO operation
> + Â Â Â Â* after the voltage transition.
> + Â Â Â Â*/
> + Â Â Â } else if (val == VOLTSCALE_POSTCHANGE &&
> + Â Â Â Â Â Â Â Â Â Â Â target_volt_data->abb_opp == FAST_OPP) {
> + Â Â Â Â Â Â Â ret = vdd->abb.set_opp(&vdd->abb, FAST_OPP);

return vdd->abb.set_opp(&vdd->abb, FAST_OPP);

> +
> + Â Â Â /* invalid combination, bail out */
> + Â Â Â } else
> + Â Â Â Â Â Â Â ret = -EINVAL;

return -EINVAL;

> +
> +out:
> + Â Â Â return ret;

You can get rid of this last part.

> +}
> +
> Â/* Voltage scale and accessory APIs */
> Âstatic int _pre_volt_scale(struct omap_vdd_info *vdd,
> Â Â Â Â Â Â Â Âunsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
> @@ -717,6 +801,142 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
> Â Â Â Âreturn 0;
> Â}
>
> +/**
> + * omap3_abb_set_opp - program ABB LDO upon a voltage transition
> + *
> + * @abb        Â: ABB instance being programmed
> + * @opp_type  : flag for NOMINAL or FAST OPP
> + */
> +static int omap3_abb_set_opp(struct omap_abb_info *abb, int opp_type)
> +{
> + Â Â Â int ret = 0;

You don't need 'ret'.

> + Â Â Â int timeout;
> +
> + Â Â Â /* program for NOMINAL OPP or FAST OPP */
> + Â Â Â omap2_prm_rmw_mod_reg_bits(OMAP3630_OPP_SEL_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (opp_type << OMAP3630_OPP_SEL_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP3430_GR_MOD, abb->setup_offs);
> +
> + Â Â Â /* clear ABB ldo interrupt status */
> + Â Â Â omap2_prm_clear_mod_reg_bits(abb->done_st_mask, OCP_MOD,
> + Â Â Â Â Â Â Â Â Â Â Â abb->irqstatus_mpu_offs);
> +
> + Â Â Â /* enable ABB LDO OPP change */
> + Â Â Â omap2_prm_set_mod_reg_bits(OMAP3630_OPP_CHANGE_MASK, OMAP3430_GR_MOD,
> + Â Â Â Â Â Â Â Â Â Â Â abb->setup_offs);
> +
> + Â Â Â timeout = 0;
> +
> + Â Â Â /* wait until OPP change completes */
> + Â Â Â while ((timeout < ABB_TRANXDONE_TIMEOUT) &&
> + Â Â Â Â Â Â Â Â Â Â Â (!(omap2_prm_read_mod_reg(OCP_MOD,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â abb->irqstatus_mpu_offs) &
> + Â Â Â Â Â Â Â Â Â Â Â Â Âabb->done_st_mask))) {
> + Â Â Â Â Â Â Â udelay(1);
> + Â Â Â Â Â Â Â timeout++;
> + Â Â Â }
> +
> + Â Â Â if (timeout == ABB_TRANXDONE_TIMEOUT)
> + Â Â Â Â Â Â Â pr_warning("%s: TRANXDONE timed out waiting for OPP change\n",
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â __func__);
> +
> + Â Â Â timeout = 0;
> +
> + Â Â Â /* Clear all pending TRANXDONE interrupts/status */
> + Â Â Â while (timeout < ABB_TRANXDONE_TIMEOUT) {
> + Â Â Â Â Â Â Â omap2_prm_write_mod_reg((1 << abb->done_st_shift), OCP_MOD,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â abb->irqstatus_mpu_offs);
> +
> + Â Â Â Â Â Â Â if (!(omap2_prm_read_mod_reg(OCP_MOD, abb->irqstatus_mpu_offs)
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â & abb->done_st_mask))
> + Â Â Â Â Â Â Â Â Â Â Â break;
> +
> + Â Â Â Â Â Â Â udelay(1);
> + Â Â Â Â Â Â Â timeout++;
> + Â Â Â }
> +
> + Â Â Â if (timeout == ABB_TRANXDONE_TIMEOUT) {
> + Â Â Â Â Â Â Â pr_warning("%s: TRANXDONE timed out trying to clear status\n",
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â __func__);
> + Â Â Â Â Â Â Â ret = -EBUSY;

return -EBUSY here.

> + Â Â Â }
> +
> + Â Â Â return ret;

And return 0 here.

> +}
> +
> +/**
> + * omap4_abb_set_opp - program ABB LDO upon a voltage transition
> + *
> + * @abb        Â: ABB instance being programmed
> + * @opp_type  : flag for NOMINAL or FAST OPP
> + */
> +static int omap4_abb_set_opp(struct omap_abb_info *abb, int opp_type)
> +{
> + Â Â Â int ret = 0;

Again you don't need 'ret'.

> + Â Â Â int timeout;
> +
> + Â Â Â /* program for NOMINAL OPP or FAST OPP */
> + Â Â Â omap4_prminst_rmw_inst_reg_bits(OMAP4430_OPP_SEL_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (opp_type << OMAP4430_OPP_SEL_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â abb->ctrl_offs);
> +
> + Â Â Â /* clear ABB ldo interrupt status */
> + Â Â Â omap4_prminst_rmw_inst_reg_bits(abb->done_st_mask,
> + Â Â Â Â Â Â Â Â Â Â Â (0x0 << abb->done_st_shift), OMAP4430_PRM_PARTITION,
> + Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_DEVICE_INST, abb->ctrl_offs);
> +
> + Â Â Â /* enable ABB LDO OPP change */
> + Â Â Â omap4_prminst_rmw_inst_reg_bits(OMAP4430_OPP_CHANGE_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (0x1 << OMAP4430_OPP_CHANGE_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â abb->ctrl_offs);
> +
> + Â Â Â timeout = 0;
> +
> + Â Â Â /* wait until OPP change completes */
> + Â Â Â while ((timeout < ABB_TRANXDONE_TIMEOUT) &&
> + Â Â Â Â Â Â Â Â Â Â Â (!(omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ÂOMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âabb->irqstatus_mpu_offs)
> + Â Â Â Â Â Â Â Â Â Â Â Â Â& abb->done_st_mask))) {
> + Â Â Â Â Â Â Â udelay(1);
> + Â Â Â Â Â Â Â timeout++;
> + Â Â Â }
> +
> + Â Â Â if (timeout == ABB_TRANXDONE_TIMEOUT)
> + Â Â Â Â Â Â Â pr_warning("%s: TRANXDONE timed out waiting for OPP change\n",
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â __func__);
> +
> + Â Â Â timeout = 0;
> +
> + Â Â Â /* Clear all pending TRANXDONE interrupts/status */
> + Â Â Â while (timeout < ABB_TRANXDONE_TIMEOUT) {
> + Â Â Â Â Â Â Â omap4_prminst_write_inst_reg((1 << abb->done_st_shift),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_PARTITION,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â abb->irqstatus_mpu_offs);
> +
> + Â Â Â Â Â Â Â if (!(omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â abb->irqstatus_mpu_offs)
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â & abb->done_st_mask)) {
> + Â Â Â Â Â Â Â Â Â Â Â break;
> +
> + Â Â Â Â Â Â Â Â Â Â Â udelay(1);
> + Â Â Â Â Â Â Â Â Â Â Â timeout++;
> + Â Â Â Â Â Â Â }
> + Â Â Â }
> +
> + Â Â Â if (timeout == ABB_TRANXDONE_TIMEOUT) {
> + Â Â Â Â Â Â Â pr_warning("%s: TRANXDONE timed out trying to clear status\n",
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â __func__);
> + Â Â Â Â Â Â Â ret = -EBUSY;

return -EBUSY.

> + Â Â Â }
> +
> + Â Â Â return ret;

return 0

> +}
> +
> Â/* OMAP3 specific voltage init functions */
>
> Â/*
> @@ -789,6 +1009,64 @@ static void __init omap3_vc_init(struct omap_vdd_info *vdd)
> Â Â Â Âis_initialized = true;
> Â}
>
> +/**
> + * omap3_abb_configure - per-VDD configuration of ABB
> + *
> + * @abb        Â: abb instance being initialized
> + */
> +static int omap3_abb_configure(struct omap_abb_info *abb)
> +{
> + Â Â Â int ret = 0;

Once more you don't need 'ret'.

> + Â Â Â u32 sr2_wt_cnt_val;
> + Â Â Â struct clk *sys_ck;
> + Â Â Â struct omap_vdd_info *vdd;
> +
> + Â Â Â if (!abb || IS_ERR(abb)) {
> + Â Â Â Â Â Â Â Â Â Â Â pr_warning("%s: invalid abb\n", __func__);
> + Â Â Â Â Â Â Â Â Â Â Â ret = -EINVAL;
> + Â Â Â Â Â Â Â Â Â Â Â goto out;

Why set 'ret', jump to 'out' just to return 'ret'? Return -EINVAL now.

> + Â Â Â }
> +
> + Â Â Â sys_ck = clk_get(NULL, "sys_ck");
> + Â Â Â if (IS_ERR(sys_ck)) {
> + Â Â Â Â Â Â Â pr_warning("%s: unable to fetch SYS_CK\n", __func__);
> + Â Â Â Â Â Â Â ret = -ENODEV;

return -ENODEV

> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â vdd = container_of(abb, struct omap_vdd_info, abb);
> +
> + Â Â Â /* LDO settling time */
> + Â Â Â sr2_wt_cnt_val = clk_get_rate(sys_ck);
> + Â Â Â sr2_wt_cnt_val = sr2_wt_cnt_val / 1000000 / 16;
> +
> + Â Â Â omap2_prm_rmw_mod_reg_bits(OMAP3630_SR2_WTCNT_VALUE_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (sr2_wt_cnt_val << OMAP3630_SR2_WTCNT_VALUE_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP3430_GR_MOD, abb->setup_offs);
> +
> + Â Â Â /* allow FBB operation */
> + Â Â Â omap2_prm_set_mod_reg_bits(OMAP3630_ACTIVE_FBB_SEL_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â OMAP3430_GR_MOD, abb->setup_offs);
> +
> + Â Â Â /* do not allow ACTIVE RBB operation */
> + Â Â Â omap2_prm_set_mod_reg_bits(OMAP3630_ACTIVE_RBB_SEL_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â OMAP3430_GR_MOD, abb->setup_offs);
> +
> + Â Â Â /* do not allow SLEEP RBB operation */
> + Â Â Â omap2_prm_set_mod_reg_bits(OMAP3630_SLEEP_RBB_SEL_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â OMAP3430_GR_MOD, abb->setup_offs);
> +
> + Â Â Â /* enable ABB LDO */
> + Â Â Â omap2_prm_set_mod_reg_bits(OMAP3630_SR2EN_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â OMAP3430_GR_MOD, abb->ctrl_offs);
> +
> + Â Â Â /* register the notifier handler */
> + Â Â Â omap_voltage_register_notifier(vdd, &abb->nb);
> +
> +out:
> + Â Â Â return ret;

return 0

> +}
> +
> Â/* Sets up all the VDD related info for OMAP3 */
> Âstatic int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
> Â{
> @@ -824,6 +1102,9 @@ static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
> Â Â Â Â Â Â Â Âvdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA0_MASK;
> Â Â Â Â Â Â Â Âvdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT;
> Â Â Â Â Â Â Â Âvdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK;
> +
> + Â Â Â Â Â Â Â /* configure ABB */
> + Â Â Â Â Â Â Â vdd->abb.configure(&vdd->abb);
> Â Â Â Â} else if (!strcmp(vdd->voltdm.name, "core")) {
> Â Â Â Â Â Â Â Âif (cpu_is_omap3630())
> Â Â Â Â Â Â Â Â Â Â Â Âvdd->volt_data = omap36xx_vddcore_volt_data;
> @@ -975,6 +1256,73 @@ static void __init omap4_vc_init(struct omap_vdd_info *vdd)
> Â Â Â Âis_initialized = true;
> Â}
>
> +/**
> + * omap4_abb_configure - per-VDD configuration of ABB
> + *
> + * @abb        Â: abb instance being initialized
> + */
> +static int omap4_abb_configure(struct omap_abb_info *abb)
> +{
> + Â Â Â int ret = 0;

Get rid of 'ret'.

> + Â Â Â u32 sr2_wt_cnt_val;
> + Â Â Â struct clk *sys_ck;
> + Â Â Â struct omap_vdd_info *vdd;
> +
> + Â Â Â if (!abb || IS_ERR(abb)) {
> + Â Â Â Â Â Â Â Â Â Â Â pr_warning("%s: invalid abb\n", __func__);
> + Â Â Â Â Â Â Â Â Â Â Â ret = -EINVAL;

return -EINVAL

> + Â Â Â Â Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â sys_ck = clk_get(NULL, "sys_clkin_ck");
> + Â Â Â if (IS_ERR(sys_ck)) {
> + Â Â Â Â Â Â Â pr_warning("%s: unable to fetch SYS_CK", __func__);
> + Â Â Â Â Â Â Â ret = -ENODEV;

return -ENODEV

> + Â Â Â Â Â Â Â goto out;
> + Â Â Â }
> +
> + Â Â Â vdd = container_of(abb, struct omap_vdd_info, abb);
> +
> + Â Â Â /* LDO settling time */
> + Â Â Â sr2_wt_cnt_val = clk_get_rate(sys_ck);
> + Â Â Â sr2_wt_cnt_val = sr2_wt_cnt_val / 1000000 / 16;
> +
> + Â Â Â omap4_prminst_rmw_inst_reg_bits(OMAP4430_SR2_WTCNT_VALUE_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (sr2_wt_cnt_val << OMAP4430_SR2_WTCNT_VALUE_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â abb->setup_offs);
> +
> + Â Â Â /* allow FBB operation */
> + Â Â Â omap4_prminst_rmw_inst_reg_bits(OMAP4430_ACTIVE_FBB_SEL_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (1 << OMAP4430_ACTIVE_FBB_SEL_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â abb->setup_offs);
> +
> + Â Â Â /* do not allow ACTIVE RBB operation */
> + Â Â Â omap4_prminst_rmw_inst_reg_bits(OMAP4430_ACTIVE_RBB_SEL_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (0 << OMAP4430_ACTIVE_RBB_SEL_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â abb->setup_offs);
> +
> + Â Â Â /* do not allow SLEEP RBB operation */
> + Â Â Â omap4_prminst_rmw_inst_reg_bits(OMAP4430_SLEEP_RBB_SEL_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (0 << OMAP4430_SLEEP_RBB_SEL_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â abb->setup_offs);
> +
> + Â Â Â /* enable ABB LDO */
> + Â Â Â omap4_prminst_rmw_inst_reg_bits(OMAP4430_SR2EN_MASK,
> + Â Â Â Â Â Â Â Â Â Â Â (1 << OMAP4430_SR2EN_SHIFT),
> + Â Â Â Â Â Â Â Â Â Â Â OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> + Â Â Â Â Â Â Â Â Â Â Â abb->setup_offs);
> +
> + Â Â Â /* register the notifier handler */
> + Â Â Â omap_voltage_register_notifier(vdd, &abb->nb);
> +
> +out:
> + Â Â Â return ret;

return 0.

Regards,

David Cohen

> +}
> +
> Â/* Sets up all the VDD related info for OMAP4 */
> Âstatic int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
> Â{
> @@ -983,8 +1331,8 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
>
> Â Â Â Âif (!vdd->pmic_info) {
> Â Â Â Â Â Â Â Âpr_err("%s: PMIC info requried to configure vdd_%s not"
> - Â Â Â Â Â Â Â Â Â Â Â "populated.Hence cannot initialize vdd_%s\n",
> - Â Â Â Â Â Â Â Â Â Â Â __func__, vdd->voltdm.name, vdd->voltdm.name);
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â "populated.Hence cannot initialize vdd_%s\n",
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â __func__, vdd->voltdm.name, vdd->voltdm.name);
> Â Â Â Â Â Â Â Âreturn -EINVAL;
> Â Â Â Â}
>
> @@ -1005,6 +1353,9 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
> Â Â Â Â Â Â Â Âvdd->vc_reg.voltsetup_reg =
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ÂOMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET;
> Â Â Â Â Â Â Â Âvdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET;
> +
> + Â Â Â Â Â Â Â /* configure ABB */
> + Â Â Â Â Â Â Â vdd->abb.configure(&vdd->abb);
> Â Â Â Â} else if (!strcmp(vdd->voltdm.name, "core")) {
> Â Â Â Â Â Â Â Âvdd->volt_data = omap44xx_vdd_core_volt_data;
> Â Â Â Â Â Â Â Âvdd->vp_reg.tranxdone_status =
> @@ -1032,6 +1383,9 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
> Â Â Â Â Â Â Â Âvdd->vc_reg.voltsetup_reg =
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ÂOMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET;
> Â Â Â Â Â Â Â Âvdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
> +
> + Â Â Â Â Â Â Â /* configure ABB */
> + Â Â Â Â Â Â Â vdd->abb.configure(&vdd->abb);
> Â Â Â Â} else {
> Â Â Â Â Â Â Â Âpr_warning("%s: vdd_%s does not exisit in OMAP4\n",
> Â Â Â Â Â Â Â Â Â Â Â Â__func__, vdd->voltdm.name);
> @@ -1299,6 +1653,7 @@ int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
>
> Â Â Â Â/* load notifier chain data */
> Â Â Â Âv_info.target_volt = target_volt;
> + Â Â Â v_info.curr_volt = vdd->curr_volt;
> Â Â Â Âv_info.vdd = vdd;
>
> Â Â Â Âsrcu_notifier_call_chain(&vdd->volt_change_notify_chain,
> diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
> index af790bf..07997f7 100644
> --- a/arch/arm/plat-omap/include/plat/voltage.h
> +++ b/arch/arm/plat-omap/include/plat/voltage.h
> @@ -235,8 +235,8 @@ struct omap_vdd_dep_info {
> Â* @irqstatus_mpu_offs : PRM_IRQSTATUS_MPU* register offset
> Â* @done_st_shift   Â: ABB_vdd_DONE_ST shift
> Â* @done_st_mask    : ABB_vdd_DONE_ST bit mask
> + * @nb         : voltage transition notifier block
> Â* @configure     Â: boot-time configuration
> - * @nb_handler     : voltage transition notification handler
> Â* @set_opp      Â: transition function called from nb_handler
> Â*/
> Âstruct omap_abb_info {
> @@ -245,9 +245,8 @@ struct omap_abb_info {
> Â Â Â Âu8 irqstatus_mpu_offs;
> Â Â Â Âu8 done_st_shift;
> Â Â Â Âu32 done_st_mask;
> + Â Â Â struct notifier_block nb;
> Â Â Â Âint (*configure) (struct omap_abb_info *abb);
> - Â Â Â int (*nb_handler) (struct notifier_block *nb, unsigned long val,
> - Â Â Â Â Â Â Â Â Â Â Â void *data);
> Â Â Â Âint (*set_opp) (struct omap_abb_info *abb, int opp_type);
> Â};
>
> @@ -302,6 +301,7 @@ struct omap_vdd_info {
> Â*/
> Âstruct omap_volt_change_info {
> Â Â Â Âunsigned long target_volt;
> + Â Â Â unsigned long curr_volt;
> Â Â Â Âstruct omap_vdd_info *vdd;
> Â};
>
> --
> 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
>
ÿô.nlj·Ÿ®‰­†+%ŠË±é¥Šwÿº{.nlj·¥Š{±þ‰š§ø¡Ü}©ž²ÆzÚj:+v‰¨þø®w¥þŠàÞ¨è&¢)ß«a¶Úÿûz¹ÞúŽŠÝjÿŠwèf



[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux