From patchwork Wed Oct 2 11:25:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Icenowy Zheng X-Patchwork-Id: 11170887 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2AC7F1599 for ; Wed, 2 Oct 2019 11:36:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 13DF62133F for ; Wed, 2 Oct 2019 11:36:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726888AbfJBLgJ (ORCPT ); Wed, 2 Oct 2019 07:36:09 -0400 Received: from hermes.aosc.io ([199.195.250.187]:42753 "EHLO hermes.aosc.io" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726239AbfJBLgJ (ORCPT ); Wed, 2 Oct 2019 07:36:09 -0400 X-Greylist: delayed 566 seconds by postgrey-1.27 at vger.kernel.org; Wed, 02 Oct 2019 07:36:09 EDT Received: from localhost (localhost [127.0.0.1]) (Authenticated sender: icenowy@aosc.io) by hermes.aosc.io (Postfix) with ESMTPSA id DE8DE82D37; Wed, 2 Oct 2019 11:26:45 +0000 (UTC) From: Icenowy Zheng To: Sebastian Reichel , Chen-Yu Tsai Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com, Icenowy Zheng Subject: [PATCH 1/2] power: supply: axp20x_usb_power: enable USB BC detection on AXP813 Date: Wed, 2 Oct 2019 19:25:44 +0800 Message-Id: <20191002112545.58481-2-icenowy@aosc.io> In-Reply-To: <20191002112545.58481-1-icenowy@aosc.io> References: <20191002112545.58481-1-icenowy@aosc.io> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The AXP813 PMIC has support for detection of USB Battery Charging specification, and it will limit the current to 500mA by default when the detection is not enabled or the detection result is SDP. Enable the BC detection to allow correctly selection of the current. Signed-off-by: Icenowy Zheng --- drivers/power/supply/axp20x_usb_power.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index dc4c316eff81..5f0a5722b19e 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -48,6 +48,8 @@ #define AXP20X_VBUS_MON_VBUS_VALID 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. @@ -495,6 +497,12 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) return -EINVAL; } + if (power->axp20x_id == AXP813_ID) { + /* Enable USB Battery Charging specification detection */ + regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL, + AXP813_BC_EN, AXP813_BC_EN); + } + psy_cfg.of_node = pdev->dev.of_node; psy_cfg.drv_data = power; From patchwork Wed Oct 2 11:25:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Icenowy Zheng X-Patchwork-Id: 11170891 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DE55513B1 for ; Wed, 2 Oct 2019 11:36:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BDA342133F for ; Wed, 2 Oct 2019 11:36:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726464AbfJBLgK (ORCPT ); Wed, 2 Oct 2019 07:36:10 -0400 Received: from hermes.aosc.io ([199.195.250.187]:42754 "EHLO hermes.aosc.io" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726839AbfJBLgK (ORCPT ); Wed, 2 Oct 2019 07:36:10 -0400 Received: from localhost (localhost [127.0.0.1]) (Authenticated sender: icenowy@aosc.io) by hermes.aosc.io (Postfix) with ESMTPSA id BFE2482D3A; Wed, 2 Oct 2019 11:26:54 +0000 (UTC) From: Icenowy Zheng To: Sebastian Reichel , Chen-Yu Tsai Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com, Icenowy Zheng Subject: [PATCH 2/2] power: supply: axp20x_usb_power: add applied max Vbus support for AXP813 Date: Wed, 2 Oct 2019 19:25:45 +0800 Message-Id: <20191002112545.58481-3-icenowy@aosc.io> In-Reply-To: <20191002112545.58481-1-icenowy@aosc.io> References: <20191002112545.58481-1-icenowy@aosc.io> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org AXP813 PMIC has two Vbus maximum value settings -- one is the default value, which is currently the only supported one; the other is the really applied value, which is set according to the default value if the BC detection module detected a charging port, or 500mA if no charging port is detected. Add support for reading and writing of the really applied Vbus maxmium value. Interestingly it has a larger range than the default value. Signed-off-by: Icenowy Zheng --- drivers/power/supply/axp20x_usb_power.c | 132 +++++++++++++++++++++++- 1 file changed, 129 insertions(+), 3 deletions(-) diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index 5f0a5722b19e..905668a2727f 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -50,6 +50,18 @@ #define AXP813_BC_EN BIT(0) +#define AXP813_VBUS_CLIMIT_REAL_MASK GENMASK(7, 4) +#define AXP813_VBUS_CLIMIT_REAL_100mA (0 << 4) +#define AXP813_VBUS_CLIMIT_REAL_500mA (1 << 4) +#define AXP813_VBUS_CLIMIT_REAL_900mA (2 << 4) +#define AXP813_VBUS_CLIMIT_REAL_1500mA (3 << 4) +#define AXP813_VBUS_CLIMIT_REAL_2000mA (4 << 4) +#define AXP813_VBUS_CLIMIT_REAL_2500mA (5 << 4) +#define AXP813_VBUS_CLIMIT_REAL_3000mA (6 << 4) +#define AXP813_VBUS_CLIMIT_REAL_3500mA (7 << 4) +#define AXP813_VBUS_CLIMIT_REAL_4000mA (8 << 4) +/* The remaining values are all 4000mA according to the datasheet */ + /* * Note do not raise the debounce time, we must report Vusb high within * 100ms otherwise we get Vbus errors in musb. @@ -159,6 +171,47 @@ static int axp813_get_current_max(struct axp20x_usb_power *power, int *val) return 0; } +static int axp813_get_input_current_limit(struct axp20x_usb_power *power, int *val) +{ + unsigned int v; + int ret = regmap_read(power->regmap, AXP22X_CHRG_CTRL3, &v); + + if (ret) + return ret; + + switch (v & AXP813_VBUS_CLIMIT_REAL_MASK) { + case AXP813_VBUS_CLIMIT_REAL_100mA: + *val = 100000; + break; + case AXP813_VBUS_CLIMIT_REAL_500mA: + *val = 500000; + break; + case AXP813_VBUS_CLIMIT_REAL_900mA: + *val = 900000; + break; + case AXP813_VBUS_CLIMIT_REAL_1500mA: + *val = 1500000; + break; + case AXP813_VBUS_CLIMIT_REAL_2000mA: + *val = 2000000; + break; + case AXP813_VBUS_CLIMIT_REAL_2500mA: + *val = 2500000; + break; + case AXP813_VBUS_CLIMIT_REAL_3000mA: + *val = 3000000; + break; + case AXP813_VBUS_CLIMIT_REAL_3500mA: + *val = 3500000; + break; + default: + /* All other cases are 4000mA */ + *val = 4000000; + break; + } + return 0; +} + static int axp20x_usb_power_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { @@ -200,6 +253,8 @@ static int axp20x_usb_power_get_property(struct power_supply *psy, if (power->axp20x_id == AXP813_ID) return axp813_get_current_max(power, &val->intval); return axp20x_get_current_max(power, &val->intval); + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + return axp813_get_input_current_limit(power, &val->intval); case POWER_SUPPLY_PROP_CURRENT_NOW: if (IS_ENABLED(CONFIG_AXP20X_ADC)) { ret = iio_read_channel_processed(power->vbus_i, @@ -338,6 +393,48 @@ static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, return -EINVAL; } +static int axp20x_usb_power_set_input_current_limit(struct axp20x_usb_power *power, + int intval) +{ + int val; + + switch (intval) { + case 100000: + val = AXP813_VBUS_CLIMIT_REAL_100mA; + break; + case 500000: + val = AXP813_VBUS_CLIMIT_REAL_500mA; + break; + case 900000: + val = AXP813_VBUS_CLIMIT_REAL_900mA; + break; + case 1500000: + val = AXP813_VBUS_CLIMIT_REAL_1500mA; + break; + case 2000000: + val = AXP813_VBUS_CLIMIT_REAL_2000mA; + break; + case 2500000: + val = AXP813_VBUS_CLIMIT_REAL_2500mA; + break; + case 3000000: + val = AXP813_VBUS_CLIMIT_REAL_3000mA; + break; + case 3500000: + val = AXP813_VBUS_CLIMIT_REAL_3500mA; + break; + case 4000000: + val = AXP813_VBUS_CLIMIT_REAL_4000mA; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(power->regmap, + AXP22X_CHRG_CTRL3, + AXP813_VBUS_CLIMIT_REAL_MASK, val); +} + static int axp20x_usb_power_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *val) @@ -354,6 +451,9 @@ static int axp20x_usb_power_set_property(struct power_supply *psy, val->intval); return axp20x_usb_power_set_current_max(power, val->intval); + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + return axp20x_usb_power_set_input_current_limit(power, val->intval); + default: return -EINVAL; } @@ -365,7 +465,8 @@ static int axp20x_usb_power_prop_writeable(struct power_supply *psy, enum power_supply_property psp) { return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN || - psp == POWER_SUPPLY_PROP_CURRENT_MAX; + psp == POWER_SUPPLY_PROP_CURRENT_MAX || + psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT; } static enum power_supply_property axp20x_usb_power_properties[] = { @@ -386,6 +487,15 @@ static enum power_supply_property axp22x_usb_power_properties[] = { POWER_SUPPLY_PROP_CURRENT_MAX, }; +static enum power_supply_property axp813_usb_power_properties[] = { + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_VOLTAGE_MIN, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, +}; + static const struct power_supply_desc axp20x_usb_power_desc = { .name = "axp20x-usb", .type = POWER_SUPPLY_TYPE_USB, @@ -406,6 +516,16 @@ static const struct power_supply_desc axp22x_usb_power_desc = { .set_property = axp20x_usb_power_set_property, }; +static const struct power_supply_desc axp813_usb_power_desc = { + .name = "axp20x-usb", + .type = POWER_SUPPLY_TYPE_USB, + .properties = axp813_usb_power_properties, + .num_properties = ARRAY_SIZE(axp813_usb_power_properties), + .property_is_writeable = axp20x_usb_power_prop_writeable, + .get_property = axp20x_usb_power_get_property, + .set_property = axp20x_usb_power_set_property, +}; + static int configure_iio_channels(struct platform_device *pdev, struct axp20x_usb_power *power) { @@ -487,10 +607,16 @@ static int axp20x_usb_power_probe(struct platform_device *pdev) usb_power_desc = &axp20x_usb_power_desc; irq_names = axp20x_irq_names; } else if (power->axp20x_id == AXP221_ID || - power->axp20x_id == AXP223_ID || - power->axp20x_id == AXP813_ID) { + power->axp20x_id == AXP223_ID) { usb_power_desc = &axp22x_usb_power_desc; irq_names = axp22x_irq_names; + } else if (power->axp20x_id == AXP813_ID) { + usb_power_desc = &axp813_usb_power_desc; + irq_names = axp22x_irq_names; + + /* Enable USB Battery Charging specification detection */ + regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL, + AXP813_BC_EN, AXP813_BC_EN); } else { dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", axp20x->variant);