mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
regulator: bd71828: Support ROHM BD73800
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 <mazziesaccount@gmail.com> Acked-by: Mark Brown <broonie@kernel.org> Link: https://patch.msgid.link/94a1cef828fb5f6ea1703167c819f321ee3bde77.1789538455.git.mazziesaccount@gmail.com Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
parent
fcf132b701
commit
e2be915076
|
|
@ -241,12 +241,12 @@ config REGULATOR_BD71815
|
|||
will be called bd71815-regulator.
|
||||
|
||||
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.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright (C) 2019 ROHM Semiconductors
|
||||
// bd71828-regulator.c ROHM BD71828GW-DS1 regulator driver
|
||||
//
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
/*
|
||||
* LDO1 and LDO3 node names are used also in the driver to find OTP setting for
|
||||
* the used voltage range.
|
||||
*/
|
||||
#define LDO1_NODE_NAME "ldo1"
|
||||
#define LDO3_NODE_NAME "ldo3"
|
||||
|
||||
static const struct reg_init bd71828_buck1_inits[] = {
|
||||
/*
|
||||
* DVS Buck voltages can be changed by register values or via GPIO.
|
||||
|
|
@ -172,6 +179,55 @@ static const struct linear_range bd72720_ldo6_volts[] = {
|
|||
REGULATOR_LINEAR_RANGE(1800000, 0x79, 0x7f, 0),
|
||||
};
|
||||
|
||||
static const struct linear_range bd73800_buck12348_volts[] = {
|
||||
REGULATOR_LINEAR_RANGE(500000, 0x00, 0x50, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1300000, 0x51, 0xff, 0),
|
||||
};
|
||||
|
||||
static const unsigned int bd73800_buck5_volt_range_sel[] = {
|
||||
0x0, 0x0, 0x1, 0x1,
|
||||
};
|
||||
|
||||
static const struct linear_range bd73800_buck5_volts[] = {
|
||||
/* 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[] = {
|
||||
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[] = {
|
||||
REGULATOR_LINEAR_RANGE(600000, 0x00, 0x78, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1800000, 0x79, 0xff, 0),
|
||||
};
|
||||
|
||||
static const struct linear_range bd73800_ldo13_high_volts[] = {
|
||||
REGULATOR_LINEAR_RANGE(750000, 0x00, 0xff, 10000),
|
||||
};
|
||||
|
||||
static const struct linear_range bd73800_ldo24_volts[] = {
|
||||
REGULATOR_LINEAR_RANGE(750000, 0x00, 0xff, 10000),
|
||||
};
|
||||
|
||||
static const unsigned int bd71828_ramp_delay[] = { 2500, 5000, 10000, 20000 };
|
||||
|
||||
/*
|
||||
|
|
@ -225,6 +281,36 @@ static int bd71828_ldo6_parse_dt(struct device_node *np,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Operations for all other BUCKs but BUCK 5 */
|
||||
static const struct regulator_ops bd73800_buck_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_ramp_delay = regulator_set_ramp_delay_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_ops bd73800_buck5_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 = regulator_set_voltage_sel_pickable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
|
||||
.set_ramp_delay = regulator_set_ramp_delay_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_ops bd73800_ldo_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,
|
||||
};
|
||||
|
||||
static const struct regulator_ops bd71828_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
|
|
@ -1565,6 +1651,412 @@ static const struct bd71828_regulator_data bd72720_rdata[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct bd71828_regulator_data bd73800_rdata[] = {
|
||||
{
|
||||
.desc = {
|
||||
.name = "buck1",
|
||||
.of_match = of_match_ptr("buck1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK1,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK1_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK1_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK1_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK1_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK1_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK1_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck2",
|
||||
.of_match = of_match_ptr("buck2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK2,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK2_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK2_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK2_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK2_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK2_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK2_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck3",
|
||||
.of_match = of_match_ptr("buck3"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK3,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK3_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK3_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK3_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK3_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK3_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK3_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck4",
|
||||
.of_match = of_match_ptr("buck4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK4,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK4_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK4_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK4_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK4_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK4_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK4_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck5",
|
||||
.of_match = of_match_ptr("buck5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK5,
|
||||
.ops = &bd73800_buck5_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck5_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck5_volts),
|
||||
.linear_range_selectors_bitfield =
|
||||
bd73800_buck5_volt_range_sel,
|
||||
.n_voltages = BD73800_NUM_BUCK5_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK5_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK5_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_BUCK5_VOLT,
|
||||
.vsel_range_reg = BD73800_REG_BUCK5_MODE,
|
||||
.vsel_range_mask = BD73800_BUCK5_RANGE_MASK,
|
||||
.range_applied_by_vsel = true,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK5_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.dvs = {
|
||||
/*
|
||||
* 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 = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK5_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck6",
|
||||
.of_match = of_match_ptr("buck6"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK6,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck67_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck67_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK6_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK6_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK6_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK6_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK6_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK6_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck7",
|
||||
.of_match = of_match_ptr("buck7"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK7,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck67_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck67_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK7_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK7_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK7_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK7_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK7_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK7_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "buck8",
|
||||
.of_match = of_match_ptr("buck8"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_BUCK8,
|
||||
.ops = &bd73800_buck_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_buck12348_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_BUCK8_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_BUCK8_VOLT_RUN,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.ramp_delay_table = bd71828_ramp_delay,
|
||||
.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
|
||||
.ramp_reg = BD73800_REG_BUCK8_MODE,
|
||||
.ramp_mask = BD73800_MASK_RAMP_DELAY,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_BUCK8_VOLT_RUN,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_reg = BD73800_REG_BUCK8_VOLT_IDLE,
|
||||
.idle_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_reg = BD73800_REG_BUCK8_VOLT_SUSP,
|
||||
.suspend_mask = BD73800_MASK_VOLT,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "ldo1",
|
||||
.of_match = of_match_ptr(LDO1_NODE_NAME),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_LDO1,
|
||||
.ops = &bd73800_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_ldo13_low_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_ldo13_low_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_LDO1_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_LDO1_VOLT,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
/*
|
||||
* 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 = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_LDO1_VOLT,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "ldo2",
|
||||
.of_match = of_match_ptr("ldo2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_LDO2,
|
||||
.ops = &bd73800_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_ldo24_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_ldo24_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_LDO2_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_LDO2_VOLT,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_LDO2_VOLT,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "ldo3",
|
||||
.of_match = of_match_ptr(LDO3_NODE_NAME),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_LDO3,
|
||||
.ops = &bd73800_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_ldo13_low_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_ldo13_low_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_LDO3_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_LDO3_VOLT,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_LDO3_VOLT,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = BD73800_MASK_SUSP_EN,
|
||||
},
|
||||
}, {
|
||||
.desc = {
|
||||
.name = "ldo4",
|
||||
.of_match = of_match_ptr("ldo4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = BD73800_LDO4,
|
||||
.ops = &bd73800_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.linear_ranges = bd73800_ldo24_volts,
|
||||
.n_linear_ranges = ARRAY_SIZE(bd73800_ldo24_volts),
|
||||
.n_voltages = BD73800_NUM_VOLTS,
|
||||
.enable_reg = BD73800_REG_LDO4_ON,
|
||||
.enable_mask = BD73800_MASK_RUN_EN,
|
||||
.vsel_reg = BD73800_REG_LDO4_VOLT,
|
||||
.vsel_mask = BD73800_MASK_VOLT,
|
||||
.owner = THIS_MODULE,
|
||||
.of_parse_cb = buck_set_hw_dvs_levels,
|
||||
},
|
||||
.dvs = {
|
||||
.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
|
||||
ROHM_DVS_LEVEL_SUSPEND,
|
||||
.run_reg = BD73800_REG_LDO4_VOLT,
|
||||
.run_mask = BD73800_MASK_VOLT,
|
||||
.idle_on_mask = BD73800_MASK_IDLE_EN,
|
||||
.suspend_on_mask = 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);
|
||||
}
|
||||
|
||||
static bool bd73800_use_ldo_high_range(struct device_node *nproot,
|
||||
const char *ldo_node)
|
||||
{
|
||||
struct device_node *np __free(device_node) =
|
||||
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) =
|
||||
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 != BD73800_LDO1);
|
||||
WARN_ON(d[BD73800_LDO3].desc.id != 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 = bd73800_ldo13_high_volts;
|
||||
d[BD73800_LDO1].desc.n_linear_ranges =
|
||||
ARRAY_SIZE(bd73800_ldo13_high_volts);
|
||||
}
|
||||
|
||||
if (bd73800_use_ldo_high_range(nproot, LDO3_NODE_NAME)) {
|
||||
d[BD73800_LDO3].desc.linear_ranges = bd73800_ldo13_high_volts;
|
||||
d[BD73800_LDO3].desc.n_linear_ranges =
|
||||
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 *pdev)
|
|||
num_regulators = ARRAY_SIZE(bd71828_rdata);
|
||||
|
||||
break;
|
||||
|
||||
case ROHM_CHIP_TYPE_BD73800:
|
||||
{
|
||||
rdata = devm_kmemdup(&pdev->dev, bd73800_rdata,
|
||||
sizeof(bd73800_rdata), GFP_KERNEL);
|
||||
if (!rdata)
|
||||
return -ENOMEM;
|
||||
|
||||
num_regulators = ARRAY_SIZE(bd73800_rdata);
|
||||
|
||||
ret = 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[] = {
|
||||
{ .name = "bd71828-pmic", .driver_data = ROHM_CHIP_TYPE_BD71828 },
|
||||
{ .name = "bd72720-pmic", .driver_data = ROHM_CHIP_TYPE_BD72720 },
|
||||
{ .name = "bd73800-pmic", .driver_data = ROHM_CHIP_TYPE_BD73800 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, bd71828_pmic_id);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user