From patchwork Fri Aug 30 15:11:43 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Seungwon Jeon X-Patchwork-Id: 2852109 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.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 81F6EC0AB5 for ; Fri, 30 Aug 2013 15:11:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4A01D2018D for ; Fri, 30 Aug 2013 15:11:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D868220182 for ; Fri, 30 Aug 2013 15:11:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755904Ab3H3PLq (ORCPT ); Fri, 30 Aug 2013 11:11:46 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:47151 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752794Ab3H3PLp (ORCPT ); Fri, 30 Aug 2013 11:11:45 -0400 Received: from epcpsbgr1.samsung.com (u141.gpu120.samsung.co.kr [203.254.230.141]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MSC00E8LNJK1260@mailout1.samsung.com> for linux-mmc@vger.kernel.org; Sat, 31 Aug 2013 00:11:44 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [203.254.230.47]) by epcpsbgr1.samsung.com (EPCPMTA) with SMTP id 03.02.30629.036B0225; Sat, 31 Aug 2013 00:11:44 +0900 (KST) X-AuditID: cbfee68d-b7fe86d0000077a5-4d-5220b630c55d Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 91.31.09055.F26B0225; Sat, 31 Aug 2013 00:11:43 +0900 (KST) Received: from DOTGIHJUN01 ([12.23.118.161]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MSC001GENJJCA30@mmp1.samsung.com>; Sat, 31 Aug 2013 00:11:43 +0900 (KST) From: Seungwon Jeon To: linux-mmc@vger.kernel.org Cc: 'Chris Ball' , 'Jaehoon Chung' References: In-reply-to: Subject: [PATCH 03/22] mmc: dw_mmc: Honor requests to set the clock to 0 Date: Sat, 31 Aug 2013 00:11:43 +0900 Message-id: <000601cea593$3cb8c280$b62a4780$%jun@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-transfer-encoding: 7bit X-Mailer: Microsoft Office Outlook 12.0 Thread-index: Ac03z3aCvVFr8FaITt2vKVQKst76fw3OcIrwS9fJ1BAByUIdcA== Content-language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrAIsWRmVeSWpSXmKPExsVy+t8zfV2DbQpBBiteM1tsf72RzeLGrzZW iyP/+xkdmD0OXVnL6NG3ZRWjx+dNcgHMUVw2Kak5mWWpRfp2CVwZz+4qFDxVrvi6YSNLA+Mi mS5GTg4JAROJnaeXMkLYYhIX7q1n62Lk4hASWMYosflBJyNM0eR/h5khEosYJVpn7WKEcP4w Suy+9oEVpIpNQEvi75s3zCC2iICsxM8/F9hAbGYBb4lX89cANXAANXBLrG4OAglzCvBIrPvT CVYuLOAh0fpuIlg5i4CqxNoFL8AW8wrYShx5uIkFwhaU+DH5HgvIGGYBdYkpU3IhpstLbF7z lhkkLAEUfvRXF+IAJ4mzTQcZIUpEJPa9eAd2sYTALnaJbQfeMUGsEpD4NvkQC0SvrMSmA8wQ 70pKHFxxg2UCo8QsJItnISyehWTxLCQbFjCyrGIUTS1ILihOSi8y1CtOzC0uzUvXS87P3cQI ib3eHYy3D1gfYkwG2j6RWUo0OR8Yu3kl8YbGZkYWpiamxkbmlmakCSuJ86q1WAcKCaQnlqRm p6YWpBbFF5XmpBYfYmTi4JRqYHR4uL2NPeG6YlCl4d71R/RfV2w3MdF4fnny+9XX+/6/3sc1 v/lI4Grt5WxiLLLKp6P6Xy6YumPGN4u5bnF3YuV8vh1a8nR54uLEy0Wze49zfZv086KGx+Ml cypXfDn9+sb/3wrh64/4635/wLqF1ebHA9mZOsGuUv3mm6Z861m+5WQjf9uBB8x6SizFGYmG WsxFxYkAX3a+PNMCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprLKsWRmVeSWpSXmKPExsVy+t9jAV39bQpBBgsP2Vhsf72RzeLGrzZW iyP/+xkdmD0OXVnL6NG3ZRWjx+dNcgHMUQ2MNhmpiSmpRQqpecn5KZl56bZK3sHxzvGmZgaG uoaWFuZKCnmJuam2Si4+AbpumTlAm5QUyhJzSoFCAYnFxUr6dpgmhIa46VrANEbo+oYEwfUY GaCBhHWMGc/uKhQ8Va74umEjSwPjIpkuRk4OCQETicn/DjND2GISF+6tZ+ti5OIQEljEKNE6 axcjhPOHUWL3tQ+sIFVsAloSf9+8AesQEZCV+PnnAhuIzSzgLfFq/hqgBg6gBm6J1c1BIGFO AR6JdX86wcqFBTwkWt9NBCtnEVCVWLvgBSOIzStgK3Hk4SYWCFtQ4sfkeywgY5gF1CWmTMmF mC4vsXnNW2aQsARQ+NFfXYgDnCTONh1khCgRkdj34h3jBEahWUgGzUIYNAvJoFlIOhYwsqxi FE0tSC4oTkrPNdQrTswtLs1L10vOz93ECI7sZ1I7GFc2WBxiFOBgVOLhTViqECTEmlhWXJl7 iFGCg1lJhPfjYqAQb0piZVVqUX58UWlOavEhxmSgNycyS4km5wOTTl5JvKGxiZmRpZGZhZGJ uTlpwkrivAdarQOFBNITS1KzU1MLUotgtjBxcEo1MFaHR1Usvf74Dstj00Oqr7+m/lnw7MjM ZY6sBZtKhKyENNIqN7w7sX2eX/gXa71Pk+/w8mcFy/n18dw612ITsnVKC28t+4sFTusUP9U9 y1oge64k+dfdXZ5Hg7qml+0WtdIzcOzbav/B8mKv133bY+I1+xyUrQL5DC2a1q+LzuBvr2ha cK7rpBJLcUaioRZzUXEiAEXHzbAwAwAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-9.0 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 From: Doug Anderson Previously the dw_mmc driver would ignore any requests to disable the card's clock. This doesn't seem like a good thing in general, but had one extra bad side effect in the following situation: * mmc core would set clk to 400kHz at boot time while scanning * mmc core would set clk to 0 since no card, but it would be ignored. * suspend to ram and resume; clocks in the dw_mmc IP block are now 0 but dw_mmc thinks that they're 400kHz (it ignored the set to 0). * insert card * mmc core would set clk to 400kHz which would be considered a no-op. Note that if there is no card in the slot and we do a suspend/resume cycle, we _do_ still end up with differences in a dw_mmc register dump, but the differences are clock related and we've got the clock disabled both before and after, so this should be OK. Signed-off-by: Doug Anderson Signed-off-by: Seungwon Jeon --- drivers/mmc/host/dw_mmc.c | 44 ++++++++++++++++++++++++++++---------------- 1 files changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index dc81034..3ad0fd8 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -88,6 +88,9 @@ struct idmac_desc { * @queue_node: List node for placing this node in the @queue list of * &struct dw_mci. * @clock: Clock rate configured by set_ios(). Protected by host->lock. + * @__clk_old: The last updated clock with reflecting clock divider. + * Keeping track of this helps us to avoid spamming the console + * with CONFIG_MMC_CLKGATE. * @flags: Random state bits associated with the slot. * @id: Number of this slot. * @last_detect_state: Most recently observed card detect state. @@ -105,6 +108,7 @@ struct dw_mci_slot { struct list_head queue_node; unsigned int clock; + unsigned int __clk_old; unsigned long flags; #define DW_MMC_CARD_PRESENT 0 #define DW_MMC_CARD_NEED_INIT 1 @@ -632,24 +636,31 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) { struct dw_mci *host = slot->host; + unsigned int clock = slot->clock; u32 div; u32 clk_en_a; - if (slot->clock != host->current_speed || force_clkinit) { - div = host->bus_hz / slot->clock; - if (host->bus_hz % slot->clock && host->bus_hz > slot->clock) + if (!clock) { + mci_writel(host, CLKENA, 0); + mci_send_cmd(slot, + SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); + } else if (clock != host->current_speed || force_clkinit) { + div = host->bus_hz / clock; + if (host->bus_hz % clock && host->bus_hz > clock) /* * move the + 1 after the divide to prevent * over-clocking the card. */ div += 1; - div = (host->bus_hz != slot->clock) ? DIV_ROUND_UP(div, 2) : 0; + div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0; - dev_info(&slot->mmc->class_dev, - "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ" - " div = %d)\n", slot->id, host->bus_hz, slot->clock, - div ? ((host->bus_hz / div) >> 1) : host->bus_hz, div); + if ((clock << div) != slot->__clk_old || force_clkinit) + dev_info(&slot->mmc->class_dev, + "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n", + slot->id, host->bus_hz, clock, + div ? ((host->bus_hz / div) >> 1) : + host->bus_hz, div); /* disable clock */ mci_writel(host, CLKENA, 0); @@ -676,9 +687,12 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); - host->current_speed = slot->clock; + /* keep the clock with reflecting clock dividor */ + slot->__clk_old = clock << div; } + host->current_speed = clock; + /* Set the current slot bus width */ mci_writel(host, CTYPE, (slot->ctype << slot->id)); } @@ -807,13 +821,11 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) mci_writel(slot->host, UHS_REG, regs); - if (ios->clock) { - /* - * Use mirror of ios->clock to prevent race with mmc - * core ios update when finding the minimum. - */ - slot->clock = ios->clock; - } + /* + * Use mirror of ios->clock to prevent race with mmc + * core ios update when finding the minimum. + */ + slot->clock = ios->clock; if (drv_data && drv_data->set_ios) drv_data->set_ios(slot->host, ios);