From patchwork Wed Jan 22 15:00:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 3523951 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 9385BC02DC for ; Wed, 22 Jan 2014 15:01:06 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6C818200D6 for ; Wed, 22 Jan 2014 15:01:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 40DCA2013D for ; Wed, 22 Jan 2014 15:01:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755996AbaAVPAr (ORCPT ); Wed, 22 Jan 2014 10:00:47 -0500 Received: from mail-wi0-f173.google.com ([209.85.212.173]:54750 "EHLO mail-wi0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755316AbaAVPAr (ORCPT ); Wed, 22 Jan 2014 10:00:47 -0500 Received: by mail-wi0-f173.google.com with SMTP id d13so5710806wiw.12 for ; Wed, 22 Jan 2014 07:00:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2Hr3tVUxJF5dSuq3mfs7RwdlsTyiiel4QDY7bv0xVpU=; b=AiGa2rlVxtonhcKOXSG63sGIe99QanmoMXET3bmrBYuTZSZjGLvuAZ1evCkxJxqRrI 9BkymgS7YhTM7Q/tYZIW2V9YV2y+YSkYNLcWqfNAkXLO6P1LO1jTiE5kKQ9Zcb2VtyUx lPQRPkUH+aUOmaq2ynSIiUgQi7KoUZaqvRwKrQMFcIO1zZ0M3WlDNkzfbGmd6IuPpEKe 31+LsZ1Hr78IH8h1yz92efpkl2NwTbswjlFr/4VMyzSzNccebw4Idy4lpL+AIJU4V3Rr d+NsYcyA0LT4xiede6gbl84WjVLimGjo6HUe9M/5PfHZTldd2ImAJlOjjzspu0ixbmcn 3VvA== X-Gm-Message-State: ALoCoQlZDBBdpNQjpEYk7acSOLpYVA79Jme8wf8TRjqIaMVtAn2XfhxEusJzy/Jv1Sx0h14mnqzm X-Received: by 10.194.185.205 with SMTP id fe13mr2231332wjc.23.1390402845678; Wed, 22 Jan 2014 07:00:45 -0800 (PST) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id dd3sm15401824wjb.9.2014.01.22.07.00.43 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 22 Jan 2014 07:00:45 -0800 (PST) From: Ulf Hansson To: linux-mmc@vger.kernel.org, Chris Ball Cc: Dong Aisheng , Stephen Warren , Vladimir Zapolskiy , Adrian Hunter , Ulf Hansson , Russell King , Johan Rudholm Subject: [PATCH 10/10] mmc: mmci: Enable support for busy detection for ux500 variant Date: Wed, 22 Jan 2014 16:00:24 +0100 Message-Id: <1390402824-9850-11-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1390402824-9850-1-git-send-email-ulf.hansson@linaro.org> References: <1390402824-9850-1-git-send-email-ulf.hansson@linaro.org> Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Cc: Johan Rudholm Signed-off-by: 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;