linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30
@ 2018-08-30 18:04 Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 1/8] ARM: trusted_foundations: Implement L2 cache initialization callback Dmitry Osipenko
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

Hello,

All consumer-grade Tegra30 devices, like Nexus 7 tablet; Ouya console and
others, use Trusted Foundations firmware that doesn't allow CPU to access
secure registers directly from the Linux kernel, these accesses shall be
done via the firmware calls. This patch-series adds a full-featured support
of the Trusted Foundations firmware that opens the door for supporting of
various Tegra30-based devices in the upstream Linux kernel.

Changelog:

v3:	- Implemented suspend-resume support.

	- Reworked arm/firmware/trusted_foundations.c a tad. Now cache
	  is getting properly initialized, cache enabling / disabling is
	  supported.

v2:
	- The "Don't apply CPU erratas in insecure mode" patch got some
	  cleanup, in particular resolved the messiness in
	  __tegra_cpu_reset_handler_data.

	- Added a comment to tf_cache_write_sec(), justifying the warning
	  message.

Dmitry Osipenko (8):
  ARM: trusted_foundations: Implement L2 cache initialization callback
  ARM: trusted_foundations: Make prepare_idle call to take mode argument
  ARM: trusted_foundations: Provide information about whether firmware
    is registered
  ARM: tegra: Setup L2 cache using Trusted Foundations firmware
  ARM: tegra: Don't apply CPU erratas in insecure mode
  ARM: tegra: Always boot CPU in ARM-mode
  ARM: tegra: Support L2 cache maintenance done via firmware
  ARM: tegra: Add firmware calls required for suspend-resume

 arch/arm/firmware/trusted_foundations.c    | 80 +++++++++++++++++++++-
 arch/arm/include/asm/firmware.h            |  2 +-
 arch/arm/include/asm/trusted_foundations.h | 13 ++++
 arch/arm/mach-tegra/cpuidle-tegra114.c     |  3 +-
 arch/arm/mach-tegra/pm.c                   | 43 ++++++++++++
 arch/arm/mach-tegra/reset-handler.S        | 66 ++++++++++++++----
 arch/arm/mach-tegra/reset.c                |  3 +
 arch/arm/mach-tegra/reset.h                |  9 ++-
 arch/arm/mach-tegra/sleep-tegra20.S        |  4 ++
 arch/arm/mach-tegra/sleep.S                |  4 ++
 arch/arm/mach-tegra/tegra.c                | 10 +++
 11 files changed, 216 insertions(+), 21 deletions(-)

-- 
2.18.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/8] ARM: trusted_foundations: Implement L2 cache initialization callback
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
@ 2018-08-30 18:04 ` Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 2/8] ARM: trusted_foundations: Make prepare_idle call to take mode argument Dmitry Osipenko
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

Implement L2 cache initialization firmware callback that should be invoked
early in boot in order to setup the required outer cache driver callbacks.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/firmware/trusted_foundations.c | 46 +++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/arch/arm/firmware/trusted_foundations.c b/arch/arm/firmware/trusted_foundations.c
index 689e6565abfc..3bf61a5933b9 100644
--- a/arch/arm/firmware/trusted_foundations.c
+++ b/arch/arm/firmware/trusted_foundations.c
@@ -18,8 +18,15 @@
 #include <linux/init.h>
 #include <linux/of.h>
 #include <asm/firmware.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/outercache.h>
 #include <asm/trusted_foundations.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_CPU_PM		0xfffffffc
@@ -67,9 +74,48 @@ static int tf_prepare_idle(void)
 	return 0;
 }
 
+#ifdef CONFIG_CACHE_L2X0
+static void tf_cache_write_sec(unsigned long val, unsigned int reg)
+{
+	static u32 l2x0_way_mask = 0xff;
+	static u32 l2x0_aux_ctrl = 0;
+
+	switch (reg) {
+	case L2X0_AUX_CTRL:
+		l2x0_aux_ctrl = val;
+
+		if (l2x0_aux_ctrl & BIT(16))
+			l2x0_way_mask = 0xffff;
+		break;
+
+	case L2X0_CTRL:
+		if (val == L2X0_CTRL_EN)
+			tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_ENABLE,
+				       l2x0_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 = {
 	.set_cpu_boot_addr = tf_set_cpu_boot_addr,
 	.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)
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 2/8] ARM: trusted_foundations: Make prepare_idle call to take mode argument
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 1/8] ARM: trusted_foundations: Implement L2 cache initialization callback Dmitry Osipenko
@ 2018-08-30 18:04 ` Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 3/8] ARM: trusted_foundations: Provide information about whether firmware is registered Dmitry Osipenko
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

The Trusted Foundations firmware call varies depending on the required
suspend-mode. Make the firmware API to take the mode argument in order
to expose all of the modes to firmware user.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/firmware/trusted_foundations.c    | 29 ++++++++++++++++++++--
 arch/arm/include/asm/firmware.h            |  2 +-
 arch/arm/include/asm/trusted_foundations.h |  6 +++++
 arch/arm/mach-tegra/cpuidle-tegra114.c     |  3 ++-
 4 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/arch/arm/firmware/trusted_foundations.c b/arch/arm/firmware/trusted_foundations.c
index 3bf61a5933b9..c496f4cc49cb 100644
--- a/arch/arm/firmware/trusted_foundations.c
+++ b/arch/arm/firmware/trusted_foundations.c
@@ -67,9 +67,34 @@ static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
 	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;
 }
diff --git a/arch/arm/include/asm/firmware.h b/arch/arm/include/asm/firmware.h
index 34c1d96ef46d..6698272bbcbf 100644
--- a/arch/arm/include/asm/firmware.h
+++ b/arch/arm/include/asm/firmware.h
@@ -24,7 +24,7 @@ struct firmware_ops {
 	/*
 	 * Inform the firmware we intend to enter CPU idle mode
 	 */
-	int (*prepare_idle)(void);
+	int (*prepare_idle)(unsigned long mode);
 	/*
 	 * Enters CPU idle mode
 	 */
diff --git a/arch/arm/include/asm/trusted_foundations.h b/arch/arm/include/asm/trusted_foundations.h
index 00748350cf72..cdd48ab7d191 100644
--- a/arch/arm/include/asm/trusted_foundations.h
+++ b/arch/arm/include/asm/trusted_foundations.h
@@ -32,6 +32,12 @@
 #include <linux/cpu.h>
 #include <linux/smp.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 {
 	unsigned int version_major;
 	unsigned int version_minor;
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
index e3fbcfedf845..3b9af4766cdf 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra114.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -24,6 +24,7 @@
 #include <asm/cpuidle.h>
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
+#include <asm/trusted_foundations.h>
 #include <asm/psci.h>
 
 #include "cpuidle.h"
@@ -46,7 +47,7 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
 	tegra_set_cpu_in_lp2();
 	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 */
 	if (call_firmware_op(do_idle, 0) == -ENOSYS)
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 3/8] ARM: trusted_foundations: Provide information about whether firmware is registered
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 1/8] ARM: trusted_foundations: Implement L2 cache initialization callback Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 2/8] ARM: trusted_foundations: Make prepare_idle call to take mode argument Dmitry Osipenko
@ 2018-08-30 18:04 ` Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 4/8] ARM: tegra: Setup L2 cache using Trusted Foundations firmware Dmitry Osipenko
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

Add a helper that provides information about whether Trusted Foundations
firmware operations have been registered.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/firmware/trusted_foundations.c    | 5 +++++
 arch/arm/include/asm/trusted_foundations.h | 7 +++++++
 2 files changed, 12 insertions(+)

diff --git a/arch/arm/firmware/trusted_foundations.c b/arch/arm/firmware/trusted_foundations.c
index c496f4cc49cb..d795ed83a3cd 100644
--- a/arch/arm/firmware/trusted_foundations.c
+++ b/arch/arm/firmware/trusted_foundations.c
@@ -172,3 +172,8 @@ void of_register_trusted_foundations(void)
 		panic("Trusted Foundation: missing version-minor property\n");
 	register_trusted_foundations(&pdata);
 }
+
+bool trusted_foundations_registered(void)
+{
+	return firmware_ops == &trusted_foundations_ops;
+}
diff --git a/arch/arm/include/asm/trusted_foundations.h b/arch/arm/include/asm/trusted_foundations.h
index cdd48ab7d191..3f23fa493db6 100644
--- a/arch/arm/include/asm/trusted_foundations.h
+++ b/arch/arm/include/asm/trusted_foundations.h
@@ -31,6 +31,7 @@
 #include <linux/of.h>
 #include <linux/cpu.h>
 #include <linux/smp.h>
+#include <linux/types.h>
 
 #define TF_PM_MODE_LP0			0
 #define TF_PM_MODE_LP1			1
@@ -47,6 +48,7 @@ struct trusted_foundations_platform_data {
 
 void register_trusted_foundations(struct trusted_foundations_platform_data *pd);
 void of_register_trusted_foundations(void);
+bool trusted_foundations_registered(void);
 
 #else /* CONFIG_TRUSTED_FOUNDATIONS */
 
@@ -74,6 +76,11 @@ static inline void of_register_trusted_foundations(void)
 	if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"))
 		register_trusted_foundations(NULL);
 }
+
+static inline bool trusted_foundations_registered(void)
+{
+	return false;
+}
 #endif /* CONFIG_TRUSTED_FOUNDATIONS */
 
 #endif
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 4/8] ARM: tegra: Setup L2 cache using Trusted Foundations firmware
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2018-08-30 18:04 ` [PATCH v3 3/8] ARM: trusted_foundations: Provide information about whether firmware is registered Dmitry Osipenko
@ 2018-08-30 18:04 ` Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 5/8] ARM: tegra: Don't apply CPU erratas in insecure mode Dmitry Osipenko
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

On Tegra30 L2 cache should be initialized using firmware call if CPU is
running in insecure mode. Initialize L2 cache and setup the outer-cache
callbacks in early boot using the firmware API.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/mach-tegra/tegra.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index f9587be48235..67d8ae60ac67 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -38,6 +38,7 @@
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
+#include <asm/firmware.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
@@ -70,9 +71,18 @@ u32 tegra_uart_config[3] = {
 	0,
 };
 
+static void __init tegra_trusted_foundations_l2x0_cache_init(void)
+{
+	if (IS_ENABLED(CONFIG_CACHE_L2X0) &&
+	    IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) &&
+	    of_machine_is_compatible("nvidia,tegra30"))
+		call_firmware_op(l2x0_init);
+}
+
 static void __init tegra_init_early(void)
 {
 	of_register_trusted_foundations();
+	tegra_trusted_foundations_l2x0_cache_init();
 	tegra_cpu_reset_handler_init();
 }
 
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 5/8] ARM: tegra: Don't apply CPU erratas in insecure mode
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
                   ` (3 preceding siblings ...)
  2018-08-30 18:04 ` [PATCH v3 4/8] ARM: tegra: Setup L2 cache using Trusted Foundations firmware Dmitry Osipenko
@ 2018-08-30 18:04 ` Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 6/8] ARM: tegra: Always boot CPU in ARM-mode Dmitry Osipenko
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

CPU isn't allowed to touch secure registers while running under secure
monitor. Hence skip applying of CPU erratas in the reset handler if
Trusted Foundations firmware presents.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/mach-tegra/reset-handler.S | 24 ++++++++++++------------
 arch/arm/mach-tegra/reset.c         |  3 +++
 arch/arm/mach-tegra/reset.h         |  9 +++++++--
 arch/arm/mach-tegra/sleep-tegra20.S |  4 ++++
 4 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 805f306fa6f7..a9f13230da2f 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -29,8 +29,6 @@
 
 #define PMC_SCRATCH41	0x140
 
-#define RESET_DATA(x)	((TEGRA_RESET_##x)*4)
-
 #ifdef CONFIG_PM_SLEEP
 /*
  *	tegra_resume
@@ -121,6 +119,12 @@ ENTRY(__tegra_cpu_reset_handler)
 	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
 
 	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
 t20_check:
 	cmp	r6, #TEGRA20
@@ -155,7 +159,6 @@ after_errata:
 	and	r10, r10, #0x3			@ R10 = CPU number
 	mov	r11, #1
 	mov	r11, r11, lsl r10  		@ R11 = CPU mask
-	adr	r12, __tegra_cpu_reset_handler_data
 
 #ifdef CONFIG_SMP
 	/* Does the OS know about this CPU? */
@@ -169,10 +172,9 @@ after_errata:
 	cmp	r6, #TEGRA20
 	bne	1f
 	/* 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
 	cmp	r10, #0
-	strneb	r0, [r5, #__tegra20_cpu1_resettable_status_offset]
+	strneb	r0, [r12, #RESET_DATA(RESETTABLE_STATUS)]
 1:
 #endif
 
@@ -277,14 +279,12 @@ ENDPROC(__tegra_cpu_reset_handler)
 	.align L1_CACHE_SHIFT
 	.type	__tegra_cpu_reset_handler_data, %object
 	.globl	__tegra_cpu_reset_handler_data
+	.globl	__tegra_cpu_reset_handler_data_offset
+	.equ	__tegra_cpu_reset_handler_data_offset, \
+					. - __tegra_cpu_reset_handler_start
 __tegra_cpu_reset_handler_data:
-	.rept	TEGRA_RESET_DATA_SIZE
-	.long	0
+	.rept   TEGRA_RESET_DATA_SIZE
+	.long   0
 	.endr
-	.globl	__tegra20_cpu1_resettable_status_offset
-	.equ	__tegra20_cpu1_resettable_status_offset, \
-					. - __tegra_cpu_reset_handler_start
-	.byte	0
 	.align L1_CACHE_SHIFT
-
 ENTRY(__tegra_cpu_reset_handler_end)
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index dc558892753c..b02ae7699842 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -24,6 +24,7 @@
 #include <asm/cacheflush.h>
 #include <asm/firmware.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <asm/trusted_foundations.h>
 
 #include "iomap.h"
 #include "irammap.h"
@@ -89,6 +90,8 @@ static void __init tegra_cpu_reset_handler_enable(void)
 
 void __init tegra_cpu_reset_handler_init(void)
 {
+	__tegra_cpu_reset_handler_data[TEGRA_RESET_TF_PRESENT] =
+		trusted_foundations_registered();
 
 #ifdef CONFIG_SMP
 	__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
diff --git a/arch/arm/mach-tegra/reset.h b/arch/arm/mach-tegra/reset.h
index 9c479c7925b8..db0e6b3097ab 100644
--- a/arch/arm/mach-tegra/reset.h
+++ b/arch/arm/mach-tegra/reset.h
@@ -25,7 +25,11 @@
 #define TEGRA_RESET_STARTUP_SECONDARY	3
 #define TEGRA_RESET_STARTUP_LP2		4
 #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__
 
@@ -49,7 +53,8 @@ void __tegra_cpu_reset_handler_end(void);
 	 (u32)__tegra_cpu_reset_handler_start)))
 #define tegra20_cpu1_resettable_status \
 	(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
 
 #define tegra_cpu_reset_handler_offset \
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index 5c8e638ee51a..11f423e4a263 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -28,6 +28,7 @@
 #include <asm/cache.h>
 
 #include "irammap.h"
+#include "reset.h"
 #include "sleep.h"
 
 #define EMC_CFG				0xc
@@ -54,6 +55,9 @@
 #define APB_MISC_XM2CFGCPADCTRL2	0x8e4
 #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
 	ldr	\rd, [\r_car_base, #\pll_base]
 	tst	\rd, #(1 << 30)
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 6/8] ARM: tegra: Always boot CPU in ARM-mode
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
                   ` (4 preceding siblings ...)
  2018-08-30 18:04 ` [PATCH v3 5/8] ARM: tegra: Don't apply CPU erratas in insecure mode Dmitry Osipenko
@ 2018-08-30 18:04 ` Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 7/8] ARM: tegra: Support L2 cache maintenance done via firmware Dmitry Osipenko
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

CPU always jumps into reset handler in ARM-mode from the Trusted
Foundations firmware, hence let's make CPU to always jump into kernel
in ARM-mode regardless of the firmware presence to support. This is
required to make  Thumb-2 kernel working with the Trusted Foundations
firmware on Tegra30.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/mach-tegra/reset-handler.S | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index a9f13230da2f..555c652f5a07 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -20,6 +20,7 @@
 #include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
+#include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
@@ -112,10 +113,20 @@ ENTRY(__tegra_cpu_reset_handler_start)
  * NOTE: This code is copied to IRAM. All code and data accesses
  *       must be position-independent.
  */
-
+	.arm
 	.align L1_CACHE_SHIFT
 ENTRY(__tegra_cpu_reset_handler)
 
+	/*
+	 * Tegra30 ignores first bit of the reset vector and always jumps
+	 * into kernel in .ARM mode from the firmware, hence force the mode
+	 * switch if kernel is compiled in Thumb-2.
+	 */
+ THUMB(	badr	r0, 1f		)
+ THUMB(	bx	r0		)
+ THUMB(	.thumb 			)
+ THUMB(	1: 			)
+
 	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
 
 	tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
@@ -215,7 +226,7 @@ __no_cpu0_chk:
 	ldr	lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
 	cmp	lr, #0
 	bleq	__die				@ no secondary startup handler
-	bx	lr
+	ret	lr
 #endif
 
 /*
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 7/8] ARM: tegra: Support L2 cache maintenance done via firmware
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
                   ` (5 preceding siblings ...)
  2018-08-30 18:04 ` [PATCH v3 6/8] ARM: tegra: Always boot CPU in ARM-mode Dmitry Osipenko
@ 2018-08-30 18:04 ` Dmitry Osipenko
  2018-08-30 18:04 ` [PATCH v3 8/8] ARM: tegra: Add firmware calls required for suspend-resume Dmitry Osipenko
  2018-10-15 12:34 ` [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

Trusted Foundations firmware require MMU to be enabled for L2 cache
maintenance on Tegra30, hence perform the maintenance early-late on
suspend-resume respectively.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/mach-tegra/pm.c            | 36 +++++++++++++++++++++++++++++
 arch/arm/mach-tegra/reset-handler.S |  8 ++-----
 arch/arm/mach-tegra/sleep.S         |  4 ++++
 3 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1ad5719779b0..66c8cd63dd86 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -38,6 +38,7 @@
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
+#include <asm/trusted_foundations.h>
 
 #include "iomap.h"
 #include "pm.h"
@@ -195,8 +196,27 @@ void tegra_idle_lp2_last(void)
 	cpu_cluster_pm_enter();
 	suspend_cpu_complex();
 
+	/*
+	 * L2 cache disabling using kernel API only allowed when all
+	 * secondary CPU's are offline. Cache have to be disabled early
+	 * 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 codepath only
+	 * for Tegra20/30.
+	 */
+	if (trusted_foundations_registered())
+		outer_disable();
+
 	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.
+	 */
+	outer_resume();
+
 	restore_cpu_complex();
 	cpu_cluster_pm_exit();
 }
@@ -340,8 +360,24 @@ static int tegra_suspend_enter(suspend_state_t state)
 		break;
 	}
 
+	/*
+	 * Cache have to be disabled early if cache maintenance is done
+	 * via Trusted Foundations firmware. Otherwise this is a no-op,
+	 * like on Tegra114+.
+	 */
+	if (trusted_foundations_registered())
+		outer_disable();
+
 	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) {
 	case TEGRA_SUSPEND_LP1:
 		tegra_suspend_exit_lp1();
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 555c652f5a07..4973ea053bd7 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -69,7 +69,7 @@ ENTRY(tegra_resume)
 
 	mov32	r9, 0xc09
 	cmp	r8, r9
-	bne	end_ca9_scu_l2_resume
+	bne	end_ca9_scu_resume
 #ifdef CONFIG_HAVE_ARM_SCU
 	/* enable SCU */
 	mov32	r0, TEGRA_ARM_PERIF_BASE
@@ -78,11 +78,7 @@ ENTRY(tegra_resume)
 	str	r1, [r0]
 #endif
 
-#ifdef CONFIG_CACHE_L2X0
-	/* L2 cache resume & re-enable */
-	bl	l2c310_early_resume
-#endif
-end_ca9_scu_l2_resume:
+end_ca9_scu_resume:
 	mov32	r9, 0xc0f
 	cmp	r8, r9
 	bleq	tegra_init_l2_for_a15
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 5e3496753df1..b96126fe5dc5 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -132,8 +132,12 @@ ENTRY(tegra_shut_off_mmu)
 #ifdef CONFIG_CACHE_L2X0
 	/* Disable L2 cache */
 	check_cpu_part_num 0xc09, r9, r10
+	retne	r0
+
 	movweq	r2, #:lower16:(TEGRA_ARM_PERIF_BASE + 0x3000)
 	movteq	r2, #:upper16:(TEGRA_ARM_PERIF_BASE + 0x3000)
+	ldr	r3, [r2, #L2X0_CTRL]
+	cmp	r3, #1
 	moveq	r3, #0
 	streq	r3, [r2, #L2X0_CTRL]
 #endif
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 8/8] ARM: tegra: Add firmware calls required for suspend-resume
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
                   ` (6 preceding siblings ...)
  2018-08-30 18:04 ` [PATCH v3 7/8] ARM: tegra: Support L2 cache maintenance done via firmware Dmitry Osipenko
@ 2018-08-30 18:04 ` Dmitry Osipenko
  2018-10-15 12:34 ` [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-08-30 18:04 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

In order to resume CPU from suspend via trusted Foundations firmware,
the LP1/LP2 boot vectors shall be specified using the firmware calls.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/mach-tegra/pm.c            |  7 ++++++
 arch/arm/mach-tegra/reset-handler.S | 33 +++++++++++++++++++++++++++--
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 66c8cd63dd86..12341ffabb99 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -33,6 +33,7 @@
 #include <soc/tegra/pmc.h>
 
 #include <asm/cacheflush.h>
+#include <asm/firmware.h>
 #include <asm/idmap.h>
 #include <asm/proc-fns.h>
 #include <asm/smp_plat.h>
@@ -150,6 +151,10 @@ bool tegra_set_cpu_in_lp2(void)
 		tegra20_cpu_set_resettable_soon();
 
 	spin_unlock(&tegra_lp2_lock);
+
+	if (last_cpu)
+		call_firmware_op(prepare_idle, TF_PM_MODE_LP2);
+
 	return last_cpu;
 }
 
@@ -316,6 +321,8 @@ static void tegra_suspend_enter_lp1(void)
 		tegra_lp1_iram.start_addr, iram_save_size);
 
 	*((u32 *)tegra_cpu_lp1_mask) = 1;
+
+	call_firmware_op(prepare_idle, TF_PM_MODE_LP1);
 }
 
 static void tegra_suspend_exit_lp1(void)
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 4973ea053bd7..0e208b2e246e 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -69,7 +69,7 @@ ENTRY(tegra_resume)
 
 	mov32	r9, 0xc09
 	cmp	r8, r9
-	bne	end_ca9_scu_resume
+	bne	end_ca9_scu_l2_resume
 #ifdef CONFIG_HAVE_ARM_SCU
 	/* enable SCU */
 	mov32	r0, TEGRA_ARM_PERIF_BASE
@@ -77,14 +77,43 @@ ENTRY(tegra_resume)
 	orr	r1, r1, #1
 	str	r1, [r0]
 #endif
+	bl	tegra_resume_trusted_foundations
 
-end_ca9_scu_resume:
+#ifdef CONFIG_CACHE_L2X0
+	/* L2 cache resume & re-enable */
+	bleq	l2c310_early_resume		@ No, resume cache early
+#endif
+end_ca9_scu_l2_resume:
 	mov32	r9, 0xc0f
 	cmp	r8, r9
 	bleq	tegra_init_l2_for_a15
 
 	b	cpu_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
 
 	.align L1_CACHE_SHIFT
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30
  2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
                   ` (7 preceding siblings ...)
  2018-08-30 18:04 ` [PATCH v3 8/8] ARM: tegra: Add firmware calls required for suspend-resume Dmitry Osipenko
@ 2018-10-15 12:34 ` Dmitry Osipenko
  8 siblings, 0 replies; 10+ messages in thread
From: Dmitry Osipenko @ 2018-10-15 12:34 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Russell King
  Cc: linux-arm-kernel, linux-tegra, linux-kernel

On 8/30/18 9:04 PM, Dmitry Osipenko wrote:
> Hello,
> 
> All consumer-grade Tegra30 devices, like Nexus 7 tablet; Ouya console and
> others, use Trusted Foundations firmware that doesn't allow CPU to access
> secure registers directly from the Linux kernel, these accesses shall be
> done via the firmware calls. This patch-series adds a full-featured support
> of the Trusted Foundations firmware that opens the door for supporting of
> various Tegra30-based devices in the upstream Linux kernel.
> 
> Changelog:
> 
> v3:	- Implemented suspend-resume support.
> 
> 	- Reworked arm/firmware/trusted_foundations.c a tad. Now cache
> 	  is getting properly initialized, cache enabling / disabling is
> 	  supported.
> 
> v2:
> 	- The "Don't apply CPU erratas in insecure mode" patch got some
> 	  cleanup, in particular resolved the messiness in
> 	  __tegra_cpu_reset_handler_data.
> 
> 	- Added a comment to tf_cache_write_sec(), justifying the warning
> 	  message.
> 
> Dmitry Osipenko (8):
>   ARM: trusted_foundations: Implement L2 cache initialization callback
>   ARM: trusted_foundations: Make prepare_idle call to take mode argument
>   ARM: trusted_foundations: Provide information about whether firmware
>     is registered
>   ARM: tegra: Setup L2 cache using Trusted Foundations firmware
>   ARM: tegra: Don't apply CPU erratas in insecure mode
>   ARM: tegra: Always boot CPU in ARM-mode
>   ARM: tegra: Support L2 cache maintenance done via firmware
>   ARM: tegra: Add firmware calls required for suspend-resume
> 
>  arch/arm/firmware/trusted_foundations.c    | 80 +++++++++++++++++++++-
>  arch/arm/include/asm/firmware.h            |  2 +-
>  arch/arm/include/asm/trusted_foundations.h | 13 ++++
>  arch/arm/mach-tegra/cpuidle-tegra114.c     |  3 +-
>  arch/arm/mach-tegra/pm.c                   | 43 ++++++++++++
>  arch/arm/mach-tegra/reset-handler.S        | 66 ++++++++++++++----
>  arch/arm/mach-tegra/reset.c                |  3 +
>  arch/arm/mach-tegra/reset.h                |  9 ++-
>  arch/arm/mach-tegra/sleep-tegra20.S        |  4 ++
>  arch/arm/mach-tegra/sleep.S                |  4 ++
>  arch/arm/mach-tegra/tegra.c                | 10 +++
>  11 files changed, 216 insertions(+), 21 deletions(-)
> 

ping

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-10-15 12:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-30 18:04 [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko
2018-08-30 18:04 ` [PATCH v3 1/8] ARM: trusted_foundations: Implement L2 cache initialization callback Dmitry Osipenko
2018-08-30 18:04 ` [PATCH v3 2/8] ARM: trusted_foundations: Make prepare_idle call to take mode argument Dmitry Osipenko
2018-08-30 18:04 ` [PATCH v3 3/8] ARM: trusted_foundations: Provide information about whether firmware is registered Dmitry Osipenko
2018-08-30 18:04 ` [PATCH v3 4/8] ARM: tegra: Setup L2 cache using Trusted Foundations firmware Dmitry Osipenko
2018-08-30 18:04 ` [PATCH v3 5/8] ARM: tegra: Don't apply CPU erratas in insecure mode Dmitry Osipenko
2018-08-30 18:04 ` [PATCH v3 6/8] ARM: tegra: Always boot CPU in ARM-mode Dmitry Osipenko
2018-08-30 18:04 ` [PATCH v3 7/8] ARM: tegra: Support L2 cache maintenance done via firmware Dmitry Osipenko
2018-08-30 18:04 ` [PATCH v3 8/8] ARM: tegra: Add firmware calls required for suspend-resume Dmitry Osipenko
2018-10-15 12:34 ` [PATCH v3 0/8] Support Trusted Foundations firmware on Tegra30 Dmitry Osipenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).