Commit 57870747 authored by Konstantin Porotchkin's avatar Konstantin Porotchkin
Browse files

plat/marvell/armada/common/mss: use MSS SRAM in secure mode



The CP MSS IRAM is only accessible by CM3 CPU and MSS DMA.
In secure boot mode the MSS DMA is unable to directly load
the MSS FW image from DRAM to IRAM.
This patch adds support for using the MSS SRAM as intermediate
storage. The MSS FW image is loaded by application CPU into the
MSS SRAM first, then transferred to MSS IRAM by MSS DMA.
Such change allows the CP MSS image load in secure mode.

Change-Id: Iee7a51d157743a0bdf8acb668ee3d599f760a712
Signed-off-by: default avatarKonstantin Porotchkin <kostap@marvell.com>
Reviewed-by: default avatarStefan Chulski <stefanc@marvell.com>
Reviewed-by: default avatarGrzegorz Jaszczyk <jaszczyk@marvell.com>
parent c42d5eea
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#define MSS_EXTERNAL_ADDR_MASK 0xfffffff #define MSS_EXTERNAL_ADDR_MASK 0xfffffff
#define MSS_INTERNAL_ACCESS_BIT 28 #define MSS_INTERNAL_ACCESS_BIT 28
#define MSS_AP_REGS_OFFSET 0x580000
#define MSS_CP_SRAM_OFFSET 0x220000
#define MSS_CP_REGS_OFFSET 0x280000
struct addr_map_win ccu_mem_map[] = { struct addr_map_win ccu_mem_map[] = {
{MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID} {MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID}
}; };
...@@ -121,12 +125,21 @@ int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) ...@@ -121,12 +125,21 @@ int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx) uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx)
{ {
return MVEBU_CP_REGS_BASE(cp_idx) + 0x280000; return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET;
}
uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx)
{
if (is_secure()) {
return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET;
}
return 0; /* SRAM will not be used */
} }
uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx) uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx)
{ {
return MVEBU_REGS_BASE + 0x580000; return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET;
} }
uint32_t bl2_plat_get_cp_count(int ap_idx) uint32_t bl2_plat_get_cp_count(int ap_idx)
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#define HEADER_VERSION 0x1 #define HEADER_VERSION 0x1
#define MSS_IDRAM_SIZE 0x10000 /* 64KB */ #define MSS_IDRAM_SIZE 0x10000 /* 64KB */
#define MSS_SRAM_SIZE 0x8000 /* 32KB */
/* Types definitions */ /* Types definitions */
typedef struct file_header { typedef struct file_header {
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#define MSS_DMA_TIMEOUT 1000 #define MSS_DMA_TIMEOUT 1000
#define MSS_EXTERNAL_SPACE 0x50000000 #define MSS_EXTERNAL_SPACE 0x50000000
#define MSS_EXTERNAL_ADDR_MASK 0xfffffff #define MSS_EXTERNAL_ADDR_MASK 0xfffffff
#define MSS_INTERNAL_SPACE 0x40000000
#define MSS_INTERNAL_ADDR_MASK 0x00ffffff
#define DMA_SIZE 128 #define DMA_SIZE 128
...@@ -60,60 +62,108 @@ static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl) ...@@ -60,60 +62,108 @@ static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
return 0; return 0;
} }
static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs) static int mss_iram_dma_load(uint32_t src_addr, uint32_t size,
uintptr_t mss_regs)
{ {
uint32_t i, loop_num, timeout; uint32_t i, loop_num, timeout;
/* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
if (size > MSS_IDRAM_SIZE) {
ERROR("image is too big to fit into MSS CM3 memory\n");
return 1;
}
NOTICE("Loading MSS image from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
src_addr, size, mss_regs);
/* load image to MSS RAM using DMA */ /* load image to MSS RAM using DMA */
loop_num = (size / DMA_SIZE) + (((size & (DMA_SIZE - 1)) == 0) ? 0 : 1); loop_num = (size / DMA_SIZE) + !!(size % DMA_SIZE);
for (i = 0; i < loop_num; i++) { for (i = 0; i < loop_num; i++) {
/* write destination and source addresses */ /* write source address */
mmio_write_32(MSS_DMA_SRCBR(mss_regs), mmio_write_32(MSS_DMA_SRCBR(mss_regs),
MSS_EXTERNAL_SPACE | src_addr + (i * DMA_SIZE));
((src_addr & MSS_EXTERNAL_ADDR_MASK) + /* write destination address */
(i * DMA_SIZE)));
mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE)); mmio_write_32(MSS_DMA_DSTBR(mss_regs), (i * DMA_SIZE));
/* make sure DMA data is ready before triggering it */
dsb(); /* make sure DMA data is ready before triggering it */ dsb();
/* set the DMA control register */ /* set the DMA control register */
mmio_write_32(MSS_DMA_CTRLR(mss_regs), ((MSS_DMA_CTRLR_REQ_SET mmio_write_32(MSS_DMA_CTRLR(mss_regs),
<< MSS_DMA_CTRLR_REQ_OFFSET) | ((MSS_DMA_CTRLR_REQ_SET <<
MSS_DMA_CTRLR_REQ_OFFSET) |
(DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET))); (DMA_SIZE << MSS_DMA_CTRLR_SIZE_OFFSET)));
/* Poll DMA_ACK at MSS_DMACTLR until it is ready */ /* Poll DMA_ACK at MSS_DMACTLR until it is ready */
timeout = MSS_DMA_TIMEOUT; timeout = MSS_DMA_TIMEOUT;
while (timeout) { while (timeout > 0U) {
if ((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >> if ((mmio_read_32(MSS_DMA_CTRLR(mss_regs)) >>
MSS_DMA_CTRLR_ACK_OFFSET & MSS_DMA_CTRLR_ACK_MASK) (MSS_DMA_CTRLR_ACK_OFFSET &
MSS_DMA_CTRLR_ACK_MASK))
== MSS_DMA_CTRLR_ACK_READY) { == MSS_DMA_CTRLR_ACK_READY) {
break; break;
} }
udelay(50); udelay(50);
timeout--; timeout--;
} }
if (timeout == 0) { if (timeout == 0) {
ERROR("\nDMA failed to load MSS image\n"); ERROR("\nMSS DMA failed (timeout)\n");
return 1;
}
}
return 0;
}
static int mss_image_load(uint32_t src_addr, uint32_t size,
uintptr_t mss_regs, uintptr_t sram)
{
uint32_t chunks = 1; /* !sram case */
uint32_t chunk_num;
int ret;
/* Check if the img size is not bigger than ID-RAM size of MSS CM3 */
if (size > MSS_IDRAM_SIZE) {
ERROR("image is too big to fit into MSS CM3 memory\n");
return 1; return 1;
} }
/* The CPx MSS DMA cannot access DRAM directly in secure boot mode
* Copy the MSS FW image to MSS SRAM by the CPU first, then run
* MSS DMA for SRAM to IRAM copy
*/
if (sram != 0) {
chunks = size / MSS_SRAM_SIZE + !!(size % MSS_SRAM_SIZE);
}
NOTICE("%s Loading MSS FW from addr. 0x%x Size 0x%x to MSS at 0x%lx\n",
sram == 0 ? "" : "SECURELY", src_addr, size, mss_regs);
for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
size_t chunk_size = size;
uint32_t img_src = MSS_EXTERNAL_SPACE | /* no SRAM */
(src_addr & MSS_EXTERNAL_ADDR_MASK);
if (sram != 0) {
uintptr_t chunk_source =
src_addr + MSS_SRAM_SIZE * chunk_num;
if (chunk_num != (size / MSS_SRAM_SIZE)) {
chunk_size = MSS_SRAM_SIZE;
} else {
chunk_size = size % MSS_SRAM_SIZE;
}
if (chunk_size == 0) {
break;
}
VERBOSE("Chunk %d -> SRAM 0x%lx from 0x%lx SZ 0x%lx\n",
chunk_num, sram, chunk_source, chunk_size);
memcpy((void *)sram, (void *)chunk_source, chunk_size);
dsb();
img_src = MSS_INTERNAL_SPACE |
(sram & MSS_INTERNAL_ADDR_MASK);
}
ret = mss_iram_dma_load(img_src, chunk_size, mss_regs);
if (ret != 0) {
ERROR("MSS FW chunk %d load failed\n", chunk_num);
return ret;
}
} }
bl2_plat_configure_mss_windows(mss_regs); bl2_plat_configure_mss_windows(mss_regs);
/* Release M3 from reset */ /* Release M3 from reset */
mmio_write_32(MSS_M3_RSTCR(mss_regs), (MSS_M3_RSTCR_RST_OFF << mmio_write_32(MSS_M3_RSTCR(mss_regs),
MSS_M3_RSTCR_RST_OFFSET)); (MSS_M3_RSTCR_RST_OFF << MSS_M3_RSTCR_RST_OFFSET));
NOTICE("Done\n"); NOTICE("Done\n");
...@@ -162,7 +212,7 @@ static int mss_ap_load_image(uintptr_t single_img, ...@@ -162,7 +212,7 @@ static int mss_ap_load_image(uintptr_t single_img,
VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n"); VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n");
ret = mss_image_load(single_img, image_size, ret = mss_image_load(single_img, image_size,
bl2_plat_get_ap_mss_regs(ap_idx)); bl2_plat_get_ap_mss_regs(ap_idx), 0);
if (ret != 0) { if (ret != 0) {
ERROR("SCP Image load failed\n"); ERROR("SCP Image load failed\n");
return -1; return -1;
...@@ -218,6 +268,8 @@ static int load_img_to_cm3(enum cm3_t cm3_type, ...@@ -218,6 +268,8 @@ static int load_img_to_cm3(enum cm3_t cm3_type,
cp_index, ap_idx); cp_index, ap_idx);
ret = mss_image_load(single_img, image_size, ret = mss_image_load(single_img, image_size,
bl2_plat_get_cp_mss_regs( bl2_plat_get_cp_mss_regs(
ap_idx, cp_index),
bl2_plat_get_cp_mss_sram(
ap_idx, cp_index)); ap_idx, cp_index));
if (ret != 0) { if (ret != 0) {
ERROR("SCP Image load failed\n"); ERROR("SCP Image load failed\n");
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
int scp_bootloader_transfer(void *image, unsigned int image_size); int scp_bootloader_transfer(void *image, unsigned int image_size);
uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx); uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx);
uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx);
uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx); uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx);
uint32_t bl2_plat_get_cp_count(int ap_idx); uint32_t bl2_plat_get_cp_count(int ap_idx);
uint32_t bl2_plat_get_ap_count(void); uint32_t bl2_plat_get_ap_count(void);
......
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