From 0564e11a463c57fda69b979ceb75eae2346a8e3c Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Sat, 17 Feb 2024 22:42:02 +0800 Subject: [PATCH] mmc: sdhci-of-dwcmshc: Add support for Sophgo CV1800B and SG2002 Add support for the mmc controller in the Sophgo CV1800B and SG2002 with corresponding new compatible strings. Implement custom sdhci_ops. Signed-off-by: Jisheng Zhang --- drivers/mmc/host/sdhci-of-dwcmshc.c | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 3a3bae6948a899..1086b213b885ec 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -36,6 +36,20 @@ #define DWCMSHC_ENHANCED_STROBE BIT(8) #define DWCMSHC_EMMC_ATCTRL 0x40 +/* Sophgo CV18XX specific Registers */ +#define CV18XX_SDHCI_MSHC_CTRL 0x00 +#define CV18XX_EMMC_FUNC_EN BIT(0) +#define CV18XX_LATANCY_1T BIT(1) +#define CV18XX_SDHCI_PHY_TX_RX_DLY 0x40 +#define CV18XX_PHY_TX_DLY_MSK GENMASK(6, 0) +#define CV18XX_PHY_TX_SRC_MSK GENMASK(9, 8) +#define CV18XX_PHY_TX_SRC_INVERT_CLK_TX 0x1 +#define CV18XX_PHY_RX_DLY_MSK GENMASK(22, 16) +#define CV18XX_PHY_RX_SRC_MSK GENMASK(25, 24) +#define CV18XX_PHY_RX_SRC_INVERT_RX_CLK 0x1 +#define CV18XX_SDHCI_PHY_CONFIG 0x4c +#define CV18XX_PHY_TX_BPS BIT(0) + /* Rockchip specific Registers */ #define DWCMSHC_EMMC_DLL_CTRL 0x800 #define DWCMSHC_EMMC_DLL_RXCLK 0x804 @@ -338,6 +352,35 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask) sdhci_reset(host, mask); } +static void cv18xx_sdhci_reset(struct sdhci_host *host, u8 mask) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + u32 val, emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO; + + sdhci_reset(host, mask); + + if ((host->mmc->caps2 & emmc_caps) == emmc_caps) { + val = sdhci_readl(host, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL); + val |= CV18XX_EMMC_FUNC_EN; + sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL); + } + + val = sdhci_readl(host, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL); + val |= CV18XX_LATANCY_1T; + sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL); + + val = sdhci_readl(host, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_CONFIG); + val |= CV18XX_PHY_TX_BPS; + sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_CONFIG); + + val = (FIELD_PREP(CV18XX_PHY_TX_DLY_MSK, 0) | + FIELD_PREP(CV18XX_PHY_TX_SRC_MSK, CV18XX_PHY_TX_SRC_INVERT_CLK_TX) | + FIELD_PREP(CV18XX_PHY_RX_DLY_MSK, 0) | + FIELD_PREP(CV18XX_PHY_RX_SRC_MSK, CV18XX_PHY_RX_SRC_INVERT_RX_CLK)); + sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_TX_RX_DLY); +} + static const struct sdhci_ops sdhci_dwcmshc_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, @@ -356,6 +399,15 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = { .adma_write_desc = dwcmshc_adma_write_desc, }; +static const struct sdhci_ops sdhci_dwcmshc_cv18xx_ops = { + .set_clock = sdhci_set_clock, + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = dwcmshc_set_uhs_signaling, + .get_max_clock = dwcmshc_get_max_clock, + .reset = cv18xx_sdhci_reset, + .adma_write_desc = dwcmshc_adma_write_desc, +}; + static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { .ops = &sdhci_dwcmshc_ops, .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, @@ -379,6 +431,12 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = { SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, }; +static const struct sdhci_pltfm_data sdhci_dwcmshc_cv18xx_pdata = { + .ops = &sdhci_dwcmshc_cv18xx_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, +}; + static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) { int err; @@ -447,6 +505,14 @@ static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { .compatible = "snps,dwcmshc-sdhci", .data = &sdhci_dwcmshc_pdata, }, + { + .compatible = "sophgo,cv1800b-dwcmshc", + .data = &sdhci_dwcmshc_cv18xx_pdata, + }, + { + .compatible = "sophgo,sg2002-dwcmshc", + .data = &sdhci_dwcmshc_cv18xx_pdata, + }, {}, }; MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);