From 6c98f22770c0f1bcca87fa5a197bcf3ee7e428f7 Mon Sep 17 00:00:00 2001 From: Joan-Na-adi Date: Thu, 14 Aug 2025 11:52:35 +0900 Subject: [PATCH] only for test Signed-off-by: Joan-Na-adi --- .../bindings/regulator/maxim,max77675.yaml | 202 ++++ drivers/regulator/Kconfig | 7 + drivers/regulator/Makefile | 1 + drivers/regulator/max77675-regulator.c | 904 ++++++++++++++++++ drivers/regulator/max77675-regulator.h | 291 ++++++ .../regulator/maxim,max77675-regulator.h | 78 ++ 6 files changed, 1483 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/maxim,max77675.yaml create mode 100644 drivers/regulator/max77675-regulator.c create mode 100644 drivers/regulator/max77675-regulator.h create mode 100644 include/dt-bindings/regulator/maxim,max77675-regulator.h diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77675.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77675.yaml new file mode 100644 index 00000000000000..f93dfdc499bc40 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/maxim,max77675.yaml @@ -0,0 +1,202 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/maxim,max77675.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX77675 PMIC Regulator + +maintainers: + - Joan Na + +description: | + The MAX77675 is a PMIC providing multiple switching buck regulators + (SBB0–SBB3), accessible via I2C. Each SBB can be configured individually + in the Device Tree. Additional PMIC settings can be configured through + device-specific properties. + Users should use the macros from dt-bindings/regulator/maxim,max77675-regulator.h + +allOf: + - $ref: regulator.yaml# + +properties: + compatible: + const: maxim,max77675 + + reg: + maxItems: 1 + + maxim,dvs-slew-rate: + description: | + DVS slew rate setting. + 0 (MAX77675_DVS_SLEW_5MV) - 5 mV/μs + 1 (MAX77675_DVS_SLEW_10MV) - 10 mV/μs + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + + maxim,latency-mode: + description: | + Latency mode for voltage transition: + 0 (MAX77675_LAT_MODE_HIGH_LATENCY) - Low quiescent current, high latency (~100μs) + 1 (MAX77675_LAT_MODE_LOW_LATENCY) - High quiescent current, low latency (~10μs) + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + + maxim,drv-sbb-strength: + description: | + SIMO Buck-Boost Drive Strength Trim. + 0 (MAX77675_DRV_SBB_FASTEST) - Fastest transition (~0.6 ns) + 1 (MAX77675_DRV_SBB_FAST) - Faster transition (~1.2 ns) + 2 (MAX77675_DRV_SBB_MEDIUM) - Moderate transition (~1.8 ns) + 3 (MAX77675_DRV_SBB_SLOWEST) - Slowest transition (~8 ns) + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + maxim,manual-reset-time: + description: | + Manual reset time in seconds: + 0 (MAX77675_MRT_4S): 4 seconds + 1 (MAX77675_MRT_8S): 8 seconds + 2 (MAX77675_MRT_12S): 12 seconds + 3 (MAX77675_MRT_16S): 16 seconds + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + maxim,en-pullup-disable: + description: | + Disable internal pull-up for EN pin. + 0 (MAX77675_PU_EN): Internal pull-up enabled (default). + 1 (MAX77675_PU_DIS): Internal pull-up disabled. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + + maxim,bias-low-power-request: + description: | + Controls the bias low-power mode setting. + 0 (MAX77675_BIAS_NORMAL): Normal bias operation + 1 (MAX77675_BIAS_LPM_REQ): Request low-power bias mode + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + + maxim,simo-int-ldo-always-on: + description: | + SIMO internal channel disable configuration. + 0 (MAX77675_SIMO_INT_NORMAL): SIMO channel enabled + 1 (MAX77675_SIMO_INT_LDO): SIMO channel disabled + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + + maxim,en-mode: + description: | + Enable mode configuration. + 0 (MAX77675_EN_PUSH_BUTTON): Push button + 1 (MAX77675_EN_SLIDE_SWITCH): Slide switch + 2 (MAX77675_EN_LOGIC): Logic mode + 3 (MAX77675_EN_RESERVED): Reserved + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + + maxim,en-debounce-time: + description: | + Debounce timer enable. + 0 (MAX77675_DBEN_100US): 100us + 1 (MAX77675_DBEN_30MS): 30ms + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + + regulators: + type: object + description: Regulator child nodes + patternProperties: + "^sbb[0-3]$": + type: object + $ref: regulator.yaml# + properties: + maxim,fps-slot: + description: | + FPS slot selection. + 0 (MAX77675_FPS_SLOT_0): FPS Slot 0 + 1 (MAX77675_FPS_SLOT_1): FPS Slot 1 + 2 (MAX77675_FPS_SLOT_2): FPS Slot 2 + 3 (MAX77675_FPS_SLOT_3): FPS Slot 3 + 4 (MAX77675_FPS_NONE): No FPS Slot (disabled) + 5 (MAX77675_FPS_DEF): Use the defaul + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3, 4, 5] + + maxim,slew-rate-use-dvs: + description: | + 0 (MAX77675_SR_2MV_PER_US): Fixed slew rate of 2mV/μs. + 1 (MAX77675_SR_USE_DVS): Uses maxim,dvs-slew-rate for dynamic voltage scaling. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + additionalProperties: false + +required: + - compatible + - reg + - regulators + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + max77675: pmic@44 { + compatible = "maxim,max77675"; + reg = <0x44>; + + maxim,dvs-slew-rate = ; + maxim,latency-mode = ; + maxim,drv-sbb-strength = ; + maxim,manual-reset-time = ; + maxim,en-pullup-disable = ; + maxim,bias-low-power-request = ; + maxim,simo-int-ldo-always-on = ; + maxim,en-mode = ; + maxim,en-debounce-time = ; + + regulators { + sbb0: sbb0 { + regulator-name = "sbb0"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <5500000>; + maxim,fps-slot = ; + maxim,slew-rate-use-dvs = ; + }; + + sbb1: sbb1 { + regulator-name = "sbb1"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <5500000>; + regulator-allow-set-voltage; + maxim,fps-slot = ; + maxim,slew-rate-use-dvs = ; + }; + + sbb2: sbb2 { + regulator-name = "sbb2"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <5500000>; + regulator-allow-set-voltage; + maxim,fps-slot = ; + maxim,slew-rate-use-dvs = ; + }; + + sbb3: sbb3 { + regulator-name = "sbb3"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <5500000>; + regulator-allow-set-voltage; + maxim,fps-slot = ; + maxim,slew-rate-use-dvs = ; + }; + }; + }; + }; + diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4c08cf755d88e5..6e51e40edd9163 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -641,6 +641,13 @@ config REGULATOR_MAX77650 Semiconductor. This device has a SIMO with three independent power rails and an LDO. +config REGULATOR_MAX77675 + tristate "MAX77675 regulator driver" + depends on I2C + select REGMAP_I2C + help + Regulator driver for Maxim MAX77675. + config REGULATOR_MAX77857 tristate "ADI MAX77857/MAX77831 regulator support" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 71f45d9317d24e..537487d789cb41 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_REGULATOR_MAX77503) += max77503-regulator.o obj-$(CONFIG_REGULATOR_MAX77541) += max77541-regulator.o obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o +obj-$(CONFIG_REGULATOR_MAX77675) += max77675-regulator.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o obj-$(CONFIG_REGULATOR_MAX8893) += max8893.o diff --git a/drivers/regulator/max77675-regulator.c b/drivers/regulator/max77675-regulator.c new file mode 100644 index 00000000000000..44332215d03f7d --- /dev/null +++ b/drivers/regulator/max77675-regulator.c @@ -0,0 +1,904 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 Analog Devices, Inc. + * ADI regulator driver for MAX77675. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "max77675-regulator.h" + +struct max77675_regulator_pdata { + u8 fps_slot; + u8 dvs_slew_rate; +}; + +struct max77675_config { + u8 drv_slew_rate; + u8 latency_mode; + u8 drv_sbb_strength; + u8 manual_reset_time; + u8 en_pullup_disable; + u8 bias_low_power_request; + u8 simo_int_ldo_always_on; + u8 en_mode; + u8 en_debounce_time; +}; + +struct max77675_regulator { + struct device *dev; // Device pointer for logging and PM + struct regmap *regmap; // Regmap for register access + struct max77675_config config; + struct max77675_regulator_pdata pdata[MAX77675_NUM_REGULATORS]; +}; + +static int max77675_regulator_enable(struct regulator_dev *rdev) +{ + struct max77675_regulator *maxreg = rdev_get_drvdata(rdev); + const struct regulator_desc *desc = rdev->desc; + unsigned int val; + int ret; + + dev_info(maxreg->dev, "Enable called for regulator: %s (reg=0x%02x, mask=0x%02x)\n", + desc->name, desc->enable_reg, desc->enable_mask); + + ret = regmap_read(maxreg->regmap, desc->enable_reg, &val); + if (ret) { + dev_err(maxreg->dev, "Failed to read enable_reg (0x%02x): %d\n", + desc->enable_reg, ret); + return ret; + } + + dev_info(maxreg->dev, "Original enable_reg value: 0x%02x\n", val); + + val &= ~desc->enable_mask; + val |= desc->enable_val; + + dev_info(maxreg->dev, "Modified enable_reg value: 0x%02x\n", val); + + ret = regmap_write(maxreg->regmap, desc->enable_reg, val); + if (ret) + dev_err(maxreg->dev, "Failed to write enable_reg (0x%02x): %d\n", + desc->enable_reg, ret); + else + dev_info(maxreg->dev, "Successfully enabled regulator: %s\n", desc->name); + + return ret; +} + +/** + * Disable the regulator by setting enable bits to OFF (0b000). + */ +static int max77675_regulator_disable(struct regulator_dev *rdev) +{ + struct max77675_regulator *maxreg = rdev_get_drvdata(rdev); + const struct regulator_desc *desc = rdev->desc; + unsigned int val; + int ret; + + ret = regmap_read(maxreg->regmap, desc->enable_reg, &val); + if (ret) + return ret; + + val &= ~desc->enable_mask; + val |= desc->disable_val; + + return regmap_write(maxreg->regmap, desc->enable_reg, val); +} + +/** + * Check if the regulator is enabled by reading enable bits. + * + * Return: 1 if enabled, 0 if disabled, negative error code on failure. + */ +static int max77675_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct max77675_regulator *maxreg = rdev_get_drvdata(rdev); + const struct regulator_desc *desc = rdev->desc; + unsigned int val; + int ret; + unsigned int enable_bits; + + ret = regmap_read(maxreg->regmap, desc->enable_reg, &val); + if (ret) + return ret; + + enable_bits = (val & desc->enable_mask) >> __ffs(desc->enable_mask); + + return (enable_bits == MAX77675_ENABLE_ON) ? 1 : 0; +} + +/** + * List the voltage for a given selector. + * + * This function calculates the voltage in microvolts (uV) corresponding to the given + * selector value using the step size (uV_step) and minimum voltage (min_uV) from + * the regulator's descriptor. + * + * @param rdev Pointer to the regulator device structure. + * @param selector The selector value representing a specific voltage step. + * + * @return The calculated voltage in microvolts (uV). + */ +static int max77675_list_voltage(struct regulator_dev *rdev, unsigned int selector) +{ + unsigned int voltage; + + // Use uV_step from regulator_desc + unsigned int uV_step = rdev->desc->uV_step; + + // Calculate the voltage in microvolts based on the selector value + voltage = selector * uV_step + rdev->desc->min_uV; + + return voltage; +} + +/** + * Set latency mode. + * + * @param maxreg Pointer to max77675 device structure. + * @param enable true to enable latency mode, false to disable. + */ +static int max77675_set_latency_mode(struct max77675_regulator *maxreg, bool enable) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_SBB_TOP_B, + MAX77675_LAT_MODE_BIT, + FIELD_PREP(MAX77675_LAT_MODE_BIT, enable)); +} + +/** + * Set DVS slew rate mode. + * + * @param maxreg Pointer to max77675 device structure. + * @param enable true to use DVS-controlled slew rate, false for fixed 2mV/us. + */ +static int max77675_set_dvs_slew_rate(struct max77675_regulator *maxreg, bool enable) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_SBB_TOP_B, + MAX77675_DVS_SLEW_BIT, + FIELD_PREP(MAX77675_DVS_SLEW_BIT, enable)); +} + +/** + * Set drive strength. + * + * @param maxreg Pointer to max77675 device structure. + * @param strength 2-bit drive strength value (0-3). + * + * @return 0 on success, negative error code on failure. + */ +static int max77675_set_drv_sbb_strength(struct max77675_regulator *maxreg, u8 strength) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_SBB_TOP_A, + MAX77675_DRV_SBB_MASK, + FIELD_PREP(MAX77675_DRV_SBB_MASK, strength)); +} + +/** + * Set manual reset time (MRT) for EN pin. + * + * @param maxreg Pointer to max77675 device structure. + * @param mrt 2-bit value (0x0: 4s, 0x1: 8s, 0x2: 12s, 0x3: 16s) + */ +static int max77675_set_manual_reset_time(struct max77675_regulator *maxreg, u8 mrt) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_GLBL_A, + MAX77675_MRT_MASK, + FIELD_PREP(MAX77675_MRT_MASK, mrt)); +} + +/** + * Enable or disable internal pull-up resistor on EN pin. + * + * @param maxreg Pointer to max77675 device structure. + * @param disable true to disable pull-up, false to enable + */ +static int max77675_set_en_pullup_disable(struct max77675_regulator *maxreg, bool disable) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_GLBL_A, + MAX77675_PU_DIS_BIT, + FIELD_PREP(MAX77675_PU_DIS_BIT, disable)); +} + +/** + * Request main bias to enter low-power mode. + * + * @param maxreg Pointer to max77675 device structure. + * @param enable true to request low-power mode, false for normal + */ +static int max77675_set_bias_low_power_request(struct max77675_regulator *maxreg, bool enable) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_GLBL_A, + MAX77675_BIAS_LPM_BIT, + FIELD_PREP(MAX77675_BIAS_LPM_BIT, enable)); +} + +/** + * Force SIMO internal LDO to always supply 1.8V. + * + * @param maxreg Pointer to max77675 device structure. + * @param enable true to always supply 1.8V, false for normal operation + */ +static int max77675_set_simo_int_ldo_always_on(struct max77675_regulator *maxreg, bool enable) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_GLBL_A, + MAX77675_SIMO_CH_DIS_BIT, + FIELD_PREP(MAX77675_SIMO_CH_DIS_BIT, enable)); +} + +/** + * Set EN pin mode. + * + * @param maxreg Pointer to max77675 device structure. + * @param mode 2-bit value: 0x0 (push-button), 0x1 (slide-switch), 0x2 (logic) + */ +static int max77675_set_en_mode(struct max77675_regulator *maxreg, u8 mode) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_GLBL_A, + MAX77675_EN_MODE_MASK, + FIELD_PREP(MAX77675_EN_MODE_MASK, mode)); +} + +/** + * Set debounce time for EN pin. + * + * @param maxreg Pointer to max77675 device structure. + * @param debounce_30ms true for 30ms, false for 100us + */ +static int max77675_set_en_debounce_time(struct max77675_regulator *maxreg, bool debounce_30ms) +{ + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_GLBL_A, + MAX77675_DBEN_EN_BIT, + FIELD_PREP(MAX77675_DBEN_EN_BIT, debounce_30ms)); +} + +static int max77675_regulator_get_fps_src(struct max77675_regulator *maxreg, int id) +{ + unsigned int reg_addr; + unsigned int val; + int ret; + + switch (id) { + case 0: + reg_addr = MAX77675_REG_CNFG_SBB0_B; + break; + case 1: + reg_addr = MAX77675_REG_CNFG_SBB1_B; + break; + case 2: + reg_addr = MAX77675_REG_CNFG_SBB2_B; + break; + case 3: + reg_addr = MAX77675_REG_CNFG_SBB3_B; + break; + default: + dev_err(maxreg->dev, "Invalid regulator id: %d\n", id); + return -EINVAL; + } + + ret = regmap_read(maxreg->regmap, reg_addr, &val); + if (ret < 0) { + dev_err(maxreg->dev, "Failed to read FPS source (reg 0x%02x): %d\n", + reg_addr, ret); + return ret; + } + + return val & MAX77675_EN_SBB_MASK; +} + +static int max77675_regulator_set_fps_src(struct max77675_regulator *maxreg, int id, u8 fps_src) +{ + unsigned int reg_addr; + int ret; + + switch (id) { + case 0: + reg_addr = MAX77675_REG_CNFG_SBB0_B; + break; + case 1: + reg_addr = MAX77675_REG_CNFG_SBB1_B; + break; + case 2: + reg_addr = MAX77675_REG_CNFG_SBB2_B; + break; + case 3: + reg_addr = MAX77675_REG_CNFG_SBB3_B; + break; + default: + dev_err(maxreg->dev, "Invalid regulator id: %d\n", id); + return -EINVAL; + } + + ret = regmap_update_bits(maxreg->regmap, reg_addr, + MAX77675_EN_SBB_MASK, fps_src); + if (ret < 0) { + dev_err(maxreg->dev, "Failed to set FPS source (reg 0x%02x): %d\n", + reg_addr, ret); + return ret; + } + + return 0; +} + +/** + * max77675_set_sbb_slew_rate - Set the slew rate for a specific SBB regulator channel + * + * @maxreg: Pointer to the max77675 regulator structure + * @id: Regulator channel ID (ID_SBB0 ~ ID_SBB3) + * @val: Slew rate value (0 = 2mV/us, 1 = use DVS_SLEW) + * + * This function configures the slew rate control source for the specified SBB channel by + * updating the corresponding bits in the CNFG_SBB_TOP_B register. + * + * Return: 0 on success, negative error code on failure (e.g., invalid channel ID). + */ +static int max77675_set_sbb_slew_rate(struct max77675_regulator *maxreg, int id, u8 val) +{ + u8 mask, value; + + switch (id) { + case ID_SBB0: + mask = MAX77675_SR_SBB0_BIT; + value = FIELD_PREP(MAX77675_SR_SBB0_BIT, val); + break; + + case ID_SBB1: + mask = MAX77675_SR_SBB1_BIT; + value = FIELD_PREP(MAX77675_SR_SBB1_BIT, val); + break; + + case ID_SBB2: + mask = MAX77675_SR_SBB2_BIT; + value = FIELD_PREP(MAX77675_SR_SBB2_BIT, val); + break; + + case ID_SBB3: + mask = MAX77675_SR_SBB3_BIT; + value = FIELD_PREP(MAX77675_SR_SBB3_BIT, val); + break; + default: + return -EINVAL; + } + + return regmap_update_bits(maxreg->regmap, MAX77675_REG_CNFG_SBB_TOP_B, mask, val); +} + +static int max77675_init_regulator(struct max77675_regulator *maxreg, int id) +{ + struct max77675_regulator_pdata *rpdata = &maxreg->pdata[id]; + int ret; + + if (rpdata->fps_slot == MAX77675_FPS_DEF) { + ret = max77675_regulator_get_fps_src(maxreg, id); + if (ret < 0) { + dev_err(maxreg->dev, "Failed to read FPS source for ID %d\n", id); + return ret; + } + rpdata->fps_slot = ret; + } + + ret = max77675_regulator_set_fps_src(maxreg, id, rpdata->fps_slot); + if (ret) + dev_warn(maxreg->dev, "Failed to set FPS source for ID %d\n", id); + + ret = max77675_set_sbb_slew_rate(maxreg, id, rpdata->dvs_slew_rate); + if (ret) + dev_warn(maxreg->dev, "Failed to set slew rate for ID %d\n", id); + + dev_dbg(maxreg->dev, "Regulator ID %d: FPS slot = %u, slew rate = %u\n", + id, rpdata->fps_slot, rpdata->dvs_slew_rate); + + return 0; +} + +static int max77675_of_parse_cb(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *config) +{ + struct max77675_regulator *maxreg = config->driver_data; + struct max77675_regulator_pdata *rpdata = &maxreg->pdata[desc->id]; + u32 pval; + int ret; + + /* Parse FPS slot from DT */ + ret = of_property_read_u32(np, "maxim,fps-slot", &pval); + rpdata->fps_slot = (!ret) ? (u8)pval : MAX77675_FPS_DEF; + + /* Parse slew rate control source */ + ret = of_property_read_u32(np, "maxim,slew-rate-use-drv", &pval); + rpdata->dvs_slew_rate = (!ret) ? (u8)pval : 0; + + dev_dbg(maxreg->dev, "Regulator %s: parsed fps_slot=%u, dvs_slew_rate=%u\n", + desc->name, rpdata->fps_slot, rpdata->dvs_slew_rate); + + /* Apply parsed configuration */ + return max77675_init_regulator(maxreg, desc->id); +} + +static int max77675_get_error_flags(struct regulator_dev *rdev, unsigned int *flags) +{ + struct max77675_regulator *maxreg = rdev_get_drvdata(rdev); + unsigned int int_flags; + int id = rdev_get_id(rdev); + int ret; + + ret = regmap_read(maxreg->regmap, MAX77675_REG_INT_GLBL, &int_flags); + if (ret) { + dev_err(maxreg->dev, "Failed to read INT_GLBL: %d\n", ret); + return ret; + } + + *flags = 0; + + switch (id) { + case 0: + if (!(int_flags & MAX77675_INT_SBB0_F_BIT)) + *flags |= REGULATOR_ERROR_FAIL; + break; + case 1: + if (!(int_flags & MAX77675_INT_SBB1_F_BIT)) + *flags |= REGULATOR_ERROR_FAIL; + break; + case 2: + if (!(int_flags & MAX77675_INT_SBB2_F_BIT)) + *flags |= REGULATOR_ERROR_FAIL; + break; + case 3: + if (!(int_flags & MAX77675_INT_SBB3_F_BIT)) + *flags |= REGULATOR_ERROR_FAIL; + break; + default: + dev_warn(maxreg->dev, "Unsupported regulator ID: %d\n", id); + break; + } + + if (!(int_flags & MAX77675_INT_TJAL1_R_BIT) || !(int_flags & MAX77675_INT_TJAL2_R_BIT)) + *flags |= REGULATOR_ERROR_OVER_TEMP; + + dev_dbg(maxreg->dev, "%s: flags = 0x%x\n", __func__, *flags); + + return 0; +} + +static const struct regulator_ops max77675_regulator_ops = { + .list_voltage = max77675_list_voltage, + .enable = max77675_regulator_enable, + .disable = max77675_regulator_disable, + .is_enabled = max77675_regulator_is_enabled, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, + .get_error_flags = max77675_get_error_flags, +}; + +static struct regulator_desc max77675_regulators[MAX77675_NUM_REGULATORS] = { + { + .name = "sbb0", + .of_match = of_match_ptr("sbb0"), + .regulators_node = of_match_ptr("regulators"), + .of_parse_cb = max77675_of_parse_cb, + .id = ID_SBB0, + .ops = &max77675_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = MAX77675_NUM_LEVELS_25MV, + .min_uV = MAX77675_MIN_UV, + .uV_step = MAX77675_STEP_25MV, + .vsel_reg = MAX77675_REG_CNFG_SBB0_A, + .vsel_mask = MAX77675_TV_SBB0_MASK, + .enable_reg = MAX77675_REG_CNFG_SBB0_B, + .enable_mask = MAX77675_EN_SBB0_MASK, + .enable_val = MAX77675_ENABLE_ON, + .disable_val = MAX77675_ENABLE_OFF, + .active_discharge_off = MAX77675_REGULATOR_AD_OFF, + .active_discharge_on = MAX77675_REGULATOR_AD_ON, + .active_discharge_mask = MAX77675_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77675_REG_CNFG_SBB0_B, + }, + { + .name = "sbb1", + .of_match = of_match_ptr("sbb1"), + .regulators_node = of_match_ptr("regulators"), + .of_parse_cb = max77675_of_parse_cb, + .id = ID_SBB1, + .ops = &max77675_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = MAX77675_NUM_LEVELS_25MV, + .min_uV = MAX77675_MIN_UV, + .uV_step = MAX77675_STEP_25MV, + .vsel_reg = MAX77675_REG_CNFG_SBB1_A, + .vsel_mask = MAX77675_TV_SBB1_MASK, + .enable_reg = MAX77675_REG_CNFG_SBB1_B, + .enable_mask = MAX77675_EN_SBB1_MASK, + .enable_val = MAX77675_ENABLE_ON, + .disable_val = MAX77675_ENABLE_OFF, + .active_discharge_off = MAX77675_REGULATOR_AD_OFF, + .active_discharge_on = MAX77675_REGULATOR_AD_ON, + .active_discharge_mask = MAX77675_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77675_REG_CNFG_SBB1_B, + }, + { + .name = "sbb2", + .of_match = of_match_ptr("sbb2"), + .regulators_node = of_match_ptr("regulators"), + .of_parse_cb = max77675_of_parse_cb, + .id = ID_SBB2, + .ops = &max77675_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = MAX77675_NUM_LEVELS_25MV, + .min_uV = MAX77675_MIN_UV, + .uV_step = MAX77675_STEP_25MV, + .vsel_reg = MAX77675_REG_CNFG_SBB2_A, + .vsel_mask = MAX77675_TV_SBB2_MASK, + .enable_reg = MAX77675_REG_CNFG_SBB2_B, + .enable_mask = MAX77675_EN_SBB2_MASK, + .enable_val = MAX77675_ENABLE_ON, + .disable_val = MAX77675_ENABLE_OFF, + .active_discharge_off = MAX77675_REGULATOR_AD_OFF, + .active_discharge_on = MAX77675_REGULATOR_AD_ON, + .active_discharge_mask = MAX77675_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77675_REG_CNFG_SBB2_B, + }, + { + .name = "sbb3", + .of_match = of_match_ptr("sbb3"), + .regulators_node = of_match_ptr("regulators"), + .of_parse_cb = max77675_of_parse_cb, + .id = ID_SBB3, + .ops = &max77675_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = MAX77675_NUM_LEVELS_25MV, + .min_uV = MAX77675_MIN_UV, + .uV_step = MAX77675_STEP_25MV, + .vsel_reg = MAX77675_REG_CNFG_SBB3_A, + .vsel_mask = MAX77675_TV_SBB3_MASK, + .enable_reg = MAX77675_REG_CNFG_SBB3_B, + .enable_mask = MAX77675_EN_SBB3_MASK, + .enable_val = MAX77675_ENABLE_ON, + .disable_val = MAX77675_ENABLE_OFF, + .active_discharge_off = MAX77675_REGULATOR_AD_OFF, + .active_discharge_on = MAX77675_REGULATOR_AD_ON, + .active_discharge_mask = MAX77675_REGULATOR_AD_MASK, + .active_discharge_reg = MAX77675_REG_CNFG_SBB3_B, + }, +}; + +static const struct regmap_config max77675_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX77675_MAX_REGISTER, + .cache_type = REGCACHE_RBTREE, +}; + +static int max77675_apply_config(struct max77675_regulator *maxreg, + const struct max77675_config *config) +{ + int ret; + + ret = max77675_set_dvs_slew_rate(maxreg, config->drv_slew_rate); + if (ret) { + dev_err(maxreg->dev, "Failed to set DVS slew rate: %d\n", ret); + return ret; + } + + ret = max77675_set_latency_mode(maxreg, config->latency_mode); + if (ret) { + dev_err(maxreg->dev, "Failed to set latency mode: %d\n", ret); + return ret; + } + + ret = max77675_set_drv_sbb_strength(maxreg, config->drv_sbb_strength); + if (ret) { + dev_err(maxreg->dev, "Failed to set drive strength: %d\n", ret); + return ret; + } + + ret = max77675_set_manual_reset_time(maxreg, config->manual_reset_time); + if (ret) { + dev_err(maxreg->dev, "Failed to set manual reset time: %d\n", ret); + return ret; + } + + ret = max77675_set_en_pullup_disable(maxreg, config->en_pullup_disable); + if (ret) { + dev_err(maxreg->dev, "Failed to set EN pull-up disable: %d\n", ret); + return ret; + } + + ret = max77675_set_bias_low_power_request(maxreg, config->bias_low_power_request); + if (ret) { + dev_err(maxreg->dev, "Failed to set bias low-power request: %d\n", ret); + return ret; + } + + ret = max77675_set_simo_int_ldo_always_on(maxreg, config->simo_int_ldo_always_on); + if (ret) { + dev_err(maxreg->dev, "Failed to set SIMO internal LDO always-on: %d\n", ret); + return ret; + } + + ret = max77675_set_en_mode(maxreg, config->en_mode); + if (ret) { + dev_err(maxreg->dev, "Failed to set EN mode: %d\n", ret); + return ret; + } + + ret = max77675_set_en_debounce_time(maxreg, config->en_debounce_time); + if (ret) { + dev_err(maxreg->dev, "Failed to set EN debounce time: %d\n", ret); + return ret; + } + + return 0; +} + +static int max77675_parse_config(struct device_node *np, struct max77675_config *config) +{ + int ret; + u32 val; + + /* drv slew rate */ + ret = of_property_read_u32(np, "maxim,dvs-slew-rate", &val); + if (ret < 0) + val = 0; + config->drv_slew_rate = val ? 1 : 0; + + /* latency mode */ + ret = of_property_read_u32(np, "maxim,latency-mode", &val); + if (ret < 0) + val = 0; + config->latency_mode = val ? 1 : 0; + + /* drive strength */ + ret = of_property_read_u32(np, "maxim,drv-sbb-strength", &val); + if (ret < 0) + val = 0; + config->drv_sbb_strength = val & 0x3; + + /* Manual reset time for EN pin */ + ret = of_property_read_u32(np, "maxim,manual-reset-time", &val); + if (ret < 0) + val = 0; + config->manual_reset_time = val & 0x3; + + /* Disable internal pull-up resistor on EN pin */ + ret = of_property_read_u32(np, "maxim,en-pullup-disable", &val); + if (ret < 0) + val = 0; + config->en_pullup_disable = val ? 1 : 0; + + /* Request low-power mode for main bias */ + ret = of_property_read_u32(np, "maxim,bias-low-power-request", &val); + if (ret < 0) + val = 0; + config->bias_low_power_request = val ? 1 : 0; + + /* Force internal LDO to always supply 1.8V */ + ret = of_property_read_u32(np, "maxim,simo-int-ldo-always-on", &val); + if (ret < 0) + val = 0; + config->simo_int_ldo_always_on = val ? 1 : 0; + + /* EN pin mode: push-button, slide-switch, or logic */ + ret = of_property_read_u32(np, "maxim,en-mode", &val); + if (ret < 0) + val = 0; + config->en_mode = val & 0x3; + + /* Debounce time for EN pin */ + ret = of_property_read_u32(np, "maxim,en-debounce-time", &val); + if (ret < 0) + val = 0; + config->en_debounce_time = val ? 1 : 0; + + /* Debug print all parsed values */ + pr_info("MAX77675 config parsed:\n" + " dvs_slew_rate: %u\n" + " latency_mode: %u\n" + " drv_sbb_strength: %u\n" + " manual_reset_time: %u\n" + " en_pullup_disable: %u\n" + " bias_low_power_request: %u\n" + " simo_int_ldo_always_on: %u\n" + " en_mode: %u\n" + " en_debounce_time: %u\n", + config->drv_slew_rate, + config->latency_mode, + config->drv_sbb_strength, + config->manual_reset_time, + config->en_pullup_disable, + config->bias_low_power_request, + config->simo_int_ldo_always_on, + config->en_mode, + config->en_debounce_time); + + return 0; +} + +static int max77675_init_event(struct max77675_regulator *maxreg) +{ + unsigned int ercflag, int_glbl; + int ret; + + ret = regmap_read(maxreg->regmap, MAX77675_REG_ERCF_GLBL, &ercflag); + if (ret) { + dev_err(maxreg->dev, "Failed to read CID register: %d\n", ret); + return ret; + } + + ret = regmap_read(maxreg->regmap, MAX77675_REG_INT_GLBL, &int_glbl); + if (ret) { + dev_err(maxreg->dev, "Failed to read INT_GLBL register: %d\n", ret); + return ret; + } + + if (ercflag & MAX77675_SFT_CRST_F_BIT) + dev_info(maxreg->dev, "Software Cold Reset Flag is set\n"); + + if (ercflag & MAX77675_SFT_OFF_F_BIT) + dev_info(maxreg->dev, "Software Off Flag is set\n"); + + if (ercflag & MAX77675_MRST_BIT) + dev_info(maxreg->dev, "Manual Reset Timer Flag is set\n"); + + if (ercflag & MAX77675_UVLO_BIT) + dev_info(maxreg->dev, "Undervoltage Lockout Flag is set\n"); + + if (ercflag & MAX77675_OVLO_BIT) + dev_info(maxreg->dev, "Overvoltage Lockout Flag is set\n"); + + if (ercflag & MAX77675_TOVLD_BIT) + dev_info(maxreg->dev, "Thermal Overload Flag is set\n"); + + if (int_glbl & MAX77675_INT_SBB3_F_BIT) + dev_info(maxreg->dev, "SBB3 Channel Fault Interrupt occurred\n"); + + if (int_glbl & MAX77675_INT_SBB2_F_BIT) + dev_info(maxreg->dev, "SBB2 Channel Fault Interrupt occurred\n"); + + if (int_glbl & MAX77675_INT_SBB1_F_BIT) + dev_info(maxreg->dev, "SBB1 Channel Fault Interrupt occurred\n"); + + if (int_glbl & MAX77675_INT_SBB0_F_BIT) + dev_info(maxreg->dev, "SBB0 Channel Fault Interrupt occurred\n"); + + if (int_glbl & MAX77675_INT_TJAL2_R_BIT) + dev_info(maxreg->dev, "Thermal Alarm 2 Rising Interrupt occurred\n"); + + if (int_glbl & MAX77675_INT_TJAL1_R_BIT) + dev_info(maxreg->dev, "Thermal Alarm 1 Rising Interrupt occurred\n"); + + if (int_glbl & MAX77675_INT_EN_R_BIT) + dev_info(maxreg->dev, "nEN Rising Edge Interrupt occurred\n"); + + if (int_glbl & MAX77675_INT_EN_F_BIT) + dev_info(maxreg->dev, "nEN Falling Edge Interrupt occurred\n"); + + return 0; +} + +static int max77675_regulator_probe(struct i2c_client *client) +{ + struct max77675_regulator *maxreg; + struct regulator_config config = {}; + struct device_node *regulators_np; + int i, ret; + + maxreg = devm_kzalloc(&client->dev, sizeof(*maxreg), GFP_KERNEL); + if (!maxreg) + return -ENOMEM; + + maxreg->dev = &client->dev; + + maxreg->regmap = devm_regmap_init_i2c(client, &max77675_regmap_config); + if (IS_ERR(maxreg->regmap)) { + dev_err(maxreg->dev, "Failed to init regmap\n"); + return PTR_ERR(maxreg->regmap); + } + + ret = max77675_init_event(maxreg); + if (ret) { + dev_err(maxreg->dev, "Failed to init event flag for regulator\n"); + return ret; + } + + // global config parsing + ret = max77675_parse_config(client->dev.of_node, &maxreg->config); + if (ret) + dev_warn(maxreg->dev, "Failed to parse global config, using defaults\n"); + + ret = max77675_apply_config(maxreg, &maxreg->config); + if (ret) + dev_warn(maxreg->dev, "Failed to apply config: %d\n", ret); + + config.dev = &client->dev; + config.regmap = maxreg->regmap; + config.driver_data = maxreg; + + regulators_np = of_get_child_by_name(client->dev.of_node, "regulators"); + if (!regulators_np) { + dev_err(maxreg->dev, "No 'regulators' subnode found in DT\n"); + return -EINVAL; + } + + for (i = 0; i < MAX77675_NUM_REGULATORS; i++) { + const struct regulator_desc *desc = &max77675_regulators[i]; + struct regulator_dev *rdev; + struct device_node *child_np; + + child_np = of_get_child_by_name(regulators_np, desc->name); + if (!child_np) { + dev_warn(maxreg->dev, "No DT node for regulator %s\n", desc->name); + continue; + } + + config.of_node = child_np; + + rdev = devm_regulator_register(&client->dev, desc, &config); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(maxreg->dev, + "Failed to register regulator %d (%s): %d\n", + i, desc->name, ret); + of_node_put(child_np); + return ret; + } + of_node_put(child_np); + } + + i2c_set_clientdata(client, maxreg); + + dev_info(&client->dev, "MAX77675 regulators registered\n"); + return 0; +} + +static void max77675_regulator_remove(struct i2c_client *client) +{ + struct max77675_regulator *maxreg = i2c_get_clientdata(client); + + dev_info(maxreg->dev, "MAX77675 regulators removed\n"); +} + +static const struct i2c_device_id max77675_i2c_id[] = { + { "max77675", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max77675_i2c_id); + +#ifdef CONFIG_OF +static const struct of_device_id max77675_of_match[] = { + { .compatible = "maxim,max77675", }, + { } +}; +MODULE_DEVICE_TABLE(of, max77675_of_match); +#endif + +static struct i2c_driver max77675_regulator_driver = { + .driver = { + .name = "max77675", + .of_match_table = of_match_ptr(max77675_of_match), + }, + .probe = max77675_regulator_probe, + .remove = max77675_regulator_remove, + .id_table = max77675_i2c_id, +}; + +module_i2c_driver(max77675_regulator_driver); + +MODULE_DESCRIPTION("MAX77675 Regulator Driver"); +MODULE_AUTHOR("Joan Na "); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max77675-regulator.h b/drivers/regulator/max77675-regulator.h new file mode 100644 index 00000000000000..eaef281ddfdcf3 --- /dev/null +++ b/drivers/regulator/max77675-regulator.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * MAX77675 Register Definitions + * Reference: MAX77675 Datasheet + */ + +#ifndef __MAX77675_REG_H__ +#define __MAX77675_REG_H__ + +#include + +/* Register Addresses */ +#define MAX77675_REG_CNFG_GLBL_A 0x00 +#define MAX77675_REG_CNFG_GLBL_B 0x01 +#define MAX77675_REG_INT_GLBL 0x02 +#define MAX77675_REG_INTM_GLBL 0x03 +#define MAX77675_REG_STAT_GLBL 0x04 +#define MAX77675_REG_ERCF_GLBL 0x05 +#define MAX77675_REG_CID 0x06 +#define MAX77675_REG_CNFG_SBB_TOP_A 0x07 +#define MAX77675_REG_CNFG_SBB0_A 0x08 +#define MAX77675_REG_CNFG_SBB0_B 0x09 +#define MAX77675_REG_CNFG_SBB1_A 0x0A +#define MAX77675_REG_CNFG_SBB1_B 0x0B +#define MAX77675_REG_CNFG_SBB2_A 0x0C +#define MAX77675_REG_CNFG_SBB2_B 0x0D +#define MAX77675_REG_CNFG_SBB3_A 0x0E +#define MAX77675_REG_CNFG_SBB3_B 0x0F +#define MAX77675_REG_CNFG_SBB_TOP_B 0x10 + +/* CNFG_GLBL_A (0x00) bit masks and shifts */ +#define MAX77675_MRT_MASK GENMASK(7, 6) /* Manual Reset Time (bits 7:6) */ +#define MAX77675_MRT_SHIFT 6 +#define MAX77675_PU_DIS_BIT BIT(5) /* Pullup Disable (bit 5) */ +#define MAX77675_PU_DIS_SHIFT 5 +#define MAX77675_BIAS_LPM_BIT BIT(4) /* Bias Low Power Mode (bit 4) */ +#define MAX77675_BIAS_LPM_SHIFT 4 +#define MAX77675_SIMO_CH_DIS_BIT BIT(3) /* SIMO Internal Channel Disable (bit 3) */ +#define MAX77675_SIMO_CH_DIS_SHIFT 3 +#define MAX77675_EN_MODE_MASK GENMASK(2, 1) /* nEN Mode (bits 2:1) */ +#define MAX77675_EN_MODE_SHIFT 1 +#define MAX77675_DBEN_EN_BIT BIT(0) /* Debounce Enable (bit 0) */ +#define MAX77675_DBEN_EN_SHIFT 0 + +/* CNFG_GLBL_B (0x01) */ +#define MAX77675_SFT_CTRL_MASK GENMASK(2, 0) /* Soft Start Control */ +#define MAX77675_SFT_CTRL_SHIFT 0 + +/* INT_GLBL (0x02) bit bits and shifts */ +#define MAX77675_INT_SBB3_F_BIT BIT(7) +#define MAX77675_INT_SBB3_F_SHIFT 7 +#define MAX77675_INT_SBB2_F_BIT BIT(6) +#define MAX77675_INT_SBB2_F_SHIFT 6 +#define MAX77675_INT_SBB1_F_BIT BIT(5) +#define MAX77675_INT_SBB1_F_SHIFT 5 +#define MAX77675_INT_SBB0_F_BIT BIT(4) +#define MAX77675_INT_SBB0_F_SHIFT 4 +#define MAX77675_INT_TJAL2_R_BIT BIT(3) +#define MAX77675_INT_TJAL2_R_SHIFT 3 +#define MAX77675_INT_TJAL1_R_BIT BIT(2) +#define MAX77675_INT_TJAL1_R_SHIFT 2 +#define MAX77675_INT_EN_R_BIT BIT(1) +#define MAX77675_INT_EN_R_SHIFT 1 +#define MAX77675_INT_EN_F_BIT BIT(0) +#define MAX77675_INT_EN_F_SHIFT 0 + +/* INTM_GLBL (0x03) bits and shifts */ +#define MAX77675_INTM_SBB3_F_BIT BIT(7) +#define MAX77675_INTM_SBB3_F_SHIFT 7 +#define MAX77675_INTM_SBB2_F_BIT BIT(6) +#define MAX77675_INTM_SBB2_F_SHIFT 6 +#define MAX77675_INTM_SBB1_F_BIT BIT(5) +#define MAX77675_INTM_SBB1_F_SHIFT 5 +#define MAX77675_INTM_SBB0_F_BIT BIT(4) +#define MAX77675_INTM_SBB0_F_SHIFT 4 +#define MAX77675_INTM_TJAL2_R_BIT BIT(3) +#define MAX77675_INTM_TJAL2_R_SHIFT 3 +#define MAX77675_INTM_TJAL1_R_BIT BIT(2) +#define MAX77675_INTM_TJAL1_R_SHIFT 2 +#define MAX77675_INTM_EN_R_BIT BIT(1) +#define MAX77675_INTM_EN_R_SHIFT 1 +#define MAX77675_INTM_EN_F_BIT BIT(0) +#define MAX77675_INTM_EN_F_SHIFT 0 + +/* STAT_GLBL (0x04) bits and shifts */ +#define MAX77675_STAT_SBB3_S_BIT BIT(7) +#define MAX77675_STAT_SBB3_S_SHIFT 7 +#define MAX77675_STAT_SBB2_S_BIT BIT(6) +#define MAX77675_STAT_SBB2_S_SHIFT 6 +#define MAX77675_STAT_SBB1_S_BIT BIT(5) +#define MAX77675_STAT_SBB1_S_SHIFT 5 +#define MAX77675_STAT_SBB0_S_BIT BIT(4) +#define MAX77675_STAT_SBB0_S_SHIFT 4 +#define MAX77675_STAT_TJAL2_S_BIT BIT(2) +#define MAX77675_STAT_TJAL2_S_SHIFT 2 +#define MAX77675_STAT_TJAL1_S_BIT BIT(1) +#define MAX77675_STAT_TJAL1_S_SHIFT 1 +#define MAX77675_STAT_STAT_EN_BIT BIT(0) +#define MAX77675_STAT_STAT_EN_SHIFT 0 + +#define MAX77675_STAT_STAT_EN_BIT BIT(0) +#define MAX77675_STAT_STAT_EN_SHIFT 0 + +/* ERCFLAG (0x05) bits and shifts */ +#define MAX77675_SFT_CRST_F_BIT BIT(5) /* Software Cold Reset Flag */ +#define MAX77675_SFT_CRST_F_SHIFT 5 +#define MAX77675_SFT_OFF_F_BIT BIT(4) /* Software Off Flag */ +#define MAX77675_SFT_OFF_F_SHIFT 4 +#define MAX77675_MRST_BIT BIT(3) /* Manual Reset Timer Flag */ +#define MAX77675_MRST_SHIFT 3 +#define MAX77675_UVLO_BIT BIT(2) /* Undervoltage Lockout Flag */ +#define MAX77675_UVLO_SHIFT 2 +#define MAX77675_OVLO_BIT BIT(1) /* Overvoltage Lockout Flag */ +#define MAX77675_OVLO_SHIFT 1 +#define MAX77675_TOVLD_BIT BIT(0) /* Thermal Overload Flag */ +#define MAX77675_TOVLD_SHIFT 0 + +/* CID (0x06) bits and shifts */ +#define MAX77675_CID_MASK GENMASK(4, 0) /* Chip Identification Code mask */ +#define MAX77675_CID_SHIFT 0 /* Starts at bit 0 */ + +/* CNFG_SBB_TOP_A (0x07) bits and shifts */ +#define MAX77675_STEP_SZ_SBB3_BIT BIT(5) +#define MAX77675_STEP_SZ_SBB3_SHIFT 5 +#define MAX77675_STEP_SZ_SBB2_BIT BIT(4) +#define MAX77675_STEP_SZ_SBB2_SHIFT 4 +#define MAX77675_STEP_SZ_SBB1_BIT BIT(3) +#define MAX77675_STEP_SZ_SBB1_SHIFT 3 +#define MAX77675_STEP_SZ_SBB0_BIT BIT(2) +#define MAX77675_STEP_SZ_SBB0_SHIFT 2 +#define MAX77675_DRV_SBB_MASK GENMASK(1, 0) +#define MAX77675_DRV_SBB_SHIFT 0 + +/* CNFG_SBB0_A (0x08) bits and shifts */ +#define MAX77675_TV_SBB0_MASK GENMASK(7, 0) +#define MAX77675_TV_SBB0_SHIFT 0 + +/* CNFG_SBB0_B (0x09) bits and shifts */ +#define MAX77675_ADE_SBB0_BIT BIT(3) +#define MAX77675_ADE_SBB0_SHIFT 3 +#define MAX77675_EN_SBB0_MASK GENMASK(2, 0) +#define MAX77675_EN_SBB0_SHIFT 0 + +/* CNFG_SBB1_A (0x0A) bits and shifts */ +#define MAX77675_TV_SBB1_MASK GENMASK(7, 0) +#define MAX77675_TV_SBB1_SHIFT 0 + +/* CNFG_SBB1_B (0x0B) bits and shifts */ +#define MAX77675_ADE_SBB1_BIT BIT(3) +#define MAX77675_ADE_SBB1_SHIFT 3 +#define MAX77675_EN_SBB1_MASK GENMASK(2, 0) +#define MAX77675_EN_SBB1_SHIFT 0 + +/* CNFG_SBB2_A (0x0C) bits and shifts */ +#define MAX77675_TV_SBB2_MASK GENMASK(7, 0) +#define MAX77675_TV_SBB2_SHIFT 0 + +/* CNFG_SBB2_B (0x0D) bits and shifts */ +#define MAX77675_ADE_SBB2_BIT BIT(3) +#define MAX77675_ADE_SBB2_SHIFT 3 +#define MAX77675_EN_SBB2_MASK GENMASK(2, 0) +#define MAX77675_EN_SBB2_SHIFT 0 + +/* CNFG_SBB3_A (0x0E) bits and shifts */ +#define MAX77675_TV_SBB3_MASK GENMASK(7, 0) +#define MAX77675_TV_SBB3_SHIFT 0 + +/* CNFG_SBB3_B (0x0F) bits and shifts */ +#define MAX77675_ADE_SBB3_BIT BIT(3) +#define MAX77675_ADE_SBB3_SHIFT 3 +#define MAX77675_EN_SBB3_MASK GENMASK(2, 0) +#define MAX77675_EN_SBB3_SHIFT 0 + +#define MAX77675_EN_SBB_MASK GENMASK(2, 0) + +/* CNFG_SBB_TOP_B (0x10) bits and shifts */ +#define MAX77675_DVS_SLEW_BIT BIT(5) +#define MAX77675_DVS_SLEW_SHIFT 5 +#define MAX77675_LAT_MODE_BIT BIT(4) +#define MAX77675_LAT_MODE_SHIFT 4 +#define MAX77675_SR_SBB3_BIT BIT(3) +#define MAX77675_SR_SBB3_SHIFT 3 +#define MAX77675_SR_SBB2_BIT BIT(2) +#define MAX77675_SR_SBB2_SHIFT 2 +#define MAX77675_SR_SBB1_BIT BIT(1) +#define MAX77675_SR_SBB1_SHIFT 1 +#define MAX77675_SR_SBB0_BIT BIT(0) +#define MAX77675_SR_SBB0_SHIFT 0 + +#define MAX77675_MAX_REGISTER 0x10 + +/* Common minimum voltage (in microvolts) */ +#define MAX77675_MIN_UV 500000 // 500 mV + +/* Voltage step configuration for 25mV mode */ +#define MAX77675_STEP_25MV 25000 // Step size: 25 mV +#define MAX77675_MAX_UV_25MV 5500000 // Max voltage: 5.5 V +#define MAX77675_NUM_LEVELS_25MV 201 // levels = (5500mV - 500mV) / 25mV + 1 + +/* Voltage step configuration for 12.5mV mode */ +#define MAX77675_STEP_12_5MV 12500 // Step size: 12.5 mV +#define MAX77675_MAX_UV_12_5MV 3687500 // Max voltage: 3.6875 V +#define MAX77675_NUM_LEVELS_12_5MV 255 // levels = (3687.5mV - 500mV) / 12.5mV + 1 + +#define MAX77675_ENABLE_MASK 0x07 +#define MAX77675_ENABLE_OFF 0x04 +#define MAX77675_ENABLE_ON 0x06 + +#define MAX77675_REGULATOR_AD_MASK BIT(3) +#define MAX77675_REGULATOR_AD_OFF 0x00 +#define MAX77675_REGULATOR_AD_ON BIT(3) + +/* FPS Source */ +enum max77675_fps_src { + MAX77675_FPS_SLOT_0, + MAX77675_FPS_SLOT_1, + MAX77675_FPS_SLOT_2, + MAX77675_FPS_SLOT_3, + MAX77675_FPS_NONE, + MAX77675_FPS_DEF, +}; + +/* Regulator ID enumeration */ +enum max77675_regulator_id { + ID_SBB0 = 0, + ID_SBB1, + ID_SBB2, + ID_SBB3, + MAX77675_NUM_REGULATORS +}; + +/* nEN Mode options */ +enum max77675_en_mode { + EN_PUSH_BUTTON = 0x0, + EN_SLIDE_SWITCH = 0x1, + EN_LOGIC = 0x2, +}; + +/* Use DVS_SLEW for SR_SBBx (0 = 2mV/us, 1 = use DVS_SLEW) */ +enum max77675_slew_rate { + SLEW_RATE_2MV_PER_US = 0, + SLEW_RATE_DVS_SLEW = 1, +}; + +/* Software Control (SFT_CTRL) values */ +enum max77675_sft_ctrl { + SFT_NO_ACTION = 0x0, + SFT_COLD_RESET = 0x1, + SFT_OFF = 0x2, + SFT_STBY = 0x3, + SFT_EXIT_STBY = 0x4, +}; + +enum max77675_drv_sbb_strength { + DRV_SBB_FASTEST = 0x0, // ~0.6ns + DRV_SBB_FAST = 0x1, // ~1.2ns + DRV_SBB_SLOW = 0x2, // ~1.8ns + DRV_SBB_SLOWEST = 0x3, // ~8ns +}; + +struct max77675_irq_status { + bool sbb3_fault; + bool sbb2_fault; + bool sbb1_fault; + bool sbb0_fault; + bool tjal2_rising; + bool tjal1_rising; + bool nen_rising; + bool nen_falling; +}; + +struct max77675_status { + bool sbb3_overload; + bool sbb2_overload; + bool sbb1_overload; + bool sbb0_overload; + bool tjal2_status; + bool tjal1_status; + bool nen_status; +}; + +struct max77675_ercf_status { + bool sft_crst_f; + bool sft_off_f; + bool mrst; + bool uvlo; + bool ovlo; + bool tovld; +}; + +#endif /* __MAX77675_REG_H__ */ diff --git a/include/dt-bindings/regulator/maxim,max77675-regulator.h b/include/dt-bindings/regulator/maxim,max77675-regulator.h new file mode 100644 index 00000000000000..f68b0dfb2ce1b3 --- /dev/null +++ b/include/dt-bindings/regulator/maxim,max77675-regulator.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD 2-Clause */ +/* + * This header provides macros for MAXIM MAX77675 device bindings. + * + * Copyright (c) 2025, Analog Device inc. + * Author: Joan Na + */ + +#ifndef _DT_BINDINGS_REGULATOR_MAX77675_ +#define _DT_BINDINGS_REGULATOR_MAX77675_ + +// Define the voltage limits for 12.5mV and 25mV steps +#define MAX77675_MIN_UV 500000 // 500 mV + +#define MAX77675_MAX_UV_25MV 5500000 // 5.5V in microvolts for 25mV step +#define MAX77675_MAX_UV_12_5MV 3687500 // 3.6875V in microvolts for 12.5mV step + +#define MAX77675_STEP_25MV 25000 // 25 mV +#define MAX77675_STEP_12_5MV 12500 // 12.5 mV + +#define MAX77675_NUM_LEVELS_25MV 201 +#define MAX77675_NUM_LEVELS_12_5MV 255 + +/* FPS source */ +#define MAX77675_FPS_SLOT_0 0 +#define MAX77675_FPS_SLOT_1 1 +#define MAX77675_FPS_SLOT_2 2 +#define MAX77675_FPS_SLOT_3 3 +#define MAX77675_FPS_NONE 4 +#define MAX77675_FPS_DEF 5 + +/* nEN Manual Reset Time Configuration (MRT) */ +#define MAX77675_MRT_4S 0x0 +#define MAX77675_MRT_8S 0x1 +#define MAX77675_MRT_12S 0x2 +#define MAX77675_MRT_16S 0x3 + +/* Internal Pull-Up Disable (PU_DIS) */ +#define MAX77675_PU_EN 0x0 +#define MAX77675_PU_DIS 0x1 + +/* Bias Low-Power Mode (BIAS_LPM) */ +#define MAX77675_BIAS_NORMAL 0x0 +#define MAX77675_BIAS_LPM_REQ 0x1 + +/* SIMO Internal Channel Disable (SIMO_INT_CH_DIS) */ +#define MAX77675_SIMO_INT_NORMAL 0x0 +#define MAX77675_SIMO_INT_LDO 0x1 + +/* nEN Mode Configuration */ +#define MAX77675_EN_PUSH_BUTTON 0x0 +#define MAX77675_EN_SLIDE_SWITCH 0x1 +#define MAX77675_EN_LOGIC 0x2 +#define MAX77675_EN_RESERVED 0x3 + +/* Debounce Timer Enable (DBEN_nEN) */ +#define MAX77675_DBEN_100US 0x0 +#define MAX77675_DBEN_30MS 0x1 + +/* Rising slew rate control for SBB0 when ramping up */ +#define MAX77675_SR_2MV_PER_US 0x0 // 2 mV/µs +#define MAX77675_SR_USE_DVS 0x1 // Use DVS slew rate setting (maxim,dvs-slew-rate) + +/* Dynamic Voltage Scaling (DVS) Slew Rate */ +#define MAX77675_DVS_SLEW_5MV 0x0 // 5 mV/µs +#define MAX77675_DVS_SLEW_10MV 0x1 // 10 mV/µs + +/* Latency Mode */ +#define MAX77675_LAT_MODE_HIGH_LATENCY 0 // Low quiescent current, high latency (~100µs) +#define MAX77675_LAT_MODE_LOW_LATENCY 1 // High quiescent current, low latency (~10µs) + +/* SIMO Buck-Boost Drive Strength (All Channels) */ +#define MAX77675_DRV_SBB_FASTEST 0 // Fastest transition (~0.6 ns) +#define MAX77675_DRV_SBB_FAST 1 // Faster transition (~1.2 ns) +#define MAX77675_DRV_SBB_MEDIUM 2 // Moderate transition (~1.8 ns) +#define MAX77675_DRV_SBB_SLOWEST 3 // Slowest transition (~8 ns) + +#endif