Merge tag 'for-5.14-regulator' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra...
[linux-block.git] / drivers / regulator / rt6160-regulator.c
CommitLineData
de20b747
CH
1// SPDX-License-Identifier: GPL-2.0-only
2
3#include <linux/delay.h>
4#include <linux/gpio/consumer.h>
5#include <linux/i2c.h>
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/property.h>
9#include <linux/regmap.h>
10#include <linux/regulator/driver.h>
11#include <linux/regulator/of_regulator.h>
12
13#define RT6160_MODE_AUTO 0
14#define RT6160_MODE_FPWM 1
15
16#define RT6160_REG_CNTL 0x01
17#define RT6160_REG_STATUS 0x02
18#define RT6160_REG_DEVID 0x03
19#define RT6160_REG_VSELL 0x04
20#define RT6160_REG_VSELH 0x05
21#define RT6160_NUM_REGS (RT6160_REG_VSELH + 1)
22
23#define RT6160_FPWM_MASK BIT(3)
24#define RT6160_RAMPRATE_MASK GENMASK(1, 0)
25#define RT6160_VID_MASK GENMASK(7, 4)
26#define RT6160_VSEL_MASK GENMASK(6, 0)
27#define RT6160_HDSTAT_MASK BIT(4)
28#define RT6160_UVSTAT_MASK BIT(3)
29#define RT6160_OCSTAT_MASK BIT(2)
30#define RT6160_TSDSTAT_MASK BIT(1)
31#define RT6160_PGSTAT_MASK BIT(0)
32
33#define RT6160_VENDOR_ID 0xA0
34#define RT6160_VOUT_MINUV 2025000
35#define RT6160_VOUT_MAXUV 5200000
36#define RT6160_VOUT_STPUV 25000
37#define RT6160_N_VOUTS ((RT6160_VOUT_MAXUV - RT6160_VOUT_MINUV) / RT6160_VOUT_STPUV + 1)
38
39#define RT6160_I2CRDY_TIMEUS 100
40
41struct rt6160_priv {
42 struct regulator_desc desc;
43 struct gpio_desc *enable_gpio;
44 struct regmap *regmap;
45 bool vsel_active_low;
46 bool enable_state;
47};
48
49static int rt6160_enable(struct regulator_dev *rdev)
50{
51 struct rt6160_priv *priv = rdev_get_drvdata(rdev);
52
53 if (!priv->enable_gpio)
54 return 0;
55
56 gpiod_set_value_cansleep(priv->enable_gpio, 1);
57 priv->enable_state = true;
58
59 usleep_range(RT6160_I2CRDY_TIMEUS, RT6160_I2CRDY_TIMEUS + 100);
60
61 regcache_cache_only(priv->regmap, false);
62 return regcache_sync(priv->regmap);
63}
64
65static int rt6160_disable(struct regulator_dev *rdev)
66{
67 struct rt6160_priv *priv = rdev_get_drvdata(rdev);
68
69 if (!priv->enable_gpio)
70 return -EINVAL;
71
72 /* Mark regcache as dirty and cache only before HW disabled */
73 regcache_cache_only(priv->regmap, true);
74 regcache_mark_dirty(priv->regmap);
75
76 priv->enable_state = false;
77 gpiod_set_value_cansleep(priv->enable_gpio, 0);
78
79 return 0;
80
81}
82
83static int rt6160_is_enabled(struct regulator_dev *rdev)
84{
85 struct rt6160_priv *priv = rdev_get_drvdata(rdev);
86
87 return priv->enable_state ? 1 : 0;
88}
89
90static int rt6160_set_mode(struct regulator_dev *rdev, unsigned int mode)
91{
92 struct regmap *regmap = rdev_get_regmap(rdev);
93 unsigned int mode_val;
94
95 switch (mode) {
96 case REGULATOR_MODE_FAST:
97 mode_val = RT6160_FPWM_MASK;
98 break;
99 case REGULATOR_MODE_NORMAL:
100 mode_val = 0;
101 break;
102 default:
103 dev_err(&rdev->dev, "mode not supported\n");
104 return -EINVAL;
105 }
106
107 return regmap_update_bits(regmap, RT6160_REG_CNTL, RT6160_FPWM_MASK, mode_val);
108}
109
110static unsigned int rt6160_get_mode(struct regulator_dev *rdev)
111{
112 struct regmap *regmap = rdev_get_regmap(rdev);
113 unsigned int val;
114 int ret;
115
116 ret = regmap_read(regmap, RT6160_REG_CNTL, &val);
117 if (ret)
118 return ret;
119
120 if (val & RT6160_FPWM_MASK)
121 return REGULATOR_MODE_FAST;
122
123 return REGULATOR_MODE_NORMAL;
124}
125
126static int rt6160_set_suspend_voltage(struct regulator_dev *rdev, int uV)
127{
128 struct rt6160_priv *priv = rdev_get_drvdata(rdev);
129 struct regmap *regmap = rdev_get_regmap(rdev);
130 unsigned int reg = RT6160_REG_VSELH;
131 int vsel;
132
133 vsel = regulator_map_voltage_linear(rdev, uV, uV);
134 if (vsel < 0)
135 return vsel;
136
137 if (priv->vsel_active_low)
138 reg = RT6160_REG_VSELL;
139
140 return regmap_update_bits(regmap, reg, RT6160_VSEL_MASK, vsel);
141}
142
143static int rt6160_set_ramp_delay(struct regulator_dev *rdev, int target)
144{
145 struct regmap *regmap = rdev_get_regmap(rdev);
146 const int ramp_tables[] = { 1000, 2500, 5000, 10000 };
147 unsigned int i, sel;
148
149 /* Find closest larger or equal */
150 for (i = 0; i < ARRAY_SIZE(ramp_tables); i++) {
151 sel = i;
152
153 /* If ramp delay is equal to 0, directly set ramp speed to fastest */
154 if (target == 0) {
155 sel = ARRAY_SIZE(ramp_tables) - 1;
156 break;
157 }
158
159 if (target <= ramp_tables[i])
160 break;
161 }
162
163 sel <<= ffs(RT6160_RAMPRATE_MASK) - 1;
164
165 return regmap_update_bits(regmap, RT6160_REG_CNTL, RT6160_RAMPRATE_MASK, sel);
166}
167
168static int rt6160_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
169{
170 struct regmap *regmap = rdev_get_regmap(rdev);
171 unsigned int val, events = 0;
172 int ret;
173
174 ret = regmap_read(regmap, RT6160_REG_STATUS, &val);
175 if (ret)
176 return ret;
177
178 if (val & (RT6160_HDSTAT_MASK | RT6160_TSDSTAT_MASK))
179 events |= REGULATOR_ERROR_OVER_TEMP;
180
181 if (val & RT6160_UVSTAT_MASK)
182 events |= REGULATOR_ERROR_UNDER_VOLTAGE;
183
184 if (val & RT6160_OCSTAT_MASK)
185 events |= REGULATOR_ERROR_OVER_CURRENT;
186
187 if (val & RT6160_PGSTAT_MASK)
188 events |= REGULATOR_ERROR_FAIL;
189
190 *flags = events;
191 return 0;
192}
193
194static const struct regulator_ops rt6160_regulator_ops = {
195 .list_voltage = regulator_list_voltage_linear,
196 .set_voltage_sel = regulator_set_voltage_sel_regmap,
197 .get_voltage_sel = regulator_get_voltage_sel_regmap,
198
199 .enable = rt6160_enable,
200 .disable = rt6160_disable,
201 .is_enabled = rt6160_is_enabled,
202
203 .set_mode = rt6160_set_mode,
204 .get_mode = rt6160_get_mode,
205 .set_suspend_voltage = rt6160_set_suspend_voltage,
206 .set_ramp_delay = rt6160_set_ramp_delay,
207 .get_error_flags = rt6160_get_error_flags,
208};
209
210static unsigned int rt6160_of_map_mode(unsigned int mode)
211{
212 switch (mode) {
213 case RT6160_MODE_FPWM:
214 return REGULATOR_MODE_FAST;
215 case RT6160_MODE_AUTO:
216 return REGULATOR_MODE_NORMAL;
217 }
218
219 return REGULATOR_MODE_INVALID;
220}
221
222static bool rt6160_is_accessible_reg(struct device *dev, unsigned int reg)
223{
224 if (reg >= RT6160_REG_CNTL && reg <= RT6160_REG_VSELH)
225 return true;
226 return false;
227}
228
229static bool rt6160_is_volatile_reg(struct device *dev, unsigned int reg)
230{
231 if (reg == RT6160_REG_STATUS)
232 return true;
233 return false;
234}
235
236static const struct regmap_config rt6160_regmap_config = {
237 .reg_bits = 8,
238 .val_bits = 8,
239 .max_register = RT6160_REG_VSELH,
240 .num_reg_defaults_raw = RT6160_NUM_REGS,
241 .cache_type = REGCACHE_FLAT,
242
243 .writeable_reg = rt6160_is_accessible_reg,
244 .readable_reg = rt6160_is_accessible_reg,
245 .volatile_reg = rt6160_is_volatile_reg,
246};
247
248static int rt6160_probe(struct i2c_client *i2c)
249{
250 struct rt6160_priv *priv;
251 struct regulator_config regulator_cfg = {};
252 struct regulator_dev *rdev;
253 unsigned int devid;
254 int ret;
255
256 priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
257 if (!priv)
258 return -ENOMEM;
259
260 priv->vsel_active_low = device_property_present(&i2c->dev, "richtek,vsel-active-low");
261
262 priv->enable_gpio = devm_gpiod_get_optional(&i2c->dev, "enable", GPIOD_OUT_HIGH);
263 if (IS_ERR(priv->enable_gpio)) {
264 dev_err(&i2c->dev, "Failed to get 'enable' gpio\n");
265 return PTR_ERR(priv->enable_gpio);
266 }
267 priv->enable_state = true;
268
269 usleep_range(RT6160_I2CRDY_TIMEUS, RT6160_I2CRDY_TIMEUS + 100);
270
271 priv->regmap = devm_regmap_init_i2c(i2c, &rt6160_regmap_config);
272 if (IS_ERR(priv->regmap)) {
273 ret = PTR_ERR(priv->regmap);
274 dev_err(&i2c->dev, "Failed to init regmap (%d)\n", ret);
275 return ret;
276 }
277
278 ret = regmap_read(priv->regmap, RT6160_REG_DEVID, &devid);
279 if (ret)
280 return ret;
281
282 if ((devid & RT6160_VID_MASK) != RT6160_VENDOR_ID) {
283 dev_err(&i2c->dev, "VID not correct [0x%02x]\n", devid);
284 return -ENODEV;
285 }
286
287 priv->desc.name = "rt6160-buckboost";
288 priv->desc.type = REGULATOR_VOLTAGE;
289 priv->desc.owner = THIS_MODULE;
290 priv->desc.min_uV = RT6160_VOUT_MINUV;
291 priv->desc.uV_step = RT6160_VOUT_STPUV;
292 priv->desc.vsel_reg = RT6160_REG_VSELH;
293 priv->desc.vsel_mask = RT6160_VSEL_MASK;
294 priv->desc.n_voltages = RT6160_N_VOUTS;
295 priv->desc.of_map_mode = rt6160_of_map_mode;
296 priv->desc.ops = &rt6160_regulator_ops;
297 if (priv->vsel_active_low)
298 priv->desc.vsel_reg = RT6160_REG_VSELL;
299
300 regulator_cfg.dev = &i2c->dev;
301 regulator_cfg.of_node = i2c->dev.of_node;
302 regulator_cfg.regmap = priv->regmap;
303 regulator_cfg.driver_data = priv;
304 regulator_cfg.init_data = of_get_regulator_init_data(&i2c->dev, i2c->dev.of_node,
305 &priv->desc);
306
307 rdev = devm_regulator_register(&i2c->dev, &priv->desc, &regulator_cfg);
308 if (IS_ERR(rdev)) {
309 dev_err(&i2c->dev, "Failed to register regulator\n");
310 return PTR_ERR(rdev);
311 }
312
313 return 0;
314}
315
316static const struct of_device_id __maybe_unused rt6160_of_match_table[] = {
317 { .compatible = "richtek,rt6160", },
318 {}
319};
320MODULE_DEVICE_TABLE(of, rt6160_of_match_table);
321
322static struct i2c_driver rt6160_driver = {
323 .driver = {
324 .name = "rt6160",
325 .of_match_table = rt6160_of_match_table,
326 },
327 .probe_new = rt6160_probe,
328};
329module_i2c_driver(rt6160_driver);
330
331MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
332MODULE_LICENSE("GPL v2");