From patchwork Wed Apr 6 01:09:51 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Warkentin X-Patchwork-Id: 689071 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p360PV5H030521 for ; Wed, 6 Apr 2011 00:30:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751954Ab1DFAaK (ORCPT ); Tue, 5 Apr 2011 20:30:10 -0400 Received: from exprod5og114.obsmtp.com ([64.18.0.28]:49167 "EHLO exprod5og114.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752102Ab1DFAaJ (ORCPT ); Tue, 5 Apr 2011 20:30:09 -0400 Received: from il93mgrg01.am.mot-mobility.com ([144.188.21.13]) (using TLSv1) by exprod5ob114.postini.com ([64.18.4.12]) with SMTP ID DSNKTZu0EG2z2U/NzDVjSLZi8CXC505L31nV@postini.com; Tue, 05 Apr 2011 17:30:08 PDT Received: from il93mgrg01.am.mot-mobility.com ([10.176.130.20]) by il93mgrg01.am.mot-mobility.com (8.14.3/8.14.3) with ESMTP id p360SOQY015644 for ; Tue, 5 Apr 2011 20:28:24 -0400 (EDT) Received: from mail-yx0-f170.google.com (mail-yx0-f170.google.com [209.85.213.170]) by il93mgrg01.am.mot-mobility.com (8.14.3/8.14.3) with ESMTP id p360S0Tx015446 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Tue, 5 Apr 2011 20:28:24 -0400 (EDT) Received: by mail-yx0-f170.google.com with SMTP id 11so632037yxi.15 for ; Tue, 05 Apr 2011 17:30:07 -0700 (PDT) Received: by 10.236.182.135 with SMTP id o7mr401103yhm.182.1302049807100; Tue, 05 Apr 2011 17:30:07 -0700 (PDT) Received: from localhost.localdomain (dyngate-ca119-13.motorola.com [144.189.96.13]) by mx.google.com with ESMTPS id p51sm13355yhm.52.2011.04.05.17.30.05 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 05 Apr 2011 17:30:06 -0700 (PDT) From: Andrei Warkentin To: linux-mmc@vger.kernel.org Cc: arnd@arndb.de, cjb@laptop.org, Andrei Warkentin Subject: [PATCH 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE. Date: Tue, 5 Apr 2011 20:09:51 -0500 Message-Id: <1302052193-23317-3-git-send-email-andreiw@motorola.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1302052193-23317-1-git-send-email-andreiw@motorola.com> References: <1302052193-23317-1-git-send-email-andreiw@motorola.com> X-CFilter-Loop: Reflected Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 06 Apr 2011 00:30:10 +0000 (UTC) ERASE command needs R1B response, so fix R1B-type command handling for SDHCI controller. For non-DAT commands using a busy reponse, the cmd->cmd_timeout (in ms) field is used for timeout calculations. Based on patch by Chuanxiao Dong Signed-off-by: Andrei Warkentin --- drivers/mmc/host/sdhci.c | 43 +++++++++++++++++++++++++++---------------- 1 files changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9e15f41..88aaf5e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -40,7 +40,6 @@ static unsigned int debug_quirks = 0; -static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); static void sdhci_finish_data(struct sdhci_host *); static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); @@ -591,9 +590,10 @@ static void sdhci_adma_table_post(struct sdhci_host *host, data->sg_len, direction); } -static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) +static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) { u8 count; + struct mmc_data *data = cmd->data; unsigned target_timeout, current_timeout; /* @@ -605,12 +605,16 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) return 0xE; - /* timeout in us */ - target_timeout = data->timeout_ns / 1000 + - data->timeout_clks / host->clock; + /* Unspecified timeout, assume max */ + if (!data && !cmd->cmd_timeout) + return 0xE; - if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) - host->timeout_clk = host->clock / 1000; + /* timeout in us */ + if (!data) + target_timeout = cmd->cmd_timeout * 1000; + else + target_timeout = data->timeout_ns / 1000 + + data->timeout_clks / host->clock; /* * Figure out needed cycles. @@ -632,8 +636,9 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) } if (count >= 0xF) { - printk(KERN_WARNING "%s: Too large timeout requested!\n", - mmc_hostname(host->mmc)); + printk(KERN_WARNING "%s: Too large timeout requested for CMD%d!\n", + mmc_hostname(host->mmc), + cmd->opcode); count = 0xE; } @@ -651,15 +656,21 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); } -static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) +static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) { u8 count; u8 ctrl; + struct mmc_data *data = cmd->data; int ret; WARN_ON(host->data); - if (data == NULL) + if (data || (cmd->flags & MMC_RSP_BUSY)) { + count = sdhci_calc_timeout(host, cmd); + sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); + } + + if (!data) return; /* Sanity checks */ @@ -670,9 +681,6 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) host->data = data; host->data_early = 0; - count = sdhci_calc_timeout(host, data); - sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) host->flags |= SDHCI_REQ_USE_DMA; @@ -920,7 +928,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) host->cmd = cmd; - sdhci_prepare_data(host, cmd->data); + sdhci_prepare_data(host, cmd); sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); @@ -1867,6 +1875,9 @@ int sdhci_add_host(struct sdhci_host *host) if (caps & SDHCI_TIMEOUT_CLK_UNIT) host->timeout_clk *= 1000; + if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) + host->timeout_clk = host->clock / 1000; + /* * Set host parameters. */ @@ -1879,7 +1890,7 @@ int sdhci_add_host(struct sdhci_host *host) mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; mmc->f_max = host->max_clk; - mmc->caps |= MMC_CAP_SDIO_IRQ; + mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE; /* * A controller may support 8-bit width, but the board itself