diff options
| author | Rakesh Kota <rakesh.kota@oss.qualcomm.com> | 2026-07-06 18:01:06 +0530 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-07-06 23:34:09 +0100 |
| commit | 56cb4a0e8e7121e58df6395218c8d64bf2ff08d0 (patch) | |
| tree | 90f5f13fbca65e5c9f41d844e6590dae274e32c8 /drivers | |
| parent | a58d2e5e1c0406d4375861094070c22d6137713a (diff) | |
regulator: qcom_usb_vbus: add register abstraction and PM8150B support
Introduce per-compatible regulator descriptor data via struct
qcom_usb_vbus_reg_data to abstract register layout differences between
PMICs. This allows the probe function to dynamically populate the
regulator_desc fields rather than relying on compile-time constants.
Refactor the existing PM8150B support to use this abstraction, wiring in
its CMD_OTG, OTG_CFG, and current-limit registers through pm8150b_data.
No functional change is intended for PM8150B.
Signed-off-by: Rakesh Kota <rakesh.kota@oss.qualcomm.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://patch.msgid.link/20260706-add_pm4125-vbus-reg-v3-2-999d78a87b81@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/regulator/qcom_usb_vbus-regulator.c | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/drivers/regulator/qcom_usb_vbus-regulator.c b/drivers/regulator/qcom_usb_vbus-regulator.c index cd94ed67621f..0201a3983981 100644 --- a/drivers/regulator/qcom_usb_vbus-regulator.c +++ b/drivers/regulator/qcom_usb_vbus-regulator.c @@ -20,6 +20,21 @@ #define OTG_CFG 0x53 #define OTG_EN_SRC_CFG BIT(1) +struct qcom_usb_vbus_reg_data { + u16 cmd_otg; + u16 otg_cfg; + u8 otg_en_src_cfg; + u16 csel_reg; + u8 csel_mask; + const unsigned int *curr_table; + unsigned int n_current_limits; + u16 vsel_reg; + u8 vsel_mask; + const unsigned int *volt_table; + unsigned int n_voltages; + const struct regulator_ops *ops; +}; + static const unsigned int curr_table[] = { 500000, 1000000, 1500000, 2000000, 2500000, 3000000, }; @@ -32,19 +47,23 @@ static const struct regulator_ops qcom_usb_vbus_reg_ops = { .set_current_limit = regulator_set_current_limit_regmap, }; -static struct regulator_desc qcom_usb_vbus_rdesc = { - .name = "usb_vbus", - .ops = &qcom_usb_vbus_reg_ops, - .owner = THIS_MODULE, - .type = REGULATOR_VOLTAGE, +static const struct qcom_usb_vbus_reg_data pm8150b_data = { + .cmd_otg = CMD_OTG, + .otg_cfg = OTG_CFG, + .otg_en_src_cfg = OTG_EN_SRC_CFG, + .csel_reg = OTG_CURRENT_LIMIT_CFG, + .csel_mask = OTG_CURRENT_LIMIT_MASK, .curr_table = curr_table, .n_current_limits = ARRAY_SIZE(curr_table), + .ops = &qcom_usb_vbus_reg_ops, }; static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const struct qcom_usb_vbus_reg_data *data; struct regulator_dev *rdev; + struct regulator_desc *rdesc; struct regmap *regmap; struct regulator_config config = { }; struct regulator_init_data *init_data; @@ -57,27 +76,51 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) return ret; } + data = of_device_get_match_data(dev); + if (!data) + return -EINVAL; + regmap = dev_get_regmap(dev->parent, NULL); if (!regmap) { dev_err(dev, "Failed to get regmap\n"); return -ENOENT; } - init_data = of_get_regulator_init_data(dev, dev->of_node, - &qcom_usb_vbus_rdesc); + rdesc = devm_kzalloc(dev, sizeof(*rdesc), GFP_KERNEL); + if (!rdesc) + return -ENOMEM; + + rdesc->name = "usb_vbus"; + rdesc->ops = data->ops; + rdesc->owner = THIS_MODULE; + rdesc->type = REGULATOR_VOLTAGE; + rdesc->enable_reg = base + data->cmd_otg; + rdesc->enable_mask = OTG_EN; + + if (data->curr_table) { + rdesc->curr_table = data->curr_table; + rdesc->n_current_limits = data->n_current_limits; + rdesc->csel_reg = base + data->csel_reg; + rdesc->csel_mask = data->csel_mask; + } + + if (data->volt_table) { + rdesc->volt_table = data->volt_table; + rdesc->n_voltages = data->n_voltages; + rdesc->vsel_reg = base + data->vsel_reg; + rdesc->vsel_mask = data->vsel_mask; + } + + init_data = of_get_regulator_init_data(dev, dev->of_node, rdesc); if (!init_data) return -ENOMEM; - qcom_usb_vbus_rdesc.enable_reg = base + CMD_OTG; - qcom_usb_vbus_rdesc.enable_mask = OTG_EN; - qcom_usb_vbus_rdesc.csel_reg = base + OTG_CURRENT_LIMIT_CFG; - qcom_usb_vbus_rdesc.csel_mask = OTG_CURRENT_LIMIT_MASK; config.dev = dev; config.init_data = init_data; config.of_node = dev->of_node; config.regmap = regmap; - rdev = devm_regulator_register(dev, &qcom_usb_vbus_rdesc, &config); + rdev = devm_regulator_register(dev, rdesc, &config); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); dev_err(dev, "not able to register vbus reg %d\n", ret); @@ -85,13 +128,13 @@ static int qcom_usb_vbus_regulator_probe(struct platform_device *pdev) } /* Disable HW logic for VBUS enable */ - regmap_update_bits(regmap, base + OTG_CFG, OTG_EN_SRC_CFG, 0); + regmap_update_bits(regmap, base + data->otg_cfg, data->otg_en_src_cfg, 0); return 0; } static const struct of_device_id qcom_usb_vbus_regulator_match[] = { - { .compatible = "qcom,pm8150b-vbus-reg" }, + { .compatible = "qcom,pm8150b-vbus-reg", .data = &pm8150b_data }, { } }; MODULE_DEVICE_TABLE(of, qcom_usb_vbus_regulator_match); |
