+obj-y := irq.o int-handler.o prom.o setup.o time.o pci.o
diff -urN linux.old/arch/mips/bcm947xx/broadcom/Makefile linux.dev/arch/mips/bcm947xx/broadcom/Makefile
--- linux.old/arch/mips/bcm947xx/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/bcm947xx/broadcom/Makefile 2005-12-15 16:59:40.571216500 +0100
++++ linux.dev/arch/mips/bcm947xx/broadcom/Makefile 2005-12-17 20:51:17.749271000 +0100
@@ -0,0 +1,6 @@
+#
+# Makefile for the BCM47xx specific kernel interface routines
+# under Linux.
+#
+
-+obj-y := sbutils.o linux_osl.o bcmsrom.o bcmutils.o sbmips.o sbpci.o sflash.o nvram.o
++obj-y := sbutils.o linux_osl.o bcmsrom.o bcmutils.o sbmips.o sbpci.o sflash.o nvram.o cfe_env.o
diff -urN linux.old/arch/mips/bcm947xx/broadcom/bcmsrom.c linux.dev/arch/mips/bcm947xx/broadcom/bcmsrom.c
--- linux.old/arch/mips/bcm947xx/broadcom/bcmsrom.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/bcm947xx/broadcom/bcmsrom.c 2005-12-15 17:35:21.719238750 +0100
-@@ -0,0 +1,483 @@
++++ linux.dev/arch/mips/bcm947xx/broadcom/bcmsrom.c 2005-12-17 01:21:23.007883000 +0100
+@@ -0,0 +1,481 @@
+/*
+ * Misc useful routines to access NIC SROM/OTP .
+ *
+ int woff, i;
+ char *vp, *base;
+ osl_t *osh = sb_osh(sbh);
-+ char name[SB_DEVPATH_BUFSZ+16], *value;
-+ char devpath[SB_DEVPATH_BUFSZ];
+ int err;
+
+ /*
+
diff -urN linux.old/arch/mips/bcm947xx/broadcom/bcmutils.c linux.dev/arch/mips/bcm947xx/broadcom/bcmutils.c
--- linux.old/arch/mips/bcm947xx/broadcom/bcmutils.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/bcm947xx/broadcom/bcmutils.c 2005-12-15 20:14:31.420035750 +0100
-@@ -0,0 +1,358 @@
++++ linux.dev/arch/mips/bcm947xx/broadcom/bcmutils.c 2005-12-17 17:53:52.387365000 +0100
+@@ -0,0 +1,356 @@
+/*
+ * Misc useful OS-independent routines.
+ *
+#define CNBUFS 5
+
+#endif
+diff -urN linux.old/arch/mips/bcm947xx/broadcom/cfe_env.c linux.dev/arch/mips/bcm947xx/broadcom/cfe_env.c
+--- linux.old/arch/mips/bcm947xx/broadcom/cfe_env.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.dev/arch/mips/bcm947xx/broadcom/cfe_env.c 2005-12-17 21:40:08.166726750 +0100
+@@ -0,0 +1,234 @@
++/*
++ * NVRAM variable manipulation (Linux kernel half)
++ *
++ * Copyright 2001-2003, Broadcom Corporation
++ * All Rights Reserved.
++ *
++ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
++ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
++ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
++ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
++ *
++ * $Id$
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <typedefs.h>
++#include <osl.h>
++#include <bcmendian.h>
++#include <bcmutils.h>
++
++#define NVRAM_SIZE (0x1ff0)
++static char _nvdata[NVRAM_SIZE] __initdata;
++static char _valuestr[256] __initdata;
++
++/*
++ * TLV types. These codes are used in the "type-length-value"
++ * encoding of the items stored in the NVRAM device (flash or EEPROM)
++ *
++ * The layout of the flash/nvram is as follows:
++ *
++ * <type> <length> <data ...> <type> <length> <data ...> <type_end>
++ *
++ * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
++ * The "length" field marks the length of the data section, not
++ * including the type and length fields.
++ *
++ * Environment variables are stored as follows:
++ *
++ * <type_env> <length> <flags> <name> = <value>
++ *
++ * If bit 0 (low bit) is set, the length is an 8-bit value.
++ * If bit 0 (low bit) is clear, the length is a 16-bit value
++ *
++ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
++ * indicates the size of the length field.
++ *
++ * Flags are from the constants below:
++ *
++ */
++#define ENV_LENGTH_16BITS 0x00 /* for low bit */
++#define ENV_LENGTH_8BITS 0x01
++
++#define ENV_TYPE_USER 0x80
++
++#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
++#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
++
++/*
++ * The actual TLV types we support
++ */
++
++#define ENV_TLV_TYPE_END 0x00
++#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
++
++/*
++ * Environment variable flags
++ */
++
++#define ENV_FLG_NORMAL 0x00 /* normal read/write */
++#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
++#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
++
++#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
++#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
++
++
++/* *********************************************************************
++ * _nvram_read(buffer,offset,length)
++ *
++ * Read data from the NVRAM device
++ *
++ * Input parameters:
++ * buffer - destination buffer
++ * offset - offset of data to read
++ * length - number of bytes to read
++ *
++ * Return value:
++ * number of bytes read, or <0 if error occured
++ ********************************************************************* */
++static int
++_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
++{
++ int i;
++ if (offset > NVRAM_SIZE)
++ return -1;
++
++ for ( i = 0; i < length; i++) {
++ buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
++ }
++ return length;
++}
+
+
++static char*
++_strnchr(const char *dest,int c,size_t cnt)
++{
++ while (*dest && (cnt > 0)) {
++ if (*dest == c) return (char *) dest;
++ dest++;
++ cnt--;
++ }
++ return NULL;
++}
++
++
++
++/*
++ * Core support API: Externally visible.
++ */
++
++/*
++ * Get the value of an NVRAM variable
++ * @param name name of variable to get
++ * @return value of variable or NULL if undefined
++ */
++
++char*
++cfe_env_get(unsigned char *nv_buf, char* name)
++{
++ int size;
++ unsigned char *buffer;
++ unsigned char *ptr;
++ unsigned char *envval;
++ unsigned int reclen;
++ unsigned int rectype;
++ int offset;
++ int flg;
++
++ size = NVRAM_SIZE;
++ buffer = &_nvdata[0];
++
++ ptr = buffer;
++ offset = 0;
++
++ /* Read the record type and length */
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
++ goto error;
++ }
++
++ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
++
++ /* Adjust pointer for TLV type */
++ rectype = *(ptr);
++ offset++;
++ size--;
++
++ /*
++ * Read the length. It can be either 1 or 2 bytes
++ * depending on the code
++ */
++ if (rectype & ENV_LENGTH_8BITS) {
++ /* Read the record type and length - 8 bits */
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
++ goto error;
++ }
++ reclen = *(ptr);
++ size--;
++ offset++;
++ }
++ else {
++ /* Read the record type and length - 16 bits, MSB first */
++ if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
++ goto error;
++ }
++ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
++ size -= 2;
++ offset += 2;
++ }
++
++ if (reclen > size)
++ break; /* should not happen, bad NVRAM */
++
++ switch (rectype) {
++ case ENV_TLV_TYPE_ENV:
++ /* Read the TLV data */
++ if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
++ goto error;
++ flg = *ptr++;
++ envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
++ if (envval) {
++ *envval++ = '\0';
++ memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
++ _valuestr[(reclen-1)-(envval-ptr)] = '\0';
++#if 0
++ printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
++#endif
++ if(!strcmp(ptr, name)){
++ return _valuestr;
++ }
++ if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
++ return _valuestr;
++ }
++ break;
++
++ default:
++ /* Unknown TLV type, skip it. */
++ break;
++ }
++
++ /*
++ * Advance to next TLV
++ */
++
++ size -= (int)reclen;
++ offset += reclen;
++
++ /* Read the next record type */
++ ptr = buffer;
++ if (_nvram_read(nv_buf, ptr,offset,1) != 1)
++ goto error;
++ }
++
++error:
++ return NULL;
++
++}
++
diff -urN linux.old/arch/mips/bcm947xx/broadcom/linux_osl.c linux.dev/arch/mips/bcm947xx/broadcom/linux_osl.c
--- linux.old/arch/mips/bcm947xx/broadcom/linux_osl.c 1970-01-01 01:00:00.000000000 +0100
+++ linux.dev/arch/mips/bcm947xx/broadcom/linux_osl.c 2005-12-15 17:11:05.818041750 +0100
+
diff -urN linux.old/arch/mips/bcm947xx/broadcom/nvram.c linux.dev/arch/mips/bcm947xx/broadcom/nvram.c
--- linux.old/arch/mips/bcm947xx/broadcom/nvram.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/bcm947xx/broadcom/nvram.c 2005-12-15 17:36:23.151078000 +0100
-@@ -0,0 +1,145 @@
++++ linux.dev/arch/mips/bcm947xx/broadcom/nvram.c 2005-12-18 04:59:36.185204500 +0100
+@@ -0,0 +1,165 @@
+/*
+ * NVRAM variable manipulation (Linux kernel half)
+ *
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
-+#include <linux/bootmem.h>
++#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+/* Global SB handle */
+extern void *sbh;
+extern spinlock_t bcm947xx_sbh_lock;
++static int cfe_env;
++
++extern char *cfe_env_get(char *nv_buf, const char *name);
++
+
+/* Convenience */
+#define sbh_lock bcm947xx_sbh_lock
+ uint32 base, off, lim;
+ u32 *src, *dst;
+
++ cfe_env = 0;
+ if ((cc = sb_setcore(sbh, SB_CC, 0)) != NULL) {
+ base = KSEG1ADDR(SB_FLASH2);
+ switch (readl(&cc->capabilities) & CAP_FLASH_MASK) {
+ lim = SB_FLASH1_SZ;
+ }
+
++ /* XXX: hack for supporting the CFE environment stuff on WGT634U */
++ src = (u32 *) KSEG1ADDR(base + 8 * 1024 * 1024 - 0x2000);
++ dst = (u32 *) nvram_buf;
++ if ((lim == 0x02000000) && ((*src & 0xff00ff) == 0x000001)) {
++ printk("early_nvram_init: WGT634U NVRAM found.\n");
++
++ for (i = 0; i < 0x1ff0; i++) {
++ if (*src == 0xFFFFFFFF)
++ break;
++ *dst++ = *src++;
++ }
++ cfe_env = 1;
++ return;
++ }
++
+ off = FLASH_MIN;
+ while (off <= lim) {
+ /* Windowed flash access */
+ if (header->magic == NVRAM_MAGIC)
+ goto found;
+
-+ printk("early_nvram_init: NVRAM not found\n");
+ return;
+
+found:
+ if (!nvram_buf[0])
+ early_nvram_init();
+
++ if (cfe_env)
++ return cfe_env_get(nvram_buf, name);
++
+ /* Look for name=value and return value */
+ var = &nvram_buf[sizeof(struct nvram_header)];
+ end = nvram_buf + sizeof(nvram_buf) - 2;
+
+ return NULL;
+}
-+
-+EXPORT_SYMBOL(nvram_get);
diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbmips.c linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c
--- linux.old/arch/mips/bcm947xx/broadcom/sbmips.c 1970-01-01 01:00:00.000000000 +0100
+++ linux.dev/arch/mips/bcm947xx/broadcom/sbmips.c 2005-12-15 16:46:31.122961250 +0100
+
diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbpci.c linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c
--- linux.old/arch/mips/bcm947xx/broadcom/sbpci.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c 2005-12-15 20:09:46.562233250 +0100
-@@ -0,0 +1,529 @@
++++ linux.dev/arch/mips/bcm947xx/broadcom/sbpci.c 2005-12-18 05:36:53.351735500 +0100
+@@ -0,0 +1,533 @@
+/*
+ * Low-Level PCI and SB support for BCM47xx
+ *
+ n = (R_REG(&sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT;
+ if (off == OFFSETOF(pci_config_regs, base[0]))
+ cfg->base[0] = ~(sb_size(R_REG(&sb->sbadmatch0)) - 1);
++#if 0
+ else if (off == OFFSETOF(pci_config_regs, base[1]) && n >= 1)
+ cfg->base[1] = ~(sb_size(R_REG(&sb->sbadmatch1)) - 1);
+ else if (off == OFFSETOF(pci_config_regs, base[2]) && n >= 2)
+ cfg->base[2] = ~(sb_size(R_REG(&sb->sbadmatch2)) - 1);
+ else if (off == OFFSETOF(pci_config_regs, base[3]) && n >= 3)
+ cfg->base[3] = ~(sb_size(R_REG(&sb->sbadmatch3)) - 1);
++#endif
+ }
+ sb_setcoreidx(sbh, coreidx);
+ return 0;
+ subclass = PCI_MEMORY_RAM;
+ break;
+ case SB_PCI:
++#if 0
+ class = PCI_CLASS_BRIDGE;
+ subclass = PCI_BRIDGE_PCI;
+ break;
++#endif
+ case SB_MIPS:
+ case SB_MIPS33:
+ class = PCI_CLASS_CPU;
+ cfg->sub_class = subclass;
+ cfg->base_class = class;
+ cfg->base[0] = htol32(sb_base(R_REG(&sb->sbadmatch0)));
-+ cfg->base[1] = htol32(sb_base(R_REG(&sb->sbadmatch1)));
-+ cfg->base[2] = htol32(sb_base(R_REG(&sb->sbadmatch2)));
-+ cfg->base[3] = htol32(sb_base(R_REG(&sb->sbadmatch3)));
++ cfg->base[1] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch1)));
++ cfg->base[2] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch2)));
++ cfg->base[3] = 0;//htol32(sb_base(R_REG(&sb->sbadmatch3)));
+ cfg->base[4] = 0;
+ cfg->base[5] = 0;
+ if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI)
+
diff -urN linux.old/arch/mips/bcm947xx/broadcom/sbutils.c linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c
--- linux.old/arch/mips/bcm947xx/broadcom/sbutils.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c 2005-12-15 17:31:12.211645500 +0100
-@@ -0,0 +1,2407 @@
++++ linux.dev/arch/mips/bcm947xx/broadcom/sbutils.c 2005-12-17 01:21:12.951254500 +0100
+@@ -0,0 +1,2370 @@
+/*
+ * Misc utility routines for accessing chip-specific features
+ * of the SiliconBackplane-based Broadcom chips.
+ *pciprogif = progif;
+}
+
-+#if 0
-+/* Build device path. Support SB, PCI, and JTAG for now. */
-+int
-+sb_devpath(sb_t *sbh, char *path, int size)
-+{
-+ ASSERT(path);
-+ ASSERT(size >= SB_DEVPATH_BUFSZ);
-+
-+ switch (BUSTYPE((SB_INFO(sbh))->sb.bustype)) {
-+ case SB_BUS:
-+ case JTAG_BUS:
-+ sprintf(path, "sb/%u/", sb_coreidx(sbh));
-+ break;
-+ case PCI_BUS:
-+ ASSERT((SB_INFO(sbh))->osh);
-+ sprintf(path, "pci/%u/%u/", OSL_PCI_BUS((SB_INFO(sbh))->osh),
-+ PCI_SLOT(((struct pci_dev *)(SB_INFO(sbh))->osh)->pdev)->devfn);
-+ break;
-+ case SDIO_BUS:
-+ SB_ERROR(("sb_devpath: device 0 assumed\n"));
-+ sprintf(path, "sd/%u/", sb_coreidx(sbh));
-+ break;
-+ default:
-+ ASSERT(0);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
+/* Fix chip's configuration. The current core may be changed upon return */
+static int
+sb_pci_fixcfg(sb_info_t *si)
+ uint origidx, pciidx;
+ sbpciregs_t *pciregs;
+ uint16 val16, *reg16;
-+ char name[SB_DEVPATH_BUFSZ+16], *value;
-+ char devpath[SB_DEVPATH_BUFSZ];
+
+ ASSERT(BUSTYPE(si->sb.bustype) == PCI_BUS);
+
+ /* restore the original index */
+ sb_setcoreidx(&si->sb, origidx);
+
-+#if 0
-+ /* Fix bar0window */
-+ /* !do it last, it changes the current core! */
-+ if (sb_devpath(&si->sb, devpath, sizeof(devpath)))
-+ return -1;
-+ sprintf(name, "%sb0w", devpath);
-+ if ((value = getvar(NULL, name))) {
-+ OSL_PCI_WRITE_CONFIG(si->osh, PCI_BAR0_WIN, sizeof(uint32),
-+ bcm_strtoul(value, NULL, 16));
-+ /* update curidx since the current core is changed */
-+ si->curidx = _sb_coreidx(si);
-+ if (si->curidx == BADIDX) {
-+ SB_ERROR(("sb_pci_fixcfg: bad core index\n"));
-+ return -1;
-+ }
-+ }
-+#endif
-+
+ return 0;
+}
+
++EXPORT_SYMBOL(sb_boardtype);
++EXPORT_SYMBOL(sb_boardvendor);
++EXPORT_SYMBOL(sb_gpiocontrol);
++EXPORT_SYMBOL(sb_gpioin);
++EXPORT_SYMBOL(sb_gpiointmask);
++EXPORT_SYMBOL(sb_gpiointpolarity);
++EXPORT_SYMBOL(sb_gpioled);
++EXPORT_SYMBOL(sb_gpioout);
++EXPORT_SYMBOL(sb_gpioouten);
++EXPORT_SYMBOL(sb_gpiorelease);
++EXPORT_SYMBOL(sb_gpioreserve);
++EXPORT_SYMBOL(sb_gpiosetcore);
++EXPORT_SYMBOL(sb_gpiotimerval);
++EXPORT_SYMBOL(sb_watchdog);
diff -urN linux.old/arch/mips/bcm947xx/broadcom/sflash.c linux.dev/arch/mips/bcm947xx/broadcom/sflash.c
--- linux.old/arch/mips/bcm947xx/broadcom/sflash.c 1970-01-01 01:00:00.000000000 +0100
+++ linux.dev/arch/mips/bcm947xx/broadcom/sflash.c 2005-12-15 16:59:20.045933750 +0100
+}
diff -urN linux.old/arch/mips/bcm947xx/pci.c linux.dev/arch/mips/bcm947xx/pci.c
--- linux.old/arch/mips/bcm947xx/pci.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/bcm947xx/pci.c 2005-12-15 23:25:48.489984500 +0100
-@@ -0,0 +1,92 @@
++++ linux.dev/arch/mips/bcm947xx/pci.c 2005-12-18 07:01:36.731635000 +0100
+@@ -0,0 +1,215 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <sbmips.h>
+#include <sbconfig.h>
+#include <sbpci.h>
++#include <bcmdevs.h>
++#include <pcicfg.h>
+
+extern sb_t *sbh;
++extern spinlock_t sbh_lock;
+
+
+static int
+ int reg, int size, u32 *val)
+{
+ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&sbh_lock, flags);
+ ret = sbpci_read_config(sbh, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), reg, val, size);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+ int reg, int size, u32 val)
+{
+ int ret;
++ unsigned long flags;
++
++ spin_lock_irqsave(&sbh_lock, flags);
+ ret = sbpci_write_config(sbh, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), reg, &val, size);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
+ return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+ .write = sb_pci_write_config,
+};
+
-+
+static struct resource sb_pci_mem_resource = {
+ .name = "SB PCI Memory resources",
+ .start = SB_ENUM_BASE,
+
+static struct resource sb_pci_io_resource = {
+ .name = "SB PCI I/O resources",
-+ .start = 0x100,
-+ .end = 0x1FF,
++ .start = 0x000,
++ .end = 0x0FF,
+ .flags = IORESOURCE_IO,
+};
+
+
+static struct resource ext_pci_io_resource = {
+ .name = "Ext PCI I/O resources",
-+ .start = 0x200,
-+ .end = 0x2FF,
++ .start = 0x100,
++ .end = 0x1FF,
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller bcm47xx_ext_pci_controller = {
+ .pci_ops = &sb_pci_ops,
-+ .mem_resource = &ext_pci_mem_resource,
+ .io_resource = &ext_pci_io_resource,
++ .mem_resource = &ext_pci_mem_resource,
++ .mem_offset = 0x24000000,
+};
+
+void bcm47xx_pci_init(void)
+{
++ unsigned long flags;
++
++ spin_lock_irqsave(&sbh_lock, flags);
+ sbpci_init(sbh);
++ spin_unlock_irqrestore(&sbh_lock, flags);
+
+ set_io_port_base((unsigned long) ioremap_nocache(SB_PCI_MEM, 0x04000000));
+
+ register_pci_controller(&bcm47xx_sb_pci_controller);
+ register_pci_controller(&bcm47xx_ext_pci_controller);
+}
++
++int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ u8 irq;
++
++ if (dev->bus->number == 1)
++ return 2;
++
++ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
++ return irq + 2;
++}
++
++u32 pci_iobase = 0x100;
++u32 pci_membase = SB_PCI_DMA;
++
++static void bcm47xx_fixup_device(struct pci_dev *d)
++{
++ struct resource *res;
++ int pos, size;
++ u32 *base;
++
++ if (d->bus->number == 0)
++ return;
++
++ printk("PCI: Fixing up device %s\n", pci_name(d));
++
++ /* Fix up resource bases */
++ for (pos = 0; pos < 6; pos++) {
++ res = &d->resource[pos];
++ base = ((res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase);
++ if (res->end) {
++ size = res->end - res->start + 1;
++ if (*base & (size - 1))
++ *base = (*base + size) & ~(size - 1);
++ res->start = *base;
++ res->end = res->start + size - 1;
++ *base += size;
++ pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
++ }
++ /* Fix up PCI bridge BAR0 only */
++ if (d->bus->number == 1 && PCI_SLOT(d->devfn) == 0)
++ break;
++ }
++ /* Fix up interrupt lines */
++ if (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))
++ d->irq = (pci_find_device(VENDOR_BROADCOM, SB_PCI, NULL))->irq;
++ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
++}
++
++
++static void bcm47xx_fixup_bridge(struct pci_dev *dev)
++{
++ if (dev->bus->number != 1 || PCI_SLOT(dev->devfn) != 0)
++ return;
++
++ printk("PCI: fixing up bridge\n");
++
++ /* Enable PCI bridge bus mastering and memory space */
++ pci_set_master(dev);
++ pcibios_enable_device(dev, ~0);
++
++ /* Enable PCI bridge BAR1 prefetch and burst */
++ pci_write_config_dword(dev, PCI_BAR1_CONTROL, 3);
++}
++
++/* Do platform specific device initialization at pci_enable_device() time */
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ uint coreidx;
++ unsigned long flags;
++
++ bcm47xx_fixup_device(dev);
++
++ /* These cores come out of reset enabled */
++ if ((dev->bus->number != 0) ||
++ (dev->device == SB_MIPS) ||
++ (dev->device == SB_MIPS33) ||
++ (dev->device == SB_EXTIF) ||
++ (dev->device == SB_CC))
++ return 0;
++
++ /* Do a core reset */
++ spin_lock_irqsave(&sbh_lock, flags);
++ coreidx = sb_coreidx(sbh);
++ if (sb_setcoreidx(sbh, PCI_SLOT(dev->devfn)) && (sb_coreid(sbh) == SB_USB)) {
++ /*
++ * The USB core requires a special bit to be set during core
++ * reset to enable host (OHCI) mode. Resetting the SB core in
++ * pcibios_enable_device() is a hack for compatibility with
++ * vanilla usb-ohci so that it does not have to know about
++ * SB. A driver that wants to use the USB core in device mode
++ * should know about SB and should reset the bit back to 0
++ * after calling pcibios_enable_device().
++ */
++ sb_core_disable(sbh, sb_coreflags(sbh, 0, 0));
++ sb_core_reset(sbh, 1 << 29);
++ } else {
++ sb_core_reset(sbh, 0);
++ }
++ sb_setcoreidx(sbh, coreidx);
++ spin_unlock_irqrestore(&sbh_lock, flags);
++
++ return 0;
++}
++
++DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcm47xx_fixup_bridge);
diff -urN linux.old/arch/mips/bcm947xx/prom.c linux.dev/arch/mips/bcm947xx/prom.c
--- linux.old/arch/mips/bcm947xx/prom.c 1970-01-01 01:00:00.000000000 +0100
+++ linux.dev/arch/mips/bcm947xx/prom.c 2005-12-15 12:57:27.877187750 +0100
+}
diff -urN linux.old/arch/mips/bcm947xx/setup.c linux.dev/arch/mips/bcm947xx/setup.c
--- linux.old/arch/mips/bcm947xx/setup.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/bcm947xx/setup.c 2005-12-15 19:17:21.508844000 +0100
-@@ -0,0 +1,107 @@
++++ linux.dev/arch/mips/bcm947xx/setup.c 2005-12-18 06:34:52.106215250 +0100
+@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2004 Florian Schirmer (jolt@tuxbox.org)
+ * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
++ * Copyright (C) 2005 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+#include <sbpci.h>
+#include <sbconfig.h>
+#include <bcmdevs.h>
++#include <bcmutils.h>
++#include <bcmnvram.h>
+
+extern void bcm47xx_pci_init(void);
+extern void bcm47xx_time_init(void);
+extern void bcm47xx_timer_setup(struct irqaction *irq);
+void *sbh;
++spinlock_t sbh_lock = SPIN_LOCK_UNLOCKED;
++int boardflags;
+
+static int ser_line = 0;
+
++typedef struct {
++ void *regs;
++ uint irq;
++ uint baud_base;
++ uint reg_shift;
++} serial_port;
++
++static serial_port ports[4];
++static int num_ports = 0;
++
+static void
+serial_add(void *regs, uint irq, uint baud_base, uint reg_shift)
+{
++ ports[num_ports].regs = regs;
++ ports[num_ports].irq = irq;
++ ports[num_ports].baud_base = baud_base;
++ ports[num_ports].reg_shift = reg_shift;
++ num_ports++;
++}
++
++static void
++do_serial_add(serial_port *port)
++{
++ void *regs;
++ uint irq;
++ uint baud_base;
++ uint reg_shift;
+ struct uart_port s;
++
++ regs = port->regs;
++ irq = port->irq;
++ baud_base = port->baud_base;
++ reg_shift = port->reg_shift;
+
+ memset(&s, 0, sizeof(s));
+
+
+void __init plat_setup(void)
+{
-+
-+ sbh = sb_kattach();
++ char *s;
++ int i;
++
++ sbh = (void *) sb_kattach();
+ sb_mips_init(sbh);
+
+ bcm47xx_pci_init();
+
-+ set_io_port_base((unsigned long) ioremap_nocache(SB_PCI_MEM, 0x04000000));
-+
+ sb_serial_init(sbh, serial_add);
-+
++ boardflags = getintvar(NULL, "boardflags");
++
++ /* reverse serial ports if the nvram variable kernel_args starts with console=ttyS1 */
++ s = nvram_get("kernel_args");
++ if (!s) s = "";
++ if (!strncmp(s, "console=ttyS1", 13)) {
++ for (i = num_ports; i; i--)
++ do_serial_add(&ports[i - 1]);
++ } else {
++ for (i = 0; i < num_ports; i++)
++ do_serial_add(&ports[i]);
++ }
++
+ _machine_restart = bcm47xx_machine_restart;
+ _machine_halt = bcm47xx_machine_halt;
+ _machine_power_off = bcm47xx_machine_halt;
+ board_time_init = bcm47xx_time_init;
+ board_timer_setup = bcm47xx_timer_setup;
+}
++
++EXPORT_SYMBOL(sbh);
++EXPORT_SYMBOL(sbh_lock);
++EXPORT_SYMBOL(boardflags);
diff -urN linux.old/arch/mips/bcm947xx/time.c linux.dev/arch/mips/bcm947xx/time.c
--- linux.old/arch/mips/bcm947xx/time.c 1970-01-01 01:00:00.000000000 +0100
+++ linux.dev/arch/mips/bcm947xx/time.c 2005-12-15 12:57:27.877187750 +0100
tlbw(p);
break;
-diff -urN linux.old/arch/mips/pci/Makefile linux.dev/arch/mips/pci/Makefile
---- linux.old/arch/mips/pci/Makefile 2005-12-15 13:26:49.814003000 +0100
-+++ linux.dev/arch/mips/pci/Makefile 2005-12-15 14:27:26.439319250 +0100
-@@ -18,6 +18,7 @@
- obj-$(CONFIG_MIPS_TX3927) += ops-tx3927.o
- obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o
- obj-$(CONFIG_NEC_CMBVR4133) += fixup-vr4133.o
-+obj-$(CONFIG_BCM947XX) += fixup-bcm47xx.o
-
- #
- # These are still pretty much in the old state, watch, go blind.
-diff -urN linux.old/arch/mips/pci/fixup-bcm47xx.c linux.dev/arch/mips/pci/fixup-bcm47xx.c
---- linux.old/arch/mips/pci/fixup-bcm47xx.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux.dev/arch/mips/pci/fixup-bcm47xx.c 2005-12-15 12:57:27.945158000 +0100
-@@ -0,0 +1,23 @@
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+
-+/* Do platform specific device initialization at pci_enable_device() time */
-+int pcibios_plat_dev_init(struct pci_dev *dev)
-+{
-+ return 0;
-+}
-+
-+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+ u8 irq;
-+
-+ if (dev->bus->number == 1)
-+ return 2;
-+
-+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
-+ return irq + 2;
-+}
-+
-+struct pci_fixup pcibios_fixups[] = {
-+ { 0 }
-+};
diff -urN linux.old/include/asm-mips/bootinfo.h linux.dev/include/asm-mips/bootinfo.h
--- linux.old/include/asm-mips/bootinfo.h 2005-12-15 13:26:49.818001250 +0100
+++ linux.dev/include/asm-mips/bootinfo.h 2005-12-15 12:57:27.969147500 +0100