lzma loader patch from oleg, great thanks good work, saves another 300 kb flashmemory
[openwrt.git] / package / linux / kernel-source / arch / mips / brcm-boards / bcm947xx / setup.c
1 /*
2  * Generic setup routines for Broadcom MIPS boards
3  *
4  * Copyright 2004, 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$
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/time.h>
22 #include <asm/reboot.h>
23
24 #ifdef CONFIG_MTD_PARTITIONS
25 #include <linux/mtd/mtd.h>
26 #include <linux/mtd/partitions.h>
27 #endif
28
29 #include <typedefs.h>
30 #include <bcmutils.h>
31 #include <bcmnvram.h>
32 #include <sbmips.h>
33 #include <sbutils.h>
34 #include <trxhdr.h>
35
36 extern void bcm947xx_time_init(void);
37 extern void bcm947xx_timer_setup(struct irqaction *irq);
38
39 #ifdef CONFIG_REMOTE_DEBUG
40 extern void set_debug_traps(void);
41 extern void rs_kgdb_hook(struct serial_state *);
42 extern void breakpoint(void);
43 #endif
44
45 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
46 extern struct ide_ops std_ide_ops;
47 #endif
48
49 /* Global SB handle */
50 void *bcm947xx_sbh = NULL;
51 spinlock_t bcm947xx_sbh_lock = SPIN_LOCK_UNLOCKED;
52 EXPORT_SYMBOL(bcm947xx_sbh);
53 EXPORT_SYMBOL(bcm947xx_sbh_lock);
54
55 /* Convenience */
56 #define sbh bcm947xx_sbh
57 #define sbh_lock bcm947xx_sbh_lock
58
59 /* Kernel command line */
60 char arcs_cmdline[CL_SIZE] __initdata = CONFIG_CMDLINE;
61
62 void
63 bcm947xx_machine_restart(char *command)
64 {
65         printk("Please stand by while rebooting the system...\n");
66
67         /* Set the watchdog timer to reset immediately */
68         __cli();
69         sb_watchdog(sbh, 1);
70         while (1);
71 }
72
73 void
74 bcm947xx_machine_halt(void)
75 {
76         printk("System halted\n");
77
78         /* Disable interrupts and watchdog and spin forever */
79         __cli();
80         sb_watchdog(sbh, 0);
81         while (1);
82 }
83
84 #ifdef CONFIG_SERIAL
85
86 static struct serial_struct rs = {
87         line: 0,
88         flags: ASYNC_BOOT_AUTOCONF,
89         io_type: SERIAL_IO_MEM,
90 };
91
92 static void __init
93 serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
94 {
95         rs.iomem_base = regs;
96         rs.irq = irq + 2;
97         rs.baud_base = baud_base / 16;
98         rs.iomem_reg_shift = reg_shift;
99
100         early_serial_setup(&rs);
101
102         rs.line++;
103 }
104
105 static void __init
106 serial_setup(void *sbh)
107 {
108         sb_serial_init(sbh, serial_add);
109
110 #ifdef CONFIG_REMOTE_DEBUG
111         /* Use the last port for kernel debugging */
112         if (rs.iomem_base)
113                 rs_kgdb_hook(&rs);
114 #endif
115 }
116
117 #endif /* CONFIG_SERIAL */
118
119 void __init
120 brcm_setup(void)
121 {
122         char *value;
123
124         /* Get global SB handle */
125         sbh = sb_kattach();
126
127         /* Initialize clocks and interrupts */
128         sb_mips_init(sbh);
129
130 #ifdef CONFIG_SERIAL
131         /* Initialize UARTs */
132         serial_setup(sbh);
133 #endif
134
135 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
136         ide_ops = &std_ide_ops;
137 #endif
138
139         /* Override default command line arguments */
140         value = nvram_get("kernel_args");
141         if (value && strlen(value) && strncmp(value, "empty", 5))
142                 strncpy(arcs_cmdline, value, sizeof(arcs_cmdline));
143
144
145         /* Generic setup */
146         _machine_restart = bcm947xx_machine_restart;
147         _machine_halt = bcm947xx_machine_halt;
148         _machine_power_off = bcm947xx_machine_halt;
149
150         board_time_init = bcm947xx_time_init;
151         board_timer_setup = bcm947xx_timer_setup;
152 }
153
154 const char *
155 get_system_type(void)
156 {
157         return "Broadcom BCM947XX";
158 }
159
160 void __init
161 bus_error_init(void)
162 {
163 }
164
165 #ifdef CONFIG_MTD_PARTITIONS
166
167 static struct mtd_partition bcm947xx_parts[] = {
168         { name: "pmon", offset: 0, size: 0, mask_flags: MTD_WRITEABLE, },
169         { name: "linux", offset: 0, size: 0, },
170         { name: "rootfs", offset: 0, size: 0, },
171         { name: "nvram", offset: 0, size: 0, },
172         { name: "OpenWrt", offset: 0, size: 0, },
173         { name: NULL, },
174 };
175
176 static int __init
177 find_root(struct mtd_info *mtd, size_t size, struct mtd_partition *part)
178 {
179         struct trx_header *trx;
180         unsigned char buf[512];
181         int off;
182         size_t len;
183
184         trx = (struct trx_header *) buf;
185
186         for (off = (256*1024); off < size; off += mtd->erasesize) {
187                 memset(buf, 0xe5, sizeof(buf));
188
189                 /*
190                  * Read into buffer 
191                  */
192                 if (MTD_READ(mtd, off, sizeof(buf), &len, buf) ||
193                     len != sizeof(buf))
194                         continue;
195
196                 /* found a TRX header */
197                 if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
198                         part->offset = le32_to_cpu(trx->offsets[2]) ? : 
199                                 le32_to_cpu(trx->offsets[1]);
200                         part->size = le32_to_cpu(trx->len); 
201
202                         part->size -= part->offset;
203                         part->offset += off;
204
205                         goto done;
206                 }
207         }
208
209         printk(KERN_NOTICE
210                "%s: Couldn't find root filesystem\n",
211                mtd->name);
212         return -1;
213
214  done:
215                 return part->size;
216 }
217
218 struct mtd_partition * __init
219 init_mtd_partitions(struct mtd_info *mtd, size_t size)
220 {
221
222         /* boot loader */
223         bcm947xx_parts[0].offset=0;
224         bcm947xx_parts[0].size=256*1024;
225
226         /* nvram */
227         bcm947xx_parts[3].offset = size - ROUNDUP(NVRAM_SPACE, mtd->erasesize);
228         bcm947xx_parts[3].size   = size - bcm947xx_parts[3].offset;
229
230         /* Size linux (kernel and rootfs) */
231         bcm947xx_parts[1].offset = bcm947xx_parts[0].size;
232         bcm947xx_parts[1].size   = bcm947xx_parts[3].offset - bcm947xx_parts[1].offset;
233
234         /* Find and size rootfs */
235         if (find_root(mtd,size,&bcm947xx_parts[2])==0) {
236                 /* entirely jffs2 */
237                 bcm947xx_parts[2].size = bcm947xx_parts[3].offset - bcm947xx_parts[2].offset; 
238                 bcm947xx_parts[4].name = NULL;
239         } else {
240                 /* legacy setup */
241                 /* calculate leftover flash, and assign it to the jffs2 partition */
242                 bcm947xx_parts[4].offset = bcm947xx_parts[2].offset + bcm947xx_parts[2].size;
243                 bcm947xx_parts[4].offset = ROUNDUP(bcm947xx_parts[4].offset, mtd->erasesize);
244                 bcm947xx_parts[4].size = bcm947xx_parts[3].offset - bcm947xx_parts[4].offset;
245         }
246
247         return bcm947xx_parts;
248 }
249
250 EXPORT_SYMBOL(init_mtd_partitions);
251
252 #endif