aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Popov <ppopov@embeddedalley.com>2005-07-14 17:47:57 +0000
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 19:31:54 +0100
commitbdf21b18b4abf983db38f04ef7fec88f47389867 (patch)
treeb7e551f09f0ee39f4a59132be4c0890e1ba80d91
parente01402b115cccb6357f956649487aca2c6f7fbba (diff)
Philips PNX8550 support: MIPS32-like core with 2 Trimedias on it.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/Kconfig21
-rw-r--r--arch/mips/Makefile14
-rw-r--r--arch/mips/kernel/cpu-probe.c19
-rw-r--r--arch/mips/kernel/proc.c3
-rw-r--r--arch/mips/kernel/time.c3
-rw-r--r--arch/mips/mm/tlbex.c1
-rw-r--r--arch/mips/pci/Makefile1
-rw-r--r--arch/mips/pci/fixup-pnx8550.c57
-rw-r--r--arch/mips/pci/ops-pnx8550.c284
-rw-r--r--arch/mips/philips/pnx8550/common/Kconfig1
-rw-r--r--arch/mips/philips/pnx8550/common/Makefile27
-rw-r--r--arch/mips/philips/pnx8550/common/gdb_hook.c109
-rw-r--r--arch/mips/philips/pnx8550/common/int.c293
-rw-r--r--arch/mips/philips/pnx8550/common/mipsIRQ.S76
-rw-r--r--arch/mips/philips/pnx8550/common/pci.c133
-rw-r--r--arch/mips/philips/pnx8550/common/platform.c135
-rw-r--r--arch/mips/philips/pnx8550/common/proc.c113
-rw-r--r--arch/mips/philips/pnx8550/common/prom.c138
-rw-r--r--arch/mips/philips/pnx8550/common/reset.c49
-rw-r--r--arch/mips/philips/pnx8550/common/setup.c149
-rw-r--r--arch/mips/philips/pnx8550/common/time.c105
-rw-r--r--arch/mips/philips/pnx8550/jbs/Makefile4
-rw-r--r--arch/mips/philips/pnx8550/jbs/board_setup.c65
-rw-r--r--arch/mips/philips/pnx8550/jbs/init.c57
-rw-r--r--arch/mips/philips/pnx8550/jbs/irqmap.c36
-rw-r--r--include/asm-mips/bootinfo.h1
-rw-r--r--include/asm-mips/cpu.h4
-rw-r--r--include/asm-mips/mach-pnx8550/cm.h43
-rw-r--r--include/asm-mips/mach-pnx8550/glb.h86
-rw-r--r--include/asm-mips/mach-pnx8550/int.h140
-rw-r--r--include/asm-mips/mach-pnx8550/kernel-entry-init.h262
-rw-r--r--include/asm-mips/mach-pnx8550/nand.h121
-rw-r--r--include/asm-mips/mach-pnx8550/pci.h185
-rw-r--r--include/asm-mips/mach-pnx8550/uart.h16
-rw-r--r--include/asm-mips/mach-pnx8550/usb.h32
-rw-r--r--include/asm-mips/mipsregs.h12
-rw-r--r--include/linux/serial_core.h3
-rw-r--r--include/linux/serial_ip3106.h81
38 files changed, 2876 insertions, 3 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4ef015f580f..f6b25ae1861 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -489,6 +489,16 @@ config HYPERTRANSPORT
bool "Hypertransport Support for PMC-Sierra Yosemite"
depends on PMC_YOSEMITE
+config PNX8550_V2PCI
+ bool "Support for Philips PNX8550 based Viper2-PCI board"
+ select PNX8550
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config PNX8550_JBS
+ bool "Support for Philips PNX8550 based JBS board"
+ select PNX8550
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
config DDB5074
bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)"
depends on EXPERIMENTAL
@@ -827,6 +837,7 @@ config TOSHIBA_FPCIB0
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
+source "arch/mips/philips/pnx8550/common/Kconfig"
config RWSEM_GENERIC_SPINLOCK
bool
@@ -954,6 +965,16 @@ config ITE_BOARD_GEN
depends on MIPS_IVR || MIPS_ITE8172
default y
+config PNX8550
+ bool
+ select SOC_PNX8550
+
+config SOC_PNX8550
+ bool
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+
config SWAP_IO_SPACE
bool
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6780d115a7d..d62787ab9ff 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -228,6 +228,7 @@ cflags-$(CONFIG_CPU_RM9000) += \
$(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \
-Wa,--trap
+
cflags-$(CONFIG_CPU_SB1) += \
$(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \
-Wa,--trap
@@ -561,6 +562,19 @@ load-$(CONFIG_CASIO_E55) += 0xffffffff80004000
load-$(CONFIG_TANBAC_TB022X) += 0xffffffff80000000
#
+# Common Philips PNX8550
+#
+core-$(CONFIG_SOC_PNX8550) += arch/mips/philips/pnx8550/common/
+cflags-$(CONFIG_SOC_PNX8550) += -Iinclude/asm-mips/mach-pnx8550
+
+#
+# Philips PNX8550 JBS board
+#
+libs-$(CONFIG_PNX8550_JBS) += arch/mips/philips/pnx8550/jbs/
+#cflags-$(CONFIG_PNX8550_JBS) += -Iinclude/asm-mips/mach-pnx8550
+load-$(CONFIG_PNX8550_JBS) += 0xffffffff80060000
+
+#
# SGI IP22 (Indy/Indigo2)
#
# Set the load address to >= 0xffffffff88069000 if you want to leave space for
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 844126b39ed..70c8ad9bc8f 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -121,6 +121,7 @@ static inline void check_wait(void)
case CPU_24K:
case CPU_25KF:
case CPU_34K:
+ case CPU_PR4450:
cpu_wait = r4k_wait;
printk(" available.\n");
break;
@@ -624,6 +625,21 @@ static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c)
}
}
+static inline void cpu_probe_philips(struct cpuinfo_mips *c)
+{
+ decode_configs(c);
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_PR4450:
+ c->cputype = CPU_PR4450;
+ c->isa_level = MIPS_CPU_ISA_M32;
+ break;
+ default:
+ panic("Unknown Philips Core!"); /* REVISIT: die? */
+ break;
+ }
+}
+
+
__init void cpu_probe(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -649,6 +665,9 @@ __init void cpu_probe(void)
case PRID_COMP_SANDCRAFT:
cpu_probe_sandcraft(c);
break;
+ case PRID_COMP_PHILIPS:
+ cpu_probe_philips(c);
+ break;
default:
c->cputype = CPU_UNKNOWN;
}
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 1bd40af508e..e46a92d01d5 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -80,7 +80,8 @@ static const char *cpu_name[] = {
[CPU_VR4133] = "NEC VR4133",
[CPU_VR4181] = "NEC VR4181",
[CPU_VR4181A] = "NEC VR4181A",
- [CPU_SR71000] = "Sandcraft SR71000"
+ [CPU_SR71000] = "Sandcraft SR71000",
+ [CPU_PR4450] = "Philips PR4450",
};
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index fbc153c8f83..a24651dfaab 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -11,6 +11,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -112,8 +113,10 @@ static void c0_timer_ack(void)
{
unsigned int count;
+#ifndef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
/* Ack this timer interrupt and set the next one. */
expirelo += cycles_per_jiffy;
+#endif
write_c0_compare(expirelo);
/* Check to see if we have missed any timer interrupts. */
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index c1d394d36f6..a876ed6cde2 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -844,6 +844,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
case CPU_AU1500:
case CPU_AU1550:
case CPU_AU1200:
+ case CPU_PR4450:
i_nop(p);
tlbw(p);
break;
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 83d81c9cdc2..ea8438b81fe 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8172g.o
obj-$(CONFIG_MIPS_IVR) += fixup-ivr.o
obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o
+obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o
obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o
obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o
diff --git a/arch/mips/pci/fixup-pnx8550.c b/arch/mips/pci/fixup-pnx8550.c
new file mode 100644
index 00000000000..4256b3b30b7
--- /dev/null
+++ b/arch/mips/pci/fixup-pnx8550.c
@@ -0,0 +1,57 @@
+/*
+ * Philips PNX8550 pci fixups.
+ *
+ * Copyright 2005 Embedded Alley Solutions, Inc
+ * source@embeddealley.com
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * 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.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mach-pnx8550/pci.h>
+#include <asm/mach-pnx8550/int.h>
+
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+extern char irq_tab_jbs[][5];
+
+void __init pcibios_fixup_resources(struct pci_dev *dev)
+{
+ /* no need to fixup IO resources */
+}
+
+void __init pcibios_fixup(void)
+{
+ /* nothing to do here */
+}
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return irq_tab_jbs[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
diff --git a/arch/mips/pci/ops-pnx8550.c b/arch/mips/pci/ops-pnx8550.c
new file mode 100644
index 00000000000..454b65cc335
--- /dev/null
+++ b/arch/mips/pci/ops-pnx8550.c
@@ -0,0 +1,284 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *
+ * 2.6 port, Embedded Alley Solutions, Inc
+ *
+ * Based on:
+ * Author: source@mvista.com
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * 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.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+
+#include <asm/mach-pnx8550/pci.h>
+#include <asm/mach-pnx8550/glb.h>
+#include <asm/debug.h>
+
+
+static inline void clear_status(void)
+{
+ unsigned long pci_stat;
+
+ pci_stat = inl(PCI_BASE | PCI_GPPM_STATUS);
+ outl(pci_stat, PCI_BASE | PCI_GPPM_ICLR);
+}
+
+static inline unsigned int
+calc_cfg_addr(struct pci_bus *bus, unsigned int devfn, int where)
+{
+ unsigned int addr;
+
+ addr = ((bus->number > 0) ? (((bus->number & 0xff) << PCI_CFG_BUS_SHIFT) | 1) : 0);
+ addr |= ((devfn & 0xff) << PCI_CFG_FUNC_SHIFT) | (where & 0xfc);
+
+ return addr;
+}
+
+static int
+config_access(unsigned int pci_cmd, struct pci_bus *bus, unsigned int devfn, int where, unsigned int pci_mode, unsigned int *val)
+{
+ unsigned int flags;
+ unsigned long loops = 0;
+ unsigned long ioaddr = calc_cfg_addr(bus, devfn, where);
+
+ local_irq_save(flags);
+ /*Clear pending interrupt status */
+ if (inl(PCI_BASE | PCI_GPPM_STATUS)) {
+ clear_status();
+ while (!(inl(PCI_BASE | PCI_GPPM_STATUS) == 0)) ;
+ }
+
+ outl(ioaddr, PCI_BASE | PCI_GPPM_ADDR);
+
+ if ((pci_cmd == PCI_CMD_IOW) || (pci_cmd == PCI_CMD_CONFIG_WRITE))
+ outl(*val, PCI_BASE | PCI_GPPM_WDAT);
+
+ outl(INIT_PCI_CYCLE | pci_cmd | (pci_mode & PCI_BYTE_ENABLE_MASK),
+ PCI_BASE | PCI_GPPM_CTRL);
+
+ loops =
+ ((loops_per_jiffy *
+ PCI_IO_JIFFIES_TIMEOUT) >> (PCI_IO_JIFFIES_SHIFT));
+ while (1) {
+ if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_DONE) {
+ if ((pci_cmd == PCI_CMD_IOR) ||
+ (pci_cmd == PCI_CMD_CONFIG_READ))
+ *val = inl(PCI_BASE | PCI_GPPM_RDAT);
+ clear_status();
+ local_irq_restore(flags);
+ return PCIBIOS_SUCCESSFUL;
+ } else if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_R_MABORT) {
+ break;
+ }
+
+ loops--;
+ if (loops == 0) {
+ printk("%s : Arbiter Locked.\n", __FUNCTION__);
+ }
+ }
+
+ clear_status();
+ if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_IOW)) {
+ printk("%s timeout (GPPM_CTRL=%X) ioaddr %lX pci_cmd %X\n",
+ __FUNCTION__, inl(PCI_BASE | PCI_GPPM_CTRL), ioaddr,
+ pci_cmd);
+ }
+
+ if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_CONFIG_READ))
+ *val = 0xffffffff;
+ local_irq_restore(flags);
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+/*
+ * We can't address 8 and 16 bit words directly. Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int
+read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val)
+{
+ unsigned int data = 0;
+ int err;
+
+ if (bus == 0)
+ return -1;
+
+ err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
+ switch (where & 0x03) {
+ case 0:
+ *val = (unsigned char)(data & 0x000000ff);
+ break;
+ case 1:
+ *val = (unsigned char)((data & 0x0000ff00) >> 8);
+ break;
+ case 2:
+ *val = (unsigned char)((data & 0x00ff0000) >> 16);
+ break;
+ case 3:
+ *val = (unsigned char)((data & 0xff000000) >> 24);
+ break;
+ }
+
+ return err;
+}
+
+static int
+read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val)
+{
+ unsigned int data = 0;
+ int err;
+
+ if (bus == 0)
+ return -1;
+
+ if (where & 0x01)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(3 << (where & 3)), &data);
+ switch (where & 0x02) {
+ case 0:
+ *val = (unsigned short)(data & 0x0000ffff);
+ break;
+ case 2:
+ *val = (unsigned short)((data & 0xffff0000) >> 16);
+ break;
+ }
+
+ return err;
+}
+
+static int
+read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
+{
+ int err;
+ if (bus == 0)
+ return -1;
+
+ if (where & 0x03)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, 0, val);
+
+ return err;
+}
+
+static int
+write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val)
+{
+ unsigned int data = (unsigned int)val;
+ int err;
+
+ if (bus == 0)
+ return -1;
+
+ switch (where & 0x03) {
+ case 1:
+ data = (data << 8);
+ break;
+ case 2:
+ data = (data << 16);
+ break;
+ case 3:
+ data = (data << 24);
+ break;
+ default:
+ break;
+ }
+
+ err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data);
+
+ return err;
+}
+
+static int
+write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val)
+{
+ unsigned int data = (unsigned int)val;
+ int err;
+
+ if (bus == 0)
+ return -1;
+
+ if (where & 0x01)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ switch (where & 0x02) {
+ case 2:
+ data = (data << 16);
+ break;
+ default:
+ break;
+ }
+ err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(3 << (where & 3)), &data);
+
+ return err;
+}
+
+static int
+write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val)
+{
+ int err;
+ if (bus == 0)
+ return -1;
+
+ if (where & 0x03)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, 0, &val);
+
+ return err;
+}
+
+static int config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val)
+{
+ switch (size) {
+ case 1: {
+ u8 _val;
+ int rc = read_config_byte(bus, devfn, where, &_val);
+ *val = _val;
+ return rc;
+ }
+ case 2: {
+ u16 _val;
+ int rc = read_config_word(bus, devfn, where, &_val);
+ *val = _val;
+ return rc;
+ }
+ default:
+ return read_config_dword(bus, devfn, where, val);
+ }
+}
+
+static int config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val)
+{
+ switch (size) {
+ case 1:
+ return write_config_byte(bus, devfn, where, (u8) val);
+ case 2:
+ return write_config_word(bus, devfn, where, (u16) val);
+ default:
+ return write_config_dword(bus, devfn, where, val);
+ }
+}
+
+struct pci_ops pnx8550_pci_ops = {
+ config_read,
+ config_write
+};
diff --git a/arch/mips/philips/pnx8550/common/Kconfig b/arch/mips/philips/pnx8550/common/Kconfig
new file mode 100644
index 00000000000..072572d173c
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/Kconfig
@@ -0,0 +1 @@
+# Place holder
diff --git a/arch/mips/philips/pnx8550/common/Makefile b/arch/mips/philips/pnx8550/common/Makefile
new file mode 100644
index 00000000000..6e38f3bc443
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/Makefile
@@ -0,0 +1,27 @@
+#
+# Per Hallsmark, per.hallsmark@mvista.com
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# 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.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the PNX8550 specific kernel interface routines
+# under Linux.
+#
+
+obj-y := setup.o prom.o mipsIRQ.o int.o reset.o time.o proc.o platform.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_KGDB) += gdb_hook.o
diff --git a/arch/mips/philips/pnx8550/common/gdb_hook.c b/arch/mips/philips/pnx8550/common/gdb_hook.c
new file mode 100644
index 00000000000..ad4624f6d9b
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/gdb_hook.c
@@ -0,0 +1,109 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * 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.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * This is the interface to the remote debugger stub.
+ *
+ */
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_ip3106.h>
+
+#include <asm/serial.h>
+#include <asm/io.h>
+
+#include <uart.h>
+
+static struct serial_state rs_table[IP3106_NR_PORTS] = {
+};
+static struct async_struct kdb_port_info = {0};
+
+void rs_kgdb_hook(int tty_no)
+{
+ struct serial_state *ser = &rs_table[tty_no];
+
+ kdb_port_info.state = ser;
+ kdb_port_info.magic = SERIAL_MAGIC;
+ kdb_port_info.port = tty_no;
+ kdb_port_info.flags = ser->flags;
+
+ /*
+ * Clear all interrupts
+ */
+ /* Clear all the transmitter FIFO counters (pointer and status) */
+ ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_TX_RST;
+ /* Clear all the receiver FIFO counters (pointer and status) */
+ ip3106_lcr(UART_BASE, tty_no) |= IP3106_UART_LCR_RX_RST;
+ /* Clear all interrupts */
+ ip3106_iclr(UART_BASE, tty_no) = IP3106_UART_INT_ALLRX |
+ IP3106_UART_INT_ALLTX;
+
+ /*
+ * Now, initialize the UART
+ */
+ ip3106_lcr(UART_BASE, tty_no) = IP3106_UART_LCR_8BIT;
+ ip3106_baud(UART_BASE, tty_no) = 5; // 38400 Baud
+}
+
+int putDebugChar(char c)
+{
+ /* Wait until FIFO not full */
+ while (((ip3106_fifo(UART_BASE, kdb_port_info.port) & IP3106_UART_FIFO_TXFIFO) >> 16) >= 16)
+ ;
+ /* Send one char */
+ ip3106_fifo(UART_BASE, kdb_port_info.port) = c;
+
+ return 1;
+}
+
+char getDebugChar(void)
+{
+ char ch;
+
+ /* Wait until there is a char in the FIFO */
+ while (!((ip3106_fifo(UART_BASE, kdb_port_info.port) &
+ IP3106_UART_FIFO_RXFIFO) >> 8))
+ ;
+ /* Read one char */
+ ch = ip3106_fifo(UART_BASE, kdb_port_info.port) &
+ IP3106_UART_FIFO_RBRTHR;
+ /* Advance the RX FIFO read pointer */
+ ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_NEXT;
+ return (ch);
+}
+
+void rs_disable_debug_interrupts(void)
+{
+ ip3106_ien(UART_BASE, kdb_port_info.port) = 0; /* Disable all interrupts */
+}
+
+void rs_enable_debug_interrupts(void)
+{
+ /* Clear all the transmitter FIFO counters (pointer and status) */
+ ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_TX_RST;
+ /* Clear all the receiver FIFO counters (pointer and status) */
+ ip3106_lcr(UART_BASE, kdb_port_info.port) |= IP3106_UART_LCR_RX_RST;
+ /* Clear all interrupts */
+ ip3106_iclr(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX |
+ IP3106_UART_INT_ALLTX;
+ ip3106_ien(UART_BASE, kdb_port_info.port) = IP3106_UART_INT_ALLRX; /* Enable RX interrupts */
+}
diff --git a/arch/mips/philips/pnx8550/common/int.c b/arch/mips/philips/pnx8550/common/int.c
new file mode 100644
index 00000000000..546144988bf
--- /dev/null
+++ b/arch/mips/philips/pnx8550/common/int.c
@@ -0,0 +1,293 @@
+/*
+ *
+ * Copyright (C) 2005 Embedded Alley Solutions, Inc
+ * Ported to 2.6.
+ *
+ * Per Hallsmark, per.hallsmark@mvista.com
+ * Copyright (C) 2000, 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ *
+ * Cleaned up and bug fixing: Pete Popov, ppopov@embeddedalley.com
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * 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.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/random.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/gdb-stub.h>
+#include <int.h>
+#include <uart.h>
+
+extern asmlinkage void cp0_irqdispatch(void);
+
+static DEFINE_SPINLOCK(irq_lock);
+
+/* default prio for interrupts */
+/* first one is a no-no so therefore always prio 0 (disabled) */
+static char gic_prio[PNX8550_INT_GIC_TOTINT] = {
+ 0, 1, 1, 1, 1, 15, 1, 1, 1, 1, // 0 - 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 19
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 29
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 39
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 49
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, // 50 - 59
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 69
+ 1 // 70
+};
+
+void hw0_irqdispatch(int irq, struct pt_regs *regs)
+{
+ /* find out which interrupt */
+ irq = PNX8550_GIC_VECTOR_0 >> 3;
+
+ if (irq == 0) {
+ printk("hw0_irqdispatch: irq 0, spurious interrupt?\n");
+ return;
+ }
+ do_IRQ(PNX8550_INT_GIC_MIN + irq, regs);
+}
+
+
+void timer_irqdispatch(int irq, struct pt_regs *regs)
+{
+ irq = (0x01c0 & read_c0_config7()) >> 6;
+
+ if (irq == 0) {
+ printk("timer_irqdispatch: irq 0, spurious interrupt?\n");
+ return;
+ }
+
+ if (irq & 0x1) {
+ do_IRQ(PNX8550_INT_TIMER1, regs);
+ }
+ if (irq & 0x2) {
+ do_IRQ(PNX8550_INT_TIMER2, regs);
+ }
+ if (irq & 0x4) {
+ do_IRQ(PNX8550_INT_TIMER3, regs);
+ }
+}
+
+static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
+{
+ unsigned long status = read_c0_status();
+
+ status &= ~((clr_mask & 0xFF) << 8);
+ status |= (set_mask & 0xFF) << 8;
+
+ write_c0_status(status);
+}
+
+static inline void mask_gic_int(unsigned int irq_nr)
+{
+ /* interrupt disabled, bit 26(WE_ENABLE)=1 and bit 16(enable)=0 */
+ PNX8550_GIC_REQ(irq_nr) = 1<<28; /* set priority to 0 */
+}
+
+static inline void unmask_gic_int(unsigned int irq_nr)
+{
+ /* set prio mask to lower four bits and enable interrupt */
+ PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr];
+}
+
+static inline void mask_irq(unsigned int irq_nr)
+{
+ if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
+ modify_cp0_intmask(1 << irq_nr, 0);
+ } else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
+ (irq_nr <= PNX8550_INT_GIC_MAX)) {
+ mask_gic_int(irq_nr - PNX8550_INT_GIC_MIN);
+ } else if ((PNX8550_INT_TIMER_MIN <= irq_nr) &&
+ (irq_nr <= PNX8550_INT_TIMER_MAX)) {
+ modify_cp0_intmask(1 << 7, 0);
+ } else {
+ printk("mask_irq: irq %d doesn't exist!\n", irq_nr);
+ }
+}
+
+static inline void unmask_irq(unsigned int irq_nr)