1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017, Schneider Electric
4  * Copyright (c) 2020, Linaro Limited
5  */
6 
7 #include <arm.h>
8 #include <io.h>
9 #include <kernel/boot.h>
10 #include <kernel/misc.h>
11 #include <mm/core_memprot.h>
12 #include <platform_config.h>
13 #include <sm/psci.h>
14 #include <sm/std_smc.h>
15 
16 #define SYSCTRL_REG_RSTEN		(SYSCTRL_BASE + 0x120)
17 #define SYSCTRL_REG_RSTCTRL		(SYSCTRL_BASE + 0x198)
18 #define SYSCTRL_BOOTADDR_REG		(SYSCTRL_BASE + 0x204)
19 
20 #define SYSCTRL_REG_RSTEN_MRESET_EN	BIT(0)
21 #define SYSCTRL_REG_RSTEN_SWRST_EN	BIT(6)
22 #define SYSCTRL_REG_RSTCTRL_SWRST_REQ	BIT(6)
23 
psci_features(uint32_t psci_fid)24 int psci_features(uint32_t psci_fid)
25 {
26 	switch (psci_fid) {
27 	case PSCI_PSCI_FEATURES:
28 	case PSCI_VERSION:
29 	case PSCI_CPU_ON:
30 	case PSCI_CPU_OFF:
31 	case PSCI_SYSTEM_RESET:
32 		return PSCI_RET_SUCCESS;
33 	default:
34 		return PSCI_RET_NOT_SUPPORTED;
35 	}
36 }
37 
psci_version(void)38 uint32_t psci_version(void)
39 {
40 	return PSCI_VERSION_1_0;
41 }
42 
psci_cpu_on(uint32_t core_id,uint32_t entry,uint32_t context_id)43 int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id)
44 {
45 	vaddr_t sctl_va = core_mmu_get_va(SYSCTRL_BOOTADDR_REG,
46 					  MEM_AREA_IO_SEC,
47 					  sizeof(uint32_t));
48 
49 	if (core_id == 0 || core_id >= CFG_TEE_CORE_NB_CORE)
50 		return PSCI_RET_INVALID_PARAMETERS;
51 
52 	DMSG("core_id: %" PRIu32, core_id);
53 
54 	boot_set_core_ns_entry(core_id, entry, context_id);
55 	io_write32(sctl_va, TEE_LOAD_ADDR);
56 
57 	dsb();
58 	sev();
59 
60 	return PSCI_RET_SUCCESS;
61 }
62 
psci_cpu_off(void)63 int __noreturn psci_cpu_off(void)
64 {
65 	DMSG("core_id: %" PRIu32, get_core_pos());
66 
67 	psci_armv7_cpu_off();
68 
69 	thread_mask_exceptions(THREAD_EXCP_ALL);
70 
71 	while (1)
72 		wfi();
73 }
74 
psci_system_reset(void)75 void psci_system_reset(void)
76 {
77 	/* Enable software reset */
78 	io_setbits32(core_mmu_get_va(SYSCTRL_REG_RSTEN, MEM_AREA_IO_SEC,
79 				     sizeof(uint32_t)),
80 		     SYSCTRL_REG_RSTEN_SWRST_EN | SYSCTRL_REG_RSTEN_MRESET_EN);
81 
82 	/* Trigger software reset */
83 	io_setbits32(core_mmu_get_va(SYSCTRL_REG_RSTCTRL, MEM_AREA_IO_SEC,
84 				     sizeof(uint32_t)),
85 		     SYSCTRL_REG_RSTCTRL_SWRST_REQ);
86 
87 	dsb();
88 }
89