xref: /aosp_15_r20/external/coreboot/src/soc/mediatek/common/msdc.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * MTK MSDC Host Controller interface specific code
4  */
5 #include <assert.h>
6 #include <commonlib/bsd/helpers.h>
7 #include <commonlib/storage/sd_mmc.h>
8 #include <delay.h>
9 #include <device/mmio.h>
10 #include <lib.h>
11 #include <soc/msdc.h>
12 #include <string.h>
13 #include <timer.h>
14 
msdc_set_field(void * reg,u32 field,u32 val)15 static inline void msdc_set_field(void *reg, u32 field, u32 val)
16 {
17 	clrsetbits32(reg, field, val << __ffs(field));
18 }
19 
20 /*
21  * Periodically poll an address until a condition is met or a timeout occurs
22  * @addr: Address to poll
23  * @mask: mask condition
24  * @timeout: Timeout in us, 0 means never timeout
25  *
26  * Returns 0 on success and -MSDC_NOT_READY upon a timeout.
27  */
msdc_poll_timeout(void * addr,u32 mask)28 static int msdc_poll_timeout(void *addr, u32 mask)
29 {
30 	struct stopwatch timer;
31 	stopwatch_init_usecs_expire(&timer, MSDC_TIMEOUT_US);
32 	u32 reg;
33 
34 	do {
35 		reg = read32(addr);
36 		if (stopwatch_expired(&timer))
37 			return -MSDC_NOT_READY;
38 		udelay(1);
39 	} while (reg & mask);
40 
41 	return MSDC_SUCCESS;
42 }
43 
44 /*
45  * Wait for a bit mask in a given register. To avoid endless loops, a
46  * time-out is implemented here.
47  */
msdc_wait_done(void * addr,u32 mask,u32 * status)48 static int msdc_wait_done(void *addr, u32 mask, u32 *status)
49 {
50 	struct stopwatch timer;
51 	stopwatch_init_usecs_expire(&timer, CMD_TIMEOUT_MS);
52 	u32 reg;
53 
54 	do {
55 		reg = read32(addr);
56 		if (stopwatch_expired(&timer)) {
57 			if (status)
58 				*status = reg;
59 			return -MSDC_NOT_READY;
60 		}
61 		udelay(1);
62 	} while (!(reg & mask));
63 
64 	if (status)
65 		*status = reg;
66 
67 	return MSDC_SUCCESS;
68 }
69 
msdc_reset_hw(struct msdc_ctrlr * host)70 static void msdc_reset_hw(struct msdc_ctrlr *host)
71 {
72 	u32 val;
73 
74 	setbits32(host->base + MSDC_CFG, MSDC_CFG_RST);
75 	if (msdc_poll_timeout(host->base + MSDC_CFG, MSDC_CFG_RST) != MSDC_SUCCESS)
76 		msdc_error("Softwave reset timeout!\n");
77 
78 	setbits32(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
79 	if (msdc_poll_timeout(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR) != MSDC_SUCCESS)
80 		msdc_error("Clear FIFO timeout!\n");
81 
82 	val = read32(host->base + MSDC_INT);
83 	write32(host->base + MSDC_INT, val);
84 }
85 
msdc_init_hw(struct msdc_ctrlr * host)86 static void msdc_init_hw(struct msdc_ctrlr *host)
87 {
88 	/* Configure to MMC/SD mode */
89 	setbits32(host->base + MSDC_CFG, MSDC_CFG_MODE);
90 
91 	/* Reset */
92 	msdc_reset_hw(host);
93 
94 	/* Set PIO mode */
95 	setbits32(host->base + MSDC_CFG, MSDC_CFG_PIO);
96 
97 	write32(host->top_base + EMMC_TOP_CONTROL, 0);
98 	write32(host->top_base + EMMC_TOP_CMD, 0);
99 
100 	write32(host->base + MSDC_IOCON, 0);
101 	clrbits32(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL);
102 	write32(host->base + MSDC_PATCH_BIT, 0x403c0046);
103 	msdc_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1);
104 	write32(host->base + MSDC_PATCH_BIT1, 0xffff4089);
105 	setbits32(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL);
106 
107 	msdc_set_field(host->base + MSDC_PATCH_BIT1,
108 		       MSDC_PATCH_BIT1_STOP_DLY, 3);
109 	clrbits32(host->base + SDC_FIFO_CFG, SDC_FIFO_CFG_WRVALIDSEL);
110 	clrbits32(host->base + SDC_FIFO_CFG, SDC_FIFO_CFG_RDVALIDSEL);
111 
112 	clrbits32(host->base + MSDC_PATCH_BIT1, (1 << 7));
113 
114 	msdc_set_field(host->base + MSDC_PATCH_BIT2, MSDC_PB2_RESPWAIT, 3);
115 	if (host->top_base)
116 		setbits32(host->top_base + EMMC_TOP_CONTROL, SDC_RX_ENH_EN);
117 	else
118 		setbits32(host->base + SDC_ADV_CFG0, SDC_RX_ENHANCE_EN);
119 	/* Use async fifo, then no need to tune internal delay */
120 	clrbits32(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGRESP);
121 	setbits32(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS);
122 
123 	if (host->top_base) {
124 		setbits32(host->top_base + EMMC_TOP_CONTROL,
125 			  PAD_DAT_RD_RXDLY_SEL);
126 		clrbits32(host->top_base + EMMC_TOP_CONTROL, DATA_K_VALUE_SEL);
127 		setbits32(host->top_base + EMMC_TOP_CMD, PAD_CMD_RD_RXDLY_SEL);
128 	} else {
129 		setbits32(host->base + MSDC_PAD_TUNE,
130 			  MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL);
131 	}
132 
133 	/* Configure to enable SDIO mode. Otherwise, sdio cmd5 will fail. */
134 	setbits32(host->base + SDC_CFG, SDC_CFG_SDIO);
135 
136 	/* Config SDIO device detect interrupt function */
137 	clrbits32(host->base + SDC_CFG, SDC_CFG_SDIOIDE);
138 	setbits32(host->base + SDC_ADV_CFG0, SDC_DAT1_IRQ_TRIGGER);
139 
140 	/* Configure to default data timeout */
141 	msdc_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, 3);
142 
143 	msdc_debug("init hardware done!\n");
144 }
145 
msdc_fifo_clr(struct msdc_ctrlr * host)146 static void msdc_fifo_clr(struct msdc_ctrlr *host)
147 {
148 	setbits32(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR);
149 
150 	if (msdc_poll_timeout(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR) != MSDC_SUCCESS)
151 		msdc_error("Clear FIFO timeout!\n");
152 }
153 
msdc_cmd_find_resp(struct msdc_ctrlr * host,struct mmc_command * cmd)154 static u32 msdc_cmd_find_resp(struct msdc_ctrlr *host, struct mmc_command *cmd)
155 {
156 	switch (cmd->resp_type) {
157 	case CARD_RSP_R1:
158 		return 0x1;
159 	case CARD_RSP_R1b:
160 		return 0x7;
161 	case CARD_RSP_R2:
162 		return 0x2;
163 	case CARD_RSP_R3:
164 		return 0x3;
165 	case CARD_RSP_NONE:
166 	default:
167 		return 0x0;
168 	}
169 }
170 
msdc_cmd_is_ready(struct msdc_ctrlr * host)171 static bool msdc_cmd_is_ready(struct msdc_ctrlr *host)
172 {
173 	int ret;
174 
175 	ret = msdc_poll_timeout(host->base + SDC_STS, SDC_STS_CMDBUSY);
176 	if (ret != MSDC_SUCCESS) {
177 		msdc_error("CMD bus busy detected, SDC_STS: %#x\n",
178 			   read32(host->base + SDC_STS));
179 		msdc_reset_hw(host);
180 		return false;
181 	}
182 
183 	ret = msdc_poll_timeout(host->base + SDC_STS, SDC_STS_SDCBUSY);
184 	if (ret != MSDC_SUCCESS) {
185 		msdc_error("SD controller busy detected, SDC_STS: %#x\n",
186 			   read32(host->base + SDC_STS));
187 		msdc_reset_hw(host);
188 		return false;
189 	}
190 
191 	return true;
192 }
193 
msdc_cmd_prepare_raw_cmd(struct msdc_ctrlr * host,struct mmc_command * cmd,struct mmc_data * data)194 static u32 msdc_cmd_prepare_raw_cmd(struct msdc_ctrlr *host,
195 				    struct mmc_command *cmd,
196 				    struct mmc_data *data)
197 {
198 	u32 opcode = cmd->cmdidx;
199 	u32 resp_type = msdc_cmd_find_resp(host, cmd);
200 	u32 blocksize = 0;
201 	u32 dtype = 0;
202 	u32 rawcmd = 0;
203 
204 	switch (opcode) {
205 	case MMC_CMD_WRITE_MULTIPLE_BLOCK:
206 	case MMC_CMD_READ_MULTIPLE_BLOCK:
207 		dtype = 2;
208 		break;
209 	case MMC_CMD_WRITE_SINGLE_BLOCK:
210 	case MMC_CMD_READ_SINGLE_BLOCK:
211 	case MMC_CMD_AUTO_TUNING_SEQUENCE:
212 		dtype = 1;
213 		break;
214 	case MMC_CMD_SEND_STATUS:
215 		if (data)
216 			dtype = 1;
217 	}
218 
219 	if (data) {
220 		if (data->flags == DATA_FLAG_READ)
221 			rawcmd |= SDC_CMD_WR;
222 
223 		if (data->blocks > 1)
224 			dtype = 2;
225 
226 		blocksize = data->blocksize;
227 	}
228 
229 	rawcmd |= (opcode << SDC_CMD_CMD_S) & SDC_CMD_CMD_M;
230 	rawcmd |= (resp_type << SDC_CMD_RSPTYP_S) & SDC_CMD_RSPTYP_M;
231 	rawcmd |= (blocksize << SDC_CMD_BLK_LEN_S) & SDC_CMD_BLK_LEN_M;
232 	rawcmd |= (dtype << SDC_CMD_DTYPE_S) & SDC_CMD_DTYPE_M;
233 
234 	if (opcode == MMC_CMD_STOP_TRANSMISSION)
235 		rawcmd |= SDC_CMD_STOP;
236 
237 	return rawcmd;
238 }
239 
msdc_cmd_done(struct msdc_ctrlr * host,int events,struct mmc_command * cmd)240 static int msdc_cmd_done(struct msdc_ctrlr *host, int events,
241 			 struct mmc_command *cmd)
242 {
243 	u32 *rsp = cmd->response;
244 	int ret = 0;
245 
246 	if (cmd->resp_type & CARD_RSP_PRESENT) {
247 		if (cmd->resp_type & CARD_RSP_136) {
248 			rsp[0] = read32(host->base + SDC_RESP3);
249 			rsp[1] = read32(host->base + SDC_RESP2);
250 			rsp[2] = read32(host->base + SDC_RESP1);
251 			rsp[3] = read32(host->base + SDC_RESP0);
252 		} else {
253 			rsp[0] = read32(host->base + SDC_RESP0);
254 		}
255 	}
256 
257 	if (!(events & MSDC_INT_CMDRDY)) {
258 		if (cmd->cmdidx != MMC_CMD_AUTO_TUNING_SEQUENCE) {
259 			/*
260 			 * should not clear fifo/interrupt as the tune data
261 			 * may have already come.
262 			 */
263 			msdc_reset_hw(host);
264 		}
265 		if (events & MSDC_INT_CMDTMO)
266 			ret = -ETIMEDOUT;
267 		else
268 			ret = -EIO;
269 	}
270 
271 	return ret;
272 }
273 
msdc_start_command(struct msdc_ctrlr * host,struct mmc_command * cmd,struct mmc_data * data)274 static int msdc_start_command(struct msdc_ctrlr *host, struct mmc_command *cmd,
275 			      struct mmc_data *data)
276 {
277 	u32 rawcmd, status;
278 	u32 blocks = 0;
279 	int ret;
280 
281 	if (!msdc_cmd_is_ready(host))
282 		return -EIO;
283 
284 	if (read32(host->base + MSDC_FIFOCS) &
285 	    (MSDC_FIFOCS_TXCNT | MSDC_FIFOCS_RXCNT)) {
286 		msdc_error("TX/RX FIFO non-empty before start of IO. Reset\n");
287 		msdc_reset_hw(host);
288 	}
289 
290 	msdc_fifo_clr(host);
291 
292 	rawcmd = msdc_cmd_prepare_raw_cmd(host, cmd, data);
293 
294 	if (data)
295 		blocks = data->blocks;
296 
297 	write32(host->base + MSDC_INT, CMD_INTS_MASK);
298 	write32(host->base + SDC_BLK_NUM, blocks);
299 	write32(host->base + SDC_ARG, cmd->cmdarg);
300 	write32(host->base + SDC_CMD, rawcmd);
301 
302 	ret = msdc_wait_done(host->base + MSDC_INT, CMD_INTS_MASK, &status);
303 	if (ret != MSDC_SUCCESS)
304 		status = MSDC_INT_CMDTMO;
305 
306 	return msdc_cmd_done(host, status, cmd);
307 }
308 
msdc_send_command(struct sd_mmc_ctrlr * ctrlr,struct mmc_command * cmd,struct mmc_data * data)309 static int msdc_send_command(struct sd_mmc_ctrlr *ctrlr,
310 	struct mmc_command *cmd, struct mmc_data *data)
311 {
312 	struct msdc_ctrlr *host;
313 
314 	host = container_of(ctrlr, struct msdc_ctrlr, sd_mmc_ctrlr);
315 
316 	return msdc_start_command(host, cmd, data);
317 }
318 
msdc_set_clock(struct msdc_ctrlr * host,u32 clock)319 static void msdc_set_clock(struct msdc_ctrlr *host, u32 clock)
320 {
321 	u32 mode, mode_shift;
322 	u32 div, div_mask;
323 	const u32 div_width = 12;
324 	u32 sclk;
325 	u32 hclk = host->src_hz;
326 	struct sd_mmc_ctrlr *ctrlr = &host->sd_mmc_ctrlr;
327 
328 	if (clock >= hclk) {
329 		mode = 0x1;     /* no divisor */
330 		div = 0;
331 		sclk = hclk;
332 	} else {
333 		mode = 0x0;     /* use divisor */
334 		if (clock >= (hclk / 2)) {
335 			div = 0;        /* mean div = 1/2 */
336 			sclk = hclk / 2;        /* sclk = clk / 2 */
337 		} else {
338 			div = DIV_ROUND_UP(hclk, clock * 4);
339 			sclk = (hclk >> 2) / div;
340 		}
341 	}
342 
343 	div_mask = (1 << div_width) - 1;
344 	mode_shift = 8 + div_width;
345 	assert(div <= div_mask);
346 
347 	clrsetbits_le32(host->base + MSDC_CFG, (0x3 << mode_shift) | (div_mask << 8),
348 			(mode << mode_shift) | (div << 8));
349 	if (msdc_wait_done(host->base + MSDC_CFG, MSDC_CFG_CKSTB, NULL) != MSDC_SUCCESS)
350 		msdc_error("Failed while wait clock stable!\n");
351 
352 	ctrlr->bus_hz = sclk;
353 	msdc_debug("sclk: %d\n", sclk);
354 }
355 
msdc_set_buswidth(struct msdc_ctrlr * host,u32 width)356 static void msdc_set_buswidth(struct msdc_ctrlr *host, u32 width)
357 {
358 	u32 val = read32(host->base + SDC_CFG);
359 
360 	val &= ~SDC_CFG_BUSWIDTH;
361 
362 	switch (width) {
363 	default:
364 	case 1:
365 		val |= (MSDC_BUS_1BITS << 16);
366 		break;
367 	case 4:
368 		val |= (MSDC_BUS_4BITS << 16);
369 		break;
370 	case 8:
371 		val |= (MSDC_BUS_8BITS << 16);
372 		break;
373 	}
374 
375 	write32(host->base + SDC_CFG, val);
376 	msdc_trace("Bus Width = %d\n", width);
377 }
378 
msdc_set_ios(struct sd_mmc_ctrlr * ctrlr)379 static void msdc_set_ios(struct sd_mmc_ctrlr *ctrlr)
380 {
381 	struct msdc_ctrlr *host;
382 
383 	host = container_of(ctrlr, struct msdc_ctrlr, sd_mmc_ctrlr);
384 
385 	/* Set the clock frequency */
386 	if (ctrlr->bus_hz != ctrlr->request_hz)
387 		msdc_set_clock(host, ctrlr->request_hz);
388 
389 	msdc_set_buswidth(host, ctrlr->bus_width);
390 }
391 
msdc_update_pointers(struct msdc_ctrlr * host)392 static void msdc_update_pointers(struct msdc_ctrlr *host)
393 {
394 	struct sd_mmc_ctrlr *ctrlr = &host->sd_mmc_ctrlr;
395 
396 	/* Update the routine pointers */
397 	ctrlr->send_cmd = &msdc_send_command;
398 	ctrlr->set_ios = &msdc_set_ios;
399 
400 	ctrlr->f_min = 400 * 1000;
401 	ctrlr->f_max = 52 * 1000 * 1000;
402 	ctrlr->bus_width = 1;
403 	ctrlr->caps |= DRVR_CAP_HS | DRVR_CAP_HC;
404 	ctrlr->voltages = 0x40ff8080;
405 }
406 
add_msdc(struct msdc_ctrlr * host)407 static void add_msdc(struct msdc_ctrlr *host)
408 {
409 	struct sd_mmc_ctrlr *ctrlr = &host->sd_mmc_ctrlr;
410 
411 	msdc_update_pointers(host);
412 
413 	/* Initialize the MTK MSDC controller */
414 	msdc_init_hw(host);
415 
416 	/* Display the results */
417 	msdc_trace("%#010x: ctrlr->caps\n", ctrlr->caps);
418 	msdc_trace("%d.%03d MHz: ctrlr->f_max\n",
419 		    ctrlr->f_max / 1000000,
420 		    (ctrlr->f_max / 1000) % 1000);
421 	msdc_trace("%d.%03d MHz: ctrlr->f_min\n",
422 		    ctrlr->f_min / 1000000,
423 		    (ctrlr->f_min / 1000) % 1000);
424 	msdc_trace("%#010x: ctrlr->voltages\n", ctrlr->voltages);
425 }
426 
msdc_controller_init(struct msdc_ctrlr * host,void * base,void * top_base)427 static void msdc_controller_init(struct msdc_ctrlr *host, void *base, void *top_base)
428 {
429 	memset(host, 0, sizeof(*host));
430 	host->base = base;
431 	host->top_base = top_base;
432 	host->src_hz = 50 * 1000 * 1000;
433 
434 	add_msdc(host);
435 }
436 
mtk_emmc_early_init(void * base,void * top_base)437 int mtk_emmc_early_init(void *base, void *top_base)
438 {
439 	struct storage_media media = { 0 };
440 	struct msdc_ctrlr msdc_host;
441 	struct sd_mmc_ctrlr *mmc_ctrlr = &msdc_host.sd_mmc_ctrlr;
442 
443 	/* Init mtk mmc ctrlr */
444 	msdc_controller_init(&msdc_host, base, top_base);
445 
446 	media.ctrlr = mmc_ctrlr;
447 	SET_CLOCK(mmc_ctrlr, 400 * 1000);
448 	SET_BUS_WIDTH(mmc_ctrlr, 1);
449 
450 	/* Send CMD1 */
451 	return  mmc_send_cmd1(&media);
452 }
453