diff options
Diffstat (limited to 'include/linux/mmc')
-rw-r--r-- | include/linux/mmc/card.h | 8 | ||||
-rw-r--r-- | include/linux/mmc/core.h | 1 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 68 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 32 | ||||
-rw-r--r-- | include/linux/mmc/sdio_func.h | 5 |
5 files changed, 114 insertions, 0 deletions
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 403aa505f27e..9167c389779e 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -40,8 +40,16 @@ struct mmc_csd { }; struct mmc_ext_csd { + u8 rev; + unsigned int sa_timeout; /* Units: 100ns */ unsigned int hs_max_dtr; unsigned int sectors; + unsigned int card_type; +#define MMC_DDR_MODE_MASK (0x3<<2) + unsigned char boot_info; + unsigned char boot_size_mult; + unsigned char boot_config; + unsigned char boot_bus_width; }; struct sd_scr { diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 7ac8b500d55c..e4898e9eeb59 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -139,6 +139,7 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int); extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort); extern void mmc_release_host(struct mmc_host *host); +extern int mmc_try_claim_host(struct mmc_host *host); /** * mmc_claim_host - exclusively claim a host diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 3e7615e9087e..289c17d3e705 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -13,6 +13,7 @@ #include <linux/leds.h> #include <linux/mmc/core.h> +#include <linux/mmc/pm.h> struct mmc_ios { unsigned int clock; /* clock rate */ @@ -42,6 +43,7 @@ struct mmc_ios { #define MMC_BUS_WIDTH_1 0 #define MMC_BUS_WIDTH_4 2 #define MMC_BUS_WIDTH_8 3 +#define MMC_BUS_WIDTH_DDR 8 unsigned char timing; /* timing specification used */ @@ -51,6 +53,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", @@ -90,6 +121,7 @@ struct mmc_host { unsigned int f_min; unsigned int f_max; u32 ocr_avail; + struct notifier_block pm_notify; #define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ @@ -118,6 +150,12 @@ 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_DATA_DDR (1 << 7) /* Can the host do ddr 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 */ + + mmc_pm_flag_t pm_caps; /* supported pm features */ /* host specific block data */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */ @@ -142,9 +180,19 @@ struct mmc_host { unsigned int removed:1; /* host is being removed */ #endif + /* Only used with MMC_CAP_DISABLE */ + int enabled; /* host is enabled */ + int rescan_disable; /* disable card detection */ + 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; @@ -155,6 +203,8 @@ struct mmc_host { struct task_struct *sdio_irq_thread; atomic_t sdio_irq_thread_abort; + mmc_pm_flag_t pm_flags; /* requested pm features */ + #ifdef CONFIG_LEDS_TRIGGERS struct led_trigger *led; /* activity led */ #endif @@ -183,6 +233,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 +250,20 @@ 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); +int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); + +static inline void mmc_set_disable_delay(struct mmc_host *host, + unsigned int disable_delay) +{ + host->disable_delay = disable_delay; +} + #endif diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 14b81f3e5232..37a51b3122df 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -31,6 +31,7 @@ #define MMC_ALL_SEND_CID 2 /* bcr R2 */ #define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ #define MMC_SET_DSR 4 /* bc [31:16] RCA */ +#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */ #define MMC_SWITCH 6 /* ac [31:0] See below R1b */ #define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ #define MMC_SEND_EXT_CSD 8 /* adtc R1 */ @@ -249,11 +250,16 @@ struct _mmc_csd { * EXT_CSD fields */ +#define EXT_CSD_BOOT_BUS_WIDTH 177 /* R/W */ +#define EXT_CSD_BOOT_CONFIG 179 /* R/W */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ #define EXT_CSD_HS_TIMING 185 /* R/W */ #define EXT_CSD_CARD_TYPE 196 /* RO */ #define EXT_CSD_REV 192 /* RO */ #define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ +#define EXT_CSD_S_A_TIMEOUT 217 +#define EXT_CSD_BOOT_SIZE_MULT 226 /* RO, 1 bytes */ +#define EXT_CSD_BOOT_INFO 228 /* RO, 1 bytes */ /* * EXT_CSD field definitions @@ -265,10 +271,36 @@ struct _mmc_csd { #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ +#define EXT_CSD_CARD_TYPE_DDR_52 (2<<1) /* Card can run at DDR 52MHz */ #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ +#define EXT_CSD_BUS_WIDTH_4_DDR 5 /* Card is in 4 bit ddr mode */ +#define EXT_CSD_BUS_WIDTH_8_DDR 6 /* Card is in 8 bit ddr mode */ + +#define EXT_CSD_BOOT_BUS_WIDTH_MASK (0x1F) +#define EXT_CSD_BOOT_BUS_WIDTH_MODE_MASK (0x3 << 3) +#define EXT_CSD_BOOT_BUS_WIDTH_MODE_SDR_NORMAL (0x0) +#define EXT_CSD_BOOT_BUS_WIDTH_MODE_SDR_HIGH (0x1) +#define EXT_CSD_BOOT_BUS_WIDTH_MODE_DDR (0x2) +#define EXT_CSD_BOOT_BUS_WIDTH_RST_WIDTH (1 << 2) +#define EXT_CSD_BOOT_BUS_WIDTH_WIDTH_MASK (0x3) +#define EXT_CSD_BOOT_BUS_WIDTH_1_SDR_4_DDR (0x0) +#define EXT_CSD_BOOT_BUS_WIDTH_4_SDR_4_DDR (0x1) +#define EXT_CSD_BOOT_BUS_WIDTH_8_SDR_8_DDR (0x2) + +#define EXT_CSD_BOOT_ACK_ENABLE (0x1 << 6) +#define EXT_CSD_BOOT_PARTITION_ENABLE_MASK (0x7 << 3) +#define EXT_CSD_BOOT_PARTITION_DISABLE (0x0) +#define EXT_CSD_BOOT_PARTITION_PART1 (0x1 << 3) +#define EXT_CSD_BOOT_PARTITION_PART2 (0x2 << 3) +#define EXT_CSD_BOOT_PARTITION_USER (0x7 << 3) + +#define EXT_CSD_BOOT_PARTITION_ACCESS_MASK (0x7) +#define EXT_CSD_BOOT_PARTITION_ACCESS_DISABLE (0x0) +#define EXT_CSD_BOOT_PARTITION_ACCESS_PART1 (0x1) +#define EXT_CSD_BOOT_PARTITION_ACCESS_PART2 (0x2) /* * MMC_SWITCH access modes diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index 451bdfc85830..51332c5bc2ef 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -15,6 +15,8 @@ #include <linux/device.h> #include <linux/mod_devicetable.h> +#include <linux/mmc/pm.h> + struct mmc_card; struct sdio_func; @@ -150,5 +152,8 @@ extern unsigned char sdio_f0_readb(struct sdio_func *func, extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr, int *err_ret); +extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func); +extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags); + #endif |