SDMMC-emmc:add the capability to support hs200 mode
authorxbw <xbw@rock-chips.com>
Tue, 4 Mar 2014 09:47:47 +0000 (17:47 +0800)
committerxbw <xbw@rock-chips.com>
Tue, 4 Mar 2014 09:47:47 +0000 (17:47 +0800)
Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt [new file with mode: 0755]
Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt [changed mode: 0644->0755]
drivers/mmc/host/dw_mmc-rockchip.c
drivers/mmc/host/rk_sdmmc.c
drivers/mmc/host/rk_sdmmc_of.c
include/linux/mmc/dw_mmc.h
include/linux/mmc/rk_mmc.h [new file with mode: 0755]

diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt
new file mode 100755 (executable)
index 0000000..c559f3f
--- /dev/null
@@ -0,0 +1,23 @@
+* Rockchip specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Rockchip specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+       - "rockchip,rk2928-dw-mshc": for Rockchip RK2928 and following
+
+Example:
+
+       rkdwmmc0@12200000 {
+               compatible = "rockchip,rk2928-dw-mshc";
+               reg = <0x12200000 0x1000>;
+               interrupts = <0 75 0>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
old mode 100644 (file)
new mode 100755 (executable)
index 726fd21..8f3f133
@@ -1,14 +1,14 @@
-* Synopsis Designware Mobile Storage Host Controller
+* Synopsys Designware Mobile Storage Host Controller
 
-The Synopsis designware mobile storage host controller is used to interface
+The Synopsys designware mobile storage host controller is used to interface
 a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
 differences between the core mmc properties described by mmc.txt and the
-properties used by the Synopsis Designware Mobile Storage Host Controller.
+properties used by the Synopsys Designware Mobile Storage Host Controller.
 
 Required Properties:
 
 * compatible: should be
-       - snps,dw-mshc: for controllers compliant with synopsis dw-mshc.
+       - snps,dw-mshc: for controllers compliant with synopsys dw-mshc.
 * #address-cells: should be 1.
 * #size-cells: should be 0.
 
@@ -39,6 +39,22 @@ Required Properties:
 
 Optional properties:
 
+* clocks: from common clock binding: handle to biu and ciu clocks for the
+  bus interface unit clock and the card interface unit clock.
+
+* clock-names: from common clock binding: Shall be "biu" and "ciu".
+  If the biu clock is missing we'll simply skip enabling it.  If the
+  ciu clock is missing we'll just assume that the clock is running at
+  clock-frequency.  It is an error to omit both the ciu clock and the
+  clock-frequency.
+
+* clock-frequency: should be the frequency (in Hz) of the ciu clock.  If this
+  is specified and the ciu clock is specified then we'll try to set the ciu
+  clock to this at probe time.
+
+* clock-freq-min-max: Minimum and Maximum clock frequency for card output
+  clock(cclk_out). If it's not specified, max is 200MHZ and min is 400KHz by default.
+
 * num-slots: specifies the number of slots supported by the controller.
   The number of physical slots actually used could be equal or less than the
   value specified by num-slots. If this property is not specified, the value
@@ -51,10 +67,17 @@ Optional properties:
 * card-detect-delay: Delay in milli-seconds before detecting card after card
   insert event. The default value is 0.
 
-* supports-highspeed: Enables support for high speed cards (upto 50MHz)
+* supports-highspeed: Enables support for high speed cards (up to 50MHz)
+
+* caps2-mmc-hs200-1_8v: Supports mmc HS200 SDR 1.8V mode
+
+* caps2-mmc-hs200-1_2v: Supports mmc HS200 SDR 1.2V mode
 
 * broken-cd: as documented in mmc core bindings.
 
+* vmmc-supply: The phandle to the regulator to use for vmmc.  If this is
+  specified we'll defer probe until we can find this regulator.
+
 Aliases:
 
 - All the MSHC controller nodes should be represented in the aliases node using
@@ -67,6 +90,8 @@ board specific portions as listed below.
 
        dwmmc0@12200000 {
                compatible = "snps,dw-mshc";
+               clocks = <&clock 351>, <&clock 132>;
+               clock-names = "biu", "ciu";
                reg = <0x12200000 0x1000>;
                interrupts = <0 75 0>;
                #address-cells = <1>;
@@ -74,11 +99,15 @@ board specific portions as listed below.
        };
 
        dwmmc0@12200000 {
+               clock-frequency = <400000000>;
+               clock-freq-min-max = <400000 200000000>;
                num-slots = <1>;
                supports-highspeed;
+               caps2-mmc-hs200-1_8v;
                broken-cd;
                fifo-depth = <0x80>;
                card-detect-delay = <200>;
+               vmmc-supply = <&buck8>;
 
                slot@0 {
                        reg = <0>;
index 0d07c55bdd32062eb828ea54e85b9559d4aa19b6..856bc7ccfc72d57b5bd6efa04a365644a7c92d00 100755 (executable)
@@ -16,7 +16,7 @@
 #include <linux/slab.h>
 
 #include <linux/mmc/host.h>
-#include <linux/mmc/dw_mmc.h>
+#include <linux/mmc/rk_mmc.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 
index b719917cebc79325cc9c93c397529eb17888d720..071d444259322621b0064d63b99f236e17edfdb9 100755 (executable)
@@ -31,7 +31,7 @@
 #include <linux/irq.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
-#include <linux/mmc/dw_mmc.h>
+#include <linux/mmc/rk_mmc.h>
 #include <linux/bitops.h>
 #include <linux/regulator/consumer.h>
 #include <linux/workqueue.h>
@@ -523,6 +523,78 @@ static void dw_mci_post_req(struct mmc_host *mmc,
        data->host_cookie = 0;
 }
 
+static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
+{
+#ifdef CONFIG_MMC_DW_IDMAC
+       unsigned int blksz = data->blksz;
+       const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256};
+       u32 fifo_width = 1 << host->data_shift;
+       u32 blksz_depth = blksz / fifo_width, fifoth_val;
+       u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers;
+       int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1;
+
+       tx_wmark = (host->fifo_depth) / 2;
+       tx_wmark_invers = host->fifo_depth - tx_wmark;
+
+       /*
+        * MSIZE is '1',
+        * if blksz is not a multiple of the FIFO width
+        */
+       if (blksz % fifo_width) {
+               msize = 0;
+               rx_wmark = 1;
+               goto done;
+       }
+
+       do {
+               if (!((blksz_depth % mszs[idx]) ||
+                    (tx_wmark_invers % mszs[idx]))) {
+                       msize = idx;
+                       rx_wmark = mszs[idx] - 1;
+                       break;
+               }
+       } while (--idx > 0);
+       /*
+        * If idx is '0', it won't be tried
+        * Thus, initial values are uesed
+        */
+done:
+       fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark);
+       mci_writel(host, FIFOTH, fifoth_val);
+#endif
+}
+
+static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data)
+{
+       unsigned int blksz = data->blksz;
+       u32 blksz_depth, fifo_depth;
+       u16 thld_size;
+
+       WARN_ON(!(data->flags & MMC_DATA_READ));
+
+       if (host->timing != MMC_TIMING_MMC_HS200 &&
+           host->timing != MMC_TIMING_UHS_SDR104)
+               goto disable;
+
+       blksz_depth = blksz / (1 << host->data_shift);
+       fifo_depth = host->fifo_depth;
+
+       if (blksz_depth > fifo_depth)
+               goto disable;
+
+       /*
+        * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz'
+        * If (blksz_depth) <  (fifo_depth >> 1), should be thld_size = blksz
+        * Currently just choose blksz.
+        */
+       thld_size = blksz;
+       mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1));
+       return;
+
+disable:
+       mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0));
+}
+
 static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
 {
        int sg_len;
@@ -572,10 +644,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
        host->sg = NULL;
        host->data = data;
 
-       if (data->flags & MMC_DATA_READ)
+       if (data->flags & MMC_DATA_READ) {
                host->dir_status = DW_MCI_RECV_STATUS;
-       else
+               dw_mci_ctrl_rd_thld(host, data);
+       } else {
                host->dir_status = DW_MCI_SEND_STATUS;
+       }
 
        if (dw_mci_submit_data_dma(host, data)) {
                int flags = SG_MITER_ATOMIC;
@@ -807,6 +881,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                regs &= ~((0x1 << slot->id) << 16);
 
        mci_writel(slot->host, UHS_REG, regs);
+       slot->host->timing = ios->timing;
 
        /*
         * Use mirror of ios->clock to prevent race with mmc
@@ -2231,6 +2306,16 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
        if (of_find_property(np, "enable-sdio-wakeup", NULL))
                pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
 
+       if (of_find_property(np, "supports-highspeed", NULL))
+               pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
+
+       if (of_find_property(np, "caps2-mmc-hs200-1_8v", NULL))
+               pdata->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
+
+       if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
+               pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
+
+
        return pdata;
 }
 
index 0ea94619742bac38f10d309464b2ed9e5eef8b46..b298af99412bcd941850b8179bd725d18b6e7edc 100755 (executable)
@@ -2,9 +2,9 @@
 \r
 static void rockchip_mmc_of_dump(struct rk_sdmmc_of *rk_mmc_property)\r
 {\r
-printk("%d..%s: =====test====\n", __LINE__, __FUNCTION__);\r
+//printk("%d..%s: =====test====\n", __LINE__, __FUNCTION__);\r
 //dump_stack();\r
-/*\r
+\r
     mmc_debug(MMC_DBG_BOOT,"=========rockchip mmc dts dump info start==============\n");\r
     mmc_debug(MMC_DBG_BOOT,"mmc,caps: 0x%x\n",rk_mmc_property->mmc_caps);\r
     mmc_debug(MMC_DBG_BOOT,"mmc,ocr:  0x%x\n",rk_mmc_property->mmc_ocr);\r
@@ -14,7 +14,7 @@ printk("%d..%s: =====test====\n", __LINE__, __FUNCTION__);
                                                    rk_mmc_property->mmc_dma_is_used[1]);\r
     mmc_debug(MMC_DBG_BOOT,"mmc,dma_ch: %d\n",rk_mmc_property->mmc_dma_chn);\r
     mmc_debug(MMC_DBG_BOOT,"=========rockchip mmc dts dump info end================\n");\r
-    */\r
+  /*\r
       printk("=========rockchip mmc dts dump info start==============\n");\r
     printk("mmc,caps: 0x%x\n",rk_mmc_property->mmc_caps);\r
     printk("mmc,ocr:  0x%x\n",rk_mmc_property->mmc_ocr);\r
@@ -23,7 +23,8 @@ printk("%d..%s: =====test====\n", __LINE__, __FUNCTION__);
     printk("mmc,use_dma:  %d %d\n",rk_mmc_property->mmc_dma_is_used[0],\r
                                                    rk_mmc_property->mmc_dma_is_used[1]);\r
     printk("mmc,dma_ch: %d\n",rk_mmc_property->mmc_dma_chn);\r
-    printk("=========rockchip mmc dts dump info end================\n");  \r
+    printk("=========rockchip mmc dts dump info end================\n");\r
+*/  \r
 }\r
 \r
 \r
index 198f0fa44e9fd5c8f2b351c38f7679f165f89f7b..6ce7d2cd3c7ad7dd5eea530192de207b3d1aef22 100644 (file)
@@ -15,6 +15,7 @@
 #define LINUX_MMC_DW_MMC_H
 
 #include <linux/scatterlist.h>
+#include <linux/mmc/core.h>
 
 #define MAX_MCI_SLOTS  2
 
@@ -129,6 +130,9 @@ struct dw_mci {
        struct mmc_request      *mrq;
        struct mmc_command      *cmd;
        struct mmc_data         *data;
+       struct mmc_command      stop_abort;
+       unsigned int            prev_blksz;
+       unsigned char           timing;
        struct workqueue_struct *card_workqueue;
 
        /* DMA interface members*/
diff --git a/include/linux/mmc/rk_mmc.h b/include/linux/mmc/rk_mmc.h
new file mode 100755 (executable)
index 0000000..6ce7d2c
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Synopsys DesignWare Multimedia Card Interface driver
+ *  (Based on NXP driver for lpc 31xx)
+ *
+ * Copyright (C) 2009 NXP Semiconductors
+ * Copyright (C) 2009, 2010 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef LINUX_MMC_DW_MMC_H
+#define LINUX_MMC_DW_MMC_H
+
+#include <linux/scatterlist.h>
+#include <linux/mmc/core.h>
+
+#define MAX_MCI_SLOTS  2
+
+enum dw_mci_state {
+       STATE_IDLE = 0,
+       STATE_SENDING_CMD,
+       STATE_SENDING_DATA,
+       STATE_DATA_BUSY,
+       STATE_SENDING_STOP,
+       STATE_DATA_ERROR,
+};
+
+enum {
+       EVENT_CMD_COMPLETE = 0,
+       EVENT_XFER_COMPLETE,
+       EVENT_DATA_COMPLETE,
+       EVENT_DATA_ERROR,
+       EVENT_XFER_ERROR
+};
+
+struct mmc_data;
+
+/**
+ * struct dw_mci - MMC controller state shared between all slots
+ * @lock: Spinlock protecting the queue and associated data.
+ * @regs: Pointer to MMIO registers.
+ * @sg: Scatterlist entry currently being processed by PIO code, if any.
+ * @sg_miter: PIO mapping scatterlist iterator.
+ * @cur_slot: The slot which is currently using the controller.
+ * @mrq: The request currently being processed on @cur_slot,
+ *     or NULL if the controller is idle.
+ * @cmd: The command currently being sent to the card, or NULL.
+ * @data: The data currently being transferred, or NULL if no data
+ *     transfer is in progress.
+ * @use_dma: Whether DMA channel is initialized or not.
+ * @using_dma: Whether DMA is in use for the current transfer.
+ * @sg_dma: Bus address of DMA buffer.
+ * @sg_cpu: Virtual address of DMA buffer.
+ * @dma_ops: Pointer to platform-specific DMA callbacks.
+ * @cmd_status: Snapshot of SR taken upon completion of the current
+ *     command. Only valid when EVENT_CMD_COMPLETE is pending.
+ * @data_status: Snapshot of SR taken upon completion of the current
+ *     data transfer. Only valid when EVENT_DATA_COMPLETE or
+ *     EVENT_DATA_ERROR is pending.
+ * @stop_cmdr: Value to be loaded into CMDR when the stop command is
+ *     to be sent.
+ * @dir_status: Direction of current transfer.
+ * @tasklet: Tasklet running the request state machine.
+ * @card_tasklet: Tasklet handling card detect.
+ * @pending_events: Bitmask of events flagged by the interrupt handler
+ *     to be processed by the tasklet.
+ * @completed_events: Bitmask of events which the state machine has
+ *     processed.
+ * @state: Tasklet state.
+ * @queue: List of slots waiting for access to the controller.
+ * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus
+ *     rate and timeout calculations.
+ * @current_speed: Configured rate of the controller.
+ * @num_slots: Number of slots available.
+ * @verid: Denote Version ID.
+ * @data_offset: Set the offset of DATA register according to VERID.
+ * @dev: Device associated with the MMC controller.
+ * @pdata: Platform data associated with the MMC controller.
+ * @drv_data: Driver specific data for identified variant of the controller
+ * @priv: Implementation defined private data.
+ * @biu_clk: Pointer to bus interface unit clock instance.
+ * @ciu_clk: Pointer to card interface unit clock instance.
+ * @slot: Slots sharing this MMC controller.
+ * @fifo_depth: depth of FIFO.
+ * @data_shift: log2 of FIFO item size.
+ * @part_buf_start: Start index in part_buf.
+ * @part_buf_count: Bytes of partial data in part_buf.
+ * @part_buf: Simple buffer for partial fifo reads/writes.
+ * @push_data: Pointer to FIFO push function.
+ * @pull_data: Pointer to FIFO pull function.
+ * @quirks: Set of quirks that apply to specific versions of the IP.
+ * @irq_flags: The flags to be passed to request_irq.
+ * @irq: The irq value to be passed to request_irq.
+ *
+ * Locking
+ * =======
+ *
+ * @lock is a softirq-safe spinlock protecting @queue as well as
+ * @cur_slot, @mrq and @state. These must always be updated
+ * at the same time while holding @lock.
+ *
+ * The @mrq field of struct dw_mci_slot is also protected by @lock,
+ * and must always be written at the same time as the slot is added to
+ * @queue.
+ *
+ * @pending_events and @completed_events are accessed using atomic bit
+ * operations, so they don't need any locking.
+ *
+ * None of the fields touched by the interrupt handler need any
+ * locking. However, ordering is important: Before EVENT_DATA_ERROR or
+ * EVENT_DATA_COMPLETE is set in @pending_events, all data-related
+ * interrupts must be disabled and @data_status updated with a
+ * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the
+ * CMDRDY interrupt must be disabled and @cmd_status updated with a
+ * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the
+ * bytes_xfered field of @data must be written. This is ensured by
+ * using barriers.
+ */
+struct dw_mci {
+       spinlock_t              lock;
+       void __iomem            *regs;
+
+       struct scatterlist      *sg;
+       struct sg_mapping_iter  sg_miter;
+
+       struct dw_mci_slot      *cur_slot;
+       struct mmc_request      *mrq;
+       struct mmc_command      *cmd;
+       struct mmc_data         *data;
+       struct mmc_command      stop_abort;
+       unsigned int            prev_blksz;
+       unsigned char           timing;
+       struct workqueue_struct *card_workqueue;
+
+       /* DMA interface members*/
+       int                     use_dma;
+       int                     using_dma;
+
+       dma_addr_t              sg_dma;
+       void                    *sg_cpu;
+       const struct dw_mci_dma_ops     *dma_ops;
+#ifdef CONFIG_MMC_DW_IDMAC
+       unsigned int            ring_size;
+#else
+       struct dw_mci_dma_data  *dma_data;
+#endif
+       u32                     cmd_status;
+       u32                     data_status;
+       u32                     stop_cmdr;
+       u32                     dir_status;
+       struct tasklet_struct   tasklet;
+       struct work_struct      card_work;
+       unsigned long           pending_events;
+       unsigned long           completed_events;
+       enum dw_mci_state       state;
+       struct list_head        queue;
+
+       u32                     bus_hz;
+       u32                     current_speed;
+       u32                     num_slots;
+       u32                     fifoth_val;
+       u16                     verid;
+       u16                     data_offset;
+       struct device           *dev;
+       struct dw_mci_board     *pdata;
+       const struct dw_mci_drv_data    *drv_data;
+       void                    *priv;
+       struct clk              *biu_clk;
+       struct clk              *ciu_clk;
+       struct dw_mci_slot      *slot[MAX_MCI_SLOTS];
+
+       /* FIFO push and pull */
+       int                     fifo_depth;
+       int                     data_shift;
+       u8                      part_buf_start;
+       u8                      part_buf_count;
+       union {
+               u16             part_buf16;
+               u32             part_buf32;
+               u64             part_buf;
+       };
+       void (*push_data)(struct dw_mci *host, void *buf, int cnt);
+       void (*pull_data)(struct dw_mci *host, void *buf, int cnt);
+
+       /* Workaround flags */
+       u32                     quirks;
+
+       struct regulator        *vmmc;  /* Power regulator */
+       unsigned long           irq_flags; /* IRQ flags */
+       int                     irq;
+};
+
+/* DMA ops for Internal/External DMAC interface */
+struct dw_mci_dma_ops {
+       /* DMA Ops */
+       int (*init)(struct dw_mci *host);
+       void (*start)(struct dw_mci *host, unsigned int sg_len);
+       void (*complete)(struct dw_mci *host);
+       void (*stop)(struct dw_mci *host);
+       void (*cleanup)(struct dw_mci *host);
+       void (*exit)(struct dw_mci *host);
+};
+
+/* IP Quirks/flags. */
+/* DTO fix for command transmission with IDMAC configured */
+#define DW_MCI_QUIRK_IDMAC_DTO                 BIT(0)
+/* delay needed between retries on some 2.11a implementations */
+#define DW_MCI_QUIRK_RETRY_DELAY               BIT(1)
+/* High Speed Capable - Supports HS cards (up to 50MHz) */
+#define DW_MCI_QUIRK_HIGHSPEED                 BIT(2)
+/* Unreliable card detection */
+#define DW_MCI_QUIRK_BROKEN_CARD_DETECTION     BIT(3)
+
+/* Slot level quirks */
+/* This slot has no write protect */
+#define DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT     BIT(0)
+
+struct dma_pdata;
+
+struct block_settings {
+       unsigned short  max_segs;       /* see blk_queue_max_segments */
+       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_req_size;   /* maximum number of bytes in one req*/
+       unsigned int    max_seg_size;   /* see blk_queue_max_segment_size */
+};
+
+/* Board platform data */
+struct dw_mci_board {
+       u32 num_slots;
+
+       u32 quirks; /* Workaround / Quirk flags */
+       unsigned int bus_hz; /* Clock speed at the cclk_in pad */
+
+       u32 caps;       /* Capabilities */
+       u32 caps2;      /* More capabilities */
+       u32 pm_caps;    /* PM capabilities */
+       /*
+        * Override fifo depth. If 0, autodetect it from the FIFOTH register,
+        * but note that this may not be reliable after a bootloader has used
+        * it.
+        */
+       unsigned int fifo_depth;
+
+       /* delay in mS before detecting cards after interrupt */
+       u32 detect_delay_ms;
+
+       int (*init)(u32 slot_id, irq_handler_t , void *);
+       int (*get_ro)(u32 slot_id);
+       int (*get_cd)(u32 slot_id);
+       int (*get_ocr)(u32 slot_id);
+       int (*get_bus_wd)(u32 slot_id);
+       /*
+        * Enable power to selected slot and set voltage to desired level.
+        * Voltage levels are specified using MMC_VDD_xxx defines defined
+        * in linux/mmc/host.h file.
+        */
+       void (*setpower)(u32 slot_id, u32 volt);
+       void (*exit)(u32 slot_id);
+       void (*select_slot)(u32 slot_id);
+
+       struct dw_mci_dma_ops *dma_ops;
+       struct dma_pdata *data;
+       struct block_settings *blk_settings;
+};
+
+#endif /* LINUX_MMC_DW_MMC_H */