This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3352: Different readings on ADC depending on board power

Part Number: AM3352


Hi

I'm investigating a problem that has started to appear on numerous boards using the AM3352 processor. We've had boards running for a few years without any issue and suddenly on some newly produced boards we have started getting faulty readings on the ADC AIN6 input. We can see that the value read differs depending on how the board is powered. We're using the TPS65217C and when powered over USB the readings are ok but when powered over AC from the mains it returns the wrong value.

AIN6 Measurements
AIN6 Measure multi-meter +1V8 measure multi-meter AIN6 software measure
USB powered 0.235V 1.810V 0.232V
AC powered 0.247V 1.811V 0.342V

The schematics for the ADC is as follows.

And the TPS65217C

Attached you can also find a minimum code example that shows how we read the ADC input.

/**
 * SPDX-License-Identifier:    GPL-2.0+
 */
#include "adc.h"
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <asm/arch/hardware.h>
#include <asm/io.h>

/**
 * @brief Configure the ADC channel
 * @param channel Channel number (0-8)
 * @return Non-zero value on error
 */
int adc_config(unsigned char channel)
{
  if (channel > AIN7)
  {
    return -1;
  }

  // Unprotect step registers, TSC_ADC_SS module disabled because configuration in progress
  writel(ADC_CTRL_UNPROTECT_MASK, TSC_ADC_SS_CTRL);
  while((readl(TSC_ADC_SS_CTRL) & ADC_SS_CTRL_ENABLE) !=0)
  {
    // wait...
  }

  // No idle mode
  writel(ADC_SYSCONFIG_NO_IDLE_MASK, TSC_ADC_SS_SYSCONFIG);
  writel(ADC_CLKDIV_3MHZ, TSC_ADC_SS_ADC_CLKDIV);

  // Enable step 1 (because it is the first one)
  writel(ADC_SS_STEPENABLE_SETP1, TSC_ADC_SS_STEPENABLE);

  // Data in FIFO 16 samples average, SW enabled, oneshot
  writel(ADC_CTRL_16K_SAMPLES | ((unsigned long)channel<<ADC_CTRL_CH_SHIFT), TSC_ADC_SS_STEPCONFIG1);

  // TSC_ADC_SS module enabled
  writel(ADC_SS_CTRL_ENABLE, TSC_ADC_SS_CTRL);
  while((readl(TSC_ADC_SS_CTRL) & ADC_SS_CTRL_ENABLE)==0)
  {
    // wait...
  }
  return 0;
}

/**
 * @brief Get voltage on ADC channel
 * @param channel Channel number (0-8)
 * @return Voltage in mV, or non-zero error value
 */
int adc_get_voltage(unsigned char channel)
{
  int tempo=5000; /* 5 msec */
  int voltage, raw_data=0;

  if(channel > AIN7)
  {
    return -1;
  }

  noah_hmi_adc_config(channel);
  // Wait for a value in FIFO
  while((readl(TSC_ADC_SS_FIFO0COUNT) & 0x7F)==0 && --tempo)
  {
    udelay(1);
  }
  if(tempo==0)
  {
    // Error: ADC stuck...
    return -1;
  }

  // Calc the voltage being given
  raw_data = readl(TSC_ADC_SS_FIFO0DATA);
  voltage = (1800*(raw_data & 0xFFF))/0xFFF;
  return voltage;
}

adc.h

BR,

Måns