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