summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Wilczynski <m.wilczynski@samsung.com>2024-08-22 10:08:09 +0200
committerMichal Wilczynski <m.wilczynski@samsung.com>2024-08-22 13:53:51 +0200
commit66c6ad44bcf4d14082f55932b37772990d842b7d (patch)
treecaf165eda13daa3ca60e1b72ed7cf7aa379a4393
parent537fabbf2a196e262b45638f1e3d69b3d5f89c27 (diff)
downloadlinux-riscv-66c6ad44bcf4d14082f55932b37772990d842b7d.tar.gz
linux-riscv-66c6ad44bcf4d14082f55932b37772990d842b7d.tar.bz2
linux-riscv-66c6ad44bcf4d14082f55932b37772990d842b7d.zip
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 <m.wilczynski@samsung.com>
-rw-r--r--drivers/mmc/core/core.c23
-rw-r--r--drivers/mmc/core/mmc.c14
-rw-r--r--drivers/mmc/core/sd.c35
-rw-r--r--drivers/mmc/host/sdhci.c13
-rw-r--r--drivers/mmc/host/sdhci.h17
5 files changed, 102 insertions, 0 deletions
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