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