123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /*
- * Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <common/debug.h>
- #include <drivers/delay_timer.h>
- #include <lib/mmio.h>
- #include <platform_def.h>
- #include <pmic_wrap_init.h>
- /* pmic wrap module wait_idle and read polling interval (in microseconds) */
- enum {
- WAIT_IDLE_POLLING_DELAY_US = 1,
- READ_POLLING_DELAY_US = 2
- };
- static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
- void *wacs_register,
- void *wacs_vldclr_register,
- uint32_t *read_reg)
- {
- uint32_t reg_rdata;
- uint32_t retry;
- retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
- WAIT_IDLE_POLLING_DELAY_US;
- do {
- udelay(WAIT_IDLE_POLLING_DELAY_US);
- reg_rdata = mmio_read_32((uintptr_t)wacs_register);
- /* if last read command timeout,clear vldclr bit
- * read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
- * write:FSM_REQ-->idle
- */
- switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
- RDATA_WACS_FSM_MASK)) {
- case WACS_FSM_WFVLDCLR:
- mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
- ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
- break;
- case WACS_FSM_WFDLE:
- ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
- break;
- case WACS_FSM_REQ:
- ERROR("WACS_FSM = WACS_FSM_REQ\n");
- break;
- case WACS_FSM_IDLE:
- goto done;
- default:
- break;
- }
- retry--;
- } while (retry);
- done:
- if (!retry) /* timeout */
- return E_PWR_WAIT_IDLE_TIMEOUT;
- if (read_reg)
- *read_reg = reg_rdata;
- return 0;
- }
- static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
- void *wacs_register,
- uint32_t *read_reg)
- {
- uint32_t reg_rdata;
- uint32_t retry;
- retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
- do {
- udelay(READ_POLLING_DELAY_US);
- reg_rdata = mmio_read_32((uintptr_t)wacs_register);
- if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
- == WACS_FSM_WFVLDCLR)
- break;
- retry--;
- } while (retry);
- if (!retry) { /* timeout */
- ERROR("timeout when waiting for idle\n");
- return E_PWR_WAIT_IDLE_TIMEOUT_READ;
- }
- if (read_reg)
- *read_reg = reg_rdata;
- return 0;
- }
- static int32_t pwrap_wacs2(uint32_t write,
- uint32_t adr,
- uint32_t wdata,
- uint32_t *rdata,
- uint32_t init_check)
- {
- uint32_t reg_rdata = 0;
- uint32_t wacs_write = 0;
- uint32_t wacs_adr = 0;
- uint32_t wacs_cmd = 0;
- uint32_t return_value = 0;
- if (init_check) {
- reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
- /* Prevent someone to used pwrap before pwrap init */
- if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
- RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
- ERROR("initialization isn't finished\n");
- return E_PWR_NOT_INIT_DONE;
- }
- }
- reg_rdata = 0;
- /* Check IDLE in advance */
- return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
- &mtk_pwrap->wacs2_rdata,
- &mtk_pwrap->wacs2_vldclr,
- 0);
- if (return_value != 0) {
- ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
- goto FAIL;
- }
- wacs_write = write << 31;
- wacs_adr = (adr >> 1) << 16;
- wacs_cmd = wacs_write | wacs_adr | wdata;
- mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, wacs_cmd);
- if (write == 0) {
- if (rdata == NULL) {
- ERROR("rdata is a NULL pointer\n");
- return_value = E_PWR_INVALID_ARG;
- goto FAIL;
- }
- return_value = wait_for_state_ready(TIMEOUT_READ,
- &mtk_pwrap->wacs2_rdata,
- ®_rdata);
- if (return_value != 0) {
- ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
- return_value);
- goto FAIL;
- }
- *rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
- & RDATA_WACS_RDATA_MASK);
- mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 1);
- }
- FAIL:
- return return_value;
- }
- /* external API for pmic_wrap user */
- int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
- {
- return pwrap_wacs2(0, adr, 0, rdata, 1);
- }
- int32_t pwrap_write(uint32_t adr, uint32_t wdata)
- {
- return pwrap_wacs2(1, adr, wdata, 0, 1);
- }
|