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.

Accessing the AM335x internal TSC ADC in Linux

Other Parts Discussed in Thread: TPS65910, TPS65217, DA8XX

Hi,

I would like to use the AM335x TSC ADC in my Linux application to read slow analog signals.  I'm not using the touch screen controller (as my LCD does not have a touch screen).  I'm currently using linux-3.2.0-psp04.06.00.08.sdk on an AM335x EVM (without the display board).  Is there a simple way to patch in ADC support into this release of Linux?

I noticed that Patil Rachna (ti.com) is currently submitting patches to http://arago-project.org/git/projects/?p=linux-am33x.git;a=summary but I would rather stay with a release version of the PSP.  When will the next release of the Linux PSP be?

  • John,

    As far as official PSP release is concerned, it is scheduled for 1Q-13.

    I understand that you want to use an official PSP release which is supported and fully tested by PSP, but I would still recommend you to start using PSP Arago repo, which is where we push all our development which in-turn goes into release. Couple of benefits we get with this, you can start your development early and also report back to us if there are any issues, it may get fixed and enrolled into next PSP release itself.

    Early version of User Guide is available at http://processors.wiki.ti.com/index.php/AM335x_ADC_Driver%27s_Guide

    Thanks,

    Vaibhav

  • Thanks, I will try the Arago git repo.

  • Yep, I got it going in ADC mode (8 channels), like so:

    git clone http://arago-project.org/git/projects/linux-am33x.git

    git checkout -b v3.2-staging origin/v3.2-staging

    Edit board-am335xevm.c as below.

    Build kernel (nb: configured both touch-screen and ADC as modules):

    export PATH=/home/johnmu/ti-sdk-am335x-evm-05.05.00.00/linux-devkit/bin/:$PATH

    make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm am335x_evm_defconfig
    make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm menuconfig
    make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm uImage
    make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm modules

    Boot new kernel and do "modprobe ti_adc".

    Then, e.g. "cat /sys/bus/iio/devices/iio\:device0/in_voltage5_raw".

    =========================================

    johnmu@johnmu-VirtualBox:~/arago/linux-am33x$ git diff
    diff --git a/arch/arm/mach-omap2/board-am335xevm.c b/arch/arm/mach-omap2/board-am335xevm.c
    index 878c74e..1f4b14b 100644
    --- a/arch/arm/mach-omap2/board-am335xevm.c
    +++ b/arch/arm/mach-omap2/board-am335xevm.c
    @@ -36,6 +36,8 @@
    #include <linux/mfd/tps65910.h>
    #include <linux/mfd/tps65217.h>
    #include <linux/pwm_backlight.h>
    +// JFM added:
    +#include <linux/platform_data/ti_adc.h>
    #include <linux/input/ti_tsc.h>
    #include <linux/mfd/ti_tscadc.h>
    #include <linux/reboot.h>
    @@ -149,13 +151,21 @@ struct da8xx_lcdc_platform_data NHD_480272MF_ATXI_pdata = {

    /* TSc controller */
    static struct tsc_data am335x_touchscreen_data = {
    - .wires = 4,
    +// JFM changed wires to 0:
    + .wires = 0,
    .x_plate_resistance = 200,
    .steps_to_configure = 5,
    };

    +// JFM added:
    +static struct adc_data am335x_adc_data = {
    + .adc_channels = 8,
    +};
    +
    static struct mfd_tscadc_board tscadc = {
    .tsc_init = &am335x_touchscreen_data,
    +// JFM added:
    + .adc_init = &am335x_adc_data,
    };

    static u8 am335x_iis_serializer_direction1[] = {
    johnmu@johnmu-VirtualBox:~/arago/linux-am33x$

  • Hi Rachna Patel,

    I noticed that when I take two readings in VERY quick succession from a channel, i.e. read "/sys/bus/iio/devices/iio:device0/in_voltage4_raw", then the second reading can be corrupt.  This is probably not possible to repeat fast enough in a shell script, but easy to do in a C application.  The reason appears to be that the function tiadc_read_raw() in drivers/staging/iio/adc/ti_adc.c does not handle the case of the FIFO being empty (see code below).  This case is more of a practical problem when say reading two different channels (e.g. 3 and 4) simultaneously, a common requirement.  The FIFO will be empty in this case as well.

    IE:  *val is not assigned a value.

    static int tiadc_read_raw(struct iio_dev *idev,
    struct iio_chan_spec const *chan,
    int *val, int *val2, long mask)
    {
    struct adc_device *adc_dev = iio_priv(idev);
    int i;
    unsigned int fifo1count, readx1;

    fifo1count = adc_readl(adc_dev, TSCADC_REG_FIFO1CNT);
    for (i = 0; i < fifo1count; i++) {
    readx1 = adc_readl(adc_dev, TSCADC_REG_FIFO1);
    if (i == chan->channel) {
    readx1 = readx1 & 0xfff;
    *val = readx1;
    }
    }
    adc_writel(adc_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
    return IIO_VAL_INT;
    }