xref: /aosp_15_r20/external/coreboot/src/soc/mediatek/common/pmif.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <console/console.h>
5 #include <device/mmio.h>
6 #include <soc/addressmap.h>
7 #include <soc/pmif.h>
8 #include <soc/pmif_spi.h>
9 #include <soc/pmif_spmi.h>
10 #include <soc/pmif_sw.h>
11 #include <soc/spmi.h>
12 #include <timer.h>
13 
pmif_check_swinf(struct pmif * arb,long timeout_us,u32 expected_status)14 static int pmif_check_swinf(struct pmif *arb, long timeout_us, u32 expected_status)
15 {
16 	u32 reg_rdata;
17 	struct stopwatch sw;
18 
19 	stopwatch_init_usecs_expire(&sw, timeout_us);
20 	do {
21 		reg_rdata = read32(&arb->ch->ch_sta);
22 		if (stopwatch_expired(&sw))
23 			return E_TIMEOUT;
24 	} while (GET_SWINF_0_FSM(reg_rdata) != expected_status);
25 
26 	return 0;
27 }
28 
pmif_send_cmd(struct pmif * arb,int write,u32 opc,u32 slvid,u32 addr,u32 * rdata,u32 wdata,u32 len)29 static void pmif_send_cmd(struct pmif *arb, int write, u32 opc, u32 slvid,
30 			  u32 addr, u32 *rdata, u32 wdata, u32 len)
31 {
32 	int ret;
33 	u32 data, bc = len - 1;
34 
35 	/* Wait for Software Interface FSM state to be IDLE. */
36 	ret = pmif_check_swinf(arb, PMIF_WAIT_IDLE_US, SWINF_FSM_IDLE);
37 	if (ret) {
38 		printk(BIOS_ERR, "[%s] idle timeout\n", __func__);
39 		return;
40 	}
41 
42 	/* Set the write data */
43 	if (write)
44 		write32(&arb->ch->wdata, wdata);
45 
46 	/* Send the command. */
47 	write32(&arb->ch->ch_send,
48 		(opc << 30) | (write << 29) | (slvid << 24) | (bc << 16) | addr);
49 
50 	if (!write) {
51 		/*
52 		 * Wait for Software Interface FSM state to be WFVLDCLR,
53 		 * read the data and clear the valid flag.
54 		 */
55 		ret = pmif_check_swinf(arb, PMIF_READ_US, SWINF_FSM_WFVLDCLR);
56 		if (ret) {
57 			printk(BIOS_ERR, "[%s] read timeout\n", __func__);
58 			return;
59 		}
60 
61 		data = read32(&arb->ch->rdata);
62 		*rdata = data;
63 		write32(&arb->ch->ch_rdy, 0x1);
64 	}
65 }
66 
pmif_spmi_read(struct pmif * arb,u32 slvid,u32 reg,u32 * data)67 static void pmif_spmi_read(struct pmif *arb, u32 slvid, u32 reg, u32 *data)
68 {
69 	*data = 0;
70 	pmif_send_cmd(arb, 0, PMIF_CMD_EXT_REG_LONG, slvid, reg, data, 0, 1);
71 }
72 
pmif_spmi_write(struct pmif * arb,u32 slvid,u32 reg,u32 data)73 static void pmif_spmi_write(struct pmif *arb, u32 slvid, u32 reg, u32 data)
74 {
75 	pmif_send_cmd(arb, 1, PMIF_CMD_EXT_REG_LONG, slvid, reg, NULL, data, 1);
76 }
77 
pmif_spmi_read_field(struct pmif * arb,u32 slvid,u32 reg,u32 mask,u32 shift)78 static u32 pmif_spmi_read_field(struct pmif *arb, u32 slvid, u32 reg, u32 mask, u32 shift)
79 {
80 	u32 data;
81 
82 	pmif_spmi_read(arb, slvid, reg, &data);
83 	data &= (mask << shift);
84 	data >>= shift;
85 
86 	return data;
87 }
88 
pmif_spmi_write_field(struct pmif * arb,u32 slvid,u32 reg,u32 val,u32 mask,u32 shift)89 static void pmif_spmi_write_field(struct pmif *arb, u32 slvid, u32 reg,
90 				  u32 val, u32 mask, u32 shift)
91 {
92 	u32 old, new;
93 
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);
98 }
99 
pmif_spi_read(struct pmif * arb,u32 slvid,u32 reg,u32 * data)100 static void pmif_spi_read(struct pmif *arb, u32 slvid, u32 reg, u32 *data)
101 {
102 	*data = 0;
103 	pmif_send_cmd(arb, 0, PMIF_CMD_REG_0, slvid, reg, data, 0, 1);
104 }
105 
pmif_spi_write(struct pmif * arb,u32 slvid,u32 reg,u32 data)106 static void pmif_spi_write(struct pmif *arb, u32 slvid, u32 reg, u32 data)
107 {
108 	pmif_send_cmd(arb, 1, PMIF_CMD_REG_0, slvid, reg, NULL, data, 1);
109 }
110 
pmif_spi_read_field(struct pmif * arb,u32 slvid,u32 reg,u32 mask,u32 shift)111 static u32 pmif_spi_read_field(struct pmif *arb, u32 slvid, u32 reg, u32 mask, u32 shift)
112 {
113 	u32 data;
114 
115 	pmif_spi_read(arb, slvid, reg, &data);
116 	data &= (mask << shift);
117 	data >>= shift;
118 
119 	return data;
120 }
121 
pmif_spi_write_field(struct pmif * arb,u32 slvid,u32 reg,u32 val,u32 mask,u32 shift)122 static void pmif_spi_write_field(struct pmif *arb, u32 slvid, u32 reg,
123 				 u32 val, u32 mask, u32 shift)
124 {
125 	u32 old, new;
126 
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);
131 }
132 
is_pmif_init_done(struct pmif * arb)133 static int is_pmif_init_done(struct pmif *arb)
134 {
135 	if (read32(&arb->mtk_pmif->init_done) & 0x1)
136 		return 0;
137 
138 	return -E_NODEV;
139 }
140 
141 static const struct pmif pmif_spmi_arb[] = {
142 	{
143 		.mtk_pmif = (struct mtk_pmif_regs *)PMIF_SPMI_BASE,
144 		.ch = (struct chan_regs *)PMIF_SPMI_AP_CHAN,
145 		.mstid = SPMI_MASTER_0,
146 		.pmifid = PMIF_SPMI,
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,
152 	},
153 };
154 
155 static const struct pmif pmif_spi_arb[] = {
156 	{
157 		.mtk_pmif = (struct mtk_pmif_regs *)PMIF_SPI_BASE,
158 		.ch = (struct chan_regs *)PMIF_SPI_AP_CHAN,
159 		.pmifid = PMIF_SPI,
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,
165 	},
166 };
167 
get_pmif_controller(int inf,int mstid)168 struct pmif *get_pmif_controller(int inf, int mstid)
169 {
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];
174 
175 	die("[%s] Failed to get pmif controller: inf = %d, mstid = %d\n", __func__, inf, mstid);
176 	return NULL;
177 }
178 
pmif_select(enum pmic_interface mode)179 static void pmif_select(enum pmic_interface mode)
180 {
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;
187 
188 	switch (mode) {
189 	case PMIF_VLD_RDY:
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;
195 
196 		/*
197 		 * pmic vld/rdy control spi mode enable
198 		 * srclken control spi mode disable
199 		 * vreq control spi mode disable
200 		 */
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;
207 
208 		/* srclken rc interface enable */
209 		spi_inf_srclken_rc_en = 1;
210 
211 		/* dcxo interface disable */
212 		spi_other_inf_dcxo0_en = 0;
213 		spi_other_inf_dcxo1_en = 0;
214 
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;
219 		break;
220 
221 	case PMIF_SLP_REQ:
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;
227 
228 		/*
229 		 * pmic vld/rdy control spi mode disable
230 		 * srclken control spi mode enable
231 		 * vreq control spi mode enable
232 		 */
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;
239 
240 		/* srclken rc interface disable */
241 		spi_inf_srclken_rc_en = 0;
242 
243 		/* dcxo interface enable */
244 		spi_other_inf_dcxo0_en = 1;
245 		spi_other_inf_dcxo1_en = 1;
246 
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;
251 		break;
252 
253 	default:
254 		die("Can't support pmif mode %d\n", mode);
255 	}
256 
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);
280 }
281 
pmwrap_interface_init(void)282 void pmwrap_interface_init(void)
283 {
284 	if (CONFIG(SRCLKEN_RC_SUPPORT)) {
285 		printk(BIOS_INFO, "%s: Select PMIF_VLD_RDY\n", __func__);
286 		pmif_select(PMIF_VLD_RDY);
287 	} else {
288 		printk(BIOS_INFO, "%s: Select PMIF_SLP_REQ\n", __func__);
289 		pmif_select(PMIF_SLP_REQ);
290 	}
291 }
292 
mtk_pmif_init(void)293 int mtk_pmif_init(void)
294 {
295 	int ret;
296 
297 	ret = pmif_clk_init();
298 	if (!ret)
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));
302 
303 	return ret;
304 }
305