fvp_helpers.S 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright (c) 2016-2017, 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 <drivers/arm/fvp/fvp_pwrc.h>
  9. #include <platform_def.h>
  10. .globl plat_secondary_cold_boot_setup
  11. .globl plat_get_my_entrypoint
  12. .globl plat_is_my_cpu_primary
  13. .globl plat_arm_calc_core_pos
  14. /* --------------------------------------------------------------------
  15. * void plat_secondary_cold_boot_setup (void);
  16. *
  17. * For AArch32, cold-booting secondary CPUs is not yet
  18. * implemented and they panic.
  19. * --------------------------------------------------------------------
  20. */
  21. func plat_secondary_cold_boot_setup
  22. cb_panic:
  23. b cb_panic
  24. endfunc plat_secondary_cold_boot_setup
  25. /* ---------------------------------------------------------------------
  26. * unsigned long plat_get_my_entrypoint (void);
  27. *
  28. * Main job of this routine is to distinguish between a cold and warm
  29. * boot. On FVP, this information can be queried from the power
  30. * controller. The Power Control SYS Status Register (PSYSR) indicates
  31. * the wake-up reason for the CPU.
  32. *
  33. * For a cold boot, return 0.
  34. * For a warm boot, read the mailbox and return the address it contains.
  35. *
  36. * TODO: PSYSR is a common register and should be
  37. * accessed using locks. Since it is not possible
  38. * to use locks immediately after a cold reset
  39. * we are relying on the fact that after a cold
  40. * reset all cpus will read the same WK field
  41. * ---------------------------------------------------------------------
  42. */
  43. func plat_get_my_entrypoint
  44. /* ---------------------------------------------------------------------
  45. * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
  46. * WakeRequest signal" then it is a warm boot.
  47. * ---------------------------------------------------------------------
  48. */
  49. ldcopr r2, MPIDR
  50. ldr r1, =PWRC_BASE
  51. str r2, [r1, #PSYSR_OFF]
  52. ldr r2, [r1, #PSYSR_OFF]
  53. ubfx r2, r2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
  54. cmp r2, #WKUP_PPONR
  55. beq warm_reset
  56. cmp r2, #WKUP_GICREQ
  57. beq warm_reset
  58. /* Cold reset */
  59. mov r0, #0
  60. bx lr
  61. warm_reset:
  62. /* ---------------------------------------------------------------------
  63. * A mailbox is maintained in the trusted SRAM. It is flushed out of the
  64. * caches after every update using normal memory so it is safe to read
  65. * it here with SO attributes.
  66. * ---------------------------------------------------------------------
  67. */
  68. ldr r0, =PLAT_ARM_TRUSTED_MAILBOX_BASE
  69. ldr r0, [r0]
  70. cmp r0, #0
  71. beq _panic
  72. bx lr
  73. /* ---------------------------------------------------------------------
  74. * The power controller indicates this is a warm reset but the mailbox
  75. * is empty. This should never happen!
  76. * ---------------------------------------------------------------------
  77. */
  78. _panic:
  79. b _panic
  80. endfunc plat_get_my_entrypoint
  81. /* -----------------------------------------------------
  82. * unsigned int plat_is_my_cpu_primary (void);
  83. *
  84. * Find out whether the current cpu is the primary
  85. * cpu.
  86. * -----------------------------------------------------
  87. */
  88. func plat_is_my_cpu_primary
  89. ldcopr r0, MPIDR
  90. ldr r1, =MPIDR_AFFINITY_MASK
  91. and r0, r1
  92. cmp r0, #FVP_PRIMARY_CPU
  93. moveq r0, #1
  94. movne r0, #0
  95. bx lr
  96. endfunc plat_is_my_cpu_primary
  97. /* ---------------------------------------------------------------------
  98. * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
  99. *
  100. * Function to calculate the core position on FVP.
  101. *
  102. * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
  103. * (CPUId * FVP_MAX_PE_PER_CPU) +
  104. * ThreadId
  105. *
  106. * which can be simplified as:
  107. *
  108. * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
  109. * + ThreadId
  110. * ---------------------------------------------------------------------
  111. */
  112. func plat_arm_calc_core_pos
  113. mov r3, r0
  114. /*
  115. * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
  116. * look as if in a multi-threaded implementation
  117. */
  118. tst r0, #MPIDR_MT_MASK
  119. lsleq r3, r0, #MPIDR_AFFINITY_BITS
  120. /* Extract individual affinity fields from MPIDR */
  121. ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
  122. ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
  123. ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
  124. /* Compute linear position */
  125. mov r3, #FVP_MAX_CPUS_PER_CLUSTER
  126. mla r1, r2, r3, r1
  127. mov r3, #FVP_MAX_PE_PER_CPU
  128. mla r0, r1, r3, r0
  129. bx lr
  130. endfunc plat_arm_calc_core_pos