1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <device/mmio.h>
5 #include <soc/addressmap.h>
7 #include <soc/pmif_spi.h>
8 #include <soc/pmif_spmi.h>
9 #include <soc/pmif_sw.h>
13 static int pmif_check_swinf(struct pmif
*arb
, long timeout_us
, u32 expected_status
)
18 stopwatch_init_usecs_expire(&sw
, timeout_us
);
20 reg_rdata
= read32(&arb
->ch
->ch_sta
);
21 if (stopwatch_expired(&sw
))
23 } while (GET_SWINF_0_FSM(reg_rdata
) != expected_status
);
28 static void pmif_send_cmd(struct pmif
*arb
, int write
, u32 opc
, u32 slvid
,
29 u32 addr
, u32
*rdata
, u32 wdata
, u32 len
)
32 u32 data
, bc
= len
- 1;
34 /* Wait for Software Interface FSM state to be IDLE. */
35 ret
= pmif_check_swinf(arb
, PMIF_WAIT_IDLE_US
, SWINF_FSM_IDLE
);
37 printk(BIOS_ERR
, "[%s] idle timeout\n", __func__
);
41 /* Set the write data */
43 write32(&arb
->ch
->wdata
, wdata
);
45 /* Send the command. */
46 write32(&arb
->ch
->ch_send
,
47 (opc
<< 30) | (write
<< 29) | (slvid
<< 24) | (bc
<< 16) | addr
);
51 * Wait for Software Interface FSM state to be WFVLDCLR,
52 * read the data and clear the valid flag.
54 ret
= pmif_check_swinf(arb
, PMIF_READ_US
, SWINF_FSM_WFVLDCLR
);
56 printk(BIOS_ERR
, "[%s] read timeout\n", __func__
);
60 data
= read32(&arb
->ch
->rdata
);
62 write32(&arb
->ch
->ch_rdy
, 0x1);
66 void pmif_spmi_read(struct pmif
*arb
, u32 slvid
, u32 reg
, u32
*data
)
69 pmif_send_cmd(arb
, 0, PMIF_CMD_EXT_REG_LONG
, slvid
, reg
, data
, 0, 1);
72 void pmif_spmi_write(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 data
)
74 pmif_send_cmd(arb
, 1, PMIF_CMD_EXT_REG_LONG
, slvid
, reg
, NULL
, data
, 1);
77 void pmif_spmi_read16(struct pmif
*arb
, u32 slvid
, u32 reg
, u16
*data
)
80 pmif_send_cmd(arb
, 0, PMIF_CMD_EXT_REG_LONG
, slvid
, reg
, &rdata
, 0, 2);
84 void pmif_spmi_write16(struct pmif
*arb
, u32 slvid
, u32 reg
, u16 data
)
86 pmif_send_cmd(arb
, 1, PMIF_CMD_EXT_REG_LONG
, slvid
, reg
, NULL
, data
, 2);
89 u32
pmif_spmi_read_field(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 mask
, u32 shift
)
93 pmif_spmi_read(arb
, slvid
, reg
, &data
);
94 data
&= (mask
<< shift
);
100 void pmif_spmi_write_field(struct pmif
*arb
, u32 slvid
, u32 reg
,
101 u32 val
, u32 mask
, u32 shift
)
105 pmif_spmi_read(arb
, slvid
, reg
, &old
);
106 new = old
& ~(mask
<< shift
);
107 new |= (val
<< shift
);
108 pmif_spmi_write(arb
, slvid
, reg
, new);
111 void pmif_spi_read(struct pmif
*arb
, u32 slvid
, u32 reg
, u32
*data
)
114 pmif_send_cmd(arb
, 0, PMIF_CMD_REG_0
, slvid
, reg
, data
, 0, 1);
117 void pmif_spi_write(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 data
)
119 pmif_send_cmd(arb
, 1, PMIF_CMD_REG_0
, slvid
, reg
, NULL
, data
, 1);
122 u32
pmif_spi_read_field(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 mask
, u32 shift
)
126 pmif_spi_read(arb
, slvid
, reg
, &data
);
127 data
&= (mask
<< shift
);
133 void pmif_spi_write_field(struct pmif
*arb
, u32 slvid
, u32 reg
,
134 u32 val
, u32 mask
, u32 shift
)
138 pmif_spi_read(arb
, slvid
, reg
, &old
);
139 new = old
& ~(mask
<< shift
);
140 new |= (val
<< shift
);
141 pmif_spi_write(arb
, slvid
, reg
, new);
144 int pmif_check_init_done(struct pmif
*arb
)
146 if (read32(&arb
->mtk_pmif
->init_done
) & 0x1)
152 struct pmif
*get_pmif_controller(int inf
, int mstid
)
154 if (inf
== PMIF_SPMI
&& mstid
< pmif_spmi_arb_count
)
155 return (struct pmif
*)&pmif_spmi_arb
[mstid
];
156 else if (inf
== PMIF_SPI
)
157 return (struct pmif
*)&pmif_spi_arb
[0];
159 die("[%s] Failed to get pmif controller: inf = %d, mstid = %d\n", __func__
, inf
, mstid
);
163 static void pmif_select(enum pmic_interface mode
)
165 unsigned int spi_spm_sleep_req
, spi_scp_sleep_req
,
166 spmi_spm_sleep_req
, spmi_scp_sleep_req
,
167 spi_md_ctl_pmif_rdy
, spi_md_ctl_srclk_en
, spi_md_ctl_srvol_en
,
168 spmi_md_ctl_pmif_rdy
, spmi_md_ctl_srclk_en
, spmi_md_ctl_srvol_en
,
169 spi_inf_srclken_rc_en
, spi_other_inf_dcxo0_en
, spi_other_inf_dcxo1_en
,
170 spi_arb_srclken_rc_en
, spi_arb_dcxo_conn_en
, spi_arb_dcxo_nfc_en
;
174 /* spm and scp sleep request disable spi and spmi */
175 spi_spm_sleep_req
= 1;
176 spi_scp_sleep_req
= 1;
177 spmi_spm_sleep_req
= 1;
178 spmi_scp_sleep_req
= 1;
181 * pmic vld/rdy control spi mode enable
182 * srclken control spi mode disable
183 * vreq control spi mode disable
185 spi_md_ctl_pmif_rdy
= 1;
186 spi_md_ctl_srclk_en
= 0;
187 spi_md_ctl_srvol_en
= 0;
188 spmi_md_ctl_pmif_rdy
= 1;
189 spmi_md_ctl_srclk_en
= 0;
190 spmi_md_ctl_srvol_en
= 0;
192 /* srclken rc interface enable */
193 spi_inf_srclken_rc_en
= 1;
195 /* dcxo interface disable */
196 spi_other_inf_dcxo0_en
= 0;
197 spi_other_inf_dcxo1_en
= 0;
199 /* srclken enable, dcxo0,1 disable */
200 spi_arb_srclken_rc_en
= 1;
201 spi_arb_dcxo_conn_en
= 0;
202 spi_arb_dcxo_nfc_en
= 0;
206 /* spm and scp sleep request enable spi and spmi */
207 spi_spm_sleep_req
= 0;
208 spi_scp_sleep_req
= 0;
209 spmi_spm_sleep_req
= 0;
210 spmi_scp_sleep_req
= 0;
213 * pmic vld/rdy control spi mode disable
214 * srclken control spi mode enable
215 * vreq control spi mode enable
217 spi_md_ctl_pmif_rdy
= 0;
218 spi_md_ctl_srclk_en
= 1;
219 spi_md_ctl_srvol_en
= 1;
220 spmi_md_ctl_pmif_rdy
= 0;
221 spmi_md_ctl_srclk_en
= 1;
222 spmi_md_ctl_srvol_en
= 1;
224 /* srclken rc interface disable */
225 spi_inf_srclken_rc_en
= 0;
227 /* dcxo interface enable */
228 spi_other_inf_dcxo0_en
= 1;
229 spi_other_inf_dcxo1_en
= 1;
231 /* srclken disable, dcxo0,1 enable */
232 spi_arb_srclken_rc_en
= 0;
233 spi_arb_dcxo_conn_en
= 1;
234 spi_arb_dcxo_nfc_en
= 1;
238 die("Can't support pmif mode %d\n", mode
);
241 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->sleep_protection_ctrl
,
242 PMIFSPI_SPM_SLEEP_REQ_SEL
, spi_spm_sleep_req
,
243 PMIFSPI_SCP_SLEEP_REQ_SEL
, spi_scp_sleep_req
);
244 SET32_BITFIELDS(&pmif_spmi_arb
[0].mtk_pmif
->sleep_protection_ctrl
,
245 PMIFSPMI_SPM_SLEEP_REQ_SEL
, spmi_spm_sleep_req
,
246 PMIFSPMI_SCP_SLEEP_REQ_SEL
, spmi_scp_sleep_req
);
247 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->spi_mode_ctrl
,
248 PMIFSPI_MD_CTL_PMIF_RDY
, spi_md_ctl_pmif_rdy
,
249 PMIFSPI_MD_CTL_SRCLK_EN
, spi_md_ctl_srclk_en
,
250 PMIFSPI_MD_CTL_SRVOL_EN
, spi_md_ctl_srvol_en
);
251 SET32_BITFIELDS(&pmif_spmi_arb
[0].mtk_pmif
->spi_mode_ctrl
,
252 PMIFSPMI_MD_CTL_PMIF_RDY
, spmi_md_ctl_pmif_rdy
,
253 PMIFSPMI_MD_CTL_SRCLK_EN
, spmi_md_ctl_srclk_en
,
254 PMIFSPMI_MD_CTL_SRVOL_EN
, spmi_md_ctl_srvol_en
);
255 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->inf_en
,
256 PMIFSPI_INF_EN_SRCLKEN_RC_HW
, spi_inf_srclken_rc_en
);
257 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->other_inf_en
,
258 PMIFSPI_OTHER_INF_DXCO0_EN
, spi_other_inf_dcxo0_en
,
259 PMIFSPI_OTHER_INF_DXCO1_EN
, spi_other_inf_dcxo1_en
);
260 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->arb_en
,
261 PMIFSPI_ARB_EN_SRCLKEN_RC_HW
, spi_arb_srclken_rc_en
,
262 PMIFSPI_ARB_EN_DCXO_CONN
, spi_arb_dcxo_conn_en
,
263 PMIFSPI_ARB_EN_DCXO_NFC
, spi_arb_dcxo_nfc_en
);
266 void pmwrap_interface_init(void)
268 if (CONFIG(SRCLKEN_RC_SUPPORT
)) {
269 printk(BIOS_INFO
, "%s: Select PMIF_VLD_RDY\n", __func__
);
270 pmif_select(PMIF_VLD_RDY
);
272 printk(BIOS_INFO
, "%s: Select PMIF_SLP_REQ\n", __func__
);
273 pmif_select(PMIF_SLP_REQ
);