xref: /OK3568_Linux_fs/u-boot/drivers/dfu/dfu_mtd.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2021 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:     GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <boot_rkimg.h>
8*4882a593Smuzhiyun #include <div64.h>
9*4882a593Smuzhiyun #include <dfu.h>
10*4882a593Smuzhiyun #include <errno.h>
11*4882a593Smuzhiyun #include <linux/mtd/mtd.h>
12*4882a593Smuzhiyun #include <malloc.h>
13*4882a593Smuzhiyun #include <part.h>
14*4882a593Smuzhiyun 
dfu_write_medium_mtd(struct dfu_entity * dfu,u64 offset,void * buf,long * len)15*4882a593Smuzhiyun static int dfu_write_medium_mtd(struct dfu_entity *dfu,	u64 offset, void *buf, long *len)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun 	struct blk_desc *dev_desc;
18*4882a593Smuzhiyun 	u64 block_start, block_len;
19*4882a593Smuzhiyun 	int ret = -ENODEV;
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun 	switch (dfu->layout) {
22*4882a593Smuzhiyun 	case DFU_RAW_ADDR:
23*4882a593Smuzhiyun 		/* if buf == NULL return total size of the area */
24*4882a593Smuzhiyun 		if (!buf) {
25*4882a593Smuzhiyun 			*len = dfu->data.nand.size;
26*4882a593Smuzhiyun 			return 0;
27*4882a593Smuzhiyun 		}
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 		dev_desc = rockchip_get_bootdev();
30*4882a593Smuzhiyun 		if (!dev_desc) {
31*4882a593Smuzhiyun 			printf("%s: dev_desc is NULL!\n", __func__);
32*4882a593Smuzhiyun 			return -ENODEV;
33*4882a593Smuzhiyun 		}
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 		/* in case of ubi partition, erase rest of the partition */
36*4882a593Smuzhiyun 		if (dfu->data.mtd.ubi && !offset) {
37*4882a593Smuzhiyun 			block_start = dfu->data.mtd.start >> 9;
38*4882a593Smuzhiyun 			block_len = dfu->data.mtd.size >> 9;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 			ret = blk_derase(dev_desc, block_start, block_len);
41*4882a593Smuzhiyun 			if (ret != 0)
42*4882a593Smuzhiyun 				printf("Failure erase: %d\n", ret);
43*4882a593Smuzhiyun 		}
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 		block_start = (dfu->data.mtd.start + offset) >> 9;
46*4882a593Smuzhiyun 		block_len = (*len) >> 9;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 		ret = blk_dwrite(dev_desc, block_start, block_len, buf);
49*4882a593Smuzhiyun 		if (ret == block_len)
50*4882a593Smuzhiyun 			ret = 0;
51*4882a593Smuzhiyun 		break;
52*4882a593Smuzhiyun 	default:
53*4882a593Smuzhiyun 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
54*4882a593Smuzhiyun 		       dfu_get_layout(dfu->layout));
55*4882a593Smuzhiyun 	}
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	return ret;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
dfu_get_medium_size_mtd(struct dfu_entity * dfu,u64 * size)60*4882a593Smuzhiyun static int dfu_get_medium_size_mtd(struct dfu_entity *dfu, u64 *size)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	*size = dfu->data.mtd.size;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	return 0;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun 
dfu_read_medium_mtd(struct dfu_entity * dfu,u64 offset,void * buf,long * len)67*4882a593Smuzhiyun static int dfu_read_medium_mtd(struct dfu_entity *dfu, u64 offset, void *buf, long *len)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	struct blk_desc *dev_desc;
70*4882a593Smuzhiyun 	u64 block_start, block_len;
71*4882a593Smuzhiyun 	int ret = -ENODEV;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	switch (dfu->layout) {
74*4882a593Smuzhiyun 	case DFU_RAW_ADDR:
75*4882a593Smuzhiyun 		/* if buf == NULL return total size of the area */
76*4882a593Smuzhiyun 		if (!buf) {
77*4882a593Smuzhiyun 			*len = dfu->data.nand.size;
78*4882a593Smuzhiyun 			return 0;
79*4882a593Smuzhiyun 		}
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 		dev_desc = rockchip_get_bootdev();
82*4882a593Smuzhiyun 		if (!dev_desc) {
83*4882a593Smuzhiyun 			printf("%s: dev_desc is NULL!\n", __func__);
84*4882a593Smuzhiyun 			return -ENODEV;
85*4882a593Smuzhiyun 		}
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 		block_start = (dfu->data.mtd.start + offset) >> 9;
88*4882a593Smuzhiyun 		block_len = (*len) >> 9;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 		ret = blk_dread(dev_desc, block_start, block_len, buf);
91*4882a593Smuzhiyun 		if (ret == block_len)
92*4882a593Smuzhiyun 			ret = 0;
93*4882a593Smuzhiyun 		break;
94*4882a593Smuzhiyun 	default:
95*4882a593Smuzhiyun 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
96*4882a593Smuzhiyun 		       dfu_get_layout(dfu->layout));
97*4882a593Smuzhiyun 	}
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	return ret;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
dfu_flush_medium_mtd(struct dfu_entity * dfu)102*4882a593Smuzhiyun static int dfu_flush_medium_mtd(struct dfu_entity *dfu)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	return 0;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
dfu_polltimeout_mtd(struct dfu_entity * dfu)107*4882a593Smuzhiyun unsigned int dfu_polltimeout_mtd(struct dfu_entity *dfu)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	/*
110*4882a593Smuzhiyun 	 * Currently, Poll Timeout != 0 is only needed on nand
111*4882a593Smuzhiyun 	 * ubi partition, as the not used sectors need an erase
112*4882a593Smuzhiyun 	 */
113*4882a593Smuzhiyun 	if (dfu->data.mtd.ubi)
114*4882a593Smuzhiyun 		return DFU_MANIFEST_POLL_TIMEOUT;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return DFU_DEFAULT_POLL_TIMEOUT;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
dfu_fill_entity_mtd(struct dfu_entity * dfu,char * devstr,char * s)119*4882a593Smuzhiyun int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	struct blk_desc *dev_desc;
122*4882a593Smuzhiyun 	disk_partition_t dfu_part;
123*4882a593Smuzhiyun 	char *st;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	dfu->data.mtd.ubi = 0;
126*4882a593Smuzhiyun 	dfu->dev_type = DFU_DEV_MTD;
127*4882a593Smuzhiyun 	st = strsep(&s, " ");
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	if (!strcmp(st, "raw") || !strcmp(st, "rawubi")) {
130*4882a593Smuzhiyun 		dfu->layout = DFU_RAW_ADDR;
131*4882a593Smuzhiyun 		dfu->data.mtd.start = simple_strtoul(s, &s, 16);
132*4882a593Smuzhiyun 		s++;
133*4882a593Smuzhiyun 		dfu->data.mtd.size = simple_strtoul(s, &s, 16);
134*4882a593Smuzhiyun 		if (!strcmp(st, "rawubi"))
135*4882a593Smuzhiyun 			dfu->data.mtd.ubi = 1;
136*4882a593Smuzhiyun 	} else if ((!strcmp(st, "part")) || (!strcmp(st, "partubi"))) {
137*4882a593Smuzhiyun 		dev_desc = rockchip_get_bootdev();
138*4882a593Smuzhiyun 		if (!dev_desc) {
139*4882a593Smuzhiyun 			printf("%s: dev_desc is NULL!\n", __func__);
140*4882a593Smuzhiyun 			return -ENODEV;
141*4882a593Smuzhiyun 		}
142*4882a593Smuzhiyun 		dfu->layout = DFU_RAW_ADDR;
143*4882a593Smuzhiyun 		if (part_get_info_by_name(dev_desc, s, &dfu_part) < 0)
144*4882a593Smuzhiyun 			return -EIO;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 		dfu->data.mtd.start = dfu_part.start << 9;
147*4882a593Smuzhiyun 		dfu->data.mtd.size = dfu_part.size << 9;
148*4882a593Smuzhiyun 		if (!strcmp(st, "partubi"))
149*4882a593Smuzhiyun 			dfu->data.mtd.ubi = 1;
150*4882a593Smuzhiyun 	} else {
151*4882a593Smuzhiyun 		printf("%s: Memory layout (%s) not supported!\n", __func__, st);
152*4882a593Smuzhiyun 		return -1;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	dfu->get_medium_size = dfu_get_medium_size_mtd;
156*4882a593Smuzhiyun 	dfu->read_medium = dfu_read_medium_mtd;
157*4882a593Smuzhiyun 	dfu->write_medium = dfu_write_medium_mtd;
158*4882a593Smuzhiyun 	dfu->flush_medium = dfu_flush_medium_mtd;
159*4882a593Smuzhiyun 	dfu->poll_timeout = dfu_polltimeout_mtd;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	/* initial state */
162*4882a593Smuzhiyun 	dfu->inited = 0;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	return 0;
165*4882a593Smuzhiyun }
166