Home | History | Annotate | Download | only in uniphier
      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