/* * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "uniphier.h" #define UNIPHIER_ROM_RSV3 0x5980120c #define UNIPHIER_STMBE2COM 0x5f800030 #define UNIPHIER_BETOSTMIRQ0PT 0x5f800070 #define UNIPHIER_SCP_READY_MAGIC 0x0000b6a5 #define UNIPHIER_SCP_PACKET_START 0xA0 #define UNIPHIER_SCP_PACKET_END 0xA5 #define UNIPHIER_SCP_PACKET_ESC 0xA6 #define UNIPHIER_SCP_IS_CTRL_CODE(c) (0xA0 <= (c) && (c) <= 0xA6) int uniphier_scp_is_running(void) { return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC; } void uniphier_scp_start(void) { uint32_t tmp; mmio_write_32(UNIPHIER_STMBE2COM + 4, UNIPHIER_SCP_BASE); mmio_write_32(UNIPHIER_STMBE2COM, UNIPHIER_SCP_READY_MAGIC); do { tmp = mmio_read_32(UNIPHIER_ROM_RSV3); } while (!(tmp & BIT(8))); mmio_write_32(UNIPHIER_ROM_RSV3, tmp | BIT(9)); } static void uniphier_scp_send_packet(const uint8_t *packet, int packet_len) { uintptr_t reg = UNIPHIER_STMBE2COM; uint32_t word; int len, i; while (packet_len) { len = MIN(packet_len, 4); word = 0; for (i = 0; i < len; i++) word |= *packet++ << (8 * i); mmio_write_32(reg, word); reg += 4; packet_len -= len; } mmio_write_8(UNIPHIER_BETOSTMIRQ0PT, 0x55); } static void uniphier_scp_send_cmd(const uint8_t *cmd, int cmd_len) { uint8_t packet[32]; /* long enough */ uint8_t *p = packet; uint8_t c; int i; *p++ = UNIPHIER_SCP_PACKET_START; *p++ = cmd_len; for (i = 0; i < cmd_len; i++) { c = *cmd++; if (UNIPHIER_SCP_IS_CTRL_CODE(c)) { *p++ = UNIPHIER_SCP_PACKET_ESC; *p++ = c ^ BIT(7); } else { *p++ = c; } } *p++ = UNIPHIER_SCP_PACKET_END; uniphier_scp_send_packet(packet, p - packet); } #define UNIPHIER_SCP_CMD(name, ...) \ static const uint8_t __uniphier_scp_##name##_cmd[] = { \ __VA_ARGS__ \ }; \ void uniphier_scp_##name(void) \ { \ uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd, \ ARRAY_SIZE(__uniphier_scp_##name##_cmd)); \ } UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05) UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01) UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00)