Did anybody get SPI interface working on TX1?

Did anybody get SPI interface working on TX1?
For example SPI1 on J21 header.

Sure! Kangalow’s site, JetsonHacks.com, has several examples.

EDIT: Oops – my bad. His examples are for I2C.

Did you make any progress?

I have been working on this for a while and have not been able to get very far. It looks like the driver is configuring the registers correctly, and it looks like the pinmux is correct in the dts, yet nothing seems to come out.

Is this something that is being worked on, or should it work out of the box?

Please try with this kernel patch or comment out pinmux initialization of spi pins in uboot. File board/nvidia/p2371-2180/pinmux-config-p2371-2180.h

From 58c98929f6b388bc9642c6a445f8f9ea67d150ff Mon Sep 17 00:00:00 2001
From: Shreshtha SAHU <ssahu@nvidia.com>
Date: Wed, 2 Mar 2016 19:30:00 +0530
Subject: [PATCH] arm64: dts: jetson-cv: configure GPIO to SFIO

Configure PC0, PC1, PC2, PC03 and PC04 from GPIO to SPI.
This is required in addition to SPI configuration done in DT file.
During boot, bootloader configures these pins as GPIO as per RasPi interface.

Bug 1729683

Change-Id: I74e85be37c8e8fc673283a222c4f726817407f82
Signed-off-by: Shreshtha SAHU <ssahu@nvidia.com>
---
 arch/arm64/boot/dts/tegra210-jetson-cv-base-p2597-2180-a00.dts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/tegra210-jetson-cv-base-p2597-2180-a00.dts b/arch/arm64/boot/dts/tegra210-jetson-cv-base-p2597-2180-a00.dts
index 25b2b3d..ba66cf9 100644
--- a/arch/arm64/boot/dts/tegra210-jetson-cv-base-p2597-2180-a00.dts
+++ b/arch/arm64/boot/dts/tegra210-jetson-cv-base-p2597-2180-a00.dts
@@ -274,6 +274,12 @@
 		};
 	};
 
+	gpio@6000d000 {
+		gpio_default: default {
+			gpio-to-sfio = <16 17 18 19 20>;
+		};
+	};
+
 	serial@70006040 {
 		status = "okay";
 	};
-- 
2.1.4

Thanks for the suggestion

I used the dts patch being I don’t have u-boot source on my computer, but I still do not get anything out of the port.

To test, I connected MOSI and MISO together, then compiled and ran Documentation/spi/spidev_test.c, but all I get are FF for the Rx.

I updated my kernel source to the head of l4t/l4t-r23.2 but that did not help.

Here is what I added to my dts file

&gpio {
	gpio_default: default {
		gpio-to-sfio = <16 17 18 19 20>;
	};
};

&spi1 {
	status = "okay";
	spi-spidev@0 {
		status = "okay";
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		compatible = "linux,spidev", "spidev";
		reg = <0>;
		spi-max-frequency = <16000000>;
		spi-cpha;
		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>;
			nvidia,default-chipselect;
			nvidia,chipselect-gpio = <&gpio 19 0>;
		};
	};
};

Do you know what else I could be missing?

Thanks again

Could there be a conflict between “enable-hw-based-cs” and “chipselect-gpio”? According to the TK1 SPI article,
http://neurorobotictech.com/Community/Blog/tabid/184/ID/13/Using-the-Jetson-TK1-SPI--Part-3-Configuring-SPI-in-the-device-tree.aspx

“nvidia,enable-hw-based-cs: If this is present then spidev will use the hardware based control of the chip select line. If it is absent then you will need to configure your own chip select using one of the GPIO lines, and ensure that it is set to to the correct value while transmitting or receiving.”

If it helps, here is my full dts file stored under arch/arm64/boot/dts

/*
 * Based off of
 * arch/arm64/boot/dts/tegra210-jetson-tx1-p2597-2180-a01-devkit.dts
 *
 * Copyright (c) 2014-2015, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 */

#include "tegra210-jetson-cv-base-p2597-2180-a00.dts"

/ {
	model = "jetson_tx1";
	compatible = "nvidia,jetson-cv", "nvidia,tegra210";
	nvidia,dtsfilename = __FILE__;

	#address-cells = <2>;
	#size-cells = <2>;

	chosen {
		bootloader {
			nvidia,skip-display-init;
		};
	};

	host1x {
		dc@54200000 {
			status = "disabled";
		};

		dc@54240000 {
			nvidia,dc-or-node = "/host1x/sor1";
		};

		dsi {
			status = "disabled";
			panel-a-wuxga-8-0 {
				status = "disabled";
			};
		};
	};

	i2c@7000c400 {
		lp8557-backlight-a-wuxga-8-0@2c {
			status = "disabled";
		};
	};

	backlight {
		status = "disabled";
	};

};

&gpio {
	gpio_default: default {
		gpio-to-sfio = <16 17 18 19 20>;
	};
};

&spi0 {
	status = "disabled";
};

&spi1 {
	status = "okay";
	spi-spidev@0 {
		status = "okay";
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		compatible = "linux,spidev", "spidev";
		reg = <0>;
		spi-max-frequency = <16000000>;
		spi-cpha;
		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>;
			nvidia,default-chipselect;
			nvidia,chipselect-gpio = <&gpio 19 0>;
		};
	};
};

&spi2 {
	status = "disabled";
};

&spi3 {
	status = "disabled";
};

Using this, and adding the spidev module in my kernel configuraiton (I think the tegra spi driver is selected by default), I get /dev/spidev1.0 to show up.

Note: I don’t know why I need the “nvidia,chipselect-gpio” entry, I thought “nvidia,enable-hw-based-cs” was supposed to prevent me needing that. But if I don’t have it then spi-tegra114.c throws away my controller-data.

Thanks. I have /dev/spidev1.0 appearing now. But no joy on getting anything out of SPI1 on J21. I have tried:

  • your dts
  • the dts from the TK1 SPI arcticle
  • u-boot compiled with SPI1 pinmuxes commented out
  • u-boot compiled with SPI1 pinmuxes set to "reasonable" values (mux group=SPI1; e_input=OUTPUT for MOSI, MISO, CLK

Nothing worked. spidev_test returns all FF for me as well.

A logic analyzer shows the SPI1 pins on J21 all pulled low.

I think the commenting out that bbasu was referring to is the GPIO_INIT for C0-C4 in the pinmux-config-p2371-2180.h file. I just realized that this morning. But still no luck for me.

A basic example config with spidev_test and MISO/MOSI jumpered would be awesome… seems like somebody at nvidia would know how to do this?

There’s a clue in this git commit, where SPI1 pinmuxes seem to have been disabled:

http://nv-tegra.nvidia.com/gitweb/?p=3rdparty/u-boot.git;a=commitdiff;h=039e851097b26472fccfa4a7a2d5f9aaaaf3630f

However, I tried restoring them to their previous definition (and commenting out the corresponding GPIOs) and that did not help :(

In fact, none of the changes I make in that file end up reflected in the pinmux registers, after u-boot flash and boot. (comparing register values from devmem2 with the mux registers in the TRM, e.g. 0x70003050)

This does feel like a muxing problem.

I finally got this working. Jumpered MISO / MOSI (J21 pins 19/21) and ran spidev_test.c, and the output matched input. Logic analyzer showed expected CLK as well.

The main issue is a naming discrepancy between the carrier board spec and device tree… J21 SPI1 is actually @7000d400, which is spi0 in the device tree. This definition worked for me:

spi@7000d400 {
    status = "okay";

    spi0_0 {
        #address-cells = <0x1>;
        #size-cells = <0x0>;
        compatible = "spidev";
        reg = <0x0>;
        spi-max-frequency = <0x17d7840>;
        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>;
    };
};

I also currently have a bunch of experimental pinmux / device tree changes in my build as a result of trying all day to make this work, which may or may not also be required. Tomorrow I’ll back those changes out and see which if any made a difference, and post them here.

The only other piece required is the gpio-to-sfio section provided by bbasu above, which frees up pins C0-C4 for SPI. Other forays into pinmuxing weren’t necessary…

These entries were enough to make loopback SPI work (jumper on J21 19/21). Of course you may have to add polarity, phase or other settings for specific devices.

gpio@6000d000 {
    gpio_default: default {
        gpio-to-sfio = <16 17 18 19 20>;
    };
};

spi@7000d400 {
    status = "okay";

    spi0_0 {
        #address-cells = <0x1>;
        #size-cells = <0x0>;
        compatible = "spidev";
        reg = <0x0>;
        spi-max-frequency = <0x17d7840>;
        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>;
    };
};

Thanks so much! You know, I was testing all the channels at first, but by the time bbasu commented I had just assumed the DTS SPI1 was really SPI1 on J21…

By the way, I caution you by not using nvidia,chipselect-gpio. I think it is a bug with the driver. When I boot without that parameter, I get the error

spi spi0.0: CS GPIO is not found on node controller-data: -2

If you look at drivers/spi/spi-tegra114.c at around line 1123, this means none of the controller-data will be used. So you can either use nvidia,chipselect-gpio, or else I suggest using the following patch (not an official patch!)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index ec8c5a4..6aaff03 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -1118,13 +1118,15 @@ static struct tegra_spi_device_controller_data
                cdata->cs_inactive_cycles = cdata->clk_delay_between_packets;
 
        cdata->cs_gpio = -EINVAL;
-       cdata->cs_gpio = of_get_named_gpio(data_np,
-                                       "nvidia,chipselect-gpio", 0);
-       if ((cdata->cs_gpio < 0) && (cdata->cs_gpio != -EINVAL)) {
-               dev_err(&spi->dev,
-                       "CS GPIO is not found on node %s: %d\n",
-                       data_np->name, cdata->cs_gpio);
-               return NULL;
+       if (of_find_property(data_np, "nvidia,chipselect-gpio", NULL)) {
+               cdata->cs_gpio = of_get_named_gpio(data_np,
+                                               "nvidia,chipselect-gpio", 0);
+               if (cdata->cs_gpio < 0) {
+                       dev_err(&spi->dev,
+                               "CS GPIO is not found on node %s: %d\n",
+                               data_np->name, cdata->cs_gpio);
+                       return NULL;
+               }
        }
        if ((cdata->cs_gpio < 0) && (cdata->clk_delay_between_packets)) {
                dev_err(&spi->dev,

Gents,
I want to edit the dts file on my Jetson TX1, to get the SPI active.
The tegra210-jetson-cv-base-p2597-2180-a00.dtb from the /boot folder is converted to the dts file.
But now I saw there are already some SPI sections…
Should I remove this sectoin, and replace it with your important changes…?

Thanks

spi@7000d400 {
		compatible = "nvidia,tegra210-spi";
		reg = <0x0 0x7000d400 0x0 0x200>;
		interrupts = <0x0 0x3b 0x4>;
		nvidia,dma-request-selector = <0x5c 0xf>;
		iommus = <0x57 0xe>;
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		dmas = <0x5c 0xf 0x5c 0xf>;
		dma-names = "rx", "tx";
		nvidia,clk-parents = "pll_p", "clk_m";
		status = "okay";

		prod-settings {

			prod {
				prod = <0x4 0xfffff000 0x0>;
			};

			prod_c_flash {
				status = "disabled";
				prod = <0x4 0xffffffc0 0x7>;
			};

			prod_c_loop {
				status = "disabled";
				prod = <0x4 0xfffff000 0x44b>;
			};
		};
	};

Add/Modify what you want to spi@7000d400 entry, but do not remove anything. For example, you will want to add the child node for the specific SPI channel (something like spi-spidev@0 {} from previous examples here)

If there is a gpio@6000d000 section, then add the “gpio_default: default” child node. If there is not that section, then add it somewhere before the last }; of the file (I would just add it as the last node).

Example of what to add…

gpio@6000d000 {
    gpio_default: default {
        gpio-to-sfio = <16 17 18 19 20>;
    };
    // OK if more stuff is in here
};

Keep in mind, gpio 19 = CS0, gpio 20 = CS1, so if you only want to use, say, cs0 and leave cs1 for gpio, then you only need gpio-to-sfio = <16 17 18 19>

Ok, still didn’t got the spidevice…

Here is my relevant section from dts for the GPIO.

gpio@6000d000 {

		compatible = "nvidia,tegra210-gpio", "nvidia,tegra124-gpio", "nvidia,tegra30-gpio";
		reg = <0x0 0x6000d000 0x0 0x1000>;
		interrupts = <0x0 0x20 0x4 0x0 0x21 0x4 0x0 0x22 0x4 0x0 0x23 0x4 0x0 0x37 0x4 0x0 0x57 0x4 0x0 0x59 0x4 0x0 0x7d 0x4>;
		#gpio-cells = <0x2>;
		gpio-controller;
		#interrupt-cells = <0x2>;
		interrupt-controller;
		gpio-ranges = <0x4e 0x0 0x0 0xf6>;
		status = "okay";
		gpio-init-1 = <0x4f>;
		linux,phandle = <0x5e>;
		phandle = <0x5e>;

		wlan-default {
			gpio-input = <0x3a 0x41>;
			gpio-output-high = <0x38 0x40>;
			linux,phandle = <0x4f>;
			phandle = <0x4f>;
		};
		gpio_default: default {
		    gpio-to-sfio = <16 17 18 19 20>;
		};
	};

For GPIO, i “just” add the gpio-to-sfio.

Section in dts for SPI, here also I added the last few lines, the sub-nodes spi0_0.
The other settings are already in the default dts file…

spi@7000d400 {
		compatible = "nvidia,tegra210-spi";
		reg = <0x0 0x7000d400 0x0 0x200>;
		interrupts = <0x0 0x3b 0x4>;
		nvidia,dma-request-selector = <0x5c 0xf>;
		iommus = <0x57 0xe>;
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		dmas = <0x5c 0xf 0x5c 0xf>;
		dma-names = "rx", "tx";
		nvidia,clk-parents = "pll_p", "clk_m";
		status = "okay";

		prod-settings {

			prod {
				prod = <0x4 0xfffff000 0x0>;
			};

			prod_c_flash {
				status = "disabled";
				prod = <0x4 0xffffffc0 0x7>;
			};

			prod_c_loop {
				status = "disabled";
				prod = <0x4 0xfffff000 0x44b>;
			};
		};

	    spi0_0 {
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		compatible = "spidev";
		reg = <0x0>;
		spi-max-frequency = <0x17d7840>;
		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>;
	    };
	};

I also checked the
CONFIG_SPIDEV=y in the kernel config, and compiled the kernel on my host, and copy it to the tx1.

ok, got now the deivce…

@Readonly

Readonly wrote:

The only other piece required is the gpio-to-sfio section provided by bbasu above, which frees up pins C0-C4 for SPI. Other forays into pinmuxing weren’t necessary…

These entries were enough to make loopback SPI work (jumper on J21 19/21). Of course you may have to add polarity, phase or other settings for specific devices.

Can you please clarify what file you placed this in and what build steps you took after the file was edited with this content?