From: Tom Rini <trini@kernel.crashing.org>

From: Randy Vinson <rvinson@mvista.com>

- Fixup IBM Spruce support (GEN550, general fixes and cleanups).
- Forward-port the INTERACTIVE_CONSOLE bits from 2.4.
- Forward-port the bootinfo code.
- Add a weak get_mem_size() function.



---

 25-akpm/arch/ppc/Kconfig                   |    2 
 25-akpm/arch/ppc/boot/common/bootinfo.c    |   70 ++++++++
 25-akpm/arch/ppc/boot/simple/Makefile      |    4 
 25-akpm/arch/ppc/boot/simple/misc-spruce.c |  235 ++++-------------------------
 25-akpm/arch/ppc/boot/simple/misc.c        |   85 +++++-----
 25-akpm/arch/ppc/platforms/spruce.h        |   32 +++
 25-akpm/arch/ppc/platforms/spruce_setup.c  |   83 +++++++++-
 25-akpm/include/asm-ppc/bootinfo.h         |   11 +
 8 files changed, 266 insertions(+), 256 deletions(-)

diff -puN /dev/null arch/ppc/boot/common/bootinfo.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/arch/ppc/boot/common/bootinfo.c	Tue Feb 10 12:54:20 2004
@@ -0,0 +1,70 @@
+/*
+ * arch/ppc/common/bootinfo.c
+ *
+ * General bootinfo record utilities
+ * Author: Randy Vinson <rvinson@mvista.com>
+ *
+ * 2002 (c) MontaVista Software, Inc. This file is licensed under the terms
+ * of the GNU General Public License version 2. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/bootinfo.h>
+
+#include "nonstdio.h"
+
+static struct bi_record * birec = NULL;
+
+static struct bi_record *
+__bootinfo_build(struct bi_record *rec, unsigned long tag, unsigned long size,
+		 void *data)
+{
+	/* set the tag */
+	rec->tag = tag;
+
+	/* if the caller has any data, copy it */
+	if (size)
+		memcpy(rec->data, (char *)data, size);
+
+	/* set the record size */
+	rec->size = sizeof(struct bi_record) + size;
+
+	/* advance to the next available space */
+	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+
+	return rec;
+}
+
+void
+bootinfo_init(struct bi_record *rec)
+{
+
+	/* save start of birec area */
+	birec = rec;
+
+	/* create an empty list */
+	rec = __bootinfo_build(rec, BI_FIRST, 0, NULL);
+	(void) __bootinfo_build(rec, BI_LAST, 0, NULL);
+
+}
+
+void
+bootinfo_append(unsigned long tag, unsigned long size, void * data)
+{
+
+	struct bi_record *rec = birec;
+
+	/* paranoia */
+	if ((rec == NULL) || (rec->tag != BI_FIRST))
+		return;
+
+	/* find the last entry in the list */
+	while (rec->tag != BI_LAST)
+		rec = (struct bi_record *)((ulong)rec + rec->size);
+
+	/* overlay BI_LAST record with new one and tag on a new BI_LAST */
+	rec = __bootinfo_build(rec, tag, size, data);
+	(void) __bootinfo_build(rec, BI_LAST, 0, NULL);
+}
diff -puN arch/ppc/boot/simple/Makefile~ppc32-boot-platform-fixes arch/ppc/boot/simple/Makefile
--- 25/arch/ppc/boot/simple/Makefile~ppc32-boot-platform-fixes	Tue Feb 10 12:54:20 2004
+++ 25-akpm/arch/ppc/boot/simple/Makefile	Tue Feb 10 12:54:20 2004
@@ -30,7 +30,7 @@ tftpboot			:= /tftpboot
 
 # Normally, we use the 'misc.c' file for decompress_kernel and
 # whatnot.  Sometimes we need to override this however.
-misc-y	:= misc.o
+misc-y	:= misc.o ../common/bootinfo.o
 
 # Normally, we have our images end in .elf, but something we want to
 # change this.
@@ -103,7 +103,7 @@ zimageinitrd-$(pcore)			:= zImage.initrd
 zimageinitrd-$(CONFIG_SPRUCE)		:= zImage.initrd-TREE
          end-$(CONFIG_SPRUCE)		:= spruce
   entrypoint-$(CONFIG_SPRUCE)		:= 0x00800000
-        misc-$(CONFIG_SPRUCE)		:= misc-spruce.o
+        misc-$(CONFIG_SPRUCE)		+= misc-spruce.o
 
 # SMP images should have a '.smp' suffix.
          end-$(CONFIG_SMP)		+= .smp
diff -puN arch/ppc/boot/simple/misc.c~ppc32-boot-platform-fixes arch/ppc/boot/simple/misc.c
--- 25/arch/ppc/boot/simple/misc.c~ppc32-boot-platform-fixes	Tue Feb 10 12:54:20 2004
+++ 25-akpm/arch/ppc/boot/simple/misc.c	Tue Feb 10 12:54:20 2004
@@ -1,5 +1,5 @@
 /*
- * arch/ppc/common/misc-simple.c
+ * arch/ppc/simple/misc.c
  *
  * Misc. bootloader code for many machines.  This assumes you have are using
  * a 6xx/7xx/74xx CPU in your machine.  This assumes the chunk of memory
@@ -46,6 +46,15 @@
 #define HAS_KEYB 0
 #endif
 
+/* Will / Can the user give input?
+ * Val Henson has requested that Gemini doesn't wait for the
+ * user to edit the cmdline or not.
+ */
+#if (defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_VGA_CONSOLE)) \
+	&& !defined(CONFIG_GEMINI)
+#define INTERACTIVE_CONSOLE	1
+#endif
+
 char *avail_ram;
 char *end_avail;
 char *zimage_start;
@@ -66,19 +75,28 @@ extern char _end[];
 extern unsigned long start;
 
 extern int CRT_tstc(void);
-extern unsigned long get_mem_size(void);
 extern unsigned long serial_init(int chan, void *ignored);
 extern void serial_close(unsigned long com_port);
 extern void gunzip(void *, int, unsigned char *, int *);
 extern void serial_fixups(void);
 
+/* Allow get_mem_size to be hooked into.  This is the default. */
+unsigned long __attribute__ ((weak))
+get_mem_size(void)
+{
+	return 0;
+}
+
 struct bi_record *
 decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
 {
+#ifdef INTERACTIVE_CONSOLE
 	int timer = 0;
-	char *cp, ch;
+	char ch;
+#endif
+	char *cp;
 	struct bi_record *rec;
-	unsigned long TotalMemory = 0, rec_loc, initrd_loc;
+	unsigned long initrd_loc, TotalMemory = 0;
 
 	serial_fixups();
 	com_port = serial_init(0, NULL);
@@ -93,13 +111,11 @@ decompress_kernel(unsigned long load_add
 	__asm__ __volatile__("eieio");
 #endif
 
-#if defined(CONFIG_LOPEC) || defined(CONFIG_PAL4)
 	/*
 	 * Call get_mem_size(), which is memory controller dependent,
 	 * and we must have the correct file linked in here.
 	 */
 	TotalMemory = get_mem_size();
-#endif
 
 	/* assume the chunk below 8M is free */
 	end_avail = (char *)0x00800000;
@@ -170,9 +186,11 @@ decompress_kernel(unsigned long load_add
 	memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
 	while ( *cp ) putc(*cp++);
 
-#ifndef CONFIG_GEMINI
-	/* Val Henson has requested that Gemini doesn't wait for the
-	 * user to edit the cmdline or not. */
+#ifdef INTERACTIVE_CONSOLE
+	/*
+	 * If they have a console, allow them to edit the command line.
+	 * Otherwise, don't bother wasting the five seconds.
+	 */
 	while (timer++ < 5*1000) {
 		if (tstc()) {
 			while ((ch = getc()) != '\n' && ch != '\r') {
@@ -205,16 +223,13 @@ decompress_kernel(unsigned long load_add
 	gunzip(0, 0x400000, zimage_start, &zimage_size);
 	puts("done.\n");
 
-	/*
-	 * Create bi_recs for cmd_line and initrds
-	 */
-	rec_loc = _ALIGN((unsigned long)(zimage_size) +
-			(1 << 20) - 1, (1 << 20));
-	rec = (struct bi_record *)rec_loc;
+	/* get the bi_rec address */
+	rec = bootinfo_addr(zimage_size);
 
 	/* We need to make sure that the initrd and bi_recs do not
 	 * overlap. */
 	if ( initrd_size ) {
+		unsigned long rec_loc = (unsigned long) rec;
 		initrd_loc = (unsigned long)(&__ramdisk_begin);
 		/* If the bi_recs are in the middle of the current
 		 * initrd, move the initrd to the next MB
@@ -231,39 +246,25 @@ decompress_kernel(unsigned long load_add
 		}
 	}
 
-	rec->tag = BI_FIRST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	if ( TotalMemory ) {
-		rec->tag = BI_MEMSIZE;
-		rec->data[0] = TotalMemory;
-		rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-		rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	}
+	bootinfo_init(rec);
+	if ( TotalMemory )
+		bootinfo_append(BI_MEMSIZE, sizeof(int), (void*)&TotalMemory);
 
-	rec->tag = BI_CMD_LINE;
-	memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
-	rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+	bootinfo_append(BI_CMD_LINE, strlen(cmd_line)+1, (void*)cmd_line);
 
-	if ( initrd_size ) {
-		rec->tag = BI_INITRD;
-		rec->data[0] = initrd_loc;
-		rec->data[1] = initrd_size;
-		rec->size = sizeof(struct bi_record) + 2 *
-			sizeof(unsigned long);
-		rec = (struct bi_record *)((unsigned long)rec +
-				rec->size);
-	}
+	/* add a bi_rec for the initrd if it exists */
+	if (initrd_size) {
+		unsigned long initrd[2];
 
-	rec->tag = BI_LAST;
-	rec->size = sizeof(struct bi_record);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
+		initrd[0] = initrd_loc;
+		initrd[1] = initrd_size;
+
+		bootinfo_append(BI_INITRD, sizeof(initrd), &initrd);
+	}
 	puts("Now booting the kernel\n");
 	serial_close(com_port);
 
-	return (struct bi_record *)rec_loc;
+	return rec;
 }
 
 /* Allow decompress_kernel to be hooked into.  This is the default. */
diff -puN arch/ppc/boot/simple/misc-spruce.c~ppc32-boot-platform-fixes arch/ppc/boot/simple/misc-spruce.c
--- 25/arch/ppc/boot/simple/misc-spruce.c~ppc32-boot-platform-fixes	Tue Feb 10 12:54:20 2004
+++ 25-akpm/arch/ppc/boot/simple/misc-spruce.c	Tue Feb 10 12:54:20 2004
@@ -15,55 +15,19 @@
  */
 
 #include <linux/types.h>
-#include <linux/elf.h>
 #include <linux/config.h>
 #include <linux/pci.h>
 
-#include <asm/page.h>
-#include <asm/mmu.h>
 #include <asm/bootinfo.h>
 
-#include "zlib.h"
+extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
+				       unsigned long cksum);
 
 /* Define some important locations of the Spruce. */
 #define SPRUCE_PCI_CONFIG_ADDR	0xfec00000
 #define SPRUCE_PCI_CONFIG_DATA	0xfec00004
 #define SPRUCE_ISA_IO_BASE	0xf8000000
 
-unsigned long com_port;
-
-char *avail_ram;
-char *end_avail;
-
-/* The linker tells us where the image is. */
-extern char __image_begin, __image_end;
-extern char __ramdisk_begin, __ramdisk_end;
-extern char _end[];
-
-#ifdef CONFIG_CMDLINE
-#define CMDLINE CONFIG_CMDLINE
-#else
-#define CMDLINE ""
-#endif
-char cmd_preset[] = CMDLINE;
-char cmd_buf[256];
-char *cmd_line = cmd_buf;
-
-unsigned long initrd_size = 0;
-
-char *zimage_start;
-int zimage_size;
-
-extern void udelay(long);
-extern void puts(const char *);
-extern void putc(const char c);
-extern void puthex(unsigned long val);
-extern int getc(void);
-extern int tstc(void);
-extern void gunzip(void *, int, unsigned char *, int *);
-
-extern unsigned long serial_init(int chan, void *ignored);
-
 /* PCI configuration space access routines. */
 unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR;
 unsigned char *pci_config_data   = (unsigned char *)SPRUCE_PCI_CONFIG_DATA;
@@ -146,45 +110,16 @@ unsigned long isa_io_base = SPRUCE_ISA_I
 #define MEM_B2EA	0x60
 
 unsigned long
-load_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
+get_mem_size(void)
 {
-	int timer = 0;
-	char *cp, ch;
-
 	int loop;
-	int csr0;
-	int csr_id;
-	int *mem_addr = (int *)0xff500008;
-	int *mem_data = (int *)0xff50000c;
-	int mem_size = 0;
+	unsigned long mem_size = 0;
 	unsigned long mem_mben;
 	unsigned long mem_type;
 	unsigned long mem_start;
 	unsigned long mem_end;
-	int *pif_addr = (int *)0xff500000;
-	int *pif_data = (int *)0xff500004;
-	int pci_devfn;
-	int found_multi = 0;
-	unsigned short vendor;
-	unsigned short device;
-	unsigned short command;
-	unsigned char header_type;
-	unsigned int bar0;
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-	/* Initialize the serial console port */
-	com_port = serial_init(0, NULL);
-#endif
-
-	/*
-	 * Gah, these firmware guys need to learn that hardware
-	 * byte swapping is evil! Disable all hardware byte
-	 * swapping so it doesn't hurt anyone.
-	 */
-	*pif_addr = PLBMIFOPT;
-	asm("sync");
-	*pif_data = 0x00000000;
-	asm("sync");
+	volatile int *mem_addr = (int *)0xff500008;
+	volatile int *mem_data = (int *)0xff50000c;
 
 	/* Get the size of memory from the memory controller. */
 	*mem_addr = MEM_MBEN;
@@ -235,6 +170,33 @@ load_kernel(unsigned long load_addr, int
 
 		mem_size += mem_end - mem_start + 0x100000;
 	}
+	return mem_size;
+}
+
+unsigned long
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
+{
+	int csr0;
+	int csr_id;
+	int pci_devfn;
+	int found_multi = 0;
+	unsigned short vendor;
+	unsigned short device;
+	unsigned short command;
+	unsigned char header_type;
+	unsigned int bar0;
+	volatile int *pif_addr = (int *)0xff500000;
+	volatile int *pif_data = (int *)0xff500004;
+
+	/*
+	 * Gah, these firmware guys need to learn that hardware
+	 * byte swapping is evil! Disable all hardware byte
+	 * swapping so it doesn't hurt anyone.
+	 */
+	*pif_addr = PLBMIFOPT;
+	asm("sync");
+	*pif_data = 0x00000000;
+	asm("sync");
 
 	/* Search out and turn off the PcNet ethernet boot device. */
 	for (pci_devfn = 1; pci_devfn < 0xff; pci_devfn++) {
@@ -310,134 +272,5 @@ load_kernel(unsigned long load_addr, int
 		}
 	}
 
-	/* assume the chunk below 8M is free */
-	end_avail = (char *)0x00800000;
-
-	/*
-	 * We link ourself to 0x00800000.  When we run, we relocate
-	 * ourselves there.  So we just need __image_begin for the
-	 * start. -- Tom
-	 */
-	zimage_start = (char *)(unsigned long)(&__image_begin);
-	zimage_size = (unsigned long)(&__image_end) -
-			(unsigned long)(&__image_begin);
-
-	initrd_size = (unsigned long)(&__ramdisk_end) -
-		(unsigned long)(&__ramdisk_begin);
-
-	/*
-	 * The zImage and initrd will be between start and _end, so they've
-	 * already been moved once.  We're good to go now. -- Tom
-	 */
-	avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
-	puts("zimage at:     "); puthex((unsigned long)zimage_start);
-	puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
-	puts("\n");
-
-	if ( initrd_size ) {
-		puts("initrd at:     ");
-		puthex((unsigned long)(&__ramdisk_begin));
-		puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
-	}
-
-	avail_ram = (char *)0x00400000;
-	end_avail = (char *)0x00800000;
-	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
-	puthex((unsigned long)end_avail); puts("\n");
-
-	/* Display standard Linux/PPC boot prompt for kernel args */
-	puts("\nLinux/PPC load: ");
-	cp = cmd_line;
-	memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
-	while ( *cp ) putc(*cp++);
-	while (timer++ < 5*1000) {
-		if (tstc()) {
-			while ((ch = getc()) != '\n' && ch != '\r') {
-				if (ch == '\b') {
-					if (cp != cmd_line) {
-						cp--;
-						puts("\b \b");
-					}
-				} else {
-					*cp++ = ch;
-					putc(ch);
-				}
-			}
-			break;  /* Exit 'timer' loop */
-		}
-		udelay(1000);  /* 1 msec */
-	}
-	*cp = 0;
-	puts("\n");
-
-	puts("Uncompressing Linux...");
-
-	gunzip(0, 0x400000, zimage_start, &zimage_size);
-
-	puts("done.\n");
-
-	{
-		struct bi_record *rec;
-		unsigned long initrd_loc;
-		unsigned long rec_loc = _ALIGN((unsigned long)(zimage_size) +
-				(1 << 20) - 1, (1 << 20));
-		rec = (struct bi_record *)rec_loc;
-
-		/* We need to make sure that the initrd and bi_recs do not
-		 * overlap. */
-		if ( initrd_size ) {
-			initrd_loc = (unsigned long)(&__ramdisk_begin);
-			/* If the bi_recs are in the middle of the current
-			 * initrd, move the initrd to the next MB
-			 * boundary. */
-			if ((rec_loc > initrd_loc) &&
-					((initrd_loc + initrd_size)
-					 > rec_loc)) {
-				initrd_loc = _ALIGN((unsigned long)(zimage_size)
-						+ (2 << 20) - 1, (2 << 20));
-			 	memmove((void *)initrd_loc, &__ramdisk_begin,
-					 initrd_size);
-		         	puts("initrd moved:  "); puthex(initrd_loc);
-			 	puts(" "); puthex(initrd_loc + initrd_size);
-			 	puts("\n");
-			}
-		}
-
-		rec->tag = BI_FIRST;
-        	rec->size = sizeof(struct bi_record);
-        	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-        	rec->tag = BI_BOOTLOADER_ID;
-        	memcpy( (void *)rec->data, "spruceboot", 11);
-        	rec->size = sizeof(struct bi_record) + 10 + 1;
-        	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-        	rec->tag = BI_MEMSIZE;
-        	rec->data[0] = mem_size;
-        	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-        	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-        	rec->tag = BI_CMD_LINE;
-        	memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
-        	rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
-        	rec = (struct bi_record *)((ulong)rec + rec->size);
-
-		if ( initrd_size ) {
-			rec->tag = BI_INITRD;
-			rec->data[0] = initrd_loc;
-			rec->data[1] = initrd_size;
-			rec->size = sizeof(struct bi_record) + 2 *
-				sizeof(unsigned long);
-			rec = (struct bi_record *)((unsigned long)rec +
-					rec->size);
-		}
-
-        	rec->tag = BI_LAST;
-        	rec->size = sizeof(struct bi_record);
-        	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	}
-
-	puts("Now booting the kernel\n");
-
-	return 0;
+	return decompress_kernel(load_addr, num_words, cksum);
 }
diff -puN arch/ppc/Kconfig~ppc32-boot-platform-fixes arch/ppc/Kconfig
--- 25/arch/ppc/Kconfig~ppc32-boot-platform-fixes	Tue Feb 10 12:54:20 2004
+++ 25-akpm/arch/ppc/Kconfig	Tue Feb 10 12:54:20 2004
@@ -604,7 +604,7 @@ config PPC_OF
 
 config PPC_GEN550
 	bool
-	depends on SANDPOINT || MCPN765
+	depends on SANDPOINT || MCPN765 || SPRUCE
 	default y
 
 config FORCE
diff -puN arch/ppc/platforms/spruce.h~ppc32-boot-platform-fixes arch/ppc/platforms/spruce.h
--- 25/arch/ppc/platforms/spruce.h~ppc32-boot-platform-fixes	Tue Feb 10 12:54:20 2004
+++ 25-akpm/arch/ppc/platforms/spruce.h	Tue Feb 10 12:54:20 2004
@@ -35,11 +35,37 @@
 #define SPRUCE_MEM_SIZE		0x04000000
 #define SPRUCE_BUS_SPEED	66666667
 
-#define SPRUCE_SERIAL_1_ADDR	0xff600300
-#define SPRUCE_SERIAL_2_ADDR	0xff600400
-
 #define SPRUCE_NVRAM_BASE_ADDR	0xff800000
 #define SPRUCE_RTC_BASE_ADDR	SPRUCE_NVRAM_BASE_ADDR
 
+/*
+ * Serial port defines
+ */
+#define SPRUCE_FPGA_REG_A	0xff820000
+#define SPRUCE_UARTCLK_33M	0x02
+#define SPRUCE_UARTCLK_IS_33M(reg)	(reg & SPRUCE_UARTCLK_33M)
+
+#define UART0_IO_BASE	0xff600300
+#define UART1_IO_BASE	0xff600400
+
+#define RS_TABLE_SIZE	2
+
+#define SPRUCE_BAUD_33M	(33000000/64)
+#define SPRUCE_BAUD_30M	(30000000/64)
+#define BASE_BAUD	SPRUCE_BAUD_33M
+
+#define UART0_INT	3
+#define UART1_INT	4
+
+#define STD_UART_OP(num)				\
+	{ 0, BASE_BAUD, 0, UART##num##_INT,		\
+		ASYNC_BOOT_AUTOCONF,			\
+		iomem_base: UART##num##_IO_BASE,	\
+		io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS	\
+	STD_UART_OP(0)		\
+	STD_UART_OP(1)
+
 #endif /* __ASM_SPRUCE_H__ */
 #endif /* __KERNEL__ */
diff -puN arch/ppc/platforms/spruce_setup.c~ppc32-boot-platform-fixes arch/ppc/platforms/spruce_setup.c
--- 25/arch/ppc/platforms/spruce_setup.c~ppc32-boot-platform-fixes	Tue Feb 10 12:54:20 2004
+++ 25-akpm/arch/ppc/platforms/spruce_setup.c	Tue Feb 10 12:54:20 2004
@@ -28,6 +28,9 @@
 #include <linux/seq_file.h>
 #include <linux/ide.h>
 #include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -39,6 +42,7 @@
 #include <platforms/spruce.h>
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
+#include <asm/kgdb.h>
 
 #include <syslib/cpc700.h>
 
@@ -103,6 +107,46 @@ spruce_show_cpuinfo(struct seq_file *m)
 	return 0;
 }
 
+static void __init
+spruce_early_serial_map(void)
+{
+	u32 uart_clk;
+	struct uart_port serial_req;
+
+	if (SPRUCE_UARTCLK_IS_33M(readb(SPRUCE_FPGA_REG_A)))
+		uart_clk = SPRUCE_BAUD_33M * 16;
+	else
+		uart_clk = SPRUCE_BAUD_30M * 16;
+
+	/* Setup serial port access */
+	memset(&serial_req, 0, sizeof(serial_req));
+	serial_req.uartclk = uart_clk;
+	serial_req.irq = UART0_INT;
+	serial_req.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.membase = (u_char *)UART0_IO_BASE;
+	serial_req.regshift = 0;
+
+	gen550_init(0, &serial_req);
+
+#ifdef CONFIG_SERIAL_8250
+	if (early_serial_setup(&serial_req) != 0)
+		printk("Early serial init of port 0 failed\n");
+#endif
+
+	/* Assume early_serial_setup() doesn't modify serial_req */
+	serial_req.line = 1;
+	serial_req.irq = UART1_INT;
+	serial_req.membase = (u_char *)UART1_IO_BASE;
+
+	gen550_init(1, &serial_req);
+
+#ifdef CONFIG_SERIAL_8250
+	if (early_serial_setup(&serial_req) != 0)
+		printk("Early serial init of port 1 failed\n");
+#endif
+}
+
 TODC_ALLOC();
 
 static void __init
@@ -128,10 +172,11 @@ spruce_setup_arch(void)
 		ROOT_DEV = Root_SDA1;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
+#ifdef CONFIG_VT
 	conswitchp = &dummy_con;
 #endif
 
+
 	/* Identify the system */
 	printk(KERN_INFO "System Identification: IBM Spruce\n");
 	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
@@ -146,12 +191,12 @@ spruce_restart(char *cmd)
 	/* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
 	__asm__ __volatile__
 	("\n\
-	lis	3,0xfff0
-	ori	3,3,0x0100
-	mtspr	26,3
-	li	3,0
-	mtspr	27,3
-	rfi
+	lis	3,0xfff0	\n\
+	ori	3,3,0x0100	\n\
+	mtspr	26,3		\n\
+	li	3,0		\n\
+	mtspr	27,3		\n\
+	rfi			\n\
 	");
 	for(;;);
 }
@@ -175,12 +220,27 @@ spruce_map_io(void)
 			 0x08000000, _PAGE_IO);
 }
 
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+spruce_set_bat(void)
+{
+	mb();
+	mtspr(DBAT1U, 0xf8000ffe);
+	mtspr(DBAT1L, 0xf800002a);
+	mb();
+}
+
 void __init
 platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	      unsigned long r6, unsigned long r7)
 {
 	parse_bootinfo(find_bootinfo());
 
+	/* Map in board regs, etc. */
+	spruce_set_bat();
+
 	isa_io_base = SPRUCE_ISA_IO_BASE;
 	pci_dram_offset = SPRUCE_PCI_SYS_MEM_BASE;
 
@@ -202,4 +262,13 @@ platform_init(unsigned long r3, unsigned
 
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
+
+	spruce_early_serial_map();
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#ifdef CONFIG_KGDB
+	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
+#endif
 }
diff -puN include/asm-ppc/bootinfo.h~ppc32-boot-platform-fixes include/asm-ppc/bootinfo.h
--- 25/include/asm-ppc/bootinfo.h~ppc32-boot-platform-fixes	Tue Feb 10 12:54:20 2004
+++ 25-akpm/include/asm-ppc/bootinfo.h	Tue Feb 10 12:54:20 2004
@@ -10,6 +10,7 @@
 #define _PPC_BOOTINFO_H
 
 #include <linux/config.h>
+#include <asm/page.h>
 
 #if defined(CONFIG_APUS) && !defined(__BOOTER__)
 #include <asm-m68k/bootinfo.h>
@@ -29,11 +30,21 @@ struct bi_record {
 #define BI_SYSMAP		0x1015
 #define BI_MACHTYPE		0x1016
 #define BI_MEMSIZE		0x1017
+#define BI_BOARD_INFO		0x1018
 
 extern struct bi_record *find_bootinfo(void);
+extern void bootinfo_init(struct bi_record *rec);
+extern void bootinfo_append(unsigned long tag, unsigned long size, void * data);
 extern void parse_bootinfo(struct bi_record *rec);
 extern unsigned long boot_mem_size;
 
+static inline struct bi_record *
+bootinfo_addr(unsigned long offset)
+{
+
+	return (struct bi_record *)_ALIGN((offset) + (1 << 20) - 1,
+					  (1 << 20));
+}
 #endif /* CONFIG_APUS */
 
 

_