diff options
author | Mark Brown <broonie@kernel.org> | 2018-09-28 17:07:30 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-09-28 17:07:30 +0300 |
commit | 5451521409ce1c04d56c03854008fe8861893b05 (patch) | |
tree | 8d8ee36c9021cd511fdf2f0416664d05b5ec406d | |
parent | 5a7d7d0f9f791b1e13f26dbbb07c86482912ad62 (diff) | |
parent | 2ece646c90c5b45dd76c76ea207a3f3459f2c472 (diff) | |
download | linux-5451521409ce1c04d56c03854008fe8861893b05.tar.xz |
Merge tag 'bd71847-support' into regulator-4.20
regulator/mfd: Support for the ROHM BD71847
This adds support for the BD71847 which touches both MFD and regulator.
There's a few other bits and pieces included as some dependency patches
had already been applied so would've required rebasing.
-rw-r--r-- | Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt | 17 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt | 12 | ||||
-rw-r--r-- | drivers/mfd/rohm-bd718x7.c | 162 | ||||
-rw-r--r-- | drivers/regulator/Kconfig | 2 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 2 | ||||
-rw-r--r-- | drivers/regulator/bd71837-regulator.c | 626 | ||||
-rw-r--r-- | drivers/regulator/bd718x7-regulator.c | 1138 | ||||
-rw-r--r-- | drivers/regulator/core.c | 9 | ||||
-rw-r--r-- | drivers/regulator/helpers.c | 232 | ||||
-rw-r--r-- | drivers/regulator/of_regulator.c | 2 | ||||
-rw-r--r-- | include/linux/mfd/da9063/pdata.h | 16 | ||||
-rw-r--r-- | include/linux/mfd/rohm-bd718x7.h | 374 | ||||
-rw-r--r-- | include/linux/regulator/driver.h | 20 | ||||
-rw-r--r-- | include/linux/regulator/machine.h | 6 |
14 files changed, 1694 insertions, 924 deletions
diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt b/Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt index 3ca56fdb5ffe..a4b056761eaa 100644 --- a/Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt +++ b/Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt @@ -1,16 +1,17 @@ -* ROHM BD71837 Power Management Integrated Circuit bindings +* ROHM BD71837 and BD71847 Power Management Integrated Circuit bindings -BD71837MWV is a programmable Power Management IC for powering single-core, -dual-core, and quad-core SoCs such as NXP-i.MX 8M. It is optimized for -low BOM cost and compact solution footprint. It integrates 8 Buck -egulators and 7 LDOs to provide all the power rails required by the SoC and -the commonly used peripherals. +BD71837MWV and BD71847MWV are programmable Power Management ICs for powering +single-core, dual-core, and quad-core SoCs such as NXP-i.MX 8M. They are +optimized for low BOM cost and compact solution footprint. BD71837MWV +integrates 8 Buck regulators and 7 LDOs. BD71847MWV contains 6 Buck regulators +and 6 LDOs. -Datasheet for PMIC is available at: +Datasheet for BD71837 is available at: https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e Required properties: - - compatible : Should be "rohm,bd71837". + - compatible : Should be "rohm,bd71837" for bd71837 + "rohm,bd71847" for bd71847. - reg : I2C slave address. - interrupt-parent : Phandle to the parent interrupt controller. - interrupts : The interrupt line the device is connected to. diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt index 76ead07072b1..4b98ca26e61a 100644 --- a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.txt @@ -1,7 +1,9 @@ -ROHM BD71837 Power Management Integrated Circuit (PMIC) regulator bindings +ROHM BD71837 and BD71847 Power Management Integrated Circuit regulator bindings Required properties: - - regulator-name: should be "buck1", ..., "buck8" and "ldo1", ..., "ldo7" + - regulator-name: should be "buck1", ..., "buck8" and "ldo1", ..., "ldo7" for + BD71837. For BD71847 names should be "buck1", ..., "buck6" + and "ldo1", ..., "ldo6" List of regulators provided by this controller. BD71837 regulators node should be sub node of the BD71837 MFD node. See BD71837 MFD bindings at @@ -16,10 +18,14 @@ disabled by driver at startup. LDO5 and LDO6 are supplied by those and if they are disabled at startup the voltage monitoring for LDO5/LDO6 will cause PMIC to reset. -The valid names for regulator nodes are: +The valid names for BD71837 regulator nodes are: BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, BUCK7, BUCK8 LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7 +The valid names for BD71847 regulator nodes are: +BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6 +LDO1, LDO2, LDO3, LDO4, LDO5, LDO6 + Optional properties: - Any optional property defined in bindings/regulator/regulator.txt diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c index 75c8ec659547..161c8aac6d86 100644 --- a/drivers/mfd/rohm-bd718x7.c +++ b/drivers/mfd/rohm-bd718x7.c @@ -2,26 +2,21 @@ // // Copyright (C) 2018 ROHM Semiconductors // -// ROHM BD71837MWV PMIC driver +// ROHM BD71837MWV and BD71847MWV PMIC driver // -// Datasheet available from +// Datasheet for BD71837MWV available from // https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e +#include <linux/gpio_keys.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/interrupt.h> #include <linux/mfd/rohm-bd718x7.h> #include <linux/mfd/core.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/regmap.h> - -/* - * gpio_keys.h requires definiton of bool. It is brought in - * by above includes. Keep this as last until gpio_keys.h gets fixed. - */ -#include <linux/gpio_keys.h> - -static const u8 supported_revisions[] = { 0xA2 /* BD71837 */ }; +#include <linux/types.h> static struct gpio_keys_button button = { .code = KEY_POWER, @@ -35,42 +30,42 @@ static struct gpio_keys_platform_data bd718xx_powerkey_data = { .name = "bd718xx-pwrkey", }; -static struct mfd_cell bd71837_mfd_cells[] = { +static struct mfd_cell bd718xx_mfd_cells[] = { { .name = "gpio-keys", .platform_data = &bd718xx_powerkey_data, .pdata_size = sizeof(bd718xx_powerkey_data), }, - { .name = "bd71837-clk", }, - { .name = "bd71837-pmic", }, + { .name = "bd718xx-clk", }, + { .name = "bd718xx-pmic", }, }; -static const struct regmap_irq bd71837_irqs[] = { - REGMAP_IRQ_REG(BD71837_INT_SWRST, 0, BD71837_INT_SWRST_MASK), - REGMAP_IRQ_REG(BD71837_INT_PWRBTN_S, 0, BD71837_INT_PWRBTN_S_MASK), - REGMAP_IRQ_REG(BD71837_INT_PWRBTN_L, 0, BD71837_INT_PWRBTN_L_MASK), - REGMAP_IRQ_REG(BD71837_INT_PWRBTN, 0, BD71837_INT_PWRBTN_MASK), - REGMAP_IRQ_REG(BD71837_INT_WDOG, 0, BD71837_INT_WDOG_MASK), - REGMAP_IRQ_REG(BD71837_INT_ON_REQ, 0, BD71837_INT_ON_REQ_MASK), - REGMAP_IRQ_REG(BD71837_INT_STBY_REQ, 0, BD71837_INT_STBY_REQ_MASK), +static const struct regmap_irq bd718xx_irqs[] = { + REGMAP_IRQ_REG(BD718XX_INT_SWRST, 0, BD718XX_INT_SWRST_MASK), + REGMAP_IRQ_REG(BD718XX_INT_PWRBTN_S, 0, BD718XX_INT_PWRBTN_S_MASK), + REGMAP_IRQ_REG(BD718XX_INT_PWRBTN_L, 0, BD718XX_INT_PWRBTN_L_MASK), + REGMAP_IRQ_REG(BD718XX_INT_PWRBTN, 0, BD718XX_INT_PWRBTN_MASK), + REGMAP_IRQ_REG(BD718XX_INT_WDOG, 0, BD718XX_INT_WDOG_MASK), + REGMAP_IRQ_REG(BD718XX_INT_ON_REQ, 0, BD718XX_INT_ON_REQ_MASK), + REGMAP_IRQ_REG(BD718XX_INT_STBY_REQ, 0, BD718XX_INT_STBY_REQ_MASK), }; -static struct regmap_irq_chip bd71837_irq_chip = { - .name = "bd71837-irq", - .irqs = bd71837_irqs, - .num_irqs = ARRAY_SIZE(bd71837_irqs), +static struct regmap_irq_chip bd718xx_irq_chip = { + .name = "bd718xx-irq", + .irqs = bd718xx_irqs, + .num_irqs = ARRAY_SIZE(bd718xx_irqs), .num_regs = 1, .irq_reg_stride = 1, - .status_base = BD71837_REG_IRQ, - .mask_base = BD71837_REG_MIRQ, - .ack_base = BD71837_REG_IRQ, + .status_base = BD718XX_REG_IRQ, + .mask_base = BD718XX_REG_MIRQ, + .ack_base = BD718XX_REG_IRQ, .init_ack_masked = true, .mask_invert = false, }; static const struct regmap_range pmic_status_range = { - .range_min = BD71837_REG_IRQ, - .range_max = BD71837_REG_POW_STATE, + .range_min = BD718XX_REG_IRQ, + .range_max = BD718XX_REG_POW_STATE, }; static const struct regmap_access_table volatile_regs = { @@ -78,67 +73,53 @@ static const struct regmap_access_table volatile_regs = { .n_yes_ranges = 1, }; -static const struct regmap_config bd71837_regmap_config = { +static const struct regmap_config bd718xx_regmap_config = { .reg_bits = 8, .val_bits = 8, .volatile_table = &volatile_regs, - .max_register = BD71837_MAX_REGISTER - 1, + .max_register = BD718XX_MAX_REGISTER - 1, .cache_type = REGCACHE_RBTREE, }; -static int bd71837_i2c_probe(struct i2c_client *i2c, +static int bd718xx_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct bd71837 *bd71837; - int ret, i; - unsigned int val; - - bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL); + struct bd718xx *bd718xx; + int ret; - if (!bd71837) - return -ENOMEM; - - bd71837->chip_irq = i2c->irq; - - if (!bd71837->chip_irq) { + if (!i2c->irq) { dev_err(&i2c->dev, "No IRQ configured\n"); return -EINVAL; } - bd71837->dev = &i2c->dev; - dev_set_drvdata(&i2c->dev, bd71837); + bd718xx = devm_kzalloc(&i2c->dev, sizeof(struct bd718xx), GFP_KERNEL); - bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config); - if (IS_ERR(bd71837->regmap)) { - dev_err(&i2c->dev, "regmap initialization failed\n"); - return PTR_ERR(bd71837->regmap); - } + if (!bd718xx) + return -ENOMEM; - ret = regmap_read(bd71837->regmap, BD71837_REG_REV, &val); - if (ret) { - dev_err(&i2c->dev, "Read BD71837_REG_DEVICE failed\n"); - return ret; - } - for (i = 0; i < ARRAY_SIZE(supported_revisions); i++) - if (supported_revisions[i] == val) - break; + bd718xx->chip_irq = i2c->irq; + bd718xx->chip_type = (unsigned int) + of_device_get_match_data(&i2c->dev); + bd718xx->dev = &i2c->dev; + dev_set_drvdata(&i2c->dev, bd718xx); - if (i == ARRAY_SIZE(supported_revisions)) { - dev_err(&i2c->dev, "Unsupported chip revision\n"); - return -ENODEV; + bd718xx->regmap = devm_regmap_init_i2c(i2c, &bd718xx_regmap_config); + if (IS_ERR(bd718xx->regmap)) { + dev_err(&i2c->dev, "regmap initialization failed\n"); + return PTR_ERR(bd718xx->regmap); } - ret = devm_regmap_add_irq_chip(&i2c->dev, bd71837->regmap, - bd71837->chip_irq, IRQF_ONESHOT, 0, - &bd71837_irq_chip, &bd71837->irq_data); + ret = devm_regmap_add_irq_chip(&i2c->dev, bd718xx->regmap, + bd718xx->chip_irq, IRQF_ONESHOT, 0, + &bd718xx_irq_chip, &bd718xx->irq_data); if (ret) { dev_err(&i2c->dev, "Failed to add irq_chip\n"); return ret; } /* Configure short press to 10 milliseconds */ - ret = regmap_update_bits(bd71837->regmap, - BD71837_REG_PWRONCONFIG0, + ret = regmap_update_bits(bd718xx->regmap, + BD718XX_REG_PWRONCONFIG0, BD718XX_PWRBTN_PRESS_DURATION_MASK, BD718XX_PWRBTN_SHORT_PRESS_10MS); if (ret) { @@ -148,8 +129,8 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, } /* Configure long press to 10 seconds */ - ret = regmap_update_bits(bd71837->regmap, - BD71837_REG_PWRONCONFIG1, + ret = regmap_update_bits(bd718xx->regmap, + BD718XX_REG_PWRONCONFIG1, BD718XX_PWRBTN_PRESS_DURATION_MASK, BD718XX_PWRBTN_LONG_PRESS_10S); @@ -159,7 +140,7 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, return ret; } - ret = regmap_irq_get_virq(bd71837->irq_data, BD71837_INT_PWRBTN_S); + ret = regmap_irq_get_virq(bd718xx->irq_data, BD718XX_INT_PWRBTN_S); if (ret < 0) { dev_err(&i2c->dev, "Failed to get the IRQ\n"); @@ -168,44 +149,51 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, button.irq = ret; - ret = devm_mfd_add_devices(bd71837->dev, PLATFORM_DEVID_AUTO, - bd71837_mfd_cells, - ARRAY_SIZE(bd71837_mfd_cells), NULL, 0, - regmap_irq_get_domain(bd71837->irq_data)); + ret = devm_mfd_add_devices(bd718xx->dev, PLATFORM_DEVID_AUTO, + bd718xx_mfd_cells, + ARRAY_SIZE(bd718xx_mfd_cells), NULL, 0, + regmap_irq_get_domain(bd718xx->irq_data)); if (ret) dev_err(&i2c->dev, "Failed to create subdevices\n"); return ret; } -static const struct of_device_id bd71837_of_match[] = { - { .compatible = "rohm,bd71837", }, +static const struct of_device_id bd718xx_of_match[] = { + { + .compatible = "rohm,bd71837", + .data = (void *)BD718XX_TYPE_BD71837, + }, + { + .compatible = "rohm,bd71847", + .data = (void *)BD718XX_TYPE_BD71847, + }, { } }; -MODULE_DEVICE_TABLE(of, bd71837_of_match); +MODULE_DEVICE_TABLE(of, bd718xx_of_match); -static struct i2c_driver bd71837_i2c_driver = { +static struct i2c_driver bd718xx_i2c_driver = { .driver = { .name = "rohm-bd718x7", - .of_match_table = bd71837_of_match, + .of_match_table = bd718xx_of_match, }, - .probe = bd71837_i2c_probe, + .probe = bd718xx_i2c_probe, }; -static int __init bd71837_i2c_init(void) +static int __init bd718xx_i2c_init(void) { - return i2c_add_driver(&bd71837_i2c_driver); + return i2c_add_driver(&bd718xx_i2c_driver); } /* Initialise early so consumer devices can complete system boot */ -subsys_initcall(bd71837_i2c_init); +subsys_initcall(bd718xx_i2c_init); -static void __exit bd71837_i2c_exit(void) +static void __exit bd718xx_i2c_exit(void) { - i2c_del_driver(&bd71837_i2c_driver); + i2c_del_driver(&bd718xx_i2c_driver); } -module_exit(bd71837_i2c_exit); +module_exit(bd718xx_i2c_exit); MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); -MODULE_DESCRIPTION("ROHM BD71837 Power Management IC driver"); +MODULE_DESCRIPTION("ROHM BD71837/BD71847 Power Management IC driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 329cdd33ed62..6e96ef1bd74a 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -189,7 +189,7 @@ config REGULATOR_BD718XX and LDO regulators. This driver can also be built as a module. If so, the module - will be called bd71837-regulator. + will be called bd718x7-regulator. config REGULATOR_BD9571MWV tristate "ROHM BD9571MWV Regulators" diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 801d9a34a203..eac4d794f3b8 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -27,7 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o -obj-$(CONFIG_REGULATOR_BD718XX) += bd71837-regulator.o +obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o diff --git a/drivers/regulator/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c deleted file mode 100644 index 4fe519581235..000000000000 --- a/drivers/regulator/bd71837-regulator.c +++ /dev/null @@ -1,626 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (C) 2018 ROHM Semiconductors -// bd71837-regulator.c ROHM BD71837MWV regulator driver - -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/gpio.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/mfd/rohm-bd718x7.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/regulator/driver.h> -#include <linux/regulator/machine.h> -#include <linux/regulator/of_regulator.h> -#include <linux/slab.h> - -struct bd71837_pmic { - struct regulator_desc descs[BD71837_REGULATOR_CNT]; - struct bd71837 *mfd; - struct platform_device *pdev; - struct regulator_dev *rdev[BD71837_REGULATOR_CNT]; -}; - -/* - * BUCK1/2/3/4 - * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting - * 00: 10.00mV/usec 10mV 1uS - * 01: 5.00mV/usec 10mV 2uS - * 10: 2.50mV/usec 10mV 4uS - * 11: 1.25mV/usec 10mV 8uS - */ -static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, - int ramp_delay) -{ - struct bd71837_pmic *pmic = rdev_get_drvdata(rdev); - struct bd71837 *mfd = pmic->mfd; - int id = rdev->desc->id; - unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; - - dev_dbg(&pmic->pdev->dev, "Buck[%d] Set Ramp = %d\n", id + 1, - ramp_delay); - switch (ramp_delay) { - case 1 ... 1250: - ramp_value = BUCK_RAMPRATE_1P25MV; - break; - case 1251 ... 2500: - ramp_value = BUCK_RAMPRATE_2P50MV; - break; - case 2501 ... 5000: - ramp_value = BUCK_RAMPRATE_5P00MV; - break; - case 5001 ... 10000: - ramp_value = BUCK_RAMPRATE_10P00MV; - break; - default: - ramp_value = BUCK_RAMPRATE_10P00MV; - dev_err(&pmic->pdev->dev, - "%s: ramp_delay: %d not supported, setting 10000mV//us\n", - rdev->desc->name, ramp_delay); - } - - return regmap_update_bits(mfd->regmap, BD71837_REG_BUCK1_CTRL + id, - BUCK_RAMPRATE_MASK, ramp_value << 6); -} - -/* Bucks 1 to 4 support DVS. PWM mode is used when voltage is changed. - * Bucks 5 to 8 and LDOs can use PFM and must be disabled when voltage - * is changed. Hence we return -EBUSY for these if voltage is changed - * when BUCK/LDO is enabled. - */ -static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, - unsigned int sel) -{ - if (regulator_is_enabled_regmap(rdev)) - return -EBUSY; - - return regulator_set_voltage_sel_regmap(rdev, sel); -} - -static struct regulator_ops bd71837_ldo_regulator_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_linear_range, - .set_voltage_sel = bd71837_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, -}; - -static struct regulator_ops bd71837_ldo_regulator_nolinear_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_table, - .set_voltage_sel = bd71837_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, -}; - -static struct regulator_ops bd71837_buck_regulator_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_linear_range, - .set_voltage_sel = bd71837_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, -}; - -static struct regulator_ops bd71837_buck_regulator_nolinear_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_table, - .set_voltage_sel = bd71837_set_voltage_sel_restricted, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, -}; - -static struct regulator_ops bd71837_buck1234_regulator_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, - .is_enabled = regulator_is_enabled_regmap, - .list_voltage = regulator_list_voltage_linear_range, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_ramp_delay = bd71837_buck1234_set_ramp_delay, -}; - -/* - * BUCK1/2/3/4 - * 0.70 to 1.30V (10mV step) - */ -static const struct regulator_linear_range bd71837_buck1234_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(700000, 0x00, 0x3C, 10000), - REGULATOR_LINEAR_RANGE(1300000, 0x3D, 0x3F, 0), -}; - -/* - * BUCK5 - * 0.9V to 1.35V () - */ -static const struct regulator_linear_range bd71837_buck5_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000), - REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000), - REGULATOR_LINEAR_RANGE(1200000, 0x06, 0x07, 150000), -}; - -/* - * BUCK6 - * 3.0V to 3.3V (step 100mV) - */ -static const struct regulator_linear_range bd71837_buck6_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), -}; - -/* - * BUCK7 - * 000 = 1.605V - * 001 = 1.695V - * 010 = 1.755V - * 011 = 1.8V (Initial) - * 100 = 1.845V - * 101 = 1.905V - * 110 = 1.95V - * 111 = 1.995V - */ -static const unsigned int buck_7_volts[] = { - 1605000, 1695000, 1755000, 1800000, 1845000, 1905000, 1950000, 1995000 -}; - -/* - * BUCK8 - * 0.8V to 1.40V (step 10mV) - */ -static const struct regulator_linear_range bd71837_buck8_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(800000, 0x00, 0x3C, 10000), - REGULATOR_LINEAR_RANGE(1400000, 0x3D, 0x3F, 0), -}; - -/* - * LDO1 - * 3.0 to 3.3V (100mV step) - */ -static const struct regulator_linear_range bd71837_ldo1_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), -}; - -/* - * LDO2 - * 0.8 or 0.9V - */ -static const unsigned int ldo_2_volts[] = { - 900000, 800000 -}; - -/* - * LDO3 - * 1.8 to 3.3V (100mV step) - */ -static const struct regulator_linear_range bd71837_ldo3_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), -}; - -/* - * LDO4 - * 0.9 to 1.8V (100mV step) - */ -static const struct regulator_linear_range bd71837_ldo4_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), - REGULATOR_LINEAR_RANGE(1800000, 0x0A, 0x0F, 0), -}; - -/* - * LDO5 - * 1.8 to 3.3V (100mV step) - */ -static const struct regulator_linear_range bd71837_ldo5_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), -}; - -/* - * LDO6 - * 0.9 to 1.8V (100mV step) - */ -static const struct regulator_linear_range bd71837_ldo6_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), - REGULATOR_LINEAR_RANGE(1800000, 0x0A, 0x0F, 0), -}; - -/* - * LDO7 - * 1.8 to 3.3V (100mV step) - */ -static const struct regulator_linear_range bd71837_ldo7_voltage_ranges[] = { - REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), -}; - -static const struct regulator_desc bd71837_regulators[] = { - { - .name = "buck1", - .of_match = of_match_ptr("BUCK1"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_BUCK1, - .ops = &bd71837_buck1234_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_BUCK1_VOLTAGE_NUM, - .linear_ranges = bd71837_buck1234_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), - .vsel_reg = BD71837_REG_BUCK1_VOLT_RUN, - .vsel_mask = BUCK1_RUN_MASK, - .enable_reg = BD71837_REG_BUCK1_CTRL, - .enable_mask = BD71837_BUCK_EN, - .owner = THIS_MODULE, - }, - { - .name = "buck2", - .of_match = of_match_ptr("BUCK2"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_BUCK2, - .ops = &bd71837_buck1234_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_BUCK2_VOLTAGE_NUM, - .linear_ranges = bd71837_buck1234_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), - .vsel_reg = BD71837_REG_BUCK2_VOLT_RUN, - .vsel_mask = BUCK2_RUN_MASK, - .enable_reg = BD71837_REG_BUCK2_CTRL, - .enable_mask = BD71837_BUCK_EN, - .owner = THIS_MODULE, - }, - { - .name = "buck3", - .of_match = of_match_ptr("BUCK3"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_BUCK3, - .ops = &bd71837_buck1234_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_BUCK3_VOLTAGE_NUM, - .linear_ranges = bd71837_buck1234_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), - .vsel_reg = BD71837_REG_BUCK3_VOLT_RUN, - .vsel_mask = BUCK3_RUN_MASK, - .enable_reg = BD71837_REG_BUCK3_CTRL, - .enable_mask = BD71837_BUCK_EN, - .owner = THIS_MODULE, - }, - { - .name = "buck4", - .of_match = of_match_ptr("BUCK4"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_BUCK4, - .ops = &bd71837_buck1234_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_BUCK4_VOLTAGE_NUM, - .linear_ranges = bd71837_buck1234_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_buck1234_voltage_ranges), - .vsel_reg = BD71837_REG_BUCK4_VOLT_RUN, - .vsel_mask = BUCK4_RUN_MASK, - .enable_reg = BD71837_REG_BUCK4_CTRL, - .enable_mask = BD71837_BUCK_EN, - .owner = THIS_MODULE, - }, - { - .name = "buck5", - .of_match = of_match_ptr("BUCK5"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_BUCK5, - .ops = &bd71837_buck_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_BUCK5_VOLTAGE_NUM, - .linear_ranges = bd71837_buck5_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_buck5_voltage_ranges), - .vsel_reg = BD71837_REG_BUCK5_VOLT, - .vsel_mask = BUCK5_MASK, - .enable_reg = BD71837_REG_BUCK5_CTRL, - .enable_mask = BD71837_BUCK_EN, - .owner = THIS_MODULE, - }, - { - .name = "buck6", - .of_match = of_match_ptr("BUCK6"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_BUCK6, - .ops = &bd71837_buck_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_BUCK6_VOLTAGE_NUM, - .linear_ranges = bd71837_buck6_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_buck6_voltage_ranges), - .vsel_reg = BD71837_REG_BUCK6_VOLT, - .vsel_mask = BUCK6_MASK, - .enable_reg = BD71837_REG_BUCK6_CTRL, - .enable_mask = BD71837_BUCK_EN, - .owner = THIS_MODULE, - }, - { - .name = "buck7", - .of_match = of_match_ptr("BUCK7"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_BUCK7, - .ops = &bd71837_buck_regulator_nolinear_ops, - .type = REGULATOR_VOLTAGE, - .volt_table = &buck_7_volts[0], - .n_voltages = ARRAY_SIZE(buck_7_volts), - .vsel_reg = BD71837_REG_BUCK7_VOLT, - .vsel_mask = BUCK7_MASK, - .enable_reg = BD71837_REG_BUCK7_CTRL, - .enable_mask = BD71837_BUCK_EN, - .owner = THIS_MODULE, - }, - { - .name = "buck8", - .of_match = of_match_ptr("BUCK8"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_BUCK8, - .ops = &bd71837_buck_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_BUCK8_VOLTAGE_NUM, - .linear_ranges = bd71837_buck8_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_buck8_voltage_ranges), - .vsel_reg = BD71837_REG_BUCK8_VOLT, - .vsel_mask = BUCK8_MASK, - .enable_reg = BD71837_REG_BUCK8_CTRL, - .enable_mask = BD71837_BUCK_EN, - .owner = THIS_MODULE, - }, - { - .name = "ldo1", - .of_match = of_match_ptr("LDO1"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_LDO1, - .ops = &bd71837_ldo_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_LDO1_VOLTAGE_NUM, - .linear_ranges = bd71837_ldo1_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_ldo1_voltage_ranges), - .vsel_reg = BD71837_REG_LDO1_VOLT, - .vsel_mask = LDO1_MASK, - .enable_reg = BD71837_REG_LDO1_VOLT, - .enable_mask = BD71837_LDO_EN, - .owner = THIS_MODULE, - }, - { - .name = "ldo2", - .of_match = of_match_ptr("LDO2"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_LDO2, - .ops = &bd71837_ldo_regulator_nolinear_ops, - .type = REGULATOR_VOLTAGE, - .volt_table = &ldo_2_volts[0], - .n_voltages = ARRAY_SIZE(ldo_2_volts), - .vsel_reg = BD71837_REG_LDO2_VOLT, - .vsel_mask = LDO2_MASK, - .enable_reg = BD71837_REG_LDO2_VOLT, - .enable_mask = BD71837_LDO_EN, - .owner = THIS_MODULE, - }, - { - .name = "ldo3", - .of_match = of_match_ptr("LDO3"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_LDO3, - .ops = &bd71837_ldo_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_LDO3_VOLTAGE_NUM, - .linear_ranges = bd71837_ldo3_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_ldo3_voltage_ranges), - .vsel_reg = BD71837_REG_LDO3_VOLT, - .vsel_mask = LDO3_MASK, - .enable_reg = BD71837_REG_LDO3_VOLT, - .enable_mask = BD71837_LDO_EN, - .owner = THIS_MODULE, - }, - { - .name = "ldo4", - .of_match = of_match_ptr("LDO4"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_LDO4, - .ops = &bd71837_ldo_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_LDO4_VOLTAGE_NUM, - .linear_ranges = bd71837_ldo4_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_ldo4_voltage_ranges), - .vsel_reg = BD71837_REG_LDO4_VOLT, - .vsel_mask = LDO4_MASK, - .enable_reg = BD71837_REG_LDO4_VOLT, - .enable_mask = BD71837_LDO_EN, - .owner = THIS_MODULE, - }, - { - .name = "ldo5", - .of_match = of_match_ptr("LDO5"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_LDO5, - .ops = &bd71837_ldo_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_LDO5_VOLTAGE_NUM, - .linear_ranges = bd71837_ldo5_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_ldo5_voltage_ranges), - /* LDO5 is supplied by buck6 */ - .supply_name = "buck6", - .vsel_reg = BD71837_REG_LDO5_VOLT, - .vsel_mask = LDO5_MASK, - .enable_reg = BD71837_REG_LDO5_VOLT, - .enable_mask = BD71837_LDO_EN, - .owner = THIS_MODULE, - }, - { - .name = "ldo6", - .of_match = of_match_ptr("LDO6"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_LDO6, - .ops = &bd71837_ldo_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_LDO6_VOLTAGE_NUM, - .linear_ranges = bd71837_ldo6_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_ldo6_voltage_ranges), - /* LDO6 is supplied by buck7 */ - .supply_name = "buck7", - .vsel_reg = BD71837_REG_LDO6_VOLT, - .vsel_mask = LDO6_MASK, - .enable_reg = BD71837_REG_LDO6_VOLT, - .enable_mask = BD71837_LDO_EN, - .owner = THIS_MODULE, - }, - { - .name = "ldo7", - .of_match = of_match_ptr("LDO7"), - .regulators_node = of_match_ptr("regulators"), - .id = BD71837_LDO7, - .ops = &bd71837_ldo_regulator_ops, - .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_LDO7_VOLTAGE_NUM, - .linear_ranges = bd71837_ldo7_voltage_ranges, - .n_linear_ranges = ARRAY_SIZE(bd71837_ldo7_voltage_ranges), - .vsel_reg = BD71837_REG_LDO7_VOLT, - .vsel_mask = LDO7_MASK, - .enable_reg = BD71837_REG_LDO7_VOLT, - .enable_mask = BD71837_LDO_EN, - .owner = THIS_MODULE, - }, -}; - -struct reg_init { - unsigned int reg; - unsigned int mask; -}; - -static int bd71837_probe(struct platform_device *pdev) -{ - struct bd71837_pmic *pmic; - struct regulator_config config = { 0 }; - struct reg_init pmic_regulator_inits[] = { - { - .reg = BD71837_REG_BUCK1_CTRL, - .mask = BD71837_BUCK_SEL, - }, { - .reg = BD71837_REG_BUCK2_CTRL, - .mask = BD71837_BUCK_SEL, - }, { - .reg = BD71837_REG_BUCK3_CTRL, - .mask = BD71837_BUCK_SEL, - }, { - .reg = BD71837_REG_BUCK4_CTRL, - .mask = BD71837_BUCK_SEL, - }, { - .reg = BD71837_REG_BUCK5_CTRL, - .mask = BD71837_BUCK_SEL, - }, { - .reg = BD71837_REG_BUCK6_CTRL, - .mask = BD71837_BUCK_SEL, - }, { - .reg = BD71837_REG_BUCK7_CTRL, - .mask = BD71837_BUCK_SEL, - }, { - .reg = BD71837_REG_BUCK8_CTRL, - .mask = BD71837_BUCK_SEL, - }, { - .reg = BD71837_REG_LDO1_VOLT, - .mask = BD71837_LDO_SEL, - }, { - .reg = BD71837_REG_LDO2_VOLT, - .mask = BD71837_LDO_SEL, - }, { - .reg = BD71837_REG_LDO3_VOLT, - .mask = BD71837_LDO_SEL, - }, { - .reg = BD71837_REG_LDO4_VOLT, - .mask = BD71837_LDO_SEL, - }, { - .reg = BD71837_REG_LDO5_VOLT, - .mask = BD71837_LDO_SEL, - }, { - .reg = BD71837_REG_LDO6_VOLT, - .mask = BD71837_LDO_SEL, - }, { - .reg = BD71837_REG_LDO7_VOLT, - .mask = BD71837_LDO_SEL, - } - }; - - int i, err; - - pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); - if (!pmic) - return -ENOMEM; - - memcpy(pmic->descs, bd71837_regulators, sizeof(pmic->descs)); - - pmic->pdev = pdev; - pmic->mfd = dev_get_drvdata(pdev->dev.parent); - - if (!pmic->mfd) { - dev_err(&pdev->dev, "No MFD driver data\n"); - err = -EINVAL; - goto err; - } - platform_set_drvdata(pdev, pmic); - - /* Register LOCK release */ - err = regmap_update_bits(pmic->mfd->regmap, BD71837_REG_REGLOCK, - (REGLOCK_PWRSEQ | REGLOCK_VREG), 0); - if (err) { - dev_err(&pmic->pdev->dev, "Failed to unlock PMIC (%d)\n", err); - goto err; - } else { - dev_dbg(&pmic->pdev->dev, "Unlocked lock register 0x%x\n", - BD71837_REG_REGLOCK); - } - - for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) { - - struct regulator_desc *desc; - struct regulator_dev *rdev; - - desc = &pmic->descs[i]; - - config.dev = pdev->dev.parent; - config.driver_data = pmic; - config.regmap = pmic->mfd->regmap; - - rdev = devm_regulator_register(&pdev->dev, desc, &config); - if (IS_ERR(rdev)) { - dev_err(pmic->mfd->dev, - "failed to register %s regulator\n", - desc->name); - err = PTR_ERR(rdev); - goto err; - } - /* Regulator register gets the regulator constraints and - * applies them (set_machine_constraints). This should have - * turned the control register(s) to correct values and we - * can now switch the control from PMIC state machine to the - * register interface - */ - err = regmap_update_bits(pmic->mfd->regmap, - pmic_regulator_inits[i].reg, - pmic_regulator_inits[i].mask, - 0xFFFFFFFF); - if (err) { - dev_err(&pmic->pdev->dev, - "Failed to write BUCK/LDO SEL bit for (%s)\n", - desc->name); - goto err; - } - - pmic->rdev[i] = rdev; - } - -err: - return err; -} - -static struct platform_driver bd71837_regulator = { - .driver = { - .name = "bd71837-pmic", - }, - .probe = bd71837_probe, -}; - -module_platform_driver(bd71837_regulator); - -MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); -MODULE_DESCRIPTION("BD71837 voltage regulator driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c new file mode 100644 index 000000000000..d2522d4e1505 --- /dev/null +++ b/drivers/regulator/bd718x7-regulator.c @@ -0,0 +1,1138 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 ROHM Semiconductors +// bd71837-regulator.c ROHM BD71837MWV/BD71847MWV regulator driver + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mfd/rohm-bd718x7.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/slab.h> + +struct bd718xx_pmic { + struct bd718xx_regulator_data *rdata; + struct bd718xx *mfd; + struct platform_device *pdev; + struct regulator_dev *rdev[BD718XX_REGULATOR_AMOUNT]; +}; + +/* + * BUCK1/2/3/4 + * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting + * 00: 10.00mV/usec 10mV 1uS + * 01: 5.00mV/usec 10mV 2uS + * 10: 2.50mV/usec 10mV 4uS + * 11: 1.25mV/usec 10mV 8uS + */ +static int bd718xx_buck1234_set_ramp_delay(struct regulator_dev *rdev, + int ramp_delay) +{ + struct bd718xx_pmic *pmic = rdev_get_drvdata(rdev); + struct bd718xx *mfd = pmic->mfd; + int id = rdev->desc->id; + unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; + + dev_dbg(&pmic->pdev->dev, "Buck[%d] Set Ramp = %d\n", id + 1, + ramp_delay); + switch (ramp_delay) { + case 1 ... 1250: + ramp_value = BUCK_RAMPRATE_1P25MV; + break; + case 1251 ... 2500: + ramp_value = BUCK_RAMPRATE_2P50MV; + break; + case 2501 ... 5000: + ramp_value = BUCK_RAMPRATE_5P00MV; + break; + case 5001 ... 10000: + ramp_value = BUCK_RAMPRATE_10P00MV; + break; + default: + ramp_value = BUCK_RAMPRATE_10P00MV; + dev_err(&pmic->pdev->dev, + "%s: ramp_delay: %d not supported, setting 10000mV//us\n", + rdev->desc->name, ramp_delay); + } + + return regmap_update_bits(mfd->regmap, BD718XX_REG_BUCK1_CTRL + id, + BUCK_RAMPRATE_MASK, ramp_value << 6); +} + +/* Bucks 1 to 4 support DVS. PWM mode is used when voltage is changed. + * Bucks 5 to 8 and LDOs can use PFM and must be disabled when voltage + * is changed. Hence we return -EBUSY for these if voltage is changed + * when BUCK/LDO is enabled. + */ +static int bd718xx_set_voltage_sel_restricted(struct regulator_dev *rdev, + unsigned int sel) +{ + if (regulator_is_enabled_regmap(rdev)) + return -EBUSY; + + return regulator_set_voltage_sel_regmap(rdev, sel); +} + +static int bd718xx_set_voltage_sel_pickable_restricted( + struct regulator_dev *rdev, unsigned int sel) +{ + if (regulator_is_enabled_regmap(rdev)) + return -EBUSY; + + return regulator_set_voltage_sel_pickable_regmap(rdev, sel); +} + +static struct regulator_ops bd718xx_pickable_range_ldo_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_pickable_linear_range, + .set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted, + .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, +}; + +static struct regulator_ops bd718xx_pickable_range_buck_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_pickable_linear_range, + .set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted, + .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +static struct regulator_ops bd718xx_ldo_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = bd718xx_set_voltage_sel_restricted, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static struct regulator_ops bd718xx_ldo_regulator_nolinear_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = bd718xx_set_voltage_sel_restricted, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static struct regulator_ops bd718xx_buck_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = bd718xx_set_voltage_sel_restricted, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = bd718xx_set_voltage_sel_restricted, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +}; + +static struct regulator_ops bd718xx_dvs_buck_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = bd718xx_buck1234_set_ramp_delay, +}; + +/* + * BD71837 BUCK1/2/3/4 + * BD71847 BUCK1/2 + * 0.70 to 1.30V (10mV step) + */ +static const struct regulator_linear_range bd718xx_dvs_buck_volts[] = { + REGULATOR_LINEAR_RANGE(700000, 0x00, 0x3C, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0x3D, 0x3F, 0), +}; + +/* + * BD71837 BUCK5 + * 0.7V to 1.35V (range 0) + * and + * 0.675 to 1.325 (range 1) + */ +static const struct regulator_linear_range bd71837_buck5_volts[] = { + /* Ranges when VOLT_SEL bit is 0 */ + REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000), + REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000), + REGULATOR_LINEAR_RANGE(1200000, 0x06, 0x07, 150000), + /* Ranges when VOLT_SEL bit is 1 */ + REGULATOR_LINEAR_RANGE(675000, 0x0, 0x3, 100000), + REGULATOR_LINEAR_RANGE(1025000, 0x4, 0x5, 50000), + REGULATOR_LINEAR_RANGE(1175000, 0x6, 0x7, 150000), +}; + +/* + * Range selector for first 3 linear ranges is 0x0 + * and 0x1 for last 3 ranges. + */ +static const unsigned int bd71837_buck5_volt_range_sel[] = { + 0x0, 0x0, 0x0, 0x80, 0x80, 0x80 +}; + +/* + * BD71847 BUCK3 + */ +static const struct regulator_linear_range bd71847_buck3_volts[] = { + /* Ranges when VOLT_SEL bits are 00 */ + REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000), + REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000), + REGULATOR_LINEAR_RANGE(1200000, 0x06, 0x07, 150000), + /* Ranges when VOLT_SEL bits are 01 */ + REGULATOR_LINEAR_RANGE(550000, 0x0, 0x7, 50000), + /* Ranges when VOLT_SEL bits are 11 */ + REGULATOR_LINEAR_RANGE(675000, 0x0, 0x3, 100000), + REGULATOR_LINEAR_RANGE(1025000, 0x4, 0x5, 50000), + REGULATOR_LINEAR_RANGE(1175000, 0x6, 0x7, 150000), +}; + +static const unsigned int bd71847_buck3_volt_range_sel[] = { + 0x0, 0x0, 0x0, 0x40, 0x80, 0x80, 0x80 +}; + +static const struct regulator_linear_range bd71847_buck4_volts[] = { + REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), + REGULATOR_LINEAR_RANGE(2600000, 0x00, 0x03, 100000), +}; + +static const unsigned int bd71847_buck4_volt_range_sel[] = { 0x0, 0x40 }; + +/* + * BUCK6 + * 3.0V to 3.3V (step 100mV) + */ +static const struct regulator_linear_range bd71837_buck6_volts[] = { + REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), +}; + +/* + * BD71837 BUCK7 + * BD71847 BUCK5 + * 000 = 1.605V + * 001 = 1.695V + * 010 = 1.755V + * 011 = 1.8V (Initial) + * 100 = 1.845V + * 101 = 1.905V + * 110 = 1.95V + * 111 = 1.995V + */ +static const unsigned int bd718xx_3rd_nodvs_buck_volts[] = { + 1605000, 1695000, 1755000, 1800000, 1845000, 1905000, 1950000, 1995000 +}; + +/* + * BUCK8 + * 0.8V to 1.40V (step 10mV) + */ +static const struct regulator_linear_range bd718xx_4th_nodvs_buck_volts[] = { + REGULATOR_LINEAR_RANGE(800000, 0x00, 0x3C, 10000), +}; + +/* + * LDO1 + * 3.0 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd718xx_ldo1_volts[] = { + REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), + REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000), +}; + +static const unsigned int bd718xx_ldo1_volt_range_sel[] = { 0x0, 0x20 }; + +/* + * LDO2 + * 0.8 or 0.9V + */ +static const unsigned int ldo_2_volts[] = { + 900000, 800000 +}; + +/* + * LDO3 + * 1.8 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd718xx_ldo3_volts[] = { + REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), +}; + +/* + * LDO4 + * 0.9 to 1.8V (100mV step) + */ +static const struct regulator_linear_range bd718xx_ldo4_volts[] = { + REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), +}; + +/* + * LDO5 for BD71837 + * 1.8 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd71837_ldo5_volts[] = { + REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), +}; + +/* + * LDO5 for BD71837 + * 1.8 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd71847_ldo5_volts[] = { + REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), + REGULATOR_LINEAR_RANGE(800000, 0x00, 0x0F, 100000), +}; + +static const unsigned int bd71847_ldo5_volt_range_sel[] = { 0x0, 0x20 }; + +/* + * LDO6 + * 0.9 to 1.8V (100mV step) + */ +static const struct regulator_linear_range bd718xx_ldo6_volts[] = { + REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), +}; + +/* + * LDO7 + * 1.8 to 3.3V (100mV step) + */ +static const struct regulator_linear_range bd71837_ldo7_volts[] = { + REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), +}; + +struct reg_init { + unsigned int reg; + unsigned int mask; + unsigned int val; +}; +struct bd718xx_regulator_data { + struct regulator_desc desc; + const struct reg_init init; + const struct reg_init *additional_inits; + int additional_init_amnt; +}; + +/* + * There is a HW quirk in BD71837. The shutdown sequence timings for + * bucks/LDOs which are controlled via register interface are changed. + * At PMIC poweroff the voltage for BUCK6/7 is cut immediately at the + * beginning of shut-down sequence. As bucks 6 and 7 are parent + * supplies for LDO5 and LDO6 - this causes LDO5/6 voltage + * monitoring to errorneously detect under voltage and force PMIC to + * emergency state instead of poweroff. In order to avoid this we + * disable voltage monitoring for LDO5 and LDO6 + */ +static const struct reg_init bd71837_ldo5_inits[] = { + { + .reg = BD718XX_REG_MVRFLTMASK2, + .mask = BD718XX_LDO5_VRMON80, + .val = BD718XX_LDO5_VRMON80, + }, +}; + +static const struct reg_init bd71837_ldo6_inits[] = { + { + .reg = BD718XX_REG_MVRFLTMASK2, + .mask = BD718XX_LDO6_VRMON80, + .val = BD718XX_LDO6_VRMON80, + }, +}; + +static const struct bd718xx_regulator_data bd71847_regulators[] = { + { + .desc = { + .name = "buck1", + .of_match = of_match_ptr("BUCK1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK1, + .ops = &bd718xx_dvs_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_dvs_buck_volts, + .n_linear_ranges = + ARRAY_SIZE(bd718xx_dvs_buck_volts), + .vsel_reg = BD718XX_REG_BUCK1_VOLT_RUN, + .vsel_mask = DVS_BUCK_RUN_MASK, + .enable_reg = BD718XX_REG_BUCK1_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_BUCK1_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck2", + .of_match = of_match_ptr("BUCK2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK2, + .ops = &bd718xx_dvs_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_dvs_buck_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts), + .vsel_reg = BD718XX_REG_BUCK2_VOLT_RUN, + .vsel_mask = DVS_BUCK_RUN_MASK, + .enable_reg = BD718XX_REG_BUCK2_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_BUCK2_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck3", + .of_match = of_match_ptr("BUCK3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK3, + .ops = &bd718xx_pickable_range_buck_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71847_BUCK3_VOLTAGE_NUM, + .linear_ranges = bd71847_buck3_volts, + .n_linear_ranges = + ARRAY_SIZE(bd71847_buck3_volts), + .vsel_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, + .vsel_mask = BD718XX_1ST_NODVS_BUCK_MASK, + .vsel_range_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, + .vsel_range_mask = BD71847_BUCK3_RANGE_MASK, + .linear_range_selectors = bd71847_buck3_volt_range_sel, + .enable_reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck4", + .of_match = of_match_ptr("BUCK4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK4, + .ops = &bd718xx_pickable_range_buck_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71847_BUCK4_VOLTAGE_NUM, + .linear_ranges = bd71847_buck4_volts, + .n_linear_ranges = + ARRAY_SIZE(bd71847_buck4_volts), + .enable_reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL, + .vsel_reg = BD718XX_REG_2ND_NODVS_BUCK_VOLT, + .vsel_mask = BD71847_BUCK4_MASK, + .vsel_range_reg = BD718XX_REG_2ND_NODVS_BUCK_VOLT, + .vsel_range_mask = BD71847_BUCK4_RANGE_MASK, + .linear_range_selectors = bd71847_buck4_volt_range_sel, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck5", + .of_match = of_match_ptr("BUCK5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK5, + .ops = &bd718xx_buck_regulator_nolinear_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &bd718xx_3rd_nodvs_buck_volts[0], + .n_voltages = ARRAY_SIZE(bd718xx_3rd_nodvs_buck_volts), + .vsel_reg = BD718XX_REG_3RD_NODVS_BUCK_VOLT, + .vsel_mask = BD718XX_3RD_NODVS_BUCK_MASK, + .enable_reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck6", + .of_match = of_match_ptr("BUCK6"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK6, + .ops = &bd718xx_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_4th_nodvs_buck_volts, + .n_linear_ranges = + ARRAY_SIZE(bd718xx_4th_nodvs_buck_volts), + .vsel_reg = BD718XX_REG_4TH_NODVS_BUCK_VOLT, + .vsel_mask = BD718XX_4TH_NODVS_BUCK_MASK, + .enable_reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "ldo1", + .of_match = of_match_ptr("LDO1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO1, + .ops = &bd718xx_pickable_range_ldo_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_LDO1_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo1_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo1_volts), + .vsel_reg = BD718XX_REG_LDO1_VOLT, + .vsel_mask = BD718XX_LDO1_MASK, + .vsel_range_reg = BD718XX_REG_LDO1_VOLT, + .vsel_range_mask = BD718XX_LDO1_RANGE_MASK, + .linear_range_selectors = bd718xx_ldo1_volt_range_sel, + .enable_reg = BD718XX_REG_LDO1_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO1_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo2", + .of_match = of_match_ptr("LDO2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO2, + .ops = &bd718xx_ldo_regulator_nolinear_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &ldo_2_volts[0], + .vsel_reg = BD718XX_REG_LDO2_VOLT, + .vsel_mask = BD718XX_LDO2_MASK, + .n_voltages = ARRAY_SIZE(ldo_2_volts), + .enable_reg = BD718XX_REG_LDO2_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO2_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo3", + .of_match = of_match_ptr("LDO3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO3, + .ops = &bd718xx_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_LDO3_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo3_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo3_volts), + .vsel_reg = BD718XX_REG_LDO3_VOLT, + .vsel_mask = BD718XX_LDO3_MASK, + .enable_reg = BD718XX_REG_LDO3_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO3_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo4", + .of_match = of_match_ptr("LDO4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO4, + .ops = &bd718xx_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_LDO4_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo4_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo4_volts), + .vsel_reg = BD718XX_REG_LDO4_VOLT, + .vsel_mask = BD718XX_LDO4_MASK, + .enable_reg = BD718XX_REG_LDO4_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO4_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo5", + .of_match = of_match_ptr("LDO5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO5, + .ops = &bd718xx_pickable_range_ldo_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71847_LDO5_VOLTAGE_NUM, + .linear_ranges = bd71847_ldo5_volts, + .n_linear_ranges = ARRAY_SIZE(bd71847_ldo5_volts), + .vsel_reg = BD718XX_REG_LDO5_VOLT, + .vsel_mask = BD71847_LDO5_MASK, + .vsel_range_reg = BD718XX_REG_LDO5_VOLT, + .vsel_range_mask = BD71847_LDO5_RANGE_MASK, + .linear_range_selectors = bd71847_ldo5_volt_range_sel, + .enable_reg = BD718XX_REG_LDO5_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO5_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo6", + .of_match = of_match_ptr("LDO6"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO6, + .ops = &bd718xx_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_LDO6_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo6_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo6_volts), + /* LDO6 is supplied by buck5 */ + .supply_name = "buck5", + .vsel_reg = BD718XX_REG_LDO6_VOLT, + .vsel_mask = BD718XX_LDO6_MASK, + .enable_reg = BD718XX_REG_LDO6_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO6_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, +}; + +static const struct bd718xx_regulator_data bd71837_regulators[] = { + { + .desc = { + .name = "buck1", + .of_match = of_match_ptr("BUCK1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK1, + .ops = &bd718xx_dvs_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_dvs_buck_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts), + .vsel_reg = BD718XX_REG_BUCK1_VOLT_RUN, + .vsel_mask = DVS_BUCK_RUN_MASK, + .enable_reg = BD718XX_REG_BUCK1_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_BUCK1_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck2", + .of_match = of_match_ptr("BUCK2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK2, + .ops = &bd718xx_dvs_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_dvs_buck_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts), + .vsel_reg = BD718XX_REG_BUCK2_VOLT_RUN, + .vsel_mask = DVS_BUCK_RUN_MASK, + .enable_reg = BD718XX_REG_BUCK2_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_BUCK2_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck3", + .of_match = of_match_ptr("BUCK3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK3, + .ops = &bd718xx_dvs_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_dvs_buck_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts), + .vsel_reg = BD71837_REG_BUCK3_VOLT_RUN, + .vsel_mask = DVS_BUCK_RUN_MASK, + .enable_reg = BD71837_REG_BUCK3_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD71837_REG_BUCK3_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck4", + .of_match = of_match_ptr("BUCK4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK4, + .ops = &bd718xx_dvs_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_DVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_dvs_buck_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_dvs_buck_volts), + .vsel_reg = BD71837_REG_BUCK4_VOLT_RUN, + .vsel_mask = DVS_BUCK_RUN_MASK, + .enable_reg = BD71837_REG_BUCK4_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD71837_REG_BUCK4_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck5", + .of_match = of_match_ptr("BUCK5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK5, + .ops = &bd718xx_pickable_range_buck_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK5_VOLTAGE_NUM, + .linear_ranges = bd71837_buck5_volts, + .n_linear_ranges = + ARRAY_SIZE(bd71837_buck5_volts), + .vsel_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, + .vsel_mask = BD71837_BUCK5_MASK, + .vsel_range_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, + .vsel_range_mask = BD71837_BUCK5_RANGE_MASK, + .linear_range_selectors = bd71837_buck5_volt_range_sel, + .enable_reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck6", + .of_match = of_match_ptr("BUCK6"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK6, + .ops = &bd718xx_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_BUCK6_VOLTAGE_NUM, + .linear_ranges = bd71837_buck6_volts, + .n_linear_ranges = + ARRAY_SIZE(bd71837_buck6_volts), + .vsel_reg = BD718XX_REG_2ND_NODVS_BUCK_VOLT, + .vsel_mask = BD71837_BUCK6_MASK, + .enable_reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck7", + .of_match = of_match_ptr("BUCK7"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK7, + .ops = &bd718xx_buck_regulator_nolinear_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &bd718xx_3rd_nodvs_buck_volts[0], + .n_voltages = ARRAY_SIZE(bd718xx_3rd_nodvs_buck_volts), + .vsel_reg = BD718XX_REG_3RD_NODVS_BUCK_VOLT, + .vsel_mask = BD718XX_3RD_NODVS_BUCK_MASK, + .enable_reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "buck8", + .of_match = of_match_ptr("BUCK8"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK8, + .ops = &bd718xx_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_4th_nodvs_buck_volts, + .n_linear_ranges = + ARRAY_SIZE(bd718xx_4th_nodvs_buck_volts), + .vsel_reg = BD718XX_REG_4TH_NODVS_BUCK_VOLT, + .vsel_mask = BD718XX_4TH_NODVS_BUCK_MASK, + .enable_reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, + }, + { + .desc = { + .name = "ldo1", + .of_match = of_match_ptr("LDO1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO1, + .ops = &bd718xx_pickable_range_ldo_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_LDO1_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo1_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo1_volts), + .vsel_reg = BD718XX_REG_LDO1_VOLT, + .vsel_mask = BD718XX_LDO1_MASK, + .vsel_range_reg = BD718XX_REG_LDO1_VOLT, + .vsel_range_mask = BD718XX_LDO1_RANGE_MASK, + .linear_range_selectors = bd718xx_ldo1_volt_range_sel, + .enable_reg = BD718XX_REG_LDO1_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO1_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo2", + .of_match = of_match_ptr("LDO2"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO2, + .ops = &bd718xx_ldo_regulator_nolinear_ops, + .type = REGULATOR_VOLTAGE, + .volt_table = &ldo_2_volts[0], + .vsel_reg = BD718XX_REG_LDO2_VOLT, + .vsel_mask = BD718XX_LDO2_MASK, + .n_voltages = ARRAY_SIZE(ldo_2_volts), + .enable_reg = BD718XX_REG_LDO2_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO2_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo3", + .of_match = of_match_ptr("LDO3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO3, + .ops = &bd718xx_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_LDO3_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo3_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo3_volts), + .vsel_reg = BD718XX_REG_LDO3_VOLT, + .vsel_mask = BD718XX_LDO3_MASK, + .enable_reg = BD718XX_REG_LDO3_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO3_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo4", + .of_match = of_match_ptr("LDO4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO4, + .ops = &bd718xx_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_LDO4_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo4_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo4_volts), + .vsel_reg = BD718XX_REG_LDO4_VOLT, + .vsel_mask = BD718XX_LDO4_MASK, + .enable_reg = BD718XX_REG_LDO4_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO4_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, + { + .desc = { + .name = "ldo5", + .of_match = of_match_ptr("LDO5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO5, + .ops = &bd718xx_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_LDO5_VOLTAGE_NUM, + .linear_ranges = bd71837_ldo5_volts, + .n_linear_ranges = ARRAY_SIZE(bd71837_ldo5_volts), + /* LDO5 is supplied by buck6 */ + .supply_name = "buck6", + .vsel_reg = BD718XX_REG_LDO5_VOLT, + .vsel_mask = BD71837_LDO5_MASK, + .enable_reg = BD718XX_REG_LDO5_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO5_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + .additional_inits = bd71837_ldo5_inits, + .additional_init_amnt = ARRAY_SIZE(bd71837_ldo5_inits), + }, + { + .desc = { + .name = "ldo6", + .of_match = of_match_ptr("LDO6"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO6, + .ops = &bd718xx_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_LDO6_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo6_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo6_volts), + /* LDO6 is supplied by buck7 */ + .supply_name = "buck7", + .vsel_reg = BD718XX_REG_LDO6_VOLT, + .vsel_mask = BD718XX_LDO6_MASK, + .enable_reg = BD718XX_REG_LDO6_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_LDO6_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + .additional_inits = bd71837_ldo6_inits, + .additional_init_amnt = ARRAY_SIZE(bd71837_ldo6_inits), + }, + { + .desc = { + .name = "ldo7", + .of_match = of_match_ptr("LDO7"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO7, + .ops = &bd718xx_ldo_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71837_LDO7_VOLTAGE_NUM, + .linear_ranges = bd71837_ldo7_volts, + .n_linear_ranges = ARRAY_SIZE(bd71837_ldo7_volts), + .vsel_reg = BD71837_REG_LDO7_VOLT, + .vsel_mask = BD71837_LDO7_MASK, + .enable_reg = BD71837_REG_LDO7_VOLT, + .enable_mask = BD718XX_LDO_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD71837_REG_LDO7_VOLT, + .mask = BD718XX_LDO_SEL, + .val = BD718XX_LDO_SEL, + }, + }, +}; + +struct bd718xx_pmic_inits { + const struct bd718xx_regulator_data (*r_datas)[]; + unsigned int r_amount; +}; + +static int bd718xx_probe(struct platform_device *pdev) +{ + struct bd718xx_pmic *pmic; + struct regulator_config config = { 0 }; + struct bd718xx_pmic_inits pmic_regulators[] = { + [BD718XX_TYPE_BD71837] = { + .r_datas = &bd71837_regulators, + .r_amount = ARRAY_SIZE(bd71837_regulators), + }, + [BD718XX_TYPE_BD71847] = { + .r_datas = &bd71847_regulators, + .r_amount = ARRAY_SIZE(bd71847_regulators), + }, + }; + + int i, j, err; + + pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); + if (!pmic) + return -ENOMEM; + + pmic->pdev = pdev; + pmic->mfd = dev_get_drvdata(pdev->dev.parent); + + if (!pmic->mfd) { + dev_err(&pdev->dev, "No MFD driver data\n"); + err = -EINVAL; + goto err; + } + if (pmic->mfd->chip_type >= BD718XX_TYPE_AMOUNT || + !pmic_regulators[pmic->mfd->chip_type].r_datas) { + dev_err(&pdev->dev, "Unsupported chip type\n"); + err = -EINVAL; + goto err; + } + + platform_set_drvdata(pdev, pmic); + + /* Register LOCK release */ + err = regmap_update_bits(pmic->mfd->regmap, BD718XX_REG_REGLOCK, + (REGLOCK_PWRSEQ | REGLOCK_VREG), 0); + if (err) { + dev_err(&pmic->pdev->dev, "Failed to unlock PMIC (%d)\n", err); + goto err; + } else { + dev_dbg(&pmic->pdev->dev, "Unlocked lock register 0x%x\n", + BD718XX_REG_REGLOCK); + } + + for (i = 0; i < pmic_regulators[pmic->mfd->chip_type].r_amount; i++) { + + const struct regulator_desc *desc; + struct regulator_dev *rdev; + const struct bd718xx_regulator_data *r; + + r = &(*pmic_regulators[pmic->mfd->chip_type].r_datas)[i]; + desc = &r->desc; + + config.dev = pdev->dev.parent; + config.driver_data = pmic; + config.regmap = pmic->mfd->regmap; + + rdev = devm_regulator_register(&pdev->dev, desc, &config); + if (IS_ERR(rdev)) { + dev_err(pmic->mfd->dev, + "failed to register %s regulator\n", + desc->name); + err = PTR_ERR(rdev); + goto err; + } + /* Regulator register gets the regulator constraints and + * applies them (set_machine_constraints). This should have + * turned the control register(s) to correct values and we + * can now switch the control from PMIC state machine to the + * register interface + */ + err = regmap_update_bits(pmic->mfd->regmap, r->init.reg, + r->init.mask, r->init.val); + if (err) { + dev_err(&pmic->pdev->dev, + "Failed to write BUCK/LDO SEL bit for (%s)\n", + desc->name); + goto err; + } + for (j = 0; j < r->additional_init_amnt; j++) { + err = regmap_update_bits(pmic->mfd->regmap, + r->additional_inits[j].reg, + r->additional_inits[j].mask, + r->additional_inits[j].val); + if (err) { + dev_err(&pmic->pdev->dev, + "Buck (%s) initialization failed\n", + desc->name); + goto err; + } + } + + pmic->rdev[i] = rdev; + } + +err: + return err; +} + +static struct platform_driver bd718xx_regulator = { + .driver = { + .name = "bd718xx-pmic", + }, + .probe = bd718xx_probe, +}; + +module_platform_driver(bd718xx_regulator); + +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); +MODULE_DESCRIPTION("BD71837/BD71847 voltage regulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 45fee12b9878..2c66b528aede 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2788,6 +2788,11 @@ static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, if (desc->ops->list_voltage == regulator_list_voltage_linear_range) return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); + if (desc->ops->list_voltage == + regulator_list_voltage_pickable_linear_range) + return regulator_map_voltage_pickable_linear_range(rdev, + min_uV, max_uV); + return regulator_map_voltage_iterate(rdev, min_uV, max_uV); } @@ -3166,7 +3171,7 @@ static inline int regulator_suspend_toggle(struct regulator_dev *rdev, if (!rstate->changeable) return -EPERM; - rstate->enabled = en; + rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND; return 0; } @@ -4404,13 +4409,13 @@ regulator_register(const struct regulator_desc *regulator_desc, !rdev->desc->fixed_uV) rdev->is_switch = true; + dev_set_drvdata(&rdev->dev, rdev); ret = device_register(&rdev->dev); if (ret != 0) { put_device(&rdev->dev); goto unset_supplies; } - dev_set_drvdata(&rdev->dev, rdev); rdev_init_debugfs(rdev); /* try to resolve regulators supply since a new one was registered */ diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index ef09021dc46e..5686a1335bd3 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -103,6 +103,128 @@ int regulator_disable_regmap(struct regulator_dev *rdev) } EXPORT_SYMBOL_GPL(regulator_disable_regmap); +static int regulator_range_selector_to_index(struct regulator_dev *rdev, + unsigned int rval) +{ + int i; + + if (!rdev->desc->linear_range_selectors) + return -EINVAL; + + rval &= rdev->desc->vsel_range_mask; + + for (i = 0; i < rdev->desc->n_linear_ranges; i++) { + if (rdev->desc->linear_range_selectors[i] == rval) + return i; + } + return -EINVAL; +} + +/** + * regulator_get_voltage_sel_pickable_regmap - pickable range get_voltage_sel + * + * @rdev: regulator to operate on + * + * Regulators that use regmap for their register I/O and use pickable + * ranges can set the vsel_reg, vsel_mask, vsel_range_reg and vsel_range_mask + * fields in their descriptor and then use this as their get_voltage_vsel + * operation, saving some code. + */ +int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev) +{ + unsigned int r_val; + int range; + unsigned int val; + int ret, i; + unsigned int voltages_in_range = 0; + + if (!rdev->desc->linear_ranges) + return -EINVAL; + + ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); + if (ret != 0) + return ret; + + ret = regmap_read(rdev->regmap, rdev->desc->vsel_range_reg, &r_val); + if (ret != 0) + return ret; + + val &= rdev->desc->vsel_mask; + val >>= ffs(rdev->desc->vsel_mask) - 1; + + range = regulator_range_selector_to_index(rdev, r_val); + if (range < 0) + return -EINVAL; + + for (i = 0; i < range; i++) + voltages_in_range += (rdev->desc->linear_ranges[i].max_sel - + rdev->desc->linear_ranges[i].min_sel) + 1; + + return val + voltages_in_range; +} +EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap); + +/** + * regulator_set_voltage_sel_pickable_regmap - pickable range set_voltage_sel + * + * @rdev: regulator to operate on + * @sel: Selector to set + * + * Regulators that use regmap for their register I/O and use pickable + * ranges can set the vsel_reg, vsel_mask, vsel_range_reg and vsel_range_mask + * fields in their descriptor and then use this as their set_voltage_vsel + * operation, saving some code. + */ +int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev, + unsigned int sel) +{ + unsigned int range; + int ret, i; + unsigned int voltages_in_range = 0; + + for (i = 0; i < rdev->desc->n_linear_ranges; i++) { + voltages_in_range = (rdev->desc->linear_ranges[i].max_sel - + rdev->desc->linear_ranges[i].min_sel) + 1; + if (sel < voltages_in_range) + break; + sel -= voltages_in_range; + } + + if (i == rdev->desc->n_linear_ranges) + return -EINVAL; + + sel <<= ffs(rdev->desc->vsel_mask) - 1; + sel += rdev->desc->linear_ranges[i].min_sel; + + range = rdev->desc->linear_range_selectors[i]; + + if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) { + ret = regmap_update_bits(rdev->regmap, + rdev->desc->vsel_reg, + rdev->desc->vsel_range_mask | + rdev->desc->vsel_mask, sel | range); + } else { + ret = regmap_update_bits(rdev->regmap, + rdev->desc->vsel_range_reg, + rdev->desc->vsel_range_mask, range); + if (ret) + return ret; + + ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + rdev->desc->vsel_mask, sel); + } + + if (ret) + return ret; + + if (rdev->desc->apply_bit) + ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg, + rdev->desc->apply_bit, + rdev->desc->apply_bit); + return ret; +} +EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_pickable_regmap); + /** * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users * @@ -338,6 +460,76 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev, EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range); /** + * regulator_map_voltage_pickable_linear_range - map_voltage, pickable ranges + * + * @rdev: Regulator to operate on + * @min_uV: Lower bound for voltage + * @max_uV: Upper bound for voltage + * + * Drivers providing pickable linear_ranges in their descriptor can use + * this as their map_voltage() callback. + */ +int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + const struct regulator_linear_range *range; + int ret = -EINVAL; + int voltage, i; + unsigned int selector = 0; + + if (!rdev->desc->n_linear_ranges) { + BUG_ON(!rdev->desc->n_linear_ranges); + return -EINVAL; + } + + for (i = 0; i < rdev->desc->n_linear_ranges; i++) { + int linear_max_uV; + + range = &rdev->desc->linear_ranges[i]; + linear_max_uV = range->min_uV + + (range->max_sel - range->min_sel) * range->uV_step; + + if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV)) { + selector += (range->max_sel - range->min_sel + 1); + continue; + } + + if (min_uV <= range->min_uV) + min_uV = range->min_uV; + + /* range->uV_step == 0 means fixed voltage range */ + if (range->uV_step == 0) { + ret = 0; + } else { + ret = DIV_ROUND_UP(min_uV - range->min_uV, + range->uV_step); + if (ret < 0) + return ret; + } + + ret += selector; + + voltage = rdev->desc->ops->list_voltage(rdev, ret); + + /* + * Map back into a voltage to verify we're still in bounds. + * We may have overlapping voltage ranges. Hence we don't + * exit but retry until we have checked all ranges. + */ + if (voltage < min_uV || voltage > max_uV) + selector += (range->max_sel - range->min_sel + 1); + else + break; + } + + if (i == rdev->desc->n_linear_ranges) + return -EINVAL; + + return ret; +} +EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range); + +/** * regulator_list_voltage_linear - List voltages with simple calculation * * @rdev: Regulator device @@ -362,6 +554,46 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev, EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); /** + * regulator_list_voltage_pickable_linear_range - pickable range list voltages + * + * @rdev: Regulator device + * @selector: Selector to convert into a voltage + * + * list_voltage() operation, intended to be used by drivers utilizing pickable + * ranges helpers. + */ +int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev, + unsigned int selector) +{ + const struct regulator_linear_range *range; + int i; + unsigned int all_sels = 0; + + if (!rdev->desc->n_linear_ranges) { + BUG_ON(!rdev->desc->n_linear_ranges); + return -EINVAL; + } + + for (i = 0; i < rdev->desc->n_linear_ranges; i++) { + unsigned int sels_in_range; + + range = &rdev->desc->linear_ranges[i]; + + sels_in_range = range->max_sel - range->min_sel; + + if (all_sels + sels_in_range >= selector) { + selector -= all_sels; + return range->min_uV + (range->uV_step * selector); + } + + all_sels += (sels_in_range + 1); + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range); + +/** * regulator_list_voltage_linear_range - List voltages for linear ranges * * @rdev: Regulator device diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 92a516b959a7..c4223b3e0dff 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -213,8 +213,6 @@ static void of_get_regulation_constraints(struct device_node *np, else if (of_property_read_bool(suspend_np, "regulator-off-in-suspend")) suspend_state->enabled = DISABLE_IN_SUSPEND; - else - suspend_state->enabled = DO_NOTHING_IN_SUSPEND; if (!of_property_read_u32(np, "regulator-suspend-min-microvolt", &pval)) diff --git a/include/linux/mfd/da9063/pdata.h b/include/linux/mfd/da9063/pdata.h index 8a125701ef7b..50bed4f89c1a 100644 --- a/include/linux/mfd/da9063/pdata.h +++ b/include/linux/mfd/da9063/pdata.h @@ -21,7 +21,7 @@ /* * Regulator configuration */ -/* DA9063 regulator IDs */ +/* DA9063 and DA9063L regulator IDs */ enum { /* BUCKs */ DA9063_ID_BCORE1, @@ -37,18 +37,20 @@ enum { DA9063_ID_BMEM_BIO_MERGED, /* When two BUCKs are merged, they cannot be reused separately */ - /* LDOs */ + /* LDOs on both DA9063 and DA9063L */ + DA9063_ID_LDO3, + DA9063_ID_LDO7, + DA9063_ID_LDO8, + DA9063_ID_LDO9, + DA9063_ID_LDO11, + + /* DA9063-only LDOs */ DA9063_ID_LDO1, DA9063_ID_LDO2, - DA9063_ID_LDO3, DA9063_ID_LDO4, DA9063_ID_LDO5, DA9063_ID_LDO6, - DA9063_ID_LDO7, - DA9063_ID_LDO8, - DA9063_ID_LDO9, DA9063_ID_LDO10, - DA9063_ID_LDO11, }; /* Regulators platform data */ diff --git a/include/linux/mfd/rohm-bd718x7.h b/include/linux/mfd/rohm-bd718x7.h index a528747f8aed..26acf9a92498 100644 --- a/include/linux/mfd/rohm-bd718x7.h +++ b/include/linux/mfd/rohm-bd718x7.h @@ -1,112 +1,127 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* Copyright (C) 2018 ROHM Semiconductors */ -#ifndef __LINUX_MFD_BD71837_H__ -#define __LINUX_MFD_BD71837_H__ +#ifndef __LINUX_MFD_BD718XX_H__ +#define __LINUX_MFD_BD718XX_H__ #include <linux/regmap.h> enum { - BD71837_BUCK1 = 0, - BD71837_BUCK2, - BD71837_BUCK3, - BD71837_BUCK4, - BD71837_BUCK5, - BD71837_BUCK6, - BD71837_BUCK7, - BD71837_BUCK8, - BD71837_LDO1, - BD71837_LDO2, - BD71837_LDO3, - BD71837_LDO4, - BD71837_LDO5, - BD71837_LDO6, - BD71837_LDO7, - BD71837_REGULATOR_CNT, + BD718XX_TYPE_BD71837 = 0, + BD718XX_TYPE_BD71847, + BD718XX_TYPE_AMOUNT }; -#define BD71837_BUCK1_VOLTAGE_NUM 0x40 -#define BD71837_BUCK2_VOLTAGE_NUM 0x40 -#define BD71837_BUCK3_VOLTAGE_NUM 0x40 -#define BD71837_BUCK4_VOLTAGE_NUM 0x40 +enum { + BD718XX_BUCK1 = 0, + BD718XX_BUCK2, + BD718XX_BUCK3, + BD718XX_BUCK4, + BD718XX_BUCK5, + BD718XX_BUCK6, + BD718XX_BUCK7, + BD718XX_BUCK8, + BD718XX_LDO1, + BD718XX_LDO2, + BD718XX_LDO3, + BD718XX_LDO4, + BD718XX_LDO5, + BD718XX_LDO6, + BD718XX_LDO7, + BD718XX_REGULATOR_AMOUNT, +}; + +/* Common voltage configurations */ +#define BD718XX_DVS_BUCK_VOLTAGE_NUM 0x3D +#define BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM 0x3D + +#define BD718XX_LDO1_VOLTAGE_NUM 0x08 +#define BD718XX_LDO2_VOLTAGE_NUM 0x02 +#define BD718XX_LDO3_VOLTAGE_NUM 0x10 +#define BD718XX_LDO4_VOLTAGE_NUM 0x0A +#define BD718XX_LDO6_VOLTAGE_NUM 0x0A -#define BD71837_BUCK5_VOLTAGE_NUM 0x08 +/* BD71837 specific voltage configurations */ +#define BD71837_BUCK5_VOLTAGE_NUM 0x10 #define BD71837_BUCK6_VOLTAGE_NUM 0x04 #define BD71837_BUCK7_VOLTAGE_NUM 0x08 -#define BD71837_BUCK8_VOLTAGE_NUM 0x40 - -#define BD71837_LDO1_VOLTAGE_NUM 0x04 -#define BD71837_LDO2_VOLTAGE_NUM 0x02 -#define BD71837_LDO3_VOLTAGE_NUM 0x10 -#define BD71837_LDO4_VOLTAGE_NUM 0x10 #define BD71837_LDO5_VOLTAGE_NUM 0x10 -#define BD71837_LDO6_VOLTAGE_NUM 0x10 #define BD71837_LDO7_VOLTAGE_NUM 0x10 +/* BD71847 specific voltage configurations */ +#define BD71847_BUCK3_VOLTAGE_NUM 0x18 +#define BD71847_BUCK4_VOLTAGE_NUM 0x08 +#define BD71847_LDO5_VOLTAGE_NUM 0x20 + +/* Registers specific to BD71837 */ +enum { + BD71837_REG_BUCK3_CTRL = 0x07, + BD71837_REG_BUCK4_CTRL = 0x08, + BD71837_REG_BUCK3_VOLT_RUN = 0x12, + BD71837_REG_BUCK4_VOLT_RUN = 0x13, + BD71837_REG_LDO7_VOLT = 0x1E, +}; + +/* Registers common for BD71837 and BD71847 */ enum { - BD71837_REG_REV = 0x00, - BD71837_REG_SWRESET = 0x01, - BD71837_REG_I2C_DEV = 0x02, - BD71837_REG_PWRCTRL0 = 0x03, - BD71837_REG_PWRCTRL1 = 0x04, - BD71837_REG_BUCK1_CTRL = 0x05, - BD71837_REG_BUCK2_CTRL = 0x06, - BD71837_REG_BUCK3_CTRL = 0x07, - BD71837_REG_BUCK4_CTRL = 0x08, - BD71837_REG_BUCK5_CTRL = 0x09, - BD71837_REG_BUCK6_CTRL = 0x0A, - BD71837_REG_BUCK7_CTRL = 0x0B, - BD71837_REG_BUCK8_CTRL = 0x0C, - BD71837_REG_BUCK1_VOLT_RUN = 0x0D, - BD71837_REG_BUCK1_VOLT_IDLE = 0x0E, - BD71837_REG_BUCK1_VOLT_SUSP = 0x0F, - BD71837_REG_BUCK2_VOLT_RUN = 0x10, - BD71837_REG_BUCK2_VOLT_IDLE = 0x11, - BD71837_REG_BUCK3_VOLT_RUN = 0x12, - BD71837_REG_BUCK4_VOLT_RUN = 0x13, - BD71837_REG_BUCK5_VOLT = 0x14, - BD71837_REG_BUCK6_VOLT = 0x15, - BD71837_REG_BUCK7_VOLT = 0x16, - BD71837_REG_BUCK8_VOLT = 0x17, - BD71837_REG_LDO1_VOLT = 0x18, - BD71837_REG_LDO2_VOLT = 0x19, - BD71837_REG_LDO3_VOLT = 0x1A, - BD71837_REG_LDO4_VOLT = 0x1B, - BD71837_REG_LDO5_VOLT = 0x1C, - BD71837_REG_LDO6_VOLT = 0x1D, - BD71837_REG_LDO7_VOLT = 0x1E, - BD71837_REG_TRANS_COND0 = 0x1F, - BD71837_REG_TRANS_COND1 = 0x20, - BD71837_REG_VRFAULTEN = 0x21, - BD71837_REG_MVRFLTMASK0 = 0x22, - BD71837_REG_MVRFLTMASK1 = 0x23, - BD71837_REG_MVRFLTMASK2 = 0x24, - BD71837_REG_RCVCFG = 0x25, - BD71837_REG_RCVNUM = 0x26, - BD71837_REG_PWRONCONFIG0 = 0x27, - BD71837_REG_PWRONCONFIG1 = 0x28, - BD71837_REG_RESETSRC = 0x29, - BD71837_REG_MIRQ = 0x2A, - BD71837_REG_IRQ = 0x2B, - BD71837_REG_IN_MON = 0x2C, - BD71837_REG_POW_STATE = 0x2D, - BD71837_REG_OUT32K = 0x2E, - BD71837_REG_REGLOCK = 0x2F, - BD71837_REG_OTPVER = 0xFF, - BD71837_MAX_REGISTER = 0x100, + BD718XX_REG_REV = 0x00, + BD718XX_REG_SWRESET = 0x01, + BD718XX_REG_I2C_DEV = 0x02, + BD718XX_REG_PWRCTRL0 = 0x03, + BD718XX_REG_PWRCTRL1 = 0x04, + BD718XX_REG_BUCK1_CTRL = 0x05, + BD718XX_REG_BUCK2_CTRL = 0x06, + BD718XX_REG_1ST_NODVS_BUCK_CTRL = 0x09, + BD718XX_REG_2ND_NODVS_BUCK_CTRL = 0x0A, + BD718XX_REG_3RD_NODVS_BUCK_CTRL = 0x0B, + BD718XX_REG_4TH_NODVS_BUCK_CTRL = 0x0C, + BD718XX_REG_BUCK1_VOLT_RUN = 0x0D, + BD718XX_REG_BUCK1_VOLT_IDLE = 0x0E, + BD718XX_REG_BUCK1_VOLT_SUSP = 0x0F, + BD718XX_REG_BUCK2_VOLT_RUN = 0x10, + BD718XX_REG_BUCK2_VOLT_IDLE = 0x11, + BD718XX_REG_1ST_NODVS_BUCK_VOLT = 0x14, + BD718XX_REG_2ND_NODVS_BUCK_VOLT = 0x15, + BD718XX_REG_3RD_NODVS_BUCK_VOLT = 0x16, + BD718XX_REG_4TH_NODVS_BUCK_VOLT = 0x17, + BD718XX_REG_LDO1_VOLT = 0x18, + BD718XX_REG_LDO2_VOLT = 0x19, + BD718XX_REG_LDO3_VOLT = 0x1A, + BD718XX_REG_LDO4_VOLT = 0x1B, + BD718XX_REG_LDO5_VOLT = 0x1C, + BD718XX_REG_LDO6_VOLT = 0x1D, + BD718XX_REG_TRANS_COND0 = 0x1F, + BD718XX_REG_TRANS_COND1 = 0x20, + BD718XX_REG_VRFAULTEN = 0x21, + BD718XX_REG_MVRFLTMASK0 = 0x22, + BD718XX_REG_MVRFLTMASK1 = 0x23, + BD718XX_REG_MVRFLTMASK2 = 0x24, + BD718XX_REG_RCVCFG = 0x25, + BD718XX_REG_RCVNUM = 0x26, + BD718XX_REG_PWRONCONFIG0 = 0x27, + BD718XX_REG_PWRONCONFIG1 = 0x28, + BD718XX_REG_RESETSRC = 0x29, + BD718XX_REG_MIRQ = 0x2A, + BD718XX_REG_IRQ = 0x2B, + BD718XX_REG_IN_MON = 0x2C, + BD718XX_REG_POW_STATE = 0x2D, + BD718XX_REG_OUT32K = 0x2E, + BD718XX_REG_REGLOCK = 0x2F, + BD718XX_REG_OTPVER = 0xFF, + BD718XX_MAX_REGISTER = 0x100, }; #define REGLOCK_PWRSEQ 0x1 #define REGLOCK_VREG 0x10 /* Generic BUCK control masks */ -#define BD71837_BUCK_SEL 0x02 -#define BD71837_BUCK_EN 0x01 -#define BD71837_BUCK_RUN_ON 0x04 +#define BD718XX_BUCK_SEL 0x02 +#define BD718XX_BUCK_EN 0x01 +#define BD718XX_BUCK_RUN_ON 0x04 /* Generic LDO masks */ -#define BD71837_LDO_SEL 0x80 -#define BD71837_LDO_EN 0x40 +#define BD718XX_LDO_SEL 0x80 +#define BD718XX_LDO_EN 0x40 /* BD71837 BUCK ramp rate CTRL reg bits */ #define BUCK_RAMPRATE_MASK 0xC0 @@ -115,51 +130,64 @@ enum { #define BUCK_RAMPRATE_2P50MV 0x2 #define BUCK_RAMPRATE_1P25MV 0x3 -/* BD71837_REG_BUCK1_VOLT_RUN bits */ -#define BUCK1_RUN_MASK 0x3F -#define BUCK1_RUN_DEFAULT 0x14 - -/* BD71837_REG_BUCK1_VOLT_SUSP bits */ -#define BUCK1_SUSP_MASK 0x3F -#define BUCK1_SUSP_DEFAULT 0x14 - -/* BD71837_REG_BUCK1_VOLT_IDLE bits */ -#define BUCK1_IDLE_MASK 0x3F -#define BUCK1_IDLE_DEFAULT 0x14 - -/* BD71837_REG_BUCK2_VOLT_RUN bits */ -#define BUCK2_RUN_MASK 0x3F -#define BUCK2_RUN_DEFAULT 0x1E - -/* BD71837_REG_BUCK2_VOLT_IDLE bits */ -#define BUCK2_IDLE_MASK 0x3F -#define BUCK2_IDLE_DEFAULT 0x14 - -/* BD71837_REG_BUCK3_VOLT_RUN bits */ -#define BUCK3_RUN_MASK 0x3F -#define BUCK3_RUN_DEFAULT 0x1E - -/* BD71837_REG_BUCK4_VOLT_RUN bits */ -#define BUCK4_RUN_MASK 0x3F -#define BUCK4_RUN_DEFAULT 0x1E - -/* BD71837_REG_BUCK5_VOLT bits */ -#define BUCK5_MASK 0x07 -#define BUCK5_DEFAULT 0x02 - -/* BD71837_REG_BUCK6_VOLT bits */ -#define BUCK6_MASK 0x03 -#define BUCK6_DEFAULT 0x03 - -/* BD71837_REG_BUCK7_VOLT bits */ -#define BUCK7_MASK 0x07 -#define BUCK7_DEFAULT 0x03 - -/* BD71837_REG_BUCK8_VOLT bits */ -#define BUCK8_MASK 0x3F -#define BUCK8_DEFAULT 0x1E - -/* BD71837_REG_IRQ bits */ +#define DVS_BUCK_RUN_MASK 0x3F +#define DVS_BUCK_SUSP_MASK 0x3F +#define DVS_BUCK_IDLE_MASK 0x3F + +#define BD718XX_1ST_NODVS_BUCK_MASK 0x07 +#define BD718XX_3RD_NODVS_BUCK_MASK 0x07 +#define BD718XX_4TH_NODVS_BUCK_MASK 0x3F + +#define BD71847_BUCK3_MASK 0x07 +#define BD71847_BUCK3_RANGE_MASK 0xC0 +#define BD71847_BUCK4_MASK 0x03 +#define BD71847_BUCK4_RANGE_MASK 0x40 + +#define BD71837_BUCK5_MASK 0x07 +#define BD71837_BUCK5_RANGE_MASK 0x80 +#define BD71837_BUCK6_MASK 0x03 + +#define BD718XX_LDO1_MASK 0x03 +#define BD718XX_LDO1_RANGE_MASK 0x20 +#define BD718XX_LDO2_MASK 0x20 +#define BD718XX_LDO3_MASK 0x0F +#define BD718XX_LDO4_MASK 0x0F +#define BD718XX_LDO6_MASK 0x0F + +#define BD71837_LDO5_MASK 0x0F +#define BD71847_LDO5_MASK 0x0F +#define BD71847_LDO5_RANGE_MASK 0x20 + +#define BD71837_LDO7_MASK 0x0F + +/* BD718XX Voltage monitoring masks */ +#define BD718XX_BUCK1_VRMON80 0x1 +#define BD718XX_BUCK1_VRMON130 0x2 +#define BD718XX_BUCK2_VRMON80 0x4 +#define BD718XX_BUCK2_VRMON130 0x8 +#define BD718XX_1ST_NODVS_BUCK_VRMON80 0x1 +#define BD718XX_1ST_NODVS_BUCK_VRMON130 0x2 +#define BD718XX_2ND_NODVS_BUCK_VRMON80 0x4 +#define BD718XX_2ND_NODVS_BUCK_VRMON130 0x8 +#define BD718XX_3RD_NODVS_BUCK_VRMON80 0x10 +#define BD718XX_3RD_NODVS_BUCK_VRMON130 0x20 +#define BD718XX_4TH_NODVS_BUCK_VRMON80 0x40 +#define BD718XX_4TH_NODVS_BUCK_VRMON130 0x80 +#define BD718XX_LDO1_VRMON80 0x1 +#define BD718XX_LDO2_VRMON80 0x2 +#define BD718XX_LDO3_VRMON80 0x4 +#define BD718XX_LDO4_VRMON80 0x8 +#define BD718XX_LDO5_VRMON80 0x10 +#define BD718XX_LDO6_VRMON80 0x20 + +/* BD71837 specific voltage monitoring masks */ +#define BD71837_BUCK3_VRMON80 0x10 +#define BD71837_BUCK3_VRMON130 0x20 +#define BD71837_BUCK4_VRMON80 0x40 +#define BD71837_BUCK4_VRMON130 0x80 +#define BD71837_LDO7_VRMON80 0x40 + +/* BD718XX_REG_IRQ bits */ #define IRQ_SWRST 0x40 #define IRQ_PWRON_S 0x20 #define IRQ_PWRON_L 0x10 @@ -168,52 +196,31 @@ enum { #define IRQ_ON_REQ 0x02 #define IRQ_STBY_REQ 0x01 -/* BD71837_REG_OUT32K bits */ -#define BD71837_OUT32K_EN 0x01 +/* BD718XX_REG_OUT32K bits */ +#define BD718XX_OUT32K_EN 0x01 -/* BD71837 gated clock rate */ -#define BD71837_CLK_RATE 32768 +/* BD7183XX gated clock rate */ +#define BD718XX_CLK_RATE 32768 -/* ROHM BD71837 irqs */ +/* ROHM BD718XX irqs */ enum { - BD71837_INT_STBY_REQ, - BD71837_INT_ON_REQ, - BD71837_INT_WDOG, - BD71837_INT_PWRBTN, - BD71837_INT_PWRBTN_L, - BD71837_INT_PWRBTN_S, - BD71837_INT_SWRST + BD718XX_INT_STBY_REQ, + BD718XX_INT_ON_REQ, + BD718XX_INT_WDOG, + BD718XX_INT_PWRBTN, + BD718XX_INT_PWRBTN_L, + BD718XX_INT_PWRBTN_S, + BD718XX_INT_SWRST }; -/* ROHM BD71837 interrupt masks */ -#define BD71837_INT_SWRST_MASK 0x40 -#define BD71837_INT_PWRBTN_S_MASK 0x20 -#define BD71837_INT_PWRBTN_L_MASK 0x10 -#define BD71837_INT_PWRBTN_MASK 0x8 -#define BD71837_INT_WDOG_MASK 0x4 -#define BD71837_INT_ON_REQ_MASK 0x2 -#define BD71837_INT_STBY_REQ_MASK 0x1 - -/* BD71837_REG_LDO1_VOLT bits */ -#define LDO1_MASK 0x03 - -/* BD71837_REG_LDO1_VOLT bits */ -#define LDO2_MASK 0x20 - -/* BD71837_REG_LDO3_VOLT bits */ -#define LDO3_MASK 0x0F - -/* BD71837_REG_LDO4_VOLT bits */ -#define LDO4_MASK 0x0F - -/* BD71837_REG_LDO5_VOLT bits */ -#define LDO5_MASK 0x0F - -/* BD71837_REG_LDO6_VOLT bits */ -#define LDO6_MASK 0x0F - -/* BD71837_REG_LDO7_VOLT bits */ -#define LDO7_MASK 0x0F +/* ROHM BD718XX interrupt masks */ +#define BD718XX_INT_SWRST_MASK 0x40 +#define BD718XX_INT_PWRBTN_S_MASK 0x20 +#define BD718XX_INT_PWRBTN_L_MASK 0x10 +#define BD718XX_INT_PWRBTN_MASK 0x8 +#define BD718XX_INT_WDOG_MASK 0x4 +#define BD718XX_INT_ON_REQ_MASK 0x2 +#define BD718XX_INT_STBY_REQ_MASK 0x1 /* Register write induced reset settings */ @@ -223,13 +230,13 @@ enum { * write 1 to it we will trigger the action. So always write 0 to it when * changning SWRESET action - no matter what we read from it. */ -#define BD71837_SWRESET_TYPE_MASK 7 -#define BD71837_SWRESET_TYPE_DISABLED 0 -#define BD71837_SWRESET_TYPE_COLD 4 -#define BD71837_SWRESET_TYPE_WARM 6 +#define BD718XX_SWRESET_TYPE_MASK 7 +#define BD718XX_SWRESET_TYPE_DISABLED 0 +#define BD718XX_SWRESET_TYPE_COLD 4 +#define BD718XX_SWRESET_TYPE_WARM 6 -#define BD71837_SWRESET_RESET_MASK 1 -#define BD71837_SWRESET_RESET 1 +#define BD718XX_SWRESET_RESET_MASK 1 +#define BD718XX_SWRESET_RESET 1 /* Poweroff state transition conditions */ @@ -314,10 +321,11 @@ enum { BD718XX_PWRBTN_LONG_PRESS_15S }; -struct bd71837_pmic; -struct bd71837_clk; +struct bd718xx_pmic; +struct bd718xx_clk; -struct bd71837 { +struct bd718xx { + unsigned int chip_type; struct device *dev; struct regmap *regmap; unsigned long int id; @@ -325,8 +333,8 @@ struct bd71837 { int chip_irq; struct regmap_irq_chip_data *irq_data; - struct bd71837_pmic *pmic; - struct bd71837_clk *clk; + struct bd718xx_pmic *pmic; + struct bd718xx_clk *clk; }; -#endif /* __LINUX_MFD_BD71837_H__ */ +#endif /* __LINUX_MFD_BD718XX_H__ */ diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 0fd8fbb74763..a9c030192147 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -271,9 +271,16 @@ enum regulator_type { * @ramp_delay: Time to settle down after voltage change (unit: uV/us) * @min_dropout_uV: The minimum dropout voltage this regulator can handle * @linear_ranges: A constant table of possible voltage ranges. - * @n_linear_ranges: Number of entries in the @linear_ranges table. + * @linear_range_selectors: A constant table of voltage range selectors. + * If pickable ranges are used each range must + * have corresponding selector here. + * @n_linear_ranges: Number of entries in the @linear_ranges (and in + * linear_range_selectors if used) table(s). * @volt_table: Voltage mapping table (if table based mapping) * + * @vsel_range_reg: Register for range selector when using pickable ranges + * and regulator_regmap_X_voltage_X_pickable functions. + * @vsel_range_mask: Mask for register bitfield used for range selector * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @vsel_mask: Mask for register bitfield used for selector * @csel_reg: Register for TPS65218 LS3 current regulator @@ -338,10 +345,14 @@ struct regulator_desc { int min_dropout_uV; const struct regulator_linear_range *linear_ranges; + const unsigned int *linear_range_selectors; + int n_linear_ranges; const unsigned int *volt_table; + unsigned int vsel_range_reg; + unsigned int vsel_range_mask; unsigned int vsel_reg; unsigned int vsel_mask; unsigned int csel_reg; @@ -498,18 +509,25 @@ int regulator_mode_to_status(unsigned int); int regulator_list_voltage_linear(struct regulator_dev *rdev, unsigned int selector); +int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev, + unsigned int selector); int regulator_list_voltage_linear_range(struct regulator_dev *rdev, unsigned int selector); int regulator_list_voltage_table(struct regulator_dev *rdev, unsigned int selector); int regulator_map_voltage_linear(struct regulator_dev *rdev, int min_uV, int max_uV); +int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev, + int min_uV, int max_uV); int regulator_map_voltage_linear_range(struct regulator_dev *rdev, int min_uV, int max_uV); int regulator_map_voltage_iterate(struct regulator_dev *rdev, int min_uV, int max_uV); int regulator_map_voltage_ascend(struct regulator_dev *rdev, int min_uV, int max_uV); +int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev); +int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev, + unsigned int sel); int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev); int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel); int regulator_is_enabled_regmap(struct regulator_dev *rdev); diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 3468703d663a..a459a5e973a7 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -48,9 +48,9 @@ struct regulator; * DISABLE_IN_SUSPEND - turn off regulator in suspend states * ENABLE_IN_SUSPEND - keep regulator on in suspend states */ -#define DO_NOTHING_IN_SUSPEND (-1) -#define DISABLE_IN_SUSPEND 0 -#define ENABLE_IN_SUSPEND 1 +#define DO_NOTHING_IN_SUSPEND 0 +#define DISABLE_IN_SUSPEND 1 +#define ENABLE_IN_SUSPEND 2 /* Regulator active discharge flags */ enum regulator_active_discharge { |