xref: /rk3399_rockchip-uboot/drivers/dfu/dfu_mmc.c (revision 7c4213f6a52f35ff6ba2d97aa4eb04cbfc963b86)
1cb383cd2SLukasz Majewski /*
2cb383cd2SLukasz Majewski  * dfu.c -- DFU back-end routines
3cb383cd2SLukasz Majewski  *
4cb383cd2SLukasz Majewski  * Copyright (C) 2012 Samsung Electronics
5cb383cd2SLukasz Majewski  * author: Lukasz Majewski <l.majewski@samsung.com>
6cb383cd2SLukasz Majewski  *
71a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
8cb383cd2SLukasz Majewski  */
9cb383cd2SLukasz Majewski 
10cb383cd2SLukasz Majewski #include <common.h>
11cb383cd2SLukasz Majewski #include <malloc.h>
121b6ca18bSPantelis Antoniou #include <errno.h>
13ea2453d5SPantelis Antoniou #include <div64.h>
14cb383cd2SLukasz Majewski #include <dfu.h>
150e285b50SStephen Warren #include <ext4fs.h>
160e285b50SStephen Warren #include <fat.h>
177d0b605aSŁukasz Majewski #include <mmc.h>
18cb383cd2SLukasz Majewski 
1941ac233cSPrzemyslaw Marczak static unsigned char *dfu_file_buf;
20ea2453d5SPantelis Antoniou static long dfu_file_buf_len;
21411c5e57SStephen Warren static long dfu_file_buf_filled;
22ea2453d5SPantelis Antoniou 
23c8151b4aSLukasz Majewski static int mmc_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part)
24c8151b4aSLukasz Majewski {
25c8151b4aSLukasz Majewski 	int ret;
26c8151b4aSLukasz Majewski 
27c8151b4aSLukasz Majewski 	if (part == mmc->part_num)
28c8151b4aSLukasz Majewski 		return 0;
29c8151b4aSLukasz Majewski 
30dd64827eSStephen Warren 	ret = mmc_switch_part(dfu->data.mmc.dev_num, part);
31c8151b4aSLukasz Majewski 	if (ret) {
32c8151b4aSLukasz Majewski 		error("Cannot switch to partition %d\n", part);
33c8151b4aSLukasz Majewski 		return ret;
34c8151b4aSLukasz Majewski 	}
35c8151b4aSLukasz Majewski 	mmc->part_num = part;
36c8151b4aSLukasz Majewski 
37c8151b4aSLukasz Majewski 	return 0;
38c8151b4aSLukasz Majewski }
39c8151b4aSLukasz Majewski 
405a127c84SAfzal Mohammed static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
41ea2453d5SPantelis Antoniou 			u64 offset, void *buf, long *len)
42cb383cd2SLukasz Majewski {
437da6fa27SPrzemyslaw Marczak 	struct mmc *mmc;
447d0b605aSŁukasz Majewski 	u32 blk_start, blk_count, n = 0;
45c8151b4aSLukasz Majewski 	int ret, part_num_bkp = 0;
46cb383cd2SLukasz Majewski 
477da6fa27SPrzemyslaw Marczak 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
487da6fa27SPrzemyslaw Marczak 	if (!mmc) {
497da6fa27SPrzemyslaw Marczak 		error("Device MMC %d - not found!", dfu->data.mmc.dev_num);
507da6fa27SPrzemyslaw Marczak 		return -ENODEV;
517da6fa27SPrzemyslaw Marczak 	}
527da6fa27SPrzemyslaw Marczak 
53ea2453d5SPantelis Antoniou 	/*
54ea2453d5SPantelis Antoniou 	 * We must ensure that we work in lba_blk_size chunks, so ALIGN
55ea2453d5SPantelis Antoniou 	 * this value.
56ea2453d5SPantelis Antoniou 	 */
57ea2453d5SPantelis Antoniou 	*len = ALIGN(*len, dfu->data.mmc.lba_blk_size);
58ea2453d5SPantelis Antoniou 
59ea2453d5SPantelis Antoniou 	blk_start = dfu->data.mmc.lba_start +
60ea2453d5SPantelis Antoniou 			(u32)lldiv(offset, dfu->data.mmc.lba_blk_size);
61ea2453d5SPantelis Antoniou 	blk_count = *len / dfu->data.mmc.lba_blk_size;
62ea2453d5SPantelis Antoniou 	if (blk_start + blk_count >
63ea2453d5SPantelis Antoniou 			dfu->data.mmc.lba_start + dfu->data.mmc.lba_size) {
64ea2453d5SPantelis Antoniou 		puts("Request would exceed designated area!\n");
65ea2453d5SPantelis Antoniou 		return -EINVAL;
66ea2453d5SPantelis Antoniou 	}
67ea2453d5SPantelis Antoniou 
68c8151b4aSLukasz Majewski 	if (dfu->data.mmc.hw_partition >= 0) {
69c8151b4aSLukasz Majewski 		part_num_bkp = mmc->part_num;
70c8151b4aSLukasz Majewski 		ret = mmc_access_part(dfu, mmc, dfu->data.mmc.hw_partition);
71c8151b4aSLukasz Majewski 		if (ret)
72c8151b4aSLukasz Majewski 			return ret;
73c8151b4aSLukasz Majewski 	}
74c8151b4aSLukasz Majewski 
757d0b605aSŁukasz Majewski 	debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
76dd64827eSStephen Warren 	      op == DFU_OP_READ ? "MMC READ" : "MMC WRITE",
77dd64827eSStephen Warren 	      dfu->data.mmc.dev_num, blk_start, blk_count, buf);
787d0b605aSŁukasz Majewski 	switch (op) {
797d0b605aSŁukasz Majewski 	case DFU_OP_READ:
80*7c4213f6SStephen Warren 		n = mmc->block_dev.block_read(&mmc->block_dev, blk_start,
817d0b605aSŁukasz Majewski 					      blk_count, buf);
827d0b605aSŁukasz Majewski 		break;
837d0b605aSŁukasz Majewski 	case DFU_OP_WRITE:
84*7c4213f6SStephen Warren 		n = mmc->block_dev.block_write(&mmc->block_dev, blk_start,
857d0b605aSŁukasz Majewski 					       blk_count, buf);
867d0b605aSŁukasz Majewski 		break;
877d0b605aSŁukasz Majewski 	default:
887d0b605aSŁukasz Majewski 		error("Operation not supported\n");
897d0b605aSŁukasz Majewski 	}
90cb383cd2SLukasz Majewski 
917d0b605aSŁukasz Majewski 	if (n != blk_count) {
927d0b605aSŁukasz Majewski 		error("MMC operation failed");
93c8151b4aSLukasz Majewski 		if (dfu->data.mmc.hw_partition >= 0)
94c8151b4aSLukasz Majewski 			mmc_access_part(dfu, mmc, part_num_bkp);
957d0b605aSŁukasz Majewski 		return -EIO;
967d0b605aSŁukasz Majewski 	}
977d0b605aSŁukasz Majewski 
98c8151b4aSLukasz Majewski 	if (dfu->data.mmc.hw_partition >= 0) {
99c8151b4aSLukasz Majewski 		ret = mmc_access_part(dfu, mmc, part_num_bkp);
100c8151b4aSLukasz Majewski 		if (ret)
101c8151b4aSLukasz Majewski 			return ret;
102c8151b4aSLukasz Majewski 	}
103c8151b4aSLukasz Majewski 
1047d0b605aSŁukasz Majewski 	return 0;
105cb383cd2SLukasz Majewski }
106cb383cd2SLukasz Majewski 
107ea2453d5SPantelis Antoniou static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len)
108cb383cd2SLukasz Majewski {
109ea2453d5SPantelis Antoniou 	if (dfu_file_buf_len + *len > CONFIG_SYS_DFU_MAX_FILE_SIZE) {
110ea2453d5SPantelis Antoniou 		dfu_file_buf_len = 0;
111ea2453d5SPantelis Antoniou 		return -EINVAL;
112cb383cd2SLukasz Majewski 	}
113cb383cd2SLukasz Majewski 
114ea2453d5SPantelis Antoniou 	/* Add to the current buffer. */
115ea2453d5SPantelis Antoniou 	memcpy(dfu_file_buf + dfu_file_buf_len, buf, *len);
116ea2453d5SPantelis Antoniou 	dfu_file_buf_len += *len;
117ea2453d5SPantelis Antoniou 
118ea2453d5SPantelis Antoniou 	return 0;
119cb383cd2SLukasz Majewski }
120cb383cd2SLukasz Majewski 
1215a127c84SAfzal Mohammed static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
122cb383cd2SLukasz Majewski 			void *buf, long *len)
123cb383cd2SLukasz Majewski {
1240e285b50SStephen Warren 	const char *fsname, *opname;
125cb383cd2SLukasz Majewski 	char cmd_buf[DFU_CMD_BUF_SIZE];
126cb383cd2SLukasz Majewski 	char *str_env;
127cb383cd2SLukasz Majewski 	int ret;
128cb383cd2SLukasz Majewski 
12943e66272SŁukasz Majewski 	switch (dfu->layout) {
13043e66272SŁukasz Majewski 	case DFU_FS_FAT:
1310e285b50SStephen Warren 		fsname = "fat";
13243e66272SŁukasz Majewski 		break;
13343e66272SŁukasz Majewski 	case DFU_FS_EXT4:
1340e285b50SStephen Warren 		fsname = "ext4";
13543e66272SŁukasz Majewski 		break;
13643e66272SŁukasz Majewski 	default:
13743e66272SŁukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
13843e66272SŁukasz Majewski 		       dfu_get_layout(dfu->layout));
139ea2453d5SPantelis Antoniou 		return -1;
14043e66272SŁukasz Majewski 	}
141cb383cd2SLukasz Majewski 
1420e285b50SStephen Warren 	switch (op) {
1430e285b50SStephen Warren 	case DFU_OP_READ:
1440e285b50SStephen Warren 		opname = "load";
1450e285b50SStephen Warren 		break;
1460e285b50SStephen Warren 	case DFU_OP_WRITE:
1470e285b50SStephen Warren 		opname = "write";
1480e285b50SStephen Warren 		break;
1490e285b50SStephen Warren 	case DFU_OP_SIZE:
1500e285b50SStephen Warren 		opname = "size";
1510e285b50SStephen Warren 		break;
1520e285b50SStephen Warren 	default:
1530e285b50SStephen Warren 		return -1;
1540e285b50SStephen Warren 	}
1550e285b50SStephen Warren 
1560e285b50SStephen Warren 	sprintf(cmd_buf, "%s%s mmc %d:%d", fsname, opname,
1570e285b50SStephen Warren 		dfu->data.mmc.dev, dfu->data.mmc.part);
1580e285b50SStephen Warren 
1590e285b50SStephen Warren 	if (op != DFU_OP_SIZE)
160e621c7abSStephen Warren 		sprintf(cmd_buf + strlen(cmd_buf), " %p", buf);
1610e285b50SStephen Warren 
1620e285b50SStephen Warren 	sprintf(cmd_buf + strlen(cmd_buf), " %s", dfu->name);
1630e285b50SStephen Warren 
16417eb1d8fSLukasz Majewski 	if (op == DFU_OP_WRITE)
16517eb1d8fSLukasz Majewski 		sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len);
16617eb1d8fSLukasz Majewski 
167cb383cd2SLukasz Majewski 	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
168cb383cd2SLukasz Majewski 
169cb383cd2SLukasz Majewski 	ret = run_command(cmd_buf, 0);
170cb383cd2SLukasz Majewski 	if (ret) {
171cb383cd2SLukasz Majewski 		puts("dfu: Read error!\n");
172cb383cd2SLukasz Majewski 		return ret;
173cb383cd2SLukasz Majewski 	}
174cb383cd2SLukasz Majewski 
1750e285b50SStephen Warren 	if (op != DFU_OP_WRITE) {
176cb383cd2SLukasz Majewski 		str_env = getenv("filesize");
177cb383cd2SLukasz Majewski 		if (str_env == NULL) {
178cb383cd2SLukasz Majewski 			puts("dfu: Wrong file size!\n");
179cb383cd2SLukasz Majewski 			return -1;
180cb383cd2SLukasz Majewski 		}
181cb383cd2SLukasz Majewski 		*len = simple_strtoul(str_env, NULL, 16);
182cb383cd2SLukasz Majewski 	}
183cb383cd2SLukasz Majewski 
184cb383cd2SLukasz Majewski 	return ret;
185cb383cd2SLukasz Majewski }
186cb383cd2SLukasz Majewski 
187ea2453d5SPantelis Antoniou int dfu_write_medium_mmc(struct dfu_entity *dfu,
188ea2453d5SPantelis Antoniou 		u64 offset, void *buf, long *len)
189cb383cd2SLukasz Majewski {
190cb383cd2SLukasz Majewski 	int ret = -1;
191cb383cd2SLukasz Majewski 
192cb383cd2SLukasz Majewski 	switch (dfu->layout) {
193cb383cd2SLukasz Majewski 	case DFU_RAW_ADDR:
194ea2453d5SPantelis Antoniou 		ret = mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
195cb383cd2SLukasz Majewski 		break;
196cb383cd2SLukasz Majewski 	case DFU_FS_FAT:
19743e66272SŁukasz Majewski 	case DFU_FS_EXT4:
198ea2453d5SPantelis Antoniou 		ret = mmc_file_buffer(dfu, buf, len);
199cb383cd2SLukasz Majewski 		break;
200cb383cd2SLukasz Majewski 	default:
201cb383cd2SLukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
202cb383cd2SLukasz Majewski 		       dfu_get_layout(dfu->layout));
203cb383cd2SLukasz Majewski 	}
204cb383cd2SLukasz Majewski 
205cb383cd2SLukasz Majewski 	return ret;
206cb383cd2SLukasz Majewski }
207cb383cd2SLukasz Majewski 
208ea2453d5SPantelis Antoniou int dfu_flush_medium_mmc(struct dfu_entity *dfu)
209ea2453d5SPantelis Antoniou {
210ea2453d5SPantelis Antoniou 	int ret = 0;
211ea2453d5SPantelis Antoniou 
212ea2453d5SPantelis Antoniou 	if (dfu->layout != DFU_RAW_ADDR) {
213ea2453d5SPantelis Antoniou 		/* Do stuff here. */
21441ac233cSPrzemyslaw Marczak 		ret = mmc_file_op(DFU_OP_WRITE, dfu, dfu_file_buf,
215ea2453d5SPantelis Antoniou 				&dfu_file_buf_len);
216ea2453d5SPantelis Antoniou 
217ea2453d5SPantelis Antoniou 		/* Now that we're done */
218ea2453d5SPantelis Antoniou 		dfu_file_buf_len = 0;
219ea2453d5SPantelis Antoniou 	}
220ea2453d5SPantelis Antoniou 
221ea2453d5SPantelis Antoniou 	return ret;
222ea2453d5SPantelis Antoniou }
223ea2453d5SPantelis Antoniou 
2240e285b50SStephen Warren long dfu_get_medium_size_mmc(struct dfu_entity *dfu)
2250e285b50SStephen Warren {
2260e285b50SStephen Warren 	int ret;
2270e285b50SStephen Warren 	long len;
2280e285b50SStephen Warren 
2290e285b50SStephen Warren 	switch (dfu->layout) {
2300e285b50SStephen Warren 	case DFU_RAW_ADDR:
2310e285b50SStephen Warren 		return dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size;
2320e285b50SStephen Warren 	case DFU_FS_FAT:
2330e285b50SStephen Warren 	case DFU_FS_EXT4:
234411c5e57SStephen Warren 		dfu_file_buf_filled = -1;
2350e285b50SStephen Warren 		ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, &len);
2360e285b50SStephen Warren 		if (ret < 0)
2370e285b50SStephen Warren 			return ret;
238411c5e57SStephen Warren 		if (len > CONFIG_SYS_DFU_MAX_FILE_SIZE)
239411c5e57SStephen Warren 			return -1;
2400e285b50SStephen Warren 		return len;
2410e285b50SStephen Warren 	default:
2420e285b50SStephen Warren 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
2430e285b50SStephen Warren 		       dfu_get_layout(dfu->layout));
2440e285b50SStephen Warren 		return -1;
2450e285b50SStephen Warren 	}
2460e285b50SStephen Warren }
2470e285b50SStephen Warren 
248411c5e57SStephen Warren static int mmc_file_unbuffer(struct dfu_entity *dfu, u64 offset, void *buf,
249411c5e57SStephen Warren 			     long *len)
250411c5e57SStephen Warren {
251411c5e57SStephen Warren 	int ret;
252411c5e57SStephen Warren 	long file_len;
253411c5e57SStephen Warren 
254411c5e57SStephen Warren 	if (dfu_file_buf_filled == -1) {
255411c5e57SStephen Warren 		ret = mmc_file_op(DFU_OP_READ, dfu, dfu_file_buf, &file_len);
256411c5e57SStephen Warren 		if (ret < 0)
257411c5e57SStephen Warren 			return ret;
258411c5e57SStephen Warren 		dfu_file_buf_filled = file_len;
259411c5e57SStephen Warren 	}
260411c5e57SStephen Warren 	if (offset + *len > dfu_file_buf_filled)
261411c5e57SStephen Warren 		return -EINVAL;
262411c5e57SStephen Warren 
263411c5e57SStephen Warren 	/* Add to the current buffer. */
264411c5e57SStephen Warren 	memcpy(buf, dfu_file_buf + offset, *len);
265411c5e57SStephen Warren 
266411c5e57SStephen Warren 	return 0;
267411c5e57SStephen Warren }
268411c5e57SStephen Warren 
269ea2453d5SPantelis Antoniou int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
270ea2453d5SPantelis Antoniou 		long *len)
271cb383cd2SLukasz Majewski {
272cb383cd2SLukasz Majewski 	int ret = -1;
273cb383cd2SLukasz Majewski 
274cb383cd2SLukasz Majewski 	switch (dfu->layout) {
275cb383cd2SLukasz Majewski 	case DFU_RAW_ADDR:
276ea2453d5SPantelis Antoniou 		ret = mmc_block_op(DFU_OP_READ, dfu, offset, buf, len);
277cb383cd2SLukasz Majewski 		break;
278cb383cd2SLukasz Majewski 	case DFU_FS_FAT:
27943e66272SŁukasz Majewski 	case DFU_FS_EXT4:
280411c5e57SStephen Warren 		ret = mmc_file_unbuffer(dfu, offset, buf, len);
281cb383cd2SLukasz Majewski 		break;
282cb383cd2SLukasz Majewski 	default:
283cb383cd2SLukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
284cb383cd2SLukasz Majewski 		       dfu_get_layout(dfu->layout));
285cb383cd2SLukasz Majewski 	}
286cb383cd2SLukasz Majewski 
287cb383cd2SLukasz Majewski 	return ret;
288cb383cd2SLukasz Majewski }
289cb383cd2SLukasz Majewski 
29041ac233cSPrzemyslaw Marczak void dfu_free_entity_mmc(struct dfu_entity *dfu)
29141ac233cSPrzemyslaw Marczak {
29241ac233cSPrzemyslaw Marczak 	if (dfu_file_buf) {
29341ac233cSPrzemyslaw Marczak 		free(dfu_file_buf);
29441ac233cSPrzemyslaw Marczak 		dfu_file_buf = NULL;
29541ac233cSPrzemyslaw Marczak 	}
29641ac233cSPrzemyslaw Marczak }
29741ac233cSPrzemyslaw Marczak 
298711b931fSMateusz Zalega /*
299711b931fSMateusz Zalega  * @param s Parameter string containing space-separated arguments:
300711b931fSMateusz Zalega  *	1st:
301711b931fSMateusz Zalega  *		raw	(raw read/write)
302711b931fSMateusz Zalega  *		fat	(files)
303711b931fSMateusz Zalega  *		ext4	(^)
304711b931fSMateusz Zalega  *		part	(partition image)
305711b931fSMateusz Zalega  *	2nd and 3rd:
306711b931fSMateusz Zalega  *		lba_start and lba_size, for raw write
307711b931fSMateusz Zalega  *		mmc_dev and mmc_part, for filesystems and part
308c8151b4aSLukasz Majewski  *	4th (optional):
309c8151b4aSLukasz Majewski  *		mmcpart <num> (access to HW eMMC partitions)
310711b931fSMateusz Zalega  */
311dd64827eSStephen Warren int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s)
312cb383cd2SLukasz Majewski {
313711b931fSMateusz Zalega 	const char *entity_type;
314711b931fSMateusz Zalega 	size_t second_arg;
315711b931fSMateusz Zalega 	size_t third_arg;
316711b931fSMateusz Zalega 
3171b6ca18bSPantelis Antoniou 	struct mmc *mmc;
318711b931fSMateusz Zalega 
319711b931fSMateusz Zalega 	const char *argv[3];
320711b931fSMateusz Zalega 	const char **parg = argv;
321711b931fSMateusz Zalega 
322dd64827eSStephen Warren 	dfu->data.mmc.dev_num = simple_strtoul(devstr, NULL, 10);
323dd64827eSStephen Warren 
324711b931fSMateusz Zalega 	for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
325711b931fSMateusz Zalega 		*parg = strsep(&s, " ");
326711b931fSMateusz Zalega 		if (*parg == NULL) {
327711b931fSMateusz Zalega 			error("Invalid number of arguments.\n");
328711b931fSMateusz Zalega 			return -ENODEV;
329711b931fSMateusz Zalega 		}
330711b931fSMateusz Zalega 	}
331711b931fSMateusz Zalega 
332711b931fSMateusz Zalega 	entity_type = argv[0];
333b7d4259aSMateusz Zalega 	/*
334b7d4259aSMateusz Zalega 	 * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8,
335b7d4259aSMateusz Zalega 	 * with default 10.
336b7d4259aSMateusz Zalega 	 */
337b7d4259aSMateusz Zalega 	second_arg = simple_strtoul(argv[1], NULL, 0);
338b7d4259aSMateusz Zalega 	third_arg = simple_strtoul(argv[2], NULL, 0);
339711b931fSMateusz Zalega 
340dd64827eSStephen Warren 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
341711b931fSMateusz Zalega 	if (mmc == NULL) {
342dd64827eSStephen Warren 		error("Couldn't find MMC device no. %d.\n",
343dd64827eSStephen Warren 		      dfu->data.mmc.dev_num);
344711b931fSMateusz Zalega 		return -ENODEV;
345711b931fSMateusz Zalega 	}
346711b931fSMateusz Zalega 
347711b931fSMateusz Zalega 	if (mmc_init(mmc)) {
348711b931fSMateusz Zalega 		error("Couldn't init MMC device.\n");
349711b931fSMateusz Zalega 		return -ENODEV;
350711b931fSMateusz Zalega 	}
351711b931fSMateusz Zalega 
352c8151b4aSLukasz Majewski 	dfu->data.mmc.hw_partition = -EINVAL;
353711b931fSMateusz Zalega 	if (!strcmp(entity_type, "raw")) {
354711b931fSMateusz Zalega 		dfu->layout			= DFU_RAW_ADDR;
355711b931fSMateusz Zalega 		dfu->data.mmc.lba_start		= second_arg;
356711b931fSMateusz Zalega 		dfu->data.mmc.lba_size		= third_arg;
357711b931fSMateusz Zalega 		dfu->data.mmc.lba_blk_size	= mmc->read_bl_len;
358c8151b4aSLukasz Majewski 
359c8151b4aSLukasz Majewski 		/*
360c8151b4aSLukasz Majewski 		 * Check for an extra entry at dfu_alt_info env variable
361c8151b4aSLukasz Majewski 		 * specifying the mmc HW defined partition number
362c8151b4aSLukasz Majewski 		 */
363c8151b4aSLukasz Majewski 		if (s)
364c8151b4aSLukasz Majewski 			if (!strcmp(strsep(&s, " "), "mmcpart"))
365c8151b4aSLukasz Majewski 				dfu->data.mmc.hw_partition =
366c8151b4aSLukasz Majewski 					simple_strtoul(s, NULL, 0);
367c8151b4aSLukasz Majewski 
368711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "part")) {
3691b6ca18bSPantelis Antoniou 		disk_partition_t partinfo;
370711b931fSMateusz Zalega 		block_dev_desc_t *blk_dev = &mmc->block_dev;
371711b931fSMateusz Zalega 		int mmcdev = second_arg;
372711b931fSMateusz Zalega 		int mmcpart = third_arg;
373cb383cd2SLukasz Majewski 
374711b931fSMateusz Zalega 		if (get_partition_info(blk_dev, mmcpart, &partinfo) != 0) {
375711b931fSMateusz Zalega 			error("Couldn't find part #%d on mmc device #%d\n",
376711b931fSMateusz Zalega 			      mmcpart, mmcdev);
3771b6ca18bSPantelis Antoniou 			return -ENODEV;
3781b6ca18bSPantelis Antoniou 		}
3791b6ca18bSPantelis Antoniou 
380711b931fSMateusz Zalega 		dfu->layout			= DFU_RAW_ADDR;
3811b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_start		= partinfo.start;
3821b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_size		= partinfo.size;
3831b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_blk_size	= partinfo.blksz;
384711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "fat")) {
385711b931fSMateusz Zalega 		dfu->layout = DFU_FS_FAT;
386711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "ext4")) {
387711b931fSMateusz Zalega 		dfu->layout = DFU_FS_EXT4;
388cb383cd2SLukasz Majewski 	} else {
389711b931fSMateusz Zalega 		error("Memory layout (%s) not supported!\n", entity_type);
3901b6ca18bSPantelis Antoniou 		return -ENODEV;
391cb383cd2SLukasz Majewski 	}
392cb383cd2SLukasz Majewski 
393711b931fSMateusz Zalega 	/* if it's NOT a raw write */
394711b931fSMateusz Zalega 	if (strcmp(entity_type, "raw")) {
395711b931fSMateusz Zalega 		dfu->data.mmc.dev = second_arg;
396711b931fSMateusz Zalega 		dfu->data.mmc.part = third_arg;
39743e66272SŁukasz Majewski 	}
39843e66272SŁukasz Majewski 
399711b931fSMateusz Zalega 	dfu->dev_type = DFU_DEV_MMC;
4000e285b50SStephen Warren 	dfu->get_medium_size = dfu_get_medium_size_mmc;
401cb383cd2SLukasz Majewski 	dfu->read_medium = dfu_read_medium_mmc;
402cb383cd2SLukasz Majewski 	dfu->write_medium = dfu_write_medium_mmc;
403ea2453d5SPantelis Antoniou 	dfu->flush_medium = dfu_flush_medium_mmc;
404ea2453d5SPantelis Antoniou 	dfu->inited = 0;
40541ac233cSPrzemyslaw Marczak 	dfu->free_entity = dfu_free_entity_mmc;
40641ac233cSPrzemyslaw Marczak 
40741ac233cSPrzemyslaw Marczak 	/* Check if file buffer is ready */
40841ac233cSPrzemyslaw Marczak 	if (!dfu_file_buf) {
40941ac233cSPrzemyslaw Marczak 		dfu_file_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
41041ac233cSPrzemyslaw Marczak 					CONFIG_SYS_DFU_MAX_FILE_SIZE);
41141ac233cSPrzemyslaw Marczak 		if (!dfu_file_buf) {
41241ac233cSPrzemyslaw Marczak 			error("Could not memalign 0x%x bytes",
41341ac233cSPrzemyslaw Marczak 			      CONFIG_SYS_DFU_MAX_FILE_SIZE);
41441ac233cSPrzemyslaw Marczak 			return -ENOMEM;
41541ac233cSPrzemyslaw Marczak 		}
41641ac233cSPrzemyslaw Marczak 	}
417cb383cd2SLukasz Majewski 
418cb383cd2SLukasz Majewski 	return 0;
419cb383cd2SLukasz Majewski }
420