2 * HND MIPS boards setup routines
4 * Copyright (C) 2009, Broadcom Corporation
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>
26 #include <asm/bootinfo.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>
46 #include <mips33_core.h>
47 #include <mips74k_core.h>
50 #include <hndpci.h> /* for 4706 reboot issue*/
53 #include <ctf/hndctf.h>
58 extern void bcm947xx_time_init(void);
59 extern void bcm947xx_timer_setup(struct irqaction
*irq
);
62 extern void set_debug_traps(void);
63 extern void rs_kgdb_hook(struct uart_port
*);
64 extern void breakpoint(void);
67 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
68 extern struct ide_ops std_ide_ops
;
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
);
82 EXPORT_SYMBOL(bcm947xx_cpu_clk
);
85 #define sih bcm947xx_sih
86 #define sih_lock bcm947xx_sih_lock
91 ctf_attach_t ctf_attach_fn
= NULL
;
92 EXPORT_SYMBOL(ctf_attach_fn
);
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
;
101 bcm947xx_reboot_handler(void)
103 /* Reset the PCI(e) interfaces */
104 if (CHIPID(sih
->chip
) == BCM4706_CHIP_ID
)
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
);
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
);
127 bcm947xx_machine_restart(char *command
)
129 printk("Please stand by while rebooting the system...\n");
131 /* Set the watchdog timer to reset immediately */
133 bcm947xx_reboot_handler();
138 bcm947xx_machine_halt(void)
140 printk("System halted\n");
142 /* Disable interrupts and watchdog and spin forever */
145 bcm947xx_reboot_handler();
149 #ifdef CONFIG_SERIAL_CORE
151 static int num_ports
= 0;
154 serial_add(void *regs
, uint irq
, uint baud_base
, uint reg_shift
)
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
;
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");
175 serial_setup(si_t
*sih
)
177 si_serial_init(sih
, serial_add
);
180 /* Use the last port for kernel debugging */
186 #endif /* CONFIG_SERIAL_CORE */
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 */
212 #endif /* CONFIG_SERIAL_CORE */
214 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
215 ide_ops
= &std_ide_ops
;
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
)) ==
227 /* Check if we want to enable cpu wait */
228 if (nvram_match("wait", "1"))
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
);
242 si_gpioout(sih
, reset
, reset
, GPIO_DRV_PRIORITY
);
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
;
255 get_system_type(void)
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
);
267 return "Broadcom BCM947XX";
282 #ifdef CONFIG_MTD_PARTITIONS
283 static size_t get_erasesize(struct mtd_info
*mtd
, size_t offset
, size_t size
)
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
;
301 erasesize
= mtd
->erasesize
;
308 new layout -- zzz 04/2006
312 +---+----------+ < search for HDR0
314 | i +----------+ < + trx->offset[1]
316 + u +----------+ < + trx->len + gap
318 +--------------+ < size - NVRAM_SPACE
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, },
341 #define PART_JFFS2_MIN 5
342 #ifndef PART_JFFS2_GAP
343 #define PART_JFFS2_GAP 0x40000UL /* 256K, power of 2 */
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
;
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
;
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
)))
378 /* Try looking at TRX header for rootfs offset */
379 if (le32_to_cpu(trx
->magic
) == TRX_MAGIC
) {
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
;
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
;
424 printk(KERN_NOTICE
"%s: Unable to find a valid linux partition\n", mtd
->name
);
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
);
438 return bcm947xx_parts
;
442 static struct mtd_partition bcm947xx_parts
[] =
448 // .mask_flags = MTD_WRITEABLE
459 .mask_flags
= MTD_WRITEABLE
467 #endif /* BCMCONFMTD */
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];
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
) ||
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
)
524 /* romfs is at block zero too */
525 if (romfsb
->word0
== ROMSB_WORD0
&&
526 romfsb
->word1
== ROMSB_WORD1
) {
528 "%s: romfs filesystem found at block %d\n",
529 mtd
->name
, off
/ BLOCK_SIZE
);
534 if (cramfsb
->magic
== CRAMFS_MAGIC
) {
536 "%s: cramfs filesystem found at block %d\n",
537 mtd
->name
, off
/ BLOCK_SIZE
);
541 /* squashfs is at block zero too */
542 if (squashfsb
->s_magic
== SQUASHFS_MAGIC
543 || squashfsb
->s_magic
== SQUASHFS_MAGIC_LZMA
) {
545 "%s: squashfs filesystem found at block %d\n",
546 mtd
->name
, off
/ BLOCK_SIZE
);
552 "%s: Couldn't find valid ROM disk image\n",
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
;
562 /* Setup WAPI MTD partition */
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 */
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
;
578 bcm947xx_parts
[0].size
= bcm947xx_parts
[1].offset
- bcm947xx_parts
[0].offset
;
580 return bcm947xx_parts
;
584 EXPORT_SYMBOL(init_mtd_partitions
);