fpga_helpers.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <arch.h>
  7. #include <asm_macros.S>
  8. #include <common/bl_common.h>
  9. #include "../fpga_private.h"
  10. #include <platform_def.h>
  11. .globl plat_get_my_entrypoint
  12. .globl plat_secondary_cold_boot_setup
  13. .globl plat_is_my_cpu_primary
  14. .globl platform_mem_init
  15. .globl plat_my_core_pos
  16. .globl plat_crash_console_init
  17. .globl plat_crash_console_putc
  18. .globl plat_crash_console_flush
  19. .globl plat_fpga_calc_core_pos
  20. /* -----------------------------------------------------------------------
  21. * Indicate a cold boot for every CPU - warm boot is unsupported for the
  22. * holding pen PSCI implementation.
  23. * -----------------------------------------------------------------------
  24. */
  25. func plat_get_my_entrypoint
  26. mov x0, #0
  27. ret
  28. endfunc plat_get_my_entrypoint
  29. /* -----------------------------------------------------------------------
  30. * void plat_secondary_cold_boot_setup (void);
  31. * -----------------------------------------------------------------------
  32. */
  33. func plat_secondary_cold_boot_setup
  34. /*
  35. * Wait for the primary processor to initialise the .BSS segment
  36. * to avoid a race condition that would erase fpga_valid_mpids
  37. * if it is populated before the C runtime is ready.
  38. *
  39. * We cannot use the current spin-lock implementation until the
  40. * runtime is up and we should not rely on sevl/wfe instructions as
  41. * it is optional whether they are implemented or not, so we use
  42. * a global variable as lock and wait for the primary processor to
  43. * finish the C runtime bring-up.
  44. */
  45. ldr w0, =C_RUNTIME_READY_KEY
  46. adrp x1, secondary_core_spinlock
  47. add x1, x1, :lo12:secondary_core_spinlock
  48. 1:
  49. wfe
  50. ldr w2, [x1]
  51. cmp w2, w0
  52. b.ne 1b
  53. /* Prevent reordering of the store into fpga_valid_mpids below */
  54. dmb ish
  55. mov x10, x30
  56. bl plat_my_core_pos
  57. mov x30, x10
  58. adrp x4, fpga_valid_mpids
  59. add x4, x4, :lo12:fpga_valid_mpids
  60. mov x5, #VALID_MPID
  61. strb w5, [x4, x0]
  62. /*
  63. * Poll the CPU's hold entry until it indicates to jump
  64. * to the entrypoint address.
  65. */
  66. adrp x1, hold_base
  67. add x1, x1, :lo12:hold_base
  68. poll_hold_entry:
  69. ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
  70. cmp x3, #PLAT_FPGA_HOLD_STATE_GO
  71. b.ne 1f
  72. adrp x2, fpga_sec_entrypoint
  73. add x2, x2, :lo12:fpga_sec_entrypoint
  74. ldr x3, [x2]
  75. br x3
  76. 1:
  77. wfe
  78. b poll_hold_entry
  79. endfunc plat_secondary_cold_boot_setup
  80. /* -----------------------------------------------------------------------
  81. * unsigned int plat_is_my_cpu_primary (void);
  82. *
  83. * Find out whether the current cpu is the primary cpu
  84. * -----------------------------------------------------------------------
  85. */
  86. func plat_is_my_cpu_primary
  87. mrs x0, mpidr_el1
  88. mov_imm x1, MPIDR_AFFINITY_MASK
  89. and x0, x0, x1
  90. cmp x0, #FPGA_PRIMARY_CPU
  91. cset w0, eq
  92. ret
  93. endfunc plat_is_my_cpu_primary
  94. func platform_mem_init
  95. ret
  96. endfunc platform_mem_init
  97. func plat_my_core_pos
  98. ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
  99. mrs x0, mpidr_el1
  100. and x0, x0, x1
  101. b plat_fpga_calc_core_pos
  102. endfunc plat_my_core_pos
  103. /* -----------------------------------------------------------------------
  104. * unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
  105. * Clobber registers: x0 to x5
  106. * -----------------------------------------------------------------------
  107. */
  108. func plat_fpga_calc_core_pos
  109. /*
  110. * Check for MT bit in MPIDR, which may be either value for images
  111. * running on the FPGA.
  112. *
  113. * If not set, shift MPIDR to left to make it look as if in a
  114. * multi-threaded implementation.
  115. *
  116. */
  117. tst x0, #MPIDR_MT_MASK
  118. lsl x3, x0, #MPIDR_AFFINITY_BITS
  119. csel x3, x3, x0, eq
  120. /* Extract individual affinity fields from MPIDR */
  121. ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
  122. ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
  123. ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
  124. mov x4, #FPGA_MAX_CPUS_PER_CLUSTER
  125. mov x5, #FPGA_MAX_PE_PER_CPU
  126. /* Compute linear position */
  127. madd x1, x2, x4, x1
  128. madd x0, x1, x5, x0
  129. ret
  130. endfunc plat_fpga_calc_core_pos
  131. func plat_crash_console_init
  132. mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
  133. b console_pl011_core_init
  134. endfunc plat_crash_console_init
  135. func plat_crash_console_putc
  136. mov_imm x1, PLAT_FPGA_CRASH_UART_BASE
  137. b console_pl011_core_putc
  138. endfunc plat_crash_console_putc
  139. func plat_crash_console_flush
  140. mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
  141. b console_pl011_core_flush
  142. endfunc plat_crash_console_flush