From patchwork Wed Jul 25 15:33:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 1238351 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 97266DFFCD for ; Wed, 25 Jul 2012 15:33:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751860Ab2GYPdj (ORCPT ); Wed, 25 Jul 2012 11:33:39 -0400 Received: from mail-qa0-f74.google.com ([209.85.216.74]:41894 "EHLO mail-qa0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754670Ab2GYPdX (ORCPT ); Wed, 25 Jul 2012 11:33:23 -0400 Received: by qabg24 with SMTP id g24so111248qab.1 for ; Wed, 25 Jul 2012 08:33:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=y/a/Hs/8OnJM9W8+7Gkt38m1x0BByXhlaURhFFwsXAU=; b=JP3Tb7aUT2Or8nO6vy/x3gryeuV9AUcSDl0RlLLqCKaTXyvBtBdugp0j+9/z4PCCCD 9tnavfY/phRO12Iy3YImfVto5U3macV2tDGQJbWmtevUPRKEuclt4WMQMhNy5nR3c8Kv mQ5JpU090b51RWG6jeo5BsRrUGjwmUt7r040Hcg7jsE56NWoRnJ23/GvPvCzAfR9TXBW 65hajkMjTMZ9a9t7VOgUqhu8XDcxn8gsmgpua1zzk8ZpX8wV3BW9G3ZLn7Q6wCOnBbo6 pGsWdEa/tBYZiJRB/DIO+tYhQX+3FrE1ad6gkem8ByQPLwQT6tvgFwIbXBCcZlmHSyBo ubYw== Received: by 10.236.76.227 with SMTP id b63mr9665158yhe.21.1343230402412; Wed, 25 Jul 2012 08:33:22 -0700 (PDT) Received: by 10.236.76.227 with SMTP id b63mr9665138yhe.21.1343230402343; Wed, 25 Jul 2012 08:33:22 -0700 (PDT) Received: from wpzn3.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id c61si2908140yhm.3.2012.07.25.08.33.22 (version=TLSv1/SSLv3 cipher=AES128-SHA); Wed, 25 Jul 2012 08:33:22 -0700 (PDT) Received: from peppermint.mtv.corp.google.com (peppermint.mtv.corp.google.com [172.22.162.25]) by wpzn3.hot.corp.google.com (Postfix) with ESMTP id 25FBD100047; Wed, 25 Jul 2012 08:33:22 -0700 (PDT) Received: by peppermint.mtv.corp.google.com (Postfix, from userid 121310) id C268E19AA34; Wed, 25 Jul 2012 08:33:21 -0700 (PDT) From: Doug Anderson To: linux-mmc@vger.kernel.org Cc: Chris Ball , Will Newton , James Hogan , Seungwon Jeon , Jaehoon Chung , linux-kernel@vger.kernel.org, Grant Grundler , Olof Johansson , shashidharh@vayavyalabs.com, ki0351.kim@samsung.com, Doug Anderson Subject: [PATCH v4] mmc: dw_mmc: Disable low power mode if SDIO interrupts are used Date: Wed, 25 Jul 2012 08:33:17 -0700 Message-Id: <1343230397-10500-1-git-send-email-dianders@chromium.org> X-Mailer: git-send-email 1.7.7.3 In-Reply-To: References: X-Gm-Message-State: ALoCoQlN7B3ery+T+Bz+BUAoUUGOkRuk9VnrAjAuBxISAPoOTjSWmiQdcmcDM7vjCphf8cO9BGP3ArpgGqcO+Fb7S9/qZ7RPDmCKrmyAZXWyVR2QvRoOevaDTBJdrqoLVfWNrq+m0sEEurOJUdNi3UiPyahbA+UmtbZUAqj6aJtRZABN4m9PdpY39c9Kf31j3hRb6QryTlY0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org The documentation for the dw_mmc part says that the low power mode should normally only be set for MMC and SD memory and should be turned off for SDIO cards that need interrupts detected. The best place I could find to do this is when the SDIO interrupt was first enabled. I rely on the fact that dw_mci_setup_bus() will be called when it's time to reenable. Signed-off-by: Doug Anderson Acked-by: Seungwon Jeon --- Changes in v4: - Don't regenerate slot variable when we already had it. Changes in v3: - Commenting fixes requested by Seungwoon Jeon and Jaehoon Chung. - Only pass 'slot' to the low power disable function since whole mmc structure wasn't needed. Changes in v2: - Commenting fixes requested by Grant Grundler. - Be extra certain that we don't re-turn on the low power mode in CLKENA in dw_mci_setup_bus() if SDIO interrupts are enabled. There are no known instances of this happening but it's good to be safe. drivers/mmc/host/dw_mmc.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 files changed, 38 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 72dc3cd..882748b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) { struct dw_mci *host = slot->host; u32 div; + u32 clk_en_a; if (slot->clock != host->current_speed) { div = host->bus_hz / slot->clock; @@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); - /* enable clock */ - mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE | - SDMMC_CLKEN_LOW_PWR) << slot->id)); + /* enable clock; only low power if no SDIO */ + clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; + if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) + clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; + mci_writel(host, CLKENA, clk_en_a); /* inform CIU */ mci_send_cmd(slot, @@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc) return present; } +/* + * Disable lower power mode. + * + * Low power mode will stop the card clock when idle. According to the + * description of the CLKENA register we should disable low power mode + * for SDIO cards if we need SDIO interrupts to work. + * + * This function is fast if low power mode is already disabled. + */ +static void dw_mci_disable_low_power(struct dw_mci_slot *slot) +{ + struct dw_mci *host = slot->host; + u32 clk_en_a; + const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; + + clk_en_a = mci_readl(host, CLKENA); + + if (clk_en_a & clken_low_pwr) { + mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | + SDMMC_CMD_PRV_DAT_WAIT, 0); + } +} + static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) { struct dw_mci_slot *slot = mmc_priv(mmc); @@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) /* Enable/disable Slot Specific SDIO interrupt */ int_mask = mci_readl(host, INTMASK); if (enb) { + /* + * Turn off low power mode if it was enabled. This is a bit of + * a heavy operation and we disable / enable IRQs a lot, so + * we'll leave low power mode disabled and it will get + * re-enabled again in dw_mci_setup_bus(). + */ + dw_mci_disable_low_power(slot); + mci_writel(host, INTMASK, (int_mask | SDMMC_INT_SDIO(slot->id))); } else {