From: Andrei Lalaev <andrey.lalaev@gmail.com>
To: barebox@lists.infradead.org
Cc: Andrei Lalaev <andrey.lalaev@gmail.com>
Subject: [PATCH RFC 1/6] mci: add driver for Broadcom SDHCI
Date: Tue, 01 Sep 2026 17:12:56 +0200 [thread overview]
Message-ID: <20260901-add-rpi5-support-v1-1-129784fe06fa@gmail.com> (raw)
In-Reply-To: <20260901-add-rpi5-support-v1-0-129784fe06fa@gmail.com>
This adds support for Broadcom SDHCI controller found on BCM2712
SoCs. The driver was ported from U-Boot.
Signed-off-by: Andrei Lalaev <andrey.lalaev@gmail.com>
---
arch/arm/configs/rpi_v8a_defconfig | 1 +
drivers/mci/Kconfig | 5 ++
drivers/mci/Makefile | 1 +
drivers/mci/bcmstb-sdhci.c | 165 +++++++++++++++++++++++++++++++++++++
4 files changed, 172 insertions(+)
diff --git a/arch/arm/configs/rpi_v8a_defconfig b/arch/arm/configs/rpi_v8a_defconfig
index c29fe30701e8..90899218b192 100644
--- a/arch/arm/configs/rpi_v8a_defconfig
+++ b/arch/arm/configs/rpi_v8a_defconfig
@@ -92,6 +92,7 @@ CONFIG_USB_GADGET=y
CONFIG_MCI=y
CONFIG_MCI_BCM283X=y
CONFIG_MCI_BCM283X_SDHOST=y
+CONFIG_MCI_BCMSTB=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_LED_GPIO_OF=y
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 2c3365e723a4..eebf85db9f5f 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -154,6 +154,11 @@ config MCI_BCM283X_SDHOST
depends on ARCH_BCM283X || COMPILE_TEST
select MCI_SDHCI
+config MCI_BCMSTB
+ bool "MCI support for BCMSTB"
+ depends on ARCH_BCM283X || COMPILE_TEST
+ select MCI_SDHCI
+
config MCI_DOVE
bool "Marvell Dove SDHCI"
depends on ARCH_DOVE || COMPILE_TEST
diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
index 761f4187c079..eca997dccbd3 100644
--- a/drivers/mci/Makefile
+++ b/drivers/mci/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_MCI_ATMEL_SDHCI) += atmel-sdhci.o atmel-sdhci-common.o
obj-$(CONFIG_MCI_BCM283X) += mci-bcm2835.o
obj-$(CONFIG_MCI_BCM283X_SDHOST) += bcm2835-sdhost.o
obj-$(CONFIG_MCI_CADENCE_SDHCI) += cadence-sdhci.o cadence-sdhci6.o
+obj-$(CONFIG_MCI_BCMSTB) += bcmstb-sdhci.o
obj-$(CONFIG_MCI_DOVE) += dove-sdhci.o
pbl-$(CONFIG_MCI_ATMEL_PBL) += atmel_mci_pbl.o atmel_mci_common.o
pbl-$(CONFIG_MCI_ATMEL_SDHCI_PBL) += atmel-sdhci-pbl.o atmel-sdhci-common.o
diff --git a/drivers/mci/bcmstb-sdhci.c b/drivers/mci/bcmstb-sdhci.c
new file mode 100644
index 000000000000..f1275a8936ea
--- /dev/null
+++ b/drivers/mci/bcmstb-sdhci.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * This code is ported from U-Boot by Andrei Lalaev <andrey.lalaev@gmail.com>
+ *
+ * The original code has the following copyright:
+ * (C) Copyright 2018 Cisco Systems, Inc.
+ * (C) Copyright 2019 Synamedia
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <mci.h>
+#include <malloc.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include "sdhci.h"
+
+#define BCMSTB_SDHCI_MAXIMUM_CLOCK_FREQUENCY 52000000
+#define BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY 400000
+
+#define SDIO_CFG_CTRL 0x0
+#define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31)
+#define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30)
+
+#define SDIO_CFG_SD_PIN_SEL 0x44
+#define SDIO_CFG_SD_PIN_SEL_MASK 0x3
+#define SDIO_CFG_SD_PIN_SEL_CARD BIT(1)
+
+struct sdhci_bcmstb_mci_host {
+ struct mci_host mci;
+ void __iomem *cfg_regs;
+ struct sdhci sdhci;
+};
+
+static inline struct sdhci_bcmstb_mci_host *to_sdhci_bcmstb_host(struct mci_host *mci)
+{
+ return container_of(mci, struct sdhci_bcmstb_mci_host, mci);
+}
+
+static int sdhci_brcmstb_init_2712(struct mci_host *mci, struct device *dev)
+{
+ struct sdhci_bcmstb_mci_host *host = to_sdhci_bcmstb_host(mci);
+ u32 reg;
+ int ret;
+
+ ret = sdhci_reset(&host->sdhci, SDHCI_RESET_ALL);
+ if (ret)
+ return ret;
+
+ sdhci_write8(&host->sdhci, SDHCI_POWER_CONTROL,
+ SDHCI_BUS_VOLTAGE_330 | SDHCI_BUS_POWER_EN);
+ udelay(400);
+
+ sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK);
+ sdhci_write32(&host->sdhci, SDHCI_SIGNAL_ENABLE, 0x00);
+
+ if (host->mci.host_caps & MMC_CAP_NONREMOVABLE) {
+ /* Force presence */
+ reg = readl(host->cfg_regs + SDIO_CFG_CTRL);
+ reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
+ reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
+ writel(reg, host->cfg_regs + SDIO_CFG_CTRL);
+ } else {
+ /* Enable card detection line */
+ reg = readl(host->cfg_regs + SDIO_CFG_SD_PIN_SEL);
+ reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
+ reg |= SDIO_CFG_SD_PIN_SEL_CARD;
+ writel(reg, host->cfg_regs + SDIO_CFG_SD_PIN_SEL);
+ }
+
+ return 0;
+}
+
+static void sdhci_brcmstb_set_ios(struct mci_host *mci, struct mci_ios *ios)
+{
+ struct sdhci_bcmstb_mci_host *host = to_sdhci_bcmstb_host(mci);
+
+ if (ios->clock)
+ sdhci_set_clock(&host->sdhci, ios->clock, host->sdhci.max_clk);
+ sdhci_set_bus_width(&host->sdhci, ios->bus_width);
+}
+
+static int sdhci_brcmstb_send_cmd(struct mci_host *mci, struct mci_cmd *cmd)
+{
+ struct sdhci_bcmstb_mci_host *host = to_sdhci_bcmstb_host(mci);
+
+ return sdhci_send_command(&host->sdhci, cmd);
+}
+
+static int sdhci_brcmstb_execute_tuning(struct mci_host *mci, u32 opcode)
+{
+ struct sdhci_bcmstb_mci_host *host = to_sdhci_bcmstb_host(mci);
+
+ return sdhci_execute_tuning(&host->sdhci, opcode);
+}
+
+static const struct mci_ops bcmstb_sdhci_ops = {
+ .init = sdhci_brcmstb_init_2712,
+ .set_ios = sdhci_brcmstb_set_ios,
+ .send_cmd = sdhci_brcmstb_send_cmd,
+ .execute_tuning = sdhci_brcmstb_execute_tuning,
+};
+
+static int sdhci_bcmstb_probe(struct device *dev)
+{
+ struct sdhci_bcmstb_mci_host *host;
+ struct resource *iores_cfg;
+ struct resource *iores;
+ struct clk *clk;
+ int ret;
+
+ clk = clk_get(dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ ret = clk_enable(clk);
+ if (ret)
+ return ret;
+
+ iores = dev_request_mem_resource_by_name(dev, "host");
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ iores_cfg = dev_request_mem_resource_by_name(dev, "cfg");
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ host = xzalloc(sizeof(*host));
+ host->mci.ops = bcmstb_sdhci_ops;
+ host->mci.hw_dev = dev;
+ host->mci.f_min = BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY;
+ host->mci.f_max = BCMSTB_SDHCI_MAXIMUM_CLOCK_FREQUENCY;
+
+ host->cfg_regs = IOMEM(iores_cfg->start);
+
+ host->sdhci.base = IOMEM(iores->start);
+ host->sdhci.mci = &host->mci;
+
+ mci_of_parse(&host->mci);
+
+ ret = sdhci_setup_host(&host->sdhci);
+ if (ret) {
+ dev_err(dev, "Failed to setup SDHCI host");
+ return ret;
+ }
+
+ return mci_register(&host->mci);
+}
+
+static const struct of_device_id sdhci_bcmstb_compatible[] = {
+ { .compatible = "brcm,bcm2712-sdhci" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sdhci_bcmstb_match);
+
+static struct driver sdhci_bcmstb_driver = {
+ .name = "sdhci-bcmstb",
+ .probe = sdhci_bcmstb_probe,
+ .of_compatible = DRV_OF_COMPAT(sdhci_bcmstb_compatible),
+};
+
+device_platform_driver(sdhci_bcmstb_driver);
--
2.55.0
next prev parent reply other threads:[~2026-09-01 15:15 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-01 15:12 [RFC PATCH 0/6] Add Raspberry Pi 5 initial support Andrei Lalaev
2026-09-01 15:12 ` Andrei Lalaev [this message]
2026-09-01 15:12 ` [PATCH RFC 2/6] ARM: rpi: add Raspberry Pi 5 support Andrei Lalaev
2026-09-01 15:12 ` [PATCH RFC 3/6] Documentation: bcm283x: " Andrei Lalaev
2026-09-01 15:12 ` [PATCH RFC 4/6] arm: dts: bcm2712-rpi: specify clock frequency for uart Andrei Lalaev
2026-09-01 15:13 ` [PATCH RFC 5/6] arm: dts: bcm2712-rpi: disable wifi SDIO Andrei Lalaev
2026-09-01 15:13 ` [PATCH RFC 6/6] bcm283x: debug_ll: add Raspberry Pi 5 UART support Andrei Lalaev
2026-09-04 9:38 ` [RFC PATCH 0/6] Add Raspberry Pi 5 initial support Sascha Hauer
2026-09-04 10:36 ` Andrei Lalaev
2026-09-04 11:06 ` Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260901-add-rpi5-support-v1-1-129784fe06fa@gmail.com \
--to=andrey.lalaev@gmail.com \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.