100 lines
2.6 KiB
Diff
100 lines
2.6 KiB
Diff
|
--- 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;
|
||
|
}
|
||
|
|