1 /*
2  * Copyright (c) 2024, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #include "bootutil/bootutil_log.h"
8 #include "host_device_definition.h"
9 #include "host_base_address.h"
10 #include "ni_tower_lib.h"
11 
12 #include <stddef.h>
13 
14 #define RAM_AXIS_RO_APU_REGION_IDX  (0)
15 #define RAM_AXIS_RW_APU_REGION_IDX  (1)
16 
17 /* Peripheral NI-Tower component nodes */
18 const struct ni_tower_component_node periph_ram_amni  = {
19     .type = NI_TOWER_AMNI,
20     .id = PERIPH_RAM_AMNI_ID,
21 };
22 
23 const struct ni_tower_component_node periph_nsuart0_pmni  = {
24     .type = NI_TOWER_PMNI,
25     .id = PERIPH_NSUART0_PMNI_ID,
26 };
27 
28 const struct ni_tower_component_node periph_secuart_pmni  = {
29     .type = NI_TOWER_PMNI,
30     .id = PERIPH_SECUART_PMNI_ID,
31 };
32 
33 const struct ni_tower_component_node periph_nsuart1_pmni  = {
34     .type = NI_TOWER_PMNI,
35     .id = PERIPH_NSUART1_PMNI_ID,
36 };
37 
38 const struct ni_tower_component_node periph_nsgenwdog_pmni  = {
39     .type = NI_TOWER_PMNI,
40     .id = PERIPH_NSGENWDOG_PMNI_ID,
41 };
42 
43 const struct ni_tower_component_node periph_rootgenwdog_pmni  = {
44     .type = NI_TOWER_PMNI,
45     .id = PERIPH_ROOTGENWDOG_PMNI_ID,
46 };
47 
48 const struct ni_tower_component_node periph_secgenwdog_pmni  = {
49     .type = NI_TOWER_PMNI,
50     .id = PERIPH_SECGENWDOG_PMNI_ID,
51 };
52 
53 const struct ni_tower_component_node PERIPH_ECCREG_PMNI_APU_DEV_CFG  = {
54     .type = NI_TOWER_PMNI,
55     .id = PERIPH_ECCREG_PMNI_ID,
56 };
57 
58 const struct ni_tower_component_node periph_gtimerctrl_pmni  = {
59     .type = NI_TOWER_PMNI,
60     .id = PERIPH_GTIMERCTRL_PMNI_ID,
61 };
62 
63 const struct ni_tower_component_node periph_secgtimer_pmni  = {
64     .type = NI_TOWER_PMNI,
65     .id = PERIPH_SECGTIMER_PMNI_ID,
66 };
67 
68 const struct ni_tower_component_node periph_nsgtimer_pmni  = {
69     .type = NI_TOWER_PMNI,
70     .id = PERIPH_NSGTIMER_PMNI_ID,
71 };
72 
73 /*
74  * Software implementation defined region for SRAM and is accessible by AP,
75  * RSE, SCP and MCP. First region (AP BL1 code region) will be changed to Read
76  * only access after RSE loads AP BL1 image.
77  */
78 static const struct ni_tower_apu_reg_cfg_info ram_axim_apu[] = {
79     [RAM_AXIS_RO_APU_REGION_IDX] =
80         INIT_APU_REGION_UNLOCKED(
81                         HOST_AP_BL1_RO_SRAM_PHYS_BASE,
82                         HOST_AP_BL1_RO_SRAM_PHYS_LIMIT,
83                         NI_T_ROOT_RW),
84     [RAM_AXIS_RW_APU_REGION_IDX] =
85         INIT_APU_REGION(HOST_AP_BL1_RW_SRAM_PHYS_BASE,
86                         HOST_AP_BL1_RW_SRAM_PHYS_LIMIT,
87                         NI_T_ROOT_RW),
88 };
89 
90 /* AP Non-secure UART */
91 static const struct ni_tower_apu_reg_cfg_info nsuart0_apbm_apu[] = {
92     INIT_APU_REGION(HOST_NS_UART_PHYS_BASE,
93                     HOST_NS_UART_PHYS_LIMIT,
94                     NI_T_ALL_PERM),
95 };
96 
97 /* AP Secure UART */
98 static const struct ni_tower_apu_reg_cfg_info secuart_apbm_apu[] = {
99     INIT_APU_REGION(HOST_S_UART_PHYS_BASE,
100                     HOST_S_UART_PHYS_LIMIT,
101                     NI_T_ROOT_RW | NI_T_SEC_RW),
102 };
103 
104 /* AP Non-secure UART for RMM debug */
105 static const struct ni_tower_apu_reg_cfg_info nsuart1_apbm_apu[] = {
106     INIT_APU_REGION(HOST_RMM_NS_UART_PHYS_BASE,
107                     HOST_RMM_NS_UART_PHYS_LIMIT,
108                     NI_T_REALM_RW),
109 };
110 
111 /* AP Non-secure WatchDog */
112 static const struct ni_tower_apu_reg_cfg_info nsgenwdog_apbm_apu[] = {
113     INIT_APU_REGION(HOST_AP_NS_WDOG_PHYS_BASE,
114                     HOST_AP_NS_WDOG_PHYS_LIMIT,
115                     NI_T_ALL_PERM),
116 };
117 
118 /* AP root WatchDog */
119 static const struct ni_tower_apu_reg_cfg_info rootgenwdog_apbm_apu[] = {
120     INIT_APU_REGION(HOST_AP_RT_WDOG_PHYS_BASE,
121                     HOST_AP_RT_WDOG_PHYS_LIMIT,
122                     NI_T_ROOT_RW),
123 };
124 
125 /* AP Secure WatchDog */
126 static const struct ni_tower_apu_reg_cfg_info secgenwdog_apbm_apu[] = {
127     INIT_APU_REGION(HOST_AP_S_WDOG_PHYS_BASE,
128                     HOST_AP_S_WDOG_PHYS_LIMIT,
129                     NI_T_ROOT_RW | NI_T_SEC_RW),
130 };
131 
132 /* Secure SRAM Error record block for the shared ARSM SRAM */
133 static const struct ni_tower_apu_reg_cfg_info eccreg_apbm_apu[] = {
134     INIT_APU_REGION(HOST_AP_S_ARSM_RAM_ECC_REC_PHYS_BASE,
135                     HOST_AP_S_ARSM_RAM_ECC_REC_PHYS_LIMIT,
136                     NI_T_ROOT_RW | NI_T_SEC_RW),
137     INIT_APU_REGION(HOST_AP_NS_ARSM_RAM_ECC_REC_PHYS_BASE,
138                     HOST_AP_NS_ARSM_RAM_ECC_REC_PHYS_LIMIT,
139                     NI_T_ALL_PERM),
140     INIT_APU_REGION(HOST_AP_RT_ARSM_RAM_ECC_REC_PHYS_BASE,
141                     HOST_AP_RT_ARSM_RAM_ECC_REC_PHYS_LIMIT,
142                     NI_T_ROOT_RW),
143     INIT_APU_REGION(HOST_AP_RL_ARSM_RAM_ECC_REC_PHYS_BASE,
144                     HOST_AP_RL_ARSM_RAM_ECC_REC_PHYS_LIMIT,
145                     NI_T_REALM_RW),
146     INIT_APU_REGION(HOST_SCP_S_ARSM_RAM_ECC_REC_PHYS_BASE,
147                     HOST_SCP_S_ARSM_RAM_ECC_REC_PHYS_LIMIT,
148                     NI_T_ROOT_RW | NI_T_SEC_RW),
149     INIT_APU_REGION(HOST_SCP_NS_ARSM_RAM_ECC_REC_PHYS_BASE,
150                     HOST_SCP_NS_ARSM_RAM_ECC_REC_PHYS_LIMIT,
151                     NI_T_ALL_PERM),
152     INIT_APU_REGION(HOST_SCP_RT_ARSM_RAM_ECC_REC_PHYS_BASE,
153                     HOST_SCP_RT_ARSM_RAM_ECC_REC_PHYS_LIMIT,
154                     NI_T_ROOT_RW),
155     INIT_APU_REGION(HOST_SCP_RL_ARSM_RAM_ECC_REC_PHYS_BASE,
156                     HOST_SCP_RL_ARSM_RAM_ECC_REC_PHYS_LIMIT,
157                     NI_T_REALM_RW),
158     INIT_APU_REGION(HOST_MCP_S_ARSM_RAM_ECC_REC_PHYS_BASE,
159                     HOST_MCP_S_ARSM_RAM_ECC_REC_PHYS_LIMIT,
160                     NI_T_ROOT_RW | NI_T_SEC_RW),
161     INIT_APU_REGION(HOST_MCP_NS_ARSM_RAM_ECC_REC_PHYS_BASE,
162                     HOST_MCP_NS_ARSM_RAM_ECC_REC_PHYS_LIMIT,
163                     NI_T_ALL_PERM),
164     INIT_APU_REGION(HOST_MCP_RT_ARSM_RAM_ECC_REC_PHYS_BASE,
165                     HOST_MCP_RT_ARSM_RAM_ECC_REC_PHYS_LIMIT,
166                     NI_T_ROOT_RW),
167     INIT_APU_REGION(HOST_MCP_RL_ARSM_RAM_ECC_REC_PHYS_BASE,
168                     HOST_MCP_RL_ARSM_RAM_ECC_REC_PHYS_LIMIT,
169                     NI_T_REALM_RW),
170     INIT_APU_REGION(HOST_RSE_S_ARSM_RAM_ECC_REC_PHYS_BASE,
171                     HOST_RSE_S_ARSM_RAM_ECC_REC_PHYS_LIMIT,
172                     NI_T_ROOT_RW | NI_T_SEC_RW),
173     INIT_APU_REGION(HOST_RSE_NS_ARSM_RAM_ECC_REC_PHYS_BASE,
174                     HOST_RSE_NS_ARSM_RAM_ECC_REC_PHYS_LIMIT,
175                     NI_T_ALL_PERM),
176     INIT_APU_REGION(HOST_RSE_RT_ARSM_RAM_ECC_REC_PHYS_BASE,
177                     HOST_RSE_RT_ARSM_RAM_ECC_REC_PHYS_LIMIT,
178                     NI_T_ROOT_RW),
179     INIT_APU_REGION(HOST_RSE_RL_ARSM_RAM_ECC_REC_PHYS_BASE,
180                     HOST_RSE_RL_ARSM_RAM_ECC_REC_PHYS_LIMIT,
181                     NI_T_REALM_RW),
182 };
183 
184 /* AP Generic Timer Control Frame */
185 static const struct ni_tower_apu_reg_cfg_info gtimerctrl_apbm_apu[] = {
186     INIT_APU_REGION(HOST_AP_REFCLK_CNTCTL_PHYS_BASE,
187                     HOST_AP_REFCLK_CNTCTL_PHYS_LIMIT,
188                     NI_T_ALL_PERM),
189 };
190 
191 /* AP Secure Generic Timer Control Base Frame */
192 static const struct ni_tower_apu_reg_cfg_info secgtimer_apbm_apu[] = {
193     INIT_APU_REGION(HOST_AP_S_REFCLK_CNTBASE0_PHYS_BASE,
194                     HOST_AP_S_REFCLK_CNTBASE0_PHYS_LIMIT,
195                     NI_T_ROOT_RW | NI_T_SEC_RW),
196 };
197 
198 /* AP Non-secure Generic Timer Control Base Frame */
199 static const struct ni_tower_apu_reg_cfg_info nsgtimer_apbm_apu[] = {
200     INIT_APU_REGION(HOST_AP_NS_REFCLK_CNTBASE1_PHYS_BASE,
201                     HOST_AP_NS_REFCLK_CNTBASE1_PHYS_LIMIT,
202                     NI_T_ALL_PERM),
203 };
204 
205 /*
206  * Configure Access Protection Unit (APU) to setup access permission for each
207  * memory region based on its target in Peripheral NI-Tower.
208  */
program_periph_apu(void)209 static int32_t program_periph_apu(void)
210 {
211     enum ni_tower_err err;
212 
213     /*
214      * Populates all APU entry into a table array to confgiure and enable
215      * desired APUs
216      */
217     const struct ni_tower_apu_cfgs apu_table[] = {
218         {
219             .component = &periph_ram_amni,
220             .region_count = ARRAY_SIZE(ram_axim_apu),
221             .regions = ram_axim_apu,
222             .add_chip_addr_offset = false,
223         },
224         {
225             .component = &periph_nsuart0_pmni,
226             .region_count = ARRAY_SIZE(nsuart0_apbm_apu),
227             .regions = nsuart0_apbm_apu,
228             .add_chip_addr_offset = false,
229         },
230         {
231             .component = &periph_secuart_pmni,
232             .region_count = ARRAY_SIZE(secuart_apbm_apu),
233             .regions = secuart_apbm_apu,
234             .add_chip_addr_offset = false,
235         },
236         {
237             .component = &periph_nsuart1_pmni,
238             .region_count = ARRAY_SIZE(nsuart1_apbm_apu),
239             .regions = nsuart1_apbm_apu,
240             .add_chip_addr_offset = false,
241         },
242         {
243             .component = &periph_nsgenwdog_pmni,
244             .region_count = ARRAY_SIZE(nsgenwdog_apbm_apu),
245             .regions = nsgenwdog_apbm_apu,
246             .add_chip_addr_offset = false,
247         },
248         {
249             .component = &periph_rootgenwdog_pmni,
250             .region_count = ARRAY_SIZE(rootgenwdog_apbm_apu),
251             .regions = rootgenwdog_apbm_apu,
252             .add_chip_addr_offset = false,
253         },
254         {
255             .component = &periph_secgenwdog_pmni,
256             .region_count = ARRAY_SIZE(secgenwdog_apbm_apu),
257             .regions = secgenwdog_apbm_apu,
258             .add_chip_addr_offset = false,
259         },
260         {
261             .component = &PERIPH_ECCREG_PMNI_APU_DEV_CFG,
262             .region_count = ARRAY_SIZE(eccreg_apbm_apu),
263             .regions = eccreg_apbm_apu,
264             .add_chip_addr_offset = false,
265         },
266         {
267             .component = &periph_gtimerctrl_pmni,
268             .region_count = ARRAY_SIZE(gtimerctrl_apbm_apu),
269             .regions = gtimerctrl_apbm_apu,
270             .add_chip_addr_offset = false,
271         },
272         {
273             .component = &periph_secgtimer_pmni,
274             .region_count = ARRAY_SIZE(secgtimer_apbm_apu),
275             .regions = secgtimer_apbm_apu,
276             .add_chip_addr_offset = false,
277         },
278         {
279             .component = &periph_nsgtimer_pmni,
280             .region_count = ARRAY_SIZE(nsgtimer_apbm_apu),
281             .regions = nsgtimer_apbm_apu,
282             .add_chip_addr_offset = false,
283         },
284     };
285 
286     err = ni_tower_program_apu_table(&PERIPH_NI_TOWER_DEV, apu_table,
287                                                         ARRAY_SIZE(apu_table));
288     if (err != NI_TOWER_SUCCESS) {
289         return -1;
290     }
291 
292     return 0;
293 }
294 
program_periph_ni_tower(void)295 int32_t program_periph_ni_tower(void)
296 {
297     return program_periph_apu();
298 }
299 
program_periph_ni_tower_post_ap_bl1_load(void)300 int32_t program_periph_ni_tower_post_ap_bl1_load(void)
301 {
302     enum ni_tower_err err;
303     struct ni_tower_apu_dev apu_dev = {0};
304 
305     /* Make AP_BL1_RO region read only access */
306     struct ni_tower_apu_reg_cfg_info ram_axim_region_0 =
307             INIT_APU_REGION(HOST_AP_BL1_RO_SRAM_PHYS_BASE,
308                             HOST_AP_BL1_RO_SRAM_PHYS_LIMIT,
309                             NI_T_ROOT_R);
310 
311     /* Initialize APU device */
312     err = ni_tower_apu_dev_init(&PERIPH_NI_TOWER_DEV,
313                                 &periph_ram_amni,
314                                 PERIPH_NI_TOWER_DEV.chip_addr_offset,
315                                 &apu_dev);
316     if (err != NI_TOWER_SUCCESS) {
317         return -1;
318     }
319 
320     if (ni_tower_apu_configure_region(&apu_dev, &ram_axim_region_0,
321                                       RAM_AXIS_RO_APU_REGION_IDX) !=
322         NI_TOWER_SUCCESS) {
323         return -1;
324     }
325 
326     return 0;
327 }
328