/** * @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 #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