AnsweredAssumed Answered

iMX6UL adc calibration fails

Question asked by Durmuş Kurtuluş on Aug 15, 2016
Latest reply on Aug 18, 2016 by Durmuş Kurtuluş

Hi,

 

I'm trying to test adc module of iMX6UL. I keep getting "ADC calibration failed" error. When I read count values from /sys/bus/iio/devices/iio:device0/in_voltageX_raw, it kind of works. But indeed there seems to be a calibration problem. When I apply 0V to the pin, I read 320. However, it reaches max value (4095) at about 1V despite the reference being 3.3V. In between 0V and 1V, the count seems to rise linearly.

 

Some background information:

1) Custom board based on iMX6UL EVK board.

2) BSP version: L3.14.52_1.1.0_ga

3) Device tree:

&adc1 {

  pinctrl-names = "default";

  pinctrl-0 = <&pinctrl_adc1>;

  vref-supply = <&reg_vref_3v3>;

  status = "okay";

};

 

reg_vref_3v3: regulator-vref {

  compatible = "regulator-fixed";

  regulator-name = "vref-3v3";

  regulator-min-microvolt = <3300000>;

  regulator-max-microvolt = <3300000>;

};

 

pinctrl_adc1: adc1grp {

  fsl,pins = <

  MX6UL_PAD_GPIO1_IO08__GPIO1_IO08 0xb0     /* I only use Analog channel 1 input 8

 

  >;

};

 

Also in imx6ul.dtsi:

adc1: adc@02198000 {

  ...

  num-channels = <10>;

  ...

};

 

4) Both VDDA_ADC_3P3 and ADC_VREFH are tied to the same 3.3V supply.

5) The pin is also configured as GPIO in U-boot.

MX6_PAD_GPIO1_IO08__GPIO1_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL),

 

vf610_adc driver:

I checked the vf610_adc driver and calibration function. FWIW, I added the following lines to see the values of adc related registers before and after the calibration attempt.

 

static void vf610_adc_calibration(struct vf610_adc *info)

{

  int adc_gc, hc_cfg;

  int timeout;

 

  if (!info->adc_feature.calibration)

       return;

 

  dev_err(info->dev, "VF610_REG_ADC_HC0 = %x\n", readl(info->regs + VF610_REG_ADC_HC0));

  dev_err(info->dev, "VF610_REG_ADC_HC1 = %x\n", readl(info->regs + VF610_REG_ADC_HC1));

  dev_err(info->dev, "VF610_REG_ADC_HS = %x\n", readl(info->regs + VF610_REG_ADC_HS));

  dev_err(info->dev, "VF610_REG_ADC_R0 = %x\n", readl(info->regs + VF610_REG_ADC_R0));

  dev_err(info->dev, "VF610_REG_ADC_R1 = %x\n", readl(info->regs + VF610_REG_ADC_R1));

  dev_err(info->dev, "VF610_REG_ADC_CFG = %x\n", readl(info->regs + VF610_REG_ADC_CFG));

  dev_err(info->dev, "VF610_REG_ADC_GC = %x\n", readl(info->regs + VF610_REG_ADC_GC));

  dev_err(info->dev, "VF610_REG_ADC_GS = %x\n", readl(info->regs + VF610_REG_ADC_GS));

  dev_err(info->dev, "VF610_REG_ADC_CV = %x\n", readl(info->regs + VF610_REG_ADC_CV));

  dev_err(info->dev, "VF610_REG_ADC_OFS = %x\n", readl(info->regs + VF610_REG_ADC_OFS));

  dev_err(info->dev, "VF610_REG_ADC_CAL = %x\n", readl(info->regs + VF610_REG_ADC_CAL));

  dev_err(info->dev, "VF610_REG_ADC_PCTL = %x\n", readl(info->regs + VF610_REG_ADC_PCTL));

 

  /* enable calibration interrupt */

  hc_cfg = VF610_ADC_AIEN | VF610_ADC_CONV_DISABLE;

  writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);

 

  adc_gc = readl(info->regs + VF610_REG_ADC_GC);

  writel(adc_gc | VF610_ADC_CAL, info->regs + VF610_REG_ADC_GC);

 

  timeout = wait_for_completion_timeout(&info->completion, VF610_ADC_TIMEOUT);

  if (timeout == 0)

       dev_err(info->dev, "Timeout for adc calibration\n");

 

  dev_err(info->dev, "VF610_REG_ADC_HC0 = %x\n", readl(info->regs + VF610_REG_ADC_HC0));

  dev_err(info->dev, "VF610_REG_ADC_HC1 = %x\n", readl(info->regs + VF610_REG_ADC_HC1));

  dev_err(info->dev, "VF610_REG_ADC_HS = %x\n", readl(info->regs + VF610_REG_ADC_HS));

  dev_err(info->dev, "VF610_REG_ADC_R0 = %x\n", readl(info->regs + VF610_REG_ADC_R0));

  dev_err(info->dev, "VF610_REG_ADC_R1 = %x\n", readl(info->regs + VF610_REG_ADC_R1));

  dev_err(info->dev, "VF610_REG_ADC_CFG = %x\n", readl(info->regs + VF610_REG_ADC_CFG));

  dev_err(info->dev, "VF610_REG_ADC_GC = %x\n", readl(info->regs + VF610_REG_ADC_GC));

  dev_err(info->dev, "VF610_REG_ADC_GS = %x\n", readl(info->regs + VF610_REG_ADC_GS));

  dev_err(info->dev, "VF610_REG_ADC_CV = %x\n", readl(info->regs + VF610_REG_ADC_CV));

  dev_err(info->dev, "VF610_REG_ADC_OFS = %x\n", readl(info->regs + VF610_REG_ADC_OFS));

  dev_err(info->dev, "VF610_REG_ADC_CAL = %x\n", readl(info->regs + VF610_REG_ADC_CAL));

  dev_err(info->dev, "VF610_REG_ADC_PCTL = %x\n", readl(info->regs + VF610_REG_ADC_PCTL));

 

  adc_gc = readl(info->regs + VF610_REG_ADC_GS);

  if (adc_gc & VF610_ADC_CALF)

       dev_err(info->dev, "ADC calibration failed\n");

 

  info->adc_feature.calibration = false;

}

 

Here are the results:

BEFORE (Note that all values are in hex format)

VF610_REG_ADC_HC0 = 1f

VF610_REG_ADC_HC1 = 1f

VF610_REG_ADC_HS = 0

VF610_REG_ADC_R0 = 0

VF610_REG_ADC_R1 = 0

VF610_REG_ADC_CFG = 10488

VF610_REG_ADC_GC = 20

VF610_REG_ADC_GS = 0

VF610_REG_ADC_CV = 0

VF610_REG_ADC_OFS = 0

VF610_REG_ADC_CAL = 0

VF610_REG_ADC_PCTL = 0

AFTER (Note that all values are in hex format)

VF610_REG_ADC_HC0 = 9f

VF610_REG_ADC_HC1 = 1f

VF610_REG_ADC_HS = 0

VF610_REG_ADC_R0 = 58

VF610_REG_ADC_R1 = 0

VF610_REG_ADC_CFG = 10488

VF610_REG_ADC_GC = 20

VF610_REG_ADC_GS = 2

VF610_REG_ADC_CV = 0

VF610_REG_ADC_OFS = 0

VF610_REG_ADC_CAL = f

VF610_REG_ADC_PCTL = 0

 

* We see that CALF bit of VF610_REG_ADC_GS is set, hence the calibration error.

* It seems that a conversion is performed and VF610_REG_ADC_R0 is loaded with some value. Reference manual says "While calibration is active, no ADC register can be written and no stop mode may be entered or the calibration routine will be aborted causing the CAL bit to clear and the CALF bit to set." Can this be the cause of calibration error? Or is it just the consequence of the error?

* Somehow VF610_REG_ADC_CAL is loaded with 0xf. What does this mean?

 

On a related note, since VF610_REG_ADC_CAL register value is only 4-bit long (16 distinct values, 0 to 15), I also tried loading every value manually and checked the performance that way. But nothing seems to change. The count still reaches 4095 at 1V every time. What exactly does this value represent?

 

Can someone please shed some light on this topic? What might I be missing?

 

Thanks.

Durmus

Outcomes