blob: 58eb72eff0f94fdf4ea5fd7dcb46ddbea66c314a [file] [log] [blame]
Masahiro Yamada574388c2016-09-03 11:37:40 +09001/*
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
Dai Okamura331a1132018-10-05 08:56:24 +090015#define UNIPHIER_STMTOBEIRQ 0x5f800060
Masahiro Yamada574388c2016-09-03 11:37:40 +090016#define UNIPHIER_BETOSTMIRQ0PT 0x5f800070
Dai Okamura331a1132018-10-05 08:56:24 +090017#define UNIPHIER_BEIRQCLRPT 0x5f800072
Masahiro Yamada574388c2016-09-03 11:37:40 +090018
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
26int uniphier_scp_is_running(void)
27{
28 return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC;
29}
30
31void uniphier_scp_start(void)
32{
33 uint32_t tmp;
34
35 mmio_write_32(UNIPHIER_STMBE2COM + 4, UNIPHIER_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
45static 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);
Dai Okamura331a1132018-10-05 08:56:24 +090064
65 while (!(mmio_read_32(UNIPHIER_STMTOBEIRQ) & BIT(1)))
66 ;
67 mmio_write_8(UNIPHIER_BEIRQCLRPT, BIT(1) | BIT(0));
Masahiro Yamada574388c2016-09-03 11:37:40 +090068}
69
70static 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, ...) \
96static const uint8_t __uniphier_scp_##name##_cmd[] = { \
97 __VA_ARGS__ \
98}; \
99void uniphier_scp_##name(void) \
100{ \
101 uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd, \
102 ARRAY_SIZE(__uniphier_scp_##name##_cmd)); \
103}
104
105UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05)
106UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01)
107UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00)