From patchwork Mon Jun 15 14:05:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Machek X-Patchwork-Id: 11605133 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 2C03B13B1 for ; Mon, 15 Jun 2020 14:06:23 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0154F207F5 for ; Mon, 15 Jun 2020 14:06:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="N0T0jw6b" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0154F207F5 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ucw.cz Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: MIME-Version:Message-ID:Subject:To:From:Date:Reply-To:Cc: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=nOGD3vr3OMQpaUy2+KKJivPNGRB8738RzyS2PXuKCag=; b=N0T 0jw6bqmlNRuJSxtwqud5Rs7PhnYQMOrFphGuyKdkT/EtrFF9IhS58l95e3Eg7WNN0zs3wL+zOcO/L 16C/k9LPcJ1dTZJgJemjeegWa4RP2qy1TGmzrd0EtClmf711J+S39QIraC5nHbZOyyoftbJygAgUs gSopr3pRagnAH9pmfapflkd7t+I2Me4osthzRA94oM1ykyaCh526k59yoE2dtxnUuVclPzQnBsx5w Y8ONEVkHz7jmXip8fFMZYCKm1X6mcKB30u8vMiAmfFz37sBB0i2xsFUF5IL2WzRxywQZD5joubAuE mdaD51/+LrOKOCPvdT1BZINH0GVXqXA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jkpkc-00009v-6m; Mon, 15 Jun 2020 14:06:14 +0000 Received: from jabberwock.ucw.cz ([46.255.230.98]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jkpkY-000090-Sh for linux-arm-kernel@lists.infradead.org; Mon, 15 Jun 2020 14:06:13 +0000 Received: by jabberwock.ucw.cz (Postfix, from userid 1017) id CC4281C0BD2; Mon, 15 Jun 2020 16:05:57 +0200 (CEST) Date: Mon, 15 Jun 2020 16:05:57 +0200 From: Pavel Machek To: kernel list , linux-arm-kernel , linux-omap@vger.kernel.org, tony@atomide.com, sre@kernel.org, nekit1000@gmail.com, mpartap@gmx.net, merlijn@wizzup.org, martin_rysavy@centrum.cz, linux-pm@vger.kernel.org Subject: [RFC] Limiting charge current on Droid 4 (and N900) Message-ID: <20200615140557.GA22781@duo.ucw.cz> MIME-Version: 1.0 User-Agent: Mutt/1.10.1 (2018-07-13) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200615_070611_081762_B103110B X-CRM114-Status: GOOD ( 12.97 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Hi! Droid 4 has same problem as N900: it is often neccessary to manually tweak current draw from USB, for example when using thin charging cable. N900 creates unique attribute by hand, but I believe POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT looks suitable. (Should N900 be converted?) Comments? Would the patch be acceptable after fixing whitespace? Best regards, Pavel Signed-off-by: Pavel Machek diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c index b16848cfb58c..39a00716372f 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -3,7 +3,7 @@ * * Copyright (C) 2017 Tony Lindgren * - * Some parts of the code based on earlie Motorola mapphone Linux kernel + * Some parts of the code based on earlier Motorola mapphone Linux kernel * drivers: * * Copyright (C) 2009-2010 Motorola, Inc. diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c index cf1e05b511d9..292d7a31c663 100644 --- a/drivers/power/supply/cpcap-charger.c +++ b/drivers/power/supply/cpcap-charger.c @@ -89,6 +89,8 @@ * CPCAP_REG_CRM charge currents. These seem to match MC13783UG.pdf * values in "Table 8-3. Charge Path Regulator Current Limit * Characteristics" for the nominal values. + * + * Except 70mA and 1.596A and unlimited, these are simply 88.7mA / step. */ #define CPCAP_REG_CRM_ICHRG(val) (((val) & 0xf) << 0) #define CPCAP_REG_CRM_ICHRG_0A000 CPCAP_REG_CRM_ICHRG(0x0) @@ -147,6 +149,8 @@ struct cpcap_charger_ddata { int status; int state; int voltage; + int limit_current; + int last_current; int last_current_retries; }; @@ -175,6 +179,7 @@ static enum power_supply_property cpcap_charger_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, }; @@ -238,6 +243,9 @@ static int cpcap_charger_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_STATUS: val->intval = ddata->status; break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + val->intval = ddata->limit_current; + break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: val->intval = ddata->voltage; break; @@ -308,6 +316,25 @@ cpcap_charger_get_bat_const_charge_voltage(struct cpcap_charger_ddata *ddata) return voltage; } +static int cpcap_charger_current_to_regval(int microamp) +{ + int miliamp = microamp/1000; + int res; + if (miliamp < 0) + return -EINVAL; + if (miliamp < 70) + return CPCAP_REG_CRM_ICHRG(0x0); + if (miliamp < 177) + return CPCAP_REG_CRM_ICHRG(0x1); + if (miliamp > 1596) + return CPCAP_REG_CRM_ICHRG(0xe); + + res = microamp / 88666; + if (res > 0xd) + res = 0xd; + return CPCAP_REG_CRM_ICHRG(res); +} + static int cpcap_charger_set_property(struct power_supply *psy, enum power_supply_property psp, const union power_supply_propval *val) @@ -316,6 +343,12 @@ static int cpcap_charger_set_property(struct power_supply *psy, int voltage, batvolt; switch (psp) { + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: + if (cpcap_charger_current_to_regval(val->intval) < 0) + return -EINVAL; + ddata->limit_current = val->intval; + schedule_delayed_work(&ddata->detect_work, 0); + break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: voltage = cpcap_charger_match_voltage(val->intval); batvolt = cpcap_charger_get_bat_const_charge_voltage(ddata); @@ -335,6 +368,7 @@ static int cpcap_charger_property_is_writeable(struct power_supply *psy, enum power_supply_property psp) { switch (psp) { + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: return 1; default: @@ -657,23 +691,21 @@ static void cpcap_usb_detect(struct work_struct *work) if (!ddata->feeding_vbus && cpcap_charger_vbus_valid(ddata) && s.chrgcurr1) { - int max_current; - int vchrg; + int max_current = 532000; + int vchrg, ichrg; if (cpcap_charger_battery_found(ddata)) - max_current = CPCAP_REG_CRM_ICHRG_1A596; - else - max_current = CPCAP_REG_CRM_ICHRG_0A532; + max_current = 1596000; switch (ddata->state) { case CPCAP_CHARGER_DETECTING: ddata->last_current_retries = 0; break; case CPCAP_CHARGER_DISCONNECTED: - if (ddata->last_current > CPCAP_REG_CRM_ICHRG_0A532) { + if (ddata->last_current > 532000) { /* Attempt current 3 times before lowering */ if (ddata->last_current_retries++ >= 3) { - ddata->last_current--; + ddata->last_current -= 100000; ddata->last_current_retries = 0; /* Wait a bit for voltage to ramp up */ usleep_range(40000, 50000); @@ -688,11 +720,16 @@ static void cpcap_usb_detect(struct work_struct *work) break; } + if (max_current > ddata->limit_current) + max_current = ddata->limit_current; + ddata->last_current = max_current; + + ichrg = cpcap_charger_current_to_regval(max_current); vchrg = cpcap_charger_voltage_to_regval(ddata->voltage); error = cpcap_charger_set_state(ddata, CPCAP_REG_CRM_VCHRG(vchrg), - max_current, 0); + ichrg, 0); if (error) goto out_err; cpcap_charger_update_state(ddata, CPCAP_CHARGER_CHARGING); @@ -864,6 +901,7 @@ static int cpcap_charger_probe(struct platform_device *pdev) ddata->dev = &pdev->dev; ddata->voltage = 4200000; + ddata->limit_current = 532000; ddata->reg = dev_get_regmap(ddata->dev->parent, NULL); if (!ddata->reg)