pmic_wrap_init.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <common/debug.h>
  7. #include <drivers/delay_timer.h>
  8. #include <lib/mmio.h>
  9. #include <platform_def.h>
  10. #include <pmic_wrap_init.h>
  11. /* pmic wrap module wait_idle and read polling interval (in microseconds) */
  12. enum {
  13. WAIT_IDLE_POLLING_DELAY_US = 1,
  14. READ_POLLING_DELAY_US = 2
  15. };
  16. static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
  17. void *wacs_register,
  18. void *wacs_vldclr_register,
  19. uint32_t *read_reg)
  20. {
  21. uint32_t reg_rdata;
  22. uint32_t retry;
  23. retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
  24. WAIT_IDLE_POLLING_DELAY_US;
  25. do {
  26. udelay(WAIT_IDLE_POLLING_DELAY_US);
  27. reg_rdata = mmio_read_32((uintptr_t)wacs_register);
  28. /* if last read command timeout,clear vldclr bit
  29. * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
  30. * write:FSM_REQ-->idle
  31. */
  32. switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
  33. RDATA_WACS_FSM_MASK)) {
  34. case WACS_FSM_WFVLDCLR:
  35. mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
  36. ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
  37. break;
  38. case WACS_FSM_WFDLE:
  39. ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
  40. break;
  41. case WACS_FSM_REQ:
  42. ERROR("WACS_FSM = WACS_FSM_REQ\n");
  43. break;
  44. case WACS_FSM_IDLE:
  45. goto done;
  46. default:
  47. break;
  48. }
  49. retry--;
  50. } while (retry);
  51. done:
  52. if (!retry) /* timeout */
  53. return E_PWR_WAIT_IDLE_TIMEOUT;
  54. if (read_reg)
  55. *read_reg = reg_rdata;
  56. return 0;
  57. }
  58. static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
  59. void *wacs_register,
  60. uint32_t *read_reg)
  61. {
  62. uint32_t reg_rdata;
  63. uint32_t retry;
  64. retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
  65. do {
  66. udelay(READ_POLLING_DELAY_US);
  67. reg_rdata = mmio_read_32((uintptr_t)wacs_register);
  68. if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
  69. == WACS_FSM_WFVLDCLR)
  70. break;
  71. retry--;
  72. } while (retry);
  73. if (!retry) { /* timeout */
  74. ERROR("timeout when waiting for idle\n");
  75. return E_PWR_WAIT_IDLE_TIMEOUT_READ;
  76. }
  77. if (read_reg)
  78. *read_reg = reg_rdata;
  79. return 0;
  80. }
  81. static int32_t pwrap_wacs2(uint32_t write,
  82. uint32_t adr,
  83. uint32_t wdata,
  84. uint32_t *rdata,
  85. uint32_t init_check)
  86. {
  87. uint32_t reg_rdata = 0;
  88. uint32_t wacs_write = 0;
  89. uint32_t wacs_adr = 0;
  90. uint32_t wacs_cmd = 0;
  91. uint32_t return_value = 0;
  92. if (init_check) {
  93. reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
  94. /* Prevent someone to used pwrap before pwrap init */
  95. if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
  96. RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
  97. ERROR("initialization isn't finished\n");
  98. return E_PWR_NOT_INIT_DONE;
  99. }
  100. }
  101. reg_rdata = 0;
  102. /* Check IDLE in advance */
  103. return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
  104. &mtk_pwrap->wacs2_rdata,
  105. &mtk_pwrap->wacs2_vldclr,
  106. 0);
  107. if (return_value != 0) {
  108. ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
  109. goto FAIL;
  110. }
  111. wacs_write = write << 31;
  112. wacs_adr = (adr >> 1) << 16;
  113. wacs_cmd = wacs_write | wacs_adr | wdata;
  114. mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, wacs_cmd);
  115. if (write == 0) {
  116. if (rdata == NULL) {
  117. ERROR("rdata is a NULL pointer\n");
  118. return_value = E_PWR_INVALID_ARG;
  119. goto FAIL;
  120. }
  121. return_value = wait_for_state_ready(TIMEOUT_READ,
  122. &mtk_pwrap->wacs2_rdata,
  123. &reg_rdata);
  124. if (return_value != 0) {
  125. ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
  126. return_value);
  127. goto FAIL;
  128. }
  129. *rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
  130. & RDATA_WACS_RDATA_MASK);
  131. mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 1);
  132. }
  133. FAIL:
  134. return return_value;
  135. }
  136. /* external API for pmic_wrap user */
  137. int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
  138. {
  139. return pwrap_wacs2(0, adr, 0, rdata, 1);
  140. }
  141. int32_t pwrap_write(uint32_t adr, uint32_t wdata)
  142. {
  143. return pwrap_wacs2(1, adr, wdata, 0, 1);
  144. }