From 3b6e7088afc919f5b52e4d2de8501ad34d35b09b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 12 Mar 2021 14:02:40 +0100 Subject: [PATCH 1/5] regulator: bd9571mwv: Fix AVS and DVFS voltage range According to Table 30 ("DVFS_MoniVDAC [6:0] Setting Table") in the BD9571MWV-M Datasheet Rev. 002, the valid voltage range is 600..1100 mV (settings 0x3c..0x6e). While the lower limit is taken into account (by setting regulator_desc.linear_min_sel to 0x3c), the upper limit is not. Fix this by reducing regulator_desc.n_voltages from 0x80 to 0x6f. Fixes: e85c5a153fe237f2 ("regulator: Add ROHM BD9571MWV-M PMIC regulator driver") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210312130242.3390038-2-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/regulator/bd9571mwv-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index 7b0cd08db4462..13393cdc6be14 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -125,7 +125,7 @@ static const struct regulator_ops vid_ops = { static const struct regulator_desc regulators[] = { BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f, - 0x80, 600000, 10000, 0x3c), + 0x6f, 600000, 10000, 0x3c), BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf, 16, 1625000, 25000, 0), BD9571MWV_REG("VD25", "vd25", VD25, vid_ops, BD9571MWV_VD25_VID, 0xf, @@ -134,7 +134,7 @@ static const struct regulator_desc regulators[] = { 11, 2800000, 100000, 0), BD9571MWV_REG("DVFS", "dvfs", DVFS, reg_ops, BD9571MWV_DVFS_MONIVDAC, 0x7f, - 0x80, 600000, 10000, 0x3c), + 0x6f, 600000, 10000, 0x3c), }; #ifdef CONFIG_PM_SLEEP From 9cbc23f7d51fb0b1363bdfdd0b770aa7b5982f2f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 12 Mar 2021 14:02:41 +0100 Subject: [PATCH 2/5] regulator: bd9571mwv: Fix regulator name printed on registration failure If a regulator fails to register, the driver prints an error message like: bd9571mwv-regulator bd9571mwv-regulator.6.auto: failed to register bd9571mwv-regulator regulator However, the platform device's name is already printed as part of dev_err(), and does not allow the user to distinguish among the various regulators that are part of the PMIC. Fix this by printing regulator_desc.name instead, to change the message like: bd9571mwv-regulator bd9571mwv-regulator.6.auto: failed to register DVFS regulator Signed-off-by: Geert Uytterhoeven Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20210312130242.3390038-3-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/regulator/bd9571mwv-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index 13393cdc6be14..a4d406022587d 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -301,7 +301,7 @@ static int bd9571mwv_regulator_probe(struct platform_device *pdev) &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s regulator\n", - pdev->name); + regulators[i].name); return PTR_ERR(rdev); } } From 1deceabbdc0dd3162def1e26acb2e57a93275909 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 12 Mar 2021 14:02:42 +0100 Subject: [PATCH 3/5] regulator: bd9571mwv: Convert device attribute to sysfs_emit() Convert the "backup_mode" device attribute from sprintf() to sysfs_emit(), as the latter is aware of the PAGE_SIZE buffer. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210312130242.3390038-4-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/regulator/bd9571mwv-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index a4d406022587d..ba020a45f238e 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -174,7 +174,7 @@ static ssize_t backup_mode_show(struct device *dev, { struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", bdreg->bkup_mode_enabled ? "on" : "off"); + return sysfs_emit(buf, "%s\n", bdreg->bkup_mode_enabled ? "on" : "off"); } static ssize_t backup_mode_store(struct device *dev, From 013592be146a10d3567c0062cd1416faab060704 Mon Sep 17 00:00:00 2001 From: Adam Ward Date: Wed, 21 Apr 2021 12:03:06 +0000 Subject: [PATCH 4/5] regulator: da9121: automotive variants identity fix This patch fixes identification of DA913x parts by the DA9121 driver, where a lack of clarity lead to implementation on the basis that variant IDs were to be identical to the equivalent rated non-automotive parts. There is a new emphasis on the DT identity to cope with overlap in these ID's - this is not considered to be problematic, because projects would be exclusively using automotive or consumer grade parts. Signed-off-by: Adam Ward Link: https://lore.kernel.org/r/20210421120306.DB5B880007F@slsrvapps-01.diasemi.com Signed-off-by: Mark Brown --- drivers/regulator/da9121-regulator.c | 80 ++++++++++++++++++---------- drivers/regulator/da9121-regulator.h | 13 +++++ 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index a2ede7d7897eb..08cbf688e14d3 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -40,6 +40,7 @@ struct da9121 { unsigned int passive_delay; int chip_irq; int variant_id; + int subvariant_id; }; /* Define ranges for different variants, enabling translation to/from @@ -812,7 +813,6 @@ static struct regmap_config da9121_2ch_regmap_config = { static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip) { u32 device_id; - u8 chip_id = chip->variant_id; u32 variant_id; u8 variant_mrc, variant_vrc; char *type; @@ -839,22 +839,34 @@ static int da9121_check_device_type(struct i2c_client *i2c, struct da9121 *chip) variant_vrc = variant_id & DA9121_MASK_OTP_VARIANT_ID_VRC; - switch (variant_vrc) { - case DA9121_VARIANT_VRC: - type = "DA9121/DA9130"; - config_match = (chip_id == DA9121_TYPE_DA9121_DA9130); + switch (chip->subvariant_id) { + case DA9121_SUBTYPE_DA9121: + type = "DA9121"; + config_match = (variant_vrc == DA9121_VARIANT_VRC); break; - case DA9220_VARIANT_VRC: - type = "DA9220/DA9132"; - config_match = (chip_id == DA9121_TYPE_DA9220_DA9132); + case DA9121_SUBTYPE_DA9130: + type = "DA9130"; + config_match = (variant_vrc == DA9130_VARIANT_VRC); break; - case DA9122_VARIANT_VRC: - type = "DA9122/DA9131"; - config_match = (chip_id == DA9121_TYPE_DA9122_DA9131); + case DA9121_SUBTYPE_DA9220: + type = "DA9220"; + config_match = (variant_vrc == DA9220_VARIANT_VRC); break; - case DA9217_VARIANT_VRC: + case DA9121_SUBTYPE_DA9132: + type = "DA9132"; + config_match = (variant_vrc == DA9132_VARIANT_VRC); + break; + case DA9121_SUBTYPE_DA9122: + type = "DA9122"; + config_match = (variant_vrc == DA9122_VARIANT_VRC); + break; + case DA9121_SUBTYPE_DA9131: + type = "DA9131"; + config_match = (variant_vrc == DA9131_VARIANT_VRC); + break; + case DA9121_SUBTYPE_DA9217: type = "DA9217"; - config_match = (chip_id == DA9121_TYPE_DA9217); + config_match = (variant_vrc == DA9217_VARIANT_VRC); break; default: type = "Unknown"; @@ -892,15 +904,27 @@ static int da9121_assign_chip_model(struct i2c_client *i2c, chip->dev = &i2c->dev; - switch (chip->variant_id) { - case DA9121_TYPE_DA9121_DA9130: - fallthrough; - case DA9121_TYPE_DA9217: + /* Use configured subtype to select the regulator descriptor index and + * register map, common to both consumer and automotive grade variants + */ + switch (chip->subvariant_id) { + case DA9121_SUBTYPE_DA9121: + case DA9121_SUBTYPE_DA9130: + chip->variant_id = DA9121_TYPE_DA9121_DA9130; regmap = &da9121_1ch_regmap_config; break; - case DA9121_TYPE_DA9122_DA9131: - fallthrough; - case DA9121_TYPE_DA9220_DA9132: + case DA9121_SUBTYPE_DA9217: + chip->variant_id = DA9121_TYPE_DA9217; + regmap = &da9121_1ch_regmap_config; + break; + case DA9121_SUBTYPE_DA9122: + case DA9121_SUBTYPE_DA9131: + chip->variant_id = DA9121_TYPE_DA9122_DA9131; + regmap = &da9121_2ch_regmap_config; + break; + case DA9121_SUBTYPE_DA9220: + case DA9121_SUBTYPE_DA9132: + chip->variant_id = DA9121_TYPE_DA9220_DA9132; regmap = &da9121_2ch_regmap_config; break; } @@ -975,13 +999,13 @@ static int da9121_config_irq(struct i2c_client *i2c, } static const struct of_device_id da9121_dt_ids[] = { - { .compatible = "dlg,da9121", .data = (void *) DA9121_TYPE_DA9121_DA9130 }, - { .compatible = "dlg,da9130", .data = (void *) DA9121_TYPE_DA9121_DA9130 }, - { .compatible = "dlg,da9217", .data = (void *) DA9121_TYPE_DA9217 }, - { .compatible = "dlg,da9122", .data = (void *) DA9121_TYPE_DA9122_DA9131 }, - { .compatible = "dlg,da9131", .data = (void *) DA9121_TYPE_DA9122_DA9131 }, - { .compatible = "dlg,da9220", .data = (void *) DA9121_TYPE_DA9220_DA9132 }, - { .compatible = "dlg,da9132", .data = (void *) DA9121_TYPE_DA9220_DA9132 }, + { .compatible = "dlg,da9121", .data = (void *) DA9121_SUBTYPE_DA9121 }, + { .compatible = "dlg,da9130", .data = (void *) DA9121_SUBTYPE_DA9130 }, + { .compatible = "dlg,da9217", .data = (void *) DA9121_SUBTYPE_DA9217 }, + { .compatible = "dlg,da9122", .data = (void *) DA9121_SUBTYPE_DA9122 }, + { .compatible = "dlg,da9131", .data = (void *) DA9121_SUBTYPE_DA9131 }, + { .compatible = "dlg,da9220", .data = (void *) DA9121_SUBTYPE_DA9220 }, + { .compatible = "dlg,da9132", .data = (void *) DA9121_SUBTYPE_DA9132 }, { } }; MODULE_DEVICE_TABLE(of, da9121_dt_ids); @@ -1011,7 +1035,7 @@ static int da9121_i2c_probe(struct i2c_client *i2c, } chip->pdata = i2c->dev.platform_data; - chip->variant_id = da9121_of_get_id(&i2c->dev); + chip->subvariant_id = da9121_of_get_id(&i2c->dev); ret = da9121_assign_chip_model(i2c, chip); if (ret < 0) diff --git a/drivers/regulator/da9121-regulator.h b/drivers/regulator/da9121-regulator.h index 3c34cb889ca87..357f416e17c1d 100644 --- a/drivers/regulator/da9121-regulator.h +++ b/drivers/regulator/da9121-regulator.h @@ -29,6 +29,16 @@ enum da9121_variant { DA9121_TYPE_DA9217 }; +enum da9121_subvariant { + DA9121_SUBTYPE_DA9121, + DA9121_SUBTYPE_DA9130, + DA9121_SUBTYPE_DA9220, + DA9121_SUBTYPE_DA9132, + DA9121_SUBTYPE_DA9122, + DA9121_SUBTYPE_DA9131, + DA9121_SUBTYPE_DA9217 +}; + /* Minimum, maximum and default polling millisecond periods are provided * here as an example. It is expected that any final implementation will * include a modification of these settings to match the required @@ -279,6 +289,9 @@ enum da9121_variant { #define DA9220_VARIANT_VRC 0x0 #define DA9122_VARIANT_VRC 0x2 #define DA9217_VARIANT_VRC 0x7 +#define DA9130_VARIANT_VRC 0x0 +#define DA9131_VARIANT_VRC 0x1 +#define DA9132_VARIANT_VRC 0x2 /* DA9121_REG_OTP_CUSTOMER_ID */ From a5ccccb3ec0b052804d03df90c0d08689be54170 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Thu, 22 Apr 2021 10:30:44 +0200 Subject: [PATCH 5/5] regulator: core: Respect off_on_delay at startup We currently do not respect off_on_delay the first time we turn on a regulator. This is problematic since the regulator could have been turned off by the bootloader, or it could it have been turned off during the probe of the regulator driver (such as when regulator-fixed requests the enable GPIO), either of which could potentially have happened less than off_on_delay microseconds ago before the first time a client requests for the regulator to be turned on. We can't know exactly when the regulator was turned off, but initialise off_on_delay to the current time when registering the regulator, so that we guarantee that we respect the off_on_delay in all cases. Signed-off-by: Vincent Whitchurch Link: https://lore.kernel.org/r/20210422083044.11479-1-vincent.whitchurch@axis.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 16114aea099a2..d6219cb8bd29f 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1439,6 +1439,8 @@ static int set_machine_constraints(struct regulator_dev *rdev) if (rdev->constraints->always_on) rdev->use_count++; + } else if (rdev->desc->off_on_delay) { + rdev->last_off_jiffy = jiffies; } print_constraints(rdev);