3a9f7d081f61cb388a67b1419ea9922958efd218
[openwrt/svn-archive/archive.git] / openwrt / 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("OpenWrt");
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 +};