ToastBucket
Very Active Member
So what are the options? One is loading it in the initramfs (which I think it loaded by the bootloader or something rather close to it) and the other is doing it in the bootloader itself? I guess doing it in the initramfs will be slower to start charging, because it need to load the initramfs of a potentially slow SD card, but then again the initramfs is only in the order to 8MiB or so I assume, which could take as long as two seconds on an old class 4 card but in all likelihood probably won't. But I'm still tending to support the idea of doing it from the bootloader, because it seems simpler.
Boot process is as follows:
1. USB power is presented on microUSB or the power key is pressed. This causes the PMIC to begin its powerup procedure. It is unavoidable that both of these events trigger a powerup, that is how the hardware is configured.
2. BootROM begins executing and tries to locate the SPL (primary bootloader). If it finds it, it loads it into OCRAM and jumps to the start vector. It will first search the left SD slot, then eMMC/uSD.
3. SPL does basic device configuration setting up some necessary clocks and most importantly configure the SDRAM and load the full bootloader U-Boot into SDRAM and jump. I've modified the SPL to also reset the charger chip and bump up the input current limit to 3A at this point. While the SPL is running, most of the system is off and the SOC is running at a low clock speed. This keeps us under the 500mA limit which is the default input current limit on the charger chip. Once this is bumped up, we are safe to turn on other devices and start consuming more power.
4. U-Boot does all configuration of the SOC necessary for booting, loads the kernel, initramfs, and device tree into RAM and jumps to the kernel start vector. It does some other boring but important stuff, like check the HW revision number to load the right device tree, handle some logic for the eMMC/uSD, and further configure the charger chip/PMIC.
The two options for handling the charging without booting are:
1. Handle charging in the bootloader. If we detect the battery is below some threshold (read the fuel gauge chip) or that we have not booted by user request (warm reset or power button), then we can sit and hang in the bootloader after we've configured the charger. Here we can display the charge level by modifying the color of an LED (red=low, orange=ok, green=good). In the future, I could potentially append this to have display feedback depending on level of effort and priorities (or someone else can do it too ). While in this state, if the user presses the power key and we are above charge threshold, we will continue to boot (at this point we have not loaded the kernel). Otherwise we hang here, periodically checking the battery level and status of the power input (power off if removed). In this state, we will be consuming less power than with a fully or partially booted kernel, as most things are still turned off. (though we may have some things turned on and unconfigured, which may be worse. need to check this out).
2. Handle charging in the initramfs. When we boot the kernel, the initramfs is used as a filesystem before mounting the actual rootfs. There are some configuration scripts which run here, but the kernel is fully booted with the exception of kernel modules. We could add a script which checks the battery level and halts the process if we are below threshold until we are above. At this point we have the benefit of most kernel drivers up and running, so we can (I believe) do display feedback out of the box and we'll be running with the full kernel driver for the fuel gauge and charger chip rather than the minimalistic ones in the bootloader. However, we need to fully boot the kernel (just the kernel, not the OS) to get to this point. Also to make use of this feature, you must be using our initramfs. The initramfs is not necessary and some users may use a custom boot process which bypasses this.
Option one is currently WIP. Option 2 I hadn't considered until this conversation.