From patchwork Wed Jul 31 10:00:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 170132 Delivered-To: patch@linaro.org Received: by 2002:a92:512:0:0:0:0:0 with SMTP id q18csp3802733ile; Wed, 31 Jul 2019 03:01:00 -0700 (PDT) X-Google-Smtp-Source: APXvYqzWQ3mw96KsxuMjGzDp0sZ5pEiuHuMhB/jzNoH1qa7a1OkBlSzgdPNeZf5cWBXkoPSpQeKq X-Received: by 2002:a17:902:145:: with SMTP id 63mr123237104plb.55.1564567260670; Wed, 31 Jul 2019 03:01:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564567260; cv=none; d=google.com; s=arc-20160816; b=CLCLb4eYu/FXpIf66id1oQYKte0ND7BF0896tUUnHwMGiiI6K7Ia3M3we7O6RgcLXc J3GDAI8L7vhpNmFkC4a6/VvmZG6F5dYtNWVEqm5rhRtNxbubiGJClyPKfQkxawpTIUyB 3auc5miOYP19qtoctX/sh4a23hEMMrMlEE6Rn50Vgl6kKRmQb34WkCEt6CAqFXx/B2yM hEdVWcFWQXz5ibk7KjUBXyYVgKIagaOmlRr3bapueci973qTcNXFgN6UdOOj56m4MpeA 2k3K2Pv7Z5YHXS8UxJ6fu3wLPxtdpRSsflhM96g2jlOk8dhH0qlGriZhJcZfv31qf77G kKug== 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=vuwg/qLthBT40Ca2xrbvcRHyZdgOFkkkM28IonKKxd4=; b=lx2Q4EzWFSEB+3MzQIYVMr5pCKoJFEF2TI15dBDdxV2W3OCBi8tyL4/ae/gCAN74XL 3w9GylSZaDuLmRSJBJG4OeCkz1NtETRGOrj2/oDgL6tPfW52j4mQdGIUEYsyGCUervQ5 nSU9LaR29gGza+2Uqr49W3ZcqOeEPSAdB/llQT5T03jxs9NMRrlsYDKmjXjn2HA5nrf3 YO/3aG9Tp5VimvnBuau7wdM49xlIcNccJSWFthC/0qGxtqsNkZ1nefFspw1PPuy8CBJb FZTiLnOF08eX9+2tHwJpc89KFDuZebyqk5JRpZscn3k+EnrFEZQ9zv2W/LAWKl2D5Q/p lgQQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BGrk88fa; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 h3si32613928pld.32.2019.07.31.03.01.00; Wed, 31 Jul 2019 03:01:00 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-pm-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=BGrk88fa; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 S2387668AbfGaKA7 (ORCPT + 11 others); Wed, 31 Jul 2019 06:00:59 -0400 Received: from mail-pg1-f194.google.com ([209.85.215.194]:40824 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387681AbfGaKA6 (ORCPT ); Wed, 31 Jul 2019 06:00:58 -0400 Received: by mail-pg1-f194.google.com with SMTP id w10so31724522pgj.7 for ; Wed, 31 Jul 2019 03:00:58 -0700 (PDT) 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=vuwg/qLthBT40Ca2xrbvcRHyZdgOFkkkM28IonKKxd4=; b=BGrk88fawYJnzHlTqSp6jAcbVl4MvCckvfC8RgMr9Iq0piEiaZ2vyikaRxDhM9fLSn xlRwXhOZymwnuqLXEXZCVXGakJTqcBwfe9pSQxJQs9tFf3b/btbIEU6bWd7a22pHa1FX XnbKJaf5d6QeBvS6a2hJi6b7eYrlKLuT+vR5nw85UjKNJF5NAg2AvIgaN0qfUq9KW+H1 D+86lngDkbCc9sND22axjQyz0lGSDKqA/KvdbbGuRQLdSkH2iJCYhFVAMrLM5vvqeIaY 1uy4NRxiurckC0uiTQF7DYa0lIdvjQPzWAUMdCLG6DdM+/QmJSMk4+8tPDCW8GLhIrqw JCAw== 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=vuwg/qLthBT40Ca2xrbvcRHyZdgOFkkkM28IonKKxd4=; b=pNKGKu2hcGuDDX/YWo04sgAmLbIuOGllHxrtUkK53bcek9kNO10EW/YWRd73H1SebW 9rckvkX/8hA0H0Cmh7GEApaIe+8xWrx/QdQvPC5L+STq9yeotqXZ0pqtHZgbugxLk37R 7iNeiBblks75HN5yglzWHDXnY1UxD2SmTrrCgGfb9PA6zyK1oKhh2oguTOyszcZni+ot VTtVyD4twt2Dm+uYwdnFxaOQNdPTLpgNHPt1pjDV2mse73m6fuMsYfDnk0sqnpMEqA8J o51QoRrKp1drzDIjhHYnoM9MAUmaUgQtItuVtTbumS9go5a325PwnK90buGXDBFCY03P 5bhQ== X-Gm-Message-State: APjAAAUhnOtvbMdjZyGii+7IgeaynAaNOrD/tk9kzb2rHieQeqCn9yxv laNh7fboUatiI6sZeBBBm3Nm0A== X-Received: by 2002:a63:ee08:: with SMTP id e8mr59564051pgi.70.1564567258256; Wed, 31 Jul 2019 03:00:58 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id m6sm68611352pfb.151.2019.07.31.03.00.56 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 31 Jul 2019 03:00:57 -0700 (PDT) From: Baolin Wang To: sre@kernel.org Cc: orsonzhai@gmail.com, zhang.lyra@gmail.com, yuanjiang.yu@unisoc.com, baolin.wang@linaro.org, vincent.guittot@linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/6] power: supply: sc27xx: Fix the the accuracy issue of coulomb calculation Date: Wed, 31 Jul 2019 18:00:25 +0800 Message-Id: <0e86ed1f992d2eb99fd4abb9e0c51ca2c4ccd4eb.1564566425.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Yuanjiang Yu The Spreadtrum fuel gauge will multiply by 2 for counting the coulomb counter to improve the accuracy, which means the value saved in fuel gauge is: coulomb counter * 2 * 1000ma_adc. Thus fix the conversion formular to improve the accuracy of calculating the battery capacity. Signed-off-by: Yuanjiang Yu Signed-off-by: Baolin Wang --- drivers/power/supply/sc27xx_fuel_gauge.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) -- 1.7.9.5 diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index ca7b73e..ab3afa1 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -326,8 +326,6 @@ static int sc27xx_fgu_set_clbcnt(struct sc27xx_fgu_data *data, int clbcnt) { int ret; - clbcnt *= SC27XX_FGU_SAMPLE_HZ; - ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_CLBCNT_SETL, SC27XX_FGU_CLBCNT_MASK, clbcnt); @@ -362,7 +360,6 @@ static int sc27xx_fgu_get_clbcnt(struct sc27xx_fgu_data *data, int *clb_cnt) *clb_cnt = ccl & SC27XX_FGU_CLBCNT_MASK; *clb_cnt |= (cch & SC27XX_FGU_CLBCNT_MASK) << SC27XX_FGU_CLBCNT_SHIFT; - *clb_cnt /= SC27XX_FGU_SAMPLE_HZ; return 0; } @@ -380,10 +377,10 @@ static int sc27xx_fgu_get_capacity(struct sc27xx_fgu_data *data, int *cap) /* * Convert coulomb counter to delta capacity (mAh), and set multiplier - * as 100 to improve the precision. + * as 10 to improve the precision. */ - temp = DIV_ROUND_CLOSEST(delta_clbcnt, 360); - temp = sc27xx_fgu_adc_to_current(data, temp); + temp = DIV_ROUND_CLOSEST(delta_clbcnt * 10, 36 * SC27XX_FGU_SAMPLE_HZ); + temp = sc27xx_fgu_adc_to_current(data, temp / 1000); /* * Convert to capacity percent of the battery total capacity, @@ -790,7 +787,7 @@ static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity) * Convert current capacity (mAh) to coulomb counter according to the * formula: 1 mAh =3.6 coulomb. */ - return DIV_ROUND_CLOSEST(cur_cap * 36 * data->cur_1000ma_adc, 10); + return DIV_ROUND_CLOSEST(cur_cap * 36 * data->cur_1000ma_adc * SC27XX_FGU_SAMPLE_HZ, 10); } static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data) From patchwork Wed Jul 31 10:00:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 170133 Delivered-To: patch@linaro.org Received: by 2002:a92:512:0:0:0:0:0 with SMTP id q18csp3802817ile; Wed, 31 Jul 2019 03:01:03 -0700 (PDT) X-Google-Smtp-Source: APXvYqz+6PinPBDXz7B79eG9s6HE1l+BmqZUwhBPhmdQCnMYicWjbp4zId9PFjAxQoYaeHHh83iJ X-Received: by 2002:a17:902:fe93:: with SMTP id x19mr110955938plm.77.1564567263332; Wed, 31 Jul 2019 03:01:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564567263; cv=none; d=google.com; s=arc-20160816; b=ScUjJ4XtnXQ4eOlmS4n1WZpFnCJSVlOn/jBrDkW0r5v2NpT/7Nfe7wbQZ3DYJhe+Wo 0Vmfll+TnxYSCfeM8V3Qc0A7kte0R8bN1ivUs9ZSe/M3CW43GeTFG+l/kAyJKMI/Vq1g N69ud72DOpYZPIRjYCAQpN6TjxrAOgw170qQzTTFlj3rAlwOTYkjmnwq43DlekvWDuak iYiAfS9UhP1AesYXrcSt6S/S9wi3vIiWXD9MvLQL3ByagJzPUoCWDc6E6Qr5quPaj+jI 7UjyEsFw3I+nkf8hOXGKjdICIHNypkxxEMDpz5qEFHtol8JZTCoyPEqCzzXodI8rHDH3 p9fw== 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=lzudkxND7QXBPzukVZ8caM1zSAxHaq1C/uuuYUCx2po=; b=teZfTNBonLF5NUagM8VyfRQZNj0VN42bZEaBUx0+ZvbjkB+uLmHDRBKb1VDIGx7pqp WQ1PjEOXsgFjGmlO0BzN7SaJ8au73i2tX0nTPVVUxG+ilAByoqg50cngDwCQCbphZpft w9pKQlb6dJRvmN0sfGXYAe9D9rj3BukhcnITxNKd8vIV/Gl4Cp5aNCirQWQaMazd6zEn O/Vkm0bKyB+9B34v5uUI/2MZbfpN2g3S4djz1qDU6Gj7nWJfgGPizZAczinYTZMd1s4S yCVZ5EH7mrsLcr9TGqCkrLYp72V918YBBSrJ40AjfpA20WCLNYStsIIXsGF2q8cPgxpr iJXg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JYv4Dfa5; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 h3si32613928pld.32.2019.07.31.03.01.03; Wed, 31 Jul 2019 03:01:03 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-pm-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=JYv4Dfa5; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 S2387705AbfGaKBB (ORCPT + 11 others); Wed, 31 Jul 2019 06:01:01 -0400 Received: from mail-pl1-f194.google.com ([209.85.214.194]:40405 "EHLO mail-pl1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387692AbfGaKBB (ORCPT ); Wed, 31 Jul 2019 06:01:01 -0400 Received: by mail-pl1-f194.google.com with SMTP id a93so30212267pla.7 for ; Wed, 31 Jul 2019 03:01:01 -0700 (PDT) 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=lzudkxND7QXBPzukVZ8caM1zSAxHaq1C/uuuYUCx2po=; b=JYv4Dfa5hcngN9DoTOGV4efGVdwLlRNapWP8kKxPLBBoo8QqvDyDZqRLCkSwKS1E+I NOX/xhTUok4OWxNDBqrXEDfiTWFgfk2d38fMFffnafAiCMyUQD0o800ed1YjDeoL7HT9 ZTG/w8M9Whi8WhgceM0vjdQ7K/iN5cfK8LxHF7iNXjB0Z3tnrhb2SFGsfEEi6aS4HSY2 wi38XC1RfJl7qJ+C0L3S6BCvibvLQ2CgLYoHC8JNNQwmp47MAY3X8JLS3A+p5MuWlKcB 6Efxk2uOLoWwHEtebA++1wAID8Y+ffRS3dD+hpdxRHr50yUsa2aqEOijbNN/QhwB+vSO 8zfA== 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=lzudkxND7QXBPzukVZ8caM1zSAxHaq1C/uuuYUCx2po=; b=lZXpYZUgNwF210p0yPw1asSsD9b7feF08MqqbiJDD8dnnmGfOPdnnTJKKSCuj/LqUS 6zQbZO6rsXX8EWoEVxsl1jPWCvMhdmx51RUQRecnAa0oE+aD0rRODnlPC6DLJxQdSpDV lYGxYMQP8zkaUdltiWM6PxWxbFOR9Lgs0O1d1P8ycl66/eEkHtkuYyeW/xnA9mCHUHln L1xR1YBn2To3rtATw6UUrYgEpeTyuzNiVf3BDW6Q38jr3RGivc76/0iqqFxBstjcKKZn qbnVFS1qWtuLOsmh9UV0KTaBn6MN/VsbQPL6c5XeeYZfjzBOQxgyGOoJ0uTNQbdfrCy2 yLIw== X-Gm-Message-State: APjAAAWbL6cRM0rGzWD+ZQ5TCGHZX5y/nv83HbWJMkM40K8JfpIBCuFv k4iP/Mw+xhnEmqcfrtiVBN0e0w== X-Received: by 2002:a17:902:2de4:: with SMTP id p91mr88832811plb.28.1564567260751; Wed, 31 Jul 2019 03:01:00 -0700 (PDT) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id m6sm68611352pfb.151.2019.07.31.03.00.58 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 31 Jul 2019 03:01:00 -0700 (PDT) From: Baolin Wang To: sre@kernel.org Cc: orsonzhai@gmail.com, zhang.lyra@gmail.com, yuanjiang.yu@unisoc.com, baolin.wang@linaro.org, vincent.guittot@linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/6] power: supply: sc27xx: Optimize the battery capacity calibration Date: Wed, 31 Jul 2019 18:00:26 +0800 Message-Id: <6d4155a2d95a67546c27b49ba4cd1ab2898cb570.1564566425.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org From: Yuanjiang Yu This patch factors out the capacity calibration into one single function to calibrate the battery capacity, and adding more abnormal cases to calibrate the capacity when the OCV value is not matchable with current capacity. Moreover we also allow to calibrate the capacity when charger magager tries to get current capacity to make sure we give a correct capacity for userspace. Signed-off-by: Yuanjiang Yu Signed-off-by: Baolin Wang --- drivers/power/supply/sc27xx_fuel_gauge.c | 127 ++++++++++++++++++++++-------- 1 file changed, 92 insertions(+), 35 deletions(-) -- 1.7.9.5 diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index ab3afa1..f670131 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -109,6 +109,8 @@ struct sc27xx_fgu_data { }; static int sc27xx_fgu_cap_to_clbcnt(struct sc27xx_fgu_data *data, int capacity); +static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data, + int cap, int int_mode); static const char * const sc27xx_charger_supply_name[] = { "sc2731_charger", @@ -389,6 +391,9 @@ static int sc27xx_fgu_get_capacity(struct sc27xx_fgu_data *data, int *cap) delta_cap = DIV_ROUND_CLOSEST(temp * 100, data->total_cap); *cap = delta_cap + data->init_cap; + /* Calibrate the battery capacity in a normal range. */ + sc27xx_fgu_capacity_calibration(data, *cap, false); + return 0; } @@ -661,50 +666,62 @@ static int sc27xx_fgu_property_is_writeable(struct power_supply *psy, static void sc27xx_fgu_adjust_cap(struct sc27xx_fgu_data *data, int cap) { + int ret; + data->init_cap = cap; - data->init_clbcnt = sc27xx_fgu_cap_to_clbcnt(data, data->init_cap); + ret = sc27xx_fgu_get_clbcnt(data, &data->init_clbcnt); + if (ret) + dev_err(data->dev, "failed to get init coulomb counter\n"); } -static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id) +static void sc27xx_fgu_capacity_calibration(struct sc27xx_fgu_data *data, + int cap, int int_mode) { - struct sc27xx_fgu_data *data = dev_id; - int ret, cap, ocv, adc; - u32 status; - - mutex_lock(&data->lock); + int ret, ocv, chg_sts, adc; - ret = regmap_read(data->regmap, data->base + SC27XX_FGU_INT_STS, - &status); - if (ret) - goto out; + ret = sc27xx_fgu_get_vbat_ocv(data, &ocv); + if (ret) { + dev_err(data->dev, "get battery ocv error.\n"); + return; + } - ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_CLR, - status, status); - if (ret) - goto out; + ret = sc27xx_fgu_get_status(data, &chg_sts); + if (ret) { + dev_err(data->dev, "get charger status error.\n"); + return; + } /* - * When low overload voltage interrupt happens, we should calibrate the - * battery capacity in lower voltage stage. + * If we are in charging mode, then we do not need to calibrate the + * lower capacity. */ - if (!(status & SC27XX_FGU_LOW_OVERLOAD_INT)) - goto out; + if (chg_sts == POWER_SUPPLY_STATUS_CHARGING) + return; - ret = sc27xx_fgu_get_capacity(data, &cap); - if (ret) - goto out; - - ret = sc27xx_fgu_get_vbat_ocv(data, &ocv); - if (ret) - goto out; - - /* - * If current OCV value is less than the minimum OCV value in OCV table, - * which means now battery capacity is 0%, and we should adjust the - * inititial capacity to 0. - */ - if (ocv <= data->cap_table[data->table_len - 1].ocv) { + if ((ocv > data->cap_table[0].ocv && cap < 100) || cap > 100) { + /* + * If current OCV value is larger than the max OCV value in + * OCV table, or the current capacity is larger than 100, + * we should force the inititial capacity to 100. + */ + sc27xx_fgu_adjust_cap(data, 100); + } else if (ocv <= data->cap_table[data->table_len - 1].ocv) { + /* + * If current OCV value is leass than the minimum OCV value in + * OCV table, we should force the inititial capacity to 0. + */ sc27xx_fgu_adjust_cap(data, 0); + } else if ((ocv > data->cap_table[data->table_len - 1].ocv && cap <= 0) || + (ocv > data->min_volt && cap <= data->alarm_cap)) { + /* + * If current OCV value is not matchable with current capacity, + * we should re-calculate current capacity by looking up the + * OCV table. + */ + int cur_cap = power_supply_ocv2cap_simple(data->cap_table, + data->table_len, ocv); + + sc27xx_fgu_adjust_cap(data, cur_cap); } else if (ocv <= data->min_volt) { /* * If current OCV value is less than the low alarm voltage, but @@ -713,7 +730,7 @@ static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id) */ if (cap > data->alarm_cap) { sc27xx_fgu_adjust_cap(data, data->alarm_cap); - } else if (cap <= 0) { + } else { int cur_cap; /* @@ -728,15 +745,55 @@ static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id) sc27xx_fgu_adjust_cap(data, cur_cap); } + if (!int_mode) + return; + /* * After adjusting the battery capacity, we should set the * lowest alarm voltage instead. */ data->min_volt = data->cap_table[data->table_len - 1].ocv; + data->alarm_cap = power_supply_ocv2cap_simple(data->cap_table, + data->table_len, + data->min_volt); + adc = sc27xx_fgu_voltage_to_adc(data, data->min_volt / 1000); - regmap_update_bits(data->regmap, data->base + SC27XX_FGU_LOW_OVERLOAD, + regmap_update_bits(data->regmap, + data->base + SC27XX_FGU_LOW_OVERLOAD, SC27XX_FGU_LOW_OVERLOAD_MASK, adc); } +} + +static irqreturn_t sc27xx_fgu_interrupt(int irq, void *dev_id) +{ + struct sc27xx_fgu_data *data = dev_id; + int ret, cap; + u32 status; + + mutex_lock(&data->lock); + + ret = regmap_read(data->regmap, data->base + SC27XX_FGU_INT_STS, + &status); + if (ret) + goto out; + + ret = regmap_update_bits(data->regmap, data->base + SC27XX_FGU_INT_CLR, + status, status); + if (ret) + goto out; + + /* + * When low overload voltage interrupt happens, we should calibrate the + * battery capacity in lower voltage stage. + */ + if (!(status & SC27XX_FGU_LOW_OVERLOAD_INT)) + goto out; + + ret = sc27xx_fgu_get_capacity(data, &cap); + if (ret) + goto out; + + sc27xx_fgu_capacity_calibration(data, cap, true); out: mutex_unlock(&data->lock);