Adding SPI Slave Device - Overlays or device tree?

Hello,
Lots of information is scattered around the web related to device tree overlay and device tree , I am trying to use a SPI peripheral with the BBB ( kernel 4.14 + ubuntu 20.04 => git checkout origin/am33x-v4.14 -b tmp) on spi0.

Which way should i go :
(1) Using Device tree overlay
(2) Modifying the device tree

I proceeded with #2 and tried to find the device tree entry of the SPI0 and the corresponding driver node
I did the modification in the file : KERNEL/arch/arm/boot/dts/am335x-bone-pinmux-spi0.dtsi

  • as below bold part
/ *standard* /
&am33xx_pinmux {
    spi0_pins: pinmux_spi0_pins {
        pinctrl-single,pins = <
        0x150 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */
        0x154 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */
        0x158 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
        0x15c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
        >;
    };
};
&spi0 {
    cs-gpios = <&pio0 4>;
    status = "okay";

    stnfc@0{
        reg = <0>;
        compatible = "st,stnfc";
        status = "okay";
        spi-max-frequency = <1000000>;
        enable-gpio = <&pio4 0>;
        interrupt-parent = <&pio0>;
        interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
    };
};

but on ./tool/rebuild.sh (rebuilding) I noticed this file was not picked up .

I wanted to know which all device tree files I need to modify and how to include them in the build?
second which one is better way #1 or #2
If you can please point me to the appropriate/official link which can help me interfacing or you can suggest changes here.
Thanks in advance !
Br,
S

Hi @sr007, the best method is #2, modifying the device tree directly.

Did you include “am335x-bone-pinmux-spi0.dtsi” in your final *.dts file, you may still need to touch your chosen *.dts and run ./tool/rebuild.sh

Regards,

1 Like

Thanks for the quick response @RobertCNelson

I included am335x-bone-pinmux-spi0.dtsi in the am335x-boneblack.dtb
, below is the build logs last lines

CALL scripts/checksyscalls.sh
DTC arch/arm/boot/dts/am335x-boneblack.dtb
arch/arm/boot/dts/am335x-boneblack.dtb: ERROR (phandle_references): Reference to non-existent node or label "gpio4"

I changed the pio reference to gpio , and below is the changed portion :

&spi0 {
    cs-gpios = <&gpio0 4>;
    status = "okay";

    stnfc@0{
        reg = <0>;
        compatible = "st,stnfc";
        status = "okay";
        spi-max-frequency = <1000000>;
        enable-gpio = <&gpio4 0 GPIO_ACTIVE_HIGH>;
        interrupt-parent = <&gpio0 >;
        interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
    };
};

Do I need to define gpio4 somewhere else as well , or include some other file as well? Why it didnt give error for gpio0? btw am335x-bone-pinmux-spi0.dtsi is the correct file right where I have to make an entry for my slave device to be interfaced with spi0?

Hi @sr007, what pin’s are you using in this design?

For example the “am335x-bone-pinmux-spi0.dtsi”

has:

&am33xx_pinmux {
    spi0_pins: pinmux_spi0_pins {
        pinctrl-single,pins = <
        0x150 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */
        0x154 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */
        0x158 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
        0x15c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
        >;
    };
};

Which means you’d use:

&spi0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&bb_spi0_pins>;

    stnfc@0{
        reg = <0>;
        compatible = "st,stnfc";
        status = "okay";
        spi-max-frequency = <1000000>;
        enable-gpio = <&pio4 0>;
        interrupt-parent = <&pio0>;
        interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
    };
};

For enable-gpio, what gpio/pin line did you wire up?

        enable-gpio = <&pio4 0>;

For the irq, line, what gpio/pin line did you wire up?

        interrupt-parent = <&pio0>;
        interrupts = <7 IRQ_TYPE_EDGE_FALLING>;

Regards,

Hello @RobertCNelson,

This is the h/w connection
(P9_Header Pin : GPIO controller) BBB <--------> Slave ST NFC Transceiver
(P9_17 : gpio0[5]) SPIO_CS0<---------------------> Slave-CS
(P9_21 : gpio0[3]) SPIO_D0<-----------------------> Slave-MISO
(P9_18) : gpio0[4]) SPIO_D1<----------------------> Slave-MOSI
(P9_22 : gpio0[2]) SPIO_SCLK<------------------> Slave-CLK
(P9_1 : gpio1[15]) GPIO_48<-----------------------> Slave-ENABLE(enable-gpio entry in the DT) ( to be configured as GPIO Output for slave wakeup from Host)
(P9_16 : gpio1[16]) GPIO_51<--------> Slave-IRQ (interrupt-parent entry in the DT) to be configured as GPIO Input for interrupt from slave)

below is th new dts and the build error log

&am33xx_pinmux {
        spi0_pins: pinmux_spi0_pins {
                pinctrl-single,pins = <
                        0x150 (PIN_INPUT_PULLUP | MUX_MODE0)    /* spi0_sclk.spi0_sclk */
                        0x154 (PIN_INPUT_PULLUP | MUX_MODE0)    /* spi0_d0.spi0_d0 */
                        0x158 (PIN_OUTPUT_PULLUP | MUX_MODE0)   /* spi0_d1.spi0_d1 */
                        0x15c (PIN_OUTPUT_PULLUP | MUX_MODE0)   /* spi0_cs0.spi0_cs0 */
                >;
        };
};

&spi0 {
        #cs-gpios = <&pio0 5>;
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&bb_spi0_pins>;

        stnfc@0{
            reg = <0>;
            compatible = "st,stnfc";
            status = "okay";
            spi-max-frequency = <1000000>;
            enable-gpio = <&pio1 15>;
            interrupt-parent = <&pio1>;
            interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
        };
};

Build error log :

DTC arch/arm/boot/dts/am335x-boneblack.dtb
arch/arm/boot/dts/am335x-boneblack.dtb: ERROR (phandle_references): Reference to non-existent node or label “pio0”

arch/arm/boot/dts/am335x-boneblack.dtb: ERROR (phandle_references): Reference to non-existent node or label “bb_spi0_pins”

arch/arm/boot/dts/am335x-boneblack.dtb: ERROR (phandle_references): Reference to non-existent node or label “pio1”

arch/arm/boot/dts/am335x-boneblack.dtb: ERROR (phandle_references): Reference to non-existent node or label “pio1”

ERROR: Input tree has errors, aborting (use -f to force output)
make[1]: *** [scripts/Makefile.lib:317: arch/arm/boot/dts/am335x-boneblack.dtb] Error 2
make: *** [arch/arm/Makefile:350: dtbs] Error 2

and if I change pio to gpio I get below build error log

arch/arm/boot/dts/am335x-boneblack.dtb: ERROR (phandle_references): Reference to non-existent node or label “bb_spi0_pins”

ERROR: Input tree has errors, aborting (use -f to force output)
make[1]: *** [scripts/Makefile.lib:317: arch/arm/boot/dts/am335x-boneblack.dtb] Error 2
make: *** [arch/arm/Makefile:350: dtbs] Error 2

I am confused above pio and gpio here.

Thanks and Regards,
S

Hi @sr007,

Both of these pin’s are invalid:

P9_1 is NOT controllable… DGND… (gpio1[15] is P8_15)
P9_16 is NOT gpio1[16] (P9_15 is gpio1[16]…)

So what pin’s are you using for IRQ and enable?

That’s because your device-tree is still not complete. So please let me know which pins you are using for IRQ and enable?

Here is the current version of the device-tree, but still needs your GPIO information.

diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index 40b17b956109..9d9b073e28bb 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -19,6 +19,39 @@
 	};
 };
 
+&am33xx_pinmux {
+	spi0_pins: pinmux_spi0_pins {
+		pinctrl-single,pins = <
+			0x150 (PIN_INPUT | MUX_MODE0)	/* P9_22 (A17) spi0_sclk.spi0_sclk */
+			0x154 (PIN_INPUT | MUX_MODE0)	/* P9_21 (B17) spi0_d0.spi0_d0 */
+			0x158 (PIN_INPUT | MUX_MODE0)	/* P9_18 (B16) spi0_d1.spi0_d1 */
+			0x15c (PIN_INPUT | MUX_MODE0)	/* P9_17 (A16) spi0_cs0.spi0_cs0 */
+		>;
+	};
+
+	//spi0_nfc_pins: pinmux_spi0_nfc_pins {
+	//	pinctrl-single,pins = <
+	//		
+	//	>;
+	//};
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins>;
+
+	stnfc@0{
+		reg = <0>;
+		compatible = "st,stnfc";
+		status = "okay";
+		spi-max-frequency = <1000000>;
+		//enable-gpio = <&pio4 0>;
+		//interrupt-parent = <&pio0>;
+		//interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
 &cpu0_opp_table {
 	/*
 	 * All PG 2.0 silicon may not support 1GHz but some of the early

The BeagleBone Black schematic can be found here:

Regards,

Hello @RobertCNelson,
Sorry I mistyped the PINs.

for IRQ I am using Pin number 16 of P9 Header ( if this is not available I will use Pin number 23 of P9 header)
for ENABLE I am using Pin number 15 of P9 Header.

All pins I am referring wrt to this : http://beagleboard.org/static/images/cape-headers-spi.png

Regards,

This would support that setup:

diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index 40b17b956109..e88d1c7ac776 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -19,6 +19,47 @@
 	};
 };
 
+&am33xx_pinmux {
+	spi0_pins: pinmux_spi0_pins {
+		pinctrl-single,pins = <
+			0x150 (PIN_INPUT | MUX_MODE0)	/* P9_22 (A17) spi0_sclk.spi0_sclk */
+			0x154 (PIN_INPUT | MUX_MODE0)	/* P9_21 (B17) spi0_d0.spi0_d0 */
+			0x158 (PIN_INPUT | MUX_MODE0)	/* P9_18 (B16) spi0_d1.spi0_d1 */
+			0x15c (PIN_INPUT | MUX_MODE0)	/* P9_17 (A16) spi0_cs0.spi0_cs0 */
+		>;
+	};
+
+	spi0_nfc_pins: pinmux_spi0_nfc_pins {
+		pinctrl-single,pins = <
+			0x040 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* P9_15 (R13) gpmc_a0.gpio1_16 EN */
+			0x04C (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* P9_16 (T14) gpmc_a3.gpio1_19 IRQ */
+		>;
+	};
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins>;
+
+	stnfc@0{
+		reg = <0>;
+		compatible = "st,stnfc";
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi0_nfc_pins>;
+
+		spi-max-frequency = <1000000>;
+
+		enable-gpio = <&gpio1 16 GPIO_ACTIVE_HIGH>;
+		//enable-gpio = <&gpio1 16 GPIO_ACTIVE_LOW>;
+
+		interrupt-parent = <&gpio1>;
+		interrupts = <19 IRQ_TYPE_EDGE_RISING>;
+		//interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
 &cpu0_opp_table {
 	/*
 	 * All PG 2.0 silicon may not support 1GHz but some of the early

Now it’s up to you to test the polarity of the enable gpio:

enable-gpio = <&gpio1 16 GPIO_ACTIVE_HIGH>;

or

enable-gpio = <&gpio1 16 GPIO_ACTIVE_LOW>;

and the irq trigger state:

interrupts = <19 IRQ_TYPE_EDGE_RISING>;

or

interrupts = <19 IRQ_TYPE_EDGE_FALLING>;

Regards,

1 Like

Thanks @RobertCNelson , this builds successfully now.
I will test it now.
Regards,

Hello @RobertCNelson,
While interacting with the driver using a test application(provided by nfc framework from linux) , I am getting this below error(dmesg) :

[ 655.775300] stnfc spi1.0: phy timeout error
[ 655.779524] stnfc spi1.0: send receive of frame fail with -110

Do you have any idea could it be related to spi configuration or hardware wiring I
did?
I could see the driver loading and the entry in /sys/bus/spi/devices/spi1.0 , so i think we are right as far as the matter of hardware connection and device tree configuration .

lrwxrwxrwx 1 root gpio 0 Dec 20 06:17 driver -> …/…/…/…/…/…/…/bus/spi/drivers/stnfc
-r–r--r-- 1 root gpio 4096 Dec 20 06:17 modalias
drwxrwxr-x 3 root gpio 0 Dec 20 06:17 nfc
lrwxrwxrwx 1 root gpio 0 Dec 20 06:17 of_node -> …/…/…/…/…/…/…/firmware/devicetree/base/ocp/spi@48030000/stnfc@0
drwxrwxr-x 2 root gpio 0 Dec 20 06:17 power
drwxrwxr-x 2 root gpio 0 Dec 20 06:17 statistics
lrwxrwxrwx 1 root gpio 0 Dec 20 06:17 subsystem -> …/…/…/…/…/…/…/bus/spi

Regards,

Correct, test all 4 cases of the possible enable-gpio and interrupt values… -110 means it wasn’t detected, so you have 1 of the 4 confirmed to be wrong…

Regards,

OK, but is it possible to know which one threw the error?
Regards,

Not really, but you should be able to test all 4 combinations in under 5-10 minutes. As id doesn’t require a full kernel build, just rebuild, install, boot and test…

Regards,

1 Like

New year greetings !!
A query

why to use above blob and then use

+		pinctrl-0 = <&spi0_nfc_pins>;

when we are refering the below two explicity

		enable-gpio = <&gpio1 16 GPIO_ACTIVE_HIGH>;
		interrupts = <19 IRQ_TYPE_EDGE_RISING>;

I checked on the raspberry side example(for i2c) > https://www.nxp.com/docs/en/application-note/AN11690.pdf , Page 5
and based on that I am asking this.

        pinctrl-0 = <&pinctrl_i2c3>;
        status = "okay";
 
+       pn54x: pn54x@28 {
+               compatible ="nxp,pn547";
+               reg = <0x28>;
+               interrupt-gpios = <&gpio5 11 0>;
+               enable-gpios = <&gpio5 12 0>;
+       };
+

Regards,

Simple, while you “explicitly” told the pn54x driver to use them… You still need to configure the “pinmux” of the gpio into the proper mode. (in this case MUX_MODE7)… Otherwise those signals will not be actually routed to the pins on the SOC.

You only posted a small section, i’m betting gpio5_11/gpio5_12 are pre-configured as GPIO by default somewhere in the Device Tree for that other device…

Regards,