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.

AM5729: McSPI receive issue

Part Number: AM5729
Other Parts Discussed in Thread: AM3358

I am on the BeagleBone AI (AM5729) and I added this to the dtb:

&mcspi3 {

  #address-cells = <1>;
  #size-cells = <0>;
  status = "okay";
  cs-gpios = <0>, <&gpio7 11 0>;

  channel@0 {
    #address-cells = <1>;
    #size-cells = <0>;
    compatible = "spidev";
    reg = <0>;
    spi-max-frequency = <24000000>;
  };

  channel@1 {
    #address-cells = <1>;
    #size-cells = <0>;
    compatible = "spidev";
    reg = <1>;
    spi-max-frequency = <24000000>;
  };
};

When I try to use the McSPI, the SCLK and MOSI lines work just fine, however I cannot receive any data on the input. I tried both connecting the MISO and MOSI lines together and connecting the MISO line to 3.3V, with no luck.

Here's my code:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>

int main(){
	static struct spi_ioc_transfer transfer_spidev;

	int fd = 0;
	char* spi_dev_path = "/dev/spidev2.0";

	unsigned long spi_bus_speed = 1000000;
	unsigned char spi_chip_select = 0;
	unsigned short spi_delay_us = 0;
	unsigned char spi_bits_no = 8;
	unsigned char spi_mode = SPI_MODE_3;

	/* Open the spidev device */
	if((fd = open(spi_dev_path, O_RDWR))<0)
	{
		perror("SPI: Failed to open spidev1.0 |");
		return -1;
	}

	/* Set the SPI mode for RD and WR operations */
	if(ioctl(fd, SPI_IOC_WR_MODE, &spi_mode)==-1) {
		perror("SPI: Failed to set SPIMODE |");
		return -1;
	}
	if(ioctl(fd, SPI_IOC_RD_MODE, &spi_mode)==-1) {
		perror("SPI: Failed to set SPIMODE |");
		return -1;
	}
	/* Set the No. of bits per transaction */
	if(ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_no)==-1) {
		perror("SPI: Failed to set No. of bits per word |");
		return -1;
	}
	if(ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &spi_bits_no)==-1) {
		perror("SPI: Failed to set No. of bits per word |");
		return -1;
	}

	/* Set the SPI bus speed in Hz */
	if(ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_bus_speed)==-1) {
		perror("SPI: Failed to set SPI bus frequency |");
		return -1;
	}
	if(ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &spi_bus_speed)==-1) {
		perror("SPI: Failed to set SPI bus frequency |");
		return -1;
	}

	/* Initialize the spi_ioc_transfer structure that will be passed to the
	 * KERNEL to define/configure each SPI Transactions*/
	transfer_spidev.tx_buf = 0;
	transfer_spidev.rx_buf = 0;
	transfer_spidev.pad = 0;
	transfer_spidev.tx_nbits = 0;
	transfer_spidev.rx_nbits = 0;
	transfer_spidev.speed_hz = spi_bus_speed;
	transfer_spidev.delay_usecs = spi_delay_us;
	transfer_spidev.bits_per_word = spi_bits_no;
	transfer_spidev.cs_change = spi_chip_select;

	int transmissionLength = 4;
	unsigned char tx_spi[transmissionLength];
	unsigned char rx_spi[transmissionLength];
        tx_spi[0] = 0xff;
        tx_spi[1] = 0x22;
        tx_spi[2] = 0xff;
        tx_spi[3] = 0x0;
	for(int n = 0; n < transmissionLength; ++n)
		rx_spi[n] = 0xA0; // initialize to known value

	while(1) {
	/* Points to the Tx and Rx buffer */
	transfer_spidev.tx_buf = (unsigned long)tx_spi;
	transfer_spidev.rx_buf = (unsigned long)rx_spi;

	/* Override No. of bytes per transaction */
	transfer_spidev.len = transmissionLength;

	/* Perform a SPI Transaction */
	if (ioctl(fd, SPI_IOC_MESSAGE(1), &transfer_spidev)<0)
	{
		perror("SPI: SPI_IOC_MESSAGE Failed |");
		return -1;
	}
	printf("rx_buf [%u]: ", transfer_spidev.len);
	for(int n = 0; n < transfer_spidev.len; ++n)
		printf("0x%02x ", rx_spi[n]);
	printf("\n");

	usleep(100000);
	}
	close(fd);
	return 0;
}

Regardless of whether I connect the MISO line to 3.3V or to MOSI, or leave it unconnected, I alway get as an output:

rx_buf [4]: 0x0 0x0 0x00 0x00

Notes:

- on the am5729 I get the same results (i.e.: no input) with kernel 4.14 and 4.19

- this code works just fine on the am3358 (PocketBeagle).

  • Please make sure that you have configured the SPI clock pin with input enabled. See the Note below Table 24-288 in the AM572x TRM Rev. L for details.

  • Great, that did it, thanks!
    Should the TI pinmux tool not take care of this automatically?
    Also, the note at the bottom of table 24-288 says:

    > For the spim_sclk signals to work properly, the INPUTENABLE bit of the appropriate CTRL_CORE_PAD_x registers should be set to 0x1 because of retiming purposes.

    and did not really serve as a hint for me here: as far as I could tell, the `spim_sclk` signal was working properly, but the spim_d[1] was not.

    Here is the complete, working dtb fragment:

    &dra7_pmx_core {
            mcspi3_pins: pinmux_mcspi3_pins {
                    pinctrl-single,pins = <
                            DRA7XX_CORE_IOPAD(0x3780, MUX_MODE1 | PIN_INPUT) /* AC4: P8.20: mmc3_cmd.spi3_sclk */
                            DRA7XX_CORE_IOPAD(0x3788, MUX_MODE1 | PIN_INPUT) /* AC6: P8.24: mmc3_dat1.spi3_d0 */
                            DRA7XX_CORE_IOPAD(0x3784, MUX_MODE1 | PIN_INPUT) /* AC7: P8.25: mmc3_dat0.spi3_d1 */
                    >;
            };
    };
    &mcspi3 {
            #address-cells = <1>;
            #size-cells = <0>;
            status = "okay";
            pinctrl-names = "default";
            pinctrl-0 = <&mcspi3_pins>;
            //ti,pindir-d0-out-d1-in; //optional, swaps MISO and MOSI pins
    
            cs-gpios = <0>, <&gpio7 11 0>;
    
            channel@0 {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    compatible = "spidev";
                    reg = <0>;
                    spi-max-frequency = <24000000>;
            };
    
            channel@1 {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    compatible = "spidev";
                    reg = <1>;
                    spi-max-frequency = <24000000>;
            };
    };