How to set to spi slave mode

Hello

I want to run spi test by connecting spi1 and spi3 of jetson xavier nx board.
Before connecting spi1-spi3, I connected spi1’s MOSI-MISO (spi3’s MOSI-MISO) and tested with the spidev_test.c example to confirm that tx rx works well for both spi1 and spi3.
(Currently jetson xavier nx board has jetpack4.4 version installed.)
Here I have some questions.

  1. How to set the master mode and slave mode when connecting spi1 and spi3? (Should I update pinmux? or
    https://www.jetsonhacks.com/2020/05/04/spi-on-jetson-using-jetson-io/ like this link on jetson?
  1. https://forums.developer.nvidia.com/t/spi-cant-work-in-slave-mode-on-xavier/128835
    If I set it like this post, does it become slave mode?
    If so, 1) how to configure the device tree and 2) how to add properties?
  1. How to connect spi1-spi3 between the two methods below?
  1. spi1 MISO ↔ spi3 MISO / spi1 MOSI ↔ spi3 MOSI / spi1 SCK<-> spi3 SCK / spi1 CS0 ↔ spi CS0
    2)spi1 MISO ↔ spi3 MOSI / spi1 MOSI ↔ spi3 MISO / spi1 SCK<-> spi3 SCK / spi1 CS0 ↔ spi CS0
  1. How to do rx in spi slave?
    Does an interrupt appear when data comes in?
    Looking at the spi example (spidev_test.c), ioctl(fd, SPI_IOC_MESSAGE(1), &tr) is used to check tx and rx. Is this the only way to check rx?
    If you check rx with ioctl(fd, SPI_IOC_MESSAGE(1), &tr), how do you know if the data has come in?
    Are there any c++ examples of spi slaves?

Thank you.

For 1 and 2.
Configure as below. Add tegra124-spi-slave to the device tree.

  1. Should be 1

  2. open ssh terminal and start the spi slave first with following command
    "./spidev_test -D /dev/spidev0.0 -s 150000 -n100 -g30 -p4 -z
    In another terminal start the spi master with following command
    “./spidev_test -D /dev/spidev3.1 -s 150000 -n100 -g30 -p4 -z”

Thank you for answering.

I tried testing the slave mode as indicated, but I got an’invalid option’ error.
I downloaded the source from this link and tested it.

As you told me, how do I get ./spidev_test -D /dev/spidev0.0 -s 150000 -n100 -g30 -p4 -z to run?

This’s build by my tree. Remove the .txt and change it as executable file.

spidev_test.txt (69.1 KB)

I saw this link and tried to follow it, but I’m not sure.
I proceeded in the following way to modify dts.

1.Run /opt/nvidia/jetson-io/jetson-io.py and activate spi1, spi3
2. sudo dtc -I dts -O dtb -o ~/user-custom.dts /boot/tegra194-p3668-all-p3509-0000-user-custom.dtb
3. Modify user-custom.dts

spi@3210000 {
compatible = “nvidia,tegra186-spi”;
reg = <0x0 0x3210000 0x0 0x10000>;
interrupts = <0x0 0x24 0x4>;
#address-cells = <0x1>;
#size-cells = <0x0>;
iommus = <0x2 0x20>;
dma-coherent;
dmas = <0x19 0xf 0x19 0xf>;
dma-names = “rx”, “tx”;
spi-max-frequency = <0x3dfd240>;
nvidia,clk-parents = “pll_p”, “clk_m”;
clocks = <0x4 0x87 0x4 0x66 0x4 0xe>;
clock-names = “spi”, “pll_p”, “clk_m”;
resets = <0x5 0x5b>;
reset-names = “spi”;
status = “okay”;
linux,phandle = <0xf2>;
phandle = <0xf2>;
spi@0 {
compatible = “spidev”;
reg = <0x0>;
spi-max-frequency = <0x2faf080>;
controller-data {
nvidia,enable-hw-based-cs;
nvidia,rx-clk-tap-delay = <0x10>;
nvidia,tx-clk-tap-delay = <0x0>;
};
};
spi@1 {
compatible = “spidev”;
reg = <0x1>;
spi-max-frequency = <0x2faf080>;
controller-data {
nvidia,enable-hw-based-cs;
nvidia,rx-clk-tap-delay = <0x10>;
nvidia,tx-clk-tap-delay = <0x0>;
};
};
};
spi@3230000 {
compatible = “nvidia,tegra186-spi-slave”;
reg = <0x0 0x3230000 0x0 0x10000>;
interrupts = <0x0 0x26 0x4>;
#address-cells = <0x1>;
#size-cells = <0x0>;
iommus = <0x2 0x20>;
dma-coherent;
dmas = <0x19 0x11 0x19 0x11>;
dma-names = “rx”, “tx”;
spi-max-frequency = <0x3dfd240>;
nvidia,clk-parents = “pll_p”, “clk_m”;
clocks = <0x4 0x89 0x4 0x66 0x4 0xe>;
clock-names = “spi”, “pll_p”, “clk_m”;
resets = <0x5 0x5d>;
reset-names = “spi”;
status = “okay”;
linux,phandle = <0xf4>;
phandle = <0xf4>;
spi@0 {
compatible = “spidev”;
reg = <0x0>;
spi-max-frequency = <0x2faf080>;
controller-data {
nvidia,enable-hw-based-cs;
nvidia,rx-clk-tap-delay = <0x10>;
nvidia,tx-clk-tap-delay = <0x0>;
};
};
spi@1 {
compatible = “spidev”;
reg = <0x1>;
spi-max-frequency = <0x2faf080>;
controller-data {
nvidia,enable-hw-based-cs;
nvidia,rx-clk-tap-delay = <0x10>;
nvidia,tx-clk-tap-delay = <0x0>;
};
};
};

  1. sudo dtc -I dts -O dtb -o /boot/tegra194-p3668-all-p3509-0000-user-custom.dtb ~/user-custom.dts
  2. reboot

By modifying dts in this way, spi1(master, spidev0.0), spi3(slave, spidev2.0) were connected and executed as follows.

./spidev_test -D /dev/spidev2.0 -s 150000 -n10000 -g30 -p4 -z

./spidev_test -D /dev/spidev0.0 -s 150000 -n10000 -g30 -p4 -z

(The photo shows’./spidev_test -D /dev/spidev0.0 -s 150000 -n10000 -g30 -p4 -z -r’, but When I used ‘./spidev_test -D /dev/spidev0.0 -s 150000 -n10000- g30 -p4 -z’ , the result was the same.)

The result is shown in the photo.


When I ran it in slave mode, a transfer error occurred and the master was test failed.

What did I do wrong?

Have devmem2 to read those REG to confirm the setting.

Are jetson xaiver nx the same as the register value in this post?
Should I change the register values of spi1 and spi3 the same?

Jetson NX is the same chip with Xavier

I still get the error though.
Instead of flashing by modifying pinmux, I used devmem2 to temporarily change the register value.

when checking dmesg, the following error appears.

[ 280.340212] spi-tegra124-slave 3230000.spi: Tx is not supported in mode 0
[ 280.340215] spi-tegra124-slave 3230000.spi: spi can not start transfer, err -22
[ 280.340301] spi_master spi2: failed to transfer one message from queue

Below is suggest.

Have connected -> SPI1_MOSI<-->SPI3_MISO, SPI1_CLK<-->SPI3_CLK, SP1_CS0 <--> SPI3_CS0  and SPI1_CS1->SPI3_CS1.

SPI1 has to be configured as Master and SPI3 has to be configured as slave in the dt and pinmux settings have to be updated. 
SPI1 DT:    
spi@3210000 {
        status = "okay";
        compatible = "nvidia,tegra186-spi";
        spi@0 {
            compatible = "spidev";
            reg = <0>;
            spi-max-frequency = <65000000>;
            controller-data {
                nvidia,enable-hw-based-cs;
            };
        };
    };

SPI3 DT
    spi@3230000 {
        status = "okay";
        compatible = "nvidia,tegra186-spi-slave";
        spi@0 {
            compatible = "spidev";
            reg = <0>;
            spi-max-frequency = <65000000>;
            controller-data {
                nvidia,enable-hw-based-cs;
            };
        };
     };

PINMUX settings are listed below for SPI1 and SP13 for loopback. (Note: SPI1 and SP3 have an internal loopback connection for Xavier)

SPI_1 pinmux settings:
PADCTL_UART_SPI1_MISO_0  (0x0243d020) =  0x440;
PADCTL_UART_SPI1_MOSI_0 (0x0243d058) =  0x440;
PADCTL_UART_SPI1_SCK_0 (0x0243d040) =  0x440;
PADCTL_UART_SPI1_CS0_0 (0x0243d010) =  0x448;
PADCTL_UART_SPI1_CS1_0 (0x0243d050) =  0x448;

SPI_3 pinmux settings:
PADCTL_UART_SPI3_MISO_0  (0x0243d008) =  0x440;
PADCTL_UART_SPI3_MOSI_0 (0x0243d060) =  0x440;
PADCTL_UART_SPI3_SCK_0 (0x0243d048) =  0x444;
PADCTL_UART_SPI3_CS0_0 (0x0243d018) =  0x448;
PADCTL_UART_SPI3_CS1_0 (0x0243d028) =  0x448;

There are a few things I’d like to ask in your answer.

  1. Do you connect SPI1_MOSI<–>SPI3_MISO?
    Why connect MOSI and MISO?
    SPI1_MISO<–> Why doesn’t SPI3_MOSI connect?

  2. Do I need to update the pinmux setting by changing from dt to slave means I have to flash again?
    Can’t I do it in the following way?

(1) Activate spi1, spi3 in /opt/nvidia/jetson-io/jetson-io.py
(2) dtb decompile
—> sudo dtc -I dtb -O dts -o ~/ user-custom.dts / boot / tegra194-p3668-all- p3509-0000-user-custom.dtb
(3) Open the ~/ user-custom.dts file and change spi3(spi@3230000) to slave
(compatible = “nvidia, tegra186-spi” → compatible = “nvidia, tegra186-spi-slave”)
(4) dts compilation
—> sudo dtc -I dts -O dtb -o /boot/tegra194-p3668-all- p3509-0000-user-custom.dtb ~/user-custom.dts
(5) reboot jetson
(6) Change reg value using devmem2 (temporary)
(7) Connection: SPI1_MOSI<–>SPI3_MISO, SPI1_CLK<–>SPI3_CLK, SP1_CS0 ↔ SPI3_CS0 and SPI1_CS1<–>SPI3_CS1
(8) test

  1. Where is the dt file? (Where should I change the spi3 slave?)

  2. Where do I change the reg? Do I change it in my cfg (galen.cfg)?

  3. Is the pinmux update method correct?

&&pinmux update method&&
(1) Jetson_Xavier_NX_Pinmux_Configuration_Template_v1.06 Set pinmux with .xlsm and create DT
(tegra19x-jetson_xavier_nx_module-gpio-default.dtsi, tegra19x-jetson_xavier_nx_module-padvoltage-default.dtsi, tegra19x-jetson_xavier_nx_module-pinmux.dtsi)
(2) Install Linux_for_Tegra with SDK Manager on Linux host PC
(3) Go to /Linux_for_Tegra/kernel/pinmux/t19x
(4) Import the dtsi( tegra19x-jetson_xavier_nx_module-gpio-default.dtsi, tegra19x-jetson_xavier_nx_module-padvoltage-default.dtsi, tegra19x-jetson_xavier_nx_module-pinmux.dtsi) file to the Linux host PC and create a cfg file.
----> python pinmux-dts2cfg.py --pinmux addr_info.txt gpio_addr_info.txt por_val.txt tegra19x-jetson_xavier_nx_module-pinmux.dtsi tegra19x-jetson_xavier_nx_module-gpio-default.dtsi 1.0>galen.cfg <------------
(5) Change galen.cfg to /Linux_for_Tegra/bootloader/t186ref/BCT/tegra19x-mb1-pinmux-p3668-a01
(6) Flash with sdk manager (or sudo ./flash.sh jetson-xavier-nx-devkit mmcblk0p1

  1. Can you give me the source file of spi_test.txt that you gave me?
    I want to know how to slave (functions used, interrupts, etc.)
  1. Should be SPI1_MOSI<- ->SPI3_MOSI, SPI1_MISO<- ->SPI3_MISO, SPI1_CLK<–>SPI3_CLK, SP1_CS0 <–> SPI3_CS0 and SPI1_CS1->SPI3_CS1.

  2. You can try devmem2 to write those pinmux setting.

  3. You can still update the dtb like as you do before. How to set to spi slave mode - #6 by _JJANG

  4. change the cfg file …/Linux_for_Tegra/bootloader/t186ref/BCT/ and check with devmem2 would be good.

  5. Correct.

  6. It’s public source. linux/spidev_test.c at master · torvalds/linux · GitHub

When testing by connecting spi1(master)-spi3(slave), should I connect both SP1_CS0 <–> SPI3_CS0 and SPI1_CS1->SPI3_CS1?
Do you connect only one of cs0 or cs1?

Here you are told to run the command
./spidev_test -D /dev/spidev0.0 -s 150000 -n100 -g30 -p4 -z,
but the source code you gave me does not have the -g, -p, -z, -n options.

Also, how do I test master(spi1) -slave(spi3) with this code?
I need to run the slave first and then the master, but when I run the slave (/dev/spidev2.0) I get an error.

can’t send spi message: Invalid argument
Aborted (core dumped)
<<<<< dmesg >>>>>>
spi-tegra124-slave 3230000.spi: Tx is not supported in mode 0
spi-tegra124-slave 3230000.spi: spi can not start transfer, err -22
spi_master spi2: failed to transfer one message from queue

Before make it working I would suggest to connect both of the cs0 and cs1.
Run the master first may be make a script like

./spidev_test -D /dev/spidev0.0 -s 150000 -n100 -g30 -p4 -z
sleep 1
./spidev_test -D /dev/spidev0.1 -s 150000 -n100 -g30 -p4 -z

I want to test by connecting spi1(master)-spi3(slave)!
Master doesn’t want to know
An error occurs when executing the slave mode program.
I modified dt and reg value as you tell me to do, but when I run the program an error occurs.

can’t send spi message: Invalid argument
Aborted (core dumped)
<<<<< dmesg >>>>>>
spi-tegra124-slave 3230000.spi: Tx is not supported in mode 0
spi-tegra124-slave 3230000.spi: spi can not start transfer, err -22
spi_master spi2: failed to transfer one message from queue

Please tell me how to run the program in slave mode.

Have a try below command.

./spidev_test -D /dev/spidev0.0 -s 150000 -n100 -g30 -p4 -z & ./spidev_test -D /dev/spidev2.1 -s 150000 -n100 -g30 -p4 -z

https://github.com/torvalds/linux/blob/master/tools/spi/spidev_test.c
This source code is ./spidev_test -D /dev/spidev0.0 -s 150000 -n100 -g30 -p4 -z & Can you run ./spidev_test -D /dev/spidev2.1 -s 150000 -n100 -g30 -p4 -z command?

Why do you need the source?
This binary should be modify by internal developer for some case. I think the public source should be OK for the test.

If you look at the error that occurs when you run the program, it seems that there is a problem with tx in slave mode.
So I want to see the source code.

can’t send spi message: Invalid argument
Aborted (core dumped)
<<<<< dmesg >>>>>>
spi-tegra124-slave 3230000.spi: Tx is not supported in mode 0
spi-tegra124-slave 3230000.spi: spi can not start transfer, err -22
spi_master spi2: failed to transfer one message from queue

https://github.com/torvalds/linux/blob/master/tools/spi/spidev_test.c
Was this source code program tested in slave mode?

I did what you said
1. Modify dt to slave(/boot/tegra194-p3668-all-p3509-0000-user-custom.dtb)


2. Change reg value

3. Connection: SPI1 MOSI (pin 19) ↔ SPI3 MOSI (pin 37), SPI1 MISO (pin 21) ↔ SPI3 MISO (pin 22), SPI1 SCK (pin 23) ↔ SPI3 SCK (pin 13), SPI1 CS0 (pin 24) ↔ SPI3 CS0 (pin 18), SPI1 CS1 (pin 26) ↔ SPI3 CS1 (pin 16)

But why do I still get the error in slave mode?

And I have another question.
In the source code, ioctl(fd, SPI_IOC_MESSAGE(1), &tr) sends and receives data to tx,rx included in the tr structure.
Do you use ioctl(fd, SPI_IOC_MESSAGE(1), &tr) to send and receive data even in slave mode?

Why!!! Can’t I!!!
What else do I need to fix?
Or do I need to create a new driver for the slave?
Should I create a new test program?

Will have a check with developer to verify the loopback mode on NX.