firmware.txt 2.3 KB

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