aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/act8865-regulator.c
diff options
context:
space:
mode:
authorBeniamino Galvani <b.galvani@gmail.com>2014-07-05 09:20:54 -0400
committerMark Brown <broonie@linaro.org>2014-08-05 13:02:52 -0400
commit50a03e35b09ea5098ca42a59ad3fdb56a965f2dd (patch)
treef5217e74c7191916a2f55b1ea638cfeb0ee377ef /drivers/regulator/act8865-regulator.c
parentbbb83f38a8b0702f1b333aef1e8a3aa14068cdc7 (diff)
regulator: act8865: prepare support for other act88xx devices
This patch prepares support for other devices in the act88xx family of PMUs manufactured by Active-Semi. http://www.active-semi.com/products/power-management-units/act88xx/ Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> Tested-by: Wenyou Yang <wenyou.yang@atmel.com> Reviewed-by: Axel Lin <axel.lin@ingics.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/regulator/act8865-regulator.c')
-rw-r--r--drivers/regulator/act8865-regulator.c211
1 files changed, 83 insertions, 128 deletions
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 52d1b6cad76f..b26eaf7580fc 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * act8865-regulator.c - Voltage regulation for the active-semi ACT8865 2 * act8865-regulator.c - Voltage regulation for active-semi ACT88xx PMUs
3 * http://www.active-semi.com/sheets/ACT8865_Datasheet.pdf 3 *
4 * http://www.active-semi.com/products/power-management-units/act88xx/
4 * 5 *
5 * Copyright (C) 2013 Atmel Corporation 6 * Copyright (C) 2013 Atmel Corporation
6 * 7 *
@@ -70,7 +71,7 @@ static const struct regmap_config act8865_regmap_config = {
70 .val_bits = 8, 71 .val_bits = 8,
71}; 72};
72 73
73static const struct regulator_linear_range act8865_volatge_ranges[] = { 74static const struct regulator_linear_range act8865_voltage_ranges[] = {
74 REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000), 75 REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
75 REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000), 76 REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
76 REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000), 77 REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
@@ -86,110 +87,35 @@ static struct regulator_ops act8865_ops = {
86 .is_enabled = regulator_is_enabled_regmap, 87 .is_enabled = regulator_is_enabled_regmap,
87}; 88};
88 89
89static const struct regulator_desc act8865_reg[] = { 90#define ACT88xx_REG(_name, _family, _id, _vsel_reg) \
90 { 91 [_family##_ID_##_id] = { \
91 .name = "DCDC_REG1", 92 .name = _name, \
92 .id = ACT8865_ID_DCDC1, 93 .id = _family##_ID_##_id, \
93 .ops = &act8865_ops, 94 .type = REGULATOR_VOLTAGE, \
94 .type = REGULATOR_VOLTAGE, 95 .ops = &act8865_ops, \
95 .n_voltages = ACT8865_VOLTAGE_NUM, 96 .n_voltages = ACT8865_VOLTAGE_NUM, \
96 .linear_ranges = act8865_volatge_ranges, 97 .linear_ranges = act8865_voltage_ranges, \
97 .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges), 98 .n_linear_ranges = ARRAY_SIZE(act8865_voltage_ranges), \
98 .vsel_reg = ACT8865_DCDC1_VSET1, 99 .vsel_reg = _family##_##_id##_##_vsel_reg, \
99 .vsel_mask = ACT8865_VSEL_MASK, 100 .vsel_mask = ACT8865_VSEL_MASK, \
100 .enable_reg = ACT8865_DCDC1_CTRL, 101 .enable_reg = _family##_##_id##_CTRL, \
101 .enable_mask = ACT8865_ENA, 102 .enable_mask = ACT8865_ENA, \
102 .owner = THIS_MODULE, 103 .owner = THIS_MODULE, \
103 }, 104 }
104 { 105
105 .name = "DCDC_REG2", 106static const struct regulator_desc act8865_regulators[] = {
106 .id = ACT8865_ID_DCDC2, 107 ACT88xx_REG("DCDC_REG1", ACT8865, DCDC1, VSET1),
107 .ops = &act8865_ops, 108 ACT88xx_REG("DCDC_REG2", ACT8865, DCDC2, VSET1),
108 .type = REGULATOR_VOLTAGE, 109 ACT88xx_REG("DCDC_REG3", ACT8865, DCDC3, VSET1),
109 .n_voltages = ACT8865_VOLTAGE_NUM, 110 ACT88xx_REG("LDO_REG1", ACT8865, LDO1, VSET),
110 .linear_ranges = act8865_volatge_ranges, 111 ACT88xx_REG("LDO_REG2", ACT8865, LDO2, VSET),
111 .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges), 112 ACT88xx_REG("LDO_REG3", ACT8865, LDO3, VSET),
112 .vsel_reg = ACT8865_DCDC2_VSET1, 113 ACT88xx_REG("LDO_REG4", ACT8865, LDO4, VSET),
113 .vsel_mask = ACT8865_VSEL_MASK,
114 .enable_reg = ACT8865_DCDC2_CTRL,
115 .enable_mask = ACT8865_ENA,
116 .owner = THIS_MODULE,
117 },
118 {
119 .name = "DCDC_REG3",
120 .id = ACT8865_ID_DCDC3,
121 .ops = &act8865_ops,
122 .type = REGULATOR_VOLTAGE,
123 .n_voltages = ACT8865_VOLTAGE_NUM,
124 .linear_ranges = act8865_volatge_ranges,
125 .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
126 .vsel_reg = ACT8865_DCDC3_VSET1,
127 .vsel_mask = ACT8865_VSEL_MASK,
128 .enable_reg = ACT8865_DCDC3_CTRL,
129 .enable_mask = ACT8865_ENA,
130 .owner = THIS_MODULE,
131 },
132 {
133 .name = "LDO_REG1",
134 .id = ACT8865_ID_LDO1,
135 .ops = &act8865_ops,
136 .type = REGULATOR_VOLTAGE,
137 .n_voltages = ACT8865_VOLTAGE_NUM,
138 .linear_ranges = act8865_volatge_ranges,
139 .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
140 .vsel_reg = ACT8865_LDO1_VSET,
141 .vsel_mask = ACT8865_VSEL_MASK,
142 .enable_reg = ACT8865_LDO1_CTRL,
143 .enable_mask = ACT8865_ENA,
144 .owner = THIS_MODULE,
145 },
146 {
147 .name = "LDO_REG2",
148 .id = ACT8865_ID_LDO2,
149 .ops = &act8865_ops,
150 .type = REGULATOR_VOLTAGE,
151 .n_voltages = ACT8865_VOLTAGE_NUM,
152 .linear_ranges = act8865_volatge_ranges,
153 .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
154 .vsel_reg = ACT8865_LDO2_VSET,
155 .vsel_mask = ACT8865_VSEL_MASK,
156 .enable_reg = ACT8865_LDO2_CTRL,
157 .enable_mask = ACT8865_ENA,
158 .owner = THIS_MODULE,
159 },
160 {
161 .name = "LDO_REG3",
162 .id = ACT8865_ID_LDO3,
163 .ops = &act8865_ops,
164 .type = REGULATOR_VOLTAGE,
165 .n_voltages = ACT8865_VOLTAGE_NUM,
166 .linear_ranges = act8865_volatge_ranges,
167 .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
168 .vsel_reg = ACT8865_LDO3_VSET,
169 .vsel_mask = ACT8865_VSEL_MASK,
170 .enable_reg = ACT8865_LDO3_CTRL,
171 .enable_mask = ACT8865_ENA,
172 .owner = THIS_MODULE,
173 },
174 {
175 .name = "LDO_REG4",
176 .id = ACT8865_ID_LDO4,
177 .ops = &act8865_ops,
178 .type = REGULATOR_VOLTAGE,
179 .n_voltages = ACT8865_VOLTAGE_NUM,
180 .linear_ranges = act8865_volatge_ranges,
181 .n_linear_ranges = ARRAY_SIZE(act8865_volatge_ranges),
182 .vsel_reg = ACT8865_LDO4_VSET,
183 .vsel_mask = ACT8865_VSEL_MASK,
184 .enable_reg = ACT8865_LDO4_CTRL,
185 .enable_mask = ACT8865_ENA,
186 .owner = THIS_MODULE,
187 },
188}; 114};
189 115
190#ifdef CONFIG_OF 116#ifdef CONFIG_OF
191static const struct of_device_id act8865_dt_ids[] = { 117static const struct of_device_id act8865_dt_ids[] = {
192 { .compatible = "active-semi,act8865" }, 118 { .compatible = "active-semi,act8865", .data = (void *)ACT8865 },
193 { } 119 { }
194}; 120};
195MODULE_DEVICE_TABLE(of, act8865_dt_ids); 121MODULE_DEVICE_TABLE(of, act8865_dt_ids);
@@ -206,7 +132,9 @@ static struct of_regulator_match act8865_matches[] = {
206 132
207static int act8865_pdata_from_dt(struct device *dev, 133static int act8865_pdata_from_dt(struct device *dev,
208 struct device_node **of_node, 134 struct device_node **of_node,
209 struct act8865_platform_data *pdata) 135 struct act8865_platform_data *pdata,
136 struct of_regulator_match *matches,
137 int num_matches)
210{ 138{
211 int matched, i; 139 int matched, i;
212 struct device_node *np; 140 struct device_node *np;
@@ -218,26 +146,25 @@ static int act8865_pdata_from_dt(struct device *dev,
218 return -EINVAL; 146 return -EINVAL;
219 } 147 }
220 148
221 matched = of_regulator_match(dev, np, 149 matched = of_regulator_match(dev, np, matches, num_matches);
222 act8865_matches, ARRAY_SIZE(act8865_matches));
223 of_node_put(np); 150 of_node_put(np);
224 if (matched <= 0) 151 if (matched <= 0)
225 return matched; 152 return matched;
226 153
227 pdata->regulators = devm_kzalloc(dev, 154 pdata->regulators = devm_kzalloc(dev,
228 sizeof(struct act8865_regulator_data) * 155 sizeof(struct act8865_regulator_data) *
229 ARRAY_SIZE(act8865_matches), GFP_KERNEL); 156 num_matches, GFP_KERNEL);
230 if (!pdata->regulators) 157 if (!pdata->regulators)
231 return -ENOMEM; 158 return -ENOMEM;
232 159
233 pdata->num_regulators = ARRAY_SIZE(act8865_matches); 160 pdata->num_regulators = num_matches;
234 regulator = pdata->regulators; 161 regulator = pdata->regulators;
235 162
236 for (i = 0; i < ARRAY_SIZE(act8865_matches); i++) { 163 for (i = 0; i < num_matches; i++) {
237 regulator->id = i; 164 regulator->id = i;
238 regulator->name = act8865_matches[i].name; 165 regulator->name = matches[i].name;
239 regulator->platform_data = act8865_matches[i].init_data; 166 regulator->platform_data = matches[i].init_data;
240 of_node[i] = act8865_matches[i].of_node; 167 of_node[i] = matches[i].of_node;
241 regulator++; 168 regulator++;
242 } 169 }
243 170
@@ -269,34 +196,59 @@ static struct regulator_init_data
269} 196}
270 197
271static int act8865_pmic_probe(struct i2c_client *client, 198static int act8865_pmic_probe(struct i2c_client *client,
272 const struct i2c_device_id *i2c_id) 199 const struct i2c_device_id *i2c_id)
273{ 200{
274 struct regulator_dev *rdev; 201 static const struct regulator_desc *regulators;
202 struct act8865_platform_data pdata_of, *pdata;
203 struct of_regulator_match *matches;
275 struct device *dev = &client->dev; 204 struct device *dev = &client->dev;
276 struct act8865_platform_data *pdata = dev_get_platdata(dev); 205 struct device_node **of_node;
277 struct regulator_config config = { }; 206 int i, ret, num_regulators;
278 struct act8865 *act8865; 207 struct act8865 *act8865;
279 struct device_node *of_node[ACT8865_REG_NUM]; 208 unsigned long type;
280 int i; 209
281 int ret; 210 pdata = dev_get_platdata(dev);
282 211
283 if (dev->of_node && !pdata) { 212 if (dev->of_node && !pdata) {
284 const struct of_device_id *id; 213 const struct of_device_id *id;
285 struct act8865_platform_data pdata_of;
286 214
287 id = of_match_device(of_match_ptr(act8865_dt_ids), dev); 215 id = of_match_device(of_match_ptr(act8865_dt_ids), dev);
288 if (!id) 216 if (!id)
289 return -ENODEV; 217 return -ENODEV;
290 218
291 ret = act8865_pdata_from_dt(dev, of_node, &pdata_of); 219 type = (unsigned long) id->data;
220 } else {
221 type = i2c_id->driver_data;
222 }
223
224 switch (type) {
225 case ACT8865:
226 matches = act8865_matches;
227 regulators = act8865_regulators;
228 num_regulators = ARRAY_SIZE(act8865_regulators);
229 break;
230 default:
231 dev_err(dev, "invalid device id %lu\n", type);
232 return -EINVAL;
233 }
234
235 of_node = devm_kzalloc(dev, sizeof(struct device_node *) *
236 num_regulators, GFP_KERNEL);
237 if (!of_node)
238 return -ENOMEM;
239
240 if (dev->of_node && !pdata) {
241 ret = act8865_pdata_from_dt(dev, of_node, &pdata_of, matches,
242 num_regulators);
292 if (ret < 0) 243 if (ret < 0)
293 return ret; 244 return ret;
294 245
295 pdata = &pdata_of; 246 pdata = &pdata_of;
296 } 247 }
297 248
298 if (pdata->num_regulators > ACT8865_REG_NUM) { 249 if (pdata->num_regulators > num_regulators) {
299 dev_err(dev, "Too many regulators found!\n"); 250 dev_err(dev, "too many regulators: %d\n",
251 pdata->num_regulators);
300 return -EINVAL; 252 return -EINVAL;
301 } 253 }
302 254
@@ -313,8 +265,10 @@ static int act8865_pmic_probe(struct i2c_client *client,
313 } 265 }
314 266
315 /* Finally register devices */ 267 /* Finally register devices */
316 for (i = 0; i < ACT8865_REG_NUM; i++) { 268 for (i = 0; i < num_regulators; i++) {
317 const struct regulator_desc *desc = &act8865_reg[i]; 269 const struct regulator_desc *desc = &regulators[i];
270 struct regulator_config config = { };
271 struct regulator_dev *rdev;
318 272
319 config.dev = dev; 273 config.dev = dev;
320 config.init_data = act8865_get_init_data(desc->id, pdata); 274 config.init_data = act8865_get_init_data(desc->id, pdata);
@@ -330,12 +284,13 @@ static int act8865_pmic_probe(struct i2c_client *client,
330 } 284 }
331 285
332 i2c_set_clientdata(client, act8865); 286 i2c_set_clientdata(client, act8865);
287 devm_kfree(dev, of_node);
333 288
334 return 0; 289 return 0;
335} 290}
336 291
337static const struct i2c_device_id act8865_ids[] = { 292static const struct i2c_device_id act8865_ids[] = {
338 { "act8865", 0 }, 293 { .name = "act8865", .driver_data = ACT8865 },
339 { }, 294 { },
340}; 295};
341MODULE_DEVICE_TABLE(i2c, act8865_ids); 296MODULE_DEVICE_TABLE(i2c, act8865_ids);
@@ -351,6 +306,6 @@ static struct i2c_driver act8865_pmic_driver = {
351 306
352module_i2c_driver(act8865_pmic_driver); 307module_i2c_driver(act8865_pmic_driver);
353 308
354MODULE_DESCRIPTION("active-semi act8865 voltage regulator driver"); 309MODULE_DESCRIPTION("active-semi act88xx voltage regulator driver");
355MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>"); 310MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
356MODULE_LICENSE("GPL v2"); 311MODULE_LICENSE("GPL v2");