OBS-URL: https://build.opensuse.org/request/show/1146923 OBS-URL: https://build.opensuse.org/package/show/hardware:boot/u-boot?expand=0&rev=206
131 lines
3.8 KiB
Diff
131 lines
3.8 KiB
Diff
From 370b4e60fdfd9af54571f5e7aac55f6799f638ff Mon Sep 17 00:00:00 2001
|
|
From: "Ivan T. Ivanov" <iivanov@suse.de>
|
|
Date: Tue, 23 Jan 2024 10:07:57 +0200
|
|
Subject: [PATCH] mmc: bcmstb: Add support for bcm2712 SD controller
|
|
|
|
Make sure that core SDHCI accessors are used and add
|
|
device specific card detection initialization, which
|
|
is borrowed from vendor Linux driver code.
|
|
|
|
Tested-by: Jens Maus <mail@jens-maus.de>
|
|
Tested by: Darko Alavanja <darko.alavanja@konsulko.com>
|
|
Signed-off-by: Ivan T. Ivanov <iivanov@suse.de>
|
|
Signed-off-by: Matthias Brugger <mbrugger@suse.com>
|
|
---
|
|
drivers/mmc/bcmstb_sdhci.c | 64 +++++++++++++++++++++++++++++++++++---
|
|
1 file changed, 60 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c
|
|
index dc96818cff4..49846adcf54 100644
|
|
--- a/drivers/mmc/bcmstb_sdhci.c
|
|
+++ b/drivers/mmc/bcmstb_sdhci.c
|
|
@@ -38,15 +38,52 @@
|
|
*/
|
|
#define BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY 400000
|
|
|
|
-/*
|
|
- * This driver has only been tested with eMMC devices; SD devices may
|
|
- * not work.
|
|
- */
|
|
+#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_plat {
|
|
struct mmc_config cfg;
|
|
struct mmc mmc;
|
|
};
|
|
|
|
+struct sdhci_brcmstb_dev_priv {
|
|
+ int (*init)(struct udevice *dev);
|
|
+};
|
|
+
|
|
+static int sdhci_brcmstb_init_2712(struct udevice *dev)
|
|
+{
|
|
+ struct sdhci_host *host = dev_get_priv(dev);
|
|
+ void *cfg_regs;
|
|
+ u32 reg;
|
|
+
|
|
+ /* Map in the non-standard CFG registers */
|
|
+ cfg_regs = dev_remap_addr_name(dev, "cfg");
|
|
+ if (!cfg_regs)
|
|
+ return -ENOENT;
|
|
+
|
|
+ if ((host->mmc->host_caps & MMC_CAP_NONREMOVABLE) ||
|
|
+ (host->mmc->host_caps & MMC_CAP_NEEDS_POLL)) {
|
|
+ /* Force presence */
|
|
+ reg = readl(cfg_regs + SDIO_CFG_CTRL);
|
|
+ reg &= ~SDIO_CFG_CTRL_SDCD_N_TEST_LEV;
|
|
+ reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN;
|
|
+ writel(reg, cfg_regs + SDIO_CFG_CTRL);
|
|
+ } else {
|
|
+ /* Enable card detection line */
|
|
+ reg = readl(cfg_regs + SDIO_CFG_SD_PIN_SEL);
|
|
+ reg &= ~SDIO_CFG_SD_PIN_SEL_MASK;
|
|
+ reg |= SDIO_CFG_SD_PIN_SEL_CARD;
|
|
+ writel(reg, cfg_regs + SDIO_CFG_SD_PIN_SEL);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int sdhci_bcmstb_bind(struct udevice *dev)
|
|
{
|
|
struct sdhci_bcmstb_plat *plat = dev_get_plat(dev);
|
|
@@ -54,14 +91,20 @@ static int sdhci_bcmstb_bind(struct udevice *dev)
|
|
return sdhci_bind(dev, &plat->mmc, &plat->cfg);
|
|
}
|
|
|
|
+/* No specific SDHCI operations are required */
|
|
+static const struct sdhci_ops bcmstb_sdhci_ops = { 0 };
|
|
+
|
|
static int sdhci_bcmstb_probe(struct udevice *dev)
|
|
{
|
|
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
|
struct sdhci_bcmstb_plat *plat = dev_get_plat(dev);
|
|
struct sdhci_host *host = dev_get_priv(dev);
|
|
+ struct sdhci_brcmstb_dev_priv *dev_priv;
|
|
fdt_addr_t base;
|
|
int ret;
|
|
|
|
+ dev_priv = (struct sdhci_brcmstb_dev_priv *)dev_get_driver_data(dev);
|
|
+
|
|
base = dev_read_addr(dev);
|
|
if (base == FDT_ADDR_T_NONE)
|
|
return -EINVAL;
|
|
@@ -75,6 +118,8 @@ static int sdhci_bcmstb_probe(struct udevice *dev)
|
|
|
|
host->mmc = &plat->mmc;
|
|
host->mmc->dev = dev;
|
|
+ host->ops = &bcmstb_sdhci_ops;
|
|
+
|
|
ret = sdhci_setup_cfg(&plat->cfg, host,
|
|
BCMSTB_SDHCI_MAXIMUM_CLOCK_FREQUENCY,
|
|
BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY);
|
|
@@ -84,10 +129,21 @@ static int sdhci_bcmstb_probe(struct udevice *dev)
|
|
upriv->mmc = &plat->mmc;
|
|
host->mmc->priv = host;
|
|
|
|
+ if (dev_priv && dev_priv->init) {
|
|
+ ret = dev_priv->init(dev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
return sdhci_probe(dev);
|
|
}
|
|
|
|
+static const struct sdhci_brcmstb_dev_priv match_priv_2712 = {
|
|
+ .init = sdhci_brcmstb_init_2712,
|
|
+};
|
|
+
|
|
static const struct udevice_id sdhci_bcmstb_match[] = {
|
|
+ { .compatible = "brcm,bcm2712-sdhci", .data = (ulong)&match_priv_2712 },
|
|
{ .compatible = "brcm,bcm7425-sdhci" },
|
|
{ .compatible = "brcm,sdhci-brcmstb" },
|
|
{ }
|