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