1. change jffs2 size calc method. it should be a bug while set it's size. it was...
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / arch / mips / brcm-boards / bcm947xx / setup-nonand.c
blobd82e61108629020fef267c888ae4bc65f5dbfc3a
1 /*
2 * HND MIPS boards setup routines
4 * Copyright (C) 2009, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12 * $Id: setup.c,v 1.14 2010/02/26 04:43:25 Exp $
15 #include <linux/types.h>
16 #include <linux/config.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/serial.h>
20 #include <linux/serialP.h>
21 #include <linux/serial_core.h>
22 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
23 #include <linux/blkdev.h>
24 #include <linux/ide.h>
25 #endif
26 #include <asm/bootinfo.h>
27 #include <asm/cpu.h>
28 #include <asm/time.h>
29 #include <asm/reboot.h>
31 #ifdef CONFIG_MTD_PARTITIONS
32 #include <linux/mtd/mtd.h>
33 #include <linux/mtd/partitions.h>
34 #include <linux/romfs_fs.h>
35 #include <linux/cramfs_fs.h>
36 #include <linux/squashfs_fs.h>
37 #endif
39 #include <typedefs.h>
40 #include <osl.h>
41 #include <bcmutils.h>
42 #include <bcmnvram.h>
43 #include <siutils.h>
44 #include <hndsoc.h>
45 #include <hndcpu.h>
46 #include <mips33_core.h>
47 #include <mips74k_core.h>
48 #include <sbchipc.h>
49 #include <hndchipc.h>
50 #include <hndpci.h> /* for 4706 reboot issue*/
51 #include <trxhdr.h>
52 #ifdef HNDCTF
53 #include <ctf/hndctf.h>
54 #endif /* HNDCTF */
55 #include "bcm947xx.h"
56 #include "bcmdevs.h"
58 extern void bcm947xx_time_init(void);
59 extern void bcm947xx_timer_setup(struct irqaction *irq);
61 #ifdef CONFIG_KGDB
62 extern void set_debug_traps(void);
63 extern void rs_kgdb_hook(struct uart_port *);
64 extern void breakpoint(void);
65 #endif
67 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
68 extern struct ide_ops std_ide_ops;
69 #endif
71 /* Enable CPU wait or not */
72 extern int cpu_wait_enable;
74 /* Global SB handle */
75 si_t *bcm947xx_sih = NULL;
76 spinlock_t bcm947xx_sih_lock = SPIN_LOCK_UNLOCKED;
77 EXPORT_SYMBOL(bcm947xx_sih);
78 EXPORT_SYMBOL(bcm947xx_sih_lock);
80 /* CPU freq */
81 int bcm947xx_cpu_clk;
82 EXPORT_SYMBOL(bcm947xx_cpu_clk);
84 /* Convenience */
85 #define sih bcm947xx_sih
86 #define sih_lock bcm947xx_sih_lock
88 #ifdef HNDCTF
89 ctf_t *kcih = NULL;
90 EXPORT_SYMBOL(kcih);
91 ctf_attach_t ctf_attach_fn = NULL;
92 EXPORT_SYMBOL(ctf_attach_fn);
93 #endif /* HNDCTF */
95 /* Kernel command line */
96 extern char arcs_cmdline[CL_SIZE];
97 static int lanports_enable = 0;
98 static int wombo_reset = GPIO_PIN_NOTDEFINED;
100 static void
101 bcm947xx_reboot_handler(void)
103 /* Reset the PCI(e) interfaces */
104 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
105 hndpci_deinit(sih);
107 if (lanports_enable) {
108 uint lp = 1 << lanports_enable;
110 si_gpioout(sih, lp, 0, GPIO_DRV_PRIORITY);
111 si_gpioouten(sih, lp, lp, GPIO_DRV_PRIORITY);
112 bcm_mdelay(1);
115 /* gpio 0 is also valid wombo_reset */
116 if (wombo_reset != GPIO_PIN_NOTDEFINED) {
117 int reset = 1 << wombo_reset;
119 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
120 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
121 bcm_mdelay(10);
126 void
127 bcm947xx_machine_restart(char *command)
129 printk("Please stand by while rebooting the system...\n");
131 /* Set the watchdog timer to reset immediately */
132 local_irq_disable();
133 bcm947xx_reboot_handler();
134 hnd_cpu_reset(sih);
137 void
138 bcm947xx_machine_halt(void)
140 printk("System halted\n");
142 /* Disable interrupts and watchdog and spin forever */
143 local_irq_disable();
144 si_watchdog(sih, 0);
145 bcm947xx_reboot_handler();
146 while (1);
149 #ifdef CONFIG_SERIAL_CORE
151 static int num_ports = 0;
153 static void __init
154 serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
156 struct uart_port rs;
158 memset(&rs, 0, sizeof(rs));
159 rs.line = num_ports++;
160 rs.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
161 rs.iotype = UPIO_MEM;
163 rs.mapbase = (unsigned int) regs;
164 rs.membase = regs;
165 rs.irq = irq + 2;
166 rs.uartclk = baud_base;
167 rs.regshift = reg_shift;
169 if (early_serial_setup(&rs) != 0) {
170 printk(KERN_ERR "Serial setup failed!\n");
174 static void __init
175 serial_setup(si_t *sih)
177 si_serial_init(sih, serial_add);
179 #ifdef CONFIG_KGDB
180 /* Use the last port for kernel debugging */
181 if (rs.membase)
182 rs_kgdb_hook(&rs);
183 #endif
186 #endif /* CONFIG_SERIAL_CORE */
188 void __init
189 brcm_setup(void)
191 char *value;
193 /* Get global SB handle */
194 sih = si_kattach(SI_OSH);
196 /* Initialize clocks and interrupts */
197 si_mips_init(sih, SBMIPS_VIRTIRQ_BASE);
199 if (BCM330X(current_cpu_data.processor_id) &&
200 (read_c0_diag() & BRCM_PFC_AVAIL)) {
202 * Now that the sih is inited set the proper PFC value
204 printk("Setting the PFC to its default value\n");
205 enable_pfc(PFC_AUTO);
209 #ifdef CONFIG_SERIAL_CORE
210 /* Initialize UARTs */
211 serial_setup(sih);
212 #endif /* CONFIG_SERIAL_CORE */
214 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
215 ide_ops = &std_ide_ops;
216 #endif
218 /* Override default command line arguments */
219 value = nvram_get("kernel_args");
220 if (value && strlen(value) && strncmp(value, "empty", 5))
221 strncpy(arcs_cmdline, value, sizeof(arcs_cmdline));
223 if ((lanports_enable = getgpiopin(NULL, "lanports_enable", GPIO_PIN_NOTDEFINED)) ==
224 GPIO_PIN_NOTDEFINED)
225 lanports_enable = 0;
227 /* Check if we want to enable cpu wait */
228 if (nvram_match("wait", "1"))
229 cpu_wait_enable = 1;
231 /* wombo reset */
232 if ((wombo_reset = getgpiopin(NULL, "wombo_reset", GPIO_PIN_NOTDEFINED)) !=
233 GPIO_PIN_NOTDEFINED) {
234 int reset = 1 << wombo_reset;
236 printk("wombo_reset set to gpio %d\n", wombo_reset);
238 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
239 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
240 bcm_mdelay(10);
242 si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY);
243 bcm_mdelay(20);
246 /* Generic setup */
247 _machine_restart = bcm947xx_machine_restart;
248 _machine_halt = bcm947xx_machine_halt;
249 pm_power_off = bcm947xx_machine_halt;
251 board_time_init = bcm947xx_time_init;
254 const char *
255 get_system_type(void)
257 static char s[32];
258 char cn[8];
260 if (bcm947xx_sih) {
261 bcm_chipname(bcm947xx_sih->chip, cn, 8);
262 sprintf(s, "Broadcom BCM%s chip rev %d pkg %d", cn,
263 bcm947xx_sih->chiprev, bcm947xx_sih->chippkg);
264 return s;
266 else
267 return "Broadcom BCM947XX";
270 void __init
271 bus_error_init(void)
275 void __init
276 plat_mem_setup(void)
278 brcm_setup();
279 return;
282 #ifdef CONFIG_MTD_PARTITIONS
283 static size_t get_erasesize(struct mtd_info *mtd, size_t offset, size_t size)
285 int i;
286 struct mtd_erase_region_info *regions;
287 size_t erasesize = 0;
289 if (mtd->numeraseregions > 1) {
290 regions = mtd->eraseregions;
292 /* Find the first erase regions which is part of this partition */
293 for (i = 0; i < mtd->numeraseregions && offset >= regions[i].offset; i++);
295 for (i--; i < mtd->numeraseregions && offset + size > regions[i].offset; i++) {
296 if (erasesize < regions[i].erasesize)
297 erasesize = regions[i].erasesize;
300 else {
301 erasesize = mtd->erasesize;
304 return erasesize;
308 new layout -- zzz 04/2006
310 +--------------+
311 | boot |
312 +---+----------+ < search for HDR0
313 | l | kernel |
314 | i +----------+ < + trx->offset[1]
315 | n | rootfs |
316 + u +----------+ < + trx->len + gap
317 | x | jffs2 |
318 +--------------+ < size - NVRAM_SPACE
319 | nvram |
320 +--------------+ < size
323 static struct mtd_partition bcm947xx_parts[] = {
324 { name: "pmon", offset: 0, size: 0, },
325 { name: "linux", offset: 0, size: 0, },
326 { name: "rootfs", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
327 { name: "nvram", offset: 0, size: 0, },
328 { name: "jffs2", offset: 0, size: 0, },
329 { name: NULL, },
332 enum {
333 PART_BOOT = 0,
334 PART_LINUX,
335 PART_ROOTFS,
336 PART_NVRAM,
337 PART_JFFS2,
338 PART_COUNT
341 #define PART_JFFS2_MIN 5
342 #ifndef PART_JFFS2_GAP
343 #define PART_JFFS2_GAP 0x40000UL /* 256K, power of 2 */
344 #endif
346 struct mtd_partition *
347 init_mtd_partitions(struct mtd_info *mtd, size_t size)
349 struct trx_header *trx;
350 unsigned char buf[512];
351 size_t off, trxoff, boardoff;
352 size_t len;
353 size_t trxsize;
355 /* Find and size nvram */
356 bcm947xx_parts[PART_NVRAM].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
357 bcm947xx_parts[PART_NVRAM].offset = size - bcm947xx_parts[PART_NVRAM].size;
359 /* Fine-tune nvram size */
360 len = get_erasesize(mtd, bcm947xx_parts[PART_NVRAM].offset, bcm947xx_parts[PART_NVRAM].size);
361 if (len < mtd->erasesize) {
362 bcm947xx_parts[PART_NVRAM].size = ROUNDUP(NVRAM_SPACE, len);
363 bcm947xx_parts[PART_NVRAM].offset = size - bcm947xx_parts[PART_NVRAM].size;
366 /* Size board_data */
367 boardoff = bcm947xx_parts[PART_NVRAM].offset;
369 trxsize = 0;
370 trx = (struct trx_header *) buf;
371 for (off = 0; off < size; off += mtd->erasesize) {
373 * Read block 0 to test for rootfs
375 if ((mtd->read(mtd, off, sizeof(buf), &len, buf)) || (len != sizeof(buf)))
376 continue;
378 /* Try looking at TRX header for rootfs offset */
379 if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
380 /* Size pmon */
381 bcm947xx_parts[PART_BOOT].size = off;
383 /* Size linux (kernel and rootfs, including any remaining space) */
384 bcm947xx_parts[PART_LINUX].offset = off;
385 bcm947xx_parts[PART_LINUX].size = boardoff - off;
387 /* Find and size rootfs */
388 trxoff = (le32_to_cpu(trx->offsets[2]) > off) ? trx->offsets[2] : trx->offsets[1];
389 trxsize = ROUNDUP(le32_to_cpu(trx->len), mtd->erasesize); /* kernel + rootfs */
390 bcm947xx_parts[PART_ROOTFS].offset = trxoff + off;
391 bcm947xx_parts[PART_ROOTFS].size = trxsize - trxoff;
393 /* Find and size jffs2 */
394 if (boardoff > off + trxsize)
395 bcm947xx_parts[PART_JFFS2].size = boardoff - off - trxsize;
396 len = PART_JFFS2_MIN * mtd->erasesize;
397 if (bcm947xx_parts[PART_JFFS2].size >= len) {
398 #if 1 /* Gap jffs2 from rootfs up to 256K */
399 if(PART_JFFS2_GAP > 0) {
400 bcm947xx_parts[PART_JFFS2].size -= len;
401 bcm947xx_parts[PART_JFFS2].size &= ~(PART_JFFS2_GAP - 1); // round down
402 bcm947xx_parts[PART_JFFS2].size += len;
404 #else /* Temporary compatibility for Boyau */
405 bcm947xx_parts[PART_JFFS2].size = len;
406 #endif
407 } else {
408 /* We have 3 variants here:
409 * 1. hide jffs2 partition
410 bcm947xx_parts[PART_JFFS2].name = NULL;
411 * 2. set size to zero
412 bcm947xx_parts[PART_JFFS2].size = 0;
413 * 3. leave it erasesize-aligned with any size, by default
416 bcm947xx_parts[PART_JFFS2].offset = boardoff - bcm947xx_parts[PART_JFFS2].size;
418 break;
422 if (trxsize == 0) {
423 // uh, now what...
424 printk(KERN_NOTICE "%s: Unable to find a valid linux partition\n", mtd->name);
427 #if 0
428 int i;
429 for (i = 0; bcm947xx_parts[i].name; ++i) {
430 printk(KERN_NOTICE "%8x %8x (%8x) %s\n",
431 bcm947xx_parts[i].offset,
432 (bcm947xx_parts[i].offset + bcm947xx_parts[i].size) - 1,
433 bcm947xx_parts[i].size,
434 bcm947xx_parts[i].name);
436 #endif
438 return bcm947xx_parts;
441 #if 0
442 static struct mtd_partition bcm947xx_parts[] =
445 .name = "boot",
446 .size = 0,
447 .offset = 0,
448 // .mask_flags = MTD_WRITEABLE
451 .name = "linux",
452 .size = 0,
453 .offset = 0
456 .name = "rootfs",
457 .size = 0,
458 .offset = 0,
459 .mask_flags = MTD_WRITEABLE
461 #ifdef BCMCONFMTD
463 .name = "confmtd",
464 .size = 0,
465 .offset = 0
467 #endif /* BCMCONFMTD */
469 .name = "nvram",
470 .size = 0,
471 .offset = 0
474 .name = 0,
475 .size = 0,
476 .offset = 0
480 struct mtd_partition *
481 init_mtd_partitions(struct mtd_info *mtd, size_t size)
483 struct romfs_super_block *romfsb;
484 struct cramfs_super *cramfsb;
485 struct squashfs_super_block *squashfsb;
486 struct trx_header *trx;
487 unsigned char buf[512];
488 int off;
489 size_t len;
490 int i;
492 romfsb = (struct romfs_super_block *) buf;
493 cramfsb = (struct cramfs_super *) buf;
494 squashfsb = (struct squashfs_super_block *) buf;
495 trx = (struct trx_header *) buf;
497 /* Look at every 64 KB boundary */
498 for (off = 0; off < size; off += (64 * 1024)) {
499 memset(buf, 0xe5, sizeof(buf));
502 * Read block 0 to test for romfs and cramfs superblock
504 if (mtd->read(mtd, off, sizeof(buf), &len, buf) ||
505 len != sizeof(buf))
506 continue;
508 /* Try looking at TRX header for rootfs offset */
509 if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
510 bcm947xx_parts[1].offset = off;
511 // if (le32_to_cpu(trx->offsets[1]) > off)
512 if (le32_to_cpu(trx->offsets[2]) > off)
513 off = le32_to_cpu(trx->offsets[2]);
514 else if (le32_to_cpu(trx->offsets[1]) > off)
515 off = le32_to_cpu(trx->offsets[1]);
516 /* In case where CFE boots from ROM, we expect
517 * Linux to fit in first flash partition.
519 if (bcm947xx_parts[1].offset == 0 && off)
520 off -= (64 * 1024);
521 continue;
524 /* romfs is at block zero too */
525 if (romfsb->word0 == ROMSB_WORD0 &&
526 romfsb->word1 == ROMSB_WORD1) {
527 printk(KERN_NOTICE
528 "%s: romfs filesystem found at block %d\n",
529 mtd->name, off / BLOCK_SIZE);
530 goto done;
533 /* so is cramfs */
534 if (cramfsb->magic == CRAMFS_MAGIC) {
535 printk(KERN_NOTICE
536 "%s: cramfs filesystem found at block %d\n",
537 mtd->name, off / BLOCK_SIZE);
538 goto done;
541 /* squashfs is at block zero too */
542 if (squashfsb->s_magic == SQUASHFS_MAGIC
543 || squashfsb->s_magic == SQUASHFS_MAGIC_LZMA) {
544 printk(KERN_NOTICE
545 "%s: squashfs filesystem found at block %d\n",
546 mtd->name, off / BLOCK_SIZE);
547 goto done;
551 printk(KERN_NOTICE
552 "%s: Couldn't find valid ROM disk image\n",
553 mtd->name);
555 done:
556 /* Setup NVRAM MTD partition */
557 i = (sizeof(bcm947xx_parts)/sizeof(struct mtd_partition)) - 2;
559 bcm947xx_parts[i].size = ROUNDUP(NVRAM_SPACE, mtd->erasesize);
560 bcm947xx_parts[i].offset = size - bcm947xx_parts[i].size;
561 #ifdef BCMCONFMTD
562 /* Setup WAPI MTD partition */
563 i--;
564 bcm947xx_parts[i].size = mtd->erasesize;
565 bcm947xx_parts[i].offset = bcm947xx_parts[i+1].offset - bcm947xx_parts[i].size;
566 #endif /* BCMCONFMTD */
568 /* Find and size rootfs */
569 if (off < size) {
570 bcm947xx_parts[2].offset = off;
571 bcm947xx_parts[2].size = bcm947xx_parts[3].offset - bcm947xx_parts[2].offset;
574 /* Size linux (kernel and rootfs) */
575 bcm947xx_parts[1].size = bcm947xx_parts[3].offset - bcm947xx_parts[1].offset;
577 /* Size pmon */
578 bcm947xx_parts[0].size = bcm947xx_parts[1].offset - bcm947xx_parts[0].offset;
580 return bcm947xx_parts;
582 #endif // 0
584 EXPORT_SYMBOL(init_mtd_partitions);
586 #endif