diff options
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/host/mtk-sd.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-msm.c | 28 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-of-esdhc.c | 17 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pci-core.c | 10 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 11 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.h | 2 | 
6 files changed, 50 insertions, 20 deletions
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 189e42674d85..010fe29a4888 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -228,6 +228,7 @@  #define MSDC_PATCH_BIT_SPCPUSH    (0x1 << 29)	/* 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_BIT2_CFGRESP   (0x1 << 15)   /* RW */ @@ -1881,6 +1882,7 @@ static int hs400_tune_response(struct mmc_host *mmc, u32 opcode)  	/* select EMMC50 PAD CMD tune */  	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 ||  	    mmc->ios.timing == MMC_TIMING_UHS_SDR104) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index b75c82d8d6c1..3d0bb5e2e09b 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -99,7 +99,7 @@  #define CORE_PWRSAVE_DLL	BIT(3) -#define DDR_CONFIG_POR_VAL	0x80040853 +#define DDR_CONFIG_POR_VAL	0x80040873  #define INVALID_TUNING_PHASE	-1 @@ -148,8 +148,9 @@ struct sdhci_msm_offset {  	u32 core_ddr_200_cfg;  	u32 core_vendor_spec3;  	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_2;  };  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_vendor_spec3 = 0x250,  	.core_dll_config_2 = 0x254, -	.core_ddr_config = 0x258, -	.core_ddr_config_2 = 0x25c, +	.core_dll_config_3 = 0x258, +	.core_ddr_config = 0x25c,  };  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_vendor_spec3 = 0x1b0,  	.core_dll_config_2 = 0x1b4, -	.core_ddr_config = 0x1b8, -	.core_ddr_config_2 = 0x1bc, +	.core_ddr_config_old = 0x1b8, +	.core_ddr_config = 0x1bc,  };  struct sdhci_msm_variant_ops { @@ -253,6 +254,7 @@ struct sdhci_msm_host {  	const struct sdhci_msm_offset *offset;  	bool use_cdr;  	u32 transfer_mode; +	bool updated_ddr_cfg;  };  static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host) @@ -924,8 +926,10 @@ out:  static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)  {  	struct mmc_host *mmc = host->mmc; -	u32 dll_status, config; +	u32 dll_status, config, ddr_cfg_offset;  	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 =  					sdhci_priv_msm_offset(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  	 * values will need to be programmed appropriately.  	 */ -	writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + -			msm_offset->core_ddr_config); +	if (msm_host->updated_ddr_cfg) +		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) {  		config = readl_relaxed(host->ioaddr + @@ -1899,6 +1906,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)  				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  	 * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 5cca3fa4610b..500f70a6ee42 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -80,6 +80,7 @@ struct sdhci_esdhc {  	bool quirk_tuning_erratum_type1;  	bool quirk_tuning_erratum_type2;  	bool quirk_ignore_data_inhibit; +	bool quirk_delay_before_data_reset;  	bool in_sw_tuning;  	unsigned int peripheral_clock;  	const struct esdhc_clk_fixup *clk_fixup; @@ -759,14 +760,16 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)  	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);  	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_writel(host, host->ier, SDHCI_INT_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) {  		val = sdhci_readl(host, ESDHC_TBCTL);  		val &= ~ESDHC_TB_EN; @@ -1221,6 +1224,10 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)  	if (match)  		esdhc->clk_fixup = match->data;  	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);  	if (!IS_ERR(clk)) {  		/* @@ -1303,8 +1310,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)  		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;  	if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { -		host->quirks2 |= SDHCI_QUIRK_RESET_AFTER_REQUEST; -		host->quirks2 |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; +		host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; +		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;  	}  	if (of_device_is_compatible(np, "fsl,p5040-esdhc") || diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index acefb76b4e15..5091e2c1c0e5 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -27,6 +27,7 @@  #include <linux/mmc/slot-gpio.h>  #include <linux/mmc/sdhci-pci-data.h>  #include <linux/acpi.h> +#include <linux/dmi.h>  #ifdef CONFIG_X86  #include <asm/iosf_mbi.h> @@ -783,11 +784,18 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)  	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)  {  	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) {  		slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES, diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3140fe2e5dba..1b1c26da3fe0 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1882,9 +1882,7 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)  		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;  	else if (timing == MMC_TIMING_UHS_SDR12)  		ctrl_2 |= SDHCI_CTRL_UHS_SDR12; -	else if (timing == MMC_TIMING_SD_HS || -		 timing == MMC_TIMING_MMC_HS || -		 timing == MMC_TIMING_UHS_SDR25) +	else if (timing == MMC_TIMING_UHS_SDR25)  		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;  	else if (timing == MMC_TIMING_UHS_SDR50)  		ctrl_2 |= SDHCI_CTRL_UHS_SDR50; @@ -2419,8 +2417,8 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)  		sdhci_send_tuning(host, opcode);  		if (!host->tuning_done) { -			pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n", -				mmc_hostname(host->mmc)); +			pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n", +				 mmc_hostname(host->mmc));  			sdhci_abort_tuning(host, opcode);  			return -ETIMEDOUT;  		} @@ -3769,6 +3767,9 @@ int sdhci_setup_host(struct sdhci_host *host)  		       mmc_hostname(mmc), host->version);  	} +	if (host->quirks & SDHCI_QUIRK_BROKEN_CQE) +		mmc->caps2 &= ~MMC_CAP2_CQE; +  	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)  		host->flags |= SDHCI_USE_SDMA;  	else if (!(host->caps & SDHCI_CAN_DO_SDMA)) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0ed3e0eaef5f..fe83ece6965b 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -409,6 +409,8 @@ struct sdhci_host {  #define SDHCI_QUIRK_BROKEN_CARD_DETECTION		(1<<15)  /* Controller reports inverted write-protect state */  #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 */  #define SDHCI_QUIRK_PIO_NEEDS_DELAY			(1<<18)  /* Controller does not have a LED */  | 
