On Fri, 15 May 2026 at 14:07, Simon Glass <[email protected]> wrote:
>
> Hi Aidan,
>
> On 2026-05-13T00:26:04, Aidan Garske <[email protected]> wrote:
> > spi: add BCM2835/BCM2711 hardware SPI controller driver
> >
> > The BCM2835/BCM2711 SoC on Raspberry Pi 3/4 has no in-tree U-Boot
> > driver for its hardware SPI0 controller; existing U-Boot work with
> > SPI peripherals on these boards has to fall back to GPIO bit-banging
> > via spi-gpio.  That fallback is functional but slow (a few hundred
> > kHz versus the 32 MHz the controller supports), and for protocols
> > like the Infineon SLB9670 / SLB9672 TPM 2.0 TIS interface it makes
> > early-boot operations (startup, self-test, PCR extend) noticeably
> > sluggish.
> >
> > Port the Linux kernel driver drivers/spi/spi-bcm2835.c into U-Boot
> > so existing device-tree nodes using the 'brcm,bcm2835-spi' /
> > 'brcm,bcm2711-spi' compatible work out of the box.  The port keeps
> > the same register layout and software-GPIO chip-select scheme the
> > Linux driver already uses, which is necessary to work around the
> > BCM2835 SPI block's CS auto-deassert behaviour - that behaviour
> > corrupts multi-byte TPM TIS transactions when hardware CS is left
> > enabled.
> >
> > [...]
> >
> > drivers/spi/Kconfig       |   9 +
> >  drivers/spi/Makefile      |   1 +
> >  drivers/spi/bcm2835_spi.c | 440 
> > ++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 450 insertions(+)
>
> > diff --git a/drivers/spi/bcm2835_spi.c b/drivers/spi/bcm2835_spi.c
> > @@ -0,0 +1,440 @@
> > +/* TPM Reset via GPIO4 and GPIO24 */
> > +static void bcm2835_spi_tpm_reset(void)
> > +{
> > +     void __iomem *gpio_base = (void __iomem *)0xFE200000;
> > +     u32 val;
> > +
> > +     /* Set GPIO4 as output (GPFSEL0, bits 14:12) */
>
> The GPIO base should come from the devicetree and more generally,
> access to it should be via a GPIO driver. Please use lower-case hex.
>
> This should not be in a generic SPI controller driver, and it
> contradicts the commit message claim that the driver is not
> TPM-specific. Any board that probes this driver currently pulses GPIO4
> and GPIO24 low for 100 ms - what if something is wired to those pins?
> TPM reset belongs in the TPM driver (perhaps with a gpio-reset in the
> DT node for the TPM).
>
> > diff --git a/drivers/spi/bcm2835_spi.c b/drivers/spi/bcm2835_spi.c
> > @@ -0,0 +1,440 @@
> > +/* GPIO base for software CS control */
> > +static void __iomem *g_gpio_base = (void __iomem *)0xFE200000;
>
> This is BCM2711-only, so BCM2835 (Pi 3, which the Kconfig help and
> commit subject both advertise) has its GPIO block at 0x3f200000, so
> the driver will silently corrupt unrelated memory there. Anyway,
> U-Boot already has pinctrl (pinctrl-bcm283x.c) and GPIO
> (bcm2835_gpio.c) drivers for this SoC; please go through those.
>
> > diff --git a/drivers/spi/bcm2835_spi.c b/drivers/spi/bcm2835_spi.c
> > @@ -0,0 +1,440 @@
> > +     /* Try to get CS GPIO from device tree */
> > +     ret = gpio_request_by_name(bus, 'cs-gpios', 0, &priv->cs_gpio,
> > +                                GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
> > +     if (!ret) {
> > +             priv->cs_gpio_valid = 1;
> > +             /* Deassert CS initially */
> > +             dm_gpio_set_value(&priv->cs_gpio, 1);
> > +     } else {
> > +             priv->cs_gpio_valid = 0;
> > +     }
>
> priv->cs_gpio and priv->cs_gpio_valid are written here but never read
> - bcm2835_spi_xfer() instead does
>
>    int cs_pin = (cs == 0) ? 8 : 7;
>
> and pokes GPSET0/GPCLR0 directly, ignoring the DT. Either honour
> cs-gpios via dm_gpio_set_value() (the normal U-Boot pattern, which
> DM_SPI_GPIO already handles generically), or drop the cs_gpio request
> and document that the driver hardcodes the Pi SPI0 CE0/CE1 pin
> assignment. As written it's half of each.
>
> > diff --git a/drivers/spi/bcm2835_spi.c b/drivers/spi/bcm2835_spi.c
> > @@ -0,0 +1,440 @@
> > +struct bcm2835_spi_priv {
> > +     void __iomem *regs;
> > +     u32 clk_hz;
> > +     u32 cs_reg;         /* Cached CS register value */
> > +     u32 speed_hz;
> > +     u8 mode;
> > +     struct gpio_desc cs_gpio;
> > +     int cs_gpio_valid;
> > +     int cs_asserted;    /* Track if CS should stay asserted between 
> > transfers */
> > +};
>
> cs_asserted is assigned in three places in xfer() but never read.
> Please remove it (and the comment that promises behaviour it does not
> implement).
>
> > diff --git a/drivers/spi/bcm2835_spi.c b/drivers/spi/bcm2835_spi.c
> > @@ -0,0 +1,440 @@
> > +/* Default clock rate - 250 MHz for Pi 4 */
> > +#define BCM2835_SPI_DEFAULT_CLK     250000000
>
> This is the SPI core/source clock, not a default transfer rate - the
> default transfer speed is 1 MHz below. The name is confusing. More
> importantly, on BCM2835 vs BCM2711 vs different VPU clock settings
> this number is not constant; please pull it from the clk uclass (or
> from clock-frequency in DT, which you already read, with no hard-coded
> fallback).
>
> > diff --git a/drivers/spi/bcm2835_spi.c b/drivers/spi/bcm2835_spi.c
> > @@ -0,0 +1,440 @@
> > +static inline void bcm2835_spi_writel(struct bcm2835_spi_priv *priv,
> > +                                                                        
> > u32 reg, u32 val)
> > +{
> > +     writel(val, priv->regs + reg);
> > +}
>
> Please check indent for tab-alignment. Patman or checkpatch will flag these.
>
> > diff --git a/drivers/spi/bcm2835_spi.c b/drivers/spi/bcm2835_spi.c
> > @@ -0,0 +1,440 @@
> > +     /* Poll for completion - transfer byte by byte */
> > +     timeout = 100000;
> > +     while ((tx_count < len || rx_count < len) && timeout > 0) {
>
> The 100000 and 10000 timeouts are bare loop counters, not time bounds
> so at 1 MHz a 4 KB transfer takes ~32 ms and the loop body has no
> fixed cost, so these mean nothing except 'don't hang forever'. Please
> convert to get_timer() / timer_get_us(), the way other DM_SPI drivers
> do, so the timeout is independent of CPU speed and transfer length.
>
> > diff --git a/drivers/spi/bcm2835_spi.c b/drivers/spi/bcm2835_spi.c
> > @@ -0,0 +1,440 @@
> > +config BCM2835_SPI
> > +     bool "BCM2835/BCM2711 SPI driver"
> > +     depends on ARCH_BCM283X
>
> Given the hard-coded 0xfe200000 GPIO base and the BCM2711-only fix-up
> in of_to_plat(), the BCM2835 half of this option is not actually
> supported. Either fix the driver to derive the GPIO base from DT /
> from the existing bcm2835_gpio driver and exercise it on a Pi 3, or
> narrow the Kconfig text and commit subject to say BCM2711 only.

This needs to support all, if it's an option people will try to use it
and get a bad experience.

Reply via email to