aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Weißschuh <linux@weissschuh.net>2024-12-08 15:59:28 +0100
committerSebastian Reichel <sebastian.reichel@collabora.com>2024-12-10 02:51:45 +0100
commitc28dc9fc24f5fa802d44ef7620a511035bdd803e (patch)
tree64ae16360ba992b9966d0a3b04d44e4f442e5c03
parente65a1b7fad0e112573eea7d64d4ab4fc513b8695 (diff)
downloadlinux-c28dc9fc24f5fa802d44ef7620a511035bdd803e.tar.gz
linux-c28dc9fc24f5fa802d44ef7620a511035bdd803e.tar.bz2
linux-c28dc9fc24f5fa802d44ef7620a511035bdd803e.zip
power: supply: cros_charge-control: hide start threshold on v2 cmd
ECs implementing the v2 command will not stop charging when the end threshold is reached. Instead they will begin discharging until the start threshold is reached, leading to permanent charge and discharge cycles. This defeats the point of the charge control mechanism. Avoid the issue by hiding the start threshold on v2 systems. Instead on those systems program the EC with start == end which forces the EC to reach and stay at that level. v1 does not support thresholds and v3 works correctly, at least judging from the code. Reported-by: Thomas Koch <linrunner@gmx.net> Fixes: c6ed48ef5259 ("power: supply: add ChromeOS EC based charge control driver") Cc: stable@vger.kernel.org Signed-off-by: Thomas Weißschuh <linux@weissschuh.net> Link: https://lore.kernel.org/r/20241208-cros_charge-control-v2-v1-3-8d168d0f08a3@weissschuh.net Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
-rw-r--r--drivers/power/supply/cros_charge-control.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/power/supply/cros_charge-control.c b/drivers/power/supply/cros_charge-control.c
index 108b121db442..9b0a7500296b 100644
--- a/drivers/power/supply/cros_charge-control.c
+++ b/drivers/power/supply/cros_charge-control.c
@@ -139,6 +139,10 @@ static ssize_t cros_chctl_store_threshold(struct device *dev, struct cros_chctl_
return -EINVAL;
if (is_end_threshold) {
+ /* Start threshold is not exposed, use fixed value */
+ if (priv->cmd_version == 2)
+ priv->current_start_threshold = val == 100 ? 0 : val;
+
if (val < priv->current_start_threshold)
return -EINVAL;
priv->current_end_threshold = val;
@@ -234,12 +238,10 @@ static umode_t cros_chtl_attr_is_visible(struct kobject *kobj, struct attribute
{
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(attr, n);
- if (priv->cmd_version < 2) {
- if (n == CROS_CHCTL_ATTR_START_THRESHOLD)
- return 0;
- if (n == CROS_CHCTL_ATTR_END_THRESHOLD)
- return 0;
- }
+ if (n == CROS_CHCTL_ATTR_START_THRESHOLD && priv->cmd_version < 3)
+ return 0;
+ else if (n == CROS_CHCTL_ATTR_END_THRESHOLD && priv->cmd_version < 2)
+ return 0;
return attr->mode;
}