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