diff mbox

[v2,2/2] mmc: core: Add Poweroff Notify handling

Message ID 1315306767-9549-3-git-send-email-girish.shivananjappa@linaro.org
State New
Headers show

Commit Message

Girish K S Sept. 6, 2011, 10:59 a.m. UTC
This patch adds the power off notification handling
during suspend and system poweroff.
For suspend mode short timeout is used, whereas for the
normal poweroff long timeout is used.

Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
---
 drivers/mmc/core/core.c  |   33 +++++++++++++++++++++++++++++++++
 drivers/mmc/core/mmc.c   |    4 +++-
 drivers/mmc/host/sdhci.c |   10 ++++++++++
 include/linux/mmc/card.h |   19 +++++++++++++++++++
 include/linux/mmc/host.h |    4 ++++
 5 files changed, 69 insertions(+), 1 deletions(-)

Comments

Seungwon Jeon Sept. 6, 2011, 11:52 a.m. UTC | #1
Hi Girish,

In case of system poweroff, mmc_power_off can be called indeed?
And I added some comments.

Best regards,
Seungwon Jeon.

Girish K S wrote:
> 
> This patch adds the power off notification handling
> during suspend and system poweroff.
> For suspend mode short timeout is used, whereas for the
> normal poweroff long timeout is used.
> 
> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> ---
>  drivers/mmc/core/core.c  |   33 +++++++++++++++++++++++++++++++++
>  drivers/mmc/core/mmc.c   |    4 +++-
>  drivers/mmc/host/sdhci.c |   10 ++++++++++
>  include/linux/mmc/card.h |   19 +++++++++++++++++++
>  include/linux/mmc/host.h |    4 ++++
>  5 files changed, 69 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index a65e1ca..16da927 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -1130,9 +1130,38 @@ static void mmc_power_up(struct mmc_host *host)
> 
>  static void mmc_power_off(struct mmc_host *host)
>  {
> +	struct mmc_card *card = host->card;
> +	unsigned int notify_type;
> +	unsigned int timeout;
> +	int err;
> +
>  	host->ios.clock = 0;
>  	host->ios.vdd = 0;
> 
> +	if (mmc_card_mmc(card) &&
> +		(mmc_card_powernotify_on(card))) {
> +
> +		if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
> +			notify_type = EXT_CSD_POWER_OFF_SHORT;
> +			timeout = card->ext_csd.generic_cmd6_time;
> +			mmc_card_set_powernotify_short(card);
> +		} else {
> +			notify_type = EXT_CSD_POWER_OFF_LONG;
> +			timeout = card->ext_csd.power_off_longtime;
> +			mmc_card_set_powernotify_long(card);
> +		}
> +
> +		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> +				EXT_CSD_POWER_OFF_NOTIFICATION,
> +				notify_type, timeout);
> +
> +		if (err && err != -EBADMSG)
> +			printk(KERN_ERR "Device failed to respond "
> +					"within %d poweroff time."
> +					"forcefully powering down"
> +					"the device\n", timeout);
> +	}
> +
It'd be fine if one function take it above all.

>  	/*
>  	 * Reset ocr mask to be the highest possible voltage supported for
>  	 * this mmc host. This value will be used at next power up.
> @@ -1147,6 +1176,8 @@ static void mmc_power_off(struct mmc_host *host)
>  	host->ios.bus_width = MMC_BUS_WIDTH_1;
>  	host->ios.timing = MMC_TIMING_LEGACY;
>  	mmc_set_ios(host);
> +	/*Set the card state to no notification after the poweroff*/
> +	mmc_card_set_powernotify_off(card);
>  }
> 
>  /*
> @@ -2026,6 +2057,7 @@ int mmc_pm_notify(struct notifier_block
> *notify_block,
> 
>  		spin_lock_irqsave(&host->lock, flags);
>  		host->rescan_disable = 1;
> +		host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
>  		spin_unlock_irqrestore(&host->lock, flags);
>  		cancel_delayed_work_sync(&host->detect);
> 
> @@ -2048,6 +2080,7 @@ int mmc_pm_notify(struct notifier_block
> *notify_block,
> 
>  		spin_lock_irqsave(&host->lock, flags);
>  		host->rescan_disable = 0;
> +		host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
>  		spin_unlock_irqrestore(&host->lock, flags);
>  		mmc_detect_change(host, 0);
> 
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 2f06b37..8868da8 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -715,13 +715,15 @@ static int mmc_init_card(struct mmc_host *host, u32
> ocr,
>  	 * If the host supports the power_off_notify capability then
>  	 * set the notification byte in the ext_csd register of device
>  	 */
> -	if (host->caps & MMC_CAP_POWER_OFF_NOTIFY) {
> +	if ((host->caps & MMC_CAP_POWER_OFF_NOTIFY)	&&
> +		(mmc_card_powernotify_off(card))) {

Previous version seems to be good. 

>  		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>  				EXT_CSD_POWER_OFF_NOTIFICATION,
>  				EXT_CSD_POWER_ON,
>  				card->ext_csd.generic_cmd6_time);
>  		if (err && err != -EBADMSG)
>  			goto free_card;
> +		mmc_card_set_powernotify_on(card);

If err is -EBADMSG, switching for 'POWERED_ON' is maybe failed.
It is sure to be successful?
So, your state flag should be changed to 'off'

>  	}
> 
>  	/*
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 0e02cc1..2ca427a 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2566,6 +2566,16 @@ int sdhci_add_host(struct sdhci_host *host)
>  	if (caps[1] & SDHCI_DRIVER_TYPE_D)
>  		mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
> 
> +	/*
> +	 * If Notify capability is enabled and
> +	 * notify type is not initialised by host, set default to
> +	 * long power off notify timeout value
> +	 */
> +	if (mmc->caps == MMC_CAP_POWER_OFF_NOTIFY)
> +		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
> +	else
> +		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
> +
>  	/* Initial value for re-tuning timer count */
>  	host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
>  			      SDHCI_RETUNING_TIMER_COUNT_SHIFT;
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index 2bf2843..1d6a832 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -190,6 +190,11 @@ struct mmc_card {
>  #define MMC_QUIRK_DISABLE_CD	(1<<5)		/* disconnect CD/DAT[3]
> resistor */
>  #define MMC_QUIRK_INAND_CMD38	(1<<6)		/* iNAND devices have
> broken CMD38 */
>  #define MMC_QUIRK_BLK_NO_CMD23	(1<<7)		/* Avoid CMD23 for regular
> multiblock */
> +	unsigned int    poweroff_notify_state;/*eMMC4.5 notify feature  */
> +#define MMC_NO_POWER_NOTIFICATION  0
> +#define MMC_POWERED_ON     1
> +#define MMC_POWEROFF_SHORT 2
> +#define MMC_POWEROFF_LONG  3
> 
>  	unsigned int		erase_size;	/* erase size in sectors */
>   	unsigned int		erase_shift;	/* if erase unit is power 2 */
> @@ -325,6 +330,20 @@ static inline void __maybe_unused remove_quirk(struct
> mmc_card *card, int data)
>  #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
>  #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
> 
> +#define mmc_card_powernotify_on(c)     \
> +		((c)->poweroff_notify_state == MMC_POWERED_ON)
> +#define mmc_card_powernotify_off(c)    \
> +		((c)->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)
> +
> +#define mmc_card_set_powernotify_off(c)    \
> +		((c)->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION)
> +#define mmc_card_set_powernotify_on(c) \
> +		((c)->poweroff_notify_state = MMC_POWERED_ON)
> +#define mmc_card_set_powernotify_short(c)  \
> +		((c)->poweroff_notify_state = MMC_POWEROFF_SHORT)
> +#define mmc_card_set_powernotify_long(c)   \
> +		((c)->poweroff_notify_state = MMC_POWEROFF_LONG)
> +
>  /*
>   * Quirk add/remove for MMC products.
>   */
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index cf2dadc..4f24702 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -232,6 +232,10 @@ struct mmc_host {
>  #define MMC_CAP_POWER_OFF_NOTIFY    (1 << 31)/*Notify poweroff supported
> */
> 
>  	mmc_pm_flag_t		pm_caps;	/* supported pm features */
> +	unsigned int        power_notify_type;
> +#define MMC_HOST_PW_NOTIFY_NONE	0
> +#define MMC_HOST_PW_NOTIFY_SHORT	1
> +#define MMC_HOST_PW_NOTIFY_LONG	2
> 
>  #ifdef CONFIG_MMC_CLKGATE
>  	int			clk_requests;	/* internal reference counter */
> --
> 1.7.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Girish K S Sept. 6, 2011, 12:11 p.m. UTC | #2
Hi Jeon,
Thanks for the review.

On 6 September 2011 17:22, Seungwon Jeon <tgih.jun@samsung.com> wrote:
> Hi Girish,
>
> In case of system poweroff, mmc_power_off can be called indeed?
> And I added some comments.
>
> Best regards,
> Seungwon Jeon.
>
> Girish K S wrote:
>>
>> This patch adds the power off notification handling
>> during suspend and system poweroff.
>> For suspend mode short timeout is used, whereas for the
>> normal poweroff long timeout is used.
>>
>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>> ---
>>  drivers/mmc/core/core.c  |   33 +++++++++++++++++++++++++++++++++
>>  drivers/mmc/core/mmc.c   |    4 +++-
>>  drivers/mmc/host/sdhci.c |   10 ++++++++++
>>  include/linux/mmc/card.h |   19 +++++++++++++++++++
>>  include/linux/mmc/host.h |    4 ++++
>>  5 files changed, 69 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>> index a65e1ca..16da927 100644
>> --- a/drivers/mmc/core/core.c
>> +++ b/drivers/mmc/core/core.c
>> @@ -1130,9 +1130,38 @@ static void mmc_power_up(struct mmc_host *host)
>>
>>  static void mmc_power_off(struct mmc_host *host)
>>  {
>> +     struct mmc_card *card = host->card;
>> +     unsigned int notify_type;
>> +     unsigned int timeout;
>> +     int err;
>> +
>>       host->ios.clock = 0;
>>       host->ios.vdd = 0;
>>
>> +     if (mmc_card_mmc(card) &&
>> +             (mmc_card_powernotify_on(card))) {
>> +
>> +             if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
>> +                     notify_type = EXT_CSD_POWER_OFF_SHORT;
>> +                     timeout = card->ext_csd.generic_cmd6_time;
>> +                     mmc_card_set_powernotify_short(card);
>> +             } else {
>> +                     notify_type = EXT_CSD_POWER_OFF_LONG;
>> +                     timeout = card->ext_csd.power_off_longtime;
>> +                     mmc_card_set_powernotify_long(card);
>> +             }
>> +
>> +             err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> +                             EXT_CSD_POWER_OFF_NOTIFICATION,
>> +                             notify_type, timeout);
>> +
>> +             if (err && err != -EBADMSG)
>> +                     printk(KERN_ERR "Device failed to respond "
>> +                                     "within %d poweroff time."
>> +                                     "forcefully powering down"
>> +                                     "the device\n", timeout);
>> +     }
>> +
> It'd be fine if one function take it above all.
I change the state to off after the host executes the poweroff function.
i.e. after complete device power off.
>
>>       /*
>>        * Reset ocr mask to be the highest possible voltage supported for
>>        * this mmc host. This value will be used at next power up.
>> @@ -1147,6 +1176,8 @@ static void mmc_power_off(struct mmc_host *host)
>>       host->ios.bus_width = MMC_BUS_WIDTH_1;
>>       host->ios.timing = MMC_TIMING_LEGACY;
>>       mmc_set_ios(host);
>> +     /*Set the card state to no notification after the poweroff*/
>> +     mmc_card_set_powernotify_off(card);
>>  }
>>
>>  /*
>> @@ -2026,6 +2057,7 @@ int mmc_pm_notify(struct notifier_block
>> *notify_block,
>>
>>               spin_lock_irqsave(&host->lock, flags);
>>               host->rescan_disable = 1;
>> +             host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
>>               spin_unlock_irqrestore(&host->lock, flags);
>>               cancel_delayed_work_sync(&host->detect);
>>
>> @@ -2048,6 +2080,7 @@ int mmc_pm_notify(struct notifier_block
>> *notify_block,
>>
>>               spin_lock_irqsave(&host->lock, flags);
>>               host->rescan_disable = 0;
>> +             host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
>>               spin_unlock_irqrestore(&host->lock, flags);
>>               mmc_detect_change(host, 0);
>>
>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> index 2f06b37..8868da8 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -715,13 +715,15 @@ static int mmc_init_card(struct mmc_host *host, u32
>> ocr,
>>        * If the host supports the power_off_notify capability then
>>        * set the notification byte in the ext_csd register of device
>>        */
>> -     if (host->caps & MMC_CAP_POWER_OFF_NOTIFY) {
>> +     if ((host->caps & MMC_CAP_POWER_OFF_NOTIFY)     &&
>> +             (mmc_card_powernotify_off(card))) {
>
> Previous version seems to be good.
>
>>               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>>                               EXT_CSD_POWER_OFF_NOTIFICATION,
>>                               EXT_CSD_POWER_ON,
>>                               card->ext_csd.generic_cmd6_time);
>>               if (err && err != -EBADMSG)
>>                       goto free_card;
>> +             mmc_card_set_powernotify_on(card);
>
> If err is -EBADMSG, switching for 'POWERED_ON' is maybe failed.
> It is sure to be successful?
> So, your state flag should be changed to 'off'
If err is  -EBADMSG then the state remains off. it will change only if
successful.
>
>>       }
>>
>>       /*
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 0e02cc1..2ca427a 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2566,6 +2566,16 @@ int sdhci_add_host(struct sdhci_host *host)
>>       if (caps[1] & SDHCI_DRIVER_TYPE_D)
>>               mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
>>
>> +     /*
>> +      * If Notify capability is enabled and
>> +      * notify type is not initialised by host, set default to
>> +      * long power off notify timeout value
>> +      */
>> +     if (mmc->caps == MMC_CAP_POWER_OFF_NOTIFY)
>> +             mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
>> +     else
>> +             mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
>> +
>>       /* Initial value for re-tuning timer count */
>>       host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
>>                             SDHCI_RETUNING_TIMER_COUNT_SHIFT;
>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>> index 2bf2843..1d6a832 100644
>> --- a/include/linux/mmc/card.h
>> +++ b/include/linux/mmc/card.h
>> @@ -190,6 +190,11 @@ struct mmc_card {
>>  #define MMC_QUIRK_DISABLE_CD (1<<5)          /* disconnect CD/DAT[3]
>> resistor */
>>  #define MMC_QUIRK_INAND_CMD38        (1<<6)          /* iNAND devices have
>> broken CMD38 */
>>  #define MMC_QUIRK_BLK_NO_CMD23       (1<<7)          /* Avoid CMD23 for regular
>> multiblock */
>> +     unsigned int    poweroff_notify_state;/*eMMC4.5 notify feature  */
>> +#define MMC_NO_POWER_NOTIFICATION  0
>> +#define MMC_POWERED_ON     1
>> +#define MMC_POWEROFF_SHORT 2
>> +#define MMC_POWEROFF_LONG  3
>>
>>       unsigned int            erase_size;     /* erase size in sectors */
>>       unsigned int            erase_shift;    /* if erase unit is power 2 */
>> @@ -325,6 +330,20 @@ static inline void __maybe_unused remove_quirk(struct
>> mmc_card *card, int data)
>>  #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
>>  #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
>>
>> +#define mmc_card_powernotify_on(c)     \
>> +             ((c)->poweroff_notify_state == MMC_POWERED_ON)
>> +#define mmc_card_powernotify_off(c)    \
>> +             ((c)->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)
>> +
>> +#define mmc_card_set_powernotify_off(c)    \
>> +             ((c)->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION)
>> +#define mmc_card_set_powernotify_on(c) \
>> +             ((c)->poweroff_notify_state = MMC_POWERED_ON)
>> +#define mmc_card_set_powernotify_short(c)  \
>> +             ((c)->poweroff_notify_state = MMC_POWEROFF_SHORT)
>> +#define mmc_card_set_powernotify_long(c)   \
>> +             ((c)->poweroff_notify_state = MMC_POWEROFF_LONG)
>> +
>>  /*
>>   * Quirk add/remove for MMC products.
>>   */
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> index cf2dadc..4f24702 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -232,6 +232,10 @@ struct mmc_host {
>>  #define MMC_CAP_POWER_OFF_NOTIFY    (1 << 31)/*Notify poweroff supported
>> */
>>
>>       mmc_pm_flag_t           pm_caps;        /* supported pm features */
>> +     unsigned int        power_notify_type;
>> +#define MMC_HOST_PW_NOTIFY_NONE      0
>> +#define MMC_HOST_PW_NOTIFY_SHORT     1
>> +#define MMC_HOST_PW_NOTIFY_LONG      2
>>
>>  #ifdef CONFIG_MMC_CLKGATE
>>       int                     clk_requests;   /* internal reference counter */
>> --
>> 1.7.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
Kyungmin Park Sept. 7, 2011, 1:49 a.m. UTC | #3
On Tue, Sep 6, 2011 at 7:59 PM, Girish K S
<girish.shivananjappa@linaro.org> wrote:
> This patch adds the power off notification handling
> during suspend and system poweroff.
> For suspend mode short timeout is used, whereas for the
> normal poweroff long timeout is used.
>
> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> ---
>  drivers/mmc/core/core.c  |   33 +++++++++++++++++++++++++++++++++
>  drivers/mmc/core/mmc.c   |    4 +++-
>  drivers/mmc/host/sdhci.c |   10 ++++++++++
>  include/linux/mmc/card.h |   19 +++++++++++++++++++
>  include/linux/mmc/host.h |    4 ++++
>  5 files changed, 69 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
> index a65e1ca..16da927 100644
> --- a/drivers/mmc/core/core.c
> +++ b/drivers/mmc/core/core.c
> @@ -1130,9 +1130,38 @@ static void mmc_power_up(struct mmc_host *host)
>
>  static void mmc_power_off(struct mmc_host *host)
>  {
> +       struct mmc_card *card = host->card;
> +       unsigned int notify_type;
> +       unsigned int timeout;
> +       int err;
> +
>        host->ios.clock = 0;
>        host->ios.vdd = 0;
>
> +       if (mmc_card_mmc(card) &&
> +               (mmc_card_powernotify_on(card))) {
> +
> +               if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
> +                       notify_type = EXT_CSD_POWER_OFF_SHORT;
> +                       timeout = card->ext_csd.generic_cmd6_time;
> +                       mmc_card_set_powernotify_short(card);
> +               } else {
> +                       notify_type = EXT_CSD_POWER_OFF_LONG;
> +                       timeout = card->ext_csd.power_off_longtime;
> +                       mmc_card_set_powernotify_long(card);
> +               }
> +
> +               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
> +                               EXT_CSD_POWER_OFF_NOTIFICATION,
> +                               notify_type, timeout);
> +
> +               if (err && err != -EBADMSG)
> +                       printk(KERN_ERR "Device failed to respond "
> +                                       "within %d poweroff time."
> +                                       "forcefully powering down"
> +                                       "the device\n", timeout);
> +       }
> +
Okay this function is called when suspend.
>        /*
>         * Reset ocr mask to be the highest possible voltage supported for
>         * this mmc host. This value will be used at next power up.
> @@ -1147,6 +1176,8 @@ static void mmc_power_off(struct mmc_host *host)
>        host->ios.bus_width = MMC_BUS_WIDTH_1;
>        host->ios.timing = MMC_TIMING_LEGACY;
>        mmc_set_ios(host);
> +       /*Set the card state to no notification after the poweroff*/
> +       mmc_card_set_powernotify_off(card);
>  }
>
>  /*
> @@ -2026,6 +2057,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
>
>                spin_lock_irqsave(&host->lock, flags);
>                host->rescan_disable = 1;
> +               host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
>                spin_unlock_irqrestore(&host->lock, flags);
>                cancel_delayed_work_sync(&host->detect);
>
> @@ -2048,6 +2080,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
>
>                spin_lock_irqsave(&host->lock, flags);
>                host->rescan_disable = 0;
> +               host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
>                spin_unlock_irqrestore(&host->lock, flags);
>                mmc_detect_change(host, 0);
>
> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
> index 2f06b37..8868da8 100644
> --- a/drivers/mmc/core/mmc.c
> +++ b/drivers/mmc/core/mmc.c
> @@ -715,13 +715,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>         * If the host supports the power_off_notify capability then
>         * set the notification byte in the ext_csd register of device
>         */
> -       if (host->caps & MMC_CAP_POWER_OFF_NOTIFY) {
> +       if ((host->caps & MMC_CAP_POWER_OFF_NOTIFY)     &&
> +               (mmc_card_powernotify_off(card))) {
>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>                                EXT_CSD_POWER_OFF_NOTIFICATION,
>                                EXT_CSD_POWER_ON,
>                                card->ext_csd.generic_cmd6_time);
>                if (err && err != -EBADMSG)
>                        goto free_card;
> +               mmc_card_set_powernotify_on(card);
>        }
>
>        /*
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 0e02cc1..2ca427a 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2566,6 +2566,16 @@ int sdhci_add_host(struct sdhci_host *host)
>        if (caps[1] & SDHCI_DRIVER_TYPE_D)
>                mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
>
> +       /*
> +        * If Notify capability is enabled and
> +        * notify type is not initialised by host, set default to
> +        * long power off notify timeout value
> +        */
> +       if (mmc->caps == MMC_CAP_POWER_OFF_NOTIFY)
You should be check the mmc->caps & MMC_CAP_*. I think it's almost false.
> +               mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
> +       else
> +               mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
> +
>        /* Initial value for re-tuning timer count */
>        host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
>                              SDHCI_RETUNING_TIMER_COUNT_SHIFT;
> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
> index 2bf2843..1d6a832 100644
> --- a/include/linux/mmc/card.h
> +++ b/include/linux/mmc/card.h
> @@ -190,6 +190,11 @@ struct mmc_card {
>  #define MMC_QUIRK_DISABLE_CD   (1<<5)          /* disconnect CD/DAT[3] resistor */
>  #define MMC_QUIRK_INAND_CMD38  (1<<6)          /* iNAND devices have broken CMD38 */
>  #define MMC_QUIRK_BLK_NO_CMD23 (1<<7)          /* Avoid CMD23 for regular multiblock */
> +       unsigned int    poweroff_notify_state;/*eMMC4.5 notify feature  */
> +#define MMC_NO_POWER_NOTIFICATION  0
> +#define MMC_POWERED_ON     1
> +#define MMC_POWEROFF_SHORT 2
> +#define MMC_POWEROFF_LONG  3
>
>        unsigned int            erase_size;     /* erase size in sectors */
>        unsigned int            erase_shift;    /* if erase unit is power 2 */
> @@ -325,6 +330,20 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
>  #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
>  #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
>
> +#define mmc_card_powernotify_on(c)     \
> +               ((c)->poweroff_notify_state == MMC_POWERED_ON)
> +#define mmc_card_powernotify_off(c)    \
> +               ((c)->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)
> +
> +#define mmc_card_set_powernotify_off(c)    \
> +               ((c)->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION)
> +#define mmc_card_set_powernotify_on(c) \
> +               ((c)->poweroff_notify_state = MMC_POWERED_ON)
> +#define mmc_card_set_powernotify_short(c)  \
> +               ((c)->poweroff_notify_state = MMC_POWEROFF_SHORT)
> +#define mmc_card_set_powernotify_long(c)   \
> +               ((c)->poweroff_notify_state = MMC_POWEROFF_LONG)
> +
>  /*
>  * Quirk add/remove for MMC products.
>  */
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index cf2dadc..4f24702 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -232,6 +232,10 @@ struct mmc_host {
>  #define MMC_CAP_POWER_OFF_NOTIFY    (1 << 31)/*Notify poweroff supported */
>
>        mmc_pm_flag_t           pm_caps;        /* supported pm features */
> +       unsigned int        power_notify_type;
> +#define MMC_HOST_PW_NOTIFY_NONE        0
> +#define MMC_HOST_PW_NOTIFY_SHORT       1
> +#define MMC_HOST_PW_NOTIFY_LONG        2

> +#define MMC_NO_POWER_NOTIFICATION  0
> +#define MMC_POWERED_ON     1
> +#define MMC_POWEROFF_SHORT 2
> +#define MMC_POWEROFF_LONG  3

I think you can make one macros.

>
>  #ifdef CONFIG_MMC_CLKGATE
>        int                     clk_requests;   /* internal reference counter */
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
Girish K S Sept. 7, 2011, 3:57 a.m. UTC | #4
On 7 September 2011 07:19, Kyungmin Park <kmpark@infradead.org> wrote:
> On Tue, Sep 6, 2011 at 7:59 PM, Girish K S
> <girish.shivananjappa@linaro.org> wrote:
>> This patch adds the power off notification handling
>> during suspend and system poweroff.
>> For suspend mode short timeout is used, whereas for the
>> normal poweroff long timeout is used.
>>
>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>> ---
>>  drivers/mmc/core/core.c  |   33 +++++++++++++++++++++++++++++++++
>>  drivers/mmc/core/mmc.c   |    4 +++-
>>  drivers/mmc/host/sdhci.c |   10 ++++++++++
>>  include/linux/mmc/card.h |   19 +++++++++++++++++++
>>  include/linux/mmc/host.h |    4 ++++
>>  5 files changed, 69 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>> index a65e1ca..16da927 100644
>> --- a/drivers/mmc/core/core.c
>> +++ b/drivers/mmc/core/core.c
>> @@ -1130,9 +1130,38 @@ static void mmc_power_up(struct mmc_host *host)
>>
>>  static void mmc_power_off(struct mmc_host *host)
>>  {
>> +       struct mmc_card *card = host->card;
>> +       unsigned int notify_type;
>> +       unsigned int timeout;
>> +       int err;
>> +
>>        host->ios.clock = 0;
>>        host->ios.vdd = 0;
>>
>> +       if (mmc_card_mmc(card) &&
>> +               (mmc_card_powernotify_on(card))) {
>> +
>> +               if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
>> +                       notify_type = EXT_CSD_POWER_OFF_SHORT;
>> +                       timeout = card->ext_csd.generic_cmd6_time;
>> +                       mmc_card_set_powernotify_short(card);
>> +               } else {
>> +                       notify_type = EXT_CSD_POWER_OFF_LONG;
>> +                       timeout = card->ext_csd.power_off_longtime;
>> +                       mmc_card_set_powernotify_long(card);
>> +               }
>> +
>> +               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>> +                               EXT_CSD_POWER_OFF_NOTIFICATION,
>> +                               notify_type, timeout);
>> +
>> +               if (err && err != -EBADMSG)
>> +                       printk(KERN_ERR "Device failed to respond "
>> +                                       "within %d poweroff time."
>> +                                       "forcefully powering down"
>> +                                       "the device\n", timeout);
>> +       }
>> +
> Okay this function is called when suspend.
>>        /*
>>         * Reset ocr mask to be the highest possible voltage supported for
>>         * this mmc host. This value will be used at next power up.
>> @@ -1147,6 +1176,8 @@ static void mmc_power_off(struct mmc_host *host)
>>        host->ios.bus_width = MMC_BUS_WIDTH_1;
>>        host->ios.timing = MMC_TIMING_LEGACY;
>>        mmc_set_ios(host);
>> +       /*Set the card state to no notification after the poweroff*/
>> +       mmc_card_set_powernotify_off(card);
>>  }
>>
>>  /*
>> @@ -2026,6 +2057,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
>>
>>                spin_lock_irqsave(&host->lock, flags);
>>                host->rescan_disable = 1;
>> +               host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
>>                spin_unlock_irqrestore(&host->lock, flags);
>>                cancel_delayed_work_sync(&host->detect);
>>
>> @@ -2048,6 +2080,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
>>
>>                spin_lock_irqsave(&host->lock, flags);
>>                host->rescan_disable = 0;
>> +               host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
>>                spin_unlock_irqrestore(&host->lock, flags);
>>                mmc_detect_change(host, 0);
>>
>> diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
>> index 2f06b37..8868da8 100644
>> --- a/drivers/mmc/core/mmc.c
>> +++ b/drivers/mmc/core/mmc.c
>> @@ -715,13 +715,15 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
>>         * If the host supports the power_off_notify capability then
>>         * set the notification byte in the ext_csd register of device
>>         */
>> -       if (host->caps & MMC_CAP_POWER_OFF_NOTIFY) {
>> +       if ((host->caps & MMC_CAP_POWER_OFF_NOTIFY)     &&
>> +               (mmc_card_powernotify_off(card))) {
>>                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
>>                                EXT_CSD_POWER_OFF_NOTIFICATION,
>>                                EXT_CSD_POWER_ON,
>>                                card->ext_csd.generic_cmd6_time);
>>                if (err && err != -EBADMSG)
>>                        goto free_card;
>> +               mmc_card_set_powernotify_on(card);
>>        }
>>
>>        /*
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 0e02cc1..2ca427a 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2566,6 +2566,16 @@ int sdhci_add_host(struct sdhci_host *host)
>>        if (caps[1] & SDHCI_DRIVER_TYPE_D)
>>                mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
>>
>> +       /*
>> +        * If Notify capability is enabled and
>> +        * notify type is not initialised by host, set default to
>> +        * long power off notify timeout value
>> +        */
>> +       if (mmc->caps == MMC_CAP_POWER_OFF_NOTIFY)
> You should be check the mmc->caps & MMC_CAP_*. I think it's almost false.
oops.. will change it.
>> +               mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
>> +       else
>> +               mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
>> +
>>        /* Initial value for re-tuning timer count */
>>        host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
>>                              SDHCI_RETUNING_TIMER_COUNT_SHIFT;
>> diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
>> index 2bf2843..1d6a832 100644
>> --- a/include/linux/mmc/card.h
>> +++ b/include/linux/mmc/card.h
>> @@ -190,6 +190,11 @@ struct mmc_card {
>>  #define MMC_QUIRK_DISABLE_CD   (1<<5)          /* disconnect CD/DAT[3] resistor */
>>  #define MMC_QUIRK_INAND_CMD38  (1<<6)          /* iNAND devices have broken CMD38 */
>>  #define MMC_QUIRK_BLK_NO_CMD23 (1<<7)          /* Avoid CMD23 for regular multiblock */
>> +       unsigned int    poweroff_notify_state;/*eMMC4.5 notify feature  */
>> +#define MMC_NO_POWER_NOTIFICATION  0
>> +#define MMC_POWERED_ON     1
>> +#define MMC_POWEROFF_SHORT 2
>> +#define MMC_POWEROFF_LONG  3
>>
>>        unsigned int            erase_size;     /* erase size in sectors */
>>        unsigned int            erase_shift;    /* if erase unit is power 2 */
>> @@ -325,6 +330,20 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
>>  #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
>>  #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
>>
>> +#define mmc_card_powernotify_on(c)     \
>> +               ((c)->poweroff_notify_state == MMC_POWERED_ON)
>> +#define mmc_card_powernotify_off(c)    \
>> +               ((c)->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)
>> +
>> +#define mmc_card_set_powernotify_off(c)    \
>> +               ((c)->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION)
>> +#define mmc_card_set_powernotify_on(c) \
>> +               ((c)->poweroff_notify_state = MMC_POWERED_ON)
>> +#define mmc_card_set_powernotify_short(c)  \
>> +               ((c)->poweroff_notify_state = MMC_POWEROFF_SHORT)
>> +#define mmc_card_set_powernotify_long(c)   \
>> +               ((c)->poweroff_notify_state = MMC_POWEROFF_LONG)
>> +
>>  /*
>>  * Quirk add/remove for MMC products.
>>  */
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> index cf2dadc..4f24702 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -232,6 +232,10 @@ struct mmc_host {
>>  #define MMC_CAP_POWER_OFF_NOTIFY    (1 << 31)/*Notify poweroff supported */
>>
>>        mmc_pm_flag_t           pm_caps;        /* supported pm features */
>> +       unsigned int        power_notify_type;
>> +#define MMC_HOST_PW_NOTIFY_NONE        0
>> +#define MMC_HOST_PW_NOTIFY_SHORT       1
>> +#define MMC_HOST_PW_NOTIFY_LONG        2
>
>> +#define MMC_NO_POWER_NOTIFICATION  0
>> +#define MMC_POWERED_ON     1
>> +#define MMC_POWEROFF_SHORT 2
>> +#define MMC_POWEROFF_LONG  3
>
> I think you can make one macros.
but these macros are in 2 different contexts  card and host.
if i make it a single macro pls suggest me a better place to define.
should it be host.h or card.h?


>
>>
>>  #ifdef CONFIG_MMC_CLKGATE
>>        int                     clk_requests;   /* internal reference counter */
>> --
>> 1.7.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
diff mbox

Patch

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a65e1ca..16da927 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1130,9 +1130,38 @@  static void mmc_power_up(struct mmc_host *host)
 
 static void mmc_power_off(struct mmc_host *host)
 {
+	struct mmc_card *card = host->card;
+	unsigned int notify_type;
+	unsigned int timeout;
+	int err;
+
 	host->ios.clock = 0;
 	host->ios.vdd = 0;
 
+	if (mmc_card_mmc(card) &&
+		(mmc_card_powernotify_on(card))) {
+
+		if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) {
+			notify_type = EXT_CSD_POWER_OFF_SHORT;
+			timeout = card->ext_csd.generic_cmd6_time;
+			mmc_card_set_powernotify_short(card);
+		} else {
+			notify_type = EXT_CSD_POWER_OFF_LONG;
+			timeout = card->ext_csd.power_off_longtime;
+			mmc_card_set_powernotify_long(card);
+		}
+
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_POWER_OFF_NOTIFICATION,
+				notify_type, timeout);
+
+		if (err && err != -EBADMSG)
+			printk(KERN_ERR "Device failed to respond "
+					"within %d poweroff time."
+					"forcefully powering down"
+					"the device\n", timeout);
+	}
+
 	/*
 	 * Reset ocr mask to be the highest possible voltage supported for
 	 * this mmc host. This value will be used at next power up.
@@ -1147,6 +1176,8 @@  static void mmc_power_off(struct mmc_host *host)
 	host->ios.bus_width = MMC_BUS_WIDTH_1;
 	host->ios.timing = MMC_TIMING_LEGACY;
 	mmc_set_ios(host);
+	/*Set the card state to no notification after the poweroff*/
+	mmc_card_set_powernotify_off(card);
 }
 
 /*
@@ -2026,6 +2057,7 @@  int mmc_pm_notify(struct notifier_block *notify_block,
 
 		spin_lock_irqsave(&host->lock, flags);
 		host->rescan_disable = 1;
+		host->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
 		spin_unlock_irqrestore(&host->lock, flags);
 		cancel_delayed_work_sync(&host->detect);
 
@@ -2048,6 +2080,7 @@  int mmc_pm_notify(struct notifier_block *notify_block,
 
 		spin_lock_irqsave(&host->lock, flags);
 		host->rescan_disable = 0;
+		host->power_notify_type = MMC_HOST_PW_NOTIFY_LONG;
 		spin_unlock_irqrestore(&host->lock, flags);
 		mmc_detect_change(host, 0);
 
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 2f06b37..8868da8 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -715,13 +715,15 @@  static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	 * If the host supports the power_off_notify capability then
 	 * set the notification byte in the ext_csd register of device
 	 */
-	if (host->caps & MMC_CAP_POWER_OFF_NOTIFY) {
+	if ((host->caps & MMC_CAP_POWER_OFF_NOTIFY)	&&
+		(mmc_card_powernotify_off(card))) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				EXT_CSD_POWER_OFF_NOTIFICATION,
 				EXT_CSD_POWER_ON,
 				card->ext_csd.generic_cmd6_time);
 		if (err && err != -EBADMSG)
 			goto free_card;
+		mmc_card_set_powernotify_on(card);
 	}
 
 	/*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0e02cc1..2ca427a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2566,6 +2566,16 @@  int sdhci_add_host(struct sdhci_host *host)
 	if (caps[1] & SDHCI_DRIVER_TYPE_D)
 		mmc->caps |= MMC_CAP_DRIVER_TYPE_D;
 
+	/*
+	 * If Notify capability is enabled and
+	 * notify type is not initialised by host, set default to
+	 * long power off notify timeout value
+	 */
+	if (mmc->caps == MMC_CAP_POWER_OFF_NOTIFY)
+		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT;
+	else
+		mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE;
+
 	/* Initial value for re-tuning timer count */
 	host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >>
 			      SDHCI_RETUNING_TIMER_COUNT_SHIFT;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 2bf2843..1d6a832 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -190,6 +190,11 @@  struct mmc_card {
 #define MMC_QUIRK_DISABLE_CD	(1<<5)		/* disconnect CD/DAT[3] resistor */
 #define MMC_QUIRK_INAND_CMD38	(1<<6)		/* iNAND devices have broken CMD38 */
 #define MMC_QUIRK_BLK_NO_CMD23	(1<<7)		/* Avoid CMD23 for regular multiblock */
+	unsigned int    poweroff_notify_state;/*eMMC4.5 notify feature  */
+#define MMC_NO_POWER_NOTIFICATION  0
+#define MMC_POWERED_ON     1
+#define MMC_POWEROFF_SHORT 2
+#define MMC_POWEROFF_LONG  3
 
 	unsigned int		erase_size;	/* erase size in sectors */
  	unsigned int		erase_shift;	/* if erase unit is power 2 */
@@ -325,6 +330,20 @@  static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
 #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
 #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
 
+#define mmc_card_powernotify_on(c)     \
+		((c)->poweroff_notify_state == MMC_POWERED_ON)
+#define mmc_card_powernotify_off(c)    \
+		((c)->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)
+
+#define mmc_card_set_powernotify_off(c)    \
+		((c)->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION)
+#define mmc_card_set_powernotify_on(c) \
+		((c)->poweroff_notify_state = MMC_POWERED_ON)
+#define mmc_card_set_powernotify_short(c)  \
+		((c)->poweroff_notify_state = MMC_POWEROFF_SHORT)
+#define mmc_card_set_powernotify_long(c)   \
+		((c)->poweroff_notify_state = MMC_POWEROFF_LONG)
+
 /*
  * Quirk add/remove for MMC products.
  */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index cf2dadc..4f24702 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -232,6 +232,10 @@  struct mmc_host {
 #define MMC_CAP_POWER_OFF_NOTIFY    (1 << 31)/*Notify poweroff supported */
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
+	unsigned int        power_notify_type;
+#define MMC_HOST_PW_NOTIFY_NONE	0
+#define MMC_HOST_PW_NOTIFY_SHORT	1
+#define MMC_HOST_PW_NOTIFY_LONG	2
 
 #ifdef CONFIG_MMC_CLKGATE
 	int			clk_requests;	/* internal reference counter */