psci.S 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright 2015 Freescale Semiconductor, Inc.
  3. * Author: Wang Dongsheng <dongsheng.wang@freescale.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <config.h>
  8. #include <linux/linkage.h>
  9. #include <asm/armv7.h>
  10. #include <asm/arch-armv7/generictimer.h>
  11. #include <asm/psci.h>
  12. #define SCFG_CORE0_SFT_RST 0x130
  13. #define SCFG_CORESRENCR 0x204
  14. #define DCFG_CCSR_BRR 0x0E4
  15. #define DCFG_CCSR_SCRATCHRW1 0x200
  16. .pushsection ._secure.text, "ax"
  17. .arch_extension sec
  18. #define ONE_MS (GENERIC_TIMER_CLK / 1000)
  19. #define RESET_WAIT (30 * ONE_MS)
  20. @ r0: return value ARM_PSCI_RET_SUCCESS or ARM_PSCI_RET_INVAL
  21. @ r1: input target CPU ID in MPIDR format, original value in r1 may be dropped
  22. @ r4: output validated CPU ID if ARM_PSCI_RET_SUCCESS returns, meaningless for
  23. @ ARM_PSCI_RET_INVAL,suppose caller saves r4 before calling
  24. LENTRY(psci_check_target_cpu_id)
  25. @ Get the real CPU number
  26. and r4, r1, #0xff
  27. mov r0, #ARM_PSCI_RET_INVAL
  28. @ Bit[31:24], bits must be zero.
  29. tst r1, #0xff000000
  30. bxne lr
  31. @ Affinity level 2 - Cluster: only one cluster in LS1021xa.
  32. tst r1, #0xff0000
  33. bxne lr
  34. @ Affinity level 1 - Processors: should be in 0xf00 format.
  35. lsr r1, r1, #8
  36. teq r1, #0xf
  37. bxne lr
  38. @ Affinity level 0 - CPU: only 0, 1 are valid in LS1021xa.
  39. cmp r4, #2
  40. bxge lr
  41. mov r0, #ARM_PSCI_RET_SUCCESS
  42. bx lr
  43. ENDPROC(psci_check_target_cpu_id)
  44. @ r1 = target CPU
  45. @ r2 = target PC
  46. .globl psci_cpu_on
  47. psci_cpu_on:
  48. push {r4, r5, r6, lr}
  49. @ Clear and Get the correct CPU number
  50. @ r1 = 0xf01
  51. bl psci_check_target_cpu_id
  52. cmp r0, #ARM_PSCI_RET_INVAL
  53. beq out_psci_cpu_on
  54. mov r0, r4
  55. mov r1, r2
  56. bl psci_save_target_pc
  57. mov r1, r4
  58. @ Get DCFG base address
  59. movw r4, #(CONFIG_SYS_FSL_GUTS_ADDR & 0xffff)
  60. movt r4, #(CONFIG_SYS_FSL_GUTS_ADDR >> 16)
  61. @ Detect target CPU state
  62. ldr r2, [r4, #DCFG_CCSR_BRR]
  63. rev r2, r2
  64. lsr r2, r2, r1
  65. ands r2, r2, #1
  66. beq holdoff_release
  67. @ Reset target CPU
  68. @ Get SCFG base address
  69. movw r0, #(CONFIG_SYS_FSL_SCFG_ADDR & 0xffff)
  70. movt r0, #(CONFIG_SYS_FSL_SCFG_ADDR >> 16)
  71. @ Enable CORE Soft Reset
  72. movw r5, #0
  73. movt r5, #(1 << 15)
  74. rev r5, r5
  75. str r5, [r0, #SCFG_CORESRENCR]
  76. @ Get CPUx offset register
  77. mov r6, #0x4
  78. mul r6, r6, r1
  79. add r2, r0, r6
  80. @ Do reset on target CPU
  81. movw r5, #0
  82. movt r5, #(1 << 15)
  83. rev r5, r5
  84. str r5, [r2, #SCFG_CORE0_SFT_RST]
  85. @ Wait target CPU up
  86. timer_wait r2, RESET_WAIT
  87. @ Disable CORE soft reset
  88. mov r5, #0
  89. str r5, [r0, #SCFG_CORESRENCR]
  90. holdoff_release:
  91. @ Release on target CPU
  92. ldr r2, [r4, #DCFG_CCSR_BRR]
  93. mov r6, #1
  94. lsl r6, r6, r1 @ 32 bytes per CPU
  95. rev r6, r6
  96. orr r2, r2, r6
  97. str r2, [r4, #DCFG_CCSR_BRR]
  98. @ Set secondary boot entry
  99. ldr r6, =psci_cpu_entry
  100. rev r6, r6
  101. str r6, [r4, #DCFG_CCSR_SCRATCHRW1]
  102. isb
  103. dsb
  104. @ Return
  105. mov r0, #ARM_PSCI_RET_SUCCESS
  106. out_psci_cpu_on:
  107. pop {r4, r5, r6, lr}
  108. bx lr
  109. .globl psci_cpu_off
  110. psci_cpu_off:
  111. bl psci_cpu_off_common
  112. 1: wfi
  113. b 1b
  114. .popsection