summaryrefslogtreecommitdiff
path: root/include/linux/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/mmc')
-rw-r--r--include/linux/mmc/card.h8
-rw-r--r--include/linux/mmc/core.h1
-rw-r--r--include/linux/mmc/host.h68
-rw-r--r--include/linux/mmc/mmc.h32
-rw-r--r--include/linux/mmc/sdio_func.h5
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