Post Go back to editing

AD7791 iio driver and device tree entry

Hi,

I'm developing system with AD7791 running under custom linux system. I'm building on buildroot version 2017.02.1 with linux kernel 4.9.13.

I have configured spi hardware support, IIO support and AD7791 driver. most significant configs in regard to spi and iio are shown below:

CONFIG_SPI=y
CONFIG_SPI_DEBUG=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_DESIGNWARE=y
CONFIG_SPI_DW_MMIO=y

CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
# CONFIG_IIO_BUFFER_CB is not set
CONFIG_IIO_KFIFO_BUF=y
CONFIG_IIO_TRIGGERED_BUFFER=y
CONFIG_IIO_CONFIGFS=y
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
CONFIG_IIO_SW_DEVICE=y
# CONFIG_IIO_SW_TRIGGER is not set

CONFIG_AD_SIGMA_DELTA=y

CONFIG_AD7791=y

I don't use boardconfig (or whatever it was called) but device tree. I have made dts entry like that:

        hps_spim0: spi@0xfff00000 {
            compatible = "snps,dw-spi-mmio-17.0", "snps,dw-spi-mmio", "snps,dw-apb-ssi";
            reg = <0xfff00000 0x00000100>;
            interrupt-parent = <&hps_arm_gic_0>;
            interrupts = <0 154 4>;
            clocks = <&spi_m_clk>;
            #address-cells = <1>;    /* embeddedsw.dts.params.#address-cells type NUMBER */
            #size-cells = <0>;    /* embeddedsw.dts.params.#size-cells type NUMBER */
            //bus-num = <0>;    /* embeddedsw.dts.params.bus-num type NUMBER */
            num-chipselect = <4>;    /* embeddedsw.dts.params.num-chipselect type NUMBER */
            status = "okay";    /* embeddedsw.dts.params.status type STRING */
            
               VtempADC@0 {
                compatible="adi,ad7791";
                status = "okay";
                reg = <0>; //chipselect
                spi-max-frequency= <5000000>;
                //bus-num = <0>;
                spi-cpha;
                spi-cpol;
                vref-supply = <&adc_vref>;
                vcc-supply = <&adc_supply>;
               };

...

my system detects 2 spi devices:

dmesg | grep spi
[    0.701451] dw_spi_mmio fff00000.spi: Detected FIFO size: 256 bytes
[    0.701705] dw_spi_mmio fff00000.spi: registered master spi32766 (dynamic)
[    0.702513] spi spi32766.0: setup mode 3, 8 bits/w, 5000000 Hz max --> 0
[    0.702770] dw_spi_mmio fff00000.spi: registered child spi32766.0
[    0.702817] spi spi32766.1: setup mode 3, 8 bits/w, 5000000 Hz max --> 0
[    0.703026] dw_spi_mmio fff00000.spi: registered child spi32766.1
[    0.961755] ad7791 spi32766.0: Missing IRQ.
[    0.965969] ad7791 spi32766.1: Missing IRQ.

/sys/bus/spi/devices/

directory shows two spi devices correctly i guess:

spi32766.0/  spi32766.1/

         BUT,

/sys/bus/iio/devices/ directory is empty

iio_info tool gives output like that

iio_info
Library version: 0.9 (git tag: v0.9)
Compiled with backends: local xml ip usb serial
IIO context created with local backend.
Backend version: 0.9 (git tag: v0.9)
Backend description string: Linux gb 4.9.13 #4 SMP Wed Nov 29 16:17:28 CET 2017 armv7l
IIO context has 1 attributes:
        local,kernel: 4.9.13
IIO context has 0 devices:

Does anyone have any clue why my SPI devices are not detected by iio subsystem?

or

Can I easily handle ADCs with SPI alone, without IIO?

  • [    0.961755] ad7791 spi32766.0: Missing IRQ.
    [    0.965969] ad7791 spi32766.1: Missing IRQ.

    Please see here:

    https://github.com/analogdevicesinc/linux/blob/xcomm_zynq/drivers/iio/adc/ad7791.c#L405

    The driver probe is aborts with error - (before it creates the iio device).

    Please supply an IRQ via the device tree.

    -Michael

  • The AD7791 IRQ is an GPIO IRQ source.

    You need an pull-up connected to DOUT/RDY and an interrupt capable GPIO.

    So in total you connect SPI-MISO, a GPIO and a Pull-Up to DOUT/RDY.

    The interrupt then signals when it's safe to read the conversion result.

    -Michael

  • Thank you for the response,

    I assumed that the IRQ will be derived from the parent node (SPI). I have just copied the interrupt data but have another problems with irq registration:

    Device-tree:

            hps_spim0: spi@0xfff00000 {
                compatible = "snps,dw-spi-mmio-17.0", "snps,dw-spi-mmio", "snps,dw-apb-ssi";
                reg = <0xfff00000 0x00000100>;
                interrupt-parent = <&hps_arm_gic_0>;
                interrupts = <0 154 4>;
                clocks = <&spi_m_clk>;
                #address-cells = <1>;    /* embeddedsw.dts.params.#address-cells type NUMBER */
                #size-cells = <0>;    /* embeddedsw.dts.params.#size-cells type NUMBER */
                bus-num = <0>;        /* embeddedsw.dts.params.bus-num type NUMBER */
                num-chipselect = <4>;    /* embeddedsw.dts.params.num-chipselect type NUMBER */
                status = "okay";    /* embeddedsw.dts.params.status type STRING */
                
                   VtempADC@0 {
                    compatible="adi,ad7791";
                    status = "okay";
                    reg = <0>; //chipselect
                    spi-max-frequency= <5000000>;
                    //bus-num = <0>;
                    spi-cpha;
                    spi-cpol;
                    //vref-supply = <&adc_vref>;
                    vcc-supply = <&adc_supply>;
                    refin-supply = <&adc_vref>;
                    interrupt-parent = <&hps_arm_gic_0>;
                    interrupts = <0 154 4>;
                   };

    and dmesg output

    [    0.962165] genirq: Flags mismatch irq 33. 00000008 (ad7791) vs. 00000084 (dw_spi65535)

    [    0.970187] iio iio:device0: request_irq <- my "prinf" debugging to backtrace failing function
    [    0.974101] iio iio:device0: ad_sd_probe_trigger <- my "prinf" debugging to backtrace failing function
    [    0.978730] ad7791 spi32766.0: ad_sd_setup_buffer_and_trigger <- my "prinf" debugging 2backtrace failing function
    [    0.985029] ad7791: probe of spi32766.0 failed with error -16

    if i change the flags in device tree to

    interrupts = <0 154 8>;

    because for DT:

            1 = low-to-high edge triggered         2 = high-to-low edge triggered         4 = active high level-sensitive         8 = active low level-sensitive

    and code ad_sd_probe_trigger requests low level:

        ret = request_irq(sigma_delta->spi->irq,
                  ad_sd_data_rdy_trig_poll,
                  IRQF_TRIGGER_LOW,
                  indio_dev->name,
                  sigma_delta);

    i have an output:

    [    0.962182] irq: type mismatch, failed to map hwirq-186 for /sopc@0/intc@0xfffed000!

    [    0.969939] ad7791 spi32766.0: Missing IRQ.

    (IRQ' identifiers hwirq-186 and <0 154> are equivalent in my hardware)

    my SPI IRQ combines several events (Cortex-A9 Microprocessor Unit Subsystem; Cyclone V Device Handbook):

    This interrupt combines the following interrupts: ssi_txe_intr, ssi_txo_intr, ssi_rxf_intr, ssi_rxo_intr, ssi_rxu_intr and ssi_mst_intr.

    and probably cannot be changed to LOW level sensitive, so I've changed

    IRQF_TRIGGER_LOW, -> IRQF_TRIGGER_HIGH | IRQF_SHARED,

    and irq is registered.

    However my devices are still not visible:

    # iio_info
    Library version: 0.9 (git tag: v0.9)
    Compiled with backends: local xml ip usb serial
    Unable to create IIO context: Invalid argument

    I have no idea how to make the ADCs present to IIO subsystem

    Documentation/devicetree/bindings/iio/iio-bindings.txt gives little explanation and i cannot match correct DT entries.

    I would appreciate any help!

  • one update. i've managed to get iio devices in sysfs. iio_info still doesn't detect anything, but devices are seem to be present in the system

  • OK, so I managed to make some new investigation with the devices. Before details, short version:

    I can make one AD7791 device to work, but when there are two configured in device tree, none is responding.

    Details, what I have done:

    With FPGS SoC there is a fun thing that I can connect my outputs to various devices. My tests includes two IP cores as the SPI master device: Synopsys DesignWare SPI master that is a "Hard IP" and Altera Avalon SPI master that is a "Soft IP". Both ipcores have their linux drivers in mainline linux. Additional IRQ was connected to ARM Generic Interrupt Controller.

    All results described below are identical in both configurations:

    I have connected SPI Input to additional IRQ line.

    configured devicetree as follows:

            hps_spim0: spi@0xfff00000 {
                compatible = "snps,dw-spi-mmio-17.0", "snps,dw-spi-mmio", "snps,dw-apb-ssi";
                reg = <0xfff00000 0x00000100>;
                interrupt-parent = <&hps_arm_gic_0>;
                interrupts = <0 154 4>;
                clocks = <&spi_m_clk>;
                #address-cells = <1>;    /* embeddedsw.dts.params.#address-cells type NUMBER */
                #size-cells = <0>;    /* embeddedsw.dts.params.#size-cells type NUMBER */
                bus-num = <0>;    /* embeddedsw.dts.params.bus-num type NUMBER */
                num-chipselect = <4>;    /* embeddedsw.dts.params.num-chipselect type NUMBER */
                status = "okay";    /* embeddedsw.dts.params.status type STRING */

                   VgnADC: voltage-sensor@1 {
                    compatible="adi,ad7791";
                    status = "okay";
                    reg = <0>; //chipselect
                    spi-max-frequency= <128000>;
                    spi-cpha;
                    spi-cpol;
                    vcc-supply = <&adc_supply>;
                        refin-supply = <&adc_vref>;
                    interrupt-parent = <&hps_arm_gic_0>;
                        interrupts = <0 42 4>;
                    #io-channel-cells = <1>;
                   };
                   VtempADC: voltage-sensor@0 {
                    compatible="adi,ad7791";
                    status = "okay";
                    reg = <1>; //chipselect
                    spi-max-frequency= <128000>;
                    spi-cpha;
                    spi-cpol;
                    vcc-supply = <&adc_supply>;
                    refin-supply = <&adc_vref>;
                    interrupt-parent = <&hps_arm_gic_0>;
                    interrupts = <0 42 4>;
                    #io-channel-cells = <1>;
                   };

    or analogously in AlteraSPI case:

                spi_temp: spi@0x100000080 {
                    compatible = "altr,spi-17.0", "altr,spi-1.0";
                    reg = <0x00000001 0x00000080 0x00000020>;
                    interrupt-parent = <&hps_arm_gic_0>;
                    interrupts = <0 40 4>;
                    clocks = <&clkin>;
                    status = "okay";    /* embeddedsw.dts.params.status type STRING */
                    #address-cells = <1>;    /* embeddedsw.dts.params.#address-cells type NUMBER */
                    #size-cells = <0>;    /* embeddedsw.dts.params.#size-cells type NUMBER */
                        spi-cpha;
                        spi-cpol;

                       VtempADC: voltage-sensor@0 {
                        compatible="adi,ad7791";
                        status = "okay";
                        reg = <0>; //chipselect
                        spi-max-frequency= <128000>;
                        //bus-num = <0>;
                        spi-cpha;
                        spi-cpol;
                        //vref-supply = <&adc_vref>;
                        vcc-supply = <&adc_supply>;
                        refin-supply = <&adc_vref>;
                        interrupt-parent = <&hps_arm_gic_0>;
                                //interrupts = <0 154 8>;
                            interrupts = <0 42 4>;
                        #io-channel-cells = <1>;
                       };

                       VgnADC: voltage-sensor@1 {
                        compatible="adi,ad7791";
                        status = "okay";
                        reg = <1>; //chipselect
                        spi-max-frequency= <128000>;
                        spi-cpha;
                        spi-cpol;
                        vcc-supply = <&adc_supply>;
                                refin-supply = <&adc_vref>;
                        interrupt-parent = <&hps_arm_gic_0>;
                                interrupts = <0 42 4>;
                        #io-channel-cells = <1>;
                       };

                }; //end spi@0x100000080 (spi_temp)

    I had to modify IRQ registration procedure in ad_sigma_delta.c file like earlier:

    IRQF_TRIGGER_LOW, -> IRQF_TRIGGER_HIGH | IRQF_SHARED

    In such configuration nothing works, but whatever AD7791 device I delete from devicetree, the other starts to respond.

    with two devices in DT:

    cat in_voltage0-voltage0_raw
    cat: read error: Input/output error

    with one entry in Device Tree:

    cat in_voltage0-voltage0_raw
    8388606

    I would appreciate any help...

  • Please check the number of the interrupts -both slaves are using the interrupt 42.