From 7366b92a77fc00357294819bb495896d7482f30c Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 11 Dec 2012 13:58:43 +0900 Subject: ARM: Add interface for registering and calling firmware-specific operations Some boards are running with secure firmware running in TrustZone secure world, which changes the way some things have to be initialized. This patch adds an interface for platforms to specify available firmware operations and call them. A wrapper macro, call_firmware_op(), checks if the operation is provided and calls it if so, otherwise returns -ENOSYS to allow fallback to legacy operation.. By default no operations are provided. Example of use: In code using firmware ops: __raw_writel(virt_to_phys(exynos4_secondary_startup), CPU1_BOOT_REG); /* Call Exynos specific smc call */ if (call_firmware_op(cpu_boot, cpu) == -ENOSYS) cpu_boot_legacy(...); /* Try legacy way */ gic_raise_softirq(cpumask_of(cpu), 1); In board-/platform-specific code: static int platformX_do_idle(void) { /* tell platformX firmware to enter idle */ return 0; } static int platformX_cpu_boot(int i) { /* tell platformX firmware to boot CPU i */ return 0; } static const struct firmware_ops platformX_firmware_ops = { .do_idle = exynos_do_idle, .cpu_boot = exynos_cpu_boot, /* other operations not available on platformX */ }; static void __init board_init_early(void) { register_firmware_ops(&platformX_firmware_ops); } Signed-off-by: Kyungmin Park Signed-off-by: Tomasz Figa Signed-off-by: Kukjin Kim --- Documentation/arm/firmware.txt | 88 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Documentation/arm/firmware.txt (limited to 'Documentation') diff --git a/Documentation/arm/firmware.txt b/Documentation/arm/firmware.txt new file mode 100644 index 000000000000..c2e468fe7b0b --- /dev/null +++ b/Documentation/arm/firmware.txt @@ -0,0 +1,88 @@ +Interface for registering and calling firmware-specific operations for ARM. +---- +Written by Tomasz Figa + +Some boards are running with secure firmware running in TrustZone secure +world, which changes the way some things have to be initialized. This makes +a need to provide an interface for such platforms to specify available firmware +operations and call them when needed. + +Firmware operations can be specified using struct firmware_ops + + struct firmware_ops { + /* + * Enters CPU idle mode + */ + int (*do_idle)(void); + /* + * Sets boot address of specified physical CPU + */ + int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr); + /* + * Boots specified physical CPU + */ + int (*cpu_boot)(int cpu); + /* + * Initializes L2 cache + */ + int (*l2x0_init)(void); + }; + +and then registered with register_firmware_ops function + + void register_firmware_ops(const struct firmware_ops *ops) + +the ops pointer must be non-NULL. + +There is a default, empty set of operations provided, so there is no need to +set anything if platform does not require firmware operations. + +To call a firmware operation, a helper macro is provided + + #define call_firmware_op(op, ...) \ + ((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS)) + +the macro checks if the operation is provided and calls it or otherwise returns +-ENOSYS to signal that given operation is not available (for example, to allow +fallback to legacy operation). + +Example of registering firmware operations: + + /* board file */ + + static int platformX_do_idle(void) + { + /* tell platformX firmware to enter idle */ + return 0; + } + + static int platformX_cpu_boot(int i) + { + /* tell platformX firmware to boot CPU i */ + return 0; + } + + static const struct firmware_ops platformX_firmware_ops = { + .do_idle = exynos_do_idle, + .cpu_boot = exynos_cpu_boot, + /* other operations not available on platformX */ + }; + + /* init_early callback of machine descriptor */ + static void __init board_init_early(void) + { + register_firmware_ops(&platformX_firmware_ops); + } + +Example of using a firmware operation: + + /* some platform code, e.g. SMP initialization */ + + __raw_writel(virt_to_phys(exynos4_secondary_startup), + CPU1_BOOT_REG); + + /* Call Exynos specific smc call */ + if (call_firmware_op(cpu_boot, cpu) == -ENOSYS) + cpu_boot_legacy(...); /* Try legacy way */ + + gic_raise_softirq(cpumask_of(cpu), 1); -- cgit v1.2.3 From bca28f8f6b93fc1fb000d8695e59266d307aceab Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 11 Dec 2012 13:58:43 +0900 Subject: ARM: EXYNOS: Add support for Exynos secure firmware Some Exynos-based boards contain secure firmware and must use firmware operations to set up some hardware. This patch adds firmware operations for Exynos secure firmware and a way for board code and device tree to specify that they must be used. Example of use: In board code: ...MACHINE_START(...) /* ... */ .init_early = exynos_firmware_init, /* ... */ MACHINE_END In device tree: / { /* ... */ firmware@0203F000 { compatible = "samsung,secure-firmware"; reg = <0x0203F000 0x1000>; }; /* ... */ }; Signed-off-by: Kyungmin Park Signed-off-by: Tomasz Figa Signed-off-by: Kukjin Kim --- .../devicetree/bindings/arm/samsung-boards.txt | 10 ++++ arch/arm/mach-exynos/Makefile | 1 + arch/arm/mach-exynos/common.h | 2 + arch/arm/mach-exynos/firmware.c | 70 ++++++++++++++++++++++ arch/arm/mach-exynos/mach-exynos4-dt.c | 1 + 5 files changed, 84 insertions(+) create mode 100644 arch/arm/mach-exynos/firmware.c (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung-boards.txt index 0bf68be56fd1..2168ed31e1b0 100644 --- a/Documentation/devicetree/bindings/arm/samsung-boards.txt +++ b/Documentation/devicetree/bindings/arm/samsung-boards.txt @@ -6,3 +6,13 @@ Required root node properties: - compatible = should be one or more of the following. (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board. (b) "samsung,exynos4210" - for boards based on Exynos4210 SoC. + +Optional: + - firmware node, specifying presence and type of secure firmware: + - compatible: only "samsung,secure-firmware" is currently supported + - reg: address of non-secure SYSRAM used for communication with firmware + + firmware@0203F000 { + compatible = "samsung,secure-firmware"; + reg = <0x0203F000 0x1000>; + }; diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 5567bf7d04ba..b09b027178f3 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_ARCH_EXYNOS) += exynos-smc.o +obj-$(CONFIG_ARCH_EXYNOS) += firmware.o plus_sec := $(call as-instr,.arch_extension sec,+sec) AFLAGS_exynos-smc.o :=-Wa,-march=armv7-a$(plus_sec) diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index cb89ab886950..b17448c1a164 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -30,6 +30,8 @@ void exynos_init_late(void); void exynos4_clk_init(struct device_node *np); void exynos4_clk_register_fixed_ext(unsigned long, unsigned long); +void exynos_firmware_init(void); + #ifdef CONFIG_PM_GENERIC_DOMAINS int exynos_pm_late_initcall(void); #else diff --git a/arch/arm/mach-exynos/firmware.c b/arch/arm/mach-exynos/firmware.c new file mode 100644 index 000000000000..ed11f100d479 --- /dev/null +++ b/arch/arm/mach-exynos/firmware.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 Samsung Electronics. + * Kyungmin Park + * Tomasz Figa + * + * This program is free software,you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include "smc.h" + +static int exynos_do_idle(void) +{ + exynos_smc(SMC_CMD_SLEEP, 0, 0, 0); + return 0; +} + +static int exynos_cpu_boot(int cpu) +{ + exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0); + return 0; +} + +static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr) +{ + void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu; + + __raw_writel(boot_addr, boot_reg); + return 0; +} + +static const struct firmware_ops exynos_firmware_ops = { + .do_idle = exynos_do_idle, + .set_cpu_boot_addr = exynos_set_cpu_boot_addr, + .cpu_boot = exynos_cpu_boot, +}; + +void __init exynos_firmware_init(void) +{ + if (of_have_populated_dt()) { + struct device_node *nd; + const __be32 *addr; + + nd = of_find_compatible_node(NULL, NULL, + "samsung,secure-firmware"); + if (!nd) + return; + + addr = of_get_address(nd, 0, NULL, NULL); + if (!addr) { + pr_err("%s: No address specified.\n", __func__); + return; + } + } + + pr_info("Running under secure firmware.\n"); + + register_firmware_ops(&exynos_firmware_ops); +} diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index ac27f3cd121f..b9ed834a7eee 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -57,6 +57,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)") .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = exynos4_dt_map_io, + .init_early = exynos_firmware_init, .init_machine = exynos4_dt_machine_init, .init_late = exynos_init_late, .init_time = exynos_init_time, -- cgit v1.2.3 From 7f6c62e2695bcb1547afdeb4ad3bcdf8c610be2c Mon Sep 17 00:00:00 2001 From: Christian Daudt Date: Wed, 13 Mar 2013 15:05:37 -0700 Subject: ARM: bcm281xx: Add DT support for SMC handler - Adds devicetree binding and documentation for the smc handler Updates from V1: - Created this separate patch for the DT portion - Added SoC compatible to smc binding Signed-off-by: Christian Daudt Acked-by: Arnd Bergmann --- Documentation/devicetree/bindings/misc/smc.txt | 14 ++++++++++++++ arch/arm/boot/dts/bcm11351.dtsi | 5 +++++ 2 files changed, 19 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/smc.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/misc/smc.txt b/Documentation/devicetree/bindings/misc/smc.txt new file mode 100644 index 000000000000..02b428136177 --- /dev/null +++ b/Documentation/devicetree/bindings/misc/smc.txt @@ -0,0 +1,14 @@ +Broadcom Secure Monitor Bounce buffer +----------------------------------------------------- +This binding defines the location of the bounce buffer +used for non-secure to secure communications. + +Required properties: +- compatible : "bcm,kona-smc" +- reg : Location and size of bounce buffer + +Example: + smc@0x3404c000 { + compatible = "bcm,bcm11351-smc", "bcm,kona-smc"; + reg = <0x3404c000 0x400>; //1 KiB in SRAM + }; diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi index ad135885bd2a..be2a26132376 100644 --- a/arch/arm/boot/dts/bcm11351.dtsi +++ b/arch/arm/boot/dts/bcm11351.dtsi @@ -31,6 +31,11 @@ <0x3ff00100 0x100>; }; + smc@0x3404c000 { + compatible = "bcm,bcm11351-smc", "bcm,kona-smc"; + reg = <0x3404c000 0x400>; //1 KiB in SRAM + }; + uart@3e000000 { compatible = "bcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart"; status = "disabled"; -- cgit v1.2.3