brintos

brintos / linux-shallow public Read only

0
0
Text · 19.4 KiB · 40dec55 Raw
824 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Power supply driver for the RICOH RN5T618 power management chip family4 *5 * Copyright (C) 2020 Andreas Kemnade6 */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 0x4023#define CHG_STATE_USB_INPUT 0x8024#define CHG_STATE_MASK	0x1f25#define CHG_STATE_CHG_OFF	026#define CHG_STATE_CHG_READY_VADP	127#define CHG_STATE_CHG_TRICKLE	228#define CHG_STATE_CHG_RAPID	329#define CHG_STATE_CHG_COMPLETE	430#define CHG_STATE_SUSPEND	531#define CHG_STATE_VCHG_OVER_VOL	632#define CHG_STATE_BAT_ERROR	733#define CHG_STATE_NO_BAT	834#define CHG_STATE_BAT_OVER_VOL	935#define CHG_STATE_BAT_TEMP_ERR	1036#define CHG_STATE_DIE_ERR	1137#define CHG_STATE_DIE_SHUTDOWN	1238#define CHG_STATE_NO_BAT2	1339#define CHG_STATE_CHG_READY_VUSB	1440 41#define GCHGDET_TYPE_MASK 0x3042#define GCHGDET_TYPE_SDP 0x0043#define GCHGDET_TYPE_CDP 0x1044#define GCHGDET_TYPE_DCP 0x2045 46#define FG_ENABLE 147 48/*49 * Formula seems accurate for battery current, but for USB current around 70mA50 * per step was seen on Kobo Clara HD but all sources show the same formula51 * also fur USB current. To avoid accidentially unwanted high currents we stick52 * to that formula53 */54#define TO_CUR_REG(x) ((x) / 100000 - 1)55#define FROM_CUR_REG(x) ((((x) & 0x1f) + 1) * 100000)56#define CHG_MIN_CUR 10000057#define CHG_MAX_CUR 180000058#define ADP_MAX_CUR 250000059#define USB_MAX_CUR 140000060 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_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 82static 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 91static 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 106static 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 134static 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 155static 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	} else170		val->intval = POWER_SUPPLY_STATUS_DISCHARGING;171 172	return ret;173}174 175static 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	else189		val->intval = 1;190 191	return ret;192}193 194static 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 209static 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 225static 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 240static 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 255static 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 273static 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 291static 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 305static 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 321static 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 336static 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 351static 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 402static 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 416static 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 427static 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 481static 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 509static 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 520static 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 547static 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 615static 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 643static 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 654static 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 664static 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 674static 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 688static 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 715static 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 Ebook752		 * readers disable the fuel gauge on shutdown. If a kernel753		 * without fuel gauge support is booted after that, the fuel754		 * 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 813static struct platform_driver rn5t618_power_driver = {814	.driver = {815		.name   = "rn5t618-power",816	},817	.probe = rn5t618_power_probe,818};819 820module_platform_driver(rn5t618_power_driver);821MODULE_ALIAS("platform:rn5t618-power");822MODULE_DESCRIPTION("Power supply driver for RICOH RN5T618");823MODULE_LICENSE("GPL");824