plat_helpers.S 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * Copyright (c) 2015-2024, 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 <assert_macros.S>
  9. #include <platform_def.h>
  10. #include <cortex_a72.h>
  11. .globl plat_crash_console_flush
  12. .globl plat_crash_console_init
  13. .globl plat_crash_console_putc
  14. .globl platform_mem_init
  15. .globl plat_get_my_entrypoint
  16. .globl plat_is_my_cpu_primary
  17. .globl plat_my_core_pos
  18. .globl plat_reset_handler
  19. .globl plat_rpi3_calc_core_pos
  20. .globl plat_secondary_cold_boot_setup
  21. .globl plat_rpi_get_model
  22. /* -----------------------------------------------------
  23. * unsigned int plat_my_core_pos(void)
  24. *
  25. * This function uses the plat_rpi3_calc_core_pos()
  26. * definition to get the index of the calling CPU.
  27. *
  28. * When MT is set, lowest affinity represents the thread ID.
  29. * Since we only support one thread per core, discard this field
  30. * so cluster and core IDs go back into Aff1 and Aff0 respectively.
  31. * The upper bits are also affected, but plat_rpi3_calc_core_pos()
  32. * does not use them.
  33. * -----------------------------------------------------
  34. */
  35. func plat_my_core_pos
  36. mrs x0, mpidr_el1
  37. tst x0, #MPIDR_MT_MASK
  38. lsr x1, x0, #MPIDR_AFFINITY_BITS
  39. csel x0, x1, x0, ne
  40. b plat_rpi3_calc_core_pos
  41. endfunc plat_my_core_pos
  42. /* -----------------------------------------------------
  43. * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
  44. *
  45. * CorePos = (ClusterId * 4) + CoreId
  46. * -----------------------------------------------------
  47. */
  48. func plat_rpi3_calc_core_pos
  49. and x1, x0, #MPIDR_CPU_MASK
  50. and x0, x0, #MPIDR_CLUSTER_MASK
  51. add x0, x1, x0, LSR #6
  52. ret
  53. endfunc plat_rpi3_calc_core_pos
  54. /* -----------------------------------------------------
  55. * unsigned int plat_is_my_cpu_primary (void);
  56. *
  57. * Find out whether the current cpu is the primary
  58. * cpu.
  59. * -----------------------------------------------------
  60. */
  61. func plat_is_my_cpu_primary
  62. mrs x0, mpidr_el1
  63. and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
  64. cmp x0, #RPI_PRIMARY_CPU
  65. cset w0, eq
  66. ret
  67. endfunc plat_is_my_cpu_primary
  68. /* -----------------------------------------------------
  69. * void plat_wait_for_warm_boot (void);
  70. *
  71. * This function performs any platform specific actions
  72. * needed for a CPU to be put into holding pen to wait
  73. * for a warm boot request.
  74. * The function will never return.
  75. * -----------------------------------------------------
  76. */
  77. func plat_wait_for_warm_boot
  78. /*
  79. * Calculate address of our hold entry.
  80. * As the function will never return, there is no need to save LR.
  81. */
  82. bl plat_my_core_pos
  83. lsl x0, x0, #3
  84. mov_imm x2, PLAT_RPI3_TM_HOLD_BASE
  85. add x0, x0, x2
  86. /*
  87. * This code runs way before requesting the warmboot of this core,
  88. * so it is possible to clear the mailbox before getting a request
  89. * to boot.
  90. */
  91. mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
  92. str x1,[x0]
  93. /* Wait until we have a go */
  94. poll_mailbox:
  95. wfe
  96. ldr x1, [x0]
  97. cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO
  98. bne poll_mailbox
  99. /* Jump to the provided entrypoint */
  100. mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT
  101. ldr x1, [x0]
  102. br x1
  103. endfunc plat_wait_for_warm_boot
  104. /* -----------------------------------------------------
  105. * void plat_secondary_cold_boot_setup (void);
  106. *
  107. * This function performs any platform specific actions
  108. * needed for a secondary cpu after a cold reset e.g
  109. * mark the cpu's presence, mechanism to place it in a
  110. * holding pen etc.
  111. * -----------------------------------------------------
  112. */
  113. func plat_secondary_cold_boot_setup
  114. b plat_wait_for_warm_boot
  115. endfunc plat_secondary_cold_boot_setup
  116. /* ---------------------------------------------------------------------
  117. * uintptr_t plat_get_my_entrypoint (void);
  118. *
  119. * Main job of this routine is to distinguish between a cold and a warm
  120. * boot.
  121. *
  122. * This functions returns:
  123. * - 0 for a cold boot.
  124. * - Any other value for a warm boot.
  125. * ---------------------------------------------------------------------
  126. */
  127. func plat_get_my_entrypoint
  128. mov x1, x30
  129. bl plat_is_my_cpu_primary
  130. /*
  131. * Secondaries always cold boot.
  132. */
  133. cbz w0, 1f
  134. /*
  135. * Primaries warm boot if they are requested
  136. * to power off.
  137. */
  138. mov_imm x0, PLAT_RPI3_TM_HOLD_BASE
  139. ldr x0, [x0]
  140. cmp x0, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF
  141. adr x0, plat_wait_for_warm_boot
  142. csel x0, x0, xzr, eq
  143. ret x1
  144. 1: mov x0, #0
  145. ret x1
  146. endfunc plat_get_my_entrypoint
  147. /* ---------------------------------------------
  148. * void platform_mem_init (void);
  149. *
  150. * No need to carry out any memory initialization.
  151. * ---------------------------------------------
  152. */
  153. func platform_mem_init
  154. ret
  155. endfunc platform_mem_init
  156. /* ---------------------------------------------
  157. * int plat_crash_console_init(void)
  158. * Function to initialize the crash console
  159. * without a C Runtime to print crash report.
  160. * Clobber list : x0 - x3
  161. * ---------------------------------------------
  162. */
  163. func plat_crash_console_init
  164. mov_imm x0, PLAT_RPI_CRASH_UART_BASE
  165. #if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
  166. mov_imm x1, RPI4_PL011_UART_CLOCK
  167. mov_imm x2, PLAT_RPI_UART_BAUDRATE
  168. b console_pl011_core_init
  169. #else
  170. mov x1, xzr
  171. mov x2, xzr
  172. b console_16550_core_init
  173. #endif
  174. endfunc plat_crash_console_init
  175. /* ---------------------------------------------
  176. * int plat_crash_console_putc(int c)
  177. * Function to print a character on the crash
  178. * console without a C Runtime.
  179. * Clobber list : x1, x2
  180. * ---------------------------------------------
  181. */
  182. func plat_crash_console_putc
  183. mov_imm x1, PLAT_RPI_CRASH_UART_BASE
  184. #if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
  185. b console_pl011_core_putc
  186. #else
  187. b console_16550_core_putc
  188. #endif
  189. endfunc plat_crash_console_putc
  190. /* ---------------------------------------------
  191. * void plat_crash_console_flush()
  192. * Function to force a write of all buffered
  193. * data that hasn't been output.
  194. * Out : void.
  195. * Clobber list : x0, x1
  196. * ---------------------------------------------
  197. */
  198. func plat_crash_console_flush
  199. mov_imm x0, PLAT_RPI_CRASH_UART_BASE
  200. #if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
  201. b console_pl011_core_flush
  202. #else
  203. b console_16550_core_flush
  204. #endif
  205. endfunc plat_crash_console_flush
  206. /* ---------------------------------------------
  207. * int plat_rpi_get_model()
  208. * Macro to determine whether we are running on
  209. * a Raspberry Pi 3 or 4. Just checks the MIDR for
  210. * being either a Cortex-A72 or a Cortex-A53.
  211. * Out : return 4 if RPi4, 3 otherwise.
  212. * Clobber list : x0
  213. * ---------------------------------------------
  214. */
  215. .macro _plat_rpi_get_model
  216. mrs x0, midr_el1
  217. and x0, x0, #0xf0 /* Isolate low byte of part number */
  218. cmp w0, #0x80 /* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */
  219. mov w0, #3
  220. csinc w0, w0, w0, ne
  221. .endm
  222. func plat_rpi_get_model
  223. _plat_rpi_get_model
  224. ret
  225. endfunc plat_rpi_get_model
  226. /* ---------------------------------------------
  227. * void plat_reset_handler(void);
  228. * ---------------------------------------------
  229. */
  230. func plat_reset_handler
  231. /* L2 cache setup only needed on RPi4 */
  232. _plat_rpi_get_model
  233. cmp w0, #4
  234. b.ne 1f
  235. /* ------------------------------------------------
  236. * Set L2 read/write cache latency:
  237. * - L2 Data RAM latency: 3 cycles (0b010)
  238. * - L2 Data RAM setup: 1 cycle (bit 5)
  239. * ------------------------------------------------
  240. */
  241. mrs x0, CORTEX_A72_L2CTLR_EL1
  242. mov x1, #0x22
  243. orr x0, x0, x1
  244. msr CORTEX_A72_L2CTLR_EL1, x0
  245. isb
  246. 1:
  247. ret
  248. endfunc plat_reset_handler