xref: /rk3399_rockchip-uboot/drivers/dfu/dfu_mmc.c (revision 0e285b503c41bb53f6ef962e6f9c942c1ca47cc6)
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>
15*0e285b50SStephen Warren #include <ext4fs.h>
16*0e285b50SStephen Warren #include <fat.h>
177d0b605aSŁukasz Majewski #include <mmc.h>
18cb383cd2SLukasz Majewski 
19ea2453d5SPantelis Antoniou static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
20ea2453d5SPantelis Antoniou 				dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE];
21ea2453d5SPantelis Antoniou static long dfu_file_buf_len;
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 
30c8151b4aSLukasz Majewski 	ret = mmc_switch_part(dfu->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 {
437d0b605aSŁukasz Majewski 	struct mmc *mmc = find_mmc_device(dfu->dev_num);
447d0b605aSŁukasz Majewski 	u32 blk_start, blk_count, n = 0;
45c8151b4aSLukasz Majewski 	int ret, part_num_bkp = 0;
46cb383cd2SLukasz Majewski 
47ea2453d5SPantelis Antoniou 	/*
48ea2453d5SPantelis Antoniou 	 * We must ensure that we work in lba_blk_size chunks, so ALIGN
49ea2453d5SPantelis Antoniou 	 * this value.
50ea2453d5SPantelis Antoniou 	 */
51ea2453d5SPantelis Antoniou 	*len = ALIGN(*len, dfu->data.mmc.lba_blk_size);
52ea2453d5SPantelis Antoniou 
53ea2453d5SPantelis Antoniou 	blk_start = dfu->data.mmc.lba_start +
54ea2453d5SPantelis Antoniou 			(u32)lldiv(offset, dfu->data.mmc.lba_blk_size);
55ea2453d5SPantelis Antoniou 	blk_count = *len / dfu->data.mmc.lba_blk_size;
56ea2453d5SPantelis Antoniou 	if (blk_start + blk_count >
57ea2453d5SPantelis Antoniou 			dfu->data.mmc.lba_start + dfu->data.mmc.lba_size) {
58ea2453d5SPantelis Antoniou 		puts("Request would exceed designated area!\n");
59ea2453d5SPantelis Antoniou 		return -EINVAL;
60ea2453d5SPantelis Antoniou 	}
61ea2453d5SPantelis Antoniou 
62c8151b4aSLukasz Majewski 	if (dfu->data.mmc.hw_partition >= 0) {
63c8151b4aSLukasz Majewski 		part_num_bkp = mmc->part_num;
64c8151b4aSLukasz Majewski 		ret = mmc_access_part(dfu, mmc, dfu->data.mmc.hw_partition);
65c8151b4aSLukasz Majewski 		if (ret)
66c8151b4aSLukasz Majewski 			return ret;
67c8151b4aSLukasz Majewski 	}
68c8151b4aSLukasz Majewski 
697d0b605aSŁukasz Majewski 	debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
707d0b605aSŁukasz Majewski 	      op == DFU_OP_READ ? "MMC READ" : "MMC WRITE", dfu->dev_num,
717d0b605aSŁukasz Majewski 	      blk_start, blk_count, buf);
727d0b605aSŁukasz Majewski 	switch (op) {
737d0b605aSŁukasz Majewski 	case DFU_OP_READ:
747d0b605aSŁukasz Majewski 		n = mmc->block_dev.block_read(dfu->dev_num, blk_start,
757d0b605aSŁukasz Majewski 					      blk_count, buf);
767d0b605aSŁukasz Majewski 		break;
777d0b605aSŁukasz Majewski 	case DFU_OP_WRITE:
787d0b605aSŁukasz Majewski 		n = mmc->block_dev.block_write(dfu->dev_num, blk_start,
797d0b605aSŁukasz Majewski 					       blk_count, buf);
807d0b605aSŁukasz Majewski 		break;
817d0b605aSŁukasz Majewski 	default:
827d0b605aSŁukasz Majewski 		error("Operation not supported\n");
837d0b605aSŁukasz Majewski 	}
84cb383cd2SLukasz Majewski 
857d0b605aSŁukasz Majewski 	if (n != blk_count) {
867d0b605aSŁukasz Majewski 		error("MMC operation failed");
87c8151b4aSLukasz Majewski 		if (dfu->data.mmc.hw_partition >= 0)
88c8151b4aSLukasz Majewski 			mmc_access_part(dfu, mmc, part_num_bkp);
897d0b605aSŁukasz Majewski 		return -EIO;
907d0b605aSŁukasz Majewski 	}
917d0b605aSŁukasz Majewski 
92c8151b4aSLukasz Majewski 	if (dfu->data.mmc.hw_partition >= 0) {
93c8151b4aSLukasz Majewski 		ret = mmc_access_part(dfu, mmc, part_num_bkp);
94c8151b4aSLukasz Majewski 		if (ret)
95c8151b4aSLukasz Majewski 			return ret;
96c8151b4aSLukasz Majewski 	}
97c8151b4aSLukasz Majewski 
987d0b605aSŁukasz Majewski 	return 0;
99cb383cd2SLukasz Majewski }
100cb383cd2SLukasz Majewski 
101ea2453d5SPantelis Antoniou static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len)
102cb383cd2SLukasz Majewski {
103ea2453d5SPantelis Antoniou 	if (dfu_file_buf_len + *len > CONFIG_SYS_DFU_MAX_FILE_SIZE) {
104ea2453d5SPantelis Antoniou 		dfu_file_buf_len = 0;
105ea2453d5SPantelis Antoniou 		return -EINVAL;
106cb383cd2SLukasz Majewski 	}
107cb383cd2SLukasz Majewski 
108ea2453d5SPantelis Antoniou 	/* Add to the current buffer. */
109ea2453d5SPantelis Antoniou 	memcpy(dfu_file_buf + dfu_file_buf_len, buf, *len);
110ea2453d5SPantelis Antoniou 	dfu_file_buf_len += *len;
111ea2453d5SPantelis Antoniou 
112ea2453d5SPantelis Antoniou 	return 0;
113cb383cd2SLukasz Majewski }
114cb383cd2SLukasz Majewski 
1155a127c84SAfzal Mohammed static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
116cb383cd2SLukasz Majewski 			void *buf, long *len)
117cb383cd2SLukasz Majewski {
118*0e285b50SStephen Warren 	const char *fsname, *opname;
119cb383cd2SLukasz Majewski 	char cmd_buf[DFU_CMD_BUF_SIZE];
120cb383cd2SLukasz Majewski 	char *str_env;
121cb383cd2SLukasz Majewski 	int ret;
122cb383cd2SLukasz Majewski 
12343e66272SŁukasz Majewski 	switch (dfu->layout) {
12443e66272SŁukasz Majewski 	case DFU_FS_FAT:
125*0e285b50SStephen Warren 		fsname = "fat";
12643e66272SŁukasz Majewski 		break;
12743e66272SŁukasz Majewski 	case DFU_FS_EXT4:
128*0e285b50SStephen Warren 		fsname = "ext4";
12943e66272SŁukasz Majewski 		break;
13043e66272SŁukasz Majewski 	default:
13143e66272SŁukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
13243e66272SŁukasz Majewski 		       dfu_get_layout(dfu->layout));
133ea2453d5SPantelis Antoniou 		return -1;
13443e66272SŁukasz Majewski 	}
135cb383cd2SLukasz Majewski 
136*0e285b50SStephen Warren 	switch (op) {
137*0e285b50SStephen Warren 	case DFU_OP_READ:
138*0e285b50SStephen Warren 		opname = "load";
139*0e285b50SStephen Warren 		break;
140*0e285b50SStephen Warren 	case DFU_OP_WRITE:
141*0e285b50SStephen Warren 		opname = "write";
142*0e285b50SStephen Warren 		break;
143*0e285b50SStephen Warren 	case DFU_OP_SIZE:
144*0e285b50SStephen Warren 		opname = "size";
145*0e285b50SStephen Warren 		break;
146*0e285b50SStephen Warren 	default:
147*0e285b50SStephen Warren 		return -1;
148*0e285b50SStephen Warren 	}
149*0e285b50SStephen Warren 
150*0e285b50SStephen Warren 	sprintf(cmd_buf, "%s%s mmc %d:%d", fsname, opname,
151*0e285b50SStephen Warren 		dfu->data.mmc.dev, dfu->data.mmc.part);
152*0e285b50SStephen Warren 
153*0e285b50SStephen Warren 	if (op != DFU_OP_SIZE)
154*0e285b50SStephen Warren 		sprintf(cmd_buf + strlen(cmd_buf), " 0x%x", (unsigned int)buf);
155*0e285b50SStephen Warren 
156*0e285b50SStephen Warren 	sprintf(cmd_buf + strlen(cmd_buf), " %s", dfu->name);
157*0e285b50SStephen Warren 
15817eb1d8fSLukasz Majewski 	if (op == DFU_OP_WRITE)
15917eb1d8fSLukasz Majewski 		sprintf(cmd_buf + strlen(cmd_buf), " %lx", *len);
16017eb1d8fSLukasz Majewski 
161cb383cd2SLukasz Majewski 	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
162cb383cd2SLukasz Majewski 
163cb383cd2SLukasz Majewski 	ret = run_command(cmd_buf, 0);
164cb383cd2SLukasz Majewski 	if (ret) {
165cb383cd2SLukasz Majewski 		puts("dfu: Read error!\n");
166cb383cd2SLukasz Majewski 		return ret;
167cb383cd2SLukasz Majewski 	}
168cb383cd2SLukasz Majewski 
169*0e285b50SStephen Warren 	if (op != DFU_OP_WRITE) {
170cb383cd2SLukasz Majewski 		str_env = getenv("filesize");
171cb383cd2SLukasz Majewski 		if (str_env == NULL) {
172cb383cd2SLukasz Majewski 			puts("dfu: Wrong file size!\n");
173cb383cd2SLukasz Majewski 			return -1;
174cb383cd2SLukasz Majewski 		}
175cb383cd2SLukasz Majewski 		*len = simple_strtoul(str_env, NULL, 16);
176cb383cd2SLukasz Majewski 	}
177cb383cd2SLukasz Majewski 
178cb383cd2SLukasz Majewski 	return ret;
179cb383cd2SLukasz Majewski }
180cb383cd2SLukasz Majewski 
181ea2453d5SPantelis Antoniou int dfu_write_medium_mmc(struct dfu_entity *dfu,
182ea2453d5SPantelis Antoniou 		u64 offset, void *buf, long *len)
183cb383cd2SLukasz Majewski {
184cb383cd2SLukasz Majewski 	int ret = -1;
185cb383cd2SLukasz Majewski 
186cb383cd2SLukasz Majewski 	switch (dfu->layout) {
187cb383cd2SLukasz Majewski 	case DFU_RAW_ADDR:
188ea2453d5SPantelis Antoniou 		ret = mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
189cb383cd2SLukasz Majewski 		break;
190cb383cd2SLukasz Majewski 	case DFU_FS_FAT:
19143e66272SŁukasz Majewski 	case DFU_FS_EXT4:
192ea2453d5SPantelis Antoniou 		ret = mmc_file_buffer(dfu, buf, len);
193cb383cd2SLukasz Majewski 		break;
194cb383cd2SLukasz Majewski 	default:
195cb383cd2SLukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
196cb383cd2SLukasz Majewski 		       dfu_get_layout(dfu->layout));
197cb383cd2SLukasz Majewski 	}
198cb383cd2SLukasz Majewski 
199cb383cd2SLukasz Majewski 	return ret;
200cb383cd2SLukasz Majewski }
201cb383cd2SLukasz Majewski 
202ea2453d5SPantelis Antoniou int dfu_flush_medium_mmc(struct dfu_entity *dfu)
203ea2453d5SPantelis Antoniou {
204ea2453d5SPantelis Antoniou 	int ret = 0;
205ea2453d5SPantelis Antoniou 
206ea2453d5SPantelis Antoniou 	if (dfu->layout != DFU_RAW_ADDR) {
207ea2453d5SPantelis Antoniou 		/* Do stuff here. */
208ea2453d5SPantelis Antoniou 		ret = mmc_file_op(DFU_OP_WRITE, dfu, &dfu_file_buf,
209ea2453d5SPantelis Antoniou 				&dfu_file_buf_len);
210ea2453d5SPantelis Antoniou 
211ea2453d5SPantelis Antoniou 		/* Now that we're done */
212ea2453d5SPantelis Antoniou 		dfu_file_buf_len = 0;
213ea2453d5SPantelis Antoniou 	}
214ea2453d5SPantelis Antoniou 
215ea2453d5SPantelis Antoniou 	return ret;
216ea2453d5SPantelis Antoniou }
217ea2453d5SPantelis Antoniou 
218*0e285b50SStephen Warren long dfu_get_medium_size_mmc(struct dfu_entity *dfu)
219*0e285b50SStephen Warren {
220*0e285b50SStephen Warren 	int ret;
221*0e285b50SStephen Warren 	long len;
222*0e285b50SStephen Warren 
223*0e285b50SStephen Warren 	switch (dfu->layout) {
224*0e285b50SStephen Warren 	case DFU_RAW_ADDR:
225*0e285b50SStephen Warren 		return dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size;
226*0e285b50SStephen Warren 	case DFU_FS_FAT:
227*0e285b50SStephen Warren 	case DFU_FS_EXT4:
228*0e285b50SStephen Warren 		ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, &len);
229*0e285b50SStephen Warren 		if (ret < 0)
230*0e285b50SStephen Warren 			return ret;
231*0e285b50SStephen Warren 		return len;
232*0e285b50SStephen Warren 	default:
233*0e285b50SStephen Warren 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
234*0e285b50SStephen Warren 		       dfu_get_layout(dfu->layout));
235*0e285b50SStephen Warren 		return -1;
236*0e285b50SStephen Warren 	}
237*0e285b50SStephen Warren }
238*0e285b50SStephen Warren 
239ea2453d5SPantelis Antoniou int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
240ea2453d5SPantelis Antoniou 		long *len)
241cb383cd2SLukasz Majewski {
242cb383cd2SLukasz Majewski 	int ret = -1;
243cb383cd2SLukasz Majewski 
244cb383cd2SLukasz Majewski 	switch (dfu->layout) {
245cb383cd2SLukasz Majewski 	case DFU_RAW_ADDR:
246ea2453d5SPantelis Antoniou 		ret = mmc_block_op(DFU_OP_READ, dfu, offset, buf, len);
247cb383cd2SLukasz Majewski 		break;
248cb383cd2SLukasz Majewski 	case DFU_FS_FAT:
24943e66272SŁukasz Majewski 	case DFU_FS_EXT4:
250ea2453d5SPantelis Antoniou 		ret = mmc_file_op(DFU_OP_READ, dfu, buf, len);
251cb383cd2SLukasz Majewski 		break;
252cb383cd2SLukasz Majewski 	default:
253cb383cd2SLukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
254cb383cd2SLukasz Majewski 		       dfu_get_layout(dfu->layout));
255cb383cd2SLukasz Majewski 	}
256cb383cd2SLukasz Majewski 
257cb383cd2SLukasz Majewski 	return ret;
258cb383cd2SLukasz Majewski }
259cb383cd2SLukasz Majewski 
260711b931fSMateusz Zalega /*
261711b931fSMateusz Zalega  * @param s Parameter string containing space-separated arguments:
262711b931fSMateusz Zalega  *	1st:
263711b931fSMateusz Zalega  *		raw	(raw read/write)
264711b931fSMateusz Zalega  *		fat	(files)
265711b931fSMateusz Zalega  *		ext4	(^)
266711b931fSMateusz Zalega  *		part	(partition image)
267711b931fSMateusz Zalega  *	2nd and 3rd:
268711b931fSMateusz Zalega  *		lba_start and lba_size, for raw write
269711b931fSMateusz Zalega  *		mmc_dev and mmc_part, for filesystems and part
270c8151b4aSLukasz Majewski  *	4th (optional):
271c8151b4aSLukasz Majewski  *		mmcpart <num> (access to HW eMMC partitions)
272711b931fSMateusz Zalega  */
273cb383cd2SLukasz Majewski int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
274cb383cd2SLukasz Majewski {
275711b931fSMateusz Zalega 	const char *entity_type;
276711b931fSMateusz Zalega 	size_t second_arg;
277711b931fSMateusz Zalega 	size_t third_arg;
278711b931fSMateusz Zalega 
2791b6ca18bSPantelis Antoniou 	struct mmc *mmc;
280711b931fSMateusz Zalega 
281711b931fSMateusz Zalega 	const char *argv[3];
282711b931fSMateusz Zalega 	const char **parg = argv;
283711b931fSMateusz Zalega 
284711b931fSMateusz Zalega 	for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
285711b931fSMateusz Zalega 		*parg = strsep(&s, " ");
286711b931fSMateusz Zalega 		if (*parg == NULL) {
287711b931fSMateusz Zalega 			error("Invalid number of arguments.\n");
288711b931fSMateusz Zalega 			return -ENODEV;
289711b931fSMateusz Zalega 		}
290711b931fSMateusz Zalega 	}
291711b931fSMateusz Zalega 
292711b931fSMateusz Zalega 	entity_type = argv[0];
293b7d4259aSMateusz Zalega 	/*
294b7d4259aSMateusz Zalega 	 * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8,
295b7d4259aSMateusz Zalega 	 * with default 10.
296b7d4259aSMateusz Zalega 	 */
297b7d4259aSMateusz Zalega 	second_arg = simple_strtoul(argv[1], NULL, 0);
298b7d4259aSMateusz Zalega 	third_arg = simple_strtoul(argv[2], NULL, 0);
299711b931fSMateusz Zalega 
300711b931fSMateusz Zalega 	mmc = find_mmc_device(dfu->dev_num);
301711b931fSMateusz Zalega 	if (mmc == NULL) {
302711b931fSMateusz Zalega 		error("Couldn't find MMC device no. %d.\n", dfu->dev_num);
303711b931fSMateusz Zalega 		return -ENODEV;
304711b931fSMateusz Zalega 	}
305711b931fSMateusz Zalega 
306711b931fSMateusz Zalega 	if (mmc_init(mmc)) {
307711b931fSMateusz Zalega 		error("Couldn't init MMC device.\n");
308711b931fSMateusz Zalega 		return -ENODEV;
309711b931fSMateusz Zalega 	}
310711b931fSMateusz Zalega 
311c8151b4aSLukasz Majewski 	dfu->data.mmc.hw_partition = -EINVAL;
312711b931fSMateusz Zalega 	if (!strcmp(entity_type, "raw")) {
313711b931fSMateusz Zalega 		dfu->layout			= DFU_RAW_ADDR;
314711b931fSMateusz Zalega 		dfu->data.mmc.lba_start		= second_arg;
315711b931fSMateusz Zalega 		dfu->data.mmc.lba_size		= third_arg;
316711b931fSMateusz Zalega 		dfu->data.mmc.lba_blk_size	= mmc->read_bl_len;
317c8151b4aSLukasz Majewski 
318c8151b4aSLukasz Majewski 		/*
319c8151b4aSLukasz Majewski 		 * Check for an extra entry at dfu_alt_info env variable
320c8151b4aSLukasz Majewski 		 * specifying the mmc HW defined partition number
321c8151b4aSLukasz Majewski 		 */
322c8151b4aSLukasz Majewski 		if (s)
323c8151b4aSLukasz Majewski 			if (!strcmp(strsep(&s, " "), "mmcpart"))
324c8151b4aSLukasz Majewski 				dfu->data.mmc.hw_partition =
325c8151b4aSLukasz Majewski 					simple_strtoul(s, NULL, 0);
326c8151b4aSLukasz Majewski 
327711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "part")) {
3281b6ca18bSPantelis Antoniou 		disk_partition_t partinfo;
329711b931fSMateusz Zalega 		block_dev_desc_t *blk_dev = &mmc->block_dev;
330711b931fSMateusz Zalega 		int mmcdev = second_arg;
331711b931fSMateusz Zalega 		int mmcpart = third_arg;
332cb383cd2SLukasz Majewski 
333711b931fSMateusz Zalega 		if (get_partition_info(blk_dev, mmcpart, &partinfo) != 0) {
334711b931fSMateusz Zalega 			error("Couldn't find part #%d on mmc device #%d\n",
335711b931fSMateusz Zalega 			      mmcpart, mmcdev);
3361b6ca18bSPantelis Antoniou 			return -ENODEV;
3371b6ca18bSPantelis Antoniou 		}
3381b6ca18bSPantelis Antoniou 
339711b931fSMateusz Zalega 		dfu->layout			= DFU_RAW_ADDR;
3401b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_start		= partinfo.start;
3411b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_size		= partinfo.size;
3421b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_blk_size	= partinfo.blksz;
343711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "fat")) {
344711b931fSMateusz Zalega 		dfu->layout = DFU_FS_FAT;
345711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "ext4")) {
346711b931fSMateusz Zalega 		dfu->layout = DFU_FS_EXT4;
347cb383cd2SLukasz Majewski 	} else {
348711b931fSMateusz Zalega 		error("Memory layout (%s) not supported!\n", entity_type);
3491b6ca18bSPantelis Antoniou 		return -ENODEV;
350cb383cd2SLukasz Majewski 	}
351cb383cd2SLukasz Majewski 
352711b931fSMateusz Zalega 	/* if it's NOT a raw write */
353711b931fSMateusz Zalega 	if (strcmp(entity_type, "raw")) {
354711b931fSMateusz Zalega 		dfu->data.mmc.dev = second_arg;
355711b931fSMateusz Zalega 		dfu->data.mmc.part = third_arg;
35643e66272SŁukasz Majewski 	}
35743e66272SŁukasz Majewski 
358711b931fSMateusz Zalega 	dfu->dev_type = DFU_DEV_MMC;
359*0e285b50SStephen Warren 	dfu->get_medium_size = dfu_get_medium_size_mmc;
360cb383cd2SLukasz Majewski 	dfu->read_medium = dfu_read_medium_mmc;
361cb383cd2SLukasz Majewski 	dfu->write_medium = dfu_write_medium_mmc;
362ea2453d5SPantelis Antoniou 	dfu->flush_medium = dfu_flush_medium_mmc;
363ea2453d5SPantelis Antoniou 	dfu->inited = 0;
364cb383cd2SLukasz Majewski 
365cb383cd2SLukasz Majewski 	return 0;
366cb383cd2SLukasz Majewski }
367