
From: Ralf Baechle <ralf@linux-mips.org>

SGI IP32 aka O2 Updates:

 o Handle all possibly memory configurations
 o Fix PS/2 handling
 o Sysfs magic for IP32's GBE frame buffer driver.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/mips/Kconfig                                  |    5 
 25-akpm/arch/mips/configs/ip32_defconfig                   |   58 +++++-
 25-akpm/arch/mips/sgi-ip32/Makefile                        |    2 
 25-akpm/arch/mips/sgi-ip32/crime.c                         |    4 
 25-akpm/arch/mips/sgi-ip32/ip32-irq.c                      |    2 
 25-akpm/arch/mips/sgi-ip32/ip32-memory.c                   |   49 +++++
 25-akpm/arch/mips/sgi-ip32/ip32-reset.c                    |    4 
 25-akpm/arch/mips/sgi-ip32/ip32-setup.c                    |    6 
 25-akpm/drivers/input/serio/maceps2.c                      |   24 +-
 25-akpm/drivers/video/gbefb.c                              |  124 ++++++++++---
 25-akpm/include/asm-mips/ip32/crime.h                      |    2 
 25-akpm/include/asm-mips/mach-ip32/cpu-feature-overrides.h |   41 ++++
 25-akpm/include/asm-mips/mach-ip32/mc146818rtc.h           |    1 
 25-akpm/include/asm-mips/mach-ip32/spaces.h                |   18 -
 14 files changed, 273 insertions(+), 67 deletions(-)

diff -puN arch/mips/configs/ip32_defconfig~mips-sgi-ip32-updates arch/mips/configs/ip32_defconfig
--- 25/arch/mips/configs/ip32_defconfig~mips-sgi-ip32-updates	2005-01-29 11:26:03.115274328 -0800
+++ 25-akpm/arch/mips/configs/ip32_defconfig	2005-01-29 11:26:03.136271136 -0800
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2
-# Sun Nov 21 14:12:00 2004
+# Linux kernel version: 2.6.11-rc2
+# Wed Jan 26 02:49:04 2005
 #
 CONFIG_MIPS=y
 CONFIG_MIPS64=y
@@ -78,14 +78,16 @@ CONFIG_SGI_IP32=y
 # CONFIG_SIBYTE_SB1xxx_SOC is not set
 # CONFIG_SNI_RM200_PCI is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_ARC=y
+CONFIG_DMA_IP32=y
+CONFIG_OWN_DMA=y
 CONFIG_DMA_NONCOHERENT=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_ARC32=y
 CONFIG_BOOT_ELF32=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
-CONFIG_ARC32=y
-# CONFIG_FB is not set
 CONFIG_ARC_MEMORY=y
 CONFIG_ARC_PROMLIB=y
 
@@ -131,6 +133,20 @@ CONFIG_PCI_NAMES=y
 CONFIG_MMU=y
 
 #
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
@@ -151,6 +167,7 @@ CONFIG_BINFMT_ELF32=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -174,11 +191,13 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -191,6 +210,7 @@ CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+CONFIG_ATA_OVER_ETH=y
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -225,6 +245,7 @@ CONFIG_SCSI_LOGGING=y
 #
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -258,14 +279,12 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLOGIC_1280_1040 is not set
 CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_QLA21XX is not set
 # CONFIG_SCSI_QLA22XX is not set
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -465,6 +484,7 @@ CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
 # CONFIG_SERIO_MACEPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
 CONFIG_SERIO_RAW=y
 
 #
@@ -519,7 +539,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -550,12 +569,14 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # Graphics support
 #
+# CONFIG_FB is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -570,11 +591,25 @@ CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -678,6 +713,11 @@ CONFIG_SGI_PARTITION=y
 # CONFIG_NLS is not set
 
 #
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
@@ -697,6 +737,10 @@ CONFIG_KEYS_DEBUG_PROC_KEYS=y
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
diff -puN arch/mips/Kconfig~mips-sgi-ip32-updates arch/mips/Kconfig
--- 25/arch/mips/Kconfig~mips-sgi-ip32-updates	2005-01-29 11:26:03.117274024 -0800
+++ 25-akpm/arch/mips/Kconfig	2005-01-29 11:26:03.143270072 -0800
@@ -499,6 +499,11 @@ config REPLICATE_EXHANDLERS
 config SGI_IP32
 	bool "Support for SGI IP32 (O2) (EXPERIMENTAL)"
 	depends on MIPS64 && EXPERIMENTAL
+	select ARC
+	select ARC32
+	select BOOT_ELF32
+	select OWN_DMA
+	select DMA_IP32
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select R5000_CPU_SCACHE
diff -puN arch/mips/sgi-ip32/crime.c~mips-sgi-ip32-updates arch/mips/sgi-ip32/crime.c
--- 25/arch/mips/sgi-ip32/crime.c~mips-sgi-ip32-updates	2005-01-29 11:26:03.118273872 -0800
+++ 25-akpm/arch/mips/sgi-ip32/crime.c	2005-01-29 11:26:03.136271136 -0800
@@ -4,6 +4,7 @@
  * for more details.
  *
  * Copyright (C) 2001, 2003 Keith M Wesolowski
+ * Copyright (C) 2005 Ilya A. Volynets <ilya@total-knowledge.com>
  */
 #include <linux/types.h>
 #include <linux/init.h>
@@ -24,7 +25,8 @@ void __init crime_init(void)
 {
 	unsigned int id, rev;
 	const int field = 2 * sizeof(unsigned long);
-	
+
+	set_io_port_base((unsigned long) ioremap(MACEPCI_LOW_IO, 0x2000000));
 	crime = ioremap(CRIME_BASE, sizeof(struct sgi_crime));
 	mace = ioremap(MACE_BASE, sizeof(struct sgi_mace));
 
diff -puN arch/mips/sgi-ip32/ip32-irq.c~mips-sgi-ip32-updates arch/mips/sgi-ip32/ip32-irq.c
--- 25/arch/mips/sgi-ip32/ip32-irq.c~mips-sgi-ip32-updates	2005-01-29 11:26:03.120273568 -0800
+++ 25-akpm/arch/mips/sgi-ip32/ip32-irq.c	2005-01-29 11:26:03.137270984 -0800
@@ -117,7 +117,7 @@ static void inline flush_mace_bus(void)
  * IRQ spinlock - Ralf says not to disable CPU interrupts,
  * and I think he knows better.
  */
-static spinlock_t ip32_irq_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ip32_irq_lock);
 
 /* Some initial interrupts to set up */
 extern irqreturn_t crime_memerr_intr (int irq, void *dev_id,
diff -puN /dev/null arch/mips/sgi-ip32/ip32-memory.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/arch/mips/sgi-ip32/ip32-memory.c	2005-01-29 11:26:03.137270984 -0800
@@ -0,0 +1,49 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Keith M Wesolowski
+ * Copyright (C) 2005 Ilya A. Volynets (Total Knowledge)
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/ip32/crime.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+
+extern void crime_init(void);
+
+void __init prom_meminit (void)
+{
+	u64 base, size;
+	int bank;
+
+	crime_init();
+
+	for (bank=0; bank < CRIME_MAXBANKS; bank++) {
+		u64 bankctl = crime->bank_ctrl[bank];
+		base = (bankctl & CRIME_MEM_BANK_CONTROL_ADDR) << 25;
+		if (bank != 0 && base == 0)
+			continue;
+		size = (bankctl & CRIME_MEM_BANK_CONTROL_SDRAM_SIZE) ? 128 : 32;
+		size <<= 20;
+		if (base + size > (256 << 20))
+			base += CRIME_HI_MEM_BASE;
+
+		printk("CRIME MC: bank %u base 0x%016lx size %luMB\n",
+			bank, base, size);
+		add_memory_region (base, size, BOOT_MEM_RAM);
+	}
+}
+
+
+unsigned long __init prom_free_prom_memory (void)
+{
+	return 0;
+}
diff -puN arch/mips/sgi-ip32/ip32-reset.c~mips-sgi-ip32-updates arch/mips/sgi-ip32/ip32-reset.c
--- 25/arch/mips/sgi-ip32/ip32-reset.c~mips-sgi-ip32-updates	2005-01-29 11:26:03.121273416 -0800
+++ 25-akpm/arch/mips/sgi-ip32/ip32-reset.c	2005-01-29 11:26:03.138270832 -0800
@@ -189,11 +189,13 @@ static __init int ip32_reboot_setup(void
 	_machine_restart = ip32_machine_restart;
 	_machine_halt = ip32_machine_halt;
 	_machine_power_off = ip32_machine_power_off;
-	request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL);
+
 	init_timer(&blink_timer);
 	blink_timer.function = blink_timeout;
 	notifier_chain_register(&panic_notifier_list, &panic_block);
 
+	request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL);
+
 	return 0;
 }
 
diff -puN arch/mips/sgi-ip32/ip32-setup.c~mips-sgi-ip32-updates arch/mips/sgi-ip32/ip32-setup.c
--- 25/arch/mips/sgi-ip32/ip32-setup.c~mips-sgi-ip32-updates	2005-01-29 11:26:03.122273264 -0800
+++ 25-akpm/arch/mips/sgi-ip32/ip32-setup.c	2005-01-29 11:26:03.138270832 -0800
@@ -6,7 +6,7 @@
  * for more details.
  *
  * Copyright (C) 2000 Harald Koerfgen
- * Copyright (C) 2002, 03 Ilya A. Volynets
+ * Copyright (C) 2002, 2003, 2005 Ilya A. Volynets
  */
 #include <linux/config.h>
 #include <linux/console.h>
@@ -94,10 +94,6 @@ void __init ip32_timer_setup(struct irqa
 
 static int __init ip32_setup(void)
 {
-	set_io_port_base((unsigned long) ioremap(MACEPCI_LOW_IO, 0x2000000));
-
-	crime_init();
-
 	board_be_init = ip32_be_init;
 
 	rtc_get_time = mc146818_get_cmos_time;
diff -puN arch/mips/sgi-ip32/Makefile~mips-sgi-ip32-updates arch/mips/sgi-ip32/Makefile
--- 25/arch/mips/sgi-ip32/Makefile~mips-sgi-ip32-updates	2005-01-29 11:26:03.124272960 -0800
+++ 25-akpm/arch/mips/sgi-ip32/Makefile	2005-01-29 11:26:03.139270680 -0800
@@ -4,6 +4,6 @@
 #
 
 obj-y	+= ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-reset.o \
-	   crime.o
+	   crime.o ip32-memory.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff -puN drivers/input/serio/maceps2.c~mips-sgi-ip32-updates drivers/input/serio/maceps2.c
--- 25/drivers/input/serio/maceps2.c~mips-sgi-ip32-updates	2005-01-29 11:26:03.125272808 -0800
+++ 25-akpm/drivers/input/serio/maceps2.c	2005-01-29 11:26:03.140270528 -0800
@@ -62,8 +62,8 @@ static int maceps2_write(struct serio *d
 	unsigned int timeout = MACE_PS2_TIMEOUT;
 
 	do {
-		if (mace_read(port->status) & PS2_STATUS_TX_EMPTY) {
-			mace_write(val, port->tx);
+		if (port->status & PS2_STATUS_TX_EMPTY) {
+			port->tx = val;
 			return 0;
 		}
 		udelay(50);
@@ -72,14 +72,15 @@ static int maceps2_write(struct serio *d
 	return -1;
 }
 
-static irqreturn_t maceps2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
+				     struct pt_regs *regs)
 {
 	struct serio *dev = dev_id;
 	struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
-	unsigned int byte;
+	unsigned long byte;
 
-	if (mace_read(port->status) & PS2_STATUS_RX_FULL) {
-		byte = mace_read(port->rx);
+	if (port->status & PS2_STATUS_RX_FULL) {
+		byte = port->rx;
 		serio_interrupt(dev, byte & 0xff, 0, regs);
         }
 
@@ -96,13 +97,13 @@ static int maceps2_open(struct serio *de
 	}
 
 	/* Reset port */
-	mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
-		   data->port->control);
+	data->port->control = PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET;
 	udelay(100);
 
         /* Enable interrupts */
-	mace_write(PS2_CONTROL_RX_CLOCK_ENABLE | PS2_CONTROL_TX_ENABLE |
-		   PS2_CONTROL_RX_INT_ENABLE, data->port->control);
+	data->port->control = PS2_CONTROL_RX_CLOCK_ENABLE |
+			      PS2_CONTROL_TX_ENABLE |
+			      PS2_CONTROL_RX_INT_ENABLE;
 
 	return 0;
 }
@@ -111,8 +112,7 @@ static void maceps2_close(struct serio *
 {
 	struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
 
-	mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
-		   data->port->control);
+	data->port->control = PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET;
 	udelay(100);
 	free_irq(data->irq, dev);
 }
diff -puN drivers/video/gbefb.c~mips-sgi-ip32-updates drivers/video/gbefb.c
--- 25/drivers/video/gbefb.c~mips-sgi-ip32-updates	2005-01-29 11:26:03.126272656 -0800
+++ 25-akpm/drivers/video/gbefb.c	2005-01-29 11:26:03.142270224 -0800
@@ -85,7 +85,6 @@ static struct {
 
 static int gbe_revision;
 
-static struct fb_info fb_info;
 static int ypan, ywrap;
 
 static uint32_t pseudo_palette[256];
@@ -190,8 +189,6 @@ struct fb_var_screeninfo *default_var = 
 
 static int flat_panel_enabled = 0;
 
-static struct gbefb_par par_current;
-
 static void gbe_reset(void)
 {
 	/* Turn on dotclock PLL */
@@ -1045,6 +1042,36 @@ static struct fb_ops gbefb_ops = {
 };
 
 /*
+ * sysfs
+ */
+
+static ssize_t gbefb_show_memsize(struct device *dev, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_mem_size);
+}
+
+static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
+
+static ssize_t gbefb_show_rev(struct device *device, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
+}
+
+static DEVICE_ATTR(revision, S_IRUGO, gbefb_show_rev, NULL);
+
+static void __devexit gbefb_remove_sysfs(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_size);
+	device_remove_file(dev, &dev_attr_revision);
+}
+
+static void gbefb_create_sysfs(struct device *dev)
+{
+	device_create_file(dev, &dev_attr_size);
+	device_create_file(dev, &dev_attr_revision);
+}
+
+/*
  * Initialization
  */
 
@@ -1079,13 +1106,21 @@ int __init gbefb_setup(char *options)
 	return 0;
 }
 
-int __init gbefb_init(void)
+static int __init gbefb_probe(struct device *dev)
 {
 	int i, ret = 0;
-
+	struct fb_info *info;
+	struct gbefb_par *par;
+	struct platform_device *p_dev = to_platform_device(dev);
 #ifndef MODULE
 	char *options = NULL;
+#endif
 
+	info = framebuffer_alloc(sizeof(struct gbefb_par), &p_dev->dev);
+	if (!info)
+		return -ENOMEM;
+
+#ifndef MODULE
 	if (fb_get_options("gbefb", &options))
 		return -ENODEV;
 	gbefb_setup(options);
@@ -1093,7 +1128,8 @@ int __init gbefb_init(void)
 
 	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
 		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
-		return -EBUSY;
+		ret = -EBUSY;
+		goto out_release_framebuffer;
 	}
 
 	gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe));
@@ -1113,7 +1149,6 @@ int __init gbefb_init(void)
 		goto out_unmap;
 	}
 
-
 	if (gbe_mem_phys) {
 		/* memory was allocated at boot time */
 		gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);
@@ -1140,32 +1175,35 @@ int __init gbefb_init(void)
 	for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)
 		gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;
 
-	fb_info.fbops = &gbefb_ops;
-	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_DEFAULT;
-	fb_info.screen_base = gbe_mem;
-	fb_alloc_cmap(&fb_info.cmap, 256, 0);
+	info->fbops = &gbefb_ops;
+	info->pseudo_palette = pseudo_palette;
+	info->flags = FBINFO_DEFAULT;
+	info->screen_base = gbe_mem;
+	fb_alloc_cmap(&info->cmap, 256, 0);
 
 	/* reset GBE */
 	gbe_reset();
 
+	par = info->par;
 	/* turn on default video mode */
-	if (fb_find_mode(&par_current.var, &fb_info, mode_option, NULL, 0,
+	if (fb_find_mode(&par->var, info, mode_option, NULL, 0,
 			 default_mode, 8) == 0)
-		par_current.var = *default_var;
-	fb_info.var = par_current.var;
-	gbefb_check_var(&par_current.var, &fb_info);
-	gbefb_encode_fix(&fb_info.fix, &fb_info.var);
-	fb_info.par = &par_current;
+		par->var = *default_var;
+	info->var = par->var;
+	gbefb_check_var(&par->var, info);
+	gbefb_encode_fix(&info->fix, &info->var);
 
-	if (register_framebuffer(&fb_info) < 0) {
-		ret = -ENXIO;
+	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR "gbefb: couldn't register framebuffer\n");
+		ret = -ENXIO;
 		goto out_gbe_unmap;
 	}
 
+	dev_set_drvdata(&p_dev->dev, info);
+	gbefb_create_sysfs(dev);
+
 	printk(KERN_INFO "fb%d: %s rev %d @ 0x%08x using %dkB memory\n",
-	       fb_info.node, fb_info.fix.id, gbe_revision, (unsigned) GBE_BASE,
+	       info->node, info->fix.id, gbe_revision, (unsigned) GBE_BASE,
 	       gbe_mem_size >> 10);
 
 	return 0;
@@ -1182,12 +1220,18 @@ out_unmap:
 	iounmap(gbe);
 out_release_mem_region:
 	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
+out_release_framebuffer:
+	framebuffer_release(info);
+
 	return ret;
 }
 
-void __exit gbefb_exit(void)
+static int __devexit gbefb_remove(struct device* dev)
 {
-	unregister_framebuffer(&fb_info);
+	struct platform_device *p_dev = to_platform_device(dev);
+	struct fb_info *info = dev_get_drvdata(&p_dev->dev);
+
+	unregister_framebuffer(info);
 	gbe_turn_off();
 	if (gbe_dma_addr)
 		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
@@ -1197,12 +1241,40 @@ void __exit gbefb_exit(void)
 			  (void *)gbe_tiles.cpu, gbe_tiles.dma);
 	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
 	iounmap(gbe);
+	gbefb_remove_sysfs(dev);
+	framebuffer_release(info);
+
+	return 0;
 }
 
-module_init(gbefb_init);
+static struct device_driver gbefb_driver = {
+	.name = "gbefb",
+	.bus = &platform_bus_type,
+	.probe = gbefb_probe,
+	.remove = __devexit_p(gbefb_remove),
+};
+
+static struct platform_device gbefb_device = {
+	.name = "gbefb",
+};
 
-#ifdef MODULE
+int __init gbefb_init(void)
+{
+	int ret = driver_register(&gbefb_driver);
+	if (!ret) {
+		ret = platform_device_register(&gbefb_device);
+		if (ret)
+			driver_unregister(&gbefb_driver);
+	}
+	return ret;
+}
+
+void __exit gbefb_exit(void)
+{
+	 driver_unregister(&gbefb_driver);
+}
+
+module_init(gbefb_init);
 module_exit(gbefb_exit);
-#endif
 
 MODULE_LICENSE("GPL");
diff -puN include/asm-mips/ip32/crime.h~mips-sgi-ip32-updates include/asm-mips/ip32/crime.h
--- 25/include/asm-mips/ip32/crime.h~mips-sgi-ip32-updates	2005-01-29 11:26:03.128272352 -0800
+++ 25-akpm/include/asm-mips/ip32/crime.h	2005-01-29 11:26:03.139270680 -0800
@@ -156,4 +156,6 @@ struct sgi_crime {
 
 extern struct sgi_crime *crime;
 
+#define CRIME_HI_MEM_BASE	0x40000000	/* this is where whole 1G of RAM is mapped */
+
 #endif /* __ASM_CRIME_H__ */
diff -puN /dev/null include/asm-mips/mach-ip32/cpu-feature-overrides.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/include/asm-mips/mach-ip32/cpu-feature-overrides.h	2005-01-29 11:26:03.145269768 -0800
@@ -0,0 +1,41 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Ilya A. Volynets-Evenbakh
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H
+
+#include <linux/config.h>
+
+/*
+ * R5000 has an interesting "restriction":  ll(d)/sc(d)
+ * instructions to XKPHYS region simply do uncached bus
+ * requests. This breaks all the atomic bitops functions.
+ * so, for 64bit IP32 kernel we just don't use ll/sc.
+ * This does not affect luserland.
+ */
+#if defined(CONFIG_CPU_R5000) && defined(CONFIG_MIPS64)
+#define cpu_has_llsc		0
+#else
+#define cpu_has_llsc		1
+#endif
+
+/* Settings which are common for all ip32 CPUs */
+#define cpu_has_tlb		1
+#define cpu_has_4kex		1
+#define cpu_has_fpu		1
+#define cpu_has_32fpr		1
+#define cpu_has_counter		1
+#define cpu_has_mips16		0
+#define cpu_has_vce		0
+#define cpu_has_cache_cdex_s	0
+#define cpu_has_mcheck		0
+#define cpu_has_ejtag		0
+#define cpu_has_vtag_icache	0
+#define cpu_has_ic_fills_f_dc	0
+
+#endif /* __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H */
diff -puN include/asm-mips/mach-ip32/mc146818rtc.h~mips-sgi-ip32-updates include/asm-mips/mach-ip32/mc146818rtc.h
--- 25/include/asm-mips/mach-ip32/mc146818rtc.h~mips-sgi-ip32-updates	2005-01-29 11:26:03.130272048 -0800
+++ 25-akpm/include/asm-mips/mach-ip32/mc146818rtc.h	2005-01-29 11:26:03.144269920 -0800
@@ -15,7 +15,6 @@
 #include <asm/ip32/mace.h>
 
 #define RTC_PORT(x)	(0x70 + (x))
-#define RTC_IRQ		MACEISA_RTC_IRQ
 
 static unsigned char CMOS_READ(unsigned long addr)
 {
diff -puN include/asm-mips/mach-ip32/spaces.h~mips-sgi-ip32-updates include/asm-mips/mach-ip32/spaces.h
--- 25/include/asm-mips/mach-ip32/spaces.h~mips-sgi-ip32-updates	2005-01-29 11:26:03.131271896 -0800
+++ 25-akpm/include/asm-mips/mach-ip32/spaces.h	2005-01-29 11:26:03.144269920 -0800
@@ -3,20 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 1994 - 1999, 2000, 03, 04, 05 Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2000, 2002  Maciej W. Rozycki
  * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_MACH_IP32_SPACES_H
 #define _ASM_MACH_IP32_SPACES_H
 
-#include <linux/config.h>
-
-/*
- * This handles the memory map.
- */
-#define PAGE_OFFSET		0xffffffff80000000
-
 /*
  * Memory above this physical address will be considered highmem.
  * Fixme: 59 bits is a fictive number and makes assumptions about processors
@@ -26,11 +19,7 @@
 #define HIGHMEM_START		(1UL << 59UL)
 #endif
 
-#ifdef CONFIG_DMA_NONCOHERENT
 #define CAC_BASE		0x9800000000000000
-#else
-#define CAC_BASE		0xa800000000000000
-#endif
 #define IO_BASE			0x9000000000000000
 #define UNCAC_BASE		0x9000000000000000
 #define MAP_BASE		0xc000000000000000
@@ -39,4 +28,9 @@
 #define TO_CAC(x)		(CAC_BASE   | ((x) & TO_PHYS_MASK))
 #define TO_UNCAC(x)		(UNCAC_BASE | ((x) & TO_PHYS_MASK))
 
+/*
+ * This handles the memory map.
+ */
+#define PAGE_OFFSET		CAC_BASE
+
 #endif /* __ASM_MACH_IP32_SPACES_H */
_
