add proper ar7 flash map driver and change image stuff to save more flash space
[openwrt.git] / target / linux / linux-2.4 / patches / ar7 / 001-flash_map.patch
1 diff -urN linux.old/drivers/mtd/maps/ar7-flash.c linux.dev/drivers/mtd/maps/ar7-flash.c
2 --- linux.old/drivers/mtd/maps/ar7-flash.c      1970-01-01 01:00:00.000000000 +0100
3 +++ linux.dev/drivers/mtd/maps/ar7-flash.c      2005-07-21 09:01:39.994240680 +0200
4 @@ -0,0 +1,272 @@
5 +/*
6 + * $Id$
7 + *
8 + * Normal mappings of chips in physical memory
9 + */
10 +
11 +#include <linux/module.h>
12 +#include <linux/types.h>
13 +#include <linux/kernel.h>
14 +#include <asm/io.h>
15 +#include <linux/mtd/mtd.h>
16 +#include <linux/mtd/map.h>
17 +#include <linux/config.h>
18 +#include <linux/mtd/partitions.h>
19 +#include "trxhdr.h"
20 +
21 +#define WINDOW_ADDR CONFIG_MTD_AR7_START
22 +#define WINDOW_SIZE CONFIG_MTD_AR7_LEN
23 +#define BUSWIDTH CONFIG_MTD_AR7_BUSWIDTH
24 +
25 +#include <asm/mips-boards/prom.h>
26 +extern char *prom_getenv(char *name);
27 +
28 +static int create_mtd_partitions(void);
29 +static void __exit ar7_mtd_cleanup(void);
30 +       
31 +#define MAX_NUM_PARTITIONS 5
32 +static struct mtd_partition ar7_partinfo[MAX_NUM_PARTITIONS];
33 +
34 +static struct mtd_info *ar7_mtd_info;
35 +
36 +__u8 ar7_read8(struct map_info *map, unsigned long ofs)
37 +{
38 +       return __raw_readb(map->map_priv_1 + ofs);
39 +}
40 +
41 +__u16 ar7_read16(struct map_info *map, unsigned long ofs)
42 +{
43 +       return __raw_readw(map->map_priv_1 + ofs);
44 +}
45 +
46 +__u32 ar7_read32(struct map_info *map, unsigned long ofs)
47 +{
48 +       return __raw_readl(map->map_priv_1 + ofs);
49 +}
50 +
51 +void ar7_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
52 +{
53 +       memcpy_fromio(to, map->map_priv_1 + from, len);
54 +}
55 +
56 +void ar7_write8(struct map_info *map, __u8 d, unsigned long adr)
57 +{
58 +       __raw_writeb(d, map->map_priv_1 + adr);
59 +       mb();
60 +}
61 +
62 +void ar7_write16(struct map_info *map, __u16 d, unsigned long adr)
63 +{
64 +       __raw_writew(d, map->map_priv_1 + adr);
65 +       mb();
66 +}
67 +
68 +void ar7_write32(struct map_info *map, __u32 d, unsigned long adr)
69 +{
70 +       __raw_writel(d, map->map_priv_1 + adr);
71 +       mb();
72 +}
73 +
74 +void ar7_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
75 +{
76 +       memcpy_toio(map->map_priv_1 + to, from, len);
77 +}
78 +
79 +struct map_info ar7_map = {
80 +       name: "Physically mapped flash",
81 +       size: WINDOW_SIZE,
82 +       buswidth: BUSWIDTH,
83 +       read8: ar7_read8,
84 +       read16: ar7_read16,
85 +       read32: ar7_read32,
86 +       copy_from: ar7_copy_from,
87 +       write8: ar7_write8,
88 +       write16: ar7_write16,
89 +       write32: ar7_write32,
90 +       copy_to: ar7_copy_to
91 +};
92 +
93 +int __init ar7_mtd_init(void)
94 +{
95 +       int partitions;
96 +       
97 +               printk(KERN_NOTICE "ar7 flash device: 0x%lx at 0x%lx.\n", (unsigned long)WINDOW_SIZE, (unsigned long)WINDOW_ADDR);
98 +       ar7_map.map_priv_1 = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
99 +
100 +       if (!ar7_map.map_priv_1) {
101 +               printk("Failed to ioremap\n");
102 +               return -EIO;
103 +       }
104 +       
105 +       ar7_mtd_info = do_map_probe("cfi_probe", &ar7_map);
106 +       if (!ar7_mtd_info)
107 +       {
108 +               ar7_mtd_cleanup();
109 +               return -ENXIO;
110 +       }
111 +       
112 +       ar7_mtd_info->module = THIS_MODULE;
113 +
114 +       if (!(partitions = create_mtd_partitions()))
115 +               add_mtd_device(ar7_mtd_info);
116 +       else            
117 +               add_mtd_partitions(ar7_mtd_info, ar7_partinfo, partitions);
118 +
119 +       return 0;
120 +}
121 +
122 +static char *strdup(char *str)
123 +{
124 +       int n = strlen(str)+1;
125 +       char *s = kmalloc(n, GFP_KERNEL);
126 +       if (!s) return NULL;
127 +       return strcpy(s, str);
128 +}
129 +
130 +
131 +static int create_mtd_partitions(void)
132 +{
133 +       unsigned int offset;
134 +       unsigned int size;
135 +       unsigned int found = 0;
136 +       unsigned int p = 0;
137 +       unsigned char *flash_base;
138 +       unsigned char *flash_end;
139 +       struct trx_header hdr;
140 +       char *env_ptr;
141 +       char *base_ptr;
142 +       char *end_ptr;
143 +       unsigned int adam2_size = 0x20000;
144 +       unsigned int config_offset = WINDOW_SIZE;
145 +       unsigned int rootfs_start = 0xe0000;
146 +
147 +       printk("Parsing ADAM2 partition map...\n");
148 +       
149 +       do {
150 +               char    env_name[20];
151 +
152 +               /* get base and end addresses of flash file system from environment */
153 +               sprintf(env_name, "mtd%1u", p);
154 +               printk("Looking for mtd device :%s:\n", env_name);
155 +
156 +               env_ptr = prom_getenv(env_name);
157 +               if(env_ptr == NULL) {
158 +                       /* No more partitions to find */
159 +                       break;
160 +               }
161 +
162 +               /* Extract the start and stop addresses of the partition */
163 +               base_ptr = strtok(env_ptr, ",");
164 +               end_ptr = strtok(NULL, ",");
165 +               if ((base_ptr == NULL) || (end_ptr == NULL)) {  
166 +                       printk("ADAM2 partition error: Invalid %s start,end.\n", env_name);
167 +                       break;
168 +               }
169 +
170 +               flash_base = (unsigned char*) simple_strtol(base_ptr, NULL, 0);
171 +               flash_end = (unsigned char*) simple_strtol(end_ptr, NULL, 0);
172 +               if((!flash_base) || (!flash_end)) {
173 +                       printk("ADAM2 partition error: Invalid %s start,end.\n", env_name);
174 +                       break;
175 +               }
176 +
177 +               offset = virt_to_bus(flash_base) - WINDOW_ADDR;
178 +               size = flash_end - flash_base;
179 +               printk("Found a %s image (0x%x), with size (0x%x).\n",env_name, offset, size);
180 +
181 +               
182 +               if (offset == 0) {
183 +                       printk("Assuming adam2 size of 0x%x\n", size);
184 +                       adam2_size = size;                      // boot loader
185 +               } else if (offset > 0x120000) {
186 +                       if (config_offset > offset)
187 +                               config_offset = offset;         // reserved at the end of the flash chip
188 +               } else if (offset > 0x30000) {
189 +                       printk("Assuming rootfs offset of 0x%x\n", offset);
190 +                       rootfs_start = offset;                  // probably root fs
191 +               }
192 +               
193 +               p++;
194 +       } while (p < MAX_NUM_PARTITIONS);
195 +       
196 +       p = 0;
197 +       
198 +       ar7_partinfo[p].name = strdup("adam2");
199 +       ar7_partinfo[p].offset = 0;
200 +       ar7_partinfo[p].size = adam2_size;
201 +       ar7_partinfo[p++].mask_flags = 0;
202 +
203 +       ar7_partinfo[p].name = strdup("linux");
204 +       ar7_partinfo[p].offset = adam2_size;
205 +       ar7_partinfo[p].size = config_offset - adam2_size;
206 +       ar7_partinfo[p++].mask_flags = 0;
207 +
208 +       for (offset = adam2_size; !found && (offset < rootfs_start); offset += 1024) {
209 +               if (ar7_read32(&ar7_map, offset) == TRX_MAGIC) {
210 +                       found = 1;
211 +                       rootfs_start = offset;
212 +               }
213 +       }
214 +       
215 +       ar7_partinfo[p].name = strdup("rootfs");
216 +       ar7_partinfo[p].offset = rootfs_start;
217 +       ar7_partinfo[p].size = config_offset - rootfs_start;
218 +       
219 +       ar7_copy_from(&ar7_map, &hdr, rootfs_start, sizeof(hdr));
220 +       if (hdr.magic == TRX_MAGIC) {
221 +               printk("TRX header in rootfs partition detected.\n");
222 +               printk("offset[0] = 0x%05x\n", hdr.offsets[0]);
223 +               printk("offset[1] = 0x%05x\n", hdr.offsets[1]);
224 +               printk("offset[2] = 0x%05x\n", hdr.offsets[2]);
225 +               ar7_partinfo[p].offset += hdr.offsets[0];
226 +               ar7_partinfo[p].size -= hdr.offsets[0];
227 +       }
228 +
229 +       ar7_partinfo[p++].mask_flags = 0;
230 +
231 +       ar7_partinfo[p].name = strdup("config");
232 +       ar7_partinfo[p].offset = config_offset;
233 +       ar7_partinfo[p].size = WINDOW_SIZE - config_offset;
234 +       ar7_partinfo[p++].mask_flags = 0;
235 +
236 +       if (ar7_read32(&ar7_map, rootfs_start + hdr.offsets[0]) == 0x73717368) {
237 +               int newsize;
238 +               
239 +               printk("Squashfs detected. Adding extra partition\n");
240 +               newsize = hdr.len;
241 +               if (newsize % ar7_mtd_info->erasesize)
242 +                       newsize += ar7_mtd_info->erasesize - ((newsize + hdr.offsets[0]) % ar7_mtd_info->erasesize);
243 +               
244 +
245 +               ar7_partinfo[p].name = strdup("test");
246 +               ar7_partinfo[p].offset = rootfs_start + newsize;
247 +               ar7_partinfo[p].size = ar7_partinfo[p - 2].size + hdr.offsets[0] - newsize;
248 +               ar7_partinfo[p - 2].size = newsize - hdr.offsets[0];
249 +
250 +               p++;
251 +       }
252 +
253 +
254 +       return p;
255 +}
256 +
257 +static void __exit ar7_mtd_cleanup(void)
258 +{
259 +       if (ar7_mtd_info) {
260 +               del_mtd_partitions(ar7_mtd_info);
261 +               del_mtd_device(ar7_mtd_info);
262 +               map_destroy(ar7_mtd_info);
263 +       }
264 +
265 +       if (ar7_map.map_priv_1) {
266 +               iounmap((void *)ar7_map.map_priv_1);
267 +               ar7_map.map_priv_1 = 0;
268 +       }
269 +}
270 +
271 +module_init(ar7_mtd_init);
272 +module_exit(ar7_mtd_cleanup);
273 +
274 +MODULE_LICENSE("GPL");
275 +MODULE_AUTHOR("Felix Fietkau");
276 +MODULE_DESCRIPTION("AR7 CFI map driver");
277 diff -urN linux.old/drivers/mtd/maps/Config.in linux.dev/drivers/mtd/maps/Config.in
278 --- linux.old/drivers/mtd/maps/Config.in        2005-07-21 05:36:32.414242296 +0200
279 +++ linux.dev/drivers/mtd/maps/Config.in        2005-07-21 06:29:04.067118232 +0200
280 @@ -48,6 +48,21 @@
281  fi
282  
283  if [ "$CONFIG_MIPS" = "y" ]; then
284 +    if [ "$CONFIG_AR7" = "y" ]; then
285 +      dep_tristate '  Flash chip mapping on Texas Instruments AR7' CONFIG_MTD_AR7 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS
286 +      dep_bool     '    Use defaults for Texas Instruments AR7' CONFIG_MTD_AR7_DEFAULTS $CONFIG_MTD_AR7
287 +      if [ "$CONFIG_MTD_AR7" = "y" -o "$CONFIG_MTD_AR7" = "m" ]; then
288 +         if [ "$CONFIG_MTD_AR7_DEFAULTS" = "y" ]; then
289 +            define_hex CONFIG_MTD_AR7_START 0x10000000
290 +            define_hex CONFIG_MTD_AR7_LEN 0x400000
291 +            define_int CONFIG_MTD_AR7_BUSWIDTH 2
292 +         else
293 +            hex '      Physical start address of flash mapping' CONFIG_MTD_AR7_START 0x10000000
294 +            hex '      Physical length of flash mapping' CONFIG_MTD_AR7_LEN 0x400000
295 +            int '      Bus width in octets' CONFIG_MTD_AR7_BUSWIDTH 2
296 +         fi
297 +      fi
298 +   fi
299     dep_tristate '  Pb1000 MTD support' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000
300     dep_tristate '  Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500
301     dep_tristate '  Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100
302 diff -urN linux.old/drivers/mtd/maps/Makefile linux.dev/drivers/mtd/maps/Makefile
303 --- linux.old/drivers/mtd/maps/Makefile 2005-07-21 05:36:32.414242296 +0200
304 +++ linux.dev/drivers/mtd/maps/Makefile 2005-07-21 06:56:33.265401984 +0200
305 @@ -10,6 +10,7 @@
306  endif
307  
308  # Chip mappings
309 +obj-$(CONFIG_MTD_AR7)          += ar7-flash.o
310  obj-$(CONFIG_MTD_CDB89712)     += cdb89712.o
311  obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
312  obj-$(CONFIG_MTD_CFI_FLAGADM)  += cfi_flagadm.o
313 diff -urN linux.old/drivers/mtd/maps/trxhdr.h linux.dev/drivers/mtd/maps/trxhdr.h
314 --- linux.old/drivers/mtd/maps/trxhdr.h 1970-01-01 01:00:00.000000000 +0100
315 +++ linux.dev/drivers/mtd/maps/trxhdr.h 2005-07-10 20:50:43.550827000 +0200
316 @@ -0,0 +1,29 @@
317 +/*
318 + * TRX image file header format.
319 + *
320 + * Copyright 2005, Broadcom Corporation
321 + * All Rights Reserved.
322 + * 
323 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
324 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
325 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
326 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
327 + *
328 + * $Id$
329 + */ 
330 +
331 +
332 +#define TRX_MAGIC      0x30524448      /* "HDR0" */
333 +#define TRX_VERSION    1
334 +#define TRX_MAX_LEN    0x3A0000
335 +#define TRX_NO_HEADER  1               /* Do not write TRX header */   
336 +#define TRX_GZ_FILES   0x2     /* Contains up to TRX_MAX_OFFSET individual gzip files */
337 +#define TRX_MAX_OFFSET 3
338 +
339 +struct trx_header {
340 +       __u32 magic;            /* "HDR0" */
341 +       __u32 len;              /* Length of file including header */
342 +       __u32 crc32;            /* 32-bit CRC from flag_version to end of file */
343 +       __u32 flag_version;     /* 0:15 flags, 16:31 version */
344 +       __u32 offsets[TRX_MAX_OFFSET];  /* Offsets of partitions from start of header */
345 +};