diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/mfd/tps65217.c | 130 | ||||
| -rw-r--r-- | drivers/regulator/tps65217-regulator.c | 124 |
2 files changed, 152 insertions, 102 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 | } |
