ARM: enable cache via Trusted Foundations firmware
Subsystems (3)
cover ARM: enable cache via Trusted Foundations firmware
This set enables platforms using Trusted Foundations firmware to use their L2 cache. L2 cache can be enabled only by calling the firmware.
Micha? Miros?aw (3):
ARM: cache-l2x0: share l2x0_base with PMU code
ARM: trusted_foundations: enable L2x0 cache via firmware_ops
ARM: trusted_foundations: announce firmware version
arch/arm/firmware/trusted_foundations.c | 67 +++++++++++++++++++++- arch/arm/include/asm/hardware/cache-l2x0.h | 6 +- arch/arm/mm/cache-l2x0-pmu.c | 9 +-- arch/arm/mm/cache-l2x0.c | 14 ++++- 4 files changed, 82 insertions(+), 14 deletions(-)
Signature · 1 line
2.19.1
PATCH 1/3 ARM: cache-l2x0: share l2x0_base with PMU code
Avoid l2x0_base duplication with PMU driver by sharing it and using l2x0_name as the 'enabled' flag instead. Since l2x0_name is not used for anything else, mark it as __initdata.
This will also be needed for cache maintenance with Trusted Foundations firmware.
--- arch/arm/include/asm/hardware/cache-l2x0.h | 6 ++++-- arch/arm/mm/cache-l2x0-pmu.c | 9 +++------ arch/arm/mm/cache-l2x0.c | 6 +++--- 3 files changed, 10 insertions(+), 11 deletions(-)
arch/arm/include/asm/hardware/cache-l2x0.h +4 -2
@@ -167,11 +167,11 @@ static inline int l2x0_of_init(u32 aux_val, u32 aux_mask)#endif #ifdef CONFIG_CACHE_L2X0_PMU -void l2x0_pmu_register (void __iomem *base,u32 part); +void l2x0_pmu_register (u32 part);void l2x0_pmu_suspend (void );void l2x0_pmu_resume (void );#else -static inline void l2x0_pmu_register (void __iomem *base,u32 part) {} +static inline void l2x0_pmu_register (u32 part) {}static inline void l2x0_pmu_suspend (void ) {}static inline void l2x0_pmu_resume (void ) {}#endif
@@ -193,6 +193,8 @@ struct l2x0_regs { unsigned long aux2_ctrl; }; +extern void __iomem *l2x0_base; +extern u32 l2x0_way_mask;/* Bitmask of active ways */ extern struct l2x0_regs l2x0_saved_regs;#endif /* __ASSEMBLY__ */
arch/arm/mm/cache-l2x0-pmu.c +3 -6
@@ -29,11 +29,10 @@#define PMU_NR_COUNTERS 2 -static void __iomem *l2x0_base;static struct pmu *l2x0_pmu;static cpumask_t pmu_cpu; -static const char *l2x0_name; +static const char *__initdata l2x0_name =NULL ;static ktime_t l2x0_pmu_poll_period;static struct hrtimer l2x0_pmu_hrtimer;
@@ -491,7 +490,7 @@ void l2x0_pmu_resume(void)l2x0_pmu_enable (l2x0_pmu); } -void __init l2x0_pmu_register (void __iomem *base,u32 part) +void __init l2x0_pmu_register (u32 part) {/* * Determine whether we support the PMU, and choose the name for sysfs.
@@ -516,15 +515,13 @@ void __init l2x0_pmu_register(void __iomem *base, u32 part)default :return ; } - - l2x0_base = base; }static __init int l2x0_pmu_init (void ) {int ret; -if (!l2x0_base) +if (!l2x0_name)return 0 ; l2x0_pmu =kzalloc (sizeof (*l2x0_pmu),GFP_KERNEL );
arch/arm/mm/cache-l2x0.c +3 -3
@@ -48,13 +48,13 @@ struct l2c_init_data {#define CACHE_LINE_SIZE 32 -static void __iomem *l2x0_base;static const struct l2c_init_data *l2x0_data;static DEFINE_RAW_SPINLOCK (l2x0_lock); -static u32 l2x0_way_mask;/* Bitmask of active ways */ static u32 l2x0_size;static unsigned long sync_reg_offset =L2X0_CACHE_SYNC ; +void __iomem *l2x0_base; +u32 l2x0_way_mask;/* Bitmask of active ways */ struct l2x0_regs l2x0_saved_regs;static bool l2x0_bresp_disable;
@@ -900,7 +900,7 @@ static int __init __l2c_init(const struct l2c_init_data *data,pr_info ("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n" , data->type, cache_id, aux); -l2x0_pmu_register (l2x0_base, cache_id); +l2x0_pmu_register (cache_id);return 0 ; }
Signature · 1 line
2.19.1
PATCH 2/3 ARM: trusted_foundations: enable L2x0 cache via firmware_ops
In reply to Michał MirosławUse firmware_ops to provide hook for cache initialization through Trusted Foundations firmware, as some writes need Secure mode.
Avoid l2x0_base conflict (duplication) with PMU driver by sharing l2x0_name and using l2x0_name as the enable flag there.
--- arch/arm/firmware/trusted_foundations.c | 46 +++++++++++++++++++++++++ arch/arm/mm/cache-l2x0.c | 8 +++++ 2 files changed, 54 insertions(+)
arch/arm/firmware/trusted_foundations.c +46 -0
@@ -17,11 +17,19 @@#include <linux/kernel.h> #include <linux/init.h> #include <linux/of.h> +#include <asm/io.h> #include <asm/firmware.h> +#include <asm/outercache.h> +#include <asm/hardware/cache-l2x0.h> #include <asm/trusted_foundations.h> +#define TF_CACHE_MAINT 0xfffff100#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200 +#define TF_CACHE_INIT 1 +#define TF_CACHE_FLUSH 2 +#define TF_CACHE_REENABLE 4 +#define TF_CPU_PM 0xfffffffc#define TF_CPU_PM_S3 0xffffffe3#define TF_CPU_PM_S2 0xffffffe6
@@ -67,9 +75,47 @@ static int tf_prepare_idle(void)return 0 ; } +#ifdef CONFIG_CACHE_L2X0 +static void tf_write_sec (unsigned long val,unsigned reg) +{ +unsigned long cur =readl_relaxed (l2x0_base + reg); + +pr_warn ("TF: ignoring write_sec[0x%x]: 0x%08lx -> 0x%08lx\n" , reg, cur, val); +} + +static void tf_disable_cache (void ) +{ +tf_generic_smc (TF_CACHE_MAINT ,TF_CACHE_FLUSH , l2x0_way_mask); +} + +static void tf_resume_cache (void ) +{ +unsigned long aux_val =readl_relaxed (l2x0_base +L2X0_AUX_CTRL ); +tf_generic_smc (TF_CACHE_MAINT ,TF_CACHE_REENABLE , aux_val); +} + +static void tf_configure_cache (const struct l2x0_regs *regs) +{ + outer_cache.disable = tf_disable_cache; + outer_cache.resume = tf_resume_cache; +} + +static int tf_init_cache (void ) +{ +tf_generic_smc (TF_CACHE_MAINT ,TF_CACHE_INIT ,0 ); + + outer_cache.write_sec = tf_write_sec; + outer_cache.configure = tf_configure_cache; +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)
arch/arm/mm/cache-l2x0.c +8 -0
@@ -30,6 +30,7 @@#include <asm/cp15.h> #include <asm/cputype.h> #include <asm/hardware/cache-l2x0.h> +#include <asm/firmware.h> #include "cache-tauros3.h" #include "cache-aurora-l2.h"
@@ -37,6 +38,7 @@ struct l2c_init_data {const char *type;unsigned way_size_0;unsigned num_lock; +void (*init)(void __iomem *,u32 *,u32 *);void (*of_parse)(const struct device_node *,u32 *,u32 *);void (*enable)(void __iomem *,unsigned );void (*fixup)(void __iomem *,u32 ,struct outer_cache_fns *);
@@ -1760,6 +1762,7 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)u32 cache_id;u32 cache_level =2 ;bool nosync = false; +int err; np =of_find_matching_node (NULL , l2x0_ids);if (!np)
@@ -1792,6 +1795,11 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask) nosync =of_property_read_bool (np,"arm,outer-sync-disable" ); +/* Call firmware init */ + err =call_firmware_op (l2x0_init); +if (err && err != -ENOSYS ) +return err; +/* Read back current (default) hardware configuration */ if (data->save) data->save (l2x0_base);
Signature · 1 line
2.19.1
PATCH 3/3 ARM: trusted_foundations: announce firmware version
In reply to Michał MirosławAnnounce Trusted Foundations version for debugging and documentation.
--- arch/arm/firmware/trusted_foundations.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
arch/arm/firmware/trusted_foundations.c +18 -3
@@ -30,6 +30,8 @@#define TF_CACHE_FLUSH 2#define TF_CACHE_REENABLE 4 +#define TF_GET_PROTOCOL_VERSION 0xfffffffb +#define TF_CPU_PM 0xfffffffc#define TF_CPU_PM_S3 0xffffffe3#define TF_CPU_PM_S2 0xffffffe6
@@ -39,7 +41,7 @@static unsigned long cpu_boot_addr; -static void tf_generic_smc (u32 type,u32 arg1,u32 arg2) +static u64 tf_generic_smc (u32 type,u32 arg1,u32 arg2) { register u32 r0 asm("r0") = type; register u32 r1 asm("r1") = arg1;
@@ -55,9 +57,10 @@ static void tf_generic_smc(u32 type, u32 arg1, u32 arg2)"mov r4, #0\n\t" "smc #0\n\t" "ldmfd sp!, {r4 - r11}\n\t" - : - : "r" (r0), "r" (r1), "r" (r2) + : "+r" (r0), "+r" (r1) + : "r" (r2) : "memory", "r3", "r12", "lr"); + return ((u64 )r1 <<32 ) | r0; }static int tf_set_cpu_boot_addr (int cpu,unsigned long boot_addr)
@@ -110,6 +113,11 @@ static int tf_init_cache(void) }#endif /* CONFIG_CACHE_L2X0 */ +static u32 tf_get_protocol_version (void ) +{ +return tf_generic_smc (TF_GET_PROTOCOL_VERSION ,0 ,0 ) >>48 ; +} +static const struct firmware_ops trusted_foundations_ops = { .set_cpu_boot_addr = tf_set_cpu_boot_addr, .prepare_idle = tf_prepare_idle,
@@ -120,6 +128,12 @@ static const struct firmware_ops trusted_foundations_ops = {void register_trusted_foundations (struct trusted_foundations_platform_data *pd) { +unsigned int protocol =tf_get_protocol_version (); + +pr_info ("TF: version %u.%u, protocol %u.%u\n" , + pd->version_major, pd->version_minor, + protocol >>8 , protocol &0xFF ); +/* * we are not using version information for now since currently * supported SMCs are compatible with all TF releases
@@ -145,5 +159,6 @@ void of_register_trusted_foundations(void) &pdata.version_minor);if (err !=0 )panic ("Trusted Foundation: missing version-minor property\n" ); +register_trusted_foundations (&pdata); }
Signature · 1 line
2.19.1
cover ARM: tegra: enable SMP boot with TF
In reply to Michał MirosławThis patchset enables starting up all cores on Tegra3 with Trusted Foundations firmware. This is Tegra-specific part and depends on "ARM: enable cache via Trusted Foundations firmware" patchset sent earlier.
Micha? Miros?aw (2):
ARM: tegra: enable cache via TF
ARM: tegra: avoid touching Secure registers in reset handler
arch/arm/firmware/trusted_foundations.c | 6 +++-- arch/arm/include/asm/trusted_foundations.h | 6 +++-- arch/arm/mach-tegra/reset-handler.S | 27 +++++++++++++++++++++- arch/arm/mach-tegra/reset.c | 5 +++- arch/arm/mach-tegra/reset.h | 5 ++-- arch/arm/mach-tegra/tegra.c | 6 +++-- 6 files changed, 45 insertions(+), 10 deletions(-)
Signature · 1 line
2.19.1
PATCH 1/2 ARM: tegra: enable cache via TF
Cache enable needs to go via firmware call with TF running.
This version is based on code proposed by Dmitry Osipenko that uses run-time TF-presence instead of hardcoded in Kconfig.
--- arch/arm/firmware/trusted_foundations.c | 6 ++++-- arch/arm/include/asm/trusted_foundations.h | 6 ++++-- arch/arm/mach-tegra/reset-handler.S | 20 +++++++++++++++++++- arch/arm/mach-tegra/reset.c | 5 ++++- arch/arm/mach-tegra/reset.h | 5 +++-- arch/arm/mach-tegra/tegra.c | 6 ++++-- 6 files changed, 38 insertions(+), 10 deletions(-)
arch/arm/firmware/trusted_foundations.c +4 -2
@@ -141,7 +141,7 @@ void register_trusted_foundations(struct trusted_foundations_platform_data *pd)register_firmware_ops (&trusted_foundations_ops); } -void of_register_trusted_foundations (void ) +int of_register_trusted_foundations (void ) {struct device_node *node;struct trusted_foundations_platform_data pdata;
@@ -149,7 +149,7 @@ void of_register_trusted_foundations(void) node =of_find_compatible_node (NULL ,NULL ,"tlm,trusted-foundations" );if (!node) -return ; +return -ENOENT ; err =of_property_read_u32 (node,"tlm,version-major" , &pdata.version_major);
@@ -161,4 +161,6 @@ void of_register_trusted_foundations(void)panic ("Trusted Foundation: missing version-minor property\n" );register_trusted_foundations (&pdata); + +return 0 ; }
arch/arm/include/asm/trusted_foundations.h +4 -2
@@ -40,7 +40,7 @@ struct trusted_foundations_platform_data {#if IS_ENABLED (CONFIG_TRUSTED_FOUNDATIONS )void register_trusted_foundations (struct trusted_foundations_platform_data *pd); -void of_register_trusted_foundations (void ); +int of_register_trusted_foundations (void );#else /* CONFIG_TRUSTED_FOUNDATIONS */
@@ -59,7 +59,7 @@ static inline void register_trusted_foundations(cpu_idle_poll_ctrl (true); } -static inline void of_register_trusted_foundations (void ) +static inline int of_register_trusted_foundations (void ) {/* * If we find the target should enable TF but does not support it,
@@ -67,6 +67,8 @@ static inline void of_register_trusted_foundations(void)*/ if (of_find_compatible_node (NULL ,NULL ,"tlm,trusted-foundations" ))register_trusted_foundations (NULL ); + + return -ENOENT; }#endif /* CONFIG_TRUSTED_FOUNDATIONS */
arch/arm/mach-tegra/reset-handler.S +19 -1
@@ -78,8 +78,26 @@ ENTRY(tegra_resume) orr r1, r1, #1 str r1, [r0] #endif - #ifdef CONFIG_CACHE_L2X0 +#ifdef CONFIG_TRUSTED_FOUNDATIONS + adr r3, __tegra_cpu_reset_handler_data + ldr r0, [r3, #RESET_DATA(TF_PRESENT)] + cmp r0, #0 + beq ca9_scu_l2_resume + + push {r8} /* TF call might corrupt r4-r12 */ + + mov r0, #3 // local wake + mov r3, #0 + mov r4, #0 + dsb + .arch_extension sec + smc #0 + + pop {r8} + b end_ca9_scu_l2_resume +ca9_scu_l2_resume: +#endif /* L2 cache resume & re-enable */ bl l2c310_early_resume #endif
arch/arm/mach-tegra/reset.c +4 -1
@@ -18,6 +18,7 @@#include <linux/cpumask.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/of.h> #include <soc/tegra/fuse.h>
@@ -87,7 +88,7 @@ static void __init tegra_cpu_reset_handler_enable(void) } } -void __init tegra_cpu_reset_handler_init (void ) +void __init tegra_cpu_reset_handler_init (bool tf_present) {#ifdef CONFIG_SMP
@@ -104,5 +105,7 @@ void __init tegra_cpu_reset_handler_init(void)__pa_symbol ((void *)tegra_resume);#endif + __tegra_cpu_reset_handler_data[TEGRA_RESET_TF_PRESENT ] = tf_present; +tegra_cpu_reset_handler_enable (); }
arch/arm/mach-tegra/reset.h +3 -2
@@ -25,7 +25,8 @@#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_TF_PRESENT 6 +#define TEGRA_RESET_DATA_SIZE 7#ifndef __ASSEMBLY__
@@ -60,7 +61,7 @@ void __tegra_cpu_reset_handler_end(void); (__tegra_cpu_reset_handler_end - \ __tegra_cpu_reset_handler_start) -void __init tegra_cpu_reset_handler_init (void ); +void __init tegra_cpu_reset_handler_init (bool tf_present);#endif #endif
arch/arm/mach-tegra/tegra.c +4 -2
@@ -72,8 +72,10 @@ u32 tegra_uart_config[3] = {static void __init tegra_init_early (void ) { -of_register_trusted_foundations (); -tegra_cpu_reset_handler_init (); +bool tf_present; + + tf_present =of_register_trusted_foundations () ==0 ; +tegra_cpu_reset_handler_init (tf_present); }static void __init tegra_dt_init_irq (void )
Signature · 1 line
2.19.1
PATCH 2/2 ARM: tegra: avoid touching Secure registers in reset handler
In reply to Michał MirosławThis allows secondary CPUs to boot with Trusted Foundations firmware.
--- arch/arm/mach-tegra/reset-handler.S | 7 +++++++ 1 file changed, 7 insertions(+)
arch/arm/mach-tegra/reset-handler.S +7 -0
@@ -139,6 +139,13 @@ ENTRY(__tegra_cpu_reset_handler) cpsid aif, 0x13 @ SVC mode, interrupts disabled tegra_get_soc_id TEGRA_APB_MISC_BASE, r6 + +#ifdef CONFIG_TRUSTED_FOUNDATIONS + adr r3, __tegra_cpu_reset_handler_data + ldr r0, [r3, #RESET_DATA(TF_PRESENT)] + cmp r0, #0 + bne after_errata +#endif /* CONFIG_TRUSTED_FOUNDATIONS */ #ifdef CONFIG_ARCH_TEGRA_2x_SOC t20_check: cmp r6, #TEGRA20
Signature · 1 line
2.19.1
cover ARM: enable cache via Trusted Foundations firmware
In reply to Michał MirosławQuoted 8 lines · Micha? Miros?aw
This set enables platforms using Trusted Foundations firmware to use their L2 cache. L2 cache can be enabled only by calling the firmware.
Micha? Miros?aw (3):
ARM: cache-l2x0: sharel2x0_basewith PMU code
ARM:trusted_foundations: enable L2x0 cache viafirmware_ops
ARM:trusted_foundations: announce firmware version
Quoted 6 lines
arch/arm/firmware/trusted_foundations.c | 67 +++++++++++++++++++++- arch/arm/include/asm/hardware/cache-l2x0.h | 6 +- arch/arm/mm/cache-l2x0-pmu.c | 9 +-- arch/arm/mm/cache-l2x0.c | 14 ++++- 4 files changed, 82 insertions(+), 14 deletions(-)
Hello Micha?,
Very nice to see that you are keeping to work on it! Couple months ago I posted patches that add a full-featured Trusted Foundations support on Tegra30 [0] (including suspend-resume, thumb2 kernel, handling CONFIG_CACHE_L2X0=n), unfortunately they didn't get any attention yet. Could you please take a look and try out [0]? I've got everything working without touching arch/arm/mm/cache-l2x0* at all. Would be awesome if we could cooperate the efforts somehow, maybe that will also help to get more attention from the maintainers.
[0] https://patchwork.ozlabs.org/project/linux-tegra/list/?series=63339