diff options
| author | Bernard Xiong <[email protected]> | 2021-05-28 16:20:08 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-05-28 16:20:08 +0800 |
| commit | 92beddf3bccf6346e26aa097f82464456fb8e6bd (patch) | |
| tree | 197e4a108118dda016ea02274172f0c40e7ee8ed /bsp/dm365/drivers/mmcsd.c | |
| parent | b18a99b44240ec3152011e159cc24a5af8dff0ce (diff) | |
| parent | 03f4d40e30f3c94e1db0b3a65b3610dee695694a (diff) | |
Merge pull request #4737 from mysterywolf/3,1,xformatv3.1.5
[lts 3.1.x] format codes
Diffstat (limited to 'bsp/dm365/drivers/mmcsd.c')
| -rw-r--r-- | bsp/dm365/drivers/mmcsd.c | 1938 |
1 files changed, 969 insertions, 969 deletions
diff --git a/bsp/dm365/drivers/mmcsd.c b/bsp/dm365/drivers/mmcsd.c index 7fcd0ef0c7..8e12236256 100644 --- a/bsp/dm365/drivers/mmcsd.c +++ b/bsp/dm365/drivers/mmcsd.c @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 * * Change Logs: - * Date Author Notes - * 2011-01-13 weety first version + * Date Author Notes + * 2011-01-13 weety first version */ #include <rtthread.h> @@ -18,66 +18,66 @@ #define RT_USING_MMCSD0 -#define MMCSD_DEBUG 0 +#define MMCSD_DEBUG 0 #if MMCSD_DEBUG -#define mmc_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) +#define mmc_dbg(fmt, ...) rt_kprintf(fmt, ##__VA_ARGS__) #else #define mmc_dbg(fmt, ...) #endif -#define MMU_NOCACHE_ADDR(a) ((rt_uint32_t)a | (1UL<<29)) -#define CACHE_LINE_SIZE 32 +#define MMU_NOCACHE_ADDR(a) ((rt_uint32_t)a | (1UL<<29)) +#define CACHE_LINE_SIZE 32 extern void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size); extern void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size); -#define EVT_QUEUE_NUM 0 /* EDMA3 Event queue number. */ +#define EVT_QUEUE_NUM 0 /* EDMA3 Event queue number. */ static unsigned rw_threshold = 32; static rt_bool_t use_dma = RT_TRUE; enum DATA_DIR_TYPE { - DM365_MMC_DATADIR_NONE = 0, - DM365_MMC_DATADIR_READ, - DM365_MMC_DATADIR_WRITE, + DM365_MMC_DATADIR_NONE = 0, + DM365_MMC_DATADIR_READ, + DM365_MMC_DATADIR_WRITE, }; -struct mmc_dm365_host +struct mmc_dm365_host { - struct rt_mmcsd_host *mmc; - struct rt_mmcsd_req *req; - struct rt_mmcsd_data *data; - struct rt_mmcsd_cmd *cmd; - struct edmacc_param tx_template; - struct edmacc_param rx_template; + struct rt_mmcsd_host *mmc; + struct rt_mmcsd_req *req; + struct rt_mmcsd_data *data; + struct rt_mmcsd_cmd *cmd; + struct edmacc_param tx_template; + struct edmacc_param rx_template; - rt_uint32_t mmc_input_clk; - rt_uint32_t ns_in_one_cycle; /* for ns in one cycle calculation */ + rt_uint32_t mmc_input_clk; + rt_uint32_t ns_in_one_cycle; /* for ns in one cycle calculation */ - mmcsd_regs_t *mmcsd_regs; - rt_uint8_t bus_mode; + mmcsd_regs_t *mmcsd_regs; + rt_uint8_t bus_mode; - enum DATA_DIR_TYPE data_dir; + enum DATA_DIR_TYPE data_dir; - rt_uint32_t rxdma; - rt_uint32_t txdma; - rt_bool_t use_dma; - rt_bool_t do_dma; + rt_uint32_t rxdma; + rt_uint32_t txdma; + rt_bool_t use_dma; + rt_bool_t do_dma; - rt_uint8_t *buffer; - rt_uint32_t buffer_bytes_left; - rt_uint32_t bytes_left; + rt_uint8_t *buffer; + rt_uint32_t buffer_bytes_left; + rt_uint32_t bytes_left; - rt_uint8_t *dma_buffer; - rt_bool_t use_dma_buffer; - rt_bool_t sdio_int; + rt_uint8_t *dma_buffer; + rt_bool_t use_dma_buffer; + rt_bool_t sdio_int; }; void *mmc_priv(struct rt_mmcsd_host *host) { - return (void *)host->private_data; + return (void *)host->private_data; } static void delay_us(rt_uint32_t us) @@ -90,968 +90,968 @@ static void delay_us(rt_uint32_t us) /******************************************************************************************************* ** 函数名称: calculate_freq_for_card() ** 功能描述: 此函数用于计算设置SD卡频率所需的分频数 -** -** 输 入: host -> DM365 MMC host句柄 -** mmc_req_freq -> MMC工作频率 +** +** 输 入: host -> DM365 MMC host句柄 +** mmc_req_freq -> MMC工作频率 ** ** 输 出: 分频值 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static rt_uint32_t calculate_freq_for_card(struct mmc_dm365_host *host, rt_uint32_t mmc_req_freq) { - rt_uint32_t mmc_freq = 0; - rt_uint32_t mmc_pclk = 0; - rt_uint32_t mmc_push_pull_divisor = 0; + rt_uint32_t mmc_freq = 0; + rt_uint32_t mmc_pclk = 0; + rt_uint32_t mmc_push_pull_divisor = 0; + + mmc_pclk = host->mmc_input_clk; + + if (mmc_req_freq && mmc_pclk > (2 * mmc_req_freq)) + mmc_push_pull_divisor = ((rt_uint32_t)mmc_pclk / (2 * mmc_req_freq)) - 1; + else + mmc_push_pull_divisor = 0; - mmc_pclk = host->mmc_input_clk; - - if (mmc_req_freq && mmc_pclk > (2 * mmc_req_freq)) - mmc_push_pull_divisor = ((rt_uint32_t)mmc_pclk / (2 * mmc_req_freq)) - 1; - else - mmc_push_pull_divisor = 0; + mmc_freq = (rt_uint32_t)mmc_pclk / (2 * (mmc_push_pull_divisor + 1)); - mmc_freq = (rt_uint32_t)mmc_pclk / (2 * (mmc_push_pull_divisor + 1)); + if (mmc_freq > mmc_req_freq) + mmc_push_pull_divisor = mmc_push_pull_divisor + 1; - if (mmc_freq > mmc_req_freq) - mmc_push_pull_divisor = mmc_push_pull_divisor + 1; - - /* Convert ns to clock cycles */ - if (mmc_req_freq <= 400000) - host->ns_in_one_cycle = (1000000)/(((mmc_pclk/(2*(mmc_push_pull_divisor+1)))/1000)); - else - host->ns_in_one_cycle = (1000000)/(((mmc_pclk/(2*(mmc_push_pull_divisor+1)))/1000000)); + /* Convert ns to clock cycles */ + if (mmc_req_freq <= 400000) + host->ns_in_one_cycle = (1000000)/(((mmc_pclk/(2*(mmc_push_pull_divisor+1)))/1000)); + else + host->ns_in_one_cycle = (1000000)/(((mmc_pclk/(2*(mmc_push_pull_divisor+1)))/1000000)); - return mmc_push_pull_divisor; + return mmc_push_pull_divisor; } /******************************************************************************************************* ** 函数名称: calculate_freq_for_card() ** 功能描述: 此函数用于计算MMC clock分频数 -** -** 输 入: host -> DM365 MMC host句柄 -** ios -> MMC 操作句柄 +** +** 输 入: host -> DM365 MMC host句柄 +** ios -> MMC 操作句柄 ** ** 输 出: 读取到的PHY寄存器值 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void calculate_clk_divider(struct rt_mmcsd_host *mmc, struct rt_mmcsd_io_cfg *ios) { - rt_uint32_t temp = 0; - rt_uint32_t mmc_pclk = 0; - rt_uint32_t open_drain_freq = 0; - rt_uint32_t mmc_push_pull_freq = 0; - struct mmc_dm365_host *host = mmc_priv(mmc); + rt_uint32_t temp = 0; + rt_uint32_t mmc_pclk = 0; + rt_uint32_t open_drain_freq = 0; + rt_uint32_t mmc_push_pull_freq = 0; + struct mmc_dm365_host *host = mmc_priv(mmc); - mmc_pclk = host->mmc_input_clk; + mmc_pclk = host->mmc_input_clk; - if (ios->bus_mode == MMCSD_BUSMODE_OPENDRAIN) - { - /* Ignoring the init clock value passed for fixing the inter - * operability with different cards. - */ - open_drain_freq = ((rt_uint32_t)mmc_pclk / (2 * MMCSD_INIT_CLOCK)) - 1; + if (ios->bus_mode == MMCSD_BUSMODE_OPENDRAIN) + { + /* Ignoring the init clock value passed for fixing the inter + * operability with different cards. + */ + open_drain_freq = ((rt_uint32_t)mmc_pclk / (2 * MMCSD_INIT_CLOCK)) - 1; - if (open_drain_freq > 0xFF) - open_drain_freq = 0xFF; + if (open_drain_freq > 0xFF) + open_drain_freq = 0xFF; - temp = host->mmcsd_regs->MMCCLK & ~MMCCLK_CLKRT_MASK; - temp |= open_drain_freq; - host->mmcsd_regs->MMCCLK = temp; + temp = host->mmcsd_regs->MMCCLK & ~MMCCLK_CLKRT_MASK; + temp |= open_drain_freq; + host->mmcsd_regs->MMCCLK = temp; - - /* Convert ns to clock cycles */ - host->ns_in_one_cycle = (1000000) / (MMCSD_INIT_CLOCK / 1000); - } - else - { - mmc_push_pull_freq = calculate_freq_for_card(host, ios->clock); - if (mmc_push_pull_freq > 0xFF) - mmc_push_pull_freq = 0xFF; + /* Convert ns to clock cycles */ + host->ns_in_one_cycle = (1000000) / (MMCSD_INIT_CLOCK / 1000); + } + else + { + mmc_push_pull_freq = calculate_freq_for_card(host, ios->clock); + + if (mmc_push_pull_freq > 0xFF) + mmc_push_pull_freq = 0xFF; + + temp = host->mmcsd_regs->MMCCLK & ~MMCCLK_CLKEN; + host->mmcsd_regs->MMCCLK = temp; - temp = host->mmcsd_regs->MMCCLK & ~MMCCLK_CLKEN; - host->mmcsd_regs->MMCCLK = temp; - - delay_us(10); + delay_us(10); - temp = host->mmcsd_regs->MMCCLK & ~MMCCLK_CLKRT_MASK; - temp |= mmc_push_pull_freq; - host->mmcsd_regs->MMCCLK = temp; - - host->mmcsd_regs->MMCCLK = temp | MMCCLK_CLKEN; + temp = host->mmcsd_regs->MMCCLK & ~MMCCLK_CLKRT_MASK; + temp |= mmc_push_pull_freq; + host->mmcsd_regs->MMCCLK = temp; - delay_us(10); - } + host->mmcsd_regs->MMCCLK = temp | MMCCLK_CLKEN; + + delay_us(10); + } } /******************************************************************************************************* ** 函数名称: mmc_dm365_set_ios() ** 功能描述: 此函数是mmc设置设置 -** -** 输 入: mmc -> mmc host 句柄 -** ios -> mmc 操作句柄 +** +** 输 入: mmc -> mmc host 句柄 +** ios -> mmc 操作句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_set_ios(struct rt_mmcsd_host *mmc, struct rt_mmcsd_io_cfg *ios) { - struct mmc_dm365_host *host = mmc_priv(mmc); + struct mmc_dm365_host *host = mmc_priv(mmc); - mmc_dbg("clock %dHz busmode %d powermode %d Vdd %04x\n", ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); + mmc_dbg("clock %dHz busmode %d powermode %d Vdd %04x\n", ios->clock, ios->bus_mode, ios->power_mode, ios->vdd); - switch (ios->bus_width) + switch (ios->bus_width) { - case MMCSD_BUS_WIDTH_8: + case MMCSD_BUS_WIDTH_8: mmc_dbg("Enabling 8 bit mode\n"); - host->mmcsd_regs->MMCCTL = (host->mmcsd_regs->MMCCTL & ~MMCCTL_WIDTH_4_BIT) | MMCCTL_WIDTH_8_BIT; - break; - case MMCSD_BUS_WIDTH_4: + host->mmcsd_regs->MMCCTL = (host->mmcsd_regs->MMCCTL & ~MMCCTL_WIDTH_4_BIT) | MMCCTL_WIDTH_8_BIT; + break; + case MMCSD_BUS_WIDTH_4: mmc_dbg("Enabling 4 bit mode\n"); - host->mmcsd_regs->MMCCTL = (host->mmcsd_regs->MMCCTL & ~MMCCTL_WIDTH_8_BIT) | MMCCTL_WIDTH_4_BIT; - break; - case MMCSD_BUS_WIDTH_1: + host->mmcsd_regs->MMCCTL = (host->mmcsd_regs->MMCCTL & ~MMCCTL_WIDTH_8_BIT) | MMCCTL_WIDTH_4_BIT; + break; + case MMCSD_BUS_WIDTH_1: mmc_dbg("Enabling 1 bit mode\n"); - host->mmcsd_regs->MMCCTL = host->mmcsd_regs->MMCCTL & ~(MMCCTL_WIDTH_8_BIT | MMCCTL_WIDTH_4_BIT); - break; - } + host->mmcsd_regs->MMCCTL = host->mmcsd_regs->MMCCTL & ~(MMCCTL_WIDTH_8_BIT | MMCCTL_WIDTH_4_BIT); + break; + } - calculate_clk_divider(mmc, ios); + calculate_clk_divider(mmc, ios); - host->bus_mode = ios->bus_mode; - if (ios->power_mode == MMCSD_POWER_UP) + host->bus_mode = ios->bus_mode; + if (ios->power_mode == MMCSD_POWER_UP) { - unsigned long timeout = rt_tick_get() + 500; - rt_bool_t lose = 1; + unsigned long timeout = rt_tick_get() + 500; + rt_bool_t lose = 1; - host->mmcsd_regs->MMCARGHL = 0; - host->mmcsd_regs->MMCCMD = MMCCMD_INITCK; - - while (rt_tick_get() < timeout) - { - rt_uint32_t tmp = host->mmcsd_regs->MMCST0; + host->mmcsd_regs->MMCARGHL = 0; + host->mmcsd_regs->MMCCMD = MMCCMD_INITCK; - if (tmp & MMCST0_RSPDNE) - { - lose = 0; - break; - } - } - if (lose) - mmc_dbg("powerup timeout\n"); - } + while (rt_tick_get() < timeout) + { + rt_uint32_t tmp = host->mmcsd_regs->MMCST0; + + if (tmp & MMCST0_RSPDNE) + { + lose = 0; + break; + } + } + if (lose) + mmc_dbg("powerup timeout\n"); + } } /******************************************************************************************************* ** 函数名称: dm365_fifo_data_trans() ** 功能描述: 此函数是fifo模式传输 -** -** 输 入: host -> DM365 mmc host 句柄 -** n -> 传输字节数 +** +** 输 入: host -> DM365 mmc host 句柄 +** n -> 传输字节数 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void dm365_fifo_data_trans(struct mmc_dm365_host *host, rt_uint32_t n) { - rt_uint8_t *p; - rt_uint32_t i; + rt_uint8_t *p; + rt_uint32_t i; + + p = host->buffer; - p = host->buffer; + if (host->bytes_left < n) + n = host->bytes_left; - if (host->bytes_left < n) - n = host->bytes_left; - - host->bytes_left -= n; + host->bytes_left -= n; - /* NOTE: we never transfer more than rw_threshold bytes - * to/from the fifo here; there's no I/O overlap. - * This also assumes that access width( i.e. ACCWD) is 4 bytes - */ - if (host->data_dir == DM365_MMC_DATADIR_WRITE) - { - for (i = 0; i < (n >> 2); i++) - { - host->mmcsd_regs->MMCDXR = *((rt_uint32_t *)p); - p = p + 4; - } - if (n & 3) - { - rt_kprintf("to do ... \n"); -// iowrite8_rep(host->base + MMCSD_MMCDXR, p, (n & 3)); - p = p + (n & 3); - } - } - else - { - for (i = 0; i < (n >> 2); i++) - { - *((rt_uint32_t *)p) = host->mmcsd_regs->MMCDRR; - p = p + 4; - } - if (n & 3) - { + /* NOTE: we never transfer more than rw_threshold bytes + * to/from the fifo here; there's no I/O overlap. + * This also assumes that access width( i.e. ACCWD) is 4 bytes + */ + if (host->data_dir == DM365_MMC_DATADIR_WRITE) + { + for (i = 0; i < (n >> 2); i++) + { + host->mmcsd_regs->MMCDXR = *((rt_uint32_t *)p); + p = p + 4; + } + if (n & 3) + { + rt_kprintf("to do ... \n"); +// iowrite8_rep(host->base + MMCSD_MMCDXR, p, (n & 3)); + p = p + (n & 3); + } + } + else + { + for (i = 0; i < (n >> 2); i++) + { + *((rt_uint32_t *)p) = host->mmcsd_regs->MMCDRR; + p = p + 4; + } + if (n & 3) + { rt_kprintf("to do ... \n"); -// ioread8_rep(host->base + MMCSD_MMCDRR, p, (n & 3)); - p = p + (n & 3); - } - } - host->buffer = p; +// ioread8_rep(host->base + MMCSD_MMCDRR, p, (n & 3)); + p = p + (n & 3); + } + } + host->buffer = p; } /******************************************************************************************************* ** 函数名称: mmc_dm365_start_command() ** 功能描述: 此函数是开始发送SD命令 -** -** 输 入: host -> DM365 mmc host 句柄 -** cmd -> SD命令句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** cmd -> SD命令句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_start_command(struct mmc_dm365_host *host, struct rt_mmcsd_cmd *cmd) { - rt_uint32_t cmd_reg = 0; - rt_uint32_t im_val; - - host->cmd = cmd; + rt_uint32_t cmd_reg = 0; + rt_uint32_t im_val; + + host->cmd = cmd; - switch (resp_type(cmd)) - { - case RESP_R1B: - /* There's some spec confusion about when R1B is - * allowed, but if the card doesn't issue a BUSY - * then it's harmless for us to allow it. - */ - cmd_reg |= MMCCMD_BSYEXP; - /* FALLTHROUGH */ - case RESP_R1: /* 48 bits, CRC */ + switch (resp_type(cmd)) + { + case RESP_R1B: + /* There's some spec confusion about when R1B is + * allowed, but if the card doesn't issue a BUSY + * then it's harmless for us to allow it. + */ + cmd_reg |= MMCCMD_BSYEXP; + /* FALLTHROUGH */ + case RESP_R1: /* 48 bits, CRC */ case RESP_R4: - case RESP_R5: + case RESP_R5: case RESP_R6: - case RESP_R7: - cmd_reg |= MMCCMD_RSPFMT_R1456; - break; - case RESP_R2: /* 136 bits, CRC */ - cmd_reg |= MMCCMD_RSPFMT_R2; - break; - case RESP_R3: /* 48 bits, no CRC */ - cmd_reg |= MMCCMD_RSPFMT_R3; - break; - default: - cmd_reg |= MMCCMD_RSPFMT_NONE; - mmc_dbg("unknown resp_type %04x\n", resp_type(cmd)); - break; - } + case RESP_R7: + cmd_reg |= MMCCMD_RSPFMT_R1456; + break; + case RESP_R2: /* 136 bits, CRC */ + cmd_reg |= MMCCMD_RSPFMT_R2; + break; + case RESP_R3: /* 48 bits, no CRC */ + cmd_reg |= MMCCMD_RSPFMT_R3; + break; + default: + cmd_reg |= MMCCMD_RSPFMT_NONE; + mmc_dbg("unknown resp_type %04x\n", resp_type(cmd)); + break; + } + + /* Set command index */ + cmd_reg |= cmd->cmd_code; + + /* Enable EDMA transfer triggers */ + if (host->do_dma == RT_TRUE) + cmd_reg |= MMCCMD_DMATRIG; - /* Set command index */ - cmd_reg |= cmd->cmd_code; + if (host->data != RT_NULL && host->data_dir == DM365_MMC_DATADIR_READ) + cmd_reg |= MMCCMD_DMATRIG; - /* Enable EDMA transfer triggers */ - if (host->do_dma == RT_TRUE) - cmd_reg |= MMCCMD_DMATRIG; + /* Setting whether command involves data transfer or not */ + if (cmd->data) + cmd_reg |= MMCCMD_WDATX; - if (host->data != RT_NULL && host->data_dir == DM365_MMC_DATADIR_READ) - cmd_reg |= MMCCMD_DMATRIG; + /* Setting whether stream or block transfer */ + if (cmd->flags & MMC_DATA_STREAM) + { + mmc_dbg("to do\n"); + cmd_reg |= MMCCMD_STRMTP; + } - /* Setting whether command involves data transfer or not */ - if (cmd->data) - cmd_reg |= MMCCMD_WDATX; + /* Setting whether data read or write */ + if (host->data_dir == DM365_MMC_DATADIR_WRITE) + cmd_reg |= MMCCMD_DTRW; - /* Setting whether stream or block transfer */ - if (cmd->flags & MMC_DATA_STREAM) - { - mmc_dbg("to do\n"); - cmd_reg |= MMCCMD_STRMTP; - } + if (host->bus_mode == MMCSD_BUSMODE_PUSHPULL) + { + cmd_reg |= MMCCMD_PPLEN; + } - /* Setting whether data read or write */ - if (host->data_dir == DM365_MMC_DATADIR_WRITE) - cmd_reg |= MMCCMD_DTRW; + /* set Command timeout */ + host->mmcsd_regs->MMCTOR = 0x1FFF; - if (host->bus_mode == MMCSD_BUSMODE_PUSHPULL) - { - cmd_reg |= MMCCMD_PPLEN; - } - - /* set Command timeout */ - host->mmcsd_regs->MMCTOR = 0x1FFF; - - /* Enable interrupt (calculate here, defer until FIFO is stuffed). */ - im_val = MMCST0_RSPDNE | MMCST0_CRCRS | MMCST0_TOUTRS; - if (host->data_dir == DM365_MMC_DATADIR_WRITE) - { - im_val |= MMCST0_DATDNE | MMCST0_CRCWR; + /* Enable interrupt (calculate here, defer until FIFO is stuffed). */ + im_val = MMCST0_RSPDNE | MMCST0_CRCRS | MMCST0_TOUTRS; + if (host->data_dir == DM365_MMC_DATADIR_WRITE) + { + im_val |= MMCST0_DATDNE | MMCST0_CRCWR; - if (host->do_dma == RT_FALSE) - im_val |= MMCST0_DXRDY; - } - else if (host->data_dir == DM365_MMC_DATADIR_READ) - { - im_val |= MMCST0_DATDNE | MMCST0_CRCRD | MMCST0_TOUTRD; + if (host->do_dma == RT_FALSE) + im_val |= MMCST0_DXRDY; + } + else if (host->data_dir == DM365_MMC_DATADIR_READ) + { + im_val |= MMCST0_DATDNE | MMCST0_CRCRD | MMCST0_TOUTRD; - if (host->do_dma == RT_FALSE) - im_val |= MMCST0_DRRDY; - } + if (host->do_dma == RT_FALSE) + im_val |= MMCST0_DRRDY; + } - /* - * Before non-DMA WRITE commands the controller needs priming: - * FIFO should be populated with 32 bytes i.e. whatever is the FIFO size - */ - if ((host->do_dma == RT_FALSE) && (host->data_dir == DM365_MMC_DATADIR_WRITE)) - dm365_fifo_data_trans(host, rw_threshold); + /* + * Before non-DMA WRITE commands the controller needs priming: + * FIFO should be populated with 32 bytes i.e. whatever is the FIFO size + */ + if ((host->do_dma == RT_FALSE) && (host->data_dir == DM365_MMC_DATADIR_WRITE)) + dm365_fifo_data_trans(host, rw_threshold); - host->mmcsd_regs->MMCARGHL = cmd->arg; - host->mmcsd_regs->MMCCMD = cmd_reg; - host->mmcsd_regs->MMCIM = im_val; + host->mmcsd_regs->MMCARGHL = cmd->arg; + host->mmcsd_regs->MMCCMD = cmd_reg; + host->mmcsd_regs->MMCIM = im_val; } /******************************************************************************************************* ** 函数名称: dm365_abort_dma() ** 功能描述: 此函数终止DMA传输 -** -** 输 入: host -> DM365 mmc host 句柄 +** +** 输 入: host -> DM365 mmc host 句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void dm365_abort_dma(struct mmc_dm365_host *host) { - int sync_dev; + int sync_dev; - if (host->data_dir == DM365_MMC_DATADIR_READ) - sync_dev = host->rxdma; - else - sync_dev = host->txdma; + if (host->data_dir == DM365_MMC_DATADIR_READ) + sync_dev = host->rxdma; + else + sync_dev = host->txdma; - //EDMA3DisableTransfer(EDMA0CC0_REG_BASE, sync_dev, EDMA3_TRIG_MODE_EVENT); - edma_stop(sync_dev); - edma_clean_channel(sync_dev); + //EDMA3DisableTransfer(EDMA0CC0_REG_BASE, sync_dev, EDMA3_TRIG_MODE_EVENT); + edma_stop(sync_dev); + edma_clean_channel(sync_dev); } /******************************************************************************************************* ** 函数名称: mmc_request_done() ** 功能描述: 此函数用于结束处理一个MMC请求 -** -** 输 入: host -> DM365 mmc host 句柄 -** mrq -> request 句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** mrq -> request 句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ void mmc_request_done(struct rt_mmcsd_host *host, struct rt_mmcsd_req *mrq) { - struct rt_mmcsd_cmd *cmd = mrq->cmd; - int err = cmd->err; + struct rt_mmcsd_cmd *cmd = mrq->cmd; + int err = cmd->err; - if (err && cmd->retries) - { - mmc_dbg("req failed (CMD%u): %d, retrying...\n", cmd->cmd_code, err); + if (err && cmd->retries) + { + mmc_dbg("req failed (CMD%u): %d, retrying...\n", cmd->cmd_code, err); - cmd->retries--; - cmd->err = 0; - host->ops->request(host, mrq); - } - else - { - mmc_dbg("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n", - "dm365 host", cmd->cmd_code, err, - cmd->resp[0], cmd->resp[1], - cmd->resp[2], cmd->resp[3]); + cmd->retries--; + cmd->err = 0; + host->ops->request(host, mrq); + } + else + { + mmc_dbg("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n", + "dm365 host", cmd->cmd_code, err, + cmd->resp[0], cmd->resp[1], + cmd->resp[2], cmd->resp[3]); - if (mrq->data) - { - mmc_dbg("%s: %d bytes transferred: %d\n", - "dm365 host", - mrq->data->bytes_xfered, mrq->data->err); - } + if (mrq->data) + { + mmc_dbg("%s: %d bytes transferred: %d\n", + "dm365 host", + mrq->data->bytes_xfered, mrq->data->err); + } - if (mrq->stop) - { - mmc_dbg("%s: (CMD%u): %d: %08x %08x %08x %08x\n", - "dm365 host", mrq->stop->cmd_code, - mrq->stop->err, - mrq->stop->resp[0], mrq->stop->resp[1], - mrq->stop->resp[2], mrq->stop->resp[3]); - } + if (mrq->stop) + { + mmc_dbg("%s: (CMD%u): %d: %08x %08x %08x %08x\n", + "dm365 host", mrq->stop->cmd_code, + mrq->stop->err, + mrq->stop->resp[0], mrq->stop->resp[1], + mrq->stop->resp[2], mrq->stop->resp[3]); + } - mmcsd_req_complete(host); - } + mmcsd_req_complete(host); + } } /******************************************************************************************************* ** 函数名称: mmc_dm365_xfer_done() ** 功能描述: 数据传送结束调用此函数 -** -** 输 入: host -> DM365 mmc host 句柄 -** data -> data 句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** data -> data 句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_xfer_done(struct mmc_dm365_host *host, struct rt_mmcsd_data *data) { - host->data = RT_NULL; + host->data = RT_NULL; + + if (host->mmc->flags & MMCSD_SUP_SDIO_IRQ) { + /* + * SDIO Interrupt Detection work-around as suggested by + * Davinci Errata (TMS320DM355 Silicon Revision 1.1 Errata + * 2.1.6): Signal SDIO interrupt only if it is enabled by core + */ + if (host->sdio_int && !(host->mmcsd_regs->SDIOST0 & + SDIOST0_DAT1_HI)) { + host->mmcsd_regs->SDIOIST = SDIOIST_IOINT; + sdio_irq_wakeup(host->mmc); + } + } - if (host->mmc->flags & MMCSD_SUP_SDIO_IRQ) { - /* - * SDIO Interrupt Detection work-around as suggested by - * Davinci Errata (TMS320DM355 Silicon Revision 1.1 Errata - * 2.1.6): Signal SDIO interrupt only if it is enabled by core - */ - if (host->sdio_int && !(host->mmcsd_regs->SDIOST0 & - SDIOST0_DAT1_HI)) { - host->mmcsd_regs->SDIOIST = SDIOIST_IOINT; - sdio_irq_wakeup(host->mmc); - } - } + if (host->do_dma == RT_TRUE) + { + dm365_abort_dma(host); - if (host->do_dma == RT_TRUE) - { - dm365_abort_dma(host); + if (data->flags & DATA_DIR_READ) + { + /* read operation */ + if (host->use_dma_buffer == RT_TRUE) + { + /* copy DMA buffer to read buffer */ + memcpy(data->buf, (void*)MMU_NOCACHE_ADDR(host->dma_buffer), data->blks * data->blksize); + } + /*else + { + mmu_invalidate_dcache((rt_uint32_t)data->buf, data->blks * data->blksize); + }*/ + } - if (data->flags & DATA_DIR_READ) - { - /* read operation */ - if (host->use_dma_buffer == RT_TRUE) - { - /* copy DMA buffer to read buffer */ - memcpy(data->buf, (void*)MMU_NOCACHE_ADDR(host->dma_buffer), data->blks * data->blksize); - } - /*else - { - mmu_invalidate_dcache((rt_uint32_t)data->buf, data->blks * data->blksize); - }*/ - } + host->do_dma = RT_FALSE; + } - host->do_dma = RT_FALSE; - } - - host->data_dir = DM365_MMC_DATADIR_NONE; + host->data_dir = DM365_MMC_DATADIR_NONE; - if (!data->stop || (host->cmd && host->cmd->err)) - { - mmc_request_done(host->mmc, data->mrq); - host->mmcsd_regs->MMCIM = 0; - } - else - mmc_dm365_start_command(host, data->stop); + if (!data->stop || (host->cmd && host->cmd->err)) + { + mmc_request_done(host->mmc, data->mrq); + host->mmcsd_regs->MMCIM = 0; + } + else + mmc_dm365_start_command(host, data->stop); } static void mmc_dm365_dma_cb(unsigned channel, rt_uint16_t ch_status, void *data) { - if (DMA_COMPLETE != ch_status) { - struct mmc_dm365_host *host = data; + if (DMA_COMPLETE != ch_status) { + struct mmc_dm365_host *host = data; - /* Currently means: DMA Event Missed, or "null" transfer - * request was seen. In the future, TC errors (like bad - * addresses) might be presented too. - */ - mmc_dbg("DMA %s error\n", - (host->data->flags & MMC_DATA_WRITE) - ? "write" : "read"); - host->data->err = -RT_EIO; - mmc_dm365_xfer_done(host, host->data); - } + /* Currently means: DMA Event Missed, or "null" transfer + * request was seen. In the future, TC errors (like bad + * addresses) might be presented too. + */ + mmc_dbg("DMA %s error\n", + (host->data->flags & MMC_DATA_WRITE) + ? "write" : "read"); + host->data->err = -RT_EIO; + mmc_dm365_xfer_done(host, host->data); + } } /******************************************************************************************************* ** 函数名称: mmc_dm365_dma_setup() ** 功能描述: DMA 设置函数 -** -** 输 入: host -> DM365 mmc host 句柄 -** tx -> 布尔变量,用于判断Tx或者是Rx -** template -> 用于保存EDMA3CCPaRAMEntry机构数据 +** +** 输 入: host -> DM365 mmc host 句柄 +** tx -> 布尔变量,用于判断Tx或者是Rx +** template -> 用于保存EDMA3CCPaRAMEntry机构数据 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_dma_setup(struct mmc_dm365_host *host, rt_bool_t tx, struct edmacc_param *template) { - rt_uint32_t sync_dev; - const rt_uint16_t acnt = 4; - const rt_uint16_t bcnt = rw_threshold >> 2; - const rt_uint16_t ccnt = 0; - rt_uint32_t src_port = 0; - rt_uint32_t dst_port = 0; - rt_int16_t src_bidx, dst_bidx; - rt_int16_t src_cidx, dst_cidx; + rt_uint32_t sync_dev; + const rt_uint16_t acnt = 4; + const rt_uint16_t bcnt = rw_threshold >> 2; + const rt_uint16_t ccnt = 0; + rt_uint32_t src_port = 0; + rt_uint32_t dst_port = 0; + rt_int16_t src_bidx, dst_bidx; + rt_int16_t src_cidx, dst_cidx; //edmacc_param paramSet; - /* - * A-B Sync transfer: each DMA request is for one "frame" of - * rw_threshold bytes, broken into "acnt"-size chunks repeated - * "bcnt" times. Each segment needs "ccnt" such frames; since - * we tell the block layer our mmc->max_seg_size limit, we can - * trust (later) that it's within bounds. - * - * The FIFOs are read/written in 4-byte chunks (acnt == 4) and - * EDMA will optimize memory operations to use larger bursts. - */ - if (tx) - { - sync_dev = host->txdma; + /* + * A-B Sync transfer: each DMA request is for one "frame" of + * rw_threshold bytes, broken into "acnt"-size chunks repeated + * "bcnt" times. Each segment needs "ccnt" such frames; since + * we tell the block layer our mmc->max_seg_size limit, we can + * trust (later) that it's within bounds. + * + * The FIFOs are read/written in 4-byte chunks (acnt == 4) and + * EDMA will optimize memory operations to use larger bursts. + */ + if (tx) + { + sync_dev = host->txdma; + + /* src_prt, ccnt, and link to be set up later */ + /*paramSet.srcBIdx = acnt; + paramSet.srcCIdx = acnt * bcnt; - /* src_prt, ccnt, and link to be set up later */ - /*paramSet.srcBIdx = acnt; - paramSet.srcCIdx = acnt * bcnt; + paramSet.destAddr = (rt_uint32_t)&(host->mmcsd_regs->MMCDXR); + paramSet.destBIdx = 0; + paramSet.destCIdx = 0;*/ + /* src_prt, ccnt, and link to be set up later */ + src_bidx = acnt; + src_cidx = acnt * bcnt; - paramSet.destAddr = (rt_uint32_t)&(host->mmcsd_regs->MMCDXR); - paramSet.destBIdx = 0; - paramSet.destCIdx = 0;*/ - /* src_prt, ccnt, and link to be set up later */ - src_bidx = acnt; - src_cidx = acnt * bcnt; + dst_port = (rt_uint32_t)&(host->mmcsd_regs->MMCDXR); + dst_bidx = 0; + dst_cidx = 0; + } + else + { + sync_dev = host->rxdma; - dst_port = (rt_uint32_t)&(host->mmcsd_regs->MMCDXR); - dst_bidx = 0; - dst_cidx = 0; - } - else - { - sync_dev = host->rxdma; + /* dst_prt, ccnt, and link to be set up later */ + /*paramSet.srcAddr = (rt_uint32_t)&(host->mmcsd_regs->MMCDRR); + paramSet.srcBIdx = 0; + paramSet.srcCIdx = 0; - /* dst_prt, ccnt, and link to be set up later */ - /*paramSet.srcAddr = (rt_uint32_t)&(host->mmcsd_regs->MMCDRR); - paramSet.srcBIdx = 0; - paramSet.srcCIdx = 0; + paramSet.destBIdx = acnt; + paramSet.destCIdx = acnt * bcnt;*/ + src_port = (rt_uint32_t)&(host->mmcsd_regs->MMCDRR); + src_bidx = 0; + src_cidx = 0; - paramSet.destBIdx = acnt; - paramSet.destCIdx = acnt * bcnt;*/ - src_port = (rt_uint32_t)&(host->mmcsd_regs->MMCDRR); - src_bidx = 0; - src_cidx = 0; + /* dst_prt, ccnt, and link to be set up later */ + dst_bidx = acnt; + dst_cidx = acnt * bcnt; + } + /* + * We can't use FIFO mode for the FIFOs because MMC FIFO addresses + * are not 256-bit (32-byte) aligned. So we use INCR, and the W8BIT + * parameter is ignored. + */ + edma_set_src(sync_dev, src_port, INCR, W8BIT); + edma_set_dest(sync_dev, dst_port, INCR, W8BIT); - /* dst_prt, ccnt, and link to be set up later */ - dst_bidx = acnt; - dst_cidx = acnt * bcnt; - } - /* - * We can't use FIFO mode for the FIFOs because MMC FIFO addresses - * are not 256-bit (32-byte) aligned. So we use INCR, and the W8BIT - * parameter is ignored. - */ - edma_set_src(sync_dev, src_port, INCR, W8BIT); - edma_set_dest(sync_dev, dst_port, INCR, W8BIT); + edma_set_src_index(sync_dev, src_bidx, src_cidx); + edma_set_dest_index(sync_dev, dst_bidx, dst_cidx); - edma_set_src_index(sync_dev, src_bidx, src_cidx); - edma_set_dest_index(sync_dev, dst_bidx, dst_cidx); + edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC); - edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC); + edma_read_slot(sync_dev, template); - edma_read_slot(sync_dev, template); + /* don't bother with irqs or chaining */ + template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12; - /* don't bother with irqs or chaining */ - template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12; - #if 0 - paramSet.opt = 0u; - /* Src & Dest are in INCR modes */ - paramSet.opt &= 0xFFFFFFFCu; - /* Program the TCC */ - paramSet.opt |= ((sync_dev << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC); - - paramSet.aCnt = acnt; - paramSet.bCnt = bcnt; - - /* AB Sync Transfer Mode */ - paramSet.opt |= (1 << EDMA3CC_OPT_SYNCDIM_SHIFT); - - /* Now, write the PaRAM Set. */ - EDMA3SetPaRAM(EDMA0CC0_REG_BASE, sync_dev, ¶mSet); + paramSet.opt = 0u; + /* Src & Dest are in INCR modes */ + paramSet.opt &= 0xFFFFFFFCu; + /* Program the TCC */ + paramSet.opt |= ((sync_dev << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC); - EDMA3GetPaRAM(EDMA0CC0_REG_BASE, sync_dev, template); + paramSet.aCnt = acnt; + paramSet.bCnt = bcnt; + + /* AB Sync Transfer Mode */ + paramSet.opt |= (1 << EDMA3CC_OPT_SYNCDIM_SHIFT); + + /* Now, write the PaRAM Set. */ + EDMA3SetPaRAM(EDMA0CC0_REG_BASE, sync_dev, ¶mSet); + + EDMA3GetPaRAM(EDMA0CC0_REG_BASE, sync_dev, template); #endif } /******************************************************************************************************* ** 函数名称: mmc_dm365_send_dma_request() ** 功能描述: 发送DMA请求 -** -** 输 入: host -> DM365 mmc host 句柄 -** data -> DMA传送数据结构句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** data -> DMA传送数据结构句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_send_dma_request(struct mmc_dm365_host *host, struct rt_mmcsd_data *data) { - //struct EDMA3CCPaRAMEntry *template; - struct edmacc_param *template; - rt_uint32_t buf_ptr; - rt_uint32_t channel; - rt_uint32_t bytes_left = host->bytes_left; - rt_uint32_t count = host->bytes_left; - const rt_uint32_t shift = ffs(rw_threshold) - 1; + //struct EDMA3CCPaRAMEntry *template; + struct edmacc_param *template; + rt_uint32_t buf_ptr; + rt_uint32_t channel; + rt_uint32_t bytes_left = host->bytes_left; + rt_uint32_t count = host->bytes_left; + const rt_uint32_t shift = ffs(rw_threshold) - 1; - if (host->use_dma_buffer == RT_TRUE) - buf_ptr = host->dma_buffer;//MMU_NOCACHE_ADDR(host->dma_buffer); - else - buf_ptr = (rt_uint32_t)data->buf; + if (host->use_dma_buffer == RT_TRUE) + buf_ptr = host->dma_buffer;//MMU_NOCACHE_ADDR(host->dma_buffer); + else + buf_ptr = (rt_uint32_t)data->buf; - if (host->data_dir == DM365_MMC_DATADIR_WRITE) - { - template = &host->tx_template; - channel = host->txdma; - } - else - { - template = &host->rx_template; - channel = host->rxdma; - } + if (host->data_dir == DM365_MMC_DATADIR_WRITE) + { + template = &host->tx_template; + channel = host->txdma; + } + else + { + template = &host->rx_template; + channel = host->rxdma; + } - template->link_bcntrld = 0xffff; - //template->bCntReload = 0x0; + template->link_bcntrld = 0xffff; + //template->bCntReload = 0x0; - if (count > bytes_left) - count = bytes_left; - bytes_left -= count; + if (count > bytes_left) + count = bytes_left; + bytes_left -= count; - if (host->data_dir == DM365_MMC_DATADIR_WRITE) - template->src = buf_ptr; - else - template->dst = buf_ptr; - template->ccnt = count >> shift; + if (host->data_dir == DM365_MMC_DATADIR_WRITE) + template->src = buf_ptr; + else + template->dst = buf_ptr; + template->ccnt = count >> shift; - edma_write_slot(channel, template); + edma_write_slot(channel, template); - edma_clear_event(channel); + edma_clear_event(channel); - /*EDMA3SetPaRAM(EDMA0CC0_REG_BASE, channel, template); - EDMA3ClrEvt(EDMA0CC0_REG_BASE, channel); - EDMA3EnableTransfer(EDMA0CC0_REG_BASE, channel, EDMA3_TRIG_MODE_EVENT);*/ - edma_start(channel); + /*EDMA3SetPaRAM(EDMA0CC0_REG_BASE, channel, template); + EDMA3ClrEvt(EDMA0CC0_REG_BASE, channel); + EDMA3EnableTransfer(EDMA0CC0_REG_BASE, channel, EDMA3_TRIG_MODE_EVENT);*/ + edma_start(channel); } /******************************************************************************************************* ** 函数名称: mmc_dm365_start_dma_transfer() ** 功能描述: 开始DMA传输 -** -** 输 入: host -> DM365 mmc host 句柄 -** data -> DMA传送数据结构句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** data -> DMA传送数据结构句柄 ** ** 输 出: DMA传输字节数 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static int mmc_dm365_start_dma_transfer(struct mmc_dm365_host *host, struct rt_mmcsd_data *data) { - /* set initial value */ - host->use_dma_buffer = RT_FALSE; + /* set initial value */ + host->use_dma_buffer = RT_FALSE; - if (!(data->flags & DATA_DIR_READ)) - { - if ((rt_uint32_t)data->buf & (RT_ALIGN_SIZE - 1)) - { - /* not align to basic size, use DMA buffer */ - host->use_dma_buffer = RT_TRUE; - memcpy((void*)MMU_NOCACHE_ADDR(host->dma_buffer), data->buf, data->blks * data->blksize); - } - else - { - rt_uint32_t addr; - addr = ((rt_uint32_t)data->buf & ~(CACHE_LINE_SIZE - 1)); - /* write data case, always clean DCache */ - mmu_clean_dcache(addr, (data->blks + 1)* data->blksize); - } - } - else - { - /* whether align to cache line in read operation */ - if (((rt_uint32_t)data->buf) & (CACHE_LINE_SIZE - 1)) - host->use_dma_buffer = RT_TRUE; - else - mmu_invalidate_dcache((rt_uint32_t)data->buf, data->blks * data->blksize); - } + if (!(data->flags & DATA_DIR_READ)) + { + if ((rt_uint32_t)data->buf & (RT_ALIGN_SIZE - 1)) + { + /* not align to basic size, use DMA buffer */ + host->use_dma_buffer = RT_TRUE; + memcpy((void*)MMU_NOCACHE_ADDR(host->dma_buffer), data->buf, data->blks * data->blksize); + } + else + { + rt_uint32_t addr; + addr = ((rt_uint32_t)data->buf & ~(CACHE_LINE_SIZE - 1)); + /* write data case, always clean DCache */ + mmu_clean_dcache(addr, (data->blks + 1)* data->blksize); + } + } + else + { + /* whether align to cache line in read operation */ + if (((rt_uint32_t)data->buf) & (CACHE_LINE_SIZE - 1)) + host->use_dma_buffer = RT_TRUE; + else + mmu_invalidate_dcache((rt_uint32_t)data->buf, data->blks * data->blksize); + } - host->do_dma = RT_TRUE; - mmc_dm365_send_dma_request(host, data); + host->do_dma = RT_TRUE; + mmc_dm365_send_dma_request(host, data); - return 0; + return 0; } #if 0 /******************************************************************************************************* ** 函数名称: acquire_dma_channels() ** 功能描述: 获取DMA channel -** -** 输 入: host -> DM365 mmc host 句柄 +** +** 输 入: host -> DM365 mmc host 句柄 ** ** 输 出: DMA 通道号 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static int acquire_dma_channels(struct mmc_dm365_host *host) { - int r; + int r; - /* Acquire master DMA write channel */ - r = EDMA3RequestChannel(EDMA0CC0_REG_BASE, EDMA3_CHANNEL_TYPE_DMA, host->txdma, host->txdma, EVT_QUEUE_NUM); - if (r < 0) - { - rt_kprintf("alloc %s channel err %d\n", "tx", r); - return r; - } - mmc_dm365_dma_setup(host, RT_TRUE, &host->tx_template); + /* Acquire master DMA write channel */ + r = EDMA3RequestChannel(EDMA0CC0_REG_BASE, EDMA3_CHANNEL_TYPE_DMA, host->txdma, host->txdma, EVT_QUEUE_NUM); + if (r < 0) + { + rt_kprintf("alloc %s channel err %d\n", "tx", r); + return r; + } + mmc_dm365_dma_setup(host, RT_TRUE, &host->tx_template); - /* Acquire master DMA read channel */ - r = EDMA3RequestChannel(EDMA0CC0_REG_BASE, EDMA3_CHANNEL_TYPE_DMA, host->rxdma, host->rxdma, EVT_QUEUE_NUM); - if (r < 0) - { - rt_kprintf("alloc %s channel err %d\n", "rx", r); - goto free_master_write; - } - mmc_dm365_dma_setup(host, RT_FALSE, &host->rx_template); + /* Acquire master DMA read channel */ + r = EDMA3RequestChannel(EDMA0CC0_REG_BASE, EDMA3_CHANNEL_TYPE_DMA, host->rxdma, host->rxdma, EVT_QUEUE_NUM); + if (r < 0) + { + rt_kprintf("alloc %s channel err %d\n", "rx", r); + goto free_master_write; + } + mmc_dm365_dma_setup(host, RT_FALSE, &host->rx_template); - return 0; + return 0; free_master_write: - EDMA3FreeChannel(EDMA0CC0_REG_BASE, EDMA3_CHANNEL_TYPE_DMA, host->txdma, EDMA3_TRIG_MODE_EVENT, host->txdma, EVT_QUEUE_NUM); + EDMA3FreeChannel(EDMA0CC0_REG_BASE, EDMA3_CHANNEL_TYPE_DMA, host->txdma, EDMA3_TRIG_MODE_EVENT, host->txdma, EVT_QUEUE_NUM); - return r; + return r; } #endif static int acquire_dma_channels(struct mmc_dm365_host *host) { - //u32 link_size; - int r, i; + //u32 link_size; + int r, i; - /* Acquire master DMA write channel */ - r = edma_alloc_channel(host->txdma, mmc_dm365_dma_cb, host, - EVENTQ_DEFAULT); - if (r < 0) { - mmc_dbg("alloc %s channel err %d\n", - "tx", r); - return r; - } - mmc_dm365_dma_setup(host, RT_TRUE, &host->tx_template); + /* Acquire master DMA write channel */ + r = edma_alloc_channel(host->txdma, mmc_dm365_dma_cb, host, + EVENTQ_DEFAULT); + if (r < 0) { + mmc_dbg("alloc %s channel err %d\n", + "tx", r); + return r; + } + mmc_dm365_dma_setup(host, RT_TRUE, &host->tx_template); - /* Acquire master DMA read channel */ - r = edma_alloc_channel(host->rxdma, mmc_dm365_dma_cb, host, - EVENTQ_DEFAULT); - if (r < 0) { - mmc_dbg("alloc %s channel err %d\n", - "rx", r); - goto free_master_write; - } - mmc_dm365_dma_setup(host, RT_FALSE, &host->rx_template); + /* Acquire master DMA read channel */ + r = edma_alloc_channel(host->rxdma, mmc_dm365_dma_cb, host, + EVENTQ_DEFAULT); + if (r < 0) { + mmc_dbg("alloc %s channel err %d\n", + "rx", r); + goto free_master_write; + } + mmc_dm365_dma_setup(host, RT_FALSE, &host->rx_template); - /* Allocate parameter RAM slots, which will later be bound to a - * channel as needed to handle a scatterlist. - */ + /* Allocate parameter RAM slots, which will later be bound to a + * channel as needed to handle a scatterlist. + */ #if 0 - link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links)); - for (i = 0; i < link_size; i++) { - r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); - if (r < 0) { - mmc_dbg("dma PaRAM alloc --> %d\n", - r); - break; - } - host->links[i] = r; - } - host->n_link = i; + link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links)); + for (i = 0; i < link_size; i++) { + r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); + if (r < 0) { + mmc_dbg("dma PaRAM alloc --> %d\n", + r); + break; + } + host->links[i] = r; + } + host->n_link = i; #endif - return 0; + return 0; free_master_write: - edma_free_channel(host->txdma); + edma_free_channel(host->txdma); - return r; + return r; } /******************************************************************************************************* ** 函数名称: mmc_dm365_prepare_data() ** 功能描述: 准备 DMA 数据 -** -** 输 入: host -> DM365 mmc host 句柄 -** req -> SD request 结构句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** req -> SD request 结构句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_prepare_data(struct mmc_dm365_host *host, struct rt_mmcsd_req *req) { - int timeout; - int fifo_lev; - struct rt_mmcsd_data *data = req->data; + int timeout; + int fifo_lev; + struct rt_mmcsd_data *data = req->data; + + fifo_lev = (rw_threshold == 64) ? MMCFIFOCTL_FIFOLEV : 0; - fifo_lev = (rw_threshold == 64) ? MMCFIFOCTL_FIFOLEV : 0; + host->data = data; + if (data == RT_NULL) + { + host->data_dir = DM365_MMC_DATADIR_NONE; + host->mmcsd_regs->MMCBLEN = 0; + host->mmcsd_regs->MMCNBLK = 0; + return; + } - host->data = data; - if (data == RT_NULL) - { - host->data_dir = DM365_MMC_DATADIR_NONE; - host->mmcsd_regs->MMCBLEN = 0; - host->mmcsd_regs->MMCNBLK = 0; - return; - } + mmc_dbg("%s %s, %d blocks of %d bytes\n", + (data->flags & DATA_STREAM) ? "stream" : "block", + (data->flags & DATA_DIR_WRITE) ? "write" : "read", + data->blks, data->blksize); + mmc_dbg(" DTO %d cycles + %d ns\n", + data->timeout_clks, data->timeout_ns); + timeout = data->timeout_clks + (data->timeout_ns / host->ns_in_one_cycle); + if (timeout > 0xffff) + timeout = 0xffff; - mmc_dbg("%s %s, %d blocks of %d bytes\n", - (data->flags & DATA_STREAM) ? "stream" : "block", - (data->flags & DATA_DIR_WRITE) ? "write" : "read", - data->blks, data->blksize); - mmc_dbg(" DTO %d cycles + %d ns\n", - data->timeout_clks, data->timeout_ns); - timeout = data->timeout_clks + (data->timeout_ns / host->ns_in_one_cycle); - if (timeout > 0xffff) - timeout = 0xffff; + host->mmcsd_regs->MMCTOD = timeout; + host->mmcsd_regs->MMCNBLK = data->blks; + host->mmcsd_regs->MMCBLEN = data->blksize; - host->mmcsd_regs->MMCTOD = timeout; - host->mmcsd_regs->MMCNBLK = data->blks; - host->mmcsd_regs->MMCBLEN = data->blksize; - - /* Configure the FIFO */ - switch (data->flags & DATA_DIR_WRITE) - { - case DATA_DIR_WRITE: - host->data_dir = DM365_MMC_DATADIR_WRITE; - host->mmcsd_regs->MMCFIFOCTL = fifo_lev | MMCFIFOCTL_FIFODIR_WR | MMCFIFOCTL_FIFORST; - host->mmcsd_regs->MMCFIFOCTL = fifo_lev | MMCFIFOCTL_FIFODIR_WR; - break; + /* Configure the FIFO */ + switch (data->flags & DATA_DIR_WRITE) + { + case DATA_DIR_WRITE: + host->data_dir = DM365_MMC_DATADIR_WRITE; + host->mmcsd_regs->MMCFIFOCTL = fifo_lev | MMCFIFOCTL_FIFODIR_WR | MMCFIFOCTL_FIFORST; + host->mmcsd_regs->MMCFIFOCTL = fifo_lev | MMCFIFOCTL_FIFODIR_WR; + break; - default: - host->data_dir = DM365_MMC_DATADIR_READ; - host->mmcsd_regs->MMCFIFOCTL = fifo_lev | MMCFIFOCTL_FIFODIR_RD | MMCFIFOCTL_FIFORST; - host->mmcsd_regs->MMCFIFOCTL = fifo_lev | MMCFIFOCTL_FIFODIR_RD; - break; - } + default: + host->data_dir = DM365_MMC_DATADIR_READ; + host->mmcsd_regs->MMCFIFOCTL = fifo_lev | MMCFIFOCTL_FIFODIR_RD | MMCFIFOCTL_FIFORST; + host->mmcsd_regs->MMCFIFOCTL = fifo_lev | MMCFIFOCTL_FIFODIR_RD; + break; + } - host->buffer = RT_NULL; - host->bytes_left = data->blks * data->blksize; + host->buffer = RT_NULL; + host->bytes_left = data->blks * data->blksize; - /* For now we try to use DMA whenever we won't need partial FIFO - * reads or writes, either for the whole transfer (as tested here) - * or for any individual scatterlist segment (tested when we call - * start_dma_transfer). - * - * While we *could* change that, unusual block sizes are rarely - * used. The occasional fallback to PIO should't hurt. - */ - if ((host->use_dma == RT_TRUE) && (host->bytes_left & (rw_threshold - 1)) == 0 && - mmc_dm365_start_dma_transfer(host, data) == 0) - { - /* zero this to ensure we take no PIO paths */ - host->bytes_left = 0; - } - else - { - /* Revert to CPU Copy */ - host->buffer = (rt_uint8_t*)req->data->buf; - } + /* For now we try to use DMA whenever we won't need partial FIFO + * reads or writes, either for the whole transfer (as tested here) + * or for any individual scatterlist segment (tested when we call + * start_dma_transfer). + * + * While we *could* change that, unusual block sizes are rarely + * used. The occasional fallback to PIO should't hurt. + */ + if ((host->use_dma == RT_TRUE) && (host->bytes_left & (rw_threshold - 1)) == 0 && + mmc_dm365_start_dma_transfer(host, data) == 0) + { + /* zero this to ensure we take no PIO paths */ + host->bytes_left = 0; + } + else + { + /* Revert to CPU Copy */ + host->buffer = (rt_uint8_t*)req->data->buf; + } } /******************************************************************************************************* ** 函数名称: mmc_dm365_request() ** 功能描述: 此函数实现SD request操作 -** -** 输 入: host -> DM365 mmc host 句柄 -** req -> SD request 结构句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** req -> SD request 结构句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_request(struct rt_mmcsd_host *mmc, struct rt_mmcsd_req *req) { - struct mmc_dm365_host *host = mmc_priv(mmc); - unsigned long timeout = rt_tick_get() + 900; - rt_uint32_t mmcst1 = 0; + struct mmc_dm365_host *host = mmc_priv(mmc); + unsigned long timeout = rt_tick_get() + 900; + rt_uint32_t mmcst1 = 0; - /* Card may still be sending BUSY after a previous operation, - * typically some kind of write. If so, we can't proceed yet. - */ - while (rt_tick_get() < timeout) + /* Card may still be sending BUSY after a previous operation, + * typically some kind of write. If so, we can't proceed yet. + */ + while (rt_tick_get() < timeout) { - mmcst1 = host->mmcsd_regs->MMCST1; - if (!(mmcst1 & MMCST1_BUSY)) - break; - } - if (mmcst1 & MMCST1_BUSY) + mmcst1 = host->mmcsd_regs->MMCST1; + if (!(mmcst1 & MMCST1_BUSY)) + break; + } + if (mmcst1 & MMCST1_BUSY) { - mmc_dbg("still BUSY? bad ... \n"); - req->cmd->err = -RT_ETIMEOUT; - mmc_request_done(mmc, req); - return; - } + mmc_dbg("still BUSY? bad ... \n"); + req->cmd->err = -RT_ETIMEOUT; + mmc_request_done(mmc, req); + return; + } - host->do_dma = RT_FALSE; - mmc_dm365_prepare_data(host, req); - mmc_dm365_start_command(host, req->cmd); + host->do_dma = RT_FALSE; + mmc_dm365_prepare_data(host, req); + mmc_dm365_start_command(host, req->cmd); } static void mmc_dm365_enable_sdio_irq(struct rt_mmcsd_host *mmc, rt_int32_t enable) { - struct mmc_dm365_host *host = mmc_priv(mmc); + struct mmc_dm365_host *host = mmc_priv(mmc); - if (enable) - { - if (!(host->mmcsd_regs->SDIOST0 & SDIOST0_DAT1_HI)) - { - host->mmcsd_regs->SDIOIST = SDIOIST_IOINT; - sdio_irq_wakeup(host->mmc); - } - else - { - host->sdio_int = RT_TRUE; - host->mmcsd_regs->SDIOIEN |= SDIOIEN_IOINTEN; - } - } - else - { - host->sdio_int = RT_FALSE; - host->mmcsd_regs->SDIOIEN &= ~SDIOIEN_IOINTEN; - } + if (enable) + { + if (!(host->mmcsd_regs->SDIOST0 & SDIOST0_DAT1_HI)) + { + host->mmcsd_regs->SDIOIST = SDIOIST_IOINT; + sdio_irq_wakeup(host->mmc); + } + else + { + host->sdio_int = RT_TRUE; + host->mmcsd_regs->SDIOIEN |= SDIOIEN_IOINTEN; + } + } + else + { + host->sdio_int = RT_FALSE; + host->mmcsd_regs->SDIOIEN &= ~SDIOIEN_IOINTEN; + } } -static const struct rt_mmcsd_host_ops mmc_dm365_ops = +static const struct rt_mmcsd_host_ops mmc_dm365_ops = { - mmc_dm365_request, - mmc_dm365_set_ios, + mmc_dm365_request, + mmc_dm365_set_ios, RT_NULL, mmc_dm365_enable_sdio_irq }; @@ -1059,409 +1059,409 @@ static const struct rt_mmcsd_host_ops mmc_dm365_ops = /******************************************************************************************************* ** 函数名称: mmc_dm365_reset_ctrl() ** 功能描述: 此函数用于reset mmc控制器 -** -** 输 入: host -> DM365 mmc host 句柄 -** val -> 判断做reset还是enable +** +** 输 入: host -> DM365 mmc host 句柄 +** val -> 判断做reset还是enable ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_reset_ctrl(struct mmc_dm365_host *host, int val) { - rt_uint32_t temp; + rt_uint32_t temp; + + temp = host->mmcsd_regs->MMCCTL; - temp = host->mmcsd_regs->MMCCTL; - - if (val) /* reset */ - temp |= MMCCTL_CMDRST | MMCCTL_DATRST; - else /* enable */ - temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST); + if (val) /* reset */ + temp |= MMCCTL_CMDRST | MMCCTL_DATRST; + else /* enable */ + temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST); - host->mmcsd_regs->MMCCTL = temp; + host->mmcsd_regs->MMCCTL = temp; - delay_us(10); + delay_us(10); } /******************************************************************************************************* ** 函数名称: init_mmcsd_host() ** 功能描述: 此函数用于初始化DM365 MMCSD控制器 -** -** 输 入: host -> DM365 mmc host 句柄 +** +** 输 入: host -> DM365 mmc host 句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void init_mmcsd_host(struct mmc_dm365_host *host) { - mmc_dm365_reset_ctrl(host, 1); + mmc_dm365_reset_ctrl(host, 1); + + host->mmcsd_regs->MMCCLK = 0; + host->mmcsd_regs->MMCCLK = MMCCLK_CLKEN; - host->mmcsd_regs->MMCCLK = 0; - host->mmcsd_regs->MMCCLK = MMCCLK_CLKEN; + host->mmcsd_regs->MMCTOR = 0x1FFF; + host->mmcsd_regs->MMCTOD = 0xFFFF; - host->mmcsd_regs->MMCTOR = 0x1FFF; - host->mmcsd_regs->MMCTOD = 0xFFFF; - - mmc_dm365_reset_ctrl(host, 0); + mmc_dm365_reset_ctrl(host, 0); } /******************************************************************************************************* ** 函数名称: mmc_dm365_cmd_done() ** 功能描述: 结束SD 命令后调用此函数 -** -** 输 入: host -> DM365 mmc host 句柄 -** cmd -> SD 命令结构句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** cmd -> SD 命令结构句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_cmd_done(struct mmc_dm365_host *host, struct rt_mmcsd_cmd *cmd) { - host->cmd = RT_NULL; + host->cmd = RT_NULL; - if (resp_type(cmd) != RESP_NONE) - { - if (resp_type(cmd) == RESP_R2) - { - /* response type 2 */ - cmd->resp[3] = host->mmcsd_regs->MMCRSP01; - cmd->resp[2] = host->mmcsd_regs->MMCRSP23; - cmd->resp[1] = host->mmcsd_regs->MMCRSP45; - cmd->resp[0] = host->mmcsd_regs->MMCRSP67; - } - else - { - /* response types 1, 1b, 3, 4, 5, 6 */ - cmd->resp[0] = host->mmcsd_regs->MMCRSP67; - } - } + if (resp_type(cmd) != RESP_NONE) + { + if (resp_type(cmd) == RESP_R2) + { + /* response type 2 */ + cmd->resp[3] = host->mmcsd_regs->MMCRSP01; + cmd->resp[2] = host->mmcsd_regs->MMCRSP23; + cmd->resp[1] = host->mmcsd_regs->MMCRSP45; + cmd->resp[0] = host->mmcsd_regs->MMCRSP67; + } + else + { + /* response types 1, 1b, 3, 4, 5, 6 */ + cmd->resp[0] = host->mmcsd_regs->MMCRSP67; + } + } - if (host->data == RT_NULL || cmd->err) - { - if (cmd->err == -RT_ETIMEOUT) - cmd->mrq->cmd->retries = 0; - mmc_request_done(host->mmc, cmd->mrq); - host->mmcsd_regs->MMCIM = 0; - } + if (host->data == RT_NULL || cmd->err) + { + if (cmd->err == -RT_ETIMEOUT) + cmd->mrq->cmd->retries = 0; + mmc_request_done(host->mmc, cmd->mrq); + host->mmcsd_regs->MMCIM = 0; + } } /******************************************************************************************************* ** 函数名称: dm365_abort_data() ** 功能描述: 此函数用于终止数据传输 -** -** 输 入: host -> DM365 mmc host 句柄 -** data -> data 结构句柄 +** +** 输 入: host -> DM365 mmc host 句柄 +** data -> data 结构句柄 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void dm365_abort_data(struct mmc_dm365_host *host, struct rt_mmcsd_data *data) { - mmc_dm365_reset_ctrl(host, 1); - mmc_dm365_reset_ctrl(host, 0); + mmc_dm365_reset_ctrl(host, 1); + mmc_dm365_reset_ctrl(host, 0); } static void mmc_dm365_sdio_irq(int irq, void *param) { - struct mmc_dm365_host *host = (struct mmc_dm365_host *)param; - rt_uint32_t status; + struct mmc_dm365_host *host = (struct mmc_dm365_host *)param; + rt_uint32_t status; - status = host->mmcsd_regs->SDIOIST;//readl(host->base + DAVINCI_SDIOIST); - if (status & SDIOIST_IOINT) { - mmc_dbg("SDIO interrupt status %x\n", status); - //writel(status | SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); - host->mmcsd_regs->SDIOIST = status | SDIOIST_IOINT; - sdio_irq_wakeup(host->mmc); - } + status = host->mmcsd_regs->SDIOIST;//readl(host->base + DAVINCI_SDIOIST); + if (status & SDIOIST_IOINT) { + mmc_dbg("SDIO interrupt status %x\n", status); + //writel(status | SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); + host->mmcsd_regs->SDIOIST = status | SDIOIST_IOINT; + sdio_irq_wakeup(host->mmc); + } } /******************************************************************************************************* ** 函数名称: mmc_dm365_irq() ** 功能描述: MMCSD的中断处理程序 -** -** 输 入: irq ->中断向量号 +** +** 输 入: irq ->中断向量号 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void mmc_dm365_irq(int irq, void *param) { - struct mmc_dm365_host *host = (struct mmc_dm365_host *)param; - rt_uint32_t status, qstatus; - int end_command = 0; - int end_transfer = 0; - struct rt_mmcsd_data *data = host->data; + struct mmc_dm365_host *host = (struct mmc_dm365_host *)param; + rt_uint32_t status, qstatus; + int end_command = 0; + int end_transfer = 0; + struct rt_mmcsd_data *data = host->data; + + if (host->cmd == RT_NULL && host->data == RT_NULL) + { + status = host->mmcsd_regs->MMCST0; + mmc_dbg("Spurious interrupt 0x%04x\n", status); + /* Disable the interrupt from mmcsd */ + host->mmcsd_regs->MMCIM = 0; + return; + } - if (host->cmd == RT_NULL && host->data == RT_NULL) - { - status = host->mmcsd_regs->MMCST0; - mmc_dbg("Spurious interrupt 0x%04x\n", status); - /* Disable the interrupt from mmcsd */ - host->mmcsd_regs->MMCIM = 0; - return; - } + status = host->mmcsd_regs->MMCST0; + qstatus = status; - status = host->mmcsd_regs->MMCST0; - qstatus = status; - - /* handle FIFO first when using PIO for data. - * bytes_left will decrease to zero as I/O progress and status will - * read zero over iteration because this controller status - * register(MMCST0) reports any status only once and it is cleared - * by read. So, it is not unbouned loop even in the case of - * non-dma. - */ - while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) - { - dm365_fifo_data_trans(host, rw_threshold); - status = host->mmcsd_regs->MMCST0; - if (!status) - break; - qstatus |= status; - } + /* handle FIFO first when using PIO for data. + * bytes_left will decrease to zero as I/O progress and status will + * read zero over iteration because this controller status + * register(MMCST0) reports any status only once and it is cleared + * by read. So, it is not unbouned loop even in the case of + * non-dma. + */ + while (host->bytes_left && (status & (MMCST0_DXRDY | MMCST0_DRRDY))) + { + dm365_fifo_data_trans(host, rw_threshold); + status = host->mmcsd_regs->MMCST0; + if (!status) + break; + qstatus |= status; + } - if (qstatus & MMCST0_DATDNE) - { - /* All blocks sent/received, and CRC checks passed */ - if (data != RT_NULL) - { - if ((host->do_dma == RT_FALSE) && (host->bytes_left > 0)) - { - /* if datasize < rw_threshold - * no RX ints are generated - */ - rt_kprintf("to do! host->bytes_left=0x%x\n", host->bytes_left); - dm365_fifo_data_trans(host, host->bytes_left); - } - end_transfer = 1; - data->bytes_xfered = data->blks* data->blksize; - } - else - { - mmc_dbg("DATDNE with no host->data\n"); - } - } + if (qstatus & MMCST0_DATDNE) + { + /* All blocks sent/received, and CRC checks passed */ + if (data != RT_NULL) + { + if ((host->do_dma == RT_FALSE) && (host->bytes_left > 0)) + { + /* if datasize < rw_threshold + * no RX ints are generated + */ + rt_kprintf("to do! host->bytes_left=0x%x\n", host->bytes_left); + dm365_fifo_data_trans(host, host->bytes_left); + } + end_transfer = 1; + data->bytes_xfered = data->blks* data->blksize; + } + else + { + mmc_dbg("DATDNE with no host->data\n"); + } + } - if (qstatus & MMCST0_TOUTRD) - { - /* Read data timeout */ - data->err = -RT_ETIMEOUT; - end_transfer = 1; + if (qstatus & MMCST0_TOUTRD) + { + /* Read data timeout */ + data->err = -RT_ETIMEOUT; + end_transfer = 1; - mmc_dbg("read data timeout, status %x\n", qstatus); - rt_kprintf("read data timeout, status %x\n", qstatus); + mmc_dbg("read data timeout, status %x\n", qstatus); + rt_kprintf("read data timeout, status %x\n", qstatus); - dm365_abort_data(host, data); - } + dm365_abort_data(host, data); + } - if (qstatus & (MMCST0_CRCWR | MMCST0_CRCRD)) - { - /* Data CRC error */ - data->err = -RT_ERROR; - end_transfer = 1; + if (qstatus & (MMCST0_CRCWR | MMCST0_CRCRD)) + { + /* Data CRC error */ + data->err = -RT_ERROR; + end_transfer = 1; - /* NOTE: this controller uses CRCWR to report both CRC - * errors and timeouts (on writes). MMCDRSP values are - * only weakly documented, but 0x9f was clearly a timeout - * case and the two three-bit patterns in various SD specs - * (101, 010) aren't part of it ... - */ - if (qstatus & MMCST0_CRCWR) - { - rt_uint32_t temp = host->mmcsd_regs->MMCDRSP; + /* NOTE: this controller uses CRCWR to report both CRC + * errors and timeouts (on writes). MMCDRSP values are + * only weakly documented, but 0x9f was clearly a timeout + * case and the two three-bit patterns in various SD specs + * (101, 010) aren't part of it ... + */ + if (qstatus & MMCST0_CRCWR) + { + rt_uint32_t temp = host->mmcsd_regs->MMCDRSP; - if (temp == 0x9f) - data->err = -RT_ETIMEOUT; - } - mmc_dbg("data %s %s error\n", (qstatus & MMCST0_CRCWR) ? "write" : "read", (data->err == -110) ? "timeout" : "CRC"); + if (temp == 0x9f) + data->err = -RT_ETIMEOUT; + } + mmc_dbg("data %s %s error\n", (qstatus & MMCST0_CRCWR) ? "write" : "read", (data->err == -110) ? "timeout" : "CRC"); - rt_kprintf("data %s %s error\n", (qstatus & MMCST0_CRCWR) ? "write" : "read", (data->err == -110) ? "timeout" : "CRC"); + rt_kprintf("data %s %s error\n", (qstatus & MMCST0_CRCWR) ? "write" : "read", (data->err == -110) ? "timeout" : "CRC"); - dm365_abort_data(host, data); - } + dm365_abort_data(host, data); + } - if (qstatus & MMCST0_TOUTRS) - { - /* Command timeout */ - if (host->cmd) - { - mmc_dbg("CMD%d timeout, status %x\n", host->cmd->cmd_code, qstatus); - host->cmd->err = -RT_ETIMEOUT; - if (data) - { - end_transfer = 1; - dm365_abort_data(host, data); - } - else - end_command = 1; - } - } + if (qstatus & MMCST0_TOUTRS) + { + /* Command timeout */ + if (host->cmd) + { + mmc_dbg("CMD%d timeout, status %x\n", host->cmd->cmd_code, qstatus); + host->cmd->err = -RT_ETIMEOUT; + if (data) + { + end_transfer = 1; + dm365_abort_data(host, data); + } + else + end_command = 1; + } + } - if (qstatus & MMCST0_CRCRS) - { - /* Command CRC error */ - mmc_dbg("Command CRC error\n"); - if (host->cmd) - { - host->cmd->err = -RT_ERROR; - end_command = 1; - } - } + if (qstatus & MMCST0_CRCRS) + { + /* Command CRC error */ + mmc_dbg("Command CRC error\n"); + if (host->cmd) + { + host->cmd->err = -RT_ERROR; + end_command = 1; + } + } - if (qstatus & MMCST0_RSPDNE) - { - /* End of command phase */ - end_command = (int) host->cmd; - } + if (qstatus & MMCST0_RSPDNE) + { + /* End of command phase */ + end_command = (int) host->cmd; + } - if (end_command) - mmc_dm365_cmd_done(host, host->cmd); - if (end_transfer) - mmc_dm365_xfer_done(host, data); + if (end_command) + mmc_dm365_cmd_done(host, host->cmd); + if (end_transfer) + mmc_dm365_xfer_done(host, data); - return; + return; } #if 0 /******************************************************************************************************* ** 函数名称: rt_hw_edma_init() ** 功能描述: 此函数用于初始化EDMA3 -** +** ** 输 入: 无 ** ** 输 出: 无 -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ static void rt_hw_edma_init(void) { - psc_transition(PSC0, DOMAIN0, LPSC_TPCC, PSC_ENABLE); - psc_transition(PSC0, DOMAIN0, LPSC_TPTC0, PSC_ENABLE); + psc_transition(PSC0, DOMAIN0, LPSC_TPCC, PSC_ENABLE); + psc_transition(PSC0, DOMAIN0, LPSC_TPTC0, PSC_ENABLE); - /* Initialization of EDMA3 */ + /* Initialization of EDMA3 */ edma3_init(EDMA0CC0_REG_BASE, EVT_QUEUE_NUM); - + /* Register EDMA3 Interrupts */ -// ConfigureAINTCIntEDMA3(); +// ConfigureAINTCIntEDMA3(); } #endif /******************************************************************************************************* ** 函数名称: rt_hw_mmcsd_init() ** 功能描述: 此函数用于初始化MMC驱动模块 -** +** ** 输 入: 无 ** ** 输 出: 如果初始化成功,返回0;如果初始化失败,返回-RT_ENOMEM -** -** 全局变量: +** +** 全局变量: ** 调用模块: 无 ** ********************************************************************************************************/ int rt_hw_mmcsd_init(void) { - struct clk *clk; - struct mmc_dm365_host *dm365_host; - struct rt_mmcsd_host *mmc = RT_NULL; + struct clk *clk; + struct mmc_dm365_host *dm365_host; + struct rt_mmcsd_host *mmc = RT_NULL; - mmc = mmcsd_alloc_host(); - if (!mmc) - { - mmc_dbg("alloc mmc failed\n"); - return -RT_ERROR; - } + mmc = mmcsd_alloc_host(); + if (!mmc) + { + mmc_dbg("alloc mmc failed\n"); + return -RT_ERROR; + } - dm365_host = rt_malloc(sizeof(struct mmc_dm365_host)); - if (!dm365_host) - { - mmc_dbg("alloc mci failed\n"); - goto err; - } + dm365_host = rt_malloc(sizeof(struct mmc_dm365_host)); + if (!dm365_host) + { + mmc_dbg("alloc mci failed\n"); + goto err; + } - rt_memset(dm365_host, 0, sizeof(struct mmc_dm365_host)); + rt_memset(dm365_host, 0, sizeof(struct mmc_dm365_host)); #ifdef RT_USING_MMCSD0 - //psc_transition(PSC0, DOMAIN0, LPSC_MMCSD0, PSC_ENABLE); - //pinmux_config(PINMUX_MMCSD0_REG, PINMUX_MMCSD0_MASK, PINMUX_MMCSD0_VAL); - psc_change_state(DAVINCI_DM365_LPSC_MMC_SD0, PSC_ENABLE); - dm365_host->mmcsd_regs = (mmcsd_regs_t *)DM365_MMC_SD0_BASE; + //psc_transition(PSC0, DOMAIN0, LPSC_MMCSD0, PSC_ENABLE); + //pinmux_config(PINMUX_MMCSD0_REG, PINMUX_MMCSD0_MASK, PINMUX_MMCSD0_VAL); + psc_change_state(DAVINCI_DM365_LPSC_MMC_SD0, PSC_ENABLE); + dm365_host->mmcsd_regs = (mmcsd_regs_t *)DM365_MMC_SD0_BASE; #else #ifdef RT_USING_MMCSD1 - psc_transition(PSC1, DOMAIN0, LPSC_MMCSD1, PSC_ENABLE); - pinmux_config(PINMUX_MMCSD1_REG, PINMUX_MMCSD1_MASK, PINMUX_MMCSD1_VAL); - dm365_host->mmcsd_regs = MMCSD1; + psc_transition(PSC1, DOMAIN0, LPSC_MMCSD1, PSC_ENABLE); + pinmux_config(PINMUX_MMCSD1_REG, PINMUX_MMCSD1_MASK, PINMUX_MMCSD1_VAL); + dm365_host->mmcsd_regs = MMCSD1; #endif #endif - //rt_hw_edma_init(); + //rt_hw_edma_init(); - clk = clk_get("MMCSDCLK0"); - dm365_host->mmc_input_clk = clk_get_rate(clk); - dm365_host->rxdma = DM365_DMA_MMC0RXEVT; - dm365_host->txdma = DM365_DMA_MMC0TXEVT; - dm365_host->use_dma = use_dma; - if ((dm365_host->use_dma == RT_TRUE)&& acquire_dma_channels(dm365_host) != 0) - { - dm365_host->use_dma = RT_FALSE; - } - else - { - dm365_host->dma_buffer = (rt_uint8_t*)rt_malloc_align(64*1024, 32); - if (dm365_host->dma_buffer == RT_NULL) - dm365_host->use_dma = RT_FALSE; - } + clk = clk_get("MMCSDCLK0"); + dm365_host->mmc_input_clk = clk_get_rate(clk); + dm365_host->rxdma = DM365_DMA_MMC0RXEVT; + dm365_host->txdma = DM365_DMA_MMC0TXEVT; + dm365_host->use_dma = use_dma; + if ((dm365_host->use_dma == RT_TRUE)&& acquire_dma_channels(dm365_host) != 0) + { + dm365_host->use_dma = RT_FALSE; + } + else + { + dm365_host->dma_buffer = (rt_uint8_t*)rt_malloc_align(64*1024, 32); + if (dm365_host->dma_buffer == RT_NULL) + dm365_host->use_dma = RT_FALSE; + } - mmc->ops = &mmc_dm365_ops; - mmc->freq_min = 312500; - mmc->freq_max = 25000000; - mmc->valid_ocr = VDD_32_33 | VDD_33_34; - mmc->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE; - mmc->flags |= MMCSD_SUP_SDIO_IRQ; + mmc->ops = &mmc_dm365_ops; + mmc->freq_min = 312500; + mmc->freq_max = 25000000; + mmc->valid_ocr = VDD_32_33 | VDD_33_34; + mmc->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE; + mmc->flags |= MMCSD_SUP_SDIO_IRQ; - dm365_host->mmc = mmc; - mmc->private_data = dm365_host; + dm365_host->mmc = mmc; + mmc->private_data = dm365_host; - /* install interrupt */ + /* install interrupt */ #ifdef RT_USING_MMCSD0 - rt_hw_interrupt_install(IRQ_DM3XX_MMCINT0, mmc_dm365_irq, - (void *)dm365_host, "MMC0"); - rt_hw_interrupt_umask(IRQ_DM3XX_MMCINT0); - rt_hw_interrupt_install(IRQ_DM3XX_SDIOINT0, mmc_dm365_sdio_irq, - (void *)dm365_host, "SDIO0"); - rt_hw_interrupt_umask(IRQ_DM3XX_SDIOINT0); + rt_hw_interrupt_install(IRQ_DM3XX_MMCINT0, mmc_dm365_irq, + (void *)dm365_host, "MMC0"); + rt_hw_interrupt_umask(IRQ_DM3XX_MMCINT0); + rt_hw_interrupt_install(IRQ_DM3XX_SDIOINT0, mmc_dm365_sdio_irq, + (void *)dm365_host, "SDIO0"); + rt_hw_interrupt_umask(IRQ_DM3XX_SDIOINT0); #endif #ifdef RT_USING_MMCSD1 - rt_hw_interrupt_install(MMCSD_INT1, mmc_dm365_irq, - (void *)dm365_host, "MMC1"); - rt_hw_interrupt_umask(MMCSD_INT1); + rt_hw_interrupt_install(MMCSD_INT1, mmc_dm365_irq, + (void *)dm365_host, "MMC1"); + rt_hw_interrupt_umask(MMCSD_INT1); #endif - init_mmcsd_host(dm365_host); + init_mmcsd_host(dm365_host); - mmcsd_change(mmc); + mmcsd_change(mmc); - return 0; + return 0; err: - mmcsd_free_host(mmc); + mmcsd_free_host(mmc); - return -RT_ENOMEM; + return -RT_ENOMEM; } INIT_DEVICE_EXPORT(rt_hw_mmcsd_init); |
