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