diff mbox series

[3/4] power: supply: axp20x_usb_power: Add support for AXP717

Message ID 20240522230132.364915-4-macroalpha82@gmail.com
State New
Headers show
Series AXP717: Add USB Power Supply | expand

Commit Message

Chris Morgan May 22, 2024, 11:01 p.m. UTC
From: Chris Morgan <macromorgan@hotmail.com>

Add support for the AXP717. It does USB BC 1.2 detection similar to the
AXP813, however it is otherwise very different from previous AXP
devices.

Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
 drivers/mfd/axp20x.c                    |  19 ++-
 drivers/power/supply/axp20x_usb_power.c | 216 +++++++++++++++++++++++-
 include/linux/mfd/axp20x.h              |  18 ++
 3 files changed, 248 insertions(+), 5 deletions(-)

Comments

Oliver Neukum May 27, 2024, 9:10 a.m. UTC | #1
On 23.05.24 01:01, Chris Morgan wrote:
> From: Chris Morgan <macromorgan@hotmail.com>
> 
> Add support for the AXP717. It does USB BC 1.2 detection similar to the
> AXP813, however it is otherwise very different from previous AXP
> devices.
> 
> Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> ---

> +static int axp717_usb_init(struct axp20x_usb_power *power)
> +{
> +	int ret;
> +
> +	ret = regmap_update_bits(power->regmap, AXP717_ADC_CH_EN_CONTROL,
> +				 AXP717_ADC_EN_VSYS_VOLT |
> +				 AXP717_ADC_EN_VBUS_VOLT,
> +				 AXP717_ADC_EN_VSYS_VOLT |
> +				 AXP717_ADC_EN_VBUS_VOLT);
> +	if (ret)
> +		return ret;
> +
> +	return 0;

This is a bit silly.

> +}
> +
>   static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
>   					    int intval)
>   {
> @@ -307,6 +417,20 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
>   	return -EINVAL;
>   }
>   
> +static int axp717_usb_power_set_voltage_min(struct axp20x_usb_power *power,
> +					    int intval)
> +{
> +	int val;
> +
> +	if (intval < 3880000 || intval > 5080000)

Do you really want raw numbers here?

[..]
> +static int axp717_usb_power_set_property(struct power_supply *psy,
> +					 enum power_supply_property psp,
> +					 const union power_supply_propval *val)
> +{
> +	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
> +
> +	switch (psp) {
> +	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
> +		return axp717_usb_power_set_input_current_limit(power, val->intval);
> +
> +	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
> +		return axp717_usb_power_set_voltage_min(power, val->intval);
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return -EINVAL;

This is also a bit silly.

	Regards
		Oliver
Chris Morgan May 29, 2024, 3:22 p.m. UTC | #2
On Mon, May 27, 2024 at 11:10:32AM +0200, Oliver Neukum wrote:
> 
> 
> On 23.05.24 01:01, Chris Morgan wrote:
> > From: Chris Morgan <macromorgan@hotmail.com>
> > 
> > Add support for the AXP717. It does USB BC 1.2 detection similar to the
> > AXP813, however it is otherwise very different from previous AXP
> > devices.
> > 
> > Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> > ---
> 
> > +static int axp717_usb_init(struct axp20x_usb_power *power)
> > +{
> > +	int ret;
> > +
> > +	ret = regmap_update_bits(power->regmap, AXP717_ADC_CH_EN_CONTROL,
> > +				 AXP717_ADC_EN_VSYS_VOLT |
> > +				 AXP717_ADC_EN_VBUS_VOLT,
> > +				 AXP717_ADC_EN_VSYS_VOLT |
> > +				 AXP717_ADC_EN_VBUS_VOLT);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return 0;
> 
> This is a bit silly.

Agreed, I'll fix.

> 
> > +}
> > +
> >   static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
> >   					    int intval)
> >   {
> > @@ -307,6 +417,20 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
> >   	return -EINVAL;
> >   }
> > +static int axp717_usb_power_set_voltage_min(struct axp20x_usb_power *power,
> > +					    int intval)
> > +{
> > +	int val;
> > +
> > +	if (intval < 3880000 || intval > 5080000)
> 
> Do you really want raw numbers here?
> 

Raw numbers are used throughout the driver, but it probably makes
sense to document *why* these numbers are here and what they mean, so
I'll do that.

> [..]
> > +static int axp717_usb_power_set_property(struct power_supply *psy,
> > +					 enum power_supply_property psp,
> > +					 const union power_supply_propval *val)
> > +{
> > +	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
> > +
> > +	switch (psp) {
> > +	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
> > +		return axp717_usb_power_set_input_current_limit(power, val->intval);
> > +
> > +	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
> > +		return axp717_usb_power_set_voltage_min(power, val->intval);
> > +
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +
> > +	return -EINVAL;
> 
> This is also a bit silly.

That's how it's done above, but I might as well just remove the default
statement so it returns -EINVAL if neither of the other two conditions
aren't true.

> 
> 	Regards
> 		Oliver
> 

I'll resubmit with the changes mentioned above.

Thank you,
Chris
Chris Morgan June 6, 2024, 5:09 p.m. UTC | #3
On Wed, May 29, 2024 at 10:22:33AM -0500, Chris Morgan wrote:
> On Mon, May 27, 2024 at 11:10:32AM +0200, Oliver Neukum wrote:
> > 
> > 
> > On 23.05.24 01:01, Chris Morgan wrote:
> > > From: Chris Morgan <macromorgan@hotmail.com>
> > > 
> > > Add support for the AXP717. It does USB BC 1.2 detection similar to the
> > > AXP813, however it is otherwise very different from previous AXP
> > > devices.
> > > 
> > > Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> > > ---
> > 
> > > +static int axp717_usb_init(struct axp20x_usb_power *power)
> > > +{
> > > +	int ret;
> > > +
> > > +	ret = regmap_update_bits(power->regmap, AXP717_ADC_CH_EN_CONTROL,
> > > +				 AXP717_ADC_EN_VSYS_VOLT |
> > > +				 AXP717_ADC_EN_VBUS_VOLT,
> > > +				 AXP717_ADC_EN_VSYS_VOLT |
> > > +				 AXP717_ADC_EN_VBUS_VOLT);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	return 0;
> > 
> > This is a bit silly.
> 
> Agreed, I'll fix.
> 
> > 
> > > +}
> > > +
> > >   static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
> > >   					    int intval)
> > >   {
> > > @@ -307,6 +417,20 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
> > >   	return -EINVAL;
> > >   }
> > > +static int axp717_usb_power_set_voltage_min(struct axp20x_usb_power *power,
> > > +					    int intval)
> > > +{
> > > +	int val;
> > > +
> > > +	if (intval < 3880000 || intval > 5080000)
> > 
> > Do you really want raw numbers here?
> > 
> 
> Raw numbers are used throughout the driver, but it probably makes
> sense to document *why* these numbers are here and what they mean, so
> I'll do that.
> 
> > [..]
> > > +static int axp717_usb_power_set_property(struct power_supply *psy,
> > > +					 enum power_supply_property psp,
> > > +					 const union power_supply_propval *val)
> > > +{
> > > +	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
> > > +
> > > +	switch (psp) {
> > > +	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
> > > +		return axp717_usb_power_set_input_current_limit(power, val->intval);
> > > +
> > > +	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
> > > +		return axp717_usb_power_set_voltage_min(power, val->intval);
> > > +
> > > +	default:
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	return -EINVAL;
> > 
> > This is also a bit silly.
> 
> That's how it's done above, but I might as well just remove the default
> statement so it returns -EINVAL if neither of the other two conditions
> aren't true.
> 
> > 
> > 	Regards
> > 		Oliver
> > 
> 
> I'll resubmit with the changes mentioned above.

I'm going to go back to the drawing board with this, so for now I'm
withdrawing this patch series. Basically moving on to the next logical
step of working with the battery it became obvious I should have done
this using an ADC controller just like the existing axp usb and battery
drivers. So I'll start with that and then resubmit a redone version of
this once I have the ADC code in place.

Thank you,
Chris.

> 
> Thank you,
> Chris
diff mbox series

Patch

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 16950c3206d7..d52d0c1c3367 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -209,15 +209,20 @@  static const struct regmap_access_table axp313a_volatile_table = {
 };
 
 static const struct regmap_range axp717_writeable_ranges[] = {
-	regmap_reg_range(AXP717_MODULE_EN_CONTROL_2, AXP717_MODULE_EN_CONTROL_2),
-	regmap_reg_range(AXP717_BOOST_CONTROL, AXP717_BOOST_CONTROL),
+	regmap_reg_range(AXP717_PMU_FAULT, AXP717_MODULE_EN_CONTROL_1),
+	regmap_reg_range(AXP717_MIN_SYS_V_CONTROL, AXP717_BOOST_CONTROL),
 	regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN),
 	regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
 	regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL),
+	regmap_reg_range(AXP717_ADC_CH_EN_CONTROL, AXP717_ADC_CH_EN_CONTROL),
+	regmap_reg_range(AXP717_ADC_DATA_SEL, AXP717_ADC_DATA_SEL),
 };
 
 static const struct regmap_range axp717_volatile_ranges[] = {
+	regmap_reg_range(AXP717_ON_INDICATE, AXP717_BC_DETECT),
 	regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
+	regmap_reg_range(AXP717_ADC_VBAT_H, AXP717_ADC_ICHG_L),
+	regmap_reg_range(AXP717_ADC_DATA_H, AXP717_ADC_DATA_L),
 };
 
 static const struct regmap_access_table axp717_writeable_table = {
@@ -310,6 +315,11 @@  static const struct resource axp22x_usb_power_supply_resources[] = {
 	DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
 };
 
+static const struct resource axp717_usb_power_supply_resources[] = {
+	DEFINE_RES_IRQ_NAMED(AXP717_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
+	DEFINE_RES_IRQ_NAMED(AXP717_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
+};
+
 /* AXP803 and AXP813/AXP818 share the same interrupts */
 static const struct resource axp803_usb_power_supply_resources[] = {
 	DEFINE_RES_IRQ_NAMED(AXP803_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
@@ -424,7 +434,7 @@  static const struct regmap_config axp717_regmap_config = {
 	.val_bits = 8,
 	.wr_table = &axp717_writeable_table,
 	.volatile_table = &axp717_volatile_table,
-	.max_register = AXP717_CPUSLDO_CONTROL,
+	.max_register = AXP717_ADC_DATA_L,
 	.cache_type = REGCACHE_MAPLE,
 };
 
@@ -1026,6 +1036,9 @@  static struct mfd_cell axp313a_cells[] = {
 static struct mfd_cell axp717_cells[] = {
 	MFD_CELL_NAME("axp20x-regulator"),
 	MFD_CELL_RES("axp20x-pek", axp717_pek_resources),
+	MFD_CELL_OF("axp717-usb-power-supply",
+		    axp717_usb_power_supply_resources, NULL, 0, 0,
+		    "x-powers,axp717-usb-power-supply"),
 };
 
 static const struct resource axp288_adc_resources[] = {
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index dae7e5cfc54e..3d6815bd614b 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -6,6 +6,7 @@ 
  * Copyright (C) 2014 Bruno Prémont <bonbons@linux-vserver.org>
  */
 
+#include <asm/unaligned.h>
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/devm-helpers.h>
@@ -30,14 +31,25 @@ 
 #define AXP20X_PWR_STATUS_VBUS_PRESENT	BIT(5)
 #define AXP20X_PWR_STATUS_VBUS_USED	BIT(4)
 
+#define AXP717_PWR_STATUS_VBUS_GOOD	BIT(5)
+
 #define AXP20X_USB_STATUS_VBUS_VALID	BIT(2)
 
+#define AXP717_PMU_FAULT_VBUS		BIT(5)
+#define AXP717_PMU_FAULT_VSYS		BIT(3)
+
 #define AXP20X_VBUS_VHOLD_uV(b)		(4000000 + (((b) >> 3) & 7) * 100000)
 #define AXP20X_VBUS_VHOLD_MASK		GENMASK(5, 3)
 #define AXP20X_VBUS_VHOLD_OFFSET	3
 
-#define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)
+#define AXP717_INPUT_VOL_LIMIT_MASK	GENMASK(3, 0)
+#define AXP717_INPUT_CUR_LIMIT_MASK	GENMASK(5, 0)
+
 #define AXP20X_ADC_EN1_VBUS_VOLT	BIT(3)
+#define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)
+
+#define AXP717_ADC_EN_VSYS_VOLT		BIT(3)
+#define AXP717_ADC_EN_VBUS_VOLT		BIT(2)
 
 /*
  * Note do not raise the debounce time, we must report Vusb high within
@@ -45,6 +57,8 @@ 
  */
 #define DEBOUNCE_TIME			msecs_to_jiffies(50)
 
+struct axp20x_usb_power;
+
 struct axp_data {
 	const struct power_supply_desc	*power_desc;
 	const char * const		*irq_names;
@@ -58,6 +72,8 @@  struct axp_data {
 	struct reg_field		usb_bc_det_fld;
 	struct reg_field		vbus_disable_bit;
 	bool				vbus_needs_polling: 1;
+	int (*axp20x_usb_init)(struct axp20x_usb_power *power);
+	void (*axp20x_read_vbus)(struct work_struct *work);
 };
 
 struct axp20x_usb_power {
@@ -136,6 +152,24 @@  static void axp20x_usb_power_poll_vbus(struct work_struct *work)
 		mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
 }
 
+static void axp717_usb_power_poll_vbus(struct work_struct *work)
+{
+	struct axp20x_usb_power *power =
+		container_of(work, struct axp20x_usb_power, vbus_detect.work);
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &val);
+	if (ret)
+		return;
+
+	val &= AXP717_PWR_STATUS_VBUS_GOOD;
+	if (val != power->old_status)
+		power_supply_changed(power->supply);
+
+	power->old_status = val;
+}
+
 static int axp20x_get_usb_type(struct axp20x_usb_power *power,
 			       union power_supply_propval *val)
 {
@@ -281,6 +315,82 @@  static int axp20x_usb_power_get_property(struct power_supply *psy,
 	return 0;
 }
 
+static int axp717_usb_power_get_property(struct power_supply *psy,
+	enum power_supply_property psp, union power_supply_propval *val)
+{
+	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
+	unsigned int v;
+	u8 bulk_reg[2];
+	int ret;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_HEALTH:
+		val->intval = POWER_SUPPLY_HEALTH_GOOD;
+		ret = regmap_read(power->regmap, AXP717_PMU_FAULT_VBUS, &v);
+		if (ret)
+			return ret;
+
+		v &= (AXP717_PMU_FAULT_VBUS | AXP717_PMU_FAULT_VSYS);
+		if (v) {
+			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+			regmap_write(power->regmap, AXP717_PMU_FAULT_VBUS, v);
+		}
+
+		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+		ret = regmap_read(power->regmap, AXP717_INPUT_CUR_LIMIT_CTRL, &v);
+		if (ret)
+			return ret;
+
+		v &= AXP717_INPUT_CUR_LIMIT_MASK;
+		val->intval = (v * 50000) + 100000;
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+	case POWER_SUPPLY_PROP_PRESENT:
+		ret = regmap_read(power->regmap, AXP717_ON_INDICATE, &v);
+		if (ret)
+			return ret;
+		val->intval = !!(v & AXP717_PWR_STATUS_VBUS_GOOD);
+		break;
+	case POWER_SUPPLY_PROP_USB_TYPE:
+		return axp20x_get_usb_type(power, val);
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+		ret = regmap_read(power->regmap, AXP717_INPUT_VOL_LIMIT_CTRL, &v);
+		if (ret)
+			return ret;
+
+		v &= AXP717_INPUT_VOL_LIMIT_MASK;
+		val->intval = (v * 80000) + 3880000;
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = regmap_bulk_read(power->regmap, AXP717_ADC_VBUS_H, bulk_reg, 2);
+		if (ret)
+			return ret;
+		val->intval = get_unaligned_be16(bulk_reg) * 1000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+
+}
+
+static int axp717_usb_init(struct axp20x_usb_power *power)
+{
+	int ret;
+
+	ret = regmap_update_bits(power->regmap, AXP717_ADC_CH_EN_CONTROL,
+				 AXP717_ADC_EN_VSYS_VOLT |
+				 AXP717_ADC_EN_VBUS_VOLT,
+				 AXP717_ADC_EN_VSYS_VOLT |
+				 AXP717_ADC_EN_VBUS_VOLT);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
 					    int intval)
 {
@@ -307,6 +417,20 @@  static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
 	return -EINVAL;
 }
 
+static int axp717_usb_power_set_voltage_min(struct axp20x_usb_power *power,
+					    int intval)
+{
+	int val;
+
+	if (intval < 3880000 || intval > 5080000)
+		return -EINVAL;
+
+	val = (intval - 3880000) / 80000;
+	return regmap_update_bits(power->regmap,
+				  AXP717_INPUT_VOL_LIMIT_CTRL,
+				  AXP717_INPUT_VOL_LIMIT_MASK, val);
+}
+
 static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
 						    int intval)
 {
@@ -340,6 +464,20 @@  static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *pow
 	return regmap_field_write(power->curr_lim_fld, reg);
 }
 
+static int axp717_usb_power_set_input_current_limit(struct axp20x_usb_power *power,
+						    int intval)
+{
+	int val;
+
+	if (intval < 100000 || intval > 3250000)
+		return -EINVAL;
+
+	val = (intval - 100000) / 50000;
+	return regmap_update_bits(power->regmap,
+				  AXP717_INPUT_CUR_LIMIT_CTRL,
+				  AXP717_INPUT_CUR_LIMIT_MASK, val);
+}
+
 static int axp20x_usb_power_set_property(struct power_supply *psy,
 					 enum power_supply_property psp,
 					 const union power_supply_propval *val)
@@ -366,6 +504,26 @@  static int axp20x_usb_power_set_property(struct power_supply *psy,
 	return -EINVAL;
 }
 
+static int axp717_usb_power_set_property(struct power_supply *psy,
+					 enum power_supply_property psp,
+					 const union power_supply_propval *val)
+{
+	struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+		return axp717_usb_power_set_input_current_limit(power, val->intval);
+
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+		return axp717_usb_power_set_voltage_min(power, val->intval);
+
+	default:
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
 static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
 					   enum power_supply_property psp)
 {
@@ -385,6 +543,13 @@  static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
 	       psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
 }
 
+static int axp717_usb_power_prop_writeable(struct power_supply *psy,
+					   enum power_supply_property psp)
+{
+	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
+	       psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT;
+}
+
 static enum power_supply_property axp20x_usb_power_properties[] = {
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_PRESENT,
@@ -403,6 +568,16 @@  static enum power_supply_property axp22x_usb_power_properties[] = {
 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 };
 
+static enum power_supply_property axp717_usb_power_properties[] = {
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_USB_TYPE,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
 static enum power_supply_property axp813_usb_power_properties[] = {
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_PRESENT,
@@ -439,6 +614,18 @@  static const struct power_supply_desc axp22x_usb_power_desc = {
 	.set_property = axp20x_usb_power_set_property,
 };
 
+static const struct power_supply_desc axp717_usb_power_desc = {
+	.name = "axp20x-usb",
+	.type = POWER_SUPPLY_TYPE_USB,
+	.properties = axp717_usb_power_properties,
+	.num_properties = ARRAY_SIZE(axp717_usb_power_properties),
+	.property_is_writeable = axp717_usb_power_prop_writeable,
+	.get_property = axp717_usb_power_get_property,
+	.set_property = axp717_usb_power_set_property,
+	.usb_types = axp813_usb_types,
+	.num_usb_types = ARRAY_SIZE(axp813_usb_types),
+};
+
 static const struct power_supply_desc axp813_usb_power_desc = {
 	.name = "axp20x-usb",
 	.type = POWER_SUPPLY_TYPE_USB,
@@ -505,6 +692,7 @@  static const struct axp_data axp192_data = {
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 	.vbus_valid_bit = REG_FIELD(AXP192_USB_OTG_STATUS, 2, 2),
 	.vbus_mon_bit   = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
+	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 };
 
 static const struct axp_data axp202_data = {
@@ -516,6 +704,7 @@  static const struct axp_data axp202_data = {
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 	.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
 	.vbus_mon_bit   = REG_FIELD(AXP20X_VBUS_MON, 3, 3),
+	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 };
 
 static const struct axp_data axp221_data = {
@@ -526,6 +715,7 @@  static const struct axp_data axp221_data = {
 	.curr_lim_table_size = ARRAY_SIZE(axp221_usb_curr_lim_table),
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 	.vbus_needs_polling = true,
+	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 };
 
 static const struct axp_data axp223_data = {
@@ -536,6 +726,18 @@  static const struct axp_data axp223_data = {
 	.curr_lim_table_size = ARRAY_SIZE(axp20x_usb_curr_lim_table),
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 	.vbus_needs_polling = true,
+	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
+};
+
+static const struct axp_data axp717_data = {
+	.power_desc	= &axp717_usb_power_desc,
+	.irq_names	= axp22x_irq_names,
+	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
+	.curr_lim_fld	= REG_FIELD(AXP717_INPUT_CUR_LIMIT_CTRL, 0, 5),
+	.usb_bc_en_bit	= REG_FIELD(AXP717_MODULE_EN_CONTROL_1, 4, 4),
+	.usb_bc_det_fld = REG_FIELD(AXP717_BC_DETECT, 5, 7),
+	.axp20x_usb_init = &axp717_usb_init,
+	.axp20x_read_vbus = &axp717_usb_power_poll_vbus,
 };
 
 static const struct axp_data axp813_data = {
@@ -549,6 +751,7 @@  static const struct axp_data axp813_data = {
 	.usb_bc_det_fld = REG_FIELD(AXP288_BC_DET_STAT, 5, 7),
 	.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
 	.vbus_needs_polling = true,
+	.axp20x_read_vbus = &axp20x_usb_power_poll_vbus,
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -707,7 +910,7 @@  static int axp20x_usb_power_probe(struct platform_device *pdev)
 		return ret;
 
 	ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
-					   axp20x_usb_power_poll_vbus);
+					   axp_data->axp20x_read_vbus);
 	if (ret)
 		return ret;
 
@@ -733,6 +936,12 @@  static int axp20x_usb_power_probe(struct platform_device *pdev)
 			return ret;
 	}
 
+	if (power->axp_data->axp20x_usb_init) {
+		ret = axp_data->axp20x_usb_init(power);
+		if (ret)
+			return ret;
+	}
+
 	psy_cfg.of_node = pdev->dev.of_node;
 	psy_cfg.drv_data = power;
 
@@ -778,6 +987,9 @@  static const struct of_device_id axp20x_usb_power_match[] = {
 	}, {
 		.compatible = "x-powers,axp223-usb-power-supply",
 		.data = &axp223_data,
+	}, {
+		.compatible = "x-powers,axp717-usb-power-supply",
+		.data = &axp717_data,
 	}, {
 		.compatible = "x-powers,axp813-usb-power-supply",
 		.data = &axp813_data,
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index e0cd66bd3b6d..107808df33e9 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -115,6 +115,12 @@  enum axp20x_variants {
 #define AXP313A_IRQ_STATE		0x21
 
 #define AXP717_ON_INDICATE		0x00
+#define AXP717_BC_DETECT		0x05
+#define AXP717_PMU_FAULT		0x08
+#define AXP717_MODULE_EN_CONTROL_1	0x0b
+#define AXP717_MIN_SYS_V_CONTROL	0x15
+#define AXP717_INPUT_VOL_LIMIT_CTRL	0x16
+#define AXP717_INPUT_CUR_LIMIT_CTRL	0x17
 #define AXP717_MODULE_EN_CONTROL_2	0x19
 #define AXP717_BOOST_CONTROL		0x1e
 #define AXP717_IRQ0_EN			0x40
@@ -147,6 +153,18 @@  enum axp20x_variants {
 #define AXP717_CLDO3_CONTROL		0x9d
 #define AXP717_CLDO4_CONTROL		0x9e
 #define AXP717_CPUSLDO_CONTROL		0x9f
+#define AXP717_ADC_CH_EN_CONTROL	0xc0
+#define AXP717_ADC_VBAT_H		0xc4
+#define AXP717_ADC_VBAT_L		0xc5
+#define AXP717_ADC_VBUS_H		0xc6
+#define AXP717_ADC_VBUS_L		0xc7
+#define AXP717_ADC_VSYS_H		0xc8
+#define AXP717_ADC_VSYS_L		0xc9
+#define AXP717_ADC_ICHG_H		0xca
+#define AXP717_ADC_ICHG_L		0xcb
+#define AXP717_ADC_DATA_SEL		0xcd
+#define AXP717_ADC_DATA_H		0xce
+#define AXP717_ADC_DATA_L		0xcf
 
 #define AXP806_STARTUP_SRC		0x00
 #define AXP806_CHIP_ID			0x03