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