diff --git a/firmware/target/arm/imx233/power-imx233.c b/firmware/target/arm/imx233/power-imx233.c index c02d6ddb77..186256f7b8 100644 --- a/firmware/target/arm/imx233/power-imx233.c +++ b/firmware/target/arm/imx233/power-imx233.c @@ -102,6 +102,8 @@ void power_init(void) __FIELD_SET(HW_POWER_VDDDCTRL, LINREG_OFFSET, 2); __FIELD_SET(HW_POWER_VDDACTRL, LINREG_OFFSET, 2); __FIELD_SET(HW_POWER_VDDIOCTRL, LINREG_OFFSET, 2); + /* enable DCDC (more efficient) */ + __REG_SET(HW_POWER_5VCTRL) = HW_POWER_5VCTRL__ENABLE_DCDC; /* enable a few bits controlling the DC-DC as recommended by Freescale */ __REG_SET(HW_POWER_LOOPCTRL) = HW_POWER_LOOPCTRL__TOGGLE_DIF | HW_POWER_LOOPCTRL__EN_CM_HYST; @@ -250,6 +252,8 @@ void imx233_power_set_regulator(enum imx233_regulator_t reg, unsigned value_mv, // compute raw values unsigned raw_val = (value_mv - regulator_info[reg].min) / regulator_info[reg].step; unsigned raw_bo_offset = (value_mv - brownout_mv) / regulator_info[reg].step; + // clear dc-dc ok flag + __REG_SET(HW_POWER_CTRL) = HW_POWER_CTRL__DC_OK_IRQ; // update uint32_t reg_val = (*regulator_info[reg].reg) & ~regulator_info[reg].trg_bm; reg_val |= raw_val << regulator_info[reg].trg_bp; @@ -259,6 +263,17 @@ void imx233_power_set_regulator(enum imx233_regulator_t reg, unsigned value_mv, reg_val |= raw_bo_offset << regulator_info[reg].bo_bp; } *regulator_info[reg].reg = reg_val; + /* Wait until regulator is stable (ie brownout condition is gone) + * If DC-DC is used, we can use the DCDC_OK irq + * Otherwise it is unreliable (doesn't work when lowering voltage on linregs) + * It usually takes between 0.5ms and 2.5ms */ + if(!(HW_POWER_5VCTRL & HW_POWER_5VCTRL__ENABLE_DCDC)) + panicf("regulator %d: wait for voltage stabilize in linreg mode !", reg); + unsigned timeout = current_tick + (HZ * 20) / 1000; + while(!(HW_POWER_CTRL & HW_POWER_CTRL__DC_OK_IRQ) || !TIME_AFTER(current_tick, timeout)) + yield(); + if(!(HW_POWER_CTRL & HW_POWER_CTRL__DC_OK_IRQ)) + panicf("regulator %d: failed to stabilize", reg); } // offset is -1,0 or 1 diff --git a/firmware/target/arm/imx233/power-imx233.h b/firmware/target/arm/imx233/power-imx233.h index 6991fde7b2..786a450972 100644 --- a/firmware/target/arm/imx233/power-imx233.h +++ b/firmware/target/arm/imx233/power-imx233.h @@ -31,6 +31,8 @@ #define HW_POWER_CTRL__ENIRQ_VBUS_VALID (1 << 3) #define HW_POWER_CTRL__VBUSVALID_IRQ (1 << 4) #define HW_POWER_CTRL__POLARITY_VBUSVALID (1 << 5) +#define HW_POWER_CTRL__ENIRQ_DC_OK (1 << 14) +#define HW_POWER_CTRL__DC_OK_IRQ (1 << 15) #define HW_POWER_5VCTRL (*(volatile uint32_t *)(HW_POWER_BASE + 0x10)) #define HW_POWER_5VCTRL__ENABLE_DCDC (1 << 0) @@ -191,6 +193,7 @@ enum imx233_regulator_t void imx233_power_get_regulator(enum imx233_regulator_t reg, unsigned *target_mv, unsigned *brownout_mv); +// WARNING this call will block until voltage is stable void imx233_power_set_regulator(enum imx233_regulator_t reg, unsigned target_mv, unsigned brownout_mv);