On 01/23/2014 10:20 AM, Nishanth Menon wrote:
> On 12:29-20140123, Mark Brown wrote:
>> On Wed, Jan 22, 2014 at 04:25:23PM -0600, Nishanth Menon wrote:
>>
>>> How about something like the following? If this is acceptable, I can do
>>> a complete round of retest and ensure everything is functional on all
>>> platforms and post it as a formal patch:
>>
>> Looks OK from a quick scan.  It seems nothing in mainline is using the
>> -v2 binding so it's probably OK to delete it but if it's not too much
>> bother it might be better to keep it since I expect some downstream
>> trees might've picked that up already.
> True - how about the following (formal post pending comprehensive
> testing and your feedback on approach):
> 
> From 35b0c999f7ef94bf92acc17e1086af22b187943a Mon Sep 17 00:00:00 2001
> From: Nishanth Menon <n...@ti.com>
> Date: Thu, 23 Jan 2014 10:00:22 -0600
> Subject: [PATCH V3] regulator: ti-abb: Add support for interleaved LDO 
> registers
> 
> Certain platforms such as DRA7 have quirky memory maps such as:
> PRM_ABBLDO_DSPEVE_CTRL      0x4ae07e20
> PRM_ABBLDO_IVA_CTRL 0x4ae07e24
> other-registers
> PRM_ABBLDO_DSPEVE_SETUP     0x4ae07e30
> PRM_ABBLDO_IVA_SETUP        0x4ae07e34
> 
> These need the address range allocation to be either not reserved OR unique
> allocation per register instance or use something like syscon based
> solution.
> 
> By going with unique allocation per register, we are able to now have a
> single compatible driver for all instances on all platforms which use
> the IP block.
> 
> So, introduce a new "ti,abb-v3" compatible to allow for definitions
> where explicit register definitions are provided, while maintaining
> backward compatibility of older predefined register offsets provided
> by "ti-abb-v1" and "ti-abb-v2".
> 
> Signed-off-by: Nishanth Menon <n...@ti.com>
> ---
>  .../bindings/regulator/ti-abb-regulator.txt        |    6 +-
>  drivers/regulator/ti-abb-regulator.c               |   91 
> +++++++++++++-------
>  2 files changed, 67 insertions(+), 30 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt 
> b/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt
> index 2e57a33..0d2dc26 100644
> --- a/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt
> +++ b/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt
> @@ -4,10 +4,14 @@ Required Properties:
>  - compatible: Should be one of:
>    - "ti,abb-v1" for older SoCs like OMAP3
>    - "ti,abb-v2" for newer SoCs like OMAP4, OMAP5
> +  - "ti,abb-v3" for a generic definition where setup and control registers 
> are
> +     provided (example: DRA7)
>  - reg: Address and length of the register set for the device. It contains
>    the information of registers in the same order as described by reg-names
>  - reg-names: Should contain the reg names
> -  - "base-address"   - contains base address of ABB module
> +  - "base-address"   - contains base address of ABB module 
> (ti,abb-v1,ti,abb-v2)
> +  - "control-address"        - contains base address of ABB module 
> (ti,abb-v3)
> +  - "setup-address"  - contains base address of ABB module (ti,abb-v3)
>    - "int-address"    - contains address of interrupt register for ABB module
>    (also see Optional properties)
>  - #address-cell: should be 0
> diff --git a/drivers/regulator/ti-abb-regulator.c 
> b/drivers/regulator/ti-abb-regulator.c
> index b187b6b..134c481 100644
> --- a/drivers/regulator/ti-abb-regulator.c
> +++ b/drivers/regulator/ti-abb-regulator.c
> @@ -54,8 +54,8 @@ struct ti_abb_info {
>  
>  /**
>   * struct ti_abb_reg - Register description for ABB block
> - * @setup_reg:                       setup register offset from base
> - * @control_reg:             control register offset from base
> + * @setup_off:                       setup register offset from base
> + * @control_off:             setup register offset from base
>   * @sr2_wtcnt_value_mask:    setup register- sr2_wtcnt_value mask
>   * @fbb_sel_mask:            setup register- FBB sel mask
>   * @rbb_sel_mask:            setup register- RBB sel mask
> @@ -64,8 +64,8 @@ struct ti_abb_info {
>   * @opp_sel_mask:            control register - mask for mode to operate
>   */
>  struct ti_abb_reg {
> -     u32 setup_reg;
> -     u32 control_reg;
> +     u32 setup_off;
> +     u32 control_off;
>  
>       /* Setup register fields */
>       u32 sr2_wtcnt_value_mask;
> @@ -83,6 +83,8 @@ struct ti_abb_reg {
>   * @rdesc:                   regulator descriptor
>   * @clk:                     clock(usually sysclk) supplying ABB block
>   * @base:                    base address of ABB block
> + * @setup_reg:                       setup register of ABB block
> + * @control_reg:             setup register of ABB block
>   * @int_base:                        interrupt register base address
>   * @efuse_base:                      (optional) efuse base address for ABB 
> modes
>   * @ldo_base:                        (optional) LDOVBB vset override base 
> address
> @@ -99,6 +101,8 @@ struct ti_abb {
>       struct regulator_desc rdesc;
>       struct clk *clk;
>       void __iomem *base;
> +     void __iomem *setup_reg;
> +     void __iomem *control_reg;
>       void __iomem *int_base;
>       void __iomem *efuse_base;
>       void __iomem *ldo_base;
> @@ -118,20 +122,18 @@ struct ti_abb {
>   * ti_abb_rmw() - handy wrapper to set specific register bits
>   * @mask:    mask for register field
>   * @value:   value shifted to mask location and written
> - * @offset:  offset of register
> - * @base:    base address
> + * @reg:     register address
>   *
>   * Return: final register value (may be unused)
>   */
> -static inline u32 ti_abb_rmw(u32 mask, u32 value, u32 offset,
> -                          void __iomem *base)
> +static inline u32 ti_abb_rmw(u32 mask, u32 value, void __iomem *reg)
>  {
>       u32 val;
>  
> -     val = readl(base + offset);
> +     val = readl(reg);
>       val &= ~mask;
>       val |= (value << __ffs(mask)) & mask;
> -     writel(val, base + offset);
> +     writel(val, reg);
>  
>       return val;
>  }
> @@ -263,21 +265,20 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, 
> struct ti_abb *abb,
>       if (ret)
>               goto out;
>  
> -     ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, regs->setup_reg,
> -                abb->base);
> +     ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0,
> +                abb->setup_reg);
>  
>       switch (info->opp_sel) {
>       case TI_ABB_SLOW_OPP:
> -             ti_abb_rmw(regs->rbb_sel_mask, 1, regs->setup_reg, abb->base);
> +             ti_abb_rmw(regs->rbb_sel_mask, 1, abb->setup_reg);
>               break;
>       case TI_ABB_FAST_OPP:
> -             ti_abb_rmw(regs->fbb_sel_mask, 1, regs->setup_reg, abb->base);
> +             ti_abb_rmw(regs->fbb_sel_mask, 1, abb->setup_reg);
>               break;
>       }
>  
>       /* program next state of ABB ldo */
> -     ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, regs->control_reg,
> -                abb->base);
> +     ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, abb->control_reg);
>  
>       /*
>        * program LDO VBB vset override if needed for !bypass mode
> @@ -288,7 +289,7 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, 
> struct ti_abb *abb,
>               ti_abb_program_ldovbb(dev, abb, info);
>  
>       /* Initiate ABB ldo change */
> -     ti_abb_rmw(regs->opp_change_mask, 1, regs->control_reg, abb->base);
> +     ti_abb_rmw(regs->opp_change_mask, 1, abb->control_reg);
>  
>       /* Wait for ABB LDO to complete transition to new Bias setting */
>       ret = ti_abb_wait_txdone(dev, abb);
> @@ -490,8 +491,8 @@ static int ti_abb_init_timings(struct device *dev, struct 
> ti_abb *abb)
>       dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__,
>               clk_get_rate(abb->clk), sr2_wt_cnt_val);
>  
> -     ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, regs->setup_reg,
> -                abb->base);
> +     ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val,
> +                abb->setup_reg);
>  
>       return 0;
>  }
> @@ -648,8 +649,8 @@ static struct regulator_ops ti_abb_reg_ops = {
>  /* Default ABB block offsets, IF this changes in future, create new one */
>  static const struct ti_abb_reg abb_regs_v1 = {
>       /* WARNING: registers are wrongly documented in TRM */
> -     .setup_reg              = 0x04,
> -     .control_reg            = 0x00,
> +     .setup_off              = 0x04,
> +     .control_off            = 0x00,
>  
>       .sr2_wtcnt_value_mask   = (0xff << 8),
>       .fbb_sel_mask           = (0x01 << 2),
> @@ -661,8 +662,8 @@ static const struct ti_abb_reg abb_regs_v1 = {
>  };
>  
>  static const struct ti_abb_reg abb_regs_v2 = {
> -     .setup_reg              = 0x00,
> -     .control_reg            = 0x04,
> +     .setup_off              = 0x00,
> +     .control_off            = 0x04,
>  
>       .sr2_wtcnt_value_mask   = (0xff << 8),
>       .fbb_sel_mask           = (0x01 << 2),
> @@ -673,9 +674,20 @@ static const struct ti_abb_reg abb_regs_v2 = {
>       .opp_sel_mask           = (0x03 << 0),
>  };
>  
> +static const struct ti_abb_reg abb_regs_generic = {
> +     .sr2_wtcnt_value_mask   = (0xff << 8),
> +     .fbb_sel_mask           = (0x01 << 2),
> +     .rbb_sel_mask           = (0x01 << 1),
> +     .sr2_en_mask            = (0x01 << 0),
> +
> +     .opp_change_mask        = (0x01 << 2),
> +     .opp_sel_mask           = (0x03 << 0),
> +};
> +
>  static const struct of_device_id ti_abb_of_match[] = {
>       {.compatible = "ti,abb-v1", .data = &abb_regs_v1},
>       {.compatible = "ti,abb-v2", .data = &abb_regs_v2},
> +     {.compatible = "ti,abb-v3", .data = &abb_regs_generic},
>       { },
>  };
>  
> @@ -719,14 +731,35 @@ static int ti_abb_probe(struct platform_device *pdev)
>       abb = devm_kzalloc(dev, sizeof(struct ti_abb), GFP_KERNEL);
>       if (!abb)
>               return -ENOMEM;
> +     abb->regs = devm_kzalloc(dev, sizeof(struct ti_abb_reg), GFP_KERNEL);
> +     if (!abb->regs)
> +             return -ENOMEM;
>       abb->regs = match->data;
>  
>       /* Map ABB resources */
> -     pname = "base-address";
> -     res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
> -     abb->base = devm_ioremap_resource(dev, res);
> -     if (IS_ERR(abb->base))
> -             return PTR_ERR(abb->base);
> +     if (!abb->regs->setup_off && !abb->regs->control_off) {
Sigh.. the check was supposed to be:
if (abb->regs->setup_off || abb->regs->control_off) {

Darned.. forgot to commit! Grr... anyways.. still looking for feedback
for the remaining.
> +             pname = "base-address";
> +             res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
> +             abb->base = devm_ioremap_resource(dev, res);
> +             if (IS_ERR(abb->base))
> +                     return PTR_ERR(abb->base);
> +
> +             abb->setup_reg = abb->base + abb->regs->setup_off;
> +             abb->control_reg = abb->base + abb->regs->control_off;
> +
> +     } else {
> +             pname = "control-address";
> +             res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
> +             abb->control_reg = devm_ioremap_resource(dev, res);
> +             if (IS_ERR(abb->control_reg))
> +                     return PTR_ERR(abb->control_reg);
> +
> +             pname = "setup-address";
> +             res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
> +             abb->setup_reg = devm_ioremap_resource(dev, res);
> +             if (IS_ERR(abb->setup_reg))
> +                     return PTR_ERR(abb->setup_reg);
> +     }
>  
>       pname = "int-address";
>       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
> @@ -860,7 +893,7 @@ skip_opt:
>       platform_set_drvdata(pdev, rdev);
>  
>       /* Enable the ldo if not already done by bootloader */
> -     ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base);
> +     ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->setup_reg);
>  
>       return 0;
>  }
> 


-- 
Regards,
Nishanth Menon
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to