psci.S 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright (C) 2014, NVIDIA
  3. * Copyright (C) 2015, Siemens AG
  4. *
  5. * Authors:
  6. * Thierry Reding <treding@nvidia.com>
  7. * Jan Kiszka <jan.kiszka@siemens.com>
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. #include <linux/linkage.h>
  12. #include <asm/macro.h>
  13. #include <asm/psci.h>
  14. .pushsection ._secure.text, "ax"
  15. .arch_extension sec
  16. #define TEGRA_SB_CSR_0 0x6000c200
  17. #define NS_RST_VEC_WR_DIS (1 << 1)
  18. #define TEGRA_RESET_EXCEPTION_VECTOR 0x6000f100
  19. #define TEGRA_FLOW_CTRL_BASE 0x60007000
  20. #define FLOW_CTRL_CPU_CSR 0x08
  21. #define CSR_ENABLE (1 << 0)
  22. #define CSR_IMMEDIATE_WAKE (1 << 3)
  23. #define CSR_WAIT_WFI_SHIFT 8
  24. #define FLOW_CTRL_CPU1_CSR 0x18
  25. @ converts CPU ID into FLOW_CTRL_CPUn_CSR offset
  26. .macro get_csr_reg cpu, ofs, tmp
  27. cmp \cpu, #0 @ CPU0?
  28. lsl \tmp, \cpu, #3 @ multiple by 8 (register offset CPU1-3)
  29. moveq \ofs, #FLOW_CTRL_CPU_CSR
  30. addne \ofs, \tmp, #FLOW_CTRL_CPU1_CSR - 8
  31. .endm
  32. ENTRY(psci_arch_init)
  33. mov r6, lr
  34. mrc p15, 0, r5, c1, c1, 0 @ Read SCR
  35. bic r5, r5, #1 @ Secure mode
  36. mcr p15, 0, r5, c1, c1, 0 @ Write SCR
  37. isb
  38. @ lock reset vector for non-secure
  39. ldr r4, =TEGRA_SB_CSR_0
  40. ldr r5, [r4]
  41. orr r5, r5, #NS_RST_VEC_WR_DIS
  42. str r5, [r4]
  43. bl psci_get_cpu_id @ CPU ID => r0
  44. adr r5, _sys_clock_freq
  45. cmp r0, #0
  46. mrceq p15, 0, r7, c14, c0, 0 @ read CNTFRQ from CPU0
  47. streq r7, [r5]
  48. ldrne r7, [r5]
  49. mcrne p15, 0, r7, c14, c0, 0 @ write CNTFRQ to CPU1..3
  50. bl psci_get_cpu_stack_top @ stack top => r0
  51. mov sp, r0
  52. bx r6
  53. ENDPROC(psci_arch_init)
  54. _sys_clock_freq:
  55. .word 0
  56. ENTRY(psci_cpu_off)
  57. bl psci_cpu_off_common
  58. bl psci_get_cpu_id @ CPU ID => r0
  59. get_csr_reg r0, r2, r3
  60. ldr r6, =TEGRA_FLOW_CTRL_BASE
  61. mov r5, #(CSR_ENABLE)
  62. mov r4, #(1 << CSR_WAIT_WFI_SHIFT)
  63. add r5, r4, lsl r0
  64. str r5, [r6, r2]
  65. _loop: wfi
  66. b _loop
  67. ENDPROC(psci_cpu_off)
  68. ENTRY(psci_cpu_on)
  69. push {lr}
  70. mov r0, r1
  71. bl psci_get_cpu_stack_top @ get stack top of target CPU
  72. str r2, [r0] @ store target PC at stack top
  73. dsb
  74. ldr r6, =TEGRA_RESET_EXCEPTION_VECTOR
  75. ldr r5, =psci_cpu_entry
  76. str r5, [r6]
  77. get_csr_reg r1, r2, r3
  78. ldr r6, =TEGRA_FLOW_CTRL_BASE
  79. mov r5, #(CSR_IMMEDIATE_WAKE | CSR_ENABLE)
  80. str r5, [r6, r2]
  81. mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS
  82. pop {pc}
  83. ENDPROC(psci_cpu_on)
  84. .globl psci_text_end
  85. psci_text_end:
  86. .popsection