uboot/drivers/mmc/sh_sdhi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * drivers/mmc/sh_sdhi.c
   4 *
   5 * SD/MMC driver for Renesas rmobile ARM SoCs.
   6 *
   7 * Copyright (C) 2011,2013-2017 Renesas Electronics Corporation
   8 * Copyright (C) 2014 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
   9 * Copyright (C) 2008-2009 Renesas Solutions Corp.
  10 */
  11
  12#include <common.h>
  13#include <log.h>
  14#include <malloc.h>
  15#include <mmc.h>
  16#include <dm.h>
  17#include <part.h>
  18#include <dm/device_compat.h>
  19#include <linux/bitops.h>
  20#include <linux/delay.h>
  21#include <linux/errno.h>
  22#include <linux/compat.h>
  23#include <linux/io.h>
  24#include <linux/sizes.h>
  25#include <asm/arch/rmobile.h>
  26#include <asm/arch/sh_sdhi.h>
  27#include <asm/global_data.h>
  28#include <clk.h>
  29
  30#define DRIVER_NAME "sh-sdhi"
  31
  32struct sh_sdhi_host {
  33        void __iomem *addr;
  34        int ch;
  35        int bus_shift;
  36        unsigned long quirks;
  37        unsigned char wait_int;
  38        unsigned char sd_error;
  39        unsigned char detect_waiting;
  40        unsigned char app_cmd;
  41};
  42
  43static inline void sh_sdhi_writeq(struct sh_sdhi_host *host, int reg, u64 val)
  44{
  45        writeq(val, host->addr + (reg << host->bus_shift));
  46}
  47
  48static inline u64 sh_sdhi_readq(struct sh_sdhi_host *host, int reg)
  49{
  50        return readq(host->addr + (reg << host->bus_shift));
  51}
  52
  53static inline void sh_sdhi_writew(struct sh_sdhi_host *host, int reg, u16 val)
  54{
  55        writew(val, host->addr + (reg << host->bus_shift));
  56}
  57
  58static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg)
  59{
  60        return readw(host->addr + (reg << host->bus_shift));
  61}
  62
  63static void sh_sdhi_detect(struct sh_sdhi_host *host)
  64{
  65        sh_sdhi_writew(host, SDHI_OPTION,
  66                       OPT_BUS_WIDTH_1 | sh_sdhi_readw(host, SDHI_OPTION));
  67
  68        host->detect_waiting = 0;
  69}
  70
  71static int sh_sdhi_intr(void *dev_id)
  72{
  73        struct sh_sdhi_host *host = dev_id;
  74        int state1 = 0, state2 = 0;
  75
  76        state1 = sh_sdhi_readw(host, SDHI_INFO1);
  77        state2 = sh_sdhi_readw(host, SDHI_INFO2);
  78
  79        debug("%s: state1 = %x, state2 = %x\n", __func__, state1, state2);
  80
  81        /* CARD Insert */
  82        if (state1 & INFO1_CARD_IN) {
  83                sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_CARD_IN);
  84                if (!host->detect_waiting) {
  85                        host->detect_waiting = 1;
  86                        sh_sdhi_detect(host);
  87                }
  88                sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
  89                               INFO1M_ACCESS_END | INFO1M_CARD_IN |
  90                               INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
  91                return -EAGAIN;
  92        }
  93        /* CARD Removal */
  94        if (state1 & INFO1_CARD_RE) {
  95                sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_CARD_RE);
  96                if (!host->detect_waiting) {
  97                        host->detect_waiting = 1;
  98                        sh_sdhi_detect(host);
  99                }
 100                sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
 101                               INFO1M_ACCESS_END | INFO1M_CARD_RE |
 102                               INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
 103                sh_sdhi_writew(host, SDHI_SDIO_INFO1_MASK, SDIO_INFO1M_ON);
 104                sh_sdhi_writew(host, SDHI_SDIO_MODE, SDIO_MODE_OFF);
 105                return -EAGAIN;
 106        }
 107
 108        if (state2 & INFO2_ALL_ERR) {
 109                sh_sdhi_writew(host, SDHI_INFO2,
 110                               (unsigned short)~(INFO2_ALL_ERR));
 111                sh_sdhi_writew(host, SDHI_INFO2_MASK,
 112                               INFO2M_ALL_ERR |
 113                               sh_sdhi_readw(host, SDHI_INFO2_MASK));
 114                host->sd_error = 1;
 115                host->wait_int = 1;
 116                return 0;
 117        }
 118        /* Respons End */
 119        if (state1 & INFO1_RESP_END) {
 120                sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
 121                sh_sdhi_writew(host, SDHI_INFO1_MASK,
 122                               INFO1M_RESP_END |
 123                               sh_sdhi_readw(host, SDHI_INFO1_MASK));
 124                host->wait_int = 1;
 125                return 0;
 126        }
 127        /* SD_BUF Read Enable */
 128        if (state2 & INFO2_BRE_ENABLE) {
 129                sh_sdhi_writew(host, SDHI_INFO2, ~INFO2_BRE_ENABLE);
 130                sh_sdhi_writew(host, SDHI_INFO2_MASK,
 131                               INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ |
 132                               sh_sdhi_readw(host, SDHI_INFO2_MASK));
 133                host->wait_int = 1;
 134                return 0;
 135        }
 136        /* SD_BUF Write Enable */
 137        if (state2 & INFO2_BWE_ENABLE) {
 138                sh_sdhi_writew(host, SDHI_INFO2, ~INFO2_BWE_ENABLE);
 139                sh_sdhi_writew(host, SDHI_INFO2_MASK,
 140                               INFO2_BWE_ENABLE | INFO2M_BUF_ILL_WRITE |
 141                               sh_sdhi_readw(host, SDHI_INFO2_MASK));
 142                host->wait_int = 1;
 143                return 0;
 144        }
 145        /* Access End */
 146        if (state1 & INFO1_ACCESS_END) {
 147                sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_ACCESS_END);
 148                sh_sdhi_writew(host, SDHI_INFO1_MASK,
 149                               INFO1_ACCESS_END |
 150                               sh_sdhi_readw(host, SDHI_INFO1_MASK));
 151                host->wait_int = 1;
 152                return 0;
 153        }
 154        return -EAGAIN;
 155}
 156
 157static int sh_sdhi_wait_interrupt_flag(struct sh_sdhi_host *host)
 158{
 159        int timeout = 10000000;
 160
 161        while (1) {
 162                timeout--;
 163                if (timeout < 0) {
 164                        debug(DRIVER_NAME": %s timeout\n", __func__);
 165                        return 0;
 166                }
 167
 168                if (!sh_sdhi_intr(host))
 169                        break;
 170
 171                udelay(1);      /* 1 usec */
 172        }
 173
 174        return 1; /* Return value: NOT 0 = complete waiting */
 175}
 176
 177static int sh_sdhi_clock_control(struct sh_sdhi_host *host, unsigned long clk)
 178{
 179        u32 clkdiv, i, timeout;
 180
 181        if (sh_sdhi_readw(host, SDHI_INFO2) & (1 << 14)) {
 182                printf(DRIVER_NAME": Busy state ! Cannot change the clock\n");
 183                return -EBUSY;
 184        }
 185
 186        sh_sdhi_writew(host, SDHI_CLK_CTRL,
 187                       ~CLK_ENABLE & sh_sdhi_readw(host, SDHI_CLK_CTRL));
 188
 189        if (clk == 0)
 190                return -EIO;
 191
 192        clkdiv = 0x80;
 193        i = CONFIG_SH_SDHI_FREQ >> (0x8 + 1);
 194        for (; clkdiv && clk >= (i << 1); (clkdiv >>= 1))
 195                i <<= 1;
 196
 197        sh_sdhi_writew(host, SDHI_CLK_CTRL, clkdiv);
 198
 199        timeout = 100000;
 200        /* Waiting for SD Bus busy to be cleared */
 201        while (timeout--) {
 202                if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000))
 203                        break;
 204        }
 205
 206        if (timeout)
 207                sh_sdhi_writew(host, SDHI_CLK_CTRL,
 208                               CLK_ENABLE | sh_sdhi_readw(host, SDHI_CLK_CTRL));
 209        else
 210                return -EBUSY;
 211
 212        return 0;
 213}
 214
 215static int sh_sdhi_sync_reset(struct sh_sdhi_host *host)
 216{
 217        u32 timeout;
 218        sh_sdhi_writew(host, SDHI_SOFT_RST, SOFT_RST_ON);
 219        sh_sdhi_writew(host, SDHI_SOFT_RST, SOFT_RST_OFF);
 220        sh_sdhi_writew(host, SDHI_CLK_CTRL,
 221                       CLK_ENABLE | sh_sdhi_readw(host, SDHI_CLK_CTRL));
 222
 223        timeout = 100000;
 224        while (timeout--) {
 225                if (!(sh_sdhi_readw(host, SDHI_INFO2) & INFO2_CBUSY))
 226                        break;
 227                udelay(100);
 228        }
 229
 230        if (!timeout)
 231                return -EBUSY;
 232
 233        if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
 234                sh_sdhi_writew(host, SDHI_HOST_MODE, 1);
 235
 236        return 0;
 237}
 238
 239static int sh_sdhi_error_manage(struct sh_sdhi_host *host)
 240{
 241        unsigned short e_state1, e_state2;
 242        int ret;
 243
 244        host->sd_error = 0;
 245        host->wait_int = 0;
 246
 247        e_state1 = sh_sdhi_readw(host, SDHI_ERR_STS1);
 248        e_state2 = sh_sdhi_readw(host, SDHI_ERR_STS2);
 249        if (e_state2 & ERR_STS2_SYS_ERROR) {
 250                if (e_state2 & ERR_STS2_RES_STOP_TIMEOUT)
 251                        ret = -ETIMEDOUT;
 252                else
 253                        ret = -EILSEQ;
 254                debug("%s: ERR_STS2 = %04x\n",
 255                      DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS2));
 256                sh_sdhi_sync_reset(host);
 257
 258                sh_sdhi_writew(host, SDHI_INFO1_MASK,
 259                               INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
 260                return ret;
 261        }
 262        if (e_state1 & ERR_STS1_CRC_ERROR || e_state1 & ERR_STS1_CMD_ERROR)
 263                ret = -EILSEQ;
 264        else
 265                ret = -ETIMEDOUT;
 266
 267        debug("%s: ERR_STS1 = %04x\n",
 268              DRIVER_NAME, sh_sdhi_readw(host, SDHI_ERR_STS1));
 269        sh_sdhi_sync_reset(host);
 270        sh_sdhi_writew(host, SDHI_INFO1_MASK,
 271                       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
 272        return ret;
 273}
 274
 275static int sh_sdhi_single_read(struct sh_sdhi_host *host, struct mmc_data *data)
 276{
 277        long time;
 278        unsigned short blocksize, i;
 279        unsigned short *p = (unsigned short *)data->dest;
 280        u64 *q = (u64 *)data->dest;
 281
 282        if ((unsigned long)p & 0x00000001) {
 283                debug(DRIVER_NAME": %s: The data pointer is unaligned.",
 284                      __func__);
 285                return -EIO;
 286        }
 287
 288        host->wait_int = 0;
 289        sh_sdhi_writew(host, SDHI_INFO2_MASK,
 290                       ~(INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ) &
 291                       sh_sdhi_readw(host, SDHI_INFO2_MASK));
 292        sh_sdhi_writew(host, SDHI_INFO1_MASK,
 293                       ~INFO1M_ACCESS_END &
 294                       sh_sdhi_readw(host, SDHI_INFO1_MASK));
 295        time = sh_sdhi_wait_interrupt_flag(host);
 296        if (time == 0 || host->sd_error != 0)
 297                return sh_sdhi_error_manage(host);
 298
 299        host->wait_int = 0;
 300        blocksize = sh_sdhi_readw(host, SDHI_SIZE);
 301        if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
 302                for (i = 0; i < blocksize / 8; i++)
 303                        *q++ = sh_sdhi_readq(host, SDHI_BUF0);
 304        else
 305                for (i = 0; i < blocksize / 2; i++)
 306                        *p++ = sh_sdhi_readw(host, SDHI_BUF0);
 307
 308        time = sh_sdhi_wait_interrupt_flag(host);
 309        if (time == 0 || host->sd_error != 0)
 310                return sh_sdhi_error_manage(host);
 311
 312        host->wait_int = 0;
 313        return 0;
 314}
 315
 316static int sh_sdhi_multi_read(struct sh_sdhi_host *host, struct mmc_data *data)
 317{
 318        long time;
 319        unsigned short blocksize, i, sec;
 320        unsigned short *p = (unsigned short *)data->dest;
 321        u64 *q = (u64 *)data->dest;
 322
 323        if ((unsigned long)p & 0x00000001) {
 324                debug(DRIVER_NAME": %s: The data pointer is unaligned.",
 325                      __func__);
 326                return -EIO;
 327        }
 328
 329        debug("%s: blocks = %d, blocksize = %d\n",
 330              __func__, data->blocks, data->blocksize);
 331
 332        host->wait_int = 0;
 333        for (sec = 0; sec < data->blocks; sec++) {
 334                sh_sdhi_writew(host, SDHI_INFO2_MASK,
 335                               ~(INFO2M_BRE_ENABLE | INFO2M_BUF_ILL_READ) &
 336                               sh_sdhi_readw(host, SDHI_INFO2_MASK));
 337
 338                time = sh_sdhi_wait_interrupt_flag(host);
 339                if (time == 0 || host->sd_error != 0)
 340                        return sh_sdhi_error_manage(host);
 341
 342                host->wait_int = 0;
 343                blocksize = sh_sdhi_readw(host, SDHI_SIZE);
 344                if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
 345                        for (i = 0; i < blocksize / 8; i++)
 346                                *q++ = sh_sdhi_readq(host, SDHI_BUF0);
 347                else
 348                        for (i = 0; i < blocksize / 2; i++)
 349                                *p++ = sh_sdhi_readw(host, SDHI_BUF0);
 350        }
 351
 352        return 0;
 353}
 354
 355static int sh_sdhi_single_write(struct sh_sdhi_host *host,
 356                struct mmc_data *data)
 357{
 358        long time;
 359        unsigned short blocksize, i;
 360        const unsigned short *p = (const unsigned short *)data->src;
 361        const u64 *q = (const u64 *)data->src;
 362
 363        if ((unsigned long)p & 0x00000001) {
 364                debug(DRIVER_NAME": %s: The data pointer is unaligned.",
 365                      __func__);
 366                return -EIO;
 367        }
 368
 369        debug("%s: blocks = %d, blocksize = %d\n",
 370              __func__, data->blocks, data->blocksize);
 371
 372        host->wait_int = 0;
 373        sh_sdhi_writew(host, SDHI_INFO2_MASK,
 374                       ~(INFO2M_BWE_ENABLE | INFO2M_BUF_ILL_WRITE) &
 375                       sh_sdhi_readw(host, SDHI_INFO2_MASK));
 376        sh_sdhi_writew(host, SDHI_INFO1_MASK,
 377                       ~INFO1M_ACCESS_END &
 378                       sh_sdhi_readw(host, SDHI_INFO1_MASK));
 379
 380        time = sh_sdhi_wait_interrupt_flag(host);
 381        if (time == 0 || host->sd_error != 0)
 382                return sh_sdhi_error_manage(host);
 383
 384        host->wait_int = 0;
 385        blocksize = sh_sdhi_readw(host, SDHI_SIZE);
 386        if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
 387                for (i = 0; i < blocksize / 8; i++)
 388                        sh_sdhi_writeq(host, SDHI_BUF0, *q++);
 389        else
 390                for (i = 0; i < blocksize / 2; i++)
 391                        sh_sdhi_writew(host, SDHI_BUF0, *p++);
 392
 393        time = sh_sdhi_wait_interrupt_flag(host);
 394        if (time == 0 || host->sd_error != 0)
 395                return sh_sdhi_error_manage(host);
 396
 397        host->wait_int = 0;
 398        return 0;
 399}
 400
 401static int sh_sdhi_multi_write(struct sh_sdhi_host *host, struct mmc_data *data)
 402{
 403        long time;
 404        unsigned short i, sec, blocksize;
 405        const unsigned short *p = (const unsigned short *)data->src;
 406        const u64 *q = (const u64 *)data->src;
 407
 408        debug("%s: blocks = %d, blocksize = %d\n",
 409              __func__, data->blocks, data->blocksize);
 410
 411        host->wait_int = 0;
 412        for (sec = 0; sec < data->blocks; sec++) {
 413                sh_sdhi_writew(host, SDHI_INFO2_MASK,
 414                               ~(INFO2M_BWE_ENABLE | INFO2M_BUF_ILL_WRITE) &
 415                               sh_sdhi_readw(host, SDHI_INFO2_MASK));
 416
 417                time = sh_sdhi_wait_interrupt_flag(host);
 418                if (time == 0 || host->sd_error != 0)
 419                        return sh_sdhi_error_manage(host);
 420
 421                host->wait_int = 0;
 422                blocksize = sh_sdhi_readw(host, SDHI_SIZE);
 423                if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
 424                        for (i = 0; i < blocksize / 8; i++)
 425                                sh_sdhi_writeq(host, SDHI_BUF0, *q++);
 426                else
 427                        for (i = 0; i < blocksize / 2; i++)
 428                                sh_sdhi_writew(host, SDHI_BUF0, *p++);
 429        }
 430
 431        return 0;
 432}
 433
 434static void sh_sdhi_get_response(struct sh_sdhi_host *host, struct mmc_cmd *cmd)
 435{
 436        unsigned short i, j, cnt = 1;
 437        unsigned short resp[8];
 438
 439        if (cmd->resp_type & MMC_RSP_136) {
 440                cnt = 4;
 441                resp[0] = sh_sdhi_readw(host, SDHI_RSP00);
 442                resp[1] = sh_sdhi_readw(host, SDHI_RSP01);
 443                resp[2] = sh_sdhi_readw(host, SDHI_RSP02);
 444                resp[3] = sh_sdhi_readw(host, SDHI_RSP03);
 445                resp[4] = sh_sdhi_readw(host, SDHI_RSP04);
 446                resp[5] = sh_sdhi_readw(host, SDHI_RSP05);
 447                resp[6] = sh_sdhi_readw(host, SDHI_RSP06);
 448                resp[7] = sh_sdhi_readw(host, SDHI_RSP07);
 449
 450                /* SDHI REGISTER SPECIFICATION */
 451                for (i = 7, j = 6; i > 0; i--) {
 452                        resp[i] = (resp[i] << 8) & 0xff00;
 453                        resp[i] |= (resp[j--] >> 8) & 0x00ff;
 454                }
 455                resp[0] = (resp[0] << 8) & 0xff00;
 456        } else {
 457                resp[0] = sh_sdhi_readw(host, SDHI_RSP00);
 458                resp[1] = sh_sdhi_readw(host, SDHI_RSP01);
 459        }
 460
 461#if defined(__BIG_ENDIAN_BITFIELD)
 462        if (cnt == 4) {
 463                cmd->response[0] = (resp[6] << 16) | resp[7];
 464                cmd->response[1] = (resp[4] << 16) | resp[5];
 465                cmd->response[2] = (resp[2] << 16) | resp[3];
 466                cmd->response[3] = (resp[0] << 16) | resp[1];
 467        } else {
 468                cmd->response[0] = (resp[0] << 16) | resp[1];
 469        }
 470#else
 471        if (cnt == 4) {
 472                cmd->response[0] = (resp[7] << 16) | resp[6];
 473                cmd->response[1] = (resp[5] << 16) | resp[4];
 474                cmd->response[2] = (resp[3] << 16) | resp[2];
 475                cmd->response[3] = (resp[1] << 16) | resp[0];
 476        } else {
 477                cmd->response[0] = (resp[1] << 16) | resp[0];
 478        }
 479#endif /* __BIG_ENDIAN_BITFIELD */
 480}
 481
 482static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host,
 483                        struct mmc_data *data, unsigned short opc)
 484{
 485        if (host->app_cmd) {
 486                if (!data)
 487                        host->app_cmd = 0;
 488                return opc | BIT(6);
 489        }
 490
 491        switch (opc) {
 492        case MMC_CMD_SWITCH:
 493                return opc | (data ? 0x1c00 : 0x40);
 494        case MMC_CMD_SEND_EXT_CSD:
 495                return opc | (data ? 0x1c00 : 0);
 496        case MMC_CMD_SEND_OP_COND:
 497                return opc | 0x0700;
 498        case MMC_CMD_APP_CMD:
 499                host->app_cmd = 1;
 500        default:
 501                return opc;
 502        }
 503}
 504
 505static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host,
 506                        struct mmc_data *data, unsigned short opc)
 507{
 508        if (host->app_cmd) {
 509                host->app_cmd = 0;
 510                switch (opc) {
 511                case SD_CMD_APP_SEND_SCR:
 512                case SD_CMD_APP_SD_STATUS:
 513                        return sh_sdhi_single_read(host, data);
 514                default:
 515                        printf(DRIVER_NAME": SD: NOT SUPPORT APP CMD = d'%04d\n",
 516                                opc);
 517                        return -EINVAL;
 518                }
 519        } else {
 520                switch (opc) {
 521                case MMC_CMD_WRITE_MULTIPLE_BLOCK:
 522                        return sh_sdhi_multi_write(host, data);
 523                case MMC_CMD_READ_MULTIPLE_BLOCK:
 524                        return sh_sdhi_multi_read(host, data);
 525                case MMC_CMD_WRITE_SINGLE_BLOCK:
 526                        return sh_sdhi_single_write(host, data);
 527                case MMC_CMD_READ_SINGLE_BLOCK:
 528                case MMC_CMD_SWITCH:
 529                case MMC_CMD_SEND_EXT_CSD:;
 530                        return sh_sdhi_single_read(host, data);
 531                default:
 532                        printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc);
 533                        return -EINVAL;
 534                }
 535        }
 536}
 537
 538static int sh_sdhi_start_cmd(struct sh_sdhi_host *host,
 539                        struct mmc_data *data, struct mmc_cmd *cmd)
 540{
 541        long time;
 542        unsigned short shcmd, opc = cmd->cmdidx;
 543        int ret = 0;
 544        unsigned long timeout;
 545
 546        debug("opc = %d, arg = %x, resp_type = %x\n",
 547              opc, cmd->cmdarg, cmd->resp_type);
 548
 549        if (opc == MMC_CMD_STOP_TRANSMISSION) {
 550                /* SDHI sends the STOP command automatically by STOP reg */
 551                sh_sdhi_writew(host, SDHI_INFO1_MASK, ~INFO1M_ACCESS_END &
 552                               sh_sdhi_readw(host, SDHI_INFO1_MASK));
 553
 554                time = sh_sdhi_wait_interrupt_flag(host);
 555                if (time == 0 || host->sd_error != 0)
 556                        return sh_sdhi_error_manage(host);
 557
 558                sh_sdhi_get_response(host, cmd);
 559                return 0;
 560        }
 561
 562        if (data) {
 563                if ((opc == MMC_CMD_READ_MULTIPLE_BLOCK) ||
 564                    opc == MMC_CMD_WRITE_MULTIPLE_BLOCK) {
 565                        sh_sdhi_writew(host, SDHI_STOP, STOP_SEC_ENABLE);
 566                        sh_sdhi_writew(host, SDHI_SECCNT, data->blocks);
 567                }
 568                sh_sdhi_writew(host, SDHI_SIZE, data->blocksize);
 569        }
 570
 571        shcmd = sh_sdhi_set_cmd(host, data, opc);
 572
 573        /*
 574         *  U-Boot cannot use interrupt.
 575         *  So this flag may not be clear by timing
 576         */
 577        sh_sdhi_writew(host, SDHI_INFO1, ~INFO1_RESP_END);
 578
 579        sh_sdhi_writew(host, SDHI_INFO1_MASK,
 580                       INFO1M_RESP_END | sh_sdhi_readw(host, SDHI_INFO1_MASK));
 581        sh_sdhi_writew(host, SDHI_ARG0,
 582                       (unsigned short)(cmd->cmdarg & ARG0_MASK));
 583        sh_sdhi_writew(host, SDHI_ARG1,
 584                       (unsigned short)((cmd->cmdarg >> 16) & ARG1_MASK));
 585
 586        timeout = 100000;
 587        /* Waiting for SD Bus busy to be cleared */
 588        while (timeout--) {
 589                if ((sh_sdhi_readw(host, SDHI_INFO2) & 0x2000))
 590                        break;
 591        }
 592
 593        host->wait_int = 0;
 594        sh_sdhi_writew(host, SDHI_INFO1_MASK,
 595                       ~INFO1M_RESP_END & sh_sdhi_readw(host, SDHI_INFO1_MASK));
 596        sh_sdhi_writew(host, SDHI_INFO2_MASK,
 597                       ~(INFO2M_CMD_ERROR | INFO2M_CRC_ERROR |
 598                       INFO2M_END_ERROR | INFO2M_TIMEOUT |
 599                       INFO2M_RESP_TIMEOUT | INFO2M_ILA) &
 600                       sh_sdhi_readw(host, SDHI_INFO2_MASK));
 601
 602        sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(shcmd & CMD_MASK));
 603        time = sh_sdhi_wait_interrupt_flag(host);
 604        if (!time) {
 605                host->app_cmd = 0;
 606                return sh_sdhi_error_manage(host);
 607        }
 608
 609        if (host->sd_error) {
 610                switch (cmd->cmdidx) {
 611                case MMC_CMD_ALL_SEND_CID:
 612                case MMC_CMD_SELECT_CARD:
 613                case SD_CMD_SEND_IF_COND:
 614                case MMC_CMD_APP_CMD:
 615                        ret = -ETIMEDOUT;
 616                        break;
 617                default:
 618                        debug(DRIVER_NAME": Cmd(d'%d) err\n", opc);
 619                        debug(DRIVER_NAME": cmdidx = %d\n", cmd->cmdidx);
 620                        ret = sh_sdhi_error_manage(host);
 621                        break;
 622                }
 623                host->sd_error = 0;
 624                host->wait_int = 0;
 625                host->app_cmd = 0;
 626                return ret;
 627        }
 628
 629        if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) {
 630                host->app_cmd = 0;
 631                return -EINVAL;
 632        }
 633
 634        if (host->wait_int) {
 635                sh_sdhi_get_response(host, cmd);
 636                host->wait_int = 0;
 637        }
 638
 639        if (data)
 640                ret = sh_sdhi_data_trans(host, data, opc);
 641
 642        debug("ret = %d, resp = %08x, %08x, %08x, %08x\n",
 643              ret, cmd->response[0], cmd->response[1],
 644              cmd->response[2], cmd->response[3]);
 645        return ret;
 646}
 647
 648static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host,
 649                                   struct mmc_cmd *cmd, struct mmc_data *data)
 650{
 651        host->sd_error = 0;
 652
 653        return sh_sdhi_start_cmd(host, data, cmd);
 654}
 655
 656static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc)
 657{
 658        int ret;
 659
 660        ret = sh_sdhi_clock_control(host, mmc->clock);
 661        if (ret)
 662                return -EINVAL;
 663
 664        if (mmc->bus_width == 8)
 665                sh_sdhi_writew(host, SDHI_OPTION,
 666                               OPT_BUS_WIDTH_8 | (~OPT_BUS_WIDTH_M &
 667                               sh_sdhi_readw(host, SDHI_OPTION)));
 668        else if (mmc->bus_width == 4)
 669                sh_sdhi_writew(host, SDHI_OPTION,
 670                               OPT_BUS_WIDTH_4 | (~OPT_BUS_WIDTH_M &
 671                               sh_sdhi_readw(host, SDHI_OPTION)));
 672        else
 673                sh_sdhi_writew(host, SDHI_OPTION,
 674                               OPT_BUS_WIDTH_1 | (~OPT_BUS_WIDTH_M &
 675                               sh_sdhi_readw(host, SDHI_OPTION)));
 676
 677        debug("clock = %d, buswidth = %d\n", mmc->clock, mmc->bus_width);
 678
 679        return 0;
 680}
 681
 682static int sh_sdhi_initialize_common(struct sh_sdhi_host *host)
 683{
 684        int ret = sh_sdhi_sync_reset(host);
 685
 686        sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT);
 687
 688#if defined(__BIG_ENDIAN_BITFIELD)
 689        sh_sdhi_writew(host, SDHI_EXT_SWAP, SET_SWAP);
 690#endif
 691
 692        sh_sdhi_writew(host, SDHI_INFO1_MASK, INFO1M_RESP_END |
 693                       INFO1M_ACCESS_END | INFO1M_CARD_RE |
 694                       INFO1M_DATA3_CARD_RE | INFO1M_DATA3_CARD_IN);
 695
 696        return ret;
 697}
 698
 699#ifndef CONFIG_DM_MMC
 700static void *mmc_priv(struct mmc *mmc)
 701{
 702        return (void *)mmc->priv;
 703}
 704
 705static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 706                            struct mmc_data *data)
 707{
 708        struct sh_sdhi_host *host = mmc_priv(mmc);
 709
 710        return sh_sdhi_send_cmd_common(host, cmd, data);
 711}
 712
 713static int sh_sdhi_set_ios(struct mmc *mmc)
 714{
 715        struct sh_sdhi_host *host = mmc_priv(mmc);
 716
 717        return sh_sdhi_set_ios_common(host, mmc);
 718}
 719
 720static int sh_sdhi_initialize(struct mmc *mmc)
 721{
 722        struct sh_sdhi_host *host = mmc_priv(mmc);
 723
 724        return sh_sdhi_initialize_common(host);
 725}
 726
 727static const struct mmc_ops sh_sdhi_ops = {
 728        .send_cmd       = sh_sdhi_send_cmd,
 729        .set_ios        = sh_sdhi_set_ios,
 730        .init           = sh_sdhi_initialize,
 731};
 732
 733#ifdef CONFIG_RCAR_GEN3
 734static struct mmc_config sh_sdhi_cfg = {
 735        .name           = DRIVER_NAME,
 736        .ops            = &sh_sdhi_ops,
 737        .f_min          = CLKDEV_INIT,
 738        .f_max          = CLKDEV_HS_DATA,
 739        .voltages       = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
 740        .host_caps      = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HS |
 741                          MMC_MODE_HS_52MHz,
 742        .part_type      = PART_TYPE_DOS,
 743        .b_max          = CONFIG_SYS_MMC_MAX_BLK_COUNT,
 744};
 745#else
 746static struct mmc_config sh_sdhi_cfg = {
 747        .name           = DRIVER_NAME,
 748        .ops            = &sh_sdhi_ops,
 749        .f_min          = CLKDEV_INIT,
 750        .f_max          = CLKDEV_HS_DATA,
 751        .voltages       = MMC_VDD_32_33 | MMC_VDD_33_34,
 752        .host_caps      = MMC_MODE_4BIT | MMC_MODE_HS,
 753        .part_type      = PART_TYPE_DOS,
 754        .b_max          = CONFIG_SYS_MMC_MAX_BLK_COUNT,
 755};
 756#endif
 757
 758int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks)
 759{
 760        int ret = 0;
 761        struct mmc *mmc;
 762        struct sh_sdhi_host *host = NULL;
 763
 764        if (ch >= CONFIG_SYS_SH_SDHI_NR_CHANNEL)
 765                return -ENODEV;
 766
 767        host = malloc(sizeof(struct sh_sdhi_host));
 768        if (!host)
 769                return -ENOMEM;
 770
 771        mmc = mmc_create(&sh_sdhi_cfg, host);
 772        if (!mmc) {
 773                ret = -1;
 774                goto error;
 775        }
 776
 777        host->ch = ch;
 778        host->addr = (void __iomem *)addr;
 779        host->quirks = quirks;
 780
 781        if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
 782                host->bus_shift = 2;
 783        else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
 784                host->bus_shift = 1;
 785
 786        return ret;
 787error:
 788        free(host);
 789        return ret;
 790}
 791
 792#else
 793
 794struct sh_sdhi_plat {
 795        struct mmc_config cfg;
 796        struct mmc mmc;
 797};
 798
 799int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 800                        struct mmc_data *data)
 801{
 802        struct sh_sdhi_host *host = dev_get_priv(dev);
 803
 804        return sh_sdhi_send_cmd_common(host, cmd, data);
 805}
 806
 807int sh_sdhi_dm_set_ios(struct udevice *dev)
 808{
 809        struct sh_sdhi_host *host = dev_get_priv(dev);
 810        struct mmc *mmc = mmc_get_mmc_dev(dev);
 811
 812        return sh_sdhi_set_ios_common(host, mmc);
 813}
 814
 815static const struct dm_mmc_ops sh_sdhi_dm_ops = {
 816        .send_cmd       = sh_sdhi_dm_send_cmd,
 817        .set_ios        = sh_sdhi_dm_set_ios,
 818};
 819
 820static int sh_sdhi_dm_bind(struct udevice *dev)
 821{
 822        struct sh_sdhi_plat *plat = dev_get_plat(dev);
 823
 824        return mmc_bind(dev, &plat->mmc, &plat->cfg);
 825}
 826
 827static int sh_sdhi_dm_probe(struct udevice *dev)
 828{
 829        struct sh_sdhi_plat *plat = dev_get_plat(dev);
 830        struct sh_sdhi_host *host = dev_get_priv(dev);
 831        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 832        struct clk sh_sdhi_clk;
 833        const u32 quirks = dev_get_driver_data(dev);
 834        fdt_addr_t base;
 835        int ret;
 836
 837        base = dev_read_addr(dev);
 838        if (base == FDT_ADDR_T_NONE)
 839                return -EINVAL;
 840
 841        host->addr = devm_ioremap(dev, base, SZ_2K);
 842        if (!host->addr)
 843                return -ENOMEM;
 844
 845        ret = clk_get_by_index(dev, 0, &sh_sdhi_clk);
 846        if (ret) {
 847                debug("failed to get clock, ret=%d\n", ret);
 848                return ret;
 849        }
 850
 851        ret = clk_enable(&sh_sdhi_clk);
 852        if (ret) {
 853                debug("failed to enable clock, ret=%d\n", ret);
 854                return ret;
 855        }
 856
 857        host->quirks = quirks;
 858
 859        if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF)
 860                host->bus_shift = 2;
 861        else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF)
 862                host->bus_shift = 1;
 863
 864        plat->cfg.name = dev->name;
 865        plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
 866
 867        switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
 868                               1)) {
 869        case 8:
 870                plat->cfg.host_caps |= MMC_MODE_8BIT;
 871                break;
 872        case 4:
 873                plat->cfg.host_caps |= MMC_MODE_4BIT;
 874                break;
 875        case 1:
 876                break;
 877        default:
 878                dev_err(dev, "Invalid \"bus-width\" value\n");
 879                return -EINVAL;
 880        }
 881
 882        sh_sdhi_initialize_common(host);
 883
 884        plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
 885        plat->cfg.f_min = CLKDEV_INIT;
 886        plat->cfg.f_max = CLKDEV_HS_DATA;
 887        plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 888
 889        upriv->mmc = &plat->mmc;
 890
 891        return 0;
 892}
 893
 894static const struct udevice_id sh_sdhi_sd_match[] = {
 895        { .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF },
 896        { .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF },
 897        { /* sentinel */ }
 898};
 899
 900U_BOOT_DRIVER(sh_sdhi_mmc) = {
 901        .name                   = "sh-sdhi-mmc",
 902        .id                     = UCLASS_MMC,
 903        .of_match               = sh_sdhi_sd_match,
 904        .bind                   = sh_sdhi_dm_bind,
 905        .probe                  = sh_sdhi_dm_probe,
 906        .priv_auto      = sizeof(struct sh_sdhi_host),
 907        .plat_auto      = sizeof(struct sh_sdhi_plat),
 908        .ops                    = &sh_sdhi_dm_ops,
 909};
 910#endif
 911