xref: /linux/drivers/regulator/bq257xx-regulator.c (revision 68a052239fc4b351e961f698b824f7654a346091)
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, &reg);
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