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