xref: /OK3568_Linux_fs/kernel/drivers/regulator/tps549b22-regulator.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2017-2018 Rockchip Electronics Co. Ltd.
3  * Author: XiaoDong Huang <derrick.huang@rock-chips.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15 
16 #include <linux/bug.h>
17 #include <linux/debugfs.h>
18 #include <linux/delay.h>
19 #include <linux/err.h>
20 #include <linux/i2c.h>
21 #include <linux/kernel.h>
22 #include <linux/mutex.h>
23 #include <linux/module.h>
24 #include <linux/of.h>
25 #include <linux/of_device.h>
26 #include <linux/regulator/of_regulator.h>
27 #include <linux/regulator/driver.h>
28 #include <linux/regulator/machine.h>
29 #include <linux/regulator/driver.h>
30 #include <linux/regmap.h>
31 #include <linux/types.h>
32 #include <linux/uaccess.h>
33 
34 #define TPS549b22_REG_OPERATION		0x01
35 #define TPS549b22_REG_ON_OFF_CFG	0x02
36 #define TPS549b22_REG_WRITE_PROTECT	0x10
37 #define TPS549b22_REG_COMMAND		0x21
38 #define TPS549b22_REG_MRG_H		0x25
39 #define TPS549b22_REG_MRG_L		0x26
40 #define TPS549b22_REG_ST_BYTE		0x78
41 #define TPS549b22_REG_MFR_SPC_44	0xfc
42 
43 #define TPS549b22_ID			0x0200
44 
45 #define VOL_MSK				0x3ff
46 #define VOL_OFF_MSK			0x40
47 #define OPERATION_ON_MSK		0x80
48 #define OPERATION_MRG_MSK		0x3c
49 #define ON_OFF_CFG_OPT_MSK		0x0c
50 #define VOL_MIN_IDX			0x133
51 #define VOL_MAX_IDX			0x266
52 #define VOL_STEP_DEF			2500
53 
54 #define VOL2REG(vol_sel, vol_step) \
55 		((vol_sel) / (vol_step) & VOL_MSK)
56 #define REG2VOL(val, vol_step) \
57 		((vol_step) * ((val) & VOL_MSK))
58 
59 #define TPS549b22_NUM_REGULATORS	1
60 
61 struct tps549b22 {
62 	struct device *dev;
63 	struct i2c_client *i2c;
64 	int num_regulators;
65 	struct regulator_dev **rdev;
66 	struct regmap *regmap_8bits;
67 	struct regmap *regmap_16bits;
68 	int vol_step;
69 };
70 
71 struct tps549b22_board {
72 	struct regulator_init_data
73 		*tps549b22_init_data[TPS549b22_NUM_REGULATORS];
74 	struct device_node *of_node[TPS549b22_NUM_REGULATORS];
75 };
76 
77 struct tps549b22_regulator_subdev {
78 	int id;
79 	struct regulator_init_data *initdata;
80 	struct device_node *reg_node;
81 };
82 
tps549b22_dcdc_list_voltage(struct regulator_dev * rdev,unsigned int index)83 static int tps549b22_dcdc_list_voltage(struct regulator_dev *rdev,
84 				       unsigned int index)
85 {
86 	struct tps549b22 *tps549b22 = rdev_get_drvdata(rdev);
87 
88 	if (index + VOL_MIN_IDX > VOL_MAX_IDX)
89 		return -EINVAL;
90 
91 	return REG2VOL(index + VOL_MIN_IDX, tps549b22->vol_step);
92 }
93 
tps549b22_reg_init(struct tps549b22 * tps549b22)94 static int tps549b22_reg_init(struct tps549b22 *tps549b22)
95 {
96 	if (regmap_update_bits(tps549b22->regmap_8bits,
97 			       TPS549b22_REG_OPERATION,
98 			       OPERATION_ON_MSK,
99 			       0x80) == 0)
100 		return regmap_update_bits(tps549b22->regmap_8bits,
101 					  TPS549b22_REG_ON_OFF_CFG,
102 					  ON_OFF_CFG_OPT_MSK,
103 					  0x0c);
104 
105 	dev_err(tps549b22->dev, "regulator init err\n");
106 
107 	return -1;
108 }
109 
tps549b22dcdc_is_enabled(struct regulator_dev * rdev)110 static int tps549b22dcdc_is_enabled(struct regulator_dev *rdev)
111 {
112 	struct tps549b22 *tps549b22 = rdev_get_drvdata(rdev);
113 	int err;
114 	u32 val;
115 
116 	err = regmap_read(tps549b22->regmap_8bits, TPS549b22_REG_ST_BYTE, &val);
117 	if (err)
118 		return 0;
119 
120 	return !(val & VOL_OFF_MSK);
121 }
122 
tps549b22dcdc_enable(struct regulator_dev * rdev)123 static int tps549b22dcdc_enable(struct regulator_dev *rdev)
124 {
125 	struct tps549b22 *tps549b22 = rdev_get_drvdata(rdev);
126 
127 	return regmap_update_bits(tps549b22->regmap_8bits,
128 				  TPS549b22_REG_OPERATION,
129 				  OPERATION_ON_MSK,
130 				  0x80);
131 }
132 
tps549b22dcdc_disable(struct regulator_dev * rdev)133 static int tps549b22dcdc_disable(struct regulator_dev *rdev)
134 {
135 	struct tps549b22 *tps549b22 = rdev_get_drvdata(rdev);
136 
137 	return regmap_update_bits(tps549b22->regmap_8bits,
138 				  TPS549b22_REG_OPERATION,
139 				  OPERATION_ON_MSK,
140 				  0);
141 }
142 
tps549b22dcdc_get_voltage(struct regulator_dev * rdev)143 static int tps549b22dcdc_get_voltage(struct regulator_dev *rdev)
144 {
145 	struct tps549b22 *tps549b22 = rdev_get_drvdata(rdev);
146 	int err;
147 	u32 val = 0;
148 
149 	err = regmap_read(tps549b22->regmap_16bits,
150 			  TPS549b22_REG_COMMAND,
151 			  &val);
152 	if (!err)
153 		return REG2VOL(val, tps549b22->vol_step);
154 
155 	return -1;
156 }
157 
tps549b22dcdc_set_voltage(struct regulator_dev * rdev,int min_uV,int max_uV,unsigned int * selector)158 static int tps549b22dcdc_set_voltage(struct regulator_dev *rdev,
159 				     int min_uV,
160 				     int max_uV,
161 				     unsigned int *selector)
162 {
163 	struct tps549b22 *tps549b22 = rdev_get_drvdata(rdev);
164 	int val;
165 	int err;
166 
167 	if (min_uV < REG2VOL(VOL_MIN_IDX, tps549b22->vol_step) ||
168 	    min_uV > REG2VOL(VOL_MAX_IDX, tps549b22->vol_step)) {
169 		dev_warn(rdev_get_dev(rdev),
170 			 "this voltage is out of limit! voltage set is %d mv\n",
171 			 REG2VOL(min_uV, tps549b22->vol_step));
172 		return -EINVAL;
173 	}
174 
175 	for (val = VOL_MIN_IDX; val <= VOL_MAX_IDX; val++)
176 		if (REG2VOL(val, tps549b22->vol_step) >= min_uV)
177 			break;
178 
179 	if (REG2VOL(val, tps549b22->vol_step) > max_uV)
180 		dev_warn(rdev_get_dev(rdev),
181 			 "this voltage is not support! voltage set is %d mv\n",
182 			 REG2VOL(val, tps549b22->vol_step));
183 
184 	err = regmap_update_bits(tps549b22->regmap_16bits,
185 				 TPS549b22_REG_COMMAND,
186 				 VOL_MSK,
187 				 val);
188 	if (err)
189 		dev_err(rdev_get_dev(rdev),
190 			"set voltage is error! voltage set is %d mv\n",
191 			REG2VOL(val, tps549b22->vol_step));
192 
193 	return err;
194 }
195 
196 static struct regulator_ops tps549b22dcdc_ops = {
197 	.set_voltage = tps549b22dcdc_set_voltage,
198 	.get_voltage = tps549b22dcdc_get_voltage,
199 	.is_enabled = tps549b22dcdc_is_enabled,
200 	.enable = tps549b22dcdc_enable,
201 	.disable = tps549b22dcdc_disable,
202 	.list_voltage = tps549b22_dcdc_list_voltage,
203 };
204 
205 static struct regulator_desc regulators[] = {
206 	{
207 		.name = "tps549b22_DCDC1",
208 		.id = 0,
209 		.ops = &tps549b22dcdc_ops,
210 		.n_voltages = VOL_MAX_IDX - VOL_MIN_IDX + 1,
211 		.type = REGULATOR_VOLTAGE,
212 		.owner = THIS_MODULE,
213 	},
214 };
215 
216 static struct of_regulator_match tps549b22_reg_matches[] = {
217 	{ .name = "tps549b22_dcdc1", .driver_data = (void *)0},
218 };
219 
220 static struct tps549b22_board *
tps549b22_parse_dt(struct tps549b22 * tps549b22)221 tps549b22_parse_dt(struct tps549b22 *tps549b22)
222 {
223 	struct tps549b22_board *pdata;
224 	struct device_node *regs;
225 	struct device_node *tps549b22_np;
226 	int count;
227 
228 	tps549b22_np = of_node_get(tps549b22->dev->of_node);
229 	if (!tps549b22_np) {
230 		pr_err("could not find pmic sub-node\n");
231 		goto err;
232 	}
233 
234 	regs = of_get_child_by_name(tps549b22_np, "regulators");
235 	if (!regs)
236 		goto err;
237 
238 	count = of_regulator_match(tps549b22->dev,
239 				   regs,
240 				   tps549b22_reg_matches,
241 				   TPS549b22_NUM_REGULATORS);
242 
243 	if (of_property_read_u32(tps549b22_reg_matches[0].of_node,
244 				 "voltage-step",
245 				 &tps549b22->vol_step))
246 		tps549b22->vol_step = VOL_STEP_DEF;
247 
248 	dev_info(tps549b22->dev, "voltage-step: %duV\n", tps549b22->vol_step);
249 
250 	of_node_put(regs);
251 	of_node_put(tps549b22_np);
252 
253 	if (count <= 0)
254 		goto err;
255 
256 	pdata = devm_kzalloc(tps549b22->dev, sizeof(*pdata), GFP_KERNEL);
257 	if (!pdata)
258 		goto err;
259 
260 	pdata->tps549b22_init_data[0] = tps549b22_reg_matches[0].init_data;
261 	pdata->of_node[0] = tps549b22_reg_matches[0].of_node;
262 
263 	return pdata;
264 
265 err:
266 	return NULL;
267 }
268 
269 static const struct of_device_id tps549b22_of_match[] = {
270 	{.compatible = "ti,tps549b22"},
271 	{ },
272 };
273 MODULE_DEVICE_TABLE(of, tps549b22_of_match);
274 
275 static const struct regmap_config tps549b22_8bits_regmap_config = {
276 	.reg_bits = 8,
277 	.val_bits = 8,
278 	.max_register = TPS549b22_REG_MFR_SPC_44 + 1,
279 	.cache_type = REGCACHE_NONE,
280 };
281 
282 static const struct regmap_config tps549b22_16bits_regmap_config = {
283 	.reg_bits = 8,
284 	.val_bits = 16,
285 	.max_register = TPS549b22_REG_MFR_SPC_44 + 1,
286 	.cache_type = REGCACHE_NONE,
287 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
288 };
289 
tps549b22_i2c_probe(struct i2c_client * i2c,const struct i2c_device_id * id)290 static int tps549b22_i2c_probe(struct i2c_client *i2c,
291 			       const struct i2c_device_id *id)
292 {
293 	struct tps549b22 *tps549b22;
294 	struct tps549b22_board *pdev = NULL;
295 	const struct of_device_id *match;
296 	struct regulator_config config = { };
297 	struct regulator_dev *rdev;
298 	struct regulator_init_data *reg_data;
299 	int ret;
300 	u32 val;
301 
302 	if (i2c->dev.of_node) {
303 		match = of_match_device(tps549b22_of_match, &i2c->dev);
304 		if (!match) {
305 			pr_err("Failed to find matching dt id\n");
306 			return -EINVAL;
307 		}
308 	}
309 
310 	tps549b22 = devm_kzalloc(&i2c->dev,
311 				 sizeof(struct tps549b22),
312 				 GFP_KERNEL);
313 	if (!tps549b22) {
314 		ret = -ENOMEM;
315 		goto err;
316 	}
317 
318 	tps549b22->regmap_8bits =
319 		devm_regmap_init_i2c(i2c, &tps549b22_8bits_regmap_config);
320 	if (IS_ERR(tps549b22->regmap_8bits)) {
321 		dev_err(&i2c->dev, "8 bits regmap initialization failed\n");
322 		return PTR_ERR(tps549b22->regmap_8bits);
323 	}
324 
325 	tps549b22->regmap_16bits =
326 		devm_regmap_init_i2c(i2c, &tps549b22_16bits_regmap_config);
327 	if (IS_ERR(tps549b22->regmap_16bits)) {
328 		dev_err(&i2c->dev, "16 bits regmap initialization failed\n");
329 		return PTR_ERR(tps549b22->regmap_16bits);
330 	}
331 
332 	tps549b22->i2c = i2c;
333 	tps549b22->dev = &i2c->dev;
334 	i2c_set_clientdata(i2c, tps549b22);
335 
336 	ret = regmap_read(tps549b22->regmap_16bits,
337 			  TPS549b22_REG_MFR_SPC_44,
338 			  &val);
339 	if (!ret) {
340 		if (val != TPS549b22_ID)
341 			dev_warn(tps549b22->dev,
342 				 "The device is not tps549b22 0x%x\n",
343 				 val);
344 	} else {
345 		dev_err(tps549b22->dev,
346 			"Tps549b22_reg_read err, ret = %d\n",
347 			ret);
348 		return -EINVAL;
349 	}
350 
351 	tps549b22_reg_init(tps549b22);
352 
353 	if (tps549b22->dev->of_node)
354 		pdev = tps549b22_parse_dt(tps549b22);
355 
356 	if (pdev) {
357 		tps549b22->num_regulators = TPS549b22_NUM_REGULATORS;
358 		tps549b22->rdev =
359 			devm_kmalloc_array(tps549b22->dev,
360 					   TPS549b22_NUM_REGULATORS,
361 					   sizeof(struct regulator_dev *),
362 					   GFP_KERNEL);
363 		if (!tps549b22->rdev)
364 			return -ENOMEM;
365 
366 		/* Instantiate the regulators */
367 		reg_data = pdev->tps549b22_init_data[0];
368 		config.dev = tps549b22->dev;
369 		config.driver_data = tps549b22;
370 		if (tps549b22->dev->of_node)
371 			config.of_node = pdev->of_node[0];
372 
373 		config.init_data = reg_data;
374 
375 		rdev = devm_regulator_register(tps549b22->dev,
376 					       &regulators[0],
377 					       &config);
378 		if (IS_ERR(rdev)) {
379 			pr_err("failed to register regulator\n");
380 			goto err;
381 		}
382 
383 		tps549b22->rdev[0] = rdev;
384 	}
385 
386 	return 0;
387 err:
388 	return ret;
389 }
390 
tps549b22_i2c_remove(struct i2c_client * i2c)391 static int tps549b22_i2c_remove(struct i2c_client *i2c)
392 {
393 	i2c_set_clientdata(i2c, NULL);
394 
395 	return 0;
396 }
397 
398 static const struct i2c_device_id tps549b22_i2c_id[] = {
399 	{"tps549b22", 0},
400 	{ }
401 };
402 
403 MODULE_DEVICE_TABLE(i2c, tps549b22_i2c_id);
404 
405 static struct i2c_driver tps549b22_i2c_driver = {
406 	.driver = {
407 		.name = "tps549b22",
408 		.of_match_table = of_match_ptr(tps549b22_of_match),
409 	},
410 	.probe = tps549b22_i2c_probe,
411 	.remove = tps549b22_i2c_remove,
412 	.id_table = tps549b22_i2c_id,
413 };
414 
tps549b22_module_init(void)415 static int __init tps549b22_module_init(void)
416 {
417 	int ret;
418 
419 	ret = i2c_add_driver(&tps549b22_i2c_driver);
420 
421 	if (ret != 0)
422 		pr_err("Failed to register I2C driver: %d\n", ret);
423 
424 	return ret;
425 }
426 subsys_initcall_sync(tps549b22_module_init);
427 
tps549b22_module_exit(void)428 static void __exit tps549b22_module_exit(void)
429 {
430 	i2c_del_driver(&tps549b22_i2c_driver);
431 }
432 module_exit(tps549b22_module_exit);
433 
434 MODULE_LICENSE("GPL");
435 
436 MODULE_AUTHOR("derrick.huang@rock-chips.com");
437 MODULE_DESCRIPTION("   tps549b22 dcdc driver");
438