summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/imx233/power-imx233.c15
-rw-r--r--firmware/target/arm/imx233/power-imx233.h3
2 files changed, 18 insertions, 0 deletions
diff --git a/firmware/target/arm/imx233/power-imx233.c b/firmware/target/arm/imx233/power-imx233.c
index c02d6dd..186256f 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 6991fde..786a450 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);