TX2 SPI4

Just started with TX2, and I’ve problems getting anything out from the SPI on J21. Running R32.1, Jetpack 4.2.

I’ve modified the SPI on 3240000 in the tegra186-quill-p3310-1000-a00-00-base.dtb:

spi@3240000 {
  compatible = "nvidia,tegra186-spi";
  reg = <0x0 0x3240000 0x0 0x10000>;
  interrupts = <0x0 0x27 0x4>;
  iommus = <0x11 0x20>;
  dmas = <0x25 0x12 0x25 0x12>;
  dma-names = "rx", "tx";
  nvidia,clk-parents = "pll_p", "clk_m";
  clocks = <0x10 0x4a 0x10 0x10d 0x10 0x261>;
  clock-names = "spi", "pll_p", "clk_m";
  resets = <0x10 0x2b>;
  reset-names = "spi";
  status = "okay";
  linux,phandle = <0x18f>;
  phandle = <0x18f>;

  spidev@0 {
    compatible = "spidev";
    reg = <0x0>;
    spi-max-frequency = <25000000>;
  };
};

This is compiled with device tree compiler and flashed with flash.sh on host computer.

This is my program on the TX2:

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

struct spi_ioc_transfer xfer;
 
void spi_write(int nbytes,char value[10],int file)
{
    char tx[10];
    char rx[10];

    tx[0] = value[0];
    tx[1] = value[1];

    xfer.tx_buf = (unsigned long)tx;
    xfer.rx_buf = (unsigned long)rx;
    xfer.len = nbytes;
    xfer.speed_hz = 12000000;
    xfer.bits_per_word = 8;
    xfer.delay_usecs = 0;

    printf("Bytes=%d\r\n",ioctl(file, SPI_IOC_MESSAGE(1), xfer));
    printf("TX: %02x %02x\n", tx[0], tx[1]);
    printf("RX: %02x %02x\n", rx[0], rx[1]);
}


void main(void)
{
  char buf[10];

  int file = open("/dev/spidev3.0",O_RDWR);
  buf[0] = 0xf0;
  buf[1] = 0x55;
  spi_write(2,buf,file);
  close(file);
}

I get spidev listed in lsmod and spidev3.0 is in the /dev folder. The result from running as root is:
Bytes=2
TX: f0 55
RX: 00 00

Thankful for any ideas of how to get further, it seems that I’ve missed something.

Please have a reference to below link to check the pinmux for TX2

Thanks for answer.

I’ve been able to make it work when manually setting the pins using
sudo devmem2 0x02430038 w 0x401
sudo devmem2 0x02430040 w 0x455
sudo devmem2 0x02430048 w 0x401
sudo devmem2 0x02430050 w 0x409

Is it possible to implement these settings into the dtb? Could not make the pinmux pyhton script working because it did not find the dtsi file.

The real problem is to implement the SPI4 as slave. I’ve changed the setting:

compatible = “nvidia,tegra124-spi-slave”;

Jetson TX2 will wait for ever for a spi byte when running:
sudo ./devspi_test -D /dev/spidev3.0 -H -b 8

Is there pins or anything else than the devmem2 above that need to be enabled?

No interrupts are piling up. This is from dmesg after ^C:
spi-tegra124-slave 3240000.spi: waiting for master was interrupted
spi_master spi3: failed to transfer one message from queue

Thankful for any help or hints

Did you try to modify the cfg file for TX2

Please can you tell me where it is and what the name of this config file is?

Have reference to below doc.

[url]https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%2520Linux%2520Driver%2520Package%2520Development%2520Guide%2Fmb1_platform_config_tx2.html%23wwconnect_header[/url]

I’ve tried to change the cfg file on the host computer, but the default values will not be loaded.

I’ve changed these memory locations:
sudo devmem2 0x02430038 w 0x445
sudo devmem2 0x02430040 w 0x445
sudo devmem2 0x02430048 w 0x445
sudo devmem2 0x02430050 w 0x449

The slave spi is now kind of working, but it seems that there is only 32 bits buffer. Maximum 4 bytes can be read/written between each cs low pulses. I now transfer 4 times 32 bits, 128 bits totally. I’m not able to read all the data, there should be possible to read more than four bytes at the time. My code is:

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

struct spi_ioc_transfer xfer;
unsigned char tx[320];
unsigned char rx[320];

static __uint32_t mode = 1;
static __uint8_t bits = 8;
static __uint32_t speed = 12000000;

void spi_init(int file)
{
  mode = 1;
  (void)ioctl(file, SPI_IOC_WR_MODE32, &mode);
  mode = 3;
  (void)ioctl(file, SPI_IOC_RD_MODE32, &mode);
}

void spi_write(int file, int len)
{
  char i;

  xfer.tx_buf = (unsigned long)tx;
  xfer.rx_buf = (unsigned long)rx;
  xfer.speed_hz = speed;
  xfer.bits_per_word = 8;
  xfer.len = len;

  (void)ioctl(file, SPI_IOC_MESSAGE(1), xfer);

  for(i = 0; i < len; i++) 
    printf("%02x ", rx[i]);
}

void main(void)
{
  int file = open("/dev/spidev3.0",O_RDWR);
  spi_init(file);
  spi_write(file, 4);
  close(file);
}

Is there full documentation on the SPI slave port somewhere?
I’ve added four SPI clock pulses between each 32 bits when cs is high, do not now if that is needed or if CPU clocks are sufficient (delay).

Is there a way of using the ioctl to read four words or do I need to implement interrupt?

I’m also missing linux/interrupt.h, what do I do to implement/install this?

Thankful for any help.