power: supply: qcom_smbx: add charge_behaviour support

Implement the generic charge_behaviour property with the "auto", "inhibit-charge" and "force-discharge" modes.

"inhibit-charge" clears CHARGING_ENABLE_CMD_BIT, which stops charging the battery while keeping the USB input path active, so the system continues to run from the charger. "force-discharge" additionally sets USBIN_SUSPEND_BIT to suspend the USB input, forcing the system to run from the battery even while a charger is connected. "auto" restores normal firmware-controlled charging.

This lets userspace hold the battery below full on permanently powered devices to reduce calendar aging.

Signed-off-by: Tristan Geiser oss.tristan.geiser@gmail.com


Currently using it with the following script:

#!/bin/sh
BAT=/sys/class/power_supply/bq27411-0
CHG=/sys/class/power_supply/pmi8998-charger
BEHAVIOUR="$CHG/charge_behaviour"
START=50; STOP=60; SHUTDOWN=20; INTERVAL=30
[ -e "$BEHAVIOUR" ] || { echo "charge-limit: patched kernel required"; exit 1; }
get() { sed 's/.*\[\(.*\)\].*/\1/' "$BEHAVIOUR"; }
set_b() { [ "$(get)" = "$1" ] && return 0; echo "$1" > "$BEHAVIOUR" \
  && echo "charge-limit: -> $1 (${cap}%)"; }
low=0
while true; do
  cap=$(cat "$BAT/capacity" 2>/dev/null); [ -z "$cap" ] && { sleep "$INTERVAL"; continue; }
  if [ "$cap" -gt "$STOP" ]; then
    set_b force-discharge; low=0                 # drain toward band (no-op if unplugged)
  elif [ "$cap" -le "$SHUTDOWN" ]; then
    set_b auto                                    # charge if plugged
    if [ "$(cat "$CHG/online" 2>/dev/null)" = "0" ]; then
      low=$((low + 1)); echo "charge-limit: low ${cap}% on battery ($low/2)"
      [ "$low" -ge 2 ] && { echo "charge-limit: poweroff"; systemctl poweroff; sleep 120; continue; }
    else low=0; fi
  elif [ "$cap" -le "$START" ]; then
    set_b auto; low=0                             # charge up (no-op if unplugged)
  else
    low=0                                         # in band
    if [ "$(get)" = "auto" ] && [ "$cap" -lt "$STOP" ]; then :  # keep charging to STOP
    else set_b inhibit-charge; fi
  fi
  sleep "$INTERVAL"
done
Edited by Trigus42

Merge request reports

Loading
Loading