Bernard Blackham wrote:
> This is actually a forward port of the SD/MMC driver from the latest
> LSP, melded into linux-2.6.23-git. I've tried to keep the style
> updates that were merged recently. I fixed the exit code (in
> davinci_mmcsd_exit) to release clocks, and some failure paths in
> davinci_mmcsd_init.
> 
> This is probably not quite what David and Dirk were wanting, as it's
> probably further from being merged upstream than previously.
> However, it works for me (have tried reading/writing an SD card
> successfully, reading at about ~6MB/s and writing at ~1MB/s). It
> hasn't been put under particularly strenuous testing either, so
> beware.

At this point, I'm willing to take something that works, but needs
rework/cleanup as it's better than what is there today.

Also, there's a whole new MMC/SD/SDIO framework headed for mailine, so
it will probably need some rework for that as well.  But with a couple
minor cleanups as mentioned below, I'll merge it.

Please add a Signed-off-by: line as well.

> 
>  davinci_mmc.c |  748 
> ++++++++++++++++++++++++++++++++++++++--------------------
>  davinci_mmc.h |   23 +
>  2 files changed, 520 insertions(+), 251 deletions(-)
> 
> diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
> index 5d8e79f..3a635d0 100644
> --- a/drivers/mmc/host/davinci_mmc.c
> +++ b/drivers/mmc/host/davinci_mmc.c
> @@ -24,13 +24,17 @@
>   Modifications:
>   ver. 1.0: Oct 2005, Purushotam Kumar   Initial version
>   ver 1.1:  Nov  2005, Purushotam Kumar  Solved bugs
> - ver 1.2:  Jan  2066, Purushotam Kumar   Added card remove insert support
> + ver 1.2:  Jan  2006, Purushotam Kumar   Added card remove insert support

What, you don't think he could've done this update in the future?  ;)

> -
>   */
>  
>  #include <linux/module.h>
> +#include <linux/version.h>
> +/* DEBUG check shall be made before kernel.h or device.h is included */
> +#ifdef CONFIG_MMC_DEBUG
> +#define DEBUG
> +#endif

You don't need this, as the equivalent is already done by the Makefile.

>  #include <linux/tty.h>
>  #include <linux/ioport.h>
>  #include <linux/init.h>
> @@ -41,35 +45,25 @@ #include <linux/clk.h>
>  #include <linux/mmc/host.h>
>  #include <linux/mmc/card.h>
>  #include <linux/mmc/mmc.h>
> -
>  #include <asm/io.h>
>  #include <asm/irq.h>
>  #include <asm/hardware.h>
> +#include <linux/delay.h>
> +#include <linux/dma-mapping.h>
>  #include <asm/arch/irqs.h>
>  #include <asm/arch/hardware.h>
>  
>  #include "davinci_mmc.h"
>  #include <asm/arch/edma.h>
>  
> -/* FIXME: old defines  from old mmc.h */
> -/* #define MMC_RSP_NONE      (0 << 0) */
> -/* #define MMC_RSP_SHORT     (1 << 0) */
> -/* #define MMC_RSP_LONG      (2 << 0) */
> -/* #define MMC_RSP_MASK      (3 << 0) */
> -/* #define MMC_RSP_CRC       (1 << 3)                /\* expect valid crc 
> *\/ */
> -/* #define MMC_RSP_BUSY      (1 << 4)                /\* card may send busy 
> *\/ */
> -#define MMC_RSP_SHORT        MMC_RSP_PRESENT
> -#define MMC_RSP_LONG    MMC_RSP_136
> -#define MMC_RSP_MASK    (MMC_RSP_PRESENT | MMC_RSP_136)
> -
>  extern void davinci_clean_channel(int ch_no);
>  
>  /* MMCSD Init clock in Hz in opendain mode */
> -#define MMCSD_INIT_CLOCK             200000
> -#define DRIVER_NAME                  "mmc0"
> -#define MMCINT_INTERRUPT             IRQ_MMCINT
> -#define MMCSD_REGS_BASE_ADDR         DAVINCI_MMC_SD_BASE
> -#define TCINTEN                              (0x1<<20)
> +#define MMCSD_INIT_CLOCK             200000
> +#define DRIVER_NAME                  "mmc0"
> +#define MMCINT_INTERRUPT             IRQ_MMCINT
> +#define MMCSD_REGS_BASE_ADDR                 DAVINCI_MMC_SD_BASE
> +#define TCINTEN                      (0x1<<20)
>  
>  /* This macro could not be defined to 0 (ZERO) or -ve value.
>   * This value is multiplied to "HZ"
> @@ -83,6 +77,8 @@ mmcsd_config_def mmcsd_cfg = {
>  /* read write thresholds (in bytes) can be any power of 2 from 2 to 64 */
>       32,
>  /* To use the DMA or not-- 1- Use DMA, 0-Interrupt mode */
> +     1,
> +/* flag Indicates 1bit/4bit mode */
>       1
>  };
>  
> @@ -107,54 +103,71 @@ static struct mmc_request *que_mmc_reque
>  /* tells whether card is initizlzed or not */
>  static unsigned int is_card_initialized = 0;
>  static unsigned int new_card_state = 0;      /* tells current state of card 
> */
> +static unsigned int is_card_removed = 0;
>  
>  static DEFINE_SPINLOCK(mmc_lock);
>  
> +#define RSP_TYPE(x)  ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
> +#define MMCST1_BUSY  (1 << 0)
> +
> +static inline void wait_on_data(void)
> +{
> +     int cnt = 900000;
> +     while (((mmcsd_regs->mmc_st1) & MMCST1_BUSY) && cnt) {
> +             cnt--;
> +             udelay(1);
> +     }
> +     if (!cnt) {
> +             dev_warn(&mmc_dev, "ERROR: TOUT waiting for BUSY\n");
> +     }
> +}
> +
>  static void mmc_davinci_start_command(struct mmc_davinci_host *host,
>               struct mmc_command *cmd)
>  {
>       u32 cmd_reg = 0;
>       u32 resp_type = 0;
>       u32 cmd_type = 0;
> -     int byte_cnt = 0, i = 0;
>       unsigned long flags;
>  
> +#ifdef CONFIG_MMC_DEBUG
>       dev_dbg(&mmc_dev, "\nMMCSD : CMD%d, argument 0x%08x",
>               cmd->opcode, cmd->arg);
> -     if (cmd->flags & MMC_RSP_SHORT)
> -             dev_dbg(&mmc_dev, ", 32-bit response");
> -     if (cmd->flags & MMC_RSP_LONG)
> -             dev_dbg(&mmc_dev, ", 128-bit response");
> -     if (cmd->flags & MMC_RSP_CRC)
> -             dev_dbg(&mmc_dev, ", CRC");
> -     if (cmd->flags & MMC_RSP_BUSY)
> -             dev_dbg(&mmc_dev, ", busy notification");
> -     else
> -             dev_dbg(&mmc_dev, ", No busy notification");
> +     switch (RSP_TYPE(mmc_resp_type(cmd))) {
> +     case RSP_TYPE(MMC_RSP_R1):
> +             dev_dbg(&mmc_dev, ", R1/R1b response");
> +             break;
> +     case RSP_TYPE(MMC_RSP_R2):
> +             dev_dbg(&mmc_dev, ", R2 response");
> +             break;
> +     case RSP_TYPE(MMC_RSP_R3):
> +             dev_dbg(&mmc_dev, ", R3 response");
> +             break;
> +     default:
> +             break;
> +     }
>       dev_dbg(&mmc_dev, "\n");
> +#endif
>       host->cmd = cmd;
>  
>       /* Protocol layer does not provide response type,
>        * but our hardware needs to know exact type, not just size!
>        */
> -     switch (cmd->flags & MMC_RSP_MASK) {
> +     switch (RSP_TYPE(mmc_resp_type(cmd))) {
>       case MMC_RSP_NONE:
>               /* resp 0 */
>               break;
> -     case MMC_RSP_SHORT:
> -             /* resp 1, resp 1b */
> -             /* OR resp 3!! (assume this if bus is set opendrain) */
> -             if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) {
> -                     resp_type = 3;
> -                     if (cmd->opcode == 3)
> -                             resp_type = 1;
> -             } else
> -                     resp_type = 1;
> +     case RSP_TYPE(MMC_RSP_R1):
> +             resp_type = 1;
>               break;
> -     case MMC_RSP_LONG:
> -             /* resp 2 */
> +     case RSP_TYPE(MMC_RSP_R2):
>               resp_type = 2;
>               break;
> +     case RSP_TYPE(MMC_RSP_R3):
> +             resp_type = 3;
> +             break;
> +     default:
> +             break;
>       }
>  
>       /* Protocol layer does not provide command type, but our hardware
> @@ -171,11 +184,11 @@ static void mmc_davinci_start_command(st
>        * rest are ac, except if opendrain
>        */
>  
> -     if (host->data_dir)
> +     if (mmc_cmd_type(cmd) == MMC_CMD_ADTC)
>               cmd_type = DAVINCI_MMC_CMDTYPE_ADTC;
> -     else if (resp_type == 0 && cmd->opcode != 15)
> +     else if (mmc_cmd_type(cmd) == MMC_CMD_BC)
>               cmd_type = DAVINCI_MMC_CMDTYPE_BC;
> -     else if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
> +     else if (mmc_cmd_type(cmd) == MMC_CMD_BCR)
>               cmd_type = DAVINCI_MMC_CMDTYPE_BCR;
>       else
>               cmd_type = DAVINCI_MMC_CMDTYPE_AC;
> @@ -198,10 +211,9 @@ static void mmc_davinci_start_command(st
>               cmd_reg = cmd_reg | (1 << 14);
>  
>       /* Set for generating DMA Xfer event */
> -     if ((host->use_dma == 1) && (host->data != NULL)
> -                     && ((cmd->opcode == 18) || (cmd->opcode == 25)
> -                             || (cmd->opcode == 24)
> -                             || (cmd->opcode == 17)))
> +     if ((host->do_dma == 1) && (host->data != NULL)
> +         && ((cmd->opcode == 18) || (cmd->opcode == 25)
> +             || (cmd->opcode == 24) || (cmd->opcode == 17)))
>               cmd_reg = cmd_reg | (1 << 16);
>  
>       /* Setting whether command involves data transfer or not */
> @@ -227,7 +239,7 @@ static void mmc_davinci_start_command(st
>  
>       /* Enable interrupt */
>       if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
> -             if (host->use_dma != 1)
> +             if (host->do_dma != 1)
>                       mmcsd_regs->mmc_im = MMCSD_EVENT_EOFCMD
>                                       | MMCSD_EVENT_WRITE
>                                       | MMCSD_EVENT_ERROR_CMDCRC
> @@ -243,7 +255,7 @@ static void mmc_davinci_start_command(st
>                                       | MMCSD_EVENT_ERROR_DATATIMEOUT
>                                       | MMCSD_EVENT_BLOCK_XFERRED;
>       } else if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
> -             if (host->use_dma != 1)
> +             if (host->do_dma != 1)
>                       mmcsd_regs->mmc_im = MMCSD_EVENT_EOFCMD
>                                       | MMCSD_EVENT_READ
>                                       | MMCSD_EVENT_ERROR_CMDCRC
> @@ -271,25 +283,22 @@ static void mmc_davinci_start_command(st
>        */
>       if ((host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
>                       && (cmd_type == DAVINCI_MMC_CMDTYPE_ADTC)
> -                     && (host->use_dma != 1)) {
> -             byte_cnt = mmcsd_cfg.rw_threshold;
> -             host->bytes_left -= mmcsd_cfg.rw_threshold;
> -             for (i = 0; i < (byte_cnt / 4); i++) {
> -                     mmcsd_regs->mmc_dxr = *host->buffer;
> -                     host->buffer++;
> -             }
> -     }
> +                     && (host->do_dma != 1))
> +             /* Fill the FIFO for Tx */
> +             davinci_fifo_data_trans(host);
>  
>       if (cmd->opcode == 7) {
>               spin_lock_irqsave(&mmc_lock, flags);
> +             is_card_removed = 0;
>               new_card_state = 1;
>               is_card_initialized = 1;
>               host->old_card_state = new_card_state;
>               is_init_progress = 0;
>               spin_unlock_irqrestore(&mmc_lock, flags);
>       }
> -     if (cmd->opcode == 1) {
> +     if (cmd->opcode == 1 || cmd->opcode == 41) {
>               spin_lock_irqsave(&mmc_lock, flags);
> +             is_card_initialized = 0;
>               is_init_progress = 1;
>               spin_unlock_irqrestore(&mmc_lock, flags);
>       }
> @@ -302,47 +311,178 @@ static void mmc_davinci_start_command(st
>  
>  static void mmc_davinci_dma_cb(int lch, u16 ch_status, void *data)
>  {
> -     int sync_dev = 0;
> -     struct mmc_davinci_host *host = (struct mmc_davinci_host *)data;
> +     if (DMA_COMPLETE != ch_status) {
> +             struct mmc_davinci_host *host = (struct mmc_davinci_host *)data;
> +             dev_warn(&mmc_dev, "[DMA FAILED]");
> +             davinci_abort_dma(host);
> +     }
> +}
>  
> -     if (DMA_COMPLETE == ch_status) {
> +static void davinci_fifo_data_trans(struct mmc_davinci_host *host)
> +{
> +     int n, i;
>  
> -             if (host->cmd == NULL && host->data == NULL) {
> -                     if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
> -                             sync_dev = DAVINCI_DMA_MMCTXEVT;
> -                     } else {
> -                             sync_dev = DAVINCI_DMA_MMCRXEVT;
> -                     }
> -                     dev_dbg(&mmc_dev,
> -                             "Interrupt from DMA when no request has been 
> made\n");
> -                     davinci_stop_dma(sync_dev);
> -                     return;
> -             }
> +     if (host->buffer_bytes_left == 0) {
> +             host->sg_idx++;
> +             BUG_ON(host->sg_idx == host->sg_len);
> +             mmc_davinci_sg_to_buf(host);
> +     }
>  
> -             if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
> -                     sync_dev = DAVINCI_DMA_MMCTXEVT;        /* Write */
> -             } else {
> -                     sync_dev = DAVINCI_DMA_MMCRXEVT;        /* Read */
> +     n = mmcsd_cfg.rw_threshold;
> +     if (n > host->buffer_bytes_left)
> +             n = host->buffer_bytes_left;
> +     host->buffer_bytes_left -= n;
> +     host->bytes_left -= n;
> +
> +     if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
> +             for (i = 0; i < (n / 4); i++) {
> +                     mmcsd_regs->mmc_dxr = *host->buffer;
> +                     host->buffer++;
>               }
> -             davinci_stop_dma(sync_dev);
>       } else {
> -             /* Handing of Event missed interreupt from DMA */
> -             dev_dbg(&mmc_dev,
> -                     "Event miss interrupt has been generated by DMA\n");
> -             if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
> -                     sync_dev = DAVINCI_DMA_MMCTXEVT;        /* Write */
> -             } else {
> -                     sync_dev = DAVINCI_DMA_MMCRXEVT;        /* Read */
> +             for (i = 0; i < (n / 4); i++) {
> +                     *host->buffer = mmcsd_regs->mmc_drr;
> +                     host->buffer++;
>               }
> -             davinci_clean_channel(sync_dev);
>       }
>  }
>  
> +static void davinci_reinit_chan(void)
> +{
> +     int sync_dev;
> +
> +     sync_dev = DAVINCI_DMA_MMCTXEVT;
> +     davinci_stop_dma(sync_dev);
> +     davinci_clean_channel(sync_dev);
> +
> +     sync_dev = DAVINCI_DMA_MMCRXEVT;
> +     davinci_stop_dma(sync_dev);
> +     davinci_clean_channel(sync_dev);
> +}
> +
> +static void davinci_abort_dma(struct mmc_davinci_host *host)
> +{
> +     int sync_dev = 0;
> +
> +     if (host->data_dir == DAVINCI_MMC_DATADIR_READ)
> +             sync_dev = DAVINCI_DMA_MMCTXEVT;
> +     else
> +             sync_dev = DAVINCI_DMA_MMCRXEVT;
> +
> +     davinci_stop_dma(sync_dev);
> +     davinci_clean_channel(sync_dev);
> +
> +}
> +
>  static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host,
>               struct mmc_request *req)
>  {
> -     const char *dev_name;
> -     int sync_dev, r, edma_ch = 0, tcc = 0;
> +     int use_dma = 1, i;
> +     struct mmc_data *data = host->data;
> +     int block_size = data->blksz;
> +
> +     host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
> +                             ((data->flags & MMC_DATA_WRITE)
> +                             ? DMA_TO_DEVICE
> +                             : DMA_FROM_DEVICE));
> +
> +     /* Decide if we can use DMA */
> +     for (i = 0; i < host->sg_len; i++) {
> +             if ((data->sg[i].length % block_size) != 0) {
> +                     use_dma = 0;
> +                     break;
> +             }
> +     }
> +
> +     if (!use_dma) {
> +             dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
> +                               (data->flags & MMC_DATA_WRITE)
> +                             ? DMA_TO_DEVICE
> +                             : DMA_FROM_DEVICE);
> +             return -1;
> +     }
> +
> +     host->do_dma = 1;
> +
> +     host->dma_state = 0;
> +
> +     mmc_davinci_send_dma_request(host, req);
> +
> +     return 0;
> +
> +}
> +
> +static int davinci_release_dma_channels(struct mmc_davinci_host *host)
> +{
> +     davinci_free_dma(DAVINCI_DMA_MMCTXEVT);
> +     davinci_free_dma(DAVINCI_DMA_MMCRXEVT);
> +
> +     if (host->edma_ch_details.cnt_chanel) {
> +             davinci_free_dma(host->edma_ch_details.chanel_num[0]);
> +             host->edma_ch_details.cnt_chanel = 0;
> +     }
> +
> +     return 0;
> +}
> +
> +static int davinci_acquire_dma_channels(struct mmc_davinci_host *host)
> +{
> +     int edma_chan_num, tcc = 0, r, sync_dev;
> +     enum dma_event_q queue_no = EVENTQ_0;
> +
> +     /* Acquire master DMA write channel */
> +     if ((r = davinci_request_dma(DAVINCI_DMA_MMCTXEVT, "MMC_WRITE",
> +                     mmc_davinci_dma_cb, host, &edma_chan_num, &tcc,
> +                     queue_no)) != 0) {
> +             dev_warn(&mmc_dev,
> +                             "MMC: davinci_request_dma() failed with %d\n",
> +                             r);
> +             return r;
> +     }
> +
> +     /* Acquire master DMA read channel */
> +     if ((r = davinci_request_dma(DAVINCI_DMA_MMCRXEVT, "MMC_READ",
> +                     mmc_davinci_dma_cb, host, &edma_chan_num, &tcc,
> +                     queue_no)) != 0) {
> +             dev_warn(&mmc_dev,
> +                             "MMC: davinci_request_dma() failed with %d\n",
> +                             r);
> +             goto free_master_write;
> +     }
> +
> +     host->edma_ch_details.cnt_chanel = 0;
> +
> +     /* currently data Writes are done using single block mode,
> +      * so no DMA slave write channel is required for now */
> +
> +     /* Create a DMA slave read channel 
> +      * (assuming max segments handled is 2) */
> +     sync_dev = DAVINCI_DMA_MMCRXEVT;
> +     if ((r = davinci_request_dma(DAVINCI_EDMA_PARAM_ANY, "LINK",
> +                     NULL, NULL, &edma_chan_num, &sync_dev,
> +                     queue_no)) != 0) {
> +             dev_warn(&mmc_dev,
> +                     "MMC: davinci_request_dma() failed with %d\n", r);
> +             goto free_master_read;
> +     }
> +
> +     host->edma_ch_details.cnt_chanel++;
> +     host->edma_ch_details.chanel_num[0] = edma_chan_num;
> +
> +     return 0;
> +
> +free_master_read:
> +     davinci_free_dma(DAVINCI_DMA_MMCRXEVT);
> +free_master_write:
> +     davinci_free_dma(DAVINCI_DMA_MMCTXEVT);
> +
> +     return r;
> +}
> +
> +static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
> +                                     struct mmc_request *req)
> +{
> +     int sync_dev;
>       unsigned char i, j;
>       unsigned short acnt, bcnt, ccnt;
>       unsigned int src_port, dst_port, temp_ccnt;
> @@ -353,69 +493,50 @@ static int mmc_davinci_start_dma_transfe
>       unsigned short bcntrld;
>       enum sync_dimension sync_mode;
>       edmacc_paramentry_regs temp;
> -     enum dma_event_q queue_no = EVENTQ_0;
>       int edma_chan_num;
> -     unsigned int num_eight_words = (req->data->blocks * 512) / 32;
>       static unsigned int option_read = 0;
>       static unsigned int option_write = 0;
> -     static unsigned char dma_read_req = 1;
> -     static unsigned char dma_write_req = 1;
> +     struct mmc_data *data = host->data;
> +     struct scatterlist *sg = &data->sg[0];
> +     unsigned int count;
> +     int num_frames, frame;
>  
>  #define MAX_C_CNT            64000
>  
> -     if ((req->data->flags & MMC_DATA_WRITE)) {
> -             sync_dev = DAVINCI_DMA_MMCTXEVT;        /* Write */
> -             dev_name = "MMC_WRITE";
> +     frame = data->blksz;
> +     count = sg_dma_len(sg);
>  
> -             if (dma_write_req) {
> -                     r = davinci_request_dma(sync_dev, dev_name,
> -                                             mmc_davinci_dma_cb, host,
> -                                             &edma_ch, &tcc, queue_no);
> -                     if (r != 0) {
> -                             dev_dbg(&mmc_dev,
> -                                     "MMC: davinci_request_dma() failed with 
> %d\n",
> -r);
> -                             return r;
> -                     }
> -                     dma_write_req = 0;
> -             }
> -     } else {
> -             sync_dev = DAVINCI_DMA_MMCRXEVT;        /* Read */
> -             dev_name = "MMC_READ";
> -             if (dma_read_req) {
> -                     r = davinci_request_dma(sync_dev, dev_name,
> -                                             mmc_davinci_dma_cb, host,
> -                                             &edma_ch, &tcc, queue_no);
> -                     if (r != 0) {
> -                             dev_dbg(&mmc_dev,
> -                                     "MMC: davinci_request_dma() failed with 
> %d\n",
> -                                     r);
> -                             return r;
> -                     }
> -                     dma_read_req = 0;
> -             }
> +     if ((data->blocks == 1) && (count > data->blksz)) {
> +             count = frame;
>       }
>  
> -     if ((req->data->flags & MMC_DATA_WRITE)) {
> -             /* AB Sync Transfer */
> -             /* Acnt =32, Bcnt= , Cnt=1 */
> -
> -             sync_dev = DAVINCI_DMA_MMCTXEVT;        /* Write */
> +     if (count % 32 == 0) {
>               acnt = 4;
>               bcnt = 8;
> -             if (num_eight_words > MAX_C_CNT) {
> -                     temp_ccnt = MAX_C_CNT;
> -                     ccnt = temp_ccnt;
> -             } else {
> -                     ccnt = num_eight_words;
> -                     temp_ccnt = ccnt;
> -             }
> +             num_frames = count / 32;
> +     } else {
> +             acnt = count;
> +             bcnt = 1;
> +             num_frames = 1;
> +     }
> +
> +     if (num_frames > MAX_C_CNT) {
> +             temp_ccnt = MAX_C_CNT;
> +             ccnt = temp_ccnt;
> +     } else {
> +             ccnt = num_frames;
> +             temp_ccnt = ccnt;
> +     }
> +
> +     if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
> +             /*AB Sync Transfer */
> +             sync_dev = DAVINCI_DMA_MMCTXEVT;
>  
> -             src_port = (unsigned int)virt_to_phys(req->data->mrq->buffer);
> +             src_port = (unsigned int)sg_dma_address(sg);
>               mode_src = INCR;
>               fifo_width_src = W8BIT; /* It's not cared as modeDsr is INCR */
> -             src_bidx = 4;
> -             src_cidx = 32;
> +             src_bidx = acnt;
> +             src_cidx = acnt * bcnt;
>               dst_port = MMCSD_REGS_BASE_ADDR + 0x2C;
>               mode_dst = INCR;
>               fifo_width_dst = W8BIT; /* It's not cared as modeDsr is INCR */
> @@ -425,27 +546,18 @@ r);
>               sync_mode = ABSYNC;
>  
>       } else {
> -             sync_dev = DAVINCI_DMA_MMCRXEVT;        /* Read */
> -             acnt = 4;
> -             bcnt = 8;
> -             if (num_eight_words > MAX_C_CNT) {
> -                     temp_ccnt = MAX_C_CNT;
> -                     ccnt = temp_ccnt;
> -             } else {
> -                     ccnt = num_eight_words;
> -                     temp_ccnt = ccnt;
> -             }
> +             sync_dev = DAVINCI_DMA_MMCRXEVT;
>  
>               src_port = MMCSD_REGS_BASE_ADDR + 0x28;
>               mode_src = INCR;
>               fifo_width_src = W8BIT;
>               src_bidx = 0;
>               src_cidx = 0;
> -             dst_port = (unsigned int)virt_to_phys(req->data->mrq->buffer);
> +             dst_port = (unsigned int)sg_dma_address(sg);
>               mode_dst = INCR;
>               fifo_width_dst = W8BIT; /* It's not cared as modeDsr is INCR */
> -             dst_bidx = 4;
> -             dst_cidx = 32;
> +             dst_bidx = acnt;
> +             dst_cidx = acnt * bcnt;
>               bcntrld = 8;
>               sync_mode = ABSYNC;
>       }
> @@ -459,7 +571,6 @@ r);
>       davinci_set_dma_transfer_params(sync_dev, acnt, bcnt, ccnt, bcntrld,
>                                       sync_mode);
>  
> -     host->edma_ch_details.cnt_chanel = 0;
>       davinci_get_dma_params(sync_dev, &temp);
>       if (sync_dev == DAVINCI_DMA_MMCTXEVT) {
>               if (option_write == 0) {
> @@ -478,12 +589,15 @@ r);
>               }
>       }
>  
> -     if (num_eight_words > MAX_C_CNT) {      /* Linking will be performed */
> +     if (host->sg_len > 1) {
>               davinci_get_dma_params(sync_dev, &temp);
>               temp.opt &= ~TCINTEN;
>               davinci_set_dma_params(sync_dev, &temp);
>  
> -             for (i = 0; i < EDMA_MAX_LOGICAL_CHA_ALLOWED; i++) {
> +             for (i = 0; i < host->sg_len - 1; i++) {
> +
> +                     sg = &data->sg[i + 1];
> +
>                       if (i != 0) {
>                               j = i - 1;
>                               davinci_get_dma_params(
> @@ -495,30 +609,24 @@ r);
>                                       &temp);
>                       }
>  
> -                     host->edma_ch_details.cnt_chanel++;
> -                     davinci_request_dma(DAVINCI_EDMA_PARAM_ANY, "LINK",
> -                                     NULL, NULL, &edma_chan_num,
> -                                     &sync_dev, queue_no);
> -                     host->edma_ch_details.chanel_num[i] = edma_chan_num;
> -                     ccnt = temp.ccnt & 0x0000FFFF;
> -                     if (sync_dev == DAVINCI_DMA_MMCTXEVT) {
> -                             temp.src = temp.src + (acnt * bcnt * ccnt);
> -                     } else {
> -                             temp.dst = temp.dst + (acnt * bcnt * ccnt);
> -                     }
> +                     edma_chan_num = host->edma_ch_details.chanel_num[0];
> +
> +                     frame = data->blksz;
> +                     count = sg_dma_len(sg);
> +
> +                     if ((data->blocks == 1) && (count > data->blksz))
> +                             count = frame;
> +
> +                     ccnt = count / 32;
> +
> +                     if (sync_dev == DAVINCI_DMA_MMCTXEVT)
> +                             temp.src = (unsigned int)sg_dma_address(sg);
> +                     else
> +                             temp.dst = (unsigned int)sg_dma_address(sg);
>                       temp.opt |= TCINTEN;
>  
> -                     if ((num_eight_words - temp_ccnt) > MAX_C_CNT) {
> -                             temp.ccnt = (temp.ccnt & 0xFFFF0000)
> -                                     | MAX_C_CNT;
> -                             ccnt = temp.ccnt & 0x0000FFFF;
> -                             temp_ccnt = temp_ccnt + ccnt;
> -                     } else {
> -                             temp.ccnt = (temp.ccnt & 0xFFFF0000)
> -                                     | (num_eight_words -temp_ccnt);
> -                             ccnt = temp.ccnt & 0x0000FFFF;
> -                             temp_ccnt = temp_ccnt + ccnt;
> -                     }
> +                     temp.ccnt = (temp.ccnt & 0xFFFF0000) | (ccnt);
> +
>                       davinci_set_dma_params(edma_chan_num, &temp);
>                       if (i != 0) {
>                               j = i - 1;
> @@ -526,8 +634,6 @@ r);
>                                               chanel_num[j],
>                                               edma_chan_num);
>                       }
> -                     if (temp_ccnt == num_eight_words)
> -                             break;
>               }
>               davinci_dma_link_lch(sync_dev,
>                               host->edma_ch_details.chanel_num[0]);
> @@ -540,8 +646,7 @@ r);
>  static void
>  mmc_davinci_prepare_data(struct mmc_davinci_host *host, struct mmc_request 
> *req)
>  {
> -     int timeout;
> -
> +     int timeout, sg_len;
>       host->data = req->data;
>       if (req->data == NULL) {
>               host->data_dir = DAVINCI_MMC_DATADIR_NONE;
> @@ -549,6 +654,9 @@ mmc_davinci_prepare_data(struct mmc_davi
>               mmcsd_regs->mmc_nblk = 0;
>               return;
>       }
> +     /* Init idx */
> +     host->sg_idx = 0;
> +
>       dev_dbg(&mmc_dev,
>               "MMCSD : Data xfer (%s %s), "
>               "DTO %d cycles + %d ns, %d blocks of %d bytes\r\n",
> @@ -589,15 +697,33 @@ mmc_davinci_prepare_data(struct mmc_davi
>               break;
>       }
>  
> -     if ((host->use_dma == 1)
> -                     && (mmc_davinci_start_dma_transfer(host, req) == 0)) {
> +     sg_len = (req->data->blocks == 1) ? 1 : req->data->sg_len;
> +     host->sg_len = sg_len;
> +
> +     host->bytes_left = req->data->blocks * req->data->blksz;
> +
> +     if ((host->use_dma == 1) && (host->bytes_left % 32 == 0)
> +         && (mmc_davinci_start_dma_transfer(host, req) == 0)) {
>               host->buffer = NULL;
>               host->bytes_left = 0;
>       } else {
>               /* Revert to CPU Copy */
> -             host->buffer = (u32 *) (req->data->mrq->buffer);
> -             host->bytes_left = req->data->blocks * req->data->blksz;
> -             host->use_dma = 0;
> +
> +             host->do_dma = 0;
> +             mmc_davinci_sg_to_buf(host);
> +     }
> +}
> +
> +/* PIO only */
> +static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host)
> +{
> +     struct scatterlist *sg;
> +
> +     sg = host->data->sg + host->sg_idx;
> +     host->buffer_bytes_left = sg->length;
> +     host->buffer = page_address(sg->page) + sg->offset;
> +     if (host->buffer_bytes_left > host->bytes_left) {
> +             host->buffer_bytes_left = host->bytes_left;
>       }
>  }
>  
> @@ -606,14 +732,27 @@ static void mmc_davinci_request(struct m
>       struct mmc_davinci_host *host = mmc_priv(mmc);
>       unsigned long flags;
>  
> +     if (is_card_removed) {
> +             if (req->cmd) {
> +                     req->cmd->error |= MMC_ERR_TIMEOUT;
> +                     mmc_request_done(mmc, req);
> +             }
> +             dev_dbg(&mmc_dev,
> +                     "From code segment excuted when card removed\n");
> +             return;
> +     }
> +
> +     wait_on_data();
> +
>       if (!is_card_detect_progress) {
>               spin_lock_irqsave(&mmc_lock, flags);
>               is_card_busy = 1;
>               spin_unlock_irqrestore(&mmc_lock, flags);
> +             host->do_dma = 0;
>               mmc_davinci_prepare_data(host, req);
>               mmc_davinci_start_command(host, req->cmd);
>       } else {
> -             /* Queu up the request as card dectection is being excuted */
> +             /* Queue up the request as card dectection is being excuted */
>               que_mmc_host = mmc;
>               que_mmc_request = req;
>               spin_lock_irqsave(&mmc_lock, flags);
> @@ -652,6 +791,13 @@ static void mmc_davinci_set_ios(struct m
>       dev_dbg(&mmc_dev, "clock %dHz busmode %d powermode %d Vdd %d.%02d\r\n",
>               ios->clock, ios->bus_mode, ios->power_mode,
>               ios->vdd / 100, ios->vdd % 100);
> +     if (ios->bus_width == MMC_BUS_WIDTH_4) {
> +             dev_dbg(&mmc_dev, "\nEnabling 4 bit mode\n");
> +             mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl | (1 << 2);
> +     } else {
> +             dev_dbg(&mmc_dev, "Disabling 4 bit mode\n");
> +             mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl & ~(1 << 2);
> +     }
>  
>       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
>               open_drain_freq = ((unsigned int)cpu_arm_clk
> @@ -660,8 +806,12 @@ static void mmc_davinci_set_ios(struct m
>                               | open_drain_freq;
>       } else {
>               mmc_push_pull_freq = calculate_freq_for_card(ios->clock);
> +             mmcsd_regs->mmc_clk &= ~(0x100);
> +             udelay(10);
>               mmcsd_regs->mmc_clk = (mmcsd_regs->mmc_clk & ~(0xFF))
>                               | mmc_push_pull_freq;
> +             mmcsd_regs->mmc_clk |= 0x100;
> +             udelay(10);
>       }
>       host->bus_mode = ios->bus_mode;
>       if (ios->power_mode == MMC_POWER_UP) {
> @@ -685,6 +835,15 @@ mmc_davinci_xfer_done(struct mmc_davinci
>       if (data->error == MMC_ERR_NONE)
>               data->bytes_xfered += data->blocks * data->blksz;
>  
> +     if (host->do_dma) {
> +             davinci_abort_dma(host);
> +
> +             dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len,
> +                          (data->
> +                           flags & MMC_DATA_WRITE) ? DMA_TO_DEVICE :
> +                          DMA_FROM_DEVICE);
> +     }
> +
>       if (data->error == MMC_ERR_TIMEOUT) {
>               spin_lock_irqsave(&mmc_lock, flags);
>               is_card_busy = 0;
> @@ -708,25 +867,24 @@ static void mmc_davinci_cmd_done(struct 
>                                struct mmc_command *cmd)
>  {
>       unsigned long flags;
> -
>       host->cmd = NULL;
> -     switch (cmd->flags & MMC_RSP_MASK) {
> -     case MMC_RSP_NONE:
> -             /* resp 0 */
> -             break;
>  
> -     case MMC_RSP_SHORT:
> -             /* response types 1, 1b, 3, 4, 5, 6 */
> -             cmd->resp[0] = mmcsd_regs->mmc_rsp67;
> -             break;
> +     if (!cmd) {
> +             dev_warn(&mmc_dev, "%s(): No cmd ptr\n", __FUNCTION__);
> +             return;
> +     }
>  
> -     case MMC_RSP_LONG:
> -             /* response type 2 */
> -             cmd->resp[3] = mmcsd_regs->mmc_rsp01;
> -             cmd->resp[2] = mmcsd_regs->mmc_rsp23;
> -             cmd->resp[1] = mmcsd_regs->mmc_rsp45;
> -             cmd->resp[0] = mmcsd_regs->mmc_rsp67;
> -             break;
> +     if (cmd->flags & MMC_RSP_PRESENT) {
> +             if (cmd->flags & MMC_RSP_136) {
> +                     /* response type 2 */
> +                     cmd->resp[3] = mmcsd_regs->mmc_rsp01;
> +                     cmd->resp[2] = mmcsd_regs->mmc_rsp23;
> +                     cmd->resp[1] = mmcsd_regs->mmc_rsp45;
> +                     cmd->resp[0] = mmcsd_regs->mmc_rsp67;
> +             } else {
> +                     /* response types 1, 1b, 3, 4, 5, 6 */
> +                     cmd->resp[0] = mmcsd_regs->mmc_rsp67;
> +             }
>       }
>  
>       if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
> @@ -746,7 +904,6 @@ static irqreturn_t mmc_davinci_irq(int i
>       u16 status;
>       int end_command;
>       int end_transfer;
> -     int byte_cnt = 0, i = 0;
>       unsigned long flags;
>  
>       if (host->is_core_command) {
> @@ -783,44 +940,36 @@ static irqreturn_t mmc_davinci_irq(int i
>                       if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
>                               if (status & MMCSD_EVENT_WRITE) {
>                                       /* Buffer almost empty */
> -                                     if (host->bytes_left > 0) {
> -                                             byte_cnt =
> -                                                     mmcsd_cfg.rw_threshold;
> -                                             host->bytes_left -=
> -                                                     mmcsd_cfg.rw_threshold;
> -                                             for (i = 0; i < (byte_cnt / 4);
> -                                                             i++) {
> -                                                     mmcsd_regs->mmc_dxr =
> -                                                             *host->buffer;
> -                                                     host->buffer++;
> -                                             }
> -                                     }
> +                                     if (host->bytes_left > 0)
> +                                             davinci_fifo_data_trans(host);
>                               }
>                       }
>  
>                       if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
>                               if (status & MMCSD_EVENT_READ) {
>                                       /* Buffer almost empty */
> -                                     if (host->bytes_left > 0) {
> -                                             byte_cnt =
> -                                                     mmcsd_cfg.rw_threshold;
> -                                             host->bytes_left -=
> -                                                     mmcsd_cfg.rw_threshold;
> -                                             for (i = 0; i < (byte_cnt / 4);
> -                                                             i++) {
> -                                                     *host->buffer =
> -                                                             mmcsd_regs->
> -                                                                     mmc_drr;
> -                                                     host->buffer++;
> -                                             }
> -                                     }
> +                                     if (host->bytes_left > 0)
> +                                             davinci_fifo_data_trans(host);
>                               }
>                       }
>  
>                       if (status & MMCSD_EVENT_BLOCK_XFERRED) {
>                               /* Block sent/received */
>                               if (host->data != NULL) {
> -                                     end_transfer = 1;
> +
> +                                     if (host->do_dma == 1) {
> +                                             end_transfer = 1;
> +                                     } else {
> +                                             /* if datasize<32 no RX ints 
> are generated */
> +                                             if (host->bytes_left > 0) {
> +                                                     davinci_fifo_data_trans
> +                                                         (host);
> +                                             }
> +                                             end_transfer = 1;
> +                                     }
> +                             } else {
> +                                     dev_warn(&mmc_dev,
> +                                              "TC:host->data is NULL\n");
>                               }
>                       }
>  
> @@ -829,6 +978,7 @@ static irqreturn_t mmc_davinci_irq(int i
>                               if ((host->data) && (new_card_state != 0)) {
>                                       host->data->error |= MMC_ERR_TIMEOUT;
>                                       spin_lock_irqsave(&mmc_lock, flags);
> +                                     is_card_removed = 1;
>                                       new_card_state = 0;
>                                       is_card_initialized = 0;
>                                       spin_unlock_irqrestore(&mmc_lock,
> @@ -836,15 +986,23 @@ static irqreturn_t mmc_davinci_irq(int i
>                                       dev_dbg(&mmc_dev,
>                                               "MMCSD: Data timeout, CMD%d and 
> status is %x\r\n",
>                                               host->cmd->opcode, status);
> +
> +                                     if (host->cmd) {
> +                                             host->cmd->error |=
> +                                                 MMC_ERR_TIMEOUT;
> +                                     }
>                                       end_transfer = 1;
> -                                     host->cmd->error |= MMC_ERR_TIMEOUT;
>                               }
> -                             dev_dbg(&mmc_dev,
> -                                     "MMCSD: Data timeout, CMD%d and status 
> is %x\r\n",
> -                                     host->cmd->opcode, status);
>                       }
>  
>                       if (status & MMCSD_EVENT_ERROR_DATACRC) {
> +                             /* DAT line portion is diabled and in reset 
> state */
> +                             mmcsd_regs->mmc_ctl =
> +                                 mmcsd_regs->mmc_ctl | (1 << 1);
> +                             udelay(10);
> +                             mmcsd_regs->mmc_ctl =
> +                                 mmcsd_regs->mmc_ctl & ~(1 << 1);
> +
>                               /* Data CRC error */
>                               if (host->data) {
>                                       host->data->error |= MMC_ERR_BADCRC;
> @@ -859,6 +1017,10 @@ static irqreturn_t mmc_davinci_irq(int i
>                       }
>  
>                       if (status & MMCSD_EVENT_ERROR_CMDTIMEOUT) {
> +                             if (host->do_dma)
> +                                     /* abort DMA transfer */
> +                                     davinci_abort_dma(host);
> +
>                               /* Command timeout */
>                               if (host->cmd) {
>                                       /* Timeouts are normal in case of
> @@ -888,7 +1050,11 @@ static irqreturn_t mmc_davinci_irq(int i
>                               /* Command CRC error */
>                               dev_dbg(&mmc_dev, "Command CRC error\r\n");
>                               if (host->cmd) {
> -                                     host->cmd->error |= MMC_ERR_BADCRC;
> +                                     /* Ignore CMD CRC errors during high 
> speed operation */
> +                                     if (host->mmc->ios.clock <= 25000000) {
> +                                             host->cmd->error |=
> +                                                 MMC_ERR_BADCRC;
> +                                     }
>                                       end_command = 1;
>                               }
>                       }
> @@ -926,6 +1092,7 @@ static irqreturn_t mmc_davinci_irq(int i
>  
>                       } else {
>                               spin_lock_irqsave(&mmc_lock, flags);
> +                             is_card_removed = 1;
>                               new_card_state = 0;
>                               is_card_initialized = 0;
>                               spin_unlock_irqrestore(&mmc_lock, flags);
> @@ -945,15 +1112,17 @@ static irqreturn_t mmc_davinci_irq(int i
>  
>               }
>  
> -             if (host->cmd_code == 1) {
> +             if (host->cmd_code == 1 || host->cmd_code == 55) {
>                       if (status & MMCSD_EVENT_EOFCMD) {
>                               spin_lock_irqsave(&mmc_lock, flags);
> +                             is_card_removed = 0;
>                               new_card_state = 1;
>                               is_card_initialized = 0;
>                               spin_unlock_irqrestore(&mmc_lock, flags);
>                       } else {
>  
>                               spin_lock_irqsave(&mmc_lock, flags);
> +                             is_card_removed = 1;
>                               new_card_state = 0;
>                               is_card_initialized = 0;
>                               spin_unlock_irqrestore(&mmc_lock, flags);
> @@ -970,19 +1139,31 @@ static irqreturn_t mmc_davinci_irq(int i
>                               is_req_queued_up = 0;
>                               spin_unlock_irqrestore(&mmc_lock, flags);
>                       }
> -
>               }
>  
>               if (host->cmd_code == 0) {
>                       if (status & MMCSD_EVENT_EOFCMD) {
> +                             static int flag_sd_mmc;
>                               host->is_core_command = 0;
> -                             host->cmd_code = 1;
> -                             dev_dbg(&mmc_dev,
> -                                     "MMC-Probing mmc with cmd1\n");
> -                             /* Issue cmd1 */
> -                             mmcsd_regs->mmc_arghl = 0x80300000;
> -                             mmcsd_regs->mmc_cmd = 0x00000601;
>  
> +                             if (flag_sd_mmc) {
> +                                     flag_sd_mmc = 0;
> +                                     host->cmd_code = 1;
> +                                     /* Issue cmd1 */
> +                                     mmcsd_regs->mmc_arghl = 0x80300000;
> +                                     mmcsd_regs->mmc_cmd = 0x00000601;
> +                             } else {
> +                                     flag_sd_mmc = 1;
> +                                     host->cmd_code = 55;
> +                                     /* Issue cmd55 */
> +                                     mmcsd_regs->mmc_arghl = 0x0;
> +                                     mmcsd_regs->mmc_cmd =
> +                                         ((0x0 | (1 << 9) | 55));
> +                             }
> +
> +                             dev_dbg(&mmc_dev,
> +                                     "MMC-Probing mmc with cmd%d\n",
> +                                     host->cmd_code);
>                       } else {
>                               spin_lock_irqsave(&mmc_lock, flags);
>                               new_card_state = 0;
> @@ -999,12 +1180,22 @@ static irqreturn_t mmc_davinci_irq(int i
>  static struct mmc_host_ops mmc_davinci_ops = {
>       .request = mmc_davinci_request,
>       .set_ios = mmc_davinci_set_ios,
> +     .get_ro = mmc_davinci_get_ro
>  };
>  
> +static int mmc_davinci_get_ro(struct mmc_host *mmc)
> +{
> +     return 0;
> +}
> +
>  void mmc_check_card(unsigned long data)
>  {
>       struct mmc_davinci_host *host = (struct mmc_davinci_host *)data;
>       unsigned long flags;
> +     struct mmc_card *card = NULL;
> +
> +     if (host->mmc && host->mmc->card)
> +             card = host->mmc->card;
>  
>       if ((!is_card_detect_progress) || (!is_init_progress)) {
>               if (is_card_initialized) {
> @@ -1014,7 +1205,9 @@ void mmc_check_card(unsigned long data)
>                       is_card_detect_progress = 1;
>                       spin_unlock_irqrestore(&mmc_lock, flags);
>                       /* Issue cmd13 */
> -                     mmcsd_regs->mmc_arghl = 0x10000;
> +                     mmcsd_regs->mmc_arghl = (card
> +                                              && mmc_card_sd(card))
> +                         ? (card->rca << 16) : 0x10000;
>                       mmcsd_regs->mmc_cmd = 0x0000028D;
>               } else {
>                       host->is_core_command = 0;
> @@ -1041,6 +1234,8 @@ static void davinci_mmc_check_status(uns
>  
>       if (!is_card_busy) {
>               if (host->old_card_state ^ new_card_state) {
> +                     davinci_reinit_chan();
> +                     init_mmcsd_host();
>                       mmc_detect_change(host->mmc, 0);
>                       spin_lock_irqsave(&mmc_lock, flags);
>                       host->old_card_state = new_card_state;
> @@ -1057,6 +1252,7 @@ static void init_mmcsd_host(void)
>       mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl | 0x1;
>       /* DAT line portion is diabled and in reset state */
>       mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl | (1 << 1);
> +     udelay(10);
>  
>       mmcsd_regs->mmc_clk = 0x0;
>       mmcsd_regs->mmc_clk = mmcsd_regs->mmc_clk | (1 << 8);
> @@ -1066,13 +1262,14 @@ static void init_mmcsd_host(void)
>  
>       mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl & ~(0x1);
>       mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl & ~(1 << 1);
> +     udelay(10);
>  }
>  
>  static int davinci_mmcsd_probe(struct platform_device *pdev)
>  {
>       struct mmc_davinci_host *host;
>       struct mmc_host *mmc;
> -     int ret;
> +     int ret = 0;
>  
>       mmc = mmc_alloc_host(sizeof(struct mmc_davinci_host), &pdev->dev);
>       if (!mmc) {
> @@ -1085,14 +1282,44 @@ static int davinci_mmcsd_probe(struct pl
>  
>       init_mmcsd_host();
>  
> +     if (mmcsd_cfg.use_4bit_mode) {
> +             dev_warn(&mmc_dev, "Supporting 4-bit mode\n");
> +             mmc->caps |= MMC_CAP_4_BIT_DATA;
> +     } else
> +             dev_warn(&mmc_dev, "Not Supporting 4-bit mode\n");
> +
>       mmc->ops = &mmc_davinci_ops;
>       mmc->f_min = 312500;
> -     mmc->f_max = 20000000;
> +#ifdef CONFIG_MMC_HIGHSPEED
> +     mmc->f_max = 50000000;
> +#else
> +     mmc->f_max = 25000000;
> +#endif
>       mmc->ocr_avail = MMC_VDD_32_33;
>  
> +     mmc->max_phys_segs = 2;
> +     mmc->max_hw_segs   = 2;
> +     mmc->max_blk_size  = 4095;  /* BLEN is 11 bits */
> +     mmc->max_blk_count = 65535; /* NBLK is 16 bits */
> +     mmc->max_req_size  = mmc->max_blk_size * mmc->max_blk_count;
> +     mmc->max_seg_size  = mmc->max_req_size;
> +
> +     dev_dbg(&mmc_dev, "max_phys_segs=%d\n", mmc->max_phys_segs);
> +     dev_dbg(&mmc_dev, "max_hw_segs=%d\n", mmc->max_hw_segs);
> +     dev_dbg(&mmc_dev, "max_blk_size=%d\n", mmc->max_blk_size);
> +     dev_dbg(&mmc_dev, "max_req_size=%d\n", mmc->max_req_size);
> +     dev_dbg(&mmc_dev, "max_seg_size=%d\n", mmc->max_seg_size);
> +
>       host = mmc_priv(mmc);
>       host->mmc = mmc;        /* Important */
>  
> +     if (mmcsd_cfg.use_dma) {
> +             dev_dbg(&mmc_dev, "Using DMA mode\n");
> +             if (davinci_acquire_dma_channels(host) != 0)
> +                     goto out;
> +     } else
> +             dev_dbg(&mmc_dev, "Not Using DMA mode\n");
> +
>       host->use_dma = mmcsd_cfg.use_dma;
>       host->irq = MMCINT_INTERRUPT;
>       host->sd_support = 1;
> @@ -1122,13 +1349,20 @@ out:
>  static int davinci_mmcsd_remove(struct platform_device *pdev)
>  {
>       struct mmc_davinci_host *host = platform_get_drvdata(pdev);
> +     unsigned long flags;
>  
>       platform_set_drvdata(pdev, NULL);
> -     mmc_remove_host(host->mmc);
> -     free_irq(host->irq, host);
> -     del_timer(&host->timer);
> -     davinci_free_dma(DAVINCI_DMA_MMCTXEVT);
> -     davinci_free_dma(DAVINCI_DMA_MMCRXEVT);
> +     if (host) {
> +             mmc_remove_host(host->mmc);
> +             free_irq(host->irq, host);
> +
> +             spin_lock_irqsave(&mmc_lock, flags);
> +             del_timer(&host->timer);
> +             spin_unlock_irqrestore(&mmc_lock, flags);
> +
> +             davinci_release_dma_channels(host);
> +     }
> +
>       return 0;
>  
>  }
> @@ -1222,14 +1456,26 @@ free1:
>               platform_device_unregister(&mmc_davinci_device);
>       }
>  
> +     if (clkp) {
> +             mmc_clkp = NULL;
> +             clk_put(clkp);
> +     }
> +
>       return -ENODEV;
>  }
>  
>  static void __exit davinci_mmcsd_exit(void)
>  {
> +     struct clk *clkp;
> +
>       platform_driver_unregister(&davinci_mmcsd_driver);
>       platform_device_unregister(&mmc_davinci_device);
> -     clk_disable(mmc_clkp);
> +
> +     clkp = mmc_clkp;
> +     mmc_clkp = NULL;
> +
> +     clk_disable(clkp);
> +     clk_put(clkp);
>  }
>  
>  module_init(davinci_mmcsd_init);
> diff --git a/drivers/mmc/host/davinci_mmc.h b/drivers/mmc/host/davinci_mmc.h
> index a6c4557..5840ccf 100644
> --- a/drivers/mmc/host/davinci_mmc.h
> +++ b/drivers/mmc/host/davinci_mmc.h
> @@ -132,6 +132,7 @@ #define DAVINCI_MMC_DATADIR_WRITE 2
>       int power_pin;
>  
>       int use_dma;
> +     int do_dma;
>       struct completion dma_completion;
>  
>       struct timer_list timer;
> @@ -143,10 +144,16 @@ #define DAVINCI_MMC_DATADIR_WRITE       2
>  
>       edma_ch_mmcsd edma_ch_details;
>  
> +     unsigned int sg_len;
> +     int sg_idx;
> +     unsigned int buffer_bytes_left;
> +     unsigned int dma_len;
> +     int dma_state;
>  };
>  typedef struct {
>       unsigned short rw_threshold;
>       unsigned short use_dma;
> +     unsigned short use_4bit_mode;
>  } mmcsd_config_def;
>  
>  typedef enum {
> @@ -168,4 +175,20 @@ #define MMCSD_EVENT_CRC_ERROR \
>  #define MMCSD_EVENT_ERROR \
>   (MMCSD_EVENT_TIMEOUT_ERROR | MMCSD_EVENT_CRC_ERROR)
>  
> +static void init_mmcsd_host(void);
> +
> +static void davinci_fifo_data_trans(struct mmc_davinci_host *host);
> +
> +static void mmc_davinci_sg_to_buf(struct mmc_davinci_host *host);
> +
> +static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
> +                                     struct mmc_request *req);
> +
> +static void mmc_davinci_xfer_done(struct mmc_davinci_host *host,
> +                               struct mmc_data *data);
> +
> +static int mmc_davinci_get_ro(struct mmc_host *mmc);
> +
> +static void davinci_abort_dma(struct mmc_davinci_host *host);
> +
>  #endif /* DAVINCI_MMC_H_ */
> _______________________________________________
> Davinci-linux-open-source mailing list
> Davinci-linux-open-source@linux.davincidsp.com
> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

_______________________________________________
Davinci-linux-open-source mailing list
Davinci-linux-open-source@linux.davincidsp.com
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to