[PATCH v2 07/10] regulator: bd71828: Support ROHM BD73800
Matti Vaittinen <[email protected]> Tue, 4 Aug 2026 13:22:39 +0300
| Newsgroups | org.kernel.vger.linux-clk,dev.linux.lists.mfd,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-gpio,org.kernel.vger.linux-kernel,org.kernel.vger.linux-rtc |
|---|---|
| Message-ID | <f81e7214f9c02fb1a92d12944bc6b8790d5ea6a8.1785838585.git.mazziesaccount@gmail.com> |
--y8VN4YtQIluSFgZs Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable =46rom: Matti Vaittinen <[email protected]> The ROHM BD73800 is a power management IC which integrates 8 BUCKs and 4 LDOs. The PMIC has internal state-machine and it can support transitions to RUN, SUSPEND and IDLE states. The LDOs 1 and 3 have two different voltage range configurations that can be set at the manufacturing phase by OTP. By default driver assumes low voltage ranges to be used because the data-sheet indicates the higher voltage ranges to be an 'OTP option'. The high voltage range can be indicated via device-tree property. Signed-off-by: Matti Vaittinen <[email protected]> --- Revision history: v1 =3D> v2: - Simplified DT parsing as was suggested by Mark - Fix buck5 vsel_mask --- drivers/regulator/Kconfig | 4 +- drivers/regulator/bd71828-regulator.c | 558 +++++++++++++++++++++++++- 2 files changed, 559 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 89789ac7a786..13928af8cad4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -241,12 +241,12 @@ config REGULATOR_BD71815 will be called bd71815-regulator. =20 config REGULATOR_BD71828 - tristate "ROHM BD71828, BD72720 and BD73900 Power Regulators" + tristate "ROHM BD71828, BD72720 and BD73[8/9]00 Power Regulators" depends on MFD_ROHM_BD71828 select REGULATOR_ROHM help This driver supports voltage regulators on ROHM BD71828, - BD71879, BD72720 and BD73900 PMICs. This will enable + BD71879, BD72720 and BD73[8/9]00 PMICs. This will enable support for the software controllable buck and LDO regulators. =20 This driver can also be built as a module. If so, the module diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71= 828-regulator.c index 2ced81df0c02..dea551cf658a 100644 --- a/drivers/regulator/bd71828-regulator.c +++ b/drivers/regulator/bd71828-regulator.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright (C) 2019 ROHM Semiconductors // bd71828-regulator.c ROHM BD71828GW-DS1 regulator driver -// =20 #include <linux/cleanup.h> #include <linux/delay.h> @@ -10,6 +9,7 @@ #include <linux/kernel.h> #include <linux/mfd/rohm-bd71828.h> #include <linux/mfd/rohm-bd72720.h> +#include <linux/mfd/rohm-bd73800.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> @@ -31,6 +31,13 @@ struct bd71828_regulator_data { int reg_init_amnt; }; =20 +/* + * LDO1 and LDO3 node names are used also in the driver to find OTP settin= g for + * the used voltage range. + */ +#define LDO1_NODE_NAME "ldo1" +#define LDO3_NODE_NAME "ldo3" + static const struct reg_init bd71828_buck1_inits[] =3D { /* * DVS Buck voltages can be changed by register values or via GPIO. @@ -172,6 +179,55 @@ static const struct linear_range bd72720_ldo6_volts[] = =3D { REGULATOR_LINEAR_RANGE(1800000, 0x79, 0x7f, 0), }; =20 +static const struct linear_range bd73800_buck12348_volts[] =3D { + REGULATOR_LINEAR_RANGE(500000, 0x00, 0x50, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0x51, 0xff, 0), +}; + +static const unsigned int bd73800_buck5_volt_range_sel[] =3D { + 0x0, 0x0, 0x1, 0x1, +}; + +static const struct linear_range bd73800_buck5_volts[] =3D { + /* range selector 0 */ + REGULATOR_LINEAR_RANGE(500000, 0x00, 0x50, 10000), + REGULATOR_LINEAR_RANGE(1300000, 0x51, 0x7f, 0), + /* range selector 1 */ + REGULATOR_LINEAR_RANGE(300000, 0x00, 0x46, 10000), + REGULATOR_LINEAR_RANGE(1000000, 0x47, 0x7f, 0), +}; + +/* + * BUCK5 has two different pickable ranges, each having voltages matching + * selectors 0x0 to 0x7f. This gives 0x7f + 1 different voltages for each = of + * the ranges. + */ +#define BD73800_NUM_BUCK5_VOLTS ((0x7f + 1) * 2) + +static const struct linear_range bd73800_buck67_volts[] =3D { + REGULATOR_LINEAR_RANGE(1500000, 0x00, 0xc8, 10000), + REGULATOR_LINEAR_RANGE(3500000, 0xc9, 0xff, 0), +}; + +/* + * On the BD73800 the LDO1 and LDO3 support two different voltage areas. + * Whether to use 'high' or 'low' ranges is configured by OTP. There seems + * to be no register to read the configured area so it must be given via + * device-tree properties. + */ +static const struct linear_range bd73800_ldo13_low_volts[] =3D { + REGULATOR_LINEAR_RANGE(600000, 0x00, 0x78, 10000), + REGULATOR_LINEAR_RANGE(1800000, 0x79, 0xff, 0), +}; + +static const struct linear_range bd73800_ldo13_high_volts[] =3D { + REGULATOR_LINEAR_RANGE(750000, 0x00, 0xff, 10000), +}; + +static const struct linear_range bd73800_ldo24_volts[] =3D { + REGULATOR_LINEAR_RANGE(750000, 0x00, 0xff, 10000), +}; + static const unsigned int bd71828_ramp_delay[] =3D { 2500, 5000, 10000, 20= 000 }; =20 /* @@ -225,6 +281,36 @@ static int bd71828_ldo6_parse_dt(struct device_node *n= p, return 0; } =20 +/* Operations for all other BUCKs but BUCK 5 */ +static const struct regulator_ops bd73800_buck_ops =3D { + .enable =3D regulator_enable_regmap, + .disable =3D regulator_disable_regmap, + .is_enabled =3D regulator_is_enabled_regmap, + .list_voltage =3D regulator_list_voltage_linear_range, + .set_voltage_sel =3D regulator_set_voltage_sel_regmap, + .get_voltage_sel =3D regulator_get_voltage_sel_regmap, + .set_ramp_delay =3D regulator_set_ramp_delay_regmap, +}; + +static const struct regulator_ops bd73800_buck5_ops =3D { + .enable =3D regulator_enable_regmap, + .disable =3D regulator_disable_regmap, + .is_enabled =3D regulator_is_enabled_regmap, + .list_voltage =3D regulator_list_voltage_pickable_linear_range, + .set_voltage_sel =3D regulator_set_voltage_sel_pickable_regmap, + .get_voltage_sel =3D regulator_get_voltage_sel_pickable_regmap, + .set_ramp_delay =3D regulator_set_ramp_delay_regmap, +}; + +static const struct regulator_ops bd73800_ldo_ops =3D { + .enable =3D regulator_enable_regmap, + .disable =3D regulator_disable_regmap, + .is_enabled =3D regulator_is_enabled_regmap, + .list_voltage =3D regulator_list_voltage_linear_range, + .set_voltage_sel =3D regulator_set_voltage_sel_regmap, + .get_voltage_sel =3D regulator_get_voltage_sel_regmap, +}; + static const struct regulator_ops bd71828_buck_ops =3D { .enable =3D regulator_enable_regmap, .disable =3D regulator_disable_regmap, @@ -1565,6 +1651,412 @@ static const struct bd71828_regulator_data bd72720_= rdata[] =3D { }, }; =20 +static const struct bd71828_regulator_data bd73800_rdata[] =3D { + { + .desc =3D { + .name =3D "buck1", + .of_match =3D of_match_ptr("buck1"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_BUCK1, + .ops =3D &bd73800_buck_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_buck12348_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_buck12348_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_BUCK1_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_BUCK1_VOLT_RUN, + .vsel_mask =3D BD73800_MASK_VOLT, + .ramp_delay_table =3D bd71828_ramp_delay, + .n_ramp_values =3D ARRAY_SIZE(bd71828_ramp_delay), + .ramp_reg =3D BD73800_REG_BUCK1_MODE, + .ramp_mask =3D BD73800_MASK_RAMP_DELAY, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_BUCK1_VOLT_RUN, + .run_mask =3D BD73800_MASK_VOLT, + .idle_reg =3D BD73800_REG_BUCK1_VOLT_IDLE, + .idle_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_reg =3D BD73800_REG_BUCK1_VOLT_SUSP, + .suspend_mask =3D BD73800_MASK_VOLT, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "buck2", + .of_match =3D of_match_ptr("buck2"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_BUCK2, + .ops =3D &bd73800_buck_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_buck12348_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_buck12348_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_BUCK2_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_BUCK2_VOLT_RUN, + .vsel_mask =3D BD73800_MASK_VOLT, + .ramp_delay_table =3D bd71828_ramp_delay, + .n_ramp_values =3D ARRAY_SIZE(bd71828_ramp_delay), + .ramp_reg =3D BD73800_REG_BUCK2_MODE, + .ramp_mask =3D BD73800_MASK_RAMP_DELAY, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_BUCK2_VOLT_RUN, + .run_mask =3D BD73800_MASK_VOLT, + .idle_reg =3D BD73800_REG_BUCK2_VOLT_IDLE, + .idle_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_reg =3D BD73800_REG_BUCK2_VOLT_SUSP, + .suspend_mask =3D BD73800_MASK_VOLT, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "buck3", + .of_match =3D of_match_ptr("buck3"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_BUCK3, + .ops =3D &bd73800_buck_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_buck12348_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_buck12348_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_BUCK3_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_BUCK3_VOLT_RUN, + .vsel_mask =3D BD73800_MASK_VOLT, + .ramp_delay_table =3D bd71828_ramp_delay, + .n_ramp_values =3D ARRAY_SIZE(bd71828_ramp_delay), + .ramp_reg =3D BD73800_REG_BUCK3_MODE, + .ramp_mask =3D BD73800_MASK_RAMP_DELAY, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_BUCK3_VOLT_RUN, + .run_mask =3D BD73800_MASK_VOLT, + .idle_reg =3D BD73800_REG_BUCK3_VOLT_IDLE, + .idle_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_reg =3D BD73800_REG_BUCK3_VOLT_SUSP, + .suspend_mask =3D BD73800_MASK_VOLT, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + + }, { + .desc =3D { + .name =3D "buck4", + .of_match =3D of_match_ptr("buck4"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_BUCK4, + .ops =3D &bd73800_buck_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_buck12348_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_buck12348_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_BUCK4_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_BUCK4_VOLT_RUN, + .vsel_mask =3D BD73800_MASK_VOLT, + .ramp_delay_table =3D bd71828_ramp_delay, + .n_ramp_values =3D ARRAY_SIZE(bd71828_ramp_delay), + .ramp_reg =3D BD73800_REG_BUCK4_MODE, + .ramp_mask =3D BD73800_MASK_RAMP_DELAY, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_BUCK4_VOLT_RUN, + .run_mask =3D BD73800_MASK_VOLT, + .idle_reg =3D BD73800_REG_BUCK4_VOLT_IDLE, + .idle_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_reg =3D BD73800_REG_BUCK4_VOLT_SUSP, + .suspend_mask =3D BD73800_MASK_VOLT, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "buck5", + .of_match =3D of_match_ptr("buck5"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_BUCK5, + .ops =3D &bd73800_buck5_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_buck5_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_buck5_volts), + .linear_range_selectors_bitfield =3D + bd73800_buck5_volt_range_sel, + .n_voltages =3D BD73800_NUM_BUCK5_VOLTS, + .enable_reg =3D BD73800_REG_BUCK5_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_BUCK5_VOLT_RUN, + .vsel_mask =3D BD73800_MASK_BUCK5_VOLT, + .vsel_range_reg =3D BD73800_REG_BUCK5_MODE, + .vsel_range_mask =3D BD73800_BUCK5_RANGE_MASK, + .range_applied_by_vsel =3D true, + .ramp_delay_table =3D bd71828_ramp_delay, + .n_ramp_values =3D ARRAY_SIZE(bd71828_ramp_delay), + .ramp_reg =3D BD73800_REG_BUCK5_MODE, + .ramp_mask =3D BD73800_MASK_RAMP_DELAY, + .owner =3D THIS_MODULE, + }, + .dvs =3D { + /* + * We don't support setting the IDLE / SUSPEND voltages + * for the BUCK 5 for now. Reason is that the pickable + * range selector bit is common for all states (RUN, + * SUSPEND and IDLE), and toggling it for one impacts + * also others. + * Furthermore, writing the BD73800 range selector does + * not impact the RUN voltage until a new voltage value + * is also written to the vsel register. Hence the + * voltage change can be done without any 'intermediate + * voltages', even when the range is changed when the + * BUCK is enabled. + * It, however, is not documented how the IDLE / SUSPEND + * states work in this regard. I expect the full + * combination of the range selector and vsel is taken + * into account at the state change, no matter when they + * have been written to. + */ + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_BUCK5_VOLT_RUN, + .run_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + + }, { + .desc =3D { + .name =3D "buck6", + .of_match =3D of_match_ptr("buck6"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_BUCK6, + .ops =3D &bd73800_buck_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_buck67_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_buck67_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_BUCK6_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_BUCK6_VOLT_RUN, + .vsel_mask =3D BD73800_MASK_VOLT, + .ramp_delay_table =3D bd71828_ramp_delay, + .n_ramp_values =3D ARRAY_SIZE(bd71828_ramp_delay), + .ramp_reg =3D BD73800_REG_BUCK6_MODE, + .ramp_mask =3D BD73800_MASK_RAMP_DELAY, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_BUCK6_VOLT_RUN, + .run_mask =3D BD73800_MASK_VOLT, + .idle_reg =3D BD73800_REG_BUCK6_VOLT_IDLE, + .idle_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_reg =3D BD73800_REG_BUCK6_VOLT_SUSP, + .suspend_mask =3D BD73800_MASK_VOLT, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "buck7", + .of_match =3D of_match_ptr("buck7"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_BUCK7, + .ops =3D &bd73800_buck_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_buck67_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_buck67_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_BUCK7_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_BUCK7_VOLT_RUN, + .vsel_mask =3D BD73800_MASK_VOLT, + .ramp_delay_table =3D bd71828_ramp_delay, + .n_ramp_values =3D ARRAY_SIZE(bd71828_ramp_delay), + .ramp_reg =3D BD73800_REG_BUCK7_MODE, + .ramp_mask =3D BD73800_MASK_RAMP_DELAY, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_BUCK7_VOLT_RUN, + .run_mask =3D BD73800_MASK_VOLT, + .idle_reg =3D BD73800_REG_BUCK7_VOLT_IDLE, + .idle_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_reg =3D BD73800_REG_BUCK7_VOLT_SUSP, + .suspend_mask =3D BD73800_MASK_VOLT, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "buck8", + .of_match =3D of_match_ptr("buck8"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_BUCK8, + .ops =3D &bd73800_buck_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_buck12348_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_buck12348_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_BUCK8_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_BUCK8_VOLT_RUN, + .vsel_mask =3D BD73800_MASK_VOLT, + .ramp_delay_table =3D bd71828_ramp_delay, + .n_ramp_values =3D ARRAY_SIZE(bd71828_ramp_delay), + .ramp_reg =3D BD73800_REG_BUCK8_MODE, + .ramp_mask =3D BD73800_MASK_RAMP_DELAY, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_BUCK8_VOLT_RUN, + .run_mask =3D BD73800_MASK_VOLT, + .idle_reg =3D BD73800_REG_BUCK8_VOLT_IDLE, + .idle_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_reg =3D BD73800_REG_BUCK8_VOLT_SUSP, + .suspend_mask =3D BD73800_MASK_VOLT, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "ldo1", + .of_match =3D of_match_ptr(LDO1_NODE_NAME), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_LDO1, + .ops =3D &bd73800_ldo_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_ldo13_low_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_ldo13_low_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_LDO1_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_LDO1_VOLT, + .vsel_mask =3D BD73800_MASK_VOLT, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + /* + * LDOs support only single voltage for all states. + * Voltage can be individually enabled for each state + * though. Allow setting enable/disable config by + * setting the <state>_on_mask for all supported states. + */ + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_LDO1_VOLT, + .run_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "ldo2", + .of_match =3D of_match_ptr("ldo2"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_LDO2, + .ops =3D &bd73800_ldo_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_ldo24_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_ldo24_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_LDO2_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_LDO2_VOLT, + .vsel_mask =3D BD73800_MASK_VOLT, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_LDO2_VOLT, + .run_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "ldo3", + .of_match =3D of_match_ptr(LDO3_NODE_NAME), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_LDO3, + .ops =3D &bd73800_ldo_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_ldo13_low_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_ldo13_low_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_LDO3_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_LDO3_VOLT, + .vsel_mask =3D BD73800_MASK_VOLT, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_LDO3_VOLT, + .run_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, { + .desc =3D { + .name =3D "ldo4", + .of_match =3D of_match_ptr("ldo4"), + .regulators_node =3D of_match_ptr("regulators"), + .id =3D BD73800_LDO4, + .ops =3D &bd73800_ldo_ops, + .type =3D REGULATOR_VOLTAGE, + .linear_ranges =3D bd73800_ldo24_volts, + .n_linear_ranges =3D ARRAY_SIZE(bd73800_ldo24_volts), + .n_voltages =3D BD73800_NUM_VOLTS, + .enable_reg =3D BD73800_REG_LDO4_ON, + .enable_mask =3D BD73800_MASK_RUN_EN, + .vsel_reg =3D BD73800_REG_LDO4_VOLT, + .vsel_mask =3D BD73800_MASK_VOLT, + .owner =3D THIS_MODULE, + .of_parse_cb =3D buck_set_hw_dvs_levels, + }, + .dvs =3D { + .level_map =3D ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | + ROHM_DVS_LEVEL_SUSPEND, + .run_reg =3D BD73800_REG_LDO4_VOLT, + .run_mask =3D BD73800_MASK_VOLT, + .idle_on_mask =3D BD73800_MASK_IDLE_EN, + .suspend_on_mask =3D BD73800_MASK_SUSP_EN, + }, + }, +}; + static int bd72720_buck10_ldon_head_mode(struct device *dev, struct device_node *npreg, struct regmap *regmap, @@ -1619,6 +2111,52 @@ static int bd72720_dt_parse(struct device *dev, return bd72720_buck10_ldon_head_mode(dev, nproot, regmap, buck10_desc); } =20 +static bool bd73800_use_ldo_high_range(struct device_node *nproot, + const char *ldo_node) +{ + struct device_node *np __free(device_node) =3D + of_get_child_by_name(nproot, ldo_node); + + if (!np) + return false; + + return of_property_read_bool(np, "rohm,ldo-range-high"); +} + +static int bd73800_check_ldo_otp_options(struct device *dev, + struct bd71828_regulator_data *d, + unsigned int num_reg_data) +{ + struct device_node *nproot __free(device_node) =3D + of_get_child_by_name(dev->parent->of_node, "regulators"); + + /* + * The code assumes regulator IDs to start from 0 and to match the + * indexing of regulator data arrays. WARN if someone changes this. + */ + WARN_ON(d[BD73800_LDO1].desc.id !=3D BD73800_LDO1); + WARN_ON(d[BD73800_LDO3].desc.id !=3D BD73800_LDO3); + + if (!nproot) { + dev_err(dev, "failed to find regulators node\n"); + return -ENODEV; + } + + if (bd73800_use_ldo_high_range(nproot, LDO1_NODE_NAME)) { + d[BD73800_LDO1].desc.linear_ranges =3D bd73800_ldo13_high_volts; + d[BD73800_LDO1].desc.n_linear_ranges =3D + ARRAY_SIZE(bd73800_ldo13_high_volts); + } + + if (bd73800_use_ldo_high_range(nproot, LDO3_NODE_NAME)) { + d[BD73800_LDO3].desc.linear_ranges =3D bd73800_ldo13_high_volts; + d[BD73800_LDO3].desc.n_linear_ranges =3D + ARRAY_SIZE(bd73800_ldo13_high_volts); + } + + return 0; +} + static int bd71828_probe(struct platform_device *pdev) { int i, j, ret, num_regulators; @@ -1656,6 +2194,23 @@ static int bd71828_probe(struct platform_device *pde= v) num_regulators =3D ARRAY_SIZE(bd71828_rdata); =20 break; + + case ROHM_CHIP_TYPE_BD73800: + { + rdata =3D devm_kmemdup(&pdev->dev, bd73800_rdata, + sizeof(bd73800_rdata), GFP_KERNEL); + if (!rdata) + return -ENOMEM; + + num_regulators =3D ARRAY_SIZE(bd73800_rdata); + + ret =3D bd73800_check_ldo_otp_options(&pdev->dev, rdata, + num_regulators); + if (ret) + return ret; + + break; + } default: return dev_err_probe(&pdev->dev, -EINVAL, "Unsupported device\n"); @@ -1692,6 +2247,7 @@ static int bd71828_probe(struct platform_device *pdev) static const struct platform_device_id bd71828_pmic_id[] =3D { { .name =3D "bd71828-pmic", .driver_data =3D ROHM_CHIP_TYPE_BD71828 }, { .name =3D "bd72720-pmic", .driver_data =3D ROHM_CHIP_TYPE_BD72720 }, + { .name =3D "bd73800-pmic", .driver_data =3D ROHM_CHIP_TYPE_BD73800 }, { } }; MODULE_DEVICE_TABLE(platform, bd71828_pmic_id); --=20 2.55.0 --y8VN4YtQIluSFgZs Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQEzBAEBCgAdFiEEIx+f8wZb28fLKEhTeFA3/03aocUFAmpxvW8ACgkQeFA3/03a ocX56Af8CLqbIVFMTub6EZA4fxIhqgnmbevKIqEwUwjtsuIKiiFKmzgSxfA9XySk lfNcQE1CAON02Fn9YOMeOOTuxfO5YvPprWC609/YhYgKgipYmN38P6G8FnNfVcc/ zJbDx3lLIxyPYOU+eBKVEavVQNsEwAIh7Bk6Hab4UKlJfrYmFcBuMsv16GAYRIwz y9/xlPJqIyxCGQ6mn6Jxjtf0KWWA7dxlVGy64gXSHWcDC5BSrVgGKEv+T93Z7Xki +mXzfH8GXNIXAOXhI+JhioIRRl/DFxTAT9pBjEyhgvjaR+cmZx8LwbM8rnHQvZNC e6BXQCAUbbT2vxWzL2/qnRyrHkvtNQ== =Z6WA -----END PGP SIGNATURE----- --y8VN4YtQIluSFgZs--