From patchwork Wed Nov 14 09:07:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 151053 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp5441552ljp; Wed, 14 Nov 2018 01:07:50 -0800 (PST) X-Google-Smtp-Source: AJdET5dxCWtkS7H7LeECjNhVM3GPQUq+7ppbVs0tNl9NymAL6GZa5ooUQBn5mfS7BXSRg1MY8vjv X-Received: by 2002:a17:902:b103:: with SMTP id q3-v6mr1085533plr.83.1542186470401; Wed, 14 Nov 2018 01:07:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542186470; cv=none; d=google.com; s=arc-20160816; b=Ti2uZD52If+QPHfhQ4xhaC6iDKtyx2vQ1+afCRv9QjM0h94zrYLA+lPYO+OqvmAsG8 DTk2BJ3HZ9MsAyvuwt9ey/ZbcblwVfa0BN7AWOdxjSXE+Bubw89jng5uVrIluru33hd0 9Stt2jorVAOTTfpbfP8KRLU5TwUJ3zINhpupob8pGeoIPHYt6DeIghonJ9x+K+9C2bIl p8XasF5oEf1rZNVas49JSr0FxdjZbbezbDILni4cQSV3PGpBcnF1NHX2ebYzxINWraqi PrFTKcocueKXJ4lYOInljVX66cbN3E98ljqbzg4cSALfjC536Ha7JzHRi9lqiTFb++Z0 t80g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=wMyqG5pI89CV6L/8kIrcswRejq6Wasnn2q5PPPGYQHQ=; b=OKnIH74ZzSbL22XN8OUe6bkOFfGOtr1SIQO4Eb/5H+ofs8MTPcRO/kEcZDKp0Q0qjW zjNgVd2kVlOQhO9VY1YE1XErZn3CO4nuFqReGTIqSecUBbOvblNZWDN7XFaRBPQ3XUR0 Csj70w+llcNG6ptu2AjcQk2d6cWNttv+nyGEb19P8L1zC2P3FPFIbjTx1oOH1zfQc6x5 N5+38B+oar1TdfCeP/2gzHPoJV/6ycus63beRg1uzk832Pnzih5iIaP0cYm/4mW7E9vv 9n9+g07TmgD32RNk70ASJKgBXFa6cSlRVeKljAVzZXfNqoEgiByUUjD5fK2xZZdrs5os E/Gw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=PWED4Jlt; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c76si11007819pga.70.2018.11.14.01.07.50; Wed, 14 Nov 2018 01:07:50 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=PWED4Jlt; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732308AbeKNTKJ (ORCPT + 32 others); Wed, 14 Nov 2018 14:10:09 -0500 Received: from mail-pl1-f194.google.com ([209.85.214.194]:40461 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727966AbeKNTKI (ORCPT ); Wed, 14 Nov 2018 14:10:08 -0500 Received: by mail-pl1-f194.google.com with SMTP id b22-v6so2030442pls.7 for ; Wed, 14 Nov 2018 01:07:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=wMyqG5pI89CV6L/8kIrcswRejq6Wasnn2q5PPPGYQHQ=; b=PWED4JltQZuViISB1WJMjPC5sXuvT1qCn/cpN0jSJrUClI9PUTCKikuXf9KwQmzlx0 nFlqcXoxIw0gzP5yhJd9R6e2/OuJxKEkD15JU/cKX/VS7v5ji1r/V1uV4F/fXpdUVRJO LGuOxAmAKT61wiE1W2JN/pr6rUvb3YsE06eBw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=wMyqG5pI89CV6L/8kIrcswRejq6Wasnn2q5PPPGYQHQ=; b=URdWUhHquPqV7KIYopSxjltcv/7eKEnL7SFbVb6c21007DtoIaRO7bTwqPkOp1dmVz M7fcTwDtIelOxAOukYK9Ocfw62i8CtBlp9/jMW3fPCmi7MJx++gj8Z156hj3N0o2JQb/ /c16QzPYxOxtsMVWSG1p/uorgd2ckJkqjaVZBGmSsZIRkrelV/dDYILj2MW+3v3XpOh/ 6xHciREsuj1FsPTyDkclzwlLNy5HKGhiYNllgZmzsHFPhVzIL8D+qvu+L4wWfFPpCCA0 wBh1lLiz3jFV54ALdqeySwAp3Z+hkdmxAdYxKIMs3KQ9dOJdqxj7p2V7GZi/GPCP1L1A Uq+A== X-Gm-Message-State: AGRZ1gJ9qULvOdbA2LVAGVeZz0f4a15GbZRnymdTjCprwx+4gE75N8eK 2m1eRRmFI+QVle6ciGWbMZ4Wbg== X-Received: by 2002:a17:902:110a:: with SMTP id d10-v6mr1097461pla.85.1542186466971; Wed, 14 Nov 2018 01:07:46 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.102]) by smtp.gmail.com with ESMTPSA id 127-v6sm25048814pfx.91.2018.11.14.01.07.43 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 14 Nov 2018 01:07:46 -0800 (PST) From: Baolin Wang To: sre@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com Cc: linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, yuanjiang.yu@unisoc.com, baolin.wang@linaro.org, broonie@kernel.org Subject: [PATCH 1/5] dt-bindings: power: supply: Add nvmem properties to calibrate FGU Date: Wed, 14 Nov 2018 17:07:04 +0800 Message-Id: <09143dca85a260cb6c3abc5efcf09075a8050265.1542185618.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add nvmem properties to calibrate FGU from eFuse controller. Signed-off-by: Baolin Wang --- .../devicetree/bindings/power/supply/sc27xx-fg.txt | 4 ++++ 1 file changed, 4 insertions(+) -- 1.7.9.5 diff --git a/Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt b/Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt index 98a2400..fc35ac5 100644 --- a/Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt +++ b/Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt @@ -11,6 +11,8 @@ Required properties: - battery-detect-gpios: GPIO for battery detection. - io-channels: Specify the IIO ADC channel to get temperature. - io-channel-names: Should be "bat-temp". +- nvmem-cells: A phandle to the calibration cells provided by eFuse device. +- nvmem-cell-names: Should be "fgu_calib". - monitored-battery: Phandle of battery characteristics devicetree node. See Documentation/devicetree/bindings/power/supply/battery.txt @@ -47,6 +49,8 @@ Example: battery-detect-gpios = <&pmic_eic 9 GPIO_ACTIVE_HIGH>; io-channels = <&pmic_adc 5>; io-channel-names = "bat-temp"; + nvmem-cells = <&fgu_calib>; + nvmem-cell-names = "fgu_calib"; monitored-battery = <&bat>; }; }; From patchwork Wed Nov 14 09:07:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 151054 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp5441594ljp; Wed, 14 Nov 2018 01:07:53 -0800 (PST) X-Google-Smtp-Source: AJdET5ciWwr8YPoo6nnTDVu+Nh2GiV7sAkdg7za1++yaFUZDb0LFFETV0dcMpdQ9HgWLwrqVzFHW X-Received: by 2002:a63:1157:: with SMTP id 23mr980807pgr.245.1542186473208; Wed, 14 Nov 2018 01:07:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542186473; cv=none; d=google.com; s=arc-20160816; b=Wa+BgEHW2npRZulT+IPk3cYQiN5kqG/3BIpVeNrDMZjdIDZ6KMBLHlYpihW7n7LV2e i/vAhtpDK9LPzGnM39Brqs7oPMLZr+FfLx1UVranOXkMPNerQdBFREF+UXHb11uwlLVX WzVartc/hSjtw//Heb/R/sonbj+qmKQz+csGUbyy2NPMMGIvoEJxH7jc+MNwMESaoFFE +7281PqUwLXaimPXcgXvC/7lBjy6Gj2lZ4VLNQJOpOHXy8U4+uarbja+ir//3H5NyKMy imQQMX49szt4YW6Vh0j54nVsq1LQGJlMf/xj/uLb/I35IYg/Dq9tj6FLJKdd7AZHHVK0 BhnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=5jCGoWWaBFWMEfVdu5BxQTbZHcNaLmB1PTqRJRj8eG0=; b=q2IsFfFm8QUleH495mGbOZoYd3HJ1qKPnGTWdYhjvw9XgQuKmWmWS6mVQCgEt664kf mKFoSxGiRrUrR4c3g/SMB4fK5cnwJJn4oLyMC4WJikkNhxbQaO4K/pSYfKBaI913iz4w 8KKqxUlU5VEHdBiSq9c8lSATcCBcCUO2QgZsfgTMrCe1LZjLZK972ig6LJ/v0nq56B/Z w+kOjD90thrFfZV+hmvVzNUivUMo/KiD6EUtFW2/Js9vM2HVUesJRIUFf1DBKwc75J3G yL75C5kpiaOjhHHhlNb+yVP9Y1sEy/+LSjkScSk+ddMeNEt2AiL76BAyXmID79pj5SVr u1bA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BwnucNaA; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m10-v6si20155777pll.320.2018.11.14.01.07.52; Wed, 14 Nov 2018 01:07:53 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BwnucNaA; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732400AbeKNTKM (ORCPT + 32 others); Wed, 14 Nov 2018 14:10:12 -0500 Received: from mail-pg1-f196.google.com ([209.85.215.196]:35564 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727966AbeKNTKM (ORCPT ); Wed, 14 Nov 2018 14:10:12 -0500 Received: by mail-pg1-f196.google.com with SMTP id 32-v6so7081229pgu.2 for ; Wed, 14 Nov 2018 01:07:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=5jCGoWWaBFWMEfVdu5BxQTbZHcNaLmB1PTqRJRj8eG0=; b=BwnucNaAnlGs23qpoK4CECQiv24ZjCFhPKAY33oXhEsXPMffEElmigj4ZKEwQDghNK M0HzRXJuvWUjH/spyWEqUdXhjcox27pGsjpwISK3OI0ageH3R8aTYtTNmFE5g8E5parg RIrkGBfWPZ6Fccbq467RTsp8AGP401aUV0Dkc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=5jCGoWWaBFWMEfVdu5BxQTbZHcNaLmB1PTqRJRj8eG0=; b=bbGleZ/KKqrqfztno+HcNjhNZSq6RTQOUqmKjbBmWFxj/GeFuKF1pvib6GAyR5nXAc CyKbxuSXvcQmMxlt0DABFOqeMvPMqScvX8Hbh3IU3V2nDUYkY0G0iWnPvev/Cmj8sr/+ FSpt6OA/emUaB6msSx4ajtAqjywQvD94mVBP83s2ZTKucKE/drk8FBNaWag3EVdQpgm2 m/r7F2UoTdJ2+qvznAMTZhsXX2c2FN2OLNKLAWFQ0R7cXkBEra0JJhDR+qZGxk77iokH +e6Wx1ZLOmMMvoNgDwqp1kMvdCKTUiJeGY0C9ayBVGDkknOa/tF68kgEztOQYtj7F5ld X9ZQ== X-Gm-Message-State: AGRZ1gLytuLYjB0fjkH2M9AsGU9t2/DZog4hMK7yTllwv0F2HNJSCt17 G9L05BV4Est+BHpl9elu+abjWg== X-Received: by 2002:a63:4d0e:: with SMTP id a14mr999631pgb.408.1542186470198; Wed, 14 Nov 2018 01:07:50 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.102]) by smtp.gmail.com with ESMTPSA id 127-v6sm25048814pfx.91.2018.11.14.01.07.47 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 14 Nov 2018 01:07:49 -0800 (PST) From: Baolin Wang To: sre@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com Cc: linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, yuanjiang.yu@unisoc.com, baolin.wang@linaro.org, broonie@kernel.org Subject: [PATCH 2/5] power: supply: sc27xx: Add fuel gauge calibration Date: Wed, 14 Nov 2018 17:07:05 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds support to read calibration values from the eFuse controller to calibrate the ADC values corresponding to current and voltage, which can make the current and voltage data more accurate. Signed-off-by: Baolin Wang --- drivers/power/supply/sc27xx_fuel_gauge.c | 62 ++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 11 deletions(-) -- 1.7.9.5 diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index 8613584..66f4db2 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -6,10 +6,12 @@ #include #include #include +#include #include #include #include #include +#include /* PMIC global control registers definition */ #define SC27XX_MODULE_EN0 0xc08 @@ -39,8 +41,6 @@ #define SC27XX_FGU_CLBCNT_MASK GENMASK(15, 0) #define SC27XX_FGU_CLBCNT_SHIFT 16 -#define SC27XX_FGU_1000MV_ADC 686 -#define SC27XX_FGU_1000MA_ADC 1372 #define SC27XX_FGU_CUR_BASIC_ADC 8192 #define SC27XX_FGU_SAMPLE_HZ 2 @@ -59,6 +59,8 @@ * @init_clbcnt: the initial coulomb counter * @max_volt: the maximum constant input voltage in millivolt * @table_len: the capacity table length + * @cur_1000ma_adc: ADC value corresponding to 1000 mA + * @vol_1000mv_adc: ADC value corresponding to 1000 mV * @cap_table: capacity table with corresponding ocv */ struct sc27xx_fgu_data { @@ -76,6 +78,8 @@ struct sc27xx_fgu_data { int init_clbcnt; int max_volt; int table_len; + int cur_1000ma_adc; + int vol_1000mv_adc; struct power_supply_battery_ocv_table *cap_table; }; @@ -86,14 +90,14 @@ struct sc27xx_fgu_data { "sc2723_charger", }; -static int sc27xx_fgu_adc_to_current(int adc) +static int sc27xx_fgu_adc_to_current(struct sc27xx_fgu_data *data, int adc) { - return DIV_ROUND_CLOSEST(adc * 1000, SC27XX_FGU_1000MA_ADC); + return DIV_ROUND_CLOSEST(adc * 1000, data->cur_1000ma_adc); } -static int sc27xx_fgu_adc_to_voltage(int adc) +static int sc27xx_fgu_adc_to_voltage(struct sc27xx_fgu_data *data, int adc) { - return DIV_ROUND_CLOSEST(adc * 1000, SC27XX_FGU_1000MV_ADC); + return DIV_ROUND_CLOSEST(adc * 1000, data->vol_1000mv_adc); } /* @@ -116,7 +120,7 @@ static int sc27xx_fgu_get_boot_capacity(struct sc27xx_fgu_data *data, int *cap) return ret; cur <<= 1; - oci = sc27xx_fgu_adc_to_current(cur - SC27XX_FGU_CUR_BASIC_ADC); + oci = sc27xx_fgu_adc_to_current(data, cur - SC27XX_FGU_CUR_BASIC_ADC); /* * Should get the OCV from SC27XX_FGU_POCV register at the system @@ -127,7 +131,7 @@ static int sc27xx_fgu_get_boot_capacity(struct sc27xx_fgu_data *data, int *cap) if (ret) return ret; - volt = sc27xx_fgu_adc_to_voltage(volt); + volt = sc27xx_fgu_adc_to_voltage(data, volt); ocv = volt * 1000 - oci * data->internal_resist; /* @@ -201,7 +205,7 @@ static int sc27xx_fgu_get_capacity(struct sc27xx_fgu_data *data, int *cap) * as 100 to improve the precision. */ temp = DIV_ROUND_CLOSEST(delta_clbcnt, 360); - temp = sc27xx_fgu_adc_to_current(temp); + temp = sc27xx_fgu_adc_to_current(data, temp); /* * Convert to capacity percent of the battery total capacity, @@ -225,7 +229,7 @@ static int sc27xx_fgu_get_vbat_vol(struct sc27xx_fgu_data *data, int *val) * It is ADC values reading from registers which need to convert to * corresponding voltage values. */ - *val = sc27xx_fgu_adc_to_voltage(vol); + *val = sc27xx_fgu_adc_to_voltage(data, vol); return 0; } @@ -242,7 +246,7 @@ static int sc27xx_fgu_get_current(struct sc27xx_fgu_data *data, int *val) * It is ADC values reading from registers which need to convert to * corresponding current values. */ - *val = sc27xx_fgu_adc_to_current(cur - SC27XX_FGU_CUR_BASIC_ADC); + *val = sc27xx_fgu_adc_to_current(data, cur - SC27XX_FGU_CUR_BASIC_ADC); return 0; } @@ -469,6 +473,38 @@ static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity) return DIV_ROUND_CLOSEST(cur_cap * 36, 10); } +static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data) +{ + struct nvmem_cell *cell; + int calib_data, cal_4200mv; + void *buf; + size_t len; + + cell = nvmem_cell_get(data->dev, "fgu_calib"); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + buf = nvmem_cell_read(cell, &len); + nvmem_cell_put(cell); + + if (IS_ERR(buf)) + return PTR_ERR(buf); + + memcpy(&calib_data, buf, min(len, sizeof(u32))); + + /* + * Get the ADC value corresponding to 4200 mV from eFuse controller + * according to below formula. Then convert to ADC values corresponding + * to 1000 mV and 1000 mA. + */ + cal_4200mv = (calib_data & 0x1ff) + 6963 - 4096 - 256; + data->vol_1000mv_adc = DIV_ROUND_CLOSEST(cal_4200mv * 10, 42); + data->cur_1000ma_adc = data->vol_1000mv_adc * 4; + + kfree(buf); + return 0; +} + static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data) { struct power_supply_battery_info info = { }; @@ -503,6 +539,10 @@ static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data) power_supply_put_battery_info(data->battery, &info); + ret = sc27xx_fgu_calibration(data); + if (ret) + return ret; + /* Enable the FGU module */ ret = regmap_update_bits(data->regmap, SC27XX_MODULE_EN0, SC27XX_FGU_EN, SC27XX_FGU_EN); From patchwork Wed Nov 14 09:07:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 151057 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp5441768ljp; Wed, 14 Nov 2018 01:08:03 -0800 (PST) X-Google-Smtp-Source: AJdET5c+ZO++/4PkBtXeh4fkn4xkyW5AZ5GGQFQfqIMKF1YAlLu1iz/l8R/TrYvMtZ950/HqzSm7 X-Received: by 2002:a17:902:a81:: with SMTP id 1-v6mr1128476plp.20.1542186483671; Wed, 14 Nov 2018 01:08:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542186483; cv=none; d=google.com; s=arc-20160816; b=qzjS3wYHr6HtyDBC43bu0uixvJRnQXixgkjOhk4UB5UPiUn066Mb3ayHQ7vb94xTLK tlVE7nBTupxZK/1uWm3IPnD8BqUCuyysbX3dF0WFCVm8Na9cUiVlplOvpj0hy99rklsj NSYiDCpRZXYelSL37vP3TxCXwMBROMqMWSKb2whAFv6lyYfsAHP1/xM/Wpf7EqW//P1h oDdIu2WzaWcZbMuJooAsqroTlU3a9yAzTJ0wTClH2BrzynjLIx7Pa9aSDnN6H6GXR2OR 8HIT+0Utl/u+vWCpWMrzHAXcAevMDLaUUBSyaHMTyIOSIw747pWSgRwA227Q9zNiimHw IEbw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature; bh=IRUXU/GFwnJl002dQVlSIACjSnNwZF6k9T9koevdIfU=; b=JegjQGLdfNm5qF3a8Y+nTcwfi0RiZQT42rk7Ikmew3/FsJ6HJYhneN2v8kqyKiffjW wlCD3/h3Kn3XNWjYz6ylm3/jdteF6BVYP4jYicbbwkMdCmzsLprxw+7wDczbacHbQfgc eDVuBuhuNfCuFGkwvDtU9n7jU2nQxIl8TxNUhBlDlPSXYsyY8ezVOHM0P323u6CC7Uos k6lHE5vdgdp7V8qpJk/tszb4HtdNGIhmqilJvamlfINzpR48x5XV6B7MGJgatTXPYmG5 Io2ojgQnQ+sAY9PRRynUt5OLnfqQA8pyjTte4JLEn9/I+RXN5LTpZ6gj/1rFIJbrFO5H m2+w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=MgP2KIyE; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 133-v6si23684172pfb.41.2018.11.14.01.08.03; Wed, 14 Nov 2018 01:08:03 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=MgP2KIyE; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732554AbeKNTKX (ORCPT + 32 others); Wed, 14 Nov 2018 14:10:23 -0500 Received: from mail-pg1-f196.google.com ([209.85.215.196]:35575 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727833AbeKNTKW (ORCPT ); Wed, 14 Nov 2018 14:10:22 -0500 Received: by mail-pg1-f196.google.com with SMTP id 32-v6so7081429pgu.2 for ; Wed, 14 Nov 2018 01:08:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=IRUXU/GFwnJl002dQVlSIACjSnNwZF6k9T9koevdIfU=; b=MgP2KIyE/Z5xkWXYph0HjfOigzpkQYVms1EkRMG4ehWPeNBeBF56HsZYWpv/crCUwL vj9Nr1LnZKKUpmBLIYImVHwp0VweT4krV8Jaj8tvmvEcR9zAZ/ZbNHiS4fAZdf90X8tG D1MLf6kMvinSd5hIqHSHPvxJDQ0e4s6RFrWB0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=IRUXU/GFwnJl002dQVlSIACjSnNwZF6k9T9koevdIfU=; b=XsQUZhMCedu3AkQX5ETOR7mbTV7yX3V2y4YOYeHmfOC7VaxkuNIK1eEDnSHYij2m4B jZVl/GvL/IrkGBNVdp7A57h14CvgVOxHTNuqc3M6VgYbf7Kion3WrejYFR83VBltO2cV XVmQP3hhBdnQlVArrsVZNZlyttNiLObOgz8t4PEIlTKCSBU9K2mIxRuibuzffCEiKYht eyv4ZCWfm2mtL6RIHGt4c7pY3XKJh3QlGVpNbMcZRpSjtXjv9DovNFfYTLmcWaZuKpk0 5sGY0OntN0UyXCeucqofG4APDCEg31yFN5vXwJD5+fbqcyagENP8C7Ezx+nnrn5WvCMK J/WQ== X-Gm-Message-State: AGRZ1gIFV4sOJfUv+cCojKe35G+2exi0G5DXE4YPd+mzS9blvd78YeWa E7dJPL4OH+AXXSL2px6owTllKw== X-Received: by 2002:a63:f710:: with SMTP id x16mr1005124pgh.322.1542186480492; Wed, 14 Nov 2018 01:08:00 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.102]) by smtp.gmail.com with ESMTPSA id 127-v6sm25048814pfx.91.2018.11.14.01.07.57 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 14 Nov 2018 01:07:59 -0800 (PST) From: Baolin Wang To: sre@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com Cc: linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, yuanjiang.yu@unisoc.com, baolin.wang@linaro.org, broonie@kernel.org Subject: [PATCH 5/5] power: supply: sc27xx: Save last battery capacity Date: Wed, 14 Nov 2018 17:07:08 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Yuanjiang Yu Our charger manager can optimize the battery capacity periodically, so we can save last battery capacity into registers. Then next system power-on, we can read the last saved battery capacity as the initial battery capacity, which can make the battery capacity more accurate. Signed-off-by: Yuanjiang Yu Signed-off-by: Baolin Wang --- drivers/power/supply/sc27xx_fuel_gauge.c | 143 +++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 1 deletion(-) -- 1.7.9.5 diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index 8c52e29..181a8f7 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -39,6 +39,9 @@ #define SC27XX_FGU_CLBCNT_VALH 0x68 #define SC27XX_FGU_CLBCNT_VALL 0x6c #define SC27XX_FGU_CLBCNT_QMAXL 0x74 +#define SC27XX_FGU_USER_AREA_SET 0xa0 +#define SC27XX_FGU_USER_AREA_CLEAR 0xa4 +#define SC27XX_FGU_USER_AREA_STATUS 0xa8 #define SC27XX_WRITE_SELCLB_EN BIT(0) #define SC27XX_FGU_CLBCNT_MASK GENMASK(15, 0) @@ -49,6 +52,14 @@ #define SC27XX_FGU_LOW_OVERLOAD_INT BIT(0) #define SC27XX_FGU_CLBCNT_DELTA_INT BIT(2) +#define SC27XX_FGU_MODE_AREA_MASK GENMASK(15, 12) +#define SC27XX_FGU_CAP_AREA_MASK GENMASK(11, 0) +#define SC27XX_FGU_MODE_AREA_SHIFT 12 + +#define SC27XX_FGU_FIRST_POWERTON GENMASK(3, 0) +#define SC27XX_FGU_DEFAULT_CAP GENMASK(11, 0) +#define SC27XX_FGU_NORMAIL_POWERTON 0x5 + #define SC27XX_FGU_CUR_BASIC_ADC 8192 #define SC27XX_FGU_SAMPLE_HZ 2 @@ -119,6 +130,80 @@ static int sc27xx_fgu_voltage_to_adc(struct sc27xx_fgu_data *data, int vol) return DIV_ROUND_CLOSEST(vol * data->vol_1000mv_adc, 1000); } +static bool sc27xx_fgu_is_first_poweron(struct sc27xx_fgu_data *data) +{ + int ret, status, cap, mode; + + ret = regmap_read(data->regmap, + data->base + SC27XX_FGU_USER_AREA_STATUS, &status); + if (ret) + return false; + + /* + * We use low 4 bits to save the last battery capacity and high 12 bits + * to save the system boot mode. + */ + mode = (status & SC27XX_FGU_MODE_AREA_MASK) >> SC27XX_FGU_MODE_AREA_SHIFT; + cap = status & SC27XX_FGU_CAP_AREA_MASK; + + /* + * When FGU has been powered down, the user area registers became + * default value (0xffff), which can be used to valid if the system is + * first power on or not. + */ + if (mode == SC27XX_FGU_FIRST_POWERTON || cap == SC27XX_FGU_DEFAULT_CAP) + return true; + + return false; +} + +static int sc27xx_fgu_save_boot_mode(struct sc27xx_fgu_data *data, + int boot_mode) +{ + int ret; + + ret = regmap_update_bits(data->regmap, + data->base + SC27XX_FGU_USER_AREA_CLEAR, + SC27XX_FGU_MODE_AREA_MASK, + SC27XX_FGU_MODE_AREA_MASK); + if (ret) + return ret; + + return regmap_update_bits(data->regmap, + data->base + SC27XX_FGU_USER_AREA_SET, + SC27XX_FGU_MODE_AREA_MASK, + boot_mode << SC27XX_FGU_MODE_AREA_SHIFT); +} + +static int sc27xx_fgu_save_last_cap(struct sc27xx_fgu_data *data, int cap) +{ + int ret; + + ret = regmap_update_bits(data->regmap, + data->base + SC27XX_FGU_USER_AREA_CLEAR, + SC27XX_FGU_CAP_AREA_MASK, + SC27XX_FGU_CAP_AREA_MASK); + if (ret) + return ret; + + return regmap_update_bits(data->regmap, + data->base + SC27XX_FGU_USER_AREA_SET, + SC27XX_FGU_CAP_AREA_MASK, cap); +} + +static int sc27xx_fgu_read_last_cap(struct sc27xx_fgu_data *data, int *cap) +{ + int ret, value; + + ret = regmap_read(data->regmap, + data->base + SC27XX_FGU_USER_AREA_STATUS, &value); + if (ret) + return ret; + + *cap = value & SC27XX_FGU_CAP_AREA_MASK; + return 0; +} + /* * When system boots on, we can not read battery capacity from coulomb * registers, since now the coulomb registers are invalid. So we should @@ -128,6 +213,20 @@ static int sc27xx_fgu_voltage_to_adc(struct sc27xx_fgu_data *data, int vol) static int sc27xx_fgu_get_boot_capacity(struct sc27xx_fgu_data *data, int *cap) { int volt, cur, oci, ocv, ret; + bool is_first_poweron = sc27xx_fgu_is_first_poweron(data); + + /* + * If system is not the first power on, we should use the last saved + * battery capacity as the initial battery capacity. Otherwise we should + * re-calculate the initial battery capacity. + */ + if (!is_first_poweron) { + ret = sc27xx_fgu_read_last_cap(data, cap); + if (ret) + return ret; + + return sc27xx_fgu_save_boot_mode(data, SC27XX_FGU_NORMAIL_POWERTON); + } /* * After system booting on, the SC27XX_FGU_CLBCNT_QMAXL register saved @@ -160,7 +259,11 @@ static int sc27xx_fgu_get_boot_capacity(struct sc27xx_fgu_data *data, int *cap) *cap = power_supply_ocv2cap_simple(data->cap_table, data->table_len, ocv); - return 0; + ret = sc27xx_fgu_save_last_cap(data, *cap); + if (ret) + return ret; + + return sc27xx_fgu_save_boot_mode(data, SC27XX_FGU_NORMAIL_POWERTON); } static int sc27xx_fgu_set_clbcnt(struct sc27xx_fgu_data *data, int clbcnt) @@ -418,6 +521,30 @@ static int sc27xx_fgu_get_property(struct power_supply *psy, return ret; } +static int sc27xx_fgu_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy); + int ret; + + mutex_lock(&data->lock); + + switch (psp) { + case POWER_SUPPLY_PROP_CAPACITY: + ret = sc27xx_fgu_save_last_cap(data, val->intval); + if (ret < 0) + dev_err(data->dev, "failed to save battery capacity\n"); + break; + + default: + ret = -EINVAL; + } + + mutex_unlock(&data->lock); + return ret; +} + static void sc27xx_fgu_external_power_changed(struct power_supply *psy) { struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy); @@ -425,6 +552,18 @@ static void sc27xx_fgu_external_power_changed(struct power_supply *psy) power_supply_changed(data->battery); } +static int sc27xx_fgu_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CAPACITY: + return 1; + + default: + return 0; + } +} + static enum power_supply_property sc27xx_fgu_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_HEALTH, @@ -444,7 +583,9 @@ static void sc27xx_fgu_external_power_changed(struct power_supply *psy) .properties = sc27xx_fgu_props, .num_properties = ARRAY_SIZE(sc27xx_fgu_props), .get_property = sc27xx_fgu_get_property, + .set_property = sc27xx_fgu_set_property, .external_power_changed = sc27xx_fgu_external_power_changed, + .property_is_writeable = sc27xx_fgu_property_is_writeable, }; static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap)