From patchwork Mon Mar 19 22:12:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Gra=C5=BEvydas_Ignotas?= X-Patchwork-Id: 147661 X-Patchwork-Delegate: afleming@freescale.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 7AE1EB7019 for ; Tue, 20 Mar 2012 09:19:07 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9356E280A1; Mon, 19 Mar 2012 23:19:04 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qMAoPI2ZQxoR; Mon, 19 Mar 2012 23:19:04 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 676882809B; Mon, 19 Mar 2012 23:19:03 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 13A562809B for ; Mon, 19 Mar 2012 23:19:02 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id dU1YAq0KyQUz for ; Mon, 19 Mar 2012 23:19:01 +0100 (CET) X-Greylist: delayed 409 seconds by postgrey-1.27 at theia; Mon, 19 Mar 2012 23:19:00 CET X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-wi0-f180.google.com (mail-wi0-f180.google.com [209.85.212.180]) by theia.denx.de (Postfix) with ESMTPS id 7BFFE28098 for ; Mon, 19 Mar 2012 23:19:00 +0100 (CET) Received: by wibhm17 with SMTP id hm17so3981818wib.9 for ; Mon, 19 Mar 2012 15:18:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer; bh=kqkjfrAPS6bZJaqHAib0jDYgvONuWB2RSi+gs4pcgD4=; b=VfpPLbHuzjLx+iVhFfdirmbUrv2SRyINBD3AtFC5uEzieflnFzO1TsSgohwM4C9PLB jc1mHu2k3nQ1LexE+bJWadCwaZjGn7DJsLzpZfi+GqmICAtWJqvdGY+2mNXUfPfNl/AB rZRnP1NgTefjiYdkjsHaGkVsmEtDrXp1nCMajhszGVB107JxENdeV7ws7vm6E6L1+uuG 08x3UyzwaSFUlxaY6CsvrebQBU5WGN8FuSQIyU9kTamth0tRAHbTk7C1fsoTYugxWSW7 Hs4xjMm7CZvP6tjgzf2laK9vrSW6xjeWoGU8nXvDVJ91w/h+Dj47GW1KNU2eUbl43Z90 rxLg== Received: by 10.216.137.226 with SMTP id y76mr7460674wei.96.1332195131158; Mon, 19 Mar 2012 15:12:11 -0700 (PDT) Received: from localhost.localdomain (ip-88-119-226-136.static.b4net.lt. [88.119.226.136]) by mx.google.com with ESMTPS id e6sm28880515wix.8.2012.03.19.15.12.09 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 19 Mar 2012 15:12:10 -0700 (PDT) From: Grazvydas Ignotas To: u-boot@lists.denx.de Date: Tue, 20 Mar 2012 00:12:06 +0200 Message-Id: <1332195126-24719-1-git-send-email-notasas@gmail.com> X-Mailer: git-send-email 1.7.0.4 Cc: Tom Rini , afleming@gmail.com Subject: [U-Boot] [PATCH] mmc: omap: handle controller errors properly X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de According to OMAP3 TRM, when the controller reports certain errors, driver must perform a software reset. This is done by setting a bit in SYSCTL and waiting it to clear: - SRC on command timeout (CTO) - SRD on data errors (DTO, DCRC and DEB) This fixes a problem seen on OMAP3 pandora board with some cards that won't work with a message printed multiple times: timedout waiting on cmd inhibit to clear Code loosely based on Linux omap_hsmmc driver. Signed-off-by: Grazvydas Ignotas Tested-by: Tom Rini Tested-by: Pali Rohár --- drivers/mmc/omap_hsmmc.c | 36 ++++++++++++++++++++++++++++++++++-- 1 files changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 4b81d0d..06cbebf 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -33,6 +33,10 @@ #include #include +/* common definitions for all OMAPs */ +#define SYSCTL_SRC (1 << 25) +#define SYSCTL_SRD (1 << 26) + /* If we fail after 1 second wait, something is really bad */ #define MAX_RETRY_MS 1000 @@ -195,6 +199,27 @@ static int mmc_init_setup(struct mmc *mmc) return 0; } +/* + * MMC controller internal finite state machine reset + * + * Used to reset command or data internal state machines, using respectively + * SRC or SRD bit of SYSCTL register + */ +static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit) +{ + ulong start; + + mmc_reg_out(&mmc_base->sysctl, bit, bit); + + start = get_timer(0); + while ((readl(&mmc_base->sysctl) & bit) != 0) { + if (get_timer(0) - start > MAX_RETRY_MS) { + printf("%s: timedout waiting for sysctl %x to clear\n", + __func__, bit); + return; + } + } +} static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) @@ -284,9 +309,10 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } } while (!mmc_stat); - if ((mmc_stat & IE_CTO) != 0) + if ((mmc_stat & IE_CTO) != 0) { + mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC); return TIMEOUT; - else if ((mmc_stat & ERRI_MASK) != 0) + } else if ((mmc_stat & ERRI_MASK) != 0) return -1; if (mmc_stat & CC_MASK) { @@ -337,6 +363,9 @@ static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size) } } while (mmc_stat == 0); + if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0) + mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD); + if ((mmc_stat & ERRI_MASK) != 0) return 1; @@ -389,6 +418,9 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, } } while (mmc_stat == 0); + if ((mmc_stat & (IE_DTO | IE_DCRC | IE_DEB)) != 0) + mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD); + if ((mmc_stat & ERRI_MASK) != 0) return 1;