1
0
Fork 0

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>
hifive-unleashed-5.1
Olof Johansson 2013-12-26 11:00:13 -08:00
commit 51b052b0d3
13 changed files with 239 additions and 11 deletions

View File

@ -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>;
};
};

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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();