[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220629143046.213584-12-aidanmacdonald.0x0@gmail.com>
Date: Wed, 29 Jun 2022 15:30:42 +0100
From: Aidan MacDonald <aidanmacdonald.0x0@...il.com>
To: linus.walleij@...aro.org, brgl@...ev.pl, robh+dt@...nel.org,
krzysztof.kozlowski+dt@...aro.org, wens@...e.org, jic23@...nel.org,
sre@...nel.org, lee.jones@...aro.org, lgirdwood@...il.com,
broonie@...nel.org
Cc: lars@...afoo.de, quic_gurus@...cinc.com,
sebastian.reichel@...labora.com, andy.shevchenko@...il.com,
michael@...le.cc, rdunlap@...radead.org,
linux-gpio@...r.kernel.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-iio@...r.kernel.org,
linux-pm@...r.kernel.org
Subject: [PATCH v4 11/15] power: supply: axp20x_usb_power: Add support for AXP192
The AXP192's USB power supply is similar to the AXP202 but it has
different USB current limits and a different offset for the VBUS
status register.
Acked-by: Sebastian Reichel <sebastian.reichel@...labora.com>
Reviewed-by: Chen-Yu Tsai <wens@...e.org>
Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@...il.com>
---
drivers/power/supply/axp20x_usb_power.c | 84 +++++++++++++++++++++----
1 file changed, 73 insertions(+), 11 deletions(-)
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index a1e6d1d44808..f83e2ed6d507 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -48,6 +48,9 @@
#define AXP813_VBUS_CLIMIT_2000mA 2
#define AXP813_VBUS_CLIMIT_2500mA 3
+#define AXP192_VBUS_CLIMIT_EN BIT(1)
+#define AXP192_VBUS_CLIMIT_100mA BIT(0)
+
#define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)
@@ -121,6 +124,25 @@ 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 axp192_get_current_max(struct axp20x_usb_power *power, int *val)
+{
+ unsigned int v;
+ int ret;
+
+ ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
+ if (ret)
+ return ret;
+
+ if (!(v & AXP192_VBUS_CLIMIT_EN))
+ *val = -1;
+ else if (v & AXP192_VBUS_CLIMIT_100mA)
+ *val = 100000;
+ else
+ *val = 500000;
+
+ return 0;
+}
+
static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val)
{
unsigned int v;
@@ -179,7 +201,7 @@ static int axp20x_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 input, v;
+ unsigned int input, v, reg;
int ret;
switch (psp) {
@@ -215,6 +237,8 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CURRENT_MAX:
if (power->axp20x_id == AXP813_ID)
return axp813_get_current_max(power, &val->intval);
+ else if (power->axp20x_id == AXP192_ID)
+ return axp192_get_current_max(power, &val->intval);
return axp20x_get_current_max(power, &val->intval);
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
@@ -256,16 +280,19 @@ 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 (ret)
- return ret;
+ if (power->axp20x_id == AXP192_ID)
+ reg = AXP192_USB_OTG_STATUS;
+ else if (power->axp20x_id == AXP202_ID)
+ reg = AXP20X_USB_OTG_STATUS;
+ else
+ break; /* Other chips lack the OTG status register */
- if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
- val->intval =
- POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
- }
+ ret = regmap_read(power->regmap, reg, &v);
+ if (ret)
+ return ret;
+
+ if (!(v & AXP20X_USB_STATUS_VBUS_VALID))
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
break;
case POWER_SUPPLY_PROP_PRESENT:
val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
@@ -316,6 +343,28 @@ static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power,
return -EINVAL;
}
+static int axp192_usb_power_set_current_max(struct axp20x_usb_power *power,
+ int intval)
+{
+ const unsigned int mask = AXP192_VBUS_CLIMIT_EN |
+ AXP192_VBUS_CLIMIT_100mA;
+ unsigned int val;
+
+ switch (intval) {
+ case 100000:
+ val = AXP192_VBUS_CLIMIT_EN | AXP192_VBUS_CLIMIT_100mA;
+ break;
+ case 500000:
+ val = AXP192_VBUS_CLIMIT_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return regmap_update_bits(power->regmap,
+ AXP20X_VBUS_IPSOUT_MGMT, mask, val);
+}
+
static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power,
int intval)
{
@@ -383,6 +432,9 @@ static int axp20x_usb_power_set_property(struct power_supply *psy,
if (power->axp20x_id == AXP813_ID)
return axp813_usb_power_set_current_max(power,
val->intval);
+ else if (power->axp20x_id == AXP192_ID)
+ return axp192_usb_power_set_current_max(power,
+ val->intval);
return axp20x_usb_power_set_current_max(power, val->intval);
default:
@@ -468,6 +520,13 @@ struct axp_data {
enum axp20x_variants axp20x_id;
};
+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),
+ .axp20x_id = AXP192_ID,
+};
+
static const struct axp_data axp202_data = {
.power_desc = &axp20x_usb_power_desc,
.irq_names = axp20x_irq_names,
@@ -600,7 +659,7 @@ static int axp20x_usb_power_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (power->axp20x_id == AXP202_ID) {
+ if (power->axp20x_id == AXP192_ID || power->axp20x_id == AXP202_ID) {
/* Enable vbus valid checking */
ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
AXP20X_VBUS_MON_VBUS_VALID,
@@ -659,6 +718,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.35.1
Powered by blists - more mailing lists