1 /*
2  * Copyright (c) 2017-2024, Arm Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "tfm_hal_device_header.h"
18 #include "fih.h"
19 #include "target_cfg.h"
20 #include "Driver_MPC.h"
21 #include "platform_retarget_dev.h"
22 #include "region_defs.h"
23 #include "tfm_plat_defs.h"
24 #include "region.h"
25 
26 #ifdef PSA_API_TEST_IPC
27 #define PSA_FF_TEST_SECURE_UART2
28 #endif
29 
30 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
31 
32 /* The section names come from the scatter file */
33 REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base);
34 REGION_DECLARE(Image$$, ER_VENEER, $$Base);
35 REGION_DECLARE(Image$$, VENEER_ALIGN, $$Limit);
36 
37 #ifdef BL2
38 REGION_DECLARE(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base);
39 #endif /* BL2 */
40 
41 const struct memory_region_limits memory_regions = {
42     .non_secure_code_start =
43         (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
44         BL2_HEADER_SIZE,
45 
46     .non_secure_partition_base =
47         (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base),
48 
49     .non_secure_partition_limit =
50         (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
51         NS_PARTITION_SIZE - 1,
52 
53     .veneer_base = (uint32_t)&REGION_NAME(Image$$, ER_VENEER, $$Base),
54     .veneer_limit = (uint32_t)&REGION_NAME(Image$$, VENEER_ALIGN, $$Limit),
55 
56 #ifdef BL2
57     .secondary_partition_base =
58         (uint32_t)&REGION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base),
59 
60     .secondary_partition_limit =
61         (uint32_t)&REGION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base) +
62         SECONDARY_PARTITION_SIZE - 1,
63 #endif /* BL2 */
64 };
65 
66 /* Allows software, via SAU, to define the code region as a NSC */
67 #define NSCCFG_CODENSC  1
68 
69 /* Import MPC driver */
70 extern ARM_DRIVER_MPC Driver_SRAM1_MPC, Driver_SRAM2_MPC;
71 
72 /* Define Peripherals NS address range for the platform */
73 #define PERIPHERALS_BASE_NS_START (0x40000000)
74 #define PERIPHERALS_BASE_NS_END   (0x4FFFFFFF)
75 
76 /* Enable system reset request for CPU 0 */
77 #define ENABLE_CPU0_SYSTEM_RESET_REQUEST (1U << 4U)
78 
79 /* To write into AIRCR register, 0x5FA value must be write to the VECTKEY field,
80  * otherwise the processor ignores the write.
81  */
82 #define SCB_AIRCR_WRITE_MASK ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos))
83 
84 /* Debug configuration flags */
85 #define SPNIDEN_SEL_STATUS (0x01u << 7)
86 #define SPNIDEN_STATUS     (0x01u << 6)
87 #define SPIDEN_SEL_STATUS  (0x01u << 5)
88 #define SPIDEN_STATUS      (0x01u << 4)
89 #define NIDEN_SEL_STATUS   (0x01u << 3)
90 #define NIDEN_STATUS       (0x01u << 2)
91 #define DBGEN_SEL_STATUS   (0x01u << 1)
92 #define DBGEN_STATUS       (0x01u << 0)
93 
94 #define All_SEL_STATUS (SPNIDEN_SEL_STATUS | SPIDEN_SEL_STATUS | \
95                         NIDEN_SEL_STATUS | DBGEN_SEL_STATUS)
96 
97 struct platform_data_t tfm_peripheral_std_uart = {
98         UART0_BASE_NS,
99         UART0_BASE_NS + 0xFFF,
100         PPC_SP_DO_NOT_CONFIGURE,
101         -1
102 };
103 
104 struct platform_data_t tfm_peripheral_uart1 = {
105         UART1_BASE_S,
106         UART1_BASE_S + 0xFFF,
107         PPC_SP_APB_PPC_EXP1,
108         CMSDK_UART1_APB_PPC_POS
109 };
110 
111 struct platform_data_t tfm_peripheral_timer0 = {
112         CMSDK_TIMER0_BASE_S,
113         CMSDK_TIMER1_BASE_S - 1,
114         PPC_SP_APB_PPC0,
115         CMSDK_TIMER0_APB_PPC_POS
116 };
117 
118 #ifdef PSA_API_TEST_IPC
119 
120 /* Below data structure are only used for PSA FF tests, and this pattern is
121  * definitely not to be followed for real life use cases, as it can break
122  * security.
123  */
124 
125 struct platform_data_t
126     tfm_peripheral_FF_TEST_UART_REGION = {
127         UART2_BASE_S,
128         UART2_BASE_S + 0xFFF,
129         PPC_SP_APB_PPC_EXP2,
130         CMSDK_UART2_APB_PPC_POS
131 };
132 
133 struct platform_data_t
134     tfm_peripheral_FF_TEST_WATCHDOG_REGION = {
135         APB_WATCHDOG_BASE_S,
136         APB_WATCHDOG_BASE_S + 0xFFF,
137         PPC_SP_DO_NOT_CONFIGURE,
138         -1
139 };
140 
141 #define FF_TEST_NVMEM_REGION_START            0x102FFC00
142 #define FF_TEST_NVMEM_REGION_END              0x102FFFFF
143 #define FF_TEST_SERVER_PARTITION_MMIO_START   0x3801FC00
144 #define FF_TEST_SERVER_PARTITION_MMIO_END     0x3801FCFF
145 #define FF_TEST_DRIVER_PARTITION_MMIO_START   0x3801FE00
146 #define FF_TEST_DRIVER_PARTITION_MMIO_END     0x3801FEFF
147 
148 struct platform_data_t
149     tfm_peripheral_FF_TEST_NVMEM_REGION = {
150         FF_TEST_NVMEM_REGION_START,
151         FF_TEST_NVMEM_REGION_END,
152         PPC_SP_DO_NOT_CONFIGURE,
153         -1
154 };
155 
156 struct platform_data_t
157     tfm_peripheral_FF_TEST_SERVER_PARTITION_MMIO = {
158         FF_TEST_SERVER_PARTITION_MMIO_START,
159         FF_TEST_SERVER_PARTITION_MMIO_END,
160         PPC_SP_DO_NOT_CONFIGURE,
161         -1
162 };
163 
164 struct platform_data_t
165     tfm_peripheral_FF_TEST_DRIVER_PARTITION_MMIO = {
166         FF_TEST_DRIVER_PARTITION_MMIO_START,
167         FF_TEST_DRIVER_PARTITION_MMIO_END,
168         PPC_SP_DO_NOT_CONFIGURE,
169         -1
170 };
171 #endif
172 
enable_fault_handlers(void)173 enum tfm_plat_err_t enable_fault_handlers(void)
174 {
175     /* Explicitly set secure fault priority to the highest */
176     NVIC_SetPriority(SecureFault_IRQn, 0);
177 
178     /* Enables BUS, MEM, USG and Secure faults */
179     SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk
180                   | SCB_SHCSR_BUSFAULTENA_Msk
181                   | SCB_SHCSR_MEMFAULTENA_Msk
182                   | SCB_SHCSR_SECUREFAULTENA_Msk;
183     return TFM_PLAT_ERR_SUCCESS;
184 }
185 
system_reset_cfg(void)186 enum tfm_plat_err_t system_reset_cfg(void)
187 {
188     struct sysctrl_t *sysctrl = (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S;
189     uint32_t reg_value = SCB->AIRCR;
190 
191     /* Enable system reset request for CPU 0, to be triggered via
192      * NVIC_SystemReset function.
193      */
194     sysctrl->resetmask |= ENABLE_CPU0_SYSTEM_RESET_REQUEST;
195 
196     /* Clear SCB_AIRCR_VECTKEY value */
197     reg_value &= ~(uint32_t)(SCB_AIRCR_VECTKEY_Msk);
198 
199     /* Enable system reset request only to the secure world */
200     reg_value |= (uint32_t)(SCB_AIRCR_WRITE_MASK | SCB_AIRCR_SYSRESETREQS_Msk);
201 
202     SCB->AIRCR = reg_value;
203 
204     return TFM_PLAT_ERR_SUCCESS;
205 }
206 
init_debug(void)207 FIH_RET_TYPE(enum tfm_plat_err_t) init_debug(void)
208 {
209     volatile struct sysctrl_t *sys_ctrl =
210                                        (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S;
211 
212 #if defined(DAUTH_NONE)
213     /* Set all the debug enable selector bits to 1 */
214     sys_ctrl->secdbgset = All_SEL_STATUS;
215     /* Set all the debug enable bits to 0 */
216     sys_ctrl->secdbgclr =
217                    DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS;
218 #elif defined(DAUTH_NS_ONLY)
219     /* Set all the debug enable selector bits to 1 */
220     sys_ctrl->secdbgset = All_SEL_STATUS;
221     /* Set the debug enable bits to 1 for NS, and 0 for S mode */
222     sys_ctrl->secdbgset = DBGEN_STATUS | NIDEN_STATUS;
223     sys_ctrl->secdbgclr = SPIDEN_STATUS | SPNIDEN_STATUS;
224 #elif defined(DAUTH_FULL)
225     /* Set all the debug enable selector bits to 1 */
226     sys_ctrl->secdbgset = All_SEL_STATUS;
227     /* Set all the debug enable bits to 1 */
228     sys_ctrl->secdbgset =
229                    DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS;
230 #else
231 
232 #if !defined(DAUTH_CHIP_DEFAULT)
233 #error "No debug authentication setting is provided."
234 #endif
235 
236     /* Set all the debug enable selector bits to 0 */
237     sys_ctrl->secdbgclr = All_SEL_STATUS;
238 
239     /* No need to set any enable bits because the value depends on
240      * input signals.
241      */
242 #endif
243 
244     FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
245 }
246 
247 /*----------------- NVIC interrupt target state to NS configuration ----------*/
nvic_interrupt_target_state_cfg(void)248 enum tfm_plat_err_t nvic_interrupt_target_state_cfg(void)
249 {
250     /* Target every interrupt to NS; unimplemented interrupts will be WI */
251     for (uint8_t i=0; i<sizeof(NVIC->ITNS)/sizeof(NVIC->ITNS[0]); i++) {
252         NVIC->ITNS[i] = 0xFFFFFFFF;
253     }
254 
255     /* Make sure that MPC and PPC are targeted to S state */
256     NVIC_ClearTargetState(MPC_IRQn);
257     NVIC_ClearTargetState(PPC_IRQn);
258 
259 #ifdef SECURE_UART1
260     /* UART1 is a secure peripheral, so its IRQs have to target S state */
261     NVIC_ClearTargetState(UARTRX1_IRQn);
262     NVIC_ClearTargetState(UARTTX1_IRQn);
263     NVIC_ClearTargetState(UART1_IRQn);
264 #endif
265 
266     return TFM_PLAT_ERR_SUCCESS;
267 }
268 
269 /*----------------- NVIC interrupt enabling for S peripherals ----------------*/
nvic_interrupt_enable(void)270 enum tfm_plat_err_t nvic_interrupt_enable(void)
271 {
272     struct spctrl_def* spctrl = CMSDK_SPCTRL;
273     int32_t ret = ARM_DRIVER_OK;
274 
275     /* MPC interrupt enabling */
276     ret = Driver_SRAM1_MPC.EnableInterrupt();
277     if (ret != ARM_DRIVER_OK) {
278         return TFM_PLAT_ERR_SYSTEM_ERR;
279     }
280     ret = Driver_SRAM2_MPC.EnableInterrupt();
281     if (ret != ARM_DRIVER_OK) {
282         return TFM_PLAT_ERR_SYSTEM_ERR;
283     }
284     NVIC_EnableIRQ(MPC_IRQn);
285 
286     /* PPC interrupt enabling */
287     /* Clear pending PPC interrupts */
288     /* In the PPC configuration function, we have used the Non-Secure
289      * Privilege Control Block to grant unprivilged NS access to some
290      * peripherals used by NS. That triggers a PPC0 exception as that
291      * register is meant for NS privileged access only. Clear it here
292      */
293     spctrl->secppcintclr = CMSDK_APB_PPC0_INT_POS_MASK;
294 
295     /* Enable PPC interrupts for APB PPC */
296     spctrl->secppcinten |= CMSDK_APB_PPC0_INT_POS_MASK |
297                            CMSDK_APB_PPC1_INT_POS_MASK |
298                            CMSDK_APB_PPCEXP0_INT_POS_MASK |
299                            CMSDK_APB_PPCEXP1_INT_POS_MASK |
300                            CMSDK_APB_PPCEXP2_INT_POS_MASK |
301                            CMSDK_APB_PPCEXP3_INT_POS_MASK;
302 
303     NVIC_EnableIRQ(PPC_IRQn);
304 
305 #ifdef PSA_FF_TEST_SECURE_UART2
306     NVIC_EnableIRQ(FF_TEST_UART_IRQ);
307 #endif
308 
309     return TFM_PLAT_ERR_SUCCESS;
310 }
311 
312 /*------------------- SAU/IDAU configuration functions -----------------------*/
313 #if defined(PSA_API_TEST_NS) && !defined(PSA_API_TEST_IPC)
314 #define DEV_APIS_TEST_NVMEM_REGION_START (NS_DATA_LIMIT + 1)
315 #define DEV_APIS_TEST_NVMEM_REGION_LIMIT \
316     (DEV_APIS_TEST_NVMEM_REGION_START + DEV_APIS_TEST_NVMEM_REGION_SIZE - 1)
317 #endif
318 
319 struct sau_cfg_t {
320     uint32_t RBAR;
321     uint32_t RLAR;
322     bool nsc;
323 };
324 
325 const struct sau_cfg_t sau_cfg[] = {
326     {
327         ((uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base)),
328         ((uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
329         NS_PARTITION_SIZE - 1),
330         false,
331     },
332     {
333         NS_DATA_START,
334         NS_DATA_LIMIT,
335         false,
336     },
337     {
338         (uint32_t)&REGION_NAME(Image$$, ER_VENEER, $$Base),
339         (uint32_t)&REGION_NAME(Image$$, VENEER_ALIGN, $$Limit) - 1,
340         true,
341     },
342     {
343         PERIPHERALS_BASE_NS_START,
344 #if (defined(SECURE_UART1) && defined(PSA_FF_TEST_SECURE_UART2))
345         (UART1_BASE_NS - 1),
346         false,
347     },
348     {
349         UART3_BASE_NS,
350 #elif defined(PSA_FF_TEST_SECURE_UART2)
351         (UART2_BASE_NS - 1),
352         false,
353     },
354     {
355         UART3_BASE_NS,
356 #elif defined(SECURE_UART1)
357         (UART1_BASE_NS - 1),
358         false,
359     },
360     {
361         UART2_BASE_NS,
362 #endif
363         PERIPHERALS_BASE_NS_END,
364         false,
365     },
366 #ifdef BL2
367     {
368         (uint32_t)&REGION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base),
369         (uint32_t)&REGION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base) +
370         SECONDARY_PARTITION_SIZE - 1,
371         false,
372     },
373 #endif
374 #if defined(PSA_API_TEST_NS) && !defined(PSA_API_TEST_IPC)
375     {
376         DEV_APIS_TEST_NVMEM_REGION_START,
377         DEV_APIS_TEST_NVMEM_REGION_LIMIT,
378         false,
379     },
380 #endif
381 };
382 
383 #define NR_SAU_INIT_STEP                 3
384 
sau_and_idau_cfg(void)385 FIH_RET_TYPE(int32_t) sau_and_idau_cfg(void)
386 {
387     struct spctrl_def *spctrl = CMSDK_SPCTRL;
388     uint32_t i;
389 
390     /* Ensure all memory accesses are completed */
391     __DMB();
392 
393     /* Enables SAU */
394     TZ_SAU_Enable();
395 
396     for (i = 0; i < ARRAY_SIZE(sau_cfg); i++) {
397         SAU->RNR = i;
398         SAU->RBAR = sau_cfg[i].RBAR & SAU_RBAR_BADDR_Msk;
399         SAU->RLAR = (sau_cfg[i].RLAR & SAU_RLAR_LADDR_Msk) |
400                     (sau_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) |
401                     SAU_RLAR_ENABLE_Msk;
402     }
403 
404     /* Allows SAU to define the code region as a NSC */
405     spctrl->nsccfg |= NSCCFG_CODENSC;
406 
407     /* Ensure the write is completed and flush pipeline */
408     __DSB();
409     __ISB();
410 
411     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
412 }
413 
414 #ifdef TFM_FIH_PROFILE_ON
fih_verify_sau_and_idau_cfg(void)415 fih_int fih_verify_sau_and_idau_cfg(void)
416 {
417     struct spctrl_def *spctrl = CMSDK_SPCTRL;
418     uint32_t i;
419 
420     /* Check SAU is enabled */
421     if ((SAU->CTRL & (SAU_CTRL_ENABLE_Msk)) != (SAU_CTRL_ENABLE_Msk)) {
422         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
423     }
424 
425     for (i = 0; i < ARRAY_SIZE(sau_cfg); i++) {
426         SAU->RNR = i;
427         if (SAU->RBAR != (sau_cfg[i].RBAR & SAU_RBAR_BADDR_Msk)) {
428             FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
429         }
430         if (SAU->RLAR != ((sau_cfg[i].RLAR & SAU_RLAR_LADDR_Msk) |
431                           (sau_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) |
432                           SAU_RLAR_ENABLE_Msk)) {
433             FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
434         }
435     }
436 
437     if ((spctrl->nsccfg & (NSCCFG_CODENSC)) != (NSCCFG_CODENSC)) {
438         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
439     }
440 
441     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
442 }
443 #endif /* TFM_FIH_PROFILE_ON */
444 
445 /*------------------- Memory configuration functions -------------------------*/
446 #ifdef BL2
447 #define NR_MPC_INIT_STEP                 7
448 #else
449 #define NR_MPC_INIT_STEP                 6
450 #endif
451 
mpc_init_cfg(void)452 FIH_RET_TYPE(int32_t) mpc_init_cfg(void)
453 {
454     int32_t ret = ARM_DRIVER_OK;
455 
456     ret = Driver_SRAM1_MPC.Initialize();
457     if (ret != ARM_DRIVER_OK) {
458         FIH_RET(fih_int_encode(ret));
459     }
460 
461     ret = Driver_SRAM1_MPC.ConfigRegion(
462                                       memory_regions.non_secure_partition_base,
463                                       memory_regions.non_secure_partition_limit,
464                                       ARM_MPC_ATTR_NONSECURE);
465     if (ret != ARM_DRIVER_OK) {
466         FIH_RET(fih_int_encode(ret));
467     }
468 
469 #ifdef BL2
470     /* Secondary image region */
471     ret = Driver_SRAM1_MPC.ConfigRegion(memory_regions.secondary_partition_base,
472                                   memory_regions.secondary_partition_limit,
473                                   ARM_MPC_ATTR_NONSECURE);
474     if (ret != ARM_DRIVER_OK) {
475         FIH_RET(fih_int_encode(ret));
476     }
477 #endif /* BL2 */
478 
479     ret = Driver_SRAM2_MPC.Initialize();
480     if (ret != ARM_DRIVER_OK) {
481         FIH_RET(fih_int_encode(ret));
482     }
483 
484     ret = Driver_SRAM2_MPC.ConfigRegion(NS_DATA_START, NS_DATA_LIMIT,
485                                         ARM_MPC_ATTR_NONSECURE);
486 #if defined(PSA_API_TEST_NS) && !defined(PSA_API_TEST_IPC)
487     ret = Driver_SRAM2_MPC.ConfigRegion(DEV_APIS_TEST_NVMEM_REGION_START,
488                                         DEV_APIS_TEST_NVMEM_REGION_LIMIT,
489                                         ARM_MPC_ATTR_NONSECURE);
490 #endif
491     if (ret != ARM_DRIVER_OK) {
492         FIH_RET(fih_int_encode(ret));
493     }
494 
495     /* Lock down the MPC configuration */
496     ret = Driver_SRAM1_MPC.LockDown();
497     if (ret != ARM_DRIVER_OK) {
498         FIH_RET(fih_int_encode(ret));
499     }
500 
501     ret = Driver_SRAM2_MPC.LockDown();
502     if (ret != ARM_DRIVER_OK) {
503         FIH_RET(fih_int_encode(ret));
504     }
505 
506     /* Add barriers to assure the MPC configuration is done before continue
507      * the execution.
508      */
509     __DSB();
510     __ISB();
511 
512     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
513 }
514 
515 #ifdef TFM_FIH_PROFILE_ON
fih_verify_mpc_cfg(void)516 fih_int fih_verify_mpc_cfg(void)
517 {
518     ARM_MPC_SEC_ATTR attr;
519 
520     Driver_SRAM1_MPC.GetRegionConfig(memory_regions.non_secure_partition_base,
521                                      memory_regions.non_secure_partition_limit,
522                                      &attr);
523     if (attr != ARM_MPC_ATTR_NONSECURE) {
524         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
525     }
526 
527 #ifdef BL2
528     Driver_SRAM1_MPC.GetRegionConfig(memory_regions.secondary_partition_base,
529                                      memory_regions.secondary_partition_limit,
530                                      &attr);
531     if (attr != ARM_MPC_ATTR_NONSECURE) {
532         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
533     }
534 #endif /* BL2 */
535 
536     Driver_SRAM2_MPC.GetRegionConfig(NS_DATA_START, NS_DATA_LIMIT, &attr);
537     if (attr != ARM_MPC_ATTR_NONSECURE) {
538         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
539     }
540 
541 #if defined(PSA_API_TEST_NS) && !defined(PSA_API_TEST_IPC)
542     Driver_SRAM2_MPC.GetRegionConfig(DEV_APIS_TEST_NVMEM_REGION_START,
543                                      DEV_APIS_TEST_NVMEM_REGION_LIMIT,
544                                      &attr);
545     if (attr != ARM_MPC_ATTR_NONSECURE) {
546         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
547     }
548 #endif /* PSA_API_TEST_NS && !PSA_API_TEST_IPC */
549 
550     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
551 }
552 #endif /* TFM_FIH_PROFILE_ON */
553 
554 /*---------------------- PPC configuration functions -------------------------*/
555 #define NR_PPC_INIT_STEP                 4
556 
ppc_init_cfg(void)557 FIH_RET_TYPE(int32_t) ppc_init_cfg(void)
558 {
559     struct spctrl_def* spctrl = CMSDK_SPCTRL;
560     struct nspctrl_def* nspctrl = CMSDK_NSPCTRL;
561 
562     /* Grant non-secure access to peripherals in the PPC0
563      * (timer0 and 1, dualtimer, watchdog, mhu 0 and 1)
564      */
565      spctrl->apbnsppc0 |= (1U << CMSDK_TIMER0_APB_PPC_POS) |
566                           (1U << CMSDK_TIMER1_APB_PPC_POS) |
567                           (1U << CMSDK_DTIMER_APB_PPC_POS) |
568                           (1U << CMSDK_MHU0_APB_PPC_POS) |
569                           (1U << CMSDK_MHU1_APB_PPC_POS);
570 
571     /* Grant non-secure access for APB peripherals on EXP1 */
572     spctrl->apbnsppcexp1 |= (1U << CMSDK_SPI0_APB_PPC_POS) |
573                             (1U << CMSDK_SPI1_APB_PPC_POS) |
574                             (1U << CMSDK_SPI2_APB_PPC_POS) |
575                             (1U << CMSDK_SPI3_APB_PPC_POS) |
576                             (1U << CMSDK_SPI4_APB_PPC_POS) |
577                             (1U << CMSDK_UART0_APB_PPC_POS) |
578 #ifdef SECURE_UART1
579     /* To statically configure a peripheral as secure, skip PPC NS peripheral
580      * configuration for the given device.
581      */
582 #else
583                             (1U << CMSDK_UART1_APB_PPC_POS) |
584 #endif
585 
586 #ifndef PSA_FF_TEST_SECURE_UART2
587                             (1U << CMSDK_UART2_APB_PPC_POS) |
588 #endif
589                             (1U << CMSDK_UART3_APB_PPC_POS) |
590                             (1U << CMSDK_UART4_APB_PPC_POS) |
591                             (1U << CMSDK_I2C0_APB_PPC_POS) |
592                             (1U << CMSDK_I2C1_APB_PPC_POS) |
593                             (1U << CMSDK_I2C2_APB_PPC_POS) |
594                             (1U << CMSDK_I2C3_APB_PPC_POS);
595     /* Grant non-secure access for APB peripherals on EXP2 */
596     spctrl->apbnsppcexp2 |= (1U << CMSDK_FPGA_SCC_PPC_POS) |
597                             (1U << CMSDK_FPGA_AUDIO_PPC_POS) |
598                             (1U << CMSDK_FPGA_IO_PPC_POS);
599 
600     /* Grant non-secure access to all peripherals on AHB EXP:
601      * Make sure that all possible peripherals are enabled by default
602      */
603     spctrl->ahbnsppcexp0 |= (1U << CMSDK_VGA_PPC_POS) |
604                             (1U << CMSDK_GPIO0_PPC_POS) |
605                             (1U << CMSDK_GPIO1_PPC_POS) |
606                             (1U << CMSDK_GPIO2_PPC_POS) |
607                             (1U << CMSDK_GPIO3_PPC_POS) |
608                             (1U << MPS2_ETHERNET_PPC_POS);
609 
610     spctrl->ahbnsppcexp1 |= (1U << CMSDK_DMA0_PPC_POS) |
611                             (1U << CMSDK_DMA1_PPC_POS) |
612                             (1U << CMSDK_DMA2_PPC_POS) |
613                             (1U << CMSDK_DMA3_PPC_POS);
614 
615     /* in NS, grant un-privileged for UART0 */
616     nspctrl->apbnspppcexp1 |= (1U << CMSDK_UART0_APB_PPC_POS);
617 
618     /* in NS, grant un-privileged access for LEDs */
619     nspctrl->apbnspppcexp2 |= (1U << CMSDK_FPGA_SCC_PPC_POS) |
620                               (1U << CMSDK_FPGA_IO_PPC_POS);
621 
622     /* Configure the response to a security violation as a
623      * bus error instead of RAZ/WI
624      */
625     spctrl->secrespcfg |= 1U;
626 
627     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
628 }
629 
630 #ifdef TFM_FIH_PROFILE_ON
fih_verify_ppc_cfg(void)631 fih_int fih_verify_ppc_cfg(void)
632 {
633     struct spctrl_def* spctrl = CMSDK_SPCTRL;
634     struct nspctrl_def* nspctrl = CMSDK_NSPCTRL;
635 
636     /* Check non-secure access to peripherals in the PPC0
637      * (timer0 and 1, dualtimer, watchdog)
638      */
639     if ((!(spctrl->apbnsppc0 & (1U << CMSDK_TIMER0_APB_PPC_POS))) ||
640         (!(spctrl->apbnsppc0 & (1U << CMSDK_TIMER1_APB_PPC_POS))) ||
641         (!(spctrl->apbnsppc0 & (1U << CMSDK_DTIMER_APB_PPC_POS)))) {
642         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
643     }
644 
645     /* Check non-secure access for APB peripherals on EXP1 */
646     if ((!(spctrl->apbnsppcexp1 & (1U << CMSDK_SPI0_APB_PPC_POS))) ||
647         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_SPI1_APB_PPC_POS))) ||
648         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_SPI2_APB_PPC_POS))) ||
649         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_SPI3_APB_PPC_POS))) ||
650         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_SPI4_APB_PPC_POS))) ||
651         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_UART0_APB_PPC_POS))) ||
652 #ifdef SECURE_UART1
653     /* Peripheral is statically configured as secure, skip check on PPC NS
654      * peripheral configuration for the given device.
655      */
656 #else
657         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_UART1_APB_PPC_POS))) ||
658 
659 #endif
660 
661 #ifndef PSA_FF_TEST_SECURE_UART2
662         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_UART2_APB_PPC_POS))) ||
663 #endif
664         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_UART3_APB_PPC_POS))) ||
665         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_UART4_APB_PPC_POS))) ||
666         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_I2C0_APB_PPC_POS))) ||
667         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_I2C1_APB_PPC_POS))) ||
668         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_I2C2_APB_PPC_POS))) ||
669         (!(spctrl->apbnsppcexp1 & (1U << CMSDK_I2C3_APB_PPC_POS)))) {
670         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
671     }
672 
673     /* In NS, check un-privileged for UART0 */
674     if (!(nspctrl->apbnspppcexp1 & (1U << CMSDK_UART0_APB_PPC_POS))) {
675         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
676     }
677 
678     /* In NS, check un-privileged access for LEDs */
679     if ((!(nspctrl->apbnspppcexp2 & (1U << CMSDK_FPGA_SCC_PPC_POS))) ||
680         (!(nspctrl->apbnspppcexp2 & (1U << CMSDK_FPGA_IO_PPC_POS)))) {
681         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
682     }
683 
684     /* Check whether the response to a security violation is a
685      * bus error instead of RAZ/WI
686      */
687     if (!(spctrl->secrespcfg & 1U)) {
688         FIH_RET(fih_int_encode(ARM_DRIVER_ERROR));
689     }
690 
691     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
692 }
693 #endif /* TFM_FIH_PROFILE_ON */
694 
ppc_configure_to_non_secure(enum ppc_bank_e bank,uint16_t pos)695 void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t pos)
696 {
697     /* Setting NS flag for peripheral to enable NS access */
698     struct spctrl_def* spctrl = CMSDK_SPCTRL;
699     ((uint32_t*)&(spctrl->ahbnsppc0))[bank] |= (1U << pos);
700 }
701 
ppc_configure_to_secure(enum ppc_bank_e bank,uint16_t pos)702 FIH_RET_TYPE(int32_t) ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos)
703 {
704     /* Clear NS flag for peripheral to prevent NS access */
705     struct spctrl_def* spctrl = CMSDK_SPCTRL;
706     ((uint32_t*)&(spctrl->ahbnsppc0))[bank] &= ~(1U << pos);
707 
708     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
709 }
710 
ppc_en_secure_unpriv(enum ppc_bank_e bank,uint16_t pos)711 FIH_RET_TYPE(int32_t) ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
712 {
713     struct spctrl_def* spctrl = CMSDK_SPCTRL;
714     ((uint32_t*)&(spctrl->ahbspppc0))[bank] |= (1U << pos);
715 
716     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
717 }
718 
ppc_clr_secure_unpriv(enum ppc_bank_e bank,uint16_t pos)719 FIH_RET_TYPE(int32_t) ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
720 {
721     struct spctrl_def* spctrl = CMSDK_SPCTRL;
722     ((uint32_t*)&(spctrl->ahbspppc0))[bank] &= ~(1U << pos);
723 
724     FIH_RET(fih_int_encode(ARM_DRIVER_OK));
725 }
726 
ppc_clear_irq(void)727 void ppc_clear_irq(void)
728 {
729     struct spctrl_def* spctrl = CMSDK_SPCTRL;
730     /* Clear APB PPC EXP2 IRQ */
731     spctrl->secppcintclr = CMSDK_APB_PPCEXP2_INT_POS_MASK;
732 }
733