All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
To: Heiner Kallweit <hkallweit1@gmail.com>
Cc: Jonathan Cameron <jic23@kernel.org>,
	linux-iio@vger.kernel.org, pmeerw@pmeerw.net
Subject: Re: [PATCH v3] iio: adc: meson-saradc: add calibration
Date: Fri, 24 Mar 2017 23:24:33 +0100	[thread overview]
Message-ID: <CAFBinCA6SnwDnsZ4m8Q4QitHFX0t7AaLDPwRChAwqtW8JopHQw@mail.gmail.com> (raw)
In-Reply-To: <f89d2909-9044-242c-fbfa-b18d8887d1d6@gmail.com>

Hi Heiner,

On Sat, Mar 18, 2017 at 7:38 PM, Heiner Kallweit <hkallweit1@gmail.com> wrote:
> This patch adds calibration for the Meson SAR ADC.
> Points 25% vref and 75% vref are used for calibration.
> It usesa simple linear calibration function: SCALE * val + BIAS
nit: should be "It uses a"
>
> Successfully tested on a Odroid C2.
>
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
> Tested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
looks good to me, so:

Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>

> ---
> v2:
> - added calibration scale
> v3:
> - added define MILLION
> - don't bail out if calibration fails
> ---
>  drivers/iio/adc/meson_saradc.c | 77 ++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 75 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
> index cde9ca7a..dd4190b5 100644
> --- a/drivers/iio/adc/meson_saradc.c
> +++ b/drivers/iio/adc/meson_saradc.c
> @@ -166,6 +166,8 @@
>
>  #define MESON_SAR_ADC_MAX_FIFO_SIZE                            32
>  #define MESON_SAR_ADC_TIMEOUT                                  100 /* ms */
> +/* for use with IIO_VAL_INT_PLUS_MICRO */
> +#define MILLION                                                        1000000
back when the initial driver was reviewed I was asked to prefix all
defines (so they won't clash with defines from other drivers, see [0])
- this is why all defines start with MESON_SAR_ADC_
if Jonathan or Peter think that it's worth renaming this #define then
you could rename it to MESON_SAR_ADC_CALIBSCALE_REF (that's what I
came up with, feel free to choose any other/more suitable name though)

>  #define MESON_SAR_ADC_CHAN(_chan) {                                    \
>         .type = IIO_VOLTAGE,                                            \
> @@ -173,7 +175,9 @@
>         .channel = _chan,                                               \
>         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |                  \
>                                 BIT(IIO_CHAN_INFO_AVERAGE_RAW),         \
> -       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),           \
> +       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |          \
> +                               BIT(IIO_CHAN_INFO_CALIBBIAS) |          \
> +                               BIT(IIO_CHAN_INFO_CALIBSCALE),          \
>         .datasheet_name = "SAR_ADC_CH"#_chan,                           \
>  }
>
> @@ -233,6 +237,8 @@ struct meson_sar_adc_priv {
>         struct clk                              *adc_div_clk;
>         struct clk_divider                      clk_div;
>         struct completion                       done;
> +       int                                     calibbias;
> +       int                                     calibscale;
>  };
>
>  static const struct regmap_config meson_sar_adc_regmap_config = {
> @@ -252,6 +258,17 @@ static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev)
>         return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
>  }
>
> +static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val)
> +{
> +       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +       int tmp;
> +
> +       /* use val_calib = scale * val_raw + offset calibration function */
> +       tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias;
> +
> +       return clamp(tmp, 0, (1 << priv->data->resolution) - 1);
> +}
> +
>  static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
>  {
>         struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> @@ -302,7 +319,7 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
>
>         fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
>         fifo_val &= GENMASK(priv->data->resolution - 1, 0);
> -       *val = fifo_val;
> +       *val = meson_sar_adc_calib_val(indio_dev, fifo_val);
>
>         return 0;
>  }
> @@ -527,6 +544,15 @@ static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
>                 *val2 = priv->data->resolution;
>                 return IIO_VAL_FRACTIONAL_LOG2;
>
> +       case IIO_CHAN_INFO_CALIBBIAS:
> +               *val = priv->calibbias;
> +               return IIO_VAL_INT;
> +
> +       case IIO_CHAN_INFO_CALIBSCALE:
> +               *val = priv->calibscale / MILLION;
> +               *val2 = priv->calibscale % MILLION;
> +               return IIO_VAL_INT_PLUS_MICRO;
> +
>         default:
>                 return -EINVAL;
>         }
> @@ -762,6 +788,47 @@ static irqreturn_t meson_sar_adc_irq(int irq, void *data)
>         return IRQ_HANDLED;
>  }
>
> +static int meson_sar_adc_calib(struct iio_dev *indio_dev)
> +{
> +       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +       int ret, nominal0, nominal1, value0, value1;
> +
> +       /* use points 25% and 75% for calibration */
> +       nominal0 = (1 << priv->data->resolution) / 4;
> +       nominal1 = (1 << priv->data->resolution) * 3 / 4;
> +
> +       meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4);
> +       usleep_range(10, 20);
> +       ret = meson_sar_adc_get_sample(indio_dev,
> +                                      &meson_sar_adc_iio_channels[7],
> +                                      MEAN_AVERAGING, EIGHT_SAMPLES, &value0);
> +       if (ret < 0)
> +               goto out;
> +
> +       meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4);
> +       usleep_range(10, 20);
> +       ret = meson_sar_adc_get_sample(indio_dev,
> +                                      &meson_sar_adc_iio_channels[7],
> +                                      MEAN_AVERAGING, EIGHT_SAMPLES, &value1);
> +       if (ret < 0)
> +               goto out;
> +
> +       if (value1 <= value0) {
> +               ret = -EINVAL;
> +               goto out;
> +       }
> +
> +       priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION,
> +                                  value1 - value0);
> +       priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale,
> +                                            MILLION);
> +       ret = 0;
> +out:
> +       meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
> +
> +       return ret;
> +}
> +
>  static const struct iio_info meson_sar_adc_iio_info = {
>         .read_raw = meson_sar_adc_iio_info_read_raw,
>         .driver_module = THIS_MODULE,
> @@ -901,6 +968,8 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>                 return PTR_ERR(priv->vref);
>         }
>
> +       priv->calibscale = MILLION;
> +
>         ret = meson_sar_adc_init(indio_dev);
>         if (ret)
>                 goto err;
> @@ -909,6 +978,10 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>         if (ret)
>                 goto err;
>
> +       ret = meson_sar_adc_calib(indio_dev);
> +       if (ret)
> +               dev_warn(&pdev->dev, "calibration failed\n");
> +
>         platform_set_drvdata(pdev, indio_dev);
>
>         ret = iio_device_register(indio_dev);
> --
> 2.12.0
>
>

Regards,
Martin

[0] http://lists.infradead.org/pipermail/linux-amlogic/2017-January/002009.html

  parent reply	other threads:[~2017-03-24 22:24 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-18 18:38 [PATCH v3] iio: adc: meson-saradc: add calibration Heiner Kallweit
2017-03-19 10:08 ` Jonathan Cameron
2017-03-24 22:24 ` Martin Blumenstingl [this message]
2017-03-25 14:57   ` Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAFBinCA6SnwDnsZ4m8Q4QitHFX0t7AaLDPwRChAwqtW8JopHQw@mail.gmail.com \
    --to=martin.blumenstingl@googlemail.com \
    --cc=hkallweit1@gmail.com \
    --cc=jic23@kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=pmeerw@pmeerw.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.