[PATCH 10/11] regulator: bq257xx: Add support for BQ25792

From: Alexey Charkov

Date: Tue Mar 03 2026 - 10:41:52 EST


Add support for TI BQ25792, an integrated battery charger and buck/boost
regulator. This enables VBUS output from the charger's boost converter
for use in USB OTG applications, supporting 2.8-22V output at up to 3.32A
with 10mV and 40mA resolution.

Signed-off-by: Alexey Charkov <alchark@xxxxxxxxxxx>
---
drivers/regulator/bq257xx-regulator.c | 98 ++++++++++++++++++++++++++++++++++-
1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/drivers/regulator/bq257xx-regulator.c b/drivers/regulator/bq257xx-regulator.c
index 0bb58ab4b8d4..61911ac8613a 100644
--- a/drivers/regulator/bq257xx-regulator.c
+++ b/drivers/regulator/bq257xx-regulator.c
@@ -31,6 +31,32 @@ static int bq25703_vbus_get_cur_limit(struct regulator_dev *rdev)
return FIELD_GET(BQ25703_OTG_CUR_MASK, reg) * BQ25703_OTG_CUR_STEP_UA;
}

+static int bq25792_vbus_get_cur_limit(struct regulator_dev *rdev)
+{
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ int ret;
+ unsigned int reg;
+
+ ret = regmap_read(regmap, BQ25792_REG0D_IOTG_REGULATION, &reg);
+ if (ret)
+ return ret;
+ return FIELD_GET(BQ25792_REG0D_IOTG_MASK, reg) * BQ25792_OTG_CUR_STEP_UA;
+}
+
+static int bq25792_vbus_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ __be16 reg;
+ int ret;
+
+ ret = regmap_raw_read(regmap, BQ25792_REG0B_VOTG_REGULATION,
+ &reg, sizeof(reg));
+ if (ret)
+ return ret;
+
+ return FIELD_GET(BQ25792_REG0B_VOTG_MASK, be16_to_cpu(reg));
+}
+
/*
* Check if the minimum current and maximum current requested are
* sane values, then set the register accordingly.
@@ -54,6 +80,37 @@ static int bq25703_vbus_set_cur_limit(struct regulator_dev *rdev,
FIELD_PREP(BQ25703_OTG_CUR_MASK, reg));
}

+static int bq25792_vbus_set_cur_limit(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
+{
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ unsigned int reg;
+
+ if ((min_uA > BQ25792_OTG_CUR_MAX_UA) ||
+ (max_uA < BQ25792_OTG_CUR_MIN_UA))
+ return -EINVAL;
+
+ reg = (max_uA / BQ25792_OTG_CUR_STEP_UA);
+
+ /* Catch rounding errors since our step is 40000uA. */
+ if ((reg * BQ25792_OTG_CUR_STEP_UA) < min_uA)
+ return -EINVAL;
+
+ return regmap_write(regmap, BQ25792_REG0D_IOTG_REGULATION,
+ FIELD_PREP(BQ25792_REG0D_IOTG_MASK, reg));
+}
+
+static int bq25792_vbus_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int sel)
+{
+ struct regmap *regmap = rdev_get_regmap(rdev);
+ __be16 reg;
+
+ reg = cpu_to_be16(FIELD_PREP(BQ25792_REG0B_VOTG_MASK, sel));
+ return regmap_raw_write(regmap, BQ25792_REG0B_VOTG_REGULATION,
+ &reg, sizeof(reg));
+}
+
static int bq25703_vbus_enable(struct regulator_dev *rdev)
{
struct bq257xx_reg_data *pdata = rdev_get_drvdata(rdev);
@@ -101,6 +158,34 @@ static const struct regulator_desc bq25703_vbus_desc = {
.vsel_mask = BQ25703_OTG_VOLT_MASK,
};

+static const struct regulator_ops bq25792_vbus_ops = {
+ /* No GPIO for enabling the OTG regulator */
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = bq25792_vbus_get_voltage_sel,
+ .set_voltage_sel = bq25792_vbus_set_voltage_sel,
+ .get_current_limit = bq25792_vbus_get_cur_limit,
+ .set_current_limit = bq25792_vbus_set_cur_limit,
+};
+
+static const struct regulator_desc bq25792_vbus_desc = {
+ .name = "vbus",
+ .of_match = of_match_ptr("vbus"),
+ .regulators_node = of_match_ptr("regulators"),
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .ops = &bq25792_vbus_ops,
+ .min_uV = BQ25792_OTG_VOLT_MIN_UV,
+ .uV_step = BQ25792_OTG_VOLT_STEP_UV,
+ .n_voltages = BQ25792_OTG_VOLT_NUM_VOLT,
+ .enable_mask = BQ25792_REG12_EN_OTG,
+ .enable_reg = BQ25792_REG12_CHARGER_CONTROL_3,
+ .enable_val = BQ25792_REG12_EN_OTG,
+ .disable_val = 0,
+};
+
/* Get optional GPIO for OTG regulator enable. */
static void bq257xx_reg_dt_parse_gpio(struct platform_device *pdev)
{
@@ -141,6 +226,7 @@ static void bq257xx_reg_dt_parse_gpio(struct platform_device *pdev)
static int bq257xx_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct bq257xx_plat *plat = dev_get_platdata(dev);
struct bq257xx_reg_data *pdata;
struct device_node *np = dev->of_node;
struct regulator_config cfg = {};
@@ -153,7 +239,17 @@ static int bq257xx_regulator_probe(struct platform_device *pdev)
if (!pdata)
return -ENOMEM;

- pdata->desc = bq25703_vbus_desc;
+ switch (plat->type) {
+ case BQ25703A:
+ pdata->desc = bq25703_vbus_desc;
+ break;
+ case BQ25792:
+ pdata->desc = bq25792_vbus_desc;
+ break;
+ default:
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "Unsupported device type\n");
+ }

platform_set_drvdata(pdev, pdata);
bq257xx_reg_dt_parse_gpio(pdev);

--
2.52.0