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