1 /*
2 * Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 
7 /***********************************************************************************************************************
8  * Includes
9  **********************************************************************************************************************/
10 #include <string.h>
11 #include "r_dtc.h"
12 
13 /***********************************************************************************************************************
14  * Macro definitions
15  **********************************************************************************************************************/
16 
17 /** Driver ID (DTC in ASCII), used to identify Data Transfer Controller (DTC) configuration  */
18 #define DTC_OPEN                    (0x44544300)
19 
20 /** Size of vector table is based on number of vectors defined in BSP. */
21 #define DTC_VECTOR_TABLE_ENTRIES    (BSP_ICU_VECTOR_MAX_ENTRIES)
22 
23 /** The size of transfer_info_t is defined in the Hardware Manual therefore it must be 16 bytes. */
24 #define DTC_TRANSFER_INFO_SIZE      (16U)
25 
26 /* Compiler specific macro to specify vector table section. */
27 #ifndef DTC_CFG_VECTOR_TABLE_SECTION_NAME
28  #define DTC_SECTION_ATTRIBUTE
29  #ifndef SUPPRESS_WARNING_DTC_CFG_VECTOR_TABLE_SECTION_NAME
30   #warning "DTC vector table is aligned on 1K boundary. Automatic placing could lead to memory holes."
31  #endif
32 #else
33  #define DTC_SECTION_ATTRIBUTE    BSP_PLACE_IN_SECTION(DTC_CFG_VECTOR_TABLE_SECTION_NAME)
34 #endif
35 
36 /* Used to generate a compiler error (divided by 0 error) if the assertion fails.  This is used in place of "#error"
37  * for expressions that cannot be evaluated by the preprocessor like sizeof(). */
38 #define DTC_COMPILE_TIME_ASSERT(e)       ((void) sizeof(char[1 - 2 * !(e)]))
39 
40 /* Calculate the mask bits for byte alignment from the transfer_size_t. */
41 #define DTC_PRV_MASK_ALIGN_N_BYTES(x)    ((1U << (x)) - 1U)
42 
43 /* Counter Register A Lower Byte Mask */
44 #define DTC_PRV_MASK_CRAL             (0xFFU)
45 
46 /* Counter Register A Upper Byte Offset */
47 #define DTC_PRV_OFFSET_CRAH           (8U)
48 
49 /* Offset of in_progress bit in R_DTC->DTCSTS. */
50 #define DTC_PRV_OFFSET_IN_PROGRESS    (15U)
51 
52 /* DTC Control Register RRS Enable value. */
53 #define DTC_PRV_RRS_ENABLE            (0x18)
54 
55 /* DTC Control Register RRS Disable value. */
56 #define DTC_PRV_RRS_DISABLE           (0x08)
57 
58 /***********************************************************************************************************************
59  * Private function prototypes
60  **********************************************************************************************************************/
61 
62 static fsp_err_t r_dtc_prv_enable(dtc_instance_ctrl_t * p_ctrl);
63 static void      r_dtc_state_initialize(void);
64 static void      r_dtc_block_repeat_initialize(transfer_info_t * p_info);
65 static void      r_dtc_set_info(dtc_instance_ctrl_t * p_ctrl, transfer_info_t * p_info);
66 
67 #if DTC_CFG_PARAM_CHECKING_ENABLE
68  #if BSP_CFG_ASSERT != 3
69 static fsp_err_t r_dtc_length_assert(transfer_info_t * p_info);
70 
71  #endif
72 static fsp_err_t r_dtc_source_destination_parameter_check(transfer_info_t * p_info);
73 
74 #endif
75 
76 static void r_dtc_wait_for_transfer_complete(dtc_instance_ctrl_t * p_ctrl);
77 static void r_dtc_disable_transfer(const IRQn_Type irq);
78 
79 /***********************************************************************************************************************
80  * Private global variables
81  **********************************************************************************************************************/
82 
83 static transfer_info_t * gp_dtc_vector_table[DTC_VECTOR_TABLE_ENTRIES] BSP_ALIGN_VARIABLE(1024)
84 DTC_SECTION_ATTRIBUTE;
85 
86 /***********************************************************************************************************************
87  * Exported global variables
88  **********************************************************************************************************************/
89 
90 /** DTC implementation of transfer API. */
91 const transfer_api_t g_transfer_on_dtc =
92 {
93     .open          = R_DTC_Open,
94     .reconfigure   = R_DTC_Reconfigure,
95     .reset         = R_DTC_Reset,
96     .infoGet       = R_DTC_InfoGet,
97     .softwareStart = R_DTC_SoftwareStart,
98     .softwareStop  = R_DTC_SoftwareStop,
99     .enable        = R_DTC_Enable,
100     .disable       = R_DTC_Disable,
101     .reload        = R_DTC_Reload,
102     .callbackSet   = R_DTC_CallbackSet,
103     .close         = R_DTC_Close,
104 };
105 
106 /*******************************************************************************************************************//**
107  * @addtogroup DTC
108  * @{
109  **********************************************************************************************************************/
110 
111 /***********************************************************************************************************************
112  * Functions
113  **********************************************************************************************************************/
114 
115 /*******************************************************************************************************************//**
116  * Configure the vector table if it hasn't been configured, enable the Module and copy the pointer to the transfer info
117  * into the DTC vector table. Implements @ref transfer_api_t::open.
118  *
119  * Example:
120  * @snippet r_dtc_example.c R_DTC_Open
121  *
122  * @retval FSP_SUCCESS              Successful open.
123  *                                      Transfer transfer info pointer copied to DTC Vector table.
124  *                                      Module started.
125  *                                      DTC vector table configured.
126  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
127  * @retval FSP_ERR_UNSUPPORTED      Address Mode Offset is selected.
128  * @retval FSP_ERR_ALREADY_OPEN     The control structure is already opened.
129  * @retval FSP_ERR_IN_USE           The index for this IRQ in the DTC vector table is already configured.
130  * @retval FSP_ERR_IRQ_BSP_DISABLED The IRQ associated with the activation source is not enabled in the BSP.
131  **********************************************************************************************************************/
R_DTC_Open(transfer_ctrl_t * const p_api_ctrl,transfer_cfg_t const * const p_cfg)132 fsp_err_t R_DTC_Open (transfer_ctrl_t * const p_api_ctrl, transfer_cfg_t const * const p_cfg)
133 {
134     /* Generate a compiler error if transfer_info_t is modified. */
135     DTC_COMPILE_TIME_ASSERT(sizeof(transfer_info_t) == DTC_TRANSFER_INFO_SIZE);
136 
137     dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
138 
139 #if DTC_CFG_PARAM_CHECKING_ENABLE
140     FSP_ASSERT(NULL != p_ctrl);
141     FSP_ERROR_RETURN(p_ctrl->open != DTC_OPEN, FSP_ERR_ALREADY_OPEN);
142     FSP_ASSERT(NULL != p_cfg);
143     FSP_ASSERT(NULL != p_cfg->p_extend);
144 #endif
145 
146     /* One time initialization for all DTC instances. */
147     r_dtc_state_initialize();
148 
149     /* Make sure the activation source is mapped in the ICU. */
150     dtc_extended_cfg_t * p_dtc_cfg = (dtc_extended_cfg_t *) p_cfg->p_extend;
151     IRQn_Type            irq       = p_dtc_cfg->activation_source;
152     FSP_ERROR_RETURN(irq >= (IRQn_Type) 0, FSP_ERR_IRQ_BSP_DISABLED);
153 
154     /* Make sure the activation source is not already being used by the DTC. */
155     FSP_ERROR_RETURN(NULL == gp_dtc_vector_table[irq], FSP_ERR_IN_USE);
156 
157     /* irq is used to index the DTC vector table. */
158     p_ctrl->irq = irq;
159 
160     /* Copy p_info into the DTC vector table. */
161     if (p_cfg->p_info)
162     {
163 #if DTC_CFG_PARAM_CHECKING_ENABLE
164         fsp_err_t err = r_dtc_length_assert(p_cfg->p_info);
165         FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
166 #endif
167         r_dtc_set_info(p_ctrl, p_cfg->p_info);
168     }
169 
170     /* Mark driver as open by initializing it to "DTC" in its ASCII equivalent. */
171     p_ctrl->open = DTC_OPEN;
172 
173     return FSP_SUCCESS;
174 }
175 
176 /*******************************************************************************************************************//**
177  * Copy pointer to transfer info into the DTC vector table and enable transfer in ICU.
178  * Implements @ref transfer_api_t::reconfigure.
179  *
180  * @retval FSP_SUCCESS              Transfer is configured and will start when trigger occurs.
181  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
182  * @retval FSP_ERR_NOT_OPEN         Handle is not initialized.  Call R_DTC_Open to initialize the control block.
183  * @retval FSP_ERR_NOT_ENABLED      Transfer source address is NULL or is not aligned correctly.
184  *                                  Transfer destination address is NULL or is not aligned correctly.
185  *
186  * @note p_info must persist until all transfers are completed.
187  **********************************************************************************************************************/
R_DTC_Reconfigure(transfer_ctrl_t * const p_api_ctrl,transfer_info_t * p_info)188 fsp_err_t R_DTC_Reconfigure (transfer_ctrl_t * const p_api_ctrl, transfer_info_t * p_info)
189 {
190     dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
191 
192 #if DTC_CFG_PARAM_CHECKING_ENABLE
193     FSP_ASSERT(NULL != p_ctrl);
194     FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
195     FSP_ASSERT(NULL != p_info);
196     FSP_ASSERT(FSP_SUCCESS == r_dtc_length_assert(p_info));
197 #endif
198 
199     /* Disable transfers on this activation source. */
200     r_dtc_disable_transfer(p_ctrl->irq);
201 
202     /* Wait for current transfer to finish. */
203     r_dtc_wait_for_transfer_complete(p_ctrl);
204 
205     /* Copy p_info into the DTC vector table. */
206     r_dtc_set_info(p_ctrl, p_info);
207 
208     /* This is an exception to FSP Architecture Parameter Checking (May return an error after modifying registers). */
209     /* Enable transfers on this activation source. */
210     FSP_ERROR_RETURN(FSP_SUCCESS == r_dtc_prv_enable(p_ctrl), FSP_ERR_NOT_ENABLED);
211 
212     return FSP_SUCCESS;
213 }
214 
215 /*******************************************************************************************************************//**
216  * Reset transfer source, destination, and number of transfers. Implements @ref transfer_api_t::reset.
217  *
218  * @retval FSP_SUCCESS              Transfer reset successfully (transfers are enabled).
219  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
220  * @retval FSP_ERR_NOT_OPEN         Handle is not initialized.  Call R_DTC_Open to initialize the control block.
221  * @retval FSP_ERR_NOT_ENABLED      Transfer source address is NULL or is not aligned correctly.
222  *                                  Transfer destination address is NULL or is not aligned correctly.
223  **********************************************************************************************************************/
R_DTC_Reset(transfer_ctrl_t * const p_api_ctrl,void const * volatile p_src,void * volatile p_dest,uint16_t const num_transfers)224 fsp_err_t R_DTC_Reset (transfer_ctrl_t * const p_api_ctrl,
225                        void const * volatile   p_src,
226                        void * volatile         p_dest,
227                        uint16_t const          num_transfers)
228 {
229     dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
230 
231 #if DTC_CFG_PARAM_CHECKING_ENABLE
232     FSP_ASSERT(NULL != p_ctrl);
233     FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
234 #endif
235 
236     const IRQn_Type         irq           = p_ctrl->irq;
237     transfer_info_t * const gp_dtc_vector = gp_dtc_vector_table[irq];
238 
239     /* Disable transfers on this activation source. */
240     r_dtc_disable_transfer(irq);
241 
242     /* Wait for current transfer to finish. */
243     r_dtc_wait_for_transfer_complete(p_ctrl);
244 
245     /* Disable read skip prior to modifying settings. It will be enabled later
246      * (See DTC Section 18.4.1 of the RA6M3 manual R01UH0886EJ0100). */
247 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
248     R_DTC->DTCCR_SEC = DTC_PRV_RRS_DISABLE;
249 #else
250     R_DTC->DTCCR = DTC_PRV_RRS_DISABLE;
251 #endif
252 
253     /* Reset transfer based on input parameters. */
254     if (NULL != p_src)
255     {
256         gp_dtc_vector->p_src = p_src;
257     }
258 
259     if (NULL != p_dest)
260     {
261         gp_dtc_vector->p_dest = p_dest;
262     }
263 
264     if (TRANSFER_MODE_BLOCK == gp_dtc_vector->transfer_settings_word_b.mode)
265     {
266         gp_dtc_vector->num_blocks = num_transfers;
267     }
268     else if (TRANSFER_MODE_NORMAL == gp_dtc_vector->transfer_settings_word_b.mode)
269     {
270         gp_dtc_vector->length = num_transfers;
271     }
272     else                               /* TRANSFER_MODE_REPEAT */
273     {
274         /* Do nothing. */
275     }
276 
277     /* Enable read skip after all settings are written. */
278 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
279     R_DTC->DTCCR_SEC = DTC_PRV_RRS_ENABLE;
280 #else
281     R_DTC->DTCCR = DTC_PRV_RRS_ENABLE;
282 #endif
283 
284     /* This is an exception to FSP Architecture Parameter Checking (May return an error after modifying registers). */
285     /* Enable transfers on this activation source. */
286     FSP_ERROR_RETURN(FSP_SUCCESS == r_dtc_prv_enable(p_ctrl), FSP_ERR_NOT_ENABLED);
287 
288     return FSP_SUCCESS;
289 }
290 
291 /*******************************************************************************************************************//**
292  * Placeholder for unsupported softwareStart function. Implements @ref transfer_api_t::softwareStart.
293  *
294  * @retval FSP_ERR_UNSUPPORTED      DTC software start is not supported.
295  **********************************************************************************************************************/
R_DTC_SoftwareStart(transfer_ctrl_t * const p_api_ctrl,transfer_start_mode_t mode)296 fsp_err_t R_DTC_SoftwareStart (transfer_ctrl_t * const p_api_ctrl, transfer_start_mode_t mode)
297 {
298     /* This function isn't supported.  It is defined only to implement a required function of transfer_api_t.
299      * Mark the input parameter as unused since this function isn't supported. */
300     FSP_PARAMETER_NOT_USED(p_api_ctrl);
301     FSP_PARAMETER_NOT_USED(mode);
302 
303     return FSP_ERR_UNSUPPORTED;
304 }
305 
306 /*******************************************************************************************************************//**
307  * Placeholder for unsupported softwareStop function. Implements @ref transfer_api_t::softwareStop.
308  *
309  * @retval FSP_ERR_UNSUPPORTED      DTC software stop is not supported.
310  **********************************************************************************************************************/
R_DTC_SoftwareStop(transfer_ctrl_t * const p_api_ctrl)311 fsp_err_t R_DTC_SoftwareStop (transfer_ctrl_t * const p_api_ctrl)
312 {
313     /* This function isn't supported.  It is defined only to implement a required function of transfer_api_t.
314      * Mark the input parameter as unused since this function isn't supported. */
315     FSP_PARAMETER_NOT_USED(p_api_ctrl);
316 
317     return FSP_ERR_UNSUPPORTED;
318 }
319 
320 /*******************************************************************************************************************//**
321  * Enable transfers on this activation source. Implements @ref transfer_api_t::enable.
322  *
323  * Example:
324  * @snippet r_dtc_example.c R_DTC_Enable
325  *
326  * @retval FSP_SUCCESS              Transfers will be triggered by the activation source
327  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
328  * @retval FSP_ERR_UNSUPPORTED      Address Mode Offset is selected.
329  * @retval FSP_ERR_NOT_OPEN         Handle is not initialized.  Call R_DTC_Open to initialize the control block.
330  **********************************************************************************************************************/
R_DTC_Enable(transfer_ctrl_t * const p_api_ctrl)331 fsp_err_t R_DTC_Enable (transfer_ctrl_t * const p_api_ctrl)
332 {
333     dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
334 #if DTC_CFG_PARAM_CHECKING_ENABLE
335     FSP_ASSERT(NULL != p_ctrl);
336     FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
337 #endif
338 
339     return r_dtc_prv_enable(p_ctrl);
340 }
341 
342 /*******************************************************************************************************************//**
343  * Disable transfer on this activation source. Implements @ref transfer_api_t::disable.
344  *
345  * @retval FSP_SUCCESS              Transfers will not occur on activation events.
346  * @retval FSP_ERR_NOT_OPEN         Handle is not initialized.  Call R_DTC_Open to initialize the control block.
347  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
348  **********************************************************************************************************************/
R_DTC_Disable(transfer_ctrl_t * const p_api_ctrl)349 fsp_err_t R_DTC_Disable (transfer_ctrl_t * const p_api_ctrl)
350 {
351     dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
352 
353 #if DTC_CFG_PARAM_CHECKING_ENABLE
354     FSP_ASSERT(NULL != p_ctrl);
355     FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
356 #endif
357 
358     /* Disable transfer. */
359     r_dtc_disable_transfer(p_ctrl->irq);
360 
361     return FSP_SUCCESS;
362 }
363 
364 /*******************************************************************************************************************//**
365  * Provides information about this transfer. Implements @ref transfer_api_t::infoGet.
366  *
367  * @retval FSP_SUCCESS              p_info updated with current instance information.
368  * @retval FSP_ERR_NOT_OPEN         Handle is not initialized. Call R_DTC_Open to initialize the control block.
369  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
370  **********************************************************************************************************************/
R_DTC_InfoGet(transfer_ctrl_t * const p_api_ctrl,transfer_properties_t * const p_properties)371 fsp_err_t R_DTC_InfoGet (transfer_ctrl_t * const p_api_ctrl, transfer_properties_t * const p_properties)
372 {
373     dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
374 
375 #if DTC_CFG_PARAM_CHECKING_ENABLE
376     FSP_ASSERT(NULL != p_ctrl);
377     FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
378     FSP_ASSERT(NULL != p_properties);
379 #endif
380 
381     transfer_info_t * p_info = gp_dtc_vector_table[p_ctrl->irq];
382 
383     p_properties->block_count_max       = 0U;
384     p_properties->block_count_remaining = 0U;
385 
386     if (TRANSFER_MODE_NORMAL != p_info->transfer_settings_word_b.mode)
387     {
388         /* Repeat and Block Mode */
389 
390         /* transfer_length_max is the same for Block and repeat mode. */
391         p_properties->transfer_length_max       = DTC_MAX_REPEAT_TRANSFER_LENGTH;
392         p_properties->transfer_length_remaining = p_info->length & DTC_PRV_MASK_CRAL;
393 
394         if (TRANSFER_MODE_BLOCK == p_info->transfer_settings_word_b.mode)
395         {
396             p_properties->block_count_max       = DTC_MAX_BLOCK_COUNT;
397             p_properties->block_count_remaining = p_info->num_blocks;
398         }
399     }
400     else
401     {
402         p_properties->transfer_length_max       = DTC_MAX_NORMAL_TRANSFER_LENGTH;
403         p_properties->transfer_length_remaining = p_info->length;
404     }
405 
406     return FSP_SUCCESS;
407 }
408 
409 /*******************************************************************************************************************//**
410  * To update next transfer information without interruption during transfer.
411  *
412  * @retval FSP_ERR_UNSUPPORTED        This feature is not supported.
413  **********************************************************************************************************************/
R_DTC_Reload(transfer_ctrl_t * const p_api_ctrl,void const * p_src,void * p_dest,uint32_t const num_transfers)414 fsp_err_t R_DTC_Reload (transfer_ctrl_t * const p_api_ctrl,
415                         void const            * p_src,
416                         void                  * p_dest,
417                         uint32_t const          num_transfers)
418 {
419     FSP_PARAMETER_NOT_USED(p_api_ctrl);
420     FSP_PARAMETER_NOT_USED(p_src);
421     FSP_PARAMETER_NOT_USED(p_dest);
422     FSP_PARAMETER_NOT_USED(num_transfers);
423 
424     return FSP_ERR_UNSUPPORTED;
425 }
426 
427 /*******************************************************************************************************************//**
428  * Placeholder for unsupported callbackset function. Implements @ref transfer_api_t::callbackSet.
429  *
430  * @retval FSP_ERR_UNSUPPORTED      DTC does not support direct callbacks.
431  **********************************************************************************************************************/
R_DTC_CallbackSet(transfer_ctrl_t * const p_api_ctrl,void (* p_callback)(transfer_callback_args_t *),void const * const p_context,transfer_callback_args_t * const p_callback_memory)432 fsp_err_t R_DTC_CallbackSet (transfer_ctrl_t * const       p_api_ctrl,
433                              void (                      * p_callback)(transfer_callback_args_t *),
434                              void const * const            p_context,
435                              transfer_callback_args_t * const  p_callback_memory)
436 {
437     /* This function isn't supported.  It is defined only to implement a required function of transfer_api_t.
438      * Mark the input parameter as unused since this function isn't supported. */
439     FSP_PARAMETER_NOT_USED(p_api_ctrl);
440     FSP_PARAMETER_NOT_USED(p_callback);
441     FSP_PARAMETER_NOT_USED(p_context);
442     FSP_PARAMETER_NOT_USED(p_callback_memory);
443 
444     return FSP_ERR_UNSUPPORTED;
445 }
446 
447 /*******************************************************************************************************************//**
448  * Disables DTC activation in the ICU, then clears transfer data from the DTC vector table.
449  * Implements @ref transfer_api_t::close.
450  *
451  * @retval FSP_SUCCESS              Successful close.
452  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
453  * @retval FSP_ERR_NOT_OPEN         Handle is not initialized.  Call R_DTC_Open to initialize the control block.
454  **********************************************************************************************************************/
R_DTC_Close(transfer_ctrl_t * const p_api_ctrl)455 fsp_err_t R_DTC_Close (transfer_ctrl_t * const p_api_ctrl)
456 {
457     dtc_instance_ctrl_t * p_ctrl = (dtc_instance_ctrl_t *) p_api_ctrl;
458     fsp_err_t             err    = FSP_SUCCESS;
459 
460 #if DTC_CFG_PARAM_CHECKING_ENABLE
461     FSP_ASSERT(NULL != p_ctrl);
462     FSP_ERROR_RETURN(p_ctrl->open == DTC_OPEN, FSP_ERR_NOT_OPEN);
463 #endif
464 
465     const IRQn_Type irq = p_ctrl->irq;
466 
467     /* Clear DTC enable bit in ICU. */
468     r_dtc_disable_transfer(irq);
469 
470     /* Clear pointer in vector table. */
471     gp_dtc_vector_table[irq] = NULL;
472 
473     /* Mark instance as closed. */
474     p_ctrl->open = 0U;
475 
476     return err;
477 }
478 
479 /*******************************************************************************************************************//**
480  * @} (end addtogroup DTC)
481  **********************************************************************************************************************/
482 
483 /*******************************************************************************************************************//**
484  * Verify that the source and destination pointers are valid then enable the DTC.
485  *
486  * @retval FSP_SUCCESS              Successfully enabled
487  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
488  * @retval FSP_ERR_UNSUPPORTED      Address Mode Offset is selected.
489  **********************************************************************************************************************/
r_dtc_prv_enable(dtc_instance_ctrl_t * p_ctrl)490 static fsp_err_t r_dtc_prv_enable (dtc_instance_ctrl_t * p_ctrl)
491 {
492 #if DTC_CFG_PARAM_CHECKING_ENABLE
493     fsp_err_t err = r_dtc_source_destination_parameter_check(gp_dtc_vector_table[p_ctrl->irq]);
494     FSP_ERROR_RETURN(FSP_SUCCESS == err, err);
495 #endif
496 
497     /* Enable transfers on this activation source. */
498 #if BSP_FEATURE_ICU_HAS_IELSR
499     R_ICU->IELSR_b[p_ctrl->irq].DTCE = 1U;
500 #else
501     R_ICU->DTCENSET[(((uint32_t) p_ctrl->irq) >> 5UL)] = 1UL << ((uint32_t) p_ctrl->irq & (uint32_t) 0x1FUL);
502 #endif
503 
504     return FSP_SUCCESS;
505 }
506 
507 /*******************************************************************************************************************//**
508  * One time state initialization for all DTC instances.
509  **********************************************************************************************************************/
r_dtc_state_initialize(void)510 static void r_dtc_state_initialize (void)
511 {
512     /* Stores initialization state to skip initialization in ::R_DTC_Open after the first call. */
513     static bool g_dtc_state_initialized = false;
514 
515     /* DTC requires a one time initialization.  This will be handled only the first time this function
516      *  is called. This initialization:
517      *  -# Stores the register base addresses for DTC and ICU.
518      *  -# Powers on the DTC block.
519      *  -# Initializes the vector table to NULL pointers.
520      *  -# Sets the vector table base address.
521      *  -# Enables DTC transfers. */
522     if (!g_dtc_state_initialized)
523     {
524         g_dtc_state_initialized = true;
525 
526         /** Power on DTC */
527         R_BSP_MODULE_START(FSP_IP_DTC, 0);
528 
529         /* The DTC vector table must be cleared during initialization because it is located in
530          * its own section outside of the .BSS section which is cleared during startup. */
531         memset(&gp_dtc_vector_table, 0U, DTC_VECTOR_TABLE_ENTRIES * sizeof(transfer_info_t *));
532 
533         /* Set DTC vector table. */
534 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
535         R_DTC->DTCVBR_SEC = (uint32_t) gp_dtc_vector_table;
536 #else
537         R_DTC->DTCVBR = (uint32_t) gp_dtc_vector_table;
538 #endif
539 
540 #if BSP_FEATURE_TZ_HAS_TRUSTZONE && BSP_TZ_NONSECURE_BUILD
541         if (1 == R_CPSCU->DTCSAR_b.DTCSTSA)
542         {
543             /* Enable the DTC Peripheral */
544             R_DTC->DTCST = 1U;
545         }
546 
547 #else
548 
549         /* Enable the DTC Peripheral */
550         R_DTC->DTCST = 1U;
551 #endif
552     }
553 }
554 
555 /*******************************************************************************************************************//**
556  * Configure the p_info state and write p_info to DTC vector table.
557  **********************************************************************************************************************/
r_dtc_set_info(dtc_instance_ctrl_t * p_ctrl,transfer_info_t * p_info)558 static void r_dtc_set_info (dtc_instance_ctrl_t * p_ctrl, transfer_info_t * p_info)
559 {
560     /* Update internal variables. */
561     r_dtc_block_repeat_initialize(p_info);
562 
563     /* Disable read skip prior to modifying settings. It will be enabled later
564      * (See DTC Section 18.4.1 of the RA6M3 manual R01UH0886EJ0100). */
565 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
566     R_DTC->DTCCR_SEC = DTC_PRV_RRS_DISABLE;
567 #else
568     R_DTC->DTCCR = DTC_PRV_RRS_DISABLE;
569 #endif
570 
571     /* Update the entry in the DTC Vector table. */
572     gp_dtc_vector_table[p_ctrl->irq] = p_info;
573 
574     /* Enable read skip after all settings are written. */
575 #if !BSP_TZ_NONSECURE_BUILD && BSP_FEATURE_TZ_HAS_TRUSTZONE
576     R_DTC->DTCCR_SEC = DTC_PRV_RRS_ENABLE;
577 #else
578     R_DTC->DTCCR = DTC_PRV_RRS_ENABLE;
579 #endif
580 }
581 
582 /*******************************************************************************************************************//**
583  * Configure the length setting for block and repeat mode.
584  **********************************************************************************************************************/
r_dtc_block_repeat_initialize(transfer_info_t * p_info)585 static void r_dtc_block_repeat_initialize (transfer_info_t * p_info)
586 {
587     uint32_t i = 0;
588     do
589     {
590         /* Update the CRA register to the desired settings */
591         if (TRANSFER_MODE_NORMAL != p_info[i].transfer_settings_word_b.mode)
592         {
593             uint8_t CRAL = p_info[i].length & DTC_PRV_MASK_CRAL;
594             p_info[i].length = (uint16_t) ((CRAL << DTC_PRV_OFFSET_CRAH) | CRAL);
595         }
596     } while (TRANSFER_CHAIN_MODE_DISABLED != p_info[i++].transfer_settings_word_b.chain_mode);
597 }
598 
599 #if DTC_CFG_PARAM_CHECKING_ENABLE
600 
601  #if BSP_CFG_ASSERT != 3
602 
603 /*******************************************************************************************************************//**
604  * Check to make sure that the length is valid for block and repeat mode.
605  *
606  * @retval FSP_SUCCESS              Parameters are valid.
607  * @retval FSP_ERR_ASSERTION        Invalid length for block or repeat mode.
608  * @retval FSP_ERR_UNSUPPORTED      Address Mode Offset is selected.
609  *
610  **********************************************************************************************************************/
r_dtc_length_assert(transfer_info_t * p_info)611 static fsp_err_t r_dtc_length_assert (transfer_info_t * p_info)
612 {
613     uint32_t i = 0;
614     do
615     {
616         FSP_ERROR_RETURN(TRANSFER_ADDR_MODE_OFFSET != p_info[i].transfer_settings_word_b.src_addr_mode,
617                          FSP_ERR_UNSUPPORTED);
618         FSP_ERROR_RETURN(TRANSFER_ADDR_MODE_OFFSET != p_info[i].transfer_settings_word_b.dest_addr_mode,
619                          FSP_ERR_UNSUPPORTED);
620 
621         if (TRANSFER_MODE_NORMAL != p_info[i].transfer_settings_word_b.mode)
622         {
623             /* transfer_length_max is the same for Block and repeat mode. */
624             FSP_ASSERT(p_info[i].length <= DTC_MAX_REPEAT_TRANSFER_LENGTH);
625         }
626     } while (TRANSFER_CHAIN_MODE_DISABLED != p_info[i++].transfer_settings_word_b.chain_mode);
627 
628     return FSP_SUCCESS;
629 }
630 
631  #endif
632 
633 /*******************************************************************************************************************//**
634  * Check that the source and destination are not NULL and that they are aligned correctly.
635  *
636  * @retval FSP_SUCCESS              Parameters are valid.
637  * @retval FSP_ERR_ASSERTION        An input parameter is invalid.
638  * @retval FSP_ERR_UNSUPPORTED      Address Mode Offset is selected.
639  *
640  **********************************************************************************************************************/
r_dtc_source_destination_parameter_check(transfer_info_t * p_info)641 static fsp_err_t r_dtc_source_destination_parameter_check (transfer_info_t * p_info)
642 {
643     uint32_t i = 0;
644     do
645     {
646         FSP_ERROR_RETURN(TRANSFER_ADDR_MODE_OFFSET != p_info[i].transfer_settings_word_b.src_addr_mode,
647                          FSP_ERR_UNSUPPORTED);
648         FSP_ERROR_RETURN(TRANSFER_ADDR_MODE_OFFSET != p_info[i].transfer_settings_word_b.dest_addr_mode,
649                          FSP_ERR_UNSUPPORTED);
650         FSP_ASSERT(NULL != p_info[i].p_src);
651         FSP_ASSERT(NULL != p_info[i].p_dest);
652         FSP_ASSERT(0U ==
653                    ((uint32_t) p_info[i].p_dest & DTC_PRV_MASK_ALIGN_N_BYTES(p_info[i].transfer_settings_word_b.size)));
654         FSP_ASSERT(0U ==
655                    ((uint32_t) p_info[i].p_src & DTC_PRV_MASK_ALIGN_N_BYTES(p_info[i].transfer_settings_word_b.size)));
656     } while (TRANSFER_CHAIN_MODE_DISABLED != p_info[i++].transfer_settings_word_b.chain_mode);
657 
658     return FSP_SUCCESS;
659 }
660 
661 #endif
662 
663 /*******************************************************************************************************************//**
664  * Wait for the current DTC transfer to complete.
665  **********************************************************************************************************************/
r_dtc_wait_for_transfer_complete(dtc_instance_ctrl_t * p_ctrl)666 static void r_dtc_wait_for_transfer_complete (dtc_instance_ctrl_t * p_ctrl)
667 {
668     uint32_t in_progress = (1U << DTC_PRV_OFFSET_IN_PROGRESS) | (uint32_t) p_ctrl->irq;
669 
670     /* Wait for the DTCSTS.ACT flag to be clear if the current vector is the activation source.*/
671     FSP_HARDWARE_REGISTER_WAIT((FSP_STYPE3_REG16_READ(R_DTC->DTCSTS, !R_CPSCU->DTCSAR_b.DTCSTSA) == in_progress), 0);
672 }
673 
674 /*******************************************************************************************************************//**
675  * Disable transfers on activation source.
676  **********************************************************************************************************************/
r_dtc_disable_transfer(const IRQn_Type irq)677 static void r_dtc_disable_transfer (const IRQn_Type irq)
678 {
679 #if BSP_FEATURE_ICU_HAS_IELSR
680     R_ICU->IELSR_b[((uint32_t) irq)].DTCE = 0U;
681 #else
682     R_ICU->DTCENCLR[(((uint32_t) irq) >> 5UL)] = 1UL << (((uint32_t) irq) & (uint32_t) 0x1FUL);
683 #endif
684 }
685