Post Go back to editing

Device Tree for AD7606 SPI on Raspberry

Hello!

I am trying to implement SPI driver for AD7606 (AD7606BSTZ) on Raspberry Pi 4B . The kernel v5.10.83  was build with support of AD7606_SPI driver as module. The chip is wired as it shown spec. During my tries to read data (in sys/bus/iio/deviceX/input_voltageY_raw) or test driver with iio_info command I am getting error "Input/output error (5)" or "Connection timed out (110)". I guess this is because there is mistake in device tree overlay. It is my first experience of implementing driver thus for me not all properties are clear. So need your support.

The device tree overlay is below:

/dts-v1/;
/plugin/;

#include </home/pi/Desktop/linux_master_5.10_depth=1/include/dt-bindings/gpio/gpio.h>
#include </home/pi/Desktop/linux_master_5.10_depth=1/include/dt-bindings/interrupt-controller/irq.h>

/ {
    compatible = "brcm,bcm2835";
    
    fragment@0 {
    target = <&spidev0>;
    __overlay__ {
        status = "disabled";
        };
    };
    fragment@1 {
    target = <&spi0>;
    __overlay__ {
        #address-cells = <1>;
        #size-cells = <0>;
        adc0: adc@0 {
            compatible = "adi,ad7606-8";
            reg = <0>;
            spi-max-frequency = <10000>;
            spi-cpol;
            spi-cpha;
            avcc-supply = <&vdd_5v0_reg>;
            interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
            interrupt-parent = <&gpio>;
            adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
            reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
            adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
            adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>,
                                           <&gpio 23 GPIO_ACTIVE_HIGH>,
                                           <&gpio 26 GPIO_ACTIVE_HIGH>;
            standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
            adi,sw-mode;
            };
        };
    };
};

And reverted DT overlay is below(the part for SPI):

spi@7e204000 {
			compatible = "brcm,bcm2835-spi";
			clocks = < 0x08 0x14 >;
			status = "okay";
			#address-cells = < 0x01 >;
			interrupts = < 0x00 0x76 0x04 >;
			cs-gpios = < 0x07 0x08 0x01 0x07 0x07 0x01 >;
			#size-cells = < 0x00 >;
			dma-names = "tx\0rx";
			phandle = < 0x33 >;
			reg = < 0x7e204000 0x200 >;
			pinctrl-0 = < 0x0e 0x0f >;
			dmas = < 0x0c 0x06 0x0c 0x07 >;
			pinctrl-names = "default";

			adc@0 {
				spi-cpol;
				compatible = "adi,ad7606-8";
				adi,conversion-start-gpios = < 0x07 0x11 0x00 >;
				spi-cpha;
				adi,first-data-gpios = < 0x07 0x16 0x00 >;
				adi,oversampling-ratio-gpios = < 0x07 0x12 0x00 0x07 0x17 0x00 0x07 0x1a 0x00 >;
				interrupt-parent = < 0x07 >;
				interrupts = < 0x19 0x02 >;
				reset-gpios = < 0x07 0x1b 0x00 >;
				phandle = < 0xe9 >;
				avcc-supply = < 0xe2 >;
				standby-gpios = < 0x07 0x18 0x01 >;
				reg = < 0x00 >;
				adi,sw-mode;
				spi-max-frequency = < 0x2710 >;
			};

			spidev@1 {
				compatible = "spidev";
				#address-cells = < 0x01 >;
				#size-cells = < 0x00 >;
				phandle = < 0xb0 >;
				reg = < 0x01 >;
				spi-max-frequency = < 0x7735940 >;
			};

			spidev@0 {
				compatible = "spidev";
				status = "disabled";
				#address-cells = < 0x01 >;
				#size-cells = < 0x00 >;
				phandle = < 0xaf >;
				reg = < 0x00 >;
				spi-max-frequency = < 0x7735940 >;
			};
		};

At this moment questions are:

  1. I am not sure that I wrote "avcc-supply" correct. What is "avcc-supply" property mean? There are few words about this.
  2. Has "adi,conversion-start-gpios" to be  really GPIO_ACTIVE_HIGH?
  3. This question more about raspberry but anyway if you give advice about this I would be happy: how to determine correct GPIO pin numbers in device tree properties. I used BCM2711 gpio numbers (like &gpio 22) but I am not sure that this is correct.
Parents
  • Some Update about topic:

    There is still problem with `raw ERROR: Input/output error (5)`. I connected to Logic Analyzer to SPI and GPIO signals. By trying to use iio_info command and reading in sysfs by cat in_volrageX_raw. More details were observed. Looks transfer of data is working but strange thigs were noticed:

    4. The CONVST works opposite than it described in technical manual pic.48. On picture the signal is inverted.

    5. Driver transfer first 16 bits and then stops with resetting AD7606. Even If I try to read other channels I can see only first 16 bits and then reset. See pictures below.

    6. Looks clock signal and data MISO are not well aligned. 

    7. Even if input channel connected to the ground the MISO signal could be FFFF or 0000.

    Can anybody help with troubleshooting?

    here is reading one channgel:

    Logic analyzer

    here is reading all 8 channels by iio_info. Transfer interrupts after each 16 bits.

    iio_info

  •   I checked conditions when driver set chip in reset state and found problem here. The driver verifies if FIRSTDATA input is high when reading first channel and if it is not then driver creates error and reset the device. It is in function static int ad7606_read_samples of ad7606.c driver file:

    static int ad7606_read_samples(struct ad7606_state *st)
    {
    	unsigned int num = st->chip_info->num_channels - 1;
    	u16 *data = st->data;
    	int ret;
    
    	/*
    	 * The frstdata signal is set to high while and after reading the sample
    	 * of the first channel and low for all other channels. This can be used
    	 * to check that the incoming data is correctly aligned. During normal
    	 * operation the data should never become unaligned, but some glitch or
    	 * electrostatic discharge might cause an extra read or clock cycle.
    	 * Monitoring the frstdata signal allows to recover from such failure
    	 * situations.
    	 */
    
    	if (st->gpio_frstdata) {
    		ret = st->bops->read_block(st->dev, 1, data);
    		if (ret)
    			return ret;
    
    		if (!gpiod_get_value(st->gpio_frstdata)) {
    			ad7606_reset(st);
    			return -EIO;
    		}
    
    		data++;
    		num--;
    	}
    
    	return st->bops->read_block(st->dev, num, data);
    }

    For some reason idk the driver doesn't see HIGH level on FRSTDATA pin however logic analyzer detect it. Temporary I deleted property adi,conversion-start-gpios in Device tree and data reading works now. Probably FIRSTDATA signal disappears too fast  from input after reading first channel and driver can't detect high level.

Reply
  •   I checked conditions when driver set chip in reset state and found problem here. The driver verifies if FIRSTDATA input is high when reading first channel and if it is not then driver creates error and reset the device. It is in function static int ad7606_read_samples of ad7606.c driver file:

    static int ad7606_read_samples(struct ad7606_state *st)
    {
    	unsigned int num = st->chip_info->num_channels - 1;
    	u16 *data = st->data;
    	int ret;
    
    	/*
    	 * The frstdata signal is set to high while and after reading the sample
    	 * of the first channel and low for all other channels. This can be used
    	 * to check that the incoming data is correctly aligned. During normal
    	 * operation the data should never become unaligned, but some glitch or
    	 * electrostatic discharge might cause an extra read or clock cycle.
    	 * Monitoring the frstdata signal allows to recover from such failure
    	 * situations.
    	 */
    
    	if (st->gpio_frstdata) {
    		ret = st->bops->read_block(st->dev, 1, data);
    		if (ret)
    			return ret;
    
    		if (!gpiod_get_value(st->gpio_frstdata)) {
    			ad7606_reset(st);
    			return -EIO;
    		}
    
    		data++;
    		num--;
    	}
    
    	return st->bops->read_block(st->dev, num, data);
    }

    For some reason idk the driver doesn't see HIGH level on FRSTDATA pin however logic analyzer detect it. Temporary I deleted property adi,conversion-start-gpios in Device tree and data reading works now. Probably FIRSTDATA signal disappears too fast  from input after reading first channel and driver can't detect high level.

Children
No Data