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 u32
pmif_spmi_read_field(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 mask
, u32 shift
)
81 pmif_spmi_read(arb
, slvid
, reg
, &data
);
82 data
&= (mask
<< shift
);
88 void pmif_spmi_write_field(struct pmif
*arb
, u32 slvid
, u32 reg
,
89 u32 val
, u32 mask
, u32 shift
)
93 pmif_spmi_read(arb
, slvid
, reg
, &old
);
94 new = old
& ~(mask
<< shift
);
95 new |= (val
<< shift
);
96 pmif_spmi_write(arb
, slvid
, reg
, new);
99 void pmif_spi_read(struct pmif
*arb
, u32 slvid
, u32 reg
, u32
*data
)
102 pmif_send_cmd(arb
, 0, PMIF_CMD_REG_0
, slvid
, reg
, data
, 0, 1);
105 void pmif_spi_write(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 data
)
107 pmif_send_cmd(arb
, 1, PMIF_CMD_REG_0
, slvid
, reg
, NULL
, data
, 1);
110 u32
pmif_spi_read_field(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 mask
, u32 shift
)
114 pmif_spi_read(arb
, slvid
, reg
, &data
);
115 data
&= (mask
<< shift
);
121 void pmif_spi_write_field(struct pmif
*arb
, u32 slvid
, u32 reg
,
122 u32 val
, u32 mask
, u32 shift
)
126 pmif_spi_read(arb
, slvid
, reg
, &old
);
127 new = old
& ~(mask
<< shift
);
128 new |= (val
<< shift
);
129 pmif_spi_write(arb
, slvid
, reg
, new);
132 int pmif_check_init_done(struct pmif
*arb
)
134 if (read32(&arb
->mtk_pmif
->init_done
) & 0x1)
140 struct pmif
*get_pmif_controller(int inf
, int mstid
)
142 if (inf
== PMIF_SPMI
&& mstid
< pmif_spmi_arb_count
)
143 return (struct pmif
*)&pmif_spmi_arb
[mstid
];
144 else if (inf
== PMIF_SPI
)
145 return (struct pmif
*)&pmif_spi_arb
[0];
147 die("[%s] Failed to get pmif controller: inf = %d, mstid = %d\n", __func__
, inf
, mstid
);
151 static void pmif_select(enum pmic_interface mode
)
153 unsigned int spi_spm_sleep_req
, spi_scp_sleep_req
,
154 spmi_spm_sleep_req
, spmi_scp_sleep_req
,
155 spi_md_ctl_pmif_rdy
, spi_md_ctl_srclk_en
, spi_md_ctl_srvol_en
,
156 spmi_md_ctl_pmif_rdy
, spmi_md_ctl_srclk_en
, spmi_md_ctl_srvol_en
,
157 spi_inf_srclken_rc_en
, spi_other_inf_dcxo0_en
, spi_other_inf_dcxo1_en
,
158 spi_arb_srclken_rc_en
, spi_arb_dcxo_conn_en
, spi_arb_dcxo_nfc_en
;
162 /* spm and scp sleep request disable spi and spmi */
163 spi_spm_sleep_req
= 1;
164 spi_scp_sleep_req
= 1;
165 spmi_spm_sleep_req
= 1;
166 spmi_scp_sleep_req
= 1;
169 * pmic vld/rdy control spi mode enable
170 * srclken control spi mode disable
171 * vreq control spi mode disable
173 spi_md_ctl_pmif_rdy
= 1;
174 spi_md_ctl_srclk_en
= 0;
175 spi_md_ctl_srvol_en
= 0;
176 spmi_md_ctl_pmif_rdy
= 1;
177 spmi_md_ctl_srclk_en
= 0;
178 spmi_md_ctl_srvol_en
= 0;
180 /* srclken rc interface enable */
181 spi_inf_srclken_rc_en
= 1;
183 /* dcxo interface disable */
184 spi_other_inf_dcxo0_en
= 0;
185 spi_other_inf_dcxo1_en
= 0;
187 /* srclken enable, dcxo0,1 disable */
188 spi_arb_srclken_rc_en
= 1;
189 spi_arb_dcxo_conn_en
= 0;
190 spi_arb_dcxo_nfc_en
= 0;
194 /* spm and scp sleep request enable spi and spmi */
195 spi_spm_sleep_req
= 0;
196 spi_scp_sleep_req
= 0;
197 spmi_spm_sleep_req
= 0;
198 spmi_scp_sleep_req
= 0;
201 * pmic vld/rdy control spi mode disable
202 * srclken control spi mode enable
203 * vreq control spi mode enable
205 spi_md_ctl_pmif_rdy
= 0;
206 spi_md_ctl_srclk_en
= 1;
207 spi_md_ctl_srvol_en
= 1;
208 spmi_md_ctl_pmif_rdy
= 0;
209 spmi_md_ctl_srclk_en
= 1;
210 spmi_md_ctl_srvol_en
= 1;
212 /* srclken rc interface disable */
213 spi_inf_srclken_rc_en
= 0;
215 /* dcxo interface enable */
216 spi_other_inf_dcxo0_en
= 1;
217 spi_other_inf_dcxo1_en
= 1;
219 /* srclken disable, dcxo0,1 enable */
220 spi_arb_srclken_rc_en
= 0;
221 spi_arb_dcxo_conn_en
= 1;
222 spi_arb_dcxo_nfc_en
= 1;
226 die("Can't support pmif mode %d\n", mode
);
229 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->sleep_protection_ctrl
,
230 PMIFSPI_SPM_SLEEP_REQ_SEL
, spi_spm_sleep_req
,
231 PMIFSPI_SCP_SLEEP_REQ_SEL
, spi_scp_sleep_req
);
232 SET32_BITFIELDS(&pmif_spmi_arb
[0].mtk_pmif
->sleep_protection_ctrl
,
233 PMIFSPMI_SPM_SLEEP_REQ_SEL
, spmi_spm_sleep_req
,
234 PMIFSPMI_SCP_SLEEP_REQ_SEL
, spmi_scp_sleep_req
);
235 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->spi_mode_ctrl
,
236 PMIFSPI_MD_CTL_PMIF_RDY
, spi_md_ctl_pmif_rdy
,
237 PMIFSPI_MD_CTL_SRCLK_EN
, spi_md_ctl_srclk_en
,
238 PMIFSPI_MD_CTL_SRVOL_EN
, spi_md_ctl_srvol_en
);
239 SET32_BITFIELDS(&pmif_spmi_arb
[0].mtk_pmif
->spi_mode_ctrl
,
240 PMIFSPMI_MD_CTL_PMIF_RDY
, spmi_md_ctl_pmif_rdy
,
241 PMIFSPMI_MD_CTL_SRCLK_EN
, spmi_md_ctl_srclk_en
,
242 PMIFSPMI_MD_CTL_SRVOL_EN
, spmi_md_ctl_srvol_en
);
243 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->inf_en
,
244 PMIFSPI_INF_EN_SRCLKEN_RC_HW
, spi_inf_srclken_rc_en
);
245 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->other_inf_en
,
246 PMIFSPI_OTHER_INF_DXCO0_EN
, spi_other_inf_dcxo0_en
,
247 PMIFSPI_OTHER_INF_DXCO1_EN
, spi_other_inf_dcxo1_en
);
248 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->arb_en
,
249 PMIFSPI_ARB_EN_SRCLKEN_RC_HW
, spi_arb_srclken_rc_en
,
250 PMIFSPI_ARB_EN_DCXO_CONN
, spi_arb_dcxo_conn_en
,
251 PMIFSPI_ARB_EN_DCXO_NFC
, spi_arb_dcxo_nfc_en
);
254 void pmwrap_interface_init(void)
256 if (CONFIG(SRCLKEN_RC_SUPPORT
)) {
257 printk(BIOS_INFO
, "%s: Select PMIF_VLD_RDY\n", __func__
);
258 pmif_select(PMIF_VLD_RDY
);
260 printk(BIOS_INFO
, "%s: Select PMIF_SLP_REQ\n", __func__
);
261 pmif_select(PMIF_SLP_REQ
);