From patchwork Tue Feb 10 14:29:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Hajda X-Patchwork-Id: 5807761 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A2440BF440 for ; Tue, 10 Feb 2015 14:29:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CC5CA2011D for ; Tue, 10 Feb 2015 14:29:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4AAF62010C for ; Tue, 10 Feb 2015 14:29:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756379AbbBJO3c (ORCPT ); Tue, 10 Feb 2015 09:29:32 -0500 Received: from mailout4.w1.samsung.com ([210.118.77.14]:37814 "EHLO mailout4.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756307AbbBJO3b (ORCPT ); Tue, 10 Feb 2015 09:29:31 -0500 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0NJK00KL38FTN1B0@mailout4.w1.samsung.com> for linux-mmc@vger.kernel.org; Tue, 10 Feb 2015 14:33:29 +0000 (GMT) X-AuditID: cbfec7f4-b7f126d000001e9a-04-54da15381e13 Received: from eusync2.samsung.com ( [203.254.199.212]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 57.55.07834.8351AD45; Tue, 10 Feb 2015 14:27:04 +0000 (GMT) Received: from AMDC1061.digital.local ([106.116.147.88]) by eusync2.samsung.com (Oracle Communications Messaging Server 7u4-23.01 (7.0.4.23.0) 64bit (built Aug 10 2011)) with ESMTPA id <0NJK00FSM890J640@eusync2.samsung.com>; Tue, 10 Feb 2015 14:29:29 +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: [RFC PATCH] mmc: dw_mmc: add status check before clock update Date: Tue, 10 Feb 2015 15:29:19 +0100 Message-id: <1423578559-27947-1-git-send-email-a.hajda@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1423572711-13787-1-git-send-email-a.hajda@samsung.com> References: <1423572711-13787-1-git-send-email-a.hajda@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrMJMWRmVeSWpSXmKPExsVy+t/xK7oWordCDE6uFLe4te4cq8WEy9sZ LW78amO1ONv0ht3iyP9+Rou1R+6yW3y4f5HZ4vjacAcOjzvX9rB53Hi1kMmjb8sqRo/Pm+QC WKK4bFJSczLLUov07RK4MpZtnslYcEawYumSuAbG3XxdjJwcEgImEh8+nWaHsMUkLtxbzwZi CwksZZTY0JbTxcgFZPcxScw6vYoVJMEmoCnxd/NNsCIRAVmJn38usIEUMQvMYpJY8+YDM0hC WMBN4kvLK8YuRg4OFgFVieYTSiBhXgFnib6OK0wQy+QkTh6bDDaTU8BF4sv3eawQi50lPq/7 zjaBkXcBI8MqRtHU0uSC4qT0XEO94sTc4tK8dL3k/NxNjJCA+rKDcfExq0OMAhyMSjy8ARNu hgixJpYVV+YeYpTgYFYS4WX4BBTiTUmsrEotyo8vKs1JLT7EyMTBKdXAyDrFK2L6utIls8Kq /7E7G/00yCn4J3dVznXVRNeIWf94XkUu+pNmJSag8YZf97rwjvDCT4Gqcz4cUy2fo2Zqfbjy 2n/zq18FcrQtii8LnWS+MkPi8I8ZB5mr7k5MC2c9YCvC9Kjz8DvFun//bQ4duryQdcL54x/f TsnzCtLewur8d+tk6QTFACWW4oxEQy3mouJEAJIWfvkGAgAA 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 --- Hi, This version corrects usleep to usleep_range function call. Regards Andrzej --- 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..6619c8a 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_range(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