iio: adc: stm32-adc: adapt clock duty cycle for proper operation
[linux-2.6-microblaze.git] / drivers / iio / adc / stm32-adc-core.c
index 0e2068e..d64a9e8 100644 (file)
@@ -202,7 +202,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
 {
        u32 ckmode, presc, val;
        unsigned long rate;
-       int i, div;
+       int i, div, duty;
 
        /* stm32h7 bus clock is common for all ADC instances (mandatory) */
        if (!priv->bclk) {
@@ -226,6 +226,11 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
                        return -EINVAL;
                }
 
+               /* If duty is an error, kindly use at least /2 divider */
+               duty = clk_get_scaled_duty_cycle(priv->aclk, 100);
+               if (duty < 0)
+                       dev_warn(&pdev->dev, "adc clock duty: %d\n", duty);
+
                for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
                        ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
                        presc = stm32h7_adc_ckmodes_spec[i].presc;
@@ -234,6 +239,13 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
                        if (ckmode)
                                continue;
 
+                       /*
+                        * For proper operation, clock duty cycle range is 49%
+                        * to 51%. Apply at least /2 prescaler otherwise.
+                        */
+                       if (div == 1 && (duty < 49 || duty > 51))
+                               continue;
+
                        if ((rate / div) <= priv->max_clk_rate)
                                goto out;
                }
@@ -246,6 +258,10 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
                return -EINVAL;
        }
 
+       duty = clk_get_scaled_duty_cycle(priv->bclk, 100);
+       if (duty < 0)
+               dev_warn(&pdev->dev, "bus clock duty: %d\n", duty);
+
        for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) {
                ckmode = stm32h7_adc_ckmodes_spec[i].ckmode;
                presc = stm32h7_adc_ckmodes_spec[i].presc;
@@ -254,6 +270,9 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
                if (!ckmode)
                        continue;
 
+               if (div == 1 && (duty < 49 || duty > 51))
+                       continue;
+
                if ((rate / div) <= priv->max_clk_rate)
                        goto out;
        }
@@ -582,11 +601,9 @@ static int stm32_adc_core_switches_probe(struct device *dev,
        priv->syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
        if (IS_ERR(priv->syscfg)) {
                ret = PTR_ERR(priv->syscfg);
-               if (ret != -ENODEV) {
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(dev, "Can't probe syscfg: %d\n", ret);
-                       return ret;
-               }
+               if (ret != -ENODEV)
+                       return dev_err_probe(dev, ret, "Can't probe syscfg\n");
+
                priv->syscfg = NULL;
        }
 
@@ -596,12 +613,9 @@ static int stm32_adc_core_switches_probe(struct device *dev,
                priv->booster = devm_regulator_get_optional(dev, "booster");
                if (IS_ERR(priv->booster)) {
                        ret = PTR_ERR(priv->booster);
-                       if (ret != -ENODEV) {
-                               if (ret != -EPROBE_DEFER)
-                                       dev_err(dev, "can't get booster %d\n",
-                                               ret);
-                               return ret;
-                       }
+                       if (ret != -ENODEV)
+                               return dev_err_probe(dev, ret, "can't get booster\n");
+
                        priv->booster = NULL;
                }
        }
@@ -612,11 +626,9 @@ static int stm32_adc_core_switches_probe(struct device *dev,
                priv->vdd = devm_regulator_get_optional(dev, "vdd");
                if (IS_ERR(priv->vdd)) {
                        ret = PTR_ERR(priv->vdd);
-                       if (ret != -ENODEV) {
-                               if (ret != -EPROBE_DEFER)
-                                       dev_err(dev, "can't get vdd %d\n", ret);
-                               return ret;
-                       }
+                       if (ret != -ENODEV)
+                               return dev_err_probe(dev, ret, "can't get vdd\n");
+
                        priv->vdd = NULL;
                }
        }
@@ -669,42 +681,24 @@ static int stm32_adc_probe(struct platform_device *pdev)
        priv->common.phys_base = res->start;
 
        priv->vdda = devm_regulator_get(&pdev->dev, "vdda");
-       if (IS_ERR(priv->vdda)) {
-               ret = PTR_ERR(priv->vdda);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(&pdev->dev, "vdda get failed, %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(priv->vdda))
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->vdda),
+                                    "vdda get failed\n");
 
        priv->vref = devm_regulator_get(&pdev->dev, "vref");
-       if (IS_ERR(priv->vref)) {
-               ret = PTR_ERR(priv->vref);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(&pdev->dev, "vref get failed, %d\n", ret);
-               return ret;
-       }
+       if (IS_ERR(priv->vref))
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->vref),
+                                    "vref get failed\n");
 
-       priv->aclk = devm_clk_get(&pdev->dev, "adc");
-       if (IS_ERR(priv->aclk)) {
-               ret = PTR_ERR(priv->aclk);
-               if (ret != -ENOENT) {
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(&pdev->dev, "Can't get 'adc' clock\n");
-                       return ret;
-               }
-               priv->aclk = NULL;
-       }
+       priv->aclk = devm_clk_get_optional(&pdev->dev, "adc");
+       if (IS_ERR(priv->aclk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->aclk),
+                                    "Can't get 'adc' clock\n");
 
-       priv->bclk = devm_clk_get(&pdev->dev, "bus");
-       if (IS_ERR(priv->bclk)) {
-               ret = PTR_ERR(priv->bclk);
-               if (ret != -ENOENT) {
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(&pdev->dev, "Can't get 'bus' clock\n");
-                       return ret;
-               }
-               priv->bclk = NULL;
-       }
+       priv->bclk = devm_clk_get_optional(&pdev->dev, "bus");
+       if (IS_ERR(priv->bclk))
+               return dev_err_probe(&pdev->dev, PTR_ERR(priv->bclk),
+                                    "Can't get 'bus' clock\n");
 
        ret = stm32_adc_core_switches_probe(dev, priv);
        if (ret)
@@ -794,6 +788,13 @@ static int stm32_adc_core_runtime_resume(struct device *dev)
 {
        return stm32_adc_core_hw_start(dev);
 }
+
+static int stm32_adc_core_runtime_idle(struct device *dev)
+{
+       pm_runtime_mark_last_busy(dev);
+
+       return 0;
+}
 #endif
 
 static const struct dev_pm_ops stm32_adc_core_pm_ops = {
@@ -801,7 +802,7 @@ static const struct dev_pm_ops stm32_adc_core_pm_ops = {
                                pm_runtime_force_resume)
        SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend,
                           stm32_adc_core_runtime_resume,
-                          NULL)
+                          stm32_adc_core_runtime_idle)
 };
 
 static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {