From patchwork Thu Nov 1 05:02:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Fleming X-Patchwork-Id: 196086 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 4B78F2C0131 for ; Thu, 1 Nov 2012 18:18:23 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id F23D94A60F; Thu, 1 Nov 2012 08:18:05 +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 4ilej16Mv0QA; Thu, 1 Nov 2012 08:18:05 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 1B2024A610; Thu, 1 Nov 2012 08:17:50 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 252C84A604 for ; Thu, 1 Nov 2012 06:02:51 +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 lVwex1kPGm3W for ; Thu, 1 Nov 2012 06:02:48 +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 tx2outboundpool.messaging.microsoft.com (tx2ehsobe002.messaging.microsoft.com [65.55.88.12]) by theia.denx.de (Postfix) with ESMTPS id 5BDD64A603 for ; Thu, 1 Nov 2012 06:02:46 +0100 (CET) Received: from mail85-tx2-R.bigfish.com (10.9.14.248) by TX2EHSOBE008.bigfish.com (10.9.40.28) with Microsoft SMTP Server id 14.1.225.23; Thu, 1 Nov 2012 05:02:42 +0000 Received: from mail85-tx2 (localhost [127.0.0.1]) by mail85-tx2-R.bigfish.com (Postfix) with ESMTP id 7552B603CF; Thu, 1 Nov 2012 05:02:42 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 0 X-BigFish: VS0(zzzz1202h1d1ah1d2ahzz8275bhz2dh2a8h668h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h1155h) Received: from mail85-tx2 (localhost.localdomain [127.0.0.1]) by mail85-tx2 (MessageSwitch) id 1351746161131124_27318; Thu, 1 Nov 2012 05:02:41 +0000 (UTC) Received: from TX2EHSMHS038.bigfish.com (unknown [10.9.14.235]) by mail85-tx2.bigfish.com (Postfix) with ESMTP id 11CDE1C007E; Thu, 1 Nov 2012 05:02:41 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by TX2EHSMHS038.bigfish.com (10.9.99.138) with Microsoft SMTP Server (TLS) id 14.1.225.23; Thu, 1 Nov 2012 05:02:40 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-005.039d.mgd.msft.net (10.84.1.17) with Microsoft SMTP Server (TLS) id 14.2.318.3; Thu, 1 Nov 2012 05:02:39 +0000 Received: from localhost (right.am.freescale.net [10.82.176.228]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id qA152cgD026172; Wed, 31 Oct 2012 22:02:39 -0700 From: Andy Fleming To: Date: Thu, 1 Nov 2012 00:02:38 -0500 Message-ID: <1351746158-19009-1-git-send-email-afleming@freescale.com> X-Mailer: git-send-email 1.7.9.7 MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-Mailman-Approved-At: Thu, 01 Nov 2012 08:17:46 +0100 Cc: marex@denx.de, Chang-Ming.Huang@freescale.com, jh80.chung@samsung.com Subject: [U-Boot] [RFC] mmc: Properly determine maximum supported bus width 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: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de At some point, a confusion arose about the use of the bit definitions in host_caps for bus widths, and the value in ext_csd. By coincidence, a simple shift could convert between one and the other: MMC_MODE_1BIT = 0, EXT_CSD_BUS_WIDTH_1 = 0 MMC_MODE_4BIT = 0x100, EXT_CSD_BUS_WIDTH_4 = 1 MMC_MODE_8BIT = 0x200, EXT_CSD_BUS_WIDTH_8 = 2 However, as host_caps is a bitmask of supported things, there is not, in fact, a one-to-one correspondence. host_caps is capable of containing MODE_4BIT | MODE_8BIT, so nonsensical things were happening where we would try to set the bus width to 12. The new code clarifies the very different namespaces: host_caps/card_caps = bitmask (MMC_MODE_*) ext CSD fields are just an index (EXT_CSD_BUS_WIDTH_*) mmc->bus_width integer number of bits (1, 4, 8) We create arrays to map between the namespaces, like in Linux. Signed-off-by: Andy Fleming Tested-by: Jaehoon Chung Tested-by: Stephen Warren --- This is, I think, the approach we should use to identify the proper bus width for an mmc device. Please review and/or test. drivers/mmc/mmc.c | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 5fbf956..c379a74 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -867,7 +867,7 @@ void mmc_set_bus_width(struct mmc *mmc, uint width) int mmc_startup(struct mmc *mmc) { - int err, width; + int err; uint mult, freq; u64 cmult, csize, capacity; struct mmc_cmd cmd; @@ -1086,21 +1086,44 @@ int mmc_startup(struct mmc *mmc) else mmc->tran_speed = 25000000; } else { - width = ((mmc->host_caps & MMC_MODE_MASK_WIDTH_BITS) >> - MMC_MODE_WIDTH_BITS_SHIFT); - for (; width >= 0; width--) { - /* Set the card to use 4 bit*/ + int idx; + + /* An array of possible bus widths in order of preference */ + static unsigned ext_csd_bits[] = { + EXT_CSD_BUS_WIDTH_8, + EXT_CSD_BUS_WIDTH_4, + EXT_CSD_BUS_WIDTH_1, + }; + + /* An array to map CSD bus widths to host cap bits */ + static unsigned ext_to_hostcaps[] = { + [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT, + [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT, + }; + + /* An array to map chosen bus width to an integer */ + static unsigned widths[] = { + 8, 4, 1, + }; + + for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) { + unsigned int extw = ext_csd_bits[idx]; + + /* + * Check to make sure the controller supports + * this bus width, if it's more than 1 + */ + if (extw != EXT_CSD_BUS_WIDTH_1 && + !(mmc->host_caps & ext_to_hostcaps[extw])) + continue; + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, width); + EXT_CSD_BUS_WIDTH, extw); if (err) continue; - if (!width) { - mmc_set_bus_width(mmc, 1); - break; - } else - mmc_set_bus_width(mmc, 4 * width); + mmc_set_bus_width(mmc, widths[idx]); err = mmc_send_ext_csd(mmc, test_csd); if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \ @@ -1114,7 +1137,7 @@ int mmc_startup(struct mmc *mmc) && memcmp(&ext_csd[EXT_CSD_SEC_CNT], \ &test_csd[EXT_CSD_SEC_CNT], 4) == 0) { - mmc->card_caps |= width; + mmc->card_caps |= ext_to_hostcaps[extw]; break; } }