Commit d2944d53 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC host fixes from Ulf Hansson:

 - mtk-sd: Fix tuning for MT8173 HS200/HS400 mode

 - sdhci: Revert a fix for incorrect switch to HS mode

 - sdhci-msm: Fixup accesses to the DDR_CONFIG register

 - sdhci-of-esdhc: Revert a bad fix for erratum A-009204

 - sdhci-of-esdhc: Re-implement fix for erratum A-009204

 - sdhci-of-esdhc: Fixup P2020 errata handling

 - sdhci-pci: Disable broken CMDQ on Intel GLK based Lenovo systems

* tag 'mmc-v5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: sdhci-of-esdhc: re-implement erratum A-009204 workaround
  mmc: sdhci: Add a quirk for broken command queuing
  mmc: sdhci: Workaround broken command queuing on Intel GLK
  mmc: sdhci-of-esdhc: fix P2020 errata handling
  mmc: sdhci: Update the tuning failed messages to pr_debug level
  mmc: sdhci-of-esdhc: Revert "mmc: sdhci-of-esdhc: add erratum A-009204 support"
  mmc: mediatek: fix CMD_TA to 2 for MT8173 HS200/HS400 mode
  mmc: sdhci-msm: Correct the offset and value for DDR_CONFIG register
  Revert "mmc: sdhci: Fix incorrect switch to HS mode"
parents 6398b9fc f667216c
...@@ -228,6 +228,7 @@ ...@@ -228,6 +228,7 @@
#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */ #define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */
#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ #define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */
#define MSDC_PATCH_BIT1_CMDTA (0x7 << 3) /* RW */
#define MSDC_PATCH_BIT1_STOP_DLY (0xf << 8) /* RW */ #define MSDC_PATCH_BIT1_STOP_DLY (0xf << 8) /* RW */
#define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */ #define MSDC_PATCH_BIT2_CFGRESP (0x1 << 15) /* RW */
...@@ -1881,6 +1882,7 @@ static int hs400_tune_response(struct mmc_host *mmc, u32 opcode) ...@@ -1881,6 +1882,7 @@ static int hs400_tune_response(struct mmc_host *mmc, u32 opcode)
/* select EMMC50 PAD CMD tune */ /* select EMMC50 PAD CMD tune */
sdr_set_bits(host->base + PAD_CMD_TUNE, BIT(0)); sdr_set_bits(host->base + PAD_CMD_TUNE, BIT(0));
sdr_set_field(host->base + MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMDTA, 2);
if (mmc->ios.timing == MMC_TIMING_MMC_HS200 || if (mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
mmc->ios.timing == MMC_TIMING_UHS_SDR104) mmc->ios.timing == MMC_TIMING_UHS_SDR104)
......
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
#define CORE_PWRSAVE_DLL BIT(3) #define CORE_PWRSAVE_DLL BIT(3)
#define DDR_CONFIG_POR_VAL 0x80040853 #define DDR_CONFIG_POR_VAL 0x80040873
#define INVALID_TUNING_PHASE -1 #define INVALID_TUNING_PHASE -1
...@@ -148,8 +148,9 @@ struct sdhci_msm_offset { ...@@ -148,8 +148,9 @@ struct sdhci_msm_offset {
u32 core_ddr_200_cfg; u32 core_ddr_200_cfg;
u32 core_vendor_spec3; u32 core_vendor_spec3;
u32 core_dll_config_2; u32 core_dll_config_2;
u32 core_dll_config_3;
u32 core_ddr_config_old; /* Applicable to sdcc minor ver < 0x49 */
u32 core_ddr_config; u32 core_ddr_config;
u32 core_ddr_config_2;
}; };
static const struct sdhci_msm_offset sdhci_msm_v5_offset = { static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
...@@ -177,8 +178,8 @@ static const struct sdhci_msm_offset sdhci_msm_v5_offset = { ...@@ -177,8 +178,8 @@ static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
.core_ddr_200_cfg = 0x224, .core_ddr_200_cfg = 0x224,
.core_vendor_spec3 = 0x250, .core_vendor_spec3 = 0x250,
.core_dll_config_2 = 0x254, .core_dll_config_2 = 0x254,
.core_ddr_config = 0x258, .core_dll_config_3 = 0x258,
.core_ddr_config_2 = 0x25c, .core_ddr_config = 0x25c,
}; };
static const struct sdhci_msm_offset sdhci_msm_mci_offset = { static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
...@@ -207,8 +208,8 @@ static const struct sdhci_msm_offset sdhci_msm_mci_offset = { ...@@ -207,8 +208,8 @@ static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
.core_ddr_200_cfg = 0x184, .core_ddr_200_cfg = 0x184,
.core_vendor_spec3 = 0x1b0, .core_vendor_spec3 = 0x1b0,
.core_dll_config_2 = 0x1b4, .core_dll_config_2 = 0x1b4,
.core_ddr_config = 0x1b8, .core_ddr_config_old = 0x1b8,
.core_ddr_config_2 = 0x1bc, .core_ddr_config = 0x1bc,
}; };
struct sdhci_msm_variant_ops { struct sdhci_msm_variant_ops {
...@@ -253,6 +254,7 @@ struct sdhci_msm_host { ...@@ -253,6 +254,7 @@ struct sdhci_msm_host {
const struct sdhci_msm_offset *offset; const struct sdhci_msm_offset *offset;
bool use_cdr; bool use_cdr;
u32 transfer_mode; u32 transfer_mode;
bool updated_ddr_cfg;
}; };
static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host) static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
...@@ -924,8 +926,10 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host) ...@@ -924,8 +926,10 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
{ {
struct mmc_host *mmc = host->mmc; struct mmc_host *mmc = host->mmc;
u32 dll_status, config; u32 dll_status, config, ddr_cfg_offset;
int ret; int ret;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
const struct sdhci_msm_offset *msm_offset = const struct sdhci_msm_offset *msm_offset =
sdhci_priv_msm_offset(host); sdhci_priv_msm_offset(host);
...@@ -938,8 +942,11 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) ...@@ -938,8 +942,11 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
* bootloaders. In the future, if this changes, then the desired * bootloaders. In the future, if this changes, then the desired
* values will need to be programmed appropriately. * values will need to be programmed appropriately.
*/ */
writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + if (msm_host->updated_ddr_cfg)
msm_offset->core_ddr_config); ddr_cfg_offset = msm_offset->core_ddr_config;
else
ddr_cfg_offset = msm_offset->core_ddr_config_old;
writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + ddr_cfg_offset);
if (mmc->ios.enhanced_strobe) { if (mmc->ios.enhanced_strobe) {
config = readl_relaxed(host->ioaddr + config = readl_relaxed(host->ioaddr +
...@@ -1899,6 +1906,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) ...@@ -1899,6 +1906,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
msm_offset->core_vendor_spec_capabilities0); msm_offset->core_vendor_spec_capabilities0);
} }
if (core_major == 1 && core_minor >= 0x49)
msm_host->updated_ddr_cfg = true;
/* /*
* Power on reset state may trigger power irq if previous status of * Power on reset state may trigger power irq if previous status of
* PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq
......
...@@ -80,6 +80,7 @@ struct sdhci_esdhc { ...@@ -80,6 +80,7 @@ struct sdhci_esdhc {
bool quirk_tuning_erratum_type1; bool quirk_tuning_erratum_type1;
bool quirk_tuning_erratum_type2; bool quirk_tuning_erratum_type2;
bool quirk_ignore_data_inhibit; bool quirk_ignore_data_inhibit;
bool quirk_delay_before_data_reset;
bool in_sw_tuning; bool in_sw_tuning;
unsigned int peripheral_clock; unsigned int peripheral_clock;
const struct esdhc_clk_fixup *clk_fixup; const struct esdhc_clk_fixup *clk_fixup;
...@@ -759,14 +760,16 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask) ...@@ -759,14 +760,16 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
u32 val; u32 val;
if (esdhc->quirk_delay_before_data_reset &&
(mask & SDHCI_RESET_DATA) &&
(host->flags & SDHCI_REQ_USE_DMA))
mdelay(5);
sdhci_reset(host, mask); sdhci_reset(host, mask);
sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"))
mdelay(5);
if (mask & SDHCI_RESET_ALL) { if (mask & SDHCI_RESET_ALL) {
val = sdhci_readl(host, ESDHC_TBCTL); val = sdhci_readl(host, ESDHC_TBCTL);
val &= ~ESDHC_TB_EN; val &= ~ESDHC_TB_EN;
...@@ -1221,6 +1224,10 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) ...@@ -1221,6 +1224,10 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
if (match) if (match)
esdhc->clk_fixup = match->data; esdhc->clk_fixup = match->data;
np = pdev->dev.of_node; np = pdev->dev.of_node;
if (of_device_is_compatible(np, "fsl,p2020-esdhc"))
esdhc->quirk_delay_before_data_reset = true;
clk = of_clk_get(np, 0); clk = of_clk_get(np, 0);
if (!IS_ERR(clk)) { if (!IS_ERR(clk)) {
/* /*
...@@ -1303,8 +1310,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) ...@@ -1303,8 +1310,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) {
host->quirks2 |= SDHCI_QUIRK_RESET_AFTER_REQUEST; host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
host->quirks2 |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
} }
if (of_device_is_compatible(np, "fsl,p5040-esdhc") || if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/mmc/slot-gpio.h> #include <linux/mmc/slot-gpio.h>
#include <linux/mmc/sdhci-pci-data.h> #include <linux/mmc/sdhci-pci-data.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dmi.h>
#ifdef CONFIG_X86 #ifdef CONFIG_X86
#include <asm/iosf_mbi.h> #include <asm/iosf_mbi.h>
...@@ -783,11 +784,18 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) ...@@ -783,11 +784,18 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
return 0; return 0;
} }
static bool glk_broken_cqhci(struct sdhci_pci_slot *slot)
{
return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC &&
dmi_match(DMI_BIOS_VENDOR, "LENOVO");
}
static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot) static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
{ {
int ret = byt_emmc_probe_slot(slot); int ret = byt_emmc_probe_slot(slot);
slot->host->mmc->caps2 |= MMC_CAP2_CQE; if (!glk_broken_cqhci(slot))
slot->host->mmc->caps2 |= MMC_CAP2_CQE;
if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) { if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES, slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES,
......
...@@ -1882,9 +1882,7 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) ...@@ -1882,9 +1882,7 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
ctrl_2 |= SDHCI_CTRL_UHS_SDR104; ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
else if (timing == MMC_TIMING_UHS_SDR12) else if (timing == MMC_TIMING_UHS_SDR12)
ctrl_2 |= SDHCI_CTRL_UHS_SDR12; ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
else if (timing == MMC_TIMING_SD_HS || else if (timing == MMC_TIMING_UHS_SDR25)
timing == MMC_TIMING_MMC_HS ||
timing == MMC_TIMING_UHS_SDR25)
ctrl_2 |= SDHCI_CTRL_UHS_SDR25; ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
else if (timing == MMC_TIMING_UHS_SDR50) else if (timing == MMC_TIMING_UHS_SDR50)
ctrl_2 |= SDHCI_CTRL_UHS_SDR50; ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
...@@ -2419,8 +2417,8 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) ...@@ -2419,8 +2417,8 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
sdhci_send_tuning(host, opcode); sdhci_send_tuning(host, opcode);
if (!host->tuning_done) { if (!host->tuning_done) {
pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n", pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n",
mmc_hostname(host->mmc)); mmc_hostname(host->mmc));
sdhci_abort_tuning(host, opcode); sdhci_abort_tuning(host, opcode);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -3769,6 +3767,9 @@ int sdhci_setup_host(struct sdhci_host *host) ...@@ -3769,6 +3767,9 @@ int sdhci_setup_host(struct sdhci_host *host)
mmc_hostname(mmc), host->version); mmc_hostname(mmc), host->version);
} }
if (host->quirks & SDHCI_QUIRK_BROKEN_CQE)
mmc->caps2 &= ~MMC_CAP2_CQE;
if (host->quirks & SDHCI_QUIRK_FORCE_DMA) if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
host->flags |= SDHCI_USE_SDMA; host->flags |= SDHCI_USE_SDMA;
else if (!(host->caps & SDHCI_CAN_DO_SDMA)) else if (!(host->caps & SDHCI_CAN_DO_SDMA))
......
...@@ -409,6 +409,8 @@ struct sdhci_host { ...@@ -409,6 +409,8 @@ struct sdhci_host {
#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15) #define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15)
/* Controller reports inverted write-protect state */ /* Controller reports inverted write-protect state */
#define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16)
/* Controller has unusable command queue engine */
#define SDHCI_QUIRK_BROKEN_CQE (1<<17)
/* Controller does not like fast PIO transfers */ /* Controller does not like fast PIO transfers */
#define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18)
/* Controller does not have a LED */ /* Controller does not have a LED */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment