summaryrefslogtreecommitdiffstats
path: root/target/linux/lantiq/patches/211-nor_split.patch
blob: 2f77681b8c8c47fc393e48c58a34770025f77ef6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
--- a/drivers/mtd/maps/lantiq.c
+++ b/drivers/mtd/maps/lantiq.c
@@ -24,6 +24,10 @@
 #include <lantiq.h>
 #include <lantiq_platform.h>
 
+#ifdef CONFIG_SOC_LANTIQ_XWAY
+#include <xway.h>
+#endif
+
 static map_word
 lq_read16(struct map_info *map, unsigned long adr)
 {
@@ -77,6 +81,75 @@ lq_copy_to(struct map_info *map, unsigne
 	spin_unlock_irqrestore(&ebu_lock, flags);
 }
 
+static unsigned long
+find_uImage_size(struct map_info *map, unsigned long offset)
+{
+#define UBOOT_MAGIC	0x56190527
+	unsigned long magic;
+	unsigned long temp;
+	map->copy_from(map, &magic, offset, 4);
+	if (le32_to_cpu(magic) != UBOOT_MAGIC)
+		return 0;
+	map->copy_from(map, &temp, offset + 12, 4);
+	return temp + 0x40;
+}
+
+static int
+detect_squashfs_partition(struct map_info *map, unsigned long offset)
+{
+	unsigned long temp;
+	map->copy_from(map, &temp, offset, 4);
+	return le32_to_cpu(temp) == SQUASHFS_MAGIC;
+}
+
+static struct mtd_partition split_partitions[] = {
+	{
+		.name = "kernel",
+		.offset = 0x0,
+		.size = 0x0,
+	}, {
+		.name = "rootfs",
+		.offset = 0x0,
+		.size = 0x0,
+	},
+};
+
+static int
+mtd_split_linux(struct map_info *map, struct mtd_info *mtd,
+	struct mtd_partition *parts, int nr_parts)
+{
+	int base_part = 0;
+	int i;
+	for (i = 0; i < nr_parts && !base_part; i++) {
+		if(!strcmp("linux", parts[i].name))
+			base_part = i;
+	}
+	if (!base_part)
+		return 0;
+	split_partitions[0].size = find_uImage_size(map, parts[base_part].offset);
+	if (!split_partitions[0].size) {
+		printk(KERN_INFO "lq_nor: no uImage found in linux partition");
+		return -1;
+	}
+	if (!detect_squashfs_partition(map,
+			parts[base_part].offset + split_partitions[0].size)) {
+		split_partitions[0].size &= ~(mtd->erasesize - 1);
+		split_partitions[0].size += mtd->erasesize;
+	}
+	split_partitions[0].offset = parts[base_part].offset;
+	split_partitions[1].offset =
+		parts[base_part].offset + split_partitions[0].size;
+	split_partitions[1].size =
+		parts[base_part].size - split_partitions[0].size;
+
+	base_part++;
+	add_mtd_partitions(mtd, parts, base_part);
+	add_mtd_partitions(mtd, split_partitions, 2);
+	if(nr_parts != base_part)
+		add_mtd_partitions(mtd, &parts[base_part], nr_parts - base_part);
+	return nr_parts + 2;
+}
+
 static const char *part_probe_types[] = { "cmdlinepart", NULL };
 
 static struct map_info lq_map = {
@@ -142,7 +215,8 @@ lq_mtd_probe(struct platform_device *pde
 		parts = lq_mtd_data->parts;
 	}
 
-	add_mtd_partitions(lq_mtd, parts, nr_parts);
+	if (!mtd_split_linux(&lq_map, lq_mtd, parts, nr_parts))
+		add_mtd_partitions(lq_mtd, parts, nr_parts);
 	return 0;
 }