GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <sq_common.h>
|
||||
#include "sq_mhu.h"
|
||||
|
||||
/* SCP MHU secure channel registers */
|
||||
#define SCP_INTR_S_STAT 0x200
|
||||
#define SCP_INTR_S_SET 0x208
|
||||
#define SCP_INTR_S_CLEAR 0x210
|
||||
|
||||
/* CPU MHU secure channel registers */
|
||||
#define CPU_INTR_S_STAT 0x300
|
||||
#define CPU_INTR_S_SET 0x308
|
||||
#define CPU_INTR_S_CLEAR 0x310
|
||||
|
||||
DEFINE_BAKERY_LOCK(sq_lock);
|
||||
|
||||
/*
|
||||
* Slot 31 is reserved because the MHU hardware uses this register bit to
|
||||
* indicate a non-secure access attempt. The total number of available slots is
|
||||
* therefore 31 [30:0].
|
||||
*/
|
||||
#define MHU_MAX_SLOT_ID 30
|
||||
|
||||
void mhu_secure_message_start(unsigned int slot_id)
|
||||
{
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
|
||||
bakery_lock_get(&sq_lock);
|
||||
|
||||
/* Make sure any previous command has finished */
|
||||
while (mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
|
||||
(1 << slot_id))
|
||||
;
|
||||
}
|
||||
|
||||
void mhu_secure_message_send(unsigned int slot_id)
|
||||
{
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
assert(!(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) &
|
||||
(1 << slot_id)));
|
||||
|
||||
/* Send command to SCP */
|
||||
mmio_write_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id);
|
||||
}
|
||||
|
||||
uint32_t mhu_secure_message_wait(void)
|
||||
{
|
||||
uint32_t response;
|
||||
|
||||
/* Wait for response from SCP */
|
||||
while (!(response = mmio_read_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_STAT)))
|
||||
;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void mhu_secure_message_end(unsigned int slot_id)
|
||||
{
|
||||
assert(slot_id <= MHU_MAX_SLOT_ID);
|
||||
|
||||
/*
|
||||
* Clear any response we got by writing one in the relevant slot bit to
|
||||
* the CLEAR register
|
||||
*/
|
||||
mmio_write_32(PLAT_SQ_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id);
|
||||
|
||||
bakery_lock_release(&sq_lock);
|
||||
}
|
||||
|
||||
void mhu_secure_init(void)
|
||||
{
|
||||
bakery_lock_init(&sq_lock);
|
||||
|
||||
/*
|
||||
* The STAT register resets to zero. Ensure it is in the expected state,
|
||||
* as a stale or garbage value would make us think it's a message we've
|
||||
* already sent.
|
||||
*/
|
||||
assert(mmio_read_32(PLAT_SQ_MHU_BASE + CPU_INTR_S_STAT) == 0);
|
||||
}
|
||||
|
||||
void plat_sq_pwrc_setup(void)
|
||||
{
|
||||
mhu_secure_init();
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SQ_MHU_H
|
||||
#define SQ_MHU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void mhu_secure_message_start(unsigned int slot_id);
|
||||
void mhu_secure_message_send(unsigned int slot_id);
|
||||
uint32_t mhu_secure_message_wait(void);
|
||||
void mhu_secure_message_end(unsigned int slot_id);
|
||||
|
||||
void mhu_secure_init(void);
|
||||
|
||||
#endif /* SQ_MHU_H */
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/css/css_mhu_doorbell.h>
|
||||
#include <drivers/arm/css/css_scp.h>
|
||||
#include <drivers/arm/css/scmi.h>
|
||||
#include <plat/arm/css/common/css_pm.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <scmi_sq.h>
|
||||
#include <sq_common.h>
|
||||
|
||||
/*
|
||||
* This file implements the SCP helper functions using SCMI protocol.
|
||||
*/
|
||||
|
||||
DEFINE_BAKERY_LOCK(sq_scmi_lock);
|
||||
#define SQ_SCMI_LOCK_GET_INSTANCE (&sq_scmi_lock)
|
||||
|
||||
#define SQ_SCMI_PAYLOAD_BASE PLAT_SQ_SCP_COM_SHARED_MEM_BASE
|
||||
#define MHU_CPU_INTR_S_SET_OFFSET 0x308
|
||||
|
||||
const uint32_t sq_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
|
||||
};
|
||||
|
||||
static scmi_channel_plat_info_t sq_scmi_plat_info = {
|
||||
.scmi_mbx_mem = SQ_SCMI_PAYLOAD_BASE,
|
||||
.db_reg_addr = PLAT_SQ_MHU_BASE + MHU_CPU_INTR_S_SET_OFFSET,
|
||||
.db_preserve_mask = 0xfffffffe,
|
||||
.db_modify_mask = 0x1,
|
||||
.ring_doorbell = &mhu_ring_doorbell,
|
||||
};
|
||||
|
||||
/*
|
||||
* SCMI power state parameter bit field encoding for SynQuacer platform.
|
||||
*
|
||||
* 31 20 19 16 15 12 11 8 7 4 3 0
|
||||
* +-------------------------------------------------------------+
|
||||
* | SBZ | Max level | Level 3 | Level 2 | Level 1 | Level 0 |
|
||||
* | | | state | state | state | state |
|
||||
* +-------------------------------------------------------------+
|
||||
*
|
||||
* `Max level` encodes the highest level that has a valid power state
|
||||
* encoded in the power state.
|
||||
*/
|
||||
#define SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT 16
|
||||
#define SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH 4
|
||||
#define SCMI_PWR_STATE_MAX_PWR_LVL_MASK \
|
||||
((1 << SCMI_PWR_STATE_MAX_PWR_LVL_WIDTH) - 1)
|
||||
#define SCMI_SET_PWR_STATE_MAX_PWR_LVL(_power_state, _max_level) \
|
||||
(_power_state) |= ((_max_level) & SCMI_PWR_STATE_MAX_PWR_LVL_MASK)\
|
||||
<< SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT
|
||||
#define SCMI_GET_PWR_STATE_MAX_PWR_LVL(_power_state) \
|
||||
(((_power_state) >> SCMI_PWR_STATE_MAX_PWR_LVL_SHIFT) \
|
||||
& SCMI_PWR_STATE_MAX_PWR_LVL_MASK)
|
||||
|
||||
#define SCMI_PWR_STATE_LVL_WIDTH 4
|
||||
#define SCMI_PWR_STATE_LVL_MASK \
|
||||
((1 << SCMI_PWR_STATE_LVL_WIDTH) - 1)
|
||||
#define SCMI_SET_PWR_STATE_LVL(_power_state, _level, _level_state) \
|
||||
(_power_state) |= ((_level_state) & SCMI_PWR_STATE_LVL_MASK) \
|
||||
<< (SCMI_PWR_STATE_LVL_WIDTH * (_level))
|
||||
#define SCMI_GET_PWR_STATE_LVL(_power_state, _level) \
|
||||
(((_power_state) >> (SCMI_PWR_STATE_LVL_WIDTH * (_level))) & \
|
||||
SCMI_PWR_STATE_LVL_MASK)
|
||||
|
||||
/*
|
||||
* The SCMI power state enumeration for a power domain level
|
||||
*/
|
||||
typedef enum {
|
||||
scmi_power_state_off = 0,
|
||||
scmi_power_state_on = 1,
|
||||
scmi_power_state_sleep = 2,
|
||||
} scmi_power_state_t;
|
||||
|
||||
/*
|
||||
* The global handle for invoking the SCMI driver APIs after the driver
|
||||
* has been initialized.
|
||||
*/
|
||||
static void *sq_scmi_handle;
|
||||
|
||||
/* The SCMI channel global object */
|
||||
static scmi_channel_t channel;
|
||||
|
||||
/*
|
||||
* Helper function to turn off a CPU power domain and
|
||||
* its parent power domains if applicable.
|
||||
*/
|
||||
void sq_scmi_off(const struct psci_power_state *target_state)
|
||||
{
|
||||
int lvl = 0, ret;
|
||||
uint32_t scmi_pwr_state = 0;
|
||||
|
||||
/* At-least the CPU level should be specified to be OFF */
|
||||
assert(target_state->pwr_domain_state[SQ_PWR_LVL0] ==
|
||||
SQ_LOCAL_STATE_OFF);
|
||||
|
||||
for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
|
||||
if (target_state->pwr_domain_state[lvl] == SQ_LOCAL_STATE_RUN)
|
||||
break;
|
||||
|
||||
assert(target_state->pwr_domain_state[lvl] ==
|
||||
SQ_LOCAL_STATE_OFF);
|
||||
SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl,
|
||||
scmi_power_state_off);
|
||||
}
|
||||
|
||||
SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
|
||||
|
||||
ret = scmi_pwr_state_set(sq_scmi_handle,
|
||||
sq_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()],
|
||||
scmi_pwr_state);
|
||||
|
||||
if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) {
|
||||
ERROR("SCMI set power state command return 0x%x unexpected\n",
|
||||
ret);
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to turn ON a CPU power domain and
|
||||
*its parent power domains if applicable.
|
||||
*/
|
||||
void sq_scmi_on(u_register_t mpidr)
|
||||
{
|
||||
int lvl = 0, ret, core_pos;
|
||||
uint32_t scmi_pwr_state = 0;
|
||||
|
||||
for (; lvl <= PLAT_MAX_PWR_LVL; lvl++)
|
||||
SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, lvl,
|
||||
scmi_power_state_on);
|
||||
|
||||
SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
|
||||
|
||||
core_pos = plat_core_pos_by_mpidr(mpidr);
|
||||
assert(core_pos >= 0 && core_pos < PLATFORM_CORE_COUNT);
|
||||
|
||||
ret = scmi_pwr_state_set(sq_scmi_handle,
|
||||
sq_core_pos_to_scmi_dmn_id_map[core_pos],
|
||||
scmi_pwr_state);
|
||||
|
||||
if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) {
|
||||
ERROR("SCMI set power state command return 0x%x unexpected\n",
|
||||
ret);
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
void __dead2 sq_scmi_system_off(int state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Disable GIC CPU interface to prevent pending interrupt from waking
|
||||
* up the AP from WFI.
|
||||
*/
|
||||
sq_gic_cpuif_disable();
|
||||
|
||||
/*
|
||||
* Issue SCMI command. First issue a graceful
|
||||
* request and if that fails force the request.
|
||||
*/
|
||||
ret = scmi_sys_pwr_state_set(sq_scmi_handle,
|
||||
SCMI_SYS_PWR_FORCEFUL_REQ,
|
||||
state);
|
||||
|
||||
if (ret != SCMI_E_SUCCESS) {
|
||||
ERROR("SCMI system power state set 0x%x returns unexpected 0x%x\n",
|
||||
state, ret);
|
||||
panic();
|
||||
}
|
||||
wfi();
|
||||
ERROR("SCMI set power state: operation not handled.\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to reset the system via SCMI.
|
||||
*/
|
||||
void __dead2 sq_scmi_sys_shutdown(void)
|
||||
{
|
||||
sq_scmi_system_off(SCMI_SYS_PWR_SHUTDOWN);
|
||||
}
|
||||
|
||||
void __dead2 sq_scmi_sys_reboot(void)
|
||||
{
|
||||
sq_scmi_system_off(SCMI_SYS_PWR_COLD_RESET);
|
||||
}
|
||||
|
||||
static int scmi_ap_core_init(scmi_channel_t *ch)
|
||||
{
|
||||
#if PROGRAMMABLE_RESET_ADDRESS
|
||||
uint32_t version;
|
||||
int ret;
|
||||
|
||||
ret = scmi_proto_version(ch, SCMI_AP_CORE_PROTO_ID, &version);
|
||||
if (ret != SCMI_E_SUCCESS) {
|
||||
WARN("SCMI AP core protocol version message failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!is_scmi_version_compatible(SCMI_AP_CORE_PROTO_VER, version)) {
|
||||
WARN("SCMI AP core protocol version 0x%x incompatible with driver version 0x%x\n",
|
||||
version, SCMI_AP_CORE_PROTO_VER);
|
||||
return -1;
|
||||
}
|
||||
INFO("SCMI AP core protocol version 0x%x detected\n", version);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init plat_sq_pwrc_setup(void)
|
||||
{
|
||||
channel.info = &sq_scmi_plat_info;
|
||||
channel.lock = SQ_SCMI_LOCK_GET_INSTANCE;
|
||||
sq_scmi_handle = scmi_init(&channel);
|
||||
if (sq_scmi_handle == NULL) {
|
||||
ERROR("SCMI Initialization failed\n");
|
||||
panic();
|
||||
}
|
||||
if (scmi_ap_core_init(&channel) < 0) {
|
||||
ERROR("SCMI AP core protocol initialization failed\n");
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t sq_scmi_get_draminfo(struct draminfo *info)
|
||||
{
|
||||
scmi_get_draminfo(sq_scmi_handle, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <sq_common.h>
|
||||
#include "sq_scpi.h"
|
||||
|
||||
/*
|
||||
* Helper function to get dram information from SCP.
|
||||
*/
|
||||
uint32_t sq_scp_get_draminfo(struct draminfo *info)
|
||||
{
|
||||
#if SQ_USE_SCMI_DRIVER
|
||||
sq_scmi_get_draminfo(info);
|
||||
#else
|
||||
scpi_get_draminfo(info);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <sq_common.h>
|
||||
|
||||
#include "sq_mhu.h"
|
||||
#include "sq_scpi.h"
|
||||
|
||||
#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_SQ_SCP_COM_SHARED_MEM_BASE
|
||||
#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_SQ_SCP_COM_SHARED_MEM_BASE \
|
||||
+ 0x100)
|
||||
|
||||
#define SCPI_CMD_HEADER_AP_TO_SCP \
|
||||
((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
|
||||
#define SCPI_CMD_PAYLOAD_AP_TO_SCP \
|
||||
((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
|
||||
|
||||
/* ID of the MHU slot used for the SCPI protocol */
|
||||
#define SCPI_MHU_SLOT_ID 0
|
||||
|
||||
static void scpi_secure_message_start(void)
|
||||
{
|
||||
mhu_secure_message_start(SCPI_MHU_SLOT_ID);
|
||||
}
|
||||
|
||||
static void scpi_secure_message_send(size_t payload_size)
|
||||
{
|
||||
/*
|
||||
* Ensure that any write to the SCPI payload area is seen by SCP before
|
||||
* we write to the MHU register. If these 2 writes were reordered by
|
||||
* the CPU then SCP would read stale payload data
|
||||
*/
|
||||
dmbst();
|
||||
|
||||
mhu_secure_message_send(SCPI_MHU_SLOT_ID);
|
||||
}
|
||||
|
||||
static void scpi_secure_message_receive(scpi_cmd_t *cmd)
|
||||
{
|
||||
uint32_t mhu_status;
|
||||
|
||||
assert(cmd != NULL);
|
||||
|
||||
mhu_status = mhu_secure_message_wait();
|
||||
|
||||
/* Expect an SCPI message, reject any other protocol */
|
||||
if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
|
||||
ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
|
||||
mhu_status);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that any read to the SCPI payload area is done after reading
|
||||
* the MHU register. If these 2 reads were reordered then the CPU would
|
||||
* read invalid payload data
|
||||
*/
|
||||
dmbld();
|
||||
|
||||
memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
|
||||
}
|
||||
|
||||
static void scpi_secure_message_end(void)
|
||||
{
|
||||
mhu_secure_message_end(SCPI_MHU_SLOT_ID);
|
||||
}
|
||||
|
||||
int scpi_wait_ready(void)
|
||||
{
|
||||
scpi_cmd_t scpi_cmd;
|
||||
scpi_status_t status = SCP_OK;
|
||||
|
||||
VERBOSE("Waiting for SCP_READY command...\n");
|
||||
|
||||
/* Get a message from the SCP */
|
||||
scpi_secure_message_start();
|
||||
scpi_secure_message_receive(&scpi_cmd);
|
||||
scpi_secure_message_end();
|
||||
|
||||
/* We are expecting 'SCP Ready', produce correct error if it's not */
|
||||
if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
|
||||
ERROR("Unexpected SCP command: expected command #%u,"
|
||||
"got command #%u\n", SCPI_CMD_SCP_READY, scpi_cmd.id);
|
||||
status = SCP_E_SUPPORT;
|
||||
} else if (scpi_cmd.size != 0) {
|
||||
ERROR("SCP_READY command has incorrect size: expected 0,"
|
||||
"got %u\n", scpi_cmd.size);
|
||||
status = SCP_E_SIZE;
|
||||
}
|
||||
|
||||
VERBOSE("Sending response for SCP_READY command\n");
|
||||
|
||||
/*
|
||||
* Send our response back to SCP.
|
||||
* We are using the same SCPI header, just update the status field.
|
||||
*/
|
||||
scpi_cmd.status = status;
|
||||
scpi_secure_message_start();
|
||||
memcpy((void *) SCPI_SHARED_MEM_AP_TO_SCP, &scpi_cmd, sizeof(scpi_cmd));
|
||||
scpi_secure_message_send(0);
|
||||
scpi_secure_message_end();
|
||||
|
||||
return status == SCP_OK ? 0 : -1;
|
||||
}
|
||||
|
||||
void scpi_set_sq_power_state(unsigned int mpidr, scpi_power_state_t cpu_state,
|
||||
scpi_power_state_t cluster_state, scpi_power_state_t sq_state)
|
||||
{
|
||||
scpi_cmd_t *cmd;
|
||||
uint32_t state = 0;
|
||||
uint32_t *payload_addr;
|
||||
|
||||
state |= mpidr & 0x0f; /* CPU ID */
|
||||
state |= (mpidr & 0xf00) >> 4; /* Cluster ID */
|
||||
state |= cpu_state << 8;
|
||||
state |= cluster_state << 12;
|
||||
state |= sq_state << 16;
|
||||
|
||||
scpi_secure_message_start();
|
||||
|
||||
/* Populate the command header */
|
||||
cmd = SCPI_CMD_HEADER_AP_TO_SCP;
|
||||
cmd->id = SCPI_CMD_SET_POWER_STATE;
|
||||
cmd->set = SCPI_SET_NORMAL;
|
||||
cmd->sender = 0;
|
||||
cmd->size = sizeof(state);
|
||||
/* Populate the command payload */
|
||||
payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
|
||||
*payload_addr = state;
|
||||
scpi_secure_message_send(sizeof(state));
|
||||
|
||||
/*
|
||||
* SCP does not reply to this command in order to avoid MHU interrupts
|
||||
* from the sender, which could interfere with its power state request.
|
||||
*/
|
||||
scpi_secure_message_end();
|
||||
}
|
||||
|
||||
uint32_t scpi_sys_power_state(scpi_system_state_t system_state)
|
||||
{
|
||||
scpi_cmd_t *cmd;
|
||||
uint8_t *payload_addr;
|
||||
scpi_cmd_t response;
|
||||
|
||||
scpi_secure_message_start();
|
||||
|
||||
/* Populate the command header */
|
||||
cmd = SCPI_CMD_HEADER_AP_TO_SCP;
|
||||
cmd->id = SCPI_CMD_SYS_POWER_STATE;
|
||||
cmd->set = 0;
|
||||
cmd->sender = 0;
|
||||
cmd->size = sizeof(*payload_addr);
|
||||
/* Populate the command payload */
|
||||
payload_addr = SCPI_CMD_PAYLOAD_AP_TO_SCP;
|
||||
*payload_addr = system_state & 0xff;
|
||||
scpi_secure_message_send(sizeof(*payload_addr));
|
||||
|
||||
scpi_secure_message_receive(&response);
|
||||
|
||||
scpi_secure_message_end();
|
||||
|
||||
return response.status;
|
||||
}
|
||||
|
||||
uint32_t scpi_get_draminfo(struct draminfo *info)
|
||||
{
|
||||
scpi_cmd_t *cmd;
|
||||
struct {
|
||||
scpi_cmd_t cmd;
|
||||
struct draminfo info;
|
||||
} response;
|
||||
uint32_t mhu_status;
|
||||
|
||||
scpi_secure_message_start();
|
||||
|
||||
/* Populate the command header */
|
||||
cmd = SCPI_CMD_HEADER_AP_TO_SCP;
|
||||
cmd->id = SCPI_CMD_GET_DRAMINFO;
|
||||
cmd->set = SCPI_SET_EXTENDED;
|
||||
cmd->sender = 0;
|
||||
cmd->size = 0;
|
||||
|
||||
scpi_secure_message_send(0);
|
||||
|
||||
mhu_status = mhu_secure_message_wait();
|
||||
|
||||
/* Expect an SCPI message, reject any other protocol */
|
||||
if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
|
||||
ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
|
||||
mhu_status);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that any read to the SCPI payload area is done after reading
|
||||
* the MHU register. If these 2 reads were reordered then the CPU would
|
||||
* read invalid payload data
|
||||
*/
|
||||
dmbld();
|
||||
|
||||
memcpy(&response, (void *)SCPI_SHARED_MEM_SCP_TO_AP, sizeof(response));
|
||||
|
||||
scpi_secure_message_end();
|
||||
|
||||
if (response.cmd.status == SCP_OK)
|
||||
*info = response.info;
|
||||
|
||||
return response.cmd.status;
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SQ_SCPI_H
|
||||
#define SQ_SCPI_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* An SCPI command consists of a header and a payload.
|
||||
* The following structure describes the header. It is 64-bit long.
|
||||
*/
|
||||
typedef struct {
|
||||
/* Command ID */
|
||||
uint32_t id : 7;
|
||||
/* Set ID. Identifies whether this is a standard or extended command. */
|
||||
uint32_t set : 1;
|
||||
/* Sender ID to match a reply. The value is sender specific. */
|
||||
uint32_t sender : 8;
|
||||
/* Size of the payload in bytes (0 - 511) */
|
||||
uint32_t size : 9;
|
||||
uint32_t reserved : 7;
|
||||
/*
|
||||
* Status indicating the success of a command.
|
||||
* See the enum below.
|
||||
*/
|
||||
uint32_t status;
|
||||
} scpi_cmd_t;
|
||||
|
||||
typedef enum {
|
||||
SCPI_SET_NORMAL = 0, /* Normal SCPI commands */
|
||||
SCPI_SET_EXTENDED /* Extended SCPI commands */
|
||||
} scpi_set_t;
|
||||
|
||||
enum {
|
||||
SCP_OK = 0, /* Success */
|
||||
SCP_E_PARAM, /* Invalid parameter(s) */
|
||||
SCP_E_ALIGN, /* Invalid alignment */
|
||||
SCP_E_SIZE, /* Invalid size */
|
||||
SCP_E_HANDLER, /* Invalid handler or callback */
|
||||
SCP_E_ACCESS, /* Invalid access or permission denied */
|
||||
SCP_E_RANGE, /* Value out of range */
|
||||
SCP_E_TIMEOUT, /* Time out has ocurred */
|
||||
SCP_E_NOMEM, /* Invalid memory area or pointer */
|
||||
SCP_E_PWRSTATE, /* Invalid power state */
|
||||
SCP_E_SUPPORT, /* Feature not supported or disabled */
|
||||
SCPI_E_DEVICE, /* Device error */
|
||||
SCPI_E_BUSY, /* Device is busy */
|
||||
};
|
||||
|
||||
typedef uint32_t scpi_status_t;
|
||||
|
||||
typedef enum {
|
||||
SCPI_CMD_SCP_READY = 0x01,
|
||||
SCPI_CMD_SET_POWER_STATE = 0x03,
|
||||
SCPI_CMD_SYS_POWER_STATE = 0x05
|
||||
} scpi_command_t;
|
||||
|
||||
typedef enum {
|
||||
scpi_power_on = 0,
|
||||
scpi_power_retention = 1,
|
||||
scpi_power_off = 3,
|
||||
} scpi_power_state_t;
|
||||
|
||||
typedef enum {
|
||||
scpi_system_shutdown = 0,
|
||||
scpi_system_reboot = 1,
|
||||
scpi_system_reset = 2
|
||||
} scpi_system_state_t;
|
||||
|
||||
extern int scpi_wait_ready(void);
|
||||
extern void scpi_set_sq_power_state(unsigned int mpidr,
|
||||
scpi_power_state_t cpu_state,
|
||||
scpi_power_state_t cluster_state,
|
||||
scpi_power_state_t css_state);
|
||||
uint32_t scpi_sys_power_state(scpi_system_state_t system_state);
|
||||
uint32_t scpi_get_draminfo(struct draminfo *info);
|
||||
|
||||
#endif /* SQ_SCPI_H */
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SYNQUACER_PLAT_LD_S__
|
||||
#define SYNQUACER_PLAT_LD_S__
|
||||
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
|
||||
#define SPM_SHIM_EXCEPTIONS_VMA SP_DRAM
|
||||
|
||||
MEMORY {
|
||||
SP_DRAM (rw): ORIGIN = PLAT_SQ_SP_PRIV_BASE, LENGTH = PLAT_SQ_SP_PRIV_SIZE
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/*
|
||||
* Put the page tables in secure DRAM so that the PTW can make cacheable
|
||||
* accesses, as the core SPM code expects. (The SRAM on SynQuacer does
|
||||
* not support inner shareable WBWA mappings so it is mapped normal
|
||||
* non-cacheable)
|
||||
*/
|
||||
sp_xlat_table (NOLOAD) : ALIGN(PAGE_SIZE) {
|
||||
*(sp_xlat_table)
|
||||
} >SP_DRAM
|
||||
}
|
||||
|
||||
#endif /* SYNQUACER_PLAT_LD_S__ */
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
/*
|
||||
* Print CCN registers
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
.endm
|
||||
|
||||
#endif /* PLAT_MACROS_S */
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
/* CPU topology */
|
||||
#define PLAT_MAX_CORES_PER_CLUSTER U(2)
|
||||
#define PLAT_CLUSTER_COUNT U(12)
|
||||
#define PLATFORM_CORE_COUNT (PLAT_CLUSTER_COUNT * \
|
||||
PLAT_MAX_CORES_PER_CLUSTER)
|
||||
|
||||
/* Macros to read the SQ power domain state */
|
||||
#define SQ_PWR_LVL0 MPIDR_AFFLVL0
|
||||
#define SQ_PWR_LVL1 MPIDR_AFFLVL1
|
||||
#define SQ_PWR_LVL2 MPIDR_AFFLVL2
|
||||
|
||||
#define SQ_CORE_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL0]
|
||||
#define SQ_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL1]
|
||||
#define SQ_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\
|
||||
(state)->pwr_domain_state[SQ_PWR_LVL2] : 0)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL U(1)
|
||||
#define PLAT_MAX_RET_STATE U(1)
|
||||
#define PLAT_MAX_OFF_STATE U(2)
|
||||
|
||||
#define SQ_LOCAL_STATE_RUN 0
|
||||
#define SQ_LOCAL_STATE_RET 1
|
||||
#define SQ_LOCAL_STATE_OFF 2
|
||||
|
||||
#define CACHE_WRITEBACK_SHIFT 6
|
||||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define MAX_XLAT_TABLES 8
|
||||
#define MAX_MMAP_REGIONS 8
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
#define PLATFORM_STACK_SIZE 0x1000
|
||||
#else
|
||||
#define PLATFORM_STACK_SIZE 0x400
|
||||
#endif
|
||||
|
||||
#if !RESET_TO_BL31
|
||||
|
||||
/* A mailbox page will be mapped from BL2 and BL31 */
|
||||
#define BL2_MAILBOX_BASE 0x0403f000
|
||||
#define BL2_MAILBOX_SIZE 0x1000
|
||||
|
||||
#define PLAT_SQ_BOOTIDX_BASE 0x08510000
|
||||
#define PLAT_SQ_MAX_BOOT_INDEX 2
|
||||
|
||||
#define MAX_IO_HANDLES 2
|
||||
#define MAX_IO_DEVICES 2
|
||||
#define MAX_IO_BLOCK_DEVICES U(1)
|
||||
|
||||
#define BL2_BASE 0x04000000
|
||||
#define BL2_SIZE (256 * 1024)
|
||||
#define BL2_LIMIT (BL2_BASE + BL2_SIZE)
|
||||
|
||||
/* If BL2 is enabled, the BL31 is loaded on secure DRAM */
|
||||
#define BL31_BASE 0xfbe00000
|
||||
#define BL31_SIZE 0x00100000
|
||||
#else
|
||||
|
||||
#define BL31_BASE 0x04000000
|
||||
#define BL31_SIZE 0x00080000
|
||||
#endif
|
||||
|
||||
#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
|
||||
|
||||
#define BL32_BASE 0xfc000000
|
||||
#define BL32_SIZE 0x03c00000
|
||||
#define BL32_LIMIT (BL32_BASE + BL32_SIZE)
|
||||
|
||||
/* Alternative BL33 */
|
||||
#define PLAT_SQ_BL33_BASE 0xe0000000
|
||||
#define PLAT_SQ_BL33_SIZE 0x00200000
|
||||
|
||||
/* FWU FIP IO base */
|
||||
#define PLAT_SQ_FIP_IOBASE 0x08600000
|
||||
#define PLAT_SQ_FIP_MAXSIZE 0x00400000
|
||||
|
||||
#define PLAT_SQ_CCN_BASE 0x32000000
|
||||
#define PLAT_SQ_CLUSTER_TO_CCN_ID_MAP \
|
||||
0, /* Cluster 0 */ \
|
||||
18, /* Cluster 1 */ \
|
||||
11, /* Cluster 2 */ \
|
||||
29, /* Cluster 3 */ \
|
||||
35, /* Cluster 4 */ \
|
||||
17, /* Cluster 5 */ \
|
||||
12, /* Cluster 6 */ \
|
||||
30, /* Cluster 7 */ \
|
||||
14, /* Cluster 8 */ \
|
||||
32, /* Cluster 9 */ \
|
||||
15, /* Cluster 10 */ \
|
||||
33 /* Cluster 11 */
|
||||
|
||||
/* UART related constants */
|
||||
#define PLAT_SQ_BOOT_UART_BASE 0x2A400000
|
||||
#define PLAT_SQ_BOOT_UART_CLK_IN_HZ 62500000
|
||||
#define SQ_CONSOLE_BAUDRATE 115200
|
||||
|
||||
#define SQ_SYS_CNTCTL_BASE 0x2a430000
|
||||
|
||||
#define SQ_SYS_TIMCTL_BASE 0x2a810000
|
||||
#define PLAT_SQ_NSTIMER_FRAME_ID 0
|
||||
#define SQ_SYS_CNT_BASE_NS 0x2a830000
|
||||
|
||||
#define DRAMINFO_BASE 0x2E00FFC0
|
||||
|
||||
#define PLAT_SQ_MHU_BASE 0x45000000
|
||||
|
||||
#define PLAT_SQ_SCP_COM_SHARED_MEM_BASE 0x45400000
|
||||
#define SCPI_CMD_GET_DRAMINFO 0x1
|
||||
|
||||
#define SQ_BOOT_CFG_ADDR 0x45410000
|
||||
#define PLAT_SQ_PRIMARY_CPU_SHIFT 8
|
||||
#define PLAT_SQ_PRIMARY_CPU_BIT_WIDTH 6
|
||||
|
||||
#define PLAT_SQ_GICD_BASE 0x30000000
|
||||
#define PLAT_SQ_GICR_BASE 0x30400000
|
||||
|
||||
#define PLAT_SQ_GPIO_BASE 0x51000000
|
||||
|
||||
#define PLAT_SPM_BUF_BASE (BL32_LIMIT - 32 * PLAT_SPM_BUF_SIZE)
|
||||
#define PLAT_SPM_BUF_SIZE ULL(0x10000)
|
||||
#define PLAT_SPM_SPM_BUF_EL0_MMAP MAP_REGION2(PLAT_SPM_BUF_BASE, \
|
||||
PLAT_SPM_BUF_BASE, \
|
||||
PLAT_SPM_BUF_SIZE, \
|
||||
MT_RO_DATA | MT_SECURE | \
|
||||
MT_USER, PAGE_SIZE)
|
||||
|
||||
#define PLAT_SP_IMAGE_NS_BUF_BASE BL32_LIMIT
|
||||
#define PLAT_SP_IMAGE_NS_BUF_SIZE ULL(0x200000)
|
||||
#define PLAT_SP_IMAGE_NS_BUF_MMAP MAP_REGION2(PLAT_SP_IMAGE_NS_BUF_BASE, \
|
||||
PLAT_SP_IMAGE_NS_BUF_BASE, \
|
||||
PLAT_SP_IMAGE_NS_BUF_SIZE, \
|
||||
MT_RW_DATA | MT_NS | \
|
||||
MT_USER, PAGE_SIZE)
|
||||
|
||||
#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x10000)
|
||||
#define PLAT_SP_IMAGE_STACK_SIZE (32 * PLAT_SP_IMAGE_STACK_PCPU_SIZE)
|
||||
#define PLAT_SP_IMAGE_STACK_BASE (PLAT_SQ_SP_HEAP_BASE + PLAT_SQ_SP_HEAP_SIZE)
|
||||
|
||||
#define PLAT_SQ_SP_IMAGE_SIZE ULL(0x200000)
|
||||
#define PLAT_SQ_SP_IMAGE_MMAP MAP_REGION2(BL32_BASE, BL32_BASE, \
|
||||
PLAT_SQ_SP_IMAGE_SIZE, \
|
||||
MT_CODE | MT_SECURE | \
|
||||
MT_USER, PAGE_SIZE)
|
||||
|
||||
#define PLAT_SQ_SP_HEAP_BASE (BL32_BASE + PLAT_SQ_SP_IMAGE_SIZE)
|
||||
#define PLAT_SQ_SP_HEAP_SIZE ULL(0x800000)
|
||||
|
||||
#define PLAT_SQ_SP_IMAGE_RW_MMAP MAP_REGION2(PLAT_SQ_SP_HEAP_BASE, \
|
||||
PLAT_SQ_SP_HEAP_BASE, \
|
||||
(PLAT_SQ_SP_HEAP_SIZE + \
|
||||
PLAT_SP_IMAGE_STACK_SIZE), \
|
||||
MT_RW_DATA | MT_SECURE | \
|
||||
MT_USER, PAGE_SIZE)
|
||||
|
||||
#define PLAT_SQ_SP_PRIV_BASE (PLAT_SP_IMAGE_STACK_BASE + \
|
||||
PLAT_SP_IMAGE_STACK_SIZE)
|
||||
#define PLAT_SQ_SP_PRIV_SIZE ULL(0x40000)
|
||||
|
||||
#define PLAT_SP_PRI 0x20
|
||||
#define PLAT_PRI_BITS 2
|
||||
#define PLAT_SPM_COOKIE_0 ULL(0)
|
||||
#define PLAT_SPM_COOKIE_1 ULL(0)
|
||||
|
||||
/* Total number of memory regions with distinct properties */
|
||||
#define PLAT_SP_IMAGE_NUM_MEM_REGIONS 6
|
||||
|
||||
#define PLAT_SP_IMAGE_MMAP_REGIONS 30
|
||||
#define PLAT_SP_IMAGE_MAX_XLAT_TABLES 20
|
||||
#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "sp_xlat_table"
|
||||
#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME "sp_xlat_table"
|
||||
|
||||
#define PLAT_SQ_UART1_BASE PLAT_SQ_BOOT_UART_BASE
|
||||
#define PLAT_SQ_UART1_SIZE ULL(0x1000)
|
||||
#define PLAT_SQ_UART1_MMAP MAP_REGION_FLAT(PLAT_SQ_UART1_BASE, \
|
||||
PLAT_SQ_UART1_SIZE, \
|
||||
MT_DEVICE | MT_RW | \
|
||||
MT_NS | MT_PRIVILEGED)
|
||||
|
||||
#define PLAT_SQ_PERIPH_BASE 0x50000000
|
||||
#define PLAT_SQ_PERIPH_SIZE ULL(0x8000000)
|
||||
#define PLAT_SQ_PERIPH_MMAP MAP_REGION_FLAT(PLAT_SQ_PERIPH_BASE, \
|
||||
PLAT_SQ_PERIPH_SIZE, \
|
||||
MT_DEVICE | MT_RW | \
|
||||
MT_NS | MT_USER)
|
||||
|
||||
#define PLAT_SQ_FLASH_BASE 0x08000000
|
||||
#define PLAT_SQ_FLASH_SIZE ULL(0x8000000)
|
||||
#define PLAT_SQ_FLASH_MMAP MAP_REGION_FLAT(PLAT_SQ_FLASH_BASE, \
|
||||
PLAT_SQ_FLASH_SIZE, \
|
||||
MT_DEVICE | MT_RW | \
|
||||
MT_NS | MT_USER)
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SQ_COMMON_H
|
||||
#define SQ_COMMON_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <lib/psci/psci.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
|
||||
struct draminfo {
|
||||
uint32_t num_regions;
|
||||
uint32_t reserved;
|
||||
uint64_t base1;
|
||||
uint64_t size1;
|
||||
uint64_t base2;
|
||||
uint64_t size2;
|
||||
uint64_t base3;
|
||||
uint64_t size3;
|
||||
};
|
||||
|
||||
uint32_t sq_scp_get_draminfo(struct draminfo *info);
|
||||
|
||||
void plat_sq_pwrc_setup(void);
|
||||
|
||||
void plat_sq_interconnect_init(void);
|
||||
void plat_sq_interconnect_enter_coherency(void);
|
||||
void plat_sq_interconnect_exit_coherency(void);
|
||||
|
||||
unsigned int sq_calc_core_pos(u_register_t mpidr);
|
||||
|
||||
void sq_gic_driver_init(void);
|
||||
void sq_gic_init(void);
|
||||
void sq_gic_cpuif_enable(void);
|
||||
void sq_gic_cpuif_disable(void);
|
||||
void sq_gic_pcpu_init(void);
|
||||
|
||||
int sq_io_setup(void);
|
||||
struct image_info *sq_get_image_info(unsigned int image_id);
|
||||
void sq_mmap_setup(uintptr_t total_base, size_t total_size,
|
||||
const struct mmap_region *mmap);
|
||||
|
||||
/* SCMI API for power management by SCP */
|
||||
void sq_scmi_off(const struct psci_power_state *target_state);
|
||||
void sq_scmi_on(u_register_t mpidr);
|
||||
void __dead2 sq_scmi_sys_shutdown(void);
|
||||
void __dead2 sq_scmi_sys_reboot(void);
|
||||
void __dead2 sq_scmi_system_off(int state);
|
||||
/* SCMI API for vendor specific protocol */
|
||||
uint32_t sq_scmi_get_draminfo(struct draminfo *info);
|
||||
|
||||
#endif /* SQ_COMMON_H */
|
||||
@@ -0,0 +1,117 @@
|
||||
#
|
||||
# Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
override PROGRAMMABLE_RESET_ADDRESS := 1
|
||||
override USE_COHERENT_MEM := 1
|
||||
override SEPARATE_CODE_AND_RODATA := 1
|
||||
override ENABLE_SVE_FOR_NS := 0
|
||||
# Enable workarounds for selected Cortex-A53 erratas.
|
||||
ERRATA_A53_855873 := 1
|
||||
|
||||
ifeq (${RESET_TO_BL31}, 1)
|
||||
override RESET_TO_BL31 := 1
|
||||
override TRUSTED_BOARD_BOOT := 0
|
||||
SQ_USE_SCMI_DRIVER ?= 0
|
||||
else
|
||||
override RESET_TO_BL31 := 0
|
||||
override BL2_AT_EL3 := 1
|
||||
SQ_USE_SCMI_DRIVER := 1
|
||||
BL2_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
|
||||
endif
|
||||
|
||||
# Libraries
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
PLAT_PATH := plat/socionext/synquacer
|
||||
PLAT_INCLUDES := -I$(PLAT_PATH)/include \
|
||||
-I$(PLAT_PATH)/drivers/scpi \
|
||||
-I$(PLAT_PATH)/drivers/mhu \
|
||||
-Idrivers/arm/css/scmi \
|
||||
-Idrivers/arm/css/scmi/vendor
|
||||
|
||||
PLAT_BL_COMMON_SOURCES += $(PLAT_PATH)/sq_helpers.S \
|
||||
drivers/arm/pl011/aarch64/pl011_console.S \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/delay_timer/generic_delay_timer.c \
|
||||
lib/cpus/aarch64/cortex_a53.S \
|
||||
$(PLAT_PATH)/sq_xlat_setup.c \
|
||||
${XLAT_TABLES_LIB_SRCS}
|
||||
|
||||
# Include GICv3 driver files
|
||||
include drivers/arm/gic/v3/gicv3.mk
|
||||
|
||||
ifneq (${RESET_TO_BL31}, 1)
|
||||
BL2_SOURCES += common/desc_image_load.c \
|
||||
drivers/io/io_fip.c \
|
||||
drivers/io/io_memmap.c \
|
||||
drivers/io/io_storage.c \
|
||||
$(PLAT_PATH)/sq_bl2_setup.c \
|
||||
$(PLAT_PATH)/sq_image_desc.c \
|
||||
$(PLAT_PATH)/sq_io_storage.c
|
||||
|
||||
ifeq (${TRUSTED_BOARD_BOOT},1)
|
||||
include drivers/auth/mbedtls/mbedtls_crypto.mk
|
||||
include drivers/auth/mbedtls/mbedtls_x509.mk
|
||||
BL2_SOURCES += drivers/auth/auth_mod.c \
|
||||
drivers/auth/crypto_mod.c \
|
||||
drivers/auth/img_parser_mod.c \
|
||||
drivers/auth/tbbr/tbbr_cot_common.c \
|
||||
drivers/auth/tbbr/tbbr_cot_bl2.c \
|
||||
plat/common/tbbr/plat_tbbr.c \
|
||||
$(PLAT_PATH)/sq_rotpk.S \
|
||||
$(PLAT_PATH)/sq_tbbr.c
|
||||
|
||||
ROT_KEY = $(BUILD_PLAT)/rot_key.pem
|
||||
ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
|
||||
|
||||
$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
|
||||
$(BUILD_PLAT)/bl2/sq_rotpk.o: $(ROTPK_HASH)
|
||||
|
||||
certificates: $(ROT_KEY)
|
||||
$(ROT_KEY): | $(BUILD_PLAT)
|
||||
@echo " OPENSSL $@"
|
||||
$(Q)${OPENSSL_BIN_PATH}/openssl genrsa 2048 > $@ 2>/dev/null
|
||||
|
||||
$(ROTPK_HASH): $(ROT_KEY)
|
||||
@echo " OPENSSL $@"
|
||||
$(Q)${OPENSSL_BIN_PATH}/openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
|
||||
${OPENSSL_BIN_PATH}/openssl dgst -sha256 -binary > $@ 2>/dev/null
|
||||
|
||||
endif # TRUSTED_BOARD_BOOT
|
||||
endif
|
||||
|
||||
BL31_SOURCES += drivers/arm/ccn/ccn.c \
|
||||
${GICV3_SOURCES} \
|
||||
plat/common/plat_gicv3.c \
|
||||
plat/common/plat_psci_common.c \
|
||||
$(PLAT_PATH)/sq_bl31_setup.c \
|
||||
$(PLAT_PATH)/sq_ccn.c \
|
||||
$(PLAT_PATH)/sq_topology.c \
|
||||
$(PLAT_PATH)/sq_psci.c \
|
||||
$(PLAT_PATH)/sq_gicv3.c \
|
||||
$(PLAT_PATH)/drivers/scp/sq_scp.c
|
||||
|
||||
ifeq (${SQ_USE_SCMI_DRIVER},0)
|
||||
BL31_SOURCES += $(PLAT_PATH)/drivers/scpi/sq_scpi.c \
|
||||
$(PLAT_PATH)/drivers/mhu/sq_mhu.c
|
||||
else
|
||||
BL31_SOURCES += $(PLAT_PATH)/drivers/scp/sq_scmi.c \
|
||||
drivers/arm/css/scmi/scmi_common.c \
|
||||
drivers/arm/css/scmi/scmi_pwr_dmn_proto.c \
|
||||
drivers/arm/css/scmi/scmi_sys_pwr_proto.c \
|
||||
drivers/arm/css/scmi/vendor/scmi_sq.c \
|
||||
drivers/arm/css/mhu/css_mhu_doorbell.c
|
||||
endif
|
||||
|
||||
ifeq (${SPM_MM},1)
|
||||
$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
|
||||
|
||||
BL31_SOURCES += $(PLAT_PATH)/sq_spm.c
|
||||
endif
|
||||
|
||||
ifeq (${SQ_USE_SCMI_DRIVER},1)
|
||||
$(eval $(call add_define,SQ_USE_SCMI_DRIVER))
|
||||
endif
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Socionext Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/desc_image_load.h>
|
||||
#include <common/image_decompress.h>
|
||||
#include <drivers/arm/pl011.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <sq_common.h>
|
||||
|
||||
static console_t console;
|
||||
|
||||
void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
|
||||
u_register_t x2, u_register_t x3)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
(void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
|
||||
PLAT_SQ_BOOT_UART_CLK_IN_HZ,
|
||||
SQ_CONSOLE_BAUDRATE, &console);
|
||||
console_set_scope(&console, CONSOLE_FLAG_BOOT);
|
||||
}
|
||||
|
||||
void bl2_el3_plat_arch_setup(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
sq_mmap_setup(BL2_BASE, BL2_SIZE, NULL);
|
||||
|
||||
ret = sq_io_setup();
|
||||
if (ret) {
|
||||
ERROR("failed to setup io devices\n");
|
||||
plat_error_handler(ret);
|
||||
}
|
||||
}
|
||||
|
||||
void bl2_platform_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void plat_flush_next_bl_params(void)
|
||||
{
|
||||
flush_bl_params_desc();
|
||||
}
|
||||
|
||||
bl_load_info_t *plat_get_bl_image_load_info(void)
|
||||
{
|
||||
return get_bl_load_info_from_mem_params_desc();
|
||||
}
|
||||
|
||||
bl_params_t *plat_get_next_bl_params(void)
|
||||
{
|
||||
return get_next_bl_params_from_mem_params_desc();
|
||||
}
|
||||
|
||||
void bl2_plat_preload_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
int bl2_plat_handle_pre_image_load(unsigned int image_id)
|
||||
{
|
||||
struct image_info *image_info;
|
||||
|
||||
image_info = sq_get_image_info(image_id);
|
||||
|
||||
return mmap_add_dynamic_region(image_info->image_base,
|
||||
image_info->image_base,
|
||||
image_info->image_max_size,
|
||||
MT_MEMORY | MT_RW | MT_NS);
|
||||
}
|
||||
|
||||
int bl2_plat_handle_post_image_load(unsigned int image_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+247
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/pl011.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <sq_common.h>
|
||||
|
||||
static console_t console;
|
||||
static entry_point_info_t bl32_image_ep_info;
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
|
||||
IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_START__, SPM_SHIM_EXCEPTIONS_START);
|
||||
IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_END__, SPM_SHIM_EXCEPTIONS_END);
|
||||
IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_LMA__, SPM_SHIM_EXCEPTIONS_LMA);
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
unsigned int counter_base_frequency;
|
||||
|
||||
/* Read the frequency from Frequency modes table */
|
||||
counter_base_frequency = mmio_read_32(SQ_SYS_CNTCTL_BASE + CNTFID_OFF);
|
||||
|
||||
/* The first entry of the frequency modes table must not be 0 */
|
||||
if (counter_base_frequency == 0)
|
||||
panic();
|
||||
|
||||
return counter_base_frequency;
|
||||
}
|
||||
|
||||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
assert(sec_state_is_valid(type));
|
||||
return type == NON_SECURE ? &bl33_image_ep_info : &bl32_image_ep_info;
|
||||
}
|
||||
|
||||
#if !RESET_TO_BL31
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
void *from_bl2 = (void *) arg0;
|
||||
bl_params_node_t *bl_params = ((bl_params_t *) from_bl2)->head;
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
(void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
|
||||
PLAT_SQ_BOOT_UART_CLK_IN_HZ,
|
||||
SQ_CONSOLE_BAUDRATE, &console);
|
||||
|
||||
console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
|
||||
|
||||
/* Initialize power controller before setting up topology */
|
||||
plat_sq_pwrc_setup();
|
||||
|
||||
while (bl_params) {
|
||||
if (bl_params->image_id == BL32_IMAGE_ID)
|
||||
bl32_image_ep_info = *bl_params->ep_info;
|
||||
|
||||
if (bl_params->image_id == BL33_IMAGE_ID)
|
||||
bl33_image_ep_info = *bl_params->ep_info;
|
||||
|
||||
bl_params = bl_params->next_params_info;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/*******************************************************************************
|
||||
* Gets SPSR for BL32 entry
|
||||
******************************************************************************/
|
||||
uint32_t sq_get_spsr_for_bl32_entry(void)
|
||||
{
|
||||
/*
|
||||
* The Secure Payload Dispatcher service is responsible for
|
||||
* setting the SPSR prior to entry into the BL32 image.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Gets SPSR for BL33 entry
|
||||
******************************************************************************/
|
||||
uint32_t sq_get_spsr_for_bl33_entry(void)
|
||||
{
|
||||
unsigned long el_status;
|
||||
unsigned int mode;
|
||||
uint32_t spsr;
|
||||
|
||||
/* Figure out what mode we enter the non-secure world in */
|
||||
el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
|
||||
el_status &= ID_AA64PFR0_ELX_MASK;
|
||||
|
||||
mode = (el_status) ? MODE_EL2 : MODE_EL1;
|
||||
|
||||
spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||
return spsr;
|
||||
}
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
(void)console_pl011_register(PLAT_SQ_BOOT_UART_BASE,
|
||||
PLAT_SQ_BOOT_UART_CLK_IN_HZ,
|
||||
SQ_CONSOLE_BAUDRATE, &console);
|
||||
|
||||
console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
|
||||
|
||||
/* There are no parameters from BL2 if BL31 is a reset vector */
|
||||
assert(arg0 == 0U);
|
||||
assert(arg1 == 0U);
|
||||
|
||||
/* Initialize power controller before setting up topology */
|
||||
plat_sq_pwrc_setup();
|
||||
|
||||
#ifdef SPD_opteed
|
||||
struct draminfo di = {0};
|
||||
|
||||
sq_scp_get_draminfo(&di);
|
||||
|
||||
/*
|
||||
* Check if OP-TEE has been loaded in Secure RAM allocated
|
||||
* from DRAM1 region
|
||||
*/
|
||||
if ((di.base1 + di.size1) <= BL32_BASE) {
|
||||
NOTICE("OP-TEE has been loaded by SCP firmware\n");
|
||||
/* Populate entry point information for BL32 */
|
||||
SET_PARAM_HEAD(&bl32_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
|
||||
bl32_image_ep_info.pc = BL32_BASE;
|
||||
bl32_image_ep_info.spsr = sq_get_spsr_for_bl32_entry();
|
||||
} else {
|
||||
NOTICE("OP-TEE has not been loaded by SCP firmware\n");
|
||||
}
|
||||
#endif /* SPD_opteed */
|
||||
|
||||
/* Populate entry point information for BL33 */
|
||||
SET_PARAM_HEAD(&bl33_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
/*
|
||||
* Tell BL31 where the non-trusted software image
|
||||
* is located and the entry state information
|
||||
*/
|
||||
bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
|
||||
bl33_image_ep_info.spsr = sq_get_spsr_for_bl33_entry();
|
||||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void sq_configure_sys_timer(void)
|
||||
{
|
||||
unsigned int reg_val;
|
||||
unsigned int freq_val = plat_get_syscnt_freq2();
|
||||
|
||||
reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT);
|
||||
reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT);
|
||||
reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT);
|
||||
mmio_write_32(SQ_SYS_TIMCTL_BASE +
|
||||
CNTACR_BASE(PLAT_SQ_NSTIMER_FRAME_ID), reg_val);
|
||||
|
||||
reg_val = (1 << CNTNSAR_NS_SHIFT(PLAT_SQ_NSTIMER_FRAME_ID));
|
||||
mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTNSAR, reg_val);
|
||||
|
||||
/* Initialize CNTFRQ register in CNTCTLBase frame */
|
||||
mmio_write_32(SQ_SYS_TIMCTL_BASE + CNTCTLBASE_CNTFRQ, freq_val);
|
||||
|
||||
/*
|
||||
* Initialize CNTFRQ register in Non-secure CNTBase frame.
|
||||
* This is required for SynQuacer, because it does not
|
||||
* follow ARM ARM in that the value updated in CNTFRQ is not
|
||||
* reflected in CNTBASEN_CNTFRQ. Hence update the value manually.
|
||||
*/
|
||||
mmio_write_32(SQ_SYS_CNT_BASE_NS + CNTBASEN_CNTFRQ, freq_val);
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
/* Initialize the CCN interconnect */
|
||||
plat_sq_interconnect_init();
|
||||
plat_sq_interconnect_enter_coherency();
|
||||
|
||||
/* Initialize the GIC driver, cpu and distributor interfaces */
|
||||
sq_gic_driver_init();
|
||||
sq_gic_init();
|
||||
|
||||
/* Enable and initialize the System level generic timer */
|
||||
mmio_write_32(SQ_SYS_CNTCTL_BASE + CNTCR_OFF,
|
||||
CNTCR_FCREQ(0U) | CNTCR_EN);
|
||||
|
||||
/* Allow access to the System counter timer module */
|
||||
sq_configure_sys_timer();
|
||||
}
|
||||
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
struct draminfo *di = (struct draminfo *)(unsigned long)DRAMINFO_BASE;
|
||||
|
||||
sq_scp_get_draminfo(di);
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
static const mmap_region_t secure_partition_mmap[] = {
|
||||
#if SPM_MM
|
||||
MAP_REGION_FLAT(PLAT_SPM_BUF_BASE,
|
||||
PLAT_SPM_BUF_SIZE,
|
||||
MT_RW_DATA | MT_SECURE),
|
||||
MAP_REGION_FLAT(PLAT_SQ_SP_PRIV_BASE,
|
||||
PLAT_SQ_SP_PRIV_SIZE,
|
||||
MT_RW_DATA | MT_SECURE),
|
||||
#endif
|
||||
#if !RESET_TO_BL31
|
||||
MAP_REGION_FLAT(BL2_MAILBOX_BASE,
|
||||
BL2_MAILBOX_SIZE,
|
||||
MT_RW | MT_SECURE),
|
||||
#endif
|
||||
{0},
|
||||
};
|
||||
|
||||
sq_mmap_setup(BL31_BASE, BL31_SIZE, secure_partition_mmap);
|
||||
enable_mmu_el3(XLAT_TABLE_NC);
|
||||
|
||||
#if SPM_MM
|
||||
memcpy((void *)SPM_SHIM_EXCEPTIONS_START,
|
||||
(void *)SPM_SHIM_EXCEPTIONS_LMA,
|
||||
(uintptr_t)SPM_SHIM_EXCEPTIONS_END -
|
||||
(uintptr_t)SPM_SHIM_EXCEPTIONS_START);
|
||||
#endif
|
||||
}
|
||||
|
||||
void bl31_plat_enable_mmu(uint32_t flags)
|
||||
{
|
||||
enable_mmu_el3(flags | XLAT_TABLE_NC);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <drivers/arm/ccn.h>
|
||||
|
||||
static const unsigned char master_to_rn_id_map[] = {
|
||||
PLAT_SQ_CLUSTER_TO_CCN_ID_MAP
|
||||
};
|
||||
|
||||
static const ccn_desc_t sq_ccn_desc = {
|
||||
.periphbase = PLAT_SQ_CCN_BASE,
|
||||
.num_masters = ARRAY_SIZE(master_to_rn_id_map),
|
||||
.master_to_rn_id_map = master_to_rn_id_map
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Helper function to initialize SQ CCN driver.
|
||||
*****************************************************************************/
|
||||
void plat_sq_interconnect_init(void)
|
||||
{
|
||||
ccn_init(&sq_ccn_desc);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Helper function to place current master into coherency
|
||||
*****************************************************************************/
|
||||
void plat_sq_interconnect_enter_coherency(void)
|
||||
{
|
||||
ccn_enter_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Helper function to remove current master from coherency
|
||||
*****************************************************************************/
|
||||
void plat_sq_interconnect_exit_coherency(void)
|
||||
{
|
||||
ccn_exit_snoop_dvm_domain(1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/interrupt_props.h>
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include "sq_common.h"
|
||||
|
||||
static uintptr_t sq_rdistif_base_addrs[PLATFORM_CORE_COUNT];
|
||||
|
||||
static const interrupt_prop_t sq_interrupt_props[] = {
|
||||
/* G0 interrupts */
|
||||
|
||||
/* SGI0 */
|
||||
INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
|
||||
GIC_INTR_CFG_EDGE),
|
||||
/* SGI6 */
|
||||
INTR_PROP_DESC(14, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
|
||||
GIC_INTR_CFG_EDGE),
|
||||
|
||||
/* G1S interrupts */
|
||||
|
||||
/* Timer */
|
||||
INTR_PROP_DESC(29, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
|
||||
GIC_INTR_CFG_LEVEL),
|
||||
/* SGI1 */
|
||||
INTR_PROP_DESC(9, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
|
||||
GIC_INTR_CFG_EDGE),
|
||||
/* SGI2 */
|
||||
INTR_PROP_DESC(10, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
|
||||
GIC_INTR_CFG_EDGE),
|
||||
/* SGI3 */
|
||||
INTR_PROP_DESC(11, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
|
||||
GIC_INTR_CFG_EDGE),
|
||||
/* SGI4 */
|
||||
INTR_PROP_DESC(12, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
|
||||
GIC_INTR_CFG_EDGE),
|
||||
/* SGI5 */
|
||||
INTR_PROP_DESC(13, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
|
||||
GIC_INTR_CFG_EDGE),
|
||||
/* SGI7 */
|
||||
INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP1S,
|
||||
GIC_INTR_CFG_EDGE)
|
||||
};
|
||||
|
||||
static unsigned int sq_mpidr_to_core_pos(u_register_t mpidr)
|
||||
{
|
||||
return plat_core_pos_by_mpidr(mpidr);
|
||||
}
|
||||
|
||||
static const struct gicv3_driver_data sq_gic_driver_data = {
|
||||
.gicd_base = PLAT_SQ_GICD_BASE,
|
||||
.gicr_base = PLAT_SQ_GICR_BASE,
|
||||
.interrupt_props = sq_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(sq_interrupt_props),
|
||||
.rdistif_num = PLATFORM_CORE_COUNT,
|
||||
.rdistif_base_addrs = sq_rdistif_base_addrs,
|
||||
.mpidr_to_core_pos = sq_mpidr_to_core_pos,
|
||||
};
|
||||
|
||||
void sq_gic_driver_init(void)
|
||||
{
|
||||
gicv3_driver_init(&sq_gic_driver_data);
|
||||
}
|
||||
|
||||
void sq_gic_init(void)
|
||||
{
|
||||
gicv3_distif_init();
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void sq_gic_cpuif_enable(void)
|
||||
{
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void sq_gic_cpuif_disable(void)
|
||||
{
|
||||
gicv3_cpuif_disable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void sq_gic_pcpu_init(void)
|
||||
{
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.global sq_calc_core_pos
|
||||
.global plat_my_core_pos
|
||||
.global platform_mem_init
|
||||
.global plat_is_my_cpu_primary
|
||||
.global plat_secondary_cold_boot_setup
|
||||
.global plat_crash_console_init
|
||||
.global plat_crash_console_putc
|
||||
.global plat_crash_console_flush
|
||||
|
||||
/*
|
||||
* unsigned int sq_calc_core_pos(u_register_t mpidr)
|
||||
* core_pos = (cluster_id * max_cpus_per_cluster) + core_id
|
||||
*/
|
||||
func sq_calc_core_pos
|
||||
and x1, x0, #MPIDR_CPU_MASK
|
||||
and x0, x0, #MPIDR_CLUSTER_MASK
|
||||
add x0, x1, x0, lsr #7
|
||||
ret
|
||||
endfunc sq_calc_core_pos
|
||||
|
||||
func plat_my_core_pos
|
||||
mrs x0, mpidr_el1
|
||||
b sq_calc_core_pos
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
func platform_mem_init
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
/*
|
||||
* Secondary CPUs are placed in a holding pen, waiting for their mailbox
|
||||
* to be populated. Note that all CPUs share the same mailbox ; therefore,
|
||||
* populating it will release all CPUs from their holding pen. If
|
||||
* finer-grained control is needed then this should be handled in the
|
||||
* code that secondary CPUs jump to.
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
#if !RESET_TO_BL31
|
||||
mov_imm x0, BL2_MAILBOX_BASE
|
||||
ldr x0, [x0]
|
||||
#else
|
||||
ldr x0, sq_sec_entrypoint
|
||||
#endif
|
||||
|
||||
/* Wait until the mailbox gets populated */
|
||||
poll_mailbox:
|
||||
cbz x0, 1f
|
||||
br x0
|
||||
1:
|
||||
wfe
|
||||
b poll_mailbox
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu (applicable only after a cold boot)
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mov x9, x30
|
||||
bl plat_my_core_pos
|
||||
ldr x1, =SQ_BOOT_CFG_ADDR
|
||||
ldr x1, [x1]
|
||||
ubfx x1, x1, #PLAT_SQ_PRIMARY_CPU_SHIFT, \
|
||||
#PLAT_SQ_PRIMARY_CPU_BIT_WIDTH
|
||||
cmp x0, x1
|
||||
cset w0, eq
|
||||
ret x9
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/*
|
||||
* int plat_crash_console_init(void)
|
||||
* Function to initialize the crash console
|
||||
* without a C Runtime to print crash report.
|
||||
* Clobber list : x0, x1, x2
|
||||
*/
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, PLAT_SQ_BOOT_UART_BASE
|
||||
mov_imm x1, PLAT_SQ_BOOT_UART_CLK_IN_HZ
|
||||
mov_imm x2, SQ_CONSOLE_BAUDRATE
|
||||
b console_pl011_core_init
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
/*
|
||||
* int plat_crash_console_putc(int c)
|
||||
* Function to print a character on the crash
|
||||
* console without a C Runtime.
|
||||
* Clobber list : x1, x2
|
||||
*/
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, PLAT_SQ_BOOT_UART_BASE
|
||||
b console_pl011_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
/*
|
||||
* void plat_crash_console_flush(int c)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* Out : void.
|
||||
* Clobber list : x0, x1
|
||||
*/
|
||||
func plat_crash_console_flush
|
||||
mov_imm x0, PLAT_SQ_BOOT_UART_BASE
|
||||
b console_pl011_core_flush
|
||||
endfunc plat_crash_console_flush
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Socionext Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <common/desc_image_load.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
static struct bl_mem_params_node sq_image_descs[] = {
|
||||
{
|
||||
.image_id = BL31_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = BL31_BASE,
|
||||
.image_info.image_max_size = BL31_SIZE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
SECURE | EXECUTABLE | EP_FIRST_EXE),
|
||||
.ep_info.pc = BL31_BASE,
|
||||
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS),
|
||||
|
||||
.next_handoff_image_id = BL32_IMAGE_ID,
|
||||
},
|
||||
{
|
||||
.image_id = BL32_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = BL32_BASE,
|
||||
.image_info.image_max_size = BL32_SIZE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
SECURE | EXECUTABLE),
|
||||
.ep_info.pc = BL32_BASE,
|
||||
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS),
|
||||
|
||||
.next_handoff_image_id = BL33_IMAGE_ID,
|
||||
},
|
||||
{
|
||||
.image_id = BL33_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = PLAT_SQ_BL33_BASE,
|
||||
.image_info.image_max_size = PLAT_SQ_BL33_SIZE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
NON_SECURE | EXECUTABLE),
|
||||
.ep_info.pc = PLAT_SQ_BL33_BASE,
|
||||
.ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS),
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
};
|
||||
REGISTER_BL_IMAGE_DESCS(sq_image_descs)
|
||||
|
||||
struct image_info *sq_get_image_info(unsigned int image_id)
|
||||
{
|
||||
struct bl_mem_params_node *desc;
|
||||
|
||||
desc = get_bl_mem_params_node(image_id);
|
||||
assert(desc);
|
||||
return &desc->image_info;
|
||||
}
|
||||
+246
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Socionext Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <drivers/io/io_block.h>
|
||||
#include <drivers/io/io_driver.h>
|
||||
#include <drivers/io/io_fip.h>
|
||||
#include <drivers/io/io_memmap.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <tools_share/firmware_image_package.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <sq_common.h>
|
||||
|
||||
static const io_dev_connector_t *sq_fip_dev_con;
|
||||
static uintptr_t sq_fip_dev_handle;
|
||||
|
||||
static const io_dev_connector_t *sq_backend_dev_con;
|
||||
static uintptr_t sq_backend_dev_handle;
|
||||
|
||||
static io_block_spec_t sq_fip_spec = {
|
||||
.offset = PLAT_SQ_FIP_IOBASE, /* FIP Image is at 5MB offset on memory-mapped NOR flash */
|
||||
.length = PLAT_SQ_FIP_MAXSIZE, /* Expected maximum FIP image size */
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_bl2_spec = {
|
||||
.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_bl31_spec = {
|
||||
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_bl32_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_bl33_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
|
||||
};
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
static const io_uuid_spec_t sq_tb_fw_cert_spec = {
|
||||
.uuid = UUID_TRUSTED_BOOT_FW_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_trusted_key_cert_spec = {
|
||||
.uuid = UUID_TRUSTED_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_soc_fw_key_cert_spec = {
|
||||
.uuid = UUID_SOC_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_tos_fw_key_cert_spec = {
|
||||
.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_nt_fw_key_cert_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_soc_fw_cert_spec = {
|
||||
.uuid = UUID_SOC_FW_CONTENT_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_tos_fw_cert_spec = {
|
||||
.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t sq_nt_fw_cert_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
|
||||
};
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
struct sq_io_policy {
|
||||
uintptr_t *dev_handle;
|
||||
uintptr_t image_spec;
|
||||
uintptr_t init_params;
|
||||
};
|
||||
|
||||
static const struct sq_io_policy sq_io_policies[] = {
|
||||
[FIP_IMAGE_ID] = {
|
||||
.dev_handle = &sq_backend_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_fip_spec,
|
||||
},
|
||||
[BL2_IMAGE_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_bl2_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[BL31_IMAGE_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_bl31_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[BL32_IMAGE_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_bl32_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[BL33_IMAGE_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_bl33_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
[TRUSTED_BOOT_FW_CERT_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_tb_fw_cert_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[TRUSTED_KEY_CERT_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_trusted_key_cert_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[SOC_FW_KEY_CERT_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_soc_fw_key_cert_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[TRUSTED_OS_FW_KEY_CERT_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_tos_fw_key_cert_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[NON_TRUSTED_FW_KEY_CERT_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_nt_fw_key_cert_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[SOC_FW_CONTENT_CERT_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_soc_fw_cert_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_tos_fw_cert_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
|
||||
.dev_handle = &sq_fip_dev_handle,
|
||||
.image_spec = (uintptr_t)&sq_nt_fw_cert_spec,
|
||||
.init_params = FIP_IMAGE_ID,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static int sq_update_fip_spec(void)
|
||||
{
|
||||
uint32_t boot_index;
|
||||
int ret;
|
||||
|
||||
ret = mmap_add_dynamic_region(PLAT_SQ_BOOTIDX_BASE, PLAT_SQ_BOOTIDX_BASE,
|
||||
PAGE_SIZE, MT_RO_DATA | MT_SECURE);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
boot_index = mmio_read_32(PLAT_SQ_BOOTIDX_BASE);
|
||||
if (boot_index < PLAT_SQ_MAX_BOOT_INDEX) {
|
||||
sq_fip_spec.offset += PLAT_SQ_FIP_MAXSIZE * boot_index;
|
||||
INFO("FWU Enabled: boot_index %d\n", boot_index);
|
||||
} else {
|
||||
WARN("FWU Disabled: wrong boot_index value. Fallback to index 0.\n");
|
||||
}
|
||||
|
||||
mmap_remove_dynamic_region(PLAT_SQ_BOOTIDX_BASE, PAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sq_io_memmap_setup(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sq_update_fip_spec();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mmap_add_dynamic_region(sq_fip_spec.offset, sq_fip_spec.offset,
|
||||
sq_fip_spec.length, MT_RO_DATA | MT_SECURE);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = register_io_dev_memmap(&sq_backend_dev_con);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return io_dev_open(sq_backend_dev_con, 0, &sq_backend_dev_handle);
|
||||
}
|
||||
|
||||
static int sq_io_fip_setup(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_io_dev_fip(&sq_fip_dev_con);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return io_dev_open(sq_fip_dev_con, 0, &sq_fip_dev_handle);
|
||||
}
|
||||
|
||||
int sq_io_setup(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sq_io_memmap_setup();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sq_io_fip_setup();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
|
||||
uintptr_t *image_spec)
|
||||
{
|
||||
uintptr_t init_params;
|
||||
|
||||
assert(image_id < ARRAY_SIZE(sq_io_policies));
|
||||
|
||||
*dev_handle = *sq_io_policies[image_id].dev_handle;
|
||||
*image_spec = sq_io_policies[image_id].image_spec;
|
||||
init_params = sq_io_policies[image_id].init_params;
|
||||
|
||||
return io_dev_init(*dev_handle, init_params);
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#include <lib/cassert.h>
|
||||
#include <lib/psci/psci.h>
|
||||
|
||||
#include <sq_common.h>
|
||||
#include "sq_scpi.h"
|
||||
|
||||
uintptr_t sq_sec_entrypoint;
|
||||
|
||||
int sq_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
#if SQ_USE_SCMI_DRIVER
|
||||
sq_scmi_on(mpidr);
|
||||
#else
|
||||
/*
|
||||
* SCP takes care of powering up parent power domains so we
|
||||
* only need to care about level 0
|
||||
*/
|
||||
scpi_set_sq_power_state(mpidr, scpi_power_on, scpi_power_on,
|
||||
scpi_power_on);
|
||||
#endif
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void sq_pwr_domain_on_finisher_common(
|
||||
const psci_power_state_t *target_state)
|
||||
{
|
||||
assert(SQ_CORE_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF);
|
||||
|
||||
/*
|
||||
* Perform the common cluster specific operations i.e enable coherency
|
||||
* if this cluster was off.
|
||||
*/
|
||||
if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF)
|
||||
plat_sq_interconnect_enter_coherency();
|
||||
}
|
||||
|
||||
void sq_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
/* Assert that the system power domain need not be initialized */
|
||||
assert(SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_RUN);
|
||||
|
||||
sq_pwr_domain_on_finisher_common(target_state);
|
||||
|
||||
/* Program the gic per-cpu distributor or re-distributor interface */
|
||||
sq_gic_pcpu_init();
|
||||
|
||||
/* Enable the gic cpu interface */
|
||||
sq_gic_cpuif_enable();
|
||||
}
|
||||
|
||||
#if !SQ_USE_SCMI_DRIVER
|
||||
static void sq_power_down_common(const psci_power_state_t *target_state)
|
||||
{
|
||||
uint32_t cluster_state = scpi_power_on;
|
||||
uint32_t system_state = scpi_power_on;
|
||||
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
sq_gic_cpuif_disable();
|
||||
|
||||
/* Check if power down at system power domain level is requested */
|
||||
if (SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF)
|
||||
system_state = scpi_power_retention;
|
||||
|
||||
/* Cluster is to be turned off, so disable coherency */
|
||||
if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) {
|
||||
plat_sq_interconnect_exit_coherency();
|
||||
cluster_state = scpi_power_off;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask the SCP to power down the appropriate components depending upon
|
||||
* their state.
|
||||
*/
|
||||
scpi_set_sq_power_state(read_mpidr_el1(),
|
||||
scpi_power_off,
|
||||
cluster_state,
|
||||
system_state);
|
||||
}
|
||||
#endif
|
||||
|
||||
void sq_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
#if SQ_USE_SCMI_DRIVER
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
sq_gic_cpuif_disable();
|
||||
|
||||
/* Cluster is to be turned off, so disable coherency */
|
||||
if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) {
|
||||
plat_sq_interconnect_exit_coherency();
|
||||
}
|
||||
|
||||
sq_scmi_off(target_state);
|
||||
#else
|
||||
sq_power_down_common(target_state);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __dead2 sq_system_off(void)
|
||||
{
|
||||
#if SQ_USE_SCMI_DRIVER
|
||||
sq_scmi_sys_shutdown();
|
||||
#else
|
||||
volatile uint32_t *gpio = (uint32_t *)PLAT_SQ_GPIO_BASE;
|
||||
|
||||
/* set PD[9] high to power off the system */
|
||||
gpio[5] |= 0x2; /* set output */
|
||||
gpio[1] |= 0x2; /* set high */
|
||||
dmbst();
|
||||
|
||||
generic_delay_timer_init();
|
||||
|
||||
mdelay(1);
|
||||
|
||||
while (1) {
|
||||
gpio[1] &= ~0x2; /* set low */
|
||||
dmbst();
|
||||
|
||||
mdelay(1);
|
||||
|
||||
gpio[1] |= 0x2; /* set high */
|
||||
dmbst();
|
||||
|
||||
mdelay(100);
|
||||
}
|
||||
|
||||
wfi();
|
||||
ERROR("SQ System Off: operation not handled.\n");
|
||||
panic();
|
||||
#endif
|
||||
}
|
||||
|
||||
void __dead2 sq_system_reset(void)
|
||||
{
|
||||
#if SQ_USE_SCMI_DRIVER
|
||||
sq_scmi_sys_reboot();
|
||||
#else
|
||||
uint32_t response;
|
||||
|
||||
/* Send the system reset request to the SCP */
|
||||
response = scpi_sys_power_state(scpi_system_reboot);
|
||||
|
||||
if (response != SCP_OK) {
|
||||
ERROR("SQ System Reset: SCP error %u.\n", response);
|
||||
panic();
|
||||
}
|
||||
wfi();
|
||||
ERROR("SQ System Reset: operation not handled.\n");
|
||||
panic();
|
||||
#endif
|
||||
}
|
||||
|
||||
void sq_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
u_register_t scr;
|
||||
|
||||
assert(cpu_state == SQ_LOCAL_STATE_RET);
|
||||
|
||||
scr = read_scr_el3();
|
||||
/* Enable PhysicalIRQ bit for NS world to wake the CPU */
|
||||
write_scr_el3(scr | SCR_IRQ_BIT);
|
||||
isb();
|
||||
dsb();
|
||||
wfi();
|
||||
|
||||
/*
|
||||
* Restore SCR to the original value, synchronisation of scr_el3 is
|
||||
* done by eret while el3_exit to save some execution cycles.
|
||||
*/
|
||||
write_scr_el3(scr);
|
||||
}
|
||||
|
||||
const plat_psci_ops_t sq_psci_ops = {
|
||||
.pwr_domain_on = sq_pwr_domain_on,
|
||||
.pwr_domain_off = sq_pwr_domain_off,
|
||||
.pwr_domain_on_finish = sq_pwr_domain_on_finish,
|
||||
.cpu_standby = sq_cpu_standby,
|
||||
.system_off = sq_system_off,
|
||||
.system_reset = sq_system_reset,
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const struct plat_psci_ops **psci_ops)
|
||||
{
|
||||
#if !RESET_TO_BL31
|
||||
uintptr_t *sq_sec_ep = (uintptr_t *)BL2_MAILBOX_BASE;
|
||||
|
||||
*sq_sec_ep = sec_entrypoint;
|
||||
flush_dcache_range((uint64_t)sq_sec_ep,
|
||||
sizeof(*sq_sec_ep));
|
||||
#else
|
||||
sq_sec_entrypoint = sec_entrypoint;
|
||||
flush_dcache_range((uint64_t)&sq_sec_entrypoint,
|
||||
sizeof(sq_sec_entrypoint));
|
||||
#endif
|
||||
|
||||
*psci_ops = &sq_psci_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Socionext Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
.global sq_rotpk_hash
|
||||
.global sq_rotpk_hash_end
|
||||
.section .rodata.sq_rotpk_hash, "a"
|
||||
sq_rotpk_hash:
|
||||
/* DER header */
|
||||
.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
|
||||
.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
||||
/* SHA256 */
|
||||
.incbin ROTPK_HASH
|
||||
sq_rotpk_hash_end:
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <bl31/ehf.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <services/spm_mm_partition.h>
|
||||
|
||||
static const mmap_region_t plat_arm_secure_partition_mmap[] = {
|
||||
PLAT_SQ_FLASH_MMAP,
|
||||
PLAT_SQ_UART1_MMAP,
|
||||
PLAT_SQ_PERIPH_MMAP,
|
||||
PLAT_SQ_SP_IMAGE_MMAP,
|
||||
PLAT_SP_IMAGE_NS_BUF_MMAP,
|
||||
PLAT_SQ_SP_IMAGE_RW_MMAP,
|
||||
PLAT_SPM_SPM_BUF_EL0_MMAP,
|
||||
{0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Boot information passed to a secure partition during initialisation. Linear
|
||||
* indices in MP information will be filled at runtime.
|
||||
*/
|
||||
static spm_mm_mp_info_t sp_mp_info[] = {
|
||||
{0x80000000, 0}, {0x80000001, 0}, {0x80000100, 0}, {0x80000101, 0},
|
||||
{0x80000200, 0}, {0x80000201, 0}, {0x80000300, 0}, {0x80000301, 0},
|
||||
{0x80000400, 0}, {0x80000401, 0}, {0x80000500, 0}, {0x80000501, 0},
|
||||
{0x80000600, 0}, {0x80000601, 0}, {0x80000700, 0}, {0x80000701, 0},
|
||||
{0x80000800, 0}, {0x80000801, 0}, {0x80000900, 0}, {0x80000901, 0},
|
||||
{0x80000a00, 0}, {0x80000a01, 0}, {0x80000b00, 0}, {0x80000b01, 0},
|
||||
};
|
||||
|
||||
const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
|
||||
.h.type = PARAM_SP_IMAGE_BOOT_INFO,
|
||||
.h.version = VERSION_1,
|
||||
.h.size = sizeof(spm_mm_boot_info_t),
|
||||
.h.attr = 0,
|
||||
.sp_mem_base = BL32_BASE,
|
||||
.sp_mem_limit = BL32_LIMIT,
|
||||
.sp_image_base = BL32_BASE,
|
||||
.sp_stack_base = PLAT_SP_IMAGE_STACK_BASE,
|
||||
.sp_heap_base = PLAT_SQ_SP_HEAP_BASE,
|
||||
.sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
|
||||
.sp_shared_buf_base = PLAT_SPM_BUF_BASE,
|
||||
.sp_image_size = PLAT_SQ_SP_IMAGE_SIZE,
|
||||
.sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
|
||||
.sp_heap_size = PLAT_SQ_SP_HEAP_SIZE,
|
||||
.sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
|
||||
.sp_shared_buf_size = PLAT_SPM_BUF_SIZE,
|
||||
.num_sp_mem_regions = PLAT_SP_IMAGE_NUM_MEM_REGIONS,
|
||||
.num_cpus = PLATFORM_CORE_COUNT,
|
||||
.mp_info = sp_mp_info,
|
||||
};
|
||||
|
||||
const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
|
||||
{
|
||||
return plat_arm_secure_partition_mmap;
|
||||
}
|
||||
|
||||
const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
|
||||
void *cookie)
|
||||
{
|
||||
return &plat_arm_secure_partition_boot_info;
|
||||
}
|
||||
|
||||
static ehf_pri_desc_t sq_exceptions[] = {
|
||||
EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI),
|
||||
};
|
||||
EHF_REGISTER_PRIORITIES(sq_exceptions, ARRAY_SIZE(sq_exceptions), PLAT_PRI_BITS);
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Socionext Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
extern char sq_rotpk_hash[], sq_rotpk_hash_end[];
|
||||
|
||||
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
|
||||
unsigned int *flags)
|
||||
{
|
||||
*key_ptr = sq_rotpk_hash;
|
||||
*key_len = sq_rotpk_hash_end - sq_rotpk_hash;
|
||||
*flags = ROTPK_IS_HASH;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
|
||||
{
|
||||
/*
|
||||
* No support for non-volatile counter. Update the ROT key to protect
|
||||
* the system against rollback.
|
||||
*/
|
||||
*nv_ctr = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
|
||||
{
|
||||
return get_mbedtls_heap_helper(heap_addr, heap_size);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch.h>
|
||||
|
||||
#include <sq_common.h>
|
||||
|
||||
unsigned char sq_pd_tree_desc[PLAT_CLUSTER_COUNT + 1];
|
||||
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cluster_id, cpu_id;
|
||||
|
||||
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
if (cluster_id >= PLAT_CLUSTER_COUNT)
|
||||
return -1;
|
||||
|
||||
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
if (cpu_id >= PLAT_MAX_CORES_PER_CLUSTER)
|
||||
return -1;
|
||||
|
||||
return sq_calc_core_pos(mpidr);
|
||||
}
|
||||
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
sq_pd_tree_desc[0] = PLAT_CLUSTER_COUNT;
|
||||
|
||||
for (i = 0; i < PLAT_CLUSTER_COUNT; i++)
|
||||
sq_pd_tree_desc[i + 1] = PLAT_MAX_CORES_PER_CLUSTER;
|
||||
|
||||
return sq_pd_tree_desc;
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
|
||||
#define SQ_REG_REGION_BASE 0x20000000ULL
|
||||
#define SQ_REG_REGION_SIZE 0x60000000ULL
|
||||
|
||||
void sq_mmap_setup(uintptr_t total_base, size_t total_size,
|
||||
const struct mmap_region *mmap)
|
||||
{
|
||||
VERBOSE("Trusted RAM seen by this BL image: %p - %p\n",
|
||||
(void *)total_base, (void *)(total_base + total_size));
|
||||
mmap_add_region(total_base, total_base,
|
||||
total_size,
|
||||
MT_NON_CACHEABLE | MT_RW | MT_SECURE);
|
||||
|
||||
/* remap the code section */
|
||||
VERBOSE("Code region: %p - %p\n",
|
||||
(void *)BL_CODE_BASE, (void *)BL_CODE_END);
|
||||
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
|
||||
round_up(BL_CODE_END, PAGE_SIZE) - BL_CODE_BASE,
|
||||
MT_NON_CACHEABLE | MT_RO | MT_SECURE);
|
||||
|
||||
/* Re-map the read-only data section */
|
||||
VERBOSE("Read-only data region: %p - %p\n",
|
||||
(void *)BL_RO_DATA_BASE, (void *)BL_RO_DATA_END);
|
||||
mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
|
||||
round_up(BL_RO_DATA_END, PAGE_SIZE) - BL_RO_DATA_BASE,
|
||||
(MT_NON_CACHEABLE | MT_RO | MT_EXECUTE_NEVER |
|
||||
MT_SECURE));
|
||||
|
||||
/* remap the coherent memory region */
|
||||
VERBOSE("Coherent region: %p - %p\n",
|
||||
(void *)BL_COHERENT_RAM_BASE, (void *)BL_COHERENT_RAM_END);
|
||||
mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
|
||||
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE);
|
||||
|
||||
/* register region */
|
||||
mmap_add_region(SQ_REG_REGION_BASE, SQ_REG_REGION_BASE,
|
||||
SQ_REG_REGION_SIZE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE);
|
||||
|
||||
/* additional regions if needed */
|
||||
if (mmap)
|
||||
mmap_add(mmap);
|
||||
|
||||
init_xlat_tables();
|
||||
}
|
||||
Reference in New Issue
Block a user