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