diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-05-21 11:52:16 +0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-05-21 11:52:16 +0400 |
commit | e1b73cba13a0cc68dd4f746eced15bd6bb24cda4 (patch) | |
tree | b1c9e10730724024a700031ad56c20419dabb500 /Documentation/arm/firmware.txt | |
parent | 98304ad186296dc1e655399e28d5973c21db6a73 (diff) | |
parent | c7788792a5e7b0d5d7f96d0766b4cb6112d47d75 (diff) | |
download | linux-e1b73cba13a0cc68dd4f746eced15bd6bb24cda4.tar.xz |
Merge tag 'v3.10-rc2' into drm-intel-next-queued
Backmerge Linux 3.10-rc2 since the various (rather trivial) conflicts
grew a bit out of hand. intel_dp.c has the only real functional
conflict since the logic changed while dev_priv->edp.bpp was moved
around.
Also squash in a whitespace fixup from Ben Widawsky for
i915_gem_gtt.c, git seems to do something pretty strange in there
(which I don't fully understand tbh).
Conflicts:
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_dp.c
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'Documentation/arm/firmware.txt')
-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 @@ +Interface for registering and calling firmware-specific operations for ARM. +---- +Written by Tomasz Figa <t.figa@samsung.com> + +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); |