gpio-uclass.c: Fix comparison of unsigned expression warning
[platform/kernel/u-boot.git] / drivers / mmc / sh_sdhi.c
1 /*
2  * drivers/mmc/sh_sdhi.c
3  *
4  * SD/MMC driver for Renesas rmobile ARM SoCs.
5  *
6  * Copyright (C) 2011,2013-2014 Renesas Electronics Corporation
7  * Copyright (C) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
8  * Copyright (C) 2008-2009 Renesas Solutions Corp.
9  *
10  * SPDX-License-Identifier:     GPL-2.0
11  */
12
13 #include <common.h>
14 #include <malloc.h>
15 #include <mmc.h>
16 #include <linux/errno.h>
17 #include <asm/io.h>
18 #include <asm/arch/rmobile.h>
19 #include <asm/arch/sh_sdhi.h>
20
21 #define DRIVER_NAME "sh-sdhi"
22
23 struct sh_sdhi_host {
24         unsigned long addr;
25         int ch;
26         int bus_shift;
27         unsigned long quirks;
28         unsigned char wait_int;
29         unsigned char sd_error;
30         unsigned char detect_waiting;
31 };
32 static inline void sh_sdhi_writew(struct sh_sdhi_host *host, int reg, u16 val)
33 {
34         writew(val, host->addr + (reg << host->bus_shift));
35 }
36
37 static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
38 {
39         return readw(host->addr + (reg << host->bus_shift));
40 }
41
42 static void *mmc_priv(struct mmc *mmc)
43 {
44         return (void *)mmc->priv;
45 }
46
47 static void sh_sdhi_detect(struct sh_sdhi_host *host)
48 {
49         sh_sdhi_writew(host, SDHI_OPTION,
50                        OPT_BUS_WIDTH_1 | sh_sdhi_readw(host, SDHI_OPTION));
51
52         host->detect_waiting = 0;
53 }
54
55 static int sh_sdhi_intr(void *dev_id)
56 {
57         struct sh_sdhi_host *host = dev_id;
58         int state1 = 0, state2 = 0;
59
60         state1 = sh_sdhi_readw(host, SDHI_INFO1);
61         state2 = sh_sdhi_readw(host, SDHI_INFO2);
62
63         debug("%s: state1 = %x, state2 = %x\n", __func__, state1, state2);
64
65         /* CARD Insert */
66         if (state1 & INFO1_CARD_IN) {
67                 sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_CARD_IN);
68                 if (!host->detect_waiting) {
69                         host->detect_waiting = 1;
70                         sh_sdhi_detect(host);
71                 }
72                 sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
73                                INFO1M_ACCESS_END | INFO1M_CARD_IN |
74                                INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
75                 return -EAGAIN;
76         }
77         /* CARD Removal */
78         if (state1 & INFO1_CARD_RE) {
79                 sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_CARD_RE);
80                 if (!host->detect_waiting) {
81                         host->detect_waiting = 1;
82                         sh_sdhi_detect(host);
83                 }
84                 sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
85                                INFO1M_ACCESS_END | INFO1M_CARD_RE |
86                                INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
87                 sh_sdhi_writew(host, SDHI_SDIO_INFO1_MASK, SDIO_INFO1M_ON);
88                 sh_sdhi_writew(host, SDHI_SDIO_MODE, SDIO_MODE_OFF);
89                 return -EAGAIN;
90         }
91
92         if (state2 & INFO2_ALL_ERR) {
93                 sh_sdhi_writew(host, SDHI_INFO2,
94                                (unsigned short)~(INFO2_ALL_ERR));
95                 sh_sdhi_writew(host, SDHI_INFO2_MASK,
96                                INFO2M_ALL_ERR |
97                                sh_sdhi_readw(host, SDHI_INFO2_MASK));
98                 host->sd_error = 1;
99                 host->wait_int = 1;
100                 return 0;
101         }
102         /* Respons End */
103         if (state1 & INFO1_RESP_END) {
104                 sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
105                 sh_sdhi_writew(host, SDHI_INFO1_MASK,
106                                INFO1M_RESP_END |
107                                sh_sdhi_readw(host, SDHI_INFO1_MASK));
108                 host->wait_int = 1;
109                 return 0;
110         }
111         /* SD_BUF Read Enable */
112         if (state2 & INFO2_BRE_ENABLE) {
113                 sh_sdhi_writew(host, SDHI_INFO2, ~INFO2_BRE_ENABLE);
114                 sh_sdhi_writew(host, SDHI_INFO2_MASK,
115                                INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ |
116                                sh_sdhi_readw(host, SDHI_INFO2_MASK));
117                 host->wait_int = 1;
118                 return 0;
119         }
120         /* SD_BUF Write Enable */
121         if (state2 & INFO2_BWE_ENABLE) {
122                 sh_sdhi_writew(host, SDHI_INFO2, ~INFO2_BWE_ENABLE);
123                 sh_sdhi_writew(host, SDHI_INFO2_MASK,
124                                INFO2_BWE_ENABLE | INFO2M_BUF_ILL_WRITE |
125                                sh_sdhi_readw(host, SDHI_INFO2_MASK));
126                 host->wait_int = 1;
127                 return 0;
128         }
129         /* Access End */
130         if (state1 & INFO1_ACCESS_END) {
131                 sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_ACCESS_END);
132                 sh_sdhi_writew(host, SDHI_INFO1_MASK,
133                                INFO1_ACCESS_END |
134                                sh_sdhi_readw(host, SDHI_INFO1_MASK));
135                 host->wait_int = 1;
136                 return 0;
137         }
138         return -EAGAIN;
139 }
140
141 static int sh_sdhi_wait_interrupt_flag(struct sh_sdhi_host *host)
142 {
143         int timeout = 10000000;
144
145         while (1) {
146                 timeout--;
147                 if (timeout < 0) {
148                         debug(DRIVER_NAME": %s timeout\n", __func__);
149                         return 0;
150                 }
151
152                 if (!sh_sdhi_intr(host))
153                         break;
154
155                 udelay(1);      /* 1 usec */
156         }
157
158         return 1; /* Return value: NOT 0 = complete waiting */
159 }
160
161 static int sh_sdhi_clock_control(struct sh_sdhi_host *host, unsigned long clk)
162 {
163         u32 clkdiv, i, timeout;
164
165         if (sh_sdhi_readw(host, SDHI_INFO2) & (1 << 14)) {
166                 printf(DRIVER_NAME": Busy state ! Cannot change the clock\n");
167                 return -EBUSY;
168         }
169
170         sh_sdhi_writew(host, SDHI_CLK_CTRL,
171                        ~CLK_ENABLE & sh_sdhi_readw(host, SDHI_CLK_CTRL));
172
173         if (clk == 0)
174                 return -EIO;
175
176         clkdiv = 0x80;
177         i = CONFIG_SH_SDHI_FREQ >> (0x8 + 1);
178         for (; clkdiv && clk >= (i << 1); (clkdiv >>= 1))
179                 i <<= 1;
180
181         sh_sdhi_writew(host, SDHI_CLK_CTRL, clkdiv);
182
183         timeout = 100000;
184         /* Waiting for SD Bus busy to be cleared */
185         while (timeout--) {
186                 if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000))
187                         break;
188         }
189
190         if (timeout)
191                 sh_sdhi_writew(host, SDHI_CLK_CTRL,
192                                CLK_ENABLE | sh_sdhi_readw(host, SDHI_CLK_CTRL));
193         else
194                 return -EBUSY;
195
196         return 0;
197 }
198
199 static int sh_sdhi_sync_reset(struct sh_sdhi_host *host)
200 {
201         u32 timeout;
202         sh_sdhi_writew(host, SDHI_SOFT_RST, SOFT_RST_ON);
203         sh_sdhi_writew(host, SDHI_SOFT_RST, SOFT_RST_OFF);
204         sh_sdhi_writew(host, SDHI_CLK_CTRL,
205                        CLK_ENABLE | sh_sdhi_readw(host, SDHI_CLK_CTRL));
206
207         timeout = 100000;
208         while (timeout--) {
209                 if (!(sh_sdhi_readw(host, SDHI_INFO2) & INFO2_CBUSY))
210                         break;
211                 udelay(100);
212         }
213
214         if (!timeout)
215                 return -EBUSY;
216
217         if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
218                 sh_sdhi_writew(host, SDHI_HOST_MODE, 1);
219
220         return 0;
221 }
222
223 static int sh_sdhi_error_manage(struct sh_sdhi_host *host)
224 {
225         unsigned short e_state1, e_state2;
226         int ret;
227
228         host->sd_error = 0;
229         host->wait_int = 0;
230
231         e_state1 = sh_sdhi_readw(host, SDHI_ERR_STS1);
232         e_state2 = sh_sdhi_readw(host, SDHI_ERR_STS2);
233         if (e_state2 & ERR_STS2_SYS_ERROR) {
234                 if (e_state2 & ERR_STS2_RES_STOP_TIMEOUT)
235                         ret = -ETIMEDOUT;
236                 else
237                         ret = -EILSEQ;
238                 debug("%s: ERR_STS2 = %04x\n",
239                       DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS2));
240                 sh_sdhi_sync_reset(host);
241
242                 sh_sdhi_writew(host, SDHI_INFO1_MASK,
243                                INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
244                 return ret;
245         }
246         if (e_state1 & ERR_STS1_CRC_ERROR || e_state1 & ERR_STS1_CMD_ERROR)
247                 ret = -EILSEQ;
248         else
249                 ret = -ETIMEDOUT;
250
251         debug("%s: ERR_STS1 = %04x\n",
252               DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS1));
253         sh_sdhi_sync_reset(host);
254         sh_sdhi_writew(host, SDHI_INFO1_MASK,
255                        INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
256         return ret;
257 }
258
259 static int sh_sdhi_single_read(struct sh_sdhi_host *host, struct mmc_data *data)
260 {
261         long time;
262         unsigned short blocksize, i;
263         unsigned short *p = (unsigned short *)data->dest;
264
265         if ((unsigned long)p & 0x00000001) {
266                 debug(DRIVER_NAME": %s: The data pointer is unaligned.",
267                       __func__);
268                 return -EIO;
269         }
270
271         host->wait_int = 0;
272         sh_sdhi_writew(host, SDHI_INFO2_MASK,
273                        ~(INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ) &
274                        sh_sdhi_readw(host, SDHI_INFO2_MASK));
275         sh_sdhi_writew(host, SDHI_INFO1_MASK,
276                        ~INFO1M_ACCESS_END &
277                        sh_sdhi_readw(host, SDHI_INFO1_MASK));
278         time = sh_sdhi_wait_interrupt_flag(host);
279         if (time == 0 || host->sd_error != 0)
280                 return sh_sdhi_error_manage(host);
281
282         host->wait_int = 0;
283         blocksize = sh_sdhi_readw(host, SDHI_SIZE);
284         for (i = 0; i < blocksize / 2; i++)
285                 *p++ = sh_sdhi_readw(host, SDHI_BUF0);
286
287         time = sh_sdhi_wait_interrupt_flag(host);
288         if (time == 0 || host->sd_error != 0)
289                 return sh_sdhi_error_manage(host);
290
291         host->wait_int = 0;
292         return 0;
293 }
294
295 static int sh_sdhi_multi_read(struct sh_sdhi_host *host, struct mmc_data *data)
296 {
297         long time;
298         unsigned short blocksize, i, sec;
299         unsigned short *p = (unsigned short *)data->dest;
300
301         if ((unsigned long)p & 0x00000001) {
302                 debug(DRIVER_NAME": %s: The data pointer is unaligned.",
303                       __func__);
304                 return -EIO;
305         }
306
307         debug("%s: blocks = %d, blocksize = %d\n",
308               __func__, data->blocks, data->blocksize);
309
310         host->wait_int = 0;
311         for (sec = 0; sec < data->blocks; sec++) {
312                 sh_sdhi_writew(host, SDHI_INFO2_MASK,
313                                ~(INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ) &
314                                sh_sdhi_readw(host, SDHI_INFO2_MASK));
315
316                 time = sh_sdhi_wait_interrupt_flag(host);
317                 if (time == 0 || host->sd_error != 0)
318                         return sh_sdhi_error_manage(host);
319
320                 host->wait_int = 0;
321                 blocksize = sh_sdhi_readw(host, SDHI_SIZE);
322                 for (i = 0; i < blocksize / 2; i++)
323                         *p++ = sh_sdhi_readw(host, SDHI_BUF0);
324         }
325
326         return 0;
327 }
328
329 static int sh_sdhi_single_write(struct sh_sdhi_host *host,
330                 struct mmc_data *data)
331 {
332         long time;
333         unsigned short blocksize, i;
334         const unsigned short *p = (const unsigned short *)data->src;
335
336         if ((unsigned long)p & 0x00000001) {
337                 debug(DRIVER_NAME": %s: The data pointer is unaligned.",
338                       __func__);
339                 return -EIO;
340         }
341
342         debug("%s: blocks = %d, blocksize = %d\n",
343               __func__, data->blocks, data->blocksize);
344
345         host->wait_int = 0;
346         sh_sdhi_writew(host, SDHI_INFO2_MASK,
347                        ~(INFO2M_BWE_ENABLE | INFO2M_BUF_ILL_WRITE) &
348                        sh_sdhi_readw(host, SDHI_INFO2_MASK));
349         sh_sdhi_writew(host, SDHI_INFO1_MASK,
350                        ~INFO1M_ACCESS_END &
351                        sh_sdhi_readw(host, SDHI_INFO1_MASK));
352
353         time = sh_sdhi_wait_interrupt_flag(host);
354         if (time == 0 || host->sd_error != 0)
355                 return sh_sdhi_error_manage(host);
356
357         host->wait_int = 0;
358         blocksize = sh_sdhi_readw(host, SDHI_SIZE);
359         for (i = 0; i < blocksize / 2; i++)
360                 sh_sdhi_writew(host, SDHI_BUF0, *p++);
361
362         time = sh_sdhi_wait_interrupt_flag(host);
363         if (time == 0 || host->sd_error != 0)
364                 return sh_sdhi_error_manage(host);
365
366         host->wait_int = 0;
367         return 0;
368 }
369
370 static int sh_sdhi_multi_write(struct sh_sdhi_host *host, struct mmc_data *data)
371 {
372         long time;
373         unsigned short i, sec, blocksize;
374         const unsigned short *p = (const unsigned short *)data->src;
375
376         debug("%s: blocks = %d, blocksize = %d\n",
377               __func__, data->blocks, data->blocksize);
378
379         host->wait_int = 0;
380         for (sec = 0; sec < data->blocks; sec++) {
381                 sh_sdhi_writew(host, SDHI_INFO2_MASK,
382                                ~(INFO2M_BWE_ENABLE | INFO2M_BUF_ILL_WRITE) &
383                                sh_sdhi_readw(host, SDHI_INFO2_MASK));
384
385                 time = sh_sdhi_wait_interrupt_flag(host);
386                 if (time == 0 || host->sd_error != 0)
387                         return sh_sdhi_error_manage(host);
388
389                 host->wait_int = 0;
390                 blocksize = sh_sdhi_readw(host, SDHI_SIZE);
391                 for (i = 0; i < blocksize / 2; i++)
392                         sh_sdhi_writew(host, SDHI_BUF0, *p++);
393         }
394
395         return 0;
396 }
397
398 static void sh_sdhi_get_response(struct sh_sdhi_host *host, struct mmc_cmd *cmd)
399 {
400         unsigned short i, j, cnt = 1;
401         unsigned short resp[8];
402
403         if (cmd->resp_type & MMC_RSP_136) {
404                 cnt = 4;
405                 resp[0] = sh_sdhi_readw(host, SDHI_RSP00);
406                 resp[1] = sh_sdhi_readw(host, SDHI_RSP01);
407                 resp[2] = sh_sdhi_readw(host, SDHI_RSP02);
408                 resp[3] = sh_sdhi_readw(host, SDHI_RSP03);
409                 resp[4] = sh_sdhi_readw(host, SDHI_RSP04);
410                 resp[5] = sh_sdhi_readw(host, SDHI_RSP05);
411                 resp[6] = sh_sdhi_readw(host, SDHI_RSP06);
412                 resp[7] = sh_sdhi_readw(host, SDHI_RSP07);
413
414                 /* SDHI REGISTER SPECIFICATION */
415                 for (i = 7, j = 6; i > 0; i--) {
416                         resp[i] = (resp[i] << 8) & 0xff00;
417                         resp[i] |= (resp[j--] >> 8) & 0x00ff;
418                 }
419                 resp[0] = (resp[0] << 8) & 0xff00;
420         } else {
421                 resp[0] = sh_sdhi_readw(host, SDHI_RSP00);
422                 resp[1] = sh_sdhi_readw(host, SDHI_RSP01);
423         }
424
425 #if defined(__BIG_ENDIAN_BITFIELD)
426         if (cnt == 4) {
427                 cmd->response[0] = (resp[6] << 16) | resp[7];
428                 cmd->response[1] = (resp[4] << 16) | resp[5];
429                 cmd->response[2] = (resp[2] << 16) | resp[3];
430                 cmd->response[3] = (resp[0] << 16) | resp[1];
431         } else {
432                 cmd->response[0] = (resp[0] << 16) | resp[1];
433         }
434 #else
435         if (cnt == 4) {
436                 cmd->response[0] = (resp[7] << 16) | resp[6];
437                 cmd->response[1] = (resp[5] << 16) | resp[4];
438                 cmd->response[2] = (resp[3] << 16) | resp[2];
439                 cmd->response[3] = (resp[1] << 16) | resp[0];
440         } else {
441                 cmd->response[0] = (resp[1] << 16) | resp[0];
442         }
443 #endif /* __BIG_ENDIAN_BITFIELD */
444 }
445
446 static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host,
447                         struct mmc_data *data, unsigned short opc)
448 {
449         switch (opc) {
450         case SD_CMD_APP_SEND_OP_COND:
451         case SD_CMD_APP_SEND_SCR:
452                 opc |= SDHI_APP;
453                 break;
454         case SD_CMD_APP_SET_BUS_WIDTH:
455                  /* SD_APP_SET_BUS_WIDTH*/
456                 if (!data)
457                         opc |= SDHI_APP;
458                 else /* SD_SWITCH */
459                         opc = SDHI_SD_SWITCH;
460                 break;
461         default:
462                 break;
463         }
464         return opc;
465 }
466
467 static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host,
468                         struct mmc_data *data, unsigned short opc)
469 {
470         unsigned short ret;
471
472         switch (opc) {
473         case MMC_CMD_READ_MULTIPLE_BLOCK:
474                 ret = sh_sdhi_multi_read(host, data);
475                 break;
476         case MMC_CMD_WRITE_MULTIPLE_BLOCK:
477                 ret = sh_sdhi_multi_write(host, data);
478                 break;
479         case MMC_CMD_WRITE_SINGLE_BLOCK:
480                 ret = sh_sdhi_single_write(host, data);
481                 break;
482         case MMC_CMD_READ_SINGLE_BLOCK:
483         case SDHI_SD_APP_SEND_SCR:
484         case SDHI_SD_SWITCH: /* SD_SWITCH */
485                 ret = sh_sdhi_single_read(host, data);
486                 break;
487         default:
488                 printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
489                 ret = -EINVAL;
490                 break;
491         }
492         return ret;
493 }
494
495 static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
496                         struct mmc_data *data, struct mmc_cmd *cmd)
497 {
498         long time;
499         unsigned short opc = cmd->cmdidx;
500         int ret = 0;
501         unsigned long timeout;
502
503         debug("opc = %d, arg = %x, resp_type = %x\n",
504               opc, cmd->cmdarg, cmd->resp_type);
505
506         if (opc == MMC_CMD_STOP_TRANSMISSION) {
507                 /* SDHI sends the STOP command automatically by STOP reg */
508                 sh_sdhi_writew(host, SDHI_INFO1_MASK, ~INFO1M_ACCESS_END &
509                                sh_sdhi_readw(host, SDHI_INFO1_MASK));
510
511                 time = sh_sdhi_wait_interrupt_flag(host);
512                 if (time == 0 || host->sd_error != 0)
513                         return sh_sdhi_error_manage(host);
514
515                 sh_sdhi_get_response(host, cmd);
516                 return 0;
517         }
518
519         if (data) {
520                 if ((opc == MMC_CMD_READ_MULTIPLE_BLOCK) ||
521                     opc == MMC_CMD_WRITE_MULTIPLE_BLOCK) {
522                         sh_sdhi_writew(host, SDHI_STOP, STOP_SEC_ENABLE);
523                         sh_sdhi_writew(host, SDHI_SECCNT, data->blocks);
524                 }
525                 sh_sdhi_writew(host, SDHI_SIZE, data->blocksize);
526         }
527         opc = sh_sdhi_set_cmd(host, data, opc);
528
529         /*
530          *  U-Boot cannot use interrupt.
531          *  So this flag may not be clear by timing
532          */
533         sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
534
535         sh_sdhi_writew(host, SDHI_INFO1_MASK,
536                        INFO1M_RESP_END | sh_sdhi_readw(host, SDHI_INFO1_MASK));
537         sh_sdhi_writew(host, SDHI_ARG0,
538                        (unsigned short)(cmd->cmdarg & ARG0_MASK));
539         sh_sdhi_writew(host, SDHI_ARG1,
540                        (unsigned short)((cmd->cmdarg >> 16) & ARG1_MASK));
541
542         timeout = 100000;
543         /* Waiting for SD Bus busy to be cleared */
544         while (timeout--) {
545                 if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000))
546                         break;
547         }
548
549         sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(opc & CMD_MASK));
550
551         host->wait_int = 0;
552         sh_sdhi_writew(host, SDHI_INFO1_MASK,
553                        ~INFO1M_RESP_END & sh_sdhi_readw(host, SDHI_INFO1_MASK));
554         sh_sdhi_writew(host, SDHI_INFO2_MASK,
555                        ~(INFO2M_CMD_ERROR | INFO2M_CRC_ERROR |
556                        INFO2M_END_ERROR | INFO2M_TIMEOUT |
557                        INFO2M_RESP_TIMEOUT | INFO2M_ILA) &
558                        sh_sdhi_readw(host, SDHI_INFO2_MASK));
559
560         time = sh_sdhi_wait_interrupt_flag(host);
561         if (!time)
562                 return sh_sdhi_error_manage(host);
563
564         if (host->sd_error) {
565                 switch (cmd->cmdidx) {
566                 case MMC_CMD_ALL_SEND_CID:
567                 case MMC_CMD_SELECT_CARD:
568                 case SD_CMD_SEND_IF_COND:
569                 case MMC_CMD_APP_CMD:
570                         ret = -ETIMEDOUT;
571                         break;
572                 default:
573                         debug(DRIVER_NAME": Cmd(d'%d) err\n", opc);
574                         debug(DRIVER_NAME": cmdidx = %d\n", cmd->cmdidx);
575                         ret = sh_sdhi_error_manage(host);
576                         break;
577                 }
578                 host->sd_error = 0;
579                 host->wait_int = 0;
580                 return ret;
581         }
582         if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END)
583                 return -EINVAL;
584
585         if (host->wait_int) {
586                 sh_sdhi_get_response(host, cmd);
587                 host->wait_int = 0;
588         }
589         if (data)
590                 ret = sh_sdhi_data_trans(host, data, opc);
591
592         debug("ret = %d, resp = %08x, %08x, %08x, %08x\n",
593               ret, cmd->response[0], cmd->response[1],
594               cmd->response[2], cmd->response[3]);
595         return ret;
596 }
597
598 static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
599                         struct mmc_data *data)
600 {
601         struct sh_sdhi_host *host = mmc_priv(mmc);
602         int ret;
603
604         host->sd_error = 0;
605
606         ret = sh_sdhi_start_cmd(host, data, cmd);
607
608         return ret;
609 }
610
611 static int sh_sdhi_set_ios(struct mmc *mmc)
612 {
613         int ret;
614         struct sh_sdhi_host *host = mmc_priv(mmc);
615
616         ret = sh_sdhi_clock_control(host, mmc->clock);
617         if (ret)
618                 return -EINVAL;
619
620         if (mmc->bus_width == 4)
621                 sh_sdhi_writew(host, SDHI_OPTION, ~OPT_BUS_WIDTH_1 &
622                                sh_sdhi_readw(host, SDHI_OPTION));
623         else
624                 sh_sdhi_writew(host, SDHI_OPTION, OPT_BUS_WIDTH_1 |
625                                sh_sdhi_readw(host, SDHI_OPTION));
626
627         debug("clock = %d, buswidth = %d\n", mmc->clock, mmc->bus_width);
628
629         return 0;
630 }
631
632 static int sh_sdhi_initialize(struct mmc *mmc)
633 {
634         struct sh_sdhi_host *host = mmc_priv(mmc);
635         int ret = sh_sdhi_sync_reset(host);
636
637         sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
638
639 #if defined(__BIG_ENDIAN_BITFIELD)
640         sh_sdhi_writew(host, SDHI_EXT_SWAP, SET_SWAP);
641 #endif
642
643         sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
644                        INFO1M_ACCESS_END | INFO1M_CARD_RE |
645                        INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
646
647         return ret;
648 }
649
650 static const struct mmc_ops sh_sdhi_ops = {
651         .send_cmd       = sh_sdhi_send_cmd,
652         .set_ios        = sh_sdhi_set_ios,
653         .init           = sh_sdhi_initialize,
654 };
655
656 static struct mmc_config sh_sdhi_cfg = {
657         .name           = DRIVER_NAME,
658         .ops            = &sh_sdhi_ops,
659         .f_min          = CLKDEV_INIT,
660         .f_max          = CLKDEV_HS_DATA,
661         .voltages       = MMC_VDD_32_33 | MMC_VDD_33_34,
662         .host_caps      = MMC_MODE_4BIT | MMC_MODE_HS,
663         .part_type      = PART_TYPE_DOS,
664         .b_max          = CONFIG_SYS_MMC_MAX_BLK_COUNT,
665 };
666
667 int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
668 {
669         int ret = 0;
670         struct mmc *mmc;
671         struct sh_sdhi_host *host = NULL;
672
673         if (ch >= CONFIG_SYS_SH_SDHI_NR_CHANNEL)
674                 return -ENODEV;
675
676         host = malloc(sizeof(struct sh_sdhi_host));
677         if (!host)
678                 return -ENOMEM;
679
680         mmc = mmc_create(&sh_sdhi_cfg, host);
681         if (!mmc) {
682                 ret = -1;
683                 goto error;
684         }
685
686         host->ch = ch;
687         host->addr = addr;
688         host->quirks = quirks;
689
690         if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
691                 host->bus_shift = 1;
692
693         return ret;
694 error:
695         if (host)
696                 free(host);
697         return ret;
698 }