[1/8] iio: adc: stm32-dfsdm: make spi_master_freq more accurate
diff mbox series

Message ID 1551862524-25098-2-git-send-email-fabrice.gasnier@st.com
State Superseded
Headers show
Series
  • iio: adc: stm32-dfsdm: add buffer modes
Related show

Commit Message

Fabrice Gasnier March 6, 2019, 8:55 a.m. UTC
When SPI clock isn't accurate, 'spi_master_freq' is filled in with
expected frequency. Use computed value instead:
- e.g. source clock / (CKOUTDIV + 1)
Also, current divider may be set to value that makes CKOUT to exceed
spi-max-frequency. Rather use lower value (e.g. round up divider when
ckout isn't accurate).

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
 drivers/iio/adc/stm32-dfsdm-core.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

Comments

Jonathan Cameron March 10, 2019, 10:09 a.m. UTC | #1
On Wed, 6 Mar 2019 09:55:17 +0100
Fabrice Gasnier <fabrice.gasnier@st.com> wrote:

> When SPI clock isn't accurate, 'spi_master_freq' is filled in with
> expected frequency. Use computed value instead:
> - e.g. source clock / (CKOUTDIV + 1)
> Also, current divider may be set to value that makes CKOUT to exceed
> spi-max-frequency. Rather use lower value (e.g. round up divider when
> ckout isn't accurate).
> 
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
> ---
>  drivers/iio/adc/stm32-dfsdm-core.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
> index bf089f5..65b7556 100644
> --- a/drivers/iio/adc/stm32-dfsdm-core.c
> +++ b/drivers/iio/adc/stm32-dfsdm-core.c
> @@ -243,13 +243,18 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev,
>  		return 0;
>  	}
>  
> -	priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem) - 1;
> +	priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem);
> +
> +	/* round up divider when clkout isn't accurate (e.g. !rem) */
> +	if (priv->spi_clk_out_div && !rem)
> +		priv->spi_clk_out_div--;
> +
This comment perhaps needs adjusting because at the moment it looks
like it decrements when it is accurate.   With the old code in place
in the patch it's obvious that's because you actually want one less.

Might even be worth the dance of

/* round up if not precise */
if (priv->spi_clk_out_div && rem)
	priv->spi_clk_out_div++;

/* subtract one because....  */
priv->spi_clk_out_div--;

>  	if (!priv->spi_clk_out_div) {
>  		/* spi_clk_out_div == 0 means ckout is OFF */
>  		dev_err(&pdev->dev, "spi-max-frequency not achievable\n");
>  		return -EINVAL;
>  	}
> -	priv->dfsdm.spi_master_freq = spi_freq;
> +	priv->dfsdm.spi_master_freq = clk_freq / (priv->spi_clk_out_div + 1);
And we increment it again here? That needs an explanation as well.
>  
>  	if (rem) {
>  		dev_warn(&pdev->dev, "SPI clock not accurate\n");
Fabrice Gasnier March 21, 2019, 1:41 p.m. UTC | #2
On 3/10/19 11:09 AM, Jonathan Cameron wrote:
> On Wed, 6 Mar 2019 09:55:17 +0100
> Fabrice Gasnier <fabrice.gasnier@st.com> wrote:
> 
>> When SPI clock isn't accurate, 'spi_master_freq' is filled in with
>> expected frequency. Use computed value instead:
>> - e.g. source clock / (CKOUTDIV + 1)
>> Also, current divider may be set to value that makes CKOUT to exceed
>> spi-max-frequency. Rather use lower value (e.g. round up divider when
>> ckout isn't accurate).
>>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> ---
>>  drivers/iio/adc/stm32-dfsdm-core.c | 9 +++++++--
>>  1 file changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
>> index bf089f5..65b7556 100644
>> --- a/drivers/iio/adc/stm32-dfsdm-core.c
>> +++ b/drivers/iio/adc/stm32-dfsdm-core.c
>> @@ -243,13 +243,18 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev,
>>  		return 0;
>>  	}
>>  
>> -	priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem) - 1;
>> +	priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem);
>> +
>> +	/* round up divider when clkout isn't accurate (e.g. !rem) */
>> +	if (priv->spi_clk_out_div && !rem)
>> +		priv->spi_clk_out_div--;
>> +
> This comment perhaps needs adjusting because at the moment it looks
> like it decrements when it is accurate.   With the old code in place
> in the patch it's obvious that's because you actually want one less.
> 
> Might even be worth the dance of
> 
> /* round up if not precise */
> if (priv->spi_clk_out_div && rem)
> 	priv->spi_clk_out_div++;
> 
> /* subtract one because....  */
> priv->spi_clk_out_div--;

Hi Jonathan,

I'll rework this patch in v2, make it easier to understand & read.

In a few words: the clock output is divider = ckoutdiv + 1.
ckoutdiv range can be from 1-255 to provide divider of 2-256.
So I'll introduce this divider as a variable, and use it to setup
spi_clk_out_div.
This should address all your remarks here.

Thanks for reviewing,
Best Regards,
Fabrice
> 
>>  	if (!priv->spi_clk_out_div) {
>>  		/* spi_clk_out_div == 0 means ckout is OFF */
>>  		dev_err(&pdev->dev, "spi-max-frequency not achievable\n");
>>  		return -EINVAL;
>>  	}
>> -	priv->dfsdm.spi_master_freq = spi_freq;
>> +	priv->dfsdm.spi_master_freq = clk_freq / (priv->spi_clk_out_div + 1);
> And we increment it again here? That needs an explanation as well.
>>  
>>  	if (rem) {
>>  		dev_warn(&pdev->dev, "SPI clock not accurate\n");
>

Patch
diff mbox series

diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
index bf089f5..65b7556 100644
--- a/drivers/iio/adc/stm32-dfsdm-core.c
+++ b/drivers/iio/adc/stm32-dfsdm-core.c
@@ -243,13 +243,18 @@  static int stm32_dfsdm_parse_of(struct platform_device *pdev,
 		return 0;
 	}
 
-	priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem) - 1;
+	priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem);
+
+	/* round up divider when clkout isn't accurate (e.g. !rem) */
+	if (priv->spi_clk_out_div && !rem)
+		priv->spi_clk_out_div--;
+
 	if (!priv->spi_clk_out_div) {
 		/* spi_clk_out_div == 0 means ckout is OFF */
 		dev_err(&pdev->dev, "spi-max-frequency not achievable\n");
 		return -EINVAL;
 	}
-	priv->dfsdm.spi_master_freq = spi_freq;
+	priv->dfsdm.spi_master_freq = clk_freq / (priv->spi_clk_out_div + 1);
 
 	if (rem) {
 		dev_warn(&pdev->dev, "SPI clock not accurate\n");