xref: /linux/drivers/power/supply/rn5t618_power.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
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/iio/consumer.h>
13 #include <linux/init.h>
14 #include <linux/interrupt.h>
15 #include <linux/module.h>
16 #include <linux/mfd/rn5t618.h>
17 #include <linux/platform_device.h>
18 #include <linux/power_supply.h>
19 #include <linux/regmap.h>
20 #include <linux/slab.h>
21 
22 #define CHG_STATE_ADP_INPUT 0x40
23 #define CHG_STATE_USB_INPUT 0x80
24 #define CHG_STATE_MASK	0x1f
25 #define CHG_STATE_CHG_OFF	0
26 #define CHG_STATE_CHG_READY_VADP	1
27 #define CHG_STATE_CHG_TRICKLE	2
28 #define CHG_STATE_CHG_RAPID	3
29 #define CHG_STATE_CHG_COMPLETE	4
30 #define CHG_STATE_SUSPEND	5
31 #define CHG_STATE_VCHG_OVER_VOL	6
32 #define CHG_STATE_BAT_ERROR	7
33 #define CHG_STATE_NO_BAT	8
34 #define CHG_STATE_BAT_OVER_VOL	9
35 #define CHG_STATE_BAT_TEMP_ERR	10
36 #define CHG_STATE_DIE_ERR	11
37 #define CHG_STATE_DIE_SHUTDOWN	12
38 #define CHG_STATE_NO_BAT2	13
39 #define CHG_STATE_CHG_READY_VUSB	14
40 
41 #define GCHGDET_TYPE_MASK 0x30
42 #define GCHGDET_TYPE_SDP 0x00
43 #define GCHGDET_TYPE_CDP 0x10
44 #define GCHGDET_TYPE_DCP 0x20
45 
46 #define FG_ENABLE 1
47 
48 /*
49  * Formula seems accurate for battery current, but for USB current around 70mA
50  * per step was seen on Kobo Clara HD but all sources show the same formula
51  * also fur USB current. To avoid accidentially unwanted high currents we stick
52  * to that formula
53  */
54 #define TO_CUR_REG(x) ((x) / 100000 - 1)
55 #define FROM_CUR_REG(x) ((((x) & 0x1f) + 1) * 100000)
56 #define CHG_MIN_CUR 100000
57 #define CHG_MAX_CUR 1800000
58 #define ADP_MAX_CUR 2500000
59 #define USB_MAX_CUR 1400000
60 
61 
62 struct rn5t618_power_info {
63 	struct rn5t618 *rn5t618;
64 	struct platform_device *pdev;
65 	struct power_supply *battery;
66 	struct power_supply *usb;
67 	struct power_supply *adp;
68 	struct iio_channel *channel_vusb;
69 	struct iio_channel *channel_vadp;
70 	int irq;
71 };
72 
73 static enum power_supply_property rn5t618_usb_props[] = {
74 	/* input current limit is not very accurate */
75 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
76 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
77 	POWER_SUPPLY_PROP_STATUS,
78 	POWER_SUPPLY_PROP_USB_TYPE,
79 	POWER_SUPPLY_PROP_ONLINE,
80 };
81 
82 static enum power_supply_property rn5t618_adp_props[] = {
83 	/* input current limit is not very accurate */
84 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
85 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
86 	POWER_SUPPLY_PROP_STATUS,
87 	POWER_SUPPLY_PROP_ONLINE,
88 };
89 
90 
91 static enum power_supply_property rn5t618_battery_props[] = {
92 	POWER_SUPPLY_PROP_STATUS,
93 	POWER_SUPPLY_PROP_PRESENT,
94 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
95 	POWER_SUPPLY_PROP_CURRENT_NOW,
96 	POWER_SUPPLY_PROP_CAPACITY,
97 	POWER_SUPPLY_PROP_TEMP,
98 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
99 	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
100 	POWER_SUPPLY_PROP_TECHNOLOGY,
101 	POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
102 	POWER_SUPPLY_PROP_CHARGE_FULL,
103 	POWER_SUPPLY_PROP_CHARGE_NOW,
104 };
105 
rn5t618_battery_read_doublereg(struct rn5t618_power_info * info,u8 reg,u16 * result)106 static int rn5t618_battery_read_doublereg(struct rn5t618_power_info *info,
107 					  u8 reg, u16 *result)
108 {
109 	int ret, i;
110 	u8 data[2];
111 	u16 old, new;
112 
113 	old = 0;
114 	/* Prevent races when registers are changing. */
115 	for (i = 0; i < 3; i++) {
116 		ret = regmap_bulk_read(info->rn5t618->regmap,
117 				       reg, data, sizeof(data));
118 		if (ret)
119 			return ret;
120 
121 		new = data[0] << 8;
122 		new |= data[1];
123 		if (new == old)
124 			break;
125 
126 		old = new;
127 	}
128 
129 	*result = new;
130 
131 	return 0;
132 }
133 
rn5t618_decode_status(unsigned int status)134 static int rn5t618_decode_status(unsigned int status)
135 {
136 	switch (status & CHG_STATE_MASK) {
137 	case CHG_STATE_CHG_OFF:
138 	case CHG_STATE_SUSPEND:
139 	case CHG_STATE_VCHG_OVER_VOL:
140 	case CHG_STATE_DIE_SHUTDOWN:
141 		return POWER_SUPPLY_STATUS_DISCHARGING;
142 
143 	case CHG_STATE_CHG_TRICKLE:
144 	case CHG_STATE_CHG_RAPID:
145 		return POWER_SUPPLY_STATUS_CHARGING;
146 
147 	case CHG_STATE_CHG_COMPLETE:
148 		return POWER_SUPPLY_STATUS_FULL;
149 
150 	default:
151 		return POWER_SUPPLY_STATUS_NOT_CHARGING;
152 	}
153 }
154 
rn5t618_battery_status(struct rn5t618_power_info * info,union power_supply_propval * val)155 static int rn5t618_battery_status(struct rn5t618_power_info *info,
156 				  union power_supply_propval *val)
157 {
158 	unsigned int v;
159 	int ret;
160 
161 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &v);
162 	if (ret)
163 		return ret;
164 
165 	val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
166 
167 	if (v & 0xc0) { /* USB or ADP plugged */
168 		val->intval = rn5t618_decode_status(v);
169 	} else
170 		val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
171 
172 	return ret;
173 }
174 
rn5t618_battery_present(struct rn5t618_power_info * info,union power_supply_propval * val)175 static int rn5t618_battery_present(struct rn5t618_power_info *info,
176 				   union power_supply_propval *val)
177 {
178 	unsigned int v;
179 	int ret;
180 
181 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &v);
182 	if (ret)
183 		return ret;
184 
185 	v &= CHG_STATE_MASK;
186 	if ((v == CHG_STATE_NO_BAT) || (v == CHG_STATE_NO_BAT2))
187 		val->intval = 0;
188 	else
189 		val->intval = 1;
190 
191 	return ret;
192 }
193 
rn5t618_battery_voltage_now(struct rn5t618_power_info * info,union power_supply_propval * val)194 static int rn5t618_battery_voltage_now(struct rn5t618_power_info *info,
195 				       union power_supply_propval *val)
196 {
197 	u16 res;
198 	int ret;
199 
200 	ret = rn5t618_battery_read_doublereg(info, RN5T618_VOLTAGE_1, &res);
201 	if (ret)
202 		return ret;
203 
204 	val->intval = res * 2 * 2500 / 4095 * 1000;
205 
206 	return 0;
207 }
208 
rn5t618_battery_current_now(struct rn5t618_power_info * info,union power_supply_propval * val)209 static int rn5t618_battery_current_now(struct rn5t618_power_info *info,
210 				       union power_supply_propval *val)
211 {
212 	u16 res;
213 	int ret;
214 
215 	ret = rn5t618_battery_read_doublereg(info, RN5T618_CC_AVEREG1, &res);
216 	if (ret)
217 		return ret;
218 
219 	/* current is negative when discharging */
220 	val->intval = sign_extend32(res, 13) * 1000;
221 
222 	return 0;
223 }
224 
rn5t618_battery_capacity(struct rn5t618_power_info * info,union power_supply_propval * val)225 static int rn5t618_battery_capacity(struct rn5t618_power_info *info,
226 				    union power_supply_propval *val)
227 {
228 	unsigned int v;
229 	int ret;
230 
231 	ret = regmap_read(info->rn5t618->regmap, RN5T618_SOC, &v);
232 	if (ret)
233 		return ret;
234 
235 	val->intval = v;
236 
237 	return 0;
238 }
239 
rn5t618_battery_temp(struct rn5t618_power_info * info,union power_supply_propval * val)240 static int rn5t618_battery_temp(struct rn5t618_power_info *info,
241 				union power_supply_propval *val)
242 {
243 	u16 res;
244 	int ret;
245 
246 	ret = rn5t618_battery_read_doublereg(info, RN5T618_TEMP_1, &res);
247 	if (ret)
248 		return ret;
249 
250 	val->intval = sign_extend32(res, 11) * 10 / 16;
251 
252 	return 0;
253 }
254 
rn5t618_battery_tte(struct rn5t618_power_info * info,union power_supply_propval * val)255 static int rn5t618_battery_tte(struct rn5t618_power_info *info,
256 			       union power_supply_propval *val)
257 {
258 	u16 res;
259 	int ret;
260 
261 	ret = rn5t618_battery_read_doublereg(info, RN5T618_TT_EMPTY_H, &res);
262 	if (ret)
263 		return ret;
264 
265 	if (res == 65535)
266 		return -ENODATA;
267 
268 	val->intval = res * 60;
269 
270 	return 0;
271 }
272 
rn5t618_battery_ttf(struct rn5t618_power_info * info,union power_supply_propval * val)273 static int rn5t618_battery_ttf(struct rn5t618_power_info *info,
274 			       union power_supply_propval *val)
275 {
276 	u16 res;
277 	int ret;
278 
279 	ret = rn5t618_battery_read_doublereg(info, RN5T618_TT_FULL_H, &res);
280 	if (ret)
281 		return ret;
282 
283 	if (res == 65535)
284 		return -ENODATA;
285 
286 	val->intval = res * 60;
287 
288 	return 0;
289 }
290 
rn5t618_battery_set_current_limit(struct rn5t618_power_info * info,const union power_supply_propval * val)291 static int rn5t618_battery_set_current_limit(struct rn5t618_power_info *info,
292 				const union power_supply_propval *val)
293 {
294 	if (val->intval < CHG_MIN_CUR)
295 		return -EINVAL;
296 
297 	if (val->intval >= CHG_MAX_CUR)
298 		return -EINVAL;
299 
300 	return regmap_update_bits(info->rn5t618->regmap,
301 				  RN5T618_CHGISET,
302 				  0x1F, TO_CUR_REG(val->intval));
303 }
304 
rn5t618_battery_get_current_limit(struct rn5t618_power_info * info,union power_supply_propval * val)305 static int rn5t618_battery_get_current_limit(struct rn5t618_power_info *info,
306 					     union power_supply_propval *val)
307 {
308 	unsigned int regval;
309 	int ret;
310 
311 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGISET,
312 			  &regval);
313 	if (ret < 0)
314 		return ret;
315 
316 	val->intval = FROM_CUR_REG(regval);
317 
318 	return 0;
319 }
320 
rn5t618_battery_charge_full(struct rn5t618_power_info * info,union power_supply_propval * val)321 static int rn5t618_battery_charge_full(struct rn5t618_power_info *info,
322 				       union power_supply_propval *val)
323 {
324 	u16 res;
325 	int ret;
326 
327 	ret = rn5t618_battery_read_doublereg(info, RN5T618_FA_CAP_H, &res);
328 	if (ret)
329 		return ret;
330 
331 	val->intval = res * 1000;
332 
333 	return 0;
334 }
335 
rn5t618_battery_charge_now(struct rn5t618_power_info * info,union power_supply_propval * val)336 static int rn5t618_battery_charge_now(struct rn5t618_power_info *info,
337 				      union power_supply_propval *val)
338 {
339 	u16 res;
340 	int ret;
341 
342 	ret = rn5t618_battery_read_doublereg(info, RN5T618_RE_CAP_H, &res);
343 	if (ret)
344 		return ret;
345 
346 	val->intval = res * 1000;
347 
348 	return 0;
349 }
350 
rn5t618_battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)351 static int rn5t618_battery_get_property(struct power_supply *psy,
352 					enum power_supply_property psp,
353 					union power_supply_propval *val)
354 {
355 	int ret = 0;
356 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
357 
358 	switch (psp) {
359 	case POWER_SUPPLY_PROP_STATUS:
360 		ret = rn5t618_battery_status(info, val);
361 		break;
362 	case POWER_SUPPLY_PROP_PRESENT:
363 		ret = rn5t618_battery_present(info, val);
364 		break;
365 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
366 		ret = rn5t618_battery_voltage_now(info, val);
367 		break;
368 	case POWER_SUPPLY_PROP_CURRENT_NOW:
369 		ret = rn5t618_battery_current_now(info, val);
370 		break;
371 	case POWER_SUPPLY_PROP_CAPACITY:
372 		ret = rn5t618_battery_capacity(info, val);
373 		break;
374 	case POWER_SUPPLY_PROP_TEMP:
375 		ret = rn5t618_battery_temp(info, val);
376 		break;
377 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
378 		ret = rn5t618_battery_tte(info, val);
379 		break;
380 	case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
381 		ret = rn5t618_battery_ttf(info, val);
382 		break;
383 	case POWER_SUPPLY_PROP_TECHNOLOGY:
384 		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
385 		break;
386 	case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
387 		ret = rn5t618_battery_get_current_limit(info, val);
388 		break;
389 	case POWER_SUPPLY_PROP_CHARGE_FULL:
390 		ret = rn5t618_battery_charge_full(info, val);
391 		break;
392 	case POWER_SUPPLY_PROP_CHARGE_NOW:
393 		ret = rn5t618_battery_charge_now(info, val);
394 		break;
395 	default:
396 		return -EINVAL;
397 	}
398 
399 	return ret;
400 }
401 
rn5t618_battery_set_property(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)402 static int rn5t618_battery_set_property(struct power_supply *psy,
403 					enum power_supply_property psp,
404 					const union power_supply_propval *val)
405 {
406 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
407 
408 	switch (psp) {
409 	case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
410 		return rn5t618_battery_set_current_limit(info, val);
411 	default:
412 		return -EINVAL;
413 	}
414 }
415 
rn5t618_battery_property_is_writeable(struct power_supply * psy,enum power_supply_property psp)416 static int rn5t618_battery_property_is_writeable(struct power_supply *psy,
417 						enum power_supply_property psp)
418 {
419 	switch (psp) {
420 	case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
421 		return true;
422 	default:
423 		return false;
424 	}
425 }
426 
rn5t618_adp_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)427 static int rn5t618_adp_get_property(struct power_supply *psy,
428 				    enum power_supply_property psp,
429 				    union power_supply_propval *val)
430 {
431 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
432 	unsigned int chgstate;
433 	unsigned int regval;
434 	bool online;
435 	int ret;
436 
437 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &chgstate);
438 	if (ret)
439 		return ret;
440 
441 	online = !!(chgstate & CHG_STATE_ADP_INPUT);
442 
443 	switch (psp) {
444 	case POWER_SUPPLY_PROP_ONLINE:
445 		val->intval = online;
446 		break;
447 	case POWER_SUPPLY_PROP_STATUS:
448 		if (!online) {
449 			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
450 			break;
451 		}
452 		val->intval = rn5t618_decode_status(chgstate);
453 		if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
454 			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
455 
456 		break;
457 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
458 		ret = regmap_read(info->rn5t618->regmap,
459 				  RN5T618_REGISET1, &regval);
460 		if (ret < 0)
461 			return ret;
462 
463 		val->intval = FROM_CUR_REG(regval);
464 		break;
465 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
466 		if (!info->channel_vadp)
467 			return -ENODATA;
468 
469 		ret = iio_read_channel_processed_scale(info->channel_vadp, &val->intval, 1000);
470 		if (ret < 0)
471 			return ret;
472 
473 		break;
474 	default:
475 		return -EINVAL;
476 	}
477 
478 	return 0;
479 }
480 
rn5t618_adp_set_property(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)481 static int rn5t618_adp_set_property(struct power_supply *psy,
482 				    enum power_supply_property psp,
483 				    const union power_supply_propval *val)
484 {
485 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
486 	int ret;
487 
488 	switch (psp) {
489 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
490 		if (val->intval > ADP_MAX_CUR)
491 			return -EINVAL;
492 
493 		if (val->intval < CHG_MIN_CUR)
494 			return -EINVAL;
495 
496 		ret = regmap_write(info->rn5t618->regmap, RN5T618_REGISET1,
497 				   TO_CUR_REG(val->intval));
498 		if (ret < 0)
499 			return ret;
500 
501 		break;
502 	default:
503 		return -EINVAL;
504 	}
505 
506 	return 0;
507 }
508 
rn5t618_adp_property_is_writeable(struct power_supply * psy,enum power_supply_property psp)509 static int rn5t618_adp_property_is_writeable(struct power_supply *psy,
510 					     enum power_supply_property psp)
511 {
512 	switch (psp) {
513 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
514 		return true;
515 	default:
516 		return false;
517 	}
518 }
519 
rc5t619_usb_get_type(struct rn5t618_power_info * info,union power_supply_propval * val)520 static int rc5t619_usb_get_type(struct rn5t618_power_info *info,
521 				union power_supply_propval *val)
522 {
523 	unsigned int regval;
524 	int ret;
525 
526 	ret = regmap_read(info->rn5t618->regmap, RN5T618_GCHGDET, &regval);
527 	if (ret < 0)
528 		return ret;
529 
530 	switch (regval & GCHGDET_TYPE_MASK) {
531 	case GCHGDET_TYPE_SDP:
532 		val->intval = POWER_SUPPLY_USB_TYPE_SDP;
533 		break;
534 	case GCHGDET_TYPE_CDP:
535 		val->intval = POWER_SUPPLY_USB_TYPE_CDP;
536 		break;
537 	case GCHGDET_TYPE_DCP:
538 		val->intval = POWER_SUPPLY_USB_TYPE_DCP;
539 		break;
540 	default:
541 		val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
542 	}
543 
544 	return 0;
545 }
546 
rn5t618_usb_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)547 static int rn5t618_usb_get_property(struct power_supply *psy,
548 				    enum power_supply_property psp,
549 				    union power_supply_propval *val)
550 {
551 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
552 	unsigned int chgstate;
553 	unsigned int regval;
554 	bool online;
555 	int ret;
556 
557 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGSTATE, &chgstate);
558 	if (ret)
559 		return ret;
560 
561 	online = !!(chgstate & CHG_STATE_USB_INPUT);
562 
563 	switch (psp) {
564 	case POWER_SUPPLY_PROP_ONLINE:
565 		val->intval = online;
566 		break;
567 	case POWER_SUPPLY_PROP_STATUS:
568 		if (!online) {
569 			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
570 			break;
571 		}
572 		val->intval = rn5t618_decode_status(chgstate);
573 		if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
574 			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
575 
576 		break;
577 	case POWER_SUPPLY_PROP_USB_TYPE:
578 		if (!online || (info->rn5t618->variant != RC5T619))
579 			return -ENODATA;
580 
581 		return rc5t619_usb_get_type(info, val);
582 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
583 		ret = regmap_read(info->rn5t618->regmap, RN5T618_CHGCTL1,
584 				  &regval);
585 		if (ret < 0)
586 			return ret;
587 
588 		val->intval = 0;
589 		if (regval & 2) {
590 			ret = regmap_read(info->rn5t618->regmap,
591 					  RN5T618_REGISET2,
592 					  &regval);
593 			if (ret < 0)
594 				return ret;
595 
596 			val->intval = FROM_CUR_REG(regval);
597 		}
598 		break;
599 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
600 		if (!info->channel_vusb)
601 			return -ENODATA;
602 
603 		ret = iio_read_channel_processed_scale(info->channel_vusb, &val->intval, 1000);
604 		if (ret < 0)
605 			return ret;
606 
607 		break;
608 	default:
609 		return -EINVAL;
610 	}
611 
612 	return 0;
613 }
614 
rn5t618_usb_set_property(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)615 static int rn5t618_usb_set_property(struct power_supply *psy,
616 				    enum power_supply_property psp,
617 				    const union power_supply_propval *val)
618 {
619 	struct rn5t618_power_info *info = power_supply_get_drvdata(psy);
620 	int ret;
621 
622 	switch (psp) {
623 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
624 		if (val->intval > USB_MAX_CUR)
625 			return -EINVAL;
626 
627 		if (val->intval < CHG_MIN_CUR)
628 			return -EINVAL;
629 
630 		ret = regmap_write(info->rn5t618->regmap, RN5T618_REGISET2,
631 				   0xE0 | TO_CUR_REG(val->intval));
632 		if (ret < 0)
633 			return ret;
634 
635 		break;
636 	default:
637 		return -EINVAL;
638 	}
639 
640 	return 0;
641 }
642 
rn5t618_usb_property_is_writeable(struct power_supply * psy,enum power_supply_property psp)643 static int rn5t618_usb_property_is_writeable(struct power_supply *psy,
644 					     enum power_supply_property psp)
645 {
646 	switch (psp) {
647 	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
648 		return true;
649 	default:
650 		return false;
651 	}
652 }
653 
654 static const struct power_supply_desc rn5t618_battery_desc = {
655 	.name                   = "rn5t618-battery",
656 	.type                   = POWER_SUPPLY_TYPE_BATTERY,
657 	.properties             = rn5t618_battery_props,
658 	.num_properties         = ARRAY_SIZE(rn5t618_battery_props),
659 	.get_property           = rn5t618_battery_get_property,
660 	.set_property           = rn5t618_battery_set_property,
661 	.property_is_writeable  = rn5t618_battery_property_is_writeable,
662 };
663 
664 static const struct power_supply_desc rn5t618_adp_desc = {
665 	.name                   = "rn5t618-adp",
666 	.type                   = POWER_SUPPLY_TYPE_MAINS,
667 	.properties             = rn5t618_adp_props,
668 	.num_properties         = ARRAY_SIZE(rn5t618_adp_props),
669 	.get_property           = rn5t618_adp_get_property,
670 	.set_property           = rn5t618_adp_set_property,
671 	.property_is_writeable  = rn5t618_adp_property_is_writeable,
672 };
673 
674 static const struct power_supply_desc rn5t618_usb_desc = {
675 	.name                   = "rn5t618-usb",
676 	.type                   = POWER_SUPPLY_TYPE_USB,
677 	.usb_types		= BIT(POWER_SUPPLY_USB_TYPE_SDP) |
678 				  BIT(POWER_SUPPLY_USB_TYPE_CDP) |
679 				  BIT(POWER_SUPPLY_USB_TYPE_DCP) |
680 				  BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
681 	.properties             = rn5t618_usb_props,
682 	.num_properties         = ARRAY_SIZE(rn5t618_usb_props),
683 	.get_property           = rn5t618_usb_get_property,
684 	.set_property           = rn5t618_usb_set_property,
685 	.property_is_writeable  = rn5t618_usb_property_is_writeable,
686 };
687 
rn5t618_charger_irq(int irq,void * data)688 static irqreturn_t rn5t618_charger_irq(int irq, void *data)
689 {
690 	struct device *dev = data;
691 	struct rn5t618_power_info *info = dev_get_drvdata(dev);
692 
693 	unsigned int ctrl, stat1, stat2, err;
694 
695 	regmap_read(info->rn5t618->regmap, RN5T618_CHGERR_IRR, &err);
696 	regmap_read(info->rn5t618->regmap, RN5T618_CHGCTRL_IRR, &ctrl);
697 	regmap_read(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR1, &stat1);
698 	regmap_read(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR2, &stat2);
699 
700 	regmap_write(info->rn5t618->regmap, RN5T618_CHGERR_IRR, 0);
701 	regmap_write(info->rn5t618->regmap, RN5T618_CHGCTRL_IRR, 0);
702 	regmap_write(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR1, 0);
703 	regmap_write(info->rn5t618->regmap, RN5T618_CHGSTAT_IRR2, 0);
704 
705 	dev_dbg(dev, "chgerr: %x chgctrl: %x chgstat: %x chgstat2: %x\n",
706 		err, ctrl, stat1, stat2);
707 
708 	power_supply_changed(info->usb);
709 	power_supply_changed(info->adp);
710 	power_supply_changed(info->battery);
711 
712 	return IRQ_HANDLED;
713 }
714 
rn5t618_power_probe(struct platform_device * pdev)715 static int rn5t618_power_probe(struct platform_device *pdev)
716 {
717 	int ret = 0;
718 	unsigned int v;
719 	struct power_supply_config psy_cfg = {};
720 	struct rn5t618_power_info *info;
721 
722 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
723 	if (!info)
724 		return -ENOMEM;
725 
726 	info->pdev = pdev;
727 	info->rn5t618 = dev_get_drvdata(pdev->dev.parent);
728 	info->irq = -1;
729 
730 	platform_set_drvdata(pdev, info);
731 
732 	info->channel_vusb = devm_iio_channel_get(&pdev->dev, "vusb");
733 	if (IS_ERR(info->channel_vusb)) {
734 		if (PTR_ERR(info->channel_vusb) == -ENODEV)
735 			return -EPROBE_DEFER;
736 		return PTR_ERR(info->channel_vusb);
737 	}
738 
739 	info->channel_vadp = devm_iio_channel_get(&pdev->dev, "vadp");
740 	if (IS_ERR(info->channel_vadp)) {
741 		if (PTR_ERR(info->channel_vadp) == -ENODEV)
742 			return -EPROBE_DEFER;
743 		return PTR_ERR(info->channel_vadp);
744 	}
745 
746 	ret = regmap_read(info->rn5t618->regmap, RN5T618_CONTROL, &v);
747 	if (ret)
748 		return ret;
749 
750 	if (!(v & FG_ENABLE)) {
751 		/* E.g. the vendor kernels of various Kobo and Tolino Ebook
752 		 * readers disable the fuel gauge on shutdown. If a kernel
753 		 * without fuel gauge support is booted after that, the fuel
754 		 * gauge will get decalibrated.
755 		 */
756 		dev_info(&pdev->dev, "Fuel gauge not enabled, enabling now\n");
757 		dev_info(&pdev->dev, "Expect imprecise results\n");
758 		regmap_update_bits(info->rn5t618->regmap, RN5T618_CONTROL,
759 				   FG_ENABLE, FG_ENABLE);
760 	}
761 
762 	psy_cfg.drv_data = info;
763 	info->battery = devm_power_supply_register(&pdev->dev,
764 						   &rn5t618_battery_desc,
765 						   &psy_cfg);
766 	if (IS_ERR(info->battery)) {
767 		ret = PTR_ERR(info->battery);
768 		dev_err(&pdev->dev, "failed to register battery: %d\n", ret);
769 		return ret;
770 	}
771 
772 	info->adp = devm_power_supply_register(&pdev->dev,
773 					       &rn5t618_adp_desc,
774 					       &psy_cfg);
775 	if (IS_ERR(info->adp)) {
776 		ret = PTR_ERR(info->adp);
777 		dev_err(&pdev->dev, "failed to register adp: %d\n", ret);
778 		return ret;
779 	}
780 
781 	info->usb = devm_power_supply_register(&pdev->dev,
782 					       &rn5t618_usb_desc,
783 					       &psy_cfg);
784 	if (IS_ERR(info->usb)) {
785 		ret = PTR_ERR(info->usb);
786 		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
787 		return ret;
788 	}
789 
790 	if (info->rn5t618->irq_data)
791 		info->irq = regmap_irq_get_virq(info->rn5t618->irq_data,
792 						RN5T618_IRQ_CHG);
793 
794 	if (info->irq < 0)
795 		info->irq = -1;
796 	else {
797 		ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
798 						rn5t618_charger_irq,
799 						IRQF_ONESHOT,
800 						"rn5t618_power",
801 						&pdev->dev);
802 
803 		if (ret < 0) {
804 			dev_err(&pdev->dev, "request IRQ:%d fail\n",
805 				info->irq);
806 			info->irq = -1;
807 		}
808 	}
809 
810 	return 0;
811 }
812 
813 static struct platform_driver rn5t618_power_driver = {
814 	.driver = {
815 		.name   = "rn5t618-power",
816 	},
817 	.probe = rn5t618_power_probe,
818 };
819 
820 module_platform_driver(rn5t618_power_driver);
821 MODULE_ALIAS("platform:rn5t618-power");
822 MODULE_DESCRIPTION("Power supply driver for RICOH RN5T618");
823 MODULE_LICENSE("GPL");
824