From 823f18f8b860526fc099c222619a126d57d2ad8c Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 29 Aug 2018 15:36:10 +0300 Subject: regulator: bd71837: Disable voltage monitoring for LDO3/4 There is a HW quirk in BD71837. The shutdown sequence timings for bucks/LDOs which are enabled via register interface are changed. At PMIC poweroff the voltage for BUCK6/7 is cut immediately at the beginning of shut-down sequence. This causes LDO5/6 voltage monitoring to detect under voltage and force PMIC to emergency state instead of poweroff. Disable voltage monitoring for LDO5 and LDO6 at probe to avoid this. Signed-off-by: Matti Vaittinen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/bd71837-regulator.c | 19 +++++++++++++++++++ include/linux/mfd/rohm-bd718x7.h | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c index 0f8ac8dec3e1..a1bd8aaf4d98 100644 --- a/drivers/regulator/bd71837-regulator.c +++ b/drivers/regulator/bd71837-regulator.c @@ -569,6 +569,25 @@ static int bd71837_probe(struct platform_device *pdev) BD71837_REG_REGLOCK); } + /* + * 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 + */ + err = regmap_update_bits(pmic->mfd->regmap, BD718XX_REG_MVRFLTMASK2, + BD718XX_LDO5_VRMON80 | BD718XX_LDO6_VRMON80, + BD718XX_LDO5_VRMON80 | BD718XX_LDO6_VRMON80); + if (err) { + dev_err(&pmic->pdev->dev, + "Failed to disable voltage monitoring\n"); + goto err; + } + for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) { struct regulator_desc *desc; diff --git a/include/linux/mfd/rohm-bd718x7.h b/include/linux/mfd/rohm-bd718x7.h index a528747f8aed..e8338e5dc10b 100644 --- a/include/linux/mfd/rohm-bd718x7.h +++ b/include/linux/mfd/rohm-bd718x7.h @@ -78,9 +78,9 @@ enum { 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, + BD718XX_REG_MVRFLTMASK0 = 0x22, + BD718XX_REG_MVRFLTMASK1 = 0x23, + BD718XX_REG_MVRFLTMASK2 = 0x24, BD71837_REG_RCVCFG = 0x25, BD71837_REG_RCVNUM = 0x26, BD71837_REG_PWRONCONFIG0 = 0x27, @@ -159,6 +159,33 @@ enum { #define BUCK8_MASK 0x3F #define BUCK8_DEFAULT 0x1E +/* 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 + /* BD71837_REG_IRQ bits */ #define IRQ_SWRST 0x40 #define IRQ_PWRON_S 0x20 -- cgit v1.2.3 From ef394f3fbecbe61d69450ad8cf0fa8f713c8ce8f Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 31 Aug 2018 14:34:02 +0200 Subject: regulator: da9063: fix DT probing with constraints Commit 1c892e38ce59 ("regulator: da9063: Handle less LDOs on DA9063L") reordered the da9063_regulator_info[] array, but not the DA9063_ID_* regulator ids and not the da9063_matches[] array, because ids are used as indices in the array initializer. This mismatch between regulator id and da9063_regulator_info[] array index causes the driver probe to fail because constraints from DT are not applied to the correct regulator: da9063 0-0058: Device detected (chip-ID: 0x61, var-ID: 0x50) DA9063_BMEM: Bringing 900000uV into 3300000-3300000uV DA9063_LDO9: Bringing 3300000uV into 2500000-2500000uV DA9063_LDO1: Bringing 900000uV into 3300000-3300000uV DA9063_LDO1: failed to apply 3300000-3300000uV constraint(-22) This patch reorders the DA9063_ID_* as apparently intended, and with them the entries in the da90630_matches[] array. Fixes: 1c892e38ce59 ("regulator: da9063: Handle less LDOs on DA9063L") Signed-off-by: Philipp Zabel Reviewed-by: Geert Uytterhoeven Reviewed-by: Marek Vasut Signed-off-by: Mark Brown --- include/linux/mfd/da9063/pdata.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) 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 */ -- cgit v1.2.3 From 3edd79cf5a44b12dbb13bc320f5788aed6562b36 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 3 Sep 2018 16:49:37 +0200 Subject: regulator: Fix 'do-nothing' value for regulators without suspend state Some regulators don't have all states defined and in such cases regulator core should not assume anything. However in current implementation of of_get_regulation_constraints() DO_NOTHING_IN_SUSPEND enable value was set only for regulators which had suspend node defined, otherwise the default 0 value was used, what means DISABLE_IN_SUSPEND. This lead to broken system suspend/resume on boards, which had simple regulator constraints definition (without suspend state nodes). To avoid further mismatches between the default and uninitialized values of the suspend enabled/disabled states, change the values of the them, so default '0' means DO_NOTHING_IN_SUSPEND. Fixes: 72069f9957a1: regulator: leave one item to record whether regulator is enabled Signed-off-by: Marek Szyprowski Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/core.c | 2 +- drivers/regulator/of_regulator.c | 2 -- include/linux/regulator/machine.h | 6 +++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index bb1324f93143..90215f57270f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3161,7 +3161,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; } diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 638f17d4c848..210fc20f7de7 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/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 { -- cgit v1.2.3 From fb6de923ca3358a91525552b4907d4cb38730bdd Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 19 Sep 2018 15:30:51 -0600 Subject: regulator: fix crash caused by null driver data dev_set_drvdata() needs to be called before device_register() exposes device to userspace. Otherwise kernel crashes after it gets null pointer from dev_get_drvdata() when userspace tries to access sysfs entries. [Removed backtrace for length -- broonie] Signed-off-by: Yu Zhao Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/regulator/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 90215f57270f..9577d8941846 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -4395,13 +4395,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 */ -- cgit v1.2.3 From 494edd266b945f36908184433dd36eda1719cdb0 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 14 Sep 2018 11:27:46 +0300 Subject: regulator/mfd: Support ROHM BD71847 power management IC BD71847 is reduced version of BD71837. DVS bucks 3 and 4 are removed as is LDO7. Voltage ranges of some regulators are expanded. Add initial support for BD71847 with BD71837 driver. Signed-off-by: Matti Vaittinen Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/mfd/rohm-bd718x7.c | 70 +-- drivers/regulator/bd71837-regulator.c | 1055 +++++++++++++++++++++++---------- include/linux/mfd/rohm-bd718x7.h | 271 ++++----- 3 files changed, 879 insertions(+), 517 deletions(-) diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c index 75c8ec659547..ce5aa5cd3545 100644 --- a/drivers/mfd/rohm-bd718x7.c +++ b/drivers/mfd/rohm-bd718x7.c @@ -7,21 +7,16 @@ // Datasheet available from // https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e +#include #include #include #include #include #include #include +#include #include - -/* - * 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 - -static const u8 supported_revisions[] = { 0xA2 /* BD71837 */ }; +#include static struct gpio_keys_button button = { .code = KEY_POWER, @@ -41,8 +36,8 @@ static struct mfd_cell bd71837_mfd_cells[] = { .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[] = { @@ -61,16 +56,16 @@ static struct regmap_irq_chip bd71837_irq_chip = { .num_irqs = ARRAY_SIZE(bd71837_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 = { @@ -82,7 +77,7 @@ static const struct regmap_config bd71837_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, }; @@ -90,8 +85,12 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct bd71837 *bd71837; - int ret, i; - unsigned int val; + int ret; + + if (!i2c->irq) { + dev_err(&i2c->dev, "No IRQ configured\n"); + return -EINVAL; + } bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL); @@ -99,12 +98,8 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, return -ENOMEM; bd71837->chip_irq = i2c->irq; - - if (!bd71837->chip_irq) { - dev_err(&i2c->dev, "No IRQ configured\n"); - return -EINVAL; - } - + bd71837->chip_type = (unsigned int)(uintptr_t) + of_device_get_match_data(&i2c->dev); bd71837->dev = &i2c->dev; dev_set_drvdata(&i2c->dev, bd71837); @@ -114,20 +109,6 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, return PTR_ERR(bd71837->regmap); } - 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; - - if (i == ARRAY_SIZE(supported_revisions)) { - dev_err(&i2c->dev, "Unsupported chip revision\n"); - return -ENODEV; - } - ret = devm_regmap_add_irq_chip(&i2c->dev, bd71837->regmap, bd71837->chip_irq, IRQF_ONESHOT, 0, &bd71837_irq_chip, &bd71837->irq_data); @@ -138,7 +119,7 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, /* Configure short press to 10 milliseconds */ ret = regmap_update_bits(bd71837->regmap, - BD71837_REG_PWRONCONFIG0, + BD718XX_REG_PWRONCONFIG0, BD718XX_PWRBTN_PRESS_DURATION_MASK, BD718XX_PWRBTN_SHORT_PRESS_10MS); if (ret) { @@ -149,7 +130,7 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, /* Configure long press to 10 seconds */ ret = regmap_update_bits(bd71837->regmap, - BD71837_REG_PWRONCONFIG1, + BD718XX_REG_PWRONCONFIG1, BD718XX_PWRBTN_PRESS_DURATION_MASK, BD718XX_PWRBTN_LONG_PRESS_10S); @@ -179,7 +160,14 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, } static const struct of_device_id bd71837_of_match[] = { - { .compatible = "rohm,bd71837", }, + { + .compatible = "rohm,bd71837", + .data = (void *)BD718XX_TYPE_BD71837, + }, + { + .compatible = "rohm,bd71847", + .data = (void *)BD718XX_TYPE_BD71847, + }, { } }; MODULE_DEVICE_TABLE(of, bd71837_of_match); diff --git a/drivers/regulator/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c index 4f4599acfebd..1dbba20ede3e 100644 --- a/drivers/regulator/bd71837-regulator.c +++ b/drivers/regulator/bd71837-regulator.c @@ -15,11 +15,11 @@ #include #include -struct bd71837_pmic { - struct regulator_desc descs[BD71837_REGULATOR_CNT]; +struct bd718xx_pmic { + struct bd718xx_regulator_data *rdata; struct bd71837 *mfd; struct platform_device *pdev; - struct regulator_dev *rdev[BD71837_REGULATOR_CNT]; + struct regulator_dev *rdev[BD718XX_REGULATOR_AMOUNT]; }; /* @@ -33,7 +33,7 @@ struct bd71837_pmic { static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { - struct bd71837_pmic *pmic = rdev_get_drvdata(rdev); + struct bd718xx_pmic *pmic = rdev_get_drvdata(rdev); struct bd71837 *mfd = pmic->mfd; int id = rdev->desc->id; unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; @@ -60,7 +60,7 @@ static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, rdev->desc->name, ramp_delay); } - return regmap_update_bits(mfd->regmap, BD71837_REG_BUCK1_CTRL + id, + return regmap_update_bits(mfd->regmap, BD718XX_REG_BUCK1_CTRL + id, BUCK_RAMPRATE_MASK, ramp_value << 6); } @@ -69,7 +69,7 @@ static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, * 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, +static int bd718xx_set_voltage_sel_restricted(struct regulator_dev *rdev, unsigned int sel) { if (regulator_is_enabled_regmap(rdev)) @@ -78,45 +78,45 @@ static int bd71837_set_voltage_sel_restricted(struct regulator_dev *rdev, return regulator_set_voltage_sel_regmap(rdev, sel); } -static struct regulator_ops bd71837_ldo_regulator_ops = { +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 = bd71837_set_voltage_sel_restricted, + .set_voltage_sel = bd718xx_set_voltage_sel_restricted, .get_voltage_sel = regulator_get_voltage_sel_regmap, }; -static struct regulator_ops bd71837_ldo_regulator_nolinear_ops = { +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 = bd71837_set_voltage_sel_restricted, + .set_voltage_sel = bd718xx_set_voltage_sel_restricted, .get_voltage_sel = regulator_get_voltage_sel_regmap, }; -static struct regulator_ops bd71837_buck_regulator_ops = { +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 = bd71837_set_voltage_sel_restricted, + .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 bd71837_buck_regulator_nolinear_ops = { +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 = bd71837_set_voltage_sel_restricted, + .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 bd71837_buck1234_regulator_ops = { +static struct regulator_ops bd718xx_dvs_buck_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -128,24 +128,30 @@ static struct regulator_ops bd71837_buck1234_regulator_ops = { }; /* - * BUCK1/2/3/4 + * BD71837 BUCK1/2/3/4 + * BD71847 BUCK1/2 * 0.70 to 1.30V (10mV step) */ -static const struct regulator_linear_range bd71837_buck1234_voltage_ranges[] = { +static const struct regulator_linear_range bd718xx_dvs_buck_volts[] = { REGULATOR_LINEAR_RANGE(700000, 0x00, 0x3C, 10000), REGULATOR_LINEAR_RANGE(1300000, 0x3D, 0x3F, 0), }; /* - * BUCK5 - * 0.9V to 1.35V () + * BD71837 BUCK5 + * BD71847 BUCK3 + * 0.7V to 1.35V () */ -static const struct regulator_linear_range bd71837_buck5_voltage_ranges[] = { +static const struct regulator_linear_range bd718xx_1st_nodvs_buck_volts[] = { REGULATOR_LINEAR_RANGE(700000, 0x00, 0x03, 100000), REGULATOR_LINEAR_RANGE(1050000, 0x04, 0x05, 50000), REGULATOR_LINEAR_RANGE(1200000, 0x06, 0x07, 150000), }; +static const struct regulator_linear_range bd71847_buck4_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), +}; + /* * BUCK6 * 3.0V to 3.3V (step 100mV) @@ -155,7 +161,8 @@ static const struct regulator_linear_range bd71837_buck6_voltage_ranges[] = { }; /* - * BUCK7 + * BD71837 BUCK7 + * BD71847 BUCK5 * 000 = 1.605V * 001 = 1.695V * 010 = 1.755V @@ -165,7 +172,7 @@ static const struct regulator_linear_range bd71837_buck6_voltage_ranges[] = { * 110 = 1.95V * 111 = 1.995V */ -static const unsigned int buck_7_volts[] = { +static const unsigned int bd718xx_3rd_nodvs_buck_volts[] = { 1605000, 1695000, 1755000, 1800000, 1845000, 1905000, 1950000, 1995000 }; @@ -173,16 +180,15 @@ static const unsigned int buck_7_volts[] = { * BUCK8 * 0.8V to 1.40V (step 10mV) */ -static const struct regulator_linear_range bd71837_buck8_voltage_ranges[] = { +static const struct regulator_linear_range bd718xx_4th_nodvs_buck_volts[] = { 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[] = { +static const struct regulator_linear_range bd718xx_ldo1_volts[] = { REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), }; @@ -198,7 +204,7 @@ static const unsigned int ldo_2_volts[] = { * LDO3 * 1.8 to 3.3V (100mV step) */ -static const struct regulator_linear_range bd71837_ldo3_voltage_ranges[] = { +static const struct regulator_linear_range bd718xx_ldo3_volts[] = { REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), }; @@ -206,16 +212,15 @@ static const struct regulator_linear_range bd71837_ldo3_voltage_ranges[] = { * LDO4 * 0.9 to 1.8V (100mV step) */ -static const struct regulator_linear_range bd71837_ldo4_voltage_ranges[] = { +static const struct regulator_linear_range bd718xx_ldo4_volts[] = { REGULATOR_LINEAR_RANGE(900000, 0x00, 0x09, 100000), - REGULATOR_LINEAR_RANGE(1800000, 0x0A, 0x0F, 0), }; /* - * LDO5 + * LDO5 for BD71837 * 1.8 to 3.3V (100mV step) */ -static const struct regulator_linear_range bd71837_ldo5_voltage_ranges[] = { +static const struct regulator_linear_range bd718xx_ldo5_volts[] = { REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), }; @@ -223,330 +228,722 @@ static const struct regulator_linear_range bd71837_ldo5_voltage_ranges[] = { * LDO6 * 0.9 to 1.8V (100mV step) */ -static const struct regulator_linear_range bd71837_ldo6_voltage_ranges[] = { +static const struct regulator_linear_range bd718xx_ldo6_volts[] = { 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[] = { +static const struct regulator_linear_range bd71837_ldo7_volts[] = { REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), }; -static const struct regulator_desc bd71837_regulators[] = { +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, + }, + }, { - .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, + .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, + }, }, { - .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, + .desc = { + .name = "buck3", + .of_match = of_match_ptr("BUCK3"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK3, + .ops = &bd718xx_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_1ST_NODVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_1st_nodvs_buck_volts, + .n_linear_ranges = + ARRAY_SIZE(bd718xx_1st_nodvs_buck_volts), + .vsel_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, + .vsel_mask = BD718XX_1ST_NODVS_BUCK_MASK, + .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, + }, }, { - .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, + .desc = { + .name = "buck4", + .of_match = of_match_ptr("BUCK4"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK4, + .ops = &bd718xx_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD71847_BUCK4_VOLTAGE_NUM, + .linear_ranges = bd71847_buck4_voltage_ranges, + .n_linear_ranges = + ARRAY_SIZE(bd71847_buck4_voltage_ranges), + .enable_reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL, + .vsel_reg = BD718XX_REG_2ND_NODVS_BUCK_VOLT, + .vsel_mask = BD71847_BUCK4_MASK, + .enable_mask = BD718XX_BUCK_EN, + .owner = THIS_MODULE, + }, + .init = { + .reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL, + .mask = BD718XX_BUCK_SEL, + .val = BD718XX_BUCK_SEL, + }, }, { - .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, + .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, + }, }, { - .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, + .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_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, + }, }, { - .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, + .desc = { + .name = "ldo1", + .of_match = of_match_ptr("LDO1"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_LDO1, + .ops = &bd718xx_ldo_regulator_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, + .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, + }, }, { - .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, + .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, + }, }, { - .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, + .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, + }, }, { - .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, + .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, + }, }, { - .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, + .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 = BD718XX_LDO5_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo5_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo5_volts), + .vsel_reg = BD718XX_REG_LDO5_VOLT, + .vsel_mask = BD71847_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, + }, }, { - .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, + .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, + }, }, { - .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, + .desc = { + .name = "buck5", + .of_match = of_match_ptr("BUCK5"), + .regulators_node = of_match_ptr("regulators"), + .id = BD718XX_BUCK5, + .ops = &bd718xx_buck_regulator_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = BD718XX_1ST_NODVS_BUCK_VOLTAGE_NUM, + .linear_ranges = bd718xx_1st_nodvs_buck_volts, + .n_linear_ranges = + ARRAY_SIZE(bd718xx_1st_nodvs_buck_volts), + .vsel_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, + .vsel_mask = BD718XX_1ST_NODVS_BUCK_MASK, + .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, + }, }, { - .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, + .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_voltage_ranges, + .n_linear_ranges = + ARRAY_SIZE(bd71837_buck6_voltage_ranges), + .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, + }, }, { - .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, + .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, + }, }, { - .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, + .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 = BD71837_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_ldo_regulator_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, + .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 = BD718XX_LDO5_VOLTAGE_NUM, + .linear_ranges = bd718xx_ldo5_volts, + .n_linear_ranges = ARRAY_SIZE(bd718xx_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 reg_init { - unsigned int reg; - unsigned int mask; +struct bd718xx_pmic_inits { + const struct bd718xx_regulator_data (*r_datas)[]; + unsigned int r_amount; }; static int bd71837_probe(struct platform_device *pdev) { - struct bd71837_pmic *pmic; + struct bd718xx_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, - } + 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, err; + int i, j, 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); @@ -555,44 +952,34 @@ static int bd71837_probe(struct platform_device *pdev) 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, BD71837_REG_REGLOCK, + 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", - BD71837_REG_REGLOCK); - } - - /* - * 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 - */ - err = regmap_update_bits(pmic->mfd->regmap, BD718XX_REG_MVRFLTMASK2, - BD718XX_LDO5_VRMON80 | BD718XX_LDO6_VRMON80, - BD718XX_LDO5_VRMON80 | BD718XX_LDO6_VRMON80); - if (err) { - dev_err(&pmic->pdev->dev, - "Failed to disable voltage monitoring\n"); - goto err; + BD718XX_REG_REGLOCK); } - for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) { + for (i = 0; i < pmic_regulators[pmic->mfd->chip_type].r_amount; i++) { - struct regulator_desc *desc; + const struct regulator_desc *desc; struct regulator_dev *rdev; + const struct bd718xx_regulator_data *r; - desc = &pmic->descs[i]; + r = &(*pmic_regulators[pmic->mfd->chip_type].r_datas)[i]; + desc = &r->desc; config.dev = pdev->dev.parent; config.driver_data = pmic; @@ -612,16 +999,26 @@ static int bd71837_probe(struct platform_device *pdev) * 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); + 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; } @@ -632,7 +1029,7 @@ err: static struct platform_driver bd71837_regulator = { .driver = { - .name = "bd71837-pmic", + .name = "bd718xx-pmic", }, .probe = bd71837_probe, }; diff --git a/include/linux/mfd/rohm-bd718x7.h b/include/linux/mfd/rohm-bd718x7.h index e8338e5dc10b..625e3607e069 100644 --- a/include/linux/mfd/rohm-bd718x7.h +++ b/include/linux/mfd/rohm-bd718x7.h @@ -7,106 +7,125 @@ #include 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 + * + * Note, we support only one range of voltages for each buck/LDO until we + * get pickable ranges support. (See range selection bits for BUCK5 and + * LDO1. On BD71847 also the second no DVS buck and LDO5) + */ + +#define BD718XX_DVS_BUCK_VOLTAGE_NUM 0x3D +#define BD718XX_1ST_NODVS_BUCK_VOLTAGE_NUM 0x08 +#define BD71837_4TH_NODVS_BUCK_VOLTAGE_NUM 0x3D + +#define BD718XX_LDO1_VOLTAGE_NUM 0x04 +#define BD718XX_LDO2_VOLTAGE_NUM 0x02 +#define BD718XX_LDO3_VOLTAGE_NUM 0x10 +#define BD718XX_LDO4_VOLTAGE_NUM 0x0A +#define BD718XX_LDO5_VOLTAGE_NUM 0x10 +#define BD718XX_LDO6_VOLTAGE_NUM 0x0A -#define BD71837_BUCK5_VOLTAGE_NUM 0x08 +/* BD71837 specific voltage configurations */ #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_BUCK4_VOLTAGE_NUM 0x04 + +/* Registers specific to BD71837 */ 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, - BD718XX_REG_MVRFLTMASK0 = 0x22, - BD718XX_REG_MVRFLTMASK1 = 0x23, - BD718XX_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, + 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 { + 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,49 +134,27 @@ 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 +#define DVS_BUCK_RUN_MASK 0x3F +#define DVS_BUCK_SUSP_MASK 0x3F +#define DVS_BUCK_IDLE_MASK 0x3F -/* BD71837_REG_BUCK1_VOLT_IDLE bits */ -#define BUCK1_IDLE_MASK 0x3F -#define BUCK1_IDLE_DEFAULT 0x14 +#define BD718XX_1ST_NODVS_BUCK_MASK 0x07 +#define BD71847_BUCK4_MASK 0x03 +#define BD71837_BUCK6_MASK 0x03 +#define BD718XX_3RD_NODVS_BUCK_MASK 0x07 +#define BD718XX_4TH_NODVS_BUCK_MASK 0x3F -/* BD71837_REG_BUCK2_VOLT_RUN bits */ -#define BUCK2_RUN_MASK 0x3F -#define BUCK2_RUN_DEFAULT 0x1E +#define BD718XX_LDO1_MASK 0x03 +#define BD718XX_LDO2_MASK 0x20 +#define BD718XX_LDO3_MASK 0x0F +#define BD718XX_LDO4_MASK 0x0F +#define BD718XX_LDO6_MASK 0x0F -/* BD71837_REG_BUCK2_VOLT_IDLE bits */ -#define BUCK2_IDLE_MASK 0x3F -#define BUCK2_IDLE_DEFAULT 0x14 +#define BD71837_LDO5_MASK 0x0F +#define BD71847_LDO5_MASK 0x0F -/* BD71837_REG_BUCK3_VOLT_RUN bits */ -#define BUCK3_RUN_MASK 0x3F -#define BUCK3_RUN_DEFAULT 0x1E +#define BD71837_LDO7_MASK 0x0F -/* 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 /* BD718XX Voltage monitoring masks */ #define BD718XX_BUCK1_VRMON80 0x1 @@ -221,27 +218,6 @@ enum { #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 - /* Register write induced reset settings */ /* @@ -341,10 +317,11 @@ enum { BD718XX_PWRBTN_LONG_PRESS_15S }; -struct bd71837_pmic; -struct bd71837_clk; +struct bd718xx_pmic; +struct bd718xx_clk; struct bd71837 { + unsigned int chip_type; struct device *dev; struct regmap *regmap; unsigned long int id; @@ -352,8 +329,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__ */ -- cgit v1.2.3 From 12fc309a956b82e75db2a19fd36074266bff9413 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 14 Sep 2018 11:30:06 +0300 Subject: regulator: dt bindings: add BD71847 device-tree binding documentation Add ROHM BD71847 Power Management IC regulator binding information to device-tree binding documents. Signed-off-by: Matti Vaittinen Reviewed-by: Rob Herring Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/rohm,bd71837-regulator.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) 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 -- cgit v1.2.3 From 01e17e5d8004f53044c6c9062e04ca118c420512 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 14 Sep 2018 11:30:58 +0300 Subject: mfd: dt bindings: add BD71847 device-tree binding documentation Add ROHM BD71847 Power Management IC MFD binding information to device-tree binding documents. Signed-off-by: Matti Vaittinen Reviewed-by: Rob Herring Acked-by: Lee Jones Signed-off-by: Mark Brown --- .../devicetree/bindings/mfd/rohm,bd71837-pmic.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 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. -- cgit v1.2.3 From 18e4b55fbd2069cee51ef9660b35c65ec13bee6d Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 14 Sep 2018 11:31:36 +0300 Subject: regulator: Support regulators where voltage ranges are selectable For example ROHM BD71837 and ROHM BD71847 Power management ICs have regulators which provide multiple linear ranges. Ranges can be selected by individual non contagious bit in vsel register. Add regmap helper functions for selecting ranges. Signed-off-by: Matti Vaittinen Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 + drivers/regulator/helpers.c | 232 +++++++++++++++++++++++++++++++++++++++ include/linux/regulator/driver.h | 20 +++- 3 files changed, 256 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 9577d8941846..4b1755a8ef00 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2783,6 +2783,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); } diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index 2ae7c3ac5940..d2b9fc359318 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 * @@ -336,6 +458,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 * @@ -360,6 +552,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 * 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); -- cgit v1.2.3 From dd2be639f4a918b335818bf22a937956e552b957 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 14 Sep 2018 11:32:26 +0300 Subject: regulator/mfd: bd718xx: rename bd71837/bd71847 common instances Rename parts of code that support both BD71837 and BD71847 to BD718XX. Signed-off-by: Matti Vaittinen Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/mfd/rohm-bd718x7.c | 98 +++++++++++++++++------------------ drivers/regulator/bd71837-regulator.c | 26 +++++----- include/linux/mfd/rohm-bd718x7.h | 64 +++++++++++------------ 3 files changed, 94 insertions(+), 94 deletions(-) diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c index ce5aa5cd3545..161c8aac6d86 100644 --- a/drivers/mfd/rohm-bd718x7.c +++ b/drivers/mfd/rohm-bd718x7.c @@ -2,9 +2,9 @@ // // 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 @@ -30,7 +30,7 @@ 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, @@ -40,20 +40,20 @@ static struct mfd_cell bd71837_mfd_cells[] = { { .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 = BD718XX_REG_IRQ, @@ -73,7 +73,7 @@ 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, @@ -81,10 +81,10 @@ static const struct regmap_config bd71837_regmap_config = { .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; + struct bd718xx *bd718xx; int ret; if (!i2c->irq) { @@ -92,33 +92,33 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, return -EINVAL; } - bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL); + bd718xx = devm_kzalloc(&i2c->dev, sizeof(struct bd718xx), GFP_KERNEL); - if (!bd71837) + if (!bd718xx) return -ENOMEM; - bd71837->chip_irq = i2c->irq; - bd71837->chip_type = (unsigned int)(uintptr_t) + bd718xx->chip_irq = i2c->irq; + bd718xx->chip_type = (unsigned int) of_device_get_match_data(&i2c->dev); - bd71837->dev = &i2c->dev; - dev_set_drvdata(&i2c->dev, bd71837); + bd718xx->dev = &i2c->dev; + dev_set_drvdata(&i2c->dev, bd718xx); - bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config); - if (IS_ERR(bd71837->regmap)) { + 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(bd71837->regmap); + 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, + ret = regmap_update_bits(bd718xx->regmap, BD718XX_REG_PWRONCONFIG0, BD718XX_PWRBTN_PRESS_DURATION_MASK, BD718XX_PWRBTN_SHORT_PRESS_10MS); @@ -129,7 +129,7 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, } /* Configure long press to 10 seconds */ - ret = regmap_update_bits(bd71837->regmap, + ret = regmap_update_bits(bd718xx->regmap, BD718XX_REG_PWRONCONFIG1, BD718XX_PWRBTN_PRESS_DURATION_MASK, BD718XX_PWRBTN_LONG_PRESS_10S); @@ -140,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"); @@ -149,17 +149,17 @@ 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[] = { +static const struct of_device_id bd718xx_of_match[] = { { .compatible = "rohm,bd71837", .data = (void *)BD718XX_TYPE_BD71837, @@ -170,30 +170,30 @@ static const struct of_device_id bd71837_of_match[] = { }, { } }; -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 "); -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/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c index 1dbba20ede3e..8e89334f94d1 100644 --- a/drivers/regulator/bd71837-regulator.c +++ b/drivers/regulator/bd71837-regulator.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (C) 2018 ROHM Semiconductors -// bd71837-regulator.c ROHM BD71837MWV regulator driver +// bd71837-regulator.c ROHM BD71837MWV/BD71847MWV regulator driver #include #include @@ -17,7 +17,7 @@ struct bd718xx_pmic { struct bd718xx_regulator_data *rdata; - struct bd71837 *mfd; + struct bd718xx *mfd; struct platform_device *pdev; struct regulator_dev *rdev[BD718XX_REGULATOR_AMOUNT]; }; @@ -30,11 +30,11 @@ struct bd718xx_pmic { * 10: 2.50mV/usec 10mV 4uS * 11: 1.25mV/usec 10mV 8uS */ -static int bd71837_buck1234_set_ramp_delay(struct regulator_dev *rdev, +static int bd718xx_buck1234_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { struct bd718xx_pmic *pmic = rdev_get_drvdata(rdev); - struct bd71837 *mfd = pmic->mfd; + struct bd718xx *mfd = pmic->mfd; int id = rdev->desc->id; unsigned int ramp_value = BUCK_RAMPRATE_10P00MV; @@ -124,7 +124,7 @@ static struct regulator_ops bd718xx_dvs_buck_regulator_ops = { .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, + .set_ramp_delay = bd718xx_buck1234_set_ramp_delay, }; /* @@ -378,7 +378,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .desc = { .name = "buck5", .of_match = of_match_ptr("BUCK5"), - .regulators_node = of_match_ptr("regulators"), + .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK5, .ops = &bd718xx_buck_regulator_nolinear_ops, .type = REGULATOR_VOLTAGE, @@ -404,7 +404,7 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .id = BD718XX_BUCK6, .ops = &bd718xx_buck_regulator_ops, .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_4TH_NODVS_BUCK_VOLTAGE_NUM, + .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), @@ -732,7 +732,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .id = BD718XX_BUCK8, .ops = &bd718xx_buck_regulator_ops, .type = REGULATOR_VOLTAGE, - .n_voltages = BD71837_4TH_NODVS_BUCK_VOLTAGE_NUM, + .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), @@ -923,7 +923,7 @@ struct bd718xx_pmic_inits { unsigned int r_amount; }; -static int bd71837_probe(struct platform_device *pdev) +static int bd718xx_probe(struct platform_device *pdev) { struct bd718xx_pmic *pmic; struct regulator_config config = { 0 }; @@ -1027,15 +1027,15 @@ err: return err; } -static struct platform_driver bd71837_regulator = { +static struct platform_driver bd718xx_regulator = { .driver = { .name = "bd718xx-pmic", }, - .probe = bd71837_probe, + .probe = bd718xx_probe, }; -module_platform_driver(bd71837_regulator); +module_platform_driver(bd718xx_regulator); MODULE_AUTHOR("Matti Vaittinen "); -MODULE_DESCRIPTION("BD71837 voltage regulator driver"); +MODULE_DESCRIPTION("BD71837/BD71847 voltage regulator driver"); MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/rohm-bd718x7.h b/include/linux/mfd/rohm-bd718x7.h index 625e3607e069..fed5fed75732 100644 --- a/include/linux/mfd/rohm-bd718x7.h +++ b/include/linux/mfd/rohm-bd718x7.h @@ -1,8 +1,8 @@ /* 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 @@ -40,7 +40,7 @@ enum { #define BD718XX_DVS_BUCK_VOLTAGE_NUM 0x3D #define BD718XX_1ST_NODVS_BUCK_VOLTAGE_NUM 0x08 -#define BD71837_4TH_NODVS_BUCK_VOLTAGE_NUM 0x3D +#define BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM 0x3D #define BD718XX_LDO1_VOLTAGE_NUM 0x04 #define BD718XX_LDO2_VOLTAGE_NUM 0x02 @@ -183,7 +183,7 @@ enum { #define BD71837_BUCK4_VRMON130 0x80 #define BD71837_LDO7_VRMON80 0x40 -/* BD71837_REG_IRQ bits */ +/* BD718XX_REG_IRQ bits */ #define IRQ_SWRST 0x40 #define IRQ_PWRON_S 0x20 #define IRQ_PWRON_L 0x10 @@ -192,31 +192,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 +/* 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 */ @@ -226,13 +226,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 */ @@ -320,7 +320,7 @@ enum { struct bd718xx_pmic; struct bd718xx_clk; -struct bd71837 { +struct bd718xx { unsigned int chip_type; struct device *dev; struct regmap *regmap; @@ -333,4 +333,4 @@ struct bd71837 { struct bd718xx_clk *clk; }; -#endif /* __LINUX_MFD_BD71837_H__ */ +#endif /* __LINUX_MFD_BD718XX_H__ */ -- cgit v1.2.3 From a4bfc2c28a21f4d5274d813b20fd015a9dc9bcfa Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 14 Sep 2018 11:33:11 +0300 Subject: regulator: bd718XX use pickable ranges Few regulators in BD71837 and BD71847 can output voltages from different voltage ranges. Register interface is arranged so that used range is selected by toggling bits which are not next to actual voltage selection bits. Then the voltage inside selected range is determined by voltage selection bits (as usual). Support BD71837 and BD71847 selectible range voltages using new pickable ranges helpers. Signed-off-by: Matti Vaittinen Signed-off-by: Mark Brown --- drivers/regulator/bd71837-regulator.c | 153 +++++++++++++++++++++++++++------- include/linux/mfd/rohm-bd718x7.h | 32 +++---- 2 files changed, 143 insertions(+), 42 deletions(-) diff --git a/drivers/regulator/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c index 8e89334f94d1..d2522d4e1505 100644 --- a/drivers/regulator/bd71837-regulator.c +++ b/drivers/regulator/bd71837-regulator.c @@ -78,6 +78,34 @@ static int bd718xx_set_voltage_sel_restricted(struct regulator_dev *rdev, 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, @@ -139,24 +167,61 @@ static const struct regulator_linear_range bd718xx_dvs_buck_volts[] = { /* * 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 - * 0.7V to 1.35V () */ -static const struct regulator_linear_range bd718xx_1st_nodvs_buck_volts[] = { +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_voltage_ranges[] = { +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_voltage_ranges[] = { +static const struct regulator_linear_range bd71837_buck6_volts[] = { REGULATOR_LINEAR_RANGE(3000000, 0x00, 0x03, 100000), }; @@ -190,8 +255,11 @@ static const struct regulator_linear_range bd718xx_4th_nodvs_buck_volts[] = { */ 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 @@ -220,10 +288,21 @@ static const struct regulator_linear_range bd718xx_ldo4_volts[] = { * LDO5 for BD71837 * 1.8 to 3.3V (100mV step) */ -static const struct regulator_linear_range bd718xx_ldo5_volts[] = { +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) @@ -332,14 +411,17 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("BUCK3"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK3, - .ops = &bd718xx_buck_regulator_ops, + .ops = &bd718xx_pickable_range_buck_ops, .type = REGULATOR_VOLTAGE, - .n_voltages = BD718XX_1ST_NODVS_BUCK_VOLTAGE_NUM, - .linear_ranges = bd718xx_1st_nodvs_buck_volts, + .n_voltages = BD71847_BUCK3_VOLTAGE_NUM, + .linear_ranges = bd71847_buck3_volts, .n_linear_ranges = - ARRAY_SIZE(bd718xx_1st_nodvs_buck_volts), + 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, @@ -356,15 +438,18 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("BUCK4"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK4, - .ops = &bd718xx_buck_regulator_ops, + .ops = &bd718xx_pickable_range_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71847_BUCK4_VOLTAGE_NUM, - .linear_ranges = bd71847_buck4_voltage_ranges, + .linear_ranges = bd71847_buck4_volts, .n_linear_ranges = - ARRAY_SIZE(bd71847_buck4_voltage_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, }, @@ -426,13 +511,16 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("LDO1"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO1, - .ops = &bd718xx_ldo_regulator_ops, + .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, @@ -517,13 +605,16 @@ static const struct bd718xx_regulator_data bd71847_regulators[] = { .of_match = of_match_ptr("LDO5"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO5, - .ops = &bd718xx_ldo_regulator_ops, + .ops = &bd718xx_pickable_range_ldo_ops, .type = REGULATOR_VOLTAGE, - .n_voltages = BD718XX_LDO5_VOLTAGE_NUM, - .linear_ranges = bd718xx_ldo5_volts, - .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo5_volts), + .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, @@ -660,14 +751,17 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("BUCK5"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_BUCK5, - .ops = &bd718xx_buck_regulator_ops, + .ops = &bd718xx_pickable_range_buck_ops, .type = REGULATOR_VOLTAGE, - .n_voltages = BD718XX_1ST_NODVS_BUCK_VOLTAGE_NUM, - .linear_ranges = bd718xx_1st_nodvs_buck_volts, + .n_voltages = BD71837_BUCK5_VOLTAGE_NUM, + .linear_ranges = bd71837_buck5_volts, .n_linear_ranges = - ARRAY_SIZE(bd718xx_1st_nodvs_buck_volts), + ARRAY_SIZE(bd71837_buck5_volts), .vsel_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, - .vsel_mask = BD718XX_1ST_NODVS_BUCK_MASK, + .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, @@ -687,9 +781,9 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .ops = &bd718xx_buck_regulator_ops, .type = REGULATOR_VOLTAGE, .n_voltages = BD71837_BUCK6_VOLTAGE_NUM, - .linear_ranges = bd71837_buck6_voltage_ranges, + .linear_ranges = bd71837_buck6_volts, .n_linear_ranges = - ARRAY_SIZE(bd71837_buck6_voltage_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, @@ -754,13 +848,16 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .of_match = of_match_ptr("LDO1"), .regulators_node = of_match_ptr("regulators"), .id = BD718XX_LDO1, - .ops = &bd718xx_ldo_regulator_ops, + .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, @@ -847,9 +944,9 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = { .id = BD718XX_LDO5, .ops = &bd718xx_ldo_regulator_ops, .type = REGULATOR_VOLTAGE, - .n_voltages = BD718XX_LDO5_VOLTAGE_NUM, - .linear_ranges = bd718xx_ldo5_volts, - .n_linear_ranges = ARRAY_SIZE(bd718xx_ldo5_volts), + .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, diff --git a/include/linux/mfd/rohm-bd718x7.h b/include/linux/mfd/rohm-bd718x7.h index fed5fed75732..26acf9a92498 100644 --- a/include/linux/mfd/rohm-bd718x7.h +++ b/include/linux/mfd/rohm-bd718x7.h @@ -31,31 +31,27 @@ enum { BD718XX_REGULATOR_AMOUNT, }; -/* Common voltage configurations - * - * Note, we support only one range of voltages for each buck/LDO until we - * get pickable ranges support. (See range selection bits for BUCK5 and - * LDO1. On BD71847 also the second no DVS buck and LDO5) - */ - +/* Common voltage configurations */ #define BD718XX_DVS_BUCK_VOLTAGE_NUM 0x3D -#define BD718XX_1ST_NODVS_BUCK_VOLTAGE_NUM 0x08 #define BD718XX_4TH_NODVS_BUCK_VOLTAGE_NUM 0x3D -#define BD718XX_LDO1_VOLTAGE_NUM 0x04 +#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_LDO5_VOLTAGE_NUM 0x10 #define BD718XX_LDO6_VOLTAGE_NUM 0x0A /* BD71837 specific voltage configurations */ +#define BD71837_BUCK5_VOLTAGE_NUM 0x10 #define BD71837_BUCK6_VOLTAGE_NUM 0x04 #define BD71837_BUCK7_VOLTAGE_NUM 0x08 +#define BD71837_LDO5_VOLTAGE_NUM 0x10 #define BD71837_LDO7_VOLTAGE_NUM 0x10 /* BD71847 specific voltage configurations */ -#define BD71847_BUCK4_VOLTAGE_NUM 0x04 +#define BD71847_BUCK3_VOLTAGE_NUM 0x18 +#define BD71847_BUCK4_VOLTAGE_NUM 0x08 +#define BD71847_LDO5_VOLTAGE_NUM 0x20 /* Registers specific to BD71837 */ enum { @@ -139,12 +135,20 @@ enum { #define DVS_BUCK_IDLE_MASK 0x3F #define BD718XX_1ST_NODVS_BUCK_MASK 0x07 -#define BD71847_BUCK4_MASK 0x03 -#define BD71837_BUCK6_MASK 0x03 #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 @@ -152,10 +156,10 @@ enum { #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 -- cgit v1.2.3 From 2ece646c90c5b45dd76c76ea207a3f3459f2c472 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Fri, 14 Sep 2018 11:34:02 +0300 Subject: regulator: bd718xx: rename bd71837 to 718xx rename bd71837-regulator.c to bd718x7-regulator.c to reflect the fact that also BD71847 is now supported by the driver. Signed-off-by: Matti Vaittinen Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 2 +- drivers/regulator/Makefile | 2 +- drivers/regulator/bd71837-regulator.c | 1138 --------------------------------- drivers/regulator/bd718x7-regulator.c | 1138 +++++++++++++++++++++++++++++++++ 4 files changed, 1140 insertions(+), 1140 deletions(-) delete mode 100644 drivers/regulator/bd71837-regulator.c create mode 100644 drivers/regulator/bd718x7-regulator.c 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 d2522d4e1505..000000000000 --- a/drivers/regulator/bd71837-regulator.c +++ /dev/null @@ -1,1138 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (C) 2018 ROHM Semiconductors -// bd71837-regulator.c ROHM BD71837MWV/BD71847MWV regulator driver - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 "); -MODULE_DESCRIPTION("BD71837/BD71847 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 "); +MODULE_DESCRIPTION("BD71837/BD71847 voltage regulator driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3