summaryrefslogtreecommitdiffstats
path: root/rbutil/mkimxboot/dualboot
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2014-01-21 19:01:34 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2014-01-21 19:01:34 +0100
commit6022d3100a31266d48d89c4eaa562ed58a1f1909 (patch)
treeceb650f475fffd661ae8ccef62f905e967cee742 /rbutil/mkimxboot/dualboot
parentcddf388f766adce344b3a45c05c33121e9d68873 (diff)
downloadrockbox-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.c38
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: