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