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