From patchwork Tue Oct 23 22:48:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Drake X-Patchwork-Id: 1635111 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 27815DF283 for ; Tue, 23 Oct 2012 22:48:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933592Ab2JWWsL (ORCPT ); Tue, 23 Oct 2012 18:48:11 -0400 Received: from mail-pa0-f46.google.com ([209.85.220.46]:48378 "EHLO mail-pa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933543Ab2JWWsK (ORCPT ); Tue, 23 Oct 2012 18:48:10 -0400 Received: by mail-pa0-f46.google.com with SMTP id hz1so3095379pad.19 for ; Tue, 23 Oct 2012 15:48:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type; bh=Mt1nZwMeb0fC6dTolYD/I2w5af99L6SCMCouynINk/U=; b=c5h+SdYp9dwlvxxcuhyf9YuQBI4kidlAwgv5Iu8q1AlOLJ+nGYJ13PTONmWI6JbR5Q pr/VeWBdswwIxAgWF/HgM227zGAmJDbmC7e4ZKJX1k06QUEFNTdcPY3kTP1smK6GDtBl BFLb+xJwcT1S5mpsrbzNTx4PyTBIfPOQwj7Ebc3SOueZoYpwYIMdsrVvmMCX6QZJM4rl vaWIGqiW+pVJUmNpO9yNIDfaeZyBVMqiYbcR3tsGGnFG23GWxQ619ji5cDNl4yu+NDVI aomtkVa3DQBMzk/XBFOWNmnqmFkuZU+CRr0aTa/BbM2sV/8N3ZuKYzDbvg+5AbcoMK0C SThg== MIME-Version: 1.0 Received: by 10.68.226.136 with SMTP id rs8mr44567789pbc.153.1351032490322; Tue, 23 Oct 2012 15:48:10 -0700 (PDT) Received: by 10.68.27.106 with HTTP; Tue, 23 Oct 2012 15:48:10 -0700 (PDT) In-Reply-To: <87bofsj52p.fsf@octavius.laptop.org> References: <1348166542-3247-1-git-send-email-johan.rudholm@stericsson.com> <87bofsj52p.fsf@octavius.laptop.org> Date: Tue, 23 Oct 2012 16:48:10 -0600 X-Google-Sender-Auth: p6SW4AczOVKyox27sHyhoBa4qgk Message-ID: Subject: Re: [PATCH 2/2] mmc: core: Power cycle card on voltage switch fail From: Daniel Drake To: Chris Ball Cc: Johan Rudholm , linux-mmc@vger.kernel.org, Per Forlin , Ulf Hansson Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org On Tue, Oct 23, 2012 at 2:39 PM, Chris Ball wrote: > Dan, maybe you could see if this patch (there's a 1/2 patch too) solves > your UHS problem? I tested [RFC/PATCH] mmc: core: Fixup signal voltage switch https://patchwork.kernel.org/patch/1514691/ This was previously failing on both XO-1.75 (kernel 3.0) and XO-4 (kernel 3.5) - the 1.8V switch would fail, but it would not successfully switch back to 3.3V. Testing on XO-4, it worked fine: the 1.8V failed switch was detected, it came back as 3.3V and everything was fine. Testing on XO-1.75, it didn't work: it thought that the 1.8V switch was successful so it left it at that, then the card reacted in a very unstable manner (failed/retried reads, huge amount of kernel log spam, etc). So I came up with the attached sdhci patch. That fixes the XO-1.75 case, which now correctly detects the 1.8V switch failure and goes to 3.3V. However, that broke XO-4, which now just does: mmc2: Signal voltage switch failed, power cycling card (retries = 10) mmc2: error -110 whilst initialising SD card (no more time to debug exactly whats happening) All tests with the same 32GB SD storage card. I wonder if this difference in behaviour is related to the difference in kernel versions on each platform (3.0 vs 3.5). I would like to test with 3.5 or newer running on both, but this requires a bit of setup work for the XO-1.75 first (long story). And I'm out of time at this point :( this was a borrowed SD card. Daniel From 664afe4de295d3783d335a737ce239cebf5885f2 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 23 Oct 2012 15:58:33 -0600 Subject: [PATCH] update sdhci for voltage changing fixes --- drivers/mmc/host/sdhci.c | 72 +++++++++--------------------------------------- 1 file changed, 13 insertions(+), 59 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 07a5346..1955406 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1587,9 +1587,7 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, struct mmc_ios *ios) { - u8 pwr; - u16 clk, ctrl; - u32 present_state; + u16 ctrl; /* * Signal Voltage Switching is only applicable for Host Controllers @@ -1622,62 +1620,9 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, } } else if (!(ctrl & SDHCI_CTRL_VDD_180) && (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) { - /* Stop SDCLK */ - clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); - clk &= ~SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); - - /* Check whether DAT[3:0] is 0000 */ - present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); - if (!((present_state & SDHCI_DATA_LVL_MASK) >> - SDHCI_DATA_LVL_SHIFT)) { - /* - * Enable 1.8V Signal Enable in the Host Control2 - * register - */ - ctrl |= SDHCI_CTRL_VDD_180; - sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); - - /* Wait for 5ms */ - usleep_range(5000, 5500); - - ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); - if (ctrl & SDHCI_CTRL_VDD_180) { - /* Provide SDCLK again and wait for 1ms*/ - clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); - clk |= SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); - usleep_range(1000, 1500); - - /* - * If DAT[3:0] level is 1111b, then the card - * was successfully switched to 1.8V signaling. - */ - present_state = sdhci_readl(host, - SDHCI_PRESENT_STATE); - if ((present_state & SDHCI_DATA_LVL_MASK) == - SDHCI_DATA_LVL_MASK) - return 0; - } - } - - /* - * If we are here, that means the switch to 1.8V signaling - * failed. We power cycle the card, and retry initialization - * sequence by setting S18R to 0. - */ - pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); - pwr &= ~SDHCI_POWER_ON; - sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); - - /* Wait for 1ms as per the spec */ - usleep_range(1000, 1500); - pwr |= SDHCI_POWER_ON; - sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); - - pr_info(DRIVER_NAME ": Switching to 1.8V signalling " - "voltage failed, retrying with S18R set to 0\n"); - return -EAGAIN; + ctrl |= SDHCI_CTRL_VDD_180; + sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); + return 0; } else /* No signal voltage switch required */ return 0; @@ -1931,11 +1876,20 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable) sdhci_runtime_pm_put(host); } +static int sdhci_card_busy(struct mmc_host *mmc, int keep_busy) +{ + struct sdhci_host *host = mmc_priv(mmc); + u32 present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); + + return (present_state & SDHCI_DATA_LVL_MASK) != SDHCI_DATA_LVL_MASK; +} + static const struct mmc_host_ops sdhci_ops = { .request = sdhci_request, .set_ios = sdhci_set_ios, .get_ro = sdhci_get_ro, .hw_reset = sdhci_hw_reset, + .card_busy = sdhci_card_busy, .enable_sdio_irq = sdhci_enable_sdio_irq, .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, .execute_tuning = sdhci_execute_tuning,