bcm2711/spi: Create interrupt-based SPI driver.

This implements an interrupt-based SPI driver for the BCM2711 SPI
interfaces (excluding auxiliary SPI interfaces). Only tested on SPI0
since proprietary firmware does not initialize any other SPI interfaces,
and doing so will require reverse engineering.
This commit is contained in:
Matteo Golin
2025-05-19 17:50:43 -04:00
committed by Alan C. Assis
parent 7cb09d96e3
commit 3feb9985a5
9 changed files with 1123 additions and 220 deletions

View File

@@ -4,6 +4,26 @@ Raspberry Pi 4B
.. tags:: chip:bcm2711, experimental
.. warning::
The board support for this device is experimental. Not all features are
implemented and they have not been extensively tested by many users.
Help is wanted if you are interested in supporting a feature or if you've
found an issue with any of the implementation! See :doc:`the contributing
guidelines </contributing/index>`.
.. warning::
The SPI driver implemented for the :doc:`BCM2711 <../../index>` has only been
tested on SPI0. It appears that even using the special `overlays
<https://github.com/raspberrypi/linux/blob/stable/arch/arm/boot/dts/overlays/README>`_
for the device tree passed to the proprietary firmware does not properly
initialize the remaining SPI interfaces, and thus they have not been working
properly. More effort is required to reverse engineer the magic incantations
required to initialize these interfaces, at which point it is assumed that
the driver implementation should extend to SPI3-6.
The `Raspberry Pi 4B <https://www.raspberrypi.com/products/raspberry-pi-4-model-b/specifications/>`_ is an ARM64
hobbyist board created by Raspberry Pi.
@@ -139,17 +159,14 @@ Board Peripheral Support
SMP is currently unsupported.
To see support for general chip peripherals (I2C, SPI, UART, etc), see the
:doc:`BCM2711 page <../../index>`
NuttX for the Raspberry Pi 4 supports these on-board peripherals:
======================== =======
Peripheral Support
======================== =======
I2C Partial (able to read, that's it)
UART Mini UART yes, PL011 no
GPIO Partial
PWM No
SPI No
PCM No
AV port No
HDMI No
WiFi No

View File

@@ -2,12 +2,38 @@
BCM2711
=======
The `BCM2711 <https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711>`_ is a Broadcom SoC used for
the Raspberry Pi 4B board.
.. tags:: chip:bcm2711, experimental
.. warning::
The support for this chip is experimental. Not all features are
implemented and they have not been extensively tested by many users.
Help is wanted if you are interested in supporting a feature or if you've
found an issue with any of the implementation! See :doc:`the contributing
guidelines </contributing/index>`.
The `BCM2711
<https://www.raspberrypi.com/documentation/computers/processors.html#bcm2711>`_
is a Broadcom SoC used for the Raspberry Pi 4B board.
- **CPU:** Quad-core ARM Cortex-A72
- **Interrupt Controller:** GIC400
Supported Peripherals
=====================
======================== =======
Peripheral Support
======================== =======
I2C Partial (able to read, that's it)
UART Mini UART yes, PL011 no
GPIO Partial
PWM No
SPI Interrupt-based driver (no DMA) for all SPI except 1 & 2 (auxiliary)
PCM No
======================== =======
Supported Boards
================

View File

@@ -20,8 +20,8 @@
*
****************************************************************************/
#ifndef __ARCH_ARM64_SRC_BCM2711_IRQ_H
#define __ARCH_ARM64_SRC_BCM2711_IRQ_H
#ifndef __ARCH_ARM64_INCLUDE_BCM2711_IRQ_H
#define __ARCH_ARM64_INCLUDE_BCM2711_IRQ_H
/****************************************************************************
* Pre-processor Definitions
@@ -122,8 +122,6 @@
#define BCM_IRQ_VC_EMMC BCM_IRQ_VC(62)
#define BCM_IRQ_VC_ETHPCIESEC BCM_IRQ_VC(63)
/* TODO: what about PACTL_CS address section 6.2.4? */
/* ETH_PCIe interrupts */
#define BCM_IRQ_ETH_BASE 160
@@ -143,4 +141,4 @@
#define BCM_IRQ_ARMLOCAL_IRQ_SOURCEN_MAILBOX_CORE3_IRQ (1 << 4)
#define BCM_IRQ_ARMLOCAL_IRQ_SOURCEN_CNT_V_IRQ (1 << 3)
#endif // __ARCH_ARM64_SRC_BCM2711_IRQ_H
#endif // __ARCH_ARM64_INCLUDE_BCM2711_IRQ_H

View File

@@ -103,17 +103,92 @@ config BCM2711_SPI
if BCM2711_SPI
config BCM2711_SPI1
bool "SPI1"
config BCM2711_SPI0
bool "SPI0"
depends on BCM2711_SPI
default n
---help---
Enable the SPI1 interface.
Enable the SPI0 interface.
if BCM2711_SPI0
config BCM2711_SPI0_CE0
int "CE0 GPIO"
depends on BCM2711_SPI0
default 8
---help---
The GPIO pin for the chip enable 0 signal (8, 36, 43)
config BCM2711_SPI0_CE1
int "CE1 GPIO"
depends on BCM2711_SPI0
default 7
---help---
The GPIO pin for the chip enable 1 signal (7, 35, 44)
config BCM2711_SPI0_MISO
int "MISO GPIO"
depends on BCM2711_SPI0
default 9
---help---
The GPIO pin for the MISO signal (9, 37, 40)
config BCM2711_SPI0_MOSI
int "MOSI GPIO"
depends on BCM2711_SPI0
default 10
---help---
The GPIO pin for the MOSI signal (10, 38, 41)
config BCM2711_SPI0_SCLK
int "SCLK GPIO"
depends on BCM2711_SPI0
default 11
---help---
The GPIO pin for the SCLK signal (11, 39, 42)
endif
config BCM2711_SPI1
bool "SPI1"
depends on BCM2711_SPI
default n
---help---
Enable the SPI1 interface (auxiliary).
config BCM2711_SPI2
bool "SPI2"
default n
---help---
Enable the SPI2 interface.
Enable the SPI2 interface (auxiliary).
config BCM2711_SPI3
bool "SPI3"
depends on BCM2711_SPI
default n
---help---
Enable the SPI3 interface.
config BCM2711_SPI4
bool "SPI4"
depends on BCM2711_SPI
default n
---help---
Enable the SPI4 interface.
config BCM2711_SPI5
bool "SPI5"
depends on BCM2711_SPI
default n
---help---
Enable the SPI5 interface.
config BCM2711_SPI6
bool "SPI6"
depends on BCM2711_SPI
default n
---help---
Enable the SPI6 interface.
endif # BCM2711_SPI

View File

@@ -327,22 +327,25 @@ void bcm2711_gpio_set_pulls(uint32_t gpio, bool up, bool down)
if (gpio <= 15)
{
value = (direction << (gpio * 2));
modreg32(value, value, BCM_GPIO_PUP_PDN_CNTRL_REG0);
modreg32(value, (0x3 << (gpio * 2)), BCM_GPIO_PUP_PDN_CNTRL_REG0);
}
else if (gpio <= 31 && gpio > 15)
{
value = (direction << ((gpio - 16) * 2));
modreg32(value, value, BCM_GPIO_PUP_PDN_CNTRL_REG1);
modreg32(value, (0x3 << ((gpio - 16) * 2)),
BCM_GPIO_PUP_PDN_CNTRL_REG1);
}
else if (gpio <= 47 && gpio > 31)
{
value = (direction << ((gpio - 32) * 2));
modreg32(value, value, BCM_GPIO_PUP_PDN_CNTRL_REG2);
modreg32(value, (0x3 << ((gpio - 32) * 2)),
BCM_GPIO_PUP_PDN_CNTRL_REG2);
}
else if (gpio <= 57 && gpio > 47)
{
value = (direction << ((gpio - 48) * 2));
modreg32(value, value, BCM_GPIO_PUP_PDN_CNTRL_REG3);
modreg32(value, (0x3 << ((gpio - 48) * 2)),
BCM_GPIO_PUP_PDN_CNTRL_REG3);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -33,108 +33,6 @@
* Pre-processor Definitions
****************************************************************************/
/* ARM_LOCAL interrupts */
/* ARMC interrupts */
#define BCM_IRQ_ARMC_TIMER 0 /* Timer */
#define BCM_IRQ_ARMC_MAILBOX 1 /* Mailbox */
#define BCM_IRQ_ARMC_DOORBELL0 2 /* Doorbell 0 */
#define BCM_IRQ_ARMC_DOORBELL1 3 /* Doorbell 1 */
#define BCM_IRQ_ARMC_VPU0HALT 4 /* VPU 0 halted */
#define BCM_IRQ_ARMC_VPU1HALT 5 /* VPU 1 halted */
#define BCM_IRQ_ARMC_ARMADDRERR 6 /* ARM address error */
#define BCM_IRQ_ARMC_ARMAXIERR 7 /* ARM AXI error */
#define BCM_IRQ_ARMC_SWI0 8 /* Software interrupt 0 */
#define BCM_IRQ_ARMC_SWI1 9 /* Software interrupt 1 */
#define BCM_IRQ_ARMC_SWI2 10 /* Software interrupt 2 */
#define BCM_IRQ_ARMC_SWI3 11 /* Software interrupt 3 */
#define BCM_IRQ_ARMC_SWI4 12 /* Software interrupt 4 */
#define BCM_IRQ_ARMC_SWI5 13 /* Software interrupt 5 */
#define BCM_IRQ_ARMC_SWI6 14 /* Software interrupt 6 */
#define BCM_IRQ_ARMC_SWI7 15 /* Software interrupt 7 */
/* VideoCore interrupts */
#define BCM_IRQ_VC_TIMER0 0
#define BCM_IRQ_VC_TIMER1 1
#define BCM_IRQ_VC_TIMER2 2
#define BCM_IRQ_VC_TIMER3 3
#define BCM_IRQ_VC_H2640 4
#define BCM_IRQ_VC_H2641 5
#define BCM_IRQ_VC_H2642 6
#define BCM_IRQ_VC_JPEG 7
#define BCM_IRQ_VC_ISP 8
#define BCM_IRQ_VC_USB 9
#define BCM_IRQ_VC_V3D 10
#define BCM_IRQ_VC_TRANSPOSE 11
#define BCM_IRQ_VC_MCSYNC0 12
#define BCM_IRQ_VC_MCSYNC1 13
#define BCM_IRQ_VC_MCSYNC2 14
#define BCM_IRQ_VC_MCSYNC3 15
#define BCM_IRQ_VC_DMA0 16
#define BCM_IRQ_VC_DMA1 17
#define BCM_IRQ_VC_DMA2 18
#define BCM_IRQ_VC_DMA3 19
#define BCM_IRQ_VC_DMA4 20
#define BCM_IRQ_VC_DMA5 21
#define BCM_IRQ_VC_DMA6 22
#define BCM_IRQ_VC_DMA7N8 23
#define BCM_IRQ_VC_DMA9N10 24
#define BCM_IRQ_VC_DMA11 25
#define BCM_IRQ_VC_DMA12 26
#define BCM_IRQ_VC_DMA13 27
#define BCM_IRQ_VC_DMA14 28
#define BCM_IRQ_VC_AUX 29
#define BCM_IRQ_VC_ARM 30
#define BCM_IRQ_VC_DMA15 31
#define BCM_IRQ_VC_HDMICEC 32
#define BCM_IRQ_VC_HVS 33
#define BCM_IRQ_VC_RPIVID 34
#define BCM_IRQ_VC_SDC 35
#define BCM_IRQ_VC_DSI0 36
#define BCM_IRQ_VC_PIXVLV2 37
#define BCM_IRQ_VC_CAM0 38
#define BCM_IRQ_VC_CAM1 39
#define BCM_IRQ_VC_HDMI0 40
#define BCM_IRQ_VC_HDMI1 41
#define BCM_IRQ_VC_PIXVLV3 42
#define BCM_IRQ_VC_SPIBSCSLV 43
#define BCM_IRQ_VC_DSI1 44
#define BCM_IRQ_VC_PXLVLV0 45
#define BCM_IRQ_VC_PXLVLV1N4 46
#define BCM_IRQ_VC_CPR 47
#define BCM_IRQ_VC_SMI 48
#define BCM_IRQ_VC_GPIO0 49
#define BCM_IRQ_VC_GPIO1 50
#define BCM_IRQ_VC_GPIO2 51
#define BCM_IRQ_VC_GPIO3 52
#define BCM_IRQ_VC_I2C 53
#define BCM_IRQ_VC_SPI 54
#define BCM_IRQ_VC_PCMI2S 55
#define BCM_IRQ_VC_SDHOST 56
#define BCM_IRQ_VC_PL011UART 57
#define BCM_IRQ_VC_ETHPCIE 58
#define BCM_IRQ_VC_VEC 59
#define BCM_IRQ_VC_CPG 60
#define BCM_IRQ_VC_RNG 61
#define BCM_IRQ_VC_EMMC 62
#define BCM_IRQ_VC_ETHPCIESEC 63
/* TODO: what about PACTL_CS address section 6.2.4? */
/* ETH_PCIe interrupts */
#define BCM_IRQ_ETH_AVS 9
#define BCM_IRQ_ETH_PCIE0_INTA 15
#define BCM_IRQ_ETH_PCIE0_INTB 16
#define BCM_IRQ_ETH_PCIE0_INTC 17
#define BCM_IRQ_ETH_PCIE0_INTD 18
#define BCM_IRQ_ETH_PCIE0_MSI 20
#define BCM_IRQ_ETH_GENET0_A 29
#define BCM_IRQ_ETH_GENET0_B 30
#define BCM_IRQ_ETH_USB0_XHCI0 48
/* ARM_LOCAL interrupt register offsets */
#define BCM_IRQ_ARMLOCAL_ARM_CONTROL_OFFSET 0x00
@@ -605,4 +503,29 @@
#define BCM_IRQ_ARMC_SWIRQ_SET_SW_INT (0xff)
#define BCM_IRQ_ARMC_SWIRQ_CLEAR_SW_INT (0xff)
/* PACTL_CS register bit definitions */
#define BCM_PACTL_CS_SPI0 (1 << 0)
#define BCM_PACTL_CS_SPI1 (1 << 1)
#define BCM_PACTL_CS_SPI2 (1 << 2)
#define BCM_PACTL_CS_SPI3 (1 << 3)
#define BCM_PACTL_CS_SPI4 (1 << 4)
#define BCM_PACTL_CS_SPI5 (1 << 5)
#define BCM_PACTL_CS_SPI6 (1 << 6)
#define BCM_PACTL_CS_I2C0 (1 << 8)
#define BCM_PACTL_CS_I2C1 (1 << 9)
#define BCM_PACTL_CS_I2C2 (1 << 10)
#define BCM_PACTL_CS_I2C3 (1 << 11)
#define BCM_PACTL_CS_I2C4 (1 << 12)
#define BCM_PACTL_CS_I2C5 (1 << 13)
#define BCM_PACTL_CS_I2C6 (1 << 14)
#define BCM_PACTL_CS_I2C7 (1 << 15)
#define BCM_PACTL_CS_UART5 (1 << 16)
#define BCM_PACTL_CS_UART4 (1 << 17)
#define BCM_PACTL_CS_UART3 (1 << 18)
#define BCM_PACTL_CS_UART2 (1 << 19)
#define BCM_PACTL_CS_UART0 (1 << 20)
#endif /* __ARCH_ARM64_SRC_BCM2711_IRQ_H */

View File

@@ -103,6 +103,10 @@
#define BCM_DMA15_BASE \
(BCM_PERIPHERAL_BASEADDR + 0x000e05000) /* DMA Channel 15 */
/* PACTL register address */
#define BCM_PACTL_CS (BCM_PERIPHERAL_BASEADDR + 0x204e00)
/* ARM_LOCAL base address */
#if defined(CONFIG_BCM2711_LOW_PERIPHERAL)

View File

@@ -44,40 +44,12 @@
/* SPI register addresses */
#define BCM_SPI0_CS (BCM_SPI0_BASEADDR + BCM_SPI_CS_OFFSET)
#define BCM_SPI0_FIFO (BCM_SPI0_BASEADDR + BCM_SPI_FIFO_OFFSET)
#define BCM_SPI0_CLK (BCM_SPI0_BASEADDR + BCM_SPI_CLK_OFFSET)
#define BCM_SPI0_DLEN (BCM_SPI0_BASEADDR + BCM_SPI_DLEN_OFFSET)
#define BCM_SPI0_LTOH (BCM_SPI0_BASEADDR + BCM_SPI_LTOH_OFFSET)
#define BCM_SPI0_DC (BCM_SPI0_BASEADDR + BCM_SPI_DC_OFFSET)
#define BCM_SPI3_CS (BCM_SPI3_BASEADDR + BCM_SPI_CS_OFFSET)
#define BCM_SPI3_FIFO (BCM_SPI3_BASEADDR + BCM_SPI_FIFO_OFFSET)
#define BCM_SPI3_CLK (BCM_SPI3_BASEADDR + BCM_SPI_CLK_OFFSET)
#define BCM_SPI3_DLEN (BCM_SPI3_BASEADDR + BCM_SPI_DLEN_OFFSET)
#define BCM_SPI3_LTOH (BCM_SPI3_BASEADDR + BCM_SPI_LTOH_OFFSET)
#define BCM_SPI3_DC (BCM_SPI3_BASEADDR + BCM_SPI_DC_OFFSET)
#define BCM_SPI4_CS (BCM_SPI4_BASEADDR + BCM_SPI_CS_OFFSET)
#define BCM_SPI4_FIFO (BCM_SPI4_BASEADDR + BCM_SPI_FIFO_OFFSET)
#define BCM_SPI4_CLK (BCM_SPI4_BASEADDR + BCM_SPI_CLK_OFFSET)
#define BCM_SPI4_DLEN (BCM_SPI4_BASEADDR + BCM_SPI_DLEN_OFFSET)
#define BCM_SPI4_LTOH (BCM_SPI4_BASEADDR + BCM_SPI_LTOH_OFFSET)
#define BCM_SPI4_DC (BCM_SPI4_BASEADDR + BCM_SPI_DC_OFFSET)
#define BCM_SPI5_CS (BCM_SPI5_BASEADDR + BCM_SPI_CS_OFFSET)
#define BCM_SPI5_FIFO (BCM_SPI5_BASEADDR + BCM_SPI_FIFO_OFFSET)
#define BCM_SPI5_CLK (BCM_SPI5_BASEADDR + BCM_SPI_CLK_OFFSET)
#define BCM_SPI5_DLEN (BCM_SPI5_BASEADDR + BCM_SPI_DLEN_OFFSET)
#define BCM_SPI5_LTOH (BCM_SPI5_BASEADDR + BCM_SPI_LTOH_OFFSET)
#define BCM_SPI5_DC (BCM_SPI5_BASEADDR + BCM_SPI_DC_OFFSET)
#define BCM_SPI6_CS (BCM_SPI6_BASEADDR + BCM_SPI_CS_OFFSET)
#define BCM_SPI6_FIFO (BCM_SPI6_BASEADDR + BCM_SPI_FIFO_OFFSET)
#define BCM_SPI6_CLK (BCM_SPI6_BASEADDR + BCM_SPI_CLK_OFFSET)
#define BCM_SPI6_DLEN (BCM_SPI6_BASEADDR + BCM_SPI_DLEN_OFFSET)
#define BCM_SPI6_LTOH (BCM_SPI6_BASEADDR + BCM_SPI_LTOH_OFFSET)
#define BCM_SPI6_DC (BCM_SPI6_BASEADDR + BCM_SPI_DC_OFFSET)
#define BCM_SPI_CS(base) ((base) + BCM_SPI_CS_OFFSET)
#define BCM_SPI_FIFO(base) ((base) + BCM_SPI_FIFO_OFFSET)
#define BCM_SPI_CLK(base) ((base) + BCM_SPI_CLK_OFFSET)
#define BCM_SPI_DLEN(base) ((base) + BCM_SPI_DLEN_OFFSET)
#define BCM_SPI_LTOH(base) ((base) + BCM_SPI_LTOH_OFFSET)
#define BCM_SPI_DC(base) ((base) + BCM_SPI_DC_OFFSET)
/* SPI register bit definitions */
@@ -123,4 +95,8 @@
#define BCM_SPI_DC_TPANIC (0xff << 8)
#define BCM_SPI_DC_TDREQ (0xff << 0)
/* Informational constants */
#define BCM_SPI_FIFO_DEPTH 16
#endif /* __ARCH_ARM64_SRC_BCM2711_SPI_H */