3d85d8971288ffb4bcee1c4961734393e9fa69f7
[openwrt/svn-archive/archive.git] / openwrt / target / linux / linux-2.6 / patches / brcm / 002-flash-map.patch
1 diff -Nur linux-2.6.15-rc5/drivers/mtd/maps/bcm47xx-flash.c linux-2.6.15-rc5-flash/drivers/mtd/maps/bcm47xx-flash.c
2 --- linux-2.6.15-rc5/drivers/mtd/maps/bcm47xx-flash.c 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.15-rc5-flash/drivers/mtd/maps/bcm47xx-flash.c 2005-12-18 23:40:45.060006250 +0100
4 @@ -0,0 +1,321 @@
5 +/*
6 + * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
7 + * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
8 + *
9 + * original functions for finding root filesystem from Mike Baker
10 + *
11 + * This program is free software; you can redistribute it and/or modify it
12 + * under the terms of the GNU General Public License as published by the
13 + * Free Software Foundation; either version 2 of the License, or (at your
14 + * option) any later version.
15 + *
16 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 + *
27 + * You should have received a copy of the GNU General Public License along
28 + * with this program; if not, write to the Free Software Foundation, Inc.,
29 + * 675 Mass Ave, Cambridge, MA 02139, USA.
30 + *
31 + * Copyright 2001-2003, Broadcom Corporation
32 + * All Rights Reserved.
33 + *
34 + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
35 + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
36 + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
37 + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
38 + *
39 + * Flash mapping for BCM947XX boards
40 + */
41 +
42 +#include <linux/init.h>
43 +#include <linux/module.h>
44 +#include <linux/types.h>
45 +#include <linux/kernel.h>
46 +#include <asm/io.h>
47 +#include <linux/mtd/mtd.h>
48 +#include <linux/mtd/map.h>
49 +#ifdef CONFIG_MTD_PARTITIONS
50 +#include <linux/mtd/partitions.h>
51 +#endif
52 +#include <linux/config.h>
53 +
54 +#include <trxhdr.h>
55 +
56 +#define WINDOW_ADDR 0x1c000000
57 +#define WINDOW_SIZE (0x400000*2)
58 +#define BUSWIDTH 2
59 +
60 +static struct mtd_info *bcm947xx_mtd;
61 +
62 +static void bcm947xx_map_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
63 +{
64 +#define MIPS_MEMCPY_ALIGN 4
65 + map_word ret;
66 + ssize_t transfer;
67 + ssize_t done = 0;
68 + if ((len >= MIPS_MEMCPY_ALIGN) && (!(from & (MIPS_MEMCPY_ALIGN - 1))) && (!(((unsigned int)to & (MIPS_MEMCPY_ALIGN - 1))))) {
69 + done = len & ~(MIPS_MEMCPY_ALIGN - 1);
70 + memcpy_fromio(to, map->virt + from, done);
71 + }
72 + while (done < len) {
73 + ret = map->read(map, from + done);
74 + transfer = len - done;
75 + if (transfer > map->bankwidth)
76 + transfer = map->bankwidth;
77 + memcpy((void *)((unsigned long)to + done), &ret.x[0], transfer);
78 + done += transfer;
79 + }
80 +}
81 +
82 +static struct map_info bcm947xx_map = {
83 + name: "Physically mapped flash",
84 + size: WINDOW_SIZE,
85 + bankwidth: BUSWIDTH,
86 + phys: WINDOW_ADDR,
87 +};
88 +
89 +#ifdef CONFIG_MTD_PARTITIONS
90 +
91 +static struct mtd_partition bcm947xx_parts[] = {
92 + { name: "cfe", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
93 + { name: "linux", offset: 0, size: 0, },
94 + { name: "rootfs", offset: 0, size: 0, },
95 + { name: "nvram", offset: 0, size: 0, },
96 + { name: "OpenWrt", offset: 0, size: 0, },
97 + { name: NULL, },
98 +};
99 +
100 +static int __init
101 +find_cfe_size(struct mtd_info *mtd, size_t size)
102 +{
103 + struct trx_header *trx;
104 + unsigned char buf[512];
105 + int off;
106 + size_t len;
107 + int cfe_size_flag;
108 +
109 + trx = (struct trx_header *) buf;
110 +
111 + cfe_size_flag=0;
112 +
113 + for (off = (256*1024); off < size; off += mtd->erasesize) {
114 + memset(buf, 0xe5, sizeof(buf));
115 +
116 + /*
117 + * Read into buffer
118 + */
119 + if (MTD_READ(mtd, off, sizeof(buf), &len, buf) ||
120 + len != sizeof(buf))
121 + continue;
122 +
123 + /* found a TRX header */
124 + if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
125 + goto done;
126 + }
127 + cfe_size_flag += 1;
128 + }
129 +
130 + printk(KERN_NOTICE
131 + "%s: Couldn't find bootloader size\n",
132 + mtd->name);
133 + return -1;
134 +
135 + done:
136 + printk(KERN_NOTICE "bootloader size flag: %d\n", cfe_size_flag);
137 + return cfe_size_flag;
138 +
139 +}
140 +
141 +static int __init
142 +find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
143 +{
144 + struct trx_header *trx;
145 + unsigned char buf[512];
146 + int off;
147 + size_t len;
148 +
149 + trx = (struct trx_header *) buf;
150 +
151 + for (off = (256*1024); off < size; off += mtd->erasesize) {
152 + memset(buf, 0xe5, sizeof(buf));
153 +
154 + /*
155 + * Read into buffer
156 + */
157 + if (MTD_READ(mtd, off, sizeof(buf), &len, buf) ||
158 + len != sizeof(buf))
159 + continue;
160 +
161 + /* found a TRX header */
162 + if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
163 + part->offset = le32_to_cpu(trx->offsets[2]) ? :
164 + le32_to_cpu(trx->offsets[1]);
165 + part->size = le32_to_cpu(trx->len);
166 +
167 + part->size -= part->offset;
168 + part->offset += off;
169 +
170 + goto done;
171 + }
172 + }
173 +
174 + printk(KERN_NOTICE
175 + "%s: Couldn't find root filesystem\n",
176 + mtd->name);
177 + return -1;
178 +
179 + done:
180 + return part->size;
181 +}
182 +
183 +struct mtd_partition * __init
184 +init_mtd_partitions(struct mtd_info *mtd, size_t size)
185 +{
186 +
187 + int cfe_size_flag;
188 +
189 + /* if cfe_size_flag=0, cfe size is 256 kb, else 384 kb */
190 + cfe_size_flag = find_cfe_size(mtd, size);
191 +
192 + /* boot loader */
193 + bcm947xx_parts[0].offset = 0;
194 + if (cfe_size_flag == 0) {
195 + bcm947xx_parts[0].size = 1024*256;
196 + } else {
197 + /* netgear wgt634u has 384 kb bootloader */
198 + bcm947xx_parts[0].size = 1024*384;
199 + }
200 +
201 + /* nvram */
202 + if (cfe_size_flag == 0) {
203 + bcm947xx_parts[3].offset = size - mtd->erasesize;
204 + } else {
205 + /* nvram (old 128kb config partition on netgear wgt634u) */
206 + bcm947xx_parts[3].offset = bcm947xx_parts[0].size;
207 + }
208 + bcm947xx_parts[3].size = mtd->erasesize;
209 +
210 + /* linux (kernel and rootfs) */
211 + if (cfe_size_flag == 0) {
212 + bcm947xx_parts[1].offset = bcm947xx_parts[0].size;
213 + bcm947xx_parts[1].size = bcm947xx_parts[3].offset -
214 + bcm947xx_parts[1].offset;
215 + } else {
216 + /* do not count the elf loader, which is on one block */
217 + bcm947xx_parts[1].offset = bcm947xx_parts[0].size +
218 + bcm947xx_parts[3].size + mtd->erasesize;
219 + bcm947xx_parts[1].size = size -
220 + bcm947xx_parts[0].size -
221 + (2*bcm947xx_parts[3].size) -
222 + mtd->erasesize;
223 + }
224 +
225 + /* find and size rootfs */
226 + if (find_root(mtd,size,&bcm947xx_parts[2])==0) {
227 + /* entirely jffs2 */
228 + bcm947xx_parts[4].name = NULL;
229 + if (cfe_size_flag == 0) {
230 + bcm947xx_parts[2].size = size - bcm947xx_parts[2].offset -
231 + bcm947xx_parts[3].size;
232 + } else {
233 + bcm947xx_parts[2].size = size - bcm947xx_parts[2].offset -
234 + bcm947xx_parts[3].size;
235 + }
236 + } else {
237 + /* legacy setup */
238 + /* calculate leftover flash, and assign it to the jffs2 partition */
239 + if (cfe_size_flag == 0) {
240 + bcm947xx_parts[4].offset = bcm947xx_parts[2].offset +
241 + bcm947xx_parts[2].size;
242 + if ((bcm947xx_parts[4].offset % mtd->erasesize) > 0) {
243 + bcm947xx_parts[4].offset += mtd->erasesize -
244 + (bcm947xx_parts[4].offset % mtd->erasesize);
245 + }
246 + bcm947xx_parts[4].size = bcm947xx_parts[3].offset -
247 + bcm947xx_parts[4].offset;
248 + } else {
249 + bcm947xx_parts[4].offset = bcm947xx_parts[2].offset +
250 + bcm947xx_parts[2].size;
251 + if ((bcm947xx_parts[4].offset % mtd->erasesize) > 0) {
252 + bcm947xx_parts[4].offset += mtd->erasesize -
253 + (bcm947xx_parts[4].offset % mtd->erasesize);
254 + }
255 + bcm947xx_parts[4].size = size - bcm947xx_parts[3].size -
256 + bcm947xx_parts[4].offset;
257 + }
258 + }
259 +
260 + return bcm947xx_parts;
261 +}
262 +#endif
263 +
264 +int __init init_bcm947xx_map(void)
265 +{
266 + size_t size;
267 + int ret = 0;
268 +#ifdef CONFIG_MTD_PARTITIONS
269 + struct mtd_partition *parts;
270 + int i;
271 +#endif
272 +
273 + bcm947xx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
274 +
275 + if (!bcm947xx_map.virt) {
276 + printk("Failed to ioremap\n");
277 + return -EIO;
278 + }
279 + simple_map_init(&bcm947xx_map);
280 +
281 + bcm947xx_map.copy_from = bcm947xx_map_copy_from;
282 +
283 + if (!(bcm947xx_mtd = do_map_probe("cfi_probe", &bcm947xx_map))) {
284 + printk("Failed to do_map_probe\n");
285 + iounmap((void *)bcm947xx_map.virt);
286 + return -ENXIO;
287 + }
288 +
289 + bcm947xx_mtd->owner = THIS_MODULE;
290 +
291 + size = bcm947xx_mtd->size;
292 +
293 + printk(KERN_NOTICE "Flash device: 0x%x at 0x%x\n", size, WINDOW_ADDR);
294 +
295 +#ifdef CONFIG_MTD_PARTITIONS
296 + parts = init_mtd_partitions(bcm947xx_mtd, size);
297 + for (i = 0; parts[i].name; i++);
298 + ret = add_mtd_partitions(bcm947xx_mtd, parts, i);
299 + if (ret) {
300 + printk(KERN_ERR "Flash: add_mtd_partitions failed\n");
301 + goto fail;
302 + }
303 +#endif
304 + return 0;
305 +
306 + fail:
307 + if (bcm947xx_mtd)
308 + map_destroy(bcm947xx_mtd);
309 + if (bcm947xx_map.virt)
310 + iounmap((void *)bcm947xx_map.virt);
311 + bcm947xx_map.virt = 0;
312 + return ret;
313 +}
314 +
315 +void __exit cleanup_bcm947xx_map(void)
316 +{
317 +#ifdef CONFIG_MTD_PARTITIONS
318 + del_mtd_partitions(bcm947xx_mtd);
319 +#endif
320 + map_destroy(bcm947xx_mtd);
321 + iounmap((void *)bcm947xx_map.virt);
322 +}
323 +
324 +module_init(init_bcm947xx_map);
325 +module_exit(cleanup_bcm947xx_map);
326 diff -Nur linux-2.6.15-rc5/drivers/mtd/maps/Kconfig linux-2.6.15-rc5-flash/drivers/mtd/maps/Kconfig
327 --- linux-2.6.15-rc5/drivers/mtd/maps/Kconfig 2005-12-04 06:10:42.000000000 +0100
328 +++ linux-2.6.15-rc5-flash/drivers/mtd/maps/Kconfig 2005-12-18 19:36:11.555087000 +0100
329 @@ -299,6 +299,12 @@
330 Mapping for the Flaga digital module. If you don't have one, ignore
331 this setting.
332
333 +config MTD_BCM47XX
334 + tristate "BCM47xx flash device"
335 + depends on MIPS && MTD_CFI && BCM947XX
336 + help
337 + Support for the flash chips on the BCM947xx board.
338 +
339 config MTD_BEECH
340 tristate "CFI Flash device mapped on IBM 405LP Beech"
341 depends on MTD_CFI && BEECH
342 diff -Nur linux-2.6.15-rc5/drivers/mtd/maps/Makefile linux-2.6.15-rc5-flash/drivers/mtd/maps/Makefile
343 --- linux-2.6.15-rc5/drivers/mtd/maps/Makefile 2005-12-04 06:10:42.000000000 +0100
344 +++ linux-2.6.15-rc5-flash/drivers/mtd/maps/Makefile 2005-12-18 19:36:11.555087000 +0100
345 @@ -31,6 +31,7 @@
346 obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
347 obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
348 obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
349 +obj-$(CONFIG_MTD_BCM47XX) += bcm47xx-flash.o
350 obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
351 obj-$(CONFIG_MTD_IPAQ) += ipaq-flash.o
352 obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o