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
|
nvidia,whistler
|
||||||
toradex,colibri_t20-512
|
toradex,colibri_t20-512
|
||||||
toradex,iris
|
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
|
ste ST-Ericsson
|
||||||
stericsson ST-Ericsson
|
stericsson ST-Ericsson
|
||||||
ti Texas Instruments
|
ti Texas Instruments
|
||||||
|
tlm Trusted Logic Mobility
|
||||||
toshiba Toshiba Corporation
|
toshiba Toshiba Corporation
|
||||||
toumaz Toumaz
|
toumaz Toumaz
|
||||||
v3 V3 Semiconductor
|
v3 V3 Semiconductor
|
||||||
|
|
|
@ -1054,6 +1054,8 @@ config ARM_TIMER_SP804
|
||||||
select CLKSRC_MMIO
|
select CLKSRC_MMIO
|
||||||
select CLKSRC_OF if OF
|
select CLKSRC_OF if OF
|
||||||
|
|
||||||
|
source "arch/arm/firmware/Kconfig"
|
||||||
|
|
||||||
source arch/arm/mm/Kconfig
|
source arch/arm/mm/Kconfig
|
||||||
|
|
||||||
config ARM_NR_BANKS
|
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/kernel/ arch/arm/mm/ arch/arm/common/
|
||||||
core-y += arch/arm/net/
|
core-y += arch/arm/net/
|
||||||
core-y += arch/arm/crypto/
|
core-y += arch/arm/crypto/
|
||||||
|
core-y += arch/arm/firmware/
|
||||||
core-y += $(machdirs) $(platdirs)
|
core-y += $(machdirs) $(platdirs)
|
||||||
|
|
||||||
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
||||||
|
|
|
@ -33,6 +33,7 @@ CONFIG_PCI=y
|
||||||
CONFIG_PCI_MSI=y
|
CONFIG_PCI_MSI=y
|
||||||
CONFIG_PCI_TEGRA=y
|
CONFIG_PCI_TEGRA=y
|
||||||
CONFIG_PCIEPORTBUS=y
|
CONFIG_PCIEPORTBUS=y
|
||||||
|
CONFIG_TRUSTED_FOUNDATIONS=y
|
||||||
CONFIG_SMP=y
|
CONFIG_SMP=y
|
||||||
CONFIG_PREEMPT=y
|
CONFIG_PREEMPT=y
|
||||||
CONFIG_AEABI=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
|
bool "NVIDIA Tegra" if ARCH_MULTI_V7
|
||||||
select ARCH_HAS_CPUFREQ
|
select ARCH_HAS_CPUFREQ
|
||||||
select ARCH_REQUIRE_GPIOLIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
|
select ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
|
||||||
select ARM_GIC
|
select ARM_GIC
|
||||||
select CLKSRC_MMIO
|
select CLKSRC_MMIO
|
||||||
select CLKSRC_OF
|
select CLKSRC_OF
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/hardware/cache-l2x0.h>
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
|
#include <asm/firmware.h>
|
||||||
|
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "irammap.h"
|
#include "irammap.h"
|
||||||
|
@ -33,26 +34,18 @@
|
||||||
|
|
||||||
static bool is_enabled;
|
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 =
|
void __iomem *evp_cpu_reset =
|
||||||
IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100);
|
IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100);
|
||||||
void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE);
|
void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE);
|
||||||
u32 reg;
|
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
|
* NOTE: This must be the one and only write to the EVP CPU reset
|
||||||
* vector in the entire system.
|
* vector in the entire system.
|
||||||
*/
|
*/
|
||||||
writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset,
|
writel(reset_address, evp_cpu_reset);
|
||||||
evp_cpu_reset);
|
|
||||||
wmb();
|
wmb();
|
||||||
reg = readl(evp_cpu_reset);
|
reg = readl(evp_cpu_reset);
|
||||||
|
|
||||||
|
@ -66,8 +59,33 @@ static void __init tegra_cpu_reset_handler_enable(void)
|
||||||
writel(reg, sb_ctrl);
|
writel(reg, sb_ctrl);
|
||||||
wmb();
|
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)
|
void __init tegra_cpu_reset_handler_init(void)
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach/time.h>
|
#include <asm/mach/time.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
#include <asm/trusted_foundations.h>
|
||||||
|
|
||||||
#include "apbio.h"
|
#include "apbio.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
|
@ -90,6 +91,7 @@ static void __init tegra_init_cache(void)
|
||||||
|
|
||||||
static void __init tegra_init_early(void)
|
static void __init tegra_init_early(void)
|
||||||
{
|
{
|
||||||
|
of_register_trusted_foundations();
|
||||||
tegra_apb_io_init();
|
tegra_apb_io_init();
|
||||||
tegra_init_fuse();
|
tegra_init_fuse();
|
||||||
tegra_cpu_reset_handler_init();
|
tegra_cpu_reset_handler_init();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче