LKML Archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192
@ 2023-05-10 11:50 Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 1/7] power: supply: axp20x_usb_power: Simplify USB current limit handling Aidan MacDonald
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Aidan MacDonald @ 2023-05-10 11:50 UTC (permalink / raw
  To: sre, robh+dt, krzysztof.kozlowski+dt, conor+dt, wens
  Cc: linux-pm, devicetree, linux-kernel

This adds support for the AXP192's USB power supply. Most of this
series (patches 1-5) consists of refactoring the driver to avoid
explicit checks based on the variant ID. Doing that makes it very
easy to add support for the AXP192 in patches 6-7, and as a nice
side benefit, should make the driver more maintainable.

Patches 1-5 are unchanged from their previous submission[1].

[1] https://lore.kernel.org/all/20230218204946.106316-1-aidanmacdonald.0x0@gmail.com/

Aidan MacDonald (7):
  power: supply: axp20x_usb_power: Simplify USB current limit handling
  power: supply: axp20x_usb_power: Use regmap fields for VBUS monitor
    feature
  power: supply: axp20x_usb_power: Use regmap fields for USB BC feature
  power: supply: axp20x_usb_power: Use regmap field for VBUS disabling
  power: supply: axp20x_usb_power: Remove variant IDs from VBUS polling
    check
  power: supply: axp20x_usb_power: Add support for AXP192
  dt-bindings: power: supply: axp20x: Add AXP192 compatible

 .../x-powers,axp20x-usb-power-supply.yaml     |   1 +
 drivers/power/supply/axp20x_usb_power.c       | 307 +++++++++---------
 2 files changed, 153 insertions(+), 155 deletions(-)

-- 
2.39.2


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v1 1/7] power: supply: axp20x_usb_power: Simplify USB current limit handling
  2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
@ 2023-05-10 11:50 ` Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 2/7] power: supply: axp20x_usb_power: Use regmap fields for VBUS monitor feature Aidan MacDonald
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aidan MacDonald @ 2023-05-10 11:50 UTC (permalink / raw
  To: sre, robh+dt, krzysztof.kozlowski+dt, conor+dt, wens
  Cc: linux-pm, devicetree, linux-kernel

Handle the USB current limit with a lookup table and regmap field,
which minimizes code duplication. Invalid or unlimited values are
denoted by -1 entries, and can't be selected from userspace.

Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
---
 drivers/power/supply/axp20x_usb_power.c | 172 ++++++++----------------
 1 file changed, 57 insertions(+), 115 deletions(-)

diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index a1e6d1d44808..67998fba702a 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -37,16 +37,6 @@
 #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_VBUS_CLIMIT_MASK		3
-#define AXP20X_VBUS_CLIMIT_900mA	0
-#define AXP20X_VBUS_CLIMIT_500mA	1
-#define AXP20X_VBUS_CLIMIT_100mA	2
-#define AXP20X_VBUS_CLIMIT_NONE		3
-
-#define AXP813_VBUS_CLIMIT_900mA	0
-#define AXP813_VBUS_CLIMIT_1500mA	1
-#define AXP813_VBUS_CLIMIT_2000mA	2
-#define AXP813_VBUS_CLIMIT_2500mA	3
 
 #define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)
 #define AXP20X_ADC_EN1_VBUS_VOLT	BIT(3)
@@ -61,10 +51,21 @@
  */
 #define DEBOUNCE_TIME			msecs_to_jiffies(50)
 
+struct axp_data {
+	const struct power_supply_desc	*power_desc;
+	const char * const		*irq_names;
+	unsigned int			num_irq_names;
+	enum axp20x_variants		axp20x_id;
+	const int			*curr_lim_table;
+	struct reg_field		curr_lim_fld;
+};
+
 struct axp20x_usb_power {
 	struct regmap *regmap;
+	struct regmap_field *curr_lim_fld;
 	struct power_supply *supply;
 	enum axp20x_variants axp20x_id;
+	const struct axp_data *axp_data;
 	struct iio_channel *vbus_v;
 	struct iio_channel *vbus_i;
 	struct delayed_work vbus_detect;
@@ -121,60 +122,6 @@ static void axp20x_usb_power_poll_vbus(struct work_struct *work)
 		mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME);
 }
 
-static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val)
-{
-	unsigned int v;
-	int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
-
-	if (ret)
-		return ret;
-
-	switch (v & AXP20X_VBUS_CLIMIT_MASK) {
-	case AXP20X_VBUS_CLIMIT_100mA:
-		if (power->axp20x_id == AXP221_ID)
-			*val = -1; /* No 100mA limit */
-		else
-			*val = 100000;
-		break;
-	case AXP20X_VBUS_CLIMIT_500mA:
-		*val = 500000;
-		break;
-	case AXP20X_VBUS_CLIMIT_900mA:
-		*val = 900000;
-		break;
-	case AXP20X_VBUS_CLIMIT_NONE:
-		*val = -1;
-		break;
-	}
-
-	return 0;
-}
-
-static int axp813_get_current_max(struct axp20x_usb_power *power, int *val)
-{
-	unsigned int v;
-	int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
-
-	if (ret)
-		return ret;
-
-	switch (v & AXP20X_VBUS_CLIMIT_MASK) {
-	case AXP813_VBUS_CLIMIT_900mA:
-		*val = 900000;
-		break;
-	case AXP813_VBUS_CLIMIT_1500mA:
-		*val = 1500000;
-		break;
-	case AXP813_VBUS_CLIMIT_2000mA:
-		*val = 2000000;
-		break;
-	case AXP813_VBUS_CLIMIT_2500mA:
-		*val = 2500000;
-		break;
-	}
-	return 0;
-}
-
 static int axp20x_usb_power_get_property(struct power_supply *psy,
 	enum power_supply_property psp, union power_supply_propval *val)
 {
@@ -213,9 +160,12 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
 		val->intval = ret * 1700; /* 1 step = 1.7 mV */
 		return 0;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		if (power->axp20x_id == AXP813_ID)
-			return axp813_get_current_max(power, &val->intval);
-		return axp20x_get_current_max(power, &val->intval);
+		ret = regmap_field_read(power->curr_lim_fld, &v);
+		if (ret)
+			return ret;
+
+		val->intval = power->axp_data->curr_lim_table[v];
+		return 0;
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 		if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
 			ret = iio_read_channel_processed(power->vbus_i,
@@ -316,50 +266,17 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
 	return -EINVAL;
 }
 
-static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power,
-					    int intval)
+static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, int intval)
 {
-	int val;
+	const unsigned int max = GENMASK(power->axp_data->curr_lim_fld.msb,
+					 power->axp_data->curr_lim_fld.lsb);
 
-	switch (intval) {
-	case 900000:
-		return regmap_update_bits(power->regmap,
-					  AXP20X_VBUS_IPSOUT_MGMT,
-					  AXP20X_VBUS_CLIMIT_MASK,
-					  AXP813_VBUS_CLIMIT_900mA);
-	case 1500000:
-	case 2000000:
-	case 2500000:
-		val = (intval - 1000000) / 500000;
-		return regmap_update_bits(power->regmap,
-					  AXP20X_VBUS_IPSOUT_MGMT,
-					  AXP20X_VBUS_CLIMIT_MASK, val);
-	default:
+	if (intval == -1)
 		return -EINVAL;
-	}
 
-	return -EINVAL;
-}
-
-static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power,
-					    int intval)
-{
-	int val;
-
-	switch (intval) {
-	case 100000:
-		if (power->axp20x_id == AXP221_ID)
-			return -EINVAL;
-		fallthrough;
-	case 500000:
-	case 900000:
-		val = (900000 - intval) / 400000;
-		return regmap_update_bits(power->regmap,
-					  AXP20X_VBUS_IPSOUT_MGMT,
-					  AXP20X_VBUS_CLIMIT_MASK, val);
-	default:
-		return -EINVAL;
-	}
+	for (unsigned int i = 0; i <= max; ++i)
+		if (power->axp_data->curr_lim_table[i] == intval)
+			return regmap_field_write(power->curr_lim_fld, i);
 
 	return -EINVAL;
 }
@@ -380,9 +297,6 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
 		return axp20x_usb_power_set_voltage_min(power, val->intval);
 
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		if (power->axp20x_id == AXP813_ID)
-			return axp813_usb_power_set_current_max(power,
-								val->intval);
 		return axp20x_usb_power_set_current_max(power, val->intval);
 
 	default:
@@ -461,11 +375,25 @@ static const char * const axp22x_irq_names[] = {
 	"VBUS_REMOVAL",
 };
 
-struct axp_data {
-	const struct power_supply_desc	*power_desc;
-	const char * const		*irq_names;
-	unsigned int			num_irq_names;
-	enum axp20x_variants		axp20x_id;
+static int axp20x_usb_curr_lim_table[] = {
+	900000,
+	500000,
+	100000,
+	-1,
+};
+
+static int axp221_usb_curr_lim_table[] = {
+	900000,
+	500000,
+	-1,
+	-1,
+};
+
+static int axp813_usb_curr_lim_table[] = {
+	900000,
+	1500000,
+	2000000,
+	2500000,
 };
 
 static const struct axp_data axp202_data = {
@@ -473,6 +401,8 @@ static const struct axp_data axp202_data = {
 	.irq_names	= axp20x_irq_names,
 	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),
 	.axp20x_id	= AXP202_ID,
+	.curr_lim_table = axp20x_usb_curr_lim_table,
+	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 };
 
 static const struct axp_data axp221_data = {
@@ -480,6 +410,8 @@ static const struct axp_data axp221_data = {
 	.irq_names	= axp22x_irq_names,
 	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
 	.axp20x_id	= AXP221_ID,
+	.curr_lim_table = axp221_usb_curr_lim_table,
+	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 };
 
 static const struct axp_data axp223_data = {
@@ -487,6 +419,8 @@ static const struct axp_data axp223_data = {
 	.irq_names	= axp22x_irq_names,
 	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
 	.axp20x_id	= AXP223_ID,
+	.curr_lim_table = axp20x_usb_curr_lim_table,
+	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 };
 
 static const struct axp_data axp813_data = {
@@ -494,6 +428,8 @@ static const struct axp_data axp813_data = {
 	.irq_names	= axp22x_irq_names,
 	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
 	.axp20x_id	= AXP813_ID,
+	.curr_lim_table = axp813_usb_curr_lim_table,
+	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -592,9 +528,15 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, power);
 
 	power->axp20x_id = axp_data->axp20x_id;
+	power->axp_data = axp_data;
 	power->regmap = axp20x->regmap;
 	power->num_irqs = axp_data->num_irq_names;
 
+	power->curr_lim_fld = devm_regmap_field_alloc(&pdev->dev, power->regmap,
+						      axp_data->curr_lim_fld);
+	if (IS_ERR(power->curr_lim_fld))
+		return PTR_ERR(power->curr_lim_fld);
+
 	ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
 					   axp20x_usb_power_poll_vbus);
 	if (ret)
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 2/7] power: supply: axp20x_usb_power: Use regmap fields for VBUS monitor feature
  2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 1/7] power: supply: axp20x_usb_power: Simplify USB current limit handling Aidan MacDonald
@ 2023-05-10 11:50 ` Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 3/7] power: supply: axp20x_usb_power: Use regmap fields for USB BC feature Aidan MacDonald
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aidan MacDonald @ 2023-05-10 11:50 UTC (permalink / raw
  To: sre, robh+dt, krzysztof.kozlowski+dt, conor+dt, wens
  Cc: linux-pm, devicetree, linux-kernel

Use regmap fields to describe the VBUS valid bit and VBUS monitor
enable bit. This allows the driver to easily support other chips,
eg. the AXP192, that have the VBUS valid bit in a different register.

Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
---
 drivers/power/supply/axp20x_usb_power.c | 57 +++++++++++++++++++------
 1 file changed, 45 insertions(+), 12 deletions(-)

diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 67998fba702a..b2049b7d95fe 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -41,8 +41,6 @@
 #define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)
 #define AXP20X_ADC_EN1_VBUS_VOLT	BIT(3)
 
-#define AXP20X_VBUS_MON_VBUS_VALID	BIT(3)
-
 #define AXP813_BC_EN		BIT(0)
 
 /*
@@ -58,11 +56,15 @@ struct axp_data {
 	enum axp20x_variants		axp20x_id;
 	const int			*curr_lim_table;
 	struct reg_field		curr_lim_fld;
+	struct reg_field		vbus_valid_bit;
+	struct reg_field		vbus_mon_bit;
 };
 
 struct axp20x_usb_power {
 	struct regmap *regmap;
 	struct regmap_field *curr_lim_fld;
+	struct regmap_field *vbus_valid_bit;
+	struct regmap_field *vbus_mon_bit;
 	struct power_supply *supply;
 	enum axp20x_variants axp20x_id;
 	const struct axp_data *axp_data;
@@ -206,16 +208,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
 
 		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 
-		if (power->axp20x_id == AXP202_ID) {
-			ret = regmap_read(power->regmap,
-					  AXP20X_USB_OTG_STATUS, &v);
+		if (power->vbus_valid_bit) {
+			ret = regmap_field_read(power->vbus_valid_bit, &v);
 			if (ret)
 				return ret;
 
-			if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
-				val->intval =
-					POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+			if (v == 0)
+				val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
 		}
+
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
@@ -403,6 +404,8 @@ static const struct axp_data axp202_data = {
 	.axp20x_id	= AXP202_ID,
 	.curr_lim_table = axp20x_usb_curr_lim_table,
 	.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),
 };
 
 static const struct axp_data axp221_data = {
@@ -501,6 +504,26 @@ static int configure_adc_registers(struct axp20x_usb_power *power)
 				  AXP20X_ADC_EN1_VBUS_VOLT);
 }
 
+static int axp20x_regmap_field_alloc_optional(struct device *dev,
+					      struct regmap *regmap,
+					      struct reg_field fdesc,
+					      struct regmap_field **fieldp)
+{
+	struct regmap_field *field;
+
+	if (fdesc.reg == 0) {
+		*fieldp = NULL;
+		return 0;
+	}
+
+	field = devm_regmap_field_alloc(dev, regmap, fdesc);
+	if (IS_ERR(field))
+		return PTR_ERR(field);
+
+	*fieldp = field;
+	return 0;
+}
+
 static int axp20x_usb_power_probe(struct platform_device *pdev)
 {
 	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -537,16 +560,26 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 	if (IS_ERR(power->curr_lim_fld))
 		return PTR_ERR(power->curr_lim_fld);
 
+	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+						 axp_data->vbus_valid_bit,
+						 &power->vbus_valid_bit);
+	if (ret)
+		return ret;
+
+	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+						 axp_data->vbus_mon_bit,
+						 &power->vbus_mon_bit);
+	if (ret)
+		return ret;
+
 	ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
 					   axp20x_usb_power_poll_vbus);
 	if (ret)
 		return ret;
 
-	if (power->axp20x_id == AXP202_ID) {
+	if (power->vbus_mon_bit) {
 		/* Enable vbus valid checking */
-		ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
-					 AXP20X_VBUS_MON_VBUS_VALID,
-					 AXP20X_VBUS_MON_VBUS_VALID);
+		ret = regmap_field_write(power->vbus_mon_bit, 1);
 		if (ret)
 			return ret;
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 3/7] power: supply: axp20x_usb_power: Use regmap fields for USB BC feature
  2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 1/7] power: supply: axp20x_usb_power: Simplify USB current limit handling Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 2/7] power: supply: axp20x_usb_power: Use regmap fields for VBUS monitor feature Aidan MacDonald
@ 2023-05-10 11:50 ` Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 4/7] power: supply: axp20x_usb_power: Use regmap field for VBUS disabling Aidan MacDonald
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aidan MacDonald @ 2023-05-10 11:50 UTC (permalink / raw
  To: sre, robh+dt, krzysztof.kozlowski+dt, conor+dt, wens
  Cc: linux-pm, devicetree, linux-kernel

Replace the use of variant IDs with a regmap field, to reduce
dependence on variant IDs.

Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
---
 drivers/power/supply/axp20x_usb_power.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index b2049b7d95fe..20a76c19cfad 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -41,8 +41,6 @@
 #define AXP20X_ADC_EN1_VBUS_CURR	BIT(2)
 #define AXP20X_ADC_EN1_VBUS_VOLT	BIT(3)
 
-#define AXP813_BC_EN		BIT(0)
-
 /*
  * Note do not raise the debounce time, we must report Vusb high within
  * 100ms otherwise we get Vbus errors in musb.
@@ -58,6 +56,7 @@ struct axp_data {
 	struct reg_field		curr_lim_fld;
 	struct reg_field		vbus_valid_bit;
 	struct reg_field		vbus_mon_bit;
+	struct reg_field		usb_bc_en_bit;
 };
 
 struct axp20x_usb_power {
@@ -65,6 +64,7 @@ struct axp20x_usb_power {
 	struct regmap_field *curr_lim_fld;
 	struct regmap_field *vbus_valid_bit;
 	struct regmap_field *vbus_mon_bit;
+	struct regmap_field *usb_bc_en_bit;
 	struct power_supply *supply;
 	enum axp20x_variants axp20x_id;
 	const struct axp_data *axp_data;
@@ -433,6 +433,7 @@ static const struct axp_data axp813_data = {
 	.axp20x_id	= AXP813_ID,
 	.curr_lim_table = axp813_usb_curr_lim_table,
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+	.usb_bc_en_bit	= REG_FIELD(AXP288_BC_GLOBAL, 0, 0),
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -572,6 +573,12 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+						 axp_data->usb_bc_en_bit,
+						 &power->usb_bc_en_bit);
+	if (ret)
+		return ret;
+
 	ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
 					   axp20x_usb_power_poll_vbus);
 	if (ret)
@@ -592,10 +599,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 			return ret;
 	}
 
-	if (power->axp20x_id == AXP813_ID) {
+	if (power->usb_bc_en_bit) {
 		/* Enable USB Battery Charging specification detection */
-		ret = regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL,
-				   AXP813_BC_EN, AXP813_BC_EN);
+		ret = regmap_field_write(power->usb_bc_en_bit, 1);
 		if (ret)
 			return ret;
 	}
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 4/7] power: supply: axp20x_usb_power: Use regmap field for VBUS disabling
  2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
                   ` (2 preceding siblings ...)
  2023-05-10 11:50 ` [PATCH v1 3/7] power: supply: axp20x_usb_power: Use regmap fields for USB BC feature Aidan MacDonald
@ 2023-05-10 11:50 ` Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 5/7] power: supply: axp20x_usb_power: Remove variant IDs from VBUS polling check Aidan MacDonald
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aidan MacDonald @ 2023-05-10 11:50 UTC (permalink / raw
  To: sre, robh+dt, krzysztof.kozlowski+dt, conor+dt, wens
  Cc: linux-pm, devicetree, linux-kernel

The POWER_SUPPLY_PROP_ONLINE property allows controlling the VBUS
enable state on supported PMICs. Switch to regmap fields to reduce
dependence on variant IDs.

Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
---
 drivers/power/supply/axp20x_usb_power.c | 29 +++++++++++--------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 20a76c19cfad..89f076615d2e 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -31,9 +31,6 @@
 
 #define AXP20X_USB_STATUS_VBUS_VALID	BIT(2)
 
-#define AXP20X_VBUS_PATH_SEL		BIT(7)
-#define AXP20X_VBUS_PATH_SEL_OFFSET	7
-
 #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
@@ -57,6 +54,7 @@ struct axp_data {
 	struct reg_field		vbus_valid_bit;
 	struct reg_field		vbus_mon_bit;
 	struct reg_field		usb_bc_en_bit;
+	struct reg_field		vbus_disable_bit;
 };
 
 struct axp20x_usb_power {
@@ -65,6 +63,7 @@ struct axp20x_usb_power {
 	struct regmap_field *vbus_valid_bit;
 	struct regmap_field *vbus_mon_bit;
 	struct regmap_field *usb_bc_en_bit;
+	struct regmap_field *vbus_disable_bit;
 	struct power_supply *supply;
 	enum axp20x_variants axp20x_id;
 	const struct axp_data *axp_data;
@@ -231,16 +230,6 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
 	return 0;
 }
 
-static int axp813_usb_power_set_online(struct axp20x_usb_power *power,
-				       int intval)
-{
-	int val = !intval << AXP20X_VBUS_PATH_SEL_OFFSET;
-
-	return regmap_update_bits(power->regmap,
-				  AXP20X_VBUS_IPSOUT_MGMT,
-				  AXP20X_VBUS_PATH_SEL, val);
-}
-
 static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
 					    int intval)
 {
@@ -290,9 +279,10 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_ONLINE:
-		if (power->axp20x_id != AXP813_ID)
+		if (!power->vbus_disable_bit)
 			return -EINVAL;
-		return axp813_usb_power_set_online(power, val->intval);
+
+		return regmap_field_write(power->vbus_disable_bit, !val->intval);
 
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		return axp20x_usb_power_set_voltage_min(power, val->intval);
@@ -320,7 +310,7 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy,
 	 * the VBUS input offline.
 	 */
 	if (psp == POWER_SUPPLY_PROP_ONLINE)
-		return power->axp20x_id == AXP813_ID;
+		return power->vbus_disable_bit != NULL;
 
 	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
 	       psp == POWER_SUPPLY_PROP_CURRENT_MAX;
@@ -434,6 +424,7 @@ static const struct axp_data axp813_data = {
 	.curr_lim_table = axp813_usb_curr_lim_table,
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 	.usb_bc_en_bit	= REG_FIELD(AXP288_BC_GLOBAL, 0, 0),
+	.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -579,6 +570,12 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = axp20x_regmap_field_alloc_optional(&pdev->dev, power->regmap,
+						 axp_data->vbus_disable_bit,
+						 &power->vbus_disable_bit);
+	if (ret)
+		return ret;
+
 	ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect,
 					   axp20x_usb_power_poll_vbus);
 	if (ret)
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 5/7] power: supply: axp20x_usb_power: Remove variant IDs from VBUS polling check
  2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
                   ` (3 preceding siblings ...)
  2023-05-10 11:50 ` [PATCH v1 4/7] power: supply: axp20x_usb_power: Use regmap field for VBUS disabling Aidan MacDonald
@ 2023-05-10 11:50 ` Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 6/7] power: supply: axp20x_usb_power: Add support for AXP192 Aidan MacDonald
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Aidan MacDonald @ 2023-05-10 11:50 UTC (permalink / raw
  To: sre, robh+dt, krzysztof.kozlowski+dt, conor+dt, wens
  Cc: linux-pm, devicetree, linux-kernel

Use an explicit boolean flag instead of a check based on the
variant ID. Since this is the last use of variant IDs in the
driver, also remove the IDs.

Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
---
 drivers/power/supply/axp20x_usb_power.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 89f076615d2e..089fe837a4b2 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -48,13 +48,13 @@ struct axp_data {
 	const struct power_supply_desc	*power_desc;
 	const char * const		*irq_names;
 	unsigned int			num_irq_names;
-	enum axp20x_variants		axp20x_id;
 	const int			*curr_lim_table;
 	struct reg_field		curr_lim_fld;
 	struct reg_field		vbus_valid_bit;
 	struct reg_field		vbus_mon_bit;
 	struct reg_field		usb_bc_en_bit;
 	struct reg_field		vbus_disable_bit;
+	bool				vbus_needs_polling: 1;
 };
 
 struct axp20x_usb_power {
@@ -65,7 +65,6 @@ struct axp20x_usb_power {
 	struct regmap_field *usb_bc_en_bit;
 	struct regmap_field *vbus_disable_bit;
 	struct power_supply *supply;
-	enum axp20x_variants axp20x_id;
 	const struct axp_data *axp_data;
 	struct iio_channel *vbus_v;
 	struct iio_channel *vbus_i;
@@ -83,7 +82,7 @@ static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
 	 * present->absent transition implies an online->offline transition
 	 * and will trigger the VBUS_REMOVAL IRQ.
 	 */
-	if (power->axp20x_id >= AXP221_ID && !power->online)
+	if (power->axp_data->vbus_needs_polling && !power->online)
 		return true;
 
 	return false;
@@ -391,7 +390,6 @@ static const struct axp_data axp202_data = {
 	.power_desc	= &axp20x_usb_power_desc,
 	.irq_names	= axp20x_irq_names,
 	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),
-	.axp20x_id	= AXP202_ID,
 	.curr_lim_table = axp20x_usb_curr_lim_table,
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 	.vbus_valid_bit = REG_FIELD(AXP20X_USB_OTG_STATUS, 2, 2),
@@ -402,29 +400,29 @@ static const struct axp_data axp221_data = {
 	.power_desc	= &axp22x_usb_power_desc,
 	.irq_names	= axp22x_irq_names,
 	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
-	.axp20x_id	= AXP221_ID,
 	.curr_lim_table = axp221_usb_curr_lim_table,
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+	.vbus_needs_polling = true,
 };
 
 static const struct axp_data axp223_data = {
 	.power_desc	= &axp22x_usb_power_desc,
 	.irq_names	= axp22x_irq_names,
 	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
-	.axp20x_id	= AXP223_ID,
 	.curr_lim_table = axp20x_usb_curr_lim_table,
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
+	.vbus_needs_polling = true,
 };
 
 static const struct axp_data axp813_data = {
 	.power_desc	= &axp22x_usb_power_desc,
 	.irq_names	= axp22x_irq_names,
 	.num_irq_names	= ARRAY_SIZE(axp22x_irq_names),
-	.axp20x_id	= AXP813_ID,
 	.curr_lim_table = axp813_usb_curr_lim_table,
 	.curr_lim_fld   = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 0, 1),
 	.usb_bc_en_bit	= REG_FIELD(AXP288_BC_GLOBAL, 0, 0),
 	.vbus_disable_bit = REG_FIELD(AXP20X_VBUS_IPSOUT_MGMT, 7, 7),
+	.vbus_needs_polling = true,
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -542,7 +540,6 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, power);
 
-	power->axp20x_id = axp_data->axp20x_id;
 	power->axp_data = axp_data;
 	power->regmap = axp20x->regmap;
 	power->num_irqs = axp_data->num_irq_names;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 6/7] power: supply: axp20x_usb_power: Add support for AXP192
  2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
                   ` (4 preceding siblings ...)
  2023-05-10 11:50 ` [PATCH v1 5/7] power: supply: axp20x_usb_power: Remove variant IDs from VBUS polling check Aidan MacDonald
@ 2023-05-10 11:50 ` Aidan MacDonald
  2023-05-10 11:50 ` [PATCH v1 7/7] dt-bindings: power: supply: axp20x: Add AXP192 compatible Aidan MacDonald
  2023-05-15 21:26 ` [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Sebastian Reichel
  7 siblings, 0 replies; 10+ messages in thread
From: Aidan MacDonald @ 2023-05-10 11:50 UTC (permalink / raw
  To: sre, robh+dt, krzysztof.kozlowski+dt, conor+dt, wens
  Cc: linux-pm, devicetree, linux-kernel

Add support for the AXP192. It is most similar to the AXP202 but
the current limits are different and the USB OTG status register
has a different address (0x04 instead of 0x02).

Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
---
 drivers/power/supply/axp20x_usb_power.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index 089fe837a4b2..51c3f9b6458d 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -26,6 +26,8 @@
 
 #define DRVNAME "axp20x-usb-power-supply"
 
+#define AXP192_USB_OTG_STATUS		0x04
+
 #define AXP20X_PWR_STATUS_VBUS_PRESENT	BIT(5)
 #define AXP20X_PWR_STATUS_VBUS_USED	BIT(4)
 
@@ -365,6 +367,13 @@ static const char * const axp22x_irq_names[] = {
 	"VBUS_REMOVAL",
 };
 
+static int axp192_usb_curr_lim_table[] = {
+	-1,
+	-1,
+	500000,
+	100000,
+};
+
 static int axp20x_usb_curr_lim_table[] = {
 	900000,
 	500000,
@@ -386,6 +395,16 @@ static int axp813_usb_curr_lim_table[] = {
 	2500000,
 };
 
+static const struct axp_data axp192_data = {
+	.power_desc	= &axp20x_usb_power_desc,
+	.irq_names	= axp20x_irq_names,
+	.num_irq_names	= ARRAY_SIZE(axp20x_irq_names),
+	.curr_lim_table = axp192_usb_curr_lim_table,
+	.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),
+};
+
 static const struct axp_data axp202_data = {
 	.power_desc	= &axp20x_usb_power_desc,
 	.irq_names	= axp20x_irq_names,
@@ -634,6 +653,9 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
 
 static const struct of_device_id axp20x_usb_power_match[] = {
 	{
+		.compatible = "x-powers,axp192-usb-power-supply",
+		.data = &axp192_data,
+	}, {
 		.compatible = "x-powers,axp202-usb-power-supply",
 		.data = &axp202_data,
 	}, {
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v1 7/7] dt-bindings: power: supply: axp20x: Add AXP192 compatible
  2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
                   ` (5 preceding siblings ...)
  2023-05-10 11:50 ` [PATCH v1 6/7] power: supply: axp20x_usb_power: Add support for AXP192 Aidan MacDonald
@ 2023-05-10 11:50 ` Aidan MacDonald
  2023-05-10 14:22   ` Krzysztof Kozlowski
  2023-05-15 21:26 ` [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Sebastian Reichel
  7 siblings, 1 reply; 10+ messages in thread
From: Aidan MacDonald @ 2023-05-10 11:50 UTC (permalink / raw
  To: sre, robh+dt, krzysztof.kozlowski+dt, conor+dt, wens
  Cc: linux-pm, devicetree, linux-kernel

The AXP192 is most similar to the AXP202, but the current
limits are different and the USB OTG status register has
a different address (0x04 instead of 0x02).

Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
---
 .../bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml  | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml b/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml
index 3ce648dd91bd..34b7959d6772 100644
--- a/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml
+++ b/Documentation/devicetree/bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml
@@ -22,6 +22,7 @@ properties:
   compatible:
     oneOf:
       - enum:
+          - x-powers,axp192-usb-power-supply
           - x-powers,axp202-usb-power-supply
           - x-powers,axp221-usb-power-supply
           - x-powers,axp223-usb-power-supply
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v1 7/7] dt-bindings: power: supply: axp20x: Add AXP192 compatible
  2023-05-10 11:50 ` [PATCH v1 7/7] dt-bindings: power: supply: axp20x: Add AXP192 compatible Aidan MacDonald
@ 2023-05-10 14:22   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2023-05-10 14:22 UTC (permalink / raw
  To: Aidan MacDonald, sre, robh+dt, krzysztof.kozlowski+dt, conor+dt,
	wens
  Cc: linux-pm, devicetree, linux-kernel

On 10/05/2023 13:50, Aidan MacDonald wrote:
> The AXP192 is most similar to the AXP202, but the current
> limits are different and the USB OTG status register has
> a different address (0x04 instead of 0x02).
> 
> Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
> ---
>  .../bindings/power/supply/x-powers,axp20x-usb-power-supply.yaml  | 1 +


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192
  2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
                   ` (6 preceding siblings ...)
  2023-05-10 11:50 ` [PATCH v1 7/7] dt-bindings: power: supply: axp20x: Add AXP192 compatible Aidan MacDonald
@ 2023-05-15 21:26 ` Sebastian Reichel
  7 siblings, 0 replies; 10+ messages in thread
From: Sebastian Reichel @ 2023-05-15 21:26 UTC (permalink / raw
  To: Aidan MacDonald
  Cc: robh+dt, krzysztof.kozlowski+dt, conor+dt, wens, linux-pm,
	devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1381 bytes --]

Hi,

On Wed, May 10, 2023 at 12:50:39PM +0100, Aidan MacDonald wrote:
> This adds support for the AXP192's USB power supply. Most of this
> series (patches 1-5) consists of refactoring the driver to avoid
> explicit checks based on the variant ID. Doing that makes it very
> easy to add support for the AXP192 in patches 6-7, and as a nice
> side benefit, should make the driver more maintainable.
> 
> Patches 1-5 are unchanged from their previous submission[1].
> 
> [1] https://lore.kernel.org/all/20230218204946.106316-1-aidanmacdonald.0x0@gmail.com/
> 
> Aidan MacDonald (7):
>   power: supply: axp20x_usb_power: Simplify USB current limit handling
>   power: supply: axp20x_usb_power: Use regmap fields for VBUS monitor
>     feature
>   power: supply: axp20x_usb_power: Use regmap fields for USB BC feature
>   power: supply: axp20x_usb_power: Use regmap field for VBUS disabling
>   power: supply: axp20x_usb_power: Remove variant IDs from VBUS polling
>     check
>   power: supply: axp20x_usb_power: Add support for AXP192
>   dt-bindings: power: supply: axp20x: Add AXP192 compatible
> 
>  .../x-powers,axp20x-usb-power-supply.yaml     |   1 +
>  drivers/power/supply/axp20x_usb_power.c       | 307 +++++++++---------
>  2 files changed, 153 insertions(+), 155 deletions(-)

Thanks, queued to power-supply's for-next branch.

-- Sebastian

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-05-15 21:26 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-05-10 11:50 [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Aidan MacDonald
2023-05-10 11:50 ` [PATCH v1 1/7] power: supply: axp20x_usb_power: Simplify USB current limit handling Aidan MacDonald
2023-05-10 11:50 ` [PATCH v1 2/7] power: supply: axp20x_usb_power: Use regmap fields for VBUS monitor feature Aidan MacDonald
2023-05-10 11:50 ` [PATCH v1 3/7] power: supply: axp20x_usb_power: Use regmap fields for USB BC feature Aidan MacDonald
2023-05-10 11:50 ` [PATCH v1 4/7] power: supply: axp20x_usb_power: Use regmap field for VBUS disabling Aidan MacDonald
2023-05-10 11:50 ` [PATCH v1 5/7] power: supply: axp20x_usb_power: Remove variant IDs from VBUS polling check Aidan MacDonald
2023-05-10 11:50 ` [PATCH v1 6/7] power: supply: axp20x_usb_power: Add support for AXP192 Aidan MacDonald
2023-05-10 11:50 ` [PATCH v1 7/7] dt-bindings: power: supply: axp20x: Add AXP192 compatible Aidan MacDonald
2023-05-10 14:22   ` Krzysztof Kozlowski
2023-05-15 21:26 ` [PATCH v1 0/7] axp20x_usb_power: Add support for AXP192 Sebastian Reichel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).