Files
6CAR/drivers/include/sdrv_dma.h
2026-04-18 09:16:58 +08:00

945 lines
30 KiB
C

/**
* @file sdrv_dma.h
* @brief SemiDrive DMA driver header file.
*
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#ifndef __SDRV_DMA_H__
#define __SDRV_DMA_H__
#include <part.h>
#include "common.h"
#include "../source/dma/sdrv_dma_regdef.h"
#include "compiler.h"
#include "regs_base.h"
#include "sdrv_common.h"
#define SDRV_DMA_LP2_TT(n) ((((n)-1) << 4) & 0xfffff0)
#define SDRV_DMA_LP2_LPSIZE(n) ((__builtin_ffs(n) - 1) & 0xf)
/* bit4 ~ bit23 */
#define SDRV_DMA_LP2_LPSIZE_MAX (0x000FFFFF)
/* bit12 ~ bit23 */
#define SDRV_DMA_LP1_LP_COUNT_MAX (0X00000FFF)
/* bit0 ~ bit11 */
#define SDRV_DMA_LP1_LPSIZE_MAX (0X00000FFF)
/* bit0 ~ bit */
#define SDRV_DMA_LP0_LPSIZE_MAX (0x00FFFFFF)
#define SDRV_DMA_MAD_CRC_REGISTERS (7)
/**
* @brief DMA status return code
*/
enum {
/* dma channel id is invalid. */
SDRV_DMA_INVALID_CHANNEL_ID = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_DMA, 0),
/* dma channel config unsupport*/
SDRV_DMA_UNSUPPORT_CONFIG = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_DMA, 1),
/* dma channel invalid muxid*/
SDRV_DMA_INVALID_MUXID = SDRV_ERROR_STATUS(SDRV_STATUS_GROUP_DMA, 2),
};
/**
* @brief DMA Channel ID.
*/
typedef enum {
SDRV_DMA_CHANNEL_INVALID = -1,
SDRV_DMA_CHANNEL_0 = 0,
SDRV_DMA_CHANNEL_1,
SDRV_DMA_CHANNEL_2,
SDRV_DMA_CHANNEL_3,
SDRV_DMA_CHANNEL_4,
SDRV_DMA_CHANNEL_5,
SDRV_DMA_CHANNEL_6,
SDRV_DMA_CHANNEL_7,
SDRV_DMA_CHANNEL_8,
SDRV_DMA_CHANNEL_9,
SDRV_DMA_CHANNEL_10,
SDRV_DMA_CHANNEL_11,
SDRV_DMA_CHANNEL_12,
SDRV_DMA_CHANNEL_13,
SDRV_DMA_CHANNEL_14,
SDRV_DMA_CHANNEL_15,
SDRV_DMA_CHANNEL_16,
SDRV_DMA_CHANNEL_17,
SDRV_DMA_CHANNEL_18,
SDRV_DMA_CHANNEL_19,
SDRV_DMA_CHANNEL_20,
SDRV_DMA_CHANNEL_21,
SDRV_DMA_CHANNEL_22,
SDRV_DMA_CHANNEL_23,
} sdrv_dma_channel_id_e;
/**
* @brief DMA channel transfer mode.
*/
typedef enum {
/**< Single mode. */
SDRV_DMA_TRANSFER_MODE_SINGLE = 0,
/**< Continuous mode. */
SDRV_DMA_TRANSFER_MODE_CONTINUOUS,
/**< Link list mode. */
SDRV_DMA_TRANSFER_MODE_LINKLIST,
/**< Channel link mode. */
SDRV_DMA_TRANSFER_MODE_CHAN_LINK,
SDRV_DMA_TRANSFER_MODE_NOT_DEFINED,
} sdrv_dma_xfer_mode_e;
/**
* @brief DMA channel transfer types.
*/
typedef enum {
SDRV_DMA_DIR_MEM2MEM = 0, /**< memory to memory */
SDRV_DMA_DIR_MEM2DEV, /**< memory to device */
SDRV_DMA_DIR_DEV2MEM, /**< device to memory */
SDRV_DMA_DIR_DEV2DEV, /**< device to device */
SDRV_DMA_DIR_REG2MEM, /**< register to memory */
SDRV_DMA_DIR_REG2DEV, /**< register to device */
SDRV_DMA_DIR_MEM2REG, /**< memory to register */
SDRV_DMA_DIR_DEV2REG, /**< device to register */
SDRV_DMA_DIR_NOT_DEFINED,
} sdrv_dma_xfer_type_e;
/**
* @brief DMA channel transfer address increase mode.
*/
typedef enum {
/**< Automatically increase DMA source or target address after each
* transaction, usually for memory buffers.
*/
SDRV_DMA_ADDR_INC = 0,
/**< Do not increase DMA source or target address after each
* transaction, usually for device registers.
*/
SDRV_DMA_ADDR_NO_INC,
} sdrv_dma_addr_inc_e;
/**
* @brief DMA channel data width for each transaction.
*
* This is actually the burst size, i.e., AXI AWSIZE and ARSIZE, for
* DMA transactions. For memory to memory transactions, use 8 bytes
* width to get better throughput. However for peripheral transactions,
* you should set bus width according to hardware register data width.
*/
typedef enum {
SDRV_DMA_BUSWIDTH_1_BYTE = 1, /**< 1 byte per transaction */
SDRV_DMA_BUSWIDTH_2_BYTES = 2, /**< 2 bytes per transaction */
SDRV_DMA_BUSWIDTH_4_BYTES = 4, /**< 4 bytes per transaction */
SDRV_DMA_BUSWIDTH_8_BYTES = 8, /**< 8 bytes per transaction */
} sdrv_dma_bus_width_e;
/**
* @brief DMA channel burst length for each transaction.
*
* This is actually the burst length, i.e. AXI AWLEN and ARLEN,for
* DMA burst transactions. for peripheral transactions,you should
* set burst length according to peripheral FIFO LEVEL.
*/
typedef enum {
SDRV_DMA_BURST_LEN_1 = 0, /**< 1 x bus_width per transaction */
SDRV_DMA_BURST_LEN_2, /**< 2 x bus_width per transaction */
SDRV_DMA_BURST_LEN_3, /**< 3 x bus_width per transaction */
SDRV_DMA_BURST_LEN_4, /**< 4 x bus_width per transaction */
SDRV_DMA_BURST_LEN_5, /**< 5 x bus_width per transaction */
SDRV_DMA_BURST_LEN_6, /**< 6 x bus_width per transaction */
SDRV_DMA_BURST_LEN_7, /**< 7 x bus_width per transaction */
SDRV_DMA_BURST_LEN_8, /**< 8 x bus_width per transaction */
SDRV_DMA_BURST_LEN_9, /**< 9 x bus_width per transaction */
SDRV_DMA_BURST_LEN_10, /**< 10 x bus_width per transaction */
SDRV_DMA_BURST_LEN_11, /**< 11 x bus_width per transaction */
SDRV_DMA_BURST_LEN_12, /**< 12 x bus_width per transaction */
SDRV_DMA_BURST_LEN_13, /**< 13 x bus_width per transaction */
SDRV_DMA_BURST_LEN_14, /**< 14 x bus_width per transaction */
SDRV_DMA_BURST_LEN_15, /**< 15 x bus_width per transaction */
SDRV_DMA_BURST_LEN_16, /**< 16 x bus_width per transaction */
SDRV_DMA_BURST_LEN_UNDEFINED,
} sdrv_dma_burst_len_e;
/**
* @brief The master port used by DMA source and target ports.
*
* The DMA controller as a bus master, has both AXI64 port (for memory access)
* and AHB32 master port (for device register access). You can configure DMA
* channels to use different ports for different source and target addresses.
*/
typedef enum {
/**< The AXI64 port, used when the source or target buffer is in
* normal memory (IRAM, SDRAM).
*/
SDRV_DMA_PORT_AXI64 = 0,
/**< The AHB32 port, used when the source or target buffer is
* peripheral register.
*/
SDRV_DMA_PORT_AHB32,
SDRV_DMA_PROT_NOT_DEFINED,
} sdrv_dma_port_sel_e;
/**
* @brief The buffer mode used by different application scenarios.
*
* MAD (Memory access description) - one transaction configuration include
* source address, target address,transfer mode,transfer length,link
* address,etc..
*
* Buffer mode is related to transfer mode and loop mode (For details see
* sdrv_dma_loop_mode_e), when Single Mode selected,buffer mode should be set to
* SINGLE_BUFFER or 2D_BUFFER. when Continuous Mode selected,buffer mode should
* be set to DOUBLE_BUFFER or CIRCULAR_BUFFER.
*/
typedef enum {
/**< single buffer should be used with Single Mode.
* When the entire length data is transferred, DMA is terminated.
*/
SDRV_DMA_SINGLE_BUFFER = 0,
/**< double buffer should be used with Continuous Mode.
* DMA need two memory areas (IRAM, SDRAM), one memory address is filled in
* source address of MAD and the another is filled in link address of MAD.
* When one memory area is transferred,the another continues to be
* transferred.
*
* Set STATUS_ABORT or STATUS_STOP if you want to terminate DMA transfer.
*/
SDRV_DMA_DOUBLE_BUFFER,
/**< circular buffer should be used with Continuous Mode.
* When the entire length data is transferred, DMA will continue to transfer
* from source address of MAD.
*
* Set STATUS_ABORT or STATUS_STOP if you want to terminate DMA transfer.
*/
SDRV_DMA_CIRCULAR_BUFFER,
/**< 2d buffer is similar to single buffer.
* The difference is that the entire length data can be transmitted at one
* handshake request regardless of LOOP_MODE_x. (For details see
* sdrv_dma_loop_mode_e)
*/
SDRV_DMA_2D_BUFFER,
SDRV_DMA_BUFFER_NOT_DEFINED,
} sdrv_dma_buffer_mode_e;
/**
* @brief Hardware control after MAD completed just for LOOP_MODE_1.
*
* When one transaction is completed according to MAD, DMA will trigger
* different control.
*/
typedef enum {
/**< DMA will be stopped and trigger interrupt when MAD done. */
SDRV_DMA_SWT_EVT_CTL_STOP_WTH_INT = 0,
/**< DMA will be halted and trigger interrupt when MAD done. If you need to
* continue to use it, you need to configure the resume register. */
SDRV_DMA_SWT_EVT_CTL_SUSPEND_WTH_INT,
/**< DMA will be continued and trigger interrupt when MAD done. Such as
linklist mode. */
SDRV_DMA_SWT_EVT_CTL_CONTINUE_WTH_INT,
/**< DMA will be continued and not trigger interrupt when MAD done. Such as
linklist mode. */
SDRV_DMA_SWT_EVT_CTL_CONTINUE_WTHOUT_INT,
SDRV_DMA_SWT_EVT_CTL_UNDEFINED,
} sdrv_dma_switch_event_ctrl_e;
/**
* @brief DMA channel transfer triggered by which mode.
*
* Select appropriate trigger mode according to transfer type and
* transfer mode. Hardware trigger actually for peripheral transactions,
* Software trigger actually for memory transactions,Gtimer trigger
* actually use DMA internal timer for period transactions, Internal event
* trigger actually for linklist transactions.
*/
typedef enum {
SDRV_DMA_TRIGGER_BY_HARDWARE = 0, /**< for peripheral transaction */
SDRV_DMA_TRIGGER_BY_SOFTWARE, /**< for memory transaction */
SDRV_DMA_TRIGGER_BY_GTIMER, /**< for period transaction */
SDRV_DMA_TRIGGER_BY_INTERNAL_EVENT, /**< for linklist transaction */
SDRV_DMA_TRIGGER_MODE_NOT_DEFINED,
} sdrv_dma_trigger_mode_e;
/**
* @brief DMA channel transfer data mode in one handshake.
*
* LOOP_MODE_0: when one handshake request, DMA transfers the entire length data
* then terminated according to MAD.
* LOOP_MODE_1: DMA transfers the specified length (burst length x bus_width)
* data through one handshake request. LOOP_MODE_2: DMA transfers the specified
* length (power of 2) data through one handshake request.
*/
typedef enum {
SDRV_DMA_LOOP_MODE_0 = 0, /**< entire length data transaction */
SDRV_DMA_LOOP_MODE_1, /**< burst length data transaction */
SDRV_DMA_LOOP_MODE_2, /**< power of 2 length data transaction */
SDRV_DMA_LOOP_MODE_UNDEFINED,
} sdrv_dma_loop_mode_e;
/**
* @brief DMA channel mux direction.
*/
typedef enum {
SDRV_DMA_MUX_RD = 0x1, /**< only peripheral to memory */
SDRV_DMA_MUX_WR = 0x2, /**< only memory to peripheral */
/**< both peripheral to memory and memory to peripheral */
SDRV_DMA_MUX_BOTH = (SDRV_DMA_MUX_RD | SDRV_DMA_MUX_WR),
} sdrv_dma_mux_direction_e;
/**
* @brief DMA channel current status.
*/
typedef enum {
SDRV_DMA_CH_STATUS_STOP = 0, /**< transfer stopped */
SDRV_DMA_CH_STATUS_FLUSH = 1, /**< next MAD config executed directly */
SDRV_DMA_CH_STATUS_REQ_FLUSH = 2, /**< periphal handshake request cleared */
SDRV_DMA_CH_STATUS_HALT = 3, /**< transfer halted */
SDRV_DMA_CH_STATUS_ENABLE = 4, /**< transfer enabled */
SDRV_DMA_CH_STATUS_RESUME = 5, /**< transfer resumed */
SDRV_DMA_CH_STATUS_ABORT = 6, /**< transfer aborted */
} sdrv_dma_channel_status_e;
/**
* @brief DMA channel interrupt types.
*/
typedef enum {
/** DMA Handshake e2e check correctable error */
SDRV_DMA_HANDSHAKE_E2E_COR_ERR = (1 << 0),
/** DMA Handshake e2e check uncorrectable error */
SDRV_DMA_HANDSHAKE_E2E_UNCOR_ERR = (1 << 1),
/** Channel FIFO data ecc check correctable error */
SDRV_DMA_CHANNEL_FIFO_ECC_COR_ERR = (1 << 2),
/** Channel FIFO data ecc check uncorrectable error */
SDRV_DMA_CHANNEL_FIFO_ECC_UNCOR_ERR = (1 << 3),
/** AHB read response error */
SDRV_DMA_AHB_READ_ERR = (1 << 4),
/** AHB write response error */
SDRV_DMA_AHB_WRITE_ERR = (1 << 5),
/** AXI read response error */
SDRV_DMA_AXI_READ_ERR = (1 << 6),
/** AXI write response error */
SDRV_DMA_AXI_WRITE_ERR = (1 << 7),
/** Channel link error */
SDRV_DMA_CHANNEL_LINK_ERR = (1 << 8),
/** MAD crc error */
SDRV_DMA_MAD_CRC_ERR = (1 << 9),
/** Firewall protection read error */
SDRV_DMA_FIREWALL_RD_ERR = (1 << 10),
/** Firewall protection write error */
SDRV_DMA_FIREWALL_WR_ERR = (1 << 11),
/** Data crc error */
SDRV_DMA_DATA_CRC_ERR = (1 << 12),
/** Pattern detected */
SDRV_DMA_PATTERN_DETECTED = (1 << 13),
/**< DMA channel all MAD transfer completed */
SDRV_DMA_LAST_MAD_DONE = (1 << 14),
/**< DMA channel every MAD transfer completed
* (actually for Continuous and Liklist mode). */
SDRV_DMA_EVERY_MAD_DONE = (1 << 15),
/** DMA channel stop*/
SDRV_DMA_CH_STOP = (1 << 16),
/** DMA channel flush*/
SDRV_DMA_CH_FLUSH = (1 << 17),
/** DMA channel requst flush*/
SDRV_DMA_CH_REQ_FLUSH = (1 << 18),
/**< DMA channel transfer halted */
SDRV_DMA_CH_HALT = (1 << 19),
/**< DMA channel transfer aborted */
SDRV_DMA_CH_ABORT = (1 << 20),
/** The handshake request timeout */
SDRV_DMA_REQ_TIMEOUT = (1 << 21),
/** In the loop mode enable with total size unfixed */
SDRV_DMA_SWITCH_EVENT = (1 << 22),
/**< DMA channel handshake request completed */
SDRV_DMA_HS_COMP = (1 << 23),
/** In the pattern mode with 3'b101 or 3'b110, The pattern status for
pattern poll mismatch */
SDRV_DMA_PATTERN_POLL_MISMACTCH = (1 << 24),
/** AXI read or write outstanding UTID error */
SDRV_DMA_AXI_OUTSTANDING_UTID_ERR = (1 << 26),
/** DMA programing sequence error */
SDRV_DMA_PROGRAMING_SEQUENCE_ERR = (1 << 27),
} sdrv_dma_interrupt_type_e;
/**
* @brief DMA channel linklist mad types.
*/
typedef enum {
/**< DMA channel middle MAD */
SDRV_DMA_LINKLIST_NORMAL_MAD = 0,
/**< DMA channel first MAD*/
SDRV_DMA_LINKLIST_FIRST_MAD,
/**< DMA channel last MAD */
SDRV_DMA_LINKLIST_LAST_MAD,
} sdrv_dma_linklist_type_e;
/**
* @brief DMA channel transfer status.
*/
typedef enum {
SDRV_DMA_COMPLETED = 0, /**< DMA channel will not accept requests */
SDRV_DMA_BLOCK_DONE, /**< DMA channel transfer every block done */
SDRV_DMA_IN_PROGRESS, /**< DMA channel in transmission */
SDRV_DMA_PAUSED, /**< DMA channel transfer paused*/
SDRV_DMA_ABORT, /**< DMA channel transfer abort*/
SDRV_DMA_ERR, /**< DMA channel transfer error */
SDRV_DMA_PENDING, /**< DMA channel transfer pending */
} sdrv_dma_status_e;
/**
* @brief DMA channel control state machine status.
*/
typedef enum {
SDRV_DMA_CH_FSM_IDLE = 0, /**< DMA channel idle state */
SDRV_DMA_CH_FSM_MAD_CHECK, /**< DMA channel mad check state */
SDRV_DMA_CH_FSM_POLL_OPD2, /**< DMA channel poll opd2 state */
SDRV_DMA_CH_FSM_DATA_TRANSFER, /**< DMA channel data_transfer state */
SDRV_DMA_CH_FSM_STOP, /**< DMA channel stop state */
SDRV_DMA_CH_FSM_HALT, /**< DMA channel halt state */
SDRV_DMA_CH_FSM_DONE, /**< DMA channel done state */
} sdrv_dma_channle_ctrl_fsm_e;
/**
* @brief DMA MAD CRC.
*/
typedef enum {
SDRV_DMA_NO_MAD_CRC = 0, /**< DMA MAD CRC Disable */
SDRV_DMA_CHECK_CURR_MAD = 1, /**< DMA MAD CRC Check current mad */
SDRV_DMA_CHECK_CURR_MAD_AND_PREVIOUS =
3, /**< DMA MAD CRC check LADR of previous MAD and current MAD(Except
LADR of current MAD) */
} sdrv_dma_mad_crc_mode_e;
/**
* @brief DMA Data CRC.
*/
typedef enum {
SDRV_DMA_NO_DATA_CRC = 0, /**< DMA Data crc disable */
SDRV_DMA_DATA_CRC_SENSE =
1, /**< DMA Data crc calculated CRC value is stored in OPD*/
SDRV_DMA_DATA_CRC_VERIFY_WITH_OPD =
2, /**< DMA Data crc verification with OPD, mismatch CRC verification
error interupt is generated */
SDRV_DMA_DATA_CRC_VERIFY_BETWEEN_WR_RD =
3, /**< DMA Data crc verification between writing data and reading data,
mismatch CRC verification error interupt is generated */
} sdrv_dma_data_crc_mode_e;
/**
* @brief DMA Data CRC Sel.
*/
typedef enum {
CRC32_802P3 = 0,
CRC16_CCITT = 1,
CRC8_CCITT = 2,
} sdrv_dma_data_crc_sel_e;
/**
* @brief DMA channel mux param structure.
*/
typedef struct {
uint32_t port; /**< mux id */
uint64_t start_addr; /**< periphal base address */
uint64_t len; /**< periphal address range */
sdrv_dma_mux_direction_e direct; /**< mux direction */
} sdrv_dma_mux_param_t;
/**
* @brief DMA link list descriptor
*
* The descriptor indicates one MAD configuration, linklist is to connect
* multiple MAD configurations in series.
*/
typedef struct {
/**< DMA channel source address register */
sdrv_dma_ch_src_reg src;
/**< DMA channel target address register */
sdrv_dma_ch_dst_reg dst;
/**< DMA channel transaction control register */
sdrv_dma_ch_tr_ctrl_reg xfer_ctrl;
/**< DMA channel block config register */
sdrv_dma_ch_blk_cfg_reg blk_cfg;
/**< DMA channel operation mode register */
sdrv_dma_ch_op_mod_reg op_mod;
/**< DMA channel operation data register */
sdrv_dma_ch_op_data_reg op_data;
/**< DMA channel mad crc register */
sdrv_dma_ch_mad_crc_reg mad_crc;
/**< DMA channel link address register */
sdrv_dma_ch_ll_addr_reg link_addr;
} sdrv_dma_linklist_descriptor_t;
/**
* @brief DMA controller structure.
*/
typedef struct sdrv_dma {
sdrv_dma_ctrl_t *dma; /**< DMA controller core register structure */
} sdrv_dma_t;
/**
* @brief DMA channel configuration structure.
*/
typedef struct {
/**< DMA controller */
sdrv_dma_t *instance;
/**< ID of this channel */
sdrv_dma_channel_id_e channel_id;
/**< Transfer mode */
sdrv_dma_xfer_mode_e xfer_mode;
/**< Transfer type - source and target buffer types */
sdrv_dma_xfer_type_e xfer_type;
/**< Source buffer address */
paddr_t src_addr;
/**< Source port bus width */
sdrv_dma_bus_width_e src_width;
/**< Increase source address after each transaction? */
sdrv_dma_addr_inc_e src_inc;
/**< Source port burst length */
uint32_t src_burst_len;
/**< Target buffer address */
paddr_t dst_addr;
/**< Target port bus width */
sdrv_dma_bus_width_e dst_width;
/**< Increase target address after each transaction? */
sdrv_dma_addr_inc_e dst_inc;
/**< Target port burst length */
uint32_t dst_burst_len;
/**< Number of bytes to transfer. */
uint32_t xfer_bytes;
/**< DMA Mux ID */
int mux_id;
/**< DMA source port select */
sdrv_dma_port_sel_e src_port_sel;
/**< DMA target port select */
sdrv_dma_port_sel_e dst_port_sel;
/**< DMA source cache enable */
uint32_t src_cache;
/**< DMA target cache enable */
uint32_t dst_cache;
/**< DMA interrupt type */
uint32_t interrupt_type;
/**< Buffer mode */
sdrv_dma_buffer_mode_e buffer_mode;
/**< Handshake request mode */
sdrv_dma_loop_mode_e loop_mode;
/**< Switch event control */
sdrv_dma_switch_event_ctrl_e switch_event_ctrl;
/**< Transfer trigger mode */
sdrv_dma_trigger_mode_e trig_mode;
/**< Link address - next MAD address */
paddr_t linklist_addr;
/**< Linklist MAD type */
sdrv_dma_linklist_type_e linklist_mad_type;
/**< MAD CRC type */
sdrv_dma_mad_crc_mode_e mad_crc_mode;
/**< Data CRC mode */
sdrv_dma_data_crc_mode_e data_crc_mode;
/**< Data CRC sel */
sdrv_dma_data_crc_sel_e data_crc_sel;
} sdrv_dma_channel_config_t;
/**
* @brief DMA channel interrupt callback type.
*/
typedef void (*sdrv_dma_irq_handler)(uint32_t status, uint32_t param,
void *context);
/**
* @brief DMA channel structure.
*/
typedef struct {
/**< DMA controller register structure */
sdrv_dma_ctrl_t *dma;
/**< DMA channel ID */
sdrv_dma_channel_id_e channel_id;
/**< DMA channel controller register structure */
sdrv_dma_channel_ctrl_t *channel;
/**< DMA channel interrupt callback */
sdrv_dma_irq_handler irq_callback;
/**< DMA channel private data for interrupt callback */
void *irq_context;
} sdrv_dma_channel_t;
/**
* @brief get dma channel controller base address.
*
* This function get dma channel base address by dma controller
* base address and channel id.
*
* @param[in] dma_base dma controller base address.
* @param[in] channel dma channel id.
* @retval channel controller base address.
*/
static inline sdrv_dma_channel_ctrl_t *
sdrv_dma_get_channel_ctrl_base(sdrv_dma_ctrl_t *dma_base,
sdrv_dma_channel_id_e channel)
{
paddr_t ch_base = (paddr_t)(dma_base);
return (sdrv_dma_channel_ctrl_t *)(ch_base + SDRV_DMA_CHANNEL_BASE_OFFSET +
SDRV_DMA_CHANNEL_SIZE * channel);
}
/**
* @brief set dma channel software handshake.
*
* This function set software handshake for memory transactions.
*
* @param[in] channel_base dma channel controller base address.
*/
static inline void
sdrv_dma_set_channel_sw_handshake(sdrv_dma_channel_ctrl_t *channel_base)
{
#define SDRV_DMA_LIMIT_TIMES 5
int32_t limit = SDRV_DMA_LIMIT_TIMES;
while (limit--) {
if (channel_base->swhs.v == 0) {
break;
}
}
channel_base->swhs.req = 1;
while (channel_base->ch_status.ctrl_fsm == SDRV_DMA_CH_FSM_DATA_TRANSFER)
;
channel_base->swhs.req = 0;
}
/**
* @brief set dma channel mux id.
*
* This function set mux id for periphal transactions.
*
* @param[in] dma_base dma controller base address.
* @param[in] channel dma channel id.
* @param[in] mux_id dma channel mux id.
*/
static inline void sdrv_dma_set_channel_muxid(sdrv_dma_ctrl_t *dma_base,
sdrv_dma_channel_id_e channel,
uint32_t mux_id)
{
sdrv_dma_channel_ctrl_t *ch_base =
sdrv_dma_get_channel_ctrl_base(dma_base, channel);
ch_base->port_cfg.csel = mux_id;
}
/**
* @brief set dma channel read outstanding.
*
* This function set read outstanding for memory transactions to get better
* performance.
*
* @param[in] dma_base dma controller base address.
* @param[in] channel dma channel id.
* @param[in] value read outstanding value.
*/
static inline void sdrv_dma_set_channel_rd_outstanding(
sdrv_dma_ctrl_t *dma_base, sdrv_dma_channel_id_e channel, uint8_t value)
{
sdrv_dma_channel_ctrl_t *ch_base =
sdrv_dma_get_channel_ctrl_base(dma_base, channel);
ch_base->port_cfg.rot = value;
}
/**
* @brief set dma channel write outstanding.
*
* This function set write outstanding for memory transactions to get better
* performance.
*
* @param[in] dma_base dma controller base address.
* @param[in] channel dma channel id.
* @param[in] value write outstanding value.
*/
static inline void sdrv_dma_set_channel_wr_outstanding(
sdrv_dma_ctrl_t *dma_base, sdrv_dma_channel_id_e channel, uint8_t value)
{
sdrv_dma_channel_ctrl_t *ch_base =
sdrv_dma_get_channel_ctrl_base(dma_base, channel);
ch_base->port_cfg.wot = value;
}
/**
* @brief set dma channel interrupt type.
*
* This function set dma channel interrupt type.
*
* @param[in] dma_base dma controller base address.
* @param[in] channel dma channel id.
* @param[in] int_type interrupt type.
*/
static inline void sdrv_dma_set_channel_interrupt(sdrv_dma_ctrl_t *dma_base,
sdrv_dma_channel_id_e channel,
uint32_t int_type)
{
sdrv_dma_channel_ctrl_t *ch_base =
sdrv_dma_get_channel_ctrl_base(dma_base, channel);
ch_base->int_en.v = int_type;
}
/**
* @brief reset dma interrupt type.
*
* This function reset dma controller interrupt status.
*
* @param[in] dma_base dma controller base address.
*/
static inline void sdrv_dma_reset_core_int_status(sdrv_dma_ctrl_t *dma_base)
{
dma_base->int_cfg.cont_int_clr.v = 0xFFFFFFFF;
dma_base->int_cfg.cont_int_clr.v = 0x00000000;
dma_base->int_cfg.int_clr.v = 0xFFFFFFFF;
dma_base->int_cfg.int_clr.v = 0x00000000;
}
/**
* @brief reset dma fifo.
*
* This function reset dma controller fifo.
*
* @param[in] dma_base dma controller base address.
*/
static inline void sdrv_dma_reset_fifo(sdrv_dma_ctrl_t *dma_base)
{
uint32_t *dma_fifo_addr =
(uint32_t *)((paddr_t)dma_base + SDRV_DMA_FIFO_OFFSET);
int index = 0;
for (index = 0; index < (SDRV_DMA_FIFO_SIZE / sizeof(uint32_t)); index++) {
dma_fifo_addr[index] = 0;
}
}
/**
* @brief set dma channel status.
*
* @param[in] channel_base dma channel controller base address.
* @param[in] status dma channel status.
*/
static inline void
sdrv_dma_set_channel_status(sdrv_dma_channel_ctrl_t *channel_base,
sdrv_dma_channel_status_e status)
{
switch (status) {
case SDRV_DMA_CH_STATUS_STOP:
channel_base->ch_cfg.stop = 1;
while (channel_base->ch_cfg.stop)
;
break;
case SDRV_DMA_CH_STATUS_FLUSH:
channel_base->ch_cfg.flush = 1;
break;
case SDRV_DMA_CH_STATUS_REQ_FLUSH:
channel_base->ch_cfg.req_flush = 1;
break;
case SDRV_DMA_CH_STATUS_HALT:
#if CONFIG_E3L
if (IS_P1)
channel_base->ch_cfg.halt = 1;
else if (channel_base->shadow_op_mod.trigger_mode !=
SDRV_DMA_TRIGGER_BY_INTERNAL_EVENT)
channel_base->ch_cfg.halt = 1;
#else
if (channel_base->shadow_op_mod.trigger_mode !=
SDRV_DMA_TRIGGER_BY_INTERNAL_EVENT)
channel_base->ch_cfg.halt = 1;
#endif
break;
case SDRV_DMA_CH_STATUS_RESUME:
channel_base->ch_cfg.resume = 1;
break;
case SDRV_DMA_CH_STATUS_ABORT:
channel_base->ch_cfg.abort = 1;
break;
default:
break;
}
}
/**
* @brief Initialize the DMA controller.
*
* This function initialize dma controller with reset status and fifo.
*
* @param[in] base DMA controller base address.
*/
void sdrv_dma_init_dmac(paddr_t base);
/**
* @brief Create DMA controller instance.
*
* This function create instance by dma controller base address.
*
* @param[in] dma_instance Pointer to DMA instance structure.
* @param[in] base DMA controller base address.
*/
status_t sdrv_dma_create_instance(sdrv_dma_t *dma_instance, paddr_t base);
/**
* @brief Initialize default configuration for DMA channel.
*
* This function get channel default configuration.
*
* @param[in] config DMA channel configuration to initialize.
* @param[in] dma_instance DMA controller instance.
*/
status_t sdrv_dma_init_channel_config(sdrv_dma_channel_config_t *config,
sdrv_dma_t *instance);
/**
* @brief Initialize DMA channel.
*
* This function set configuration to channel.
*
* @param[in] channel The channel to initialize.
* @param[in] config DMA channel configuration.
* @return True if the DMA channel is initialized successfully.
*/
status_t sdrv_dma_init_channel(sdrv_dma_channel_t *channel,
const sdrv_dma_channel_config_t *config);
/**
* @brief Start DMA transaction.
*
* This function start transfer.
*
* @param[in] channel The DMA channel to start.
*/
status_t sdrv_dma_start_channel_xfer(sdrv_dma_channel_t *channel);
/**
* @brief Stop DMA transaction.
*
* This function stop transfer.
*
* @param[in] channel The DMA channel to stop.
*/
status_t sdrv_dma_stop_channel_xfer(sdrv_dma_channel_t *channel);
/**
* @brief De-initialize the DMA channel.
*
* This function reset channel registers to default value.
*
* @param[in] channel The DMA channel to de-initialize.
*/
status_t sdrv_dma_deinit_channel(sdrv_dma_channel_t *channel);
/**
* @brief Initialize DMA link list descriptor.
*
* This function initializes a DMA link list descriptor, using specified
* channel configuration.
*
* @param[in] desc Link list descriptor.
* @param[in] config DMA channel config.
* @return
*/
status_t sdrv_dma_init_linklist_entry(sdrv_dma_linklist_descriptor_t *desc,
const sdrv_dma_channel_config_t *config);
/**
* @brief Set DMA channel source address.
*
* This function set source address to channel.
*
* @param[in] channel DMA channel.
* @param[in] addr source address.
*/
status_t sdrv_dma_set_channel_source_address(sdrv_dma_channel_t *channel,
paddr_t addr);
/**
* @brief set dma channel single transmit buffer size
*
* This is an unsafe interface. The parameters filled in need to be calculated
* by yourself, and there is no verification inside the function.
*
* @param channel dma channel ptr
* @param loop_mode loop mode
* @param total_size total bytes
* @param loop_size every handshake transmic bytes(The loop mode 0 does not take
* effect)
*
* @return
*/
void sdrv_dma_set_channel_buffer_size(sdrv_dma_channel_t *channel,
sdrv_dma_loop_mode_e loop_mode,
uint32_t total_size,
uint32_t loop_size);
/**
* @brief Set DMA channel target address.
*
* This function set target address to channel.
*
* @param[in] channel DMA channel.
* @param[in] addr target address.
*/
status_t sdrv_dma_set_channel_destination_address(sdrv_dma_channel_t *channel,
paddr_t addr);
/**
* @brief Set transfer length in bytes for the channel.
*
* This function set transfer length in one transaction.
*
* @param[in] channel DMA channel.
* @param[in] xfer_bytes transfer bytes.
*/
status_t sdrv_dma_set_channel_xfer_bytes(sdrv_dma_channel_t *channel,
uint32_t xfer_bytes);
/**
* @brief Get number of transfered bytes for the channel
*
* This function get transfered length in bytes.
*
* @param[in] channel DMA channel.
* @return Number of transfered bytes.
*/
uint32_t sdrv_dma_get_channel_xfer_bytes(sdrv_dma_channel_t *channel);
/**
* @brief Clear DMA channel transfered bytes counter.
*
* This function clear transfered bytes counter.
*
* @param[in] channel DMA channel.
*/
status_t sdrv_dma_clear_channel_xfer_bytes(sdrv_dma_channel_t *channel);
/**
* @brief Get DMA channel status.
*
* This function get channel current status.
*
* @param[in] channel DMA channel.
* @return channel status.
*/
uint32_t sdrv_dma_get_channel_xfer_status(sdrv_dma_channel_t *channel);
/**
* @brief Clear DMA channel status.
*
* This function clear channel current status.
*
* @param[in] channel DMA channel.
* @param[in] status Channel status bitmask.
*/
status_t sdrv_dma_clear_channel_xfer_status(sdrv_dma_channel_t *channel,
uint32_t status);
#endif