uboot/drivers/mmc/mmc_spi.c
<<
>>
Prefs
   1/*
   2 * generic mmc spi driver
   3 *
   4 * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
   5 * Copyright 2019 Bhargav Shah <bhargavshah1988@gmail.com>
   6 *
   7 * Licensed under the GPL-2 or later.
   8 */
   9#include <common.h>
  10#include <errno.h>
  11#include <log.h>
  12#include <malloc.h>
  13#include <part.h>
  14#include <mmc.h>
  15#include <stdlib.h>
  16#include <linux/bitops.h>
  17#include <u-boot/crc.h>
  18#include <linux/crc7.h>
  19#include <asm/byteorder.h>
  20#include <dm.h>
  21#include <spi.h>
  22
  23/* MMC/SD in SPI mode reports R1 status always */
  24#define R1_SPI_IDLE                     BIT(0)
  25#define R1_SPI_ERASE_RESET              BIT(1)
  26#define R1_SPI_ILLEGAL_COMMAND          BIT(2)
  27#define R1_SPI_COM_CRC                  BIT(3)
  28#define R1_SPI_ERASE_SEQ                BIT(4)
  29#define R1_SPI_ADDRESS                  BIT(5)
  30#define R1_SPI_PARAMETER                BIT(6)
  31/* R1 bit 7 is always zero, reuse this bit for error */
  32#define R1_SPI_ERROR                    BIT(7)
  33
  34/* Response tokens used to ack each block written: */
  35#define SPI_MMC_RESPONSE_CODE(x)        ((x) & 0x1f)
  36#define SPI_RESPONSE_ACCEPTED           ((2 << 1)|1)
  37#define SPI_RESPONSE_CRC_ERR            ((5 << 1)|1)
  38#define SPI_RESPONSE_WRITE_ERR          ((6 << 1)|1)
  39
  40/*
  41 * Read and write blocks start with these tokens and end with crc;
  42 * on error, read tokens act like a subset of R2_SPI_* values.
  43 */
  44/* single block write multiblock read */
  45#define SPI_TOKEN_SINGLE                0xfe
  46/* multiblock write */
  47#define SPI_TOKEN_MULTI_WRITE           0xfc
  48/* terminate multiblock write */
  49#define SPI_TOKEN_STOP_TRAN             0xfd
  50
  51/* MMC SPI commands start with a start bit "0" and a transmit bit "1" */
  52#define MMC_SPI_CMD(x) (0x40 | (x))
  53
  54/* bus capability */
  55#define MMC_SPI_VOLTAGE                 (MMC_VDD_32_33 | MMC_VDD_33_34)
  56#define MMC_SPI_MIN_CLOCK               400000  /* 400KHz to meet MMC spec */
  57#define MMC_SPI_MAX_CLOCK               25000000 /* SD/MMC legacy speed */
  58
  59/* timeout value */
  60#define CMD_TIMEOUT                     8
  61#define READ_TIMEOUT                    3000000 /* 1 sec */
  62#define WRITE_TIMEOUT                   3000000 /* 1 sec */
  63#define R1B_TIMEOUT                     3000000 /* 1 sec */
  64
  65struct mmc_spi_plat {
  66        struct mmc_config cfg;
  67        struct mmc mmc;
  68};
  69
  70struct mmc_spi_priv {
  71        struct spi_slave *spi;
  72};
  73
  74/**
  75 * mmc_spi_sendcmd() - send a command to the SD card
  76 *
  77 * @dev:        mmc_spi device
  78 * @cmdidx:     command index
  79 * @cmdarg:     command argument
  80 * @resp_type:  card response type
  81 * @resp:       buffer to store the card response
  82 * @resp_size:  size of the card response
  83 * @resp_match: if true, compare each of received bytes with @resp_match_value
  84 * @resp_match_value:   a value to be compared with each of received bytes
  85 * @r1b:        if true, receive additional bytes for busy signal token
  86 * @return 0 if OK, -ETIMEDOUT if no card response is received, -ve on error
  87 */
  88static int mmc_spi_sendcmd(struct udevice *dev,
  89                           ushort cmdidx, u32 cmdarg, u32 resp_type,
  90                           u8 *resp, u32 resp_size,
  91                           bool resp_match, u8 resp_match_value, bool r1b)
  92{
  93        int i, rpos = 0, ret = 0;
  94        u8 cmdo[7], r;
  95
  96        if (!resp || !resp_size)
  97                return 0;
  98
  99        debug("%s: cmd%d cmdarg=0x%x resp_type=0x%x "
 100              "resp_size=%d resp_match=%d resp_match_value=0x%x\n",
 101              __func__, cmdidx, cmdarg, resp_type,
 102              resp_size, resp_match, resp_match_value);
 103
 104        cmdo[0] = 0xff;
 105        cmdo[1] = MMC_SPI_CMD(cmdidx);
 106        cmdo[2] = cmdarg >> 24;
 107        cmdo[3] = cmdarg >> 16;
 108        cmdo[4] = cmdarg >> 8;
 109        cmdo[5] = cmdarg;
 110        cmdo[6] = (crc7(0, &cmdo[1], 5) << 1) | 0x01;
 111        ret = dm_spi_xfer(dev, sizeof(cmdo) * 8, cmdo, NULL, SPI_XFER_BEGIN);
 112        if (ret)
 113                return ret;
 114
 115        ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
 116        if (ret)
 117                return ret;
 118
 119        debug("%s: cmd%d", __func__, cmdidx);
 120
 121        if (resp_match)
 122                r = ~resp_match_value;
 123        i = CMD_TIMEOUT;
 124        while (i) {
 125                ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
 126                if (ret)
 127                        return ret;
 128                debug(" resp%d=0x%x", rpos, r);
 129                rpos++;
 130                i--;
 131
 132                if (resp_match) {
 133                        if (r == resp_match_value)
 134                                break;
 135                } else {
 136                        if (!(r & 0x80))
 137                                break;
 138                }
 139
 140                if (!i)
 141                        return -ETIMEDOUT;
 142        }
 143
 144        resp[0] = r;
 145        for (i = 1; i < resp_size; i++) {
 146                ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
 147                if (ret)
 148                        return ret;
 149                debug(" resp%d=0x%x", rpos, r);
 150                rpos++;
 151                resp[i] = r;
 152        }
 153
 154        if (r1b == true) {
 155                i = R1B_TIMEOUT;
 156                while (i) {
 157                        ret = dm_spi_xfer(dev, 1 * 8, NULL, &r, 0);
 158                        if (ret)
 159                                return ret;
 160
 161                        debug(" resp%d=0x%x", rpos, r);
 162                        rpos++;
 163                        i--;
 164
 165                        if (r)
 166                                break;
 167                }
 168                if (!i)
 169                        return -ETIMEDOUT;
 170        }
 171
 172        debug("\n");
 173
 174        return 0;
 175}
 176
 177/**
 178 * mmc_spi_readdata() - read data block(s) from the SD card
 179 *
 180 * @dev:        mmc_spi device
 181 * @xbuf:       buffer of the actual data (excluding token and crc) to read
 182 * @bcnt:       number of data blocks to transfer
 183 * @bsize:      size of the actual data (excluding token and crc) in bytes
 184 * @return 0 if OK, -ECOMM if crc error, -ETIMEDOUT on other errors
 185 */
 186static int mmc_spi_readdata(struct udevice *dev,
 187                            void *xbuf, u32 bcnt, u32 bsize)
 188{
 189        u16 crc;
 190        u8 *buf = xbuf, r1;
 191        int i, ret = 0;
 192
 193        while (bcnt--) {
 194                for (i = 0; i < READ_TIMEOUT; i++) {
 195                        ret = dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
 196                        if (ret)
 197                                return ret;
 198                        if (r1 == SPI_TOKEN_SINGLE)
 199                                break;
 200                }
 201                debug("%s: data tok%d 0x%x\n", __func__, i, r1);
 202                if (r1 == SPI_TOKEN_SINGLE) {
 203                        ret = dm_spi_xfer(dev, bsize * 8, NULL, buf, 0);
 204                        if (ret)
 205                                return ret;
 206                        ret = dm_spi_xfer(dev, 2 * 8, NULL, &crc, 0);
 207                        if (ret)
 208                                return ret;
 209#ifdef CONFIG_MMC_SPI_CRC_ON
 210                        u16 crc_ok = be16_to_cpu(crc16_ccitt(0, buf, bsize));
 211                        if (crc_ok != crc) {
 212                                debug("%s: data crc error, expected %04x got %04x\n",
 213                                      __func__, crc_ok, crc);
 214                                r1 = R1_SPI_COM_CRC;
 215                                break;
 216                        }
 217#endif
 218                        r1 = 0;
 219                } else {
 220                        r1 = R1_SPI_ERROR;
 221                        break;
 222                }
 223                buf += bsize;
 224        }
 225
 226        if (r1 & R1_SPI_COM_CRC)
 227                ret = -ECOMM;
 228        else if (r1) /* other errors */
 229                ret = -ETIMEDOUT;
 230
 231        return ret;
 232}
 233
 234/**
 235 * mmc_spi_writedata() - write data block(s) to the SD card
 236 *
 237 * @dev:        mmc_spi device
 238 * @xbuf:       buffer of the actual data (excluding token and crc) to write
 239 * @bcnt:       number of data blocks to transfer
 240 * @bsize:      size of actual data (excluding token and crc) in bytes
 241 * @multi:      indicate a transfer by multiple block write command (CMD25)
 242 * @return 0 if OK, -ECOMM if crc error, -ETIMEDOUT on other errors
 243 */
 244static int mmc_spi_writedata(struct udevice *dev, const void *xbuf,
 245                             u32 bcnt, u32 bsize, int multi)
 246{
 247        const u8 *buf = xbuf;
 248        u8 r1, tok[2];
 249        u16 crc;
 250        int i, ret = 0;
 251
 252        tok[0] = 0xff;
 253        tok[1] = multi ? SPI_TOKEN_MULTI_WRITE : SPI_TOKEN_SINGLE;
 254
 255        while (bcnt--) {
 256#ifdef CONFIG_MMC_SPI_CRC_ON
 257                crc = cpu_to_be16(crc16_ccitt(0, (u8 *)buf, bsize));
 258#endif
 259                dm_spi_xfer(dev, 2 * 8, tok, NULL, 0);
 260                dm_spi_xfer(dev, bsize * 8, buf, NULL, 0);
 261                dm_spi_xfer(dev, 2 * 8, &crc, NULL, 0);
 262                for (i = 0; i < CMD_TIMEOUT; i++) {
 263                        dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
 264                        if ((r1 & 0x10) == 0) /* response token */
 265                                break;
 266                }
 267                debug("%s: data tok%d 0x%x\n", __func__, i, r1);
 268                if (SPI_MMC_RESPONSE_CODE(r1) == SPI_RESPONSE_ACCEPTED) {
 269                        debug("%s: data accepted\n", __func__);
 270                        for (i = 0; i < WRITE_TIMEOUT; i++) { /* wait busy */
 271                                dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
 272                                if (i && r1 == 0xff) {
 273                                        r1 = 0;
 274                                        break;
 275                                }
 276                        }
 277                        if (i == WRITE_TIMEOUT) {
 278                                debug("%s: data write timeout 0x%x\n",
 279                                      __func__, r1);
 280                                r1 = R1_SPI_ERROR;
 281                                break;
 282                        }
 283                } else {
 284                        debug("%s: data error 0x%x\n", __func__, r1);
 285                        r1 = R1_SPI_COM_CRC;
 286                        break;
 287                }
 288                buf += bsize;
 289        }
 290        if (multi && bcnt == -1) { /* stop multi write */
 291                tok[1] = SPI_TOKEN_STOP_TRAN;
 292                dm_spi_xfer(dev, 2 * 8, tok, NULL, 0);
 293                for (i = 0; i < WRITE_TIMEOUT; i++) { /* wait busy */
 294                        dm_spi_xfer(dev, 1 * 8, NULL, &r1, 0);
 295                        if (i && r1 == 0xff) {
 296                                r1 = 0;
 297                                break;
 298                        }
 299                }
 300                if (i == WRITE_TIMEOUT) {
 301                        debug("%s: data write timeout 0x%x\n", __func__, r1);
 302                        r1 = R1_SPI_ERROR;
 303                }
 304        }
 305
 306        if (r1 & R1_SPI_COM_CRC)
 307                ret = -ECOMM;
 308        else if (r1) /* other errors */
 309                ret = -ETIMEDOUT;
 310
 311        return ret;
 312}
 313
 314static int dm_mmc_spi_set_ios(struct udevice *dev)
 315{
 316        return 0;
 317}
 318
 319static int dm_mmc_spi_request(struct udevice *dev, struct mmc_cmd *cmd,
 320                              struct mmc_data *data)
 321{
 322        int i, multi, ret = 0;
 323        u8 *resp = NULL;
 324        u32 resp_size = 0;
 325        bool resp_match = false, r1b = false;
 326        u8 resp8 = 0, resp16[2] = { 0 }, resp40[5] = { 0 }, resp_match_value = 0;
 327
 328        dm_spi_claim_bus(dev);
 329
 330        for (i = 0; i < 4; i++)
 331                cmd->response[i] = 0;
 332
 333        switch (cmd->cmdidx) {
 334        case SD_CMD_APP_SEND_OP_COND:
 335        case MMC_CMD_SEND_OP_COND:
 336                resp = &resp8;
 337                resp_size = sizeof(resp8);
 338                cmd->cmdarg = 0x40000000;
 339                break;
 340        case SD_CMD_SEND_IF_COND:
 341                resp = (u8 *)&resp40[0];
 342                resp_size = sizeof(resp40);
 343                resp_match = true;
 344                resp_match_value = R1_SPI_IDLE;
 345                break;
 346        case MMC_CMD_SPI_READ_OCR:
 347                resp = (u8 *)&resp40[0];
 348                resp_size = sizeof(resp40);
 349                break;
 350        case MMC_CMD_SEND_STATUS:
 351                resp = (u8 *)&resp16[0];
 352                resp_size = sizeof(resp16);
 353                break;
 354        case MMC_CMD_SET_BLOCKLEN:
 355        case MMC_CMD_SPI_CRC_ON_OFF:
 356                resp = &resp8;
 357                resp_size = sizeof(resp8);
 358                resp_match = true;
 359                resp_match_value = 0x0;
 360                break;
 361        case MMC_CMD_STOP_TRANSMISSION:
 362        case MMC_CMD_ERASE:
 363                resp = &resp8;
 364                resp_size = sizeof(resp8);
 365                r1b = true;
 366                break;
 367        case MMC_CMD_SEND_CSD:
 368        case MMC_CMD_SEND_CID:
 369        case MMC_CMD_READ_SINGLE_BLOCK:
 370        case MMC_CMD_READ_MULTIPLE_BLOCK:
 371        case MMC_CMD_WRITE_SINGLE_BLOCK:
 372        case MMC_CMD_WRITE_MULTIPLE_BLOCK:
 373        case MMC_CMD_APP_CMD:
 374        case SD_CMD_ERASE_WR_BLK_START:
 375        case SD_CMD_ERASE_WR_BLK_END:
 376                resp = &resp8;
 377                resp_size = sizeof(resp8);
 378                break;
 379        default:
 380                resp = &resp8;
 381                resp_size = sizeof(resp8);
 382                resp_match = true;
 383                resp_match_value = R1_SPI_IDLE;
 384                break;
 385        };
 386
 387        ret = mmc_spi_sendcmd(dev, cmd->cmdidx, cmd->cmdarg, cmd->resp_type,
 388                              resp, resp_size, resp_match, resp_match_value, r1b);
 389        if (ret)
 390                goto done;
 391
 392        switch (cmd->cmdidx) {
 393        case SD_CMD_APP_SEND_OP_COND:
 394        case MMC_CMD_SEND_OP_COND:
 395                cmd->response[0] = (resp8 & R1_SPI_IDLE) ? 0 : OCR_BUSY;
 396                break;
 397        case SD_CMD_SEND_IF_COND:
 398        case MMC_CMD_SPI_READ_OCR:
 399                cmd->response[0] = resp40[4];
 400                cmd->response[0] |= (uint)resp40[3] << 8;
 401                cmd->response[0] |= (uint)resp40[2] << 16;
 402                cmd->response[0] |= (uint)resp40[1] << 24;
 403                break;
 404        case MMC_CMD_SEND_STATUS:
 405                if (resp16[0] || resp16[1])
 406                        cmd->response[0] = MMC_STATUS_ERROR;
 407                else
 408                        cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
 409                break;
 410        case MMC_CMD_SEND_CID:
 411        case MMC_CMD_SEND_CSD:
 412                ret = mmc_spi_readdata(dev, cmd->response, 1, 16);
 413                if (ret)
 414                        return ret;
 415                for (i = 0; i < 4; i++)
 416                        cmd->response[i] =
 417                                cpu_to_be32(cmd->response[i]);
 418                break;
 419        default:
 420                cmd->response[0] = resp8;
 421                break;
 422        }
 423
 424        debug("%s: cmd%d resp0=0x%x resp1=0x%x resp2=0x%x resp3=0x%x\n",
 425              __func__, cmd->cmdidx, cmd->response[0], cmd->response[1],
 426              cmd->response[2], cmd->response[3]);
 427
 428        if (data) {
 429                debug("%s: data flags=0x%x blocks=%d block_size=%d\n",
 430                      __func__, data->flags, data->blocks, data->blocksize);
 431                multi = (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK);
 432                if (data->flags == MMC_DATA_READ)
 433                        ret = mmc_spi_readdata(dev, data->dest,
 434                                               data->blocks, data->blocksize);
 435                else if  (data->flags == MMC_DATA_WRITE)
 436                        ret = mmc_spi_writedata(dev, data->src,
 437                                                data->blocks, data->blocksize,
 438                                                multi);
 439        }
 440
 441done:
 442        dm_spi_xfer(dev, 0, NULL, NULL, SPI_XFER_END);
 443
 444        dm_spi_release_bus(dev);
 445
 446        return ret;
 447}
 448
 449static int mmc_spi_probe(struct udevice *dev)
 450{
 451        struct mmc_spi_priv *priv = dev_get_priv(dev);
 452        struct mmc_spi_plat *plat = dev_get_plat(dev);
 453        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 454        char *name;
 455
 456        priv->spi = dev_get_parent_priv(dev);
 457        if (!priv->spi->max_hz)
 458                priv->spi->max_hz = MMC_SPI_MAX_CLOCK;
 459        priv->spi->mode = SPI_MODE_0;
 460        priv->spi->wordlen = 8;
 461
 462        name = malloc(strlen(dev->parent->name) + strlen(dev->name) + 4);
 463        if (!name)
 464                return -ENOMEM;
 465        sprintf(name, "%s:%s", dev->parent->name, dev->name);
 466
 467        plat->cfg.name = name;
 468        plat->cfg.host_caps = MMC_MODE_SPI;
 469        plat->cfg.voltages = MMC_SPI_VOLTAGE;
 470        plat->cfg.f_min = MMC_SPI_MIN_CLOCK;
 471        plat->cfg.f_max = priv->spi->max_hz;
 472        plat->cfg.part_type = PART_TYPE_DOS;
 473        plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 474
 475        plat->mmc.cfg = &plat->cfg;
 476        plat->mmc.priv = priv;
 477        plat->mmc.dev = dev;
 478
 479        upriv->mmc = &plat->mmc;
 480
 481        return 0;
 482}
 483
 484static int mmc_spi_bind(struct udevice *dev)
 485{
 486        struct mmc_spi_plat *plat = dev_get_plat(dev);
 487
 488        return mmc_bind(dev, &plat->mmc, &plat->cfg);
 489}
 490
 491static const struct dm_mmc_ops mmc_spi_ops = {
 492        .send_cmd       = dm_mmc_spi_request,
 493        .set_ios        = dm_mmc_spi_set_ios,
 494};
 495
 496static const struct udevice_id dm_mmc_spi_match[] = {
 497        { .compatible = "mmc-spi-slot" },
 498        { /* sentinel */ }
 499};
 500
 501U_BOOT_DRIVER(mmc_spi) = {
 502        .name = "mmc_spi",
 503        .id = UCLASS_MMC,
 504        .of_match = dm_mmc_spi_match,
 505        .ops = &mmc_spi_ops,
 506        .probe = mmc_spi_probe,
 507        .bind = mmc_spi_bind,
 508        .plat_auto      = sizeof(struct mmc_spi_plat),
 509        .priv_auto      = sizeof(struct mmc_spi_priv),
 510};
 511