diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-01-21 19:01:34 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-01-21 19:01:34 +0100 |
commit | 6022d3100a31266d48d89c4eaa562ed58a1f1909 (patch) | |
tree | ceb650f475fffd661ae8ccef62f905e967cee742 /rbutil/mkimxboot/dualboot | |
parent | cddf388f766adce344b3a45c05c33121e9d68873 (diff) | |
download | rockbox-6022d3100a31266d48d89c4eaa562ed58a1f1909.tar.gz rockbox-6022d3100a31266d48d89c4eaa562ed58a1f1909.zip |
mkimxboot: tool can now recreate a stub to recover from very low battery
Several devices, including the Fuze+ have great trouble recovering from
very low battery states, even in the presence of USB power. This is partly
due to buggy Sigmatel boot stubs and Rockbox bootloader doing unsafe power
operations on boot (should be fixed soon). In such a state, it is impossible
to boot either the OF and Rockbox, so only the recovery mode is available.
With this commit, mkimxboot can now create a very small stub which only
does one thing but does it well: setup charging to recover from any situation.
It does not provide a fancy charging screen or whatever, screen will just
stay black and the device will slowly charge at ~100mA. When the battery is
back to a normal level, just unplug and boot normally.
Change-Id: Ib50880af85ed1f4f64a7eed0f2221e73c889c351
Diffstat (limited to 'rbutil/mkimxboot/dualboot')
-rw-r--r-- | rbutil/mkimxboot/dualboot/dualboot.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/rbutil/mkimxboot/dualboot/dualboot.c b/rbutil/mkimxboot/dualboot/dualboot.c index e841b12d74..0e3cca2bd9 100644 --- a/rbutil/mkimxboot/dualboot/dualboot.c +++ b/rbutil/mkimxboot/dualboot/dualboot.c @@ -22,10 +22,13 @@ #include "regs-power.h" #include "regs-lradc.h" #include "regs-digctl.h" +#include "regs-clkctrl.h" #define BOOT_ROM_CONTINUE 0 /* continue boot */ #define BOOT_ROM_SECTION 1 /* switch to new section *result_id */ +#define BOOT_ARG_CHARGE ('c' | 'h' << 8 | 'r' << 16 | 'g' << 24) + typedef unsigned long uint32_t; // target specific boot context @@ -225,8 +228,43 @@ static inline enum context_t get_context(void) #endif } +/** + * Charging function + */ +static inline void do_charge(void) +{ + BF_CLR(LRADC_CTRL0, SFTRST); + BF_CLR(LRADC_CTRL0, CLKGATE); + BF_WRn(LRADC_DELAYn, 0, TRIGGER_LRADCS, 0x80); + BF_WRn(LRADC_DELAYn, 0, TRIGGER_DELAYS, 0x1); + BF_WRn(LRADC_DELAYn, 0, DELAY, 200); + BF_SETn(LRADC_DELAYn, 0, KICK); + BF_SET(LRADC_CONVERSION, AUTOMATIC); + BF_WR_V(LRADC_CONVERSION, SCALE_FACTOR, LI_ION); + BF_WR(POWER_CHARGE, STOP_ILIMIT, 1); + BF_WR(POWER_CHARGE, BATTCHRG_I, 0x10); + BF_CLR(POWER_CHARGE, PWD_BATTCHRG); +#if IMX233_SUBTARGET >= 3780 + BF_WR(POWER_DCDC4P2, ENABLE_4P2, 1); + BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2); + BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT, 0x10); +#endif + while(1) + { + BF_WR(CLKCTRL_CPU, INTERRUPT_WAIT, 1); + asm volatile ( + "mcr p15, 0, %0, c7, c0, 4 \n" /* Wait for interrupt */ + "nop\n" /* Datasheet unclear: "The lr sent to handler points here after RTI"*/ + "nop\n" + : : "r"(0) + ); + } +} + int main(uint32_t arg, uint32_t *result_id) { + if(arg == BOOT_ARG_CHARGE) + do_charge(); switch(boot_decision(get_context())) { case BOOT_ROCK: |