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