xref: /optee_os/core/drivers/versal_pm.c (revision 3c1ae96f5b67bcef7cea8eac690e2ba85ad8aa56) !
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2022 Foundries.io Ltd
4  * Jorge Ramirez-Ortiz <jorge@foundries.io>
5  */
6 
7 #include <arm.h>
8 #include <drivers/versal_pm.h>
9 #include <drivers/versal_pmc.h>
10 #include <initcall.h>
11 #include <kernel/cache_helpers.h>
12 #include <kernel/delay.h>
13 #include <kernel/panic.h>
14 #include <kernel/thread.h>
15 #include <mm/core_memprot.h>
16 #include <string.h>
17 #include <tee/cache.h>
18 #include <tee_api_types.h>
19 #include <utee_defines.h>
20 
21 #ifdef PLATFORM_FLAVOR_net
22 /* VERSAL_SIP_UID: 80d4c25a-ebaf-11eb-94680b4e3b8fc360 */
23 #define VERSAL_SIP_UID_0 U(0x5ac2d480)
24 #define VERSAL_SIP_UID_1 U(0xeb11afeb)
25 #define VERSAL_SIP_UID_2 U(0x4e0b6894)
26 #define VERSAL_SIP_UID_3 U(0x60c38f3b)
27 #else
28 /* VERSAL_SIP_UID: 2ab9e4ec-93b9-11e7-a019dfe0dbad0ae0 */
29 #define VERSAL_SIP_UID_0 U(0xece4b92a)
30 #define VERSAL_SIP_UID_1 U(0xe711b993)
31 #define VERSAL_SIP_UID_2 U(0xe0df19a0)
32 #define VERSAL_SIP_UID_3 U(0xe00aaddb)
33 #endif
34 #define VERSAL_SIP_MAJOR  0
35 #define VERSAL_SIP_MINOR  1
36 
37 #define VERSAL_SIP_SVC_VERSION		0x8200ff03
38 #define VERSAL_SIP_SVC_UID		0x8200ff01
39 #define VERSAL_SIP_SVC			0xc2000000
40 
41 #define PAYLOAD_ARG_CNT		8
42 
43 /* MBOX IPI */
44 #define PM_MODULE_SHIFT		8
45 #define PM_MODULE		2
46 #define PM_API_ID(x)		((PM_MODULE << PM_MODULE_SHIFT) | (x))
47 #define VERSAL_PM_MAJOR		1
48 #define VERSAL_PM_MINOR		0
49 
50 /* PM API ids */
51 #define PM_GET_API_VERSION		1
52 #define PM_GET_DEVICE_STATUS		3
53 #define PM_GET_OP_CHARACTERISTIC	4
54 #define PM_REGISTER_NOTIFIER		5
55 #define PM_REQ_SUSPEND			6
56 #define PM_SELF_SUSPEND			7
57 #define PM_FORCE_POWERDOWN		8
58 #define PM_ABORT_SUSPEND		9
59 #define PM_REQ_WAKEUP			10
60 #define PM_SET_WAKEUP_SOURCE		11
61 #define PM_SYSTEM_SHUTDOWN		12
62 #define PM_REQUEST_DEVICE		13
63 #define PM_RELEASE_DEVICE		14
64 #define PM_SET_REQUIREMENT		15
65 #define PM_SET_MAX_LATENCY		16
66 #define PM_RESET_ASSERT			17
67 #define PM_RESET_GET_STATUS		18
68 #define PM_INIT_FINALIZE		21
69 #define PM_GET_CHIPID			24
70 #define	PM_PINCTRL_REQUEST		28
71 #define	PM_PINCTRL_RELEASE		29
72 #define	PM_PINCTRL_GET_FUNCTION		30
73 #define	PM_PINCTRL_SET_FUNCTION		31
74 #define	PM_PINCTRL_CONFIG_PARAM_GET	32
75 #define	PM_PINCTRL_CONFIG_PARAM_SET	33
76 #define PM_IOCTL			34
77 #define PM_QUERY_DATA			35
78 #define PM_CLOCK_ENABLE			36
79 #define PM_CLOCK_DISABLE		37
80 #define PM_CLOCK_GETSTATE		38
81 #define PM_CLOCK_SETDIVIDER		39
82 #define PM_CLOCK_GETDIVIDER		40
83 #define PM_CLOCK_SETRATE		41
84 #define PM_CLOCK_GETRATE		42
85 #define PM_CLOCK_SETPARENT		43
86 #define PM_CLOCK_GETPARENT		44
87 #define PM_PLL_SET_PARAMETER		48
88 #define PM_PLL_GET_PARAMETER		49
89 #define PM_PLL_SET_MODE			50
90 #define PM_PLL_GET_MODE			51
91 #define PM_FEATURE_CHECK		63
92 
93 /* Loader API id */
94 #define PM_LOAD_PDI			0x701
95 
96 /* PDI sources */
97 #define PDI_SRC_JTAG		0x0
98 #define PDI_SRC_QSPI24		0x1
99 #define PDI_SRC_QSPI32		0x2
100 #define PDI_SRC_SD0		0x3
101 #define PDI_SRC_EMMC0		0x4
102 #define PDI_SRC_SD1		0x5
103 #define PDI_SRC_EMMC1		0x6
104 #define PDI_SRC_USB		0x7
105 #define PDI_SRC_OSPI		0x8
106 #define PDI_SRC_SBI		0x9
107 #define PDI_SRC_SMAP		0xA
108 #define PDI_SRC_PCIE		0xB
109 #define PDI_SRC_SD1_LS		0xE
110 #define PDI_SRC_DDR		0xF
111 
112 struct versal_sip_payload {
113 	uint32_t data[PAYLOAD_ARG_CNT];
114 };
115 
versal_sip_call(uint32_t smc_fid,uint32_t arg0,uint32_t arg1,uint32_t arg2,uint32_t arg3,struct versal_sip_payload * payload)116 static uint32_t versal_sip_call(uint32_t smc_fid, uint32_t arg0, uint32_t arg1,
117 				uint32_t arg2, uint32_t arg3,
118 				struct versal_sip_payload *payload)
119 {
120 	struct thread_smc_args args = {
121 		.a0 = smc_fid,
122 		.a1 = reg_pair_to_64(arg1, arg0),
123 		.a2 = reg_pair_to_64(arg3, arg2),
124 	};
125 
126 	thread_smccc(&args);
127 
128 	if (payload) {
129 		reg_pair_from_64(args.a0, &payload->data[1], &payload->data[0]);
130 		reg_pair_from_64(args.a1, &payload->data[3], &payload->data[2]);
131 		reg_pair_from_64(args.a2, &payload->data[5], &payload->data[4]);
132 		reg_pair_from_64(args.a3, &payload->data[7], &payload->data[6]);
133 	}
134 
135 	/* allow the PLM to output its debug information */
136 	if (IS_ENABLED(CFG_VERSAL_TRACE_PLM))
137 		mdelay(500);
138 
139 	return args.a0;
140 }
141 
142 /* SIP call to program the FPGA has been obsoleted, use the PLM */
versal_write_fpga(paddr_t pa)143 TEE_Result versal_write_fpga(paddr_t pa)
144 {
145 	struct versal_ipi_cmd cmd = { };
146 
147 	cmd.data[0] = PM_LOAD_PDI;
148 	cmd.data[1] = PDI_SRC_DDR;
149 	reg_pair_from_64(pa, &cmd.data[2], &cmd.data[3]);
150 
151 	if (versal_pmc_notify(&cmd, NULL, NULL))
152 		return TEE_ERROR_GENERIC;
153 
154 	return TEE_SUCCESS;
155 }
156 
versal_soc_version(uint8_t * version)157 TEE_Result versal_soc_version(uint8_t *version)
158 {
159 	struct versal_sip_payload p = { };
160 	const uint32_t version_shift = 12;
161 
162 	if (!version)
163 		return TEE_ERROR_BAD_PARAMETERS;
164 
165 	if (versal_sip_call(VERSAL_SIP_SVC | PM_GET_CHIPID, 0, 0, 0, 0, &p))
166 		return TEE_ERROR_GENERIC;
167 
168 	*version = p.data[2] >> version_shift;
169 
170 	return TEE_SUCCESS;
171 }
172 
uuid_is_versal_pm(void)173 static bool uuid_is_versal_pm(void)
174 {
175 	struct versal_sip_payload p = { };
176 
177 	versal_sip_call(VERSAL_SIP_SVC_UID, 0, 0, 0, 0, &p);
178 
179 	if (p.data[0] == VERSAL_SIP_UID_0 && p.data[2] == VERSAL_SIP_UID_1 &&
180 	    p.data[4] == VERSAL_SIP_UID_2 && p.data[6] == VERSAL_SIP_UID_3)
181 		return true;
182 
183 	return false;
184 }
185 
versal_check_pm_abi(void)186 static TEE_Result versal_check_pm_abi(void)
187 {
188 	struct versal_sip_payload p = { };
189 	struct versal_ipi_cmd cmd = { };
190 	struct versal_ipi_cmd rsp = { };
191 	unsigned int major = 0;
192 	unsigned int minor = 0;
193 
194 	if (!uuid_is_versal_pm()) {
195 		EMSG("Invalid SiP Service");
196 		return TEE_ERROR_GENERIC;
197 	}
198 
199 	if (versal_sip_call(VERSAL_SIP_SVC_VERSION, 0, 0, 0, 0, &p))
200 		return TEE_ERROR_GENERIC;
201 
202 	major = p.data[0];
203 	minor = p.data[2];
204 	if (major != VERSAL_SIP_MAJOR || minor < VERSAL_SIP_MINOR) {
205 		EMSG("Invalid SiP version: Major %d, Minor %d", major, minor);
206 		return TEE_ERROR_GENERIC;
207 	}
208 
209 	cmd.data[0] = PM_API_ID(PM_GET_API_VERSION);
210 	if (versal_pmc_notify(&cmd, &rsp, NULL))
211 		return TEE_ERROR_GENERIC;
212 
213 	minor = rsp.data[1] & 0xFFFF;
214 	major = rsp.data[1] >> 16;
215 	if (major != VERSAL_PM_MAJOR || (int)minor < VERSAL_PM_MINOR) {
216 		EMSG("Invalid PM version: Major %d, Minor %d", major, minor);
217 		return TEE_ERROR_GENERIC;
218 	}
219 
220 	return TEE_SUCCESS;
221 }
222 
223 early_init_late(versal_check_pm_abi);
224