From patchwork Mon Sep 30 14:42:00 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 20709 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ye0-f198.google.com (mail-ye0-f198.google.com [209.85.213.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id E820125A2B for ; Mon, 30 Sep 2013 14:42:13 +0000 (UTC) Received: by mail-ye0-f198.google.com with SMTP id m11sf4939087yen.9 for ; Mon, 30 Sep 2013 07:42:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=mime-version:x-gm-message-state:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=HBUV9NtNBVvCBxmegpUAnrfMNe2L59DRezrXTSm9XKA=; b=a/TVZMqdHX+vNylik4qfX3xCwRuu1EKtxMr1dTpO/ERrrGebmLhoeXeX2R6QjZPha7 UOrx+ilk268Y1nz9+Czno4N9yTLZChafqYK91t6uEJFeTFG1UqDSrVjl/a9/oBSrBmP1 cEN5Y8lcFhhNg4edx1znPESXefQ+hUNxxhHcVyz4dAgpdXW5WitLHgBBiL8/2KZbMTrB K+ZgiiFg1i6M2PZsY94rTKGO8MNPjJGOycDSy1fX7YUnI1XCoGBbE92AyRQOdXeux/Hn GO08ydjiCiqeM8Bnsf1Mc37gB012u9dk9cFaJ2j8GYWymXG1fxyr106jiqWa/XL4zvnI A4mg== X-Received: by 10.236.63.165 with SMTP id a25mr4377458yhd.35.1380552133644; Mon, 30 Sep 2013 07:42:13 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.38.70 with SMTP id e6ls2227052qek.77.gmail; Mon, 30 Sep 2013 07:42:13 -0700 (PDT) X-Received: by 10.58.181.230 with SMTP id dz6mr165064vec.35.1380552133512; Mon, 30 Sep 2013 07:42:13 -0700 (PDT) Received: from mail-vb0-f53.google.com (mail-vb0-f53.google.com [209.85.212.53]) by mx.google.com with ESMTPS id c8si140849vcq.138.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 30 Sep 2013 07:42:13 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.53 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.53; Received: by mail-vb0-f53.google.com with SMTP id i3so3883306vbh.12 for ; Mon, 30 Sep 2013 07:42:13 -0700 (PDT) X-Gm-Message-State: ALoCoQlR9v5q7GGspS5pGsb3jSzWahoDWpFQmql/MR5l+DlNqc2oAQ5rjoAoF7ho0fc0fZ4Rb4Bk X-Received: by 10.52.230.35 with SMTP id sv3mr6018805vdc.27.1380552133380; Mon, 30 Sep 2013 07:42:13 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp110183vcz; Mon, 30 Sep 2013 07:42:12 -0700 (PDT) X-Received: by 10.15.76.68 with SMTP id m44mr664739eey.78.1380552132052; Mon, 30 Sep 2013 07:42:12 -0700 (PDT) Received: from mail-ea0-f173.google.com (mail-ea0-f173.google.com [209.85.215.173]) by mx.google.com with ESMTPS id x42si617190eel.326.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 30 Sep 2013 07:42:12 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.215.173 is neither permitted nor denied by best guess record for domain of ulf.hansson@linaro.org) client-ip=209.85.215.173; Received: by mail-ea0-f173.google.com with SMTP id g10so2745380eak.32 for ; Mon, 30 Sep 2013 07:42:11 -0700 (PDT) X-Received: by 10.15.51.74 with SMTP id m50mr4036683eew.58.1380552131326; Mon, 30 Sep 2013 07:42:11 -0700 (PDT) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id n48sm1803036eeg.17.1969.12.31.16.00.00 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 30 Sep 2013 07:42:10 -0700 (PDT) From: Ulf Hansson To: linux-mmc@vger.kernel.org, Chris Ball Cc: Linus Walleij , Ulf Hansson Subject: [PATCH 2/2] mmc: core: Remove MMC_CLKGATE Date: Mon, 30 Sep 2013 16:42:00 +0200 Message-Id: <1380552120-31003-3-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1380552120-31003-1-git-send-email-ulf.hansson@linaro.org> References: <1380552120-31003-1-git-send-email-ulf.hansson@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ulf.hansson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.53 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , No platforms seems to be using MMC_CLKGATE anymore. Moreover the same clock gating operations are easier to implement using runtime PM, which several host drivers already had converted to. By removing all related code for MMC_CLKGATE, a significant less amount of code needs to be maintained. Signed-off-by: Ulf Hansson --- Documentation/mmc/mmc-dev-attrs.txt | 10 -- drivers/mmc/core/Kconfig | 10 -- drivers/mmc/core/core.c | 116 +---------------- drivers/mmc/core/core.h | 3 - drivers/mmc/core/debugfs.c | 5 - drivers/mmc/core/host.c | 245 ----------------------------------- drivers/mmc/core/mmc.c | 6 +- drivers/mmc/core/sd.c | 12 +- drivers/mmc/core/sdio.c | 5 +- drivers/mmc/core/sdio_irq.c | 10 +- include/linux/mmc/host.h | 27 ---- 11 files changed, 12 insertions(+), 437 deletions(-) diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt index 189bab0..caa5557 100644 --- a/Documentation/mmc/mmc-dev-attrs.txt +++ b/Documentation/mmc/mmc-dev-attrs.txt @@ -72,13 +72,3 @@ Note on raw_rpmb_size_mult: "raw_rpmb_size_mult" is a mutliple of 128kB block. RPMB size in byte is calculated by using the following equation: RPMB partition size = 128kB x raw_rpmb_size_mult - -SD/MMC/SDIO Clock Gating Attribute -================================== - -Read and write access is provided to following attribute. -This attribute appears only if CONFIG_MMC_CLKGATE is enabled. - - clkgate_delay Tune the clock gating delay with desired value in milliseconds. - -echo > /sys/class/mmc_host/mmcX/clkgate_delay diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index 269d072..bb22ffd 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -16,13 +16,3 @@ config MMC_UNSAFE_RESUME This option sets a default which can be overridden by the module parameter "removable=0" or "removable=1". - -config MMC_CLKGATE - bool "MMC host clock gating" - help - This will attempt to aggressively gate the clock to the MMC card. - This is done to save power due to gating off the logic and bus - noise when the MMC card is not in use. Your host driver has to - support handling this in order for it to be of any use. - - If unsure, say N. diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 006ead2..a5ce361 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -185,8 +185,6 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) if (mrq->done) mrq->done(mrq); - - mmc_host_clk_release(host); } } @@ -251,7 +249,6 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mrq->stop->mrq = mrq; } } - mmc_host_clk_hold(host); led_trigger_event(host->led, LED_FULL); host->ops->request(host, mrq); } @@ -482,11 +479,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host, static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, bool is_first_req) { - if (host->ops->pre_req) { - mmc_host_clk_hold(host); + if (host->ops->pre_req) host->ops->pre_req(host, mrq, is_first_req); - mmc_host_clk_release(host); - } } /** @@ -501,11 +495,8 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, int err) { - if (host->ops->post_req) { - mmc_host_clk_hold(host); + if (host->ops->post_req) host->ops->post_req(host, mrq, err); - mmc_host_clk_release(host); - } } /** @@ -983,8 +974,6 @@ static inline void mmc_set_ios(struct mmc_host *host) ios->power_mode, ios->chip_select, ios->vdd, ios->bus_width, ios->timing); - if (ios->clock > 0) - mmc_set_ungated(host); host->ops->set_ios(host, ios); } @@ -993,17 +982,15 @@ static inline void mmc_set_ios(struct mmc_host *host) */ void mmc_set_chip_select(struct mmc_host *host, int mode) { - mmc_host_clk_hold(host); host->ios.chip_select = mode; mmc_set_ios(host); - mmc_host_clk_release(host); } /* * Sets the host clock to the highest possible frequency that * is below "hz". */ -static void __mmc_set_clock(struct mmc_host *host, unsigned int hz) +void mmc_set_clock(struct mmc_host *host, unsigned int hz) { WARN_ON(hz < host->f_min); @@ -1014,77 +1001,13 @@ static void __mmc_set_clock(struct mmc_host *host, unsigned int hz) mmc_set_ios(host); } -void mmc_set_clock(struct mmc_host *host, unsigned int hz) -{ - mmc_host_clk_hold(host); - __mmc_set_clock(host, hz); - mmc_host_clk_release(host); -} - -#ifdef CONFIG_MMC_CLKGATE -/* - * This gates the clock by setting it to 0 Hz. - */ -void mmc_gate_clock(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->clk_lock, flags); - host->clk_old = host->ios.clock; - host->ios.clock = 0; - host->clk_gated = true; - spin_unlock_irqrestore(&host->clk_lock, flags); - mmc_set_ios(host); -} - -/* - * This restores the clock from gating by using the cached - * clock value. - */ -void mmc_ungate_clock(struct mmc_host *host) -{ - /* - * We should previously have gated the clock, so the clock shall - * be 0 here! The clock may however be 0 during initialization, - * when some request operations are performed before setting - * the frequency. When ungate is requested in that situation - * we just ignore the call. - */ - if (host->clk_old) { - BUG_ON(host->ios.clock); - /* This call will also set host->clk_gated to false */ - __mmc_set_clock(host, host->clk_old); - } -} - -void mmc_set_ungated(struct mmc_host *host) -{ - unsigned long flags; - - /* - * We've been given a new frequency while the clock is gated, - * so make sure we regard this as ungating it. - */ - spin_lock_irqsave(&host->clk_lock, flags); - host->clk_gated = false; - spin_unlock_irqrestore(&host->clk_lock, flags); -} - -#else -void mmc_set_ungated(struct mmc_host *host) -{ -} -#endif - /* * Change the bus mode (open drain/push-pull) of a host. */ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) { - mmc_host_clk_hold(host); host->ios.bus_mode = mode; mmc_set_ios(host); - mmc_host_clk_release(host); } /* @@ -1092,10 +1015,8 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) */ void mmc_set_bus_width(struct mmc_host *host, unsigned int width) { - mmc_host_clk_hold(host); host->ios.bus_width = width; mmc_set_ios(host); - mmc_host_clk_release(host); } /** @@ -1365,10 +1286,8 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) ocr &= 3 << bit; - mmc_host_clk_hold(host); host->ios.vdd = bit; mmc_set_ios(host); - mmc_host_clk_release(host); } else { pr_warning("%s: host doesn't support card's voltages\n", mmc_hostname(host)); @@ -1384,11 +1303,8 @@ int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) int old_signal_voltage = host->ios.signal_voltage; host->ios.signal_voltage = signal_voltage; - if (host->ops->start_signal_voltage_switch) { - mmc_host_clk_hold(host); + if (host->ops->start_signal_voltage_switch) err = host->ops->start_signal_voltage_switch(host, &host->ios); - mmc_host_clk_release(host); - } if (err) host->ios.signal_voltage = old_signal_voltage; @@ -1433,7 +1349,6 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage) if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) return -EIO; - mmc_host_clk_hold(host); /* * The card should drive cmd and dat[0:3] low immediately * after the response of cmd11, but wait 1 ms to be sure @@ -1482,8 +1397,6 @@ power_cycle: mmc_power_cycle(host); } - mmc_host_clk_release(host); - return err; } @@ -1492,10 +1405,8 @@ power_cycle: */ void mmc_set_timing(struct mmc_host *host, unsigned int timing) { - mmc_host_clk_hold(host); host->ios.timing = timing; mmc_set_ios(host); - mmc_host_clk_release(host); } /* @@ -1503,10 +1414,8 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing) */ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) { - mmc_host_clk_hold(host); host->ios.drv_type = drv_type; mmc_set_ios(host); - mmc_host_clk_release(host); } /* @@ -1527,8 +1436,6 @@ void mmc_power_up(struct mmc_host *host) if (host->ios.power_mode == MMC_POWER_ON) return; - mmc_host_clk_hold(host); - /* If ocr is set, we use it */ if (host->ocr) bit = ffs(host->ocr) - 1; @@ -1565,8 +1472,6 @@ void mmc_power_up(struct mmc_host *host) * time required to reach a stable voltage. */ mmc_delay(10); - - mmc_host_clk_release(host); } void mmc_power_off(struct mmc_host *host) @@ -1574,8 +1479,6 @@ void mmc_power_off(struct mmc_host *host) if (host->ios.power_mode == MMC_POWER_OFF) return; - mmc_host_clk_hold(host); - host->ios.clock = 0; host->ios.vdd = 0; @@ -1601,8 +1504,6 @@ void mmc_power_off(struct mmc_host *host) * can be successfully turned on again. */ mmc_delay(1); - - mmc_host_clk_release(host); } void mmc_power_cycle(struct mmc_host *host) @@ -2217,9 +2118,7 @@ static void mmc_hw_reset_for_init(struct mmc_host *host) { if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) return; - mmc_host_clk_hold(host); host->ops->hw_reset(host); - mmc_host_clk_release(host); } int mmc_can_reset(struct mmc_card *card) @@ -2251,7 +2150,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check) if (!mmc_can_reset(card)) return -EOPNOTSUPP; - mmc_host_clk_hold(host); mmc_set_clock(host, host->f_init); host->ops->hw_reset(host); @@ -2266,10 +2164,8 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check) cmd.arg = card->rca << 16; cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; err = mmc_wait_for_cmd(card->host, &cmd, 0); - if (!err) { - mmc_host_clk_release(host); + if (!err) return -ENOSYS; - } } host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_DDR); @@ -2284,8 +2180,6 @@ static int mmc_do_hw_reset(struct mmc_host *host, int check) host->ios.timing = MMC_TIMING_LEGACY; mmc_set_ios(host); - mmc_host_clk_release(host); - return host->bus_ops->power_restore(host); } diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 5345d15..f7239ec 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -36,9 +36,6 @@ void mmc_init_erase(struct mmc_card *card); void mmc_set_chip_select(struct mmc_host *host, int mode); void mmc_set_clock(struct mmc_host *host, unsigned int hz); -void mmc_gate_clock(struct mmc_host *host); -void mmc_ungate_clock(struct mmc_host *host); -void mmc_set_ungated(struct mmc_host *host); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 54829c0..5509fef 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -224,11 +224,6 @@ void mmc_add_host_debugfs(struct mmc_host *host) &mmc_clock_fops)) goto err_node; -#ifdef CONFIG_MMC_CLKGATE - if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR), - root, &host->clk_delay)) - goto err_node; -#endif #ifdef CONFIG_FAIL_MMC_REQUEST if (fail_request) setup_fault_attr(&fail_default_attr, fail_request); diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 49bc403..fa6a903 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -57,246 +57,6 @@ void mmc_unregister_host_class(void) static DEFINE_IDR(mmc_host_idr); static DEFINE_SPINLOCK(mmc_host_lock); -#ifdef CONFIG_MMC_CLKGATE -static ssize_t clkgate_delay_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mmc_host *host = cls_dev_to_mmc_host(dev); - return snprintf(buf, PAGE_SIZE, "%lu\n", host->clkgate_delay); -} - -static ssize_t clkgate_delay_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct mmc_host *host = cls_dev_to_mmc_host(dev); - unsigned long flags, value; - - if (kstrtoul(buf, 0, &value)) - return -EINVAL; - - spin_lock_irqsave(&host->clk_lock, flags); - host->clkgate_delay = value; - spin_unlock_irqrestore(&host->clk_lock, flags); - return count; -} - -/* - * Enabling clock gating will make the core call out to the host - * once up and once down when it performs a request or card operation - * intermingled in any fashion. The driver will see this through - * set_ios() operations with ios.clock field set to 0 to gate (disable) - * the block clock, and to the old frequency to enable it again. - */ -static void mmc_host_clk_gate_delayed(struct mmc_host *host) -{ - unsigned long tick_ns; - unsigned long freq = host->ios.clock; - unsigned long flags; - - if (!freq) { - pr_debug("%s: frequency set to 0 in disable function, " - "this means the clock is already disabled.\n", - mmc_hostname(host)); - return; - } - /* - * New requests may have appeared while we were scheduling, - * then there is no reason to delay the check before - * clk_disable(). - */ - spin_lock_irqsave(&host->clk_lock, flags); - - /* - * Delay n bus cycles (at least 8 from MMC spec) before attempting - * to disable the MCI block clock. The reference count may have - * gone up again after this delay due to rescheduling! - */ - if (!host->clk_requests) { - spin_unlock_irqrestore(&host->clk_lock, flags); - tick_ns = DIV_ROUND_UP(1000000000, freq); - ndelay(host->clk_delay * tick_ns); - } else { - /* New users appeared while waiting for this work */ - spin_unlock_irqrestore(&host->clk_lock, flags); - return; - } - mutex_lock(&host->clk_gate_mutex); - spin_lock_irqsave(&host->clk_lock, flags); - if (!host->clk_requests) { - spin_unlock_irqrestore(&host->clk_lock, flags); - /* This will set host->ios.clock to 0 */ - mmc_gate_clock(host); - spin_lock_irqsave(&host->clk_lock, flags); - pr_debug("%s: gated MCI clock\n", mmc_hostname(host)); - } - spin_unlock_irqrestore(&host->clk_lock, flags); - mutex_unlock(&host->clk_gate_mutex); -} - -/* - * Internal work. Work to disable the clock at some later point. - */ -static void mmc_host_clk_gate_work(struct work_struct *work) -{ - struct mmc_host *host = container_of(work, struct mmc_host, - clk_gate_work.work); - - mmc_host_clk_gate_delayed(host); -} - -/** - * mmc_host_clk_hold - ungate hardware MCI clocks - * @host: host to ungate. - * - * Makes sure the host ios.clock is restored to a non-zero value - * past this call. Increase clock reference count and ungate clock - * if we're the first user. - */ -void mmc_host_clk_hold(struct mmc_host *host) -{ - unsigned long flags; - - /* cancel any clock gating work scheduled by mmc_host_clk_release() */ - cancel_delayed_work_sync(&host->clk_gate_work); - mutex_lock(&host->clk_gate_mutex); - spin_lock_irqsave(&host->clk_lock, flags); - if (host->clk_gated) { - spin_unlock_irqrestore(&host->clk_lock, flags); - mmc_ungate_clock(host); - spin_lock_irqsave(&host->clk_lock, flags); - pr_debug("%s: ungated MCI clock\n", mmc_hostname(host)); - } - host->clk_requests++; - spin_unlock_irqrestore(&host->clk_lock, flags); - mutex_unlock(&host->clk_gate_mutex); -} - -/** - * mmc_host_may_gate_card - check if this card may be gated - * @card: card to check. - */ -static bool mmc_host_may_gate_card(struct mmc_card *card) -{ - /* If there is no card we may gate it */ - if (!card) - return true; - /* - * Don't gate SDIO cards! These need to be clocked at all times - * since they may be independent systems generating interrupts - * and other events. The clock requests counter from the core will - * go down to zero since the core does not need it, but we will not - * gate the clock, because there is somebody out there that may still - * be using it. - */ - return !(card->quirks & MMC_QUIRK_BROKEN_CLK_GATING); -} - -/** - * mmc_host_clk_release - gate off hardware MCI clocks - * @host: host to gate. - * - * Calls the host driver with ios.clock set to zero as often as possible - * in order to gate off hardware MCI clocks. Decrease clock reference - * count and schedule disabling of clock. - */ -void mmc_host_clk_release(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->clk_lock, flags); - host->clk_requests--; - if (mmc_host_may_gate_card(host->card) && - !host->clk_requests) - schedule_delayed_work(&host->clk_gate_work, - msecs_to_jiffies(host->clkgate_delay)); - spin_unlock_irqrestore(&host->clk_lock, flags); -} - -/** - * mmc_host_clk_rate - get current clock frequency setting - * @host: host to get the clock frequency for. - * - * Returns current clock frequency regardless of gating. - */ -unsigned int mmc_host_clk_rate(struct mmc_host *host) -{ - unsigned long freq; - unsigned long flags; - - spin_lock_irqsave(&host->clk_lock, flags); - if (host->clk_gated) - freq = host->clk_old; - else - freq = host->ios.clock; - spin_unlock_irqrestore(&host->clk_lock, flags); - return freq; -} - -/** - * mmc_host_clk_init - set up clock gating code - * @host: host with potential clock to control - */ -static inline void mmc_host_clk_init(struct mmc_host *host) -{ - host->clk_requests = 0; - /* Hold MCI clock for 8 cycles by default */ - host->clk_delay = 8; - /* - * Default clock gating delay is 0ms to avoid wasting power. - * This value can be tuned by writing into sysfs entry. - */ - host->clkgate_delay = 0; - host->clk_gated = false; - INIT_DELAYED_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); - spin_lock_init(&host->clk_lock); - mutex_init(&host->clk_gate_mutex); -} - -/** - * mmc_host_clk_exit - shut down clock gating code - * @host: host with potential clock to control - */ -static inline void mmc_host_clk_exit(struct mmc_host *host) -{ - /* - * Wait for any outstanding gate and then make sure we're - * ungated before exiting. - */ - if (cancel_delayed_work_sync(&host->clk_gate_work)) - mmc_host_clk_gate_delayed(host); - if (host->clk_gated) - mmc_host_clk_hold(host); - /* There should be only one user now */ - WARN_ON(host->clk_requests > 1); -} - -static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) -{ - host->clkgate_delay_attr.show = clkgate_delay_show; - host->clkgate_delay_attr.store = clkgate_delay_store; - sysfs_attr_init(&host->clkgate_delay_attr.attr); - host->clkgate_delay_attr.attr.name = "clkgate_delay"; - host->clkgate_delay_attr.attr.mode = S_IRUGO | S_IWUSR; - if (device_create_file(&host->class_dev, &host->clkgate_delay_attr)) - pr_err("%s: Failed to create clkgate_delay sysfs entry\n", - mmc_hostname(host)); -} -#else - -static inline void mmc_host_clk_init(struct mmc_host *host) -{ -} - -static inline void mmc_host_clk_exit(struct mmc_host *host) -{ -} - -static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) -{ -} - -#endif - /** * mmc_of_parse() - parse host's device-tree node * @host: host whose node should be parsed. @@ -474,8 +234,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) host->class_dev.class = &mmc_host_class; device_initialize(&host->class_dev); - mmc_host_clk_init(host); - mutex_init(&host->slot.lock); host->slot.cd_irq = -EINVAL; @@ -530,7 +288,6 @@ int mmc_add_host(struct mmc_host *host) #ifdef CONFIG_DEBUG_FS mmc_add_host_debugfs(host); #endif - mmc_host_clk_sysfs_init(host); mmc_start_host(host); register_pm_notifier(&host->pm_notify); @@ -560,8 +317,6 @@ void mmc_remove_host(struct mmc_host *host) device_del(&host->class_dev); led_trigger_unregister_simple(host->led); - - mmc_host_clk_exit(host); } EXPORT_SYMBOL(mmc_remove_host); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6d02012..221c903 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1147,12 +1147,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * 4. execute tuning for HS200 */ if ((host->caps2 & MMC_CAP2_HS200) && - card->host->ops->execute_tuning) { - mmc_host_clk_hold(card->host); + card->host->ops->execute_tuning) err = card->host->ops->execute_tuning(card->host, MMC_SEND_TUNING_BLOCK_HS200); - mmc_host_clk_release(card->host); - } + if (err) { pr_warning("%s: tuning execution failed\n", mmc_hostname(card->host)); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5e8823d..c52a701 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -420,11 +420,9 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status) * information and let the hardware specific code * return what is possible given the options */ - mmc_host_clk_hold(card->host); drive_strength = card->host->ops->select_drive_strength( card->sw_caps.uhs_max_dtr, host_drv_type, card_drv_type); - mmc_host_clk_release(card->host); err = mmc_sd_switch(card, 1, 2, drive_strength, status); if (err) @@ -655,12 +653,9 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) */ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || - card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) { - mmc_host_clk_hold(card->host); + card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) err = card->host->ops->execute_tuning(card->host, MMC_SEND_TUNING_BLOCK); - mmc_host_clk_release(card->host); - } out: kfree(status); @@ -862,11 +857,8 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, if (!reinit) { int ro = -1; - if (host->ops->get_ro) { - mmc_host_clk_hold(card->host); + if (host->ops->get_ro) ro = host->ops->get_ro(host); - mmc_host_clk_release(card->host); - } if (ro < 0) { pr_warning("%s: host does not " diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 80d89cff..3b884a1 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -569,12 +569,9 @@ static int mmc_sdio_init_uhs_card(struct mmc_card *card) */ if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning && ((card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR50) || - (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) { - mmc_host_clk_hold(card->host); + (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104))) err = card->host->ops->execute_tuning(card->host, MMC_SEND_TUNING_BLOCK); - mmc_host_clk_release(card->host); - } out: diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 3d8ceb4..9dd0462 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -149,21 +149,15 @@ static int sdio_irq_thread(void *_host) } set_current_state(TASK_INTERRUPTIBLE); - if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); + if (host->caps & MMC_CAP_SDIO_IRQ) host->ops->enable_sdio_irq(host, 1); - mmc_host_clk_release(host); - } if (!kthread_should_stop()) schedule_timeout(period); set_current_state(TASK_RUNNING); } while (!kthread_should_stop()); - if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); + if (host->caps & MMC_CAP_SDIO_IRQ) host->ops->enable_sdio_irq(host, 0); - mmc_host_clk_release(host); - } pr_debug("%s: IRQ thread exiting with code %d\n", mmc_hostname(host), ret); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 3b0c33a..7d61cba 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -284,18 +284,6 @@ struct mmc_host { mmc_pm_flag_t pm_caps; /* supported pm features */ -#ifdef CONFIG_MMC_CLKGATE - int clk_requests; /* internal reference counter */ - unsigned int clk_delay; /* number of MCI clk hold cycles */ - bool clk_gated; /* clock gated */ - struct delayed_work clk_gate_work; /* delayed clock gate */ - unsigned int clk_old; /* old clock value cache */ - spinlock_t clk_lock; /* lock for clk fields */ - struct mutex clk_gate_mutex; /* mutex for clock gating */ - struct device_attribute clkgate_delay_attr; - unsigned long clkgate_delay; -#endif - /* host specific block data */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */ unsigned short max_segs; /* see blk_queue_max_segments */ @@ -468,23 +456,8 @@ static inline int mmc_host_packed_wr(struct mmc_host *host) return host->caps2 & MMC_CAP2_PACKED_WR; } -#ifdef CONFIG_MMC_CLKGATE -void mmc_host_clk_hold(struct mmc_host *host); -void mmc_host_clk_release(struct mmc_host *host); -unsigned int mmc_host_clk_rate(struct mmc_host *host); - -#else -static inline void mmc_host_clk_hold(struct mmc_host *host) -{ -} - -static inline void mmc_host_clk_release(struct mmc_host *host) -{ -} - static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) { return host->ios.clock; } -#endif #endif /* LINUX_MMC_HOST_H */