xref: /rk3399_rockchip-uboot/drivers/mtd/mtd_blk.c (revision 6a20f1c71f36fae15a116ae9a4fab2a6de0ee437)
1 /*
2  * (C) Copyright 2019 Rockchip Electronics Co., Ltd
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <blk.h>
9 #include <boot_rkimg.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <malloc.h>
13 #include <nand.h>
14 #include <part.h>
15 #include <dm/device-internal.h>
16 
17 #define MTD_PART_NAND_HEAD		"mtdparts="
18 #define MTD_PART_INFO_MAX_SIZE		512
19 #define MTD_SINGLE_PART_INFO_MAX_SIZE	40
20 
21 char *mtd_part_parse(void)
22 {
23 	char mtd_part_info_temp[MTD_SINGLE_PART_INFO_MAX_SIZE] = {0};
24 	u32 length, data_len = MTD_PART_INFO_MAX_SIZE;
25 	struct blk_desc *dev_desc;
26 	disk_partition_t info;
27 	char *mtd_part_info_p;
28 	char *mtd_part_info;
29 	int ret;
30 	int p;
31 
32 	dev_desc = rockchip_get_bootdev();
33 	if (!dev_desc)
34 		return NULL;
35 
36 	mtd_part_info = (char *)calloc(MTD_PART_INFO_MAX_SIZE, sizeof(char));
37 	if (!mtd_part_info) {
38 		printf("%s: Fail to malloc!", __func__);
39 		return NULL;
40 	}
41 
42 	mtd_part_info_p = mtd_part_info;
43 	snprintf(mtd_part_info_p, data_len - 1, "%s%s:",
44 		 MTD_PART_NAND_HEAD,
45 		 dev_desc->product);
46 	data_len -= strlen(mtd_part_info_p);
47 	mtd_part_info_p = mtd_part_info_p + strlen(mtd_part_info_p);
48 
49 	for (p = 1; p < MAX_SEARCH_PARTITIONS; p++) {
50 		ret = part_get_info(dev_desc, p, &info);
51 		if (ret)
52 			break;
53 
54 		debug("name is %s, start addr is %x\n", info.name,
55 		      (int)(size_t)info.start);
56 
57 		snprintf(mtd_part_info_p, data_len - 1, "0x%x@0x%x(%s)",
58 			 (int)(size_t)info.size << 9,
59 			 (int)(size_t)info.start << 9,
60 			 info.name);
61 		snprintf(mtd_part_info_temp, MTD_SINGLE_PART_INFO_MAX_SIZE - 1,
62 			 "0x%x@0x%x(%s)",
63 			 (int)(size_t)info.size << 9,
64 			 (int)(size_t)info.start << 9,
65 			 info.name);
66 		strcat(mtd_part_info, ",");
67 		if (part_get_info(dev_desc, p + 1, &info)) {
68 			snprintf(mtd_part_info_p, data_len - 1, "-@0x%x(%s)",
69 				 (int)(size_t)info.start << 9,
70 				 info.name);
71 			break;
72 		}
73 		length = strlen(mtd_part_info_temp);
74 		data_len -= length;
75 		mtd_part_info_p = mtd_part_info_p + length + 1;
76 		memset(mtd_part_info_temp, 0, MTD_SINGLE_PART_INFO_MAX_SIZE);
77 	}
78 
79 	return mtd_part_info;
80 }
81 
82 ulong mtd_dread(struct udevice *udev, lbaint_t start,
83 		lbaint_t blkcnt, void *dst)
84 {
85 	struct blk_desc *desc = dev_get_uclass_platdata(udev);
86 
87 	if (!desc)
88 		return 0;
89 
90 	if (blkcnt == 0)
91 		return 0;
92 
93 	if (desc->devnum == BLK_MTD_NAND) {
94 		int ret = 0;
95 		size_t rwsize = blkcnt * 512;
96 		struct mtd_info *mtd = dev_get_priv(udev->parent);
97 		struct nand_chip *chip = mtd_to_nand(mtd);
98 		loff_t off = (loff_t)(start * 512);
99 
100 		if (!mtd) {
101 			puts("\nno mtd available\n");
102 			return 0;
103 		}
104 
105 		if (!chip) {
106 			puts("\nno chip available\n");
107 			return 0;
108 		}
109 
110 		ret = nand_read_skip_bad(&chip->mtd, off, &rwsize,
111 					 NULL, chip->mtd.size,
112 					 (u_char *)(dst));
113 		if (ret)
114 			return 0;
115 		else
116 			return blkcnt;
117 	} else if (desc->devnum == BLK_MTD_SPI_NAND) {
118 		/* Not implemented */
119 		return 0;
120 	} else if (desc->devnum == BLK_MTD_SPI_NOR) {
121 		/* Not implemented */
122 		return 0;
123 	} else {
124 		return 0;
125 	}
126 }
127 
128 ulong mtd_dwrite(struct udevice *udev, lbaint_t start,
129 		 lbaint_t blkcnt, const void *src)
130 {
131 	/* Not implemented */
132 	return 0;
133 }
134 
135 ulong mtd_derase(struct udevice *udev, lbaint_t start,
136 		 lbaint_t blkcnt)
137 {
138 	/* Not implemented */
139 	return 0;
140 }
141 
142 static int mtd_blk_probe(struct udevice *udev)
143 {
144 	struct blk_desc *desc = dev_get_uclass_platdata(udev);
145 	struct mtd_info *mtd = dev_get_priv(udev->parent);
146 
147 	sprintf(desc->vendor, "0x%.4x", 0x2207);
148 	memcpy(desc->product, mtd->name, strlen(mtd->name));
149 	memcpy(desc->revision, "V1.00", sizeof("V1.00"));
150 	if (mtd->type == MTD_NANDFLASH) {
151 		/* Reserve 4 blocks for BBT(Bad Block Table) */
152 		desc->lba = (mtd->size >> 9) - (mtd->erasesize >> 9) * 4;
153 	} else {
154 		desc->lba = mtd->size >> 9;
155 	}
156 
157 	return 0;
158 }
159 
160 static const struct blk_ops mtd_blk_ops = {
161 	.read	= mtd_dread,
162 #ifndef CONFIG_SPL_BUILD
163 	.write	= mtd_dwrite,
164 	.erase	= mtd_derase,
165 #endif
166 };
167 
168 U_BOOT_DRIVER(mtd_blk) = {
169 	.name		= "mtd_blk",
170 	.id		= UCLASS_BLK,
171 	.ops		= &mtd_blk_ops,
172 	.probe		= mtd_blk_probe,
173 };
174