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