| .. | .. |
|---|
| 1 | | -/* |
|---|
| 2 | | -* Regulator driver for DA9055 PMIC |
|---|
| 3 | | -* |
|---|
| 4 | | -* Copyright(c) 2012 Dialog Semiconductor Ltd. |
|---|
| 5 | | -* |
|---|
| 6 | | -* Author: David Dajun Chen <dchen@diasemi.com> |
|---|
| 7 | | -* |
|---|
| 8 | | -* This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | -* it under the terms of the GNU General Public License as published by |
|---|
| 10 | | -* the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | -* (at your option) any later version. |
|---|
| 12 | | -* |
|---|
| 13 | | -*/ |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
|---|
| 2 | +// |
|---|
| 3 | +// Regulator driver for DA9055 PMIC |
|---|
| 4 | +// |
|---|
| 5 | +// Copyright(c) 2012 Dialog Semiconductor Ltd. |
|---|
| 6 | +// |
|---|
| 7 | +// Author: David Dajun Chen <dchen@diasemi.com> |
|---|
| 14 | 8 | |
|---|
| 15 | 9 | #include <linux/module.h> |
|---|
| 16 | 10 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 48 | 42 | #define DA9055_ID_LDO6 7 |
|---|
| 49 | 43 | |
|---|
| 50 | 44 | /* DA9055 BUCK current limit */ |
|---|
| 51 | | -static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 }; |
|---|
| 45 | +static const unsigned int da9055_current_limits[] = { |
|---|
| 46 | + 500000, 600000, 700000, 800000 |
|---|
| 47 | +}; |
|---|
| 52 | 48 | |
|---|
| 53 | 49 | struct da9055_conf_reg { |
|---|
| 54 | 50 | int reg; |
|---|
| .. | .. |
|---|
| 167 | 163 | return da9055_reg_update(regulator->da9055, volt.reg_b, |
|---|
| 168 | 164 | 1 << volt.sl_shift, |
|---|
| 169 | 165 | val << volt.sl_shift); |
|---|
| 170 | | -} |
|---|
| 171 | | - |
|---|
| 172 | | -static int da9055_buck_get_current_limit(struct regulator_dev *rdev) |
|---|
| 173 | | -{ |
|---|
| 174 | | - struct da9055_regulator *regulator = rdev_get_drvdata(rdev); |
|---|
| 175 | | - struct da9055_regulator_info *info = regulator->info; |
|---|
| 176 | | - int ret; |
|---|
| 177 | | - |
|---|
| 178 | | - ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM); |
|---|
| 179 | | - if (ret < 0) |
|---|
| 180 | | - return ret; |
|---|
| 181 | | - |
|---|
| 182 | | - ret &= info->mode.mask; |
|---|
| 183 | | - return da9055_current_limits[ret >> info->mode.shift]; |
|---|
| 184 | | -} |
|---|
| 185 | | - |
|---|
| 186 | | -static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA, |
|---|
| 187 | | - int max_uA) |
|---|
| 188 | | -{ |
|---|
| 189 | | - struct da9055_regulator *regulator = rdev_get_drvdata(rdev); |
|---|
| 190 | | - struct da9055_regulator_info *info = regulator->info; |
|---|
| 191 | | - int i; |
|---|
| 192 | | - |
|---|
| 193 | | - for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) { |
|---|
| 194 | | - if ((min_uA <= da9055_current_limits[i]) && |
|---|
| 195 | | - (da9055_current_limits[i] <= max_uA)) |
|---|
| 196 | | - return da9055_reg_update(regulator->da9055, |
|---|
| 197 | | - DA9055_REG_BUCK_LIM, |
|---|
| 198 | | - info->mode.mask, |
|---|
| 199 | | - i << info->mode.shift); |
|---|
| 200 | | - } |
|---|
| 201 | | - |
|---|
| 202 | | - return -EINVAL; |
|---|
| 203 | 166 | } |
|---|
| 204 | 167 | |
|---|
| 205 | 168 | static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev) |
|---|
| .. | .. |
|---|
| 329 | 292 | .get_mode = da9055_buck_get_mode, |
|---|
| 330 | 293 | .set_mode = da9055_buck_set_mode, |
|---|
| 331 | 294 | |
|---|
| 332 | | - .get_current_limit = da9055_buck_get_current_limit, |
|---|
| 333 | | - .set_current_limit = da9055_buck_set_current_limit, |
|---|
| 295 | + .get_current_limit = regulator_get_current_limit_regmap, |
|---|
| 296 | + .set_current_limit = regulator_set_current_limit_regmap, |
|---|
| 334 | 297 | |
|---|
| 335 | 298 | .get_voltage_sel = da9055_regulator_get_voltage_sel, |
|---|
| 336 | 299 | .set_voltage_sel = da9055_regulator_set_voltage_sel, |
|---|
| .. | .. |
|---|
| 369 | 332 | {\ |
|---|
| 370 | 333 | .reg_desc = {\ |
|---|
| 371 | 334 | .name = #_id,\ |
|---|
| 335 | + .of_match = of_match_ptr(#_id),\ |
|---|
| 336 | + .regulators_node = of_match_ptr("regulators"),\ |
|---|
| 372 | 337 | .ops = &da9055_ldo_ops,\ |
|---|
| 373 | 338 | .type = REGULATOR_VOLTAGE,\ |
|---|
| 374 | 339 | .id = DA9055_ID_##_id,\ |
|---|
| .. | .. |
|---|
| 397 | 362 | {\ |
|---|
| 398 | 363 | .reg_desc = {\ |
|---|
| 399 | 364 | .name = #_id,\ |
|---|
| 365 | + .of_match = of_match_ptr(#_id),\ |
|---|
| 366 | + .regulators_node = of_match_ptr("regulators"),\ |
|---|
| 400 | 367 | .ops = &da9055_buck_ops,\ |
|---|
| 401 | 368 | .type = REGULATOR_VOLTAGE,\ |
|---|
| 402 | 369 | .id = DA9055_ID_##_id,\ |
|---|
| .. | .. |
|---|
| 407 | 374 | .uV_step = (step) * 1000,\ |
|---|
| 408 | 375 | .linear_min_sel = (voffset),\ |
|---|
| 409 | 376 | .owner = THIS_MODULE,\ |
|---|
| 377 | + .curr_table = da9055_current_limits,\ |
|---|
| 378 | + .n_current_limits = ARRAY_SIZE(da9055_current_limits),\ |
|---|
| 379 | + .csel_reg = DA9055_REG_BUCK_LIM,\ |
|---|
| 380 | + .csel_mask = (mbits),\ |
|---|
| 410 | 381 | },\ |
|---|
| 411 | 382 | .conf = {\ |
|---|
| 412 | 383 | .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \ |
|---|
| .. | .. |
|---|
| 457 | 428 | int gpio_mux = pdata->gpio_ren[id]; |
|---|
| 458 | 429 | |
|---|
| 459 | 430 | config->ena_gpiod = pdata->ena_gpiods[id]; |
|---|
| 460 | | - config->ena_gpio_invert = 1; |
|---|
| 461 | 431 | |
|---|
| 462 | 432 | /* |
|---|
| 463 | 433 | * GPI pin is muxed with regulator to control the |
|---|
| .. | .. |
|---|
| 535 | 505 | return NULL; |
|---|
| 536 | 506 | } |
|---|
| 537 | 507 | |
|---|
| 538 | | -#ifdef CONFIG_OF |
|---|
| 539 | | -static struct of_regulator_match da9055_reg_matches[] = { |
|---|
| 540 | | - { .name = "BUCK1", }, |
|---|
| 541 | | - { .name = "BUCK2", }, |
|---|
| 542 | | - { .name = "LDO1", }, |
|---|
| 543 | | - { .name = "LDO2", }, |
|---|
| 544 | | - { .name = "LDO3", }, |
|---|
| 545 | | - { .name = "LDO4", }, |
|---|
| 546 | | - { .name = "LDO5", }, |
|---|
| 547 | | - { .name = "LDO6", }, |
|---|
| 548 | | -}; |
|---|
| 549 | | - |
|---|
| 550 | | -static int da9055_regulator_dt_init(struct platform_device *pdev, |
|---|
| 551 | | - struct da9055_regulator *regulator, |
|---|
| 552 | | - struct regulator_config *config, |
|---|
| 553 | | - int regid) |
|---|
| 554 | | -{ |
|---|
| 555 | | - struct device_node *nproot, *np; |
|---|
| 556 | | - int ret; |
|---|
| 557 | | - |
|---|
| 558 | | - nproot = of_node_get(pdev->dev.parent->of_node); |
|---|
| 559 | | - if (!nproot) |
|---|
| 560 | | - return -ENODEV; |
|---|
| 561 | | - |
|---|
| 562 | | - np = of_get_child_by_name(nproot, "regulators"); |
|---|
| 563 | | - if (!np) |
|---|
| 564 | | - return -ENODEV; |
|---|
| 565 | | - |
|---|
| 566 | | - ret = of_regulator_match(&pdev->dev, np, &da9055_reg_matches[regid], 1); |
|---|
| 567 | | - of_node_put(nproot); |
|---|
| 568 | | - if (ret < 0) { |
|---|
| 569 | | - dev_err(&pdev->dev, "Error matching regulator: %d\n", ret); |
|---|
| 570 | | - return ret; |
|---|
| 571 | | - } |
|---|
| 572 | | - |
|---|
| 573 | | - config->init_data = da9055_reg_matches[regid].init_data; |
|---|
| 574 | | - config->of_node = da9055_reg_matches[regid].of_node; |
|---|
| 575 | | - |
|---|
| 576 | | - if (!config->of_node) |
|---|
| 577 | | - return -ENODEV; |
|---|
| 578 | | - |
|---|
| 579 | | - return 0; |
|---|
| 580 | | -} |
|---|
| 581 | | -#else |
|---|
| 582 | | -static inline int da9055_regulator_dt_init(struct platform_device *pdev, |
|---|
| 583 | | - struct da9055_regulator *regulator, |
|---|
| 584 | | - struct regulator_config *config, |
|---|
| 585 | | - int regid) |
|---|
| 586 | | -{ |
|---|
| 587 | | - return -ENODEV; |
|---|
| 588 | | -} |
|---|
| 589 | | -#endif /* CONFIG_OF */ |
|---|
| 590 | | - |
|---|
| 591 | 508 | static int da9055_regulator_probe(struct platform_device *pdev) |
|---|
| 592 | 509 | { |
|---|
| 593 | 510 | struct regulator_config config = { }; |
|---|
| .. | .. |
|---|
| 608 | 525 | } |
|---|
| 609 | 526 | |
|---|
| 610 | 527 | regulator->da9055 = da9055; |
|---|
| 611 | | - config.dev = &pdev->dev; |
|---|
| 528 | + config.dev = da9055->dev; |
|---|
| 612 | 529 | config.driver_data = regulator; |
|---|
| 613 | 530 | config.regmap = da9055->regmap; |
|---|
| 614 | 531 | |
|---|
| 615 | | - if (pdata && pdata->regulators) { |
|---|
| 532 | + if (pdata) |
|---|
| 616 | 533 | config.init_data = pdata->regulators[pdev->id]; |
|---|
| 617 | | - } else { |
|---|
| 618 | | - ret = da9055_regulator_dt_init(pdev, regulator, &config, |
|---|
| 619 | | - pdev->id); |
|---|
| 620 | | - if (ret < 0) |
|---|
| 621 | | - return ret; |
|---|
| 622 | | - } |
|---|
| 623 | 534 | |
|---|
| 624 | 535 | ret = da9055_gpio_init(regulator, &config, pdata, pdev->id); |
|---|
| 625 | 536 | if (ret < 0) |
|---|