arm: exynos: Wait till ADC stabilizes before checking Odroid HC1 revision
authorKrzysztof Kozlowski <krzk@kernel.org>
Wed, 6 Mar 2019 18:37:53 +0000 (19:37 +0100)
committerMinkyu Kang <mk7.kang@samsung.com>
Mon, 11 Mar 2019 06:53:19 +0000 (15:53 +0900)
Fix detection of Odroid HC1 (Exynos5422) after reboot if kernel disabled
the LDO4/VDD_ADC regulator.

The LDO4 supplies both ADC block and the ADC input AIN9.  Voltage on
AIN9 will rise slowly, so use delay of 5 milliseconds instead of
timers-based loop to wait for voltage stabilization.

First reads on Odroid HC1 return 305, 1207, 1297 and finally 1308
(reference value is 1309).

Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Tested-by: Anand Moon <linux.amoon@gmail.com>
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
board/samsung/common/exynos5-dt-types.c

index 7c1271d6547ac83480bb721357f13c13cf78e9bf..516c32923e44df5f78d5cb165234569364ae7397 100644 (file)
@@ -57,12 +57,48 @@ static unsigned int odroid_get_rev(void)
        return 0;
 }
 
+/*
+ * Read ADC at least twice and check the resuls.  If regulator providing voltage
+ * on to measured point was just turned on, first reads might require time
+ * to stabilize.
+ */
+static int odroid_get_adc_val(unsigned int *adcval)
+{
+       unsigned int adcval_prev = 0;
+       int ret, retries = 20;
+
+       ret = adc_channel_single_shot("adc", CONFIG_ODROID_REV_AIN,
+                                     &adcval_prev);
+       if (ret)
+               return ret;
+
+       while (retries--) {
+               mdelay(5);
+
+               ret = adc_channel_single_shot("adc", CONFIG_ODROID_REV_AIN,
+                                             adcval);
+               if (ret)
+                       return ret;
+
+               /*
+                * If difference between ADC reads is less than 3%,
+                * accept the result
+                */
+               if ((100 * abs(*adcval - adcval_prev) / adcval_prev) < 3)
+                       return ret;
+
+               adcval_prev = *adcval;
+       }
+
+       return ret;
+}
+
 static int odroid_get_board_type(void)
 {
        unsigned int adcval;
        int ret, i;
 
-       ret = adc_channel_single_shot("adc", CONFIG_ODROID_REV_AIN, &adcval);
+       ret = odroid_get_adc_val(&adcval);
        if (ret)
                goto rev_default;