hikey_pm.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright (c) 2017-2018, 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 <drivers/arm/cci.h>
  10. #include <drivers/arm/gicv2.h>
  11. #include <drivers/arm/sp804_delay_timer.h>
  12. #include <lib/mmio.h>
  13. #include <lib/psci/psci.h>
  14. #include <hi6220.h>
  15. #include <hikey_def.h>
  16. #include <hisi_ipc.h>
  17. #include <hisi_pwrc.h>
  18. #include <hisi_sram_map.h>
  19. #define CORE_PWR_STATE(state) \
  20. ((state)->pwr_domain_state[MPIDR_AFFLVL0])
  21. #define CLUSTER_PWR_STATE(state) \
  22. ((state)->pwr_domain_state[MPIDR_AFFLVL1])
  23. #define SYSTEM_PWR_STATE(state) \
  24. ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
  25. static uintptr_t hikey_sec_entrypoint;
  26. static int hikey_pwr_domain_on(u_register_t mpidr)
  27. {
  28. int cpu, cluster;
  29. int curr_cluster;
  30. cluster = MPIDR_AFFLVL1_VAL(mpidr);
  31. cpu = MPIDR_AFFLVL0_VAL(mpidr);
  32. curr_cluster = MPIDR_AFFLVL1_VAL(read_mpidr());
  33. if (cluster != curr_cluster)
  34. hisi_ipc_cluster_on(cpu, cluster);
  35. hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint);
  36. hisi_pwrc_enable_debug(cpu, cluster);
  37. hisi_ipc_cpu_on(cpu, cluster);
  38. return 0;
  39. }
  40. static void hikey_pwr_domain_on_finish(const psci_power_state_t *target_state)
  41. {
  42. unsigned long mpidr;
  43. int cpu, cluster;
  44. mpidr = read_mpidr();
  45. cluster = MPIDR_AFFLVL1_VAL(mpidr);
  46. cpu = MPIDR_AFFLVL0_VAL(mpidr);
  47. /*
  48. * Enable CCI coherency for this cluster.
  49. * No need for locks as no other cpu is active at the moment.
  50. */
  51. if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
  52. cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
  53. /* Zero the jump address in the mailbox for this cpu */
  54. hisi_pwrc_set_core_bx_addr(cpu, cluster, 0);
  55. /* Program the GIC per-cpu distributor or re-distributor interface */
  56. gicv2_pcpu_distif_init();
  57. /* Enable the GIC cpu interface */
  58. gicv2_cpuif_enable();
  59. }
  60. void hikey_pwr_domain_off(const psci_power_state_t *target_state)
  61. {
  62. unsigned long mpidr;
  63. int cpu, cluster;
  64. mpidr = read_mpidr();
  65. cluster = MPIDR_AFFLVL1_VAL(mpidr);
  66. cpu = MPIDR_AFFLVL0_VAL(mpidr);
  67. gicv2_cpuif_disable();
  68. hisi_ipc_cpu_off(cpu, cluster);
  69. if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
  70. hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
  71. cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
  72. hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
  73. hisi_ipc_cluster_off(cpu, cluster);
  74. }
  75. }
  76. static void hikey_pwr_domain_suspend(const psci_power_state_t *target_state)
  77. {
  78. u_register_t mpidr = read_mpidr_el1();
  79. unsigned int cpu = mpidr & MPIDR_CPU_MASK;
  80. unsigned int cluster =
  81. (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
  82. if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
  83. return;
  84. if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
  85. /* Program the jump address for the target cpu */
  86. hisi_pwrc_set_core_bx_addr(cpu, cluster, hikey_sec_entrypoint);
  87. gicv2_cpuif_disable();
  88. if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
  89. hisi_ipc_cpu_suspend(cpu, cluster);
  90. }
  91. /* Perform the common cluster specific operations */
  92. if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
  93. hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
  94. cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
  95. hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
  96. if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
  97. hisi_pwrc_set_cluster_wfi(1);
  98. hisi_pwrc_set_cluster_wfi(0);
  99. hisi_ipc_psci_system_off();
  100. } else
  101. hisi_ipc_cluster_suspend(cpu, cluster);
  102. }
  103. }
  104. static void hikey_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
  105. {
  106. unsigned long mpidr;
  107. unsigned int cluster, cpu;
  108. /* Nothing to be done on waking up from retention from CPU level */
  109. if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
  110. return;
  111. /* Get the mpidr for this cpu */
  112. mpidr = read_mpidr_el1();
  113. cluster = (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFF1_SHIFT;
  114. cpu = mpidr & MPIDR_CPU_MASK;
  115. /* Enable CCI coherency for cluster */
  116. if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
  117. cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
  118. hisi_pwrc_set_core_bx_addr(cpu, cluster, 0);
  119. if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
  120. gicv2_distif_init();
  121. gicv2_pcpu_distif_init();
  122. gicv2_cpuif_enable();
  123. } else {
  124. gicv2_pcpu_distif_init();
  125. gicv2_cpuif_enable();
  126. }
  127. }
  128. static void hikey_get_sys_suspend_power_state(psci_power_state_t *req_state)
  129. {
  130. int i;
  131. for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
  132. req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
  133. }
  134. static void __dead2 hikey_system_off(void)
  135. {
  136. NOTICE("%s: off system\n", __func__);
  137. /* Pull down GPIO_0_0 to trigger PMIC shutdown */
  138. mmio_write_32(0xF8001810, 0x2); /* Pinmux */
  139. mmio_write_8(0xF8011400, 1); /* Pin direction */
  140. mmio_write_8(0xF8011004, 0); /* Pin output value */
  141. /* Wait for 2s to power off system by PMIC */
  142. sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
  143. mdelay(2000);
  144. /*
  145. * PMIC shutdown depends on two conditions: GPIO_0_0 (PWR_HOLD) low,
  146. * and VBUS_DET < 3.6V. For HiKey, VBUS_DET is connected to VDD_4V2
  147. * through Jumper 1-2. So, to complete shutdown, user needs to manually
  148. * remove Jumper 1-2.
  149. */
  150. NOTICE("+------------------------------------------+\n");
  151. NOTICE("| IMPORTANT: Remove Jumper 1-2 to shutdown |\n");
  152. NOTICE("| DANGER: SoC is still burning. DANGER! |\n");
  153. NOTICE("| Board will be reboot to avoid overheat |\n");
  154. NOTICE("+------------------------------------------+\n");
  155. /* Send the system reset request */
  156. mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
  157. wfi();
  158. panic();
  159. }
  160. static void __dead2 hikey_system_reset(void)
  161. {
  162. /* Send the system reset request */
  163. mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
  164. isb();
  165. dsb();
  166. wfi();
  167. panic();
  168. }
  169. int hikey_validate_power_state(unsigned int power_state,
  170. psci_power_state_t *req_state)
  171. {
  172. int pstate = psci_get_pstate_type(power_state);
  173. int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
  174. int i;
  175. assert(req_state);
  176. if (pwr_lvl > PLAT_MAX_PWR_LVL)
  177. return PSCI_E_INVALID_PARAMS;
  178. /* Sanity check the requested state */
  179. if (pstate == PSTATE_TYPE_STANDBY) {
  180. /*
  181. * It's possible to enter standby only on power level 0
  182. * Ignore any other power level.
  183. */
  184. if (pwr_lvl != MPIDR_AFFLVL0)
  185. return PSCI_E_INVALID_PARAMS;
  186. req_state->pwr_domain_state[MPIDR_AFFLVL0] =
  187. PLAT_MAX_RET_STATE;
  188. } else {
  189. for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
  190. req_state->pwr_domain_state[i] =
  191. PLAT_MAX_OFF_STATE;
  192. }
  193. /*
  194. * We expect the 'state id' to be zero.
  195. */
  196. if (psci_get_pstate_id(power_state))
  197. return PSCI_E_INVALID_PARAMS;
  198. return PSCI_E_SUCCESS;
  199. }
  200. static int hikey_validate_ns_entrypoint(uintptr_t entrypoint)
  201. {
  202. /*
  203. * Check if the non secure entrypoint lies within the non
  204. * secure DRAM.
  205. */
  206. if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
  207. return PSCI_E_SUCCESS;
  208. return PSCI_E_INVALID_ADDRESS;
  209. }
  210. static const plat_psci_ops_t hikey_psci_ops = {
  211. .cpu_standby = NULL,
  212. .pwr_domain_on = hikey_pwr_domain_on,
  213. .pwr_domain_on_finish = hikey_pwr_domain_on_finish,
  214. .pwr_domain_off = hikey_pwr_domain_off,
  215. .pwr_domain_suspend = hikey_pwr_domain_suspend,
  216. .pwr_domain_suspend_finish = hikey_pwr_domain_suspend_finish,
  217. .system_off = hikey_system_off,
  218. .system_reset = hikey_system_reset,
  219. .validate_power_state = hikey_validate_power_state,
  220. .validate_ns_entrypoint = hikey_validate_ns_entrypoint,
  221. .get_sys_suspend_power_state = hikey_get_sys_suspend_power_state,
  222. };
  223. int plat_setup_psci_ops(uintptr_t sec_entrypoint,
  224. const plat_psci_ops_t **psci_ops)
  225. {
  226. hikey_sec_entrypoint = sec_entrypoint;
  227. /*
  228. * Initialize PSCI ops struct
  229. */
  230. *psci_ops = &hikey_psci_ops;
  231. return 0;
  232. }