GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -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();
}
@@ -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 */
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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 */
@@ -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__ */
@@ -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 */
@@ -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 */
@@ -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
@@ -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;
}
@@ -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
@@ -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;
}
@@ -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;
}
@@ -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();
}