mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-15 20:26:48 +07:00
mmc: mmci: add threaded irq to abort DPSM of non-functional state
The stm32_sdmmc variant has build-in support for datatimeout for R1B requests. If a corresponding IRQ is raised, this triggers the DPSM to stay busy and remains in a non-functional state. Only a reset can bring it back to a functional state. Because a reset must be issued from non-atomic context, let's defer this to be managed from a threaded IRQ handler. Besides the reset, the threaded handler also calls mmc_request_done(), to finally complete the request. Signed-off-by: Ludovic Barre <ludovic.barre@st.com> Link: https://lore.kernel.org/r/20191211133934.16932-1-ludovic.Barre@st.com [Ulf: A few minor updates to the changelog/comments] Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
parent
d0052ad90e
commit
ee157abebc
@ -1321,6 +1321,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
|
||||
} else if (host->variant->busy_timeout && busy_resp &&
|
||||
status & MCI_DATATIMEOUT) {
|
||||
cmd->error = -ETIMEDOUT;
|
||||
host->irq_action = IRQ_WAKE_THREAD;
|
||||
} else {
|
||||
cmd->resp[0] = readl(base + MMCIRESPONSE0);
|
||||
cmd->resp[1] = readl(base + MMCIRESPONSE1);
|
||||
@ -1339,7 +1340,10 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
|
||||
return;
|
||||
}
|
||||
}
|
||||
mmci_request_end(host, host->mrq);
|
||||
|
||||
if (host->irq_action != IRQ_WAKE_THREAD)
|
||||
mmci_request_end(host, host->mrq);
|
||||
|
||||
} else if (sbc) {
|
||||
mmci_start_command(host, host->mrq->cmd, 0);
|
||||
} else if (!host->variant->datactrl_first &&
|
||||
@ -1532,9 +1536,9 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct mmci_host *host = dev_id;
|
||||
u32 status;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&host->lock);
|
||||
host->irq_action = IRQ_HANDLED;
|
||||
|
||||
do {
|
||||
status = readl(host->base + MMCISTATUS);
|
||||
@ -1574,12 +1578,41 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
|
||||
if (host->variant->busy_detect_flag)
|
||||
status &= ~host->variant->busy_detect_flag;
|
||||
|
||||
ret = 1;
|
||||
} while (status);
|
||||
|
||||
spin_unlock(&host->lock);
|
||||
|
||||
return IRQ_RETVAL(ret);
|
||||
return host->irq_action;
|
||||
}
|
||||
|
||||
/*
|
||||
* mmci_irq_thread() - A threaded IRQ handler that manages a reset of the HW.
|
||||
*
|
||||
* A reset is needed for some variants, where a datatimeout for a R1B request
|
||||
* causes the DPSM to stay busy (non-functional).
|
||||
*/
|
||||
static irqreturn_t mmci_irq_thread(int irq, void *dev_id)
|
||||
{
|
||||
struct mmci_host *host = dev_id;
|
||||
unsigned long flags;
|
||||
|
||||
if (host->rst) {
|
||||
reset_control_assert(host->rst);
|
||||
udelay(2);
|
||||
reset_control_deassert(host->rst);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
writel(host->clk_reg, host->base + MMCICLOCK);
|
||||
writel(host->pwr_reg, host->base + MMCIPOWER);
|
||||
writel(MCI_IRQENABLE | host->variant->start_err,
|
||||
host->base + MMCIMASK0);
|
||||
|
||||
host->irq_action = IRQ_HANDLED;
|
||||
mmci_request_end(host, host->mrq);
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
|
||||
return host->irq_action;
|
||||
}
|
||||
|
||||
static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
@ -2063,8 +2096,9 @@ static int mmci_probe(struct amba_device *dev,
|
||||
goto clk_disable;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&dev->dev, dev->irq[0], mmci_irq, IRQF_SHARED,
|
||||
DRIVER_NAME " (cmd)", host);
|
||||
ret = devm_request_threaded_irq(&dev->dev, dev->irq[0], mmci_irq,
|
||||
mmci_irq_thread, IRQF_SHARED,
|
||||
DRIVER_NAME " (cmd)", host);
|
||||
if (ret)
|
||||
goto clk_disable;
|
||||
|
||||
|
@ -411,6 +411,7 @@ struct mmci_host {
|
||||
|
||||
struct timer_list timer;
|
||||
unsigned int oldstat;
|
||||
u32 irq_action;
|
||||
|
||||
/* pio stuff */
|
||||
struct sg_mapping_iter sg_miter;
|
||||
|
Loading…
Reference in New Issue
Block a user