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