diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-04 15:33:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-04 15:33:36 -0400 |
commit | e3d98847ded1d183111ff7c4d1ef56b161c7f13e (patch) | |
tree | 8ec2b298eef4f1695ca612014b7f75b85badae45 /Documentation/arm | |
parent | 22b154365fbc096a46d936ec1f462ef8b9bd1f05 (diff) | |
parent | 721e0205b07589223343737a9c421d8118d87bba (diff) |
Merge tag 'firmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM platform specific firmware interfaces from Olof Johansson:
"Two platforms, bcm and exynos have their own firmware interfaces using
the "secure monitor call", this adds support for those.
We had originally planned to have a third set of patches in here,
which would extend support for the existing generic "psci" call that
is used on multiple platforms as well as Xen and KVM guests, but that
ended up getting dropped because the patches were not ready in time."
* tag 'firmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc:
ARM: bcm: mark bcm_kona_smc_init as __init
ARM: bcm281xx: Add DT support for SMC handler
ARM: bcm281xx: Add L2 cache enable code
ARM: EXYNOS: Add secure firmware support to secondary CPU bring-up
ARM: EXYNOS: Add IO mapping for non-secure SYSRAM.
ARM: EXYNOS: Add support for Exynos secure firmware
ARM: EXYNOS: Add support for secure monitor calls
ARM: Add interface for registering and calling firmware-specific operations
Diffstat (limited to 'Documentation/arm')
-rw-r--r-- | Documentation/arm/firmware.txt | 88 |
1 files changed, 88 insertions, 0 deletions
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 @@ | |||
1 | Interface for registering and calling firmware-specific operations for ARM. | ||
2 | ---- | ||
3 | Written by Tomasz Figa <t.figa@samsung.com> | ||
4 | |||
5 | Some boards are running with secure firmware running in TrustZone secure | ||
6 | world, which changes the way some things have to be initialized. This makes | ||
7 | a need to provide an interface for such platforms to specify available firmware | ||
8 | operations and call them when needed. | ||
9 | |||
10 | Firmware operations can be specified using struct firmware_ops | ||
11 | |||
12 | struct firmware_ops { | ||
13 | /* | ||
14 | * Enters CPU idle mode | ||
15 | */ | ||
16 | int (*do_idle)(void); | ||
17 | /* | ||
18 | * Sets boot address of specified physical CPU | ||
19 | */ | ||
20 | int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr); | ||
21 | /* | ||
22 | * Boots specified physical CPU | ||
23 | */ | ||
24 | int (*cpu_boot)(int cpu); | ||
25 | /* | ||
26 | * Initializes L2 cache | ||
27 | */ | ||
28 | int (*l2x0_init)(void); | ||
29 | }; | ||
30 | |||
31 | and then registered with register_firmware_ops function | ||
32 | |||
33 | void register_firmware_ops(const struct firmware_ops *ops) | ||
34 | |||
35 | the ops pointer must be non-NULL. | ||
36 | |||
37 | There is a default, empty set of operations provided, so there is no need to | ||
38 | set anything if platform does not require firmware operations. | ||
39 | |||
40 | To call a firmware operation, a helper macro is provided | ||
41 | |||
42 | #define call_firmware_op(op, ...) \ | ||
43 | ((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS)) | ||
44 | |||
45 | the macro checks if the operation is provided and calls it or otherwise returns | ||
46 | -ENOSYS to signal that given operation is not available (for example, to allow | ||
47 | fallback to legacy operation). | ||
48 | |||
49 | Example of registering firmware operations: | ||
50 | |||
51 | /* board file */ | ||
52 | |||
53 | static int platformX_do_idle(void) | ||
54 | { | ||
55 | /* tell platformX firmware to enter idle */ | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int platformX_cpu_boot(int i) | ||
60 | { | ||
61 | /* tell platformX firmware to boot CPU i */ | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static const struct firmware_ops platformX_firmware_ops = { | ||
66 | .do_idle = exynos_do_idle, | ||
67 | .cpu_boot = exynos_cpu_boot, | ||
68 | /* other operations not available on platformX */ | ||
69 | }; | ||
70 | |||
71 | /* init_early callback of machine descriptor */ | ||
72 | static void __init board_init_early(void) | ||
73 | { | ||
74 | register_firmware_ops(&platformX_firmware_ops); | ||
75 | } | ||
76 | |||
77 | Example of using a firmware operation: | ||
78 | |||
79 | /* some platform code, e.g. SMP initialization */ | ||
80 | |||
81 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | ||
82 | CPU1_BOOT_REG); | ||
83 | |||
84 | /* Call Exynos specific smc call */ | ||
85 | if (call_firmware_op(cpu_boot, cpu) == -ENOSYS) | ||
86 | cpu_boot_legacy(...); /* Try legacy way */ | ||
87 | |||
88 | gic_raise_softirq(cpumask_of(cpu), 1); | ||