flowctrl.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * Copyright (c) 2015-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 <cortex_a53.h>
  9. #include <common/debug.h>
  10. #include <drivers/delay_timer.h>
  11. #include <lib/mmio.h>
  12. #include <flowctrl.h>
  13. #include <lib/utils_def.h>
  14. #include <pmc.h>
  15. #include <tegra_def.h>
  16. #define CLK_RST_DEV_L_SET 0x300
  17. #define CLK_RST_DEV_L_CLR 0x304
  18. #define CLK_BPMP_RST (1 << 1)
  19. #define EVP_BPMP_RESET_VECTOR 0x200
  20. static const uint64_t flowctrl_offset_cpu_csr[4] = {
  21. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU0_CSR),
  22. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR),
  23. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 8),
  24. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CPU1_CSR + 16)
  25. };
  26. static const uint64_t flowctrl_offset_halt_cpu[4] = {
  27. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU0_EVENTS),
  28. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS),
  29. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 8),
  30. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_HALT_CPU1_EVENTS + 16)
  31. };
  32. static const uint64_t flowctrl_offset_cc4_ctrl[4] = {
  33. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL),
  34. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 4),
  35. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 8),
  36. (TEGRA_FLOWCTRL_BASE + FLOWCTRL_CC4_CORE0_CTRL + 12)
  37. };
  38. static inline void tegra_fc_cc4_ctrl(int cpu_id, uint32_t val)
  39. {
  40. mmio_write_32(flowctrl_offset_cc4_ctrl[cpu_id], val);
  41. val = mmio_read_32(flowctrl_offset_cc4_ctrl[cpu_id]);
  42. }
  43. static inline void tegra_fc_cpu_csr(int cpu_id, uint32_t val)
  44. {
  45. mmio_write_32(flowctrl_offset_cpu_csr[cpu_id], val);
  46. val = mmio_read_32(flowctrl_offset_cpu_csr[cpu_id]);
  47. }
  48. static inline void tegra_fc_halt_cpu(int cpu_id, uint32_t val)
  49. {
  50. mmio_write_32(flowctrl_offset_halt_cpu[cpu_id], val);
  51. val = mmio_read_32(flowctrl_offset_halt_cpu[cpu_id]);
  52. }
  53. static void tegra_fc_prepare_suspend(int cpu_id, uint32_t csr)
  54. {
  55. uint32_t val;
  56. val = FLOWCTRL_HALT_GIC_IRQ | FLOWCTRL_HALT_GIC_FIQ |
  57. FLOWCTRL_HALT_LIC_IRQ | FLOWCTRL_HALT_LIC_FIQ |
  58. FLOWCTRL_WAITEVENT;
  59. tegra_fc_halt_cpu(cpu_id, val);
  60. val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
  61. FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu_id);
  62. tegra_fc_cpu_csr(cpu_id, val | csr);
  63. }
  64. /*******************************************************************************
  65. * After this, no core can wake from C7 until the action is reverted.
  66. * If a wake up event is asserted, the FC state machine will stall until
  67. * the action is reverted.
  68. ******************************************************************************/
  69. void tegra_fc_ccplex_pgexit_lock(void)
  70. {
  71. unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
  72. uint32_t flags = tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT) & ~INTERCEPT_IRQ_PENDING;
  73. uint32_t icept_cpu_flags[] = {
  74. INTERCEPT_EXIT_PG_CORE0,
  75. INTERCEPT_EXIT_PG_CORE1,
  76. INTERCEPT_EXIT_PG_CORE2,
  77. INTERCEPT_EXIT_PG_CORE3
  78. };
  79. /* set the intercept flags */
  80. for (i = 0; i < ARRAY_SIZE(icept_cpu_flags); i++) {
  81. /* skip current CPU */
  82. if (i == cpu)
  83. continue;
  84. /* enable power gate exit intercept locks */
  85. flags |= icept_cpu_flags[i];
  86. }
  87. tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, flags);
  88. (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT);
  89. }
  90. /*******************************************************************************
  91. * Revert the ccplex powergate exit locks
  92. ******************************************************************************/
  93. void tegra_fc_ccplex_pgexit_unlock(void)
  94. {
  95. /* clear lock bits, clear pending interrupts */
  96. tegra_fc_write_32(FLOWCTRL_FC_SEQ_INTERCEPT, INTERCEPT_IRQ_PENDING);
  97. (void)tegra_fc_read_32(FLOWCTRL_FC_SEQ_INTERCEPT);
  98. }
  99. /*******************************************************************************
  100. * Powerdn the current CPU
  101. ******************************************************************************/
  102. void tegra_fc_cpu_powerdn(uint32_t mpidr)
  103. {
  104. int cpu = mpidr & MPIDR_CPU_MASK;
  105. VERBOSE("CPU%d powering down...\n", cpu);
  106. tegra_fc_prepare_suspend(cpu, 0);
  107. }
  108. /*******************************************************************************
  109. * Suspend the current CPU cluster
  110. ******************************************************************************/
  111. void tegra_fc_cluster_idle(uint32_t mpidr)
  112. {
  113. int cpu = mpidr & MPIDR_CPU_MASK;
  114. uint32_t val;
  115. VERBOSE("Entering cluster idle state...\n");
  116. tegra_fc_cc4_ctrl(cpu, 0);
  117. /* hardware L2 flush is faster for A53 only */
  118. tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
  119. !!MPIDR_AFFLVL1_VAL(mpidr));
  120. /* suspend the CPU cluster */
  121. val = FLOWCTRL_PG_CPU_NONCPU << FLOWCTRL_ENABLE_EXT;
  122. tegra_fc_prepare_suspend(cpu, val);
  123. }
  124. /*******************************************************************************
  125. * Power down the current CPU cluster
  126. ******************************************************************************/
  127. void tegra_fc_cluster_powerdn(uint32_t mpidr)
  128. {
  129. int cpu = mpidr & MPIDR_CPU_MASK;
  130. uint32_t val;
  131. VERBOSE("Entering cluster powerdn state...\n");
  132. tegra_fc_cc4_ctrl(cpu, 0);
  133. /* hardware L2 flush is faster for A53 only */
  134. tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL,
  135. read_midr() == CORTEX_A53_MIDR);
  136. /* power down the CPU cluster */
  137. val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
  138. tegra_fc_prepare_suspend(cpu, val);
  139. }
  140. /*******************************************************************************
  141. * Check if cluster idle or power down state is allowed from this CPU
  142. ******************************************************************************/
  143. bool tegra_fc_is_ccx_allowed(void)
  144. {
  145. unsigned int i, cpu = read_mpidr() & MPIDR_CPU_MASK;
  146. uint32_t val;
  147. bool ccx_allowed = true;
  148. for (i = 0; i < ARRAY_SIZE(flowctrl_offset_cpu_csr); i++) {
  149. /* skip current CPU */
  150. if (i == cpu)
  151. continue;
  152. /* check if all other CPUs are already halted */
  153. val = mmio_read_32(flowctrl_offset_cpu_csr[i]);
  154. if ((val & FLOWCTRL_CSR_HALT_MASK) == 0U) {
  155. ccx_allowed = false;
  156. }
  157. }
  158. return ccx_allowed;
  159. }
  160. /*******************************************************************************
  161. * Suspend the entire SoC
  162. ******************************************************************************/
  163. void tegra_fc_soc_powerdn(uint32_t mpidr)
  164. {
  165. int cpu = mpidr & MPIDR_CPU_MASK;
  166. uint32_t val;
  167. VERBOSE("Entering SoC powerdn state...\n");
  168. tegra_fc_cc4_ctrl(cpu, 0);
  169. tegra_fc_write_32(FLOWCTRL_L2_FLUSH_CONTROL, 1);
  170. val = FLOWCTRL_TURNOFF_CPURAIL << FLOWCTRL_ENABLE_EXT;
  171. tegra_fc_prepare_suspend(cpu, val);
  172. /* overwrite HALT register */
  173. tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
  174. }
  175. /*******************************************************************************
  176. * Power up the CPU
  177. ******************************************************************************/
  178. void tegra_fc_cpu_on(int cpu)
  179. {
  180. tegra_fc_cpu_csr(cpu, FLOWCTRL_CSR_ENABLE);
  181. tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT | FLOWCTRL_HALT_SCLK);
  182. }
  183. /*******************************************************************************
  184. * Power down the CPU
  185. ******************************************************************************/
  186. void tegra_fc_cpu_off(int cpu)
  187. {
  188. uint32_t val;
  189. /*
  190. * Flow controller powers down the CPU during wfi. The CPU would be
  191. * powered on when it receives any interrupt.
  192. */
  193. val = FLOWCTRL_CSR_INTR_FLAG | FLOWCTRL_CSR_EVENT_FLAG |
  194. FLOWCTRL_CSR_ENABLE | (FLOWCTRL_WAIT_WFI_BITMAP << cpu);
  195. tegra_fc_cpu_csr(cpu, val);
  196. tegra_fc_halt_cpu(cpu, FLOWCTRL_WAITEVENT);
  197. tegra_fc_cc4_ctrl(cpu, 0);
  198. }
  199. /*******************************************************************************
  200. * Inform the BPMP that we have completed the cluster power up
  201. ******************************************************************************/
  202. void tegra_fc_lock_active_cluster(void)
  203. {
  204. uint32_t val;
  205. val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
  206. val |= FLOWCTRL_BPMP_CLUSTER_PWRON_LOCK;
  207. tegra_fc_write_32(FLOWCTRL_BPMP_CLUSTER_CONTROL, val);
  208. val = tegra_fc_read_32(FLOWCTRL_BPMP_CLUSTER_CONTROL);
  209. }
  210. /*******************************************************************************
  211. * Power ON BPMP processor
  212. ******************************************************************************/
  213. void tegra_fc_bpmp_on(uint32_t entrypoint)
  214. {
  215. /* halt BPMP */
  216. tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
  217. /* Assert BPMP reset */
  218. mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
  219. /* Set reset address (stored in PMC_SCRATCH39) */
  220. mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, entrypoint);
  221. while (entrypoint != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
  222. ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
  223. /* Wait for 2us before de-asserting the reset signal. */
  224. udelay(2);
  225. /* De-assert BPMP reset */
  226. mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_CLR, CLK_BPMP_RST);
  227. /* Un-halt BPMP */
  228. tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, 0);
  229. }
  230. /*******************************************************************************
  231. * Power OFF BPMP processor
  232. ******************************************************************************/
  233. void tegra_fc_bpmp_off(void)
  234. {
  235. /* halt BPMP */
  236. tegra_fc_write_32(FLOWCTRL_HALT_BPMP_EVENTS, FLOWCTRL_WAITEVENT);
  237. /* Assert BPMP reset */
  238. mmio_write_32(TEGRA_CAR_RESET_BASE + CLK_RST_DEV_L_SET, CLK_BPMP_RST);
  239. /* Clear reset address */
  240. mmio_write_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR, 0);
  241. while (0 != mmio_read_32(TEGRA_EVP_BASE + EVP_BPMP_RESET_VECTOR))
  242. ; /* wait till value reaches EVP_BPMP_RESET_VECTOR */
  243. }
  244. /*******************************************************************************
  245. * Route legacy FIQ to the GICD
  246. ******************************************************************************/
  247. void tegra_fc_enable_fiq_to_ccplex_routing(void)
  248. {
  249. uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL);
  250. /* set the bit to pass FIQs to the GICD */
  251. tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val | FLOWCTRL_FIQ2CCPLEX_ENABLE);
  252. }
  253. /*******************************************************************************
  254. * Disable routing legacy FIQ to the GICD
  255. ******************************************************************************/
  256. void tegra_fc_disable_fiq_to_ccplex_routing(void)
  257. {
  258. uint32_t val = tegra_fc_read_32(FLOW_CTLR_FLOW_DBG_QUAL);
  259. /* clear the bit to pass FIQs to the GICD */
  260. tegra_fc_write_32(FLOW_CTLR_FLOW_DBG_QUAL, val & ~FLOWCTRL_FIQ2CCPLEX_ENABLE);
  261. }