blob: da6713adac8acffc5924d447473351ab84c2d289 [file] [log] [blame]
Tomasz Figa7366b922012-12-11 13:58:43 +09001Interface for registering and calling firmware-specific operations for ARM.
2----
3Written by Tomasz Figa <t.figa@samsung.com>
4
5Some boards are running with secure firmware running in TrustZone secure
6world, which changes the way some things have to be initialized. This makes
7a need to provide an interface for such platforms to specify available firmware
8operations and call them when needed.
9
Tomasz Figa9c261f82014-09-24 01:24:35 +090010Firmware operations can be specified by filling in a struct firmware_ops
11with appropriate callbacks and then registering it with register_firmware_ops()
12function.
Tomasz Figa7366b922012-12-11 13:58:43 +090013
14 void register_firmware_ops(const struct firmware_ops *ops)
15
Tomasz Figa9c261f82014-09-24 01:24:35 +090016The ops pointer must be non-NULL. More information about struct firmware_ops
17and its members can be found in arch/arm/include/asm/firmware.h header.
Tomasz Figa7366b922012-12-11 13:58:43 +090018
19There is a default, empty set of operations provided, so there is no need to
20set anything if platform does not require firmware operations.
21
22To call a firmware operation, a helper macro is provided
23
24 #define call_firmware_op(op, ...) \
25 ((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS))
26
27the macro checks if the operation is provided and calls it or otherwise returns
28-ENOSYS to signal that given operation is not available (for example, to allow
29fallback to legacy operation).
30
31Example of registering firmware operations:
32
33 /* board file */
34
35 static int platformX_do_idle(void)
36 {
37 /* tell platformX firmware to enter idle */
38 return 0;
39 }
40
41 static int platformX_cpu_boot(int i)
42 {
43 /* tell platformX firmware to boot CPU i */
44 return 0;
45 }
46
47 static const struct firmware_ops platformX_firmware_ops = {
48 .do_idle = exynos_do_idle,
49 .cpu_boot = exynos_cpu_boot,
50 /* other operations not available on platformX */
51 };
52
53 /* init_early callback of machine descriptor */
54 static void __init board_init_early(void)
55 {
56 register_firmware_ops(&platformX_firmware_ops);
57 }
58
59Example of using a firmware operation:
60
61 /* some platform code, e.g. SMP initialization */
62
63 __raw_writel(virt_to_phys(exynos4_secondary_startup),
64 CPU1_BOOT_REG);
65
66 /* Call Exynos specific smc call */
67 if (call_firmware_op(cpu_boot, cpu) == -ENOSYS)
68 cpu_boot_legacy(...); /* Try legacy way */
69
70 gic_raise_softirq(cpumask_of(cpu), 1);