1 /* 2 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <lib/mmio.h> 8 #include <lib/utils_def.h> 9 10 #include "uniphier.h" 11 12 #define UNIPHIER_ROM_RSV3 0x5980120c 13 14 #define UNIPHIER_STMBE2COM 0x5f800030 15 #define UNIPHIER_STMTOBEIRQ 0x5f800060 16 #define UNIPHIER_BETOSTMIRQ0PT 0x5f800070 17 #define UNIPHIER_BEIRQCLRPT 0x5f800072 18 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 26 int uniphier_scp_is_running(void) 27 { 28 return mmio_read_32(UNIPHIER_STMBE2COM) == UNIPHIER_SCP_READY_MAGIC; 29 } 30 31 void uniphier_scp_start(uint32_t scp_base) 32 { 33 uint32_t tmp; 34 35 mmio_write_32(UNIPHIER_STMBE2COM + 4, 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 45 static 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); 64 65 while (!(mmio_read_32(UNIPHIER_STMTOBEIRQ) & BIT(1))) 66 ; 67 mmio_write_8(UNIPHIER_BEIRQCLRPT, BIT(1) | BIT(0)); 68 } 69 70 static 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, ...) \ 96 static const uint8_t __uniphier_scp_##name##_cmd[] = { \ 97 __VA_ARGS__ \ 98 }; \ 99 void uniphier_scp_##name(void) \ 100 { \ 101 uniphier_scp_send_cmd(__uniphier_scp_##name##_cmd, \ 102 ARRAY_SIZE(__uniphier_scp_##name##_cmd)); \ 103 } 104 105 UNIPHIER_SCP_CMD(open_com, 0x00, 0x00, 0x05) 106 UNIPHIER_SCP_CMD(system_off, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01) 107 UNIPHIER_SCP_CMD(system_reset, 0x00, 0x02, 0x00) 108