summaryrefslogtreecommitdiff
path: root/bsp/dm365/drivers/mmcsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsp/dm365/drivers/mmcsd.c')
-rw-r--r--bsp/dm365/drivers/mmcsd.c1938
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, &paramSet);
+ 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, &paramSet);
+
+ 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);