pmic_wrap_init_v2.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright (c) 2020-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 pwrap_polling_interval {
  13. WAIT_IDLE_POLLING_DELAY_US = 1,
  14. READ_POLLING_DELAY_US = 2
  15. };
  16. static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us)
  17. {
  18. uint32_t reg_rdata = 0U, retry;
  19. retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
  20. WAIT_IDLE_POLLING_DELAY_US;
  21. while (retry != 0) {
  22. udelay(WAIT_IDLE_POLLING_DELAY_US);
  23. reg_rdata = mmio_read_32((uintptr_t)wacs_register);
  24. /* if last read command timeout,clear vldclr bit
  25. * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
  26. * write:FSM_REQ-->idle
  27. */
  28. switch (GET_WACS_FSM(reg_rdata)) {
  29. case SWINF_FSM_WFVLDCLR:
  30. mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
  31. INFO("WACS_FSM = SWINF_FSM_WFVLDCLR\n");
  32. break;
  33. case SWINF_FSM_WFDLE:
  34. INFO("WACS_FSM = SWINF_FSM_WFDLE\n");
  35. break;
  36. case SWINF_FSM_REQ:
  37. INFO("WACS_FSM = SWINF_FSM_REQ\n");
  38. break;
  39. case SWINF_FSM_IDLE:
  40. goto done;
  41. default:
  42. break;
  43. }
  44. retry--;
  45. };
  46. done:
  47. if (retry == 0) {
  48. /* timeout */
  49. return E_PWR_WAIT_IDLE_TIMEOUT;
  50. }
  51. return 0U;
  52. }
  53. static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us)
  54. {
  55. uint32_t reg_rdata = 0U, retry;
  56. retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
  57. while (retry != 0) {
  58. udelay(READ_POLLING_DELAY_US);
  59. reg_rdata = mmio_read_32((uintptr_t)wacs_register);
  60. if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) {
  61. break;
  62. }
  63. retry--;
  64. };
  65. if (retry == 0) {
  66. /* timeout */
  67. return E_PWR_WAIT_IDLE_TIMEOUT;
  68. }
  69. return 0U;
  70. }
  71. static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata,
  72. uint32_t *rdata, uint32_t init_check)
  73. {
  74. uint32_t reg_rdata, return_value;
  75. if (init_check != 0) {
  76. if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) {
  77. ERROR("initialization isn't finished\n");
  78. return E_PWR_NOT_INIT_DONE;
  79. }
  80. }
  81. /* Wait for Software Interface FSM state to be IDLE. */
  82. return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta,
  83. PWRAP_WAIT_IDLE_US);
  84. if (return_value != 0) {
  85. return return_value;
  86. }
  87. /* Set the write data */
  88. if (write == 1) {
  89. /* Set the write data. */
  90. mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata);
  91. }
  92. /* Send the command. */
  93. mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr);
  94. if (write == 0) {
  95. /*
  96. * Wait for Software Interface FSM state to be WFVLDCLR,
  97. * read the data and clear the valid flag.
  98. */
  99. return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta,
  100. PWRAP_READ_US);
  101. if (return_value != 0) {
  102. return return_value;
  103. }
  104. if (rdata == NULL) {
  105. return E_PWR_INVALID_ARG;
  106. }
  107. reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
  108. *rdata = reg_rdata;
  109. mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
  110. }
  111. return return_value;
  112. }
  113. /* external API for pmic_wrap user */
  114. int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
  115. {
  116. return pwrap_wacs2(0, adr, 0, rdata, 1);
  117. }
  118. int32_t pwrap_write(uint32_t adr, uint32_t wdata)
  119. {
  120. return pwrap_wacs2(1, adr, wdata, 0, 1);
  121. }