Home | History | Annotate | Download | only in emmc
      1 /*
      2  * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
      3  *
      4  * SPDX-License-Identifier: BSD-3-Clause
      5  */
      6 
      7 #include <arch.h>
      8 #include <arch_helpers.h>
      9 #include <assert.h>
     10 #include <debug.h>
     11 #include <delay_timer.h>
     12 #include <dw_mmc.h>
     13 #include <emmc.h>
     14 #include <errno.h>
     15 #include <mmio.h>
     16 #include <string.h>
     17 
     18 #define DWMMC_CTRL			(0x00)
     19 #define CTRL_IDMAC_EN			(1 << 25)
     20 #define CTRL_DMA_EN			(1 << 5)
     21 #define CTRL_INT_EN			(1 << 4)
     22 #define CTRL_DMA_RESET			(1 << 2)
     23 #define CTRL_FIFO_RESET			(1 << 1)
     24 #define CTRL_RESET			(1 << 0)
     25 #define CTRL_RESET_ALL			(CTRL_DMA_RESET | CTRL_FIFO_RESET | \
     26 					 CTRL_RESET)
     27 
     28 #define DWMMC_PWREN			(0x04)
     29 #define DWMMC_CLKDIV			(0x08)
     30 #define DWMMC_CLKSRC			(0x0c)
     31 #define DWMMC_CLKENA			(0x10)
     32 #define DWMMC_TMOUT			(0x14)
     33 #define DWMMC_CTYPE			(0x18)
     34 #define CTYPE_8BIT			(1 << 16)
     35 #define CTYPE_4BIT			(1)
     36 #define CTYPE_1BIT			(0)
     37 
     38 #define DWMMC_BLKSIZ			(0x1c)
     39 #define DWMMC_BYTCNT			(0x20)
     40 #define DWMMC_INTMASK			(0x24)
     41 #define INT_EBE				(1 << 15)
     42 #define INT_SBE				(1 << 13)
     43 #define INT_HLE				(1 << 12)
     44 #define INT_FRUN			(1 << 11)
     45 #define INT_DRT				(1 << 9)
     46 #define INT_RTO				(1 << 8)
     47 #define INT_DCRC			(1 << 7)
     48 #define INT_RCRC			(1 << 6)
     49 #define INT_RXDR			(1 << 5)
     50 #define INT_TXDR			(1 << 4)
     51 #define INT_DTO				(1 << 3)
     52 #define INT_CMD_DONE			(1 << 2)
     53 #define INT_RE				(1 << 1)
     54 
     55 #define DWMMC_CMDARG			(0x28)
     56 #define DWMMC_CMD			(0x2c)
     57 #define CMD_START			(1 << 31)
     58 #define CMD_USE_HOLD_REG		(1 << 29)	/* 0 if SDR50/100 */
     59 #define CMD_UPDATE_CLK_ONLY		(1 << 21)
     60 #define CMD_SEND_INIT			(1 << 15)
     61 #define CMD_STOP_ABORT_CMD		(1 << 14)
     62 #define CMD_WAIT_PRVDATA_COMPLETE	(1 << 13)
     63 #define CMD_WRITE			(1 << 10)
     64 #define CMD_DATA_TRANS_EXPECT		(1 << 9)
     65 #define CMD_CHECK_RESP_CRC		(1 << 8)
     66 #define CMD_RESP_LEN			(1 << 7)
     67 #define CMD_RESP_EXPECT			(1 << 6)
     68 #define CMD(x)				(x & 0x3f)
     69 
     70 #define DWMMC_RESP0			(0x30)
     71 #define DWMMC_RESP1			(0x34)
     72 #define DWMMC_RESP2			(0x38)
     73 #define DWMMC_RESP3			(0x3c)
     74 #define DWMMC_RINTSTS			(0x44)
     75 #define DWMMC_STATUS			(0x48)
     76 #define STATUS_DATA_BUSY		(1 << 9)
     77 
     78 #define DWMMC_FIFOTH			(0x4c)
     79 #define FIFOTH_TWMARK(x)		(x & 0xfff)
     80 #define FIFOTH_RWMARK(x)		((x & 0x1ff) << 16)
     81 #define FIFOTH_DMA_BURST_SIZE(x)	((x & 0x7) << 28)
     82 
     83 #define DWMMC_DEBNCE			(0x64)
     84 #define DWMMC_BMOD			(0x80)
     85 #define BMOD_ENABLE			(1 << 7)
     86 #define BMOD_FB				(1 << 1)
     87 #define BMOD_SWRESET			(1 << 0)
     88 
     89 #define DWMMC_DBADDR			(0x88)
     90 #define DWMMC_IDSTS			(0x8c)
     91 #define DWMMC_IDINTEN			(0x90)
     92 #define DWMMC_CARDTHRCTL		(0x100)
     93 #define CARDTHRCTL_RD_THR(x)		((x & 0xfff) << 16)
     94 #define CARDTHRCTL_RD_THR_EN		(1 << 0)
     95 
     96 #define IDMAC_DES0_DIC			(1 << 1)
     97 #define IDMAC_DES0_LD			(1 << 2)
     98 #define IDMAC_DES0_FS			(1 << 3)
     99 #define IDMAC_DES0_CH			(1 << 4)
    100 #define IDMAC_DES0_ER			(1 << 5)
    101 #define IDMAC_DES0_CES			(1 << 30)
    102 #define IDMAC_DES0_OWN			(1 << 31)
    103 #define IDMAC_DES1_BS1(x)		((x) & 0x1fff)
    104 #define IDMAC_DES2_BS2(x)		(((x) & 0x1fff) << 13)
    105 
    106 #define DWMMC_DMA_MAX_BUFFER_SIZE	(512 * 8)
    107 
    108 #define DWMMC_8BIT_MODE			(1 << 6)
    109 
    110 #define TIMEOUT				100000
    111 
    112 struct dw_idmac_desc {
    113 	unsigned int	des0;
    114 	unsigned int	des1;
    115 	unsigned int	des2;
    116 	unsigned int	des3;
    117 };
    118 
    119 static void dw_init(void);
    120 static int dw_send_cmd(emmc_cmd_t *cmd);
    121 static int dw_set_ios(int clk, int width);
    122 static int dw_prepare(int lba, uintptr_t buf, size_t size);
    123 static int dw_read(int lba, uintptr_t buf, size_t size);
    124 static int dw_write(int lba, uintptr_t buf, size_t size);
    125 
    126 static const emmc_ops_t dw_mmc_ops = {
    127 	.init		= dw_init,
    128 	.send_cmd	= dw_send_cmd,
    129 	.set_ios	= dw_set_ios,
    130 	.prepare	= dw_prepare,
    131 	.read		= dw_read,
    132 	.write		= dw_write,
    133 };
    134 
    135 static dw_mmc_params_t dw_params;
    136 
    137 static void dw_update_clk(void)
    138 {
    139 	unsigned int data;
    140 
    141 	mmio_write_32(dw_params.reg_base + DWMMC_CMD,
    142 		      CMD_WAIT_PRVDATA_COMPLETE | CMD_UPDATE_CLK_ONLY |
    143 		      CMD_START);
    144 	while (1) {
    145 		data = mmio_read_32(dw_params.reg_base + DWMMC_CMD);
    146 		if ((data & CMD_START) == 0)
    147 			break;
    148 		data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS);
    149 		assert(data & INT_HLE);
    150 	}
    151 }
    152 
    153 static void dw_set_clk(int clk)
    154 {
    155 	unsigned int data;
    156 	int div;
    157 
    158 	assert(clk > 0);
    159 
    160 	for (div = 1; div < 256; div++) {
    161 		if ((dw_params.clk_rate / (2 * div)) <= clk) {
    162 			break;
    163 		}
    164 	}
    165 	assert(div < 256);
    166 
    167 	/* wait until controller is idle */
    168 	do {
    169 		data = mmio_read_32(dw_params.reg_base + DWMMC_STATUS);
    170 	} while (data & STATUS_DATA_BUSY);
    171 
    172 	/* disable clock before change clock rate */
    173 	mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 0);
    174 	dw_update_clk();
    175 
    176 	mmio_write_32(dw_params.reg_base + DWMMC_CLKDIV, div);
    177 	dw_update_clk();
    178 
    179 	/* enable clock */
    180 	mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 1);
    181 	mmio_write_32(dw_params.reg_base + DWMMC_CLKSRC, 0);
    182 	dw_update_clk();
    183 }
    184 
    185 static void dw_init(void)
    186 {
    187 	unsigned int data;
    188 	uintptr_t base;
    189 
    190 	assert((dw_params.reg_base & EMMC_BLOCK_MASK) == 0);
    191 
    192 	base = dw_params.reg_base;
    193 	mmio_write_32(base + DWMMC_PWREN, 1);
    194 	mmio_write_32(base + DWMMC_CTRL, CTRL_RESET_ALL);
    195 	do {
    196 		data = mmio_read_32(base + DWMMC_CTRL);
    197 	} while (data);
    198 
    199 	/* enable DMA in CTRL */
    200 	data = CTRL_INT_EN | CTRL_DMA_EN | CTRL_IDMAC_EN;
    201 	mmio_write_32(base + DWMMC_CTRL, data);
    202 	mmio_write_32(base + DWMMC_RINTSTS, ~0);
    203 	mmio_write_32(base + DWMMC_INTMASK, 0);
    204 	mmio_write_32(base + DWMMC_TMOUT, ~0);
    205 	mmio_write_32(base + DWMMC_IDINTEN, ~0);
    206 	mmio_write_32(base + DWMMC_BLKSIZ, EMMC_BLOCK_SIZE);
    207 	mmio_write_32(base + DWMMC_BYTCNT, 256 * 1024);
    208 	mmio_write_32(base + DWMMC_DEBNCE, 0x00ffffff);
    209 	mmio_write_32(base + DWMMC_BMOD, BMOD_SWRESET);
    210 	do {
    211 		data = mmio_read_32(base + DWMMC_BMOD);
    212 	} while (data & BMOD_SWRESET);
    213 	/* enable DMA in BMOD */
    214 	data |= BMOD_ENABLE | BMOD_FB;
    215 	mmio_write_32(base + DWMMC_BMOD, data);
    216 
    217 	udelay(100);
    218 	dw_set_clk(EMMC_BOOT_CLK_RATE);
    219 	udelay(100);
    220 }
    221 
    222 static int dw_send_cmd(emmc_cmd_t *cmd)
    223 {
    224 	unsigned int op, data, err_mask;
    225 	uintptr_t base;
    226 	int timeout;
    227 
    228 	assert(cmd);
    229 
    230 	base = dw_params.reg_base;
    231 
    232 	switch (cmd->cmd_idx) {
    233 	case EMMC_CMD0:
    234 		op = CMD_SEND_INIT;
    235 		break;
    236 	case EMMC_CMD12:
    237 		op = CMD_STOP_ABORT_CMD;
    238 		break;
    239 	case EMMC_CMD13:
    240 		op = CMD_WAIT_PRVDATA_COMPLETE;
    241 		break;
    242 	case EMMC_CMD8:
    243 	case EMMC_CMD17:
    244 	case EMMC_CMD18:
    245 		op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE;
    246 		break;
    247 	case EMMC_CMD24:
    248 	case EMMC_CMD25:
    249 		op = CMD_WRITE | CMD_DATA_TRANS_EXPECT |
    250 		     CMD_WAIT_PRVDATA_COMPLETE;
    251 		break;
    252 	default:
    253 		op = 0;
    254 		break;
    255 	}
    256 	op |= CMD_USE_HOLD_REG | CMD_START;
    257 	switch (cmd->resp_type) {
    258 	case 0:
    259 		break;
    260 	case EMMC_RESPONSE_R2:
    261 		op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC |
    262 		      CMD_RESP_LEN;
    263 		break;
    264 	case EMMC_RESPONSE_R3:
    265 		op |= CMD_RESP_EXPECT;
    266 		break;
    267 	default:
    268 		op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC;
    269 		break;
    270 	}
    271 	timeout = TIMEOUT;
    272 	do {
    273 		data = mmio_read_32(base + DWMMC_STATUS);
    274 		if (--timeout <= 0)
    275 			panic();
    276 	} while (data & STATUS_DATA_BUSY);
    277 
    278 	mmio_write_32(base + DWMMC_RINTSTS, ~0);
    279 	mmio_write_32(base + DWMMC_CMDARG, cmd->cmd_arg);
    280 	mmio_write_32(base + DWMMC_CMD, op | cmd->cmd_idx);
    281 
    282 	err_mask = INT_EBE | INT_HLE | INT_RTO | INT_RCRC | INT_RE |
    283 		   INT_DCRC | INT_DRT | INT_SBE;
    284 	timeout = TIMEOUT;
    285 	do {
    286 		udelay(500);
    287 		data = mmio_read_32(base + DWMMC_RINTSTS);
    288 
    289 		if (data & err_mask)
    290 			return -EIO;
    291 		if (data & INT_DTO)
    292 			break;
    293 		if (--timeout == 0) {
    294 			ERROR("%s, RINTSTS:0x%x\n", __func__, data);
    295 			panic();
    296 		}
    297 	} while (!(data & INT_CMD_DONE));
    298 
    299 	if (op & CMD_RESP_EXPECT) {
    300 		cmd->resp_data[0] = mmio_read_32(base + DWMMC_RESP0);
    301 		if (op & CMD_RESP_LEN) {
    302 			cmd->resp_data[1] = mmio_read_32(base + DWMMC_RESP1);
    303 			cmd->resp_data[2] = mmio_read_32(base + DWMMC_RESP2);
    304 			cmd->resp_data[3] = mmio_read_32(base + DWMMC_RESP3);
    305 		}
    306 	}
    307 	return 0;
    308 }
    309 
    310 static int dw_set_ios(int clk, int width)
    311 {
    312 	switch (width) {
    313 	case EMMC_BUS_WIDTH_1:
    314 		mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_1BIT);
    315 		break;
    316 	case EMMC_BUS_WIDTH_4:
    317 		mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_4BIT);
    318 		break;
    319 	case EMMC_BUS_WIDTH_8:
    320 		mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_8BIT);
    321 		break;
    322 	default:
    323 		assert(0);
    324 	}
    325 	dw_set_clk(clk);
    326 	return 0;
    327 }
    328 
    329 static int dw_prepare(int lba, uintptr_t buf, size_t size)
    330 {
    331 	struct dw_idmac_desc *desc;
    332 	int desc_cnt, i, last;
    333 	uintptr_t base;
    334 
    335 	assert(((buf & EMMC_BLOCK_MASK) == 0) &&
    336 	       ((size % EMMC_BLOCK_SIZE) == 0) &&
    337 	       (dw_params.desc_size > 0) &&
    338 	       ((dw_params.reg_base & EMMC_BLOCK_MASK) == 0) &&
    339 	       ((dw_params.desc_base & EMMC_BLOCK_MASK) == 0) &&
    340 	       ((dw_params.desc_size & EMMC_BLOCK_MASK) == 0));
    341 
    342 	desc_cnt = (size + DWMMC_DMA_MAX_BUFFER_SIZE - 1) /
    343 		   DWMMC_DMA_MAX_BUFFER_SIZE;
    344 	assert(desc_cnt * sizeof(struct dw_idmac_desc) < dw_params.desc_size);
    345 
    346 	base = dw_params.reg_base;
    347 	desc = (struct dw_idmac_desc *)dw_params.desc_base;
    348 	mmio_write_32(base + DWMMC_BYTCNT, size);
    349 	mmio_write_32(base + DWMMC_RINTSTS, ~0);
    350 	for (i = 0; i < desc_cnt; i++) {
    351 		desc[i].des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | IDMAC_DES0_DIC;
    352 		desc[i].des1 = IDMAC_DES1_BS1(DWMMC_DMA_MAX_BUFFER_SIZE);
    353 		desc[i].des2 = buf + DWMMC_DMA_MAX_BUFFER_SIZE * i;
    354 		desc[i].des3 = dw_params.desc_base +
    355 			       (sizeof(struct dw_idmac_desc)) * (i + 1);
    356 	}
    357 	/* first descriptor */
    358 	desc->des0 |= IDMAC_DES0_FS;
    359 	/* last descriptor */
    360 	last = desc_cnt - 1;
    361 	(desc + last)->des0 |= IDMAC_DES0_LD;
    362 	(desc + last)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH);
    363 	(desc + last)->des1 = IDMAC_DES1_BS1(size - (last *
    364 				  DWMMC_DMA_MAX_BUFFER_SIZE));
    365 	/* set next descriptor address as 0 */
    366 	(desc + last)->des3 = 0;
    367 
    368 	mmio_write_32(base + DWMMC_DBADDR, dw_params.desc_base);
    369 	clean_dcache_range(dw_params.desc_base,
    370 			   desc_cnt * DWMMC_DMA_MAX_BUFFER_SIZE);
    371 
    372 	return 0;
    373 }
    374 
    375 static int dw_read(int lba, uintptr_t buf, size_t size)
    376 {
    377 	return 0;
    378 }
    379 
    380 static int dw_write(int lba, uintptr_t buf, size_t size)
    381 {
    382 	return 0;
    383 }
    384 
    385 void dw_mmc_init(dw_mmc_params_t *params)
    386 {
    387 	assert((params != 0) &&
    388 	       ((params->reg_base & EMMC_BLOCK_MASK) == 0) &&
    389 	       ((params->desc_base & EMMC_BLOCK_MASK) == 0) &&
    390 	       ((params->desc_size & EMMC_BLOCK_MASK) == 0) &&
    391 	       (params->desc_size > 0) &&
    392 	       (params->clk_rate > 0) &&
    393 	       ((params->bus_width == EMMC_BUS_WIDTH_1) ||
    394 		(params->bus_width == EMMC_BUS_WIDTH_4) ||
    395 		(params->bus_width == EMMC_BUS_WIDTH_8)));
    396 
    397 	memcpy(&dw_params, params, sizeof(dw_mmc_params_t));
    398 	emmc_init(&dw_mmc_ops, params->clk_rate, params->bus_width,
    399 		  params->flags);
    400 }
    401