Commit b8b73df3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v4.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC fixes from Ulf Hansson:
 "MMC core:
   - Fix mmc card initialization for hosts not supporting HW busy
     detection
   - Fix mmc_test for sending commands during non-blocking write

  MMC host:
   - mxs: Avoid using an uninitialized
   - sdhci: Restore enhanced strobe setting during runtime resume
   - sdhci: Fix a couple of reset related issues
   - dw_mmc: Fix a reset controller issue"

* tag 'mmc-v4.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: mxs: Initialize the spinlock prior to using it
  mmc: mmc: Use 500ms as the default generic CMD6 timeout
  mmc: mmc_test: Fix "Commands during non-blocking write" tests
  mmc: sdhci: Fix missing enhanced strobe setting during runtime resume
  mmc: sdhci: Reset cmd and data circuits after tuning failure
  mmc: sdhci: Fix unexpected data interrupt handling
  mmc: sdhci: Fix CMD line reset interfering with ongoing data transfer
  mmc: dw_mmc: add the "reset" as name of reset controller
  Documentation: synopsys-dw-mshc: add binding for reset-names
parents 5c03b53c f91346e8
...@@ -43,6 +43,9 @@ Optional properties: ...@@ -43,6 +43,9 @@ Optional properties:
reset signal present internally in some host controller IC designs. reset signal present internally in some host controller IC designs.
See Documentation/devicetree/bindings/reset/reset.txt for details. See Documentation/devicetree/bindings/reset/reset.txt for details.
* reset-names: request name for using "resets" property. Must be "reset".
(It will be used together with "resets" property.)
* clocks: from common clock binding: handle to biu and ciu clocks for the * clocks: from common clock binding: handle to biu and ciu clocks for the
bus interface unit clock and the card interface unit clock. bus interface unit clock and the card interface unit clock.
...@@ -103,6 +106,8 @@ board specific portions as listed below. ...@@ -103,6 +106,8 @@ board specific portions as listed below.
interrupts = <0 75 0>; interrupts = <0 75 0>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
resets = <&rst 20>;
reset-names = "reset";
}; };
[board specific internal DMA resources] [board specific internal DMA resources]
......
...@@ -2347,7 +2347,7 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test, ...@@ -2347,7 +2347,7 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
struct mmc_test_req *rq = mmc_test_req_alloc(); struct mmc_test_req *rq = mmc_test_req_alloc();
struct mmc_host *host = test->card->host; struct mmc_host *host = test->card->host;
struct mmc_test_area *t = &test->area; struct mmc_test_area *t = &test->area;
struct mmc_async_req areq; struct mmc_test_async_req test_areq = { .test = test };
struct mmc_request *mrq; struct mmc_request *mrq;
unsigned long timeout; unsigned long timeout;
bool expired = false; bool expired = false;
...@@ -2363,8 +2363,8 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test, ...@@ -2363,8 +2363,8 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
mrq->sbc = &rq->sbc; mrq->sbc = &rq->sbc;
mrq->cap_cmd_during_tfr = true; mrq->cap_cmd_during_tfr = true;
areq.mrq = mrq; test_areq.areq.mrq = mrq;
areq.err_check = mmc_test_check_result_async; test_areq.areq.err_check = mmc_test_check_result_async;
mmc_test_prepare_mrq(test, mrq, t->sg, t->sg_len, dev_addr, t->blocks, mmc_test_prepare_mrq(test, mrq, t->sg, t->sg_len, dev_addr, t->blocks,
512, write); 512, write);
...@@ -2378,7 +2378,7 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test, ...@@ -2378,7 +2378,7 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
/* Start ongoing data request */ /* Start ongoing data request */
if (use_areq) { if (use_areq) {
mmc_start_req(host, &areq, &ret); mmc_start_req(host, &test_areq.areq, &ret);
if (ret) if (ret)
goto out_free; goto out_free;
} else { } else {
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "mmc_ops.h" #include "mmc_ops.h"
#include "sd_ops.h" #include "sd_ops.h"
#define DEFAULT_CMD6_TIMEOUT_MS 500
static const unsigned int tran_exp[] = { static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000, 10000, 100000, 1000000, 10000000,
0, 0, 0, 0 0, 0, 0, 0
...@@ -571,6 +573,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) ...@@ -571,6 +573,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->erased_byte = 0x0; card->erased_byte = 0x0;
/* eMMC v4.5 or later */ /* eMMC v4.5 or later */
card->ext_csd.generic_cmd6_time = DEFAULT_CMD6_TIMEOUT_MS;
if (card->ext_csd.rev >= 6) { if (card->ext_csd.rev >= 6) {
card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; card->ext_csd.feature_support |= MMC_DISCARD_FEATURE;
......
...@@ -2940,7 +2940,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) ...@@ -2940,7 +2940,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
/* find reset controller when exist */ /* find reset controller when exist */
pdata->rstc = devm_reset_control_get_optional(dev, NULL); pdata->rstc = devm_reset_control_get_optional(dev, "reset");
if (IS_ERR(pdata->rstc)) { if (IS_ERR(pdata->rstc)) {
if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER) if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER)
return ERR_PTR(-EPROBE_DEFER); return ERR_PTR(-EPROBE_DEFER);
......
...@@ -661,13 +661,13 @@ static int mxs_mmc_probe(struct platform_device *pdev) ...@@ -661,13 +661,13 @@ static int mxs_mmc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mmc); platform_set_drvdata(pdev, mmc);
spin_lock_init(&host->lock);
ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0, ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0,
dev_name(&pdev->dev), host); dev_name(&pdev->dev), host);
if (ret) if (ret)
goto out_free_dma; goto out_free_dma;
spin_lock_init(&host->lock);
ret = mmc_add_host(mmc); ret = mmc_add_host(mmc);
if (ret) if (ret)
goto out_free_dma; goto out_free_dma;
......
...@@ -2086,6 +2086,10 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) ...@@ -2086,6 +2086,10 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
if (!host->tuning_done) { if (!host->tuning_done) {
pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n"); pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n");
sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_DATA);
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
ctrl &= ~SDHCI_CTRL_TUNED_CLK; ctrl &= ~SDHCI_CTRL_TUNED_CLK;
ctrl &= ~SDHCI_CTRL_EXEC_TUNING; ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
...@@ -2286,10 +2290,8 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -2286,10 +2290,8 @@ static bool sdhci_request_done(struct sdhci_host *host)
for (i = 0; i < SDHCI_MAX_MRQS; i++) { for (i = 0; i < SDHCI_MAX_MRQS; i++) {
mrq = host->mrqs_done[i]; mrq = host->mrqs_done[i];
if (mrq) { if (mrq)
host->mrqs_done[i] = NULL;
break; break;
}
} }
if (!mrq) { if (!mrq) {
...@@ -2320,6 +2322,17 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -2320,6 +2322,17 @@ static bool sdhci_request_done(struct sdhci_host *host)
* upon error conditions. * upon error conditions.
*/ */
if (sdhci_needs_reset(host, mrq)) { if (sdhci_needs_reset(host, mrq)) {
/*
* Do not finish until command and data lines are available for
* reset. Note there can only be one other mrq, so it cannot
* also be in mrqs_done, otherwise host->cmd and host->data_cmd
* would both be null.
*/
if (host->cmd || host->data_cmd) {
spin_unlock_irqrestore(&host->lock, flags);
return true;
}
/* Some controllers need this kick or reset won't work here */ /* Some controllers need this kick or reset won't work here */
if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
/* This is to force an update */ /* This is to force an update */
...@@ -2327,10 +2340,8 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -2327,10 +2340,8 @@ static bool sdhci_request_done(struct sdhci_host *host)
/* Spec says we should do both at the same time, but Ricoh /* Spec says we should do both at the same time, but Ricoh
controllers do not like that. */ controllers do not like that. */
if (!host->cmd) sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA);
if (!host->data_cmd)
sdhci_do_reset(host, SDHCI_RESET_DATA);
host->pending_reset = false; host->pending_reset = false;
} }
...@@ -2338,6 +2349,8 @@ static bool sdhci_request_done(struct sdhci_host *host) ...@@ -2338,6 +2349,8 @@ static bool sdhci_request_done(struct sdhci_host *host)
if (!sdhci_has_requests(host)) if (!sdhci_has_requests(host))
sdhci_led_deactivate(host); sdhci_led_deactivate(host);
host->mrqs_done[i] = NULL;
mmiowb(); mmiowb();
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
...@@ -2512,9 +2525,6 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) ...@@ -2512,9 +2525,6 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
if (!host->data) { if (!host->data) {
struct mmc_command *data_cmd = host->data_cmd; struct mmc_command *data_cmd = host->data_cmd;
if (data_cmd)
host->data_cmd = NULL;
/* /*
* The "data complete" interrupt is also used to * The "data complete" interrupt is also used to
* indicate that a busy state has ended. See comment * indicate that a busy state has ended. See comment
...@@ -2522,11 +2532,13 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) ...@@ -2522,11 +2532,13 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
*/ */
if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) { if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) {
if (intmask & SDHCI_INT_DATA_TIMEOUT) { if (intmask & SDHCI_INT_DATA_TIMEOUT) {
host->data_cmd = NULL;
data_cmd->error = -ETIMEDOUT; data_cmd->error = -ETIMEDOUT;
sdhci_finish_mrq(host, data_cmd->mrq); sdhci_finish_mrq(host, data_cmd->mrq);
return; return;
} }
if (intmask & SDHCI_INT_DATA_END) { if (intmask & SDHCI_INT_DATA_END) {
host->data_cmd = NULL;
/* /*
* Some cards handle busy-end interrupt * Some cards handle busy-end interrupt
* before the command completed, so make * before the command completed, so make
...@@ -2912,6 +2924,10 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) ...@@ -2912,6 +2924,10 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
} }
if ((mmc->caps2 & MMC_CAP2_HS400_ES) &&
mmc->ops->hs400_enhanced_strobe)
mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios);
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
host->runtime_suspended = false; host->runtime_suspended = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment