MMC core:
- Fix ambiguous TRIM and DISCARD args - Fix removal of debugfs file for mmc_test MMC host: - mtk-sd: Add missing clk_disable_unprepare() in an error path - sdhci: Fix I/O voltage switch delay for UHS-I SD cards - sdhci-esdhc-imx: Fix CQHCI exit halt state check - sdhci-sprd: Fix voltage switch -----BEGIN PGP SIGNATURE----- iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAmOJt2wXHHVsZi5oYW5z c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjCnIfhAAzDpsdF1zBYQDHelN6DsqMX4c vHmBO8P9DE9xfhmdt3bnCa+26WIzmXGJ/8/jZLkV9ZGYLeAjkj6sYPQ2Zgvndecd f+9l4sGBiL1b26ON2wQqnrsZcEedtDh3xYdAtuHyEwqb4hRs+ryl9vMGvwdfE685 T0Y+rvIxsT9m+X0kQfJzc7hedJ+K7wytkY5MmQhh5bMzhm7+6BhQJf/ABG2CTdUm Wilx9VJIxeVfORg1jEgQ+ssR0K9RmbuzAb3690xUYKobAK034JbSCvhodXIzVMYU g4iJ2m5rZrvdYKweuO98AAoRQ4DzNo2scGjmF9V2ImBrIbkIc2Mq2wms3PhNoYCu Rvzoa6fkoOR8acSo4dU3433xeZfdOIX9h0o5sBI+esERfdST1FwQ5FpF4SAiAr3u wXo/KZV/PfSZUAPHzbKCvIiEd330MJD6z18ORUYviqAcQNjqEhYyeARrzKxbkJA7 zOn3yirLR6yGm5cZ1YS0+A8wj4GBcf7XwkSJs2ospQqeTCpqZwceOxogs03myey9 Igx7IGT/PRHbMWFli584iERL+L6LbHUtZguJGabr/xh7YHt/vbOniH9BiG6AexXZ UzOjDaddzVJeAmvARQMowV7WssxvdVg8jnO19T4v93At0LKmTwUC015AQigaAvDP PZ3jUC/QBty5d7N3GBg= =7SFO -----END PGP SIGNATURE----- Merge tag 'mmc-v6.1-rc5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC fixes from Ulf Hansson: "MMC core: - Fix ambiguous TRIM and DISCARD args - Fix removal of debugfs file for mmc_test MMC host: - mtk-sd: Add missing clk_disable_unprepare() in an error path - sdhci: Fix I/O voltage switch delay for UHS-I SD cards - sdhci-esdhc-imx: Fix CQHCI exit halt state check - sdhci-sprd: Fix voltage switch" * tag 'mmc-v6.1-rc5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: sdhci-sprd: Fix no reset data and command after voltage switch mmc: sdhci: Fix voltage switch delay mmc: mtk-sd: Fix missing clk_disable_unprepare in msdc_of_clock_parse() mmc: mmc_test: Fix removal of debugfs file mmc: sdhci-esdhc-imx: correct CQHCI exit halt state check mmc: core: Fix ambiguous TRIM and DISCARD arg
This commit is contained in:
commit
2df2adc3e6
|
@ -1484,6 +1484,11 @@ void mmc_init_erase(struct mmc_card *card)
|
|||
card->pref_erase = 0;
|
||||
}
|
||||
|
||||
static bool is_trim_arg(unsigned int arg)
|
||||
{
|
||||
return (arg & MMC_TRIM_OR_DISCARD_ARGS) && arg != MMC_DISCARD_ARG;
|
||||
}
|
||||
|
||||
static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
|
||||
unsigned int arg, unsigned int qty)
|
||||
{
|
||||
|
@ -1766,7 +1771,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
|
|||
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (mmc_card_mmc(card) && (arg & MMC_TRIM_ARGS) &&
|
||||
if (mmc_card_mmc(card) && is_trim_arg(arg) &&
|
||||
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
@ -1796,7 +1801,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
|
|||
* identified by the card->eg_boundary flag.
|
||||
*/
|
||||
rem = card->erase_size - (from % card->erase_size);
|
||||
if ((arg & MMC_TRIM_ARGS) && (card->eg_boundary) && (nr > rem)) {
|
||||
if ((arg & MMC_TRIM_OR_DISCARD_ARGS) && card->eg_boundary && nr > rem) {
|
||||
err = mmc_do_erase(card, from, from + rem - 1, arg);
|
||||
from += rem;
|
||||
if ((err) || (to <= from))
|
||||
|
|
|
@ -3179,7 +3179,8 @@ static int __mmc_test_register_dbgfs_file(struct mmc_card *card,
|
|||
struct mmc_test_dbgfs_file *df;
|
||||
|
||||
if (card->debugfs_root)
|
||||
debugfs_create_file(name, mode, card->debugfs_root, card, fops);
|
||||
file = debugfs_create_file(name, mode, card->debugfs_root,
|
||||
card, fops);
|
||||
|
||||
df = kmalloc(sizeof(*df), GFP_KERNEL);
|
||||
if (!df) {
|
||||
|
|
|
@ -2588,13 +2588,11 @@ static int msdc_of_clock_parse(struct platform_device *pdev,
|
|||
return PTR_ERR(host->src_clk_cg);
|
||||
}
|
||||
|
||||
host->sys_clk_cg = devm_clk_get_optional(&pdev->dev, "sys_cg");
|
||||
/* If present, always enable for this clock gate */
|
||||
host->sys_clk_cg = devm_clk_get_optional_enabled(&pdev->dev, "sys_cg");
|
||||
if (IS_ERR(host->sys_clk_cg))
|
||||
host->sys_clk_cg = NULL;
|
||||
|
||||
/* If present, always enable for this clock gate */
|
||||
clk_prepare_enable(host->sys_clk_cg);
|
||||
|
||||
host->bulk_clks[0].id = "pclk_cg";
|
||||
host->bulk_clks[1].id = "axi_cg";
|
||||
host->bulk_clks[2].id = "ahb_cg";
|
||||
|
|
|
@ -1512,7 +1512,7 @@ static void esdhc_cqe_enable(struct mmc_host *mmc)
|
|||
* system resume back.
|
||||
*/
|
||||
cqhci_writel(cq_host, 0, CQHCI_CTL);
|
||||
if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT)
|
||||
if (cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT)
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"failed to exit halt state when enable CQE\n");
|
||||
|
||||
|
|
|
@ -470,7 +470,7 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
}
|
||||
|
||||
if (IS_ERR(sprd_host->pinctrl))
|
||||
return 0;
|
||||
goto reset;
|
||||
|
||||
switch (ios->signal_voltage) {
|
||||
case MMC_SIGNAL_VOLTAGE_180:
|
||||
|
@ -498,6 +498,8 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
|
||||
/* Wait for 300 ~ 500 us for pin state stable */
|
||||
usleep_range(300, 500);
|
||||
|
||||
reset:
|
||||
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -373,6 +373,7 @@ static void sdhci_init(struct sdhci_host *host, int soft)
|
|||
if (soft) {
|
||||
/* force clock reconfiguration */
|
||||
host->clock = 0;
|
||||
host->reinit_uhs = true;
|
||||
mmc->ops->set_ios(mmc, &mmc->ios);
|
||||
}
|
||||
}
|
||||
|
@ -2293,11 +2294,46 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
|
||||
|
||||
static bool sdhci_timing_has_preset(unsigned char timing)
|
||||
{
|
||||
switch (timing) {
|
||||
case MMC_TIMING_UHS_SDR12:
|
||||
case MMC_TIMING_UHS_SDR25:
|
||||
case MMC_TIMING_UHS_SDR50:
|
||||
case MMC_TIMING_UHS_SDR104:
|
||||
case MMC_TIMING_UHS_DDR50:
|
||||
case MMC_TIMING_MMC_DDR52:
|
||||
return true;
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sdhci_preset_needed(struct sdhci_host *host, unsigned char timing)
|
||||
{
|
||||
return !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
|
||||
sdhci_timing_has_preset(timing);
|
||||
}
|
||||
|
||||
static bool sdhci_presetable_values_change(struct sdhci_host *host, struct mmc_ios *ios)
|
||||
{
|
||||
/*
|
||||
* Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK
|
||||
* Frequency. Check if preset values need to be enabled, or the Driver
|
||||
* Strength needs updating. Note, clock changes are handled separately.
|
||||
*/
|
||||
return !host->preset_enabled &&
|
||||
(sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type);
|
||||
}
|
||||
|
||||
void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
bool reinit_uhs = host->reinit_uhs;
|
||||
bool turning_on_clk = false;
|
||||
u8 ctrl;
|
||||
|
||||
host->reinit_uhs = false;
|
||||
|
||||
if (ios->power_mode == MMC_POWER_UNDEFINED)
|
||||
return;
|
||||
|
||||
|
@ -2323,6 +2359,8 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
sdhci_enable_preset_value(host, false);
|
||||
|
||||
if (!ios->clock || ios->clock != host->clock) {
|
||||
turning_on_clk = ios->clock && !host->clock;
|
||||
|
||||
host->ops->set_clock(host, ios->clock);
|
||||
host->clock = ios->clock;
|
||||
|
||||
|
@ -2349,6 +2387,17 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
|
||||
host->ops->set_bus_width(host, ios->bus_width);
|
||||
|
||||
/*
|
||||
* Special case to avoid multiple clock changes during voltage
|
||||
* switching.
|
||||
*/
|
||||
if (!reinit_uhs &&
|
||||
turning_on_clk &&
|
||||
host->timing == ios->timing &&
|
||||
host->version >= SDHCI_SPEC_300 &&
|
||||
!sdhci_presetable_values_change(host, ios))
|
||||
return;
|
||||
|
||||
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
|
||||
|
||||
if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
|
||||
|
@ -2392,6 +2441,7 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
}
|
||||
|
||||
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
|
||||
host->drv_type = ios->drv_type;
|
||||
} else {
|
||||
/*
|
||||
* According to SDHC Spec v3.00, if the Preset Value
|
||||
|
@ -2419,19 +2469,14 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
host->ops->set_uhs_signaling(host, ios->timing);
|
||||
host->timing = ios->timing;
|
||||
|
||||
if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
|
||||
((ios->timing == MMC_TIMING_UHS_SDR12) ||
|
||||
(ios->timing == MMC_TIMING_UHS_SDR25) ||
|
||||
(ios->timing == MMC_TIMING_UHS_SDR50) ||
|
||||
(ios->timing == MMC_TIMING_UHS_SDR104) ||
|
||||
(ios->timing == MMC_TIMING_UHS_DDR50) ||
|
||||
(ios->timing == MMC_TIMING_MMC_DDR52))) {
|
||||
if (sdhci_preset_needed(host, ios->timing)) {
|
||||
u16 preset;
|
||||
|
||||
sdhci_enable_preset_value(host, true);
|
||||
preset = sdhci_get_preset_value(host);
|
||||
ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK,
|
||||
preset);
|
||||
host->drv_type = ios->drv_type;
|
||||
}
|
||||
|
||||
/* Re-enable SD Clock */
|
||||
|
@ -3768,6 +3813,7 @@ int sdhci_resume_host(struct sdhci_host *host)
|
|||
sdhci_init(host, 0);
|
||||
host->pwr = 0;
|
||||
host->clock = 0;
|
||||
host->reinit_uhs = true;
|
||||
mmc->ops->set_ios(mmc, &mmc->ios);
|
||||
} else {
|
||||
sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER));
|
||||
|
@ -3830,6 +3876,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
|
|||
/* Force clock and power re-program */
|
||||
host->pwr = 0;
|
||||
host->clock = 0;
|
||||
host->reinit_uhs = true;
|
||||
mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
|
||||
mmc->ops->set_ios(mmc, &mmc->ios);
|
||||
|
||||
|
|
|
@ -524,6 +524,8 @@ struct sdhci_host {
|
|||
|
||||
unsigned int clock; /* Current clock (MHz) */
|
||||
u8 pwr; /* Current voltage */
|
||||
u8 drv_type; /* Current UHS-I driver type */
|
||||
bool reinit_uhs; /* Force UHS-related re-initialization */
|
||||
|
||||
bool runtime_suspended; /* Host is runtime suspended */
|
||||
bool bus_on; /* Bus power prevents runtime suspend */
|
||||
|
|
|
@ -451,7 +451,7 @@ static inline bool mmc_ready_for_data(u32 status)
|
|||
#define MMC_SECURE_TRIM1_ARG 0x80000001
|
||||
#define MMC_SECURE_TRIM2_ARG 0x80008000
|
||||
#define MMC_SECURE_ARGS 0x80000000
|
||||
#define MMC_TRIM_ARGS 0x00008001
|
||||
#define MMC_TRIM_OR_DISCARD_ARGS 0x00008003
|
||||
|
||||
#define mmc_driver_type_mask(n) (1 << (n))
|
||||
|
||||
|
|
Loading…
Reference in New Issue