xref: /aosp_15_r20/external/arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <lib/mmio.h>
8*54fd6939SJiyong Park #include <lib/utils_def.h>
9*54fd6939SJiyong Park 
10*54fd6939SJiyong Park #include "uniphier.h"
11*54fd6939SJiyong Park 
12*54fd6939SJiyong Park #define UNIPHIER_ROM_RSV3		0x5980120c
13*54fd6939SJiyong Park 
14*54fd6939SJiyong Park #define UNIPHIER_STMBE2COM		0x5f800030
15*54fd6939SJiyong Park #define UNIPHIER_STMTOBEIRQ		0x5f800060
16*54fd6939SJiyong Park #define UNIPHIER_BETOSTMIRQ0PT		0x5f800070
17*54fd6939SJiyong Park #define UNIPHIER_BEIRQCLRPT		0x5f800072
18*54fd6939SJiyong Park 
19*54fd6939SJiyong Park #define UNIPHIER_SCP_READY_MAGIC	0x0000b6a5
20*54fd6939SJiyong Park 
21*54fd6939SJiyong Park #define UNIPHIER_SCP_PACKET_START	0xA0
22*54fd6939SJiyong Park #define UNIPHIER_SCP_PACKET_END		0xA5
23*54fd6939SJiyong Park #define UNIPHIER_SCP_PACKET_ESC		0xA6
24*54fd6939SJiyong Park #define UNIPHIER_SCP_IS_CTRL_CODE(c)	(0xA0 <= (c) && (c) <= 0xA6)
25*54fd6939SJiyong Park 
uniphier_scp_is_running(void)26*54fd6939SJiyong Park int uniphier_scp_is_running(void)
27*54fd6939SJiyong Park {
28*54fd6939SJiyong Park 	return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC;
29*54fd6939SJiyong Park }
30*54fd6939SJiyong Park 
uniphier_scp_start(uint32_t scp_base)31*54fd6939SJiyong Park void uniphier_scp_start(uint32_t scp_base)
32*54fd6939SJiyong Park {
33*54fd6939SJiyong Park 	uint32_t tmp;
34*54fd6939SJiyong Park 
35*54fd6939SJiyong Park 	mmio_write_32(UNIPHIER_STMBE2COM + 4, scp_base);
36*54fd6939SJiyong Park 	mmio_write_32(UNIPHIER_STMBE2COM, UNIPHIER_SCP_READY_MAGIC);
37*54fd6939SJiyong Park 
38*54fd6939SJiyong Park 	do {
39*54fd6939SJiyong Park 		tmp = mmio_read_32(UNIPHIER_ROM_RSV3);
40*54fd6939SJiyong Park 	} while (!(tmp & BIT(8)));
41*54fd6939SJiyong Park 
42*54fd6939SJiyong Park 	mmio_write_32(UNIPHIER_ROM_RSV3, tmp | BIT(9));
43*54fd6939SJiyong Park }
44*54fd6939SJiyong Park 
uniphier_scp_send_packet(const uint8_t * packet,int packet_len)45*54fd6939SJiyong Park static void uniphier_scp_send_packet(const uint8_t *packet, int packet_len)
46*54fd6939SJiyong Park {
47*54fd6939SJiyong Park 	uintptr_t reg = UNIPHIER_STMBE2COM;
48*54fd6939SJiyong Park 	uint32_t word;
49*54fd6939SJiyong Park 	int len, i;
50*54fd6939SJiyong Park 
51*54fd6939SJiyong Park 	while (packet_len) {
52*54fd6939SJiyong Park 		len = MIN(packet_len, 4);
53*54fd6939SJiyong Park 		word = 0;
54*54fd6939SJiyong Park 
55*54fd6939SJiyong Park 		for (i = 0; i < len; i++)
56*54fd6939SJiyong Park 			word |= *packet++ << (8 * i);
57*54fd6939SJiyong Park 
58*54fd6939SJiyong Park 		mmio_write_32(reg, word);
59*54fd6939SJiyong Park 		reg += 4;
60*54fd6939SJiyong Park 		packet_len -= len;
61*54fd6939SJiyong Park 	}
62*54fd6939SJiyong Park 
63*54fd6939SJiyong Park 	mmio_write_8(UNIPHIER_BETOSTMIRQ0PT, 0x55);
64*54fd6939SJiyong Park 
65*54fd6939SJiyong Park 	while (!(mmio_read_32(UNIPHIER_STMTOBEIRQ) & BIT(1)))
66*54fd6939SJiyong Park 		;
67*54fd6939SJiyong Park 	mmio_write_8(UNIPHIER_BEIRQCLRPT, BIT(1) | BIT(0));
68*54fd6939SJiyong Park }
69*54fd6939SJiyong Park 
uniphier_scp_send_cmd(const uint8_t * cmd,int cmd_len)70*54fd6939SJiyong Park static void uniphier_scp_send_cmd(const uint8_t *cmd, int cmd_len)
71*54fd6939SJiyong Park {
72*54fd6939SJiyong Park 	uint8_t packet[32];	/* long enough */
73*54fd6939SJiyong Park 	uint8_t *p = packet;
74*54fd6939SJiyong Park 	uint8_t c;
75*54fd6939SJiyong Park 	int i;
76*54fd6939SJiyong Park 
77*54fd6939SJiyong Park 	*p++ = UNIPHIER_SCP_PACKET_START;
78*54fd6939SJiyong Park 	*p++ = cmd_len;
79*54fd6939SJiyong Park 
80*54fd6939SJiyong Park 	for (i = 0; i < cmd_len; i++) {
81*54fd6939SJiyong Park 		c = *cmd++;
82*54fd6939SJiyong Park 		if (UNIPHIER_SCP_IS_CTRL_CODE(c)) {
83*54fd6939SJiyong Park 			*p++ = UNIPHIER_SCP_PACKET_ESC;
84*54fd6939SJiyong Park 			*p++ = c ^ BIT(7);
85*54fd6939SJiyong Park 		} else {
86*54fd6939SJiyong Park 			*p++ = c;
87*54fd6939SJiyong Park 		}
88*54fd6939SJiyong Park 	}
89*54fd6939SJiyong Park 
90*54fd6939SJiyong Park 	*p++ = UNIPHIER_SCP_PACKET_END;
91*54fd6939SJiyong Park 
92*54fd6939SJiyong Park 	uniphier_scp_send_packet(packet, p - packet);
93*54fd6939SJiyong Park }
94*54fd6939SJiyong Park 
95*54fd6939SJiyong Park #define UNIPHIER_SCP_CMD(name, ...)					\
96*54fd6939SJiyong Park static const uint8_t __uniphier_scp_##name##_cmd[] = {			\
97*54fd6939SJiyong Park 	__VA_ARGS__							\
98*54fd6939SJiyong Park };									\
99*54fd6939SJiyong Park void uniphier_scp_##name(void)						\
100*54fd6939SJiyong Park {									\
101*54fd6939SJiyong Park 	uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd,		\
102*54fd6939SJiyong Park 			      ARRAY_SIZE(__uniphier_scp_##name##_cmd));	\
103*54fd6939SJiyong Park }
104*54fd6939SJiyong Park 
105*54fd6939SJiyong Park UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05)
106*54fd6939SJiyong Park UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01)
107*54fd6939SJiyong Park UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00)
108