ARM: tegra: Trusted Foundations firmware support
Add support for the Trusted Foundations secure-mode firmware, as found on NVIDIA SHIELD. This allows Linux to run in non-secure mode on this board; all previous Tegra support has assumed the kernel is running in secure mode. This branch is based on v3.13-rc1, and shouldn't cause any merge conflicts. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJSr3NgAAoJEMzrak5tbycxRXkP/imK6IQn5cAtXY7nfKnn4Rke RjvERwURDpi6QDrXaRe6NUVg3PgZ0Z7kXLqSuj/cAPinMyhQDR5DxlJVjYiduJ50 CmMhV+RWkA/cmaU2oPjpD3YEm68txYXTyf3iWfX1ScFSuNNN0yGel3eY2rFjX/aT RgAWm8HbQTR7NDazAAt9gOqeJUtfs3msXwMxtZvD6OhRougyaPlqfuafjVpfM9vK JLDAbJuMEl6/dI2UYVvDBJvL//TOOjnwy6YFwQCZsqhYGHhT3Xc9hQABilUQmJ1d mbu29cPBrRgGiu3anpjZeh0KxVB3xDPp1a+o4lSH0iJztAPy4WTUZ1Sc3y2qwKaS qZ5Zu5SXVI1O/ywv1FChL2syuJbgOH+HGBMFslacVniQ/U1o4PmKZCJOB0pnpf8B dESAQgvDqIZeyt2eXxsAMAOw01xMTotngAaJpAtYFv0plP+PxAhr+dkHHjCwwkde 7+OKeVE5TDDwlhz5PE35/4EWdWM0622aL3sK1IxrR2q66LGpKAoQpFeKaAUr0d6z OQnQiS+uNSNrCvAEeyEL2bQfv1xsjOFpFy6PV7ShrUrAgPVR3+wj82RvwTciMdbd tv3Y7LXCugSUOdq/abc3VgAnlgMzlhH5vlj6CMcKSSPbzZ3lbRB37iBmxpJLm9qa o3Ah/MaWSqtqmIueFrpa =c5t/ -----END PGP SIGNATURE----- Merge tag 'tegra-for-3.14-trusted-foundations' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers From Stephen Warren: ARM: tegra: Trusted Foundations firmware support Add support for the Trusted Foundations secure-mode firmware, as found on NVIDIA SHIELD. This allows Linux to run in non-secure mode on this board; all previous Tegra support has assumed the kernel is running in secure mode. (The base TF support has been discussed back and forth a lot; for now the most logical place for it seems to be under arch/arm, so we're adding it here. We can move it out to a common location in the future if needed). * tag 'tegra-for-3.14-trusted-foundations' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: ARM: tegra: support Trusted Foundations by default ARM: tegra: set CPU reset handler using firmware ARM: tegra: split setting of CPU reset handler ARM: tegra: add support for Trusted Foundations of: add Trusted Foundations bindings documentation of: add vendor prefix for Trusted Logic Mobility ARM: add basic support for Trusted Foundations Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Коммит
51b052b0d3
|
@ -0,0 +1,20 @@
|
|||
Trusted Foundations
|
||||
-------------------
|
||||
|
||||
Boards that use the Trusted Foundations secure monitor can signal its
|
||||
presence by declaring a node compatible with "tlm,trusted-foundations"
|
||||
under the /firmware/ node
|
||||
|
||||
Required properties:
|
||||
- compatible: "tlm,trusted-foundations"
|
||||
- tlm,version-major: major version number of Trusted Foundations firmware
|
||||
- tlm,version-minor: minor version number of Trusted Foundations firmware
|
||||
|
||||
Example:
|
||||
firmware {
|
||||
trusted-foundations {
|
||||
compatible = "tlm,trusted-foundations";
|
||||
tlm,version-major = <2>;
|
||||
tlm,version-minor = <8>;
|
||||
};
|
||||
};
|
|
@ -32,3 +32,8 @@ board-specific compatible values:
|
|||
nvidia,whistler
|
||||
toradex,colibri_t20-512
|
||||
toradex,iris
|
||||
|
||||
Trusted Foundations
|
||||
-------------------------------------------
|
||||
Tegra supports the Trusted Foundation secure monitor. See the
|
||||
"tlm,trusted-foundations" binding's documentation for more details.
|
||||
|
|
|
@ -71,6 +71,7 @@ st STMicroelectronics
|
|||
ste ST-Ericsson
|
||||
stericsson ST-Ericsson
|
||||
ti Texas Instruments
|
||||
tlm Trusted Logic Mobility
|
||||
toshiba Toshiba Corporation
|
||||
toumaz Toumaz
|
||||
v3 V3 Semiconductor
|
||||
|
|
|
@ -1054,6 +1054,8 @@ config ARM_TIMER_SP804
|
|||
select CLKSRC_MMIO
|
||||
select CLKSRC_OF if OF
|
||||
|
||||
source "arch/arm/firmware/Kconfig"
|
||||
|
||||
source arch/arm/mm/Kconfig
|
||||
|
||||
config ARM_NR_BANKS
|
||||
|
|
|
@ -268,6 +268,7 @@ core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/
|
|||
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
|
||||
core-y += arch/arm/net/
|
||||
core-y += arch/arm/crypto/
|
||||
core-y += arch/arm/firmware/
|
||||
core-y += $(machdirs) $(platdirs)
|
||||
|
||||
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
||||
|
|
|
@ -33,6 +33,7 @@ CONFIG_PCI=y
|
|||
CONFIG_PCI_MSI=y
|
||||
CONFIG_PCI_TEGRA=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_TRUSTED_FOUNDATIONS=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_PREEMPT=y
|
||||
CONFIG_AEABI=y
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
config ARCH_SUPPORTS_FIRMWARE
|
||||
bool
|
||||
|
||||
config ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
|
||||
bool
|
||||
select ARCH_SUPPORTS_FIRMWARE
|
||||
|
||||
menu "Firmware options"
|
||||
depends on ARCH_SUPPORTS_FIRMWARE
|
||||
|
||||
config TRUSTED_FOUNDATIONS
|
||||
bool "Trusted Foundations secure monitor support"
|
||||
depends on ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
|
||||
help
|
||||
Some devices (including most Tegra-based consumer devices on the
|
||||
market) are booted with the Trusted Foundations secure monitor
|
||||
active, requiring some core operations to be performed by the secure
|
||||
monitor instead of the kernel.
|
||||
|
||||
This option allows the kernel to invoke the secure monitor whenever
|
||||
required on devices using Trusted Foundations. See
|
||||
arch/arm/include/asm/trusted_foundations.h or the
|
||||
tl,trusted-foundations device tree binding documentation for details
|
||||
on how to use it.
|
||||
|
||||
Say n if you don't know what this is about.
|
||||
|
||||
endmenu
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Trusted Foundations support for ARM CPUs
|
||||
*
|
||||
* Copyright (c) 2013, NVIDIA Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/trusted_foundations.h>
|
||||
|
||||
#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200
|
||||
|
||||
static void __naked tf_generic_smc(u32 type, u32 arg1, u32 arg2)
|
||||
{
|
||||
asm volatile(
|
||||
".arch_extension sec\n\t"
|
||||
"stmfd sp!, {r4 - r11, lr}\n\t"
|
||||
__asmeq("%0", "r0")
|
||||
__asmeq("%1", "r1")
|
||||
__asmeq("%2", "r2")
|
||||
"mov r3, #0\n\t"
|
||||
"mov r4, #0\n\t"
|
||||
"smc #0\n\t"
|
||||
"ldmfd sp!, {r4 - r11, pc}"
|
||||
:
|
||||
: "r" (type), "r" (arg1), "r" (arg2)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
|
||||
{
|
||||
tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, boot_addr, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct firmware_ops trusted_foundations_ops = {
|
||||
.set_cpu_boot_addr = tf_set_cpu_boot_addr,
|
||||
};
|
||||
|
||||
void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
|
||||
{
|
||||
/*
|
||||
* we are not using version information for now since currently
|
||||
* supported SMCs are compatible with all TF releases
|
||||
*/
|
||||
register_firmware_ops(&trusted_foundations_ops);
|
||||
}
|
||||
|
||||
void of_register_trusted_foundations(void)
|
||||
{
|
||||
struct device_node *node;
|
||||
struct trusted_foundations_platform_data pdata;
|
||||
int err;
|
||||
|
||||
node = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations");
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
err = of_property_read_u32(node, "tlm,version-major",
|
||||
&pdata.version_major);
|
||||
if (err != 0)
|
||||
panic("Trusted Foundation: missing version-major property\n");
|
||||
err = of_property_read_u32(node, "tlm,version-minor",
|
||||
&pdata.version_minor);
|
||||
if (err != 0)
|
||||
panic("Trusted Foundation: missing version-minor property\n");
|
||||
register_trusted_foundations(&pdata);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2013, NVIDIA Corporation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support for the Trusted Foundations secure monitor.
|
||||
*
|
||||
* Trusted Foundation comes active on some ARM consumer devices (most
|
||||
* Tegra-based devices sold on the market are concerned). Such devices can only
|
||||
* perform some basic operations, like setting the CPU reset vector, through
|
||||
* SMC calls to the secure monitor. The calls are completely specific to
|
||||
* Trusted Foundations, and do *not* follow the SMC calling convention or the
|
||||
* PSCI standard.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARM_TRUSTED_FOUNDATIONS_H
|
||||
#define __ASM_ARM_TRUSTED_FOUNDATIONS_H
|
||||
|
||||
#include <linux/kconfig.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
struct trusted_foundations_platform_data {
|
||||
unsigned int version_major;
|
||||
unsigned int version_minor;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_TRUSTED_FOUNDATIONS)
|
||||
|
||||
void register_trusted_foundations(struct trusted_foundations_platform_data *pd);
|
||||
void of_register_trusted_foundations(void);
|
||||
|
||||
#else /* CONFIG_TRUSTED_FOUNDATIONS */
|
||||
|
||||
static inline void register_trusted_foundations(
|
||||
struct trusted_foundations_platform_data *pd)
|
||||
{
|
||||
/*
|
||||
* If we try to register TF, this means the system needs it to continue.
|
||||
* Its absence if thus a fatal error.
|
||||
*/
|
||||
panic("No support for Trusted Foundations, stopping...\n");
|
||||
}
|
||||
|
||||
static inline void of_register_trusted_foundations(void)
|
||||
{
|
||||
/*
|
||||
* If we find the target should enable TF but does not support it,
|
||||
* fail as the system won't be able to do much anyway
|
||||
*/
|
||||
if (of_find_compatible_node(NULL, NULL, "tl,trusted-foundations"))
|
||||
register_trusted_foundations(NULL);
|
||||
}
|
||||
#endif /* CONFIG_TRUSTED_FOUNDATIONS */
|
||||
|
||||
#endif
|
|
@ -2,6 +2,7 @@ config ARCH_TEGRA
|
|||
bool "NVIDIA Tegra" if ARCH_MULTI_V7
|
||||
select ARCH_HAS_CPUFREQ
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
|
||||
select ARM_GIC
|
||||
select CLKSRC_MMIO
|
||||
select CLKSRC_OF
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#include "iomap.h"
|
||||
#include "irammap.h"
|
||||
|
@ -33,26 +34,18 @@
|
|||
|
||||
static bool is_enabled;
|
||||
|
||||
static void __init tegra_cpu_reset_handler_enable(void)
|
||||
static void __init tegra_cpu_reset_handler_set(const u32 reset_address)
|
||||
{
|
||||
void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE);
|
||||
void __iomem *evp_cpu_reset =
|
||||
IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100);
|
||||
void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE);
|
||||
u32 reg;
|
||||
|
||||
BUG_ON(is_enabled);
|
||||
BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE);
|
||||
|
||||
memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start,
|
||||
tegra_cpu_reset_handler_size);
|
||||
|
||||
/*
|
||||
* NOTE: This must be the one and only write to the EVP CPU reset
|
||||
* vector in the entire system.
|
||||
*/
|
||||
writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset,
|
||||
evp_cpu_reset);
|
||||
writel(reset_address, evp_cpu_reset);
|
||||
wmb();
|
||||
reg = readl(evp_cpu_reset);
|
||||
|
||||
|
@ -66,8 +59,33 @@ static void __init tegra_cpu_reset_handler_enable(void)
|
|||
writel(reg, sb_ctrl);
|
||||
wmb();
|
||||
}
|
||||
}
|
||||
|
||||
is_enabled = true;
|
||||
static void __init tegra_cpu_reset_handler_enable(void)
|
||||
{
|
||||
void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE);
|
||||
const u32 reset_address = TEGRA_IRAM_RESET_BASE +
|
||||
tegra_cpu_reset_handler_offset;
|
||||
int err;
|
||||
|
||||
BUG_ON(is_enabled);
|
||||
BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE);
|
||||
|
||||
memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start,
|
||||
tegra_cpu_reset_handler_size);
|
||||
|
||||
err = call_firmware_op(set_cpu_boot_addr, 0, reset_address);
|
||||
switch (err) {
|
||||
case -ENOSYS:
|
||||
tegra_cpu_reset_handler_set(reset_address);
|
||||
/* pass-through */
|
||||
case 0:
|
||||
is_enabled = true;
|
||||
break;
|
||||
default:
|
||||
pr_crit("Cannot set CPU reset handler: %d\n", err);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
void __init tegra_cpu_reset_handler_init(void)
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/trusted_foundations.h>
|
||||
|
||||
#include "apbio.h"
|
||||
#include "board.h"
|
||||
|
@ -90,6 +91,7 @@ static void __init tegra_init_cache(void)
|
|||
|
||||
static void __init tegra_init_early(void)
|
||||
{
|
||||
of_register_trusted_foundations();
|
||||
tegra_apb_io_init();
|
||||
tegra_init_fuse();
|
||||
tegra_cpu_reset_handler_init();
|
||||
|
|
Загрузка…
Ссылка в новой задаче