diff options
-rw-r--r-- | drivers/mfd/tps65217.c | 130 | ||||
-rw-r--r-- | drivers/regulator/tps65217-regulator.c | 124 | ||||
-rw-r--r-- | include/linux/mfd/tps65217.h | 12 |
3 files changed, 161 insertions, 105 deletions
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c index 61c097a98f5d..3bc274409b58 100644 --- a/drivers/mfd/tps65217.c +++ b/drivers/mfd/tps65217.c | |||
@@ -24,11 +24,18 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/regmap.h> | 25 | #include <linux/regmap.h> |
26 | #include <linux/err.h> | 26 | #include <linux/err.h> |
27 | #include <linux/regulator/of_regulator.h> | 27 | #include <linux/of.h> |
28 | #include <linux/of_device.h> | ||
28 | 29 | ||
29 | #include <linux/mfd/core.h> | 30 | #include <linux/mfd/core.h> |
30 | #include <linux/mfd/tps65217.h> | 31 | #include <linux/mfd/tps65217.h> |
31 | 32 | ||
33 | static struct mfd_cell tps65217s[] = { | ||
34 | { | ||
35 | .name = "tps65217-pmic", | ||
36 | }, | ||
37 | }; | ||
38 | |||
32 | /** | 39 | /** |
33 | * tps65217_reg_read: Read a single tps65217 register. | 40 | * tps65217_reg_read: Read a single tps65217 register. |
34 | * | 41 | * |
@@ -133,83 +140,48 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg, | |||
133 | } | 140 | } |
134 | EXPORT_SYMBOL_GPL(tps65217_clear_bits); | 141 | EXPORT_SYMBOL_GPL(tps65217_clear_bits); |
135 | 142 | ||
136 | #ifdef CONFIG_OF | ||
137 | static struct of_regulator_match reg_matches[] = { | ||
138 | { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, | ||
139 | { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, | ||
140 | { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, | ||
141 | { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, | ||
142 | { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, | ||
143 | { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, | ||
144 | { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, | ||
145 | }; | ||
146 | |||
147 | static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) | ||
148 | { | ||
149 | struct device_node *node = client->dev.of_node; | ||
150 | struct tps65217_board *pdata; | ||
151 | struct device_node *regs; | ||
152 | int count = ARRAY_SIZE(reg_matches); | ||
153 | int ret, i; | ||
154 | |||
155 | regs = of_find_node_by_name(node, "regulators"); | ||
156 | if (!regs) | ||
157 | return NULL; | ||
158 | |||
159 | ret = of_regulator_match(&client->dev, regs, reg_matches, count); | ||
160 | of_node_put(regs); | ||
161 | if ((ret < 0) || (ret > count)) | ||
162 | return NULL; | ||
163 | |||
164 | count = ret; | ||
165 | pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL); | ||
166 | if (!pdata) | ||
167 | return NULL; | ||
168 | |||
169 | for (i = 0; i < count; i++) { | ||
170 | if (!reg_matches[i].init_data || !reg_matches[i].of_node) | ||
171 | continue; | ||
172 | |||
173 | pdata->tps65217_init_data[i] = reg_matches[i].init_data; | ||
174 | pdata->of_node[i] = reg_matches[i].of_node; | ||
175 | } | ||
176 | |||
177 | return pdata; | ||
178 | } | ||
179 | |||
180 | static struct of_device_id tps65217_of_match[] = { | ||
181 | { .compatible = "ti,tps65217", }, | ||
182 | { }, | ||
183 | }; | ||
184 | #else | ||
185 | static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client) | ||
186 | { | ||
187 | return NULL; | ||
188 | } | ||
189 | #endif | ||
190 | |||
191 | static struct regmap_config tps65217_regmap_config = { | 143 | static struct regmap_config tps65217_regmap_config = { |
192 | .reg_bits = 8, | 144 | .reg_bits = 8, |
193 | .val_bits = 8, | 145 | .val_bits = 8, |
194 | }; | 146 | }; |
195 | 147 | ||
148 | static const struct of_device_id tps65217_of_match[] = { | ||
149 | { .compatible = "ti,tps65217", .data = (void *)TPS65217 }, | ||
150 | { /* sentinel */ }, | ||
151 | }; | ||
152 | |||
196 | static int __devinit tps65217_probe(struct i2c_client *client, | 153 | static int __devinit tps65217_probe(struct i2c_client *client, |
197 | const struct i2c_device_id *ids) | 154 | const struct i2c_device_id *ids) |
198 | { | 155 | { |
199 | struct tps65217 *tps; | 156 | struct tps65217 *tps; |
200 | struct regulator_init_data *reg_data; | ||
201 | struct tps65217_board *pdata = client->dev.platform_data; | ||
202 | int i, ret; | ||
203 | unsigned int version; | 157 | unsigned int version; |
158 | unsigned int chip_id = ids->driver_data; | ||
159 | const struct of_device_id *match; | ||
160 | int ret; | ||
204 | 161 | ||
205 | if (!pdata && client->dev.of_node) | 162 | if (client->dev.of_node) { |
206 | pdata = tps65217_parse_dt(client); | 163 | match = of_match_device(tps65217_of_match, &client->dev); |
164 | if (!match) { | ||
165 | dev_err(&client->dev, | ||
166 | "Failed to find matching dt id\n"); | ||
167 | return -EINVAL; | ||
168 | } | ||
169 | chip_id = (unsigned int)match->data; | ||
170 | } | ||
171 | |||
172 | if (!chip_id) { | ||
173 | dev_err(&client->dev, "id is null.\n"); | ||
174 | return -ENODEV; | ||
175 | } | ||
207 | 176 | ||
208 | tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); | 177 | tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); |
209 | if (!tps) | 178 | if (!tps) |
210 | return -ENOMEM; | 179 | return -ENOMEM; |
211 | 180 | ||
212 | tps->pdata = pdata; | 181 | i2c_set_clientdata(client, tps); |
182 | tps->dev = &client->dev; | ||
183 | tps->id = chip_id; | ||
184 | |||
213 | tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config); | 185 | tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config); |
214 | if (IS_ERR(tps->regmap)) { | 186 | if (IS_ERR(tps->regmap)) { |
215 | ret = PTR_ERR(tps->regmap); | 187 | ret = PTR_ERR(tps->regmap); |
@@ -218,8 +190,12 @@ static int __devinit tps65217_probe(struct i2c_client *client, | |||
218 | return ret; | 190 | return ret; |
219 | } | 191 | } |
220 | 192 | ||
221 | i2c_set_clientdata(client, tps); | 193 | ret = mfd_add_devices(tps->dev, -1, tps65217s, |
222 | tps->dev = &client->dev; | 194 | ARRAY_SIZE(tps65217s), NULL, 0); |
195 | if (ret < 0) { | ||
196 | dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret); | ||
197 | return ret; | ||
198 | } | ||
223 | 199 | ||
224 | ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); | 200 | ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version); |
225 | if (ret < 0) { | 201 | if (ret < 0) { |
@@ -232,41 +208,21 @@ static int __devinit tps65217_probe(struct i2c_client *client, | |||
232 | (version & TPS65217_CHIPID_CHIP_MASK) >> 4, | 208 | (version & TPS65217_CHIPID_CHIP_MASK) >> 4, |
233 | version & TPS65217_CHIPID_REV_MASK); | 209 | version & TPS65217_CHIPID_REV_MASK); |
234 | 210 | ||
235 | for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { | ||
236 | struct platform_device *pdev; | ||
237 | |||
238 | pdev = platform_device_alloc("tps65217-pmic", i); | ||
239 | if (!pdev) { | ||
240 | dev_err(tps->dev, "Cannot create regulator %d\n", i); | ||
241 | continue; | ||
242 | } | ||
243 | |||
244 | pdev->dev.parent = tps->dev; | ||
245 | pdev->dev.of_node = pdata->of_node[i]; | ||
246 | reg_data = pdata->tps65217_init_data[i]; | ||
247 | platform_device_add_data(pdev, reg_data, sizeof(*reg_data)); | ||
248 | tps->regulator_pdev[i] = pdev; | ||
249 | |||
250 | platform_device_add(pdev); | ||
251 | } | ||
252 | |||
253 | return 0; | 211 | return 0; |
254 | } | 212 | } |
255 | 213 | ||
256 | static int __devexit tps65217_remove(struct i2c_client *client) | 214 | static int __devexit tps65217_remove(struct i2c_client *client) |
257 | { | 215 | { |
258 | struct tps65217 *tps = i2c_get_clientdata(client); | 216 | struct tps65217 *tps = i2c_get_clientdata(client); |
259 | int i; | ||
260 | 217 | ||
261 | for (i = 0; i < TPS65217_NUM_REGULATOR; i++) | 218 | mfd_remove_devices(tps->dev); |
262 | platform_device_unregister(tps->regulator_pdev[i]); | ||
263 | 219 | ||
264 | return 0; | 220 | return 0; |
265 | } | 221 | } |
266 | 222 | ||
267 | static const struct i2c_device_id tps65217_id_table[] = { | 223 | static const struct i2c_device_id tps65217_id_table[] = { |
268 | {"tps65217", 0xF0}, | 224 | {"tps65217", TPS65217}, |
269 | {/* end of list */} | 225 | { /* sentinel */ } |
270 | }; | 226 | }; |
271 | MODULE_DEVICE_TABLE(i2c, tps65217_id_table); | 227 | MODULE_DEVICE_TABLE(i2c, tps65217_id_table); |
272 | 228 | ||
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 6caa222af77a..ab00cab905b7 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/err.h> | 22 | #include <linux/err.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | 24 | ||
25 | #include <linux/regulator/of_regulator.h> | ||
25 | #include <linux/regulator/driver.h> | 26 | #include <linux/regulator/driver.h> |
26 | #include <linux/regulator/machine.h> | 27 | #include <linux/regulator/machine.h> |
27 | #include <linux/mfd/tps65217.h> | 28 | #include <linux/mfd/tps65217.h> |
@@ -281,37 +282,130 @@ static const struct regulator_desc regulators[] = { | |||
281 | NULL), | 282 | NULL), |
282 | }; | 283 | }; |
283 | 284 | ||
285 | #ifdef CONFIG_OF | ||
286 | static struct of_regulator_match reg_matches[] = { | ||
287 | { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 }, | ||
288 | { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 }, | ||
289 | { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 }, | ||
290 | { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 }, | ||
291 | { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 }, | ||
292 | { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 }, | ||
293 | { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 }, | ||
294 | }; | ||
295 | |||
296 | static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) | ||
297 | { | ||
298 | struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); | ||
299 | struct device_node *node = tps->dev->of_node; | ||
300 | struct tps65217_board *pdata; | ||
301 | struct device_node *regs; | ||
302 | int i, count; | ||
303 | |||
304 | regs = of_find_node_by_name(node, "regulators"); | ||
305 | if (!regs) | ||
306 | return NULL; | ||
307 | |||
308 | count = of_regulator_match(pdev->dev.parent, regs, | ||
309 | reg_matches, TPS65217_NUM_REGULATOR); | ||
310 | of_node_put(regs); | ||
311 | if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) | ||
312 | return NULL; | ||
313 | |||
314 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
315 | if (!pdata) | ||
316 | return NULL; | ||
317 | |||
318 | for (i = 0; i < count; i++) { | ||
319 | if (!reg_matches[i].init_data || !reg_matches[i].of_node) | ||
320 | continue; | ||
321 | |||
322 | pdata->tps65217_init_data[i] = reg_matches[i].init_data; | ||
323 | pdata->of_node[i] = reg_matches[i].of_node; | ||
324 | } | ||
325 | |||
326 | return pdata; | ||
327 | } | ||
328 | #else | ||
329 | static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) | ||
330 | { | ||
331 | return NULL; | ||
332 | } | ||
333 | #endif | ||
334 | |||
284 | static int __devinit tps65217_regulator_probe(struct platform_device *pdev) | 335 | static int __devinit tps65217_regulator_probe(struct platform_device *pdev) |
285 | { | 336 | { |
337 | struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); | ||
338 | struct tps65217_board *pdata = dev_get_platdata(tps->dev); | ||
339 | struct regulator_init_data *reg_data; | ||
286 | struct regulator_dev *rdev; | 340 | struct regulator_dev *rdev; |
287 | struct tps65217 *tps; | ||
288 | struct tps_info *info = &tps65217_pmic_regs[pdev->id]; | ||
289 | struct regulator_config config = { }; | 341 | struct regulator_config config = { }; |
342 | int i, ret; | ||
290 | 343 | ||
291 | /* Already set by core driver */ | 344 | if (tps->dev->of_node) |
292 | tps = dev_to_tps65217(pdev->dev.parent); | 345 | pdata = tps65217_parse_dt(pdev); |
293 | tps->info[pdev->id] = info; | ||
294 | 346 | ||
295 | config.dev = &pdev->dev; | 347 | if (!pdata) { |
296 | config.of_node = pdev->dev.of_node; | 348 | dev_err(&pdev->dev, "Platform data not found\n"); |
297 | config.init_data = pdev->dev.platform_data; | 349 | return -EINVAL; |
298 | config.driver_data = tps; | 350 | } |
299 | 351 | ||
300 | rdev = regulator_register(®ulators[pdev->id], &config); | 352 | if (tps65217_chip_id(tps) != TPS65217) { |
301 | if (IS_ERR(rdev)) | 353 | dev_err(&pdev->dev, "Invalid tps chip version\n"); |
302 | return PTR_ERR(rdev); | 354 | return -ENODEV; |
355 | } | ||
303 | 356 | ||
304 | platform_set_drvdata(pdev, rdev); | 357 | platform_set_drvdata(pdev, tps); |
305 | 358 | ||
359 | for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { | ||
360 | |||
361 | reg_data = pdata->tps65217_init_data[i]; | ||
362 | |||
363 | /* | ||
364 | * Regulator API handles empty constraints but not NULL | ||
365 | * constraints | ||
366 | */ | ||
367 | if (!reg_data) | ||
368 | continue; | ||
369 | |||
370 | /* Register the regulators */ | ||
371 | tps->info[i] = &tps65217_pmic_regs[i]; | ||
372 | |||
373 | config.dev = tps->dev; | ||
374 | config.init_data = reg_data; | ||
375 | config.driver_data = tps; | ||
376 | config.regmap = tps->regmap; | ||
377 | if (tps->dev->of_node) | ||
378 | config.of_node = pdata->of_node[i]; | ||
379 | |||
380 | rdev = regulator_register(®ulators[i], &config); | ||
381 | if (IS_ERR(rdev)) { | ||
382 | dev_err(tps->dev, "failed to register %s regulator\n", | ||
383 | pdev->name); | ||
384 | ret = PTR_ERR(rdev); | ||
385 | goto err_unregister_regulator; | ||
386 | } | ||
387 | |||
388 | /* Save regulator for cleanup */ | ||
389 | tps->rdev[i] = rdev; | ||
390 | } | ||
306 | return 0; | 391 | return 0; |
392 | |||
393 | err_unregister_regulator: | ||
394 | while (--i >= 0) | ||
395 | regulator_unregister(tps->rdev[i]); | ||
396 | |||
397 | return ret; | ||
307 | } | 398 | } |
308 | 399 | ||
309 | static int __devexit tps65217_regulator_remove(struct platform_device *pdev) | 400 | static int __devexit tps65217_regulator_remove(struct platform_device *pdev) |
310 | { | 401 | { |
311 | struct regulator_dev *rdev = platform_get_drvdata(pdev); | 402 | struct tps65217 *tps = platform_get_drvdata(pdev); |
403 | unsigned int i; | ||
404 | |||
405 | for (i = 0; i < TPS65217_NUM_REGULATOR; i++) | ||
406 | regulator_unregister(tps->rdev[i]); | ||
312 | 407 | ||
313 | platform_set_drvdata(pdev, NULL); | 408 | platform_set_drvdata(pdev, NULL); |
314 | regulator_unregister(rdev); | ||
315 | 409 | ||
316 | return 0; | 410 | return 0; |
317 | } | 411 | } |
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h index 12c06870829a..7cd83d826ed8 100644 --- a/include/linux/mfd/tps65217.h +++ b/include/linux/mfd/tps65217.h | |||
@@ -22,6 +22,9 @@ | |||
22 | #include <linux/regulator/driver.h> | 22 | #include <linux/regulator/driver.h> |
23 | #include <linux/regulator/machine.h> | 23 | #include <linux/regulator/machine.h> |
24 | 24 | ||
25 | /* TPS chip id list */ | ||
26 | #define TPS65217 0xF0 | ||
27 | |||
25 | /* I2C ID for TPS65217 part */ | 28 | /* I2C ID for TPS65217 part */ |
26 | #define TPS65217_I2C_ID 0x24 | 29 | #define TPS65217_I2C_ID 0x24 |
27 | 30 | ||
@@ -248,13 +251,11 @@ struct tps_info { | |||
248 | struct tps65217 { | 251 | struct tps65217 { |
249 | struct device *dev; | 252 | struct device *dev; |
250 | struct tps65217_board *pdata; | 253 | struct tps65217_board *pdata; |
254 | unsigned int id; | ||
251 | struct regulator_desc desc[TPS65217_NUM_REGULATOR]; | 255 | struct regulator_desc desc[TPS65217_NUM_REGULATOR]; |
252 | struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; | 256 | struct regulator_dev *rdev[TPS65217_NUM_REGULATOR]; |
253 | struct tps_info *info[TPS65217_NUM_REGULATOR]; | 257 | struct tps_info *info[TPS65217_NUM_REGULATOR]; |
254 | struct regmap *regmap; | 258 | struct regmap *regmap; |
255 | |||
256 | /* Client devices */ | ||
257 | struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR]; | ||
258 | }; | 259 | }; |
259 | 260 | ||
260 | static inline struct tps65217 *dev_to_tps65217(struct device *dev) | 261 | static inline struct tps65217 *dev_to_tps65217(struct device *dev) |
@@ -262,6 +263,11 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev) | |||
262 | return dev_get_drvdata(dev); | 263 | return dev_get_drvdata(dev); |
263 | } | 264 | } |
264 | 265 | ||
266 | static inline int tps65217_chip_id(struct tps65217 *tps65217) | ||
267 | { | ||
268 | return tps65217->id; | ||
269 | } | ||
270 | |||
265 | int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, | 271 | int tps65217_reg_read(struct tps65217 *tps, unsigned int reg, |
266 | unsigned int *val); | 272 | unsigned int *val); |
267 | int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, | 273 | int tps65217_reg_write(struct tps65217 *tps, unsigned int reg, |