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