How to set SPI CS(chip select) timing?

Hi,
I follow this link to add the SPI interface, it is no problem.
https://github.com/gtjoseph/jetson-nano-support

I want to use Jetson-Nano SPI to control external SPI device, the device SPI spec like this picture.
(Figure1) Imgur: The magic of the Internet
External Media

But Jetson-Nano SPI out result like this:
(Figure2) Imgur: The magic of the Internet
External Media

Run command: (this sample just send one byte)
root@nano: ./spidev_test -D /dev/spidev0.0 -s 1000000 -H -O -p “\x60”

My questions are:

  1. How do I set SCK and MOSI to normal high?
  2. How do I set or control CS timing? I set Jetson-Nano SPI CS active low, but why low too long, about 750us. As Figure1 show, when I send one byte, CS just need to 10us with clock 1MHz, but jetson-nano need to 750us~1000us?

Could you add below to your device tree to try.

spi0_0 {
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = "spidev";
reg = <0x0>;
controller-data {
nvidia,enable-hw-based-cs;

};

Hi ShaneCCC:
It still can not solve this issue.

On the other hand, I find this link.
https://devtalk.nvidia.com/default/topic/1029410/jetson-tx1/spi-cs-issue/
Do I need to patch spi-tegra114.c file or not?

This is my modification in device tree tegra210-porg-p3448-common.dtsi

spi@7000d400 { /* SPI 1 to 40 pin header */
                status = "okay";
                num-cs = <2>;
                cs-gpios = <&gpio TEGRA_GPIO(C, 3) GPIO_ACTIVE_LOW>, <&gpio TEGRA_GPIO(C, 4) GPIO_ACTIVE_LOW>;
                spi@0 {
                        #address-cells = <0x1>;
                        #size-cells = <0x0>;
                        compatible = "spidev";
                        status = "okay";
                        reg = <0x0>;
                        spi-max-frequency = <65000000>;
                        controller-data {
                                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>;
                        };
                };
                spi@1 {
                        #address-cells = <0x1>;
                        #size-cells = <0x0>;
                        compatible = "spidev";
                        status = "okay";
                        reg = <1>;
                        spi-max-frequency = <65000000>;
                        controller-data {
                                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>;
                        };
                };
        };

Could you check if this patch is merge to the base that you are using?
Also check if below in your device tree.

https://devtalk.nvidia.com/default/topic/1029410/jetson-tx1/spi-cs-issue/post/5259197/#5259197

I use version R32.2.1, there is spi_cs_timing2 in spi-tegra114.c, so I think the patch has been merge.

I don’t know what your mean, could you tell me which file (device tree) do I need to check? don’t you mean this file tegra210-porg-p3448-common.dtsi?

thanks.

Just have a check if the prod-settings in your /proc/device-tree/spi@xxxx/pro-settings

If not can you add it to try.

In my case, what do I need to add? how to add?

root@will-nano:/proc/device-tree/spi@7000d400# ll
total 0
drwxr-xr-x 5 root root 0 一 29 00:21 ./
drwxr-xr-x 143 root root 0 一 29 00:26 …/
-r–r–r-- 1 root root 4 一 29 00:26 ‘#address-cells
-r–r–r-- 1 root root 16 一 29 00:26 clock-names
-r–r–r-- 1 root root 24 一 29 00:26 clocks
-r–r–r-- 1 root root 20 一 29 00:26 compatible
-r–r–r-- 1 root root 24 一 29 00:26 cs-gpios
-r–r–r-- 1 root root 6 一 29 00:26 dma-names
-r–r–r-- 1 root root 16 一 29 00:26 dmas
-r–r–r-- 1 root root 12 一 29 00:26 interrupts
-r–r–r-- 1 root root 8 一 29 00:26 iommus
-r–r–r-- 1 root root 4 一 29 00:26 linux,phandle
-r–r–r-- 1 root root 4 一 29 00:26 name
-r–r–r-- 1 root root 4 一 29 00:26 num-cs
-r–r–r-- 1 root root 12 一 29 00:26 nvidia,clk-parents
-r–r–r-- 1 root root 4 一 29 00:26 phandle
drwxr-xr-x 5 root root 0 一 29 00:20 prod-settings/
-r–r–r-- 1 root root 16 一 29 00:26 reg
-r–r–r-- 1 root root 4 一 29 00:26 reset-names
-r–r–r-- 1 root root 8 一 29 00:26 resets
-r–r–r-- 1 root root 4 一 29 00:26 ‘#size-cells
drwxr-xr-x 3 root root 0 一 29 00:26 ‘spi@0’/
drwxr-xr-x 3 root root 0 一 29 00:26 ‘spi@1’/
-r–r–r-- 1 root root 5 一 29 00:26 status

root@will-nano:/proc/device-tree/spi@7000d400# ll prod-settings/
total 0
drwxr-xr-x 5 root root 0 一 29 00:20 ./
drwxr-xr-x 5 root root 0 一 29 00:21 …/
-r–r–r-- 1 root root 14 一 29 00:20 name
drwxr-xr-x 2 root root 0 一 29 00:20 prod/
-r–r–r-- 1 root root 4 一 29 00:20 ‘#prod-cells
drwxr-xr-x 2 root root 0 一 29 00:20 prod_c_flash/
drwxr-xr-x 2 root root 0 一 29 00:20 prod_c_loop/

root@will-nano:/proc/device-tree/spi@7000d400# ll prod-settings/prod/
total 0
drwxr-xr-x 2 root root 0 一 29 00:20 ./
drwxr-xr-x 5 root root 0 一 29 00:20 …/
-r–r–r-- 1 root root 5 一 29 00:21 name
-r–r–r-- 1 root root 12 一 29 00:21 prod

root@will-nano:/proc/device-tree/spi@7000d400# ll spi@
spi@0/ spi@1/

root@will-nano:/proc/device-tree/spi@7000d400# ll spi@0/
total 0
drwxr-xr-x 3 root root 0 一 29 00:26 ./
drwxr-xr-x 5 root root 0 一 29 00:21 …/
-r–r–r-- 1 root root 4 一 29 00:27 ‘#address-cells
-r–r–r-- 1 root root 7 一 29 00:27 compatible
drwxr-xr-x 2 root root 0 一 29 00:27 controller-data/
-r–r–r-- 1 root root 4 一 29 00:27 name
-r–r–r-- 1 root root 4 一 29 00:27 reg
-r–r–r-- 1 root root 4 一 29 00:27 ‘#size-cells
-r–r–r-- 1 root root 4 一 29 00:27 spi-max-frequency
-r–r–r-- 1 root root 5 一 29 00:27 status

root@will-nano:/proc/device-tree/spi@7000d400# ll spi@0/controller-data/
total 0
drwxr-xr-x 2 root root 0 一 29 00:27 ./
drwxr-xr-x 3 root root 0 一 29 00:26 …/
-r–r–r-- 1 root root 16 一 29 00:27 name
-r–r–r-- 1 root root 4 一 29 00:27 nvidia,cs-hold-clk-count
-r–r–r-- 1 root root 4 一 29 00:27 nvidia,cs-setup-clk-count
-r–r–r-- 1 root root 0 一 29 00:27 nvidia,enable-hw-based-cs
-r–r–r-- 1 root root 4 一 29 00:27 nvidia,rx-clk-tap-delay
-r–r–r-- 1 root root 4 一 29 00:27 nvidia,tx-clk-tap-delay

Hi ShaneCCC:

I modify this file hardware/nvidia/soc/t210/kernel-dts/tegra210-soc/tegra210-prods.dtsi, it still not work.

before modification:

spi@7000d400 {
                prod-settings {
                        #prod-cells = <3>;
                        prod {
                            prod = <0x04 0x00000fff 0x0>;
                        };
                        prod_c_flash {
                            status = "disabled";
                            /* enabled for spi flash rom */
                            prod = <0x04 0x0000003f 0x00000007>;
                        };
                        prod_c_loop {
                            status = "disabled";
                            /* enabled for spi loopback mode */
                            prod = <0x04 0x00000fff 0x0000044b>;
                        };
                };
        };

after modification:

spi@7000d400 {
                prod-settings {
                        #prod-cells = <4>;
                        prod {
                            prod = <0x04 0x00000fff 0x0>;
                        };
                        prod_c_flash {
                            status = "disabled";
                            /* enabled for spi flash rom */
                            prod = <0x04 0x0000003f 0x00000007>;
                        };
                        prod_c_loop {
                            status = "disabled";
                            /* enabled for spi loopback mode */
                            prod = <0x04 0x00000fff 0x0000044b>;
                        };
                        prod_c_cs1 {
                            prod = <
                                   0x4 0x00000fff 0x00000008
                                   0x8 0x0000ff00 0x00000000>;
                        };
                };
        };

From Jetson Nano as follows:

will@will-nano:~$ ll /proc/device-tree/spi@7000d400/prod-settings/
total 0
drwxr-xr-x 6 root root 0 一 28 23:59 ./
drwxr-xr-x 5 root root 0 一 28 23:59 …/
-r–r–r-- 1 root root 14 一 28 23:59 name
drwxr-xr-x 2 root root 0 一 28 23:59 prod/
drwxr-xr-x 2 root root 0 一 28 23:59 prod_c_cs1/
-r–r–r-- 1 root root 4 一 28 23:59 ‘#prod-cells
drwxr-xr-x 2 root root 0 一 28 23:59 prod_c_flash/
drwxr-xr-x 2 root root 0 一 28 23:59 prod_c_loop/

will@will-nano:~$ ll /proc/device-tree/spi@7000d400/prod-settings/prod_c_cs1/
total 0
drwxr-xr-x 2 root root 0 一 28 23:59 ./
drwxr-xr-x 6 root root 0 一 28 23:59 …/
-r–r–r-- 1 root root 11 一 28 23:59 name
-r–r–r-- 1 root root 24 一 28 23:59 prod

Hi,
Is there any update on this issue?

Thanks.

Please have a try this patch.
73d3401.diff.txt (2.32 KB)

which patch do you mean? i don’t see the patch.

Looks like a false positive in the forum filters blocked the patch from showing up.

upload the file again. Also post the context here if still failed to upload.

From 73d3401e493fea4877a4658a4504b831039a223b Mon Sep 17 00:00:00 2001
From: Krishna Yarlagadda <kyarlagadda@nvidia.com>
Date: Thu, 20 Jul 2017 20:37:17 +0530
Subject: [PATCH] spi: tegra: Fix hardware timing programming

Setup and Hold time programming does not retain existing
values of other chip selects.
Also if cs is programmed through dt and is set to 0,
wrongly 0xF will be programmed

Fixed these errors.

Change-Id: I6fdb7c96f7e1d4d449dddc4b03dab5700e178277
Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
---

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 9f84b622..93f4ca2 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -84,8 +84,8 @@
 #define SPI_RX_TAP_DELAY(x)			(((x) & 0x3F) << 0)
 
 #define SPI_CS_TIMING1				0x008
-#define SPI_SETUP_HOLD(setup, hold)		(((setup - 1) << 4) |	\
-						(hold - 1))
+#define SPI_SETUP_HOLD(setup, hold)		(((setup) << 4) |	\
+						(hold))
 #define SPI_CS_SETUP_HOLD(reg, cs, val)			\
 		((((val) & 0xFFu) << ((cs) * 8)) |	\
 		((reg) & ~(0xFFu << ((cs) * 8))))
@@ -875,7 +875,7 @@
 	struct tegra_spi_client_ctl_data *cdata = spi->controller_data;
 	u32 set_count;
 	u32 hold_count;
-	u32 spi_cs_timing;
+	u32 spi_cs_timing = tspi->spi_cs_timing;
 	u32 spi_cs_setup;
 
 	if (!cdata || tspi->prod_list)
@@ -902,7 +902,7 @@
 {
 	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
 	struct tegra_spi_client_ctl_data *cdata = spi->controller_data;
-	u32 spi_cs_timing2 = 0;
+	u32 spi_cs_timing2 = tspi->spi_cs_timing2;
 
 	if (!cdata || tspi->prod_list)
 		return;
@@ -1096,9 +1096,7 @@
 				tegra_spi_writel(tspi, command1, SPI_COMMAND1);
 
 		tspi->is_hw_based_cs = false;
-		if (cdata && cdata->is_hw_based_cs && is_single_xfer &&
-		    ((tspi->curr_dma_words * tspi->bytes_per_word) ==
-		     (t->len - tspi->cur_pos))) {
+		if (cdata && cdata->is_hw_based_cs && is_single_xfer) {
 			tegra_spi_set_timing1(spi);
 			tspi->is_hw_based_cs = true;
 		}
@@ -2002,6 +2000,8 @@
 	tspi->def_command1_reg |= SPI_CS_SEL(tspi->def_chip_select);
 	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
 	tspi->command2_reg = tegra_spi_readl(tspi, SPI_COMMAND2);
+	tspi->spi_cs_timing = tegra_spi_readl(tspi, SPI_CS_TIMING1);
+	tspi->spi_cs_timing2 = tegra_spi_readl(tspi, SPI_CS_TIMING2);
 	tegra_spi_set_slcg(tspi);
 	pm_runtime_put(&pdev->dev);

After apply the patch, the CS still low too long, and these are my debug message.
attachment is my spi-tegra114.c

I trace the spi-tegra114.c code, I find the wait_for_completion_timeout() spend too long time.
Then I change the SPI_DMA_TIMEOUT value, still no effect.

Dec 17 10:15:51 will-desktop kernel: [   78.925929] [drivers/spi/spidev.c] spidev_ioctl cmd=0x40046b05
Dec 17 10:15:51 will-desktop kernel: [   78.925940] spidev spi0.0: setup 8 bpw, cpol, cpha, 1000000Hz
Dec 17 10:15:51 will-desktop kernel: [   78.925983] spidev spi0.0: setup mode 3, 8 bits/w, 1000000 Hz max --> 0
Dec 17 10:15:51 will-desktop kernel: [   78.925986] spidev spi0.0: spi mode 3
Dec 17 10:15:51 will-desktop kernel: [   78.925990] [drivers/spi/spidev.c] spidev_ioctl cmd=0x80046b05
Dec 17 10:15:51 will-desktop kernel: [   78.925994] [drivers/spi/spidev.c] spidev_ioctl cmd=0x40016b03
Dec 17 10:15:51 will-desktop kernel: [   78.925999] spidev spi0.0: setup 8 bpw, cpol, cpha, 1000000Hz
Dec 17 10:15:51 will-desktop kernel: [   78.926005] spidev spi0.0: setup mode 3, 8 bits/w, 1000000 Hz max --> 0
Dec 17 10:15:51 will-desktop kernel: [   78.926008] spidev spi0.0: 8 bits per word
Dec 17 10:15:51 will-desktop kernel: [   78.926012] [drivers/spi/spidev.c] spidev_ioctl cmd=0x80016b03
Dec 17 10:15:51 will-desktop kernel: [   78.926015] [drivers/spi/spidev.c] spidev_ioctl cmd=0x40046b04
Dec 17 10:15:51 will-desktop kernel: [   78.926019] spidev spi0.0: setup 8 bpw, cpol, cpha, 1000000Hz
Dec 17 10:15:51 will-desktop kernel: [   78.926025] spidev spi0.0: setup mode 3, 8 bits/w, 1000000 Hz max --> 0
Dec 17 10:15:51 will-desktop kernel: [   78.926028] [drivers/spi/spidev.c] spidev_ioctl cmd=0x80046b04
Dec 17 10:15:51 will-desktop kernel: [   78.926204] [drivers/spi/spidev.c] spidev_ioctl cmd=0x40206b00
Dec 17 10:15:51 will-desktop kernel: [   78.926215] [drivers/spi/spi-tegra114.c][tegra_spi_transfer_one_message][1437]
Dec 17 10:15:51 will-desktop kernel: [   78.926219] [drivers/spi/spi-tegra114.c][tegra_spi_setup_transfer_one][1064]
Dec 17 10:15:51 will-desktop kernel: [   78.926522] spi-tegra114 7000d400.spi: Setting clk_src clk_m
Dec 17 10:15:51 will-desktop kernel: [   78.926554] [drivers/spi/spi-tegra114.c] cdata->is_hw_based_cs: 1
Dec 17 10:15:51 will-desktop kernel: [   78.926556] [drivers/spi/spi-tegra114.c] cdata->cs_setup_clk_count: 3
Dec 17 10:15:51 will-desktop kernel: [   78.926561] [drivers/spi/spi-tegra114.c] cdata->cs_hold_clk_count: 3
Dec 17 10:15:51 will-desktop kernel: [   78.926565] [drivers/spi/spi-tegra114.c] cdata->rx_clk_tap_delay: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926570] [drivers/spi/spi-tegra114.c] cdata->tx_clk_tap_delay: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926573] [drivers/spi/spi-tegra114.c] cdata->cs_inactive_cycles: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926575] [drivers/spi/spi-tegra114.c] cdata->clk_delay_between_packets: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926588] [drivers/spi/spi-tegra114.c][tegra_spi_set_timing1][890]
Dec 17 10:15:51 will-desktop kernel: [   78.926590] [drivers/spi/spi-tegra114.c] spi_cs_timing: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926592] [drivers/spi/spi-tegra114.c][tegra_spi_set_timing2][923]
Dec 17 10:15:51 will-desktop kernel: [   78.926594] [drivers/spi/spi-tegra114.c] spi_cs_timing2: 538976288
Dec 17 10:15:51 will-desktop kernel: [   78.926607] spi-tegra114 7000d400.spi: prod settings failed with error -19
Dec 17 10:15:51 will-desktop kernel: [   78.926610] [drivers/spi/spi-tegra114.c][tegra_spi_start_transfer_one][1181]
Dec 17 10:15:51 will-desktop kernel: [   78.926614] spi-tegra114 7000d400.spi: The def 0x47d08000 and written 0x73c01807
Dec 17 10:15:51 will-desktop kernel: [   78.926617] [drivers/spi/spi-tegra114.c][tegra_spi_start_cpu_based_transfer][705]
Dec 17 10:15:51 will-desktop kernel: [   78.926640] [drivers/spi/spi-tegra114.c] tspi->polling_mode: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926741] [drivers/spi/spi-tegra114.c] timeleft: 2500
Dec 17 10:15:51 will-desktop kernel: [   78.926744] [drivers/spi/spi-tegra114.c] xfer->len: 2
Dec 17 10:15:51 will-desktop kernel: [   78.926746] [drivers/spi/spi-tegra114.c] prefer_last_used_cs: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926748] [drivers/spi/spi-tegra114.c] complete_xfer 2
Dec 17 10:15:51 will-desktop kernel: [   78.926751] [drivers/spi/spi-tegra114.c] xfer->cs_change: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926753] [drivers/spi/spi-tegra114.c] xfer->delay_usecs: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926755] [drivers/spi/spi-tegra114.c] cstate->cs_gpio_valid: 1
Dec 17 10:15:51 will-desktop kernel: [   78.926757] [drivers/spi/spi-tegra114.c] spi->cs_gpio: 19
Dec 17 10:15:51 will-desktop kernel: [   78.926760] [drivers/spi/spi-tegra114.c] complete_xfer 4
Dec 17 10:15:51 will-desktop kernel: [   78.926762] [drivers/spi/spi-tegra114.c] prefer_last_used_cs: 0
Dec 17 10:15:51 will-desktop kernel: [   78.926775] [drivers/spi/spi-tegra114.c] tspi->is_hw_based_cs: 1

spi-tegra114.c (60.4 KB)

Hi,
As the debug message, the prod settings failed, how do I set the prod settings in my Jestson Nano EVB?

Dec 17 10:15:51 will-desktop kernel: [ 78.926607] spi-tegra114 7000d400.spi: prod settings failed with error -19

Thanks.

This may have nothing to do with your issue but have you tried NOT using hardware chip select?

There’s a note in kernel/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt

- nvidia,clk-delay-between-packets : Clock delay  between packets by keeping
  CS active. For this, it is required to pass the Chip select
  as GPIO.

I have definitely noticed timing differences between using hardware chip select and GPIO chip select.
Oddly enough, it was better with GPIO.

Here’s an example of what I use…

spi@7000d400 { /* SPI 1 to 40 pin header */
      status = "okay";
      num-cs = <1>;
      cs-gpios = <&gpio TEGRA_GPIO(C, 3) GPIO_ACTIVE_LOW>;
      spi0_0 {
         #address-cells = <0x1>;
         #size-cells = <0x0>;
         compatible = "spidev";
         status = "okay";
         reg = <0>;
         spi-max-frequency = <54000000>;
         controller-data {
            nvidia,cs-setup-clk-count = <0x1e>;
            nvidia,cs-hold-clk-count = <0x1e>;
            nvidia,rx-clk-tap-delay = <0x1f>;
            nvidia,tx-clk-tap-delay = <0x0>;
         };
      };
   };

I’m coming up against the same issue. The release of chip select is taking 200 - 1000 us after the transaction. I haven’t tried software CS yet or the patch, but I was hoping someone can confirm that this issue is being worked on.

Just an update. After running jetson_clocks.sh and making sure the Nano is set to max performance (even with 5W mode), the chip select is significantly faster to de-assert now (~50us). So this seems to be some sort of scheduling / response issue with the driver and the linux kernel.

It also seems that occasionally (1 in 20 transactions) the release happens a cycle (SCK) after the transaction is finished (extremely quickly) and the CS line is actually driven high (rise time is fast).

The remainder of the time when it takes 50us to deassert the CS line, the CS is released (ie. open drain) and is pulled high by the pull-up resistance.