On 29 January 2014 23:38, Ulf Hansson <ulf.hansson@xxxxxxxxxx> wrote: > The ux500 variants have HW busy detection support, which is indicated > by the busy_detect flag. For these variants let's enable the > MMC_CAP_WAIT_WHILE_BUSY flag and add the support for it. > > The mmc core will provide the RSP_BUSY command flag for those requests > we should care about busy detection. Regarding the max_busy_timeout, > the HW don't support busy detection timeouts so at this initial step > let's make it simple and set it to zero to indicate we are able to > support any timeout. > > Cc: Russell King <linux@xxxxxxxxxxxxxxxx> > Cc: Johan Rudholm <jrudholm@xxxxxxxxx> > Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx> Hi Russell, Just wanted to know if you were happy with this patch. I would prefer if we could let Chris carry this patch, since there are a dependency. Are you fine with that? Kind regards Ulf Hansson > --- > drivers/mmc/host/mmci.c | 51 +++++++++++++++++++++++++++++++++++++++-------- > drivers/mmc/host/mmci.h | 2 ++ > 2 files changed, 45 insertions(+), 8 deletions(-) > > diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c > index 1a4b153..9976a90 100644 > --- a/drivers/mmc/host/mmci.c > +++ b/drivers/mmc/host/mmci.c > @@ -921,6 +921,29 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, > { > void __iomem *base = host->base; > bool sbc = (cmd == host->mrq->sbc); > + bool busy_resp = host->variant->busy_detect && > + (cmd->flags & MMC_RSP_BUSY); > + > + /* Check if we need to wait for busy completion. */ > + if (host->busy_status && (status & MCI_ST_CARDBUSY)) > + return; > + > + /* Enable busy completion if needed and supported. */ > + if (!host->busy_status && busy_resp && > + !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) && > + (readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) { > + writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND, > + base + MMCIMASK0); > + host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND); > + return; > + } > + > + /* At busy completion, mask the IRQ and complete the request. */ > + if (host->busy_status) { > + writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND, > + base + MMCIMASK0); > + host->busy_status = 0; > + } > > host->cmd = NULL; > > @@ -1139,14 +1162,19 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) > status &= ~MCI_IRQ1MASK; > } > > + /* > + * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's > + * enabled) since the HW seems to be triggering the IRQ on both > + * edges while monitoring DAT0 for busy completion. > + */ > status &= readl(host->base + MMCIMASK0); > writel(status, host->base + MMCICLEAR); > > dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); > > cmd = host->cmd; > - if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT| > - MCI_CMDRESPEND) && cmd) > + if ((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT| > + MCI_CMDSENT|MCI_CMDRESPEND) && cmd) > mmci_cmd_irq(host, cmd, status); > > data = host->data; > @@ -1155,6 +1183,10 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) > MCI_DATABLOCKEND) && data) > mmci_data_irq(host, data, status); > > + /* Don't poll for busy completion in irq context. */ > + if (host->busy_status) > + status &= ~MCI_ST_CARDBUSY; > + > ret = 1; > } while (status); > > @@ -1504,12 +1536,6 @@ static int mmci_probe(struct amba_device *dev, > goto clk_disable; > } > > - if (variant->busy_detect) { > - mmci_ops.card_busy = mmci_card_busy; > - mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE); > - } > - > - mmc->ops = &mmci_ops; > /* > * The ARM and ST versions of the block have slightly different > * clock divider equations which means that the minimum divider > @@ -1543,6 +1569,15 @@ static int mmci_probe(struct amba_device *dev, > mmc->caps = plat->capabilities; > mmc->caps2 = plat->capabilities2; > > + if (variant->busy_detect) { > + mmci_ops.card_busy = mmci_card_busy; > + mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE); > + mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; > + mmc->max_busy_timeout = 0; > + } > + > + mmc->ops = &mmci_ops; > + > /* We support these PM capabilities. */ > mmc->pm_caps = MMC_PM_KEEP_POWER; > > diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h > index 168bc72..b008ace 100644 > --- a/drivers/mmc/host/mmci.h > +++ b/drivers/mmc/host/mmci.h > @@ -139,6 +139,7 @@ > /* Extended status bits for the ST Micro variants */ > #define MCI_ST_SDIOITMASK (1 << 22) > #define MCI_ST_CEATAENDMASK (1 << 23) > +#define MCI_ST_BUSYEND (1 << 24) > > #define MMCIMASK1 0x040 > #define MMCIFIFOCNT 0x048 > @@ -186,6 +187,7 @@ struct mmci_host { > u32 pwr_reg; > u32 clk_reg; > u32 datactrl_reg; > + u32 busy_status; > bool vqmmc_enabled; > struct mmci_platform_data *plat; > struct variant_data *variant; > -- > 1.7.9.5 > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html