From patchwork Tue Feb 10 12:51:51 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 5806941 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 500CE9F336 for ; Tue, 10 Feb 2015 12:52:34 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7CFF020109 for ; Tue, 10 Feb 2015 12:52:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E2C0420103 for ; Tue, 10 Feb 2015 12:52:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755405AbbBJMwb (ORCPT ); Tue, 10 Feb 2015 07:52:31 -0500 Received: from mailout2.w1.samsung.com ([210.118.77.12]:38115 "EHLO mailout2.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755304AbbBJMwa (ORCPT ); Tue, 10 Feb 2015 07:52:30 -0500 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) by mailout2.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0NJK00K3S3Y6SD90@mailout2.w1.samsung.com> for linux-mmc@vger.kernel.org; Tue, 10 Feb 2015 12:56:30 +0000 (GMT) X-AuditID: cbfec7f5-b7fc86d0000066b7-d7-54d9fe78f239 Received: from eusync3.samsung.com ( [203.254.199.213]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id 29.E8.26295.87EF9D45; Tue, 10 Feb 2015 12:50:00 +0000 (GMT) Received: from AMDC1061.digital.local ([106.116.147.88]) by eusync3.samsung.com (Oracle Communications Messaging Server 7u4-23.01 (7.0.4.23.0) 64bit (built Aug 10 2011)) with ESMTPA id <0NJK007293RC3X30@eusync3.samsung.com>; Tue, 10 Feb 2015 12:52:27 +0000 (GMT) From: Andrzej Hajda To: linux-mmc@vger.kernel.org Cc: Andrzej Hajda , Seungwon Jeon , Jaehoon Chung , Chris Ball , Ulf Hansson , Marek Szyprowski , Kyungmin Park Subject: [PATCH] mmc: dw_mmc: add status check before clock update Date: Tue, 10 Feb 2015 13:51:51 +0100 Message-id: <1423572711-13787-1-git-send-email-a.hajda@samsung.com> X-Mailer: git-send-email 1.9.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrHJMWRmVeSWpSXmKPExsVy+t/xq7oV/26GGJyaYG1xa905VosJl7cz Wtz41cZqcbbpDbvFkf/9jBZrj9xlt/hw/yKzxfG14Q4cHneu7WHzuPFqIZNH35ZVjB6fN8kF sERx2aSk5mSWpRbp2yVwZbx7dp694KVAxZPdKxgbGN/ydjFyckgImEicWXqcCcIWk7hwbz1b FyMXh5DAUkaJOwtOsEI4fUwS29/cZAapYhPQlPi7+SYbiC0iICvx888FsA5mgVlMEmvefAAr EhZwkphx6Q8LiM0ioCrRsGMJmM0r4Cxx4f98doh1chInj01mncDIvYCRYRWjaGppckFxUnqu kV5xYm5xaV66XnJ+7iZGSJh83cG49JjVIUYBDkYlHt4LV26ECLEmlhVX5h5ilOBgVhLhZfh0 M0SINyWxsiq1KD++qDQntfgQIxMHp1QDY9Y6qe9SOVPvzjdsmsf+72rRTu1/09pqFKXZtVZd bSrb68b0MNlExvm94uX3Rv7Mi2r25cwomndgtsmU01GWZZvP6xzdIdfxzHfGm+7YOSLavaL3 v666zuG1KlIl6k7Or4sRbTyvL81XXhH8ual8k7run8/pO1bttE/gPi9ht/ZlKv/U1zW785RY ijMSDbWYi4oTAc1k3fTxAQAA Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP According to specs for version 250A, status register should be tested before clock update. Otherwise in case MMC card is missing mci_send_cmd timeouts and subsequent CTYPE registry write causes system hang. This behavior has been observed on Exynos5422/Odroid-XU3. Signed-off-by: Andrzej Hajda --- drivers/mmc/host/dw_mmc.c | 26 ++++++++++++++++++++++++-- drivers/mmc/host/dw_mmc.h | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 67c0451..5852067 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -878,6 +878,25 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) cmd, arg, cmd_status); } +static bool dw_mci_wait_busy(struct dw_mci *host) +{ + unsigned long timeout; + + if (host->verid < DW_MMC_250A) + return true; + + timeout = jiffies + msecs_to_jiffies(500); + while (time_before(jiffies, timeout)) { + if (!(mci_readl(host, STATUS) & SDMMC_STATUS_BUSY)) + return true; + + usleep(1000, 2000); + } + dev_err(host->dev, "Busy timeout\n"); + + return false; +} + static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) { struct dw_mci *host = slot->host; @@ -891,8 +910,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) sdmmc_cmd_bits |= SDMMC_CMD_VOLT_SWITCH; if (!clock) { - mci_writel(host, CLKENA, 0); - mci_send_cmd(slot, sdmmc_cmd_bits, 0); + if (dw_mci_wait_busy(host)) { + mci_writel(host, CLKENA, 0); + mci_send_cmd(slot, sdmmc_cmd_bits, 0); + } else + return; } else if (clock != host->current_speed || force_clkinit) { div = host->bus_hz / clock; if (host->bus_hz % clock && host->bus_hz > clock) diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 0d0f7a27..ea6d4d1 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -15,6 +15,7 @@ #define _DW_MMC_H_ #define DW_MMC_240A 0x240a +#define DW_MMC_250A 0x250a #define SDMMC_CTRL 0x000 #define SDMMC_PWREN 0x004