Skip to content

Commit

Permalink
Merge tag 'mmc-v4.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Nov 12, 2016
2 parents 5c03b53 + f91346e commit b8b73df
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 17 deletions.
5 changes: 5 additions & 0 deletions Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ Optional properties:
reset signal present internally in some host controller IC designs.
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
bus interface unit clock and the card interface unit clock.

Expand Down Expand Up @@ -103,6 +106,8 @@ board specific portions as listed below.
interrupts = <0 75 0>;
#address-cells = <1>;
#size-cells = <0>;
resets = <&rst 20>;
reset-names = "reset";
};

[board specific internal DMA resources]
Expand Down
8 changes: 4 additions & 4 deletions drivers/mmc/card/mmc_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_host *host = test->card->host;
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;
unsigned long timeout;
bool expired = false;
Expand All @@ -2363,8 +2363,8 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
mrq->sbc = &rq->sbc;
mrq->cap_cmd_during_tfr = true;

areq.mrq = mrq;
areq.err_check = mmc_test_check_result_async;
test_areq.areq.mrq = mrq;
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,
512, write);
Expand All @@ -2378,7 +2378,7 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,

/* Start ongoing data request */
if (use_areq) {
mmc_start_req(host, &areq, &ret);
mmc_start_req(host, &test_areq.areq, &ret);
if (ret)
goto out_free;
} else {
Expand Down
3 changes: 3 additions & 0 deletions drivers/mmc/core/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include "mmc_ops.h"
#include "sd_ops.h"

#define DEFAULT_CMD6_TIMEOUT_MS 500

static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
Expand Down Expand Up @@ -571,6 +573,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->erased_byte = 0x0;

/* eMMC v4.5 or later */
card->ext_csd.generic_cmd6_time = DEFAULT_CMD6_TIMEOUT_MS;
if (card->ext_csd.rev >= 6) {
card->ext_csd.feature_support |= MMC_DISCARD_FEATURE;

Expand Down
2 changes: 1 addition & 1 deletion drivers/mmc/host/dw_mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2940,7 +2940,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
return ERR_PTR(-ENOMEM);

/* 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 (PTR_ERR(pdata->rstc) == -EPROBE_DEFER)
return ERR_PTR(-EPROBE_DEFER);
Expand Down
4 changes: 2 additions & 2 deletions drivers/mmc/host/mxs-mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,13 +661,13 @@ static int mxs_mmc_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, mmc);

spin_lock_init(&host->lock);

ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0,
dev_name(&pdev->dev), host);
if (ret)
goto out_free_dma;

spin_lock_init(&host->lock);

ret = mmc_add_host(mmc);
if (ret)
goto out_free_dma;
Expand Down
36 changes: 26 additions & 10 deletions drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -2086,6 +2086,10 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)

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");

sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_DATA);

ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
ctrl &= ~SDHCI_CTRL_TUNED_CLK;
ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
Expand Down Expand Up @@ -2286,10 +2290,8 @@ static bool sdhci_request_done(struct sdhci_host *host)

for (i = 0; i < SDHCI_MAX_MRQS; i++) {
mrq = host->mrqs_done[i];
if (mrq) {
host->mrqs_done[i] = NULL;
if (mrq)
break;
}
}

if (!mrq) {
Expand Down Expand Up @@ -2320,24 +2322,35 @@ static bool sdhci_request_done(struct sdhci_host *host)
* upon error conditions.
*/
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 */
if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
/* This is to force an update */
host->ops->set_clock(host, host->clock);

/* Spec says we should do both at the same time, but Ricoh
controllers do not like that. */
if (!host->cmd)
sdhci_do_reset(host, SDHCI_RESET_CMD);
if (!host->data_cmd)
sdhci_do_reset(host, SDHCI_RESET_DATA);
sdhci_do_reset(host, SDHCI_RESET_CMD);
sdhci_do_reset(host, SDHCI_RESET_DATA);

host->pending_reset = false;
}

if (!sdhci_has_requests(host))
sdhci_led_deactivate(host);

host->mrqs_done[i] = NULL;

mmiowb();
spin_unlock_irqrestore(&host->lock, flags);

Expand Down Expand Up @@ -2512,21 +2525,20 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
if (!host->data) {
struct mmc_command *data_cmd = host->data_cmd;

if (data_cmd)
host->data_cmd = NULL;

/*
* The "data complete" interrupt is also used to
* indicate that a busy state has ended. See comment
* above in sdhci_cmd_irq().
*/
if (data_cmd && (data_cmd->flags & MMC_RSP_BUSY)) {
if (intmask & SDHCI_INT_DATA_TIMEOUT) {
host->data_cmd = NULL;
data_cmd->error = -ETIMEDOUT;
sdhci_finish_mrq(host, data_cmd->mrq);
return;
}
if (intmask & SDHCI_INT_DATA_END) {
host->data_cmd = NULL;
/*
* Some cards handle busy-end interrupt
* before the command completed, so make
Expand Down Expand Up @@ -2912,6 +2924,10 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
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);

host->runtime_suspended = false;
Expand Down

0 comments on commit b8b73df

Please sign in to comment.