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