blob: f92cf00cf4477f6cd275cffbc411efd9fe41efe9 [file] [log] [blame]
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +00001/*
2 * MMCIF driver.
3 *
4 * Copyright (C) 2011 Renesas Solutions Corp.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License.
9 */
10
11#include <config.h>
12#include <common.h>
13#include <watchdog.h>
14#include <command.h>
15#include <mmc.h>
16#include <malloc.h>
17#include <asm/errno.h>
18#include <asm/io.h>
19#include "sh_mmcif.h"
20
21#define DRIVER_NAME "sh_mmcif"
22
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +000023static int sh_mmcif_intr(void *dev_id)
24{
25 struct sh_mmcif_host *host = dev_id;
26 u32 state = 0;
27
28 state = sh_mmcif_read(&host->regs->ce_int);
29 state &= sh_mmcif_read(&host->regs->ce_int_mask);
30
31 if (state & INT_RBSYE) {
32 sh_mmcif_write(~(INT_RBSYE | INT_CRSPE), &host->regs->ce_int);
33 sh_mmcif_bitclr(MASK_MRBSYE, &host->regs->ce_int_mask);
34 goto end;
35 } else if (state & INT_CRSPE) {
36 sh_mmcif_write(~INT_CRSPE, &host->regs->ce_int);
37 sh_mmcif_bitclr(MASK_MCRSPE, &host->regs->ce_int_mask);
38 /* one more interrupt (INT_RBSYE) */
39 if (sh_mmcif_read(&host->regs->ce_cmd_set) & CMD_SET_RBSY)
40 return -EAGAIN;
41 goto end;
42 } else if (state & INT_BUFREN) {
43 sh_mmcif_write(~INT_BUFREN, &host->regs->ce_int);
44 sh_mmcif_bitclr(MASK_MBUFREN, &host->regs->ce_int_mask);
45 goto end;
46 } else if (state & INT_BUFWEN) {
47 sh_mmcif_write(~INT_BUFWEN, &host->regs->ce_int);
48 sh_mmcif_bitclr(MASK_MBUFWEN, &host->regs->ce_int_mask);
49 goto end;
50 } else if (state & INT_CMD12DRE) {
51 sh_mmcif_write(~(INT_CMD12DRE | INT_CMD12RBE | INT_CMD12CRE |
52 INT_BUFRE), &host->regs->ce_int);
53 sh_mmcif_bitclr(MASK_MCMD12DRE, &host->regs->ce_int_mask);
54 goto end;
55 } else if (state & INT_BUFRE) {
56 sh_mmcif_write(~INT_BUFRE, &host->regs->ce_int);
57 sh_mmcif_bitclr(MASK_MBUFRE, &host->regs->ce_int_mask);
58 goto end;
59 } else if (state & INT_DTRANE) {
60 sh_mmcif_write(~INT_DTRANE, &host->regs->ce_int);
61 sh_mmcif_bitclr(MASK_MDTRANE, &host->regs->ce_int_mask);
62 goto end;
63 } else if (state & INT_CMD12RBE) {
64 sh_mmcif_write(~(INT_CMD12RBE | INT_CMD12CRE),
65 &host->regs->ce_int);
66 sh_mmcif_bitclr(MASK_MCMD12RBE, &host->regs->ce_int_mask);
67 goto end;
68 } else if (state & INT_ERR_STS) {
69 /* err interrupts */
70 sh_mmcif_write(~state, &host->regs->ce_int);
71 sh_mmcif_bitclr(state, &host->regs->ce_int_mask);
72 goto err;
73 } else
74 return -EAGAIN;
75
76err:
77 host->sd_error = 1;
78 debug("%s: int err state = %08x\n", DRIVER_NAME, state);
79end:
80 host->wait_int = 1;
81 return 0;
82}
83
84static int mmcif_wait_interrupt_flag(struct sh_mmcif_host *host)
85{
86 int timeout = 10000000;
87
88 while (1) {
89 timeout--;
90 if (timeout < 0) {
91 printf("timeout\n");
92 return 0;
93 }
94
95 if (!sh_mmcif_intr(host))
96 break;
97
98 udelay(1); /* 1 usec */
99 }
100
101 return 1; /* Return value: NOT 0 = complete waiting */
102}
103
104static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
105{
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000106 sh_mmcif_bitclr(CLK_ENABLE, &host->regs->ce_clk_ctrl);
107 sh_mmcif_bitclr(CLK_CLEAR, &host->regs->ce_clk_ctrl);
108
109 if (!clk)
110 return;
Nobuhiro Iwamatsu21ea3502014-12-03 17:57:00 +0900111
112 if (clk == CLKDEV_EMMC_DATA)
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000113 sh_mmcif_bitset(CLK_PCLK, &host->regs->ce_clk_ctrl);
Nobuhiro Iwamatsu21ea3502014-12-03 17:57:00 +0900114 else
115 sh_mmcif_bitset((fls(DIV_ROUND_UP(host->clk,
116 clk) - 1) - 1) << 16,
117 &host->regs->ce_clk_ctrl);
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000118 sh_mmcif_bitset(CLK_ENABLE, &host->regs->ce_clk_ctrl);
119}
120
121static void sh_mmcif_sync_reset(struct sh_mmcif_host *host)
122{
123 u32 tmp;
124
125 tmp = sh_mmcif_read(&host->regs->ce_clk_ctrl) & (CLK_ENABLE |
126 CLK_CLEAR);
127
128 sh_mmcif_write(SOFT_RST_ON, &host->regs->ce_version);
129 sh_mmcif_write(SOFT_RST_OFF, &host->regs->ce_version);
130 sh_mmcif_bitset(tmp | SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29,
131 &host->regs->ce_clk_ctrl);
132 /* byte swap on */
133 sh_mmcif_bitset(BUF_ACC_ATYP, &host->regs->ce_buf_acc);
134}
135
136static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
137{
138 u32 state1, state2;
139 int ret, timeout = 10000000;
140
141 host->sd_error = 0;
142 host->wait_int = 0;
143
144 state1 = sh_mmcif_read(&host->regs->ce_host_sts1);
145 state2 = sh_mmcif_read(&host->regs->ce_host_sts2);
146 debug("%s: ERR HOST_STS1 = %08x\n", \
147 DRIVER_NAME, sh_mmcif_read(&host->regs->ce_host_sts1));
148 debug("%s: ERR HOST_STS2 = %08x\n", \
149 DRIVER_NAME, sh_mmcif_read(&host->regs->ce_host_sts2));
150
151 if (state1 & STS1_CMDSEQ) {
152 debug("%s: Forced end of command sequence\n", DRIVER_NAME);
153 sh_mmcif_bitset(CMD_CTRL_BREAK, &host->regs->ce_cmd_ctrl);
154 sh_mmcif_bitset(~CMD_CTRL_BREAK, &host->regs->ce_cmd_ctrl);
155 while (1) {
156 timeout--;
157 if (timeout < 0) {
158 printf(DRIVER_NAME": Forceed end of " \
159 "command sequence timeout err\n");
160 return -EILSEQ;
161 }
162 if (!(sh_mmcif_read(&host->regs->ce_host_sts1)
163 & STS1_CMDSEQ))
164 break;
165 }
166 sh_mmcif_sync_reset(host);
167 return -EILSEQ;
168 }
169
170 if (state2 & STS2_CRC_ERR)
171 ret = -EILSEQ;
172 else if (state2 & STS2_TIMEOUT_ERR)
173 ret = TIMEOUT;
174 else
175 ret = -EILSEQ;
176 return ret;
177}
178
179static int sh_mmcif_single_read(struct sh_mmcif_host *host,
180 struct mmc_data *data)
181{
182 long time;
183 u32 blocksize, i;
184 unsigned long *p = (unsigned long *)data->dest;
185
186 if ((unsigned long)p & 0x00000001) {
187 printf("%s: The data pointer is unaligned.", __func__);
188 return -EIO;
189 }
190
191 host->wait_int = 0;
192
193 /* buf read enable */
194 sh_mmcif_bitset(MASK_MBUFREN, &host->regs->ce_int_mask);
195 time = mmcif_wait_interrupt_flag(host);
196 if (time == 0 || host->sd_error != 0)
197 return sh_mmcif_error_manage(host);
198
199 host->wait_int = 0;
200 blocksize = (BLOCK_SIZE_MASK &
201 sh_mmcif_read(&host->regs->ce_block_set)) + 3;
202 for (i = 0; i < blocksize / 4; i++)
203 *p++ = sh_mmcif_read(&host->regs->ce_data);
204
205 /* buffer read end */
206 sh_mmcif_bitset(MASK_MBUFRE, &host->regs->ce_int_mask);
207 time = mmcif_wait_interrupt_flag(host);
208 if (time == 0 || host->sd_error != 0)
209 return sh_mmcif_error_manage(host);
210
211 host->wait_int = 0;
212 return 0;
213}
214
215static int sh_mmcif_multi_read(struct sh_mmcif_host *host,
216 struct mmc_data *data)
217{
218 long time;
219 u32 blocksize, i, j;
220 unsigned long *p = (unsigned long *)data->dest;
221
222 if ((unsigned long)p & 0x00000001) {
223 printf("%s: The data pointer is unaligned.", __func__);
224 return -EIO;
225 }
226
227 host->wait_int = 0;
228 blocksize = BLOCK_SIZE_MASK & sh_mmcif_read(&host->regs->ce_block_set);
229 for (j = 0; j < data->blocks; j++) {
230 sh_mmcif_bitset(MASK_MBUFREN, &host->regs->ce_int_mask);
231 time = mmcif_wait_interrupt_flag(host);
232 if (time == 0 || host->sd_error != 0)
233 return sh_mmcif_error_manage(host);
234
235 host->wait_int = 0;
236 for (i = 0; i < blocksize / 4; i++)
237 *p++ = sh_mmcif_read(&host->regs->ce_data);
238
239 WATCHDOG_RESET();
240 }
241 return 0;
242}
243
244static int sh_mmcif_single_write(struct sh_mmcif_host *host,
245 struct mmc_data *data)
246{
247 long time;
248 u32 blocksize, i;
249 const unsigned long *p = (unsigned long *)data->dest;
250
251 if ((unsigned long)p & 0x00000001) {
252 printf("%s: The data pointer is unaligned.", __func__);
253 return -EIO;
254 }
255
256 host->wait_int = 0;
257 sh_mmcif_bitset(MASK_MBUFWEN, &host->regs->ce_int_mask);
258
259 time = mmcif_wait_interrupt_flag(host);
260 if (time == 0 || host->sd_error != 0)
261 return sh_mmcif_error_manage(host);
262
263 host->wait_int = 0;
264 blocksize = (BLOCK_SIZE_MASK &
265 sh_mmcif_read(&host->regs->ce_block_set)) + 3;
266 for (i = 0; i < blocksize / 4; i++)
267 sh_mmcif_write(*p++, &host->regs->ce_data);
268
269 /* buffer write end */
270 sh_mmcif_bitset(MASK_MDTRANE, &host->regs->ce_int_mask);
271
272 time = mmcif_wait_interrupt_flag(host);
273 if (time == 0 || host->sd_error != 0)
274 return sh_mmcif_error_manage(host);
275
276 host->wait_int = 0;
277 return 0;
278}
279
280static int sh_mmcif_multi_write(struct sh_mmcif_host *host,
281 struct mmc_data *data)
282{
283 long time;
284 u32 i, j, blocksize;
285 const unsigned long *p = (unsigned long *)data->dest;
286
287 if ((unsigned long)p & 0x00000001) {
288 printf("%s: The data pointer is unaligned.", __func__);
289 return -EIO;
290 }
291
292 host->wait_int = 0;
293 blocksize = BLOCK_SIZE_MASK & sh_mmcif_read(&host->regs->ce_block_set);
294 for (j = 0; j < data->blocks; j++) {
295 sh_mmcif_bitset(MASK_MBUFWEN, &host->regs->ce_int_mask);
296
297 time = mmcif_wait_interrupt_flag(host);
298
299 if (time == 0 || host->sd_error != 0)
300 return sh_mmcif_error_manage(host);
301
302 host->wait_int = 0;
303 for (i = 0; i < blocksize / 4; i++)
304 sh_mmcif_write(*p++, &host->regs->ce_data);
305
306 WATCHDOG_RESET();
307 }
308 return 0;
309}
310
311static void sh_mmcif_get_response(struct sh_mmcif_host *host,
312 struct mmc_cmd *cmd)
313{
314 if (cmd->resp_type & MMC_RSP_136) {
315 cmd->response[0] = sh_mmcif_read(&host->regs->ce_resp3);
316 cmd->response[1] = sh_mmcif_read(&host->regs->ce_resp2);
317 cmd->response[2] = sh_mmcif_read(&host->regs->ce_resp1);
318 cmd->response[3] = sh_mmcif_read(&host->regs->ce_resp0);
319 debug(" RESP %08x, %08x, %08x, %08x\n", cmd->response[0],
320 cmd->response[1], cmd->response[2], cmd->response[3]);
321 } else {
322 cmd->response[0] = sh_mmcif_read(&host->regs->ce_resp0);
323 }
324}
325
326static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host,
327 struct mmc_cmd *cmd)
328{
329 cmd->response[0] = sh_mmcif_read(&host->regs->ce_resp_cmd12);
330}
331
332static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
333 struct mmc_data *data, struct mmc_cmd *cmd)
334{
335 u32 tmp = 0;
336 u32 opc = cmd->cmdidx;
337
338 /* Response Type check */
339 switch (cmd->resp_type) {
340 case MMC_RSP_NONE:
341 tmp |= CMD_SET_RTYP_NO;
342 break;
343 case MMC_RSP_R1:
344 case MMC_RSP_R1b:
345 case MMC_RSP_R3:
346 tmp |= CMD_SET_RTYP_6B;
347 break;
348 case MMC_RSP_R2:
349 tmp |= CMD_SET_RTYP_17B;
350 break;
351 default:
352 printf(DRIVER_NAME": Not support type response.\n");
353 break;
354 }
355
356 /* RBSY */
357 if (opc == MMC_CMD_SWITCH)
358 tmp |= CMD_SET_RBSY;
359
360 /* WDAT / DATW */
361 if (host->data) {
362 tmp |= CMD_SET_WDAT;
363 switch (host->bus_width) {
364 case MMC_BUS_WIDTH_1:
365 tmp |= CMD_SET_DATW_1;
366 break;
367 case MMC_BUS_WIDTH_4:
368 tmp |= CMD_SET_DATW_4;
369 break;
370 case MMC_BUS_WIDTH_8:
371 tmp |= CMD_SET_DATW_8;
372 break;
373 default:
374 printf(DRIVER_NAME": Not support bus width.\n");
375 break;
376 }
377 }
378 /* DWEN */
379 if (opc == MMC_CMD_WRITE_SINGLE_BLOCK ||
380 opc == MMC_CMD_WRITE_MULTIPLE_BLOCK)
381 tmp |= CMD_SET_DWEN;
382 /* CMLTE/CMD12EN */
383 if (opc == MMC_CMD_READ_MULTIPLE_BLOCK ||
384 opc == MMC_CMD_WRITE_MULTIPLE_BLOCK) {
385 tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN;
386 sh_mmcif_bitset(data->blocks << 16, &host->regs->ce_block_set);
387 }
388 /* RIDXC[1:0] check bits */
389 if (opc == MMC_CMD_SEND_OP_COND || opc == MMC_CMD_ALL_SEND_CID ||
390 opc == MMC_CMD_SEND_CSD || opc == MMC_CMD_SEND_CID)
391 tmp |= CMD_SET_RIDXC_BITS;
392 /* RCRC7C[1:0] check bits */
393 if (opc == MMC_CMD_SEND_OP_COND)
394 tmp |= CMD_SET_CRC7C_BITS;
395 /* RCRC7C[1:0] internal CRC7 */
396 if (opc == MMC_CMD_ALL_SEND_CID ||
397 opc == MMC_CMD_SEND_CSD || opc == MMC_CMD_SEND_CID)
398 tmp |= CMD_SET_CRC7C_INTERNAL;
399
400 return opc = ((opc << 24) | tmp);
401}
402
403static u32 sh_mmcif_data_trans(struct sh_mmcif_host *host,
404 struct mmc_data *data, u16 opc)
405{
406 u32 ret;
407
408 switch (opc) {
409 case MMC_CMD_READ_MULTIPLE_BLOCK:
410 ret = sh_mmcif_multi_read(host, data);
411 break;
412 case MMC_CMD_WRITE_MULTIPLE_BLOCK:
413 ret = sh_mmcif_multi_write(host, data);
414 break;
415 case MMC_CMD_WRITE_SINGLE_BLOCK:
416 ret = sh_mmcif_single_write(host, data);
417 break;
418 case MMC_CMD_READ_SINGLE_BLOCK:
419 case MMC_CMD_SEND_EXT_CSD:
420 ret = sh_mmcif_single_read(host, data);
421 break;
422 default:
423 printf(DRIVER_NAME": NOT SUPPORT CMD = d'%08d\n", opc);
424 ret = -EINVAL;
425 break;
426 }
427 return ret;
428}
429
430static int sh_mmcif_start_cmd(struct sh_mmcif_host *host,
431 struct mmc_data *data, struct mmc_cmd *cmd)
432{
433 long time;
434 int ret = 0, mask = 0;
435 u32 opc = cmd->cmdidx;
436
437 if (opc == MMC_CMD_STOP_TRANSMISSION) {
438 /* MMCIF sends the STOP command automatically */
439 if (host->last_cmd == MMC_CMD_READ_MULTIPLE_BLOCK)
440 sh_mmcif_bitset(MASK_MCMD12DRE,
441 &host->regs->ce_int_mask);
442 else
443 sh_mmcif_bitset(MASK_MCMD12RBE,
444 &host->regs->ce_int_mask);
445
446 time = mmcif_wait_interrupt_flag(host);
447 if (time == 0 || host->sd_error != 0)
448 return sh_mmcif_error_manage(host);
449
450 sh_mmcif_get_cmd12response(host, cmd);
451 return 0;
452 }
453 if (opc == MMC_CMD_SWITCH)
454 mask = MASK_MRBSYE;
455 else
456 mask = MASK_MCRSPE;
457
458 mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR |
459 MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR |
460 MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO |
461 MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO;
462
463 if (host->data) {
464 sh_mmcif_write(0, &host->regs->ce_block_set);
465 sh_mmcif_write(data->blocksize, &host->regs->ce_block_set);
466 }
467 opc = sh_mmcif_set_cmd(host, data, cmd);
468
469 sh_mmcif_write(INT_START_MAGIC, &host->regs->ce_int);
470 sh_mmcif_write(mask, &host->regs->ce_int_mask);
471
472 debug("CMD%d ARG:%08x\n", cmd->cmdidx, cmd->cmdarg);
473 /* set arg */
474 sh_mmcif_write(cmd->cmdarg, &host->regs->ce_arg);
475 host->wait_int = 0;
476 /* set cmd */
477 sh_mmcif_write(opc, &host->regs->ce_cmd_set);
478
479 time = mmcif_wait_interrupt_flag(host);
480 if (time == 0)
481 return sh_mmcif_error_manage(host);
482
483 if (host->sd_error) {
484 switch (cmd->cmdidx) {
485 case MMC_CMD_ALL_SEND_CID:
486 case MMC_CMD_SELECT_CARD:
487 case MMC_CMD_APP_CMD:
488 ret = TIMEOUT;
489 break;
490 default:
491 printf(DRIVER_NAME": Cmd(d'%d) err\n", cmd->cmdidx);
492 ret = sh_mmcif_error_manage(host);
493 break;
494 }
495 host->sd_error = 0;
496 host->wait_int = 0;
497 return ret;
498 }
499
500 /* if no response */
501 if (!(opc & 0x00C00000))
502 return 0;
503
504 if (host->wait_int == 1) {
505 sh_mmcif_get_response(host, cmd);
506 host->wait_int = 0;
507 }
508 if (host->data)
509 ret = sh_mmcif_data_trans(host, data, cmd->cmdidx);
510 host->last_cmd = cmd->cmdidx;
511
512 return ret;
513}
514
515static int sh_mmcif_request(struct mmc *mmc, struct mmc_cmd *cmd,
516 struct mmc_data *data)
517{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200518 struct sh_mmcif_host *host = mmc->priv;
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000519 int ret;
520
521 WATCHDOG_RESET();
522
523 switch (cmd->cmdidx) {
524 case MMC_CMD_APP_CMD:
525 return TIMEOUT;
526 case MMC_CMD_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
527 if (data)
528 /* ext_csd */
529 break;
530 else
531 /* send_if_cond cmd (not support) */
532 return TIMEOUT;
533 default:
534 break;
535 }
536 host->sd_error = 0;
537 host->data = data;
538 ret = sh_mmcif_start_cmd(host, data, cmd);
539 host->data = NULL;
540
541 return ret;
542}
543
544static void sh_mmcif_set_ios(struct mmc *mmc)
545{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200546 struct sh_mmcif_host *host = mmc->priv;
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000547
548 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);
559}
560
561static int sh_mmcif_init(struct mmc *mmc)
562{
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200563 struct sh_mmcif_host *host = mmc->priv;
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000564
565 sh_mmcif_sync_reset(host);
566 sh_mmcif_write(MASK_ALL, &host->regs->ce_int_mask);
567 return 0;
568}
569
Pantelis Antoniouab769f22014-02-26 19:28:45 +0200570static const struct mmc_ops sh_mmcif_ops = {
571 .send_cmd = sh_mmcif_request,
572 .set_ios = sh_mmcif_set_ios,
573 .init = sh_mmcif_init,
574};
575
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200576static struct mmc_config sh_mmcif_cfg = {
577 .name = DRIVER_NAME,
578 .ops = &sh_mmcif_ops,
579 .host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT |
Rob Herring5a203972015-03-23 17:56:59 -0500580 MMC_MODE_8BIT,
Nobuhiro Iwamatsucd2bf482014-03-31 14:54:28 +0900581 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34,
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200582 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
583};
584
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000585int mmcif_mmc_init(void)
586{
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000587 struct mmc *mmc;
588 struct sh_mmcif_host *host = NULL;
589
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000590 host = malloc(sizeof(struct sh_mmcif_host));
591 if (!host)
Nobuhiro Iwamatsu74c32ef2014-03-31 14:54:29 +0900592 return -ENOMEM;
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000593 memset(host, 0, sizeof(*host));
594
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000595 host->regs = (struct sh_mmcif_regs *)CONFIG_SH_MMCIF_ADDR;
596 host->clk = CONFIG_SH_MMCIF_CLK;
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000597
Nobuhiro Iwamatsu7a7eb982014-12-03 17:57:01 +0900598 sh_mmcif_cfg.f_min = MMC_CLK_DIV_MIN(host->clk);
Nobuhiro Iwamatsu9675f612014-12-03 17:57:48 +0900599 sh_mmcif_cfg.f_max = MMC_CLK_DIV_MAX(host->clk);
Nobuhiro Iwamatsu7a7eb982014-12-03 17:57:01 +0900600
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200601 mmc = mmc_create(&sh_mmcif_cfg, host);
602 if (mmc == NULL) {
603 free(host);
604 return -ENOMEM;
605 }
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000606
Pantelis Antoniou93bfd612014-03-11 19:34:20 +0200607 return 0;
Yoshihiro Shimodaafb35662011-07-04 22:21:22 +0000608}