1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * BQ257XX Battery Charger Driver 4 * Copyright (C) 2025 Chris Morgan <macromorgan@hotmail.com> 5 */ 6 7 #include <linux/bitfield.h> 8 #include <linux/err.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/mfd/bq257xx.h> 11 #include <linux/of.h> 12 #include <linux/platform_device.h> 13 #include <linux/regmap.h> 14 #include <linux/regulator/driver.h> 15 #include <linux/regulator/of_regulator.h> 16 17 struct bq257xx_reg_data { 18 struct bq257xx_device *bq; 19 struct regulator_dev *bq257xx_reg; 20 struct gpio_desc *otg_en_gpio; 21 struct regulator_desc desc; 22 }; 23 24 static int bq25703_vbus_get_cur_limit(struct regulator_dev *rdev) 25 { 26 struct bq257xx_reg_data *pdata = rdev_get_drvdata(rdev); 27 int ret; 28 unsigned int reg; 29 30 ret = regmap_read(pdata->bq->regmap, BQ25703_OTG_CURRENT, ®); 31 if (ret) 32 return ret; 33 return FIELD_GET(BQ25703_OTG_CUR_MASK, reg) * BQ25703_OTG_CUR_STEP_UA; 34 } 35 36 /* 37 * Check if the minimum current and maximum current requested are 38 * sane values, then set the register accordingly. 39 */ 40 static int bq25703_vbus_set_cur_limit(struct regulator_dev *rdev, 41 int min_uA, int max_uA) 42 { 43 struct bq257xx_reg_data *pdata = rdev_get_drvdata(rdev); 44 unsigned int reg; 45 46 if ((min_uA > BQ25703_OTG_CUR_MAX_UA) || (max_uA < 0)) 47 return -EINVAL; 48 49 reg = (max_uA / BQ25703_OTG_CUR_STEP_UA); 50 51 /* Catch rounding errors since our step is 50000uA. */ 52 if ((reg * BQ25703_OTG_CUR_STEP_UA) < min_uA) 53 return -EINVAL; 54 55 return regmap_write(pdata->bq->regmap, BQ25703_OTG_CURRENT, 56 FIELD_PREP(BQ25703_OTG_CUR_MASK, reg)); 57 } 58 59 static int bq25703_vbus_enable(struct regulator_dev *rdev) 60 { 61 struct bq257xx_reg_data *pdata = rdev_get_drvdata(rdev); 62 63 if (pdata->otg_en_gpio) 64 gpiod_set_value_cansleep(pdata->otg_en_gpio, 1); 65 return regulator_enable_regmap(rdev); 66 } 67 68 static int bq25703_vbus_disable(struct regulator_dev *rdev) 69 { 70 struct bq257xx_reg_data *pdata = rdev_get_drvdata(rdev); 71 72 if (pdata->otg_en_gpio) 73 gpiod_set_value_cansleep(pdata->otg_en_gpio, 0); 74 return regulator_disable_regmap(rdev); 75 } 76 77 static const struct regulator_ops bq25703_vbus_ops = { 78 .enable = bq25703_vbus_enable, 79 .disable = bq25703_vbus_disable, 80 .is_enabled = regulator_is_enabled_regmap, 81 .list_voltage = regulator_list_voltage_linear, 82 .get_voltage_sel = regulator_get_voltage_sel_regmap, 83 .set_voltage_sel = regulator_set_voltage_sel_regmap, 84 .get_current_limit = bq25703_vbus_get_cur_limit, 85 .set_current_limit = bq25703_vbus_set_cur_limit, 86 }; 87 88 static const struct regulator_desc bq25703_vbus_desc = { 89 .name = "vbus", 90 .of_match = of_match_ptr("vbus"), 91 .regulators_node = of_match_ptr("regulators"), 92 .type = REGULATOR_VOLTAGE, 93 .owner = THIS_MODULE, 94 .ops = &bq25703_vbus_ops, 95 .min_uV = BQ25703_OTG_VOLT_MIN_UV, 96 .uV_step = BQ25703_OTG_VOLT_STEP_UV, 97 .n_voltages = BQ25703_OTG_VOLT_NUM_VOLT, 98 .enable_mask = BQ25703_EN_OTG_MASK, 99 .enable_reg = BQ25703_CHARGE_OPTION_3, 100 .enable_val = BQ25703_EN_OTG_MASK, 101 .disable_val = 0, 102 .vsel_reg = BQ25703_OTG_VOLT, 103 .vsel_mask = BQ25703_OTG_VOLT_MASK, 104 }; 105 106 /* Get optional GPIO for OTG regulator enable. */ 107 static void bq257xx_reg_dt_parse_gpio(struct platform_device *pdev) 108 { 109 struct device_node *child, *subchild; 110 struct bq257xx_reg_data *pdata = platform_get_drvdata(pdev); 111 112 child = of_get_child_by_name(pdev->dev.of_node, 113 pdata->desc.regulators_node); 114 if (!child) 115 return; 116 117 subchild = of_get_child_by_name(child, pdata->desc.of_match); 118 if (!subchild) 119 return; 120 121 of_node_put(child); 122 123 pdata->otg_en_gpio = devm_fwnode_gpiod_get_index(&pdev->dev, 124 of_fwnode_handle(subchild), 125 "enable", 0, 126 GPIOD_OUT_LOW, 127 pdata->desc.of_match); 128 129 of_node_put(subchild); 130 131 if (IS_ERR(pdata->otg_en_gpio)) { 132 dev_err(&pdev->dev, "Error getting enable gpio: %ld\n", 133 PTR_ERR(pdata->otg_en_gpio)); 134 return; 135 } 136 } 137 138 static int bq257xx_regulator_probe(struct platform_device *pdev) 139 { 140 struct device *dev = &pdev->dev; 141 struct bq257xx_device *bq = dev_get_drvdata(pdev->dev.parent); 142 struct bq257xx_reg_data *pdata; 143 struct device_node *np = dev->of_node; 144 struct regulator_config cfg = {}; 145 146 pdev->dev.of_node = pdev->dev.parent->of_node; 147 pdev->dev.of_node_reused = true; 148 149 pdata = devm_kzalloc(&pdev->dev, sizeof(struct bq257xx_reg_data), GFP_KERNEL); 150 if (!pdata) 151 return -ENOMEM; 152 153 pdata->bq = bq; 154 pdata->desc = bq25703_vbus_desc; 155 156 platform_set_drvdata(pdev, pdata); 157 bq257xx_reg_dt_parse_gpio(pdev); 158 159 cfg.dev = &pdev->dev; 160 cfg.driver_data = pdata; 161 cfg.of_node = np; 162 cfg.regmap = dev_get_regmap(pdev->dev.parent, NULL); 163 if (!cfg.regmap) 164 return -ENODEV; 165 166 pdata->bq257xx_reg = devm_regulator_register(dev, &pdata->desc, &cfg); 167 if (IS_ERR(pdata->bq257xx_reg)) { 168 return dev_err_probe(&pdev->dev, PTR_ERR(pdata->bq257xx_reg), 169 "error registering bq257xx regulator"); 170 } 171 172 return 0; 173 } 174 175 static struct platform_driver bq257xx_reg_driver = { 176 .driver = { 177 .name = "bq257xx-regulator", 178 }, 179 .probe = bq257xx_regulator_probe, 180 }; 181 182 module_platform_driver(bq257xx_reg_driver); 183 184 MODULE_DESCRIPTION("bq257xx regulator driver"); 185 MODULE_AUTHOR("Chris Morgan <macromorgan@hotmail.com>"); 186 MODULE_LICENSE("GPL"); 187