1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <console/console.h>
5 #include <device/mmio.h>
6 #include <soc/addressmap.h>
8 #include <soc/pmif_spi.h>
9 #include <soc/pmif_spmi.h>
10 #include <soc/pmif_sw.h>
14 static int pmif_check_swinf(struct pmif
*arb
, long timeout_us
, u32 expected_status
)
19 stopwatch_init_usecs_expire(&sw
, timeout_us
);
21 reg_rdata
= read32(&arb
->ch
->ch_sta
);
22 if (stopwatch_expired(&sw
))
24 } while (GET_SWINF_0_FSM(reg_rdata
) != expected_status
);
29 static void pmif_send_cmd(struct pmif
*arb
, int write
, u32 opc
, u32 slvid
,
30 u32 addr
, u32
*rdata
, u32 wdata
, u32 len
)
33 u32 data
, bc
= len
- 1;
35 /* Wait for Software Interface FSM state to be IDLE. */
36 ret
= pmif_check_swinf(arb
, PMIF_WAIT_IDLE_US
, SWINF_FSM_IDLE
);
38 printk(BIOS_ERR
, "[%s] idle timeout\n", __func__
);
42 /* Set the write data */
44 write32(&arb
->ch
->wdata
, wdata
);
46 /* Send the command. */
47 write32(&arb
->ch
->ch_send
,
48 (opc
<< 30) | (write
<< 29) | (slvid
<< 24) | (bc
<< 16) | addr
);
52 * Wait for Software Interface FSM state to be WFVLDCLR,
53 * read the data and clear the valid flag.
55 ret
= pmif_check_swinf(arb
, PMIF_READ_US
, SWINF_FSM_WFVLDCLR
);
57 printk(BIOS_ERR
, "[%s] read timeout\n", __func__
);
61 data
= read32(&arb
->ch
->rdata
);
63 write32(&arb
->ch
->ch_rdy
, 0x1);
67 static void pmif_spmi_read(struct pmif
*arb
, u32 slvid
, u32 reg
, u32
*data
)
70 pmif_send_cmd(arb
, 0, PMIF_CMD_EXT_REG_LONG
, slvid
, reg
, data
, 0, 1);
73 static void pmif_spmi_write(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 data
)
75 pmif_send_cmd(arb
, 1, PMIF_CMD_EXT_REG_LONG
, slvid
, reg
, NULL
, data
, 1);
78 static u32
pmif_spmi_read_field(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 mask
, u32 shift
)
82 pmif_spmi_read(arb
, slvid
, reg
, &data
);
83 data
&= (mask
<< shift
);
89 static void pmif_spmi_write_field(struct pmif
*arb
, u32 slvid
, u32 reg
,
90 u32 val
, u32 mask
, u32 shift
)
94 pmif_spmi_read(arb
, slvid
, reg
, &old
);
95 new = old
& ~(mask
<< shift
);
96 new |= (val
<< shift
);
97 pmif_spmi_write(arb
, slvid
, reg
, new);
100 static void pmif_spi_read(struct pmif
*arb
, u32 slvid
, u32 reg
, u32
*data
)
103 pmif_send_cmd(arb
, 0, PMIF_CMD_REG_0
, slvid
, reg
, data
, 0, 1);
106 static void pmif_spi_write(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 data
)
108 pmif_send_cmd(arb
, 1, PMIF_CMD_REG_0
, slvid
, reg
, NULL
, data
, 1);
111 static u32
pmif_spi_read_field(struct pmif
*arb
, u32 slvid
, u32 reg
, u32 mask
, u32 shift
)
115 pmif_spi_read(arb
, slvid
, reg
, &data
);
116 data
&= (mask
<< shift
);
122 static void pmif_spi_write_field(struct pmif
*arb
, u32 slvid
, u32 reg
,
123 u32 val
, u32 mask
, u32 shift
)
127 pmif_spi_read(arb
, slvid
, reg
, &old
);
128 new = old
& ~(mask
<< shift
);
129 new |= (val
<< shift
);
130 pmif_spi_write(arb
, slvid
, reg
, new);
133 static int is_pmif_init_done(struct pmif
*arb
)
135 if (read32(&arb
->mtk_pmif
->init_done
) & 0x1)
141 static const struct pmif pmif_spmi_arb
[] = {
143 .mtk_pmif
= (struct mtk_pmif_regs
*)PMIF_SPMI_BASE
,
144 .ch
= (struct chan_regs
*)PMIF_SPMI_AP_CHAN
,
145 .mstid
= SPMI_MASTER_0
,
147 .write
= pmif_spmi_write
,
148 .read
= pmif_spmi_read
,
149 .write_field
= pmif_spmi_write_field
,
150 .read_field
= pmif_spmi_read_field
,
151 .is_pmif_init_done
= is_pmif_init_done
,
155 static const struct pmif pmif_spi_arb
[] = {
157 .mtk_pmif
= (struct mtk_pmif_regs
*)PMIF_SPI_BASE
,
158 .ch
= (struct chan_regs
*)PMIF_SPI_AP_CHAN
,
160 .write
= pmif_spi_write
,
161 .read
= pmif_spi_read
,
162 .write_field
= pmif_spi_write_field
,
163 .read_field
= pmif_spi_read_field
,
164 .is_pmif_init_done
= is_pmif_init_done
,
168 struct pmif
*get_pmif_controller(int inf
, int mstid
)
170 if (inf
== PMIF_SPMI
&& mstid
< ARRAY_SIZE(pmif_spmi_arb
))
171 return (struct pmif
*)&pmif_spmi_arb
[mstid
];
172 else if (inf
== PMIF_SPI
)
173 return (struct pmif
*)&pmif_spi_arb
[0];
175 die("[%s] Failed to get pmif controller: inf = %d, mstid = %d\n", __func__
, inf
, mstid
);
179 static void pmif_select(enum pmic_interface mode
)
181 unsigned int spi_spm_sleep_req
, spi_scp_sleep_req
,
182 spmi_spm_sleep_req
, spmi_scp_sleep_req
,
183 spi_md_ctl_pmif_rdy
, spi_md_ctl_srclk_en
, spi_md_ctl_srvol_en
,
184 spmi_md_ctl_pmif_rdy
, spmi_md_ctl_srclk_en
, spmi_md_ctl_srvol_en
,
185 spi_inf_srclken_rc_en
, spi_other_inf_dcxo0_en
, spi_other_inf_dcxo1_en
,
186 spi_arb_srclken_rc_en
, spi_arb_dcxo_conn_en
, spi_arb_dcxo_nfc_en
;
190 /* spm and scp sleep request disable spi and spmi */
191 spi_spm_sleep_req
= 1;
192 spi_scp_sleep_req
= 1;
193 spmi_spm_sleep_req
= 1;
194 spmi_scp_sleep_req
= 1;
197 * pmic vld/rdy control spi mode enable
198 * srclken control spi mode disable
199 * vreq control spi mode disable
201 spi_md_ctl_pmif_rdy
= 1;
202 spi_md_ctl_srclk_en
= 0;
203 spi_md_ctl_srvol_en
= 0;
204 spmi_md_ctl_pmif_rdy
= 1;
205 spmi_md_ctl_srclk_en
= 0;
206 spmi_md_ctl_srvol_en
= 0;
208 /* srclken rc interface enable */
209 spi_inf_srclken_rc_en
= 1;
211 /* dcxo interface disable */
212 spi_other_inf_dcxo0_en
= 0;
213 spi_other_inf_dcxo1_en
= 0;
215 /* srclken enable, dcxo0,1 disable */
216 spi_arb_srclken_rc_en
= 1;
217 spi_arb_dcxo_conn_en
= 0;
218 spi_arb_dcxo_nfc_en
= 0;
222 /* spm and scp sleep request enable spi and spmi */
223 spi_spm_sleep_req
= 0;
224 spi_scp_sleep_req
= 0;
225 spmi_spm_sleep_req
= 0;
226 spmi_scp_sleep_req
= 0;
229 * pmic vld/rdy control spi mode disable
230 * srclken control spi mode enable
231 * vreq control spi mode enable
233 spi_md_ctl_pmif_rdy
= 0;
234 spi_md_ctl_srclk_en
= 1;
235 spi_md_ctl_srvol_en
= 1;
236 spmi_md_ctl_pmif_rdy
= 0;
237 spmi_md_ctl_srclk_en
= 1;
238 spmi_md_ctl_srvol_en
= 1;
240 /* srclken rc interface disable */
241 spi_inf_srclken_rc_en
= 0;
243 /* dcxo interface enable */
244 spi_other_inf_dcxo0_en
= 1;
245 spi_other_inf_dcxo1_en
= 1;
247 /* srclken disable, dcxo0,1 enable */
248 spi_arb_srclken_rc_en
= 0;
249 spi_arb_dcxo_conn_en
= 1;
250 spi_arb_dcxo_nfc_en
= 1;
254 die("Can't support pmif mode %d\n", mode
);
257 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->sleep_protection_ctrl
,
258 PMIFSPI_SPM_SLEEP_REQ_SEL
, spi_spm_sleep_req
,
259 PMIFSPI_SCP_SLEEP_REQ_SEL
, spi_scp_sleep_req
);
260 SET32_BITFIELDS(&pmif_spmi_arb
[0].mtk_pmif
->sleep_protection_ctrl
,
261 PMIFSPMI_SPM_SLEEP_REQ_SEL
, spmi_spm_sleep_req
,
262 PMIFSPMI_SCP_SLEEP_REQ_SEL
, spmi_scp_sleep_req
);
263 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->spi_mode_ctrl
,
264 PMIFSPI_MD_CTL_PMIF_RDY
, spi_md_ctl_pmif_rdy
,
265 PMIFSPI_MD_CTL_SRCLK_EN
, spi_md_ctl_srclk_en
,
266 PMIFSPI_MD_CTL_SRVOL_EN
, spi_md_ctl_srvol_en
);
267 SET32_BITFIELDS(&pmif_spmi_arb
[0].mtk_pmif
->spi_mode_ctrl
,
268 PMIFSPMI_MD_CTL_PMIF_RDY
, spmi_md_ctl_pmif_rdy
,
269 PMIFSPMI_MD_CTL_SRCLK_EN
, spmi_md_ctl_srclk_en
,
270 PMIFSPMI_MD_CTL_SRVOL_EN
, spmi_md_ctl_srvol_en
);
271 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->inf_en
,
272 PMIFSPI_INF_EN_SRCLKEN_RC_HW
, spi_inf_srclken_rc_en
);
273 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->other_inf_en
,
274 PMIFSPI_OTHER_INF_DXCO0_EN
, spi_other_inf_dcxo0_en
,
275 PMIFSPI_OTHER_INF_DXCO1_EN
, spi_other_inf_dcxo1_en
);
276 SET32_BITFIELDS(&pmif_spi_arb
[0].mtk_pmif
->arb_en
,
277 PMIFSPI_ARB_EN_SRCLKEN_RC_HW
, spi_arb_srclken_rc_en
,
278 PMIFSPI_ARB_EN_DCXO_CONN
, spi_arb_dcxo_conn_en
,
279 PMIFSPI_ARB_EN_DCXO_NFC
, spi_arb_dcxo_nfc_en
);
282 void pmwrap_interface_init(void)
284 if (CONFIG(SRCLKEN_RC_SUPPORT
)) {
285 printk(BIOS_INFO
, "%s: Select PMIF_VLD_RDY\n", __func__
);
286 pmif_select(PMIF_VLD_RDY
);
288 printk(BIOS_INFO
, "%s: Select PMIF_SLP_REQ\n", __func__
);
289 pmif_select(PMIF_SLP_REQ
);
293 int mtk_pmif_init(void)
297 ret
= pmif_clk_init();
299 ret
= pmif_spmi_init(get_pmif_controller(PMIF_SPMI
, SPMI_MASTER_0
));
300 if (!ret
&& !CONFIG(PWRAP_WITH_PMIF_SPMI
))
301 ret
= pmif_spi_init(get_pmif_controller(PMIF_SPI
, 0));