blob: 2390bcad8a187cbcf9f923f0480579987470a5f1 [file] [log] [blame]
Antonio Nino Diaz272e8712018-09-18 01:36:00 +01001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <mmio.h>
9#include <platform.h>
10#include <platform_def.h>
11#include <string.h>
12
13#include "gxbb_private.h"
14
15#define SIZE_SHIFT 20
16#define SIZE_MASK 0x1FF
17
18/*
19 * Note: The Amlogic SCP firmware uses the legacy SCPI protocol.
20 */
21#define SCPI_CMD_SET_CSS_POWER_STATE 0x04
22#define SCPI_CMD_SET_SYS_POWER_STATE 0x08
23
24#define SCPI_CMD_JTAG_SET_STATE 0xC0
25#define SCPI_CMD_EFUSE_READ 0xC2
26
27static inline uint32_t scpi_cmd(uint32_t command, uint32_t size)
28{
29 return command | (size << SIZE_SHIFT);
30}
31
32void scpi_secure_message_send(uint32_t command, uint32_t size)
33{
34 mhu_secure_message_send(scpi_cmd(command, size));
35}
36
37uint32_t scpi_secure_message_receive(void **message_out, size_t *size_out)
38{
39 uint32_t response = mhu_secure_message_wait();
40
41 size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
42
43 response &= ~(SIZE_MASK << SIZE_SHIFT);
44
45 if (size_out != NULL)
46 *size_out = size;
47
48 if (message_out != NULL)
49 *message_out = (void *)GXBB_MHU_SECURE_SCP_TO_AP_PAYLOAD;
50
51 return response;
52}
53
54void scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
55 uint32_t cluster_state, uint32_t css_state)
56{
57 uint32_t state = (mpidr & 0x0F) | /* CPU ID */
58 ((mpidr & 0xF00) >> 4) | /* Cluster ID */
59 (cpu_state << 8) |
60 (cluster_state << 12) |
61 (css_state << 16);
62
63 mhu_secure_message_start();
64 mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, state);
65 mhu_secure_message_send(scpi_cmd(SCPI_CMD_SET_CSS_POWER_STATE, 4));
66 mhu_secure_message_wait();
67 mhu_secure_message_end();
68}
69
70uint32_t scpi_sys_power_state(uint64_t system_state)
71{
72 uint32_t *response;
73 size_t size;
74
75 mhu_secure_message_start();
76 mmio_write_8(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, system_state);
77 mhu_secure_message_send(scpi_cmd(SCPI_CMD_SET_SYS_POWER_STATE, 1));
78 scpi_secure_message_receive((void *)&response, &size);
79 mhu_secure_message_end();
80
81 return *response;
82}
83
84void scpi_jtag_set_state(uint32_t state, uint8_t select)
85{
86 assert(state <= GXBB_JTAG_STATE_OFF);
87
88 if (select > GXBB_JTAG_A53_EE) {
89 WARN("BL31: Invalid JTAG select (0x%x).\n", select);
90 return;
91 }
92
93 mhu_secure_message_start();
94 mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD,
95 (state << 8) | (uint32_t)select);
96 mhu_secure_message_send(scpi_cmd(SCPI_CMD_JTAG_SET_STATE, 4));
97 mhu_secure_message_wait();
98 mhu_secure_message_end();
99}
100
101uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size)
102{
103 uint32_t *response;
104 size_t resp_size;
105
106 if (size > 0x1FC)
107 return 0;
108
109 mhu_secure_message_start();
110 mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, base);
111 mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 4, size);
112 mhu_secure_message_send(scpi_cmd(SCPI_CMD_EFUSE_READ, 8));
113 scpi_secure_message_receive((void *)&response, &resp_size);
114 mhu_secure_message_end();
115
116 /*
117 * response[0] is the size of the response message.
118 * response[1 ... N] are the contents.
119 */
120 if (*response != 0)
121 memcpy(dst, response + 1, *response);
122
123 return *response;
124}
125
126void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
127 uint32_t arg2, uint32_t arg3)
128{
129 mhu_secure_message_start();
130 mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x0, arg0);
131 mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x4, arg1);
132 mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x8, arg2);
133 mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0xC, arg3);
134 mhu_secure_message_send(scpi_cmd(0xC3, 16));
135 mhu_secure_message_wait();
136 mhu_secure_message_end();
137}