uboot/drivers/mmc/meson_gx_mmc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2016 Carlo Caione <carlo@caione.org>
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <fdtdec.h>
   9#include <malloc.h>
  10#include <mmc.h>
  11#include <asm/io.h>
  12#include <asm/arch/sd_emmc.h>
  13#include <linux/log2.h>
  14
  15static inline void *get_regbase(const struct mmc *mmc)
  16{
  17        struct meson_mmc_platdata *pdata = mmc->priv;
  18
  19        return pdata->regbase;
  20}
  21
  22static inline uint32_t meson_read(struct mmc *mmc, int offset)
  23{
  24        return readl(get_regbase(mmc) + offset);
  25}
  26
  27static inline void meson_write(struct mmc *mmc, uint32_t val, int offset)
  28{
  29        writel(val, get_regbase(mmc) + offset);
  30}
  31
  32static void meson_mmc_config_clock(struct mmc *mmc)
  33{
  34        uint32_t meson_mmc_clk = 0;
  35        unsigned int clk, clk_src, clk_div;
  36
  37        if (!mmc->clock)
  38                return;
  39
  40        /* 1GHz / CLK_MAX_DIV = 15,9 MHz */
  41        if (mmc->clock > 16000000) {
  42                clk = SD_EMMC_CLKSRC_DIV2;
  43                clk_src = CLK_SRC_DIV2;
  44        } else {
  45                clk = SD_EMMC_CLKSRC_24M;
  46                clk_src = CLK_SRC_24M;
  47        }
  48        clk_div = DIV_ROUND_UP(clk, mmc->clock);
  49
  50        /* 180 phase core clock */
  51        meson_mmc_clk |= CLK_CO_PHASE_180;
  52
  53        /* 180 phase tx clock */
  54        meson_mmc_clk |= CLK_TX_PHASE_000;
  55
  56        /* clock settings */
  57        meson_mmc_clk |= clk_src;
  58        meson_mmc_clk |= clk_div;
  59
  60        meson_write(mmc, meson_mmc_clk, MESON_SD_EMMC_CLOCK);
  61}
  62
  63static int meson_dm_mmc_set_ios(struct udevice *dev)
  64{
  65        struct mmc *mmc = mmc_get_mmc_dev(dev);
  66        uint32_t meson_mmc_cfg;
  67
  68        meson_mmc_config_clock(mmc);
  69
  70        meson_mmc_cfg = meson_read(mmc, MESON_SD_EMMC_CFG);
  71
  72        meson_mmc_cfg &= ~CFG_BUS_WIDTH_MASK;
  73        if (mmc->bus_width == 1)
  74                meson_mmc_cfg |= CFG_BUS_WIDTH_1;
  75        else if (mmc->bus_width == 4)
  76                meson_mmc_cfg |= CFG_BUS_WIDTH_4;
  77        else if (mmc->bus_width == 8)
  78                meson_mmc_cfg |= CFG_BUS_WIDTH_8;
  79        else
  80                return -EINVAL;
  81
  82        /* 512 bytes block length */
  83        meson_mmc_cfg &= ~CFG_BL_LEN_MASK;
  84        meson_mmc_cfg |= CFG_BL_LEN_512;
  85
  86        /* Response timeout 256 clk */
  87        meson_mmc_cfg &= ~CFG_RESP_TIMEOUT_MASK;
  88        meson_mmc_cfg |= CFG_RESP_TIMEOUT_256;
  89
  90        /* Command-command gap 16 clk */
  91        meson_mmc_cfg &= ~CFG_RC_CC_MASK;
  92        meson_mmc_cfg |= CFG_RC_CC_16;
  93
  94        meson_write(mmc, meson_mmc_cfg, MESON_SD_EMMC_CFG);
  95
  96        return 0;
  97}
  98
  99static void meson_mmc_setup_cmd(struct mmc *mmc, struct mmc_data *data,
 100                                struct mmc_cmd *cmd)
 101{
 102        uint32_t meson_mmc_cmd = 0, cfg;
 103
 104        meson_mmc_cmd |= cmd->cmdidx << CMD_CFG_CMD_INDEX_SHIFT;
 105
 106        if (cmd->resp_type & MMC_RSP_PRESENT) {
 107                if (cmd->resp_type & MMC_RSP_136)
 108                        meson_mmc_cmd |= CMD_CFG_RESP_128;
 109
 110                if (cmd->resp_type & MMC_RSP_BUSY)
 111                        meson_mmc_cmd |= CMD_CFG_R1B;
 112
 113                if (!(cmd->resp_type & MMC_RSP_CRC))
 114                        meson_mmc_cmd |= CMD_CFG_RESP_NOCRC;
 115        } else {
 116                meson_mmc_cmd |= CMD_CFG_NO_RESP;
 117        }
 118
 119        if (data) {
 120                cfg = meson_read(mmc, MESON_SD_EMMC_CFG);
 121                cfg &= ~CFG_BL_LEN_MASK;
 122                cfg |= ilog2(data->blocksize) << CFG_BL_LEN_SHIFT;
 123                meson_write(mmc, cfg, MESON_SD_EMMC_CFG);
 124
 125                if (data->flags == MMC_DATA_WRITE)
 126                        meson_mmc_cmd |= CMD_CFG_DATA_WR;
 127
 128                meson_mmc_cmd |= CMD_CFG_DATA_IO | CMD_CFG_BLOCK_MODE |
 129                                 data->blocks;
 130        }
 131
 132        meson_mmc_cmd |= CMD_CFG_TIMEOUT_4S | CMD_CFG_OWNER |
 133                         CMD_CFG_END_OF_CHAIN;
 134
 135        meson_write(mmc, meson_mmc_cmd, MESON_SD_EMMC_CMD_CFG);
 136}
 137
 138static void meson_mmc_setup_addr(struct mmc *mmc, struct mmc_data *data)
 139{
 140        struct meson_mmc_platdata *pdata = mmc->priv;
 141        unsigned int data_size;
 142        uint32_t data_addr = 0;
 143
 144        if (data) {
 145                data_size = data->blocks * data->blocksize;
 146
 147                if (data->flags == MMC_DATA_READ) {
 148                        data_addr = (ulong) data->dest;
 149                        invalidate_dcache_range(data_addr,
 150                                                data_addr + data_size);
 151                } else {
 152                        pdata->w_buf = calloc(data_size, sizeof(char));
 153                        data_addr = (ulong) pdata->w_buf;
 154                        memcpy(pdata->w_buf, data->src, data_size);
 155                        flush_dcache_range(data_addr, data_addr + data_size);
 156                }
 157        }
 158
 159        meson_write(mmc, data_addr, MESON_SD_EMMC_CMD_DAT);
 160}
 161
 162static void meson_mmc_read_response(struct mmc *mmc, struct mmc_cmd *cmd)
 163{
 164        if (cmd->resp_type & MMC_RSP_136) {
 165                cmd->response[0] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP3);
 166                cmd->response[1] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP2);
 167                cmd->response[2] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP1);
 168                cmd->response[3] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP);
 169        } else {
 170                cmd->response[0] = meson_read(mmc, MESON_SD_EMMC_CMD_RSP);
 171        }
 172}
 173
 174static int meson_dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 175                                 struct mmc_data *data)
 176{
 177        struct mmc *mmc = mmc_get_mmc_dev(dev);
 178        struct meson_mmc_platdata *pdata = mmc->priv;
 179        uint32_t status;
 180        ulong start;
 181        int ret = 0;
 182
 183        /* max block size supported by chip is 512 byte */
 184        if (data && data->blocksize > 512)
 185                return -EINVAL;
 186
 187        meson_mmc_setup_cmd(mmc, data, cmd);
 188        meson_mmc_setup_addr(mmc, data);
 189
 190        meson_write(mmc, cmd->cmdarg, MESON_SD_EMMC_CMD_ARG);
 191
 192        /* use 10s timeout */
 193        start = get_timer(0);
 194        do {
 195                status = meson_read(mmc, MESON_SD_EMMC_STATUS);
 196        } while(!(status & STATUS_END_OF_CHAIN) && get_timer(start) < 10000);
 197
 198        if (!(status & STATUS_END_OF_CHAIN))
 199                ret = -ETIMEDOUT;
 200        else if (status & STATUS_RESP_TIMEOUT)
 201                ret = -ETIMEDOUT;
 202        else if (status & STATUS_ERR_MASK)
 203                ret = -EIO;
 204
 205        meson_mmc_read_response(mmc, cmd);
 206
 207        if (data && data->flags == MMC_DATA_WRITE)
 208                free(pdata->w_buf);
 209
 210        /* reset status bits */
 211        meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
 212
 213        return ret;
 214}
 215
 216static const struct dm_mmc_ops meson_dm_mmc_ops = {
 217        .send_cmd = meson_dm_mmc_send_cmd,
 218        .set_ios = meson_dm_mmc_set_ios,
 219};
 220
 221static int meson_mmc_ofdata_to_platdata(struct udevice *dev)
 222{
 223        struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
 224        fdt_addr_t addr;
 225
 226        addr = devfdt_get_addr(dev);
 227        if (addr == FDT_ADDR_T_NONE)
 228                return -EINVAL;
 229
 230        pdata->regbase = (void *)addr;
 231
 232        return 0;
 233}
 234
 235static int meson_mmc_probe(struct udevice *dev)
 236{
 237        struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
 238        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
 239        struct mmc *mmc = &pdata->mmc;
 240        struct mmc_config *cfg = &pdata->cfg;
 241        uint32_t val;
 242
 243        cfg->voltages = MMC_VDD_33_34 | MMC_VDD_32_33 |
 244                        MMC_VDD_31_32 | MMC_VDD_165_195;
 245        cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_4BIT |
 246                        MMC_MODE_HS_52MHz | MMC_MODE_HS;
 247        cfg->f_min = DIV_ROUND_UP(SD_EMMC_CLKSRC_24M, CLK_MAX_DIV);
 248        cfg->f_max = 100000000; /* 100 MHz */
 249        cfg->b_max = 511; /* max 512 - 1 blocks */
 250        cfg->name = dev->name;
 251
 252        mmc->priv = pdata;
 253        upriv->mmc = mmc;
 254
 255        mmc_set_clock(mmc, cfg->f_min, false);
 256
 257        /* reset all status bits */
 258        meson_write(mmc, STATUS_MASK, MESON_SD_EMMC_STATUS);
 259
 260        /* disable interrupts */
 261        meson_write(mmc, 0, MESON_SD_EMMC_IRQ_EN);
 262
 263        /* enable auto clock mode */
 264        val = meson_read(mmc, MESON_SD_EMMC_CFG);
 265        val &= ~CFG_SDCLK_ALWAYS_ON;
 266        val |= CFG_AUTO_CLK;
 267        meson_write(mmc, val, MESON_SD_EMMC_CFG);
 268
 269        return 0;
 270}
 271
 272int meson_mmc_bind(struct udevice *dev)
 273{
 274        struct meson_mmc_platdata *pdata = dev_get_platdata(dev);
 275
 276        return mmc_bind(dev, &pdata->mmc, &pdata->cfg);
 277}
 278
 279static const struct udevice_id meson_mmc_match[] = {
 280        { .compatible = "amlogic,meson-gx-mmc" },
 281        { /* sentinel */ }
 282};
 283
 284U_BOOT_DRIVER(meson_mmc) = {
 285        .name = "meson_gx_mmc",
 286        .id = UCLASS_MMC,
 287        .of_match = meson_mmc_match,
 288        .ops = &meson_dm_mmc_ops,
 289        .probe = meson_mmc_probe,
 290        .bind = meson_mmc_bind,
 291        .ofdata_to_platdata = meson_mmc_ofdata_to_platdata,
 292        .platdata_auto_alloc_size = sizeof(struct meson_mmc_platdata),
 293};
 294