xref: /linux/drivers/power/supply/rn5t618_power.c (revision 4fd18fc38757217c746aa063ba9e4729814dc737)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Power supply driver for the RICOH RN5T618 power management chip family
4  *
5  * Copyright (C) 2020 Andreas Kemnade
6  */
7 
8 #include <linux/kernel.h>
9 #include <linux/device.h>
10 #include <linux/bitops.h>
11 #include <linux/errno.h>
12 #include <linux/init.h>
13 #include <linux/interrupt.h>
14 #include <linux/module.h>
15 #include <linux/mfd/rn5t618.h>
16 #include <linux/platform_device.h>
17 #include <linux/power_supply.h>
18 #include <linux/regmap.h>
19 #include <linux/slab.h>
20 
21 #define CHG_STATE_ADP_INPUT 0x40
22 #define CHG_STATE_USB_INPUT 0x80
23 #define CHG_STATE_MASK	0x1f
24 #define CHG_STATE_CHG_OFF	0
25 #define CHG_STATE_CHG_READY_VADP	1
26 #define CHG_STATE_CHG_TRICKLE	2
27 #define CHG_STATE_CHG_RAPID	3
28 #define CHG_STATE_CHG_COMPLETE	4
29 #define CHG_STATE_SUSPEND	5
30 #define CHG_STATE_VCHG_OVER_VOL	6
31 #define CHG_STATE_BAT_ERROR	7
32 #define CHG_STATE_NO_BAT	8
33 #define CHG_STATE_BAT_OVER_VOL	9
34 #define CHG_STATE_BAT_TEMP_ERR	10
35 #define CHG_STATE_DIE_ERR	11
36 #define CHG_STATE_DIE_SHUTDOWN	12
37 #define CHG_STATE_NO_BAT2	13
38 #define CHG_STATE_CHG_READY_VUSB	14
39 
40 #define FG_ENABLE 1
41 
42 struct rn5t618_power_info {
43 	struct rn5t618 *rn5t618;
44 	struct platform_device *pdev;
45 	struct power_supply *battery;
46 	struct power_supply *usb;
47 	struct power_supply *adp;
48 	int irq;
49 };
50 
51 static enum power_supply_property rn5t618_usb_props[] = {
52 	POWER_SUPPLY_PROP_STATUS,
53 	POWER_SUPPLY_PROP_ONLINE,
54 };
55 
56 static enum power_supply_property rn5t618_adp_props[] = {
57 	POWER_SUPPLY_PROP_STATUS,
58 	POWER_SUPPLY_PROP_ONLINE,
59 };
60 
61 
62 static enum power_supply_property rn5t618_battery_props[] = {
63 	POWER_SUPPLY_PROP_STATUS,
64 	POWER_SUPPLY_PROP_PRESENT,
65 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
66 	POWER_SUPPLY_PROP_CURRENT_NOW,
67 	POWER_SUPPLY_PROP_CAPACITY,
68 	POWER_SUPPLY_PROP_TEMP,
69 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
70 	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
71 	POWER_SUPPLY_PROP_TECHNOLOGY,
72 	POWER_SUPPLY_PROP_CHARGE_FULL,
73 	POWER_SUPPLY_PROP_CHARGE_NOW,
74 };
75 
76 static int rn5t618_battery_read_doublereg(struct rn5t618_power_info *info,
77 					  u8 reg, u16 *result)
78 {
79 	int ret, i;
80 	u8 data[2];
81 	u16 old, new;
82 
83 	old = 0;
84 	/* Prevent races when registers are changing. */
85 	for (i = 0; i < 3; i++) {
86 		ret = regmap_bulk_read(info->rn5t618->regmap,
87 				       reg, data, sizeof(data));
88 		if (ret)
89 			return ret;
90 
91 		new = data[0] << 8;
92 		new |= data[1];
93 		if (new == old)
94 			break;
95 
96 		old = new;
97 	}
98 
99 	*result = new;
100 
101 	return 0;
102 }
103 
104 static int rn5t618_decode_status(unsigned int status)
105 {
106 	switch (status & CHG_STATE_MASK) {
107 	case CHG_STATE_CHG_OFF:
108 	case CHG_STATE_SUSPEND:
109 	case CHG_STATE_VCHG_OVER_VOL:
110 	case CHG_STATE_DIE_SHUTDOWN:
111 		return POWER_SUPPLY_STATUS_DISCHARGING;
112 
113 	case CHG_STATE_CHG_TRICKLE:
114 	case CHG_STATE_CHG_RAPID:
115 		return POWER_SUPPLY_STATUS_CHARGING;
116 
117 	case CHG_STATE_CHG_COMPLETE:
118 		return POWER_SUPPLY_STATUS_FULL;
119 
120 	default:
121 		return POWER_SUPPLY_STATUS_NOT_CHARGING;
122 	}
123 }
124 
125 static int rn5t618_battery_status(struct rn5t618_power_info *info,
126 				  union power_supply_propval *val)
127 {
128 	unsigned int v;
129 	int ret;
130 
131 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &v);
132 	if (ret)
133 		return ret;
134 
135 	val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
136 
137 	if (v & 0xc0) { /* USB or ADP plugged */
138 		val->intval = rn5t618_decode_status(v);
139 	} else
140 		val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
141 
142 	return ret;
143 }
144 
145 static int rn5t618_battery_present(struct rn5t618_power_info *info,
146 				   union power_supply_propval *val)
147 {
148 	unsigned int v;
149 	int ret;
150 
151 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &v);
152 	if (ret)
153 		return ret;
154 
155 	v &= CHG_STATE_MASK;
156 	if ((v == CHG_STATE_NO_BAT) || (v == CHG_STATE_NO_BAT2))
157 		val->intval = 0;
158 	else
159 		val->intval = 1;
160 
161 	return ret;
162 }
163 
164 static int rn5t618_battery_voltage_now(struct rn5t618_power_info *info,
165 				       union power_supply_propval *val)
166 {
167 	u16 res;
168 	int ret;
169 
170 	ret = rn5t618_battery_read_doublereg(info, RN5T618_VOLTAGE_1, &res);
171 	if (ret)
172 		return ret;
173 
174 	val->intval = res * 2 * 2500 / 4095 * 1000;
175 
176 	return 0;
177 }
178 
179 static int rn5t618_battery_current_now(struct rn5t618_power_info *info,
180 				       union power_supply_propval *val)
181 {
182 	u16 res;
183 	int ret;
184 
185 	ret = rn5t618_battery_read_doublereg(info, RN5T618_CC_AVEREG1, &res);
186 	if (ret)
187 		return ret;
188 
189 	/* current is negative when discharging */
190 	val->intval = sign_extend32(res, 13) * 1000;
191 
192 	return 0;
193 }
194 
195 static int rn5t618_battery_capacity(struct rn5t618_power_info *info,
196 				    union power_supply_propval *val)
197 {
198 	unsigned int v;
199 	int ret;
200 
201 	ret = regmap_read(info->rn5t618->regmap, RN5T618_SOC, &v);
202 	if (ret)
203 		return ret;
204 
205 	val->intval = v;
206 
207 	return 0;
208 }
209 
210 static int rn5t618_battery_temp(struct rn5t618_power_info *info,
211 				union power_supply_propval *val)
212 {
213 	u16 res;
214 	int ret;
215 
216 	ret = rn5t618_battery_read_doublereg(info, RN5T618_TEMP_1, &res);
217 	if (ret)
218 		return ret;
219 
220 	val->intval = sign_extend32(res, 11) * 10 / 16;
221 
222 	return 0;
223 }
224 
225 static int rn5t618_battery_tte(struct rn5t618_power_info *info,
226 			       union power_supply_propval *val)
227 {
228 	u16 res;
229 	int ret;
230 
231 	ret = rn5t618_battery_read_doublereg(info, RN5T618_TT_EMPTY_H, &res);
232 	if (ret)
233 		return ret;
234 
235 	if (res == 65535)
236 		return -ENODATA;
237 
238 	val->intval = res * 60;
239 
240 	return 0;
241 }
242 
243 static int rn5t618_battery_ttf(struct rn5t618_power_info *info,
244 			       union power_supply_propval *val)
245 {
246 	u16 res;
247 	int ret;
248 
249 	ret = rn5t618_battery_read_doublereg(info, RN5T618_TT_FULL_H, &res);
250 	if (ret)
251 		return ret;
252 
253 	if (res == 65535)
254 		return -ENODATA;
255 
256 	val->intval = res * 60;
257 
258 	return 0;
259 }
260 
261 static int rn5t618_battery_charge_full(struct rn5t618_power_info *info,
262 				       union power_supply_propval *val)
263 {
264 	u16 res;
265 	int ret;
266 
267 	ret = rn5t618_battery_read_doublereg(info, RN5T618_FA_CAP_H, &res);
268 	if (ret)
269 		return ret;
270 
271 	val->intval = res * 1000;
272 
273 	return 0;
274 }
275 
276 static int rn5t618_battery_charge_now(struct rn5t618_power_info *info,
277 				      union power_supply_propval *val)
278 {
279 	u16 res;
280 	int ret;
281 
282 	ret = rn5t618_battery_read_doublereg(info, RN5T618_RE_CAP_H, &res);
283 	if (ret)
284 		return ret;
285 
286 	val->intval = res * 1000;
287 
288 	return 0;
289 }
290 
291 static int rn5t618_battery_get_property(struct power_supply *psy,
292 					enum power_supply_property psp,
293 					union power_supply_propval *val)
294 {
295 	int ret = 0;
296 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
297 
298 	switch (psp) {
299 	case POWER_SUPPLY_PROP_STATUS:
300 		ret = rn5t618_battery_status(info, val);
301 		break;
302 	case POWER_SUPPLY_PROP_PRESENT:
303 		ret = rn5t618_battery_present(info, val);
304 		break;
305 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
306 		ret = rn5t618_battery_voltage_now(info, val);
307 		break;
308 	case POWER_SUPPLY_PROP_CURRENT_NOW:
309 		ret = rn5t618_battery_current_now(info, val);
310 		break;
311 	case POWER_SUPPLY_PROP_CAPACITY:
312 		ret = rn5t618_battery_capacity(info, val);
313 		break;
314 	case POWER_SUPPLY_PROP_TEMP:
315 		ret = rn5t618_battery_temp(info, val);
316 		break;
317 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
318 		ret = rn5t618_battery_tte(info, val);
319 		break;
320 	case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
321 		ret = rn5t618_battery_ttf(info, val);
322 		break;
323 	case POWER_SUPPLY_PROP_TECHNOLOGY:
324 		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
325 		break;
326 	case POWER_SUPPLY_PROP_CHARGE_FULL:
327 		ret = rn5t618_battery_charge_full(info, val);
328 		break;
329 	case POWER_SUPPLY_PROP_CHARGE_NOW:
330 		ret = rn5t618_battery_charge_now(info, val);
331 		break;
332 	default:
333 		return -EINVAL;
334 	}
335 
336 	return ret;
337 }
338 
339 static int rn5t618_adp_get_property(struct power_supply *psy,
340 				    enum power_supply_property psp,
341 				    union power_supply_propval *val)
342 {
343 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
344 	unsigned int chgstate;
345 	bool online;
346 	int ret;
347 
348 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &chgstate);
349 	if (ret)
350 		return ret;
351 
352 	online = !!(chgstate & CHG_STATE_ADP_INPUT);
353 
354 	switch (psp) {
355 	case POWER_SUPPLY_PROP_ONLINE:
356 		val->intval = online;
357 		break;
358 	case POWER_SUPPLY_PROP_STATUS:
359 		if (!online) {
360 			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
361 			break;
362 		}
363 		val->intval = rn5t618_decode_status(chgstate);
364 		if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
365 			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
366 
367 		break;
368 	default:
369 		return -EINVAL;
370 	}
371 
372 	return 0;
373 }
374 
375 static int rn5t618_usb_get_property(struct power_supply *psy,
376 				    enum power_supply_property psp,
377 				    union power_supply_propval *val)
378 {
379 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
380 	unsigned int chgstate;
381 	bool online;
382 	int ret;
383 
384 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &chgstate);
385 	if (ret)
386 		return ret;
387 
388 	online = !!(chgstate & CHG_STATE_USB_INPUT);
389 
390 	switch (psp) {
391 	case POWER_SUPPLY_PROP_ONLINE:
392 		val->intval = online;
393 		break;
394 	case POWER_SUPPLY_PROP_STATUS:
395 		if (!online) {
396 			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
397 			break;
398 		}
399 		val->intval = rn5t618_decode_status(chgstate);
400 		if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
401 			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
402 
403 		break;
404 	default:
405 		return -EINVAL;
406 	}
407 
408 	return 0;
409 }
410 
411 static const struct power_supply_desc rn5t618_battery_desc = {
412 	.name                   = "rn5t618-battery",
413 	.type                   = POWER_SUPPLY_TYPE_BATTERY,
414 	.properties             = rn5t618_battery_props,
415 	.num_properties         = ARRAY_SIZE(rn5t618_battery_props),
416 	.get_property           = rn5t618_battery_get_property,
417 };
418 
419 static const struct power_supply_desc rn5t618_adp_desc = {
420 	.name                   = "rn5t618-adp",
421 	.type                   = POWER_SUPPLY_TYPE_MAINS,
422 	.properties             = rn5t618_adp_props,
423 	.num_properties         = ARRAY_SIZE(rn5t618_adp_props),
424 	.get_property           = rn5t618_adp_get_property,
425 };
426 
427 static const struct power_supply_desc rn5t618_usb_desc = {
428 	.name                   = "rn5t618-usb",
429 	.type                   = POWER_SUPPLY_TYPE_USB,
430 	.properties             = rn5t618_usb_props,
431 	.num_properties         = ARRAY_SIZE(rn5t618_usb_props),
432 	.get_property           = rn5t618_usb_get_property,
433 };
434 
435 static irqreturn_t rn5t618_charger_irq(int irq, void *data)
436 {
437 	struct device *dev = data;
438 	struct rn5t618_power_info *info = dev_get_drvdata(dev);
439 
440 	unsigned int ctrl, stat1, stat2, err;
441 
442 	regmap_read(info->rn5t618->regmap, RN5T618_CHGERR_IRR, &err);
443 	regmap_read(info->rn5t618->regmap, RN5T618_CHGCTRL_IRR, &ctrl);
444 	regmap_read(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR1, &stat1);
445 	regmap_read(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR2, &stat2);
446 
447 	regmap_write(info->rn5t618->regmap, RN5T618_CHGERR_IRR, 0);
448 	regmap_write(info->rn5t618->regmap, RN5T618_CHGCTRL_IRR, 0);
449 	regmap_write(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR1, 0);
450 	regmap_write(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR2, 0);
451 
452 	dev_dbg(dev, "chgerr: %x chgctrl: %x chgstat: %x chgstat2: %x\n",
453 		err, ctrl, stat1, stat2);
454 
455 	power_supply_changed(info->usb);
456 	power_supply_changed(info->adp);
457 	power_supply_changed(info->battery);
458 
459 	return IRQ_HANDLED;
460 }
461 
462 static int rn5t618_power_probe(struct platform_device *pdev)
463 {
464 	int ret = 0;
465 	unsigned int v;
466 	struct power_supply_config psy_cfg = {};
467 	struct rn5t618_power_info *info;
468 
469 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
470 	if (!info)
471 		return -ENOMEM;
472 
473 	info->pdev = pdev;
474 	info->rn5t618 = dev_get_drvdata(pdev->dev.parent);
475 	info->irq = -1;
476 
477 	platform_set_drvdata(pdev, info);
478 
479 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CONTROL, &v);
480 	if (ret)
481 		return ret;
482 
483 	if (!(v & FG_ENABLE)) {
484 		/* E.g. the vendor kernels of various Kobo and Tolino Ebook
485 		 * readers disable the fuel gauge on shutdown. If a kernel
486 		 * without fuel gauge support is booted after that, the fuel
487 		 * gauge will get decalibrated.
488 		 */
489 		dev_info(&pdev->dev, "Fuel gauge not enabled, enabling now\n");
490 		dev_info(&pdev->dev, "Expect imprecise results\n");
491 		regmap_update_bits(info->rn5t618->regmap, RN5T618_CONTROL,
492 				   FG_ENABLE, FG_ENABLE);
493 	}
494 
495 	psy_cfg.drv_data = info;
496 	info->battery = devm_power_supply_register(&pdev->dev,
497 						   &rn5t618_battery_desc,
498 						   &psy_cfg);
499 	if (IS_ERR(info->battery)) {
500 		ret = PTR_ERR(info->battery);
501 		dev_err(&pdev->dev, "failed to register battery: %d\n", ret);
502 		return ret;
503 	}
504 
505 	info->adp = devm_power_supply_register(&pdev->dev,
506 					       &rn5t618_adp_desc,
507 					       &psy_cfg);
508 	if (IS_ERR(info->adp)) {
509 		ret = PTR_ERR(info->adp);
510 		dev_err(&pdev->dev, "failed to register adp: %d\n", ret);
511 		return ret;
512 	}
513 
514 	info->usb = devm_power_supply_register(&pdev->dev,
515 					       &rn5t618_usb_desc,
516 					       &psy_cfg);
517 	if (IS_ERR(info->usb)) {
518 		ret = PTR_ERR(info->usb);
519 		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
520 		return ret;
521 	}
522 
523 	if (info->rn5t618->irq_data)
524 		info->irq = regmap_irq_get_virq(info->rn5t618->irq_data,
525 						RN5T618_IRQ_CHG);
526 
527 	if (info->irq < 0)
528 		info->irq = -1;
529 	else {
530 		ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
531 						rn5t618_charger_irq,
532 						IRQF_ONESHOT,
533 						"rn5t618_power",
534 						&pdev->dev);
535 
536 		if (ret < 0) {
537 			dev_err(&pdev->dev, "request IRQ:%d fail\n",
538 				info->irq);
539 			info->irq = -1;
540 		}
541 	}
542 
543 	return 0;
544 }
545 
546 static struct platform_driver rn5t618_power_driver = {
547 	.driver = {
548 		.name   = "rn5t618-power",
549 	},
550 	.probe = rn5t618_power_probe,
551 };
552 
553 module_platform_driver(rn5t618_power_driver);
554 MODULE_ALIAS("platform:rn5t618-power");
555 MODULE_DESCRIPTION("Power supply driver for RICOH RN5T618");
556 MODULE_LICENSE("GPL");
557