xref: /openbmc/u-boot/drivers/mmc/sh_sdhi.c (revision ee943655)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * drivers/mmc/sh_sdhi.c
4  *
5  * SD/MMC driver for Renesas rmobile ARM SoCs.
6  *
7  * Copyright (C) 2011,2013-2017 Renesas Electronics Corporation
8  * Copyright (C) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
9  * Copyright (C) 2008-2009 Renesas Solutions Corp.
10  */
11 
12 #include <common.h>
13 #include <malloc.h>
14 #include <mmc.h>
15 #include <dm.h>
16 #include <linux/errno.h>
17 #include <linux/compat.h>
18 #include <linux/io.h>
19 #include <linux/sizes.h>
20 #include <asm/arch/rmobile.h>
21 #include <asm/arch/sh_sdhi.h>
22 #include <clk.h>
23 
24 #define DRIVER_NAME "sh-sdhi"
25 
26 struct sh_sdhi_host {
27 	void __iomem *addr;
28 	int ch;
29 	int bus_shift;
30 	unsigned long quirks;
31 	unsigned char wait_int;
32 	unsigned char sd_error;
33 	unsigned char detect_waiting;
34 	unsigned char app_cmd;
35 };
36 
37 static inline void sh_sdhi_writeq(struct sh_sdhi_host *host, int reg, u64 val)
38 {
39 	writeq(val, host->addr + (reg << host->bus_shift));
40 }
41 
42 static inline u64 sh_sdhi_readq(struct sh_sdhi_host *host, int reg)
43 {
44 	return readq(host->addr + (reg << host->bus_shift));
45 }
46 
47 static inline void sh_sdhi_writew(struct sh_sdhi_host *host, int reg, u16 val)
48 {
49 	writew(val, host->addr + (reg << host->bus_shift));
50 }
51 
52 static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
53 {
54 	return readw(host->addr + (reg << host->bus_shift));
55 }
56 
57 static void sh_sdhi_detect(struct sh_sdhi_host *host)
58 {
59 	sh_sdhi_writew(host, SDHI_OPTION,
60 		       OPT_BUS_WIDTH_1 | sh_sdhi_readw(host, SDHI_OPTION));
61 
62 	host->detect_waiting = 0;
63 }
64 
65 static int sh_sdhi_intr(void *dev_id)
66 {
67 	struct sh_sdhi_host *host = dev_id;
68 	int state1 = 0, state2 = 0;
69 
70 	state1 = sh_sdhi_readw(host, SDHI_INFO1);
71 	state2 = sh_sdhi_readw(host, SDHI_INFO2);
72 
73 	debug("%s: state1 = %x, state2 = %x\n", __func__, state1, state2);
74 
75 	/* CARD Insert */
76 	if (state1 & INFO1_CARD_IN) {
77 		sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_CARD_IN);
78 		if (!host->detect_waiting) {
79 			host->detect_waiting = 1;
80 			sh_sdhi_detect(host);
81 		}
82 		sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
83 			       INFO1M_ACCESS_END | INFO1M_CARD_IN |
84 			       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
85 		return -EAGAIN;
86 	}
87 	/* CARD Removal */
88 	if (state1 & INFO1_CARD_RE) {
89 		sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_CARD_RE);
90 		if (!host->detect_waiting) {
91 			host->detect_waiting = 1;
92 			sh_sdhi_detect(host);
93 		}
94 		sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
95 			       INFO1M_ACCESS_END | INFO1M_CARD_RE |
96 			       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
97 		sh_sdhi_writew(host, SDHI_SDIO_INFO1_MASK, SDIO_INFO1M_ON);
98 		sh_sdhi_writew(host, SDHI_SDIO_MODE, SDIO_MODE_OFF);
99 		return -EAGAIN;
100 	}
101 
102 	if (state2 & INFO2_ALL_ERR) {
103 		sh_sdhi_writew(host, SDHI_INFO2,
104 			       (unsigned short)~(INFO2_ALL_ERR));
105 		sh_sdhi_writew(host, SDHI_INFO2_MASK,
106 			       INFO2M_ALL_ERR |
107 			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
108 		host->sd_error = 1;
109 		host->wait_int = 1;
110 		return 0;
111 	}
112 	/* Respons End */
113 	if (state1 & INFO1_RESP_END) {
114 		sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
115 		sh_sdhi_writew(host, SDHI_INFO1_MASK,
116 			       INFO1M_RESP_END |
117 			       sh_sdhi_readw(host, SDHI_INFO1_MASK));
118 		host->wait_int = 1;
119 		return 0;
120 	}
121 	/* SD_BUF Read Enable */
122 	if (state2 & INFO2_BRE_ENABLE) {
123 		sh_sdhi_writew(host, SDHI_INFO2, ~INFO2_BRE_ENABLE);
124 		sh_sdhi_writew(host, SDHI_INFO2_MASK,
125 			       INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ |
126 			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
127 		host->wait_int = 1;
128 		return 0;
129 	}
130 	/* SD_BUF Write Enable */
131 	if (state2 & INFO2_BWE_ENABLE) {
132 		sh_sdhi_writew(host, SDHI_INFO2, ~INFO2_BWE_ENABLE);
133 		sh_sdhi_writew(host, SDHI_INFO2_MASK,
134 			       INFO2_BWE_ENABLE | INFO2M_BUF_ILL_WRITE |
135 			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
136 		host->wait_int = 1;
137 		return 0;
138 	}
139 	/* Access End */
140 	if (state1 & INFO1_ACCESS_END) {
141 		sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_ACCESS_END);
142 		sh_sdhi_writew(host, SDHI_INFO1_MASK,
143 			       INFO1_ACCESS_END |
144 			       sh_sdhi_readw(host, SDHI_INFO1_MASK));
145 		host->wait_int = 1;
146 		return 0;
147 	}
148 	return -EAGAIN;
149 }
150 
151 static int sh_sdhi_wait_interrupt_flag(struct sh_sdhi_host *host)
152 {
153 	int timeout = 10000000;
154 
155 	while (1) {
156 		timeout--;
157 		if (timeout < 0) {
158 			debug(DRIVER_NAME": %s timeout\n", __func__);
159 			return 0;
160 		}
161 
162 		if (!sh_sdhi_intr(host))
163 			break;
164 
165 		udelay(1);	/* 1 usec */
166 	}
167 
168 	return 1; /* Return value: NOT 0 = complete waiting */
169 }
170 
171 static int sh_sdhi_clock_control(struct sh_sdhi_host *host, unsigned long clk)
172 {
173 	u32 clkdiv, i, timeout;
174 
175 	if (sh_sdhi_readw(host, SDHI_INFO2) & (1 << 14)) {
176 		printf(DRIVER_NAME": Busy state ! Cannot change the clock\n");
177 		return -EBUSY;
178 	}
179 
180 	sh_sdhi_writew(host, SDHI_CLK_CTRL,
181 		       ~CLK_ENABLE & sh_sdhi_readw(host, SDHI_CLK_CTRL));
182 
183 	if (clk == 0)
184 		return -EIO;
185 
186 	clkdiv = 0x80;
187 	i = CONFIG_SH_SDHI_FREQ >> (0x8 + 1);
188 	for (; clkdiv && clk >= (i << 1); (clkdiv >>= 1))
189 		i <<= 1;
190 
191 	sh_sdhi_writew(host, SDHI_CLK_CTRL, clkdiv);
192 
193 	timeout = 100000;
194 	/* Waiting for SD Bus busy to be cleared */
195 	while (timeout--) {
196 		if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000))
197 			break;
198 	}
199 
200 	if (timeout)
201 		sh_sdhi_writew(host, SDHI_CLK_CTRL,
202 			       CLK_ENABLE | sh_sdhi_readw(host, SDHI_CLK_CTRL));
203 	else
204 		return -EBUSY;
205 
206 	return 0;
207 }
208 
209 static int sh_sdhi_sync_reset(struct sh_sdhi_host *host)
210 {
211 	u32 timeout;
212 	sh_sdhi_writew(host, SDHI_SOFT_RST, SOFT_RST_ON);
213 	sh_sdhi_writew(host, SDHI_SOFT_RST, SOFT_RST_OFF);
214 	sh_sdhi_writew(host, SDHI_CLK_CTRL,
215 		       CLK_ENABLE | sh_sdhi_readw(host, SDHI_CLK_CTRL));
216 
217 	timeout = 100000;
218 	while (timeout--) {
219 		if (!(sh_sdhi_readw(host, SDHI_INFO2) & INFO2_CBUSY))
220 			break;
221 		udelay(100);
222 	}
223 
224 	if (!timeout)
225 		return -EBUSY;
226 
227 	if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
228 		sh_sdhi_writew(host, SDHI_HOST_MODE, 1);
229 
230 	return 0;
231 }
232 
233 static int sh_sdhi_error_manage(struct sh_sdhi_host *host)
234 {
235 	unsigned short e_state1, e_state2;
236 	int ret;
237 
238 	host->sd_error = 0;
239 	host->wait_int = 0;
240 
241 	e_state1 = sh_sdhi_readw(host, SDHI_ERR_STS1);
242 	e_state2 = sh_sdhi_readw(host, SDHI_ERR_STS2);
243 	if (e_state2 & ERR_STS2_SYS_ERROR) {
244 		if (e_state2 & ERR_STS2_RES_STOP_TIMEOUT)
245 			ret = -ETIMEDOUT;
246 		else
247 			ret = -EILSEQ;
248 		debug("%s: ERR_STS2 = %04x\n",
249 		      DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS2));
250 		sh_sdhi_sync_reset(host);
251 
252 		sh_sdhi_writew(host, SDHI_INFO1_MASK,
253 			       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
254 		return ret;
255 	}
256 	if (e_state1 & ERR_STS1_CRC_ERROR || e_state1 & ERR_STS1_CMD_ERROR)
257 		ret = -EILSEQ;
258 	else
259 		ret = -ETIMEDOUT;
260 
261 	debug("%s: ERR_STS1 = %04x\n",
262 	      DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS1));
263 	sh_sdhi_sync_reset(host);
264 	sh_sdhi_writew(host, SDHI_INFO1_MASK,
265 		       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
266 	return ret;
267 }
268 
269 static int sh_sdhi_single_read(struct sh_sdhi_host *host, struct mmc_data *data)
270 {
271 	long time;
272 	unsigned short blocksize, i;
273 	unsigned short *p = (unsigned short *)data->dest;
274 	u64 *q = (u64 *)data->dest;
275 
276 	if ((unsigned long)p & 0x00000001) {
277 		debug(DRIVER_NAME": %s: The data pointer is unaligned.",
278 		      __func__);
279 		return -EIO;
280 	}
281 
282 	host->wait_int = 0;
283 	sh_sdhi_writew(host, SDHI_INFO2_MASK,
284 		       ~(INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ) &
285 		       sh_sdhi_readw(host, SDHI_INFO2_MASK));
286 	sh_sdhi_writew(host, SDHI_INFO1_MASK,
287 		       ~INFO1M_ACCESS_END &
288 		       sh_sdhi_readw(host, SDHI_INFO1_MASK));
289 	time = sh_sdhi_wait_interrupt_flag(host);
290 	if (time == 0 || host->sd_error != 0)
291 		return sh_sdhi_error_manage(host);
292 
293 	host->wait_int = 0;
294 	blocksize = sh_sdhi_readw(host, SDHI_SIZE);
295 	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
296 		for (i = 0; i < blocksize / 8; i++)
297 			*q++ = sh_sdhi_readq(host, SDHI_BUF0);
298 	else
299 		for (i = 0; i < blocksize / 2; i++)
300 			*p++ = sh_sdhi_readw(host, SDHI_BUF0);
301 
302 	time = sh_sdhi_wait_interrupt_flag(host);
303 	if (time == 0 || host->sd_error != 0)
304 		return sh_sdhi_error_manage(host);
305 
306 	host->wait_int = 0;
307 	return 0;
308 }
309 
310 static int sh_sdhi_multi_read(struct sh_sdhi_host *host, struct mmc_data *data)
311 {
312 	long time;
313 	unsigned short blocksize, i, sec;
314 	unsigned short *p = (unsigned short *)data->dest;
315 	u64 *q = (u64 *)data->dest;
316 
317 	if ((unsigned long)p & 0x00000001) {
318 		debug(DRIVER_NAME": %s: The data pointer is unaligned.",
319 		      __func__);
320 		return -EIO;
321 	}
322 
323 	debug("%s: blocks = %d, blocksize = %d\n",
324 	      __func__, data->blocks, data->blocksize);
325 
326 	host->wait_int = 0;
327 	for (sec = 0; sec < data->blocks; sec++) {
328 		sh_sdhi_writew(host, SDHI_INFO2_MASK,
329 			       ~(INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ) &
330 			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
331 
332 		time = sh_sdhi_wait_interrupt_flag(host);
333 		if (time == 0 || host->sd_error != 0)
334 			return sh_sdhi_error_manage(host);
335 
336 		host->wait_int = 0;
337 		blocksize = sh_sdhi_readw(host, SDHI_SIZE);
338 		if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
339 			for (i = 0; i < blocksize / 8; i++)
340 				*q++ = sh_sdhi_readq(host, SDHI_BUF0);
341 		else
342 			for (i = 0; i < blocksize / 2; i++)
343 				*p++ = sh_sdhi_readw(host, SDHI_BUF0);
344 	}
345 
346 	return 0;
347 }
348 
349 static int sh_sdhi_single_write(struct sh_sdhi_host *host,
350 		struct mmc_data *data)
351 {
352 	long time;
353 	unsigned short blocksize, i;
354 	const unsigned short *p = (const unsigned short *)data->src;
355 	const u64 *q = (const u64 *)data->src;
356 
357 	if ((unsigned long)p & 0x00000001) {
358 		debug(DRIVER_NAME": %s: The data pointer is unaligned.",
359 		      __func__);
360 		return -EIO;
361 	}
362 
363 	debug("%s: blocks = %d, blocksize = %d\n",
364 	      __func__, data->blocks, data->blocksize);
365 
366 	host->wait_int = 0;
367 	sh_sdhi_writew(host, SDHI_INFO2_MASK,
368 		       ~(INFO2M_BWE_ENABLE | INFO2M_BUF_ILL_WRITE) &
369 		       sh_sdhi_readw(host, SDHI_INFO2_MASK));
370 	sh_sdhi_writew(host, SDHI_INFO1_MASK,
371 		       ~INFO1M_ACCESS_END &
372 		       sh_sdhi_readw(host, SDHI_INFO1_MASK));
373 
374 	time = sh_sdhi_wait_interrupt_flag(host);
375 	if (time == 0 || host->sd_error != 0)
376 		return sh_sdhi_error_manage(host);
377 
378 	host->wait_int = 0;
379 	blocksize = sh_sdhi_readw(host, SDHI_SIZE);
380 	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
381 		for (i = 0; i < blocksize / 8; i++)
382 			sh_sdhi_writeq(host, SDHI_BUF0, *q++);
383 	else
384 		for (i = 0; i < blocksize / 2; i++)
385 			sh_sdhi_writew(host, SDHI_BUF0, *p++);
386 
387 	time = sh_sdhi_wait_interrupt_flag(host);
388 	if (time == 0 || host->sd_error != 0)
389 		return sh_sdhi_error_manage(host);
390 
391 	host->wait_int = 0;
392 	return 0;
393 }
394 
395 static int sh_sdhi_multi_write(struct sh_sdhi_host *host, struct mmc_data *data)
396 {
397 	long time;
398 	unsigned short i, sec, blocksize;
399 	const unsigned short *p = (const unsigned short *)data->src;
400 	const u64 *q = (const u64 *)data->src;
401 
402 	debug("%s: blocks = %d, blocksize = %d\n",
403 	      __func__, data->blocks, data->blocksize);
404 
405 	host->wait_int = 0;
406 	for (sec = 0; sec < data->blocks; sec++) {
407 		sh_sdhi_writew(host, SDHI_INFO2_MASK,
408 			       ~(INFO2M_BWE_ENABLE | INFO2M_BUF_ILL_WRITE) &
409 			       sh_sdhi_readw(host, SDHI_INFO2_MASK));
410 
411 		time = sh_sdhi_wait_interrupt_flag(host);
412 		if (time == 0 || host->sd_error != 0)
413 			return sh_sdhi_error_manage(host);
414 
415 		host->wait_int = 0;
416 		blocksize = sh_sdhi_readw(host, SDHI_SIZE);
417 		if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
418 			for (i = 0; i < blocksize / 8; i++)
419 				sh_sdhi_writeq(host, SDHI_BUF0, *q++);
420 		else
421 			for (i = 0; i < blocksize / 2; i++)
422 				sh_sdhi_writew(host, SDHI_BUF0, *p++);
423 	}
424 
425 	return 0;
426 }
427 
428 static void sh_sdhi_get_response(struct sh_sdhi_host *host, struct mmc_cmd *cmd)
429 {
430 	unsigned short i, j, cnt = 1;
431 	unsigned short resp[8];
432 
433 	if (cmd->resp_type & MMC_RSP_136) {
434 		cnt = 4;
435 		resp[0] = sh_sdhi_readw(host, SDHI_RSP00);
436 		resp[1] = sh_sdhi_readw(host, SDHI_RSP01);
437 		resp[2] = sh_sdhi_readw(host, SDHI_RSP02);
438 		resp[3] = sh_sdhi_readw(host, SDHI_RSP03);
439 		resp[4] = sh_sdhi_readw(host, SDHI_RSP04);
440 		resp[5] = sh_sdhi_readw(host, SDHI_RSP05);
441 		resp[6] = sh_sdhi_readw(host, SDHI_RSP06);
442 		resp[7] = sh_sdhi_readw(host, SDHI_RSP07);
443 
444 		/* SDHI REGISTER SPECIFICATION */
445 		for (i = 7, j = 6; i > 0; i--) {
446 			resp[i] = (resp[i] << 8) & 0xff00;
447 			resp[i] |= (resp[j--] >> 8) & 0x00ff;
448 		}
449 		resp[0] = (resp[0] << 8) & 0xff00;
450 	} else {
451 		resp[0] = sh_sdhi_readw(host, SDHI_RSP00);
452 		resp[1] = sh_sdhi_readw(host, SDHI_RSP01);
453 	}
454 
455 #if defined(__BIG_ENDIAN_BITFIELD)
456 	if (cnt == 4) {
457 		cmd->response[0] = (resp[6] << 16) | resp[7];
458 		cmd->response[1] = (resp[4] << 16) | resp[5];
459 		cmd->response[2] = (resp[2] << 16) | resp[3];
460 		cmd->response[3] = (resp[0] << 16) | resp[1];
461 	} else {
462 		cmd->response[0] = (resp[0] << 16) | resp[1];
463 	}
464 #else
465 	if (cnt == 4) {
466 		cmd->response[0] = (resp[7] << 16) | resp[6];
467 		cmd->response[1] = (resp[5] << 16) | resp[4];
468 		cmd->response[2] = (resp[3] << 16) | resp[2];
469 		cmd->response[3] = (resp[1] << 16) | resp[0];
470 	} else {
471 		cmd->response[0] = (resp[1] << 16) | resp[0];
472 	}
473 #endif /* __BIG_ENDIAN_BITFIELD */
474 }
475 
476 static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host,
477 			struct mmc_data *data, unsigned short opc)
478 {
479 	if (host->app_cmd) {
480 		if (!data)
481 			host->app_cmd = 0;
482 		return opc | BIT(6);
483 	}
484 
485 	switch (opc) {
486 	case MMC_CMD_SWITCH:
487 		return opc | (data ? 0x1c00 : 0x40);
488 	case MMC_CMD_SEND_EXT_CSD:
489 		return opc | (data ? 0x1c00 : 0);
490 	case MMC_CMD_SEND_OP_COND:
491 		return opc | 0x0700;
492 	case MMC_CMD_APP_CMD:
493 		host->app_cmd = 1;
494 	default:
495 		return opc;
496 	}
497 }
498 
499 static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host,
500 			struct mmc_data *data, unsigned short opc)
501 {
502 	if (host->app_cmd) {
503 		host->app_cmd = 0;
504 		switch (opc) {
505 		case SD_CMD_APP_SEND_SCR:
506 		case SD_CMD_APP_SD_STATUS:
507 			return sh_sdhi_single_read(host, data);
508 		default:
509 			printf(DRIVER_NAME": SD: NOT SUPPORT APP CMD = d'%04d\n",
510 				opc);
511 			return -EINVAL;
512 		}
513 	} else {
514 		switch (opc) {
515 		case MMC_CMD_WRITE_MULTIPLE_BLOCK:
516 			return sh_sdhi_multi_write(host, data);
517 		case MMC_CMD_READ_MULTIPLE_BLOCK:
518 			return sh_sdhi_multi_read(host, data);
519 		case MMC_CMD_WRITE_SINGLE_BLOCK:
520 			return sh_sdhi_single_write(host, data);
521 		case MMC_CMD_READ_SINGLE_BLOCK:
522 		case MMC_CMD_SWITCH:
523 		case MMC_CMD_SEND_EXT_CSD:;
524 			return sh_sdhi_single_read(host, data);
525 		default:
526 			printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
527 			return -EINVAL;
528 		}
529 	}
530 }
531 
532 static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
533 			struct mmc_data *data, struct mmc_cmd *cmd)
534 {
535 	long time;
536 	unsigned short shcmd, opc = cmd->cmdidx;
537 	int ret = 0;
538 	unsigned long timeout;
539 
540 	debug("opc = %d, arg = %x, resp_type = %x\n",
541 	      opc, cmd->cmdarg, cmd->resp_type);
542 
543 	if (opc == MMC_CMD_STOP_TRANSMISSION) {
544 		/* SDHI sends the STOP command automatically by STOP reg */
545 		sh_sdhi_writew(host, SDHI_INFO1_MASK, ~INFO1M_ACCESS_END &
546 			       sh_sdhi_readw(host, SDHI_INFO1_MASK));
547 
548 		time = sh_sdhi_wait_interrupt_flag(host);
549 		if (time == 0 || host->sd_error != 0)
550 			return sh_sdhi_error_manage(host);
551 
552 		sh_sdhi_get_response(host, cmd);
553 		return 0;
554 	}
555 
556 	if (data) {
557 		if ((opc == MMC_CMD_READ_MULTIPLE_BLOCK) ||
558 		    opc == MMC_CMD_WRITE_MULTIPLE_BLOCK) {
559 			sh_sdhi_writew(host, SDHI_STOP, STOP_SEC_ENABLE);
560 			sh_sdhi_writew(host, SDHI_SECCNT, data->blocks);
561 		}
562 		sh_sdhi_writew(host, SDHI_SIZE, data->blocksize);
563 	}
564 
565 	shcmd = sh_sdhi_set_cmd(host, data, opc);
566 
567 	/*
568 	 *  U-Boot cannot use interrupt.
569 	 *  So this flag may not be clear by timing
570 	 */
571 	sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
572 
573 	sh_sdhi_writew(host, SDHI_INFO1_MASK,
574 		       INFO1M_RESP_END | sh_sdhi_readw(host, SDHI_INFO1_MASK));
575 	sh_sdhi_writew(host, SDHI_ARG0,
576 		       (unsigned short)(cmd->cmdarg & ARG0_MASK));
577 	sh_sdhi_writew(host, SDHI_ARG1,
578 		       (unsigned short)((cmd->cmdarg >> 16) & ARG1_MASK));
579 
580 	timeout = 100000;
581 	/* Waiting for SD Bus busy to be cleared */
582 	while (timeout--) {
583 		if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000))
584 			break;
585 	}
586 
587 	host->wait_int = 0;
588 	sh_sdhi_writew(host, SDHI_INFO1_MASK,
589 		       ~INFO1M_RESP_END & sh_sdhi_readw(host, SDHI_INFO1_MASK));
590 	sh_sdhi_writew(host, SDHI_INFO2_MASK,
591 		       ~(INFO2M_CMD_ERROR | INFO2M_CRC_ERROR |
592 		       INFO2M_END_ERROR | INFO2M_TIMEOUT |
593 		       INFO2M_RESP_TIMEOUT | INFO2M_ILA) &
594 		       sh_sdhi_readw(host, SDHI_INFO2_MASK));
595 
596 	sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(shcmd & CMD_MASK));
597 	time = sh_sdhi_wait_interrupt_flag(host);
598 	if (!time) {
599 		host->app_cmd = 0;
600 		return sh_sdhi_error_manage(host);
601 	}
602 
603 	if (host->sd_error) {
604 		switch (cmd->cmdidx) {
605 		case MMC_CMD_ALL_SEND_CID:
606 		case MMC_CMD_SELECT_CARD:
607 		case SD_CMD_SEND_IF_COND:
608 		case MMC_CMD_APP_CMD:
609 			ret = -ETIMEDOUT;
610 			break;
611 		default:
612 			debug(DRIVER_NAME": Cmd(d'%d) err\n", opc);
613 			debug(DRIVER_NAME": cmdidx = %d\n", cmd->cmdidx);
614 			ret = sh_sdhi_error_manage(host);
615 			break;
616 		}
617 		host->sd_error = 0;
618 		host->wait_int = 0;
619 		host->app_cmd = 0;
620 		return ret;
621 	}
622 
623 	if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) {
624 		host->app_cmd = 0;
625 		return -EINVAL;
626 	}
627 
628 	if (host->wait_int) {
629 		sh_sdhi_get_response(host, cmd);
630 		host->wait_int = 0;
631 	}
632 
633 	if (data)
634 		ret = sh_sdhi_data_trans(host, data, opc);
635 
636 	debug("ret = %d, resp = %08x, %08x, %08x, %08x\n",
637 	      ret, cmd->response[0], cmd->response[1],
638 	      cmd->response[2], cmd->response[3]);
639 	return ret;
640 }
641 
642 static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
643 				   struct mmc_cmd *cmd, struct mmc_data *data)
644 {
645 	host->sd_error = 0;
646 
647 	return sh_sdhi_start_cmd(host, data, cmd);
648 }
649 
650 static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc)
651 {
652 	int ret;
653 
654 	ret = sh_sdhi_clock_control(host, mmc->clock);
655 	if (ret)
656 		return -EINVAL;
657 
658 	if (mmc->bus_width == 8)
659 		sh_sdhi_writew(host, SDHI_OPTION,
660 			       OPT_BUS_WIDTH_8 | (~OPT_BUS_WIDTH_M &
661 			       sh_sdhi_readw(host, SDHI_OPTION)));
662 	else if (mmc->bus_width == 4)
663 		sh_sdhi_writew(host, SDHI_OPTION,
664 			       OPT_BUS_WIDTH_4 | (~OPT_BUS_WIDTH_M &
665 			       sh_sdhi_readw(host, SDHI_OPTION)));
666 	else
667 		sh_sdhi_writew(host, SDHI_OPTION,
668 			       OPT_BUS_WIDTH_1 | (~OPT_BUS_WIDTH_M &
669 			       sh_sdhi_readw(host, SDHI_OPTION)));
670 
671 	debug("clock = %d, buswidth = %d\n", mmc->clock, mmc->bus_width);
672 
673 	return 0;
674 }
675 
676 static int sh_sdhi_initialize_common(struct sh_sdhi_host *host)
677 {
678 	int ret = sh_sdhi_sync_reset(host);
679 
680 	sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
681 
682 #if defined(__BIG_ENDIAN_BITFIELD)
683 	sh_sdhi_writew(host, SDHI_EXT_SWAP, SET_SWAP);
684 #endif
685 
686 	sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
687 		       INFO1M_ACCESS_END | INFO1M_CARD_RE |
688 		       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
689 
690 	return ret;
691 }
692 
693 #ifndef CONFIG_DM_MMC
694 static void *mmc_priv(struct mmc *mmc)
695 {
696 	return (void *)mmc->priv;
697 }
698 
699 static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
700 			    struct mmc_data *data)
701 {
702 	struct sh_sdhi_host *host = mmc_priv(mmc);
703 
704 	return sh_sdhi_send_cmd_common(host, cmd, data);
705 }
706 
707 static int sh_sdhi_set_ios(struct mmc *mmc)
708 {
709 	struct sh_sdhi_host *host = mmc_priv(mmc);
710 
711 	return sh_sdhi_set_ios_common(host, mmc);
712 }
713 
714 static int sh_sdhi_initialize(struct mmc *mmc)
715 {
716 	struct sh_sdhi_host *host = mmc_priv(mmc);
717 
718 	return sh_sdhi_initialize_common(host);
719 }
720 
721 static const struct mmc_ops sh_sdhi_ops = {
722 	.send_cmd       = sh_sdhi_send_cmd,
723 	.set_ios        = sh_sdhi_set_ios,
724 	.init           = sh_sdhi_initialize,
725 };
726 
727 #ifdef CONFIG_RCAR_GEN3
728 static struct mmc_config sh_sdhi_cfg = {
729 	.name           = DRIVER_NAME,
730 	.ops            = &sh_sdhi_ops,
731 	.f_min          = CLKDEV_INIT,
732 	.f_max          = CLKDEV_HS_DATA,
733 	.voltages       = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
734 	.host_caps      = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HS |
735 			  MMC_MODE_HS_52MHz,
736 	.part_type      = PART_TYPE_DOS,
737 	.b_max          = CONFIG_SYS_MMC_MAX_BLK_COUNT,
738 };
739 #else
740 static struct mmc_config sh_sdhi_cfg = {
741 	.name           = DRIVER_NAME,
742 	.ops            = &sh_sdhi_ops,
743 	.f_min          = CLKDEV_INIT,
744 	.f_max          = CLKDEV_HS_DATA,
745 	.voltages       = MMC_VDD_32_33 | MMC_VDD_33_34,
746 	.host_caps      = MMC_MODE_4BIT | MMC_MODE_HS,
747 	.part_type      = PART_TYPE_DOS,
748 	.b_max          = CONFIG_SYS_MMC_MAX_BLK_COUNT,
749 };
750 #endif
751 
752 int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
753 {
754 	int ret = 0;
755 	struct mmc *mmc;
756 	struct sh_sdhi_host *host = NULL;
757 
758 	if (ch >= CONFIG_SYS_SH_SDHI_NR_CHANNEL)
759 		return -ENODEV;
760 
761 	host = malloc(sizeof(struct sh_sdhi_host));
762 	if (!host)
763 		return -ENOMEM;
764 
765 	mmc = mmc_create(&sh_sdhi_cfg, host);
766 	if (!mmc) {
767 		ret = -1;
768 		goto error;
769 	}
770 
771 	host->ch = ch;
772 	host->addr = (void __iomem *)addr;
773 	host->quirks = quirks;
774 
775 	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
776 		host->bus_shift = 2;
777 	else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
778 		host->bus_shift = 1;
779 
780 	return ret;
781 error:
782 	if (host)
783 		free(host);
784 	return ret;
785 }
786 
787 #else
788 
789 struct sh_sdhi_plat {
790 	struct mmc_config cfg;
791 	struct mmc mmc;
792 };
793 
794 int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
795 			struct mmc_data *data)
796 {
797 	struct sh_sdhi_host *host = dev_get_priv(dev);
798 
799 	return sh_sdhi_send_cmd_common(host, cmd, data);
800 }
801 
802 int sh_sdhi_dm_set_ios(struct udevice *dev)
803 {
804 	struct sh_sdhi_host *host = dev_get_priv(dev);
805 	struct mmc *mmc = mmc_get_mmc_dev(dev);
806 
807 	return sh_sdhi_set_ios_common(host, mmc);
808 }
809 
810 static const struct dm_mmc_ops sh_sdhi_dm_ops = {
811 	.send_cmd	= sh_sdhi_dm_send_cmd,
812 	.set_ios	= sh_sdhi_dm_set_ios,
813 };
814 
815 static int sh_sdhi_dm_bind(struct udevice *dev)
816 {
817 	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
818 
819 	return mmc_bind(dev, &plat->mmc, &plat->cfg);
820 }
821 
822 static int sh_sdhi_dm_probe(struct udevice *dev)
823 {
824 	struct sh_sdhi_plat *plat = dev_get_platdata(dev);
825 	struct sh_sdhi_host *host = dev_get_priv(dev);
826 	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
827 	struct clk sh_sdhi_clk;
828 	const u32 quirks = dev_get_driver_data(dev);
829 	fdt_addr_t base;
830 	int ret;
831 
832 	base = devfdt_get_addr(dev);
833 	if (base == FDT_ADDR_T_NONE)
834 		return -EINVAL;
835 
836 	host->addr = devm_ioremap(dev, base, SZ_2K);
837 	if (!host->addr)
838 		return -ENOMEM;
839 
840 	ret = clk_get_by_index(dev, 0, &sh_sdhi_clk);
841 	if (ret) {
842 		debug("failed to get clock, ret=%d\n", ret);
843 		return ret;
844 	}
845 
846 	ret = clk_enable(&sh_sdhi_clk);
847 	if (ret) {
848 		debug("failed to enable clock, ret=%d\n", ret);
849 		return ret;
850 	}
851 
852 	host->quirks = quirks;
853 
854 	if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
855 		host->bus_shift = 2;
856 	else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
857 		host->bus_shift = 1;
858 
859 	plat->cfg.name = dev->name;
860 	plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
861 
862 	switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
863 			       1)) {
864 	case 8:
865 		plat->cfg.host_caps |= MMC_MODE_8BIT;
866 		break;
867 	case 4:
868 		plat->cfg.host_caps |= MMC_MODE_4BIT;
869 		break;
870 	case 1:
871 		break;
872 	default:
873 		dev_err(dev, "Invalid \"bus-width\" value\n");
874 		return -EINVAL;
875 	}
876 
877 	sh_sdhi_initialize_common(host);
878 
879 	plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
880 	plat->cfg.f_min = CLKDEV_INIT;
881 	plat->cfg.f_max = CLKDEV_HS_DATA;
882 	plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
883 
884 	upriv->mmc = &plat->mmc;
885 
886 	return 0;
887 }
888 
889 static const struct udevice_id sh_sdhi_sd_match[] = {
890 	{ .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
891 	{ .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
892 	{ /* sentinel */ }
893 };
894 
895 U_BOOT_DRIVER(sh_sdhi_mmc) = {
896 	.name			= "sh-sdhi-mmc",
897 	.id			= UCLASS_MMC,
898 	.of_match		= sh_sdhi_sd_match,
899 	.bind			= sh_sdhi_dm_bind,
900 	.probe			= sh_sdhi_dm_probe,
901 	.priv_auto_alloc_size	= sizeof(struct sh_sdhi_host),
902 	.platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat),
903 	.ops			= &sh_sdhi_dm_ops,
904 };
905 #endif
906