NoeMurr
Posts: 5
Joined: Thu May 23, 2019 9:42 am

Add spidev0.2 device

Thu May 23, 2019 10:24 am

Hi all,

I'm using raspberry pi 2 model B as master in a spi communication.

I want to communicate with more than two slaves but the raspberry gives me only /dev/spidev0.0 and /dev/spidev0.1 devices.

Can I configure the device tree to add a new spi device with a custom chip select (e.g. /dev/spidev0.2) ?
If yes how can I do that?

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3840
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Add spidev0.2 device

Thu May 23, 2019 12:51 pm

Yes you can. The Linux SPI subsystem can use arbitrary GPIOs as extra chip select lines. In fact, the BCM2835 SPI driver chooses to use software/GPIO chip selects in preference to the ones driven by the SPI interfaces to work around some limitations.

You can base your interface on the spi0-cs overlay that allows the spi0 CS lines to be changed - something like this ought to work:

Code: Select all

/dts-v1/;
/plugin/;


/ {
	compatible = "brcm,bcm2835";

	fragment@0 {
		target = <&spi0_cs_pins>;
		frag0: __overlay__ {
			brcm,pins = <8 7 6>;
		};
	};

	fragment@1 {
		target = <&spi0>;
		frag1: __overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;

			cs-gpios = <&gpio 8 1>, <&gpio 7 1>, <&gpio 6 1>;
			status = "okay";

			spidev0_2: spidev@2 {
				compatible = "spidev";
				reg = <2>;	/* CE2 */
				#address-cells = <1>;
				#size-cells = <0>;
				spi-max-frequency = <125000000>;
			};
		};
	};

	__overrides__ {
		cs0_pin  = <&frag0>,"brcm,pins:0",
			   <&frag1>,"cs-gpios:4";
		cs1_pin  = <&frag0>,"brcm,pins:4",
			   <&frag1>,"cs-gpios:16";
		cs2_pin  = <&frag0>,"brcm,pins:8",
			   <&frag1>,"cs-gpios:28";
		cs2_spidev = <&spidev0_2>, "status";
 	};
};
(Unfortunately you can't just append to the existing cs-gpios property, hence the need to replicate the standard values).

Save it as spi0-3cs-overlay.dts and compile and install it like this:

Code: Select all

$ dtc -@ -I dts -O dtb -o spi0-3cs.dtbo spi0-3cs-overlay.dts
$ sudo cp spi0-3cs.dtbo /boot/overlays
Use it by adding "dtoverlay=spi0-3cs". If you want to change the CS GPIOs from the defaults, add e.g. ",cs2_pin=12" to the end of the line. To disable spidev0.2 (not that you're likely to want to) add ",cs2_spidev=off".

You can also apply the overlay at run time:

Code: Select all

$ sudo dtoverlay spi0-3cs cs2_pin=12
$ ls /dev/spi*
/dev/spidev0.0  /dev/spidev0.1  /dev/spidev0.2
Note that this overlay includes the enable for spi0, so you no longer need "dtparam=spi0=on".

justwinatch
Posts: 4
Joined: Mon Mar 15, 2021 6:37 am

Re: Add spidev0.2 device

Mon Mar 15, 2021 7:22 am

Hi there,

I am currently trying to add additional chip selects to my Raspberry Pi 4 Model B by creating a new SPI overlay to support the additional CS pins. I have followed the approach as suggested by PhilE, having used the spi0-3cs-overlay.dts code provided, and have been able to successfully add a third chip select.

However, I am having trouble extending this approach. Ultimately, I would like to support 16 different chip selects, but I am uncertain on the meaning behind the __overrides__ section of the provided code, which I have copied below for reference.

Code: Select all

__overrides__ {
		cs0_pin  = <&frag0>,"brcm,pins:0",
			   <&frag1>,"cs-gpios:4";
		cs1_pin  = <&frag0>,"brcm,pins:4",
			   <&frag1>,"cs-gpios:16";
		cs2_pin  = <&frag0>,"brcm,pins:8",
			   <&frag1>,"cs-gpios:28";
		cs2_spidev = <&spidev0_2>, "status";
 	};
Namely, for each of cs0_pin, cs1_pin, and cs2_pin, it says that the brcm pins are 0, 4, and 16, respectively. However, my understanding was that the brcm pins for these CS pins were 8, 7, and 6, respectively? Furthermore, I am not sure where the cs-gpio values are coming from for each of these CS pins, namely the 4, 16, and 28. I can't seem to find a Raspberry Pi model where these brcm and gpio numberings matchup (e.g. where the brcm pin 4 is associated with GPIO 28), and so I am not sure from where these numbers are coming.

If someone wouldn't mind providing clarification as to where these numbering values are coming from in the __overrides__ section, it would be greatly appreciated.

Thanks so much!

dehnhardt
Posts: 3
Joined: Wed May 21, 2014 8:05 pm

Re: Add spidev0.2 device

Fri Apr 09, 2021 10:17 pm

However, I am having trouble extending this approach. Ultimately, I would like to support 16 different chip selects, but I am uncertain on the meaning behind the __overrides__ section of the provided code, which I have copied below for reference.
Tha'ts exactly my current question as well. The values looks like a series: 0, 4, 8 for the pins and 8, 16, 28 for the cs-gpios. Even though I would have expected the actual gpio numbers there. However, if I extend it to 0, 4, 8, 12 and 8, 16, 28, 40, the pins are shown with the given names in gpioinfo.
But i can't see the devices /dev/spidev0.3 and /dev/spidev0.3.
@justwinatch: Did you solve the problem already?

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3840
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Add spidev0.2 device

Mon Apr 12, 2021 9:22 am

Code: Select all

		cs0_pin  = <&frag0>,"brcm,pins:0",
			   <&frag1>,"cs-gpios:4";
These lines declare a DT parameter - "cs0_pin" - and the locations to be patched with its assigned value, e.g. "cs0_pin=23".

The first location is the 4-byte integer (the ":") at offset 0 in the "brcm,pins" property of the node with the label "frag0":

Code: Select all

	fragment@0 {
		target = <&spi0_cs_pins>;
		frag0: __overlay__ {
			brcm,pins = <8 7 6>;
		};
	};
Each of the numbers within the <> angle-brackets is a 4-byte integer, and the integer at offset 0 is the GPIO number for CS 0, i.e. 8. The GPIO for CS 1 is the next integer, i.e. offset 4, making offset = CS * 4.

The second location is the integer at offset 4 in the "cs-gpios" property of the node with the label "frag1":

Code: Select all

	fragment@1 {
		target = <&spi0>;
		frag1: __overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;

			cs-gpios = <&gpio 8 1>, <&gpio 7 1>, <&gpio 6 1>;
...
"&gpio" is a reference to a label, which is converted into a 4-byte integer known as a phandle. This occupies offsets 0-3, putting the "8" at offset 4 and the "1" at offset 8. The offset to the GPIO for CS 1 is 16, the general formula being offset = 12 * CS + 4.

justwinatch
Posts: 4
Joined: Mon Mar 15, 2021 6:37 am

Re: Add spidev0.2 device

Fri Apr 16, 2021 2:07 am

Thank you so much for your help, PhilE! This is exactly the information I was looking for!

All the best!

justwinatch
Posts: 4
Joined: Mon Mar 15, 2021 6:37 am

Re: Add spidev0.2 device

Fri Apr 16, 2021 2:10 am

Hi @dehnhardt,

If you still have questions regarding the addition of SPI devices (chip selects), this other RPi forum thread was also helpful for me, as well!

Here's the link to it: viewtopic.php?t=98318&start=100

Hope this may help provide further clarity!

justwinatch
Posts: 4
Joined: Mon Mar 15, 2021 6:37 am

Re: Add spidev0.2 device

Fri Apr 16, 2021 2:45 am

Thanks again for your help, PhilE!

As a quick follow-up, I'm also a bit curious as to how the following DT overlay code snippet would change for adding a spidev0.3, for example.

This code is copy and pasted from above for adding a spidev0.2:

Code: Select all

spidev0_2: spidev@2 {
		compatible = "spidev";
		reg = <2>;	/* CE2 */
		#address-cells = <1>;
		#size-cells = <0>;
		spi-max-frequency = <125000000>;
};
I'm wondering, to now also add a spidev0.3 (in addition to the other changes that would have to happen to the overlay patch, following the same procedure as when adding the spidev0.2), would the following be a correct approach for doing so:

Code: Select all

spidev0_3: spidev@3 {
		compatible = "spidev";
		reg = <3>;
		#address-cells = <1>;
		#size-cells = <0>;
		spi-max-frequency = <125000000>;
};
I'm wondering if the "reg" is the only thing that would change here? So for then adding a spidev0.4, for example, the "reg" value would become:

Code: Select all

reg=<4>;
Thanks so much for the clarification!

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 3840
Joined: Mon Sep 29, 2014 1:07 pm
Location: Cambridge

Re: Add spidev0.2 device

Fri Apr 16, 2021 8:13 am

Your spidev0.3 looks good. In reviewing that I noticed that I had failed to update the "CE" comment on the spidev0.2 overlay - that's now corrected, to avoid confusion.

In theory adding spidev0.4 would follow the same procedure, but it was brought to my attention yesterday that the SPI driver has a limit of four CEs per controller, and that exceeding that limit could result in undefined behaviour. There's a Pull Request to remove the limit and allow the list to grow dynamically here: https://github.com/raspberrypi/linux/pull/4281

dehnhardt
Posts: 3
Joined: Wed May 21, 2014 8:05 pm

Re: Add spidev0.2 device

Sat Apr 17, 2021 11:22 am

Thank you so much @PhilE and @justwinatch for your replies. Now everything looks much clearer to me!

Holger

Return to “Device Tree”