1/*
2 * HND MIPS boards setup routines
3 *
4 * Copyright 2006, 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.
11 *
12 * $Id: setup.c,v 1.1.1.1 2008/10/15 03:26:06 james26_jang Exp $
13 */
14
15#include <linux/config.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/serialP.h>
19#include <linux/ide.h>
20#include <asm/bootinfo.h>
21#include <asm/cpu.h>
22#include <asm/time.h>
23#include <asm/reboot.h>
24
25#ifdef CONFIG_MTD_PARTITIONS
26#include <linux/mtd/mtd.h>
27#include <linux/mtd/partitions.h>
28#include <linux/minix_fs.h>
29#include <linux/ext2_fs.h>
30#include <linux/romfs_fs.h>
31#include <linux/cramfs_fs.h>
32#endif
33
34#include <typedefs.h>
35#include <osl.h>
36#include <bcmutils.h>
37#include <bcmnvram.h>
38#include <sbutils.h>
39#include <hndcpu.h>
40#include <sbhndmips.h>
41#include <hndmips.h>
42#include <sbchipc.h>
43#include <hndchipc.h>
44#include <trxhdr.h>
45#include "bcm947xx.h"
46
47extern void bcm947xx_time_init(void);
48extern void bcm947xx_timer_setup(struct irqaction *irq);
49
50#ifdef CONFIG_REMOTE_DEBUG
51extern void set_debug_traps(void);
52extern void rs_kgdb_hook(struct serial_state *);
53extern void breakpoint(void);
54#endif
55
56#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
57extern struct ide_ops std_ide_ops;
58#endif
59
60/* Global SB handle */
61sb_t *bcm947xx_sbh = NULL;
62spinlock_t bcm947xx_sbh_lock = SPIN_LOCK_UNLOCKED;
63EXPORT_SYMBOL(bcm947xx_sbh);
64EXPORT_SYMBOL(bcm947xx_sbh_lock);
65
66/* Convenience */
67#define sbh bcm947xx_sbh
68#define sbh_lock bcm947xx_sbh_lock
69
70/* Kernel command line */
71char arcs_cmdline[CL_SIZE] __initdata = CONFIG_CMDLINE;
72
73void
74bcm947xx_machine_restart(char *command)
75{
76	printk("Please stand by while rebooting the system...\n");
77
78	/* Set the watchdog timer to reset immediately */
79	__cli();
80	hnd_cpu_reset(sbh);
81}
82
83void
84bcm947xx_machine_halt(void)
85{
86	printk("System halted\n");
87
88	/* Disable interrupts and watchdog and spin forever */
89	__cli();
90	sb_watchdog(sbh, 0);
91	while (1);
92}
93
94#ifdef CONFIG_SERIAL
95
96static struct serial_struct rs = {
97	line: 0,
98	flags: ASYNC_BOOT_AUTOCONF,
99	io_type: SERIAL_IO_MEM,
100};
101
102static void __init
103serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
104{
105	rs.iomem_base = regs;
106	rs.irq = irq + 2;
107	rs.baud_base = baud_base / 16;
108	rs.iomem_reg_shift = reg_shift;
109
110	early_serial_setup(&rs);
111
112	rs.line++;
113}
114
115static void __init
116serial_setup(sb_t *sbh)
117{
118	sb_serial_init(sbh, serial_add);
119
120#ifdef CONFIG_REMOTE_DEBUG
121	/* Use the last port for kernel debugging */
122	if (rs.iomem_base)
123		rs_kgdb_hook(&rs);
124#endif
125}
126
127#endif /* CONFIG_SERIAL */
128
129void __init
130brcm_setup(void)
131{
132	char *value;
133
134	/* Get global SB handle */
135	sbh = sb_kattach(SB_OSH);
136
137	/* Initialize clocks and interrupts */
138	sb_mips_init(sbh, SBMIPS_VIRTIRQ_BASE);
139
140	if (BCM330X(mips_cpu.processor_id) &&
141		(read_c0_diag() & BRCM_PFC_AVAIL)) {
142		/*
143		 * Now that the sbh is inited set the  proper PFC value
144		 */
145		printk("Setting the PFC to its default value\n");
146		enable_pfc(PFC_AUTO);
147	}
148
149
150#ifdef CONFIG_SERIAL
151	/* Initialize UARTs */
152	serial_setup(sbh);
153#endif
154
155#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
156	ide_ops = &std_ide_ops;
157#endif
158
159	/* Override default command line arguments */
160	value = nvram_get("kernel_args");
161	if (value && strlen(value) && strncmp(value, "empty", 5))
162		strncpy(arcs_cmdline, value, sizeof(arcs_cmdline));
163
164
165	/* Generic setup */
166	_machine_restart = bcm947xx_machine_restart;
167	_machine_halt = bcm947xx_machine_halt;
168	_machine_power_off = bcm947xx_machine_halt;
169
170	board_time_init = bcm947xx_time_init;
171	board_timer_setup = bcm947xx_timer_setup;
172}
173
174const char *
175get_system_type(void)
176{
177	static char s[32];
178
179	if (bcm947xx_sbh) {
180		sprintf(s, "Broadcom BCM%X chip rev %d", sb_chip(bcm947xx_sbh),
181			sb_chiprev(bcm947xx_sbh));
182		return s;
183	}
184	else
185		return "Broadcom BCM947XX";
186}
187
188void __init
189bus_error_init(void)
190{
191}
192
193#ifdef CONFIG_MTD_PARTITIONS
194// Modify by Chen-I
195static struct mtd_partition bcm947xx_parts[] = {
196	{ name: "boot",	offset: 0, size: 0, },
197	{ name: "linux", offset: 0, size: 0, },
198	{ name: "rootfs", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
199	{ name: "nvram", offset: 0, size: 0, },
200	{ name: NULL, },
201};
202
203struct mtd_partition * __init
204init_mtd_partitions(struct mtd_info *mtd, size_t size)
205{
206	struct minix_super_block *minixsb;
207	struct ext2_super_block *ext2sb;
208	struct romfs_super_block *romfsb;
209	struct squashfs_super_block *squashfsb;
210	struct cramfs_super *cramfsb;
211	struct trx_header *trx;
212	unsigned char buf[512];
213	int off;
214	size_t len;
215
216	minixsb = (struct minix_super_block *) buf;
217	ext2sb = (struct ext2_super_block *) buf;
218	romfsb = (struct romfs_super_block *) buf;
219	squashfsb = (struct squashfs_super_block *) buf;
220	cramfsb = (struct cramfs_super *) buf;
221	trx = (struct trx_header *) buf;
222
223	/* Look at every 64 KB boundary */
224	for (off = 0; off < size; off += (64 * 1024)) {
225		memset(buf, 0xe5, sizeof(buf));
226
227		/*
228		 * Read block 0 to test for romfs and cramfs superblock
229		 */
230		if (MTD_READ(mtd, off, sizeof(buf), &len, buf) ||
231		    len != sizeof(buf))
232			continue;
233
234		/* Try looking at TRX header for rootfs offset */
235		if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
236			bcm947xx_parts[1].offset = off;
237//			if (le32_to_cpu(trx->offsets[1]) > off)
238                        if (le32_to_cpu(trx->offsets[2]) > off)
239                                off = le32_to_cpu(trx->offsets[2]);
240                        else if (le32_to_cpu(trx->offsets[1]) > off)
241				off = le32_to_cpu(trx->offsets[1]);
242
243			continue;
244		}
245
246		/* romfs is at block zero too */
247		if (romfsb->word0 == ROMSB_WORD0 &&
248		    romfsb->word1 == ROMSB_WORD1) {
249			printk(KERN_NOTICE
250			       "%s: romfs filesystem found at block %d\n",
251			       mtd->name, off / BLOCK_SIZE);
252			goto done;
253		}
254
255                /* squashfs is at block zero too */
256                if (squashfsb->s_magic == SQUASHFS_MAGIC) {
257                        printk(KERN_NOTICE
258                               "%s: squashfs filesystem found at block %d\n",
259                               mtd->name, off / BLOCK_SIZE);
260                        goto done;
261                }
262
263
264		/* so is cramfs */
265		if (cramfsb->magic == CRAMFS_MAGIC) {
266			printk(KERN_NOTICE
267			       "%s: cramfs filesystem found at block %d\n",
268			       mtd->name, off / BLOCK_SIZE);
269			goto done;
270		}
271
272		/*
273		 * Read block 1 to test for minix and ext2 superblock
274		 */
275		if (MTD_READ(mtd, off + BLOCK_SIZE, sizeof(buf), &len, buf) ||
276		    len != sizeof(buf))
277			continue;
278
279		/* Try minix */
280		if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
281		    minixsb->s_magic == MINIX_SUPER_MAGIC2) {
282			printk(KERN_NOTICE
283			       "%s: Minix filesystem found at block %d\n",
284			       mtd->name, off / BLOCK_SIZE);
285			goto done;
286		}
287
288		/* Try ext2 */
289		if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
290			printk(KERN_NOTICE
291			       "%s: ext2 filesystem found at block %d\n",
292			       mtd->name, off / BLOCK_SIZE);
293			goto done;
294		}
295	}
296
297	printk(KERN_NOTICE
298	       "%s: Couldn't find valid ROM disk image\n",
299	       mtd->name);
300
301 done:
302	/* Find and size nvram */
303	bcm947xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
304	bcm947xx_parts[3].size = size - bcm947xx_parts[3].offset;
305
306	/* Find and size rootfs */
307	if (off < size) {
308		bcm947xx_parts[2].offset = off;
309		bcm947xx_parts[2].size = bcm947xx_parts[3].offset - bcm947xx_parts[2].offset;
310	}
311
312	/* Size linux (kernel and rootfs) */
313	bcm947xx_parts[1].size = bcm947xx_parts[3].offset - bcm947xx_parts[1].offset;
314
315	/* Size pmon */
316	bcm947xx_parts[0].size = bcm947xx_parts[1].offset - bcm947xx_parts[0].offset;
317
318	return bcm947xx_parts;
319}
320
321EXPORT_SYMBOL(init_mtd_partitions);
322
323#endif
324