summaryrefslogtreecommitdiffstats
path: root/arch/mips/txx9/generic
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-25 11:37:07 +0200
committerIngo Molnar <mingo@elte.hu>2008-07-25 11:37:07 +0200
commit0e2f65ee30eee2db054f7fd73f462c5da33ec963 (patch)
tree26c61eb7745da0c0d9135e9d12088f570cb8530d /arch/mips/txx9/generic
parentda7878d75b8520c9ae00d27dfbbce546a7bfdfbb (diff)
parentfb2e405fc1fc8b20d9c78eaa1c7fd5a297efde43 (diff)
Merge branch 'linus' into x86/pebs
Conflicts: arch/x86/Kconfig.cpu arch/x86/kernel/cpu/intel.c arch/x86/kernel/setup_64.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/mips/txx9/generic')
-rw-r--r--arch/mips/txx9/generic/Makefile12
-rw-r--r--arch/mips/txx9/generic/dbgio.c48
-rw-r--r--arch/mips/txx9/generic/irq_tx4927.c37
-rw-r--r--arch/mips/txx9/generic/irq_tx4938.c25
-rw-r--r--arch/mips/txx9/generic/mem_tx4927.c77
-rw-r--r--arch/mips/txx9/generic/pci.c388
-rw-r--r--arch/mips/txx9/generic/setup.c246
-rw-r--r--arch/mips/txx9/generic/setup_tx4927.c194
-rw-r--r--arch/mips/txx9/generic/setup_tx4938.c259
-rw-r--r--arch/mips/txx9/generic/smsc_fdc37m81x.c172
10 files changed, 1458 insertions, 0 deletions
diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile
new file mode 100644
index 00000000000..9c120771e65
--- /dev/null
+++ b/arch/mips/txx9/generic/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for common code for TXx9 based systems
+#
+
+obj-y += setup.o
+obj-$(CONFIG_PCI) += pci.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_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o
+obj-$(CONFIG_KGDB) += dbgio.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/txx9/generic/dbgio.c b/arch/mips/txx9/generic/dbgio.c
new file mode 100644
index 00000000000..33b9c672a32
--- /dev/null
+++ b/arch/mips/txx9/generic/dbgio.c
@@ -0,0 +1,48 @@
+/*
+ * linux/arch/mips/tx4938/common/dbgio.c
+ *
+ * kgdb interface for gdb
+ *
+ * Author: MontaVista Software, Inc.
+ * source@mvista.com
+ *
+ * Copyright 2005 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.
+ *
+ * Support for TX4938 in 2.6 - Hiroshi DOYU <Hiroshi_DOYU@montavista.co.jp>
+ */
+
+#include <linux/types>
+
+extern u8 txx9_sio_kdbg_rd(void);
+extern int txx9_sio_kdbg_wr( u8 ch );
+
+u8 getDebugChar(void)
+{
+ return (txx9_sio_kdbg_rd());
+}
+
+int putDebugChar(u8 byte)
+{
+ return (txx9_sio_kdbg_wr(byte));
+}
+
diff --git a/arch/mips/txx9/generic/irq_tx4927.c b/arch/mips/txx9/generic/irq_tx4927.c
new file mode 100644
index 00000000000..cbea1fdde82
--- /dev/null
+++ b/arch/mips/txx9/generic/irq_tx4927.c
@@ -0,0 +1,37 @@
+/*
+ * 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 <asm/irq_cpu.h>
+#include <asm/txx9/tx4927.h>
+
+void __init tx4927_irq_init(void)
+{
+ mips_cpu_irq_init();
+ txx9_irq_init(TX4927_IRC_REG & 0xfffffffffULL);
+ set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT,
+ handle_simple_irq);
+}
diff --git a/arch/mips/txx9/generic/irq_tx4938.c b/arch/mips/txx9/generic/irq_tx4938.c
new file mode 100644
index 00000000000..6eac684bf19
--- /dev/null
+++ b/arch/mips/txx9/generic/irq_tx4938.c
@@ -0,0 +1,25 @@
+/*
+ * 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 <asm/irq_cpu.h>
+#include <asm/txx9/tx4938.h>
+
+void __init tx4938_irq_init(void)
+{
+ mips_cpu_irq_init();
+ txx9_irq_init(TX4938_IRC_REG & 0xfffffffffULL);
+ set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT,
+ handle_simple_irq);
+}
diff --git a/arch/mips/txx9/generic/mem_tx4927.c b/arch/mips/txx9/generic/mem_tx4927.c
new file mode 100644
index 00000000000..ef6ea6e9787
--- /dev/null
+++ b/arch/mips/txx9/generic/mem_tx4927.c
@@ -0,0 +1,77 @@
+/*
+ * linux/arch/mips/txx9/generic/mem_tx4927.c
+ *
+ * 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 00000000000..0b92d8c1320
--- /dev/null
+++ b/arch/mips/txx9/generic/pci.c
@@ -0,0 +1,388 @@
+/*
+ * 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 <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_dev fake_dev;
+ struct pci_bus fake_bus;
+
+ fake_dev.bus = &fake_bus;
+ fake_dev.sysdata = hose;
+ fake_dev.devfn = devfn;
+ 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_read_config_word(&fake_dev, 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);
+
+ printk(KERN_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)) {
+ printk(KERN_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 addresss. 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 */
+
+ printk(KERN_INFO "PCI: IO 0x%08llx-0x%08llx MEM 0x%08llx-0x%08llx\n",
+ (unsigned long long)pcic->mem_resource[1].start,
+ (unsigned long long)pcic->mem_resource[1].end,
+ (unsigned long long)pcic->mem_resource[0].start,
+ (unsigned long long)pcic->mem_resource[0].end);
+
+ /* 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);
+ printk(KERN_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 __init
+txx9_i8259_irq_setup(int irq)
+{
+ int err;
+
+ init_i8259_irqs();
+ err = request_irq(irq, &i8259_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ "cascade(i8259)", (void *)(long)irq);
+ if (!err)
+ printk(KERN_INFO "PCI-ISA bridge PIC (irq %d)\n", irq);
+ return err;
+}
+
+static void __init 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);
+ printk(KERN_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);
+ printk(KERN_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, regs[i], dat);
+ pci_read_config_byte(dev, 0x5c, &dat);
+ printk(KERN_CONT " REG5C %02x", dat);
+ printk(KERN_CONT "\n");
+}
+#endif /* CONFIG_TOSHIBA_FPCIB0 */
+
+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);
+ printk(KERN_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))
+ printk(KERN_CONT "failed. (0x%x)\n", bist);
+ else
+ printk(KERN_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_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;
+}
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ return txx9_board_vec->pci_map_irq(dev, slot, pin);
+}
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
new file mode 100644
index 00000000000..8c60c78b9a9
--- /dev/null
+++ b/arch/mips/txx9/generic/setup.c
@@ -0,0 +1,246 @@
+/*
+ * linux/arch/mips/txx9/generic/setup.c
+ *
+ * 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/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/txx9/generic.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];
+ }
+
+ 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;
+
+int txx9_ccfg_toeon __initdata = 1;
+
+/* Minimum CLK support */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ if (!strcmp(id, "spi-baseclk"))
+ return (struct clk *)((unsigned long)txx9_gbus_clock / 2 / 4);
+ if (!strcmp(id, "imbus_clk"))
+ return (struct clk *)((unsigned long)txx9_gbus_clock / 2);
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return (unsigned long)clk;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+/* GPIO support */
+
+#ifdef CONFIG_GENERIC_GPIO
+int gpio_to_irq(unsigned gpio)
+{
+ return -EINVAL;
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int irq_to_gpio(unsigned irq)
+{
+ return -EINVAL;
+}
+EXPORT_SYMBOL(irq_to_gpio);
+#endif
+
+extern struct txx9_board_vec jmr3927_vec;
+extern struct txx9_board_vec rbtx4927_vec;
+extern struct txx9_board_vec rbtx4937_vec;
+extern struct txx9_board_vec rbtx4938_vec;
+
+struct txx9_board_vec *txx9_board_vec __initdata;
+static char txx9_system_type[32];
+
+void __init prom_init_cmdline(void)
+{
+ int argc = (int)fw_arg0;
+ char **argv = (char **)fw_arg1;
+ int i; /* Always ignore the "-c" at argv[0] */
+#ifdef CONFIG_64BIT
+ char *fixed_argv[32];
+ for (i = 0; i < argc; i++)
+ fixed_argv[i] = (char *)(long)(*((__s32 *)argv + i));
+ argv = fixed_argv;
+#endif
+
+ /* ignore all built-in args if any f/w args given */
+ if (argc > 1)
+ *arcs_cmdline = '\0';
+
+ for (i = 1; i < argc; i++) {
+ if (i != 1)
+ strcat(arcs_cmdline, " ");
+ strcat(arcs_cmdline, argv[i]);
+ }
+}
+
+void __init prom_init(void)
+{
+#ifdef CONFIG_CPU_TX39XX
+ 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
+ }
+#endif
+
+ strcpy(txx9_system_type, txx9_board_vec->system);
+
+ txx9_board_vec->prom_init();
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+const char *get_system_type(void)
+{
+ return txx9_system_type;
+}
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+/* 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 */
+ txx9_board_vec->mem_setup();
+}
+
+void __init arch_init_irq(void)
+{
+ txx9_board_vec->irq_setup();
+}
+
+void __init plat_time_init(void)
+{
+ txx9_board_vec->time_init();
+}
+
+static int __init _txx9_arch_init(void)
+{
+ 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
diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c
new file mode 100644
index 00000000000..89d6e28add9
--- /dev/null
+++ b/arch/mips/txx9/generic/setup_tx4927.c
@@ -0,0 +1,194 @@
+/*
+ * 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/serial_core.h>
+#include <linux/param.h>
+#include <asm/txx9irq.h>
+#include <asm/txx9tmr.h>
+#include <asm/txx9pio.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/tx4927.h>
+
+void __init tx4927_wdr_init(void)
+{
+ /* clear WatchDogReset (W1C) */
+ tx4927_ccfg_set(TX4927_CCFG_WDRST);
+ /* do reset on watchdog */
+ tx4927_ccfg_set(TX4927_CCFG_WR);
+}
+
+static struct resource tx4927_sdram_resource[4];
+
+void __init tx4927_setup(void)
+{
+ int i;
+ __u32 divmode;
+ int cpuclk = 0;
+ u64 ccfg;
+
+ txx9_reg_res_init(TX4927_REV_PCODE(), TX4927_REG_BASE,
+ TX4927_REG_SIZE);
+
+ /* 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);
+
+ printk(KERN_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),
+ (unsigned long long)____raw_readq(&tx4927_ccfgptr->ccfg),
+ (unsigned long long)____raw_readq(&tx4927_ccfgptr->pcfg));
+
+ printk(KERN_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;
+ printk(" CR%d:%016llx", i, (unsigned long long)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]);
+ }
+ printk(" TR:%09llx\n",
+ (unsigned long long)____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 */
+ txx9_gpio_init(TX4927_PIO_REG & 0xfffffffffULL, 0, TX4927_NUM_PIO);
+ __raw_writel(0, &tx4927_pioptr->maskcpu);
+ __raw_writel(0, &tx4927_pioptr->maskext);
+}
+
+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_setup_serial(void)
+{
+#ifdef CONFIG_SERIAL_TXX9
+ int i;
+ struct uart_port req;
+
+ for (i = 0; i < 2; i++) {
+ memset(&req, 0, sizeof(req));
+ req.line = i;
+ req.iotype = UPIO_MEM;
+ req.membase = (unsigned char __iomem *)TX4927_SIO_REG(i);
+ req.mapbase = TX4927_SIO_REG(i) & 0xfffffffffULL;
+ req.irq = TXX9_IRQ_BASE + TX4927_IR_SIO(i);
+ req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+ req.uartclk = TXX9_IMCLK;
+ early_serial_txx9_setup(&req);
+ }
+#endif /* CONFIG_SERIAL_TXX9 */
+}
diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c
new file mode 100644
index 00000000000..317378d8579
--- /dev/null
+++ b/arch/mips/txx9/generic/setup_tx4938.c
@@ -0,0 +1,259 @@
+/*
+ * 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/serial_core.h>
+#include <linux/param.h>
+#include <asm/txx9irq.h>
+#include <asm/txx9tmr.h>
+#include <asm/txx9pio.h>
+#include <asm/txx9/generic.h>
+#include <asm/txx9/tx4938.h>
+
+void __init tx4938_wdr_init(void)
+{
+ /* clear WatchDogReset (W1C) */
+ tx4938_ccfg_set(TX4938_CCFG_WDRST);
+ /* do reset on watchdog */
+ tx4938_ccfg_set(TX4938_CCFG_WR);
+}
+
+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;
+ int cpuclk = 0;
+ u64 ccfg;
+
+ txx9_reg_res_init(TX4938_REV_PCODE(), TX4938_REG_BASE,
+ TX4938_REG_SIZE);
+
+ /* 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);
+
+ printk(KERN_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),
+ (unsigned long long)____raw_readq(&tx4938_ccfgptr->ccfg),
+ (unsigned long long)____raw_readq(&tx4938_ccfgptr->pcfg));
+
+ printk(KERN_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;
+ printk(" CR%d:%016llx", i, (unsigned long long)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]);
+ }
+ printk(" TR:%09llx\n",
+ (unsigned long long)____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);
+
+ /* DMA */
+ for (i = 0; i < 2; i++)
+ ____raw_writeq(TX4938_DMA_MCR_MSTEN,
+ (void __iomem *)(TX4938_DMA_REG(i) + 0x50));
+
+ /* PIO */
+ txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, TX4938_NUM_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 {
+ printk(KERN_INFO "%s: stop PCIC1\n", txx9_pcode_str);
+ /* stop PCIC1 */
+ txx9_set64(&tx4938_ccfgptr->clkctr,
+ TX4938_CLKCTR_PCIC1CKD);
+ }
+ if (!(pcfg & TX4938_PCFG_ETH0_SEL)) {
+ printk(KERN_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)) {
+ printk(KERN_INFO "%s: stop ETH1\n", txx9_pcode_str);
+ txx9_set64(&tx4938_ccfgptr->clkctr,
+ TX4938_CLKCTR_ETH1RST);
+ txx9_set64(&tx4938_ccfgptr->clkctr,
+ TX4938_CLKCTR_ETH1CKD);
+ }
+ }
+}
+
+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_setup_serial(void)
+{
+#ifdef CONFIG_SERIAL_TXX9
+ int i;
+ struct uart_port req;
+ 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;
+ memset(&req, 0, sizeof(req));
+ req.line = i;
+ req.iotype = UPIO_MEM;
+ req.membase = (unsigned char __iomem *)TX4938_SIO_REG(i);
+ req.mapbase = TX4938_SIO_REG(i) & 0xfffffffffULL;
+ req.irq = TXX9_IRQ_BASE + TX4938_IR_SIO(i);
+ req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+ req.uartclk = TXX9_IMCLK;
+ early_serial_txx9_setup(&req);
+ }
+#endif /* CONFIG_SERIAL_TXX9 */
+}
diff --git a/arch/mips/txx9/generic/smsc_fdc37m81x.c b/arch/mips/txx9/generic/smsc_fdc37m81x.c
new file mode 100644
index 00000000000..69e487467fa
--- /dev/null
+++ b/arch/mips/txx9/generic/smsc_fdc37m81x.c
@@ -0,0 +1,172 @@
+/*
+ * 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>
+
+#define DEBUG
+
+/* 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 = 0;
+
+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)
+ printk("smsc_fdc37m81x_init() stepping on old base=0x%0*lx\n",
+ 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 {
+ printk("smsc_fdc37m81x_init() unknow chip id 0x%02x\n",
+ chip_id);
+ g_smsc_fdc37m81x_base = 0;
+ }
+
+ return g_smsc_fdc37m81x_base;
+}
+
+#ifdef DEBUG
+void smsc_fdc37m81x_config_dump_one(char *key, u8 dev, u8 reg)
+{
+ printk("%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;
+ char *fname = "smsc_fdc37m81x_config_dump()";
+
+ smsc_fdc37m81x_config_beg();
+
+ orig = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DNUM);
+
+ printk("%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);
+
+ printk("%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