hikey960_pm.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * Copyright (c) 2017, 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/pl011.h>
  12. #include <drivers/arm/pl061_gpio.h>
  13. #include <drivers/delay_timer.h>
  14. #include <lib/mmio.h>
  15. #include <lib/psci/psci.h>
  16. #include <hi3660.h>
  17. #include <hi3660_crg.h>
  18. #include "drivers/pwrc/hisi_pwrc.h"
  19. #include "hikey960_def.h"
  20. #include "hikey960_private.h"
  21. #define CORE_PWR_STATE(state) \
  22. ((state)->pwr_domain_state[MPIDR_AFFLVL0])
  23. #define CLUSTER_PWR_STATE(state) \
  24. ((state)->pwr_domain_state[MPIDR_AFFLVL1])
  25. #define SYSTEM_PWR_STATE(state) \
  26. ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
  27. #define DMAC_GLB_REG_SEC 0x694
  28. #define AXI_CONF_BASE 0x820
  29. static unsigned int uart_base;
  30. static console_t console;
  31. static uintptr_t hikey960_sec_entrypoint;
  32. static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
  33. {
  34. unsigned long scr;
  35. scr = read_scr_el3();
  36. /* Enable Physical IRQ and FIQ to wake the CPU */
  37. write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
  38. /* Add barrier before CPU enter WFI state */
  39. isb();
  40. dsb();
  41. wfi();
  42. /*
  43. * Restore SCR to the original value, synchronisazion of
  44. * scr_el3 is done by eret while el3_exit to save some
  45. * execution cycles.
  46. */
  47. write_scr_el3(scr);
  48. }
  49. static int hikey960_pwr_domain_on(u_register_t mpidr)
  50. {
  51. unsigned int core = mpidr & MPIDR_CPU_MASK;
  52. unsigned int cluster =
  53. (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
  54. int cluster_stat = cluster_is_powered_on(cluster);
  55. hisi_set_cpu_boot_flag(cluster, core);
  56. mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
  57. hikey960_sec_entrypoint >> 2);
  58. if (cluster_stat)
  59. hisi_powerup_core(cluster, core);
  60. else
  61. hisi_powerup_cluster(cluster, core);
  62. return PSCI_E_SUCCESS;
  63. }
  64. static void
  65. hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state)
  66. {
  67. if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
  68. cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
  69. gicv2_pcpu_distif_init();
  70. gicv2_cpuif_enable();
  71. }
  72. void hikey960_pwr_domain_off(const psci_power_state_t *target_state)
  73. {
  74. unsigned long mpidr = read_mpidr_el1();
  75. unsigned int core = mpidr & MPIDR_CPU_MASK;
  76. unsigned int cluster =
  77. (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
  78. clr_ex();
  79. isb();
  80. dsbsy();
  81. gicv2_cpuif_disable();
  82. hisi_clear_cpu_boot_flag(cluster, core);
  83. hisi_powerdn_core(cluster, core);
  84. /* check if any core is powered up */
  85. if (hisi_test_cpu_down(cluster, core)) {
  86. cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
  87. isb();
  88. dsbsy();
  89. hisi_powerdn_cluster(cluster, core);
  90. }
  91. }
  92. static void __dead2 hikey960_system_off(void)
  93. {
  94. gpio_set_direction(176, GPIO_DIR_OUT);
  95. gpio_set_value(176, GPIO_LEVEL_LOW);
  96. panic();
  97. }
  98. static void __dead2 hikey960_system_reset(void)
  99. {
  100. dsb();
  101. isb();
  102. mdelay(2000);
  103. mmio_write_32(SCTRL_SCPEREN1_REG,
  104. SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS);
  105. mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef);
  106. panic();
  107. }
  108. int hikey960_validate_power_state(unsigned int power_state,
  109. psci_power_state_t *req_state)
  110. {
  111. unsigned int pstate = psci_get_pstate_type(power_state);
  112. unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
  113. int i;
  114. assert(req_state);
  115. if (pwr_lvl > PLAT_MAX_PWR_LVL)
  116. return PSCI_E_INVALID_PARAMS;
  117. /* Sanity check the requested state */
  118. if (pstate == PSTATE_TYPE_STANDBY) {
  119. /*
  120. * It's possible to enter standby only on power level 0
  121. * Ignore any other power level.
  122. */
  123. if (pwr_lvl != MPIDR_AFFLVL0)
  124. return PSCI_E_INVALID_PARAMS;
  125. req_state->pwr_domain_state[MPIDR_AFFLVL0] =
  126. PLAT_MAX_RET_STATE;
  127. } else {
  128. for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
  129. req_state->pwr_domain_state[i] =
  130. PLAT_MAX_OFF_STATE;
  131. }
  132. /*
  133. * We expect the 'state id' to be zero.
  134. */
  135. if (psci_get_pstate_id(power_state))
  136. return PSCI_E_INVALID_PARAMS;
  137. return PSCI_E_SUCCESS;
  138. }
  139. static int hikey960_validate_ns_entrypoint(uintptr_t entrypoint)
  140. {
  141. /*
  142. * Check if the non secure entrypoint lies within the non
  143. * secure DRAM.
  144. */
  145. if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
  146. return PSCI_E_SUCCESS;
  147. return PSCI_E_INVALID_ADDRESS;
  148. }
  149. static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state)
  150. {
  151. u_register_t mpidr = read_mpidr_el1();
  152. unsigned int core = mpidr & MPIDR_CPU_MASK;
  153. unsigned int cluster =
  154. (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
  155. if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
  156. return;
  157. if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
  158. clr_ex();
  159. isb();
  160. dsbsy();
  161. gicv2_cpuif_disable();
  162. hisi_cpuidle_lock(cluster, core);
  163. hisi_set_cpuidle_flag(cluster, core);
  164. hisi_cpuidle_unlock(cluster, core);
  165. mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
  166. hikey960_sec_entrypoint >> 2);
  167. hisi_enter_core_idle(cluster, core);
  168. }
  169. /* Perform the common cluster specific operations */
  170. if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
  171. hisi_cpuidle_lock(cluster, core);
  172. hisi_disable_pdc(cluster);
  173. /* check if any core is powered up */
  174. if (hisi_test_pwrdn_allcores(cluster, core)) {
  175. cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
  176. isb();
  177. dsbsy();
  178. /* mask the pdc wakeup irq, then
  179. * enable pdc to power down the core
  180. */
  181. hisi_pdc_mask_cluster_wakeirq(cluster);
  182. hisi_enable_pdc(cluster);
  183. hisi_cpuidle_unlock(cluster, core);
  184. /* check the SR flag bit to determine
  185. * CLUSTER_IDLE_IPC or AP_SR_IPC to send
  186. */
  187. if (hisi_test_ap_suspend_flag())
  188. hisi_enter_ap_suspend(cluster, core);
  189. else
  190. hisi_enter_cluster_idle(cluster, core);
  191. } else {
  192. /* enable pdc */
  193. hisi_enable_pdc(cluster);
  194. hisi_cpuidle_unlock(cluster, core);
  195. }
  196. }
  197. }
  198. static void hikey960_sr_dma_reinit(void)
  199. {
  200. unsigned int ctr = 0;
  201. mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3);
  202. /* 1~15 channel is set non_secure */
  203. for (ctr = 1; ctr <= 15; ctr++)
  204. mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40),
  205. (1 << 6) | (1 << 18));
  206. }
  207. static void
  208. hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
  209. {
  210. unsigned long mpidr = read_mpidr_el1();
  211. unsigned int core = mpidr & MPIDR_CPU_MASK;
  212. unsigned int cluster =
  213. (mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
  214. /* Nothing to be done on waking up from retention from CPU level */
  215. if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
  216. return;
  217. hisi_cpuidle_lock(cluster, core);
  218. hisi_clear_cpuidle_flag(cluster, core);
  219. hisi_cpuidle_unlock(cluster, core);
  220. if (hisi_test_ap_suspend_flag()) {
  221. hikey960_sr_dma_reinit();
  222. gicv2_cpuif_enable();
  223. console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ,
  224. PL011_BAUDRATE, &console);
  225. }
  226. hikey960_pwr_domain_on_finish(target_state);
  227. }
  228. static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state)
  229. {
  230. int i;
  231. for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
  232. req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
  233. }
  234. static const plat_psci_ops_t hikey960_psci_ops = {
  235. .cpu_standby = hikey960_pwr_domain_standby,
  236. .pwr_domain_on = hikey960_pwr_domain_on,
  237. .pwr_domain_on_finish = hikey960_pwr_domain_on_finish,
  238. .pwr_domain_off = hikey960_pwr_domain_off,
  239. .pwr_domain_suspend = hikey960_pwr_domain_suspend,
  240. .pwr_domain_suspend_finish = hikey960_pwr_domain_suspend_finish,
  241. .system_off = hikey960_system_off,
  242. .system_reset = hikey960_system_reset,
  243. .validate_power_state = hikey960_validate_power_state,
  244. .validate_ns_entrypoint = hikey960_validate_ns_entrypoint,
  245. .get_sys_suspend_power_state = hikey960_get_sys_suspend_power_state,
  246. };
  247. int plat_setup_psci_ops(uintptr_t sec_entrypoint,
  248. const plat_psci_ops_t **psci_ops)
  249. {
  250. unsigned int id = 0;
  251. int ret;
  252. ret = hikey960_read_boardid(&id);
  253. if (ret == 0) {
  254. if (id == 5300U)
  255. uart_base = PL011_UART5_BASE;
  256. else
  257. uart_base = PL011_UART6_BASE;
  258. } else {
  259. uart_base = PL011_UART6_BASE;
  260. }
  261. hikey960_sec_entrypoint = sec_entrypoint;
  262. INFO("%s: sec_entrypoint=0x%lx\n", __func__,
  263. (unsigned long)hikey960_sec_entrypoint);
  264. /*
  265. * Initialize PSCI ops struct
  266. */
  267. *psci_ops = &hikey960_psci_ops;
  268. return 0;
  269. }