cns3xxx: merge gpio patches
[openwrt.git] / target / linux / lantiq / patches-3.3 / 0019-owrt-mtd-split.patch
1 From 2a295753a10823a47542c779a25bbb1f52c71281 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Fri, 3 Aug 2012 10:27:13 +0200
4 Subject: [PATCH 19/25] owrt mtd split
5
6 ---
7  .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    1 +
8  arch/mips/lantiq/setup.c                           |    7 +
9  drivers/mtd/Kconfig                                |    4 +
10  drivers/mtd/mtdpart.c                              |  173 +++++++++++++++++++-
11  4 files changed, 184 insertions(+), 1 deletions(-)
12
13 diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
14 index 1ec8f2a..1ff93cc 100644
15 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
16 +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
17 @@ -166,6 +166,7 @@ extern unsigned char ltq_boot_select(void);
18  
19  extern __iomem void *ltq_ebu_membase;
20  extern __iomem void *ltq_cgu_membase;
21 +extern unsigned long ltq_brn_boot;
22  
23  static inline int ltq_is_ase(void)
24  {
25 diff --git a/arch/mips/lantiq/setup.c b/arch/mips/lantiq/setup.c
26 index 1ff6c9d..708e969 100644
27 --- a/arch/mips/lantiq/setup.c
28 +++ b/arch/mips/lantiq/setup.c
29 @@ -18,6 +18,9 @@
30  #include "devices.h"
31  #include "prom.h"
32  
33 +/* set to 1 if the bootloader is BRN-BOOT instead of u-boot */
34 +unsigned long ltq_brn_boot = 0;
35 +
36  void __init plat_mem_setup(void)
37  {
38         /* assume 16M as default incase uboot fails to pass proper ramsize */
39 @@ -38,6 +41,10 @@ void __init plat_mem_setup(void)
40                         if (strict_strtoul(e, 0, &memsize))
41                                 pr_warn("bad memsize specified\n");
42                 }
43 +               if (!strncmp(e, "BRN-BOOT", 8)){
44 +                       pr_info("Found BRN-BOOT instead of u-boot\n");
45 +                       ltq_brn_boot = 1;
46 +               }
47                 envp++;
48         }
49         memsize *= 1024 * 1024;
50 diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
51 index 982a98b..e2f3f3e 100644
52 --- a/drivers/mtd/Kconfig
53 +++ b/drivers/mtd/Kconfig
54 @@ -31,6 +31,10 @@ config MTD_ROOTFS_SPLIT
55         bool "Automatically split 'rootfs' partition for squashfs"
56         default y
57  
58 +config MTD_UIMAGE_SPLIT
59 +       bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
60 +       default y
61 +
62  config MTD_REDBOOT_PARTS
63         tristate "RedBoot partition table parsing"
64         ---help---
65 diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
66 index 855b70b..93711e2 100644
67 --- a/drivers/mtd/mtdpart.c
68 +++ b/drivers/mtd/mtdpart.c
69 @@ -867,6 +867,168 @@ static int refresh_rootfs_split(struct mtd_info *mtd)
70  }
71  #endif /* CONFIG_MTD_ROOTFS_SPLIT */
72  
73 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
74 +static unsigned long find_uimage_size(struct mtd_info *mtd,
75 +                                     unsigned long offset)
76 +{
77 +#define UBOOT_MAGIC    0x56190527
78 +       unsigned long magic = 0;
79 +       unsigned long temp;
80 +       size_t len;
81 +       int ret;
82 +
83 +       ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
84 +       if (ret || len != sizeof(magic))
85 +               return 0;
86 +
87 +       if (le32_to_cpu(magic) != UBOOT_MAGIC)
88 +               return 0;
89 +
90 +       ret = mtd->read(mtd, offset + 12, 4, &len, (void *)&temp);
91 +       if (ret || len != sizeof(temp))
92 +               return 0;
93 +
94 +       return temp + 0x40;
95 +}
96 +
97 +static unsigned long find_eva_size(struct mtd_info *mtd,
98 +                                     unsigned long offset)
99 +{
100 +#define EVA_MAGIC      0xfeed1281
101 +       unsigned long magic = 0;
102 +       unsigned long temp;
103 +       size_t len;
104 +       int ret;
105 +
106 +       ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
107 +       if (ret || len != sizeof(magic))
108 +               return 0;
109 +
110 +       if (le32_to_cpu(magic) != EVA_MAGIC)
111 +               return 0;
112 +
113 +       ret = mtd->read(mtd, offset + 4, 4, &len, (void *)&temp);
114 +       if (ret || len != sizeof(temp))
115 +               return 0;
116 +
117 +       /* add eva header size */
118 +       temp = le32_to_cpu(temp) + 0x18;
119 +
120 +       temp &= ~0xffff;
121 +       temp += 0x10000;
122 +       return temp;
123 +}
124 +
125 +static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
126 +{
127 +       unsigned long temp;
128 +       size_t len;
129 +       int ret;
130 +
131 +       ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
132 +       if (ret || len != sizeof(temp))
133 +               return 0;
134 +
135 +
136 +       return le32_to_cpu(temp) == SQUASHFS_MAGIC;
137 +}
138 +
139 +static int detect_eva_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
140 +{
141 +       unsigned long temp;
142 +       size_t len;
143 +       int ret;
144 +
145 +       ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
146 +       if (ret || len != sizeof(temp))
147 +               return 0;
148 +
149 +       return be32_to_cpu(temp) == SQUASHFS_MAGIC;
150 +}
151 +
152 +static unsigned long find_brnimage_size(struct mtd_info *mtd,
153 +                                       unsigned long offset)
154 +{
155 +       unsigned long buf[4];
156 +       // Assume at most 2MB of kernel image
157 +       unsigned long end = offset + (2 << 20);
158 +       unsigned long ptr = offset + 0x400 - 12;
159 +       size_t len;
160 +       int ret;
161 +
162 +       while (ptr < end) {
163 +               long size_min = ptr - 0x400 - 12 - offset;
164 +               long size_max = ptr + 12 - offset;
165 +               ret = mtd->read(mtd, ptr, 16, &len, (void *)buf);
166 +               if (ret || len != 16)
167 +                       return 0;
168 +
169 +               if (le32_to_cpu(buf[0]) < size_min ||
170 +                   le32_to_cpu(buf[0]) > size_max) {
171 +                       ptr += 0x400;
172 +                       continue;
173 +               }
174 +
175 +               if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC)
176 +                       return ptr + 12 - offset;
177 +
178 +               ptr += 0x400;
179 +       }
180 +
181 +       return 0;
182 +}
183 +
184 +static int split_uimage(struct mtd_info *mtd,
185 +                       const struct mtd_partition *part)
186 +{
187 +       static struct mtd_partition split_partitions[] = {
188 +               {
189 +                       .name = "kernel",
190 +                       .offset = 0x0,
191 +                       .size = 0x0,
192 +               }, {
193 +                       .name = "rootfs",
194 +                       .offset = 0x0,
195 +                       .size = 0x0,
196 +               },
197 +       };
198 +
199 +       split_partitions[0].size = find_uimage_size(mtd, part->offset);
200 +       if (!split_partitions[0].size) {
201 +               split_partitions[0].size = find_eva_size(mtd, part->offset);
202 +               if (!split_partitions[0].size) {
203 +                       split_partitions[0].size = find_brnimage_size(mtd, part->offset);
204 +                       if (!split_partitions[0].size) {
205 +                               printk(KERN_NOTICE "no uImage or brnImage or eva found in linux partition\n");
206 +                               return -1;
207 +                       }
208 +               }
209 +       }
210 +
211 +       if (detect_eva_squashfs_partition(mtd,
212 +                                      part->offset
213 +                                      + split_partitions[0].size)) {
214 +               split_partitions[0].size += 0x100;
215 +               pr_info("found eva dummy squashfs behind kernel\n");
216 +       } else if (!detect_squashfs_partition(mtd,
217 +                                      part->offset
218 +                                      + split_partitions[0].size)) {
219 +               split_partitions[0].size &= ~(mtd->erasesize - 1);
220 +               split_partitions[0].size += mtd->erasesize;
221 +       } else {
222 +               pr_info("found squashfs behind kernel\n");
223 +       }
224 +
225 +       split_partitions[0].offset = part->offset;
226 +       split_partitions[1].offset = part->offset + split_partitions[0].size;
227 +       split_partitions[1].size = part->size - split_partitions[0].size;
228 +
229 +       add_mtd_partitions(mtd, split_partitions, 2);
230 +
231 +       return 0;
232 +}
233 +#endif
234 +
235  /*
236   * This function, given a master MTD object and a partition table, creates
237   * and registers slave MTD objects which are bound to the master according to
238 @@ -883,7 +1045,7 @@ int add_mtd_partitions(struct mtd_info *master,
239         struct mtd_part *slave;
240         uint64_t cur_offset = 0;
241         int i;
242 -#ifdef CONFIG_MTD_ROOTFS_SPLIT
243 +#if defined(CONFIG_MTD_ROOTFS_SPLIT) || defined(CONFIG_MTD_UIMAGE_SPLIT)
244         int ret;
245  #endif
246  
247 @@ -900,6 +1062,15 @@ int add_mtd_partitions(struct mtd_info *master,
248  
249                 add_mtd_device(&slave->mtd);
250  
251 +#ifdef CONFIG_MTD_UIMAGE_SPLIT
252 +               if (!strcmp(parts[i].name, "linux")) {
253 +                       ret = split_uimage(master, &parts[i]);
254 +
255 +                       if (ret)
256 +                               printk(KERN_WARNING "Can't split linux partition\n");
257 +               }
258 +#endif
259 +
260                 if (!strcmp(parts[i].name, "rootfs")) {
261  #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
262                         if (ROOT_DEV == 0) {
263 -- 
264 1.7.9.1
265