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