From eea55b946314103d499efddafd2100421acc8275 Mon Sep 17 00:00:00 2001 From: Peifu Jiang Date: Wed, 24 May 2017 18:34:15 +0800 Subject: [PATCH] security: arm: meson: add tee support [2/2] PD#145094: security: arm: meson: add tee support Change-Id: I8789ef2b6d774abb6252e60c0726e7384127339f Signed-off-by: Peifu Jiang --- MAINTAINERS | 5 + arch/arm/boot/dts/amlogic/meson8b_m200.dts | 7 ++ arch/arm/boot/dts/amlogic/meson8b_m400.dts | 7 ++ arch/arm/mach-meson/Makefile | 2 + arch/arm/mach-meson/meson-secure.c | 188 +++++++++++++++++++++++++++++ arch/arm/mach-meson/meson-smc.S | 148 +++++++++++++++++++++++ arch/arm/mach-meson/meson.c | 53 ++++++++ arch/arm/mach-meson/platsmp.c | 62 +++++----- drivers/amlogic/cpu_version/meson32_cpu.c | 20 ++- drivers/amlogic/efuse/efuse_hw.c | 166 ++++++++++++------------- drivers/amlogic/jtag/meson_jtag.c | 43 ++++++- include/linux/amlogic/meson-secure.h | 112 +++++++++++++++++ 12 files changed, 678 insertions(+), 135 deletions(-) create mode 100644 arch/arm/mach-meson/meson-secure.c create mode 100644 arch/arm/mach-meson/meson-smc.S create mode 100644 include/linux/amlogic/meson-secure.h diff --git a/MAINTAINERS b/MAINTAINERS index aa6783e..46d24af 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13925,3 +13925,8 @@ F: sound/soc/amlogic/auge/* F: sound/soc/codecs/amlogic/* F: include/dt-bindings/clock/amlogic,axg-audio-clk.h +AMLOGIC Security Support +M: Peifu Jiang +F: include/linux/amlogic/meson-secure.h +F: arch/arm/mach-meson/meson-smc.S +F: arch/arm/mach-meson/meson-secure.c \ No newline at end of file diff --git a/arch/arm/boot/dts/amlogic/meson8b_m200.dts b/arch/arm/boot/dts/amlogic/meson8b_m200.dts index e29004a..72b4f68 100644 --- a/arch/arm/boot/dts/amlogic/meson8b_m200.dts +++ b/arch/arm/boot/dts/amlogic/meson8b_m200.dts @@ -42,6 +42,13 @@ compatible = "amlogic, pm-m8b-reserve"; reg = <0x04f00000 0x100000>; }; + + secos_reserved:linux,secos { + status = "disabled"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x06100000 0x3000000>; + no-map; + }; }; bt-dev{ diff --git a/arch/arm/boot/dts/amlogic/meson8b_m400.dts b/arch/arm/boot/dts/amlogic/meson8b_m400.dts index f35b9b1..534d193 100644 --- a/arch/arm/boot/dts/amlogic/meson8b_m400.dts +++ b/arch/arm/boot/dts/amlogic/meson8b_m400.dts @@ -40,6 +40,13 @@ compatible = "amlogic, pm-m8b-reserve"; reg = <0x04f00000 0x100000>; }; + + secos_reserved:linux,secos { + status = "disabled"; + compatible = "amlogic, aml_secos_memory"; + reg = <0x06100000 0x3000000>; + no-map; + }; }; sdio { diff --git a/arch/arm/mach-meson/Makefile b/arch/arm/mach-meson/Makefile index fe8345de..99732ca 100644 --- a/arch/arm/mach-meson/Makefile +++ b/arch/arm/mach-meson/Makefile @@ -1,3 +1,5 @@ obj-$(CONFIG_ARCH_MESON) += meson.o +obj-$(CONFIG_ARCH_MESON) += meson-smc.o +obj-$(CONFIG_ARCH_MESON) += meson-secure.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o hotplug-asm.o diff --git a/arch/arm/mach-meson/meson-secure.c b/arch/arm/mach-meson/meson-secure.c new file mode 100644 index 0000000..d47b458 --- /dev/null +++ b/arch/arm/mach-meson/meson-secure.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2014-2017 Amlogic, Inc. All rights reserved. + * + * All information contained herein is Amlogic confidential. + * + * This software is provided to you pursuant to Software License Agreement + * (SLA) with Amlogic Inc ("Amlogic"). This software may be used + * only in accordance with the terms of this agreement. + * + * Redistribution and use in source and binary forms, with or without + * modification is strictly prohibited without prior written permission from + * Amlogic. + * + * 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 + * OWNER 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MESON_SECURE_DEBUG 0 +#if MESON_SECURE_DEBUG +#undef pr_fmt +#define pr_fmt(fmt) "meson-secure: " fmt +#define TZDBG(fmt, ...) pr_info(fmt, ##__VA_ARGS__) +#else +#define TZDBG(fmt, ...) +#endif + +#define MESON_SECURE_FLAG_REG 0xC11081F0 +#define MESON_SECURE_FLAG_VALUE_DISABLED 0x0 +#define MESON_SECURE_FLAG_VALUE_ENABLED 0x1 +#define MESON_SECURE_FLAG_VALUE_INVALID 0xFFFFFFFF + +static uint32_t secure_flag = MESON_SECURE_FLAG_VALUE_INVALID; +static void __iomem *secure_flag_base; + +/* check secure status + * + * return value: + * true: secure enabled + * false: secure disabled + */ +bool meson_secure_enabled(void) +{ + bool ret = false; + + if (secure_flag == MESON_SECURE_FLAG_VALUE_INVALID) { + secure_flag_base = ioremap(MESON_SECURE_FLAG_REG, 4); + if (!secure_flag_base) { + TZDBG("iomap(0x%x) error.", MESON_SECURE_FLAG_REG); + return false; + } + secure_flag = readl_relaxed(secure_flag_base); + } + + TZDBG("secure_flag: 0x%x\n", secure_flag); + switch (secure_flag) { + case MESON_SECURE_FLAG_VALUE_ENABLED: + ret = true; + break; + case MESON_SECURE_FLAG_VALUE_DISABLED: + ret = false; + break; + case MESON_SECURE_FLAG_VALUE_INVALID: + ret = false; + break; + + default: + ret = false; + break; + } + + return ret; +} +EXPORT_SYMBOL(meson_secure_enabled); + +uint32_t meson_secure_reg_read(uint32_t addr) +{ + uint32_t ret; + uint32_t paddr; + int offset; + + offset = 0;//IO_SECBUS_PHY_BASE - IO_SECBUS_BASE; + paddr = addr + offset; + ret = meson_smc2(paddr); + TZDBG("end call smc2, read [0x%x]=%x\n", paddr, ret); + + return ret; +} + +uint32_t meson_secure_reg_write(uint32_t addr, uint32_t val) +{ + uint32_t ret; + uint32_t paddr; + int offset; + + offset = 0;//IO_SECBUS_PHY_BASE - IO_SECBUS_BASE; + paddr = addr + offset; + ret = meson_smc3(paddr, val); + TZDBG("end call smc3, write [0x%x 0x%x]=%x\n", paddr, val, ret); + + return ret; +} + +uint32_t meson_secure_mem_base_start(void) +{ + return meson_smc1(TRUSTZONE_MON_MEM_BASE, 0); +} + +uint32_t meson_secure_mem_total_size(void) +{ + return meson_smc1(TRUSTZONE_MON_MEM_TOTAL_SIZE, 0); +} + +uint32_t meson_secure_mem_flash_start(void) +{ + return meson_smc1(TRUSTZONE_MON_MEM_FLASH, 0); +} + +uint32_t meson_secure_mem_flash_size(void) +{ + return meson_smc1(TRUSTZONE_MON_MEM_FLASH_SIZE, 0); +} + +int32_t meson_secure_mem_ge2d_access(uint32_t msec) +{ + int ret = -1; + + set_cpus_allowed_ptr(current, cpumask_of(0)); + ret = meson_smc_hal_api(TRUSTZONE_HAL_API_MEMCONFIG_GE2D, msec); + set_cpus_allowed_ptr(current, cpu_all_mask); + + return ret; +} +EXPORT_SYMBOL(meson_secure_jtag_disable); + +uint32_t meson_secure_jtag_disable(void) +{ + return meson_smc1(TRUSTZONE_MON_JTAG_DISABLE, 0); +} + +uint32_t meson_secure_jtag_apao(void) +{ + return meson_smc1(TRUSTZONE_MON_JTAG_APAO, 0); +} +EXPORT_SYMBOL(meson_secure_jtag_apao); + +uint32_t meson_secure_jtag_apee(void) +{ + return meson_smc1(TRUSTZONE_MON_JTAG_APEE, 0); +} +EXPORT_SYMBOL(meson_secure_jtag_apee); + +int meson_trustzone_efuse(void *arg) +{ + int ret; + + if (!arg) + return -1; + + set_cpus_allowed_ptr(current, cpumask_of(0)); + + ret = meson_smc_hal_api(TRUSTZONE_HAL_API_EFUSE, __pa(arg)); + + set_cpus_allowed_ptr(current, cpu_all_mask); + + return ret; +} +EXPORT_SYMBOL(meson_trustzone_efuse); diff --git a/arch/arm/mach-meson/meson-smc.S b/arch/arm/mach-meson/meson-smc.S new file mode 100644 index 0000000..bc5d54e --- /dev/null +++ b/arch/arm/mach-meson/meson-smc.S @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2014-2017 Amlogic, Inc. All rights reserved. + * + * All information contained herein is Amlogic confidential. + * + * This software is provided to you pursuant to Software License Agreement + * (SLA) with Amlogic Inc ("Amlogic"). This software may be used + * only in accordance with the terms of this agreement. + * + * Redistribution and use in source and binary forms, with or without + * modification is strictly prohibited without prior written permission from + * Amlogic. + * + * 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 + * OWNER 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 +#include + +.arch_extension sec + +ENTRY(meson_smc1) + stmfd sp!, {r2-r12, lr} + mov r2, r1 + mov r1, r0 + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_smc1) + +ENTRY(meson_smc_hal_api) + stmfd sp!, {r3-r12, lr} + mov r2, r1 + mov r1, r0 + ldr r0, =CALL_TRUSTZONE_HAL_API + dsb + smc #0 + ldmfd sp!, {r3-r12, pc} +ENDPROC(meson_smc_hal_api) + +ENTRY(meson_smc2) + stmfd sp!, {r2-r12, lr} + mov r1, r0 + ldr r0, =0x2 + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_smc2) + +ENTRY(meson_smc3) + stmfd sp!, {r2-r12, lr} + mov r2, r1 + mov r1, r0 + ldr r0, =0x3 + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_smc3) + +ENTRY(meson_read_corectrl) + stmfd sp!, {r2-r12, lr} + ldr r1, =TRUSTZONE_MON_CORE_RD_CTRL_INDEX + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_read_corectrl) + +ENTRY(meson_modify_corectrl) + stmfd sp!, {r2-r12, lr} + mov r2, r0 + ldr r1, =TRUSTZONE_MON_CORE_WR_CTRL_INDEX + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_modify_corectrl) + +ENTRY(meson_read_corestatus) + stmfd sp!, {r2-r12, lr} + ldr r1, =TRUSTZONE_MON_CORE_RD_STATUS0_INDEX + add r1, r1, r0, lsl #1 + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_read_corestatus) + +ENTRY(meson_modify_corestatus) + stmfd sp!, {r2-r12, lr} + mov r2, r1 + ldr r1, =TRUSTZONE_MON_CORE_WR_STATUS0_INDEX + add r1, r1, r0, lsl #1 + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_modify_corestatus) + +ENTRY(meson_auxcoreboot_addr) + stmfd sp!, {r2-r12, lr} + mov r3, r1 + mov r2, r0 + ldr r1, =TRUSTZONE_MON_CORE_BOOTADDR_INDEX + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_auxcoreboot_addr) + +ENTRY(meson_suspend_firmware) + stmfd sp!, {r2-r12, lr} + mov r2, r0 + ldr r1, =TRUSTZONE_MON_SUSPNED_FIRMWARE + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_suspend_firmware) + +ENTRY(meson_read_socrev1) + stmfd sp!, {r2-r12, lr} + ldr r1, =TRUSTZONE_MON_CORE_RD_SOC_REV1 + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_read_socrev1) + +ENTRY(meson_read_socrev2) + stmfd sp!, {r2-r12, lr} + ldr r1, =TRUSTZONE_MON_CORE_RD_SOC_REV2 + ldr r0, =CALL_TRUSTZONE_MON + dsb + smc #0 + ldmfd sp!, {r2-r12, pc} +ENDPROC(meson_read_socrev2) diff --git a/arch/arm/mach-meson/meson.c b/arch/arm/mach-meson/meson.c index 1778a18..ab814ed 100644 --- a/arch/arm/mach-meson/meson.c +++ b/arch/arm/mach-meson/meson.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include static const char * const meson_common_board_compat[] = { "amlogic,meson6", @@ -46,10 +48,61 @@ static void __init meson_map_io(void) } #endif +static void meson_l2c310_write_sec(unsigned long val, unsigned int reg) +{ +#define MESON_L2C310_BASE_REG 0xc4200000 + static void __iomem *l2x0_base; + + if (!meson_secure_enabled()) { + if (!l2x0_base) + l2x0_base = ioremap(MESON_L2C310_BASE_REG, 0x1000); + + if (l2x0_base) + writel_relaxed(val, (l2x0_base + reg)); + + return; + } + + switch (reg) { + case L2X0_CTRL: + meson_smc1(TRUSTZONE_MON_L2X0_CTRL_INDEX, val); + break; + case L2X0_AUX_CTRL: + meson_smc1(TRUSTZONE_MON_L2X0_AUXCTRL_INDEX, val); + break; + case L2X0_DEBUG_CTRL: + meson_smc1(TRUSTZONE_MON_L2X0_DEBUG_INDEX, val); + break; + case L310_TAG_LATENCY_CTRL: + meson_smc1(TRUSTZONE_MON_L2X0_TAGLATENCY_INDEX, val); + break; + case L310_DATA_LATENCY_CTRL: + meson_smc1(TRUSTZONE_MON_L2X0_DATALATENCY_INDEX, val); + break; + case L310_ADDR_FILTER_START: + meson_smc1(TRUSTZONE_MON_L2X0_FILTERSTART_INDEX, val); + break; + case L310_ADDR_FILTER_END: + meson_smc1(TRUSTZONE_MON_L2X0_FILTEREND_INDEX, val); + break; + case L310_PREFETCH_CTRL: + meson_smc1(TRUSTZONE_MON_L2X0_PREFETCH_INDEX, val); + break; + case L310_POWER_CTRL: + meson_smc1(TRUSTZONE_MON_L2X0_POWER_INDEX, val); + break; + + default: + WARN_ONCE(1, "Meson L2C310: ignoring write to reg 0x%x\n", reg); + break; + } +} + DT_MACHINE_START(MESON, "Amlogic Meson platform") .dt_compat = meson_common_board_compat, .l2c_aux_val = 0, .l2c_aux_mask = ~0, + .l2c_write_sec = meson_l2c310_write_sec, #ifdef CONFIG_AMLOGIC_M8B_SUSPEND .map_io = meson_map_io, #endif diff --git a/arch/arm/mach-meson/platsmp.c b/arch/arm/mach-meson/platsmp.c index ee6e112..554b295 100644 --- a/arch/arm/mach-meson/platsmp.c +++ b/arch/arm/mach-meson/platsmp.c @@ -33,6 +33,7 @@ #include #include #include +#include static DEFINE_SPINLOCK(boot_lock); static DEFINE_SPINLOCK(clockfw_lock); @@ -47,42 +48,39 @@ void meson_set_cpu_ctrl_addr(uint32_t cpu, const uint32_t addr) { spin_lock(&clockfw_lock); -#ifdef CONFIG_MESON_TRUSTZONE - meson_auxcoreboot_addr(cpu, addr); -#else - writel(addr, (void *)(CPU1_CONTROL_ADDR_REG + ((cpu-1) << 2))); -#endif + if (meson_secure_enabled()) + meson_auxcoreboot_addr(cpu, addr); + else + writel(addr, (void *)(CPU1_CONTROL_ADDR_REG + ((cpu-1) << 2))); + spin_unlock(&clockfw_lock); } void meson_set_cpu_ctrl_reg(int cpu, int is_on) { -#ifdef CONFIG_MESON_TRUSTZONE uint32_t value = 0; -#endif + spin_lock(&clockfw_lock); -#ifdef CONFIG_MESON_TRUSTZONE - value = meson_read_corectrl(); - value = (value & ~(1U << cpu)) | (is_on << cpu); - value |= 1; - meson_modify_corectrl(value); -#else - aml_set_reg32_bits(CPU_CONTROL_REG, is_on, cpu, 1); - aml_set_reg32_bits(CPU_CONTROL_REG, 1, 0, 1); -#endif + if (meson_secure_enabled()) { + value = meson_read_corectrl(); + value = (value & ~(1U << cpu)) | (is_on << cpu); + value |= 1; + meson_modify_corectrl(value); + } else { + aml_set_reg32_bits(CPU_CONTROL_REG, is_on, cpu, 1); + aml_set_reg32_bits(CPU_CONTROL_REG, 1, 0, 1); + } spin_unlock(&clockfw_lock); } int meson_get_cpu_ctrl_addr(int cpu) { -#ifdef CONFIG_MESON_TRUSTZONE - return 0; -#else - return readl((void *)(CPU1_CONTROL_ADDR_REG + ((cpu-1) << 2))); -#endif - + if (meson_secure_enabled()) + return 0; + else + return readl((void *)(CPU1_CONTROL_ADDR_REG + ((cpu-1) << 2))); } void meson_set_cpu_power_ctrl(uint32_t cpu, int is_power_on) @@ -200,17 +198,17 @@ static int meson_boot_secondary(unsigned int cpu, struct task_struct *idle) */ write_pen_release(cpu_logical_map(cpu)); -#ifndef CONFIG_MESON_TRUSTZONE - meson_set_cpu_ctrl_addr(cpu, - (const uint32_t)virt_to_phys(meson_secondary_startup)); - meson_set_cpu_power_ctrl(cpu, 1); - timeout = jiffies + (10 * HZ); + if (!meson_secure_enabled()) { + meson_set_cpu_ctrl_addr(cpu, + (const uint32_t)virt_to_phys(meson_secondary_startup)); + meson_set_cpu_power_ctrl(cpu, 1); + timeout = jiffies + (10 * HZ); - while (meson_get_cpu_ctrl_addr(cpu)) - ; - if (!time_before(jiffies, timeout)) - return -EPERM; -#endif + while (meson_get_cpu_ctrl_addr(cpu)) + ; + if (!time_before(jiffies, timeout)) + return -EPERM; + } meson_secondary_set(cpu); dsb_sev(); diff --git a/drivers/amlogic/cpu_version/meson32_cpu.c b/drivers/amlogic/cpu_version/meson32_cpu.c index ac567cc..6b4918b 100644 --- a/drivers/amlogic/cpu_version/meson32_cpu.c +++ b/drivers/amlogic/cpu_version/meson32_cpu.c @@ -24,10 +24,7 @@ #include #include #include - -#ifdef CONFIG_MESON_TRUSTZONE -#include -#endif +#include #define IO_REGS_BASE 0xFE000000 #define IO_BOOTROM_BASE (IO_REGS_BASE + 0x010000) /*64K*/ @@ -40,9 +37,7 @@ int __init meson_cpu_version_init(void) void __iomem *assist_hw_rev0; void __iomem *assist_hw_rev1; void __iomem *assist_hw_rev2; -#ifndef CONFIG_MESON_TRUSTZONE unsigned int *version_map; -#endif cpu_version = of_find_node_by_name(NULL, "cpu_version"); if (!cpu_version) { @@ -62,12 +57,13 @@ int __init meson_cpu_version_init(void) meson_cpu_version[MESON_CPU_VERSION_LVL_MAJOR] = readl(assist_hw_rev0); -#ifndef CONFIG_MESON_TRUSTZONE - version_map = (unsigned int *)assist_hw_rev2; - meson_cpu_version[MESON_CPU_VERSION_LVL_MISC] = version_map[1]; -#else - meson_cpu_version[MESON_CPU_VERSION_LVL_MISC] = meson_read_socrev1(); -#endif + if (meson_secure_enabled()) { + meson_cpu_version[MESON_CPU_VERSION_LVL_MISC] = + meson_read_socrev1(); + } else { + version_map = (unsigned int *)assist_hw_rev2; + meson_cpu_version[MESON_CPU_VERSION_LVL_MISC] = version_map[1]; + } version = readl(assist_hw_rev1); switch (version) { diff --git a/drivers/amlogic/efuse/efuse_hw.c b/drivers/amlogic/efuse/efuse_hw.c index 6e5884be..8d11fb0 100644 --- a/drivers/amlogic/efuse/efuse_hw.c +++ b/drivers/amlogic/efuse/efuse_hw.c @@ -30,9 +30,12 @@ #ifndef CONFIG_ARM64 #include #endif +#include #include #include "efuse_regs.h" #include "efuse.h" + + int efuse_active_version = -1; #ifdef EFUSE_DEBUG @@ -51,22 +54,6 @@ static void __efuse_read_dword_debug(unsigned long addr, unsigned long *data) } #endif -/* to do meson_efuse_fn_smc */ - -int meson_trustzone_efuse(struct efuse_hal_api_arg *arg) -{ - int ret; - - if (!arg) - return -1; - - set_cpus_allowed_ptr(current, cpumask_of(0)); - //ret = meson_efuse_fn_smc(arg); - set_cpus_allowed_ptr(current, cpu_all_mask); - return ret; -} - -#ifndef CONFIG_MESON_TRUSTZONE #ifndef EFUSE_DEBUG static void __efuse_write_byte(unsigned long addr, unsigned long data) { @@ -122,8 +109,10 @@ static void __efuse_write_byte(unsigned long addr, unsigned long data) * then disable it upon exit */ if (auto_wr_is_enabled == 0) { - aml_set_reg32_bits(P_EFUSE_CNTL1, CNTL1_AUTO_WR_ENABLE_OFF, - CNTL1_AUTO_WR_ENABLE_BIT, CNTL1_AUTO_WR_ENABLE_SIZE); + aml_set_reg32_bits(P_EFUSE_CNTL1, + CNTL1_AUTO_WR_ENABLE_OFF, + CNTL1_AUTO_WR_ENABLE_BIT, + CNTL1_AUTO_WR_ENABLE_SIZE); } //set efuse PD=1 @@ -188,22 +177,20 @@ static void __efuse_read_dword(unsigned long addr, unsigned long *data) pr_debug("__efuse_read_dword: addr=%ld, data=0x%lx\n", addr, *data); } #endif -#endif + static ssize_t __efuse_read(char *buf, size_t count, loff_t *ppos) { unsigned long *contents = kzalloc(sizeof(unsigned long)*EFUSE_DWORDS, GFP_KERNEL); unsigned int pos = *ppos; -#ifndef CONFIG_MESON_TRUSTZONE unsigned long *pdw; char *tmp_p; /*pos may not align to 4*/ unsigned int dwsize = (count + 3 + pos%4) >> 2; -#else struct efuse_hal_api_arg arg; unsigned long retcnt; int ret; -#endif + if (!contents) { pr_info("memory not enough\n"); return -ENOMEM; @@ -217,66 +204,65 @@ static ssize_t __efuse_read(char *buf, size_t count, loff_t *ppos) if (count > EFUSE_BYTES) return -EFAULT; -#ifndef CONFIG_MESON_TRUSTZONE - clk_prepare_enable(efuse_clk); - aml_set_reg32_bits(P_EFUSE_CNTL1, CNTL1_AUTO_RD_ENABLE_ON, - CNTL1_AUTO_RD_ENABLE_BIT, CNTL1_AUTO_RD_ENABLE_SIZE); + if (!meson_secure_enabled()) { + clk_prepare_enable(efuse_clk); + aml_set_reg32_bits(P_EFUSE_CNTL1, CNTL1_AUTO_RD_ENABLE_ON, + CNTL1_AUTO_RD_ENABLE_BIT, CNTL1_AUTO_RD_ENABLE_SIZE); - for (pdw = contents + pos/4; - dwsize-- > 0 && pos < EFUSE_BYTES; - pos += 4, ++pdw) { - #ifdef EFUSE_DEBUG - __efuse_read_dword_debug(pos, pdw); - #else - /* if pos does not align to 4, __efuse_read_dword - * read from next dword, so, discount this un-aligned - * partition - */ - __efuse_read_dword((pos - pos%4), pdw); - #endif - } + for (pdw = contents + pos/4; + dwsize-- > 0 && pos < EFUSE_BYTES; + pos += 4, ++pdw) { + #ifdef EFUSE_DEBUG + __efuse_read_dword_debug(pos, pdw); + #else + /* if pos does not align to 4, __efuse_read_dword + * read from next dword, so, discount this un-aligned + * partition + */ + __efuse_read_dword((pos - pos%4), pdw); + #endif + } - aml_set_reg32_bits(P_EFUSE_CNTL1, CNTL1_AUTO_RD_ENABLE_OFF, - CNTL1_AUTO_RD_ENABLE_BIT, CNTL1_AUTO_RD_ENABLE_SIZE); + aml_set_reg32_bits(P_EFUSE_CNTL1, + CNTL1_AUTO_RD_ENABLE_OFF, + CNTL1_AUTO_RD_ENABLE_BIT, + CNTL1_AUTO_RD_ENABLE_SIZE); - clk_disable_unprepare(efuse_clk); - tmp_p = (char *)contents; - tmp_p += *ppos; - - memcpy(buf, tmp_p, count); - - *ppos += count; -#else - arg.cmd = EFUSE_HAL_API_READ; - arg.offset = pos; - arg.size = count; - arg.buffer = (unsigned long)contents; - arg.retcnt = (unsigned long)(&retcnt); - ret = meson_trustzone_efuse(&arg); - - if (ret == 0) { - count = retcnt; - *ppos += retcnt; - memcpy(buf, contents, retcnt); - } else - count = 0; -#endif /* CONFIG_MESON_TRUSTZONE */ + clk_disable_unprepare(efuse_clk); + tmp_p = (char *)contents; + tmp_p += *ppos; + + memcpy(buf, tmp_p, count); + + *ppos += count; + } else { + arg.cmd = EFUSE_HAL_API_READ; + arg.offset = pos; + arg.size = count; + arg.buffer = virt_to_phys(contents); + arg.retcnt = virt_to_phys(&retcnt); + ret = meson_trustzone_efuse((void *)&arg); + if (ret == 0) { + count = retcnt; + *ppos += retcnt; + memcpy(buf, contents, retcnt); + } else + count = 0; + } /*if (contents)*/ kfree(contents); + return count; } static ssize_t __efuse_write(const char *buf, size_t count, loff_t *ppos) { unsigned int pos = *ppos; -#ifndef CONFIG_MESON_TRUSTZONE unsigned char *pc; -#else struct efuse_hal_api_arg arg; unsigned int retcnt; int ret; -#endif if (pos >= EFUSE_BYTES) return 0; /* Past EOF */ @@ -285,29 +271,31 @@ static ssize_t __efuse_write(const char *buf, size_t count, loff_t *ppos) if (count > EFUSE_BYTES) return -EFAULT; -#ifndef CONFIG_MESON_TRUSTZONE - for (pc = (char *)buf; count--; ++pos, ++pc) - #ifdef EFUSE_DEBUG - __efuse_write_byte_debug(pos, *pc); - #else - __efuse_write_byte(pos, *pc); - #endif - - *ppos = pos; - return (const char *)pc - buf; -#else - arg.cmd = EFUSE_HAL_API_WRITE; - arg.offset = pos; - arg.size = count; - arg.buffer = (unsigned long)buf; - arg.retcnt = (unsigned long)(&retcnt); - ret = meson_trustzone_efuse(&arg); - if (ret == 0) { - *ppos = pos+retcnt; - return retcnt; - } else - return 0; -#endif + if (!meson_secure_enabled()) { + for (pc = (char *)buf; count--; ++pos, ++pc) + #ifdef EFUSE_DEBUG + __efuse_write_byte_debug(pos, *pc); + #else + __efuse_write_byte(pos, *pc); + #endif + + *ppos = pos; + ret = (const char *)pc - buf; + } else { + arg.cmd = EFUSE_HAL_API_WRITE; + arg.offset = pos; + arg.size = count; + arg.buffer = virt_to_phys(buf); + arg.retcnt = virt_to_phys(&retcnt); + ret = meson_trustzone_efuse((void *)&arg); + if (ret == 0) { + *ppos = pos+retcnt; + ret = retcnt; + } else + ret = 0; + } + + return ret; } ssize_t aml__efuse_read(char *buf, size_t count, loff_t *ppos) diff --git a/drivers/amlogic/jtag/meson_jtag.c b/drivers/amlogic/jtag/meson_jtag.c index 8817fc4..4e8b4cb 100644 --- a/drivers/amlogic/jtag/meson_jtag.c +++ b/drivers/amlogic/jtag/meson_jtag.c @@ -41,6 +41,9 @@ #include #include +#ifdef CONFIG_MACH_MESON8B +#include +#endif #include "meson_jtag.h" @@ -266,7 +269,34 @@ static int aml_jtag_apee_free_gpios(struct platform_device *pdev) #ifdef CONFIG_MACH_MESON8B -static int aml_jtag_select(struct platform_device *pdev) +static int aml_jtag_select_tee(struct platform_device *pdev) +{ + struct aml_jtag_dev *jdev = platform_get_drvdata(pdev); + uint32_t select = jdev->select; + + pr_info("set state %u\n", select); + set_cpus_allowed_ptr(current, cpumask_of(0)); + switch (select) { + case AMLOGIC_JTAG_DISABLE: + meson_secure_jtag_disable(); + break; + case AMLOGIC_JTAG_APAO: + meson_secure_jtag_apao(); + break; + case AMLOGIC_JTAG_APEE: + meson_secure_jtag_apao(); + break; + + default: + writel_relaxed(0x0, jdev->base); + break; + } + set_cpus_allowed_ptr(current, cpu_all_mask); + + return 0; +} + +static int aml_jtag_select_ree(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -304,6 +334,16 @@ static int aml_jtag_select(struct platform_device *pdev) return 0; } +static int aml_jtag_select(struct platform_device *pdev) +{ + if (meson_secure_enabled()) + aml_jtag_select_tee(pdev); + else + aml_jtag_select_ree(pdev); + + return 0; +} + #else static unsigned long __invoke_psci_fn_smc(unsigned long function_id, @@ -616,4 +656,3 @@ module_exit(aml_jtag_exit); MODULE_DESCRIPTION("Meson JTAG Driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Amlogic, Inc."); - diff --git a/include/linux/amlogic/meson-secure.h b/include/linux/amlogic/meson-secure.h new file mode 100644 index 0000000..1b38da0 --- /dev/null +++ b/include/linux/amlogic/meson-secure.h @@ -0,0 +1,112 @@ +/* + * include/linux/amlogic/meson-secure.h + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _MESON_SECURE_H_ +#define _MESON_SECURE_H_ + +/* Meson Secure Monitor/HAL APIs */ +#define CALL_TRUSTZONE_API 0x1 +#define CALL_TRUSTZONE_MON 0x4 +#define CALL_TRUSTZONE_HAL_API 0x5 + +/* Secure Monitor mode APIs */ +#define TRUSTZONE_MON_TYPE_MASK 0xF00 +#define TRUSTZONE_MON_FUNC_MASK 0x0FF +#define TRUSTZONE_MON_L2X0 0x100 +#define TRUSTZONE_MON_L2X0_CTRL_INDEX 0x101 +#define TRUSTZONE_MON_L2X0_AUXCTRL_INDEX 0x102 +#define TRUSTZONE_MON_L2X0_PREFETCH_INDEX 0x103 +#define TRUSTZONE_MON_L2X0_TAGLATENCY_INDEX 0x104 +#define TRUSTZONE_MON_L2X0_DATALATENCY_INDEX 0x105 +#define TRUSTZONE_MON_L2X0_FILTERSTART_INDEX 0x106 +#define TRUSTZONE_MON_L2X0_FILTEREND_INDEX 0x107 +#define TRUSTZONE_MON_L2X0_DEBUG_INDEX 0x108 +#define TRUSTZONE_MON_L2X0_POWER_INDEX 0x109 + +#define TRUSTZONE_MON_CORE 0x200 +#define TRUSTZONE_MON_CORE_RD_CTRL_INDEX 0x201 +#define TRUSTZONE_MON_CORE_WR_CTRL_INDEX 0x202 +#define TRUSTZONE_MON_CORE_RD_STATUS0_INDEX 0x203 +#define TRUSTZONE_MON_CORE_WR_STATUS0_INDEX 0x204 +#define TRUSTZONE_MON_CORE_RD_STATUS1_INDEX 0x205 +#define TRUSTZONE_MON_CORE_WR_STATUS1_INDEX 0x206 +#define TRUSTZONE_MON_CORE_BOOTADDR_INDEX 0x207 +#define TRUSTZONE_MON_CORE_DDR_INDEX 0x208 +#define TRUSTZONE_MON_CORE_RD_SOC_REV1 0x209 +#define TRUSTZONE_MON_CORE_RD_SOC_REV2 0x20A +#define TRUSTZONE_MON_CORE_OFF 0x20B + +#define TRUSTZONE_MON_SUSPNED_FIRMWARE 0x300 +#define TRUSTZONE_MON_SAVE_CPU_GIC 0x400 + +#define TRUSTZONE_MON_RTC 0x500 +#define TRUSTZONE_MON_RTC_RD_REG_INDEX 0x501 +#define TRUSTZONE_MON_RTC_WR_REG_INDEX 0x502 + +#define TRUSTZONE_MON_REG 0x600 +#define TRUSTZONE_MON_REG_RD_INDEX 0x601 +#define TRUSTZONE_MON_REG_WR_INDEX 0x602 + +#define TRUSTZONE_MON_MEM 0x700 +#define TRUSTZONE_MON_MEM_BASE 0x701 +#define TRUSTZONE_MON_MEM_TOTAL_SIZE 0x702 +#define TRUSTZONE_MON_MEM_FLASH 0x703 +#define TRUSTZONE_MON_MEM_FLASH_SIZE 0x704 +#define TRUSTZONE_MON_MEM_GE2D 0x705 + +#define TRUSTZONE_MON_JTAG 0x800 +#define TRUSTZONE_MON_JTAG_DISABLE 0x801 +#define TRUSTZONE_MON_JTAG_APAO 0x802 +#define TRUSTZONE_MON_JTAG_APEE 0x803 + +/* Secure HAL APIs*/ +#define TRUSTZONE_HAL_API_EFUSE 0x100 +#define TRUSTZONE_HAL_API_STORAGE 0x200 +#define TRUSTZONE_HAL_API_MEMCONFIG 0x300 +#define TRUSTZONE_HAL_API_MEMCONFIG_GE2D 0x301 + +#ifndef __ASSEMBLER__ +extern int meson_smc1(uint32_t fn, uint32_t arg); +extern int meson_smc_hal_api(uint32_t cmdidx, uint32_t arg); +extern int meson_smc2(uint32_t arg); +extern int meson_smc3(uint32_t arg1, uint32_t arg2); +extern bool meson_secure_enabled(void); +extern uint32_t meson_read_corectrl(void); +extern uint32_t meson_modify_corectrl(uint32_t arg); +extern uint32_t meson_read_corestatus(uint32_t cpu); +extern uint32_t meson_modify_corestatus(uint32_t cpu, uint32_t arg); +extern void meson_auxcoreboot_addr(uint32_t cpu, uint32_t arg); +extern void meson_suspend_firmware(void); +extern uint32_t meson_secure_reg_read(uint32_t addr); +extern uint32_t meson_secure_reg_write(uint32_t addr, uint32_t val); +extern uint32_t meson_read_socrev1(void); +extern uint32_t meson_read_socrev2(void); +extern uint32_t meson_secure_mem_base_start(void); +extern uint32_t meson_secure_mem_total_size(void); +extern uint32_t meson_secure_mem_flash_start(void); +extern uint32_t meson_secure_mem_flash_size(void); +extern int32_t meson_secure_mem_ge2d_access(uint32_t msec); + +extern uint32_t meson_secure_jtag_disable(void); +extern uint32_t meson_secure_jtag_apao(void); +extern uint32_t meson_secure_jtag_apee(void); + +extern int meson_trustzone_efuse(void *arg); + +#endif /* __ASSEMBLER__ */ + +#endif /* _MESON_SECURE_H_ */ -- 2.7.4