summary refs log tree commit diff
path: root/arch/mips/pmc-sierra
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/pmc-sierra')
-rw-r--r--arch/mips/pmc-sierra/yosemite/Makefile8
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c171
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h69
-rw-r--r--arch/mips/pmc-sierra/yosemite/dbg_io.c180
-rw-r--r--arch/mips/pmc-sierra/yosemite/ht-irq.c53
-rw-r--r--arch/mips/pmc-sierra/yosemite/ht.c454
-rw-r--r--arch/mips/pmc-sierra/yosemite/i2c-yosemite.c188
-rw-r--r--arch/mips/pmc-sierra/yosemite/i2c-yosemite.h96
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq-handler.S93
-rw-r--r--arch/mips/pmc-sierra/yosemite/irq.c167
-rw-r--r--arch/mips/pmc-sierra/yosemite/prom.c141
-rw-r--r--arch/mips/pmc-sierra/yosemite/py-console.c114
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.c235
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.h32
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c172
15 files changed, 2173 insertions, 0 deletions
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
new file mode 100644
index 000000000000..ae96a71a3089
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the PMC-Sierra Titan
+#
+
+obj-y    += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o
+
+obj-$(CONFIG_KGDB)		+= dbg_io.o
+obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
new file mode 100644
index 000000000000..b067988614c3
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
@@ -0,0 +1,171 @@
+/*
+ *  arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
+ *
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.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.
+ */
+
+/*
+ * Description:
+ *
+ * This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL
+ * 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program
+ * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are 
+ * expected to have a connectivity from the EEPROM to the serial port. This program does
+ * __not__ communicate using the I2C protocol
+ */
+
+#include "atmel_read_eeprom.h"
+
+static void delay(int delay)
+{
+	while (delay--);
+}
+
+static void send_bit(unsigned char bit)
+{
+	scl_lo;
+	delay(TXX);
+	if (bit)
+		sda_hi;
+	else
+		sda_lo;
+
+	delay(TXX);
+	scl_hi;
+	delay(TXX);
+}
+
+static void send_ack(void)
+{
+	send_bit(0);
+}
+
+static void send_byte(unsigned char byte)
+{
+	int	i = 0;
+	
+	for (i = 7; i >= 0; i--) 
+		send_bit((byte >> i) & 0x01);
+}
+	
+static void send_start(void)
+{
+	sda_hi; 
+	delay(TXX);
+	scl_hi;
+	delay(TXX);
+	sda_lo;
+	delay(TXX);
+}
+
+static void send_stop(void)
+{
+	sda_lo;
+	delay(TXX);
+	scl_hi;
+	delay(TXX);
+	sda_hi;
+	delay(TXX);
+}
+
+static void do_idle(void)
+{
+	sda_hi;
+	scl_hi;
+	vcc_off;
+}
+
+static int recv_bit(void)
+{
+	int	status;
+
+	scl_lo;
+	delay(TXX);
+	sda_hi;
+	delay(TXX);
+	scl_hi;
+	delay(TXX);
+
+	return 1;
+}
+
+static unsigned char recv_byte(void) {
+        int i;
+        unsigned char byte=0;
+
+        for (i=7;i>=0;i--)                             
+                byte |= (recv_bit() << i);
+ 
+        return byte;
+}
+
+static int recv_ack(void)
+{
+	unsigned int	ack;
+
+	ack = (unsigned int)recv_bit();
+	scl_lo;
+
+	if (ack) {
+		do_idle();
+		printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM \n");
+		return -1;
+	}
+
+	return ack;
+}
+
+/*
+ * This function does the actual read of the EEPROM. It needs the buffer into which the
+ * read data is copied, the size of the EEPROM being read and the buffer size
+ */
+int read_eeprom(char *buffer, int eeprom_size, int size)
+{
+	int	i = 0, err;
+
+	send_start();
+	send_byte(W_HEADER);
+	recv_ack();
+
+	/* EEPROM with size of more then 2K need two byte addressing */
+	if (eeprom_size > 2048) {
+		send_byte(0x00);
+		recv_ack();
+	}
+
+	send_start();
+	send_byte(R_HEADER);
+	err = recv_ack();
+	if (err == -1)
+		return err;
+
+	for (i = 0; i < size; i++) {
+		*buffer++ = recv_byte();
+		send_ack();
+	}
+
+	/* Note : We should do some check if the buffer contains correct information */
+
+	send_stop();
+}
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
new file mode 100644
index 000000000000..d27566d99ffc
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h
@@ -0,0 +1,69 @@
+/*
+ *  arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
+ *
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *  Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  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.
+ */
+
+/*
+ * Header file for atmel_read_eeprom.c 
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <linux/init.h>
+#include <asm/termios.h>
+#include <asm/ioctls.h>
+#include <linux/ioctl.h>
+#include <linux/fcntl.h>
+
+#define	DEFAULT_PORT 	"/dev/ttyS0"	/* Port to open */
+#define	TXX		0 		/* Dummy loop for spinning */
+
+#define	BLOCK_SEL	0x00		
+#define	SLAVE_ADDR	0xa0
+#define	READ_BIT	0x01
+#define	WRITE_BIT	0x00
+#define	R_HEADER	SLAVE_ADDR + BLOCK_SEL + READ_BIT
+#define	W_HEADER	SLAVE_ADDR + BLOCK_SEL + WRITE_BIT
+
+/*
+ * Clock, Voltages and Data
+ */
+#define	vcc_off		(ioctl(fd, TIOCSBRK, 0))
+#define	vcc_on		(ioctl(fd, TIOCCBRK, 0))
+#define	sda_hi		(ioctl(fd, TIOCMBIS, &dtr))
+#define	sda_lo		(ioctl(fd, TIOCMBIC, &dtr))
+#define	scl_lo		(ioctl(fd, TIOCMBIC, &rts))
+#define	scl_hi		(ioctl(fd, TIOCMBIS, &rts))
+
+const char rts = TIOCM_RTS;
+const char dtr = TIOCM_DTR;
+int fd;
+
diff --git a/arch/mips/pmc-sierra/yosemite/dbg_io.c b/arch/mips/pmc-sierra/yosemite/dbg_io.c
new file mode 100644
index 000000000000..0f659c9106ac
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/dbg_io.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.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.
+ */
+
+/*
+ * Support for KGDB for the Yosemite board. We make use of single serial
+ * port to be used for KGDB as well as console. The second serial port
+ * seems to be having a problem. Single IRQ is allocated for both the
+ * ports. Hence, the interrupt routing code needs to figure out whether
+ * the interrupt came from channel A or B.
+ */
+
+#include <asm/serial.h>
+
+/*
+ * Baud rate, Parity, Data and Stop bit settings for the
+ * serial port on the Yosemite. Note that the Early printk
+ * patch has been added. So, we should be all set to go
+ */
+#define	YOSEMITE_BAUD_2400	2400
+#define	YOSEMITE_BAUD_4800	4800
+#define	YOSEMITE_BAUD_9600	9600
+#define	YOSEMITE_BAUD_19200	19200
+#define	YOSEMITE_BAUD_38400	38400
+#define	YOSEMITE_BAUD_57600	57600
+#define	YOSEMITE_BAUD_115200	115200
+
+#define	YOSEMITE_PARITY_NONE	0
+#define	YOSEMITE_PARITY_ODD	0x08
+#define	YOSEMITE_PARITY_EVEN	0x18
+#define	YOSEMITE_PARITY_MARK	0x28
+#define	YOSEMITE_PARITY_SPACE	0x38
+
+#define	YOSEMITE_DATA_5BIT	0x0
+#define	YOSEMITE_DATA_6BIT	0x1
+#define	YOSEMITE_DATA_7BIT	0x2
+#define	YOSEMITE_DATA_8BIT	0x3
+
+#define	YOSEMITE_STOP_1BIT	0x0
+#define	YOSEMITE_STOP_2BIT	0x4
+
+/* This is crucial */
+#define	SERIAL_REG_OFS		0x1
+
+#define	SERIAL_RCV_BUFFER	0x0
+#define	SERIAL_TRANS_HOLD	0x0
+#define	SERIAL_SEND_BUFFER	0x0
+#define	SERIAL_INTR_ENABLE	(1 * SERIAL_REG_OFS)
+#define	SERIAL_INTR_ID		(2 * SERIAL_REG_OFS)
+#define	SERIAL_DATA_FORMAT	(3 * SERIAL_REG_OFS)
+#define	SERIAL_LINE_CONTROL	(3 * SERIAL_REG_OFS)
+#define	SERIAL_MODEM_CONTROL	(4 * SERIAL_REG_OFS)
+#define	SERIAL_RS232_OUTPUT	(4 * SERIAL_REG_OFS)
+#define	SERIAL_LINE_STATUS	(5 * SERIAL_REG_OFS)
+#define	SERIAL_MODEM_STATUS	(6 * SERIAL_REG_OFS)
+#define	SERIAL_RS232_INPUT	(6 * SERIAL_REG_OFS)
+#define	SERIAL_SCRATCH_PAD	(7 * SERIAL_REG_OFS)
+
+#define	SERIAL_DIVISOR_LSB	(0 * SERIAL_REG_OFS)
+#define	SERIAL_DIVISOR_MSB	(1 * SERIAL_REG_OFS)
+
+/*
+ * Functions to READ and WRITE to serial port 0
+ */
+#define	SERIAL_READ(ofs)		(*((volatile unsigned char*)	\
+					(TITAN_SERIAL_BASE + ofs)))
+
+#define	SERIAL_WRITE(ofs, val)		((*((volatile unsigned char*)	\
+					(TITAN_SERIAL_BASE + ofs))) = val)
+
+/*
+ * Functions to READ and WRITE to serial port 1
+ */
+#define	SERIAL_READ_1(ofs)		(*((volatile unsigned char*)	\
+					(TITAN_SERIAL_BASE_1 + ofs)
+
+#define	SERIAL_WRITE_1(ofs, val)	((*((volatile unsigned char*)	\
+					(TITAN_SERIAL_BASE_1 + ofs))) = val)
+
+/*
+ * Second serial port initialization
+ */
+void init_second_port(void)
+{
+	/* Disable Interrupts */
+	SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
+	SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0x0);
+
+	{
+		unsigned int divisor;
+
+		SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x80);
+		divisor = TITAN_SERIAL_BASE_BAUD / YOSEMITE_BAUD_115200;
+		SERIAL_WRITE_1(SERIAL_DIVISOR_LSB, divisor & 0xff);
+
+		SERIAL_WRITE_1(SERIAL_DIVISOR_MSB,
+			       (divisor & 0xff00) >> 8);
+		SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
+	}
+
+	SERIAL_WRITE_1(SERIAL_DATA_FORMAT, YOSEMITE_DATA_8BIT |
+		       YOSEMITE_PARITY_NONE | YOSEMITE_STOP_1BIT);
+
+	/* Enable Interrupts */
+	SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0xf);
+}
+
+/* Initialize the serial port for KGDB debugging */
+void debugInit(unsigned int baud, unsigned char data, unsigned char parity,
+	       unsigned char stop)
+{
+	/* Disable Interrupts */
+	SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
+	SERIAL_WRITE(SERIAL_INTR_ENABLE, 0x0);
+
+	{
+		unsigned int divisor;
+
+		SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x80);
+
+		divisor = TITAN_SERIAL_BASE_BAUD / baud;
+		SERIAL_WRITE(SERIAL_DIVISOR_LSB, divisor & 0xff);
+
+		SERIAL_WRITE(SERIAL_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+		SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
+	}
+
+	SERIAL_WRITE(SERIAL_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+unsigned char getDebugChar(void)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(YOSEMITE_BAUD_115200,
+			  YOSEMITE_DATA_8BIT,
+			  YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
+	}
+
+	while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x1) == 0);
+	return SERIAL_READ(SERIAL_RCV_BUFFER);
+}
+
+int putDebugChar(unsigned char byte)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(YOSEMITE_BAUD_115200,
+			  YOSEMITE_DATA_8BIT,
+			  YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
+	}
+
+	while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x20) == 0);
+	SERIAL_WRITE(SERIAL_SEND_BUFFER, byte);
+
+	return 1;
+}
diff --git a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c
new file mode 100644
index 000000000000..d22c9ffe4914
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.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/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <asm/pci.h>
+
+/*
+ * HT Bus fixup for the Titan
+ * XXX IRQ values need to change based on the board layout
+ */
+void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus)
+{
+        struct pci_bus *current_bus = bus;
+        struct pci_dev *devices;
+        struct list_head *devices_link;
+
+	list_for_each(devices_link, &(current_bus->devices)) {
+                devices = pci_dev_b(devices_link);
+                if (devices == NULL)
+                        continue;
+	}
+
+	/*
+	 * PLX and SPKT related changes go here
+	 */
+
+}
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
new file mode 100644
index 000000000000..dad228d3a220
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/ht.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.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/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+
+#include <linux/init.h>
+#include <asm/titan_dep.h>
+
+#ifdef CONFIG_HYPERTRANSPORT
+
+
+/*
+ * This function check if the Hypertransport Link Initialization completed. If
+ * it did, then proceed further with scanning bus #2
+ */
+static __inline__ int check_titan_htlink(void)
+{
+        u32 val;
+
+        val = *(volatile uint32_t *)(RM9000x2_HTLINK_REG);
+        if (val & 0x00000020)
+                /* HT Link Initialization completed */
+                return 1;
+        else
+                return 0;
+}
+
+static int titan_ht_config_read_dword(struct pci_dev *device,
+                                             int offset, u32* val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                                        0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        RM9K_WRITE(address_reg, address);
+        RM9K_READ(data_reg, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int titan_ht_config_read_word(struct pci_dev *device,
+                                             int offset, u16* val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                                0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        if ((offset & 0x3) == 0)
+                offset = 0x2;
+        else
+                offset = 0x0;
+
+        RM9K_WRITE(address_reg, address);
+        RM9K_READ_16(data_reg + offset, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+u32 longswap(unsigned long l)
+{
+        unsigned char b1,b2,b3,b4;
+
+        b1 = l&255;
+        b2 = (l>>8)&255;
+        b3 = (l>>16)&255;
+        b4 = (l>>24)&255;
+
+        return ((b1<<24) + (b2<<16) + (b3<<8) + b4);
+}
+
+
+static int titan_ht_config_read_byte(struct pci_dev *device,
+                                             int offset, u8* val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+        int offset1;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                                        0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        RM9K_WRITE(address_reg, address);
+
+        if ((offset & 0x3) == 0) {
+                offset1 = 0x3;
+        }
+        if ((offset & 0x3) == 1) {
+                offset1 = 0x2;
+        }
+        if ((offset & 0x3) == 2) {
+                offset1 = 0x1;
+        }
+        if ((offset & 0x3) == 3) {
+                offset1 = 0x0;
+        }
+        RM9K_READ_8(data_reg + offset1, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int titan_ht_config_write_dword(struct pci_dev *device,
+                                             int offset, u8 val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                                        0x80000000 | 0x1;
+        else
+              address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        RM9K_WRITE(address_reg, address);
+        RM9K_WRITE(data_reg, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_write_word(struct pci_dev *device,
+                                             int offset, u8 val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        if ((offset & 0x3) == 0)
+                offset = 0x2;
+        else
+                offset = 0x0;
+
+        RM9K_WRITE(address_reg, address);
+        RM9K_WRITE_16(data_reg + offset, val);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_write_byte(struct pci_dev *device,
+                                             int offset, u8 val)
+{
+        int dev, bus, func;
+        uint32_t address_reg, data_reg;
+        uint32_t address;
+        int offset1;
+
+        bus = device->bus->number;
+        dev = PCI_SLOT(device->devfn);
+        func = PCI_FUNC(device->devfn);
+
+	/* XXX Need to change the Bus # */
+        if (bus > 2)
+                address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) |
+                                0x80000000 | 0x1;
+        else
+                address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000;
+
+        address_reg = RM9000x2_OCD_HTCFGA;
+        data_reg =  RM9000x2_OCD_HTCFGD;
+
+        RM9K_WRITE(address_reg, address);
+
+        if ((offset & 0x3) == 0) {
+             offset1 = 0x3;
+        }
+        if ((offset & 0x3) == 1) {
+             offset1 = 0x2;
+        }
+        if ((offset & 0x3) == 2) {
+             offset1 = 0x1;
+        }
+        if ((offset & 0x3) == 3) {
+            offset1 = 0x0;
+        }
+
+        RM9K_WRITE_8(data_reg + offset1, val);
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+static void titan_pcibios_set_master(struct pci_dev *dev)
+{
+        u16 cmd;
+        int bus = dev->bus->number;
+
+	if (check_titan_htlink())
+            titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
+
+	cmd |= PCI_COMMAND_MASTER;
+
+	if (check_titan_htlink())
+            titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
+}
+
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+        u16 cmd, old_cmd;
+        u8 tmp1;
+        int idx;
+        struct resource *r;
+        int bus = dev->bus->number;
+
+	if (check_titan_htlink())
+            titan_ht_config_read_word(dev, PCI_COMMAND, &cmd);
+
+	old_cmd = cmd;
+        for (idx = 0; idx < 6; idx++) {
+                r = &dev->resource[idx];
+                if (!r->start && r->end) {
+                        printk(KERN_ERR
+                               "PCI: Device %s not available because of "
+                               "resource collisions\n", pci_name(dev));
+                        return -EINVAL;
+                }
+                if (r->flags & IORESOURCE_IO)
+                        cmd |= PCI_COMMAND_IO;
+                if (r->flags & IORESOURCE_MEM)
+                        cmd |= PCI_COMMAND_MEMORY;
+        }
+        if (cmd != old_cmd) {
+		if (check_titan_htlink())
+                   titan_ht_config_write_word(dev, PCI_COMMAND, cmd);
+	}
+
+	if (check_titan_htlink())
+		titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1);
+
+	if (tmp1 != 8) {
+                printk(KERN_WARNING "PCI setting cache line size to 8 from "
+                       "%d\n", tmp1);
+	}
+
+	if (check_titan_htlink())
+		titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8);
+
+	if (check_titan_htlink())
+		titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1);
+
+	if (tmp1 < 32 || tmp1 == 0xff) {
+                printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n",
+                       tmp1);
+	}
+
+	if (check_titan_htlink())
+		titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32);
+
+	return 0;
+}
+
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+        return pcibios_enable_resources(dev);
+}
+
+
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                             struct resource *res, int resource)
+{
+        u32 new, check;
+        int reg;
+
+        return;
+
+        new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+        if (resource < 6) {
+                reg = PCI_BASE_ADDRESS_0 + 4 * resource;
+        } else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= IORESOURCE_ROM_ENABLE;
+                reg = dev->rom_base_reg;
+        } else {
+                /*
+                 * Somebody might have asked allocation of a non-standard
+                 * resource
+                 */
+                return;
+        }
+
+        pci_write_config_dword(dev, reg, new);
+        pci_read_config_dword(dev, reg, &check);
+        if ((new ^ check) &
+            ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
+             PCI_BASE_ADDRESS_MEM_MASK)) {
+                printk(KERN_ERR "PCI: Error while updating region "
+                       "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
+                       new, check);
+        }
+}
+
+
+void pcibios_align_resource(void *data, struct resource *res,
+                            unsigned long size, unsigned long align)
+{
+        struct pci_dev *dev = data;
+
+        if (res->flags & IORESOURCE_IO) {
+                unsigned long start = res->start;
+
+                /* We need to avoid collisions with `mirrored' VGA ports
+                   and other strange ISA hardware, so we always want the
+                   addresses kilobyte aligned.  */
+                if (size > 0x100) {
+                        printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+                               " (%ld bytes)\n", pci_name(dev),
+                                dev->resource - res, size);
+                }
+
+                start = (start + 1024 - 1) & ~(1024 - 1);
+                res->start = start;
+        }
+}
+
+struct pci_ops titan_pci_ops = {
+        titan_ht_config_read_byte,
+        titan_ht_config_read_word,
+        titan_ht_config_read_dword,
+        titan_ht_config_write_byte,
+        titan_ht_config_write_word,
+        titan_ht_config_write_dword
+};
+
+void __init pcibios_fixup_bus(struct pci_bus *c)
+{
+        titan_ht_pcibios_fixup_bus(c);
+}
+
+void __init pcibios_init(void)
+{
+
+        /* Reset PCI I/O and PCI MEM values */
+	/* XXX Need to add the proper values here */
+        ioport_resource.start = 0xe0000000;
+        ioport_resource.end   = 0xe0000000 + 0x20000000 - 1;
+        iomem_resource.start  = 0xc0000000;
+        iomem_resource.end    = 0xc0000000 + 0x20000000 - 1;
+
+	/* XXX Need to add bus values */
+        pci_scan_bus(2, &titan_pci_ops, NULL);
+        pci_scan_bus(3, &titan_pci_ops, NULL);
+}
+
+/*
+ * for parsing "pci=" kernel boot arguments.
+ */
+char *pcibios_setup(char *str)
+{
+        printk(KERN_INFO "rr: pcibios_setup\n");
+        /* Nothing to do for now.  */
+
+        return str;
+}
+
+unsigned __init int pcibios_assign_all_busses(void)
+{
+        /* We want to use the PCI bus detection done by PMON */
+        return 0;
+}
+
+#endif /* CONFIG_HYPERTRANSPORT */
diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c
new file mode 100644
index 000000000000..416da22b3bf4
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c
@@ -0,0 +1,188 @@
+/*
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.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.
+ */
+
+/*
+ * Detailed Description:
+ *
+ * This block implements the I2C interface to the slave devices like the
+ * Atmel 24C32 EEPROM and the MAX 1619 Sensors device. The I2C Master interface
+ * can be controlled by the SCMB block. And the SCMB block kicks in only when
+ * using the Ethernet Mode of operation and __not__ the SysAD mode
+ *
+ * The SCMB controls the two modes: MDIO and the I2C. The MDIO mode is used to
+ * communicate with the Quad-PHY from Marvel. The I2C is used to communicate
+ * with the I2C slave devices.  It seems that the driver does not explicitly
+ * deal with the control of SDA and SCL serial lines. So, the driver will set
+ * the slave address, drive the command and then the data.  The SCMB will then
+ * control the two serial lines as required.
+ *
+ * It seems the documents are very unclear abt this. Hence, I took some time
+ * out to write the desciption to have an idea of how the I2C can actually
+ * work. Currently, this Linux driver wont be integrated into the generic Linux
+ * I2C framework. And finally, the I2C interface is also known as the 2BI
+ * interface. 2BI means 2-bit interface referring to SDA and SCL serial lines
+ * respectively.
+ *
+ * - Manish Lachwani (12/09/2003)
+ */
+
+#include "i2c-yosemite.h"
+
+/*
+ * Poll the I2C interface for the BUSY bit.
+ */
+static int titan_i2c_poll(void)
+{
+	int i = 0;
+	unsigned long val = 0;
+
+	for (i = 0; i < TITAN_I2C_MAX_POLL; i++) {
+		val = TITAN_I2C_READ(TITAN_I2C_COMMAND);
+
+		if (!(val & 0x8000))
+			return 0;
+	}
+
+	return TITAN_I2C_ERR_TIMEOUT;
+}
+
+/*
+ * Execute the I2C command
+ */
+int titan_i2c_xfer(unsigned int slave_addr, titan_i2c_command * cmd,
+		   int size, unsigned int *addr)
+{
+	int loop = 0, bytes, i;
+	unsigned int *write_data, data, *read_data;
+	unsigned long reg_val, val;
+
+	write_data = cmd->data;
+	read_data = addr;
+
+	TITAN_I2C_WRITE(TITAN_I2C_SLAVE_ADDRESS, slave_addr);
+
+	if (cmd->type == TITAN_I2C_CMD_WRITE)
+		loop = cmd->write_size;
+	else
+		loop = size;
+
+	while (loop > 0) {
+		if ((cmd->type == TITAN_I2C_CMD_WRITE) ||
+		    (cmd->type == TITAN_I2C_CMD_READ_WRITE)) {
+
+			reg_val = TITAN_I2C_DATA;
+			for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW;
+			     ++i, write_data += 2, reg_val += 4) {
+				if (bytes < cmd->write_size) {
+					data = write_data[0];
+					++data;
+				}
+
+				if (bytes < cmd->write_size) {
+					data = write_data[1];
+					++data;
+				}
+
+				TITAN_I2C_WRITE(reg_val, data);
+			}
+		}
+
+		TITAN_I2C_WRITE(TITAN_I2C_COMMAND,
+				(unsigned int) (cmd->type << 13));
+		if (titan_i2c_poll() != TITAN_I2C_ERR_OK)
+			return TITAN_I2C_ERR_TIMEOUT;
+
+		if ((cmd->type == TITAN_I2C_CMD_READ) ||
+		    (cmd->type == TITAN_I2C_CMD_READ_WRITE)) {
+
+			reg_val = TITAN_I2C_DATA;
+			for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW;
+			     ++i, read_data += 2, reg_val += 4) {
+				data = TITAN_I2C_READ(reg_val);
+
+				if (bytes < size) {
+					read_data[0] = data & 0xff;
+					++bytes;
+				}
+
+				if (bytes < size) {
+					read_data[1] =
+					    ((data >> 8) & 0xff);
+					++bytes;
+				}
+			}
+		}
+
+		loop -= (TITAN_I2C_MAX_WORDS_PER_RW * 2);
+	}
+
+	/*
+	 * Read the Interrupt status and then return the appropriate error code
+	 */
+
+	val = TITAN_I2C_READ(TITAN_I2C_INTERRUPTS);
+	if (val & 0x0020)
+		return TITAN_I2C_ERR_ARB_LOST;
+
+	if (val & 0x0040)
+		return TITAN_I2C_ERR_NO_RESP;
+
+	if (val & 0x0080)
+		return TITAN_I2C_ERR_DATA_COLLISION;
+
+	return TITAN_I2C_ERR_OK;
+}
+
+/*
+ * Init the I2C subsystem of the PMC-Sierra Yosemite board
+ */
+int titan_i2c_init(titan_i2c_config * config)
+{
+	unsigned int val;
+
+	/*
+	 * Reset the SCMB and program into the I2C mode
+	 */
+	TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0xA000);
+	TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0x2000);
+
+	/*
+	 * Configure the filtera and clka values
+	 */
+	val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_A);
+	val |= ((val & ~(0xF000)) | ((config->filtera << 12) & 0xF000));
+	val |= ((val & ~(0x03FF)) | (config->clka & 0x03FF));
+	TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_A, val);
+
+	/*
+	 * Configure the filterb and clkb values
+	 */
+	val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_B);
+	val |= ((val & ~(0xF000)) | ((config->filterb << 12) & 0xF000));
+	val |= ((val & ~(0x03FF)) | (config->clkb & 0x03FF));
+	TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_B, val);
+
+	return TITAN_I2C_ERR_OK;
+}
diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
new file mode 100644
index 000000000000..31c5523276fa
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
@@ -0,0 +1,96 @@
+/*
+ *  arch/mips/pmc-sierra/yosemite/i2c-yosemite.h
+ *
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.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.
+ */
+
+#ifndef __I2C_YOSEMITE_H
+#define __I2C_YOSEMITE_H
+
+/* Read and Write operations to the chip */
+
+#define TITAN_I2C_BASE			0xbb000000	/* XXX Needs to change */
+
+#define	TITAN_I2C_WRITE(offset, data)	\
+					*(volatile unsigned long *)(TITAN_I2C_BASE + offset) = data
+
+#define	TITAN_I2C_READ(offset) *(volatile unsigned long *)(TITAN_I2C_BASE + offset)
+
+
+/* Local constansts*/
+#define TITAN_I2C_MAX_FILTER            15
+#define TITAN_I2C_MAX_CLK               1023
+#define TITAN_I2C_MAX_ARBF              15
+#define TITAN_I2C_MAX_NAK               15
+#define TITAN_I2C_MAX_MASTERCODE        7
+#define TITAN_I2C_MAX_WORDS_PER_RW      4
+#define TITAN_I2C_MAX_POLL		100
+
+/* Registers used for I2C work */
+#define TITAN_I2C_SCMB_CONTROL		0x0180	/* SCMB Control */
+#define TITAN_I2C_SCMB_CLOCK_A		0x0184	/* SCMB Clock A */
+#define TITAN_I2C_SCMB_CLOCK_B		0x0188	/* SCMB Clock B */
+#define	TITAN_I2C_CONFIG		0x01A0	/* I2C Config */
+#define TITAN_I2C_COMMAND		0x01A4	/* I2C Command */
+#define	TITAN_I2C_SLAVE_ADDRESS		0x01A8	/* I2C Slave Address */
+#define TITAN_I2C_DATA			0x01AC	/* I2C Data [15:0] */
+#define TITAN_I2C_INTERRUPTS		0x01BC	/* I2C Interrupts */
+
+/* Error */
+#define	TITAN_I2C_ERR_ARB_LOST		(-9220)
+#define	TITAN_I2C_ERR_NO_RESP		(-9221)
+#define	TITAN_I2C_ERR_DATA_COLLISION	(-9222)
+#define	TITAN_I2C_ERR_TIMEOUT		(-9223)
+#define	TITAN_I2C_ERR_OK		0
+
+/* I2C Command Type */
+typedef enum {
+	TITAN_I2C_CMD_WRITE = 0,
+	TITAN_I2C_CMD_READ = 1,
+	TITAN_I2C_CMD_READ_WRITE = 2
+} titan_i2c_cmd_type;
+
+/* I2C structures */
+typedef struct {
+	int filtera;		/* Register 0x0184, bits 15 - 12 */
+	int clka;		/* Register 0x0184, bits 9 - 0 */
+	int filterb;		/* Register 0x0188, bits 15 - 12 */
+	int clkb;		/* Register 0x0188, bits 9 - 0 */
+} titan_i2c_config;
+
+/* I2C command type */
+typedef struct {
+	titan_i2c_cmd_type type;	/* Type of command */
+	int num_arb;		/* Register 0x01a0, bits 15 - 12 */
+	int num_nak;		/* Register 0x01a0, bits 11 - 8 */
+	int addr_size;		/* Register 0x01a0, bit 7 */
+	int mst_code;		/* Register 0x01a0, bits 6 - 4 */
+	int arb_en;		/* Register 0x01a0, bit 1 */
+	int speed;		/* Register 0x01a0, bit 0 */
+	int slave_addr;		/* Register 0x01a8 */
+	int write_size;		/* Register 0x01a4, bits 10 - 8 */
+	unsigned int *data;	/* Register 0x01ac */
+} titan_i2c_command;
+
+#endif				/* __I2C_YOSEMITE_H */
diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S
new file mode 100644
index 000000000000..33b9c40d4f5c
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/irq-handler.S
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2003, 04 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com
+ * Copyright 2004 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * First-level interrupt router for the PMC-Sierra Titan board
+ *
+ * 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.
+ *
+ * Titan supports Hypertransport or PCI but not both. Hence, one interrupt
+ * line is shared between the PCI slot A and Hypertransport. This is the
+ * Processor INTB #0.
+ */
+
+#include <linux/config.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+		.align	5
+		NESTED(titan_handle_int, PT_SIZE, sp)
+		SAVE_ALL
+		CLI
+		.set	at
+		.set	noreorder
+		la	ra, ret_from_irq
+		mfc0	t0, CP0_CAUSE
+		mfc0	t2, CP0_STATUS
+
+		and	t0, t2
+
+		andi	t2, t0, STATUSF_IP7	/* INTB5 hardware line */
+		bnez	t2, ll_timer_irq	/* Timer */
+		andi	t1, t0, STATUSF_IP2	/* INTB0 hardware line */
+		bnez	t1, ll_pcia_irq		/* 64-bit PCI */
+		andi	t2, t0, STATUSF_IP3	/* INTB1 hardware line */
+		bnez	t2, ll_pcib_irq		/* second 64-bit PCI slot */
+		andi	t1, t0, STATUSF_IP4	/* INTB2 hardware line */
+		bnez	t1, ll_duart_irq	/* UART	*/
+		andi    t2, t0, STATUSF_IP5	/* SMP inter-core interrupts */
+		bnez    t2, ll_smp_irq
+		andi	t1, t0, STATUSF_IP6
+		bnez	t1, ll_ht_irq		/* Hypertransport */
+
+		move	a0, sp
+		j	do_extended_irq
+		END(titan_handle_int)
+
+		.set	reorder
+		.align	5
+
+ll_pcia_irq:
+		li	a0, 2
+		move	a1, sp
+#ifdef CONFIG_HYPERTRANSPORT
+		j	ll_ht_smp_irq_handler
+#else
+		j	do_IRQ
+#endif
+
+ll_pcib_irq:
+		li	a0, 3
+		move	a1, sp
+		j	do_IRQ
+
+ll_duart_irq:
+		li	a0, 4
+		move	a1, sp
+		j	do_IRQ
+
+ll_smp_irq:
+		li	a0, 5
+		move	a1, sp
+#ifdef CONFIG_SMP
+		j	titan_mailbox_irq
+#else
+		j	do_IRQ
+#endif
+
+ll_ht_irq:
+		li	a0, 6
+		move	a1, sp
+		j	ll_ht_smp_irq_handler
+
+ll_timer_irq:
+		li	a0, 7
+		move	a1, sp
+		j	do_IRQ
diff --git a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c
new file mode 100644
index 000000000000..f4e2897d9bf7
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/irq.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2003 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.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.
+ *
+ * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/titan_dep.h>
+
+/* Hypertransport specific */
+#define IRQ_ACK_BITS            0x00000000	/* Ack bits */
+
+#define HYPERTRANSPORT_INTA     0x78		/* INTA# */
+#define HYPERTRANSPORT_INTB     0x79		/* INTB# */
+#define HYPERTRANSPORT_INTC     0x7a		/* INTC# */
+#define HYPERTRANSPORT_INTD     0x7b		/* INTD# */
+
+extern asmlinkage void titan_handle_int(void);
+extern void jaguar_mailbox_irq(struct pt_regs *);
+
+/*
+ * Handle hypertransport & SMP interrupts. The interrupt lines are scarce.
+ * For interprocessor interrupts, the best thing to do is to use the INTMSG
+ * register. We use the same external interrupt line, i.e. INTB3 and monitor
+ * another status bit
+ */
+asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs)
+{
+	u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4);
+
+	/* Ack all the bits that correspond to the interrupt sources */
+	if (status != 0)
+		OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS);
+
+	status = OCD_READ(RM9000x2_OCD_INTP1STATUS4);
+	if (status != 0)
+		OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS);
+
+#ifdef CONFIG_HT_LEVEL_TRIGGER
+	/*
+	 * Level Trigger Mode only. Send the HT EOI message back to the source.
+	 */
+	switch (status) {
+	case 0x1000000:
+		OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
+		break;
+	case 0x2000000:
+		OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
+		break;
+	case 0x4000000:
+		OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
+		break;
+	case 0x8000000:
+		OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
+		break;
+	case 0x0000001:
+		/* PLX */
+		OCD_WRITE(RM9000x2_OCD_HTEOI, 0x20);
+		OCD_WRITE(IRQ_CLEAR_REG, IRQ_ACK_BITS);
+		break;
+	case 0xf000000:
+		OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA);
+		OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB);
+		OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC);
+		OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD);
+		break;
+	}
+#endif /* CONFIG_HT_LEVEL_TRIGGER */
+
+	do_IRQ(irq, regs);
+}
+
+asmlinkage void do_extended_irq(struct pt_regs *regs)
+{
+	unsigned int intcontrol = read_c0_intcontrol();
+	unsigned int cause = read_c0_cause();
+	unsigned int status = read_c0_status();
+	unsigned int pending_sr, pending_ic;
+
+	pending_sr = status & cause & 0xff00;
+	pending_ic = (cause >> 8) & intcontrol & 0xff00;
+
+	if (pending_ic & (1 << 13))
+		do_IRQ(13, regs);
+
+}
+
+#ifdef CONFIG_KGDB
+extern void init_second_port(void);
+#endif
+
+/*
+ * Initialize the next level interrupt handler
+ */
+void __init arch_init_irq(void)
+{
+	clear_c0_status(ST0_IM);
+
+	set_except_vector(0, titan_handle_int);
+	mips_cpu_irq_init(0);
+	rm7k_cpu_irq_init(8);
+	rm9k_cpu_irq_init(12);
+
+#ifdef CONFIG_KGDB
+	/* At this point, initialize the second serial port */
+	init_second_port();
+#endif
+
+#ifdef CONFIG_GDB_CONSOLE
+	register_gdb_console();
+#endif
+}
+
+#ifdef CONFIG_KGDB
+/*
+ * The 16550 DUART has two ports, but is allocated one IRQ
+ * for the serial console. Hence, a generic framework for
+ * serial IRQ routing in place. Currently, just calls the
+ * do_IRQ fuction. But, going in the future, need to check
+ * DUART registers for channel A and B, then decide the
+ * appropriate action
+ */
+asmlinkage void yosemite_kgdb_irq(int irq, struct pt_regs *regs)
+{
+	do_IRQ(irq, regs);
+}
+#endif
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c
new file mode 100644
index 000000000000..1fb3e697948d
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/prom.c
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2003, 2004 PMC-Sierra Inc.
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ * Copyright (C) 2004 Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/pmon.h>
+
+#ifdef CONFIG_SMP
+extern void prom_grab_secondary(void);
+#else
+#define prom_grab_secondary() do { } while (0)
+#endif
+
+#include "setup.h"
+
+struct callvectors *debug_vectors;
+
+extern unsigned long yosemite_base;
+extern unsigned long cpu_clock;
+
+const char *get_system_type(void)
+{
+	return "PMC-Sierra Yosemite";
+}
+
+static void prom_cpu0_exit(void *arg)
+{
+	void *nvram = (void *) YOSEMITE_RTC_BASE;
+
+	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
+	writeb(0x84, nvram + 0xff7);
+
+	/* wait for the watchdog to go off */
+	mdelay(100 + (1000 / 16));
+
+	/* if the watchdog fails for some reason, let people know */
+	printk(KERN_NOTICE "Watchdog reset failed\n");
+}
+
+/*
+ * Reset the NVRAM over the local bus
+ */
+static void prom_exit(void)
+{
+#ifdef CONFIG_SMP
+	if (smp_processor_id())
+		/* CPU 1 */
+		smp_call_function(prom_cpu0_exit, NULL, 1, 1);
+#endif
+	prom_cpu0_exit(NULL);
+}
+
+/*
+ * Halt the system
+ */
+static void prom_halt(void)
+{
+	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+	while (1)
+		__asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
+}
+
+/*
+ * Init routine which accepts the variables from PMON
+ */
+void __init prom_init(void)
+{
+	int argc = fw_arg0;
+	char **arg = (char **) fw_arg1;
+	char **env = (char **) fw_arg2;
+	struct callvectors *cv = (struct callvectors *) fw_arg3;
+	int i = 0;
+
+	/* Callbacks for halt, restart */
+	_machine_restart = (void (*)(char *)) prom_exit;
+	_machine_halt = prom_halt;
+	_machine_power_off = prom_halt;
+
+	debug_vectors = cv;
+	arcs_cmdline[0] = '\0';
+
+	/* Get the boot parameters */
+	for (i = 1; i < argc; i++) {
+		if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
+		    sizeof(arcs_cmdline))
+			break;
+
+		strcat(arcs_cmdline, arg[i]);
+		strcat(arcs_cmdline, " ");
+	}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+	if ((strstr(arcs_cmdline, "console=ttyS")) == NULL)
+		strcat(arcs_cmdline, "console=ttyS0,115200");
+#endif
+
+	while (*env) {
+		if (strncmp("ocd_base", *env, strlen("ocd_base")) == 0)
+			yosemite_base =
+			    simple_strtol(*env + strlen("ocd_base="), NULL,
+					  16);
+
+		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0)
+			cpu_clock =
+			    simple_strtol(*env + strlen("cpuclock="), NULL,
+					  10);
+
+		env++;
+	}
+
+	mips_machgroup = MACH_GROUP_TITAN;
+	mips_machtype = MACH_TITAN_YOSEMITE;
+
+	prom_grab_secondary();
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
+{
+}
diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c
new file mode 100644
index 000000000000..757e605693ff
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/py-console.c
@@ -0,0 +1,114 @@
+/*
+ * 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) 2001, 2002, 2004 Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/termios.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+
+/* SUPERIO uart register map */
+struct yo_uartregs {
+	union {
+		volatile u8	rbr;	/* read only, DLAB == 0 */
+		volatile u8	thr;	/* write only, DLAB == 0 */
+		volatile u8	dll;	/* DLAB == 1 */
+	} u1;
+	union {
+		volatile u8	ier;	/* DLAB == 0 */
+		volatile u8	dlm;	/* DLAB == 1 */
+	} u2;
+	union {
+		volatile u8	iir;	/* read only */
+		volatile u8	fcr;	/* write only */
+	} u3;
+	volatile u8	iu_lcr;
+	volatile u8	iu_mcr;
+	volatile u8	iu_lsr;
+	volatile u8	iu_msr;
+	volatile u8	iu_scr;
+} yo_uregs_t;
+
+#define iu_rbr u1.rbr
+#define iu_thr u1.thr
+#define iu_dll u1.dll
+#define iu_ier u2.ier
+#define iu_dlm u2.dlm
+#define iu_iir u3.iir
+#define iu_fcr u3.fcr
+
+#define ssnop()		__asm__ __volatile__("sll	$0, $0, 1\n");
+#define ssnop_4()	do { ssnop(); ssnop(); ssnop(); ssnop(); } while (0)
+
+#define IO_BASE_64	0x9000000000000000ULL
+
+static unsigned char readb_outer_space(unsigned long long phys)
+{
+	unsigned long long vaddr = IO_BASE_64 | phys;
+	unsigned char res;
+	unsigned int sr;
+
+	sr = read_c0_status();
+	write_c0_status((sr | ST0_KX) & ~ ST0_IE);
+	ssnop_4();
+
+	__asm__ __volatile__ (
+	"	.set	mips3		\n"
+	"	ld	%0, %1		\n"
+	"	lbu	%0, (%0)	\n"
+	"	.set	mips0		\n"
+	: "=r" (res)
+	: "m" (vaddr));
+
+	write_c0_status(sr);
+	ssnop_4();
+
+	return res;
+}
+
+static void writeb_outer_space(unsigned long long phys, unsigned char c)
+{
+	unsigned long long vaddr = IO_BASE_64 | phys;
+	unsigned long tmp;
+	unsigned int sr;
+
+	sr = read_c0_status();
+	write_c0_status((sr | ST0_KX) & ~ ST0_IE);
+	ssnop_4();
+
+	__asm__ __volatile__ (
+	"	.set	mips3		\n"
+	"	ld	%0, %1		\n"
+	"	sb	%2, (%0)	\n"
+	"	.set	mips0		\n"
+	: "=&r" (tmp)
+	: "m" (vaddr), "r" (c));
+
+	write_c0_status(sr);
+	ssnop_4();
+}
+
+void prom_putchar(char c)
+{
+	unsigned long lsr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_lsr);
+	unsigned long thr = 0xfd000008ULL + offsetof(struct yo_uartregs, iu_thr);
+
+	while ((readb_outer_space(lsr) & 0x20) == 0);
+	writeb_outer_space(thr, c);
+}
+
+char __init prom_getchar(void)
+{
+	return 0;
+}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
new file mode 100644
index 000000000000..7225bbf20ce4
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -0,0 +1,235 @@
+/*
+ *  Copyright (C) 2003 PMC-Sierra Inc.
+ *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  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/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/swap.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/time.h>
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/serial.h>
+#include <asm/titan_dep.h>
+#include <asm/m48t37.h>
+
+#include "setup.h"
+
+unsigned char titan_ge_mac_addr_base[6] = {
+	// 0x00, 0x03, 0xcc, 0x1d, 0x22, 0x00
+	0x00, 0xe0, 0x04, 0x00, 0x00, 0x21
+};
+
+unsigned long cpu_clock;
+unsigned long yosemite_base;
+
+static struct m48t37_rtc *m48t37_base;
+
+void __init bus_error_init(void)
+{
+	/* Do nothing */
+}
+
+
+unsigned long m48t37y_get_time(void)
+{
+	unsigned int year, month, day, hour, min, sec;
+
+	/* Stop the update to the time */
+	m48t37_base->control = 0x40;
+
+	year = BCD2BIN(m48t37_base->year);
+	year += BCD2BIN(m48t37_base->century) * 100;
+
+	month = BCD2BIN(m48t37_base->month);
+	day = BCD2BIN(m48t37_base->date);
+	hour = BCD2BIN(m48t37_base->hour);
+	min = BCD2BIN(m48t37_base->min);
+	sec = BCD2BIN(m48t37_base->sec);
+
+	/* Start the update to the time again */
+	m48t37_base->control = 0x00;
+
+	return mktime(year, month, day, hour, min, sec);
+}
+
+int m48t37y_set_time(unsigned long sec)
+{
+	struct rtc_time tm;
+
+	/* convert to a more useful format -- note months count from 0 */
+	to_tm(sec, &tm);
+	tm.tm_mon += 1;
+
+	/* enable writing */
+	m48t37_base->control = 0x80;
+
+	/* year */
+	m48t37_base->year = BIN2BCD(tm.tm_year % 100);
+	m48t37_base->century = BIN2BCD(tm.tm_year / 100);
+
+	/* month */
+	m48t37_base->month = BIN2BCD(tm.tm_mon);
+
+	/* day */
+	m48t37_base->date = BIN2BCD(tm.tm_mday);
+
+	/* hour/min/sec */
+	m48t37_base->hour = BIN2BCD(tm.tm_hour);
+	m48t37_base->min = BIN2BCD(tm.tm_min);
+	m48t37_base->sec = BIN2BCD(tm.tm_sec);
+
+	/* day of week -- not really used, but let's keep it up-to-date */
+	m48t37_base->day = BIN2BCD(tm.tm_wday + 1);
+
+	/* disable writing */
+	m48t37_base->control = 0x00;
+
+	return 0;
+}
+
+void yosemite_timer_setup(struct irqaction *irq)
+{
+	setup_irq(7, irq);
+}
+
+void yosemite_time_init(void)
+{
+	board_timer_setup = yosemite_timer_setup;
+	mips_hpt_frequency = cpu_clock / 2;
+mips_hpt_frequency = 33000000 * 3 * 5;
+}
+
+/* No other usable initialization hook than this ...  */
+extern void (*late_time_init)(void);
+
+unsigned long ocd_base;
+
+EXPORT_SYMBOL(ocd_base);
+
+/*
+ * Common setup before any secondaries are started
+ */
+
+#define TITAN_UART_CLK		3686400
+#define TITAN_SERIAL_BASE_BAUD	(TITAN_UART_CLK / 16)
+#define TITAN_SERIAL_IRQ	4
+#define TITAN_SERIAL_BASE	0xfd000008UL
+
+static void __init py_map_ocd(void)
+{
+	ocd_base = (unsigned long) ioremap(OCD_BASE, OCD_SIZE);
+	if (!ocd_base)
+		panic("Mapping OCD failed - game over.  Your score is 0.");
+
+	/* Kludge for PMON bug ... */
+	OCD_WRITE(0x0710, 0x0ffff029);
+}
+
+static void __init py_uart_setup(void)
+{
+	struct uart_port up;
+
+	/*
+	 * Register to interrupt zero because we share the interrupt with
+	 * the serial driver which we don't properly support yet.
+	 */
+	memset(&up, 0, sizeof(up));
+	up.membase      = (unsigned char *) ioremap(TITAN_SERIAL_BASE, 8);
+	up.irq          = TITAN_SERIAL_IRQ;
+	up.uartclk      = TITAN_UART_CLK;
+	up.regshift     = 0;
+	up.iotype       = UPIO_MEM;
+	up.flags        = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+	up.line         = 0;
+
+	if (early_serial_setup(&up))
+		printk(KERN_ERR "Early serial init of port 0 failed\n");
+}
+
+static void __init py_rtc_setup(void)
+{
+	m48t37_base = ioremap(YOSEMITE_RTC_BASE, YOSEMITE_RTC_SIZE);
+	if (!m48t37_base)
+		printk(KERN_ERR "Mapping the RTC failed\n");
+
+	rtc_get_time = m48t37y_get_time;
+	rtc_set_time = m48t37y_set_time;
+
+	write_seqlock(&xtime_lock);
+	xtime.tv_sec = m48t37y_get_time();
+	xtime.tv_nsec = 0;
+
+	set_normalized_timespec(&wall_to_monotonic,
+	                        -xtime.tv_sec, -xtime.tv_nsec);
+	write_sequnlock(&xtime_lock);
+}
+
+/* Not only time init but that's what the hook it's called through is named */
+static void __init py_late_time_init(void)
+{
+	py_map_ocd();
+	py_uart_setup();
+	py_rtc_setup();
+}
+
+static int __init pmc_yosemite_setup(void)
+{
+	board_time_init = yosemite_time_init;
+	late_time_init = py_late_time_init;
+
+	/* Add memory regions */
+	add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM);
+
+#if 0 /* XXX Crash ...  */
+	OCD_WRITE(RM9000x2_OCD_HTSC,
+	          OCD_READ(RM9000x2_OCD_HTSC) | HYPERTRANSPORT_ENABLE);
+
+	/* Set the BAR. Shifted mode */
+	OCD_WRITE(RM9000x2_OCD_HTBAR0, HYPERTRANSPORT_BAR0_ADDR);
+	OCD_WRITE(RM9000x2_OCD_HTMASK0, HYPERTRANSPORT_SIZE0);
+#endif
+
+	return 0;
+}
+
+early_initcall(pmc_yosemite_setup);
diff --git a/arch/mips/pmc-sierra/yosemite/setup.h b/arch/mips/pmc-sierra/yosemite/setup.h
new file mode 100644
index 000000000000..1a01abfc7d33
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/setup.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2003, 04 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ * Copyright 2004 Ralf Baechle <ralf@linux-mips.org>
+ *
+ * Board specific definititions for the PMC-Sierra Yosemite
+ *
+ * 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.
+ */
+#ifndef __SETUP_H__
+#define __SETUP_H__
+
+/* M48T37 RTC + NVRAM */
+#define	YOSEMITE_RTC_BASE		0xfc800000
+#define	YOSEMITE_RTC_SIZE		0x00800000
+
+#define HYPERTRANSPORT_BAR0_ADDR        0x00000006
+#define HYPERTRANSPORT_SIZE0            0x0fffffff
+#define HYPERTRANSPORT_BAR0_ATTR        0x00002000
+
+#define HYPERTRANSPORT_ENABLE           0x6
+
+/*
+ * EEPROM Size
+ */
+#define	TITAN_ATMEL_24C32_SIZE		32768
+#define	TITAN_ATMEL_24C64_SIZE		65536
+
+#endif /* __SETUP_H__ */
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
new file mode 100644
index 000000000000..1d3b0734c78c
--- /dev/null
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -0,0 +1,172 @@
+#include <linux/linkage.h>
+#include <linux/sched.h>
+
+#include <asm/pmon.h>
+#include <asm/titan_dep.h>
+
+extern unsigned int (*mips_hpt_read)(void);
+extern void (*mips_hpt_init)(unsigned int);
+
+#define LAUNCHSTACK_SIZE 256
+
+static spinlock_t launch_lock __initdata;
+
+static unsigned long secondary_sp __initdata;
+static unsigned long secondary_gp __initdata;
+
+static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata
+	__attribute__((aligned(2 * sizeof(long))));
+
+static void __init prom_smp_bootstrap(void)
+{
+	local_irq_disable();
+
+	while (spin_is_locked(&launch_lock));
+
+	__asm__ __volatile__(
+	"	move	$sp, %0		\n"
+	"	move	$gp, %1		\n"
+	"	j	smp_bootstrap	\n"
+	:
+	: "r" (secondary_sp), "r" (secondary_gp));
+}
+
+/*
+ * PMON is a fragile beast.  It'll blow up once the mappings it's littering
+ * right into the middle of KSEG3 are blown away so we have to grab the slave
+ * core early and keep it in a waiting loop.
+ */
+void __init prom_grab_secondary(void)
+{
+	spin_lock(&launch_lock);
+
+	pmon_cpustart(1, &prom_smp_bootstrap,
+	              launchstack + LAUNCHSTACK_SIZE, 0);
+}
+
+/*
+ * Detect available CPUs, populate phys_cpu_present_map before smp_init
+ *
+ * We don't want to start the secondary CPU yet nor do we have a nice probing
+ * feature in PMON so we just assume presence of the secondary core.
+ */
+static char maxcpus_string[] __initdata =
+	KERN_WARNING "max_cpus set to 0; using 1 instead\n";
+
+void __init prom_prepare_cpus(unsigned int max_cpus)
+{
+	int enabled = 0, i;
+
+	if (max_cpus == 0) {
+		printk(maxcpus_string);
+		max_cpus = 1;
+	}
+
+	cpus_clear(phys_cpu_present_map);
+
+	for (i = 0; i < 2; i++) {
+		if (i == max_cpus)
+			break;
+
+		/*
+		 * The boot CPU
+		 */
+		cpu_set(i, phys_cpu_present_map);
+		__cpu_number_map[i]	= i;
+		__cpu_logical_map[i]	= i;
+		enabled++;
+	}
+
+	/*
+	 * Be paranoid.  Enable the IPI only if we're really about to go SMP.
+	 */
+	if (enabled > 1)
+		set_c0_status(STATUSF_IP5);
+}
+
+/*
+ * Firmware CPU startup hook
+ * Complicated by PMON's weird interface which tries to minimic the UNIX fork.
+ * It launches the next * available CPU and copies some information on the
+ * stack so the first thing we do is throw away that stuff and load useful
+ * values into the registers ...
+ */
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+	unsigned long gp = (unsigned long) idle->thread_info;
+	unsigned long sp = gp + THREAD_SIZE - 32;
+
+	secondary_sp = sp;
+	secondary_gp = gp;
+
+	spin_unlock(&launch_lock);
+}
+
+/* Hook for after all CPUs are online */
+void prom_cpus_done(void)
+{
+}
+
+/*
+ *  After we've done initial boot, this function is called to allow the
+ *  board code to clean up state, if needed
+ */
+void prom_init_secondary(void)
+{
+	mips_hpt_init(mips_hpt_read());
+
+	set_c0_status(ST0_CO | ST0_IE | ST0_IM);
+}
+
+void prom_smp_finish(void)
+{
+}
+
+asmlinkage void titan_mailbox_irq(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	unsigned long status;
+
+	if (cpu == 0) {
+		status = OCD_READ(RM9000x2_OCD_INTP0STATUS3);
+		OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status);
+	}
+
+	if (cpu == 1) {
+		status = OCD_READ(RM9000x2_OCD_INTP1STATUS3);
+		OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status);
+	}
+
+	if (status & 0x2)
+		smp_call_function_interrupt();
+}
+
+/*
+ * Send inter-processor interrupt
+ */
+void core_send_ipi(int cpu, unsigned int action)
+{
+	/*
+	 * Generate an INTMSG so that it can be sent over to the
+	 * destination CPU. The INTMSG will put the STATUS bits
+	 * based on the action desired. An alternative strategy
+	 * is to write to the Interrupt Set register, read the
+	 * Interrupt Status register and clear the Interrupt
+	 * Clear register. The latter is preffered.
+	 */
+	switch (action) {
+	case SMP_RESCHEDULE_YOURSELF:
+		if (cpu == 1)
+			OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
+		else
+			OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
+		break;
+
+	case SMP_CALL_FUNCTION:
+		if (cpu == 1)
+			OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
+		else
+			OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
+		break;
+	}
+}