aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt6
-rw-r--r--drivers/regulator/ti-abb-regulator.c86
2 files changed, 62 insertions, 30 deletions
diff --git a/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt b/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt
index 2e57a33e9029..c58db75f959e 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:
4- compatible: Should be one of: 4- compatible: Should be one of:
5 - "ti,abb-v1" for older SoCs like OMAP3 5 - "ti,abb-v1" for older SoCs like OMAP3
6 - "ti,abb-v2" for newer SoCs like OMAP4, OMAP5 6 - "ti,abb-v2" for newer SoCs like OMAP4, OMAP5
7 - "ti,abb-v3" for a generic definition where setup and control registers are
8 provided (example: DRA7)
7- reg: Address and length of the register set for the device. It contains 9- reg: Address and length of the register set for the device. It contains
8 the information of registers in the same order as described by reg-names 10 the information of registers in the same order as described by reg-names
9- reg-names: Should contain the reg names 11- reg-names: Should contain the reg names
10 - "base-address" - contains base address of ABB module 12 - "base-address" - contains base address of ABB module (ti,abb-v1,ti,abb-v2)
13 - "control-address" - contains control register address of ABB module (ti,abb-v3)
14 - "setup-address" - contains setup register address of ABB module (ti,abb-v3)
11 - "int-address" - contains address of interrupt register for ABB module 15 - "int-address" - contains address of interrupt register for ABB module
12 (also see Optional properties) 16 (also see Optional properties)
13- #address-cell: should be 0 17- #address-cell: should be 0
diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c
index b187b6bba7ad..a97d0c5e1097 100644
--- a/drivers/regulator/ti-abb-regulator.c
+++ b/drivers/regulator/ti-abb-regulator.c
@@ -54,8 +54,8 @@ struct ti_abb_info {
54 54
55/** 55/**
56 * struct ti_abb_reg - Register description for ABB block 56 * struct ti_abb_reg - Register description for ABB block
57 * @setup_reg: setup register offset from base 57 * @setup_off: setup register offset from base
58 * @control_reg: control register offset from base 58 * @control_off: control register offset from base
59 * @sr2_wtcnt_value_mask: setup register- sr2_wtcnt_value mask 59 * @sr2_wtcnt_value_mask: setup register- sr2_wtcnt_value mask
60 * @fbb_sel_mask: setup register- FBB sel mask 60 * @fbb_sel_mask: setup register- FBB sel mask
61 * @rbb_sel_mask: setup register- RBB sel mask 61 * @rbb_sel_mask: setup register- RBB sel mask
@@ -64,8 +64,8 @@ struct ti_abb_info {
64 * @opp_sel_mask: control register - mask for mode to operate 64 * @opp_sel_mask: control register - mask for mode to operate
65 */ 65 */
66struct ti_abb_reg { 66struct ti_abb_reg {
67 u32 setup_reg; 67 u32 setup_off;
68 u32 control_reg; 68 u32 control_off;
69 69
70 /* Setup register fields */ 70 /* Setup register fields */
71 u32 sr2_wtcnt_value_mask; 71 u32 sr2_wtcnt_value_mask;
@@ -83,6 +83,8 @@ struct ti_abb_reg {
83 * @rdesc: regulator descriptor 83 * @rdesc: regulator descriptor
84 * @clk: clock(usually sysclk) supplying ABB block 84 * @clk: clock(usually sysclk) supplying ABB block
85 * @base: base address of ABB block 85 * @base: base address of ABB block
86 * @setup_reg: setup register of ABB block
87 * @control_reg: control register of ABB block
86 * @int_base: interrupt register base address 88 * @int_base: interrupt register base address
87 * @efuse_base: (optional) efuse base address for ABB modes 89 * @efuse_base: (optional) efuse base address for ABB modes
88 * @ldo_base: (optional) LDOVBB vset override base address 90 * @ldo_base: (optional) LDOVBB vset override base address
@@ -99,6 +101,8 @@ struct ti_abb {
99 struct regulator_desc rdesc; 101 struct regulator_desc rdesc;
100 struct clk *clk; 102 struct clk *clk;
101 void __iomem *base; 103 void __iomem *base;
104 void __iomem *setup_reg;
105 void __iomem *control_reg;
102 void __iomem *int_base; 106 void __iomem *int_base;
103 void __iomem *efuse_base; 107 void __iomem *efuse_base;
104 void __iomem *ldo_base; 108 void __iomem *ldo_base;
@@ -118,20 +122,18 @@ struct ti_abb {
118 * ti_abb_rmw() - handy wrapper to set specific register bits 122 * ti_abb_rmw() - handy wrapper to set specific register bits
119 * @mask: mask for register field 123 * @mask: mask for register field
120 * @value: value shifted to mask location and written 124 * @value: value shifted to mask location and written
121 * @offset: offset of register 125 * @reg: register address
122 * @base: base address
123 * 126 *
124 * Return: final register value (may be unused) 127 * Return: final register value (may be unused)
125 */ 128 */
126static inline u32 ti_abb_rmw(u32 mask, u32 value, u32 offset, 129static inline u32 ti_abb_rmw(u32 mask, u32 value, void __iomem *reg)
127 void __iomem *base)
128{ 130{
129 u32 val; 131 u32 val;
130 132
131 val = readl(base + offset); 133 val = readl(reg);
132 val &= ~mask; 134 val &= ~mask;
133 val |= (value << __ffs(mask)) & mask; 135 val |= (value << __ffs(mask)) & mask;
134 writel(val, base + offset); 136 writel(val, reg);
135 137
136 return val; 138 return val;
137} 139}
@@ -263,21 +265,19 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb,
263 if (ret) 265 if (ret)
264 goto out; 266 goto out;
265 267
266 ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, regs->setup_reg, 268 ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, abb->setup_reg);
267 abb->base);
268 269
269 switch (info->opp_sel) { 270 switch (info->opp_sel) {
270 case TI_ABB_SLOW_OPP: 271 case TI_ABB_SLOW_OPP:
271 ti_abb_rmw(regs->rbb_sel_mask, 1, regs->setup_reg, abb->base); 272 ti_abb_rmw(regs->rbb_sel_mask, 1, abb->setup_reg);
272 break; 273 break;
273 case TI_ABB_FAST_OPP: 274 case TI_ABB_FAST_OPP:
274 ti_abb_rmw(regs->fbb_sel_mask, 1, regs->setup_reg, abb->base); 275 ti_abb_rmw(regs->fbb_sel_mask, 1, abb->setup_reg);
275 break; 276 break;
276 } 277 }
277 278
278 /* program next state of ABB ldo */ 279 /* program next state of ABB ldo */
279 ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, regs->control_reg, 280 ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, abb->control_reg);
280 abb->base);
281 281
282 /* 282 /*
283 * program LDO VBB vset override if needed for !bypass mode 283 * program LDO VBB vset override if needed for !bypass mode
@@ -288,7 +288,7 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb,
288 ti_abb_program_ldovbb(dev, abb, info); 288 ti_abb_program_ldovbb(dev, abb, info);
289 289
290 /* Initiate ABB ldo change */ 290 /* Initiate ABB ldo change */
291 ti_abb_rmw(regs->opp_change_mask, 1, regs->control_reg, abb->base); 291 ti_abb_rmw(regs->opp_change_mask, 1, abb->control_reg);
292 292
293 /* Wait for ABB LDO to complete transition to new Bias setting */ 293 /* Wait for ABB LDO to complete transition to new Bias setting */
294 ret = ti_abb_wait_txdone(dev, abb); 294 ret = ti_abb_wait_txdone(dev, abb);
@@ -490,8 +490,7 @@ static int ti_abb_init_timings(struct device *dev, struct ti_abb *abb)
490 dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__, 490 dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__,
491 clk_get_rate(abb->clk), sr2_wt_cnt_val); 491 clk_get_rate(abb->clk), sr2_wt_cnt_val);
492 492
493 ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, regs->setup_reg, 493 ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, abb->setup_reg);
494 abb->base);
495 494
496 return 0; 495 return 0;
497} 496}
@@ -648,8 +647,8 @@ static struct regulator_ops ti_abb_reg_ops = {
648/* Default ABB block offsets, IF this changes in future, create new one */ 647/* Default ABB block offsets, IF this changes in future, create new one */
649static const struct ti_abb_reg abb_regs_v1 = { 648static const struct ti_abb_reg abb_regs_v1 = {
650 /* WARNING: registers are wrongly documented in TRM */ 649 /* WARNING: registers are wrongly documented in TRM */
651 .setup_reg = 0x04, 650 .setup_off = 0x04,
652 .control_reg = 0x00, 651 .control_off = 0x00,
653 652
654 .sr2_wtcnt_value_mask = (0xff << 8), 653 .sr2_wtcnt_value_mask = (0xff << 8),
655 .fbb_sel_mask = (0x01 << 2), 654 .fbb_sel_mask = (0x01 << 2),
@@ -661,8 +660,8 @@ static const struct ti_abb_reg abb_regs_v1 = {
661}; 660};
662 661
663static const struct ti_abb_reg abb_regs_v2 = { 662static const struct ti_abb_reg abb_regs_v2 = {
664 .setup_reg = 0x00, 663 .setup_off = 0x00,
665 .control_reg = 0x04, 664 .control_off = 0x04,
666 665
667 .sr2_wtcnt_value_mask = (0xff << 8), 666 .sr2_wtcnt_value_mask = (0xff << 8),
668 .fbb_sel_mask = (0x01 << 2), 667 .fbb_sel_mask = (0x01 << 2),
@@ -673,9 +672,20 @@ static const struct ti_abb_reg abb_regs_v2 = {
673 .opp_sel_mask = (0x03 << 0), 672 .opp_sel_mask = (0x03 << 0),
674}; 673};
675 674
675static const struct ti_abb_reg abb_regs_generic = {
676 .sr2_wtcnt_value_mask = (0xff << 8),
677 .fbb_sel_mask = (0x01 << 2),
678 .rbb_sel_mask = (0x01 << 1),
679 .sr2_en_mask = (0x01 << 0),
680
681 .opp_change_mask = (0x01 << 2),
682 .opp_sel_mask = (0x03 << 0),
683};
684
676static const struct of_device_id ti_abb_of_match[] = { 685static const struct of_device_id ti_abb_of_match[] = {
677 {.compatible = "ti,abb-v1", .data = &abb_regs_v1}, 686 {.compatible = "ti,abb-v1", .data = &abb_regs_v1},
678 {.compatible = "ti,abb-v2", .data = &abb_regs_v2}, 687 {.compatible = "ti,abb-v2", .data = &abb_regs_v2},
688 {.compatible = "ti,abb-v3", .data = &abb_regs_generic},
679 { }, 689 { },
680}; 690};
681 691
@@ -722,11 +732,29 @@ static int ti_abb_probe(struct platform_device *pdev)
722 abb->regs = match->data; 732 abb->regs = match->data;
723 733
724 /* Map ABB resources */ 734 /* Map ABB resources */
725 pname = "base-address"; 735 if (abb->regs->setup_off || abb->regs->control_off) {
726 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); 736 pname = "base-address";
727 abb->base = devm_ioremap_resource(dev, res); 737 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
728 if (IS_ERR(abb->base)) 738 abb->base = devm_ioremap_resource(dev, res);
729 return PTR_ERR(abb->base); 739 if (IS_ERR(abb->base))
740 return PTR_ERR(abb->base);
741
742 abb->setup_reg = abb->base + abb->regs->setup_off;
743 abb->control_reg = abb->base + abb->regs->control_off;
744
745 } else {
746 pname = "control-address";
747 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
748 abb->control_reg = devm_ioremap_resource(dev, res);
749 if (IS_ERR(abb->control_reg))
750 return PTR_ERR(abb->control_reg);
751
752 pname = "setup-address";
753 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
754 abb->setup_reg = devm_ioremap_resource(dev, res);
755 if (IS_ERR(abb->setup_reg))
756 return PTR_ERR(abb->setup_reg);
757 }
730 758
731 pname = "int-address"; 759 pname = "int-address";
732 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); 760 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
@@ -860,7 +888,7 @@ skip_opt:
860 platform_set_drvdata(pdev, rdev); 888 platform_set_drvdata(pdev, rdev);
861 889
862 /* Enable the ldo if not already done by bootloader */ 890 /* Enable the ldo if not already done by bootloader */
863 ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base); 891 ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->setup_reg);
864 892
865 return 0; 893 return 0;
866} 894}