Commit 327ad299 authored by Remi Pommarel's avatar Remi Pommarel
Browse files

meson/gxl: Configure and boot SCP



On Amlogic gxl (s905x) SOC, in order to use SCP, bl31 has to send bl30
and bl301 firmware along with their SHA256 hash over scpi.
Signed-off-by: default avatarRemi Pommarel <repk@triplefau.lt>
parent b99f9224
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
* BL31 from BL2. * BL31 from BL2.
*/ */
static entry_point_info_t bl33_image_ep_info; static entry_point_info_t bl33_image_ep_info;
static image_info_t bl30_image_info;
static image_info_t bl301_image_info;
/******************************************************************************* /*******************************************************************************
* Return a pointer to the 'entry_point_info' structure of the next image for * Return a pointer to the 'entry_point_info' structure of the next image for
...@@ -50,19 +52,20 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) ...@@ -50,19 +52,20 @@ entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
* tables. BL2 has flushed this information to memory, so we are guaranteed * tables. BL2 has flushed this information to memory, so we are guaranteed
* to pick up good data. * to pick up good data.
******************************************************************************/ ******************************************************************************/
struct gxbb_bl31_param { struct gxl_bl31_param {
param_header_t h; param_header_t h;
image_info_t *bl31_image_info; image_info_t *bl31_image_info;
entry_point_info_t *bl32_ep_info; entry_point_info_t *bl32_ep_info;
image_info_t *bl32_image_info; image_info_t *bl32_image_info;
entry_point_info_t *bl33_ep_info; entry_point_info_t *bl33_ep_info;
image_info_t *bl33_image_info; image_info_t *bl33_image_info;
image_info_t *scp_image_info[];
}; };
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3) u_register_t arg2, u_register_t arg3)
{ {
struct gxbb_bl31_param *from_bl2; struct gxl_bl31_param *from_bl2;
/* Initialize the console to provide early debug support */ /* Initialize the console to provide early debug support */
gxbb_console_init(); gxbb_console_init();
...@@ -74,7 +77,7 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, ...@@ -74,7 +77,7 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
assert(arg1 == GXBB_BL31_PLAT_PARAM_VAL); assert(arg1 == GXBB_BL31_PLAT_PARAM_VAL);
/* Check that params passed from BL2 are not NULL. */ /* Check that params passed from BL2 are not NULL. */
from_bl2 = (struct gxbb_bl31_param *) arg0; from_bl2 = (struct gxl_bl31_param *) arg0;
/* Check params passed from BL2 are not NULL. */ /* Check params passed from BL2 are not NULL. */
assert(from_bl2 != NULL); assert(from_bl2 != NULL);
...@@ -91,6 +94,9 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, ...@@ -91,6 +94,9 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
ERROR("BL31: BL33 entrypoint not obtained from BL2\n"); ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
panic(); panic();
} }
bl30_image_info = *from_bl2->scp_image_info[0];
bl301_image_info = *from_bl2->scp_image_info[1];
} }
void bl31_plat_arch_setup(void) void bl31_plat_arch_setup(void)
...@@ -100,6 +106,14 @@ void bl31_plat_arch_setup(void) ...@@ -100,6 +106,14 @@ void bl31_plat_arch_setup(void)
enable_mmu_el3(0); enable_mmu_el3(0);
} }
static inline void gxl_scp_boot(void)
{
scpi_upload_scp_fw(bl30_image_info.image_base,
bl30_image_info.image_size, 0);
scpi_upload_scp_fw(bl301_image_info.image_base,
bl301_image_info.image_size, 1);
}
/******************************************************************************* /*******************************************************************************
* GICv2 driver setup information * GICv2 driver setup information
******************************************************************************/ ******************************************************************************/
...@@ -140,5 +154,7 @@ void bl31_platform_setup(void) ...@@ -140,5 +154,7 @@ void bl31_platform_setup(void)
gicv2_pcpu_distif_init(); gicv2_pcpu_distif_init();
gicv2_cpuif_enable(); gicv2_cpuif_enable();
// gxbb_thermal_unknown(); gxl_scp_boot();
gxbb_thermal_unknown();
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define GXBB_PRIVATE_H #define GXBB_PRIVATE_H
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
/* Utility functions */ /* Utility functions */
unsigned int plat_gxbb_calc_core_pos(u_register_t mpidr); unsigned int plat_gxbb_calc_core_pos(u_register_t mpidr);
...@@ -29,6 +30,7 @@ void scpi_jtag_set_state(uint32_t state, uint8_t select); ...@@ -29,6 +30,7 @@ void scpi_jtag_set_state(uint32_t state, uint8_t select);
uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size); uint32_t scpi_efuse_read(void *dst, uint32_t base, uint32_t size);
void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1, void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
uint32_t arg2, uint32_t arg3); uint32_t arg2, uint32_t arg3);
void scpi_upload_scp_fw(uintptr_t addr, size_t size, int send);
/* Peripherals */ /* Peripherals */
void gxbb_thermal_unknown(void); void gxbb_thermal_unknown(void);
......
...@@ -9,11 +9,13 @@ ...@@ -9,11 +9,13 @@
#include <plat/common/platform.h> #include <plat/common/platform.h>
#include <platform_def.h> #include <platform_def.h>
#include <string.h> #include <string.h>
#include <crypto/sha_dma.h>
#include "gxl_private.h" #include "gxl_private.h"
#define SIZE_SHIFT 20 #define SIZE_SHIFT 20
#define SIZE_MASK 0x1FF #define SIZE_MASK 0x1FF
#define SIZE_FWBLK 0x200UL
/* /*
* Note: The Amlogic SCP firmware uses the legacy SCPI protocol. * Note: The Amlogic SCP firmware uses the legacy SCPI protocol.
...@@ -24,12 +26,16 @@ ...@@ -24,12 +26,16 @@
#define SCPI_CMD_JTAG_SET_STATE 0xC0 #define SCPI_CMD_JTAG_SET_STATE 0xC0
#define SCPI_CMD_EFUSE_READ 0xC2 #define SCPI_CMD_EFUSE_READ 0xC2
#define SCPI_CMD_COPY_FW 0xd4
#define SCPI_CMD_SET_FW_ADDR 0xd3
#define SCPI_CMD_FW_SIZE 0xd2
static inline uint32_t scpi_cmd(uint32_t command, uint32_t size) static inline uint32_t scpi_cmd(uint32_t command, uint32_t size)
{ {
return command | (size << SIZE_SHIFT); return command | (size << SIZE_SHIFT);
} }
void scpi_secure_message_send(uint32_t command, uint32_t size) static void scpi_secure_message_send(uint32_t command, uint32_t size)
{ {
mhu_secure_message_send(scpi_cmd(command, size)); mhu_secure_message_send(scpi_cmd(command, size));
} }
...@@ -135,3 +141,71 @@ void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1, ...@@ -135,3 +141,71 @@ void scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
mhu_secure_message_wait(); mhu_secure_message_wait();
mhu_secure_message_end(); mhu_secure_message_end();
} }
static inline void scpi_copy_scp_data(uint8_t *data, size_t len)
{
void *dst = (void *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
size_t sz;
mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
mhu_secure_message_wait();
for (sz = 0; sz < len; sz += SIZE_FWBLK) {
memcpy(dst, data + sz, MIN(SIZE_FWBLK, len - sz));
mhu_secure_message_send(SCPI_CMD_COPY_FW);
}
}
static inline void scpi_set_scp_addr(uint64_t addr, size_t len)
{
volatile uint64_t *dst = (uint64_t *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
/*
* It is ok as GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD is mapped as
* non cachable
*/
*dst = addr;
scpi_secure_message_send(SCPI_CMD_SET_FW_ADDR, sizeof(addr));
mhu_secure_message_wait();
mmio_write_32(GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
mhu_secure_message_wait();
}
static inline void scpi_send_fw_hash(uint8_t hash[], size_t len)
{
void *dst = (void *)GXBB_MHU_SECURE_AP_TO_SCP_PAYLOAD;
memcpy(dst, hash, len);
mhu_secure_message_send(0xd0);
mhu_secure_message_send(0xd1);
mhu_secure_message_send(0xd5);
mhu_secure_message_end();
}
/**
* Upload a FW to SCP.
*
* @param addr: firmware data address
* @param size: size of firmware
* @param send: If set, actually copy the firmware in SCP memory otherwise only
* send the firmware address.
*/
void scpi_upload_scp_fw(uintptr_t addr, size_t size, int send)
{
struct asd_ctx ctx;
asd_sha_init(&ctx, ASM_SHA256);
asd_sha_update(&ctx, (void *)addr, size);
asd_sha_finalize(&ctx);
mhu_secure_message_start();
if (send == 0)
scpi_set_scp_addr(addr, size);
else
scpi_copy_scp_data((void *)addr, size);
scpi_send_fw_hash(ctx.digest, sizeof(ctx.digest));
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment