mtspmc.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright (c) 2021, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <common/debug.h>
  8. #include <drivers/delay_timer.h>
  9. #include <lib/mmio.h>
  10. #include <mcucfg.h>
  11. #include <mtspmc.h>
  12. #include <mtspmc_private.h>
  13. #include <plat/common/platform.h>
  14. void mcucfg_disable_gic_wakeup(unsigned int cluster, unsigned int cpu)
  15. {
  16. mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
  17. }
  18. void mcucfg_enable_gic_wakeup(unsigned int cluster, unsigned int cpu)
  19. {
  20. mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, GIC_WAKEUP_IGNORE(cpu));
  21. /* Clear cpu's cpc sw hint */
  22. mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
  23. }
  24. void mcucfg_set_bootaddr(unsigned int cluster, unsigned int cpu, uintptr_t bootaddr)
  25. {
  26. assert(cluster == 0U);
  27. mmio_write_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR), bootaddr);
  28. }
  29. uintptr_t mcucfg_get_bootaddr(unsigned int cluster, unsigned int cpu)
  30. {
  31. assert(cluster == 0U);
  32. return (uintptr_t)mmio_read_32(per_cpu(cluster, cpu, MCUCFG_BOOTADDR));
  33. }
  34. void mcucfg_init_archstate(unsigned int cluster, unsigned int cpu, bool arm64)
  35. {
  36. uint32_t reg;
  37. assert(cluster == 0U);
  38. reg = per_cluster(cluster, MCUCFG_INITARCH);
  39. if (arm64) {
  40. mmio_setbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
  41. } else {
  42. mmio_clrbits_32(reg, MCUCFG_INITARCH_CPU_BIT(cpu));
  43. }
  44. }
  45. /*
  46. * Return subsystem's power state.
  47. *
  48. * @mask: mask to SPM_CPU_PWR_STATUS to query the power state
  49. * of one subsystem.
  50. * RETURNS:
  51. * 0 (the subsys was powered off)
  52. * 1 (the subsys was powered on)
  53. */
  54. bool spm_get_powerstate(uint32_t mask)
  55. {
  56. return (mmio_read_32(SPM_CPU_PWR_STATUS) & mask);
  57. }
  58. bool spm_get_cluster_powerstate(unsigned int cluster)
  59. {
  60. assert(cluster == 0U);
  61. return spm_get_powerstate(MP0_CPUTOP);
  62. }
  63. bool spm_get_cpu_powerstate(unsigned int cluster, unsigned int cpu)
  64. {
  65. uint32_t mask = BIT(cpu);
  66. assert(cluster == 0U);
  67. return spm_get_powerstate(mask);
  68. }
  69. int spmc_init(void)
  70. {
  71. unsigned int cpu = plat_my_core_pos();
  72. INFO("SPM: enable CPC mode\n");
  73. mmio_write_32(SPM_POWERON_CONFIG_EN, PROJECT_CODE | BCLK_CG_EN);
  74. mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWR_RST_B);
  75. mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWR_RST_B);
  76. mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWR_RST_B);
  77. mmio_setbits_32(per_cpu(0, 4, SPM_CPU_PWR), PWR_RST_B);
  78. mmio_setbits_32(per_cpu(0, 5, SPM_CPU_PWR), PWR_RST_B);
  79. mmio_setbits_32(per_cpu(0, 6, SPM_CPU_PWR), PWR_RST_B);
  80. mmio_setbits_32(per_cpu(0, 7, SPM_CPU_PWR), PWR_RST_B);
  81. mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
  82. mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
  83. mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), RESETPWRON_CONFIG);
  84. mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
  85. /* Clear bootup cpu's cpc sw hint */
  86. mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
  87. return 0;
  88. }
  89. /*
  90. * Power on a core with specified cluster and core index
  91. *
  92. * @cluster: the cluster ID of the CPU which to be powered on
  93. * @cpu: the CPU ID of the CPU which to be powered on
  94. */
  95. void spm_poweron_cpu(unsigned int cluster, unsigned int cpu)
  96. {
  97. /* info CPC that CPU hotplug on */
  98. mmio_setbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
  99. /* Set mp0_spmc_pwr_on_cpuX = 1 */
  100. mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
  101. /* wait for power on ack */
  102. while (!spm_get_cpu_powerstate(cluster, cpu))
  103. ;
  104. /* info CPC that CPU hotplug off */
  105. mmio_clrbits_32(MCUCFG_CPC_FLOW_CTRL_CFG, SSPM_ALL_PWR_CTRL_EN);
  106. }
  107. /*
  108. * Power off a core with specified cluster and core index
  109. *
  110. * @cluster: the cluster ID of the CPU which to be powered off
  111. * @cpu: the CPU ID of the CPU which to be powered off
  112. */
  113. void spm_poweroff_cpu(unsigned int cluster, unsigned int cpu)
  114. {
  115. /* Set mp0_spmc_pwr_on_cpuX = 0 */
  116. mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWR_ON);
  117. }
  118. /*
  119. * Power off a cluster with specified index
  120. *
  121. * @cluster: the cluster index which to be powered off
  122. */
  123. void spm_poweroff_cluster(unsigned int cluster)
  124. {
  125. /* No need to power on/off cluster on single cluster platform */
  126. assert(false);
  127. }
  128. /*
  129. * Power on a cluster with specified index
  130. *
  131. * @cluster: the cluster index which to be powered on
  132. */
  133. void spm_poweron_cluster(unsigned int cluster)
  134. {
  135. /* No need to power on/off cluster on single cluster platform */
  136. assert(false);
  137. }