Re: [PATCH 1/8] iio: adc: stm32-dfsdm: make spi_master_freq more accurate
From: Jonathan Cameron
Date: Sun Mar 10 2019 - 06:10:04 EST
On Wed, 6 Mar 2019 09:55:17 +0100
Fabrice Gasnier <fabrice.gasnier@xxxxxx> 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@xxxxxx>
> ---
> 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");