lowlevel.S 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * (C) Copyright 2014 Freescale Semiconductor
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. *
  6. * Extracted from armv8/start.S
  7. */
  8. #include <config.h>
  9. #include <linux/linkage.h>
  10. #include <asm/gic.h>
  11. #include <asm/macro.h>
  12. #include "mp.h"
  13. ENTRY(lowlevel_init)
  14. mov x29, lr /* Save LR */
  15. /* Set the SMMU page size in the sACR register */
  16. ldr x1, =SMMU_BASE
  17. ldr w0, [x1, #0x10]
  18. orr w0, w0, #1 << 16 /* set sACR.pagesize to indicate 64K page */
  19. str w0, [x1, #0x10]
  20. /* Initialize GIC Secure Bank Status */
  21. #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
  22. branch_if_slave x0, 1f
  23. ldr x0, =GICD_BASE
  24. bl gic_init_secure
  25. 1:
  26. #ifdef CONFIG_GICV3
  27. ldr x0, =GICR_BASE
  28. bl gic_init_secure_percpu
  29. #elif defined(CONFIG_GICV2)
  30. ldr x0, =GICD_BASE
  31. ldr x1, =GICC_BASE
  32. bl gic_init_secure_percpu
  33. #endif
  34. #endif
  35. branch_if_master x0, x1, 2f
  36. ldr x0, =secondary_boot_func
  37. blr x0
  38. 2:
  39. mov lr, x29 /* Restore LR */
  40. ret
  41. ENDPROC(lowlevel_init)
  42. /* Keep literals not used by the secondary boot code outside it */
  43. .ltorg
  44. /* Using 64 bit alignment since the spin table is accessed as data */
  45. .align 4
  46. .global secondary_boot_code
  47. /* Secondary Boot Code starts here */
  48. secondary_boot_code:
  49. .global __spin_table
  50. __spin_table:
  51. .space CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE
  52. .align 2
  53. ENTRY(secondary_boot_func)
  54. /*
  55. * MPIDR_EL1 Fields:
  56. * MPIDR[1:0] = AFF0_CPUID <- Core ID (0,1)
  57. * MPIDR[7:2] = AFF0_RES
  58. * MPIDR[15:8] = AFF1_CLUSTERID <- Cluster ID (0,1,2,3)
  59. * MPIDR[23:16] = AFF2_CLUSTERID
  60. * MPIDR[24] = MT
  61. * MPIDR[29:25] = RES0
  62. * MPIDR[30] = U
  63. * MPIDR[31] = ME
  64. * MPIDR[39:32] = AFF3
  65. *
  66. * Linear Processor ID (LPID) calculation from MPIDR_EL1:
  67. * (We only use AFF0_CPUID and AFF1_CLUSTERID for now
  68. * until AFF2_CLUSTERID and AFF3 have non-zero values)
  69. *
  70. * LPID = MPIDR[15:8] | MPIDR[1:0]
  71. */
  72. mrs x0, mpidr_el1
  73. ubfm x1, x0, #8, #15
  74. ubfm x2, x0, #0, #1
  75. orr x10, x2, x1, lsl #2 /* x10 has LPID */
  76. ubfm x9, x0, #0, #15 /* x9 contains MPIDR[15:0] */
  77. /*
  78. * offset of the spin table element for this core from start of spin
  79. * table (each elem is padded to 64 bytes)
  80. */
  81. lsl x1, x10, #6
  82. ldr x0, =__spin_table
  83. /* physical address of this cpus spin table element */
  84. add x11, x1, x0
  85. str x9, [x11, #16] /* LPID */
  86. mov x4, #1
  87. str x4, [x11, #8] /* STATUS */
  88. dsb sy
  89. #if defined(CONFIG_GICV3)
  90. gic_wait_for_interrupt_m x0
  91. #elif defined(CONFIG_GICV2)
  92. ldr x0, =GICC_BASE
  93. gic_wait_for_interrupt_m x0, w1
  94. #endif
  95. bl secondary_switch_to_el2
  96. #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
  97. bl secondary_switch_to_el1
  98. #endif
  99. slave_cpu:
  100. wfe
  101. ldr x0, [x11]
  102. cbz x0, slave_cpu
  103. #ifndef CONFIG_ARMV8_SWITCH_TO_EL1
  104. mrs x1, sctlr_el2
  105. #else
  106. mrs x1, sctlr_el1
  107. #endif
  108. tbz x1, #25, cpu_is_le
  109. rev x0, x0 /* BE to LE conversion */
  110. cpu_is_le:
  111. br x0 /* branch to the given address */
  112. ENDPROC(secondary_boot_func)
  113. ENTRY(secondary_switch_to_el2)
  114. switch_el x0, 1f, 0f, 0f
  115. 0: ret
  116. 1: armv8_switch_to_el2_m x0
  117. ENDPROC(secondary_switch_to_el2)
  118. ENTRY(secondary_switch_to_el1)
  119. switch_el x0, 0f, 1f, 0f
  120. 0: ret
  121. 1: armv8_switch_to_el1_m x0, x1
  122. ENDPROC(secondary_switch_to_el1)
  123. /* Ensure that the literals used by the secondary boot code are
  124. * assembled within it (this is required so that we can protect
  125. * this area with a single memreserve region
  126. */
  127. .ltorg
  128. /* 64 bit alignment for elements accessed as data */
  129. .align 4
  130. .globl __secondary_boot_code_size
  131. .type __secondary_boot_code_size, %object
  132. /* Secondary Boot Code ends here */
  133. __secondary_boot_code_size:
  134. .quad .-secondary_boot_code