apusys_rv_pwr_ctrl.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * Copyright (c) 2024, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <errno.h>
  7. #include <common/debug.h>
  8. #include <drivers/delay_timer.h>
  9. #include <lib/mmio.h>
  10. #include "apusys_power.h"
  11. #include "apusys_rv.h"
  12. #include "apusys_rv_pwr_ctrl.h"
  13. #define RPC_POWER_OFF_TIMEOUT_CNT (100000) /* 100ms */
  14. static int wait_for_state_ready(uint32_t reg, uint32_t mask, uint32_t expect,
  15. uint32_t retry_times, uint32_t set_reg, uint32_t set_val)
  16. {
  17. uint32_t count = 0;
  18. while ((mmio_read_32(reg) & mask) != expect) {
  19. if (count > retry_times) {
  20. ERROR("%s: timed out, reg = %x, mask = %x, expect = %x\n",
  21. __func__, reg, mask, expect);
  22. return -EBUSY;
  23. }
  24. count += 1;
  25. if (set_reg)
  26. mmio_write_32(set_reg, set_val);
  27. udelay(1);
  28. }
  29. return 0;
  30. }
  31. int apu_hw_sema_ctl_per_mbox(uint32_t sem_ctrl_addr, uint32_t sem_sta_addr,
  32. uint8_t usr_bit, enum apu_hw_sem_op ctl, uint32_t timeout,
  33. uint8_t bypass)
  34. {
  35. int ret;
  36. uint8_t ctl_bit = 0;
  37. if (ctl == HW_SEM_GET)
  38. ctl_bit = 0x1;
  39. else if (ctl == HW_SEM_PUT)
  40. ctl_bit = 0x2;
  41. else
  42. return -EINVAL;
  43. /* return fail if semaphore is currently not held by this user */
  44. if (ctl == HW_SEM_PUT && ((mmio_read_32(sem_sta_addr) & BIT(usr_bit)) == 0)
  45. && !bypass) {
  46. ERROR("%s release error: usr_bit:%d ctl:%d (sem_addr(0x%08x) = 0x%08x)\n",
  47. __func__, usr_bit, ctl, sem_sta_addr, mmio_read_32(sem_sta_addr));
  48. return -EINVAL;
  49. }
  50. mmio_write_32(sem_ctrl_addr, ctl_bit);
  51. if (ctl == HW_SEM_PUT)
  52. return 0;
  53. ret = wait_for_state_ready(sem_sta_addr, BIT(usr_bit), BIT(usr_bit), timeout,
  54. sem_ctrl_addr, ctl_bit);
  55. if (ret)
  56. return ret;
  57. return 0;
  58. }
  59. int apusys_rv_pwr_ctrl(enum APU_PWR_OP op)
  60. {
  61. int ret;
  62. uint32_t global_ref_cnt;
  63. ret = apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA0_CTRL,
  64. APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA0_STA,
  65. APU_HW_SEM_SYS_APMCU, HW_SEM_GET, HW_SEM_TIMEOUT, 0);
  66. if (ret) {
  67. ERROR("%s(%d): sem acquire timeout\n", __func__, op);
  68. return ret;
  69. }
  70. global_ref_cnt = mmio_read_32(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_DUMMY);
  71. if (global_ref_cnt > 2) {
  72. ERROR("%s: global_ref_cnt(%d) > 2\n", __func__, global_ref_cnt);
  73. } else if (op == APU_PWR_OFF) {
  74. global_ref_cnt--;
  75. mmio_write_32(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_DUMMY, global_ref_cnt);
  76. if (global_ref_cnt == 0)
  77. mmio_write_32(APU_MBOX_WKUP_CFG(11), 0);
  78. } else if (op == APU_PWR_ON) {
  79. global_ref_cnt++;
  80. mmio_write_32(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_DUMMY, global_ref_cnt);
  81. if (global_ref_cnt == 1)
  82. mmio_write_32(APU_MBOX_WKUP_CFG(11), 1);
  83. }
  84. ret = apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA0_CTRL,
  85. APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA0_STA,
  86. APU_HW_SEM_SYS_APMCU, HW_SEM_PUT, HW_SEM_TIMEOUT, 0);
  87. if (ret)
  88. ERROR("%s(%d): sem release timeout\n", __func__, op);
  89. return ret;
  90. }
  91. int rv_iommu_hw_sem_trylock(void)
  92. {
  93. return apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_CTRL,
  94. APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_STA,
  95. APU_HW_SEM_SYS_APMCU, HW_SEM_GET, 0, 0);
  96. }
  97. int rv_iommu_hw_sem_unlock(void)
  98. {
  99. return apu_hw_sema_ctl_per_mbox(APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_CTRL,
  100. APU_MBOX(APU_HW_SEM_SYS_APMCU) + APU_MBOX_SEMA1_STA,
  101. APU_HW_SEM_SYS_APMCU, HW_SEM_PUT, 0, 0);
  102. }
  103. int apu_hw_sema_ctl(uint32_t sem_addr, uint8_t usr_bit, uint8_t ctl, uint32_t timeout,
  104. uint8_t bypass)
  105. {
  106. int ret;
  107. uint8_t ctl_bit = 0;
  108. if (ctl == HW_SEM_GET)
  109. ctl_bit = usr_bit;
  110. else if (ctl == HW_SEM_PUT)
  111. ctl_bit = usr_bit + HW_SEM_PUT_BIT_SHIFT;
  112. else
  113. return -EINVAL;
  114. if (ctl == HW_SEM_PUT && ((mmio_read_32(sem_addr) & BIT(ctl_bit)) == 0) && !bypass) {
  115. ERROR("%s release error: usr_bit:%d ctl:%d (sem_addr(0x%08x) = 0x%08x)\n",
  116. __func__, usr_bit, ctl, sem_addr, mmio_read_32(sem_addr));
  117. return -EINVAL;
  118. }
  119. mmio_write_32(sem_addr, BIT(ctl_bit));
  120. if (ctl == HW_SEM_PUT)
  121. goto end;
  122. ret = wait_for_state_ready(sem_addr, BIT(ctl_bit), BIT(ctl_bit), timeout,
  123. sem_addr, BIT(ctl_bit));
  124. if (ret)
  125. return ret;
  126. end:
  127. VERBOSE("%s: sem_addr = 0x%x, usr_bit: %d, ctl: %d, sem_addr = 0x%08x\n",
  128. __func__, sem_addr, usr_bit, ctl, mmio_read_32(sem_addr));
  129. return 0;
  130. }
  131. int apusys_infra_dcm_setup(void)
  132. {
  133. mmio_write_32(APU_REG_AO_GLUE_CONFG,
  134. mmio_read_32(APU_REG_AO_GLUE_CONFG) | BIT(24) | BIT(26));
  135. return 0;
  136. }