hisi_ipc.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <stdarg.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <platform_def.h>
  10. #include <arch_helpers.h>
  11. #include <common/debug.h>
  12. #include <lib/mmio.h>
  13. #include <hisi_ipc.h>
  14. #include <hisi_sram_map.h>
  15. static int ipc_init;
  16. static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = {
  17. {
  18. HISI_IPC_MCU_INT_SRC_ACPU0_PD,
  19. HISI_IPC_MCU_INT_SRC_ACPU1_PD,
  20. HISI_IPC_MCU_INT_SRC_ACPU2_PD,
  21. HISI_IPC_MCU_INT_SRC_ACPU3_PD,
  22. },
  23. {
  24. HISI_IPC_MCU_INT_SRC_ACPU4_PD,
  25. HISI_IPC_MCU_INT_SRC_ACPU5_PD,
  26. HISI_IPC_MCU_INT_SRC_ACPU6_PD,
  27. HISI_IPC_MCU_INT_SRC_ACPU7_PD,
  28. }
  29. };
  30. int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu,
  31. unsigned int cluster)
  32. {
  33. unsigned int val = 0, cpu_val = 0;
  34. int i;
  35. val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
  36. val = val >> (cluster * 16);
  37. for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) {
  38. if (cpu == i)
  39. continue;
  40. cpu_val = (val >> (i * 4)) & 0xF;
  41. if (cpu_val == 0x8)
  42. return 0;
  43. }
  44. return 1;
  45. }
  46. int hisi_cpus_powered_off_besides_curr(unsigned int cpu)
  47. {
  48. unsigned int val;
  49. val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
  50. return (val == (0x8 << (cpu * 4)));
  51. }
  52. static void hisi_ipc_send(unsigned int ipc_num)
  53. {
  54. if (!ipc_init) {
  55. printf("error ipc base is null!!!\n");
  56. return;
  57. }
  58. mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num);
  59. }
  60. void hisi_ipc_spin_lock(unsigned int signal)
  61. {
  62. unsigned int hs_ctrl;
  63. if (signal >= HISI_IPC_INT_SRC_NUM)
  64. return;
  65. do {
  66. hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal));
  67. } while (hs_ctrl);
  68. }
  69. void hisi_ipc_spin_unlock(unsigned int signal)
  70. {
  71. if (signal >= HISI_IPC_INT_SRC_NUM)
  72. return;
  73. mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0);
  74. }
  75. void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster,
  76. unsigned int mode)
  77. {
  78. unsigned int val = 0;
  79. unsigned int offset;
  80. if (mode == HISI_IPC_PM_ON)
  81. offset = cluster * 16 + cpu * 4;
  82. else
  83. offset = cluster * 16 + cpu * 4 + 1;
  84. hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
  85. val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
  86. val |= (0x01 << offset);
  87. mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
  88. isb();
  89. dsb();
  90. hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
  91. hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
  92. }
  93. void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster)
  94. {
  95. hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON);
  96. }
  97. void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster)
  98. {
  99. hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF);
  100. }
  101. void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster,
  102. unsigned int mode)
  103. {
  104. unsigned int val = 0;
  105. unsigned int offset;
  106. if (mode == HISI_IPC_PM_ON)
  107. offset = cluster * 4;
  108. else
  109. offset = cluster * 4 + 1;
  110. hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
  111. val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
  112. val |= (0x01 << offset);
  113. mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
  114. isb();
  115. dsb();
  116. hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
  117. hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
  118. }
  119. void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster)
  120. {
  121. hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON);
  122. }
  123. void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster)
  124. {
  125. hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF);
  126. }
  127. void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster)
  128. {
  129. unsigned int val = 0;
  130. unsigned int offset;
  131. offset = cluster * 16 + cpu * 4 + 2;
  132. hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
  133. val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
  134. val |= (0x01 << offset);
  135. mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
  136. hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
  137. hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
  138. }
  139. void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster)
  140. {
  141. unsigned int val;
  142. unsigned int offset;
  143. offset = cluster * 4 + 1;
  144. hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
  145. if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) {
  146. val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
  147. val |= (0x01 << offset);
  148. mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
  149. }
  150. hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
  151. hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
  152. }
  153. void hisi_ipc_psci_system_off(void)
  154. {
  155. hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD);
  156. }
  157. int hisi_ipc_init(void)
  158. {
  159. ipc_init = 1;
  160. mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8);
  161. mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8);
  162. return 0;
  163. }