]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - include/linux/mmc/host.h
Merge commit 'main-jb-2012.08.03-B4' into t114-0806
[linux-2.6.git] / include / linux / mmc / host.h
index c1cbe598d470930a389a16b73eb897d1f4f444a3..05de12d851146efc8d50a5de704d7df94dc6b3f7 100644 (file)
 #define LINUX_MMC_HOST_H
 
 #include <linux/leds.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/fault-inject.h>
+#include <linux/wakelock.h>
 
 #include <linux/mmc/core.h>
+#include <linux/mmc/pm.h>
 
 struct mmc_ios {
        unsigned int    clock;                  /* clock rate */
@@ -48,38 +53,52 @@ struct mmc_ios {
 #define MMC_TIMING_LEGACY      0
 #define MMC_TIMING_MMC_HS      1
 #define MMC_TIMING_SD_HS       2
+#define MMC_TIMING_UHS_SDR12   MMC_TIMING_LEGACY
+#define MMC_TIMING_UHS_SDR25   MMC_TIMING_SD_HS
+#define MMC_TIMING_UHS_SDR50   3
+#define MMC_TIMING_UHS_SDR104  4
+#define MMC_TIMING_UHS_DDR50   5
+#define MMC_TIMING_MMC_HS200   6
+
+#define MMC_SDR_MODE           0
+#define MMC_1_2V_DDR_MODE      1
+#define MMC_1_8V_DDR_MODE      2
+#define MMC_1_2V_SDR_MODE      3
+#define MMC_1_8V_SDR_MODE      4
+
+       unsigned char   signal_voltage;         /* signalling voltage (1.8V or 3.3V) */
+
+#define MMC_SIGNAL_VOLTAGE_330 0
+#define MMC_SIGNAL_VOLTAGE_180 1
+#define MMC_SIGNAL_VOLTAGE_120 2
+
+       unsigned char   drv_type;               /* driver type (A, B, C, D) */
+
+#define MMC_SET_DRIVER_TYPE_B  0
+#define MMC_SET_DRIVER_TYPE_A  1
+#define MMC_SET_DRIVER_TYPE_C  2
+#define MMC_SET_DRIVER_TYPE_D  3
 };
 
 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.
+        * 'enable' is called when the host is claimed and 'disable' is called
+        * when the host is released. 'enable' and 'disable' are deprecated.
         */
        int (*enable)(struct mmc_host *host);
-       int (*disable)(struct mmc_host *host, int lazy);
+       int (*disable)(struct mmc_host *host);
+       /*
+        * It is optional for the host to implement pre_req and post_req in
+        * order to support double buffering of requests (prepare one
+        * request while another request is active).
+        * pre_req() must always be followed by a post_req().
+        * To undo a call made to pre_req(), call post_req() with
+        * a nonzero err condition.
+        */
+       void    (*post_req)(struct mmc_host *host, struct mmc_request *req,
+                           int err);
+       void    (*pre_req)(struct mmc_host *host, struct mmc_request *req,
+                          bool is_first_req);
        void    (*request)(struct mmc_host *host, struct mmc_request *req);
        /*
         * Avoid calling these three functions too often or in a "fast path",
@@ -106,11 +125,37 @@ struct mmc_host_ops {
        int     (*get_cd)(struct mmc_host *host);
 
        void    (*enable_sdio_irq)(struct mmc_host *host, int enable);
+
+       /* optional callback for HC quirks */
+       void    (*init_card)(struct mmc_host *host, struct mmc_card *card);
+
+       int     (*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios);
+
+       /* The tuning command opcode value is different for SD and eMMC cards */
+       int     (*execute_tuning)(struct mmc_host *host, u32 opcode);
+       void    (*enable_preset_value)(struct mmc_host *host, bool enable);
+       int     (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
+       void    (*hw_reset)(struct mmc_host *host);
 };
 
 struct mmc_card;
 struct device;
 
+struct mmc_async_req {
+       /* active mmc request */
+       struct mmc_request      *mrq;
+       /*
+        * Check error status of completed mmc request.
+        * Returns 0 if success otherwise non zero.
+        */
+       int (*err_check) (struct mmc_card *, struct mmc_async_req *);
+};
+
+struct mmc_hotplug {
+       unsigned int irq;
+       void *handler_priv;
+};
+
 struct mmc_host {
        struct device           *parent;
        struct device           class_dev;
@@ -118,7 +163,12 @@ struct mmc_host {
        const struct mmc_host_ops *ops;
        unsigned int            f_min;
        unsigned int            f_max;
+       unsigned int            f_init;
        u32                     ocr_avail;
+       u32                     ocr_avail_sdio; /* SDIO-specific OCR */
+       u32                     ocr_avail_sd;   /* SD-specific OCR */
+       u32                     ocr_avail_mmc;  /* MMC-specific OCR */
+       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 */
@@ -147,17 +197,83 @@ 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 */
+#define MMC_CAP_ERASE          (1 << 10)       /* Allow erase/trim commands */
+#define MMC_CAP_1_8V_DDR       (1 << 11)       /* can support */
+                                               /* DDR mode at 1.8V */
+#define MMC_CAP_1_2V_DDR       (1 << 12)       /* can support */
+                                               /* DDR mode at 1.2V */
+#define MMC_CAP_POWER_OFF_CARD (1 << 13)       /* Can power off after boot */
+#define MMC_CAP_BUS_WIDTH_TEST (1 << 14)       /* CMD14/CMD19 bus width ok */
+#define MMC_CAP_UHS_SDR12      (1 << 15)       /* Host supports UHS SDR12 mode */
+#define MMC_CAP_UHS_SDR25      (1 << 16)       /* Host supports UHS SDR25 mode */
+#define MMC_CAP_UHS_SDR50      (1 << 17)       /* Host supports UHS SDR50 mode */
+#define MMC_CAP_UHS_SDR104     (1 << 18)       /* Host supports UHS SDR104 mode */
+#define MMC_CAP_UHS_DDR50      (1 << 19)       /* Host supports UHS DDR50 mode */
+#define MMC_CAP_SET_XPC_330    (1 << 20)       /* Host supports >150mA current at 3.3V */
+#define MMC_CAP_SET_XPC_300    (1 << 21)       /* Host supports >150mA current at 3.0V */
+#define MMC_CAP_SET_XPC_180    (1 << 22)       /* Host supports >150mA current at 1.8V */
+#define MMC_CAP_DRIVER_TYPE_A  (1 << 23)       /* Host supports Driver Type A */
+#define MMC_CAP_DRIVER_TYPE_C  (1 << 24)       /* Host supports Driver Type C */
+#define MMC_CAP_DRIVER_TYPE_D  (1 << 25)       /* Host supports Driver Type D */
+#define MMC_CAP_MAX_CURRENT_200        (1 << 26)       /* Host max current limit is 200mA */
+#define MMC_CAP_MAX_CURRENT_400        (1 << 27)       /* Host max current limit is 400mA */
+#define MMC_CAP_MAX_CURRENT_600        (1 << 28)       /* Host max current limit is 600mA */
+#define MMC_CAP_MAX_CURRENT_800        (1 << 29)       /* Host max current limit is 800mA */
+#define MMC_CAP_CMD23          (1 << 30)       /* CMD23 supported. */
+#define MMC_CAP_HW_RESET       (1 << 31)       /* Hardware reset */
+
+       unsigned int            caps2;          /* More host capabilities */
+
+#define MMC_CAP2_BOOTPART_NOACC        (1 << 0)        /* Boot partition no access */
+#define MMC_CAP2_CACHE_CTRL    (1 << 1)        /* Allow cache control */
+#define MMC_CAP2_POWEROFF_NOTIFY (1 << 2)      /* Notify poweroff supported */
+#define MMC_CAP2_NO_MULTI_READ (1 << 3)        /* Multiblock reads don't work */
+#define MMC_CAP2_NO_SLEEP_CMD  (1 << 4)        /* Don't allow sleep command */
+#define MMC_CAP2_HS200_1_8V_SDR        (1 << 5)        /* can support */
+#define MMC_CAP2_HS200_1_2V_SDR        (1 << 6)        /* can support */
+#define MMC_CAP2_HS200         (MMC_CAP2_HS200_1_8V_SDR | \
+                                MMC_CAP2_HS200_1_2V_SDR)
+#define MMC_CAP2_BROKEN_VOLTAGE        (1 << 7)        /* Use the broken voltage */
+#define MMC_CAP2_DETECT_ON_ERR (1 << 8)        /* On I/O err check card removal */
+#define MMC_CAP2_HC_ERASE_SZ   (1 << 9)        /* High-capacity erase size */
+#define MMC_CAP2_BKOPS         (1 << 10)       /* Host supports BKOPS */
+
+       unsigned int            caps2;                  /* More host capabilities */
+#define MMC_CAP2_BOOTPART_NOACC        (1 << 0)        /* Boot partition no access */
+#define MMC_CAP2_CACHE_CTRL            (1 << 1)        /* Allow cache control */
+#define MMC_CAP2_POWEROFF_NOTIFY       (1 << 2)        /* Notify poweroff supported */
+#define MMC_CAP2_NO_MULTI_READ (1 << 3)        /* Multiblock reads don't work */
+#define MMC_CAP2_NO_SLEEP_CMD          (1 << 4)        /* Don't allow sleep command */
+
+       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 */
+       unsigned int            clk_delay;      /* number of MCI clk hold cycles */
+       bool                    clk_gated;      /* clock gated */
+       struct delayed_work     clk_gate_work; /* delayed clock gate */
+       unsigned int            clk_old;        /* old clock value cache */
+       spinlock_t              clk_lock;       /* lock for clk fields */
+       struct mutex            clk_gate_mutex; /* mutex for clock gating */
+       struct device_attribute clkgate_delay_attr;
+       unsigned long           clkgate_delay;
+#endif
 
        /* host specific block data */
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
-       unsigned short          max_hw_segs;    /* see blk_queue_max_hw_segments */
-       unsigned short          max_phys_segs;  /* see blk_queue_max_phys_segments */
+       unsigned short          max_segs;       /* see blk_queue_max_segments */
        unsigned short          unused;
        unsigned int            max_req_size;   /* maximum number of bytes in one req */
        unsigned int            max_blk_size;   /* maximum size of one mmc block */
        unsigned int            max_blk_count;  /* maximum number of blocks in one req */
+       unsigned int            max_discard_to; /* max. discard timeout in ms */
 
        /* private data */
        spinlock_t              lock;           /* lock for claim and bus ops */
@@ -173,12 +289,7 @@ 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 */
+       int                     rescan_disable; /* disable card detection */
 
        struct mmc_card         *card;          /* device attached to this host */
 
@@ -187,20 +298,51 @@ struct mmc_host {
        int                     claim_cnt;      /* "claim" nesting count */
 
        struct delayed_work     detect;
+       struct wake_lock        detect_wake_lock;
+       int                     detect_change;  /* card detect flag */
+       struct mmc_hotplug      hotplug;
 
        const struct mmc_bus_ops *bus_ops;      /* current bus driver */
        unsigned int            bus_refs;       /* reference counter */
 
+       unsigned int            bus_resume_flags;
+#define MMC_BUSRESUME_MANUAL_RESUME    (1 << 0)
+#define MMC_BUSRESUME_NEEDS_RESUME     (1 << 1)
+
        unsigned int            sdio_irqs;
        struct task_struct      *sdio_irq_thread;
+       bool                    sdio_irq_pending;
        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
 
+#ifdef CONFIG_REGULATOR
+       bool                    regulator_enabled; /* regulator state */
+#endif
+
        struct dentry           *debugfs_root;
 
+       struct mmc_async_req    *areq;          /* active async req */
+
+#ifdef CONFIG_FAIL_MMC_REQUEST
+       struct fault_attr       fail_mmc_request;
+#endif
+
+       unsigned int            actual_clock;   /* Actual HC clock rate */
+
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+       struct {
+               struct sdio_cis                 *cis;
+               struct sdio_cccr                *cccr;
+               struct sdio_embedded_func       *funcs;
+               int                             num_funcs;
+       } embedded_sdio_data;
+#endif
+
        unsigned long           private[0] ____cacheline_aligned;
 };
 
@@ -209,6 +351,14 @@ extern int mmc_add_host(struct mmc_host *);
 extern void mmc_remove_host(struct mmc_host *);
 extern void mmc_free_host(struct mmc_host *);
 
+#ifdef CONFIG_MMC_EMBEDDED_SDIO
+extern void mmc_set_embedded_sdio_data(struct mmc_host *host,
+                                      struct sdio_cis *cis,
+                                      struct sdio_cccr *cccr,
+                                      struct sdio_embedded_func *funcs,
+                                      int num_funcs);
+#endif
+
 static inline void *mmc_priv(struct mmc_host *host)
 {
        return (void *)host->private;
@@ -219,36 +369,112 @@ static inline void *mmc_priv(struct mmc_host *host)
 #define mmc_dev(x)     ((x)->parent)
 #define mmc_classdev(x)        (&(x)->class_dev)
 #define mmc_hostname(x)        (dev_name(&(x)->class_dev))
+#define mmc_bus_needs_resume(host) ((host)->bus_resume_flags & MMC_BUSRESUME_NEEDS_RESUME)
+#define mmc_bus_manual_resume(host) ((host)->bus_resume_flags & MMC_BUSRESUME_MANUAL_RESUME)
+
+static inline void mmc_set_bus_resume_policy(struct mmc_host *host, int manual)
+{
+       if (manual)
+               host->bus_resume_flags |= MMC_BUSRESUME_MANUAL_RESUME;
+       else
+               host->bus_resume_flags &= ~MMC_BUSRESUME_MANUAL_RESUME;
+}
+
+extern int mmc_resume_bus(struct mmc_host *host);
 
-extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
+extern int mmc_suspend_host(struct mmc_host *);
 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 int mmc_power_save_host(struct mmc_host *host);
+extern int 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 *);
 
+extern int mmc_cache_ctrl(struct mmc_host *, u8);
+
 static inline void mmc_signal_sdio_irq(struct mmc_host *host)
 {
        host->ops->enable_sdio_irq(host, 0);
+       host->sdio_irq_pending = true;
        wake_up_process(host->sdio_irq_thread);
 }
 
 struct regulator;
 
+#ifdef CONFIG_REGULATOR
 int mmc_regulator_get_ocrmask(struct regulator *supply);
-int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit);
+int mmc_regulator_set_ocr(struct mmc_host *mmc,
+                       struct regulator *supply,
+                       unsigned short vdd_bit);
+#else
+static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
+{
+       return 0;
+}
+
+static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
+                                struct regulator *supply,
+                                unsigned short vdd_bit)
+{
+       return 0;
+}
+#endif
+
+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 *);
+int mmc_speed_class_control(struct mmc_host *host,
+       unsigned int speed_class_ctrl_arg);
 
-static inline void mmc_set_disable_delay(struct mmc_host *host,
-                                        unsigned int disable_delay)
+
+/* Module parameter */
+extern bool mmc_assume_removable;
+
+static inline int mmc_card_is_removable(struct mmc_host *host)
 {
-       host->disable_delay = disable_delay;
+       return !(host->caps & MMC_CAP_NONREMOVABLE) && mmc_assume_removable;
 }
 
-#endif
+static inline int mmc_card_keep_power(struct mmc_host *host)
+{
+       return host->pm_flags & MMC_PM_KEEP_POWER;
+}
+
+static inline int mmc_card_wake_sdio_irq(struct mmc_host *host)
+{
+       return host->pm_flags & MMC_PM_WAKE_SDIO_IRQ;
+}
 
+static inline int mmc_host_cmd23(struct mmc_host *host)
+{
+       return host->caps & MMC_CAP_CMD23;
+}
+
+static inline int mmc_boot_partition_access(struct mmc_host *host)
+{
+       return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC);
+}
+
+#ifdef CONFIG_MMC_CLKGATE
+void mmc_host_clk_hold(struct mmc_host *host);
+void mmc_host_clk_release(struct mmc_host *host);
+unsigned int mmc_host_clk_rate(struct mmc_host *host);
+
+#else
+static inline void mmc_host_clk_hold(struct mmc_host *host)
+{
+}
+
+static inline void mmc_host_clk_release(struct mmc_host *host)
+{
+}
+
+static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
+{
+       return host->ios.clock;
+}
+#endif
+#endif /* LINUX_MMC_HOST_H */