All of lore.kernel.org
 help / color / mirror / Atom feed
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




  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.