1 /*
2 * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <stdint.h>
9 #include "bootutil/bootutil_log.h"
10 #include "boot_dma.h"
11 #include "tfm_hal_device_header.h"
12 #include "tfm_plat_defs.h"
13 #include "dma350_lib.h"
14 #include "device_definition.h"
15
16 #define BOOT_DMA0_COMBINED_S_SIGNAL (24)
17 #define BOOT_DMA_NUM_CHANNELS (4)
18
19 static struct dma350_ch_dev_t *const dma350_channel_list[BOOT_DMA_NUM_CHANNELS] = {
20 &DMA350_DMA0_CH0_DEV_S,
21 &DMA350_DMA0_CH1_DEV_S,
22 &DMA350_DMA0_CH2_DEV_S,
23 &DMA350_DMA0_CH3_DEV_S
24 };
25
26 /* DMA350 checker layer has to know the TCM remaps */
27 /* Subordinate TCM Interface provides system access only to TCM internal to each
28 * CPU. The memory map presented on the interface for TCM access are defined by
29 * TRM. Below address remaps by adding offset provides access to respective
30 * CPU instruction and data TCM.
31 */
32
33 /* TCM memories addresses from perspective of cpu0
34 * 0x0000_0000 .. 0x00ff_ffff NS ITCM
35 * 0x1000_0000 .. 0x10ff_ffff S ITCM
36 * 0x2000_0000 .. 0x20ff_ffff NS DTCM
37 * 0x3000_0000 .. 0x30ff_ffff S DTCM
38 */
39
40 const struct dma350_remap_range_t dma350_address_remap_list[] = {
41 /* Non-secure CPU ITCM */
42 {.begin = 0x00000000, .end = 0x00FFFFFF, .offset = 0x0A000000},
43 /* Secure CPU ITCM */
44 {.begin = 0x10000000, .end = 0x10FFFFFF, .offset = 0x0A000000},
45 /* Non-secure CPU DTCM */
46 {.begin = 0x20000000, .end = 0x20FFFFFF, .offset = 0x04000000},
47 /* Secure CPU DTCM */
48 {.begin = 0x30000000, .end = 0x30FFFFFF, .offset = 0x04000000}
49 };
50
51 const struct dma350_remap_list_t dma350_address_remap = {
52 .size = sizeof(dma350_address_remap_list)/
53 sizeof(dma350_address_remap_list[0]),
54 .map = dma350_address_remap_list
55 };
56
57 /*------------------- DMA configuration functions -------------------------*/
boot_dma_init_cfg(void)58 enum tfm_plat_err_t boot_dma_init_cfg(void)
59 {
60 enum dma350_error_t dma_err;
61 enum dma350_ch_error_t ch_err;
62 struct dma350_ch_dev_t *dma_ch_ptr;
63 uint32_t i;
64
65 dma_err = dma350_init(&DMA350_DMA0_DEV_S);
66 if (dma_err != DMA350_ERR_NONE) {
67 BOOT_LOG_ERR("DMA350_DMA0_DEV_S init failed!");
68 return TFM_PLAT_ERR_SYSTEM_ERR;
69 }
70
71 for (i = 0; i < BOOT_DMA_NUM_CHANNELS; i++) {
72 dma_ch_ptr = dma350_channel_list[i];
73
74 ch_err = dma350_ch_init(dma_ch_ptr);
75 if (ch_err != DMA350_CH_ERR_NONE) {
76 BOOT_LOG_ERR("DMA350_DMA0_CH%u_DEV_S init failed!", i);
77 return TFM_PLAT_ERR_SYSTEM_ERR;
78 }
79
80 dma_err = dma350_set_ch_privileged(&DMA350_DMA0_DEV_S, i);
81 if (dma_err != DMA350_ERR_NONE) {
82 BOOT_LOG_ERR("Failed to set DMA350_DM0 channel:%u privileged!",
83 i);
84 return TFM_PLAT_ERR_SYSTEM_ERR;
85 }
86
87 dma_err = dma350_set_ch_secure(&DMA350_DMA0_DEV_S, i);
88 if (dma_err != DMA350_ERR_NONE) {
89 BOOT_LOG_ERR("Failed to set DMA350_DM0 channel:%u secure!",
90 i);
91 return TFM_PLAT_ERR_SYSTEM_ERR;
92 }
93 }
94
95 /* Use combined secure interrupt because there are no channel IRQs */
96 DMA350_DMA0_DEV_S.cfg->dma_sec_ctrl->SEC_CTRL |= 0x1UL;
97 DMA350_DMA0_DEV_S.cfg->dma_nsec_ctrl->NSEC_CTRL |= 0x1UL;
98
99 return TFM_PLAT_ERR_SUCCESS;
100 }
101
boot_dma_memcpy(uint32_t src_addr,uint32_t dest_addr,uint32_t size,uint32_t ch_idx)102 int32_t boot_dma_memcpy(uint32_t src_addr,
103 uint32_t dest_addr,
104 uint32_t size,
105 uint32_t ch_idx)
106 {
107 struct dma350_ch_dev_t *dma_ch_ptr;
108 enum dma350_lib_error_t dma_config_ret_val =
109 DMA350_LIB_ERR_INVALID_CONFIG_TYPE;
110
111 if (ch_idx >= BOOT_DMA_NUM_CHANNELS) {
112 BOOT_LOG_ERR("[DMA350 BL2] Input dma channel: %u is invalid \r\n",
113 ch_idx);
114 return -1;
115 }
116
117 dma_ch_ptr = dma350_channel_list[ch_idx];
118 dma_config_ret_val = dma350_memcpy(dma_ch_ptr,
119 (void *)src_addr,
120 (void *)dest_addr,
121 size,
122 DMA350_LIB_EXEC_BLOCKING);
123
124 if (dma_config_ret_val != 0) {
125 BOOT_LOG_ERR("[DMA350 BL2] dma350_memcpy return value: 0x%x",
126 dma_config_ret_val);
127 BOOT_LOG_ERR("[DMA350 BL2] Fail to copy %u bytes from 0x%x to 0x%x",
128 size, src_addr, dest_addr);
129 return -1;
130 }
131
132 return 0;
133 }
134