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 <nm@xxxxxx> > 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 <nm@xxxxxx> > --- > .../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-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html