From: lhh Date: Thu, 18 Nov 2010 07:24:34 +0000 (+0800) Subject: update X-Git-Tag: firefly_0821_release~11016^2~19 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2e187c10ea507748bd83cc464dce143a7da0093e;p=firefly-linux-kernel-4.4.55.git update --- diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index ee2c8b23408e..dd73e752951d 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -509,7 +509,7 @@ static int rk29_sdmmc0_cfg_gpio(void) return 0; } -#define CONFIG_SDMMC0_USE_DMA +//#define CONFIG_SDMMC0_USE_DMA struct rk29_sdmmc_platform_data default_sdmmc0_data = { .num_slots = 1, .host_ocr_avail = (MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30| @@ -526,7 +526,7 @@ struct rk29_sdmmc_platform_data default_sdmmc0_data = { }; #endif #ifdef CONFIG_SDMMC1_RK29 -#define CONFIG_SDMMC1_USE_DMA +//#define CONFIG_SDMMC1_USE_DMA static int rk29_sdmmc1_cfg_gpio(void) { rk29_mux_api_set(GPIO1C2_SDMMC1CMD_NAME, GPIO1H_SDMMC1_CMD); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 0aa0cf0dde24..fa8f13bb5444 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -38,10 +38,15 @@ if SDMMC_RK29 config SDMMC0_RK29 tristate "RK29 SDMMC0 controller support(sdmmc)" default y - depends on ARCH_RK29 + depends on ARCH_RK29 help This supports the use of the SDMMC0 controller on Rk29 processors. - + config EMMC_RK29 + tristate "RK29 EMMC controller support(sdmmc)" + default y + depends on SDMMC0_RK29 + help + This supports the use of the EMMC controller on Rk29 processors. config SDMMC1_RK29 tristate "RK29 SDMMC1 controller support(sdio)" default y diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c index 6e1339e0c5dd..8d8ec2c19f43 100644 --- a/drivers/mmc/host/rk29_sdmmc.c +++ b/drivers/mmc/host/rk29_sdmmc.c @@ -47,7 +47,7 @@ #define DBG(x...) do { } while (0) #endif -#define RK29_SDMMC_DATA_ERROR_FLAGS (SDMMC_INT_DTO | SDMMC_INT_DCRC | SDMMC_INT_HTO | SDMMC_INT_SBE | SDMMC_INT_EBE) +#define RK29_SDMMC_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | SDMMC_INT_HTO | SDMMC_INT_SBE | SDMMC_INT_EBE) #define RK29_SDMMC_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | SDMMC_INT_RE | SDMMC_INT_HLE) #define RK29_SDMMC_ERROR_FLAGS (RK29_SDMMC_DATA_ERROR_FLAGS | RK29_SDMMC_CMD_ERROR_FLAGS | SDMMC_INT_HLE) #define RK29_SDMMC_SEND_STATUS 1 @@ -196,31 +196,6 @@ static const struct file_operations rk29_sdmmc_req_fops = { .release = single_release, }; -#define SDMMC_CTRL (0x000) -#define SDMMC_PWREN (0x004) -#define SDMMC_CLKDIV (0x008) -#define SDMMC_CLKSRC (0x00c) -#define SDMMC_CLKENA (0x010) -#define SDMMC_TMOUT (0x014) -#define SDMMC_CTYPE (0x018) -#define SDMMC_BLKSIZ (0x01c) -#define SDMMC_BYTCNT (0x020) -#define SDMMC_INTMASK (0x024) -#define SDMMC_CMDARG (0x028) -#define SDMMC_CMD (0x02c) -#define SDMMC_RESP0 (0x030) -#define SDMMC_RESP1 (0x034) -#define SDMMC_RESP2 (0x038) -#define SDMMC_RESP3 (0x03c) -#define SDMMC_MINTSTS (0x040) -#define SDMMC_RINTSTS (0x044) -#define SDMMC_STATUS (0x048) -#define SDMMC_FIFOTH (0x04c) -#define SDMMC_CDETECT (0x050) -#define SDMMC_WRTPRT (0x054) -#define SDMMC_TCBCNT (0x05c) -#define SDMMC_TBBCNT (0x060) -#define SDMMC_DEBNCE (0x064) static int rk29_sdmmc_regs_show(struct seq_file *s, void *v) { struct rk29_sdmmc *host = s->private; @@ -385,9 +360,6 @@ static void send_stop_cmd(struct rk29_sdmmc *host, struct mmc_data *data) rk29_sdmmc_start_command(host, data->stop, host->stop_cmdr); } - -#ifdef USE_DMA - static void rk29_sdmmc_dma_cleanup(struct rk29_sdmmc *host) { struct mmc_data *data = host->data; @@ -400,8 +372,11 @@ static void rk29_sdmmc_dma_cleanup(struct rk29_sdmmc *host) static void rk29_sdmmc_stop_dma(struct rk29_sdmmc *host) { + if(host->use_dma == 0) + return; if (host->dma_chn > 0) { - dma_stop_channel(host->dma_chn); + //dma_stop_channel(host->dma_chn); + rk29_dma_ctrl(host->dma_chn,RK29_DMAOP_STOP); rk29_sdmmc_dma_cleanup(host); } else { /* Data transfer was stopped by the interrupt handler */ @@ -410,16 +385,19 @@ static void rk29_sdmmc_stop_dma(struct rk29_sdmmc *host) } /* This function is called by the DMA driver from tasklet context. */ -static void rk29_sdmmc_dma_complete(int chn, dma_irq_type_t type, void *arg) +static void rk29_sdmmc_dma_complete(void *arg, int size, enum rk29_dma_buffresult result) ///(int chn, dma_irq_type_t type, void *arg) { struct rk29_sdmmc *host = arg; struct mmc_data *data = host->data; + if(host->use_dma == 0) + return; dev_vdbg(&host->pdev->dev, "DMA complete\n"); - + if(result != RK29_RES_OK) + printk("%s: sdio dma complete err\n",__FUNCTION__); spin_lock(&host->lock); rk29_sdmmc_dma_cleanup(host); - + /* * If the card was removed, data will be NULL. No point trying * to send the stop command or waiting for NBUSY in this case. @@ -434,13 +412,14 @@ static void rk29_sdmmc_dma_complete(int chn, dma_irq_type_t type, void *arg) static int rk29_sdmmc_submit_data_dma(struct rk29_sdmmc *host, struct mmc_data *data) { struct scatterlist *sg; - unsigned int i, direction, sg_len; - unsigned int j, trans_len; + unsigned int direction; + if(host->use_dma == 0) + return -ENOSYS; /* If we don't have a channel, we can't do DMA */ if (host->dma_chn < 0) return -ENODEV; - + /* * We don't do DMA on "complex" transfers, i.e. with * non-word-aligned buffers or lengths. Also, we don't bother @@ -451,92 +430,25 @@ static int rk29_sdmmc_submit_data_dma(struct rk29_sdmmc *host, struct mmc_data * if (data->blksz & 3) return -EINVAL; - for_each_sg(data->sg, sg, data->sg_len, i) { + for_each_sg(data->sg, sg, data->sg_len, host->dma_chn) { if (sg->offset & 3 || sg->length & 3) return -EINVAL; } if (data->flags & MMC_DATA_READ) - direction = DMA_FROM_DEVICE; + direction = RK29_DMASRC_HW; else - direction = DMA_TO_DEVICE; - - sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, - direction); - - dev_vdbg(&host->pdev->dev, "sd sg_cpu: 0x%08x sg_dma:0x%08x sg_len:%d \n", - (u32)host->sg_cpu, (u32)host->sg_dma, sg_len); - - for (i = 0, j = 0; i < sg_len; i++) { - unsigned int length = sg_dma_len(&data->sg[i]); - u32 mem_addr = sg_dma_address(&data->sg[i]); - - while (length) { - - host->sg_cpu[j].setup.cfg = DMA_CFG_CMP_CH_EN | DMA_CFG_CMP_CH_NR(host->dma_chn); - - if (data->flags & MMC_DATA_READ) { - host->sg_cpu[j].setup.src_address = SDMMC_DATA_ADR; - host->sg_cpu[j].setup.dest_address = mem_addr; - host->sg_cpu[j].setup.cfg |= DMA_CFG_RD_SLV_NR(DMA_SLV_SDMMC); - } else { - host->sg_cpu[j].setup.src_address = mem_addr; - host->sg_cpu[j].setup.dest_address = SDMMC_DATA_ADR; - host->sg_cpu[j].setup.cfg |= DMA_CFG_WR_SLV_NR(DMA_SLV_SDMMC); - } - host->sg_cpu[j].next_entry = host->sg_dma + (j + 1) * - sizeof(dma_sg_ll_t); - - if (trans_len > DMA_MAX_TRANSFERS) { - trans_len = DMA_MAX_TRANSFERS; - length -= (DMA_MAX_TRANSFERS + 1) << 2; - mem_addr += ((DMA_MAX_TRANSFERS + 1) << 2); - } - else { - length = 0; - } - - host->sg_cpu[j].setup.trans_length = trans_len; - - dev_vdbg(&host->pdev->dev, "sd src: 0x%08x dest:0x%08x cfg:0x%08x nxt:0x%08x len:%d \n", - host->sg_cpu[j].setup.src_address, host->sg_cpu[j].setup.dest_address, - host->sg_cpu[j].setup.cfg, host->sg_cpu[j].next_entry, - host->sg_cpu[j].setup.trans_length); - - /* move to next transfer descriptor */ - j++; - } - } - host->sg_cpu[j].setup.src_address = host->sg_dma; - host->sg_cpu[j].setup.dest_address = DMACH_SOFT_INT_PHYS; - host->sg_cpu[j].setup.trans_length = 1; - host->sg_cpu[j].setup.cfg = 0; - // disable irq of RX & TX, let DMA handle it - //SDMMC_INTMASK &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR); - ///SDMMC_CTRL |= SDMMC_CTRL_DMA_ENABLE; // enable dma - rk29_sdmmc_write(host->regs, SDMMC_CTRL, (rk29_sdmmc_read(host->regs, SDMMC_CTRL))|SDMMC_CTRL_DMA_ENABLE); - dma_prog_sg_channel(host->dma_chn, host->sg_dma); - wmb(); - /* Go! */ - dma_start_channel(host->dma_chn); - + direction = RK29_DMASRC_MEM; + dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, + (data->flags & MMC_DATA_READ)? DMA_FROM_DEVICE : DMA_TO_DEVICE); + rk29_dma_devconfig(host->dma_chn, direction, (unsigned long )(host->regs+SDMMC_DATA)); + rk29_dma_enqueue(host->dma_chn, NULL, data->sg->dma_address, data->sg->length); + rk29_sdmmc_write(host->regs, SDMMC_CTRL, (rk29_sdmmc_read(host->regs, SDMMC_CTRL))|SDMMC_CTRL_DMA_ENABLE);// enable dma + rk29_dma_ctrl(host->dma_chn, RK29_DMAF_AUTOSTART); + printk("Enter:%s-----%d DMA DATA START\n",__FUNCTION__,__LINE__); return 0; } -#else -static int rk29_sdmmc_submit_data_dma(struct rk29_sdmmc *host, struct mmc_data *data) -{ - return -ENOSYS; -} - -static void rk29_sdmmc_stop_dma(struct rk29_sdmmc *host) -{ - /* Data transfer was stopped by the interrupt handler */ - rk29_sdmmc_set_pending(host, EVENT_XFER_COMPLETE); - -} -#endif - static void rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *data) { data->error = -EINPROGRESS; @@ -567,7 +479,7 @@ static void sdmmc_send_cmd(struct rk29_sdmmc *host, unsigned int cmd, int arg) while (--tmo && readl(host->regs + SDMMC_CMD) & SDMMC_CMD_START); if(!tmo) { printk("%s %d set cmd register timeout error!!!\n",__FUNCTION__,__LINE__); - } + } } void rk29_sdmmc_setup_bus(struct rk29_sdmmc *host) @@ -607,24 +519,21 @@ static void rk29_sdmmc_start_request(struct rk29_sdmmc *host) struct mmc_data *data; u32 cmdflags; - mrq = host->curr_mrq; - + mrq = host->mrq; /* Slot specific timing and width adjustment */ rk29_sdmmc_setup_bus(host); + host->curr_mrq = mrq; host->pending_events = 0; host->completed_events = 0; host->data_status = 0; - data = mrq->data; if (data) { rk29_sdmmc_set_timeout(host,data); rk29_sdmmc_write(host->regs, SDMMC_BYTCNT,data->blksz*data->blocks); rk29_sdmmc_write(host->regs, SDMMC_BLKSIZ,data->blksz); } - cmd = mrq->cmd; cmdflags = rk29_sdmmc_prepare_command(host->mmc, cmd); - if (unlikely(test_and_clear_bit(RK29_SDMMC_CARD_NEED_INIT, &host->flags))) cmdflags |= SDMMC_CMD_INIT; //this is the first command, let set send the initializtion clock @@ -650,20 +559,17 @@ static void rk29_sdmmc_queue_request(struct rk29_sdmmc *host,struct mmc_request } spin_unlock(&host->lock); } - - + static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct rk29_sdmmc *host = mmc_priv(mmc); WARN_ON(host->mrq); - if (!test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags)) { mrq->cmd->error = -ENOMEDIUM; mmc_request_done(mmc, mrq); return; } - rk29_sdmmc_queue_request(host,mrq); } @@ -680,7 +586,6 @@ static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->ctype = SDMMC_CTYPE_4BIT; break; } - if (ios->clock) { spin_lock(&host->lock); /* @@ -695,7 +600,6 @@ static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->clock = 0; spin_unlock(&host->lock); } - switch (ios->power_mode) { case MMC_POWER_UP: set_bit(RK29_SDMMC_CARD_NEED_INIT, &host->flags); @@ -719,7 +623,6 @@ static int rk29_sdmmc_get_cd(struct mmc_host *mmc) { struct rk29_sdmmc *host = mmc_priv(mmc); u32 cdetect = rk29_sdmmc_read(host->regs, SDMMC_CDETECT); - return (cdetect & SDMMC_CARD_DETECT_N)?0:1; } @@ -760,6 +663,7 @@ static void rk29_sdmmc_request_end(struct rk29_sdmmc *host, struct mmc_request * WARN_ON(host->cmd || host->data); host->curr_mrq = NULL; + host->mrq = NULL; if (!list_empty(&host->queue)) { host = list_entry(host->queue.next, struct rk29_sdmmc, queue_node); @@ -800,9 +704,9 @@ static void rk29_sdmmc_command_complete(struct rk29_sdmmc *host, cmd->resp[0] = rk29_sdmmc_read(host->regs, SDMMC_RESP3); } else { cmd->resp[0] = rk29_sdmmc_read(host->regs, SDMMC_RESP0); - cmd->resp[1] = 0; - cmd->resp[2] = 0; - cmd->resp[3] = 0; + cmd->resp[1] = 0; + cmd->resp[2] = 0; + cmd->resp[3] = 0; } } @@ -887,14 +791,12 @@ static void rk29_sdmmc_tasklet_func(unsigned long priv) case STATE_DATA_BUSY: if (!rk29_sdmmc_test_and_clear_pending(host, EVENT_DATA_COMPLETE)) - break; - + break; host->data = NULL; rk29_sdmmc_set_completed(host, EVENT_DATA_COMPLETE); status = host->data_status; - if (unlikely(status & RK29_SDMMC_DATA_ERROR_FLAGS)) { - if (status & SDMMC_INT_DTO) { + if (status & SDMMC_INT_DRTO) { dev_err(&host->pdev->dev, "data timeout error\n"); data->error = -ETIMEDOUT; @@ -957,9 +859,9 @@ inline static void rk29_sdmmc_push_data(struct rk29_sdmmc *host, void *buf,int c u32* pData = (u32*)buf; if (cnt % 4 != 0) - printk("error not align 4\n"); - - cnt = cnt >> 2; + cnt = (cnt>>2) +1; + else + cnt = cnt >> 2; while (cnt > 0) { rk29_sdmmc_write(host->regs, SDMMC_DATA,*pData++); cnt--; @@ -969,11 +871,12 @@ inline static void rk29_sdmmc_push_data(struct rk29_sdmmc *host, void *buf,int c inline static void rk29_sdmmc_pull_data(struct rk29_sdmmc *host,void *buf,int cnt) { u32* pData = (u32*)buf; - + if (cnt % 4 != 0) - printk("error not align 4\n"); - cnt = cnt >> 2; - while (cnt > 0) { + cnt = (cnt>>2) +1; + else + cnt = cnt >> 2; + while (cnt > 0) { *pData++ = rk29_sdmmc_read(host->regs, SDMMC_DATA); cnt--; } @@ -987,7 +890,7 @@ static void rk29_sdmmc_read_data_pio(struct rk29_sdmmc *host) struct mmc_data *data = host->data; u32 status; unsigned int nbytes = 0,len,old_len,count =0; - + do { len = SDMMC_GET_FCNT(rk29_sdmmc_read(host->regs, SDMMC_STATUS)) << 2; if(count == 0) @@ -1071,7 +974,6 @@ static void rk29_sdmmc_write_data_pio(struct rk29_sdmmc *host) } } else { unsigned int remaining = sg->length - offset; - rk29_sdmmc_push_data(host, (void *)(buf + offset), remaining); nbytes += remaining; @@ -1131,25 +1033,20 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id) do { status = rk29_sdmmc_read(host->regs, SDMMC_RINTSTS); pending = rk29_sdmmc_read(host->regs, SDMMC_MINTSTS);// read only mask reg + if (!pending) break; if(pending & SDMMC_INT_CD) { writel(SDMMC_INT_CD, host->regs + SDMMC_RINTSTS); // clear sd detect int - present = rk29_sdmmc_get_cd(host->mmc); present_old = test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); if(present != present_old) { - if (present != 0) { set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); } else { clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); - } - if(host->pdev->id ==0) { //sdmmc0 - mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK_SDMMC0_SWITCH_POLL_DELAY)); - } else { //sdio - mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(20)); - } + } + mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(20)); } } if(pending & RK29_SDMMC_CMD_ERROR_FLAGS) { @@ -1215,46 +1112,46 @@ static void rk29_sdmmc_detect_change(unsigned long data) { struct mmc_request *mrq; struct rk29_sdmmc *host = (struct rk29_sdmmc *)data;; - + smp_rmb(); if (test_bit(RK29_SDMMC_SHUTDOWN, &host->flags)) - return; + return; spin_lock(&host->lock); /* Clean up queue if present */ - mrq = host->mrq; - if (mrq) { - if (mrq == host->curr_mrq) { - /* reset all blocks */ - rk29_sdmmc_write(host->regs, SDMMC_CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)); - /* wait till resets clear */ - while (rk29_sdmmc_read(host->regs, SDMMC_CTRL) & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)); - rk29_sdmmc_write(host->regs, SDMMC_CTRL, SDMMC_CTRL_INT_ENABLE); - host->data = NULL; - host->cmd = NULL; - - switch (host->state) { - case STATE_IDLE: + mrq = host->mrq; + if (mrq) { + if (mrq == host->curr_mrq) { + /* reset all blocks */ + rk29_sdmmc_write(host->regs, SDMMC_CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)); + /* wait till resets clear */ + while (rk29_sdmmc_read(host->regs, SDMMC_CTRL) & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)); + rk29_sdmmc_write(host->regs, SDMMC_CTRL, SDMMC_CTRL_INT_ENABLE); + host->data = NULL; + host->cmd = NULL; + + switch (host->state) { + case STATE_IDLE: + break; + case STATE_SENDING_CMD: + mrq->cmd->error = -ENOMEDIUM; + if (!mrq->data) break; - case STATE_SENDING_CMD: - mrq->cmd->error = -ENOMEDIUM; - if (!mrq->data) - break; - /* fall through */ - case STATE_SENDING_DATA: + /* fall through */ + case STATE_SENDING_DATA: + mrq->data->error = -ENOMEDIUM; + rk29_sdmmc_stop_dma(host); + break; + case STATE_DATA_BUSY: + case STATE_DATA_ERROR: + if (mrq->data->error == -EINPROGRESS) mrq->data->error = -ENOMEDIUM; - rk29_sdmmc_stop_dma(host); - break; - case STATE_DATA_BUSY: - case STATE_DATA_ERROR: - if (mrq->data->error == -EINPROGRESS) - mrq->data->error = -ENOMEDIUM; - if (!mrq->stop) - break; - /* fall through */ - case STATE_SENDING_STOP: - mrq->stop->error = -ENOMEDIUM; + if (!mrq->stop) break; - } + /* fall through */ + case STATE_SENDING_STOP: + mrq->stop->error = -ENOMEDIUM; + break; + } rk29_sdmmc_request_end(host, mrq); } else { @@ -1264,14 +1161,13 @@ static void rk29_sdmmc_detect_change(unsigned long data) mrq->data->error = -ENOMEDIUM; if (mrq->stop) mrq->stop->error = -ENOMEDIUM; - spin_unlock(&host->lock); mmc_request_done(host->mmc, mrq); spin_lock(&host->lock); - } - + } } - mmc_detect_change(host->mmc, 0); + spin_unlock(&host->lock); + mmc_detect_change(host->mmc, 0); } static int rk29_sdmmc_probe(struct platform_device *pdev) @@ -1312,16 +1208,17 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) ret = -ENOMEM; host->regs = ioremap(regs->start, regs->end - regs->start); if (!host->regs) - goto err_freehost; - -#ifdef USE_DMA - if((strncmp(host->dma_name, "sdio", strlen("sdio")) == 1) - host->dma_chn = rk29_dma_request(DMACH_SDIO, &rk29_dma_sdio1_client, NULL); - if((strncmp(host->dma_name, "sd_mmc", strlen("sd_mmc")) == 1) - host->dma_chn = rk29_dma_request(DMACH_SDMMC, &rk29_dma_sdmmc0_client, NULL); - rk29_dma_config(host->dma_chn, 16); - rk29_dma_set_buffdone_fn(host->dma_chn, rk29_sdmmc_dma_complete) -#endif + goto err_freemap; + host->use_dma = pdata->use_dma; + if(host->use_dma){ + if(strncmp(host->dma_name, "sdio", strlen("sdio")) == 1) + host->dma_chn = rk29_dma_request(DMACH_SDIO, &rk29_dma_sdio1_client, NULL); + if(strncmp(host->dma_name, "sd_mmc", strlen("sd_mmc")) == 1) + host->dma_chn = rk29_dma_request(DMACH_SDMMC, &rk29_dma_sdmmc0_client, NULL); + rk29_dma_config(host->dma_chn, 16); + rk29_dma_setflags(host->dma_chn, RK29_DMAF_AUTOSTART); + rk29_dma_set_buffdone_fn(host->dma_chn, rk29_sdmmc_dma_complete); + } host->bus_hz = 25000000; ////cgu_get_clk_freq(CGU_SB_SD_MMC_CCLK_IN_ID); /* reset all blocks */ @@ -1349,29 +1246,28 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) if (ret) goto err_dmaunmap; - platform_set_drvdata(pdev, host); + platform_set_drvdata(pdev, host); memcpy(host->dma_name, pdata->dma_name, 8); mmc->ops = &rk29_sdmmc_ops[pdev->id]; - mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); - mmc->f_max = host->bus_hz/2; //max f is clock to mmc_clk/2 + mmc->f_min = host->bus_hz/510; + mmc->f_max = host->bus_hz/20; //max f is clock to mmc_clk/2 mmc->ocr_avail = pdata->host_ocr_avail; mmc->caps = pdata->host_caps; mmc->max_phys_segs = 64; mmc->max_hw_segs = 64; - mmc->max_blk_size = 65536; /* SDMMC_BLKSIZ is 16 bits*/ + mmc->max_blk_size = 4095; //65536; /* SDMMC_BLKSIZ is 16 bits*/ mmc->max_blk_count = 512; mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; mmc->max_seg_size = mmc->max_req_size; /* Assume card is present initially */ - if(!rk29_sdmmc_get_cd(host->mmc)) + if(rk29_sdmmc_get_cd(host->mmc)) set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); else clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); mmc_add_host(mmc); - - + #if defined (CONFIG_DEBUG_FS) rk29_sdmmc_init_debugfs(host); #endif @@ -1381,21 +1277,21 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) // enable interrupt for command done, data over, data empty, receive ready and error such as transmit, receive timeout, crc error rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF); - rk29_sdmmc_write(host->regs, SDMMC_INTMASK,SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_TXDR | SDMMC_INT_RXDR | RK29_SDMMC_ERROR_FLAGS); + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_TXDR | SDMMC_INT_RXDR | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD); rk29_sdmmc_write(host->regs, SDMMC_CTRL,SDMMC_CTRL_INT_ENABLE); // enable mci interrupt - - + rk29_sdmmc_write(host->regs, SDMMC_CLKENA,1); + ///rk29_sdmmc_write(host->regs, SDMMC_CLKDIV,2); dev_info(&pdev->dev, "RK29 SDMMC controller at irq %d\n", irq); return 0; err_dmaunmap: -#ifdef USE_DMA - if((strncmp(host->dma_name, "sdio", strlen("sdio")) == 1) - rk29_dma_free(DMACH_SDIO, &rk29_dma_sdio1_client); - if((strncmp(host->dma_name, "sd_mmc", strlen("sd_mmc")) == 1) - rk29_dma_free(DMACH_SDMMC, &rk29_dma_sdmmc0_client); + if(host->use_dma){ + if(strncmp(host->dma_name, "sdio", strlen("sdio")) == 1) + rk29_dma_free(DMACH_SDIO, &rk29_dma_sdio1_client); + if(strncmp(host->dma_name, "sd_mmc", strlen("sd_mmc")) == 1) + rk29_dma_free(DMACH_SDMMC, &rk29_dma_sdmmc0_client); + } err_freemap: -#endif iounmap(host->regs); err_freehost: kfree(host); @@ -1425,12 +1321,12 @@ static int __exit rk29_sdmmc_remove(struct platform_device *pdev) rk29_sdmmc_write(host->regs, SDMMC_CLKSRC,0); free_irq(platform_get_irq(pdev, 0), host); -#ifdef USE_DMA - if((strncmp(host->dma_name, "sdio", strlen("sdio")) == 1) - rk29_dma_free(DMACH_SDIO, &rk29_dma_sdio1_client); - if((strncmp(host->dma_name, "sd_mmc", strlen("sd_mmc")) == 1) - rk29_dma_free(DMACH_SDMMC, &rk29_dma_sdmmc0_client); -#endif + if(host->use_dma){ + if(strncmp(host->dma_name, "sdio", strlen("sdio")) == 1) + rk29_dma_free(DMACH_SDIO, &rk29_dma_sdio1_client); + if(strncmp(host->dma_name, "sd_mmc", strlen("sd_mmc")) == 1) + rk29_dma_free(DMACH_SDMMC, &rk29_dma_sdmmc0_client); + } iounmap(host->regs); kfree(host);