Skip to content

Instantly share code, notes, and snippets.

@linrunner
Last active September 24, 2021 16:28
Show Gist options
  • Save linrunner/2d8eadc217a86d28c1939ac31f434271 to your computer and use it in GitHub Desktop.
Save linrunner/2d8eadc217a86d28c1939ac31f434271 to your computer and use it in GitHub Desktop.

TLP 1.4 Test: Battery Care for Huawei MateBooks

Read the overview document first.

Supported Features

Huawei laptops using the huawei_wmi driver provide both a start and a stop charge threshold ranging from 0% (threshold off) to 100%. The hardware behaviour is:

  1. When connecting the charger, charging starts if the charge level is below the start threshold

  2. Once started, charging stops when the charge level reaches the stop threshold

  3. If the charge level is higher than the stop threshold, the battery will not discharge automatically; it will only be discharged when the charger is removed i.e. the laptop runs on battery

When suitable hardware has been detected, tlp-stat -b shows:

+++ Battery Care
Plugin: huawei
Supported features: charge thresholds
Driver usage:
* natacpi (huawei_wmi) = active (charge thresholds)
Parameter value ranges:
* START_CHARGE_THRESH_BAT0/1:  0(off)..95(default)..100
* STOP_CHARGE_THRESH_BAT0/1:   0(off)..100(default)

+++ Battery Status: BAT0
...
/sys/class/power_supply/BAT0/charge_control_start_threshold =     95 [%]
/sys/class/power_supply/BAT0/charge_control_end_threshold   =    100 [%]
...

How it works

Battery charging is a process not controlled by TLP itself, but by the laptop's embedded controller (EC). This makes the process work even when switched off or no operating system is running. You cannot change the basic behavior, it is hard-coded into the EC firmware by the vendor. TLP just writes the charge threshold into the EC with the help of the kernel driver, the EC takes care of the rest.

Installation

Packages are provided at the download page.

Linux kernel 5.4 or higher required.

Test Cases

Important: please provide all terminal input and output from the test cases via an individual Gist and link it in your post below.

1. Configure and apply a charge thresholds

Edit /etc/tlp.conf (or a config file of your choice under /etc/tlp.d/):

START_CHARGE_THRESH_BAT0="70"
STOP_CHARGE_THRESH_BAT0="80"

Note: if necessary replace with your own values that suit the test case.

Connect the charger.

Enter the following commands in a terminal (as root or with sudo):

tlp start
tlp-stat -s -c -b

Verify that charge_control_start_threshold = 70 and charge_control_end_threshold = 80.

2. Verify the charging process

  1. Let the laptop run on battery power until the charge level falls below the stop threshold by at least 2%
  2. Connect the charger and see if charging starts
  3. Verify that charging stops at 80% (or your configured value)

Enter the command (as root or with sudo):

tlp-stat -b

3. Change charge thresholds manually

Enter the commands (as root or with sudo):

tlp setcharge 85 90
tlp-stat -b

Verify that charge_control_start_threshold = 85, charge_control_end_threshold = 90 and charging starts.

Note: if necessary replace with your own values that suit the test case.

Enter the commands (as root or with sudo):

tlp setcharge
tlp-stat -b

Verify thatcharge_control_start_threshold = 70, charge_control_end_threshold = 80 and charging halts.

4. Disable charge thresholds and return to full charge

Edit the config file used above and comment the parameters to disable them:

#START_CHARGE_THRESH_BAT0="70"
#STOP_CHARGE_THRESH_BAT0="80"

Enter the commands (as root or with sudo):

tlp fullcharge
tlp-stat -b

Verify that charge_control_start_threshold = 95, charge_control_end_threshold = 100 and the battery gets fully charged.

What else should I check?

  • Are there Huawei laptops with more than one battery (tlp-stat -b should show)?
@Ryk97
Copy link

Ryk97 commented Apr 20, 2021

Hey,

I tried to test this feature, but it failed to write the START_CHARGE_THRESH_BAT0 threshold. The error I am getting is: Warning: writing charge start threshold for BAT0 failed.

Please find all the commands and their output below:

~ >>> sudo vim /etc/tlp.d/01-thresh.conf                                                                                          
~ >>> sudo cat /etc/tlp.d/01-thresh.conf                                                                                          
START_CHARGE_THRESH_BAT0="94"
STOP_CHARGE_THRESH_BAT0="95"
~ >>> sudo tlp start                                                                                                              
Warning: writing charge start threshold for BAT0 failed.
TLP started in battery mode (auto).
~ >>> sudo tlp-stat -s -c -b                                                                                                      
--- TLP 1.4.0-alpha.1 --------------------------------------------

+++ Configured Settings:
defaults.conf L0004: TLP_ENABLE="1"
defaults.conf L0005: TLP_WARN_LEVEL="3"
defaults.conf L0006: TLP_PERSISTENT_DEFAULT="0"
defaults.conf L0007: DISK_IDLE_SECS_ON_AC="0"
defaults.conf L0008: DISK_IDLE_SECS_ON_BAT="2"
defaults.conf L0009: MAX_LOST_WORK_SECS_ON_AC="15"
defaults.conf L0010: MAX_LOST_WORK_SECS_ON_BAT="60"
defaults.conf L0011: CPU_ENERGY_PERF_POLICY_ON_AC="balance_performance"
defaults.conf L0012: CPU_ENERGY_PERF_POLICY_ON_BAT="balance_power"
defaults.conf L0013: SCHED_POWERSAVE_ON_AC="0"
defaults.conf L0014: SCHED_POWERSAVE_ON_BAT="1"
defaults.conf L0015: NMI_WATCHDOG="0"
defaults.conf L0016: DISK_DEVICES="nvme0n1 sda"
defaults.conf L0017: DISK_APM_LEVEL_ON_AC="254 254"
defaults.conf L0018: DISK_APM_LEVEL_ON_BAT="128 128"
defaults.conf L0019: DISK_APM_CLASS_DENYLIST="usb ieee1394"
defaults.conf L0020: DISK_IOSCHED="keep keep"
defaults.conf L0021: SATA_LINKPWR_ON_AC="med_power_with_dipm max_performance"
defaults.conf L0022: SATA_LINKPWR_ON_BAT="med_power_with_dipm min_power"
defaults.conf L0023: AHCI_RUNTIME_PM_ON_AC="on"
defaults.conf L0024: AHCI_RUNTIME_PM_ON_BAT="auto"
defaults.conf L0025: AHCI_RUNTIME_PM_TIMEOUT="15"
defaults.conf L0026: PCIE_ASPM_ON_AC="default"
defaults.conf L0027: PCIE_ASPM_ON_BAT="default"
defaults.conf L0028: RADEON_POWER_PROFILE_ON_AC="default"
defaults.conf L0029: RADEON_POWER_PROFILE_ON_BAT="default"
defaults.conf L0030: RADEON_DPM_PERF_LEVEL_ON_AC="auto"
defaults.conf L0031: RADEON_DPM_PERF_LEVEL_ON_BAT="auto"
defaults.conf L0032: WIFI_PWR_ON_AC="off"
defaults.conf L0033: WIFI_PWR_ON_BAT="on"
defaults.conf L0034: WOL_DISABLE="Y"
defaults.conf L0035: SOUND_POWER_SAVE_ON_AC="1"
defaults.conf L0036: SOUND_POWER_SAVE_ON_BAT="1"
defaults.conf L0037: SOUND_POWER_SAVE_CONTROLLER="Y"
defaults.conf L0038: BAY_POWEROFF_ON_AC="0"
defaults.conf L0039: BAY_POWEROFF_ON_BAT="0"
defaults.conf L0040: BAY_DEVICE="sr0"
defaults.conf L0041: RUNTIME_PM_ON_AC="on"
defaults.conf L0042: RUNTIME_PM_ON_BAT="auto"
defaults.conf L0043: RUNTIME_PM_DRIVER_DENYLIST="mei_me nouveau radeon"
defaults.conf L0044: USB_AUTOSUSPEND="1"
defaults.conf L0045: USB_EXCLUDE_AUDIO="1"
defaults.conf L0046: USB_EXCLUDE_BTUSB="0"
defaults.conf L0047: USB_EXCLUDE_PHONE="0"
defaults.conf L0048: USB_EXCLUDE_PRINTER="1"
defaults.conf L0049: USB_EXCLUDE_WWAN="0"
defaults.conf L0050: USB_AUTOSUSPEND_DISABLE_ON_SHUTDOWN="0"
defaults.conf L0051: RESTORE_DEVICE_STATE_ON_STARTUP="0"
defaults.conf L0052: RESTORE_THRESHOLDS_ON_BAT="0"
defaults.conf L0053: NATACPI_ENABLE="1"
defaults.conf L0054: TPACPI_ENABLE="1"
defaults.conf L0055: TPSMAPI_ENABLE="1"
/etc/tlp.d/01-thresh.conf L0001: START_CHARGE_THRESH_BAT0="94"
/etc/tlp.d/01-thresh.conf L0002: STOP_CHARGE_THRESH_BAT0="95"

+++ System Info
System         = HUAWEI M1130 KLVL-WXX9
BIOS           = 1.05
OS Release     = Arch Linux
Kernel         = 5.11.15-arch1-2 #1 SMP PREEMPT Sat, 17 Apr 2021 00:22:30 +0000 x86_64
/proc/cmdline  = BOOT_IMAGE=/vmlinuz-linux root=UUID=e54260fc-952b-4a28-941e-978589301620 rw rootflags=subvol=@ cryptdevice=/dev/disk/by-uuid/024d288c-2abc-4b9c-9306-4bad5ee04e5a:cryptroot root=/dev/mapper/cryptroot rootflags=subvolid=256 resume=/dev/mapper/cryptroot resume_offset=33980383 quiet splash loglevel=3 rd.udev.log_priority=3 vt.global_cursor_default=0
Init system    = systemd 
Boot mode      = UEFI

+++ TLP Status
State          = enabled
RDW state      = not installed
Last run       = 22:38:08,     69 sec(s) ago
Mode           = battery
Power source   = battery

Warning: tlp.service is not enabled -- invoke "systemctl enable tlp.service" to correct this!
Warning: systemd-rfkill.service is not masked -- invoke "systemctl mask systemd-rfkill.service" to correct this!
Warning: systemd-rfkill.socket is not masked -- invoke "systemctl mask systemd-rfkill.socket" to correct this!

+++ Battery Wear Control
Plugin: huawei
Supported features: charge thresholds
Driver usage:
* natacpi (huawei_wmi) = active (charge thresholds)
Parameter value ranges:
* START_CHARGE_THRESH_BAT0/1:  0(off)..95(default)..100
* STOP_CHARGE_THRESH_BAT0/1:   0(off)..100(default)

+++ Battery Status: BAT0
/sys/class/power_supply/BAT0/manufacturer                   = Desay
/sys/class/power_supply/BAT0/model_name                     = HB4593R1ECW-22T0
/sys/class/power_supply/BAT0/cycle_count                    =     41
/sys/class/power_supply/BAT0/charge_full_design             =   7230 [mAh]
/sys/class/power_supply/BAT0/charge_full                    =   7168 [mAh]
/sys/class/power_supply/BAT0/charge_now                     =   6679 [mAh]
/sys/class/power_supply/BAT0/current_now                    =    632 [mA]
/sys/class/power_supply/BAT0/status                         = Discharging

/sys/class/power_supply/BAT0/charge_control_start_threshold =      0 [%]
/sys/class/power_supply/BAT0/charge_control_end_threshold   =      0 [%]

Charge                                                      =   93.2 [%]
Capacity                                                    =   99.1 [%]

~ >>> sudo tlp start                                                                                                              
Warning: writing charge start threshold for BAT0 failed.
TLP started in battery mode (auto).
~ >>> tlp setcharge 94 95                                                                                                         
zsh: correct 'tlp' to 'top' [nyae]? n
Error: missing root privilege.
~ >>> sudo !!                                                                                                                  [1]
sudo tlp setcharge 94 95
Setting temporary charge thresholds for BAT0:
  stop  =  95
  start =  94 (Error: write failed)
~ >>> sudo tlp-stat -s -c -b                                                                                                   [5]
--- TLP 1.4.0-alpha.1 --------------------------------------------

+++ Configured Settings:
defaults.conf L0004: TLP_ENABLE="1"
defaults.conf L0005: TLP_WARN_LEVEL="3"
defaults.conf L0006: TLP_PERSISTENT_DEFAULT="0"
defaults.conf L0007: DISK_IDLE_SECS_ON_AC="0"
defaults.conf L0008: DISK_IDLE_SECS_ON_BAT="2"
defaults.conf L0009: MAX_LOST_WORK_SECS_ON_AC="15"
defaults.conf L0010: MAX_LOST_WORK_SECS_ON_BAT="60"
defaults.conf L0011: CPU_ENERGY_PERF_POLICY_ON_AC="balance_performance"
defaults.conf L0012: CPU_ENERGY_PERF_POLICY_ON_BAT="balance_power"
defaults.conf L0013: SCHED_POWERSAVE_ON_AC="0"
defaults.conf L0014: SCHED_POWERSAVE_ON_BAT="1"
defaults.conf L0015: NMI_WATCHDOG="0"
defaults.conf L0016: DISK_DEVICES="nvme0n1 sda"
defaults.conf L0017: DISK_APM_LEVEL_ON_AC="254 254"
defaults.conf L0018: DISK_APM_LEVEL_ON_BAT="128 128"
defaults.conf L0019: DISK_APM_CLASS_DENYLIST="usb ieee1394"
defaults.conf L0020: DISK_IOSCHED="keep keep"
defaults.conf L0021: SATA_LINKPWR_ON_AC="med_power_with_dipm max_performance"
defaults.conf L0022: SATA_LINKPWR_ON_BAT="med_power_with_dipm min_power"
defaults.conf L0023: AHCI_RUNTIME_PM_ON_AC="on"
defaults.conf L0024: AHCI_RUNTIME_PM_ON_BAT="auto"
defaults.conf L0025: AHCI_RUNTIME_PM_TIMEOUT="15"
defaults.conf L0026: PCIE_ASPM_ON_AC="default"
defaults.conf L0027: PCIE_ASPM_ON_BAT="default"
defaults.conf L0028: RADEON_POWER_PROFILE_ON_AC="default"
defaults.conf L0029: RADEON_POWER_PROFILE_ON_BAT="default"
defaults.conf L0030: RADEON_DPM_PERF_LEVEL_ON_AC="auto"
defaults.conf L0031: RADEON_DPM_PERF_LEVEL_ON_BAT="auto"
defaults.conf L0032: WIFI_PWR_ON_AC="off"
defaults.conf L0033: WIFI_PWR_ON_BAT="on"
defaults.conf L0034: WOL_DISABLE="Y"
defaults.conf L0035: SOUND_POWER_SAVE_ON_AC="1"
defaults.conf L0036: SOUND_POWER_SAVE_ON_BAT="1"
defaults.conf L0037: SOUND_POWER_SAVE_CONTROLLER="Y"
defaults.conf L0038: BAY_POWEROFF_ON_AC="0"
defaults.conf L0039: BAY_POWEROFF_ON_BAT="0"
defaults.conf L0040: BAY_DEVICE="sr0"
defaults.conf L0041: RUNTIME_PM_ON_AC="on"
defaults.conf L0042: RUNTIME_PM_ON_BAT="auto"
defaults.conf L0043: RUNTIME_PM_DRIVER_DENYLIST="mei_me nouveau radeon"
defaults.conf L0044: USB_AUTOSUSPEND="1"
defaults.conf L0045: USB_EXCLUDE_AUDIO="1"
defaults.conf L0046: USB_EXCLUDE_BTUSB="0"
defaults.conf L0047: USB_EXCLUDE_PHONE="0"
defaults.conf L0048: USB_EXCLUDE_PRINTER="1"
defaults.conf L0049: USB_EXCLUDE_WWAN="0"
defaults.conf L0050: USB_AUTOSUSPEND_DISABLE_ON_SHUTDOWN="0"
defaults.conf L0051: RESTORE_DEVICE_STATE_ON_STARTUP="0"
defaults.conf L0052: RESTORE_THRESHOLDS_ON_BAT="0"
defaults.conf L0053: NATACPI_ENABLE="1"
defaults.conf L0054: TPACPI_ENABLE="1"
defaults.conf L0055: TPSMAPI_ENABLE="1"
/etc/tlp.d/01-thresh.conf L0001: START_CHARGE_THRESH_BAT0="94"
/etc/tlp.d/01-thresh.conf L0002: STOP_CHARGE_THRESH_BAT0="95"

+++ System Info
System         = HUAWEI M1130 KLVL-WXX9
BIOS           = 1.05
OS Release     = Arch Linux
Kernel         = 5.11.15-arch1-2 #1 SMP PREEMPT Sat, 17 Apr 2021 00:22:30 +0000 x86_64
/proc/cmdline  = BOOT_IMAGE=/vmlinuz-linux root=UUID=e54260fc-952b-4a28-941e-978589301620 rw rootflags=subvol=@ cryptdevice=/dev/disk/by-uuid/024d288c-2abc-4b9c-9306-4bad5ee04e5a:cryptroot root=/dev/mapper/cryptroot rootflags=subvolid=256 resume=/dev/mapper/cryptroot resume_offset=33980383 quiet splash loglevel=3 rd.udev.log_priority=3 vt.global_cursor_default=0
Init system    = systemd 
Boot mode      = UEFI

+++ TLP Status
State          = enabled
RDW state      = not installed
Last run       = 22:39:56,     47 sec(s) ago
Mode           = battery
Power source   = battery

Warning: tlp.service is not enabled -- invoke "systemctl enable tlp.service" to correct this!
Warning: systemd-rfkill.service is not masked -- invoke "systemctl mask systemd-rfkill.service" to correct this!
Warning: systemd-rfkill.socket is not masked -- invoke "systemctl mask systemd-rfkill.socket" to correct this!

+++ Battery Wear Control
Plugin: huawei
Supported features: charge thresholds
Driver usage:
* natacpi (huawei_wmi) = active (charge thresholds)
Parameter value ranges:
* START_CHARGE_THRESH_BAT0/1:  0(off)..95(default)..100
* STOP_CHARGE_THRESH_BAT0/1:   0(off)..100(default)

+++ Battery Status: BAT0
/sys/class/power_supply/BAT0/manufacturer                   = Desay
/sys/class/power_supply/BAT0/model_name                     = HB4593R1ECW-22T0
/sys/class/power_supply/BAT0/cycle_count                    =     41
/sys/class/power_supply/BAT0/charge_full_design             =   7230 [mAh]
/sys/class/power_supply/BAT0/charge_full                    =   7168 [mAh]
/sys/class/power_supply/BAT0/charge_now                     =   6663 [mAh]
/sys/class/power_supply/BAT0/current_now                    =    582 [mA]
/sys/class/power_supply/BAT0/status                         = Discharging

/sys/class/power_supply/BAT0/charge_control_start_threshold =      0 [%]
/sys/class/power_supply/BAT0/charge_control_end_threshold   =      0 [%]

Charge                                                      =   93.0 [%]
Capacity                                                    =   99.1 [%]

~ >>> sudo systemctl enable tlp.service                                                                                           
Created symlink /etc/systemd/system/multi-user.target.wants/tlp.service → /usr/lib/systemd/system/tlp.service.
~ >>> sudo tlp-stat -b                                                                                                            
--- TLP 1.4.0-alpha.1 --------------------------------------------

+++ Battery Wear Control
Plugin: huawei
Supported features: charge thresholds
Driver usage:
* natacpi (huawei_wmi) = active (charge thresholds)
Parameter value ranges:
* START_CHARGE_THRESH_BAT0/1:  0(off)..95(default)..100
* STOP_CHARGE_THRESH_BAT0/1:   0(off)..100(default)

+++ Battery Status: BAT0
/sys/class/power_supply/BAT0/manufacturer                   = Desay
/sys/class/power_supply/BAT0/model_name                     = HB4593R1ECW-22T0
/sys/class/power_supply/BAT0/cycle_count                    =     41
/sys/class/power_supply/BAT0/charge_full_design             =   7230 [mAh]
/sys/class/power_supply/BAT0/charge_full                    =   7168 [mAh]
/sys/class/power_supply/BAT0/charge_now                     =   6632 [mAh]
/sys/class/power_supply/BAT0/current_now                    =    600 [mA]
/sys/class/power_supply/BAT0/status                         = Discharging

/sys/class/power_supply/BAT0/charge_control_start_threshold =      0 [%]
/sys/class/power_supply/BAT0/charge_control_end_threshold   =      0 [%]

Charge                                                      =   92.5 [%]
Capacity                                                    =   99.1 [%]

~ >>> sudo tlp start                                                                                                              
Warning: writing charge start threshold for BAT0 failed.
TLP started in battery mode (auto).
~ >>> sudo vim /etc/tlp.d/01-thresh.conf                                                                                          
~ >>> sudo tlp start                                                                                                              
Warning: writing charge start threshold for BAT0 failed.
TLP started in battery mode (auto).
~ >>> sudo cat /etc/tlp.d/01-thresh.conf                                                                                          
START_CHARGE_THRESH_BAT0="80"
STOP_CHARGE_THRESH_BAT0="90"
~ >>> sudo tlp setcharge 80 95                                                                                                    
Setting temporary charge thresholds for BAT0:
  stop  =  95
  start =  80 (Error: write failed)
~ >>> sudo tlp-stat -b                                                                                                         [5]
--- TLP 1.4.0-alpha.1 --------------------------------------------

+++ Battery Wear Control
Plugin: huawei
Supported features: charge thresholds
Driver usage:
* natacpi (huawei_wmi) = active (charge thresholds)
Parameter value ranges:
* START_CHARGE_THRESH_BAT0/1:  0(off)..95(default)..100
* STOP_CHARGE_THRESH_BAT0/1:   0(off)..100(default)

+++ Battery Status: BAT0
/sys/class/power_supply/BAT0/manufacturer                   = Desay
/sys/class/power_supply/BAT0/model_name                     = HB4593R1ECW-22T0
/sys/class/power_supply/BAT0/cycle_count                    =     41
/sys/class/power_supply/BAT0/charge_full_design             =   7230 [mAh]
/sys/class/power_supply/BAT0/charge_full                    =   7168 [mAh]
/sys/class/power_supply/BAT0/charge_now                     =   6613 [mAh]
/sys/class/power_supply/BAT0/current_now                    =    665 [mA]
/sys/class/power_supply/BAT0/status                         = Discharging

/sys/class/power_supply/BAT0/charge_control_start_threshold =      0 [%]
/sys/class/power_supply/BAT0/charge_control_end_threshold   =      0 [%]

Charge                                                      =   92.3 [%]
Capacity                                                    =   99.1 [%]

~ >>>                                   

Any Ideas what I can try to get the threshold to be written?

@linrunner
Copy link
Author

Interesting. What happens if you write the thresholds manually?

Invoke a root shell:

sudo -s

Write:

echo 95 > /sys/class/power_supply/BAT0/charge_control_end_threshold
echo 94 > /sys/class/power_supply/BAT0/charge_control_start_threshold

Check:

grep . /sys/class/power_supply/BAT0/charge_control*

@Ryk97
Copy link

Ryk97 commented Apr 21, 2021

Does not work either:

~ >>> sudo -i                                                                                                                     
[sudo] Passwort für niklas: 
[root@matebook14-arch ~]# echo 95 > /sys/class/power_supply//BAT0/charge_control_end_threshold 
[root@matebook14-arch ~]# echo 90 > /sys/class/power_supply//BAT0/charge_control_start_threshold 
-bash: echo: Schreibfehler: Kein passendes Gerät gefunden.
[root@matebook14-arch ~]# grep . /sys/class/power_supply/BAT0/charge_control*
/sys/class/power_supply/BAT0/charge_control_end_threshold:0
/sys/class/power_supply/BAT0/charge_control_start_threshold:0
[root@matebook14-arch ~]# 

The error that is shown when writing to start_threshold translates to: write error: no such device

@linrunner
Copy link
Author

Seems to be a kernel bug, do you mind reporting it? charge_control_end_threshold is ignored too.

@aymanbagabas
Copy link

Hi all, @Ryk97 could you please open a new ticket at https://github.com/aymanbagabas/Huawei-WMI with an acpi dump, dmidecode, and a dmesg log after setting the thresholds?

@linrunner
Copy link
Author

Beta 2 is out. Enjoy!

@linrunner
Copy link
Author

linrunner commented Sep 24, 2021

TLP 1.4 is released. Have fun and keep testing please1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment