I’ve been trying to attach multiple SPI devices to SPI2 on the Duo but I’ve got a bit stuck.
As I understand it SPI2 only has one hardware CS so I’ve tried to use cs-gpios. This works if cs-gpios is a single value. With something like the below I can successfully drive an SPI screen attached to that CS.
cs-gpios = <&porta 22 GPIO_ACTIVE_LOW>;
However if I change it to the below then I see errors some timeout errors and the screen can’t be driven through /dev/fb0.
cs-gpios = <&porta 22 GPIO_ACTIVE_LOW>, <&porta 25 GPIO_ACTIVE_LOW>;
[ 1.245165] fb_ili9341 spi0.1: SPI transfer timed out
[ 1.250466] spi_master spi0: failed to transfer one message from queue
I’ve had some success by bringing in the latest 5.10 of drivers/spi and include/spi from the Raspberry Pi Linux repo. Using that I can have a list of multiple cs-gpios and the screen being attached to the first one works. However, if I try to write to the second one then I see timeouts.
I’ve also tried having my cs-gpios contain the hardware CS and a software one and encountered the same errors.
cs-gpios = <0> <&porta 22 GPIO_ACTIVE_LOW>;
This is the spi2 section from my cv1800b_milkv_duo_sd.dts file
&spi2 {
status = "okay";
cs-gpios = <&porta 22 GPIO_ACTIVE_LOW>, <&porta 25 GPIO_ACTIVE_LOW>;
ili9341: ili9341@0 {
compatible = "ilitek,ili9341";
reg = <0>;
status = "okay";
spi-max-frequency = <48000000>;
spi-cpol;
spi-cpha;
rotate = <270>;
fps = <30>;
bgr;
buswidth = <8>;
dc = <&porta 24 GPIO_ACTIVE_HIGH>;
reset = <&porta 23 GPIO_ACTIVE_HIGH>;
debug = <0x0>;
};
spidev@0{
compatible = "spidev";
reg = <1>;
status = "okay";
spi-max-frequency = <48000000>;
};
};
Has anyone else had any luck with multiple CS pins or any ideas on how to proceed?
I use SPI LoRa radio and SPI ST7789 connected to other CS pins (also not defined in dts - using application)
Meshtastic Linux-Native port with TFT gui (m5stack cardkb i2c) - running on Ubuntu 22.04
1 Like
Thanks mark.birss. Reassuring at least to know it’s possible at the hardware level.
I’ve done a lot of digging. I’ve even tried the linux-next 6.9 with all the patches in to see if SPI worked there. Sadly it did not, which was quite a journey.
Anyway, for anyone who finds this, apply the patch that’s here to be able to use multiple chip-selects in the DTS file. SPI transfer fails with [Errno 110] Connection timed out when there are > 4 CS pins configured · Issue #6159 · raspberrypi/linux · GitHub
A quick guide for anybody who reads this now got it working on the 5.10 kernel in buildroot.
Apply this patch
diff --git a/linux_5.10/drivers/spi/spi-dw-core.c b/linux_5.10/drivers/spi/spi-dw-core.c
index c33866f74..1722c2753 100644
--- a/linux_5.10/drivers/spi/spi-dw-core.c
+++ b/linux_5.10/drivers/spi/spi-dw-core.c
@@ -102,7 +102,8 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable)
* support active-high or active-low CS level.
*/
if (cs_high == enable)
- dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select));
+ dw_writel(dws, DW_SPI_SER,
+ BIT(spi->cs_gpiod ? 0 : spi->chip_select));
else
dw_writel(dws, DW_SPI_SER, 0);
}
And then you can patch the DTS file like this to create multiple spidev devices, or replace the spidevs with other peripherals.
&spi2 {
status = "okay";
cs-gpios = <&porta 22 GPIO_ACTIVE_LOW>, <&porta 25 GPIO_ACTIVE_LOW>;
spidev@0 {
compatible = "rohm,dh2228fv";
reg = <0>;
status = "okay";
spi-max-frequency = <48000000>;
};
spidev@1 {
compatible = "rohm,dh2228fv";
reg = <1>;
status = "okay";
spi-max-frequency = <48000000>;
};
};
See here for mappings. Look for things like XGPIOA[22]. Duo | Milk-V
Be aware that anything to use as a chip select must be muxed as a GPIO.
1 Like
Thank you for sharing your finding and fixes.
Using my approach as i did pictured is not working out on the DuoS at the moment…
On the Raspberry Pi we have to make use of that “dtoverlay=spi0-0cs” overlay to stop the kernel from locking the cs pins.
I will have to look into how that overlay for the Milk-V DuoS it seems
This might be what is still missing with the DuoS… when not using Buildroot OS
I’m not sure there’s anything super-useful I can add but there’s a couple of bits from my digging.
I think the Pi has mux support from the device-tree but the Duo doesn’t seem to yet but it looks like it’s in the works on the mainline patches so any muxing is initialised in U-Boot and then some is overridden with the duo-pinmux command in init.d.
The SPI2_CS pin will always be asserted even when using cs-gpios by the way, so you can’t use hardware CS with GPIO CS. You could re-use that pin though by using duo-pinmux to turn it into a GPIO and then using it as a CS.
Thank you, it helps my understanding