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 24 int uniphier_scp_is_running(void) 25 { 26 return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC; 27 } 28 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 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 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