uboot/drivers/mmc/ftsdc010_mci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Faraday MMC/SD Host Controller
   4 *
   5 * (C) Copyright 2010 Faraday Technology
   6 * Dante Su <dantesu@faraday-tech.com>
   7 *
   8 * Copyright 2018 Andes Technology, Inc.
   9 * Author: Rick Chen (rick@andestech.com)
  10 */
  11
  12#include <common.h>
  13#include <clk.h>
  14#include <malloc.h>
  15#include <part.h>
  16#include <mmc.h>
  17#include <linux/io.h>
  18#include <linux/errno.h>
  19#include <asm/byteorder.h>
  20#include <faraday/ftsdc010.h>
  21#include "ftsdc010_mci.h"
  22#include <dm.h>
  23#include <dt-structs.h>
  24#include <errno.h>
  25#include <mapmem.h>
  26#include <pwrseq.h>
  27#include <syscon.h>
  28#include <linux/err.h>
  29
  30DECLARE_GLOBAL_DATA_PTR;
  31
  32#define CFG_CMD_TIMEOUT (CONFIG_SYS_HZ >> 4) /* 250 ms */
  33#define CFG_RST_TIMEOUT CONFIG_SYS_HZ /* 1 sec reset timeout */
  34
  35#if CONFIG_IS_ENABLED(OF_PLATDATA)
  36struct ftsdc010 {
  37        fdt32_t         bus_width;
  38        bool            cap_mmc_highspeed;
  39        bool            cap_sd_highspeed;
  40        fdt32_t         clock_freq_min_max[2];
  41        struct phandle_2_cell   clocks[4];
  42        fdt32_t         fifo_depth;
  43        fdt32_t         reg[2];
  44};
  45#endif
  46
  47struct ftsdc010_plat {
  48#if CONFIG_IS_ENABLED(OF_PLATDATA)
  49        struct ftsdc010 dtplat;
  50#endif
  51        struct mmc_config cfg;
  52        struct mmc mmc;
  53};
  54
  55struct ftsdc_priv {
  56        struct clk clk;
  57        struct ftsdc010_chip chip;
  58        int fifo_depth;
  59        bool fifo_mode;
  60        u32 minmax[2];
  61};
  62
  63static inline int ftsdc010_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
  64{
  65        struct ftsdc010_chip *chip = mmc->priv;
  66        struct ftsdc010_mmc __iomem *regs = chip->regs;
  67        int ret = -ETIMEDOUT;
  68        uint32_t ts, st;
  69        uint32_t cmd   = FTSDC010_CMD_IDX(mmc_cmd->cmdidx);
  70        uint32_t arg   = mmc_cmd->cmdarg;
  71        uint32_t flags = mmc_cmd->resp_type;
  72
  73        cmd |= FTSDC010_CMD_CMD_EN;
  74
  75        if (chip->acmd) {
  76                cmd |= FTSDC010_CMD_APP_CMD;
  77                chip->acmd = 0;
  78        }
  79
  80        if (flags & MMC_RSP_PRESENT)
  81                cmd |= FTSDC010_CMD_NEED_RSP;
  82
  83        if (flags & MMC_RSP_136)
  84                cmd |= FTSDC010_CMD_LONG_RSP;
  85
  86        writel(FTSDC010_STATUS_RSP_MASK | FTSDC010_STATUS_CMD_SEND,
  87                &regs->clr);
  88        writel(arg, &regs->argu);
  89        writel(cmd, &regs->cmd);
  90
  91        if (!(flags & (MMC_RSP_PRESENT | MMC_RSP_136))) {
  92                for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
  93                        if (readl(&regs->status) & FTSDC010_STATUS_CMD_SEND) {
  94                                writel(FTSDC010_STATUS_CMD_SEND, &regs->clr);
  95                                ret = 0;
  96                                break;
  97                        }
  98                }
  99        } else {
 100                st = 0;
 101                for (ts = get_timer(0); get_timer(ts) < CFG_CMD_TIMEOUT; ) {
 102                        st = readl(&regs->status);
 103                        writel(st & FTSDC010_STATUS_RSP_MASK, &regs->clr);
 104                        if (st & FTSDC010_STATUS_RSP_MASK)
 105                                break;
 106                }
 107                if (st & FTSDC010_STATUS_RSP_CRC_OK) {
 108                        if (flags & MMC_RSP_136) {
 109                                mmc_cmd->response[0] = readl(&regs->rsp3);
 110                                mmc_cmd->response[1] = readl(&regs->rsp2);
 111                                mmc_cmd->response[2] = readl(&regs->rsp1);
 112                                mmc_cmd->response[3] = readl(&regs->rsp0);
 113                        } else {
 114                                mmc_cmd->response[0] = readl(&regs->rsp0);
 115                        }
 116                        ret = 0;
 117                } else {
 118                        debug("ftsdc010: rsp err (cmd=%d, st=0x%x)\n",
 119                                mmc_cmd->cmdidx, st);
 120                }
 121        }
 122
 123        if (ret) {
 124                debug("ftsdc010: cmd timeout (op code=%d)\n",
 125                        mmc_cmd->cmdidx);
 126        } else if (mmc_cmd->cmdidx == MMC_CMD_APP_CMD) {
 127                chip->acmd = 1;
 128        }
 129
 130        return ret;
 131}
 132
 133static void ftsdc010_clkset(struct mmc *mmc, uint32_t rate)
 134{
 135        struct ftsdc010_chip *chip = mmc->priv;
 136        struct ftsdc010_mmc __iomem *regs = chip->regs;
 137        uint32_t div;
 138
 139        for (div = 0; div < 0x7f; ++div) {
 140                if (rate >= chip->sclk / (2 * (div + 1)))
 141                        break;
 142        }
 143        chip->rate = chip->sclk / (2 * (div + 1));
 144
 145        writel(FTSDC010_CCR_CLK_DIV(div), &regs->ccr);
 146
 147        if (IS_SD(mmc)) {
 148                setbits_le32(&regs->ccr, FTSDC010_CCR_CLK_SD);
 149
 150                if (chip->rate > 25000000)
 151                        setbits_le32(&regs->ccr, FTSDC010_CCR_CLK_HISPD);
 152                else
 153                        clrbits_le32(&regs->ccr, FTSDC010_CCR_CLK_HISPD);
 154        }
 155}
 156
 157static int ftsdc010_wait(struct ftsdc010_mmc __iomem *regs, uint32_t mask)
 158{
 159        int ret = -ETIMEDOUT;
 160        uint32_t st, timeout = 10000000;
 161        while (timeout--) {
 162                st = readl(&regs->status);
 163                if (!(st & mask))
 164                        continue;
 165                writel(st & mask, &regs->clr);
 166                ret = 0;
 167                break;
 168        }
 169
 170        if (ret){
 171                debug("ftsdc010: wait st(0x%x) timeout\n", mask);
 172        }
 173
 174        return ret;
 175}
 176
 177/*
 178 * u-boot mmc api
 179 */
 180static int ftsdc010_request(struct udevice *dev, struct mmc_cmd *cmd,
 181        struct mmc_data *data)
 182{
 183        struct mmc *mmc = mmc_get_mmc_dev(dev);
 184        int ret = -EOPNOTSUPP;
 185        uint32_t len = 0;
 186        struct ftsdc010_chip *chip = mmc->priv;
 187        struct ftsdc010_mmc __iomem *regs = chip->regs;
 188
 189        if (data && (data->flags & MMC_DATA_WRITE) && chip->wprot) {
 190                printf("ftsdc010: the card is write protected!\n");
 191                return ret;
 192        }
 193
 194        if (data) {
 195                uint32_t dcr;
 196
 197                len = data->blocksize * data->blocks;
 198
 199                /* 1. data disable + fifo reset */
 200                dcr = 0;
 201#ifdef CONFIG_FTSDC010_SDIO
 202                dcr |= FTSDC010_DCR_FIFO_RST;
 203#endif
 204                writel(dcr, &regs->dcr);
 205
 206                /* 2. clear status register */
 207                writel(FTSDC010_STATUS_DATA_MASK | FTSDC010_STATUS_FIFO_URUN
 208                        | FTSDC010_STATUS_FIFO_ORUN, &regs->clr);
 209
 210                /* 3. data timeout (1 sec) */
 211                writel(chip->rate, &regs->dtr);
 212
 213                /* 4. data length (bytes) */
 214                writel(len, &regs->dlr);
 215
 216                /* 5. data enable */
 217                dcr = (ffs(data->blocksize) - 1) | FTSDC010_DCR_DATA_EN;
 218                if (data->flags & MMC_DATA_WRITE)
 219                        dcr |= FTSDC010_DCR_DATA_WRITE;
 220                writel(dcr, &regs->dcr);
 221        }
 222
 223        ret = ftsdc010_send_cmd(mmc, cmd);
 224        if (ret) {
 225                printf("ftsdc010: CMD%d failed\n", cmd->cmdidx);
 226                return ret;
 227        }
 228
 229        if (!data)
 230                return ret;
 231
 232        if (data->flags & MMC_DATA_WRITE) {
 233                const uint8_t *buf = (const uint8_t *)data->src;
 234
 235                while (len > 0) {
 236                        int wlen;
 237
 238                        /* wait for tx ready */
 239                        ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_URUN);
 240                        if (ret)
 241                                break;
 242
 243                        /* write bytes to ftsdc010 */
 244                        for (wlen = 0; wlen < len && wlen < chip->fifo; ) {
 245                                writel(*(uint32_t *)buf, &regs->dwr);
 246                                buf  += 4;
 247                                wlen += 4;
 248                        }
 249
 250                        len -= wlen;
 251                }
 252
 253        } else {
 254                uint8_t *buf = (uint8_t *)data->dest;
 255
 256                while (len > 0) {
 257                        int rlen;
 258
 259                        /* wait for rx ready */
 260                        ret = ftsdc010_wait(regs, FTSDC010_STATUS_FIFO_ORUN);
 261                        if (ret)
 262                                break;
 263
 264                        /* fetch bytes from ftsdc010 */
 265                        for (rlen = 0; rlen < len && rlen < chip->fifo; ) {
 266                                *(uint32_t *)buf = readl(&regs->dwr);
 267                                buf  += 4;
 268                                rlen += 4;
 269                        }
 270
 271                        len -= rlen;
 272                }
 273
 274        }
 275
 276        if (!ret) {
 277                ret = ftsdc010_wait(regs,
 278                        FTSDC010_STATUS_DATA_END | FTSDC010_STATUS_DATA_CRC_OK);
 279        }
 280
 281        return ret;
 282}
 283
 284static int ftsdc010_set_ios(struct udevice *dev)
 285{
 286        struct mmc *mmc = mmc_get_mmc_dev(dev);
 287        struct ftsdc010_chip *chip = mmc->priv;
 288        struct ftsdc010_mmc __iomem *regs = chip->regs;
 289
 290        ftsdc010_clkset(mmc, mmc->clock);
 291
 292        clrbits_le32(&regs->bwr, FTSDC010_BWR_MODE_MASK);
 293        switch (mmc->bus_width) {
 294        case 4:
 295                setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_4BIT);
 296                break;
 297        case 8:
 298                setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_8BIT);
 299                break;
 300        default:
 301                setbits_le32(&regs->bwr, FTSDC010_BWR_MODE_1BIT);
 302                break;
 303        }
 304
 305        return 0;
 306}
 307
 308static int ftsdc010_get_cd(struct udevice *dev)
 309{
 310        struct mmc *mmc = mmc_get_mmc_dev(dev);
 311        struct ftsdc010_chip *chip = mmc->priv;
 312        struct ftsdc010_mmc __iomem *regs = chip->regs;
 313        return !(readl(&regs->status) & FTSDC010_STATUS_CARD_DETECT);
 314}
 315
 316static int ftsdc010_get_wp(struct udevice *dev)
 317{
 318        struct mmc *mmc = mmc_get_mmc_dev(dev);
 319        struct ftsdc010_chip *chip = mmc->priv;
 320        struct ftsdc010_mmc __iomem *regs = chip->regs;
 321        if (readl(&regs->status) & FTSDC010_STATUS_WRITE_PROT) {
 322                printf("ftsdc010: write protected\n");
 323                chip->wprot = 1;
 324        }
 325
 326        return 0;
 327}
 328
 329static int ftsdc010_init(struct mmc *mmc)
 330{
 331        struct ftsdc010_chip *chip = mmc->priv;
 332        struct ftsdc010_mmc __iomem *regs = chip->regs;
 333        uint32_t ts;
 334
 335        chip->fifo = (readl(&regs->feature) & 0xff) << 2;
 336
 337        /* 1. chip reset */
 338        writel(FTSDC010_CMD_SDC_RST, &regs->cmd);
 339        for (ts = get_timer(0); get_timer(ts) < CFG_RST_TIMEOUT; ) {
 340                if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST)
 341                        continue;
 342                break;
 343        }
 344        if (readl(&regs->cmd) & FTSDC010_CMD_SDC_RST) {
 345                printf("ftsdc010: reset failed\n");
 346                return -EOPNOTSUPP;
 347        }
 348
 349        /* 2. enter low speed mode (400k card detection) */
 350        ftsdc010_clkset(mmc, 400000);
 351
 352        /* 3. interrupt disabled */
 353        writel(0, &regs->int_mask);
 354
 355        return 0;
 356}
 357
 358static int ftsdc010_probe(struct udevice *dev)
 359{
 360        struct mmc *mmc = mmc_get_mmc_dev(dev);
 361        return ftsdc010_init(mmc);
 362}
 363
 364const struct dm_mmc_ops dm_ftsdc010_mmc_ops = {
 365        .send_cmd       = ftsdc010_request,
 366        .set_ios        = ftsdc010_set_ios,
 367        .get_cd         = ftsdc010_get_cd,
 368        .get_wp         = ftsdc010_get_wp,
 369};
 370
 371static void ftsdc_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
 372                     uint caps, u32 max_clk, u32 min_clk)
 373{
 374        cfg->name = name;
 375        cfg->f_min = min_clk;
 376        cfg->f_max = max_clk;
 377        cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
 378        cfg->host_caps = caps;
 379        if (buswidth == 8) {
 380                cfg->host_caps |= MMC_MODE_8BIT;
 381                cfg->host_caps &= ~MMC_MODE_4BIT;
 382        } else {
 383                cfg->host_caps |= MMC_MODE_4BIT;
 384                cfg->host_caps &= ~MMC_MODE_8BIT;
 385        }
 386        cfg->part_type = PART_TYPE_DOS;
 387        cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 388}
 389
 390static int ftsdc010_mmc_ofdata_to_platdata(struct udevice *dev)
 391{
 392#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 393        struct ftsdc_priv *priv = dev_get_priv(dev);
 394        struct ftsdc010_chip *chip = &priv->chip;
 395        chip->name = dev->name;
 396        chip->ioaddr = (void *)devfdt_get_addr(dev);
 397        chip->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 398                                        "bus-width", 4);
 399        chip->priv = dev;
 400        priv->fifo_depth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 401                                    "fifo-depth", 0);
 402        priv->fifo_mode = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
 403                                          "fifo-mode");
 404        if (fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
 405                         "clock-freq-min-max", priv->minmax, 2)) {
 406                int val = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
 407                                  "max-frequency", -EINVAL);
 408                if (val < 0)
 409                        return val;
 410
 411                priv->minmax[0] = 400000;  /* 400 kHz */
 412                priv->minmax[1] = val;
 413        } else {
 414                debug("%s: 'clock-freq-min-max' property was deprecated.\n",
 415                __func__);
 416        }
 417#endif
 418        chip->sclk = priv->minmax[1];
 419        chip->regs = chip->ioaddr;
 420        return 0;
 421}
 422
 423static int ftsdc010_mmc_probe(struct udevice *dev)
 424{
 425        struct ftsdc010_plat *plat = dev_get_platdata(dev);
 426        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 427        struct ftsdc_priv *priv = dev_get_priv(dev);
 428        struct ftsdc010_chip *chip = &priv->chip;
 429        struct udevice *pwr_dev __maybe_unused;
 430
 431#if CONFIG_IS_ENABLED(OF_PLATDATA)
 432        int ret;
 433        struct ftsdc010 *dtplat = &plat->dtplat;
 434        chip->name = dev->name;
 435        chip->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
 436        chip->buswidth = dtplat->bus_width;
 437        chip->priv = dev;
 438        chip->dev_index = 1;
 439        memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax));
 440        ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
 441        if (ret < 0)
 442                return ret;
 443#endif
 444
 445        if (dev_read_bool(dev, "cap-mmc-highspeed") || \
 446                  dev_read_bool(dev, "cap-sd-highspeed"))
 447                chip->caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz;
 448
 449        ftsdc_setup_cfg(&plat->cfg, dev->name, chip->buswidth, chip->caps,
 450                        priv->minmax[1] , priv->minmax[0]);
 451        chip->mmc = &plat->mmc;
 452        chip->mmc->priv = &priv->chip;
 453        chip->mmc->dev = dev;
 454        upriv->mmc = chip->mmc;
 455        return ftsdc010_probe(dev);
 456}
 457
 458int ftsdc010_mmc_bind(struct udevice *dev)
 459{
 460        struct ftsdc010_plat *plat = dev_get_platdata(dev);
 461
 462        return mmc_bind(dev, &plat->mmc, &plat->cfg);
 463}
 464
 465static const struct udevice_id ftsdc010_mmc_ids[] = {
 466        { .compatible = "andestech,atfsdc010" },
 467        { }
 468};
 469
 470U_BOOT_DRIVER(ftsdc010_mmc) = {
 471        .name           = "ftsdc010_mmc",
 472        .id             = UCLASS_MMC,
 473        .of_match       = ftsdc010_mmc_ids,
 474        .ofdata_to_platdata = ftsdc010_mmc_ofdata_to_platdata,
 475        .ops            = &dm_ftsdc010_mmc_ops,
 476        .bind           = ftsdc010_mmc_bind,
 477        .probe          = ftsdc010_mmc_probe,
 478        .priv_auto_alloc_size = sizeof(struct ftsdc_priv),
 479        .platdata_auto_alloc_size = sizeof(struct ftsdc010_plat),
 480};
 481