2 * This file is part of the coreboot project.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <device/mmio.h>
16 #include <soc/pmic_wrap.h>
19 u32
wait_for_state_idle(u32 timeout_us
, void *wacs_register
,
20 void *wacs_vldclr_register
, u32
*read_reg
)
26 stopwatch_init_usecs_expire(&sw
, timeout_us
);
28 reg_rdata
= read32((wacs_register
));
29 /* if last read command timeout,clear vldclr bit
30 read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
31 write:FSM_REQ-->idle */
32 switch (((reg_rdata
>> RDATA_WACS_FSM_SHIFT
) &
33 RDATA_WACS_FSM_MASK
)) {
34 case WACS_FSM_WFVLDCLR
:
35 write32(wacs_vldclr_register
, 1);
36 pwrap_err("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
39 pwrap_err("WACS_FSM = WACS_FSM_WFDLE\n");
42 pwrap_err("WACS_FSM = WACS_FSM_REQ\n");
48 if (stopwatch_expired(&sw
))
49 return E_PWR_WAIT_IDLE_TIMEOUT
;
51 } while (((reg_rdata
>> RDATA_WACS_FSM_SHIFT
) & RDATA_WACS_FSM_MASK
) !=
52 WACS_FSM_IDLE
); /* IDLE State */
54 *read_reg
= reg_rdata
;
58 u32
wait_for_state_ready(loop_condition_fp fp
, u32 timeout_us
,
59 void *wacs_register
, u32
*read_reg
)
64 stopwatch_init_usecs_expire(&sw
, timeout_us
);
66 reg_rdata
= read32((wacs_register
));
68 if (stopwatch_expired(&sw
)) {
69 pwrap_err("timeout when waiting for idle\n");
70 return E_PWR_WAIT_IDLE_TIMEOUT
;
72 } while (fp(reg_rdata
)); /* IDLE State */
74 *read_reg
= reg_rdata
;
78 s32
pwrap_reset_spislv(void)
82 write32(&mtk_pwrap
->hiprio_arb_en
, 0);
83 write32(&mtk_pwrap
->wrap_en
, 0);
84 write32(&mtk_pwrap
->mux_sel
, 1);
85 write32(&mtk_pwrap
->man_en
, 1);
86 write32(&mtk_pwrap
->dio_en
, 0);
88 write32(&mtk_pwrap
->man_cmd
, (OP_WR
<< 13) | (OP_CSL
<< 8));
90 write32(&mtk_pwrap
->man_cmd
, (OP_WR
<< 13) | (OP_OUTS
<< 8));
91 write32(&mtk_pwrap
->man_cmd
, (OP_WR
<< 13) | (OP_CSH
<< 8));
93 * In order to pull CSN signal to PMIC,
94 * PMIC will count it then reset spi slave
96 write32(&mtk_pwrap
->man_cmd
, (OP_WR
<< 13) | (OP_OUTS
<< 8));
97 write32(&mtk_pwrap
->man_cmd
, (OP_WR
<< 13) | (OP_OUTS
<< 8));
98 write32(&mtk_pwrap
->man_cmd
, (OP_WR
<< 13) | (OP_OUTS
<< 8));
99 write32(&mtk_pwrap
->man_cmd
, (OP_WR
<< 13) | (OP_OUTS
<< 8));
101 if (wait_for_state_ready(wait_for_sync
, TIMEOUT_WAIT_IDLE_US
,
102 &mtk_pwrap
->wacs2_rdata
, 0))
105 write32(&mtk_pwrap
->man_en
, 0);
106 write32(&mtk_pwrap
->mux_sel
, 0);
111 s32
pwrap_wacs2(u32 write
, u16 addr
, u16 wdata
, u16
*rdata
, u32 init_check
)
120 reg_rdata
= read32(&mtk_pwrap
->wacs2_rdata
);
121 /* Prevent someone to use pwrap before pwrap init */
122 if (((reg_rdata
>> RDATA_INIT_DONE_SHIFT
) &
123 RDATA_INIT_DONE_MASK
) != WACS_INIT_DONE
) {
124 pwrap_err("Pwrap initialization isn't finished\n");
125 return E_PWR_NOT_INIT_DONE
;
129 /* Check IDLE in advance */
130 wait_result
= wait_for_state_idle(TIMEOUT_WAIT_IDLE_US
,
131 &mtk_pwrap
->wacs2_rdata
,
132 &mtk_pwrap
->wacs2_vldclr
,
134 if (wait_result
!= 0) {
135 pwrap_err("wait_for_fsm_idle fail,wait_result=%d\n",
137 return E_PWR_WAIT_IDLE_TIMEOUT
;
139 wacs_write
= write
<< 31;
140 wacs_addr
= (addr
>> 1) << 16;
141 wacs_cmd
= wacs_write
| wacs_addr
| wdata
;
143 write32(&mtk_pwrap
->wacs2_cmd
, wacs_cmd
);
146 pwrap_err("rdata is a NULL pointer\n");
147 return E_PWR_INVALID_ARG
;
149 wait_result
= wait_for_state_ready(wait_for_fsm_vldclr
,
151 &mtk_pwrap
->wacs2_rdata
,
153 if (wait_result
!= 0) {
154 pwrap_err("wait_for_fsm_vldclr fail,wait_result=%d\n",
156 return E_PWR_WAIT_IDLE_TIMEOUT_READ
;
158 *rdata
= ((reg_rdata
>> RDATA_WACS_RDATA_SHIFT
)
159 & RDATA_WACS_RDATA_MASK
);
160 write32(&mtk_pwrap
->wacs2_vldclr
, 1);