brintos

brintos / linux-shallow public Read only

0
0
Text · 18.8 KiB · dac9875 Raw
747 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ADP5061 I2C Programmable Linear Battery Charger4 *5 * Copyright 2018 Analog Devices Inc.6 */7 8#include <linux/init.h>9#include <linux/module.h>10#include <linux/slab.h>11#include <linux/i2c.h>12#include <linux/delay.h>13#include <linux/pm.h>14#include <linux/mod_devicetable.h>15#include <linux/power_supply.h>16#include <linux/platform_device.h>17#include <linux/of.h>18#include <linux/regmap.h>19 20/* ADP5061 registers definition */21#define ADP5061_ID			0x0022#define ADP5061_REV			0x0123#define ADP5061_VINX_SET		0x0224#define ADP5061_TERM_SET		0x0325#define ADP5061_CHG_CURR		0x0426#define ADP5061_VOLTAGE_TH		0x0527#define ADP5061_TIMER_SET		0x0628#define ADP5061_FUNC_SET_1		0x0729#define ADP5061_FUNC_SET_2		0x0830#define ADP5061_INT_EN			0x0931#define ADP5061_INT_ACT			0x0A32#define ADP5061_CHG_STATUS_1		0x0B33#define ADP5061_CHG_STATUS_2		0x0C34#define ADP5061_FAULT			0x0D35#define ADP5061_BATTERY_SHORT		0x1036#define ADP5061_IEND			0x1137 38/* ADP5061_VINX_SET */39#define ADP5061_VINX_SET_ILIM_MSK		GENMASK(3, 0)40#define ADP5061_VINX_SET_ILIM_MODE(x)		(((x) & 0x0F) << 0)41 42/* ADP5061_TERM_SET */43#define ADP5061_TERM_SET_VTRM_MSK		GENMASK(7, 2)44#define ADP5061_TERM_SET_VTRM_MODE(x)		(((x) & 0x3F) << 2)45#define ADP5061_TERM_SET_CHG_VLIM_MSK		GENMASK(1, 0)46#define ADP5061_TERM_SET_CHG_VLIM_MODE(x)	(((x) & 0x03) << 0)47 48/* ADP5061_CHG_CURR */49#define ADP5061_CHG_CURR_ICHG_MSK		GENMASK(6, 2)50#define ADP5061_CHG_CURR_ICHG_MODE(x)		(((x) & 0x1F) << 2)51#define ADP5061_CHG_CURR_ITRK_DEAD_MSK		GENMASK(1, 0)52#define ADP5061_CHG_CURR_ITRK_DEAD_MODE(x)	(((x) & 0x03) << 0)53 54/* ADP5061_VOLTAGE_TH */55#define ADP5061_VOLTAGE_TH_DIS_RCH_MSK		BIT(7)56#define ADP5061_VOLTAGE_TH_DIS_RCH_MODE(x)	(((x) & 0x01) << 7)57#define ADP5061_VOLTAGE_TH_VRCH_MSK		GENMASK(6, 5)58#define ADP5061_VOLTAGE_TH_VRCH_MODE(x)		(((x) & 0x03) << 5)59#define ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK	GENMASK(4, 3)60#define ADP5061_VOLTAGE_TH_VTRK_DEAD_MODE(x)	(((x) & 0x03) << 3)61#define ADP5061_VOLTAGE_TH_VWEAK_MSK		GENMASK(2, 0)62#define ADP5061_VOLTAGE_TH_VWEAK_MODE(x)	(((x) & 0x07) << 0)63 64/* ADP5061_CHG_STATUS_1 */65#define ADP5061_CHG_STATUS_1_VIN_OV(x)		(((x) >> 7) & 0x1)66#define ADP5061_CHG_STATUS_1_VIN_OK(x)		(((x) >> 6) & 0x1)67#define ADP5061_CHG_STATUS_1_VIN_ILIM(x)	(((x) >> 5) & 0x1)68#define ADP5061_CHG_STATUS_1_THERM_LIM(x)	(((x) >> 4) & 0x1)69#define ADP5061_CHG_STATUS_1_CHDONE(x)		(((x) >> 3) & 0x1)70#define ADP5061_CHG_STATUS_1_CHG_STATUS(x)	(((x) >> 0) & 0x7)71 72/* ADP5061_CHG_STATUS_2 */73#define ADP5061_CHG_STATUS_2_THR_STATUS(x)	(((x) >> 5) & 0x7)74#define ADP5061_CHG_STATUS_2_RCH_LIM_INFO(x)	(((x) >> 3) & 0x1)75#define ADP5061_CHG_STATUS_2_BAT_STATUS(x)	(((x) >> 0) & 0x7)76 77/* ADP5061_IEND */78#define ADP5061_IEND_IEND_MSK			GENMASK(7, 5)79#define ADP5061_IEND_IEND_MODE(x)		(((x) & 0x07) << 5)80 81#define ADP5061_NO_BATTERY	0x0182#define ADP5061_ICHG_MAX	1300 // mA83 84enum adp5061_chg_status {85	ADP5061_CHG_OFF,86	ADP5061_CHG_TRICKLE,87	ADP5061_CHG_FAST_CC,88	ADP5061_CHG_FAST_CV,89	ADP5061_CHG_COMPLETE,90	ADP5061_CHG_LDO_MODE,91	ADP5061_CHG_TIMER_EXP,92	ADP5061_CHG_BAT_DET,93};94 95static const int adp5061_chg_type[4] = {96	[ADP5061_CHG_OFF] = POWER_SUPPLY_CHARGE_TYPE_NONE,97	[ADP5061_CHG_TRICKLE] = POWER_SUPPLY_CHARGE_TYPE_TRICKLE,98	[ADP5061_CHG_FAST_CC] = POWER_SUPPLY_CHARGE_TYPE_FAST,99	[ADP5061_CHG_FAST_CV] = POWER_SUPPLY_CHARGE_TYPE_FAST,100};101 102static const int adp5061_vweak_th[8] = {103	2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400,104};105 106static const int adp5061_prechg_current[4] = {107	5, 10, 20, 80,108};109 110static const int adp5061_vmin[4] = {111	2000, 2500, 2600, 2900,112};113 114static const int adp5061_const_chg_vmax[4] = {115	3200, 3400, 3700, 3800,116};117 118static const int adp5061_const_ichg[24] = {119	50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650,120	700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1200, 1300,121};122 123static const int adp5061_vmax[36] = {124	3800, 3820, 3840, 3860, 3880, 3900, 3920, 3940, 3960, 3980,125	4000, 4020, 4040, 4060, 4080, 4100, 4120, 4140, 4160, 4180,126	4200, 4220, 4240, 4260, 4280, 4300, 4320, 4340, 4360, 4380,127	4400, 4420, 4440, 4460, 4480, 4500,128};129 130static const int adp5061_in_current_lim[16] = {131	100, 150, 200, 250, 300, 400, 500, 600, 700,132	800, 900, 1000, 1200, 1500, 1800, 2100,133};134 135static const int adp5061_iend[8] = {136	12500, 32500, 52500, 72500, 92500, 117500, 142500, 170000,137};138 139struct adp5061_state {140	struct i2c_client		*client;141	struct regmap			*regmap;142	struct power_supply		*psy;143};144 145static int adp5061_get_array_index(const int *array, u8 size, int val)146{147	int i;148 149	for (i = 1; i < size; i++) {150		if (val < array[i])151			break;152	}153 154	return i-1;155}156 157static int adp5061_get_status(struct adp5061_state *st,158			      u8 *status1, u8 *status2)159{160	u8 buf[2];161	int ret;162 163	/* CHG_STATUS1 and CHG_STATUS2 are adjacent regs */164	ret = regmap_bulk_read(st->regmap, ADP5061_CHG_STATUS_1,165			       &buf[0], 2);166	if (ret < 0)167		return ret;168 169	*status1 = buf[0];170	*status2 = buf[1];171 172	return ret;173}174 175static int adp5061_get_input_current_limit(struct adp5061_state *st,176		union power_supply_propval *val)177{178	unsigned int regval;179	int mode, ret;180 181	ret = regmap_read(st->regmap, ADP5061_VINX_SET, &regval);182	if (ret < 0)183		return ret;184 185	mode = ADP5061_VINX_SET_ILIM_MODE(regval);186	val->intval = adp5061_in_current_lim[mode] * 1000;187 188	return ret;189}190 191static int adp5061_set_input_current_limit(struct adp5061_state *st, int val)192{193	int index;194 195	/* Convert from uA to mA */196	val /= 1000;197	index = adp5061_get_array_index(adp5061_in_current_lim,198					ARRAY_SIZE(adp5061_in_current_lim),199					val);200	if (index < 0)201		return index;202 203	return regmap_update_bits(st->regmap, ADP5061_VINX_SET,204				  ADP5061_VINX_SET_ILIM_MSK,205				  ADP5061_VINX_SET_ILIM_MODE(index));206}207 208static int adp5061_set_min_voltage(struct adp5061_state *st, int val)209{210	int index;211 212	/* Convert from uV to mV */213	val /= 1000;214	index = adp5061_get_array_index(adp5061_vmin,215					ARRAY_SIZE(adp5061_vmin),216					val);217	if (index < 0)218		return index;219 220	return regmap_update_bits(st->regmap, ADP5061_VOLTAGE_TH,221				  ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK,222				  ADP5061_VOLTAGE_TH_VTRK_DEAD_MODE(index));223}224 225static int adp5061_get_min_voltage(struct adp5061_state *st,226				   union power_supply_propval *val)227{228	unsigned int regval;229	int ret;230 231	ret = regmap_read(st->regmap, ADP5061_VOLTAGE_TH, &regval);232	if (ret < 0)233		return ret;234 235	regval = ((regval & ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK) >> 3);236	val->intval = adp5061_vmin[regval] * 1000;237 238	return ret;239}240 241static int adp5061_get_chg_volt_lim(struct adp5061_state *st,242				    union power_supply_propval *val)243{244	unsigned int regval;245	int mode, ret;246 247	ret = regmap_read(st->regmap, ADP5061_TERM_SET, &regval);248	if (ret < 0)249		return ret;250 251	mode = ADP5061_TERM_SET_CHG_VLIM_MODE(regval);252	val->intval = adp5061_const_chg_vmax[mode] * 1000;253 254	return ret;255}256 257static int adp5061_get_max_voltage(struct adp5061_state *st,258				   union power_supply_propval *val)259{260	unsigned int regval;261	int ret;262 263	ret = regmap_read(st->regmap, ADP5061_TERM_SET, &regval);264	if (ret < 0)265		return ret;266 267	regval = ((regval & ADP5061_TERM_SET_VTRM_MSK) >> 2) - 0x0F;268	if (regval >= ARRAY_SIZE(adp5061_vmax))269		regval = ARRAY_SIZE(adp5061_vmax) - 1;270 271	val->intval = adp5061_vmax[regval] * 1000;272 273	return ret;274}275 276static int adp5061_set_max_voltage(struct adp5061_state *st, int val)277{278	int vmax_index;279 280	/* Convert from uV to mV */281	val /= 1000;282	if (val > 4500)283		val = 4500;284 285	vmax_index = adp5061_get_array_index(adp5061_vmax,286					     ARRAY_SIZE(adp5061_vmax), val);287	if (vmax_index < 0)288		return vmax_index;289 290	vmax_index += 0x0F;291 292	return regmap_update_bits(st->regmap, ADP5061_TERM_SET,293				  ADP5061_TERM_SET_VTRM_MSK,294				  ADP5061_TERM_SET_VTRM_MODE(vmax_index));295}296 297static int adp5061_set_const_chg_vmax(struct adp5061_state *st, int val)298{299	int index;300 301	/* Convert from uV to mV */302	val /= 1000;303	index = adp5061_get_array_index(adp5061_const_chg_vmax,304					ARRAY_SIZE(adp5061_const_chg_vmax),305					val);306	if (index < 0)307		return index;308 309	return regmap_update_bits(st->regmap, ADP5061_TERM_SET,310				  ADP5061_TERM_SET_CHG_VLIM_MSK,311				  ADP5061_TERM_SET_CHG_VLIM_MODE(index));312}313 314static int adp5061_set_const_chg_current(struct adp5061_state *st, int val)315{316 317	int index;318 319	/* Convert from uA to mA */320	val /= 1000;321	if (val > ADP5061_ICHG_MAX)322		val = ADP5061_ICHG_MAX;323 324	index = adp5061_get_array_index(adp5061_const_ichg,325					ARRAY_SIZE(adp5061_const_ichg),326					val);327	if (index < 0)328		return index;329 330	return regmap_update_bits(st->regmap, ADP5061_CHG_CURR,331				  ADP5061_CHG_CURR_ICHG_MSK,332				  ADP5061_CHG_CURR_ICHG_MODE(index));333}334 335static int adp5061_get_const_chg_current(struct adp5061_state *st,336		union power_supply_propval *val)337{338	unsigned int regval;339	int ret;340 341	ret = regmap_read(st->regmap, ADP5061_CHG_CURR, &regval);342	if (ret < 0)343		return ret;344 345	regval = ((regval & ADP5061_CHG_CURR_ICHG_MSK) >> 2);346	if (regval >= ARRAY_SIZE(adp5061_const_ichg))347		regval = ARRAY_SIZE(adp5061_const_ichg) - 1;348 349	val->intval = adp5061_const_ichg[regval] * 1000;350 351	return ret;352}353 354static int adp5061_get_prechg_current(struct adp5061_state *st,355				      union power_supply_propval *val)356{357	unsigned int regval;358	int ret;359 360	ret = regmap_read(st->regmap, ADP5061_CHG_CURR, &regval);361	if (ret < 0)362		return ret;363 364	regval &= ADP5061_CHG_CURR_ITRK_DEAD_MSK;365	val->intval = adp5061_prechg_current[regval] * 1000;366 367	return ret;368}369 370static int adp5061_set_prechg_current(struct adp5061_state *st, int val)371{372	int index;373 374	/* Convert from uA to mA */375	val /= 1000;376	index = adp5061_get_array_index(adp5061_prechg_current,377					ARRAY_SIZE(adp5061_prechg_current),378					val);379	if (index < 0)380		return index;381 382	return regmap_update_bits(st->regmap, ADP5061_CHG_CURR,383				  ADP5061_CHG_CURR_ITRK_DEAD_MSK,384				  ADP5061_CHG_CURR_ITRK_DEAD_MODE(index));385}386 387static int adp5061_get_vweak_th(struct adp5061_state *st,388				union power_supply_propval *val)389{390	unsigned int regval;391	int ret;392 393	ret = regmap_read(st->regmap, ADP5061_VOLTAGE_TH, &regval);394	if (ret < 0)395		return ret;396 397	regval &= ADP5061_VOLTAGE_TH_VWEAK_MSK;398	val->intval = adp5061_vweak_th[regval] * 1000;399 400	return ret;401}402 403static int adp5061_set_vweak_th(struct adp5061_state *st, int val)404{405	int index;406 407	/* Convert from uV to mV */408	val /= 1000;409	index = adp5061_get_array_index(adp5061_vweak_th,410					ARRAY_SIZE(adp5061_vweak_th),411					val);412	if (index < 0)413		return index;414 415	return regmap_update_bits(st->regmap, ADP5061_VOLTAGE_TH,416				  ADP5061_VOLTAGE_TH_VWEAK_MSK,417				  ADP5061_VOLTAGE_TH_VWEAK_MODE(index));418}419 420static int adp5061_get_chg_type(struct adp5061_state *st,421				union power_supply_propval *val)422{423	u8 status1, status2;424	int chg_type, ret;425 426	ret = adp5061_get_status(st, &status1, &status2);427	if (ret < 0)428		return ret;429 430	chg_type = ADP5061_CHG_STATUS_1_CHG_STATUS(status1);431	if (chg_type >= ARRAY_SIZE(adp5061_chg_type))432		val->intval = POWER_SUPPLY_STATUS_UNKNOWN;433	else434		val->intval = adp5061_chg_type[chg_type];435 436	return ret;437}438 439static int adp5061_get_charger_status(struct adp5061_state *st,440				      union power_supply_propval *val)441{442	u8 status1, status2;443	int ret;444 445	ret = adp5061_get_status(st, &status1, &status2);446	if (ret < 0)447		return ret;448 449	switch (ADP5061_CHG_STATUS_1_CHG_STATUS(status1)) {450	case ADP5061_CHG_OFF:451		val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;452		break;453	case ADP5061_CHG_TRICKLE:454	case ADP5061_CHG_FAST_CC:455	case ADP5061_CHG_FAST_CV:456		val->intval = POWER_SUPPLY_STATUS_CHARGING;457		break;458	case ADP5061_CHG_COMPLETE:459		val->intval = POWER_SUPPLY_STATUS_FULL;460		break;461	case ADP5061_CHG_TIMER_EXP:462		/* The battery must be discharging if there is a charge fault */463		val->intval = POWER_SUPPLY_STATUS_DISCHARGING;464		break;465	default:466		val->intval = POWER_SUPPLY_STATUS_UNKNOWN;467	}468 469	return ret;470}471 472static int adp5061_get_battery_status(struct adp5061_state *st,473				      union power_supply_propval *val)474{475	u8 status1, status2;476	int ret;477 478	ret = adp5061_get_status(st, &status1, &status2);479	if (ret < 0)480		return ret;481 482	switch (ADP5061_CHG_STATUS_2_BAT_STATUS(status2)) {483	case 0x0: /* Battery monitor off */484	case 0x1: /* No battery */485		val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;486		break;487	case 0x2: /* VBAT < VTRK */488		val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;489		break;490	case 0x3: /* VTRK < VBAT_SNS < VWEAK */491		val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;492		break;493	case 0x4: /* VBAT_SNS > VWEAK */494		val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;495		break;496	default:497		val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;498		break;499	}500 501	return ret;502}503 504static int adp5061_get_termination_current(struct adp5061_state *st,505					   union power_supply_propval *val)506{507	unsigned int regval;508	int ret;509 510	ret = regmap_read(st->regmap, ADP5061_IEND, &regval);511	if (ret < 0)512		return ret;513 514	regval = (regval & ADP5061_IEND_IEND_MSK) >> 5;515	val->intval = adp5061_iend[regval];516 517	return ret;518}519 520static int adp5061_set_termination_current(struct adp5061_state *st, int val)521{522	int index;523 524	index = adp5061_get_array_index(adp5061_iend,525					ARRAY_SIZE(adp5061_iend),526					val);527	if (index < 0)528		return index;529 530	return regmap_update_bits(st->regmap, ADP5061_IEND,531				  ADP5061_IEND_IEND_MSK,532				  ADP5061_IEND_IEND_MODE(index));533}534 535static int adp5061_get_property(struct power_supply *psy,536				enum power_supply_property psp,537				union power_supply_propval *val)538{539	struct adp5061_state *st = power_supply_get_drvdata(psy);540	u8 status1, status2;541	int mode, ret;542 543	switch (psp) {544	case POWER_SUPPLY_PROP_PRESENT:545		ret = adp5061_get_status(st, &status1, &status2);546		if (ret < 0)547			return ret;548 549		mode = ADP5061_CHG_STATUS_2_BAT_STATUS(status2);550		if (mode == ADP5061_NO_BATTERY)551			val->intval = 0;552		else553			val->intval = 1;554		break;555	case POWER_SUPPLY_PROP_CHARGE_TYPE:556		return adp5061_get_chg_type(st, val);557	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:558		/* This property is used to indicate the input current559		 * limit into VINx (ILIM)560		 */561		return adp5061_get_input_current_limit(st, val);562	case POWER_SUPPLY_PROP_VOLTAGE_MAX:563		/* This property is used to indicate the termination564		 * voltage (VTRM)565		 */566		return adp5061_get_max_voltage(st, val);567	case POWER_SUPPLY_PROP_VOLTAGE_MIN:568		/*569		 * This property is used to indicate the trickle to fast570		 * charge threshold (VTRK_DEAD)571		 */572		return adp5061_get_min_voltage(st, val);573	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:574		/* This property is used to indicate the charging575		 * voltage limit (CHG_VLIM)576		 */577		return adp5061_get_chg_volt_lim(st, val);578	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:579		/*580		 * This property is used to indicate the value of the constant581		 * current charge (ICHG)582		 */583		return adp5061_get_const_chg_current(st, val);584	case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:585		/*586		 * This property is used to indicate the value of the trickle587		 * and weak charge currents (ITRK_DEAD)588		 */589		return adp5061_get_prechg_current(st, val);590	case POWER_SUPPLY_PROP_VOLTAGE_AVG:591		/*592		 * This property is used to set the VWEAK threshold593		 * bellow this value, weak charge mode is entered594		 * above this value, fast chargerge mode is entered595		 */596		return adp5061_get_vweak_th(st, val);597	case POWER_SUPPLY_PROP_STATUS:598		/*599		 * Indicate the charger status in relation to power600		 * supply status property601		 */602		return adp5061_get_charger_status(st, val);603	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:604		/*605		 * Indicate the battery status in relation to power606		 * supply capacity level property607		 */608		return adp5061_get_battery_status(st, val);609	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:610		/* Indicate the values of the termination current */611		return adp5061_get_termination_current(st, val);612	default:613		return -EINVAL;614	}615 616	return 0;617}618 619static int adp5061_set_property(struct power_supply *psy,620				enum power_supply_property psp,621				const union power_supply_propval *val)622{623	struct adp5061_state *st = power_supply_get_drvdata(psy);624 625	switch (psp) {626	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:627		return adp5061_set_input_current_limit(st, val->intval);628	case POWER_SUPPLY_PROP_VOLTAGE_MAX:629		return adp5061_set_max_voltage(st, val->intval);630	case POWER_SUPPLY_PROP_VOLTAGE_MIN:631		return adp5061_set_min_voltage(st, val->intval);632	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:633		return adp5061_set_const_chg_vmax(st, val->intval);634	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:635		return adp5061_set_const_chg_current(st, val->intval);636	case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:637		return adp5061_set_prechg_current(st, val->intval);638	case POWER_SUPPLY_PROP_VOLTAGE_AVG:639		return adp5061_set_vweak_th(st, val->intval);640	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:641		return adp5061_set_termination_current(st, val->intval);642	default:643		return -EINVAL;644	}645 646	return 0;647}648 649static int adp5061_prop_writeable(struct power_supply *psy,650				  enum power_supply_property psp)651{652	switch (psp) {653	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:654	case POWER_SUPPLY_PROP_VOLTAGE_MAX:655	case POWER_SUPPLY_PROP_VOLTAGE_MIN:656	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:657	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:658	case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:659	case POWER_SUPPLY_PROP_VOLTAGE_AVG:660	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:661		return 1;662	default:663		return 0;664	}665}666 667static enum power_supply_property adp5061_props[] = {668	POWER_SUPPLY_PROP_PRESENT,669	POWER_SUPPLY_PROP_CHARGE_TYPE,670	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,671	POWER_SUPPLY_PROP_VOLTAGE_MAX,672	POWER_SUPPLY_PROP_VOLTAGE_MIN,673	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,674	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,675	POWER_SUPPLY_PROP_PRECHARGE_CURRENT,676	POWER_SUPPLY_PROP_VOLTAGE_AVG,677	POWER_SUPPLY_PROP_STATUS,678	POWER_SUPPLY_PROP_CAPACITY_LEVEL,679	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,680};681 682static const struct regmap_config adp5061_regmap_config = {683	.reg_bits = 8,684	.val_bits = 8,685};686 687static const struct power_supply_desc adp5061_desc = {688	.name			= "adp5061",689	.type			= POWER_SUPPLY_TYPE_USB,690	.get_property		= adp5061_get_property,691	.set_property		= adp5061_set_property,692	.property_is_writeable	= adp5061_prop_writeable,693	.properties		= adp5061_props,694	.num_properties		= ARRAY_SIZE(adp5061_props),695};696 697static int adp5061_probe(struct i2c_client *client)698{699	struct power_supply_config psy_cfg = {};700	struct adp5061_state *st;701 702	st = devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL);703	if (!st)704		return -ENOMEM;705 706	st->client = client;707	st->regmap = devm_regmap_init_i2c(client,708					  &adp5061_regmap_config);709	if (IS_ERR(st->regmap)) {710		dev_err(&client->dev, "Failed to initialize register map\n");711		return -EINVAL;712	}713 714	i2c_set_clientdata(client, st);715	psy_cfg.drv_data = st;716 717	st->psy = devm_power_supply_register(&client->dev,718					     &adp5061_desc,719					     &psy_cfg);720 721	if (IS_ERR(st->psy)) {722		dev_err(&client->dev, "Failed to register power supply\n");723		return PTR_ERR(st->psy);724	}725 726	return 0;727}728 729static const struct i2c_device_id adp5061_id[] = {730	{ "adp5061" },731	{ }732};733MODULE_DEVICE_TABLE(i2c, adp5061_id);734 735static struct i2c_driver adp5061_driver = {736	.driver = {737		.name = KBUILD_MODNAME,738	},739	.probe = adp5061_probe,740	.id_table = adp5061_id,741};742module_i2c_driver(adp5061_driver);743 744MODULE_DESCRIPTION("Analog Devices adp5061 battery charger driver");745MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");746MODULE_LICENSE("GPL v2");747