| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Regulators driver for Marvell 88PM8607 |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2009 Marvell International Ltd. |
|---|
| 5 | 6 | * Haojian Zhuang <haojian.zhuang@marvell.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 9 | | - * published by the Free Software Foundation. |
|---|
| 10 | 7 | */ |
|---|
| 11 | 8 | #include <linux/kernel.h> |
|---|
| 12 | 9 | #include <linux/init.h> |
|---|
| 13 | 10 | #include <linux/err.h> |
|---|
| 14 | | -#include <linux/i2c.h> |
|---|
| 15 | 11 | #include <linux/of.h> |
|---|
| 16 | 12 | #include <linux/regulator/of_regulator.h> |
|---|
| 17 | 13 | #include <linux/platform_device.h> |
|---|
| .. | .. |
|---|
| 22 | 18 | |
|---|
| 23 | 19 | struct pm8607_regulator_info { |
|---|
| 24 | 20 | struct regulator_desc desc; |
|---|
| 25 | | - struct pm860x_chip *chip; |
|---|
| 26 | | - struct regulator_dev *regulator; |
|---|
| 27 | | - struct i2c_client *i2c; |
|---|
| 28 | | - struct i2c_client *i2c_8606; |
|---|
| 29 | 21 | |
|---|
| 30 | | - unsigned int *vol_table; |
|---|
| 31 | 22 | unsigned int *vol_suspend; |
|---|
| 32 | 23 | |
|---|
| 33 | 24 | int slope_double; |
|---|
| .. | .. |
|---|
| 210 | 201 | static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) |
|---|
| 211 | 202 | { |
|---|
| 212 | 203 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); |
|---|
| 213 | | - int ret = -EINVAL; |
|---|
| 204 | + int ret; |
|---|
| 214 | 205 | |
|---|
| 215 | | - if (info->vol_table && (index < rdev->desc->n_voltages)) { |
|---|
| 216 | | - ret = info->vol_table[index]; |
|---|
| 217 | | - if (info->slope_double) |
|---|
| 218 | | - ret <<= 1; |
|---|
| 219 | | - } |
|---|
| 206 | + ret = regulator_list_voltage_table(rdev, index); |
|---|
| 207 | + if (ret < 0) |
|---|
| 208 | + return ret; |
|---|
| 209 | + |
|---|
| 210 | + if (info->slope_double) |
|---|
| 211 | + ret <<= 1; |
|---|
| 212 | + |
|---|
| 220 | 213 | return ret; |
|---|
| 221 | 214 | } |
|---|
| 222 | 215 | |
|---|
| .. | .. |
|---|
| 239 | 232 | { \ |
|---|
| 240 | 233 | .desc = { \ |
|---|
| 241 | 234 | .name = "PREG", \ |
|---|
| 235 | + .of_match = of_match_ptr("PREG"), \ |
|---|
| 236 | + .regulators_node = of_match_ptr("regulators"), \ |
|---|
| 242 | 237 | .ops = &pm8606_preg_ops, \ |
|---|
| 243 | 238 | .type = REGULATOR_CURRENT, \ |
|---|
| 244 | 239 | .id = PM8606_ID_PREG, \ |
|---|
| .. | .. |
|---|
| 253 | 248 | { \ |
|---|
| 254 | 249 | .desc = { \ |
|---|
| 255 | 250 | .name = #vreg, \ |
|---|
| 251 | + .of_match = of_match_ptr(#vreg), \ |
|---|
| 252 | + .regulators_node = of_match_ptr("regulators"), \ |
|---|
| 256 | 253 | .ops = &pm8607_regulator_ops, \ |
|---|
| 257 | 254 | .type = REGULATOR_VOLTAGE, \ |
|---|
| 258 | 255 | .id = PM8607_ID_##vreg, \ |
|---|
| 259 | 256 | .owner = THIS_MODULE, \ |
|---|
| 257 | + .volt_table = vreg##_table, \ |
|---|
| 260 | 258 | .n_voltages = ARRAY_SIZE(vreg##_table), \ |
|---|
| 261 | 259 | .vsel_reg = PM8607_##vreg, \ |
|---|
| 262 | 260 | .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \ |
|---|
| .. | .. |
|---|
| 266 | 264 | .enable_mask = 1 << (ebit), \ |
|---|
| 267 | 265 | }, \ |
|---|
| 268 | 266 | .slope_double = (0), \ |
|---|
| 269 | | - .vol_table = (unsigned int *)&vreg##_table, \ |
|---|
| 270 | 267 | .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ |
|---|
| 271 | 268 | } |
|---|
| 272 | 269 | |
|---|
| .. | .. |
|---|
| 274 | 271 | { \ |
|---|
| 275 | 272 | .desc = { \ |
|---|
| 276 | 273 | .name = "LDO" #_id, \ |
|---|
| 274 | + .of_match = of_match_ptr("LDO" #_id), \ |
|---|
| 275 | + .regulators_node = of_match_ptr("regulators"), \ |
|---|
| 277 | 276 | .ops = &pm8607_regulator_ops, \ |
|---|
| 278 | 277 | .type = REGULATOR_VOLTAGE, \ |
|---|
| 279 | 278 | .id = PM8607_ID_LDO##_id, \ |
|---|
| 280 | 279 | .owner = THIS_MODULE, \ |
|---|
| 280 | + .volt_table = LDO##_id##_table, \ |
|---|
| 281 | 281 | .n_voltages = ARRAY_SIZE(LDO##_id##_table), \ |
|---|
| 282 | 282 | .vsel_reg = PM8607_##vreg, \ |
|---|
| 283 | 283 | .vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \ |
|---|
| .. | .. |
|---|
| 285 | 285 | .enable_mask = 1 << (ebit), \ |
|---|
| 286 | 286 | }, \ |
|---|
| 287 | 287 | .slope_double = (0), \ |
|---|
| 288 | | - .vol_table = (unsigned int *)&LDO##_id##_table, \ |
|---|
| 289 | 288 | .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \ |
|---|
| 290 | 289 | } |
|---|
| 291 | 290 | |
|---|
| .. | .. |
|---|
| 313 | 312 | PM8606_PREG(PREREGULATORB, 5), |
|---|
| 314 | 313 | }; |
|---|
| 315 | 314 | |
|---|
| 316 | | -#ifdef CONFIG_OF |
|---|
| 317 | | -static int pm8607_regulator_dt_init(struct platform_device *pdev, |
|---|
| 318 | | - struct pm8607_regulator_info *info, |
|---|
| 319 | | - struct regulator_config *config) |
|---|
| 320 | | -{ |
|---|
| 321 | | - struct device_node *nproot, *np; |
|---|
| 322 | | - nproot = pdev->dev.parent->of_node; |
|---|
| 323 | | - if (!nproot) |
|---|
| 324 | | - return -ENODEV; |
|---|
| 325 | | - nproot = of_get_child_by_name(nproot, "regulators"); |
|---|
| 326 | | - if (!nproot) { |
|---|
| 327 | | - dev_err(&pdev->dev, "failed to find regulators node\n"); |
|---|
| 328 | | - return -ENODEV; |
|---|
| 329 | | - } |
|---|
| 330 | | - for_each_child_of_node(nproot, np) { |
|---|
| 331 | | - if (!of_node_cmp(np->name, info->desc.name)) { |
|---|
| 332 | | - config->init_data = |
|---|
| 333 | | - of_get_regulator_init_data(&pdev->dev, np, |
|---|
| 334 | | - &info->desc); |
|---|
| 335 | | - config->of_node = np; |
|---|
| 336 | | - break; |
|---|
| 337 | | - } |
|---|
| 338 | | - } |
|---|
| 339 | | - of_node_put(nproot); |
|---|
| 340 | | - return 0; |
|---|
| 341 | | -} |
|---|
| 342 | | -#else |
|---|
| 343 | | -#define pm8607_regulator_dt_init(x, y, z) (-1) |
|---|
| 344 | | -#endif |
|---|
| 345 | | - |
|---|
| 346 | 315 | static int pm8607_regulator_probe(struct platform_device *pdev) |
|---|
| 347 | 316 | { |
|---|
| 348 | 317 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
|---|
| 349 | 318 | struct pm8607_regulator_info *info = NULL; |
|---|
| 350 | 319 | struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev); |
|---|
| 351 | 320 | struct regulator_config config = { }; |
|---|
| 321 | + struct regulator_dev *rdev; |
|---|
| 352 | 322 | struct resource *res; |
|---|
| 353 | 323 | int i; |
|---|
| 354 | 324 | |
|---|
| .. | .. |
|---|
| 371 | 341 | /* i is used to check regulator ID */ |
|---|
| 372 | 342 | i = -1; |
|---|
| 373 | 343 | } |
|---|
| 374 | | - info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; |
|---|
| 375 | | - info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion : |
|---|
| 376 | | - chip->client; |
|---|
| 377 | | - info->chip = chip; |
|---|
| 378 | 344 | |
|---|
| 379 | 345 | /* check DVC ramp slope double */ |
|---|
| 380 | | - if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double) |
|---|
| 346 | + if ((i == PM8607_ID_BUCK3) && chip->buck3_double) |
|---|
| 381 | 347 | info->slope_double = 1; |
|---|
| 382 | 348 | |
|---|
| 383 | | - config.dev = &pdev->dev; |
|---|
| 349 | + config.dev = chip->dev; |
|---|
| 384 | 350 | config.driver_data = info; |
|---|
| 385 | 351 | |
|---|
| 386 | | - if (pm8607_regulator_dt_init(pdev, info, &config)) |
|---|
| 387 | | - if (pdata) |
|---|
| 388 | | - config.init_data = pdata; |
|---|
| 352 | + if (pdata) |
|---|
| 353 | + config.init_data = pdata; |
|---|
| 389 | 354 | |
|---|
| 390 | 355 | if (chip->id == CHIP_PM8607) |
|---|
| 391 | 356 | config.regmap = chip->regmap; |
|---|
| 392 | 357 | else |
|---|
| 393 | 358 | config.regmap = chip->regmap_companion; |
|---|
| 394 | 359 | |
|---|
| 395 | | - info->regulator = devm_regulator_register(&pdev->dev, &info->desc, |
|---|
| 396 | | - &config); |
|---|
| 397 | | - if (IS_ERR(info->regulator)) { |
|---|
| 360 | + rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); |
|---|
| 361 | + if (IS_ERR(rdev)) { |
|---|
| 398 | 362 | dev_err(&pdev->dev, "failed to register regulator %s\n", |
|---|
| 399 | 363 | info->desc.name); |
|---|
| 400 | | - return PTR_ERR(info->regulator); |
|---|
| 364 | + return PTR_ERR(rdev); |
|---|
| 401 | 365 | } |
|---|
| 402 | 366 | |
|---|
| 403 | 367 | platform_set_drvdata(pdev, info); |
|---|