Merge tag 'pci-v6.4-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
[linux.git] / drivers / regulator / rt5739.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Device driver for RT5739 regulator
4  *
5  * Copyright (C) 2023 Richtek Technology Corp.
6  *
7  * Author: ChiYuan Huang <cy_huang@richtek.com>
8  */
9
10 #include <linux/bits.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/i2c.h>
13 #include <linux/kernel.h>
14 #include <linux/mod_devicetable.h>
15 #include <linux/property.h>
16 #include <linux/regmap.h>
17 #include <linux/regulator/driver.h>
18 #include <linux/regulator/of_regulator.h>
19
20 #define RT5739_AUTO_MODE        0
21 #define RT5739_FPWM_MODE        1
22
23 #define RT5739_REG_NSEL0        0x00
24 #define RT5739_REG_NSEL1        0x01
25 #define RT5739_REG_CNTL1        0x02
26 #define RT5739_REG_ID1          0x03
27 #define RT5739_REG_CNTL2        0x06
28 #define RT5739_REG_CNTL4        0x08
29
30 #define RT5739_VSEL_MASK        GENMASK(7, 0)
31 #define RT5739_MODEVSEL1_MASK   BIT(1)
32 #define RT5739_MODEVSEL0_MASK   BIT(0)
33 #define RT5739_VID_MASK         GENMASK(7, 5)
34 #define RT5739_ACTD_MASK        BIT(7)
35 #define RT5739_ENVSEL1_MASK     BIT(1)
36 #define RT5739_ENVSEL0_MASK     BIT(0)
37
38 #define RT5739_VOLT_MINUV       300000
39 #define RT5739_VOLT_MAXUV       1300000
40 #define RT5739_VOLT_STPUV       5000
41 #define RT5739_N_VOLTS          201
42 #define RT5739_I2CRDY_TIMEUS    1000
43
44 static int rt5739_set_mode(struct regulator_dev *rdev, unsigned int mode)
45 {
46         const struct regulator_desc *desc = rdev->desc;
47         struct regmap *regmap = rdev_get_regmap(rdev);
48         unsigned int mask, val;
49
50         if (desc->vsel_reg == RT5739_REG_NSEL0)
51                 mask = RT5739_MODEVSEL0_MASK;
52         else
53                 mask = RT5739_MODEVSEL1_MASK;
54
55         switch (mode) {
56         case REGULATOR_MODE_FAST:
57                 val = mask;
58                 break;
59         case REGULATOR_MODE_NORMAL:
60                 val = 0;
61                 break;
62         default:
63                 return -EINVAL;
64         }
65
66         return regmap_update_bits(regmap, RT5739_REG_CNTL1, mask, val);
67 }
68
69 static unsigned int rt5739_get_mode(struct regulator_dev *rdev)
70 {
71         const struct regulator_desc *desc = rdev->desc;
72         struct regmap *regmap = rdev_get_regmap(rdev);
73         unsigned int mask, val;
74         int ret;
75
76         if (desc->vsel_reg == RT5739_REG_NSEL0)
77                 mask = RT5739_MODEVSEL0_MASK;
78         else
79                 mask = RT5739_MODEVSEL1_MASK;
80
81         ret = regmap_read(regmap, RT5739_REG_CNTL1, &val);
82         if (ret)
83                 return REGULATOR_MODE_INVALID;
84
85         if (val & mask)
86                 return REGULATOR_MODE_FAST;
87
88         return REGULATOR_MODE_NORMAL;
89 }
90
91 static int rt5739_set_suspend_voltage(struct regulator_dev *rdev, int uV)
92 {
93         const struct regulator_desc *desc = rdev->desc;
94         struct regmap *regmap = rdev_get_regmap(rdev);
95         unsigned int reg, vsel;
96
97         if (uV < RT5739_VOLT_MINUV || uV > RT5739_VOLT_MAXUV)
98                 return -EINVAL;
99
100         if (desc->vsel_reg == RT5739_REG_NSEL0)
101                 reg = RT5739_REG_NSEL1;
102         else
103                 reg = RT5739_REG_NSEL0;
104
105         vsel = (uV - RT5739_VOLT_MINUV) / RT5739_VOLT_STPUV;
106         return regmap_write(regmap, reg, vsel);
107 }
108
109 static int rt5739_set_suspend_enable(struct regulator_dev *rdev)
110 {
111         const struct regulator_desc *desc = rdev->desc;
112         struct regmap *regmap = rdev_get_regmap(rdev);
113         unsigned int mask;
114
115         if (desc->vsel_reg == RT5739_REG_NSEL0)
116                 mask = RT5739_ENVSEL1_MASK;
117         else
118                 mask = RT5739_ENVSEL0_MASK;
119
120         return regmap_update_bits(regmap, desc->enable_reg, mask, mask);
121 }
122
123 static int rt5739_set_suspend_disable(struct regulator_dev *rdev)
124 {
125         const struct regulator_desc *desc = rdev->desc;
126         struct regmap *regmap = rdev_get_regmap(rdev);
127         unsigned int mask;
128
129         if (desc->vsel_reg == RT5739_REG_NSEL0)
130                 mask = RT5739_ENVSEL1_MASK;
131         else
132                 mask = RT5739_ENVSEL0_MASK;
133
134         return regmap_update_bits(regmap, desc->enable_reg, mask, 0);
135 }
136
137 static int rt5739_set_suspend_mode(struct regulator_dev *rdev,
138                                    unsigned int mode)
139 {
140         const struct regulator_desc *desc = rdev->desc;
141         struct regmap *regmap = rdev_get_regmap(rdev);
142         unsigned int mask, val;
143
144         if (desc->vsel_reg == RT5739_REG_NSEL0)
145                 mask = RT5739_MODEVSEL1_MASK;
146         else
147                 mask = RT5739_MODEVSEL0_MASK;
148
149         switch (mode) {
150         case REGULATOR_MODE_FAST:
151                 val = mask;
152                 break;
153         case REGULATOR_MODE_NORMAL:
154                 val = 0;
155                 break;
156         default:
157                 return -EINVAL;
158         }
159
160         return regmap_update_bits(regmap, RT5739_REG_CNTL1, mask, val);
161 }
162
163 static const struct regulator_ops rt5739_regulator_ops = {
164         .list_voltage = regulator_list_voltage_linear,
165         .get_voltage_sel = regulator_get_voltage_sel_regmap,
166         .set_voltage_sel = regulator_set_voltage_sel_regmap,
167         .enable = regulator_enable_regmap,
168         .disable = regulator_disable_regmap,
169         .is_enabled = regulator_is_enabled_regmap,
170         .set_active_discharge = regulator_set_active_discharge_regmap,
171         .set_mode = rt5739_set_mode,
172         .get_mode = rt5739_get_mode,
173         .set_suspend_voltage = rt5739_set_suspend_voltage,
174         .set_suspend_enable = rt5739_set_suspend_enable,
175         .set_suspend_disable = rt5739_set_suspend_disable,
176         .set_suspend_mode = rt5739_set_suspend_mode,
177 };
178
179 static unsigned int rt5739_of_map_mode(unsigned int mode)
180 {
181         switch (mode) {
182         case RT5739_AUTO_MODE:
183                 return REGULATOR_MODE_NORMAL;
184         case RT5739_FPWM_MODE:
185                 return REGULATOR_MODE_FAST;
186         default:
187                 return REGULATOR_MODE_INVALID;
188         }
189 }
190
191 static void rt5739_init_regulator_desc(struct regulator_desc *desc,
192                                        bool vsel_active_high)
193 {
194         /* Fixed */
195         desc->name = "rt5739-regulator";
196         desc->owner = THIS_MODULE;
197         desc->ops = &rt5739_regulator_ops;
198         desc->n_voltages = RT5739_N_VOLTS;
199         desc->min_uV = RT5739_VOLT_MINUV;
200         desc->uV_step = RT5739_VOLT_STPUV;
201         desc->vsel_mask = RT5739_VSEL_MASK;
202         desc->enable_reg = RT5739_REG_CNTL2;
203         desc->active_discharge_reg = RT5739_REG_CNTL1;
204         desc->active_discharge_mask = RT5739_ACTD_MASK;
205         desc->active_discharge_on = RT5739_ACTD_MASK;
206         desc->of_map_mode = rt5739_of_map_mode;
207
208         /* Assigned by vsel level */
209         if (vsel_active_high) {
210                 desc->vsel_reg = RT5739_REG_NSEL1;
211                 desc->enable_mask = RT5739_ENVSEL1_MASK;
212         } else {
213                 desc->vsel_reg = RT5739_REG_NSEL0;
214                 desc->enable_mask = RT5739_ENVSEL0_MASK;
215         }
216 }
217
218 static const struct regmap_config rt5739_regmap_config = {
219         .name = "rt5739",
220         .reg_bits = 8,
221         .val_bits = 8,
222         .max_register = RT5739_REG_CNTL4,
223 };
224
225 static int rt5739_probe(struct i2c_client *i2c)
226 {
227         struct device *dev = &i2c->dev;
228         struct regulator_desc *desc;
229         struct regmap *regmap;
230         struct gpio_desc *enable_gpio;
231         struct regulator_config cfg = {};
232         struct regulator_dev *rdev;
233         bool vsel_acth;
234         unsigned int vid;
235         int ret;
236
237         desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
238         if (!desc)
239                 return -ENOMEM;
240
241         enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
242         if (IS_ERR(enable_gpio))
243                 return dev_err_probe(dev, PTR_ERR(enable_gpio), "Failed to get 'enable' gpio\n");
244         else if (enable_gpio)
245                 usleep_range(RT5739_I2CRDY_TIMEUS, RT5739_I2CRDY_TIMEUS + 1000);
246
247         regmap = devm_regmap_init_i2c(i2c, &rt5739_regmap_config);
248         if (IS_ERR(regmap))
249                 return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n");
250
251         ret = regmap_read(regmap, RT5739_REG_ID1, &vid);
252         if (ret)
253                 return dev_err_probe(dev, ret, "Failed to read VID\n");
254
255         /* RT5739: (VID & MASK) must be 0 */
256         if (vid & RT5739_VID_MASK)
257                 return dev_err_probe(dev, -ENODEV, "Incorrect VID (0x%02x)\n", vid);
258
259         vsel_acth = device_property_read_bool(dev, "richtek,vsel-active-high");
260
261         rt5739_init_regulator_desc(desc, vsel_acth);
262
263         cfg.dev = dev;
264         cfg.of_node = dev_of_node(dev);
265         cfg.init_data = of_get_regulator_init_data(dev, dev_of_node(dev), desc);
266         rdev = devm_regulator_register(dev, desc, &cfg);
267         if (IS_ERR(rdev))
268                 return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register regulator\n");
269
270         return 0;
271 }
272
273 static const struct of_device_id rt5739_device_table[] = {
274         { .compatible = "richtek,rt5739" },
275         { /* sentinel */ }
276 };
277 MODULE_DEVICE_TABLE(of, rt5739_device_table);
278
279 static struct i2c_driver rt5739_driver = {
280         .driver = {
281                 .name = "rt5739",
282                 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
283                 .of_match_table = rt5739_device_table,
284         },
285         .probe_new = rt5739_probe,
286 };
287 module_i2c_driver(rt5739_driver);
288
289 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
290 MODULE_DESCRIPTION("Richtek RT5739 regulator driver");
291 MODULE_LICENSE("GPL");