Implement Apple Silicon Support (there is a way!)
godly-devotion opened this issue ยท 19 comments
Although it was not known before, there is now a way to support Apple Silicon based MacBooks due to the hard work over at another similar project.
Code: AppHouseKitchen/AlDente-Charge-Limiter@77119a1#diff-49a0a057547a2cf2e243b33525c55136dd7c41fc9fb133bed10746e349bda1ff
Discussion: AppHouseKitchen/AlDente-Charge-Limiter#52
Hopefully, it can eventually be implemented in bclm
as well.
In the (linked) long discussion, this is the first comment, where the new SMC key CH0B
first was mentioned: AppHouseKitchen/AlDente-Charge-Limiter#52 (comment) (see also the following).
As it seems (according to this discussion), writing 00
into SMC key CH0B
enables charging and writing 02
disables charging.
This is also the way AlDente seems to use, see this line: https://github.com/davidwernhart/AlDente/blob/0abfeafbd2232d16116c0fe5a6fbd0acb6f9826b/AlDente/Helper.swift#L227
Also the behaviour seems to be different than the current BCLM
value where you set a charging maximum value (and let the charging logic decide when to turn actually on or off charging). This new CH0B
seems to directly simply turn on/off charging (at any level).
@johnzweng so you have some resources on how SMC
values are written? If this repo stagnates I could write a script to do something similar.
Apologies for not getting around to this sooner. Looking at the changes, am I correct that for M1 we are only able to enable/disable charging as opposed to Intel where we set a max charging value? These seem like unrelated ideas to me. If so, is there really a reason to enable/disable charging manually, especially without something polling battery percentage?
Apologies for not getting around to this sooner.
Never apologise for open source work :)
Looking at the changes, am I correct that for M1 we are only able to enable/disable charging as opposed to Intel where we set a max charging value?
Can't speak for @johnzweng but I am solidly not this familiar with how macs manage their hardware.
I can help with a digest of the above thread though:
TL;DR: Aldente thread
My cursory read:
pmset -g batt
is able to read battery/charge state.
Setting CH0C
to 01
stops charging (but retains adapter power usage) and 00
continues charging. But for some reason Aldente uses the CH0B
key. Not sure what the difference is. convo source.
This script shared by @thloh85 illustrated a potential approach:
while [ true ];
do
BATT_PERCENT=`pmset -g batt | tail -n1 | awk '{print $3}' | sed s:\%\;::`
echo Battery percent : $BATT_PERCENT
if [ $BATT_PERCENT -ge 43 ]; then
./smc -k CH0C -w 01
else
./smc -k CH0C -w 00
fi
sleep 60
done
@joelucid made a GUI app here.
It appears Aldente does have to force the system into an awake state:
@inprealpha From my knowledge, it is not possible for an application to get any CPU time while the system is asleep. Since this necessary for the M1 version because charge has to be inhibited in just the right moment, AlDente stops the System from going to sleep until the desired value is reached. This is done using IOPMAssertions. source
@zackelia how would you feel about using the above info to simply include a "enable/disable charging" toggle?
I think many M1 users such as myself would already be very happy to be able to do that from CLI.
In case anyone finds it useful, I made a little open source tool that adds the following CLI commands:
battery charging on
: sets CH0B to 00 (allow charging)
battery charging off
: sets CH0B to 02 (disallow charging)
Open source and without warranty.
From my knowledge, it is not possible for an application to get any CPU time while the system is asleep.
If you can trigger a dark wake I think you will get cpu time then. I have a suspicion that when native battery optimization is enabled, there is a periodic wake up scheduled at which point the charging state is changed.
But this seems like a worse design from a hardware perspective compared to the older behavior where the SMC could manage the target charge state... no idea what Apple was thinking.
Just something I discovered while looking into Asahi Linux (source):
/*
* CH0I/CH0C are "hard" controls that will allow the battery to run down to 0.
* CH0K/CH0B are "soft" controls that are reset to 0 when SOC drops below 50%;
* we don't expose these yet.
*/
These could be useful for the bclm tool I guess.
Oooh @aykevl that is super cool to know. I'm currently writing both values, but it sounds like CH0C
is the "master switch" for practical purposes?
Also do you know by heart the function of CH0I
and CH0K
?
I really don't know, I just looked through the Linux kernel source to make an AlDente equivalent for Linux (haven't done that yet, but I did find the values exposed in /sys
so it should be simple). The Apple Silicon wizard here is @marcan.
while [ true ]; do BATT_PERCENT=`pmset -g batt | tail -n1 | awk '{print $3}' | sed s:\%\;::` echo Battery percent : $BATT_PERCENT if [ $BATT_PERCENT -ge 43 ]; then ./smc -k CH0C -w 01 else ./smc -k CH0C -w 00 fi sleep 60 done
Thanks for this tip, I've been using this manually to just toggle charging. It works well.
It seems that for Apple Silicon chips, we are only able to enable/disable charging. A polling solution would be required which would be quite different to how bclm behaves currently. As well, ince other tooling seems to have been developed and optimized battery charging exists for Apple Silicon, it doesn't make sense to me to add it to bclm.
It seems that for Apple Silicon chips, we are only able to enable/disable charging. A polling solution would be required which would be quite different to how bclm behaves currently. As well, ince other tooling seems to have been developed and optimized battery charging exists for Apple Silicon, it doesn't make sense to me to add it to bclm.
Now there is a solution for Apple Silicon, see a naive implementation here using CHWA
flag. It sets a 80% (fixed) limit managed by the firmware that is maintained while sleeping. Kudos to Asahi team
Now there is a solution for Apple Silicon, see a naive implementation here using
CHWA
flag.
Thanks @double-thinker for calling my attention to this! While the key does not take a specified value like BCLM
, I believe this is an acceptable compromise that fits well into the original model of bclm
. This is a much better path forward for Apple Silicon and I am willing to implement this.
Since last update, I now have Apple Silicon hardware which will expedite development and testing. Expect updates in the coming days. Reopening this issue.
Apple silicon support implemented via CHWA in release v0.1.0.
"support for Apple ARM M1":
Would this by chance also support ARM M2?
@seamusdemora While I have only personally tested it on an M1 chip, I see no reason why it wouldn't work on M2. If it doesn't work, please let know so I can document that!
roger that!