drivers: regulator: refactor PMIC binding to use physical PMIC IC

Refactor binding to use root PMIC IC, so that properties can be shared
between regulator devices. Each individual regulator output is still
created as an individual device, since the regulator API aligns with
these devices better than the PMIC IC itself.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
Daniel DeGrasse 2022-10-06 15:45:05 -05:00 committed by Carles Cufí
commit f367897bce
4 changed files with 129 additions and 113 deletions

View file

@ -156,9 +156,9 @@ arduino_serial: &flexcomm12 {
pca9420: pca9420@61 { pca9420: pca9420@61 {
reg = <0x61>; reg = <0x61>;
compatible = "regulator-pmic";
pca9420_sw1: sw1_buck { pca9420_sw1: sw1_buck {
compatible = "regulator-pmic";
voltage-range = <PCA9420_SW1_VOLTAGE_RANGE>; voltage-range = <PCA9420_SW1_VOLTAGE_RANGE>;
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>; current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
num-voltages = <42>; num-voltages = <42>;
@ -175,7 +175,6 @@ arduino_serial: &flexcomm12 {
}; };
pca9420_sw2: sw2_buck { pca9420_sw2: sw2_buck {
compatible = "regulator-pmic";
voltage-range = <PCA9420_SW2_VOLTAGE_RANGE>; voltage-range = <PCA9420_SW2_VOLTAGE_RANGE>;
num-voltages = <50>; num-voltages = <50>;
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>; current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
@ -192,7 +191,6 @@ arduino_serial: &flexcomm12 {
}; };
pca9420_ldo1: ldo1_reg { pca9420_ldo1: ldo1_reg {
compatible = "regulator-pmic";
voltage-range = <PCA9420_LDO1_VOLTAGE_RANGE>; voltage-range = <PCA9420_LDO1_VOLTAGE_RANGE>;
num-voltages = <9>; num-voltages = <9>;
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>; current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
@ -209,7 +207,6 @@ arduino_serial: &flexcomm12 {
}; };
pca9420_ldo2: ldo2_reg { pca9420_ldo2: ldo2_reg {
compatible = "regulator-pmic";
voltage-range = <PCA9420_LDO2_VOLTAGE_RANGE>; voltage-range = <PCA9420_LDO2_VOLTAGE_RANGE>;
num-voltages = <50>; num-voltages = <50>;
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>; current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;

View file

@ -230,9 +230,9 @@ i2s1: &flexcomm3 {
pca9420: pca9420@61 { pca9420: pca9420@61 {
reg = <0x61>; reg = <0x61>;
compatible = "regulator-pmic";
pca9420_sw1: sw1_buck { pca9420_sw1: sw1_buck {
compatible = "regulator-pmic";
voltage-range = <PCA9420_SW1_VOLTAGE_RANGE>; voltage-range = <PCA9420_SW1_VOLTAGE_RANGE>;
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>; current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
num-voltages = <42>; num-voltages = <42>;
@ -249,7 +249,6 @@ i2s1: &flexcomm3 {
}; };
pca9420_sw2: sw2_buck { pca9420_sw2: sw2_buck {
compatible = "regulator-pmic";
voltage-range = <PCA9420_SW2_VOLTAGE_RANGE>; voltage-range = <PCA9420_SW2_VOLTAGE_RANGE>;
num-voltages = <50>; num-voltages = <50>;
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>; current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
@ -266,7 +265,6 @@ i2s1: &flexcomm3 {
}; };
pca9420_ldo1: ldo1_reg { pca9420_ldo1: ldo1_reg {
compatible = "regulator-pmic";
voltage-range = <PCA9420_LDO1_VOLTAGE_RANGE>; voltage-range = <PCA9420_LDO1_VOLTAGE_RANGE>;
num-voltages = <9>; num-voltages = <9>;
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>; current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;
@ -283,7 +281,6 @@ i2s1: &flexcomm3 {
}; };
pca9420_ldo2: ldo2_reg { pca9420_ldo2: ldo2_reg {
compatible = "regulator-pmic";
voltage-range = <PCA9420_LDO2_VOLTAGE_RANGE>; voltage-range = <PCA9420_LDO2_VOLTAGE_RANGE>;
num-voltages = <50>; num-voltages = <50>;
current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>; current-levels = <PCA9420_CURRENT_LIMIT_LEVELS>;

View file

@ -308,32 +308,52 @@ static const struct regulator_driver_api api = {
.disable = disable_regulator .disable = disable_regulator
}; };
#define CONFIGURE_REGULATOR(id) \
static uint32_t pmic_reg_##id##_cur_limits[] = \ /*
DT_INST_PROP_OR(id, current_levels, {}); \ * Each regulator output will be initialized as a separate device struct,
static uint32_t pmic_reg_##id##_vol_range[] = \ * and implement the regulator API. Since the DT binding is defined for the
DT_INST_PROP(id, voltage_range); \ * entire regulator, this macro will be called for each child node of the
static struct regulator_data pmic_reg_##id##_data; \ * regulator device. This allows the regulator to have common DTS properties
static struct regulator_config pmic_reg_##id##_cfg = { \ * shared between each regulator output
.vsel_mask = DT_INST_PROP(id, vsel_mask), \ */
.vsel_reg = DT_INST_PROP(id, vsel_reg), \ #define CONFIGURE_REGULATOR_OUTPUT(node, ord) \
.num_voltages = DT_INST_PROP(id, num_voltages), \ static uint32_t pmic_reg_##ord##_cur_limits[] = \
.num_current_levels = DT_INST_PROP(id, num_current_levels), \ DT_PROP_OR(node, current_levels, {}); \
.enable_reg = DT_INST_PROP(id, enable_reg), \ static uint32_t pmic_reg_##ord##_vol_range[] = \
.enable_mask = DT_INST_PROP(id, enable_mask), \ DT_PROP(node, voltage_range); \
.enable_val = DT_INST_PROP(id, enable_val), \ static struct regulator_data pmic_reg_##ord##_data; \
.min_uV = DT_INST_PROP(id, min_uv), \ static struct regulator_config pmic_reg_##ord##_cfg = { \
.max_uV = DT_INST_PROP(id, max_uv), \ .vsel_mask = DT_PROP(node, vsel_mask), \
.ilim_reg = DT_INST_PROP_OR(id, ilim_reg, 0), \ .vsel_reg = DT_PROP(node, vsel_reg), \
.ilim_mask = DT_INST_PROP_OR(id, ilim_mask, 0), \ .num_voltages = DT_PROP(node, num_voltages), \
.enable_inverted = DT_INST_PROP(id, enable_inverted), \ .num_current_levels = DT_PROP(node, num_current_levels), \
.i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(id)), \ .enable_reg = DT_PROP(node, enable_reg), \
.voltage_array = pmic_reg_##id##_vol_range, \ .enable_mask = DT_PROP(node, enable_mask), \
.current_array = pmic_reg_##id##_cur_limits, \ .enable_val = DT_PROP(node, enable_val), \
.min_uV = DT_PROP(node, min_uv), \
.max_uV = DT_PROP(node, max_uv), \
.ilim_reg = DT_PROP_OR(node, ilim_reg, 0), \
.ilim_mask = DT_PROP_OR(node, ilim_mask, 0), \
.enable_inverted = DT_PROP(node, enable_inverted), \
.i2c = I2C_DT_SPEC_GET(DT_PARENT(node)), \
.voltage_array = pmic_reg_##ord##_vol_range, \
.current_array = pmic_reg_##ord##_cur_limits, \
}; \ }; \
DEVICE_DT_INST_DEFINE(id, pmic_reg_init, NULL, \ DEVICE_DT_DEFINE(node, pmic_reg_init, NULL, \
&pmic_reg_##id##_data, &pmic_reg_##id##_cfg, \ &pmic_reg_##ord##_data, \
&pmic_reg_##ord##_cfg, \
POST_KERNEL, CONFIG_PMIC_REGULATOR_INIT_PRIORITY, \ POST_KERNEL, CONFIG_PMIC_REGULATOR_INIT_PRIORITY, \
&api); \ &api); \
/* Intermediate macros to extract DT node ordinal
* (used as a unique token for variable names)
*/
#define _CONFIGURE_REGULATOR_OUTPUT(node, ord) \
CONFIGURE_REGULATOR_OUTPUT(node, ord)
#define __CONFIGURE_REGULATOR_OUTPUT(node) \
_CONFIGURE_REGULATOR_OUTPUT(node, DT_DEP_ORD(node))
#define CONFIGURE_REGULATOR(id) \
DT_INST_FOREACH_CHILD(id, __CONFIGURE_REGULATOR_OUTPUT)
DT_INST_FOREACH_STATUS_OKAY(CONFIGURE_REGULATOR) DT_INST_FOREACH_STATUS_OKAY(CONFIGURE_REGULATOR)

View file

@ -7,84 +7,86 @@ include: regulator.yaml
compatible: "regulator-pmic" compatible: "regulator-pmic"
properties: child-binding:
voltage-range: description: Voltage output of PMIC controller regulator
type: array properties:
required: true voltage-range:
description: | type: array
array of voltage values in uV, followed by the register value that required: true
must be written to enable the voltage. For example, [3300000, 0x3] description: |
denotes a value of 0x3 must be written to the register to set 3.3V array of voltage values in uV, followed by the register value that
num-voltages: must be written to enable the voltage. For example, [3300000, 0x3]
type: int denotes a value of 0x3 must be written to the register to set 3.3V
required: true num-voltages:
description: number of voltages present in the voltage-range array. type: int
vsel-reg: required: true
type: int description: number of voltages present in the voltage-range array.
required: true vsel-reg:
description: I2C register to write voltage selection value to type: int
vsel-mask: required: true
type: int description: I2C register to write voltage selection value to
required: true vsel-mask:
description: | type: int
Mask to apply to the voltage range value when written to vsel required: true
register description: |
enable-reg: Mask to apply to the voltage range value when written to vsel
type: int register
required: true enable-reg:
description: I2C register to write enable value to type: int
enable-mask: required: true
type: int description: I2C register to write enable value to
required: true enable-mask:
description: | type: int
Mask to apply to the enable bit (either 1 for enabled, required: true
or 0 for disabled) when writing it to the I2C enable register. description: |
enable-val: Mask to apply to the enable bit (either 1 for enabled,
type: int or 0 for disabled) when writing it to the I2C enable register.
required: true enable-val:
description: | type: int
value to apply enable-mask to, and write to enable-reg in order required: true
to enable the regulator output. description: |
min-uV: value to apply enable-mask to, and write to enable-reg in order
type: int to enable the regulator output.
required: true min-uV:
description: | type: int
Minimum voltage in microvolts that this regulator supports required: true
max-uV: description: |
type: int Minimum voltage in microvolts that this regulator supports
required: true max-uV:
description: | type: int
Maximum voltage in microvolts that this regulator supports required: true
enable-inverted: description: |
type: boolean Maximum voltage in microvolts that this regulator supports
required: false enable-inverted:
description: | type: boolean
If the enable bit should be zero to turn the regulator on, add this required: false
property. description: |
current-levels: If the enable bit should be zero to turn the regulator on, add this
type: array property.
required: false current-levels:
description: | type: array
Array of current limit values in uA, followed by the register value required: false
that must be written to enable the current limit. For example, description: |
[800000, 0x3] denotes a value of 0x3 must be written to the register Array of current limit values in uA, followed by the register value
to set a current limit of 800mA that must be written to enable the current limit. For example,
num-current-levels: [800000, 0x3] denotes a value of 0x3 must be written to the register
type: int to set a current limit of 800mA
required: false num-current-levels:
default: 0 type: int
description: | required: false
Number of current limit levels this regulator supports. If left as default: 0
default, regulator current support will be disabled. description: |
ilim-reg: Number of current limit levels this regulator supports. If left as
type: int default, regulator current support will be disabled.
required: false ilim-reg:
description: | type: int
Register to write the register value given in current-levels into required: false
to set the current limit description: |
ilim-mask: Register to write the register value given in current-levels into
type: int to set the current limit
required: false ilim-mask:
description: | type: int
Mask to apply to the current-levels value before writing it to the required: false
ilim-reg value to set the current limit description: |
Mask to apply to the current-levels value before writing it to the
ilim-reg value to set the current limit