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