File Index
Files and directories
Sign in
FILE

axp20x_battery.c

File preview with syntax highlighting.

linux-6.19.14/drivers/power/supply/axp20x_battery.c C
   1/*
   2 * Battery power supply driver for X-Powers AXP20X and AXP22X PMICs
   3 *
   4 * Copyright 2016 Free Electrons NextThing Co.
   5 *	Quentin Schulz <quentin.schulz@free-electrons.com>
   6 *
   7 * This driver is based on a previous upstreaming attempt by:
   8 *	Bruno Prémont <bonbons@linux-vserver.org>
   9 *
  10 * This file is subject to the terms and conditions of the GNU General
  11 * Public License. See the file "COPYING" in the main directory of this
  12 * archive for more details.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 * GNU General Public License for more details.
  18 */
  19
  20#include <linux/bitfield.h>
  21#include <linux/err.h>
  22#include <linux/interrupt.h>
  23#include <linux/irq.h>
  24#include <linux/module.h>
  25#include <linux/of.h>
  26#include <linux/platform_device.h>
  27#include <linux/power_supply.h>
  28#include <linux/regmap.h>
  29#include <linux/slab.h>
  30#include <linux/time.h>
  31#include <linux/iio/iio.h>
  32#include <linux/iio/consumer.h>
  33#include <linux/mfd/axp20x.h>
  34
  35#define AXP20X_PWR_STATUS_BAT_CHARGING	BIT(2)
  36#define AXP717_PWR_STATUS_MASK		GENMASK(6, 5)
  37#define AXP717_PWR_STATUS_BAT_STANDBY	0
  38#define AXP717_PWR_STATUS_BAT_CHRG	1
  39#define AXP717_PWR_STATUS_BAT_DISCHRG	2
  40
  41#define AXP20X_PWR_OP_BATT_PRESENT	BIT(5)
  42#define AXP20X_PWR_OP_BATT_ACTIVATED	BIT(3)
  43#define AXP717_PWR_OP_BATT_PRESENT	BIT(3)
  44
  45#define AXP717_BATT_PMU_FAULT_MASK	GENMASK(2, 0)
  46#define AXP717_BATT_UVLO_2_5V		BIT(2)
  47#define AXP717_BATT_OVER_TEMP		BIT(1)
  48#define AXP717_BATT_UNDER_TEMP		BIT(0)
  49
  50#define AXP209_FG_PERCENT		GENMASK(6, 0)
  51#define AXP22X_FG_VALID			BIT(7)
  52
  53#define AXP20X_CHRG_CTRL1_ENABLE	BIT(7)
  54#define AXP20X_CHRG_CTRL1_TGT_VOLT	GENMASK(6, 5)
  55#define AXP20X_CHRG_CTRL1_TGT_4_1V	(0 << 5)
  56#define AXP20X_CHRG_CTRL1_TGT_4_15V	(1 << 5)
  57#define AXP20X_CHRG_CTRL1_TGT_4_2V	(2 << 5)
  58#define AXP20X_CHRG_CTRL1_TGT_4_36V	(3 << 5)
  59
  60#define AXP22X_CHRG_CTRL1_TGT_4_22V	(1 << 5)
  61#define AXP22X_CHRG_CTRL1_TGT_4_24V	(3 << 5)
  62
  63#define AXP717_CHRG_ENABLE		BIT(1)
  64#define AXP717_CHRG_CV_VOLT_MASK	GENMASK(2, 0)
  65#define AXP717_CHRG_CV_4_0V		0
  66#define AXP717_CHRG_CV_4_1V		1
  67#define AXP717_CHRG_CV_4_2V		2
  68#define AXP717_CHRG_CV_4_35V		3
  69#define AXP717_CHRG_CV_4_4V		4
  70/* Values 5 and 6 reserved. */
  71#define AXP717_CHRG_CV_5_0V		7
  72
  73#define AXP813_CHRG_CTRL1_TGT_4_35V	(3 << 5)
  74
  75#define AXP20X_CHRG_CTRL1_TGT_CURR	GENMASK(3, 0)
  76#define AXP717_ICC_CHARGER_LIM_MASK	GENMASK(5, 0)
  77
  78#define AXP717_ITERM_CHG_LIM_MASK	GENMASK(3, 0)
  79#define AXP717_ITERM_CC_STEP		64000
  80
  81#define AXP20X_V_OFF_MASK		GENMASK(2, 0)
  82#define AXP717_V_OFF_MASK		GENMASK(6, 4)
  83
  84#define AXP717_BAT_VMIN_MIN_UV		2600000
  85#define AXP717_BAT_VMIN_MAX_UV		3300000
  86#define AXP717_BAT_VMIN_STEP		100000
  87#define AXP717_BAT_CV_MIN_UV		4000000
  88#define AXP717_BAT_CV_MAX_UV		5000000
  89#define AXP717_BAT_CC_MIN_UA		0
  90#define AXP717_BAT_CC_MAX_UA		3008000
  91
  92#define AXP717_TS_PIN_DISABLE		BIT(4)
  93
  94struct axp20x_batt_ps;
  95
  96struct axp_data {
  97	int		ccc_scale;
  98	int		ccc_offset;
  99	unsigned int	ccc_reg;
 100	unsigned int	ccc_mask;
 101	bool		has_fg_valid;
 102	const struct	power_supply_desc *bat_ps_desc;
 103	int	(*get_max_voltage)(struct axp20x_batt_ps *batt, int *val);
 104	int	(*set_max_voltage)(struct axp20x_batt_ps *batt, int val);
 105	int	(*cfg_iio_chan)(struct platform_device *pdev,
 106				struct axp20x_batt_ps *axp_batt);
 107	void	(*set_bat_info)(struct platform_device *pdev,
 108				struct axp20x_batt_ps *axp_batt,
 109				struct power_supply_battery_info *info);
 110};
 111
 112struct axp20x_batt_ps {
 113	struct regmap *regmap;
 114	struct power_supply *batt;
 115	struct device *dev;
 116	struct iio_channel *batt_chrg_i;
 117	struct iio_channel *batt_dischrg_i;
 118	struct iio_channel *batt_v;
 119	/* Maximum constant charge current */
 120	unsigned int max_ccc;
 121	const struct axp_data	*data;
 122	bool ts_disable;
 123};
 124
 125static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
 126					  int *val)
 127{
 128	int ret, reg;
 129
 130	ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
 131	if (ret)
 132		return ret;
 133
 134	switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
 135	case AXP20X_CHRG_CTRL1_TGT_4_1V:
 136		*val = 4100000;
 137		break;
 138	case AXP20X_CHRG_CTRL1_TGT_4_15V:
 139		*val = 4150000;
 140		break;
 141	case AXP20X_CHRG_CTRL1_TGT_4_2V:
 142		*val = 4200000;
 143		break;
 144	case AXP20X_CHRG_CTRL1_TGT_4_36V:
 145		*val = 4360000;
 146		break;
 147	default:
 148		return -EINVAL;
 149	}
 150
 151	return 0;
 152}
 153
 154static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
 155					  int *val)
 156{
 157	int ret, reg;
 158
 159	ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
 160	if (ret)
 161		return ret;
 162
 163	switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
 164	case AXP20X_CHRG_CTRL1_TGT_4_1V:
 165		*val = 4100000;
 166		break;
 167	case AXP20X_CHRG_CTRL1_TGT_4_2V:
 168		*val = 4200000;
 169		break;
 170	case AXP22X_CHRG_CTRL1_TGT_4_22V:
 171		*val = 4220000;
 172		break;
 173	case AXP22X_CHRG_CTRL1_TGT_4_24V:
 174		*val = 4240000;
 175		break;
 176	default:
 177		return -EINVAL;
 178	}
 179
 180	return 0;
 181}
 182
 183static int axp717_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
 184					  int *val)
 185{
 186	int ret, reg;
 187
 188	ret = regmap_read(axp20x_batt->regmap, AXP717_CV_CHG_SET, &reg);
 189	if (ret)
 190		return ret;
 191
 192	switch (reg & AXP717_CHRG_CV_VOLT_MASK) {
 193	case AXP717_CHRG_CV_4_0V:
 194		*val = 4000000;
 195		return 0;
 196	case AXP717_CHRG_CV_4_1V:
 197		*val = 4100000;
 198		return 0;
 199	case AXP717_CHRG_CV_4_2V:
 200		*val = 4200000;
 201		return 0;
 202	case AXP717_CHRG_CV_4_35V:
 203		*val = 4350000;
 204		return 0;
 205	case AXP717_CHRG_CV_4_4V:
 206		*val = 4400000;
 207		return 0;
 208	case AXP717_CHRG_CV_5_0V:
 209		*val = 5000000;
 210		return 0;
 211	default:
 212		return -EINVAL;
 213	}
 214}
 215
 216static int axp813_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
 217					  int *val)
 218{
 219	int ret, reg;
 220
 221	ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
 222	if (ret)
 223		return ret;
 224
 225	switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
 226	case AXP20X_CHRG_CTRL1_TGT_4_1V:
 227		*val = 4100000;
 228		break;
 229	case AXP20X_CHRG_CTRL1_TGT_4_15V:
 230		*val = 4150000;
 231		break;
 232	case AXP20X_CHRG_CTRL1_TGT_4_2V:
 233		*val = 4200000;
 234		break;
 235	case AXP813_CHRG_CTRL1_TGT_4_35V:
 236		*val = 4350000;
 237		break;
 238	default:
 239		return -EINVAL;
 240	}
 241
 242	return 0;
 243}
 244
 245static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp,
 246					      int *val)
 247{
 248	int ret;
 249
 250	ret = regmap_read(axp->regmap, AXP20X_CHRG_CTRL1, val);
 251	if (ret)
 252		return ret;
 253
 254	*val &= AXP20X_CHRG_CTRL1_TGT_CURR;
 255
 256	*val = *val * axp->data->ccc_scale + axp->data->ccc_offset;
 257
 258	return 0;
 259}
 260
 261static int axp717_get_constant_charge_current(struct axp20x_batt_ps *axp,
 262					      int *val)
 263{
 264	int ret;
 265
 266	ret = regmap_read(axp->regmap, AXP717_ICC_CHG_SET, val);
 267	if (ret)
 268		return ret;
 269
 270	*val = FIELD_GET(AXP717_ICC_CHARGER_LIM_MASK, *val) *
 271		axp->data->ccc_scale;
 272
 273	return 0;
 274}
 275
 276static int axp20x_battery_get_prop(struct power_supply *psy,
 277				   enum power_supply_property psp,
 278				   union power_supply_propval *val)
 279{
 280	struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
 281	int ret = 0, reg, val1;
 282
 283	switch (psp) {
 284	case POWER_SUPPLY_PROP_PRESENT:
 285	case POWER_SUPPLY_PROP_ONLINE:
 286		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
 287				  &reg);
 288		if (ret)
 289			return ret;
 290
 291		val->intval = !!(reg & AXP20X_PWR_OP_BATT_PRESENT);
 292		break;
 293
 294	case POWER_SUPPLY_PROP_STATUS:
 295		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
 296				  &reg);
 297		if (ret)
 298			return ret;
 299
 300		if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
 301			val->intval = POWER_SUPPLY_STATUS_CHARGING;
 302			return 0;
 303		}
 304
 305		ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i,
 306						 &val1);
 307		if (ret)
 308			return ret;
 309
 310		if (val1) {
 311			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
 312			return 0;
 313		}
 314
 315		ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &val1);
 316		if (ret)
 317			return ret;
 318
 319		/*
 320		 * Fuel Gauge data takes 7 bits but the stored value seems to be
 321		 * directly the raw percentage without any scaling to 7 bits.
 322		 */
 323		if ((val1 & AXP209_FG_PERCENT) == 100)
 324			val->intval = POWER_SUPPLY_STATUS_FULL;
 325		else
 326			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
 327		break;
 328
 329	case POWER_SUPPLY_PROP_HEALTH:
 330		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
 331				  &val1);
 332		if (ret)
 333			return ret;
 334
 335		if (val1 & AXP20X_PWR_OP_BATT_ACTIVATED) {
 336			val->intval = POWER_SUPPLY_HEALTH_DEAD;
 337			return 0;
 338		}
 339
 340		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 341		break;
 342
 343	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 344		ret = axp20x_get_constant_charge_current(axp20x_batt,
 345							 &val->intval);
 346		if (ret)
 347			return ret;
 348		break;
 349
 350	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 351		val->intval = axp20x_batt->max_ccc;
 352		break;
 353
 354	case POWER_SUPPLY_PROP_CURRENT_NOW:
 355		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
 356				  &reg);
 357		if (ret)
 358			return ret;
 359
 360		/* IIO framework gives mA but Power Supply framework gives uA */
 361		if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
 362			ret = iio_read_channel_processed_scale(axp20x_batt->batt_chrg_i,
 363							       &val->intval, 1000);
 364		} else {
 365			ret = iio_read_channel_processed_scale(axp20x_batt->batt_dischrg_i,
 366							       &val1, 1000);
 367			val->intval = -val1;
 368		}
 369		if (ret)
 370			return ret;
 371
 372		break;
 373
 374	case POWER_SUPPLY_PROP_CAPACITY:
 375		/* When no battery is present, return capacity is 100% */
 376		ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
 377				  &reg);
 378		if (ret)
 379			return ret;
 380
 381		if (!(reg & AXP20X_PWR_OP_BATT_PRESENT)) {
 382			val->intval = 100;
 383			return 0;
 384		}
 385
 386		ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &reg);
 387		if (ret)
 388			return ret;
 389
 390		if (axp20x_batt->data->has_fg_valid && !(reg & AXP22X_FG_VALID))
 391			return -EINVAL;
 392
 393		/*
 394		 * Fuel Gauge data takes 7 bits but the stored value seems to be
 395		 * directly the raw percentage without any scaling to 7 bits.
 396		 */
 397		val->intval = reg & AXP209_FG_PERCENT;
 398		break;
 399
 400	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 401		return axp20x_batt->data->get_max_voltage(axp20x_batt,
 402							  &val->intval);
 403
 404	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 405		ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, &reg);
 406		if (ret)
 407			return ret;
 408
 409		val->intval = 2600000 + 100000 * (reg & AXP20X_V_OFF_MASK);
 410		break;
 411
 412	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 413		/* IIO framework gives mV but Power Supply framework gives uV */
 414		ret = iio_read_channel_processed_scale(axp20x_batt->batt_v,
 415						 &val->intval, 1000);
 416		if (ret)
 417			return ret;
 418
 419		break;
 420
 421	default:
 422		return -EINVAL;
 423	}
 424
 425	return 0;
 426}
 427
 428static int axp717_battery_get_prop(struct power_supply *psy,
 429				   enum power_supply_property psp,
 430				   union power_supply_propval *val)
 431{
 432	struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
 433	int ret = 0, reg;
 434
 435	switch (psp) {
 436	case POWER_SUPPLY_PROP_PRESENT:
 437	case POWER_SUPPLY_PROP_ONLINE:
 438		ret = regmap_read(axp20x_batt->regmap, AXP717_ON_INDICATE,
 439				  &reg);
 440		if (ret)
 441			return ret;
 442
 443		val->intval = FIELD_GET(AXP717_PWR_OP_BATT_PRESENT, reg);
 444		return 0;
 445
 446	case POWER_SUPPLY_PROP_STATUS:
 447		ret = regmap_read(axp20x_batt->regmap, AXP717_PMU_STATUS_2,
 448				  &reg);
 449		if (ret)
 450			return ret;
 451
 452		switch (FIELD_GET(AXP717_PWR_STATUS_MASK, reg)) {
 453		case AXP717_PWR_STATUS_BAT_STANDBY:
 454			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
 455			return 0;
 456
 457		case AXP717_PWR_STATUS_BAT_CHRG:
 458			val->intval = POWER_SUPPLY_STATUS_CHARGING;
 459			return 0;
 460
 461		case AXP717_PWR_STATUS_BAT_DISCHRG:
 462			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
 463			return 0;
 464
 465		default:
 466			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
 467			return 0;
 468		}
 469
 470	/*
 471	 * If a fault is detected it must also be cleared; if the
 472	 * condition persists it should reappear. A restart was not
 473	 * sufficient to clear the bit in testing despite the register
 474	 * listed as POR.
 475	 */
 476	case POWER_SUPPLY_PROP_HEALTH:
 477		ret = regmap_read(axp20x_batt->regmap, AXP717_PMU_FAULT,
 478				  &reg);
 479		if (ret)
 480			return ret;
 481
 482		switch (reg & AXP717_BATT_PMU_FAULT_MASK) {
 483		case AXP717_BATT_UVLO_2_5V:
 484			val->intval = POWER_SUPPLY_HEALTH_DEAD;
 485			regmap_write_bits(axp20x_batt->regmap,
 486					  AXP717_PMU_FAULT,
 487					  AXP717_BATT_UVLO_2_5V,
 488					  AXP717_BATT_UVLO_2_5V);
 489			return 0;
 490
 491		case AXP717_BATT_OVER_TEMP:
 492			val->intval = POWER_SUPPLY_HEALTH_HOT;
 493			regmap_write_bits(axp20x_batt->regmap,
 494					  AXP717_PMU_FAULT,
 495					  AXP717_BATT_OVER_TEMP,
 496					  AXP717_BATT_OVER_TEMP);
 497			return 0;
 498
 499		case AXP717_BATT_UNDER_TEMP:
 500			val->intval = POWER_SUPPLY_HEALTH_COLD;
 501			regmap_write_bits(axp20x_batt->regmap,
 502					  AXP717_PMU_FAULT,
 503					  AXP717_BATT_UNDER_TEMP,
 504					  AXP717_BATT_UNDER_TEMP);
 505			return 0;
 506
 507		default:
 508			val->intval = POWER_SUPPLY_HEALTH_GOOD;
 509			return 0;
 510		}
 511
 512	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 513		ret = axp717_get_constant_charge_current(axp20x_batt,
 514							 &val->intval);
 515		if (ret)
 516			return ret;
 517		return 0;
 518
 519	case POWER_SUPPLY_PROP_CURRENT_NOW:
 520		/*
 521		 * The offset of this value is currently unknown and is
 522		 * not documented in the datasheet. Based on
 523		 * observation it's assumed to be somewhere around
 524		 * 450ma. I will leave the value raw for now. Note that
 525		 * IIO framework gives mA but Power Supply framework
 526		 * gives uA.
 527		 */
 528		ret = iio_read_channel_processed_scale(axp20x_batt->batt_chrg_i,
 529						       &val->intval, 1000);
 530		if (ret)
 531			return ret;
 532
 533		return 0;
 534
 535	case POWER_SUPPLY_PROP_CAPACITY:
 536		ret = regmap_read(axp20x_batt->regmap, AXP717_ON_INDICATE,
 537				  &reg);
 538		if (ret)
 539			return ret;
 540
 541		if (!FIELD_GET(AXP717_PWR_OP_BATT_PRESENT, reg))
 542			return -ENODEV;
 543
 544		ret = regmap_read(axp20x_batt->regmap,
 545				  AXP717_BATT_PERCENT_DATA, &reg);
 546		if (ret)
 547			return ret;
 548
 549		/*
 550		 * Fuel Gauge data takes 7 bits but the stored value seems to be
 551		 * directly the raw percentage without any scaling to 7 bits.
 552		 */
 553		val->intval = reg & AXP209_FG_PERCENT;
 554		return 0;
 555
 556	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 557		return axp20x_batt->data->get_max_voltage(axp20x_batt,
 558							  &val->intval);
 559
 560	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 561		ret = regmap_read(axp20x_batt->regmap,
 562				  AXP717_VSYS_V_POWEROFF, &reg);
 563		if (ret)
 564			return ret;
 565
 566		val->intval = AXP717_BAT_VMIN_MIN_UV + AXP717_BAT_VMIN_STEP *
 567			(reg & AXP717_V_OFF_MASK);
 568		return 0;
 569
 570	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 571		/* IIO framework gives mV but Power Supply framework gives uV */
 572		ret = iio_read_channel_processed_scale(axp20x_batt->batt_v,
 573						       &val->intval, 1000);
 574		if (ret)
 575			return ret;
 576
 577		return 0;
 578
 579	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
 580		ret = regmap_read(axp20x_batt->regmap,
 581				  AXP717_ITERM_CHG_SET, &reg);
 582		if (ret)
 583			return ret;
 584
 585		val->intval = (reg & AXP717_ITERM_CHG_LIM_MASK) * AXP717_ITERM_CC_STEP;
 586		return 0;
 587
 588	default:
 589		return -EINVAL;
 590	}
 591}
 592
 593static int axp22x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
 594					  int val)
 595{
 596	switch (val) {
 597	case 4100000:
 598		val = AXP20X_CHRG_CTRL1_TGT_4_1V;
 599		break;
 600
 601	case 4200000:
 602		val = AXP20X_CHRG_CTRL1_TGT_4_2V;
 603		break;
 604
 605	default:
 606		/*
 607		 * AXP20x max voltage can be set to 4.36V and AXP22X max voltage
 608		 * can be set to 4.22V and 4.24V, but these voltages are too
 609		 * high for Lithium based batteries (AXP PMICs are supposed to
 610		 * be used with these kinds of battery).
 611		 */
 612		return -EINVAL;
 613	}
 614
 615	return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
 616				  AXP20X_CHRG_CTRL1_TGT_VOLT, val);
 617}
 618
 619static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
 620					  int val)
 621{
 622	switch (val) {
 623	case 4100000:
 624		val = AXP20X_CHRG_CTRL1_TGT_4_1V;
 625		break;
 626
 627	case 4150000:
 628		val = AXP20X_CHRG_CTRL1_TGT_4_15V;
 629		break;
 630
 631	case 4200000:
 632		val = AXP20X_CHRG_CTRL1_TGT_4_2V;
 633		break;
 634
 635	default:
 636		/*
 637		 * AXP20x max voltage can be set to 4.36V and AXP22X max voltage
 638		 * can be set to 4.22V and 4.24V, but these voltages are too
 639		 * high for Lithium based batteries (AXP PMICs are supposed to
 640		 * be used with these kinds of battery).
 641		 */
 642		return -EINVAL;
 643	}
 644
 645	return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
 646				  AXP20X_CHRG_CTRL1_TGT_VOLT, val);
 647}
 648
 649static int axp717_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
 650					  int val)
 651{
 652	switch (val) {
 653	case 4000000:
 654		val = AXP717_CHRG_CV_4_0V;
 655		break;
 656
 657	case 4100000:
 658		val = AXP717_CHRG_CV_4_1V;
 659		break;
 660
 661	case 4200000:
 662		val = AXP717_CHRG_CV_4_2V;
 663		break;
 664
 665	default:
 666		/*
 667		 * AXP717 can go up to 4.35, 4.4, and 5.0 volts which
 668		 * seem too high for lithium batteries, so do not allow.
 669		 */
 670		return -EINVAL;
 671	}
 672
 673	return regmap_update_bits(axp20x_batt->regmap,
 674				  AXP717_CV_CHG_SET,
 675				  AXP717_CHRG_CV_VOLT_MASK, val);
 676}
 677
 678static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
 679					      int charge_current)
 680{
 681	if (charge_current > axp_batt->max_ccc)
 682		return -EINVAL;
 683
 684	charge_current = (charge_current - axp_batt->data->ccc_offset) /
 685		axp_batt->data->ccc_scale;
 686
 687	if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
 688		return -EINVAL;
 689
 690	return regmap_update_bits(axp_batt->regmap, AXP20X_CHRG_CTRL1,
 691				  AXP20X_CHRG_CTRL1_TGT_CURR, charge_current);
 692}
 693
 694static int axp717_set_constant_charge_current(struct axp20x_batt_ps *axp,
 695					      int charge_current)
 696{
 697	int val;
 698
 699	if (charge_current > axp->max_ccc)
 700		return -EINVAL;
 701
 702	if (charge_current > AXP717_BAT_CC_MAX_UA || charge_current < 0)
 703		return -EINVAL;
 704
 705	val = (charge_current - axp->data->ccc_offset) /
 706		axp->data->ccc_scale;
 707
 708	return regmap_update_bits(axp->regmap, AXP717_ICC_CHG_SET,
 709				  AXP717_ICC_CHARGER_LIM_MASK, val);
 710}
 711
 712static int axp20x_set_max_constant_charge_current(struct axp20x_batt_ps *axp,
 713						  int charge_current)
 714{
 715	bool lower_max = false;
 716
 717	charge_current = (charge_current - axp->data->ccc_offset) /
 718		axp->data->ccc_scale;
 719
 720	if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
 721		return -EINVAL;
 722
 723	charge_current = charge_current * axp->data->ccc_scale +
 724		axp->data->ccc_offset;
 725
 726	if (charge_current > axp->max_ccc)
 727		dev_warn(axp->dev,
 728			 "Setting max constant charge current higher than previously defined. Note that increasing the constant charge current may damage your battery.\n");
 729	else
 730		lower_max = true;
 731
 732	axp->max_ccc = charge_current;
 733
 734	if (lower_max) {
 735		int current_cc;
 736
 737		axp20x_get_constant_charge_current(axp, &current_cc);
 738		if (current_cc > charge_current)
 739			axp20x_set_constant_charge_current(axp, charge_current);
 740	}
 741
 742	return 0;
 743}
 744static int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
 745					 int min_voltage)
 746{
 747	int val1 = (min_voltage - 2600000) / 100000;
 748
 749	if (val1 < 0 || val1 > AXP20X_V_OFF_MASK)
 750		return -EINVAL;
 751
 752	return regmap_update_bits(axp_batt->regmap, AXP20X_V_OFF,
 753				  AXP20X_V_OFF_MASK, val1);
 754}
 755
 756static int axp717_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
 757					 int min_voltage)
 758{
 759	int val1 = (min_voltage - AXP717_BAT_VMIN_MIN_UV) / AXP717_BAT_VMIN_STEP;
 760
 761	if (val1 < 0 || val1 > AXP717_V_OFF_MASK)
 762		return -EINVAL;
 763
 764	return regmap_update_bits(axp_batt->regmap,
 765				  AXP717_VSYS_V_POWEROFF,
 766				  AXP717_V_OFF_MASK, val1);
 767}
 768
 769static int axp20x_battery_set_prop(struct power_supply *psy,
 770				   enum power_supply_property psp,
 771				   const union power_supply_propval *val)
 772{
 773	struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
 774
 775	switch (psp) {
 776	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 777		return axp20x_set_voltage_min_design(axp20x_batt, val->intval);
 778
 779	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 780		return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
 781
 782	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 783		return axp20x_set_constant_charge_current(axp20x_batt,
 784							  val->intval);
 785	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 786		return axp20x_set_max_constant_charge_current(axp20x_batt,
 787							      val->intval);
 788	case POWER_SUPPLY_PROP_STATUS:
 789		switch (val->intval) {
 790		case POWER_SUPPLY_STATUS_CHARGING:
 791			return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
 792				AXP20X_CHRG_CTRL1_ENABLE, AXP20X_CHRG_CTRL1_ENABLE);
 793
 794		case POWER_SUPPLY_STATUS_DISCHARGING:
 795		case POWER_SUPPLY_STATUS_NOT_CHARGING:
 796			return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
 797				AXP20X_CHRG_CTRL1_ENABLE, 0);
 798		}
 799		fallthrough;
 800	default:
 801		return -EINVAL;
 802	}
 803}
 804
 805static int axp717_battery_set_prop(struct power_supply *psy,
 806				   enum power_supply_property psp,
 807				   const union power_supply_propval *val)
 808{
 809	struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
 810
 811	switch (psp) {
 812	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 813		return axp717_set_voltage_min_design(axp20x_batt, val->intval);
 814
 815	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 816		return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
 817
 818	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 819		return axp717_set_constant_charge_current(axp20x_batt,
 820							  val->intval);
 821	case POWER_SUPPLY_PROP_STATUS:
 822		switch (val->intval) {
 823		case POWER_SUPPLY_STATUS_CHARGING:
 824			return regmap_update_bits(axp20x_batt->regmap,
 825						  AXP717_MODULE_EN_CONTROL_2,
 826						  AXP717_CHRG_ENABLE,
 827						  AXP717_CHRG_ENABLE);
 828
 829		case POWER_SUPPLY_STATUS_DISCHARGING:
 830		case POWER_SUPPLY_STATUS_NOT_CHARGING:
 831			return regmap_update_bits(axp20x_batt->regmap,
 832						  AXP717_MODULE_EN_CONTROL_2,
 833						  AXP717_CHRG_ENABLE, 0);
 834		}
 835		return -EINVAL;
 836	default:
 837		return -EINVAL;
 838	}
 839}
 840
 841static enum power_supply_property axp20x_battery_props[] = {
 842	POWER_SUPPLY_PROP_PRESENT,
 843	POWER_SUPPLY_PROP_ONLINE,
 844	POWER_SUPPLY_PROP_STATUS,
 845	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 846	POWER_SUPPLY_PROP_CURRENT_NOW,
 847	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
 848	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
 849	POWER_SUPPLY_PROP_HEALTH,
 850	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 851	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 852	POWER_SUPPLY_PROP_CAPACITY,
 853};
 854
 855static enum power_supply_property axp717_battery_props[] = {
 856	POWER_SUPPLY_PROP_PRESENT,
 857	POWER_SUPPLY_PROP_ONLINE,
 858	POWER_SUPPLY_PROP_STATUS,
 859	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 860	POWER_SUPPLY_PROP_CURRENT_NOW,
 861	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
 862	POWER_SUPPLY_PROP_HEALTH,
 863	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 864	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 865	POWER_SUPPLY_PROP_CAPACITY,
 866	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
 867};
 868
 869static int axp20x_battery_prop_writeable(struct power_supply *psy,
 870					 enum power_supply_property psp)
 871{
 872	return psp == POWER_SUPPLY_PROP_STATUS ||
 873	       psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
 874	       psp == POWER_SUPPLY_PROP_VOLTAGE_MAX ||
 875	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
 876	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
 877}
 878
 879static int axp717_battery_prop_writeable(struct power_supply *psy,
 880					 enum power_supply_property psp)
 881{
 882	return psp == POWER_SUPPLY_PROP_STATUS ||
 883	       psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
 884	       psp == POWER_SUPPLY_PROP_VOLTAGE_MAX ||
 885	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
 886}
 887
 888static const struct power_supply_desc axp209_batt_ps_desc = {
 889	.name = "axp20x-battery",
 890	.type = POWER_SUPPLY_TYPE_BATTERY,
 891	.properties = axp20x_battery_props,
 892	.num_properties = ARRAY_SIZE(axp20x_battery_props),
 893	.property_is_writeable = axp20x_battery_prop_writeable,
 894	.get_property = axp20x_battery_get_prop,
 895	.set_property = axp20x_battery_set_prop,
 896};
 897
 898static const struct power_supply_desc axp717_batt_ps_desc = {
 899	.name = "axp20x-battery",
 900	.type = POWER_SUPPLY_TYPE_BATTERY,
 901	.properties = axp717_battery_props,
 902	.num_properties = ARRAY_SIZE(axp717_battery_props),
 903	.property_is_writeable = axp717_battery_prop_writeable,
 904	.get_property = axp717_battery_get_prop,
 905	.set_property = axp717_battery_set_prop,
 906};
 907
 908static int axp209_bat_cfg_iio_channels(struct platform_device *pdev,
 909				       struct axp20x_batt_ps *axp_batt)
 910{
 911	axp_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
 912	if (IS_ERR(axp_batt->batt_v)) {
 913		if (PTR_ERR(axp_batt->batt_v) == -ENODEV)
 914			return -EPROBE_DEFER;
 915		return PTR_ERR(axp_batt->batt_v);
 916	}
 917
 918	axp_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
 919							"batt_chrg_i");
 920	if (IS_ERR(axp_batt->batt_chrg_i)) {
 921		if (PTR_ERR(axp_batt->batt_chrg_i) == -ENODEV)
 922			return -EPROBE_DEFER;
 923		return PTR_ERR(axp_batt->batt_chrg_i);
 924	}
 925
 926	axp_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev,
 927							   "batt_dischrg_i");
 928	if (IS_ERR(axp_batt->batt_dischrg_i)) {
 929		if (PTR_ERR(axp_batt->batt_dischrg_i) == -ENODEV)
 930			return -EPROBE_DEFER;
 931		return PTR_ERR(axp_batt->batt_dischrg_i);
 932	}
 933
 934	return 0;
 935}
 936
 937static int axp717_bat_cfg_iio_channels(struct platform_device *pdev,
 938				       struct axp20x_batt_ps *axp_batt)
 939{
 940	axp_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
 941	if (IS_ERR(axp_batt->batt_v)) {
 942		if (PTR_ERR(axp_batt->batt_v) == -ENODEV)
 943			return -EPROBE_DEFER;
 944		return PTR_ERR(axp_batt->batt_v);
 945	}
 946
 947	axp_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
 948							"batt_chrg_i");
 949	if (IS_ERR(axp_batt->batt_chrg_i)) {
 950		if (PTR_ERR(axp_batt->batt_chrg_i) == -ENODEV)
 951			return -EPROBE_DEFER;
 952		return PTR_ERR(axp_batt->batt_chrg_i);
 953	}
 954
 955	return 0;
 956}
 957
 958static void axp209_set_battery_info(struct platform_device *pdev,
 959				    struct axp20x_batt_ps *axp_batt,
 960				    struct power_supply_battery_info *info)
 961{
 962	int vmin = info->voltage_min_design_uv;
 963	int ccc = info->constant_charge_current_max_ua;
 964
 965	if (vmin > 0 && axp20x_set_voltage_min_design(axp_batt, vmin))
 966		dev_err(&pdev->dev,
 967			"couldn't set voltage_min_design\n");
 968
 969	/* Set max to unverified value to be able to set CCC */
 970	axp_batt->max_ccc = ccc;
 971
 972	if (ccc <= 0 || axp20x_set_constant_charge_current(axp_batt, ccc)) {
 973		dev_err(&pdev->dev,
 974			"couldn't set ccc from DT: fallback to min value\n");
 975		ccc = 300000;
 976		axp_batt->max_ccc = ccc;
 977		axp20x_set_constant_charge_current(axp_batt, ccc);
 978	}
 979}
 980
 981static void axp717_set_battery_info(struct platform_device *pdev,
 982				    struct axp20x_batt_ps *axp_batt,
 983				    struct power_supply_battery_info *info)
 984{
 985	int vmin = info->voltage_min_design_uv;
 986	int vmax = info->voltage_max_design_uv;
 987	int ccc = info->constant_charge_current_max_ua;
 988	int val;
 989
 990	axp_batt->ts_disable = (device_property_read_bool(axp_batt->dev,
 991							  "x-powers,no-thermistor"));
 992
 993	/*
 994	 * Under rare conditions an incorrectly programmed efuse for
 995	 * the temp sensor on the PMIC may trigger a fault condition.
 996	 * Allow users to hard-code if the ts pin is not used to work
 997	 * around this problem. Note that this requires the battery
 998	 * be correctly defined in the device tree with a monitored
 999	 * battery node.
1000	 */
1001	if (axp_batt->ts_disable) {
1002		regmap_update_bits(axp_batt->regmap,
1003				   AXP717_TS_PIN_CFG,
1004				   AXP717_TS_PIN_DISABLE,
1005				   AXP717_TS_PIN_DISABLE);
1006	}
1007
1008	if (vmin > 0 && axp717_set_voltage_min_design(axp_batt, vmin))
1009		dev_err(&pdev->dev,
1010			"couldn't set voltage_min_design\n");
1011
1012	if (vmax > 0 && axp717_battery_set_max_voltage(axp_batt, vmax))
1013		dev_err(&pdev->dev,
1014			"couldn't set voltage_max_design\n");
1015
1016	axp717_get_constant_charge_current(axp_batt, &val);
1017	axp_batt->max_ccc = ccc;
1018	if (ccc <= 0 || axp717_set_constant_charge_current(axp_batt, ccc)) {
1019		dev_err(&pdev->dev,
1020			"couldn't set ccc from DT: current ccc is %d\n",
1021			val);
1022	}
1023}
1024
1025static const struct axp_data axp209_data = {
1026	.ccc_scale = 100000,
1027	.ccc_offset = 300000,
1028	.ccc_reg = AXP20X_CHRG_CTRL1,
1029	.ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
1030	.bat_ps_desc = &axp209_batt_ps_desc,
1031	.get_max_voltage = axp20x_battery_get_max_voltage,
1032	.set_max_voltage = axp20x_battery_set_max_voltage,
1033	.cfg_iio_chan = axp209_bat_cfg_iio_channels,
1034	.set_bat_info = axp209_set_battery_info,
1035};
1036
1037static const struct axp_data axp221_data = {
1038	.ccc_scale = 150000,
1039	.ccc_offset = 300000,
1040	.ccc_reg = AXP20X_CHRG_CTRL1,
1041	.ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
1042	.has_fg_valid = true,
1043	.bat_ps_desc = &axp209_batt_ps_desc,
1044	.get_max_voltage = axp22x_battery_get_max_voltage,
1045	.set_max_voltage = axp22x_battery_set_max_voltage,
1046	.cfg_iio_chan = axp209_bat_cfg_iio_channels,
1047	.set_bat_info = axp209_set_battery_info,
1048};
1049
1050static const struct axp_data axp717_data = {
1051	.ccc_scale = 64000,
1052	.ccc_offset = 0,
1053	.ccc_reg = AXP717_ICC_CHG_SET,
1054	.ccc_mask = AXP717_ICC_CHARGER_LIM_MASK,
1055	.bat_ps_desc = &axp717_batt_ps_desc,
1056	.get_max_voltage = axp717_battery_get_max_voltage,
1057	.set_max_voltage = axp717_battery_set_max_voltage,
1058	.cfg_iio_chan = axp717_bat_cfg_iio_channels,
1059	.set_bat_info = axp717_set_battery_info,
1060};
1061
1062static const struct axp_data axp813_data = {
1063	.ccc_scale = 200000,
1064	.ccc_offset = 200000,
1065	.ccc_reg = AXP20X_CHRG_CTRL1,
1066	.ccc_mask = AXP20X_CHRG_CTRL1_TGT_CURR,
1067	.has_fg_valid = true,
1068	.bat_ps_desc = &axp209_batt_ps_desc,
1069	.get_max_voltage = axp813_battery_get_max_voltage,
1070	.set_max_voltage = axp20x_battery_set_max_voltage,
1071	.cfg_iio_chan = axp209_bat_cfg_iio_channels,
1072	.set_bat_info = axp209_set_battery_info,
1073};
1074
1075static const struct of_device_id axp20x_battery_ps_id[] = {
1076	{
1077		.compatible = "x-powers,axp209-battery-power-supply",
1078		.data = (void *)&axp209_data,
1079	}, {
1080		.compatible = "x-powers,axp221-battery-power-supply",
1081		.data = (void *)&axp221_data,
1082	}, {
1083		.compatible = "x-powers,axp717-battery-power-supply",
1084		.data = (void *)&axp717_data,
1085	}, {
1086		.compatible = "x-powers,axp813-battery-power-supply",
1087		.data = (void *)&axp813_data,
1088	}, { /* sentinel */ },
1089};
1090MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id);
1091
1092static int axp20x_power_probe(struct platform_device *pdev)
1093{
1094	struct axp20x_batt_ps *axp20x_batt;
1095	struct power_supply_config psy_cfg = {};
1096	struct power_supply_battery_info *info;
1097	struct device *dev = &pdev->dev;
1098	int ret;
1099
1100	if (!of_device_is_available(pdev->dev.of_node))
1101		return -ENODEV;
1102
1103	axp20x_batt = devm_kzalloc(&pdev->dev, sizeof(*axp20x_batt),
1104				   GFP_KERNEL);
1105	if (!axp20x_batt)
1106		return -ENOMEM;
1107
1108	axp20x_batt->dev = &pdev->dev;
1109
1110	axp20x_batt->regmap = dev_get_regmap(pdev->dev.parent, NULL);
1111	platform_set_drvdata(pdev, axp20x_batt);
1112
1113	psy_cfg.drv_data = axp20x_batt;
1114	psy_cfg.fwnode = dev_fwnode(&pdev->dev);
1115
1116	axp20x_batt->data = (struct axp_data *)of_device_get_match_data(dev);
1117
1118	ret = axp20x_batt->data->cfg_iio_chan(pdev, axp20x_batt);
1119	if (ret)
1120		return ret;
1121
1122	axp20x_batt->batt = devm_power_supply_register(&pdev->dev,
1123						       axp20x_batt->data->bat_ps_desc,
1124						       &psy_cfg);
1125	if (IS_ERR(axp20x_batt->batt)) {
1126		dev_err(&pdev->dev, "failed to register power supply: %ld\n",
1127			PTR_ERR(axp20x_batt->batt));
1128		return PTR_ERR(axp20x_batt->batt);
1129	}
1130
1131	if (!power_supply_get_battery_info(axp20x_batt->batt, &info)) {
1132		axp20x_batt->data->set_bat_info(pdev, axp20x_batt, info);
1133		power_supply_put_battery_info(axp20x_batt->batt, info);
1134	}
1135
1136	/*
1137	 * Update max CCC to a valid value if battery info is present or set it
1138	 * to current register value by default.
1139	 */
1140	axp20x_get_constant_charge_current(axp20x_batt, &axp20x_batt->max_ccc);
1141
1142	return 0;
1143}
1144
1145static struct platform_driver axp20x_batt_driver = {
1146	.probe    = axp20x_power_probe,
1147	.driver   = {
1148		.name  = "axp20x-battery-power-supply",
1149		.of_match_table = axp20x_battery_ps_id,
1150	},
1151};
1152
1153module_platform_driver(axp20x_batt_driver);
1154
1155MODULE_DESCRIPTION("Battery power supply driver for AXP20X and AXP22X PMICs");
1156MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
1157MODULE_LICENSE("GPL");
~/ Read-only file preview.