Open mpeter50 opened 1 year ago
In the /sys/class/power_supply/
directory I have subdirectories AC, BAT0, CROS_USBPD_CHARGER0 and CROS_USBPD_CHARGER1.
The 2nd one seems to be the actual battery, and the 1st, 3rd and 4th seem to be related to charging controllers.
The 3rd indicates charging only if I plug in the charger to the left side USB-C port, the 4th only if I plug in the charger to the right side USB-C port, and the 1st one indicated charging in both cases, just as BAT0.
So apparently, this feature is supported on at least some ChromeOS devices. The most important source of information seems to be the ChromeOS Adaptive Charging page. A brief summary.
ectool chargecontrol normal <lower> <upper>
. See that page for details on the parameters.chargecontrol
sub-command will enable both "Battery Sustainer" feature and "charge limit".ectool chargecurrentlimit <max_current_mA>
.Caveat: I'm a prospective Chromebook buyer and do not have any ChromeOS device to test.
@MrChromebox Do you know of any device supporting the chargecontrol
and chargecurrentlimit
sub-commands? Can we change this before flashing custom firmware and retain the settings after flashing?
I'm not sure when this feature was introduced, nor how easily it could be backported. ectool isn't a part of ChromeOS anymore even, so I don't know how you'd change it before flashing - it would need to be done from the OS afterwards
I have no idea about the details, but this documentation page was added about two years ago. Based on what I've read, some devices do support this feature.
https://chromium.googlesource.com/chromiumos/platform2/+/d31efe96afbe52c7edfd857f988108b521c252fd
Oh, and the Charge Limit section in particular was added six months ago, so this feature is very new. https://chromium.googlesource.com/chromiumos/platform2/+/647763a9faa54d81793bc9ae91c44fd17e1eca35
Oh I found some additional info, but totally forgot to comment it here. Thanks for reminding me!
For the past few months I have been using the ectool made for the framework laptop to limit charging. If I remember it right, those use the same EC firmware. I think I have built it on the machine from framework's source, but if more accurate details are needed I think I have it written up somewhere..
ectool chargecontrol normal <lower> <upper>
on my laptop works by disabling charging as soon as the charge percentage reaches the <upper>
value. After that, the battery starts discharging, and charging is probably re-enabled when the percentage reaches the <lower>
value. Probably, as I didn't test it, because I didn't like this way of conserving battery life. Sure its better than without, but there's an even better way!
ectool chargecontrol idle
disables charging, and as I understand, the laptop will draw power from the charger instead of the battery. Charge percentage does not change when this is in use, and /sys/class/power_supply/BAT0/current_now
will say 0 (while it says something higher when it is using the battery when charger is not connected). I think I have also read it somewhere that this does not work with any USB-C charger, but so far I haven't tried it with anything other than it's original one.
Right now, it also means I have to manually put the EC into idle or normal charging mode when I want to change it, even though I think KDE has a toggle for it, for when the kernel supports it. The plan for myself was to attempt to add support for this to the kernel. I have read the relevant source and I think I have an idea where would this be added, but so far I have never written kernel modules and didn't have the time to continue it. In the meantime I had made helper commands that shorten (and limit the power of) the ectool commands, and marked these in the sudoers as executable without any password, and am using it from the Yakuake drop down terminal. It's a bit inconvenient, even more when I would use it folded away, but I mostly keep it in idle charging mode.
A few more things I have noticed. If you turn it to normal mode with battery sustainer, but it was in idle mode, it wont apply the battery sustainer, and it will charge all the way to 100%. If you rerun the same command it will also apply the battery sustainer. Idle charging can be only enabled (with the ectool at least) while the device is charging, otherwise it will print an error (EC result 2 (ERROR), Is AC connected?), but it can be switched back to normal mode any time.
I'm not sure when this feature was introduced
I was using it since ~february, I think with version 4.18.2 of your firmware package.
If you want to test something, let me know and I'll take a look at it. Currently I use the MrChromebox 4.21.0 firmware, with openSUSE 15.5 and kernel version 5.14.21
From that page:
If lower and upper are the same, the charger will idle (no current to or from the battery) while at that charge.
Did you try this? What laptop model do you have?
Did you try this?
Not yet, I think. I'll try it out.
What laptop model do you have?
I have a Lenovo 500e 2nd Gen (Code name: Phaser360S, Board name: Octopus)
If I run ectool chargecontrol normal 0 0
, /sys/class/power_supply/BAT0/current_now
will read 0 (it had a higher value before running the command).
However, the help page of the command suggests to me that this way its not actually not charging, but that its trying to keep it in balance:
# ectool chargecontrol help
[...]
Usage: chargecontrol normal <lower> <upper>
Enable battery sustainer. <lower> and <upper> are battery SoC
between which EC tries to keep the battery level.
The documentation linked by you says explicitely that this is not whats happening (below is a quote from it), but I thought its worth to mention that these contradict.
If lower and upper are the same, the charger will idle (no current to or from the battery) while at that charge.
I thought you should use
ectool chargecontrol normal 70 70
to achieve: do not charge past 70 percent, and charge to 70 percent if under 70 percent. If currently is 70 percent, draw power from AC.
Or,
ectool chargecontrol normal 30 70
to achieve: do not charge past 70 percent, and charge to 70 percent if under 30 percent. If currently is between 30 and 70 percent, draw power from AC.
Here is the source code:
https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/main/common/charge_state.c
Quote from line 912:
/*
* The sustain range is defined by 'lower' and 'upper' where the equal
* values are inclusive:
*
* |------------NORMAL------------+--IDLE--+---DISCHARGE---|
* 0% ^ ^ 100%
* lower upper
*
* The switch statement below allows the sustainer to start with any soc
* (0% ~ 100%) and any previous lower & upper limits. It sets mode to
* NORMAL to charge till the soc hits the upper limit or sets mode to
* DISCHARGE to discharge till the soc hits the upper limit.
*
* Once the soc enters in the sustain range, it'll switch to IDLE. In
* IDLE mode, the system power is supplied from the AC. Thus, the soc
* normally should stay in the sustain range unless there is high load
* on the system or the charger is too weak.
*
* Some boards have a sing capacitor problem with mode == IDLE. For such
* boards, a host can specify EC_CHARGE_CONTROL_FLAG_NO_IDLE, which
* makes the sustainer use DISCHARGE instead of IDLE. This is done by
* setting lower != upper in V2, which doesn't support the flag.
*/
case CHARGE_CONTROL_NORMAL:
/* Currently charging */
if (sustain_soc.upper < soc) {
/*
* We come here only if the soc is already above the
* upper limit at the time the sustainer started.
*/
new_mode = CHARGE_CONTROL_DISCHARGE;
} else if (sustain_soc.upper == soc) {
/*
* We've been charging and finally reached the upper.
* Let's switch to IDLE to stay.
*/
if (sustain_soc.flags & EC_CHARGE_CONTROL_FLAG_NO_IDLE)
new_mode = CHARGE_CONTROL_DISCHARGE;
else
new_mode = CHARGE_CONTROL_IDLE;
}
break;
case CHARGE_CONTROL_IDLE:
/* Discharging naturally */
if (soc < sustain_soc.lower)
/*
* Presumably, we stayed in the sustain range for a
* while but finally fell off the range. Let's charge to
* the upper.
*/
new_mode = CHARGE_CONTROL_NORMAL;
else if (sustain_soc.upper < soc)
/*
* This can happen only if sustainer is restarted with
* decreased upper limit. Let's discharge to the upper.
*/
new_mode = CHARGE_CONTROL_DISCHARGE;
break;
case CHARGE_CONTROL_DISCHARGE:
/* Discharging actively. */
if (soc <= sustain_soc.upper &&
!(sustain_soc.flags & EC_CHARGE_CONTROL_FLAG_NO_IDLE))
/*
* Normal case. We've been discharging and finally
* reached the upper. Let's switch to IDLE to stay.
*/
new_mode = CHARGE_CONTROL_IDLE;
else if (soc < sustain_soc.lower)
/*
* This can happen only if sustainer is restarted with
* increase lower limit. Let's charge to the upper (then
* switch to IDLE).
*/
new_mode = CHARGE_CONTROL_NORMAL;
break;
If I understood correctly, this would provide us one of the most flexible charging controls available.
mpeter50 @.***> writes:
However, the help page of the command suggests to me that this way its not actually not charging, but that its trying to keep it in balance:
ectool chargecontrol help
[...] Usage: chargecontrol normal
Enable battery sustainer. and are battery SoC between which EC tries to keep the battery level.
Maybe the help page is outdated.
P.S. From their test cases: https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/main/test/sbs_charging.c
Using ``ectool chargecontrol normal 79 80'' might be useful:
/* Enable sustainer. */
rv = battery_sustainer_set(version, 79, 80, flags);
ectool chargecontrol normal 70 70
to achieve: do not charge past 70 percent, and charge to 70 percent if under 70 percent. If currently is 70 percent, draw power from AC.
Or,
ectool chargecontrol normal 30 70
to achieve: do not charge past 70 percent, and charge to 70 percent if under 30 percent. If currently is between 30 and 70 percent, draw power from AC.
I think that should be right. I know that the latter is working that way, and the former should work that way based on how ectool chargecontrol normal 0 0
works.
- Once the soc enters in the sustain range, it'll switch to IDLE. In
- IDLE mode, the system power is supplied from the AC. Thus, the soc
- normally should stay in the sustain range unless there is high load
- on the system or the charger is too weak
Oh, so this is known that it basically automates IDLE mode. That's good to know.
If I understood correctly, this would provide us one of the most flexible charging controls available.
Yeah, based on the code you quoted I might not even need to manually set idle and normal modes, as it switches to IDLE when it has reached the upper limit specified in the command. Such a command could also be set up to run at every boot. Maybe I could use a second "profile" thatr sets the lower limit higher when I know I'll need a little more until I can charge it again.
I will need to test this. Honestly I have a faint memory as if the battery sustainer would have set the charging state to DISHCHARGE not IDLE when I was testing it, but maybe I'm wrong, or they have changed it since I have tested it (almost a year ago) and I already have the new code.
Maybe the help page is outdated.
Yeah, possibly, that is coming from ectool
, which I haven't rebuilt since ~march.
Using ``ectool chargecontrol normal 79 80'' might be useful:
The code you quoted mentions the case when power consumption is larger than what the charger can provide.
For that case, this (or even a larger range) would be useful I think, as it wouldn't recharge to 80% immediately when it falls to 79, but with e.g. ectool chargecontrol normal 70 80
only after it has fallen a whole 10%, to 69%.
mpeter50 @.***> writes:
I will need to test this. Honestly I have a faint memory as if the battery sustainer would have set the charging state to DISHCHARGE not IDLE when I was testing it, but maybe I'm wrong, or they have changed it since I have tested it (almost a year ago) and I already have the new code.
This last sentence from the quote above might be related:
Yeah, possibly, that is coming from ectool, which I haven't rebuilt since ~march.
No, the master branch from Google has the exact help message as yours. I guess the developers haven't synced the help message with new features. In any case, reading the source code is a more reliable way to determine how does ectool and EC interact.
This last sentence from the quote above might be related:
- Some boards have a sing capacitor problem with mode == IDLE. For
- such boards, a host can specify EC_CHARGE_CONTROL_FLAG_NO_IDLE,
- which makes the sustainer use DISCHARGE instead of IDLE. This is
- done by setting lower != upper in V2, which doesn't support the
- flag.
Yeah, thats a possibility, and that would be great, to say the least. By the way there is certainly a capacitor that sings in it, but that certainly does not depend on IDLE mode, but instead as I have noticed it depends on power consmuption. It does that independently of whether it is connected to a charger or not.
What exactly is this issue requesting? I can think of two possibilities:
/sys/class/power_supply/<battery name>/charge_start_threshold
so that it can be used with TLPHere is a kernel patch that hooks up the ChromeOS EC charge control to the standard Linux sysfs files: https://lore.kernel.org/lkml/20240519-cros_ec-charge-control-v1-0-baf305dc79b8@weissschuh.net/
Testing would be welcome.
I'll try to test it. But I have a few questions about it:
ectool fwchargelimit
but on Chromebooks it's set with ectool chargecontrol
.I'll try to test it.
Thanks!
Is it supposed to work on Chromebooks?
Yes, it does not use any Framework specific APIs.
Also on my FW 13 AMD ectool chargecontrol
works just fine.
Does it work with Chromebooks that don't support charge control sustainer?
I don't think so.
My chromebook (Jinlon) doesn't support charge control sustainer. I can only do chargecontrol idle
. I can't do chargecontrol normal 80 80
.
It would need extensions in the driver to use the old protocol. I hoped not needing this. I'll take a look.
I think that supporting charge control for Chromebooks without sustainer is pretty important because the sustainer only started with 11th Gen Chromebooks (I'm pretty sure), and a lot of people who use Linux on Chromebooks use Chromebooks which are 2020 or older models.
Please try https://git.sr.ht/~t-8ch/linux/log/b4/cros_ec-charge-control
It should only show the charge_behaviour
sysfs file.
Can your device do force discharge?
Can your device do force discharge?
Yes. normal
, idle
, and discharge
all work. It doesn't support GET or sustainer.
Please try https://git.sr.ht/~t-8ch/linux/log/b4/cros_ec-charge-control
I will. I'm on NixOS btw so it should be easy to experiment with the kernel patches without messing up my normal system. This is my first time using custom kernel packages so it may take a while for me to figure it out.
This is my first time using custom kernel packages so it may take a while for me to figure it out.
Good luck!
Note: I have some other drivers for which I would also be grateful to get some testing. https://community.frame.work/t/request-testing-of-linux-drivers-on-all-laptop-models/51283
Note: I have some other drivers for which I would also be grateful to get some testing. https://community.frame.work/t/request-testing-of-linux-drivers-on-all-laptop-models/51283
I am happy to test all drivers that I can on my Jinlon.
LED Driver - I'm guessing from what I read from your post that this will let me control the two LEDs on Jinlon, next to the USB-C port on the left and right side. This would be very cool.
Keyboard backlight - It works just fine OOTB, I'm guessing I should test if it continues to work just fine with your patches.
Sensors - I'm not sure what this patch does. I'm guessing that it will show
[rajas@nixos:~]$ sudo ectool temps all
--sensor name -------- temperature -------- ratio (fan_off and fan_max) --
Charger 300 K (= 27 C) 4% (298 K and 343 K)
5v Reg 302 K (= 29 C) 16% (298 K and 323 K)
CPU 304 K (= 31 C) N/A (fan_off=0 K, fan_max=0 K)
IR Sensor 301 K (= 28 C) N/A (fan_off=0 K, fan_max=0 K)
through the file system, and maybe adjusting the thresholds that activate fans in the future.
All your guesses are correct. The keyboard backlight is probably already probed through ACPI.
I got the kernel to build, I haven't tested it yet. Is there a git repo for the keyboard backlight patch like the other sourcehut branches?
I pushed it now to the same repo, branch b4/cros_ec-kbd-led-framework
.
Could you first test the tag sent/20240505-cros_ec-kbd-led-framework-7e2e831bc79c-v2
instead?
With it you may see the following warning in dmesg:
Led cros_ec::kbd_backlight renamed to cros_ec::kbd_backlight_1 due to name collision.
Can you confirm this? It should not happen anymore with the branch.
I will continue editing this comment as I test the other kernels:
sent/20240505-cros_ec-kbd-led-framework-7e2e831bc79c-v2
I can control thee keyboard light using my Chromebook's keyboard brightness up and down keys. I get this message:
[rajas@nixos:~]$ dmesg | grep rename
[ 7.406100] cros-keyboard-leds cros-keyboard-leds.6.auto: Led chromeos::kbd_backlight renamed to chromeos::kbd_backlight_1 due to name collision
I can change the keyboard light by writing to either /sys/class/leds/chromeos::kbd_backlight_1/brightness
or /sys/class/leds/chromeos::kbd_backlight/brightness
cros_ec-charge-control
/sys/class/power_supply/BAT0/charge_behaviour
shows up. Thresholds don't show up. The charge control was idle
when I booted my Chromebook, but ig since the EC doesn't support GET there's no way of knowing (besides guessing based on battery current).
Writing to the file sets the charge control as expected. However, I think my Chromebook can't do force discharge cuz if I set it to force discharge (with either the /sys
file or ectool
), it only discharges a tiny bit for 2 seconds and then the current becomes 0mA
. I will see if this happens on a normal kernel too.
cros_ec-hwmon
The sensors command shows this:
cros_ec-isa-0000
Adapter: ISA adapter
fan1: 0 RPM
fan2: 0 RPM
Charger: +36.9°C
5v Reg: +34.9°C
CPU: +39.9°C
IR Sensor: +32.9°C
which matches with ectool temps all
, so nice. Fan speeds also work.
cros_ec-led
cros_ec:multicolor:left
, cros_ec:multicolor:right
, and cros_ec:white:power
show up in /sys/class/leds
.
trigger
Setting none
or cros_ec-auto
works. However, there are a bunch of other options that seem to do the same as none
. The options are none rc-feedback kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock mmc1 rfkill-any rfkill-none mmc0 BAT0-charging-or-full BAT0-charging BAT0-full BAT0-charging-blink-full-solid AC-online CROS_USBPD_CHARGER0-online CROS_USBPD_CHARGER1-online [cros_ec-auto] hid-0018:27C6:0E0C.0001-battery-charging-or-full hid-0018:27C6:0E0C.0001-battery-charging hid-0018:27C6:0E0C.0001-battery-full hid-0018:27C6:0E0C.0001-battery-charging-blink-full-solid phy0rx phy0tx phy0assoc phy0radio rfkill1 rfkill8
. I tried setting it to AC-online
, expecting that the light would be on if the charger is plugged in. The charger was plugged in when I did that, but the LED did not turn on. Plugging in the charger did not turn it on either.
Other than that, setting brightness
to 0
or 1
turns it on or off as expected
brightness
Works as expected
trigger
Setting to none
or cros_ec-auto
works. Same comments as the power LED's trigger
file.
multi_intensity
By default the value of this is 100 100
. From experimenting, if set to 0 0
, the LED will be off. If set to not-zero anything
, the LED will be white. If set to 0 not-zero
, the LED will be amber. However, the file seems to have no valid range. It accepts any number, even >100 and negative numbers. And even 1 1
is confusing because it seems to be doing white + amber = white. The LED cannot mix white and amber together. It can only do white, amber, or off.
cros_ec-kbd-led-framework
Keyboard backlight works as normal, no "renamed" message.
Thanks for your tests!
It would be great to get some Tested-by tags for them on LKML. If you give me an email address I'll add you to Cc for future submissions. And you could test those formally, providing the Tested-by tag.
My email address is paranjperajas@gmail.com
I updated my comment
I tried setting it to AC-online ...
That one is a (very old) bug: https://lore.kernel.org/lkml/20240526-acpi-ac-changed-v1-1-f4b5997753bb@weissschuh.net/
Hi! Sorry for not replying so far, I'll also test the driver on my phaser360s. Thanks for your work! It might take some time as I'm a first time kernel patcher too.
Which version should I test? These on the mailing list, or an other set of them?
You mentioned a few other patches. Do those also apply for chromebooks? If so, I would patch whichever applies for my hardware.
@mpeter50 All of these changes are in Linus' master branch. If you try https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ you get everything without any manual patching. Just make sure to enable the "CHROMEOS EC" modules.
I must have made some mistake, because I dont see anything new in the /sys/class/power_supply/BAT0/
directory. For example there is no charge_behaviour
file, and the only writable files are alarm
and uevent
.
I'm testing on a KDE Neon installation,
I have got the kernel from here: git://git.launchpad.net/~ubuntu-kernel-test/ubuntu/+source/linux/+git/mainline-crack
At the time I have checked and as I remember I have found your patches in it.
For the rest, I have basically followed this Debian manual.
Checked out the v6.10 ref, edited the .config file
where necessary. I assumed you meant to enable the CONFIG_CROS_EC kernel config setting, I have left it as m
, in my understanding that enables it too.
This is the kernel config that I was using: https://gist.github.com/mpeter50/98df1a0d5f8804caab5567c273c81498
Then built the kernel by running make deb-pkg LOCALVERSION=-custom
.
The kernel was built, I grabbed the linux-image-6.10.0-custom_6.10.0-8_amd64.deb
from the outer directory, and put that on a pendrive.
Booted the KDE Neon system on by chromebook, installed the package with dpkg -i linux-image-6.10.0-custom_6.10.0-8_amd64.deb
. Other than a warning about the i915 module missing some firmware, there was no other complaint.
Then I booted to my main system, openSUSE Leap, and begged to the bootloader configurator to reconfigure GRUB, so that it gets the entry for KDE Neon's new kernel. When that was done, I have booted KDE Neon as normal. Some diagnostic info from it:
uname -a
Linux teszt-phaser360 6.10.0-custom #8 SMP PREEMPT_DYNAMIC Tue Jul 23 01:26:08 CEST 2024 x86_64 x86_64 x86_64 GNU/Linux
lsmod | grep cros
cros_ec_lid_angle 12288 0
cros_ec_sensors 12288 0
cros_ec_sensors_core 20480 2 cros_ec_sensors,cros_ec_lid_angle
industrialio_triggered_buffer 12288 2 cros_ec_lid_angle,cros_ec_sensors_core
kfifo_buf 12288 2 industrialio_triggered_buffer,cros_ec_sensors_core
industrialio 122880 5 industrialio_triggered_buffer,cros_ec_sensors,cros_ec_lid_angle,kfifo_buf,cros_ec_sensors_core
cros_usbpd_logger 16384 0
cros_usbpd_charger 24576 0
cros_ec_chardev 12288 0
cros_ec_sysfs 12288 0
cros_ec_sensorhub 36864 1 cros_ec_sensors_core
cros_ec_debugfs 12288 0
cros_usbpd_notify 20480 1 cros_usbpd_charger
cros_ec_dev 12288 0
cros_ec_keyb 20480 0
matrix_keymap 12288 1 cros_ec_keyb
cros_ec_lpcs 20480 0
cros_ec 20480 1 cros_ec_lpcs
ls -hal /sys/class/power_supply/BAT0/
total 0
drwxr-xr-x 4 root root 0 aug 24 07:40 .
drwxr-xr-x 3 root root 0 aug 24 07:40 ..
-rw-r--r-- 1 root root 4,0K aug 24 07:43 alarm
-r--r--r-- 1 root root 4,0K aug 24 07:40 capacity
-r--r--r-- 1 root root 4,0K aug 24 07:43 capacity_level
-r--r--r-- 1 root root 4,0K aug 24 07:40 charge_full
-r--r--r-- 1 root root 4,0K aug 24 07:40 charge_full_design
-r--r--r-- 1 root root 4,0K aug 24 07:40 charge_now
-r--r--r-- 1 root root 4,0K aug 24 07:40 current_now
-r--r--r-- 1 root root 4,0K aug 24 07:40 cycle_count
lrwxrwxrwx 1 root root 0 aug 24 07:43 device -> ../../../PNP0C0A:00
drwxr-xr-x 3 root root 0 aug 24 07:40 hwmon1
-r--r--r-- 1 root root 4,0K aug 24 07:40 manufacturer
-r--r--r-- 1 root root 4,0K aug 24 07:40 model_name
drwxr-xr-x 2 root root 0 aug 24 07:43 power
-r--r--r-- 1 root root 4,0K aug 24 07:40 present
-r--r--r-- 1 root root 4,0K aug 24 07:40 serial_number
-r--r--r-- 1 root root 4,0K aug 24 07:40 status
lrwxrwxrwx 1 root root 0 aug 24 07:40 subsystem -> ../../../../../../../../../class/power_supply
-r--r--r-- 1 root root 4,0K aug 24 07:40 technology
-r--r--r-- 1 root root 4,0K aug 24 07:40 type
-rw-r--r-- 1 root root 4,0K aug 24 07:40 uevent
-r--r--r-- 1 root root 4,0K aug 24 07:40 voltage_min_design
-r--r--r-- 1 root root 4,0K aug 24 07:40 voltage_now
By the output of lsmod, it looks to me it has loaded the cros kernel modules.
I also see devices like CROS_USBPD_CHARGER0
in /sys/class/power_supply/
, so I think the cros modules should be present and loaded.
What did I miss? If it cannot be known from the above, please let me know what should I do to get to know it.
uname -a Linux teszt-phaser360 6.10.0-custom #8 SMP PREEMPTDYNAMIC Tue Jul 23 01:26:08 CEST 2024 x8664 x8664 x8664 GNU/Linux
Should be 6.11.
Oh. Well, since then they have started releasing rc-s of 6.11, so I'll build the latest one, 6.11-rc4. It'll be easier now that I have done that once already :D
With 6.11 I see the control files, and KDE in the advanced power settings also shows the charging threshold controls. I'll try how it works here and will report back with the results.
All tests are executed with the original charger connected.
Test checklist: (this list will be updated in place)
Additional good-to-know tests:
When the charge controller was set to idle mode with the ectool on the other system, after rebooting to the test system /sys/class/power_supply/BAT0/charge_behaviour
says it is in auto
mode. Rebooting back to the other system, ectool chargecontrol
says thats in normal mode now.
Setting charge_behaviour
to inhibit-charge
results in current_now
going 0, and setting it to auto
results in it getting a positive value, so this indicates that charge inhibition works as expected.
Rebooting to the same system results in the charge_behaviour
being set to auto
. current_now
has a positive value at this point (charger is connected).
Rebooting to the old system results in the IDLE status being preserved, if the new system has set charge_behaviour
to inhibit-charge
. Rebooting back to the test system will result in the charge_behaviour
being set to auto
. current_now
has a positive value at this point (charger is connected).
force-discharge
mode works, it does not charge the battery when on charger.
start and end thresholds dont seem to work.
A minute ago I was on 90%, in force-discharge
mode. I have set charge_control_start_threshold
to 70, charge_control_end_threshold
to 85, charge_behaviour
to auto
(in this order), and now I'm on 92%.
I've taken the following steps to try and resolve the issue with setting battery charge thresholds on the Lenovo 500e 2nd Gen Chromebook (openSUSE Leap 15.4, Kernel 5.14.21):
Kernel Update:
Update the kernel to the latest stable version using the Kernel: stable repository: bash
sudo zypper ar -f http://download.opensuse.org/repositories/Kernel:/stable/standard/ kernel-repo sudo zypper ref sudo zypper in --from kernel-repo kernel-default sudo reboot After the reboot, the new kernel version is active. Checked for Sysfs Battery Control Files:
Navigated to the following: /sys/class/power_supply/ and found the battery directory (e.g., BAT0). However, charge_start_threshold and charge_stop_threshold files were still not present. Installed and Configured TLP (Optional):
Installed TLP to manage power settings: bash
sudo zypper install tlp sudo tlp-stat --battery Unfortunately, TLP does not support this device, confirming that battery charge control is not possible via TLP. Checked BIOS/UEFI Settings (Optional):
I entered the BIOS/UEFI settings but did not find any options for setting battery charge thresholds.
The outcome of this is that despite updating the kernel and checking all the possible configurations, the required sysfs files for battery charge control (charge_start_threshold, charge_stop_threshold) are not available. This indicates that this feature is not currently supported for this device under Linux. It may require specific driver support or a newer kernel release.
I've taken the following steps to try and resolve the issue with setting battery charge thresholds on the Lenovo 500e 2nd Gen Chromebook (openSUSE Leap 15.4, Kernel 5.14.21):
Kernel Update:
Update the kernel to the latest stable version using the Kernel: stable repository: bash
As far as I know, the feature is available in Linux 6.11
@anshshettyy
I'm also using leap 15.4 as my main OS, and this is expected. Leap maintains and uses very old kernels, as with almost everything else, and it will take some time (1-2 years?) until they will transition to the 6.11 version of the kernel.
You'll have to build a new kernel, from the sources of the 6.11 version, if you want to make use of t-8ch's additions.
I entered the BIOS/UEFI settings but did not find any options for setting battery charge thresholds.
If you are using the Coreboot firmware, yeah, thats very barebones, it does not have hardware-specific settings.
But also be aware, that currently these do not work properly:
charge_behaviour
is always reset to auto
when booting the system that has the new driver@mpeter50
Can you provide the output of sudo ectool cmdversions 0x0096
?
charge start and end tresholds
The work correctly when set via ectool, correct?
charge_behaviour is always reset to auto when booting the system that has the new driver
This is intentional. The kernel has no place to store the settings and read-back from the EC does not work.
Can you provide the output of
sudo ectool cmdversions 0x0096
?
Here it is:
$ sudo ectool cmdversions 0x0096
Command 0x96 supports version mask 0x00000006
charge start and end tresholds
The work correctly when set via ectool, correct?
Yes, it does. If I set up charge thresholds with ectool chargecontrol normal 80 85
, then it will start charging a little after it reached 79, and stop charging at around 85.
But, I always have had to issue the ectool chargecontrol normal
command twice if I also want to set the charge limits, when the charging mode wasn't already NORMAL before running the command. If I only do it once, despite passing the numbers, it does not get applied, and reading the status with ectool chargecontrol
will say this:
Charge mode = NORMAL (0)
Battery sustainer = off (-1% ~ -1%)
charge_behaviour is always reset to auto when booting the system that has the new driver
This is intentional. The kernel has no place to store the settings and read-back from the EC does not work.
Oh, I see. Would it be feasible to have a kernel parameter that can override the value it sets at startup? I would prefer to always have it in idle mode, instead of charging to 100% every time I reboot the system.
But also, which part of it does not work? The ectool
command can do that, I (relatively) frequently use it to see the current setting.
To be clear, I have answered all of the above according to the system that runs the old kernel.
But, I always have had to issue the ectool chargecontrol normal command twice if I also want to set the charge limits, when the charging mode wasn't already NORMAL before running the command.
That is very useful information. Let me cook up a patch for you to test that does the same for the driver.
Would it be feasible to have a kernel parameter that can override the value it sets at startup?
That would be possible, but why not use a custom script?
But also, which part of it does not work?
If charge limits are applied and normal mode is active, while charging is inhibited, ectool will show "IDLE" instead of normal. This is a mismatch with the kernel APIs.
@mpeter50 Can you try this:
diff --git a/drivers/power/supply/cros_charge-control.c b/drivers/power/supply/cros_charge-control.c
index 17c53591ce19..7313cbfc5f2e 100644
--- a/drivers/power/supply/cros_charge-control.c
+++ b/drivers/power/supply/cros_charge-control.c
@@ -84,6 +84,7 @@ static int cros_chctl_send_charge_control_cmd(struct cros_ec_device *cros_ec,
static int cros_chctl_configure_ec(struct cros_chctl_priv *priv)
{
struct ec_params_charge_control req = {};
+ int ret;
req.cmd = EC_CHARGE_CONTROL_CMD_SET;
@@ -111,6 +112,13 @@ static int cros_chctl_configure_ec(struct cros_chctl_priv *priv)
req.sustain_soc.upper = -1;
}
+ /* Some devices need the command to be sent twice to apply */
+ if (req.sustain_soc.lower != -1) {
+ ret = cros_chctl_send_charge_control_cmd(priv->cros_ec, priv->cmd_version, &req);
+ if (ret)
+ return ret;
+ }
+
return cros_chctl_send_charge_control_cmd(priv->cros_ec, priv->cmd_version, &req);
}
I wanted to set up limiting the charge level of the battery of my chromebook, so that it may remain useful for a longer time, but it seems currently it may not be possible.
So far I have found out that on Linux systems where the kernel supports controlling how the battery is charged, control and monitoring happens through virtual files of the power supply device class, in the sysfs file system, more specifically these (usually):
/sys/class/power_supply/<battery name>/charge_start_threshold
/sys/class/power_supply/<battery name>/charge_stop_threshold
<battery name>
is usually BAT0, but sometimes slightly different.Source is the Linux kernel documentation and this issue at a software's (TLP) repository that deals with power management of laptops on Linux systems.
However, on my system installation, these files do not exist, and the only writeable files in that directory are
alarm
anduevent
. The same is true for a live system I tried, which used kernel version 6.1.2. After installing TLP from the package manager, runningtlp-stat --battery
confirms that my device is not supported by this tool. The tool uses a standard Linux kernel mechanism for accessing battery information and control interfaces, so I suspect this also means that battery charge control is currently not supported by the system.Device model: Lenovo 500e 2nd Gen (Code name: Phaser360S, Board name: Octopus) Firmware: UEFI firmware 20221129 Kernel version: 5.14.21 Operating system: openSUSE Leap 15.4