SDMMC:
authorxbw <xbw@rock-chips.com>
Thu, 8 Aug 2013 08:50:13 +0000 (16:50 +0800)
committerxbw <xbw@rock-chips.com>
Thu, 8 Aug 2013 08:50:13 +0000 (16:50 +0800)
1、Simplify the driver code.
2、modify the SDMMC_CLKEN_DISABLE
3、prepare for IDMA.
4、continue with 2b0034ec2ea1fe2c836741b2010b80982016ab53

drivers/mmc/host/rk29_sdmmc.c
drivers/mmc/host/rk29_sdmmc.h

index 0059e0220b92215891c4a62594fa953703d689b8..60e3f0824bf2d660da768dcfe9e5c86883f258e4 100755 (executable)
@@ -64,64 +64,7 @@ int debug_level = 5;
 #define xbwprintk(n, arg...)
 #endif
 
-#if defined(CONFIG_ARCH_RK29)
-#define SDMMC_USE_INT_UNBUSY     0
-#else
-#define SDMMC_USE_INT_UNBUSY     0///1 
-#endif
-
-/*
-** You can set the macro to true, if some module wants to use this feature, which is about SDIO suspend-resume.
-** As the following example.
-** added by xbw at 2013-05-08
-*/
-#if defined(CONFIG_MTK_COMBO_DRIVER_VERSION_JB2)
-#define RK_SDMMC_USE_SDIO_SUSPEND_RESUME    1
-#else
-#define RK_SDMMC_USE_SDIO_SUSPEND_RESUME    0
-#endif
-
-#define RK29_SDMMC_ERROR_FLAGS         (SDMMC_INT_FRUN | SDMMC_INT_HLE )
-
-#if defined(CONFIG_SDMMC0_RK29_SDCARD_DET_FROM_GPIO)
-    #if SDMMC_USE_INT_UNBUSY
-    #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS )
-    #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_TXDR | SDMMC_INT_RXDR )
-    #else
-    #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS )
-    #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_TXDR | SDMMC_INT_RXDR )
-    #endif
-#else
-    #if SDMMC_USE_INT_UNBUSY
-    #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD)
-    #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD| SDMMC_INT_TXDR | SDMMC_INT_RXDR )
-    #else
-    #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD)
-    #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD| SDMMC_INT_TXDR | SDMMC_INT_RXDR )
-    #endif
-#endif
-
-#define RK29_SDMMC_SEND_START_TIMEOUT   3000  //The time interval from the time SEND_CMD to START_CMD_BIT cleared.
-#define RK29_ERROR_PRINTK_INTERVAL      200   //The time interval between the two printk for the same error. 
-#define RK29_SDMMC_WAIT_DTO_INTERNVAL   4500  //The time interval from the CMD_DONE_INT to DTO_INT
-#define RK29_SDMMC_REMOVAL_DELAY        2000  //The time interval from the CD_INT to detect_timer react.
-
-#define RK29_SDMMC_VERSION "Ver.6.00 The last modify date is 2013-08-02"
-
-#if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) 
-#define RK29_CTRL_SDMMC_ID   0  //mainly used by SDMMC
-#define RK29_CTRL_SDIO1_ID   1  //mainly used by sdio-wifi
-#define RK29_CTRL_SDIO2_ID   2  //mainly used by sdio-card
-#else
-#define RK29_CTRL_SDMMC_ID   5  
-#define RK29_CTRL_SDIO1_ID   1  
-#define RK29_CTRL_SDIO2_ID   2  
-#endif
-
-#define SDMMC_CLOCK_TEST     0
-
-#define RK29_SDMMC_NOTIFY_REMOVE_INSERTION /* use sysfs to notify the removal or insertion of sd-card*/
-//#define RK29_SDMMC_LIST_QUEUE            /* use list-queue for multi-card*/
+#define RK29_SDMMC_VERSION "Ver.6.01 The last modify date is 2013-08-05"
 
 #define RK29_SDMMC_DEFAULT_SDIO_FREQ   0 // 1--run in default frequency(50Mhz); 0---run in 25Mhz, 
 #if defined(CONFIG_MT6620)|| defined(CONFIG_ESP8089)
@@ -137,172 +80,9 @@ int debug_level = 5;
 #define DRIVER_SDMMC_USE_NEW_IOMUX_API 0
 #endif
 
-//support Internal DMA 
-#if 0 //Sometime in the future to enable
-#define DRIVER_SDMMC_USE_IDMA 1
-#else
-#define DRIVER_SDMMC_USE_IDMA 0
-#endif
-
 #define SWITCH_VOLTAGE_18_33            0 //RK30_PIN2_PD7 //Temporary experiment
 #define SWITCH_VOLTAGE_ENABLE_VALUE_33  GPIO_LOW
 
-enum {
-       EVENT_CMD_COMPLETE = 0,
-       EVENT_DATA_COMPLETE,
-       EVENT_DATA_UNBUSY,
-       EVENT_DATA_ERROR,
-       EVENT_XFER_ERROR
-};
-
-enum rk29_sdmmc_state {
-       STATE_IDLE = 0,
-       STATE_SENDING_CMD,
-       STATE_DATA_BUSY,
-       STATE_DATA_UNBUSY,
-       STATE_DATA_END,
-       STATE_SENDING_STOP,
-};
-
-struct rk29_sdmmc_dma_info {
-       enum dma_ch chn;
-       char *name;
-       struct rk29_dma_client client;
-};
-
-static struct rk29_sdmmc_dma_info rk29_sdmmc_dma_infos[]= {
-       {
-               .chn = DMACH_SDMMC,
-               .client = {
-                       .name = "rk29-dma-sdmmc0",
-               }
-       },
-       {
-               .chn = DMACH_SDIO,
-               .client = {
-                       .name = "rk29-dma-sdio1",
-               }
-       },
-
-       {
-               .chn = DMACH_EMMC,
-               .client = {
-                       .name = "rk29-dma-sdio2",
-               }
-       },
-};
-
-
-/* Interrupt Information */
-typedef struct TagSDC_INT_INFO
-{
-    u32     transLen;               //the length of data sent.
-    u32     desLen;                 //the total length of the all data.
-    u32    *pBuf;                   //the data buffer for interrupt read or write.
-}SDC_INT_INFO_T;
-
-
-struct rk29_sdmmc {
-       spinlock_t              lock;
-       void __iomem    *regs;
-       struct clk              *clk;
-
-       struct mmc_request      *mrq;
-       struct mmc_request      *new_mrq;
-       struct mmc_command      *cmd;
-       struct mmc_data         *data;  
-       struct scatterlist      *sg;
-
-       dma_addr_t              dma_addr;;
-       unsigned int    use_dma:1;
-       char                    dma_name[8];
-       u32                     cmd_status;
-       u32                     data_status;
-       u32                     stop_cmdr;
-
-    u32         old_div;
-       u32                     cmdr;   //the value setted into command-register
-       u32                     dodma;  //sign the DMA used for transfer.
-       u32         errorstep;//record the error point.
-       int         timeout_times;  //use to force close the sdmmc0 when the timeout_times exceeds the limit.
-       u32         *pbuf;
-       SDC_INT_INFO_T    intInfo; 
-    struct rk29_sdmmc_dma_info         dma_info;
-    int         irq;
-       int error_times;
-       u32 old_cmd;
-       
-       struct tasklet_struct   tasklet;
-       unsigned long           pending_events;
-       unsigned long           completed_events;
-       enum rk29_sdmmc_state   state;
-
-#ifdef RK29_SDMMC_LIST_QUEUE
-       struct list_head        queue;
-       struct list_head        queue_node;
-#endif
-
-       u32                     bus_hz;
-       struct platform_device  *pdev;
-       struct mmc_host         *mmc;
-       u32                     ctype;
-       unsigned int            clock;
-       unsigned long           flags;
-       
-#define RK29_SDMMC_CARD_PRESENT        0
-
-       int                     id;
-
-       struct timer_list       detect_timer; 
-       struct timer_list       request_timer; //the timer for INT_CMD_DONE
-       struct timer_list       DTO_timer;     //the timer for INT_DTO
-       struct mmc_command      stopcmd;
-    struct rksdmmc_gpio det_pin;
-
-       /* flag for current bus settings */
-    u32 bus_mode;
-
-    unsigned int            oldstatus;
-    unsigned int            complete_done;
-    unsigned int            retryfunc;
-    
-    int gpio_irq;
-       int gpio_power_en;
-       int gpio_power_en_level;
-       struct delayed_work             work;
-
-#ifdef CONFIG_RK29_SDIO_IRQ_FROM_GPIO
-    unsigned int sdio_INT_gpio;
-    unsigned int sdio_irq;
-    unsigned long trigger_level;
-#endif
-
-#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT)
-    int write_protect;
-    int protect_level;
-#endif
-
-       bool                    irq_state;
-    void (*set_iomux)(int device_id, unsigned int bus_width);
-
-};
-
-
-#ifdef RK29_SDMMC_NOTIFY_REMOVE_INSERTION
-static struct rk29_sdmmc    *globalSDhost[3];
-#endif
-
-#define rk29_sdmmc_test_and_clear_pending(host, event)         \
-       test_and_clear_bit(event, &host->pending_events)
-#define rk29_sdmmc_test_pending(host, event)           \
-       test_bit(event, &host->pending_events)
-#define rk29_sdmmc_test_completed(host, event)           \
-        test_bit(event, &host->completed_events)       
-#define rk29_sdmmc_set_completed(host, event)                  \
-       set_bit(event, &host->completed_events)
-#define rk29_sdmmc_set_pending(host, event)                            \
-       set_bit(event, &host->pending_events)
-
 static void rk29_sdmmc_start_error(struct rk29_sdmmc *host);
 static int rk29_sdmmc_clear_fifo(struct rk29_sdmmc *host);
 int rk29_sdmmc_hw_init(void *data);
@@ -319,40 +99,14 @@ static unsigned int rk29_sdmmc_read(unsigned char  __iomem *regbase, unsigned in
 
 static int rk29_sdmmc_regs_printk(struct rk29_sdmmc *host)
 {
-       printk("SDMMC_CTRL:   \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CTRL));
-       printk("SDMMC_PWREN:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_PWREN));
-       printk("SDMMC_CLKDIV: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKDIV));
-       printk("SDMMC_CLKSRC: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKSRC));
-       printk("SDMMC_CLKENA: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKENA));
-       printk("SDMMC_TMOUT:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TMOUT));
-       printk("SDMMC_CTYPE:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CTYPE));
-       printk("SDMMC_BLKSIZ: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BLKSIZ));
-       printk("SDMMC_BYTCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BYTCNT));
-       printk("SDMMC_INTMASK:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_INTMASK));
-       printk("SDMMC_CMDARG: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CMDARG));
-       printk("SDMMC_CMD:    \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CMD));
-       printk("SDMMC_RESP0:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP0));
-       printk("SDMMC_RESP1:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP1));
-       printk("SDMMC_RESP2:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP2));
-       printk("SDMMC_RESP3:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP3));
-       printk("SDMMC_MINTSTS:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_MINTSTS));
-       printk("SDMMC_RINTSTS:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RINTSTS));
-       printk("SDMMC_STATUS: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_STATUS));
-       printk("SDMMC_FIFOTH: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_FIFOTH));
-       printk("SDMMC_CDETECT:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CDETECT));
-       printk("SDMMC_WRTPRT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_WRTPRT));
-       printk("SDMMC_TCBCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TCBCNT));
-       printk("SDMMC_TBBCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TBBCNT));
-       printk("SDMMC_DEBNCE: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_DEBNCE));
-    printk("SDMMC_USRID: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_USRID));
-
-#if !defined(CONFIG_ARCH_RK29)         
-    printk("SDMMC_VERID: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_VERID));
-       printk("SDMMC_UHS_REG:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_UHS_REG));
-       printk("SDMMC_RST_n: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RST_n));
-       printk("SDMMC_CARDTHRCTL: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CARDTHRCTL));
-       printk("SDMMC_BACK_END_POWER: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BACK_END_POWER));
-#endif 
+    struct sdmmc_reg *regs = rk_sdmmc_regs;
+
+    while( regs->name != 0 )
+    {
+        printk("%s: (0x%04x) = 0x%08x\n", regs->name, regs->addr, rk29_sdmmc_read(host->regs,  regs->addr));
+        regs++;
+       }
+       
        printk("=======printk %s-register end =========\n", host->dma_name);
        return 0;
 }
@@ -362,9 +116,7 @@ static void rk29_sdmmc_enable_irq(struct rk29_sdmmc *host, bool irqflag)
        unsigned long flags;
 
     if(!host)
-    {
         return;
-    }
     
        local_irq_save(flags);
        if(host->irq_state != irqflag)
@@ -384,6 +136,18 @@ static void rk29_sdmmc_enable_irq(struct rk29_sdmmc *host, bool irqflag)
 
 
 #ifdef RK29_SDMMC_NOTIFY_REMOVE_INSERTION
+/*
+** debug the progress.
+**
+**  # echo version > sys/sd-sdio/rescan         //check the current sdmmc-driver version
+**
+**  # echo sd-reset > sys/sd-sdio/rescan        //run mmc0 mmc_rescan again
+**  # echo sd-regs > sys/sd-sdio/rescan         //printk all registers of mmc0.
+**
+**  # echo sdio1-reset > sys/sd-sdio/rescan     //run mmc1 mmc_rescan again
+**  # echo sdio1-regs > sys/sd-sdio/rescan      //printk all registers of mmc1.
+**
+*/
 ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *attr,
                         const char *buf, size_t count)
 {
@@ -549,8 +313,6 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a
     return count;
 }
 
-
-
 struct kobj_attribute mmc_reset_attrs = 
 {
         .attr = {
@@ -576,9 +338,8 @@ static int rk29_sdmmc_progress_add_attr( struct platform_device *pdev )
                 struct kobject *parentkobject; 
         struct kobject * me = kmalloc(sizeof(struct kobject) , GFP_KERNEL );
         if(!me)
-        {
             return -ENOMEM;
-        }
+            
         memset(me ,0,sizeof(struct kobject));
         kobject_init( me , &mmc_kset_ktype );
         
@@ -589,157 +350,6 @@ static int rk29_sdmmc_progress_add_attr( struct platform_device *pdev )
 }
 #endif
 
-#if defined (CONFIG_DEBUG_FS)
-static int rk29_sdmmc_regs_show(struct seq_file *s, void *v)
-{
-       struct rk29_sdmmc       *host = s->private;
-
-       seq_printf(s, "SDMMC_CTRL:   \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CTRL));
-       seq_printf(s, "SDMMC_PWREN:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_PWREN));
-       seq_printf(s, "SDMMC_CLKDIV: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKDIV));
-       seq_printf(s, "SDMMC_CLKSRC: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKSRC));
-       seq_printf(s, "SDMMC_CLKENA: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CLKENA));
-       seq_printf(s, "SDMMC_TMOUT:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TMOUT));
-       seq_printf(s, "SDMMC_CTYPE:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CTYPE));
-       seq_printf(s, "SDMMC_BLKSIZ: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BLKSIZ));
-       seq_printf(s, "SDMMC_BYTCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_BYTCNT));
-       seq_printf(s, "SDMMC_INTMASK:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_INTMASK));
-       seq_printf(s, "SDMMC_CMDARG: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CMDARG));
-       seq_printf(s, "SDMMC_CMD:    \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CMD));
-       seq_printf(s, "SDMMC_RESP0:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP0));
-       seq_printf(s, "SDMMC_RESP1:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP1));
-       seq_printf(s, "SDMMC_RESP2:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP2));
-       seq_printf(s, "SDMMC_RESP3:  \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RESP3));
-       seq_printf(s, "SDMMC_MINTSTS:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_MINTSTS));
-       seq_printf(s, "SDMMC_RINTSTS:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_RINTSTS));
-       seq_printf(s, "SDMMC_STATUS: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_STATUS));
-       seq_printf(s, "SDMMC_FIFOTH: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_FIFOTH));
-       seq_printf(s, "SDMMC_CDETECT:\t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_CDETECT));
-       seq_printf(s, "SDMMC_WRTPRT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_WRTPRT));
-       seq_printf(s, "SDMMC_TCBCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TCBCNT));
-       seq_printf(s, "SDMMC_TBBCNT: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_TBBCNT));
-       seq_printf(s, "SDMMC_DEBNCE: \t0x%08x\n", rk29_sdmmc_read(host->regs, SDMMC_DEBNCE));
-
-       return 0;
-}
-
-
-/*
- * The debugfs stuff below is mostly optimized away when
- * CONFIG_DEBUG_FS is not set.
- */
-static int rk29_sdmmc_req_show(struct seq_file *s, void *v)
-{
-       struct rk29_sdmmc       *host = s->private;
-       struct mmc_request      *mrq;
-       struct mmc_command      *cmd;
-       struct mmc_command      *stop;
-       struct mmc_data         *data;
-
-       /* Make sure we get a consistent snapshot */
-       spin_lock(&host->lock);
-       
-       mrq = host->mrq;
-
-       if (mrq) {
-               cmd = mrq->cmd;
-               data = mrq->data;
-               stop = mrq->stop;
-
-               if (cmd)
-                       seq_printf(s,
-                               "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
-                               cmd->opcode, cmd->arg, cmd->flags,
-                               cmd->resp[0], cmd->resp[1], cmd->resp[2],
-                               cmd->resp[2], cmd->error);
-               if (data)
-                       seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
-                               data->bytes_xfered, data->blocks,
-                               data->blksz, data->flags, data->error);
-               if (stop)
-                       seq_printf(s,
-                               "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
-                               stop->opcode, stop->arg, stop->flags,
-                               stop->resp[0], stop->resp[1], stop->resp[2],
-                               stop->resp[2], stop->error);
-       }
-
-       spin_unlock(&host->lock);
-
-       return 0;
-}
-
-static int rk29_sdmmc_req_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, rk29_sdmmc_req_show, inode->i_private);
-}
-
-static const struct file_operations rk29_sdmmc_req_fops = {
-       .owner          = THIS_MODULE,
-       .open           = rk29_sdmmc_req_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-
-static int rk29_sdmmc_regs_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, rk29_sdmmc_regs_show, inode->i_private);
-}
-
-static const struct file_operations rk29_sdmmc_regs_fops = {
-       .owner          = THIS_MODULE,
-       .open           = rk29_sdmmc_regs_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static void rk29_sdmmc_init_debugfs(struct rk29_sdmmc *host)
-{
-       struct mmc_host         *mmc = host->mmc;
-       struct dentry           *root;
-       struct dentry           *node;
-
-       root = mmc->debugfs_root;
-       if (!root)
-               return;
-
-       node = debugfs_create_file("regs", S_IRUSR, root, host,
-                       &rk29_sdmmc_regs_fops);
-       if (IS_ERR(node))
-               return;
-       if (!node)
-               goto err;
-
-       node = debugfs_create_file("req", S_IRUSR, root, host, &rk29_sdmmc_req_fops);
-       if (!node)
-               goto err;
-
-       node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state);
-       if (!node)
-               goto err;
-
-       node = debugfs_create_x32("pending_events", S_IRUSR, root,
-                                    (u32 *)&host->pending_events);
-       if (!node)
-               goto err;
-
-       node = debugfs_create_x32("completed_events", S_IRUSR, root,
-                                    (u32 *)&host->completed_events);
-       if (!node)
-               goto err;
-
-       return;
-
-err:
-       dev_err(&mmc->class_dev, "failed to initialize debugfs for host\n");
-}
-#endif
-
-
-
 /**
 **  This function checks whether the core supports the IDMAC.
 **  return Returns 1 if HW supports IDMAC, else returns 0.
@@ -757,9 +367,6 @@ u32 rk_sdmmc_check_idma_support(struct rk29_sdmmc *host)
        return retval;
 }
 
-
-
-
 static u32 rk29_sdmmc_prepare_command(struct mmc_command *cmd)
 {
        u32             cmdr = cmd->opcode;
@@ -769,7 +376,6 @@ static u32 rk29_sdmmc_prepare_command(struct mmc_command *cmd)
            case MMC_GO_IDLE_STATE: 
             cmdr |= (SDMMC_CMD_INIT | SDMMC_CMD_PRV_DAT_NO_WAIT);
             break;
-
         case MMC_STOP_TRANSMISSION:
             cmdr |= (SDMMC_CMD_STOP | SDMMC_CMD_PRV_DAT_NO_WAIT);
             break;
@@ -777,7 +383,6 @@ static u32 rk29_sdmmc_prepare_command(struct mmc_command *cmd)
         case MMC_GO_INACTIVE_STATE:   
             cmdr |= SDMMC_CMD_PRV_DAT_NO_WAIT;
             break;
-
         default:
             cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
             break;
@@ -1030,13 +635,9 @@ static void rk29_sdmmc_control_host_dma(struct rk29_sdmmc *host, bool enable)
     u32 value = rk29_sdmmc_read(host->regs, SDMMC_CTRL);
 
     if (enable)
-    {
         value |= SDMMC_CTRL_DMA_ENABLE;
-    }
     else
-    {
         value &= ~(SDMMC_CTRL_DMA_ENABLE);
-    }
 
     rk29_sdmmc_write(host->regs, SDMMC_CTRL, value);
 }
@@ -1044,10 +645,7 @@ static void rk29_sdmmc_control_host_dma(struct rk29_sdmmc *host, bool enable)
 static void send_stop_cmd(struct rk29_sdmmc *host)
 {
     int ret, i;
-   // int timeout = 250;
-   // unsigned int value;
-
-
+    
     if(host->mrq->cmd->error)
     {
         //stop DMA
@@ -1120,15 +718,42 @@ static void rk29_sdmmc_dma_complete(void *arg, int size, enum rk29_dma_buffresul
        host->intInfo.transLen = host->intInfo.desLen;  
 }
 
+static void rk_sdmmc_push_data32(struct rk29_sdmmc *host, void *buf, int cnt)
+{
+       u32 *pdata = (u32 *)buf;
+
+       WARN_ON(cnt % 4 != 0);
+       WARN_ON((unsigned long)pdata & 0x3);
+
+       cnt = cnt >> 2;
+       while (cnt > 0) {
+               rk29_sdmmc_write(host->regs, SDMMC_DATA, *pdata++);
+               cnt--;
+       }
+}
+
+static void rk_sdmmc_pull_data32(struct rk29_sdmmc *host, void *buf, int cnt)
+{
+       u32 *pdata = (u32 *)buf;
+
+       WARN_ON(cnt % 4 != 0);
+       WARN_ON((unsigned long)pdata & 0x3);
+
+       cnt = cnt >> 2;
+       while (cnt > 0) {
+               *pdata++ = rk29_sdmmc_read(host->regs, SDMMC_DATA);
+               cnt--;
+       }
+}
+
 static int rk29_sdmmc_read_data_pio(struct rk29_sdmmc *host)
 {
        struct scatterlist      *sg;
-       u32                     *buf;
-       unsigned int            offset = 0;
-       struct mmc_data         *data;
+       void    *buf;
+       unsigned int offset;
+       struct mmc_data  *data = host->data;
        u32                     value;
-       unsigned int            nbytes = 0;
-    int remaining;
+       unsigned int            nbytes=0, len;
 
     value = rk29_sdmmc_read(host->regs, SDMMC_STATUS);
        if ( value& SDMMC_STAUTS_FIFO_EMPTY)
@@ -1139,60 +764,55 @@ static int rk29_sdmmc_read_data_pio(struct rk29_sdmmc *host)
 
     if((NULL == host)&&(NULL == host->data))
         goto done;
-
-    data = host->data;
+        
        sg = host->sg;
-       buf = (u32 *)sg_virt(sg);
+       buf = sg_virt(sg);
+       offset =  host->pio_offset;
        
     while ( (host->intInfo.transLen < host->intInfo.desLen)  && (!(value & SDMMC_STAUTS_FIFO_EMPTY)) )
     {
-        if( ((offset + (host->intInfo.desLen - host->intInfo.transLen))<<2) <= sg->length )
-        {
-            buf[offset] = rk29_sdmmc_read(host->regs, SDMMC_DATA);
-            offset ++;
-               nbytes += 4;
-               host->intInfo.transLen++;
+        len = SDMMC_GET_FCNT(value) << PIO_DATA_SHIFT;
+        if (offset + len <= sg->length) {
+                       host->pull_data(host, (void *)(buf + offset), len);
 
-               if ((offset<<2) == sg->length) 
-               {
+                       offset += len;
+                       nbytes += len;
+                       host->intInfo.transLen++;
+
+                       if (offset == sg->length) {
                                flush_dcache_page(sg_page(sg));
                                host->sg = sg = sg_next(sg);
                                if (!sg)
                                        goto done;
 
                                offset = 0;
-                               buf = (u32 *)sg_virt(sg);
+                               buf = sg_virt(sg);
                        }
-               
-        }
-        else
-        {
-            remaining = (sg->length>>2) - offset;
-            while( remaining>0)
-            {
-                buf[offset] = rk29_sdmmc_read(host->regs, SDMMC_DATA);
-                offset ++;
-                   nbytes += 4;
-                   remaining --;
-                   host->intInfo.transLen++;
-            }
-
-            flush_dcache_page(sg_page(sg));
-
-               host->sg = sg = sg_next(sg);
-               if (!sg)
-                       goto done;
-
-            offset = 0;
-               buf = (u32 *)sg_virt(sg);                   
-        }
-
+               }else {
+                       unsigned int remaining = sg->length - offset;
+                       host->pull_data(host, (void *)(buf + offset),remaining);
+                       nbytes += remaining;
+                       host->intInfo.transLen++;
+
+                       flush_dcache_page(sg_page(sg));
+                       host->sg = sg = sg_next(sg);
+                       if (!sg)
+                               goto done;
+
+                       offset = len - remaining;
+                       buf = sg_virt(sg);
+                       host->pull_data(host, buf, offset);
+                       nbytes += offset;
+               }
+               
+        host->pio_offset = offset;
         data->bytes_xfered += nbytes;
 
         value = rk29_sdmmc_read(host->regs, SDMMC_STATUS);
     }
-
+    return 0;
 done:
+       data->bytes_xfered += nbytes;
     return 0;
 }
 
@@ -1200,12 +820,11 @@ done:
 static int rk29_sdmmc_write_data_pio(struct rk29_sdmmc *host)
 {
        struct scatterlist      *sg;
-       u32                     *buf;
-       unsigned int            offset = 0;
-       struct mmc_data         *data;
+       void    *buf;
+       unsigned int offset;
+       struct mmc_data         *data = host->data;
        u32                     value;
-       unsigned int            nbytes = 0;
-    int remaining;
+       unsigned int            nbytes=0, len;
 
     value = rk29_sdmmc_read(host->regs, SDMMC_STATUS);
        if ( value& SDMMC_STAUTS_FIFO_EMPTY)
@@ -1217,62 +836,61 @@ static int rk29_sdmmc_write_data_pio(struct rk29_sdmmc *host)
     if((NULL == host)&&(NULL == host->data))
         goto done;
 
-    data = host->data;
        sg = host->sg;
-       buf = (u32 *)sg_virt(sg);
-       
+       buf = sg_virt(sg);
+    offset =  host->pio_offset;
+
     while ( (host->intInfo.transLen < host->intInfo.desLen)  && (!(value & SDMMC_STAUTS_FIFO_EMPTY)) )
     {
-        if( ((offset + (host->intInfo.desLen - host->intInfo.transLen))<<2) <= sg->length )
-        {
-            rk29_sdmmc_write(host->regs, SDMMC_DATA, buf[offset]);
-            offset ++;
-               nbytes += 4;
-               host->intInfo.transLen++;
+        len = SDMMC_FIFO_SZ -(SDMMC_GET_FCNT(value) << PIO_DATA_SHIFT);
+               if (offset + len <= sg->length) {
+                       host->push_data(host, (void *)(buf + offset), len);
 
-               if ((offset<<2) == sg->length) 
-               {
+                       offset += len;
+                       nbytes += len;
+                       host->intInfo.transLen++;
+                       if (offset == sg->length) {
                                host->sg = sg = sg_next(sg);
                                if (!sg)
                                        goto done;
 
                                offset = 0;
-                               buf = (u32 *)sg_virt(sg);
+                               buf = sg_virt(sg);
                        }
-               
-        }
-        else
-        {
-            remaining = (sg->length>>2) - offset;
-            while( remaining>0)
-            {
-                rk29_sdmmc_write(host->regs, SDMMC_DATA, buf[offset]);
-                offset ++;
-                   nbytes += 4;
-                   remaining --;
-                   host->intInfo.transLen++;
-            }
-
-               host->sg = sg = sg_next(sg);
-               if (!sg)
-                       goto done;
-
-            offset = 0;
-               buf = (u32 *)sg_virt(sg);                   
-        }
+               } else {
+                       unsigned int remaining = sg->length - offset;
+
+                       host->push_data(host, (void *)(buf + offset),
+                                       remaining);
+                       nbytes += remaining;
+                       host->intInfo.transLen++;
+
+                       host->sg = sg = sg_next(sg);
+                       if (!sg)
+                               goto done;
+
+                       offset = len - remaining;
+                       buf = sg_virt(sg);
+                       host->push_data(host, (void *)buf, offset);
+                       nbytes += offset;
+               }
 
-        data->bytes_xfered += nbytes;
+        host->pio_offset = offset;
+           data->bytes_xfered += nbytes;
 
         value = rk29_sdmmc_read(host->regs, SDMMC_STATUS);
     }
     
+    return 0;
+    
 done:
+    data->bytes_xfered += nbytes;
     return 0;
 }
 
 static int rk29_sdmmc_submit_data_dma(struct rk29_sdmmc *host, struct mmc_data *data)
 {
-       unsigned int                    i,direction, sgDirection;
+       unsigned int    i,direction, sgDirection;
        int ret, dma_len=0;
        
        if(host->use_dma == 0)
@@ -1398,9 +1016,10 @@ static int rk29_sdmmc_prepare_write_data(struct rk29_sdmmc *host, struct mmc_dat
         host->intInfo.transLen = 0;
         host->intInfo.pBuf = (u32 *)pBuf;
         
-        if(0)//(host->intInfo.desLen <= 512 
+        if(0)//(host->intInfo.desLen <= TX_WMARK
         {  
-            //use pio-mode          
+            //use pio-mode 
+            rk29_sdmmc_write_data_pio(host);
             return SDM_SUCCESS;
         } 
         else 
@@ -1429,9 +1048,6 @@ static int rk29_sdmmc_prepare_write_data(struct rk29_sdmmc *host, struct mmc_dat
     return output;
 }
 
-
-
-
 static int rk29_sdmmc_prepare_read_data(struct rk29_sdmmc *host, struct mmc_data *data)
 {
     u32  count = 0;
@@ -1452,9 +1068,10 @@ static int rk29_sdmmc_prepare_read_data(struct rk29_sdmmc *host, struct mmc_data
        
     if(count > (RX_WMARK+1))  //datasheet error.actually, it can nont waken the interrupt when less and equal than RX_WMARK+1
     {
-        if(0) //(host->intInfo.desLen <= 512 )
+        if(0)//(host->intInfo.desLen <= RX_WMARK)
         {
             //use pio-mode
+            rk29_sdmmc_read_data_pio(host);
             return SDM_SUCCESS;
         }        
         else 
@@ -1538,6 +1155,7 @@ static void rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *dat
 
         data->bytes_xfered = 0;
         host->pbuf = (u32*)sg_virt(data->sg);
+        host->pio_offset = 0;
 
         if (data->flags & MMC_DATA_STREAM)
                {
@@ -4057,6 +3675,12 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
                host->dma_addr = regs->start + SDMMC_DATA;
        }
 
+    /*
+        * Get the host data width,default 32bit
+       */
+    host->push_data = rk_sdmmc_push_data32;
+       host->pull_data = rk_sdmmc_pull_data32;
+
 #if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT)
        host->write_protect = pdata->write_prt;
        host->protect_level = pdata->write_prt_enalbe_level;
@@ -4212,10 +3836,6 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
     }
 #endif 
        
-#if defined (CONFIG_DEBUG_FS)
-       rk29_sdmmc_init_debugfs(host);
-#endif
-
     printk(KERN_INFO ".Line%d..The End of SDMMC-probe %s.  [%s]\n", __LINE__, RK29_SDMMC_VERSION,host->dma_name);
        return 0;
 
index 8bcd32491df5ab68092d8084d366f95cb48be220..53853b95ecca9aedac90751965aebaf1e7cfad1d 100755 (executable)
 #define SDMMC_DATA            SDMMC_FIFO_BASE
 #endif
 
+struct sdmmc_reg
+{
+  u32      addr;
+  char   * name;
+};
+
+static struct sdmmc_reg rk_sdmmc_regs[] =
+{
+  { 0x0000, "      CTRL" },
+  { 0x0004, "     PWREN" },
+  { 0x0008, "    CLKDIV" },
+  { 0x000C, "    CLKSRC" },
+  { 0x0010, "    CLKENA" },
+  { 0x0014, "     TMOUT" },
+  { 0x0018, "     CTYPE" },
+  { 0x001C, "    BLKSIZ" },
+  { 0x0020, "    BYTCNT" },
+  { 0x0024, "    INTMSK" },
+  { 0x0028, "    CMDARG" },
+  { 0x002C, "       CMD" },
+  { 0x0030, "     RESP0" },
+  { 0x0034, "     RESP1" },
+  { 0x0038, "     RESP2" },
+  { 0x003C, "     RESP3" },
+  { 0x0040, "    MINSTS" },
+  { 0x0044, "   RINTSTS" },
+  { 0x0048, "    STATUS" },
+  { 0x004C, "    FIFOTH" },
+  { 0x0050, "   CDETECT" },
+  { 0x0054, "    WRTPRT" },
+  { 0x0058, "      GPIO" },
+  { 0x005C, "    TCBCNT" },
+  { 0x0060, "    TBBCNT" },
+  { 0x0064, "    DEBNCE" },
+  { 0x0068, "     USRID" },
+#if !defined(CONFIG_ARCH_RK29)  
+  { 0x006C, "     VERID" },
+  { 0x0070, "      HCON" },
+  { 0x0074, "   UHS_REG" },
+  { 0x0078, "     RST_n" },
+  { 0x0080, "      BMOD" },
+  { 0x0084, "    PLDMND" },
+  { 0x0088, "    DBADDR" },
+  { 0x008C, "     IDSTS" },
+  { 0x0090, "   IDINTEN" },
+  { 0x0094, "   DSCADDR" },
+  { 0x0098, "   BUFADDR" },
+  { 0x0100, "CARDTHRCTL" },
+  { 0x0104, "BackEndPwr" },
+#endif  
+  { 0, 0 }
+};
+
 #define BIT(n)                         (1<<(n))
 #define RK_CLEAR_BIT(n)                        (0<<(n))
 
 #define SDMMC_CLKEN_LOW_PWR      BIT(16)
 #define SDMMC_CLKEN_NO_LOW_PWR   RK_CLEAR_BIT(16)   //low-power mode disabled
 #define SDMMC_CLKEN_ENABLE       BIT(0)
-#define SDMMC_CLKEN_DISABLE      RK_CLEAR_BIT(16)   //clock disabled
+#define SDMMC_CLKEN_DISABLE      RK_CLEAR_BIT(0)   //clock disabled
 
 /* time-out register defines(base+0x14) */
 #define SDMMC_TMOUT_DATA(n)      _SBF(8, (n))
 #define SDMMC_STAUTS_FIFO_EMPTY            BIT(2)          //FIFO is empty status
 
 /* Status register defines */
-#define SDMMC_GET_FCNT(x)           (((x)>>17) & 0x1FF)//fifo_count, numbers of filled locations in FIFO
+#define SDMMC_GET_FCNT(x)           (((x)>>17) & 0x1FFF)//fifo_count, numbers of filled locations in FIFO
 #define SDMMC_FIFO_SZ               32
+#define PIO_DATA_SHIFT              2
 
 
 /* FIFO Register (base + 0x4c)*/
 #define SDM_WAIT_FOR_CMDSTART_TIMEOUT   (12)  
 #define SDM_WAIT_FOR_FIFORESET_TIMEOUT  (13)  
 
-
-
 #define FALSE                  0
 #define TRUE                   1
 
-
 #define DEBOUNCE_TIME         (25)     //uint is ms, recommend 5--25ms
 
+#if defined(CONFIG_ARCH_RK29)
+#define SDMMC_USE_INT_UNBUSY     0
+#else
+#define SDMMC_USE_INT_UNBUSY     0///1 
+#endif
+
+/*
+** You can set the macro to true, if some module wants to use this feature, which is about SDIO suspend-resume.
+** As the following example.
+** added by xbw at 2013-05-08
+*/
+#if defined(CONFIG_MTK_COMBO_DRIVER_VERSION_JB2)
+#define RK_SDMMC_USE_SDIO_SUSPEND_RESUME    1
+#else
+#define RK_SDMMC_USE_SDIO_SUSPEND_RESUME    0
+#endif
+
+#define RK29_SDMMC_ERROR_FLAGS         (SDMMC_INT_FRUN | SDMMC_INT_HLE )
+
+#if defined(CONFIG_SDMMC0_RK29_SDCARD_DET_FROM_GPIO)
+    #if SDMMC_USE_INT_UNBUSY
+    #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS )
+    #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_TXDR | SDMMC_INT_RXDR )
+    #else
+    #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS )
+    #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_TXDR | SDMMC_INT_RXDR )
+    #endif
+#else
+    #if SDMMC_USE_INT_UNBUSY
+    #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD)
+    #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD| SDMMC_INT_TXDR | SDMMC_INT_RXDR )
+    #else
+    #define RK29_SDMMC_INTMASK_USEDMA   (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD)
+    #define RK29_SDMMC_INTMASK_USEIO    (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD| SDMMC_INT_TXDR | SDMMC_INT_RXDR )
+    #endif
+#endif
+
+#define RK29_SDMMC_SEND_START_TIMEOUT   3000  //The time interval from the time SEND_CMD to START_CMD_BIT cleared.
+#define RK29_ERROR_PRINTK_INTERVAL      200   //The time interval between the two printk for the same error. 
+#define RK29_SDMMC_WAIT_DTO_INTERNVAL   4500  //The time interval from the CMD_DONE_INT to DTO_INT
+#define RK29_SDMMC_REMOVAL_DELAY        2000  //The time interval from the CD_INT to detect_timer react.
+
+//#define RK29_SDMMC_VERSION "Ver.6.00 The last modify date is 2013-08-02"
+
+#if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) 
+#define RK29_CTRL_SDMMC_ID   0  //mainly used by SDMMC
+#define RK29_CTRL_SDIO1_ID   1  //mainly used by sdio-wifi
+#define RK29_CTRL_SDIO2_ID   2  //mainly used by sdio-card
+#else
+#define RK29_CTRL_SDMMC_ID   5  
+#define RK29_CTRL_SDIO1_ID   1  
+#define RK29_CTRL_SDIO2_ID   2  
+#endif
+
+#define SDMMC_CLOCK_TEST     0
+
+#define RK29_SDMMC_NOTIFY_REMOVE_INSERTION /* use sysfs to notify the removal or insertion of sd-card*/
+//#define RK29_SDMMC_LIST_QUEUE            /* use list-queue for multi-card*/
+
+//support Internal DMA 
+#if 0 //Sometime in the future to enable
+#define DRIVER_SDMMC_USE_IDMA 1
+#else
+#define DRIVER_SDMMC_USE_IDMA 0
+#endif
+
+
+enum {
+       EVENT_CMD_COMPLETE = 0,
+       EVENT_DATA_COMPLETE,
+       EVENT_DATA_UNBUSY,
+       EVENT_DATA_ERROR,
+       EVENT_XFER_ERROR
+};
+
+enum rk29_sdmmc_state {
+       STATE_IDLE = 0,
+       STATE_SENDING_CMD,
+       STATE_DATA_BUSY,
+       STATE_DATA_UNBUSY,
+       STATE_DATA_END,
+       STATE_SENDING_STOP,
+};
+
+struct rk29_sdmmc_dma_info {
+       enum dma_ch chn;
+       char *name;
+       struct rk29_dma_client client;
+};
+
+static struct rk29_sdmmc_dma_info rk29_sdmmc_dma_infos[]= {
+       {
+               .chn = DMACH_SDMMC,
+               .client = {
+                       .name = "rk29-dma-sdmmc0",
+               }
+       },
+       {
+               .chn = DMACH_SDIO,
+               .client = {
+                       .name = "rk29-dma-sdio1",
+               }
+       },
+
+       {
+               .chn = DMACH_EMMC,
+               .client = {
+                       .name = "rk29-dma-sdio2",
+               }
+       },
+};
+
+
+/* Interrupt Information */
+typedef struct TagSDC_INT_INFO
+{
+    u32     transLen;               //the length of data sent.
+    u32     desLen;                 //the total length of the all data.
+    u32    *pBuf;                   //the data buffer for interrupt read or write.
+}SDC_INT_INFO_T;
+
+
+struct rk29_sdmmc {
+       spinlock_t              lock;
+       void __iomem    *regs;
+       struct clk              *clk;
+
+       struct mmc_request      *mrq;
+       struct mmc_request      *new_mrq;
+       struct mmc_command      *cmd;
+       struct mmc_data         *data;  
+       struct scatterlist      *sg;
+       unsigned int            pio_offset;
+
+       dma_addr_t              dma_addr;;
+       unsigned int    use_dma:1;
+       char                    dma_name[8];
+       u32                     cmd_status;
+       u32                     data_status;
+       u32                     stop_cmdr;
+
+    u32         old_div;
+       u32                     cmdr;   //the value setted into command-register
+       u32                     dodma;  //sign the DMA used for transfer.
+       u32         errorstep;//record the error point.
+       int         timeout_times;  //use to force close the sdmmc0 when the timeout_times exceeds the limit.
+       u32         *pbuf;
+       SDC_INT_INFO_T    intInfo; 
+    struct rk29_sdmmc_dma_info         dma_info;
+    int         irq;
+       int error_times;
+       u32 old_cmd;
+       
+       struct tasklet_struct   tasklet;
+       unsigned long           pending_events;
+       unsigned long           completed_events;
+       enum rk29_sdmmc_state   state;
+
+#ifdef RK29_SDMMC_LIST_QUEUE
+       struct list_head        queue;
+       struct list_head        queue_node;
+#endif
+
+       u32                     bus_hz;
+       struct platform_device  *pdev;
+       struct mmc_host         *mmc;
+       u32                     ctype;
+       unsigned int            clock;
+       unsigned long           flags;
+       
+#define RK29_SDMMC_CARD_PRESENT        0
+
+       int                     id;
+
+       struct timer_list       detect_timer; 
+       struct timer_list       request_timer; //the timer for INT_CMD_DONE
+       struct timer_list       DTO_timer;     //the timer for INT_DTO
+       struct mmc_command      stopcmd;
+    struct rksdmmc_gpio det_pin;
+
+       /* flag for current bus settings */
+    u32 bus_mode;
+
+    unsigned int            oldstatus;
+    unsigned int            complete_done;
+    unsigned int            retryfunc;
+    
+    int gpio_irq;
+       int gpio_power_en;
+       int gpio_power_en_level;
+       struct delayed_work             work;
+
+#ifdef CONFIG_RK29_SDIO_IRQ_FROM_GPIO
+    unsigned int sdio_INT_gpio;
+    unsigned int sdio_irq;
+    unsigned long trigger_level;
+#endif
+
+#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT)
+    int write_protect;
+    int protect_level;
+#endif
+
+       bool                    irq_state;
+    void (*set_iomux)(int device_id, unsigned int bus_width);
+
+    /* FIFO push and pull */
+    int         data_shift;
+    void (*push_data)(struct rk29_sdmmc *host, void *buf, int cnt);
+    void (*pull_data)(struct rk29_sdmmc *host, void *buf, int cnt);
+};
+
+
+#ifdef RK29_SDMMC_NOTIFY_REMOVE_INSERTION
+static struct rk29_sdmmc    *globalSDhost[3];
+#endif
+
+#define rk29_sdmmc_test_and_clear_pending(host, event)         \
+       test_and_clear_bit(event, &host->pending_events)
+#define rk29_sdmmc_test_pending(host, event)           \
+       test_bit(event, &host->pending_events)
+#define rk29_sdmmc_test_completed(host, event)           \
+        test_bit(event, &host->completed_events)       
+#define rk29_sdmmc_set_completed(host, event)                  \
+       set_bit(event, &host->completed_events)
+#define rk29_sdmmc_set_pending(host, event)                            \
+       set_bit(event, &host->pending_events)
+
+
 
 #endif