From 66c6ad44bcf4d14082f55932b37772990d842b7d Mon Sep 17 00:00:00 2001 From: Michal Wilczynski Date: Thu, 22 Aug 2024 10:08:09 +0200 Subject: mmc: Add vendor hacks to core mmc files It seems that the mmc devices don't work correctly without some changes to mmc core code. Port the hacks from the vendor kernel [1]. [1] - https://github.com/BPI-SINOVOIP/pi-linux.git Change-Id: Id4ef2af64f2706d0f195e825be19574c40b23cf4 Signed-off-by: Michal Wilczynski --- drivers/mmc/core/core.c | 23 +++++++++++++++++++++++ drivers/mmc/core/mmc.c | 14 ++++++++++++++ drivers/mmc/core/sd.c | 35 +++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci.c | 13 +++++++++++++ drivers/mmc/host/sdhci.h | 17 +++++++++++++++++ 5 files changed, 102 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index a8c17b4cd737..c4e12377074b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1421,6 +1421,13 @@ void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq) __pm_wakeup_event(host->ws, 5000); host->detect_change = 1; +#ifdef CONFIG_ARCH_SPACEMIT_K1X + if (!(host->caps2 & MMC_CAP2_NO_MMC)) { + mmc_rescan(&host->detect.work); + return; + } +#endif + mmc_schedule_delayed_work(&host->detect, delay); } @@ -2084,6 +2091,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) return 0; } +#ifdef CONFIG_ARCH_SPACEMIT_K1X + if (host->ops->encrypt_config) + host->ops->encrypt_config(host, 0); +#endif + + /* Order's important: probe SDIO, then SD, then MMC */ if (!(host->caps2 & MMC_CAP2_NO_SDIO)) if (!mmc_attach_sdio(host)) @@ -2097,6 +2110,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) if (!mmc_attach_mmc(host)) return 0; +#ifdef CONFIG_ARCH_SPACEMIT_K1X + if (host->ops->encrypt_config) + host->ops->encrypt_config(host, 1); +#endif + + out: mmc_power_off(host); return -EIO; @@ -2291,6 +2310,10 @@ void mmc_start_host(struct mmc_host *host) } mmc_gpiod_request_cd_irq(host); +#ifdef CONFIG_ARCH_SPACEMIT_K1X + if (host->caps2 & MMC_CAP2_DISABLE_PROBE_SCAN) + return; +#endif _mmc_detect_change(host, 0, false); } diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 7e39017e440f..0a892267b680 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -2160,14 +2160,28 @@ static int mmc_suspend(struct mmc_host *host) static int _mmc_resume(struct mmc_host *host) { int err = 0; +#ifdef CONFIG_ARCH_SPACEMIT_K1X + int retry = 3; +#endif mmc_claim_host(host); if (!mmc_card_suspended(host->card)) goto out; +#ifdef CONFIG_ARCH_SPACEMIT_K1X +retry_resume: +#endif mmc_power_up(host, host->card->ocr); err = mmc_init_card(host, host->card->ocr, host->card); +#ifdef CONFIG_ARCH_SPACEMIT_K1X + if (err && retry--) { + pr_err("%s: try to retry resume, err:%d\n", + mmc_hostname(host), err); + mmc_power_off(host); + goto retry_resume; + } +#endif mmc_card_clr_suspended(host->card); out: diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c3e554344c99..e25ed03513c1 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1409,6 +1409,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, u32 rocr = 0; bool v18_fixup_failed = false; +#ifdef CONFIG_ARCH_SPACEMIT_K1X + u8 tuning_fail = 0; +#endif + + WARN_ON(!host->claimed); retry: err = mmc_sd_get_cid(host, ocr, cid, &rocr); @@ -1498,9 +1503,23 @@ retry: goto cont; } +#ifdef CONFIG_ARCH_SPACEMIT_K1X + if (tuning_fail) + card->sw_caps.sd3_bus_mode &= ~SD_MODE_UHS_SDR104; +#endif + /* Initialization sequence for UHS-I cards */ if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { err = mmc_sd_init_uhs_card(card); +#ifdef CONFIG_ARCH_SPACEMIT_K1X + if (err && err == -EIO) { + mmc_power_off(host); + mmc_power_up(host, host->ocr_avail); + tuning_fail = 1; + goto retry; + } +#endif + if (err) goto free_card; } else { @@ -1803,8 +1822,24 @@ static int mmc_sd_runtime_resume(struct mmc_host *host) static int mmc_sd_hw_reset(struct mmc_host *host) { +#ifdef CONFIG_ARCH_SPACEMIT_K1X + int ret; + int sdr104; +#endif + mmc_power_cycle(host, host->card->ocr); +#ifdef CONFIG_ARCH_SPACEMIT_K1X + /* if all selected delaycode have crc, reset to DDR50 */ + sdr104 = host->caps & MMC_CAP_UHS_SDR104; + if (sdr104) + host->caps &= ~MMC_CAP_UHS_SDR104; + ret = mmc_sd_init_card(host, host->card->ocr, host->card); + if (sdr104) + host->caps |= MMC_CAP_UHS_SDR104; + return ret; +#else return mmc_sd_init_card(host, host->card->ocr, host->card); +#endif } static const struct mmc_bus_ops mmc_sd_ops = { diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ff41aa56564e..cc6602c17e2d 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2712,6 +2712,16 @@ static int sdhci_card_busy(struct mmc_host *mmc) return !(present_state & SDHCI_DATA_0_LVL_MASK); } +#ifdef CONFIG_ARCH_SPACEMIT_K1X +static void sdhci_encrypt_config(struct mmc_host *mmc, unsigned int enc_flag) +{ + struct sdhci_host *host = mmc_priv(mmc); + + if (host->ops->set_encrypt_feature) + host->ops->set_encrypt_feature(host, enc_flag); +} +#endif + static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) { struct sdhci_host *host = mmc_priv(mmc); @@ -3062,6 +3072,9 @@ static const struct mmc_host_ops sdhci_ops = { .execute_tuning = sdhci_execute_tuning, .card_event = sdhci_card_event, .card_busy = sdhci_card_busy, +#ifdef CONFIG_ARCH_SPACEMIT_K1X + .encrypt_config = sdhci_encrypt_config, +#endif }; /*****************************************************************************\ diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index f219bdea8f28..ec648fc1fe04 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -486,6 +486,20 @@ struct sdhci_host { /* Issue CMD and DATA reset together */ #define SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER (1<<19) + +#ifdef CONFIG_ARCH_SPACEMIT_K1X +/* Support SDH controller on FPGA */ +#define SDHCI_QUIRK2_SUPPORT_PHY_BYPASS (1<<25) +/* Disable scan card at probe phase */ +#define SDHCI_QUIRK2_DISABLE_PROBE_CDSCAN (1<<26) +/* Need to set IO capability by SOC part register */ +#define SDHCI_QUIRK2_SET_AIB_MMC (1<<27) +/* Controller not support phy module */ +#define SDHCI_QUIRK2_BROKEN_PHY_MODULE (1<<28) +/* Controller support encrypt module */ +#define SDHCI_QUIRK2_SUPPORT_ENCRYPT (1<<29) +#endif + int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ phys_addr_t mapbase; /* physical address base */ @@ -668,6 +682,9 @@ struct sdhci_ops { void (*request_done)(struct sdhci_host *host, struct mmc_request *mrq); void (*dump_vendor_regs)(struct sdhci_host *host); +#ifdef CONFIG_ARCH_SPACEMIT_K1X + void (*set_encrypt_feature)(struct sdhci_host *host, unsigned int enc_flag); +#endif }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS -- cgit v1.2.3