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 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 void 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; 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 630 static int sh_sdhi_initialize(struct mmc *mmc) 631 { 632 struct sh_sdhi_host *host = mmc_priv(mmc); 633 int ret = sh_sdhi_sync_reset(host); 634 635 sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT); 636 637 #if defined(__BIG_ENDIAN_BITFIELD) 638 sh_sdhi_writew(host, SDHI_EXT_SWAP, SET_SWAP); 639 #endif 640 641 sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END | 642 INFO1M_ACCESS_END | INFO1M_CARD_RE | 643 INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN); 644 645 return ret; 646 } 647 648 static const struct mmc_ops sh_sdhi_ops = { 649 .send_cmd = sh_sdhi_send_cmd, 650 .set_ios = sh_sdhi_set_ios, 651 .init = sh_sdhi_initialize, 652 }; 653 654 static struct mmc_config sh_sdhi_cfg = { 655 .name = DRIVER_NAME, 656 .ops = &sh_sdhi_ops, 657 .f_min = CLKDEV_INIT, 658 .f_max = CLKDEV_HS_DATA, 659 .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, 660 .host_caps = MMC_MODE_4BIT | MMC_MODE_HS, 661 .part_type = PART_TYPE_DOS, 662 .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT, 663 }; 664 665 int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks) 666 { 667 int ret = 0; 668 struct mmc *mmc; 669 struct sh_sdhi_host *host = NULL; 670 671 if (ch >= CONFIG_SYS_SH_SDHI_NR_CHANNEL) 672 return -ENODEV; 673 674 host = malloc(sizeof(struct sh_sdhi_host)); 675 if (!host) 676 return -ENOMEM; 677 678 mmc = mmc_create(&sh_sdhi_cfg, host); 679 if (!mmc) { 680 ret = -1; 681 goto error; 682 } 683 684 host->ch = ch; 685 host->addr = addr; 686 host->quirks = quirks; 687 688 if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF) 689 host->bus_shift = 1; 690 691 return ret; 692 error: 693 if (host) 694 free(host); 695 return ret; 696 } 697