]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mmc: dw_mmc: add exynos7870 DW MMC support
authorKaustabh Chakraborty <kauschluss@disroot.org>
Tue, 18 Feb 2025 18:47:49 +0000 (00:17 +0530)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 11 Mar 2025 17:41:53 +0000 (18:41 +0100)
Add support for Exynos7870 DW MMC controllers, for both SMU and non-SMU
variants. These controllers require a quirk to access 64-bit FIFO in 32-bit
accesses (DW_MMC_QUIRK_FIFO64_32).

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-3-b4255a3e39ed@disroot.org
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/dw_mmc-exynos.c

index 53d32d0f2709e0780ec5f31a3b412f33aaa6baa4..e3548408ca392c6b7afbfb05a439435073ab7657 100644 (file)
@@ -27,6 +27,8 @@ enum dw_mci_exynos_type {
        DW_MCI_TYPE_EXYNOS5420_SMU,
        DW_MCI_TYPE_EXYNOS7,
        DW_MCI_TYPE_EXYNOS7_SMU,
+       DW_MCI_TYPE_EXYNOS7870,
+       DW_MCI_TYPE_EXYNOS7870_SMU,
        DW_MCI_TYPE_ARTPEC8,
 };
 
@@ -69,6 +71,12 @@ static struct dw_mci_exynos_compatible {
        }, {
                .compatible     = "samsung,exynos7-dw-mshc-smu",
                .ctrl_type      = DW_MCI_TYPE_EXYNOS7_SMU,
+       }, {
+               .compatible     = "samsung,exynos7870-dw-mshc",
+               .ctrl_type      = DW_MCI_TYPE_EXYNOS7870,
+       }, {
+               .compatible     = "samsung,exynos7870-dw-mshc-smu",
+               .ctrl_type      = DW_MCI_TYPE_EXYNOS7870_SMU,
        }, {
                .compatible     = "axis,artpec8-dw-mshc",
                .ctrl_type      = DW_MCI_TYPE_ARTPEC8,
@@ -85,6 +93,8 @@ static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host)
                return EXYNOS4210_FIXED_CIU_CLK_DIV;
        else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                        priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                        priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1;
        else
@@ -100,7 +110,8 @@ static void dw_mci_exynos_config_smu(struct dw_mci *host)
         * set for non-ecryption mode at this time.
         */
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU ||
-               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) {
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) {
                mci_writel(host, MPSBEGIN0, 0);
                mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX);
                mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT |
@@ -126,6 +137,12 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host)
                                DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl);
        }
 
+       if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) {
+               /* Quirk needed for certain Exynos SoCs */
+               host->quirks |= DW_MMC_QUIRK_FIFO64_32;
+       }
+
        if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) {
                /* Quirk needed for the ARTPEC-8 SoC */
                host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT;
@@ -143,6 +160,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
 
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                clksel = mci_readl(host, CLKSEL64);
        else
@@ -152,6 +171,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing)
 
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                mci_writel(host, CLKSEL64, clksel);
        else
@@ -222,6 +243,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev)
 
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                clksel = mci_readl(host, CLKSEL64);
        else
@@ -230,6 +253,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev)
        if (clksel & SDMMC_CLKSEL_WAKEUP_INT) {
                if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                        priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+                       priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                        priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                        mci_writel(host, CLKSEL64, clksel);
                else
@@ -409,6 +434,8 @@ static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host)
 
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL64));
        else
@@ -422,6 +449,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
 
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                clksel = mci_readl(host, CLKSEL64);
        else
@@ -429,6 +458,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
        clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample);
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                mci_writel(host, CLKSEL64, clksel);
        else
@@ -443,6 +474,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
 
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                clksel = mci_readl(host, CLKSEL64);
        else
@@ -453,6 +486,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
 
        if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 ||
                priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 ||
+               priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU ||
                priv->ctrl_type == DW_MCI_TYPE_ARTPEC8)
                mci_writel(host, CLKSEL64, clksel);
        else
@@ -632,6 +667,10 @@ static const struct of_device_id dw_mci_exynos_match[] = {
                        .data = &exynos_drv_data, },
        { .compatible = "samsung,exynos7-dw-mshc-smu",
                        .data = &exynos_drv_data, },
+       { .compatible = "samsung,exynos7870-dw-mshc",
+                       .data = &exynos_drv_data, },
+       { .compatible = "samsung,exynos7870-dw-mshc-smu",
+                       .data = &exynos_drv_data, },
        { .compatible = "axis,artpec8-dw-mshc",
                        .data = &artpec_drv_data, },
        {},