#include #include "bk_arm_arch.h" #include "bk_uart.h" #include "sdma_pub.h" #include "sdma.h" #include #include #if CONFIG_SDIO || CONFIG_SDIO_TRANS TX_FUNC intr_tx_func = 0; RX_FUNC intr_rx_func = 0; CMD_FUNC intr_cmd_func = 0; UINT8 *cmd_buf = 0; volatile UINT32 cmd_data_dir = SDMA_DIR_IDLE; void sdma_init(void) { UINT32 reg; #if CONFIG_REAL_SDIO bk_int_isr_register(INT_SRC_SDIO_DMA, sdma_isr, NULL); #endif reg = REG_READ(REG_SDMA_INTR_STATUS); REG_WRITE(REG_SDMA_INTR_STATUS, reg); sdma_clr_tx_valid(); } void sdma_open(void) { UINT32 reg; reg = SDMA_CONFIG_INTR_EN_TX | SDMA_CONFIG_INTR_EN_RX | SDMA_CONFIG_INTR_EN_CMD; REG_WRITE(REG_SDMA_CONFIG, reg); } void sdma_uninit(void) { } void sdma_close(void) { UINT32 reg; reg = REG_READ(REG_SDMA_CONFIG); reg &= ~(SDMA_CONFIG_INTR_EN_TX | SDMA_CONFIG_INTR_EN_RX | SDMA_CONFIG_INTR_EN_CMD); REG_WRITE(REG_SDMA_CONFIG, reg); } #ifdef SDMA_INTERACT_WITH_HOST UINT32 sdma_get_blk_len(void) { UINT32 reg; UINT32 power; UINT32 blk_len; /* Rd Only */ reg = REG_READ(REG_SDMA_INTERACTIVE_HOST); power = (reg >> INTERACTIVE_BLK_LEN_POSI) & INTERACTIVE_BLK_LEN_MASK; blk_len = 2 << (power + 8); return blk_len; } void sdma_set_tx_valid(void) { UINT32 reg; reg = REG_READ(REG_SDMA_INTERACTIVE_HOST); reg |= INTERACTIVE_RX_VALID_BIT; REG_WRITE(REG_SDMA_INTERACTIVE_HOST, reg); } void sdma_clr_tx_valid(void) { UINT32 reg; reg = REG_READ(REG_SDMA_INTERACTIVE_HOST); reg &= ~INTERACTIVE_RX_VALID_BIT; REG_WRITE(REG_SDMA_INTERACTIVE_HOST, reg); } void sdma_set_tx_dat_count(UINT32 val) { UINT32 reg; reg = REG_READ(REG_SDMA_INTERACTIVE_HOST); reg &= ~(INTERACTIVE_RX_COUNT_MASK << INTERACTIVE_RX_COUNT_POSI); reg |= (val & INTERACTIVE_RX_COUNT_MASK) << INTERACTIVE_RX_COUNT_POSI; REG_WRITE(REG_SDMA_INTERACTIVE_HOST, reg); } #endif // SDMA_INTERACT_WITH_HOST void sdma_register_handler(TX_FUNC tx_callback, RX_FUNC rx_callback, CMD_FUNC cmd_callback) { if (tx_callback) intr_tx_func = tx_callback; if (rx_callback) intr_rx_func = rx_callback; if (cmd_callback) intr_cmd_func = cmd_callback; return; } UINT32 sdma_dma_start(UINT8 *buf, UINT32 len) { UINT32 reg; UINT32 addr; BK_ASSERT(len); BK_ASSERT(buf); addr = (UINT32)buf; REG_WRITE(REG_SDMA_ADDR, addr); reg = REG_READ(REG_SDMA_CONFIG); reg |= SDMA_CONFIG_ADDR_READY; REG_WRITE(REG_SDMA_CONFIG, reg); return 0; } UINT32 sdma_start_tx(UINT8 *buf, UINT32 len) { cmd_data_dir = SDMA_DIR_TX; return sdma_dma_start(buf, len); } UINT32 sdma_start_rx(UINT8 *buf, UINT32 len) { cmd_data_dir = SDMA_DIR_RX; return sdma_dma_start(buf, len); } void sdma_fake_stop_dma(void) { cmd_data_dir = SDMA_DIR_IDLE; } UINT32 sdma_start_cmd(UINT8 *cmd, UINT32 len) { UINT32 reg; if (len != CMD_BUF_MAX_LEN) return SDMA_FAILURE; cmd_buf = cmd; /*startup dma*/ reg = REG_READ(REG_SDMA_CONFIG); if (reg & SDMA_CONFIG_ADDR_READY) return SDMA_BUSY; reg |= SDMA_CONFIG_DMA_EN; REG_WRITE(REG_SDMA_CONFIG, reg); return 0; } void sdma_rd_cmd_content(void *buf, UINT32 len) { UINT8 *src; if (len > CMD_BUF_MAX_LEN) { warning_prf("cmd_len_exception:%d\r\n", len); len = CMD_BUF_MAX_LEN; } src = (UINT8 *)REG_SDMA_CMD_BA; os_memcpy(buf, src, len); return; } /* Target -> Host */ void sdma_tx_isr_handler(UINT32 irq_status) { if (irq_status & SDMA_INTR_TX_DATA_BIT) { SDMA_PRT("sdma_tx\r\n"); REG_WRITE(REG_SDMA_INTR_STATUS, SDMA_INTR_TX_DATA_BIT); cmd_data_dir = SDMA_DIR_IDLE; if (intr_tx_func) (*intr_tx_func)(); } } /* Host -> Target */ void sdma_rx_isr_handler(UINT32 irq_status) { UINT32 rx_count; if (irq_status & SDMA_INTR_RX_DATA_BIT) { SDMA_PRT("sdma_rx\r\n"); REG_WRITE(REG_SDMA_INTR_STATUS, SDMA_INTR_RX_DATA_BIT); cmd_data_dir = SDMA_DIR_IDLE; if (intr_rx_func) { rx_count = (REG_READ(REG_SDMA_COUNT)) & SDMA_COUNT_MASK; (*intr_rx_func)(rx_count); } } } void sdma_cmd_isr_handler(UINT32 irq_status) { UINT32 rx_count; if (irq_status & SDMA_INTR_CMD_BIT) { SDMA_PRT("sdma_cmd\r\n"); if (intr_cmd_func) { rx_count = (REG_READ(REG_SDMA_COUNT)) & SDMA_COUNT_MASK; sdma_rd_cmd_content(cmd_buf, rx_count); (*intr_cmd_func)(cmd_buf, rx_count); } REG_WRITE(REG_SDMA_INTR_STATUS, SDMA_INTR_CMD_BIT); } } void sdma_isr(void) { UINT32 irq_sta; /*0, get isr status*/ irq_sta = REG_READ(REG_SDMA_INTR_STATUS); #if 0 BK_LOG_RAW("%c%c%c\n", irq_sta & SDMA_INTR_CMD_BIT ? 'C' : '-', irq_sta & SDMA_INTR_RX_DATA_BIT ? 'R' : '-', irq_sta & SDMA_INTR_TX_DATA_BIT ? 'T' : '-'); #endif #if 0 // DON'T DELETE ME /*1, handle isr branch*/ if (SDMA_DIR_TX == cmd_data_dir) { sdma_tx_isr_handler(irq_sta); sdma_cmd_isr_handler(irq_sta); sdma_rx_isr_handler(irq_sta); } else if (SDMA_DIR_RX == cmd_data_dir) { sdma_rx_isr_handler(irq_sta); sdma_cmd_isr_handler(irq_sta); sdma_tx_isr_handler(irq_sta); } else { sdma_cmd_isr_handler(irq_sta); sdma_rx_isr_handler(irq_sta); sdma_tx_isr_handler(irq_sta); } #else sdma_rx_isr_handler(irq_sta); sdma_tx_isr_handler(irq_sta); /* handle cmd last */ sdma_cmd_isr_handler(irq_sta); #endif if (!((irq_sta & SDMA_INTR_CMD_BIT) || (irq_sta & SDMA_INTR_RX_DATA_BIT) || (irq_sta & SDMA_INTR_TX_DATA_BIT))) warning_prf("sdma:contrary to expectation:%x\r\n", irq_sta); return; } #endif // EOF