From da3b1486d7e398617d09c022c71593462b98d67f Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Wed, 7 Apr 2021 11:15:39 +0800 Subject: [PATCH 01/54] mmc: s3cmci: move to use request_irq by IRQF_NO_AUTOEN flag disable_irq() after request_irq() still has a time gap in which interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will disable IRQ auto-enable because of requesting. Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1617765339-28946-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/s3cmci.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 0ca6f6d30b75..8d5929a32d34 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1578,17 +1578,12 @@ static int s3cmci_probe(struct platform_device *pdev) goto probe_iounmap; } - if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) { + if (request_irq(host->irq, s3cmci_irq, IRQF_NO_AUTOEN, DRIVER_NAME, host)) { dev_err(&pdev->dev, "failed to request mci interrupt.\n"); ret = -ENOENT; goto probe_iounmap; } - /* We get spurious interrupts even when we have set the IMSK - * register to ignore everything, so use disable_irq() to make - * ensure we don't lock the system with un-serviceable requests. */ - - disable_irq(host->irq); host->irq_state = false; /* Depending on the dma state, get a DMA channel to use. */ From 6a45d70cda6a6e3fa3cffe37d47495fb3c4a4bfa Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Wed, 28 Apr 2021 18:05:00 -0500 Subject: [PATCH 02/54] dt-bindings: mmc: sdhci-am654: Remove duplicate ti,j721e-sdhci-4bit The commit 7c7905df68c5 ("dt-bindings: mmc: sdhci-am654: fix compatible for j7200") switched the compatible property from a regular enum to an more appropriate combinatorial oneOf convention, and in the process has introduced a duplicate ti,j721e-sdhci-4bit. This generated the following warning on J721E boards that use the ti,j721e-sdhci-4bit for two nodes: "mmc@4fb0000: compatible: More than one condition true in oneOf schema" "mmc@4f98000: compatible: More than one condition true in oneOf schema" Remove the duplicate to fix this. Fixes: 7c7905df68c5 ("dt-bindings: mmc: sdhci-am654: fix compatible for j7200") Signed-off-by: Suman Anna Link: https://lore.kernel.org/r/20210428230500.19214-1-s-anna@ti.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-am654.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml index 3a79e39253d2..29399e88ac53 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml @@ -19,7 +19,6 @@ properties: - const: ti,am654-sdhci-5.1 - const: ti,j721e-sdhci-8bit - const: ti,j721e-sdhci-4bit - - const: ti,j721e-sdhci-4bit - const: ti,am64-sdhci-8bit - const: ti,am64-sdhci-4bit - items: From 873e90883069a4e32bc6ecd150b0107f9aa542b8 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Thu, 29 Apr 2021 16:11:44 +0800 Subject: [PATCH 03/54] dt-bindings: mmc: rockchip-dw-mshc: add description for rk3568 Add "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc" compatibles for mmc nodes on a rk3568 platform to rockchip-dw-mshc.yaml. Let's also take to opportunity to clean up some old redundant comments around previous compatibles. Signed-off-by: Liang Chen Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210429081151.17558-4-cl@rock-chips.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml index 3762f1c8de96..eaa3b0ef24f6 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml @@ -29,21 +29,14 @@ properties: - const: rockchip,rk3288-dw-mshc - items: - enum: - # for Rockchip PX30 - rockchip,px30-dw-mshc - # for Rockchip RK3036 - rockchip,rk3036-dw-mshc - # for Rockchip RK322x - rockchip,rk3228-dw-mshc - # for Rockchip RK3308 - rockchip,rk3308-dw-mshc - # for Rockchip RK3328 - rockchip,rk3328-dw-mshc - # for Rockchip RK3368 - rockchip,rk3368-dw-mshc - # for Rockchip RK3399 - rockchip,rk3399-dw-mshc - # for Rockchip RV1108 + - rockchip,rk3568-dw-mshc - rockchip,rv1108-dw-mshc - const: rockchip,rk3288-dw-mshc From 94ee6782e045645abd9180ab9369b01293d862bd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 3 May 2021 11:21:57 +0200 Subject: [PATCH 04/54] mmc: sdhci-acpi: Disable write protect detection on Toshiba Encore 2 WT8-B On the Toshiba Encore 2 WT8-B the microSD slot always reports the card being write-protected even though microSD cards do not have a write-protect switch at all. Add a new DMI_QUIRK_SD_NO_WRITE_PROTECT quirk entry to sdhci-acpi.c's DMI quirk table for this. Signed-off-by: Hans de Goede Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20210503092157.5689-1-hdegoede@redhat.com Signed-off-by: Ulf Hansson Cc: stable@vger.kernel.org --- drivers/mmc/host/sdhci-acpi.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index c3fbf8c825c4..8fe65f172a61 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -822,6 +822,17 @@ static const struct dmi_system_id sdhci_acpi_quirks[] = { }, .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT, }, + { + /* + * The Toshiba WT8-B's microSD slot always reports the card being + * write-protected. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TOSHIBA ENCORE 2 WT8-B"), + }, + .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT, + }, {} /* Terminating entry */ }; From e62f1e0b2384e25fe61042da3ecf08b7d8262f8d Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:12 +0200 Subject: [PATCH 05/54] mmc: core: Drop open coding when preparing commands with busy signaling Similar code for validating the host->max_busy_timeout towards the current command's busy timeout, exists in mmc_do_erase(), mmc_sleep() and __mmc_switch(). Let's move the common code into a helper function. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-2-ulf.hansson@linaro.org --- drivers/mmc/core/core.c | 20 ++---------------- drivers/mmc/core/mmc.c | 20 +++--------------- drivers/mmc/core/mmc_ops.c | 42 +++++++++++++++++++++----------------- drivers/mmc/core/mmc_ops.h | 3 +++ 4 files changed, 31 insertions(+), 54 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f194940c5974..b00c84ea8441 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1582,7 +1582,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, { struct mmc_command cmd = {}; unsigned int qty = 0, busy_timeout = 0; - bool use_r1b_resp = false; + bool use_r1b_resp; int err; mmc_retune_hold(card->host); @@ -1650,23 +1650,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, cmd.opcode = MMC_ERASE; cmd.arg = arg; busy_timeout = mmc_erase_timeout(card, arg, qty); - /* - * If the host controller supports busy signalling and the timeout for - * 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 - * 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->caps & MMC_CAP_NEED_RSP_BUSY) && - card->host->max_busy_timeout && - busy_timeout > card->host->max_busy_timeout) { - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; - } else { - cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; - cmd.busy_timeout = busy_timeout; - use_r1b_resp = true; - } + use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd, busy_timeout); err = mmc_wait_for_cmd(card->host, &cmd, 0); if (err) { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 8674c3e0c02c..63a7bd0b239c 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1910,6 +1910,7 @@ static int mmc_sleep(struct mmc_host *host) struct mmc_command cmd = {}; struct mmc_card *card = host->card; unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000); + bool use_r1b_resp; int err; /* Re-tuning can't be done once the card is deselected */ @@ -1922,22 +1923,7 @@ static int mmc_sleep(struct mmc_host *host) cmd.opcode = MMC_SLEEP_AWAKE; cmd.arg = card->rca << 16; cmd.arg |= 1 << 15; - - /* - * 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 - * from doing hw busy detection, which is done by converting to a R1 - * 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->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout && - (timeout_ms > host->max_busy_timeout)) { - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - } else { - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - cmd.busy_timeout = timeout_ms; - } + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms); err = mmc_wait_for_cmd(host, &cmd, 0); if (err) @@ -1949,7 +1935,7 @@ static int mmc_sleep(struct mmc_host *host) * SEND_STATUS command to poll the status because that command (and most * others) is invalid while the card sleeps. */ - if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) + if (!use_r1b_resp || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) mmc_delay(timeout_ms); out_release: diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 5756781fef37..025a4134d5c7 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -521,6 +521,27 @@ int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, return __mmc_poll_for_busy(card, timeout_ms, true, false, busy_cmd); } +bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, + unsigned int timeout_ms) +{ + /* + * 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 + * the host to avoid HW busy detection, by converting to a R1 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->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout && + (timeout_ms > host->max_busy_timeout)) { + cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1 | MMC_RSP_R1; + return false; + } + + cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1B | MMC_RSP_R1B; + cmd->busy_timeout = timeout_ms; + return true; +} + /** * __mmc_switch - modify EXT_CSD register * @card: the MMC card associated with the data transfer @@ -543,7 +564,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, struct mmc_host *host = card->host; int err; struct mmc_command cmd = {}; - bool use_r1b_resp = true; + bool use_r1b_resp; unsigned char old_timing = host->ios.timing; mmc_retune_hold(host); @@ -554,29 +575,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, timeout_ms = card->ext_csd.generic_cmd6_time; } - /* - * 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 - * the host to avoid HW busy detection, by converting to a R1 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->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout && - (timeout_ms > host->max_busy_timeout)) - use_r1b_resp = false; - cmd.opcode = MMC_SWITCH; cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | set; - cmd.flags = MMC_CMD_AC; - if (use_r1b_resp) { - cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; - cmd.busy_timeout = timeout_ms; - } else { - cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; - } + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms); err = mmc_wait_for_cmd(host, &cmd, retries); if (err) diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 7bc1cfb0654c..ba898c435658 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -18,6 +18,7 @@ enum mmc_busy_cmd { struct mmc_host; struct mmc_card; +struct mmc_command; int mmc_select_card(struct mmc_card *card); int mmc_deselect_cards(struct mmc_host *host); @@ -35,6 +36,8 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_can_ext_csd(struct mmc_card *card); int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); +bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, + unsigned int timeout_ms); int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, enum mmc_busy_cmd busy_cmd); int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, From c7bedef053cf7fd26efca90551a95c1776dd9e2f Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:13 +0200 Subject: [PATCH 06/54] mmc: core: Take into account MMC_CAP_NEED_RSP_BUSY for eMMC HPI commands In mmc_send_hpi_cmd() the host->max_busy_timeout is being validated towards the timeout for the eMMC HPI command, as to decide whether an R1 or R1B response should be used. Although, it has turned out the some host can't cope with that conversion, but needs R1B, which means MMC_CAP_NEED_RSP_BUSY is set for them. Let's take this into account, via using the common mmc_prepare_busy_cmd() when doing the validation, which also avoids some open coding. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-3-ulf.hansson@linaro.org --- drivers/mmc/core/mmc_ops.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 025a4134d5c7..66ae699a410f 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -817,28 +817,17 @@ static int mmc_send_hpi_cmd(struct mmc_card *card) { unsigned int busy_timeout_ms = card->ext_csd.out_of_int_time; struct mmc_host *host = card->host; - bool use_r1b_resp = true; + bool use_r1b_resp = false; struct mmc_command cmd = {}; int err; cmd.opcode = card->ext_csd.hpi_cmd; cmd.arg = card->rca << 16 | 1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - /* - * Make sure the host's max_busy_timeout fit the needed timeout for HPI. - * In case it doesn't, let's instruct the host to avoid HW busy - * detection, by using a R1 response instead of R1B. - */ - if (host->max_busy_timeout && busy_timeout_ms > host->max_busy_timeout) - use_r1b_resp = false; - - if (cmd.opcode == MMC_STOP_TRANSMISSION && use_r1b_resp) { - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - cmd.busy_timeout = busy_timeout_ms; - } else { - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - use_r1b_resp = false; - } + if (cmd.opcode == MMC_STOP_TRANSMISSION) + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, + busy_timeout_ms); err = mmc_wait_for_cmd(host, &cmd, 0); if (err) { From 1e0b069bdc583925d6207e091e55ad4d0f30eb4c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:14 +0200 Subject: [PATCH 07/54] mmc: core: Re-structure some code in __mmc_poll_for_busy() To make the code a bit more understandable, let's move the check about whether polling is allowed or not, out to the caller instead. In this way, we can also drop the send_status in-parameter, so let's do that. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-4-ulf.hansson@linaro.org --- drivers/mmc/core/mmc_ops.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 66ae699a410f..ccaee1cb7ff5 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -465,8 +465,7 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, } static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - bool send_status, bool retry_crc_err, - enum mmc_busy_cmd busy_cmd) + bool retry_crc_err, enum mmc_busy_cmd busy_cmd) { struct mmc_host *host = card->host; int err; @@ -475,16 +474,6 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, bool expired = false; bool busy = false; - /* - * In cases when not allowed to poll by using CMD13 or because we aren't - * capable of polling by using ->card_busy(), then rely on waiting the - * stated timeout to be sufficient. - */ - if (!send_status && !host->ops->card_busy) { - mmc_delay(timeout_ms); - return 0; - } - timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1; do { /* @@ -518,7 +507,7 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, enum mmc_busy_cmd busy_cmd) { - return __mmc_poll_for_busy(card, timeout_ms, true, false, busy_cmd); + return __mmc_poll_for_busy(card, timeout_ms, false, busy_cmd); } bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, @@ -591,8 +580,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, mmc_host_is_spi(host)) goto out_tim; + /* + * If the host doesn't support HW polling via the ->card_busy() ops and + * when it's not allowed to poll by using CMD13, then we need to rely on + * waiting the stated timeout to be sufficient. + */ + if (!send_status && !host->ops->card_busy) { + mmc_delay(timeout_ms); + goto out_tim; + } + /* Let's try to poll to find out when the command is completed. */ - err = __mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err, + err = __mmc_poll_for_busy(card, timeout_ms, retry_crc_err, MMC_BUSY_CMD6); if (err) goto out; From 04f967ad28c836815f6894b618643dd23670c6e5 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:15 +0200 Subject: [PATCH 08/54] mmc: core: Extend re-use of __mmc_poll_for_busy() Via __mmc_poll_for_busy() we end up polling with the ->card_busy() host ops or by sending the CMD13. To allow polling of different types, which is needed to support a few new SD card features, let's rework the code around __mmc_poll_for_busy() to make it more generic. More precisely, let __mmc_poll_for_busy() take a pointer to a callback function as in-parameter, which it calls to poll for busy state completion. Additionally, let's share __mmc_poll_for_busy() to allow it to be re-used outside of mmc_ops.c. Subsequent changes will make use of it. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-5-ulf.hansson@linaro.org --- drivers/mmc/core/core.c | 2 +- drivers/mmc/core/mmc_ops.c | 42 ++++++++++++++++++++++++-------------- drivers/mmc/core/mmc_ops.h | 5 ++++- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index b00c84ea8441..b039dcff17f8 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1671,7 +1671,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, goto out; /* Let's poll to find out when the erase operation completes. */ - err = mmc_poll_for_busy(card, busy_timeout, MMC_BUSY_ERASE); + err = mmc_poll_for_busy(card, busy_timeout, false, MMC_BUSY_ERASE); out: mmc_retune_release(card->host); diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index ccaee1cb7ff5..653627fe02a3 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -53,6 +53,12 @@ static const u8 tuning_blk_pattern_8bit[] = { 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, }; +struct mmc_busy_data { + struct mmc_card *card; + bool retry_crc_err; + enum mmc_busy_cmd busy_cmd; +}; + int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries) { int err; @@ -424,10 +430,10 @@ int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) return mmc_switch_status_error(card->host, status); } -static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, - enum mmc_busy_cmd busy_cmd, bool *busy) +static int mmc_busy_cb(void *cb_data, bool *busy) { - struct mmc_host *host = card->host; + struct mmc_busy_data *data = cb_data; + struct mmc_host *host = data->card->host; u32 status = 0; int err; @@ -436,17 +442,17 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, return 0; } - err = mmc_send_status(card, &status); - if (retry_crc_err && err == -EILSEQ) { + err = mmc_send_status(data->card, &status); + if (data->retry_crc_err && err == -EILSEQ) { *busy = true; return 0; } if (err) return err; - switch (busy_cmd) { + switch (data->busy_cmd) { case MMC_BUSY_CMD6: - err = mmc_switch_status_error(card->host, status); + err = mmc_switch_status_error(host, status); break; case MMC_BUSY_ERASE: err = R1_STATUS(status) ? -EIO : 0; @@ -464,8 +470,9 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, return 0; } -static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - bool retry_crc_err, enum mmc_busy_cmd busy_cmd) +int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data) { struct mmc_host *host = card->host; int err; @@ -482,7 +489,7 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, */ expired = time_after(jiffies, timeout); - err = mmc_busy_status(card, retry_crc_err, busy_cmd, &busy); + err = (*busy_cb)(cb_data, &busy); if (err) return err; @@ -505,9 +512,15 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, } int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - enum mmc_busy_cmd busy_cmd) + bool retry_crc_err, enum mmc_busy_cmd busy_cmd) { - return __mmc_poll_for_busy(card, timeout_ms, false, busy_cmd); + struct mmc_busy_data cb_data; + + cb_data.card = card; + cb_data.retry_crc_err = retry_crc_err; + cb_data.busy_cmd = busy_cmd; + + return __mmc_poll_for_busy(card, timeout_ms, &mmc_busy_cb, &cb_data); } bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, @@ -591,8 +604,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, } /* Let's try to poll to find out when the command is completed. */ - err = __mmc_poll_for_busy(card, timeout_ms, retry_crc_err, - MMC_BUSY_CMD6); + err = mmc_poll_for_busy(card, timeout_ms, retry_crc_err, MMC_BUSY_CMD6); if (err) goto out; @@ -840,7 +852,7 @@ static int mmc_send_hpi_cmd(struct mmc_card *card) return 0; /* Let's poll to find out when the HPI request completes. */ - return mmc_poll_for_busy(card, busy_timeout_ms, MMC_BUSY_HPI); + return mmc_poll_for_busy(card, busy_timeout_ms, false, MMC_BUSY_HPI); } /** diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index ba898c435658..aca66c128804 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -38,8 +38,11 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, unsigned int timeout_ms); +int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data); int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - enum mmc_busy_cmd busy_cmd); + bool retry_crc_err, enum mmc_busy_cmd busy_cmd); int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms, unsigned char timing, bool send_status, bool retry_crc_err, unsigned int retries); From 6fa79651cc808f68db6f6f297be5a950ccd5dffb Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:16 +0200 Subject: [PATCH 09/54] mmc: core: Enable eMMC sleep commands to use HW busy polling After the eMMC sleep command (CMD5) has been sent, the card start signals busy on the DAT0 line, which can be monitored to understand when it's allowed to proceed to power off the VCC regulator. When MMC_CAP_WAIT_WHILE_BUSY isn't supported by the host the DAT0 line isn't being monitored for busy completion, but instead we are waiting a fixed period of time. The time corresponds to the sleep timeout that is specified in the EXT_CSD register of the eMMC card. This is many cases suboptimal, as the timeout corresponds to the worst case scenario. To improve the situation add support for HW busy polling through the ->card_busy() host ops, when the host supports this. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-6-ulf.hansson@linaro.org --- drivers/mmc/core/mmc.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 63a7bd0b239c..13074aa1f605 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1905,6 +1905,14 @@ static int mmc_can_sleep(struct mmc_card *card) return card->ext_csd.rev >= 3; } +static int mmc_sleep_busy_cb(void *cb_data, bool *busy) +{ + struct mmc_host *host = cb_data; + + *busy = host->ops->card_busy(host); + return 0; +} + static int mmc_sleep(struct mmc_host *host) { struct mmc_command cmd = {}; @@ -1930,13 +1938,20 @@ static int mmc_sleep(struct mmc_host *host) goto out_release; /* - * If the host does not wait while the card signals busy, then we will - * will have to wait the sleep/awake timeout. Note, we cannot use the - * SEND_STATUS command to poll the status because that command (and most - * others) is invalid while the card sleeps. + * If the host does not wait while the card signals busy, then we can + * try to poll, but only if the host supports HW polling, as the + * SEND_STATUS cmd is not allowed. If we can't poll, then we simply need + * to wait the sleep/awake timeout. */ - if (!use_r1b_resp || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) + if (host->caps & MMC_CAP_WAIT_WHILE_BUSY && use_r1b_resp) + goto out_release; + + if (!host->ops->card_busy) { mmc_delay(timeout_ms); + goto out_release; + } + + err = __mmc_poll_for_busy(card, timeout_ms, &mmc_sleep_busy_cb, host); out_release: mmc_retune_release(host); From cec18ad93e35a219d2277dbbdbfedb4f83a7a220 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:17 +0200 Subject: [PATCH 10/54] mmc: core: Prepare mmc_send_cxd_data() to be re-used for additional cmds The function mmc_send_cxd_data() sends a data read command of ADTC type and prepares to receive an R1 response. To make it even more re-usable, let's extend it with another in-parameter for the command argument. While at it, let's also rename the function to mmc_send_adtc_data() as it better describes its purpose. Note that, this change doesn't add any new users of the function. Instead that is done from subsequent changes. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-7-ulf.hansson@linaro.org --- drivers/mmc/core/mmc_ops.c | 11 +++++------ drivers/mmc/core/mmc_ops.h | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 653627fe02a3..b1da8f1950ee 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -252,9 +252,8 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) * NOTE: void *buf, caller for the buf is required to use DMA-capable * buffer or on-stack buffer (with some overhead in callee). */ -static int -mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, - u32 opcode, void *buf, unsigned len) +int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, + u32 args, void *buf, unsigned len) { struct mmc_request mrq = {}; struct mmc_command cmd = {}; @@ -265,7 +264,7 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, mrq.data = &data; cmd.opcode = opcode; - cmd.arg = 0; + cmd.arg = args; /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we * rely on callers to never use this with "native" calls for reading @@ -311,7 +310,7 @@ static int mmc_spi_send_cxd(struct mmc_host *host, u32 *cxd, u32 opcode) if (!cxd_tmp) return -ENOMEM; - ret = mmc_send_cxd_data(NULL, host, opcode, cxd_tmp, 16); + ret = mmc_send_adtc_data(NULL, host, opcode, 0, cxd_tmp, 16); if (ret) goto err; @@ -359,7 +358,7 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) if (!ext_csd) return -ENOMEM; - err = mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, ext_csd, + err = mmc_send_adtc_data(card, card->host, MMC_SEND_EXT_CSD, 0, ext_csd, 512); if (err) kfree(ext_csd); diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index aca66c128804..2b1d730e56bf 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -26,6 +26,8 @@ int mmc_set_dsr(struct mmc_host *host); int mmc_go_idle(struct mmc_host *host); int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_set_relative_addr(struct mmc_card *card); +int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, + u32 args, void *buf, unsigned len); int mmc_send_csd(struct mmc_card *card, u32 *csd); int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries); int mmc_send_status(struct mmc_card *card, u32 *status); From 41e84fe1647e0d6ec309882bc247667e304c351f Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:18 +0200 Subject: [PATCH 11/54] mmc: core: Drop open coding in mmc_sd_switch() The SD_SWITCH (CMD6) is an ADTC type of command with an R1 response, which can be sent by using the mmc_send_adtc_data(). Let's do that and drop the open coding in mmc_sd_switch(). Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-8-ulf.hansson@linaro.org --- drivers/mmc/core/sd_ops.c | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index d61ff811218c..ef8d1dce5af1 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -17,6 +17,7 @@ #include "core.h" #include "sd_ops.h" +#include "mmc_ops.h" int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) { @@ -309,43 +310,18 @@ int mmc_app_send_scr(struct mmc_card *card) int mmc_sd_switch(struct mmc_card *card, int mode, int group, u8 value, u8 *resp) { - struct mmc_request mrq = {}; - struct mmc_command cmd = {}; - struct mmc_data data = {}; - struct scatterlist sg; + u32 cmd_args; /* NOTE: caller guarantees resp is heap-allocated */ mode = !!mode; value &= 0xF; + cmd_args = mode << 31 | 0x00FFFFFF; + cmd_args &= ~(0xF << (group * 4)); + cmd_args |= value << (group * 4); - mrq.cmd = &cmd; - mrq.data = &data; - - cmd.opcode = SD_SWITCH; - cmd.arg = mode << 31 | 0x00FFFFFF; - cmd.arg &= ~(0xF << (group * 4)); - cmd.arg |= value << (group * 4); - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; - - data.blksz = 64; - data.blocks = 1; - data.flags = MMC_DATA_READ; - data.sg = &sg; - data.sg_len = 1; - - sg_init_one(&sg, resp, 64); - - mmc_set_data_timeout(&data, card); - - mmc_wait_for_req(card->host, &mrq); - - if (cmd.error) - return cmd.error; - if (data.error) - return data.error; - - return 0; + return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp, + 64); } int mmc_app_sd_status(struct mmc_card *card, void *ssr) From dbea8ae9febdea11cb74d094e6b730987079679e Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:19 +0200 Subject: [PATCH 12/54] mmc: core: Parse the SD SCR register for support of CMD48/49 and CMD58/59 In SD spec v4.x the support for CMD48/49 and CMD58/59 were introduced as optional features. To let the card announce whether it supports the commands, the SCR register has been extended with corresponding support bits. Let's parse and store this information for later use. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-9-ulf.hansson@linaro.org --- drivers/mmc/core/sd.c | 4 +++- include/linux/mmc/card.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 2c48d6504101..de7b5f8df550 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -222,7 +222,9 @@ static int mmc_decode_scr(struct mmc_card *card) else card->erased_byte = 0x0; - if (scr->sda_spec3) + if (scr->sda_spec4) + scr->cmds = UNSTUFF_BITS(resp, 32, 4); + else if (scr->sda_spec3) scr->cmds = UNSTUFF_BITS(resp, 32, 2); /* SD Spec says: any SD Card shall set at least bits 0 and 2 */ diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index f9ad35dd6012..858fc4d11240 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -139,6 +139,8 @@ struct sd_scr { unsigned char cmds; #define SD_SCR_CMD20_SUPPORT (1<<0) #define SD_SCR_CMD23_SUPPORT (1<<1) +#define SD_SCR_CMD48_SUPPORT (1<<2) +#define SD_SCR_CMD58_SUPPORT (1<<3) }; struct sd_ssr { From c784f92769ae8eafb2eb489408757528ff7525df Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:20 +0200 Subject: [PATCH 13/54] mmc: core: Read the SD function extension registers for power management In the SD spec v4.0 the CMD48/49 and CMD58/59 were introduced as optional commands. In the SD spec v4.1 the SD function extension registers were introduced, which requires support for CMD48/49/58/59 to be read/written from/to. Moreover, a specific function extension register were added to let the card announce support for optional features in regards to power management. The features that were added are "Power Off Notification", "Power Down Mode" and "Power Sustenance". As a first step to support this, let's read and parse the register for power management during the SD card initialization and store the information about the supported features in the struct mmc_card. In this way, we prepare for subsequent changes to implement the complete support for the new features. Signed-off-by: Ulf Hansson Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Acked-by: Avri Altman Link: https://lore.kernel.org/r/20210504161222.101536-10-ulf.hansson@linaro.org --- drivers/mmc/core/sd.c | 178 +++++++++++++++++++++++++++++++++++++++ include/linux/mmc/card.h | 13 +++ include/linux/mmc/sd.h | 3 + 3 files changed, 194 insertions(+) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index de7b5f8df550..2e687f1f4542 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -996,6 +996,177 @@ static bool mmc_sd_card_using_v18(struct mmc_card *card) (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); } +static int sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page, + u16 offset, u16 len, u8 *reg_buf) +{ + u32 cmd_args; + + /* + * Command arguments of CMD48: + * [31:31] MIO (0 = memory). + * [30:27] FNO (function number). + * [26:26] reserved (0). + * [25:18] page number. + * [17:9] offset address. + * [8:0] length (0 = 1 byte, 1ff = 512 bytes). + */ + cmd_args = fno << 27 | page << 18 | offset << 9 | (len -1); + + return mmc_send_adtc_data(card, card->host, SD_READ_EXTR_SINGLE, + cmd_args, reg_buf, 512); +} + +static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page, + u16 offset) +{ + int err; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* Read the extension register for power management function. */ + err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); + if (err) { + pr_warn("%s: error %d reading PM func of ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* PM revision consists of 4 bits. */ + card->ext_power.rev = reg_buf[0] & 0xf; + + /* Power Off Notification support at bit 4. */ + if (reg_buf[1] & BIT(4)) + card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY; + + /* Power Sustenance support at bit 5. */ + if (reg_buf[1] & BIT(5)) + card->ext_power.feature_support |= SD_EXT_POWER_SUSTENANCE; + + /* Power Down Mode support at bit 6. */ + if (reg_buf[1] & BIT(6)) + card->ext_power.feature_support |= SD_EXT_POWER_DOWN_MODE; + + card->ext_power.fno = fno; + card->ext_power.page = page; + card->ext_power.offset = offset; + +out: + kfree(reg_buf); + return err; +} + +static int sd_parse_ext_reg(struct mmc_card *card, u8 *gen_info_buf, + u16 *next_ext_addr) +{ + u8 num_regs, fno, page; + u16 sfc, offset, ext = *next_ext_addr; + u32 reg_addr; + + /* + * Parse only one register set per extension, as that is sufficient to + * support the standard functions. This means another 48 bytes in the + * buffer must be available. + */ + if (ext + 48 > 512) + return -EFAULT; + + /* Standard Function Code */ + memcpy(&sfc, &gen_info_buf[ext], 2); + + /* Address to the next extension. */ + memcpy(next_ext_addr, &gen_info_buf[ext + 40], 2); + + /* Number of registers for this extension. */ + num_regs = gen_info_buf[ext + 42]; + + /* We support only one register per extension. */ + if (num_regs != 1) + return 0; + + /* Extension register address. */ + memcpy(®_addr, &gen_info_buf[ext + 44], 4); + + /* 9 bits (0 to 8) contains the offset address. */ + offset = reg_addr & 0x1ff; + + /* 8 bits (9 to 16) contains the page number. */ + page = reg_addr >> 9 & 0xff ; + + /* 4 bits (18 to 21) contains the function number. */ + fno = reg_addr >> 18 & 0xf; + + /* Standard Function Code for power management. */ + if (sfc == 0x1) + return sd_parse_ext_reg_power(card, fno, page, offset); + + return 0; +} + +static int sd_read_ext_regs(struct mmc_card *card) +{ + int err, i; + u8 num_ext, *gen_info_buf; + u16 rev, len, next_ext_addr; + + if (mmc_host_is_spi(card->host)) + return 0; + + if (!(card->scr.cmds & SD_SCR_CMD48_SUPPORT)) + return 0; + + gen_info_buf = kzalloc(512, GFP_KERNEL); + if (!gen_info_buf) + return -ENOMEM; + + /* + * Read 512 bytes of general info, which is found at function number 0, + * at page 0 and with no offset. + */ + err = sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf); + if (err) { + pr_warn("%s: error %d reading general info of SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* General info structure revision. */ + memcpy(&rev, &gen_info_buf[0], 2); + + /* Length of general info in bytes. */ + memcpy(&len, &gen_info_buf[2], 2); + + /* Number of extensions to be find. */ + num_ext = gen_info_buf[4]; + + /* We support revision 0, but limit it to 512 bytes for simplicity. */ + if (rev != 0 || len > 512) { + pr_warn("%s: non-supported SD ext reg layout\n", + mmc_hostname(card->host)); + goto out; + } + + /* + * Parse the extension registers. The first extension should start + * immediately after the general info header (16 bytes). + */ + next_ext_addr = 16; + for (i = 0; i < num_ext; i++) { + err = sd_parse_ext_reg(card, gen_info_buf, &next_ext_addr); + if (err) { + pr_warn("%s: error %d parsing SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + } + +out: + kfree(gen_info_buf); + return err; +} + /* * Handle the detection and initialisation of a card. * @@ -1144,6 +1315,13 @@ retry: } } + if (!oldcard) { + /* Read/parse the extension registers. */ + err = sd_read_ext_regs(card); + if (err) + goto free_card; + } + if (host->cqe_ops && !host->cqe_enabled) { err = host->cqe_ops->cqe_enable(host, card); if (!err) { diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 858fc4d11240..03a862e93594 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -191,6 +191,18 @@ struct sd_switch_caps { #define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) }; +struct sd_ext_reg { + u8 fno; + u8 page; + u16 offset; + u8 rev; + u8 feature_support; +/* Power Management Function. */ +#define SD_EXT_POWER_OFF_NOTIFY (1<<0) +#define SD_EXT_POWER_SUSTENANCE (1<<1) +#define SD_EXT_POWER_DOWN_MODE (1<<2) +}; + struct sdio_cccr { unsigned int sdio_vsn; unsigned int sd_vsn; @@ -292,6 +304,7 @@ struct mmc_card { struct sd_scr scr; /* extra SD information */ struct sd_ssr ssr; /* yet more SD information */ struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ + struct sd_ext_reg ext_power; /* SD extension reg for PM */ unsigned int sdio_funcs; /* number of SDIO functions */ atomic_t sdio_funcs_probed; /* number of probed SDIO funcs */ diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index 2236aa540faa..43bfc5c39ad4 100644 --- a/include/linux/mmc/sd.h +++ b/include/linux/mmc/sd.h @@ -29,6 +29,9 @@ #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ #define SD_APP_SEND_SCR 51 /* adtc R1 */ + /* class 11 */ +#define SD_READ_EXTR_SINGLE 48 /* adtc [31:0] R1 */ + /* OCR bit definitions */ #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ From 4e6306e0b83c6251699c2202e859b55ddf7b8c5f Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:21 +0200 Subject: [PATCH 14/54] mmc: core: Read performance enhancements registers for SD cards In SD spec v6.x the SD function extension registers for performance enhancements were introduced. These registers let the SD card announce supports for various performance related features, like "self-maintenance", "cache" and "command queuing". Let's extend the parsing of SD function extension registers and store the information in the struct mmc_card. This prepares for subsequent changes to implement the complete support for new the performance enhancement features. Signed-off-by: Ulf Hansson Acked-by: Avri Altman Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Link: https://lore.kernel.org/r/20210504161222.101536-11-ulf.hansson@linaro.org --- drivers/mmc/core/sd.c | 53 ++++++++++++++++++++++++++++++++++++++++ include/linux/mmc/card.h | 7 ++++++ 2 files changed, 60 insertions(+) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 2e687f1f4542..0b882aaedf78 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1058,6 +1058,55 @@ out: return err; } +static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page, + u16 offset) +{ + int err; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); + if (err) { + pr_warn("%s: error %d reading PERF func of ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* PERF revision. */ + card->ext_perf.rev = reg_buf[0]; + + /* FX_EVENT support at bit 0. */ + if (reg_buf[1] & BIT(0)) + card->ext_perf.feature_support |= SD_EXT_PERF_FX_EVENT; + + /* Card initiated self-maintenance support at bit 0. */ + if (reg_buf[2] & BIT(0)) + card->ext_perf.feature_support |= SD_EXT_PERF_CARD_MAINT; + + /* Host initiated self-maintenance support at bit 1. */ + if (reg_buf[2] & BIT(1)) + card->ext_perf.feature_support |= SD_EXT_PERF_HOST_MAINT; + + /* Cache support at bit 0. */ + if (reg_buf[4] & BIT(0)) + card->ext_perf.feature_support |= SD_EXT_PERF_CACHE; + + /* Command queue support indicated via queue depth bits (0 to 4). */ + if (reg_buf[6] & 0x1f) + card->ext_perf.feature_support |= SD_EXT_PERF_CMD_QUEUE; + + card->ext_perf.fno = fno; + card->ext_perf.page = page; + card->ext_perf.offset = offset; + +out: + kfree(reg_buf); + return err; +} + static int sd_parse_ext_reg(struct mmc_card *card, u8 *gen_info_buf, u16 *next_ext_addr) { @@ -1102,6 +1151,10 @@ static int sd_parse_ext_reg(struct mmc_card *card, u8 *gen_info_buf, if (sfc == 0x1) return sd_parse_ext_reg_power(card, fno, page, offset); + /* Standard Function Code for performance enhancement. */ + if (sfc == 0x2) + return sd_parse_ext_reg_perf(card, fno, page, offset); + return 0; } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 03a862e93594..2867af0635f8 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -201,6 +201,12 @@ struct sd_ext_reg { #define SD_EXT_POWER_OFF_NOTIFY (1<<0) #define SD_EXT_POWER_SUSTENANCE (1<<1) #define SD_EXT_POWER_DOWN_MODE (1<<2) +/* Performance Enhancement Function. */ +#define SD_EXT_PERF_FX_EVENT (1<<0) +#define SD_EXT_PERF_CARD_MAINT (1<<1) +#define SD_EXT_PERF_HOST_MAINT (1<<2) +#define SD_EXT_PERF_CACHE (1<<3) +#define SD_EXT_PERF_CMD_QUEUE (1<<4) }; struct sdio_cccr { @@ -305,6 +311,7 @@ struct mmc_card { struct sd_ssr ssr; /* yet more SD information */ struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ struct sd_ext_reg ext_power; /* SD extension reg for PM */ + struct sd_ext_reg ext_perf; /* SD extension reg for PERF */ unsigned int sdio_funcs; /* number of SDIO functions */ atomic_t sdio_funcs_probed; /* number of probed SDIO funcs */ From 2c5d42769038045b92160a849aad43c4b3170e2a Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 4 May 2021 18:12:22 +0200 Subject: [PATCH 15/54] mmc: core: Add support for Power Off Notification for SD cards Rather than only deselecting the SD card via a CMD7, before we cut power to it at system suspend, at runtime suspend or at shutdown, let's add support for a graceful power off sequence via enabling the SD Power Off Notification feature. Note that, the Power Off Notification feature was added in the SD spec v4.x, which is several years ago. However, it's still a bit unclear how often the SD card vendors decides to implement support for it. To validate these changes a Sandisk Extreme PRO A2 64GB has been used, which seems to work nicely. Signed-off-by: Ulf Hansson Acked-by: Avri Altman Reviewed-by: Linus Walleij Reviewed-by: Shawn Lin Link: https://lore.kernel.org/r/20210504161222.101536-12-ulf.hansson@linaro.org --- drivers/mmc/core/sd.c | 136 ++++++++++++++++++++++++++++++++++++++++- include/linux/mmc/sd.h | 1 + 2 files changed, 134 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 0b882aaedf78..bd40c682d264 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -66,6 +66,13 @@ static const unsigned int sd_au_size[] = { __res & __mask; \ }) +#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000 + +struct sd_busy_data { + struct mmc_card *card; + u8 *reg_buf; +}; + /* * Given the decoded CSD structure, decode the raw CID to our CID structure. */ @@ -996,6 +1003,66 @@ static bool mmc_sd_card_using_v18(struct mmc_card *card) (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); } +static int sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset, + u8 reg_data) +{ + struct mmc_host *host = card->host; + struct mmc_request mrq = {}; + struct mmc_command cmd = {}; + struct mmc_data data = {}; + struct scatterlist sg; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + mrq.cmd = &cmd; + mrq.data = &data; + + /* + * Arguments of CMD49: + * [31:31] MIO (0 = memory). + * [30:27] FNO (function number). + * [26:26] MW - mask write mode (0 = disable). + * [25:18] page number. + * [17:9] offset address. + * [8:0] length (0 = 1 byte). + */ + cmd.arg = fno << 27 | page << 18 | offset << 9; + + /* The first byte in the buffer is the data to be written. */ + reg_buf[0] = reg_data; + + data.flags = MMC_DATA_WRITE; + data.blksz = 512; + data.blocks = 1; + data.sg = &sg; + data.sg_len = 1; + sg_init_one(&sg, reg_buf, 512); + + cmd.opcode = SD_WRITE_EXTR_SINGLE; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + mmc_set_data_timeout(&data, card); + mmc_wait_for_req(host, &mrq); + + kfree(reg_buf); + + /* + * Note that, the SD card is allowed to signal busy on DAT0 up to 1s + * after the CMD49. Although, let's leave this to be managed by the + * caller. + */ + + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + + return 0; +} + static int sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset, u16 len, u8 *reg_buf) { @@ -1446,21 +1513,84 @@ static void mmc_sd_detect(struct mmc_host *host) } } +static int sd_can_poweroff_notify(struct mmc_card *card) +{ + return card->ext_power.feature_support & SD_EXT_POWER_OFF_NOTIFY; +} + +static int sd_busy_poweroff_notify_cb(void *cb_data, bool *busy) +{ + struct sd_busy_data *data = cb_data; + struct mmc_card *card = data->card; + int err; + + /* + * Read the status register for the power management function. It's at + * one byte offset and is one byte long. The Power Off Notification + * Ready is bit 0. + */ + err = sd_read_ext_reg(card, card->ext_power.fno, card->ext_power.page, + card->ext_power.offset + 1, 1, data->reg_buf); + if (err) { + pr_warn("%s: error %d reading status reg of PM func\n", + mmc_hostname(card->host), err); + return err; + } + + *busy = !(data->reg_buf[0] & BIT(0)); + return 0; +} + +static int sd_poweroff_notify(struct mmc_card *card) +{ + struct sd_busy_data cb_data; + u8 *reg_buf; + int err; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set the Power Off Notification bit in the power management settings + * register at 2 bytes offset. + */ + err = sd_write_ext_reg(card, card->ext_power.fno, card->ext_power.page, + card->ext_power.offset + 2, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Power Off Notify bit\n", + mmc_hostname(card->host), err); + goto out; + } + + cb_data.card = card; + cb_data.reg_buf = reg_buf; + err = __mmc_poll_for_busy(card, SD_POWEROFF_NOTIFY_TIMEOUT_MS, + &sd_busy_poweroff_notify_cb, &cb_data); + +out: + kfree(reg_buf); + return err; +} + static int _mmc_sd_suspend(struct mmc_host *host) { + struct mmc_card *card = host->card; int err = 0; mmc_claim_host(host); - if (mmc_card_suspended(host->card)) + if (mmc_card_suspended(card)) goto out; - if (!mmc_host_is_spi(host)) + if (sd_can_poweroff_notify(card)) + err = sd_poweroff_notify(card); + else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); if (!err) { mmc_power_off(host); - mmc_card_set_suspended(host->card); + mmc_card_set_suspended(card); } out: diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index 43bfc5c39ad4..6727576a8755 100644 --- a/include/linux/mmc/sd.h +++ b/include/linux/mmc/sd.h @@ -31,6 +31,7 @@ /* class 11 */ #define SD_READ_EXTR_SINGLE 48 /* adtc [31:0] R1 */ +#define SD_WRITE_EXTR_SINGLE 49 /* adtc [31:0] R1 */ /* OCR bit definitions */ #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ From 70b52f09080565030a530a784f1c9948a7f48ca3 Mon Sep 17 00:00:00 2001 From: Bean Huo Date: Tue, 4 May 2021 22:32:09 +0200 Subject: [PATCH 16/54] mmc: block: Disable CMDQ on the ioctl path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the eMMC Spec: "When command queuing is enabled (CMDQ Mode En bit in CMDQ_MODE_EN field is set to ‘1’) class 11 commands are the only method through which data transfer tasks can be issued. Existing data transfer commands, namely CMD18/CMD17 and CMD25/CMD24, are not supported when command queuing is enabled." which means if CMDQ is enabled, the FFU commands will not be supported. To fix this issue, just simply disable CMDQ on the ioctl path, and re-enable CMDQ once ioctl request is completed. Tested-by: Michael Brunner Signed-off-by: Bean Huo Acked-by: Adrian Hunter Fixes: 1e8e55b67030 (mmc: block: Add CQE support) Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210504203209.361597-1-huobean@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 689eb9afeeed..2518bc085659 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1004,6 +1004,12 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) switch (mq_rq->drv_op) { case MMC_DRV_OP_IOCTL: + if (card->ext_csd.cmdq_en) { + ret = mmc_cmdq_disable(card); + if (ret) + break; + } + fallthrough; case MMC_DRV_OP_IOCTL_RPMB: idata = mq_rq->drv_op_data; for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) { @@ -1014,6 +1020,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) /* Always switch back to main area after RPMB access */ if (rpmb_ioctl) mmc_blk_part_switch(card, 0); + else if (card->reenable_cmdq && !card->ext_csd.cmdq_en) + mmc_cmdq_enable(card); break; case MMC_DRV_OP_BOOT_WP: ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, From 8ae11edeb95682f6ab1983986c1daff3a00e01fc Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 6 May 2021 16:58:28 +0200 Subject: [PATCH 17/54] mmc: core: Move eMMC cache flushing to a new bus_ops callback To prepare to add internal cache management for SD cards, let's start by moving the eMMC specific code into a new ->flush_cache() bus_ops callback. In this way, it becomes straight forward to add the SD specific parts, as subsequent changes are about to show. Signed-off-by: Ulf Hansson Reviewed-by: Avri Altman Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210506145829.198823-2-ulf.hansson@linaro.org --- drivers/mmc/core/block.c | 2 +- drivers/mmc/core/core.h | 9 +++++++++ drivers/mmc/core/mmc.c | 25 +++++++++++++++++++++++-- drivers/mmc/core/mmc_ops.c | 21 --------------------- drivers/mmc/core/mmc_ops.h | 1 - 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 2518bc085659..f85e107895da 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1167,7 +1167,7 @@ static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) struct mmc_card *card = md->queue.card; int ret = 0; - ret = mmc_flush_cache(card); + ret = mmc_flush_cache(card->host); blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK); } diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index db3c9c68875d..0c4de2030b3f 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -30,6 +30,7 @@ struct mmc_bus_ops { int (*hw_reset)(struct mmc_host *); int (*sw_reset)(struct mmc_host *); bool (*cache_enabled)(struct mmc_host *); + int (*flush_cache)(struct mmc_host *); }; void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); @@ -172,4 +173,12 @@ static inline bool mmc_cache_enabled(struct mmc_host *host) return false; } +static inline int mmc_flush_cache(struct mmc_host *host) +{ + if (host->bus_ops->flush_cache) + return host->bus_ops->flush_cache(host); + + return 0; +} + #endif diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 13074aa1f605..838726b68ff3 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -28,6 +28,7 @@ #define DEFAULT_CMD6_TIMEOUT_MS 500 #define MIN_CACHE_EN_TIMEOUT_MS 1600 +#define CACHE_FLUSH_TIMEOUT_MS 30000 /* 30s */ static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, @@ -2036,6 +2037,25 @@ static bool _mmc_cache_enabled(struct mmc_host *host) host->card->ext_csd.cache_ctrl & 1; } +/* + * Flush the internal cache of the eMMC to non-volatile storage. + */ +static int _mmc_flush_cache(struct mmc_host *host) +{ + int err = 0; + + if (_mmc_cache_enabled(host)) { + err = mmc_switch(host->card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_FLUSH_CACHE, 1, + CACHE_FLUSH_TIMEOUT_MS); + if (err) + pr_err("%s: cache flush error %d\n", + mmc_hostname(host), err); + } + + return err; +} + static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; @@ -2047,7 +2067,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_card_suspended(host->card)) goto out; - err = mmc_flush_cache(host->card); + err = _mmc_flush_cache(host); if (err) goto out; @@ -2188,7 +2208,7 @@ static int _mmc_hw_reset(struct mmc_host *host) * In the case of recovery, we can't expect flushing the cache to work * always, but we have a go and ignore errors. */ - mmc_flush_cache(host->card); + _mmc_flush_cache(host); if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset && mmc_can_reset(card)) { @@ -2216,6 +2236,7 @@ static const struct mmc_bus_ops mmc_ops = { .shutdown = mmc_shutdown, .hw_reset = _mmc_hw_reset, .cache_enabled = _mmc_cache_enabled, + .flush_cache = _mmc_flush_cache, }; /* diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index b1da8f1950ee..af423acc4c88 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -20,7 +20,6 @@ #include "mmc_ops.h" #define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */ -#define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */ #define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */ static const u8 tuning_blk_pattern_4bit[] = { @@ -964,26 +963,6 @@ void mmc_run_bkops(struct mmc_card *card) } EXPORT_SYMBOL(mmc_run_bkops); -/* - * Flush the cache to the non-volatile storage. - */ -int mmc_flush_cache(struct mmc_card *card) -{ - int err = 0; - - if (mmc_cache_enabled(card->host)) { - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_FLUSH_CACHE, 1, - MMC_CACHE_FLUSH_TIMEOUT_MS); - if (err) - pr_err("%s: cache flush error %d\n", - mmc_hostname(card->host), err); - } - - return err; -} -EXPORT_SYMBOL(mmc_flush_cache); - static int mmc_cmdq_switch(struct mmc_card *card, bool enable) { u8 val = enable ? EXT_CSD_CMDQ_MODE_ENABLED : 0; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 2b1d730e56bf..c3c1d9c2577e 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -51,7 +51,6 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms); void mmc_run_bkops(struct mmc_card *card); -int mmc_flush_cache(struct mmc_card *card); int mmc_cmdq_enable(struct mmc_card *card); int mmc_cmdq_disable(struct mmc_card *card); int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms); From 3ae613765851cc2a651a42ce9d586078a899d8c8 Mon Sep 17 00:00:00 2001 From: Shubhankar Kuranagatti Date: Fri, 7 May 2021 12:05:28 +0530 Subject: [PATCH 18/54] drivers: memstick: core:ms_block.c: Fix alignment of block comment A * has been added to subsequent lines of block comment The closing */ has been shifted to a new line A new line has been give after declaration This is done to maintain code uniformity. Signed-off-by: Shubhankar Kuranagatti Link: https://lore.kernel.org/r/20210507063528.tvlbu2cwnlczgbga@kewl-virtual-machine Signed-off-by: Ulf Hansson --- drivers/memstick/core/ms_block.c | 37 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index 8004dd64d09a..d971acd98236 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -129,7 +129,7 @@ static int msb_sg_compare_to_buffer(struct scatterlist *sg, * Each zone consists of 512 eraseblocks, out of which in first * zone 494 are used and 496 are for all following zones. * Therefore zone #0 hosts blocks 0-493, zone #1 blocks 494-988, etc... -*/ + */ static int msb_get_zone_from_lba(int lba) { if (lba < 494) @@ -348,8 +348,9 @@ again: switch (msb->state) { case MSB_RP_SEND_BLOCK_ADDRESS: /* msb_write_regs sometimes "fails" because it needs to update - the reg window, and thus it returns request for that. - Then we stay in this state and retry */ + * the reg window, and thus it returns request for that. + * Then we stay in this state and retry + */ if (!msb_write_regs(msb, offsetof(struct ms_register, param), sizeof(struct ms_param_register), @@ -368,7 +369,8 @@ again: case MSB_RP_SEND_INT_REQ: msb->state = MSB_RP_RECEIVE_INT_REQ_RESULT; /* If dont actually need to send the int read request (only in - serial mode), then just fall through */ + * serial mode), then just fall through + */ if (msb_read_int_reg(msb, -1)) return 0; fallthrough; @@ -702,7 +704,8 @@ static int h_msb_parallel_switch(struct memstick_dev *card, case MSB_PS_SWICH_HOST: /* Set parallel interface on our side + send a dummy request - to see if card responds */ + * to see if card responds + */ host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); memstick_init_req(mrq, MS_TPC_GET_INT, NULL, 1); msb->state = MSB_PS_CONFIRM; @@ -821,6 +824,7 @@ static int msb_mark_page_bad(struct msb_data *msb, int pba, int page) static int msb_erase_block(struct msb_data *msb, u16 pba) { int error, try; + if (msb->read_only) return -EROFS; @@ -997,6 +1001,7 @@ static int msb_write_block(struct msb_data *msb, u16 pba, u32 lba, struct scatterlist *sg, int offset) { int error, current_try = 1; + BUG_ON(sg->length < msb->page_size); if (msb->read_only) @@ -1045,11 +1050,12 @@ static int msb_write_block(struct msb_data *msb, error = msb_run_state_machine(msb, h_msb_write_block); /* Sector we just wrote to is assumed erased since its pba - was erased. If it wasn't erased, write will succeed - and will just clear the bits that were set in the block - thus test that what we have written, - matches what we expect. - We do trust the blocks that we erased */ + * was erased. If it wasn't erased, write will succeed + * and will just clear the bits that were set in the block + * thus test that what we have written, + * matches what we expect. + * We do trust the blocks that we erased + */ if (!error && (verify_writes || !test_bit(pba, msb->erased_blocks_bitmap))) error = msb_verify_block(msb, pba, sg, offset); @@ -1493,6 +1499,7 @@ static int msb_ftl_scan(struct msb_data *msb) static void msb_cache_flush_timer(struct timer_list *t) { struct msb_data *msb = from_timer(msb, t, cache_flush_timer); + msb->need_flush_cache = true; queue_work(msb->io_queue, &msb->io_work); } @@ -1673,7 +1680,8 @@ static int msb_cache_read(struct msb_data *msb, int lba, * This table content isn't that importaint, * One could put here different values, providing that they still * cover whole disk. - * 64 MB entry is what windows reports for my 64M memstick */ + * 64 MB entry is what windows reports for my 64M memstick + */ static const struct chs_entry chs_table[] = { /* size sectors cylynders heads */ @@ -1706,8 +1714,9 @@ static int msb_init_card(struct memstick_dev *card) return error; /* Due to a bug in Jmicron driver written by Alex Dubov, - its serial mode barely works, - so we switch to parallel mode right away */ + * its serial mode barely works, + * so we switch to parallel mode right away + */ if (host->caps & MEMSTICK_CAP_PAR4) msb_switch_to_parallel(msb); @@ -2033,6 +2042,7 @@ static blk_status_t msb_queue_rq(struct blk_mq_hw_ctx *hctx, static int msb_check_card(struct memstick_dev *card) { struct msb_data *msb = memstick_get_drvdata(card); + return (msb->card_dead == 0); } @@ -2333,6 +2343,7 @@ static struct memstick_driver msb_driver = { static int __init msb_init(void) { int rc = memstick_register_driver(&msb_driver); + if (rc) pr_err("failed to register memstick driver (error %d)\n", rc); From 2f9ae69e5267f53e89e296fccee291975a85f0eb Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Sat, 8 May 2021 10:03:21 +0800 Subject: [PATCH 19/54] mmc: usdhi6rol0: fix error return code in usdhi6_probe() Fix to return a negative error code from the error handling case instead of 0, as done elsewhere in this function. Fixes: 75fa9ea6e3c0 ("mmc: add a driver for the Renesas usdhi6rol0 SD/SDIO host controller") Reported-by: Hulk Robot Signed-off-by: Zhen Lei Link: https://lore.kernel.org/r/20210508020321.1677-1-thunder.leizhen@huawei.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/usdhi6rol0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 615f3d008af1..b9b79b1089a0 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1801,6 +1801,7 @@ static int usdhi6_probe(struct platform_device *pdev) version = usdhi6_read(host, USDHI6_VERSION); if ((version & 0xfff) != 0xa0d) { + ret = -EPERM; dev_err(dev, "Version not recognized %x\n", version); goto e_clk_off; } From d03be8c1c7de2ae9ebdcc34b11f9089e2349709d Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Tue, 11 May 2021 17:33:29 +0800 Subject: [PATCH 20/54] mmc: jz4740: Remove redundant error printing in jz4740_mmc_probe() When devm_ioremap_resource() fails, a clear enough error message will be printed by its subfunction __devm_ioremap_resource(). The error information contains the device name, failure cause, and possibly resource information. Therefore, remove the error printing here to simplify code and reduce the binary size. Reported-by: Hulk Robot Signed-off-by: Zhen Lei Link: https://lore.kernel.org/r/20210511093329.4670-1-thunder.leizhen@huawei.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/jz4740_mmc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index b3c636edbb46..861ff6d9661a 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -1013,7 +1013,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev) host->base = devm_ioremap_resource(&pdev->dev, host->mem_res); if (IS_ERR(host->base)) { ret = PTR_ERR(host->base); - dev_err(&pdev->dev, "Failed to ioremap base memory\n"); goto err_free_host; } From 110a8688c6cd11e81a1805d5dc24a7a6b5d86a18 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 May 2021 14:13:21 +0200 Subject: [PATCH 21/54] dt-bindings: mmc: renesas,mmcif: Convert to json-schema Convert the Renesas Multi Media Card Interface (MMCIF) Device Tree binding documentation to json-schema. Document missing properties. Update the example to match reality. Signed-off-by: Geert Uytterhoeven Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/04b97315fed0f4f512356b68f9f5bb6ed7adc41f.1620648698.git.geert+renesas@glider.be Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/renesas,mmcif.txt | 53 ------- .../bindings/mmc/renesas,mmcif.yaml | 135 ++++++++++++++++++ 2 files changed, 135 insertions(+), 53 deletions(-) delete mode 100644 Documentation/devicetree/bindings/mmc/renesas,mmcif.txt create mode 100644 Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml diff --git a/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt b/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt deleted file mode 100644 index 291532ac0446..000000000000 --- a/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt +++ /dev/null @@ -1,53 +0,0 @@ -* Renesas Multi Media Card Interface (MMCIF) Controller - -This file documents differences between the core properties in mmc.txt -and the properties used by the MMCIF device. - - -Required properties: - -- compatible: should be "renesas,mmcif-", "renesas,sh-mmcif" as a - fallback. Examples with are: - - "renesas,mmcif-r7s72100" for the MMCIF found in r7s72100 SoCs - - "renesas,mmcif-r8a73a4" for the MMCIF found in r8a73a4 SoCs - - "renesas,mmcif-r8a7740" for the MMCIF found in r8a7740 SoCs - - "renesas,mmcif-r8a7742" for the MMCIF found in r8a7742 SoCs - - "renesas,mmcif-r8a7743" for the MMCIF found in r8a7743 SoCs - - "renesas,mmcif-r8a7744" for the MMCIF found in r8a7744 SoCs - - "renesas,mmcif-r8a7745" for the MMCIF found in r8a7745 SoCs - - "renesas,mmcif-r8a7778" for the MMCIF found in r8a7778 SoCs - - "renesas,mmcif-r8a7790" for the MMCIF found in r8a7790 SoCs - - "renesas,mmcif-r8a7791" for the MMCIF found in r8a7791 SoCs - - "renesas,mmcif-r8a7793" for the MMCIF found in r8a7793 SoCs - - "renesas,mmcif-r8a7794" for the MMCIF found in r8a7794 SoCs - - "renesas,mmcif-sh73a0" for the MMCIF found in sh73a0 SoCs - -- interrupts: Some SoCs have only 1 shared interrupt, while others have either - 2 or 3 individual interrupts (error, int, card detect). Below is the number - of interrupts for each SoC: - 1: r8a73a4, r8a7742, r8a7743, r8a7744, r8a7745, r8a7778, r8a7790, r8a7791, - r8a7793, r8a7794 - 2: r8a7740, sh73a0 - 3: r7s72100 - -- clocks: reference to the functional clock - -- dmas: reference to the DMA channels, one per channel name listed in the - dma-names property. -- dma-names: must contain "tx" for the transmit DMA channel and "rx" for the - receive DMA channel. -- max-frequency: Maximum operating clock frequency, driver uses default clock - frequency if it is not set. - - -Example: R8A7790 (R-Car H2) MMCIF0 - - mmcif0: mmc@ee200000 { - compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif"; - reg = <0 0xee200000 0 0x80>; - interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>; - dmas = <&dmac0 0xd1>, <&dmac0 0xd2>; - dma-names = "tx", "rx"; - max-frequency = <97500000>; - }; diff --git a/Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml b/Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml new file mode 100644 index 000000000000..c36ba561c387 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml @@ -0,0 +1,135 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/renesas,mmcif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas Multi Media Card Interface (MMCIF) Controller + +maintainers: + - Wolfram Sang + +allOf: + - $ref: "mmc-controller.yaml" + +properties: + compatible: + items: + - enum: + - renesas,mmcif-r7s72100 # RZ/A1H + - renesas,mmcif-r8a73a4 # R-Mobile APE6 + - renesas,mmcif-r8a7740 # R-Mobile A1 + - renesas,mmcif-r8a7742 # RZ/G1H + - renesas,mmcif-r8a7743 # RZ/G1M + - renesas,mmcif-r8a7744 # RZ/G1N + - renesas,mmcif-r8a7745 # RZ/G1E + - renesas,mmcif-r8a7778 # R-Car M1A + - renesas,mmcif-r8a7790 # R-Car H2 + - renesas,mmcif-r8a7791 # R-Car M2-W + - renesas,mmcif-r8a7793 # R-Car M2-N + - renesas,mmcif-r8a7794 # R-Car E2 + - renesas,mmcif-sh73a0 # SH-Mobile AG5 + - const: renesas,sh-mmcif + + reg: + maxItems: 1 + + interrupts: true + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + dmas: + minItems: 2 + maxItems: 4 + description: + Must contain a list of pairs of references to DMA specifiers, one for + transmission, and one for reception. + + dma-names: + minItems: 2 + maxItems: 4 + items: + enum: + - tx + - rx + + max-frequency: true + +required: + - compatible + - reg + - interrupts + - clocks + - power-domains + +if: + properties: + compatible: + contains: + const: renesas,mmcif-r7s72100 +then: + properties: + interrupts: + items: + - description: Error interrupt + - description: Normal operation interrupt + - description: Card detection interrupt +else: + if: + properties: + compatible: + contains: + enum: + - renesas,mmcif-r8a7740 + - renesas,mmcif-sh73a0 + then: + properties: + interrupts: + items: + - description: Error interrupt + - description: Normal operation interrupt + else: + if: + properties: + compatible: + contains: + enum: + - renesas,mmcif-r8a73a4 + - renesas,mmcif-r8a7778 + then: + properties: + interrupts: + maxItems: 1 + else: + properties: + interrupts: + maxItems: 1 + required: + - resets + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + mmcif0: mmc@ee200000 { + compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif"; + reg = <0xee200000 0x80>; + interrupts = ; + clocks = <&cpg CPG_MOD 315>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 315>; + dmas = <&dmac0 0xd1>, <&dmac0 0xd2>, <&dmac1 0xd1>, <&dmac1 0xd2>; + dma-names = "tx", "rx", "tx", "rx"; + max-frequency = <97500000>; + }; From 34dd3ccccab0b93ebdf7ecde138814d121f72e98 Mon Sep 17 00:00:00 2001 From: Ben Chuang Date: Tue, 11 May 2021 14:18:35 +0800 Subject: [PATCH 22/54] mmc: sdhci-pci-gli: Fine tune GL9763E L1 entry delay Fine tune the value to 21us in order to improve read/write performance. Signed-off-by: Ben Chuang Link: https://lore.kernel.org/r/20210511061835.5559-1-benchuanggli@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-gli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 061618aa247f..4fd99c1e82ba 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -94,7 +94,7 @@ #define PCIE_GLI_9763E_CFG2 0x8A4 #define GLI_9763E_CFG2_L1DLY GENMASK(28, 19) -#define GLI_9763E_CFG2_L1DLY_MID 0x50 +#define GLI_9763E_CFG2_L1DLY_MID 0x54 #define PCIE_GLI_9763E_MMC_CTRL 0x960 #define GLI_9763E_HS400_SLOW BIT(3) @@ -847,7 +847,7 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, &value); value &= ~GLI_9763E_CFG2_L1DLY; - /* set ASPM L1 entry delay to 20us */ + /* set ASPM L1 entry delay to 21us */ value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID); pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value); From 130206a615a9831a65e186484a5a332f9f6d29c8 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 11 May 2021 12:13:59 +0200 Subject: [PATCH 23/54] mmc: core: Add support for cache ctrl for SD cards In SD spec v6.x the SD function extension registers for performance enhancements were introduced. As a part of this an optional internal cache on the SD card, can be used to improve performance. The let the SD card use the cache, the host needs to enable it and manage flushing of the cache, so let's add support for this. Note that for an SD card supporting the cache it's mandatory for it, to also support the poweroff notification feature. According to the SD spec, if the cache has been enabled and a poweroff notification is sent to the card, that implicitly also means that the card should flush its internal cache. Therefore, dealing with cache flushing for REQ_OP_FLUSH block requests is sufficient. Reviewed-by: Linus Walleij Signed-off-by: Ulf Hansson Reviewed-by: Avri Altman Link: https://lore.kernel.org/r/20210511101359.83521-1-ulf.hansson@linaro.org --- drivers/mmc/core/mmc_ops.c | 1 + drivers/mmc/core/mmc_ops.h | 1 + drivers/mmc/core/sd.c | 100 +++++++++++++++++++++++++++++++++++++ include/linux/mmc/card.h | 1 + 4 files changed, 103 insertions(+) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index af423acc4c88..3c58f6d0f482 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -456,6 +456,7 @@ static int mmc_busy_cb(void *cb_data, bool *busy) err = R1_STATUS(status) ? -EIO : 0; break; case MMC_BUSY_HPI: + case MMC_BUSY_EXTR_SINGLE: break; default: err = -EINVAL; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index c3c1d9c2577e..41ab4f573a31 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -14,6 +14,7 @@ enum mmc_busy_cmd { MMC_BUSY_CMD6, MMC_BUSY_ERASE, MMC_BUSY_HPI, + MMC_BUSY_EXTR_SINGLE, }; struct mmc_host; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index bd40c682d264..781c1e24308c 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -67,6 +67,7 @@ static const unsigned int sd_au_size[] = { }) #define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000 +#define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000 struct sd_busy_data { struct mmc_card *card; @@ -1287,6 +1288,96 @@ out: return err; } +static bool sd_cache_enabled(struct mmc_host *host) +{ + return host->card->ext_perf.feature_enabled & SD_EXT_PERF_CACHE; +} + +static int sd_flush_cache(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + u8 *reg_buf, fno, page; + u16 offset; + int err; + + if (!sd_cache_enabled(host)) + return 0; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set Flush Cache at bit 0 in the performance enhancement register at + * 261 bytes offset. + */ + fno = card->ext_perf.fno; + page = card->ext_perf.page; + offset = card->ext_perf.offset + 261; + + err = sd_write_ext_reg(card, fno, page, offset, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Cache Flush bit\n", + mmc_hostname(host), err); + goto out; + } + + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (err) + goto out; + + /* + * Read the Flush Cache bit. The card shall reset it, to confirm that + * it's has completed the flushing of the cache. + */ + err = sd_read_ext_reg(card, fno, page, offset, 1, reg_buf); + if (err) { + pr_warn("%s: error %d reading Cache Flush bit\n", + mmc_hostname(host), err); + goto out; + } + + if (reg_buf[0] & BIT(0)) + err = -ETIMEDOUT; +out: + kfree(reg_buf); + return err; +} + +static int sd_enable_cache(struct mmc_card *card) +{ + u8 *reg_buf; + int err; + + card->ext_perf.feature_enabled &= ~SD_EXT_PERF_CACHE; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set Cache Enable at bit 0 in the performance enhancement register at + * 260 bytes offset. + */ + err = sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page, + card->ext_perf.offset + 260, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Cache Enable bit\n", + mmc_hostname(card->host), err); + goto out; + } + + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (!err) + card->ext_perf.feature_enabled |= SD_EXT_PERF_CACHE; + +out: + kfree(reg_buf); + return err; +} + /* * Handle the detection and initialisation of a card. * @@ -1442,6 +1533,13 @@ retry: goto free_card; } + /* Enable internal SD cache if supported. */ + if (card->ext_perf.feature_support & SD_EXT_PERF_CACHE) { + err = sd_enable_cache(card); + if (err) + goto free_card; + } + if (host->cqe_ops && !host->cqe_enabled) { err = host->cqe_ops->cqe_enable(host, card); if (!err) { @@ -1694,6 +1792,8 @@ static const struct mmc_bus_ops mmc_sd_ops = { .alive = mmc_sd_alive, .shutdown = mmc_sd_suspend, .hw_reset = mmc_sd_hw_reset, + .cache_enabled = sd_cache_enabled, + .flush_cache = sd_flush_cache, }; /* diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 2867af0635f8..74e6c0624d27 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -196,6 +196,7 @@ struct sd_ext_reg { u8 page; u16 offset; u8 rev; + u8 feature_enabled; u8 feature_support; /* Power Management Function. */ #define SD_EXT_POWER_OFF_NOTIFY (1<<0) From 4d895de3505f7eb9734f679a340c976f8949ab43 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 10 May 2021 21:03:58 +0200 Subject: [PATCH 24/54] dt-bindings: mmc: add no-mmc-hs400 flag HS400 requires a data strobe line in addition to the usual MMC signal lines. If a board design neglects to wire up this signal, HS400 mode is not available, even if both the controller and the eMMC are claiming to support this mode. Add a DT flag to allow boards to disable the HS400 support in this case. Signed-off-by: Lucas Stach Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210510190400.105162-1-l.stach@pengutronix.de Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/mmc-controller.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml index e141330c1114..ac80d09df3a9 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml @@ -220,6 +220,11 @@ properties: description: eMMC HS400 enhanced strobe mode is supported + no-mmc-hs400: + $ref: /schemas/types.yaml#/definitions/flag + description: + All eMMC HS400 modes are not supported. + dsr: description: Value the card Driver Stage Register (DSR) should be programmed From 2991ad76d2537a4ebe7132d087cdbc76377da302 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 10 May 2021 21:03:59 +0200 Subject: [PATCH 25/54] mmc: sdhci-esdhc-imx: advertise HS400 mode through MMC caps Instead of having an indirection through the SDHCI layer and emulating a capability bit, that isn't there in hardware, do the same same thing as with HS400_ES and advertise the support for HS400 directly through the MMC caps. Signed-off-by: Lucas Stach Reviewed-by: Haibo Chen Link: https://lore.kernel.org/r/20210510190400.105162-2-l.stach@pengutronix.de Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index b991cf0e60c5..fba4a963d12e 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -427,9 +427,6 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) | FIELD_PREP(SDHCI_RETUNING_MODE_MASK, SDHCI_TUNING_MODE_3); - if (imx_data->socdata->flags & ESDHC_FLAG_HS400) - val |= SDHCI_SUPPORT_HS400; - /* * Do not advertise faster UHS modes if there are no * pinctrl states for 100MHz/200MHz. @@ -1591,7 +1588,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; if (imx_data->socdata->flags & ESDHC_FLAG_HS400) - host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400; + host->mmc->caps2 |= MMC_CAP2_HS400; if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; From f722e650d965307f8c4c24cf4edc166b6abe9dc6 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 10 May 2021 21:04:00 +0200 Subject: [PATCH 26/54] mmc: core: add support for disabling HS400 mode via DT On some boards the data strobe line isn't wired up, rendering HS400 support broken, even if both the controller and the eMMC claim to support it. Allow to disable HS400 mode via DT. Signed-off-by: Lucas Stach Link: https://lore.kernel.org/r/20210510190400.105162-3-l.stach@pengutronix.de Signed-off-by: Ulf Hansson --- drivers/mmc/core/host.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 0b0577990ddc..eda4a1892c33 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -388,6 +388,9 @@ int mmc_of_parse(struct mmc_host *host) host->caps2 |= MMC_CAP2_NO_SD; if (device_property_read_bool(dev, "no-mmc")) host->caps2 |= MMC_CAP2_NO_MMC; + if (device_property_read_bool(dev, "no-mmc-hs400")) + host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | + MMC_CAP2_HS400_ES); /* Must be after "non-removable" check */ if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) { From 42933c8aa14be1caa9eda41f65cde8a3a95d3e39 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Tue, 11 May 2021 12:39:45 -0400 Subject: [PATCH 27/54] memstick: rtsx_usb_ms: fix UAF This patch fixes the following issues: 1. memstick_free_host() will free the host, so the use of ms_dev(host) after it will be a problem. To fix this, move memstick_free_host() after when we are done with ms_dev(host). 2. In rtsx_usb_ms_drv_remove(), pm need to be disabled before we remove and free host otherwise memstick_check will be called and UAF will happen. [ 11.351173] BUG: KASAN: use-after-free in rtsx_usb_ms_drv_remove+0x94/0x140 [rtsx_usb_ms] [ 11.357077] rtsx_usb_ms_drv_remove+0x94/0x140 [rtsx_usb_ms] [ 11.357376] platform_remove+0x2a/0x50 [ 11.367531] Freed by task 298: [ 11.368537] kfree+0xa4/0x2a0 [ 11.368711] device_release+0x51/0xe0 [ 11.368905] kobject_put+0xa2/0x120 [ 11.369090] rtsx_usb_ms_drv_remove+0x8c/0x140 [rtsx_usb_ms] [ 11.369386] platform_remove+0x2a/0x50 [ 12.038408] BUG: KASAN: use-after-free in __mutex_lock.isra.0+0x3ec/0x7c0 [ 12.045432] mutex_lock+0xc9/0xd0 [ 12.046080] memstick_check+0x6a/0x578 [memstick] [ 12.046509] process_one_work+0x46d/0x750 [ 12.052107] Freed by task 297: [ 12.053115] kfree+0xa4/0x2a0 [ 12.053272] device_release+0x51/0xe0 [ 12.053463] kobject_put+0xa2/0x120 [ 12.053647] rtsx_usb_ms_drv_remove+0xc4/0x140 [rtsx_usb_ms] [ 12.053939] platform_remove+0x2a/0x50 Signed-off-by: Tong Zhang Co-developed-by: Ulf Hansson Link: https://lore.kernel.org/r/20210511163944.1233295-1-ztong0001@gmail.com Signed-off-by: Ulf Hansson --- drivers/memstick/host/rtsx_usb_ms.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c index 102dbb8080da..29271ad4728a 100644 --- a/drivers/memstick/host/rtsx_usb_ms.c +++ b/drivers/memstick/host/rtsx_usb_ms.c @@ -799,9 +799,9 @@ static int rtsx_usb_ms_drv_probe(struct platform_device *pdev) return 0; err_out: - memstick_free_host(msh); pm_runtime_disable(ms_dev(host)); pm_runtime_put_noidle(ms_dev(host)); + memstick_free_host(msh); return err; } @@ -828,9 +828,6 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) } mutex_unlock(&host->host_mutex); - memstick_remove_host(msh); - memstick_free_host(msh); - /* Balance possible unbalanced usage count * e.g. unconditional module removal */ @@ -838,10 +835,11 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) pm_runtime_put(ms_dev(host)); pm_runtime_disable(ms_dev(host)); - platform_set_drvdata(pdev, NULL); - + memstick_remove_host(msh); dev_dbg(ms_dev(host), ": Realtek USB Memstick controller has been removed\n"); + memstick_free_host(msh); + platform_set_drvdata(pdev, NULL); return 0; } From 8931acce6b771dfe01d23e6d36e0b09f717c90c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Mon, 17 May 2021 01:05:48 +0200 Subject: [PATCH 28/54] dt-bindings: mmc: rockchip-dw-mshc: Add Rockchip RK1808 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a compatible string for Rockchip RK1808 SoC. Signed-off-by: Andreas Färber Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210516230551.12469-7-afaerber@suse.de Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml index eaa3b0ef24f6..54fb59820d2b 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml @@ -30,6 +30,7 @@ properties: - items: - enum: - rockchip,px30-dw-mshc + - rockchip,rk1808-dw-mshc - rockchip,rk3036-dw-mshc - rockchip,rk3228-dw-mshc - rockchip,rk3308-dw-mshc From 151071351bb6f3d1861e99a22c4cebadf81911a0 Mon Sep 17 00:00:00 2001 From: Yue Hu Date: Mon, 17 May 2021 18:09:00 +0800 Subject: [PATCH 29/54] mmc: mediatek: use data instead of mrq parameter from msdc_{un}prepare_data() We already have 'mrq->data' before calling these two functions, no need to find it again via 'mrq->data' internally. Also remove local data variable accordingly. Signed-off-by: Yue Hu Link: https://lore.kernel.org/r/20210517100900.1620-1-zbestahu@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 898ed1b023df..c4db944ad9be 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -724,10 +724,8 @@ static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, writel(lower_32_bits(dma->gpd_addr), host->base + MSDC_DMA_SA); } -static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq) +static void msdc_prepare_data(struct msdc_host *host, struct mmc_data *data) { - struct mmc_data *data = mrq->data; - if (!(data->host_cookie & MSDC_PREPARE_FLAG)) { data->host_cookie |= MSDC_PREPARE_FLAG; data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len, @@ -735,10 +733,8 @@ static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq) } } -static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq) +static void msdc_unprepare_data(struct msdc_host *host, struct mmc_data *data) { - struct mmc_data *data = mrq->data; - if (data->host_cookie & MSDC_ASYNC_FLAG) return; @@ -1140,7 +1136,7 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq) msdc_track_cmd_data(host, mrq->cmd, mrq->data); if (mrq->data) - msdc_unprepare_data(host, mrq); + msdc_unprepare_data(host, mrq->data); if (host->error) msdc_reset_hw(host); mmc_request_done(mmc_from_priv(host), mrq); @@ -1311,7 +1307,7 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) host->mrq = mrq; if (mrq->data) - msdc_prepare_data(host, mrq); + msdc_prepare_data(host, mrq->data); /* if SBC is required, we have HW option and SW option. * if HW option is enabled, and SBC does not have "special" flags, @@ -1332,7 +1328,7 @@ static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) if (!data) return; - msdc_prepare_data(host, mrq); + msdc_prepare_data(host, data); data->host_cookie |= MSDC_ASYNC_FLAG; } @@ -1340,14 +1336,14 @@ static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, int err) { struct msdc_host *host = mmc_priv(mmc); - struct mmc_data *data; + struct mmc_data *data = mrq->data; - data = mrq->data; if (!data) return; + if (data->host_cookie) { data->host_cookie &= ~MSDC_ASYNC_FLAG; - msdc_unprepare_data(host, mrq); + msdc_unprepare_data(host, data); } } From f0ed43edb4cb793f4d9909feef32510ed77ed35a Mon Sep 17 00:00:00 2001 From: Yue Hu Date: Mon, 17 May 2021 18:54:32 +0800 Subject: [PATCH 30/54] mmc: mediatek: remove useless data parameter from msdc_data_xfer_next() We do not use the 'data' in msdc_data_xfer_next(). Signed-off-by: Yue Hu Link: https://lore.kernel.org/r/20210517105432.1682-1-zbestahu@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index c4db944ad9be..4dfc246c5f95 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -1347,8 +1347,7 @@ static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, } } -static void msdc_data_xfer_next(struct msdc_host *host, - struct mmc_request *mrq, struct mmc_data *data) +static void msdc_data_xfer_next(struct msdc_host *host, struct mmc_request *mrq) { if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && !mrq->stop->error && !mrq->sbc) @@ -1407,7 +1406,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events, (int)data->error, data->bytes_xfered); } - msdc_data_xfer_next(host, mrq, data); + msdc_data_xfer_next(host, mrq); done = true; } return done; From 1e9daaf616a2f053eb80e20a84b47ebf2d5e20d3 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 19 May 2021 10:37:12 -0500 Subject: [PATCH 31/54] dt-bindings: mmc: Clean-up examples to match documented bindings The "sdhci" compatible is not documented though used as a fallback in a few cases. It is also not supported by a Linux driver. Just remove the example as part of ridding examples of undocumented bindings. The "brcm,bcm43xx-fmac" compatible is also not documented. Update the example to use one of the correct ones, "brcm,bcm4329-fmac", instead and use a device class based nodename. Cc: Ulf Hansson Cc: linux-mmc@vger.kernel.org Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20210519153712.3146025-1-robh@kernel.org Signed-off-by: Ulf Hansson --- .../bindings/mmc/mmc-controller.yaml | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml index ac80d09df3a9..25ac8e200970 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml @@ -362,22 +362,6 @@ dependencies: additionalProperties: true examples: - - | - mmc@ab000000 { - compatible = "sdhci"; - reg = <0xab000000 0x200>; - interrupts = <23>; - bus-width = <4>; - cd-gpios = <&gpio 69 0>; - cd-inverted; - wp-gpios = <&gpio 70 0>; - max-frequency = <50000000>; - keep-power-in-suspend; - wakeup-source; - mmc-pwrseq = <&sdhci0_pwrseq>; - clk-phase-sd-hs = <63>, <72>; - }; - - | mmc3: mmc@1c12000 { #address-cells = <1>; @@ -390,9 +374,9 @@ examples: non-removable; mmc-pwrseq = <&sdhci0_pwrseq>; - brcmf: bcrmf@1 { + brcmf: wifi@1 { reg = <1>; - compatible = "brcm,bcm43xx-fmac"; + compatible = "brcm,bcm4329-fmac"; interrupt-parent = <&pio>; interrupts = <10 8>; interrupt-names = "host-wake"; From 47d23c95fe0518b6e4cf7d7f6829987f377bd0d3 Mon Sep 17 00:00:00 2001 From: Yue Hu Date: Thu, 20 May 2021 18:13:30 +0800 Subject: [PATCH 32/54] mmc: cqhci: fix typo 'descritors' -> 'descriptors' Signed-off-by: Yue Hu Link: https://lore.kernel.org/r/20210520101330.2255-1-zbestahu@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/cqhci-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c index 93b0432bb601..54f4f9ad249d 100644 --- a/drivers/mmc/host/cqhci-core.c +++ b/drivers/mmc/host/cqhci-core.c @@ -146,7 +146,7 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host) } /* - * The allocated descriptor table for task, link & transfer descritors + * The allocated descriptor table for task, link & transfer descriptors * looks like: * |----------| * |task desc | |->|----------| From 83c49302566ea7328e6962fb81ceada2c93486b9 Mon Sep 17 00:00:00 2001 From: Yue Hu Date: Fri, 21 May 2021 11:44:32 +0800 Subject: [PATCH 33/54] mmc: cqhci: introduce get_trans_desc_offset() The same calculation to get transfer descriptor offset is already used at 3 different locations. Let's create a new helper to simplify code. Signed-off-by: Yue Hu Link: https://lore.kernel.org/r/20210521034432.2321-1-zbestahu@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/cqhci-core.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c index 54f4f9ad249d..38559a956330 100644 --- a/drivers/mmc/host/cqhci-core.c +++ b/drivers/mmc/host/cqhci-core.c @@ -45,17 +45,23 @@ static inline u8 *get_link_desc(struct cqhci_host *cq_host, u8 tag) return desc + cq_host->task_desc_len; } +static inline size_t get_trans_desc_offset(struct cqhci_host *cq_host, u8 tag) +{ + return cq_host->trans_desc_len * cq_host->mmc->max_segs * tag; +} + static inline dma_addr_t get_trans_desc_dma(struct cqhci_host *cq_host, u8 tag) { - return cq_host->trans_desc_dma_base + - (cq_host->mmc->max_segs * tag * - cq_host->trans_desc_len); + size_t offset = get_trans_desc_offset(cq_host, tag); + + return cq_host->trans_desc_dma_base + offset; } static inline u8 *get_trans_desc(struct cqhci_host *cq_host, u8 tag) { - return cq_host->trans_desc_base + - (cq_host->trans_desc_len * cq_host->mmc->max_segs * tag); + size_t offset = get_trans_desc_offset(cq_host, tag); + + return cq_host->trans_desc_base + offset; } static void setup_trans_desc(struct cqhci_host *cq_host, u8 tag) @@ -194,8 +200,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) cq_host->desc_size = cq_host->slot_sz * cq_host->num_slots; - cq_host->data_size = cq_host->trans_desc_len * cq_host->mmc->max_segs * - cq_host->mmc->cqe_qdepth; + cq_host->data_size = get_trans_desc_offset(cq_host, cq_host->mmc->cqe_qdepth); pr_debug("%s: cqhci: desc_size: %zu data_sz: %zu slot-sz: %d\n", mmc_hostname(cq_host->mmc), cq_host->desc_size, cq_host->data_size, From 05335af1e82a3ce2a7d410c7b1695a3c4ec37ea9 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Thu, 20 May 2021 20:21:44 +0800 Subject: [PATCH 34/54] mmc: core: Use pm_runtime_resume_and_get() to replace open coding use pm_runtime_resume_and_get() to replace pm_runtime_get_sync and pm_runtime_put_noidle. this change is just to simplify the code, no actual functional changes Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1621513304-27824-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 3eb94ac2712e..68edf7a615be 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -937,11 +937,9 @@ static void mmc_sdio_detect(struct mmc_host *host) /* Make sure card is powered before detecting it */ if (host->caps & MMC_CAP_POWER_OFF_CARD) { - err = pm_runtime_get_sync(&host->card->dev); - if (err < 0) { - pm_runtime_put_noidle(&host->card->dev); + err = pm_runtime_resume_and_get(&host->card->dev); + if (err < 0) goto out; - } } mmc_claim_host(host); From 07e70346e21eb8f018c8478cc4881ad9026bb12e Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Fri, 21 May 2021 08:59:35 +0800 Subject: [PATCH 35/54] mmc: sdhci_am654: Use pm_runtime_resume_and_get() to replace open coding use pm_runtime_resume_and_get() to replace pm_runtime_get_sync and pm_runtime_put_noidle. this change is just to simplify the code, no actual functional changes. Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1621558775-31185-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 1fad6e442688..f654afbe8e83 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -809,11 +809,9 @@ static int sdhci_am654_probe(struct platform_device *pdev) /* Clocks are enabled using pm_runtime */ pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) goto pm_runtime_disable; - } base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(base)) { From 809ae4e1ca0a719db29ed747fc2febf099a77b9f Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Fri, 21 May 2021 09:02:45 +0800 Subject: [PATCH 36/54] mmc: sdhci-omap: Use pm_runtime_resume_and_get() to replace open coding use pm_runtime_resume_and_get() to replace pm_runtime_get_sync and pm_runtime_put_noidle. this change is just to simplify the code, no actual functional changes. Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1621558965-34077-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-omap.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 7893fd3599b6..8f4d1f003f65 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -1173,10 +1173,9 @@ static int sdhci_omap_probe(struct platform_device *pdev) * as part of pm_runtime_get_sync. */ pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { + ret = pm_runtime_resume_and_get(dev); + if (ret) { dev_err(dev, "pm_runtime_get_sync failed\n"); - pm_runtime_put_noidle(dev); goto err_rpm_disable; } From 3c0bb3107703d2c58f7a0a7a2060bb57bc120326 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 21 May 2021 15:30:26 +0200 Subject: [PATCH 37/54] mmc: vub3000: fix control-request direction The direction of the pipe argument must match the request-type direction bit or control requests may fail depending on the host-controller-driver implementation. Fix the SET_ROM_WAIT_STATES request which erroneously used usb_rcvctrlpipe(). Fixes: 88095e7b473a ("mmc: Add new VUB300 USB-to-SD/SDIO/MMC driver") Cc: stable@vger.kernel.org # 3.0 Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210521133026.17296-1-johan@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/vub300.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index 739cf63ef6e2..4950d10d3a19 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -2279,7 +2279,7 @@ static int vub300_probe(struct usb_interface *interface, if (retval < 0) goto error5; retval = - usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0), + usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0), SET_ROM_WAIT_STATES, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, firmware_rom_wait_states, 0x0000, NULL, 0, HZ); From 7c45b2268e515b83772ff9c5d3db5f16ae3ca3bf Mon Sep 17 00:00:00 2001 From: Aviral Gupta Date: Sun, 23 May 2021 21:29:15 +0530 Subject: [PATCH 38/54] mmc: core: Add a missing SPDX license header Add the missing license header to drivers/mmc/core/block.c Signed-off-by: Aviral Gupta Link: https://lore.kernel.org/r/20210523155914.5200-1-shiv14112001@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index f85e107895da..88f4c215caa6 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Block driver for media (i.e., flash cards) * From dd646d982cf9b3b0c04c6f418bb91c275ce86336 Mon Sep 17 00:00:00 2001 From: Steven Lee Date: Mon, 24 May 2021 15:32:56 +0800 Subject: [PATCH 39/54] mmc: sdhci-of-aspeed: Configure the SDHCIs as specified by the devicetree. The hardware provides capability configuration registers for each SDHCI in the global configuration space for the SD controller. Writes to the global capability registers are mirrored to the capability registers in the associated SDHCI. Configuration of the capabilities must be written through the mirror registers prior to initialisation of the SDHCI. Signed-off-by: Steven Lee Reviewed-by: Andrew Jeffery Reviewed-by: Joel Stanley Link: https://lore.kernel.org/r/20210524073308.9328-5-steven_lee@aspeedtech.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-aspeed.c | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index d001c51074a0..65b5685f6c15 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -31,6 +31,11 @@ #define ASPEED_SDC_S0_PHASE_OUT_EN GENMASK(1, 0) #define ASPEED_SDC_PHASE_MAX 31 +/* SDIO{10,20} */ +#define ASPEED_SDC_CAP1_1_8V (0 * 32 + 26) +/* SDIO{14,24} */ +#define ASPEED_SDC_CAP2_SDR104 (1 * 32 + 1) + struct aspeed_sdc { struct clk *clk; struct resource *res; @@ -72,6 +77,37 @@ struct aspeed_sdhci { const struct aspeed_sdhci_phase_desc *phase_desc; }; +/* + * The function sets the mirror register for updating + * capbilities of the current slot. + * + * slot | capability | caps_reg | mirror_reg + * -----|-------------|----------|------------ + * 0 | CAP1_1_8V | SDIO140 | SDIO10 + * 0 | CAP2_SDR104 | SDIO144 | SDIO14 + * 1 | CAP1_1_8V | SDIO240 | SDIO20 + * 1 | CAP2_SDR104 | SDIO244 | SDIO24 + */ +static void aspeed_sdc_set_slot_capability(struct sdhci_host *host, struct aspeed_sdc *sdc, + int capability, bool enable, u8 slot) +{ + u32 mirror_reg_offset; + u32 cap_val; + u8 cap_reg; + + if (slot > 1) + return; + + cap_reg = capability / 32; + cap_val = sdhci_readl(host, 0x40 + (cap_reg * 4)); + if (enable) + cap_val |= BIT(capability % 32); + else + cap_val &= ~BIT(capability % 32); + mirror_reg_offset = ((slot + 1) * 0x10) + (cap_reg * 4); + writel(cap_val, sdc->regs + mirror_reg_offset); +} + static void aspeed_sdc_configure_8bit_mode(struct aspeed_sdc *sdc, struct aspeed_sdhci *sdhci, bool bus8) @@ -328,6 +364,7 @@ static inline int aspeed_sdhci_calculate_slot(struct aspeed_sdhci *dev, static int aspeed_sdhci_probe(struct platform_device *pdev) { const struct aspeed_sdhci_pdata *aspeed_pdata; + struct device_node *np = pdev->dev.of_node; struct sdhci_pltfm_host *pltfm_host; struct aspeed_sdhci *dev; struct sdhci_host *host; @@ -372,6 +409,17 @@ static int aspeed_sdhci_probe(struct platform_device *pdev) sdhci_get_of_property(pdev); + if (of_property_read_bool(np, "mmc-hs200-1_8v") || + of_property_read_bool(np, "sd-uhs-sdr104")) { + aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP1_1_8V, + true, slot); + } + + if (of_property_read_bool(np, "sd-uhs-sdr104")) { + aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP2_SDR104, + true, slot); + } + pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(pltfm_host->clk)) return PTR_ERR(pltfm_host->clk); From de905475bd4bd0805a33ba64b614d837e4bd292a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 27 May 2021 21:42:26 +0200 Subject: [PATCH 40/54] mmc: dw_mmc-pltfm: Remove unused As of commit 4cdc2ec1da322776 ("mmc: dw_mmc: move rockchip related code to a separate file"), dw_mmc-pltfm.c no longer uses the clock API. Signed-off-by: Geert Uytterhoeven Reviewed-by: Jaehoon Chung Link: https://lore.kernel.org/r/20210527194226.1705607-1-geert@linux-m68k.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-pltfm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 73731cd3ba23..9901208be797 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -17,7 +17,6 @@ #include #include #include -#include #include "dw_mmc.h" #include "dw_mmc-pltfm.h" From 91445d5eed6b19d6d31506fb7c3f65e9acc175c5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 28 May 2021 14:21:26 +0300 Subject: [PATCH 41/54] mmc: mmc_spi: Drop duplicate 'mmc_spi' in the debug messages dev_dbg() in any case prints the device and driver name, no need to repeat this in (some) messages. Drop duplicates for good. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210528112127.71738-1-andriy.shevchenko@linux.intel.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mmc_spi.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 9776a03a10f5..65c65bb5737f 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -504,7 +504,7 @@ mmc_spi_command_send(struct mmc_spi_host *host, /* else: R1 (most commands) */ } - dev_dbg(&host->spi->dev, " mmc_spi: CMD%d, resp %s\n", + dev_dbg(&host->spi->dev, " CMD%d, resp %s\n", cmd->opcode, maptype(cmd)); /* send command, leaving chipselect active */ @@ -928,8 +928,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, while (length) { t->len = min(length, blk_size); - dev_dbg(&host->spi->dev, - " mmc_spi: %s block, %d bytes\n", + dev_dbg(&host->spi->dev, " %s block, %d bytes\n", (direction == DMA_TO_DEVICE) ? "write" : "read", t->len); @@ -974,7 +973,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, int tmp; const unsigned statlen = sizeof(scratch->status); - dev_dbg(&spi->dev, " mmc_spi: STOP_TRAN\n"); + dev_dbg(&spi->dev, " STOP_TRAN\n"); /* Tweak the per-block message we set up earlier by morphing * it to hold single buffer with the token followed by some @@ -1175,7 +1174,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) canpower = host->pdata && host->pdata->setpower; - dev_dbg(&host->spi->dev, "mmc_spi: power %s (%d)%s\n", + dev_dbg(&host->spi->dev, "power %s (%d)%s\n", mmc_powerstring(ios->power_mode), ios->vdd, canpower ? ", can switch" : ""); @@ -1248,8 +1247,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->spi->max_speed_hz = ios->clock; status = spi_setup(host->spi); - dev_dbg(&host->spi->dev, - "mmc_spi: clock to %d Hz, %d\n", + dev_dbg(&host->spi->dev, " clock to %d Hz, %d\n", host->spi->max_speed_hz, status); } } From 706998e70104d93d7e137b92ff0c216aee66c0dd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 28 May 2021 14:21:27 +0300 Subject: [PATCH 42/54] mmc: mmc_spi: Imply container_of() to be no-op Since we don't use structure field layout randomization the manual shuffling can affect some macros, in particular container_of() against struct of_mmc_spi, which becomes a no-op when pdata member is the first one in the structure. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210528112127.71738-2-andriy.shevchenko@linux.intel.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/of_mmc_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index 9d480a05f655..3629550528b6 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -22,8 +22,8 @@ MODULE_LICENSE("GPL"); struct of_mmc_spi { - int detect_irq; struct mmc_spi_platform_data pdata; + int detect_irq; }; static struct of_mmc_spi *to_of_mmc_spi(struct device *dev) From 09247e110b2efce3a104e57e887c373e0a57a412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=B6hle?= Date: Wed, 12 May 2021 16:03:24 +0000 Subject: [PATCH 43/54] mmc: core: Allow UHS-I voltage switch for SDSC cards if supported While initializing an UHS-I SD card, the mmc core first tries to switch to 1.8V I/O voltage, before it continues to change the settings for the bus speed mode. However, the current behaviour in the mmc core is inconsistent and doesn't conform to the SD spec. More precisely, an SD card that supports UHS-I must set both the SD_OCR_CCS bit and the SD_OCR_S18R bit in the OCR register response. When switching to 1.8V I/O the mmc core correctly checks both of the bits, but only the SD_OCR_S18R bit when changing the settings for bus speed mode. Rather than actually fixing the code to confirm to the SD spec, let's deliberately deviate from it by requiring only the SD_OCR_S18R bit for both parts. This enables us to support UHS-I for SDSC cards (outside spec), which is actually being supported by some existing SDSC cards. Moreover, this fixes the inconsistent behaviour. Signed-off-by: Christian Loehle Link: https://lore.kernel.org/r/CWXP265MB26803AE79E0AD5ED083BF2A6C4529@CWXP265MB2680.GBRP265.PROD.OUTLOOK.COM Cc: stable@vger.kernel.org [Ulf: Rewrote commit message and comments to clarify the changes] Signed-off-by: Ulf Hansson --- drivers/mmc/core/sd.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 781c1e24308c..4646b7a03db6 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -857,11 +857,13 @@ try_again: return err; /* - * In case CCS and S18A in the response is set, start Signal Voltage - * Switch procedure. SPI mode doesn't support CMD11. + * In case the S18A bit is set in the response, let's start the signal + * voltage switch procedure. SPI mode doesn't support CMD11. + * Note that, according to the spec, the S18A bit is not valid unless + * the CCS bit is set as well. We deliberately deviate from the spec in + * regards to this, which allows UHS-I to be supported for SDSC cards. */ - if (!mmc_host_is_spi(host) && rocr && - ((*rocr & 0x41000000) == 0x41000000)) { + if (!mmc_host_is_spi(host) && rocr && (*rocr & 0x01000000)) { err = mmc_set_uhs_voltage(host, pocr); if (err == -EAGAIN) { retries--; From 15dd8dc9ffcca7f4f77bffef44dca26678489459 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 1 Jun 2021 11:54:02 +0200 Subject: [PATCH 44/54] mmc: sdhci-esdhc-imx: remove unused is_imx6q_usdhc The is_imx6q_usdhc() function is unused: drivers/mmc/host/sdhci-esdhc-imx.c:343:19: warning: unused function 'is_imx6q_usdhc' Reported-by: kernel test robot Fixes: f47c4bbfa283 ("mmc: sdhci-esdhc-imx: create struct esdhc_soc_data") Signed-off-by: Krzysztof Kozlowski Reviewed-by: Haibo Chen Link: https://lore.kernel.org/r/20210601095403.236007-1-krzysztof.kozlowski@canonical.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index fba4a963d12e..7336ae749137 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -324,11 +324,6 @@ static inline int is_imx53_esdhc(struct pltfm_imx_data *data) return data->socdata == &esdhc_imx53_data; } -static inline int is_imx6q_usdhc(struct pltfm_imx_data *data) -{ - return data->socdata == &usdhc_imx6q_data; -} - static inline int esdhc_is_usdhc(struct pltfm_imx_data *data) { return !!(data->socdata->flags & ESDHC_FLAG_USDHC); From 961470820021e6f9d74db4837bd6831a1a30341b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 1 Jun 2021 11:54:03 +0200 Subject: [PATCH 45/54] mmc: sdhci-sprd: use sdhci_sprd_writew The sdhci_sprd_writew() was defined by never used in sdhci_ops: drivers/mmc/host/sdhci-sprd.c:134:20: warning: unused function 'sdhci_sprd_writew' Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20210601095403.236007-2-krzysztof.kozlowski@canonical.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 5dc36efff47f..11e375579cfb 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -393,6 +393,7 @@ static void sdhci_sprd_request_done(struct sdhci_host *host, static struct sdhci_ops sdhci_sprd_ops = { .read_l = sdhci_sprd_readl, .write_l = sdhci_sprd_writel, + .write_w = sdhci_sprd_writew, .write_b = sdhci_sprd_writeb, .set_clock = sdhci_sprd_set_clock, .get_max_clock = sdhci_sprd_get_max_clock, From 45c8ddd06c4b729c56a6083ab311bfbd9643f4a6 Mon Sep 17 00:00:00 2001 From: Zheyu Ma Date: Thu, 3 Jun 2021 13:33:20 +0000 Subject: [PATCH 46/54] mmc: via-sdmmc: add a check against NULL pointer dereference Before referencing 'host->data', the driver needs to check whether it is null pointer, otherwise it will cause a null pointer reference. This log reveals it: [ 29.355199] BUG: kernel NULL pointer dereference, address: 0000000000000014 [ 29.357323] #PF: supervisor write access in kernel mode [ 29.357706] #PF: error_code(0x0002) - not-present page [ 29.358088] PGD 0 P4D 0 [ 29.358280] Oops: 0002 [#1] PREEMPT SMP PTI [ 29.358595] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 5.12.4- g70e7f0549188-dirty #102 [ 29.359164] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 [ 29.359978] RIP: 0010:via_sdc_isr+0x21f/0x410 [ 29.360314] Code: ff ff e8 84 aa d0 fd 66 45 89 7e 28 66 41 f7 c4 00 10 75 56 e8 72 aa d0 fd 66 41 f7 c4 00 c0 74 10 e8 65 aa d0 fd 48 8b 43 18 40 14 ac ff ff ff e8 55 aa d0 fd 48 89 df e8 ad fb ff ff e9 77 [ 29.361661] RSP: 0018:ffffc90000118e98 EFLAGS: 00010046 [ 29.362042] RAX: 0000000000000000 RBX: ffff888107d77880 RCX: 0000000000000000 [ 29.362564] RDX: 0000000000000000 RSI: ffffffff835d20bb RDI: 00000000ffffffff [ 29.363085] RBP: ffffc90000118ed8 R08: 0000000000000001 R09: 0000000000000001 [ 29.363604] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000008600 [ 29.364128] R13: ffff888107d779c8 R14: ffffc90009c00200 R15: 0000000000008000 [ 29.364651] FS: 0000000000000000(0000) GS:ffff88817bc80000(0000) knlGS:0000000000000000 [ 29.365235] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 29.365655] CR2: 0000000000000014 CR3: 0000000005a2e000 CR4: 00000000000006e0 [ 29.366170] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 29.366683] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 29.367197] Call Trace: [ 29.367381] [ 29.367537] __handle_irq_event_percpu+0x53/0x3e0 [ 29.367916] handle_irq_event_percpu+0x35/0x90 [ 29.368247] handle_irq_event+0x39/0x60 [ 29.368632] handle_fasteoi_irq+0xc2/0x1d0 [ 29.368950] __common_interrupt+0x7f/0x150 [ 29.369254] common_interrupt+0xb4/0xd0 [ 29.369547] [ 29.369708] asm_common_interrupt+0x1e/0x40 [ 29.370016] RIP: 0010:native_safe_halt+0x17/0x20 [ 29.370360] Code: 07 0f 00 2d db 80 43 00 f4 5d c3 0f 1f 84 00 00 00 00 00 8b 05 c2 37 e5 01 55 48 89 e5 85 c0 7e 07 0f 00 2d bb 80 43 00 fb f4 <5d> c3 cc cc cc cc cc cc cc 55 48 89 e5 e8 67 53 ff ff 8b 0d f9 91 [ 29.371696] RSP: 0018:ffffc9000008fe90 EFLAGS: 00000246 [ 29.372079] RAX: 0000000000000000 RBX: 0000000000000002 RCX: 0000000000000000 [ 29.372595] RDX: 0000000000000000 RSI: ffffffff854f67a4 RDI: ffffffff85403406 [ 29.373122] RBP: ffffc9000008fe90 R08: 0000000000000001 R09: 0000000000000001 [ 29.373646] R10: 0000000000000000 R11: 0000000000000001 R12: ffffffff86009188 [ 29.374160] R13: 0000000000000000 R14: 0000000000000000 R15: ffff888100258000 [ 29.374690] default_idle+0x9/0x10 [ 29.374944] arch_cpu_idle+0xa/0x10 [ 29.375198] default_idle_call+0x6e/0x250 [ 29.375491] do_idle+0x1f0/0x2d0 [ 29.375740] cpu_startup_entry+0x18/0x20 [ 29.376034] start_secondary+0x11f/0x160 [ 29.376328] secondary_startup_64_no_verify+0xb0/0xbb [ 29.376705] Modules linked in: [ 29.376939] Dumping ftrace buffer: [ 29.377187] (ftrace buffer empty) [ 29.377460] CR2: 0000000000000014 [ 29.377712] ---[ end trace 51a473dffb618c47 ]--- [ 29.378056] RIP: 0010:via_sdc_isr+0x21f/0x410 [ 29.378380] Code: ff ff e8 84 aa d0 fd 66 45 89 7e 28 66 41 f7 c4 00 10 75 56 e8 72 aa d0 fd 66 41 f7 c4 00 c0 74 10 e8 65 aa d0 fd 48 8b 43 18 40 14 ac ff ff ff e8 55 aa d0 fd 48 89 df e8 ad fb ff ff e9 77 [ 29.379714] RSP: 0018:ffffc90000118e98 EFLAGS: 00010046 [ 29.380098] RAX: 0000000000000000 RBX: ffff888107d77880 RCX: 0000000000000000 [ 29.380614] RDX: 0000000000000000 RSI: ffffffff835d20bb RDI: 00000000ffffffff [ 29.381134] RBP: ffffc90000118ed8 R08: 0000000000000001 R09: 0000000000000001 [ 29.381653] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000008600 [ 29.382176] R13: ffff888107d779c8 R14: ffffc90009c00200 R15: 0000000000008000 [ 29.382697] FS: 0000000000000000(0000) GS:ffff88817bc80000(0000) knlGS:0000000000000000 [ 29.383277] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 29.383697] CR2: 0000000000000014 CR3: 0000000005a2e000 CR4: 00000000000006e0 [ 29.384223] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 29.384736] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 29.385260] Kernel panic - not syncing: Fatal exception in interrupt [ 29.385882] Dumping ftrace buffer: [ 29.386135] (ftrace buffer empty) [ 29.386401] Kernel Offset: disabled [ 29.386656] Rebooting in 1 seconds.. Signed-off-by: Zheyu Ma Link: https://lore.kernel.org/r/1622727200-15808-1-git-send-email-zheyuma97@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/via-sdmmc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index a1d098560099..c32df5530b94 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -857,6 +857,9 @@ static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask) { BUG_ON(intmask == 0); + if (!host->data) + return; + if (intmask & VIA_CRDR_SDSTS_DT) host->data->error = -ETIMEDOUT; else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC)) From 039259156b3bbe62bff3492f007f0dd247013fa6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 4 Jun 2021 12:44:59 +0200 Subject: [PATCH 47/54] mmc: debugfs: add description for module parameter Make it obvious what this is for. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20210604104459.7574-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 9ec84c86c46a..3fdbc801e64a 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -26,6 +26,7 @@ static DECLARE_FAULT_ATTR(fail_default_attr); static char *fail_request; module_param(fail_request, charp, 0); +MODULE_PARM_DESC(fail_request, "default fault injection attributes"); #endif /* CONFIG_FAIL_MMC_REQUEST */ From a7ab186f60785850b5af1be183867000485ad491 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Mon, 7 Jun 2021 11:00:20 +0930 Subject: [PATCH 48/54] mmc: sdhci-of-aspeed: Turn down a phase correction warning The card timing and the bus frequency are not changed atomically with respect to calls to the set_clock() callback in the driver. The result is the driver sees a transient state where there's a mismatch between the two and thus the inputs to the phase correction calculation formula are garbage. Switch from dev_warn() to dev_dbg() to avoid noise in the normal case, though the change does make bad configurations less likely to be noticed. Reported-by: Joel Stanley Signed-off-by: Andrew Jeffery Reviewed-by: Joel Stanley Link: https://lore.kernel.org/r/20210607013020.85885-1-andrew@aj.id.au Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-aspeed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index 65b5685f6c15..6e4e132903a6 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -186,7 +186,7 @@ static int aspeed_sdhci_phase_to_tap(struct device *dev, unsigned long rate_hz, tap = div_u64(phase_period_ps, prop_delay_ps); if (tap > ASPEED_SDHCI_NR_TAPS) { - dev_warn(dev, + dev_dbg(dev, "Requested out of range phase tap %d for %d degrees of phase compensation at %luHz, clamping to tap %d\n", tap, phase_deg, rate_hz, ASPEED_SDHCI_NR_TAPS); tap = ASPEED_SDHCI_NR_TAPS; From 21adc2e45f4ef32786807375107543797ff68615 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 8 Jun 2021 20:06:20 +0200 Subject: [PATCH 49/54] mmc: Improve function name when aborting a tuning cmd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'mmc_abort_tuning()' made me think tuning gets completely aborted. However, it sends only a STOP cmd to cancel the current tuning cmd. Tuning process may still continue after that. So, rename the function to 'mmc_send_abort_tuning()' to better reflect all this. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20210608180620.40059-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc_ops.c | 4 ++-- drivers/mmc/host/renesas_sdhi_core.c | 2 +- drivers/mmc/host/sdhci.c | 2 +- include/linux/mmc/host.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 3c58f6d0f482..973756ed4016 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -700,7 +700,7 @@ out: } EXPORT_SYMBOL_GPL(mmc_send_tuning); -int mmc_abort_tuning(struct mmc_host *host, u32 opcode) +int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode) { struct mmc_command cmd = {}; @@ -723,7 +723,7 @@ int mmc_abort_tuning(struct mmc_host *host, u32 opcode) return mmc_wait_for_cmd(host, &cmd, 0); } -EXPORT_SYMBOL_GPL(mmc_abort_tuning); +EXPORT_SYMBOL_GPL(mmc_send_abort_tuning); static int mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index baab4c2e1b53..e49ca0f7fe9a 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -704,7 +704,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) set_bit(i, priv->smpcmp); if (cmd_error) - mmc_abort_tuning(mmc, opcode); + mmc_send_abort_tuning(mmc, opcode); } ret = renesas_sdhi_select_tuning(host); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bf238ade1602..6aaf5c3ce34c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2680,7 +2680,7 @@ void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) sdhci_end_tuning(host); - mmc_abort_tuning(host->mmc, opcode); + mmc_send_abort_tuning(host->mmc, opcode); } EXPORT_SYMBOL_GPL(sdhci_abort_tuning); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c7e7b43600e9..0abd47e9ef9b 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -632,6 +632,6 @@ static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data) } int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error); -int mmc_abort_tuning(struct mmc_host *host, u32 opcode); +int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode); #endif /* LINUX_MMC_HOST_H */ From f62f7bcc827fe7f0b02208d4811caec65aad1c8e Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Thu, 10 Jun 2021 20:01:26 +0800 Subject: [PATCH 50/54] mmc: sdhci-esdhc-imx: Enable support for system wakeup for SDIO Enable support for system wakeup, by setting the wakeup capability for the slot corresponding to the SDIO card. Users need to enable the wakeup through the sysfs interface. Signed-off-by: Haibo Chen Link: https://lore.kernel.org/r/1623326486-25275-1-git-send-email-haibo.chen@nxp.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 7336ae749137..72c0bf0c1887 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1620,6 +1620,14 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (err) goto disable_ahb_clk; + /* + * Setup the wakeup capability here, let user to decide + * whether need to enable this wakeup through sysfs interface. + */ + if ((host->mmc->pm_caps & MMC_PM_KEEP_POWER) && + (host->mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ)) + device_set_wakeup_capable(&pdev->dev, true); + pm_runtime_set_active(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_use_autosuspend(&pdev->dev); From 3160e025361fad1085e527a898c5dcfedf7e796d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=90=B0=E6=9D=B0=20=28Zhou=20Yanjie=29?= Date: Thu, 10 Jun 2021 20:58:49 +0800 Subject: [PATCH 51/54] dt-bindings: mmc: JZ4740: Add bindings for JZ4775 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a compatible to the mmc DT bindings for the JZ4775 SoC from Ingenic. Signed-off-by: 周琰杰 (Zhou Yanjie) Acked-by: Paul Cercueil Link: https://lore.kernel.org/r/1623329930-14387-2-git-send-email-zhouyanjie@wanyeetech.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml b/Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml index 04ba8b7fc054..546480f41141 100644 --- a/Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml +++ b/Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml @@ -19,6 +19,7 @@ properties: - ingenic,jz4740-mmc - ingenic,jz4725b-mmc - ingenic,jz4760-mmc + - ingenic,jz4775-mmc - ingenic,jz4780-mmc - ingenic,x1000-mmc - items: From d1c777ee5c5e0a08755ee39f6dc4d222bfd9c832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=90=B0=E6=9D=B0=20=28Zhou=20Yanjie=29?= Date: Thu, 10 Jun 2021 20:58:50 +0800 Subject: [PATCH 52/54] mmc: JZ4740: Add support for JZ4775 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the variant on the JZ4775 SoC from Ingenic. Let's also clarify that the drive clock selection and sample clock selection have been supported since JZ4775, not X1000. So, support for these two functions has been added for JZ4775 and JZ4780. Signed-off-by: 周琰杰 (Zhou Yanjie) Acked-by: Paul Cercueil Link: https://lore.kernel.org/r/1623329930-14387-3-git-send-email-zhouyanjie@wanyeetech.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/jz4740_mmc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 861ff6d9661a..0db17bcc9c16 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -674,7 +674,7 @@ static void jz4740_mmc_send_command(struct jz4740_mmc_host *host, cmdat |= JZ_MMC_CMDAT_WRITE; if (host->use_dma) { /* - * The 4780's MMC controller has integrated DMA ability + * The JZ4780's MMC controller has integrated DMA ability * in addition to being able to use the external DMA * controller. It moves DMA control bits to a separate * register. The DMA_SEL bit chooses the external @@ -866,7 +866,7 @@ static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate) writew(div, host->base + JZ_REG_MMC_CLKRT); if (real_rate > 25000000) { - if (host->version >= JZ_MMC_X1000) { + if (host->version >= JZ_MMC_JZ4780) { writel(JZ_MMC_LPM_DRV_RISING_QTR_PHASE_DLY | JZ_MMC_LPM_SMP_RISING_QTR_OR_HALF_PHASE_DLY | JZ_MMC_LPM_LOW_POWER_MODE_EN, @@ -959,6 +959,7 @@ static const struct of_device_id jz4740_mmc_of_match[] = { { .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 }, { .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B }, { .compatible = "ingenic,jz4760-mmc", .data = (void *) JZ_MMC_JZ4760 }, + { .compatible = "ingenic,jz4775-mmc", .data = (void *) JZ_MMC_JZ4780 }, { .compatible = "ingenic,jz4780-mmc", .data = (void *) JZ_MMC_JZ4780 }, { .compatible = "ingenic,x1000-mmc", .data = (void *) JZ_MMC_X1000 }, {}, From 09a8ec9a2d03efa2813d9d306424eb6802146b57 Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Wed, 2 Jun 2021 15:27:57 -0400 Subject: [PATCH 53/54] dt-bindings: mmc: sdhci-iproc: Add brcm,bcm7211a0-sdhci Add new compatible string for the legacy sdhci controller on the BCM7211 family of SoC's. Signed-off-by: Al Cooper Link: https://lore.kernel.org/r/20210602192758.38735-1-alcooperx@gmail.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml index 6f569fbfa134..2f63f2cdeb71 100644 --- a/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml @@ -21,6 +21,7 @@ properties: - brcm,bcm2711-emmc2 - brcm,sdhci-iproc-cygnus - brcm,sdhci-iproc + - brcm,bcm7211a0-sdhci reg: minItems: 1 From 98b5ce4c08ca85727888fdbd362d574bcfa18e3c Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Wed, 2 Jun 2021 15:27:58 -0400 Subject: [PATCH 54/54] mmc: sdhci-iproc: Add support for the legacy sdhci controller on the BCM7211 Add support for the legacy Arasan sdhci controller on the BCM7211 and related SoC's. This includes adding a .shutdown callback to increase the power savings during S5. Signed-off-by: Al Cooper Link: https://lore.kernel.org/r/20210602192758.38735-2-alcooperx@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 2 +- drivers/mmc/host/sdhci-iproc.c | 30 ++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci.h | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index a4d4c757eea0..561184fa7eb9 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -412,7 +412,7 @@ config MMC_SDHCI_MILBEAUT config MMC_SDHCI_IPROC tristate "SDHCI support for the BCM2835 & iProc SD/MMC Controller" - depends on ARCH_BCM2835 || ARCH_BCM_IPROC || COMPILE_TEST + depends on ARCH_BCM2835 || ARCH_BCM_IPROC || ARCH_BRCMSTB || COMPILE_TEST depends on MMC_SDHCI_PLTFM depends on OF || ACPI default ARCH_BCM_IPROC diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index ddeaf8e1f72f..cce390fe9cf3 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -286,11 +286,35 @@ static const struct sdhci_iproc_data bcm2711_data = { .mmc_caps = MMC_CAP_3_3V_DDR, }; +static const struct sdhci_pltfm_data sdhci_bcm7211a0_pltfm_data = { + .quirks = SDHCI_QUIRK_MISSING_CAPS | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | + SDHCI_QUIRK_BROKEN_DMA | + SDHCI_QUIRK_BROKEN_ADMA, + .ops = &sdhci_iproc_ops, +}; + +#define BCM7211A0_BASE_CLK_MHZ 100 +static const struct sdhci_iproc_data bcm7211a0_data = { + .pdata = &sdhci_bcm7211a0_pltfm_data, + .caps = ((BCM7211A0_BASE_CLK_MHZ / 2) << SDHCI_TIMEOUT_CLK_SHIFT) | + (BCM7211A0_BASE_CLK_MHZ << SDHCI_CLOCK_BASE_SHIFT) | + ((0x2 << SDHCI_MAX_BLOCK_SHIFT) + & SDHCI_MAX_BLOCK_MASK) | + SDHCI_CAN_VDD_330 | + SDHCI_CAN_VDD_180 | + SDHCI_CAN_DO_SUSPEND | + SDHCI_CAN_DO_HISPD, + .caps1 = SDHCI_DRIVER_TYPE_C | + SDHCI_DRIVER_TYPE_D, +}; + static const struct of_device_id sdhci_iproc_of_match[] = { { .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data }, { .compatible = "brcm,bcm2711-emmc2", .data = &bcm2711_data }, { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data}, { .compatible = "brcm,sdhci-iproc", .data = &iproc_data }, + { .compatible = "brcm,bcm7211a0-sdhci", .data = &bcm7211a0_data }, { } }; MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match); @@ -384,6 +408,11 @@ err: return ret; } +static void sdhci_iproc_shutdown(struct platform_device *pdev) +{ + sdhci_pltfm_suspend(&pdev->dev); +} + static struct platform_driver sdhci_iproc_driver = { .driver = { .name = "sdhci-iproc", @@ -394,6 +423,7 @@ static struct platform_driver sdhci_iproc_driver = { }, .probe = sdhci_iproc_probe, .remove = sdhci_pltfm_unregister, + .shutdown = sdhci_iproc_shutdown, }; module_platform_driver(sdhci_iproc_driver); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0770c036e2ff..c35ed4be75b7 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -201,8 +201,10 @@ #define SDHCI_CAPABILITIES 0x40 #define SDHCI_TIMEOUT_CLK_MASK GENMASK(5, 0) +#define SDHCI_TIMEOUT_CLK_SHIFT 0 #define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 #define SDHCI_CLOCK_BASE_MASK GENMASK(13, 8) +#define SDHCI_CLOCK_BASE_SHIFT 8 #define SDHCI_CLOCK_V3_BASE_MASK GENMASK(15, 8) #define SDHCI_MAX_BLOCK_MASK 0x00030000 #define SDHCI_MAX_BLOCK_SHIFT 16