OSDN Git Service

iio: adc: stm32: allow to tune analog clock
authorFabrice Gasnier <fabrice.gasnier@st.com>
Mon, 28 Oct 2019 16:11:48 +0000 (17:11 +0100)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Sat, 9 Nov 2019 12:37:18 +0000 (12:37 +0000)
Add new optional dt property to tune analog clock prescaler.
Driver looks for optional "st,max-clk-rate-hz", then computes
best approximation below that rate, using ADC internal prescaler.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/stm32-adc-core.c

index 20c626c..6537f4f 100644 (file)
@@ -79,6 +79,7 @@ struct stm32_adc_priv_cfg {
  * @domain:            irq domain reference
  * @aclk:              clock reference for the analog circuitry
  * @bclk:              bus clock common for all ADCs, depends on part used
+ * @max_clk_rate:      desired maximum clock rate
  * @booster:           booster supply reference
  * @vdd:               vdd supply reference
  * @vdda:              vdda analog supply reference
@@ -95,6 +96,7 @@ struct stm32_adc_priv {
        struct irq_domain               *domain;
        struct clk                      *aclk;
        struct clk                      *bclk;
+       u32                             max_clk_rate;
        struct regulator                *booster;
        struct regulator                *vdd;
        struct regulator                *vdda;
@@ -141,7 +143,7 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
        }
 
        for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
-               if ((rate / stm32f4_pclk_div[i]) <= priv->cfg->max_clk_rate_hz)
+               if ((rate / stm32f4_pclk_div[i]) <= priv->max_clk_rate)
                        break;
        }
        if (i >= ARRAY_SIZE(stm32f4_pclk_div)) {
@@ -230,7 +232,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
                        if (ckmode)
                                continue;
 
-                       if ((rate / div) <= priv->cfg->max_clk_rate_hz)
+                       if ((rate / div) <= priv->max_clk_rate)
                                goto out;
                }
        }
@@ -250,7 +252,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
                if (!ckmode)
                        continue;
 
-               if ((rate / div) <= priv->cfg->max_clk_rate_hz)
+               if ((rate / div) <= priv->max_clk_rate)
                        goto out;
        }
 
@@ -655,6 +657,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct device_node *np = pdev->dev.of_node;
        struct resource *res;
+       u32 max_rate;
        int ret;
 
        if (!pdev->dev.of_node)
@@ -731,6 +734,13 @@ static int stm32_adc_probe(struct platform_device *pdev)
        priv->common.vref_mv = ret / 1000;
        dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
 
+       ret = of_property_read_u32(pdev->dev.of_node, "st,max-clk-rate-hz",
+                                  &max_rate);
+       if (!ret)
+               priv->max_clk_rate = min(max_rate, priv->cfg->max_clk_rate_hz);
+       else
+               priv->max_clk_rate = priv->cfg->max_clk_rate_hz;
+
        ret = priv->cfg->clk_sel(pdev, priv);
        if (ret < 0)
                goto err_hw_stop;