File Index
Files and directories
Sign in
FILE

axp20x_usb_power.c

File preview with syntax highlighting.

linux-6.19.14/drivers/power/supply/axp20x_usb_power.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * AXP20x PMIC USB power supply status driver
   4 *
   5 * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
   6 * Copyright (C) 2014 Bruno Prémont <bonbons@linux-vserver.org>
   7 */
   8
   9#include <linux/bitops.h>
  10#include <linux/device.h>
  11#include <linux/devm-helpers.h>
  12#include <linux/init.h>
  13#include <linux/interrupt.h>
  14#include <linux/kernel.h>
  15#include <linux/mfd/axp20x.h>
  16#include <linux/module.h>
  17#include <linux/of.h>
  18#include <linux/platform_device.h>
  19#include <linux/pm.h>
  20#include <linux/power_supply.h>
  21#include <linux/regmap.h>
  22#include <linux/slab.h>
  23#include <linux/iio/consumer.h>
  24#include <linux/workqueue.h>
  25
  26#define DRVNAME "axp20x-usb-power-supply"
  27
  28#define AXP192_USB_OTG_STATUS		0x04
  29
  30#define AXP20X_PWR_STATUS_VBUS_PRESENT	BIT(5)
  31#define AXP20X_PWR_STATUS_VBUS_USED	BIT(4)
  32
  33#define AXP717_PWR_STATUS_VBUS_GOOD	BIT(5)
  34
  35#define AXP20X_USB_STATUS_VBUS_VALID	BIT(2)
  36
  37#define AXP717_PMU_FAULT_VBUS		BIT(5)
  38#define AXP717_PMU_FAULT_VSYS		BIT(3)
  39
  40#define AXP20X_VBUS_VHOLD_uV(b)		(4000000 + (((b) >> 3) & 7) * 100000)
  41#define AXP20X_VBUS_VHOLD_MASK		GENMASK(5, 3)
  42#define AXP20X_VBUS_VHOLD_OFFSET	3
  43
  44#define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)
  45#define AXP20X_ADC_EN1_VBUS_VOLT	BIT(3)
  46
  47#define AXP717_INPUT_VOL_LIMIT_MASK	GENMASK(3, 0)
  48#define AXP717_INPUT_CUR_LIMIT_MASK	GENMASK(5, 0)
  49#define AXP717_ADC_DATA_MASK		GENMASK(14, 0)
  50
  51#define AXP717_ADC_EN_VBUS_VOLT		BIT(2)
  52
  53/*
  54 * Note do not raise the debounce time, we must report Vusb high within
  55 * 100ms otherwise we get Vbus errors in musb.
  56 */
  57#define DEBOUNCE_TIME			msecs_to_jiffies(50)
  58
  59struct axp20x_usb_power;
  60
  61struct axp_data {
  62	const struct power_supply_desc	*power_desc;
  63	const char * const		*irq_names;
  64	unsigned int			num_irq_names;
  65	const int			*curr_lim_table;
  66	int				curr_lim_table_size;
  67	struct reg_field		curr_lim_fld;
  68	struct reg_field		vbus_valid_bit;
  69	struct reg_field		vbus_mon_bit;
  70	struct reg_field		usb_bc_en_bit;
  71	struct reg_field		usb_bc_det_fld;
  72	struct reg_field		vbus_disable_bit;
  73	bool				vbus_needs_polling: 1;
  74	void (*axp20x_read_vbus)(struct work_struct *work);
  75	int (*axp20x_cfg_iio_chan)(struct platform_device *pdev,
  76				   struct axp20x_usb_power *power);
  77	int (*axp20x_cfg_adc_reg)(struct axp20x_usb_power *power);
  78};
  79
  80struct axp20x_usb_power {
  81	struct device *dev;
  82	struct regmap *regmap;
  83	struct regmap_field *curr_lim_fld;
  84	struct regmap_field *vbus_valid_bit;
  85	struct regmap_field *vbus_mon_bit;
  86	struct regmap_field *usb_bc_en_bit;
  87	struct regmap_field *usb_bc_det_fld;
  88	struct regmap_field *vbus_disable_bit;
  89	struct power_supply *supply;
  90	const struct axp_data *axp_data;
  91	struct iio_channel *vbus_v;
  92	struct iio_channel *vbus_i;
  93	struct delayed_work vbus_detect;
  94	int max_input_cur;
  95	unsigned int old_status;
  96	unsigned int online;
  97	unsigned int num_irqs;
  98	unsigned int irqs[] __counted_by(num_irqs);
  99};
 100
 101static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
 102{
 103	/*
 104	 * Polling is only necessary while VBUS is offline. While online, a
 105	 * present->absent transition implies an online->offline transition
 106	 * and will trigger the VBUS_REMOVAL IRQ.
 107	 */
 108	if (power->axp_data->vbus_needs_polling && !power->online)
 109		return true;
 110
 111	return false;
 112}
 113
 114static irqreturn_t axp20x_usb_power_irq(int irq, void *devid)
 115{
 116	struct axp20x_usb_power *power = devid;
 117
 118	power_supply_changed(power->supply);
 119
 120	mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
 121
 122	return IRQ_HANDLED;
 123}
 124
 125static void axp20x_usb_power_poll_vbus(struct work_struct *work)
 126{
 127	struct axp20x_usb_power *power =
 128		container_of(work, struct axp20x_usb_power, vbus_detect.work);
 129	unsigned int val;
 130	int ret;
 131
 132	ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &val);
 133	if (ret)
 134		goto out;
 135
 136	val &= (AXP20X_PWR_STATUS_VBUS_PRESENT | AXP20X_PWR_STATUS_VBUS_USED);
 137	if (val != power->old_status)
 138		power_supply_changed(power->supply);
 139
 140	if (power->usb_bc_en_bit && (val & AXP20X_PWR_STATUS_VBUS_PRESENT) !=
 141		(power->old_status & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
 142		dev_dbg(power->dev, "Cable status changed, re-enabling USB BC");
 143		ret = regmap_field_write(power->usb_bc_en_bit, 1);
 144		if (ret)
 145			dev_err(power->dev, "failed to enable USB BC: errno %d",
 146				ret);
 147	}
 148
 149	power->old_status = val;
 150	power->online = val & AXP20X_PWR_STATUS_VBUS_USED;
 151
 152out:
 153	if (axp20x_usb_vbus_needs_polling(power))
 154		mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
 155}
 156
 157static void axp717_usb_power_poll_vbus(struct work_struct *work)
 158{
 159	struct axp20x_usb_power *power =
 160		container_of(work, struct axp20x_usb_power, vbus_detect.work);
 161	unsigned int val;
 162	int ret;
 163
 164	ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &val);
 165	if (ret)
 166		return;
 167
 168	val &= AXP717_PWR_STATUS_VBUS_GOOD;
 169	if (val != power->old_status)
 170		power_supply_changed(power->supply);
 171
 172	power->old_status = val;
 173}
 174
 175static int axp20x_get_usb_type(struct axp20x_usb_power *power,
 176			       union power_supply_propval *val)
 177{
 178	unsigned int reg;
 179	int ret;
 180
 181	if (!power->usb_bc_det_fld)
 182		return -EINVAL;
 183
 184	ret = regmap_field_read(power->usb_bc_det_fld, &reg);
 185	if (ret)
 186		return ret;
 187
 188	switch (reg) {
 189	case 1:
 190		val->intval = POWER_SUPPLY_USB_TYPE_SDP;
 191		break;
 192	case 2:
 193		val->intval = POWER_SUPPLY_USB_TYPE_CDP;
 194		break;
 195	case 3:
 196		val->intval = POWER_SUPPLY_USB_TYPE_DCP;
 197		break;
 198	default:
 199		val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
 200		break;
 201	}
 202
 203	return 0;
 204}
 205
 206static int axp20x_usb_power_get_property(struct power_supply *psy,
 207	enum power_supply_property psp, union power_supply_propval *val)
 208{
 209	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
 210	unsigned int input, v;
 211	int ret;
 212
 213	switch (psp) {
 214	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 215		ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
 216		if (ret)
 217			return ret;
 218
 219		val->intval = AXP20X_VBUS_VHOLD_uV(v);
 220		return 0;
 221	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 222		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
 223			/*
 224			 * IIO framework gives mV but Power Supply framework
 225			 * gives uV.
 226			 */
 227			ret = iio_read_channel_processed_scale(power->vbus_v,
 228							       &val->intval, 1000);
 229			if (ret)
 230				return ret;
 231
 232			return 0;
 233		}
 234
 235		ret = axp20x_read_variable_width(power->regmap,
 236						 AXP20X_VBUS_V_ADC_H, 12);
 237		if (ret < 0)
 238			return ret;
 239
 240		val->intval = ret * 1700; /* 1 step = 1.7 mV */
 241		return 0;
 242	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 243		ret = regmap_field_read(power->curr_lim_fld, &v);
 244		if (ret)
 245			return ret;
 246
 247		if (v < power->axp_data->curr_lim_table_size)
 248			val->intval = power->axp_data->curr_lim_table[v];
 249		else
 250			val->intval = power->axp_data->curr_lim_table[
 251				power->axp_data->curr_lim_table_size - 1];
 252		return 0;
 253	case POWER_SUPPLY_PROP_CURRENT_NOW:
 254		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
 255			/*
 256			 * IIO framework gives mA but Power Supply framework
 257			 * gives uA.
 258			 */
 259			ret = iio_read_channel_processed_scale(power->vbus_i,
 260							       &val->intval, 1000);
 261			if (ret)
 262				return ret;
 263
 264			return 0;
 265		}
 266
 267		ret = axp20x_read_variable_width(power->regmap,
 268						 AXP20X_VBUS_I_ADC_H, 12);
 269		if (ret < 0)
 270			return ret;
 271
 272		val->intval = ret * 375; /* 1 step = 0.375 mA */
 273		return 0;
 274
 275	case POWER_SUPPLY_PROP_USB_TYPE:
 276		return axp20x_get_usb_type(power, val);
 277	default:
 278		break;
 279	}
 280
 281	/* All the properties below need the input-status reg value */
 282	ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);
 283	if (ret)
 284		return ret;
 285
 286	switch (psp) {
 287	case POWER_SUPPLY_PROP_HEALTH:
 288		if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
 289			val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
 290			break;
 291		}
 292
 293		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 294
 295		if (power->vbus_valid_bit) {
 296			ret = regmap_field_read(power->vbus_valid_bit, &v);
 297			if (ret)
 298				return ret;
 299
 300			if (v == 0)
 301				val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
 302		}
 303
 304		break;
 305	case POWER_SUPPLY_PROP_PRESENT:
 306		val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
 307		break;
 308	case POWER_SUPPLY_PROP_ONLINE:
 309		val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED);
 310		break;
 311	default:
 312		return -EINVAL;
 313	}
 314
 315	return 0;
 316}
 317
 318static int axp717_usb_power_get_property(struct power_supply *psy,
 319	enum power_supply_property psp, union power_supply_propval *val)
 320{
 321	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
 322	unsigned int v;
 323	int ret;
 324
 325	switch (psp) {
 326	case POWER_SUPPLY_PROP_HEALTH:
 327		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 328		ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);
 329		if (ret)
 330			return ret;
 331
 332		if (!(v & AXP717_PWR_STATUS_VBUS_GOOD))
 333			val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
 334
 335		ret = regmap_read(power->regmap, AXP717_PMU_FAULT_VBUS, &v);
 336		if (ret)
 337			return ret;
 338
 339		v &= (AXP717_PMU_FAULT_VBUS | AXP717_PMU_FAULT_VSYS);
 340		if (v) {
 341			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
 342			regmap_write(power->regmap, AXP717_PMU_FAULT_VBUS, v);
 343		}
 344
 345		break;
 346	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 347		ret = regmap_read(power->regmap, AXP717_INPUT_CUR_LIMIT_CTRL, &v);
 348		if (ret)
 349			return ret;
 350
 351		/* 50ma step size with 100ma offset. */
 352		v &= AXP717_INPUT_CUR_LIMIT_MASK;
 353		val->intval = (v * 50000) + 100000;
 354		break;
 355	case POWER_SUPPLY_PROP_ONLINE:
 356	case POWER_SUPPLY_PROP_PRESENT:
 357		ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);
 358		if (ret)
 359			return ret;
 360		val->intval = !!(v & AXP717_PWR_STATUS_VBUS_GOOD);
 361		break;
 362	case POWER_SUPPLY_PROP_USB_TYPE:
 363		return axp20x_get_usb_type(power, val);
 364	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 365		ret = regmap_read(power->regmap, AXP717_INPUT_VOL_LIMIT_CTRL, &v);
 366		if (ret)
 367			return ret;
 368
 369		/* 80mv step size with 3.88v offset. */
 370		v &= AXP717_INPUT_VOL_LIMIT_MASK;
 371		val->intval = (v * 80000) + 3880000;
 372		break;
 373	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 374		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
 375			/*
 376			 * IIO framework gives mV but Power Supply framework
 377			 * gives uV.
 378			 */
 379			ret = iio_read_channel_processed_scale(power->vbus_v,
 380							       &val->intval, 1000);
 381			if (ret)
 382				return ret;
 383
 384			return 0;
 385		}
 386
 387		ret = axp20x_read_variable_width(power->regmap,
 388						 AXP717_VBUS_V_H, 16);
 389		if (ret < 0)
 390			return ret;
 391
 392		val->intval = (ret % AXP717_ADC_DATA_MASK) * 1000;
 393		break;
 394	default:
 395		return -EINVAL;
 396	}
 397
 398	return 0;
 399
 400}
 401
 402static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
 403					    int intval)
 404{
 405	int val;
 406
 407	switch (intval) {
 408	case 4000000:
 409	case 4100000:
 410	case 4200000:
 411	case 4300000:
 412	case 4400000:
 413	case 4500000:
 414	case 4600000:
 415	case 4700000:
 416		val = (intval - 4000000) / 100000;
 417		return regmap_update_bits(power->regmap,
 418					  AXP20X_VBUS_IPSOUT_MGMT,
 419					  AXP20X_VBUS_VHOLD_MASK,
 420					  val << AXP20X_VBUS_VHOLD_OFFSET);
 421	default:
 422		return -EINVAL;
 423	}
 424
 425	return -EINVAL;
 426}
 427
 428static int axp717_usb_power_set_voltage_min(struct axp20x_usb_power *power,
 429					    int intval)
 430{
 431	int val;
 432
 433	/* Minimum value of 3.88v and maximum of 5.08v. */
 434	if (intval < 3880000 || intval > 5080000)
 435		return -EINVAL;
 436
 437	/* step size of 80ma with 3.88v offset. */
 438	val = (intval - 3880000) / 80000;
 439	return regmap_update_bits(power->regmap,
 440				  AXP717_INPUT_VOL_LIMIT_CTRL,
 441				  AXP717_INPUT_VOL_LIMIT_MASK, val);
 442}
 443
 444static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
 445						    int intval)
 446{
 447	int ret;
 448	unsigned int reg;
 449	const unsigned int max = power->axp_data->curr_lim_table_size;
 450
 451	if (intval == -1)
 452		return -EINVAL;
 453
 454	if (power->max_input_cur && (intval > power->max_input_cur)) {
 455		dev_warn(power->dev,
 456			 "requested current %d clamped to max current %d\n",
 457			 intval, power->max_input_cur);
 458		intval = power->max_input_cur;
 459	}
 460
 461	/*
 462	 * BC1.2 detection can cause a race condition if we try to set a current
 463	 * limit while it's in progress. When it finishes it will overwrite the
 464	 * current limit we just set.
 465	 */
 466	if (power->usb_bc_en_bit) {
 467		dev_dbg(power->dev,
 468			"disabling BC1.2 detection because current limit was set");
 469		ret = regmap_field_write(power->usb_bc_en_bit, 0);
 470		if (ret)
 471			return ret;
 472	}
 473
 474	for (reg = max - 1; reg > 0; reg--)
 475		if (power->axp_data->curr_lim_table[reg] <= intval)
 476			break;
 477
 478	dev_dbg(power->dev, "setting input current limit reg to %d (%d uA), requested %d uA",
 479		reg, power->axp_data->curr_lim_table[reg], intval);
 480
 481	return regmap_field_write(power->curr_lim_fld, reg);
 482}
 483
 484static int axp717_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
 485						    int intval)
 486{
 487	int tmp;
 488
 489	/* Minimum value of 100mA and maximum value of 3.25A*/
 490	if (intval < 100000 || intval > 3250000)
 491		return -EINVAL;
 492
 493	if (power->max_input_cur && (intval > power->max_input_cur)) {
 494		dev_warn(power->dev,
 495			 "requested current %d clamped to max current %d\n",
 496			 intval, power->max_input_cur);
 497		intval = power->max_input_cur;
 498	}
 499
 500	/* Minimum value of 100mA with step size of 50mA. */
 501	tmp = (intval - 100000) / 50000;
 502	return regmap_update_bits(power->regmap,
 503				  AXP717_INPUT_CUR_LIMIT_CTRL,
 504				  AXP717_INPUT_CUR_LIMIT_MASK, tmp);
 505}
 506
 507static int axp20x_usb_power_set_property(struct power_supply *psy,
 508					 enum power_supply_property psp,
 509					 const union power_supply_propval *val)
 510{
 511	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
 512
 513	switch (psp) {
 514	case POWER_SUPPLY_PROP_ONLINE:
 515		if (!power->vbus_disable_bit)
 516			return -EINVAL;
 517
 518		return regmap_field_write(power->vbus_disable_bit, !val->intval);
 519
 520	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 521		return axp20x_usb_power_set_voltage_min(power, val->intval);
 522
 523	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 524		return axp20x_usb_power_set_input_current_limit(power, val->intval);
 525
 526	default:
 527		return -EINVAL;
 528	}
 529}
 530
 531static int axp717_usb_power_set_property(struct power_supply *psy,
 532					 enum power_supply_property psp,
 533					 const union power_supply_propval *val)
 534{
 535	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
 536
 537	switch (psp) {
 538	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 539		return axp717_usb_power_set_input_current_limit(power, val->intval);
 540
 541	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 542		return axp717_usb_power_set_voltage_min(power, val->intval);
 543
 544	default:
 545		return -EINVAL;
 546	}
 547
 548	return -EINVAL;
 549}
 550
 551static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
 552					   enum power_supply_property psp)
 553{
 554	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
 555
 556	/*
 557	 * The VBUS path select flag works differently on AXP288 and newer:
 558	 *  - On AXP20x and AXP22x, the flag enables VBUS (ignoring N_VBUSEN).
 559	 *  - On AXP288 and AXP8xx, the flag disables VBUS (ignoring N_VBUSEN).
 560	 * We only expose the control on variants where it can be used to force
 561	 * the VBUS input offline.
 562	 */
 563	if (psp == POWER_SUPPLY_PROP_ONLINE)
 564		return power->vbus_disable_bit != NULL;
 565
 566	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
 567	       psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
 568}
 569
 570static int axp717_usb_power_prop_writeable(struct power_supply *psy,
 571					   enum power_supply_property psp)
 572{
 573	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
 574	       psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
 575}
 576
 577static int axp20x_configure_iio_channels(struct platform_device *pdev,
 578					 struct axp20x_usb_power *power)
 579{
 580	power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
 581	if (IS_ERR(power->vbus_v)) {
 582		if (PTR_ERR(power->vbus_v) == -ENODEV)
 583			return -EPROBE_DEFER;
 584		return PTR_ERR(power->vbus_v);
 585	}
 586
 587	power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i");
 588	if (IS_ERR(power->vbus_i)) {
 589		if (PTR_ERR(power->vbus_i) == -ENODEV)
 590			return -EPROBE_DEFER;
 591		return PTR_ERR(power->vbus_i);
 592	}
 593
 594	return 0;
 595}
 596
 597static int axp717_configure_iio_channels(struct platform_device *pdev,
 598					 struct axp20x_usb_power *power)
 599{
 600	power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v");
 601	if (IS_ERR(power->vbus_v)) {
 602		if (PTR_ERR(power->vbus_v) == -ENODEV)
 603			return -EPROBE_DEFER;
 604		return PTR_ERR(power->vbus_v);
 605	}
 606
 607	return 0;
 608}
 609
 610static int axp20x_configure_adc_registers(struct axp20x_usb_power *power)
 611{
 612	/* Enable vbus voltage and current measurement */
 613	return regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
 614				  AXP20X_ADC_EN1_VBUS_CURR |
 615				  AXP20X_ADC_EN1_VBUS_VOLT,
 616				  AXP20X_ADC_EN1_VBUS_CURR |
 617				  AXP20X_ADC_EN1_VBUS_VOLT);
 618}
 619
 620static int axp717_configure_adc_registers(struct axp20x_usb_power *power)
 621{
 622	/* Enable vbus voltage measurement  */
 623	return regmap_update_bits(power->regmap, AXP717_ADC_CH_EN_CONTROL,
 624				  AXP717_ADC_EN_VBUS_VOLT,
 625				  AXP717_ADC_EN_VBUS_VOLT);
 626}
 627
 628static enum power_supply_property axp20x_usb_power_properties[] = {
 629	POWER_SUPPLY_PROP_HEALTH,
 630	POWER_SUPPLY_PROP_PRESENT,
 631	POWER_SUPPLY_PROP_ONLINE,
 632	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 633	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 634	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 635	POWER_SUPPLY_PROP_CURRENT_NOW,
 636};
 637
 638static enum power_supply_property axp22x_usb_power_properties[] = {
 639	POWER_SUPPLY_PROP_HEALTH,
 640	POWER_SUPPLY_PROP_PRESENT,
 641	POWER_SUPPLY_PROP_ONLINE,
 642	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 643	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 644};
 645
 646static enum power_supply_property axp717_usb_power_properties[] = {
 647	POWER_SUPPLY_PROP_HEALTH,
 648	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 649	POWER_SUPPLY_PROP_ONLINE,
 650	POWER_SUPPLY_PROP_PRESENT,
 651	POWER_SUPPLY_PROP_USB_TYPE,
 652	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 653	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 654};
 655
 656static enum power_supply_property axp813_usb_power_properties[] = {
 657	POWER_SUPPLY_PROP_HEALTH,
 658	POWER_SUPPLY_PROP_PRESENT,
 659	POWER_SUPPLY_PROP_ONLINE,
 660	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 661	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 662	POWER_SUPPLY_PROP_USB_TYPE,
 663};
 664
 665static const struct power_supply_desc axp20x_usb_power_desc = {
 666	.name = "axp20x-usb",
 667	.type = POWER_SUPPLY_TYPE_USB,
 668	.properties = axp20x_usb_power_properties,
 669	.num_properties = ARRAY_SIZE(axp20x_usb_power_properties),
 670	.property_is_writeable = axp20x_usb_power_prop_writeable,
 671	.get_property = axp20x_usb_power_get_property,
 672	.set_property = axp20x_usb_power_set_property,
 673};
 674
 675static const struct power_supply_desc axp22x_usb_power_desc = {
 676	.name = "axp20x-usb",
 677	.type = POWER_SUPPLY_TYPE_USB,
 678	.properties = axp22x_usb_power_properties,
 679	.num_properties = ARRAY_SIZE(axp22x_usb_power_properties),
 680	.property_is_writeable = axp20x_usb_power_prop_writeable,
 681	.get_property = axp20x_usb_power_get_property,
 682	.set_property = axp20x_usb_power_set_property,
 683};
 684
 685static const struct power_supply_desc axp717_usb_power_desc = {
 686	.name = "axp20x-usb",
 687	.type = POWER_SUPPLY_TYPE_USB,
 688	.properties = axp717_usb_power_properties,
 689	.num_properties = ARRAY_SIZE(axp717_usb_power_properties),
 690	.property_is_writeable = axp717_usb_power_prop_writeable,
 691	.get_property = axp717_usb_power_get_property,
 692	.set_property = axp717_usb_power_set_property,
 693	.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
 694		     BIT(POWER_SUPPLY_USB_TYPE_CDP) |
 695		     BIT(POWER_SUPPLY_USB_TYPE_DCP) |
 696		     BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
 697};
 698
 699static const struct power_supply_desc axp813_usb_power_desc = {
 700	.name = "axp20x-usb",
 701	.type = POWER_SUPPLY_TYPE_USB,
 702	.properties = axp813_usb_power_properties,
 703	.num_properties = ARRAY_SIZE(axp813_usb_power_properties),
 704	.property_is_writeable = axp20x_usb_power_prop_writeable,
 705	.get_property = axp20x_usb_power_get_property,
 706	.set_property = axp20x_usb_power_set_property,
 707	.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
 708		     BIT(POWER_SUPPLY_USB_TYPE_CDP) |
 709		     BIT(POWER_SUPPLY_USB_TYPE_DCP) |
 710		     BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
 711};
 712
 713static const char * const axp20x_irq_names[] = {
 714	"VBUS_PLUGIN",
 715	"VBUS_REMOVAL",
 716	"VBUS_VALID",
 717	"VBUS_NOT_VALID",
 718};
 719
 720static const char * const axp22x_irq_names[] = {
 721	"VBUS_PLUGIN",
 722	"VBUS_REMOVAL",
 723};
 724
 725static const char * const axp717_irq_names[] = {
 726	"VBUS_PLUGIN",
 727	"VBUS_REMOVAL",
 728	"VBUS_OVER_V",
 729};
 730
 731static int axp192_usb_curr_lim_table[] = {
 732	-1,
 733	-1,
 734	500000,
 735	100000,
 736};
 737
 738static int axp20x_usb_curr_lim_table[] = {
 739	900000,
 740	500000,
 741	100000,
 742	-1,
 743};
 744
 745static int axp221_usb_curr_lim_table[] = {
 746	900000,
 747	500000,
 748	-1,
 749	-1,
 750};
 751
 752static int axp813_usb_curr_lim_table[] = {
 753	100000,
 754	500000,
 755	900000,
 756	1500000,
 757	2000000,
 758	2500000,
 759	3000000,
 760	3500000,
 761	4000000,
 762};
 763
 764static const struct axp_data axp192_data = {
 765	.power_desc	= &axp20x_usb_power_desc,
 766	.irq_names	= axp20x_irq_names,
 767	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),
 768	.curr_lim_table = axp192_usb_curr_lim_table,
 769	.curr_lim_table_size = ARRAY_SIZE(axp192_usb_curr_lim_table),
 770	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 771	.vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
 772	.vbus_mon_bit   = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
 773	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 774	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
 775	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
 776};
 777
 778static const struct axp_data axp202_data = {
 779	.power_desc	= &axp20x_usb_power_desc,
 780	.irq_names	= axp20x_irq_names,
 781	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),
 782	.curr_lim_table = axp20x_usb_curr_lim_table,
 783	.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
 784	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 785	.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
 786	.vbus_mon_bit   = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
 787	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 788	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
 789	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
 790};
 791
 792static const struct axp_data axp221_data = {
 793	.power_desc	= &axp22x_usb_power_desc,
 794	.irq_names	= axp22x_irq_names,
 795	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
 796	.curr_lim_table = axp221_usb_curr_lim_table,
 797	.curr_lim_table_size = ARRAY_SIZE(axp221_usb_curr_lim_table),
 798	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 799	.vbus_needs_polling = true,
 800	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 801	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
 802	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
 803};
 804
 805static const struct axp_data axp223_data = {
 806	.power_desc	= &axp22x_usb_power_desc,
 807	.irq_names	= axp22x_irq_names,
 808	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
 809	.curr_lim_table = axp20x_usb_curr_lim_table,
 810	.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
 811	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 812	.vbus_needs_polling = true,
 813	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 814	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
 815	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
 816};
 817
 818static const struct axp_data axp717_data = {
 819	.power_desc     = &axp717_usb_power_desc,
 820	.irq_names      = axp717_irq_names,
 821	.num_irq_names  = ARRAY_SIZE(axp717_irq_names),
 822	.curr_lim_fld   = REG_FIELD(AXP717_INPUT_CUR_LIMIT_CTRL, 0, 5),
 823	.usb_bc_en_bit  = REG_FIELD(AXP717_MODULE_EN_CONTROL_1, 4, 4),
 824	.usb_bc_det_fld = REG_FIELD(AXP717_BC_DETECT, 5, 7),
 825	.vbus_mon_bit   = REG_FIELD(AXP717_ADC_CH_EN_CONTROL, 2, 2),
 826	.vbus_needs_polling = false,
 827	.axp20x_read_vbus = &axp717_usb_power_poll_vbus,
 828	.axp20x_cfg_iio_chan = axp717_configure_iio_channels,
 829	.axp20x_cfg_adc_reg = axp717_configure_adc_registers,
 830};
 831
 832static const struct axp_data axp813_data = {
 833	.power_desc	= &axp813_usb_power_desc,
 834	.irq_names	= axp22x_irq_names,
 835	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
 836	.curr_lim_table = axp813_usb_curr_lim_table,
 837	.curr_lim_table_size = ARRAY_SIZE(axp813_usb_curr_lim_table),
 838	.curr_lim_fld	= REG_FIELD(AXP22X_CHRG_CTRL3, 4, 7),
 839	.usb_bc_en_bit	= REG_FIELD(AXP288_BC_GLOBAL, 0, 0),
 840	.usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7),
 841	.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
 842	.vbus_needs_polling = true,
 843	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 844	.axp20x_cfg_iio_chan = axp20x_configure_iio_channels,
 845	.axp20x_cfg_adc_reg = axp20x_configure_adc_registers,
 846};
 847
 848#ifdef CONFIG_PM_SLEEP
 849static int axp20x_usb_power_suspend(struct device *dev)
 850{
 851	struct axp20x_usb_power *power = dev_get_drvdata(dev);
 852	int i = 0;
 853
 854	/*
 855	 * Allow wake via VBUS_PLUGIN only.
 856	 *
 857	 * As nested threaded IRQs are not automatically disabled during
 858	 * suspend, we must explicitly disable the remainder of the IRQs.
 859	 */
 860	if (device_may_wakeup(&power->supply->dev))
 861		enable_irq_wake(power->irqs[i++]);
 862	while (i < power->num_irqs)
 863		disable_irq(power->irqs[i++]);
 864
 865	return 0;
 866}
 867
 868static int axp20x_usb_power_resume(struct device *dev)
 869{
 870	struct axp20x_usb_power *power = dev_get_drvdata(dev);
 871	int i = 0;
 872
 873	if (device_may_wakeup(&power->supply->dev))
 874		disable_irq_wake(power->irqs[i++]);
 875	while (i < power->num_irqs)
 876		enable_irq(power->irqs[i++]);
 877
 878	mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
 879
 880	return 0;
 881}
 882#endif
 883
 884static SIMPLE_DEV_PM_OPS(axp20x_usb_power_pm_ops, axp20x_usb_power_suspend,
 885						  axp20x_usb_power_resume);
 886
 887static int axp20x_regmap_field_alloc_optional(struct device *dev,
 888					      struct regmap *regmap,
 889					      struct reg_field fdesc,
 890					      struct regmap_field **fieldp)
 891{
 892	struct regmap_field *field;
 893
 894	if (fdesc.reg == 0) {
 895		*fieldp = NULL;
 896		return 0;
 897	}
 898
 899	field = devm_regmap_field_alloc(dev, regmap, fdesc);
 900	if (IS_ERR(field))
 901		return PTR_ERR(field);
 902
 903	*fieldp = field;
 904	return 0;
 905}
 906
 907/* Optionally allow users to specify a maximum charging current. */
 908static void axp20x_usb_power_parse_dt(struct device *dev,
 909				      struct axp20x_usb_power *power)
 910{
 911	int ret;
 912
 913	ret = device_property_read_u32(dev, "input-current-limit-microamp",
 914				       &power->max_input_cur);
 915	if (ret)
 916		dev_dbg(dev, "%s() no input-current-limit specified\n", __func__);
 917}
 918
 919static int axp20x_usb_power_probe(struct platform_device *pdev)
 920{
 921	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
 922	struct power_supply_config psy_cfg = {};
 923	struct axp20x_usb_power *power;
 924	const struct axp_data *axp_data;
 925	int i, irq, ret;
 926
 927	if (!of_device_is_available(pdev->dev.of_node))
 928		return -ENODEV;
 929
 930	if (!axp20x) {
 931		dev_err(&pdev->dev, "Parent drvdata not set\n");
 932		return -EINVAL;
 933	}
 934
 935	axp_data = of_device_get_match_data(&pdev->dev);
 936
 937	power = devm_kzalloc(&pdev->dev,
 938			     struct_size(power, irqs, axp_data->num_irq_names),
 939			     GFP_KERNEL);
 940	if (!power)
 941		return -ENOMEM;
 942
 943	platform_set_drvdata(pdev, power);
 944
 945	power->dev = &pdev->dev;
 946	power->axp_data = axp_data;
 947	power->regmap = axp20x->regmap;
 948	power->num_irqs = axp_data->num_irq_names;
 949
 950	power->curr_lim_fld = devm_regmap_field_alloc(&pdev->dev, power->regmap,
 951						      axp_data->curr_lim_fld);
 952	if (IS_ERR(power->curr_lim_fld))
 953		return PTR_ERR(power->curr_lim_fld);
 954
 955	axp20x_usb_power_parse_dt(&pdev->dev, power);
 956
 957	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
 958						 axp_data->vbus_valid_bit,
 959						 &power->vbus_valid_bit);
 960	if (ret)
 961		return ret;
 962
 963	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
 964						 axp_data->vbus_mon_bit,
 965						 &power->vbus_mon_bit);
 966	if (ret)
 967		return ret;
 968
 969	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
 970						 axp_data->usb_bc_en_bit,
 971						 &power->usb_bc_en_bit);
 972	if (ret)
 973		return ret;
 974
 975	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
 976						 axp_data->usb_bc_det_fld,
 977						 &power->usb_bc_det_fld);
 978	if (ret)
 979		return ret;
 980
 981	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
 982						 axp_data->vbus_disable_bit,
 983						 &power->vbus_disable_bit);
 984	if (ret)
 985		return ret;
 986
 987	ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
 988					   axp_data->axp20x_read_vbus);
 989	if (ret)
 990		return ret;
 991
 992	if (power->vbus_mon_bit) {
 993		/* Enable vbus valid checking */
 994		ret = regmap_field_write(power->vbus_mon_bit, 1);
 995		if (ret)
 996			return ret;
 997
 998		if (IS_ENABLED(CONFIG_AXP20X_ADC))
 999			ret = axp_data->axp20x_cfg_iio_chan(pdev, power);
1000		else
1001			ret = axp_data->axp20x_cfg_adc_reg(power);
1002
1003		if (ret)
1004			return ret;
1005	}
1006
1007	if (power->usb_bc_en_bit) {
1008		/* Enable USB Battery Charging specification detection */
1009		ret = regmap_field_write(power->usb_bc_en_bit, 1);
1010		if (ret)
1011			return ret;
1012	}
1013
1014	psy_cfg.fwnode = dev_fwnode(&pdev->dev);
1015	psy_cfg.drv_data = power;
1016
1017	power->supply = devm_power_supply_register(&pdev->dev,
1018						   axp_data->power_desc,
1019						   &psy_cfg);
1020	if (IS_ERR(power->supply))
1021		return PTR_ERR(power->supply);
1022
1023	/* Request irqs after registering, as irqs may trigger immediately */
1024	for (i = 0; i < axp_data->num_irq_names; i++) {
1025		irq = platform_get_irq_byname(pdev, axp_data->irq_names[i]);
1026		if (irq < 0)
1027			return irq;
1028
1029		power->irqs[i] = regmap_irq_get_virq(axp20x->regmap_irqc, irq);
1030		ret = devm_request_any_context_irq(&pdev->dev, power->irqs[i],
1031						   axp20x_usb_power_irq, 0,
1032						   DRVNAME, power);
1033		if (ret < 0) {
1034			dev_err(&pdev->dev, "Error requesting %s IRQ: %d\n",
1035				axp_data->irq_names[i], ret);
1036			return ret;
1037		}
1038	}
1039
1040	if (axp20x_usb_vbus_needs_polling(power))
1041		queue_delayed_work(system_power_efficient_wq, &power->vbus_detect, 0);
1042
1043	return 0;
1044}
1045
1046static const struct of_device_id axp20x_usb_power_match[] = {
1047	{
1048		.compatible = "x-powers,axp192-usb-power-supply",
1049		.data = &axp192_data,
1050	}, {
1051		.compatible = "x-powers,axp202-usb-power-supply",
1052		.data = &axp202_data,
1053	}, {
1054		.compatible = "x-powers,axp221-usb-power-supply",
1055		.data = &axp221_data,
1056	}, {
1057		.compatible = "x-powers,axp223-usb-power-supply",
1058		.data = &axp223_data,
1059	}, {
1060		.compatible = "x-powers,axp717-usb-power-supply",
1061		.data = &axp717_data,
1062	}, {
1063		.compatible = "x-powers,axp813-usb-power-supply",
1064		.data = &axp813_data,
1065	}, { /* sentinel */ }
1066};
1067MODULE_DEVICE_TABLE(of, axp20x_usb_power_match);
1068
1069static struct platform_driver axp20x_usb_power_driver = {
1070	.probe = axp20x_usb_power_probe,
1071	.driver = {
1072		.name		= DRVNAME,
1073		.of_match_table	= axp20x_usb_power_match,
1074		.pm		= &axp20x_usb_power_pm_ops,
1075	},
1076};
1077
1078module_platform_driver(axp20x_usb_power_driver);
1079
1080MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
1081MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver");
1082MODULE_LICENSE("GPL");
~/ Read-only file preview.