power: regulator: stm32: vrefbuf: fix a possible overshoot when re-enabling
authorFabrice Gasnier <fabrice.gasnier@st.com>
Fri, 12 Jun 2020 08:40:58 +0000 (10:40 +0200)
committerPatrick Delaunay <patrick.delaunay@st.com>
Tue, 7 Jul 2020 14:01:23 +0000 (16:01 +0200)
There maybe an overshoot:
- when disabling, then re-enabling vrefbuf too quickly
- or upon platform reset as external capacitor maybe slow
  discharging (VREFBUF is HiZ at reset by default).
VREFBUF is used by ADC/DAC on some boards. An overshoot on the reference
voltage make the conversions inaccurate for a short period of time. So:
- Don't put the VREFBUF in HiZ when disabling, to force an active
  discharge.
- Enforce a 1ms OFF/ON delay, also upon reset

Penalty is a 1ms delay is applied (even for a cold boot), when enabling
VREFBUF.

Fixes: 93cf0ae7758d ("power: regulator: Add support for stm32-vrefbuf")

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
drivers/power/regulator/stm32-vrefbuf.c

index 2507735..9213696 100644 (file)
@@ -43,8 +43,20 @@ static int stm32_vrefbuf_set_enable(struct udevice *dev, bool enable)
        u32 val;
        int ret;
 
-       clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ | STM32_ENVR,
-                       enable ? STM32_ENVR : STM32_HIZ);
+       if (enable && !(readl(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR)) {
+               /*
+                * There maybe an overshoot:
+                * - when disabling, then re-enabling vrefbuf too quickly
+                * - or upon platform reset as external capacitor maybe slow
+                *   discharging (VREFBUF is HiZ at reset by default).
+                * So force active discharge (HiZ=0) for 1ms before enabling.
+                */
+               clrbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ);
+               udelay(1000);
+       }
+
+       clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_ENVR,
+                       enable ? STM32_ENVR : 0);
        if (!enable)
                return 0;