18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Battery power supply driver for X-Powers AXP20X and AXP22X PMICs
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright 2016 Free Electrons NextThing Co.
58c2ecf20Sopenharmony_ci *	Quentin Schulz <quentin.schulz@free-electrons.com>
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * This driver is based on a previous upstreaming attempt by:
88c2ecf20Sopenharmony_ci *	Bruno Prémont <bonbons@linux-vserver.org>
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General
118c2ecf20Sopenharmony_ci * Public License. See the file "COPYING" in the main directory of this
128c2ecf20Sopenharmony_ci * archive for more details.
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful,
158c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
168c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
178c2ecf20Sopenharmony_ci * GNU General Public License for more details.
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <linux/err.h>
218c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
228c2ecf20Sopenharmony_ci#include <linux/irq.h>
238c2ecf20Sopenharmony_ci#include <linux/module.h>
248c2ecf20Sopenharmony_ci#include <linux/of.h>
258c2ecf20Sopenharmony_ci#include <linux/of_device.h>
268c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
278c2ecf20Sopenharmony_ci#include <linux/power_supply.h>
288c2ecf20Sopenharmony_ci#include <linux/regmap.h>
298c2ecf20Sopenharmony_ci#include <linux/slab.h>
308c2ecf20Sopenharmony_ci#include <linux/time.h>
318c2ecf20Sopenharmony_ci#include <linux/iio/iio.h>
328c2ecf20Sopenharmony_ci#include <linux/iio/consumer.h>
338c2ecf20Sopenharmony_ci#include <linux/mfd/axp20x.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define AXP20X_PWR_STATUS_BAT_CHARGING	BIT(2)
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define AXP20X_PWR_OP_BATT_PRESENT	BIT(5)
388c2ecf20Sopenharmony_ci#define AXP20X_PWR_OP_BATT_ACTIVATED	BIT(3)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define AXP209_FG_PERCENT		GENMASK(6, 0)
418c2ecf20Sopenharmony_ci#define AXP22X_FG_VALID			BIT(7)
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#define AXP20X_CHRG_CTRL1_TGT_VOLT	GENMASK(6, 5)
448c2ecf20Sopenharmony_ci#define AXP20X_CHRG_CTRL1_TGT_4_1V	(0 << 5)
458c2ecf20Sopenharmony_ci#define AXP20X_CHRG_CTRL1_TGT_4_15V	(1 << 5)
468c2ecf20Sopenharmony_ci#define AXP20X_CHRG_CTRL1_TGT_4_2V	(2 << 5)
478c2ecf20Sopenharmony_ci#define AXP20X_CHRG_CTRL1_TGT_4_36V	(3 << 5)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define AXP22X_CHRG_CTRL1_TGT_4_22V	(1 << 5)
508c2ecf20Sopenharmony_ci#define AXP22X_CHRG_CTRL1_TGT_4_24V	(3 << 5)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define AXP813_CHRG_CTRL1_TGT_4_35V	(3 << 5)
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define AXP20X_CHRG_CTRL1_TGT_CURR	GENMASK(3, 0)
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define AXP20X_V_OFF_MASK		GENMASK(2, 0)
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistruct axp20x_batt_ps;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistruct axp_data {
618c2ecf20Sopenharmony_ci	int	ccc_scale;
628c2ecf20Sopenharmony_ci	int	ccc_offset;
638c2ecf20Sopenharmony_ci	bool	has_fg_valid;
648c2ecf20Sopenharmony_ci	int	(*get_max_voltage)(struct axp20x_batt_ps *batt, int *val);
658c2ecf20Sopenharmony_ci	int	(*set_max_voltage)(struct axp20x_batt_ps *batt, int val);
668c2ecf20Sopenharmony_ci};
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistruct axp20x_batt_ps {
698c2ecf20Sopenharmony_ci	struct regmap *regmap;
708c2ecf20Sopenharmony_ci	struct power_supply *batt;
718c2ecf20Sopenharmony_ci	struct device *dev;
728c2ecf20Sopenharmony_ci	struct iio_channel *batt_chrg_i;
738c2ecf20Sopenharmony_ci	struct iio_channel *batt_dischrg_i;
748c2ecf20Sopenharmony_ci	struct iio_channel *batt_v;
758c2ecf20Sopenharmony_ci	/* Maximum constant charge current */
768c2ecf20Sopenharmony_ci	unsigned int max_ccc;
778c2ecf20Sopenharmony_ci	const struct axp_data	*data;
788c2ecf20Sopenharmony_ci};
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
818c2ecf20Sopenharmony_ci					  int *val)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	int ret, reg;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
868c2ecf20Sopenharmony_ci	if (ret)
878c2ecf20Sopenharmony_ci		return ret;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
908c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_1V:
918c2ecf20Sopenharmony_ci		*val = 4100000;
928c2ecf20Sopenharmony_ci		break;
938c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_15V:
948c2ecf20Sopenharmony_ci		*val = 4150000;
958c2ecf20Sopenharmony_ci		break;
968c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_2V:
978c2ecf20Sopenharmony_ci		*val = 4200000;
988c2ecf20Sopenharmony_ci		break;
998c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_36V:
1008c2ecf20Sopenharmony_ci		*val = 4360000;
1018c2ecf20Sopenharmony_ci		break;
1028c2ecf20Sopenharmony_ci	default:
1038c2ecf20Sopenharmony_ci		return -EINVAL;
1048c2ecf20Sopenharmony_ci	}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	return 0;
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
1108c2ecf20Sopenharmony_ci					  int *val)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	int ret, reg;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
1158c2ecf20Sopenharmony_ci	if (ret)
1168c2ecf20Sopenharmony_ci		return ret;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
1198c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_1V:
1208c2ecf20Sopenharmony_ci		*val = 4100000;
1218c2ecf20Sopenharmony_ci		break;
1228c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_2V:
1238c2ecf20Sopenharmony_ci		*val = 4200000;
1248c2ecf20Sopenharmony_ci		break;
1258c2ecf20Sopenharmony_ci	case AXP22X_CHRG_CTRL1_TGT_4_22V:
1268c2ecf20Sopenharmony_ci		*val = 4220000;
1278c2ecf20Sopenharmony_ci		break;
1288c2ecf20Sopenharmony_ci	case AXP22X_CHRG_CTRL1_TGT_4_24V:
1298c2ecf20Sopenharmony_ci		*val = 4240000;
1308c2ecf20Sopenharmony_ci		break;
1318c2ecf20Sopenharmony_ci	default:
1328c2ecf20Sopenharmony_ci		return -EINVAL;
1338c2ecf20Sopenharmony_ci	}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	return 0;
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
1398c2ecf20Sopenharmony_ci					  int *val)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	int ret, reg;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
1448c2ecf20Sopenharmony_ci	if (ret)
1458c2ecf20Sopenharmony_ci		return ret;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
1488c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_1V:
1498c2ecf20Sopenharmony_ci		*val = 4100000;
1508c2ecf20Sopenharmony_ci		break;
1518c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_15V:
1528c2ecf20Sopenharmony_ci		*val = 4150000;
1538c2ecf20Sopenharmony_ci		break;
1548c2ecf20Sopenharmony_ci	case AXP20X_CHRG_CTRL1_TGT_4_2V:
1558c2ecf20Sopenharmony_ci		*val = 4200000;
1568c2ecf20Sopenharmony_ci		break;
1578c2ecf20Sopenharmony_ci	case AXP813_CHRG_CTRL1_TGT_4_35V:
1588c2ecf20Sopenharmony_ci		*val = 4350000;
1598c2ecf20Sopenharmony_ci		break;
1608c2ecf20Sopenharmony_ci	default:
1618c2ecf20Sopenharmony_ci		return -EINVAL;
1628c2ecf20Sopenharmony_ci	}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	return 0;
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp,
1688c2ecf20Sopenharmony_ci					      int *val)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	int ret;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	ret = regmap_read(axp->regmap, AXP20X_CHRG_CTRL1, val);
1738c2ecf20Sopenharmony_ci	if (ret)
1748c2ecf20Sopenharmony_ci		return ret;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	*val &= AXP20X_CHRG_CTRL1_TGT_CURR;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	*val = *val * axp->data->ccc_scale + axp->data->ccc_offset;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	return 0;
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic int axp20x_battery_get_prop(struct power_supply *psy,
1848c2ecf20Sopenharmony_ci				   enum power_supply_property psp,
1858c2ecf20Sopenharmony_ci				   union power_supply_propval *val)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
1888c2ecf20Sopenharmony_ci	int ret = 0, reg, val1;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	switch (psp) {
1918c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_PRESENT:
1928c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_ONLINE:
1938c2ecf20Sopenharmony_ci		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
1948c2ecf20Sopenharmony_ci				  &reg);
1958c2ecf20Sopenharmony_ci		if (ret)
1968c2ecf20Sopenharmony_ci			return ret;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci		val->intval = !!(reg & AXP20X_PWR_OP_BATT_PRESENT);
1998c2ecf20Sopenharmony_ci		break;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_STATUS:
2028c2ecf20Sopenharmony_ci		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
2038c2ecf20Sopenharmony_ci				  &reg);
2048c2ecf20Sopenharmony_ci		if (ret)
2058c2ecf20Sopenharmony_ci			return ret;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci		if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
2088c2ecf20Sopenharmony_ci			val->intval = POWER_SUPPLY_STATUS_CHARGING;
2098c2ecf20Sopenharmony_ci			return 0;
2108c2ecf20Sopenharmony_ci		}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci		ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i,
2138c2ecf20Sopenharmony_ci						 &val1);
2148c2ecf20Sopenharmony_ci		if (ret)
2158c2ecf20Sopenharmony_ci			return ret;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		if (val1) {
2188c2ecf20Sopenharmony_ci			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
2198c2ecf20Sopenharmony_ci			return 0;
2208c2ecf20Sopenharmony_ci		}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci		ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &val1);
2238c2ecf20Sopenharmony_ci		if (ret)
2248c2ecf20Sopenharmony_ci			return ret;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci		/*
2278c2ecf20Sopenharmony_ci		 * Fuel Gauge data takes 7 bits but the stored value seems to be
2288c2ecf20Sopenharmony_ci		 * directly the raw percentage without any scaling to 7 bits.
2298c2ecf20Sopenharmony_ci		 */
2308c2ecf20Sopenharmony_ci		if ((val1 & AXP209_FG_PERCENT) == 100)
2318c2ecf20Sopenharmony_ci			val->intval = POWER_SUPPLY_STATUS_FULL;
2328c2ecf20Sopenharmony_ci		else
2338c2ecf20Sopenharmony_ci			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
2348c2ecf20Sopenharmony_ci		break;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_HEALTH:
2378c2ecf20Sopenharmony_ci		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
2388c2ecf20Sopenharmony_ci				  &val1);
2398c2ecf20Sopenharmony_ci		if (ret)
2408c2ecf20Sopenharmony_ci			return ret;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci		if (val1 & AXP20X_PWR_OP_BATT_ACTIVATED) {
2438c2ecf20Sopenharmony_ci			val->intval = POWER_SUPPLY_HEALTH_DEAD;
2448c2ecf20Sopenharmony_ci			return 0;
2458c2ecf20Sopenharmony_ci		}
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci		val->intval = POWER_SUPPLY_HEALTH_GOOD;
2488c2ecf20Sopenharmony_ci		break;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
2518c2ecf20Sopenharmony_ci		ret = axp20x_get_constant_charge_current(axp20x_batt,
2528c2ecf20Sopenharmony_ci							 &val->intval);
2538c2ecf20Sopenharmony_ci		if (ret)
2548c2ecf20Sopenharmony_ci			return ret;
2558c2ecf20Sopenharmony_ci		break;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
2588c2ecf20Sopenharmony_ci		val->intval = axp20x_batt->max_ccc;
2598c2ecf20Sopenharmony_ci		break;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_CURRENT_NOW:
2628c2ecf20Sopenharmony_ci		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
2638c2ecf20Sopenharmony_ci				  &reg);
2648c2ecf20Sopenharmony_ci		if (ret)
2658c2ecf20Sopenharmony_ci			return ret;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci		if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
2688c2ecf20Sopenharmony_ci			ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
2698c2ecf20Sopenharmony_ci		} else {
2708c2ecf20Sopenharmony_ci			ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i, &val1);
2718c2ecf20Sopenharmony_ci			val->intval = -val1;
2728c2ecf20Sopenharmony_ci		}
2738c2ecf20Sopenharmony_ci		if (ret)
2748c2ecf20Sopenharmony_ci			return ret;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci		/* IIO framework gives mA but Power Supply framework gives uA */
2778c2ecf20Sopenharmony_ci		val->intval *= 1000;
2788c2ecf20Sopenharmony_ci		break;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_CAPACITY:
2818c2ecf20Sopenharmony_ci		/* When no battery is present, return capacity is 100% */
2828c2ecf20Sopenharmony_ci		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
2838c2ecf20Sopenharmony_ci				  &reg);
2848c2ecf20Sopenharmony_ci		if (ret)
2858c2ecf20Sopenharmony_ci			return ret;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci		if (!(reg & AXP20X_PWR_OP_BATT_PRESENT)) {
2888c2ecf20Sopenharmony_ci			val->intval = 100;
2898c2ecf20Sopenharmony_ci			return 0;
2908c2ecf20Sopenharmony_ci		}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci		ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &reg);
2938c2ecf20Sopenharmony_ci		if (ret)
2948c2ecf20Sopenharmony_ci			return ret;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci		if (axp20x_batt->data->has_fg_valid && !(reg & AXP22X_FG_VALID))
2978c2ecf20Sopenharmony_ci			return -EINVAL;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci		/*
3008c2ecf20Sopenharmony_ci		 * Fuel Gauge data takes 7 bits but the stored value seems to be
3018c2ecf20Sopenharmony_ci		 * directly the raw percentage without any scaling to 7 bits.
3028c2ecf20Sopenharmony_ci		 */
3038c2ecf20Sopenharmony_ci		val->intval = reg & AXP209_FG_PERCENT;
3048c2ecf20Sopenharmony_ci		break;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
3078c2ecf20Sopenharmony_ci		return axp20x_batt->data->get_max_voltage(axp20x_batt,
3088c2ecf20Sopenharmony_ci							  &val->intval);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
3118c2ecf20Sopenharmony_ci		ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, &reg);
3128c2ecf20Sopenharmony_ci		if (ret)
3138c2ecf20Sopenharmony_ci			return ret;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		val->intval = 2600000 + 100000 * (reg & AXP20X_V_OFF_MASK);
3168c2ecf20Sopenharmony_ci		break;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
3198c2ecf20Sopenharmony_ci		ret = iio_read_channel_processed(axp20x_batt->batt_v,
3208c2ecf20Sopenharmony_ci						 &val->intval);
3218c2ecf20Sopenharmony_ci		if (ret)
3228c2ecf20Sopenharmony_ci			return ret;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci		/* IIO framework gives mV but Power Supply framework gives uV */
3258c2ecf20Sopenharmony_ci		val->intval *= 1000;
3268c2ecf20Sopenharmony_ci		break;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	default:
3298c2ecf20Sopenharmony_ci		return -EINVAL;
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	return 0;
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_cistatic int axp22x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
3368c2ecf20Sopenharmony_ci					  int val)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	switch (val) {
3398c2ecf20Sopenharmony_ci	case 4100000:
3408c2ecf20Sopenharmony_ci		val = AXP20X_CHRG_CTRL1_TGT_4_1V;
3418c2ecf20Sopenharmony_ci		break;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	case 4200000:
3448c2ecf20Sopenharmony_ci		val = AXP20X_CHRG_CTRL1_TGT_4_2V;
3458c2ecf20Sopenharmony_ci		break;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	default:
3488c2ecf20Sopenharmony_ci		/*
3498c2ecf20Sopenharmony_ci		 * AXP20x max voltage can be set to 4.36V and AXP22X max voltage
3508c2ecf20Sopenharmony_ci		 * can be set to 4.22V and 4.24V, but these voltages are too
3518c2ecf20Sopenharmony_ci		 * high for Lithium based batteries (AXP PMICs are supposed to
3528c2ecf20Sopenharmony_ci		 * be used with these kinds of battery).
3538c2ecf20Sopenharmony_ci		 */
3548c2ecf20Sopenharmony_ci		return -EINVAL;
3558c2ecf20Sopenharmony_ci	}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
3588c2ecf20Sopenharmony_ci				  AXP20X_CHRG_CTRL1_TGT_VOLT, val);
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
3628c2ecf20Sopenharmony_ci					  int val)
3638c2ecf20Sopenharmony_ci{
3648c2ecf20Sopenharmony_ci	switch (val) {
3658c2ecf20Sopenharmony_ci	case 4100000:
3668c2ecf20Sopenharmony_ci		val = AXP20X_CHRG_CTRL1_TGT_4_1V;
3678c2ecf20Sopenharmony_ci		break;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	case 4150000:
3708c2ecf20Sopenharmony_ci		val = AXP20X_CHRG_CTRL1_TGT_4_15V;
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	case 4200000:
3748c2ecf20Sopenharmony_ci		val = AXP20X_CHRG_CTRL1_TGT_4_2V;
3758c2ecf20Sopenharmony_ci		break;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	default:
3788c2ecf20Sopenharmony_ci		/*
3798c2ecf20Sopenharmony_ci		 * AXP20x max voltage can be set to 4.36V and AXP22X max voltage
3808c2ecf20Sopenharmony_ci		 * can be set to 4.22V and 4.24V, but these voltages are too
3818c2ecf20Sopenharmony_ci		 * high for Lithium based batteries (AXP PMICs are supposed to
3828c2ecf20Sopenharmony_ci		 * be used with these kinds of battery).
3838c2ecf20Sopenharmony_ci		 */
3848c2ecf20Sopenharmony_ci		return -EINVAL;
3858c2ecf20Sopenharmony_ci	}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
3888c2ecf20Sopenharmony_ci				  AXP20X_CHRG_CTRL1_TGT_VOLT, val);
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_cistatic int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
3928c2ecf20Sopenharmony_ci					      int charge_current)
3938c2ecf20Sopenharmony_ci{
3948c2ecf20Sopenharmony_ci	if (charge_current > axp_batt->max_ccc)
3958c2ecf20Sopenharmony_ci		return -EINVAL;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	charge_current = (charge_current - axp_batt->data->ccc_offset) /
3988c2ecf20Sopenharmony_ci		axp_batt->data->ccc_scale;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
4018c2ecf20Sopenharmony_ci		return -EINVAL;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	return regmap_update_bits(axp_batt->regmap, AXP20X_CHRG_CTRL1,
4048c2ecf20Sopenharmony_ci				  AXP20X_CHRG_CTRL1_TGT_CURR, charge_current);
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_cistatic int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps *axp,
4088c2ecf20Sopenharmony_ci						  int charge_current)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	bool lower_max = false;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	charge_current = (charge_current - axp->data->ccc_offset) /
4138c2ecf20Sopenharmony_ci		axp->data->ccc_scale;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
4168c2ecf20Sopenharmony_ci		return -EINVAL;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	charge_current = charge_current * axp->data->ccc_scale +
4198c2ecf20Sopenharmony_ci		axp->data->ccc_offset;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	if (charge_current > axp->max_ccc)
4228c2ecf20Sopenharmony_ci		dev_warn(axp->dev,
4238c2ecf20Sopenharmony_ci			 "Setting max constant charge current higher than previously defined. Note that increasing the constant charge current may damage your battery.\n");
4248c2ecf20Sopenharmony_ci	else
4258c2ecf20Sopenharmony_ci		lower_max = true;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	axp->max_ccc = charge_current;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	if (lower_max) {
4308c2ecf20Sopenharmony_ci		int current_cc;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci		axp20x_get_constant_charge_current(axp, &current_cc);
4338c2ecf20Sopenharmony_ci		if (current_cc > charge_current)
4348c2ecf20Sopenharmony_ci			axp20x_set_constant_charge_current(axp, charge_current);
4358c2ecf20Sopenharmony_ci	}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	return 0;
4388c2ecf20Sopenharmony_ci}
4398c2ecf20Sopenharmony_cistatic int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
4408c2ecf20Sopenharmony_ci					 int min_voltage)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	int val1 = (min_voltage - 2600000) / 100000;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	if (val1 < 0 || val1 > AXP20X_V_OFF_MASK)
4458c2ecf20Sopenharmony_ci		return -EINVAL;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	return regmap_update_bits(axp_batt->regmap, AXP20X_V_OFF,
4488c2ecf20Sopenharmony_ci				  AXP20X_V_OFF_MASK, val1);
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_cistatic int axp20x_battery_set_prop(struct power_supply *psy,
4528c2ecf20Sopenharmony_ci				   enum power_supply_property psp,
4538c2ecf20Sopenharmony_ci				   const union power_supply_propval *val)
4548c2ecf20Sopenharmony_ci{
4558c2ecf20Sopenharmony_ci	struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	switch (psp) {
4588c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
4598c2ecf20Sopenharmony_ci		return axp20x_set_voltage_min_design(axp20x_batt, val->intval);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
4628c2ecf20Sopenharmony_ci		return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
4658c2ecf20Sopenharmony_ci		return axp20x_set_constant_charge_current(axp20x_batt,
4668c2ecf20Sopenharmony_ci							  val->intval);
4678c2ecf20Sopenharmony_ci	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
4688c2ecf20Sopenharmony_ci		return axp20x_set_max_constant_charge_current(axp20x_batt,
4698c2ecf20Sopenharmony_ci							      val->intval);
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	default:
4728c2ecf20Sopenharmony_ci		return -EINVAL;
4738c2ecf20Sopenharmony_ci	}
4748c2ecf20Sopenharmony_ci}
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_cistatic enum power_supply_property axp20x_battery_props[] = {
4778c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_PRESENT,
4788c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_ONLINE,
4798c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_STATUS,
4808c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_VOLTAGE_NOW,
4818c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_CURRENT_NOW,
4828c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
4838c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
4848c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_HEALTH,
4858c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
4868c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
4878c2ecf20Sopenharmony_ci	POWER_SUPPLY_PROP_CAPACITY,
4888c2ecf20Sopenharmony_ci};
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_cistatic int axp20x_battery_prop_writeable(struct power_supply *psy,
4918c2ecf20Sopenharmony_ci					 enum power_supply_property psp)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN ||
4948c2ecf20Sopenharmony_ci	       psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
4958c2ecf20Sopenharmony_ci	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
4968c2ecf20Sopenharmony_ci	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
4978c2ecf20Sopenharmony_ci}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_cistatic const struct power_supply_desc axp20x_batt_ps_desc = {
5008c2ecf20Sopenharmony_ci	.name = "axp20x-battery",
5018c2ecf20Sopenharmony_ci	.type = POWER_SUPPLY_TYPE_BATTERY,
5028c2ecf20Sopenharmony_ci	.properties = axp20x_battery_props,
5038c2ecf20Sopenharmony_ci	.num_properties = ARRAY_SIZE(axp20x_battery_props),
5048c2ecf20Sopenharmony_ci	.property_is_writeable = axp20x_battery_prop_writeable,
5058c2ecf20Sopenharmony_ci	.get_property = axp20x_battery_get_prop,
5068c2ecf20Sopenharmony_ci	.set_property = axp20x_battery_set_prop,
5078c2ecf20Sopenharmony_ci};
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_cistatic const struct axp_data axp209_data = {
5108c2ecf20Sopenharmony_ci	.ccc_scale = 100000,
5118c2ecf20Sopenharmony_ci	.ccc_offset = 300000,
5128c2ecf20Sopenharmony_ci	.get_max_voltage = axp20x_battery_get_max_voltage,
5138c2ecf20Sopenharmony_ci	.set_max_voltage = axp20x_battery_set_max_voltage,
5148c2ecf20Sopenharmony_ci};
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic const struct axp_data axp221_data = {
5178c2ecf20Sopenharmony_ci	.ccc_scale = 150000,
5188c2ecf20Sopenharmony_ci	.ccc_offset = 300000,
5198c2ecf20Sopenharmony_ci	.has_fg_valid = true,
5208c2ecf20Sopenharmony_ci	.get_max_voltage = axp22x_battery_get_max_voltage,
5218c2ecf20Sopenharmony_ci	.set_max_voltage = axp22x_battery_set_max_voltage,
5228c2ecf20Sopenharmony_ci};
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_cistatic const struct axp_data axp813_data = {
5258c2ecf20Sopenharmony_ci	.ccc_scale = 200000,
5268c2ecf20Sopenharmony_ci	.ccc_offset = 200000,
5278c2ecf20Sopenharmony_ci	.has_fg_valid = true,
5288c2ecf20Sopenharmony_ci	.get_max_voltage = axp813_battery_get_max_voltage,
5298c2ecf20Sopenharmony_ci	.set_max_voltage = axp20x_battery_set_max_voltage,
5308c2ecf20Sopenharmony_ci};
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_cistatic const struct of_device_id axp20x_battery_ps_id[] = {
5338c2ecf20Sopenharmony_ci	{
5348c2ecf20Sopenharmony_ci		.compatible = "x-powers,axp209-battery-power-supply",
5358c2ecf20Sopenharmony_ci		.data = (void *)&axp209_data,
5368c2ecf20Sopenharmony_ci	}, {
5378c2ecf20Sopenharmony_ci		.compatible = "x-powers,axp221-battery-power-supply",
5388c2ecf20Sopenharmony_ci		.data = (void *)&axp221_data,
5398c2ecf20Sopenharmony_ci	}, {
5408c2ecf20Sopenharmony_ci		.compatible = "x-powers,axp813-battery-power-supply",
5418c2ecf20Sopenharmony_ci		.data = (void *)&axp813_data,
5428c2ecf20Sopenharmony_ci	}, { /* sentinel */ },
5438c2ecf20Sopenharmony_ci};
5448c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, axp20x_battery_ps_id);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_cistatic int axp20x_power_probe(struct platform_device *pdev)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	struct axp20x_batt_ps *axp20x_batt;
5498c2ecf20Sopenharmony_ci	struct power_supply_config psy_cfg = {};
5508c2ecf20Sopenharmony_ci	struct power_supply_battery_info info;
5518c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	if (!of_device_is_available(pdev->dev.of_node))
5548c2ecf20Sopenharmony_ci		return -ENODEV;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	axp20x_batt = devm_kzalloc(&pdev->dev, sizeof(*axp20x_batt),
5578c2ecf20Sopenharmony_ci				   GFP_KERNEL);
5588c2ecf20Sopenharmony_ci	if (!axp20x_batt)
5598c2ecf20Sopenharmony_ci		return -ENOMEM;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	axp20x_batt->dev = &pdev->dev;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	axp20x_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
5648c2ecf20Sopenharmony_ci	if (IS_ERR(axp20x_batt->batt_v)) {
5658c2ecf20Sopenharmony_ci		if (PTR_ERR(axp20x_batt->batt_v) == -ENODEV)
5668c2ecf20Sopenharmony_ci			return -EPROBE_DEFER;
5678c2ecf20Sopenharmony_ci		return PTR_ERR(axp20x_batt->batt_v);
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	axp20x_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
5718c2ecf20Sopenharmony_ci							"batt_chrg_i");
5728c2ecf20Sopenharmony_ci	if (IS_ERR(axp20x_batt->batt_chrg_i)) {
5738c2ecf20Sopenharmony_ci		if (PTR_ERR(axp20x_batt->batt_chrg_i) == -ENODEV)
5748c2ecf20Sopenharmony_ci			return -EPROBE_DEFER;
5758c2ecf20Sopenharmony_ci		return PTR_ERR(axp20x_batt->batt_chrg_i);
5768c2ecf20Sopenharmony_ci	}
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	axp20x_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev,
5798c2ecf20Sopenharmony_ci							   "batt_dischrg_i");
5808c2ecf20Sopenharmony_ci	if (IS_ERR(axp20x_batt->batt_dischrg_i)) {
5818c2ecf20Sopenharmony_ci		if (PTR_ERR(axp20x_batt->batt_dischrg_i) == -ENODEV)
5828c2ecf20Sopenharmony_ci			return -EPROBE_DEFER;
5838c2ecf20Sopenharmony_ci		return PTR_ERR(axp20x_batt->batt_dischrg_i);
5848c2ecf20Sopenharmony_ci	}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	axp20x_batt->regmap = dev_get_regmap(pdev->dev.parent, NULL);
5878c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, axp20x_batt);
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	psy_cfg.drv_data = axp20x_batt;
5908c2ecf20Sopenharmony_ci	psy_cfg.of_node = pdev->dev.of_node;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	axp20x_batt->data = (struct axp_data *)of_device_get_match_data(dev);
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	axp20x_batt->batt = devm_power_supply_register(&pdev->dev,
5958c2ecf20Sopenharmony_ci						       &axp20x_batt_ps_desc,
5968c2ecf20Sopenharmony_ci						       &psy_cfg);
5978c2ecf20Sopenharmony_ci	if (IS_ERR(axp20x_batt->batt)) {
5988c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to register power supply: %ld\n",
5998c2ecf20Sopenharmony_ci			PTR_ERR(axp20x_batt->batt));
6008c2ecf20Sopenharmony_ci		return PTR_ERR(axp20x_batt->batt);
6018c2ecf20Sopenharmony_ci	}
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
6048c2ecf20Sopenharmony_ci		int vmin = info.voltage_min_design_uv;
6058c2ecf20Sopenharmony_ci		int ccc = info.constant_charge_current_max_ua;
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci		if (vmin > 0 && axp20x_set_voltage_min_design(axp20x_batt,
6088c2ecf20Sopenharmony_ci							      vmin))
6098c2ecf20Sopenharmony_ci			dev_err(&pdev->dev,
6108c2ecf20Sopenharmony_ci				"couldn't set voltage_min_design\n");
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci		/* Set max to unverified value to be able to set CCC */
6138c2ecf20Sopenharmony_ci		axp20x_batt->max_ccc = ccc;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci		if (ccc <= 0 || axp20x_set_constant_charge_current(axp20x_batt,
6168c2ecf20Sopenharmony_ci								   ccc)) {
6178c2ecf20Sopenharmony_ci			dev_err(&pdev->dev,
6188c2ecf20Sopenharmony_ci				"couldn't set constant charge current from DT: fallback to minimum value\n");
6198c2ecf20Sopenharmony_ci			ccc = 300000;
6208c2ecf20Sopenharmony_ci			axp20x_batt->max_ccc = ccc;
6218c2ecf20Sopenharmony_ci			axp20x_set_constant_charge_current(axp20x_batt, ccc);
6228c2ecf20Sopenharmony_ci		}
6238c2ecf20Sopenharmony_ci	}
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	/*
6268c2ecf20Sopenharmony_ci	 * Update max CCC to a valid value if battery info is present or set it
6278c2ecf20Sopenharmony_ci	 * to current register value by default.
6288c2ecf20Sopenharmony_ci	 */
6298c2ecf20Sopenharmony_ci	axp20x_get_constant_charge_current(axp20x_batt,
6308c2ecf20Sopenharmony_ci					   &axp20x_batt->max_ccc);
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	return 0;
6338c2ecf20Sopenharmony_ci}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_cistatic struct platform_driver axp20x_batt_driver = {
6368c2ecf20Sopenharmony_ci	.probe    = axp20x_power_probe,
6378c2ecf20Sopenharmony_ci	.driver   = {
6388c2ecf20Sopenharmony_ci		.name  = "axp20x-battery-power-supply",
6398c2ecf20Sopenharmony_ci		.of_match_table = axp20x_battery_ps_id,
6408c2ecf20Sopenharmony_ci	},
6418c2ecf20Sopenharmony_ci};
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_cimodule_platform_driver(axp20x_batt_driver);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Battery power supply driver for AXP20X and AXP22X PMICs");
6468c2ecf20Sopenharmony_ciMODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
6478c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
648