287 lines
5.3 KiB
C
Raw Normal View History

2025-10-10 16:07:00 +08:00
#include <common/bk_include.h>
#include "bk_arm_arch.h"
#include "bk_uart.h"
#include "sdma_pub.h"
#include "sdma.h"
#include <os/mem.h>
#include <driver/int.h>
#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