Hi Dong,
On 5 November 2013 07:49, Dong Aisheng <[email protected]> wrote:
> Hi Ulf,
>
> On Thu, Oct 31, 2013 at 8:01 AM, Ulf Hansson <[email protected]> wrote:
>> No platforms is 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. The corresponding code for the
>> MMC_QUIRK_BROKEN_CLK_GATING is also removed in this patch.
>>
>> Signed-off-by: Ulf Hansson <[email protected]>
>
> This looks good to me.
>
> A question below:
>
>>
>> Changes in v2:
>> - Rebased patches towards latest mmc-next.
>> - Removed code for corresponding MMC_QUIRK_BROKEN_CLK_GATING as well.
>
> Does it mean that then we need reply on host driver to manage clock
> resource for SDIO card
> specificly?
Yes. Host drivers that gates clocks in their runtime_suspend callbacks
and supports SDIO irq, need to handle this as a special case.
>From a generic SDIO card case (no SDIO irq support), there should be
nothing to specific to handle I believe.
> e.g. if detect the card is SDIO, the host does not gate the clock all
> the time in runtime PM.
It depends on how the host decide to implement SDIO irq. If possible,
I think it would make sense to re-route the DAT1 line (line for SDIO
irq) to a GPIO irq while enter runtime suspend. Then the clock should
be possible to gate in this case as well.
If not possible to re-route to GPIO irq, the host must prevent runtime
suspend from being executed when SDIO irq is enabled. In other words,
add a pm_runtime_get|put somewhere in the code when the SDIO irq is
enabled/disabled for the host.
Kind regards
Ulf Hansson
>
> Regards
> Dong Aisheng
>
>>
>> ---
>> Documentation/mmc/mmc-dev-attrs.txt | 10 --
>> drivers/mmc/core/Kconfig | 10 --
>> drivers/mmc/core/core.c | 114 +---------------
>> 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/quirks.c | 18 ---
>> drivers/mmc/core/sd.c | 12 +-
>> drivers/mmc/core/sdio.c | 5 +-
>> drivers/mmc/core/sdio_irq.c | 10 +-
>> include/linux/mmc/card.h | 1 -
>> include/linux/mmc/host.h | 27 ----
>> 13 files changed, 12 insertions(+), 454 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 <desired delay> > /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 57a2b40..2b0a122 100644
>> --- a/drivers/mmc/core/core.c
>> +++ b/drivers/mmc/core/core.c
>> @@ -186,8 +186,6 @@ void mmc_request_done(struct mmc_host *host, struct
>> mmc_request *mrq)
>>
>> if (mrq->done)
>> mrq->done(mrq);
>> -
>> - mmc_host_clk_release(host);
>> }
>> }
>>
>> @@ -252,7 +250,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);
>> }
>> @@ -483,11 +480,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);
>> - }
>> }
>>
>> /**
>> @@ -502,11 +496,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);
>> - }
>> }
>>
>> /**
>> @@ -984,8 +975,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);
>> }
>>
>> @@ -994,17 +983,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);
>>
>> @@ -1015,77 +1002,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);
>> }
>>
>> /*
>> @@ -1093,10 +1016,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);
>> }
>>
>> /**
>> @@ -1394,11 +1315,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;
>> @@ -1443,7 +1361,6 @@ int mmc_set_signal_voltage(struct mmc_host *host, int
>> signal_voltage, u32 ocr)
>> 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
>> @@ -1492,8 +1409,6 @@ power_cycle:
>> mmc_power_cycle(host, ocr);
>> }
>>
>> - mmc_host_clk_release(host);
>> -
>> return err;
>> }
>>
>> @@ -1502,10 +1417,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);
>> }
>>
>> /*
>> @@ -1513,10 +1426,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);
>> }
>>
>> /*
>> @@ -1535,8 +1446,6 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
>> if (host->ios.power_mode == MMC_POWER_ON)
>> return;
>>
>> - mmc_host_clk_hold(host);
>> -
>> host->ios.vdd = fls(ocr) - 1;
>> if (mmc_host_is_spi(host))
>> host->ios.chip_select = MMC_CS_HIGH;
>> @@ -1567,8 +1476,6 @@ void mmc_power_up(struct mmc_host *host, u32 ocr)
>> * time required to reach a stable voltage.
>> */
>> mmc_delay(10);
>> -
>> - mmc_host_clk_release(host);
>> }
>>
>> void mmc_power_off(struct mmc_host *host)
>> @@ -1576,8 +1483,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;
>>
>> @@ -1596,8 +1501,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, u32 ocr)
>> @@ -2226,9 +2129,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)
>> @@ -2260,7 +2161,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);
>> @@ -2275,10 +2175,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);
>> @@ -2293,8 +2191,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 443a584..2eb1ade 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 f631f5a..8b57510 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -1149,12 +1149,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/quirks.c b/drivers/mmc/core/quirks.c
>> index 06ee1ae..5ada359 100644
>> --- a/drivers/mmc/core/quirks.c
>> +++ b/drivers/mmc/core/quirks.c
>> @@ -30,25 +30,7 @@
>> #define SDIO_DEVICE_ID_STE_CW1200 0x2280
>> #endif
>>
>> -/*
>> - * This hook just adds a quirk for all sdio devices
>> - */
>> -static void add_quirk_for_sdio_devices(struct mmc_card *card, int data)
>> -{
>> - if (mmc_card_sdio(card))
>> - card->quirks |= data;
>> -}
>> -
>> static const struct mmc_fixup mmc_fixup_methods[] = {
>> - /* by default sdio devices are considered CLK_GATING broken */
>> - /* good cards will be whitelisted as they are tested */
>> - SDIO_FIXUP(SDIO_ANY_ID, SDIO_ANY_ID,
>> - add_quirk_for_sdio_devices,
>> - MMC_QUIRK_BROKEN_CLK_GATING),
>> -
>> - SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
>> - remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),
>> -
>> SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
>> add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
>>
>> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
>> index 6f42050..d106f86 100644
>> --- a/drivers/mmc/core/sd.c
>> +++ b/drivers/mmc/core/sd.c
>> @@ -421,11 +421,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)
>> @@ -656,12 +654,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);
>> @@ -865,11 +860,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 4d721c6..625840a 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/card.h b/include/linux/mmc/card.h
>> index 176fdf8..aa4bd27 100644
>> --- a/include/linux/mmc/card.h
>> +++ b/include/linux/mmc/card.h
>> @@ -265,7 +265,6 @@ struct mmc_card {
>> /* for byte mode */
>> #define MMC_QUIRK_NONSTD_SDIO (1<<2) /* non-standard SDIO card
>> attached */
>> /* (missing CIA registers) */
>> -#define MMC_QUIRK_BROKEN_CLK_GATING (1<<3) /* clock gating the sdio bus
>> will make card fail */
>> #define MMC_QUIRK_NONSTD_FUNC_IF (1<<4) /* SDIO card has
>> nonstd function interfaces */
>> #define MMC_QUIRK_DISABLE_CD (1<<5) /* disconnect CD/DAT[3]
>> resistor */
>> #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken
>> CMD38 */
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> index 99f5709..4ce9357 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -285,18 +285,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 */
>> @@ -465,23 +453,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 */
>> --
>> 1.7.9.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html