Re: [PATCH V2 0/4] mmc: sdhci: Disable re-tuning for HS400

2014-12-11 Thread Aaron Lu
On 12/06/2014 01:25 AM, Adrian Hunter wrote:
 Hi
 
 Here is V2 of patches to disable re-tuning for HS400.
 
 As described in patch 4, re-tuning for HS400 has to be done
 in HS200 mode, but there is no support for that, so re-tuning
 needs to be disabled until support is added.
 
 Changes in V2:
 
   Added mmc: sdhci: Simplify use of tuning timer
   patch.
 
   Changed mmc: sdhci: Disable re-tuning for HS400
   so that the tuning timer is not started instead
   of stopping it when HS400 mode is selected.
 
 
 Adrian Hunter (4):
   mmc: sdhci: Tuning should not change max_blk_count
   mmc: sdhci: Add out_unlock to sdhci_execute_tuning
   mmc: sdhci: Simplify use of tuning timer
   mmc: sdhci: Disable re-tuning for HS400

For patch 1-3: Reviewed-by: Aaron Lu aaron...@intel.com

Thanks,
Aaron

 
  drivers/mmc/host/sdhci.c  | 66 
 ++-
  include/linux/mmc/sdhci.h |  1 +
  2 files changed, 43 insertions(+), 24 deletions(-)
 
 
 Regards
 Adrian
 

--
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


Re: [PATCH v5 07/11] mmc: sdio: Convert to dev_pm_domain_attach|detach()

2014-10-12 Thread Aaron Lu
On 10/02/2014 08:27 AM, Dmitry Torokhov wrote:
 Hi Ulf,
 
 On Fri, Sep 19, 2014 at 08:27:40PM +0200, Ulf Hansson wrote:
 Previously only the ACPI PM domain was supported by the sdio bus.

 Let's convert to the common attach/detach functions for PM domains,
 which currently means we are extending the support to include the
 generic PM domain as well.

 Cc: linux-mmc@vger.kernel.org
 Signed-off-by: Ulf Hansson ulf.hans...@linaro.org
 Reviewed-by: Kevin Hilman khil...@linaro.org
 ---
  drivers/mmc/core/sdio_bus.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

 diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
 index 4fa8fef9..1df0fc6 100644
 --- a/drivers/mmc/core/sdio_bus.c
 +++ b/drivers/mmc/core/sdio_bus.c
 @@ -315,7 +315,7 @@ int sdio_add_func(struct sdio_func *func)
  ret = device_add(func-dev);
  if (ret == 0) {
  sdio_func_set_present(func);
 -acpi_dev_pm_attach(func-dev, false);
 +dev_pm_domain_attach(func-dev, false);
 
 Admittedly it is not brought in by your change, but I am a bit worried
 about this code. In all other busses we attach power domain to a device
 before probing it (and detach if probe fails). Why here we only attach
 it to power domain after adding the device to the bus? If driver for the
 function has already been loaded the probe() would run without device
 being attached to a power domain...

Sorry for replying late...

I see your concern, but it should be safe here. The dev_pm_domain_attach
does primarily two things(for ACPI based system): assign the pm_domian
field so that later system and runtime PM transitions we have proper
callbacks for this device; power on the device if needed.

I was using Broadcom BCM43241 SDIO wifi card when developing the code,
it doesn't need the pm_domain set in its probe function and since the
SDIO wifi card is powered on after system boot, no power on is needed
either. That's why I added the attach function after device_add to save
a little code(detach if probe fails).

Feel free to change the sequence if the current one is a bad one, I'm OK
with either case.

 
 Adding Aaron as he's the author of the original change.

Thanks,
Aaron
--
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


Re: one doubt about mmc_sdio_init_card function

2014-07-01 Thread Aaron Lu
On 07/01/2014 01:39 PM, Fu, Zhonghui wrote:
 
 Hi, all
 
 The mmc_sdio_init_card(drivers/mmc/core/sdio.c) function calls 
 mmc_alloc_card(drivers/mmc/core/bus.c) function to allocate a card structure. 
 card-dev.bus is assigned with mmc_bus_type in mmc_alloc_card function. Why 
 not assign sdio_bus_type to card-dev.bus?

sdio card, mmc card, sd card are all devices on the mmc bus, hence their
bus type is set to mmc_bus_type.

sdio function device is a device on the sdio bus, hence its bus type is
sdio_bus_type.

Hope this helps,
Aaron

 
 
 struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type 
 *type)
 {
 struct mmc_card *card;
 
 card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
 if (!card)
 return ERR_PTR(-ENOMEM);
 
 card-host = host;
 
 device_initialize(card-dev);
 
 card-dev.parent = mmc_classdev(host);
 card-dev.bus = mmc_bus_type;
 card-dev.release = mmc_release_card;
 card-dev.type = type;
 
 return card;
 }
 
 
 Thanks,
 Zhonghui
 

--
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


Re: RESEND:[PATCH V3] sdhci: only reprogram retuning timer when flag is set

2014-03-19 Thread Aaron Lu
On 02/22/2014 03:59 AM, Arend van Spriel wrote:
 When the host-tuning_count is zero it means that the
 retuning is disabled. This is checked on the first
 run of sdhci_execute_tuning() by the if statement below:
 
   if (!(host-flags  SDHCI_NEEDS_RETUNING)  host-tuning_count 
   (host-tuning_mode == SDHCI_TUNING_MODE_1)) {
 
 So only when tuning_count is non-zero it will set the host
 flag SDHCI_USING_RETUNING_TIMER. The else statement is only
 for re-programming the timer, which means that flag must be
 set. Because that is not checked the else statement is executed
 in the first run when tuning_count is zero.
 
 This was seen on a host controller which indicated
 SDHCI_TUNING_MODE_1 (0) and tuning_count being zero. Suspect
 that (one of) these registers is not properly set.
 
 Cc: Dong Aisheng donga...@gmail.com
 Cc: Aaron Lu aaron@gmail.com
 Signed-off-by: Arend van Spriel ar...@broadcom.com

In addition to solve your problem, this patch also makes sense in the
common case, so:

Reviewed-by: Aaron Lu aaron...@intel.com
--
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


Re: [RFC PATCH] mmc: core: Invoke sdio func driver's PM callbacks from the sdio bus

2014-03-12 Thread Aaron Lu
On 03/12/2014 11:44 AM, Dong, Chuanxiao wrote:
 Hi Aaron,
 
 This patch is tested on Intel platform, and SDIO function driver's 
 suspend/resume callback will only be called once, which fixed this issue. 
 Previously, they can be called twice.
 
 Here is the tested-by:
 
 Tested-by: xiaoming wang xiaoming.w...@intel.com
 Tested-by: Chuanxiao Dong chuanxiao.d...@intel.com

Thanks a lot for the test!

-Aaron

 
 Thanks
 Chuanxiao
 
 -Original Message-
 From: Lu, Aaron
 Sent: Wednesday, March 12, 2014 10:36 AM
 To: Ulf Hansson; linux-mmc@vger.kernel.org; Chris Ball; Liu, Chuansheng; 
 Dong,
 Chuanxiao
 Cc: linux-ker...@vger.kernel.org; NeilBrown; Rafael J. Wysocki
 Subject: Re: [RFC PATCH] mmc: core: Invoke sdio func driver's PM callbacks 
 from the
 sdio bus

 Hi Chuansheng  Chuanxiao,

 Can you please help us testing this patch on your platform and let us know 
 the test
 result? Thanks.

 -Aaron

 On 02/28/2014 07:49 PM, Ulf Hansson wrote:
 The sdio func device is added to the driver model after the card
 device.

 This means the sdio func device will be suspend before the card device
 and thus resumed after. The consequence are the mmc core don't
 explicity need to protect itself from receiving sdio requests in
 suspended state. Instead that can be handled from the sdio bus, which
 is thus invokes the PM callbacks instead of old dummy function.

 In the case were the sdio func driver don't implement the PM callbacks
 the mmc core will in the early phase of system suspend, remove the
 card from the driver model and thus power off it.

 Cc: Aaron Lu aaron...@intel.com
 Cc: NeilBrown ne...@suse.de
 Cc: Rafael J. Wysocki r...@rjwysocki.net
 Signed-off-by: Ulf Hansson ulf.hans...@linaro.org
 ---

 Note, this patch has only been compile tested. Would appreciate if
 some with SDIO and a sdio func driver could help out to test this.
 Especially the libertas driver would be nice.

 ---
  drivers/mmc/core/sdio.c |   45 
 ---
  drivers/mmc/core/sdio_bus.c |   14 +-
  2 files changed, 5 insertions(+), 54 deletions(-)

 diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index
 4d721c6..9933e42 100644
 --- a/drivers/mmc/core/sdio.c
 +++ b/drivers/mmc/core/sdio.c
 @@ -943,40 +943,21 @@ static int mmc_sdio_pre_suspend(struct mmc_host
 *host)
   */
  static int mmc_sdio_suspend(struct mmc_host *host)  {
 -   int i, err = 0;
 -
 -   for (i = 0; i  host-card-sdio_funcs; i++) {
 -   struct sdio_func *func = host-card-sdio_func[i];
 -   if (func  sdio_func_present(func)  func-dev.driver) {
 -   const struct dev_pm_ops *pmops = func-dev.driver-pm;
 -   err = pmops-suspend(func-dev);
 -   if (err)
 -   break;
 -   }
 -   }
 -   while (err  --i = 0) {
 -   struct sdio_func *func = host-card-sdio_func[i];
 -   if (func  sdio_func_present(func)  func-dev.driver) {
 -   const struct dev_pm_ops *pmops = func-dev.driver-pm;
 -   pmops-resume(func-dev);
 -   }
 -   }
 -
 -   if (!err  mmc_card_keep_power(host)  mmc_card_wake_sdio_irq(host))
 {
 +   if (mmc_card_keep_power(host)  mmc_card_wake_sdio_irq(host)) {
 mmc_claim_host(host);
 sdio_disable_wide(host-card);
 mmc_release_host(host);
 }

 -   if (!err  !mmc_card_keep_power(host))
 +   if (!mmc_card_keep_power(host))
 mmc_power_off(host);

 -   return err;
 +   return 0;
  }

  static int mmc_sdio_resume(struct mmc_host *host)  {
 -   int i, err = 0;
 +   int err = 0;

 BUG_ON(!host);
 BUG_ON(!host-card);
 @@ -1019,24 +1000,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
 wake_up_process(host-sdio_irq_thread);
 mmc_release_host(host);

 -   /*
 -* If the card looked to be the same as before suspending, then
 -* we proceed to resume all card functions.  If one of them returns
 -* an error then we simply return that error to the core and the
 -* card will be redetected as new.  It is the responsibility of
 -* the function driver to perform further tests with the extra
 -* knowledge it has of the card to confirm the card is indeed the
 -* same as before suspending (same MAC address for network cards,
 -* etc.) and return an error otherwise.
 -*/
 -   for (i = 0; !err  i  host-card-sdio_funcs; i++) {
 -   struct sdio_func *func = host-card-sdio_func[i];
 -   if (func  sdio_func_present(func)  func-dev.driver) {
 -   const struct dev_pm_ops *pmops = func-dev.driver-pm;
 -   err = pmops-resume(func-dev);
 -   }
 -   }
 -
 host-pm_flags = ~MMC_PM_KEEP_POWER;
 return err;
  }
 diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
 index 92d1ba8..4fa8fef9 100644
 --- a/drivers/mmc/core/sdio_bus.c
 +++ b/drivers/mmc/core/sdio_bus.c
 @@ -197,20 +197,8 @@ static int

Re: [RFC PATCH] mmc: core: Invoke sdio func driver's PM callbacks from the sdio bus

2014-03-11 Thread Aaron Lu
Hi Chuansheng  Chuanxiao,

Can you please help us testing this patch on your platform
and let us know the test result? Thanks.

-Aaron

On 02/28/2014 07:49 PM, Ulf Hansson wrote:
 The sdio func device is added to the driver model after the card
 device.
 
 This means the sdio func device will be suspend before the card device
 and thus resumed after. The consequence are the mmc core don't
 explicity need to protect itself from receiving sdio requests in
 suspended state. Instead that can be handled from the sdio bus, which
 is thus invokes the PM callbacks instead of old dummy function.
 
 In the case were the sdio func driver don't implement the PM callbacks
 the mmc core will in the early phase of system suspend, remove the
 card from the driver model and thus power off it.
 
 Cc: Aaron Lu aaron...@intel.com
 Cc: NeilBrown ne...@suse.de
 Cc: Rafael J. Wysocki r...@rjwysocki.net
 Signed-off-by: Ulf Hansson ulf.hans...@linaro.org
 ---
 
 Note, this patch has only been compile tested. Would appreciate if some with
 SDIO and a sdio func driver could help out to test this. Especially the
 libertas driver would be nice.
 
 ---
  drivers/mmc/core/sdio.c |   45 
 ---
  drivers/mmc/core/sdio_bus.c |   14 +-
  2 files changed, 5 insertions(+), 54 deletions(-)
 
 diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
 index 4d721c6..9933e42 100644
 --- a/drivers/mmc/core/sdio.c
 +++ b/drivers/mmc/core/sdio.c
 @@ -943,40 +943,21 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)
   */
  static int mmc_sdio_suspend(struct mmc_host *host)
  {
 - int i, err = 0;
 -
 - for (i = 0; i  host-card-sdio_funcs; i++) {
 - struct sdio_func *func = host-card-sdio_func[i];
 - if (func  sdio_func_present(func)  func-dev.driver) {
 - const struct dev_pm_ops *pmops = func-dev.driver-pm;
 - err = pmops-suspend(func-dev);
 - if (err)
 - break;
 - }
 - }
 - while (err  --i = 0) {
 - struct sdio_func *func = host-card-sdio_func[i];
 - if (func  sdio_func_present(func)  func-dev.driver) {
 - const struct dev_pm_ops *pmops = func-dev.driver-pm;
 - pmops-resume(func-dev);
 - }
 - }
 -
 - if (!err  mmc_card_keep_power(host)  mmc_card_wake_sdio_irq(host)) {
 + if (mmc_card_keep_power(host)  mmc_card_wake_sdio_irq(host)) {
   mmc_claim_host(host);
   sdio_disable_wide(host-card);
   mmc_release_host(host);
   }
  
 - if (!err  !mmc_card_keep_power(host))
 + if (!mmc_card_keep_power(host))
   mmc_power_off(host);
  
 - return err;
 + return 0;
  }
  
  static int mmc_sdio_resume(struct mmc_host *host)
  {
 - int i, err = 0;
 + int err = 0;
  
   BUG_ON(!host);
   BUG_ON(!host-card);
 @@ -1019,24 +1000,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
   wake_up_process(host-sdio_irq_thread);
   mmc_release_host(host);
  
 - /*
 -  * If the card looked to be the same as before suspending, then
 -  * we proceed to resume all card functions.  If one of them returns
 -  * an error then we simply return that error to the core and the
 -  * card will be redetected as new.  It is the responsibility of
 -  * the function driver to perform further tests with the extra
 -  * knowledge it has of the card to confirm the card is indeed the
 -  * same as before suspending (same MAC address for network cards,
 -  * etc.) and return an error otherwise.
 -  */
 - for (i = 0; !err  i  host-card-sdio_funcs; i++) {
 - struct sdio_func *func = host-card-sdio_func[i];
 - if (func  sdio_func_present(func)  func-dev.driver) {
 - const struct dev_pm_ops *pmops = func-dev.driver-pm;
 - err = pmops-resume(func-dev);
 - }
 - }
 -
   host-pm_flags = ~MMC_PM_KEEP_POWER;
   return err;
  }
 diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
 index 92d1ba8..4fa8fef9 100644
 --- a/drivers/mmc/core/sdio_bus.c
 +++ b/drivers/mmc/core/sdio_bus.c
 @@ -197,20 +197,8 @@ static int sdio_bus_remove(struct device *dev)
  
  #ifdef CONFIG_PM
  
 -#ifdef CONFIG_PM_SLEEP
 -static int pm_no_operation(struct device *dev)
 -{
 - /*
 -  * Prevent the PM core from calling SDIO device drivers' suspend
 -  * callback routines, which it is not supposed to do, by using this
 -  * empty function as the bus type suspend callaback for SDIO.
 -  */
 - return 0;
 -}
 -#endif
 -
  static const struct dev_pm_ops sdio_bus_pm_ops = {
 - SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
 + SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
   SET_RUNTIME_PM_OPS(
   pm_generic_runtime_suspend

Re: SDIO driver return -ENOSYS behaviour change?

2014-02-28 Thread Aaron Lu
On 02/28/2014 04:30 PM, Ulf Hansson wrote:
 On 28 February 2014 03:37, Aaron Lu aaron...@intel.com wrote:
 On 02/27/2014 09:05 PM, Ulf Hansson wrote:
 I think it's more a matter of having a controlled suspend sequence.
 The mmc core are not able to serve any new SDIO requests while it is
 suspended, therefore it tells the sdio func driver about when it safe
 to send request - using it's PM callbacks.

 Does this mean after the function device is suspended from PM core's
 pespective, the mmc core will still send some requests to the function
 device? I did see one such request, disable_width, get sent after the
 function driver's suspend callback is invoked, don't know if there are
 others.
 
 Nope. The mmc core will send request to the card device during
 suspend. Those are part's of a sequence to put the card in a proper
 suspend mode.

I suppose this request is sent after calling function driver's suspend
callback? BTW, what request is it?

 

 From the mmc_sdio_suspend function I can see two things are done:
 1 function device driver's suspend callback is called;
 2 optionally disable_width and power off the card according to some flags.

 So once we fixed the -ENOSYS problem, can we have the function device
 run its own suspend callback and have the mmc_sdio_suspend just did the
 disable_width and power off thing?
 
 That requires that all sdio func devices get suspended before the card
 devices. (And resumed after, but that will of course be implicit.)

Yes, and this is guaranteed by PM core as the function device is the
child of the card device.

 
 I guess the guarantee for that is already present, since we have added
 the func device to the driver model after we have added the card
 device at mmc_sdio_attach(). So, I suppose this could work.

Exactly.

 
 Do you want me to create a patch that you can test?

That would be good. I do not have any SDIO card at hand, but I would be
glad to review the patch.

Thanks,
Aaron
--
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


Re: [RFC PATCH] mmc: core: Invoke sdio func driver's PM callbacks from the sdio bus

2014-02-28 Thread Aaron Lu
On 02/28/2014 07:49 PM, Ulf Hansson wrote:
 The sdio func device is added to the driver model after the card
 device.
 
 This means the sdio func device will be suspend before the card device
 and thus resumed after. The consequence are the mmc core don't
 explicity need to protect itself from receiving sdio requests in
 suspended state. Instead that can be handled from the sdio bus, which
 is thus invokes the PM callbacks instead of old dummy function.
 
 In the case were the sdio func driver don't implement the PM callbacks
 the mmc core will in the early phase of system suspend, remove the
 card from the driver model and thus power off it.
 
 Cc: Aaron Lu aaron...@intel.com
 Cc: NeilBrown ne...@suse.de
 Cc: Rafael J. Wysocki r...@rjwysocki.net
 Signed-off-by: Ulf Hansson ulf.hans...@linaro.org
 ---
 
 Note, this patch has only been compile tested. Would appreciate if some with
 SDIO and a sdio func driver could help out to test this. Especially the
 libertas driver would be nice.
 
 ---
  drivers/mmc/core/sdio.c |   45 
 ---
  drivers/mmc/core/sdio_bus.c |   14 +-
  2 files changed, 5 insertions(+), 54 deletions(-)
 
 diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
 index 4d721c6..9933e42 100644
 --- a/drivers/mmc/core/sdio.c
 +++ b/drivers/mmc/core/sdio.c
 @@ -943,40 +943,21 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)
   */
  static int mmc_sdio_suspend(struct mmc_host *host)
  {
 - int i, err = 0;
 -
 - for (i = 0; i  host-card-sdio_funcs; i++) {
 - struct sdio_func *func = host-card-sdio_func[i];
 - if (func  sdio_func_present(func)  func-dev.driver) {
 - const struct dev_pm_ops *pmops = func-dev.driver-pm;
 - err = pmops-suspend(func-dev);
 - if (err)
 - break;
 - }
 - }
 - while (err  --i = 0) {
 - struct sdio_func *func = host-card-sdio_func[i];
 - if (func  sdio_func_present(func)  func-dev.driver) {
 - const struct dev_pm_ops *pmops = func-dev.driver-pm;
 - pmops-resume(func-dev);
 - }
 - }
 -
 - if (!err  mmc_card_keep_power(host)  mmc_card_wake_sdio_irq(host)) {
 + if (mmc_card_keep_power(host)  mmc_card_wake_sdio_irq(host)) {
   mmc_claim_host(host);
   sdio_disable_wide(host-card);
   mmc_release_host(host);
   }
  
 - if (!err  !mmc_card_keep_power(host))
 + if (!mmc_card_keep_power(host))
   mmc_power_off(host);
  
 - return err;
 + return 0;
  }
  
  static int mmc_sdio_resume(struct mmc_host *host)
  {
 - int i, err = 0;
 + int err = 0;
  
   BUG_ON(!host);
   BUG_ON(!host-card);
 @@ -1019,24 +1000,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
   wake_up_process(host-sdio_irq_thread);
   mmc_release_host(host);
  
 - /*
 -  * If the card looked to be the same as before suspending, then
 -  * we proceed to resume all card functions.  If one of them returns
 -  * an error then we simply return that error to the core and the
 -  * card will be redetected as new.  It is the responsibility of
 -  * the function driver to perform further tests with the extra
 -  * knowledge it has of the card to confirm the card is indeed the
 -  * same as before suspending (same MAC address for network cards,
 -  * etc.) and return an error otherwise.
 -  */
 - for (i = 0; !err  i  host-card-sdio_funcs; i++) {
 - struct sdio_func *func = host-card-sdio_func[i];
 - if (func  sdio_func_present(func)  func-dev.driver) {
 - const struct dev_pm_ops *pmops = func-dev.driver-pm;
 - err = pmops-resume(func-dev);
 - }
 - }
 -
   host-pm_flags = ~MMC_PM_KEEP_POWER;
   return err;
  }
 diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
 index 92d1ba8..4fa8fef9 100644
 --- a/drivers/mmc/core/sdio_bus.c
 +++ b/drivers/mmc/core/sdio_bus.c
 @@ -197,20 +197,8 @@ static int sdio_bus_remove(struct device *dev)
  
  #ifdef CONFIG_PM
  
 -#ifdef CONFIG_PM_SLEEP
 -static int pm_no_operation(struct device *dev)
 -{
 - /*
 -  * Prevent the PM core from calling SDIO device drivers' suspend
 -  * callback routines, which it is not supposed to do, by using this
 -  * empty function as the bus type suspend callaback for SDIO.
 -  */
 - return 0;
 -}
 -#endif
 -
  static const struct dev_pm_ops sdio_bus_pm_ops = {
 - SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
 + SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)

The same thing can be achieved by not defining the two callbacks here,
the PM core will use driver's callback in that case, but that is not a
big deal.

Reviewed-by: Aaron Lu aaron...@intel.com

Thanks

SDIO driver return -ENOSYS behaviour change?

2014-02-27 Thread Aaron Lu
Hi Ulf,

I was tracking some SDIO suspend problem and came across this. As Neil
mentioned here:
http://lkml.org/lkml/2012/3/25/20
Quote:

SDIO (and possible MMC in general) has a protocol where the suspend
 method can return -ENOSYS and this means There is no point in suspending,
 just turn me off.


It seems that the following commit:

commit 810caddba42a54fe5db4e2664757a9a334ba359c
Author: Ulf Hansson ulf.hans...@linaro.org
Date:   Mon Jun 10 17:03:37 2013 +0200

mmc: core: Validate suspend prerequisites for SDIO at SUSPEND_PREPARE

Changed this behaviour?

For example, the libertas SDIO driver's suspend callback still returns
-ENOSYS and before this commit, that error code will result in the SDIO
device being removed; after this commit, that would result in an error
code returned to PM core and a failure in system suspend.

I'm not sure if I understand this correctly as I do not have any SDIO
card to test. Can you please take a look at this? If this is indeed the
case, do we need to maintain this behaviour? I need to know this answer
as that would affect the way I'm going to solve my problem. Thanks.
--
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


Re: SDIO driver return -ENOSYS behaviour change?

2014-02-27 Thread Aaron Lu
On 02/27/2014 06:18 PM, Ulf Hansson wrote:
 On 27 February 2014 10:10, Aaron Lu aaron...@intel.com wrote:
 Hi Ulf,

 I was tracking some SDIO suspend problem and came across this. As Neil
 mentioned here:
 http://lkml.org/lkml/2012/3/25/20
 Quote:
 
 SDIO (and possible MMC in general) has a protocol where the suspend
  method can return -ENOSYS and this means There is no point in suspending,
  just turn me off.
 

 It seems that the following commit:

 commit 810caddba42a54fe5db4e2664757a9a334ba359c
 Author: Ulf Hansson ulf.hans...@linaro.org
 Date:   Mon Jun 10 17:03:37 2013 +0200

 mmc: core: Validate suspend prerequisites for SDIO at SUSPEND_PREPARE

 Changed this behaviour?
 
 I realized I changed the behaviour to not cover for sdio func drivers,
 that actually implements the pm callbacks - but do return -ENOSYS in
 them. That wasn't obvious when looking at the code back then, sorry!

Never mind, this behaviour change doesn't cause my problems but knowing
whether this behaviour should be kept affects how I'm going to solve my
problem.

My problem is that, after the following commit:

commit eed222aca8d077af3600b651176f6fd04d95cce1
Author: Aaron Lu aaron...@intel.com
Date:   Tue Mar 5 11:24:52 2013 +0800

mmc: sdio: bind acpi with sdio function device

The SDIO function that has an ACPI node associated with will have the
pm_domain assigned, which breaks the intention that during SDIO function
device suspend phase nothing should be done by having a dummy BUS layer
callback. The existence of the pm_domain for the SDIO function device
will make its function driver's suspend callback gets called now. The
end result is the function driver's suspend callback is called twice.

To solve this problem, I was wondering why SDIO function device has this
'special' requirement that nothing should be done at its own device
suspend phase but instead, relies on its suspend callback gets called in
its parent device's suspend callback. And then I realized the reason is
for the special handling of -ENOSYS.

So if we could get rid of the -ENOSYS, my problem could be easily solved
by deleting some lines in current code(the calling of function driver's
suspend callback in mmc_sdio_suspend and the dummy system suspend/resume
callback for SDIO bus). Buf if the behaviour has to be kept, I'll
probably need to remove the pm_domain for the device and do some
additional ACPI handing in mmc_sdio_suspend/resume for the function
device.

 
 There are no solution to this problem in the mmc core right now, since
 we can't remove the card while we have reach the state when the
 suspend callback is being invoked.
 
 Instead, the sdio func driver shall not implement the PM callbacks at
 all. That behaviour means the mmc core will remove the card, but now
 it's done a in an earlier phase of the system suspend when we are
 still able to remove it.

The libertas suspend callback is doing different things depending on
different conditions - sometime it will enable wakeup capability and
sometime it will want the mmc core to remove the device entirely by
retuning -ENOSYS, so it may not be that easy by just deleting the
callback, but I don't know for sure.

Thanks,
Aaron
--
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


Re: SDIO driver return -ENOSYS behaviour change?

2014-02-27 Thread Aaron Lu
On 02/27/2014 09:05 PM, Ulf Hansson wrote:
 On 27 February 2014 12:26, Aaron Lu aaron...@intel.com wrote:
 On 02/27/2014 06:18 PM, Ulf Hansson wrote:
 On 27 February 2014 10:10, Aaron Lu aaron...@intel.com wrote:
 Hi Ulf,

 I was tracking some SDIO suspend problem and came across this. As Neil
 mentioned here:
 http://lkml.org/lkml/2012/3/25/20
 Quote:
 
 SDIO (and possible MMC in general) has a protocol where the suspend
  method can return -ENOSYS and this means There is no point in suspending,
  just turn me off.
 

 It seems that the following commit:

 commit 810caddba42a54fe5db4e2664757a9a334ba359c
 Author: Ulf Hansson ulf.hans...@linaro.org
 Date:   Mon Jun 10 17:03:37 2013 +0200

 mmc: core: Validate suspend prerequisites for SDIO at SUSPEND_PREPARE

 Changed this behaviour?

 I realized I changed the behaviour to not cover for sdio func drivers,
 that actually implements the pm callbacks - but do return -ENOSYS in
 them. That wasn't obvious when looking at the code back then, sorry!

 Never mind, this behaviour change doesn't cause my problems but knowing
 whether this behaviour should be kept affects how I'm going to solve my
 problem.
 
 So let's aim for the a proper solution instead of a quick hack.

OK.

 
 Although apparently mwifiex, libertas and btmrvl_sdio (bluetooth) may
 return -ENOSYS from the respective system supend callbacks, thus
 expecting the card to be removed. Currently this won't happen, but
 instead the suspend will be aborted, which is really bad.
 
 I believe those driver's suspend callback should be fixed to not
 return -ENOSYS. Returning 0 will, when MMC_PM_KEEP_POWER is not set,
 power off the card similar what's done when removing the card - that
 should be perfectly fine. Do note that the sdio func driver then
 should expect the resume callback to invoked, instead of being
 _probed_ at the next system resume.

Good to know this.

 

 My problem is that, after the following commit:

 commit eed222aca8d077af3600b651176f6fd04d95cce1
 Author: Aaron Lu aaron...@intel.com
 Date:   Tue Mar 5 11:24:52 2013 +0800

 mmc: sdio: bind acpi with sdio function device

 The SDIO function that has an ACPI node associated with will have the
 pm_domain assigned, which breaks the intention that during SDIO function
 device suspend phase nothing should be done by having a dummy BUS layer
 callback. The existence of the pm_domain for the SDIO function device
 will make its function driver's suspend callback gets called now. The
 end result is the function driver's suspend callback is called twice.
 
 Why is the sdio bus ignored?

In __device_suspend, if pm_domain is set, the suspend callback is
fetched there, no matter if there is a suspend callback defined in the
pm_domain or not. In ACPI PM domain's case, the suspend callback is
NULL, so the driver's suspend callback is used then.

I consulted Rafael whether adding a NULL check before goto Run is OK
like the following shows:

diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 1b41fca3d65a..506583d84ed4 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1160,7 +1160,8 @@ static int __device_suspend(struct device *dev, 
pm_message_t state, bool async)
if (dev-pm_domain) {
info = power domain ;
callback = pm_op(dev-pm_domain-ops, state);
-   goto Run;
+   if (callback)
+   goto Run;
}
 
if (dev-type  dev-type-pm) {

And Rafael said that would introduce regressions elsewhere, so it's a no
go.

 
 Are you saying the power domain is using the pm_generic_suspend for or
 from it's -suspend callback? If so, that could be the problem!?
 

 To solve this problem, I was wondering why SDIO function device has this
 'special' requirement that nothing should be done at its own device
 suspend phase but instead, relies on its suspend callback gets called in
 its parent device's suspend callback. And then I realized the reason is
 for the special handling of -ENOSYS.
 
 That's to my understanding not the only reason.
 
 I think it's more a matter of having a controlled suspend sequence.
 The mmc core are not able to serve any new SDIO requests while it is
 suspended, therefore it tells the sdio func driver about when it safe
 to send request - using it's PM callbacks.

Does this mean after the function device is suspended from PM core's
pespective, the mmc core will still send some requests to the function
device? I did see one such request, disable_width, get sent after the
function driver's suspend callback is invoked, don't know if there are
others.

From the mmc_sdio_suspend function I can see two things are done:
1 function device driver's suspend callback is called;
2 optionally disable_width and power off the card according to some flags.

So once we fixed the -ENOSYS problem, can we have the function device
run its own suspend callback and have the mmc_sdio_suspend just did the
disable_width

Re: [PATCH V2] sdhci: only reprogram retuning timer when flag is set

2013-11-13 Thread Aaron Lu
On 11/13/2013 07:25 PM, Dong Aisheng wrote:
 On Wed, Nov 13, 2013 at 7:18 PM, Arend van Spriel ar...@broadcom.com wrote:
 On 11/13/2013 12:12 PM, Dong Aisheng wrote:

 Hi Arend,

 On Wed, Nov 13, 2013 at 6:21 PM, Arend van Spriel ar...@broadcom.com
 wrote:

 On 11/13/2013 06:02 AM, Dong Aisheng wrote:


 Hi Arend,

 On Mon, Nov 11, 2013 at 5:49 PM, Arend van Spriel ar...@broadcom.com
 wrote:


 When the host-tuning_count is zero it means that the
 retuning is disabled. This is checked on the first
 run of sdhci_execute_tuning() by the if statement below:

   if (!(host-flags  SDHCI_NEEDS_RETUNING) 
 host-tuning_count
 
   (host-tuning_mode == SDHCI_TUNING_MODE_1)) {

 So only when tuning_count is non-zero it will set the host
 flag SDHCI_USING_RETUNING_TIMER. The else statement is only
 for re-programming the timer, which means that flag must be
 set. Because that is not checked the else statement is executed
 in the first run when tuning_count is zero.

 This was seen on a host controller which indicated
 SDHCI_TUNING_MODE_1 (0) and tuning_count being zero. Suspect
 that (one of) these registers is not properly set.

 Signed-off-by: Arend van Spriel ar...@broadcom.com
 ---
 This patch applies to the mmc-next branch.

 V2:
 - add more explanation to the commit message
 - check host flag SDHCI_USING_RETUNING_TIMER
 ---
drivers/mmc/host/sdhci.c |2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index bd8a098..5974599 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2014,7 +2014,7 @@ out:
   host-tuning_count * HZ);
   /* Tuning mode 1 limits the maximum data length to
 4MB
 */
   mmc-max_blk_count = (4 * 1024 * 1024) /
 mmc-max_blk_size;
 -   } else {
 +   } else if (host-flags  SDHCI_USING_RETUNING_TIMER) {
   host-flags = ~SDHCI_NEEDS_RETUNING;
   /* Reload the new initial value for timer */
   if (host-tuning_mode == SDHCI_TUNING_MODE_1)



 I wonder if we could also remove this line?
 It looks to me it's not neccesary to check the tuning_mode again since
 we already check the flag
 above and SDHCI_TUNING_MODE_1 seems like the prerequisite of
 SDHCI_USING_RETUNING_TIMER.



 According the spec the other tuning modes also can use retuning timer.
 Currently, the mmc stack in upstream linux only supports tuning mode 1.
 When
 adding the other modes this if statement will probably go.


 For currently code, it looks like also not necessary to check it since
 SDHCI_USING_RETUNING_TIMER will only be set when tunning_mode is
 SDHCI_TUNING_MODE_1.
 And SDHCI_TUNING_MODE_1 just indicates the tuning mode while the flag
 SDHCI_USING_RETUNING_TIMER represents the retuning timer implementation.
 So check the flag to invoke the timer seems make more sense to me.
 do you agree?


 The flag SDHCI_USING_RETUNING_TIMER is only set after the initial tuning run
 so in the if-statement. So currently in the else-statement the fact that
 SDHCI_USING_RETUNING_TIMER is set implies SDHCI_TUNING_MODE_1.

 
 Right, so that means we could remove the tuning_mode check in the
 else-statement.

I agree.

-Aaron

 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 2d55e6a..b2928ef 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2015,12 +2015,11 @@ out:
 host-tuning_count * HZ);
 /* Tuning mode 1 limits the maximum data length to 4MB */
 mmc-max_blk_count = (4 * 1024 * 1024) / mmc-max_blk_size;
 -   } else {
 +   } else if (host-flags  SDHCI_USING_RETUNING_TIMER) {
 host-flags = ~SDHCI_NEEDS_RETUNING;
 /* Reload the new initial value for timeout workqueue */
 -   if (host-tuning_mode == SDHCI_TUNING_MODE_1)
 -   schedule_delayed_work(host-tuning_timeout_work,
 -   host-tuning_count * HZ);
 +   schedule_delayed_work(host-tuning_timeout_work,
 +   host-tuning_count * HZ);
 }
 
 /*
 
 Regards
 Dong Aisheng
 

 Regards,
 Arend

 Regards
 Dong Aisheng

 Regards,
 Arend


 Regards
 Dong Aisheng

 --
 1.7.10.4


 --
 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
 

--
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


Re: [PATCH V2] mmc: sdhci: supporting PCI MSI

2013-11-13 Thread Aaron Lu
On 11/13/2013 02:00 PM, Jackey Shen wrote:
 On Wed, Nov 13, 2013 at 01:55:08PM +0800, Jackey Shen wrote:
 What about we only call pci_enable_msi in sdhci-pci.c and then assign
 host-irq appropriately before calling sdhci_add_host, will that work?
 The only difference would be, request_irq will have SHARED flag, but I
 suppose that's not a problem.

 There are 2 points for this part:
 1. fall back to legacy interrupt right after MSI request fails;

 If we call pci_enable_msi somewhere in sdhci_pci_probe_slot, then if it
 failed, we can also fall back I suppose?

 Yes, it is. 
 But, sdhci_pci_disable_msi should be kept since pci_disable_msi is
 pci bus releted and better not used in sdhci.c.
 So, enable msi and disable msi are NOT symmetric in style.
 What's your opinion?
 
 Sorry for missing word.
 So, enable msi and disable msi are NOT symmetric in style.


I meant something like this:

diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index d7d6bc8..96461a3 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -1339,12 +1339,17 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
host-quirks = chip-quirks;
host-quirks2 = chip-quirks2;

+   ret = pci_enable_msi(pdev);
+   if (ret) {
+   dev_err(pdev-dev, cannot enable msi\n);
+   goto cleanup;
+   }
host-irq = pdev-irq;

ret = pci_request_region(pdev, bar, mmc_hostname(host-mmc));
if (ret) {
dev_err(pdev-dev, cannot request region\n);
-   goto cleanup;
+   goto disable_msi;
}

host-ioaddr = pci_ioremap_bar(pdev, bar);
@@ -1396,6 +1401,9 @@ unmap:
 release:
pci_release_region(pdev, bar);

+disable_msi:
+   pci_disable_msi(pdev);
+
 cleanup:
if (slot-data  slot-data-cleanup)
slot-data-cleanup(slot-data);
@@ -1431,6 +1439,8 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot 
*slot)

pci_release_region(slot-chip-pdev, slot-pci_bar);

+   pci_disable_msi(slot-chip-pdev);
+
sdhci_free_host(slot-host);
 }


We can do all these MSI stuffs in sdhci-pci.c, but I'm not sure if this
is correct.

Thanks,
Aaron
--
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


Re: [PATCH V2] mmc: sdhci: supporting PCI MSI

2013-11-12 Thread Aaron Lu
On 11/12/2013 05:27 PM, Jackey Shen wrote:
 On Tue, Nov 12, 2013 at 03:44:40PM +0800, Aaron Lu wrote:
 On 11/12/2013 02:56 PM, Jackey Shen wrote:
 Enable MSI support in sdhci-pci driver and provide the mechanism
 to fall back to Legacy Pin-based Interrupt if MSI register fails.

 Tested with SD cards on AMD platform.


 -

 Change from V1:
 - implement this PCI MSI feature in sdhci-pci.c instead of sdhci.c

 Such words can be placed under the --- below so that it will not appear
 in git log.


 Signed-off-by: Jackey Shen jackey.s...@amd.com
 Reviewed-by: Huang Rui ray.hu...@amd.com
 ---

 -
 Put change related info Here.
 
 OK. I will update my patch.
 

  drivers/mmc/host/Kconfig | 11 +
  drivers/mmc/host/sdhci-pci.c | 58 
 
  drivers/mmc/host/sdhci.c | 42 ++--
  drivers/mmc/host/sdhci.h |  2 ++
  include/linux/mmc/sdhci.h|  2 ++
  5 files changed, 107 insertions(+), 8 deletions(-)

 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
 index 7fc5099..a56cf27 100644
 --- a/drivers/mmc/host/Kconfig
 +++ b/drivers/mmc/host/Kconfig
 @@ -68,6 +68,17 @@ config MMC_SDHCI_PCI
  
   If unsure, say N.
  
 +config MMC_SDHCI_PCI_MSI
 +   bool SDHCI support with MSI on PCI bus
 +   depends on MMC_SDHCI_PCI  PCI_MSI
 +   help
 + This enables PCI MSI (Message Signaled Interrupts) for Secure
 + Digital Host Controller Interface.
 +
 + If you have a controller with this capability, say Y or M here.
 +
 + If unsure, say N.
 +
  config MMC_RICOH_MMC
 bool Ricoh MMC Controller Disabler
 depends on MMC_SDHCI_PCI
 diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
 index 8f75381..2ca29c0 100644
 --- a/drivers/mmc/host/sdhci-pci.c
 +++ b/drivers/mmc/host/sdhci-pci.c
 @@ -1143,10 +1143,68 @@ static void sdhci_pci_hw_reset(struct sdhci_host 
 *host)
 slot-hw_reset(host);
  }
  
 +#ifdef CONFIG_MMC_SDHCI_PCI_MSI
 +static int sdhci_pci_setup_msi(struct sdhci_host *host, irq_handler_t 
 handler)
 +{
 +   int ret;
 +   struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 +   host-msi_enabled = false;
 +
 +   ret = pci_enable_msi(pdev);
 +   if (ret) {
 +   pr_warn(%s: Failed to allocate MSI entry\n,
 +   mmc_hostname(host-mmc));
 +   return ret;
 +   }
 +
 +   ret = request_irq(pdev-irq, handler, 0,
 +   mmc_hostname(host-mmc), host);
 +   if (ret) {
 +   pr_warn(%s: Failed to request MSI IRQ %d: %d\n,
 +  mmc_hostname(host-mmc), pdev-irq, ret);
 +   pci_disable_msi(pdev);
 +   return ret;
 +   }
 +
 +   host-irq = pdev-irq;
 +   host-msi_enabled = true;
 +   return ret;
 +}

 What about we only call pci_enable_msi in sdhci-pci.c and then assign
 host-irq appropriately before calling sdhci_add_host, will that work?
 The only difference would be, request_irq will have SHARED flag, but I
 suppose that's not a problem.

 There are 2 points for this part:
 1. fall back to legacy interrupt right after MSI request fails;

If we call pci_enable_msi somewhere in sdhci_pci_probe_slot, then if it
failed, we can also fall back I suppose?

 2. prompt user more information about where error/warning occur.
 
 +
 +static int sdhci_pci_enable_msi(struct sdhci_host *host, irq_handler_t 
 handler)
 +{
 +   return sdhci_pci_setup_msi(host, handler);
 +}
 +
 +static void sdhci_pci_disable_msi(struct sdhci_host *host)
 +{
 +   struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 +   if (host-msi_enabled) {
 +   pci_disable_msi(pdev);
 +   host-msi_enabled = false;
 +   }
 +}
 +
 +#else
 +
 +static int sdhci_pci_enable_msi(struct sdhci_host *host, irq_handler_t 
 handler)
 +{
 +   return 0;
 +}
 +
 +static void sdhci_pci_disable_msi(struct sdhci_host *host)
 +{
 +}
 +#endif /* CONFIG_MMC_SDHCI_PCI_MSI */
 +
  static const struct sdhci_ops sdhci_pci_ops = {
 .enable_dma = sdhci_pci_enable_dma,
 .platform_bus_width = sdhci_pci_bus_width,
 .hw_reset   = sdhci_pci_hw_reset,
 +   .enable_msi = sdhci_pci_enable_msi,
 +   .disable_msi= sdhci_pci_disable_msi,
  };
  
  
 /*\
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 6785fb1..4c2a1ac 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2554,6 +2554,31 @@ void sdhci_disable_irq_wakeups(struct sdhci_host 
 *host)
  }
  EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);
  
 +static int sdhci_request_irq(struct sdhci_host *host)
 +{
 +   int ret = 0;
 +
 +   /* try to enable MSI */
 +   if (host-ops-enable_msi) {
 +   ret = host-ops-enable_msi(host, sdhci_irq);
 +   if (ret)
 +   pr_warn(%s: Fall back to Pin-based Interrupt: %d\n,
 +   mmc_hostname(host-mmc), ret);
 +   }
 +
 +   if (!host-msi_enabled

Re: [PATCH] mmc: sdhci: supporting PCI MSI

2013-11-11 Thread Aaron Lu
On 11/01/2013 05:45 PM, Jackey Shen wrote:
 Enable MSI support in sdhci-pci driver and provide the mechanism
 to fall back to Legacy Pin-based Interrupt if MSI register fails.

Also note the following thread:
http://marc.info/?l=linux-mmcm=133346937412708w=2

Thanks,
Aaron

 
 Signed-off-by: Jackey Shen jackey.s...@amd.com
 Reviewed-by: Huang Rui ray.hu...@amd.com
 ---
  drivers/mmc/host/Kconfig  |  11 +
  drivers/mmc/host/sdhci.c  | 108 
 --
  include/linux/mmc/sdhci.h |   2 +
  3 files changed, 109 insertions(+), 12 deletions(-)
 
 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
 index 7fc5099..a56cf27 100644
 --- a/drivers/mmc/host/Kconfig
 +++ b/drivers/mmc/host/Kconfig
 @@ -68,6 +68,17 @@ config MMC_SDHCI_PCI
  
 If unsure, say N.
  
 +config MMC_SDHCI_PCI_MSI
 + bool SDHCI support with MSI on PCI bus
 + depends on MMC_SDHCI_PCI  PCI_MSI
 + help
 +   This enables PCI MSI (Message Signaled Interrupts) for Secure
 +   Digital Host Controller Interface.
 +
 +   If you have a controller with this capability, say Y or M here.
 +
 +   If unsure, say N.
 +
  config MMC_RICOH_MMC
   bool Ricoh MMC Controller Disabler
   depends on MMC_SDHCI_PCI
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 6785fb1..de509bc 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -13,6 +13,10 @@
   * - JMicron (hardware and technical support)
   */
  
 +#ifdef CONFIG_MMC_SDHCI_PCI_MSI
 +#include linux/pci.h
 +#endif
 +
  #include linux/delay.h
  #include linux/highmem.h
  #include linux/io.h
 @@ -2520,6 +2524,64 @@ out:
   return result;
  }
  
 +#ifdef CONFIG_MMC_SDHCI_PCI_MSI
 +static int sdhci_setup_msi(struct sdhci_host *host)
 +{
 + int ret;
 + struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 + host-msi_enabled = false;
 +
 + ret = pci_enable_msi(pdev);
 + if (ret) {
 + pr_warn(%s: Failed to allocate MSI entry\n,
 + mmc_hostname(host-mmc));
 + return ret;
 + }
 +
 + ret = request_irq(pdev-irq, sdhci_irq, 0,
 + mmc_hostname(host-mmc), host);
 + if (ret) {
 + pr_warn(%s: Failed to request MSI IRQ %d: %d\n,
 +mmc_hostname(host-mmc), pdev-irq, ret);
 + pci_disable_msi(pdev);
 + return ret;
 + }
 +
 + host-irq = pdev-irq;
 + host-msi_enabled = true;
 + return ret;
 +}
 +
 +static int sdhci_try_enable_msi(struct sdhci_host *host)
 +{
 + return sdhci_setup_msi(host);
 +}
 +
 +static void sdhci_cleanup_msi(struct sdhci_host *host)
 +{
 + struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 + free_irq(host-irq, host);
 + if (host-msi_enabled) {
 + pci_disable_msi(pdev);
 + host-msi_enabled = false;
 + }
 +}
 +
 +#else
 +
 +static int sdhci_try_enable_msi(struct sdhci_host *host)
 +{
 + return 0;
 +}
 +
 +static void sdhci_cleanup_msi(struct sdhci_host *host)
 +{
 + free_irq(host-irq, host);
 +}
 +#endif /* CONFIG_MMC_SDHCI_PCI_MSI */
 +
  
 /*\
   *   
 *
   * Suspend/resume
 *
 @@ -2569,7 +2631,8 @@ int sdhci_suspend_host(struct sdhci_host *host)
  
   if (!device_may_wakeup(mmc_dev(host-mmc))) {
   sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
 - free_irq(host-irq, host);
 + /* free any IRQ and disable MSI */
 + sdhci_cleanup_msi(host);
   } else {
   sdhci_enable_irq_wakeups(host);
   enable_irq_wake(host-irq);
 @@ -2589,10 +2652,22 @@ int sdhci_resume_host(struct sdhci_host *host)
   }
  
   if (!device_may_wakeup(mmc_dev(host-mmc))) {
 - ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
 -   mmc_hostname(host-mmc), host);
 + /* try to enable MSI */
 + ret = sdhci_try_enable_msi(host);
   if (ret)
 - return ret;
 + pr_warn(%s: Fall back to Legacy Pin-based Interrupt: 
 %d\n,
 + mmc_hostname(host-mmc), ret);
 +
 + if (!host-msi_enabled) {
 + /* fall back to legacy pin-based interrupt */
 + ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
 + mmc_hostname(host-mmc), host);
 + if (ret) {
 + pr_err(%s: Failed to request IRQ %d: %d\n,
 +  mmc_hostname(host-mmc), host-irq, 
 ret);
 + return ret;
 + }
 + }
   } else {
   sdhci_disable_irq_wakeups(host);
   

Re: [PATCH V2] sdhci: only reprogram retuning timer when flag is set

2013-11-11 Thread Aaron Lu
On 11/11/2013 05:49 PM, Arend van Spriel wrote:
 When the host-tuning_count is zero it means that the
 retuning is disabled. This is checked on the first
 run of sdhci_execute_tuning() by the if statement below:
 
   if (!(host-flags  SDHCI_NEEDS_RETUNING)  host-tuning_count 
   (host-tuning_mode == SDHCI_TUNING_MODE_1)) {
 
 So only when tuning_count is non-zero it will set the host
 flag SDHCI_USING_RETUNING_TIMER. The else statement is only
 for re-programming the timer, which means that flag must be
 set. Because that is not checked the else statement is executed
 in the first run when tuning_count is zero.
 
 This was seen on a host controller which indicated
 SDHCI_TUNING_MODE_1 (0) and tuning_count being zero. Suspect
 that (one of) these registers is not properly set.
 
 Signed-off-by: Arend van Spriel ar...@broadcom.com

Reviewed-by: Aaron Lu aaron...@intel.com

-Aaron

 ---
 This patch applies to the mmc-next branch.
 
 V2:
 - add more explanation to the commit message
 - check host flag SDHCI_USING_RETUNING_TIMER
 ---
  drivers/mmc/host/sdhci.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index bd8a098..5974599 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2014,7 +2014,7 @@ out:
   host-tuning_count * HZ);
   /* Tuning mode 1 limits the maximum data length to 4MB */
   mmc-max_blk_count = (4 * 1024 * 1024) / mmc-max_blk_size;
 - } else {
 + } else if (host-flags  SDHCI_USING_RETUNING_TIMER) {
   host-flags = ~SDHCI_NEEDS_RETUNING;
   /* Reload the new initial value for timer */
   if (host-tuning_mode == SDHCI_TUNING_MODE_1)
 

--
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


Re: [PATCH V2] mmc: sdhci: supporting PCI MSI

2013-11-11 Thread Aaron Lu
On 11/12/2013 02:56 PM, Jackey Shen wrote:
 Enable MSI support in sdhci-pci driver and provide the mechanism
 to fall back to Legacy Pin-based Interrupt if MSI register fails.
 
 Tested with SD cards on AMD platform.
 

-

 Change from V1:
 - implement this PCI MSI feature in sdhci-pci.c instead of sdhci.c

Such words can be placed under the --- below so that it will not appear
in git log.

 
 Signed-off-by: Jackey Shen jackey.s...@amd.com
 Reviewed-by: Huang Rui ray.hu...@amd.com
 ---

-
Put change related info Here.

  drivers/mmc/host/Kconfig | 11 +
  drivers/mmc/host/sdhci-pci.c | 58 
 
  drivers/mmc/host/sdhci.c | 42 ++--
  drivers/mmc/host/sdhci.h |  2 ++
  include/linux/mmc/sdhci.h|  2 ++
  5 files changed, 107 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
 index 7fc5099..a56cf27 100644
 --- a/drivers/mmc/host/Kconfig
 +++ b/drivers/mmc/host/Kconfig
 @@ -68,6 +68,17 @@ config MMC_SDHCI_PCI
  
 If unsure, say N.
  
 +config MMC_SDHCI_PCI_MSI
 + bool SDHCI support with MSI on PCI bus
 + depends on MMC_SDHCI_PCI  PCI_MSI
 + help
 +   This enables PCI MSI (Message Signaled Interrupts) for Secure
 +   Digital Host Controller Interface.
 +
 +   If you have a controller with this capability, say Y or M here.
 +
 +   If unsure, say N.
 +
  config MMC_RICOH_MMC
   bool Ricoh MMC Controller Disabler
   depends on MMC_SDHCI_PCI
 diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
 index 8f75381..2ca29c0 100644
 --- a/drivers/mmc/host/sdhci-pci.c
 +++ b/drivers/mmc/host/sdhci-pci.c
 @@ -1143,10 +1143,68 @@ static void sdhci_pci_hw_reset(struct sdhci_host 
 *host)
   slot-hw_reset(host);
  }
  
 +#ifdef CONFIG_MMC_SDHCI_PCI_MSI
 +static int sdhci_pci_setup_msi(struct sdhci_host *host, irq_handler_t 
 handler)
 +{
 + int ret;
 + struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 + host-msi_enabled = false;
 +
 + ret = pci_enable_msi(pdev);
 + if (ret) {
 + pr_warn(%s: Failed to allocate MSI entry\n,
 + mmc_hostname(host-mmc));
 + return ret;
 + }
 +
 + ret = request_irq(pdev-irq, handler, 0,
 + mmc_hostname(host-mmc), host);
 + if (ret) {
 + pr_warn(%s: Failed to request MSI IRQ %d: %d\n,
 +mmc_hostname(host-mmc), pdev-irq, ret);
 + pci_disable_msi(pdev);
 + return ret;
 + }
 +
 + host-irq = pdev-irq;
 + host-msi_enabled = true;
 + return ret;
 +}

What about we only call pci_enable_msi in sdhci-pci.c and then assign
host-irq appropriately before calling sdhci_add_host, will that work?
The only difference would be, request_irq will have SHARED flag, but I
suppose that's not a problem.

 +
 +static int sdhci_pci_enable_msi(struct sdhci_host *host, irq_handler_t 
 handler)
 +{
 + return sdhci_pci_setup_msi(host, handler);
 +}
 +
 +static void sdhci_pci_disable_msi(struct sdhci_host *host)
 +{
 + struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 + if (host-msi_enabled) {
 + pci_disable_msi(pdev);
 + host-msi_enabled = false;
 + }
 +}
 +
 +#else
 +
 +static int sdhci_pci_enable_msi(struct sdhci_host *host, irq_handler_t 
 handler)
 +{
 + return 0;
 +}
 +
 +static void sdhci_pci_disable_msi(struct sdhci_host *host)
 +{
 +}
 +#endif /* CONFIG_MMC_SDHCI_PCI_MSI */
 +
  static const struct sdhci_ops sdhci_pci_ops = {
   .enable_dma = sdhci_pci_enable_dma,
   .platform_bus_width = sdhci_pci_bus_width,
   .hw_reset   = sdhci_pci_hw_reset,
 + .enable_msi = sdhci_pci_enable_msi,
 + .disable_msi= sdhci_pci_disable_msi,
  };
  
  
 /*\
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 6785fb1..4c2a1ac 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2554,6 +2554,31 @@ void sdhci_disable_irq_wakeups(struct sdhci_host *host)
  }
  EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);
  
 +static int sdhci_request_irq(struct sdhci_host *host)
 +{
 + int ret = 0;
 +
 + /* try to enable MSI */
 + if (host-ops-enable_msi) {
 + ret = host-ops-enable_msi(host, sdhci_irq);
 + if (ret)
 + pr_warn(%s: Fall back to Pin-based Interrupt: %d\n,
 + mmc_hostname(host-mmc), ret);
 + }
 +
 + if (!host-msi_enabled) {
 + /* fall back to legacy pin-based interrupt */
 + ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
 + mmc_hostname(host-mmc), host);
 + if (ret) {
 + pr_err(%s: Failed to request IRQ %d: %d\n,
 +  

Re: [PATCH] mmc: sdhci: supporting PCI MSI

2013-11-08 Thread Aaron Lu
On 11/08/2013 04:05 PM, Jackey Shen wrote:
 Hi Aaron,
 
 On Fri, Nov 08, 2013 at 02:58:45PM +0800, Aaron Lu wrote:
 On 11/01/2013 05:45 PM, Jackey Shen wrote:
 Enable MSI support in sdhci-pci driver and provide the mechanism
 to fall back to Legacy Pin-based Interrupt if MSI register fails.

 Signed-off-by: Jackey Shen jackey.s...@amd.com
 Reviewed-by: Huang Rui ray.hu...@amd.com
 ---
  drivers/mmc/host/Kconfig  |  11 +
  drivers/mmc/host/sdhci.c  | 108 
 --
  include/linux/mmc/sdhci.h |   2 +
  3 files changed, 109 insertions(+), 12 deletions(-)

 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
 index 7fc5099..a56cf27 100644
 --- a/drivers/mmc/host/Kconfig
 +++ b/drivers/mmc/host/Kconfig
 @@ -68,6 +68,17 @@ config MMC_SDHCI_PCI
  
   If unsure, say N.
  
 +config MMC_SDHCI_PCI_MSI
 +   bool SDHCI support with MSI on PCI bus
 +   depends on MMC_SDHCI_PCI  PCI_MSI
 +   help
 + This enables PCI MSI (Message Signaled Interrupts) for Secure
 + Digital Host Controller Interface.
 +
 + If you have a controller with this capability, say Y or M here.
 +
 + If unsure, say N.
 +
  config MMC_RICOH_MMC
 bool Ricoh MMC Controller Disabler
 depends on MMC_SDHCI_PCI
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 6785fb1..de509bc 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c

 I think PCI stuffs should be in sdhci-pci.c, not sdhci.c.
 
 But I ran into one issue as per your suggestion:
 sdhci_add|remove_host() in sdhci.c calls back sdhci_try_enable|cleanup()
 in_msi sdhci-pci.c if sdhci_try_enable|cleanup_msi() are moved into 
 sdhci-pci.c.

I don't know much about PCI and interrupt, but what is the problem of
doing enable/disable msi in sdhci_pci_probe_slot?

Thanks,
Aaron

 
 Is it a best practice?
 
 Thanks,
 Jackey
 

 Thanks,
 Aaron

 @@ -13,6 +13,10 @@
   * - JMicron (hardware and technical support)
   */
  
 +#ifdef CONFIG_MMC_SDHCI_PCI_MSI
 +#include linux/pci.h
 +#endif
 +
  #include linux/delay.h
  #include linux/highmem.h
  #include linux/io.h
 @@ -2520,6 +2524,64 @@ out:
 return result;
  }
  
 +#ifdef CONFIG_MMC_SDHCI_PCI_MSI
 +static int sdhci_setup_msi(struct sdhci_host *host)
 +{
 +   int ret;
 +   struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 +   host-msi_enabled = false;
 +
 +   ret = pci_enable_msi(pdev);
 +   if (ret) {
 +   pr_warn(%s: Failed to allocate MSI entry\n,
 +   mmc_hostname(host-mmc));
 +   return ret;
 +   }
 +
 +   ret = request_irq(pdev-irq, sdhci_irq, 0,
 +   mmc_hostname(host-mmc), host);
 +   if (ret) {
 +   pr_warn(%s: Failed to request MSI IRQ %d: %d\n,
 +  mmc_hostname(host-mmc), pdev-irq, ret);
 +   pci_disable_msi(pdev);
 +   return ret;
 +   }
 +
 +   host-irq = pdev-irq;
 +   host-msi_enabled = true;
 +   return ret;
 +}
 +
 +static int sdhci_try_enable_msi(struct sdhci_host *host)
 +{
 +   return sdhci_setup_msi(host);
 +}
 +
 +static void sdhci_cleanup_msi(struct sdhci_host *host)
 +{
 +   struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 +   free_irq(host-irq, host);
 +   if (host-msi_enabled) {
 +   pci_disable_msi(pdev);
 +   host-msi_enabled = false;
 +   }
 +}
 +
 +#else
 +
 +static int sdhci_try_enable_msi(struct sdhci_host *host)
 +{
 +   return 0;
 +}
 +
 +static void sdhci_cleanup_msi(struct sdhci_host *host)
 +{
 +   free_irq(host-irq, host);
 +}
 +#endif /* CONFIG_MMC_SDHCI_PCI_MSI */
 +
  
 /*\
   * 
   *
   * Suspend/resume  
   *
 @@ -2569,7 +2631,8 @@ int sdhci_suspend_host(struct sdhci_host *host)
  
 if (!device_may_wakeup(mmc_dev(host-mmc))) {
 sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
 -   free_irq(host-irq, host);
 +   /* free any IRQ and disable MSI */
 +   sdhci_cleanup_msi(host);
 } else {
 sdhci_enable_irq_wakeups(host);
 enable_irq_wake(host-irq);
 @@ -2589,10 +2652,22 @@ int sdhci_resume_host(struct sdhci_host *host)
 }
  
 if (!device_may_wakeup(mmc_dev(host-mmc))) {
 -   ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
 - mmc_hostname(host-mmc), host);
 +   /* try to enable MSI */
 +   ret = sdhci_try_enable_msi(host);
 if (ret)
 -   return ret;
 +   pr_warn(%s: Fall back to Legacy Pin-based Interrupt: 
 %d\n,
 +   mmc_hostname(host-mmc), ret);
 +
 +   if (!host-msi_enabled) {
 +   /* fall back to legacy pin-based interrupt */
 +   ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
 +   mmc_hostname(host-mmc), host

Re: [PATCH] sdhci: do not program timer when tuning_count is zero

2013-11-08 Thread Aaron Lu
On 11/08/2013 05:10 PM, Arend van Spriel wrote:
 On 11/08/2013 07:50 AM, Aaron Lu wrote:
 On 11/07/2013 06:59 PM, Arend van Spriel wrote:
 When the host-tuning_count is zero it means that the

 If the tuning_count is zero, then the retuning timer shouldn't be
 started in the first place and not possible to run code there. Or is the
 tuning_count dynamically changed?
 
 Actually, the sdhci_execute_tuning() must run once to do the initial 
 tuning procedure. This is mandatory for SDR104. However, *re*tuning is 
 not and a zero tuning_count disables it.

So the host in question doesn't need do retuning while in SDR104 mode?
It seems your host's retuning mode is mode_1.

 
 The function is executed initially. The 'if' statement above the patched 
 'else' statement is actually responsible for programming the retuning 
 timer for the first time. However, it requires tuning_count to be 
 non-zero. The 'else' statement is actually for reloading the retuning 
 timer, which is not the case. Adding the non-zero check assures the 
 retuning timer is never started.

OK, I see.
The SDHCI_USING_RETUNING_TIMER flag is supposed to mean if the host is
currently using retuning timer to do retuning, it could also be used to
decide if retuning timer needs be re-programmed.

Anyway, a host in retuning mode 1 does not have tuning_count set seems a
little odd to me...

Thanks,
Aaron

 
 I guess the fact that this needs explaining indicates that the commit 
 message should be updated. I will send a V2 for this.
 
 Regards,
 Arend
 
 Thanks,
 Aaron

 retuning is disabled. Doing a mod_timer() with a zero
 tuning_count does something else.

 Signed-off-by: Arend van Spriel ar...@broadcom.com
 ---
   drivers/mmc/host/sdhci.c |3 ++-
   1 file changed, 2 insertions(+), 1 deletion(-)

 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 7a7fb4f..9803e7a 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2007,7 +2007,8 @@ out:
 } else {
 host-flags = ~SDHCI_NEEDS_RETUNING;
 /* Reload the new initial value for timer */
 -   if (host-tuning_mode == SDHCI_TUNING_MODE_1)
 +   if (host-tuning_count 
 +   host-tuning_mode == SDHCI_TUNING_MODE_1)
 mod_timer(host-tuning_timer, jiffies +
 host-tuning_count * HZ);
 }



 
 

--
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


Re: [PATCH] sdhci: do not program timer when tuning_count is zero

2013-11-08 Thread Aaron Lu
On 11/08/2013 07:55 PM, Arend van Spriel wrote:
 On 11/08/2013 12:49 PM, Aaron Lu wrote:
 On 11/08/2013 05:10 PM, Arend van Spriel wrote:
 On 11/08/2013 07:50 AM, Aaron Lu wrote:
 On 11/07/2013 06:59 PM, Arend van Spriel wrote:
 When the host-tuning_count is zero it means that the

 If the tuning_count is zero, then the retuning timer shouldn't be
 started in the first place and not possible to run code there. Or is the
 tuning_count dynamically changed?

 Actually, the sdhci_execute_tuning() must run once to do the initial
 tuning procedure. This is mandatory for SDR104. However, *re*tuning is
 not and a zero tuning_count disables it.

 So the host in question doesn't need do retuning while in SDR104 mode?
 It seems your host's retuning mode is mode_1.


 The function is executed initially. The 'if' statement above the patched
 'else' statement is actually responsible for programming the retuning
 timer for the first time. However, it requires tuning_count to be
 non-zero. The 'else' statement is actually for reloading the retuning
 timer, which is not the case. Adding the non-zero check assures the
 retuning timer is never started.

 OK, I see.
 The SDHCI_USING_RETUNING_TIMER flag is supposed to mean if the host is
 currently using retuning timer to do retuning, it could also be used to
 decide if retuning timer needs be re-programmed.
 
 True. I can go for that approach.
 
 Anyway, a host in retuning mode 1 does not have tuning_count set seems a
 little odd to me...
 
 Looking at sdhci.h it actually seems sdhci code is missing support for 
 the other modes:
 
   unsigned inttuning_count;   /* Timer count for re-tuning */
   unsigned inttuning_mode;/* Re-tuning mode supported by 
 host */
 #define SDHCI_TUNING_MODE_1   0
   struct timer_list   tuning_timer;   /* Timer for tuning */
 
 At least the other modes are not defined here.

Right, only retuning mode 1 is implemented currently.

Thanks,
Aaron

 
 Regards,
 Arend
 
 Thanks,
 Aaron


 I guess the fact that this needs explaining indicates that the commit
 message should be updated. I will send a V2 for this.

 Regards,
 Arend

 Thanks,
 Aaron

 retuning is disabled. Doing a mod_timer() with a zero
 tuning_count does something else.

 Signed-off-by: Arend van Spriel ar...@broadcom.com
 ---
drivers/mmc/host/sdhci.c |3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 7a7fb4f..9803e7a 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2007,7 +2007,8 @@ out:
   } else {
   host-flags = ~SDHCI_NEEDS_RETUNING;
   /* Reload the new initial value for timer */
 - if (host-tuning_mode == SDHCI_TUNING_MODE_1)
 + if (host-tuning_count 
 + host-tuning_mode == SDHCI_TUNING_MODE_1)
   mod_timer(host-tuning_timer, jiffies +
   host-tuning_count * HZ);
   }







 
 

--
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


Re: [PATCH] sdhci: do not program timer when tuning_count is zero

2013-11-07 Thread Aaron Lu
On 11/07/2013 06:59 PM, Arend van Spriel wrote:
 When the host-tuning_count is zero it means that the

If the tuning_count is zero, then the retuning timer shouldn't be
started in the first place and not possible to run code there. Or is the
tuning_count dynamically changed?

Thanks,
Aaron

 retuning is disabled. Doing a mod_timer() with a zero
 tuning_count does something else.
 
 Signed-off-by: Arend van Spriel ar...@broadcom.com
 ---
  drivers/mmc/host/sdhci.c |3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 7a7fb4f..9803e7a 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2007,7 +2007,8 @@ out:
   } else {
   host-flags = ~SDHCI_NEEDS_RETUNING;
   /* Reload the new initial value for timer */
 - if (host-tuning_mode == SDHCI_TUNING_MODE_1)
 + if (host-tuning_count 
 + host-tuning_mode == SDHCI_TUNING_MODE_1)
   mod_timer(host-tuning_timer, jiffies +
   host-tuning_count * HZ);
   }
 

--
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


Re: [PATCH] mmc: sdhci: supporting PCI MSI

2013-11-07 Thread Aaron Lu
On 11/01/2013 05:45 PM, Jackey Shen wrote:
 Enable MSI support in sdhci-pci driver and provide the mechanism
 to fall back to Legacy Pin-based Interrupt if MSI register fails.
 
 Signed-off-by: Jackey Shen jackey.s...@amd.com
 Reviewed-by: Huang Rui ray.hu...@amd.com
 ---
  drivers/mmc/host/Kconfig  |  11 +
  drivers/mmc/host/sdhci.c  | 108 
 --
  include/linux/mmc/sdhci.h |   2 +
  3 files changed, 109 insertions(+), 12 deletions(-)
 
 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
 index 7fc5099..a56cf27 100644
 --- a/drivers/mmc/host/Kconfig
 +++ b/drivers/mmc/host/Kconfig
 @@ -68,6 +68,17 @@ config MMC_SDHCI_PCI
  
 If unsure, say N.
  
 +config MMC_SDHCI_PCI_MSI
 + bool SDHCI support with MSI on PCI bus
 + depends on MMC_SDHCI_PCI  PCI_MSI
 + help
 +   This enables PCI MSI (Message Signaled Interrupts) for Secure
 +   Digital Host Controller Interface.
 +
 +   If you have a controller with this capability, say Y or M here.
 +
 +   If unsure, say N.
 +
  config MMC_RICOH_MMC
   bool Ricoh MMC Controller Disabler
   depends on MMC_SDHCI_PCI
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 6785fb1..de509bc 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c

I think PCI stuffs should be in sdhci-pci.c, not sdhci.c.

Thanks,
Aaron

 @@ -13,6 +13,10 @@
   * - JMicron (hardware and technical support)
   */
  
 +#ifdef CONFIG_MMC_SDHCI_PCI_MSI
 +#include linux/pci.h
 +#endif
 +
  #include linux/delay.h
  #include linux/highmem.h
  #include linux/io.h
 @@ -2520,6 +2524,64 @@ out:
   return result;
  }
  
 +#ifdef CONFIG_MMC_SDHCI_PCI_MSI
 +static int sdhci_setup_msi(struct sdhci_host *host)
 +{
 + int ret;
 + struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 + host-msi_enabled = false;
 +
 + ret = pci_enable_msi(pdev);
 + if (ret) {
 + pr_warn(%s: Failed to allocate MSI entry\n,
 + mmc_hostname(host-mmc));
 + return ret;
 + }
 +
 + ret = request_irq(pdev-irq, sdhci_irq, 0,
 + mmc_hostname(host-mmc), host);
 + if (ret) {
 + pr_warn(%s: Failed to request MSI IRQ %d: %d\n,
 +mmc_hostname(host-mmc), pdev-irq, ret);
 + pci_disable_msi(pdev);
 + return ret;
 + }
 +
 + host-irq = pdev-irq;
 + host-msi_enabled = true;
 + return ret;
 +}
 +
 +static int sdhci_try_enable_msi(struct sdhci_host *host)
 +{
 + return sdhci_setup_msi(host);
 +}
 +
 +static void sdhci_cleanup_msi(struct sdhci_host *host)
 +{
 + struct pci_dev *pdev = to_pci_dev(host-mmc-parent);
 +
 + free_irq(host-irq, host);
 + if (host-msi_enabled) {
 + pci_disable_msi(pdev);
 + host-msi_enabled = false;
 + }
 +}
 +
 +#else
 +
 +static int sdhci_try_enable_msi(struct sdhci_host *host)
 +{
 + return 0;
 +}
 +
 +static void sdhci_cleanup_msi(struct sdhci_host *host)
 +{
 + free_irq(host-irq, host);
 +}
 +#endif /* CONFIG_MMC_SDHCI_PCI_MSI */
 +
  
 /*\
   *   
 *
   * Suspend/resume
 *
 @@ -2569,7 +2631,8 @@ int sdhci_suspend_host(struct sdhci_host *host)
  
   if (!device_may_wakeup(mmc_dev(host-mmc))) {
   sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
 - free_irq(host-irq, host);
 + /* free any IRQ and disable MSI */
 + sdhci_cleanup_msi(host);
   } else {
   sdhci_enable_irq_wakeups(host);
   enable_irq_wake(host-irq);
 @@ -2589,10 +2652,22 @@ int sdhci_resume_host(struct sdhci_host *host)
   }
  
   if (!device_may_wakeup(mmc_dev(host-mmc))) {
 - ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
 -   mmc_hostname(host-mmc), host);
 + /* try to enable MSI */
 + ret = sdhci_try_enable_msi(host);
   if (ret)
 - return ret;
 + pr_warn(%s: Fall back to Legacy Pin-based Interrupt: 
 %d\n,
 + mmc_hostname(host-mmc), ret);
 +
 + if (!host-msi_enabled) {
 + /* fall back to legacy pin-based interrupt */
 + ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
 + mmc_hostname(host-mmc), host);
 + if (ret) {
 + pr_err(%s: Failed to request IRQ %d: %d\n,
 +  mmc_hostname(host-mmc), host-irq, 
 ret);
 + return ret;
 + }
 + }
   } else {
   sdhci_disable_irq_wakeups(host);
   disable_irq_wake(host-irq);
 @@ 

Re: [RFC PATCH 4/4] sdio: pm: set device's power state after driver runtime suspended it

2012-10-21 Thread Aaron Lu
On 10/22/2012 03:57 AM, Rafael J. Wysocki wrote:
 On Saturday 20 of October 2012 15:15:41 Aaron Lu wrote:
 On Fri, Oct 19, 2012 at 08:08:38PM +0200, Rafael J. Wysocki wrote:
 On Friday 19 of October 2012 01:39:25 Rafael J. Wysocki wrote:
 On Friday 12 of October 2012 11:12:41 Aaron Lu wrote:
 In sdio bus level runtime callback function, after call the driver's
 runtime suspend callback, we will check if the device supports a
 platform level power management, and if so, a proper power state is
 chosen by the corresponding platform callback and then set.

 Platform level runtime wakeup is also set, if device is enabled for
 runtime wakeup by its driver, it will be armed the ability to generate
 a wakeup event by the platform.

 Signed-off-by: Aaron Lu aaron...@intel.com
 ---
  drivers/mmc/core/sdio_bus.c | 49 
 +++--
  1 file changed, 47 insertions(+), 2 deletions(-)

 diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
 index aaec9e2..d83dea8 100644
 --- a/drivers/mmc/core/sdio_bus.c
 +++ b/drivers/mmc/core/sdio_bus.c
 @@ -23,6 +23,7 @@
  
  #include sdio_cis.h
  #include sdio_bus.h
 +#include sdio.h
  #include sdio_acpi.h
  
  /* show configuration fields */
 @@ -194,10 +195,54 @@ static int sdio_bus_remove(struct device *dev)
  }
  
  #ifdef CONFIG_PM
 +
 +static int sdio_bus_runtime_suspend(struct device *dev)
 +{
 + int ret;
 + sdio_power_t state;
 +
 + ret = pm_generic_runtime_suspend(dev);
 + if (ret)
 + goto out;
 +
 + if (!platform_sdio_power_manageable(dev))
 + goto out;
 +
 + platform_sdio_run_wake(dev, true);
 +
 + state = platform_sdio_choose_power_state(dev);
 + if (state == SDIO_POWER_ERROR) {
 + ret = -EIO;
 + goto out;
 + }
 +
 + ret = platform_sdio_set_power_state(dev, state);
 +
 +out:
 + return ret;
 +}
 +
 +static int sdio_bus_runtime_resume(struct device *dev)
 +{
 + int ret;
 +
 + if (platform_sdio_power_manageable(dev)) {
 + platform_sdio_run_wake(dev, false);
 + ret = platform_sdio_set_power_state(dev, SDIO_D0);
 + if (ret)
 + goto out;
 + }
 +
 + ret = pm_generic_runtime_resume(dev);
 +
 +out:
 + return ret;
 +}
 +

 Most likely we will need to make analogous changes for other bus types that
 don't support power management natively, like platform, SPI, I2C etc.  In 
 all
 of them the _runtime_suspend() and _runtime_resume() routine will look
 almost exactly the same except for the platform_sdio_ prefix.

 For this reason, I think it would be better to simply define two functions
 acpi_pm_runtime_suspend() and acpi_pm_runtime_resume() that will do all of
 the ACPI-specific operations related to runtime suspend/resume.  Then, we
 will be able to use these functions for all of the bus types in question
 in the same way (we may also need to add analogous functions for system
 suspend/resume handling).

 Something like in the (totally untested) patch below.

 Looks good to me.
 I'll test the code and put it into v2 of the patchset with your
 sign-off, is it OK?
 
 I'd rather do it a bit differently in the signed-off version (I'm working
 on these patches, they should be ready around Tuesday), but if you can test

OK, thanks.

 it in its current form, that'd be useful too.

I was planning to test it some time later, so looks like I can directly
test your signed-off version :-)

Thanks,
Aaron

--
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


Re: [RFC PATCH 2/4] mmc: sdio: bind sdio device with acpi device

2012-10-20 Thread Aaron Lu
On Fri, Oct 19, 2012 at 01:25:46AM +0200, Rafael J. Wysocki wrote:
 On Friday 12 of October 2012 11:12:39 Aaron Lu wrote:
  ACPI spec defines the _ADDR encoding for sdio bus as:
  High word - slot number (0 based)
  Low word  - function number
  
  This patch adds support for sdio device binding with acpi using the
  generic ACPI glue framework.
  
  Signed-off-by: Aaron Lu aaron...@intel.com
  ---
   drivers/mmc/core/Makefile|  1 +
   drivers/mmc/core/sdio_acpi.c | 35 +++
   drivers/mmc/core/sdio_bus.c  | 14 --
   drivers/mmc/core/sdio_bus.h  |  2 ++
   4 files changed, 50 insertions(+), 2 deletions(-)
   create mode 100644 drivers/mmc/core/sdio_acpi.c
  
  diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
  index 38ed210..c8300aa 100644
  --- a/drivers/mmc/core/Makefile
  +++ b/drivers/mmc/core/Makefile
  @@ -10,3 +10,4 @@ mmc_core-y:= core.o bus.o host.o \
 quirks.o slot-gpio.o
   
   mmc_core-$(CONFIG_DEBUG_FS)+= debugfs.o
  +mmc_core-$(CONFIG_ACPI)+= sdio_acpi.o
  diff --git a/drivers/mmc/core/sdio_acpi.c b/drivers/mmc/core/sdio_acpi.c
  new file mode 100644
  index 000..0f92e90
  --- /dev/null
  +++ b/drivers/mmc/core/sdio_acpi.c
  @@ -0,0 +1,35 @@
  +#include linux/mmc/host.h
  +#include linux/mmc/card.h
  +#include linux/mmc/sdhci.h
  +#include linux/mmc/sdio_func.h
  +#include linux/acpi.h
  +#include acpi/acpi_bus.h
  +#include sdio_bus.h
  +
  +static int acpi_sdio_find_device(struct device *dev, acpi_handle *handle)
  +{
  +   struct sdio_func *func;
  +   struct sdhci_host *host;
  +   u64 addr;
  +
  +   func = dev_to_sdio_func(dev);
  +   host = mmc_priv(func-card-host);
  +
  +   addr = (host-slotno  16) | func-num;
  +
  +   *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev), addr);
  +   if (!*handle)
  +   return -ENODEV;
  +
  +   return 0;
  +}
  +
  +static struct acpi_bus_type acpi_sdio_bus = {
  +   .bus = sdio_bus_type,
  +   .find_device = acpi_sdio_find_device,
  +};
  +
  +int sdio_acpi_register(void)
 
 I'd call it sdio_acpi_register_bus().

OK, will update this in v2.

 
  +{
  +   return register_acpi_bus_type(acpi_sdio_bus);
  +}
  diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
  index 6bf6879..aaec9e2 100644
  --- a/drivers/mmc/core/sdio_bus.c
  +++ b/drivers/mmc/core/sdio_bus.c
  @@ -23,6 +23,7 @@
   
   #include sdio_cis.h
   #include sdio_bus.h
  +#include sdio_acpi.h
   
   /* show configuration fields */
   #define sdio_config_attr(field, format_string) 
  \
  @@ -209,7 +210,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
   
   #endif /* !CONFIG_PM */
   
  -static struct bus_type sdio_bus_type = {
  +struct bus_type sdio_bus_type = {
  .name   = sdio,
  .dev_attrs  = sdio_dev_attrs,
  .match  = sdio_bus_match,
  @@ -221,7 +222,16 @@ static struct bus_type sdio_bus_type = {
   
   int sdio_register_bus(void)
   {
  -   return bus_register(sdio_bus_type);
  +   int ret;
  +
  +   ret = bus_register(sdio_bus_type);
  +   if (ret)
  +   goto out;
  +
  +   ret = sdio_acpi_register();
 
 What happens if this fails?

Oh, yes, it shouldn't affect the sdio_register_bus function. So I'll not
check its return value in v2.

Thanks,
Aaron

 
  +
  +out:
  +   return ret;
   }
   
   void sdio_unregister_bus(void)
  diff --git a/drivers/mmc/core/sdio_bus.h b/drivers/mmc/core/sdio_bus.h
  index 567a768..91c0e93 100644
  --- a/drivers/mmc/core/sdio_bus.h
  +++ b/drivers/mmc/core/sdio_bus.h
  @@ -18,5 +18,7 @@ void sdio_remove_func(struct sdio_func *func);
   int sdio_register_bus(void);
   void sdio_unregister_bus(void);
   
  +extern struct bus_type sdio_bus_type;
  +
   #endif
 
 Thanks,
 Rafael
 
 
 -- 
 I speak only for myself.
 Rafael J. Wysocki, Intel Open Source Technology Center.
--
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


Re: [RFC PATCH 4/4] sdio: pm: set device's power state after driver runtime suspended it

2012-10-20 Thread Aaron Lu
On Fri, Oct 19, 2012 at 08:08:38PM +0200, Rafael J. Wysocki wrote:
 On Friday 19 of October 2012 01:39:25 Rafael J. Wysocki wrote:
  On Friday 12 of October 2012 11:12:41 Aaron Lu wrote:
   In sdio bus level runtime callback function, after call the driver's
   runtime suspend callback, we will check if the device supports a
   platform level power management, and if so, a proper power state is
   chosen by the corresponding platform callback and then set.
   
   Platform level runtime wakeup is also set, if device is enabled for
   runtime wakeup by its driver, it will be armed the ability to generate
   a wakeup event by the platform.
   
   Signed-off-by: Aaron Lu aaron...@intel.com
   ---
drivers/mmc/core/sdio_bus.c | 49 
   +++--
1 file changed, 47 insertions(+), 2 deletions(-)
   
   diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
   index aaec9e2..d83dea8 100644
   --- a/drivers/mmc/core/sdio_bus.c
   +++ b/drivers/mmc/core/sdio_bus.c
   @@ -23,6 +23,7 @@

#include sdio_cis.h
#include sdio_bus.h
   +#include sdio.h
#include sdio_acpi.h

/* show configuration fields */
   @@ -194,10 +195,54 @@ static int sdio_bus_remove(struct device *dev)
}

#ifdef CONFIG_PM
   +
   +static int sdio_bus_runtime_suspend(struct device *dev)
   +{
   + int ret;
   + sdio_power_t state;
   +
   + ret = pm_generic_runtime_suspend(dev);
   + if (ret)
   + goto out;
   +
   + if (!platform_sdio_power_manageable(dev))
   + goto out;
   +
   + platform_sdio_run_wake(dev, true);
   +
   + state = platform_sdio_choose_power_state(dev);
   + if (state == SDIO_POWER_ERROR) {
   + ret = -EIO;
   + goto out;
   + }
   +
   + ret = platform_sdio_set_power_state(dev, state);
   +
   +out:
   + return ret;
   +}
   +
   +static int sdio_bus_runtime_resume(struct device *dev)
   +{
   + int ret;
   +
   + if (platform_sdio_power_manageable(dev)) {
   + platform_sdio_run_wake(dev, false);
   + ret = platform_sdio_set_power_state(dev, SDIO_D0);
   + if (ret)
   + goto out;
   + }
   +
   + ret = pm_generic_runtime_resume(dev);
   +
   +out:
   + return ret;
   +}
   +
  
  Most likely we will need to make analogous changes for other bus types that
  don't support power management natively, like platform, SPI, I2C etc.  In 
  all
  of them the _runtime_suspend() and _runtime_resume() routine will look
  almost exactly the same except for the platform_sdio_ prefix.
  
  For this reason, I think it would be better to simply define two functions
  acpi_pm_runtime_suspend() and acpi_pm_runtime_resume() that will do all of
  the ACPI-specific operations related to runtime suspend/resume.  Then, we
  will be able to use these functions for all of the bus types in question
  in the same way (we may also need to add analogous functions for system
  suspend/resume handling).
 
 Something like in the (totally untested) patch below.

Looks good to me.
I'll test the code and put it into v2 of the patchset with your
sign-off, is it OK?

Thanks,
Aaron

 
 With this code the SDIO bus type should be able to use
 acpi_subsys_runtime_suspend() and acpi_subsys_runtime_resume() as its
 bus-type-level runtime suspend/resume callback routines, respectively.
 
 Thanks,
 Rafael
 
 
 Prototype, no sign-off.
 ---
  drivers/acpi/dev_pm.c |   54 
 ++
  include/linux/acpi.h  |   12 +++
  2 files changed, 66 insertions(+)
 
 Index: linux-pm/drivers/acpi/dev_pm.c
 ===
 --- /dev/null
 +++ linux-pm/drivers/acpi/dev_pm.c
 @@ -0,0 +1,54 @@
 +#include linux/acpi.h
 +#include linux/device.h
 +#include linux/kernel.h
 +#include linux/pm_qos.h
 +#include linux/pm_runtime.h
 +
 +#include acpi/acpi_bus.h
 +
 +int acpi_dev_runtime_suspend(struct device *dev)
 +{
 + acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
 + bool enable_wakeup;
 + int power_state;
 +
 + if (!handle || !acpi_bus_power_manageable(handle))
 + return 0;
 +
 + enable_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP))
 + != PM_QOS_FLAGS_NONE;
 + acpi_pm_device_run_wake(dev, enable_wakeup);
 +
 + power_state = acpi_pm_device_sleep_state(dev, NULL, ACPI_STATE_D3);
 + if (power_state  ACPI_STATE_D0 || power_state  ACPI_STATE_D3)
 + return -EIO;
 +
 + return acpi_bus_set_power(handle, power_state);
 +}
 +EXPORT_SYMBOL_GPL(acpi_dev_runtime_suspend);
 +
 +int acpi_dev_runtime_resume(struct device *dev)
 +{
 + acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
 +
 + if (!handle || !acpi_bus_power_manageable(handle))
 + return 0;
 +
 + acpi_pm_device_run_wake(dev, false);
 + return acpi_bus_set_power(handle, ACPI_STATE_D0);
 +}
 +EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume);
 +
 +int acpi_subsys_runtime_suspend

[RFC PATCH 0/4] Enable setting of sdio device power state with ACPI

2012-10-11 Thread Aaron Lu
This patchset enables setting of acpi power state for sdio device
when it is runtime suspended/resumed. SDIO function drivers can use
the interfaces too introduced in patch 3 when there is such a need.

Patch 1 adds slot number information to the sdhci_host structure,
the slot number will be used to bind the sdio device with acpi node.

Patch 2 does the actual binding.

Patch 3 introduces a platform power management operation structure,
in which 4 callbacks are defined. The reason this structure is used is
that in addition to ACPI, there may be other platform mechanisms to
place a device into a low power state. And a implementation of this
structure is done for ACPI in this patch. The idea and the definition
of this structure is heavily based on the one used in PCI subsystem.

Patch 4 utilizes the newly added platform pm api to set the device
into a low power state after its driver's runtime suspend callback.
Its runtime wakeup capability is also enabled, and for this to work,
driver must call device_set_run_wake(dev, true) somewhere when wakeup
is desired. Please note that this wakeup mentioned here is realized
through a sideband signal, it's not done by a SDIO interrupt. So
platform support code is needed.

Aaron Lu (4):
  sdhci: add slot number into sdhci_host structure
  mmc: sdio: bind sdio device with acpi device
  sdio: introduce sdio_platform_pm_ops
  sdio: pm: set device's power state after driver runtime suspended it

 drivers/mmc/core/Makefile  |  1 +
 drivers/mmc/core/sdio.c| 37 +++
 drivers/mmc/core/sdio.h| 28 +++
 drivers/mmc/core/sdio_acpi.c   | 81 ++
 drivers/mmc/core/sdio_bus.c| 63 +---
 drivers/mmc/core/sdio_bus.h|  2 ++
 drivers/mmc/host/sdhci-pci.c   |  2 +-
 drivers/mmc/host/sdhci-pltfm.c |  4 +--
 drivers/mmc/host/sdhci-s3c.c   |  2 +-
 drivers/mmc/host/sdhci-spear.c |  4 +--
 drivers/mmc/host/sdhci.c   |  3 +-
 drivers/mmc/host/sdhci.h   |  2 +-
 include/linux/mmc/sdhci.h  |  1 +
 13 files changed, 218 insertions(+), 12 deletions(-)
 create mode 100644 drivers/mmc/core/sdio.h
 create mode 100644 drivers/mmc/core/sdio_acpi.c

-- 
1.7.12.21.g871e293

--
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


[RFC PATCH 2/4] mmc: sdio: bind sdio device with acpi device

2012-10-11 Thread Aaron Lu
ACPI spec defines the _ADDR encoding for sdio bus as:
High word - slot number (0 based)
Low word  - function number

This patch adds support for sdio device binding with acpi using the
generic ACPI glue framework.

Signed-off-by: Aaron Lu aaron...@intel.com
---
 drivers/mmc/core/Makefile|  1 +
 drivers/mmc/core/sdio_acpi.c | 35 +++
 drivers/mmc/core/sdio_bus.c  | 14 --
 drivers/mmc/core/sdio_bus.h  |  2 ++
 4 files changed, 50 insertions(+), 2 deletions(-)
 create mode 100644 drivers/mmc/core/sdio_acpi.c

diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 38ed210..c8300aa 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -10,3 +10,4 @@ mmc_core-y:= core.o bus.o host.o \
   quirks.o slot-gpio.o
 
 mmc_core-$(CONFIG_DEBUG_FS)+= debugfs.o
+mmc_core-$(CONFIG_ACPI)+= sdio_acpi.o
diff --git a/drivers/mmc/core/sdio_acpi.c b/drivers/mmc/core/sdio_acpi.c
new file mode 100644
index 000..0f92e90
--- /dev/null
+++ b/drivers/mmc/core/sdio_acpi.c
@@ -0,0 +1,35 @@
+#include linux/mmc/host.h
+#include linux/mmc/card.h
+#include linux/mmc/sdhci.h
+#include linux/mmc/sdio_func.h
+#include linux/acpi.h
+#include acpi/acpi_bus.h
+#include sdio_bus.h
+
+static int acpi_sdio_find_device(struct device *dev, acpi_handle *handle)
+{
+   struct sdio_func *func;
+   struct sdhci_host *host;
+   u64 addr;
+
+   func = dev_to_sdio_func(dev);
+   host = mmc_priv(func-card-host);
+
+   addr = (host-slotno  16) | func-num;
+
+   *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev), addr);
+   if (!*handle)
+   return -ENODEV;
+
+   return 0;
+}
+
+static struct acpi_bus_type acpi_sdio_bus = {
+   .bus = sdio_bus_type,
+   .find_device = acpi_sdio_find_device,
+};
+
+int sdio_acpi_register(void)
+{
+   return register_acpi_bus_type(acpi_sdio_bus);
+}
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 6bf6879..aaec9e2 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -23,6 +23,7 @@
 
 #include sdio_cis.h
 #include sdio_bus.h
+#include sdio_acpi.h
 
 /* show configuration fields */
 #define sdio_config_attr(field, format_string) \
@@ -209,7 +210,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
 
 #endif /* !CONFIG_PM */
 
-static struct bus_type sdio_bus_type = {
+struct bus_type sdio_bus_type = {
.name   = sdio,
.dev_attrs  = sdio_dev_attrs,
.match  = sdio_bus_match,
@@ -221,7 +222,16 @@ static struct bus_type sdio_bus_type = {
 
 int sdio_register_bus(void)
 {
-   return bus_register(sdio_bus_type);
+   int ret;
+
+   ret = bus_register(sdio_bus_type);
+   if (ret)
+   goto out;
+
+   ret = sdio_acpi_register();
+
+out:
+   return ret;
 }
 
 void sdio_unregister_bus(void)
diff --git a/drivers/mmc/core/sdio_bus.h b/drivers/mmc/core/sdio_bus.h
index 567a768..91c0e93 100644
--- a/drivers/mmc/core/sdio_bus.h
+++ b/drivers/mmc/core/sdio_bus.h
@@ -18,5 +18,7 @@ void sdio_remove_func(struct sdio_func *func);
 int sdio_register_bus(void);
 void sdio_unregister_bus(void);
 
+extern struct bus_type sdio_bus_type;
+
 #endif
 
-- 
1.7.12.21.g871e293

--
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


[RFC PATCH 3/4] sdio: introduce sdio_platform_pm_ops

2012-10-11 Thread Aaron Lu
Some platform has the ability to set the sdio device into a low power
state with some specific method, e.g. ACPI on x86 based system can use
acpi control methods to change the device's power state.

Considering there may be different platforms utilizing different
mechanisms to achieve this, a new structure is introduced to let
individual platform to use these callbacks to do the job.

The structure contains 4 callbacks:
- is_manageable
  return true when the platform can manage the device's power;
  return false otherwise.
- choose_state
  Choose a proper power state for the device
- set_state
  Set the device's power state
- run_wake
  Enable the device's runtime wakeup capability from the platform's
  perspective.

And 4 functions to wrap these callbacks:
- bool platform_sdio_power_manageable(struct device *dev)
- int platform_sdio_choose_power_state(struct device *dev)
- int platform_sdio_set_power_state(struct device *dev, int state)
- int platform_sdio_run_wake(struct device *dev, bool enable)
So when these callbacks are desired, these wrapper functions should be
used. And if someday some sdio function driver which lives out of the
mmc subsystem has a need to use these wrapper functions, they can be
exported.

sdio_acpi.c implements these callbacks utilizing ACPI code.

The idea of this patch and the definition/wrapper of these callbacks
are heavily based on the one used in PCI subsystem.

Signed-off-by: Aaron Lu aaron...@intel.com
---
 drivers/mmc/core/sdio.c  | 37 ++
 drivers/mmc/core/sdio.h  | 28 ++
 drivers/mmc/core/sdio_acpi.c | 48 +++-
 3 files changed, 112 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/core/sdio.h

diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index d4619e2..84b01b2 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -27,6 +27,7 @@
 #include sd_ops.h
 #include sdio_ops.h
 #include sdio_cis.h
+#include sdio.h
 
 static int sdio_read_fbr(struct sdio_func *func)
 {
@@ -1178,3 +1179,39 @@ err:
return err;
 }
 
+static struct sdio_platform_pm_ops *sdio_platform_pm;
+
+int sdio_set_platform_pm(struct sdio_platform_pm_ops *ops)
+{
+   if (!ops-is_manageable || !ops-choose_state ||
+   !ops-set_state || !ops-run_wake)
+   return -EINVAL;
+
+   sdio_platform_pm = ops;
+
+   return 0;
+}
+
+bool platform_sdio_power_manageable(struct device *dev)
+{
+   return sdio_platform_pm ?
+   sdio_platform_pm-is_manageable(dev) : false;
+}
+
+int platform_sdio_run_wake(struct device *dev, bool enable)
+{
+   return sdio_platform_pm ?
+   sdio_platform_pm-run_wake(dev, enable) : -ENODEV;
+}
+
+int platform_sdio_choose_power_state(struct device *dev)
+{
+   return sdio_platform_pm ?
+   sdio_platform_pm-choose_state(dev) : SDIO_POWER_ERROR;
+}
+
+int platform_sdio_set_power_state(struct device *dev, int state)
+{
+   return sdio_platform_pm ?
+   sdio_platform_pm-set_state(dev, state) : -ENOSYS;
+}
diff --git a/drivers/mmc/core/sdio.h b/drivers/mmc/core/sdio.h
new file mode 100644
index 000..a95929e
--- /dev/null
+++ b/drivers/mmc/core/sdio.h
@@ -0,0 +1,28 @@
+#ifndef __SDIO_H
+#define __SDIO_H
+
+typedef int __bitwise sdio_power_t;
+
+#define SDIO_D0  ((sdio_power_t __force) 0)
+#define SDIO_D1  ((sdio_power_t __force) 1)
+#define SDIO_D2  ((sdio_power_t __force) 2)
+#define SDIO_D3hot   ((sdio_power_t __force) 3)
+#define SDIO_D3cold  ((sdio_power_t __force) 4)
+#define SDIO_UNKNOWN ((sdio_power_t __force) 5)
+#define SDIO_POWER_ERROR ((sdio_power_t __force) -1)
+
+struct sdio_platform_pm_ops {
+   bool (*is_manageable)(struct device *dev);
+   int (*choose_state)(struct device *dev);
+   int (*set_state)(struct device *dev, sdio_power_t state);
+   int (*run_wake)(struct device *dev, bool enabel);
+};
+
+int sdio_set_platform_pm(struct sdio_platform_pm_ops *ops);
+
+bool platform_sdio_power_manageable(struct device *dev);
+sdio_power_t platform_sdio_choose_power_state(struct device *dev);
+int platform_sdio_set_power_state(struct device *dev, sdio_power_t state);
+int platform_sdio_run_wake(struct device *dev, bool enable);
+
+#endif
diff --git a/drivers/mmc/core/sdio_acpi.c b/drivers/mmc/core/sdio_acpi.c
index 0f92e90..a5b3012 100644
--- a/drivers/mmc/core/sdio_acpi.c
+++ b/drivers/mmc/core/sdio_acpi.c
@@ -4,8 +4,45 @@
 #include linux/mmc/sdio_func.h
 #include linux/acpi.h
 #include acpi/acpi_bus.h
+#include sdio.h
 #include sdio_bus.h
 
+static bool acpi_sdio_power_manageable(struct device *dev)
+{
+   acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
+   return handle ? acpi_bus_power_manageable(handle) : false;
+}
+
+static int acpi_sdio_choose_power_state(struct device *dev)
+{
+   return acpi_pm_device_sleep_state(dev, NULL, ACPI_STATE_D3);
+}
+
+static int

[RFC PATCH 4/4] sdio: pm: set device's power state after driver runtime suspended it

2012-10-11 Thread Aaron Lu
In sdio bus level runtime callback function, after call the driver's
runtime suspend callback, we will check if the device supports a
platform level power management, and if so, a proper power state is
chosen by the corresponding platform callback and then set.

Platform level runtime wakeup is also set, if device is enabled for
runtime wakeup by its driver, it will be armed the ability to generate
a wakeup event by the platform.

Signed-off-by: Aaron Lu aaron...@intel.com
---
 drivers/mmc/core/sdio_bus.c | 49 +++--
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index aaec9e2..d83dea8 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -23,6 +23,7 @@
 
 #include sdio_cis.h
 #include sdio_bus.h
+#include sdio.h
 #include sdio_acpi.h
 
 /* show configuration fields */
@@ -194,10 +195,54 @@ static int sdio_bus_remove(struct device *dev)
 }
 
 #ifdef CONFIG_PM
+
+static int sdio_bus_runtime_suspend(struct device *dev)
+{
+   int ret;
+   sdio_power_t state;
+
+   ret = pm_generic_runtime_suspend(dev);
+   if (ret)
+   goto out;
+
+   if (!platform_sdio_power_manageable(dev))
+   goto out;
+
+   platform_sdio_run_wake(dev, true);
+
+   state = platform_sdio_choose_power_state(dev);
+   if (state == SDIO_POWER_ERROR) {
+   ret = -EIO;
+   goto out;
+   }
+
+   ret = platform_sdio_set_power_state(dev, state);
+
+out:
+   return ret;
+}
+
+static int sdio_bus_runtime_resume(struct device *dev)
+{
+   int ret;
+
+   if (platform_sdio_power_manageable(dev)) {
+   platform_sdio_run_wake(dev, false);
+   ret = platform_sdio_set_power_state(dev, SDIO_D0);
+   if (ret)
+   goto out;
+   }
+
+   ret = pm_generic_runtime_resume(dev);
+
+out:
+   return ret;
+}
+
 static const struct dev_pm_ops sdio_bus_pm_ops = {
SET_RUNTIME_PM_OPS(
-   pm_generic_runtime_suspend,
-   pm_generic_runtime_resume,
+   sdio_bus_runtime_suspend,
+   sdio_bus_runtime_resume,
pm_generic_runtime_idle
)
 };
-- 
1.7.12.21.g871e293

--
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


Re: v3.6-rc1: modprobe hangs with sdhci failure on dell e6410

2012-08-23 Thread Aaron Lu
On Wed, Aug 22, 2012 at 10:11 PM, Arend van Spriel ar...@broadcom.com wrote:
 A quick search using google did not provide clues. Regardless if there is
 anything inserted the hang occurs.

 Gr. AvS

Also, your .config might be helpful.

Thanks,
Aaron
--
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


Re: v3.6-rc1: modprobe hangs with sdhci failure on dell e6410

2012-08-22 Thread Aaron Lu
On 08/22/2012 10:11 PM, Arend van Spriel wrote:
 A quick search using google did not provide clues. Regardless if there 
 is anything inserted the hang occurs.

your dmesg shows:

[  241.908294] INFO: task modprobe:134 blocked for more than 120 seconds.
[  241.908298] echo 0  /proc/sys/kernel/hung_task_timeout_secs disables this 
message.
[  241.908301] modprobeD f48abbcc 0   134 98 0x
[  241.908307]  f48abc3c 0082 f59d0ebc f48abbcc c1289228  f4f3e480 
c17b0380
[  241.908313]  c17b0380 c17b0380 1de51926  c17b0380 f59d5380 f4f3e480 
f4853ed0
[  241.908319]   0001 f48abc28  f59d0eb0 f4df3131 c17abe80 
0003
[  241.908326] Call Trace:
[  241.908337]  [c1289228] ? timerqueue_add+0x58/0xb0
[  241.908345]  [c14ca103] schedule+0x23/0x60
[  241.908349]  [c14c8f5f] schedule_hrtimeout_range_clock+0xaf/0x130
[  241.908354]  [c105b4f0] ? update_rmtp+0x80/0x80
[  241.908359]  [c105c796] ? hrtimer_start_range_ns+0x26/0x30
[  241.908362]  [c14c8ff7] schedule_hrtimeout_range+0x17/0x20
[  241.908369]  [c10462c9] usleep_range+0x39/0x40
[  241.908384]  [f8030b39] sdhci_do_start_signal_voltage_switch+0x59/0x150 
[sdhci]
[  241.908390]  [f8030c71] sdhci_start_signal_voltage_switch+0x41/0x80 [sdhci]
[  241.908401]  [f805ded8] mmc_set_signal_voltage+0x58/0xb0 [mmc_core]
[  241.908411]  [f805e105] mmc_power_up+0x85/0xf0 [mmc_core]
[  241.908420]  [f805e1a8] mmc_start_host+0x38/0x50 [mmc_core]
[  241.908430]  [f805f4b0] mmc_add_host+0x50/0x90 [mmc_core]
[  241.908436]  [f8031b37] sdhci_add_host+0x837/0xbc0 [sdhci]
[  241.908444]  [f807f10a] sdhci_pci_probe+0x3fc/0x5f0 [sdhci_pci]
[  241.908449]  [c14cac5f] ? _raw_spin_lock_irqsave+0x2f/0x50
[  241.908455]  [c12a5407] local_pci_probe+0x47/0xb0
[  241.908460]  [c12a6458] pci_device_probe+0x68/0x90
[  241.908467]  [c1337c48] driver_probe_device+0x78/0x1f0
[  241.908471]  [c12a5393] ? pci_match_device+0xb3/0xc0
[  241.908476]  [c1337e41] __driver_attach+0x81/0x90
[  241.908480]  [c1336613] bus_for_each_dev+0x53/0x80
[  241.908484]  [c1337abe] driver_attach+0x1e/0x20
[  241.908488]  [c1337dc0] ? driver_probe_device+0x1f0/0x1f0
[  241.908491]  [c1337512] bus_add_driver+0xb2/0x230
[  241.908495]  [c12a62d0] ? pci_dev_put+0x20/0x20
[  241.908499]  [c12a62d0] ? pci_dev_put+0x20/0x20
[  241.908502]  [c133841a] driver_register+0x6a/0x140
[  241.908509]  [c10be41b] ? tracepoint_module_notify+0x12b/0x190
[  241.908514]  [c12a6694] __pci_register_driver+0x44/0xb0
[  241.908522]  [f8086017] sdhci_drv_init+0x17/0x19 [sdhci_pci]
[  241.908526]  [c1001114] do_one_initcall+0x34/0x170
[  241.908532]  [f8086000] ? 0xf8085fff
[  241.908539]  [c1090c3e] sys_init_module+0xee/0x1460
[  241.908542]  [c108f620] ? free_notes_attrs+0x50/0x50
[  241.908549]  [f8073000] ? 0xf8072fff
[  241.908556]  [c14d175f] sysenter_do_call+0x12/0x28

Looks like the usleep_range called in
sdhci_do_start_signal_voltage_switch blocked modprobe, maybe the timeout
never happens for whatever reason?

Can you please try the following patch:

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 8ac5246..30ce05d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1212,6 +1212,9 @@ static void mmc_power_up(struct mmc_host *host)
host-ios.timing = MMC_TIMING_LEGACY;
mmc_set_ios(host);
 
+   /* debug */
+   usleep_range(5000, 5500);
+
/* Set signal voltage to 3.3V */
mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, false);
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 9a11dc3..a181c46 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1616,7 +1616,8 @@ static int sdhci_do_start_signal_voltage_switch(struct 
sdhci_host *host,
 * to 3.3V. If so, we change the voltage to 3.3V and return quickly.
 */
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-   if (ios-signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+   if (ios-signal_voltage == MMC_SIGNAL_VOLTAGE_330 
+   (ctrl  SDHCI_CTRL_VDD_180)) {
/* Set 1.8V Signal Enable in the Host Control2 register to 0 */
ctrl = ~SDHCI_CTRL_VDD_180;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);


The above code did 2 things:
1 calling usleep_range in another place to see what happened;
2 avoid setting 3.3v signalling voltage if host is already at 3.3v
signalling voltage.

Thanks,
Aaron
--
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


Re: [PATCH] Add MSI support for SDHCI PCI hosts

2012-08-19 Thread Aaron Lu
Hello,

On 08/18/2012 01:06 PM, Daniel J Blueman wrote:
 Hi Philip,
 
 The interrupt could be from another source, though Message Signalled
 Interrupts are a PCI (and variants) only feature at present. I'm happy
 to split the patch and/or make the module param specific to sdhci-pci.

Not sure if you are aware of the following thread:
http://marc.info/?l=linux-mmcm=133346937412708w=2

Enabling msi will break some systems.

And more comments below.

 
 Let's see what the maintainers prefer...Chris?
 
 Dan
 
 On 18 August 2012 00:35, Philip Rakity prak...@marvell.com wrote:

 The interrupt source could be from a non-pci device.  Say a gpio or whatever.
 Does it make sense to break this patch into two patches ?

 On Aug 17, 2012, at 2:14 AM, Daniel J Blueman dan...@quora.org wrote:

 Allow module parameter 'enable_msi' to request an MSI interrupt for
 hosts where available (presently PCI). Useful as a workaround on
 platforms where the legacy interrupt is broken.

 Signed-off-by: Daniel J Blueman dan...@quora.org
 ---
 drivers/mmc/host/sdhci-pci.c |   30 ++
 drivers/mmc/host/sdhci.c |   23 +++
 drivers/mmc/host/sdhci.h |2 ++
 3 files changed, 55 insertions(+)

 diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
 index 504da71..fbde589 100644
 --- a/drivers/mmc/host/sdhci-pci.c
 +++ b/drivers/mmc/host/sdhci-pci.c
 @@ -934,6 +934,34 @@ static int sdhci_pci_enable_dma(struct sdhci_host 
 *host)
   return 0;
 }

 +static int sdhci_pci_enable_msi(struct sdhci_host *host)
 +{
 + struct sdhci_pci_slot *slot;
 + struct pci_dev *pdev;
 + int ret;
 +
 + slot = sdhci_priv(host);
 + pdev = slot-chip-pdev;
 +
 + ret = pci_enable_msi(pdev);
 + if (ret)
 + return ret;
 +
 + host-irq = pdev-irq;
 + return 0;
 +}
 +
 +static void sdhci_pci_disable_msi(struct sdhci_host *host)
 +{
 + struct sdhci_pci_slot *slot;
 + struct pci_dev *pdev;
 +
 + slot = sdhci_priv(host);
 + pdev = slot-chip-pdev;
 +
 + pci_disable_msi(pdev);
 +}
 +
 static int sdhci_pci_8bit_width(struct sdhci_host *host, int width)
 {
   u8 ctrl;
 @@ -976,6 +1004,8 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)

 static struct sdhci_ops sdhci_pci_ops = {
   .enable_dma = sdhci_pci_enable_dma,
 + .enable_msi = sdhci_pci_enable_msi,
 + .disable_msi= sdhci_pci_disable_msi,
   .platform_8bit_width= sdhci_pci_8bit_width,
   .hw_reset   = sdhci_pci_hw_reset,
 };
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 9a11dc3..9fa2180 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -45,6 +45,7 @@

 static unsigned int debug_quirks = 0;
 static unsigned int debug_quirks2;
 +static bool enable_msi;

 static void sdhci_finish_data(struct sdhci_host *);

 @@ -2433,6 +2434,9 @@ int sdhci_suspend_host(struct sdhci_host *host)

   free_irq(host-irq, host);

 + if (host-ops-disable_msi  enable_msi)
 + host-ops-disable_msi(host);
 +

Don't know why msi needs to be disabled/enabled on suspend/resume.
And doing this in sdhci_pci_suspend/resume might be more appropriate if
required.

Thanks,
Aaron

   return ret;
 }

 @@ -2447,6 +2451,12 @@ int sdhci_resume_host(struct sdhci_host *host)
   host-ops-enable_dma(host);
   }

 + if (host-ops-enable_msi  enable_msi) {
 + ret = host-ops-enable_msi(host);
 + if (ret)
 + return ret;
 + }
 +
   ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
 mmc_hostname(host-mmc), host);
   if (ret)
 @@ -3024,6 +3034,12 @@ int sdhci_add_host(struct sdhci_host *host)
   host-tuning_timer.function = sdhci_tuning_timer;
   }

 + if (host-ops-enable_msi  enable_msi) {
 + ret = host-ops-enable_msi(host);
 + if (ret)
 + return ret;
 + }
 +
   ret = request_irq(host-irq, sdhci_irq, IRQF_SHARED,
   mmc_hostname(mmc), host);
   if (ret) {
 @@ -3071,6 +3087,8 @@ int sdhci_add_host(struct sdhci_host *host)
 reset:
   sdhci_reset(host, SDHCI_RESET_ALL);
   free_irq(host-irq, host);
 + if (host-ops-disable_msi  enable_msi)
 + host-ops-disable_msi(host);
 #endif
 untasklet:
   tasklet_kill(host-card_tasklet);
 @@ -3114,6 +3132,9 @@ void sdhci_remove_host(struct sdhci_host *host, int 
 dead)

   free_irq(host-irq, host);

 + if (host-ops-disable_msi  enable_msi)
 + host-ops-disable_msi(host);
 +
   del_timer_sync(host-timer);

   tasklet_kill(host-card_tasklet);
 @@ -3162,6 +3183,7 @@ module_exit(sdhci_drv_exit);

 module_param(debug_quirks, uint, 0444);
 module_param(debug_quirks2, uint, 0444);
 +module_param(enable_msi, bool, 0444);

 MODULE_AUTHOR(Pierre Ossman pie...@ossman.eu);
 MODULE_DESCRIPTION(Secure Digital Host Controller 

Re: [PATCH 2/2] mmc: sd: Fix sd current limit setting

2012-07-18 Thread Aaron Lu
Hi Chris,

On Wed, Jul 18, 2012 at 01:28:40AM -0400, Chris Ball wrote:
 Hi Aaron,
 
 On Wed, Jul 18 2012, Aaron Lu wrote:
  Is the following patch OK? This is based on top of current mmc-next with
  the previous one in tree. Not sure if this is what you want though.
 
 Yes, that's perfect; squashed into the original patch and pushed out
 to mmc-next.  Thanks!
 
 Having there be so many MAX_CURRENT defines -- and having them be
 split in the middle between CAP_ and CAP2_ -- is starting to feel
 a bit awkward.

I agree.

 Does anyone have ideas on how that might be tidied up,
 since we have an opportunity to come up with a better plan
 before this gets merged soon?

What about we add three fields in mmc_host to store the max current
value for 3.3v/3.0v/1.8v and use that when needed instead of the cap
setting of the host?

I've prepared the following code, please check if this is better than
the current one:

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 312b78d..2232004 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -517,11 +517,36 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, 
u8 *status)
return 0;
 }
 
+/* Get host's max current setting at its current voltage */
+static u32 sd_get_host_max_current(struct mmc_host *host)
+{
+   u32 voltage, max_current;
+
+   voltage = 1  host-ios.vdd;
+   switch (voltage) {
+   case MMC_VDD_165_195:
+   max_current = host-max_current_180;
+   break;
+   case MMC_VDD_29_30:
+   case MMC_VDD_30_31:
+   max_current = host-max_current_300;
+   break;
+   case MMC_VDD_32_33:
+   case MMC_VDD_33_34:
+   max_current = host-max_current_330;
+   break;
+   default:
+   max_current = 0;
+   }
+
+   return max_current;
+}
+
 static int sd_set_current_limit(struct mmc_card *card, u8 *status)
 {
int current_limit = SD_SET_CURRENT_NO_CHANGE;
int err;
-   u32 voltage;
+   u32 max_current;
 
/*
 * Current limit switch is only defined for SDR50, SDR104, and DDR50
@@ -535,9 +560,9 @@ static int sd_set_current_limit(struct mmc_card *card, u8 
*status)
 
/*
 * Host has different current capabilities when operating at
-* different voltages, so find out the current voltage first.
+* different voltages, so find out its max current first.
 */
-   voltage = 1  card-host-ios.vdd;
+   max_current = sd_get_host_max_current(card-host);
 
/*
 * We only check host's capability here, if we set a limit that is
@@ -547,34 +572,15 @@ static int sd_set_current_limit(struct mmc_card *card, u8 
*status)
 * when we set current limit to 400/600/800ma, the card will draw its
 * maximum 300ma from the host.
 */
-   if (voltage == MMC_VDD_165_195) {
-   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_180)
-   current_limit = SD_SET_CURRENT_LIMIT_800;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_180)
-   current_limit = SD_SET_CURRENT_LIMIT_600;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_180)
-   current_limit = SD_SET_CURRENT_LIMIT_400;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_180)
-   current_limit = SD_SET_CURRENT_LIMIT_200;
-   } else if (voltage  (MMC_VDD_29_30 | MMC_VDD_30_31)) {
-   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_300)
-   current_limit = SD_SET_CURRENT_LIMIT_800;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_300)
-   current_limit = SD_SET_CURRENT_LIMIT_600;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_300)
-   current_limit = SD_SET_CURRENT_LIMIT_400;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_300)
-   current_limit = SD_SET_CURRENT_LIMIT_200;
-   } else if (voltage  (MMC_VDD_32_33 | MMC_VDD_33_34)) {
-   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_330)
-   current_limit = SD_SET_CURRENT_LIMIT_800;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_330)
-   current_limit = SD_SET_CURRENT_LIMIT_600;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_330)
-   current_limit = SD_SET_CURRENT_LIMIT_400;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_330)
-   current_limit = SD_SET_CURRENT_LIMIT_200;
-   }
+
+   if (max_current = 800)
+   current_limit = SD_SET_CURRENT_LIMIT_800;
+   else if (max_current = 600)
+   current_limit = SD_SET_CURRENT_LIMIT_600;
+   else if (max_current = 400)
+   current_limit = SD_SET_CURRENT_LIMIT_400;
+   else if (max_current = 200

Re: [PATCH 2/2] mmc: sd: Fix sd current limit setting

2012-07-17 Thread Aaron Lu
On Tue, Jul 17, 2012 at 03:04:05PM +0530, Girish K S wrote:
  @@ -261,6 +261,14 @@ struct mmc_host {
   #define MMC_CAP2_HC_ERASE_SZ   (1  9)/* High-capacity erase size 
  */
   #define MMC_CAP2_CD_ACTIVE_HIGH(1  10)   /* Card-detect 
  signal active high */
   #define MMC_CAP2_RO_ACTIVE_HIGH(1  11)   /* Write-protect 
  signal active high */
  +#define MMC_CAP_MAX_CURRENT_200_300 (1  12)  /* Host max current limit 
  is 200mA at 3.0V */
  +#define MMC_CAP_MAX_CURRENT_400_300 (1  13)  /* Host max current limit 
  is 400mA at 3.0V */
  +#define MMC_CAP_MAX_CURRENT_600_300 (1  14)  /* Host max current limit 
  is 600mA at 3.0V */
  +#define MMC_CAP_MAX_CURRENT_800_300 (1  15)  /* Host max current limit 
  is 800mA at 3.0V */
  +#define MMC_CAP_MAX_CURRENT_200_330 (1  16)  /* Host max current limit 
  is 200mA at 3.3V */
  +#define MMC_CAP_MAX_CURRENT_400_330 (1  17)  /* Host max current limit 
  is 400mA at 3.3V */
  +#define MMC_CAP_MAX_CURRENT_600_330 (1  18)  /* Host max current limit 
  is 600mA at 3.3V */
  +#define MMC_CAP_MAX_CURRENT_800_330 (1  19)  /* Host max current limit 
  is 800mA at 3.3V */
 sorry for seeing this late.
 The macro name should be **_CAP2_***.

Thanks for pointing this out, I'll be more careful next time.

 This is already merged in chris's mmc-next branch,
 Chris,
 Is it possible to change the macro name in the mmc-next branch for this patch?

Chris, please let me know how you want to deal with this and I'll be
glad to do whatever I can to fix this. Sorry for the trouble.

-Aaron
--
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


Re: [PATCH 2/2] mmc: sd: Fix sd current limit setting

2012-07-17 Thread Aaron Lu
Hi,

On Tue, Jul 17, 2012 at 11:43:26AM -0400, Chris Ball wrote:
 
  Chris, please let me know how you want to deal with this and I'll be
  glad to do whatever I can to fix this. Sorry for the trouble.
 
 No worries, I can rebase it in.  Mind sending a patch on top of current
 mmc-next for me to squash on top of the previous one?

Is the following patch OK? This is based on top of current mmc-next with
the previous one in tree. Not sure if this is what you want though.

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 312b78d..ec03d15 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -557,22 +557,22 @@ static int sd_set_current_limit(struct mmc_card *card, u8 
*status)
else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_180)
current_limit = SD_SET_CURRENT_LIMIT_200;
} else if (voltage  (MMC_VDD_29_30 | MMC_VDD_30_31)) {
-   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_300)
+   if (card-host-caps2  MMC_CAP2_MAX_CURRENT_800_300)
current_limit = SD_SET_CURRENT_LIMIT_800;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_300)
+   else if (card-host-caps2  MMC_CAP2_MAX_CURRENT_600_300)
current_limit = SD_SET_CURRENT_LIMIT_600;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_300)
+   else if (card-host-caps2  MMC_CAP2_MAX_CURRENT_400_300)
current_limit = SD_SET_CURRENT_LIMIT_400;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_300)
+   else if (card-host-caps2  MMC_CAP2_MAX_CURRENT_200_300)
current_limit = SD_SET_CURRENT_LIMIT_200;
} else if (voltage  (MMC_VDD_32_33 | MMC_VDD_33_34)) {
-   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_330)
+   if (card-host-caps2  MMC_CAP2_MAX_CURRENT_800_330)
current_limit = SD_SET_CURRENT_LIMIT_800;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_330)
+   else if (card-host-caps2  MMC_CAP2_MAX_CURRENT_600_330)
current_limit = SD_SET_CURRENT_LIMIT_600;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_330)
+   else if (card-host-caps2  MMC_CAP2_MAX_CURRENT_400_330)
current_limit = SD_SET_CURRENT_LIMIT_400;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_330)
+   else if (card-host-caps2  MMC_CAP2_MAX_CURRENT_200_330)
current_limit = SD_SET_CURRENT_LIMIT_200;
}
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 455a093..29d4357 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2920,13 +2920,13 @@ int sdhci_add_host(struct sdhci_host *host)
 
/* Maximum current capabilities of the host at 3.3V */
if (max_current_330 = 800)
-   mmc-caps |= MMC_CAP_MAX_CURRENT_800_330;
+   mmc-caps2 |= MMC_CAP2_MAX_CURRENT_800_330;
else if (max_current_330 = 600)
-   mmc-caps |= MMC_CAP_MAX_CURRENT_600_330;
+   mmc-caps2 |= MMC_CAP2_MAX_CURRENT_600_330;
else if (max_current_330 = 400)
-   mmc-caps |= MMC_CAP_MAX_CURRENT_400_330;
+   mmc-caps2 |= MMC_CAP2_MAX_CURRENT_400_330;
else if (max_current_330 = 200)
-   mmc-caps |= MMC_CAP_MAX_CURRENT_200_330;
+   mmc-caps2 |= MMC_CAP2_MAX_CURRENT_200_330;
}
if (caps[0]  SDHCI_CAN_VDD_300) {
int max_current_300;
@@ -2943,13 +2943,13 @@ int sdhci_add_host(struct sdhci_host *host)
 
/* Maximum current capabilities of the host at 3.0V */
if (max_current_300 = 800)
-   mmc-caps |= MMC_CAP_MAX_CURRENT_800_300;
+   mmc-caps2 |= MMC_CAP2_MAX_CURRENT_800_300;
else if (max_current_300 = 600)
-   mmc-caps |= MMC_CAP_MAX_CURRENT_600_300;
+   mmc-caps2 |= MMC_CAP2_MAX_CURRENT_600_300;
else if (max_current_300 = 400)
-   mmc-caps |= MMC_CAP_MAX_CURRENT_400_300;
+   mmc-caps2 |= MMC_CAP2_MAX_CURRENT_400_300;
else if (max_current_300 = 200)
-   mmc-caps |= MMC_CAP_MAX_CURRENT_200_300;
+   mmc-caps2 |= MMC_CAP2_MAX_CURRENT_200_300;
}
if (caps[0]  SDHCI_CAN_VDD_180) {
int max_current_180;
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 79d8921..4a40312 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -261,14 +261,14 @@ struct mmc_host {
 #define MMC_CAP2_HC_ERASE_SZ   (1  9)/* High-capacity erase size */
 #define MMC_CAP2_CD_ACTIVE_HIGH(1  10)   

[PATCH] mmc: core: reset sigal voltage on power up

2012-07-10 Thread Aaron Lu
Add a call to mmc_set_signal_voltage to set signal voltage to 3.3v in
mmc_power_up so that we do not need to touch signal voltage setting in
mmc/sd/sdio init functions and rescan function.

For mmc/sd cards, when doing a suspend/resume cycle, consider the unsafe
resume case, the card will lose its power and when powered on again, we
will set signal voltage to 3.3v in mmc_power_up before its resume function
gets called, which will re-init the card.

And for sdio cards, when doing a suspend/resume cycle, consider the unsafe
resume case, the card will either lose its power or not depending on if it
wants to wakeup the host. If power is not maintained, it is the same case as
mmc/sd cards. If power is maintained, mmc_power_up will not be called and
the card's signal voltage will remain at the last setting.

Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/core/core.c | 6 +++---
 drivers/mmc/core/mmc.c  | 3 ---
 drivers/mmc/core/sd.c   | 3 ---
 drivers/mmc/core/sdio.c | 7 ---
 4 files changed, 3 insertions(+), 16 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9503cab..8ac5246 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1212,6 +1212,9 @@ static void mmc_power_up(struct mmc_host *host)
host-ios.timing = MMC_TIMING_LEGACY;
mmc_set_ios(host);
 
+   /* Set signal voltage to 3.3V */
+   mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, false);
+
/*
 * This delay should be sufficient to allow the power supply
 * to reach the minimum voltage.
@@ -1963,9 +1966,6 @@ static int mmc_rescan_try_freq(struct mmc_host *host, 
unsigned freq)
 */
mmc_hw_reset_for_init(host);
 
-   /* Initialization should be done at 3.3 V I/O voltage. */
-   mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
/*
 * sdio_reset sends CMD52 to reset card.  Since we do not know
 * if the card is being re-initialized, just send it.  CMD52
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 4f4489a..396b258 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -818,9 +818,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
if (!mmc_host_is_spi(host))
mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
 
-   /* Initialization should be done at 3.3 V I/O voltage. */
-   mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
/*
 * Since we're changing the OCR value, we seem to
 * need to tell some cards to go back to the idle
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 312b78d..2182d92 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -892,9 +892,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
BUG_ON(!host);
WARN_ON(!host-claimed);
 
-   /* The initialization should be done at 3.3 V I/O voltage. */
-   mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
err = mmc_sd_get_cid(host, ocr, cid, rocr);
if (err)
return err;
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 41c5fd8..d4619e2 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -591,9 +591,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 
ocr,
 * Inform the card of the voltage
 */
if (!powered_resume) {
-   /* The initialization should be done at 3.3 V I/O voltage. */
-   mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
err = mmc_send_io_op_cond(host, host-ocr, ocr);
if (err)
goto err;
@@ -1006,10 +1003,6 @@ static int mmc_sdio_power_restore(struct mmc_host *host)
 * restore the correct voltage setting of the card.
 */
 
-   /* The initialization should be done at 3.3 V I/O voltage. */
-   if (!mmc_card_keep_power(host))
-   mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
sdio_reset(host);
mmc_go_idle(host);
mmc_send_if_cond(host, host-ocr_avail);
-- 
1.7.11.1.3.g4c8a9db


--
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


Re: [PATCH] mmc: host: sdhci. UHS Switch failure - cycle power if regulator is used

2012-07-09 Thread Aaron Lu

On 06/28/2012 12:15 AM, philipspatc...@gmail.com wrote:

From: Philip Rakityprak...@marvell.com

Power needs to be removed from the card when switching to 1.8v fails.

If a regulator is used to control vmmc we need to turn the
regulator off and then back on otherwise power will not be removed
from the card.


Reviewed-by: Aaron Lu aaron...@amd.com

-Aaron



Signed-off-by: Philip Rakityprak...@marvell.com
---
  drivers/mmc/host/sdhci.c |4 
  1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index f4b8b4d..ef4231a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1663,11 +1663,15 @@ static int sdhci_do_start_signal_voltage_switch(struct 
sdhci_host *host,
pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
pwr= ~SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+   if (host-vmmc)
+   regulator_disable(host-vmmc);

/* Wait for 1ms as per the spec */
usleep_range(1000, 1500);
pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+   if (host-vmmc)
+   regulator_enable(host-vmmc);

pr_info(DRIVER_NAME : Switching to 1.8V signalling 
voltage failed, retrying with S18R set to 0\n);



--
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


Re: [PATCH 2/2] mmc: only support voltage (vdd) that regulator agree's with

2012-07-03 Thread Aaron Lu
Hi Chris,

On Fri, Jun 29, 2012 at 07:19:19PM -0400, Chris Ball wrote:
 Hi,
 
 On Fri, Jun 08 2012, philipspatc...@gmail.com wrote:
  From: Philip Rakity prak...@marvell.com
 
  If we are using a regulator the SD Host Controller and the
  regulator should agree about the voltages supported.  Use
  the common subset that is supported.
 
  Signed-off-by: Philip Rakity prak...@marvell.com
 
 This breaks the build when CONFIG_REGULATOR=n -- I've applied what looks
 like the correct fix to me:
 
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index eae7c3c..caba999 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2832,51 +2832,53 @@ int sdhci_add_host(struct sdhci_host *host)
 +#ifdef CONFIG_REGULATOR
   /*
* According to SD Host Controller spec v3.00, if the Host System
* can afford more than 150mA, Host Driver should set XPC to 1. Also
* the value is meaningful only if Voltage Support in the Capabilities
* register is set. The actual current value is 4 times the register
* value.
*/
The above comments does not belong to regulator code, it should be
placed on top of the max_current_caps variable like this:

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index caba999..f76736b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2845,13 +2845,6 @@ int sdhci_add_host(struct sdhci_host *host)
}
 
 #ifdef CONFIG_REGULATOR
-   /*
-* According to SD Host Controller spec v3.00, if the Host System
-* can afford more than 150mA, Host Driver should set XPC to 1. Also
-* the value is meaningful only if Voltage Support in the Capabilities
-* register is set. The actual current value is 4 times the register
-* value.
-*/
if (host-vmmc) {
ret = regulator_is_supported_voltage(host-vmmc, 330,
330);
@@ -2868,6 +2861,13 @@ int sdhci_add_host(struct sdhci_host *host)
}
 #endif /* CONFIG_REGULATOR */
 
+   /*
+* According to SD Host Controller spec v3.00, if the Host System
+* can afford more than 150mA, Host Driver should set XPC to 1. Also
+* the value is meaningful only if Voltage Support in the Capabilities
+* register is set. The actual current value is 4 times the register
+* value.
+*/
max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
if (!max_current_caps  host-vmmc) {
u32 curr = regulator_get_current_limit(host-vmmc);

Thanks,
Aaron

   if (host-vmmc) {
   ret = regulator_is_supported_voltage(host-vmmc, 330,
   330);
   if ((ret = 0) || (!(caps[0]  SDHCI_CAN_VDD_330)))
   caps[0] = ~SDHCI_CAN_VDD_330;
   ret = regulator_is_supported_voltage(host-vmmc, 300,
   300);
   if ((ret = 0) || (!(caps[0]  SDHCI_CAN_VDD_300)))
   caps[0] = ~SDHCI_CAN_VDD_300;
   ret = regulator_is_supported_voltage(host-vmmc, 180,
   180);
   if ((ret = 0) || (!(caps[0]  SDHCI_CAN_VDD_180)))
   caps[0] = ~SDHCI_CAN_VDD_180;
   }
 +#endif /* CONFIG_REGULATOR */
 
 -- 
 Chris Ball   c...@laptop.org   http://printf.net/
 One Laptop Per Child
 

--
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


[PATCH 0/2] SD current limit setting fix

2012-07-03 Thread Aaron Lu
The following 2 patches fix setting of SD current limit

Aaron Lu (2):
  mmc: core: Simplify and fix for SD switch processing
  mmc: sd: Fix sd current limit setting

 drivers/mmc/core/sd.c| 144 +++
 drivers/mmc/host/sdhci.c |  28 +++--
 include/linux/mmc/host.h |  16 --
 3 files changed, 105 insertions(+), 83 deletions(-)

-- 
1.7.11.1.3.g4c8a9db


--
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


[PATCH 1/2] mmc: core: Simplify and fix for SD switch processing

2012-07-03 Thread Aaron Lu
In mmc_read_switch, just do a one time mode 0 switch command to get the
support bits information, no need to do multiple times as the support
bits do not change with different arguments.

And no need to check current limit support bits, as these bits is
fixed according to the signal voltage. If the signal voltage is 1.8V,
the support bits would be 0xf and if the signal voltage is 3.3V, the
support bits would be 0x01. We will check host's ability to set the
current limit.

Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/core/sd.c | 94 ---
 1 file changed, 22 insertions(+), 72 deletions(-)

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index b0b9e37..ae72d6e 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -290,8 +290,12 @@ static int mmc_read_switch(struct mmc_card *card)
return -ENOMEM;
}
 
-   /* Find out the supported Bus Speed Modes. */
-   err = mmc_sd_switch(card, 0, 0, 1, status);
+   /*
+* Find out the card's support bits with a mode 0 operation.
+* The argument does not matter, as the support bits do not
+* change with the arguments.
+*/
+   err = mmc_sd_switch(card, 0, 0, 0, status);
if (err) {
/*
 * If the host or the card can't do the switch,
@@ -312,46 +316,8 @@ static int mmc_read_switch(struct mmc_card *card)
 
if (card-scr.sda_spec3) {
card-sw_caps.sd3_bus_mode = status[13];
-
-   /* Find out Driver Strengths supported by the card */
-   err = mmc_sd_switch(card, 0, 2, 1, status);
-   if (err) {
-   /*
-* If the host or the card can't do the switch,
-* fail more gracefully.
-*/
-   if (err != -EINVAL  err != -ENOSYS  err != -EFAULT)
-   goto out;
-
-   pr_warning(%s: problem reading 
-   Driver Strength.\n,
-   mmc_hostname(card-host));
-   err = 0;
-
-   goto out;
-   }
-
+   /* Driver Strengths supported by the card */
card-sw_caps.sd3_drv_type = status[9];
-
-   /* Find out Current Limits supported by the card */
-   err = mmc_sd_switch(card, 0, 3, 1, status);
-   if (err) {
-   /*
-* If the host or the card can't do the switch,
-* fail more gracefully.
-*/
-   if (err != -EINVAL  err != -ENOSYS  err != -EFAULT)
-   goto out;
-
-   pr_warning(%s: problem reading 
-   Current Limit.\n,
-   mmc_hostname(card-host));
-   err = 0;
-
-   goto out;
-   }
-
-   card-sw_caps.sd3_curr_limit = status[7];
}
 
 out:
@@ -560,41 +526,24 @@ static int sd_set_current_limit(struct mmc_card *card, u8 
*status)
 * Current limit switch is only defined for SDR50, SDR104, and DDR50
 * bus speed modes. For other bus speed modes, we do not change the
 * current limit.
+* We only check host's capability here, if we set a limit that is
+* higher than the card's maximum current, the card will be using its
+* maximum current, e.g. if the card's maximum current is 300ma, and
+* when we set current limit to 200ma, the card will draw 200ma, and
+* when we set current limit to 400/600/800ma, the card will draw its
+* maximum 300ma from the host.
 */
if ((card-sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
(card-sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
(card-sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
-   if (card-host-caps  MMC_CAP_MAX_CURRENT_800) {
-   if (card-sw_caps.sd3_curr_limit  SD_MAX_CURRENT_800)
-   current_limit = SD_SET_CURRENT_LIMIT_800;
-   else if (card-sw_caps.sd3_curr_limit 
-   SD_MAX_CURRENT_600)
-   current_limit = SD_SET_CURRENT_LIMIT_600;
-   else if (card-sw_caps.sd3_curr_limit 
-   SD_MAX_CURRENT_400)
-   current_limit = SD_SET_CURRENT_LIMIT_400;
-   else if (card-sw_caps.sd3_curr_limit 
-   SD_MAX_CURRENT_200)
-   current_limit = SD_SET_CURRENT_LIMIT_200;
-   } else if (card-host-caps  MMC_CAP_MAX_CURRENT_600) {
-   if (card-sw_caps.sd3_curr_limit  SD_MAX_CURRENT_600

[PATCH 2/2] mmc: sd: Fix sd current limit setting

2012-07-03 Thread Aaron Lu
Host has different current capabilities at different voltages, we need
to record these settings seperately. Before set current limit for the sd
card, find out the current voltage first and then find out the current
capabilities of the host to set the limit.

Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/core/sd.c| 58 ++--
 drivers/mmc/host/sdhci.c | 28 +++
 include/linux/mmc/host.h | 16 +
 3 files changed, 87 insertions(+), 15 deletions(-)

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ae72d6e..4b4cf4d 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -521,11 +521,39 @@ static int sd_set_current_limit(struct mmc_card *card, u8 
*status)
 {
int current_limit = SD_SET_CURRENT_NO_CHANGE;
int err;
+   u8 voltage;
 
/*
 * Current limit switch is only defined for SDR50, SDR104, and DDR50
 * bus speed modes. For other bus speed modes, we do not change the
 * current limit.
+*/
+   if ((card-sd_bus_speed != UHS_SDR50_BUS_SPEED) 
+   (card-sd_bus_speed != UHS_SDR104_BUS_SPEED) 
+   (card-sd_bus_speed != UHS_DDR50_BUS_SPEED))
+   return 0;
+
+   /*
+* Host has different current capabilities when operating at
+* different voltages, so find out the current voltage first.
+*/
+   switch (1  card-host-ios.vdd) {
+   case MMC_VDD_165_195:
+   voltage = 0; /* host's voltage is 1.8V */
+   break;
+   case MMC_VDD_29_30:
+   case MMC_VDD_30_31:
+   voltage = 1; /* host's voltage is 3.0V */
+   break;
+   case MMC_VDD_32_33:
+   case MMC_VDD_33_34:
+   voltage = 2; /* host's voltage is 3.3V */
+   break;
+   default:
+   BUG(); /* host's voltage is invalid */
+   }
+
+   /*
 * We only check host's capability here, if we set a limit that is
 * higher than the card's maximum current, the card will be using its
 * maximum current, e.g. if the card's maximum current is 300ma, and
@@ -533,16 +561,32 @@ static int sd_set_current_limit(struct mmc_card *card, u8 
*status)
 * when we set current limit to 400/600/800ma, the card will draw its
 * maximum 300ma from the host.
 */
-   if ((card-sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
-   (card-sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
-   (card-sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
-   if (card-host-caps  MMC_CAP_MAX_CURRENT_800)
+   if (voltage == 0) {
+   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_180)
+   current_limit = SD_SET_CURRENT_LIMIT_800;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_180)
+   current_limit = SD_SET_CURRENT_LIMIT_600;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_180)
+   current_limit = SD_SET_CURRENT_LIMIT_400;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_180)
+   current_limit = SD_SET_CURRENT_LIMIT_200;
+   } else if (voltage == 1) {
+   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_300)
+   current_limit = SD_SET_CURRENT_LIMIT_800;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_300)
+   current_limit = SD_SET_CURRENT_LIMIT_600;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_300)
+   current_limit = SD_SET_CURRENT_LIMIT_400;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_300)
+   current_limit = SD_SET_CURRENT_LIMIT_200;
+   } else if (voltage == 2) {
+   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_330)
current_limit = SD_SET_CURRENT_LIMIT_800;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600)
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_330)
current_limit = SD_SET_CURRENT_LIMIT_600;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400)
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_330)
current_limit = SD_SET_CURRENT_LIMIT_400;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200)
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_330)
current_limit = SD_SET_CURRENT_LIMIT_200;
}
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index caba999..00c2cbb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2897,6 +2897,16 @@ int sdhci_add_host(struct sdhci_host *host)
 
if (max_current_330  150)
mmc-caps |= MMC_CAP_SET_XPC_330

[PATCH v2] mmc: sdhci: fix incorrect command used in tuning

2012-07-03 Thread Aaron Lu
V2:
Fix for SDIO case: both SD and SDIO cards use cmd19 while eMMC use cmd21.

V1:
For SD hosts using retuning mode 1, when retuning timer expired, it will
need to do retuning in sdhci_request before processing the actual
request. But the retuning command is fixed: cmd19 for SD card and cmd21
for eMMC card, so we can't use the original request's command to do the
tuning.

And since the tuning command depends on the card type atteched to the
host, we will need to know the card type to use the correct tuning
command.

Cc: stable sta...@vger.kernel.org [3.3+]
Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/host/sdhci.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index f76736b..4e53e6b 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -27,6 +27,7 @@
 
 #include linux/mmc/mmc.h
 #include linux/mmc/host.h
+#include linux/mmc/card.h
 
 #include sdhci.h
 
@@ -1245,6 +1246,7 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
struct sdhci_host *host;
bool present;
unsigned long flags;
+   u32 tuning_opcode;
 
host = mmc_priv(mmc);
 
@@ -1292,8 +1294,12 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
 */
if ((host-flags  SDHCI_NEEDS_RETUNING) 
!(present_state  (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
+   /* eMMC uses cmd21 while sd and sdio use cmd19 */
+   tuning_opcode = mmc-card-type == MMC_TYPE_MMC ?
+   MMC_SEND_TUNING_BLOCK_HS200 :
+   MMC_SEND_TUNING_BLOCK;
spin_unlock_irqrestore(host-lock, flags);
-   sdhci_execute_tuning(mmc, mrq-cmd-opcode);
+   sdhci_execute_tuning(mmc, tuning_opcode);
spin_lock_irqsave(host-lock, flags);
 
/* Restore original mmc_request structure */
-- 
1.7.11.1.3.g4c8a9db


--
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


Re: [PATCH v2] mmc: sdhci: fix incorrect command used in tuning

2012-07-03 Thread Aaron Lu
Hi,

On Tue, Jul 03, 2012 at 03:28:28PM +0530, Girish K S wrote:
 On 3 July 2012 14:57, Aaron Lu aaron...@amd.com wrote:
  V2:
  Fix for SDIO case: both SD and SDIO cards use cmd19 while eMMC use cmd21.
 
  V1:
  For SD hosts using retuning mode 1, when retuning timer expired, it will
  need to do retuning in sdhci_request before processing the actual
  request. But the retuning command is fixed: cmd19 for SD card and cmd21
  for eMMC card, so we can't use the original request's command to do the
  tuning.
 
  And since the tuning command depends on the card type atteched to the
  host, we will need to know the card type to use the correct tuning
  command.
 
  Cc: stable sta...@vger.kernel.org [3.3+]
  Signed-off-by: Aaron Lu aaron...@amd.com
  ---
   drivers/mmc/host/sdhci.c | 8 +++-
   1 file changed, 7 insertions(+), 1 deletion(-)
 
  diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
  index f76736b..4e53e6b 100644
  --- a/drivers/mmc/host/sdhci.c
  +++ b/drivers/mmc/host/sdhci.c
  @@ -27,6 +27,7 @@
 
   #include linux/mmc/mmc.h
   #include linux/mmc/host.h
  +#include linux/mmc/card.h
 
   #include sdhci.h
 
  @@ -1245,6 +1246,7 @@ static void sdhci_request(struct mmc_host *mmc, 
  struct mmc_request *mrq)
          struct sdhci_host *host;
          bool present;
          unsigned long flags;
  +       u32 tuning_opcode;
 
          host = mmc_priv(mmc);
 
  @@ -1292,8 +1294,12 @@ static void sdhci_request(struct mmc_host *mmc, 
  struct mmc_request *mrq)
                   */
                  if ((host-flags  SDHCI_NEEDS_RETUNING) 
                      !(present_state  (SDHCI_DOING_WRITE | 
  SDHCI_DOING_READ))) {
  +                       /* eMMC uses cmd21 while sd and sdio use cmd19 */
  +                       tuning_opcode = mmc-card-type == MMC_TYPE_MMC ?
  +                               MMC_SEND_TUNING_BLOCK_HS200 :
  +                               MMC_SEND_TUNING_BLOCK;
                          spin_unlock_irqrestore(host-lock, flags);
  -                       sdhci_execute_tuning(mmc, mrq-cmd-opcode);
  +                       sdhci_execute_tuning(mmc, tuning_opcode);
 dont you think the previous implementation does the same. It is
 already handled by introducing the 2nd parameter.

Suppose the following scenario:
mmc_start_request (e.g. mrq-cmd-opcode is 18 for this call)
  - host-ops-request
  (sdhci's retuning timer expired, the flag SDHCI_NEEDS_RETUNING is set)
- sdhci_request
  - sdhci_execute_tuning will be called before processing the
actual request due to retuning's requirement, but with the wrong command
opcode(cmd18) instead of cmd19 for sd/sdio or cmd21 for emmc.

The problem is with retuning, for normal explicit calls of
sdhci_execute_tuning, there is no problem with the code. But when
retuning is required, sdhci_execute_retuning will be executed implicitly
to the above layer and we have to use the right tuning command instead of
the current processing command, which can be any of the valid sd/sdio/mmc
commands.

-Aaron

                          spin_lock_irqsave(host-lock, flags);
 
                          /* Restore original mmc_request structure */
  --
  1.7.11.1.3.g4c8a9db
 
 
--
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


Re: [PATCH v2] mmc: sdhci: fix incorrect command used in tuning

2012-07-03 Thread Aaron Lu
Hi,

On Tue, Jul 03, 2012 at 05:32:36PM +0530, Girish K S wrote:
   @@ -1292,8 +1294,12 @@ static void sdhci_request(struct mmc_host *mmc, 
   struct mmc_request *mrq)
                    */
                   if ((host-flags  SDHCI_NEEDS_RETUNING) 
                       !(present_state  (SDHCI_DOING_WRITE | 
   SDHCI_DOING_READ))) {
   +                       /* eMMC uses cmd21 while sd and sdio use cmd19 
   */
   +                       tuning_opcode = mmc-card-type == MMC_TYPE_MMC 
   ?
   +                               MMC_SEND_TUNING_BLOCK_HS200 :
   +                               MMC_SEND_TUNING_BLOCK;
                           spin_unlock_irqrestore(host-lock, flags);
   -                       sdhci_execute_tuning(mmc, mrq-cmd-opcode);
   +                       sdhci_execute_tuning(mmc, tuning_opcode);
  dont you think the previous implementation does the same. It is
  already handled by introducing the 2nd parameter.
 
  Suppose the following scenario:
  mmc_start_request (e.g. mrq-cmd-opcode is 18 for this call)
    - host-ops-request
    (sdhci's retuning timer expired, the flag SDHCI_NEEDS_RETUNING is set)
      - sdhci_request
        - sdhci_execute_tuning will be called before processing the
  actual request due to retuning's requirement, but with the wrong command
  opcode(cmd18) instead of cmd19 for sd/sdio or cmd21 for emmc.
 
  The problem is with retuning, for normal explicit calls of
  sdhci_execute_tuning, there is no problem with the code. But when
  retuning is required, sdhci_execute_retuning will be executed implicitly
  to the above layer and we have to use the right tuning command instead of
  the current processing command, which can be any of the valid sd/sdio/mmc
  commands.
  Thanks for the explanation. is it possible to make a separate local
  function for this. Since mmc_host_ops has a member .execute_tuning
  which takes 2 parameters that are called from respective sd/mmc/sdio
  card files. there might be conflict
 Sorry i just read it wrongly (function has only 1 param).

So do you have any other problems with this patch?
If not, can I have your ack on this patch?

Thanks,
Aaron

--
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


Re: [PATCH v2] mmc: sdhci: fix incorrect command used in tuning

2012-07-03 Thread Aaron Lu
Hi Chris,

On Tue, Jul 03, 2012 at 08:37:33PM -0400, Chris Ball wrote:
 Hi,
 
 On Tue, Jul 03 2012, Aaron Lu wrote:
  V2:
  Fix for SDIO case: both SD and SDIO cards use cmd19 while eMMC use cmd21.
 
  V1:
  For SD hosts using retuning mode 1, when retuning timer expired, it will
  need to do retuning in sdhci_request before processing the actual
  request. But the retuning command is fixed: cmd19 for SD card and cmd21
  for eMMC card, so we can't use the original request's command to do the
  tuning.
 
  And since the tuning command depends on the card type atteched to the
  host, we will need to know the card type to use the correct tuning
  command.
 
  Cc: stable sta...@vger.kernel.org [3.3+]
  Signed-off-by: Aaron Lu aaron...@amd.com
  ---
 
 Thanks, pushed to mmc-next for 3.6 with Philip's Reviewed-by.
 
 For next time, please put the patch changelog at this point in the patch
 (after ---) so that it doesn't show up in the recorded commit message.
 
 Also, please don't e-mail the patch to stable@ before it has entered
 mainline.  They'll pick it up from the CC in the commit message when
 Linus merges it, they don't want a copy of the patch before then.

OK, thanks for pointing this out, will follow this in the future.

-Aaron

 
 Thanks!
 
 - Chris.
 -- 
 Chris Ball   c...@laptop.org   http://printf.net/
 One Laptop Per Child
 --
 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


[PATCH v3 2/2] mmc: sdhci: A new flag SDHCI_USING_RETUNING_TIMER

2012-07-03 Thread Aaron Lu
Add a new flag of SDHCI_USING_RETUNING_TIMER to represent if the host
is using a retuning timer for the card inserted.

This flag is set when the host does tuning the first time for the card
and the host's retuning mode is 1. This flag is used afterwards whenever
needs to decide if the host is currently using a retuning timer.

This flag is cleared when the card is removed in sdhci_reinit.

The set/clear of the flag and the start/stop of the retuning timer is
associated with the card's init/remove time, so there is no need to
touch it when the host is to be removed as at that time the card should
have already been removed.

Signed-off-by: Aaron Lu aaron...@amd.com
---
v3:
Change the macro name from SDHCI_NEEDS_RETUNING_TIMER to
SDHCI_USING_RETUNING_TIMER for better description of the flag as suggested
by Chris Ball.

v2:
v1 mistakenly removed the line del_timer_sync(host-timer) in
sdhci_remove_host, fix this by adding back the code.

 drivers/mmc/host/sdhci.c  | 30 --
 include/linux/mmc/sdhci.h |  1 +
 2 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b0a5629..3ec4182 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -250,8 +250,9 @@ static void sdhci_reinit(struct sdhci_host *host)
 * applicable to UHS-I cards. So reset these fields to their initial
 * value when card is removed.
 */
-   if (host-version = SDHCI_SPEC_300  host-tuning_count 
-   host-tuning_mode == SDHCI_TUNING_MODE_1) {
+   if (host-flags  SDHCI_USING_RETUNING_TIMER) {
+   host-flags = ~SDHCI_USING_RETUNING_TIMER;
+
del_timer_sync(host-tuning_timer);
host-flags = ~SDHCI_NEEDS_RETUNING;
host-mmc-max_blk_count =
@@ -1873,6 +1874,7 @@ out:
 */
if (!(host-flags  SDHCI_NEEDS_RETUNING)  host-tuning_count 
(host-tuning_mode == SDHCI_TUNING_MODE_1)) {
+   host-flags |= SDHCI_USING_RETUNING_TIMER;
mod_timer(host-tuning_timer, jiffies +
host-tuning_count * HZ);
/* Tuning mode 1 limits the maximum data length to 4MB */
@@ -1890,10 +1892,10 @@ out:
 * try tuning again at a later time, when the re-tuning timer expires.
 * So for these controllers, we return 0. Since there might be other
 * controllers who do not have this capability, we return error for
-* them.
+* them. SDHCI_USING_RETUNING_TIMER means the host is currently using
+* a retuning timer to do the retuning for the card.
 */
-   if (err  host-tuning_count 
-   host-tuning_mode == SDHCI_TUNING_MODE_1)
+   if (err  (host-flags  SDHCI_USING_RETUNING_TIMER))
err = 0;
 
sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
@@ -2400,7 +2402,6 @@ out:
 int sdhci_suspend_host(struct sdhci_host *host)
 {
int ret;
-   bool has_tuning_timer;
 
if (host-ops-platform_suspend)
host-ops-platform_suspend(host);
@@ -2408,16 +2409,14 @@ int sdhci_suspend_host(struct sdhci_host *host)
sdhci_disable_card_detection(host);
 
/* Disable tuning since we are suspending */
-   has_tuning_timer = host-version = SDHCI_SPEC_300 
-   host-tuning_count  host-tuning_mode == SDHCI_TUNING_MODE_1;
-   if (has_tuning_timer) {
+   if (host-flags  SDHCI_USING_RETUNING_TIMER) {
del_timer_sync(host-tuning_timer);
host-flags = ~SDHCI_NEEDS_RETUNING;
}
 
ret = mmc_suspend_host(host-mmc);
if (ret) {
-   if (has_tuning_timer) {
+   if (host-flags  SDHCI_USING_RETUNING_TIMER) {
host-flags |= SDHCI_NEEDS_RETUNING;
mod_timer(host-tuning_timer, jiffies +
host-tuning_count * HZ);
@@ -2468,8 +2467,7 @@ int sdhci_resume_host(struct sdhci_host *host)
host-ops-platform_resume(host);
 
/* Set the re-tuning expiration flag */
-   if ((host-version = SDHCI_SPEC_300)  host-tuning_count 
-   (host-tuning_mode == SDHCI_TUNING_MODE_1))
+   if (host-flags  SDHCI_USING_RETUNING_TIMER)
host-flags |= SDHCI_NEEDS_RETUNING;
 
return ret;
@@ -2508,8 +2506,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
int ret = 0;
 
/* Disable tuning since we are suspending */
-   if (host-version = SDHCI_SPEC_300 
-   host-tuning_mode == SDHCI_TUNING_MODE_1) {
+   if (host-flags  SDHCI_USING_RETUNING_TIMER) {
del_timer_sync(host-tuning_timer);
host-flags = ~SDHCI_NEEDS_RETUNING;
}
@@ -2550,8 +2547,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
sdhci_do_enable_preset_value(host, true);
 
/* Set the re-tuning expiration flag

[PATCH v2 2/2] mmc: sd: Fix sd current limit setting

2012-07-03 Thread Aaron Lu
Host has different current capabilities at different voltages, we need
to record these settings seperately. The defined voltages are 1.8/3.0/3.3.
For other voltages, we do not touch current limit setting.

Before set current limit for the sd card, find out the host's operating
voltage first and then find out the current capabilities of the host at
that voltage to set the current limit.

Signed-off-by: Aaron Lu aaron...@amd.com
---
v2:
Do not call BUG() when the host's voltage is not supported as suggested by
Chris Ball.
Do not use 0/1/2 to represent the host's voltage as suggested by Philip Rakity.

 drivers/mmc/core/sd.c| 44 +---
 drivers/mmc/host/sdhci.c | 28 
 include/linux/mmc/host.h | 16 
 3 files changed, 73 insertions(+), 15 deletions(-)

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 8460568..312b78d 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -521,11 +521,25 @@ static int sd_set_current_limit(struct mmc_card *card, u8 
*status)
 {
int current_limit = SD_SET_CURRENT_NO_CHANGE;
int err;
+   u32 voltage;
 
/*
 * Current limit switch is only defined for SDR50, SDR104, and DDR50
 * bus speed modes. For other bus speed modes, we do not change the
 * current limit.
+*/
+   if ((card-sd_bus_speed != UHS_SDR50_BUS_SPEED) 
+   (card-sd_bus_speed != UHS_SDR104_BUS_SPEED) 
+   (card-sd_bus_speed != UHS_DDR50_BUS_SPEED))
+   return 0;
+
+   /*
+* Host has different current capabilities when operating at
+* different voltages, so find out the current voltage first.
+*/
+   voltage = 1  card-host-ios.vdd;
+
+   /*
 * We only check host's capability here, if we set a limit that is
 * higher than the card's maximum current, the card will be using its
 * maximum current, e.g. if the card's maximum current is 300ma, and
@@ -533,16 +547,32 @@ static int sd_set_current_limit(struct mmc_card *card, u8 
*status)
 * when we set current limit to 400/600/800ma, the card will draw its
 * maximum 300ma from the host.
 */
-   if ((card-sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
-   (card-sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
-   (card-sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
-   if (card-host-caps  MMC_CAP_MAX_CURRENT_800)
+   if (voltage == MMC_VDD_165_195) {
+   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_180)
+   current_limit = SD_SET_CURRENT_LIMIT_800;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_180)
+   current_limit = SD_SET_CURRENT_LIMIT_600;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_180)
+   current_limit = SD_SET_CURRENT_LIMIT_400;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_180)
+   current_limit = SD_SET_CURRENT_LIMIT_200;
+   } else if (voltage  (MMC_VDD_29_30 | MMC_VDD_30_31)) {
+   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_300)
+   current_limit = SD_SET_CURRENT_LIMIT_800;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_300)
+   current_limit = SD_SET_CURRENT_LIMIT_600;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_300)
+   current_limit = SD_SET_CURRENT_LIMIT_400;
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_300)
+   current_limit = SD_SET_CURRENT_LIMIT_200;
+   } else if (voltage  (MMC_VDD_32_33 | MMC_VDD_33_34)) {
+   if (card-host-caps  MMC_CAP_MAX_CURRENT_800_330)
current_limit = SD_SET_CURRENT_LIMIT_800;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600)
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_600_330)
current_limit = SD_SET_CURRENT_LIMIT_600;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400)
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_400_330)
current_limit = SD_SET_CURRENT_LIMIT_400;
-   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200)
+   else if (card-host-caps  MMC_CAP_MAX_CURRENT_200_330)
current_limit = SD_SET_CURRENT_LIMIT_200;
}
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 3ec4182..d89e97c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2913,6 +2913,16 @@ int sdhci_add_host(struct sdhci_host *host)
 
if (max_current_330  150)
mmc-caps |= MMC_CAP_SET_XPC_330;
+
+   /* Maximum current capabilities of the host at 3.3V */
+   if (max_current_330 = 800)
+   mmc-caps |= MMC_CAP_MAX_CURRENT_800_330;
+   else

[PATCH 0/2] Fixes for tuning stuffs

2012-06-29 Thread Aaron Lu
The following 2 patches fixed a bug related the tuning stuffs and
refactored the code to make it simpler and easier to read and understand.

Aaron Lu (2):
  mmc: sdhci: restore host settings when card is removed
  mmc: sdhci: A new flag SDHCI_NEEDS_RETUNING_TIMER

 drivers/mmc/host/sdhci.c  | 39 +--
 include/linux/mmc/sdhci.h |  1 +
 2 files changed, 22 insertions(+), 18 deletions(-)

-- 
1.7.11.1.3.g4c8a9db


--
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


[PATCH 1/2] mmc: sdhci: restore host settings when card is removed

2012-06-29 Thread Aaron Lu
Some of the host settings are affected by different cards inserted, e.g.
when an UHS-I card is inserted, the SDHCI_NEEDS_RETUING flag might be
set when the tuning timer expired and host's max_blk_count will be
reduced to make sure the data transfer for a command does not exceed 4MiB
to meet the retuning mode 1's requirement.

When the card is removed, we should restore the original setting of the
host since we can't be sure the next card being inserted will still be
an UHS-I card that needs tuning. The original setting include its
max_blk_count and no set of the flag of SDHCI_NEEDS_RETUNING.

Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/host/sdhci.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index ff522ec..7e182ad 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -245,6 +245,18 @@ static void sdhci_init(struct sdhci_host *host, int soft)
 static void sdhci_reinit(struct sdhci_host *host)
 {
sdhci_init(host, 0);
+   /*
+* Retuning stuffs are affected by different cards inserted and only
+* applicable to UHS-I cards. So reset these fields to their initial
+* value when card is removed.
+*/
+   if (host-version = SDHCI_SPEC_300  host-tuning_count 
+   host-tuning_mode == SDHCI_TUNING_MODE_1) {
+   del_timer_sync(host-tuning_timer);
+   host-flags = ~SDHCI_NEEDS_RETUNING;
+   host-mmc-max_blk_count =
+   (host-quirks  SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
+   }
sdhci_enable_card_detection(host);
 }
 
-- 
1.7.11.1.3.g4c8a9db


--
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


[PATCH 2/2] mmc: sdhci: A new flag SDHCI_NEEDS_RETUNING_TIMER

2012-06-29 Thread Aaron Lu
Add a new flag of SDHCI_NEEDS_RETUNING_TIMER to represent if the host
needs retuning timer currently when driving the card inserted.

This flag is set when the host does tuning the first time for the card
and is used afterwards whenever needs to decide if the host is currently
using a retuning timer.

This flag is cleared when the card is removed in sdhci_reinit.

The set/clear of the flag and the start/stop of the retuning timer is
associated with the card's init/remove time, so there is no need to
touch it when the host is to be removed as at that time the card should
have already been removed.

Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/host/sdhci.c  | 31 +++
 include/linux/mmc/sdhci.h |  1 +
 2 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7e182ad..9918bcc 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -250,8 +250,9 @@ static void sdhci_reinit(struct sdhci_host *host)
 * applicable to UHS-I cards. So reset these fields to their initial
 * value when card is removed.
 */
-   if (host-version = SDHCI_SPEC_300  host-tuning_count 
-   host-tuning_mode == SDHCI_TUNING_MODE_1) {
+   if (host-flags  SDHCI_NEEDS_RETUNING_TIMER) {
+   host-flags = ~SDHCI_NEEDS_RETUNING_TIMER;
+
del_timer_sync(host-tuning_timer);
host-flags = ~SDHCI_NEEDS_RETUNING;
host-mmc-max_blk_count =
@@ -1872,6 +1873,7 @@ out:
 */
if (!(host-flags  SDHCI_NEEDS_RETUNING)  host-tuning_count 
(host-tuning_mode == SDHCI_TUNING_MODE_1)) {
+   host-flags |= SDHCI_NEEDS_RETUNING_TIMER;
mod_timer(host-tuning_timer, jiffies +
host-tuning_count * HZ);
/* Tuning mode 1 limits the maximum data length to 4MB */
@@ -1889,10 +1891,9 @@ out:
 * try tuning again at a later time, when the re-tuning timer expires.
 * So for these controllers, we return 0. Since there might be other
 * controllers who do not have this capability, we return error for
-* them.
+* them. SDHCI_NEEDS_RETUNING_TIMER means the host supports re-tuning.
 */
-   if (err  host-tuning_count 
-   host-tuning_mode == SDHCI_TUNING_MODE_1)
+   if (err  (host-flags  SDHCI_NEEDS_RETUNING_TIMER))
err = 0;
 
sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
@@ -2399,7 +2400,6 @@ out:
 int sdhci_suspend_host(struct sdhci_host *host)
 {
int ret;
-   bool has_tuning_timer;
 
if (host-ops-platform_suspend)
host-ops-platform_suspend(host);
@@ -2407,16 +2407,14 @@ int sdhci_suspend_host(struct sdhci_host *host)
sdhci_disable_card_detection(host);
 
/* Disable tuning since we are suspending */
-   has_tuning_timer = host-version = SDHCI_SPEC_300 
-   host-tuning_count  host-tuning_mode == SDHCI_TUNING_MODE_1;
-   if (has_tuning_timer) {
+   if (host-flags  SDHCI_NEEDS_RETUNING_TIMER) {
del_timer_sync(host-tuning_timer);
host-flags = ~SDHCI_NEEDS_RETUNING;
}
 
ret = mmc_suspend_host(host-mmc);
if (ret) {
-   if (has_tuning_timer) {
+   if (host-flags  SDHCI_NEEDS_RETUNING_TIMER) {
host-flags |= SDHCI_NEEDS_RETUNING;
mod_timer(host-tuning_timer, jiffies +
host-tuning_count * HZ);
@@ -2467,8 +2465,7 @@ int sdhci_resume_host(struct sdhci_host *host)
host-ops-platform_resume(host);
 
/* Set the re-tuning expiration flag */
-   if ((host-version = SDHCI_SPEC_300)  host-tuning_count 
-   (host-tuning_mode == SDHCI_TUNING_MODE_1))
+   if (host-flags  SDHCI_NEEDS_RETUNING_TIMER)
host-flags |= SDHCI_NEEDS_RETUNING;
 
return ret;
@@ -2507,8 +2504,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
int ret = 0;
 
/* Disable tuning since we are suspending */
-   if (host-version = SDHCI_SPEC_300 
-   host-tuning_mode == SDHCI_TUNING_MODE_1) {
+   if (host-flags  SDHCI_NEEDS_RETUNING_TIMER) {
del_timer_sync(host-tuning_timer);
host-flags = ~SDHCI_NEEDS_RETUNING;
}
@@ -2549,8 +2545,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
sdhci_do_enable_preset_value(host, true);
 
/* Set the re-tuning expiration flag */
-   if ((host-version = SDHCI_SPEC_300)  host-tuning_count 
-   (host-tuning_mode == SDHCI_TUNING_MODE_1))
+   if (host-flags  SDHCI_NEEDS_RETUNING_TIMER)
host-flags |= SDHCI_NEEDS_RETUNING;
 
spin_lock_irqsave(host-lock, flags);
@@ -3097,10 +3092,6 @@ void sdhci_remove_host(struct sdhci_host *host, int dead

Re: [PATCH 2/2] mmc: sdhci: A new flag SDHCI_NEEDS_RETUNING_TIMER

2012-06-29 Thread Aaron Lu
Hi,

On Fri, Jun 29, 2012 at 02:11:29AM -0400, Chris Ball wrote:
 Hi,
 
 On Fri, Jun 29 2012, Aaron Lu wrote:
  Add a new flag of SDHCI_NEEDS_RETUNING_TIMER to represent if the host
  needs retuning timer currently when driving the card inserted.
 
  This flag is set when the host does tuning the first time for the card
  and is used afterwards whenever needs to decide if the host is currently
  using a retuning timer.
 
  This flag is cleared when the card is removed in sdhci_reinit.
 
  The set/clear of the flag and the start/stop of the retuning timer is
  associated with the card's init/remove time, so there is no need to
  touch it when the host is to be removed as at that time the card should
  have already been removed.
 
 [...]
  @@ -3097,10 +3092,6 @@ void sdhci_remove_host(struct sdhci_host *host, int 
  dead)
   
  free_irq(host-irq, host);
   
  -   del_timer_sync(host-timer);
  -   if (host-version = SDHCI_SPEC_300)
  -   del_timer_sync(host-tuning_timer);
  -
  tasklet_kill(host-card_tasklet);
  tasklet_kill(host-finish_tasklet);
 
 The last paragraph of the commit message explains why you remove the
 del_timer_sync() call on the tuning_timer; but why do you remove it
 from the main (timeouts) host-timer too?
Oops... My mistake, sorry for that.
Will send v2.

Thanks,
Aaron

 
 Thanks,
 
 - Chris.
 -- 
 Chris Ball   c...@laptop.org   http://printf.net/
 One Laptop Per Child
 --
 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


[PATCH v2 0/2] Fixes for tuning stuffs

2012-06-29 Thread Aaron Lu
v2:
v1 mistakenly removed the line del_timer_sync(host-timer) in
sdhci_remove_host, fix this by adding back the code.

v1:
The following 2 patches fixed a bug related the tuning stuffs and
refactored the code to make it simpler and easier to read and understand.

-- 
1.7.11.1.3.g4c8a9db


--
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


[PATCH] mmc: sdhci: fix incorrect command used in tuning

2012-06-27 Thread Aaron Lu
For SD hosts using retuning mode 1, when retuning timer expired, it will
need to do retuning in sdhci_request before processing the actual
request. But the retuning command is fixed: cmd19 for SD card and cmd21
for eMMC card, so we can't use the original request's command to do the
tuning.

And since the tuning command depends on the card type atteched to the
host, we will need to know the card type to use the correct tuning
command.

Signed-off-by: Aaron Lu aaron...@amd.com
Cc: stable sta...@vger.kernel.org [3.3+]
---
 drivers/mmc/host/sdhci.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index f4b8b4d..ff522ec 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -27,6 +27,7 @@
 
 #include linux/mmc/mmc.h
 #include linux/mmc/host.h
+#include linux/mmc/card.h
 
 #include sdhci.h
 
@@ -1245,6 +1246,7 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
struct sdhci_host *host;
bool present;
unsigned long flags;
+   u32 tuning_opcode;
 
host = mmc_priv(mmc);
 
@@ -1292,8 +1294,11 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
 */
if ((host-flags  SDHCI_NEEDS_RETUNING) 
!(present_state  (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
+   tuning_opcode = mmc-card-type == MMC_TYPE_SD ?
+   MMC_SEND_TUNING_BLOCK :
+   MMC_SEND_TUNING_BLOCK_HS200;
spin_unlock_irqrestore(host-lock, flags);
-   sdhci_execute_tuning(mmc, mrq-cmd-opcode);
+   sdhci_execute_tuning(mmc, tuning_opcode);
spin_lock_irqsave(host-lock, flags);
 
/* Restore original mmc_request structure */
-- 
1.7.11.2.gd284367


--
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


Re: [PATCH v2 1/1] mmc: bus: print bus speed mode of UHS-I card

2012-03-30 Thread Aaron Lu
Hi,

On Fri, Mar 30, 2012 at 12:10:18PM +0530, Subhash Jadavani wrote:
 When UHS-I card is detected also print the bus speed mode
 in which UHS-I card will be running.
 
 Signed-off-by: Subhash Jadavani subha...@codeaurora.org

Acked-by: Aaron Lu aaron...@amd.com

-Aaron

 ---
  drivers/mmc/core/bus.c |   17 +++--
  1 files changed, 15 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
 index 5d011a3..3f60606 100644
 --- a/drivers/mmc/core/bus.c
 +++ b/drivers/mmc/core/bus.c
 @@ -267,6 +267,15 @@ int mmc_add_card(struct mmc_card *card)
  {
   int ret;
   const char *type;
 + const char *uhs_bus_speed_mode = ;
 + static const char *const uhs_speeds[] = {
 + [UHS_SDR12_BUS_SPEED] = SDR12 ,
 + [UHS_SDR25_BUS_SPEED] = SDR25 ,
 + [UHS_SDR50_BUS_SPEED] = SDR50 ,
 + [UHS_SDR104_BUS_SPEED] = SDR104 ,
 + [UHS_DDR50_BUS_SPEED] = DDR50 ,
 + };
 +
  
   dev_set_name(card-dev, %s:%04x, mmc_hostname(card-host), 
 card-rca);
  
 @@ -296,6 +305,10 @@ int mmc_add_card(struct mmc_card *card)
   break;
   }
  
 + if (mmc_sd_card_uhs(card) 
 + (card-sd_bus_speed  ARRAY_SIZE(uhs_speeds)))
 + uhs_bus_speed_mode = uhs_speeds[card-sd_bus_speed];
 +
   if (mmc_host_is_spi(card-host)) {
   pr_info(%s: new %s%s%s card on SPI\n,
   mmc_hostname(card-host),
 @@ -303,13 +316,13 @@ int mmc_add_card(struct mmc_card *card)
   mmc_card_ddr_mode(card) ? DDR  : ,
   type);
   } else {
 - pr_info(%s: new %s%s%s%s card at address %04x\n,
 + pr_info(%s: new %s%s%s%s%s card at address %04x\n,
   mmc_hostname(card-host),
   mmc_card_uhs(card) ? ultra high speed  :
   (mmc_card_highspeed(card) ? high speed  : ),
   (mmc_card_hs200(card) ? HS200  : ),
   mmc_card_ddr_mode(card) ? DDR  : ,
 - type, card-rca);
 + uhs_bus_speed_mode, type, card-rca);
   }
  
  #ifdef CONFIG_DEBUG_FS
 -- 
 1.7.1.1
 
 --
 Sent by a consultant of the Qualcomm Innovation Center, Inc.
 The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
 

--
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


Re: [PATCH v1 1/1] mmc: bus: print bus speed mode of UHS-I card

2012-03-27 Thread Aaron Lu
Hi,

On Mon, Mar 26, 2012 at 12:00:27PM +0530, Subhash Jadavani wrote:
  Actually we are already printing the HS200/DDR (for eMMC) bus speed mode
  along with card detected print. So why not bus speed mode for UHS-I cards.
  It really gives good impression to user what this card is capable of doing
 by
  just looking at this print.
  Correct we can this information from /sys/kernel/debug/mmc/ios but this
  needs extra effort than just looking at the kernel logs.
 
 But still please check if this point makes sense?


Yes, I think this makes sense.

-Aaron
 

--
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


Re: [PATCH v1 1/1] mmc: bus: print bus speed mode of UHS-I card

2012-03-25 Thread Aaron Lu
Hi Subhash,

On Fri, Mar 23, 2012 at 11:26:36AM +0530, Subhash Jadavani wrote:
 When UHS-I card is detected also print the bus speed mode
 in which UHS-I card will be running.

The patch looks correct to me, except that I' m not sure if this is
needed. /sys/kernel/debug/mmc/ios also has such info.

-Aaron

 
 Signed-off-by: Subhash Jadavani subha...@codeaurora.org
 ---
  drivers/mmc/core/bus.c |   26 +-
  1 files changed, 25 insertions(+), 1 deletions(-)
 
 diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
 index 5d011a3..0517a91 100644
 --- a/drivers/mmc/core/bus.c
 +++ b/drivers/mmc/core/bus.c
 @@ -267,6 +267,7 @@ int mmc_add_card(struct mmc_card *card)
  {
   int ret;
   const char *type;
 + const char *uhs_bus_speed_mode = ;
  
   dev_set_name(card-dev, %s:%04x, mmc_hostname(card-host), 
 card-rca);
  
 @@ -296,6 +297,28 @@ int mmc_add_card(struct mmc_card *card)
   break;
   }
  
 + if (mmc_sd_card_uhs(card)) {
 + switch (card-sd_bus_speed) {
 + case UHS_SDR104_BUS_SPEED:
 + uhs_bus_speed_mode = SDR104 ;
 + break;
 + case UHS_SDR50_BUS_SPEED:
 + uhs_bus_speed_mode = SDR50 ;
 + break;
 + case UHS_DDR50_BUS_SPEED:
 + uhs_bus_speed_mode = DDR50 ;
 + break;
 + case UHS_SDR25_BUS_SPEED:
 + uhs_bus_speed_mode = SDR25 ;
 + break;
 + case UHS_SDR12_BUS_SPEED:
 + uhs_bus_speed_mode = SDR12 ;
 + break;
 + default:
 + uhs_bus_speed_mode = ;
 + break;
 + }
 + }
   if (mmc_host_is_spi(card-host)) {
   pr_info(%s: new %s%s%s card on SPI\n,
   mmc_hostname(card-host),
 @@ -303,12 +326,13 @@ int mmc_add_card(struct mmc_card *card)
   mmc_card_ddr_mode(card) ? DDR  : ,
   type);
   } else {
 - pr_info(%s: new %s%s%s%s card at address %04x\n,
 + pr_info(%s: new %s%s%s%s%s card at address %04x\n,
   mmc_hostname(card-host),
   mmc_card_uhs(card) ? ultra high speed  :
   (mmc_card_highspeed(card) ? high speed  : ),
   (mmc_card_hs200(card) ? HS200  : ),
   mmc_card_ddr_mode(card) ? DDR  : ,
 + uhs_bus_speed_mode,
   type, card-rca);
   }
  
 -- 
 1.7.1.1
 
 --
 Sent by a consultant of the Qualcomm Innovation Center, Inc.
 The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
 --
 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


Re: [PATCH 2/2] mmc: sdhci: always reset all during resume

2012-02-02 Thread Aaron Lu
On Mon, Jan 30, 2012 at 02:27:19PM +0200, Adrian Hunter wrote:
 During suspend the host controller may or may not be powered off.
 In order to get the same result either way, always perform a
 software reset all when resuming.
 
 Signed-off-by: Adrian Hunter adrian.hun...@intel.com
 Cc: Philip Rakity prak...@marvell.com
 Cc: Aaron Lu aaron...@amd.com

Acked-by: Aaron Lu aaron...@amd.com

 ---
  drivers/mmc/host/sdhci.c |   29 +++--
  1 files changed, 11 insertions(+), 18 deletions(-)
 
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 8d66706..ef2434c 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -219,31 +219,20 @@ static void sdhci_reset(struct sdhci_host *host, u8 
 mask)
   }
  }
  
 -static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
 -
 -static void sdhci_init(struct sdhci_host *host, int soft)
 +static void sdhci_init(struct sdhci_host *host)
  {
 - if (soft)
 - sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
 - else
 - sdhci_reset(host, SDHCI_RESET_ALL);
 + sdhci_reset(host, SDHCI_RESET_ALL);
  
   sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
   SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
   SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
   SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
   SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
 -
 - if (soft) {
 - /* force clock reconfiguration */
 - host-clock = 0;
 - sdhci_set_ios(host-mmc, host-mmc-ios);
 - }
  }
  
  static void sdhci_reinit(struct sdhci_host *host)
  {
 - sdhci_init(host, 0);
 + sdhci_init(host);
   sdhci_enable_card_detection(host);
  }
  
 @@ -2423,8 +2412,12 @@ int sdhci_resume_host(struct sdhci_host *host)
   if (ret)
   return ret;
  
 - sdhci_init(host, (host-mmc-pm_flags  MMC_PM_KEEP_POWER));
 - mmiowb();
 + sdhci_init(host);
 +
 + /* Force clock and power re-program */
 + host-pwr = 0;
 + host-clock = 0;
 + sdhci_do_set_ios(host, host-mmc-ios);
  
   ret = mmc_resume_host(host-mmc);
   sdhci_enable_card_detection(host);
 @@ -2500,7 +2493,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
   host-ops-enable_dma(host);
   }
  
 - sdhci_init(host, 0);
 + sdhci_init(host);
  
   /* Force clock and power re-program */
   host-pwr = 0;
 @@ -2980,7 +2973,7 @@ int sdhci_add_host(struct sdhci_host *host)
   host-vmmc = NULL;
   }
  
 - sdhci_init(host, 0);
 + sdhci_init(host);
  
  #ifdef CONFIG_MMC_DEBUG
   sdhci_dumpregs(host);
 -- 
 1.7.6.4
 
 

--
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


Re: [PATCH 1/4 v3] MMC/core: Add f_min to mmc_power_on()

2012-01-12 Thread Aaron Lu
Hi,

On Fri, Jan 13, 2012 at 02:24:46AM +, Huang Changming-R66093 wrote:
 Hi, Chris,
 Could you have any comment about this patch?
 Can it go into 3.3 or 3.4?
 
  -Original Message-
  From: Huang Changming-R66093
  Sent: Friday, December 09, 2011 10:54 AM
  To: linux-mmc@vger.kernel.org
  Cc: Huang Changming-R66093; Chris Ball
  Subject: [PATCH 1/4 v3] MMC/core: Add f_min to mmc_power_on()
  
  From: Jerry Huang chang-ming.hu...@freescale.com
  
  When f_init is zero, the SDHC can't work correctly. So f_min will replace
  f_init, when f_init is zero.

What about setting f_init before your call to mmc_power_up?

  
  Signed-off-by: Jerry Huang chang-ming.hu...@freescale.com
  CC: Chris Ball c...@laptop.org
  ---
  changes for v2:
  - add the CC
  changes for v3:
  - enalbe the controller clock in platform, instead of core
  
   drivers/mmc/core/core.c |5 -
   1 files changed, 4 insertions(+), 1 deletions(-)
  
  diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
  index a08e6b1..2d40c04 100644
  --- a/drivers/mmc/core/core.c
  +++ b/drivers/mmc/core/core.c
  @@ -1253,7 +1253,10 @@ static void mmc_power_up(struct mmc_host *host)
   */
  mmc_delay(10);
  
  -   host-ios.clock = host-f_init;
  +   if (host-f_init)
  +   host-ios.clock = host-f_init;
  +   else
  +   host-ios.clock = host-f_min;
  
  host-ios.power_mode = MMC_POWER_ON;
  mmc_set_ios(host);
  --
  1.7.5.4
 
 
 --
 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


Re: [PATCH 2/4 v4] MMC/SD: Add callback function to detect card

2012-01-12 Thread Aaron Lu
Hi,

On Fri, Jan 13, 2012 at 02:25:11AM +, Huang Changming-R66093 wrote:
 Hi, Chris,
 Could you have any comment about this patch?
 Can it go into 3.3 or 3.4?
 
 Thanks
 Jerry Huang
  -Original Message-
  From: Huang Changming-R66093
  Sent: Tuesday, December 27, 2011 4:01 PM
  To: linux-mmc@vger.kernel.org
  Cc: Huang Changming-R66093; Chris Ball
  Subject: [PATCH 2/4 v4] MMC/SD: Add callback function to detect card
  
  From: Jerry Huang chang-ming.hu...@freescale.com
  
  In order to check whether the card has been removed, the function
  mmc_send_status() will send command CMD13 to card and ask the card
  to send its status register to sdhc driver, which will generate
  many interrupts repeatedly and make the system performance bad.

For sd hosts, this should only happen for hosts which have
SDHCI_QUIRK_BROKEN_CARD_DETECTION set.

  
  Therefore, add callback function get_cd() to check whether
  the card has been removed when the driver has this callback function.

I don't quite get the meaning of cd, what does get_cd suppose to mean?

  
  If the card is present, 1 will return, if the card is absent, 0 will
  return.
  If the controller will not support this feature, -ENOSYS will return.

What about get_present, return 0 for present, and return error code
otherwise like the alive function does.

  
  Signed-off-by: Jerry Huang chang-ming.hu...@freescale.com
  CC: Chris Ball c...@laptop.org
  ---
  changes for v2:
  - when controller don't support get_cd, return -ENOSYS
  - add the CC
  changes for v3:
  - enalbe the controller clock in platform, instead of core
  changes for v4:
  - move the detect code to core.c according to the new structure
  
   drivers/mmc/core/core.c |   10 --
   1 files changed, 8 insertions(+), 2 deletions(-)
  
  diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
  index 6db6621..d570c72 100644
  --- a/drivers/mmc/core/core.c
  +++ b/drivers/mmc/core/core.c
  @@ -2060,7 +2060,7 @@ static int mmc_rescan_try_freq(struct mmc_host
  *host, unsigned freq)
  

snip
   int _mmc_detect_card_removed(struct mmc_host *host)
   {
  -   int ret;
  +   int ret = -ENOSYS;
  
  if ((host-caps  MMC_CAP_NONREMOVABLE) || !host-bus_ops-alive)
  return 0;
  @@ -2068,7 +2068,13 @@ int _mmc_detect_card_removed(struct mmc_host *host)
  if (!host-card || mmc_card_removed(host-card))
  return 1;
  
  -   ret = host-bus_ops-alive(host);
  +   if (host-ops-get_cd) {
  +   ret = host-ops-get_cd(host);
  +   if (ret = 0)
  +   ret = !ret;
  +   }
  +   if (ret  0)
  +   ret = host-bus_ops-alive(host);
  if (ret) {
  mmc_card_set_removed(host-card);
  pr_debug(%s: card remove detected\n, mmc_hostname(host));
  --
  1.7.5.4

And the code can be changed to something like:
if (host-ops-get_present)
ret = host-ops-get_present(host);
else
ret = host-bus_ops-alive(host);
if (ret) {
mmc_card_set_removed(host-card);
pr_debug(%s: card remove detected\n, mmc_hostname(host));
}


Does this make sense?

-Aaron

 
 
 --
 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


Re: [PATCH 3/4 v5] SDHCI: add sdhci_get_cd callback to detect the card

2012-01-12 Thread Aaron Lu
Hi,

On Fri, Jan 13, 2012 at 02:25:18AM +, Huang Changming-R66093 wrote:
 Hi, Chris,
 Could you have any comment about this patch?
 Can it go into 3.3 or 3.4?
 
 Thanks
 Jerry Huang
 
  -Original Message-
  From: Huang Changming-R66093
  Sent: Wednesday, December 14, 2011 10:18 AM
  To: linux-mmc@vger.kernel.org
  Cc: Huang Changming-R66093; Chris Ball
  Subject: [PATCH 3/4 v5] SDHCI: add sdhci_get_cd callback to detect the
  card
  
  From: Jerry Huang chang-ming.hu...@freescale.com
  
  Add callback function sdhci_get_cd to detect the card.
  And one new callback added to implement the card detect in sdhci
  struncture.
  If special platform has the card detect callback, it will return the card
  state, the value zero is for absent cardi and one is for present card.
  If the controller don't support card detect, sdhci_get_cd will return -
  ENOSYS.
  
  Signed-off-by: Jerry Huang chang-ming.hu...@freescale.com
  CC: Chris Ball c...@laptop.org
  ---
  changes for v2:
  - when controller don't support get_cd, return -ENOSYS
  - add new callback for sdhci to detect the card
  - add the CC
  changes for v3:
  - use pin_lock only when get_cd defined
  changes for v4:
  - enalbe the controller clock in platform, instead of core
  changes for v5:
  - remove the copyright
  
   drivers/mmc/host/sdhci.c |   21 ++
   drivers/mmc/host/sdhci.h |2 ++
   2 files changed, 23 insertions(+), 0 deletions(-)
  
  diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
  index 6d8eea3..fbe2f46 100644
  --- a/drivers/mmc/host/sdhci.c
  +++ b/drivers/mmc/host/sdhci.c
  @@ -1518,6 +1519,26 @@ static int sdhci_get_ro(struct mmc_host *mmc)
  return ret;
   }

snip
  
  +/* Return values for the sdjco_get_cd callback:
  + *   0 for a absent card
  + *   1 for a present card
  + *   -ENOSYS when not supported (equal to NULL callback)
  + */
  +static int sdhci_get_cd(struct mmc_host *mmc)
  +{
  +   struct sdhci_host *host = mmc_priv(mmc);
  +   unsigned long flags;
  +   int present = -ENOSYS;
  +
  +   if (host-ops-get_cd) {
  +   spin_lock_irqsave(host-lock, flags);
  +   present = host-ops-get_cd(host);
  +   spin_unlock_irqrestore(host-lock, flags);
  +   }
  +
  +   return present;
  +}
  +

I think this function has to take care of standard sd host behaviour: if
a specific host has implemented the get_cd callback, then use it; if
not, then see the BROKEN_DETECT quirk; finally, use the present register
to get the value like the sdhci_request function does.

-Aaron

   static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int
  enable)
   {
  if (host-flags  SDHCI_DEVICE_DEAD)
  @@ -1884,6 +1905,7 @@ static const struct mmc_host_ops sdhci_ops = {
  .request= sdhci_request,
  .set_ios= sdhci_set_ios,
  .get_ro = sdhci_get_ro,
  +   .get_cd = sdhci_get_cd,
  .hw_reset   = sdhci_hw_reset,
  .enable_sdio_irq = sdhci_enable_sdio_irq,
  .start_signal_voltage_switch= sdhci_start_signal_voltage_switch,
  diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
  index 0a5b654..82f4d27 100644
  --- a/drivers/mmc/host/sdhci.h
  +++ b/drivers/mmc/host/sdhci.h
  @@ -69,6 +69,7 @@
   #define  SDHCI_SPACE_AVAILABLE 0x0400
   #define  SDHCI_DATA_AVAILABLE  0x0800
   #define  SDHCI_CARD_PRESENT0x0001
  +#define  SDHCI_CARD_CDPL   0x0004
   #define  SDHCI_WRITE_PROTECT   0x0008
   #define  SDHCI_DATA_LVL_MASK   0x00F0
   #define   SDHCI_DATA_LVL_SHIFT 20
  @@ -261,6 +262,7 @@ struct sdhci_ops {
  
  void(*set_clock)(struct sdhci_host *host, unsigned int clock);
  
  +   int (*get_cd)(struct sdhci_host *host);
  int (*enable_dma)(struct sdhci_host *host);
  unsigned int(*get_max_clock)(struct sdhci_host *host);
  unsigned int(*get_min_clock)(struct sdhci_host *host);
  --
  1.7.5.4
 
 
 --
 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


Re: [PATCH 3/4 v5] SDHCI: add sdhci_get_cd callback to detect the card

2012-01-12 Thread Aaron Lu
On Fri, Jan 13, 2012 at 04:50:11AM +, Huang Changming-R66093 wrote:
 
 
  I think this function has to take care of standard sd host behaviour: if
  a specific host has implemented the get_cd callback, then use it; if
  not, then see the BROKEN_DETECT quirk; finally, use the present register
  to get the value like the sdhci_request function does.
  
 Yes, I have thought about it.
 In this patch, only FSL eSDHC use it.

Only FSL eSDHC defines it, but all sd hosts will use it since the call
is made in core.c with host-ops-get_cd.

If you only cares about FSL eSDHC, then probably you should do this in
sdhci.c instead of core.c, by adding a callback to the sdhci_ops and in
the sdhci_request call, instead of checking present register, call the
get_cd callback if available.

 For the other platform, the get_cd is NULL.





--
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


Re: [PATCH 2/4 v4] MMC/SD: Add callback function to detect card

2012-01-12 Thread Aaron Lu
Hi,

On Fri, Jan 13, 2012 at 04:52:42AM +, Huang Changming-R66093 wrote:
 
  For sd hosts, this should only happen for hosts which have
  SDHCI_QUIRK_BROKEN_CARD_DETECTION set.
 Yes, but which will impact the performance.

You only set this bit when your host broke, and if your host has other
means to detect this, then go with your newly added callback.

 
 
   
Therefore, add callback function get_cd() to check whether the card
has been removed when the driver has this callback function.
  
  I don't quite get the meaning of cd, what does get_cd suppose to mean?
 This get_cd callback is implement in the special platform, because some SOC 
 don't support this feature
 
   
If the card is present, 1 will return, if the card is absent, 0 will
return.
If the controller will not support this feature, -ENOSYS will return.
  
  What about get_present, return 0 for present, and return error code
  otherwise like the alive function does.
 The hook to detect card is get_cd in the kernel, don't need the new.
 

I didn't mean to add a new function, I just can't get the meaning of cd.
I just did a grep of the code and find some same fuction names in
various host files, I think it's OK to continue with this name.

   
Signed-off-by: Jerry Huang chang-ming.hu...@freescale.com
CC: Chris Ball c...@laptop.org
---
changes for v2:
- when controller don't support get_cd, return -ENOSYS
- add the CC
changes for v3:
- enalbe the controller clock in platform, instead of core
changes for v4:
- move the detect code to core.c according to the new structure
   
 drivers/mmc/core/core.c |   10 --
 1 files changed, 8 insertions(+), 2 deletions(-)
   
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index
6db6621..d570c72 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2060,7 +2060,7 @@ static int mmc_rescan_try_freq(struct mmc_host
*host, unsigned freq)
   
  
  snip
 int _mmc_detect_card_removed(struct mmc_host *host)  {
-   int ret;
+   int ret = -ENOSYS;
   
if ((host-caps  MMC_CAP_NONREMOVABLE) || 
!host-bus_ops-alive)
return 0;
@@ -2068,7 +2068,13 @@ int _mmc_detect_card_removed(struct mmc_host
  *host)
if (!host-card || mmc_card_removed(host-card))
return 1;
   
-   ret = host-bus_ops-alive(host);
+   if (host-ops-get_cd) {
+   ret = host-ops-get_cd(host);
+   if (ret = 0)
+   ret = !ret;
+   }
+   if (ret  0)
+   ret = host-bus_ops-alive(host);
if (ret) {
mmc_card_set_removed(host-card);
pr_debug(%s: card remove detected\n, 
mmc_hostname(host));
--
1.7.5.4
  
  And the code can be changed to something like:
  if (host-ops-get_present)
  ret = host-ops-get_present(host);
  else
  ret = host-bus_ops-alive(host);
  if (ret) {
  mmc_card_set_removed(host-card);
  pr_debug(%s: card remove detected\n, mmc_hostname(host));
  }
  
  
  Does this make sense?
 No.
 Because the get_cd is the hook to detect card in mmc_host_ops structure in 
 include/linux/mmc/host.h.
 We don't need to add new.


I just suggested to change the name and use a different return value for
this get_cd function, not to add a new function call.


--
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


Re: [PATCH 1/4 v3] MMC/core: Add f_min to mmc_power_on()

2012-01-12 Thread Aaron Lu
Hi,

On Fri, Jan 13, 2012 at 03:39:53AM +, Huang Changming-R66093 wrote:
 
 
  -Original Message-
  From: Aaron Lu [mailto:aaron...@amd.com]
  Sent: Friday, January 13, 2012 11:27 AM
  To: Huang Changming-R66093
  Cc: linux-mmc@vger.kernel.org; Chris Ball
  Subject: Re: [PATCH 1/4 v3] MMC/core: Add f_min to mmc_power_on()
  
  Hi,
  
  On Fri, Jan 13, 2012 at 02:24:46AM +, Huang Changming-R66093 wrote:
   Hi, Chris,
   Could you have any comment about this patch?
   Can it go into 3.3 or 3.4?
  
-Original Message-
From: Huang Changming-R66093
Sent: Friday, December 09, 2011 10:54 AM
To: linux-mmc@vger.kernel.org
Cc: Huang Changming-R66093; Chris Ball
Subject: [PATCH 1/4 v3] MMC/core: Add f_min to mmc_power_on()
   
From: Jerry Huang chang-ming.hu...@freescale.com
   
When f_init is zero, the SDHC can't work correctly. So f_min will
replace f_init, when f_init is zero.
  
  What about setting f_init before your call to mmc_power_up?
 f_init is initialized only by mmc_rescan_try_freq, and mmc_power_up will use 
 it.
 But mmc_power_up will called not only by mmc_rescan_try_freq, but also by 
 other functions.
 You will see it in my previous email about it.


Yes, I know there are other callers for mmc_power_up.
Either you set host-f_init in mmc_power_up, or you set it before you
call mmc_power_up. I prefer the latter one but I'm not sure which one
should be used. Maybe Chris can comment on this.


--
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


Re: [PATCH 2/4 v4] MMC/SD: Add callback function to detect card

2012-01-12 Thread Aaron Lu
On Fri, Jan 13, 2012 at 07:05:19AM +, Huang Changming-R66093 wrote:
 If you read the previous email about this serial patches discussed with other 
 guys, you can understand.
 
  -Original Message-
  From: Aaron Lu [mailto:aaron...@amd.com]
  Sent: Friday, January 13, 2012 2:28 PM
  To: Huang Changming-R66093
  Cc: linux-mmc@vger.kernel.org; Chris Ball
  Subject: Re: [PATCH 2/4 v4] MMC/SD: Add callback function to detect card
  
  Hi,
  
  On Fri, Jan 13, 2012 at 04:52:42AM +, Huang Changming-R66093 wrote:
  
For sd hosts, this should only happen for hosts which have
SDHCI_QUIRK_BROKEN_CARD_DETECTION set.
   Yes, but which will impact the performance.
  
  You only set this bit when your host broke, and if your host has other
  means to detect this, then go with your newly added callback.
 To detect the card state, if SDHCI_QUIRK_BROKEN_CARD_DETECTION is set, then 
 driver will send command to card, which will cause the bad performance.
 So my patch will do:
 1. use get_cd to detect the card state, if platform don't support this 
 feature(get_cd is not defined in special platform), -ENOSYS will be returned
 2. if -ENOSYS, then send the command to card.

OK, this is clear. I didn't know there is a get_cd callback already
defined in sdhci_ops with a clear return value description, sorry for
the mess.

  I just suggested to change the name and use a different return value for
  this get_cd function, not to add a new function call.
  
 The description for get_cd in file include/linux/mmc/host.h:
  * Return values for the get_cd callback should be:
  *   0 for a absent card
  *   1 for a present card
  *   -ENOSYS when not supported (equal to NULL callback)
  *   or a negative errno value when something bad happened
 I don't think your suggest is reasonable.
Agree.


--
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


Re: typo in Documentation/devices.txt ?

2012-01-09 Thread Aaron Lu
Hi,

On Thu, Jan 05, 2012 at 07:08:27AM +, 허종만 wrote:
 
 Hi, all..
 
 Here is description for MMC block devices in Documentation/devices.txt :
 
 179 block   MMC block devices
   0 = /dev/mmcblk0  First SD/MMC card
   1 = /dev/mmcblk0p1First partition on first MMC card
   8 = /dev/mmcblk1  Second SD/MMC card
   ^^
 The start of next SD/MMC card can be configured with
 CONFIG_MMC_BLOCK_MINORS, or overridden at boot/modprobe
 time using the mmcblk.perdev_minors option. That would
 bump the offset between each card to be the configured
 value instead of the default 8.
 
 
 Shouldn't  8 = /dev/mmcblk1 be 9 = /dev/mmcblk1 ?

No, mmcblk1's minor is 8, mmcblk2's minor is 16, etc...

 
 If we have 8 partitions on first MMC card, we need mmcblk0p1 ~ mmcblk0p8 
 devices, with minor number 1 ~ 8.
 Am I misunderstanding?

Each mmc block device by default has 8 minors, not 8 partitions. Minor 0
represent the whole disk. So each mmc block device at most has 7
partitions instead of 8.

See code in function mmc_blk_alloc_req on assigning minor value to the
whole disk of the block device:
md-disk-first_minor = devidx * perdev_minors;

And code in function blk_alloc_devt on checking partition number against
disk minors:
/* in consecutive minor range? */
if (part-partno  disk-minors) {
*devt = MKDEV(disk-major, disk-first_minor + part-partno);
return 0;
}

-Aaron

 
 Regards,
 Jongman Heo.

--
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


Re: sdhci max_blk_size

2012-01-04 Thread Aaron Lu
On Wed, Jan 04, 2012 at 04:01:07PM +0100, Matthieu CASTET wrote:
 Hi,
 
 our controller set Max Block Length to 3 (4096 byte), but the linux driver
 ignore this value [1].
 
 Is there any reason to do that .

The reason is, sd host controller spec defines 3 as reserved, not 4096.

 Or it is code that was written with an older sdhci spec, and we can ignore 
 this
 check today.

The current sdhci driver follows v3 spec, is the v4 spec out that
defined this bit?

 
 
 
 Matthieu
 
 PS : please keep me in CC.
 
 [1]
 if (mmc-max_blk_size = 3) {
 pr_warning(%s: Invalid maximum block size, 
 assuming 512 bytes\n, mmc_hostname(mmc));
 mmc-max_blk_size = 0;
 }
 --

--
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


Re: [PATCH] mmc: sdhci: deactivate tuning timer when host is suspending

2012-01-03 Thread Aaron Lu
On Mon, Jan 02, 2012 at 07:02:27PM -0500, Chris Ball wrote:
 Hi,
 
 On Mon, Dec 26 2011, Aaron Lu wrote:
  From: Philip Rakity prak...@marvell.com
 
  Since we are suspending, the tuning timer should be deactivated.
 
  Signed-off-by: Philip Rakity prak...@marvell.com
  Acked-by: Aaron Lu aaron...@amd.com
  ---
   drivers/mmc/host/sdhci.c |3 +--
   1 files changed, 1 insertions(+), 2 deletions(-)
 
  diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
  index ab6018f..1abbd26 100644
  --- a/drivers/mmc/host/sdhci.c
  +++ b/drivers/mmc/host/sdhci.c
  @@ -2347,8 +2347,7 @@ int sdhci_suspend_host(struct sdhci_host *host)
  if (host-version = SDHCI_SPEC_300  host-tuning_count 
  host-tuning_mode == SDHCI_TUNING_MODE_1) {
  host-flags = ~SDHCI_NEEDS_RETUNING;
  -   mod_timer(host-tuning_timer, jiffies +
  -   host-tuning_count * HZ);
  +   del_timer_sync(host-tuning_timer);
  }
   
  ret = mmc_suspend_host(host-mmc);
 
 Pushed to mmc-next for 3.3 with a stable@ tag, thanks.

I'm sorry Chris, this patch is deprecated and please apply the following
patch with Adrian's ack instead:
[PATCH 1/2] mmc: sdhci: Fix tuning timer incorrect setting when suspending host

Thanks.

 
 - Chris.
 -- 
 Chris Ball   c...@laptop.org   http://printf.net/
 One Laptop Per Child
 

--
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


[PATCH v3 2/2] mmc: sdhci: Deal with failure case in sdhci_suspend_host

2012-01-03 Thread Aaron Lu
V3: Rework on top of Adrian's vmmc patch

V2: Error processing code in sdhci_pci_suspend should not be deleted,
it is used to resume hosts which are already successfully suspended for
a multi slot pci device as suggested by Adrian.

If there are errors happened in sdhci_suspend_host, handle it so that
when the function returns with an error, the host's behaviour is the
same before this function call, e.g. card detection is enabled and
tuning timer is active, etc.

Signed-off-by: Philip Rakity prak...@marvell.com
Signed-off-by: Aaron Lu aaron...@amd.com
Cc: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/host/sdhci.c |   18 ++
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 988ae06..823b83e 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2349,20 +2349,30 @@ out:
 
 int sdhci_suspend_host(struct sdhci_host *host)
 {
-   int ret;
+   int ret, has_tuning_timer;
 
sdhci_disable_card_detection(host);
 
/* Disable tuning since we are suspending */
-   if (host-version = SDHCI_SPEC_300  host-tuning_count 
-   host-tuning_mode == SDHCI_TUNING_MODE_1) {
+   has_tuning_timer = host-version = SDHCI_SPEC_300 
+   host-tuning_count  host-tuning_mode == SDHCI_TUNING_MODE_1;
+   if (has_tuning_timer) {
del_timer_sync(host-tuning_timer);
host-flags = ~SDHCI_NEEDS_RETUNING;
}
 
ret = mmc_suspend_host(host-mmc);
-   if (ret)
+   if (ret) {
+   if (has_tuning_timer) {
+   host-flags |= SDHCI_NEEDS_RETUNING;
+   mod_timer(host-tuning_timer, jiffies +
+   host-tuning_count * HZ);
+   }
+
+   sdhci_enable_card_detection(host);
+
return ret;
+   }
 
free_irq(host-irq, host);
 
-- 
1.7.7.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


Re: [PATCH 2/2] mmc: sdhci: Deal with failure case in sdhci_suspend_host

2011-12-28 Thread Aaron Lu
On Wed, Dec 28, 2011 at 02:23:32PM +0200, Adrian Hunter wrote:
  -
  -err_pci_suspend:
  -   while (--i = 0)
  -   sdhci_resume_host(chip-slots[i]-host);
  -   return ret;
 
 This doesn't look right.  This is about having multiple
 host controllers on the same PCI device.  If those
 hosts have been successfully suspended, then they must
 be resumed on error.


You are right, I failed to understand the code.
Will send the patch again without touching the pci recover code, thanks.

 
   }
 


--
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


[PATCH v2 2/2] mmc: sdhci: Deal with failure case in sdhci_suspend_host

2011-12-28 Thread Aaron Lu
V2: Error processing code in sdhci_pci_suspend should not be deleted,
it is used to resume hosts which are already successfully suspended for
a multi slot pci device as suggested by Adrian.

If there are errors happened in sdhci_suspend_host, handle it so that
when the function returns with an error, the host's behaviour is the
same before this function call, e.g. card detection is enabled and
tuning timer is active, etc.

Signed-off-by: Philip Rakity prak...@marvell.com
Signed-off-by: Aaron Lu aaron...@amd.com
Cc: Adrian Hunter adrian.hun...@intel.com
---
 drivers/mmc/host/sdhci.c |   27 +--
 1 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2007d37..37aeb81 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2339,25 +2339,40 @@ out:
 
 int sdhci_suspend_host(struct sdhci_host *host)
 {
-   int ret;
+   int ret, has_tuning_timer;
 
sdhci_disable_card_detection(host);
 
/* Disable tuning since we are suspending */
-   if (host-version = SDHCI_SPEC_300  host-tuning_count 
-   host-tuning_mode == SDHCI_TUNING_MODE_1) {
+   has_tuning_timer = host-version = SDHCI_SPEC_300 
+   host-tuning_count  host-tuning_mode == SDHCI_TUNING_MODE_1;
+   if (has_tuning_timer) {
del_timer_sync(host-tuning_timer);
host-flags = ~SDHCI_NEEDS_RETUNING;
}
 
ret = mmc_suspend_host(host-mmc);
if (ret)
-   return ret;
+   goto err_suspend;
+
+   if (host-vmmc) {
+   ret = regulator_disable(host-vmmc);
+   if (ret)
+   goto err_suspend;
+   }
 
free_irq(host-irq, host);
 
-   if (host-vmmc)
-   ret = regulator_disable(host-vmmc);
+   return 0;
+
+err_suspend:
+   if (has_tuning_timer) {
+   host-flags |= SDHCI_NEEDS_RETUNING;
+   mod_timer(host-tuning_timer, jiffies +
+   host-tuning_count * HZ);
+   }
+
+   sdhci_enable_card_detection(host);
 
return ret;
 }
-- 
1.7.7.4


--
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


[PATCH 0/2] mmc: sdhci: Fix for sdhci suspend function

2011-12-27 Thread Aaron Lu
Fixed a bug in sdhci_suspend_host, the tuning timer should be
deactivated instead of reactivated when suspending.

Handle failure case in sdhci_suspend_host, so that calling function
does not need to take care of the error recovery.

mmc: sdhci: Fix tuning timer incorrect setting when suspending host
mmc: sdhci: Deal with failure case in sdhci_suspend_host

 drivers/mmc/host/sdhci-pci.c |9 ++---
 drivers/mmc/host/sdhci.c |   30 ++
 2 files changed, 24 insertions(+), 15 deletions(-)

-- 
1.7.7.4


--
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


[PATCH] mmc: sdhci: deactivate tuning timer when host is suspending

2011-12-26 Thread Aaron Lu
From: Philip Rakity prak...@marvell.com

Since we are suspending, the tuning timer should be deactivated.

Signed-off-by: Philip Rakity prak...@marvell.com
Acked-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/host/sdhci.c |3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index ab6018f..1abbd26 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2347,8 +2347,7 @@ int sdhci_suspend_host(struct sdhci_host *host)
if (host-version = SDHCI_SPEC_300  host-tuning_count 
host-tuning_mode == SDHCI_TUNING_MODE_1) {
host-flags = ~SDHCI_NEEDS_RETUNING;
-   mod_timer(host-tuning_timer, jiffies +
-   host-tuning_count * HZ);
+   del_timer_sync(host-tuning_timer);
}
 
ret = mmc_suspend_host(host-mmc);
-- 
1.7.7.4


--
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


Re: [PATCH] SD/MMC: fix the issue of SDHC performance regression

2011-11-08 Thread Aaron Lu
On Mon, Nov 07, 2011 at 08:20:10AM -0500, Chris Ball wrote:
 Have you seen:
 
 http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=f2815f68dabbb373fd1c9f0fd4a609d486697c2b
  
 (mmc: sd: Handle SD3.0 cards not supporting UHS-I bus speed mode)
 
 which is already in mainline?  I think your patch is identical.
Hi Chris,

I think the existing code is somewhat confusing, since SDR50 means
100MHZ frequency while high speed is 50MHZ.
The reason it is correct is UHS_SDR50_BUS_SPEED is defined as 2,
which happened to be the same value as (1  UHS_SDR25_BUS_SPEED).

How about change it like this:

diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index a230e7f..670fd7f 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -306,7 +306,7 @@ static int mmc_read_switch(struct mmc_card *card)
goto out;
}
 
-   if (status[13]  UHS_SDR50_BUS_SPEED)
+   if (status[13]  SD_MODE_UHS_SDR25)
card-sw_caps.hs_max_dtr = 5000;
 
if (card-scr.sda_spec3) {

SDR25 is also 50MHZ, the same frequency as high speed.
Or we can add a new macro for high speed like qiang has done,
which one you prefer?

Thanks,
Aaron

--
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


Re: [PATCH V1] mmc: core: HS200 mode support for eMMC 4.5

2011-09-22 Thread Aaron Lu
On Thu, Sep 22, 2011 at 04:43:40PM +0530, Girish K S wrote:
 This patch adds the support of the HS200 bus speed for
 eMMC 4.5 devices.
 The eMMC 4.5 devices have support for 200MHz bus speed.
 The mmc core and host modules have been touched to add support
 for this module.
 It is necessary to know the card type in the sdhci.c file to
 add support for eMMC tuning function. So card.h file is included
 to import the card data structure.
 
 Signed-off-by: Girish K S girish.shivananja...@linaro.org
 ---
  v1:
  cases which produce same result have been combined to reduce
  repeated assignments. patch recreated after rebase to chris 
  balls mmc-next branch.

Your patch does not apply to mmc-next tree...

 
 @@ -1661,7 +1663,10 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
   if (!tuning_loop_counter  !timeout)
   break;
 

The sdhci_execute_tuning will not proceed here unless the ctrl register
indicates the host is running at UHS_SDR104 or UHS_SDR50 with
SDHCI_SDR50_NEEDS_TUNING flag set. Does your host also reflect this when
running at 200Mhz bus speed?

 - cmd.opcode = MMC_SEND_TUNING_BLOCK;
 + if (mmc-card-type == MMC_TYPE_MMC)
 + cmd.opcode = MMC_SEND_TUNING_BLOCK_HS200;
 + else
 + cmd.opcode = MMC_SEND_TUNING_BLOCK;
   cmd.arg = 0;
   cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
   cmd.retries = 0;

--
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


Re: [PATCH] mmc: core: Set correct bus mode before card init

2011-09-15 Thread Aaron Lu
Hi Ulf,

I'm not familiar with mmc, but I've some questions on sd below.

On Thu, Sep 15, 2011 at 05:50:38PM +0200, Ulf Hansson wrote:
 Earlier all cards where initiated with bus mode set as OPENDRAIN, and then
 later switched to PUSHPULL. According to the MMC/SD/SDIO specifications only
 MMC cards use OPENDRAIN during init. For both SD and SDIO the bus mode shall
 be PUSHPULL before attempting to init the card.
AFAIK, there is no open drain mode in sd, and the sd host controller
actually does not care about this setting(sdhci_set_ios does not
manipulate bus_mode stored in ios).
 
 The consequence of having incorrect bus mode can lead to not being able
 to detect the card. Therefore the default behavior have now been changed to
 PUSHPULL in mmc_power_up, and will only be temporarily switched when trying
 to attach or init a MMC card.
Do you see any sd cards that failed to be detected due to the incorrect
bus_mode setting?

Anyway, your patch removed an unnecessary call to mmc_set_bus_mode which
should have no effect if the underlying controller is sdhci.

-Aaron

--
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


Re: confusion regarding the CMD19 and CMD21 in eMMC/SD card spec

2011-09-15 Thread Aaron Lu
On Fri, Sep 16, 2011 at 11:00:12AM +0530, Girish K S wrote:
 Hello Aaron Lu,
Hi,

 please check the mmc 4.5 specification CMD21 is
 tuning command.

So you are using a mmc card with a sd host?

-Aaron

--
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


[PATCH] mmc: core: add sd uhs string for mmc_ios_show

2011-09-02 Thread Aaron Lu
This is a minor fix. It makes mmc_ios_show print proper string when the
host's timing is one of the newly added UHS-I modes.

Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/core/debugfs.c |9 +
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 5acd707..96c603b 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -114,6 +114,15 @@ static int mmc_ios_show(struct seq_file *s, void *data)
case MMC_TIMING_SD_HS:
str = sd high-speed;
break;
+   case MMC_TIMING_UHS_SDR50:
+   str = sd uhs SDR50;
+   break;
+   case MMC_TIMING_UHS_SDR104:
+   str = sd uhs SDR104;
+   break;
+   case MMC_TIMING_UHS_DDR50:
+   str = sd uhs DDR50;
+   break;
default:
str = invalid;
break;
-- 
1.7.4.4


--
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


[PATCH] mmc: sdhci: add support for re-tuning mode 2

2011-08-23 Thread Aaron Lu
Hosts which support re-tuning mode 2 has the capability to indicate
the re-tuning timing by issuing re-tuning request during data transfers.
During non-data transfers, re-tuning timing is determined by either
re-tuning timer or re-tuning request.

Since there is no way to determine the host's capability to generate
re-tuning request during non-data transfers, we will start the re-tuning
timer by default for re-tuning mode 2. If we ever received a re-tuning
request during non-data transfers, that means the host is also capable
of generating re-tuning request for non-data transfers, we will then
deactivate the re-tuning timer altogether.

The SDHCI_RETUNING_TIMER flag is added to indicate the fact that the
host requires re-tuning timer to trigger the re-tuning timing.

The SDHCI_NEEDS_RETUNING, SDHCI_RETUNING_TIMER flags and the max block
count of the host will be restored to their default values since they
are affected by different cards inserted too.

Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/host/sdhci.c  |  128 +
 drivers/mmc/host/sdhci.h  |3 +
 include/linux/mmc/sdhci.h |4 ++
 3 files changed, 102 insertions(+), 33 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0e02cc1..f620c72 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -222,6 +222,22 @@ static void sdhci_reinit(struct sdhci_host *host)
 {
sdhci_init(host, 0);
sdhci_enable_card_detection(host);
+
+   if (host-version = SDHCI_SPEC_300) {
+   /*
+* Clear re-tuning related flags, since these flags
+* are also affected by different cards inserted
+*/
+   host-flags = ~(SDHCI_NEEDS_RETUNING |
+   SDHCI_RETUNING_TIMER);
+
+   /*
+* restore max block count, since it might be
+* reduced due to re-tuning mode 1 and 2
+*/
+   host-mmc-max_blk_count =
+   (host-quirks  SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
+   }
 }
 
 static void sdhci_activate_led(struct sdhci_host *host)
@@ -1245,7 +1261,7 @@ static void sdhci_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
 
present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
/*
-* Check if the re-tuning timer has already expired and there
+* Check if the re-tuning timing has already arrived and there
 * is no on-going data transfer. If so, we need to execute
 * tuning procedure before sending command.
 */
@@ -1733,34 +1749,41 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
 
 out:
/*
-* If this is the very first time we are here, we start the retuning
-* timer. Since only during the first time, SDHCI_NEEDS_RETUNING
-* flag won't be set, we check this condition before actually starting
-* the timer.
+* If this is the very first time we are here, we setup the
+* corresponding re-tuning condition. Since only during the
+* first time, SDHCI_NEEDS_RETUNING flag won't be set.
 */
-   if (!(host-flags  SDHCI_NEEDS_RETUNING)  host-tuning_count 
-   (host-tuning_mode == SDHCI_TUNING_MODE_1)) {
-   mod_timer(host-tuning_timer, jiffies +
-   host-tuning_count * HZ);
-   /* Tuning mode 1 limits the maximum data length to 4MB */
-   mmc-max_blk_count = (4 * 1024 * 1024) / mmc-max_blk_size;
+   if (!(host-flags  SDHCI_NEEDS_RETUNING)) {
+   if (host-tuning_count 
+   host-tuning_mode != SDHCI_TUNING_MODE_RSV) {
+   host-flags |= SDHCI_RETUNING_TIMER;
+   mod_timer(host-tuning_timer, jiffies +
+   host-tuning_count * HZ);
+   }
+   /* Enable re-tuning event for tuning mode 2 */
+   if (host-tuning_mode == SDHCI_TUNING_MODE_2)
+   ier |= SDHCI_INT_RETUNING;
+   /* Tuning mode 1 and 2 limits the maximum data length to 4MB */
+   if (host-tuning_mode == SDHCI_TUNING_MODE_1 ||
+   host-tuning_mode == SDHCI_TUNING_MODE_2)
+   mmc-max_blk_count = (4 * 1024 * 1024) /
+   mmc-max_blk_size;
} else {
host-flags = ~SDHCI_NEEDS_RETUNING;
-   /* Reload the new initial value for timer */
-   if (host-tuning_mode == SDHCI_TUNING_MODE_1)
+   /* Reload the new initial value for re-tuning timer */
+   if (host-flags  SDHCI_RETUNING_TIMER)
mod_timer(host-tuning_timer, jiffies +
host-tuning_count * HZ);
}
 
/*
 * In case tuning fails, host

Re: [PATCH] mmc: sdhci: fix retuning timer wrongly deleted in sdhci_tasklet_finish

2011-07-21 Thread Aaron Lu
On Thu, Jul 21, 2011 at 05:35:02PM +0800, zhangfei gao wrote:
 
 Does the execute_tuning is called again?
 del_timer is not delete timer really, but deactivate the timer, which
 could be re-activated by mod_timer.
 So if execute_tuning is called, the mod_timer will tigger the tuning
 timer again.


Hi zhangfei,

Thanks for the comment.

The execute_tuning will be called at two places:
1 In mmc_sd_init_uhs_card, when host is initializing an UHS card,
and the re-tuning timer will be activated for the first time;
2 When re-tuning timer expired

So if the re-tuning timer is deactivated in sdhci_tasklet_finish,
execute_tuning will have no chance of getting called again, and the
host will not be able to do the re-tuning anymore.
 
  
   Signed-off-by: Aaron Lu aaron...@amd.com
   ---
    drivers/mmc/host/sdhci.c |    3 ---
    1 files changed, 0 insertions(+), 3 deletions(-)
  
   diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
   index 91d9892..6250bac 100644
   --- a/drivers/mmc/host/sdhci.c
   +++ b/drivers/mmc/host/sdhci.c
   @@ -1863,9 +1863,6 @@ static void sdhci_tasklet_finish(unsigned long
   param)
  
       del_timer(host-timer);
  
   -   if (host-version = SDHCI_SPEC_300)
   -           del_timer(host-tuning_timer);
   -
       mrq = host-mrq;
  
       /*
   --
   1.7.1
 
 
 
 
 

--
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


Re: [PATCH] mmc: sdhci: fix retuning timer wrongly deleted in sdhci_tasklet_finish

2011-07-21 Thread Aaron Lu
Hi Philip,

On Thu, Jul 21, 2011 at 01:27:11PM -0700, Philip Rakity wrote:
 
 Aaron,
 
 Code is fine.
Thanks.

 Do you want to also fix the problem with suspend or should I do the patch ?
 When we are suspending we should kill the tuning timer.
Yes, that is a problem.

I've another patch to add support for re-tuning mode 2 queued for
submit which should have fixed this problem, but I didn't touch anything
if mmc_suspend_host failed, so when I submit the other patch, please
take you time to review it and let's see how we can fix the problem
altogether :-)

 
 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
 index 4da6a4d..88c25e8 100644
 --- a/drivers/mmc/host/sdhci.c
 +++ b/drivers/mmc/host/sdhci.c
 @@ -2289,18 +2289,14 @@ int sdhci_suspend_host(struct sdhci_host *host, 
 pm_message_t state)
  
   sdhci_disable_card_detection(host);
  
 - /* Disable tuning since we are suspending */
 - if (host-version = SDHCI_SPEC_300  host-tuning_count 
 - host-tuning_mode == SDHCI_TUNING_MODE_1) {
 - host-flags = ~SDHCI_NEEDS_RETUNING;
 - mod_timer(host-tuning_timer, jiffies +
 - host-tuning_count * HZ);
 - }
 -
   ret = mmc_suspend_host(host-mmc);
   if (ret)
   return ret;
  
 + /* Disable tuning since we are suspending */
 + if (host-version = SDHCI_SPEC_300)
 + del_timer_sync(host-tuning_timer);
 +
   free_irq(host-irq, host);
  
   if (host-vmmc)
 
 
 
 Philip
 
 On Jul 21, 2011, at 3:03 AM, Aaron Lu wrote:
 
  On Thu, Jul 21, 2011 at 05:35:02PM +0800, zhangfei gao wrote:
  
  Does the execute_tuning is called again?
  del_timer is not delete timer really, but deactivate the timer, which
  could be re-activated by mod_timer.
  So if execute_tuning is called, the mod_timer will tigger the tuning
  timer again.
  
  
  Hi zhangfei,
  
  Thanks for the comment.
  
  The execute_tuning will be called at two places:
  1 In mmc_sd_init_uhs_card, when host is initializing an UHS card,
  and the re-tuning timer will be activated for the first time;
  2 When re-tuning timer expired
  
  So if the re-tuning timer is deactivated in sdhci_tasklet_finish,
  execute_tuning will have no chance of getting called again, and the
  host will not be able to do the re-tuning anymore.
  
  
  Signed-off-by: Aaron Lu aaron...@amd.com
  ---
   drivers/mmc/host/sdhci.c |3 ---
   1 files changed, 0 insertions(+), 3 deletions(-)
  
  diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
  index 91d9892..6250bac 100644
  --- a/drivers/mmc/host/sdhci.c
  +++ b/drivers/mmc/host/sdhci.c
  @@ -1863,9 +1863,6 @@ static void sdhci_tasklet_finish(unsigned long
  param)
  
  del_timer(host-timer);
  
  -   if (host-version = SDHCI_SPEC_300)
  -   del_timer(host-tuning_timer);
  -
  mrq = host-mrq;
  
  /*
  --
  1.7.1
  
  
  
  
  
  
 
 

--
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


[PATCH] mmc: sdhci: fix retuning timer wrongly deleted in sdhci_tasklet_finish

2011-07-10 Thread Aaron Lu
Currently, the retuning timer for retuning mode 1 will be deleted in
function sdhci_tasklet_finish after a mmc request done, which will make
retuning timing never trigger again. This patch fixed this problem.

Signed-off-by: Aaron Lu aaron...@amd.com
---
 drivers/mmc/host/sdhci.c |3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 91d9892..6250bac 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1863,9 +1863,6 @@ static void sdhci_tasklet_finish(unsigned long param)
 
del_timer(host-timer);
 
-   if (host-version = SDHCI_SPEC_300)
-   del_timer(host-tuning_timer);
-
mrq = host-mrq;
 
/*
-- 
1.7.1


--
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