From patchwork Mon Apr 11 21:13:42 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Warkentin X-Patchwork-Id: 698781 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 p3BKYiIF002588 for ; Mon, 11 Apr 2011 20:34:48 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755170Ab1DKUer (ORCPT ); Mon, 11 Apr 2011 16:34:47 -0400 Received: from exprod5og116.obsmtp.com ([64.18.0.147]:55961 "EHLO exprod5og116.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753836Ab1DKUer (ORCPT ); Mon, 11 Apr 2011 16:34:47 -0400 Received: from DE01MGRG01.AM.MOT-MOBILITY.COM ([192.54.82.14]) (using TLSv1) by exprod5ob116.postini.com ([64.18.4.12]) with SMTP ID DSNKTaNl5onScjJn/FywIGmEvR0iz8G7L8Q/@postini.com; Mon, 11 Apr 2011 13:34:47 PDT Received: from DE01MGRG01.AM.MOT-MOBILITY.COM ([10.176.129.42]) by DE01MGRG01.AM.MOT-MOBILITY.COM (8.14.3/8.14.3) with ESMTP id p3BKZ8Y1018321 for ; Mon, 11 Apr 2011 16:35:08 -0400 (EDT) Received: from mail-gx0-f170.google.com (mail-gx0-f170.google.com [209.85.161.170]) by DE01MGRG01.AM.MOT-MOBILITY.COM (8.14.3/8.14.3) with ESMTP id p3BKZ1ew018269 (version=TLSv1/SSLv3 cipher=RC4-MD5 bits=128 verify=OK) for ; Mon, 11 Apr 2011 16:35:08 -0400 (EDT) Received: by mail-gx0-f170.google.com with SMTP id 27so4144611gxk.15 for ; Mon, 11 Apr 2011 13:34:45 -0700 (PDT) Received: by 10.150.60.16 with SMTP id i16mr2003491yba.274.1302554085157; Mon, 11 Apr 2011 13:34:45 -0700 (PDT) Received: from localhost.localdomain (dyngate-ca119-13.motorola.com [144.189.96.13]) by mx.google.com with ESMTPS id c18sm6362122ana.27.2011.04.11.13.34.41 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 11 Apr 2011 13:34:43 -0700 (PDT) From: Andrei Warkentin To: linux-mmc@vger.kernel.org Cc: arnd@arndb.de, cjb@laptop.org, Andrei Warkentin Subject: [patchv3 2/4] MMC: SDHCI R1B command handling + MMC_CAP_ERASE. Date: Mon, 11 Apr 2011 16:13:42 -0500 Message-Id: <1302556424-21951-2-git-send-email-andreiw@motorola.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: References: 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]); Mon, 11 Apr 2011 20:34:48 +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_ms (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..173e980 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_ms) + 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_ms * 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