mirror of https://gitee.com/openkylin/linux.git
firmware: tegra: Changes for v5.2-rc1
This set of changes includes improvements for Trusted Foundations and also moves the source files for this support into the standard location under drivers/firmware. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAly4jVETHHRyZWRpbmdA bnZpZGlhLmNvbQAKCRDdI6zXfz6zof9FD/wKq7/KMVDgv+Ja+MJz/nT5gqaTA29r d8n9KyrXMvSUJ73/uS9E9Sm97S22n5TaC1LBv3EnKVJMf4rRJRH5GuASSpWo1iJx Cv+WHjSbwGB3Glw76/KI6mq5RBJEU6BOEPUdypXPE2J+w8i0icXoRdNU70GSqjHW Pt3kaA6GKuUv4bnAxb9AZH1DaxuVuzIGs+XqolfGhs6NpNlfkZ63YJ2Ym/iRiWP0 Tqp5srZs57Zn43qgUf6zRKR+WCrsIZb2fiO7itCyIkY2Z5TiF1BXtKZNj+JsdAxI VVp6KNyperD1aU8y6qGUPFOBC/eR6QctKV3P1/06arizwPiaikobwNHnxX12VJMg G4ebPM0rhnxR73u1z/iZSXZub+X1gednSwDlq7qF9IdUDyFvnTAzxIPTBtVj5hxy VGLvJakaaeGLVe0QJqiZPPtssHXkRsp2CxJWSpEAvof6E1yvD040QRqGQdcJMzNJ QKwS2PBZMrXNs3lhd8QNk547uLAQDRv/oqaizM9J91yWDUicO+dWleya3l3kwrGq lEKUWvkUMi5bUT3frW66xRlhnv6yXqTvo9CqshcL59dQ8ZqIrEczxoR2dg7GL1c9 8i5Hqnor0j+9TlZMnw5hsbD8C2kuWI/nnZpfbiRJEMFIYe8lhF6onPMgAuiV3WRw 9EpzLPExTep0jg== =agCA -----END PGP SIGNATURE----- Merge tag 'tegra-for-5.2-firmware' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/soc firmware: tegra: Changes for v5.2-rc1 This set of changes includes improvements for Trusted Foundations and also moves the source files for this support into the standard location under drivers/firmware. * tag 'tegra-for-5.2-firmware' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: firmware: Move Trusted Foundations support ARM: tegra: Sort dependencies alphabetically ARM: tegra: Add firmware calls required for suspend-resume on Tegra30 ARM: tegra: Always boot CPU in ARM-mode ARM: tegra: Don't apply CPU erratas in insecure mode ARM: tegra: Set up L2 cache using Trusted Foundations firmware ARM: trusted_foundations: Provide information about whether firmware is registered ARM: trusted_foundations: Make prepare_idle call to take mode argument ARM: trusted_foundations: Support L2 cache maintenance Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
abfcba1c35
|
@ -900,8 +900,6 @@ config PLAT_PXA
|
||||||
config PLAT_VERSATILE
|
config PLAT_VERSATILE
|
||||||
bool
|
bool
|
||||||
|
|
||||||
source "arch/arm/firmware/Kconfig"
|
|
||||||
|
|
||||||
source "arch/arm/mm/Kconfig"
|
source "arch/arm/mm/Kconfig"
|
||||||
|
|
||||||
config IWMMXT
|
config IWMMXT
|
||||||
|
|
|
@ -290,7 +290,6 @@ core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
|
||||||
core-y += arch/arm/probes/
|
core-y += arch/arm/probes/
|
||||||
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/
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
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
|
|
||||||
default y
|
|
||||||
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
|
|
||||||
tlm,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
|
|
|
@ -1,4 +0,0 @@
|
||||||
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
|
|
||||||
|
|
||||||
# tf_generic_smc() fails to build with -fsanitize-coverage=trace-pc
|
|
||||||
KCOV_INSTRUMENT := n
|
|
|
@ -24,7 +24,7 @@ struct firmware_ops {
|
||||||
/*
|
/*
|
||||||
* Inform the firmware we intend to enter CPU idle mode
|
* Inform the firmware we intend to enter CPU idle mode
|
||||||
*/
|
*/
|
||||||
int (*prepare_idle)(void);
|
int (*prepare_idle)(unsigned long mode);
|
||||||
/*
|
/*
|
||||||
* Enters CPU idle mode
|
* Enters CPU idle mode
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
menuconfig ARCH_TEGRA
|
menuconfig ARCH_TEGRA
|
||||||
bool "NVIDIA Tegra"
|
bool "NVIDIA Tegra"
|
||||||
depends on ARCH_MULTI_V7
|
depends on ARCH_MULTI_V7
|
||||||
select ARCH_SUPPORTS_TRUSTED_FOUNDATIONS
|
select ARCH_HAS_RESET_CONTROLLER
|
||||||
select ARM_AMBA
|
select ARM_AMBA
|
||||||
select ARM_GIC
|
select ARM_GIC
|
||||||
select CLKSRC_MMIO
|
select CLKSRC_MMIO
|
||||||
|
@ -11,7 +11,6 @@ menuconfig ARCH_TEGRA
|
||||||
select HAVE_ARM_TWD if SMP
|
select HAVE_ARM_TWD if SMP
|
||||||
select PINCTRL
|
select PINCTRL
|
||||||
select PM_OPP
|
select PM_OPP
|
||||||
select ARCH_HAS_RESET_CONTROLLER
|
|
||||||
select RESET_CONTROLLER
|
select RESET_CONTROLLER
|
||||||
select SOC_BUS
|
select SOC_BUS
|
||||||
select ZONE_DMA if ARM_LPAE
|
select ZONE_DMA if ARM_LPAE
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
#include <linux/firmware/trusted_foundations.h>
|
||||||
|
|
||||||
#include <asm/cpuidle.h>
|
#include <asm/cpuidle.h>
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
#include <asm/suspend.h>
|
#include <asm/suspend.h>
|
||||||
|
@ -46,7 +48,7 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
|
||||||
tegra_set_cpu_in_lp2();
|
tegra_set_cpu_in_lp2();
|
||||||
cpu_pm_enter();
|
cpu_pm_enter();
|
||||||
|
|
||||||
call_firmware_op(prepare_idle);
|
call_firmware_op(prepare_idle, TF_PM_MODE_LP2_NOFLUSH_L2);
|
||||||
|
|
||||||
/* Do suspend by ourselves if the firmware does not implement it */
|
/* Do suspend by ourselves if the firmware does not implement it */
|
||||||
if (call_firmware_op(do_idle, 0) == -ENOSYS)
|
if (call_firmware_op(do_idle, 0) == -ENOSYS)
|
||||||
|
|
|
@ -27,12 +27,15 @@
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
|
|
||||||
|
#include <linux/firmware/trusted_foundations.h>
|
||||||
|
|
||||||
#include <soc/tegra/flowctrl.h>
|
#include <soc/tegra/flowctrl.h>
|
||||||
#include <soc/tegra/fuse.h>
|
#include <soc/tegra/fuse.h>
|
||||||
#include <soc/tegra/pm.h>
|
#include <soc/tegra/pm.h>
|
||||||
#include <soc/tegra/pmc.h>
|
#include <soc/tegra/pmc.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/firmware.h>
|
||||||
#include <asm/idmap.h>
|
#include <asm/idmap.h>
|
||||||
#include <asm/proc-fns.h>
|
#include <asm/proc-fns.h>
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
|
@ -159,6 +162,28 @@ int tegra_cpu_do_idle(void)
|
||||||
|
|
||||||
static int tegra_sleep_cpu(unsigned long v2p)
|
static int tegra_sleep_cpu(unsigned long v2p)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* L2 cache disabling using kernel API only allowed when all
|
||||||
|
* secondary CPU's are offline. Cache have to be disabled with
|
||||||
|
* MMU-on if cache maintenance is done via Trusted Foundations
|
||||||
|
* firmware. Note that CPUIDLE won't ever enter powergate on Tegra30
|
||||||
|
* if any of secondary CPU's is online and this is the LP2-idle
|
||||||
|
* code-path only for Tegra20/30.
|
||||||
|
*/
|
||||||
|
if (trusted_foundations_registered())
|
||||||
|
outer_disable();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that besides of setting up CPU reset vector this firmware
|
||||||
|
* call may also do the following, depending on the FW version:
|
||||||
|
* 1) Disable L2. But this doesn't matter since we already
|
||||||
|
* disabled the L2.
|
||||||
|
* 2) Disable D-cache. This need to be taken into account in
|
||||||
|
* particular by the tegra_disable_clean_inv_dcache() which
|
||||||
|
* shall avoid the re-disable.
|
||||||
|
*/
|
||||||
|
call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
|
||||||
|
|
||||||
setup_mm_for_reboot();
|
setup_mm_for_reboot();
|
||||||
tegra_sleep_cpu_finish(v2p);
|
tegra_sleep_cpu_finish(v2p);
|
||||||
|
|
||||||
|
@ -197,6 +222,14 @@ void tegra_idle_lp2_last(void)
|
||||||
|
|
||||||
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
|
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resume L2 cache if it wasn't re-enabled early during resume,
|
||||||
|
* which is the case for Tegra30 that has to re-enable the cache
|
||||||
|
* via firmware call. In other cases cache is already enabled and
|
||||||
|
* hence re-enabling is a no-op. This is always a no-op on Tegra114+.
|
||||||
|
*/
|
||||||
|
outer_resume();
|
||||||
|
|
||||||
restore_cpu_complex();
|
restore_cpu_complex();
|
||||||
cpu_cluster_pm_exit();
|
cpu_cluster_pm_exit();
|
||||||
}
|
}
|
||||||
|
@ -215,6 +248,15 @@ enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
|
||||||
|
|
||||||
static int tegra_sleep_core(unsigned long v2p)
|
static int tegra_sleep_core(unsigned long v2p)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Cache have to be disabled with MMU-on if cache maintenance is done
|
||||||
|
* via Trusted Foundations firmware. This is a no-op on Tegra114+.
|
||||||
|
*/
|
||||||
|
if (trusted_foundations_registered())
|
||||||
|
outer_disable();
|
||||||
|
|
||||||
|
call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
|
||||||
|
|
||||||
setup_mm_for_reboot();
|
setup_mm_for_reboot();
|
||||||
tegra_sleep_core_finish(v2p);
|
tegra_sleep_core_finish(v2p);
|
||||||
|
|
||||||
|
@ -342,6 +384,14 @@ static int tegra_suspend_enter(suspend_state_t state)
|
||||||
|
|
||||||
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
|
cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, tegra_sleep_func);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resume L2 cache if it wasn't re-enabled early during resume,
|
||||||
|
* which is the case for Tegra30 that has to re-enable the cache
|
||||||
|
* via firmware call. In other cases cache is already enabled and
|
||||||
|
* hence re-enabling is a no-op.
|
||||||
|
*/
|
||||||
|
outer_resume();
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case TEGRA_SUSPEND_LP1:
|
case TEGRA_SUSPEND_LP1:
|
||||||
tegra_suspend_exit_lp1();
|
tegra_suspend_exit_lp1();
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <soc/tegra/flowctrl.h>
|
#include <soc/tegra/flowctrl.h>
|
||||||
#include <soc/tegra/fuse.h>
|
#include <soc/tegra/fuse.h>
|
||||||
|
|
||||||
|
#include <asm/assembler.h>
|
||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
|
|
||||||
|
@ -29,8 +30,6 @@
|
||||||
|
|
||||||
#define PMC_SCRATCH41 0x140
|
#define PMC_SCRATCH41 0x140
|
||||||
|
|
||||||
#define RESET_DATA(x) ((TEGRA_RESET_##x)*4)
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
/*
|
/*
|
||||||
* tegra_resume
|
* tegra_resume
|
||||||
|
@ -78,6 +77,7 @@ ENTRY(tegra_resume)
|
||||||
orr r1, r1, #1
|
orr r1, r1, #1
|
||||||
str r1, [r0]
|
str r1, [r0]
|
||||||
#endif
|
#endif
|
||||||
|
bl tegra_resume_trusted_foundations
|
||||||
|
|
||||||
#ifdef CONFIG_CACHE_L2X0
|
#ifdef CONFIG_CACHE_L2X0
|
||||||
/* L2 cache resume & re-enable */
|
/* L2 cache resume & re-enable */
|
||||||
|
@ -90,6 +90,30 @@ end_ca9_scu_l2_resume:
|
||||||
|
|
||||||
b cpu_resume
|
b cpu_resume
|
||||||
ENDPROC(tegra_resume)
|
ENDPROC(tegra_resume)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tegra_resume_trusted_foundations
|
||||||
|
*
|
||||||
|
* Trusted Foundations firmware initialization.
|
||||||
|
*
|
||||||
|
* Doesn't return if firmware presents.
|
||||||
|
* Corrupted registers: r1, r2
|
||||||
|
*/
|
||||||
|
ENTRY(tegra_resume_trusted_foundations)
|
||||||
|
/* Check whether Trusted Foundations firmware presents. */
|
||||||
|
mov32 r2, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
|
||||||
|
ldr r1, =__tegra_cpu_reset_handler_data_offset + \
|
||||||
|
RESET_DATA(TF_PRESENT)
|
||||||
|
ldr r1, [r2, r1]
|
||||||
|
cmp r1, #0
|
||||||
|
reteq lr
|
||||||
|
|
||||||
|
.arch_extension sec
|
||||||
|
/* First call after suspend wakes firmware. No arguments required. */
|
||||||
|
smc #0
|
||||||
|
|
||||||
|
b cpu_resume
|
||||||
|
ENDPROC(tegra_resume_trusted_foundations)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.align L1_CACHE_SHIFT
|
.align L1_CACHE_SHIFT
|
||||||
|
@ -115,12 +139,19 @@ ENTRY(__tegra_cpu_reset_handler_start)
|
||||||
* must be position-independent.
|
* must be position-independent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.arm
|
||||||
.align L1_CACHE_SHIFT
|
.align L1_CACHE_SHIFT
|
||||||
ENTRY(__tegra_cpu_reset_handler)
|
ENTRY(__tegra_cpu_reset_handler)
|
||||||
|
|
||||||
cpsid aif, 0x13 @ SVC mode, interrupts disabled
|
cpsid aif, 0x13 @ SVC mode, interrupts disabled
|
||||||
|
|
||||||
tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
|
tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
|
||||||
|
|
||||||
|
adr r12, __tegra_cpu_reset_handler_data
|
||||||
|
ldr r5, [r12, #RESET_DATA(TF_PRESENT)]
|
||||||
|
cmp r5, #0
|
||||||
|
bne after_errata
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
||||||
t20_check:
|
t20_check:
|
||||||
cmp r6, #TEGRA20
|
cmp r6, #TEGRA20
|
||||||
|
@ -155,7 +186,6 @@ after_errata:
|
||||||
and r10, r10, #0x3 @ R10 = CPU number
|
and r10, r10, #0x3 @ R10 = CPU number
|
||||||
mov r11, #1
|
mov r11, #1
|
||||||
mov r11, r11, lsl r10 @ R11 = CPU mask
|
mov r11, r11, lsl r10 @ R11 = CPU mask
|
||||||
adr r12, __tegra_cpu_reset_handler_data
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/* Does the OS know about this CPU? */
|
/* Does the OS know about this CPU? */
|
||||||
|
@ -169,10 +199,9 @@ after_errata:
|
||||||
cmp r6, #TEGRA20
|
cmp r6, #TEGRA20
|
||||||
bne 1f
|
bne 1f
|
||||||
/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
|
/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
|
||||||
mov32 r5, TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET
|
|
||||||
mov r0, #CPU_NOT_RESETTABLE
|
mov r0, #CPU_NOT_RESETTABLE
|
||||||
cmp r10, #0
|
cmp r10, #0
|
||||||
strbne r0, [r5, #__tegra20_cpu1_resettable_status_offset]
|
strbne r0, [r12, #RESET_DATA(RESETTABLE_STATUS)]
|
||||||
1:
|
1:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -277,14 +306,13 @@ ENDPROC(__tegra_cpu_reset_handler)
|
||||||
.align L1_CACHE_SHIFT
|
.align L1_CACHE_SHIFT
|
||||||
.type __tegra_cpu_reset_handler_data, %object
|
.type __tegra_cpu_reset_handler_data, %object
|
||||||
.globl __tegra_cpu_reset_handler_data
|
.globl __tegra_cpu_reset_handler_data
|
||||||
__tegra_cpu_reset_handler_data:
|
.globl __tegra_cpu_reset_handler_data_offset
|
||||||
.rept TEGRA_RESET_DATA_SIZE
|
.equ __tegra_cpu_reset_handler_data_offset, \
|
||||||
.long 0
|
|
||||||
.endr
|
|
||||||
.globl __tegra20_cpu1_resettable_status_offset
|
|
||||||
.equ __tegra20_cpu1_resettable_status_offset, \
|
|
||||||
. - __tegra_cpu_reset_handler_start
|
. - __tegra_cpu_reset_handler_start
|
||||||
.byte 0
|
__tegra_cpu_reset_handler_data:
|
||||||
|
.rept TEGRA_RESET_DATA_SIZE
|
||||||
|
.long 0
|
||||||
|
.endr
|
||||||
.align L1_CACHE_SHIFT
|
.align L1_CACHE_SHIFT
|
||||||
|
|
||||||
ENTRY(__tegra_cpu_reset_handler_end)
|
ENTRY(__tegra_cpu_reset_handler_end)
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#include <linux/firmware/trusted_foundations.h>
|
||||||
|
|
||||||
#include <soc/tegra/fuse.h>
|
#include <soc/tegra/fuse.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
@ -89,6 +91,8 @@ static void __init tegra_cpu_reset_handler_enable(void)
|
||||||
|
|
||||||
void __init tegra_cpu_reset_handler_init(void)
|
void __init tegra_cpu_reset_handler_init(void)
|
||||||
{
|
{
|
||||||
|
__tegra_cpu_reset_handler_data[TEGRA_RESET_TF_PRESENT] =
|
||||||
|
trusted_foundations_registered();
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
|
__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
|
||||||
|
|
|
@ -25,7 +25,11 @@
|
||||||
#define TEGRA_RESET_STARTUP_SECONDARY 3
|
#define TEGRA_RESET_STARTUP_SECONDARY 3
|
||||||
#define TEGRA_RESET_STARTUP_LP2 4
|
#define TEGRA_RESET_STARTUP_LP2 4
|
||||||
#define TEGRA_RESET_STARTUP_LP1 5
|
#define TEGRA_RESET_STARTUP_LP1 5
|
||||||
#define TEGRA_RESET_DATA_SIZE 6
|
#define TEGRA_RESET_RESETTABLE_STATUS 6
|
||||||
|
#define TEGRA_RESET_TF_PRESENT 7
|
||||||
|
#define TEGRA_RESET_DATA_SIZE 8
|
||||||
|
|
||||||
|
#define RESET_DATA(x) ((TEGRA_RESET_##x)*4)
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
@ -49,7 +53,8 @@ void __tegra_cpu_reset_handler_end(void);
|
||||||
(u32)__tegra_cpu_reset_handler_start)))
|
(u32)__tegra_cpu_reset_handler_start)))
|
||||||
#define tegra20_cpu1_resettable_status \
|
#define tegra20_cpu1_resettable_status \
|
||||||
(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
|
(IO_ADDRESS(TEGRA_IRAM_BASE + TEGRA_IRAM_RESET_HANDLER_OFFSET + \
|
||||||
(u32)__tegra20_cpu1_resettable_status_offset))
|
((u32)&__tegra_cpu_reset_handler_data[TEGRA_RESET_RESETTABLE_STATUS] - \
|
||||||
|
(u32)__tegra_cpu_reset_handler_start)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define tegra_cpu_reset_handler_offset \
|
#define tegra_cpu_reset_handler_offset \
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
|
|
||||||
#include "irammap.h"
|
#include "irammap.h"
|
||||||
|
#include "reset.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
|
|
||||||
#define EMC_CFG 0xc
|
#define EMC_CFG 0xc
|
||||||
|
@ -53,6 +54,9 @@
|
||||||
#define APB_MISC_XM2CFGCPADCTRL2 0x8e4
|
#define APB_MISC_XM2CFGCPADCTRL2 0x8e4
|
||||||
#define APB_MISC_XM2CFGDPADCTRL2 0x8e8
|
#define APB_MISC_XM2CFGDPADCTRL2 0x8e8
|
||||||
|
|
||||||
|
#define __tegra20_cpu1_resettable_status_offset \
|
||||||
|
(__tegra_cpu_reset_handler_data_offset + RESET_DATA(RESETTABLE_STATUS))
|
||||||
|
|
||||||
.macro pll_enable, rd, r_car_base, pll_base
|
.macro pll_enable, rd, r_car_base, pll_base
|
||||||
ldr \rd, [\r_car_base, #\pll_base]
|
ldr \rd, [\r_car_base, #\pll_base]
|
||||||
tst \rd, #(1 << 30)
|
tst \rd, #(1 << 30)
|
||||||
|
|
|
@ -49,8 +49,9 @@ ENTRY(tegra_disable_clean_inv_dcache)
|
||||||
|
|
||||||
/* Disable the D-cache */
|
/* Disable the D-cache */
|
||||||
mrc p15, 0, r2, c1, c0, 0
|
mrc p15, 0, r2, c1, c0, 0
|
||||||
|
tst r2, #CR_C @ see tegra_sleep_cpu()
|
||||||
bic r2, r2, #CR_C
|
bic r2, r2, #CR_C
|
||||||
mcr p15, 0, r2, c1, c0, 0
|
mcrne p15, 0, r2, c1, c0, 0
|
||||||
isb
|
isb
|
||||||
|
|
||||||
/* Flush the D-cache */
|
/* Flush the D-cache */
|
||||||
|
@ -132,10 +133,13 @@ ENTRY(tegra_shut_off_mmu)
|
||||||
#ifdef CONFIG_CACHE_L2X0
|
#ifdef CONFIG_CACHE_L2X0
|
||||||
/* Disable L2 cache */
|
/* Disable L2 cache */
|
||||||
check_cpu_part_num 0xc09, r9, r10
|
check_cpu_part_num 0xc09, r9, r10
|
||||||
movweq r2, #:lower16:(TEGRA_ARM_PERIF_BASE + 0x3000)
|
retne r0
|
||||||
movteq r2, #:upper16:(TEGRA_ARM_PERIF_BASE + 0x3000)
|
|
||||||
moveq r3, #0
|
mov32 r2, TEGRA_ARM_PERIF_BASE + 0x3000
|
||||||
streq r3, [r2, #L2X0_CTRL]
|
ldr r3, [r2, #L2X0_CTRL]
|
||||||
|
tst r3, #L2X0_CTRL_EN @ see tegra_sleep_cpu()
|
||||||
|
mov r3, #0
|
||||||
|
strne r3, [r2, #L2X0_CTRL]
|
||||||
#endif
|
#endif
|
||||||
ret r0
|
ret r0
|
||||||
ENDPROC(tegra_shut_off_mmu)
|
ENDPROC(tegra_shut_off_mmu)
|
||||||
|
|
|
@ -35,15 +35,17 @@
|
||||||
#include <linux/sys_soc.h>
|
#include <linux/sys_soc.h>
|
||||||
#include <linux/usb/tegra_usb_phy.h>
|
#include <linux/usb/tegra_usb_phy.h>
|
||||||
|
|
||||||
|
#include <linux/firmware/trusted_foundations.h>
|
||||||
|
|
||||||
#include <soc/tegra/fuse.h>
|
#include <soc/tegra/fuse.h>
|
||||||
#include <soc/tegra/pmc.h>
|
#include <soc/tegra/pmc.h>
|
||||||
|
|
||||||
|
#include <asm/firmware.h>
|
||||||
#include <asm/hardware/cache-l2x0.h>
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach/time.h>
|
#include <asm/mach/time.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/trusted_foundations.h>
|
|
||||||
|
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
@ -74,6 +76,7 @@ static void __init tegra_init_early(void)
|
||||||
{
|
{
|
||||||
of_register_trusted_foundations();
|
of_register_trusted_foundations();
|
||||||
tegra_cpu_reset_handler_init();
|
tegra_cpu_reset_handler_init();
|
||||||
|
call_firmware_op(l2x0_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init tegra_dt_init_irq(void)
|
static void __init tegra_dt_init_irq(void)
|
||||||
|
|
|
@ -267,6 +267,22 @@ config TI_SCI_PROTOCOL
|
||||||
This protocol library is used by client drivers to use the features
|
This protocol library is used by client drivers to use the features
|
||||||
provided by the system controller.
|
provided by the system controller.
|
||||||
|
|
||||||
|
config TRUSTED_FOUNDATIONS
|
||||||
|
bool "Trusted Foundations secure monitor support"
|
||||||
|
depends on ARM
|
||||||
|
help
|
||||||
|
Some devices (including most early 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 the functions and
|
||||||
|
comments in linux/firmware/trusted_foundations.h or the device tree
|
||||||
|
bindings for "tlm,trusted-foundations" for details on how to use it.
|
||||||
|
|
||||||
|
Choose N if you don't know what this is about.
|
||||||
|
|
||||||
config HAVE_ARM_SMCCC
|
config HAVE_ARM_SMCCC
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o
|
||||||
obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
|
obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o
|
||||||
CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
|
CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
|
||||||
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
|
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
|
||||||
|
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
|
||||||
|
|
||||||
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
|
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/
|
||||||
obj-y += broadcom/
|
obj-y += broadcom/
|
||||||
|
|
|
@ -17,8 +17,17 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
|
||||||
|
#include <linux/firmware/trusted_foundations.h>
|
||||||
|
|
||||||
#include <asm/firmware.h>
|
#include <asm/firmware.h>
|
||||||
#include <asm/trusted_foundations.h>
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
|
#include <asm/outercache.h>
|
||||||
|
|
||||||
|
#define TF_CACHE_MAINT 0xfffff100
|
||||||
|
|
||||||
|
#define TF_CACHE_ENABLE 1
|
||||||
|
#define TF_CACHE_DISABLE 2
|
||||||
|
|
||||||
#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200
|
#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200
|
||||||
|
|
||||||
|
@ -60,16 +69,75 @@ static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tf_prepare_idle(void)
|
static int tf_prepare_idle(unsigned long mode)
|
||||||
{
|
{
|
||||||
tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2, cpu_boot_addr);
|
switch (mode) {
|
||||||
|
case TF_PM_MODE_LP0:
|
||||||
|
tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S3, cpu_boot_addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TF_PM_MODE_LP1:
|
||||||
|
tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2, cpu_boot_addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TF_PM_MODE_LP1_NO_MC_CLK:
|
||||||
|
tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2_NO_MC_CLK,
|
||||||
|
cpu_boot_addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TF_PM_MODE_LP2:
|
||||||
|
tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1, cpu_boot_addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TF_PM_MODE_LP2_NOFLUSH_L2:
|
||||||
|
tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2,
|
||||||
|
cpu_boot_addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CACHE_L2X0
|
||||||
|
static void tf_cache_write_sec(unsigned long val, unsigned int reg)
|
||||||
|
{
|
||||||
|
u32 l2x0_way_mask = 0xff;
|
||||||
|
|
||||||
|
switch (reg) {
|
||||||
|
case L2X0_CTRL:
|
||||||
|
if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_ASSOCIATIVITY_16)
|
||||||
|
l2x0_way_mask = 0xffff;
|
||||||
|
|
||||||
|
if (val == L2X0_CTRL_EN)
|
||||||
|
tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_ENABLE,
|
||||||
|
l2x0_saved_regs.aux_ctrl);
|
||||||
|
else
|
||||||
|
tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_DISABLE,
|
||||||
|
l2x0_way_mask);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tf_init_cache(void)
|
||||||
|
{
|
||||||
|
outer_cache.write_sec = tf_cache_write_sec;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CACHE_L2X0 */
|
||||||
|
|
||||||
static const struct firmware_ops trusted_foundations_ops = {
|
static const struct firmware_ops trusted_foundations_ops = {
|
||||||
.set_cpu_boot_addr = tf_set_cpu_boot_addr,
|
.set_cpu_boot_addr = tf_set_cpu_boot_addr,
|
||||||
.prepare_idle = tf_prepare_idle,
|
.prepare_idle = tf_prepare_idle,
|
||||||
|
#ifdef CONFIG_CACHE_L2X0
|
||||||
|
.l2x0_init = tf_init_cache,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
|
void register_trusted_foundations(struct trusted_foundations_platform_data *pd)
|
||||||
|
@ -101,3 +169,8 @@ void of_register_trusted_foundations(void)
|
||||||
panic("Trusted Foundation: missing version-minor property\n");
|
panic("Trusted Foundation: missing version-minor property\n");
|
||||||
register_trusted_foundations(&pdata);
|
register_trusted_foundations(&pdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool trusted_foundations_registered(void)
|
||||||
|
{
|
||||||
|
return firmware_ops == &trusted_foundations_ops;
|
||||||
|
}
|
|
@ -23,14 +23,24 @@
|
||||||
* PSCI standard.
|
* PSCI standard.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASM_ARM_TRUSTED_FOUNDATIONS_H
|
#ifndef __FIRMWARE_TRUSTED_FOUNDATIONS_H
|
||||||
#define __ASM_ARM_TRUSTED_FOUNDATIONS_H
|
#define __FIRMWARE_TRUSTED_FOUNDATIONS_H
|
||||||
|
|
||||||
#include <linux/printk.h>
|
#include <linux/printk.h>
|
||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
|
#include <asm/outercache.h>
|
||||||
|
|
||||||
|
#define TF_PM_MODE_LP0 0
|
||||||
|
#define TF_PM_MODE_LP1 1
|
||||||
|
#define TF_PM_MODE_LP1_NO_MC_CLK 2
|
||||||
|
#define TF_PM_MODE_LP2 3
|
||||||
|
#define TF_PM_MODE_LP2_NOFLUSH_L2 4
|
||||||
|
|
||||||
struct trusted_foundations_platform_data {
|
struct trusted_foundations_platform_data {
|
||||||
unsigned int version_major;
|
unsigned int version_major;
|
||||||
|
@ -41,8 +51,12 @@ struct trusted_foundations_platform_data {
|
||||||
|
|
||||||
void register_trusted_foundations(struct trusted_foundations_platform_data *pd);
|
void register_trusted_foundations(struct trusted_foundations_platform_data *pd);
|
||||||
void of_register_trusted_foundations(void);
|
void of_register_trusted_foundations(void);
|
||||||
|
bool trusted_foundations_registered(void);
|
||||||
|
|
||||||
#else /* CONFIG_TRUSTED_FOUNDATIONS */
|
#else /* CONFIG_TRUSTED_FOUNDATIONS */
|
||||||
|
static inline void tf_dummy_write_sec(unsigned long val, unsigned int reg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline void register_trusted_foundations(
|
static inline void register_trusted_foundations(
|
||||||
struct trusted_foundations_platform_data *pd)
|
struct trusted_foundations_platform_data *pd)
|
||||||
|
@ -53,6 +67,10 @@ static inline void register_trusted_foundations(
|
||||||
*/
|
*/
|
||||||
pr_err("No support for Trusted Foundations, continuing in degraded mode.\n");
|
pr_err("No support for Trusted Foundations, continuing in degraded mode.\n");
|
||||||
pr_err("Secondary processors as well as CPU PM will be disabled.\n");
|
pr_err("Secondary processors as well as CPU PM will be disabled.\n");
|
||||||
|
#if IS_ENABLED(CONFIG_CACHE_L2X0)
|
||||||
|
pr_err("L2X0 cache will be kept disabled.\n");
|
||||||
|
outer_cache.write_sec = tf_dummy_write_sec;
|
||||||
|
#endif
|
||||||
#if IS_ENABLED(CONFIG_SMP)
|
#if IS_ENABLED(CONFIG_SMP)
|
||||||
setup_max_cpus = 0;
|
setup_max_cpus = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -68,6 +86,11 @@ static inline void of_register_trusted_foundations(void)
|
||||||
if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"))
|
if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"))
|
||||||
register_trusted_foundations(NULL);
|
register_trusted_foundations(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool trusted_foundations_registered(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif /* CONFIG_TRUSTED_FOUNDATIONS */
|
#endif /* CONFIG_TRUSTED_FOUNDATIONS */
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue