Hi Dong,

On 5 November 2013 07:49, Dong Aisheng <donga...@gmail.com> wrote:
> Hi Ulf,
>
> On Thu, Oct 31, 2013 at 8:01 AM, Ulf Hansson <ulf.hans...@linaro.org> 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 <ulf.hans...@linaro.org>
>
> 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 majord...@vger.kernel.org
>> 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to