Skip to content

Instantly share code, notes, and snippets.

@sicelo
Last active April 19, 2022 18:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sicelo/0a0e895d81a6b73b26555d215dee296d to your computer and use it in GitHub Desktop.
Save sicelo/0a0e895d81a6b73b26555d215dee296d to your computer and use it in GitHub Desktop.
Seed bq27200 capacity with rx51_battery data
#!/bin/sh
RX51_CAPACITY="/sys/class/power_supply/rx51-battery/charge_full_design"
BQ27_CAPACITY="/sys/class/power_supply/bq27200-0/capacity"
set -e
# Confirm we have root permissions
# Unload bq27200 module if it is loaded and no capacity available
if lsmod | grep "bq27xxx_battery_i2c" &> /dev/null ; then
# If capacity is available, we have nothing to do. Exit
CAP=$(cat $BQ27_CAPACITY 2> /dev/null)
if [ $? -eq 0 ] && [ $CAP -gt 0 ]; then
# Unload rx51_battery (to keep upower happy)
modprobe -r rx51_battery
exit
fi
modprobe -r bq27xxx_battery_i2c &> /dev/null
fi
# check for presence of required tools (i2cset, cut)
# Reload bq27200 module if CI flag unset: it is normal battery empty condition
# Load rx51_battery. If unsuccessful, make up a capacity (1000mAh makes sense)
modprobe rx51_battery &> /dev/null
if [ $? -ne 0 ]; then
BAT_DESIGN_CAP=1000000 #1000mAh
else
# Get battery's design capacity as reported by rx51-battery
read BAT_DESIGN_CAP < $RX51_CAPACITY
fi
# Calculate capacity_now based on battery design_capacity
# Assume linear relationship between voltage and capacity (inaccurate)
read V_NOW < "/sys/class/power_supply/rx51-battery/voltage_now"
V_EDVF=3000000
V_MAX=4200000
V_DROP=$(($V_MAX - $V_NOW))
V_RANGE=$(($V_MAX - $V_EDVF))
PERCENT=$((100 * ($V_NOW - $V_EDVF) / $V_RANGE))
CAP_NOW=$(($PERCENT * $BAT_DESIGN_CAP / 100))
# bq27200 sense resistor is needed for calculations. On N900 it is 20 megOhms
RS=20
# Convert design capacity to bq27200 NAC format
NAC=$(($CAP_NOW * $RS / 3570))
NAC_HEX=$(printf "%04x\n" $NAC)
NAC_HEX_HI="0x"$(echo $NAC_HEX | cut -c -2 -)
NAC_HEX_LO="0x"$(echo $NAC_HEX | cut -c 3- -)
# write desired NAC to AR reg (0x02 & 0x03)
# write per byte because i2cset sometimes fails to write a full word
i2cset -f -y 2 0x55 0x02 $NAC_HEX_LO # low byte
i2cset -f -y 2 0x55 0x03 $NAC_HEX_HI # high byte
# Prepare mode register for the write operation
CNTRL_CURR=$(i2cget -f -y 2 0x55 0x01)
WRTNAC=32 # bit 5 in reg 0x01
# For completeness, (at your own risk), you can also perform:
# 1. a partial reset of the chip (NAC, LMD, and CI are unaffected) by:
# PRST = 8
# 2. a full reset of the chip (NAC, LMD, and CI also reset) by:
# FRST = 2
CNTRL_NEW=$(printf "%#02x" $(($CNTRL_CURR + $WRTNAC)))
i2cset -f -y 2 0x55 0x01 $CNTRL_NEW
# Perform write of new NAC (via control register)
i2cset -f -y 2 0x55 0x00 0xa9
# Reload bq27200 module
modprobe bq27xxx_battery_i2c
# Unload rx51_battery (to keep upower happy)
modprobe -r rx51_battery
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment