aymanbagabas/Huawei-WMI

Charge thresholds doesn't work anymore after BIOS update on HUAWEI MateBook D 15 AMD

mpi3d opened this issue · 13 comments

mpi3d commented

Hi, I just updated my BIOS from version 1.11 to version 1.17 on my HUAWEI MateBook D 15 AMD. After that, setting charge thresholds on Linux as stopped working. Everything else like FN lock and mic led is still working. Also, I'm still able to change those thresholds on Windows.

Steps to reproduce the behavior:

  1. Download the latest BIOS from HUAWEI Support: https://consumer.huawei.com/en/support/laptops/matebook-d-15-amd/
  2. Upgrade your BIOS using Windows on your SSD
  3. Start using Linux to set charge thresholds.

I just want to have charging thresholds working on Linux as it was working before.

$ lsmod | grep wmi
huawei_wmi             24576  0
ledtrig_audio          16384  3 snd_ctl_led,snd_hda_codec_generic,huawei_wmi
sparse_keymap          16384  1 huawei_wmi
wmi_bmof               16384  0
wmi                    36864  2 huawei_wmi,wmi_bmof

I can get Windows charge thresholds:

$ cat /sys/devices/platform/huawei-wmi/charge_control_thresholds
40 70

I can write them even if nothing happen (The battery continue charging above those thresholds):

$ cat /sys/devices/platform/huawei-wmi/charge_control_thresholds
95 100
$ echo "70 90" | sudo tee /sys/devices/platform/huawei-wmi/charge_control_thresholds
70 90
$ cat /sys/devices/platform/huawei-wmi/charge_control_thresholds
70 90

Special case:

$ echo "0 100" | sudo tee /sys/devices/platform/huawei-wmi/charge_control_thresholds
0 100
$ cat /sys/devices/platform/huawei-wmi/charge_control_thresholds
40 70

Hello, I have the matebook D14 dual boot Fedora and Windows. I just noticed that the windows battery charge control does not work either. Yesterday I got the BIOS update :c

@mpi3d @larax2do Charge thresholds work on Huawei MateBook D 15 with 3700U. BIOS 1.17.
In version 1.17, a new feature has been added - smart charging. It overrides battery protection. You have to turn it off so that the battery protection works as before. Later I will try to do it on Linux

mpi3d commented

@sermart1234 Indeed, it does work after turning off smart charging. But after unplugging for more than 1 minute the charger, I'm unable to change charge thresholds. I need to reboot into Windows to be able to change them again.

I am using Honor Magicbook 14 and battery thresholds don't work anymore on Linux after applying las BIOS update either. Any news?

@dalareo if you have Windows: PCManager - Settings - Battery and turn off Smart charging.
On Linux you can try check the battery protection mode

sudo -i
echo 0x00001603 | sudo tee /sys/kernel/debug/huawei-wmi/arg
sudo cat /sys/kernel/debug/huawei-wmi/call
sudo cat /sys/kernel/debug/huawei-wmi/call //strictly twice

[{0x00,0x00,0x00,0x00},{0x00,0x01,0x48,0x28,0x46,0x00... - 70%
[{0x00,0x00,0x00,0x00},{0x00,0x02,0x48,0x46,0x5a,0x00... - 90%
[{0x00,0x00,0x00,0x00},{0x00,0x03,0x48,0x5f,0x64,0x00... - 100%
[{0x00,0x00,0x00,0x00},{0x00,0x04,0x48,0x28,0x46,0x00... - smart charge

You can try set threshold

sudo -i
echo 0x462848011503 | sudo tee /sys/kernel/debug/huawei-wmi/arg // 70%
//echo 0x5a4648021503 | sudo tee /sys/kernel/debug/huawei-wmi/arg // 90%
//echo 0x645f48031503 | sudo tee /sys/kernel/debug/huawei-wmi/arg // 100%
//echo 0x462848041503 | sudo tee /sys/kernel/debug/huawei-wmi/arg // smart charge
cat /sys/kernel/debug/huawei-wmi/call
cat /sys/kernel/debug/huawei-wmi/call //strictly twice

Please, test this. Is it safe.
PCManager cannot read the values and always overwrites them, maybe.

Hi @sermart1234 I get "permissions denied" for that file. Even with root user. It works with generic image but not with low-latency one.

@dalareo sorry. I copied the wrong commands. Please repeat

@aymanbagabas acpidump and dmidecode honor_magicbook_pro_2020_4600h_bios_1_08.zip
New methods:

0x00000C02 GBAI
0x00001203 SBAC
0x00001303 GBAC
0x00001403 GAIT
0x00001503 SBCM #battery charge mode
0x00001603 GBCM #battery charge mode

SBCM can set thresholds as a SBTT. Both write in \_SB.PCI0.LPC0.EC0.BCCL and \_SB.PCI0.LPC0.EC0.BCCH
Set echo 0x462848011503 | sudo tee /sys/kernel/debug/huawei-wmi/arg
0x28 = 40
0x46 = 70
0x48 = 72 - unknown
0x[stop_threshold][start_threshold]48[mode]1503
mode 1 - home
mode 2 - office
mode 3 - travel
mode 4 - smart charge - disable user-settable thresholds
All modes except 4 do not affect thresholds
Warning! If stop_threshold or/and start_threshold equals 0 then it turn on smart charge (set mode 4) as a echo "0 0" > /sys/devices/platform/huawei-wmi/charge_control_thresholds

Also echo 0x462800001503 | sudo tee /sys/kernel/debug/huawei-wmi/arg delete smart charge in PCManager. Mode 0 is old battery protection maybe. Or if unknown = 0

SBTT
Method (SBTT, 1, NotSerialized)
{
    Name (BUFF, Buffer (0x0100) {})
    Local0 = Arg0
    CreateByteField (Arg0, 0x02, BCLB)
    CreateByteField (Arg0, 0x03, BCHB)
    CreateByteField (BUFF, Zero, STAT)
    STAT = Zero
    If (((BCLB == Zero) && (BCHB == 0x64)))
    {
        \_SB.PCI0.LPC0.EC0.BCCL = Zero
        \_SB.PCI0.LPC0.EC0.BCCH = Zero
    }
    Else
    {
        \_SB.PCI0.LPC0.EC0.BCCL = BCLB /* \SBTT.BCLB */
        \_SB.PCI0.LPC0.EC0.BCCH = BCHB /* \SBTT.BCHB */
    }

    Return (BUFF) /* \SBTT.BUFF */
}

Method (GBTT, 1, NotSerialized)
{
    Name (BUFF, Buffer (0x0100) {})
    Local0 = Arg0
    CreateByteField (BUFF, Zero, STAT)
    CreateByteField (BUFF, One, GLCP)
    CreateByteField (BUFF, 0x02, GHCP)
    STAT = Zero
    GLCP = \_SB.PCI0.LPC0.EC0.BCCL
    GHCP = \_SB.PCI0.LPC0.EC0.BCCH
    Return (BUFF) /* \GBTT.BUFF */
}
SBCM
Method (SBCM, 1, NotSerialized)
{
    Name (BUFF, Buffer (0x0100) {})
    Local0 = Arg0
    CreateByteField (Arg0, 0x02, CMOD)
    CreateByteField (Arg0, 0x03, DTTS)
    CreateByteField (Arg0, 0x04, BCLB)
    CreateByteField (Arg0, 0x05, BCHB)
    CreateByteField (BUFF, Zero, STAT)
    STAT = Zero
    \_SB.PCI0.LPC0.EC0.CHAM = CMOD /* \SBCM.CMOD */
    \_SB.PCI0.LPC0.EC0.DTTS = DTTS /* \SBCM.DTTS */
    \_SB.PCI0.LPC0.EC0.BCCL = BCLB /* \SBCM.BCLB */
    \_SB.PCI0.LPC0.EC0.BCCH = BCHB /* \SBCM.BCHB */
    Return (BUFF) /* \SBCM.BUFF */
}

Method (GBCM, 1, NotSerialized)
{
    Name (BUFF, Buffer (0x0100) {})
    Local0 = Arg0
    CreateByteField (BUFF, One, CMOD)
    CreateByteField (BUFF, 0x02, DTTS)
    CreateByteField (BUFF, 0x03, BCLB)
    CreateByteField (BUFF, 0x04, BCHB)
    CreateByteField (BUFF, Zero, STAT)
    CMOD = \_SB.PCI0.LPC0.EC0.CHAM
    DTTS = \_SB.PCI0.LPC0.EC0.DTTS
    BCLB = \_SB.PCI0.LPC0.EC0.BCCL
    BCHB = \_SB.PCI0.LPC0.EC0.BCCH
    STAT = Zero
    Return (BUFF) /* \GBCM.BUFF */
}

SBTT is legacy?

mpi3d commented

Sounds like setting thresholds using this new method also works on HUAWEI MateBook D 15 AMD.
It would be great if this could be implemented without using this "debug" method.
Anyway, thanks for your work @sermart1234

@mpi3d When I find out what the unknown parameter is responsible for, I will implement the interface. In addition, we need to deal with the old interface

mpi3d commented

Ok thanks

@mpi3d please test
#64

mpi3d commented

#64 has solved the issue. Closing.
Thanks @sermart1234.