Loading drivers/mmc/host/sdhci-msm.c +46 −0 Original line number Diff line number Diff line Loading @@ -119,6 +119,8 @@ #define CORE_VENDOR_SPEC_ADMA_ERR_ADDR1 0x118 #define CORE_VENDOR_SPEC_FUNC2 0x110 #define HC_SW_RST_WAIT_IDLE_DIS (1 << 20) #define HC_SW_RST_REQ (1 << 21) #define CORE_ONE_MID_EN (1 << 25) #define CORE_VENDOR_SPEC_CAPABILITIES0 0x11C Loading Loading @@ -2967,6 +2969,48 @@ int sdhci_msm_notify_load(struct sdhci_host *host, enum mmc_load state) return 0; } void sdhci_msm_reset_workaround(struct sdhci_host *host, u32 enable) { u32 vendor_func2; unsigned long timeout; vendor_func2 = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2); if (enable) { writel_relaxed(vendor_func2 | HC_SW_RST_REQ, host->ioaddr + CORE_VENDOR_SPEC_FUNC2); timeout = 10000; while (readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2) & HC_SW_RST_REQ) { if (timeout == 0) { pr_info("%s: Applying wait idle disable workaround\n", mmc_hostname(host->mmc)); /* * Apply the reset workaround to not wait for * pending data transfers on AXI before * resetting the controller. This could be * risky if the transfers were stuck on the * AXI bus. */ vendor_func2 = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2); writel_relaxed(vendor_func2 | HC_SW_RST_WAIT_IDLE_DIS, host->ioaddr + CORE_VENDOR_SPEC_FUNC2); host->reset_wa_t = ktime_get(); return; } timeout--; udelay(10); } pr_info("%s: waiting for SW_RST_REQ is successful\n", mmc_hostname(host->mmc)); } else { writel_relaxed(vendor_func2 & ~HC_SW_RST_WAIT_IDLE_DIS, host->ioaddr + CORE_VENDOR_SPEC_FUNC2); } } static struct sdhci_ops sdhci_msm_ops = { .crypto_engine_cfg = sdhci_msm_ice_cfg, .crypto_engine_reset = sdhci_msm_ice_reset, Loading @@ -2988,6 +3032,7 @@ static struct sdhci_ops sdhci_msm_ops = { .enhanced_strobe_mask = sdhci_msm_enhanced_strobe_mask, .detect = sdhci_msm_detect, .notify_load = sdhci_msm_notify_load, .reset_workaround = sdhci_msm_reset_workaround, }; static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host, Loading Loading @@ -3030,6 +3075,7 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host, * on 8992 (minor 0x3e) as a workaround to reset for data stuck issue. */ if (major == 1 && (minor == 0x2e || minor == 0x3e)) { host->quirks2 |= SDHCI_QUIRK2_USE_RESET_WORKAROUND; val = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2); writel_relaxed((val | CORE_ONE_MID_EN), host->ioaddr + CORE_VENDOR_SPEC_FUNC2); Loading Loading
drivers/mmc/host/sdhci-msm.c +46 −0 Original line number Diff line number Diff line Loading @@ -119,6 +119,8 @@ #define CORE_VENDOR_SPEC_ADMA_ERR_ADDR1 0x118 #define CORE_VENDOR_SPEC_FUNC2 0x110 #define HC_SW_RST_WAIT_IDLE_DIS (1 << 20) #define HC_SW_RST_REQ (1 << 21) #define CORE_ONE_MID_EN (1 << 25) #define CORE_VENDOR_SPEC_CAPABILITIES0 0x11C Loading Loading @@ -2967,6 +2969,48 @@ int sdhci_msm_notify_load(struct sdhci_host *host, enum mmc_load state) return 0; } void sdhci_msm_reset_workaround(struct sdhci_host *host, u32 enable) { u32 vendor_func2; unsigned long timeout; vendor_func2 = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2); if (enable) { writel_relaxed(vendor_func2 | HC_SW_RST_REQ, host->ioaddr + CORE_VENDOR_SPEC_FUNC2); timeout = 10000; while (readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2) & HC_SW_RST_REQ) { if (timeout == 0) { pr_info("%s: Applying wait idle disable workaround\n", mmc_hostname(host->mmc)); /* * Apply the reset workaround to not wait for * pending data transfers on AXI before * resetting the controller. This could be * risky if the transfers were stuck on the * AXI bus. */ vendor_func2 = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2); writel_relaxed(vendor_func2 | HC_SW_RST_WAIT_IDLE_DIS, host->ioaddr + CORE_VENDOR_SPEC_FUNC2); host->reset_wa_t = ktime_get(); return; } timeout--; udelay(10); } pr_info("%s: waiting for SW_RST_REQ is successful\n", mmc_hostname(host->mmc)); } else { writel_relaxed(vendor_func2 & ~HC_SW_RST_WAIT_IDLE_DIS, host->ioaddr + CORE_VENDOR_SPEC_FUNC2); } } static struct sdhci_ops sdhci_msm_ops = { .crypto_engine_cfg = sdhci_msm_ice_cfg, .crypto_engine_reset = sdhci_msm_ice_reset, Loading @@ -2988,6 +3032,7 @@ static struct sdhci_ops sdhci_msm_ops = { .enhanced_strobe_mask = sdhci_msm_enhanced_strobe_mask, .detect = sdhci_msm_detect, .notify_load = sdhci_msm_notify_load, .reset_workaround = sdhci_msm_reset_workaround, }; static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host, Loading Loading @@ -3030,6 +3075,7 @@ static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host, * on 8992 (minor 0x3e) as a workaround to reset for data stuck issue. */ if (major == 1 && (minor == 0x2e || minor == 0x3e)) { host->quirks2 |= SDHCI_QUIRK2_USE_RESET_WORKAROUND; val = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC_FUNC2); writel_relaxed((val | CORE_ONE_MID_EN), host->ioaddr + CORE_VENDOR_SPEC_FUNC2); Loading