From 1caedf12dd2a729ae2f85d4abb50b51f5acdcc3b Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Wed, 16 Nov 2022 21:37:08 +0100 Subject: [PATCH] drivers: regulator: pca9420: do not expose registers in DT Regulator registers were set for each BUCK/LDO in DT, likely because of the way the devices were instantiated. When using a generic iterator, ie, DT_INST_FOREACH_CHILD, there's no way to differentiate the child being _parsed_. Since instantiation happens now based on child node names, we are able to know which registers each devices gets assigned at the driver level. This greatly simplifies Devicetree, and it actually removes information that is not strictly hardware description from it. Signed-off-by: Gerard Marull-Paretas --- .../arm/mimxrt595_evk/mimxrt595_evk_cm33.dts | 28 --- .../arm/mimxrt685_evk/mimxrt685_evk_cm33.dts | 28 --- drivers/regulator/regulator_pca9420.c | 167 ++++++++++++++---- dts/bindings/regulator/nxp,pca9420.yaml | 36 ---- .../dt-bindings/regulator/pca9420_i2c.h | 45 +---- 5 files changed, 130 insertions(+), 174 deletions(-) diff --git a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts index 673a0ffee6f2..009ebf26fe0a 100644 --- a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts +++ b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts @@ -185,14 +185,7 @@ arduino_serial: &flexcomm12 { voltage-range = ; current-levels = ; num-voltages = <42>; - ilim-reg = ; - ilim-mask = ; num-current-levels = <7>; - vsel-reg = ; - vsel-mask = ; - enable-reg = ; - enable-mask = ; - enable-val = ; regulator-min-microvolt = <500000>; regulator-max-microvolt = <1800000>; regulator-boot-on; @@ -202,14 +195,7 @@ arduino_serial: &flexcomm12 { voltage-range = ; num-voltages = <50>; current-levels = ; - ilim-reg = ; - ilim-mask = ; num-current-levels = <7>; - vsel-reg = ; - vsel-mask = ; - enable-reg = ; - enable-mask = ; - enable-val = ; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <3300000>; regulator-boot-on; @@ -219,14 +205,7 @@ arduino_serial: &flexcomm12 { voltage-range = ; num-voltages = <9>; current-levels = ; - ilim-reg = ; - ilim-mask = ; num-current-levels = <7>; - vsel-reg = ; - vsel-mask = ; - enable-reg = ; - enable-mask = ; - enable-val = ; regulator-min-microvolt = <1700000>; regulator-max-microvolt = <1900000>; regulator-boot-on; @@ -236,14 +215,7 @@ arduino_serial: &flexcomm12 { voltage-range = ; num-voltages = <51>; current-levels = ; - ilim-reg = ; - ilim-mask = ; num-current-levels = <7>; - vsel-reg = ; - vsel-mask = ; - enable-reg = ; - enable-mask = ; - enable-val = ; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <3300000>; regulator-boot-on; diff --git a/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.dts b/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.dts index 3858eb067b54..e4c6b65a10bb 100644 --- a/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.dts +++ b/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.dts @@ -255,14 +255,7 @@ i2s1: &flexcomm3 { voltage-range = ; current-levels = ; num-voltages = <42>; - ilim-reg = ; - ilim-mask = ; num-current-levels = <7>; - vsel-reg = ; - vsel-mask = ; - enable-reg = ; - enable-mask = ; - enable-val = ; regulator-min-microvolt = <500000>; regulator-max-microvolt = <1800000>; regulator-boot-on; @@ -272,14 +265,7 @@ i2s1: &flexcomm3 { voltage-range = ; num-voltages = <50>; current-levels = ; - ilim-reg = ; - ilim-mask = ; num-current-levels = <7>; - vsel-reg = ; - vsel-mask = ; - enable-reg = ; - enable-mask = ; - enable-val = ; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <3300000>; regulator-boot-on; @@ -289,14 +275,7 @@ i2s1: &flexcomm3 { voltage-range = ; num-voltages = <9>; current-levels = ; - ilim-reg = ; - ilim-mask = ; num-current-levels = <7>; - vsel-reg = ; - vsel-mask = ; - enable-reg = ; - enable-mask = ; - enable-val = ; regulator-min-microvolt = <1700000>; regulator-max-microvolt = <1900000>; regulator-boot-on; @@ -306,14 +285,7 @@ i2s1: &flexcomm3 { voltage-range = ; num-voltages = <51>; current-levels = ; - ilim-reg = ; - ilim-mask = ; num-current-levels = <7>; - vsel-reg = ; - vsel-mask = ; - enable-reg = ; - enable-mask = ; - enable-val = ; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <3300000>; regulator-boot-on; diff --git a/drivers/regulator/regulator_pca9420.c b/drivers/regulator/regulator_pca9420.c index 96f094ddc947..902479b7a927 100644 --- a/drivers/regulator/regulator_pca9420.c +++ b/drivers/regulator/regulator_pca9420.c @@ -16,6 +16,56 @@ LOG_MODULE_REGISTER(pca9420, CONFIG_REGULATOR_LOG_LEVEL); +/** Register memory map. See datasheet for more details. */ +/** General purpose registers */ +/** @brief Top level system ctrl 0 */ +#define PCA9420_TOP_CNTL0 0x09U + +/** Regulator status indication registers */ +/** @brief Mode configuration for mode 0_0 */ +#define PCA9420_MODECFG_0_0 0x22U +/** @brief Mode configuration for mode 0_1 */ +#define PCA9420_MODECFG_0_1 0x23U +/** @brief Mode configuration for mode 0_2 */ +#define PCA9420_MODECFG_0_2 0x24U +/** @brief Mode configuration for mode 0_3 */ +#define PCA9420_MODECFG_0_3 0x25U + +/** @brief VIN input current limit selection */ +#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK 0xE0U + +/* + * @brief Mode control selection mask. When this bit is set, the external + * PMIC pins MODESEL0 and MODESEL1 can be used to select the active mode + */ +#define PCA9420_MODECFG_0_MODE_CTRL_SEL_MASK 0x40U + +/* + * @brief Mode configuration upon falling edge applied to ON pin. If set, + * the device will switch to mode 0 when a valid falling edge is applied. + * to the ON pin + */ +/** @brief Mode output voltage mask */ +#define PCA9420_MODECFG_0_SW1_OUT_MASK 0x3FU +/** @brief SW2_OUT offset and voltage level mask */ +#define PCA9420_MODECFG_1_SW2_OUT_MASK 0x3FU +/** @brief LDO1_OUT voltage level mask */ +#define PCA9420_MODECFG_2_LDO1_OUT_MASK 0xF0U +/** @brief SW1 Enable */ +#define PCA9420_MODECFG_2_SW1_EN_MASK 0x08U +#define PCA9420_MODECFG_2_SW1_EN_VAL 0x08U +/** @brief SW2 Enable */ +#define PCA9420_MODECFG_2_SW2_EN_MASK 0x04U +#define PCA9420_MODECFG_2_SW2_EN_VAL 0x04U +/** @brief LDO1 Enable */ +#define PCA9420_MODECFG_2_LDO1_EN_MASK 0x02U +#define PCA9420_MODECFG_2_LDO1_EN_VAL 0x02U +/** @brief LDO2 Enable */ +#define PCA9420_MODECFG_2_LDO2_EN_MASK 0x01U +#define PCA9420_MODECFG_2_LDO2_EN_VAL 0x01U +/** @brief LDO2_OUT offset and voltage level mask */ +#define PCA9420_MODECFG_3_LDO2_OUT_MASK 0x3FU + struct voltage_range { int32_t uV; /* Voltage in uV */ uint8_t reg_val; /* Register value for voltage */ @@ -26,6 +76,16 @@ struct current_range { uint8_t reg_val; /* Register value for current limit */ }; +struct regulator_pca9420_desc { + uint8_t enable_reg; + uint8_t enable_mask; + uint8_t enable_val; + uint8_t ilim_reg; + uint8_t ilim_mask; + uint8_t vsel_reg; + uint8_t vsel_mask; +}; + struct regulator_pca9420_data { struct onoff_sync_service srv; const struct voltage_range *voltages; @@ -36,17 +96,10 @@ struct regulator_pca9420_config { int num_voltages; int num_current_levels; int num_modes; - uint8_t vsel_reg; - uint8_t vsel_mask; int32_t max_uv; int32_t min_uv; - uint8_t enable_reg; - uint8_t enable_mask; - uint8_t enable_val; bool enable_inverted; bool boot_on; - uint8_t ilim_reg; - uint8_t ilim_mask; struct i2c_dt_spec i2c; uint16_t initial_mode; const uint32_t *voltage_array; @@ -54,6 +107,47 @@ struct regulator_pca9420_config { const uint16_t *allowed_modes; uint8_t modesel_reg; uint8_t modesel_mask; + const struct regulator_pca9420_desc *desc; +}; + +static const struct regulator_pca9420_desc buck1_desc = { + .enable_reg = PCA9420_MODECFG_0_2, + .enable_mask = PCA9420_MODECFG_2_SW1_EN_MASK, + .enable_val = PCA9420_MODECFG_2_SW1_EN_VAL, + .ilim_reg = PCA9420_TOP_CNTL0, + .ilim_mask = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK, + .vsel_mask = PCA9420_MODECFG_0_SW1_OUT_MASK, + .vsel_reg = PCA9420_MODECFG_0_0, +}; + +static const struct regulator_pca9420_desc buck2_desc = { + .enable_reg = PCA9420_MODECFG_0_2, + .enable_mask = PCA9420_MODECFG_2_SW2_EN_MASK, + .enable_val = PCA9420_MODECFG_2_SW2_EN_VAL, + .vsel_mask = PCA9420_MODECFG_1_SW2_OUT_MASK, + .vsel_reg = PCA9420_MODECFG_0_1, + .ilim_reg = PCA9420_TOP_CNTL0, + .ilim_mask = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK, +}; + +static const struct regulator_pca9420_desc ldo1_desc = { + .enable_reg = PCA9420_MODECFG_0_2, + .enable_mask = PCA9420_MODECFG_2_LDO1_EN_MASK, + .enable_val = PCA9420_MODECFG_2_LDO1_EN_VAL, + .vsel_mask = PCA9420_MODECFG_2_LDO1_OUT_MASK, + .vsel_reg = PCA9420_MODECFG_0_2, + .ilim_reg = PCA9420_TOP_CNTL0, + .ilim_mask = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK, +}; + +static const struct regulator_pca9420_desc ldo2_desc = { + .enable_reg = PCA9420_MODECFG_0_2, + .enable_mask = PCA9420_MODECFG_2_LDO2_EN_MASK, + .enable_val = PCA9420_MODECFG_2_LDO2_EN_VAL, + .vsel_reg = PCA9420_MODECFG_0_3, + .vsel_mask = PCA9420_MODECFG_3_LDO2_OUT_MASK, + .ilim_reg = PCA9420_TOP_CNTL0, + .ilim_mask = PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK, }; static int regulator_pca9420_is_supported_voltage(const struct device *dev, @@ -112,12 +206,12 @@ static int32_t regulator_pca9420_get_voltage_offset(const struct device *dev, int rc, i = 0; uint8_t raw_reg; - rc = regulator_pca9420_read_register(dev, config->vsel_reg + off, + rc = regulator_pca9420_read_register(dev, config->desc->vsel_reg + off, &raw_reg); if (rc) { return rc; } - raw_reg &= config->vsel_mask; + raw_reg &= config->desc->vsel_mask; /* Locate the voltage value in the voltage table */ while (i < config->num_voltages && raw_reg != data->voltages[i].reg_val){ @@ -162,8 +256,9 @@ static int regulator_set_voltage_offset(const struct device *dev, } LOG_DBG("Setting regulator %s to %duV", dev->name, data->voltages[i].uV); - return regulator_pca9420_modify_register(dev, config->vsel_reg + off, - config->vsel_mask, + return regulator_pca9420_modify_register(dev, + config->desc->vsel_reg + off, + config->desc->vsel_mask, data->voltages[i].reg_val); } @@ -265,7 +360,7 @@ static int regulator_pca9420_set_current_limit(const struct device *dev, } /* Set the current limit */ return regulator_pca9420_modify_register( - dev, config->ilim_reg, config->ilim_mask, + dev, config->desc->ilim_reg, config->desc->ilim_mask, data->current_levels[i].reg_val); } @@ -283,11 +378,12 @@ static int regulator_pca9420_get_current_limit(const struct device *dev) if (config->num_current_levels == 0) { return -ENOTSUP; } - rc = regulator_pca9420_read_register(dev, config->ilim_reg, &raw_reg); + rc = regulator_pca9420_read_register(dev, config->desc->ilim_reg, + &raw_reg); if (rc) { return rc; } - raw_reg &= config->ilim_mask; + raw_reg &= config->desc->ilim_mask; while (i < config->num_current_levels && data->current_levels[i].reg_val != raw_reg) { i++; @@ -356,10 +452,10 @@ static int regulator_pca9420_mode_disable(const struct device *dev, return -EINVAL; } sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT); - dis_val = config->enable_inverted ? config->enable_val : 0; - return regulator_pca9420_modify_register(dev, - config->enable_reg + sel_off, - config->enable_mask, dis_val); + dis_val = config->enable_inverted ? config->desc->enable_val : 0; + return regulator_pca9420_modify_register( + dev, config->desc->enable_reg + sel_off, + config->desc->enable_mask, dis_val); } /* @@ -388,10 +484,10 @@ static int regulator_pca9420_mode_enable(const struct device *dev, return -EINVAL; } sel_off = ((mode & PMIC_MODE_OFFSET_MASK) >> PMIC_MODE_OFFSET_SHIFT); - en_val = config->enable_inverted ? 0 : config->enable_val; - return regulator_pca9420_modify_register(dev, - config->enable_reg + sel_off, - config->enable_mask, en_val); + en_val = config->enable_inverted ? 0 : config->desc->enable_val; + return regulator_pca9420_modify_register( + dev, config->desc->enable_reg + sel_off, + config->desc->enable_mask, en_val); } /* @@ -480,9 +576,10 @@ static int regulator_pca9420_enable(const struct device *dev, /* Request has already enabled PMIC */ return onoff_sync_finalize(&data->srv, key, cli, rc, true); } - en_val = config->enable_inverted ? 0 : config->enable_val; - rc = regulator_pca9420_modify_register(dev, config->enable_reg, - config->enable_mask, en_val); + en_val = config->enable_inverted ? 0 : config->desc->enable_val; + rc = regulator_pca9420_modify_register(dev, config->desc->enable_reg, + config->desc->enable_mask, + en_val); if (rc != 0) { return onoff_sync_finalize(&data->srv, key, NULL, rc, false); } @@ -504,10 +601,10 @@ static int regulator_pca9420_disable(const struct device *dev) return onoff_sync_finalize(&data->srv, key, NULL, rc, false); } else if (rc == 1) { /* Disable regulator */ - dis_val = config->enable_inverted ? config->enable_val : 0; - rc = regulator_pca9420_modify_register(dev, config->enable_reg, - config->enable_mask, - dis_val); + dis_val = config->enable_inverted ? config->desc->enable_val : 0; + rc = regulator_pca9420_modify_register( + dev, config->desc->enable_reg, + config->desc->enable_mask, dis_val); } return onoff_sync_finalize(&data->srv, key, NULL, rc, false); } @@ -556,7 +653,7 @@ static const struct regulator_driver_api api = { .mode_enable = regulator_pca9420_mode_enable, }; -#define REGULATOR_PCA9420_DEFINE(node_id, id) \ +#define REGULATOR_PCA9420_DEFINE(node_id, id, name) \ static const uint32_t curr_limits_##id[] = \ DT_PROP_OR(node_id, current_levels, {}); \ static const uint32_t vol_range_##id[] = \ @@ -567,17 +664,10 @@ static const struct regulator_driver_api api = { static struct regulator_pca9420_data data_##id; \ \ static const struct regulator_pca9420_config config_##id = { \ - .vsel_mask = DT_PROP(node_id, vsel_mask), \ - .vsel_reg = DT_PROP(node_id, vsel_reg), \ .num_voltages = DT_PROP(node_id, num_voltages), \ .num_current_levels = DT_PROP(node_id, num_current_levels), \ - .enable_reg = DT_PROP(node_id, enable_reg), \ - .enable_mask = DT_PROP(node_id, enable_mask), \ - .enable_val = DT_PROP(node_id, enable_val), \ .min_uv = DT_PROP(node_id, regulator_min_microvolt), \ .max_uv = DT_PROP(node_id, regulator_max_microvolt), \ - .ilim_reg = DT_PROP_OR(node_id, ilim_reg, 0), \ - .ilim_mask = DT_PROP_OR(node_id, ilim_mask, 0), \ .enable_inverted = DT_PROP(node_id, enable_inverted), \ .boot_on = DT_PROP(node_id, regulator_boot_on), \ .num_modes = ARRAY_SIZE(allowed_modes_##id), \ @@ -590,6 +680,7 @@ static const struct regulator_driver_api api = { .modesel_reg = DT_PROP_OR(DT_PARENT(node_id), modesel_reg, 0), \ .modesel_mask = \ DT_PROP_OR(DT_PARENT(node_id), modesel_mask, 0), \ + .desc = &name ## _desc, \ }; \ \ DEVICE_DT_DEFINE(node_id, regulator_pca9420_init, NULL, &data_##id, \ @@ -599,7 +690,7 @@ static const struct regulator_driver_api api = { #define REGULATOR_PCA9420_DEFINE_COND(inst, child) \ COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \ (REGULATOR_PCA9420_DEFINE(DT_INST_CHILD(inst, child), \ - child ## inst)), ()) + child ## inst, child)), ()) #define REGULATOR_PCA9420_DEFINE_ALL(inst) \ REGULATOR_PCA9420_DEFINE_COND(inst, buck1) \ diff --git a/dts/bindings/regulator/nxp,pca9420.yaml b/dts/bindings/regulator/nxp,pca9420.yaml index d47532c81b0b..f49145142ff4 100644 --- a/dts/bindings/regulator/nxp,pca9420.yaml +++ b/dts/bindings/regulator/nxp,pca9420.yaml @@ -75,32 +75,6 @@ child-binding: type: int required: true description: number of voltages present in the voltage-range array. - vsel-reg: - type: int - required: true - description: I2C register to write voltage selection value to - vsel-mask: - type: int - required: true - description: | - Mask to apply to the voltage range value when written to vsel - register - enable-reg: - type: int - required: true - description: I2C register to write enable value to - enable-mask: - type: int - required: true - description: | - Mask to apply to the enable bit (either 1 for enabled, - or 0 for disabled) when writing it to the I2C enable register. - enable-val: - type: int - required: true - description: | - value to apply enable-mask to, and write to enable-reg in order - to enable the regulator output. enable-inverted: type: boolean description: | @@ -119,13 +93,3 @@ child-binding: description: | Number of current limit levels this regulator supports. If left as default, regulator current support will be disabled. - ilim-reg: - type: int - description: | - Register to write the register value given in current-levels into - to set the current limit - ilim-mask: - type: int - description: | - Mask to apply to the current-levels value before writing it to the - ilim-reg value to set the current limit diff --git a/include/zephyr/dt-bindings/regulator/pca9420_i2c.h b/include/zephyr/dt-bindings/regulator/pca9420_i2c.h index 17f54ff79dd6..d237fe3c2342 100644 --- a/include/zephyr/dt-bindings/regulator/pca9420_i2c.h +++ b/include/zephyr/dt-bindings/regulator/pca9420_i2c.h @@ -205,62 +205,19 @@ #define PCA9420_MODECFG3_PIN \ (PMIC_MODE(0xC, PMIC_MODE_FLAG_MODESEL_MULTI_REG, 0x40)) -/** Register memory map. See datasheet for more details. */ -/** General purpose registers */ -/** @brief Top level system ctrl 0 */ -#define PCA9420_TOP_CNTL0 0x09U /** @brief Top level system ctrl 3 */ #define PCA9420_TOP_CNTL3 0x0CU -/** Regulator status indication registers */ /** @brief Mode configuration for mode 0_0 */ #define PCA9420_MODECFG_0_0 0x22U -/** @brief Mode configuration for mode 0_1 */ -#define PCA9420_MODECFG_0_1 0x23U -/** @brief Mode configuration for mode 0_2 */ -#define PCA9420_MODECFG_0_2 0x24U -/** @brief Mode configuration for mode 0_3 */ -#define PCA9420_MODECFG_0_3 0x25U - -/** @brief VIN input current limit selection */ -#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_MASK 0xE0U -#define PCA9420_TOP_CNTL0_VIN_ILIM_SEL_SHIFT 0x05U /** @brief I2C Mode control mask */ #define PCA9420_TOP_CNTL3_MODE_I2C_MASK 0x18U -#define PCA9420_TOP_CNTL3_MODE_I2C_SHIFT 0x03U + /* * @brief Mode control selection mask. When this bit is set, the external * PMIC pins MODESEL0 and MODESEL1 can be used to select the active mode */ #define PCA9420_MODECFG_0_MODE_CTRL_SEL_MASK 0x40U -/** @brief Mode output voltage mask */ -#define PCA9420_MODECFG_0_SW1_OUT_MASK 0x3FU -/* - * @brief Mode configuration upon falling edge applied to ON pin. If set, - * the device will switch to mode 0 when a valid falling edge is applied. - * to the ON pin - */ -/** @brief SW2_OUT offset and voltage level mask */ -#define PCA9420_MODECFG_1_SW2_OUT_MASK 0x3FU -/** @brief LDO1_OUT voltage level mask */ -#define PCA9420_MODECFG_2_LDO1_OUT_MASK 0xF0U -#define PCA9420_MODECFG_2_LDO1_OUT_SHIFT 0x04U -/** @brief SW1 Enable */ -#define PCA9420_MODECFG_2_SW1_EN_MASK 0x08U -#define PCA9420_MODECFG_2_SW1_EN_VAL 0x08U -/** @brief SW2 Enable */ -#define PCA9420_MODECFG_2_SW2_EN_MASK 0x04U -#define PCA9420_MODECFG_2_SW2_EN_VAL 0x04U -/** @brief LDO1 Enable */ -#define PCA9420_MODECFG_2_LDO1_EN_MASK 0x02U -#define PCA9420_MODECFG_2_LDO1_EN_VAL 0x02U -/** @brief LDO2 Enable */ -#define PCA9420_MODECFG_2_LDO2_EN_MASK 0x01U -#define PCA9420_MODECFG_2_LDO2_EN_VAL 0x01U -/** @brief LDO2_OUT offset and voltage level mask */ -#define PCA9420_MODECFG_3_LDO2_OUT_MASK 0x3FU - - #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_PCA9420_I2C_H_*/