mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-03 08:50:17 -04:00
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
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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) {
|
||||
@@ -2320,6 +2322,17 @@ 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 */
|
||||
@@ -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
|
||||
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;
|
||||
}
|
||||
@@ -2338,6 +2349,8 @@ static bool sdhci_request_done(struct sdhci_host *host)
|
||||
if (!sdhci_has_requests(host))
|
||||
sdhci_led_deactivate(host);
|
||||
|
||||
host->mrqs_done[i] = NULL;
|
||||
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
|
||||
@@ -2512,9 +2525,6 @@ 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
|
||||
@@ -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 (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
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user