sunxi: add support for 4.1
[openwrt.git] / target / linux / sunxi / patches-4.1 / 101-regulator-axp20x-prep-support-for-multiple-axp-families.patch
1 From f95b73ba272eac5495e69e12795d5ea8bc81d2cd Mon Sep 17 00:00:00 2001
2 From: Boris BREZILLON <boris.brezillon@free-electrons.com>
3 Date: Fri, 10 Apr 2015 12:09:03 +0800
4 Subject: [PATCH] regulator: axp20x: Prepare support for multiple AXP chip
5  families
6
7 Rework the AXP20X_ macros and probe function to support the several chip
8 families, so that each family can define it's own set of regulators.
9
10 Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
11 [wens@csie.org: Support different DC-DC work frequency ranges]
12 Signed-off-by: Chen-Yu Tsai <wens@csie.org>
13 Reviewed-by: Mark Brown <broonie@kernel.org>
14 Signed-off-by: Lee Jones <lee.jones@linaro.org>
15 ---
16  drivers/regulator/axp20x-regulator.c | 143 +++++++++++++++++++++++------------
17  1 file changed, 94 insertions(+), 49 deletions(-)
18
19 diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
20 index e4331f5..50ae0b5 100644
21 --- a/drivers/regulator/axp20x-regulator.c
22 +++ b/drivers/regulator/axp20x-regulator.c
23 @@ -32,15 +32,15 @@
24  
25  #define AXP20X_FREQ_DCDC_MASK          0x0f
26  
27 -#define AXP20X_DESC_IO(_id, _match, _supply, _min, _max, _step, _vreg, _vmask, \
28 -                      _ereg, _emask, _enable_val, _disable_val)                \
29 -       [AXP20X_##_id] = {                                                      \
30 +#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,   \
31 +                   _vmask, _ereg, _emask, _enable_val, _disable_val)           \
32 +       [_family##_##_id] = {                                                   \
33                 .name           = #_id,                                         \
34                 .supply_name    = (_supply),                                    \
35                 .of_match       = of_match_ptr(_match),                         \
36                 .regulators_node = of_match_ptr("regulators"),                  \
37                 .type           = REGULATOR_VOLTAGE,                            \
38 -               .id             = AXP20X_##_id,                                 \
39 +               .id             = _family##_##_id,                              \
40                 .n_voltages     = (((_max) - (_min)) / (_step) + 1),            \
41                 .owner          = THIS_MODULE,                                  \
42                 .min_uV         = (_min) * 1000,                                \
43 @@ -54,15 +54,15 @@
44                 .ops            = &axp20x_ops,                                  \
45         }
46  
47 -#define AXP20X_DESC(_id, _match, _supply, _min, _max, _step, _vreg, _vmask,    \
48 -                   _ereg, _emask)                                              \
49 -       [AXP20X_##_id] = {                                                      \
50 +#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,      \
51 +                _vmask, _ereg, _emask)                                         \
52 +       [_family##_##_id] = {                                                   \
53                 .name           = #_id,                                         \
54                 .supply_name    = (_supply),                                    \
55                 .of_match       = of_match_ptr(_match),                         \
56                 .regulators_node = of_match_ptr("regulators"),                  \
57                 .type           = REGULATOR_VOLTAGE,                            \
58 -               .id             = AXP20X_##_id,                                 \
59 +               .id             = _family##_##_id,                              \
60                 .n_voltages     = (((_max) - (_min)) / (_step) + 1),            \
61                 .owner          = THIS_MODULE,                                  \
62                 .min_uV         = (_min) * 1000,                                \
63 @@ -74,29 +74,29 @@
64                 .ops            = &axp20x_ops,                                  \
65         }
66  
67 -#define AXP20X_DESC_FIXED(_id, _match, _supply, _volt)                         \
68 -       [AXP20X_##_id] = {                                                      \
69 +#define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)                   \
70 +       [_family##_##_id] = {                                                   \
71                 .name           = #_id,                                         \
72                 .supply_name    = (_supply),                                    \
73                 .of_match       = of_match_ptr(_match),                         \
74                 .regulators_node = of_match_ptr("regulators"),                  \
75                 .type           = REGULATOR_VOLTAGE,                            \
76 -               .id             = AXP20X_##_id,                                 \
77 +               .id             = _family##_##_id,                              \
78                 .n_voltages     = 1,                                            \
79                 .owner          = THIS_MODULE,                                  \
80                 .min_uV         = (_volt) * 1000,                               \
81                 .ops            = &axp20x_ops_fixed                             \
82         }
83  
84 -#define AXP20X_DESC_TABLE(_id, _match, _supply, _table, _vreg, _vmask, _ereg,  \
85 -                         _emask)                                               \
86 -       [AXP20X_##_id] = {                                                      \
87 +#define AXP_DESC_TABLE(_family, _id, _match, _supply, _table, _vreg, _vmask,   \
88 +                      _ereg, _emask)                                           \
89 +       [_family##_##_id] = {                                                   \
90                 .name           = #_id,                                         \
91                 .supply_name    = (_supply),                                    \
92                 .of_match       = of_match_ptr(_match),                         \
93                 .regulators_node = of_match_ptr("regulators"),                  \
94                 .type           = REGULATOR_VOLTAGE,                            \
95 -               .id             = AXP20X_##_id,                                 \
96 +               .id             = _family##_##_id,                              \
97                 .n_voltages     = ARRAY_SIZE(_table),                           \
98                 .owner          = THIS_MODULE,                                  \
99                 .vsel_reg       = (_vreg),                                      \
100 @@ -136,37 +136,57 @@ static struct regulator_ops axp20x_ops = {
101  };
102  
103  static const struct regulator_desc axp20x_regulators[] = {
104 -       AXP20X_DESC(DCDC2, "dcdc2", "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT,
105 -                   0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
106 -       AXP20X_DESC(DCDC3, "dcdc3", "vin3", 700, 3500, 25, AXP20X_DCDC3_V_OUT,
107 -                   0x7f, AXP20X_PWR_OUT_CTRL, 0x02),
108 -       AXP20X_DESC_FIXED(LDO1, "ldo1", "acin", 1300),
109 -       AXP20X_DESC(LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
110 -                   AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
111 -       AXP20X_DESC(LDO3, "ldo3", "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT,
112 -                   0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
113 -       AXP20X_DESC_TABLE(LDO4, "ldo4", "ldo24in", axp20x_ldo4_data,
114 -                         AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08),
115 -       AXP20X_DESC_IO(LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
116 -                      AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
117 -                      AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
118 +       AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25,
119 +                AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
120 +       AXP_DESC(AXP20X, DCDC3, "dcdc3", "vin3", 700, 3500, 25,
121 +                AXP20X_DCDC3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x02),
122 +       AXP_DESC_FIXED(AXP20X, LDO1, "ldo1", "acin", 1300),
123 +       AXP_DESC(AXP20X, LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
124 +                AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
125 +       AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
126 +                AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
127 +       AXP_DESC_TABLE(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_data,
128 +                      AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08),
129 +       AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
130 +                   AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
131 +                   AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
132  };
133  
134  static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
135  {
136         struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
137 +       u32 min, max, def, step;
138 +
139 +       switch (axp20x->variant) {
140 +       case AXP202_ID:
141 +       case AXP209_ID:
142 +               min = 750;
143 +               max = 1875;
144 +               def = 1500;
145 +               step = 75;
146 +               break;
147 +       default:
148 +               dev_err(&pdev->dev,
149 +                       "Setting DCDC frequency for unsupported AXP variant\n");
150 +               return -EINVAL;
151 +       }
152 +
153 +       if (dcdcfreq == 0)
154 +               dcdcfreq = def;
155  
156 -       if (dcdcfreq < 750) {
157 -               dcdcfreq = 750;
158 -               dev_warn(&pdev->dev, "DCDC frequency too low. Set to 750kHz\n");
159 +       if (dcdcfreq < min) {
160 +               dcdcfreq = min;
161 +               dev_warn(&pdev->dev, "DCDC frequency too low. Set to %ukHz\n",
162 +                        min);
163         }
164  
165 -       if (dcdcfreq > 1875) {
166 -               dcdcfreq = 1875;
167 -               dev_warn(&pdev->dev, "DCDC frequency too high. Set to 1875kHz\n");
168 +       if (dcdcfreq > max) {
169 +               dcdcfreq = max;
170 +               dev_warn(&pdev->dev, "DCDC frequency too high. Set to %ukHz\n",
171 +                        max);
172         }
173  
174 -       dcdcfreq = (dcdcfreq - 750) / 75;
175 +       dcdcfreq = (dcdcfreq - min) / step;
176  
177         return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ,
178                                   AXP20X_FREQ_DCDC_MASK, dcdcfreq);
179 @@ -176,7 +196,7 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
180  {
181         struct device_node *np, *regulators;
182         int ret;
183 -       u32 dcdcfreq;
184 +       u32 dcdcfreq = 0;
185  
186         np = of_node_get(pdev->dev.parent->of_node);
187         if (!np)
188 @@ -186,7 +206,6 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
189         if (!regulators) {
190                 dev_warn(&pdev->dev, "regulators node not found\n");
191         } else {
192 -               dcdcfreq = 1500;
193                 of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
194                 ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
195                 if (ret < 0) {
196 @@ -202,15 +221,27 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
197  
198  static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
199  {
200 -       unsigned int mask = AXP20X_WORKMODE_DCDC2_MASK;
201 +       struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
202 +       unsigned int mask;
203  
204 -       if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
205 -               return -EINVAL;
206 +       switch (axp20x->variant) {
207 +       case AXP202_ID:
208 +       case AXP209_ID:
209 +               if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
210 +                       return -EINVAL;
211 +
212 +               mask = AXP20X_WORKMODE_DCDC2_MASK;
213 +               if (id == AXP20X_DCDC3)
214 +                       mask = AXP20X_WORKMODE_DCDC3_MASK;
215  
216 -       if (id == AXP20X_DCDC3)
217 -               mask = AXP20X_WORKMODE_DCDC3_MASK;
218 +               workmode <<= ffs(mask) - 1;
219 +               break;
220  
221 -       workmode <<= ffs(mask) - 1;
222 +       default:
223 +               /* should not happen */
224 +               WARN_ON(1);
225 +               return -EINVAL;
226 +       }
227  
228         return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode);
229  }
230 @@ -219,22 +250,36 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
231  {
232         struct regulator_dev *rdev;
233         struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
234 +       const struct regulator_desc *regulators;
235         struct regulator_config config = {
236                 .dev = pdev->dev.parent,
237                 .regmap = axp20x->regmap,
238 +               .driver_data = axp20x,
239         };
240 -       int ret, i;
241 +       int ret, i, nregulators;
242         u32 workmode;
243  
244 +       switch (axp20x->variant) {
245 +       case AXP202_ID:
246 +       case AXP209_ID:
247 +               regulators = axp20x_regulators;
248 +               nregulators = AXP20X_REG_ID_MAX;
249 +               break;
250 +       default:
251 +               dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
252 +                       axp20x->variant);
253 +               return -EINVAL;
254 +       }
255 +
256         /* This only sets the dcdc freq. Ignore any errors */
257         axp20x_regulator_parse_dt(pdev);
258  
259 -       for (i = 0; i < AXP20X_REG_ID_MAX; i++) {
260 -               rdev = devm_regulator_register(&pdev->dev, &axp20x_regulators[i],
261 +       for (i = 0; i < nregulators; i++) {
262 +               rdev = devm_regulator_register(&pdev->dev, &regulators[i],
263                                                &config);
264                 if (IS_ERR(rdev)) {
265                         dev_err(&pdev->dev, "Failed to register %s\n",
266 -                               axp20x_regulators[i].name);
267 +                               regulators[i].name);
268  
269                         return PTR_ERR(rdev);
270                 }
271 @@ -245,7 +290,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
272                 if (!ret) {
273                         if (axp20x_set_dcdc_workmode(rdev, i, workmode))
274                                 dev_err(&pdev->dev, "Failed to set workmode on %s\n",
275 -                                       axp20x_regulators[i].name);
276 +                                       rdev->desc->name);
277                 }
278         }
279