TX2 SPI/SPIDEV receiving shifted data.

The TX2 SPIdev driver seems to be receiving data that is right shifted (>>) by one bit. I have verified that the DUT is sending correct data on an oscilloscope. The output of the decoded transfer reads:
0x70 0x00 0x0D 0x30 0x73 0xBA …
while the buffer dump read from spidev reads the following
0x38 0x00 0x06 0x18 0x39 0xdc …

performing a binary comparison on the two data sequences it becomes apparent that the spidev data is shifted by one bit, performing a software left shift (<<) corrects the error but the last bit is lost in the data transfer. I have also tested using a kernel module and spi_read() with the same outcome.

I am using spi mode 3 with SPI_CPOL and SPI_CPHA bits set. The scope decode is set to sample on CLK rising edge with MISO “1” being active high to match mode 3.

For reference when the test code was tested on a raspberry pi 3B it produced correct results.

Is this a known issue and is there a fix available?

Could you try add below to your DT to try.

spi@3210000 {
                           prod-settings {
                                         mask-one-style;
                                         prod_c_cs0 {
                                         /* enabled for spi flash rom */
                                             prod = <0x04 0x00000fc0 0x00000400>;
                                         /* enabled for spi loopback mode */
                                             /*prod = <0x04 0x00000fc0 0x00000400>;*/
                                         };
                           };
              };

              spi@c260000 {
                           prod-settings {
                                         mask-one-style;
                                         prod_c_cs0 {
                                         /* enabled for spi flash rom */
                                             prod = <0x04 0x00000fc0 0x00000400>;
                                         /* enabled for spi loopback mode */
                                             /*prod = <0x04 0x00000fc0 0x00000400>;*/
                                         };
                           };
              };

              spi@3230000 {
                           prod-settings {
                                         mask-one-style;
                                         prod_c_cs0 {
                                         /* enabled for spi flash rom only */
                                             prod = <0x04 0x0000003f 0x00000008>;
                                         /* enabled for spi loopback mode */
                                             /*prod = <0x04 0x00000fc0 0x0000043f>;*/
                                         };
                           };
              };

              spi@3240000 {
                           prod-settings {
                                         mask-one-style;
                                         prod_c_cs0 {
                                         /* enabled for spi flash rom only */
                                             prod = <0x04 0x0000003f 0x00000008>;
                                         /* enabled for spi loopback mode */
                                             /*prod = <0x04 0x00000fc0 0x0000043f>;*/
                                         };
                           };
              };

Unfortunately that did not work, I should mention that currently the speed I am running at is 20MHz. The shift bug seems to remove itself if I run at a lower clock of 18MHz.
For reference The OEM product design guide says the max frequency is 65 MHz so 20 MHz is not outside the usable clock range.
Here is the full node for spi3 which I am using to test.

spi3: spi@3240000 {
		compatible = "nvidia,tegra186-spi";
		reg = <0x0 0x03240000 0x0 0x10000>;
		interrupts = <0 39 0x04>;
		nvidia,dma-request-selector = <&gpcdma 18>;
		#address-cells = <1>;
		#size-cells = <0>;
		#stream-id-cells = <1>;
		dmas = <&gpcdma 18>, <&gpcdma 18>;
		dma-names = "rx", "tx";
		nvidia,clk-parents = "pll_p", "clk_m";
		clocks = <&tegra_car TEGRA186_CLK_SPI4>,
			<&tegra_car TEGRA186_CLK_PLLP_OUT0>,
			<&tegra_car TEGRA186_CLK_CLK_M>;
		clock-names = "spi", "pll_p", "clk_m";
		resets = <&tegra_car TEGRA186_RESET_SPI4>;
		reset-names = "spi";
		status = "disabled";
		//nvidia,polling-mode;
		nvidia,disable-runtime-pm;
		prod-settings {
			mask-one-style;
			prod_c_cs0 {
			/* enabled for spi flash rom only */
				prod = <0x04 0x0000003f 0x00000008>;
			/* enabled for spi loopback mode */
				/*prod = <0x04 0x00000fc0 0x0000043f>;*/
			};
		};
		spi@0 {
			compatible = "spidev";
			reg = <0x0>;
			spi-max-frequency = <0x1312D00>;
			nvidia,enable-hw-based-cs;
			nvidia,cs-setup-clk-count = <0x1>;
			nvidia,cs-hold-clk-count = <0x1>;
			nvidia,rx-clk-tap-delay = <0x0>;
			nvidia,tx-clk-tap-delay = <0x0>;
		};
	};

Could you check SPI_COMMAND2_x register as below.

03210004: SPI_COMMAND2_0 [5:0] = 0xa
0c260004: SPI_COMMAND2_1 [5:0] = 0xc
03230004: SPI_COMMAND2_2 [5:0] = 0xc
03240004: SPI_COMMAND2_3 [5:0] = 0x8

I am not sure how to successfully read from these address locations. I’ve tried the included busybox devmem as well as making a kernel module and using readl both of which fail causing a kernel panic.
here’s the panic log

[  504.325405] CPU3: SError detected, daif=1c0, spsr=0x800000c5, mpidr=8000010
[  504.325418] CPU0: SError detected, daif=1c0, spsr=0x800000c5, mpidr=80000100, esr=bf40c000
[  504.325476] CPU4: SError detected, daif=140, spsr=0x40000145, mpidr=80000102, esr=bf40c000
[  504.325507] CPU5: SError detected, daif=140, spsr=0x40000045, mpidr=80000103, esr=bf40c000
[  504.325519] **************************************
[  504.325535] CPU0 Machine check error in AXI2APB@0x2390000:
[  504.325555] Raw FIFO Entry: 0
[  504.325562]  ADDR: 0x43210000
[  504.325567]  STAT: 0x11868241
[  504.325574] --------------------------------------
[  504.325579] Decoded FIFO Entry: 0
[  504.325585]  Direction: READ
[  504.325591]  Bridge ID: 0x1
[  504.325599]  Error Type: 0x12 -- Timeout error
[  504.325603]  Length: 0
[  504.325616]  Protection: 0x2 -- Unprivileged, Non-Secure, Data Access
[  504.325624]  Source ID: 0x1 -- CCPLEX
[  504.325635]  AXI_ID: 0x6 -- A57 Core 2
[  504.325640]  Cache: 0x1 -- Device
[  504.325647]  Burst: 0x1
[  504.325792]  Address: 0x3210000 -- /spi@3210000 + 0x0
[  504.325797] **************************************
[  504.336933] ROC:IOB Machine Check Error:
[  504.336964]  Address Type = Secure DRAM
[  504.337122]  Address = 0x0 (Unknown Device)
[  504.337401] Bad mode in Error handler detected, code 0xbf40c000 -- SError
[  504.337423] Internal error: Oops - bad mode: 0 [#1] PREEMPT SMP
[  504.337525] Modules linked in: regdump(O+) fuse ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_natm
[  504.337557] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G        W  O    4.4.38 #2
[  504.337563] Hardware name: quill (DT)
[  504.337576] task: ffffffc001256240 ti: ffffffc001244000 task.ti: ffffffc001244000
[  504.337639] PC is at t18x_a57_enter_state+0x48/0xc4
[  504.337650] LR is at t18x_a57_enter_state+0x20/0xc4
[  504.337660] pc : [<ffffffc00092f04c>] lr : [<ffffffc00092f024>] pstate: 800000c5
[  504.337665] sp : ffffffc001247e70
[  504.337677] x29: ffffffc001247e70 x28: ffffffc001244000 
[  504.337688] x27: ffffffc000b61f00 x26: 000000756eade5f3 
[  504.337698] x25: ffffffc0013cf000 x24: 0000000000000000 
[  504.337708] x23: ffffffc00135a1c8 x22: ffffffc00135a1e0 
[  504.337718] x21: ffffffc0013cf288 x20: ffffffc001499bb8 
[  504.337729] x19: 0000000000000000 x18: 000000000340002f 
[  504.337738] x17: 0000007f9bbdff18 x16: ffffffc000b62a60 
[  504.337748] x15: 00000000fa83b2da x14: 0000000000219b39 
[  504.337757] x13: 0000000000000000 x12: 0000000000219b39 
[  504.337766] x11: 0000000000000400 x10: 00000000000008b0 
[  504.337777] x9 : ffffffc001247e70 x8 : ffffffc001256b50 
[  504.337786] x7 : 0000000000000000 x6 : 0000000000022f7c 
[  504.337795] x5 : 0000000000000000 x4 : 00ffffffffffffff 
[  504.337804] x3 : 000000003b9aca00 x2 : 00000000003c28ce 
[  504.337813] x1 : 0000000000000000 x0 : 0000000000000000 
[  504.337815] 
[  504.337825] Process swapper/0 (pid: 0, stack limit = 0xffffffc001244020)
[  504.337833] Call trace:
[  504.337847] [<ffffffc00092f04c>] t18x_a57_enter_state+0x48/0xc4
[  504.337882] [<ffffffc000800bd0>] cpuidle_enter_state+0x88/0x2dc
[  504.337891] [<ffffffc000800e5c>] cpuidle_enter+0x18/0x20
[  504.337923] [<ffffffc0000e8354>] call_cpuidle+0x28/0x50
[  504.337936] [<ffffffc0000e84f8>] cpu_startup_entry+0x17c/0x340
[  504.337967] [<ffffffc000b51f10>] rest_init+0x84/0x8c
[  504.338005] [<ffffffc0010fe980>] start_kernel+0x3a0/0x3b4
[  504.338015] [<0000000080b58000>] 0x80b58000
[  504.338752] SPI_COMMAND2_0 = 0xdead1009
[  504.341348] ---[ end trace a1efb62fabe870ce ]---
[  504.347783] Kernel panic - not syncing: Attempted to kill the idle task!
[  504.347810] CPU4: stopping
[  504.347834] CPU: 4 PID: 3372 Comm: sudo Tainted: G      D W  O    4.4.38 #2
[  504.347837] Hardware name: quill (DT)
[  504.347845] Call trace:
[  504.347904] [<ffffffc000089860>] dump_backtrace+0x0/0x100
[  504.347920] [<ffffffc000089a28>] show_stack+0x14/0x1c
[  504.347952] [<ffffffc00033cdf8>] dump_stack+0x98/0xc0
[  504.347967] [<ffffffc00008f468>] handle_IPI+0x300/0x30c
[  504.347983] [<ffffffc0000817b4>] gic_handle_irq+0x9c/0xb4
[  504.347993] [<ffffffc000084740>] el1_irq+0x80/0xf8
[  504.348022] [<ffffffc00019fa68>] unmap_vmas+0x58/0x70
[  504.348040] [<ffffffc0001a4400>] unmap_region+0x88/0xe0
[  504.348046] [<ffffffc0001a557c>] do_munmap+0x224/0x32c
[  504.348051] [<ffffffc0001a56c8>] vm_munmap+0x44/0x64
[  504.348060] [<ffffffc0001a7488>] SyS_munmap+0xc/0x18
[  504.348071] [<ffffffc000084ff0>] el0_svc_naked+0x24/0x28
[  504.348080] CPU5: stopping
[  504.348094] CPU: 5 PID: 773 Comm: in:imuxsock Tainted: G      D W  O    4.4.38 #2
[  504.348099] Hardware name: quill (DT)
[  504.348102] Call trace:
[  504.348119] [<ffffffc000089860>] dump_backtrace+0x0/0x100
[  504.348131] [<ffffffc000089a28>] show_stack+0x14/0x1c
[  504.348142] [<ffffffc00033cdf8>] dump_stack+0x98/0xc0
[  504.348152] [<ffffffc00008f468>] handle_IPI+0x300/0x30c
[  504.348159] [<ffffffc0000817b4>] gic_handle_irq+0x9c/0xb4
[  504.348166] [<ffffffc000084740>] el1_irq+0x80/0xf8
[  504.348195] [<ffffffc0001f0734>] __fget_light+0x30/0x7c
[  504.348203] [<ffffffc0001f0790>] __fdget+0x10/0x18
[  504.348239] [<ffffffc0009a1ac8>] sockfd_lookup_light+0x14/0x80
[  504.348252] [<ffffffc0009a3914>] __sys_recvmsg+0x24/0x84
[  504.348257] [<ffffffc0009a3984>] SyS_recvmsg+0x10/0x20
[  504.348265] [<ffffffc000084ff0>] el0_svc_naked+0x24/0x28
[  504.823111] CPU3: stopping
[  504.825865] CPU: 3 PID: 0 Comm: swapper/3 Tainted: G      D W  O    4.4.38 #2
[  504.833015] Hardware name: quill (DT)
[  504.836693] Call trace:
[  504.839167] [<ffffffc000089860>] dump_backtrace+0x0/0x100
[  504.844586] [<ffffffc000089a28>] show_stack+0x14/0x1c
[  504.849658] [<ffffffc00033cdf8>] dump_stack+0x98/0xc0
[  504.854731] [<ffffffc00008f468>] handle_IPI+0x300/0x30c
[  504.859971] [<ffffffc0000817b4>] gic_handle_irq+0x9c/0xb4
[  504.865387] [<ffffffc000084740>] el1_irq+0x80/0xf8
[  504.870210] [<ffffffc0000a91b0>] irq_exit+0x84/0xdc
[  504.875116] [<ffffffc0000f4f84>] __handle_domain_irq+0x6c/0xb4
[  504.880965] [<ffffffc000081774>] gic_handle_irq+0x5c/0xb4
[  504.886380] [<ffffffc000084740>] el1_irq+0x80/0xf8
[  504.891200] [<ffffffc000800e5c>] cpuidle_enter+0x18/0x20
[  504.896536] [<ffffffc0000e8354>] call_cpuidle+0x28/0x50
[  504.901781] [<ffffffc0000e84f8>] cpu_startup_entry+0x17c/0x340
[  504.907631] [<ffffffc00008ee44>] secondary_start_kernel+0x12c/0x164
[  504.913922] [<0000000080081acc>] 0x80081acc
[  504.952024] Rebooting in 5 seconds..

Please modify the REG by SPI driver.

kernel/kernel-4.4/drivers/spi/spi-tegra114.c

I placed the following line of code after line 2018 which already reads the register in spi-tegra114.c

dev_info(&pdev->dev, "SPI_COMMAND2 = 0x%08x\n", tspi->command2_reg);

the output was the following

[    3.947431] spi-tegra114 3210000.spi: SPI_COMMAND2 = 0x00000000
[    3.948040] spi-tegra114 c260000.spi: SPI_COMMAND2 = 0x00000000
[    3.948815] spi-tegra114 3240000.spi: SPI_COMMAND2 = 0x00000000

I’ve decompiled the dtb in the Linux_for_Tegra/kernel/dtb that was flashed to the board and it does contain the prod-settings node but it seems the setting doesn’t take effect.

Same problem here! I’ve followed https://elinux.org/Jetson/TX2_SPI to enable the spi interface and dtb looks like this:

spi@3240000 {
		compatible = "nvidia,tegra186-spi";
		reg = <0x0 0x3240000 0x0 0x10000>;
		interrupts = <0x0 0x27 0x4>;
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		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>;
		spi@0 {
		      compatible = "spidev";
		      reg = <0x0>;
		      spi-max-frequency = <0x112a880>;
		      nvidia,enable-hw-based-cs;
		      nvidia,cs-setup-clk-count = <0x1e>;
		      nvidia,cs-hold-clk-count = <0x1e>;
		      nvidia,rx-clk-tap-delay = <0x1f>;
		      nvidia,tx-clk-tap-delay = <0x0>;
    		}; 
	};

The /dev/spidev3.0 system file shows correctly and so on… The pinmux configuration is as shown in the guide. I’m using Jetpack 4.2.2.

In first instance I’ve made a test in loopback, using this example GitHub - rm-hull/spidev-test, and it seamed to work fine.

Now using it with an rf24 module (so the clk pin is needed) the byte received seams to be shifted right by one. Do you have any idea of how to solve this problem??

Thanks for the help!

I am not sure as to the solution to your issue. however I have found from looking at the spidev source that most of the examples online and on this fourm relating to enabling spidev miss a critical node in the device tree.

The following items “nvidia,xxxxx” should not be in the main node for the spidev device. They should be in a node called controller-data to enable hardware cs and set delays properly.

spi@0 {
		      compatible = "spidev";
		      reg = <0x0>;
		      spi-max-frequency = <0x112a880>;
		      nvidia,enable-hw-based-cs;
		      nvidia,cs-setup-clk-count = <0x1e>;
		      nvidia,cs-hold-clk-count = <0x1e>;
		      nvidia,rx-clk-tap-delay = <0x1f>;
		      nvidia,tx-clk-tap-delay = <0x0>;
};

should be

spi@0 {
			compatible = "spidev";
			reg = <0x0>;
			spi-max-frequency = <17000000>;
			spi-cpol = <1>;
			spi-cpha = <1>;
			controller-data {
				nvidia,enable-hw-based-cs;
				nvidia,cs-setup-clk-count = <0x3>;
				nvidia,cs-hold-clk-count = <0x3>;
				nvidia,rx-clk-tap-delay = <0x0>;
				nvidia,tx-clk-tap-delay = <0x0>;
			};
};

Hi Anthony35416,

In first instance, thanks for your help!

Unfortunately, I’ve tried as you mentioned but it doesn’t solve my problem: the bits are still shifted…

What frequency are you opening /dev/spidev3.0 with? try a lower frequency below 18mhz until it works.

From the last dtb modification only with 17 Mhz… Tomorrow I’ll give a try! Thanks!

Hi Anthony35416,

Today I’ve been able to try what you suggested and it seams that the problem has been solved! I had to put the speed at 7 Mhz… Thank you!