xref: /arm-trusted-firmware/plat/amlogic/common/aml_scpi.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <crypto/sha_dma.h>
9*91f16700Schasinglulu #include <lib/mmio.h>
10*91f16700Schasinglulu #include <plat/common/platform.h>
11*91f16700Schasinglulu #include <platform_def.h>
12*91f16700Schasinglulu #include <string.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu #include "aml_private.h"
15*91f16700Schasinglulu 
16*91f16700Schasinglulu #define SIZE_SHIFT	20
17*91f16700Schasinglulu #define SIZE_MASK	0x1FF
18*91f16700Schasinglulu #define SIZE_FWBLK	0x200UL
19*91f16700Schasinglulu 
20*91f16700Schasinglulu /*
21*91f16700Schasinglulu  * Note: The Amlogic SCP firmware uses the legacy SCPI protocol.
22*91f16700Schasinglulu  */
23*91f16700Schasinglulu #define SCPI_CMD_SET_CSS_POWER_STATE	0x04
24*91f16700Schasinglulu #define SCPI_CMD_SET_SYS_POWER_STATE	0x08
25*91f16700Schasinglulu 
26*91f16700Schasinglulu #define SCPI_CMD_JTAG_SET_STATE		0xC0
27*91f16700Schasinglulu #define SCPI_CMD_EFUSE_READ		0xC2
28*91f16700Schasinglulu #define SCPI_CMD_CHIP_ID		0xC6
29*91f16700Schasinglulu 
30*91f16700Schasinglulu #define SCPI_CMD_COPY_FW 0xd4
31*91f16700Schasinglulu #define SCPI_CMD_SET_FW_ADDR 0xd3
32*91f16700Schasinglulu #define SCPI_CMD_FW_SIZE 0xd2
33*91f16700Schasinglulu 
34*91f16700Schasinglulu static inline uint32_t aml_scpi_cmd(uint32_t command, uint32_t size)
35*91f16700Schasinglulu {
36*91f16700Schasinglulu 	return command | (size << SIZE_SHIFT);
37*91f16700Schasinglulu }
38*91f16700Schasinglulu 
39*91f16700Schasinglulu static void aml_scpi_secure_message_send(uint32_t command, uint32_t size)
40*91f16700Schasinglulu {
41*91f16700Schasinglulu 	aml_mhu_secure_message_send(aml_scpi_cmd(command, size));
42*91f16700Schasinglulu }
43*91f16700Schasinglulu 
44*91f16700Schasinglulu static uint32_t aml_scpi_secure_message_receive(void **message_out, size_t *size_out)
45*91f16700Schasinglulu {
46*91f16700Schasinglulu 	uint32_t response = aml_mhu_secure_message_wait();
47*91f16700Schasinglulu 
48*91f16700Schasinglulu 	size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
49*91f16700Schasinglulu 
50*91f16700Schasinglulu 	response &= ~(SIZE_MASK << SIZE_SHIFT);
51*91f16700Schasinglulu 
52*91f16700Schasinglulu 	if (size_out != NULL)
53*91f16700Schasinglulu 		*size_out = size;
54*91f16700Schasinglulu 
55*91f16700Schasinglulu 	if (message_out != NULL)
56*91f16700Schasinglulu 		*message_out = (void *)AML_MHU_SECURE_SCP_TO_AP_PAYLOAD;
57*91f16700Schasinglulu 
58*91f16700Schasinglulu 	return response;
59*91f16700Schasinglulu }
60*91f16700Schasinglulu 
61*91f16700Schasinglulu void aml_scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
62*91f16700Schasinglulu 			      uint32_t cluster_state, uint32_t css_state)
63*91f16700Schasinglulu {
64*91f16700Schasinglulu 	uint32_t state = (mpidr & 0x0F) | /* CPU ID */
65*91f16700Schasinglulu 			 ((mpidr & 0xF00) >> 4) | /* Cluster ID */
66*91f16700Schasinglulu 			 (cpu_state << 8) |
67*91f16700Schasinglulu 			 (cluster_state << 12) |
68*91f16700Schasinglulu 			 (css_state << 16);
69*91f16700Schasinglulu 
70*91f16700Schasinglulu 	aml_mhu_secure_message_start();
71*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, state);
72*91f16700Schasinglulu 	aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_SET_CSS_POWER_STATE, 4));
73*91f16700Schasinglulu 	aml_mhu_secure_message_wait();
74*91f16700Schasinglulu 	aml_mhu_secure_message_end();
75*91f16700Schasinglulu }
76*91f16700Schasinglulu 
77*91f16700Schasinglulu uint32_t aml_scpi_sys_power_state(uint64_t system_state)
78*91f16700Schasinglulu {
79*91f16700Schasinglulu 	uint32_t *response;
80*91f16700Schasinglulu 	size_t size;
81*91f16700Schasinglulu 
82*91f16700Schasinglulu 	aml_mhu_secure_message_start();
83*91f16700Schasinglulu 	mmio_write_8(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, system_state);
84*91f16700Schasinglulu 	aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_SET_SYS_POWER_STATE, 1));
85*91f16700Schasinglulu 	aml_scpi_secure_message_receive((void *)&response, &size);
86*91f16700Schasinglulu 	aml_mhu_secure_message_end();
87*91f16700Schasinglulu 
88*91f16700Schasinglulu 	return *response;
89*91f16700Schasinglulu }
90*91f16700Schasinglulu 
91*91f16700Schasinglulu void aml_scpi_jtag_set_state(uint32_t state, uint8_t select)
92*91f16700Schasinglulu {
93*91f16700Schasinglulu 	assert(state <= AML_JTAG_STATE_OFF);
94*91f16700Schasinglulu 
95*91f16700Schasinglulu 	if (select > AML_JTAG_A53_EE) {
96*91f16700Schasinglulu 		WARN("BL31: Invalid JTAG select (0x%x).\n", select);
97*91f16700Schasinglulu 		return;
98*91f16700Schasinglulu 	}
99*91f16700Schasinglulu 
100*91f16700Schasinglulu 	aml_mhu_secure_message_start();
101*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD,
102*91f16700Schasinglulu 		      (state << 8) | (uint32_t)select);
103*91f16700Schasinglulu 	aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_JTAG_SET_STATE, 4));
104*91f16700Schasinglulu 	aml_mhu_secure_message_wait();
105*91f16700Schasinglulu 	aml_mhu_secure_message_end();
106*91f16700Schasinglulu }
107*91f16700Schasinglulu 
108*91f16700Schasinglulu uint32_t aml_scpi_efuse_read(void *dst, uint32_t base, uint32_t size)
109*91f16700Schasinglulu {
110*91f16700Schasinglulu 	uint32_t *response;
111*91f16700Schasinglulu 	size_t resp_size;
112*91f16700Schasinglulu 
113*91f16700Schasinglulu 	if (size > 0x1FC)
114*91f16700Schasinglulu 		return 0;
115*91f16700Schasinglulu 
116*91f16700Schasinglulu 	aml_mhu_secure_message_start();
117*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, base);
118*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 4, size);
119*91f16700Schasinglulu 	aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_EFUSE_READ, 8));
120*91f16700Schasinglulu 	aml_scpi_secure_message_receive((void *)&response, &resp_size);
121*91f16700Schasinglulu 	aml_mhu_secure_message_end();
122*91f16700Schasinglulu 
123*91f16700Schasinglulu 	/*
124*91f16700Schasinglulu 	 * response[0] is the size of the response message.
125*91f16700Schasinglulu 	 * response[1 ... N] are the contents.
126*91f16700Schasinglulu 	 */
127*91f16700Schasinglulu 	if (*response != 0)
128*91f16700Schasinglulu 		memcpy(dst, response + 1, *response);
129*91f16700Schasinglulu 
130*91f16700Schasinglulu 	return *response;
131*91f16700Schasinglulu }
132*91f16700Schasinglulu 
133*91f16700Schasinglulu void aml_scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
134*91f16700Schasinglulu 			      uint32_t arg2, uint32_t arg3)
135*91f16700Schasinglulu {
136*91f16700Schasinglulu 	aml_mhu_secure_message_start();
137*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x0, arg0);
138*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x4, arg1);
139*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x8, arg2);
140*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0xC, arg3);
141*91f16700Schasinglulu 	aml_mhu_secure_message_send(aml_scpi_cmd(0xC3, 16));
142*91f16700Schasinglulu 	aml_mhu_secure_message_wait();
143*91f16700Schasinglulu 	aml_mhu_secure_message_end();
144*91f16700Schasinglulu }
145*91f16700Schasinglulu 
146*91f16700Schasinglulu uint32_t aml_scpi_get_chip_id(uint8_t *obuff, uint32_t osize)
147*91f16700Schasinglulu {
148*91f16700Schasinglulu 	uint32_t *response;
149*91f16700Schasinglulu 	size_t resp_size;
150*91f16700Schasinglulu 
151*91f16700Schasinglulu 	if ((osize != 16) && (osize != 12))
152*91f16700Schasinglulu 		return 0;
153*91f16700Schasinglulu 
154*91f16700Schasinglulu 	aml_mhu_secure_message_start();
155*91f16700Schasinglulu 	aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_CHIP_ID, osize));
156*91f16700Schasinglulu 	aml_scpi_secure_message_receive((void *)&response, &resp_size);
157*91f16700Schasinglulu 	aml_mhu_secure_message_end();
158*91f16700Schasinglulu 
159*91f16700Schasinglulu 	if (!((resp_size == 16) && (osize == 16)) &&
160*91f16700Schasinglulu 	    !((resp_size == 0) && (osize == 12)))
161*91f16700Schasinglulu 		return 0;
162*91f16700Schasinglulu 
163*91f16700Schasinglulu 	memcpy((void *)obuff, (const void *)response, osize);
164*91f16700Schasinglulu 
165*91f16700Schasinglulu 	return osize;
166*91f16700Schasinglulu }
167*91f16700Schasinglulu 
168*91f16700Schasinglulu static inline void aml_scpi_copy_scp_data(uint8_t *data, size_t len)
169*91f16700Schasinglulu {
170*91f16700Schasinglulu 	void *dst = (void *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
171*91f16700Schasinglulu 	size_t sz;
172*91f16700Schasinglulu 
173*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
174*91f16700Schasinglulu 	aml_scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
175*91f16700Schasinglulu 	aml_mhu_secure_message_wait();
176*91f16700Schasinglulu 
177*91f16700Schasinglulu 	for (sz = 0; sz < len; sz += SIZE_FWBLK) {
178*91f16700Schasinglulu 		memcpy(dst, data + sz, MIN(SIZE_FWBLK, len - sz));
179*91f16700Schasinglulu 		aml_mhu_secure_message_send(SCPI_CMD_COPY_FW);
180*91f16700Schasinglulu 	}
181*91f16700Schasinglulu }
182*91f16700Schasinglulu 
183*91f16700Schasinglulu static inline void aml_scpi_set_scp_addr(uint64_t addr, size_t len)
184*91f16700Schasinglulu {
185*91f16700Schasinglulu 	volatile uint64_t *dst = (uint64_t *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
186*91f16700Schasinglulu 
187*91f16700Schasinglulu 	/*
188*91f16700Schasinglulu 	 * It is ok as AML_MHU_SECURE_AP_TO_SCP_PAYLOAD is mapped as
189*91f16700Schasinglulu 	 * non cachable
190*91f16700Schasinglulu 	 */
191*91f16700Schasinglulu 	*dst = addr;
192*91f16700Schasinglulu 	aml_scpi_secure_message_send(SCPI_CMD_SET_FW_ADDR, sizeof(addr));
193*91f16700Schasinglulu 	aml_mhu_secure_message_wait();
194*91f16700Schasinglulu 
195*91f16700Schasinglulu 	mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
196*91f16700Schasinglulu 	aml_scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
197*91f16700Schasinglulu 	aml_mhu_secure_message_wait();
198*91f16700Schasinglulu }
199*91f16700Schasinglulu 
200*91f16700Schasinglulu static inline void aml_scpi_send_fw_hash(uint8_t hash[], size_t len)
201*91f16700Schasinglulu {
202*91f16700Schasinglulu 	void *dst = (void *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
203*91f16700Schasinglulu 
204*91f16700Schasinglulu 	memcpy(dst, hash, len);
205*91f16700Schasinglulu 	aml_mhu_secure_message_send(0xd0);
206*91f16700Schasinglulu 	aml_mhu_secure_message_send(0xd1);
207*91f16700Schasinglulu 	aml_mhu_secure_message_send(0xd5);
208*91f16700Schasinglulu 	aml_mhu_secure_message_end();
209*91f16700Schasinglulu }
210*91f16700Schasinglulu 
211*91f16700Schasinglulu /**
212*91f16700Schasinglulu  * Upload a FW to SCP.
213*91f16700Schasinglulu  *
214*91f16700Schasinglulu  * @param addr: firmware data address
215*91f16700Schasinglulu  * @param size: size of firmware
216*91f16700Schasinglulu  * @param send: If set, actually copy the firmware in SCP memory otherwise only
217*91f16700Schasinglulu  *  send the firmware address.
218*91f16700Schasinglulu  */
219*91f16700Schasinglulu void aml_scpi_upload_scp_fw(uintptr_t addr, size_t size, int send)
220*91f16700Schasinglulu {
221*91f16700Schasinglulu 	struct asd_ctx ctx;
222*91f16700Schasinglulu 
223*91f16700Schasinglulu 	asd_sha_init(&ctx, ASM_SHA256);
224*91f16700Schasinglulu 	asd_sha_update(&ctx, (void *)addr, size);
225*91f16700Schasinglulu 	asd_sha_finalize(&ctx);
226*91f16700Schasinglulu 
227*91f16700Schasinglulu 	aml_mhu_secure_message_start();
228*91f16700Schasinglulu 	if (send == 0)
229*91f16700Schasinglulu 		aml_scpi_set_scp_addr(addr, size);
230*91f16700Schasinglulu 	else
231*91f16700Schasinglulu 		aml_scpi_copy_scp_data((void *)addr, size);
232*91f16700Schasinglulu 
233*91f16700Schasinglulu 	aml_scpi_send_fw_hash(ctx.digest, sizeof(ctx.digest));
234*91f16700Schasinglulu }
235