diff options
Diffstat (limited to 'include/linux/mmc/host.h')
-rw-r--r-- | include/linux/mmc/host.h | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 3e7615e9087..eaf36364b7d 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -11,6 +11,7 @@ #define LINUX_MMC_HOST_H #include <linux/leds.h> +#include <linux/sched.h> #include <linux/mmc/core.h> @@ -51,6 +52,35 @@ struct mmc_ios { }; struct mmc_host_ops { + /* + * Hosts that support power saving can use the 'enable' and 'disable' + * methods to exit and enter power saving states. 'enable' is called + * when the host is claimed and 'disable' is called (or scheduled with + * a delay) when the host is released. The 'disable' is scheduled if + * the disable delay set by 'mmc_set_disable_delay()' is non-zero, + * otherwise 'disable' is called immediately. 'disable' may be + * scheduled repeatedly, to permit ever greater power saving at the + * expense of ever greater latency to re-enable. Rescheduling is + * determined by the return value of the 'disable' method. A positive + * value gives the delay in milliseconds. + * + * In the case where a host function (like set_ios) may be called + * with or without the host claimed, enabling and disabling can be + * done directly and will nest correctly. Call 'mmc_host_enable()' and + * 'mmc_host_lazy_disable()' for this purpose, but note that these + * functions must be paired. + * + * Alternatively, 'mmc_host_enable()' may be paired with + * 'mmc_host_disable()' which calls 'disable' immediately. In this + * case the 'disable' method will be called with 'lazy' set to 0. + * This is mainly useful for error paths. + * + * Because lazy disable may be called from a work queue, the 'disable' + * method must claim the host when 'lazy' != 0, which will work + * correctly because recursion is detected and handled. + */ + int (*enable)(struct mmc_host *host); + int (*disable)(struct mmc_host *host, int lazy); void (*request)(struct mmc_host *host, struct mmc_request *req); /* * Avoid calling these three functions too often or in a "fast path", @@ -118,6 +148,9 @@ struct mmc_host { #define MMC_CAP_SPI (1 << 4) /* Talks only SPI protocols */ #define MMC_CAP_NEEDS_POLL (1 << 5) /* Needs polling for card-detection */ #define MMC_CAP_8_BIT_DATA (1 << 6) /* Can the host do 8 bit transfers */ +#define MMC_CAP_DISABLE (1 << 7) /* Can the host be disabled */ +#define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ +#define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ /* host specific block data */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */ @@ -142,9 +175,18 @@ struct mmc_host { unsigned int removed:1; /* host is being removed */ #endif + /* Only used with MMC_CAP_DISABLE */ + int enabled; /* host is enabled */ + int nesting_cnt; /* "enable" nesting count */ + int en_dis_recurs; /* detect recursion */ + unsigned int disable_delay; /* disable delay in msecs */ + struct delayed_work disable; /* disabling work */ + struct mmc_card *card; /* device attached to this host */ wait_queue_head_t wq; + struct task_struct *claimer; /* task that has host claimed */ + int claim_cnt; /* "claim" nesting count */ struct delayed_work detect; @@ -183,6 +225,9 @@ static inline void *mmc_priv(struct mmc_host *host) extern int mmc_suspend_host(struct mmc_host *, pm_message_t); extern int mmc_resume_host(struct mmc_host *); +extern void mmc_power_save_host(struct mmc_host *host); +extern void mmc_power_restore_host(struct mmc_host *host); + extern void mmc_detect_change(struct mmc_host *, unsigned long delay); extern void mmc_request_done(struct mmc_host *, struct mmc_request *); @@ -197,5 +242,19 @@ struct regulator; int mmc_regulator_get_ocrmask(struct regulator *supply); int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit); +int mmc_card_awake(struct mmc_host *host); +int mmc_card_sleep(struct mmc_host *host); +int mmc_card_can_sleep(struct mmc_host *host); + +int mmc_host_enable(struct mmc_host *host); +int mmc_host_disable(struct mmc_host *host); +int mmc_host_lazy_disable(struct mmc_host *host); + +static inline void mmc_set_disable_delay(struct mmc_host *host, + unsigned int disable_delay) +{ + host->disable_delay = disable_delay; +} + #endif |