Skip to content

Instantly share code, notes, and snippets.

@DenizUgur
Created May 24, 2021 21:28
Show Gist options
  • Save DenizUgur/ecc8591eb8257cc168b23bf0535ac81a to your computer and use it in GitHub Desktop.
Save DenizUgur/ecc8591eb8257cc168b23bf0535ac81a to your computer and use it in GitHub Desktop.
RPi 4B - 4 SPI with DMA
diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
old mode 100644
new mode 100755
index 09a1182c2936..5638d5404a87
--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
@@ -301,3 +301,132 @@ &vc4 {
&vec {
status = "disabled";
};
+
+&gpio {
+ spi0_pins: spi0_pins {
+ brcm,pins = <9 10 11>;
+ brcm,function = <BCM2835_FSEL_ALT0>;
+ };
+
+ spi0_cs_pins: spi0_cs_pins {
+ brcm,pins = <8>;
+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
+ };
+
+ spi4_pins: spi4_pins {
+ brcm,pins = <5 6 7>;
+ brcm,function = <BCM2835_FSEL_ALT3>;
+ };
+
+ spi4_cs_pins: spi4_cs_pins {
+ brcm,pins = <4>;
+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
+ };
+
+ spi5_pins: spi5_pins {
+ brcm,pins = <13 14 15>;
+ brcm,function = <BCM2835_FSEL_ALT3>;
+ };
+
+ spi5_cs_pins: spi5_cs_pins {
+ brcm,pins = <12>;
+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
+ };
+
+ spi6_pins: spi6_pins {
+ brcm,pins = <19 20 21>;
+ brcm,function = <BCM2835_FSEL_ALT3>;
+ };
+
+ spi6_cs_pins: spi6_cs_pins {
+ brcm,pins = <18>;
+ brcm,function = <BCM2835_FSEL_GPIO_OUT>;
+ };
+
+ // Break UART1 (in order to free SPI5)
+ uart1_gpio14: uart1_gpio14 {
+ brcm,pins = <36 37>;
+ brcm,function = <BCM2835_FSEL_ALT5>;
+ };
+
+ uart1_ctsrts_gpio16: uart1_ctsrts_gpio16 {
+ brcm,pins = <38 39>;
+ brcm,function = <BCM2835_FSEL_ALT5>;
+ };
+};
+
+&spi {
+ dmas = <&dma 6>, <&dma 7>;
+ dma-names = "tx", "rx";
+
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
+ cs-gpios = <&gpio 8 1>;
+
+ spidev0_0: spidev@0{
+ compatible = "spidev,loopback";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <12500000>;
+ status = "okay";
+ };
+};
+
+&spi4 {
+ dmas = <&dma 19>, <&dma 20>;
+ dma-names = "tx", "rx";
+
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi4_pins &spi4_cs_pins>;
+ cs-gpios = <&gpio 4 1>;
+
+ spidev4_0: spidev@0{
+ compatible = "spidev,loopback";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <12500000>;
+ status = "okay";
+ };
+};
+
+&spi5 {
+ dmas = <&dma 21>, <&dma 22>;
+ dma-names = "tx", "rx";
+
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi5_pins &spi5_cs_pins>;
+ cs-gpios = <&gpio 12 1>;
+
+ spidev5_0: spidev@0{
+ compatible = "spidev,loopback";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <12500000>;
+ status = "okay";
+ };
+};
+
+&spi6 {
+ dmas = <&dma 23>, <&dma 27>;
+ dma-names = "tx", "rx";
+
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi6_pins &spi6_cs_pins>;
+ cs-gpios = <&gpio 18 1>;
+
+ spidev6_0: spidev@0{
+ compatible = "spidev,loopback";
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ spi-max-frequency = <12500000>;
+ status = "okay";
+ };
+};
\ No newline at end of file
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 63103f27372e..fb7cd6c44da6 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -377,6 +377,10 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
if (bs->tx_len && cs & BCM2835_SPI_CS_DONE)
bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE);
+ /* check if we got interrupt enabled */
+ if (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_INTR))
+ return IRQ_NONE;
+
/* Read as many bytes as possible from FIFO */
bcm2835_rd_fifo(bs);
/* Write as many bytes as possible to FIFO */
@@ -1399,8 +1403,8 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
bcm2835_wr(bs, BCM2835_SPI_CS,
BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
- err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
- dev_name(&pdev->dev), bs);
+ err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt,
+ IRQF_SHARED, dev_name(&pdev->dev), bs);
if (err) {
dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
goto out_dma_release;
This patch is based on a custom linux tree (which is a downstream of v5.10). Custom kernel tree is provided below.
The modification has been also test on upstream Linux and it can be applied manually as it's pretty straightforward patch.
https://git.evlproject.org/linux-evl.git/tree/?h=evl%2Fv5.10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment