psci.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
  2. /*
  3. * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
  4. */
  5. #include <config.h>
  6. #include <common.h>
  7. #include <asm/armv7.h>
  8. #include <asm/gic.h>
  9. #include <asm/io.h>
  10. #include <asm/psci.h>
  11. #include <asm/secure.h>
  12. #define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0
  13. #define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1
  14. #define MPIDR_AFF0 GENMASK(7, 0)
  15. #define RCC_MP_GRSTCSETR (STM32_RCC_BASE + 0x0404)
  16. #define RCC_MP_GRSTCSETR_MPUP1RST BIT(5)
  17. #define RCC_MP_GRSTCSETR_MPUP0RST BIT(4)
  18. #define RCC_MP_GRSTCSETR_MPSYSRST BIT(0)
  19. #define STM32MP1_PSCI_NR_CPUS 2
  20. #if STM32MP1_PSCI_NR_CPUS > CONFIG_ARMV7_PSCI_NR_CPUS
  21. #error "invalid value for CONFIG_ARMV7_PSCI_NR_CPUS"
  22. #endif
  23. u8 psci_state[STM32MP1_PSCI_NR_CPUS] __secure_data = {
  24. PSCI_AFFINITY_LEVEL_ON,
  25. PSCI_AFFINITY_LEVEL_OFF};
  26. void __secure psci_set_state(int cpu, u8 state)
  27. {
  28. psci_state[cpu] = state;
  29. dsb();
  30. isb();
  31. }
  32. static u32 __secure stm32mp_get_gicd_base_address(void)
  33. {
  34. u32 periphbase;
  35. /* get the GIC base address from the CBAR register */
  36. asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase));
  37. return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET;
  38. }
  39. static void __secure stm32mp_smp_kick_all_cpus(void)
  40. {
  41. u32 gic_dist_addr;
  42. gic_dist_addr = stm32mp_get_gicd_base_address();
  43. /* kick all CPUs (except this one) by writing to GICD_SGIR */
  44. writel(1U << 24, gic_dist_addr + GICD_SGIR);
  45. }
  46. void __secure psci_arch_cpu_entry(void)
  47. {
  48. u32 cpu = psci_get_cpu_id();
  49. psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON);
  50. }
  51. int __secure psci_features(u32 function_id, u32 psci_fid)
  52. {
  53. switch (psci_fid) {
  54. case ARM_PSCI_0_2_FN_PSCI_VERSION:
  55. case ARM_PSCI_0_2_FN_CPU_OFF:
  56. case ARM_PSCI_0_2_FN_CPU_ON:
  57. case ARM_PSCI_0_2_FN_AFFINITY_INFO:
  58. case ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
  59. case ARM_PSCI_0_2_FN_SYSTEM_OFF:
  60. case ARM_PSCI_0_2_FN_SYSTEM_RESET:
  61. return 0x0;
  62. }
  63. return ARM_PSCI_RET_NI;
  64. }
  65. unsigned int __secure psci_version(u32 function_id)
  66. {
  67. return ARM_PSCI_VER_1_0;
  68. }
  69. int __secure psci_affinity_info(u32 function_id, u32 target_affinity,
  70. u32 lowest_affinity_level)
  71. {
  72. u32 cpu = target_affinity & MPIDR_AFF0;
  73. if (lowest_affinity_level > 0)
  74. return ARM_PSCI_RET_INVAL;
  75. if (target_affinity & ~MPIDR_AFF0)
  76. return ARM_PSCI_RET_INVAL;
  77. if (cpu >= STM32MP1_PSCI_NR_CPUS)
  78. return ARM_PSCI_RET_INVAL;
  79. return psci_state[cpu];
  80. }
  81. int __secure psci_migrate_info_type(u32 function_id)
  82. {
  83. /* Trusted OS is either not present or does not require migration */
  84. return 2;
  85. }
  86. int __secure psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc,
  87. u32 context_id)
  88. {
  89. u32 cpu = target_cpu & MPIDR_AFF0;
  90. if (target_cpu & ~MPIDR_AFF0)
  91. return ARM_PSCI_RET_INVAL;
  92. if (cpu >= STM32MP1_PSCI_NR_CPUS)
  93. return ARM_PSCI_RET_INVAL;
  94. if (psci_state[cpu] == PSCI_AFFINITY_LEVEL_ON)
  95. return ARM_PSCI_RET_ALREADY_ON;
  96. /* store target PC and context id*/
  97. psci_save(cpu, pc, context_id);
  98. /* write entrypoint in backup RAM register */
  99. writel((u32)&psci_cpu_entry, TAMP_BACKUP_BRANCH_ADDRESS);
  100. psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON_PENDING);
  101. /* write magic number in backup register */
  102. if (cpu == 0x01)
  103. writel(BOOT_API_A7_CORE1_MAGIC_NUMBER,
  104. TAMP_BACKUP_MAGIC_NUMBER);
  105. else
  106. writel(BOOT_API_A7_CORE0_MAGIC_NUMBER,
  107. TAMP_BACKUP_MAGIC_NUMBER);
  108. stm32mp_smp_kick_all_cpus();
  109. return ARM_PSCI_RET_SUCCESS;
  110. }
  111. int __secure psci_cpu_off(u32 function_id)
  112. {
  113. u32 cpu;
  114. cpu = psci_get_cpu_id();
  115. psci_cpu_off_common();
  116. psci_set_state(cpu, PSCI_AFFINITY_LEVEL_OFF);
  117. /* reset core: wfi is managed by BootRom */
  118. if (cpu == 0x01)
  119. writel(RCC_MP_GRSTCSETR_MPUP1RST, RCC_MP_GRSTCSETR);
  120. else
  121. writel(RCC_MP_GRSTCSETR_MPUP0RST, RCC_MP_GRSTCSETR);
  122. /* just waiting reset */
  123. while (1)
  124. wfi();
  125. }
  126. void __secure psci_system_reset(u32 function_id)
  127. {
  128. /* System reset */
  129. writel(RCC_MP_GRSTCSETR_MPSYSRST, RCC_MP_GRSTCSETR);
  130. /* just waiting reset */
  131. while (1)
  132. wfi();
  133. }
  134. void __secure psci_system_off(u32 function_id)
  135. {
  136. /* System Off is not managed, waiting user power off
  137. * TODO: handle I2C write in PMIC Main Control register bit 0 = SWOFF
  138. */
  139. while (1)
  140. wfi();
  141. }