• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dw_update_clk(void)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 
dw_set_clk(int clk)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 
dw_init(void)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 
dw_send_cmd(emmc_cmd_t * cmd)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 
dw_set_ios(int clk,int width)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 
dw_prepare(int lba,uintptr_t buf,size_t size)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 
dw_read(int lba,uintptr_t buf,size_t size)375 static int dw_read(int lba, uintptr_t buf, size_t size)
376 {
377 	return 0;
378 }
379 
dw_write(int lba,uintptr_t buf,size_t size)380 static int dw_write(int lba, uintptr_t buf, size_t size)
381 {
382 	return 0;
383 }
384 
dw_mmc_init(dw_mmc_params_t * params)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