blob: 1a01fe5a7396e93ef6747c8710603b790e892f56 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +00002/*
3 * MMCIF driver.
4 *
5 * Copyright (C) 2011 Renesas Solutions Corp.
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +00006 */
7
8#include <config.h>
9#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +000011#include <watchdog.h>
12#include <command.h>
13#include <mmc.h>
Marek Vasut26b87a02018-04-21 17:27:11 +020014#include <clk.h>
15#include <dm.h>
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +000016#include <malloc.h>
Simon Glass9bc15642020-02-03 07:36:16 -070017#include <dm/device_compat.h>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090019#include <linux/errno.h>
Marek Vasut26b87a02018-04-21 17:27:11 +020020#include <linux/compat.h>
21#include <linux/io.h>
22#include <linux/sizes.h>
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +000023#include "sh_mmcif.h"
24
25#define DRIVER_NAME "sh_mmcif"
26
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +000027static int sh_mmcif_intr(void *dev_id)
28{
29 struct sh_mmcif_host *host = dev_id;
30 u32 state = 0;
31
32 state = sh_mmcif_read(&host->regs->ce_int);
33 state &= sh_mmcif_read(&host->regs->ce_int_mask);
34
35 if (state & INT_RBSYE) {
36 sh_mmcif_write(~(INT_RBSYE | INT_CRSPE), &host->regs->ce_int);
37 sh_mmcif_bitclr(MASK_MRBSYE, &host->regs->ce_int_mask);
38 goto end;
39 } else if (state & INT_CRSPE) {
40 sh_mmcif_write(~INT_CRSPE, &host->regs->ce_int);
41 sh_mmcif_bitclr(MASK_MCRSPE, &host->regs->ce_int_mask);
42 /* one more interrupt (INT_RBSYE) */
43 if (sh_mmcif_read(&host->regs->ce_cmd_set) & CMD_SET_RBSY)
44 return -EAGAIN;
45 goto end;
46 } else if (state & INT_BUFREN) {
47 sh_mmcif_write(~INT_BUFREN, &host->regs->ce_int);
48 sh_mmcif_bitclr(MASK_MBUFREN, &host->regs->ce_int_mask);
49 goto end;
50 } else if (state & INT_BUFWEN) {
51 sh_mmcif_write(~INT_BUFWEN, &host->regs->ce_int);
52 sh_mmcif_bitclr(MASK_MBUFWEN, &host->regs->ce_int_mask);
53 goto end;
54 } else if (state & INT_CMD12DRE) {
55 sh_mmcif_write(~(INT_CMD12DRE | INT_CMD12RBE | INT_CMD12CRE |
56 INT_BUFRE), &host->regs->ce_int);
57 sh_mmcif_bitclr(MASK_MCMD12DRE, &host->regs->ce_int_mask);
58 goto end;
59 } else if (state & INT_BUFRE) {
60 sh_mmcif_write(~INT_BUFRE, &host->regs->ce_int);
61 sh_mmcif_bitclr(MASK_MBUFRE, &host->regs->ce_int_mask);
62 goto end;
63 } else if (state & INT_DTRANE) {
64 sh_mmcif_write(~INT_DTRANE, &host->regs->ce_int);
65 sh_mmcif_bitclr(MASK_MDTRANE, &host->regs->ce_int_mask);
66 goto end;
67 } else if (state & INT_CMD12RBE) {
68 sh_mmcif_write(~(INT_CMD12RBE | INT_CMD12CRE),
69 &host->regs->ce_int);
70 sh_mmcif_bitclr(MASK_MCMD12RBE, &host->regs->ce_int_mask);
71 goto end;
72 } else if (state & INT_ERR_STS) {
73 /* err interrupts */
74 sh_mmcif_write(~state, &host->regs->ce_int);
75 sh_mmcif_bitclr(state, &host->regs->ce_int_mask);
76 goto err;
77 } else
78 return -EAGAIN;
79
80err:
81 host->sd_error = 1;
82 debug("%s: int err state = %08x\n", DRIVER_NAME, state);
83end:
84 host->wait_int = 1;
85 return 0;
86}
87
88static int mmcif_wait_interrupt_flag(struct sh_mmcif_host *host)
89{
90 int timeout = 10000000;
91
92 while (1) {
93 timeout--;
94 if (timeout < 0) {
95 printf("timeout\n");
96 return 0;
97 }
98
99 if (!sh_mmcif_intr(host))
100 break;
101
102 udelay(1); /* 1 usec */
103 }
104
105 return 1; /* Return value: NOT 0 = complete waiting */
106}
107
108static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
109{
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000110 sh_mmcif_bitclr(CLK_ENABLE, &host->regs->ce_clk_ctrl);
111 sh_mmcif_bitclr(CLK_CLEAR, &host->regs->ce_clk_ctrl);
112
113 if (!clk)
114 return;
Nobuhiro Iwamatsu72008872014-12-03 17:57:00 +0900115
116 if (clk == CLKDEV_EMMC_DATA)
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000117 sh_mmcif_bitset(CLK_PCLK, &host->regs->ce_clk_ctrl);
Nobuhiro Iwamatsu72008872014-12-03 17:57:00 +0900118 else
119 sh_mmcif_bitset((fls(DIV_ROUND_UP(host->clk,
120 clk) - 1) - 1) << 16,
121 &host->regs->ce_clk_ctrl);
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000122 sh_mmcif_bitset(CLK_ENABLE, &host->regs->ce_clk_ctrl);
123}
124
125static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
126{
127 u32 tmp;
128
129 tmp = sh_mmcif_read(&host->regs->ce_clk_ctrl) & (CLK_ENABLE |
130 CLK_CLEAR);
131
132 sh_mmcif_write(SOFT_RST_ON, &host->regs->ce_version);
133 sh_mmcif_write(SOFT_RST_OFF, &host->regs->ce_version);
134 sh_mmcif_bitset(tmp | SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29,
135 &host->regs->ce_clk_ctrl);
136 /* byte swap on */
137 sh_mmcif_bitset(BUF_ACC_ATYP, &host->regs->ce_buf_acc);
138}
139
140static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
141{
142 u32 state1, state2;
143 int ret, timeout = 10000000;
144
145 host->sd_error = 0;
146 host->wait_int = 0;
147
148 state1 = sh_mmcif_read(&host->regs->ce_host_sts1);
149 state2 = sh_mmcif_read(&host->regs->ce_host_sts2);
150 debug("%s: ERR HOST_STS1 = %08x\n", \
151 DRIVER_NAME, sh_mmcif_read(&host->regs->ce_host_sts1));
152 debug("%s: ERR HOST_STS2 = %08x\n", \
153 DRIVER_NAME, sh_mmcif_read(&host->regs->ce_host_sts2));
154
155 if (state1 & STS1_CMDSEQ) {
156 debug("%s: Forced end of command sequence\n", DRIVER_NAME);
157 sh_mmcif_bitset(CMD_CTRL_BREAK, &host->regs->ce_cmd_ctrl);
158 sh_mmcif_bitset(~CMD_CTRL_BREAK, &host->regs->ce_cmd_ctrl);
159 while (1) {
160 timeout--;
161 if (timeout < 0) {
162 printf(DRIVER_NAME": Forceed end of " \
163 "command sequence timeout err\n");
164 return -EILSEQ;
165 }
166 if (!(sh_mmcif_read(&host->regs->ce_host_sts1)
167 & STS1_CMDSEQ))
168 break;
169 }
170 sh_mmcif_sync_reset(host);
171 return -EILSEQ;
172 }
173
174 if (state2 & STS2_CRC_ERR)
175 ret = -EILSEQ;
176 else if (state2 & STS2_TIMEOUT_ERR)
Jaehoon Chung7825d202016-07-19 16:33:36 +0900177 ret = -ETIMEDOUT;
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000178 else
179 ret = -EILSEQ;
180 return ret;
181}
182
183static int sh_mmcif_single_read(struct sh_mmcif_host *host,
184 struct mmc_data *data)
185{
186 long time;
187 u32 blocksize, i;
188 unsigned long *p = (unsigned long *)data->dest;
189
190 if ((unsigned long)p & 0x00000001) {
191 printf("%s: The data pointer is unaligned.", __func__);
192 return -EIO;
193 }
194
195 host->wait_int = 0;
196
197 /* buf read enable */
198 sh_mmcif_bitset(MASK_MBUFREN, &host->regs->ce_int_mask);
199 time = mmcif_wait_interrupt_flag(host);
200 if (time == 0 || host->sd_error != 0)
201 return sh_mmcif_error_manage(host);
202
203 host->wait_int = 0;
204 blocksize = (BLOCK_SIZE_MASK &
205 sh_mmcif_read(&host->regs->ce_block_set)) + 3;
206 for (i = 0; i < blocksize / 4; i++)
207 *p++ = sh_mmcif_read(&host->regs->ce_data);
208
209 /* buffer read end */
210 sh_mmcif_bitset(MASK_MBUFRE, &host->regs->ce_int_mask);
211 time = mmcif_wait_interrupt_flag(host);
212 if (time == 0 || host->sd_error != 0)
213 return sh_mmcif_error_manage(host);
214
215 host->wait_int = 0;
216 return 0;
217}
218
219static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
220 struct mmc_data *data)
221{
222 long time;
223 u32 blocksize, i, j;
224 unsigned long *p = (unsigned long *)data->dest;
225
226 if ((unsigned long)p & 0x00000001) {
227 printf("%s: The data pointer is unaligned.", __func__);
228 return -EIO;
229 }
230
231 host->wait_int = 0;
232 blocksize = BLOCK_SIZE_MASK & sh_mmcif_read(&host->regs->ce_block_set);
233 for (j = 0; j < data->blocks; j++) {
234 sh_mmcif_bitset(MASK_MBUFREN, &host->regs->ce_int_mask);
235 time = mmcif_wait_interrupt_flag(host);
236 if (time == 0 || host->sd_error != 0)
237 return sh_mmcif_error_manage(host);
238
239 host->wait_int = 0;
240 for (i = 0; i < blocksize / 4; i++)
241 *p++ = sh_mmcif_read(&host->regs->ce_data);
242
243 WATCHDOG_RESET();
244 }
245 return 0;
246}
247
248static int sh_mmcif_single_write(struct sh_mmcif_host *host,
249 struct mmc_data *data)
250{
251 long time;
252 u32 blocksize, i;
253 const unsigned long *p = (unsigned long *)data->dest;
254
255 if ((unsigned long)p & 0x00000001) {
256 printf("%s: The data pointer is unaligned.", __func__);
257 return -EIO;
258 }
259
260 host->wait_int = 0;
261 sh_mmcif_bitset(MASK_MBUFWEN, &host->regs->ce_int_mask);
262
263 time = mmcif_wait_interrupt_flag(host);
264 if (time == 0 || host->sd_error != 0)
265 return sh_mmcif_error_manage(host);
266
267 host->wait_int = 0;
268 blocksize = (BLOCK_SIZE_MASK &
269 sh_mmcif_read(&host->regs->ce_block_set)) + 3;
270 for (i = 0; i < blocksize / 4; i++)
271 sh_mmcif_write(*p++, &host->regs->ce_data);
272
273 /* buffer write end */
274 sh_mmcif_bitset(MASK_MDTRANE, &host->regs->ce_int_mask);
275
276 time = mmcif_wait_interrupt_flag(host);
277 if (time == 0 || host->sd_error != 0)
278 return sh_mmcif_error_manage(host);
279
280 host->wait_int = 0;
281 return 0;
282}
283
284static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
285 struct mmc_data *data)
286{
287 long time;
288 u32 i, j, blocksize;
289 const unsigned long *p = (unsigned long *)data->dest;
290
291 if ((unsigned long)p & 0x00000001) {
292 printf("%s: The data pointer is unaligned.", __func__);
293 return -EIO;
294 }
295
296 host->wait_int = 0;
297 blocksize = BLOCK_SIZE_MASK & sh_mmcif_read(&host->regs->ce_block_set);
298 for (j = 0; j < data->blocks; j++) {
299 sh_mmcif_bitset(MASK_MBUFWEN, &host->regs->ce_int_mask);
300
301 time = mmcif_wait_interrupt_flag(host);
302
303 if (time == 0 || host->sd_error != 0)
304 return sh_mmcif_error_manage(host);
305
306 host->wait_int = 0;
307 for (i = 0; i < blocksize / 4; i++)
308 sh_mmcif_write(*p++, &host->regs->ce_data);
309
310 WATCHDOG_RESET();
311 }
312 return 0;
313}
314
315static void sh_mmcif_get_response(struct sh_mmcif_host *host,
316 struct mmc_cmd *cmd)
317{
318 if (cmd->resp_type & MMC_RSP_136) {
319 cmd->response[0] = sh_mmcif_read(&host->regs->ce_resp3);
320 cmd->response[1] = sh_mmcif_read(&host->regs->ce_resp2);
321 cmd->response[2] = sh_mmcif_read(&host->regs->ce_resp1);
322 cmd->response[3] = sh_mmcif_read(&host->regs->ce_resp0);
323 debug(" RESP %08x, %08x, %08x, %08x\n", cmd->response[0],
324 cmd->response[1], cmd->response[2], cmd->response[3]);
325 } else {
326 cmd->response[0] = sh_mmcif_read(&host->regs->ce_resp0);
327 }
328}
329
330static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host,
331 struct mmc_cmd *cmd)
332{
333 cmd->response[0] = sh_mmcif_read(&host->regs->ce_resp_cmd12);
334}
335
336static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
337 struct mmc_data *data, struct mmc_cmd *cmd)
338{
339 u32 tmp = 0;
340 u32 opc = cmd->cmdidx;
341
342 /* Response Type check */
343 switch (cmd->resp_type) {
344 case MMC_RSP_NONE:
345 tmp |= CMD_SET_RTYP_NO;
346 break;
347 case MMC_RSP_R1:
348 case MMC_RSP_R1b:
349 case MMC_RSP_R3:
350 tmp |= CMD_SET_RTYP_6B;
351 break;
352 case MMC_RSP_R2:
353 tmp |= CMD_SET_RTYP_17B;
354 break;
355 default:
356 printf(DRIVER_NAME": Not support type response.\n");
357 break;
358 }
359
360 /* RBSY */
361 if (opc == MMC_CMD_SWITCH)
362 tmp |= CMD_SET_RBSY;
363
364 /* WDAT / DATW */
365 if (host->data) {
366 tmp |= CMD_SET_WDAT;
367 switch (host->bus_width) {
368 case MMC_BUS_WIDTH_1:
369 tmp |= CMD_SET_DATW_1;
370 break;
371 case MMC_BUS_WIDTH_4:
372 tmp |= CMD_SET_DATW_4;
373 break;
374 case MMC_BUS_WIDTH_8:
375 tmp |= CMD_SET_DATW_8;
376 break;
377 default:
378 printf(DRIVER_NAME": Not support bus width.\n");
379 break;
380 }
381 }
382 /* DWEN */
383 if (opc == MMC_CMD_WRITE_SINGLE_BLOCK ||
384 opc == MMC_CMD_WRITE_MULTIPLE_BLOCK)
385 tmp |= CMD_SET_DWEN;
386 /* CMLTE/CMD12EN */
387 if (opc == MMC_CMD_READ_MULTIPLE_BLOCK ||
388 opc == MMC_CMD_WRITE_MULTIPLE_BLOCK) {
389 tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN;
390 sh_mmcif_bitset(data->blocks << 16, &host->regs->ce_block_set);
391 }
392 /* RIDXC[1:0] check bits */
393 if (opc == MMC_CMD_SEND_OP_COND || opc == MMC_CMD_ALL_SEND_CID ||
394 opc == MMC_CMD_SEND_CSD || opc == MMC_CMD_SEND_CID)
395 tmp |= CMD_SET_RIDXC_BITS;
396 /* RCRC7C[1:0] check bits */
397 if (opc == MMC_CMD_SEND_OP_COND)
398 tmp |= CMD_SET_CRC7C_BITS;
399 /* RCRC7C[1:0] internal CRC7 */
400 if (opc == MMC_CMD_ALL_SEND_CID ||
401 opc == MMC_CMD_SEND_CSD || opc == MMC_CMD_SEND_CID)
402 tmp |= CMD_SET_CRC7C_INTERNAL;
403
404 return opc = ((opc << 24) | tmp);
405}
406
407static u32 sh_mmcif_data_trans(struct sh_mmcif_host *host,
408 struct mmc_data *data, u16 opc)
409{
410 u32 ret;
411
412 switch (opc) {
413 case MMC_CMD_READ_MULTIPLE_BLOCK:
414 ret = sh_mmcif_multi_read(host, data);
415 break;
416 case MMC_CMD_WRITE_MULTIPLE_BLOCK:
417 ret = sh_mmcif_multi_write(host, data);
418 break;
419 case MMC_CMD_WRITE_SINGLE_BLOCK:
420 ret = sh_mmcif_single_write(host, data);
421 break;
422 case MMC_CMD_READ_SINGLE_BLOCK:
423 case MMC_CMD_SEND_EXT_CSD:
424 ret = sh_mmcif_single_read(host, data);
425 break;
426 default:
427 printf(DRIVER_NAME": NOT SUPPORT CMD = d'%08d\n", opc);
428 ret = -EINVAL;
429 break;
430 }
431 return ret;
432}
433
434static int sh_mmcif_start_cmd(struct sh_mmcif_host *host,
435 struct mmc_data *data, struct mmc_cmd *cmd)
436{
437 long time;
438 int ret = 0, mask = 0;
439 u32 opc = cmd->cmdidx;
440
441 if (opc == MMC_CMD_STOP_TRANSMISSION) {
442 /* MMCIF sends the STOP command automatically */
443 if (host->last_cmd == MMC_CMD_READ_MULTIPLE_BLOCK)
444 sh_mmcif_bitset(MASK_MCMD12DRE,
445 &host->regs->ce_int_mask);
446 else
447 sh_mmcif_bitset(MASK_MCMD12RBE,
448 &host->regs->ce_int_mask);
449
450 time = mmcif_wait_interrupt_flag(host);
451 if (time == 0 || host->sd_error != 0)
452 return sh_mmcif_error_manage(host);
453
454 sh_mmcif_get_cmd12response(host, cmd);
455 return 0;
456 }
457 if (opc == MMC_CMD_SWITCH)
458 mask = MASK_MRBSYE;
459 else
460 mask = MASK_MCRSPE;
461
462 mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR |
463 MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR |
464 MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO |
465 MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO;
466
467 if (host->data) {
468 sh_mmcif_write(0, &host->regs->ce_block_set);
469 sh_mmcif_write(data->blocksize, &host->regs->ce_block_set);
470 }
471 opc = sh_mmcif_set_cmd(host, data, cmd);
472
473 sh_mmcif_write(INT_START_MAGIC, &host->regs->ce_int);
474 sh_mmcif_write(mask, &host->regs->ce_int_mask);
475
476 debug("CMD%d ARG:%08x\n", cmd->cmdidx, cmd->cmdarg);
477 /* set arg */
478 sh_mmcif_write(cmd->cmdarg, &host->regs->ce_arg);
479 host->wait_int = 0;
480 /* set cmd */
481 sh_mmcif_write(opc, &host->regs->ce_cmd_set);
482
483 time = mmcif_wait_interrupt_flag(host);
484 if (time == 0)
485 return sh_mmcif_error_manage(host);
486
487 if (host->sd_error) {
488 switch (cmd->cmdidx) {
489 case MMC_CMD_ALL_SEND_CID:
490 case MMC_CMD_SELECT_CARD:
491 case MMC_CMD_APP_CMD:
Jaehoon Chung7825d202016-07-19 16:33:36 +0900492 ret = -ETIMEDOUT;
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000493 break;
494 default:
495 printf(DRIVER_NAME": Cmd(d'%d) err\n", cmd->cmdidx);
496 ret = sh_mmcif_error_manage(host);
497 break;
498 }
499 host->sd_error = 0;
500 host->wait_int = 0;
501 return ret;
502 }
503
504 /* if no response */
505 if (!(opc & 0x00C00000))
506 return 0;
507
508 if (host->wait_int == 1) {
509 sh_mmcif_get_response(host, cmd);
510 host->wait_int = 0;
511 }
512 if (host->data)
513 ret = sh_mmcif_data_trans(host, data, cmd->cmdidx);
514 host->last_cmd = cmd->cmdidx;
515
516 return ret;
517}
518
Marek Vasut26b87a02018-04-21 17:27:11 +0200519static int sh_mmcif_send_cmd_common(struct sh_mmcif_host *host,
520 struct mmc_cmd *cmd, struct mmc_data *data)
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000521{
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000522 int ret;
523
524 WATCHDOG_RESET();
525
526 switch (cmd->cmdidx) {
527 case MMC_CMD_APP_CMD:
Jaehoon Chung7825d202016-07-19 16:33:36 +0900528 return -ETIMEDOUT;
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000529 case MMC_CMD_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
530 if (data)
531 /* ext_csd */
532 break;
533 else
534 /* send_if_cond cmd (not support) */
Jaehoon Chung7825d202016-07-19 16:33:36 +0900535 return -ETIMEDOUT;
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000536 default:
537 break;
538 }
539 host->sd_error = 0;
540 host->data = data;
541 ret = sh_mmcif_start_cmd(host, data, cmd);
542 host->data = NULL;
543
544 return ret;
545}
546
Marek Vasut26b87a02018-04-21 17:27:11 +0200547static int sh_mmcif_set_ios_common(struct sh_mmcif_host *host, struct mmc *mmc)
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000548{
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000549 if (mmc->clock)
550 sh_mmcif_clock_control(host, mmc->clock);
551
552 if (mmc->bus_width == 8)
553 host->bus_width = MMC_BUS_WIDTH_8;
554 else if (mmc->bus_width == 4)
555 host->bus_width = MMC_BUS_WIDTH_4;
556 else
557 host->bus_width = MMC_BUS_WIDTH_1;
558
559 debug("clock = %d, buswidth = %d\n", mmc->clock, mmc->bus_width);
Jaehoon Chungb6cd1d32016-12-30 15:30:16 +0900560
561 return 0;
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000562}
563
Marek Vasut26b87a02018-04-21 17:27:11 +0200564static int sh_mmcif_initialize_common(struct sh_mmcif_host *host)
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000565{
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000566 sh_mmcif_sync_reset(host);
567 sh_mmcif_write(MASK_ALL, &host->regs->ce_int_mask);
568 return 0;
569}
570
Marek Vasut26b87a02018-04-21 17:27:11 +0200571#ifndef CONFIG_DM_MMC
572static void *mmc_priv(struct mmc *mmc)
573{
574 return (void *)mmc->priv;
575}
576
577static int sh_mmcif_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
578 struct mmc_data *data)
579{
580 struct sh_mmcif_host *host = mmc_priv(mmc);
581
582 return sh_mmcif_send_cmd_common(host, cmd, data);
583}
584
585static int sh_mmcif_set_ios(struct mmc *mmc)
586{
587 struct sh_mmcif_host *host = mmc_priv(mmc);
588
589 return sh_mmcif_set_ios_common(host, mmc);
590}
591
592static int sh_mmcif_initialize(struct mmc *mmc)
593{
594 struct sh_mmcif_host *host = mmc_priv(mmc);
595
596 return sh_mmcif_initialize_common(host);
597}
598
Pantelis Antoniouc9e75912014-02-26 19:28:45 +0200599static const struct mmc_ops sh_mmcif_ops = {
Marek Vasut26b87a02018-04-21 17:27:11 +0200600 .send_cmd = sh_mmcif_send_cmd,
601 .set_ios = sh_mmcif_set_ios,
602 .init = sh_mmcif_initialize,
Pantelis Antoniouc9e75912014-02-26 19:28:45 +0200603};
604
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200605static struct mmc_config sh_mmcif_cfg = {
606 .name = DRIVER_NAME,
607 .ops = &sh_mmcif_ops,
608 .host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
Rob Herring5fd3edd2015-03-23 17:56:59 -0500609 MMC_MODE_8BIT,
Nobuhiro Iwamatsu30600642014-03-31 14:54:28 +0900610 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200611 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
612};
613
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000614int mmcif_mmc_init(void)
615{
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000616 struct mmc *mmc;
617 struct sh_mmcif_host *host = NULL;
618
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000619 host = malloc(sizeof(struct sh_mmcif_host));
620 if (!host)
Nobuhiro Iwamatsu5cedb6e2014-03-31 14:54:29 +0900621 return -ENOMEM;
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000622 memset(host, 0, sizeof(*host));
623
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000624 host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR;
625 host->clk = CONFIG_SH_MMCIF_CLK;
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000626
Nobuhiro Iwamatsu2fb07ee2014-12-03 17:57:01 +0900627 sh_mmcif_cfg.f_min = MMC_CLK_DIV_MIN(host->clk);
Nobuhiro Iwamatsu36c6e712014-12-03 17:57:48 +0900628 sh_mmcif_cfg.f_max = MMC_CLK_DIV_MAX(host->clk);
Nobuhiro Iwamatsu2fb07ee2014-12-03 17:57:01 +0900629
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200630 mmc = mmc_create(&sh_mmcif_cfg, host);
631 if (mmc == NULL) {
632 free(host);
633 return -ENOMEM;
634 }
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000635
Pantelis Antoniou2c850462014-03-11 19:34:20 +0200636 return 0;
Yoshihiro Shimodadb7717b2011-07-04 22:21:22 +0000637}
Marek Vasut26b87a02018-04-21 17:27:11 +0200638
639#else
640struct sh_mmcif_plat {
641 struct mmc_config cfg;
642 struct mmc mmc;
643};
644
645int sh_mmcif_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
646 struct mmc_data *data)
647{
648 struct sh_mmcif_host *host = dev_get_priv(dev);
649
650 return sh_mmcif_send_cmd_common(host, cmd, data);
651}
652
653int sh_mmcif_dm_set_ios(struct udevice *dev)
654{
655 struct sh_mmcif_host *host = dev_get_priv(dev);
656 struct mmc *mmc = mmc_get_mmc_dev(dev);
657
658 return sh_mmcif_set_ios_common(host, mmc);
659}
660
661static const struct dm_mmc_ops sh_mmcif_dm_ops = {
662 .send_cmd = sh_mmcif_dm_send_cmd,
663 .set_ios = sh_mmcif_dm_set_ios,
664};
665
666static int sh_mmcif_dm_bind(struct udevice *dev)
667{
668 struct sh_mmcif_plat *plat = dev_get_platdata(dev);
669
670 return mmc_bind(dev, &plat->mmc, &plat->cfg);
671}
672
673static int sh_mmcif_dm_probe(struct udevice *dev)
674{
675 struct sh_mmcif_plat *plat = dev_get_platdata(dev);
676 struct sh_mmcif_host *host = dev_get_priv(dev);
677 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
678 struct clk sh_mmcif_clk;
679 fdt_addr_t base;
680 int ret;
681
682 base = devfdt_get_addr(dev);
683 if (base == FDT_ADDR_T_NONE)
684 return -EINVAL;
685
686 host->regs = (struct sh_mmcif_regs *)devm_ioremap(dev, base, SZ_2K);
687 if (!host->regs)
688 return -ENOMEM;
689
690 ret = clk_get_by_index(dev, 0, &sh_mmcif_clk);
691 if (ret) {
692 debug("failed to get clock, ret=%d\n", ret);
693 return ret;
694 }
695
696 ret = clk_enable(&sh_mmcif_clk);
697 if (ret) {
698 debug("failed to enable clock, ret=%d\n", ret);
699 return ret;
700 }
701
Marek Vasutac317672019-03-18 06:04:17 +0100702 host->clk = clk_set_rate(&sh_mmcif_clk, 97500000);
Marek Vasut26b87a02018-04-21 17:27:11 +0200703
704 plat->cfg.name = dev->name;
705 plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
706
707 switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
708 1)) {
709 case 8:
710 plat->cfg.host_caps |= MMC_MODE_8BIT;
711 break;
712 case 4:
713 plat->cfg.host_caps |= MMC_MODE_4BIT;
714 break;
715 case 1:
716 break;
717 default:
718 dev_err(dev, "Invalid \"bus-width\" value\n");
719 return -EINVAL;
720 }
721
722 sh_mmcif_initialize_common(host);
723
724 plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
725 plat->cfg.f_min = MMC_CLK_DIV_MIN(host->clk);
726 plat->cfg.f_max = MMC_CLK_DIV_MAX(host->clk);
727 plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
728
729 upriv->mmc = &plat->mmc;
730
731 return 0;
732}
733
734static const struct udevice_id sh_mmcif_sd_match[] = {
735 { .compatible = "renesas,sh-mmcif" },
736 { /* sentinel */ }
737};
738
739U_BOOT_DRIVER(sh_mmcif_mmc) = {
740 .name = "sh-mmcif",
741 .id = UCLASS_MMC,
742 .of_match = sh_mmcif_sd_match,
743 .bind = sh_mmcif_dm_bind,
744 .probe = sh_mmcif_dm_probe,
745 .priv_auto_alloc_size = sizeof(struct sh_mmcif_host),
746 .platdata_auto_alloc_size = sizeof(struct sh_mmcif_plat),
747 .ops = &sh_mmcif_dm_ops,
748};
749#endif