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 <asm/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 unsigned long *p1, *p2; 403 404 if (cmd->resp_type & MMC_RSP_136) { 405 cnt = 4; 406 resp[0] = sh_sdhi_readw(host, SDHI_RSP00); 407 resp[1] = sh_sdhi_readw(host, SDHI_RSP01); 408 resp[2] = sh_sdhi_readw(host, SDHI_RSP02); 409 resp[3] = sh_sdhi_readw(host, SDHI_RSP03); 410 resp[4] = sh_sdhi_readw(host, SDHI_RSP04); 411 resp[5] = sh_sdhi_readw(host, SDHI_RSP05); 412 resp[6] = sh_sdhi_readw(host, SDHI_RSP06); 413 resp[7] = sh_sdhi_readw(host, SDHI_RSP07); 414 415 /* SDHI REGISTER SPECIFICATION */ 416 for (i = 7, j = 6; i > 0; i--) { 417 resp[i] = (resp[i] << 8) & 0xff00; 418 resp[i] |= (resp[j--] >> 8) & 0x00ff; 419 } 420 resp[0] = (resp[0] << 8) & 0xff00; 421 422 /* SDHI REGISTER SPECIFICATION */ 423 p1 = ((unsigned long *)resp) + 3; 424 425 } else { 426 resp[0] = sh_sdhi_readw(host, SDHI_RSP00); 427 resp[1] = sh_sdhi_readw(host, SDHI_RSP01); 428 429 p1 = ((unsigned long *)resp); 430 } 431 432 p2 = (unsigned long *)cmd->response; 433 #if defined(__BIG_ENDIAN_BITFIELD) 434 for (i = 0; i < cnt; i++) { 435 *p2++ = ((*p1 >> 16) & 0x0000ffff) | 436 ((*p1 << 16) & 0xffff0000); 437 p1--; 438 } 439 #else 440 for (i = 0; i < cnt; i++) 441 *p2++ = *p1--; 442 #endif /* __BIG_ENDIAN_BITFIELD */ 443 } 444 445 static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host, 446 struct mmc_data *data, unsigned short opc) 447 { 448 switch (opc) { 449 case SD_CMD_APP_SEND_OP_COND: 450 case SD_CMD_APP_SEND_SCR: 451 opc |= SDHI_APP; 452 break; 453 case SD_CMD_APP_SET_BUS_WIDTH: 454 /* SD_APP_SET_BUS_WIDTH*/ 455 if (!data) 456 opc |= SDHI_APP; 457 else /* SD_SWITCH */ 458 opc = SDHI_SD_SWITCH; 459 break; 460 default: 461 break; 462 } 463 return opc; 464 } 465 466 static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host, 467 struct mmc_data *data, unsigned short opc) 468 { 469 unsigned short ret; 470 471 switch (opc) { 472 case MMC_CMD_READ_MULTIPLE_BLOCK: 473 ret = sh_sdhi_multi_read(host, data); 474 break; 475 case MMC_CMD_WRITE_MULTIPLE_BLOCK: 476 ret = sh_sdhi_multi_write(host, data); 477 break; 478 case MMC_CMD_WRITE_SINGLE_BLOCK: 479 ret = sh_sdhi_single_write(host, data); 480 break; 481 case MMC_CMD_READ_SINGLE_BLOCK: 482 case SDHI_SD_APP_SEND_SCR: 483 case SDHI_SD_SWITCH: /* SD_SWITCH */ 484 ret = sh_sdhi_single_read(host, data); 485 break; 486 default: 487 printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc); 488 ret = -EINVAL; 489 break; 490 } 491 return ret; 492 } 493 494 static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, 495 struct mmc_data *data, struct mmc_cmd *cmd) 496 { 497 long time; 498 unsigned short opc = cmd->cmdidx; 499 int ret = 0; 500 unsigned long timeout; 501 502 debug("opc = %d, arg = %x, resp_type = %x\n", 503 opc, cmd->cmdarg, cmd->resp_type); 504 505 if (opc == MMC_CMD_STOP_TRANSMISSION) { 506 /* SDHI sends the STOP command automatically by STOP reg */ 507 sh_sdhi_writew(host, SDHI_INFO1_MASK, ~INFO1M_ACCESS_END & 508 sh_sdhi_readw(host, SDHI_INFO1_MASK)); 509 510 time = sh_sdhi_wait_interrupt_flag(host); 511 if (time == 0 || host->sd_error != 0) 512 return sh_sdhi_error_manage(host); 513 514 sh_sdhi_get_response(host, cmd); 515 return 0; 516 } 517 518 if (data) { 519 if ((opc == MMC_CMD_READ_MULTIPLE_BLOCK) || 520 opc == MMC_CMD_WRITE_MULTIPLE_BLOCK) { 521 sh_sdhi_writew(host, SDHI_STOP, STOP_SEC_ENABLE); 522 sh_sdhi_writew(host, SDHI_SECCNT, data->blocks); 523 } 524 sh_sdhi_writew(host, SDHI_SIZE, data->blocksize); 525 } 526 opc = sh_sdhi_set_cmd(host, data, opc); 527 528 /* 529 * U-Boot cannot use interrupt. 530 * So this flag may not be clear by timing 531 */ 532 sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END); 533 534 sh_sdhi_writew(host, SDHI_INFO1_MASK, 535 INFO1M_RESP_END | sh_sdhi_readw(host, SDHI_INFO1_MASK)); 536 sh_sdhi_writew(host, SDHI_ARG0, 537 (unsigned short)(cmd->cmdarg & ARG0_MASK)); 538 sh_sdhi_writew(host, SDHI_ARG1, 539 (unsigned short)((cmd->cmdarg >> 16) & ARG1_MASK)); 540 541 timeout = 100000; 542 /* Waiting for SD Bus busy to be cleared */ 543 while (timeout--) { 544 if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000)) 545 break; 546 } 547 548 sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(opc & CMD_MASK)); 549 550 host->wait_int = 0; 551 sh_sdhi_writew(host, SDHI_INFO1_MASK, 552 ~INFO1M_RESP_END & sh_sdhi_readw(host, SDHI_INFO1_MASK)); 553 sh_sdhi_writew(host, SDHI_INFO2_MASK, 554 ~(INFO2M_CMD_ERROR | INFO2M_CRC_ERROR | 555 INFO2M_END_ERROR | INFO2M_TIMEOUT | 556 INFO2M_RESP_TIMEOUT | INFO2M_ILA) & 557 sh_sdhi_readw(host, SDHI_INFO2_MASK)); 558 559 time = sh_sdhi_wait_interrupt_flag(host); 560 if (!time) 561 return sh_sdhi_error_manage(host); 562 563 if (host->sd_error) { 564 switch (cmd->cmdidx) { 565 case MMC_CMD_ALL_SEND_CID: 566 case MMC_CMD_SELECT_CARD: 567 case SD_CMD_SEND_IF_COND: 568 case MMC_CMD_APP_CMD: 569 ret = -ETIMEDOUT; 570 break; 571 default: 572 debug(DRIVER_NAME": Cmd(d'%d) err\n", opc); 573 debug(DRIVER_NAME": cmdidx = %d\n", cmd->cmdidx); 574 ret = sh_sdhi_error_manage(host); 575 break; 576 } 577 host->sd_error = 0; 578 host->wait_int = 0; 579 return ret; 580 } 581 if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) 582 return -EINVAL; 583 584 if (host->wait_int) { 585 sh_sdhi_get_response(host, cmd); 586 host->wait_int = 0; 587 } 588 if (data) 589 ret = sh_sdhi_data_trans(host, data, opc); 590 591 debug("ret = %d, resp = %08x, %08x, %08x, %08x\n", 592 ret, cmd->response[0], cmd->response[1], 593 cmd->response[2], cmd->response[3]); 594 return ret; 595 } 596 597 static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, 598 struct mmc_data *data) 599 { 600 struct sh_sdhi_host *host = mmc_priv(mmc); 601 int ret; 602 603 host->sd_error = 0; 604 605 ret = sh_sdhi_start_cmd(host, data, cmd); 606 607 return ret; 608 } 609 610 static void sh_sdhi_set_ios(struct mmc *mmc) 611 { 612 int ret; 613 struct sh_sdhi_host *host = mmc_priv(mmc); 614 615 ret = sh_sdhi_clock_control(host, mmc->clock); 616 if (ret) 617 return; 618 619 if (mmc->bus_width == 4) 620 sh_sdhi_writew(host, SDHI_OPTION, ~OPT_BUS_WIDTH_1 & 621 sh_sdhi_readw(host, SDHI_OPTION)); 622 else 623 sh_sdhi_writew(host, SDHI_OPTION, OPT_BUS_WIDTH_1 | 624 sh_sdhi_readw(host, SDHI_OPTION)); 625 626 debug("clock = %d, buswidth = %d\n", mmc->clock, mmc->bus_width); 627 } 628 629 static int sh_sdhi_initialize(struct mmc *mmc) 630 { 631 struct sh_sdhi_host *host = mmc_priv(mmc); 632 int ret = sh_sdhi_sync_reset(host); 633 634 sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT); 635 636 #if defined(__BIG_ENDIAN_BITFIELD) 637 sh_sdhi_writew(host, SDHI_EXT_SWAP, SET_SWAP); 638 #endif 639 640 sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END | 641 INFO1M_ACCESS_END | INFO1M_CARD_RE | 642 INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN); 643 644 return ret; 645 } 646 647 static const struct mmc_ops sh_sdhi_ops = { 648 .send_cmd = sh_sdhi_send_cmd, 649 .set_ios = sh_sdhi_set_ios, 650 .init = sh_sdhi_initialize, 651 }; 652 653 static struct mmc_config sh_sdhi_cfg = { 654 .name = DRIVER_NAME, 655 .ops = &sh_sdhi_ops, 656 .f_min = CLKDEV_INIT, 657 .f_max = CLKDEV_HS_DATA, 658 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, 659 .host_caps = MMC_MODE_4BIT | MMC_MODE_HS, 660 .part_type = PART_TYPE_DOS, 661 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, 662 }; 663 664 int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks) 665 { 666 int ret = 0; 667 struct mmc *mmc; 668 struct sh_sdhi_host *host = NULL; 669 670 if (ch >= CONFIG_SYS_SH_SDHI_NR_CHANNEL) 671 return -ENODEV; 672 673 host = malloc(sizeof(struct sh_sdhi_host)); 674 if (!host) 675 return -ENOMEM; 676 677 mmc = mmc_create(&sh_sdhi_cfg, host); 678 if (!mmc) { 679 ret = -1; 680 goto error; 681 } 682 683 host->ch = ch; 684 host->addr = addr; 685 host->quirks = quirks; 686 687 if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF) 688 host->bus_shift = 1; 689 690 return ret; 691 error: 692 if (host) 693 free(host); 694 return ret; 695 } 696