]> git.hungrycats.org Git - linux/commitdiff
[ALPHA] Marvel (AlphaServer ES47, ES80, GS1280) support.
authorRichard Henderson <rth@kanga.twiddle.net>
Thu, 16 Jan 2003 06:23:54 +0000 (22:23 -0800)
committerRichard Henderson <rth@dorothy.sfbay.redhat.com>
Thu, 16 Jan 2003 06:23:54 +0000 (22:23 -0800)
From Jeff.Wiedemeier@hp.com.

16 files changed:
arch/alpha/Kconfig
arch/alpha/kernel/Makefile
arch/alpha/kernel/core_marvel.c [new file with mode: 0644]
arch/alpha/kernel/err_impl.h
arch/alpha/kernel/err_marvel.c [new file with mode: 0644]
arch/alpha/kernel/gct.c [new file with mode: 0644]
arch/alpha/kernel/machvec_impl.h
arch/alpha/kernel/proto.h
arch/alpha/kernel/setup.c
arch/alpha/kernel/sys_marvel.c [new file with mode: 0644]
include/asm-alpha/core_marvel.h [new file with mode: 0644]
include/asm-alpha/gct.h [new file with mode: 0644]
include/asm-alpha/hwrpb.h
include/asm-alpha/io.h
include/asm-alpha/irq.h
include/asm-alpha/pci.h

index ba515492c876280c55db8da2fc3e27a500f960f3..2534b7d96625b1dedbe3d54cc5b70f55c3d4068c 100644 (file)
@@ -65,6 +65,7 @@ choice
          LX164               AlphaPC164-LX
          Miata               Personal Workstation 433a, 433au, 500a,
          500au, 600a, or 600au
+         Marvel              AlphaServer ES47 / ES80 / GS1280
          Mikasa              AS 1000
          Noname              AXPpci33, UDB (Multia)
          Noritake            AS 1000A, AS 600A, AS 800
@@ -172,6 +173,11 @@ config ALPHA_LX164
          A technical overview of this board is available at
          <http://www.unix-ag.org/Linux-Alpha/Architectures/LX164.html>.
 
+config ALPHA_MARVEL
+       bool "Marvel"
+       help
+         AlphaServer ES47 / ES80 / GS1280 based on EV7.
+
 config ALPHA_MIATA
        bool "Miata"
        help
@@ -394,7 +400,7 @@ config ALPHA_PYXIS
 
 config ALPHA_EV6
        bool
-       depends on ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_DP264 || ALPHA_EIGER
+       depends on ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_DP264 || ALPHA_EIGER || ALPHA_MARVEL
        default y
 
 config ALPHA_TSUNAMI
@@ -404,11 +410,16 @@ config ALPHA_TSUNAMI
 
 config ALPHA_EV67
        bool "EV67 (or later) CPU (speed > 600MHz)?" if ALPHA_DP264 || ALPHA_EIGER
-       default y if ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK
+       default y if ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
        help
          Is this a machine based on the EV67 core?  If in doubt, select N here
          and the machine will be treated as an EV6.
 
+config ALPHA_EV7
+       bool
+       depends on ALPHA_MARVEL
+       default y
+
 config ALPHA_MCPCIA
        bool
        depends on ALPHA_RAWHIDE
@@ -426,7 +437,7 @@ config ALPHA_IRONGATE
 
 config ALPHA_SRM
        bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME
-       default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK
+       default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
        ---help---
          There are two different types of booting firmware on Alphas: SRM,
          which is command line driven, and ARC, which uses menus and arrow
@@ -468,7 +479,7 @@ config ALPHA_BROKEN_IRQ_MASK
 
 config SMP
        bool "Symmetric multi-processing support"
-       depends on ALPHA_SABLE || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK
+       depends on ALPHA_SABLE || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL
        ---help---
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index 62680754792f79863132a4398d19f8c0f3efd7c7..c36669ef64411937bffa4f12a5ccf55d3473a1b0 100644 (file)
@@ -21,20 +21,19 @@ obj-$(CONFIG_MODULES)       += module.o
 ifdef CONFIG_ALPHA_GENERIC
 
 obj-y   += core_apecs.o core_cia.o core_irongate.o core_lca.o \
-           core_mcpcia.o core_polaris.o core_t2.o core_tsunami.o \
-           core_titan.o core_wildfire.o
+           core_marvel.o core_mcpcia.o core_polaris.o core_t2.o \
+           core_tsunami.o core_titan.o core_wildfire.o
 
 obj-y   += sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \
-           sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o sys_titan.o \
-           sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
-           sys_sable.o sys_sio.o sys_sx164.o sys_takara.o \
-           sys_wildfire.o
+           sys_jensen.o sys_marvel.o sys_miata.o sys_mikasa.o sys_nautilus.o \
+           sys_titan.o sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
+           sys_sable.o sys_sio.o sys_sx164.o sys_takara.o sys_wildfire.o
 
 obj-y   += irq_pyxis.o irq_i8259.o irq_srm.o
 
-obj-y   += es1888.o smc37c669.o smc37c93x.o ns87312.o
+obj-y    += err_titan.o err_marvel.o
 
-obj-y    += err_titan.o
+obj-y   += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
 
 else
 
@@ -43,6 +42,7 @@ obj-$(CONFIG_ALPHA_APECS)     += core_apecs.o
 obj-$(CONFIG_ALPHA_CIA)                += core_cia.o
 obj-$(CONFIG_ALPHA_IRONGATE)   += core_irongate.o
 obj-$(CONFIG_ALPHA_LCA)                += core_lca.o
+obj-$(CONFIG_ALPHA_MARVEL)     += core_marvel.o gct.o
 obj-$(CONFIG_ALPHA_MCPCIA)     += core_mcpcia.o
 obj-$(CONFIG_ALPHA_POLARIS)    += core_polaris.o
 obj-$(CONFIG_ALPHA_T2)         += core_t2.o
@@ -70,6 +70,7 @@ obj-$(CONFIG_ALPHA_EB64P)     += sys_eb64p.o irq_i8259.o
 obj-$(CONFIG_ALPHA_EB66)       += sys_eb64p.o irq_i8259.o
 obj-$(CONFIG_ALPHA_EIGER)      += sys_eiger.o irq_i8259.o
 obj-$(CONFIG_ALPHA_JENSEN)     += sys_jensen.o pci-noop.o irq_i8259.o
+obj-$(CONFIG_ALPHA_MARVEL)     += sys_marvel.o err_marvel.o
 obj-$(CONFIG_ALPHA_MIATA)      += sys_miata.o irq_pyxis.o irq_i8259.o \
                                   es1888.o smc37c669.o
 obj-$(CONFIG_ALPHA_MIKASA)     += sys_mikasa.o irq_i8259.o irq_srm.o
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
new file mode 100644 (file)
index 0000000..a7462bd
--- /dev/null
@@ -0,0 +1,1100 @@
+/*
+ *     linux/arch/alpha/kernel/core_marvel.c
+ *
+ * Code common to all Marvel based systems
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/mc146818rtc.h>
+#include <linux/rtc.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/smp.h>
+#include <asm/hwrpb.h>
+#include <asm/gct.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/rtc.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_marvel.h>
+#undef __EXTERN_INLINE
+
+#include <linux/bootmem.h>     /* this must be *after* io.h / core_marvel.h */
+
+#include "proto.h"
+#include "pci_impl.h"
+
+\f
+/*
+ * Debug helpers
+ */
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
+# define DBG_CFG(args) printk args
+#else
+# define DBG_CFG(args)
+#endif
+
+\f
+/*
+ * Private data
+ */
+static struct io7 *io7_head = NULL;
+
+\f
+/*
+ * Helper functions
+ */
+static unsigned long 
+read_ev7_csr(int pe, unsigned long offset)
+{
+       ev7_csr *ev7csr = EV7_CSR_KERN(pe, offset);
+       unsigned long q;
+
+       mb();
+       q = ev7csr->csr;
+       mb();
+
+       return q;
+}
+
+static void __attribute__ ((unused))
+write_ev7_csr(int pe, unsigned long offset, unsigned long q)
+{
+       ev7_csr *ev7csr = EV7_CSR_KERN(pe, offset);
+
+       mb();
+       ev7csr->csr = q;
+       mb();
+}
+
+static char * __init
+mk_resource_name(int pe, int port, char *str)
+{
+       char tmp[80];
+       char *name;
+       
+       sprintf(tmp, "PCI %s PE %d PORT %d", str, pe, port);
+       name = alloc_bootmem(strlen(tmp) + 1);
+       strcpy(name, tmp);
+
+       return name;
+}
+
+struct io7 *marvel_next_io7(struct io7 *prev)
+{
+       if (!prev) return io7_head;
+       return prev->next;
+}
+
+struct io7 *marvel_find_io7(int pe)
+{
+       struct io7 *io7;
+
+       io7 = marvel_next_io7(NULL);
+       for(; io7 && io7->pe != pe; io7 = marvel_next_io7(io7));
+
+       return io7;
+}
+
+static struct io7 * __init
+alloc_io7(unsigned int pe)
+{
+       struct io7 *io7;
+       struct io7 *insp;
+       int h;
+
+       if (marvel_find_io7(pe)) {
+               printk(KERN_WARNING "IO7 at PE %d already allocated!\n", pe);
+               return NULL;
+       }
+
+       io7 = alloc_bootmem(sizeof(*io7));
+       io7->pe = pe;
+       io7->irq_lock = SPIN_LOCK_UNLOCKED;
+
+       for(h = 0; h < 4; h++) {
+               io7->ports[h].io7 = io7;
+               io7->ports[h].port = h;
+               io7->ports[h].enabled = 0; /* default to disabled */
+       }
+
+       /*
+        * insert in pe sorted order
+        */
+       if (NULL == io7_head)                   /* empty list */
+               io7_head = io7; 
+       else if (io7_head->pe > io7->pe) {      /* insert at head */
+               io7->next = io7_head;
+               io7_head = io7;
+       } else {                                /* insert at position */
+               for(insp = io7_head; insp; insp = insp->next) {
+                       if (insp->pe == io7->pe) {
+                               printk(KERN_ERR "Too many IO7s at PE %d\n", 
+                                      io7->pe);
+                               return NULL;
+                       }
+
+                       if (NULL == insp->next || 
+                           insp->next->pe > io7->pe) { /* insert here */
+                               io7->next = insp->next;
+                               insp->next = io7;
+                               break;
+                       }
+               }
+
+               if (NULL == insp) { /* couldn't insert ?!? */
+                       printk(KERN_WARNING "Failed to insert IO7 at PE %d "
+                              " - adding at head of list\n", io7->pe);
+                       io7->next = io7_head;
+                       io7_head = io7;
+               }
+       }
+       
+       return io7;
+}
+
+void
+io7_clear_errors(struct io7 *io7)
+{
+       io7_port7_csrs *p7csrs;
+       io7_ioport_csrs *csrs;
+       int port;
+
+
+       /*
+        * First the IO ports
+        */
+       for(port = 0; port < 4; port++) {
+               csrs = IO7_CSRS_KERN(io7->pe, port);
+
+               csrs->POx_ERR_SUM.csr = (unsigned long)-1L;
+               csrs->POx_TLB_ERR.csr = (unsigned long)-1L;
+               csrs->POx_SPL_COMPLT.csr = (unsigned long)-1L;
+               csrs->POx_TRANS_SUM.csr = (unsigned long)-1L;
+       }
+
+       /*
+        * Then the common ones
+        */
+       p7csrs = IO7_PORT7_CSRS_KERN(io7->pe);
+
+       p7csrs->PO7_ERROR_SUM.csr = (unsigned long)-1L;
+       p7csrs->PO7_UNCRR_SYM.csr = (unsigned long)-1L;
+       p7csrs->PO7_CRRCT_SYM.csr = (unsigned long)-1L;
+}
+
+\f
+/*
+ * IO7 PCI, PCI/X, AGP configuration
+ */
+static void __init
+io7_init_hose(struct io7 *io7, int port)
+{
+       static int hose_index = 0;
+
+       struct pci_controller *hose = alloc_pci_controller();
+       struct io7_port *io7_port = &io7->ports[port];
+       io7_ioport_csrs *csrs = IO7_CSRS_KERN(io7->pe, port);
+       int i;
+
+       hose->index = hose_index++;     /* arbitrary */
+       
+       /*
+        * We don't have an isa or legacy hose, but glibc expects to be
+        * able to use the bus == 0 / dev == 0 form of the iobase syscall
+        * to determine information about the i/o system. Since XFree86 
+        * relies on glibc's determination to tell whether or not to use
+        * sparse access, we need to point the pci_isa_hose at a real hose
+        * so at least that determination is correct.
+        */
+       if (hose->index == 0)
+               pci_isa_hose = hose;
+
+       io7_port->csrs = csrs;
+       io7_port->hose = hose;
+       hose->sysdata = io7_port;
+
+       hose->io_space = alloc_resource();
+       hose->mem_space = alloc_resource();
+
+       /*
+        * Base addresses for userland consumption. Since these are going
+        * to be mapped, they are pure physical addresses.
+        */
+       hose->sparse_mem_base = hose->sparse_io_base = 0;
+       hose->dense_mem_base = IO7_MEM_PHYS(io7->pe, port);
+       hose->dense_io_base = IO7_IO_PHYS(io7->pe, port);
+
+       /*
+        * Base addresses and resource ranges for kernel consumption
+        */
+       hose->config_space_base = (unsigned long)IO7_CONF_KERN(io7->pe, port);
+
+       hose->io_space->start = (unsigned long)IO7_IO_KERN(io7->pe, port);
+       hose->io_space->end = hose->io_space->start + IO7_IO_SPACE - 1;
+       hose->io_space->name = mk_resource_name(io7->pe, port, "IO");
+       hose->io_space->flags = IORESOURCE_IO;
+
+       hose->mem_space->start = (unsigned long)IO7_MEM_KERN(io7->pe, port);
+       hose->mem_space->end = hose->mem_space->start + IO7_MEM_SPACE - 1;
+       hose->mem_space->name = mk_resource_name(io7->pe, port, "MEM");
+       hose->mem_space->flags = IORESOURCE_MEM;
+
+       if (request_resource(&ioport_resource, hose->io_space) < 0)
+               printk(KERN_ERR "Failed to request IO on hose %d\n", 
+                      hose->index);
+       if (request_resource(&iomem_resource, hose->mem_space) < 0)
+               printk(KERN_ERR "Failed to request MEM on hose %d\n", 
+                      hose->index);
+
+       /*
+        * Save the existing DMA window settings for later restoration
+        */
+       for(i = 0; i < 4; i++) {
+               io7_port->saved_wbase[i] = csrs->POx_WBASE[i].csr;
+               io7_port->saved_wmask[i] = csrs->POx_WMASK[i].csr;
+               io7_port->saved_tbase[i] = csrs->POx_TBASE[i].csr;
+       }
+
+       /*
+        * Set up the PCI to main memory translation windows.
+        *
+        * Window 0 is scatter-gather 8MB at 8MB
+        * Window 1 is direct access 1GB at 2GB
+        * Window 2 is scatter-gather (up-to) 1GB at 3GB
+        * Window 3 is disabled
+        */
+
+       /*
+        * tbia before modifying windows
+        */
+       marvel_pci_tbi(hose, 0, -1);
+
+       /*
+        * set up window 0 for scatter-gather 8MB at 8MB
+        */
+       hose->sg_isa = iommu_arena_new_node(marvel_cpuid_to_nid(io7->pe),
+                                           hose, 0x00800000, 0x00800000, 0);
+       hose->sg_isa->align_entry = 8;  /* cache line boundary */
+       csrs->POx_WBASE[0].csr = 
+               hose->sg_isa->dma_base | wbase_m_ena | wbase_m_sg;
+       csrs->POx_WMASK[0].csr = (hose->sg_isa->size - 1) & wbase_m_addr;
+       csrs->POx_TBASE[0].csr = virt_to_phys(hose->sg_isa->ptes);
+
+       /*
+        * set up window 1 for direct-mapped 1GB at 2GB
+        */
+       csrs->POx_WBASE[1].csr = __direct_map_base | wbase_m_ena;
+       csrs->POx_WMASK[1].csr = (__direct_map_size - 1) & wbase_m_addr;
+       csrs->POx_TBASE[1].csr = 0;
+
+       /*
+        * set up window 2 for scatter-gather (up-to) 1GB at 3GB
+        */
+       hose->sg_pci = iommu_arena_new_node(marvel_cpuid_to_nid(io7->pe),
+                                           hose, 0xc0000000, 0x40000000, 0);
+       hose->sg_pci->align_entry = 8;  /* cache line boundary */
+       csrs->POx_WBASE[2].csr = 
+               hose->sg_pci->dma_base | wbase_m_ena | wbase_m_sg;
+       csrs->POx_WMASK[2].csr = (hose->sg_pci->size - 1) & wbase_m_addr;
+       csrs->POx_TBASE[2].csr = virt_to_phys(hose->sg_pci->ptes);
+
+       /*
+        * disable window 3
+        */
+       csrs->POx_WBASE[3].csr = 0;
+
+       /*
+        * Make sure that the AGP Monster Window is disabled
+        */
+       csrs->POx_CTRL.csr &= ~(1UL << 61);
+
+#if 1
+       printk("FIXME: disabling master aborts\n");
+       csrs->POx_MSK_HEI.csr &= ~(3UL << 14);
+#endif
+       /*
+        * tbia after modifying windows
+        */
+       marvel_pci_tbi(hose, 0, -1);
+}
+
+static void __init
+marvel_init_io7(struct io7 *io7)
+{
+       int i;
+
+       printk("Initializing IO7 at PID %d\n", io7->pe);
+
+       /*
+        * Get the Port 7 CSR pointer
+        */
+       io7->csrs = IO7_PORT7_CSRS_KERN(io7->pe);
+
+       /*
+        * Init this IO7's hoses
+        */
+       for(i = 0; i < IO7_NUM_PORTS; i++) {
+               io7_ioport_csrs *csrs = IO7_CSRS_KERN(io7->pe, i);
+               if (csrs->POx_CACHE_CTL.csr == 8) {
+                       io7->ports[i].enabled = 1;
+                       io7_init_hose(io7, i);
+               }
+       }
+}
+
+void marvel_io7_present(gct6_node *node)
+{
+       int pe;
+
+       if (node->type != GCT_TYPE_HOSE ||
+           node->subtype != GCT_SUBTYPE_IO_PORT_MODULE) 
+               return;
+
+       pe = (node->id >> 8) & 0xff;
+       printk("Found an IO7 at PID %d\n", pe);
+
+       alloc_io7(pe);
+}
+
+static void __init
+marvel_init_vga_hose(void)
+{
+#ifdef CONFIG_VGA_HOSE
+       u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
+
+       if (pu64[7] == 3) {     /* TERM_TYPE == graphics */
+               struct pci_controller *hose = NULL;
+               int h = (pu64[30] >> 24) & 0xff; /* TERM_OUT_LOC, hose # */
+               struct io7 *io7;
+               int pid, port;
+
+               /* FIXME - encoding is going to have to change for Marvel
+                *         since hose will be able to overflow a byte...
+                *         need to fix this decode when the console 
+                *         changes its encoding
+                */
+               printk("console graphics is on hose %d (console)\n", h);
+
+               /*
+                * The console's hose numbering is:
+                *
+                *      hose<n:2>: PID
+                *      hose<1:0>: PORT
+                *
+                * We need to find the hose at that pid and port
+                */
+               pid = h >> 2;
+               port = h & 3;
+               if ((io7 = marvel_find_io7(pid)))
+                       hose = io7->ports[port].hose;
+
+               if (hose) {
+                       printk("Console graphics on hose %d\n", hose->index);
+                       pci_vga_hose = hose;
+               }
+       }
+#endif /* CONFIG_VGA_HOSE */
+}
+
+gct6_search_struct gct_wanted_node_list[] = {
+       { GCT_TYPE_HOSE, GCT_SUBTYPE_IO_PORT_MODULE, marvel_io7_present },
+       { 0, 0, NULL }
+};
+
+/*
+ * In case the GCT is not complete, let the user specify PIDs with IO7s
+ * at boot time. Syntax is 'io7=a,b,c,...,n' where a-n are the PIDs (decimal)
+ * where IO7s are connected
+ */
+static int __init marvel_specify_io7(char *str)
+{
+       unsigned long pid;
+       struct io7 *io7;
+       char *pchar;
+
+       do {
+               pid = simple_strtoul(str, &pchar, 0);
+               if (pchar != str) {
+                       printk("User-specified IO7 at PID %lu\n", pid);
+                       io7 = alloc_io7(pid);
+                       if (io7) marvel_init_io7(io7);
+               }
+
+               if (pchar == str) pchar++;
+               str = pchar;
+       } while(*str);
+
+       return 0;
+}
+__setup("io7=", marvel_specify_io7);
+
+void __init
+marvel_init_arch(void)
+{
+       struct io7 *io7;
+
+       /* With multiple PCI busses, we play with I/O as physical addrs.  */
+       ioport_resource.end = ~0UL;
+       iomem_resource.end = ~0UL;
+
+       /* PCI DMA Direct Mapping is 1GB at 2GB */
+       __direct_map_base = 0x80000000;
+       __direct_map_size = 0x40000000;
+
+       /* parse the config tree */
+       gct6_find_nodes(GCT_NODE_PTR(0), gct_wanted_node_list);
+
+       /* init the io7s */
+       for(io7 = NULL; NULL != (io7 = marvel_next_io7(io7)); ) 
+               marvel_init_io7(io7);
+
+       /* Check for graphic console location (if any) */
+       marvel_init_vga_hose();
+}
+
+void
+marvel_kill_arch(int mode)
+{
+}
+
+\f
+/*
+ * PCI Configuration Space access functions
+ *
+ * Configuration space addresses have the following format:
+ *
+ *     |2 2 2 2|1 1 1 1|1 1 1 1|1 1 
+ *     |3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *     |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|R|R|
+ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *      n:24   reserved for hose base
+ *     23:16   bus number (8 bits = 128 possible buses)
+ *     15:11   Device number (5 bits)
+ *     10:8    function number
+ *      7:2    register number
+ *  
+ * Notes:
+ *     IO7 determines whether to use a type 0 or type 1 config cycle
+ *     based on the bus number. Therefore the bus number must be set 
+ *     to 0 for the root bus on any hose.
+ *     
+ *     The function number selects which function of a multi-function device 
+ *     (e.g., SCSI and Ethernet).
+ * 
+ */
+
+static inline unsigned long
+build_conf_addr(struct pci_controller *hose, u8 bus, 
+                unsigned int devfn, int where)
+{
+       return (hose->config_space_base | (bus << 16) | (devfn << 8) | where);
+}
+
+static unsigned long
+mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where)
+{
+       struct pci_controller *hose = pbus->sysdata;
+       struct io7_port *io7_port;
+       unsigned long addr = 0;
+       u8 bus = pbus->number;
+
+       if (!hose)
+               return addr;
+
+       /* check for enabled... */
+       io7_port = hose->sysdata;
+       if (!io7_port->enabled)
+               return addr;
+
+       if (hose->first_busno == bus) {
+               /* don't support idsel > 20 on primary bus */
+               if (devfn >= PCI_DEVFN(21, 0)) return addr;
+               bus = 0;
+       }
+
+       addr = build_conf_addr(hose, bus, devfn, where);
+
+       DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+       return addr;
+}
+
+static int
+marvel_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+                  int size, u32 *value)
+{
+       unsigned long addr;
+       
+       if (0 == (addr = mk_conf_addr(bus, devfn, where)))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       switch(size) {
+       case 1: 
+               *value = __kernel_ldbu(*(vucp)addr);
+               break;
+       case 2: 
+               *value = __kernel_ldwu(*(vusp)addr);
+               break;
+       case 4: 
+               *value = *(vuip)addr;
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+marvel_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+                   int size, u32 value)
+{
+       unsigned long addr;
+       
+       if (0 == (addr = mk_conf_addr(bus, devfn, where)))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       switch (size) {
+       case 1:
+               __kernel_stb(value, *(vucp)addr);
+               mb();
+               __kernel_ldbu(*(vucp)addr);
+               break;
+       case 2:
+               __kernel_stw(value, *(vusp)addr);
+               mb();
+               __kernel_ldwu(*(vusp)addr);
+               break;
+       case 4:
+               *(vuip)addr = value;
+               mb();
+               *(vuip)addr;
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops marvel_pci_ops =
+{
+       .read =         marvel_read_config,
+       .write =        marvel_write_config,
+};
+
+\f
+/*
+ * Other PCI helper functions
+ */
+void
+marvel_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
+{
+       io7_ioport_csrs *csrs = ((struct io7_port *)hose->sysdata)->csrs;
+
+       wmb();
+       csrs->POx_SG_TBIA.csr = 0;
+       mb();
+       csrs->POx_SG_TBIA.csr;
+}
+
+\f
+/*
+ * IO map support
+ */
+unsigned long
+marvel_ioremap(unsigned long addr, unsigned long size)
+{
+       extern struct pci_controller *hose_head;
+       struct pci_controller *hose;
+       unsigned long baddr, last;
+       struct vm_struct *area;
+       unsigned long vaddr;
+       unsigned long *ptes;
+       unsigned long pfn;
+
+       /*
+        * Adjust the addr
+        */ 
+#ifdef CONFIG_VGA_HOSE
+       if (pci_vga_hose && __marvel_is_mem_vga(addr)) {
+               addr += pci_vga_hose->mem_space->start;
+       }
+#endif
+
+       if (!marvel_is_ioaddr(addr)) return 0UL;
+
+       /*
+        * Find the hose
+        */
+       for(hose = hose_head; hose; hose = hose->next) {
+               if ((addr >> 32) == (hose->mem_space->start >> 32)) break; 
+       }
+       if (!hose) return 0UL;
+
+       /*
+        * We have the hose - calculate the bus limits
+        */
+       baddr = addr - hose->mem_space->start;
+       last = baddr + size - 1;
+
+       /*
+        * Is it direct-mapped?
+        */
+       if ((baddr >= __direct_map_base) && 
+           ((baddr + size - 1) < __direct_map_base + __direct_map_size)) 
+               return IDENT_ADDR | (baddr - __direct_map_base);
+
+       /* 
+        * Check the scatter-gather arena...
+        */
+       if (hose->sg_pci &&
+           baddr >= (unsigned long)hose->sg_pci->dma_base &&
+           last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size){
+
+               /*
+                * Adjust the limits (mappings must be page aligned)
+                */
+               baddr -= hose->sg_pci->dma_base;
+               last -= hose->sg_pci->dma_base;
+               baddr &= PAGE_MASK;
+               size = PAGE_ALIGN(last) - baddr;
+
+               /*
+                * Map it
+                */
+               area = get_vm_area(size, VM_IOREMAP);
+               if (!area) return (unsigned long)NULL;
+               ptes = hose->sg_pci->ptes;
+               for(vaddr = (unsigned long)area->addr; 
+                   baddr <= last; 
+                   baddr += PAGE_SIZE, vaddr += PAGE_SIZE) {
+                       pfn = ptes[baddr >> PAGE_SHIFT];
+                       if (!(pfn & 1)) {
+                               printk("ioremap failed... pte not valid...\n");
+                               vfree(area->addr);
+                               return 0UL;
+                       }
+                       pfn >>= 1;      /* make it a true pfn */
+                       
+                       if (__alpha_remap_area_pages(VMALLOC_VMADDR(vaddr), 
+                                                    pfn << PAGE_SHIFT, 
+                                                    PAGE_SIZE, 0)) {
+                               printk("FAILED to map...\n");
+                               vfree(area->addr);
+                               return 0UL;
+                       }
+               }
+
+               flush_tlb_all();
+
+               vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
+
+               return vaddr;
+       }
+
+       /*
+        * Not found - assume legacy ioremap
+        */
+       return addr;
+}
+
+void
+marvel_iounmap(unsigned long addr)
+{
+       if (((long)addr >> 41) == -2)
+               return; /* kseg map, nothing to do */
+       if (addr) return vfree((void *)(PAGE_MASK & addr)); 
+}
+
+\f
+/*
+ * SRMCons support
+ *
+ * Marvel doesn't have a real serial console -- it's either graphics or 
+ * server management based. If we're running on the server management based
+ * console, allow the srmcons callback driver to be a console device
+ */
+int marvel_srmcons_allowed(void)
+{
+       u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
+
+       if (pu64[7] == 2) return 1;
+       return 0;
+}
+
+
+\f
+/*
+ * RTC Support
+ */
+struct marvel_rtc_access_info {
+       unsigned long function;
+       unsigned long index;
+       unsigned long data;
+};
+
+static void __marvel_access_rtc(void *info)
+{
+       struct marvel_rtc_access_info *rtc_access = info;
+
+       register unsigned long __r0 __asm__("$0");
+       register unsigned long __r16 __asm__("$16") = rtc_access->function;
+       register unsigned long __r17 __asm__("$17") = rtc_access->index;
+       register unsigned long __r18 __asm__("$18") = rtc_access->data;
+       
+       __asm__ __volatile__(
+               "call_pal %4 # cserve rtc"
+               : "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0)
+               : "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18)
+               : "$1", "$22", "$23", "$24", "$25");
+
+       rtc_access->data = __r0;
+}
+
+u8 __marvel_rtc_io(int write, u8 b, unsigned long addr)
+{
+       struct marvel_rtc_access_info rtc_access = {0, };
+       static u8 index = 0;
+       u8 ret = 0;
+
+       switch(addr) {
+       case 0x70:                                      /* RTC_PORT(0) */
+               if (write) index = b;
+               ret = index;
+               break;
+
+       case 0x71:                                      /* RTC_PORT(1) */
+               rtc_access.index = index;
+               rtc_access.data = BCD_TO_BIN(b);
+               rtc_access.function = 0x49;             /* GET_TOY */
+               if (write) rtc_access.function = 0x48;  /* PUT_TOY */
+
+#if CONFIG_SMP
+               if (smp_processor_id() != boot_cpuid)
+                       smp_call_function_on_cpu(__marvel_access_rtc,
+                                                &rtc_access,
+                                                1,     /* retry */
+                                                1,     /* wait  */
+                                                1UL << boot_cpuid);
+               else
+                       __marvel_access_rtc(&rtc_access);
+#else
+               __marvel_access_rtc(&rtc_access);
+#endif
+               ret = BIN_TO_BCD(rtc_access.data);
+               
+               break;
+
+       default:
+               printk(KERN_WARNING "Illegal RTC port %lx\n", addr);
+               break;
+       }
+
+       return ret;
+}
+
+
+\f
+/*
+ * NUMA Support
+ */
+/**********
+ * FIXME - for now each cpu is a node by itself 
+ *              -- no real support for striped mode 
+ **********
+ */
+int marvel_pa_to_nid(unsigned long pa)
+{
+       int cpuid;
+
+       if ((pa >> 43) & 1)     /* I/O */ 
+               cpuid = (~(pa >> 35) & 0xff);
+       else                    /* mem */
+               cpuid = ((pa >> 34) & 0x3) | ((pa >> (37 - 2)) & (0x1f << 2));
+
+       return marvel_cpuid_to_nid(cpuid);
+}
+
+int marvel_cpuid_to_nid(int cpuid)
+{
+       return cpuid;
+}
+
+unsigned long marvel_node_mem_start(int nid)
+{
+       unsigned long pa;
+
+       pa = (nid & 0x3) | ((nid & (0x1f << 2)) << 1);
+       pa <<= 34;
+
+       return pa;
+}
+
+unsigned long marvel_node_mem_size(int nid)
+{
+       return 16UL * 1024 * 1024 * 1024; /* 16GB */
+}
+
+\f
+/* 
+ * AGP GART Support
+ */
+#include <linux/agp_backend.h>
+#include <asm/agp_backend.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#define MARVEL_AGP_APER_SIZE (64 * 1024 * 1024)
+
+struct marvel_agp_aperture {
+       struct pci_iommu_arena *arena;
+       long pg_start;
+       long pg_count;
+};
+
+static int marvel_agp_setup(alpha_agp_info *agp)
+{
+       struct marvel_agp_aperture *aper;
+
+       aper = kmalloc(sizeof(*aper), GFP_KERNEL);
+       if (aper == NULL) return -ENOMEM;
+
+       aper->arena = agp->hose->sg_pci;
+       aper->pg_count = MARVEL_AGP_APER_SIZE / PAGE_SIZE;
+       aper->pg_start = iommu_reserve(aper->arena, aper->pg_count,
+                                       aper->pg_count - 1);
+
+       if (aper->pg_start < 0) {
+               printk(KERN_ERR "Failed to reserve AGP memory\n");
+               kfree(aper);
+               return -ENOMEM;
+       }
+
+       agp->aperture.bus_base = 
+               aper->arena->dma_base + aper->pg_start * PAGE_SIZE;
+       agp->aperture.size = aper->pg_count * PAGE_SIZE;
+       agp->aperture.sysdata = aper;
+
+       return 0;
+}
+
+static void marvel_agp_cleanup(alpha_agp_info *agp)
+{
+       struct marvel_agp_aperture *aper = agp->aperture.sysdata;
+       int status;
+
+       status = iommu_release(aper->arena, aper->pg_start, aper->pg_count);
+       if (status == -EBUSY) {
+               printk(KERN_WARNING
+                      "Attempted to release bound AGP memory - unbinding\n");
+               iommu_unbind(aper->arena, aper->pg_start, aper->pg_count);
+               status = iommu_release(aper->arena, aper->pg_start, 
+                                      aper->pg_count);
+       }
+       if (status < 0) printk(KERN_ERR "Failed to release AGP memory\n");
+
+       kfree(aper);
+       kfree(agp);
+}
+
+static int marvel_agp_configure(alpha_agp_info *agp)
+{
+       io7_ioport_csrs *csrs = ((struct io7_port *)agp->hose->sysdata)->csrs;
+       struct io7 *io7 = ((struct io7_port *)agp->hose->sysdata)->io7;
+       unsigned int new_rate = 0;
+       unsigned long agp_pll;
+
+       /*
+        * Check the requested mode against the PLL setting.
+        * The agpgart_be code has not programmed the card yet, so we can
+        * still tweak mode here 
+        */
+       agp_pll = io7->csrs->POx_RST[IO7_AGP_PORT].csr;
+       switch(IO7_PLL_RNGB(agp_pll)) {
+       case 0x4:                               /* 2x only */
+               /* 
+                * The PLL is only programmed for 2x, so adjust the
+                * rate to 2x, if necessary
+                */
+               if (agp->mode.bits.rate != 2) 
+                       new_rate = 2;
+               break;
+
+       case 0x6:                               /* 1x / 4x */
+               /*
+                * The PLL is programmed for 1x or 4x. Don't go faster
+                * than requested, so if the requested rate is 2x, use 1x
+                */
+               if (agp->mode.bits.rate == 2) 
+                       new_rate = 1;
+               break;
+
+       default:                                /* ??????? */
+               /*
+                * Don't know what this PLL setting is, take the requested
+                * rate, but warn the user
+                */
+               printk("%s: unknown PLL setting RNGB=%lx (PLL6_CTL=%016lx)\n",
+                      __FUNCTION__, IO7_PLL_RNGB(agp_pll), agp_pll);
+               break;
+       }
+
+       /*
+        * Set the new rate, if necessary
+        */
+       if (new_rate) {
+               printk("Requested AGP Rate %dX not compatible "
+                      "with PLL setting - using %dX\n",
+                      agp->mode.bits.rate,
+                      new_rate);
+
+               agp->mode.bits.rate = new_rate;
+       }
+               
+       printk("Enabling AGP on hose %d: %dX%s RQ %d\n", 
+              agp->hose->index, agp->mode.bits.rate, 
+              agp->mode.bits.sba ? " - SBA" : "", agp->mode.bits.rq);
+
+       csrs->AGP_CMD.csr = agp->mode.lw;
+
+       return 0;
+}
+
+static int 
+marvel_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
+{
+       struct marvel_agp_aperture *aper = agp->aperture.sysdata;
+       return iommu_bind(aper->arena, aper->pg_start + pg_start, 
+                         mem->page_count, mem->memory);
+}
+
+static int 
+marvel_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
+{
+       struct marvel_agp_aperture *aper = agp->aperture.sysdata;
+       return iommu_unbind(aper->arena, aper->pg_start + pg_start,
+                           mem->page_count);
+}
+
+static unsigned long
+marvel_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
+{
+       struct marvel_agp_aperture *aper = agp->aperture.sysdata;
+       unsigned long baddr = addr - aper->arena->dma_base;
+       unsigned long pte;
+
+       if (addr < agp->aperture.bus_base ||
+           addr >= agp->aperture.bus_base + agp->aperture.size) {
+               printk("%s: addr out of range\n", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       pte = aper->arena->ptes[baddr >> PAGE_SHIFT];
+       if (!(pte & 1)) {
+               printk("%s: pte not valid\n", __FUNCTION__);
+               return -EINVAL;
+       } 
+       return (pte >> 1) << PAGE_SHIFT;
+}
+
+struct alpha_agp_ops marvel_agp_ops =
+{
+       .setup          = marvel_agp_setup,
+       .cleanup        = marvel_agp_cleanup,
+       .configure      = marvel_agp_configure,
+       .bind           = marvel_agp_bind_memory,
+       .unbind         = marvel_agp_unbind_memory,
+       .translate      = marvel_agp_translate
+};
+
+alpha_agp_info *
+marvel_agp_info(void)
+{
+       struct pci_controller *hose;
+       io7_ioport_csrs *csrs;
+       alpha_agp_info *agp;
+       struct io7 *io7;
+
+       /*
+        * Find the first IO7 with an AGP card
+        *
+        * FIXME -- there should be a better way (we want to be able to
+        * specify and what if the agp card is not video???)
+        */
+       hose = NULL;
+       for(io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) {
+               struct pci_controller *h;
+               vuip addr;
+
+               if (!io7->ports[IO7_AGP_PORT].enabled)
+                       continue;
+
+               h = io7->ports[IO7_AGP_PORT].hose;
+               addr = (vuip)build_conf_addr(h, 0, PCI_DEVFN(5, 0), 0);
+
+               if (*addr != 0xffffffffu) {
+                       hose = h;
+                       break;
+               }
+       }
+
+       printk("MARVEL - using hose %d as AGP\n", hose->index);
+
+       if (!hose || !hose->sg_pci) return NULL;
+
+       /* 
+        * Get the csrs from the hose
+        */
+       csrs = ((struct io7_port *)hose->sysdata)->csrs;
+
+       /*
+        * Allocate the info structure
+        */
+       agp = kmalloc(sizeof(*agp), GFP_KERNEL);
+
+       /*
+        * Fill it in
+        */
+       agp->type = ALPHA_CORE_AGP;
+       agp->hose = hose;
+       agp->private = NULL;
+       agp->ops = &marvel_agp_ops;
+
+       /*
+        * Aperture - not configured until ops.setup()
+        */
+       agp->aperture.bus_base = 0;
+       agp->aperture.size = 0;
+       agp->aperture.sysdata = NULL;
+
+       /*
+        * Capabilities
+        *
+        * NOTE: IO7 reports through AGP_STAT that it can support a read queue
+        *       depth of 17 (rq = 0x10). It actually only supports a depth of
+        *       16 (rq = 0xf).
+        */
+       agp->capability.lw = csrs->AGP_STAT.csr;
+       agp->capability.bits.rq = 0xf;
+       
+       /*
+        * Mode
+        */
+       agp->mode.lw = csrs->AGP_CMD.csr;
+
+       return agp;
+}
index c7f0c9b3a3de01f0c1bc44406a7cd8b2c503bb69..32c709ab75c44f7397ba53fdbecd23d98dbb7055 100644 (file)
@@ -146,6 +146,12 @@ extern void cdl_check_console_data_log(void);
 extern int cdl_register_subpacket_annotation(struct el_subpacket_annotation *);
 extern int cdl_register_subpacket_handler(struct el_subpacket_handler *);
 
+/*
+ * err_marvel.c
+ */
+extern void marvel_machine_check(u64, u64, struct pt_regs *);
+extern void marvel_register_error_handlers(void);
+
 /*
  * err_titan.c
  */
diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c
new file mode 100644 (file)
index 0000000..baf1439
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *     linux/arch/alpha/kernel/err_marvel.c
+ *
+ *     Copyright (C) 2001 Jeff Wiedemeier (Compaq Computer Corporation)
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+
+#include <asm/io.h>
+#include <asm/console.h>
+#include <asm/core_marvel.h>
+#include <asm/hwrpb.h>
+#include <asm/smp.h>
+
+#include "err_impl.h"
+#include "proto.h"
+
+\f
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_MARVEL)
+
+void
+marvel_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
+{
+       struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
+
+       /*
+        * Sync the processor
+        */
+       mb();
+       draina();
+
+srm_printk("MARVEL MACHINE CHECK!!!\n");  /* HACK */
+       el_process_subpacket(el_ptr);
+srm_printk("...PROCESSED\n");            /* HACK */
+
+       switch(vector) {
+       case SCB_Q_SYSEVENT:
+               printk(KERN_CRIT "MARVEL SYSEVENT %ld\n", vector);
+               break;
+       case SCB_Q_SYSMCHK:
+       case SCB_Q_SYSERR:
+               printk(KERN_CRIT "MARVEL SYSMCHK/ERR %ld\n", vector);
+               break;
+       default:        /* don't know it - pass it up */
+               return ev7_machine_check(vector, la_ptr, regs);
+       }       
+
+        /* 
+        * Release the logout frame 
+        */
+       wrmces(0x7);
+       mb();
+}
+
+void
+marvel_register_error_handlers(void)
+{
+       ev7_register_error_handlers();
+}
+#endif /* CONFIG_ALPHA_GENERIC || CONFIG_ALPHA_MARVEL */
diff --git a/arch/alpha/kernel/gct.c b/arch/alpha/kernel/gct.c
new file mode 100644 (file)
index 0000000..bc9074b
--- /dev/null
@@ -0,0 +1,43 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+
+#include <asm/hwrpb.h>
+#include <asm/gct.h>
+
+int
+gct6_find_nodes(gct6_node *node, gct6_search_struct *search)
+{
+       gct6_search_struct *wanted;
+       int status = 0;
+
+       /* first check the magic number */
+       if (node->magic != GCT_NODE_MAGIC) {
+               printk(KERN_ERR "GCT Node MAGIC incorrect - GCT invalid\n");
+               return -EINVAL;
+       }
+
+       /* check against the search struct */
+       for(wanted = search; 
+           wanted && (wanted->type | wanted->subtype); 
+           wanted++) {
+               if (node->type != wanted->type) continue;
+               if (node->subtype != wanted->subtype) continue;
+
+               /* found it -- call out */
+               if (wanted->callout) wanted->callout(node);
+       }
+
+       /* now walk the tree, siblings first.. */
+       if (node->next) 
+               status |= gct6_find_nodes(GCT_NODE_PTR(node->next), search);
+
+       /* then the children */
+       if (node->child) 
+               status |= gct6_find_nodes(GCT_NODE_PTR(node->child), search);
+
+       return status;
+}
+
+
index c02365ee0b3b454de0134d56b886b8ce5a04af23..f9832ce76bdaf971def7f90cf07fefd328cb75d2 100644 (file)
@@ -9,10 +9,12 @@
 #include <linux/config.h>
 #include <asm/pgalloc.h>
 
-/* Whee.  IRONGATE, POLARIS, TSUNAMI, TITAN, and WILDFIRE don't have an HAE.
+/* Whee.  These systems don't have an HAE:
+       IRONGATE, MARVEL, POLARIS, TSUNAMI, TITAN, WILDFIRE
    Fix things up for the GENERIC kernel by defining the HAE address
    to be that of the cache. Now we can read and write it as we like.  ;-)  */
 #define IRONGATE_HAE_ADDRESS   (&alpha_mv.hae_cache)
+#define MARVEL_HAE_ADDRESS     (&alpha_mv.hae_cache)
 #define POLARIS_HAE_ADDRESS    (&alpha_mv.hae_cache)
 #define TSUNAMI_HAE_ADDRESS    (&alpha_mv.hae_cache)
 #define TITAN_HAE_ADDRESS      (&alpha_mv.hae_cache)
@@ -32,7 +34,6 @@
 #define T2_IACK_SC             1
 #define WILDFIRE_IACK_SC       1 /* FIXME */
 
-
 /*
  * Some helpful macros for filling in the blanks.
  */
        mv_flush_tlb_current:           ev5_flush_tlb_current,          \
        mv_flush_tlb_current_page:      ev5_flush_tlb_current_page
 
+#define DO_EV7_MMU                                                     \
+       max_asn:                        EV6_MAX_ASN,                    \
+       mv_switch_mm:                   ev5_switch_mm,                  \
+       mv_activate_mm:                 ev5_activate_mm,                \
+       mv_flush_tlb_current:           ev5_flush_tlb_current,          \
+       mv_flush_tlb_current_page:      ev5_flush_tlb_current_page
+
 #define IO_LITE(UP,low)                                                        \
        hae_register:           (unsigned long *) CAT(UP,_HAE_ADDRESS), \
        iack_sc:                CAT(UP,_IACK_SC),                       \
@@ -91,6 +99,7 @@
 #define DO_CIA_IO      IO(CIA,cia)
 #define DO_IRONGATE_IO IO(IRONGATE,irongate)
 #define DO_LCA_IO      IO(LCA,lca)
+#define DO_MARVEL_IO   IO(MARVEL,marvel)
 #define DO_MCPCIA_IO   IO(MCPCIA,mcpcia)
 #define DO_POLARIS_IO  IO(POLARIS,polaris)
 #define DO_T2_IO       IO(T2,t2)
 #define DO_CIA_BUS     BUS(cia)
 #define DO_IRONGATE_BUS        BUS(irongate)
 #define DO_LCA_BUS     BUS(lca)
+#define DO_MARVEL_BUS  BUS(marvel)
 #define DO_MCPCIA_BUS  BUS(mcpcia)
 #define DO_POLARIS_BUS BUS(polaris)
 #define DO_T2_BUS      BUS(t2)
 #define DO_TITAN_BUS   BUS(titan)
 #define DO_WILDFIRE_BUS        BUS(wildfire)
 
-
 /*
  * In a GENERIC kernel, we have lots of these vectors floating about,
  * all but one of which we want to go away.  In a non-GENERIC kernel,
index 93b9e1aaf5273a7548f21ee93c2c36cf73a205e7..b708292c4961b6c46c9fe93c01da6c38b3dcac34 100644 (file)
@@ -41,6 +41,18 @@ extern void lca_init_arch(void);
 extern void lca_machine_check(u64, u64, struct pt_regs *);
 extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
 
+/* core_marvel.c */
+extern struct pci_ops marvel_pci_ops;
+extern void marvel_init_arch(void);
+extern void marvel_kill_arch(int);
+extern void marvel_machine_check(u64, u64, struct pt_regs *);
+extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
+extern int marvel_pa_to_nid(unsigned long);
+extern int marvel_cpuid_to_nid(int);
+extern unsigned long marvel_node_mem_start(int);
+extern unsigned long marvel_node_mem_size(int);
+extern int marvel_srmcons_allowed(void);
+
 /* core_mcpcia.c */
 extern struct pci_ops mcpcia_pci_ops;
 extern void mcpcia_init_arch(void);
index d99676913a650ea1ed092da88429e0b24461564c..405fd4b57860138ccf2dd77e02d6199c579d5573 100644 (file)
@@ -155,6 +155,7 @@ WEAK(eb66p_mv);
 WEAK(eiger_mv);
 WEAK(jensen_mv);
 WEAK(lx164_mv);
+WEAK(marvel_ev7_mv);
 WEAK(miata_mv);
 WEAK(mikasa_mv);
 WEAK(mikasa_primo_mv);
@@ -696,7 +697,7 @@ static char systype_names[][16] = {
        "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
        "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
        "Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
-       "Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan"
+       "Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan", "Marvel"
 };
 
 static char unofficial_names[][8] = {"100", "Ruffian"};
@@ -715,6 +716,11 @@ static int eb64p_indices[] = {0,0,1,2};
 static char eb66_names[][8] = {"EB66", "EB66+"};
 static int eb66_indices[] = {0,0,1};
 
+static char marvel_names[][16] = {
+       "Marvel/EV7"
+};
+static int marvel_indices[] = { 0 };
+
 static char rawhide_names[][16] = {
        "Dodge", "Wrangler", "Durango", "Tincup", "DaVinci"
 };
@@ -776,6 +782,7 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
                NULL,           /* CUSCO */
                &eiger_mv,      /* Eiger */
                NULL,           /* Titan */
+               NULL,           /* Marvel */
        };
 
        static struct alpha_machine_vector *unofficial_vecs[] __initdata =
@@ -813,6 +820,11 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
                &eb66p_mv
        };
 
+       static struct alpha_machine_vector *marvel_vecs[] __initdata =
+       {
+               &marvel_ev7_mv,
+       };
+
        static struct alpha_machine_vector *titan_vecs[] __initdata =
        {
                &titan_mv,              /* default   */
@@ -883,6 +895,10 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
                        if (member < N(eb66_indices))
                                vec = eb66_vecs[eb66_indices[member]];
                        break;
+               case ST_DEC_MARVEL:
+                       if (member < N(marvel_indices))
+                               vec = marvel_vecs[marvel_indices[member]];
+                       break;
                case ST_DEC_TITAN:
                        vec = titan_vecs[0];    /* default */
                        if (member < N(titan_indices))
@@ -1023,6 +1039,10 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
                if (member < N(eb66_indices))
                        *variation_name = eb66_names[eb66_indices[member]];
                break;
+       case ST_DEC_MARVEL:
+               if (member < N(marvel_indices))
+                       *variation_name = marvel_names[marvel_indices[member]];
+               break;
        case ST_DEC_RAWHIDE:
                if (member < N(rawhide_indices))
                        *variation_name = rawhide_names[rawhide_indices[member]];
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
new file mode 100644 (file)
index 0000000..7f12489
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * linux/arch/alpha/kernel/sys_io7.c
+ *
+ * Marvel / IO7 support
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_marvel.h>
+#include <asm/hwrpb.h>
+#include <asm/tlbflush.h>
+
+#include "proto.h"
+#include "err_impl.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
+
+\f
+/*
+ * private functions in core_marvel.c
+ */
+struct io7 *marvel_find_io7(int pe);
+struct io7 *marvel_next_io7(struct io7 *prev);
+void io7_clear_errors(struct io7 *io7);
+
+\f
+/*
+ * Interrupt handling
+ */
+#define IRQ_VEC_PE_SHIFT (10)
+#define IRQ_VEC_IRQ_MASK ((1 << IRQ_VEC_PE_SHIFT) - 1)
+
+static void 
+io7_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+       unsigned int pid;
+       unsigned int irq;
+
+       /*
+        * Vector is 0x800 + (interrupt)
+        *
+        * where (interrupt) is:
+        *
+        *      ...16|15 14|13     4|3 0
+        *      -----+-----+--------+---
+        *        PE |  0  |   irq  | 0
+        *
+        * where (irq) is 
+        *
+        *       0x0800 - 0x0ff0         - 0x0800 + (LSI id << 4)
+        *       0x1000 - 0x2ff0         - 0x1000 + (MSI_DAT<8:0> << 4)
+        */
+       pid = vector >> 16;
+       irq = ((vector & 0xffff) - 0x800) >> 4;
+
+       irq += 16;                      /* offset for legacy */
+       irq &= IRQ_VEC_IRQ_MASK;        /* not too many bits */
+       irq |= pid << IRQ_VEC_PE_SHIFT; /* merge the pid     */
+
+       handle_irq(irq, regs);
+}
+
+static volatile unsigned long *
+io7_get_irq_ctl(unsigned int irq, struct io7 **pio7)
+{
+       volatile unsigned long *ctl;
+       unsigned int pid;
+       struct io7 *io7;
+
+       pid = irq >> IRQ_VEC_PE_SHIFT;
+
+       if (!(io7 = marvel_find_io7(pid))) {
+               printk(KERN_ERR 
+                      "%s for nonexistent io7 -- vec %x, pid %d\n",
+                      __FUNCTION__, irq, pid);
+               return NULL;
+       }
+
+       irq &= IRQ_VEC_IRQ_MASK;        /* isolate the vector    */
+       irq -= 16;                      /* subtract legacy bias  */
+
+       if (irq >= 0x180) {
+               printk(KERN_ERR 
+                      "%s for invalid irq -- pid %d adjusted irq %x\n",
+                      __FUNCTION__, pid, irq);
+               return NULL;
+       }
+
+       ctl = &io7->csrs->PO7_LSI_CTL[irq & 0xff].csr; /* assume LSI */
+       if (irq >= 0x80)                /* MSI */
+               ctl = &io7->csrs->PO7_MSI_CTL[((irq - 0x80) >> 5) & 0x0f].csr;
+
+       if (pio7) *pio7 = io7;
+       return ctl;
+}
+
+static void
+io7_enable_irq(unsigned int irq)
+{
+       volatile unsigned long *ctl;
+       struct io7 *io7;
+
+       ctl = io7_get_irq_ctl(irq, &io7);
+       if (!ctl || !io7) {
+               printk(KERN_ERR "%s: get_ctl failed for irq %x\n", 
+                      __FUNCTION__, irq);
+               return;
+       }
+               
+       spin_lock(&io7->irq_lock);
+       *ctl |= 1UL << 24;
+       mb();
+       *ctl;
+       spin_unlock(&io7->irq_lock);
+}
+
+static void
+io7_disable_irq(unsigned int irq)
+{
+       volatile unsigned long *ctl;
+       struct io7 *io7;
+
+       ctl = io7_get_irq_ctl(irq, &io7);
+       if (!ctl || !io7) {
+               printk(KERN_ERR "%s: get_ctl failed for irq %x\n", 
+                      __FUNCTION__, irq);
+               return;
+       }
+               
+       spin_lock(&io7->irq_lock);
+       *ctl &= ~(1UL << 24);
+       mb();
+       *ctl;
+       spin_unlock(&io7->irq_lock);
+}
+
+static unsigned int
+io7_startup_irq(unsigned int irq)
+{
+       io7_enable_irq(irq);
+       return 0;       /* never anything pending */
+}
+
+static void
+io7_end_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+               io7_enable_irq(irq);
+}
+
+static void marvel_irq_noop(unsigned int irq) 
+{ 
+       return; 
+}
+
+static unsigned int marvel_irq_noop_return(unsigned int irq) 
+{ 
+       return 0; 
+}
+
+static struct hw_interrupt_type marvel_legacy_irq_type = {
+       .typename       = "LEGACY",
+       .startup        = marvel_irq_noop_return,
+       .shutdown       = marvel_irq_noop,
+       .enable         = marvel_irq_noop,
+       .disable        = marvel_irq_noop,
+       .ack            = marvel_irq_noop,
+       .end            = marvel_irq_noop,
+};
+
+static struct hw_interrupt_type io7_lsi_irq_type = {
+       .typename       = "LSI",
+       .startup        = io7_startup_irq,
+       .shutdown       = io7_disable_irq,
+       .enable         = io7_enable_irq,
+       .disable        = io7_disable_irq,
+       .ack            = io7_disable_irq,
+       .end            = io7_end_irq,
+};
+
+static struct hw_interrupt_type io7_msi_irq_type = {
+       .typename       = "MSI",
+       .startup        = io7_startup_irq,
+       .shutdown       = io7_disable_irq,
+       .enable         = io7_enable_irq,
+       .disable        = io7_disable_irq,
+       .ack            = marvel_irq_noop,
+       .end            = io7_end_irq,
+};
+
+static void
+io7_redirect_irq(struct io7 *io7, 
+                volatile unsigned long *csr, 
+                unsigned int where)
+{
+       unsigned long val;
+       
+       val = *csr;
+       val &= ~(0x1ffUL << 24);                /* clear the target pid   */
+       val |= ((unsigned long)where << 24);    /* set the new target pid */
+       
+       *csr = val;
+       mb();
+       *csr;
+}
+
+static void 
+io7_redirect_one_lsi(struct io7 *io7, unsigned int which, unsigned int where)
+{
+       unsigned long val;
+
+       /*
+        * LSI_CTL has target PID @ 14
+        */
+       val = io7->csrs->PO7_LSI_CTL[which].csr;
+       val &= ~(0x1ffUL << 14);                /* clear the target pid */
+       val |= ((unsigned long)where << 14);    /* set teh new target pid */
+
+       io7->csrs->PO7_LSI_CTL[which].csr = val;
+       mb();
+       io7->csrs->PO7_LSI_CTL[which].csr;
+}
+
+static void 
+io7_redirect_one_msi(struct io7 *io7, unsigned int which, unsigned int where)
+{
+       unsigned long val;
+
+       /*
+        * MSI_CTL has target PID @ 14
+        */
+       val = io7->csrs->PO7_MSI_CTL[which].csr;
+       val &= ~(0x1ffUL << 14);                /* clear the target pid */
+       val |= ((unsigned long)where << 14);    /* set teh new target pid */
+
+       io7->csrs->PO7_MSI_CTL[which].csr = val;
+       mb();
+       io7->csrs->PO7_MSI_CTL[which].csr;
+}
+
+static void __init
+init_one_io7_lsi(struct io7 *io7, unsigned int which, unsigned int where)
+{
+       /*
+        * LSI_CTL has target PID @ 14
+        */
+       io7->csrs->PO7_LSI_CTL[which].csr = ((unsigned long)where << 14);
+       mb();
+       io7->csrs->PO7_LSI_CTL[which].csr;
+}
+
+static void __init
+init_one_io7_msi(struct io7 *io7, unsigned int which, unsigned int where)
+{
+       /*
+        * MSI_CTL has target PID @ 14
+        */
+       io7->csrs->PO7_MSI_CTL[which].csr = ((unsigned long)where << 14);
+       mb();
+       io7->csrs->PO7_MSI_CTL[which].csr;
+}
+
+static void __init
+init_io7_irqs(struct io7 *io7, 
+             struct hw_interrupt_type *lsi_ops,
+             struct hw_interrupt_type *msi_ops)
+{
+       long base = (io7->pe << IRQ_VEC_PE_SHIFT) + 16;
+       long i;
+
+       printk("Initializing interrupts for IO7 at PE %u - base %lx\n",
+               io7->pe, base);
+
+       /*
+        * Where should interrupts from this IO7 go?
+        *
+        * They really should be sent to the local CPU to avoid having to
+        * traverse the mesh, but if it's not an SMP kernel, they have to
+        * go to the boot CPU. Send them all to the boot CPU for now,
+        * as each secondary starts, it can redirect it's local device 
+        * interrupts
+        */
+       printk("  Interrupts reported to CPU at PE %u\n", boot_cpuid);
+
+       spin_lock(&io7->irq_lock);
+
+       /* set up the error irqs */
+       io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, boot_cpuid);
+       io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, boot_cpuid);
+       io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, boot_cpuid);
+       io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, boot_cpuid);
+       io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, boot_cpuid);
+
+       /* set up the lsi irqs */
+       for(i = 0; i < 128; ++i) {
+               irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
+               irq_desc[base + i].handler = lsi_ops;
+       }
+
+       /* disable the implemented irqs in hardware */
+       for(i = 0; i < 0x60; ++i) 
+               init_one_io7_lsi(io7, i, boot_cpuid);
+
+       init_one_io7_lsi(io7, 0x74, boot_cpuid);
+       init_one_io7_lsi(io7, 0x75, boot_cpuid);
+
+
+       /* set up the msi irqs */
+       for(i = 128; i < (128 + 512); ++i) {
+               irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
+               irq_desc[base + i].handler = msi_ops;
+       }
+
+       for(i = 0; i < 16; ++i)
+               init_one_io7_msi(io7, i, boot_cpuid);
+
+       spin_unlock(&io7->irq_lock);
+}
+
+static void __init
+marvel_init_irq(void)
+{
+       int i;
+       struct io7 *io7 = NULL;
+
+       /* reserve the legacy irqs */
+       for(i = 0; i < 16; ++i) {
+               irq_desc[i].status = IRQ_DISABLED;
+               irq_desc[i].handler = &marvel_legacy_irq_type;
+       }
+
+       /* init the io7 irqs */
+       for(io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) {
+               init_io7_irqs(io7, &io7_lsi_irq_type, &io7_msi_irq_type);
+       }
+}
+
+static int 
+marvel_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       struct pci_controller *hose = dev->sysdata;
+       struct io7_port *io7_port = hose->sysdata;
+       struct io7 *io7 = io7_port->io7;
+       int msi_loc, msi_data_off;
+       u16 msg_ctl;
+       u16 msg_dat;
+       u8 intline; 
+       int irq;
+
+       pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
+       irq = intline;
+
+       msi_loc = pci_find_capability(dev, PCI_CAP_ID_MSI);
+       msg_ctl = 0;
+       if (msi_loc) 
+               pci_read_config_word(dev, msi_loc + PCI_MSI_FLAGS, &msg_ctl);
+
+       if (msg_ctl & PCI_MSI_FLAGS_ENABLE) {
+               msi_data_off = PCI_MSI_DATA_32;
+               if (msg_ctl & PCI_MSI_FLAGS_64BIT) 
+                       msi_data_off = PCI_MSI_DATA_64;
+               pci_read_config_word(dev, msi_loc + msi_data_off, &msg_dat);
+
+               irq = msg_dat & 0x1ff;          /* we use msg_data<8:0> */
+               irq += 0x80;                    /* offset for lsi       */
+
+#if 1
+               printk("PCI:%d:%d:%d (hose %d) [%s] is using MSI\n",
+                      dev->bus->number, 
+                      PCI_SLOT(dev->devfn), 
+                      PCI_FUNC(dev->devfn),
+                      hose->index,
+                      dev->dev.name);
+               printk("  %d message(s) from 0x%04x\n", 
+                      1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
+                      msg_dat);
+               printk("  reporting on %d IRQ(s) from %d (0x%x)\n", 
+                      1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
+                      (irq + 16) | (io7->pe << IRQ_VEC_PE_SHIFT),
+                      (irq + 16) | (io7->pe << IRQ_VEC_PE_SHIFT));
+#endif
+
+#if 0
+               pci_write_config_word(dev, msi_loc + PCI_MSI_FLAGS,
+                                     msg_ctl & ~PCI_MSI_FLAGS_ENABLE);
+               pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
+               irq = intline;
+
+               printk("  forcing LSI interrupt on irq %d [0x%x]\n", irq, irq);
+#endif
+
+       }
+
+       irq += 16;                              /* offset for legacy */
+       irq |= io7->pe << IRQ_VEC_PE_SHIFT;     /* merge the pid     */
+
+       return irq; 
+}
+
+static void __init
+marvel_init_pci(void)
+{
+       extern int pci_probe_only;
+       struct io7 *io7;
+
+       marvel_register_error_handlers();
+
+       pci_probe_only = 1;
+       common_init_pci();
+
+#ifdef CONFIG_VGA_HOSE
+       locate_and_init_vga(NULL);
+#endif
+
+       /* clear any io7 errors */
+       for(io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) 
+               io7_clear_errors(io7);
+}
+
+static void
+marvel_init_rtc(void)
+{
+       init_rtc_irq();
+}
+
+static void
+marvel_smp_callin(void)
+{
+       int cpuid = hard_smp_processor_id();
+       struct io7 *io7 = marvel_find_io7(cpuid);
+       unsigned int i;
+
+       if (io7) {
+               /* 
+                * There is a local IO7 - redirect all of it's interrupts here
+                */
+               printk("Redirecting IO7 interrupts to local CPU at PE %u\n",
+                      cpuid);
+
+               /* redirect the error IRQS here */
+               io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, cpuid);
+               io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, cpuid);
+               io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, cpuid);
+               io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, cpuid);
+               io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, cpuid);
+
+               /* redirect the implemented LSIs here */
+               for(i = 0; i < 0x60; ++i) 
+                       io7_redirect_one_lsi(io7, i, cpuid);
+
+               io7_redirect_one_lsi(io7, 0x74, cpuid);
+               io7_redirect_one_lsi(io7, 0x75, cpuid);
+
+               /* redirect the MSIs here */
+               for(i = 0; i < 16; ++i)
+                       io7_redirect_one_msi(io7, i, cpuid);
+       }
+}
+\f
+/*
+ * System Vectors
+ */
+extern void *marvel_agp_info(void);
+struct alpha_machine_vector marvel_ev7_mv __initmv = {
+       .vector_name            = "MARVEL/EV7",
+       DO_EV7_MMU,
+       DO_DEFAULT_RTC,
+       DO_MARVEL_IO,
+       DO_MARVEL_BUS,
+       .machine_check          = marvel_machine_check,
+       .max_isa_dma_address    = ALPHA_MAX_ISA_DMA_ADDRESS,
+       .min_io_address         = DEFAULT_IO_BASE,
+       .min_mem_address        = DEFAULT_MEM_BASE,
+       .pci_dac_offset         = IO7_DAC_OFFSET,
+
+       .nr_irqs                = MARVEL_NR_IRQS,
+       .device_interrupt       = io7_device_interrupt,
+
+       .agp_info               = marvel_agp_info,
+       .srmcons_allowed        = marvel_srmcons_allowed,
+
+       .smp_callin             = marvel_smp_callin,
+       .init_arch              = marvel_init_arch,
+       .init_irq               = marvel_init_irq,
+       .init_rtc               = marvel_init_rtc,
+       .init_pci               = marvel_init_pci,
+       .kill_arch              = marvel_kill_arch,
+       .pci_map_irq            = marvel_map_irq,
+       .pci_swizzle            = common_swizzle,
+
+       .pa_to_nid              = marvel_pa_to_nid,
+       .cpuid_to_nid           = marvel_cpuid_to_nid,
+       .node_mem_start         = marvel_node_mem_start,
+       .node_mem_size          = marvel_node_mem_size,
+};
+ALIAS_MV(marvel_ev7)
+
+
diff --git a/include/asm-alpha/core_marvel.h b/include/asm-alpha/core_marvel.h
new file mode 100644 (file)
index 0000000..671fc4e
--- /dev/null
@@ -0,0 +1,579 @@
+/*
+ * Marvel systems use the IO7 I/O chip provides PCI/PCIX/AGP access
+ *
+ * This file is based on:
+ *
+ * Marvel / EV7 System Programmer's Manual
+ * Revision 1.00
+ * 14 May 2001
+ */
+
+#ifndef __ALPHA_MARVEL__H__
+#define __ALPHA_MARVEL__H__
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/compiler.h>
+
+#define MARVEL_MAX_PIDS                128
+#define MARVEL_MAX_LSIS_PER_PID        256
+#define MARVEL_NR_IRQS (MARVEL_MAX_PIDS * MARVEL_MAX_LSIS_PER_PID)
+
+/*
+ * EV7 RBOX Registers
+ */
+typedef struct {
+       volatile unsigned long csr __attribute__((aligned(16)));
+} ev7_csr;
+
+typedef struct {
+       ev7_csr RBOX_CFG;               /* 0x0000 */
+       ev7_csr RBOX_NSVC;
+       ev7_csr RBOX_EWVC;
+       ev7_csr RBOX_WHAMI;
+       ev7_csr RBOX_TCTL;              /* 0x0040 */
+       ev7_csr RBOX_INT;
+       ev7_csr RBOX_IMASK;
+       ev7_csr RBOX_IREQ;
+       ev7_csr RBOX_INTQ;              /* 0x0080 */
+       ev7_csr RBOX_INTA;
+       ev7_csr RBOX_IT;
+       ev7_csr RBOX_SCRATCH1;
+       ev7_csr RBOX_SCRATCH2;          /* 0x00c0 */
+       ev7_csr RBOX_L_ERR;
+} ev7_csrs;
+
+/*
+ * EV7 CSR addressing macros
+ */
+#define EV7_MASK40(addr)        ((addr) & ((1UL << 41) - 1))
+#define EV7_KERN_ADDR(addr)    ((void *)(IDENT_ADDR | EV7_MASK40(addr)))
+
+#define EV7_PE_MASK            0x1ffUL /* 9 bits ( 256 + mem/io ) */
+#define EV7_IPE(pe)            ((~((long)(pe)) & EV7_PE_MASK) << 35)
+
+#define EV7_CSR_PHYS(pe, off)  (EV7_IPE(pe) | (0x7FFCUL << 20) | (off))
+#define EV7_CSRS_PHYS(pe)      (EV7_CSR_PHYS(pe, 0UL))
+
+#define EV7_CSR_KERN(pe, off)  (EV7_KERN_ADDR(EV7_CSR_PHYS(pe, off)))
+#define EV7_CSRS_KERN(pe)      (EV7_KERN_ADDR(EV7_CSRS_PHYS(pe)))
+
+#define EV7_CSR_OFFSET(name)   ((unsigned long)&((ev7_csrs *)NULL)->name.csr)
+
+/*
+ * IO7 registers
+ */
+typedef struct {
+       volatile unsigned long csr __attribute__((aligned(64)));
+} io7_csr;
+
+typedef struct {
+       /* I/O Port Control Registers */
+       io7_csr POx_CTRL;               /* 0x0000 */
+       io7_csr POx_CACHE_CTL;
+       io7_csr POx_TIMER;
+       io7_csr POx_IO_ADR_EXT;
+       io7_csr POx_MEM_ADR_EXT;        /* 0x0100 */
+       io7_csr POx_XCAL_CTRL;
+       io7_csr rsvd1[2];       /* ?? spec doesn't show 0x180 */
+       io7_csr POx_DM_SOURCE;          /* ox0200 */
+       io7_csr POx_DM_DEST;
+       io7_csr POx_DM_SIZE;
+       io7_csr POx_DM_STATE;
+       io7_csr rsvd2[4];               /* 0x0300 */
+
+       /* AGP Control Registers -- port 3 only */
+       io7_csr AGP_CAP_ID;             /* 0x0400 */
+       io7_csr AGP_STAT;
+       io7_csr AGP_CMD;
+       io7_csr rsvd3;
+
+       /* I/O Port Monitor Registers */
+       io7_csr POx_MONCTL;             /* 0x0500 */
+       io7_csr POx_CTRA;
+       io7_csr POx_CTRB;
+       io7_csr POx_CTR56;
+       io7_csr POx_SCRATCH;            /* 0x0600 */
+       io7_csr POx_XTRA_A;
+       io7_csr POx_XTRA_TS;
+       io7_csr POx_XTRA_Z;
+       io7_csr rsvd4;                  /* 0x0700 */
+       io7_csr POx_THRESHA;
+       io7_csr POx_THRESHB;
+       io7_csr rsvd5[33];
+
+       /* System Address Space Window Control Registers */
+
+       io7_csr POx_WBASE[4];           /* 0x1000 */
+       io7_csr POx_WMASK[4];
+       io7_csr POx_TBASE[4];
+       io7_csr POx_SG_TBIA;
+       io7_csr POx_MSI_WBASE;
+       io7_csr rsvd6[50];
+
+       /* I/O Port Error Registers */
+       io7_csr POx_ERR_SUM;
+       io7_csr POx_FIRST_ERR;
+       io7_csr POx_MSK_HEI;
+       io7_csr POx_TLB_ERR;
+       io7_csr POx_SPL_COMPLT;
+       io7_csr POx_TRANS_SUM;
+       io7_csr POx_FRC_PCI_ERR;
+       io7_csr POx_MULT_ERR;
+       io7_csr rsvd7[8];
+
+       /* I/O Port End of Interrupt Registers */
+       io7_csr EOI_DAT;
+       io7_csr rsvd8[7];
+       io7_csr POx_IACK_SPECIAL;
+       io7_csr rsvd9[103];
+} io7_ioport_csrs;
+
+typedef struct {
+       io7_csr IO_ASIC_REV;            /* 0x30.0000 */
+       io7_csr IO_SYS_REV;
+       io7_csr SER_CHAIN3;
+       io7_csr PO7_RST1;
+       io7_csr PO7_RST2;               /* 0x30.0100 */
+       io7_csr POx_RST[4];
+       io7_csr IO7_DWNH;
+       io7_csr IO7_MAF;
+       io7_csr IO7_MAF_TO;
+       io7_csr IO7_ACC_CLUMP;          /* 0x30.0300 */
+       io7_csr IO7_PMASK;
+       io7_csr IO7_IOMASK;
+       io7_csr IO7_UPH;
+       io7_csr IO7_UPH_TO;             /* 0x30.0400 */
+       io7_csr RBX_IREQ_OFF;
+       io7_csr RBX_INTA_OFF;
+       io7_csr INT_RTY;
+       io7_csr PO7_MONCTL;             /* 0x30.0500 */
+       io7_csr PO7_CTRA;
+       io7_csr PO7_CTRB;
+       io7_csr PO7_CTR56;
+       io7_csr PO7_SCRATCH;            /* 0x30.0600 */
+       io7_csr PO7_XTRA_A;
+       io7_csr PO7_XTRA_TS;
+       io7_csr PO7_XTRA_Z;
+       io7_csr PO7_PMASK;              /* 0x30.0700 */
+       io7_csr PO7_THRESHA;
+       io7_csr PO7_THRESHB;
+       io7_csr rsvd1[97];
+       io7_csr PO7_ERROR_SUM;          /* 0x30.2000 */
+       io7_csr PO7_BHOLE_MASK;
+       io7_csr PO7_HEI_MSK;
+       io7_csr PO7_CRD_MSK;
+       io7_csr PO7_UNCRR_SYM;          /* 0x30.2100 */
+       io7_csr PO7_CRRCT_SYM;
+       io7_csr PO7_ERR_PKT[2];
+       io7_csr PO7_UGBGE_SYM;          /* 0x30.2200 */
+       io7_csr rsbv2[887];
+       io7_csr PO7_LSI_CTL[128];       /* 0x31.0000 */
+       io7_csr rsvd3[123];
+       io7_csr HLT_CTL;                /* 0x31.3ec0 */
+       io7_csr HPI_CTL;                /* 0x31.3f00 */
+       io7_csr CRD_CTL;
+       io7_csr STV_CTL;
+       io7_csr HEI_CTL;
+       io7_csr PO7_MSI_CTL[16];        /* 0x31.4000 */
+       io7_csr rsvd4[240];
+
+       /*
+        * Interrupt Diagnostic / Test
+        */
+       struct {
+               io7_csr INT_PND;
+               io7_csr INT_CLR;
+               io7_csr INT_EOI;
+               io7_csr rsvd[29];
+       } INT_DIAG[4];
+       io7_csr rsvd5[125];             /* 0x31.a000 */
+       io7_csr MISC_PND;               /* 0x31.b800 */
+       io7_csr rsvd6[31];
+       io7_csr MSI_PND[16];            /* 0x31.c000 */
+       io7_csr rsvd7[16];
+       io7_csr MSI_CLR[16];            /* 0x31.c800 */
+} io7_port7_csrs;
+
+/* 
+ * IO7 DMA Window Base register (POx_WBASEx)
+ */
+#define wbase_m_ena  0x1
+#define wbase_m_sg   0x2
+#define wbase_m_dac  0x4
+#define wbase_m_addr 0xFFF00000
+union IO7_POx_WBASE {
+       struct {
+               unsigned ena : 1;       /* <0>                  */
+               unsigned sg : 1;        /* <1>                  */
+               unsigned dac : 1;       /* <2> -- window 3 only */
+               unsigned rsvd1 : 17; 
+               unsigned addr : 12;     /* <31:20>              */
+               unsigned rsvd2 : 32;
+       } bits;
+       unsigned as_long[2];
+       unsigned as_quad;
+};
+
+/*
+ * IO7 IID (Interrupt IDentifier) format
+ *
+ * For level-sensative interupts, int_num is encoded as:
+ *
+ *     bus/port        slot/device     INTx
+ *     <7:5>           <4:2>           <1:0>
+ */
+union IO7_IID {
+       struct {
+               unsigned int_num : 9;           /* <8:0>        */
+               unsigned tpu_mask : 4;          /* <12:9> rsvd  */
+               unsigned msi : 1;               /* 13           */
+               unsigned ipe : 10;              /* <23:14>      */
+               unsigned long rsvd : 40;                
+       } bits;
+       unsigned int as_long[2];
+       unsigned long as_quad;
+};
+
+/*
+ * IO7 addressing macros
+ */
+#define IO7_KERN_ADDR(addr)    (EV7_KERN_ADDR(addr))
+
+#define IO7_PORT_MASK          0x07UL  /* 3 bits of port          */
+
+#define IO7_IPE(pe)            (EV7_IPE(pe))
+#define IO7_IPORT(port)                ((~((long)(port)) & IO7_PORT_MASK) << 32)
+
+#define IO7_HOSE(pe, port)     (IO7_IPE(pe) | IO7_IPORT(port))
+
+#define IO7_MEM_PHYS(pe, port) (IO7_HOSE(pe, port) | 0x00000000UL)
+#define IO7_CONF_PHYS(pe, port)        (IO7_HOSE(pe, port) | 0xFE000000UL)
+#define IO7_IO_PHYS(pe, port)  (IO7_HOSE(pe, port) | 0xFF000000UL)
+#define IO7_CSR_PHYS(pe, port, off) \
+                                (IO7_HOSE(pe, port) | 0xFF800000UL | (off))
+#define IO7_CSRS_PHYS(pe, port)        (IO7_CSR_PHYS(pe, port, 0UL))
+#define IO7_PORT7_CSRS_PHYS(pe) (IO7_CSR_PHYS(pe, 7, 0x300000UL))
+
+#define IO7_MEM_KERN(pe, port)      (IO7_KERN_ADDR(IO7_MEM_PHYS(pe, port)))
+#define IO7_CONF_KERN(pe, port)     (IO7_KERN_ADDR(IO7_CONF_PHYS(pe, port)))
+#define IO7_IO_KERN(pe, port)       (IO7_KERN_ADDR(IO7_IO_PHYS(pe, port)))
+#define IO7_CSR_KERN(pe, port, off) (IO7_KERN_ADDR(IO7_CSR_PHYS(pe,port,off)))
+#define IO7_CSRS_KERN(pe, port)     (IO7_KERN_ADDR(IO7_CSRS_PHYS(pe, port)))
+#define IO7_PORT7_CSRS_KERN(pe)            (IO7_KERN_ADDR(IO7_PORT7_CSRS_PHYS(pe)))
+
+#define IO7_PLL_RNGA(pll)      (((pll) >> 3) & 0x7)
+#define IO7_PLL_RNGB(pll)      (((pll) >> 6) & 0x7)
+
+#define IO7_MEM_SPACE          (2UL * 1024 * 1024 * 1024)      /* 2GB MEM */
+#define IO7_IO_SPACE           (8UL * 1024 * 1024)             /* 8MB I/O */
+
+/* 
+ * Offset between ram physical addresses and pci64 DAC addresses
+ */
+#define IO7_DAC_OFFSET         (1UL << 49)
+
+/*
+ * This is needed to satisify the IO() macro used in initializing the machvec
+ */
+#define MARVEL_IACK_SC                                                         \
+        ((unsigned long)                                               \
+        (&(((io7_ioport_csrs *)IO7_CSRS_KERN(0, 0))->POx_IACK_SPECIAL)))
+
+#ifdef __KERNEL__
+
+/*
+ * IO7 structs
+ */
+#define IO7_NUM_PORTS 4
+#define IO7_AGP_PORT  3
+
+struct io7_port {
+       struct io7 *io7;
+       struct pci_controller *hose;
+
+       int enabled;
+       unsigned int port;
+       io7_ioport_csrs *csrs;
+
+       unsigned long saved_wbase[4];
+       unsigned long saved_wmask[4];
+       unsigned long saved_tbase[4];
+};
+
+struct io7 {
+       struct io7 *next;
+
+       unsigned int pe;
+       io7_port7_csrs *csrs;
+       struct io7_port ports[IO7_NUM_PORTS];
+
+       spinlock_t irq_lock;
+};
+
+#ifndef __EXTERN_INLINE
+# define __EXTERN_INLINE extern inline
+# define __IO_EXTERN_INLINE
+#endif
+
+/*
+ * I/O functions. All access through linear space.
+ */
+
+#define vucp   volatile unsigned char *
+#define vusp   volatile unsigned short *
+#define vuip   volatile unsigned int *
+#define vulp   volatile unsigned long *
+
+#ifdef CONFIG_VGA_HOSE
+extern struct pci_controller *pci_vga_hose;
+
+# define __marvel_is_port_vga(a)       \
+        (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
+# define __marvel_is_mem_vga(a)        (((a) >= 0xa0000) && ((a) <= 0xc0000))
+# define FIXUP_IOADDR_VGA(a) do {                      \
+       if (pci_vga_hose && __marvel_is_port_vga(a))    \
+               a += pci_vga_hose->io_space->start;     \
+    } while(0)
+#else
+# define FIXUP_IOADDR_VGA(a)
+#endif 
+
+#define __marvel_is_port_kbd(a)        (((a) == 0x60) || ((a) == 0x64))
+#define __marvel_is_port_rtc(a)        (((a) == 0x70) || ((a) == 0x71))
+
+#define FIXUP_IOADDR_LEGACY(a)
+
+#define FIXUP_IOADDR(a) do {                           \
+       FIXUP_IOADDR_VGA(a);                            \
+        FIXUP_IOADDR_LEGACY(a);                                \
+    } while(0)
+
+#if 0
+# define IOBUG(x) printk x
+# define IOBUG_FILTER_IOADDR(a, x)     \
+    if (!__marvel_is_port_kbd(a) && !__marvel_is_port_rtc(a)) IOBUG(x)
+#else
+# define IOBUG(x)
+# define IOBUG_FILTER_IOADDR(a, x)
+#endif
+
+extern u8 __marvel_rtc_io(int write, u8 b, unsigned long addr);
+#define __marvel_rtc_inb(a)    __marvel_rtc_io(0, 0, (a))
+#define __marvel_rtc_outb(b, a)        __marvel_rtc_io(1, (b), (a))
+
+__EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr)
+{
+       return (addr & (1UL << 40)) != 0; /*FIXME - hardwire*/
+}
+
+__EXTERN_INLINE u8 marvel_inb(unsigned long addr)
+{
+       FIXUP_IOADDR(addr);
+       if (!marvel_is_ioaddr(addr)) {
+               if (__marvel_is_port_kbd(addr)) return (u8)0;
+               if (__marvel_is_port_rtc(addr)) return __marvel_rtc_inb(addr);
+               IOBUG_FILTER_IOADDR(addr, 
+                                   ("Bad IO addr %lx - reading -1\n", addr));
+               return (u8)-1;
+       }
+       return __kernel_ldbu(*(vucp)addr);
+}
+
+__EXTERN_INLINE void marvel_outb(u8 b, unsigned long addr)
+{
+       FIXUP_IOADDR(addr);
+       if (!marvel_is_ioaddr(addr)) {
+               if (__marvel_is_port_rtc(addr)) 
+                       return (void)__marvel_rtc_outb(b, addr);
+               IOBUG_FILTER_IOADDR(addr, 
+                                   ("Bad IO addr %lx - reading -1\n", addr));
+               return;
+       }
+       __kernel_stb(b, *(vucp)addr);
+       mb();
+}
+
+__EXTERN_INLINE u16 marvel_inw(unsigned long addr)
+{
+       FIXUP_IOADDR(addr);
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG_FILTER_IOADDR(addr, 
+                                   ("Bad IO addr %lx - reading -1\n", addr));
+               return (u16)-1;
+       }
+       return __kernel_ldwu(*(vusp)addr);
+}
+
+__EXTERN_INLINE void marvel_outw(u16 w, unsigned long addr)
+{
+       FIXUP_IOADDR(addr);
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG_FILTER_IOADDR(addr, 
+                                   ("Bad IO addr %lx - reading -1\n", addr));
+               return;
+       }
+       __kernel_stw(w, *(vusp)addr);
+       mb();
+}
+
+__EXTERN_INLINE u32 marvel_inl(unsigned long addr)
+{
+       FIXUP_IOADDR(addr);
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG_FILTER_IOADDR(addr, 
+                                   ("Bad IO addr %lx - reading -1\n", addr));
+               return (u32)-1;
+       }
+       return *(vuip)addr;
+}
+
+__EXTERN_INLINE void marvel_outl(u32 l, unsigned long addr)
+{
+       FIXUP_IOADDR(addr);
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG_FILTER_IOADDR(addr, 
+                                   ("Bad IO addr %lx - reading -1\n", addr));
+               return;
+       }
+       *(vuip)addr = l;
+       mb();
+}
+
+/*
+ * Memory functions.  All accesses through linear space.
+ */
+
+extern unsigned long marvel_ioremap(unsigned long addr, unsigned long size);
+extern void marvel_iounmap(unsigned long addr);
+
+__EXTERN_INLINE u8 marvel_readb(unsigned long addr)
+{
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
+               return (u8)-1;
+       }
+       return __kernel_ldbu(*(vucp)addr);
+}
+
+__EXTERN_INLINE u16 marvel_readw(unsigned long addr)
+{
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
+               return (u16)-1;
+       }
+       return __kernel_ldwu(*(vusp)addr);
+}
+
+__EXTERN_INLINE u32 marvel_readl(unsigned long addr)
+{
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
+               return (u32)-1;
+       }
+       return *(vuip)addr;
+}
+
+__EXTERN_INLINE u64 marvel_readq(unsigned long addr)
+{
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
+               return (u64)-1;
+       }
+       return *(vulp)addr;
+}
+
+__EXTERN_INLINE void marvel_writeb(u8 b, unsigned long addr)
+{
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
+               return;
+       }
+       __kernel_stb(b, *(vucp)addr);
+}
+
+__EXTERN_INLINE void marvel_writew(u16 w, unsigned long addr)
+{
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
+               return;
+       }
+       __kernel_stw(w, *(vusp)addr);
+}
+
+__EXTERN_INLINE void marvel_writel(u32 l, unsigned long addr)
+{
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
+               return;
+       }
+       *(vuip)addr = l;
+}
+
+__EXTERN_INLINE void marvel_writeq(u64 q, unsigned long addr)
+{
+       if (!marvel_is_ioaddr(addr)) {
+               IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
+               return;
+       }
+       *(vulp)addr = q;
+}
+
+#undef FIXUP_IOADDR
+#undef FIXUP_IOADDR_LEGACY
+#undef FIXUP_IOADDR_VGA
+
+#undef vucp
+#undef vusp
+#undef vuip
+#undef vulp
+
+#ifdef __WANT_IO_DEF
+
+#define __inb(p)               alpha_mv.mv_inb((unsigned long)(p))
+#define __inw(p)               alpha_mv.mv_inw((unsigned long)(p))
+#define __inl(p)               alpha_mv.mv_inl((unsigned long)(p))
+#define __outb(x,p)            alpha_mv.mv_outb((x),(unsigned long)(p))
+#define __outw(x,p)            alpha_mv.mv_outw((x),(unsigned long)(p))
+#define __outl(x,p)            alpha_mv.mv_outl((x),(unsigned long)(p))
+#define __readb(a)             marvel_readb((unsigned long)(a))
+#define __readw(a)             marvel_readw((unsigned long)(a))
+#define __readl(a)             marvel_readl((unsigned long)(a))
+#define __readq(a)             marvel_readq((unsigned long)(a))
+#define __writeb(x,a)          marvel_writeb((x),(unsigned long)(a))
+#define __writew(x,a)          marvel_writew((x),(unsigned long)(a))
+#define __writel(x,a)          marvel_writel((x),(unsigned long)(a))
+#define __writeq(x,a)          marvel_writeq((x),(unsigned long)(a))
+#define __ioremap(a,s)         alpha_mv.mv_ioremap((unsigned long)(a),(s))
+#define __iounmap(a)           alpha_mv.mv_iounmap((unsigned long)(a))
+#define __is_ioaddr(a)         marvel_is_ioaddr((unsigned long)(a))
+
+#define inb(port)              __inb((port))
+#define inw(port)              __inw((port))
+#define inl(port)              __inl((port))
+#define outb(v, port)          __outb((v),(port))
+#define outw(v, port)          __outw((v),(port))
+#define outl(v, port)          __outl((v),(port))
+
+#define __raw_readb(a)         __readb((unsigned long)(a))
+#define __raw_readw(a)         __readw((unsigned long)(a))
+#define __raw_readl(a)         __readl((unsigned long)(a))
+#define __raw_readq(a)         __readq((unsigned long)(a))
+#define __raw_writeb(v,a)      __writeb((v),(unsigned long)(a))
+#define __raw_writew(v,a)      __writew((v),(unsigned long)(a))
+#define __raw_writel(v,a)      __writel((v),(unsigned long)(a))
+#define __raw_writeq(v,a)      __writeq((v),(unsigned long)(a))
+
+#endif /* __WANT_IO_DEF */
+
+#ifdef __IO_EXTERN_INLINE
+# undef __EXTERN_INLINE
+# undef __IO_EXTERN_INLINE
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_MARVEL__H__ */
diff --git a/include/asm-alpha/gct.h b/include/asm-alpha/gct.h
new file mode 100644 (file)
index 0000000..3504c70
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __ALPHA_GCT_H
+#define __ALPHA_GCT_H
+
+typedef u64 gct_id;
+typedef u64 gct6_handle;
+
+typedef struct __gct6_node {
+       u8 type;        
+       u8 subtype;
+       u16 size;
+       u32 hd_extension;
+       gct6_handle owner;
+       gct6_handle active_user;
+       gct_id id;
+       u64 flags;
+       u16 rev;
+       u16 change_counter;
+       u16 max_child;
+       u16 reserved1;
+       gct6_handle saved_owner;
+       gct6_handle affinity;
+       gct6_handle parent;
+       gct6_handle next;
+       gct6_handle prev;
+       gct6_handle child;
+       u64 fw_flags;
+       u64 os_usage;
+       u64 fru_id;
+       u32 checksum;
+       u32 magic;      /* 'GLXY' */
+} gct6_node;
+
+typedef struct {
+       u8 type;        
+       u8 subtype;
+       void (*callout)(gct6_node *);
+} gct6_search_struct;
+
+#define GCT_NODE_MAGIC   0x59584c47    /* 'GLXY' */
+
+/* 
+ * node types 
+ */
+#define GCT_TYPE_HOSE                  0x0E
+
+/*
+ * node subtypes
+ */
+#define GCT_SUBTYPE_IO_PORT_MODULE     0x2C
+
+#define GCT_NODE_PTR(off) ((gct6_node *)((char *)hwrpb +               \
+                                        hwrpb->frut_offset +           \
+                                        (gct6_handle)(off)))           \
+
+int gct6_find_nodes(gct6_node *, gct6_search_struct *);
+
+#endif /* __ALPHA_GCT_H */
+
index 2eb985ed7741e19c561c76bdacc9996e49db2515..8e8f871af7cf033a27b7407d0475cf93ba747585 100644 (file)
@@ -64,6 +64,7 @@
 #define ST_DEC_CUSCO            36     /* CUSCO systype        */
 #define ST_DEC_EIGER            37     /* Eiger systype        */
 #define ST_DEC_TITAN            38     /* Titan systype        */
+#define ST_DEC_MARVEL           39     /* Marvel systype       */
 
 /* UNOFFICIAL!!! */
 #define ST_UNOFFICIAL_BIAS     100
index 4eb067ecc60b7db1d29a9e94a55c5b72987dd4bf..053532447560e80d12c79f0638d439a0a01da67d 100644 (file)
@@ -190,6 +190,8 @@ extern void _sethae (unsigned long addr);   /* cached version */
 # include <asm/jensen.h>
 #elif defined(CONFIG_ALPHA_LCA)
 # include <asm/core_lca.h>
+#elif defined(CONFIG_ALPHA_MARVEL)
+# include <asm/core_marvel.h>
 #elif defined(CONFIG_ALPHA_MCPCIA)
 # include <asm/core_mcpcia.h>
 #elif defined(CONFIG_ALPHA_POLARIS)
index 1a06d47bb55d5a6e9a0dccf181714fe2dbd1ac44..4dd8a29abca0b818b863ae6a0719f044bb7762af 100644 (file)
@@ -16,7 +16,7 @@
    many places throughout the kernel to size static arrays.  That's ok,
    we'll use alpha_mv.nr_irqs when we want the real thing.  */
 
-# define NR_IRQS       2048 /* enuff for WILDFIRE with 8 QBBs */
+# define NR_IRQS       (32768 + 16) /* enough for MARVEL with 128 PIDs */
 
 #elif defined(CONFIG_ALPHA_CABRIOLET) || \
       defined(CONFIG_ALPHA_EB66P)     || \
@@ -56,6 +56,9 @@
 #elif defined(CONFIG_ALPHA_WILDFIRE)
 # define NR_IRQS       2048 /* enuff for 8 QBBs */
 
+#elif defined(CONFIG_ALPHA_MARVEL)
+# define NR_IRQS       (32768 + 16) /* enough for MARVEL with 128 PIDs */
+
 #else /* everyone else */
 # define NR_IRQS       16
 #endif
index ae1e9c9a2c4462816748ee069537aa8ab67d8516..923f913e544abd3bfc632fecf2b248a9757c22b1 100644 (file)
@@ -42,6 +42,8 @@ struct pci_controller {
 
        struct pci_iommu_arena *sg_pci;
        struct pci_iommu_arena *sg_isa;
+
+       void *sysdata;
 };
 
 /* Override the logic in pci_scan_bus for skipping already-configured