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.

PROCESSOR-SDK-AM64X: 3-wire SPI configuration in devicetree

Part Number: PROCESSOR-SDK-AM64X

Tool/software:

Hello TI Experts,

I am encountering an issue during the bring-up process of a board. I am using the AM64x EVM kit along with the AD9707 EVM kit. I have successfully configured and tested 4-wire SPI communication on another device. However, the AD9707 specifically supports 3-wire SPI mode.

To enable 3-wire SPI, I added the spi-3wire property in the device tree. However, after loading the compiled DTB file, I encountered an error indicating an unsupported mode. Also tried modifying one another property (ti,pindir-d0-out-d1-in), I modified it like this (ti,pindir-d0-out-d0-in). I would like to confirm if this property is valid or can you please suggest me other options?

I would appreciate your assistance in properly configuring my device to operate in 3-wire SPI mode.

Thanks,
Vraj

  • To enable 3-wire SPI, I added the spi-3wire property in the device tree. However, after loading the compiled DTB file, I encountered an error indicating an unsupported mode.

    The driver currently doesn't support it, here's some more background (different device but same SPI peripheral module): https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1414155/processor-sdk-am335x-support-spi-3-wire/5449211#5449211

    If speed is not a concern you could also use the bit-bang based SPI driver in the kernel as suggested in the above post; this one should support 3-wire mode I think.

    Also often external data converters like what you are using support both SPI and I2C interfaces; so one could consider using I2C instead of SPI to get things working as well. The device you are using however doesn't seem to support I2C so that's not an option. But you could perhaps look at other devices with more "friendly" SPI interfaces.

    Regards, Andreas

  • Thank you for the prompt response.

    Could you please suggest the steps to enable and use a bit-bang-based SPI driver? Any example references would be greatly appreciated.

    Regards,

    Vraj

  • You'll need to re-configure and re-build the Kernel, but with CONFIG_SPI_BITBANG enabled. The SDK documentation has steps on how to do that. Then you'll need an appropriate device tree node, describing your interface, as well as the associated pins (you'd be using the SPI pins in their GPIO capability). You should be able to find examples of all this by just searching the Kernel tree for existing support. If you can't figure it out I can provide some more guidance next week when I'm back in the office.

    Regards, Andreas

  • I have succesfully enabled CONFIG_SPI_BITBANG & CONFIG_SPI_GPIO driver and loaded the image in my destination board.

    Could you please suggest any reference example on how to implement this driver in actual C file. I have modified the device tree like this:

    spi1_gpio: spi1_gpio@0 {
    status = "okay";
    compatible = "spi-gpio";
    pinctrl-names = "default";
    pinctrl-0 = <&main_spi1_pins_default>;
    sck-gpios = <&main_gpio1 49 0>;
    mosi-gpios = <&main_gpio1 45 0>;
    miso-gpios = <&main_gpio1 46 0>;
    cs-gpios = <&main_gpio1 42 0>;
    ti,spi-num-chipselects = <1>;
    spidev@0 {
    spi-max-frequency = <10000>;
    reg = <0>;
    compatible = "rohm,dh2228fv";
    spi-cs-low;
    };

    };


    main_spi1_pins_default: main-spi1-default-pins {
    pinctrl-single,pins = <
    AM64X_IOPAD(0x0224, PIN_OUTPUT_PULLUP, 7) /* (C14) SPI1_CLK, GPIO1_49 */
    AM64X_IOPAD(0x0220, PIN_OUTPUT_PULLUP, 7) /* (D14) SPI1_CS1, GPIO1_43 */
    AM64X_IOPAD(0x021C, PIN_OUTPUT_PULLUP, 7) /* (B14) SPI1_CS0, GPIO1_42 */
    AM64X_IOPAD(0x0228, PIN_OUTPUT, 7) /* (B15) SPI1_D0, GPIO1_45 */
    AM64X_IOPAD(0x022C, PIN_INPUT_PULLUP, 7) /* (A15) SPI1_D1, GPIO1_46 */
    >;
    };


    Can you please also verify if I have modified the devicetree properly?

  • Hi,

    I hope you're doing well.
    Do you have any updates regarding this query?
    Since you were out for the past few days, we have tried a few things and now have some additional questions based on our findings.
    Our SPI bit-bang driver successfully worked for the 4-wire configuration, and we were able to test it. Below is our current DTS configuration:

    "
          spi1_gpio: spi1_gpio@0 {
                   status = "okay";
                   compatible = "spi-gpio";
                   pinctrl-names = "default";
                   pinctrl-0 = <&main_spi1_pins_default>;
                   sck-gpios = <&main_gpio1 49 0>;
                   mosi-gpios = <&main_gpio1 50 0>;
                   miso-gpios = <&main_gpio1 51 0>;
                   cs-gpios = <&main_gpio1 47 0>;
                   num-chipselects = <1>;
                   spidev@0 {
                           spi-max-frequency = <1000>;
                           reg = <0>;
                           compatible = "rohm,dh2228fv";
                   };

           };
    "

    For the 3-wire configuration, we commented out the miso-gpios line and tested our C application, but it was unsuccessful.
    From the waveform, we can see that data is being received on the MOSI line. However, since we commented out the MISO line, the rx_buf in our C application remains empty.
    Could you please guide us on the correct DTS configuration for the 3-wire SPI protocol? Additionally, are there any modifications required in the C application to properly test 3-wire communication?
    We also attempted to change the SPI mode to SPI_3WIRE in the C application, but in this case, we observed no data on the MOSI line, and the clock signal was also absent.
    Looking forward to your insights.

    Best regards,
    Vraj

  • Hi Vraj,

    glad to see you are making some progress.

    For the 3-wire configuration, we commented out the miso-gpios line and tested our C application, but it was unsuccessful.

    For this scenario, did you also add the spi-3wire property back in?

    See this example here: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/arch/arm/boot/dts/st/ste-nomadik-nhk15.dts?h=ti-linux-6.6.y#n228  Please cross-check the general structure of the entire device node.

    Regards, Andreas

  • Hi,

    Yes we have tried this property in dts file too. When we tested our C application using spi-3wire property we were not getting any waveforms in logic analyzer.
    But when we tested the same using echo command "echo -ne "\x80\x00" > /dev/spidev1.0", we were seeing the waveforms on MISO line in logic analyzer.
    Can you please help us with the C application, what should be in our C file to test 3-wire spi?

    I am attaching our C file & dts modifications below.

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/ioctl.h>
    #include <linux/spi/spidev.h>
    
    #define SPI_DEVICE "/dev/spidev1.0"  // Change as per your SPI bus
    //#define SPI_MODE SPI_MODE_0
    #define SPI_MODE SPI_3WIRE
    #define SPI_BITS_PER_WORD 8
    
    #define SPI_SPEED 1000  // 1 Hz
    
    
    int spi_transfer(int fd, uint8_t *tx_buf, uint8_t *rx_buf, size_t len) {
        struct spi_ioc_transfer transfer = {
            .tx_buf = (unsigned long)tx_buf,
            .rx_buf = (unsigned long)rx_buf,
            .len = len,
            .speed_hz = SPI_SPEED,
            .bits_per_word = SPI_BITS_PER_WORD,
            .delay_usecs = 0,
        };
    
        return ioctl(fd, SPI_IOC_MESSAGE(1), &transfer);
    }
    
    uint8_t read_SPI_CTL_reg(int fd){
    	uint8_t SPI_CTL[2] = {0x80, 0x00};
    	uint8_t spi_ctl_res[2] = {0x00, 0x00};
    	int err_code = spi_transfer(fd, (uint8_t *)SPI_CTL, spi_ctl_res, 2);
        // printf("error code : %d\r\n",err_code);
    	// uint8_t ctrl_reg = spi_ctl_res[1];
    	for(int i = 0; i < 2; i++){
    		printf("%02x ", spi_ctl_res[i]);
    	}
    	printf("\r\n");
    	return err_code;	
    }
    
    uint8_t read_version(int fd, uint8_t *buf){
        uint8_t ver_tx_buf[5] = {0xED, 0x00, 0x00, 0x00, 0x00,};
        int err_code = spi_transfer(fd, (uint8_t *)ver_tx_buf, buf, sizeof(ver_tx_buf));
        // printf("error code : %d\r\n",err_code);
        uint8_t version = buf[1];
        return 0;
    }
    
    
    int main() {
        int fd = open(SPI_DEVICE, O_RDWR);
        if (fd < 0) {
            perror("Failed to open SPI device");
            return EXIT_FAILURE;
        }
    
        uint8_t mode = SPI_MODE;
        uint8_t bits = SPI_BITS_PER_WORD;
        uint32_t speed = SPI_SPEED;
    
        ioctl(fd, SPI_IOC_WR_MODE, &mode);
        ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
        ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
    
        int err_code = read_SPI_CTL_reg(fd);
        printf("err_code : 0x%02X\r\n", err_code);
        
        uint8_t ver_rx_buf[5];
        read_version(fd, (uint8_t *)&ver_rx_buf);
        for(int i = 0; i < 5; i++){
            printf("%02X ", ver_rx_buf[i]);
        }
        printf("\r\n");
        close(fd);
        return 0;
    }

    DTS :

    spi1_gpio: spi1_gpio@0 {
              status = "okay";
              compatible = "spi-gpio";
              pinctrl-names = "default";
              pinctrl-0 = <&main_spi1_pins_default>;
              sck-gpios = <&main_gpio1 49 0>;
              mosi-gpios = <&main_gpio1 50 0>;
              /* miso-gpios = <&main_gpio1 51 0>; */
              cs-gpios = <&main_gpio1 47 0>;
              num-chipselects = <1>;
              spidev@0 {
                      spi-max-frequency = <1000>;
                      reg = <0>;
                      spi-3wire;
                      compatible = "rohm,dh2228fv";
              };
    };

    I have tested multiple combinations with same dts file in which I have commented miso line & added 3-wire property.
    1. In C application which I shared above, I am keeping SPI Mode as "SPI_MODE0" and running C application.
    Observation: Data is seen on MOSI line of Logic analyzer but rx_buf remains empty. Attaching capture image from Logic Analyzer.


    2. In C application which I shared above, I am keeping SPI Mode as "SPI_3WIRE" and running C application.
    Observation: No Data is seen on any line. Attaching capture image from Logic Analyzer.


    3. Echo command "echo -ne "\x80\x00" > /dev/spidev1.0"
    Observation: Data is seen on MOSI line of Logic analyzer. But in this scenario how to verify rx_data, where will we get Rx Data? Attaching capture image from Logic Analyzer.

    How can I get my spi-3 wire working?


    Best Regards,

    Vraj

  • Vraj,

    But when we tested the same using echo command "echo -ne "\x80\x00" > /dev/spidev1.0", we were seeing the waveforms on MISO line in logic analyzer.
    Can you please help us with the C application, what should be in our C file to test 3-wire spi?

    You should be using the SPI test example applications part of the Kernel tree as a starting point, such as spidev_test, see: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/tools/spi?h=ti-linux-6.6.y   We cannot provide support debugging any custom userspace application you created in the context of our E2E forum support.

    main_spi1_pins_default: main-spi1-default-pins {
    pinctrl-single,pins = <
    AM64X_IOPAD(0x0224, PIN_OUTPUT_PULLUP, 7) /* (C14) SPI1_CLK, GPIO1_49 */
    AM64X_IOPAD(0x0220, PIN_OUTPUT_PULLUP, 7) /* (D14) SPI1_CS1, GPIO1_43 */
    AM64X_IOPAD(0x021C, PIN_OUTPUT_PULLUP, 7) /* (B14) SPI1_CS0, GPIO1_42 */
    AM64X_IOPAD(0x0228, PIN_OUTPUT, 7) /* (B15) SPI1_D0, GPIO1_45 */
    AM64X_IOPAD(0x022C, PIN_INPUT_PULLUP, 7) /* (A15) SPI1_D1, GPIO1_46 */
    >;
    };

    Also try configuring all those pins to PIN_INPUT, this makes sure the input signal path is enables, and is important for the SPI module to operate properly (all our SysConfig-generated padconfig data is that way, and there is a note in the device TRM regarding this as well). Note that the actual pin direction will be determined by the module using the pin, such as SPI HW module, or GPIO module, so even with PIN_INPUT the pin can work as an output (I know it may sound confusing).

    Regards, Andreas


  • Hi,

    We can understand regarding your restrictions on personal customizations. Can you please provide support with spidev_test application?


    We attempted to test SPI 3-wire mode using the spidev_test application.
    In the current device tree, We have enabled both spi-gpio and spi-3wire properties.
    To activate 3-wire mode in spidev_test, We passed the " -3 " argument. However, based on the error log, it seems that spidev_test is unable to set the 3-wire mode.

    Here is the command we used:

    root@am64xx-evm:~/spi# ./spidev -D /dev/spidev1.0 -3 -p "\x80\x00"

    Output:
    spi mode: 0x10
    bits per word: 8
    max speed: 500000 Hz (500 kHz)
    can't send spi message: Wenvalid argument
    [ 1359.521005] audit: type=1701 audit(1743761242.204:68): auid=4294967295 uid=0 gid=0 ses=4294967295 subj=kernel pid=1519 comm="spidev" exe="/root/spi/spidev" sig=6 res=1
    [ 1359.560629] audit: type=1334 audit(1743761242.244:69): prog-id=41 op=LOAD
    [ 1359.567631] audit: type=1334 audit(1743761242.252:70): prog-id=42 op=LOAD
    [ 1359.575367] audit: type=1334 audit(1743761242.260:71): prog-id=43 op=LOAD
    Aborted (core dumped)


    If we modify the device tree by removing the spi-3wire and spi-gpio properties and use the standard SPI driver instead, we observed the following behavior:

    root@am64xx-evm:~/spi# ./spidev -D /dev/spidev1.0 -3 -p "\x80\x00"

    Output :

    [ 101.130252] spidev spi1.0: setup: unsupported mode bits 10
    can't set spi mode: Wenvalid argument
    [ 101.136426] kauditd_printk_skb: 5 callbacks suppressed
    [ 101.136444] audit: type=1701 audit(1743761437.082:19): auid=4294967295 uid=0 gid=0 ses=4294967295 subj=kernel pid=984 comm="spidev" exe="/root/spi/spidev" sig=6 res=1
    [ 101.209657] audit: type=1334 audit(1743761437.154:20): prog-id=20 op=LOAD
    [ 101.217553] audit: type=1334 audit(1743761437.162:21): prog-id=21 op=LOAD
    [ 101.225534] audit: type=1334 audit(1743761437.162:22): prog-id=22 op=LOAD
    Aborted (core dumped)

    Can you please provide your guidance in testing spi-3wire protocol with spidev_test application?

    Best Regards,

    Vraj

  • Andreas,

    Do we have any update on this thread?

    Regards,

    Vraj

  • Hi Vraj,

    the `spi-gpio.c` driver should support 3-wire mode as evident by several 3-wire SPI mode references in that code (SPI_3WIRE*), so I think the issue is with how that driver is configured or used.

    Can you update the `spidev_test.c` application as shown below to only transmit and not receive at the same time to see if this makes a difference.

    $ git diff
    diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
    index f2135d619a0b..ba59bf9f5510 100644
    --- a/tools/spi/spidev_test.c
    +++ b/tools/spi/spidev_test.c
    @@ -352,7 +352,7 @@ static void transfer_escaped_string(int fd, char *str)
                    pabort("can't allocate rx buffer");
    
            size = unescape((char *)tx, str, size);
    -       transfer(fd, tx, rx, size);
    +       transfer(fd, tx, NULL, size);
            free(rx);
            free(tx);
     }

    Regards, Andreas