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