From patchwork Wed Mar 9 16:51:16 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raffaele Recalcati X-Patchwork-Id: 86129 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 67194B6F0D for ; Thu, 10 Mar 2011 03:51:41 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6202628093; Wed, 9 Mar 2011 17:51:36 +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 Gg5LCP36qCGp; Wed, 9 Mar 2011 17:51:36 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CA5452809C; Wed, 9 Mar 2011 17:51:31 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 411A528088 for ; Wed, 9 Mar 2011 17:51:29 +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 Bja4ccyJ1rnZ for ; Wed, 9 Mar 2011 17:51:28 +0100 (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-ey0-f172.google.com (mail-ey0-f172.google.com [209.85.215.172]) by theia.denx.de (Postfix) with ESMTPS id 05FC328089 for ; Wed, 9 Mar 2011 17:51:26 +0100 (CET) Received: by eye13 with SMTP id 13so210403eye.3 for ; Wed, 09 Mar 2011 08:51:25 -0800 (PST) Received: by 10.213.14.148 with SMTP id g20mr3957777eba.80.1299689485428; Wed, 09 Mar 2011 08:51:25 -0800 (PST) Received: from localhost.localdomain (host41-16-static.112-2-b.business.telecomitalia.it [2.112.16.41]) by mx.google.com with ESMTPS id b52sm1702392eei.7.2011.03.09.08.51.23 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 09 Mar 2011 08:51:24 -0800 (PST) From: Raffaele Recalcati To: u-boot list Date: Wed, 9 Mar 2011 17:51:16 +0100 Message-Id: <1299689478-22747-2-git-send-email-lamiaposta71@gmail.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1299689478-22747-1-git-send-email-lamiaposta71@gmail.com> References: <1299689478-22747-1-git-send-email-lamiaposta71@gmail.com> Cc: Raffaele Recalcati Subject: [U-Boot] [RFC 1/3] mmc: checking status after commands with R1b response X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 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 From: Raffaele Recalcati It is a recommended to check card status after these kind of commands. This is done using CMD13 (SEND_STATUS) JEDEC command. In case of error the previous command is issued again. Signed-off-by: Raffaele Recalcati --- drivers/mmc/mmc.c | 106 +++++++++++++++++++++++++++++++++++++++-------------- include/mmc.h | 4 ++ 2 files changed, 82 insertions(+), 28 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 6805b33..53ed36f 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -48,6 +48,32 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) return mmc->send_cmd(mmc, cmd, data); } +int mmc_send_status(struct mmc *mmc) +{ + struct mmc_cmd cmd; + int err; + int timeout = 1000; + int status; + + cmd.cmdidx = MMC_CMD_SEND_STATUS; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = 0; + cmd.flags = 0; + + do { + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) + return err; + udelay(1000); + if (cmd.response[0] & MMC_STATUS_MASK) { + printf("Status Error: 0x%08X\n", cmd.response[0]); + return 1; + } + } while (!(cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) && timeout--); + + return 0; +} + int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd; @@ -82,6 +108,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src) { struct mmc_cmd cmd; struct mmc_data data; + int timeout = 1000; if ((start + blkcnt) > mmc->block_dev.lba) { printf("MMC: block number 0x%lx exceeds max(0x%lx)\n", @@ -113,14 +140,22 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src) } if (blkcnt > 1) { - cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; - cmd.cmdarg = 0; - cmd.resp_type = MMC_RSP_R1b; - cmd.flags = 0; - if (mmc_send_cmd(mmc, &cmd, NULL)) { - printf("mmc fail to send stop cmd\n"); - return 0; - } + do { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + cmd.flags = 0; + if (mmc_send_cmd(mmc, &cmd, NULL)) { + printf("mmc fail to send stop cmd\n"); + return 0; + } + + udelay(1000); + + } while (mmc_send_status(mmc) && timeout--); + + if (!timeout) + printf("mmc send status failed\n"); } return blkcnt; @@ -158,6 +193,7 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt) { struct mmc_cmd cmd; struct mmc_data data; + int timeout = 1000; if (blkcnt > 1) cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; @@ -181,14 +217,17 @@ int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt) return 0; if (blkcnt > 1) { - cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; - cmd.cmdarg = 0; - cmd.resp_type = MMC_RSP_R1b; - cmd.flags = 0; - if (mmc_send_cmd(mmc, &cmd, NULL)) { - printf("mmc fail to send stop cmd\n"); - return 0; - } + do { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + cmd.flags = 0; + if (mmc_send_cmd(mmc, &cmd, NULL)) { + printf("mmc fail to send stop cmd\n"); + return 0; + } + udelay(1000); + } while (mmc_send_status(mmc) && timeout--); } return blkcnt; @@ -369,15 +408,23 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd) int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) { struct mmc_cmd cmd; + int timeout = 1000; + int ret; - cmd.cmdidx = MMC_CMD_SWITCH; - cmd.resp_type = MMC_RSP_R1b; - cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (index << 16) | - (value << 8); - cmd.flags = 0; + do { + cmd.cmdidx = MMC_CMD_SWITCH; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (index << 16) | + (value << 8); + cmd.flags = 0; + + ret = mmc_send_cmd(mmc, &cmd, NULL); + udelay(1000); + } while (mmc_send_status(mmc) && timeout--); + + return ret; - return mmc_send_cmd(mmc, &cmd, NULL); } int mmc_change_freq(struct mmc *mmc) @@ -610,6 +657,7 @@ int mmc_startup(struct mmc *mmc) u64 cmult, csize; struct mmc_cmd cmd; char ext_csd[512]; + int timeout = 1000; /* Put the Card in Identify Mode */ cmd.cmdidx = MMC_CMD_ALL_SEND_CID; @@ -716,11 +764,13 @@ int mmc_startup(struct mmc *mmc) mmc->write_bl_len = 512; /* Select the card, and put it into Transfer Mode */ - cmd.cmdidx = MMC_CMD_SELECT_CARD; - cmd.resp_type = MMC_RSP_R1b; - cmd.cmdarg = mmc->rca << 16; - cmd.flags = 0; - err = mmc_send_cmd(mmc, &cmd, NULL); + do { + cmd.cmdidx = MMC_CMD_SELECT_CARD; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = mmc->rca << 16; + cmd.flags = 0; + err = mmc_send_cmd(mmc, &cmd, NULL); + } while (mmc_send_status(mmc) && timeout--); if (err) return err; diff --git a/include/mmc.h b/include/mmc.h index fcd0fd1..4ee8e1c 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -94,6 +94,10 @@ #define OCR_BUSY 0x80000000 #define OCR_HCS 0x40000000 +#define MMC_STATUS_MASK (~0x0206BF7F) +#define MMC_STATUS_RDY_FOR_DATA (1<<8) +#define MMC_STATUS_CURR_STATE (0xf<<9) + #define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ #define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */