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