Skip to content

Commit

Permalink
Add Marvell ARMADA A7K A8K platform support
Browse files Browse the repository at this point in the history
Added Marvell platform with initial support for ARMADA A7K & A8K.

Only tested 64-bit mode with default configurations:
1. build command
    make PLATFORM=marvell-armada7080 CFG_ARM64_core=y
2. Passed xtest

Signed-off-by: Kevin Peng <kevinp@marvell.com>
Acked-by: Jerome Forissier <jerome.forissier@linaro.org>
  • Loading branch information
Kevin Peng committed Sep 19, 2017
1 parent 6cfeadb commit 1cf6cec
Show file tree
Hide file tree
Showing 13 changed files with 664 additions and 0 deletions.
1 change: 1 addition & 0 deletions .shippable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ build:
- _make PLATFORM=rockchip-rk322x
- _make PLATFORM=rockchip-rk322x CFG_TEE_CORE_LOG_LEVEL=4 DEBUG=1
- _make PLATFORM=sam
- _make PLATFORM=marvell-armada7k8k CFG_ARM64_core=y

#
# Regressions tests (QEMU)
Expand Down
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ script:
# Atmel ATSAMA5D2-XULT
- $make PLATFORM=sam

# Marvell ARMADA 7K 8K
- $make PLATFORM=marvell-armada7k8k CFG_ARM64_core=y

# Run regression tests (xtest in QEMU)
- (cd ${HOME}/optee_repo/build && $make check CROSS_COMPILE="ccache arm-linux-gnueabihf-" AARCH32_CROSS_COMPILE=arm-linux-gnueabihf- CFG_TEE_CORE_DEBUG=y DUMP_LOGS_ON_ERROR=1)

Expand Down
2 changes: 2 additions & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ for these platforms.
| HiKey Board (HiSilicon Kirin 620) |`Linaro <op-tee@linaro.org>`|
| HiKey960 Board (HiSilicon Kirin 960) |`Linaro <op-tee@linaro.org>`|
| HiSilicon D02 |`Linaro <op-tee@linaro.org>`|
| Marvell Armada 70x0 |`Kevin Peng <kevinp@marvell.com>`|
| Marvell Armada 80x0 |`Kevin Peng <kevinp@marvell.com>`|
| MediaTek MT8173 EVB Board |`Linaro <op-tee@linaro.org>`|
| QEMU |`Linaro <op-tee@linaro.org>`|
| Raspberry Pi3 |`Linaro <op-tee@linaro.org>`|
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ platforms have different sub-maintainers, please refer to the file
| [HiSilicon D02](http://open-estuary.org/d02-2)|`PLATFORM=d02`| No |
| [HiKey Board (HiSilicon Kirin 620)](https://www.96boards.org/product/hikey)|`PLATFORM=hikey` or `PLATFORM=hikey-hikey`| Yes |
| [HiKey960 Board (HiSilicon Kirin 960)](https://www.96boards.org/product/hikey960)|`PLATFORM=hikey-hikey960`| Yes |
| [Marvell ARMADA 7K Family](http://www.marvell.com/embedded-processors/armada-70xx/)|`PLATFORM=marvell-armada7k8k`| No |
| [Marvell ARMADA 8K Family](http://www.marvell.com/embedded-processors/armada-80xx/)|`PLATFORM=marvell-armada7k8k`| No |
| [MediaTek MT8173 EVB Board](https://www.mediatek.com/products/tablets/mt8173)|`PLATFORM=mediatek-mt8173`| No |
| [QEMU](http://wiki.qemu.org/Main_Page) |`PLATFORM=vexpress-qemu_virt`| Yes |
| [QEMUv8](http://wiki.qemu.org/Main_Page) |`PLATFORM=vexpress-qemu_armv8a`| Yes |
Expand Down
52 changes: 52 additions & 0 deletions core/arch/arm/plat-marvell/armada7k8k/armada7k8k_core_pos_a64.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2017, Marvell International Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <asm.S>
#include <arm.h>

.globl plat_my_core_pos
/*
* unsigned int plat_my_core_pos(void)
* This function uses the plat_marvell_calc_core_pos()
* definition to get the index of the calling CPU.
*/
FUNC plat_my_core_pos , :
mrs x0, mpidr_el1
b plat_marvell_calc_core_pos
END_FUNC plat_my_core_pos

/*
* unsigned int plat_marvell_calc_core_pos(uint64_t mpidr)
* Helper function to calculate the core position.
* With this function: CorePos = (ClusterId * 2) + CoreId
*/
FUNC plat_marvell_calc_core_pos , :
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
add x0, x1, x0, LSR #7
ret
END_FUNC plat_marvell_calc_core_pos
305 changes: 305 additions & 0 deletions core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
/*
* Copyright (C) 2017 Marvell International Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <kernel/panic.h>
#include <mm/core_memprot.h>
#include <initcall.h>
#include <io.h>
#include <util.h>

#define PHY_2_VIR(addr) ((vaddr_t)phys_to_virt((addr), MEM_AREA_IO_SEC))

#define MCU_MC_CONTROL_0_REG PHY_2_VIR(MCU_BASE + 0x044)
#define TRUSTZONE_LOCK (0x1 << 31)

#define MCU_TZ_RANGE_HIGH_REG(x) PHY_2_VIR(MCU_BASE + 0x84 + ((x) << 3))
#define MCU_TZ_RANGE_LOW_REG(x) PHY_2_VIR(MCU_BASE + 0x80 + ((x) << 3))

#define RW_PERM 0x0
#define RO_PERM 0x1
#define WO_PERM 0x2
#define ABORT_PERM 0x3

#define MAX_RANGE_NUM (16)
#define INVALID_SIZE_CODE (0xff)

#ifdef TEE_RES_CFG_16M
#define RSVD_SEC_MEM (SIZE_8M + SIZE_8M)
#elif defined(TEE_RES_CFG_24M)
#define RSVD_SEC_MEM (SIZE_8M + SIZE_8M + SIZE_8M)
#elif defined(TEE_RES_CFG_8M)
#define RSVD_SEC_MEM (SIZE_8M)
#else
#error "no reserved secure memory defined."
#endif

#define RA_ADDR (TZDRAM_BASE)
#define RA_SIZE (TZDRAM_SIZE)
#define RA_PERM (ABORT_PERM)

#define TZ_GET_VALID(data, ret) ((ret) = ((data) & (0x1)))
#define TZ_SET_VALID(data, val) \
do { \
(data) &= (~(0x1)); \
(data) |= ((val) & 0x1); \
} while (0)

#define TZ_GET_PERM(data, ret) ((ret) = (((data) & (0x3 << 1)) >> 1))
#define TZ_SET_PERM(data, val) \
do { \
(data) &= (~(0x3 << 1)); \
(data) |= (((val) & 0x3) << 1); \
} while (0)

#define TZ_GET_RZ_EN(data, ret) ((ret) = (((data) & (0x1 << 3)) >> 3))
#define TZ_SET_RZ_EN(data, val) \
do { \
(data) &= (~(0x1 << 3)); \
(data) |= (((val) & 0x1) << 3); \
} while (0)

#define TZ_GET_AREA_LEN_CODE(data, ret) ((ret) = (((data) & (0x1F << 7)) >> 7))

#define TZ_SET_AREA_LEN_CODE(data, val) \
do { \
(data) &= (~(0x1F << 7)); \
(data) |= (((val) & 0x1F) << 7); \
} while (0)

#define TZ_GET_START_ADDR_L(data, ret) \
((ret) = (((data) & 0xFFFFF000)))

#define TZ_SET_START_ADDR_L(data, val) \
do { \
(data) &= (~0xFFFFF000); \
(data) |= (((val) & 0xFFFFF000)); \
} while (0)

#define TZ_GET_UR_PERM(data, val) ((ret) = (((data) & (0x3 << 4)) >> 4))
#define TZ_SET_UR_PERM(data, val) \
do { \
(data) &= (~(0x3 << 4)); \
(data) |= (((val) & 0x3) << 4); \
} while (0)

#define TZ_GET_UR_RZ_EN(data, val) \
((ret) = (((data) & (0x1 << 6)) >> 6))

#define TZ_SET_UR_RZ_EN(data, val) \
do { \
(data) &= (~(0x1 << 6)); \
(data) |= (((val) & 0x1) << 6); \
} while (0)

/* armada mini region size is 1M */
#define RANGE_SIZE_TO_CODE(size, code, i) \
do { \
(code) = INVALID_SIZE_CODE; \
for ((i) = 8; (i) <= 0x1f; (i)++) { \
if (((uint32_t)0x1 << (i)) == ((size) >> 12)) { \
(code) = (i); \
break; \
} \
} \
} while (0)

#define RANGE_CODE_TO_SIZE_K(code, sizek) \
((sizek) = ((4) << (code))) \

#define TZ_LOCK_MC(x) \
do { \
(x) = read32(MCU_MC_CONTROL_0_REG); \
(x) |= (TRUSTZONE_LOCK); \
write32((x), MCU_MC_CONTROL_0_REG); \
} while (0)

#define _IS_ALIGNED(_addr, _algn) (!((_addr) & ((_algn) - 1)))

register_phys_mem(MEM_AREA_IO_SEC, MCU_BASE, CORE_MMU_DEVICE_SIZE);
register_phys_mem(MEM_AREA_IO_SEC, MC_SCR_REGISTER, CORE_MMU_DEVICE_SIZE);

static int32_t _find_valid_range(void)
{
uint32_t i;
uint32_t tmp;
uint32_t valid;

for (i = 0; i < MAX_RANGE_NUM; i++) {
tmp = read32(MCU_TZ_RANGE_LOW_REG(i));
TZ_GET_VALID(tmp, valid);
if (!valid)
return i;
}
return -1;
}

static int32_t set_range(uint32_t addr, uint32_t size, uint32_t perm)
{
uint32_t data;
uint32_t sizecode;
int32_t valid_range;
uint32_t i;

if (!_IS_ALIGNED(addr, SIZE_1M)) {
EMSG("region addr(0x%" PRIx32 ") is not aligned with 1M!",
addr);
return -1;
}

if (!_IS_ALIGNED(size, SIZE_1M)) {
EMSG("region size(0x%" PRIx32 ") is not aligned with 1M!",
size);
return -1;
}

if (!_IS_ALIGNED(addr, size)) {
EMSG("region size(0x%" PRIx32
") not align with addr(0x%" PRIx32 ")",
size, addr);
return -1;
}

RANGE_SIZE_TO_CODE(size, sizecode, i);
if (sizecode == INVALID_SIZE_CODE) {
EMSG("not valid region size(2^n)! size:0x%" PRIx32, size);
return -1;
}

valid_range = _find_valid_range();
if (valid_range == -1) {
EMSG("ERR: can't find valid range!");
return -1;
}

data = read32(MCU_TZ_RANGE_LOW_REG(valid_range));

TZ_SET_VALID(data, 1);
TZ_SET_PERM(data, perm);
TZ_SET_AREA_LEN_CODE(data, sizecode);
TZ_SET_START_ADDR_L(data, addr);

if (!valid_range) {
/* Set Undefine Range RW */
TZ_SET_UR_PERM(data, RW_PERM);
TZ_SET_UR_RZ_EN(data, 0);
}

write32(data, MCU_TZ_RANGE_LOW_REG(valid_range));

return 0;
}

static void _dump_range(void)
{
uint32_t i;
uint32_t tmp;
uint32_t sizek;
uint32_t valid_read;
uint32_t sizecode_read;
uint32_t __maybe_unused sizem;
uint32_t __maybe_unused addr_read;
uint32_t __maybe_unused perm_read;

for (i = 0; i < MAX_RANGE_NUM; i++) {
tmp = read32(MCU_TZ_RANGE_LOW_REG(i));

TZ_GET_VALID(tmp, valid_read);
TZ_GET_PERM(tmp, perm_read);
TZ_GET_AREA_LEN_CODE(tmp, sizecode_read);
TZ_GET_START_ADDR_L(tmp, addr_read);

if (valid_read) {
DMSG("Range Num%" PRId32
": Reg 0x%" PRIx64 " = 0x%" PRIx32,
i, MCU_TZ_RANGE_LOW_REG(i), tmp);
DMSG("AddrL: 0x%08" PRIx32, addr_read);
RANGE_CODE_TO_SIZE_K(sizecode_read, sizek);
sizem = (sizek >> 10);
DMSG("Size: %" PRId32 "K, %" PRId32 "M", sizek, sizem);
DMSG("Perm: %" PRId32, perm_read);
}
}
}

static uint32_t _find_granule(uint32_t addr, uint32_t size)
{
/* max supported granule for armada is 8TB
* but 2GB is far enough here
*/
uint32_t max_granule = SIZE_2G;

while (max_granule >= SIZE_4K) { /* min granule is 4kB */
if (max_granule <= size && _IS_ALIGNED(addr, max_granule))
return max_granule;

max_granule >>= 1;
}

return 0; /* cannot find a valid granule */
}

static void _set_range(uint32_t addr, uint32_t size, uint32_t perm)
{
uint32_t rgn_addr = addr;
uint32_t rgn_size = size;
uint32_t p;

while (rgn_size) {
p = _find_granule(rgn_addr, rgn_size);
if (!p)
panic("cannot find a suitable granule!");
if (set_range(rgn_addr, p, perm))
panic("set_range failed!");

rgn_addr += p;
rgn_size -= p;
}
}

static TEE_Result init_sec_perf(void)
{
uint32_t tmp;

/* MC_SCR config: deny NS access to MC registers */
tmp = read32(PHY_2_VIR(MC_SCR_REGISTER));
tmp |= 0x1;
write32(tmp, PHY_2_VIR(MC_SCR_REGISTER));

/* Set Secure Memory Region */
DMSG("sec-rgn size: ra = 0x%08" PRIx32 ", size = 0x%" PRIx32,
RA_ADDR, RA_SIZE);
_set_range(RA_ADDR, RA_SIZE, RA_PERM);

/* Close TZ register modification */
TZ_LOCK_MC(tmp);

_dump_range();

return TEE_SUCCESS;
}

service_init(init_sec_perf);
Loading

0 comments on commit 1cf6cec

Please sign in to comment.