MMC core:
- Fix HW busy detection support for host controllers requiring the
MMC_RSP_BUSY response flag (R1B) to be set for the command. In
particular for CMD6 (eMMC), erase/trim/discard (SD/eMMC) and CMD5
(eMMC sleep).
MMC host:
- sdhci-omap|tegra: Fix support for HW busy detection
-----BEGIN PGP SIGNATURE-----
iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAl5rfBwXHHVsZi5oYW5z
c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjClhrA/+MlUKdgTL1MoySMU3xKDUslgx
Nq+ZzAnSESPMRqGaUkZ/V5ctwXUTQEa1rB8NSWlh/0qerdB+Llt8wnU8YiExBUnK
LeV0qZlmDv6OPBEVcVT2NyQgWmQDzd1BYXHbOyAhRTXJiSQ9RXiL/DK4Vbu+zikw
TIe4DUgzaOzzoFU8ohL9nRRJcoIG6L7jw8GT2hUWnJYM56qhpjnibrr62y4qQmSQ
pwPZ83Z3SYL5EIw/1QYN0swFluaOZCGjiaxC8JAK53SNJzDGLR1LDufw8y1PMwkb
huvq/lsOEZkUOiIiPwsPTBZul10p4kDC6FkqApd6zlItlT6K3M4vGfgQT5gv7Ke0
4Zd+gNDBVndwp4AgRgZa785n8F39QILkMSpB4KJ9YkfKKFI8+fm/Nzf8oyrLVmSD
Xg28TG470fRZtb4YxYVFCbJ+CZW9Czf5cAyY0RmDBkbFQzWt76w+RFxTLWFLU5U0
LZMLxjQo5oQ9TM7N4wzgoj4OQTE39xGFv3iXIrOW21sbjAMKrvqFSoJEZJxOyHZM
WMMHFfuiXacfXAHRkGiORRZwtMmoZpyp44/BMprYyVrM616z8RwYEs715QwFkvlP
8lx9Xtxx0ABgiWBa9C0TgLr/vOeXIJGvJuxv5f1oBnyyXhLzeeaTmg4QhHMt2Ti+
0UhVxVYQQ3XEpkEgz6Y=
=3dnT
-----END PGP SIGNATURE-----
Merge tag 'mmc-v5.6-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC fixes from Ulf Hansson:
"MMC core:
- Fix HW busy detection support for host controllers requiring the
MMC_RSP_BUSY response flag (R1B) to be set for the command. In
particular for CMD6 (eMMC), erase/trim/discard (SD/eMMC) and CMD5
(eMMC sleep).
MMC host:
- sdhci-omap|tegra: Fix support for HW busy detection"
* tag 'mmc-v5.6-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
mmc: core: Respect MMC_CAP_NEED_RSP_BUSY for eMMC sleep command
mmc: sdhci-tegra: Fix busy detection by enabling MMC_CAP_NEED_RSP_BUSY
mmc: sdhci-omap: Fix busy detection by enabling MMC_CAP_NEED_RSP_BUSY
mmc: core: Respect MMC_CAP_NEED_RSP_BUSY for erase/trim/discard
mmc: core: Allow host controllers to require R1B for CMD6
pull/774/merge
commit
d36561296b
|
|
@ -1732,8 +1732,11 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
|
||||||
* the erase operation does not exceed the max_busy_timeout, we should
|
* the erase operation does not exceed the max_busy_timeout, we should
|
||||||
* use R1B response. Or we need to prevent the host from doing hw busy
|
* use R1B response. Or we need to prevent the host from doing hw busy
|
||||||
* detection, which is done by converting to a R1 response instead.
|
* detection, which is done by converting to a R1 response instead.
|
||||||
|
* Note, some hosts requires R1B, which also means they are on their own
|
||||||
|
* when it comes to deal with the busy timeout.
|
||||||
*/
|
*/
|
||||||
if (card->host->max_busy_timeout &&
|
if (!(card->host->caps & MMC_CAP_NEED_RSP_BUSY) &&
|
||||||
|
card->host->max_busy_timeout &&
|
||||||
busy_timeout > card->host->max_busy_timeout) {
|
busy_timeout > card->host->max_busy_timeout) {
|
||||||
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
|
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1910,9 +1910,12 @@ static int mmc_sleep(struct mmc_host *host)
|
||||||
* If the max_busy_timeout of the host is specified, validate it against
|
* If the max_busy_timeout of the host is specified, validate it against
|
||||||
* the sleep cmd timeout. A failure means we need to prevent the host
|
* the sleep cmd timeout. A failure means we need to prevent the host
|
||||||
* from doing hw busy detection, which is done by converting to a R1
|
* from doing hw busy detection, which is done by converting to a R1
|
||||||
* response instead of a R1B.
|
* response instead of a R1B. Note, some hosts requires R1B, which also
|
||||||
|
* means they are on their own when it comes to deal with the busy
|
||||||
|
* timeout.
|
||||||
*/
|
*/
|
||||||
if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) {
|
if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
|
||||||
|
(timeout_ms > host->max_busy_timeout)) {
|
||||||
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||||
} else {
|
} else {
|
||||||
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||||
|
|
|
||||||
|
|
@ -542,9 +542,11 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||||
* If the max_busy_timeout of the host is specified, make sure it's
|
* If the max_busy_timeout of the host is specified, make sure it's
|
||||||
* enough to fit the used timeout_ms. In case it's not, let's instruct
|
* enough to fit the used timeout_ms. In case it's not, let's instruct
|
||||||
* the host to avoid HW busy detection, by converting to a R1 response
|
* the host to avoid HW busy detection, by converting to a R1 response
|
||||||
* instead of a R1B.
|
* instead of a R1B. Note, some hosts requires R1B, which also means
|
||||||
|
* they are on their own when it comes to deal with the busy timeout.
|
||||||
*/
|
*/
|
||||||
if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
|
if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
|
||||||
|
(timeout_ms > host->max_busy_timeout))
|
||||||
use_r1b_resp = false;
|
use_r1b_resp = false;
|
||||||
|
|
||||||
cmd.opcode = MMC_SWITCH;
|
cmd.opcode = MMC_SWITCH;
|
||||||
|
|
|
||||||
|
|
@ -1192,6 +1192,9 @@ static int sdhci_omap_probe(struct platform_device *pdev)
|
||||||
if (of_find_property(dev->of_node, "dmas", NULL))
|
if (of_find_property(dev->of_node, "dmas", NULL))
|
||||||
sdhci_switch_external_dma(host, true);
|
sdhci_switch_external_dma(host, true);
|
||||||
|
|
||||||
|
/* R1B responses is required to properly manage HW busy detection. */
|
||||||
|
mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
|
||||||
|
|
||||||
ret = sdhci_setup_host(host);
|
ret = sdhci_setup_host(host);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_put_sync;
|
goto err_put_sync;
|
||||||
|
|
|
||||||
|
|
@ -1552,6 +1552,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
|
||||||
if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
|
if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
|
||||||
host->mmc->caps |= MMC_CAP_1_8V_DDR;
|
host->mmc->caps |= MMC_CAP_1_8V_DDR;
|
||||||
|
|
||||||
|
/* R1B responses is required to properly manage HW busy detection. */
|
||||||
|
host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
|
||||||
|
|
||||||
tegra_sdhci_parse_dt(host);
|
tegra_sdhci_parse_dt(host);
|
||||||
|
|
||||||
tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
|
tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
|
||||||
|
|
|
||||||
|
|
@ -333,6 +333,7 @@ struct mmc_host {
|
||||||
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | \
|
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | \
|
||||||
MMC_CAP_UHS_DDR50)
|
MMC_CAP_UHS_DDR50)
|
||||||
#define MMC_CAP_SYNC_RUNTIME_PM (1 << 21) /* Synced runtime PM suspends. */
|
#define MMC_CAP_SYNC_RUNTIME_PM (1 << 21) /* Synced runtime PM suspends. */
|
||||||
|
#define MMC_CAP_NEED_RSP_BUSY (1 << 22) /* Commands with R1B can't use R1. */
|
||||||
#define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */
|
#define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */
|
||||||
#define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */
|
#define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */
|
||||||
#define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */
|
#define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue