uniphier_psci.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <arch_helpers.h>
  8. #include <common/debug.h>
  9. #include <errno.h>
  10. #include <lib/mmio.h>
  11. #include <lib/psci/psci.h>
  12. #include "uniphier.h"
  13. #define UNIPHIER_ROM_RSV0 0x0
  14. #define UNIPHIER_SLFRSTSEL 0x10
  15. #define UNIPHIER_SLFRSTSEL_MASK GENMASK(1, 0)
  16. #define UNIPHIER_SLFRSTCTL 0x14
  17. #define UNIPHIER_SLFRSTCTL_RST BIT(0)
  18. #define MPIDR_AFFINITY_INVALID ((u_register_t)-1)
  19. static uintptr_t uniphier_rom_rsv_base;
  20. static uintptr_t uniphier_slfrst_base;
  21. uintptr_t uniphier_sec_entrypoint;
  22. void uniphier_warmboot_entrypoint(void);
  23. void __dead2 uniphier_fake_pwr_down(void);
  24. u_register_t uniphier_holding_pen_release;
  25. static int uniphier_psci_scp_mode;
  26. static int uniphier_psci_pwr_domain_on(u_register_t mpidr)
  27. {
  28. uniphier_holding_pen_release = mpidr;
  29. flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
  30. sizeof(uniphier_holding_pen_release));
  31. mmio_write_64(uniphier_rom_rsv_base + UNIPHIER_ROM_RSV0,
  32. (uint64_t)&uniphier_warmboot_entrypoint);
  33. sev();
  34. return PSCI_E_SUCCESS;
  35. }
  36. static void uniphier_psci_pwr_domain_off(const psci_power_state_t *target_state)
  37. {
  38. uniphier_gic_cpuif_disable();
  39. }
  40. static void uniphier_psci_pwr_domain_on_finish(
  41. const psci_power_state_t *target_state)
  42. {
  43. uniphier_gic_pcpu_init();
  44. uniphier_gic_cpuif_enable();
  45. uniphier_cci_enable();
  46. }
  47. static void __dead2 uniphier_psci_pwr_domain_pwr_down_wfi(
  48. const psci_power_state_t *target_state)
  49. {
  50. /*
  51. * The Boot ROM cannot distinguish warm and cold resets.
  52. * Instead of the CPU reset, fake it.
  53. */
  54. uniphier_holding_pen_release = MPIDR_AFFINITY_INVALID;
  55. flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
  56. sizeof(uniphier_holding_pen_release));
  57. uniphier_fake_pwr_down();
  58. }
  59. static void uniphier_self_system_reset(void)
  60. {
  61. mmio_clrbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTSEL,
  62. UNIPHIER_SLFRSTSEL_MASK);
  63. mmio_setbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTCTL,
  64. UNIPHIER_SLFRSTCTL_RST);
  65. }
  66. static void __dead2 uniphier_psci_system_off(void)
  67. {
  68. if (uniphier_psci_scp_mode) {
  69. uniphier_scp_system_off();
  70. } else {
  71. NOTICE("SCP is disabled; can't shutdown the system.\n");
  72. NOTICE("Resetting the system instead.\n");
  73. uniphier_self_system_reset();
  74. }
  75. wfi();
  76. ERROR("UniPhier System Off: operation not handled.\n");
  77. panic();
  78. }
  79. static void __dead2 uniphier_psci_system_reset(void)
  80. {
  81. if (uniphier_psci_scp_mode)
  82. uniphier_scp_system_reset();
  83. else
  84. uniphier_self_system_reset();
  85. wfi();
  86. ERROR("UniPhier System Reset: operation not handled.\n");
  87. panic();
  88. }
  89. static const struct plat_psci_ops uniphier_psci_ops = {
  90. .pwr_domain_on = uniphier_psci_pwr_domain_on,
  91. .pwr_domain_off = uniphier_psci_pwr_domain_off,
  92. .pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish,
  93. .pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi,
  94. .system_off = uniphier_psci_system_off,
  95. .system_reset = uniphier_psci_system_reset,
  96. };
  97. int plat_setup_psci_ops(uintptr_t sec_entrypoint,
  98. const struct plat_psci_ops **psci_ops)
  99. {
  100. uniphier_sec_entrypoint = sec_entrypoint;
  101. flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
  102. sizeof(uniphier_sec_entrypoint));
  103. *psci_ops = &uniphier_psci_ops;
  104. return 0;
  105. }
  106. struct uniphier_psci_ctrl_base {
  107. uintptr_t rom_rsv_base;
  108. uintptr_t slfrst_base;
  109. };
  110. static const struct uniphier_psci_ctrl_base uniphier_psci_ctrl_base[] = {
  111. [UNIPHIER_SOC_LD11] = {
  112. .rom_rsv_base = 0x59801200,
  113. .slfrst_base = 0x61843000,
  114. },
  115. [UNIPHIER_SOC_LD20] = {
  116. .rom_rsv_base = 0x59801200,
  117. .slfrst_base = 0x61843000,
  118. },
  119. [UNIPHIER_SOC_PXS3] = {
  120. .rom_rsv_base = 0x59801200,
  121. .slfrst_base = 0x61843000,
  122. },
  123. };
  124. void uniphier_psci_init(unsigned int soc)
  125. {
  126. assert(soc < ARRAY_SIZE(uniphier_psci_ctrl_base));
  127. uniphier_rom_rsv_base = uniphier_psci_ctrl_base[soc].rom_rsv_base;
  128. uniphier_slfrst_base = uniphier_psci_ctrl_base[soc].slfrst_base;
  129. if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) {
  130. uniphier_psci_scp_mode = uniphier_scp_is_running();
  131. flush_dcache_range((uint64_t)&uniphier_psci_scp_mode,
  132. sizeof(uniphier_psci_scp_mode));
  133. if (uniphier_psci_scp_mode)
  134. uniphier_scp_open_com();
  135. }
  136. }