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
wait_for_state_idle(uint32_t timeout_us,void * wacs_register,void * wacs_vldclr_register,uint32_t * read_reg)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
wait_for_state_ready(uint32_t timeout_us,void * wacs_register,uint32_t * read_reg)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
pwrap_wacs2(uint32_t write,uint32_t adr,uint32_t wdata,uint32_t * rdata,uint32_t init_check)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
pwrap_read(uint32_t adr,uint32_t * rdata)155 int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
156 {
157 return pwrap_wacs2(0, adr, 0, rdata, 1);
158 }
159
pwrap_write(uint32_t adr,uint32_t wdata)160 int32_t pwrap_write(uint32_t adr, uint32_t wdata)
161 {
162 return pwrap_wacs2(1, adr, wdata, 0, 1);
163 }
164