Add a minimal non-DM MMC driver for use in size-constrained
environments.

Signed-off-by: Ferass El Hafidi <fundersc...@postmarketos.org>
---
 arch/arm/include/asm/arch-meson/gx.h |  5 +++
 drivers/mmc/meson_gx_mmc.c           | 75 +++++++++++++++++++++++++++++++++++-
 2 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-meson/gx.h 
b/arch/arm/include/asm/arch-meson/gx.h
index 
26ec5d0bc340bc03587047d68a88042779e64536..8cfc6b00329f252bbf452dba00f8ad56b480c707
 100644
--- a/arch/arm/include/asm/arch-meson/gx.h
+++ b/arch/arm/include/asm/arch-meson/gx.h
@@ -41,4 +41,9 @@
 #define GX_GPIO_IN(n)          GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 1)
 #define GX_GPIO_OUT(n) GX_PERIPHS_ADDR(_GX_GPIO_OFF(n) + 2)
 
+/* Non-DM MMC init */
+#if CONFIG_IS_ENABLED(MMC) && !CONFIG_IS_ENABLED(DM_MMC)
+struct mmc *meson_mmc_init(int mmc_no);
+#endif
+
 #endif /* __GX_H__ */
diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c
index 
5852b24c6d2a5a9d1b1e8a62f8c0ec325b339182..a4338f1e29c1da07acb0333be9b75a318cba1334
 100644
--- a/drivers/mmc/meson_gx_mmc.c
+++ b/drivers/mmc/meson_gx_mmc.c
@@ -16,6 +16,7 @@
 #include <linux/log2.h>
 #include "meson_gx_mmc.h"
 
+#if CONFIG_IS_ENABLED(DM_MMC)
 bool meson_gx_mmc_is_compatible(struct udevice *dev,
                                enum meson_gx_mmc_compatible family)
 {
@@ -23,6 +24,7 @@ bool meson_gx_mmc_is_compatible(struct udevice *dev,
 
        return compat == family;
 }
+#endif
 
 static inline void *get_regbase(const struct mmc *mmc)
 {
@@ -67,7 +69,7 @@ static void meson_mmc_config_clock(struct mmc *mmc)
         * Other SoCs use CLK_CO_PHASE_180 by default.
         * It needs to find what is a proper value about each SoCs.
         */
-       if (meson_gx_mmc_is_compatible(mmc->dev, MMC_COMPATIBLE_SM1))
+       if (IS_ENABLED(CONFIG_MESON_SM))
                meson_mmc_clk |= CLK_CO_PHASE_270;
        else
                meson_mmc_clk |= CLK_CO_PHASE_180;
@@ -82,9 +84,14 @@ static void meson_mmc_config_clock(struct mmc *mmc)
        meson_write(mmc, meson_mmc_clk, MESON_SD_EMMC_CLOCK);
 }
 
+#if CONFIG_IS_ENABLED(DM_MMC)
 static int meson_dm_mmc_set_ios(struct udevice *dev)
 {
        struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
+static int meson_legacy_mmc_set_ios(struct mmc *mmc)
+{
+#endif
        uint32_t meson_mmc_cfg;
 
        meson_mmc_config_clock(mmc);
@@ -193,10 +200,16 @@ static void meson_mmc_read_response(struct mmc *mmc, 
struct mmc_cmd *cmd)
        }
 }
 
+#if CONFIG_IS_ENABLED(DM_MMC)
 static int meson_dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
                                 struct mmc_data *data)
 {
        struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
+static int meson_legacy_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+                                    struct mmc_data *data)
+{
+#endif
        struct meson_mmc_plat *pdata = mmc->priv;
        uint32_t status;
        ulong start;
@@ -235,6 +248,59 @@ static int meson_dm_mmc_send_cmd(struct udevice *dev, 
struct mmc_cmd *cmd,
        return ret;
 }
 
+#if !CONFIG_IS_ENABLED(DM_MMC)
+struct meson_mmc_plat mmc_plat[2];
+
+static int meson_legacy_mmc_init(struct mmc *mmc)
+{
+       /* reset all status bits */
+       meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
+
+       /* disable interrupts */
+       meson_write(mmc, 0, MESON_SD_EMMC_IRQ_EN);
+
+       return 0;
+}
+
+static const struct mmc_ops meson_mmc_ops = {
+       .send_cmd       = meson_legacy_mmc_send_cmd,
+       .set_ios        = meson_legacy_mmc_set_ios,
+       .init           = meson_legacy_mmc_init,
+};
+
+struct mmc *meson_mmc_init(int mmc_no)
+{
+       struct meson_mmc_plat *pdata = &mmc_plat[mmc_no];
+       struct mmc_config *cfg = &pdata->cfg;
+
+       cfg->voltages = MMC_VDD_33_34 | MMC_VDD_32_33 |
+                       MMC_VDD_31_32 | MMC_VDD_165_195;
+       cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT;
+       cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
+       cfg->f_max = 6000000; /* 6 MHz */
+       cfg->b_max = 127; /* max 128 - 1 block */
+       cfg->name = "Meson SD/eMMC";
+       cfg->ops = &meson_mmc_ops;
+
+       if (mmc_no == 0) /* MMC1: SD card */
+               pdata->regbase = (void *)0xd0072000;
+       else if (mmc_no == 1) /* MMC2: eMMC */
+               pdata->regbase = (void *)0xd0074000;
+
+#if CONFIG_IS_ENABLED(MMC_PWRSEQ)
+       /* Enable power if needed */
+       ret = mmc_pwrseq_get_power(dev, cfg);
+       if (!ret) {
+               ret = pwrseq_set_power(cfg->pwr_dev, true);
+               if (ret)
+                       return ret;
+       }
+#endif
+
+       return mmc_create(cfg, pdata);
+}
+
+#else
 static const struct dm_mmc_ops meson_dm_mmc_ops = {
        .send_cmd = meson_dm_mmc_send_cmd,
        .set_ios = meson_dm_mmc_set_ios,
@@ -282,6 +348,12 @@ static int meson_mmc_probe(struct udevice *dev)
        cfg->b_max = 511; /* max 512 - 1 blocks */
        cfg->name = dev->name;
 
+       if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+               cfg->host_caps &= ~(MMC_MODE_HS_52MHz | MMC_MODE_HS);
+               cfg->f_max = 6000000; /* 6 MHz */
+               cfg->b_max = 127; /* max 128 - 1 block */
+       }
+
        mmc->priv = pdata;
        upriv->mmc = mmc;
 
@@ -336,3 +408,4 @@ U_BOOT_DRIVER(meson_mmc) = {
        .of_to_plat = meson_mmc_of_to_plat,
        .plat_auto      = sizeof(struct meson_mmc_plat),
 };
+#endif

-- 
2.51.0

Reply via email to