From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D04A606A31C for ; Wed, 11 Nov 2026 20:56:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=g3+doyZf; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20260707 header.b=IIR2bKlG DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Unsubscribe-Post:List-Owner; bh=jzg8ST1Z28Ujw49A6NvE71gYUlErZL9PTmIj8NPOPCU=; b=g3+doyZfomSAGV4kdFuBAcGBvF iTynM/87Z/PCgK1zwHpkNkJ2UrPIWRjYu/wD9qPUjqZn5Pk8FJ/BfjHnMVOuyhRDtgGGQtooadjRm VOCyxQJjEqtRribyRikGoW7IDxhAfcbeJNA5yKn1rxwC6TkYzhv/vaSxTOAyJzFCekQQhEDXFEvPh wSU2yJqPkdhps+4+XGLae5Vkx1UXrrdmb/jbwPA+6J5wlvPIc+zVhftezRzqjyoRzhFEceYzJnRg8 JkVucIbyOjOOFwdgDmZcN0Dd21qqe/cMgdFjrCbVrm7wbGgQGPp7QmYnR9UCJR7KgRQUqtCNEJos7 75dXPs2g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.100.1 #2 (Red Hat Linux)) id 1xRFN5-00000007hK1-1Z5O; Wed, 11 Nov 2026 20:56:43 +0000 Received: from mail-oi1-x235.google.com ([2607:f8b0:4864:20::235]) by bombadil.infradead.org with esmtps (Exim 4.100.1 #2 (Red Hat Linux)) id 1xRFN1-00000007hEQ-2a09 for linux-rockchip@lists.infradead.org; Wed, 11 Nov 2026 20:56:41 +0000 Received: by mail-oi1-x235.google.com with SMTP id 5614622812f47-5641f26ce05so1472374b6e.2 for ; Wed, 11 Nov 2026 12:56:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1794430598; x=1795035398; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=4+m68uKNfuhWa97eAxcw0/ilUPWIJI+gM8aeA06x9S8=; b=IIR2bKlGOTK6bMa/3U6UIq9kE4QoSHEwm2BhzPoa0P7WYryklSCxZeiqWdiNsjVpo1 JqSexKBUUr/7cXfmIXHr1sDeTIvoD9jlrr67Kfj+lvA1Cnz5cx5RAHAMS3YzxZrhoA7m 4se6y5cGNPVKmAPK6N/entFu+EXRCpqwWmLxufv84PI3c6p2S9UlU0oAvO1o6mJNEwwf 0sKPXhu7BtYfGVePqtejhuJFS1kZg0pj1YDhXyR4hOl3RUdyoIMgbFraYjCUEjoKeb/Q GEH439Y43kluh5kQ1XxECoh1St824XrxAE9rfrnW84KBwFiQRWAO7oImN04XvUamYSrY oAdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794430598; x=1795035398; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=4+m68uKNfuhWa97eAxcw0/ilUPWIJI+gM8aeA06x9S8=; b=Ko2n6IRM6HpEnWpQ6oDPABgzDJO8+wq03HeCBZukOjb3gq09twZ9eMkZ3vSSFEHs7C IozflH3Bxg6ZK4O6UbeHgO463wamaqXNYm0yZZn0Fdm7eNzYz6f5YcSkMmVtWf1RV6bL +i9dvLGVQkGvtbcN23wm3f7kVP7tsHTunICOHugs7tt9mXu56QTJ7HTMyJbwY+iP+IjP 0VSIamjytswHzJ+JAx/cL8rJZhJEJcKrihu4Rwe8zxH25eTyD5NSt53YnaFOyA0RtwCx cl3mJTj/Ug1hU4st1hY8am8T3uNKNnaz3o8jYSgSuAsoyNy05NYWTXP9f+Ir+chhHbhv 8M9Q== X-Gm-Message-State: APuU4Z+7sDOpGHuK+W0ZRKheAiE9hdL14Ck31CUeqdhOiWJYhAPhE/sQ IyN4sxJeNc218yhfhlscnICXcNtDEBvWlnP+vdosVBzTwXGEos5XvfUURqlaVPGq X-Gm-Gg: AYBFou1kyAzhg0pWdu9l8qBBJE82fcWqWoKrCz6MbY+pjjBXnRhxdl7pt7z3fK5B3uI ueEQktpa6qac73iUkxPR3BgJ+MUgFaDS9Y6+c1MAnbcCEJzaPhVuk7mtakhapiUYAwsSaHGxvgB NpFePyxvW9fjVBjFmPYlULDP0MMuIqn2R1o/DdAgwbbxh1HMTa0xMWcYpRPrN+X1GPcm5ttpjgA JNrORoNDFM8HRo18LX+Q9uoeznS3rVxh7A+wGwmH2ZLnZh5mZpLWju6UaKOgq++1m4tFfUdK4uk ZmtrTuxvm18NfrmgJ9BD07jyviMwsDFqePXlZ6pV2m3ax3QmpFYopkP9aTa2ZCJoHWWkNJJfGgo LcqmqIL+LV7XPaYHpI+lRUnfFoxBc8Qf3Lc3GSICsThP+Mrm9vkehH0Wo5Qv337OOFIK+pqXzjT Thw35w2YkchknUaw175D2TK5cxZPGxyNhZ5RFAQ6plcnuhyTUh/jNpLykToA1HXo+1C98WiU9/X 9P47oB+Uxftv8REMQWkO8qVhJvg2KdPJ9NYBksyYzm4kww50kbs2aS9UShGtlIe+jVfuVQb6gL0 jF5kjEm5gemKKEDFx6DodEfY4G6b1g== X-Received: by 2002:a05:6808:152b:b0:4f4:be18:5de2 with SMTP id 5614622812f47-56b95163ef6mr2878480b6e.13.1794430595238; Wed, 11 Nov 2026 12:56:35 -0800 (PST) Received: from neuromancer ([75.28.21.198]) by smtp.gmail.com with ESMTPSA id 5614622812f47-56906036028sm6564231b6e.11.2026.11.11.12.56.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Nov 2026 12:56:34 -0800 (PST) From: Chris Morgan To: linux-rockchip@lists.infradead.org Cc: mfd@lists.linux.dev, linux-pm@vger.kernel.org, maccraft123mc@gmail.com, heiko@sntech.de, lee@kernel.org, sre@kernel.org, Chris Morgan , Jacob Cook Subject: [PATCH V4 4/7] power: supply: rk817-charger: Resolve boot state of charge from coulomb counter Date: Wed, 11 Nov 2026 14:56:24 -0600 Message-ID: <20261111205627.56652-5-macroalpha82@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261111205627.56652-1-macroalpha82@gmail.com> References: <20261111205627.56652-1-macroalpha82@gmail.com> X-Archived-By: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20261111_125639_743668_AC8F75FB X-CRM114-Status: GOOD ( 38.73 ) X-Spam-Score: -1.9 (-) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "Linux-rockchip" X-Spam-Status: No, score=-13.8 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE, SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=4.0.1 X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on aws-us-west-2-korg-listserv-alma10-1 From: Chris Morgan The boot state of charge comes from PWRON_VOL when OFF_CNT reads three or more and from the coulomb counter otherwise, and both fail in the field. PWRON_VOL is sampled at the power-on instant. A power-on caused by plugging in a charger samples under charge current: on an RG353M it read above the pack's maximum design voltage while the pack was at 74%. An RG DS was seen holding 2.63V in the register while running. Either becomes a wrong percentage on every boot that reaches it. A negative counter was clamped to zero and reported as 0%. The counter itself keeps counting while the system is off: the same RG353M, saved at 74% and charged for 1.5 hours powered off, booted with the counter at full. The BSP driver relies on this: it reads OFF_CNT into a flag it never uses, consults PWRON_VOL only when BAT_CON marks a new battery, and adopts the counter when it diverges from the saved capacity ("system halt last time"). Keep the PWRON_VOL lookup for the first boot, but "guess" the SoC on boot based on available signals such as the stored NVRAM value, the state of charge from the battery voltage (which would be high if charging, or low if discharging, but based on testing within about 10% of the actual value), and the value reported by the gauge. Then, periodically read the OCV value reported when it is available and use that to adjust the gauge if it differs too much from what the OCV says the state of charge should be. This combined with calibrating to full when the battery stops charging while plugged in should give us a better way to report an accurate value of the battery's SOC. Log the counter, saved soc and battery voltage at boot, as the BSP logs its saved and present capacity, so a counter that diverged from the saved soc is visible. Report it when debugging is enabled so as to not spam the dmesg log otherwise. Fixes: 11cb8da0189b ("power: supply: Add charger driver for Rockchip RK817") Co-developed-by: Jacob Cook Signed-off-by: Jacob Cook Signed-off-by: Chris Morgan Acked-by: Lee Jones --- drivers/power/supply/rk817_charger.c | 262 +++++++++++++++++++++------ include/linux/mfd/rk808.h | 2 + 2 files changed, 211 insertions(+), 53 deletions(-) diff --git a/drivers/power/supply/rk817_charger.c b/drivers/power/supply/rk817_charger.c index 939d4fefff14..5b53cf288fcf 100644 --- a/drivers/power/supply/rk817_charger.c +++ b/drivers/power/supply/rk817_charger.c @@ -95,6 +95,15 @@ struct rk817_charger { int bat_voltage_min_design_uv; int bat_voltage_max_design_uv; + /* Battery voltage the PMIC sampled when the system powered on. */ + int boot_voltage_uv; + + /* Rested voltage the gauge latched, 0 if it took no usable pair. */ + int relax_voltage_uv; + + /* Retained for the ocv-capacity table the recalibration needs. */ + struct power_supply_battery_info *bat_info; + /* Values updated periodically by driver for display. */ int charge_now_uah; int volt_avg_uv; @@ -337,6 +346,59 @@ static int rk817_bat_calib_cap(struct rk817_charger *charger) return 0; } +/* + * Calibrated microvolts from one of the gas gauge's 16 bit voltage registers. + * Return voltage (which should never be negative) on success or error (which + * should always be negative) on failure. + */ +static int rk817_bat_voltage_uv(struct rk817_charger *charger, unsigned int reg) +{ + u8 bulk_reg[2]; + int ret; + + ret = regmap_bulk_read(charger->rk808->regmap, reg, bulk_reg, 2); + if (ret) + return ret; + + return (charger->voltage_k * get_unaligned_be16(bulk_reg)) + + 1000 * charger->voltage_b; +} + +/* + * Voltage the gauge latched while the battery was resting. Relax mode only + * samples below RELAX_THRE_CUR, so this is a true open circuit voltage with + * no resistance term. Returns 0 unless the battery is resting now and the + * latched pair is inside the pack's design range. + */ +static int rk817_bat_relax_voltage_uv(struct rk817_charger *charger) +{ + unsigned int need = RK817_RELAX_STS | RK817_RELAX_VOL_UPD; + int relax1_uv, relax2_uv, ret, sts, vol; + + ret = regmap_read(charger->rk808->regmap, RK817_GAS_GAUGE_GG_STS, &sts); + if (ret < 0 || (sts & need) != need) + return 0; + + /* + * If we can't get a read on both values, return 0 instead of + * a valid voltage and report it as a missing OCV value downstream. + */ + relax1_uv = rk817_bat_voltage_uv(charger, RK817_GAS_GAUGE_RELAX_VOL1_H); + if (relax1_uv < 0) + return 0; + relax2_uv = rk817_bat_voltage_uv(charger, RK817_GAS_GAUGE_RELAX_VOL2_H); + if (relax2_uv < 0) + return 0; + + vol = max(relax1_uv, relax2_uv); + + if (vol < charger->bat_voltage_min_design_uv || + vol > charger->bat_voltage_max_design_uv) + return 0; + + return vol; +} + static void rk817_read_props(struct rk817_charger *charger) { int tmp, reg; @@ -372,11 +434,9 @@ static void rk817_read_props(struct rk817_charger *charger) charger->soc = charger->charge_now_uah * 100 / charger->fcc_mah; /* Update reported voltage. */ - regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_VOL_H, - bulk_reg, 2); - tmp = get_unaligned_be16(bulk_reg); - charger->volt_avg_uv = (charger->voltage_k * tmp) + 1000 * - charger->voltage_b; + tmp = rk817_bat_voltage_uv(charger, RK817_GAS_GAUGE_BAT_VOL_H); + if (tmp > 0) + charger->volt_avg_uv = tmp; /* * Update reported current. Note value from registers is a signed 16 @@ -435,6 +495,8 @@ static void rk817_read_props(struct rk817_charger *charger) charger->charger_input_volt_avg_uv = 0; } + charger->relax_voltage_uv = rk817_bat_relax_voltage_uv(charger); + /* Calibrate battery capacity and soc. */ rk817_bat_calib_cap(charger); } @@ -751,15 +813,88 @@ static int rk817_read_battery_nvram_values(struct rk817_charger *charger) return 0; } +/* + * The relax pair is a true rested voltage: where it disagrees with the + * tracked soc by more than 5% (chosen arbitrarily), re-init the counter + * from it. + */ +static void rk817_bat_ocv_recalibrate(struct rk817_charger *charger) +{ + int ocv_soc; + + if (!charger->battery_present) + return; + + if (!charger->relax_voltage_uv) + return; + + ocv_soc = power_supply_batinfo_ocv2cap(charger->bat_info, + charger->relax_voltage_uv, + 20) * 1000; + if (ocv_soc < 0 || abs(ocv_soc - charger->soc) <= 5000) + return; + + dev_dbg(charger->dev, + "OCV %duV disagrees with soc, recalibrating (%d -> %d)\n", + charger->relax_voltage_uv, charger->soc, ocv_soc); + charger->soc = ocv_soc; + rk817_initialize_coulomb_counter(charger, + (ocv_soc * charger->fcc_mah) / 100000); + rk817_record_battery_nvram_values(charger); +} + +/* + * Since we cannot perfectly control the bootloader, we cannot trust the + * POWERON_VOL value. Instead, we have to guess with what we have available; + * the state of charge saved to NVRAM, the SoC reported by the gauge, and + * a lookup of the battery voltage against the OCV table. None of these will + * give us a true value of the state of charge, but it should ensure what we + * report to userspace is "slightly correct" until we can get an OCV value or + * we hit the charge_term_current_ua where we can stop guessing. If we have + * only the NVRAM value and the SoC from the gauge, use the NVRAM value if + * it's within 10% of the gauge SoC, otherwise use the gauge SoC. If we have + * all 3 values, sort them and keep the middle value. Then, drop the first + * or 3rd value (whichever is further away) and average the remaining 2 values. + */ +static int rk817_select_boot_soc(struct rk817_charger *charger, int gauge_soc, + int table_soc, int nvram_soc) +{ + int soc[3]; + + if (table_soc < 0) { + if (abs(gauge_soc - nvram_soc) >= 10000) + return gauge_soc; + return nvram_soc; + } + + /* Sort the values so we can drop the outlier */ + soc[0] = gauge_soc; + soc[1] = table_soc; + soc[2] = nvram_soc; + + if (soc[0] > soc[1]) + swap(soc[0], soc[1]); + if (soc[1] > soc[2]) + swap(soc[1], soc[2]); + if (soc[0] > soc[1]) + swap(soc[0], soc[1]); + + /* Drop whichever end is further from the middle and average the rest. */ + if (soc[1] - soc[0] > soc[2] - soc[1]) + return (soc[1] + soc[2]) / 2; + + return (soc[0] + soc[1]) / 2; +} + static int rk817_read_or_set_full_charge_on_boot(struct rk817_charger *charger, struct power_supply_battery_info *bat_info) { + int ret, reg, tmp, off_cnt, bat_uv, boot_soc, table_soc; struct rk808 *rk808 = charger->rk808; - u8 bulk_reg[4]; - u32 boot_voltage, boot_charge_mah; - int ret, reg, off_time, tmp; + u32 boot_charge_mah; bool first_boot; + u8 bulk_reg[4]; /* * Check if the battery is uninitalized. If it is, the coulomb counter @@ -769,25 +904,23 @@ rk817_read_or_set_full_charge_on_boot(struct rk817_charger *charger, if (ret < 0) return ret; first_boot = reg & RK817_BAT_CON; - /* - * If the battery is uninitialized, use the poweron voltage and an ocv - * lookup to guess our charge. The number won't be very accurate until - * we hit either our minimum voltage (0%) or full charge (100%). - */ + + /* PWRON_VOL only refreshes on a real power-on; bound it to the pack. */ + tmp = rk817_bat_voltage_uv(charger, RK817_GAS_GAUGE_PWRON_VOL_H); + if (tmp < 0) + return tmp; + charger->boot_voltage_uv = clamp(tmp, bat_info->voltage_min_design_uv, + bat_info->voltage_max_design_uv); + if (first_boot) { - regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_PWRON_VOL_H, - bulk_reg, 2); - tmp = get_unaligned_be16(bulk_reg); - boot_voltage = (charger->voltage_k * tmp) + - 1000 * charger->voltage_b; /* - * Since only implementation has no working thermistor, assume - * 20C for OCV lookup. If lookup fails, report error with OCV - * table. + * Nothing has been saved yet, so estimate from the boot + * voltage with an ocv lookup. Since only implementation has + * no working thermistor, assume 20C for that lookup. */ charger->soc = power_supply_batinfo_ocv2cap(bat_info, - boot_voltage, - 20) * 1000; + charger->boot_voltage_uv, + 20) * 1000; if (charger->soc < 0) charger->soc = 0; @@ -808,39 +941,47 @@ rk817_read_or_set_full_charge_on_boot(struct rk817_charger *charger, if (ret < 0) return ret; + /* + * The coulomb counter keeps counting while the system is off, + * so take it, capped at full, unless it reads invalid; the + * saved soc is then at most one update interval old. A counter + * that is merely wrong is corrected by the next rested relax + * pair. + */ regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3, bulk_reg, 4); tmp = get_unaligned_be32(bulk_reg); - if (tmp < 0) - tmp = 0; - boot_charge_mah = ADC_TO_CHARGE_UAH(tmp, - charger->res_div) / 1000; - /* - * Check if the coulomb counter has been off for more than 30 - * minutes as it tends to drift downward. If so, re-init soc - * with the boot voltage instead. Note the unit values for the - * OFF_CNT register appear to be in decaminutes and stops - * counting at 2550 (0xFF) minutes. BSP kernel used OCV, but - * for me occasionally that would show invalid values. Boot - * voltage is only accurate for me on first poweron (not - * reboots), but we shouldn't ever encounter an OFF_CNT more - * than 0 on a reboot anyway. - */ - regmap_read(rk808->regmap, RK817_GAS_GAUGE_OFF_CNT, &off_time); - if (off_time >= 3) { - regmap_bulk_read(rk808->regmap, - RK817_GAS_GAUGE_PWRON_VOL_H, - bulk_reg, 2); - tmp = get_unaligned_be16(bulk_reg); - boot_voltage = (charger->voltage_k * tmp) + - 1000 * charger->voltage_b; - charger->soc = - power_supply_batinfo_ocv2cap(bat_info, - boot_voltage, - 20) * 1000; + regmap_read(rk808->regmap, RK817_GAS_GAUGE_OFF_CNT, &off_cnt); + bat_uv = rk817_bat_voltage_uv(charger, RK817_GAS_GAUGE_BAT_VOL_H); + if (bat_uv < 0) + return bat_uv; + dev_dbg(charger->dev, + "boot: counter %d uAh, saved soc %d, fcc %d mAh, battery %d uV, off_cnt %d\n", + tmp > 0 ? ADC_TO_CHARGE_UAH(tmp, charger->res_div) : 0, + charger->soc, charger->fcc_mah, bat_uv, off_cnt); + if (tmp > 0) { + boot_charge_mah = ADC_TO_CHARGE_UAH(tmp, + charger->res_div) / 1000; + if (boot_charge_mah > charger->fcc_mah) + boot_charge_mah = charger->fcc_mah; + boot_soc = boot_charge_mah * 100000 / charger->fcc_mah; + + /* + * The gauge re-derives this count from its own ocv + * model while the pack rests, so bound it with the ocv + * table: under load the terminal voltage sits below the + * open circuit voltage, making the table a floor, and + * under charge above it, making it a ceiling on any + * saved soc that would displace the counter. + */ + table_soc = power_supply_batinfo_ocv2cap(bat_info, bat_uv, + 20) * 1000; + + charger->soc = rk817_select_boot_soc(charger, boot_soc, + table_soc, charger->soc); } else { - charger->soc = (boot_charge_mah * 1000 * 100 / - charger->fcc_mah); + dev_dbg(charger->dev, + "coulomb counter invalid, keeping saved soc\n"); } } @@ -1046,6 +1187,7 @@ static void rk817_charging_monitor(struct work_struct *work) charger = container_of(work, struct rk817_charger, work.work); rk817_read_props(charger); + rk817_bat_ocv_recalibrate(charger); /* Run every 8 seconds like the BSP driver did. */ queue_delayed_work(system_percpu_wq, &charger->work, msecs_to_jiffies(8000)); @@ -1058,6 +1200,13 @@ static void rk817_cleanup_node(void *data) of_node_put(node); } +static void rk817_put_battery_info(void *data) +{ + struct rk817_charger *charger = data; + + power_supply_put_battery_info(charger->bat_ps, charger->bat_info); +} + static int rk817_charger_probe(struct platform_device *pdev) { struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent); @@ -1174,7 +1323,14 @@ static int rk817_charger_probe(struct platform_device *pdev) if (ret) return ret; - power_supply_put_battery_info(charger->bat_ps, bat_info); + /* + * Keep the battery info: the periodic recalibration needs its + * ocv-capacity table for as long as the driver is bound. + */ + charger->bat_info = bat_info; + ret = devm_add_action_or_reset(dev, rk817_put_battery_info, charger); + if (ret) + return ret; plugin_irq = platform_get_irq(pdev, 0); if (plugin_irq < 0) diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 7ffc904c864c..72419d311626 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -1211,6 +1211,8 @@ enum rk809_reg_id { #define RK817_GAS_GAUGE_RELAX_THRE_H 0x58 #define RK817_GAS_GAUGE_RELAX_THRE_L 0x59 +#define RK817_GAS_GAUGE_RELAX_VOL1_H 0x5a +#define RK817_GAS_GAUGE_RELAX_VOL2_H 0x5c #define RK817_GAS_GAUGE_OCV_THRE_VOL 0x62 #define RK817_GAS_GAUGE_OCV_VOL_H 0x63 #define RK817_GAS_GAUGE_OCV_VOL_L 0x64 -- 2.53.0 _______________________________________________ Linux-rockchip mailing list Linux-rockchip@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-rockchip