1 /* 2 * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <common/debug.h> 8 #include <drivers/delay_timer.h> 9 #include <lib/mmio.h> 10 11 #include "platform_def.h" 12 #include "pmic_wrap_init.h" 13 14 /* pmic wrap module wait_idle and read polling interval (in microseconds) */ 15 enum pwrap_polling_interval { 16 WAIT_IDLE_POLLING_DELAY_US = 1, 17 READ_POLLING_DELAY_US = 2 18 }; 19 20 static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us) 21 { 22 uint32_t reg_rdata = 0U, retry; 23 24 retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) / 25 WAIT_IDLE_POLLING_DELAY_US; 26 while (retry != 0) { 27 udelay(WAIT_IDLE_POLLING_DELAY_US); 28 reg_rdata = mmio_read_32((uintptr_t)wacs_register); 29 /* if last read command timeout,clear vldclr bit 30 * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR; 31 * write:FSM_REQ-->idle 32 */ 33 switch (GET_WACS_FSM(reg_rdata)) { 34 case SWINF_FSM_WFVLDCLR: 35 mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1); 36 INFO("WACS_FSM = SWINF_FSM_WFVLDCLR\n"); 37 break; 38 case SWINF_FSM_WFDLE: 39 INFO("WACS_FSM = SWINF_FSM_WFDLE\n"); 40 break; 41 case SWINF_FSM_REQ: 42 INFO("WACS_FSM = SWINF_FSM_REQ\n"); 43 break; 44 case SWINF_FSM_IDLE: 45 goto done; 46 default: 47 break; 48 } 49 retry--; 50 }; 51 52 done: 53 if (retry == 0) { 54 /* timeout */ 55 return E_PWR_WAIT_IDLE_TIMEOUT; 56 } 57 58 return 0U; 59 } 60 61 static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us) 62 { 63 uint32_t reg_rdata = 0U, retry; 64 65 retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US; 66 while (retry != 0) { 67 udelay(READ_POLLING_DELAY_US); 68 reg_rdata = mmio_read_32((uintptr_t)wacs_register); 69 if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) { 70 break; 71 } 72 retry--; 73 }; 74 75 if (retry == 0) { 76 /* timeout */ 77 return E_PWR_WAIT_IDLE_TIMEOUT; 78 } 79 80 return 0U; 81 } 82 83 static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata, 84 uint32_t *rdata, uint32_t init_check) 85 { 86 uint32_t reg_rdata, return_value; 87 88 if (init_check != 0) { 89 if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) { 90 ERROR("initialization isn't finished\n"); 91 return E_PWR_NOT_INIT_DONE; 92 } 93 } 94 95 /* Wait for Software Interface FSM state to be IDLE. */ 96 return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta, 97 PWRAP_WAIT_IDLE_US); 98 if (return_value != 0) { 99 return return_value; 100 } 101 102 /* Set the write data */ 103 if (write == 1) { 104 /* Set the write data. */ 105 mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata); 106 } 107 108 /* Send the command. */ 109 mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr); 110 111 if (write == 0) { 112 /* 113 * Wait for Software Interface FSM state to be WFVLDCLR, 114 * read the data and clear the valid flag. 115 */ 116 return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta, 117 PWRAP_READ_US); 118 if (return_value != 0) { 119 return return_value; 120 } 121 122 if (rdata == NULL) { 123 return E_PWR_INVALID_ARG; 124 } 125 126 reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata); 127 *rdata = reg_rdata; 128 mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1); 129 } 130 131 return return_value; 132 } 133 134 /* external API for pmic_wrap user */ 135 int32_t pwrap_read(uint32_t adr, uint32_t *rdata) 136 { 137 return pwrap_wacs2(0, adr, 0, rdata, 1); 138 } 139 140 int32_t pwrap_write(uint32_t adr, uint32_t wdata) 141 { 142 return pwrap_wacs2(1, adr, wdata, 0, 1); 143 } 144