diff --git a/drivers/rz/CMakeLists.txt b/drivers/rz/CMakeLists.txt index 4a8e0df5..582f06f2 100644 --- a/drivers/rz/CMakeLists.txt +++ b/drivers/rz/CMakeLists.txt @@ -80,7 +80,10 @@ zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_CANFD zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_RSPI_SPI fsp/src/${SOC_SERIES_PREFIX}/r_rspi/r_rspi.c) -zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_DMA +zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_DMAC + fsp/src/${SOC_SERIES_PREFIX}/r_dmac/r_dmac.c) + +zephyr_library_sources_ifdef(CONFIG_USE_RZ_FSP_DMAC_B fsp/src/${SOC_SERIES_PREFIX}/r_dmac_b/r_dmac_b.c) if(CONFIG_DT_HAS_RENESAS_RZ_SCI_B_ENABLED) diff --git a/drivers/rz/README b/drivers/rz/README index 3a4ad5aa..21ffa35a 100644 --- a/drivers/rz/README +++ b/drivers/rz/README @@ -88,3 +88,17 @@ Patch List: Impacted files: drivers/rz/fsp/src/rzg/r_gtm/r_gtm.c drivers/rz/fsp/src/rzv/r_gtm/r_gtm.c + + * Use r_transfer_api.h of rzv-fsp to support the callbackSet member of the transfer_api_t struct + Impacted files: + drivers/rz/fsp/inc/api/r_transfer_api.h + + * Disable the BSP_FEATURE_BSP_HAS_MMU_SUPPORT configuration of the RZ/A3UL to avoid using + FSP MMU functions and let Zephyr handle MMU + Impacted files: + drivers/rz/fsp/src/rza/bsp/mcu/rza3ul/bsp_feature.h + + * Change the cast type from uint32_t to uintptr_t when assigning an address to a register in the + DMAC FSP driver of the RZ/A3UL to avoid build warnings + Impacted files: + drivers/rz/fsp/src/rza/r_dmac/r_dmac.c diff --git a/drivers/rz/fsp/inc/api/r_transfer_api.h b/drivers/rz/fsp/inc/api/r_transfer_api.h index d25a3083..c1dd35fe 100644 --- a/drivers/rz/fsp/inc/api/r_transfer_api.h +++ b/drivers/rz/fsp/inc/api/r_transfer_api.h @@ -5,7 +5,7 @@ */ /*******************************************************************************************************************//** - * @ingroup RENESAS_INTERFACES + * @ingroup RENESAS_TRANSFER_INTERFACES * @defgroup TRANSFER_API Transfer Interface * * @brief Interface for data transfer functions. @@ -13,8 +13,6 @@ * @section TRANSFER_API_SUMMARY Summary * The transfer interface supports background data transfer (no CPU intervention). * - * Implemented by: - * - @ref DMAC_B * * @{ **********************************************************************************************************************/ @@ -49,8 +47,6 @@ FSP_HEADER **********************************************************************************************************************/ /** Transfer control block. Allocate an instance specific control block to pass into the transfer API calls. - * @par Implemented as - * - dmac_b_instance_ctrl_t */ typedef void transfer_ctrl_t; @@ -95,7 +91,8 @@ typedef enum e_transfer_size { TRANSFER_SIZE_1_BYTE = 0, ///< Each transfer transfers a 8-bit value TRANSFER_SIZE_2_BYTE = 1, ///< Each transfer transfers a 16-bit value - TRANSFER_SIZE_4_BYTE = 2 ///< Each transfer transfers a 32-bit value + TRANSFER_SIZE_4_BYTE = 2, ///< Each transfer transfers a 32-bit value + TRANSFER_SIZE_8_BYTE = 3 ///< Each transfer transfers a 64-bit value } transfer_size_t; #endif @@ -172,6 +169,16 @@ typedef enum e_transfer_irq #endif +#ifndef BSP_OVERRIDE_TRANSFER_CALLBACK_ARGS_T + +/** Callback function parameter data. */ +typedef struct st_transfer_callback_args_t +{ + void const * p_context; ///< Placeholder for user data. Set in @ref transfer_api_t::open function in ::transfer_cfg_t. +} transfer_callback_args_t; + +#endif + /** Driver specific information. */ typedef struct st_transfer_properties { @@ -266,8 +273,6 @@ typedef enum e_transfer_start_mode typedef struct st_transfer_api { /** Initial configuration. - * @par Implemented as - * - @ref R_DMAC_B_Open() * * @param[in,out] p_ctrl Pointer to control block. Must be declared by user. Elements set here. * @param[in] p_cfg Pointer to configuration structure. All elements of this structure @@ -277,8 +282,6 @@ typedef struct st_transfer_api /** Reconfigure the transfer. * Enable the transfer if p_info is valid. - * @par Implemented as - * - @ref R_DMAC_B_Reconfigure() * * @param[in,out] p_ctrl Pointer to control block. Must be declared by user. Elements set here. * @param[in] p_info Pointer to a new transfer info structure. @@ -287,8 +290,6 @@ typedef struct st_transfer_api /** Reset source address pointer, destination address pointer, and/or length, keeping all other settings the same. * Enable the transfer if p_src, p_dest, and length are valid. - * @par Implemented as - * - @ref R_DMAC_B_Reset() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. * @param[in] p_src Pointer to source. Set to NULL if source pointer should not change. @@ -302,8 +303,6 @@ typedef struct st_transfer_api /** Enable transfer. Transfers occur after the activation source event (or when * @ref transfer_api_t::softwareStart is called if no peripheral event is chosen as activation source). - * @par Implemented as - * - @ref R_DMAC_B_Enable() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. */ @@ -313,8 +312,6 @@ typedef struct st_transfer_api * @ref transfer_api_t::softwareStart is called if no peripheral event is chosen as the DMAC activation source). * @note If a transfer is in progress, it will be completed. Subsequent transfer requests do not cause a * transfer. - * @par Implemented as - * - @ref R_DMAC_B_Disable() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. */ @@ -323,8 +320,6 @@ typedef struct st_transfer_api /** Start transfer in software. * @warning Only works if no peripheral event is chosen as the DMAC activation source. * @note Not supported for DTC. - * @par Implemented as - * - @ref R_DMAC_B_SoftwareStart() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. * @param[in] mode Select mode from @ref transfer_start_mode_t. @@ -335,16 +330,12 @@ typedef struct st_transfer_api * @note Not supported for DTC. * @note Only applies for transfers started with TRANSFER_START_MODE_REPEAT. * @warning Only works if no peripheral event is chosen as the DMAC activation source. - * @par Implemented as - * - @ref R_DMAC_B_SoftwareStop() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. */ fsp_err_t (* softwareStop)(transfer_ctrl_t * const p_ctrl); /** Provides information about this transfer. - * @par Implemented as - * - @ref R_DMAC_B_InfoGet() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. * @param[out] p_properties Driver specific information. @@ -352,8 +343,6 @@ typedef struct st_transfer_api fsp_err_t (* infoGet)(transfer_ctrl_t * const p_ctrl, transfer_properties_t * const p_properties); /** Releases hardware lock. This allows a transfer to be reconfigured using @ref transfer_api_t::open. - * @par Implemented as - * - @ref R_DMAC_B_Close() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. */ @@ -361,8 +350,6 @@ typedef struct st_transfer_api /** To update next transfer information without interruption during transfer. * Allow further transfer continuation. - * @par Implemented as - * - @ref R_DMAC_B_Reload() * * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. * @param[in] p_src Pointer to source. Set to NULL if source pointer should not change. @@ -372,6 +359,16 @@ typedef struct st_transfer_api fsp_err_t (* reload)(transfer_ctrl_t * const p_ctrl, void const * p_src, void * p_dest, uint32_t const num_transfers); + /** Specify callback function and optional context pointer and working memory pointer. + * + * @param[in] p_ctrl Control block set in @ref transfer_api_t::open call for this transfer. + * @param[in] p_callback Callback function to register + * @param[in] p_context Pointer to send to callback function + * @param[in] p_callback_memory Pointer to volatile memory where callback structure can be allocated. + * Callback arguments allocated here are only valid during the callback. + */ + fsp_err_t (* callbackSet)(transfer_ctrl_t * const p_ctrl, void (* p_callback)(transfer_callback_args_t *), + void const * const p_context, transfer_callback_args_t * const p_callback_memory); } transfer_api_t; /** This structure encompasses everything that is needed to use an instance of this interface. */ diff --git a/drivers/rz/fsp/inc/instances/rza/r_dmac.h b/drivers/rz/fsp/inc/instances/rza/r_dmac.h new file mode 100644 index 00000000..a3dac3d4 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rza/r_dmac.h @@ -0,0 +1,295 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup DMAC + * @{ + **********************************************************************************************************************/ + +#ifndef R_DMAC_H +#define R_DMAC_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "bsp_api.h" +#include "r_transfer_api.h" +#include "r_dmac_cfg.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Max configurable number of transfers in TRANSFER_MODE_NORMAL. */ +#define DMAC_MAX_NORMAL_TRANSFER_LENGTH (0xFFFFFFFF) + +/** Max number of transfers per block in TRANSFER_MODE_BLOCK */ +#define DMAC_MAX_BLOCK_TRANSFER_LENGTH (0xFFFFFFFF) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +typedef transfer_callback_args_t dmac_callback_args_t; + +/** Events that can trigger a callback function. */ +typedef enum e_dmac_event +{ + DMAC_EVENT_TRANSFER_END = 0, ///< DMA transfer has completed. + DMAC_EVENT_TRANSFER_ERROR = 1, ///< A bus error occurred during DMA transfer. +} dmac_event_t; + +/** Transfer size specifies the size of each individual transfer. */ +typedef enum e_dmac_transfer_size +{ + DMAC_TRANSFER_SIZE_1_BYTE = 0, ///< Each transfer transfers a 8-bit value. + DMAC_TRANSFER_SIZE_2_BYTE = 1, ///< Each transfer transfers a 16-bit value. + DMAC_TRANSFER_SIZE_4_BYTE = 2, ///< Each transfer transfers a 32-bit value. + DMAC_TRANSFER_SIZE_8_BYTE = 3, ///< Each transfer transfers a 64-bit value. + DMAC_TRANSFER_SIZE_16_BYTE = 4, ///< Each transfer transfers a 128-bit value. + DMAC_TRANSFER_SIZE_32_BYTE = 5, ///< Each transfer transfers a 256-bit value. + DMAC_TRANSFER_SIZE_64_BYTE = 6, ///< Each transfer transfers a 512-bit value. + DMAC_TRANSFER_SIZE_128_BYTE = 7, ///< Each transfer transfers a 1024-bit value. +} dmac_transfer_size_t; + +/** DACK output mode. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_ack_mode +{ + DMAC_ACK_MODE_LEVEL_MODE = 1, ///< Level mode. + DMAC_ACK_MODE_BUS_CYCLE_MODE = 2, ///< Bus cycle mode. + DMAC_ACK_MODE_MASK_DACK_OUTPUT = 4, ///< Output is masked. +} dmac_ack_mode_t; + +/** Detection method of the DMA request signal. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_detection +{ + DMAC_DETECTION_FALLING_EDGE = 1, ///< Falling edge detection. + DMAC_DETECTION_RISING_EDGE = 2, ///< Rising edge detection. + DMAC_DETECTION_LOW_LEVEL = 5, ///< Low level detection. + DMAC_DETECTION_HIGH_LEVEL = 6, ///< High level detection. +} dmac_detection_t; + +/** DMA activation request source select. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_request_direction +{ + DMAC_REQUEST_DIRECTION_SOURCE_MODULE = 0, ///< Requested by a transfer source module. + DMAC_REQUEST_DIRECTION_DESTINATION_MODULE = 1, ///< Requested by a transfer destination module. +} dmac_request_direction_t; + +/** Select the Next register set to be executed next. */ +typedef enum e_dmac_continuous_setting +{ + DMAC_CONTINUOUS_SETTING_TRANSFER_NEXT0_ONCE = 0x0, ///< Transfer only once using the Next0 register set. + DMAC_CONTINUOUS_SETTING_TRANSFER_NEXT0_NEXT1_ALTERNATELY = 0x3, ///< Transfers are performed alternately with the Next0 register set and the Next1 register set. +} dmac_continuous_setting_t; + +/** Register set settings. */ +typedef struct st_dmac_next1_register_setting +{ + void const * p_src; ///< Source pointer. + void * p_dest; ///< Destination pointer. + uint32_t length; ///< Transfer Byte. +} dmac_next1_register_setting_t; + +/** DMAC channel scheduling. */ +typedef enum e_dmac_channel_scheduling +{ + DMAC_CHANNEL_SCHEDULING_FIXED = 0, ///< Fixed priority mode. + DMAC_CHANNEL_SCHEDULING_ROUND_ROBIN = 1, ///< Round-robin mode. +} dmac_channel_scheduling_t; + +/** DMAC mode setting. */ +typedef enum e_dmac_mode_select +{ + DMAC_MODE_SELECT_REGISTER = 0, ///< Register mode. + DMAC_MODE_SELECT_LINK = 1, ///< Link mode. +} dmac_mode_select_t; + +/** Indicates the descriptor is enabled or disabled. */ +typedef enum e_dmac_link_valid +{ + DMAC_LINK_VALID_DESCRIPTOR_DISABLE = 0, ///< The Descriptor is disabled. + DMAC_LINK_VALID_DESCRIPTOR_ENABLE = 1, ///< The Descriptor is enabled. +} dmac_link_valid_t; + +/** Indicates that the link ends during DMA transfer of this descriptor. */ +typedef enum e_dmac_link_end +{ + DMAC_LINK_END_DISABLE = 0, ///< The link continues. + DMAC_LINK_END_ENABLE = 1, ///< The link ends. +} dmac_link_end_t; + +/** Masks write back execution of the dmac_link_cfg_t::link_valid. When disable, DMAC does not perform write-back operation. */ +typedef enum e_dmac_link_write_back +{ + DMAC_LINK_WRITE_BACK_ENABLE = 0, ///< Set dmac_link_cfg_t::link_valid to disable after the DMA transfer ends. + DMAC_LINK_WRITE_BACK_DISABLE = 1, ///< Remain dmac_link_cfg_t::link_valid after DMA transfer ends. +} dmac_link_write_back_t; + +/** When dmac_link_cfg_t::link_valid is DMAC_LINK_VALID_DESCRIPTOR_DISABLE at loading of header, specifies whether DMA transfer completion interrupt mask or not. */ +typedef enum e_dmac_link_interrupt_mask +{ + DMAC_LINK_INTERRUPT_MASK_DISABLE = 0, ///< DMA transfer completion interrupt is asserted. + DMAC_LINK_INTERRUPT_MASK_ENABLE = 1, ///< DMA transfer completion interrupt is masked. +} dmac_link_interrupt_mask_t; + +/** Descriptor structure used in DMAC link mode, and variables of dmac_link_cfg_t must be allocated in the memory area. */ +#if (BSP_FEATURE_DMAC_64BIT_SYSTEM == 1) +typedef struct st_dmac_link_cfg +{ + union + { + uint32_t header_u32; ///< Descriptor header + struct + { + dmac_link_valid_t link_valid : 1; ///< The descriptor is valid or not. + dmac_link_end_t link_end : 1; ///< The descriptor is end or not. + dmac_link_write_back_t write_back_disable : 1; ///< Write back enable or not. + dmac_link_interrupt_mask_t interrupt_mask : 1; ///< Interrupt mask is enable or not. + uint32_t : 28; + } header; + }; + volatile uint32_t src_addr; ///< Source address. + volatile uint32_t dest_addr; ///< Destination address. + volatile uint32_t transaction_byte; ///< Transaction byte. + volatile uint32_t channel_cfg; ///< Channel configuration (Set value for CHCFG_n register). + volatile uint32_t channel_interval; ///< Channel interval (Set value for CHITVL register). + volatile uint32_t channel_extension_cfg; ///< Channel extension configuration (Set value for CHEXT_n register). + volatile uint32_t next_link_addr; ///< Next link address. +} dmac_link_cfg_t; +#else +typedef struct st_dmac_link_cfg +{ + union + { + uint32_t header_u32; ///< Descriptor header + struct + { + dmac_link_valid_t link_valid : 1; ///< The descriptor is valid or not. + dmac_link_end_t link_end : 1; ///< The descriptor is end or not. + dmac_link_write_back_t write_back_disable : 1; ///< Write back enable or not. + dmac_link_interrupt_mask_t interrupt_mask : 1; ///< Interrupt mask is enable or not. + uint32_t : 28; + } header; + }; + void const * volatile p_src; ///< Source address. + void * volatile p_dest; ///< Destination address. + volatile uint32_t transaction_byte; ///< Transaction byte. + volatile uint32_t channel_cfg; ///< Channel configuration (Set value for CHCFG_n register). + volatile uint32_t channel_interval; ///< Channel interval (Set value for CHITVL register). + volatile uint32_t channel_extension_cfg; ///< Channel extension configuration (Set value for CHEXT_n register). + void * volatile p_next_link_addr; ///< Next link address. +} dmac_link_cfg_t; +#endif + +/** Control block used by driver. DO NOT INITIALIZE - this structure will be initialized in @ref transfer_api_t::open. */ +typedef struct st_dmac_instance_ctrl +{ + uint32_t open; // Driver ID + + transfer_cfg_t const * p_cfg; + + dmac_link_cfg_t const * p_descriptor; + + /* Pointer to base register. */ + R_DMA0_Type * p_reg; + + void (* p_callback)(dmac_callback_args_t *); // Pointer to callback + dmac_callback_args_t * p_callback_memory; // Pointer to optional callback argument memory + void const * p_context; +} dmac_instance_ctrl_t; + +/** DMAC transfer configuration extension. This extension is required. */ +typedef struct st_dmac_extended_cfg +{ + uint8_t channel; ///< Channel number + IRQn_Type dmac_int_irq; ///< DMAC interrupt number + uint8_t dmac_int_ipl; ///< DMAC interrupt priority + uint32_t dmac_int_irq_detect_type; ///< DMAC interrupt detection type + + /** Select which event will trigger the transfer. */ + dmac_trigger_event_t activation_source; + + /** The interrupt ID number that corresponds to the Activation Source. */ + IRQn_Type activation_irq_number; + + dmac_ack_mode_t ack_mode; ///< DACK output mode + dmac_detection_t detection_mode; ///< DMAC request detection method + dmac_request_direction_t activation_request_source_select; ///< DMAC activation request source + + dmac_mode_select_t dmac_mode; ///< DMAC Mode + dmac_link_cfg_t const * p_descriptor; ///< The address of the descriptor (DMA Link Mode only) + dmac_continuous_setting_t continuous_setting; ///< Next register operation settings + uint16_t transfer_interval; ///< DMA transfer interval + dmac_channel_scheduling_t channel_scheduling; ///< DMA channel scheduling + + /** Callback for transfer end interrupt. */ + void (* p_callback)(dmac_callback_args_t * cb_data); + dmac_callback_args_t * p_callback_memory; + + /** Placeholder for user data. Passed to the user p_callback in ::transfer_callback_args_t. */ + void const * p_context; +} dmac_extended_cfg_t; + +/** DMAC transfer configuration extension. This extension is required. */ +typedef struct st_dmac_extended_info +{ + /** Select number of source bytes to transfer at once. */ + dmac_transfer_size_t src_size; + + /** Select number of destnination bytes to transfer at once. */ + dmac_transfer_size_t dest_size; + + /** Next1 Register set settings */ + dmac_next1_register_setting_t * p_next1_register_setting; +} dmac_extended_info_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const transfer_api_t g_transfer_on_dmac; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Open(transfer_ctrl_t * const p_api_ctrl, transfer_cfg_t const * const p_cfg); +fsp_err_t R_DMAC_Reconfigure(transfer_ctrl_t * const p_api_ctrl, transfer_info_t * p_info); +fsp_err_t R_DMAC_Reset(transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers); +fsp_err_t R_DMAC_SoftwareStart(transfer_ctrl_t * const p_api_ctrl, transfer_start_mode_t mode); +fsp_err_t R_DMAC_SoftwareStop(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_Enable(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_Disable(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_InfoGet(transfer_ctrl_t * const p_api_ctrl, transfer_properties_t * const p_info); +fsp_err_t R_DMAC_Close(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_Reload(transfer_ctrl_t * const p_api_ctrl, + void const * p_src, + void * p_dest, + uint32_t const num_transfers); +fsp_err_t R_DMAC_CallbackSet(transfer_ctrl_t * const p_api_ctrl, + void ( * p_callback)(dmac_callback_args_t *), + void const * const p_context, + dmac_callback_args_t * const p_callback_memory); +fsp_err_t R_DMAC_LinkDescriptorSet(transfer_ctrl_t * const p_api_ctrl, dmac_link_cfg_t * p_descriptor); + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif + +/*******************************************************************************************************************//** + * @} (end defgroup DMAC) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/inc/instances/rzn/r_dmac.h b/drivers/rz/fsp/inc/instances/rzn/r_dmac.h new file mode 100644 index 00000000..7f51e272 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzn/r_dmac.h @@ -0,0 +1,252 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup DMAC + * @{ + **********************************************************************************************************************/ + +#ifndef R_DMAC_H +#define R_DMAC_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "bsp_api.h" +#include "r_dmac_cfg.h" +#include "r_transfer_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Max configurable number of transfers in TRANSFER_MODE_NORMAL. */ +#define DMAC_MAX_NORMAL_TRANSFER_LENGTH (0xFFFFFFFF) + +/** Max number of transfers per block in TRANSFER_MODE_BLOCK */ +#define DMAC_MAX_BLOCK_TRANSFER_LENGTH (0xFFFFFFFF) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** Indicates the descriptor is enabled or disabled. */ +typedef enum e_dmac_link_valid +{ + DMAC_LINK_VALID_DESCRIPTOR_DISABLE = 0, ///< The Descriptor is disabled. + DMAC_LINK_VALID_DESCRIPTOR_ENABLE = 1, ///< The Descriptor is enabled. +} dmac_link_valid_t; + +/** Indicates that the link ends during DMA transfer of this descriptor. */ +typedef enum e_dmac_link_end +{ + DMAC_LINK_END_DISABLE = 0, ///< The link continues. + DMAC_LINK_END_ENABLE = 1, ///< The link ends. +} dmac_link_end_t; + +/** Masks write back execution of the dmac_link_cfg_t::link_valid. When disable, DMAC does not perform write-back operation. */ +typedef enum e_dmac_link_write_back +{ + DMAC_LINK_WRITE_BACK_ENABLE = 0, ///< Set dmac_link_cfg_t::link_valid to disable after the DMA transfer ends. + DMAC_LINK_WRITE_BACK_DISABLE = 1, ///< Remain dmac_link_cfg_t::link_valid after DMA transfer ends. +} dmac_link_write_back_t; + +/** When dmac_link_cfg_t::link_valid is DMAC_LINK_VALID_DESCRIPTOR_DISABLE at loading of header, specifies whether DMA transfer completion interrupt mask or not. */ +typedef enum e_dmac_link_interrupt_mask +{ + DMAC_LINK_INTERRUPT_MASK_DISABLE = 0, ///< DMA transfer completion interrupt is asserted. + DMAC_LINK_INTERRUPT_MASK_ENABLE = 1, ///< DMA transfer completion interrupt is masked. +} dmac_link_interrupt_mask_t; + +/** Descriptor structure used in DMAC link mode, and variables of dmac_link_cfg_t must be allocated in the memory area. */ +#if defined(BSP_CFG_CORE_CA55) +typedef struct st_dmac_link_cfg +{ + union + { + uint32_t header_u32; ///< Descriptor header + struct + { + dmac_link_valid_t link_valid : 1; ///< The descriptor is valid or not. + dmac_link_end_t link_end : 1; ///< The descriptor is end or not. + dmac_link_write_back_t write_back_disable : 1; ///< Write back enable or not. + dmac_link_interrupt_mask_t interrupt_mask : 1; ///< Interrupt mask is enable or not. + uint32_t : 28; + } header; + }; + volatile uint32_t src_addr; ///< Source address. + volatile uint32_t dest_addr; ///< Destination address. + volatile uint32_t transaction_byte; ///< Transaction byte. + volatile uint32_t channel_cfg; ///< Channel configuration (Set value for CHCFG_n register). + volatile uint32_t channel_interval; ///< Channel interval (Set value for CHITVL register). + volatile uint32_t channel_extension_cfg; ///< Channel extension configuration (Set value for CHEXT_n register). + volatile uint32_t next_link_addr; ///< Next link address. +} dmac_link_cfg_t; +#else +typedef struct st_dmac_link_cfg +{ + union + { + uint32_t header_u32; ///< Descriptor header + struct + { + dmac_link_valid_t link_valid : 1; ///< The descriptor is valid or not. + dmac_link_end_t link_end : 1; ///< The descriptor is end or not. + dmac_link_write_back_t write_back_disable : 1; ///< Write back enable or not. + dmac_link_interrupt_mask_t interrupt_mask : 1; ///< Interrupt mask is enable or not. + uint32_t : 28; + } header; + }; + void const * volatile p_src; ///< Source address. + void * volatile p_dest; ///< Destination address. + volatile uint32_t transaction_byte; ///< Transaction byte. + volatile uint32_t channel_cfg; ///< Channel configuration (Set value for CHCFG_n register). + volatile uint32_t channel_interval; ///< Channel interval (Set value for CHITVL register). + volatile uint32_t channel_extension_cfg; ///< Channel extension configuration (Set value for CHEXT_n register). + void * volatile p_next_link_addr; ///< Next link address. +} dmac_link_cfg_t; +#endif + +/** Select the Next register set to be executed next. */ +typedef enum e_dmac_register_select_reverse +{ + DMAC_REGISTER_SELECT_REVERSE_DISABLE = 0x0, ///< Use Next0 register set. + DMAC_REGISTER_SELECT_REVERSE_ENABLE = 0x1, ///< Use Next1 register set. + DMAC_REGISTER_SELECT_REVERSE_ENABLE_PERFORM_ACCORDINGLY = 0x3, ///< Use Next1 register set after Next0 register set transfer completed. +} dmac_register_select_reverse_t; + +/** DACK output mode. See 'DMA Transfer Request Detection Operation Setting Table' of RZ microprocessor manual. */ +typedef enum e_dmac_ack_mode +{ + DMAC_ACK_MODE_LEVEL_MODE = 1, ///< Level mode. + DMAC_ACK_MODE_BUS_CYCLE_MODE = 2, ///< Bus cycle mode. + DMAC_ACK_MODE_MASK_DACK_OUTPUT = 4, ///< Output is masked. +} dmac_ack_mode_t; + +/** Detection method of the DMA request signal. See 'DMA Transfer Request Detection Operation Setting Table' of RZ microprocessor manual. */ +typedef enum e_dmac_detection +{ + DMAC_DETECTION_FALLING_EDGE = 1, ///< Falling edge detection. + DMAC_DETECTION_RISING_EDGE = 2, ///< Rising edge detection. + DMAC_DETECTION_LOW_LEVEL = 5, ///< Low level detection. + DMAC_DETECTION_HIGH_LEVEL = 6, ///< High level detection. +} dmac_detection_t; + +/** DMA activation request source select. See 'DMA Transfer Request Detection Operation Setting Table' of RZ microprocessor manual. */ +typedef enum e_dmac_request_direction +{ + DMAC_REQUEST_DIRECTION_SOURCE_MODULE = 0, ///< Requested by a transfer source module. + DMAC_REQUEST_DIRECTION_DESTINATION_MODULE = 1, ///< Requested by a transfer destination module. +} dmac_request_direction_t; + +/** DMAC channel scheduling. */ +typedef enum e_dmac_channel_scheduling +{ + DMAC_CHANNEL_SCHEDULING_FIXED = 0, ///< Fixed priority mode. + DMAC_CHANNEL_SCHEDULING_ROUND_ROBIN = 1, ///< Round-robin mode. +} dmac_channel_scheduling_t; + +/** DMAC mode setting. */ +typedef enum e_dmac_mode_select +{ + DMAC_MODE_SELECT_REGISTER = 0, ///< Register mode. + DMAC_MODE_SELECT_LINK = 1, ///< Link mode. +} dmac_mode_select_t; + +/** Control block used by driver. DO NOT INITIALIZE - this structure will be initialized in @ref transfer_api_t::open. */ +typedef struct st_dmac_instance_ctrl +{ + uint32_t open; // Driver ID + + transfer_cfg_t const * p_cfg; + + dmac_mode_select_t dmac_mode; + dmac_link_cfg_t const * p_descriptor; + + /* Pointer to base register. */ + R_DMAC0_Type * p_reg; + + void (* p_callback)(transfer_callback_args_t *); // Pointer to callback + transfer_callback_args_t * p_callback_memory; // Pointer to optional callback argument memory + void const * p_context; // Pointer to context to be passed into callback function +} dmac_instance_ctrl_t; + +/** DMAC transfer configuration extension. This extension is required. */ +typedef struct st_dmac_extended_cfg +{ + uint8_t unit; ///< Unit number + uint8_t channel; ///< Channel number + IRQn_Type dmac_int_irq; ///< DMAC interrupt number + uint8_t dmac_int_ipl; ///< DMAC interrupt priority + uint32_t dmac_int_irq_detect_type; ///< DMAC interrupt detection type + + /** Select which event will trigger the transfer. */ + elc_event_t activation_source; + + dmac_ack_mode_t ack_mode; ///< DACK output mode + dmac_detection_t detection_mode; ///< DMAC request detection method + dmac_request_direction_t activation_request_source_select; ///< DMAC activation request source + + dmac_register_select_reverse_t next_register_operation; ///< Next register operation settings + + dmac_mode_select_t dmac_mode; ///< DMAC Mode + + dmac_link_cfg_t const * p_descriptor; ///< The address of the descriptor (DMA Link Mode only) + + uint16_t transfer_interval; ///< DMA transfer interval + dmac_channel_scheduling_t channel_scheduling; ///< DMA channel scheduling + + /** Callback for transfer end interrupt. */ + void (* p_callback)(transfer_callback_args_t * cb_data); + + /** Placeholder for user data. Passed to the user p_callback in ::transfer_callback_args_t. */ + void const * p_context; +} dmac_extended_cfg_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const transfer_api_t g_transfer_on_dmac; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Open(transfer_ctrl_t * const p_ctrl, transfer_cfg_t const * const p_cfg); +fsp_err_t R_DMAC_Reconfigure(transfer_ctrl_t * const p_ctrl, transfer_info_t * p_info); +fsp_err_t R_DMAC_Reset(transfer_ctrl_t * const p_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers); +fsp_err_t R_DMAC_SoftwareStart(transfer_ctrl_t * const p_ctrl, transfer_start_mode_t mode); +fsp_err_t R_DMAC_SoftwareStop(transfer_ctrl_t * const p_ctrl); +fsp_err_t R_DMAC_Enable(transfer_ctrl_t * const p_ctrl); +fsp_err_t R_DMAC_Disable(transfer_ctrl_t * const p_ctrl); +fsp_err_t R_DMAC_InfoGet(transfer_ctrl_t * const p_ctrl, transfer_properties_t * const p_info); +fsp_err_t R_DMAC_Close(transfer_ctrl_t * const p_ctrl); +fsp_err_t R_DMAC_Reload(transfer_ctrl_t * const p_ctrl, void const * p_src, void * p_dest, + uint32_t const num_transfers); +fsp_err_t R_DMAC_CallbackSet(transfer_ctrl_t * const p_ctrl, + void ( * p_callback)(transfer_callback_args_t *), + void const * const p_context, + transfer_callback_args_t * const p_callback_memory); +fsp_err_t R_DMAC_LinkDescriptorSet(transfer_ctrl_t * const p_ctrl, dmac_link_cfg_t * p_descriptor); + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif + +/*******************************************************************************************************************//** + * @} (end defgroup DMAC) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/inc/instances/rzt/r_dmac.h b/drivers/rz/fsp/inc/instances/rzt/r_dmac.h new file mode 100644 index 00000000..70abf7df --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzt/r_dmac.h @@ -0,0 +1,252 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup DMAC + * @{ + **********************************************************************************************************************/ + +#ifndef R_DMAC_H +#define R_DMAC_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "bsp_api.h" +#include "r_dmac_cfg.h" +#include "r_transfer_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Max configurable number of transfers in TRANSFER_MODE_NORMAL. */ +#define DMAC_MAX_NORMAL_TRANSFER_LENGTH (0xFFFFFFFF) + +/** Max number of transfers per block in TRANSFER_MODE_BLOCK */ +#define DMAC_MAX_BLOCK_TRANSFER_LENGTH (0xFFFFFFFF) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +/** Indicates the descriptor is enabled or disabled. */ +typedef enum e_dmac_link_valid +{ + DMAC_LINK_VALID_DESCRIPTOR_DISABLE = 0, ///< The Descriptor is disabled. + DMAC_LINK_VALID_DESCRIPTOR_ENABLE = 1, ///< The Descriptor is enabled. +} dmac_link_valid_t; + +/** Indicates that the link ends during DMA transfer of this descriptor. */ +typedef enum e_dmac_link_end +{ + DMAC_LINK_END_DISABLE = 0, ///< The link continues. + DMAC_LINK_END_ENABLE = 1, ///< The link ends. +} dmac_link_end_t; + +/** Masks write back execution of the dmac_link_cfg_t::link_valid. When disable, DMAC does not perform write-back operation. */ +typedef enum e_dmac_link_write_back +{ + DMAC_LINK_WRITE_BACK_ENABLE = 0, ///< Set dmac_link_cfg_t::link_valid to disable after the DMA transfer ends. + DMAC_LINK_WRITE_BACK_DISABLE = 1, ///< Remain dmac_link_cfg_t::link_valid after DMA transfer ends. +} dmac_link_write_back_t; + +/** When dmac_link_cfg_t::link_valid is DMAC_LINK_VALID_DESCRIPTOR_DISABLE at loading of header, specifies whether DMA transfer completion interrupt mask or not. */ +typedef enum e_dmac_link_interrupt_mask +{ + DMAC_LINK_INTERRUPT_MASK_DISABLE = 0, ///< DMA transfer completion interrupt is asserted. + DMAC_LINK_INTERRUPT_MASK_ENABLE = 1, ///< DMA transfer completion interrupt is masked. +} dmac_link_interrupt_mask_t; + +/** Descriptor structure used in DMAC link mode, and variables of dmac_link_cfg_t must be allocated in the memory area. */ +#if defined(BSP_CFG_CORE_CA55) +typedef struct st_dmac_link_cfg +{ + union + { + uint32_t header_u32; ///< Descriptor header + struct + { + dmac_link_valid_t link_valid : 1; ///< The descriptor is valid or not. + dmac_link_end_t link_end : 1; ///< The descriptor is end or not. + dmac_link_write_back_t write_back_disable : 1; ///< Write back enable or not. + dmac_link_interrupt_mask_t interrupt_mask : 1; ///< Interrupt mask is enable or not. + uint32_t : 28; + } header; + }; + volatile uint32_t src_addr; ///< Source address. + volatile uint32_t dest_addr; ///< Destination address. + volatile uint32_t transaction_byte; ///< Transaction byte. + volatile uint32_t channel_cfg; ///< Channel configuration (Set value for CHCFG_n register). + volatile uint32_t channel_interval; ///< Channel interval (Set value for CHITVL register). + volatile uint32_t channel_extension_cfg; ///< Channel extension configuration (Set value for CHEXT_n register). + volatile uint32_t next_link_addr; ///< Next link address. +} dmac_link_cfg_t; +#else +typedef struct st_dmac_link_cfg +{ + union + { + uint32_t header_u32; ///< Descriptor header + struct + { + dmac_link_valid_t link_valid : 1; ///< The descriptor is valid or not. + dmac_link_end_t link_end : 1; ///< The descriptor is end or not. + dmac_link_write_back_t write_back_disable : 1; ///< Write back enable or not. + dmac_link_interrupt_mask_t interrupt_mask : 1; ///< Interrupt mask is enable or not. + uint32_t : 28; + } header; + }; + void const * volatile p_src; ///< Source address. + void * volatile p_dest; ///< Destination address. + volatile uint32_t transaction_byte; ///< Transaction byte. + volatile uint32_t channel_cfg; ///< Channel configuration (Set value for CHCFG_n register). + volatile uint32_t channel_interval; ///< Channel interval (Set value for CHITVL register). + volatile uint32_t channel_extension_cfg; ///< Channel extension configuration (Set value for CHEXT_n register). + void * volatile p_next_link_addr; ///< Next link address. +} dmac_link_cfg_t; +#endif + +/** Select the Next register set to be executed next. */ +typedef enum e_dmac_register_select_reverse +{ + DMAC_REGISTER_SELECT_REVERSE_DISABLE = 0x0, ///< Use Next0 register set. + DMAC_REGISTER_SELECT_REVERSE_ENABLE = 0x1, ///< Use Next1 register set. + DMAC_REGISTER_SELECT_REVERSE_ENABLE_PERFORM_ACCORDINGLY = 0x3, ///< Use Next1 register set after Next0 register set transfer completed. +} dmac_register_select_reverse_t; + +/** DACK output mode. See 'DMA Transfer Request Detection Operation Setting Table' of RZ microprocessor manual. */ +typedef enum e_dmac_ack_mode +{ + DMAC_ACK_MODE_LEVEL_MODE = 1, ///< Level mode. + DMAC_ACK_MODE_BUS_CYCLE_MODE = 2, ///< Bus cycle mode. + DMAC_ACK_MODE_MASK_DACK_OUTPUT = 4, ///< Output is masked. +} dmac_ack_mode_t; + +/** Detection method of the DMA request signal. See 'DMA Transfer Request Detection Operation Setting Table' of RZ microprocessor manual. */ +typedef enum e_dmac_detection +{ + DMAC_DETECTION_FALLING_EDGE = 1, ///< Falling edge detection. + DMAC_DETECTION_RISING_EDGE = 2, ///< Rising edge detection. + DMAC_DETECTION_LOW_LEVEL = 5, ///< Low level detection. + DMAC_DETECTION_HIGH_LEVEL = 6, ///< High level detection. +} dmac_detection_t; + +/** DMA activation request source select. See 'DMA Transfer Request Detection Operation Setting Table' of RZ microprocessor manual. */ +typedef enum e_dmac_request_direction +{ + DMAC_REQUEST_DIRECTION_SOURCE_MODULE = 0, ///< Requested by a transfer source module. + DMAC_REQUEST_DIRECTION_DESTINATION_MODULE = 1, ///< Requested by a transfer destination module. +} dmac_request_direction_t; + +/** DMAC channel scheduling. */ +typedef enum e_dmac_channel_scheduling +{ + DMAC_CHANNEL_SCHEDULING_FIXED = 0, ///< Fixed priority mode. + DMAC_CHANNEL_SCHEDULING_ROUND_ROBIN = 1, ///< Round-robin mode. +} dmac_channel_scheduling_t; + +/** DMAC mode setting. */ +typedef enum e_dmac_mode_select +{ + DMAC_MODE_SELECT_REGISTER = 0, ///< Register mode. + DMAC_MODE_SELECT_LINK = 1, ///< Link mode. +} dmac_mode_select_t; + +/** Control block used by driver. DO NOT INITIALIZE - this structure will be initialized in @ref transfer_api_t::open. */ +typedef struct st_dmac_instance_ctrl +{ + uint32_t open; // Driver ID + + transfer_cfg_t const * p_cfg; + + dmac_mode_select_t dmac_mode; + dmac_link_cfg_t const * p_descriptor; + + /* Pointer to base register. */ + R_DMAC0_Type * p_reg; + + void (* p_callback)(transfer_callback_args_t *); // Pointer to callback + transfer_callback_args_t * p_callback_memory; // Pointer to optional callback argument memory + void const * p_context; // Pointer to context to be passed into callback function +} dmac_instance_ctrl_t; + +/** DMAC transfer configuration extension. This extension is required. */ +typedef struct st_dmac_extended_cfg +{ + uint8_t unit; ///< Unit number + uint8_t channel; ///< Channel number + IRQn_Type dmac_int_irq; ///< DMAC interrupt number + uint8_t dmac_int_ipl; ///< DMAC interrupt priority + uint32_t dmac_int_irq_detect_type; ///< DMAC interrupt detection type + + /** Select which event will trigger the transfer. */ + elc_event_t activation_source; + + dmac_ack_mode_t ack_mode; ///< DACK output mode + dmac_detection_t detection_mode; ///< DMAC request detection method + dmac_request_direction_t activation_request_source_select; ///< DMAC activation request source + + dmac_register_select_reverse_t next_register_operaion; ///< DEPRECATED - next_register_operaion will be renamed next_register_operation in the major release. Next register operation settings + + dmac_mode_select_t dmac_mode; ///< DMAC Mode + + dmac_link_cfg_t const * p_descriptor; ///< The address of the descriptor (DMA Link Mode only) + + uint16_t transfer_interval; ///< DMA transfer interval + dmac_channel_scheduling_t channel_scheduling; ///< DMA channel scheduling + + /** Callback for transfer end interrupt. */ + void (* p_callback)(transfer_callback_args_t * cb_data); + + /** Placeholder for user data. Passed to the user p_callback in ::transfer_callback_args_t. */ + void const * p_context; +} dmac_extended_cfg_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const transfer_api_t g_transfer_on_dmac; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Open(transfer_ctrl_t * const p_ctrl, transfer_cfg_t const * const p_cfg); +fsp_err_t R_DMAC_Reconfigure(transfer_ctrl_t * const p_ctrl, transfer_info_t * p_info); +fsp_err_t R_DMAC_Reset(transfer_ctrl_t * const p_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers); +fsp_err_t R_DMAC_SoftwareStart(transfer_ctrl_t * const p_ctrl, transfer_start_mode_t mode); +fsp_err_t R_DMAC_SoftwareStop(transfer_ctrl_t * const p_ctrl); +fsp_err_t R_DMAC_Enable(transfer_ctrl_t * const p_ctrl); +fsp_err_t R_DMAC_Disable(transfer_ctrl_t * const p_ctrl); +fsp_err_t R_DMAC_InfoGet(transfer_ctrl_t * const p_ctrl, transfer_properties_t * const p_info); +fsp_err_t R_DMAC_Close(transfer_ctrl_t * const p_ctrl); +fsp_err_t R_DMAC_Reload(transfer_ctrl_t * const p_ctrl, void const * p_src, void * p_dest, + uint32_t const num_transfers); +fsp_err_t R_DMAC_CallbackSet(transfer_ctrl_t * const p_ctrl, + void ( * p_callback)(transfer_callback_args_t *), + void const * const p_context, + transfer_callback_args_t * const p_callback_memory); +fsp_err_t R_DMAC_LinkDescriptorSet(transfer_ctrl_t * const p_ctrl, dmac_link_cfg_t * p_descriptor); + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif + +/*******************************************************************************************************************//** + * @} (end defgroup DMAC) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/inc/instances/rzv/r_dmac_b.h b/drivers/rz/fsp/inc/instances/rzv/r_dmac_b.h new file mode 100644 index 00000000..40596bd3 --- /dev/null +++ b/drivers/rz/fsp/inc/instances/rzv/r_dmac_b.h @@ -0,0 +1,219 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*******************************************************************************************************************//** + * @addtogroup DMAC_B + * @{ + **********************************************************************************************************************/ + +#ifndef R_DMAC_B_H +#define R_DMAC_B_H + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "bsp_api.h" +#include "r_transfer_api.h" + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Max configurable number of transfers in TRANSFER_MODE_NORMAL. */ +#define DMAC_B_MAX_NORMAL_TRANSFER_LENGTH (0xFFFFFFFF) + +/** Max number of transfers per block in TRANSFER_MODE_BLOCK */ +#define DMAC_B_MAX_BLOCK_TRANSFER_LENGTH (0xFFFFFFFF) + +/*********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +typedef transfer_callback_args_t dmac_b_callback_args_t; + +/** Transfer size specifies the size of each individual transfer. */ +typedef enum e_dmac_b_transfer_size +{ + DMAC_B_TRANSFER_SIZE_1_BYTE = 0, ///< Each transfer transfers a 8-bit value. + DMAC_B_TRANSFER_SIZE_2_BYTE = 1, ///< Each transfer transfers a 16-bit value. + DMAC_B_TRANSFER_SIZE_4_BYTE = 2, ///< Each transfer transfers a 32-bit value. + DMAC_B_TRANSFER_SIZE_8_BYTE = 3, ///< Each transfer transfers a 64-bit value. + DMAC_B_TRANSFER_SIZE_16_BYTE = 4, ///< Each transfer transfers a 128-bit value. + DMAC_B_TRANSFER_SIZE_32_BYTE = 5, ///< Each transfer transfers a 256-bit value. + DMAC_B_TRANSFER_SIZE_64_BYTE = 6, ///< Each transfer transfers a 512-bit value. + DMAC_B_TRANSFER_SIZE_128_BYTE = 7, ///< Each transfer transfers a 1024-bit value. +} dmac_b_transfer_size_t; + +/** DACK output mode. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_b_ack_mode +{ + DMAC_B_ACK_MODE_LEVEL_MODE = 1, ///< Level mode. + DMAC_B_ACK_MODE_BUS_CYCLE_MODE = 2, ///< Bus cycle mode. + DMAC_B_ACK_MODE_MASK_DACK_OUTPUT = 4, ///< Output is masked. +} dmac_b_ack_mode_t; + +#ifndef BSP_OVERRIDE_DMAC_B_EXTERNAL_DETECTION_T + +/** Detection method of the external DMA request signal. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_b_external_detection +{ + DMAC_B_EXTERNAL_DETECTION_LOW_LEVEL = 0, ///< Low level detection. + DMAC_B_EXTERNAL_DETECTION_FALLING_EDGE = 1, ///< Falling edge detection. + DMAC_B_EXTERNAL_DETECTION_RISING_EDGE = 2, ///< Rising edge detection. + DMAC_B_EXTERNAL_DETECTION_FALLING_RISING_EDGE = 3, ///< Falling/Rising edge detection. +} dmac_b_external_detection_t; + +#endif + +/** Detection method of the internal DMA request signal. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_b_internal_detection +{ + DMAC_B_INTERNAL_DETECTION_NO_DETECTION = 0, ///< Not using hardware detection. + DMAC_B_INTERNAL_DETECTION_FALLING_EDGE = 1, ///< Falling edge detection. + DMAC_B_INTERNAL_DETECTION_RISING_EDGE = 2, ///< Rising edge detection. + DMAC_B_INTERNAL_DETECTION_LOW_LEVEL = 5, ///< Low level detection. + DMAC_B_INTERNAL_DETECTION_HIGH_LEVEL = 6, ///< High level detection. +} dmac_b_internal_detection_t; + +/** DMA activation request source select. See RZ/T2M hardware manual Table 14.19 DMA Transfer Request Detection Operation Setting Table. */ +typedef enum e_dmac_b_request_direction +{ + DMAC_B_REQUEST_DIRECTION_SOURCE_MODULE = 0, ///< Requested by a transfer source module. + DMAC_B_REQUEST_DIRECTION_DESTINATION_MODULE = 1, ///< Requested by a transfer destination module. +} dmac_b_request_direction_t; + +/** Select the Next register set to be executed next. */ +typedef enum e_dmac_b_continuous_setting +{ + DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE = 0x0, ///< Transfer only once using the Next0 register set. + DMAC_B_CONTINUOUS_SETTING_TRANSFER_ALTERNATELY = 0x3, ///< Transfers are performed alternately with the Next0 register set and the Next1 register set. +} dmac_b_continuous_setting_t; + +/** Register set settings. */ +typedef struct st_dmac_b_register_set_setting_t +{ + void const * p_src; ///< Source pointer. + void * p_dest; ///< Destination pointer. + uint32_t length; ///< Transfer byte. +} dmac_b_register_set_setting_t; + +/** DMAC channel scheduling. */ +typedef enum e_dmac_b_channel_scheduling +{ + DMAC_B_CHANNEL_SCHEDULING_FIXED = 0, ///< Fixed priority mode. + DMAC_B_CHANNEL_SCHEDULING_ROUND_ROBIN = 1, ///< Round-robin mode. +} dmac_b_channel_scheduling_t; + +/** DMAC mode setting. */ +typedef enum e_dmac_b_mode_select +{ + DMAC_B_MODE_SELECT_REGISTER = 0, ///< Register mode. + DMAC_B_MODE_SELECT_LINK = 1, ///< Link mode. +} dmac_b_mode_select_t; + +/** Control block used by driver. DO NOT INITIALIZE - this structure will be initialized in @ref transfer_api_t::open. */ +typedef struct st_dmac_b_instance_ctrl +{ + uint32_t open; // Driver ID + + transfer_cfg_t const * p_cfg; + + /* Pointer to base register. */ + R_DMAC_B0_Type * p_reg; + + void (* p_callback)(dmac_b_callback_args_t *); // Pointer to callback + dmac_b_callback_args_t * p_callback_memory; // Pointer to optional callback argument memory + void const * p_context; // Pointer to context to be passed into callback function +} dmac_b_instance_ctrl_t; + +/** DMAC transfer configuration extension. This extension is required. */ +typedef struct st_dmac_b_extended_cfg +{ + uint8_t unit; ///< Unit number + uint8_t channel; ///< Channel number + IRQn_Type dmac_int_irq; ///< DMAC interrupt number + uint8_t dmac_int_ipl; ///< DMAC interrupt priority + + /** Select which event will trigger the transfer. */ + dmac_trigger_event_t activation_source; + dmac_b_ack_mode_t ack_mode; ///< DACK output mode + dmac_b_external_input_pin_t dreq_input_pin; ///< DREQ input pin name + dmac_b_external_output_pin_t ack_output_pin; ///< DACK output pin name + dmac_b_external_output_pin_t tend_output_pin; ///< TEND output pin name + dmac_b_external_detection_t external_detection_mode; ///< DMAC request detection method for external pin + dmac_b_internal_detection_t internal_detection_mode; ///< DMAC request detection method for internal pin + dmac_b_request_direction_t activation_request_source_select; ///< DMAC activation request source + + dmac_b_mode_select_t dmac_mode; ///< DMAC Mode + dmac_b_continuous_setting_t continuous_setting; ///< Next register operation settings + uint16_t transfer_interval; ///< DMA transfer interval + dmac_b_channel_scheduling_t channel_scheduling; ///< DMA channel scheduling + + /** Callback for transfer end interrupt. */ + void (* p_callback)(dmac_b_callback_args_t * cb_data); + + /** Placeholder for user data. Passed to the user p_callback in ::transfer_callback_args_t. */ + void const * p_context; +} dmac_b_extended_cfg_t; + +/** DMAC transfer information configuration extension. This extension is required. */ +typedef struct st_dmac_b_extended_info +{ + /** Select number of source bytes to transfer at once. */ + dmac_b_transfer_size_t src_size; + + /** Select number of destination bytes to transfer at once. */ + dmac_b_transfer_size_t dest_size; + + /** Next1 Register set settings */ + dmac_b_register_set_setting_t * p_next1_register_setting; +} dmac_b_extended_info_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const transfer_api_t g_transfer_on_dmac_b; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public Function Prototypes + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Open(transfer_ctrl_t * const p_api_ctrl, transfer_cfg_t const * const p_cfg); +fsp_err_t R_DMAC_B_Reconfigure(transfer_ctrl_t * const p_api_ctrl, transfer_info_t * p_info); +fsp_err_t R_DMAC_B_Reset(transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers); +fsp_err_t R_DMAC_B_SoftwareStart(transfer_ctrl_t * const p_api_ctrl, transfer_start_mode_t mode); +fsp_err_t R_DMAC_B_SoftwareStop(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_B_Enable(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_B_Disable(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_B_InfoGet(transfer_ctrl_t * const p_api_ctrl, transfer_properties_t * const p_info); +fsp_err_t R_DMAC_B_Close(transfer_ctrl_t * const p_api_ctrl); +fsp_err_t R_DMAC_B_Reload(transfer_ctrl_t * const p_api_ctrl, + void const * p_src, + void * p_dest, + uint32_t const num_transfers); +fsp_err_t R_DMAC_B_CallbackSet(transfer_ctrl_t * const p_api_ctrl, + void ( * p_callback)(dmac_b_callback_args_t *), + void const * const p_context, + dmac_b_callback_args_t * const p_callback_memory); + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif + +/*******************************************************************************************************************//** + * @} (end defgroup DMAC) + **********************************************************************************************************************/ diff --git a/drivers/rz/fsp/src/rza/bsp/mcu/rza3ul/bsp_feature.h b/drivers/rz/fsp/src/rza/bsp/mcu/rza3ul/bsp_feature.h index e5bd3265..2fcd4839 100644 --- a/drivers/rz/fsp/src/rza/bsp/mcu/rza3ul/bsp_feature.h +++ b/drivers/rz/fsp/src/rza/bsp/mcu/rza3ul/bsp_feature.h @@ -35,7 +35,7 @@ /* BSP Capabilities Definitions */ #define BSP_FEATURE_BSP_SUPPORT_PLL5_CONFIG (0U) #define BSP_FEATURE_BSP_SUPPORT_OCTAL_MEMORY (1U) -#define BSP_FEATURE_BSP_HAS_MMU_SUPPORT (1) +#define BSP_FEATURE_BSP_HAS_MMU_SUPPORT (0U) #define BSP_FEATURE_BSP_HAS_ELC (0U) #define BSP_FEATURE_BSP_SUPPORT_SD_VOLT (1U) #define BSP_FEATURE_BSP_SUPPORT_ETHER_VOLT (1U) diff --git a/drivers/rz/fsp/src/rza/r_dmac/r_dmac.c b/drivers/rz/fsp/src/rza/r_dmac/r_dmac.c new file mode 100644 index 00000000..03a8d137 --- /dev/null +++ b/drivers/rz/fsp/src/rza/r_dmac/r_dmac.c @@ -0,0 +1,1156 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_dmac.h" +#include "r_dmac_cfg.h" +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + #include "hal_data.h" +#endif + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Driver ID (DMAC in ASCII) */ +#define DMAC_ID (0x444d4143) + +/** Byte limited to 2^32-1 byte */ +#define DMAC_BLOCK_MAX_LENGTH (0xFFFFFFFF) +#define DMAC_BLOCK_COUNT_MAX_LENGTH (0xFFFFFFFF) + +#define DMAC_PRV_DCTRL_DEFAULT_VALUE (0x00000000U) +#define DMAC_PRV_CHCFG_DEFAULT_VALUE (0x00000000U) + +/* Calculate the mask bits for byte alignment from the transfer_size_t. */ +#define DMAC_PRV_MASK_ALIGN_N_BYTES(x) ((1U << (x)) - 1U) +#define DMAC_PRV_MASK_ALIGN_4_BYTES (0x2U) + +/* Channel Configuration Register Bit Field Definitions */ +#define DMAC_PRV_CHCFG_SEL_VALUE_MASK (0x07U) +#define DMAC_PRV_CHCFG_REQD_VALUE_MASK (0x01U) +#define DMAC_PRV_CHCFG_DETECT_MODE_VALUE_MASK (0x07U) +#define DMAC_PRV_CHCFG_AM_VALUE_MASK (0x07U) +#define DMAC_PRV_CHCFG_SDS_OFFSET (12U) +#define DMAC_PRV_CHCFG_SDS_VALUE_MASK (0x0FU) +#define DMAC_PRV_CHCFG_DDS_OFFSET (16U) +#define DMAC_PRV_CHCFG_DDS_VALUE_MASK (0x0FU) +#define DMAC_PRV_CHCFG_SAD_OFFSET (20U) +#define DMAC_PRV_CHCFG_SAD_VALUE_MASK (0x01U) +#define DMAC_PRV_CHCFG_DAD_OFFSET (21U) +#define DMAC_PRV_CHCFG_DAD_VALUE_MASK (0x01U) +#define DMAC_PRV_CHCFG_TM_VALUE_MASK (0x02U) +#define DMAC_PRV_NEXT_REG_VALUE_MASK (0x03U) + +/* DMA Control Register Bit Field Definitions */ +#define DMAC_PRV_DCTRL_PR_OFFSET (0U) +#define DMAC_PRV_DCTRL_PR_VALUE_MASK (0x01U) + +/* DMAC Resource Select Register Bit Field Definitions */ +#define DMAC_PRV_DMARS_MID_RID_OFFSET (16U) +#define DMAC_PRV_DMARS_MID_RID_MASK (0x3FFU) +#define DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK (0xFFFU) +#define DMAC_PRV_CHCFG_TM_VALUE_POS (0x01U) + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +void dmac_int_isr(IRQn_Type const irq); +void dmac_err_isr(IRQn_Type const irq); + +static fsp_err_t r_dmac_prv_enable(dmac_instance_ctrl_t * p_ctrl); +static void r_dmac_prv_disable(dmac_instance_ctrl_t * p_ctrl); +static void r_dmac_config_transfer_info_register_mode(dmac_instance_ctrl_t * p_ctrl, transfer_info_t * p_info); +static void r_dmac_config_transfer_info_link_mode(dmac_instance_ctrl_t * p_ctrl); +static void r_dmac_activation_trigger_enable(dmac_extended_cfg_t const * const p_extend); +static void r_dmac_activation_trigger_disable(dmac_extended_cfg_t const * const p_extend); + +#if DMAC_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_dma_open_parameter_checking(dmac_instance_ctrl_t * const p_ctrl, transfer_cfg_t const * const p_cfg); +static fsp_err_t r_dmac_reconfigure_parameter_checking(transfer_info_t const * const p_info); +static fsp_err_t r_dmac_enable_parameter_checking(dmac_instance_ctrl_t * const p_ctrl); +static fsp_err_t r_dmac_enable_parameter_checking_register_mode(dmac_instance_ctrl_t * const p_ctrl); +static fsp_err_t r_dmac_enable_parameter_checking_link_mode(dmac_instance_ctrl_t * const p_ctrl); +static fsp_err_t r_dmac_link_descriptor_parameter_checking(dmac_link_cfg_t const * p_descriptor); + +#endif + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ +R_DMA_EX_Type * p_reg_ex; +R_DMA0_7_Type * p_reg0_7; +R_DMA8_15_Type * p_reg8_15; + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** DMAC implementation of transfer API. */ +const transfer_api_t g_transfer_on_dmac = +{ + .open = R_DMAC_Open, + .reconfigure = R_DMAC_Reconfigure, + .reset = R_DMAC_Reset, + .infoGet = R_DMAC_InfoGet, + .softwareStart = R_DMAC_SoftwareStart, + .softwareStop = R_DMAC_SoftwareStop, + .enable = R_DMAC_Enable, + .disable = R_DMAC_Disable, + .close = R_DMAC_Close, + .reload = R_DMAC_Reload, + .callbackSet = R_DMAC_CallbackSet, +}; + +/*******************************************************************************************************************//** + * @addtogroup DMAC + * @{ + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Configure a DMAC channel. + * + * @retval FSP_SUCCESS Successful open. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the activation source is not enabled in the BSP. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Open (transfer_ctrl_t * const p_api_ctrl, transfer_cfg_t const * const p_cfg) +{ +#if DMAC_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = FSP_SUCCESS; + err = r_dma_open_parameter_checking(p_api_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_cfg->p_extend; + + /* Calculate base address for registers on this channel. */ + uintptr_t base_address = (uintptr_t) R_DMA0_NS + + (p_extend->channel * ((uintptr_t) R_DMA1_NS - (uintptr_t) R_DMA0_NS)); + R_DMA0_Type * p_reg = (R_DMA0_Type *) base_address; + p_reg_ex = R_DMA_EX_NS; + if (p_extend->channel < 8) + { + p_reg0_7 = R_DMA0_7_NS; + } + else + { + p_reg8_15 = R_DMA8_15_NS; + } + + p_ctrl->p_cfg = p_cfg; + p_ctrl->p_reg = p_reg; + + /* Set callback and context pointers, if configured */ + p_ctrl->p_callback = p_extend->p_callback; + p_ctrl->p_context = p_extend->p_context; + p_ctrl->p_callback_memory = NULL; + + /* Supply clock to DMAC module. */ + R_BSP_MODULE_START(FSP_IP_DMAC_NS, p_extend->channel); + + /* Configure the transfer settings. */ + if (DMAC_MODE_SELECT_REGISTER == p_extend->dmac_mode) + { + r_dmac_config_transfer_info_register_mode(p_ctrl, p_cfg->p_info); + } + else if (DMAC_MODE_SELECT_LINK == p_extend->dmac_mode) + { + r_dmac_config_transfer_info_link_mode(p_ctrl); + } + else + { + /* Do nothing. */ + } + + /* Mark driver as open by initializing "DMAC" in its ASCII equivalent.*/ + p_ctrl->open = DMAC_ID; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reconfigure the transfer with new transfer info. + * + * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_ENABLED DMAC is not enabled. The current configuration must not be valid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reconfigure (transfer_ctrl_t * const p_api_ctrl, transfer_info_t * p_info) +{ + fsp_err_t err; + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl != NULL); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + err = r_dmac_reconfigure_parameter_checking(p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + FSP_ASSERT(p_ctrl->p_cfg->p_extend != NULL); + FSP_ASSERT(p_info->p_extend_info != NULL); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + dmac_extended_info_t * p_extend_info = (dmac_extended_info_t *) p_info->p_extend_info; + if (DMAC_CONTINUOUS_SETTING_TRANSFER_NEXT0_ONCE != p_extend->continuous_setting) + { + FSP_ASSERT(NULL != p_extend_info->p_next1_register_setting); + } +#endif + + /* Reconfigure the transfer settings. */ + r_dmac_config_transfer_info_register_mode(p_ctrl, p_info); + + /* Enable the transfer configuration. */ + err = r_dmac_prv_enable(p_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, FSP_ERR_NOT_ENABLED); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reconfigure the transfer descriptor information with new transfer descriptor. + * + * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_ENABLED DMAC is not enabled. The current configuration must not be valid. + * @retval FSP_ERR_INVALID_MODE DMA mode is register mode. This function can only be used when the DMA mode is link mode. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_LinkDescriptorSet (transfer_ctrl_t * const p_api_ctrl, dmac_link_cfg_t * p_descriptor) +{ + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; + + fsp_err_t err = FSP_SUCCESS; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl != NULL); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + FSP_ASSERT(p_descriptor != NULL); + err = r_dmac_link_descriptor_parameter_checking(p_descriptor); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ERROR_RETURN(p_ctrl->p_reg->CHCFG_b.DMS == 1U, FSP_ERR_INVALID_MODE); +#endif + + /* Store current descriptor */ + p_ctrl->p_descriptor = p_descriptor; + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + + /* Set address of the link destination */ + va = (uint64_t) p_descriptor; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->NXLA = (uint32_t) pa; +#else + + /* Set address of the link destination */ + p_ctrl->p_reg->NXLA = (uintptr_t) p_descriptor; +#endif + + err = r_dmac_prv_enable(p_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, FSP_ERR_NOT_ENABLED); + + /* Wait descriptor load */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->CHSTAT_b.DL, 0); + + return err; +} + +/*******************************************************************************************************************//** + * Reset transfer source, destination, and number of transfers. + * + * @retval FSP_ERR_UNSUPPORTED API not supported. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reset (transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers) +{ + FSP_PARAMETER_NOT_USED(p_api_ctrl); + FSP_PARAMETER_NOT_USED(p_src); + FSP_PARAMETER_NOT_USED(p_dest); + FSP_PARAMETER_NOT_USED(num_transfers); + + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * If the mode is TRANSFER_START_MODE_SINGLE initiate a single transfer with software. If the mode is + * TRANSFER_START_MODE_REPEAT continue triggering transfers until all of the transfers are completed. + * + * @retval FSP_SUCCESS Transfer started written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_SoftwareStart (transfer_ctrl_t * const p_api_ctrl, transfer_start_mode_t mode) +{ + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + FSP_PARAMETER_NOT_USED(mode); + + /* Set auto clear bit and software start bit. */ + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_STG_Msk; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Stop software transfers if they were started with TRANSFER_START_MODE_REPEAT. + * + * @retval FSP_SUCCESS Transfer stopped written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_SoftwareStop (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + /* Set Suspend. */ + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_SETSUS_Msk; + + /* Transfer is already stopped. */ + if (1 != p_ctrl->p_reg->CHSTAT_b.EN) + { + /* Software Reset */ + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_SWRST_Msk; + + return FSP_SUCCESS; + } + + /* Check whether a transfer is suspended. */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->CHSTAT_b.SUS, 1); + + /* Set clear enable and software stop bit. */ + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_CLREN_Msk; + + /* Check whether a transfer is stopped. */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->CHSTAT_b.TACT, 0); + + /* Software Reset */ + p_ctrl->p_reg->CHCTRL_b.SWRST = 1; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Enable transfers for the configured activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Enable (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + return r_dmac_prv_enable(p_ctrl); +} + +/*******************************************************************************************************************//** + * Disable transfers so that they are no longer triggered by the activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Disable (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + r_dmac_prv_disable(p_ctrl); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Set driver specific information in provided pointer. + * + * @retval FSP_SUCCESS Information has been written to p_info. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_InfoGet (transfer_ctrl_t * const p_api_ctrl, transfer_properties_t * const p_info) +{ + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + FSP_ASSERT(NULL != p_info); +#endif + + p_info->transfer_length_max = DMAC_MAX_NORMAL_TRANSFER_LENGTH; + p_info->block_count_max = DMAC_BLOCK_COUNT_MAX_LENGTH; + + p_info->block_count_remaining = DMAC_MAX_BLOCK_TRANSFER_LENGTH; + p_info->transfer_length_remaining = (p_ctrl->p_reg->CRTB); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfer and clean up internal data. Implements @ref transfer_api_t::close. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Close (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + /* Disable DMAC transfers on this channel. */ + r_dmac_activation_trigger_disable(p_extend); + + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_CLREN_Msk; + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->CHSTAT_b.TACT, 0); + + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_SWRST_Msk; + + if (p_extend->dmac_int_irq >= 0) + { + R_BSP_IrqDisable(p_extend->dmac_int_irq); + R_FSP_IsrContextSet(p_extend->dmac_int_irq, NULL); + } + + /* Clear ID so control block can be reused. */ + p_ctrl->open = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Make the following transfer settings to continue the transfer. Implements @ref transfer_api_t::reload. + * + * @retval FSP_SUCCESS Successful continuous transfer settings. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + * @retval FSP_ERR_INVALID_MODE This API cannot be called during link mode operation or setting not to use the Next1 register. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reload (transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint32_t const num_transfers) +{ + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + FSP_ASSERT(NULL != p_extend); + FSP_ERROR_RETURN(p_extend->dmac_mode == DMAC_MODE_SELECT_REGISTER, FSP_ERR_INVALID_MODE); +#endif + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + if ((1 == p_ctrl->p_reg->CHSTAT_b.EN) && (0 == p_ctrl->p_reg->CHCFG_b.REN)) + { + p_src_cast = (uint32_t *) p_src; + p_dest_cast = (uint32_t *) p_dest; + if (0 == p_ctrl->p_reg->CHSTAT_b.SR) + { +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = (uint64_t) p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->N1SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->N1DA = (uint32_t) pa; +#else + p_ctrl->p_reg->N1SA = (uintptr_t) p_src_cast; + p_ctrl->p_reg->N1DA = (uintptr_t) p_dest_cast; +#endif + p_ctrl->p_reg->N1TB = num_transfers; + } + else + { +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = (uint64_t) p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->N0SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->N0DA = (uint32_t) pa; +#else + p_ctrl->p_reg->N0SA = (uintptr_t) p_src_cast; + p_ctrl->p_reg->N0DA = (uintptr_t) p_dest_cast; +#endif + p_ctrl->p_reg->N0TB = num_transfers; + } + + p_ctrl->p_reg->CHCFG |= R_DMA_CHCFG_REN_Msk; + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Updates the user callback with the option to provide memory for the callback argument structure. + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_CallbackSet (transfer_ctrl_t * const p_api_ctrl, + void ( * p_callback)(dmac_callback_args_t *), + void const * const p_context, + dmac_callback_args_t * const p_callback_memory) +{ + FSP_PARAMETER_NOT_USED(p_callback_memory); + + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + p_ctrl->p_callback = p_callback; + p_ctrl->p_context = p_context; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup DMAC) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Enable transfers for the channel. + * + * @param[in] p_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_prv_enable (dmac_instance_ctrl_t * p_ctrl) +{ +#if DMAC_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = r_dmac_enable_parameter_checking(p_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + if (p_extend->activation_source) + { + /* DMAC trigger source set. */ + r_dmac_activation_trigger_enable(p_extend); + } + + if (p_extend->dmac_int_irq >= 0) + { + /* Enable transfer end interrupt requests. */ + p_ctrl->p_reg->CHCFG &= ~((uint32_t) R_DMA_CHCFG_DEM_Msk); + + /* Enable the IRQ in the GIC. */ + R_BSP_IrqCfgEnable(p_extend->dmac_int_irq, p_extend->dmac_int_ipl, p_ctrl); + } + else + { + /* Disable transfer end interrupt requests. */ + p_ctrl->p_reg->CHCFG |= R_DMA_CHCFG_DEM_Msk; + } + + /* Resets the channel status register. */ + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_SWRST_Msk; + + /* Enable transfer. */ + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_SETEN_Msk; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfers for the channel. + * + * @param p_ctrl Pointer to the control structure + **********************************************************************************************************************/ +static void r_dmac_prv_disable (dmac_instance_ctrl_t * p_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + /* Disable DMA transfer. */ + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_CLREN_Msk; + + /* Wait DMA stop */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->CHSTAT_b.TACT, 0); + + /* Software Reset */ + p_ctrl->p_reg->CHCTRL = R_DMA_CHCTRL_SWRST_Msk; + + /* Disable DMAC transfers on this channel. */ + r_dmac_activation_trigger_disable(p_extend); + + /* Set DMA transfer end interrupt mask */ + p_ctrl->p_reg->CHCFG |= R_DMA_CHCFG_DEM_Msk; +} + +/*******************************************************************************************************************//** + * Write the transfer info to the hardware registers. + * + * @param[in] p_ctrl Pointer to control structure. + * @param p_info Pointer to transfer info. + **********************************************************************************************************************/ +static void r_dmac_config_transfer_info_register_mode (dmac_instance_ctrl_t * p_ctrl, transfer_info_t * p_info) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + dmac_extended_info_t * p_extend_info = (dmac_extended_info_t *) p_info->p_extend_info; + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + uint32_t dctrl = DMAC_PRV_DCTRL_DEFAULT_VALUE; + uint32_t chcfg = DMAC_PRV_CHCFG_DEFAULT_VALUE; + + /* Disable transfers if they are currently enabled. */ + r_dmac_prv_disable(p_ctrl); + + /* Priority control select */ + dctrl |= ((p_extend->channel_scheduling) & DMAC_PRV_DCTRL_PR_VALUE_MASK) << R_DMA_DCTRL_PR_Pos; + + /* Configure channel */ + chcfg = ((p_extend->channel % 8 & DMAC_PRV_CHCFG_SEL_VALUE_MASK) << R_DMA_CHCFG_SEL_Pos) | + ((p_extend->activation_request_source_select & DMAC_PRV_CHCFG_REQD_VALUE_MASK) << R_DMA_CHCFG_REQD_Pos) | + ((p_extend->detection_mode & DMAC_PRV_CHCFG_DETECT_MODE_VALUE_MASK) << R_DMA_CHCFG_LOEN_Pos) | + ((p_extend->ack_mode & DMAC_PRV_CHCFG_AM_VALUE_MASK) << R_DMA_CHCFG_AM_Pos) | + ((p_extend_info->src_size & DMAC_PRV_CHCFG_SDS_VALUE_MASK) << R_DMA_CHCFG_SDS_Pos) | + ((p_extend_info->dest_size & DMAC_PRV_CHCFG_DDS_VALUE_MASK) << R_DMA_CHCFG_DDS_Pos) | + (((p_info->transfer_settings_word_b.mode & DMAC_PRV_CHCFG_TM_VALUE_MASK) >> DMAC_PRV_CHCFG_TM_VALUE_POS) << + R_DMA_CHCFG_TM_Pos); + if (0 == (p_info->transfer_settings_word_b.src_addr_mode & p_info->transfer_settings_word_b.dest_addr_mode)) + { + /* src or dest address mode is "address fixed mode" */ + if (TRANSFER_ADDR_MODE_FIXED == p_info->transfer_settings_word_b.src_addr_mode) + { + chcfg |= DMAC_PRV_CHCFG_SAD_VALUE_MASK << R_DMA_CHCFG_SAD_Pos; + } + + if (TRANSFER_ADDR_MODE_FIXED == p_info->transfer_settings_word_b.dest_addr_mode) + { + chcfg |= DMAC_PRV_CHCFG_DAD_VALUE_MASK << R_DMA_CHCFG_DAD_Pos; + } + } + + if (DMAC_CONTINUOUS_SETTING_TRANSFER_NEXT0_ONCE != p_extend->continuous_setting) + { + /* Transfer end interrupt mask. */ + chcfg |= R_DMA_CHCFG_DEM_Msk; + + /* Configure Register Set Reverse Select */ + chcfg |= ((p_extend->continuous_setting & DMAC_PRV_NEXT_REG_VALUE_MASK) << R_DMA_CHCFG_RSW_Pos); + } + + if (p_extend->channel < 8) + { + p_reg0_7->DCTRL = dctrl; + } + else + { + p_reg8_15->DCTRL = dctrl; + } + + p_src_cast = (uint32_t *) &p_info->p_src; + p_dest_cast = (uint32_t *) &p_info->p_dest; + + /* Next0 transfer setting. */ +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->N0SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->N0DA = (uint32_t) pa; +#else /* BSP_FEATURE_BSP_HAS_MMU_SUPPORT */ + p_ctrl->p_reg->N0SA = *p_src_cast; + p_ctrl->p_reg->N0DA = *p_dest_cast; +#endif + + p_ctrl->p_reg->N0TB = p_info->length; + + p_ctrl->p_reg->CHCFG = chcfg; + p_ctrl->p_reg->CHITVL = p_extend->transfer_interval; + + if (DMAC_CONTINUOUS_SETTING_TRANSFER_NEXT0_ONCE != p_extend->continuous_setting) + { + dmac_next1_register_setting_t * p_next1_register = p_extend_info->p_next1_register_setting; + + p_src_cast = (uint32_t *) &p_next1_register->p_src; + p_dest_cast = (uint32_t *) &p_next1_register->p_dest; + + /* Next1 transfer setting. */ +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->N1SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->N1DA = (uint32_t) pa; +#else + p_ctrl->p_reg->N1SA = *p_src_cast; + p_ctrl->p_reg->N1DA = *p_dest_cast; +#endif + p_ctrl->p_reg->N1TB = p_next1_register->length; + } +} + +/*******************************************************************************************************************//** + * Set the hardware registers for link mode operation. + * + * @param[in] p_ctrl Pointer to control structure. + **********************************************************************************************************************/ +static void r_dmac_config_transfer_info_link_mode (dmac_instance_ctrl_t * p_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + uint32_t dctrl = DMAC_PRV_DCTRL_DEFAULT_VALUE; + + /* Disable transfers if they are currently enabled. */ + r_dmac_prv_disable(p_ctrl); + + /* Priority control select */ + dctrl |= ((p_extend->channel_scheduling) & DMAC_PRV_DCTRL_PR_VALUE_MASK) << DMAC_PRV_DCTRL_PR_OFFSET; + + if (p_extend->channel < 8) + { + p_reg0_7->DCTRL = dctrl; + } + else + { + p_reg8_15->DCTRL = dctrl; + } + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + + /* Set address of the link destination */ + va = (uint64_t) (p_extend->p_descriptor); + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->NXLA = (uint32_t) pa; +#else + + /* Set address of the link destination */ + p_ctrl->p_reg->NXLA = (uintptr_t) (p_extend->p_descriptor); +#endif + + /* Store current descriptor. */ + p_ctrl->p_descriptor = p_extend->p_descriptor; + + /* Set link mode */ + p_ctrl->p_reg->CHCFG_b.DMS = 1U; +} + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Parameter checking of R_DMAC_Open. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to configuration structure. All elements of the structure must be + * set by user. + * + * @retval FSP_SUCCESS Input Parameters are Valid. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED Callback is NULL and the DMAC IRQ is not enabled. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +static fsp_err_t r_dma_open_parameter_checking (dmac_instance_ctrl_t * const p_ctrl, transfer_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open != DMAC_ID, FSP_ERR_ALREADY_OPEN); + FSP_ASSERT(NULL != p_cfg); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_cfg->p_extend; + dmac_extended_info_t * p_extend_info = (dmac_extended_info_t *) p_cfg->p_info->p_extend_info; + FSP_ASSERT(NULL != p_cfg->p_extend); + FSP_ERROR_RETURN(p_extend->channel < BSP_FEATURE_DMAC_MAX_CHANNEL, FSP_ERR_IP_CHANNEL_NOT_PRESENT); + + if (DMAC_CONTINUOUS_SETTING_TRANSFER_NEXT0_ONCE != p_extend->continuous_setting) + { + FSP_ASSERT(NULL != p_extend_info->p_next1_register_setting); + } + + if (NULL != p_extend->p_callback) + { + FSP_ERROR_RETURN(p_extend->dmac_int_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED); + } + + fsp_err_t err = r_dmac_reconfigure_parameter_checking(p_cfg->p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + if (DMAC_MODE_SELECT_LINK == p_extend->dmac_mode) + { + if (NULL != p_extend->p_descriptor) + { + err = r_dmac_link_descriptor_parameter_checking(p_extend->p_descriptor); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + } + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks for errors in the transfer into structure. + * + * @param[in] p_info Pointer transfer info. + * + * @retval FSP_SUCCESS The transfer info is valid. + * @retval FSP_ERR_ASSERTION A transfer info setting is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_reconfigure_parameter_checking (transfer_info_t const * const p_info) +{ + FSP_ASSERT(p_info != NULL); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks for errors in the transfer link mode descriptor structure. + * + * @param[in] p_descriptor Pointer link mode descriptor. + * + * @retval FSP_SUCCESS The transfer info is valid. + * @retval FSP_ERR_ASSERTION A transfer info setting is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_link_descriptor_parameter_checking (dmac_link_cfg_t const * p_descriptor) +{ + dmac_link_cfg_t const * p_current_descriptor = p_descriptor; + + do + { + /* Start address of the link destination must be 4 byte align. + * (See section 'Next Link Address Register n (NXLA_n)' of the RZ microprocessor manual) */ + FSP_ASSERT(0U == ((uintptr_t) p_current_descriptor & DMAC_PRV_MASK_ALIGN_N_BYTES(DMAC_PRV_MASK_ALIGN_4_BYTES))); + + if (DMAC_LINK_END_ENABLE == p_current_descriptor->header.link_end) + { + break; + } + + #if (BSP_FEATURE_DMAC_64BIT_SYSTEM == 1) + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->next_link_addr); + #else + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->p_next_link_addr); + #endif + } while (NULL != p_current_descriptor); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable. + * + * @param[in] p_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking (dmac_instance_ctrl_t * const p_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + FSP_ASSERT(p_extend != NULL); + + fsp_err_t err = FSP_SUCCESS; + if (DMAC_MODE_SELECT_REGISTER == p_extend->dmac_mode) + { + err = r_dmac_enable_parameter_checking_register_mode(p_ctrl); + } + else if (DMAC_MODE_SELECT_LINK == p_extend->dmac_mode) + { + err = r_dmac_enable_parameter_checking_link_mode(p_ctrl); + } + else + { + /* Do nothing. */ + } + + return err; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable at register mode operation. + * + * @param[in] p_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking_register_mode (dmac_instance_ctrl_t * const p_ctrl) +{ + uint32_t * p_src_cast = (uint32_t *) &p_ctrl->p_reg->N0SA; + uint32_t * p_dest_cast = (uint32_t *) &p_ctrl->p_reg->N0DA; + void const * p_src = (void const *) p_src_cast; + void const * p_dest = (void const *) p_dest_cast; + + /* The source and destination pointers cannot be NULL. */ + FSP_ASSERT(NULL != p_src); + FSP_ASSERT(NULL != p_dest); + + if (1 == p_ctrl->p_reg->CHCFG_b.RSW) + { + void const * p_src_next1; + void const * p_dest_next1; + p_src_cast = (uint32_t *) &p_ctrl->p_reg->N1SA; + p_dest_cast = (uint32_t *) &p_ctrl->p_reg->N1DA; + p_src_next1 = (void const *) p_src_cast; + p_dest_next1 = (void const *) p_dest_cast; + + /* The next1 register set source and destination pointers cannot be NULL. */ + FSP_ASSERT(NULL != p_src_next1); + FSP_ASSERT(NULL != p_dest_next1); + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable at link mode operation. + * + * @param[in] p_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking_link_mode (dmac_instance_ctrl_t * const p_ctrl) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_ASSERT(NULL != p_ctrl->p_descriptor); + + return FSP_SUCCESS; +} + +#endif + +static void r_dmac_activation_trigger_enable (dmac_extended_cfg_t const * const p_extend) +{ + if ((0 == p_extend->channel) || (1 == p_extend->channel)) + { + p_reg_ex->DMARS0 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + p_reg_ex->DMARS0 |= + (uint32_t) ((p_extend->activation_source & DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK) << + (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((2 == p_extend->channel) || (3 == p_extend->channel)) + { + p_reg_ex->DMARS1 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + p_reg_ex->DMARS1 |= + (uint32_t) ((p_extend->activation_source & DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK) << + (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((4 == p_extend->channel) || (5 == p_extend->channel)) + { + p_reg_ex->DMARS2 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + p_reg_ex->DMARS2 |= + (uint32_t) ((p_extend->activation_source & DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK) << + (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((6 == p_extend->channel) || (7 == p_extend->channel)) + { + p_reg_ex->DMARS3 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + p_reg_ex->DMARS3 |= + (uint32_t) ((p_extend->activation_source & DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK) << + (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((8 == p_extend->channel) || (9 == p_extend->channel)) + { + p_reg_ex->DMARS4 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + p_reg_ex->DMARS4 |= + (uint32_t) ((p_extend->activation_source & DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK) << + (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((10 == p_extend->channel) || (11 == p_extend->channel)) + { + p_reg_ex->DMARS5 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + p_reg_ex->DMARS5 |= + (uint32_t) ((p_extend->activation_source & DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK) << + (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((12 == p_extend->channel) || (13 == p_extend->channel)) + { + p_reg_ex->DMARS6 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + p_reg_ex->DMARS6 |= + (uint32_t) ((p_extend->activation_source & DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK) << + (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else + { + p_reg_ex->DMARS7 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + p_reg_ex->DMARS7 |= + (uint32_t) ((p_extend->activation_source & DMAC_PRV_ACTIVATION_SOURCE_VALUE_MASK) << + (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } +} + +static void r_dmac_activation_trigger_disable (dmac_extended_cfg_t const * const p_extend) +{ + if ((0 == p_extend->channel) || (1 == p_extend->channel)) + { + p_reg_ex->DMARS0 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((2 == p_extend->channel) || (3 == p_extend->channel)) + { + p_reg_ex->DMARS1 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((4 == p_extend->channel) || (5 == p_extend->channel)) + { + p_reg_ex->DMARS2 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((6 == p_extend->channel) || (7 == p_extend->channel)) + { + p_reg_ex->DMARS3 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((8 == p_extend->channel) || (9 == p_extend->channel)) + { + p_reg_ex->DMARS4 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((10 == p_extend->channel) || (11 == p_extend->channel)) + { + p_reg_ex->DMARS5 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else if ((12 == p_extend->channel) || (13 == p_extend->channel)) + { + p_reg_ex->DMARS6 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } + else + { + p_reg_ex->DMARS7 &= + (uint32_t) ~(DMAC_PRV_DMARS_MID_RID_MASK << (DMAC_PRV_DMARS_MID_RID_OFFSET * (p_extend->channel % 2))); + } +} + +/*******************************************************************************************************************//** + * DMAC ISR + **********************************************************************************************************************/ +void dmac_int_isr (IRQn_Type const irq) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + if (p_extend->activation_source) + { + /* Activation source disabled */ + if (1 != p_ctrl->p_reg->CHSTAT_b.EN) + { + r_dmac_activation_trigger_disable(p_extend); + } + } + + /* Call the callback routine if one is available */ + if (NULL != p_ctrl->p_callback) + { + dmac_callback_args_t args; + args.p_context = p_ctrl->p_context; + p_ctrl->p_callback(&args); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +/*******************************************************************************************************************//** + * DMAC ERR ISR + **********************************************************************************************************************/ +void dmac_err_isr (IRQn_Type const irq) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + dmac_instance_ctrl_t * p_ctrl = (dmac_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + /* Clear the error bit and software reset. */ + p_ctrl->p_reg->CHCTRL_b.SWRST = 1; + + /* Call user callback */ + if (NULL != p_ctrl->p_callback) + { + dmac_callback_args_t args; + args.p_context = p_ctrl->p_context; + p_ctrl->p_callback(&args); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} diff --git a/drivers/rz/fsp/src/rzn/r_dmac/r_dmac.c b/drivers/rz/fsp/src/rzn/r_dmac/r_dmac.c new file mode 100644 index 00000000..d504c20f --- /dev/null +++ b/drivers/rz/fsp/src/rzn/r_dmac/r_dmac.c @@ -0,0 +1,1533 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_dmac.h" +#include "r_dmac_cfg.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Driver ID (DMAC in ASCII) */ +#define DMAC_ID (0x444d4143) + +/** Byte limited to 2^32-1 byte */ +#define DMAC_BLOCK_MAX_LENGTH (0xFFFFFFFF) +#define DMAC_BLOCK_COUNT_MAX_LENGTH (0xFFFFFFFF) + +#define DMAC_PRV_MASK_ALIGN_2_BYTES (0x1U) +#define DMAC_PRV_MASK_ALIGN_4_BYTES (0x2U) + +/* Calculate the mask bits for byte alignment from the transfer_size_t. */ +#define DMAC_PRV_MASK_ALIGN_N_BYTES(x) ((1U << (x)) - 1U) + +#define DMAC_PRV_REG(unit) ((R_DMAC0_Type *) (((uintptr_t) R_DMAC1 - (uintptr_t) R_DMAC0) * unit + \ + (uintptr_t) R_DMAC0)) + +#define DMAC_PRV_CHANNEL(channel) (channel % 8) +#define DMAC_PRV_GROUP(channel) (channel / 8) + +#if BSP_MCU_GROUP_RZN2H + #define DMAC_PRV_ATCM_END_ADDRESS (0x0007FFFF) + #define DMAC_PRV_BTCM_START_ADDRESS (0x00100000) + #define DMAC_PRV_BTCM_END_ADDRESS (0x0010FFFF) +#elif BSP_MCU_GROUP_RZN2L + #define DMAC_PRV_ATCM_END_ADDRESS (0x0001FFFF) + #define DMAC_PRV_BTCM_START_ADDRESS (0x00100000) + #define DMAC_PRV_BTCM_END_ADDRESS (0x0011FFFF) +#endif + +#define DMAC_PRV_CPU0_TCM_BASE_ADDRESS (0x20000000) +#define DMAC_PRV_CPU1_TCM_BASE_ADDRESS (0x21000000) + +#define DMAC_PRV_DCTRL_DEFAULT_VALUE (0x00000000U) +#define DMAC_PRV_CHCFG_DEFAULT_VALUE (0x00000000U) + +/* Channel Extension Register Bit Field Definitions */ +#define DMAC_PRV_CHEXT_SCA_OFFSET (4U) +#define DMAC_PRV_CHEXT_DCA_OFFSET (12U) + +/* Channel Control Register Bit Field Definitions */ +#define DMAC_PRV_CHCTRL_SETEN_OFFSET (0U) +#define DMAC_PRV_CHCTRL_SETEN_MASK (1U << DMAC_PRV_CHCTRL_SETEN_OFFSET) +#define DMAC_PRV_CHCTRL_CLREN_OFFSET (1U) +#define DMAC_PRV_CHCTRL_CLREN_MASK (1U << DMAC_PRV_CHCTRL_CLREN_OFFSET) +#define DMAC_PRV_CHCTRL_STG_OFFSET (2U) +#define DMAC_PRV_CHCTRL_STG_MASK (1U << DMAC_PRV_CHCTRL_STG_OFFSET) +#define DMAC_PRV_CHCTRL_SWRST_OFFSET (3U) +#define DMAC_PRV_CHCTRL_SWRST_MASK (1U << DMAC_PRV_CHCTRL_SWRST_OFFSET) +#define DMAC_PRV_CHCTRL_CLREND_OFFSET (5U) +#define DMAC_PRV_CHCTRL_CLREND_MASK (1U << DMAC_PRV_CHCTRL_CLREND_OFFSET) +#define DMAC_PRV_CHCTRL_SETSUS_OFFSET (8U) +#define DMAC_PRV_CHCTRL_SETSUS_MASK (1U << DMAC_PRV_CHCTRL_SETSUS_OFFSET) + +/* Channel Configuration Register Bit Field Definitions */ +#define DMAC_PRV_CHCFG_SEL_OFFSET (0U) +#define DMAC_PRV_CHCFG_REQD_OFFSET (3U) +#define DMAC_PRV_CHCFG_LOEN_OFFSET (4U) +#define DMAC_PRV_CHCFG_AM_OFFSET (8U) +#define DMAC_PRV_CHCFG_SDS_OFFSET (12U) +#define DMAC_PRV_CHCFG_SDS_VALUE_MASK (0x0FU) +#define DMAC_PRV_CHCFG_DDS_OFFSET (16U) +#define DMAC_PRV_CHCFG_DDS_VALUE_MASK (0x0FU) +#define DMAC_PRV_CHCFG_SAD_OFFSET (20U) +#define DMAC_PRV_CHCFG_SAD_VALUE_MASK (0x01U) +#define DMAC_PRV_CHCFG_DAD_OFFSET (21U) +#define DMAC_PRV_CHCFG_DAD_VALUE_MASK (0x01U) +#define DMAC_PRV_CHCFG_TM_OFFSET (22U) +#define DMAC_PRV_CHCFG_DEM_OFFSET (24U) +#define DMAC_PRV_CHCFG_DEM_MASK (1U << DMAC_PRV_CHCFG_DEM_OFFSET) +#define DMAC_PRV_CHCFG_RSW_OFFSET (29U) +#define DMAC_PRV_NEXT_REG_VALUE_MASK (0x03U) + +/* DMA Control Register Bit Field Definitions */ +#define DMAC_PRV_DCTRL_PR_OFFSET (0U) +#define DMAC_PRV_DCTRL_PR_VALUE_MASK (0x01U) +#define DMAC_PRV_DCTRL_LVINT_OFFSET (1U) +#define DMAC_PRV_DCTRL_LVINT_VALUE_MASK (0x01U) + +/* DMAC Resource Select Register Bit Field Definitions */ +#define DMAC_PRV_RSSEL_REQ_SEL_OFFSET (10U) +#define DMAC_PRV_RSSEL_REQ_SEL_MASK (0x3FFU) + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +void dmac_int_isr(void); +void dmac_err_int_isr(uint32_t id); + +static fsp_err_t r_dmac_prv_enable(dmac_instance_ctrl_t * p_instance_ctrl); +static void r_dmac_prv_disable(dmac_instance_ctrl_t * p_instance_ctrl); +static void r_dmac_config_transfer_info_register_mode(dmac_instance_ctrl_t * p_instance_ctrl, + transfer_info_t * p_info); +static void r_dmac_config_transfer_info_link_mode(dmac_instance_ctrl_t * p_instance_ctrl); +static uint32_t r_dmac_config_chext(uint32_t src_address, uint32_t dest_address); +static bool r_dmac_address_tcm_check(uint32_t address); + +#if DMAC_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_dma_open_parameter_checking(dmac_instance_ctrl_t * const p_instance_ctrl, + transfer_cfg_t const * const p_cfg); +static fsp_err_t r_dmac_info_paramter_checking(transfer_info_t const * const p_info); +static fsp_err_t r_dmac_link_descriptor_paramter_checking(dmac_link_cfg_t const * p_descriptor); +static fsp_err_t r_dmac_enable_parameter_checking(dmac_instance_ctrl_t * const p_instance_ctrl); +static fsp_err_t r_dmac_enable_parameter_checking_register_mode(dmac_instance_ctrl_t * const p_instance_ctrl); +static fsp_err_t r_dmac_enable_parameter_checking_link_mode(dmac_instance_ctrl_t * const p_instance_ctrl); + +static bool r_dmac_address_tcm_via_axis_check(uint32_t address); + +#endif + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/* Channel control struct array */ +static dmac_instance_ctrl_t * gp_ctrl[BSP_FEATURE_DMAC_MAX_UNIT * BSP_FEATURE_DMAC_MAX_CHANNEL] = {NULL}; + +/** DMAC implementation of transfer API. */ +const transfer_api_t g_transfer_on_dmac = +{ + .open = R_DMAC_Open, + .reconfigure = R_DMAC_Reconfigure, + .reset = R_DMAC_Reset, + .infoGet = R_DMAC_InfoGet, + .softwareStart = R_DMAC_SoftwareStart, + .softwareStop = R_DMAC_SoftwareStop, + .enable = R_DMAC_Enable, + .disable = R_DMAC_Disable, + .reload = R_DMAC_Reload, + .callbackSet = R_DMAC_CallbackSet, + .close = R_DMAC_Close, +}; + +/*******************************************************************************************************************//** + * @addtogroup DMAC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Configure a DMAC channel. + * + * @retval FSP_SUCCESS Successful open. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the activation source is not enabled in the BSP. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Open (transfer_ctrl_t * const p_ctrl, transfer_cfg_t const * const p_cfg) +{ +#if DMAC_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = FSP_SUCCESS; + err = r_dma_open_parameter_checking(p_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_cfg->p_extend; + + p_instance_ctrl->p_cfg = p_cfg; + p_instance_ctrl->p_reg = DMAC_PRV_REG(p_extend->unit); + + /* Configure the transfer settings. */ + if (DMAC_MODE_SELECT_REGISTER == p_extend->dmac_mode) + { + p_instance_ctrl->dmac_mode = DMAC_MODE_SELECT_REGISTER; + r_dmac_config_transfer_info_register_mode(p_instance_ctrl, p_cfg->p_info); + } + else if (DMAC_MODE_SELECT_LINK == p_extend->dmac_mode) + { + p_instance_ctrl->dmac_mode = DMAC_MODE_SELECT_LINK; + r_dmac_config_transfer_info_link_mode(p_instance_ctrl); + } + else + { + /* Do nothing. */ + } + + /* Set callback and context pointers, if configured */ + p_instance_ctrl->p_callback = p_extend->p_callback; + p_instance_ctrl->p_context = p_extend->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + /* Mark driver as open by initializing "DMAC" in its ASCII equivalent.*/ + p_instance_ctrl->open = DMAC_ID; + + /* Track ctrl struct */ + gp_ctrl[(p_extend->unit) * BSP_FEATURE_DMAC_MAX_CHANNEL + (p_extend->channel)] = p_instance_ctrl; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reconfigure the transfer descriptor information with new transfer descriptor. + * + * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_ENABLED DMAC is not enabled. The current configuration must not be valid. + * @retval FSP_ERR_INVALID_MODE DMA mode is register mode. This function can only be used when the DMA mode is link mode. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_LinkDescriptorSet (transfer_ctrl_t * const p_ctrl, dmac_link_cfg_t * p_descriptor) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + + fsp_err_t err = FSP_SUCCESS; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_instance_ctrl != NULL); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + FSP_ASSERT(p_descriptor != NULL); + err = r_dmac_link_descriptor_paramter_checking(p_descriptor); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + +#if defined(BSP_CFG_CORE_CA55) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ERROR_RETURN(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DMS == 1U, FSP_ERR_INVALID_MODE); +#endif + + /* Store current descriptor */ + p_instance_ctrl->p_descriptor = p_descriptor; + +#if defined(BSP_CFG_CORE_CA55) + + /* Set address of the link destination */ + va = (uint64_t) p_descriptor; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].NXLA = (uint32_t) pa; +#else + + /* Set address of the link destination */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].NXLA = (uint32_t) p_descriptor; +#endif + + err = r_dmac_prv_enable(p_instance_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, FSP_ERR_NOT_ENABLED); + + /* Wait descriptor load */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.DL, 0); + + return err; +} + +/*******************************************************************************************************************//** + * Reconfigure the transfer with new transfer info. + * + * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_ENABLED DMAC is not enabled. The current configuration must not be valid. + * @retval FSP_ERR_INVALID_MODE DMA mode is link mode. This function can only be used when the DMA mode is register mode. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reconfigure (transfer_ctrl_t * const p_ctrl, transfer_info_t * p_info) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + + fsp_err_t err = FSP_SUCCESS; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_instance_ctrl != NULL); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + err = r_dmac_info_paramter_checking(p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + FSP_ERROR_RETURN(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DMS == 0U, FSP_ERR_INVALID_MODE); +#endif + + /* Reconfigure the transfer settings. */ + r_dmac_config_transfer_info_register_mode(p_instance_ctrl, p_info); + + err = r_dmac_prv_enable(p_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, FSP_ERR_NOT_ENABLED); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reset transfer source, destination, and number of transfers. + * + * @retval FSP_ERR_UNSUPPORTED API not supported. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reset (transfer_ctrl_t * const p_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(p_src); + FSP_PARAMETER_NOT_USED(p_dest); + FSP_PARAMETER_NOT_USED(num_transfers); + + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Set a transfer request by software. + * + * @retval FSP_SUCCESS Transfer started written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_SoftwareStart (transfer_ctrl_t * const p_ctrl, transfer_start_mode_t mode) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_instance_ctrl->p_cfg); + FSP_ASSERT(NULL != p_instance_ctrl->p_cfg->p_extend); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + FSP_PARAMETER_NOT_USED(mode); + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* Set auto clear bit and software start bit. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_STG_MASK; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Stop software transfers if they were started with TRANSFER_START_MODE_REPEAT. + * + * @retval FSP_ERR_UNSUPPORTED API not supported. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_SoftwareStop (transfer_ctrl_t * const p_ctrl) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Enable transfers for the configured activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Enable (transfer_ctrl_t * const p_ctrl) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + return r_dmac_prv_enable(p_instance_ctrl); +} + +/*******************************************************************************************************************//** + * Disable transfers so that they are no longer triggered by the activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Disable (transfer_ctrl_t * const p_ctrl) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + r_dmac_prv_disable(p_instance_ctrl); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Set driver specific information in provided pointer. + * + * @retval FSP_SUCCESS Information has been written to p_info. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_InfoGet (transfer_ctrl_t * const p_ctrl, transfer_properties_t * const p_info) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + FSP_ASSERT(NULL != p_info); +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + p_info->transfer_length_max = DMAC_MAX_NORMAL_TRANSFER_LENGTH; + p_info->block_count_max = DMAC_BLOCK_COUNT_MAX_LENGTH; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + p_info->block_count_remaining = DMAC_MAX_BLOCK_TRANSFER_LENGTH; + p_info->transfer_length_remaining = (p_instance_ctrl->p_reg->GRP[group].CH[channel].CRTB); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Make the following transfer settings to continue the transfer. + * + * @retval FSP_SUCCESS Successful continuous transfer settings. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + * @retval FSP_ERR_INVALID_MODE This API cannot be called during link mode operation or setting not to use the Next1 register. + * @retval FSP_ERR_INVALID_CALL Invalid call. The series of transfer processing has finished. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reload (transfer_ctrl_t * const p_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint32_t const num_transfers) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(p_instance_ctrl->dmac_mode == DMAC_MODE_SELECT_REGISTER, FSP_ERR_INVALID_MODE); +#endif + +#if defined(BSP_CFG_CORE_CA55) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + + /* Reload API is only available when using both Next0/1 register sets. */ + FSP_ERROR_RETURN(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.RSW == 1, FSP_ERR_INVALID_MODE); +#endif + + fsp_err_t err = FSP_SUCCESS; + + /* Confirm that DMA transaction is in progress and one of the register set transfers has completed. + * Every time a DMA transfer of a register set completes, the REN bit in the CHCFG_n register is cleared to 0 automatically. */ + if ((1 == p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.EN) && + (0 == p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.REN)) + { + p_src_cast = (uint32_t *) p_src; + p_dest_cast = (uint32_t *) p_dest; + + /* Obtain register set currently in use */ + if (1 == p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.SR) + { +#if defined(BSP_CFG_CORE_CA55) + + /* Register set currently in use is the Next1 register. Set the Next0 register for the next transfer. */ + va = (uint64_t) p_src_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = (uint32_t) pa; +#elif ((1 == BSP_CFG_CORE_CR52) && (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA)) + + /* Register set currently in use is the Next1 register. Set the Next0 register for the next transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_dest_cast); +#else + + /* Register set currently in use is the Next1 register. Set the Next0 register for the next transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_dest_cast); +#endif + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].TB = num_transfers; + } + else + { +#if defined(BSP_CFG_CORE_CA55) + + /* Register set currently in use is the Next1 register. Set the Next0 register for the next transfer. */ + va = (uint64_t) p_src_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = (uint32_t) pa; +#elif ((1 == BSP_CFG_CORE_CR52) && (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA)) + + /* Register set currently in use is the Next0 register. Set the Next1 register for the next transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src)) ? + ((uint32_t) p_src + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_src); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest)) ? + ((uint32_t) p_dest + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_dest); +#else + + /* Register set currently in use is the Next0 register. Set the Next1 register for the next transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src)) ? + ((uint32_t) p_src + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_src); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest)) ? + ((uint32_t) p_dest + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_dest); +#endif + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].TB = num_transfers; + } + + /* To perform transfers in series, write 1 to the REN bit in the CHCFG_n register.*/ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.REN = 1; + } + else + { + /* When reloading has been behind return error. */ + err = FSP_ERR_INVALID_CALL; + } + + return err; +} + +/*******************************************************************************************************************//** + * Updates the user callback with the option to provide memory for the callback argument structure. + * Implements @ref transfer_api_t::callbackSet. + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_CallbackSet (transfer_ctrl_t * const p_ctrl, + void ( * p_callback)(transfer_callback_args_t *), + void const * const p_context, + transfer_callback_args_t * const p_callback_memory) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_instance_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(DMAC_ID == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback, context and callback memory */ + p_instance_ctrl->p_callback = p_callback; + p_instance_ctrl->p_context = p_context; + p_instance_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfer and clean up internal data. Implements @ref transfer_api_t::close. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Close (transfer_ctrl_t * const p_ctrl) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* Disable DMAC transfers on this channel. */ + uint32_t rssel_register_num = p_extend->channel / 3; + uint32_t rssel_bit_bum = p_extend->channel % 3; + if (0 == p_extend->unit) + { + R_DMA->DMAC0_RSSEL[rssel_register_num] |= + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + } + else if (1 == p_extend->unit) + { + R_DMA->DMAC1_RSSEL[rssel_register_num] |= + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + } + +#if (3 == BSP_FEATURE_DMAC_MAX_UNIT) + else if (2 == p_extend->unit) + { + R_DMA->DMAC2_RSSEL[rssel_register_num] |= + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + } +#endif + else + { + /* Do nothing */ + } + + /* Disable DMA transfer */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_CLREN_MASK; + + /* Wait DMA stop */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + /* DMA Software Reset. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SWRST_MASK; + + if (NULL != p_extend->p_callback) + { + R_BSP_IrqDisable(p_extend->dmac_int_irq); + R_FSP_IsrContextSet(p_extend->dmac_int_irq, NULL); + } + + /* Clear ID so control block can be reused. */ + p_instance_ctrl->open = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup DMAC) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Enable transfers for the channel. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_prv_enable (dmac_instance_ctrl_t * p_instance_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = r_dmac_enable_parameter_checking(p_instance_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* DMA Software Reset. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SWRST_MASK; + + if (DMAC_MODE_SELECT_REGISTER == p_instance_ctrl->dmac_mode) + { + /* Does not mask DMA transfer end interrupt */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG &= (~((uint32_t) DMAC_PRV_CHCFG_DEM_MASK)); + } + + /* Enable transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SETEN_MASK; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfers for the channel. + * + * @param p_instance_ctrl Pointer to the control structure + **********************************************************************************************************************/ +static void r_dmac_prv_disable (dmac_instance_ctrl_t * p_instance_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* Disable DMA transfer */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_CLREN_MASK; + + /* Wait DMA stop */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + /* DMA Software Reset */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SWRST_MASK; + + if (DMAC_MODE_SELECT_REGISTER == p_instance_ctrl->dmac_mode) + { + /* Set DMA transfer end interrupt mask */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG |= DMAC_PRV_CHCFG_DEM_MASK; + } +} + +/*******************************************************************************************************************//** + * Write the transfer info to the hardware registers for register mode operation. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * @param p_info Pointer to transfer info. + * The structure of this argument will be changed in next major release to reflect the transfer + * API replace. + **********************************************************************************************************************/ +static void r_dmac_config_transfer_info_register_mode (dmac_instance_ctrl_t * p_instance_ctrl, transfer_info_t * p_info) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if defined(BSP_CFG_CORE_CA55) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + uint32_t dctrl = DMAC_PRV_DCTRL_DEFAULT_VALUE; + uint32_t chcfg = DMAC_PRV_CHCFG_DEFAULT_VALUE; + + /* Disable transfers if they are currently enabled. */ + r_dmac_prv_disable(p_instance_ctrl); + + /* Priority control select */ + dctrl |= ((p_extend->channel_scheduling) & DMAC_PRV_DCTRL_PR_VALUE_MASK) << DMAC_PRV_DCTRL_PR_OFFSET; + + /* Configure channel */ + /* Set source and destination size. */ + chcfg |= (uint32_t) p_info->src_size << DMAC_PRV_CHCFG_SDS_OFFSET; + chcfg |= (uint32_t) p_info->dest_size << DMAC_PRV_CHCFG_DDS_OFFSET; + + /* Set source and destination address mode. */ + chcfg |= (uint32_t) p_info->src_addr_mode << DMAC_PRV_CHCFG_SAD_OFFSET; + chcfg |= (uint32_t) p_info->dest_addr_mode << DMAC_PRV_CHCFG_DAD_OFFSET; + + /* Set transfer mode/ */ + chcfg |= (uint32_t) p_info->mode << DMAC_PRV_CHCFG_TM_OFFSET; + + chcfg |= (uint32_t) channel << DMAC_PRV_CHCFG_SEL_OFFSET; + chcfg |= (uint32_t) p_extend->activation_request_source_select << DMAC_PRV_CHCFG_REQD_OFFSET; + chcfg |= (uint32_t) p_extend->detection_mode << DMAC_PRV_CHCFG_LOEN_OFFSET; + chcfg |= (uint32_t) p_extend->ack_mode << DMAC_PRV_CHCFG_AM_OFFSET; + + if (NULL != p_extend->p_callback) + { + /* Enable transfer end interrupt requests. */ + chcfg &= ~((uint32_t) DMAC_PRV_CHCFG_DEM_MASK); + + /* Set Level Output when the DMA interrupt is enabled. */ + dctrl |= (1U & DMAC_PRV_DCTRL_LVINT_VALUE_MASK) << DMAC_PRV_DCTRL_LVINT_OFFSET; + + /* Enable the IRQ in the GIC. */ + R_BSP_IrqDetectTypeSet(p_extend->dmac_int_irq, p_extend->dmac_int_irq_detect_type); + R_BSP_IrqCfgEnable(p_extend->dmac_int_irq, p_extend->dmac_int_ipl, p_instance_ctrl); + } + else + { + /* Set DMA transfer end interrupt mask */ + chcfg |= DMAC_PRV_CHCFG_DEM_MASK; + } + + if (DMAC_REGISTER_SELECT_REVERSE_DISABLE != p_extend->next_register_operation) + { + /* Set DMA transfer end interrupt mask */ + chcfg |= DMAC_PRV_CHCFG_DEM_MASK; + + /* Configure Register Set Reverse Select */ + chcfg |= ((p_extend->next_register_operation & DMAC_PRV_NEXT_REG_VALUE_MASK) << DMAC_PRV_CHCFG_RSW_OFFSET); + } + + uint32_t rssel_register_num = p_extend->channel / 3; + uint32_t rssel_bit_bum = p_extend->channel % 3; + if (0 == p_extend->unit) + { + /* DMAC0 trigger source set. */ + uint32_t rssel = R_DMA->DMAC0_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC0_RSSEL[rssel_register_num] = rssel; + } + else if (1 == p_extend->unit) + { + /* DMAC1 trigger source set. */ + uint32_t rssel = R_DMA->DMAC1_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC1_RSSEL[rssel_register_num] = rssel; + } + +#if (3 == BSP_FEATURE_DMAC_MAX_UNIT) + else if (2 == p_extend->unit) + { + /* DMAC2 trigger source set. */ + uint32_t rssel = R_DMA->DMAC2_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC2_RSSEL[rssel_register_num] = rssel; + } +#endif + else + { + /* Do nothing */ + } + + /* Get the current value of DCTRL.LVINT to avoid overwriting setting of another channel and OR it. */ + dctrl |= (uint32_t) (p_instance_ctrl->p_reg->GRP[group].DCTRL_b.LVINT << DMAC_PRV_DCTRL_LVINT_OFFSET); + + p_instance_ctrl->p_reg->GRP[group].DCTRL = dctrl; + + p_src_cast = (uint32_t *) p_info->p_src; + p_dest_cast = (uint32_t *) p_info->p_dest; + +#if defined(BSP_CFG_CORE_CA55) + va = (uint64_t) p_src_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = (uint32_t) pa; +#elif ((1 == BSP_CFG_CORE_CR52) && (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA)) + + /* When DMAC accesses TCM, use CPU1ATCM(0x21000000 - 0x2107FFFF) / CPU1BTCM(0x21100000 - 0x2110FFFF) area. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_dest_cast); +#else + + /* When DMAC accesses TCM, use CPU0ATCM(0x20000000 - 0x2007FFFF) / CPU0BTCM(0x20100000 - 0x2010FFFF) area. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_dest_cast); +#endif + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].TB = p_info->length; + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG = chcfg; + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHITVL_b.ITVL = p_extend->transfer_interval; + + uint32_t src_address = (uint32_t) (uintptr_t) p_info->p_src; + uint32_t dest_address = (uint32_t) (uintptr_t) p_info->p_dest; + uint32_t chext = r_dmac_config_chext(src_address, dest_address); + + if (DMAC_REGISTER_SELECT_REVERSE_DISABLE != p_extend->next_register_operation) + { + p_src_cast = (uint32_t *) p_info->p_next1_src; + p_dest_cast = (uint32_t *) p_info->p_next1_dest; + +#if defined(BSP_CFG_CORE_CA55) + va = (uint64_t) p_src_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = (uint32_t) pa; +#elif ((1 == BSP_CFG_CORE_CR52) && (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA)) + + /* When DMAC accesses TCM, use CPU0ATCM(0x20000000 - 0x2007FFFF) / CPU0BTCM(0x20100000 - 0x2010FFFF) area. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : + ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : + ((uint32_t) p_dest_cast); +#else + + /* When DMAC accesses TCM, use CPU0ATCM(0x20000000 - 0x2007FFFF) / CPU0BTCM(0x20100000 - 0x2010FFFF) area. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : + ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : + ((uint32_t) p_dest_cast); +#endif + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].TB = p_info->next1_length; + + src_address = (uint32_t) (uintptr_t) p_info->p_next1_src; + dest_address = (uint32_t) (uintptr_t) p_info->p_next1_dest; + + chext |= r_dmac_config_chext(src_address, dest_address); + } + + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHEXT = chext; +} + +/*******************************************************************************************************************//** + * Set the hardware registers for link mode operation. + * + * @param[in] p_instance_ctrl Pointer to control structure. + **********************************************************************************************************************/ +static void r_dmac_config_transfer_info_link_mode (dmac_instance_ctrl_t * p_instance_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + +#if defined(BSP_CFG_CORE_CA55) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + uint32_t dctrl = DMAC_PRV_DCTRL_DEFAULT_VALUE; + + /* Disable transfers if they are currently enabled. */ + r_dmac_prv_disable(p_instance_ctrl); + + /* Priority control select */ + dctrl |= ((p_extend->channel_scheduling) & DMAC_PRV_DCTRL_PR_VALUE_MASK) << DMAC_PRV_DCTRL_PR_OFFSET; + + if (NULL != p_extend->p_callback) + { + /* Set Level Output when the DMA interrupt is enabled. */ + dctrl |= (1U & DMAC_PRV_DCTRL_LVINT_VALUE_MASK) << DMAC_PRV_DCTRL_LVINT_OFFSET; + + /* Enable the IRQ in the GIC. */ + R_BSP_IrqDetectTypeSet(p_extend->dmac_int_irq, p_extend->dmac_int_irq_detect_type); + R_BSP_IrqCfgEnable(p_extend->dmac_int_irq, p_extend->dmac_int_ipl, p_instance_ctrl); + } + + uint32_t rssel_register_num = p_extend->channel / 3; + uint32_t rssel_bit_bum = p_extend->channel % 3; + if (0 == p_extend->unit) + { + /* DMAC0 trigger source set. */ + uint32_t rssel = R_DMA->DMAC0_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC0_RSSEL[rssel_register_num] = rssel; + } + else if (1 == p_extend->unit) + { + /* DMAC1 trigger source set. */ + uint32_t rssel = R_DMA->DMAC1_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC1_RSSEL[rssel_register_num] = rssel; + } + +#if (3 == BSP_FEATURE_DMAC_MAX_UNIT) + else if (2 == p_extend->unit) + { + /* DMAC2 trigger source set. */ + uint32_t rssel = R_DMA->DMAC2_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC2_RSSEL[rssel_register_num] = rssel; + } +#endif + else + { + /* Do nothing */ + } + p_instance_ctrl->p_reg->GRP[group].DCTRL = dctrl; + +#if defined(BSP_CFG_CORE_CA55) + + /* Set address of the link destination */ + va = (uint64_t) (p_extend->p_descriptor); + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].NXLA = (uint32_t) pa; +#else + + /* Set address of the link destination */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].NXLA = (uint32_t) (p_extend->p_descriptor); +#endif + + /* Store current descriptor. */ + p_instance_ctrl->p_descriptor = p_extend->p_descriptor; + + /* Set link mode */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DMS = 1U; +} + +/*******************************************************************************************************************//** + * Determine CHEXT_n register value. + * + * @param[in] src_address Transfer source address + * @param[in] dest_address Transfer destination address + * + * @retval CHEXT_n register value. + **********************************************************************************************************************/ +static uint32_t r_dmac_config_chext (uint32_t src_address, uint32_t dest_address) +{ + uint32_t chext = 0; + + /* The SCA[3:0] bits in CHEXT_n register should be set to 0x02 if source is TCM. + * (see Section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor). + */ + if (true == r_dmac_address_tcm_check(src_address)) + { + chext |= (uint32_t) 0x02 << DMAC_PRV_CHEXT_SCA_OFFSET; + } + + /* The DXA[3:0] bits in CHEXT_n register should be set to 0x02 if destination is TCM. + * (see Section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor). + */ + if (true == r_dmac_address_tcm_check(dest_address)) + { + chext |= (uint32_t) 0x02 << DMAC_PRV_CHEXT_DCA_OFFSET;; + } + + return chext; +} + +/*******************************************************************************************************************//** + * Checks if the address is in the TCM area + * + * @param[in] address Memory address + * + * @retval true if the address is in TCM area, false if not + **********************************************************************************************************************/ +static bool r_dmac_address_tcm_check (uint32_t address) +{ + return (bool) ((address <= DMAC_PRV_ATCM_END_ADDRESS) || + ((DMAC_PRV_BTCM_START_ADDRESS <= address) && (address <= DMAC_PRV_BTCM_END_ADDRESS))); +} + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Parameter checking of R_DMAC_Open. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to configuration structure. All elements of the structure must be + * set by user. + * + * @retval FSP_SUCCESS Input Parameters are Valid. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED Callback is NULL and the DMAC IRQ is not enabled. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +static fsp_err_t r_dma_open_parameter_checking (dmac_instance_ctrl_t * const p_instance_ctrl, + transfer_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open != DMAC_ID, FSP_ERR_ALREADY_OPEN); + FSP_ASSERT(NULL != p_cfg); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_cfg->p_extend; + FSP_ASSERT(NULL != p_cfg->p_extend); + FSP_ERROR_RETURN(p_extend->channel < BSP_FEATURE_DMAC_MAX_CHANNEL, FSP_ERR_IP_CHANNEL_NOT_PRESENT); + + if (NULL != p_extend->p_callback) + { + FSP_ERROR_RETURN(p_extend->dmac_int_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED); + } + + fsp_err_t err = r_dmac_info_paramter_checking(p_cfg->p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + if (DMAC_MODE_SELECT_LINK == p_extend->dmac_mode) + { + if (NULL != p_extend->p_descriptor) + { + err = r_dmac_link_descriptor_paramter_checking(p_extend->p_descriptor); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + } + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks for errors in the transfer into structure. + * + * @param[in] p_info Pointer transfer info. + * + * @retval FSP_SUCCESS The transfer info is valid. + * @retval FSP_ERR_ASSERTION A transfer info setting is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_info_paramter_checking (transfer_info_t const * const p_info) +{ + FSP_ASSERT(p_info != NULL); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks for errors in the transfer link mode descriptor structure. + * + * @param[in] p_descriptor Pointer link mode descriptor. + * + * @retval FSP_SUCCESS The transfer info is valid. + * @retval FSP_ERR_ASSERTION A transfer info setting is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_link_descriptor_paramter_checking (dmac_link_cfg_t const * p_descriptor) +{ + dmac_link_cfg_t const * p_current_descriptor = p_descriptor; + + do + { + /* Start address of the link destination must be 4 byte align. + * (See section 'Next Link Address Register n (NXLA_n)' of the RZ microprocessor manual) */ + FSP_ASSERT(0U == ((uintptr_t) p_current_descriptor & DMAC_PRV_MASK_ALIGN_N_BYTES(DMAC_PRV_MASK_ALIGN_4_BYTES))); + + /* Start address of the link destination must not be in TCM area. + * (See section 'TCM Access via AXIS Interface of Cortex-R52' of the RZ microprocessor manual) */ + FSP_ERROR_RETURN(false == r_dmac_address_tcm_check((uint32_t) (uintptr_t) p_current_descriptor), + FSP_ERR_ASSERTION); + FSP_ERROR_RETURN(false == r_dmac_address_tcm_via_axis_check((uint32_t) (uintptr_t) p_current_descriptor), + FSP_ERR_ASSERTION); + + if (DMAC_LINK_END_ENABLE == p_current_descriptor->header.link_end) + { + break; + } + + #if defined(BSP_CFG_CORE_CA55) + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->next_link_addr); + #else + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->p_next_link_addr); + #endif + } while (NULL != p_current_descriptor); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking (dmac_instance_ctrl_t * const p_instance_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + if (DMAC_MODE_SELECT_REGISTER == p_instance_ctrl->dmac_mode) + { + err = r_dmac_enable_parameter_checking_register_mode(p_instance_ctrl); + } + else if (DMAC_MODE_SELECT_LINK == p_instance_ctrl->dmac_mode) + { + err = r_dmac_enable_parameter_checking_link_mode(p_instance_ctrl); + } + else + { + /* Do nothing. */ + } + + return err; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable at register mode operation. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking_register_mode (dmac_instance_ctrl_t * const p_instance_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + void const * p_src = (void const *) (uintptr_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA; + void const * p_dest = (void const *) (uintptr_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA; + + transfer_size_t src_size = (transfer_size_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.SDS; + transfer_size_t dest_size = (transfer_size_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DDS; + + transfer_addr_mode_t src_addr_mode = + (transfer_addr_mode_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.SAD; + transfer_addr_mode_t dest_addr_mode = + (transfer_addr_mode_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DAD; + + /* When the transfer source address is beat-aligned, specify SAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_src & DMAC_PRV_MASK_ALIGN_N_BYTES(src_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == src_addr_mode); + } + + /* When the transfer destination address is beat-aligned, specify DAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_dest & DMAC_PRV_MASK_ALIGN_N_BYTES(dest_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == dest_addr_mode); + } + + if (1 == p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.RSW) + { + void const * p_src_next1 = (void const *) (uintptr_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA; + void const * p_dest_next1 = (void const *) (uintptr_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA; + + /* The next1 register set source and destination pointers cannot be NULL. */ + FSP_ASSERT(NULL != p_src_next1); + FSP_ASSERT(NULL != p_dest_next1); + + /* When the transfer source address is beat-aligned, specify SAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_src_next1 & DMAC_PRV_MASK_ALIGN_N_BYTES(src_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == src_addr_mode); + } + + /* When the transfer destination address is beat-aligned, specify DAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_dest_next1 & DMAC_PRV_MASK_ALIGN_N_BYTES(dest_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == dest_addr_mode); + } + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable at link mode operation. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking_link_mode (dmac_instance_ctrl_t * const p_instance_ctrl) +{ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_ASSERT(NULL != p_instance_ctrl->p_descriptor); + + dmac_link_cfg_t const * p_current_descriptor = p_instance_ctrl->p_descriptor; + do + { + #if defined(BSP_CFG_CORE_CA55) + void const * p_src = (void *) (uintptr_t) p_current_descriptor->src_addr; + void const * p_dest = (void *) (uintptr_t) p_current_descriptor->dest_addr; + #else + void const * p_src = p_current_descriptor->p_src; + void const * p_dest = p_current_descriptor->p_dest; + #endif + + uint32_t channel_cfg = p_current_descriptor->channel_cfg; + + transfer_size_t src_size = + (transfer_size_t) ((channel_cfg >> DMAC_PRV_CHCFG_SDS_OFFSET) & DMAC_PRV_CHCFG_SDS_VALUE_MASK); + transfer_size_t dest_size = + (transfer_size_t) ((channel_cfg >> DMAC_PRV_CHCFG_DDS_OFFSET) & DMAC_PRV_CHCFG_DDS_VALUE_MASK); + + transfer_addr_mode_t src_addr_mode = + (transfer_addr_mode_t) ((channel_cfg >> DMAC_PRV_CHCFG_SAD_OFFSET) & DMAC_PRV_CHCFG_SAD_VALUE_MASK); + transfer_addr_mode_t dest_addr_mode = + (transfer_addr_mode_t) ((channel_cfg >> DMAC_PRV_CHCFG_DAD_OFFSET) & DMAC_PRV_CHCFG_DAD_VALUE_MASK); + + /* When the transfer source address is beat-aligned, specify SAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_src & DMAC_PRV_MASK_ALIGN_N_BYTES(src_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == src_addr_mode); + } + + /* When the transfer destination address is beat-aligned, specify DAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_dest & DMAC_PRV_MASK_ALIGN_N_BYTES(dest_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == dest_addr_mode); + } + + if (DMAC_LINK_END_ENABLE == p_current_descriptor->header.link_end) + { + break; + } + + #if defined(BSP_CFG_CORE_CA55) + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->next_link_addr); + #else + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->p_next_link_addr); + #endif + } while (NULL != p_current_descriptor); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks if the address is in the TCM via AXIS area + * + * @param[in] address Memory address + * + * @retval true if the address is in TCM via AXIS area, false if not + **********************************************************************************************************************/ +static bool r_dmac_address_tcm_via_axis_check (uint32_t address) +{ + #if (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA) + + return (bool) (((DMAC_PRV_CPU0_TCM_BASE_ADDRESS <= address) && + (address <= (DMAC_PRV_ATCM_END_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS))) || + (((DMAC_PRV_BTCM_START_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) <= address) && + (address <= (DMAC_PRV_BTCM_END_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS))) || + (((DMAC_PRV_CPU1_TCM_BASE_ADDRESS) <= address) && + (address <= (DMAC_PRV_ATCM_END_ADDRESS + DMAC_PRV_CPU1_TCM_BASE_ADDRESS))) || + (((DMAC_PRV_BTCM_START_ADDRESS + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) <= address) && + (address <= (DMAC_PRV_BTCM_END_ADDRESS + DMAC_PRV_CPU1_TCM_BASE_ADDRESS)))); + #elif (0 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA) + + return (bool) (((DMAC_PRV_CPU0_TCM_BASE_ADDRESS <= address) && + (address <= (DMAC_PRV_ATCM_END_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS))) || + (((DMAC_PRV_BTCM_START_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) <= address) && + (address <= (DMAC_PRV_BTCM_END_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS)))); + #endif +} + +#endif + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_instance_ctrl Pointer to DMAC instance control block + * @param[in] event Event code + **********************************************************************************************************************/ +static void r_dmac_call_callback (dmac_instance_ctrl_t * p_instance_ctrl, transfer_event_t event) +{ + transfer_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. */ + transfer_callback_args_t * p_args = p_instance_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->event = event; + p_args->p_context = p_instance_ctrl->p_context; + + p_instance_ctrl->p_callback(p_args); + + if (NULL != p_instance_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_instance_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * DMAC ISR + **********************************************************************************************************************/ +void dmac_int_isr (void) +{ + DMAC_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + dmac_instance_ctrl_t * p_instance_ctrl = R_FSP_IsrContextGet(irq); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* Clear interrupt condition. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_CLREND_MASK; + + /* Dummy read to ensure that interrupt event is cleared. */ + volatile uint32_t dummy = p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL; + FSP_PARAMETER_NOT_USED(dummy); + + /* Invoke the callback function if it is set. */ + if (NULL != p_instance_ctrl->p_callback) + { + r_dmac_call_callback(p_instance_ctrl, TRANSFER_EVENT_TRANSFER_END); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; + + DMAC_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} + +/*******************************************************************************************************************//** + * DMAC ERROR ISR + **********************************************************************************************************************/ +void dmac_err_int_isr (uint32_t id) +{ + DMAC_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + /* Get the DMAC unit where the error occurred from the argument id. */ + uint8_t unit = (uint8_t) (id - BSP_FEATURE_DMAC_UNIT0_ERROR_NUM); + + /* Get the channel error information DSTAT_ER. */ + R_DMAC0_Type * p_base_reg = DMAC_PRV_REG(unit); + uint32_t dstat_err_upper = p_base_reg->GRP[1].DSTAT_ER; + uint32_t dstat_err_lower = p_base_reg->GRP[0].DSTAT_ER; + uint32_t dstat_err_mask = (dstat_err_upper << 8) | dstat_err_lower; + + uint32_t dmac_error_channel = 0; + + /* After going through the event scan, the interrupt handler ends */ + while (dstat_err_mask) + { + /* Scan and search for error factors one by one */ + uint32_t next_err = __CLZ(__RBIT(dstat_err_mask)); + dstat_err_mask >>= next_err; + dmac_error_channel += next_err; + + uint8_t group = (uint8_t) DMAC_PRV_GROUP(dmac_error_channel); + uint8_t channel = (uint8_t) DMAC_PRV_CHANNEL(dmac_error_channel); + + dmac_instance_ctrl_t * p_instance_ctrl = gp_ctrl[unit * BSP_FEATURE_DMAC_MAX_CHANNEL + dmac_error_channel]; + + /* Call user registered callback */ + if (NULL != p_instance_ctrl) + { + /* When DMA transfer error occurred, after set the SWRST bit in the CHCTRL_n register to 1, + * need to set transfer information again. + * (See section 'DMA Error Interrupt' of the RZ microprocessor manual) + * + * Call the callback function after DMAC software reset. + * This allows to reset the transfer information in user callback function.*/ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SWRST_MASK; + + /* Invoke the callback function if it is set. */ + if (NULL != p_instance_ctrl->p_callback) + { + r_dmac_call_callback(p_instance_ctrl, TRANSFER_EVENT_TRANSFER_ERROR); + } + } + + /* Clear the scanned flags one by one */ + dstat_err_mask &= ~(uint32_t) (1UL); + } + + DMAC_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} diff --git a/drivers/rz/fsp/src/rzt/r_dmac/r_dmac.c b/drivers/rz/fsp/src/rzt/r_dmac/r_dmac.c new file mode 100644 index 00000000..e672b1b0 --- /dev/null +++ b/drivers/rz/fsp/src/rzt/r_dmac/r_dmac.c @@ -0,0 +1,1526 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_dmac.h" +#include "r_dmac_cfg.h" + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Driver ID (DMAC in ASCII) */ +#define DMAC_ID (0x444d4143) + +/** Byte limited to 2^32-1 byte */ +#define DMAC_BLOCK_MAX_LENGTH (0xFFFFFFFF) +#define DMAC_BLOCK_COUNT_MAX_LENGTH (0xFFFFFFFF) + +#define DMAC_PRV_MASK_ALIGN_2_BYTES (0x1U) +#define DMAC_PRV_MASK_ALIGN_4_BYTES (0x2U) + +/* Calculate the mask bits for byte alignment from the transfer_size_t. */ +#define DMAC_PRV_MASK_ALIGN_N_BYTES(x) ((1U << (x)) - 1U) + +#define DMAC_PRV_REG(unit) ((R_DMAC0_Type *) (((uintptr_t) R_DMAC1 - (uintptr_t) R_DMAC0) * unit + \ + (uintptr_t) R_DMAC0)) + +#define DMAC_PRV_CHANNEL(channel) (channel % 8) +#define DMAC_PRV_GROUP(channel) (channel / 8) + +#define DMAC_PRV_ATCM_END_ADDRESS (0x0007FFFF) +#define DMAC_PRV_BTCM_START_ADDRESS (0x00100000) +#define DMAC_PRV_BTCM_END_ADDRESS (0x0010FFFF) +#define DMAC_PRV_CPU0_TCM_BASE_ADDRESS (0x20000000) +#define DMAC_PRV_CPU1_TCM_BASE_ADDRESS (0x21000000) + +#define DMAC_PRV_DCTRL_DEFAULT_VALUE (0x00000000U) +#define DMAC_PRV_CHCFG_DEFAULT_VALUE (0x00000000U) + +/* Channel Extension Register Bit Field Definitions */ +#define DMAC_PRV_CHEXT_SCA_OFFSET (4U) +#define DMAC_PRV_CHEXT_DCA_OFFSET (12U) + +/* Channel Control Register Bit Field Definitions */ +#define DMAC_PRV_CHCTRL_SETEN_OFFSET (0U) +#define DMAC_PRV_CHCTRL_SETEN_MASK (1U << DMAC_PRV_CHCTRL_SETEN_OFFSET) +#define DMAC_PRV_CHCTRL_CLREN_OFFSET (1U) +#define DMAC_PRV_CHCTRL_CLREN_MASK (1U << DMAC_PRV_CHCTRL_CLREN_OFFSET) +#define DMAC_PRV_CHCTRL_STG_OFFSET (2U) +#define DMAC_PRV_CHCTRL_STG_MASK (1U << DMAC_PRV_CHCTRL_STG_OFFSET) +#define DMAC_PRV_CHCTRL_SWRST_OFFSET (3U) +#define DMAC_PRV_CHCTRL_SWRST_MASK (1U << DMAC_PRV_CHCTRL_SWRST_OFFSET) +#define DMAC_PRV_CHCTRL_CLREND_OFFSET (5U) +#define DMAC_PRV_CHCTRL_CLREND_MASK (1U << DMAC_PRV_CHCTRL_CLREND_OFFSET) +#define DMAC_PRV_CHCTRL_SETSUS_OFFSET (8U) +#define DMAC_PRV_CHCTRL_SETSUS_MASK (1U << DMAC_PRV_CHCTRL_SETSUS_OFFSET) + +/* Channel Configuration Register Bit Field Definitions */ +#define DMAC_PRV_CHCFG_SEL_OFFSET (0U) +#define DMAC_PRV_CHCFG_REQD_OFFSET (3U) +#define DMAC_PRV_CHCFG_LOEN_OFFSET (4U) +#define DMAC_PRV_CHCFG_AM_OFFSET (8U) +#define DMAC_PRV_CHCFG_SDS_OFFSET (12U) +#define DMAC_PRV_CHCFG_SDS_VALUE_MASK (0x0FU) +#define DMAC_PRV_CHCFG_DDS_OFFSET (16U) +#define DMAC_PRV_CHCFG_DDS_VALUE_MASK (0x0FU) +#define DMAC_PRV_CHCFG_SAD_OFFSET (20U) +#define DMAC_PRV_CHCFG_SAD_VALUE_MASK (0x01U) +#define DMAC_PRV_CHCFG_DAD_OFFSET (21U) +#define DMAC_PRV_CHCFG_DAD_VALUE_MASK (0x01U) +#define DMAC_PRV_CHCFG_TM_OFFSET (22U) +#define DMAC_PRV_CHCFG_DEM_OFFSET (24U) +#define DMAC_PRV_CHCFG_DEM_MASK (1U << DMAC_PRV_CHCFG_DEM_OFFSET) +#define DMAC_PRV_CHCFG_RSW_OFFSET (29U) +#define DMAC_PRV_NEXT_REG_VALUE_MASK (0x03U) + +/* DMA Control Register Bit Field Definitions */ +#define DMAC_PRV_DCTRL_PR_OFFSET (0U) +#define DMAC_PRV_DCTRL_PR_VALUE_MASK (0x01U) +#define DMAC_PRV_DCTRL_LVINT_OFFSET (1U) +#define DMAC_PRV_DCTRL_LVINT_VALUE_MASK (0x01U) + +/* DMAC Resource Select Register Bit Field Definitions */ +#define DMAC_PRV_RSSEL_REQ_SEL_OFFSET (10U) +#define DMAC_PRV_RSSEL_REQ_SEL_MASK (0x3FFU) + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +void dmac_int_isr(void); +void dmac_err_int_isr(uint32_t id); + +static fsp_err_t r_dmac_prv_enable(dmac_instance_ctrl_t * p_instance_ctrl); +static void r_dmac_prv_disable(dmac_instance_ctrl_t * p_instance_ctrl); +static void r_dmac_config_transfer_info_register_mode(dmac_instance_ctrl_t * p_instance_ctrl, + transfer_info_t * p_info); +static void r_dmac_config_transfer_info_link_mode(dmac_instance_ctrl_t * p_instance_ctrl); +static uint32_t r_dmac_config_chext(uint32_t src_address, uint32_t dest_address); +static bool r_dmac_address_tcm_check(uint32_t address); + +#if DMAC_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_dma_open_parameter_checking(dmac_instance_ctrl_t * const p_instance_ctrl, + transfer_cfg_t const * const p_cfg); +static fsp_err_t r_dmac_info_paramter_checking(transfer_info_t const * const p_info); +static fsp_err_t r_dmac_link_descriptor_paramter_checking(dmac_link_cfg_t const * p_descriptor); +static fsp_err_t r_dmac_enable_parameter_checking(dmac_instance_ctrl_t * const p_instance_ctrl); +static fsp_err_t r_dmac_enable_parameter_checking_register_mode(dmac_instance_ctrl_t * const p_instance_ctrl); +static fsp_err_t r_dmac_enable_parameter_checking_link_mode(dmac_instance_ctrl_t * const p_instance_ctrl); + +static bool r_dmac_address_tcm_via_axis_check(uint32_t address); + +#endif + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/* Channel control struct array */ +static dmac_instance_ctrl_t * gp_ctrl[BSP_FEATURE_DMAC_MAX_UNIT * BSP_FEATURE_DMAC_MAX_CHANNEL] = {NULL}; + +/** DMAC implementation of transfer API. */ +const transfer_api_t g_transfer_on_dmac = +{ + .open = R_DMAC_Open, + .reconfigure = R_DMAC_Reconfigure, + .reset = R_DMAC_Reset, + .infoGet = R_DMAC_InfoGet, + .softwareStart = R_DMAC_SoftwareStart, + .softwareStop = R_DMAC_SoftwareStop, + .enable = R_DMAC_Enable, + .disable = R_DMAC_Disable, + .reload = R_DMAC_Reload, + .callbackSet = R_DMAC_CallbackSet, + .close = R_DMAC_Close, +}; + +/*******************************************************************************************************************//** + * @addtogroup DMAC + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Configure a DMAC channel. + * + * @retval FSP_SUCCESS Successful open. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the activation source is not enabled in the BSP. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Open (transfer_ctrl_t * const p_ctrl, transfer_cfg_t const * const p_cfg) +{ +#if DMAC_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = FSP_SUCCESS; + err = r_dma_open_parameter_checking(p_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_cfg->p_extend; + + p_instance_ctrl->p_cfg = p_cfg; + p_instance_ctrl->p_reg = DMAC_PRV_REG(p_extend->unit); + + /* Configure the transfer settings. */ + if (DMAC_MODE_SELECT_REGISTER == p_extend->dmac_mode) + { + p_instance_ctrl->dmac_mode = DMAC_MODE_SELECT_REGISTER; + r_dmac_config_transfer_info_register_mode(p_instance_ctrl, p_cfg->p_info); + } + else if (DMAC_MODE_SELECT_LINK == p_extend->dmac_mode) + { + p_instance_ctrl->dmac_mode = DMAC_MODE_SELECT_LINK; + r_dmac_config_transfer_info_link_mode(p_instance_ctrl); + } + else + { + /* Do nothing. */ + } + + /* Set callback and context pointers, if configured */ + p_instance_ctrl->p_callback = p_extend->p_callback; + p_instance_ctrl->p_context = p_extend->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + /* Mark driver as open by initializing "DMAC" in its ASCII equivalent.*/ + p_instance_ctrl->open = DMAC_ID; + + /* Track ctrl struct */ + gp_ctrl[(p_extend->unit) * BSP_FEATURE_DMAC_MAX_CHANNEL + (p_extend->channel)] = p_instance_ctrl; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reconfigure the transfer descriptor information with new transfer descriptor. + * + * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_ENABLED DMAC is not enabled. The current configuration must not be valid. + * @retval FSP_ERR_INVALID_MODE DMA mode is register mode. This function can only be used when the DMA mode is link mode. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_LinkDescriptorSet (transfer_ctrl_t * const p_ctrl, dmac_link_cfg_t * p_descriptor) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + + fsp_err_t err = FSP_SUCCESS; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_instance_ctrl != NULL); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + FSP_ASSERT(p_descriptor != NULL); + err = r_dmac_link_descriptor_paramter_checking(p_descriptor); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + +#if defined(BSP_CFG_CORE_CA55) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ERROR_RETURN(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DMS == 1U, FSP_ERR_INVALID_MODE); +#endif + + /* Store current descriptor */ + p_instance_ctrl->p_descriptor = p_descriptor; + +#if defined(BSP_CFG_CORE_CA55) + + /* Set address of the link destination */ + va = (uint64_t) p_descriptor; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].NXLA = (uint32_t) pa; +#else + + /* Set address of the link destination */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].NXLA = (uint32_t) p_descriptor; +#endif + + err = r_dmac_prv_enable(p_instance_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, FSP_ERR_NOT_ENABLED); + + /* Wait descriptor load */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.DL, 0); + + return err; +} + +/*******************************************************************************************************************//** + * Reconfigure the transfer with new transfer info. + * + * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_ENABLED DMAC is not enabled. The current configuration must not be valid. + * @retval FSP_ERR_INVALID_MODE DMA mode is link mode. This function can only be used when the DMA mode is register mode. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reconfigure (transfer_ctrl_t * const p_ctrl, transfer_info_t * p_info) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + + fsp_err_t err = FSP_SUCCESS; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_instance_ctrl != NULL); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + err = r_dmac_info_paramter_checking(p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + FSP_ERROR_RETURN(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DMS == 0U, FSP_ERR_INVALID_MODE); +#endif + + /* Reconfigure the transfer settings. */ + r_dmac_config_transfer_info_register_mode(p_instance_ctrl, p_info); + + err = r_dmac_prv_enable(p_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, FSP_ERR_NOT_ENABLED); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reset transfer source, destination, and number of transfers. + * + * @retval FSP_ERR_UNSUPPORTED API not supported. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reset (transfer_ctrl_t * const p_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + FSP_PARAMETER_NOT_USED(p_src); + FSP_PARAMETER_NOT_USED(p_dest); + FSP_PARAMETER_NOT_USED(num_transfers); + + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Set a transfer request by software. + * + * @retval FSP_SUCCESS Transfer started written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_SoftwareStart (transfer_ctrl_t * const p_ctrl, transfer_start_mode_t mode) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_instance_ctrl->p_cfg); + FSP_ASSERT(NULL != p_instance_ctrl->p_cfg->p_extend); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + FSP_PARAMETER_NOT_USED(mode); + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* Set auto clear bit and software start bit. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_STG_MASK; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Stop software transfers if they were started with TRANSFER_START_MODE_REPEAT. + * + * @retval FSP_ERR_UNSUPPORTED API not supported. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_SoftwareStop (transfer_ctrl_t * const p_ctrl) +{ + FSP_PARAMETER_NOT_USED(p_ctrl); + + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * Enable transfers for the configured activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Enable (transfer_ctrl_t * const p_ctrl) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + return r_dmac_prv_enable(p_instance_ctrl); +} + +/*******************************************************************************************************************//** + * Disable transfers so that they are no longer triggered by the activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Disable (transfer_ctrl_t * const p_ctrl) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + r_dmac_prv_disable(p_instance_ctrl); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Set driver specific information in provided pointer. + * + * @retval FSP_SUCCESS Information has been written to p_info. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_InfoGet (transfer_ctrl_t * const p_ctrl, transfer_properties_t * const p_info) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + FSP_ASSERT(NULL != p_info); +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + p_info->transfer_length_max = DMAC_MAX_NORMAL_TRANSFER_LENGTH; + p_info->block_count_max = DMAC_BLOCK_COUNT_MAX_LENGTH; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + p_info->block_count_remaining = DMAC_MAX_BLOCK_TRANSFER_LENGTH; + p_info->transfer_length_remaining = (p_instance_ctrl->p_reg->GRP[group].CH[channel].CRTB); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Make the following transfer settings to continue the transfer. + * + * @retval FSP_SUCCESS Successful continuous transfer settings. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + * @retval FSP_ERR_INVALID_MODE This API cannot be called during link mode operation or setting not to use the Next1 register. + * @retval FSP_ERR_INVALID_CALL Invalid call. The series of transfer processing has finished. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Reload (transfer_ctrl_t * const p_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint32_t const num_transfers) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); + FSP_ERROR_RETURN(p_instance_ctrl->dmac_mode == DMAC_MODE_SELECT_REGISTER, FSP_ERR_INVALID_MODE); +#endif + +#if defined(BSP_CFG_CORE_CA55) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + + /* Reload API is only available when using both Next0/1 register sets. */ + FSP_ERROR_RETURN(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.RSW == 1, FSP_ERR_INVALID_MODE); +#endif + + fsp_err_t err = FSP_SUCCESS; + + /* Confirm that DMA transaction is in progress and one of the register set transfers has completed. + * Every time a DMA transfer of a register set completes, the REN bit in the CHCFG_n register is cleared to 0 automatically. */ + if ((1 == p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.EN) && + (0 == p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.REN)) + { + p_src_cast = (uint32_t *) p_src; + p_dest_cast = (uint32_t *) p_dest; + + /* Obtain register set currently in use */ + if (1 == p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.SR) + { +#if defined(BSP_CFG_CORE_CA55) + + /* Register set currently in use is the Next1 register. Set the Next0 register for the next transfer. */ + va = (uint64_t) p_src_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = (uint32_t) pa; +#elif ((1 == BSP_CFG_CORE_CR52) && (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA)) + + /* Register set currently in use is the Next1 register. Set the Next0 register for the next transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_dest_cast); +#else + + /* Register set currently in use is the Next1 register. Set the Next0 register for the next transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_dest_cast); +#endif + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].TB = num_transfers; + } + else + { +#if defined(BSP_CFG_CORE_CA55) + + /* Register set currently in use is the Next1 register. Set the Next0 register for the next transfer. */ + va = (uint64_t) p_src_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = (uint32_t) pa; +#elif ((1 == BSP_CFG_CORE_CR52) && (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA)) + + /* Register set currently in use is the Next0 register. Set the Next1 register for the next transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src)) ? + ((uint32_t) p_src + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_src); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest)) ? + ((uint32_t) p_dest + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_dest); +#else + + /* Register set currently in use is the Next0 register. Set the Next1 register for the next transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src)) ? + ((uint32_t) p_src + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_src); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest)) ? + ((uint32_t) p_dest + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_dest); +#endif + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].TB = num_transfers; + } + + /* To perform transfers in series, write 1 to the REN bit in the CHCFG_n register.*/ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.REN = 1; + } + else + { + /* When reloading has been behind return error. */ + err = FSP_ERR_INVALID_CALL; + } + + return err; +} + +/*******************************************************************************************************************//** + * Updates the user callback with the option to provide memory for the callback argument structure. + * Implements @ref transfer_api_t::callbackSet. + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_CallbackSet (transfer_ctrl_t * const p_ctrl, + void ( * p_callback)(transfer_callback_args_t *), + void const * const p_context, + transfer_callback_args_t * const p_callback_memory) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_instance_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(DMAC_ID == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback, context and callback memory */ + p_instance_ctrl->p_callback = p_callback; + p_instance_ctrl->p_context = p_context; + p_instance_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfer and clean up internal data. Implements @ref transfer_api_t::close. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_Close (transfer_ctrl_t * const p_ctrl) +{ + dmac_instance_ctrl_t * p_instance_ctrl = (dmac_instance_ctrl_t *) p_ctrl; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open == DMAC_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* Disable DMAC transfers on this channel. */ + uint32_t rssel_register_num = p_extend->channel / 3; + uint32_t rssel_bit_bum = p_extend->channel % 3; + if (0 == p_extend->unit) + { + R_DMA->DMAC0_RSSEL[rssel_register_num] |= + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + } + else if (1 == p_extend->unit) + { + R_DMA->DMAC1_RSSEL[rssel_register_num] |= + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + } + +#if (3 == BSP_FEATURE_DMAC_MAX_UNIT) + else if (2 == p_extend->unit) + { + R_DMA->DMAC2_RSSEL[rssel_register_num] |= + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + } +#endif + else + { + /* Do nothing */ + } + + /* Disable DMA transfer */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_CLREN_MASK; + + /* Wait DMA stop */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + /* DMA Software Reset. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SWRST_MASK; + + if (NULL != p_extend->p_callback) + { + R_BSP_IrqDisable(p_extend->dmac_int_irq); + R_FSP_IsrContextSet(p_extend->dmac_int_irq, NULL); + } + + /* Clear ID so control block can be reused. */ + p_instance_ctrl->open = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup DMAC) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Enable transfers for the channel. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_prv_enable (dmac_instance_ctrl_t * p_instance_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; +#if DMAC_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = r_dmac_enable_parameter_checking(p_instance_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* DMA Software Reset. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SWRST_MASK; + + if (DMAC_MODE_SELECT_REGISTER == p_instance_ctrl->dmac_mode) + { + /* Does not mask DMA transfer end interrupt */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG &= (~((uint32_t) DMAC_PRV_CHCFG_DEM_MASK)); + } + + /* Enable transfer. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SETEN_MASK; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfers for the channel. + * + * @param p_instance_ctrl Pointer to the control structure + **********************************************************************************************************************/ +static void r_dmac_prv_disable (dmac_instance_ctrl_t * p_instance_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* Disable DMA transfer */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_CLREN_MASK; + + /* Wait DMA stop */ + FSP_HARDWARE_REGISTER_WAIT(p_instance_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + /* DMA Software Reset */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SWRST_MASK; + + if (DMAC_MODE_SELECT_REGISTER == p_instance_ctrl->dmac_mode) + { + /* Set DMA transfer end interrupt mask */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG |= DMAC_PRV_CHCFG_DEM_MASK; + } +} + +/*******************************************************************************************************************//** + * Write the transfer info to the hardware registers for register mode operation. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * @param p_info Pointer to transfer info. + * The structure of this argument will be changed in next major release to reflect the transfer + * API replace. + **********************************************************************************************************************/ +static void r_dmac_config_transfer_info_register_mode (dmac_instance_ctrl_t * p_instance_ctrl, transfer_info_t * p_info) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if defined(BSP_CFG_CORE_CA55) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + uint32_t dctrl = DMAC_PRV_DCTRL_DEFAULT_VALUE; + uint32_t chcfg = DMAC_PRV_CHCFG_DEFAULT_VALUE; + + /* Disable transfers if they are currently enabled. */ + r_dmac_prv_disable(p_instance_ctrl); + + /* Priority control select */ + dctrl |= ((p_extend->channel_scheduling) & DMAC_PRV_DCTRL_PR_VALUE_MASK) << DMAC_PRV_DCTRL_PR_OFFSET; + + /* Configure channel */ + /* Set source and destination size. */ + chcfg |= (uint32_t) p_info->src_size << DMAC_PRV_CHCFG_SDS_OFFSET; + chcfg |= (uint32_t) p_info->dest_size << DMAC_PRV_CHCFG_DDS_OFFSET; + + /* Set source and destination address mode. */ + chcfg |= (uint32_t) p_info->src_addr_mode << DMAC_PRV_CHCFG_SAD_OFFSET; + chcfg |= (uint32_t) p_info->dest_addr_mode << DMAC_PRV_CHCFG_DAD_OFFSET; + + /* Set transfer mode/ */ + chcfg |= (uint32_t) p_info->mode << DMAC_PRV_CHCFG_TM_OFFSET; + + chcfg |= (uint32_t) channel << DMAC_PRV_CHCFG_SEL_OFFSET; + chcfg |= (uint32_t) p_extend->activation_request_source_select << DMAC_PRV_CHCFG_REQD_OFFSET; + chcfg |= (uint32_t) p_extend->detection_mode << DMAC_PRV_CHCFG_LOEN_OFFSET; + chcfg |= (uint32_t) p_extend->ack_mode << DMAC_PRV_CHCFG_AM_OFFSET; + + if (NULL != p_extend->p_callback) + { + /* Enable transfer end interrupt requests. */ + chcfg &= ~((uint32_t) DMAC_PRV_CHCFG_DEM_MASK); + + /* Set Level Output when the DMA interrupt is enabled. */ + dctrl |= (1U & DMAC_PRV_DCTRL_LVINT_VALUE_MASK) << DMAC_PRV_DCTRL_LVINT_OFFSET; + + /* Enable the IRQ in the GIC. */ + R_BSP_IrqDetectTypeSet(p_extend->dmac_int_irq, p_extend->dmac_int_irq_detect_type); + R_BSP_IrqCfgEnable(p_extend->dmac_int_irq, p_extend->dmac_int_ipl, p_instance_ctrl); + } + else + { + /* Set DMA transfer end interrupt mask */ + chcfg |= DMAC_PRV_CHCFG_DEM_MASK; + } + + if (DMAC_REGISTER_SELECT_REVERSE_DISABLE != p_extend->next_register_operaion) + { + /* Set DMA transfer end interrupt mask */ + chcfg |= DMAC_PRV_CHCFG_DEM_MASK; + + /* Configure Register Set Reverse Select */ + chcfg |= ((p_extend->next_register_operaion & DMAC_PRV_NEXT_REG_VALUE_MASK) << DMAC_PRV_CHCFG_RSW_OFFSET); + } + + uint32_t rssel_register_num = p_extend->channel / 3; + uint32_t rssel_bit_bum = p_extend->channel % 3; + if (0 == p_extend->unit) + { + /* DMAC0 trigger source set. */ + uint32_t rssel = R_DMA->DMAC0_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC0_RSSEL[rssel_register_num] = rssel; + } + else if (1 == p_extend->unit) + { + /* DMAC1 trigger source set. */ + uint32_t rssel = R_DMA->DMAC1_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC1_RSSEL[rssel_register_num] = rssel; + } + +#if (3 == BSP_FEATURE_DMAC_MAX_UNIT) + else if (2 == p_extend->unit) + { + /* DMAC2 trigger source set. */ + uint32_t rssel = R_DMA->DMAC2_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC2_RSSEL[rssel_register_num] = rssel; + } +#endif + else + { + /* Do nothing */ + } + + /* Get the current value of DCTRL.LVINT to avoid overwriting setting of another channel and OR it. */ + dctrl |= (uint32_t) (p_instance_ctrl->p_reg->GRP[group].DCTRL_b.LVINT << DMAC_PRV_DCTRL_LVINT_OFFSET); + + p_instance_ctrl->p_reg->GRP[group].DCTRL = dctrl; + + p_src_cast = (uint32_t *) p_info->p_src; + p_dest_cast = (uint32_t *) p_info->p_dest; + +#if defined(BSP_CFG_CORE_CA55) + va = (uint64_t) p_src_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = (uint32_t) pa; +#elif ((1 == BSP_CFG_CORE_CR52) && (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA)) + + /* When DMAC accesses TCM, use CPU1ATCM(0x21000000 - 0x2107FFFF) / CPU1BTCM(0x21100000 - 0x2110FFFF) area. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : ((uint32_t) p_dest_cast); +#else + + /* When DMAC accesses TCM, use CPU0ATCM(0x20000000 - 0x2007FFFF) / CPU0BTCM(0x20100000 - 0x2010FFFF) area. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : ((uint32_t) p_dest_cast); +#endif + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].TB = p_info->length; + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG = chcfg; + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHITVL_b.ITVL = p_extend->transfer_interval; + + uint32_t src_address = (uint32_t) (uintptr_t) p_info->p_src; + uint32_t dest_address = (uint32_t) (uintptr_t) p_info->p_dest; + uint32_t chext = r_dmac_config_chext(src_address, dest_address); + + if (DMAC_REGISTER_SELECT_REVERSE_DISABLE != p_extend->next_register_operaion) + { + p_src_cast = (uint32_t *) p_info->p_next1_src; + p_dest_cast = (uint32_t *) p_info->p_next1_dest; + +#if defined(BSP_CFG_CORE_CA55) + va = (uint64_t) p_src_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = (uint32_t) pa; + + va = (uint64_t) p_dest_cast; + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = (uint32_t) pa; +#elif ((1 == BSP_CFG_CORE_CR52) && (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA)) + + /* When DMAC accesses TCM, use CPU0ATCM(0x20000000 - 0x2007FFFF) / CPU0BTCM(0x20100000 - 0x2010FFFF) area. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : + ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) : + ((uint32_t) p_dest_cast); +#else + + /* When DMAC accesses TCM, use CPU0ATCM(0x20000000 - 0x2007FFFF) / CPU0BTCM(0x20100000 - 0x2010FFFF) area. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = + (true == r_dmac_address_tcm_check((uint32_t) p_src_cast)) ? + ((uint32_t) p_src_cast + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : + ((uint32_t) p_src_cast); + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = + (true == r_dmac_address_tcm_check((uint32_t) p_dest_cast)) ? + ((uint32_t) p_dest_cast + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) : + ((uint32_t) p_dest_cast); +#endif + + p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].TB = p_info->next1_length; + + src_address = (uint32_t) (uintptr_t) p_info->p_next1_src; + dest_address = (uint32_t) (uintptr_t) p_info->p_next1_dest; + + chext |= r_dmac_config_chext(src_address, dest_address); + } + + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHEXT = chext; +} + +/*******************************************************************************************************************//** + * Set the hardware registers for link mode operation. + * + * @param[in] p_instance_ctrl Pointer to control structure. + **********************************************************************************************************************/ +static void r_dmac_config_transfer_info_link_mode (dmac_instance_ctrl_t * p_instance_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + +#if defined(BSP_CFG_CORE_CA55) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#endif + + uint32_t dctrl = DMAC_PRV_DCTRL_DEFAULT_VALUE; + + /* Disable transfers if they are currently enabled. */ + r_dmac_prv_disable(p_instance_ctrl); + + /* Priority control select */ + dctrl |= ((p_extend->channel_scheduling) & DMAC_PRV_DCTRL_PR_VALUE_MASK) << DMAC_PRV_DCTRL_PR_OFFSET; + + if (NULL != p_extend->p_callback) + { + /* Set Level Output when the DMA interrupt is enabled. */ + dctrl |= (1U & DMAC_PRV_DCTRL_LVINT_VALUE_MASK) << DMAC_PRV_DCTRL_LVINT_OFFSET; + + /* Enable the IRQ in the GIC. */ + R_BSP_IrqDetectTypeSet(p_extend->dmac_int_irq, p_extend->dmac_int_irq_detect_type); + R_BSP_IrqCfgEnable(p_extend->dmac_int_irq, p_extend->dmac_int_ipl, p_instance_ctrl); + } + + uint32_t rssel_register_num = p_extend->channel / 3; + uint32_t rssel_bit_bum = p_extend->channel % 3; + if (0 == p_extend->unit) + { + /* DMAC0 trigger source set. */ + uint32_t rssel = R_DMA->DMAC0_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC0_RSSEL[rssel_register_num] = rssel; + } + else if (1 == p_extend->unit) + { + /* DMAC1 trigger source set. */ + uint32_t rssel = R_DMA->DMAC1_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC1_RSSEL[rssel_register_num] = rssel; + } + +#if (3 == BSP_FEATURE_DMAC_MAX_UNIT) + else if (2 == p_extend->unit) + { + /* DMAC2 trigger source set. */ + uint32_t rssel = R_DMA->DMAC2_RSSEL[rssel_register_num]; + rssel &= + (uint32_t) ~(DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + rssel |= (ELC_EVENT_NONE != p_extend->activation_source) ? + (uint32_t) ((p_extend->activation_source) << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)) : + (uint32_t) (DMAC_PRV_RSSEL_REQ_SEL_MASK << (DMAC_PRV_RSSEL_REQ_SEL_OFFSET * rssel_bit_bum)); + + R_DMA->DMAC2_RSSEL[rssel_register_num] = rssel; + } +#endif + else + { + /* Do nothing */ + } + p_instance_ctrl->p_reg->GRP[group].DCTRL = dctrl; + +#if defined(BSP_CFG_CORE_CA55) + + /* Set address of the link destination */ + va = (uint64_t) (p_extend->p_descriptor); + R_BSP_MmuVatoPa(va, &pa); + p_instance_ctrl->p_reg->GRP[group].CH[channel].NXLA = (uint32_t) pa; +#else + + /* Set address of the link destination */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].NXLA = (uint32_t) (p_extend->p_descriptor); +#endif + + /* Store current descriptor. */ + p_instance_ctrl->p_descriptor = p_extend->p_descriptor; + + /* Set link mode */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DMS = 1U; +} + +/*******************************************************************************************************************//** + * Determine CHEXT_n register value. + * + * @param[in] src_address Transfer source address + * @param[in] dest_address Transfer destination address + * + * @retval CHEXT_n register value. + **********************************************************************************************************************/ +static uint32_t r_dmac_config_chext (uint32_t src_address, uint32_t dest_address) +{ + uint32_t chext = 0; + + /* The SCA[3:0] bits in CHEXT_n register should be set to 0x02 if source is TCM. + * (see Section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor). + */ + if (true == r_dmac_address_tcm_check(src_address)) + { + chext |= (uint32_t) 0x02 << DMAC_PRV_CHEXT_SCA_OFFSET; + } + + /* The DXA[3:0] bits in CHEXT_n register should be set to 0x02 if destination is TCM. + * (see Section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor). + */ + if (true == r_dmac_address_tcm_check(dest_address)) + { + chext |= (uint32_t) 0x02 << DMAC_PRV_CHEXT_DCA_OFFSET;; + } + + return chext; +} + +/*******************************************************************************************************************//** + * Checks if the address is in the TCM area + * + * @param[in] address Memory address + * + * @retval true if the address is in TCM area, false if not + **********************************************************************************************************************/ +static bool r_dmac_address_tcm_check (uint32_t address) +{ + return (bool) ((address <= DMAC_PRV_ATCM_END_ADDRESS) || + ((DMAC_PRV_BTCM_START_ADDRESS <= address) && (address <= DMAC_PRV_BTCM_END_ADDRESS))); +} + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Parameter checking of R_DMAC_Open. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to configuration structure. All elements of the structure must be + * set by user. + * + * @retval FSP_SUCCESS Input Parameters are Valid. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED Callback is NULL and the DMAC IRQ is not enabled. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +static fsp_err_t r_dma_open_parameter_checking (dmac_instance_ctrl_t * const p_instance_ctrl, + transfer_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(p_instance_ctrl->open != DMAC_ID, FSP_ERR_ALREADY_OPEN); + FSP_ASSERT(NULL != p_cfg); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_cfg->p_extend; + FSP_ASSERT(NULL != p_cfg->p_extend); + FSP_ERROR_RETURN(p_extend->channel < BSP_FEATURE_DMAC_MAX_CHANNEL, FSP_ERR_IP_CHANNEL_NOT_PRESENT); + + if (NULL != p_extend->p_callback) + { + FSP_ERROR_RETURN(p_extend->dmac_int_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED); + } + + fsp_err_t err = r_dmac_info_paramter_checking(p_cfg->p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + if (DMAC_MODE_SELECT_LINK == p_extend->dmac_mode) + { + if (NULL != p_extend->p_descriptor) + { + err = r_dmac_link_descriptor_paramter_checking(p_extend->p_descriptor); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + } + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks for errors in the transfer into structure. + * + * @param[in] p_info Pointer transfer info. + * + * @retval FSP_SUCCESS The transfer info is valid. + * @retval FSP_ERR_ASSERTION A transfer info setting is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_info_paramter_checking (transfer_info_t const * const p_info) +{ + FSP_ASSERT(p_info != NULL); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks for errors in the transfer link mode descriptor structure. + * + * @param[in] p_descriptor Pointer link mode descriptor. + * + * @retval FSP_SUCCESS The transfer info is valid. + * @retval FSP_ERR_ASSERTION A transfer info setting is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_link_descriptor_paramter_checking (dmac_link_cfg_t const * p_descriptor) +{ + dmac_link_cfg_t const * p_current_descriptor = p_descriptor; + + do + { + /* Start address of the link destination must be 4 byte align. + * (See section 'Next Link Address Register n (NXLA_n)' of the RZ microprocessor manual) */ + FSP_ASSERT(0U == ((uintptr_t) p_current_descriptor & DMAC_PRV_MASK_ALIGN_N_BYTES(DMAC_PRV_MASK_ALIGN_4_BYTES))); + + /* Start address of the link destination must not be in TCM area. + * (See section 'TCM Access via AXIS Interface of Cortex-R52' of the RZ microprocessor manual) */ + FSP_ERROR_RETURN(false == r_dmac_address_tcm_check((uint32_t) (uintptr_t) p_current_descriptor), + FSP_ERR_ASSERTION); + FSP_ERROR_RETURN(false == r_dmac_address_tcm_via_axis_check((uint32_t) (uintptr_t) p_current_descriptor), + FSP_ERR_ASSERTION); + + if (DMAC_LINK_END_ENABLE == p_current_descriptor->header.link_end) + { + break; + } + + #if defined(BSP_CFG_CORE_CA55) + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->next_link_addr); + #else + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->p_next_link_addr); + #endif + } while (NULL != p_current_descriptor); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking (dmac_instance_ctrl_t * const p_instance_ctrl) +{ + fsp_err_t err = FSP_SUCCESS; + if (DMAC_MODE_SELECT_REGISTER == p_instance_ctrl->dmac_mode) + { + err = r_dmac_enable_parameter_checking_register_mode(p_instance_ctrl); + } + else if (DMAC_MODE_SELECT_LINK == p_instance_ctrl->dmac_mode) + { + err = r_dmac_enable_parameter_checking_link_mode(p_instance_ctrl); + } + else + { + /* Do nothing. */ + } + + return err; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable at register mode operation. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking_register_mode (dmac_instance_ctrl_t * const p_instance_ctrl) +{ + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + void const * p_src = (void const *) (uintptr_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].SA; + void const * p_dest = (void const *) (uintptr_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].N[0].DA; + + transfer_size_t src_size = (transfer_size_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.SDS; + transfer_size_t dest_size = (transfer_size_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DDS; + + transfer_addr_mode_t src_addr_mode = + (transfer_addr_mode_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.SAD; + transfer_addr_mode_t dest_addr_mode = + (transfer_addr_mode_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.DAD; + + /* When the transfer source address is beat-aligned, specify SAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_src & DMAC_PRV_MASK_ALIGN_N_BYTES(src_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == src_addr_mode); + } + + /* When the transfer destination address is beat-aligned, specify DAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_dest & DMAC_PRV_MASK_ALIGN_N_BYTES(dest_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == dest_addr_mode); + } + + if (1 == p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.RSW) + { + void const * p_src_next1 = (void const *) (uintptr_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].SA; + void const * p_dest_next1 = (void const *) (uintptr_t) p_instance_ctrl->p_reg->GRP[group].CH[channel].N[1].DA; + + /* The next1 register set source and destination pointers cannot be NULL. */ + FSP_ASSERT(NULL != p_src_next1); + FSP_ASSERT(NULL != p_dest_next1); + + /* When the transfer source address is beat-aligned, specify SAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_src_next1 & DMAC_PRV_MASK_ALIGN_N_BYTES(src_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == src_addr_mode); + } + + /* When the transfer destination address is beat-aligned, specify DAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_dest_next1 & DMAC_PRV_MASK_ALIGN_N_BYTES(dest_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == dest_addr_mode); + } + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_prv_enable at link mode operation. + * + * @param[in] p_instance_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_enable_parameter_checking_link_mode (dmac_instance_ctrl_t * const p_instance_ctrl) +{ + FSP_PARAMETER_NOT_USED(p_instance_ctrl); + FSP_ASSERT(NULL != p_instance_ctrl->p_descriptor); + + dmac_link_cfg_t const * p_current_descriptor = p_instance_ctrl->p_descriptor; + do + { + #if defined(BSP_CFG_CORE_CA55) + void const * p_src = (void *) (uintptr_t) p_current_descriptor->src_addr; + void const * p_dest = (void *) (uintptr_t) p_current_descriptor->dest_addr; + #else + void const * p_src = p_current_descriptor->p_src; + void const * p_dest = p_current_descriptor->p_dest; + #endif + + uint32_t channel_cfg = p_current_descriptor->channel_cfg; + + transfer_size_t src_size = + (transfer_size_t) ((channel_cfg >> DMAC_PRV_CHCFG_SDS_OFFSET) & DMAC_PRV_CHCFG_SDS_VALUE_MASK); + transfer_size_t dest_size = + (transfer_size_t) ((channel_cfg >> DMAC_PRV_CHCFG_DDS_OFFSET) & DMAC_PRV_CHCFG_DDS_VALUE_MASK); + + transfer_addr_mode_t src_addr_mode = + (transfer_addr_mode_t) ((channel_cfg >> DMAC_PRV_CHCFG_SAD_OFFSET) & DMAC_PRV_CHCFG_SAD_VALUE_MASK); + transfer_addr_mode_t dest_addr_mode = + (transfer_addr_mode_t) ((channel_cfg >> DMAC_PRV_CHCFG_DAD_OFFSET) & DMAC_PRV_CHCFG_DAD_VALUE_MASK); + + /* When the transfer source address is beat-aligned, specify SAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_src & DMAC_PRV_MASK_ALIGN_N_BYTES(src_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == src_addr_mode); + } + + /* When the transfer destination address is beat-aligned, specify DAD = 0 (increment). + * (See section 'Channel Configuration Register n (CHCFG_n)' of the RZ microprocessor manual) */ + if (0U != ((uintptr_t) p_dest & DMAC_PRV_MASK_ALIGN_N_BYTES(dest_size))) + { + FSP_ASSERT(TRANSFER_ADDR_MODE_INCREMENTED == dest_addr_mode); + } + + if (DMAC_LINK_END_ENABLE == p_current_descriptor->header.link_end) + { + break; + } + + #if defined(BSP_CFG_CORE_CA55) + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->next_link_addr); + #else + p_current_descriptor = (dmac_link_cfg_t *) (uintptr_t) (p_current_descriptor->p_next_link_addr); + #endif + } while (NULL != p_current_descriptor); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks if the address is in the TCM via AXIS area + * + * @param[in] address Memory address + * + * @retval true if the address is in TCM via AXIS area, false if not + **********************************************************************************************************************/ +static bool r_dmac_address_tcm_via_axis_check (uint32_t address) +{ + #if (1 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA) + + return (bool) (((DMAC_PRV_CPU0_TCM_BASE_ADDRESS <= address) && + (address <= (DMAC_PRV_ATCM_END_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS))) || + (((DMAC_PRV_BTCM_START_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) <= address) && + (address <= (DMAC_PRV_BTCM_END_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS))) || + (((DMAC_PRV_CPU1_TCM_BASE_ADDRESS) <= address) && + (address <= (DMAC_PRV_ATCM_END_ADDRESS + DMAC_PRV_CPU1_TCM_BASE_ADDRESS))) || + (((DMAC_PRV_BTCM_START_ADDRESS + DMAC_PRV_CPU1_TCM_BASE_ADDRESS) <= address) && + (address <= (DMAC_PRV_BTCM_END_ADDRESS + DMAC_PRV_CPU1_TCM_BASE_ADDRESS)))); + #elif (0 == BSP_FEATURE_DMAC_HAS_CPU1_TCM_AREA) + + return (bool) (((DMAC_PRV_CPU0_TCM_BASE_ADDRESS <= address) && + (address <= (DMAC_PRV_ATCM_END_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS))) || + (((DMAC_PRV_BTCM_START_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS) <= address) && + (address <= (DMAC_PRV_BTCM_END_ADDRESS + DMAC_PRV_CPU0_TCM_BASE_ADDRESS)))); + #endif +} + +#endif + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_instance_ctrl Pointer to DMAC instance control block + * @param[in] event Event code + **********************************************************************************************************************/ +static void r_dmac_call_callback (dmac_instance_ctrl_t * p_instance_ctrl, transfer_event_t event) +{ + transfer_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. */ + transfer_callback_args_t * p_args = p_instance_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->event = event; + p_args->p_context = p_instance_ctrl->p_context; + + p_instance_ctrl->p_callback(p_args); + + if (NULL != p_instance_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_instance_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * DMAC ISR + **********************************************************************************************************************/ +void dmac_int_isr (void) +{ + DMAC_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE; + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + dmac_instance_ctrl_t * p_instance_ctrl = R_FSP_IsrContextGet(irq); + dmac_extended_cfg_t * p_extend = (dmac_extended_cfg_t *) p_instance_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_PRV_CHANNEL(p_extend->channel); + + /* Clear interrupt condition. */ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_CLREND_MASK; + + /* Dummy read to ensure that interrupt event is cleared. */ + volatile uint32_t dummy = p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL; + FSP_PARAMETER_NOT_USED(dummy); + + /* Invoke the callback function if it is set. */ + if (NULL != p_instance_ctrl->p_callback) + { + r_dmac_call_callback(p_instance_ctrl, TRANSFER_EVENT_TRANSFER_END); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE; + + DMAC_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} + +/*******************************************************************************************************************//** + * DMAC ERROR ISR + **********************************************************************************************************************/ +void dmac_err_int_isr (uint32_t id) +{ + DMAC_CFG_MULTIPLEX_INTERRUPT_ENABLE; + + /* Get the DMAC unit where the error occurred from the argument id. */ + uint8_t unit = (uint8_t) (id - BSP_FEATURE_DMAC_UNIT0_ERROR_NUM); + + /* Get the channel error information DSTAT_ER. */ + R_DMAC0_Type * p_base_reg = DMAC_PRV_REG(unit); + uint32_t dstat_err_upper = p_base_reg->GRP[1].DSTAT_ER; + uint32_t dstat_err_lower = p_base_reg->GRP[0].DSTAT_ER; + uint32_t dstat_err_mask = (dstat_err_upper << 8) | dstat_err_lower; + + uint32_t dmac_error_channel = 0; + + /* After going through the event scan, the interrupt handler ends */ + while (dstat_err_mask) + { + /* Scan and search for error factors one by one */ + uint32_t next_err = __CLZ(__RBIT(dstat_err_mask)); + dstat_err_mask >>= next_err; + dmac_error_channel += next_err; + + uint8_t group = (uint8_t) DMAC_PRV_GROUP(dmac_error_channel); + uint8_t channel = (uint8_t) DMAC_PRV_CHANNEL(dmac_error_channel); + + dmac_instance_ctrl_t * p_instance_ctrl = gp_ctrl[unit * BSP_FEATURE_DMAC_MAX_CHANNEL + dmac_error_channel]; + + /* Call user registered callback */ + if (NULL != p_instance_ctrl) + { + /* When DMA transfer error occurred, after set the SWRST bit in the CHCTRL_n register to 1, + * need to set transfer information again. + * (See section 'DMA Error Interrupt' of the RZ microprocessor manual) + * + * Call the callback function after DMAC software reset. + * This allows to reset the transfer information in user callback function.*/ + p_instance_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = DMAC_PRV_CHCTRL_SWRST_MASK; + + /* Invoke the callback function if it is set. */ + if (NULL != p_instance_ctrl->p_callback) + { + r_dmac_call_callback(p_instance_ctrl, TRANSFER_EVENT_TRANSFER_ERROR); + } + } + + /* Clear the scanned flags one by one */ + dstat_err_mask &= ~(uint32_t) (1UL); + } + + DMAC_CFG_MULTIPLEX_INTERRUPT_DISABLE; +} diff --git a/drivers/rz/fsp/src/rzv/r_dmac_b/r_dmac_b.c b/drivers/rz/fsp/src/rzv/r_dmac_b/r_dmac_b.c new file mode 100644 index 00000000..e0724d4b --- /dev/null +++ b/drivers/rz/fsp/src/rzv/r_dmac_b/r_dmac_b.c @@ -0,0 +1,991 @@ +/* +* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_dmac_b.h" +#include "r_dmac_b_cfg.h" +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + #include "hal_data.h" +#endif + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** Driver ID (DMAC in ASCII) */ +#define DMAC_B_ID (0x444d4143) + +/** Byte limited to 2^32-1 byte */ +#define DMAC_B_BLOCK_MAX_LENGTH (0xFFFFFFFF) +#define DMAC_B_BLOCK_COUNT_MAX_LENGTH (0xFFFFFFFF) + +#define DMAC_B_PRV_CHANNEL(channel) (channel % 8) +#define DMAC_B_PRV_GROUP(channel) (channel / 8) + +#define DMAC_B_PRV_DCTRL_DEFAULT_VALUE (0x00000000U) +#define DMAC_B_PRV_CHCFG_DEFAULT_VALUE (0x00000000U) + +/* Channel Configuration Register Bit Field Definitions */ +#define DMAC_B_PRV_CHCFG_SEL_VALUE_MASK (0x07U) +#define DMAC_B_PRV_CHCFG_REQD_VALUE_MASK (0x01U) +#define DMAC_B_PRV_CHCFG_DETECT_MODE_VALUE_MASK (0x07U) +#define DMAC_B_PRV_CHCFG_AM_VALUE_MASK (0x07U) +#define DMAC_B_PRV_CHCFG_SDS_VALUE_MASK (0x0FU) +#define DMAC_B_PRV_CHCFG_DDS_VALUE_MASK (0x0FU) +#define DMAC_B_PRV_CHCFG_SAD_VALUE_MASK (0x01U) +#define DMAC_B_PRV_CHCFG_DAD_VALUE_MASK (0x01U) +#define DMAC_B_PRV_CHCFG_TM_VALUE_MASK (0x01U) +#define DMAC_B_PRV_NEXT_REG_VALUE_MASK (0x03U) +#define DMAC_B_PRV_ACTIVATION_SOURCE_VALUE_MASK (0xFFFU) + +#define DMAC_B_PRV_ACK_MODE_VALUE_POS (0x10U) +#define DMAC_B_PRV_DETECT_MODE_VALUE_POS (0x18U) + +/* DMA Control Register Bit Field Definitions */ +#define DMAC_B_PRV_DCTRL_PR_OFFSET (0U) +#define DMAC_B_PRV_DCTRL_PR_VALUE_MASK (0x01U) + +/* DMAC Resource Select Register Bit Field Definitions */ +#define DMAC_B_PRV_DMARS_MID_RID_OFFSET (16U) +#define DMAC_B_PRV_DMARS_MID_RID_MASK (0x3FFU) + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +void dmac_b_int_isr(void); +void dmac_b_err_isr(void); + +static fsp_err_t r_dmac_b_prv_enable(dmac_b_instance_ctrl_t * p_ctrl); +static void r_dmac_b_prv_disable(dmac_b_instance_ctrl_t * p_ctrl); +static void r_dmac_b_config_transfer_info(dmac_b_instance_ctrl_t * p_ctrl, transfer_info_t * p_info); +static void r_dmac_b_call_callback (dmac_b_instance_ctrl_t * p_ctrl, transfer_event_t event); + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_dmac_b_open_parameter_checking(dmac_b_instance_ctrl_t * const p_ctrl, + transfer_cfg_t const * const p_cfg); +static fsp_err_t r_dmac_b_info_paramter_checking(transfer_info_t const * const p_info); +static fsp_err_t r_dmac_b_enable_parameter_checking(dmac_b_instance_ctrl_t * const p_ctrl); + +#endif + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/* DMAC_B base address */ +static const uint32_t volatile * p_dmac_b_base_address[BSP_FEATURE_DMAC_MAX_UNIT] = +{ + (uint32_t *) R_DMAC_B0, +#if BSP_FEATURE_DMAC_MAX_UNIT > 1 + (uint32_t *) R_DMAC_B1, + #if BSP_FEATURE_DMAC_MAX_UNIT > 2 + (uint32_t *) R_DMAC_B2, + #if BSP_FEATURE_DMAC_MAX_UNIT > 3 + (uint32_t *) R_DMAC_B3, + #if BSP_FEATURE_DMAC_MAX_UNIT > 4 + (uint32_t *) R_DMAC_B4, + #endif + #endif + #endif +#endif +}; + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** Channel control struct array */ +static dmac_b_instance_ctrl_t * gp_ctrl[BSP_FEATURE_DMAC_MAX_UNIT * BSP_FEATURE_DMAC_MAX_CHANNEL] = {NULL}; + +/** DMAC implementation of transfer API. */ +const transfer_api_t g_transfer_on_dmac_b = +{ + .open = R_DMAC_B_Open, + .reconfigure = R_DMAC_B_Reconfigure, + .reset = R_DMAC_B_Reset, + .infoGet = R_DMAC_B_InfoGet, + .softwareStart = R_DMAC_B_SoftwareStart, + .softwareStop = R_DMAC_B_SoftwareStop, + .enable = R_DMAC_B_Enable, + .disable = R_DMAC_B_Disable, + .close = R_DMAC_B_Close, + .reload = R_DMAC_B_Reload, + .callbackSet = R_DMAC_B_CallbackSet +}; + +/*******************************************************************************************************************//** + * @addtogroup DMAC_B + * @{ + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Configure a DMAC channel. + * + * @retval FSP_SUCCESS Successful open. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the activation source is not enabled in the BSP. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Open (transfer_ctrl_t * const p_api_ctrl, transfer_cfg_t const * const p_cfg) +{ +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = FSP_SUCCESS; + err = r_dmac_b_open_parameter_checking(p_api_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_cfg->p_extend; + + p_ctrl->p_cfg = p_cfg; + p_ctrl->p_reg = (R_DMAC_B0_Type *) p_dmac_b_base_address[p_extend->unit]; + + /* Set callback and context pointers, if configured */ + p_ctrl->p_callback = p_extend->p_callback; + p_ctrl->p_context = p_extend->p_context; + p_ctrl->p_callback_memory = NULL; + + /* Supply clock to DMAC module. */ + R_BSP_MODULE_START(FSP_IP_DMAC, p_extend->unit); + + /* Configure the transfer settings. */ + r_dmac_b_config_transfer_info(p_ctrl, p_cfg->p_info); + + /* Mark driver as open by initializing "DMAC" in its ASCII equivalent.*/ + p_ctrl->open = DMAC_B_ID; + + /* Track ctrl struct */ + gp_ctrl[(p_extend->unit) * BSP_FEATURE_DMAC_MAX_CHANNEL + (p_extend->channel)] = p_ctrl; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reconfigure the transfer with new transfer info. + * + * @retval FSP_SUCCESS Transfer is configured and will start when trigger occurs. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_ENABLED DMAC is not enabled. The current configuration must not be valid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Reconfigure (transfer_ctrl_t * const p_api_ctrl, transfer_info_t * p_info) +{ + fsp_err_t err; + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl != NULL); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); + err = r_dmac_b_info_paramter_checking(p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + FSP_ASSERT(p_ctrl->p_cfg->p_extend != NULL); + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + if (DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE != p_extend->continuous_setting) + { + FSP_ASSERT(NULL != p_info->p_next1_src); + FSP_ASSERT(NULL != p_info->p_next1_dest); + FSP_ASSERT(0 != p_info->next1_length); + } +#endif + + /* Reconfigure the transfer settings. */ + r_dmac_b_config_transfer_info(p_ctrl, p_info); + + /* Enable the transfer configuration. */ + err = r_dmac_b_prv_enable(p_api_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, FSP_ERR_NOT_ENABLED); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Reset transfer source, destination, and number of transfers. + * + * @retval FSP_ERR_UNSUPPORTED API not supported. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Reset (transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint16_t const num_transfers) +{ + FSP_PARAMETER_NOT_USED(p_api_ctrl); + FSP_PARAMETER_NOT_USED(p_src); + FSP_PARAMETER_NOT_USED(p_dest); + FSP_PARAMETER_NOT_USED(num_transfers); + + return FSP_ERR_UNSUPPORTED; +} + +/*******************************************************************************************************************//** + * If the mode is TRANSFER_START_MODE_SINGLE initiate a single transfer with software. If the mode is + * TRANSFER_START_MODE_REPEAT continue triggering transfers until all of the transfers are completed. + * + * @retval FSP_SUCCESS Transfer started written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_SoftwareStart (transfer_ctrl_t * const p_api_ctrl, transfer_start_mode_t mode) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + FSP_PARAMETER_NOT_USED(mode); + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + /* Set auto clear bit and software start bit. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_STG_Msk; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Stop software transfers if they were started with TRANSFER_START_MODE_REPEAT. + * + * @retval FSP_SUCCESS Transfer stopped written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_SoftwareStop (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + /* Set Suspend. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SETSUS_Msk; + + /* Transfer is already stopped. */ + if (!(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT & R_DMAC_B0_GRP_CH_CHSTAT_EN_Msk)) + { + /* Software Reset */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SWRST_Msk; + + return FSP_SUCCESS; + } + + /* Check whether a transfer is suspended. */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.SUS, 1); + + /* Set clear enable and software stop bit. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_CLREN_Msk; + + /* Check whether a transfer is stopped. */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + /* Software Reset */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL_b.SWRST = 1; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Enable transfers for the configured activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Enable (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + return r_dmac_b_prv_enable(p_ctrl); +} + +/*******************************************************************************************************************//** + * Disable transfers so that they are no longer triggered by the activation source. + * + * @retval FSP_SUCCESS Counter value written successfully. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Disable (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + r_dmac_b_prv_disable(p_ctrl); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Set driver specific information in provided pointer. + * + * @retval FSP_SUCCESS Information has been written to p_info. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_InfoGet (transfer_ctrl_t * const p_api_ctrl, transfer_properties_t * const p_info) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); + FSP_ASSERT(NULL != p_info); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + p_info->transfer_length_max = DMAC_B_MAX_NORMAL_TRANSFER_LENGTH; + p_info->block_count_max = DMAC_B_BLOCK_COUNT_MAX_LENGTH; + + p_info->block_count_remaining = DMAC_B_MAX_BLOCK_TRANSFER_LENGTH; + p_info->transfer_length_remaining = (p_ctrl->p_reg->GRP[group].CH[channel].CRTB); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfer and clean up internal data. Implements @ref transfer_api_t::close. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Close (transfer_ctrl_t * const p_api_ctrl) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + /* Disable DMAC transfers on this channel. */ + R_BSP_DMAC_ACTIVATION_SOURCE_DISABLE(p_ctrl->p_reg, p_extend->unit, p_extend->channel); + + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_CLREN_Msk; + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SWRST_Msk; + + if (p_extend->dmac_int_irq >= 0) + { + R_BSP_IrqDisable(p_extend->dmac_int_irq); + R_FSP_IsrContextSet(p_extend->dmac_int_irq, NULL); + } + + /* Clear ID so control block can be reused. */ + p_ctrl->open = 0U; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Make the following transfer settings to continue the transfer. + * + * @retval FSP_SUCCESS Successful continuous transfer settings. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_NOT_OPEN Handle is not initialized. Call R_DMAC_Open to initialize the control block. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_Reload (transfer_ctrl_t * const p_api_ctrl, + void const * volatile p_src, + void * volatile p_dest, + uint32_t const num_transfers) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open == DMAC_B_ID, FSP_ERR_NOT_OPEN); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + uint32_t original_addr; /* Address before conversion */ + uint32_t converted_addr; /* Address after conversion */ +#endif + + if ((1 == p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.EN) && + (0 == p_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.REN)) + { + p_src_cast = (uint32_t *) &p_src; + p_dest_cast = (uint32_t *) &p_dest; + if (0 == p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.SR) + { +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = (uint32_t) pa; +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + original_addr = *p_src_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = converted_addr; + + original_addr = *p_dest_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = converted_addr; +#else + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = *p_src_cast; + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = *p_dest_cast; +#endif + p_ctrl->p_reg->GRP[group].CH[channel].N[1].TB = num_transfers; + } + else + { +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = (uint32_t) pa; +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + original_addr = *p_src_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = converted_addr; + + original_addr = *p_dest_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = converted_addr; +#else + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = *p_src_cast; + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = *p_dest_cast; +#endif + p_ctrl->p_reg->GRP[group].CH[channel].N[0].TB = num_transfers; + } + + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG |= R_DMAC_B0_GRP_CH_CHCFG_REN_Msk; + } + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Updates the user callback with the option to provide memory for the callback argument structure. + * Implements @ref transfer_api_t::callbackSet. + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + **********************************************************************************************************************/ +fsp_err_t R_DMAC_B_CallbackSet (transfer_ctrl_t * const p_api_ctrl, + void ( * p_callback)(dmac_b_callback_args_t *), + void const * const p_context, + dmac_b_callback_args_t * const p_callback_memory) +{ + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) p_api_ctrl; + +#if DMAC_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_instance_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(DMAC_B_ID == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + + /* Store callback, context and callback memory */ + p_ctrl->p_callback = p_callback; + p_ctrl->p_context = p_context; + p_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * @} (end addtogroup DMAC_B) + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Enable transfers for the channel. + * + * @param[in] p_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Successful close. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_b_prv_enable (dmac_b_instance_ctrl_t * p_ctrl) +{ +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = r_dmac_b_enable_parameter_checking(p_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + FSP_CRITICAL_SECTION_DEFINE; + FSP_CRITICAL_SECTION_ENTER; + + /* DMAC trigger source set. */ + R_BSP_DMAC_ACTIVATION_SOURCE_ENABLE(p_ctrl->p_reg, p_extend->unit, p_extend->channel, p_extend->activation_source); + + /* External DMAC REQ trigger set. */ + R_BSP_DMAC_DREQ_DETECT_METHOD_SELECT(p_ctrl->p_reg, + p_extend->channel, + p_extend->external_detection_mode, + p_extend->dreq_input_pin); + + FSP_CRITICAL_SECTION_EXIT; + + if (p_extend->dmac_int_irq >= 0) + { + /* Enable transfer end interrupt requests. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG &= ~((uint32_t) R_DMAC_B0_GRP_CH_CHCFG_DEM_Msk); + + /* Enable the IRQ in the GIC. */ + R_BSP_IrqCfgEnable(p_extend->dmac_int_irq, p_extend->dmac_int_ipl, p_ctrl); + + /* Set detect type of DMAC end interrupt */ + R_BSP_DMAC_B_TRANSFER_END_DETECT_METHOD_SELECT(p_extend->unit, p_extend->channel, 1); + } + else + { + /* Disable transfer end interrupt requests. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG |= R_DMAC_B0_GRP_CH_CHCFG_DEM_Msk; + } + + /* Resets the channel status register. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SWRST_Msk; + + /* Enable transfer. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SETEN_Msk; + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Disable transfers for the channel. + * + * @param p_ctrl Pointer to the control structure + **********************************************************************************************************************/ +static void r_dmac_b_prv_disable (dmac_b_instance_ctrl_t * p_ctrl) +{ + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + /* Disable DMA transfer. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_CLREN_Msk; + + /* Wait DMA stop */ + FSP_HARDWARE_REGISTER_WAIT(p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.TACT, 0); + + /* Software Reset */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_SWRST_Msk; + + /* Disable DMAC transfers on this channel. */ + R_BSP_DMAC_ACTIVATION_SOURCE_DISABLE(p_ctrl->p_reg, p_extend->unit, p_extend->channel); + + /* Set DMA transfer end interrupt mask */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG |= R_DMAC_B0_GRP_CH_CHCFG_DEM_Msk; +} + +/*******************************************************************************************************************//** + * Write the transfer info to the hardware registers. + * + * @param[in] p_ctrl Pointer to control structure. + * @param p_info Pointer to transfer info. + **********************************************************************************************************************/ +static void r_dmac_b_config_transfer_info (dmac_b_instance_ctrl_t * p_ctrl, transfer_info_t * p_info) +{ + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + uint32_t * p_src_cast; + uint32_t * p_dest_cast; + +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + uint64_t pa; /* Physical Address */ + uint64_t va; /* Virtual Address */ +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + uint32_t original_addr; /* Address before conversion */ + uint32_t converted_addr; /* Address after conversion */ +#endif + + uint32_t dctrl = DMAC_B_PRV_DCTRL_DEFAULT_VALUE; + uint32_t chcfg = DMAC_B_PRV_CHCFG_DEFAULT_VALUE; + + /* Disable transfers if they are currently enabled. */ + r_dmac_b_prv_disable(p_ctrl); + + /* Priority control select */ + dctrl |= ((p_extend->channel_scheduling) & DMAC_B_PRV_DCTRL_PR_VALUE_MASK) << R_DMAC_B0_GRP_DCTRL_PR_Pos; + + /* Configure channel */ + chcfg = ((p_extend->channel % 8 & DMAC_B_PRV_CHCFG_SEL_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_SEL_Pos) | + ((p_extend->activation_request_source_select & DMAC_B_PRV_CHCFG_REQD_VALUE_MASK) << + R_DMAC_B0_GRP_CH_CHCFG_REQD_Pos) | + ((p_extend->internal_detection_mode & DMAC_B_PRV_CHCFG_DETECT_MODE_VALUE_MASK) << + R_DMAC_B0_GRP_CH_CHCFG_LOEN_Pos) | + ((p_extend->ack_mode & DMAC_B_PRV_CHCFG_AM_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_AM_Pos) | + ((p_info->src_size & DMAC_B_PRV_CHCFG_SDS_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_SDS_Pos) | + ((p_info->dest_size & DMAC_B_PRV_CHCFG_DDS_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_DDS_Pos) | + ((p_info->src_addr_mode & DMAC_B_PRV_CHCFG_SAD_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_SAD_Pos) | + ((p_info->dest_addr_mode & DMAC_B_PRV_CHCFG_DAD_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_DAD_Pos) | + ((p_info->mode & DMAC_B_PRV_CHCFG_TM_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_TM_Pos); + + /* Set the output destination of the DMAACK signal. */ + R_BSP_DMAC_DACK_OUTPUT_PIN_SET(p_extend->unit, p_extend->channel, p_extend->ack_output_pin); + + /* Set the output destination of the DMATEND signal. */ + R_BSP_DMAC_TEND_OUTPUT_PIN_SET(p_extend->unit, p_extend->channel, p_extend->tend_output_pin); + + if (DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE != p_extend->continuous_setting) + { + /* Transfer end interrupt mask. */ + chcfg |= R_DMAC_B0_GRP_CH_CHCFG_DEM_Msk; + + /* Configure Register Set Reverse Select */ + chcfg |= ((p_extend->continuous_setting & DMAC_B_PRV_NEXT_REG_VALUE_MASK) << R_DMAC_B0_GRP_CH_CHCFG_RSW_Pos); + } + + p_ctrl->p_reg->GRP[group].DCTRL = dctrl; + + p_src_cast = (uint32_t *) &p_info->p_src; + p_dest_cast = (uint32_t *) &p_info->p_dest; + + /* Next0 transfer setting. */ +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = (uint32_t) pa; +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + original_addr = *p_src_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = converted_addr; + + original_addr = *p_dest_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = converted_addr; +#else + p_ctrl->p_reg->GRP[group].CH[channel].N[0].SA = *p_src_cast; + p_ctrl->p_reg->GRP[group].CH[channel].N[0].DA = *p_dest_cast; +#endif + + p_ctrl->p_reg->GRP[group].CH[channel].N[0].TB = p_info->length; + + p_ctrl->p_reg->GRP[group].CH[channel].CHCFG = chcfg; + p_ctrl->p_reg->GRP[group].CH[channel].CHITVL = p_extend->transfer_interval; + + if (DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE != p_extend->continuous_setting) + { + p_src_cast = (uint32_t *) &p_info->p_next1_src; + p_dest_cast = (uint32_t *) &p_info->p_next1_dest; + + /* Next1 transfer setting. */ +#if (BSP_FEATURE_BSP_HAS_MMU_SUPPORT) + va = *p_src_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = (uint32_t) pa; + + va = *p_dest_cast; + R_MMU_VAtoPA(&g_mmu_ctrl, va, (void *) &pa); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = (uint32_t) pa; +#elif (BSP_FEATURE_BSP_SLAVE_ADDRESS_CONVERSION_SUPPORT) + original_addr = *p_src_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = converted_addr; + + original_addr = *p_dest_cast; + converted_addr = R_BSP_SlaveAddressConversion(original_addr); + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = converted_addr; +#else + p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA = *p_src_cast; + p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA = *p_dest_cast; +#endif + p_ctrl->p_reg->GRP[group].CH[channel].N[1].TB = p_info->next1_length; + } +} + +#if DMAC_B_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Parameter checking of R_DMAC_B_Open. + * + * @param[in] p_ctrl Pointer to control structure. + * @param[in] p_cfg Pointer to configuration structure. All elements of the structure must be + * set by user. + * + * @retval FSP_SUCCESS Input Parameters are Valid. + * @retval FSP_ERR_ASSERTION An input parameter is invalid. + * @retval FSP_ERR_IP_CHANNEL_NOT_PRESENT The configured channel is invalid. + * @retval FSP_ERR_IRQ_BSP_DISABLED Callback is NULL and the DMAC IRQ is not enabled. + * @retval FSP_ERR_ALREADY_OPEN The control structure is already opened. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_b_open_parameter_checking (dmac_b_instance_ctrl_t * const p_ctrl, + transfer_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_ctrl); + FSP_ERROR_RETURN(p_ctrl->open != DMAC_B_ID, FSP_ERR_ALREADY_OPEN); + FSP_ASSERT(NULL != p_cfg); + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_cfg->p_extend; + FSP_ASSERT(NULL != p_cfg->p_extend); + FSP_ERROR_RETURN(p_extend->channel < BSP_FEATURE_DMAC_MAX_CHANNEL, FSP_ERR_IP_CHANNEL_NOT_PRESENT); + + if (DMAC_B_CONTINUOUS_SETTING_TRANSFER_ONCE != p_extend->continuous_setting) + { + FSP_ASSERT(NULL != p_cfg->p_info->p_next1_src); + FSP_ASSERT(NULL != p_cfg->p_info->p_next1_dest); + FSP_ASSERT(0 != p_cfg->p_info->next1_length); + } + + if (NULL != p_extend->p_callback) + { + FSP_ERROR_RETURN(p_extend->dmac_int_irq >= 0, FSP_ERR_IRQ_BSP_DISABLED); + } + + fsp_err_t err = r_dmac_b_info_paramter_checking(p_cfg->p_info); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Checks for errors in the transfer into structure. + * + * @param[in] p_info Pointer transfer info. + * + * @retval FSP_SUCCESS The transfer info is valid. + * @retval FSP_ERR_ASSERTION A transfer info setting is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_b_info_paramter_checking (transfer_info_t const * const p_info) +{ + FSP_ASSERT(p_info != NULL); + + return FSP_SUCCESS; +} + +/*******************************************************************************************************************//** + * Parameter checking for r_dmac_b_prv_enable. + * + * @param[in] p_ctrl Pointer to control structure. + * + * @retval FSP_SUCCESS Alignment on source and destination pointers is valid. + * @retval FSP_ERR_ASSERTION The current configuration is invalid. + **********************************************************************************************************************/ +static fsp_err_t r_dmac_b_enable_parameter_checking (dmac_b_instance_ctrl_t * const p_ctrl) +{ + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + uint32_t * p_src_cast = (uint32_t *) &p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA; + uint32_t * p_dest_cast = (uint32_t *) &p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA; + void const * p_src = (void const *) p_src_cast; + void const * p_dest = (void const *) p_dest_cast; + + /* The source and destination pointers cannot be NULL. */ + FSP_ASSERT(NULL != p_src); + FSP_ASSERT(NULL != p_dest); + + if (1 == p_ctrl->p_reg->GRP[group].CH[channel].CHCFG_b.RSW) + { + void const * p_src_next1; + void const * p_dest_next1; + p_src_cast = (uint32_t *) &p_ctrl->p_reg->GRP[group].CH[channel].N[1].SA; + p_dest_cast = (uint32_t *) &p_ctrl->p_reg->GRP[group].CH[channel].N[1].DA; + p_src_next1 = (void const *) p_src_cast; + p_dest_next1 = (void const *) p_dest_cast; + + /* The next1 register set source and destination pointers cannot be NULL. */ + FSP_ASSERT(NULL != p_src_next1); + FSP_ASSERT(NULL != p_dest_next1); + } + + return FSP_SUCCESS; +} + +#endif + +/*******************************************************************************************************************//** + * Calls user callback. + * + * @param[in] p_ctrl Pointer to DMAC instance control block + * @param[in] event Event code + **********************************************************************************************************************/ +static void r_dmac_b_call_callback (dmac_b_instance_ctrl_t * p_ctrl, transfer_event_t event) +{ + dmac_b_callback_args_t args; + + /* Store callback arguments in memory provided by user if available. */ + dmac_b_callback_args_t * p_args = p_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + args = *p_args; + } + + p_args->event = event; + p_args->p_context = p_ctrl->p_context; + + p_ctrl->p_callback(p_args); + + if (NULL != p_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_ctrl->p_callback_memory = args; + } +} + +/*******************************************************************************************************************//** + * DMAC ISR + **********************************************************************************************************************/ +void dmac_b_int_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t group = DMAC_B_PRV_GROUP(p_extend->channel); + uint8_t channel = DMAC_B_PRV_CHANNEL(p_extend->channel); + + if (DMAC_TRIGGER_EVENT_SOFTWARE_TRIGGER != p_extend->activation_source) + { + /* Activation source disabled */ + if (1 != p_ctrl->p_reg->GRP[group].CH[channel].CHSTAT_b.EN) + { + R_BSP_DMAC_ACTIVATION_SOURCE_DISABLE(p_ctrl->p_reg, p_extend->unit, p_extend->channel); + } + } + + /* Clear the DREQ request status. */ + R_BSP_DMAC_DREQ_STATUS_CLEAR(p_extend->dreq_input_pin); + + /* Clear interrupt condition. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL = R_DMAC_B0_GRP_CH_CHCTRL_CLREND_Msk; + + /* Dummy read to ensure that interrupt event is cleared. */ + volatile uint32_t dummy = p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL; + FSP_PARAMETER_NOT_USED(dummy); + + /* Call user callback */ + if (NULL != p_ctrl->p_callback) + { + r_dmac_b_call_callback(p_ctrl, TRANSFER_EVENT_TRANSFER_END); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +/*******************************************************************************************************************//** + * DMAC ERR ISR + **********************************************************************************************************************/ +void dmac_b_err_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + /* Get the DMAC unit where the error occurred from the argument id. */ + IRQn_Type irq = R_FSP_CurrentIrqGet(); + dmac_b_instance_ctrl_t * p_ctrl = (dmac_b_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + dmac_b_extended_cfg_t * p_extend = (dmac_b_extended_cfg_t *) p_ctrl->p_cfg->p_extend; + + uint8_t unit = p_extend->unit; + + /* Get the channel error information DSTAT_ER. */ + R_DMAC_B0_Type * p_base_reg = (R_DMAC_B0_Type *) p_dmac_b_base_address[unit]; + uint32_t dstat_err_upper = p_base_reg->GRP[1].DSTAT_ER; + uint32_t dstat_err_lower = p_base_reg->GRP[0].DSTAT_ER; + uint32_t dstat_err_mask = (dstat_err_upper << 8) | dstat_err_lower; + + uint32_t dmac_error_channel = 0; + + /* After going through the event scan, the interrupt handler ends */ + while (dstat_err_mask) + { + /* Scan and search for error factors one by one */ + uint32_t next_err = __CLZ(__RBIT(dstat_err_mask)); + dstat_err_mask >>= next_err; + dmac_error_channel += next_err; + + uint8_t group = (uint8_t) DMAC_B_PRV_GROUP(dmac_error_channel); + uint8_t channel = (uint8_t) DMAC_B_PRV_CHANNEL(dmac_error_channel); + + p_ctrl = gp_ctrl[unit * BSP_FEATURE_DMAC_MAX_CHANNEL + dmac_error_channel]; + + /* Call user registered callback */ + if (NULL != p_ctrl) + { + /* Clear the error bit and software reset. */ + p_ctrl->p_reg->GRP[group].CH[channel].CHCTRL_b.SWRST = 1; + + /* Invoke the callback function if it is set. */ + if (NULL != p_ctrl->p_callback) + { + /* Call user callback */ + r_dmac_b_call_callback(p_ctrl, TRANSFER_EVENT_TRANSFER_ERROR); + } + } + + /* Clear the scanned flags one by one */ + dstat_err_mask &= ~(1UL); + } + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rza/r_dmac_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rza/r_dmac_cfg.h new file mode 100644 index 00000000..10212204 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rza/r_dmac_cfg.h @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_DMAC_CFG_H_ +#define R_DMAC_CFG_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define DMAC_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) + +#ifdef __cplusplus +} +#endif +#endif /* R_DMAC_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_dmac_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_dmac_cfg.h new file mode 100644 index 00000000..d50a38c8 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzn/r_dmac_cfg.h @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_DMAC_CFG_H_ +#define R_DMAC_CFG_H_ +#define DMAC_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define DMAC_CFG_MULTIPLEX_INTERRUPT_SUPPORTED (0) +#if DMAC_CFG_MULTIPLEX_INTERRUPT_SUPPORTED + #define DMAC_CFG_MULTIPLEX_INTERRUPT_ENABLE BSP_INTERRUPT_ENABLE + #define DMAC_CFG_MULTIPLEX_INTERRUPT_DISABLE BSP_INTERRUPT_DISABLE +#else +#define DMAC_CFG_MULTIPLEX_INTERRUPT_ENABLE +#define DMAC_CFG_MULTIPLEX_INTERRUPT_DISABLE +#endif + +#define DMAC_CFG_CHANNEL_PRIORITY_UNIT0_CHANNEL0_7 (0) +#if BSP_MCU_GROUP_RZN2H + #define DMAC_CFG_CHANNEL_PRIORITY_UNIT0_CHANNEL8_15 (0) +#endif +#define DMAC_CFG_CHANNEL_PRIORITY_UNIT1_CHANNEL0_7 (0) +#if BSP_MCU_GROUP_RZN2H + #define DMAC_CFG_CHANNEL_PRIORITY_UNIT1_CHANNEL8_15 (0) +#endif +#endif /* R_DMAC_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_dmac_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_dmac_cfg.h new file mode 100644 index 00000000..f6d898be --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzt/r_dmac_cfg.h @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_DMAC_CFG_H_ +#define R_DMAC_CFG_H_ +#define DMAC_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#define DMAC_CFG_MULTIPLEX_INTERRUPT_SUPPORTED (0) +#if DMAC_CFG_MULTIPLEX_INTERRUPT_SUPPORTED + #define DMAC_CFG_MULTIPLEX_INTERRUPT_ENABLE BSP_INTERRUPT_ENABLE + #define DMAC_CFG_MULTIPLEX_INTERRUPT_DISABLE BSP_INTERRUPT_DISABLE +#else +#define DMAC_CFG_MULTIPLEX_INTERRUPT_ENABLE +#define DMAC_CFG_MULTIPLEX_INTERRUPT_DISABLE +#endif + +#define DMAC_CFG_CHANNEL_PRIORITY_UNIT0_CHANNEL0_7 (0) +#define DMAC_CFG_CHANNEL_PRIORITY_UNIT0_CHANNEL8_15 (0) +#define DMAC_CFG_CHANNEL_PRIORITY_UNIT1_CHANNEL0_7 (0) +#define DMAC_CFG_CHANNEL_PRIORITY_UNIT1_CHANNEL8_15 (0) +#endif /* R_DMAC_CFG_H_ */ diff --git a/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_dmac_b_cfg.h b/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_dmac_b_cfg.h new file mode 100644 index 00000000..09b79ac3 --- /dev/null +++ b/zephyr/rz/rz_cfg/fsp_cfg/rzv/r_dmac_b_cfg.h @@ -0,0 +1,10 @@ +/* +* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#ifndef R_DMAC_B_CFG_H_ +#define R_DMAC_B_CFG_H_ +#define DMAC_B_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#endif /* R_DMAC_B_CFG_H_ */