v4.19.13 snapshot.
diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig
new file mode 100644
index 0000000..d2509c9
--- /dev/null
+++ b/arch/mips/txx9/Kconfig
@@ -0,0 +1,128 @@
+# SPDX-License-Identifier: GPL-2.0
+config MACH_TX39XX
+	bool
+	select MACH_TXX9
+	select SYS_HAS_CPU_TX39XX
+
+config MACH_TX49XX
+	bool
+	select MACH_TXX9
+	select CEVT_R4K
+	select CSRC_R4K
+	select IRQ_MIPS_CPU
+	select SYS_HAS_CPU_TX49XX
+	select SYS_SUPPORTS_64BIT_KERNEL
+
+config MACH_TXX9
+	bool
+	select DMA_NONCOHERENT
+	select SWAP_IO_SPACE
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select COMMON_CLK
+
+config TOSHIBA_JMR3927
+	bool "Toshiba JMR-TX3927 board"
+	depends on MACH_TX39XX
+	select SOC_TX3927
+
+config TOSHIBA_RBTX4927
+	bool "Toshiba RBTX49[23]7 board"
+	depends on MACH_TX49XX
+	select SOC_TX4927
+	# TX4937 is subset of TX4938
+	select SOC_TX4938
+	help
+	  This Toshiba board is based on the TX4927 processor. Say Y here to
+	  support this machine type
+
+config TOSHIBA_RBTX4938
+	bool "Toshiba RBTX4938 board"
+	depends on MACH_TX49XX
+	select SOC_TX4938
+	help
+	  This Toshiba board is based on the TX4938 processor. Say Y here to
+	  support this machine type
+
+config TOSHIBA_RBTX4939
+	bool "Toshiba RBTX4939 board"
+	depends on MACH_TX49XX
+	select SOC_TX4939
+	select TXX9_7SEGLED
+	help
+	  This Toshiba board is based on the TX4939 processor. Say Y here to
+	  support this machine type
+
+config SOC_TX3927
+	bool
+	select CEVT_TXX9
+	select HAS_TXX9_SERIAL
+	select HW_HAS_PCI
+	select IRQ_TXX9
+	select GPIO_TXX9
+
+config SOC_TX4927
+	bool
+	select CEVT_TXX9
+	select HAS_TXX9_SERIAL
+	select HW_HAS_PCI
+	select IRQ_TXX9
+	select PCI_TX4927
+	select GPIO_TXX9
+	select HAS_TXX9_ACLC
+
+config SOC_TX4938
+	bool
+	select CEVT_TXX9
+	select HAS_TXX9_SERIAL
+	select HW_HAS_PCI
+	select IRQ_TXX9
+	select PCI_TX4927
+	select GPIO_TXX9
+	select HAS_TXX9_ACLC
+
+config SOC_TX4939
+	bool
+	select CEVT_TXX9
+	select HAS_TXX9_SERIAL
+	select HW_HAS_PCI
+	select PCI_TX4927
+	select HAS_TXX9_ACLC
+
+config TXX9_7SEGLED
+	bool
+
+config TOSHIBA_FPCIB0
+	bool "FPCIB0 Backplane Support"
+	depends on PCI && MACH_TXX9
+	select I8259
+
+config PICMG_PCI_BACKPLANE_DEFAULT
+	bool "Support for PICMG PCI Backplane"
+	depends on PCI && MACH_TXX9
+	default y if !TOSHIBA_FPCIB0
+
+if TOSHIBA_RBTX4938
+
+comment "Multiplex Pin Select"
+choice
+	prompt "PIO[58:61]"
+	default TOSHIBA_RBTX4938_MPLEX_PIO58_61
+
+config TOSHIBA_RBTX4938_MPLEX_PIO58_61
+	bool "PIO"
+config TOSHIBA_RBTX4938_MPLEX_NAND
+	bool "NAND"
+config TOSHIBA_RBTX4938_MPLEX_ATA
+	bool "ATA"
+config TOSHIBA_RBTX4938_MPLEX_KEEP
+	bool "Keep firmware settings"
+
+endchoice
+
+endif
+
+config PCI_TX4927
+	bool
diff --git a/arch/mips/txx9/Makefile b/arch/mips/txx9/Makefile
new file mode 100644
index 0000000..1952959
--- /dev/null
+++ b/arch/mips/txx9/Makefile
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Common TXx9
+#
+obj-$(CONFIG_MACH_TX39XX)      += generic/
+obj-$(CONFIG_MACH_TX49XX)      += generic/
+
+#
+# Toshiba JMR-TX3927 board
+#
+obj-$(CONFIG_TOSHIBA_JMR3927)  += jmr3927/
+
+#
+# Toshiba RBTX49XX boards
+#
+obj-$(CONFIG_TOSHIBA_RBTX4927) += rbtx4927/
+obj-$(CONFIG_TOSHIBA_RBTX4938) += rbtx4938/
+obj-$(CONFIG_TOSHIBA_RBTX4939) += rbtx4939/
diff --git a/arch/mips/txx9/Platform b/arch/mips/txx9/Platform
new file mode 100644
index 0000000..a176d1f
--- /dev/null
+++ b/arch/mips/txx9/Platform
@@ -0,0 +1,10 @@
+platform-$(CONFIG_MACH_TX39XX)	+= txx9/
+platform-$(CONFIG_MACH_TX49XX)	+= txx9/
+
+cflags-$(CONFIG_MACH_TX39XX)	+=					\
+		-I$(srctree)/arch/mips/include/asm/mach-tx39xx
+cflags-$(CONFIG_MACH_TX49XX)	+=					\
+		 -I$(srctree)/arch/mips/include/asm/mach-tx49xx
+
+load-$(CONFIG_MACH_TX39XX)	+= 0xffffffff80050000
+load-$(CONFIG_MACH_TX49XX)	+= 0xffffffff80100000
diff --git a/arch/mips/txx9/generic/7segled.c b/arch/mips/txx9/generic/7segled.c
new file mode 100644
index 0000000..2203c25
--- /dev/null
+++ b/arch/mips/txx9/generic/7segled.c
@@ -0,0 +1,123 @@
+/*
+ * 7 Segment LED routines
+ * Based on RBTX49xx patch from CELF patch archive.
+ *
+ * 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.
+ *
+ * (C) Copyright TOSHIBA CORPORATION 2005-2007
+ * All Rights Reserved.
+ */
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/map_to_7segment.h>
+#include <asm/txx9/generic.h>
+
+static unsigned int tx_7segled_num;
+static void (*tx_7segled_putc)(unsigned int pos, unsigned char val);
+
+void __init txx9_7segled_init(unsigned int num,
+			      void (*putc)(unsigned int pos, unsigned char val))
+{
+	tx_7segled_num = num;
+	tx_7segled_putc = putc;
+}
+
+static SEG7_CONVERSION_MAP(txx9_seg7map, MAP_ASCII7SEG_ALPHANUM_LC);
+
+int txx9_7segled_putc(unsigned int pos, char c)
+{
+	if (pos >= tx_7segled_num)
+		return -EINVAL;
+	c = map_to_seg7(&txx9_seg7map, c);
+	if (c < 0)
+		return c;
+	tx_7segled_putc(pos, c);
+	return 0;
+}
+
+static ssize_t ascii_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t size)
+{
+	unsigned int ch = dev->id;
+	txx9_7segled_putc(ch, buf[0]);
+	return size;
+}
+
+static ssize_t raw_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t size)
+{
+	unsigned int ch = dev->id;
+	tx_7segled_putc(ch, buf[0]);
+	return size;
+}
+
+static DEVICE_ATTR_WO(ascii);
+static DEVICE_ATTR_WO(raw);
+
+static ssize_t map_seg7_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map));
+	return sizeof(txx9_seg7map);
+}
+
+static ssize_t map_seg7_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	if (size != sizeof(txx9_seg7map))
+		return -EINVAL;
+	memcpy(&txx9_seg7map, buf, size);
+	return size;
+}
+
+static DEVICE_ATTR(map_seg7, 0600, map_seg7_show, map_seg7_store);
+
+static struct bus_type tx_7segled_subsys = {
+	.name		= "7segled",
+	.dev_name	= "7segled",
+};
+
+static void tx_7segled_release(struct device *dev)
+{
+	kfree(dev);
+}
+
+static int __init tx_7segled_init_sysfs(void)
+{
+	int error, i;
+	if (!tx_7segled_num)
+		return -ENODEV;
+	error = subsys_system_register(&tx_7segled_subsys, NULL);
+	if (error)
+		return error;
+	error = device_create_file(tx_7segled_subsys.dev_root, &dev_attr_map_seg7);
+	if (error)
+		return error;
+	for (i = 0; i < tx_7segled_num; i++) {
+		struct device *dev;
+		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+		if (!dev) {
+			error = -ENODEV;
+			break;
+		}
+		dev->id = i;
+		dev->bus = &tx_7segled_subsys;
+		dev->release = &tx_7segled_release;
+		error = device_register(dev);
+		if (error) {
+			put_device(dev);
+			return error;
+		}
+		device_create_file(dev, &dev_attr_ascii);
+		device_create_file(dev, &dev_attr_raw);
+	}
+	return error;
+}
+
+device_initcall(tx_7segled_init_sysfs);
diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile
new file mode 100644
index 0000000..6d00580
--- /dev/null
+++ b/arch/mips/txx9/generic/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for common code for TXx9 based systems
+#
+
+obj-y	+= setup.o
+obj-$(CONFIG_PCI)	+= pci.o
+obj-$(CONFIG_SOC_TX3927)	+= setup_tx3927.o irq_tx3927.o
+obj-$(CONFIG_SOC_TX4927)	+= mem_tx4927.o setup_tx4927.o irq_tx4927.o
+obj-$(CONFIG_SOC_TX4938)	+= mem_tx4927.o setup_tx4938.o irq_tx4938.o
+obj-$(CONFIG_SOC_TX4939)	+= setup_tx4939.o irq_tx4939.o
+obj-$(CONFIG_TOSHIBA_FPCIB0)	+= smsc_fdc37m81x.o
+obj-$(CONFIG_SPI)		+= spi_eeprom.o
+obj-$(CONFIG_TXX9_7SEGLED)	+= 7segled.o
diff --git a/arch/mips/txx9/generic/irq_tx3927.c b/arch/mips/txx9/generic/irq_tx3927.c
new file mode 100644
index 0000000..c683f59
--- /dev/null
+++ b/arch/mips/txx9/generic/irq_tx3927.c
@@ -0,0 +1,25 @@
+/*
+ * Common tx3927 irq handler
+ *
+ * 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 2001 MontaVista Software Inc.
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ */
+#include <linux/init.h>
+#include <asm/txx9irq.h>
+#include <asm/txx9/tx3927.h>
+
+void __init tx3927_irq_init(void)
+{
+	int i;
+
+	txx9_irq_init(TX3927_IRC_REG);
+	/* raise priority for timers, sio */
+	for (i = 0; i < TX3927_NR_TMR; i++)
+		txx9_irq_set_pri(TX3927_IR_TMR(i), 6);
+	for (i = 0; i < TX3927_NR_SIO; i++)
+		txx9_irq_set_pri(TX3927_IR_SIO(i), 7);
+}
diff --git a/arch/mips/txx9/generic/irq_tx4927.c b/arch/mips/txx9/generic/irq_tx4927.c
new file mode 100644
index 0000000..ed8e702
--- /dev/null
+++ b/arch/mips/txx9/generic/irq_tx4927.c
@@ -0,0 +1,49 @@
+/*
+ * Common tx4927 irq handler
+ *
+ * Author: MontaVista Software, Inc.
+ *	   source@mvista.com
+ *
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/txx9/tx4927.h>
+
+void __init tx4927_irq_init(void)
+{
+	int i;
+
+	mips_cpu_irq_init();
+	txx9_irq_init(TX4927_IRC_REG & 0xfffffffffULL);
+	irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT,
+				handle_simple_irq);
+	/* raise priority for errors, timers, SIO */
+	txx9_irq_set_pri(TX4927_IR_ECCERR, 7);
+	txx9_irq_set_pri(TX4927_IR_WTOERR, 7);
+	txx9_irq_set_pri(TX4927_IR_PCIERR, 7);
+	txx9_irq_set_pri(TX4927_IR_PCIPME, 7);
+	for (i = 0; i < TX4927_NUM_IR_TMR; i++)
+		txx9_irq_set_pri(TX4927_IR_TMR(i), 6);
+	for (i = 0; i < TX4927_NUM_IR_SIO; i++)
+		txx9_irq_set_pri(TX4927_IR_SIO(i), 5);
+}
diff --git a/arch/mips/txx9/generic/irq_tx4938.c b/arch/mips/txx9/generic/irq_tx4938.c
new file mode 100644
index 0000000..aace856
--- /dev/null
+++ b/arch/mips/txx9/generic/irq_tx4938.c
@@ -0,0 +1,37 @@
+/*
+ * linux/arch/mips/tx4938/common/irq.c
+ *
+ * Common tx4938 irq handler
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/txx9/tx4938.h>
+
+void __init tx4938_irq_init(void)
+{
+	int i;
+
+	mips_cpu_irq_init();
+	txx9_irq_init(TX4938_IRC_REG & 0xfffffffffULL);
+	irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT,
+				handle_simple_irq);
+	/* raise priority for errors, timers, SIO */
+	txx9_irq_set_pri(TX4938_IR_ECCERR, 7);
+	txx9_irq_set_pri(TX4938_IR_WTOERR, 7);
+	txx9_irq_set_pri(TX4938_IR_PCIERR, 7);
+	txx9_irq_set_pri(TX4938_IR_PCIPME, 7);
+	for (i = 0; i < TX4938_NUM_IR_TMR; i++)
+		txx9_irq_set_pri(TX4938_IR_TMR(i), 6);
+	for (i = 0; i < TX4938_NUM_IR_SIO; i++)
+		txx9_irq_set_pri(TX4938_IR_SIO(i), 5);
+}
diff --git a/arch/mips/txx9/generic/irq_tx4939.c b/arch/mips/txx9/generic/irq_tx4939.c
new file mode 100644
index 0000000..0d7267e
--- /dev/null
+++ b/arch/mips/txx9/generic/irq_tx4939.c
@@ -0,0 +1,216 @@
+/*
+ * TX4939 irq routines
+ * Based on linux/arch/mips/kernel/irq_txx9.c,
+ *	    and RBTX49xx patch from CELF patch archive.
+ *
+ * Copyright 2001, 2003-2005 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *	   ahennessy@mvista.com
+ *	   source@mvista.com
+ * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation
+ *
+ * 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.
+ */
+/*
+ * TX4939 defines 64 IRQs.
+ * Similer to irq_txx9.c but different register layouts.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <asm/irq_cpu.h>
+#include <asm/txx9irq.h>
+#include <asm/txx9/tx4939.h>
+
+/* IRCER : Int. Control Enable */
+#define TXx9_IRCER_ICE	0x00000001
+
+/* IRCR : Int. Control */
+#define TXx9_IRCR_LOW	0x00000000
+#define TXx9_IRCR_HIGH	0x00000001
+#define TXx9_IRCR_DOWN	0x00000002
+#define TXx9_IRCR_UP	0x00000003
+#define TXx9_IRCR_EDGE(cr)	((cr) & 0x00000002)
+
+/* IRSCR : Int. Status Control */
+#define TXx9_IRSCR_EIClrE	0x00000100
+#define TXx9_IRSCR_EIClr_MASK	0x0000000f
+
+/* IRCSR : Int. Current Status */
+#define TXx9_IRCSR_IF	0x00010000
+
+#define irc_dlevel	0
+#define irc_elevel	1
+
+static struct {
+	unsigned char level;
+	unsigned char mode;
+} tx4939irq[TX4939_NUM_IR] __read_mostly;
+
+static void tx4939_irq_unmask(struct irq_data *d)
+{
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
+	u32 __iomem *lvlp;
+	int ofs;
+	if (irq_nr < 32) {
+		irq_nr--;
+		lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r;
+	} else {
+		irq_nr -= 32;
+		lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r;
+	}
+	ofs = (irq_nr & 16) + (irq_nr & 1) * 8;
+	__raw_writel((__raw_readl(lvlp) & ~(0xff << ofs))
+		     | (tx4939irq[irq_nr].level << ofs),
+		     lvlp);
+}
+
+static inline void tx4939_irq_mask(struct irq_data *d)
+{
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
+	u32 __iomem *lvlp;
+	int ofs;
+	if (irq_nr < 32) {
+		irq_nr--;
+		lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r;
+	} else {
+		irq_nr -= 32;
+		lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r;
+	}
+	ofs = (irq_nr & 16) + (irq_nr & 1) * 8;
+	__raw_writel((__raw_readl(lvlp) & ~(0xff << ofs))
+		     | (irc_dlevel << ofs),
+		     lvlp);
+	mmiowb();
+}
+
+static void tx4939_irq_mask_ack(struct irq_data *d)
+{
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
+
+	tx4939_irq_mask(d);
+	if (TXx9_IRCR_EDGE(tx4939irq[irq_nr].mode)) {
+		irq_nr--;
+		/* clear edge detection */
+		__raw_writel((TXx9_IRSCR_EIClrE | (irq_nr & 0xf))
+			     << (irq_nr & 0x10),
+			     &tx4939_ircptr->edc.r);
+	}
+}
+
+static int tx4939_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
+	u32 cr;
+	u32 __iomem *crp;
+	int ofs;
+	int mode;
+
+	if (flow_type & IRQF_TRIGGER_PROBE)
+		return 0;
+	switch (flow_type & IRQF_TRIGGER_MASK) {
+	case IRQF_TRIGGER_RISING:
+		mode = TXx9_IRCR_UP;
+		break;
+	case IRQF_TRIGGER_FALLING:
+		mode = TXx9_IRCR_DOWN;
+		break;
+	case IRQF_TRIGGER_HIGH:
+		mode = TXx9_IRCR_HIGH;
+		break;
+	case IRQF_TRIGGER_LOW:
+		mode = TXx9_IRCR_LOW;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (irq_nr < 32) {
+		irq_nr--;
+		crp = &tx4939_ircptr->dm[(irq_nr & 8) >> 3].r;
+	} else {
+		irq_nr -= 32;
+		crp = &tx4939_ircptr->dm2[((irq_nr & 8) >> 3)].r;
+	}
+	ofs = (((irq_nr & 16) >> 1) | (irq_nr & (8 - 1))) * 2;
+	cr = __raw_readl(crp);
+	cr &= ~(0x3 << ofs);
+	cr |= (mode & 0x3) << ofs;
+	__raw_writel(cr, crp);
+	tx4939irq[irq_nr].mode = mode;
+	return 0;
+}
+
+static struct irq_chip tx4939_irq_chip = {
+	.name		= "TX4939",
+	.irq_ack	= tx4939_irq_mask_ack,
+	.irq_mask	= tx4939_irq_mask,
+	.irq_mask_ack	= tx4939_irq_mask_ack,
+	.irq_unmask	= tx4939_irq_unmask,
+	.irq_set_type	= tx4939_irq_set_type,
+};
+
+static int tx4939_irq_set_pri(int irc_irq, int new_pri)
+{
+	int old_pri;
+
+	if ((unsigned int)irc_irq >= TX4939_NUM_IR)
+		return 0;
+	old_pri = tx4939irq[irc_irq].level;
+	tx4939irq[irc_irq].level = new_pri;
+	return old_pri;
+}
+
+void __init tx4939_irq_init(void)
+{
+	int i;
+
+	mips_cpu_irq_init();
+	/* disable interrupt control */
+	__raw_writel(0, &tx4939_ircptr->den.r);
+	__raw_writel(0, &tx4939_ircptr->maskint.r);
+	__raw_writel(0, &tx4939_ircptr->maskext.r);
+	/* irq_base + 0 is not used */
+	for (i = 1; i < TX4939_NUM_IR; i++) {
+		tx4939irq[i].level = 4; /* middle level */
+		tx4939irq[i].mode = TXx9_IRCR_LOW;
+		irq_set_chip_and_handler(TXX9_IRQ_BASE + i, &tx4939_irq_chip,
+					 handle_level_irq);
+	}
+
+	/* mask all IRC interrupts */
+	__raw_writel(0, &tx4939_ircptr->msk.r);
+	for (i = 0; i < 16; i++)
+		__raw_writel(0, &tx4939_ircptr->lvl[i].r);
+	/* setup IRC interrupt mode (Low Active) */
+	for (i = 0; i < 2; i++)
+		__raw_writel(0, &tx4939_ircptr->dm[i].r);
+	for (i = 0; i < 2; i++)
+		__raw_writel(0, &tx4939_ircptr->dm2[i].r);
+	/* enable interrupt control */
+	__raw_writel(TXx9_IRCER_ICE, &tx4939_ircptr->den.r);
+	__raw_writel(irc_elevel, &tx4939_ircptr->msk.r);
+
+	irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT,
+				handle_simple_irq);
+
+	/* raise priority for errors, timers, sio */
+	tx4939_irq_set_pri(TX4939_IR_WTOERR, 7);
+	tx4939_irq_set_pri(TX4939_IR_PCIERR, 7);
+	tx4939_irq_set_pri(TX4939_IR_PCIPME, 7);
+	for (i = 0; i < TX4939_NUM_IR_TMR; i++)
+		tx4939_irq_set_pri(TX4939_IR_TMR(i), 6);
+	for (i = 0; i < TX4939_NUM_IR_SIO; i++)
+		tx4939_irq_set_pri(TX4939_IR_SIO(i), 5);
+}
+
+int tx4939_irq(void)
+{
+	u32 csr = __raw_readl(&tx4939_ircptr->cs.r);
+
+	if (likely(!(csr & TXx9_IRCSR_IF)))
+		return TXX9_IRQ_BASE + (csr & (TX4939_NUM_IR - 1));
+	return -1;
+}
diff --git a/arch/mips/txx9/generic/mem_tx4927.c b/arch/mips/txx9/generic/mem_tx4927.c
new file mode 100644
index 0000000..deea2ce
--- /dev/null
+++ b/arch/mips/txx9/generic/mem_tx4927.c
@@ -0,0 +1,75 @@
+/*
+ * common tx4927 memory interface
+ *
+ * Author: MontaVista Software, Inc.
+ *	   source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ *  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
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <asm/txx9/tx4927.h>
+
+static unsigned int __init tx4927_process_sdccr(u64 __iomem *addr)
+{
+	u64 val;
+	unsigned int sdccr_ce;
+	unsigned int sdccr_bs;
+	unsigned int sdccr_rs;
+	unsigned int sdccr_cs;
+	unsigned int sdccr_mw;
+	unsigned int bs = 0;
+	unsigned int rs = 0;
+	unsigned int cs = 0;
+	unsigned int mw = 0;
+
+	val = __raw_readq(addr);
+
+	/* MVMCP -- need #defs for these bits masks */
+	sdccr_ce = ((val & (1 << 10)) >> 10);
+	sdccr_bs = ((val & (1 << 8)) >> 8);
+	sdccr_rs = ((val & (3 << 5)) >> 5);
+	sdccr_cs = ((val & (7 << 2)) >> 2);
+	sdccr_mw = ((val & (1 << 0)) >> 0);
+
+	if (sdccr_ce) {
+		bs = 2 << sdccr_bs;
+		rs = 2048 << sdccr_rs;
+		cs = 256 << sdccr_cs;
+		mw = 8 >> sdccr_mw;
+	}
+
+	return rs * cs * mw * bs;
+}
+
+unsigned int __init tx4927_get_mem_size(void)
+{
+	unsigned int total = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tx4927_sdramcptr->cr); i++)
+		total += tx4927_process_sdccr(&tx4927_sdramcptr->cr[i]);
+	return total;
+}
diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c
new file mode 100644
index 0000000..fb99872
--- /dev/null
+++ b/arch/mips/txx9/generic/pci.c
@@ -0,0 +1,432 @@
+/*
+ * linux/arch/mips/txx9/pci.c
+ *
+ * Based on linux/arch/mips/txx9/rbtx4927/setup.c,
+ *	    linux/arch/mips/txx9/rbtx4938/setup.c,
+ *	    and RBTX49xx patch from CELF patch archive.
+ *
+ * Copyright 2001-2005 MontaVista Software Inc.
+ * Copyright (C) 1996, 97, 2001, 04  Ralf Baechle (ralf@linux-mips.org)
+ * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
+ *
+ * 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.
+ */
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/pci.h>
+#ifdef CONFIG_TOSHIBA_FPCIB0
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm/i8259.h>
+#include <asm/txx9/smsc_fdc37m81x.h>
+#endif
+
+static int __init
+early_read_config_word(struct pci_controller *hose,
+		       int top_bus, int bus, int devfn, int offset, u16 *value)
+{
+	struct pci_bus fake_bus;
+
+	fake_bus.number = bus;
+	fake_bus.sysdata = hose;
+	fake_bus.ops = hose->pci_ops;
+
+	if (bus != top_bus)
+		/* Fake a parent bus structure. */
+		fake_bus.parent = &fake_bus;
+	else
+		fake_bus.parent = NULL;
+
+	return pci_bus_read_config_word(&fake_bus, devfn, offset, value);
+}
+
+int __init txx9_pci66_check(struct pci_controller *hose, int top_bus,
+			    int current_bus)
+{
+	u32 pci_devfn;
+	unsigned short vid;
+	int cap66 = -1;
+	u16 stat;
+
+	/* It seems SLC90E66 needs some time after PCI reset... */
+	mdelay(80);
+
+	pr_info("PCI: Checking 66MHz capabilities...\n");
+
+	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
+		if (PCI_FUNC(pci_devfn))
+			continue;
+		if (early_read_config_word(hose, top_bus, current_bus,
+					   pci_devfn, PCI_VENDOR_ID, &vid) !=
+		    PCIBIOS_SUCCESSFUL)
+			continue;
+		if (vid == 0xffff)
+			continue;
+
+		/* check 66MHz capability */
+		if (cap66 < 0)
+			cap66 = 1;
+		if (cap66) {
+			early_read_config_word(hose, top_bus, current_bus,
+					       pci_devfn, PCI_STATUS, &stat);
+			if (!(stat & PCI_STATUS_66MHZ)) {
+				pr_debug("PCI: %02x:%02x not 66MHz capable.\n",
+					 current_bus, pci_devfn);
+				cap66 = 0;
+				break;
+			}
+		}
+	}
+	return cap66 > 0;
+}
+
+static struct resource primary_pci_mem_res[2] = {
+	{ .name = "PCI MEM" },
+	{ .name = "PCI MMIO" },
+};
+static struct resource primary_pci_io_res = { .name = "PCI IO" };
+struct pci_controller txx9_primary_pcic = {
+	.mem_resource = &primary_pci_mem_res[0],
+	.io_resource = &primary_pci_io_res,
+};
+
+#ifdef CONFIG_64BIT
+int txx9_pci_mem_high __initdata = 1;
+#else
+int txx9_pci_mem_high __initdata;
+#endif
+
+/*
+ * allocate pci_controller and resources.
+ * mem_base, io_base: physical address.	 0 for auto assignment.
+ * mem_size and io_size means max size on auto assignment.
+ * pcic must be &txx9_primary_pcic or NULL.
+ */
+struct pci_controller *__init
+txx9_alloc_pci_controller(struct pci_controller *pcic,
+			  unsigned long mem_base, unsigned long mem_size,
+			  unsigned long io_base, unsigned long io_size)
+{
+	struct pcic {
+		struct pci_controller c;
+		struct resource r_mem[2];
+		struct resource r_io;
+	} *new = NULL;
+	int min_size = 0x10000;
+
+	if (!pcic) {
+		new = kzalloc(sizeof(*new), GFP_KERNEL);
+		if (!new)
+			return NULL;
+		new->r_mem[0].name = "PCI mem";
+		new->r_mem[1].name = "PCI mmio";
+		new->r_io.name = "PCI io";
+		new->c.mem_resource = new->r_mem;
+		new->c.io_resource = &new->r_io;
+		pcic = &new->c;
+	} else
+		BUG_ON(pcic != &txx9_primary_pcic);
+	pcic->io_resource->flags = IORESOURCE_IO;
+
+	/*
+	 * for auto assignment, first search a (big) region for PCI
+	 * MEM, then search a region for PCI IO.
+	 */
+	if (mem_base) {
+		pcic->mem_resource[0].start = mem_base;
+		pcic->mem_resource[0].end = mem_base + mem_size - 1;
+		if (request_resource(&iomem_resource, &pcic->mem_resource[0]))
+			goto free_and_exit;
+	} else {
+		unsigned long min = 0, max = 0x20000000; /* low 512MB */
+		if (!mem_size) {
+			/* default size for auto assignment */
+			if (txx9_pci_mem_high)
+				mem_size = 0x20000000;	/* mem:512M(max) */
+			else
+				mem_size = 0x08000000;	/* mem:128M(max) */
+		}
+		if (txx9_pci_mem_high) {
+			min = 0x20000000;
+			max = 0xe0000000;
+		}
+		/* search free region for PCI MEM */
+		for (; mem_size >= min_size; mem_size /= 2) {
+			if (allocate_resource(&iomem_resource,
+					      &pcic->mem_resource[0],
+					      mem_size, min, max,
+					      mem_size, NULL, NULL) == 0)
+				break;
+		}
+		if (mem_size < min_size)
+			goto free_and_exit;
+	}
+
+	pcic->mem_resource[1].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	if (io_base) {
+		pcic->mem_resource[1].start = io_base;
+		pcic->mem_resource[1].end = io_base + io_size - 1;
+		if (request_resource(&iomem_resource, &pcic->mem_resource[1]))
+			goto release_and_exit;
+	} else {
+		if (!io_size)
+			/* default size for auto assignment */
+			io_size = 0x01000000;	/* io:16M(max) */
+		/* search free region for PCI IO in low 512MB */
+		for (; io_size >= min_size; io_size /= 2) {
+			if (allocate_resource(&iomem_resource,
+					      &pcic->mem_resource[1],
+					      io_size, 0, 0x20000000,
+					      io_size, NULL, NULL) == 0)
+				break;
+		}
+		if (io_size < min_size)
+			goto release_and_exit;
+		io_base = pcic->mem_resource[1].start;
+	}
+
+	pcic->mem_resource[0].flags = IORESOURCE_MEM;
+	if (pcic == &txx9_primary_pcic &&
+	    mips_io_port_base == (unsigned long)-1) {
+		/* map ioport 0 to PCI I/O space address 0 */
+		set_io_port_base(IO_BASE + pcic->mem_resource[1].start);
+		pcic->io_resource->start = 0;
+		pcic->io_offset = 0;	/* busaddr == ioaddr */
+		pcic->io_map_base = IO_BASE + pcic->mem_resource[1].start;
+	} else {
+		/* physaddr to ioaddr */
+		pcic->io_resource->start =
+			io_base - (mips_io_port_base - IO_BASE);
+		pcic->io_offset = io_base - (mips_io_port_base - IO_BASE);
+		pcic->io_map_base = mips_io_port_base;
+	}
+	pcic->io_resource->end = pcic->io_resource->start + io_size - 1;
+
+	pcic->mem_offset = 0;	/* busaddr == physaddr */
+
+	pr_info("PCI: IO %pR MEM %pR\n", &pcic->mem_resource[1],
+		&pcic->mem_resource[0]);
+
+	/* register_pci_controller() will request MEM resource */
+	release_resource(&pcic->mem_resource[0]);
+	return pcic;
+ release_and_exit:
+	release_resource(&pcic->mem_resource[0]);
+ free_and_exit:
+	kfree(new);
+	pr_err("PCI: Failed to allocate resources.\n");
+	return NULL;
+}
+
+static int __init
+txx9_arch_pci_init(void)
+{
+	PCIBIOS_MIN_IO = 0x8000;	/* reseve legacy I/O space */
+	return 0;
+}
+arch_initcall(txx9_arch_pci_init);
+
+/* IRQ/IDSEL mapping */
+int txx9_pci_option =
+#ifdef CONFIG_PICMG_PCI_BACKPLANE_DEFAULT
+	TXX9_PCI_OPT_PICMG |
+#endif
+	TXX9_PCI_OPT_CLK_AUTO;
+
+enum txx9_pci_err_action txx9_pci_err_action = TXX9_PCI_ERR_REPORT;
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+static irqreturn_t i8259_interrupt(int irq, void *dev_id)
+{
+	int isairq;
+
+	isairq = i8259_irq();
+	if (unlikely(isairq <= I8259A_IRQ_BASE))
+		return IRQ_NONE;
+	generic_handle_irq(isairq);
+	return IRQ_HANDLED;
+}
+
+static int txx9_i8259_irq_setup(int irq)
+{
+	int err;
+
+	init_i8259_irqs();
+	err = request_irq(irq, &i8259_interrupt, IRQF_SHARED,
+			  "cascade(i8259)", (void *)(long)irq);
+	if (!err)
+		pr_info("PCI-ISA bridge PIC (irq %d)\n", irq);
+	return err;
+}
+
+static void __ref quirk_slc90e66_bridge(struct pci_dev *dev)
+{
+	int irq;	/* PCI/ISA Bridge interrupt */
+	u8 reg_64;
+	u32 reg_b0;
+	u8 reg_e1;
+	irq = pcibios_map_irq(dev, PCI_SLOT(dev->devfn), 1); /* INTA */
+	if (!irq)
+		return;
+	txx9_i8259_irq_setup(irq);
+	pci_read_config_byte(dev, 0x64, &reg_64);
+	pci_read_config_dword(dev, 0xb0, &reg_b0);
+	pci_read_config_byte(dev, 0xe1, &reg_e1);
+	/* serial irq control */
+	reg_64 = 0xd0;
+	/* serial irq pin */
+	reg_b0 |= 0x00010000;
+	/* ide irq on isa14 */
+	reg_e1 &= 0xf0;
+	reg_e1 |= 0x0d;
+	pci_write_config_byte(dev, 0x64, reg_64);
+	pci_write_config_dword(dev, 0xb0, reg_b0);
+	pci_write_config_byte(dev, 0xe1, reg_e1);
+
+	smsc_fdc37m81x_init(0x3f0);
+	smsc_fdc37m81x_config_beg();
+	smsc_fdc37m81x_config_set(SMSC_FDC37M81X_DNUM,
+				  SMSC_FDC37M81X_KBD);
+	smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT, 1);
+	smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT2, 12);
+	smsc_fdc37m81x_config_set(SMSC_FDC37M81X_ACTIVE,
+				  1);
+	smsc_fdc37m81x_config_end();
+}
+
+static void quirk_slc90e66_ide(struct pci_dev *dev)
+{
+	unsigned char dat;
+	int regs[2] = {0x41, 0x43};
+	int i;
+
+	/* SMSC SLC90E66 IDE uses irq 14, 15 (default) */
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 14);
+	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &dat);
+	pr_info("PCI: %s: IRQ %02x", pci_name(dev), dat);
+	/* enable SMSC SLC90E66 IDE */
+	for (i = 0; i < ARRAY_SIZE(regs); i++) {
+		pci_read_config_byte(dev, regs[i], &dat);
+		pci_write_config_byte(dev, regs[i], dat | 0x80);
+		pci_read_config_byte(dev, regs[i], &dat);
+		pr_cont(" IDETIM%d %02x", i, dat);
+	}
+	pci_read_config_byte(dev, 0x5c, &dat);
+	/*
+	 * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
+	 *
+	 * This line of code is intended to provide the user with a work
+	 * around solution to the anomalies cited in SMSC's anomaly sheet
+	 * entitled, "SLC90E66 Functional Rev.J_0.1 Anomalies"".
+	 *
+	 * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!!
+	 */
+	dat |= 0x01;
+	pci_write_config_byte(dev, 0x5c, dat);
+	pci_read_config_byte(dev, 0x5c, &dat);
+	pr_cont(" REG5C %02x\n", dat);
+}
+#endif /* CONFIG_TOSHIBA_FPCIB0 */
+
+static void tc35815_fixup(struct pci_dev *dev)
+{
+	/* This device may have PM registers but not they are not supported. */
+	if (dev->pm_cap) {
+		dev_info(&dev->dev, "PM disabled\n");
+		dev->pm_cap = 0;
+	}
+}
+
+static void final_fixup(struct pci_dev *dev)
+{
+	unsigned char bist;
+
+	/* Do build-in self test */
+	if (pci_read_config_byte(dev, PCI_BIST, &bist) == PCIBIOS_SUCCESSFUL &&
+	    (bist & PCI_BIST_CAPABLE)) {
+		unsigned long timeout;
+		pci_set_power_state(dev, PCI_D0);
+		pr_info("PCI: %s BIST...", pci_name(dev));
+		pci_write_config_byte(dev, PCI_BIST, PCI_BIST_START);
+		timeout = jiffies + HZ * 2;	/* timeout after 2 sec */
+		do {
+			pci_read_config_byte(dev, PCI_BIST, &bist);
+			if (time_after(jiffies, timeout))
+				break;
+		} while (bist & PCI_BIST_START);
+		if (bist & (PCI_BIST_CODE_MASK | PCI_BIST_START))
+			pr_cont("failed. (0x%x)\n", bist);
+		else
+			pr_cont("OK.\n");
+	}
+}
+
+#ifdef CONFIG_TOSHIBA_FPCIB0
+#define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_0,
+	quirk_slc90e66_bridge);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1,
+	quirk_slc90e66_ide);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1,
+	quirk_slc90e66_ide);
+#endif
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2,
+			PCI_DEVICE_ID_TOSHIBA_TC35815_NWU, tc35815_fixup);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2,
+			PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939, tc35815_fixup);
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, final_fixup);
+DECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, final_fixup);
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
+
+static int (*txx9_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return txx9_pci_map_irq(dev, slot, pin);
+}
+
+char * (*txx9_board_pcibios_setup)(char *str) __initdata;
+
+char *__init txx9_pcibios_setup(char *str)
+{
+	if (txx9_board_pcibios_setup && !txx9_board_pcibios_setup(str))
+		return NULL;
+	if (!strcmp(str, "picmg")) {
+		/* PICMG compliant backplane (TOSHIBA JMB-PICMG-ATX
+		   (5V or 3.3V), JMB-PICMG-L2 (5V only), etc.) */
+		txx9_pci_option |= TXX9_PCI_OPT_PICMG;
+		return NULL;
+	} else if (!strcmp(str, "nopicmg")) {
+		/* non-PICMG compliant backplane (TOSHIBA
+		   RBHBK4100,RBHBK4200, Interface PCM-PCM05, etc.) */
+		txx9_pci_option &= ~TXX9_PCI_OPT_PICMG;
+		return NULL;
+	} else if (!strncmp(str, "clk=", 4)) {
+		char *val = str + 4;
+		txx9_pci_option &= ~TXX9_PCI_OPT_CLK_MASK;
+		if (strcmp(val, "33") == 0)
+			txx9_pci_option |= TXX9_PCI_OPT_CLK_33;
+		else if (strcmp(val, "66") == 0)
+			txx9_pci_option |= TXX9_PCI_OPT_CLK_66;
+		else /* "auto" */
+			txx9_pci_option |= TXX9_PCI_OPT_CLK_AUTO;
+		return NULL;
+	} else if (!strncmp(str, "err=", 4)) {
+		if (!strcmp(str + 4, "panic"))
+			txx9_pci_err_action = TXX9_PCI_ERR_PANIC;
+		else if (!strcmp(str + 4, "ignore"))
+			txx9_pci_err_action = TXX9_PCI_ERR_IGNORE;
+		return NULL;
+	}
+
+	txx9_pci_map_irq = txx9_board_vec->pci_map_irq;
+
+	return str;
+}
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
new file mode 100644
index 0000000..f6d9182
--- /dev/null
+++ b/arch/mips/txx9/generic/setup.c
@@ -0,0 +1,971 @@
+/*
+ * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
+ *	    and RBTX49xx patch from CELF patch archive.
+ *
+ * 2003-2005 (c) MontaVista Software, Inc.
+ * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/export.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/txx9/ndfmc.h>
+#include <linux/serial_core.h>
+#include <linux/mtd/physmap.h>
+#include <linux/leds.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <asm/bootinfo.h>
+#include <asm/idle.h>
+#include <asm/time.h>
+#include <asm/reboot.h>
+#include <asm/r4kcache.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/pci.h>
+#include <asm/txx9tmr.h>
+#include <asm/txx9/dmac.h>
+#ifdef CONFIG_CPU_TX49XX
+#include <asm/txx9/tx4938.h>
+#endif
+
+/* EBUSC settings of TX4927, etc. */
+struct resource txx9_ce_res[8];
+static char txx9_ce_res_name[8][4];	/* "CEn" */
+
+/* pcode, internal register */
+unsigned int txx9_pcode;
+char txx9_pcode_str[8];
+static struct resource txx9_reg_res = {
+	.name = txx9_pcode_str,
+	.flags = IORESOURCE_MEM,
+};
+void __init
+txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(txx9_ce_res); i++) {
+		sprintf(txx9_ce_res_name[i], "CE%d", i);
+		txx9_ce_res[i].flags = IORESOURCE_MEM;
+		txx9_ce_res[i].name = txx9_ce_res_name[i];
+	}
+
+	txx9_pcode = pcode;
+	sprintf(txx9_pcode_str, "TX%x", pcode);
+	if (base) {
+		txx9_reg_res.start = base & 0xfffffffffULL;
+		txx9_reg_res.end = (base & 0xfffffffffULL) + (size - 1);
+		request_resource(&iomem_resource, &txx9_reg_res);
+	}
+}
+
+/* clocks */
+unsigned int txx9_master_clock;
+unsigned int txx9_cpu_clock;
+unsigned int txx9_gbus_clock;
+
+#ifdef CONFIG_CPU_TX39XX
+/* don't enable by default - see errata */
+int txx9_ccfg_toeon __initdata;
+#else
+int txx9_ccfg_toeon __initdata = 1;
+#endif
+
+#define BOARD_VEC(board)	extern struct txx9_board_vec board;
+#include <asm/txx9/boards.h>
+#undef BOARD_VEC
+
+struct txx9_board_vec *txx9_board_vec __initdata;
+static char txx9_system_type[32];
+
+static struct txx9_board_vec *board_vecs[] __initdata = {
+#define BOARD_VEC(board)	&board,
+#include <asm/txx9/boards.h>
+#undef BOARD_VEC
+};
+
+static struct txx9_board_vec *__init find_board_byname(const char *name)
+{
+	int i;
+
+	/* search board_vecs table */
+	for (i = 0; i < ARRAY_SIZE(board_vecs); i++) {
+		if (strstr(board_vecs[i]->system, name))
+			return board_vecs[i];
+	}
+	return NULL;
+}
+
+static void __init prom_init_cmdline(void)
+{
+	int argc;
+	int *argv32;
+	int i;			/* Always ignore the "-c" at argv[0] */
+
+	if (fw_arg0 >= CKSEG0 || fw_arg1 < CKSEG0) {
+		/*
+		 * argc is not a valid number, or argv32 is not a valid
+		 * pointer
+		 */
+		argc = 0;
+		argv32 = NULL;
+	} else {
+		argc = (int)fw_arg0;
+		argv32 = (int *)fw_arg1;
+	}
+
+	arcs_cmdline[0] = '\0';
+
+	for (i = 1; i < argc; i++) {
+		char *str = (char *)(long)argv32[i];
+		if (i != 1)
+			strcat(arcs_cmdline, " ");
+		if (strchr(str, ' ')) {
+			strcat(arcs_cmdline, "\"");
+			strcat(arcs_cmdline, str);
+			strcat(arcs_cmdline, "\"");
+		} else
+			strcat(arcs_cmdline, str);
+	}
+}
+
+static int txx9_ic_disable __initdata;
+static int txx9_dc_disable __initdata;
+
+#if defined(CONFIG_CPU_TX49XX)
+/* flush all cache on very early stage (before 4k_cache_init) */
+static void __init early_flush_dcache(void)
+{
+	unsigned int conf = read_c0_config();
+	unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6));
+	unsigned int linesz = 32;
+	unsigned long addr, end;
+
+	end = INDEX_BASE + dc_size / 4;
+	/* 4way, waybit=0 */
+	for (addr = INDEX_BASE; addr < end; addr += linesz) {
+		cache_op(Index_Writeback_Inv_D, addr | 0);
+		cache_op(Index_Writeback_Inv_D, addr | 1);
+		cache_op(Index_Writeback_Inv_D, addr | 2);
+		cache_op(Index_Writeback_Inv_D, addr | 3);
+	}
+}
+
+static void __init txx9_cache_fixup(void)
+{
+	unsigned int conf;
+
+	conf = read_c0_config();
+	/* flush and disable */
+	if (txx9_ic_disable) {
+		conf |= TX49_CONF_IC;
+		write_c0_config(conf);
+	}
+	if (txx9_dc_disable) {
+		early_flush_dcache();
+		conf |= TX49_CONF_DC;
+		write_c0_config(conf);
+	}
+
+	/* enable cache */
+	conf = read_c0_config();
+	if (!txx9_ic_disable)
+		conf &= ~TX49_CONF_IC;
+	if (!txx9_dc_disable)
+		conf &= ~TX49_CONF_DC;
+	write_c0_config(conf);
+
+	if (conf & TX49_CONF_IC)
+		pr_info("TX49XX I-Cache disabled.\n");
+	if (conf & TX49_CONF_DC)
+		pr_info("TX49XX D-Cache disabled.\n");
+}
+#elif defined(CONFIG_CPU_TX39XX)
+/* flush all cache on very early stage (before tx39_cache_init) */
+static void __init early_flush_dcache(void)
+{
+	unsigned int conf = read_c0_config();
+	unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >>
+					   TX39_CONF_DCS_SHIFT));
+	unsigned int linesz = 16;
+	unsigned long addr, end;
+
+	end = INDEX_BASE + dc_size / 2;
+	/* 2way, waybit=0 */
+	for (addr = INDEX_BASE; addr < end; addr += linesz) {
+		cache_op(Index_Writeback_Inv_D, addr | 0);
+		cache_op(Index_Writeback_Inv_D, addr | 1);
+	}
+}
+
+static void __init txx9_cache_fixup(void)
+{
+	unsigned int conf;
+
+	conf = read_c0_config();
+	/* flush and disable */
+	if (txx9_ic_disable) {
+		conf &= ~TX39_CONF_ICE;
+		write_c0_config(conf);
+	}
+	if (txx9_dc_disable) {
+		early_flush_dcache();
+		conf &= ~TX39_CONF_DCE;
+		write_c0_config(conf);
+	}
+
+	/* enable cache */
+	conf = read_c0_config();
+	if (!txx9_ic_disable)
+		conf |= TX39_CONF_ICE;
+	if (!txx9_dc_disable)
+		conf |= TX39_CONF_DCE;
+	write_c0_config(conf);
+
+	if (!(conf & TX39_CONF_ICE))
+		pr_info("TX39XX I-Cache disabled.\n");
+	if (!(conf & TX39_CONF_DCE))
+		pr_info("TX39XX D-Cache disabled.\n");
+}
+#else
+static inline void txx9_cache_fixup(void)
+{
+}
+#endif
+
+static void __init preprocess_cmdline(void)
+{
+	static char cmdline[COMMAND_LINE_SIZE] __initdata;
+	char *s;
+
+	strcpy(cmdline, arcs_cmdline);
+	s = cmdline;
+	arcs_cmdline[0] = '\0';
+	while (s && *s) {
+		char *str = strsep(&s, " ");
+		if (strncmp(str, "board=", 6) == 0) {
+			txx9_board_vec = find_board_byname(str + 6);
+			continue;
+		} else if (strncmp(str, "masterclk=", 10) == 0) {
+			unsigned int val;
+			if (kstrtouint(str + 10, 10, &val) == 0)
+				txx9_master_clock = val;
+			continue;
+		} else if (strcmp(str, "icdisable") == 0) {
+			txx9_ic_disable = 1;
+			continue;
+		} else if (strcmp(str, "dcdisable") == 0) {
+			txx9_dc_disable = 1;
+			continue;
+		} else if (strcmp(str, "toeoff") == 0) {
+			txx9_ccfg_toeon = 0;
+			continue;
+		} else if (strcmp(str, "toeon") == 0) {
+			txx9_ccfg_toeon = 1;
+			continue;
+		}
+		if (arcs_cmdline[0])
+			strcat(arcs_cmdline, " ");
+		strcat(arcs_cmdline, str);
+	}
+
+	txx9_cache_fixup();
+}
+
+static void __init select_board(void)
+{
+	const char *envstr;
+
+	/* first, determine by "board=" argument in preprocess_cmdline() */
+	if (txx9_board_vec)
+		return;
+	/* next, determine by "board" envvar */
+	envstr = prom_getenv("board");
+	if (envstr) {
+		txx9_board_vec = find_board_byname(envstr);
+		if (txx9_board_vec)
+			return;
+	}
+
+	/* select "default" board */
+#ifdef CONFIG_TOSHIBA_JMR3927
+	txx9_board_vec = &jmr3927_vec;
+#endif
+#ifdef CONFIG_CPU_TX49XX
+	switch (TX4938_REV_PCODE()) {
+#ifdef CONFIG_TOSHIBA_RBTX4927
+	case 0x4927:
+		txx9_board_vec = &rbtx4927_vec;
+		break;
+	case 0x4937:
+		txx9_board_vec = &rbtx4937_vec;
+		break;
+#endif
+#ifdef CONFIG_TOSHIBA_RBTX4938
+	case 0x4938:
+		txx9_board_vec = &rbtx4938_vec;
+		break;
+#endif
+#ifdef CONFIG_TOSHIBA_RBTX4939
+	case 0x4939:
+		txx9_board_vec = &rbtx4939_vec;
+		break;
+#endif
+	}
+#endif
+}
+
+void __init prom_init(void)
+{
+	prom_init_cmdline();
+	preprocess_cmdline();
+	select_board();
+
+	strcpy(txx9_system_type, txx9_board_vec->system);
+
+	txx9_board_vec->prom_init();
+}
+
+void __init prom_free_prom_memory(void)
+{
+	unsigned long saddr = PAGE_SIZE;
+	unsigned long eaddr = __pa_symbol(&_text);
+
+	if (saddr < eaddr)
+		free_init_pages("prom memory", saddr, eaddr);
+}
+
+const char *get_system_type(void)
+{
+	return txx9_system_type;
+}
+
+const char *__init prom_getenv(const char *name)
+{
+	const s32 *str;
+
+	if (fw_arg2 < CKSEG0)
+		return NULL;
+
+	str = (const s32 *)fw_arg2;
+	/* YAMON style ("name", "value" pairs) */
+	while (str[0] && str[1]) {
+		if (!strcmp((const char *)(unsigned long)str[0], name))
+			return (const char *)(unsigned long)str[1];
+		str += 2;
+	}
+	return NULL;
+}
+
+static void __noreturn txx9_machine_halt(void)
+{
+	local_irq_disable();
+	clear_c0_status(ST0_IM);
+	while (1) {
+		if (cpu_wait) {
+			(*cpu_wait)();
+			if (cpu_has_counter) {
+				/*
+				 * Clear counter interrupt while it
+				 * breaks WAIT instruction even if
+				 * masked.
+				 */
+				write_c0_compare(0);
+			}
+		}
+	}
+}
+
+/* Watchdog support */
+void __init txx9_wdt_init(unsigned long base)
+{
+	struct resource res = {
+		.start	= base,
+		.end	= base + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	};
+	platform_device_register_simple("txx9wdt", -1, &res, 1);
+}
+
+void txx9_wdt_now(unsigned long base)
+{
+	struct txx9_tmr_reg __iomem *tmrptr =
+		ioremap(base, sizeof(struct txx9_tmr_reg));
+	/* disable watch dog timer */
+	__raw_writel(TXx9_TMWTMR_WDIS | TXx9_TMWTMR_TWC, &tmrptr->wtmr);
+	__raw_writel(0, &tmrptr->tcr);
+	/* kick watchdog */
+	__raw_writel(TXx9_TMWTMR_TWIE, &tmrptr->wtmr);
+	__raw_writel(1, &tmrptr->cpra); /* immediate */
+	__raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG,
+		     &tmrptr->tcr);
+}
+
+/* SPI support */
+void __init txx9_spi_init(int busid, unsigned long base, int irq)
+{
+	struct resource res[] = {
+		{
+			.start	= base,
+			.end	= base + 0x20 - 1,
+			.flags	= IORESOURCE_MEM,
+		}, {
+			.start	= irq,
+			.flags	= IORESOURCE_IRQ,
+		},
+	};
+	platform_device_register_simple("spi_txx9", busid,
+					res, ARRAY_SIZE(res));
+}
+
+void __init txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr)
+{
+	struct platform_device *pdev =
+		platform_device_alloc("tc35815-mac", id);
+	if (!pdev ||
+	    platform_device_add_data(pdev, ethaddr, 6) ||
+	    platform_device_add(pdev))
+		platform_device_put(pdev);
+}
+
+void __init txx9_sio_init(unsigned long baseaddr, int irq,
+			  unsigned int line, unsigned int sclk, int nocts)
+{
+#ifdef CONFIG_SERIAL_TXX9
+	struct uart_port req;
+
+	memset(&req, 0, sizeof(req));
+	req.line = line;
+	req.iotype = UPIO_MEM;
+	req.membase = ioremap(baseaddr, 0x24);
+	req.mapbase = baseaddr;
+	req.irq = irq;
+	if (!nocts)
+		req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+	if (sclk) {
+		req.flags |= UPF_MAGIC_MULTIPLIER /*USE_SCLK*/;
+		req.uartclk = sclk;
+	} else
+		req.uartclk = TXX9_IMCLK;
+	early_serial_txx9_setup(&req);
+#endif /* CONFIG_SERIAL_TXX9 */
+}
+
+#ifdef CONFIG_EARLY_PRINTK
+static void null_prom_putchar(char c)
+{
+}
+void (*txx9_prom_putchar)(char c) = null_prom_putchar;
+
+void prom_putchar(char c)
+{
+	txx9_prom_putchar(c);
+}
+
+static void __iomem *early_txx9_sio_port;
+
+static void early_txx9_sio_putchar(char c)
+{
+#define TXX9_SICISR	0x0c
+#define TXX9_SITFIFO	0x1c
+#define TXX9_SICISR_TXALS	0x00000002
+	while (!(__raw_readl(early_txx9_sio_port + TXX9_SICISR) &
+		 TXX9_SICISR_TXALS))
+		;
+	__raw_writel(c, early_txx9_sio_port + TXX9_SITFIFO);
+}
+
+void __init txx9_sio_putchar_init(unsigned long baseaddr)
+{
+	early_txx9_sio_port = ioremap(baseaddr, 0x24);
+	txx9_prom_putchar = early_txx9_sio_putchar;
+}
+#endif /* CONFIG_EARLY_PRINTK */
+
+/* wrappers */
+void __init plat_mem_setup(void)
+{
+	ioport_resource.start = 0;
+	ioport_resource.end = ~0UL;	/* no limit */
+	iomem_resource.start = 0;
+	iomem_resource.end = ~0UL;	/* no limit */
+
+	/* fallback restart/halt routines */
+	_machine_restart = (void (*)(char *))txx9_machine_halt;
+	_machine_halt = txx9_machine_halt;
+	pm_power_off = txx9_machine_halt;
+
+#ifdef CONFIG_PCI
+	pcibios_plat_setup = txx9_pcibios_setup;
+#endif
+	txx9_board_vec->mem_setup();
+}
+
+void __init arch_init_irq(void)
+{
+	txx9_board_vec->irq_setup();
+}
+
+void __init plat_time_init(void)
+{
+#ifdef CONFIG_CPU_TX49XX
+	mips_hpt_frequency = txx9_cpu_clock / 2;
+#endif
+	txx9_board_vec->time_init();
+}
+
+static void txx9_clk_init(void)
+{
+	struct clk_hw *hw;
+	int error;
+
+	hw = clk_hw_register_fixed_rate(NULL, "gbus", NULL, 0, txx9_gbus_clock);
+	if (IS_ERR(hw)) {
+		error = PTR_ERR(hw);
+		goto fail;
+	}
+
+	hw = clk_hw_register_fixed_factor(NULL, "imbus", "gbus", 0, 1, 2);
+	error = clk_hw_register_clkdev(hw, "imbus_clk", NULL);
+	if (error)
+		goto fail;
+
+#ifdef CONFIG_CPU_TX49XX
+	if (TX4938_REV_PCODE() == 0x4938) {
+		hw = clk_hw_register_fixed_factor(NULL, "spi", "gbus", 0, 1, 4);
+		error = clk_hw_register_clkdev(hw, "spi-baseclk", NULL);
+		if (error)
+			goto fail;
+	}
+#endif
+
+	return;
+
+fail:
+	pr_err("Failed to register clocks: %d\n", error);
+}
+
+static int __init _txx9_arch_init(void)
+{
+	txx9_clk_init();
+
+	if (txx9_board_vec->arch_init)
+		txx9_board_vec->arch_init();
+	return 0;
+}
+arch_initcall(_txx9_arch_init);
+
+static int __init _txx9_device_init(void)
+{
+	if (txx9_board_vec->device_init)
+		txx9_board_vec->device_init();
+	return 0;
+}
+device_initcall(_txx9_device_init);
+
+int (*txx9_irq_dispatch)(int pending);
+asmlinkage void plat_irq_dispatch(void)
+{
+	int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+	int irq = txx9_irq_dispatch(pending);
+
+	if (likely(irq >= 0))
+		do_IRQ(irq);
+	else
+		spurious_interrupt();
+}
+
+/* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */
+#ifdef NEEDS_TXX9_SWIZZLE_ADDR_B
+static unsigned long __swizzle_addr_none(unsigned long port)
+{
+	return port;
+}
+unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none;
+EXPORT_SYMBOL(__swizzle_addr_b);
+#endif
+
+#ifdef NEEDS_TXX9_IOSWABW
+static u16 ioswabw_default(volatile u16 *a, u16 x)
+{
+	return le16_to_cpu(x);
+}
+static u16 __mem_ioswabw_default(volatile u16 *a, u16 x)
+{
+	return x;
+}
+u16 (*ioswabw)(volatile u16 *a, u16 x) = ioswabw_default;
+EXPORT_SYMBOL(ioswabw);
+u16 (*__mem_ioswabw)(volatile u16 *a, u16 x) = __mem_ioswabw_default;
+EXPORT_SYMBOL(__mem_ioswabw);
+#endif
+
+void __init txx9_physmap_flash_init(int no, unsigned long addr,
+				    unsigned long size,
+				    const struct physmap_flash_data *pdata)
+{
+#if IS_ENABLED(CONFIG_MTD_PHYSMAP)
+	struct resource res = {
+		.start = addr,
+		.end = addr + size - 1,
+		.flags = IORESOURCE_MEM,
+	};
+	struct platform_device *pdev;
+	static struct mtd_partition parts[2];
+	struct physmap_flash_data pdata_part;
+
+	/* If this area contained boot area, make separate partition */
+	if (pdata->nr_parts == 0 && !pdata->parts &&
+	    addr < 0x1fc00000 && addr + size > 0x1fc00000 &&
+	    !parts[0].name) {
+		parts[0].name = "boot";
+		parts[0].offset = 0x1fc00000 - addr;
+		parts[0].size = addr + size - 0x1fc00000;
+		parts[1].name = "user";
+		parts[1].offset = 0;
+		parts[1].size = 0x1fc00000 - addr;
+		pdata_part = *pdata;
+		pdata_part.nr_parts = ARRAY_SIZE(parts);
+		pdata_part.parts = parts;
+		pdata = &pdata_part;
+	}
+
+	pdev = platform_device_alloc("physmap-flash", no);
+	if (!pdev ||
+	    platform_device_add_resources(pdev, &res, 1) ||
+	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
+	    platform_device_add(pdev))
+		platform_device_put(pdev);
+#endif
+}
+
+void __init txx9_ndfmc_init(unsigned long baseaddr,
+			    const struct txx9ndfmc_platform_data *pdata)
+{
+#if IS_ENABLED(CONFIG_MTD_NAND_TXX9NDFMC)
+	struct resource res = {
+		.start = baseaddr,
+		.end = baseaddr + 0x1000 - 1,
+		.flags = IORESOURCE_MEM,
+	};
+	struct platform_device *pdev = platform_device_alloc("txx9ndfmc", -1);
+
+	if (!pdev ||
+	    platform_device_add_resources(pdev, &res, 1) ||
+	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
+	    platform_device_add(pdev))
+		platform_device_put(pdev);
+#endif
+}
+
+#if IS_ENABLED(CONFIG_LEDS_GPIO)
+static DEFINE_SPINLOCK(txx9_iocled_lock);
+
+#define TXX9_IOCLED_MAXLEDS 8
+
+struct txx9_iocled_data {
+	struct gpio_chip chip;
+	u8 cur_val;
+	void __iomem *mmioaddr;
+	struct gpio_led_platform_data pdata;
+	struct gpio_led leds[TXX9_IOCLED_MAXLEDS];
+	char names[TXX9_IOCLED_MAXLEDS][32];
+};
+
+static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct txx9_iocled_data *data = gpiochip_get_data(chip);
+	return !!(data->cur_val & (1 << offset));
+}
+
+static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset,
+			    int value)
+{
+	struct txx9_iocled_data *data = gpiochip_get_data(chip);
+	unsigned long flags;
+	spin_lock_irqsave(&txx9_iocled_lock, flags);
+	if (value)
+		data->cur_val |= 1 << offset;
+	else
+		data->cur_val &= ~(1 << offset);
+	writeb(data->cur_val, data->mmioaddr);
+	mmiowb();
+	spin_unlock_irqrestore(&txx9_iocled_lock, flags);
+}
+
+static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset)
+{
+	return 0;
+}
+
+static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset,
+			       int value)
+{
+	txx9_iocled_set(chip, offset, value);
+	return 0;
+}
+
+void __init txx9_iocled_init(unsigned long baseaddr,
+			     int basenum, unsigned int num, int lowactive,
+			     const char *color, char **deftriggers)
+{
+	struct txx9_iocled_data *iocled;
+	struct platform_device *pdev;
+	int i;
+	static char *default_triggers[] __initdata = {
+		"heartbeat",
+		"disk-activity",
+		"nand-disk",
+		NULL,
+	};
+
+	if (!deftriggers)
+		deftriggers = default_triggers;
+	iocled = kzalloc(sizeof(*iocled), GFP_KERNEL);
+	if (!iocled)
+		return;
+	iocled->mmioaddr = ioremap(baseaddr, 1);
+	if (!iocled->mmioaddr)
+		goto out_free;
+	iocled->chip.get = txx9_iocled_get;
+	iocled->chip.set = txx9_iocled_set;
+	iocled->chip.direction_input = txx9_iocled_dir_in;
+	iocled->chip.direction_output = txx9_iocled_dir_out;
+	iocled->chip.label = "iocled";
+	iocled->chip.base = basenum;
+	iocled->chip.ngpio = num;
+	if (gpiochip_add_data(&iocled->chip, iocled))
+		goto out_unmap;
+	if (basenum < 0)
+		basenum = iocled->chip.base;
+
+	pdev = platform_device_alloc("leds-gpio", basenum);
+	if (!pdev)
+		goto out_gpio;
+	iocled->pdata.num_leds = num;
+	iocled->pdata.leds = iocled->leds;
+	for (i = 0; i < num; i++) {
+		struct gpio_led *led = &iocled->leds[i];
+		snprintf(iocled->names[i], sizeof(iocled->names[i]),
+			 "iocled:%s:%u", color, i);
+		led->name = iocled->names[i];
+		led->gpio = basenum + i;
+		led->active_low = lowactive;
+		if (deftriggers && *deftriggers)
+			led->default_trigger = *deftriggers++;
+	}
+	pdev->dev.platform_data = &iocled->pdata;
+	if (platform_device_add(pdev))
+		goto out_pdev;
+	return;
+
+out_pdev:
+	platform_device_put(pdev);
+out_gpio:
+	gpiochip_remove(&iocled->chip);
+out_unmap:
+	iounmap(iocled->mmioaddr);
+out_free:
+	kfree(iocled);
+}
+#else /* CONFIG_LEDS_GPIO */
+void __init txx9_iocled_init(unsigned long baseaddr,
+			     int basenum, unsigned int num, int lowactive,
+			     const char *color, char **deftriggers)
+{
+}
+#endif /* CONFIG_LEDS_GPIO */
+
+void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq,
+			   const struct txx9dmac_platform_data *pdata)
+{
+#if IS_ENABLED(CONFIG_TXX9_DMAC)
+	struct resource res[] = {
+		{
+			.start = baseaddr,
+			.end = baseaddr + 0x800 - 1,
+			.flags = IORESOURCE_MEM,
+#ifndef CONFIG_MACH_TX49XX
+		}, {
+			.start = irq,
+			.flags = IORESOURCE_IRQ,
+#endif
+		}
+	};
+#ifdef CONFIG_MACH_TX49XX
+	struct resource chan_res[] = {
+		{
+			.flags = IORESOURCE_IRQ,
+		}
+	};
+#endif
+	struct platform_device *pdev = platform_device_alloc("txx9dmac", id);
+	struct txx9dmac_chan_platform_data cpdata;
+	int i;
+
+	if (!pdev ||
+	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
+	    platform_device_add_data(pdev, pdata, sizeof(*pdata)) ||
+	    platform_device_add(pdev)) {
+		platform_device_put(pdev);
+		return;
+	}
+	memset(&cpdata, 0, sizeof(cpdata));
+	cpdata.dmac_dev = pdev;
+	for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) {
+#ifdef CONFIG_MACH_TX49XX
+		chan_res[0].start = irq + i;
+#endif
+		pdev = platform_device_alloc("txx9dmac-chan",
+					     id * TXX9_DMA_MAX_NR_CHANNELS + i);
+		if (!pdev ||
+#ifdef CONFIG_MACH_TX49XX
+		    platform_device_add_resources(pdev, chan_res,
+						  ARRAY_SIZE(chan_res)) ||
+#endif
+		    platform_device_add_data(pdev, &cpdata, sizeof(cpdata)) ||
+		    platform_device_add(pdev))
+			platform_device_put(pdev);
+	}
+#endif
+}
+
+void __init txx9_aclc_init(unsigned long baseaddr, int irq,
+			   unsigned int dmac_id,
+			   unsigned int dma_chan_out,
+			   unsigned int dma_chan_in)
+{
+#if IS_ENABLED(CONFIG_SND_SOC_TXX9ACLC)
+	unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS;
+	struct resource res[] = {
+		{
+			.start = baseaddr,
+			.end = baseaddr + 0x100 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.name = "txx9dmac-chan",
+			.start = dma_base + dma_chan_out,
+			.flags = IORESOURCE_DMA,
+		}, {
+			.name = "txx9dmac-chan",
+			.start = dma_base + dma_chan_in,
+			.flags = IORESOURCE_DMA,
+		}
+	};
+	struct platform_device *pdev =
+		platform_device_alloc("txx9aclc-ac97", -1);
+
+	if (!pdev ||
+	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
+	    platform_device_add(pdev))
+		platform_device_put(pdev);
+#endif
+}
+
+static struct bus_type txx9_sramc_subsys = {
+	.name = "txx9_sram",
+	.dev_name = "txx9_sram",
+};
+
+struct txx9_sramc_dev {
+	struct device dev;
+	struct bin_attribute bindata_attr;
+	void __iomem *base;
+};
+
+static ssize_t txx9_sram_read(struct file *filp, struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t pos, size_t size)
+{
+	struct txx9_sramc_dev *dev = bin_attr->private;
+	size_t ramsize = bin_attr->size;
+
+	if (pos >= ramsize)
+		return 0;
+	if (pos + size > ramsize)
+		size = ramsize - pos;
+	memcpy_fromio(buf, dev->base + pos, size);
+	return size;
+}
+
+static ssize_t txx9_sram_write(struct file *filp, struct kobject *kobj,
+			       struct bin_attribute *bin_attr,
+			       char *buf, loff_t pos, size_t size)
+{
+	struct txx9_sramc_dev *dev = bin_attr->private;
+	size_t ramsize = bin_attr->size;
+
+	if (pos >= ramsize)
+		return 0;
+	if (pos + size > ramsize)
+		size = ramsize - pos;
+	memcpy_toio(dev->base + pos, buf, size);
+	return size;
+}
+
+static void txx9_device_release(struct device *dev)
+{
+	struct txx9_sramc_dev *tdev;
+
+	tdev = container_of(dev, struct txx9_sramc_dev, dev);
+	kfree(tdev);
+}
+
+void __init txx9_sramc_init(struct resource *r)
+{
+	struct txx9_sramc_dev *dev;
+	size_t size;
+	int err;
+
+	err = subsys_system_register(&txx9_sramc_subsys, NULL);
+	if (err)
+		return;
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return;
+	size = resource_size(r);
+	dev->base = ioremap(r->start, size);
+	if (!dev->base) {
+		kfree(dev);
+		return;
+	}
+	dev->dev.release = &txx9_device_release;
+	dev->dev.bus = &txx9_sramc_subsys;
+	sysfs_bin_attr_init(&dev->bindata_attr);
+	dev->bindata_attr.attr.name = "bindata";
+	dev->bindata_attr.attr.mode = S_IRUSR | S_IWUSR;
+	dev->bindata_attr.read = txx9_sram_read;
+	dev->bindata_attr.write = txx9_sram_write;
+	dev->bindata_attr.size = size;
+	dev->bindata_attr.private = dev;
+	err = device_register(&dev->dev);
+	if (err)
+		goto exit_put;
+	err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr);
+	if (err) {
+		device_unregister(&dev->dev);
+		iounmap(dev->base);
+		kfree(dev);
+	}
+	return;
+exit_put:
+	put_device(&dev->dev);
+	return;
+}
diff --git a/arch/mips/txx9/generic/setup_tx3927.c b/arch/mips/txx9/generic/setup_tx3927.c
new file mode 100644
index 0000000..33f7a72
--- /dev/null
+++ b/arch/mips/txx9/generic/setup_tx3927.c
@@ -0,0 +1,136 @@
+/*
+ * TX3927 setup routines
+ * Based on linux/arch/mips/txx9/jmr3927/setup.c
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/param.h>
+#include <linux/io.h>
+#include <linux/mtd/physmap.h>
+#include <asm/mipsregs.h>
+#include <asm/txx9irq.h>
+#include <asm/txx9tmr.h>
+#include <asm/txx9pio.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/tx3927.h>
+
+void __init tx3927_wdt_init(void)
+{
+	txx9_wdt_init(TX3927_TMR_REG(2));
+}
+
+void __init tx3927_setup(void)
+{
+	int i;
+	unsigned int conf;
+
+	txx9_reg_res_init(TX3927_REV_PCODE(), TX3927_REG_BASE,
+			  TX3927_REG_SIZE);
+
+	/* SDRAMC,ROMC are configured by PROM */
+	for (i = 0; i < 8; i++) {
+		if (!(tx3927_romcptr->cr[i] & 0x8))
+			continue;	/* disabled */
+		txx9_ce_res[i].start = (unsigned long)TX3927_ROMC_BA(i);
+		txx9_ce_res[i].end =
+			txx9_ce_res[i].start + TX3927_ROMC_SIZE(i) - 1;
+		request_resource(&iomem_resource, &txx9_ce_res[i]);
+	}
+
+	/* clocks */
+	txx9_gbus_clock = txx9_cpu_clock / 2;
+	/* change default value to udelay/mdelay take reasonable time */
+	loops_per_jiffy = txx9_cpu_clock / HZ / 2;
+
+	/* CCFG */
+	/* enable Timeout BusError */
+	if (txx9_ccfg_toeon)
+		tx3927_ccfgptr->ccfg |= TX3927_CCFG_TOE;
+
+	/* clear BusErrorOnWrite flag */
+	tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_BEOW;
+	if (read_c0_conf() & TX39_CONF_WBON)
+		/* Disable PCI snoop */
+		tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_PSNP;
+	else
+		/* Enable PCI SNOOP - with write through only */
+		tx3927_ccfgptr->ccfg |= TX3927_CCFG_PSNP;
+	/* do reset on watchdog */
+	tx3927_ccfgptr->ccfg |= TX3927_CCFG_WR;
+
+	pr_info("TX3927 -- CRIR:%08lx CCFG:%08lx PCFG:%08lx\n",
+		tx3927_ccfgptr->crir, tx3927_ccfgptr->ccfg,
+		tx3927_ccfgptr->pcfg);
+
+	/* TMR */
+	for (i = 0; i < TX3927_NR_TMR; i++)
+		txx9_tmr_init(TX3927_TMR_REG(i));
+
+	/* DMA */
+	tx3927_dmaptr->mcr = 0;
+	for (i = 0; i < ARRAY_SIZE(tx3927_dmaptr->ch); i++) {
+		/* reset channel */
+		tx3927_dmaptr->ch[i].ccr = TX3927_DMA_CCR_CHRST;
+		tx3927_dmaptr->ch[i].ccr = 0;
+	}
+	/* enable DMA */
+#ifdef __BIG_ENDIAN
+	tx3927_dmaptr->mcr = TX3927_DMA_MCR_MSTEN;
+#else
+	tx3927_dmaptr->mcr = TX3927_DMA_MCR_MSTEN | TX3927_DMA_MCR_LE;
+#endif
+
+	/* PIO */
+	__raw_writel(0, &tx3927_pioptr->maskcpu);
+	__raw_writel(0, &tx3927_pioptr->maskext);
+
+	conf = read_c0_conf();
+	if (conf & TX39_CONF_DCE) {
+		if (!(conf & TX39_CONF_WBON))
+			pr_info("TX3927 D-Cache WriteThrough.\n");
+		else if (!(conf & TX39_CONF_CWFON))
+			pr_info("TX3927 D-Cache WriteBack.\n");
+		else
+			pr_info("TX3927 D-Cache WriteBack (CWF) .\n");
+	}
+}
+
+void __init tx3927_time_init(unsigned int evt_tmrnr, unsigned int src_tmrnr)
+{
+	txx9_clockevent_init(TX3927_TMR_REG(evt_tmrnr),
+			     TXX9_IRQ_BASE + TX3927_IR_TMR(evt_tmrnr),
+			     TXX9_IMCLK);
+	txx9_clocksource_init(TX3927_TMR_REG(src_tmrnr), TXX9_IMCLK);
+}
+
+void __init tx3927_sio_init(unsigned int sclk, unsigned int cts_mask)
+{
+	int i;
+
+	for (i = 0; i < 2; i++)
+		txx9_sio_init(TX3927_SIO_REG(i),
+			      TXX9_IRQ_BASE + TX3927_IR_SIO(i),
+			      i, sclk, (1 << i) & cts_mask);
+}
+
+void __init tx3927_mtd_init(int ch)
+{
+	struct physmap_flash_data pdata = {
+		.width = TX3927_ROMC_WIDTH(ch) / 8,
+	};
+	unsigned long start = txx9_ce_res[ch].start;
+	unsigned long size = txx9_ce_res[ch].end - start + 1;
+
+	if (!(tx3927_romcptr->cr[ch] & 0x8))
+		return; /* disabled */
+	txx9_physmap_flash_init(ch, start, size, &pdata);
+}
diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c
new file mode 100644
index 0000000..46e9c41
--- /dev/null
+++ b/arch/mips/txx9/generic/setup_tx4927.c
@@ -0,0 +1,337 @@
+/*
+ * TX4927 setup routines
+ * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
+ *	    and RBTX49xx patch from CELF patch archive.
+ *
+ * 2003-2005 (c) MontaVista Software, Inc.
+ * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/param.h>
+#include <linux/ptrace.h>
+#include <linux/mtd/physmap.h>
+#include <asm/reboot.h>
+#include <asm/traps.h>
+#include <asm/txx9irq.h>
+#include <asm/txx9tmr.h>
+#include <asm/txx9pio.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/dmac.h>
+#include <asm/txx9/tx4927.h>
+
+static void __init tx4927_wdr_init(void)
+{
+	/* report watchdog reset status */
+	if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST)
+		pr_warn("Watchdog reset detected at 0x%lx\n",
+			read_c0_errorepc());
+	/* clear WatchDogReset (W1C) */
+	tx4927_ccfg_set(TX4927_CCFG_WDRST);
+	/* do reset on watchdog */
+	tx4927_ccfg_set(TX4927_CCFG_WR);
+}
+
+void __init tx4927_wdt_init(void)
+{
+	txx9_wdt_init(TX4927_TMR_REG(2) & 0xfffffffffULL);
+}
+
+static void tx4927_machine_restart(char *command)
+{
+	local_irq_disable();
+	pr_emerg("Rebooting (with %s watchdog reset)...\n",
+		 (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDREXEN) ?
+		 "external" : "internal");
+	/* clear watchdog status */
+	tx4927_ccfg_set(TX4927_CCFG_WDRST);	/* W1C */
+	txx9_wdt_now(TX4927_TMR_REG(2) & 0xfffffffffULL);
+	while (!(____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST))
+		;
+	mdelay(10);
+	if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDREXEN) {
+		pr_emerg("Rebooting (with internal watchdog reset)...\n");
+		/* External WDRST failed.  Do internal watchdog reset */
+		tx4927_ccfg_clear(TX4927_CCFG_WDREXEN);
+	}
+	/* fallback */
+	(*_machine_halt)();
+}
+
+void show_registers(struct pt_regs *regs);
+static int tx4927_be_handler(struct pt_regs *regs, int is_fixup)
+{
+	int data = regs->cp0_cause & 4;
+	console_verbose();
+	pr_err("%cBE exception at %#lx\n", data ? 'D' : 'I', regs->cp0_epc);
+	pr_err("ccfg:%llx, toea:%llx\n",
+	       (unsigned long long)____raw_readq(&tx4927_ccfgptr->ccfg),
+	       (unsigned long long)____raw_readq(&tx4927_ccfgptr->toea));
+#ifdef CONFIG_PCI
+	tx4927_report_pcic_status();
+#endif
+	show_registers(regs);
+	panic("BusError!");
+}
+static void __init tx4927_be_init(void)
+{
+	board_be_handler = tx4927_be_handler;
+}
+
+static struct resource tx4927_sdram_resource[4];
+
+void __init tx4927_setup(void)
+{
+	int i;
+	__u32 divmode;
+	unsigned int cpuclk = 0;
+	u64 ccfg;
+
+	txx9_reg_res_init(TX4927_REV_PCODE(), TX4927_REG_BASE,
+			  TX4927_REG_SIZE);
+	set_c0_config(TX49_CONF_CWFON);
+
+	/* SDRAMC,EBUSC are configured by PROM */
+	for (i = 0; i < 8; i++) {
+		if (!(TX4927_EBUSC_CR(i) & 0x8))
+			continue;	/* disabled */
+		txx9_ce_res[i].start = (unsigned long)TX4927_EBUSC_BA(i);
+		txx9_ce_res[i].end =
+			txx9_ce_res[i].start + TX4927_EBUSC_SIZE(i) - 1;
+		request_resource(&iomem_resource, &txx9_ce_res[i]);
+	}
+
+	/* clocks */
+	ccfg = ____raw_readq(&tx4927_ccfgptr->ccfg);
+	if (txx9_master_clock) {
+		/* calculate gbus_clock and cpu_clock from master_clock */
+		divmode = (__u32)ccfg & TX4927_CCFG_DIVMODE_MASK;
+		switch (divmode) {
+		case TX4927_CCFG_DIVMODE_8:
+		case TX4927_CCFG_DIVMODE_10:
+		case TX4927_CCFG_DIVMODE_12:
+		case TX4927_CCFG_DIVMODE_16:
+			txx9_gbus_clock = txx9_master_clock * 4; break;
+		default:
+			txx9_gbus_clock = txx9_master_clock;
+		}
+		switch (divmode) {
+		case TX4927_CCFG_DIVMODE_2:
+		case TX4927_CCFG_DIVMODE_8:
+			cpuclk = txx9_gbus_clock * 2; break;
+		case TX4927_CCFG_DIVMODE_2_5:
+		case TX4927_CCFG_DIVMODE_10:
+			cpuclk = txx9_gbus_clock * 5 / 2; break;
+		case TX4927_CCFG_DIVMODE_3:
+		case TX4927_CCFG_DIVMODE_12:
+			cpuclk = txx9_gbus_clock * 3; break;
+		case TX4927_CCFG_DIVMODE_4:
+		case TX4927_CCFG_DIVMODE_16:
+			cpuclk = txx9_gbus_clock * 4; break;
+		}
+		txx9_cpu_clock = cpuclk;
+	} else {
+		if (txx9_cpu_clock == 0)
+			txx9_cpu_clock = 200000000;	/* 200MHz */
+		/* calculate gbus_clock and master_clock from cpu_clock */
+		cpuclk = txx9_cpu_clock;
+		divmode = (__u32)ccfg & TX4927_CCFG_DIVMODE_MASK;
+		switch (divmode) {
+		case TX4927_CCFG_DIVMODE_2:
+		case TX4927_CCFG_DIVMODE_8:
+			txx9_gbus_clock = cpuclk / 2; break;
+		case TX4927_CCFG_DIVMODE_2_5:
+		case TX4927_CCFG_DIVMODE_10:
+			txx9_gbus_clock = cpuclk * 2 / 5; break;
+		case TX4927_CCFG_DIVMODE_3:
+		case TX4927_CCFG_DIVMODE_12:
+			txx9_gbus_clock = cpuclk / 3; break;
+		case TX4927_CCFG_DIVMODE_4:
+		case TX4927_CCFG_DIVMODE_16:
+			txx9_gbus_clock = cpuclk / 4; break;
+		}
+		switch (divmode) {
+		case TX4927_CCFG_DIVMODE_8:
+		case TX4927_CCFG_DIVMODE_10:
+		case TX4927_CCFG_DIVMODE_12:
+		case TX4927_CCFG_DIVMODE_16:
+			txx9_master_clock = txx9_gbus_clock / 4; break;
+		default:
+			txx9_master_clock = txx9_gbus_clock;
+		}
+	}
+	/* change default value to udelay/mdelay take reasonable time */
+	loops_per_jiffy = txx9_cpu_clock / HZ / 2;
+
+	/* CCFG */
+	tx4927_wdr_init();
+	/* clear BusErrorOnWrite flag (W1C) */
+	tx4927_ccfg_set(TX4927_CCFG_BEOW);
+	/* enable Timeout BusError */
+	if (txx9_ccfg_toeon)
+		tx4927_ccfg_set(TX4927_CCFG_TOE);
+
+	/* DMA selection */
+	txx9_clear64(&tx4927_ccfgptr->pcfg, TX4927_PCFG_DMASEL_ALL);
+
+	/* Use external clock for external arbiter */
+	if (!(____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_PCIARB))
+		txx9_clear64(&tx4927_ccfgptr->pcfg, TX4927_PCFG_PCICLKEN_ALL);
+
+	pr_info("%s -- %dMHz(M%dMHz) CRIR:%08x CCFG:%llx PCFG:%llx\n",
+		txx9_pcode_str, (cpuclk + 500000) / 1000000,
+		(txx9_master_clock + 500000) / 1000000,
+		(__u32)____raw_readq(&tx4927_ccfgptr->crir),
+		____raw_readq(&tx4927_ccfgptr->ccfg),
+		____raw_readq(&tx4927_ccfgptr->pcfg));
+
+	pr_info("%s SDRAMC --", txx9_pcode_str);
+	for (i = 0; i < 4; i++) {
+		__u64 cr = TX4927_SDRAMC_CR(i);
+		unsigned long base, size;
+		if (!((__u32)cr & 0x00000400))
+			continue;	/* disabled */
+		base = (unsigned long)(cr >> 49) << 21;
+		size = (((unsigned long)(cr >> 33) & 0x7fff) + 1) << 21;
+		pr_cont(" CR%d:%016llx", i, cr);
+		tx4927_sdram_resource[i].name = "SDRAM";
+		tx4927_sdram_resource[i].start = base;
+		tx4927_sdram_resource[i].end = base + size - 1;
+		tx4927_sdram_resource[i].flags = IORESOURCE_MEM;
+		request_resource(&iomem_resource, &tx4927_sdram_resource[i]);
+	}
+	pr_cont(" TR:%09llx\n", ____raw_readq(&tx4927_sdramcptr->tr));
+
+	/* TMR */
+	/* disable all timers */
+	for (i = 0; i < TX4927_NR_TMR; i++)
+		txx9_tmr_init(TX4927_TMR_REG(i) & 0xfffffffffULL);
+
+	/* PIO */
+	__raw_writel(0, &tx4927_pioptr->maskcpu);
+	__raw_writel(0, &tx4927_pioptr->maskext);
+
+	_machine_restart = tx4927_machine_restart;
+	board_be_init = tx4927_be_init;
+}
+
+void __init tx4927_time_init(unsigned int tmrnr)
+{
+	if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_TINTDIS)
+		txx9_clockevent_init(TX4927_TMR_REG(tmrnr) & 0xfffffffffULL,
+				     TXX9_IRQ_BASE + TX4927_IR_TMR(tmrnr),
+				     TXX9_IMCLK);
+}
+
+void __init tx4927_sio_init(unsigned int sclk, unsigned int cts_mask)
+{
+	int i;
+
+	for (i = 0; i < 2; i++)
+		txx9_sio_init(TX4927_SIO_REG(i) & 0xfffffffffULL,
+			      TXX9_IRQ_BASE + TX4927_IR_SIO(i),
+			      i, sclk, (1 << i) & cts_mask);
+}
+
+void __init tx4927_mtd_init(int ch)
+{
+	struct physmap_flash_data pdata = {
+		.width = TX4927_EBUSC_WIDTH(ch) / 8,
+	};
+	unsigned long start = txx9_ce_res[ch].start;
+	unsigned long size = txx9_ce_res[ch].end - start + 1;
+
+	if (!(TX4927_EBUSC_CR(ch) & 0x8))
+		return; /* disabled */
+	txx9_physmap_flash_init(ch, start, size, &pdata);
+}
+
+void __init tx4927_dmac_init(int memcpy_chan)
+{
+	struct txx9dmac_platform_data plat_data = {
+		.memcpy_chan = memcpy_chan,
+		.have_64bit_regs = true,
+	};
+
+	txx9_dmac_init(0, TX4927_DMA_REG & 0xfffffffffULL,
+		       TXX9_IRQ_BASE + TX4927_IR_DMA(0), &plat_data);
+}
+
+void __init tx4927_aclc_init(unsigned int dma_chan_out,
+			     unsigned int dma_chan_in)
+{
+	u64 pcfg = __raw_readq(&tx4927_ccfgptr->pcfg);
+	__u64 dmasel_mask = 0, dmasel = 0;
+	unsigned long flags;
+
+	if (!(pcfg & TX4927_PCFG_SEL2))
+		return;
+	/* setup DMASEL (playback:ACLC ch0, capture:ACLC ch1) */
+	switch (dma_chan_out) {
+	case 0:
+		dmasel_mask |= TX4927_PCFG_DMASEL0_MASK;
+		dmasel |= TX4927_PCFG_DMASEL0_ACL0;
+		break;
+	case 2:
+		dmasel_mask |= TX4927_PCFG_DMASEL2_MASK;
+		dmasel |= TX4927_PCFG_DMASEL2_ACL0;
+		break;
+	default:
+		return;
+	}
+	switch (dma_chan_in) {
+	case 1:
+		dmasel_mask |= TX4927_PCFG_DMASEL1_MASK;
+		dmasel |= TX4927_PCFG_DMASEL1_ACL1;
+		break;
+	case 3:
+		dmasel_mask |= TX4927_PCFG_DMASEL3_MASK;
+		dmasel |= TX4927_PCFG_DMASEL3_ACL1;
+		break;
+	default:
+		return;
+	}
+	local_irq_save(flags);
+	txx9_clear64(&tx4927_ccfgptr->pcfg, dmasel_mask);
+	txx9_set64(&tx4927_ccfgptr->pcfg, dmasel);
+	local_irq_restore(flags);
+	txx9_aclc_init(TX4927_ACLC_REG & 0xfffffffffULL,
+		       TXX9_IRQ_BASE + TX4927_IR_ACLC,
+		       0, dma_chan_out, dma_chan_in);
+}
+
+static void __init tx4927_stop_unused_modules(void)
+{
+	__u64 pcfg, rst = 0, ckd = 0;
+	char buf[128];
+
+	buf[0] = '\0';
+	local_irq_disable();
+	pcfg = ____raw_readq(&tx4927_ccfgptr->pcfg);
+	if (!(pcfg & TX4927_PCFG_SEL2)) {
+		rst |= TX4927_CLKCTR_ACLRST;
+		ckd |= TX4927_CLKCTR_ACLCKD;
+		strcat(buf, " ACLC");
+	}
+	if (rst | ckd) {
+		txx9_set64(&tx4927_ccfgptr->clkctr, rst);
+		txx9_set64(&tx4927_ccfgptr->clkctr, ckd);
+	}
+	local_irq_enable();
+	if (buf[0])
+		pr_info("%s: stop%s\n", txx9_pcode_str, buf);
+}
+
+static int __init tx4927_late_init(void)
+{
+	if (txx9_pcode != 0x4927)
+		return -ENODEV;
+	tx4927_stop_unused_modules();
+	return 0;
+}
+late_initcall(tx4927_late_init);
diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c
new file mode 100644
index 0000000..17395d5
--- /dev/null
+++ b/arch/mips/txx9/generic/setup_tx4938.c
@@ -0,0 +1,485 @@
+/*
+ * TX4938/4937 setup routines
+ * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
+ *	    and RBTX49xx patch from CELF patch archive.
+ *
+ * 2003-2005 (c) MontaVista Software, Inc.
+ * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/param.h>
+#include <linux/ptrace.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/txx9/ndfmc.h>
+#include <asm/reboot.h>
+#include <asm/traps.h>
+#include <asm/txx9irq.h>
+#include <asm/txx9tmr.h>
+#include <asm/txx9pio.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/dmac.h>
+#include <asm/txx9/tx4938.h>
+
+static void __init tx4938_wdr_init(void)
+{
+	/* report watchdog reset status */
+	if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST)
+		pr_warn("Watchdog reset detected at 0x%lx\n",
+			read_c0_errorepc());
+	/* clear WatchDogReset (W1C) */
+	tx4938_ccfg_set(TX4938_CCFG_WDRST);
+	/* do reset on watchdog */
+	tx4938_ccfg_set(TX4938_CCFG_WR);
+}
+
+void __init tx4938_wdt_init(void)
+{
+	txx9_wdt_init(TX4938_TMR_REG(2) & 0xfffffffffULL);
+}
+
+static void tx4938_machine_restart(char *command)
+{
+	local_irq_disable();
+	pr_emerg("Rebooting (with %s watchdog reset)...\n",
+		 (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDREXEN) ?
+		 "external" : "internal");
+	/* clear watchdog status */
+	tx4938_ccfg_set(TX4938_CCFG_WDRST);	/* W1C */
+	txx9_wdt_now(TX4938_TMR_REG(2) & 0xfffffffffULL);
+	while (!(____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST))
+		;
+	mdelay(10);
+	if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDREXEN) {
+		pr_emerg("Rebooting (with internal watchdog reset)...\n");
+		/* External WDRST failed.  Do internal watchdog reset */
+		tx4938_ccfg_clear(TX4938_CCFG_WDREXEN);
+	}
+	/* fallback */
+	(*_machine_halt)();
+}
+
+void show_registers(struct pt_regs *regs);
+static int tx4938_be_handler(struct pt_regs *regs, int is_fixup)
+{
+	int data = regs->cp0_cause & 4;
+	console_verbose();
+	pr_err("%cBE exception at %#lx\n", data ? 'D' : 'I', regs->cp0_epc);
+	pr_err("ccfg:%llx, toea:%llx\n",
+	       (unsigned long long)____raw_readq(&tx4938_ccfgptr->ccfg),
+	       (unsigned long long)____raw_readq(&tx4938_ccfgptr->toea));
+#ifdef CONFIG_PCI
+	tx4927_report_pcic_status();
+#endif
+	show_registers(regs);
+	panic("BusError!");
+}
+static void __init tx4938_be_init(void)
+{
+	board_be_handler = tx4938_be_handler;
+}
+
+static struct resource tx4938_sdram_resource[4];
+static struct resource tx4938_sram_resource;
+
+#define TX4938_SRAM_SIZE 0x800
+
+void __init tx4938_setup(void)
+{
+	int i;
+	__u32 divmode;
+	unsigned int cpuclk = 0;
+	u64 ccfg;
+
+	txx9_reg_res_init(TX4938_REV_PCODE(), TX4938_REG_BASE,
+			  TX4938_REG_SIZE);
+	set_c0_config(TX49_CONF_CWFON);
+
+	/* SDRAMC,EBUSC are configured by PROM */
+	for (i = 0; i < 8; i++) {
+		if (!(TX4938_EBUSC_CR(i) & 0x8))
+			continue;	/* disabled */
+		txx9_ce_res[i].start = (unsigned long)TX4938_EBUSC_BA(i);
+		txx9_ce_res[i].end =
+			txx9_ce_res[i].start + TX4938_EBUSC_SIZE(i) - 1;
+		request_resource(&iomem_resource, &txx9_ce_res[i]);
+	}
+
+	/* clocks */
+	ccfg = ____raw_readq(&tx4938_ccfgptr->ccfg);
+	if (txx9_master_clock) {
+		/* calculate gbus_clock and cpu_clock from master_clock */
+		divmode = (__u32)ccfg & TX4938_CCFG_DIVMODE_MASK;
+		switch (divmode) {
+		case TX4938_CCFG_DIVMODE_8:
+		case TX4938_CCFG_DIVMODE_10:
+		case TX4938_CCFG_DIVMODE_12:
+		case TX4938_CCFG_DIVMODE_16:
+		case TX4938_CCFG_DIVMODE_18:
+			txx9_gbus_clock = txx9_master_clock * 4; break;
+		default:
+			txx9_gbus_clock = txx9_master_clock;
+		}
+		switch (divmode) {
+		case TX4938_CCFG_DIVMODE_2:
+		case TX4938_CCFG_DIVMODE_8:
+			cpuclk = txx9_gbus_clock * 2; break;
+		case TX4938_CCFG_DIVMODE_2_5:
+		case TX4938_CCFG_DIVMODE_10:
+			cpuclk = txx9_gbus_clock * 5 / 2; break;
+		case TX4938_CCFG_DIVMODE_3:
+		case TX4938_CCFG_DIVMODE_12:
+			cpuclk = txx9_gbus_clock * 3; break;
+		case TX4938_CCFG_DIVMODE_4:
+		case TX4938_CCFG_DIVMODE_16:
+			cpuclk = txx9_gbus_clock * 4; break;
+		case TX4938_CCFG_DIVMODE_4_5:
+		case TX4938_CCFG_DIVMODE_18:
+			cpuclk = txx9_gbus_clock * 9 / 2; break;
+		}
+		txx9_cpu_clock = cpuclk;
+	} else {
+		if (txx9_cpu_clock == 0)
+			txx9_cpu_clock = 300000000;	/* 300MHz */
+		/* calculate gbus_clock and master_clock from cpu_clock */
+		cpuclk = txx9_cpu_clock;
+		divmode = (__u32)ccfg & TX4938_CCFG_DIVMODE_MASK;
+		switch (divmode) {
+		case TX4938_CCFG_DIVMODE_2:
+		case TX4938_CCFG_DIVMODE_8:
+			txx9_gbus_clock = cpuclk / 2; break;
+		case TX4938_CCFG_DIVMODE_2_5:
+		case TX4938_CCFG_DIVMODE_10:
+			txx9_gbus_clock = cpuclk * 2 / 5; break;
+		case TX4938_CCFG_DIVMODE_3:
+		case TX4938_CCFG_DIVMODE_12:
+			txx9_gbus_clock = cpuclk / 3; break;
+		case TX4938_CCFG_DIVMODE_4:
+		case TX4938_CCFG_DIVMODE_16:
+			txx9_gbus_clock = cpuclk / 4; break;
+		case TX4938_CCFG_DIVMODE_4_5:
+		case TX4938_CCFG_DIVMODE_18:
+			txx9_gbus_clock = cpuclk * 2 / 9; break;
+		}
+		switch (divmode) {
+		case TX4938_CCFG_DIVMODE_8:
+		case TX4938_CCFG_DIVMODE_10:
+		case TX4938_CCFG_DIVMODE_12:
+		case TX4938_CCFG_DIVMODE_16:
+		case TX4938_CCFG_DIVMODE_18:
+			txx9_master_clock = txx9_gbus_clock / 4; break;
+		default:
+			txx9_master_clock = txx9_gbus_clock;
+		}
+	}
+	/* change default value to udelay/mdelay take reasonable time */
+	loops_per_jiffy = txx9_cpu_clock / HZ / 2;
+
+	/* CCFG */
+	tx4938_wdr_init();
+	/* clear BusErrorOnWrite flag (W1C) */
+	tx4938_ccfg_set(TX4938_CCFG_BEOW);
+	/* enable Timeout BusError */
+	if (txx9_ccfg_toeon)
+		tx4938_ccfg_set(TX4938_CCFG_TOE);
+
+	/* DMA selection */
+	txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_DMASEL_ALL);
+
+	/* Use external clock for external arbiter */
+	if (!(____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCIARB))
+		txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_PCICLKEN_ALL);
+
+	pr_info("%s -- %dMHz(M%dMHz) CRIR:%08x CCFG:%llx PCFG:%llx\n",
+		txx9_pcode_str, (cpuclk + 500000) / 1000000,
+		(txx9_master_clock + 500000) / 1000000,
+		(__u32)____raw_readq(&tx4938_ccfgptr->crir),
+		____raw_readq(&tx4938_ccfgptr->ccfg),
+		____raw_readq(&tx4938_ccfgptr->pcfg));
+
+	pr_info("%s SDRAMC --", txx9_pcode_str);
+	for (i = 0; i < 4; i++) {
+		__u64 cr = TX4938_SDRAMC_CR(i);
+		unsigned long base, size;
+		if (!((__u32)cr & 0x00000400))
+			continue;	/* disabled */
+		base = (unsigned long)(cr >> 49) << 21;
+		size = (((unsigned long)(cr >> 33) & 0x7fff) + 1) << 21;
+		pr_cont(" CR%d:%016llx", i, cr);
+		tx4938_sdram_resource[i].name = "SDRAM";
+		tx4938_sdram_resource[i].start = base;
+		tx4938_sdram_resource[i].end = base + size - 1;
+		tx4938_sdram_resource[i].flags = IORESOURCE_MEM;
+		request_resource(&iomem_resource, &tx4938_sdram_resource[i]);
+	}
+	pr_cont(" TR:%09llx\n", ____raw_readq(&tx4938_sdramcptr->tr));
+
+	/* SRAM */
+	if (txx9_pcode == 0x4938 && ____raw_readq(&tx4938_sramcptr->cr) & 1) {
+		unsigned int size = TX4938_SRAM_SIZE;
+		tx4938_sram_resource.name = "SRAM";
+		tx4938_sram_resource.start =
+			(____raw_readq(&tx4938_sramcptr->cr) >> (39-11))
+			& ~(size - 1);
+		tx4938_sram_resource.end =
+			tx4938_sram_resource.start + TX4938_SRAM_SIZE - 1;
+		tx4938_sram_resource.flags = IORESOURCE_MEM;
+		request_resource(&iomem_resource, &tx4938_sram_resource);
+	}
+
+	/* TMR */
+	/* disable all timers */
+	for (i = 0; i < TX4938_NR_TMR; i++)
+		txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL);
+
+	/* PIO */
+	__raw_writel(0, &tx4938_pioptr->maskcpu);
+	__raw_writel(0, &tx4938_pioptr->maskext);
+
+	if (txx9_pcode == 0x4938) {
+		__u64 pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg);
+		/* set PCIC1 reset */
+		txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIC1RST);
+		if (pcfg & (TX4938_PCFG_ETH0_SEL | TX4938_PCFG_ETH1_SEL)) {
+			mdelay(1);	/* at least 128 cpu clock */
+			/* clear PCIC1 reset */
+			txx9_clear64(&tx4938_ccfgptr->clkctr,
+				     TX4938_CLKCTR_PCIC1RST);
+		} else {
+			pr_info("%s: stop PCIC1\n", txx9_pcode_str);
+			/* stop PCIC1 */
+			txx9_set64(&tx4938_ccfgptr->clkctr,
+				   TX4938_CLKCTR_PCIC1CKD);
+		}
+		if (!(pcfg & TX4938_PCFG_ETH0_SEL)) {
+			pr_info("%s: stop ETH0\n", txx9_pcode_str);
+			txx9_set64(&tx4938_ccfgptr->clkctr,
+				   TX4938_CLKCTR_ETH0RST);
+			txx9_set64(&tx4938_ccfgptr->clkctr,
+				   TX4938_CLKCTR_ETH0CKD);
+		}
+		if (!(pcfg & TX4938_PCFG_ETH1_SEL)) {
+			pr_info("%s: stop ETH1\n", txx9_pcode_str);
+			txx9_set64(&tx4938_ccfgptr->clkctr,
+				   TX4938_CLKCTR_ETH1RST);
+			txx9_set64(&tx4938_ccfgptr->clkctr,
+				   TX4938_CLKCTR_ETH1CKD);
+		}
+	}
+
+	_machine_restart = tx4938_machine_restart;
+	board_be_init = tx4938_be_init;
+}
+
+void __init tx4938_time_init(unsigned int tmrnr)
+{
+	if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_TINTDIS)
+		txx9_clockevent_init(TX4938_TMR_REG(tmrnr) & 0xfffffffffULL,
+				     TXX9_IRQ_BASE + TX4938_IR_TMR(tmrnr),
+				     TXX9_IMCLK);
+}
+
+void __init tx4938_sio_init(unsigned int sclk, unsigned int cts_mask)
+{
+	int i;
+	unsigned int ch_mask = 0;
+
+	if (__raw_readq(&tx4938_ccfgptr->pcfg) & TX4938_PCFG_ETH0_SEL)
+		ch_mask |= 1 << 1; /* disable SIO1 by PCFG setting */
+	for (i = 0; i < 2; i++) {
+		if ((1 << i) & ch_mask)
+			continue;
+		txx9_sio_init(TX4938_SIO_REG(i) & 0xfffffffffULL,
+			      TXX9_IRQ_BASE + TX4938_IR_SIO(i),
+			      i, sclk, (1 << i) & cts_mask);
+	}
+}
+
+void __init tx4938_spi_init(int busid)
+{
+	txx9_spi_init(busid, TX4938_SPI_REG & 0xfffffffffULL,
+		      TXX9_IRQ_BASE + TX4938_IR_SPI);
+}
+
+void __init tx4938_ethaddr_init(unsigned char *addr0, unsigned char *addr1)
+{
+	u64 pcfg = __raw_readq(&tx4938_ccfgptr->pcfg);
+
+	if (addr0 && (pcfg & TX4938_PCFG_ETH0_SEL))
+		txx9_ethaddr_init(TXX9_IRQ_BASE + TX4938_IR_ETH0, addr0);
+	if (addr1 && (pcfg & TX4938_PCFG_ETH1_SEL))
+		txx9_ethaddr_init(TXX9_IRQ_BASE + TX4938_IR_ETH1, addr1);
+}
+
+void __init tx4938_mtd_init(int ch)
+{
+	struct physmap_flash_data pdata = {
+		.width = TX4938_EBUSC_WIDTH(ch) / 8,
+	};
+	unsigned long start = txx9_ce_res[ch].start;
+	unsigned long size = txx9_ce_res[ch].end - start + 1;
+
+	if (!(TX4938_EBUSC_CR(ch) & 0x8))
+		return; /* disabled */
+	txx9_physmap_flash_init(ch, start, size, &pdata);
+}
+
+void __init tx4938_ata_init(unsigned int irq, unsigned int shift, int tune)
+{
+	struct platform_device *pdev;
+	struct resource res[] = {
+		{
+			/* .start and .end are filled in later */
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	struct tx4938ide_platform_info pdata = {
+		.ioport_shift = shift,
+		/*
+		 * The IDE driver should not change bus timings if other ISA
+		 * devices existed.
+		 */
+		.gbus_clock = tune ? txx9_gbus_clock : 0,
+	};
+	u64 ebccr;
+	int i;
+
+	if ((__raw_readq(&tx4938_ccfgptr->pcfg) &
+	     (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL))
+	    != TX4938_PCFG_ATA_SEL)
+		return;
+	for (i = 0; i < 8; i++) {
+		/* check EBCCRn.ISA, EBCCRn.BSZ, EBCCRn.ME */
+		ebccr = __raw_readq(&tx4938_ebuscptr->cr[i]);
+		if ((ebccr & 0x00f00008) == 0x00e00008)
+			break;
+	}
+	if (i == 8)
+		return;
+	pdata.ebus_ch = i;
+	res[0].start = ((ebccr >> 48) << 20) + 0x10000;
+	res[0].end = res[0].start + 0x20000 - 1;
+	pdev = platform_device_alloc("tx4938ide", -1);
+	if (!pdev ||
+	    platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) ||
+	    platform_device_add_data(pdev, &pdata, sizeof(pdata)) ||
+	    platform_device_add(pdev))
+		platform_device_put(pdev);
+}
+
+void __init tx4938_ndfmc_init(unsigned int hold, unsigned int spw)
+{
+	struct txx9ndfmc_platform_data plat_data = {
+		.shift = 1,
+		.gbus_clock = txx9_gbus_clock,
+		.hold = hold,
+		.spw = spw,
+		.ch_mask = 1,
+	};
+	unsigned long baseaddr = TX4938_NDFMC_REG & 0xfffffffffULL;
+
+#ifdef __BIG_ENDIAN
+	baseaddr += 4;
+#endif
+	if ((__raw_readq(&tx4938_ccfgptr->pcfg) &
+	     (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL)) ==
+	    TX4938_PCFG_NDF_SEL)
+		txx9_ndfmc_init(baseaddr, &plat_data);
+}
+
+void __init tx4938_dmac_init(int memcpy_chan0, int memcpy_chan1)
+{
+	struct txx9dmac_platform_data plat_data = {
+		.have_64bit_regs = true,
+	};
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		plat_data.memcpy_chan = i ? memcpy_chan1 : memcpy_chan0;
+		txx9_dmac_init(i, TX4938_DMA_REG(i) & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4938_IR_DMA(i, 0),
+			       &plat_data);
+	}
+}
+
+void __init tx4938_aclc_init(void)
+{
+	u64 pcfg = __raw_readq(&tx4938_ccfgptr->pcfg);
+
+	if ((pcfg & TX4938_PCFG_SEL2) &&
+	    !(pcfg & TX4938_PCFG_ETH0_SEL))
+		txx9_aclc_init(TX4938_ACLC_REG & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4938_IR_ACLC,
+			       1, 0, 1);
+}
+
+void __init tx4938_sramc_init(void)
+{
+	if (tx4938_sram_resource.start)
+		txx9_sramc_init(&tx4938_sram_resource);
+}
+
+static void __init tx4938_stop_unused_modules(void)
+{
+	__u64 pcfg, rst = 0, ckd = 0;
+	char buf[128];
+
+	buf[0] = '\0';
+	local_irq_disable();
+	pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg);
+	switch (txx9_pcode) {
+	case 0x4937:
+		if (!(pcfg & TX4938_PCFG_SEL2)) {
+			rst |= TX4938_CLKCTR_ACLRST;
+			ckd |= TX4938_CLKCTR_ACLCKD;
+			strcat(buf, " ACLC");
+		}
+		break;
+	case 0x4938:
+		if (!(pcfg & TX4938_PCFG_SEL2) ||
+		    (pcfg & TX4938_PCFG_ETH0_SEL)) {
+			rst |= TX4938_CLKCTR_ACLRST;
+			ckd |= TX4938_CLKCTR_ACLCKD;
+			strcat(buf, " ACLC");
+		}
+		if ((pcfg &
+		     (TX4938_PCFG_ATA_SEL | TX4938_PCFG_ISA_SEL |
+		      TX4938_PCFG_NDF_SEL))
+		    != TX4938_PCFG_NDF_SEL) {
+			rst |= TX4938_CLKCTR_NDFRST;
+			ckd |= TX4938_CLKCTR_NDFCKD;
+			strcat(buf, " NDFMC");
+		}
+		if (!(pcfg & TX4938_PCFG_SPI_SEL)) {
+			rst |= TX4938_CLKCTR_SPIRST;
+			ckd |= TX4938_CLKCTR_SPICKD;
+			strcat(buf, " SPI");
+		}
+		break;
+	}
+	if (rst | ckd) {
+		txx9_set64(&tx4938_ccfgptr->clkctr, rst);
+		txx9_set64(&tx4938_ccfgptr->clkctr, ckd);
+	}
+	local_irq_enable();
+	if (buf[0])
+		pr_info("%s: stop%s\n", txx9_pcode_str, buf);
+}
+
+static int __init tx4938_late_init(void)
+{
+	if (txx9_pcode != 0x4937 && txx9_pcode != 0x4938)
+		return -ENODEV;
+	tx4938_stop_unused_modules();
+	return 0;
+}
+late_initcall(tx4938_late_init);
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c
new file mode 100644
index 0000000..360c388
--- /dev/null
+++ b/arch/mips/txx9/generic/setup_tx4939.c
@@ -0,0 +1,585 @@
+/*
+ * TX4939 setup routines
+ * Based on linux/arch/mips/txx9/generic/setup_tx4938.c,
+ *	    and RBTX49xx patch from CELF patch archive.
+ *
+ * 2003-2005 (c) MontaVista Software, Inc.
+ * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/notifier.h>
+#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/param.h>
+#include <linux/ptrace.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/txx9/ndfmc.h>
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+#include <asm/traps.h>
+#include <asm/txx9irq.h>
+#include <asm/txx9tmr.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/dmac.h>
+#include <asm/txx9/tx4939.h>
+
+static void __init tx4939_wdr_init(void)
+{
+	/* report watchdog reset status */
+	if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST)
+		pr_warn("Watchdog reset detected at 0x%lx\n",
+			read_c0_errorepc());
+	/* clear WatchDogReset (W1C) */
+	tx4939_ccfg_set(TX4939_CCFG_WDRST);
+	/* do reset on watchdog */
+	tx4939_ccfg_set(TX4939_CCFG_WR);
+}
+
+void __init tx4939_wdt_init(void)
+{
+	txx9_wdt_init(TX4939_TMR_REG(2) & 0xfffffffffULL);
+}
+
+static void tx4939_machine_restart(char *command)
+{
+	local_irq_disable();
+	pr_emerg("Rebooting (with %s watchdog reset)...\n",
+		 (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDREXEN) ?
+		 "external" : "internal");
+	/* clear watchdog status */
+	tx4939_ccfg_set(TX4939_CCFG_WDRST);	/* W1C */
+	txx9_wdt_now(TX4939_TMR_REG(2) & 0xfffffffffULL);
+	while (!(____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST))
+		;
+	mdelay(10);
+	if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDREXEN) {
+		pr_emerg("Rebooting (with internal watchdog reset)...\n");
+		/* External WDRST failed.  Do internal watchdog reset */
+		tx4939_ccfg_clear(TX4939_CCFG_WDREXEN);
+	}
+	/* fallback */
+	(*_machine_halt)();
+}
+
+void show_registers(struct pt_regs *regs);
+static int tx4939_be_handler(struct pt_regs *regs, int is_fixup)
+{
+	int data = regs->cp0_cause & 4;
+	console_verbose();
+	pr_err("%cBE exception at %#lx\n",
+	       data ? 'D' : 'I', regs->cp0_epc);
+	pr_err("ccfg:%llx, toea:%llx\n",
+	       (unsigned long long)____raw_readq(&tx4939_ccfgptr->ccfg),
+	       (unsigned long long)____raw_readq(&tx4939_ccfgptr->toea));
+#ifdef CONFIG_PCI
+	tx4927_report_pcic_status();
+#endif
+	show_registers(regs);
+	panic("BusError!");
+}
+static void __init tx4939_be_init(void)
+{
+	board_be_handler = tx4939_be_handler;
+}
+
+static struct resource tx4939_sdram_resource[4];
+static struct resource tx4939_sram_resource;
+#define TX4939_SRAM_SIZE 0x800
+
+void __init tx4939_add_memory_regions(void)
+{
+	int i;
+	unsigned long start, size;
+	u64 win;
+
+	for (i = 0; i < 4; i++) {
+		if (!((__u32)____raw_readq(&tx4939_ddrcptr->winen) & (1 << i)))
+			continue;
+		win = ____raw_readq(&tx4939_ddrcptr->win[i]);
+		start = (unsigned long)(win >> 48);
+		size = (((unsigned long)(win >> 32) & 0xffff) + 1) - start;
+		add_memory_region(start << 20, size << 20, BOOT_MEM_RAM);
+	}
+}
+
+void __init tx4939_setup(void)
+{
+	int i;
+	__u32 divmode;
+	__u64 pcfg;
+	unsigned int cpuclk = 0;
+
+	txx9_reg_res_init(TX4939_REV_PCODE(), TX4939_REG_BASE,
+			  TX4939_REG_SIZE);
+	set_c0_config(TX49_CONF_CWFON);
+
+	/* SDRAMC,EBUSC are configured by PROM */
+	for (i = 0; i < 4; i++) {
+		if (!(TX4939_EBUSC_CR(i) & 0x8))
+			continue;	/* disabled */
+		txx9_ce_res[i].start = (unsigned long)TX4939_EBUSC_BA(i);
+		txx9_ce_res[i].end =
+			txx9_ce_res[i].start + TX4939_EBUSC_SIZE(i) - 1;
+		request_resource(&iomem_resource, &txx9_ce_res[i]);
+	}
+
+	/* clocks */
+	if (txx9_master_clock) {
+		/* calculate cpu_clock from master_clock */
+		divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) &
+			TX4939_CCFG_MULCLK_MASK;
+		cpuclk = txx9_master_clock * 20 / 2;
+		switch (divmode) {
+		case TX4939_CCFG_MULCLK_8:
+			cpuclk = cpuclk / 3 * 4 /* / 6 *  8 */; break;
+		case TX4939_CCFG_MULCLK_9:
+			cpuclk = cpuclk / 2 * 3 /* / 6 *  9 */; break;
+		case TX4939_CCFG_MULCLK_10:
+			cpuclk = cpuclk / 3 * 5 /* / 6 * 10 */; break;
+		case TX4939_CCFG_MULCLK_11:
+			cpuclk = cpuclk / 6 * 11; break;
+		case TX4939_CCFG_MULCLK_12:
+			cpuclk = cpuclk * 2 /* / 6 * 12 */; break;
+		case TX4939_CCFG_MULCLK_13:
+			cpuclk = cpuclk / 6 * 13; break;
+		case TX4939_CCFG_MULCLK_14:
+			cpuclk = cpuclk / 3 * 7 /* / 6 * 14 */; break;
+		case TX4939_CCFG_MULCLK_15:
+			cpuclk = cpuclk / 2 * 5 /* / 6 * 15 */; break;
+		}
+		txx9_cpu_clock = cpuclk;
+	} else {
+		if (txx9_cpu_clock == 0)
+			txx9_cpu_clock = 400000000;	/* 400MHz */
+		/* calculate master_clock from cpu_clock */
+		cpuclk = txx9_cpu_clock;
+		divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) &
+			TX4939_CCFG_MULCLK_MASK;
+		switch (divmode) {
+		case TX4939_CCFG_MULCLK_8:
+			txx9_master_clock = cpuclk * 6 / 8; break;
+		case TX4939_CCFG_MULCLK_9:
+			txx9_master_clock = cpuclk * 6 / 9; break;
+		case TX4939_CCFG_MULCLK_10:
+			txx9_master_clock = cpuclk * 6 / 10; break;
+		case TX4939_CCFG_MULCLK_11:
+			txx9_master_clock = cpuclk * 6 / 11; break;
+		case TX4939_CCFG_MULCLK_12:
+			txx9_master_clock = cpuclk * 6 / 12; break;
+		case TX4939_CCFG_MULCLK_13:
+			txx9_master_clock = cpuclk * 6 / 13; break;
+		case TX4939_CCFG_MULCLK_14:
+			txx9_master_clock = cpuclk * 6 / 14; break;
+		case TX4939_CCFG_MULCLK_15:
+			txx9_master_clock = cpuclk * 6 / 15; break;
+		}
+		txx9_master_clock /= 10; /* * 2 / 20 */
+	}
+	/* calculate gbus_clock from cpu_clock */
+	divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) &
+		TX4939_CCFG_YDIVMODE_MASK;
+	txx9_gbus_clock = txx9_cpu_clock;
+	switch (divmode) {
+	case TX4939_CCFG_YDIVMODE_2:
+		txx9_gbus_clock /= 2; break;
+	case TX4939_CCFG_YDIVMODE_3:
+		txx9_gbus_clock /= 3; break;
+	case TX4939_CCFG_YDIVMODE_5:
+		txx9_gbus_clock /= 5; break;
+	case TX4939_CCFG_YDIVMODE_6:
+		txx9_gbus_clock /= 6; break;
+	}
+	/* change default value to udelay/mdelay take reasonable time */
+	loops_per_jiffy = txx9_cpu_clock / HZ / 2;
+
+	/* CCFG */
+	tx4939_wdr_init();
+	/* clear BusErrorOnWrite flag (W1C) */
+	tx4939_ccfg_set(TX4939_CCFG_WDRST | TX4939_CCFG_BEOW);
+	/* enable Timeout BusError */
+	if (txx9_ccfg_toeon)
+		tx4939_ccfg_set(TX4939_CCFG_TOE);
+
+	/* DMA selection */
+	txx9_clear64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_DMASEL_ALL);
+
+	/* Use external clock for external arbiter */
+	if (!(____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCIARB))
+		txx9_clear64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_PCICLKEN_ALL);
+
+	pr_info("%s -- %dMHz(M%dMHz,G%dMHz) CRIR:%08x CCFG:%llx PCFG:%llx\n",
+		txx9_pcode_str,
+		(cpuclk + 500000) / 1000000,
+		(txx9_master_clock + 500000) / 1000000,
+		(txx9_gbus_clock + 500000) / 1000000,
+		(__u32)____raw_readq(&tx4939_ccfgptr->crir),
+		____raw_readq(&tx4939_ccfgptr->ccfg),
+		____raw_readq(&tx4939_ccfgptr->pcfg));
+
+	pr_info("%s DDRC -- EN:%08x", txx9_pcode_str,
+		(__u32)____raw_readq(&tx4939_ddrcptr->winen));
+	for (i = 0; i < 4; i++) {
+		__u64 win = ____raw_readq(&tx4939_ddrcptr->win[i]);
+		if (!((__u32)____raw_readq(&tx4939_ddrcptr->winen) & (1 << i)))
+			continue;	/* disabled */
+		pr_cont(" #%d:%016llx", i, win);
+		tx4939_sdram_resource[i].name = "DDR SDRAM";
+		tx4939_sdram_resource[i].start =
+			(unsigned long)(win >> 48) << 20;
+		tx4939_sdram_resource[i].end =
+			((((unsigned long)(win >> 32) & 0xffff) + 1) <<
+			 20) - 1;
+		tx4939_sdram_resource[i].flags = IORESOURCE_MEM;
+		request_resource(&iomem_resource, &tx4939_sdram_resource[i]);
+	}
+	pr_cont("\n");
+
+	/* SRAM */
+	if (____raw_readq(&tx4939_sramcptr->cr) & 1) {
+		unsigned int size = TX4939_SRAM_SIZE;
+		tx4939_sram_resource.name = "SRAM";
+		tx4939_sram_resource.start =
+			(____raw_readq(&tx4939_sramcptr->cr) >> (39-11))
+			& ~(size - 1);
+		tx4939_sram_resource.end =
+			tx4939_sram_resource.start + TX4939_SRAM_SIZE - 1;
+		tx4939_sram_resource.flags = IORESOURCE_MEM;
+		request_resource(&iomem_resource, &tx4939_sram_resource);
+	}
+
+	/* TMR */
+	/* disable all timers */
+	for (i = 0; i < TX4939_NR_TMR; i++)
+		txx9_tmr_init(TX4939_TMR_REG(i) & 0xfffffffffULL);
+
+	/* set PCIC1 reset (required to prevent hangup on BIST) */
+	txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST);
+	pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg);
+	if (pcfg & (TX4939_PCFG_ET0MODE | TX4939_PCFG_ET1MODE)) {
+		mdelay(1);	/* at least 128 cpu clock */
+		/* clear PCIC1 reset */
+		txx9_clear64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST);
+	} else {
+		pr_info("%s: stop PCIC1\n", txx9_pcode_str);
+		/* stop PCIC1 */
+		txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1CKD);
+	}
+	if (!(pcfg & TX4939_PCFG_ET0MODE)) {
+		pr_info("%s: stop ETH0\n", txx9_pcode_str);
+		txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH0RST);
+		txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH0CKD);
+	}
+	if (!(pcfg & TX4939_PCFG_ET1MODE)) {
+		pr_info("%s: stop ETH1\n", txx9_pcode_str);
+		txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH1RST);
+		txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH1CKD);
+	}
+
+	_machine_restart = tx4939_machine_restart;
+	board_be_init = tx4939_be_init;
+}
+
+void __init tx4939_time_init(unsigned int tmrnr)
+{
+	if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_TINTDIS)
+		txx9_clockevent_init(TX4939_TMR_REG(tmrnr) & 0xfffffffffULL,
+				     TXX9_IRQ_BASE + TX4939_IR_TMR(tmrnr),
+				     TXX9_IMCLK);
+}
+
+void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask)
+{
+	int i;
+	unsigned int ch_mask = 0;
+	__u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg);
+
+	cts_mask |= ~1; /* only SIO0 have RTS/CTS */
+	if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO0)
+		cts_mask |= 1 << 0; /* disable SIO0 RTS/CTS by PCFG setting */
+	if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO2)
+		ch_mask |= 1 << 2; /* disable SIO2 by PCFG setting */
+	if (pcfg & TX4939_PCFG_SIO3MODE)
+		ch_mask |= 1 << 3; /* disable SIO3 by PCFG setting */
+	for (i = 0; i < 4; i++) {
+		if ((1 << i) & ch_mask)
+			continue;
+		txx9_sio_init(TX4939_SIO_REG(i) & 0xfffffffffULL,
+			      TXX9_IRQ_BASE + TX4939_IR_SIO(i),
+			      i, sclk, (1 << i) & cts_mask);
+	}
+}
+
+#if IS_ENABLED(CONFIG_TC35815)
+static u32 tx4939_get_eth_speed(struct net_device *dev)
+{
+	struct ethtool_link_ksettings cmd;
+
+	if (__ethtool_get_link_ksettings(dev, &cmd))
+		return 100;	/* default 100Mbps */
+
+	return cmd.base.speed;
+}
+
+static int tx4939_netdev_event(struct notifier_block *this,
+			       unsigned long event,
+			       void *ptr)
+{
+	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+
+	if (event == NETDEV_CHANGE && netif_carrier_ok(dev)) {
+		__u64 bit = 0;
+		if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(0))
+			bit = TX4939_PCFG_SPEED0;
+		else if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(1))
+			bit = TX4939_PCFG_SPEED1;
+		if (bit) {
+			if (tx4939_get_eth_speed(dev) == 100)
+				txx9_set64(&tx4939_ccfgptr->pcfg, bit);
+			else
+				txx9_clear64(&tx4939_ccfgptr->pcfg, bit);
+		}
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block tx4939_netdev_notifier = {
+	.notifier_call = tx4939_netdev_event,
+	.priority = 1,
+};
+
+void __init tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1)
+{
+	u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg);
+
+	if (addr0 && (pcfg & TX4939_PCFG_ET0MODE))
+		txx9_ethaddr_init(TXX9_IRQ_BASE + TX4939_IR_ETH(0), addr0);
+	if (addr1 && (pcfg & TX4939_PCFG_ET1MODE))
+		txx9_ethaddr_init(TXX9_IRQ_BASE + TX4939_IR_ETH(1), addr1);
+	register_netdevice_notifier(&tx4939_netdev_notifier);
+}
+#else
+void __init tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1)
+{
+}
+#endif
+
+void __init tx4939_mtd_init(int ch)
+{
+	struct physmap_flash_data pdata = {
+		.width = TX4939_EBUSC_WIDTH(ch) / 8,
+	};
+	unsigned long start = txx9_ce_res[ch].start;
+	unsigned long size = txx9_ce_res[ch].end - start + 1;
+
+	if (!(TX4939_EBUSC_CR(ch) & 0x8))
+		return; /* disabled */
+	txx9_physmap_flash_init(ch, start, size, &pdata);
+}
+
+#define TX4939_ATA_REG_PHYS(ch) (TX4939_ATA_REG(ch) & 0xfffffffffULL)
+void __init tx4939_ata_init(void)
+{
+	static struct resource ata0_res[] = {
+		{
+			.start = TX4939_ATA_REG_PHYS(0),
+			.end = TX4939_ATA_REG_PHYS(0) + 0x1000 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = TXX9_IRQ_BASE + TX4939_IR_ATA(0),
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	static struct resource ata1_res[] = {
+		{
+			.start = TX4939_ATA_REG_PHYS(1),
+			.end = TX4939_ATA_REG_PHYS(1) + 0x1000 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = TXX9_IRQ_BASE + TX4939_IR_ATA(1),
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	static struct platform_device ata0_dev = {
+		.name = "tx4939ide",
+		.id = 0,
+		.num_resources = ARRAY_SIZE(ata0_res),
+		.resource = ata0_res,
+	};
+	static struct platform_device ata1_dev = {
+		.name = "tx4939ide",
+		.id = 1,
+		.num_resources = ARRAY_SIZE(ata1_res),
+		.resource = ata1_res,
+	};
+	__u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg);
+
+	if (pcfg & TX4939_PCFG_ATA0MODE)
+		platform_device_register(&ata0_dev);
+	if ((pcfg & (TX4939_PCFG_ATA1MODE |
+		     TX4939_PCFG_ET1MODE |
+		     TX4939_PCFG_ET0MODE)) == TX4939_PCFG_ATA1MODE)
+		platform_device_register(&ata1_dev);
+}
+
+void __init tx4939_rtc_init(void)
+{
+	static struct resource res[] = {
+		{
+			.start = TX4939_RTC_REG & 0xfffffffffULL,
+			.end = (TX4939_RTC_REG & 0xfffffffffULL) + 0x100 - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = TXX9_IRQ_BASE + TX4939_IR_RTC,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	static struct platform_device rtc_dev = {
+		.name = "tx4939rtc",
+		.id = -1,
+		.num_resources = ARRAY_SIZE(res),
+		.resource = res,
+	};
+
+	platform_device_register(&rtc_dev);
+}
+
+void __init tx4939_ndfmc_init(unsigned int hold, unsigned int spw,
+			      unsigned char ch_mask, unsigned char wide_mask)
+{
+	struct txx9ndfmc_platform_data plat_data = {
+		.shift = 1,
+		.gbus_clock = txx9_gbus_clock,
+		.hold = hold,
+		.spw = spw,
+		.flags = NDFMC_PLAT_FLAG_NO_RSTR | NDFMC_PLAT_FLAG_HOLDADD |
+			 NDFMC_PLAT_FLAG_DUMMYWRITE,
+		.ch_mask = ch_mask,
+		.wide_mask = wide_mask,
+	};
+	txx9_ndfmc_init(TX4939_NDFMC_REG & 0xfffffffffULL, &plat_data);
+}
+
+void __init tx4939_dmac_init(int memcpy_chan0, int memcpy_chan1)
+{
+	struct txx9dmac_platform_data plat_data = {
+		.have_64bit_regs = true,
+	};
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		plat_data.memcpy_chan = i ? memcpy_chan1 : memcpy_chan0;
+		txx9_dmac_init(i, TX4939_DMA_REG(i) & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4939_IR_DMA(i, 0),
+			       &plat_data);
+	}
+}
+
+void __init tx4939_aclc_init(void)
+{
+	u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg);
+
+	if ((pcfg & TX4939_PCFG_I2SMODE_MASK) == TX4939_PCFG_I2SMODE_ACLC)
+		txx9_aclc_init(TX4939_ACLC_REG & 0xfffffffffULL,
+			       TXX9_IRQ_BASE + TX4939_IR_ACLC, 1, 0, 1);
+}
+
+void __init tx4939_sramc_init(void)
+{
+	if (tx4939_sram_resource.start)
+		txx9_sramc_init(&tx4939_sram_resource);
+}
+
+void __init tx4939_rng_init(void)
+{
+	static struct resource res = {
+		.start = TX4939_RNG_REG & 0xfffffffffULL,
+		.end = (TX4939_RNG_REG & 0xfffffffffULL) + 0x30 - 1,
+		.flags = IORESOURCE_MEM,
+	};
+	static struct platform_device pdev = {
+		.name = "tx4939-rng",
+		.id = -1,
+		.num_resources = 1,
+		.resource = &res,
+	};
+
+	platform_device_register(&pdev);
+}
+
+static void __init tx4939_stop_unused_modules(void)
+{
+	__u64 pcfg, rst = 0, ckd = 0;
+	char buf[128];
+
+	buf[0] = '\0';
+	local_irq_disable();
+	pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg);
+	if ((pcfg & TX4939_PCFG_I2SMODE_MASK) !=
+	    TX4939_PCFG_I2SMODE_ACLC) {
+		rst |= TX4939_CLKCTR_ACLRST;
+		ckd |= TX4939_CLKCTR_ACLCKD;
+		strcat(buf, " ACLC");
+	}
+	if ((pcfg & TX4939_PCFG_I2SMODE_MASK) !=
+	    TX4939_PCFG_I2SMODE_I2S &&
+	    (pcfg & TX4939_PCFG_I2SMODE_MASK) !=
+	    TX4939_PCFG_I2SMODE_I2S_ALT) {
+		rst |= TX4939_CLKCTR_I2SRST;
+		ckd |= TX4939_CLKCTR_I2SCKD;
+		strcat(buf, " I2S");
+	}
+	if (!(pcfg & TX4939_PCFG_ATA0MODE)) {
+		rst |= TX4939_CLKCTR_ATA0RST;
+		ckd |= TX4939_CLKCTR_ATA0CKD;
+		strcat(buf, " ATA0");
+	}
+	if (!(pcfg & TX4939_PCFG_ATA1MODE)) {
+		rst |= TX4939_CLKCTR_ATA1RST;
+		ckd |= TX4939_CLKCTR_ATA1CKD;
+		strcat(buf, " ATA1");
+	}
+	if (pcfg & TX4939_PCFG_SPIMODE) {
+		rst |= TX4939_CLKCTR_SPIRST;
+		ckd |= TX4939_CLKCTR_SPICKD;
+		strcat(buf, " SPI");
+	}
+	if (!(pcfg & (TX4939_PCFG_VSSMODE | TX4939_PCFG_VPSMODE))) {
+		rst |= TX4939_CLKCTR_VPCRST;
+		ckd |= TX4939_CLKCTR_VPCCKD;
+		strcat(buf, " VPC");
+	}
+	if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO2) {
+		rst |= TX4939_CLKCTR_SIO2RST;
+		ckd |= TX4939_CLKCTR_SIO2CKD;
+		strcat(buf, " SIO2");
+	}
+	if (pcfg & TX4939_PCFG_SIO3MODE) {
+		rst |= TX4939_CLKCTR_SIO3RST;
+		ckd |= TX4939_CLKCTR_SIO3CKD;
+		strcat(buf, " SIO3");
+	}
+	if (rst | ckd) {
+		txx9_set64(&tx4939_ccfgptr->clkctr, rst);
+		txx9_set64(&tx4939_ccfgptr->clkctr, ckd);
+	}
+	local_irq_enable();
+	if (buf[0])
+		pr_info("%s: stop%s\n", txx9_pcode_str, buf);
+}
+
+static int __init tx4939_late_init(void)
+{
+	if (txx9_pcode != 0x4939)
+		return -ENODEV;
+	tx4939_stop_unused_modules();
+	return 0;
+}
+late_initcall(tx4939_late_init);
diff --git a/arch/mips/txx9/generic/smsc_fdc37m81x.c b/arch/mips/txx9/generic/smsc_fdc37m81x.c
new file mode 100644
index 0000000..40f4098
--- /dev/null
+++ b/arch/mips/txx9/generic/smsc_fdc37m81x.c
@@ -0,0 +1,169 @@
+/*
+ * Interface for smsc fdc48m81x Super IO chip
+ *
+ * Author: MontaVista Software, Inc. source@mvista.com
+ *
+ * 2001-2003 (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.
+ *
+ * Copyright 2004 (c) MontaVista Software, Inc.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/txx9/smsc_fdc37m81x.h>
+
+/* Common Registers */
+#define SMSC_FDC37M81X_CONFIG_INDEX  0x00
+#define SMSC_FDC37M81X_CONFIG_DATA   0x01
+#define SMSC_FDC37M81X_CONF	     0x02
+#define SMSC_FDC37M81X_INDEX	     0x03
+#define SMSC_FDC37M81X_DNUM	     0x07
+#define SMSC_FDC37M81X_DID	     0x20
+#define SMSC_FDC37M81X_DREV	     0x21
+#define SMSC_FDC37M81X_PCNT	     0x22
+#define SMSC_FDC37M81X_PMGT	     0x23
+#define SMSC_FDC37M81X_OSC	     0x24
+#define SMSC_FDC37M81X_CONFPA0	     0x26
+#define SMSC_FDC37M81X_CONFPA1	     0x27
+#define SMSC_FDC37M81X_TEST4	     0x2B
+#define SMSC_FDC37M81X_TEST5	     0x2C
+#define SMSC_FDC37M81X_TEST1	     0x2D
+#define SMSC_FDC37M81X_TEST2	     0x2E
+#define SMSC_FDC37M81X_TEST3	     0x2F
+
+/* Logical device numbers */
+#define SMSC_FDC37M81X_FDD	     0x00
+#define SMSC_FDC37M81X_SERIAL1	     0x04
+#define SMSC_FDC37M81X_SERIAL2	     0x05
+#define SMSC_FDC37M81X_KBD	     0x07
+
+/* Logical device Config Registers */
+#define SMSC_FDC37M81X_ACTIVE	     0x30
+#define SMSC_FDC37M81X_BASEADDR0     0x60
+#define SMSC_FDC37M81X_BASEADDR1     0x61
+#define SMSC_FDC37M81X_INT	     0x70
+#define SMSC_FDC37M81X_INT2	     0x72
+#define SMSC_FDC37M81X_MODE	     0xF0
+
+/* Chip Config Values */
+#define SMSC_FDC37M81X_CONFIG_ENTER  0x55
+#define SMSC_FDC37M81X_CONFIG_EXIT   0xaa
+#define SMSC_FDC37M81X_CHIP_ID	     0x4d
+
+static unsigned long g_smsc_fdc37m81x_base;
+
+static inline unsigned char smsc_fdc37m81x_rd(unsigned char index)
+{
+	outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX);
+
+	return inb(g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA);
+}
+
+static inline void smsc_dc37m81x_wr(unsigned char index, unsigned char data)
+{
+	outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX);
+	outb(data, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA);
+}
+
+void smsc_fdc37m81x_config_beg(void)
+{
+	if (g_smsc_fdc37m81x_base) {
+		outb(SMSC_FDC37M81X_CONFIG_ENTER,
+		     g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX);
+	}
+}
+
+void smsc_fdc37m81x_config_end(void)
+{
+	if (g_smsc_fdc37m81x_base)
+		outb(SMSC_FDC37M81X_CONFIG_EXIT,
+		     g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX);
+}
+
+u8 smsc_fdc37m81x_config_get(u8 reg)
+{
+	u8 val = 0;
+
+	if (g_smsc_fdc37m81x_base)
+		val = smsc_fdc37m81x_rd(reg);
+
+	return val;
+}
+
+void smsc_fdc37m81x_config_set(u8 reg, u8 val)
+{
+	if (g_smsc_fdc37m81x_base)
+		smsc_dc37m81x_wr(reg, val);
+}
+
+unsigned long __init smsc_fdc37m81x_init(unsigned long port)
+{
+	const int field = sizeof(unsigned long) * 2;
+	u8 chip_id;
+
+	if (g_smsc_fdc37m81x_base)
+		pr_warn("%s: stepping on old base=0x%0*lx\n", __func__, field,
+			g_smsc_fdc37m81x_base);
+
+	g_smsc_fdc37m81x_base = port;
+
+	smsc_fdc37m81x_config_beg();
+
+	chip_id = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DID);
+	if (chip_id == SMSC_FDC37M81X_CHIP_ID)
+		smsc_fdc37m81x_config_end();
+	else {
+		pr_warn("%s: unknown chip id 0x%02x\n", __func__, chip_id);
+		g_smsc_fdc37m81x_base = 0;
+	}
+
+	return g_smsc_fdc37m81x_base;
+}
+
+#ifdef DEBUG
+static void smsc_fdc37m81x_config_dump_one(const char *key, u8 dev, u8 reg)
+{
+	pr_info("%s: dev=0x%02x reg=0x%02x val=0x%02x\n", key, dev, reg,
+		smsc_fdc37m81x_rd(reg));
+}
+
+void smsc_fdc37m81x_config_dump(void)
+{
+	u8 orig;
+	const char *fname = __func__;
+
+	smsc_fdc37m81x_config_beg();
+
+	orig = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DNUM);
+
+	pr_info("%s: common\n", fname);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
+				       SMSC_FDC37M81X_DNUM);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
+				       SMSC_FDC37M81X_DID);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
+				       SMSC_FDC37M81X_DREV);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
+				       SMSC_FDC37M81X_PCNT);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE,
+				       SMSC_FDC37M81X_PMGT);
+
+	pr_info("%s: keyboard\n", fname);
+	smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, SMSC_FDC37M81X_KBD);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD,
+				       SMSC_FDC37M81X_ACTIVE);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD,
+				       SMSC_FDC37M81X_INT);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD,
+				       SMSC_FDC37M81X_INT2);
+	smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD,
+				       SMSC_FDC37M81X_LDCR_F0);
+
+	smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, orig);
+
+	smsc_fdc37m81x_config_end();
+}
+#endif
diff --git a/arch/mips/txx9/generic/spi_eeprom.c b/arch/mips/txx9/generic/spi_eeprom.c
new file mode 100644
index 0000000..d833dd2
--- /dev/null
+++ b/arch/mips/txx9/generic/spi_eeprom.c
@@ -0,0 +1,104 @@
+/*
+ * spi_eeprom.c
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+#include <asm/txx9/spi.h>
+
+#define AT250X0_PAGE_SIZE	8
+
+/* register board information for at25 driver */
+int __init spi_eeprom_register(int busid, int chipid, int size)
+{
+	struct spi_board_info info = {
+		.modalias = "at25",
+		.max_speed_hz = 1500000,	/* 1.5Mbps */
+		.bus_num = busid,
+		.chip_select = chipid,
+		/* Mode 0: High-Active, Sample-Then-Shift */
+	};
+	struct spi_eeprom *eeprom;
+	eeprom = kzalloc(sizeof(*eeprom), GFP_KERNEL);
+	if (!eeprom)
+		return -ENOMEM;
+	strcpy(eeprom->name, "at250x0");
+	eeprom->byte_len = size;
+	eeprom->page_size = AT250X0_PAGE_SIZE;
+	eeprom->flags = EE_ADDR1;
+	info.platform_data = eeprom;
+	return spi_register_board_info(&info, 1);
+}
+
+/* simple temporary spi driver to provide early access to seeprom. */
+
+static struct read_param {
+	int busid;
+	int chipid;
+	int address;
+	unsigned char *buf;
+	int len;
+} *read_param;
+
+static int __init early_seeprom_probe(struct spi_device *spi)
+{
+	int stat = 0;
+	u8 cmd[2];
+	int len = read_param->len;
+	char *buf = read_param->buf;
+	int address = read_param->address;
+
+	dev_info(&spi->dev, "spiclk %u KHz.\n",
+		 (spi->max_speed_hz + 500) / 1000);
+	if (read_param->busid != spi->master->bus_num ||
+	    read_param->chipid != spi->chip_select)
+		return -ENODEV;
+	while (len > 0) {
+		/* spi_write_then_read can only work with small chunk */
+		int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE;
+		cmd[0] = 0x03;	/* AT25_READ */
+		cmd[1] = address;
+		stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c);
+		buf += c;
+		len -= c;
+		address += c;
+	}
+	return stat;
+}
+
+static struct spi_driver early_seeprom_driver __initdata = {
+	.driver = {
+		.name	= "at25",
+	},
+	.probe	= early_seeprom_probe,
+};
+
+int __init spi_eeprom_read(int busid, int chipid, int address,
+			   unsigned char *buf, int len)
+{
+	int ret;
+	struct read_param param = {
+		.busid = busid,
+		.chipid = chipid,
+		.address = address,
+		.buf = buf,
+		.len = len
+	};
+
+	read_param = &param;
+	ret = spi_register_driver(&early_seeprom_driver);
+	if (!ret)
+		spi_unregister_driver(&early_seeprom_driver);
+	return ret;
+}
diff --git a/arch/mips/txx9/jmr3927/Makefile b/arch/mips/txx9/jmr3927/Makefile
new file mode 100644
index 0000000..9f5d5b6
--- /dev/null
+++ b/arch/mips/txx9/jmr3927/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for TOSHIBA JMR-TX3927 board
+#
+
+obj-y	+= prom.o irq.o setup.o
diff --git a/arch/mips/txx9/jmr3927/irq.c b/arch/mips/txx9/jmr3927/irq.c
new file mode 100644
index 0000000..c22c859
--- /dev/null
+++ b/arch/mips/txx9/jmr3927/irq.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              ahennessy@mvista.com
+ *
+ * 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) 2000-2001 Toshiba Corporation
+ *
+ *  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
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/jmr3927.h>
+
+#if JMR3927_IRQ_END > NR_IRQS
+#error JMR3927_IRQ_END > NR_IRQS
+#endif
+
+/*
+ * CP0_STATUS is a thread's resource (saved/restored on context switch).
+ * So disable_irq/enable_irq MUST handle IOC/IRC registers.
+ */
+static void mask_irq_ioc(struct irq_data *d)
+{
+	/* 0: mask */
+	unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC;
+	unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
+	unsigned int bit = 1 << irq_nr;
+	jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR);
+	/* flush write buffer */
+	(void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
+}
+static void unmask_irq_ioc(struct irq_data *d)
+{
+	/* 0: mask */
+	unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC;
+	unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
+	unsigned int bit = 1 << irq_nr;
+	jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR);
+	/* flush write buffer */
+	(void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
+}
+
+static int jmr3927_ioc_irqroute(void)
+{
+	unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR);
+	int i;
+
+	for (i = 0; i < JMR3927_NR_IRQ_IOC; i++) {
+		if (istat & (1 << i))
+			return JMR3927_IRQ_IOC + i;
+	}
+	return -1;
+}
+
+static int jmr3927_irq_dispatch(int pending)
+{
+	int irq;
+
+	if ((pending & CAUSEF_IP7) == 0)
+		return -1;
+	irq = (pending >> CAUSEB_IP2) & 0x0f;
+	irq += JMR3927_IRQ_IRC;
+	if (irq == JMR3927_IRQ_IOCINT)
+		irq = jmr3927_ioc_irqroute();
+	return irq;
+}
+
+static struct irq_chip jmr3927_irq_ioc = {
+	.name = "jmr3927_ioc",
+	.irq_mask = mask_irq_ioc,
+	.irq_unmask = unmask_irq_ioc,
+};
+
+void __init jmr3927_irq_setup(void)
+{
+	int i;
+
+	txx9_irq_dispatch = jmr3927_irq_dispatch;
+	/* Now, interrupt control disabled, */
+	/* all IRC interrupts are masked, */
+	/* all IRC interrupt mode are Low Active. */
+
+	/* mask all IOC interrupts */
+	jmr3927_ioc_reg_out(0, JMR3927_IOC_INTM_ADDR);
+	/* setup IOC interrupt mode (SOFT:High Active, Others:Low Active) */
+	jmr3927_ioc_reg_out(JMR3927_IOC_INTF_SOFT, JMR3927_IOC_INTP_ADDR);
+
+	/* clear PCI Soft interrupts */
+	jmr3927_ioc_reg_out(0, JMR3927_IOC_INTS1_ADDR);
+	/* clear PCI Reset interrupts */
+	jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+
+	tx3927_irq_init();
+	for (i = JMR3927_IRQ_IOC; i < JMR3927_IRQ_IOC + JMR3927_NR_IRQ_IOC; i++)
+		irq_set_chip_and_handler(i, &jmr3927_irq_ioc,
+					 handle_level_irq);
+
+	/* setup IOC interrupt 1 (PCI, MODEM) */
+	irq_set_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq);
+}
diff --git a/arch/mips/txx9/jmr3927/prom.c b/arch/mips/txx9/jmr3927/prom.c
new file mode 100644
index 0000000..68a9647
--- /dev/null
+++ b/arch/mips/txx9/jmr3927/prom.c
@@ -0,0 +1,52 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ *    PROM library initialisation code, assuming a version of
+ *    pmon is the boot code.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              ahennessy@mvista.com
+ *
+ * Based on arch/mips/au1000/common/prom.c
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  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
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/bootinfo.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/jmr3927.h>
+
+void __init jmr3927_prom_init(void)
+{
+	/* CCFG */
+	if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0)
+		pr_err("TX3927 TLB off\n");
+
+	add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM);
+	txx9_sio_putchar_init(TX3927_SIO_REG(1));
+}
diff --git a/arch/mips/txx9/jmr3927/setup.c b/arch/mips/txx9/jmr3927/setup.c
new file mode 100644
index 0000000..6139438
--- /dev/null
+++ b/arch/mips/txx9/jmr3927/setup.c
@@ -0,0 +1,223 @@
+/*
+ *  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
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *              ahennessy@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <asm/reboot.h>
+#include <asm/txx9pio.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/pci.h>
+#include <asm/txx9/jmr3927.h>
+#include <asm/mipsregs.h>
+
+static void jmr3927_machine_restart(char *command)
+{
+	local_irq_disable();
+#if 1	/* Resetting PCI bus */
+	jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+	jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI, JMR3927_IOC_RESET_ADDR);
+	(void)jmr3927_ioc_reg_in(JMR3927_IOC_RESET_ADDR);	/* flush WB */
+	mdelay(1);
+	jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+#endif
+	jmr3927_ioc_reg_out(JMR3927_IOC_RESET_CPU, JMR3927_IOC_RESET_ADDR);
+	/* fallback */
+	(*_machine_halt)();
+}
+
+static void __init jmr3927_time_init(void)
+{
+	tx3927_time_init(0, 1);
+}
+
+#define DO_WRITE_THROUGH
+
+static void jmr3927_board_init(void);
+
+static void __init jmr3927_mem_setup(void)
+{
+	set_io_port_base(JMR3927_PORT_BASE + JMR3927_PCIIO);
+
+	_machine_restart = jmr3927_machine_restart;
+
+	/* cache setup */
+	{
+		unsigned int conf;
+#ifdef DO_WRITE_THROUGH
+		int mips_config_cwfon = 0;
+		int mips_config_wbon = 0;
+#else
+		int mips_config_cwfon = 1;
+		int mips_config_wbon = 1;
+#endif
+
+		conf = read_c0_conf();
+		conf &= ~(TX39_CONF_WBON | TX39_CONF_CWFON);
+		conf |= mips_config_wbon ? TX39_CONF_WBON : 0;
+		conf |= mips_config_cwfon ? TX39_CONF_CWFON : 0;
+
+		write_c0_conf(conf);
+		write_c0_cache(0);
+	}
+
+	/* initialize board */
+	jmr3927_board_init();
+
+	tx3927_sio_init(0, 1 << 1); /* ch1: noCTS */
+}
+
+static void __init jmr3927_pci_setup(void)
+{
+#ifdef CONFIG_PCI
+	int extarb = !(tx3927_ccfgptr->ccfg & TX3927_CCFG_PCIXARB);
+	struct pci_controller *c;
+
+	c = txx9_alloc_pci_controller(&txx9_primary_pcic,
+				      JMR3927_PCIMEM, JMR3927_PCIMEM_SIZE,
+				      JMR3927_PCIIO, JMR3927_PCIIO_SIZE);
+	register_pci_controller(c);
+	if (!extarb) {
+		/* Reset PCI Bus */
+		jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+		udelay(100);
+		jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI,
+				    JMR3927_IOC_RESET_ADDR);
+		udelay(100);
+		jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
+	}
+	tx3927_pcic_setup(c, JMR3927_SDRAM_SIZE, extarb);
+	tx3927_setup_pcierr_irq();
+#endif /* CONFIG_PCI */
+}
+
+static void __init jmr3927_board_init(void)
+{
+	txx9_cpu_clock = JMR3927_CORECLK;
+	/* SDRAMC are configured by PROM */
+
+	/* ROMC */
+	tx3927_romcptr->cr[1] = JMR3927_ROMCE1 | 0x00030048;
+	tx3927_romcptr->cr[2] = JMR3927_ROMCE2 | 0x000064c8;
+	tx3927_romcptr->cr[3] = JMR3927_ROMCE3 | 0x0003f698;
+	tx3927_romcptr->cr[5] = JMR3927_ROMCE5 | 0x0000f218;
+
+	/* Pin selection */
+	tx3927_ccfgptr->pcfg &= ~TX3927_PCFG_SELALL;
+	tx3927_ccfgptr->pcfg |=
+		TX3927_PCFG_SELSIOC(0) | TX3927_PCFG_SELSIO_ALL |
+		(TX3927_PCFG_SELDMA_ALL & ~TX3927_PCFG_SELDMA(1));
+
+	tx3927_setup();
+
+	/* PIO[15:12] connected to LEDs */
+	__raw_writel(0x0000f000, &tx3927_pioptr->dir);
+
+	jmr3927_pci_setup();
+
+	/* SIO0 DTR on */
+	jmr3927_ioc_reg_out(0, JMR3927_IOC_DTR_ADDR);
+
+	jmr3927_led_set(0);
+
+	pr_info("JMR-TX3927 (Rev %d) --- IOC(Rev %d) DIPSW:%d,%d,%d,%d\n",
+		jmr3927_ioc_reg_in(JMR3927_IOC_BREV_ADDR) & JMR3927_REV_MASK,
+		jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR) & JMR3927_REV_MASK,
+		jmr3927_dipsw1(), jmr3927_dipsw2(),
+		jmr3927_dipsw3(), jmr3927_dipsw4());
+}
+
+/* This trick makes rtc-ds1742 driver usable as is. */
+static unsigned long jmr3927_swizzle_addr_b(unsigned long port)
+{
+	if ((port & 0xffff0000) != JMR3927_IOC_NVRAMB_ADDR)
+		return port;
+	port = (port & 0xffff0000) | (port & 0x7fff << 1);
+#ifdef __BIG_ENDIAN
+	return port;
+#else
+	return port | 1;
+#endif
+}
+
+static void __init jmr3927_rtc_init(void)
+{
+	static struct resource __initdata res = {
+		.start	= JMR3927_IOC_NVRAMB_ADDR - IO_BASE,
+		.end	= JMR3927_IOC_NVRAMB_ADDR - IO_BASE + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
+	};
+	platform_device_register_simple("rtc-ds1742", -1, &res, 1);
+}
+
+static void __init jmr3927_mtd_init(void)
+{
+	int i;
+
+	for (i = 0; i < 2; i++)
+		tx3927_mtd_init(i);
+}
+
+static void __init jmr3927_device_init(void)
+{
+	unsigned long iocled_base = JMR3927_IOC_LED_ADDR - IO_BASE;
+#ifdef __LITTLE_ENDIAN
+	iocled_base |= 1;
+#endif
+	__swizzle_addr_b = jmr3927_swizzle_addr_b;
+	jmr3927_rtc_init();
+	tx3927_wdt_init();
+	jmr3927_mtd_init();
+	txx9_iocled_init(iocled_base, -1, 8, 1, "green", NULL);
+}
+
+static void __init jmr3927_arch_init(void)
+{
+	txx9_gpio_init(TX3927_PIO_REG, 0, 16);
+
+	gpio_request(11, "dipsw1");
+	gpio_request(10, "dipsw2");
+}
+
+struct txx9_board_vec jmr3927_vec __initdata = {
+	.system = "Toshiba JMR_TX3927",
+	.prom_init = jmr3927_prom_init,
+	.mem_setup = jmr3927_mem_setup,
+	.irq_setup = jmr3927_irq_setup,
+	.time_init = jmr3927_time_init,
+	.device_init = jmr3927_device_init,
+	.arch_init = jmr3927_arch_init,
+#ifdef CONFIG_PCI
+	.pci_map_irq = jmr3927_pci_map_irq,
+#endif
+};
diff --git a/arch/mips/txx9/rbtx4927/Makefile b/arch/mips/txx9/rbtx4927/Makefile
new file mode 100644
index 0000000..60b24c8
--- /dev/null
+++ b/arch/mips/txx9/rbtx4927/Makefile
@@ -0,0 +1 @@
+obj-y	+= prom.o setup.o irq.o
diff --git a/arch/mips/txx9/rbtx4927/irq.c b/arch/mips/txx9/rbtx4927/irq.c
new file mode 100644
index 0000000..3f48292
--- /dev/null
+++ b/arch/mips/txx9/rbtx4927/irq.c
@@ -0,0 +1,198 @@
+/*
+ * Toshiba RBTX4927 specific interrupt handlers
+ *
+ * Author: MontaVista Software, Inc.
+ *	   source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ *  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
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * I8259A_IRQ_BASE+00
+ * I8259A_IRQ_BASE+01 PS2/Keyboard
+ * I8259A_IRQ_BASE+02 Cascade RBTX4927-ISA (irqs 8-15)
+ * I8259A_IRQ_BASE+03
+ * I8259A_IRQ_BASE+04
+ * I8259A_IRQ_BASE+05
+ * I8259A_IRQ_BASE+06
+ * I8259A_IRQ_BASE+07
+ * I8259A_IRQ_BASE+08
+ * I8259A_IRQ_BASE+09
+ * I8259A_IRQ_BASE+10
+ * I8259A_IRQ_BASE+11
+ * I8259A_IRQ_BASE+12 PS2/Mouse (not supported at this time)
+ * I8259A_IRQ_BASE+13
+ * I8259A_IRQ_BASE+14 IDE
+ * I8259A_IRQ_BASE+15
+ *
+ * MIPS_CPU_IRQ_BASE+00 Software 0
+ * MIPS_CPU_IRQ_BASE+01 Software 1
+ * MIPS_CPU_IRQ_BASE+02 Cascade TX4927-CP0
+ * MIPS_CPU_IRQ_BASE+03 Multiplexed -- do not use
+ * MIPS_CPU_IRQ_BASE+04 Multiplexed -- do not use
+ * MIPS_CPU_IRQ_BASE+05 Multiplexed -- do not use
+ * MIPS_CPU_IRQ_BASE+06 Multiplexed -- do not use
+ * MIPS_CPU_IRQ_BASE+07 CPU TIMER
+ *
+ * TXX9_IRQ_BASE+00
+ * TXX9_IRQ_BASE+01
+ * TXX9_IRQ_BASE+02
+ * TXX9_IRQ_BASE+03 Cascade RBTX4927-IOC
+ * TXX9_IRQ_BASE+04
+ * TXX9_IRQ_BASE+05 RBTX4927 RTL-8019AS ethernet
+ * TXX9_IRQ_BASE+06
+ * TXX9_IRQ_BASE+07
+ * TXX9_IRQ_BASE+08 TX4927 SerialIO Channel 0
+ * TXX9_IRQ_BASE+09 TX4927 SerialIO Channel 1
+ * TXX9_IRQ_BASE+10
+ * TXX9_IRQ_BASE+11
+ * TXX9_IRQ_BASE+12
+ * TXX9_IRQ_BASE+13
+ * TXX9_IRQ_BASE+14
+ * TXX9_IRQ_BASE+15
+ * TXX9_IRQ_BASE+16 TX4927 PCI PCI-C
+ * TXX9_IRQ_BASE+17
+ * TXX9_IRQ_BASE+18
+ * TXX9_IRQ_BASE+19
+ * TXX9_IRQ_BASE+20
+ * TXX9_IRQ_BASE+21
+ * TXX9_IRQ_BASE+22 TX4927 PCI PCI-ERR
+ * TXX9_IRQ_BASE+23 TX4927 PCI PCI-PMA (not used)
+ * TXX9_IRQ_BASE+24
+ * TXX9_IRQ_BASE+25
+ * TXX9_IRQ_BASE+26
+ * TXX9_IRQ_BASE+27
+ * TXX9_IRQ_BASE+28
+ * TXX9_IRQ_BASE+29
+ * TXX9_IRQ_BASE+30
+ * TXX9_IRQ_BASE+31
+ *
+ * RBTX4927_IRQ_IOC+00 FPCIB0 PCI-D (SouthBridge)
+ * RBTX4927_IRQ_IOC+01 FPCIB0 PCI-C (SouthBridge)
+ * RBTX4927_IRQ_IOC+02 FPCIB0 PCI-B (SouthBridge/IDE/pin=1,INTR)
+ * RBTX4927_IRQ_IOC+03 FPCIB0 PCI-A (SouthBridge/USB/pin=4)
+ * RBTX4927_IRQ_IOC+04
+ * RBTX4927_IRQ_IOC+05
+ * RBTX4927_IRQ_IOC+06
+ * RBTX4927_IRQ_IOC+07
+ *
+ * NOTES:
+ * SouthBridge/INTR is mapped to SouthBridge/A=PCI-B/#58
+ * SouthBridge/ISA/pin=0 no pci irq used by this device
+ * SouthBridge/IDE/pin=1 no pci irq used by this device, using INTR
+ * via ISA IRQ14
+ * SouthBridge/USB/pin=4 using pci irq SouthBridge/D=PCI-A=#59
+ * SouthBridge/PMC/pin=0 no pci irq used by this device
+ * SuperIO/PS2/Keyboard, using INTR via ISA IRQ1
+ * SuperIO/PS2/Mouse, using INTR via ISA IRQ12 (mouse not currently supported)
+ * JP7 is not bus master -- do NOT use -- only 4 pci bus master's
+ * allowed -- SouthBridge, JP4, JP5, JP6
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/rbtx4927.h>
+
+static int toshiba_rbtx4927_irq_nested(int sw_irq)
+{
+	u8 level3;
+
+	level3 = readb(rbtx4927_imstat_addr) & 0x1f;
+	if (unlikely(!level3))
+		return -1;
+	return RBTX4927_IRQ_IOC + __fls8(level3);
+}
+
+static void toshiba_rbtx4927_irq_ioc_enable(struct irq_data *d)
+{
+	unsigned char v;
+
+	v = readb(rbtx4927_imask_addr);
+	v |= (1 << (d->irq - RBTX4927_IRQ_IOC));
+	writeb(v, rbtx4927_imask_addr);
+}
+
+static void toshiba_rbtx4927_irq_ioc_disable(struct irq_data *d)
+{
+	unsigned char v;
+
+	v = readb(rbtx4927_imask_addr);
+	v &= ~(1 << (d->irq - RBTX4927_IRQ_IOC));
+	writeb(v, rbtx4927_imask_addr);
+	mmiowb();
+}
+
+#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
+static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
+	.name = TOSHIBA_RBTX4927_IOC_NAME,
+	.irq_mask = toshiba_rbtx4927_irq_ioc_disable,
+	.irq_unmask = toshiba_rbtx4927_irq_ioc_enable,
+};
+
+static void __init toshiba_rbtx4927_irq_ioc_init(void)
+{
+	int i;
+
+	/* mask all IOC interrupts */
+	writeb(0, rbtx4927_imask_addr);
+	/* clear SoftInt interrupts */
+	writeb(0, rbtx4927_softint_addr);
+
+	for (i = RBTX4927_IRQ_IOC;
+	     i < RBTX4927_IRQ_IOC + RBTX4927_NR_IRQ_IOC; i++)
+		irq_set_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type,
+					 handle_level_irq);
+	irq_set_chained_handler(RBTX4927_IRQ_IOCINT, handle_simple_irq);
+}
+
+static int rbtx4927_irq_dispatch(int pending)
+{
+	int irq;
+
+	if (pending & STATUSF_IP7)			/* cpu timer */
+		irq = MIPS_CPU_IRQ_BASE + 7;
+	else if (pending & STATUSF_IP2) {		/* tx4927 pic */
+		irq = txx9_irq();
+		if (irq == RBTX4927_IRQ_IOCINT)
+			irq = toshiba_rbtx4927_irq_nested(irq);
+	} else if (pending & STATUSF_IP0)		/* user line 0 */
+		irq = MIPS_CPU_IRQ_BASE + 0;
+	else if (pending & STATUSF_IP1)			/* user line 1 */
+		irq = MIPS_CPU_IRQ_BASE + 1;
+	else
+		irq = -1;
+	return irq;
+}
+
+void __init rbtx4927_irq_setup(void)
+{
+	txx9_irq_dispatch = rbtx4927_irq_dispatch;
+	tx4927_irq_init();
+	toshiba_rbtx4927_irq_ioc_init();
+	/* Onboard 10M Ether: High Active */
+	irq_set_irq_type(RBTX4927_RTL_8019_IRQ, IRQF_TRIGGER_HIGH);
+}
diff --git a/arch/mips/txx9/rbtx4927/prom.c b/arch/mips/txx9/rbtx4927/prom.c
new file mode 100644
index 0000000..fe6d0b5
--- /dev/null
+++ b/arch/mips/txx9/rbtx4927/prom.c
@@ -0,0 +1,41 @@
+/*
+ * rbtx4927 specific prom routines
+ *
+ * Author: MontaVista Software, Inc.
+ *	   source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ *
+ *  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
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/rbtx4927.h>
+
+void __init rbtx4927_prom_init(void)
+{
+	add_memory_region(0, tx4927_get_mem_size(), BOOT_MEM_RAM);
+	txx9_sio_putchar_init(TX4927_SIO_REG(0) & 0xfffffffffULL);
+}
diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c
new file mode 100644
index 0000000..31955c1
--- /dev/null
+++ b/arch/mips/txx9/rbtx4927/setup.c
@@ -0,0 +1,380 @@
+/*
+ * Toshiba rbtx4927 specific setup
+ *
+ * Author: MontaVista Software, Inc.
+ *	   source@mvista.com
+ *
+ * Copyright 2001-2002 MontaVista Software Inc.
+ *
+ * Copyright (C) 1996, 97, 2001, 04  Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2000 RidgeRun, Inc.
+ * Author: RidgeRun, Inc.
+ *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright 2002 MontaVista Software Inc.
+ * Author: Michael Pruznick, michael_pruznick@mvista.com
+ *
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * Copyright (C) 2004 MontaVista Software Inc.
+ * Author: Manish Lachwani, mlachwani@mvista.com
+ *
+ *  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
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/txx9pio.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/pci.h>
+#include <asm/txx9/rbtx4927.h>
+#include <asm/txx9/tx4938.h>	/* for TX4937 */
+
+#ifdef CONFIG_PCI
+static void __init tx4927_pci_setup(void)
+{
+	int extarb = !(__raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_PCIARB);
+	struct pci_controller *c = &txx9_primary_pcic;
+
+	register_pci_controller(c);
+
+	if (__raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_PCI66)
+		txx9_pci_option =
+			(txx9_pci_option & ~TXX9_PCI_OPT_CLK_MASK) |
+			TXX9_PCI_OPT_CLK_66; /* already configured */
+
+	/* Reset PCI Bus */
+	writeb(1, rbtx4927_pcireset_addr);
+	/* Reset PCIC */
+	txx9_set64(&tx4927_ccfgptr->clkctr, TX4927_CLKCTR_PCIRST);
+	if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) ==
+	    TXX9_PCI_OPT_CLK_66)
+		tx4927_pciclk66_setup();
+	mdelay(10);
+	/* clear PCIC reset */
+	txx9_clear64(&tx4927_ccfgptr->clkctr, TX4927_CLKCTR_PCIRST);
+	writeb(0, rbtx4927_pcireset_addr);
+	iob();
+
+	tx4927_report_pciclk();
+	tx4927_pcic_setup(tx4927_pcicptr, c, extarb);
+	if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) ==
+	    TXX9_PCI_OPT_CLK_AUTO &&
+	    txx9_pci66_check(c, 0, 0)) {
+		/* Reset PCI Bus */
+		writeb(1, rbtx4927_pcireset_addr);
+		/* Reset PCIC */
+		txx9_set64(&tx4927_ccfgptr->clkctr, TX4927_CLKCTR_PCIRST);
+		tx4927_pciclk66_setup();
+		mdelay(10);
+		/* clear PCIC reset */
+		txx9_clear64(&tx4927_ccfgptr->clkctr, TX4927_CLKCTR_PCIRST);
+		writeb(0, rbtx4927_pcireset_addr);
+		iob();
+		/* Reinitialize PCIC */
+		tx4927_report_pciclk();
+		tx4927_pcic_setup(tx4927_pcicptr, c, extarb);
+	}
+	tx4927_setup_pcierr_irq();
+}
+
+static void __init tx4937_pci_setup(void)
+{
+	int extarb = !(__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCIARB);
+	struct pci_controller *c = &txx9_primary_pcic;
+
+	register_pci_controller(c);
+
+	if (__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCI66)
+		txx9_pci_option =
+			(txx9_pci_option & ~TXX9_PCI_OPT_CLK_MASK) |
+			TXX9_PCI_OPT_CLK_66; /* already configured */
+
+	/* Reset PCI Bus */
+	writeb(1, rbtx4927_pcireset_addr);
+	/* Reset PCIC */
+	txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST);
+	if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) ==
+	    TXX9_PCI_OPT_CLK_66)
+		tx4938_pciclk66_setup();
+	mdelay(10);
+	/* clear PCIC reset */
+	txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST);
+	writeb(0, rbtx4927_pcireset_addr);
+	iob();
+
+	tx4938_report_pciclk();
+	tx4927_pcic_setup(tx4938_pcicptr, c, extarb);
+	if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) ==
+	    TXX9_PCI_OPT_CLK_AUTO &&
+	    txx9_pci66_check(c, 0, 0)) {
+		/* Reset PCI Bus */
+		writeb(1, rbtx4927_pcireset_addr);
+		/* Reset PCIC */
+		txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST);
+		tx4938_pciclk66_setup();
+		mdelay(10);
+		/* clear PCIC reset */
+		txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST);
+		writeb(0, rbtx4927_pcireset_addr);
+		iob();
+		/* Reinitialize PCIC */
+		tx4938_report_pciclk();
+		tx4927_pcic_setup(tx4938_pcicptr, c, extarb);
+	}
+	tx4938_setup_pcierr_irq();
+}
+#else
+static inline void tx4927_pci_setup(void) {}
+static inline void tx4937_pci_setup(void) {}
+#endif /* CONFIG_PCI */
+
+static void __init rbtx4927_gpio_init(void)
+{
+	/* TX4927-SIO DTR on (PIO[15]) */
+	gpio_request(15, "sio-dtr");
+	gpio_direction_output(15, 1);
+
+	tx4927_sio_init(0, 0);
+}
+
+static void __init rbtx4927_arch_init(void)
+{
+	txx9_gpio_init(TX4927_PIO_REG & 0xfffffffffULL, 0, TX4927_NUM_PIO);
+
+	rbtx4927_gpio_init();
+
+	tx4927_pci_setup();
+}
+
+static void __init rbtx4937_arch_init(void)
+{
+	txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, TX4938_NUM_PIO);
+
+	rbtx4927_gpio_init();
+
+	tx4937_pci_setup();
+}
+
+static void toshiba_rbtx4927_restart(char *command)
+{
+	/* enable the s/w reset register */
+	writeb(1, rbtx4927_softresetlock_addr);
+
+	/* wait for enable to be seen */
+	while (!(readb(rbtx4927_softresetlock_addr) & 1))
+		;
+
+	/* do a s/w reset */
+	writeb(1, rbtx4927_softreset_addr);
+
+	/* fallback */
+	(*_machine_halt)();
+}
+
+static void __init rbtx4927_clock_init(void);
+static void __init rbtx4937_clock_init(void);
+
+static void __init rbtx4927_mem_setup(void)
+{
+	if (TX4927_REV_PCODE() == 0x4927) {
+		rbtx4927_clock_init();
+		tx4927_setup();
+	} else {
+		rbtx4937_clock_init();
+		tx4938_setup();
+	}
+
+	_machine_restart = toshiba_rbtx4927_restart;
+
+#ifdef CONFIG_PCI
+	txx9_alloc_pci_controller(&txx9_primary_pcic,
+				  RBTX4927_PCIMEM, RBTX4927_PCIMEM_SIZE,
+				  RBTX4927_PCIIO, RBTX4927_PCIIO_SIZE);
+	txx9_board_pcibios_setup = tx4927_pcibios_setup;
+#else
+	set_io_port_base(KSEG1 + RBTX4927_ISA_IO_OFFSET);
+#endif
+}
+
+static void __init rbtx4927_clock_init(void)
+{
+	/*
+	 * ASSUMPTION: PCIDIVMODE is configured for PCI 33MHz or 66MHz.
+	 *
+	 * For TX4927:
+	 * PCIDIVMODE[12:11]'s initial value is given by S9[4:3] (ON:0, OFF:1).
+	 * CPU 166MHz: PCI 66MHz : PCIDIVMODE: 00 (1/2.5)
+	 * CPU 200MHz: PCI 66MHz : PCIDIVMODE: 01 (1/3)
+	 * CPU 166MHz: PCI 33MHz : PCIDIVMODE: 10 (1/5)
+	 * CPU 200MHz: PCI 33MHz : PCIDIVMODE: 11 (1/6)
+	 * i.e. S9[3]: ON (83MHz), OFF (100MHz)
+	 */
+	switch ((unsigned long)__raw_readq(&tx4927_ccfgptr->ccfg) &
+		TX4927_CCFG_PCIDIVMODE_MASK) {
+	case TX4927_CCFG_PCIDIVMODE_2_5:
+	case TX4927_CCFG_PCIDIVMODE_5:
+		txx9_cpu_clock = 166666666;	/* 166MHz */
+		break;
+	default:
+		txx9_cpu_clock = 200000000;	/* 200MHz */
+	}
+}
+
+static void __init rbtx4937_clock_init(void)
+{
+	/*
+	 * ASSUMPTION: PCIDIVMODE is configured for PCI 33MHz or 66MHz.
+	 *
+	 * For TX4937:
+	 * PCIDIVMODE[12:11]'s initial value is given by S1[5:4] (ON:0, OFF:1)
+	 * PCIDIVMODE[10] is 0.
+	 * CPU 266MHz: PCI 33MHz : PCIDIVMODE: 000 (1/8)
+	 * CPU 266MHz: PCI 66MHz : PCIDIVMODE: 001 (1/4)
+	 * CPU 300MHz: PCI 33MHz : PCIDIVMODE: 010 (1/9)
+	 * CPU 300MHz: PCI 66MHz : PCIDIVMODE: 011 (1/4.5)
+	 * CPU 333MHz: PCI 33MHz : PCIDIVMODE: 100 (1/10)
+	 * CPU 333MHz: PCI 66MHz : PCIDIVMODE: 101 (1/5)
+	 */
+	switch ((unsigned long)__raw_readq(&tx4938_ccfgptr->ccfg) &
+		TX4938_CCFG_PCIDIVMODE_MASK) {
+	case TX4938_CCFG_PCIDIVMODE_8:
+	case TX4938_CCFG_PCIDIVMODE_4:
+		txx9_cpu_clock = 266666666;	/* 266MHz */
+		break;
+	case TX4938_CCFG_PCIDIVMODE_9:
+	case TX4938_CCFG_PCIDIVMODE_4_5:
+		txx9_cpu_clock = 300000000;	/* 300MHz */
+		break;
+	default:
+		txx9_cpu_clock = 333333333;	/* 333MHz */
+	}
+}
+
+static void __init rbtx4927_time_init(void)
+{
+	tx4927_time_init(0);
+}
+
+static void __init toshiba_rbtx4927_rtc_init(void)
+{
+	struct resource res = {
+		.start	= RBTX4927_BRAMRTC_BASE - IO_BASE,
+		.end	= RBTX4927_BRAMRTC_BASE - IO_BASE + 0x800 - 1,
+		.flags	= IORESOURCE_MEM,
+	};
+	platform_device_register_simple("rtc-ds1742", -1, &res, 1);
+}
+
+static void __init rbtx4927_ne_init(void)
+{
+	struct resource res[] = {
+		{
+			.start	= RBTX4927_RTL_8019_BASE,
+			.end	= RBTX4927_RTL_8019_BASE + 0x20 - 1,
+			.flags	= IORESOURCE_IO,
+		}, {
+			.start	= RBTX4927_RTL_8019_IRQ,
+			.flags	= IORESOURCE_IRQ,
+		}
+	};
+	platform_device_register_simple("ne", -1, res, ARRAY_SIZE(res));
+}
+
+static void __init rbtx4927_mtd_init(void)
+{
+	int i;
+
+	for (i = 0; i < 2; i++)
+		tx4927_mtd_init(i);
+}
+
+static void __init rbtx4927_gpioled_init(void)
+{
+	static const struct gpio_led leds[] = {
+		{ .name = "gpioled:green:0", .gpio = 0, .active_low = 1, },
+		{ .name = "gpioled:green:1", .gpio = 1, .active_low = 1, },
+	};
+	static struct gpio_led_platform_data pdata = {
+		.num_leds = ARRAY_SIZE(leds),
+		.leds = leds,
+	};
+	struct platform_device *pdev = platform_device_alloc("leds-gpio", 0);
+
+	if (!pdev)
+		return;
+	pdev->dev.platform_data = &pdata;
+	if (platform_device_add(pdev))
+		platform_device_put(pdev);
+}
+
+static void __init rbtx4927_device_init(void)
+{
+	toshiba_rbtx4927_rtc_init();
+	rbtx4927_ne_init();
+	tx4927_wdt_init();
+	rbtx4927_mtd_init();
+	if (TX4927_REV_PCODE() == 0x4927) {
+		tx4927_dmac_init(2);
+		tx4927_aclc_init(0, 1);
+	} else {
+		tx4938_dmac_init(0, 2);
+		tx4938_aclc_init();
+	}
+	platform_device_register_simple("txx9aclc-generic", -1, NULL, 0);
+	txx9_iocled_init(RBTX4927_LED_ADDR - IO_BASE, -1, 3, 1, "green", NULL);
+	rbtx4927_gpioled_init();
+}
+
+struct txx9_board_vec rbtx4927_vec __initdata = {
+	.system = "Toshiba RBTX4927",
+	.prom_init = rbtx4927_prom_init,
+	.mem_setup = rbtx4927_mem_setup,
+	.irq_setup = rbtx4927_irq_setup,
+	.time_init = rbtx4927_time_init,
+	.device_init = rbtx4927_device_init,
+	.arch_init = rbtx4927_arch_init,
+#ifdef CONFIG_PCI
+	.pci_map_irq = rbtx4927_pci_map_irq,
+#endif
+};
+struct txx9_board_vec rbtx4937_vec __initdata = {
+	.system = "Toshiba RBTX4937",
+	.prom_init = rbtx4927_prom_init,
+	.mem_setup = rbtx4927_mem_setup,
+	.irq_setup = rbtx4927_irq_setup,
+	.time_init = rbtx4927_time_init,
+	.device_init = rbtx4927_device_init,
+	.arch_init = rbtx4937_arch_init,
+#ifdef CONFIG_PCI
+	.pci_map_irq = rbtx4927_pci_map_irq,
+#endif
+};
diff --git a/arch/mips/txx9/rbtx4938/Makefile b/arch/mips/txx9/rbtx4938/Makefile
new file mode 100644
index 0000000..60b24c8
--- /dev/null
+++ b/arch/mips/txx9/rbtx4938/Makefile
@@ -0,0 +1 @@
+obj-y	+= prom.o setup.o irq.o
diff --git a/arch/mips/txx9/rbtx4938/irq.c b/arch/mips/txx9/rbtx4938/irq.c
new file mode 100644
index 0000000..58cd7a9
--- /dev/null
+++ b/arch/mips/txx9/rbtx4938/irq.c
@@ -0,0 +1,157 @@
+/*
+ * Toshiba RBTX4938 specific interrupt handlers
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+
+/*
+ * MIPS_CPU_IRQ_BASE+00 Software 0
+ * MIPS_CPU_IRQ_BASE+01 Software 1
+ * MIPS_CPU_IRQ_BASE+02 Cascade TX4938-CP0
+ * MIPS_CPU_IRQ_BASE+03 Multiplexed -- do not use
+ * MIPS_CPU_IRQ_BASE+04 Multiplexed -- do not use
+ * MIPS_CPU_IRQ_BASE+05 Multiplexed -- do not use
+ * MIPS_CPU_IRQ_BASE+06 Multiplexed -- do not use
+ * MIPS_CPU_IRQ_BASE+07 CPU TIMER
+ *
+ * TXX9_IRQ_BASE+00
+ * TXX9_IRQ_BASE+01
+ * TXX9_IRQ_BASE+02 Cascade RBTX4938-IOC
+ * TXX9_IRQ_BASE+03 RBTX4938 RTL-8019AS Ethernet
+ * TXX9_IRQ_BASE+04
+ * TXX9_IRQ_BASE+05 TX4938 ETH1
+ * TXX9_IRQ_BASE+06 TX4938 ETH0
+ * TXX9_IRQ_BASE+07
+ * TXX9_IRQ_BASE+08 TX4938 SIO 0
+ * TXX9_IRQ_BASE+09 TX4938 SIO 1
+ * TXX9_IRQ_BASE+10 TX4938 DMA0
+ * TXX9_IRQ_BASE+11 TX4938 DMA1
+ * TXX9_IRQ_BASE+12 TX4938 DMA2
+ * TXX9_IRQ_BASE+13 TX4938 DMA3
+ * TXX9_IRQ_BASE+14
+ * TXX9_IRQ_BASE+15
+ * TXX9_IRQ_BASE+16 TX4938 PCIC
+ * TXX9_IRQ_BASE+17 TX4938 TMR0
+ * TXX9_IRQ_BASE+18 TX4938 TMR1
+ * TXX9_IRQ_BASE+19 TX4938 TMR2
+ * TXX9_IRQ_BASE+20
+ * TXX9_IRQ_BASE+21
+ * TXX9_IRQ_BASE+22 TX4938 PCIERR
+ * TXX9_IRQ_BASE+23
+ * TXX9_IRQ_BASE+24
+ * TXX9_IRQ_BASE+25
+ * TXX9_IRQ_BASE+26
+ * TXX9_IRQ_BASE+27
+ * TXX9_IRQ_BASE+28
+ * TXX9_IRQ_BASE+29
+ * TXX9_IRQ_BASE+30
+ * TXX9_IRQ_BASE+31 TX4938 SPI
+ *
+ * RBTX4938_IRQ_IOC+00 PCI-D
+ * RBTX4938_IRQ_IOC+01 PCI-C
+ * RBTX4938_IRQ_IOC+02 PCI-B
+ * RBTX4938_IRQ_IOC+03 PCI-A
+ * RBTX4938_IRQ_IOC+04 RTC
+ * RBTX4938_IRQ_IOC+05 ATA
+ * RBTX4938_IRQ_IOC+06 MODEM
+ * RBTX4938_IRQ_IOC+07 SWINT
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/rbtx4938.h>
+
+static int toshiba_rbtx4938_irq_nested(int sw_irq)
+{
+	u8 level3;
+
+	level3 = readb(rbtx4938_imstat_addr);
+	if (unlikely(!level3))
+		return -1;
+	/* must use fls so onboard ATA has priority */
+	return RBTX4938_IRQ_IOC + __fls8(level3);
+}
+
+static void toshiba_rbtx4938_irq_ioc_enable(struct irq_data *d)
+{
+	unsigned char v;
+
+	v = readb(rbtx4938_imask_addr);
+	v |= (1 << (d->irq - RBTX4938_IRQ_IOC));
+	writeb(v, rbtx4938_imask_addr);
+	mmiowb();
+}
+
+static void toshiba_rbtx4938_irq_ioc_disable(struct irq_data *d)
+{
+	unsigned char v;
+
+	v = readb(rbtx4938_imask_addr);
+	v &= ~(1 << (d->irq - RBTX4938_IRQ_IOC));
+	writeb(v, rbtx4938_imask_addr);
+	mmiowb();
+}
+
+#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
+static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
+	.name = TOSHIBA_RBTX4938_IOC_NAME,
+	.irq_mask = toshiba_rbtx4938_irq_ioc_disable,
+	.irq_unmask = toshiba_rbtx4938_irq_ioc_enable,
+};
+
+static int rbtx4938_irq_dispatch(int pending)
+{
+	int irq;
+
+	if (pending & STATUSF_IP7)
+		irq = MIPS_CPU_IRQ_BASE + 7;
+	else if (pending & STATUSF_IP2) {
+		irq = txx9_irq();
+		if (irq == RBTX4938_IRQ_IOCINT)
+			irq = toshiba_rbtx4938_irq_nested(irq);
+	} else if (pending & STATUSF_IP1)
+		irq = MIPS_CPU_IRQ_BASE + 0;
+	else if (pending & STATUSF_IP0)
+		irq = MIPS_CPU_IRQ_BASE + 1;
+	else
+		irq = -1;
+	return irq;
+}
+
+static void __init toshiba_rbtx4938_irq_ioc_init(void)
+{
+	int i;
+
+	for (i = RBTX4938_IRQ_IOC;
+	     i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++)
+		irq_set_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type,
+					 handle_level_irq);
+
+	irq_set_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq);
+}
+
+void __init rbtx4938_irq_setup(void)
+{
+	txx9_irq_dispatch = rbtx4938_irq_dispatch;
+	/* Now, interrupt control disabled, */
+	/* all IRC interrupts are masked, */
+	/* all IRC interrupt mode are Low Active. */
+
+	/* mask all IOC interrupts */
+	writeb(0, rbtx4938_imask_addr);
+
+	/* clear SoftInt interrupts */
+	writeb(0, rbtx4938_softint_addr);
+	tx4938_irq_init();
+	toshiba_rbtx4938_irq_ioc_init();
+	/* Onboard 10M Ether: High Active */
+	irq_set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH);
+}
diff --git a/arch/mips/txx9/rbtx4938/prom.c b/arch/mips/txx9/rbtx4938/prom.c
new file mode 100644
index 0000000..bcb4692
--- /dev/null
+++ b/arch/mips/txx9/rbtx4938/prom.c
@@ -0,0 +1,23 @@
+/*
+ * rbtx4938 specific prom routines
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <asm/bootinfo.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/rbtx4938.h>
+
+void __init rbtx4938_prom_init(void)
+{
+	add_memory_region(0, tx4938_get_mem_size(), BOOT_MEM_RAM);
+	txx9_sio_putchar_init(TX4938_SIO_REG(0) & 0xfffffffffULL);
+}
diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c
new file mode 100644
index 0000000..e68eb2e
--- /dev/null
+++ b/arch/mips/txx9/rbtx4938/setup.c
@@ -0,0 +1,372 @@
+/*
+ * Setup pointers to hardware-dependent routines.
+ * Copyright (C) 2000-2001 Toshiba Corporation
+ *
+ * 2003-2005 (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.
+ *
+ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/reboot.h>
+#include <asm/io.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/pci.h>
+#include <asm/txx9/rbtx4938.h>
+#include <linux/spi/spi.h>
+#include <asm/txx9/spi.h>
+#include <asm/txx9pio.h>
+
+static void rbtx4938_machine_restart(char *command)
+{
+	local_irq_disable();
+	writeb(1, rbtx4938_softresetlock_addr);
+	writeb(1, rbtx4938_sfvol_addr);
+	writeb(1, rbtx4938_softreset_addr);
+	/* fallback */
+	(*_machine_halt)();
+}
+
+static void __init rbtx4938_pci_setup(void)
+{
+#ifdef CONFIG_PCI
+	int extarb = !(__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCIARB);
+	struct pci_controller *c = &txx9_primary_pcic;
+
+	register_pci_controller(c);
+
+	if (__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCI66)
+		txx9_pci_option =
+			(txx9_pci_option & ~TXX9_PCI_OPT_CLK_MASK) |
+			TXX9_PCI_OPT_CLK_66; /* already configured */
+
+	/* Reset PCI Bus */
+	writeb(0, rbtx4938_pcireset_addr);
+	/* Reset PCIC */
+	txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST);
+	if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) ==
+	    TXX9_PCI_OPT_CLK_66)
+		tx4938_pciclk66_setup();
+	mdelay(10);
+	/* clear PCIC reset */
+	txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST);
+	writeb(1, rbtx4938_pcireset_addr);
+	iob();
+
+	tx4938_report_pciclk();
+	tx4927_pcic_setup(tx4938_pcicptr, c, extarb);
+	if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) ==
+	    TXX9_PCI_OPT_CLK_AUTO &&
+	    txx9_pci66_check(c, 0, 0)) {
+		/* Reset PCI Bus */
+		writeb(0, rbtx4938_pcireset_addr);
+		/* Reset PCIC */
+		txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST);
+		tx4938_pciclk66_setup();
+		mdelay(10);
+		/* clear PCIC reset */
+		txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST);
+		writeb(1, rbtx4938_pcireset_addr);
+		iob();
+		/* Reinitialize PCIC */
+		tx4938_report_pciclk();
+		tx4927_pcic_setup(tx4938_pcicptr, c, extarb);
+	}
+
+	if (__raw_readq(&tx4938_ccfgptr->pcfg) &
+	    (TX4938_PCFG_ETH0_SEL|TX4938_PCFG_ETH1_SEL)) {
+		/* Reset PCIC1 */
+		txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIC1RST);
+		/* PCI1DMD==0 => PCI1CLK==GBUSCLK/2 => PCI66 */
+		if (!(__raw_readq(&tx4938_ccfgptr->ccfg)
+		      & TX4938_CCFG_PCI1DMD))
+			tx4938_ccfg_set(TX4938_CCFG_PCI1_66);
+		mdelay(10);
+		/* clear PCIC1 reset */
+		txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIC1RST);
+		tx4938_report_pci1clk();
+
+		/* mem:64K(max), io:64K(max) (enough for ETH0,ETH1) */
+		c = txx9_alloc_pci_controller(NULL, 0, 0x10000, 0, 0x10000);
+		register_pci_controller(c);
+		tx4927_pcic_setup(tx4938_pcic1ptr, c, 0);
+	}
+	tx4938_setup_pcierr_irq();
+#endif /* CONFIG_PCI */
+}
+
+/* SPI support */
+
+/* chip select for SPI devices */
+#define SEEPROM1_CS	7	/* PIO7 */
+#define SEEPROM2_CS	0	/* IOC */
+#define SEEPROM3_CS	1	/* IOC */
+#define SRTC_CS 2	/* IOC */
+#define SPI_BUSNO	0
+
+static int __init rbtx4938_ethaddr_init(void)
+{
+#ifdef CONFIG_PCI
+	unsigned char dat[17];
+	unsigned char sum;
+	int i;
+
+	/* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
+	if (spi_eeprom_read(SPI_BUSNO, SEEPROM1_CS, 0, dat, sizeof(dat))) {
+		pr_err("seeprom: read error.\n");
+		return -ENODEV;
+	} else {
+		if (strcmp(dat, "MAC") != 0)
+			pr_warn("seeprom: bad signature.\n");
+		for (i = 0, sum = 0; i < sizeof(dat); i++)
+			sum += dat[i];
+		if (sum)
+			pr_warn("seeprom: bad checksum.\n");
+	}
+	tx4938_ethaddr_init(&dat[4], &dat[4 + 6]);
+#endif /* CONFIG_PCI */
+	return 0;
+}
+
+static void __init rbtx4938_spi_setup(void)
+{
+	/* set SPI_SEL */
+	txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_SPI_SEL);
+}
+
+static struct resource rbtx4938_fpga_resource;
+
+static void __init rbtx4938_time_init(void)
+{
+	tx4938_time_init(0);
+}
+
+static void __init rbtx4938_mem_setup(void)
+{
+	unsigned long long pcfg;
+
+	if (txx9_master_clock == 0)
+		txx9_master_clock = 25000000; /* 25MHz */
+
+	tx4938_setup();
+
+#ifdef CONFIG_PCI
+	txx9_alloc_pci_controller(&txx9_primary_pcic, 0, 0, 0, 0);
+	txx9_board_pcibios_setup = tx4927_pcibios_setup;
+#else
+	set_io_port_base(RBTX4938_ETHER_BASE);
+#endif
+
+	tx4938_sio_init(7372800, 0);
+
+#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61
+	pr_info("PIOSEL: disabling both ATA and NAND selection\n");
+	txx9_clear64(&tx4938_ccfgptr->pcfg,
+		     TX4938_PCFG_NDF_SEL | TX4938_PCFG_ATA_SEL);
+#endif
+
+#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND
+	pr_info("PIOSEL: enabling NAND selection\n");
+	txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL);
+	txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL);
+#endif
+
+#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA
+	pr_info("PIOSEL: enabling ATA selection\n");
+	txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL);
+	txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL);
+#endif
+
+#ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_KEEP
+	pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg);
+	pr_info("PIOSEL: NAND %s, ATA %s\n",
+		(pcfg & TX4938_PCFG_NDF_SEL) ? "enabled" : "disabled",
+		(pcfg & TX4938_PCFG_ATA_SEL) ? "enabled" : "disabled");
+#endif
+
+	rbtx4938_spi_setup();
+	pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg);	/* updated */
+	/* fixup piosel */
+	if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) ==
+	    TX4938_PCFG_ATA_SEL)
+		writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x04,
+		       rbtx4938_piosel_addr);
+	else if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) ==
+		 TX4938_PCFG_NDF_SEL)
+		writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x08,
+		       rbtx4938_piosel_addr);
+	else
+		writeb(readb(rbtx4938_piosel_addr) & ~(0x08 | 0x04),
+		       rbtx4938_piosel_addr);
+
+	rbtx4938_fpga_resource.name = "FPGA Registers";
+	rbtx4938_fpga_resource.start = CPHYSADDR(RBTX4938_FPGA_REG_ADDR);
+	rbtx4938_fpga_resource.end = CPHYSADDR(RBTX4938_FPGA_REG_ADDR) + 0xffff;
+	rbtx4938_fpga_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	if (request_resource(&txx9_ce_res[2], &rbtx4938_fpga_resource))
+		pr_err("request resource for fpga failed\n");
+
+	_machine_restart = rbtx4938_machine_restart;
+
+	writeb(0xff, rbtx4938_led_addr);
+	pr_info("RBTX4938 --- FPGA(Rev %02x) DIPSW:%02x,%02x\n",
+		readb(rbtx4938_fpga_rev_addr),
+		readb(rbtx4938_dipsw_addr), readb(rbtx4938_bdipsw_addr));
+}
+
+static void __init rbtx4938_ne_init(void)
+{
+	struct resource res[] = {
+		{
+			.start	= RBTX4938_RTL_8019_BASE,
+			.end	= RBTX4938_RTL_8019_BASE + 0x20 - 1,
+			.flags	= IORESOURCE_IO,
+		}, {
+			.start	= RBTX4938_RTL_8019_IRQ,
+			.flags	= IORESOURCE_IRQ,
+		}
+	};
+	platform_device_register_simple("ne", -1, res, ARRAY_SIZE(res));
+}
+
+static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock);
+
+static void rbtx4938_spi_gpio_set(struct gpio_chip *chip, unsigned int offset,
+				  int value)
+{
+	u8 val;
+	unsigned long flags;
+	spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags);
+	val = readb(rbtx4938_spics_addr);
+	if (value)
+		val |= 1 << offset;
+	else
+		val &= ~(1 << offset);
+	writeb(val, rbtx4938_spics_addr);
+	mmiowb();
+	spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags);
+}
+
+static int rbtx4938_spi_gpio_dir_out(struct gpio_chip *chip,
+				     unsigned int offset, int value)
+{
+	rbtx4938_spi_gpio_set(chip, offset, value);
+	return 0;
+}
+
+static struct gpio_chip rbtx4938_spi_gpio_chip = {
+	.set = rbtx4938_spi_gpio_set,
+	.direction_output = rbtx4938_spi_gpio_dir_out,
+	.label = "RBTX4938-SPICS",
+	.base = 16,
+	.ngpio = 3,
+};
+
+static int __init rbtx4938_spi_init(void)
+{
+	struct spi_board_info srtc_info = {
+		.modalias = "rtc-rs5c348",
+		.max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */
+		.bus_num = 0,
+		.chip_select = 16 + SRTC_CS,
+		/* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS  */
+		.mode = SPI_MODE_1 | SPI_CS_HIGH,
+	};
+	spi_register_board_info(&srtc_info, 1);
+	spi_eeprom_register(SPI_BUSNO, SEEPROM1_CS, 128);
+	spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM2_CS, 128);
+	spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM3_CS, 128);
+	gpio_request(16 + SRTC_CS, "rtc-rs5c348");
+	gpio_direction_output(16 + SRTC_CS, 0);
+	gpio_request(SEEPROM1_CS, "seeprom1");
+	gpio_direction_output(SEEPROM1_CS, 1);
+	gpio_request(16 + SEEPROM2_CS, "seeprom2");
+	gpio_direction_output(16 + SEEPROM2_CS, 1);
+	gpio_request(16 + SEEPROM3_CS, "seeprom3");
+	gpio_direction_output(16 + SEEPROM3_CS, 1);
+	tx4938_spi_init(SPI_BUSNO);
+	return 0;
+}
+
+static void __init rbtx4938_mtd_init(void)
+{
+	struct physmap_flash_data pdata = {
+		.width = 4,
+	};
+
+	switch (readb(rbtx4938_bdipsw_addr) & 7) {
+	case 0:
+		/* Boot */
+		txx9_physmap_flash_init(0, 0x1fc00000, 0x400000, &pdata);
+		/* System */
+		txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata);
+		break;
+	case 1:
+		/* System */
+		txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata);
+		/* Boot */
+		txx9_physmap_flash_init(1, 0x1ec00000, 0x400000, &pdata);
+		break;
+	case 2:
+		/* Ext */
+		txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata);
+		/* System */
+		txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata);
+		/* Boot */
+		txx9_physmap_flash_init(2, 0x1dc00000, 0x400000, &pdata);
+		break;
+	case 3:
+		/* Boot */
+		txx9_physmap_flash_init(1, 0x1bc00000, 0x400000, &pdata);
+		/* System */
+		txx9_physmap_flash_init(2, 0x1a000000, 0x1000000, &pdata);
+		break;
+	}
+}
+
+static void __init rbtx4938_arch_init(void)
+{
+	txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, TX4938_NUM_PIO);
+	gpiochip_add_data(&rbtx4938_spi_gpio_chip, NULL);
+	rbtx4938_pci_setup();
+	rbtx4938_spi_init();
+}
+
+static void __init rbtx4938_device_init(void)
+{
+	rbtx4938_ethaddr_init();
+	rbtx4938_ne_init();
+	tx4938_wdt_init();
+	rbtx4938_mtd_init();
+	/* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */
+	tx4938_ndfmc_init(10, 35);
+	tx4938_ata_init(RBTX4938_IRQ_IOC_ATA, 0, 1);
+	tx4938_dmac_init(0, 2);
+	tx4938_aclc_init();
+	platform_device_register_simple("txx9aclc-generic", -1, NULL, 0);
+	tx4938_sramc_init();
+	txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL);
+}
+
+struct txx9_board_vec rbtx4938_vec __initdata = {
+	.system = "Toshiba RBTX4938",
+	.prom_init = rbtx4938_prom_init,
+	.mem_setup = rbtx4938_mem_setup,
+	.irq_setup = rbtx4938_irq_setup,
+	.time_init = rbtx4938_time_init,
+	.device_init = rbtx4938_device_init,
+	.arch_init = rbtx4938_arch_init,
+#ifdef CONFIG_PCI
+	.pci_map_irq = rbtx4938_pci_map_irq,
+#endif
+};
diff --git a/arch/mips/txx9/rbtx4939/Makefile b/arch/mips/txx9/rbtx4939/Makefile
new file mode 100644
index 0000000..5c84625
--- /dev/null
+++ b/arch/mips/txx9/rbtx4939/Makefile
@@ -0,0 +1 @@
+obj-y	 += irq.o setup.o prom.o
diff --git a/arch/mips/txx9/rbtx4939/irq.c b/arch/mips/txx9/rbtx4939/irq.c
new file mode 100644
index 0000000..69a8061
--- /dev/null
+++ b/arch/mips/txx9/rbtx4939/irq.c
@@ -0,0 +1,95 @@
+/*
+ * Toshiba RBTX4939 interrupt routines
+ * Based on linux/arch/mips/txx9/rbtx4938/irq.c,
+ *	    and RBTX49xx patch from CELF patch archive.
+ *
+ * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation
+ * 2003-2005 (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/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/txx9/rbtx4939.h>
+
+/*
+ * RBTX4939 IOC controller definition
+ */
+
+static void rbtx4939_ioc_irq_unmask(struct irq_data *d)
+{
+	int ioc_nr = d->irq - RBTX4939_IRQ_IOC;
+
+	writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr);
+}
+
+static void rbtx4939_ioc_irq_mask(struct irq_data *d)
+{
+	int ioc_nr = d->irq - RBTX4939_IRQ_IOC;
+
+	writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr);
+	mmiowb();
+}
+
+static struct irq_chip rbtx4939_ioc_irq_chip = {
+	.name		= "IOC",
+	.irq_mask	= rbtx4939_ioc_irq_mask,
+	.irq_unmask	= rbtx4939_ioc_irq_unmask,
+};
+
+
+static inline int rbtx4939_ioc_irqroute(void)
+{
+	unsigned char istat = readb(rbtx4939_ifac2_addr);
+
+	if (unlikely(istat == 0))
+		return -1;
+	return RBTX4939_IRQ_IOC + __fls8(istat);
+}
+
+static int rbtx4939_irq_dispatch(int pending)
+{
+	int irq;
+
+	if (pending & CAUSEF_IP7)
+		return MIPS_CPU_IRQ_BASE + 7;
+	irq = tx4939_irq();
+	if (likely(irq >= 0)) {
+		/* redirect IOC interrupts */
+		switch (irq) {
+		case RBTX4939_IRQ_IOCINT:
+			irq = rbtx4939_ioc_irqroute();
+			break;
+		}
+	} else if (pending & CAUSEF_IP0)
+		irq = MIPS_CPU_IRQ_BASE + 0;
+	else if (pending & CAUSEF_IP1)
+		irq = MIPS_CPU_IRQ_BASE + 1;
+	else
+		irq = -1;
+	return irq;
+}
+
+void __init rbtx4939_irq_setup(void)
+{
+	int i;
+
+	/* mask all IOC interrupts */
+	writeb(0, rbtx4939_ien_addr);
+
+	/* clear SoftInt interrupts */
+	writeb(0, rbtx4939_softint_addr);
+
+	txx9_irq_dispatch = rbtx4939_irq_dispatch;
+
+	tx4939_irq_init();
+	for (i = RBTX4939_IRQ_IOC;
+	     i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++)
+		irq_set_chip_and_handler(i, &rbtx4939_ioc_irq_chip,
+					 handle_level_irq);
+
+	irq_set_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq);
+}
diff --git a/arch/mips/txx9/rbtx4939/prom.c b/arch/mips/txx9/rbtx4939/prom.c
new file mode 100644
index 0000000..bd277ec
--- /dev/null
+++ b/arch/mips/txx9/rbtx4939/prom.c
@@ -0,0 +1,17 @@
+/*
+ * rbtx4939 specific prom routines
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/rbtx4939.h>
+
+void __init rbtx4939_prom_init(void)
+{
+	tx4939_add_memory_regions();
+	txx9_sio_putchar_init(TX4939_SIO_REG(0) & 0xfffffffffULL);
+}
diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c
new file mode 100644
index 0000000..ef29a9c
--- /dev/null
+++ b/arch/mips/txx9/rbtx4939/setup.c
@@ -0,0 +1,554 @@
+/*
+ * Toshiba RBTX4939 setup routines.
+ * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
+ *	    and RBTX49xx patch from CELF patch archive.
+ *
+ * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation
+ * 2003-2005 (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/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/interrupt.h>
+#include <linux/smc91x.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/map.h>
+#include <asm/reboot.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/pci.h>
+#include <asm/txx9/rbtx4939.h>
+
+static void rbtx4939_machine_restart(char *command)
+{
+	local_irq_disable();
+	writeb(1, rbtx4939_reseten_addr);
+	writeb(1, rbtx4939_softreset_addr);
+	while (1)
+		;
+}
+
+static void __init rbtx4939_time_init(void)
+{
+	tx4939_time_init(0);
+}
+
+#if defined(__BIG_ENDIAN) && IS_ENABLED(CONFIG_SMC91X)
+#define HAVE_RBTX4939_IOSWAB
+#define IS_CE1_ADDR(addr) \
+	((((unsigned long)(addr) - IO_BASE) & 0xfff00000) == TXX9_CE(1))
+static u16 rbtx4939_ioswabw(volatile u16 *a, u16 x)
+{
+	return IS_CE1_ADDR(a) ? x : le16_to_cpu(x);
+}
+static u16 rbtx4939_mem_ioswabw(volatile u16 *a, u16 x)
+{
+	return !IS_CE1_ADDR(a) ? x : le16_to_cpu(x);
+}
+#endif /* __BIG_ENDIAN && CONFIG_SMC91X */
+
+static void __init rbtx4939_pci_setup(void)
+{
+#ifdef CONFIG_PCI
+	int extarb = !(__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCIARB);
+	struct pci_controller *c = &txx9_primary_pcic;
+
+	register_pci_controller(c);
+
+	tx4939_report_pciclk();
+	tx4927_pcic_setup(tx4939_pcicptr, c, extarb);
+	if (!(__raw_readq(&tx4939_ccfgptr->pcfg) & TX4939_PCFG_ATA1MODE) &&
+	    (__raw_readq(&tx4939_ccfgptr->pcfg) &
+	     (TX4939_PCFG_ET0MODE | TX4939_PCFG_ET1MODE))) {
+		tx4939_report_pci1clk();
+
+		/* mem:64K(max), io:64K(max) (enough for ETH0,ETH1) */
+		c = txx9_alloc_pci_controller(NULL, 0, 0x10000, 0, 0x10000);
+		register_pci_controller(c);
+		tx4927_pcic_setup(tx4939_pcic1ptr, c, 0);
+	}
+
+	tx4939_setup_pcierr_irq();
+#endif /* CONFIG_PCI */
+}
+
+static unsigned long long default_ebccr[] __initdata = {
+	0x01c0000000007608ULL, /* 64M ROM */
+	0x017f000000007049ULL, /* 1M IOC */
+	0x0180000000408608ULL, /* ISA */
+	0,
+};
+
+static void __init rbtx4939_ebusc_setup(void)
+{
+	int i;
+	unsigned int sp;
+
+	/* use user-configured speed */
+	sp = TX4939_EBUSC_CR(0) & 0x30;
+	default_ebccr[0] |= sp;
+	default_ebccr[1] |= sp;
+	default_ebccr[2] |= sp;
+	/* initialise by myself */
+	for (i = 0; i < ARRAY_SIZE(default_ebccr); i++) {
+		if (default_ebccr[i])
+			____raw_writeq(default_ebccr[i],
+				       &tx4939_ebuscptr->cr[i]);
+		else
+			____raw_writeq(____raw_readq(&tx4939_ebuscptr->cr[i])
+				       & ~8,
+				       &tx4939_ebuscptr->cr[i]);
+	}
+}
+
+static void __init rbtx4939_update_ioc_pen(void)
+{
+	__u64 pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg);
+	__u64 ccfg = ____raw_readq(&tx4939_ccfgptr->ccfg);
+	__u8 pe1 = readb(rbtx4939_pe1_addr);
+	__u8 pe2 = readb(rbtx4939_pe2_addr);
+	__u8 pe3 = readb(rbtx4939_pe3_addr);
+	if (pcfg & TX4939_PCFG_ATA0MODE)
+		pe1 |= RBTX4939_PE1_ATA(0);
+	else
+		pe1 &= ~RBTX4939_PE1_ATA(0);
+	if (pcfg & TX4939_PCFG_ATA1MODE) {
+		pe1 |= RBTX4939_PE1_ATA(1);
+		pe1 &= ~(RBTX4939_PE1_RMII(0) | RBTX4939_PE1_RMII(1));
+	} else {
+		pe1 &= ~RBTX4939_PE1_ATA(1);
+		if (pcfg & TX4939_PCFG_ET0MODE)
+			pe1 |= RBTX4939_PE1_RMII(0);
+		else
+			pe1 &= ~RBTX4939_PE1_RMII(0);
+		if (pcfg & TX4939_PCFG_ET1MODE)
+			pe1 |= RBTX4939_PE1_RMII(1);
+		else
+			pe1 &= ~RBTX4939_PE1_RMII(1);
+	}
+	if (ccfg & TX4939_CCFG_PTSEL)
+		pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_P |
+			 RBTX4939_PE3_VP_S);
+	else {
+		__u64 vmode = pcfg &
+			(TX4939_PCFG_VSSMODE | TX4939_PCFG_VPSMODE);
+		if (vmode == 0)
+			pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_P |
+				 RBTX4939_PE3_VP_S);
+		else if (vmode == TX4939_PCFG_VPSMODE) {
+			pe3 |= RBTX4939_PE3_VP_P;
+			pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_S);
+		} else if (vmode == TX4939_PCFG_VSSMODE) {
+			pe3 |= RBTX4939_PE3_VP | RBTX4939_PE3_VP_S;
+			pe3 &= ~RBTX4939_PE3_VP_P;
+		} else {
+			pe3 |= RBTX4939_PE3_VP | RBTX4939_PE3_VP_P;
+			pe3 &= ~RBTX4939_PE3_VP_S;
+		}
+	}
+	if (pcfg & TX4939_PCFG_SPIMODE) {
+		if (pcfg & TX4939_PCFG_SIO2MODE_GPIO)
+			pe2 &= ~(RBTX4939_PE2_SIO2 | RBTX4939_PE2_SIO0);
+		else {
+			if (pcfg & TX4939_PCFG_SIO2MODE_SIO2) {
+				pe2 |= RBTX4939_PE2_SIO2;
+				pe2 &= ~RBTX4939_PE2_SIO0;
+			} else {
+				pe2 |= RBTX4939_PE2_SIO0;
+				pe2 &= ~RBTX4939_PE2_SIO2;
+			}
+		}
+		if (pcfg & TX4939_PCFG_SIO3MODE)
+			pe2 |= RBTX4939_PE2_SIO3;
+		else
+			pe2 &= ~RBTX4939_PE2_SIO3;
+		pe2 &= ~RBTX4939_PE2_SPI;
+	} else {
+		pe2 |= RBTX4939_PE2_SPI;
+		pe2 &= ~(RBTX4939_PE2_SIO3 | RBTX4939_PE2_SIO2 |
+			 RBTX4939_PE2_SIO0);
+	}
+	if ((pcfg & TX4939_PCFG_I2SMODE_MASK) == TX4939_PCFG_I2SMODE_GPIO)
+		pe2 |= RBTX4939_PE2_GPIO;
+	else
+		pe2 &= ~RBTX4939_PE2_GPIO;
+	writeb(pe1, rbtx4939_pe1_addr);
+	writeb(pe2, rbtx4939_pe2_addr);
+	writeb(pe3, rbtx4939_pe3_addr);
+}
+
+#define RBTX4939_MAX_7SEGLEDS	8
+
+#if IS_BUILTIN(CONFIG_LEDS_CLASS)
+static u8 led_val[RBTX4939_MAX_7SEGLEDS];
+struct rbtx4939_led_data {
+	struct led_classdev cdev;
+	char name[32];
+	unsigned int num;
+};
+
+/* Use "dot" in 7seg LEDs */
+static void rbtx4939_led_brightness_set(struct led_classdev *led_cdev,
+					enum led_brightness value)
+{
+	struct rbtx4939_led_data *led_dat =
+		container_of(led_cdev, struct rbtx4939_led_data, cdev);
+	unsigned int num = led_dat->num;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	led_val[num] = (led_val[num] & 0x7f) | (value ? 0x80 : 0);
+	writeb(led_val[num], rbtx4939_7seg_addr(num / 4, num % 4));
+	local_irq_restore(flags);
+}
+
+static int __init rbtx4939_led_probe(struct platform_device *pdev)
+{
+	struct rbtx4939_led_data *leds_data;
+	int i;
+	static char *default_triggers[] __initdata = {
+		"heartbeat",
+		"disk-activity",
+		"nand-disk",
+	};
+
+	leds_data = kcalloc(RBTX4939_MAX_7SEGLEDS, sizeof(*leds_data),
+			    GFP_KERNEL);
+	if (!leds_data)
+		return -ENOMEM;
+	for (i = 0; i < RBTX4939_MAX_7SEGLEDS; i++) {
+		int rc;
+		struct rbtx4939_led_data *led_dat = &leds_data[i];
+
+		led_dat->num = i;
+		led_dat->cdev.brightness_set = rbtx4939_led_brightness_set;
+		sprintf(led_dat->name, "rbtx4939:amber:%u", i);
+		led_dat->cdev.name = led_dat->name;
+		if (i < ARRAY_SIZE(default_triggers))
+			led_dat->cdev.default_trigger = default_triggers[i];
+		rc = led_classdev_register(&pdev->dev, &led_dat->cdev);
+		if (rc < 0)
+			return rc;
+		led_dat->cdev.brightness_set(&led_dat->cdev, 0);
+	}
+	return 0;
+
+}
+
+static struct platform_driver rbtx4939_led_driver = {
+	.driver	 = {
+		.name = "rbtx4939-led",
+	},
+};
+
+static void __init rbtx4939_led_setup(void)
+{
+	platform_device_register_simple("rbtx4939-led", -1, NULL, 0);
+	platform_driver_probe(&rbtx4939_led_driver, rbtx4939_led_probe);
+}
+#else
+static inline void rbtx4939_led_setup(void)
+{
+}
+#endif
+
+static void __rbtx4939_7segled_putc(unsigned int pos, unsigned char val)
+{
+#if IS_BUILTIN(CONFIG_LEDS_CLASS)
+	unsigned long flags;
+	local_irq_save(flags);
+	/* bit7: reserved for LED class */
+	led_val[pos] = (led_val[pos] & 0x80) | (val & 0x7f);
+	val = led_val[pos];
+	local_irq_restore(flags);
+#endif
+	writeb(val, rbtx4939_7seg_addr(pos / 4, pos % 4));
+}
+
+static void rbtx4939_7segled_putc(unsigned int pos, unsigned char val)
+{
+	/* convert from map_to_seg7() notation */
+	val = (val & 0x88) |
+		((val & 0x40) >> 6) |
+		((val & 0x20) >> 4) |
+		((val & 0x10) >> 2) |
+		((val & 0x04) << 2) |
+		((val & 0x02) << 4) |
+		((val & 0x01) << 6);
+	__rbtx4939_7segled_putc(pos, val);
+}
+
+#if IS_ENABLED(CONFIG_MTD_RBTX4939)
+/* special mapping for boot rom */
+static unsigned long rbtx4939_flash_fixup_ofs(unsigned long ofs)
+{
+	u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
+	unsigned char shift;
+
+	if (bdipsw & 8) {
+		/* BOOT Mode: USER ROM1 / USER ROM2 */
+		shift = bdipsw & 3;
+		/* rotate A[23:22] */
+		return (ofs & ~0xc00000) | ((((ofs >> 22) + shift) & 3) << 22);
+	}
+#ifdef __BIG_ENDIAN
+	if (bdipsw == 0)
+		/* BOOT Mode: Monitor ROM */
+		ofs ^= 0x400000;	/* swap A[22] */
+#endif
+	return ofs;
+}
+
+static map_word rbtx4939_flash_read16(struct map_info *map, unsigned long ofs)
+{
+	map_word r;
+
+	ofs = rbtx4939_flash_fixup_ofs(ofs);
+	r.x[0] = __raw_readw(map->virt + ofs);
+	return r;
+}
+
+static void rbtx4939_flash_write16(struct map_info *map, const map_word datum,
+				   unsigned long ofs)
+{
+	ofs = rbtx4939_flash_fixup_ofs(ofs);
+	__raw_writew(datum.x[0], map->virt + ofs);
+	mb();	/* see inline_map_write() in mtd/map.h */
+}
+
+static void rbtx4939_flash_copy_from(struct map_info *map, void *to,
+				     unsigned long from, ssize_t len)
+{
+	u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
+	unsigned char shift;
+	ssize_t curlen;
+
+	from += (unsigned long)map->virt;
+	if (bdipsw & 8) {
+		/* BOOT Mode: USER ROM1 / USER ROM2 */
+		shift = bdipsw & 3;
+		while (len) {
+			curlen = min_t(unsigned long, len,
+				     0x400000 - (from & (0x400000 - 1)));
+			memcpy(to,
+			       (void *)((from & ~0xc00000) |
+					((((from >> 22) + shift) & 3) << 22)),
+			       curlen);
+			len -= curlen;
+			from += curlen;
+			to += curlen;
+		}
+		return;
+	}
+#ifdef __BIG_ENDIAN
+	if (bdipsw == 0) {
+		/* BOOT Mode: Monitor ROM */
+		while (len) {
+			curlen = min_t(unsigned long, len,
+				     0x400000 - (from & (0x400000 - 1)));
+			memcpy(to, (void *)(from ^ 0x400000), curlen);
+			len -= curlen;
+			from += curlen;
+			to += curlen;
+		}
+		return;
+	}
+#endif
+	memcpy(to, (void *)from, len);
+}
+
+static void rbtx4939_flash_map_init(struct map_info *map)
+{
+	map->read = rbtx4939_flash_read16;
+	map->write = rbtx4939_flash_write16;
+	map->copy_from = rbtx4939_flash_copy_from;
+}
+
+static void __init rbtx4939_mtd_init(void)
+{
+	static struct {
+		struct platform_device dev;
+		struct resource res;
+		struct rbtx4939_flash_data data;
+	} pdevs[4];
+	int i;
+	static char names[4][8];
+	static struct mtd_partition parts[4];
+	struct rbtx4939_flash_data *boot_pdata = &pdevs[0].data;
+	u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
+
+	if (bdipsw & 8) {
+		/* BOOT Mode: USER ROM1 / USER ROM2 */
+		boot_pdata->nr_parts = 4;
+		for (i = 0; i < boot_pdata->nr_parts; i++) {
+			sprintf(names[i], "img%d", 4 - i);
+			parts[i].name = names[i];
+			parts[i].size = 0x400000;
+			parts[i].offset = MTDPART_OFS_NXTBLK;
+		}
+	} else if (bdipsw == 0) {
+		/* BOOT Mode: Monitor ROM */
+		boot_pdata->nr_parts = 2;
+		strcpy(names[0], "big");
+		strcpy(names[1], "little");
+		for (i = 0; i < boot_pdata->nr_parts; i++) {
+			parts[i].name = names[i];
+			parts[i].size = 0x400000;
+			parts[i].offset = MTDPART_OFS_NXTBLK;
+		}
+	} else {
+		/* BOOT Mode: ROM Emulator */
+		boot_pdata->nr_parts = 2;
+		parts[0].name = "boot";
+		parts[0].offset = 0xc00000;
+		parts[0].size = 0x400000;
+		parts[1].name = "user";
+		parts[1].offset = 0;
+		parts[1].size = 0xc00000;
+	}
+	boot_pdata->parts = parts;
+	boot_pdata->map_init = rbtx4939_flash_map_init;
+
+	for (i = 0; i < ARRAY_SIZE(pdevs); i++) {
+		struct resource *r = &pdevs[i].res;
+		struct platform_device *dev = &pdevs[i].dev;
+
+		r->start = 0x1f000000 - i * 0x1000000;
+		r->end = r->start + 0x1000000 - 1;
+		r->flags = IORESOURCE_MEM;
+		pdevs[i].data.width = 2;
+		dev->num_resources = 1;
+		dev->resource = r;
+		dev->id = i;
+		dev->name = "rbtx4939-flash";
+		dev->dev.platform_data = &pdevs[i].data;
+		platform_device_register(dev);
+	}
+}
+#else
+static void __init rbtx4939_mtd_init(void)
+{
+}
+#endif
+
+static void __init rbtx4939_arch_init(void)
+{
+	rbtx4939_pci_setup();
+}
+
+static void __init rbtx4939_device_init(void)
+{
+	unsigned long smc_addr = RBTX4939_ETHER_ADDR - IO_BASE;
+	struct resource smc_res[] = {
+		{
+			.start	= smc_addr,
+			.end	= smc_addr + 0x10 - 1,
+			.flags	= IORESOURCE_MEM,
+		}, {
+			.start	= RBTX4939_IRQ_ETHER,
+			/* override default irq flag defined in smc91x.h */
+			.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+		},
+	};
+	struct smc91x_platdata smc_pdata = {
+		.flags = SMC91X_USE_16BIT,
+	};
+	struct platform_device *pdev;
+#if IS_ENABLED(CONFIG_TC35815)
+	int i, j;
+	unsigned char ethaddr[2][6];
+	u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
+
+	for (i = 0; i < 2; i++) {
+		unsigned long area = CKSEG1 + 0x1fff0000 + (i * 0x10);
+		if (bdipsw == 0)
+			memcpy(ethaddr[i], (void *)area, 6);
+		else {
+			u16 buf[3];
+			if (bdipsw & 8)
+				area -= 0x03000000;
+			else
+				area -= 0x01000000;
+			for (j = 0; j < 3; j++)
+				buf[j] = le16_to_cpup((u16 *)(area + j * 2));
+			memcpy(ethaddr[i], buf, 6);
+		}
+	}
+	tx4939_ethaddr_init(ethaddr[0], ethaddr[1]);
+#endif
+	pdev = platform_device_alloc("smc91x", -1);
+	if (!pdev ||
+	    platform_device_add_resources(pdev, smc_res, ARRAY_SIZE(smc_res)) ||
+	    platform_device_add_data(pdev, &smc_pdata, sizeof(smc_pdata)) ||
+	    platform_device_add(pdev))
+		platform_device_put(pdev);
+	rbtx4939_mtd_init();
+	/* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */
+	tx4939_ndfmc_init(10, 35,
+			  (1 << 1) | (1 << 2),
+			  (1 << 2)); /* ch1:8bit, ch2:16bit */
+	rbtx4939_led_setup();
+	tx4939_wdt_init();
+	tx4939_ata_init();
+	tx4939_rtc_init();
+	tx4939_dmac_init(0, 2);
+	tx4939_aclc_init();
+	platform_device_register_simple("txx9aclc-generic", -1, NULL, 0);
+	tx4939_sramc_init();
+	tx4939_rng_init();
+}
+
+static void __init rbtx4939_setup(void)
+{
+	int i;
+
+	rbtx4939_ebusc_setup();
+	/* always enable ATA0 */
+	txx9_set64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_ATA0MODE);
+	if (txx9_master_clock == 0)
+		txx9_master_clock = 20000000;
+	tx4939_setup();
+	rbtx4939_update_ioc_pen();
+#ifdef HAVE_RBTX4939_IOSWAB
+	ioswabw = rbtx4939_ioswabw;
+	__mem_ioswabw = rbtx4939_mem_ioswabw;
+#endif
+
+	_machine_restart = rbtx4939_machine_restart;
+
+	txx9_7segled_init(RBTX4939_MAX_7SEGLEDS, rbtx4939_7segled_putc);
+	for (i = 0; i < RBTX4939_MAX_7SEGLEDS; i++)
+		txx9_7segled_putc(i, '-');
+	pr_info("RBTX4939 (Rev %02x) --- FPGA(Rev %02x) DIPSW:%02x,%02x\n",
+		readb(rbtx4939_board_rev_addr), readb(rbtx4939_ioc_rev_addr),
+		readb(rbtx4939_udipsw_addr), readb(rbtx4939_bdipsw_addr));
+
+#ifdef CONFIG_PCI
+	txx9_alloc_pci_controller(&txx9_primary_pcic, 0, 0, 0, 0);
+	txx9_board_pcibios_setup = tx4927_pcibios_setup;
+#else
+	set_io_port_base(RBTX4939_ETHER_BASE);
+#endif
+
+	tx4939_sio_init(TX4939_SCLK0(txx9_master_clock), 0);
+}
+
+struct txx9_board_vec rbtx4939_vec __initdata = {
+	.system = "Toshiba RBTX4939",
+	.prom_init = rbtx4939_prom_init,
+	.mem_setup = rbtx4939_setup,
+	.irq_setup = rbtx4939_irq_setup,
+	.time_init = rbtx4939_time_init,
+	.device_init = rbtx4939_device_init,
+	.arch_init = rbtx4939_arch_init,
+#ifdef CONFIG_PCI
+	.pci_map_irq = tx4939_pci_map_irq,
+#endif
+};