diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/regulator/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
| -rw-r--r-- | drivers/regulator/s5m8767.c | 171 | ||||
| -rw-r--r-- | drivers/regulator/st-pwm.c | 190 | ||||
| -rw-r--r-- | drivers/regulator/ti-abb-regulator.c | 140 | ||||
| -rw-r--r-- | drivers/regulator/tps51632-regulator.c | 8 | ||||
| -rw-r--r-- | drivers/regulator/tps62360-regulator.c | 9 | ||||
| -rw-r--r-- | drivers/regulator/tps6507x-regulator.c | 29 | ||||
| -rw-r--r-- | drivers/regulator/tps65090-regulator.c | 13 | ||||
| -rw-r--r-- | drivers/regulator/tps65217-regulator.c | 17 |
10 files changed, 400 insertions, 184 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index e5e4017b1011..8f3866c44a3f 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
| @@ -448,6 +448,12 @@ config REGULATOR_S5M8767 | |||
| 448 | via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and | 448 | via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and |
| 449 | supports DVS mode with 8bits of output voltage control. | 449 | supports DVS mode with 8bits of output voltage control. |
| 450 | 450 | ||
| 451 | config REGULATOR_ST_PWM | ||
| 452 | tristate "STMicroelectronics PWM voltage regulator" | ||
| 453 | depends on ARCH_STI | ||
| 454 | help | ||
| 455 | This driver supports ST's PWM controlled voltage regulators. | ||
| 456 | |||
| 451 | config REGULATOR_TI_ABB | 457 | config REGULATOR_TI_ABB |
| 452 | tristate "TI Adaptive Body Bias on-chip LDO" | 458 | tristate "TI Adaptive Body Bias on-chip LDO" |
| 453 | depends on ARCH_OMAP | 459 | depends on ARCH_OMAP |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index c3416728c14d..0cfca37941ec 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
| @@ -61,6 +61,7 @@ obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o | |||
| 61 | obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o | 61 | obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o |
| 62 | obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o | 62 | obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o |
| 63 | obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o | 63 | obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o |
| 64 | obj-$(CONFIG_REGULATOR_ST_PWM) += st-pwm.o | ||
| 64 | obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o | 65 | obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o |
| 65 | obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o | 66 | obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o |
| 66 | obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o | 67 | obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o |
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index d958dfa05125..f05badabd69e 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c | |||
| @@ -11,11 +11,8 @@ | |||
| 11 | * | 11 | * |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/bug.h> | ||
| 15 | #include <linux/err.h> | 14 | #include <linux/err.h> |
| 16 | #include <linux/gpio.h> | ||
| 17 | #include <linux/of_gpio.h> | 15 | #include <linux/of_gpio.h> |
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 20 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 21 | #include <linux/regulator/driver.h> | 18 | #include <linux/regulator/driver.h> |
| @@ -170,12 +167,11 @@ static unsigned int s5m8767_opmode_reg[][4] = { | |||
| 170 | {0x0, 0x3, 0x1, 0x1}, /* BUCK9 */ | 167 | {0x0, 0x3, 0x1, 0x1}, /* BUCK9 */ |
| 171 | }; | 168 | }; |
| 172 | 169 | ||
| 173 | static int s5m8767_get_register(struct regulator_dev *rdev, int *reg, | 170 | static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id, |
| 174 | int *enable_ctrl) | 171 | int *reg, int *enable_ctrl) |
| 175 | { | 172 | { |
| 176 | int i, reg_id = rdev_get_id(rdev); | 173 | int i; |
| 177 | unsigned int mode; | 174 | unsigned int mode; |
| 178 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | ||
| 179 | 175 | ||
| 180 | switch (reg_id) { | 176 | switch (reg_id) { |
| 181 | case S5M8767_LDO1 ... S5M8767_LDO2: | 177 | case S5M8767_LDO1 ... S5M8767_LDO2: |
| @@ -214,53 +210,6 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg, | |||
| 214 | return 0; | 210 | return 0; |
| 215 | } | 211 | } |
| 216 | 212 | ||
| 217 | static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) | ||
| 218 | { | ||
| 219 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | ||
| 220 | int ret, reg; | ||
| 221 | int enable_ctrl; | ||
| 222 | unsigned int val; | ||
| 223 | |||
| 224 | ret = s5m8767_get_register(rdev, ®, &enable_ctrl); | ||
| 225 | if (ret == -EINVAL) | ||
| 226 | return 1; | ||
| 227 | else if (ret) | ||
| 228 | return ret; | ||
| 229 | |||
| 230 | ret = regmap_read(s5m8767->iodev->regmap_pmic, reg, &val); | ||
| 231 | if (ret) | ||
| 232 | return ret; | ||
| 233 | |||
| 234 | return (val & S5M8767_ENCTRL_MASK) == enable_ctrl; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int s5m8767_reg_enable(struct regulator_dev *rdev) | ||
| 238 | { | ||
| 239 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | ||
| 240 | int ret, reg; | ||
| 241 | int enable_ctrl; | ||
| 242 | |||
| 243 | ret = s5m8767_get_register(rdev, ®, &enable_ctrl); | ||
| 244 | if (ret) | ||
| 245 | return ret; | ||
| 246 | |||
| 247 | return regmap_update_bits(s5m8767->iodev->regmap_pmic, reg, | ||
| 248 | S5M8767_ENCTRL_MASK, enable_ctrl); | ||
| 249 | } | ||
| 250 | |||
| 251 | static int s5m8767_reg_disable(struct regulator_dev *rdev) | ||
| 252 | { | ||
| 253 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | ||
| 254 | int ret, reg, enable_ctrl; | ||
| 255 | |||
| 256 | ret = s5m8767_get_register(rdev, ®, &enable_ctrl); | ||
| 257 | if (ret) | ||
| 258 | return ret; | ||
| 259 | |||
| 260 | return regmap_update_bits(s5m8767->iodev->regmap_pmic, reg, | ||
| 261 | S5M8767_ENCTRL_MASK, ~S5M8767_ENCTRL_MASK); | ||
| 262 | } | ||
| 263 | |||
| 264 | static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767) | 213 | static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767) |
| 265 | { | 214 | { |
| 266 | int reg; | 215 | int reg; |
| @@ -410,9 +359,9 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, | |||
| 410 | 359 | ||
| 411 | static struct regulator_ops s5m8767_ops = { | 360 | static struct regulator_ops s5m8767_ops = { |
| 412 | .list_voltage = regulator_list_voltage_linear, | 361 | .list_voltage = regulator_list_voltage_linear, |
| 413 | .is_enabled = s5m8767_reg_is_enabled, | 362 | .is_enabled = regulator_is_enabled_regmap, |
| 414 | .enable = s5m8767_reg_enable, | 363 | .enable = regulator_enable_regmap, |
| 415 | .disable = s5m8767_reg_disable, | 364 | .disable = regulator_disable_regmap, |
| 416 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 365 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| 417 | .set_voltage_sel = s5m8767_set_voltage_sel, | 366 | .set_voltage_sel = s5m8767_set_voltage_sel, |
| 418 | .set_voltage_time_sel = s5m8767_set_voltage_time_sel, | 367 | .set_voltage_time_sel = s5m8767_set_voltage_time_sel, |
| @@ -420,9 +369,9 @@ static struct regulator_ops s5m8767_ops = { | |||
| 420 | 369 | ||
| 421 | static struct regulator_ops s5m8767_buck78_ops = { | 370 | static struct regulator_ops s5m8767_buck78_ops = { |
| 422 | .list_voltage = regulator_list_voltage_linear, | 371 | .list_voltage = regulator_list_voltage_linear, |
| 423 | .is_enabled = s5m8767_reg_is_enabled, | 372 | .is_enabled = regulator_is_enabled_regmap, |
| 424 | .enable = s5m8767_reg_enable, | 373 | .enable = regulator_enable_regmap, |
| 425 | .disable = s5m8767_reg_disable, | 374 | .disable = regulator_disable_regmap, |
| 426 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 375 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
| 427 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 376 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| 428 | }; | 377 | }; |
| @@ -483,6 +432,66 @@ static struct regulator_desc regulators[] = { | |||
| 483 | s5m8767_regulator_desc(BUCK9), | 432 | s5m8767_regulator_desc(BUCK9), |
| 484 | }; | 433 | }; |
| 485 | 434 | ||
| 435 | /* | ||
| 436 | * Enable GPIO control over BUCK9 in regulator_config for that regulator. | ||
| 437 | */ | ||
| 438 | static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767, | ||
| 439 | struct sec_regulator_data *rdata, | ||
| 440 | struct regulator_config *config) | ||
| 441 | { | ||
| 442 | int i, mode = 0; | ||
| 443 | |||
| 444 | if (rdata->id != S5M8767_BUCK9) | ||
| 445 | return; | ||
| 446 | |||
| 447 | /* Check if opmode for regulator matches S5M8767_ENCTRL_USE_GPIO */ | ||
| 448 | for (i = 0; i < s5m8767->num_regulators; i++) { | ||
| 449 | const struct sec_opmode_data *opmode = &s5m8767->opmode[i]; | ||
| 450 | if (opmode->id == rdata->id) { | ||
| 451 | mode = s5m8767_opmode_reg[rdata->id][opmode->mode]; | ||
| 452 | break; | ||
| 453 | } | ||
| 454 | } | ||
| 455 | if (mode != S5M8767_ENCTRL_USE_GPIO) { | ||
| 456 | dev_warn(s5m8767->dev, | ||
| 457 | "ext-control for %s: mismatched op_mode (%x), ignoring\n", | ||
| 458 | rdata->reg_node->name, mode); | ||
| 459 | return; | ||
| 460 | } | ||
| 461 | |||
| 462 | if (!gpio_is_valid(rdata->ext_control_gpio)) { | ||
| 463 | dev_warn(s5m8767->dev, | ||
| 464 | "ext-control for %s: GPIO not valid, ignoring\n", | ||
| 465 | rdata->reg_node->name); | ||
| 466 | return; | ||
| 467 | } | ||
| 468 | |||
| 469 | config->ena_gpio = rdata->ext_control_gpio; | ||
| 470 | config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH; | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | ||
| 474 | * Turn on GPIO control over BUCK9. | ||
| 475 | */ | ||
| 476 | static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767, | ||
| 477 | struct regulator_dev *rdev) | ||
| 478 | { | ||
| 479 | int id = rdev_get_id(rdev); | ||
| 480 | int ret, reg, enable_ctrl; | ||
| 481 | |||
| 482 | if (id != S5M8767_BUCK9) | ||
| 483 | return -EINVAL; | ||
| 484 | |||
| 485 | ret = s5m8767_get_register(s5m8767, id, ®, &enable_ctrl); | ||
| 486 | if (ret) | ||
| 487 | return ret; | ||
| 488 | |||
| 489 | return regmap_update_bits(s5m8767->iodev->regmap_pmic, | ||
| 490 | reg, S5M8767_ENCTRL_MASK, | ||
| 491 | S5M8767_ENCTRL_USE_GPIO << S5M8767_ENCTRL_SHIFT); | ||
| 492 | } | ||
| 493 | |||
| 494 | |||
| 486 | #ifdef CONFIG_OF | 495 | #ifdef CONFIG_OF |
| 487 | static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev, | 496 | static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev, |
| 488 | struct sec_platform_data *pdata, | 497 | struct sec_platform_data *pdata, |
| @@ -520,6 +529,16 @@ static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev, | |||
| 520 | return 0; | 529 | return 0; |
| 521 | } | 530 | } |
| 522 | 531 | ||
| 532 | static void s5m8767_pmic_dt_parse_ext_control_gpio(struct sec_pmic_dev *iodev, | ||
| 533 | struct sec_regulator_data *rdata, | ||
| 534 | struct device_node *reg_np) | ||
| 535 | { | ||
| 536 | rdata->ext_control_gpio = of_get_named_gpio(reg_np, | ||
| 537 | "s5m8767,pmic-ext-control-gpios", 0); | ||
| 538 | if (!gpio_is_valid(rdata->ext_control_gpio)) | ||
| 539 | rdata->ext_control_gpio = 0; | ||
| 540 | } | ||
| 541 | |||
| 523 | static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, | 542 | static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, |
| 524 | struct sec_platform_data *pdata) | 543 | struct sec_platform_data *pdata) |
| 525 | { | 544 | { |
| @@ -546,19 +565,13 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, | |||
| 546 | 565 | ||
| 547 | rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * | 566 | rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * |
| 548 | pdata->num_regulators, GFP_KERNEL); | 567 | pdata->num_regulators, GFP_KERNEL); |
| 549 | if (!rdata) { | 568 | if (!rdata) |
| 550 | dev_err(iodev->dev, | ||
| 551 | "could not allocate memory for regulator data\n"); | ||
| 552 | return -ENOMEM; | 569 | return -ENOMEM; |
| 553 | } | ||
| 554 | 570 | ||
| 555 | rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) * | 571 | rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) * |
| 556 | pdata->num_regulators, GFP_KERNEL); | 572 | pdata->num_regulators, GFP_KERNEL); |
| 557 | if (!rmode) { | 573 | if (!rmode) |
| 558 | dev_err(iodev->dev, | ||
| 559 | "could not allocate memory for regulator mode\n"); | ||
| 560 | return -ENOMEM; | 574 | return -ENOMEM; |
| 561 | } | ||
| 562 | 575 | ||
| 563 | pdata->regulators = rdata; | 576 | pdata->regulators = rdata; |
| 564 | pdata->opmode = rmode; | 577 | pdata->opmode = rmode; |
| @@ -574,6 +587,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, | |||
| 574 | continue; | 587 | continue; |
| 575 | } | 588 | } |
| 576 | 589 | ||
| 590 | s5m8767_pmic_dt_parse_ext_control_gpio(iodev, rdata, reg_np); | ||
| 591 | |||
| 577 | rdata->id = i; | 592 | rdata->id = i; |
| 578 | rdata->initdata = of_get_regulator_init_data( | 593 | rdata->initdata = of_get_regulator_init_data( |
| 579 | &pdev->dev, reg_np); | 594 | &pdev->dev, reg_np); |
| @@ -922,6 +937,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
| 922 | for (i = 0; i < pdata->num_regulators; i++) { | 937 | for (i = 0; i < pdata->num_regulators; i++) { |
| 923 | const struct sec_voltage_desc *desc; | 938 | const struct sec_voltage_desc *desc; |
| 924 | int id = pdata->regulators[i].id; | 939 | int id = pdata->regulators[i].id; |
| 940 | int enable_reg, enable_val; | ||
| 925 | 941 | ||
| 926 | desc = reg_voltage_map[id]; | 942 | desc = reg_voltage_map[id]; |
| 927 | if (desc) { | 943 | if (desc) { |
| @@ -935,6 +951,12 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
| 935 | regulators[id].vsel_mask = 0x3f; | 951 | regulators[id].vsel_mask = 0x3f; |
| 936 | else | 952 | else |
| 937 | regulators[id].vsel_mask = 0xff; | 953 | regulators[id].vsel_mask = 0xff; |
| 954 | |||
| 955 | s5m8767_get_register(s5m8767, id, &enable_reg, | ||
| 956 | &enable_val); | ||
| 957 | regulators[id].enable_reg = enable_reg; | ||
| 958 | regulators[id].enable_mask = S5M8767_ENCTRL_MASK; | ||
| 959 | regulators[id].enable_val = enable_val; | ||
| 938 | } | 960 | } |
| 939 | 961 | ||
| 940 | config.dev = s5m8767->dev; | 962 | config.dev = s5m8767->dev; |
| @@ -942,6 +964,9 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
| 942 | config.driver_data = s5m8767; | 964 | config.driver_data = s5m8767; |
| 943 | config.regmap = iodev->regmap_pmic; | 965 | config.regmap = iodev->regmap_pmic; |
| 944 | config.of_node = pdata->regulators[i].reg_node; | 966 | config.of_node = pdata->regulators[i].reg_node; |
| 967 | if (pdata->regulators[i].ext_control_gpio) | ||
| 968 | s5m8767_regulator_config_ext_control(s5m8767, | ||
| 969 | &pdata->regulators[i], &config); | ||
| 945 | 970 | ||
| 946 | rdev[i] = devm_regulator_register(&pdev->dev, ®ulators[id], | 971 | rdev[i] = devm_regulator_register(&pdev->dev, ®ulators[id], |
| 947 | &config); | 972 | &config); |
| @@ -951,6 +976,16 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
| 951 | id); | 976 | id); |
| 952 | return ret; | 977 | return ret; |
| 953 | } | 978 | } |
| 979 | |||
| 980 | if (pdata->regulators[i].ext_control_gpio) { | ||
| 981 | ret = s5m8767_enable_ext_control(s5m8767, rdev[i]); | ||
| 982 | if (ret < 0) { | ||
| 983 | dev_err(s5m8767->dev, | ||
| 984 | "failed to enable gpio control over %s: %d\n", | ||
| 985 | rdev[i]->desc->name, ret); | ||
| 986 | return ret; | ||
| 987 | } | ||
| 988 | } | ||
| 954 | } | 989 | } |
| 955 | 990 | ||
| 956 | return 0; | 991 | return 0; |
diff --git a/drivers/regulator/st-pwm.c b/drivers/regulator/st-pwm.c new file mode 100644 index 000000000000..e367af1c5f9d --- /dev/null +++ b/drivers/regulator/st-pwm.c | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /* | ||
| 2 | * Regulator driver for ST's PWM Regulators | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 - STMicroelectronics Inc. | ||
| 5 | * | ||
| 6 | * Author: Lee Jones <lee.jones@linaro.org> | ||
| 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 version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/regulator/driver.h> | ||
| 17 | #include <linux/regulator/machine.h> | ||
| 18 | #include <linux/regulator/of_regulator.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_device.h> | ||
| 21 | #include <linux/pwm.h> | ||
| 22 | |||
| 23 | #define ST_PWM_REG_PERIOD 8448 | ||
| 24 | |||
| 25 | struct st_pwm_regulator_pdata { | ||
| 26 | const struct regulator_desc *desc; | ||
| 27 | struct st_pwm_voltages *duty_cycle_table; | ||
| 28 | }; | ||
| 29 | |||
| 30 | struct st_pwm_regulator_data { | ||
| 31 | const struct st_pwm_regulator_pdata *pdata; | ||
| 32 | struct pwm_device *pwm; | ||
| 33 | bool enabled; | ||
| 34 | int state; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct st_pwm_voltages { | ||
| 38 | unsigned int uV; | ||
| 39 | unsigned int dutycycle; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static int st_pwm_regulator_get_voltage_sel(struct regulator_dev *dev) | ||
| 43 | { | ||
| 44 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 45 | |||
| 46 | return drvdata->state; | ||
| 47 | } | ||
| 48 | |||
| 49 | static int st_pwm_regulator_set_voltage_sel(struct regulator_dev *dev, | ||
| 50 | unsigned selector) | ||
| 51 | { | ||
| 52 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 53 | int dutycycle; | ||
| 54 | int ret; | ||
| 55 | |||
| 56 | dutycycle = (ST_PWM_REG_PERIOD / 100) * | ||
| 57 | drvdata->pdata->duty_cycle_table[selector].dutycycle; | ||
| 58 | |||
| 59 | ret = pwm_config(drvdata->pwm, dutycycle, ST_PWM_REG_PERIOD); | ||
| 60 | if (ret) { | ||
| 61 | dev_err(&dev->dev, "Failed to configure PWM\n"); | ||
| 62 | return ret; | ||
| 63 | } | ||
| 64 | |||
| 65 | drvdata->state = selector; | ||
| 66 | |||
| 67 | if (!drvdata->enabled) { | ||
| 68 | ret = pwm_enable(drvdata->pwm); | ||
| 69 | if (ret) { | ||
| 70 | dev_err(&dev->dev, "Failed to enable PWM\n"); | ||
| 71 | return ret; | ||
| 72 | } | ||
| 73 | drvdata->enabled = true; | ||
| 74 | } | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int st_pwm_regulator_list_voltage(struct regulator_dev *dev, | ||
| 80 | unsigned selector) | ||
| 81 | { | ||
| 82 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
| 83 | |||
| 84 | if (selector >= dev->desc->n_voltages) | ||
| 85 | return -EINVAL; | ||
| 86 | |||
| 87 | return drvdata->pdata->duty_cycle_table[selector].uV; | ||
| 88 | } | ||
| 89 | |||
| 90 | static struct regulator_ops st_pwm_regulator_voltage_ops = { | ||
| 91 | .set_voltage_sel = st_pwm_regulator_set_voltage_sel, | ||
| 92 | .get_voltage_sel = st_pwm_regulator_get_voltage_sel, | ||
| 93 | .list_voltage = st_pwm_regulator_list_voltage, | ||
| 94 | .map_voltage = regulator_map_voltage_iterate, | ||
| 95 | }; | ||
| 96 | |||
| 97 | static struct st_pwm_voltages b2105_duty_cycle_table[] = { | ||
| 98 | { .uV = 1114000, .dutycycle = 0, }, | ||
| 99 | { .uV = 1095000, .dutycycle = 10, }, | ||
| 100 | { .uV = 1076000, .dutycycle = 20, }, | ||
| 101 | { .uV = 1056000, .dutycycle = 30, }, | ||
| 102 | { .uV = 1036000, .dutycycle = 40, }, | ||
| 103 | { .uV = 1016000, .dutycycle = 50, }, | ||
| 104 | /* WARNING: Values above 50% duty-cycle cause boot failures. */ | ||
| 105 | }; | ||
| 106 | |||
| 107 | static const struct regulator_desc b2105_desc = { | ||
| 108 | .name = "b2105-pwm-regulator", | ||
| 109 | .ops = &st_pwm_regulator_voltage_ops, | ||
| 110 | .type = REGULATOR_VOLTAGE, | ||
| 111 | .owner = THIS_MODULE, | ||
| 112 | .n_voltages = ARRAY_SIZE(b2105_duty_cycle_table), | ||
| 113 | .supply_name = "pwm", | ||
| 114 | }; | ||
| 115 | |||
| 116 | static const struct st_pwm_regulator_pdata b2105_info = { | ||
| 117 | .desc = &b2105_desc, | ||
| 118 | .duty_cycle_table = b2105_duty_cycle_table, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static struct of_device_id st_pwm_of_match[] = { | ||
| 122 | { .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, }, | ||
| 123 | { }, | ||
| 124 | }; | ||
| 125 | MODULE_DEVICE_TABLE(of, st_pwm_of_match); | ||
| 126 | |||
| 127 | static int st_pwm_regulator_probe(struct platform_device *pdev) | ||
| 128 | { | ||
| 129 | struct st_pwm_regulator_data *drvdata; | ||
| 130 | struct regulator_dev *regulator; | ||
| 131 | struct regulator_config config = { }; | ||
| 132 | struct device_node *np = pdev->dev.of_node; | ||
| 133 | const struct of_device_id *of_match; | ||
| 134 | |||
| 135 | if (!np) { | ||
| 136 | dev_err(&pdev->dev, "Device Tree node missing\n"); | ||
| 137 | return -EINVAL; | ||
| 138 | } | ||
| 139 | |||
| 140 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
| 141 | if (!drvdata) | ||
| 142 | return -ENOMEM; | ||
| 143 | |||
| 144 | of_match = of_match_device(st_pwm_of_match, &pdev->dev); | ||
| 145 | if (!of_match) { | ||
| 146 | dev_err(&pdev->dev, "failed to match of device\n"); | ||
| 147 | return -ENODEV; | ||
| 148 | } | ||
| 149 | drvdata->pdata = of_match->data; | ||
| 150 | |||
| 151 | config.init_data = of_get_regulator_init_data(&pdev->dev, np); | ||
| 152 | if (!config.init_data) | ||
| 153 | return -ENOMEM; | ||
| 154 | |||
| 155 | config.of_node = np; | ||
| 156 | config.dev = &pdev->dev; | ||
| 157 | config.driver_data = drvdata; | ||
| 158 | |||
| 159 | drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); | ||
| 160 | if (IS_ERR(drvdata->pwm)) { | ||
| 161 | dev_err(&pdev->dev, "Failed to get PWM\n"); | ||
| 162 | return PTR_ERR(drvdata->pwm); | ||
| 163 | } | ||
| 164 | |||
| 165 | regulator = devm_regulator_register(&pdev->dev, | ||
| 166 | drvdata->pdata->desc, &config); | ||
| 167 | if (IS_ERR(regulator)) { | ||
| 168 | dev_err(&pdev->dev, "Failed to register regulator %s\n", | ||
| 169 | drvdata->pdata->desc->name); | ||
| 170 | return PTR_ERR(regulator); | ||
| 171 | } | ||
| 172 | |||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 176 | static struct platform_driver st_pwm_regulator_driver = { | ||
| 177 | .driver = { | ||
| 178 | .name = "st-pwm-regulator", | ||
| 179 | .owner = THIS_MODULE, | ||
| 180 | .of_match_table = of_match_ptr(st_pwm_of_match), | ||
| 181 | }, | ||
| 182 | .probe = st_pwm_regulator_probe, | ||
| 183 | }; | ||
| 184 | |||
| 185 | module_platform_driver(st_pwm_regulator_driver); | ||
| 186 | |||
| 187 | MODULE_LICENSE("GPL"); | ||
| 188 | MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); | ||
| 189 | MODULE_DESCRIPTION("ST PWM Regulator Driver"); | ||
| 190 | MODULE_ALIAS("platform:st_pwm-regulator"); | ||
diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index b187b6bba7ad..a2dabb575b97 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c | |||
| @@ -54,8 +54,8 @@ struct ti_abb_info { | |||
| 54 | 54 | ||
| 55 | /** | 55 | /** |
| 56 | * struct ti_abb_reg - Register description for ABB block | 56 | * struct ti_abb_reg - Register description for ABB block |
| 57 | * @setup_reg: setup register offset from base | 57 | * @setup_off: setup register offset from base |
| 58 | * @control_reg: control register offset from base | 58 | * @control_off: control register offset from base |
| 59 | * @sr2_wtcnt_value_mask: setup register- sr2_wtcnt_value mask | 59 | * @sr2_wtcnt_value_mask: setup register- sr2_wtcnt_value mask |
| 60 | * @fbb_sel_mask: setup register- FBB sel mask | 60 | * @fbb_sel_mask: setup register- FBB sel mask |
| 61 | * @rbb_sel_mask: setup register- RBB sel mask | 61 | * @rbb_sel_mask: setup register- RBB sel mask |
| @@ -64,8 +64,8 @@ struct ti_abb_info { | |||
| 64 | * @opp_sel_mask: control register - mask for mode to operate | 64 | * @opp_sel_mask: control register - mask for mode to operate |
| 65 | */ | 65 | */ |
| 66 | struct ti_abb_reg { | 66 | struct ti_abb_reg { |
| 67 | u32 setup_reg; | 67 | u32 setup_off; |
| 68 | u32 control_reg; | 68 | u32 control_off; |
| 69 | 69 | ||
| 70 | /* Setup register fields */ | 70 | /* Setup register fields */ |
| 71 | u32 sr2_wtcnt_value_mask; | 71 | u32 sr2_wtcnt_value_mask; |
| @@ -83,6 +83,8 @@ struct ti_abb_reg { | |||
| 83 | * @rdesc: regulator descriptor | 83 | * @rdesc: regulator descriptor |
| 84 | * @clk: clock(usually sysclk) supplying ABB block | 84 | * @clk: clock(usually sysclk) supplying ABB block |
| 85 | * @base: base address of ABB block | 85 | * @base: base address of ABB block |
| 86 | * @setup_reg: setup register of ABB block | ||
| 87 | * @control_reg: control register of ABB block | ||
| 86 | * @int_base: interrupt register base address | 88 | * @int_base: interrupt register base address |
| 87 | * @efuse_base: (optional) efuse base address for ABB modes | 89 | * @efuse_base: (optional) efuse base address for ABB modes |
| 88 | * @ldo_base: (optional) LDOVBB vset override base address | 90 | * @ldo_base: (optional) LDOVBB vset override base address |
| @@ -99,6 +101,8 @@ struct ti_abb { | |||
| 99 | struct regulator_desc rdesc; | 101 | struct regulator_desc rdesc; |
| 100 | struct clk *clk; | 102 | struct clk *clk; |
| 101 | void __iomem *base; | 103 | void __iomem *base; |
| 104 | void __iomem *setup_reg; | ||
| 105 | void __iomem *control_reg; | ||
| 102 | void __iomem *int_base; | 106 | void __iomem *int_base; |
| 103 | void __iomem *efuse_base; | 107 | void __iomem *efuse_base; |
| 104 | void __iomem *ldo_base; | 108 | void __iomem *ldo_base; |
| @@ -118,20 +122,18 @@ struct ti_abb { | |||
| 118 | * ti_abb_rmw() - handy wrapper to set specific register bits | 122 | * ti_abb_rmw() - handy wrapper to set specific register bits |
| 119 | * @mask: mask for register field | 123 | * @mask: mask for register field |
| 120 | * @value: value shifted to mask location and written | 124 | * @value: value shifted to mask location and written |
| 121 | * @offset: offset of register | 125 | * @reg: register address |
| 122 | * @base: base address | ||
| 123 | * | 126 | * |
| 124 | * Return: final register value (may be unused) | 127 | * Return: final register value (may be unused) |
| 125 | */ | 128 | */ |
| 126 | static inline u32 ti_abb_rmw(u32 mask, u32 value, u32 offset, | 129 | static inline u32 ti_abb_rmw(u32 mask, u32 value, void __iomem *reg) |
| 127 | void __iomem *base) | ||
| 128 | { | 130 | { |
| 129 | u32 val; | 131 | u32 val; |
| 130 | 132 | ||
| 131 | val = readl(base + offset); | 133 | val = readl(reg); |
| 132 | val &= ~mask; | 134 | val &= ~mask; |
| 133 | val |= (value << __ffs(mask)) & mask; | 135 | val |= (value << __ffs(mask)) & mask; |
| 134 | writel(val, base + offset); | 136 | writel(val, reg); |
| 135 | 137 | ||
| 136 | return val; | 138 | return val; |
| 137 | } | 139 | } |
| @@ -263,21 +265,19 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb, | |||
| 263 | if (ret) | 265 | if (ret) |
| 264 | goto out; | 266 | goto out; |
| 265 | 267 | ||
| 266 | ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, regs->setup_reg, | 268 | ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, abb->setup_reg); |
| 267 | abb->base); | ||
| 268 | 269 | ||
| 269 | switch (info->opp_sel) { | 270 | switch (info->opp_sel) { |
| 270 | case TI_ABB_SLOW_OPP: | 271 | case TI_ABB_SLOW_OPP: |
| 271 | ti_abb_rmw(regs->rbb_sel_mask, 1, regs->setup_reg, abb->base); | 272 | ti_abb_rmw(regs->rbb_sel_mask, 1, abb->setup_reg); |
| 272 | break; | 273 | break; |
| 273 | case TI_ABB_FAST_OPP: | 274 | case TI_ABB_FAST_OPP: |
| 274 | ti_abb_rmw(regs->fbb_sel_mask, 1, regs->setup_reg, abb->base); | 275 | ti_abb_rmw(regs->fbb_sel_mask, 1, abb->setup_reg); |
| 275 | break; | 276 | break; |
| 276 | } | 277 | } |
| 277 | 278 | ||
| 278 | /* program next state of ABB ldo */ | 279 | /* program next state of ABB ldo */ |
| 279 | ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, regs->control_reg, | 280 | ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, abb->control_reg); |
| 280 | abb->base); | ||
| 281 | 281 | ||
| 282 | /* | 282 | /* |
| 283 | * program LDO VBB vset override if needed for !bypass mode | 283 | * program LDO VBB vset override if needed for !bypass mode |
| @@ -288,7 +288,7 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb, | |||
| 288 | ti_abb_program_ldovbb(dev, abb, info); | 288 | ti_abb_program_ldovbb(dev, abb, info); |
| 289 | 289 | ||
| 290 | /* Initiate ABB ldo change */ | 290 | /* Initiate ABB ldo change */ |
| 291 | ti_abb_rmw(regs->opp_change_mask, 1, regs->control_reg, abb->base); | 291 | ti_abb_rmw(regs->opp_change_mask, 1, abb->control_reg); |
| 292 | 292 | ||
| 293 | /* Wait for ABB LDO to complete transition to new Bias setting */ | 293 | /* Wait for ABB LDO to complete transition to new Bias setting */ |
| 294 | ret = ti_abb_wait_txdone(dev, abb); | 294 | ret = ti_abb_wait_txdone(dev, abb); |
| @@ -490,8 +490,7 @@ static int ti_abb_init_timings(struct device *dev, struct ti_abb *abb) | |||
| 490 | dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__, | 490 | dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__, |
| 491 | clk_get_rate(abb->clk), sr2_wt_cnt_val); | 491 | clk_get_rate(abb->clk), sr2_wt_cnt_val); |
| 492 | 492 | ||
| 493 | ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, regs->setup_reg, | 493 | ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, abb->setup_reg); |
| 494 | abb->base); | ||
| 495 | 494 | ||
| 496 | return 0; | 495 | return 0; |
| 497 | } | 496 | } |
| @@ -508,32 +507,24 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb, | |||
| 508 | struct regulator_init_data *rinit_data) | 507 | struct regulator_init_data *rinit_data) |
| 509 | { | 508 | { |
| 510 | struct ti_abb_info *info; | 509 | struct ti_abb_info *info; |
| 511 | const struct property *prop; | ||
| 512 | const __be32 *abb_info; | ||
| 513 | const u32 num_values = 6; | 510 | const u32 num_values = 6; |
| 514 | char *pname = "ti,abb_info"; | 511 | char *pname = "ti,abb_info"; |
| 515 | u32 num_entries, i; | 512 | u32 i; |
| 516 | unsigned int *volt_table; | 513 | unsigned int *volt_table; |
| 517 | int min_uV = INT_MAX, max_uV = 0; | 514 | int num_entries, min_uV = INT_MAX, max_uV = 0; |
| 518 | struct regulation_constraints *c = &rinit_data->constraints; | 515 | struct regulation_constraints *c = &rinit_data->constraints; |
| 519 | 516 | ||
| 520 | prop = of_find_property(dev->of_node, pname, NULL); | ||
| 521 | if (!prop) { | ||
| 522 | dev_err(dev, "No '%s' property?\n", pname); | ||
| 523 | return -ENODEV; | ||
| 524 | } | ||
| 525 | |||
| 526 | if (!prop->value) { | ||
| 527 | dev_err(dev, "Empty '%s' property?\n", pname); | ||
| 528 | return -ENODATA; | ||
| 529 | } | ||
| 530 | |||
| 531 | /* | 517 | /* |
| 532 | * Each abb_info is a set of n-tuple, where n is num_values, consisting | 518 | * Each abb_info is a set of n-tuple, where n is num_values, consisting |
| 533 | * of voltage and a set of detection logic for ABB information for that | 519 | * of voltage and a set of detection logic for ABB information for that |
| 534 | * voltage to apply. | 520 | * voltage to apply. |
| 535 | */ | 521 | */ |
| 536 | num_entries = prop->length / sizeof(u32); | 522 | num_entries = of_property_count_u32_elems(dev->of_node, pname); |
| 523 | if (num_entries < 0) { | ||
| 524 | dev_err(dev, "No '%s' property?\n", pname); | ||
| 525 | return num_entries; | ||
| 526 | } | ||
| 527 | |||
| 537 | if (!num_entries || (num_entries % num_values)) { | 528 | if (!num_entries || (num_entries % num_values)) { |
| 538 | dev_err(dev, "All '%s' list entries need %d vals\n", pname, | 529 | dev_err(dev, "All '%s' list entries need %d vals\n", pname, |
| 539 | num_values); | 530 | num_values); |
| @@ -542,38 +533,38 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb, | |||
| 542 | num_entries /= num_values; | 533 | num_entries /= num_values; |
| 543 | 534 | ||
| 544 | info = devm_kzalloc(dev, sizeof(*info) * num_entries, GFP_KERNEL); | 535 | info = devm_kzalloc(dev, sizeof(*info) * num_entries, GFP_KERNEL); |
| 545 | if (!info) { | 536 | if (!info) |
| 546 | dev_err(dev, "Can't allocate info table for '%s' property\n", | ||
| 547 | pname); | ||
| 548 | return -ENOMEM; | 537 | return -ENOMEM; |
| 549 | } | 538 | |
| 550 | abb->info = info; | 539 | abb->info = info; |
| 551 | 540 | ||
| 552 | volt_table = devm_kzalloc(dev, sizeof(unsigned int) * num_entries, | 541 | volt_table = devm_kzalloc(dev, sizeof(unsigned int) * num_entries, |
| 553 | GFP_KERNEL); | 542 | GFP_KERNEL); |
| 554 | if (!volt_table) { | 543 | if (!volt_table) |
| 555 | dev_err(dev, "Can't allocate voltage table for '%s' property\n", | ||
| 556 | pname); | ||
| 557 | return -ENOMEM; | 544 | return -ENOMEM; |
| 558 | } | ||
| 559 | 545 | ||
| 560 | abb->rdesc.n_voltages = num_entries; | 546 | abb->rdesc.n_voltages = num_entries; |
| 561 | abb->rdesc.volt_table = volt_table; | 547 | abb->rdesc.volt_table = volt_table; |
| 562 | /* We do not know where the OPP voltage is at the moment */ | 548 | /* We do not know where the OPP voltage is at the moment */ |
| 563 | abb->current_info_idx = -EINVAL; | 549 | abb->current_info_idx = -EINVAL; |
| 564 | 550 | ||
| 565 | abb_info = prop->value; | ||
| 566 | for (i = 0; i < num_entries; i++, info++, volt_table++) { | 551 | for (i = 0; i < num_entries; i++, info++, volt_table++) { |
| 567 | u32 efuse_offset, rbb_mask, fbb_mask, vset_mask; | 552 | u32 efuse_offset, rbb_mask, fbb_mask, vset_mask; |
| 568 | u32 efuse_val; | 553 | u32 efuse_val; |
| 569 | 554 | ||
| 570 | /* NOTE: num_values should equal to entries picked up here */ | 555 | /* NOTE: num_values should equal to entries picked up here */ |
| 571 | *volt_table = be32_to_cpup(abb_info++); | 556 | of_property_read_u32_index(dev->of_node, pname, i * num_values, |
| 572 | info->opp_sel = be32_to_cpup(abb_info++); | 557 | volt_table); |
| 573 | efuse_offset = be32_to_cpup(abb_info++); | 558 | of_property_read_u32_index(dev->of_node, pname, |
| 574 | rbb_mask = be32_to_cpup(abb_info++); | 559 | i * num_values + 1, &info->opp_sel); |
| 575 | fbb_mask = be32_to_cpup(abb_info++); | 560 | of_property_read_u32_index(dev->of_node, pname, |
| 576 | vset_mask = be32_to_cpup(abb_info++); | 561 | i * num_values + 2, &efuse_offset); |
| 562 | of_property_read_u32_index(dev->of_node, pname, | ||
| 563 | i * num_values + 3, &rbb_mask); | ||
| 564 | of_property_read_u32_index(dev->of_node, pname, | ||
| 565 | i * num_values + 4, &fbb_mask); | ||
| 566 | of_property_read_u32_index(dev->of_node, pname, | ||
| 567 | i * num_values + 5, &vset_mask); | ||
| 577 | 568 | ||
| 578 | dev_dbg(dev, | 569 | dev_dbg(dev, |
| 579 | "[%d]v=%d ABB=%d ef=0x%x rbb=0x%x fbb=0x%x vset=0x%x\n", | 570 | "[%d]v=%d ABB=%d ef=0x%x rbb=0x%x fbb=0x%x vset=0x%x\n", |
| @@ -648,8 +639,8 @@ static struct regulator_ops ti_abb_reg_ops = { | |||
| 648 | /* Default ABB block offsets, IF this changes in future, create new one */ | 639 | /* Default ABB block offsets, IF this changes in future, create new one */ |
| 649 | static const struct ti_abb_reg abb_regs_v1 = { | 640 | static const struct ti_abb_reg abb_regs_v1 = { |
| 650 | /* WARNING: registers are wrongly documented in TRM */ | 641 | /* WARNING: registers are wrongly documented in TRM */ |
| 651 | .setup_reg = 0x04, | 642 | .setup_off = 0x04, |
| 652 | .control_reg = 0x00, | 643 | .control_off = 0x00, |
| 653 | 644 | ||
| 654 | .sr2_wtcnt_value_mask = (0xff << 8), | 645 | .sr2_wtcnt_value_mask = (0xff << 8), |
| 655 | .fbb_sel_mask = (0x01 << 2), | 646 | .fbb_sel_mask = (0x01 << 2), |
| @@ -661,8 +652,8 @@ static const struct ti_abb_reg abb_regs_v1 = { | |||
| 661 | }; | 652 | }; |
| 662 | 653 | ||
| 663 | static const struct ti_abb_reg abb_regs_v2 = { | 654 | static const struct ti_abb_reg abb_regs_v2 = { |
| 664 | .setup_reg = 0x00, | 655 | .setup_off = 0x00, |
| 665 | .control_reg = 0x04, | 656 | .control_off = 0x04, |
| 666 | 657 | ||
| 667 | .sr2_wtcnt_value_mask = (0xff << 8), | 658 | .sr2_wtcnt_value_mask = (0xff << 8), |
| 668 | .fbb_sel_mask = (0x01 << 2), | 659 | .fbb_sel_mask = (0x01 << 2), |
| @@ -673,9 +664,20 @@ static const struct ti_abb_reg abb_regs_v2 = { | |||
| 673 | .opp_sel_mask = (0x03 << 0), | 664 | .opp_sel_mask = (0x03 << 0), |
| 674 | }; | 665 | }; |
| 675 | 666 | ||
| 667 | static const struct ti_abb_reg abb_regs_generic = { | ||
| 668 | .sr2_wtcnt_value_mask = (0xff << 8), | ||
| 669 | .fbb_sel_mask = (0x01 << 2), | ||
| 670 | .rbb_sel_mask = (0x01 << 1), | ||
| 671 | .sr2_en_mask = (0x01 << 0), | ||
| 672 | |||
| 673 | .opp_change_mask = (0x01 << 2), | ||
| 674 | .opp_sel_mask = (0x03 << 0), | ||
| 675 | }; | ||
| 676 | |||
| 676 | static const struct of_device_id ti_abb_of_match[] = { | 677 | static const struct of_device_id ti_abb_of_match[] = { |
| 677 | {.compatible = "ti,abb-v1", .data = &abb_regs_v1}, | 678 | {.compatible = "ti,abb-v1", .data = &abb_regs_v1}, |
| 678 | {.compatible = "ti,abb-v2", .data = &abb_regs_v2}, | 679 | {.compatible = "ti,abb-v2", .data = &abb_regs_v2}, |
| 680 | {.compatible = "ti,abb-v3", .data = &abb_regs_generic}, | ||
| 679 | { }, | 681 | { }, |
| 680 | }; | 682 | }; |
| 681 | 683 | ||
| @@ -722,11 +724,29 @@ static int ti_abb_probe(struct platform_device *pdev) | |||
| 722 | abb->regs = match->data; | 724 | abb->regs = match->data; |
| 723 | 725 | ||
| 724 | /* Map ABB resources */ | 726 | /* Map ABB resources */ |
| 725 | pname = "base-address"; | 727 | if (abb->regs->setup_off || abb->regs->control_off) { |
| 726 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); | 728 | pname = "base-address"; |
| 727 | abb->base = devm_ioremap_resource(dev, res); | 729 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); |
| 728 | if (IS_ERR(abb->base)) | 730 | abb->base = devm_ioremap_resource(dev, res); |
| 729 | return PTR_ERR(abb->base); | 731 | if (IS_ERR(abb->base)) |
| 732 | return PTR_ERR(abb->base); | ||
| 733 | |||
| 734 | abb->setup_reg = abb->base + abb->regs->setup_off; | ||
| 735 | abb->control_reg = abb->base + abb->regs->control_off; | ||
| 736 | |||
| 737 | } else { | ||
| 738 | pname = "control-address"; | ||
| 739 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); | ||
| 740 | abb->control_reg = devm_ioremap_resource(dev, res); | ||
| 741 | if (IS_ERR(abb->control_reg)) | ||
| 742 | return PTR_ERR(abb->control_reg); | ||
| 743 | |||
| 744 | pname = "setup-address"; | ||
| 745 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); | ||
| 746 | abb->setup_reg = devm_ioremap_resource(dev, res); | ||
| 747 | if (IS_ERR(abb->setup_reg)) | ||
| 748 | return PTR_ERR(abb->setup_reg); | ||
| 749 | } | ||
| 730 | 750 | ||
| 731 | pname = "int-address"; | 751 | pname = "int-address"; |
| 732 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); | 752 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); |
| @@ -860,7 +880,7 @@ skip_opt: | |||
| 860 | platform_set_drvdata(pdev, rdev); | 880 | platform_set_drvdata(pdev, rdev); |
| 861 | 881 | ||
| 862 | /* Enable the ldo if not already done by bootloader */ | 882 | /* Enable the ldo if not already done by bootloader */ |
| 863 | ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base); | 883 | ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->setup_reg); |
| 864 | 884 | ||
| 865 | return 0; | 885 | return 0; |
| 866 | } | 886 | } |
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index b3764f594ee9..f31f22e3e1bd 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c | |||
| @@ -227,10 +227,8 @@ static struct tps51632_regulator_platform_data * | |||
| 227 | struct device_node *np = dev->of_node; | 227 | struct device_node *np = dev->of_node; |
| 228 | 228 | ||
| 229 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 229 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
| 230 | if (!pdata) { | 230 | if (!pdata) |
| 231 | dev_err(dev, "Memory alloc failed for platform data\n"); | ||
| 232 | return NULL; | 231 | return NULL; |
| 233 | } | ||
| 234 | 232 | ||
| 235 | pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); | 233 | pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); |
| 236 | if (!pdata->reg_init_data) { | 234 | if (!pdata->reg_init_data) { |
| @@ -299,10 +297,8 @@ static int tps51632_probe(struct i2c_client *client, | |||
| 299 | } | 297 | } |
| 300 | 298 | ||
| 301 | tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); | 299 | tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); |
| 302 | if (!tps) { | 300 | if (!tps) |
| 303 | dev_err(&client->dev, "Memory allocation failed\n"); | ||
| 304 | return -ENOMEM; | 301 | return -ENOMEM; |
| 305 | } | ||
| 306 | 302 | ||
| 307 | tps->dev = &client->dev; | 303 | tps->dev = &client->dev; |
| 308 | tps->desc.name = client->name; | 304 | tps->desc.name = client->name; |
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index c3fa15a299b1..a1672044e519 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c | |||
| @@ -299,10 +299,8 @@ static struct tps62360_regulator_platform_data * | |||
| 299 | struct device_node *np = dev->of_node; | 299 | struct device_node *np = dev->of_node; |
| 300 | 300 | ||
| 301 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 301 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
| 302 | if (!pdata) { | 302 | if (!pdata) |
| 303 | dev_err(dev, "Memory alloc failed for platform data\n"); | ||
| 304 | return NULL; | 303 | return NULL; |
| 305 | } | ||
| 306 | 304 | ||
| 307 | pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); | 305 | pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); |
| 308 | if (!pdata->reg_init_data) { | 306 | if (!pdata->reg_init_data) { |
| @@ -377,11 +375,8 @@ static int tps62360_probe(struct i2c_client *client, | |||
| 377 | } | 375 | } |
| 378 | 376 | ||
| 379 | tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); | 377 | tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); |
| 380 | if (!tps) { | 378 | if (!tps) |
| 381 | dev_err(&client->dev, "%s(): Memory allocation failed\n", | ||
| 382 | __func__); | ||
| 383 | return -ENOMEM; | 379 | return -ENOMEM; |
| 384 | } | ||
| 385 | 380 | ||
| 386 | tps->en_discharge = pdata->en_discharge; | 381 | tps->en_discharge = pdata->en_discharge; |
| 387 | tps->en_internal_pulldn = pdata->en_internal_pulldn; | 382 | tps->en_internal_pulldn = pdata->en_internal_pulldn; |
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 162a0fae20b3..98e66ce26723 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
| @@ -359,7 +359,6 @@ static struct regulator_ops tps6507x_pmic_ops = { | |||
| 359 | .map_voltage = regulator_map_voltage_ascend, | 359 | .map_voltage = regulator_map_voltage_ascend, |
| 360 | }; | 360 | }; |
| 361 | 361 | ||
| 362 | #ifdef CONFIG_OF | ||
| 363 | static struct of_regulator_match tps6507x_matches[] = { | 362 | static struct of_regulator_match tps6507x_matches[] = { |
| 364 | { .name = "VDCDC1"}, | 363 | { .name = "VDCDC1"}, |
| 365 | { .name = "VDCDC2"}, | 364 | { .name = "VDCDC2"}, |
| @@ -381,12 +380,10 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data( | |||
| 381 | 380 | ||
| 382 | tps_board = devm_kzalloc(&pdev->dev, sizeof(*tps_board), | 381 | tps_board = devm_kzalloc(&pdev->dev, sizeof(*tps_board), |
| 383 | GFP_KERNEL); | 382 | GFP_KERNEL); |
| 384 | if (!tps_board) { | 383 | if (!tps_board) |
| 385 | dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n"); | ||
| 386 | return NULL; | 384 | return NULL; |
| 387 | } | ||
| 388 | 385 | ||
| 389 | regulators = of_find_node_by_name(np, "regulators"); | 386 | regulators = of_get_child_by_name(np, "regulators"); |
| 390 | if (!regulators) { | 387 | if (!regulators) { |
| 391 | dev_err(&pdev->dev, "regulator node not found\n"); | 388 | dev_err(&pdev->dev, "regulator node not found\n"); |
| 392 | return NULL; | 389 | return NULL; |
| @@ -396,6 +393,7 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data( | |||
| 396 | matches = tps6507x_matches; | 393 | matches = tps6507x_matches; |
| 397 | 394 | ||
| 398 | ret = of_regulator_match(&pdev->dev, regulators, matches, count); | 395 | ret = of_regulator_match(&pdev->dev, regulators, matches, count); |
| 396 | of_node_put(regulators); | ||
| 399 | if (ret < 0) { | 397 | if (ret < 0) { |
| 400 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", | 398 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", |
| 401 | ret); | 399 | ret); |
| @@ -406,10 +404,8 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data( | |||
| 406 | 404 | ||
| 407 | reg_data = devm_kzalloc(&pdev->dev, (sizeof(struct regulator_init_data) | 405 | reg_data = devm_kzalloc(&pdev->dev, (sizeof(struct regulator_init_data) |
| 408 | * TPS6507X_NUM_REGULATOR), GFP_KERNEL); | 406 | * TPS6507X_NUM_REGULATOR), GFP_KERNEL); |
| 409 | if (!reg_data) { | 407 | if (!reg_data) |
| 410 | dev_err(&pdev->dev, "Failure to alloc init data for regulators.\n"); | ||
| 411 | return NULL; | 408 | return NULL; |
| 412 | } | ||
| 413 | 409 | ||
| 414 | tps_board->tps6507x_pmic_init_data = reg_data; | 410 | tps_board->tps6507x_pmic_init_data = reg_data; |
| 415 | 411 | ||
| @@ -424,15 +420,7 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data( | |||
| 424 | 420 | ||
| 425 | return tps_board; | 421 | return tps_board; |
| 426 | } | 422 | } |
| 427 | #else | 423 | |
| 428 | static inline struct tps6507x_board *tps6507x_parse_dt_reg_data( | ||
| 429 | struct platform_device *pdev, | ||
| 430 | struct of_regulator_match **tps6507x_reg_matches) | ||
| 431 | { | ||
| 432 | *tps6507x_reg_matches = NULL; | ||
| 433 | return NULL; | ||
| 434 | } | ||
| 435 | #endif | ||
| 436 | static int tps6507x_pmic_probe(struct platform_device *pdev) | 424 | static int tps6507x_pmic_probe(struct platform_device *pdev) |
| 437 | { | 425 | { |
| 438 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); | 426 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); |
| @@ -453,9 +441,10 @@ static int tps6507x_pmic_probe(struct platform_device *pdev) | |||
| 453 | */ | 441 | */ |
| 454 | 442 | ||
| 455 | tps_board = dev_get_platdata(tps6507x_dev->dev); | 443 | tps_board = dev_get_platdata(tps6507x_dev->dev); |
| 456 | if (!tps_board && tps6507x_dev->dev->of_node) | 444 | if (IS_ENABLED(CONFIG_OF) && !tps_board && |
| 445 | tps6507x_dev->dev->of_node) | ||
| 457 | tps_board = tps6507x_parse_dt_reg_data(pdev, | 446 | tps_board = tps6507x_parse_dt_reg_data(pdev, |
| 458 | &tps6507x_reg_matches); | 447 | &tps6507x_reg_matches); |
| 459 | if (!tps_board) | 448 | if (!tps_board) |
| 460 | return -EINVAL; | 449 | return -EINVAL; |
| 461 | 450 | ||
| @@ -481,7 +470,7 @@ static int tps6507x_pmic_probe(struct platform_device *pdev) | |||
| 481 | tps->info[i] = info; | 470 | tps->info[i] = info; |
| 482 | if (init_data->driver_data) { | 471 | if (init_data->driver_data) { |
| 483 | struct tps6507x_reg_platform_data *data = | 472 | struct tps6507x_reg_platform_data *data = |
| 484 | init_data->driver_data; | 473 | init_data->driver_data; |
| 485 | tps->info[i]->defdcdc_default = data->defdcdc_default; | 474 | tps->info[i]->defdcdc_default = data->defdcdc_default; |
| 486 | } | 475 | } |
| 487 | 476 | ||
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 676f75548f00..2e92ef68574d 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c | |||
| @@ -168,17 +168,13 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data( | |||
| 168 | 168 | ||
| 169 | tps65090_pdata = devm_kzalloc(&pdev->dev, sizeof(*tps65090_pdata), | 169 | tps65090_pdata = devm_kzalloc(&pdev->dev, sizeof(*tps65090_pdata), |
| 170 | GFP_KERNEL); | 170 | GFP_KERNEL); |
| 171 | if (!tps65090_pdata) { | 171 | if (!tps65090_pdata) |
| 172 | dev_err(&pdev->dev, "Memory alloc for tps65090_pdata failed\n"); | ||
| 173 | return ERR_PTR(-ENOMEM); | 172 | return ERR_PTR(-ENOMEM); |
| 174 | } | ||
| 175 | 173 | ||
| 176 | reg_pdata = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * | 174 | reg_pdata = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * |
| 177 | sizeof(*reg_pdata), GFP_KERNEL); | 175 | sizeof(*reg_pdata), GFP_KERNEL); |
| 178 | if (!reg_pdata) { | 176 | if (!reg_pdata) |
| 179 | dev_err(&pdev->dev, "Memory alloc for reg_pdata failed\n"); | ||
| 180 | return ERR_PTR(-ENOMEM); | 177 | return ERR_PTR(-ENOMEM); |
| 181 | } | ||
| 182 | 178 | ||
| 183 | regulators = of_get_child_by_name(np, "regulators"); | 179 | regulators = of_get_child_by_name(np, "regulators"); |
| 184 | if (!regulators) { | 180 | if (!regulators) { |
| @@ -188,6 +184,7 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data( | |||
| 188 | 184 | ||
| 189 | ret = of_regulator_match(&pdev->dev, regulators, tps65090_matches, | 185 | ret = of_regulator_match(&pdev->dev, regulators, tps65090_matches, |
| 190 | ARRAY_SIZE(tps65090_matches)); | 186 | ARRAY_SIZE(tps65090_matches)); |
| 187 | of_node_put(regulators); | ||
| 191 | if (ret < 0) { | 188 | if (ret < 0) { |
| 192 | dev_err(&pdev->dev, | 189 | dev_err(&pdev->dev, |
| 193 | "Error parsing regulator init data: %d\n", ret); | 190 | "Error parsing regulator init data: %d\n", ret); |
| @@ -252,10 +249,8 @@ static int tps65090_regulator_probe(struct platform_device *pdev) | |||
| 252 | 249 | ||
| 253 | pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic), | 250 | pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic), |
| 254 | GFP_KERNEL); | 251 | GFP_KERNEL); |
| 255 | if (!pmic) { | 252 | if (!pmic) |
| 256 | dev_err(&pdev->dev, "mem alloc for pmic failed\n"); | ||
| 257 | return -ENOMEM; | 253 | return -ENOMEM; |
| 258 | } | ||
| 259 | 254 | ||
| 260 | for (num = 0; num < TPS65090_REGULATOR_MAX; num++) { | 255 | for (num = 0; num < TPS65090_REGULATOR_MAX; num++) { |
| 261 | tps_pdata = tps65090_pdata->reg_pdata[num]; | 256 | tps_pdata = tps65090_pdata->reg_pdata[num]; |
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 9ea1bf26bd13..10b78d2b766a 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c | |||
| @@ -187,7 +187,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) | |||
| 187 | struct device_node *regs; | 187 | struct device_node *regs; |
| 188 | int i, count; | 188 | int i, count; |
| 189 | 189 | ||
| 190 | regs = of_find_node_by_name(node, "regulators"); | 190 | regs = of_get_child_by_name(node, "regulators"); |
| 191 | if (!regs) | 191 | if (!regs) |
| 192 | return NULL; | 192 | return NULL; |
| 193 | 193 | ||
| @@ -202,7 +202,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) | |||
| 202 | return NULL; | 202 | return NULL; |
| 203 | 203 | ||
| 204 | for (i = 0; i < count; i++) { | 204 | for (i = 0; i < count; i++) { |
| 205 | if (!reg_matches[i].init_data || !reg_matches[i].of_node) | 205 | if (!reg_matches[i].of_node) |
| 206 | continue; | 206 | continue; |
| 207 | 207 | ||
| 208 | pdata->tps65217_init_data[i] = reg_matches[i].init_data; | 208 | pdata->tps65217_init_data[i] = reg_matches[i].init_data; |
| @@ -222,7 +222,6 @@ static int tps65217_regulator_probe(struct platform_device *pdev) | |||
| 222 | { | 222 | { |
| 223 | struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); | 223 | struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); |
| 224 | struct tps65217_board *pdata = dev_get_platdata(tps->dev); | 224 | struct tps65217_board *pdata = dev_get_platdata(tps->dev); |
| 225 | struct regulator_init_data *reg_data; | ||
| 226 | struct regulator_dev *rdev; | 225 | struct regulator_dev *rdev; |
| 227 | struct regulator_config config = { }; | 226 | struct regulator_config config = { }; |
| 228 | int i; | 227 | int i; |
| @@ -243,19 +242,9 @@ static int tps65217_regulator_probe(struct platform_device *pdev) | |||
| 243 | platform_set_drvdata(pdev, tps); | 242 | platform_set_drvdata(pdev, tps); |
| 244 | 243 | ||
| 245 | for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { | 244 | for (i = 0; i < TPS65217_NUM_REGULATOR; i++) { |
| 246 | |||
| 247 | reg_data = pdata->tps65217_init_data[i]; | ||
| 248 | |||
| 249 | /* | ||
| 250 | * Regulator API handles empty constraints but not NULL | ||
| 251 | * constraints | ||
| 252 | */ | ||
| 253 | if (!reg_data) | ||
| 254 | continue; | ||
| 255 | |||
| 256 | /* Register the regulators */ | 245 | /* Register the regulators */ |
| 257 | config.dev = tps->dev; | 246 | config.dev = tps->dev; |
| 258 | config.init_data = reg_data; | 247 | config.init_data = pdata->tps65217_init_data[i]; |
| 259 | config.driver_data = tps; | 248 | config.driver_data = tps; |
| 260 | config.regmap = tps->regmap; | 249 | config.regmap = tps->regmap; |
| 261 | if (tps->dev->of_node) | 250 | if (tps->dev->of_node) |
