[TRACKING] Battery flipping between charging and discharging / Draws from battery even on AC

Input prochot exacerbates battery flipping and causing massive performance hit while P3T minimizes battery flipping with very minor performance impact. Swapping is the correct design choice. I genuinely don’t understand why the EC was designed in this way, setting prochot before P3T not the other way round.

Only if it gets hit which isn’t really possible with the stock ec without manually modifying input power (and in standalone where it is kinda vital).

Those are 2 quite different things.

Ok I think I was able to reproduce it using the stock bios 3.09 ec and a 65W pd power supply (I don’t have anything 60W).

I fired up avorion (pretty much exclusively cause it has a built in frametime graph) and when I set the input current to 3300 the frametimes go in the toilet. Nothing really happens on a 100W psu when I set it to 5000 or 5200.

With my changes it doesn’t do that even when running on a 20W, though the fps are rock bottom cause I reduced the min power limit and with a 20W charger that gets rediculous XD.

Be careful with the “is_full”. It does not mean what you think it does. It is a failure mode of the battery that it attempts to recover from.

Yeah figured as much.

Can’t really get enough of an overview on the charge limit logic to figure out how to tell that it “thinks it’s full” to set vsys other than the whole idle state thing that I also don’t fully understand.

Untimately it just needs to stop doing the weird vsys voltage dance when it has finished charging which this change seems to do as far as I can tell.

There is an experimental diff that sets vsys to desired voltage if you wish to change it. I have not tested it though.

diff --git a/common/charge_state.c b/common/charge_state.c
index 500ad22b73..50b825cc00 100644
--- a/common/charge_state.c
+++ b/common/charge_state.c
@@ -487,8 +487,10 @@ int charge_request(bool use_curr, bool is_full)
                 * otherwise the BGATE FET body diode would conduct and
                 * discharge the battery.
                 */
                voltage = charger_closest_voltage(
-                       curr.batt.voltage + charger_get_info()->voltage_step);
+                       curr.batt.desired_voltage);
                /* If the battery is full, request the max voltage. */
                if (is_full)
                        voltage = battery_get_info()->voltage_max;

That is what I based mine on, I however didn’t want to set it to max all the time but only when charging is done to not disturb whatever the hell this complex voltage stepping stuff was for in the first place.

Was searching for P3T in the EC firmware code on GitHub and couldn’t find anything. Where in the codebase is that power limit referenced?

zephyr/program/framework/azalea/src/cpu_power.c

Also looks like there are sideefects for setting that lower, when I tried my 45W powerbank the soc refused to draw more than 11W under stress despite every limit I was able to check being 30+. Gotta investigate further, with the 100W psu it was fine and it does 43W continuously like before.

Ok I modified the math so it caps P3T to a minimum of 89W like it would get on battery and the mystery throttling is gone but I still see no dipping into battery when doing the firefox refresh test even on a 30W psu.

Looking pretty good so far. I wonder what that mystery throttling is though.

It would be really great if we could get someone from FW in here with the knowledge on why stuff was done this way.

It’s quite frustrating to see y’all guess what the code does, when FW could quite easily collaborate with the community here. Save frustration on community side, save expensive engineer time on FW side.

(and just a giant thanks to everyone debugging this, especially @James3 )

3 Likes

[Me as an end-user] Is that why I seem to be getting different CPU performance at different battery levels even when plugged in?

…to see that Framework has left the community to work on / fix this.

Framework, you shou…

I guess “should” is the operative word here…

1 Like

Reviewed the cpu_power.c code. Comparing the code to the PPT table I posted before, it appears the AMD CPU PPT limits for each power mode in Fedora are set by the update_os_power_slider function. My FW13 laptop has the 61Wh battery, FWIW.

If SPPT is short package power tracking (sustained load average power limit), and FPPT is fast package power tracking (short-term boost load power limit), perhaps P3T stands for peak package power tracking? Or in other words, the max instantaneous power the CPU is ever allowed to draw. Not sure how this CPU limit is enforced by the system, though.

In all three power modes, the update_os_power_slider code indicates P3T is set to 80W. This would line up with the CPU peak power draw limit James3 posted about previously.

Not sure what the thought process would be behind allowing the CPU peak power draw to reach a value exceeding what the stock charger can ever provide. I’m now also wondering if the P3T limit of 80W shows up anywhere in the sudo ryzenadj --dump-table output.

I’m also curious about under what conditions the CPU limits from the update_adapter_power_limit function come into effect. Perhaps for situations where a recognized power mode isn’t active?

With a battery present and charger plugged in, the conditions for setting power limits in update_adapter_power_limit depend on both the current battery charge level (battery_percent) and the plugged-in charger rating (active_mpower). Notably, the P3T limit is set to at least a minimum of 89W in all cases with a battery present, which is higher than the 80W P3T limit in update_os_power_slider.

Why the difference? I would think you’d want the P3T setpoint to be consistent in both functions.

Quite likely.

I have not seen the slider function actually used, all the actually set values (confirmed using cpupower on the ccd) seem to be coming from “update_adapter_power_limit”, though I do not use fedora or a power slider. I don’t know of another way to read back P3T.

Something like that was my initial guess but after seeing how it behaves it may be something more abstract.

Performance probably, seeing the quite severe mystery throttling that happens if you go lower with P3T I have some idea why they did it XD.

Potentially but I have not found a complete documentation of the msrs.

Not sure, those values may have been experimentally determined. I found setting P3T to 58500 (for 65W) or 40500 (for 45W) massively kneecapped performance which would be kind of a problem if you sell it with a 65W psu (or nothing).

I may try what happens if I set the P3T values in “update_adapter_power_limit” to the ones from “update_os_power_slider”.

Can you adjust these values in smokeless?

Which ones?

I fully reset my smokeless fuckery before I started messing with the ec.

P3T and input current prochot

Pt3 I don’t think so, I also have not found it in ryzenadj but it is possible it is somehow overridable in smokeless as it is a setting of the soc.

Input current prochot definitely not, the soc is not involved in that. It’s a setting on the charge controller set by the ec. It may be possible to tell the soc to ignore prochot but that is a really bad idea in my opinion (prochot can also come from overheating vrms and stuff like that whcih you really would not want to ignore).

From my understanding of this paragraph, if the input current reaches PD capacity, EC will tell the SoC to pull the emergency brake as if the VRMs is overheating.