Commit 0094874f authored by Ivan Kokshaysky's avatar Ivan Kokshaysky Committed by Richard Henderson

[PATCH] alpha titan update

From Jeff.Wiedemeier@hp.com:

Update titan system support include AlphaServer DS25, AGP,
enhanced machine check handling.
parent 44a2f54b
......@@ -75,7 +75,7 @@ choice
Sable AS 2000, AS 2100
Shark DS 20L
Takara Takara
Titan Privateer
Titan AlphaServer ES45 / DS25
Wildfire AlphaServer GS 40/80/160/320
If you don't know what to do, choose "generic".
......@@ -238,6 +238,8 @@ config ALPHA_TAKARA
config ALPHA_TITAN
bool "Titan"
help
AlphaServer ES45/DS25 SMP based on EV68 and Titan chipset.
config ALPHA_WILDFIRE
bool "Wildfire"
......
......@@ -34,6 +34,8 @@ 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
else
# Core logic support
......@@ -62,7 +64,8 @@ obj-$(CONFIG_ALPHA_PC164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
smc37c93x.o
obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
obj-$(CONFIG_ALPHA_SHARK) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
obj-$(CONFIG_ALPHA_TITAN) += sys_titan.o irq_i8259.o smc37c669.o
obj-$(CONFIG_ALPHA_TITAN) += sys_titan.o irq_i8259.o smc37c669.o \
err_titan.o
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
......
......@@ -10,10 +10,14 @@
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <asm/hwrpb.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
......@@ -25,8 +29,6 @@
#include "proto.h"
#include "pci_impl.h"
unsigned TITAN_agp = 0;
/* Save Titan configuration data as the console had it set up. */
struct
......@@ -49,6 +51,31 @@ struct
# define DBG_CFG(args)
#endif
/*
* Routines to access TIG registers.
*/
static volatile unsigned long *
mk_tig_addr(int offset)
{
return (volatile unsigned long *)(TITAN_TIG_SPACE + (offset << 6));
}
u8
titan_read_tig(int offset, u8 value)
{
volatile unsigned long *tig_addr = mk_tig_addr(offset);
return (u8)(*tig_addr & 0xff);
}
void
titan_write_tig(int offset, u8 value)
{
volatile unsigned long *tig_addr = mk_tig_addr(offset);
*tig_addr = (unsigned long)value;
}
/*
* Given a bus, device, and function number, compute resulting
* configuration space address
......@@ -185,7 +212,10 @@ titan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
port = &pachip->a_port;
/* We can invalidate up to 8 tlb entries in a go. The flush
matches against <31:16> in the pci address. */
matches against <31:16> in the pci address.
Note that gtlbi* and atlbi* are in the same place in the g_port
and a_port, respectively, so the g_port offset can be used
even if hose is an a_port */
csr = &port->port_specific.g.gtlbia.csr;
if (((start ^ end) & 0xffff0000) == 0)
csr = &port->port_specific.g.gtlbiv.csr;
......@@ -200,9 +230,7 @@ titan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
*csr;
}
#define FN __FUNCTION__
static int __init
static int
titan_query_agp(titan_pachip_port *port)
{
union TPAchipPCTL pctl;
......@@ -213,37 +241,6 @@ titan_query_agp(titan_pachip_port *port)
return pctl.pctl_r_bits.apctl_v_agp_present;
}
static void __init
titan_init_agp(titan_pachip_port *port, struct pci_controller *hose)
{
union TPAchipPCTL pctl;
if (!titan_query_agp(port))
return;
printk("AGP present on hose %d\n", hose->index);
/* get APCTL */
pctl.pctl_q_whole = port->pctl.csr;
pctl.pctl_r_bits.apctl_v_agp_en = 1; /* enable AGP */
pctl.pctl_r_bits.apctl_v_agp_lp_rd = 0;
pctl.pctl_r_bits.apctl_v_agp_hp_rd = 0;
port->pctl.csr = pctl.pctl_q_whole;
TITAN_agp |= 1 << hose->index;
#ifdef CONFIG_VGA_HOSE
/* is a graphics card on the AGP? (always device 5) */
if (hose != NULL &&
__kernel_ldwu(*(vusp)(hose->config_space_base + 0x280a)) ==
PCI_CLASS_DISPLAY_VGA)
set_vga_hose(hose);
#endif
}
static void __init
titan_init_one_pachip_port(titan_pachip_port *port, int index)
{
......@@ -255,10 +252,13 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
hose->io_space = alloc_resource();
hose->mem_space = alloc_resource();
/* This is for userland consumption. For some reason, the 40-bit
PIO bias that we use in the kernel through KSEG didn't work for
the page table based user mappings. So make sure we get the
43-bit PIO bias. */
/*
* This is for userland consumption. The 40-bit PIO bias that we
* use in the kernel through KSEG doesn't work in the page table
* based user mappings. (43-bit KSEG sign extends the physical
* address from bit 40 to hit the I/O bit - mapped addresses don't).
* So make sure we get the 43-bit PIO bias.
*/
hose->sparse_mem_base = 0;
hose->sparse_io_base = 0;
hose->dense_mem_base
......@@ -284,9 +284,6 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
if (request_resource(&iomem_resource, hose->mem_space) < 0)
printk(KERN_ERR "Failed to request MEM on hose %d\n", index);
/* It's safe to call this for both G-Ports and A-Ports */
titan_init_agp(port, hose);
/*
* Save the existing PCI window translations. SRM will
* need them when we go to reboot.
......@@ -313,36 +310,38 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
* Note: Window 3 on Titan is Scatter-Gather ONLY
*
* Window 0 is scatter-gather 8MB at 8MB (for isa)
* Window 1 is scatter-gather (up to) 1GB at 1GB
* Window 2 is direct access 2GB at 2GB
* Window 1 is direct access 1GB at 2GB
* Window 2 is scatter-gather 1GB at 3GB
*/
hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
hose->sg_isa->align_entry = 8; /* 64KB for ISA */
hose->sg_pci = iommu_arena_new(hose, 0x40000000,
size_for_memory(0x40000000), 0);
hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x40000000, 0);
hose->sg_pci->align_entry = 4; /* Titan caches 4 PTEs at a time */
__direct_map_base = 0x80000000;
__direct_map_size = 0x80000000;
port->wsba[0].csr = hose->sg_isa->dma_base | 3;
port->wsm[0].csr = (hose->sg_isa->size - 1) & 0xfff00000;
port->tba[0].csr = virt_to_phys(hose->sg_isa->ptes);
port->wsba[1].csr = hose->sg_pci->dma_base | 3;
port->wsm[1].csr = (hose->sg_pci->size - 1) & 0xfff00000;
port->tba[1].csr = virt_to_phys(hose->sg_pci->ptes);
port->wsba[1].csr = __direct_map_base | 1;
port->wsm[1].csr = (__direct_map_size - 1) & 0xfff00000;
port->tba[1].csr = 0;
port->wsba[2].csr = 0x80000000 | 1;
port->wsm[2].csr = (0x80000000 - 1) & 0xfff00000;
port->tba[2].csr = 0;
port->wsba[2].csr = hose->sg_pci->dma_base | 3;
port->wsm[2].csr = (hose->sg_pci->size - 1) & 0xfff00000;
port->tba[2].csr = virt_to_phys(hose->sg_pci->ptes);
port->wsba[3].csr = 0;
/* Enable the Monster Window to make DAC pci64 possible. */
port->pctl.csr |= pctl_m_mwin;
/*
* If it's an AGP port, initialize agplastwr
*/
if (titan_query_agp(port))
port->port_specific.a.agplastwr.csr = __direct_map_base;
titan_pci_tbi(hose, 0, -1);
}
......@@ -360,25 +359,51 @@ titan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */
}
static void __init
titan_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;
int h = (pu64[30] >> 24) & 0xff; /* console hose # */
/*
* Our hose numbering matches the console's, so just find
* the right one...
*/
for(hose = hose_head; hose; hose = hose->next) {
if (hose->index == h) break;
}
if (hose) {
printk("Console graphics on hose %d\n", hose->index);
pci_vga_hose = hose;
}
}
#endif /* CONFIG_VGA_HOSE */
}
void __init
titan_init_arch(void)
{
#if 0
printk("%s: titan_init_arch()\n", FN);
printk("%s: CChip registers:\n", FN);
printk("%s: CSR_CSC 0x%lx\n", FN, TITAN_cchip->csc.csr);
printk("%s: CSR_MTR 0x%lx\n", FN, TITAN_cchip->mtr.csr);
printk("%s: CSR_MISC 0x%lx\n", FN, TITAN_cchip->misc.csr);
printk("%s: CSR_DIM0 0x%lx\n", FN, TITAN_cchip->dim0.csr);
printk("%s: CSR_DIM1 0x%lx\n", FN, TITAN_cchip->dim1.csr);
printk("%s: CSR_DIR0 0x%lx\n", FN, TITAN_cchip->dir0.csr);
printk("%s: CSR_DIR1 0x%lx\n", FN, TITAN_cchip->dir1.csr);
printk("%s: CSR_DRIR 0x%lx\n", FN, TITAN_cchip->drir.csr);
printk("%s: DChip registers:\n", FN);
printk("%s: CSR_DSC 0x%lx\n", FN, TITAN_dchip->dsc.csr);
printk("%s: CSR_STR 0x%lx\n", FN, TITAN_dchip->str.csr);
printk("%s: CSR_DREV 0x%lx\n", FN, TITAN_dchip->drev.csr);
printk("%s: titan_init_arch()\n", __FUNCTION__);
printk("%s: CChip registers:\n", __FUNCTION__);
printk("%s: CSR_CSC 0x%lx\n", __FUNCTION__, TITAN_cchip->csc.csr);
printk("%s: CSR_MTR 0x%lx\n", __FUNCTION__, TITAN_cchip->mtr.csr);
printk("%s: CSR_MISC 0x%lx\n", __FUNCTION__, TITAN_cchip->misc.csr);
printk("%s: CSR_DIM0 0x%lx\n", __FUNCTION__, TITAN_cchip->dim0.csr);
printk("%s: CSR_DIM1 0x%lx\n", __FUNCTION__, TITAN_cchip->dim1.csr);
printk("%s: CSR_DIR0 0x%lx\n", __FUNCTION__, TITAN_cchip->dir0.csr);
printk("%s: CSR_DIR1 0x%lx\n", __FUNCTION__, TITAN_cchip->dir1.csr);
printk("%s: CSR_DRIR 0x%lx\n", __FUNCTION__, TITAN_cchip->drir.csr);
printk("%s: DChip registers:\n", __FUNCTION__);
printk("%s: CSR_DSC 0x%lx\n", __FUNCTION__, TITAN_dchip->dsc.csr);
printk("%s: CSR_STR 0x%lx\n", __FUNCTION__, TITAN_dchip->str.csr);
printk("%s: CSR_DREV 0x%lx\n", __FUNCTION__, TITAN_dchip->drev.csr);
#endif
boot_cpuid = __hard_smp_processor_id();
......@@ -387,8 +412,15 @@ titan_init_arch(void)
ioport_resource.end = ~0UL;
iomem_resource.end = ~0UL;
/* PCI DMA Direct Mapping is 1GB at 2GB */
__direct_map_base = 0x80000000;
__direct_map_size = 0x40000000;
/* Init the PA chip(s) */
titan_init_pachips(TITAN_pachip0, TITAN_pachip1);
/* Check for graphic console location (if any) */
titan_init_vga_hose();
}
static void
......@@ -430,38 +462,328 @@ titan_kill_arch(int mode)
titan_kill_pachips(TITAN_pachip0, TITAN_pachip1);
}
static inline void
titan_pci_clr_err_1(titan_pachip *pachip)
/*
* IO map support
*/
unsigned long
titan_ioremap(unsigned long addr, unsigned long size)
{
unsigned int jd;
int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT;
unsigned long baddr = addr & ~TITAN_HOSE_MASK;
unsigned long last = baddr + size - 1;
struct pci_controller *hose;
struct vm_struct *area;
unsigned long vaddr;
unsigned long *ptes;
unsigned long pfn;
/*
* Adjust the addr
*/
#ifdef CONFIG_VGA_HOSE
if (pci_vga_hose && __titan_is_mem_vga(addr)) {
h = pci_vga_hose->index;
addr += pci_vga_hose->mem_space->start;
}
#endif
/*
* Find the hose
*/
for(hose = hose_head; hose; hose = hose->next)
if (hose->index == h) break;
if (!hose) return (unsigned long)NULL;
/*
* Is it direct-mapped?
*/
if ((baddr >= __direct_map_base) &&
((baddr + size - 1) < __direct_map_base + __direct_map_size))
return addr - __direct_map_base + TITAN_MEM_BIAS;
/*
* 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 (unsigned long)NULL;
}
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 (unsigned long)NULL;
}
}
flush_tlb_all();
vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
return vaddr;
}
/*
* Not found - assume legacy ioremap
*/
return addr + TITAN_MEM_BIAS;
jd = pachip->g_port.port_specific.g.gperror.csr;
pachip->g_port.port_specific.g.gperror.csr = jd;
mb();
pachip->g_port.port_specific.g.gperror.csr;
}
static inline void
titan_pci_clr_err(void)
void
titan_iounmap(unsigned long addr)
{
titan_pci_clr_err_1(TITAN_pachip0);
if (((long)addr >> 41) == -2)
return; /* kseg map, nothing to do */
if (addr) return vfree((void *)(PAGE_MASK & addr));
}
if (TITAN_cchip->csc.csr & 1L<<14)
titan_pci_clr_err_1(TITAN_pachip1);
/*
* AGP GART Support
*/
#if defined(CONFIG_ALPHA_CORE_AGP)
#include <linux/agp_backend.h>
#include <asm/agp_backend.h>
#include <linux/slab.h>
#include <linux/delay.h>
#define TITAN_AGP_APER_SIZE (64 * 1024 * 1024)
struct titan_agp_aperture {
struct pci_iommu_arena *arena;
long pg_start;
long pg_count;
};
static int titan_agp_setup(alpha_agp_info *agp)
{
struct titan_agp_aperture *aper;
aper = kmalloc(sizeof(struct titan_agp_aperture), GFP_KERNEL);
if (aper == NULL) return -ENOMEM;
aper->arena = agp->hose->sg_pci;
aper->pg_count = TITAN_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;
}
void
titan_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
static void titan_agp_cleanup(alpha_agp_info *agp)
{
/* clear error before any reporting. */
mb();
draina();
titan_pci_clr_err();
wrmces(0x7);
mb();
struct titan_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");
process_mcheck_info(vector, la_ptr, regs, "TITAN",
mcheck_expected(smp_processor_id()));
kfree(aper);
kfree(agp);
}
static int titan_agp_configure(alpha_agp_info *agp)
{
union TPAchipPCTL pctl;
titan_pachip_port *port = agp->private;
pctl.pctl_q_whole = port->pctl.csr;
/* Side-Band Addressing? */
pctl.pctl_r_bits.apctl_v_agp_sba_en = agp->mode.bits.sba;
/* AGP Rate? */
pctl.pctl_r_bits.apctl_v_agp_rate = 0; /* 1x */
if (agp->mode.bits.rate & 2)
pctl.pctl_r_bits.apctl_v_agp_rate = 1; /* 2x */
#if 0
if (agp->mode.bits.rate & 4)
pctl.pctl_r_bits.apctl_v_agp_rate = 2; /* 4x */
#endif
/* RQ Depth? */
pctl.pctl_r_bits.apctl_v_agp_hp_rd = 2;
pctl.pctl_r_bits.apctl_v_agp_lp_rd = 7;
/*
* AGP Enable
*/
pctl.pctl_r_bits.apctl_v_agp_en = agp->mode.bits.enable;
/* Tell the user... */
printk("Enabling AGP: %dX%s\n",
1 << pctl.pctl_r_bits.apctl_v_agp_rate,
pctl.pctl_r_bits.apctl_v_agp_sba_en ? " - SBA" : "");
/* Write it */
port->pctl.csr = pctl.pctl_q_whole;
/* And wait at least 5000 66MHz cycles (per Titan spec) */
udelay(100);
return 0;
}
static int
titan_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
{
struct titan_agp_aperture *aper = agp->aperture.sysdata;
return iommu_bind(aper->arena, aper->pg_start + pg_start,
mem->page_count, mem->memory);
}
static int
titan_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
{
struct titan_agp_aperture *aper = agp->aperture.sysdata;
return iommu_unbind(aper->arena, aper->pg_start + pg_start,
mem->page_count);
}
static unsigned long
titan_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
{
struct titan_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 titan_agp_ops =
{
setup: titan_agp_setup,
cleanup: titan_agp_cleanup,
configure: titan_agp_configure,
bind: titan_agp_bind_memory,
unbind: titan_agp_unbind_memory,
translate: titan_agp_translate
};
alpha_agp_info *
titan_agp_info(void)
{
extern struct pci_controller *hose_head;
alpha_agp_info *agp;
struct pci_controller *hose;
titan_pachip_port *port;
int hosenum = -1;
union TPAchipPCTL pctl;
/*
* Find the AGP port
*/
port = &TITAN_pachip0->a_port;
if (titan_query_agp(port))
hosenum = 2;
if (hosenum < 0 &&
titan_query_agp(port = &TITAN_pachip1->a_port))
hosenum = 3;
/*
* Find the hose the port is on
*/
for(hose = hose_head; hose; hose = hose->next) {
if (hose->index == hosenum) break;
}
if (!hose || !hose->sg_pci) return NULL;
/*
* Allocate the info structure
*/
agp = kmalloc(sizeof(*agp), GFP_KERNEL);
/*
* Fill it in
*/
agp->type = ALPHA_CORE_AGP;
agp->hose = hose;
agp->private = port;
agp->ops = &titan_agp_ops;
/*
* Aperture - not configured until ops.setup()
*
* FIXME - should we go ahead and allocate it here?
*/
agp->aperture.bus_base = 0;
agp->aperture.size = 0;
agp->aperture.sysdata = NULL;
/*
* Capabilities
*/
agp->capability.lw = 0;
agp->capability.bits.rate = 3; /* 2x, 1x */
agp->capability.bits.sba = 1;
agp->capability.bits.rq = 7; /* 8 - 1 */
/*
* Mode
*/
pctl.pctl_q_whole = port->pctl.csr;
agp->mode.lw = 0;
agp->mode.bits.rate = 1 << pctl.pctl_r_bits.apctl_v_agp_rate;
agp->mode.bits.sba = pctl.pctl_r_bits.apctl_v_agp_sba_en;
agp->mode.bits.rq = 7; /* RQ Depth? */
agp->mode.bits.enable = pctl.pctl_r_bits.apctl_v_agp_en;
return agp;
}
#endif /* CONFIG_ALPHA_CORE_AGP */
......@@ -146,3 +146,11 @@ 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_titan.c
*/
extern int titan_process_logout_frame(struct el_common *, int);
extern void titan_machine_check(u64, u64, struct pt_regs *);
extern void titan_register_error_handlers(void);
extern int privateer_process_logout_frame(struct el_common *, int);
extern void privateer_machine_check(u64, u64, struct pt_regs *);
/*
* linux/arch/alpha/kernel/err_titan.c
*
* Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
*
* Error handling code supporting TITAN systems
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/core_titan.h>
#include <asm/hwrpb.h>
#include <asm/smp.h>
#include "err_impl.h"
#include "proto.h"
/*
* Titan generic
*/
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_TITAN)
static int
titan_parse_c_misc(u64 c_misc, int print)
{
char *src;
int nxs = 0;
int status = MCHK_DISPOSITION_REPORT;
#define TITAN__CCHIP_MISC__NXM (1UL << 28)
#define TITAN__CCHIP_MISC__NXS__S (29)
#define TITAN__CCHIP_MISC__NXS__M (0x7)
if (!(c_misc & TITAN__CCHIP_MISC__NXM))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
nxs = EXTRACT(c_misc, TITAN__CCHIP_MISC__NXS);
switch(nxs) {
case 0: /* CPU 0 */
case 1: /* CPU 1 */
case 2: /* CPU 2 */
case 3: /* CPU 3 */
src = "CPU";
/* num is already the CPU number */
break;
case 4: /* Pchip 0 */
case 5: /* Pchip 1 */
src = "Pchip";
nxs -= 4;
break;
default:/* reserved */
src = "Unknown, NXS =";
/* leave num untouched */
break;
}
printk("%s Non-existent memory access from: %s %d\n",
err_print_prefix, src, nxs);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
titan_parse_p_serror(int which, u64 serror, int print)
{
int status = MCHK_DISPOSITION_REPORT;
#ifdef CONFIG_VERBOSE_MCHECK
char *serror_src[] = {"GPCI", "APCI", "AGP HP", "AGP LP"};
char *serror_cmd[] = {"DMA Read", "DMA RMW", "SGTE Read", "Reserved"};
#endif /* CONFIG_VERBOSE_MCHECK */
#define TITAN__PCHIP_SERROR__LOST_UECC (1UL << 0)
#define TITAN__PCHIP_SERROR__UECC (1UL << 1)
#define TITAN__PCHIP_SERROR__CRE (1UL << 2)
#define TITAN__PCHIP_SERROR__NXIO (1UL << 3)
#define TITAN__PCHIP_SERROR__LOST_CRE (1UL << 4)
#define TITAN__PCHIP_SERROR__ECCMASK (TITAN__PCHIP_SERROR__UECC | \
TITAN__PCHIP_SERROR__CRE)
#define TITAN__PCHIP_SERROR__ERRMASK (TITAN__PCHIP_SERROR__LOST_UECC | \
TITAN__PCHIP_SERROR__UECC | \
TITAN__PCHIP_SERROR__CRE | \
TITAN__PCHIP_SERROR__NXIO | \
TITAN__PCHIP_SERROR__LOST_CRE)
#define TITAN__PCHIP_SERROR__SRC__S (52)
#define TITAN__PCHIP_SERROR__SRC__M (0x3)
#define TITAN__PCHIP_SERROR__CMD__S (54)
#define TITAN__PCHIP_SERROR__CMD__M (0x3)
#define TITAN__PCHIP_SERROR__SYN__S (56)
#define TITAN__PCHIP_SERROR__SYN__M (0xff)
#define TITAN__PCHIP_SERROR__ADDR__S (15)
#define TITAN__PCHIP_SERROR__ADDR__M (0xffffffffUL)
if (!(serror & TITAN__PCHIP_SERROR__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
printk("%s PChip %d SERROR: %016lx\n",
err_print_prefix, which, serror);
if (serror & TITAN__PCHIP_SERROR__ECCMASK) {
printk("%s %sorrectable ECC Error:\n"
" Source: %-6s Command: %-8s Syndrome: 0x%08x\n"
" Address: 0x%lx\n",
err_print_prefix,
(serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C",
serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)],
serror_cmd[EXTRACT(serror, TITAN__PCHIP_SERROR__CMD)],
(unsigned)EXTRACT(serror, TITAN__PCHIP_SERROR__SYN),
EXTRACT(serror, TITAN__PCHIP_SERROR__ADDR));
}
if (serror & TITAN__PCHIP_SERROR__NXIO)
printk("%s Non Existent I/O Error\n", err_print_prefix);
if (serror & TITAN__PCHIP_SERROR__LOST_UECC)
printk("%s Lost Uncorrectable ECC Error\n",
err_print_prefix);
if (serror & TITAN__PCHIP_SERROR__LOST_CRE)
printk("%s Lost Correctable ECC Error\n", err_print_prefix);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
titan_parse_p_perror(int which, int port, u64 perror, int print)
{
int cmd;
unsigned long addr;
int status = MCHK_DISPOSITION_REPORT;
#ifdef CONFIG_VERBOSE_MCHECK
char *perror_cmd[] = { "Interrupt Acknowledge", "Special Cycle",
"I/O Read", "I/O Write",
"Reserved", "Reserved",
"Memory Read", "Memory Write",
"Reserved", "Reserved",
"Configuration Read", "Configuration Write",
"Memory Read Multiple", "Dual Address Cycle",
"Memory Read Line","Memory Write and Invalidate"
};
#endif /* CONFIG_VERBOSE_MCHECK */
#define TITAN__PCHIP_PERROR__LOST (1UL << 0)
#define TITAN__PCHIP_PERROR__SERR (1UL << 1)
#define TITAN__PCHIP_PERROR__PERR (1UL << 2)
#define TITAN__PCHIP_PERROR__DCRTO (1UL << 3)
#define TITAN__PCHIP_PERROR__SGE (1UL << 4)
#define TITAN__PCHIP_PERROR__APE (1UL << 5)
#define TITAN__PCHIP_PERROR__TA (1UL << 6)
#define TITAN__PCHIP_PERROR__DPE (1UL << 7)
#define TITAN__PCHIP_PERROR__NDS (1UL << 8)
#define TITAN__PCHIP_PERROR__IPTPR (1UL << 9)
#define TITAN__PCHIP_PERROR__IPTPW (1UL << 10)
#define TITAN__PCHIP_PERROR__ERRMASK (TITAN__PCHIP_PERROR__LOST | \
TITAN__PCHIP_PERROR__SERR | \
TITAN__PCHIP_PERROR__PERR | \
TITAN__PCHIP_PERROR__DCRTO | \
TITAN__PCHIP_PERROR__SGE | \
TITAN__PCHIP_PERROR__APE | \
TITAN__PCHIP_PERROR__TA | \
TITAN__PCHIP_PERROR__DPE | \
TITAN__PCHIP_PERROR__NDS | \
TITAN__PCHIP_PERROR__IPTPR | \
TITAN__PCHIP_PERROR__IPTPW)
#define TITAN__PCHIP_PERROR__DAC (1UL << 47)
#define TITAN__PCHIP_PERROR__MWIN (1UL << 48)
#define TITAN__PCHIP_PERROR__CMD__S (52)
#define TITAN__PCHIP_PERROR__CMD__M (0x0f)
#define TITAN__PCHIP_PERROR__ADDR__S (14)
#define TITAN__PCHIP_PERROR__ADDR__M (0x1ffffffff)
if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
cmd = EXTRACT(perror, TITAN__PCHIP_PERROR__CMD);
addr = EXTRACT(perror, TITAN__PCHIP_PERROR__ADDR) << 2;
/*
* Initializing the BIOS on a video card on a bus without
* a south bridge (subtractive decode agent) can result in
* master aborts as the BIOS probes the capabilities of the
* card. XFree86 does such initialization. If the error
* is a master abort (No DevSel as PCI Master) and the command
* is an I/O read or write below the address where we start
* assigning PCI I/O spaces (SRM uses 0x1000), then mark the
* error as dismissable so starting XFree86 doesn't result
* in a series of uncorrectable errors being reported. Also
* dismiss master aborts to VGA frame buffer space
* (0xA0000 - 0xC0000) and legacy BIOS space (0xC0000 - 0x100000)
* for the same reason.
*
* Also mark the error dismissible if it looks like the right
* error but only the Lost bit is set. Since the BIOS initialization
* can cause multiple master aborts and the error interrupt can
* be handled on a different CPU than the BIOS code is run on,
* it is possible for a second master abort to occur between the
* time the PALcode reads PERROR and the time it writes PERROR
* to acknowledge the error. If this timing happens, a second
* error will be signalled after the first, and if no additional
* errors occur, will look like a Lost error with no additional
* errors on the same transaction as the previous error.
*/
if (((perror & TITAN__PCHIP_PERROR__NDS) ||
((perror & TITAN__PCHIP_PERROR__ERRMASK) ==
TITAN__PCHIP_PERROR__LOST)) &&
((((cmd & 0xE) == 2) && (addr < 0x1000)) ||
(((cmd & 0xE) == 6) && (addr >= 0xA0000) && (addr < 0x100000)))) {
status = MCHK_DISPOSITION_DISMISS;
}
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
printk("%s PChip %d %cPERROR: %016lx\n",
err_print_prefix, which,
port ? 'A' : 'G', perror);
if (perror & TITAN__PCHIP_PERROR__IPTPW)
printk("%s Invalid Peer-to-Peer Write\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__IPTPR)
printk("%s Invalid Peer-to-Peer Read\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__NDS)
printk("%s No DEVSEL as PCI Master [Master Abort]\n",
err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__DPE)
printk("%s Data Parity Error\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__TA)
printk("%s Target Abort\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__APE)
printk("%s Address Parity Error\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__SGE)
printk("%s Scatter-Gather Error, Invalid PTE\n",
err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__DCRTO)
printk("%s Delayed-Completion Retry Timeout\n",
err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__PERR)
printk("%s PERR Asserted\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__SERR)
printk("%s SERR Asserted\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__LOST)
printk("%s Lost Error\n", err_print_prefix);
printk("%s Command: 0x%x - %s\n"
" Address: 0x%lx\n",
err_print_prefix,
cmd, perror_cmd[cmd],
addr);
if (perror & TITAN__PCHIP_PERROR__DAC)
printk("%s Dual Address Cycle\n", err_print_prefix);
if (perror & TITAN__PCHIP_PERROR__MWIN)
printk("%s Hit in Monster Window\n", err_print_prefix);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
titan_parse_p_agperror(int which, u64 agperror, int print)
{
int cmd, len;
unsigned long addr;
int status = MCHK_DISPOSITION_REPORT;
#ifdef CONFIG_VERBOSE_MCHECK
char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)",
"Write (low-priority)",
"Write (high-priority)",
"Reserved", "Reserved",
"Flush", "Fence"
};
#endif /* CONFIG_VERBOSE_MCHECK */
#define TITAN__PCHIP_AGPERROR__LOST (1UL << 0)
#define TITAN__PCHIP_AGPERROR__LPQFULL (1UL << 1)
#define TITAN__PCHIP_AGPERROR__HPQFULL (1UL << 2)
#define TITAN__PCHIP_AGPERROR__RESCMD (1UL << 3)
#define TITAN__PCHIP_AGPERROR__IPTE (1UL << 4)
#define TITAN__PCHIP_AGPERROR__PTP (1UL << 5)
#define TITAN__PCHIP_AGPERROR__NOWINDOW (1UL << 6)
#define TITAN__PCHIP_AGPERROR__ERRMASK (TITAN__PCHIP_AGPERROR__LOST | \
TITAN__PCHIP_AGPERROR__LPQFULL | \
TITAN__PCHIP_AGPERROR__HPQFULL | \
TITAN__PCHIP_AGPERROR__RESCMD | \
TITAN__PCHIP_AGPERROR__IPTE | \
TITAN__PCHIP_AGPERROR__PTP | \
TITAN__PCHIP_AGPERROR__NOWINDOW)
#define TITAN__PCHIP_AGPERROR__DAC (1UL << 48)
#define TITAN__PCHIP_AGPERROR__MWIN (1UL << 49)
#define TITAN__PCHIP_AGPERROR__FENCE (1UL << 59)
#define TITAN__PCHIP_AGPERROR__CMD__S (50)
#define TITAN__PCHIP_AGPERROR__CMD__M (0x07)
#define TITAN__PCHIP_AGPERROR__ADDR__S (15)
#define TITAN__PCHIP_AGPERROR__ADDR__M (0xffffffffUL)
#define TITAN__PCHIP_AGPERROR__LEN__S (53)
#define TITAN__PCHIP_AGPERROR__LEN__M (0x3f)
if (!(agperror & TITAN__PCHIP_AGPERROR__ERRMASK))
return MCHK_DISPOSITION_UNKNOWN_ERROR;
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
cmd = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__CMD);
addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3;
len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN);
printk("%s PChip %d AGPERROR: %016lx\n", err_print_prefix,
which, agperror);
if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW)
printk("%s No Window\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__PTP)
printk("%s Peer-to-Peer set\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__IPTE)
printk("%s Invalid PTE\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__RESCMD)
printk("%s Reserved Command\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__HPQFULL)
printk("%s HP Transaction Received while Queue Full\n",
err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__LPQFULL)
printk("%s LP Transaction Received while Queue Full\n",
err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__LOST)
printk("%s Lost Error\n", err_print_prefix);
printk("%s Command: 0x%x - %s, %d Quadwords%s\n"
" Address: 0x%lx\n",
err_print_prefix, cmd, agperror_cmd[cmd], len,
(agperror & TITAN__PCHIP_AGPERROR__FENCE) ? ", FENCE" : "",
addr);
if (agperror & TITAN__PCHIP_AGPERROR__DAC)
printk("%s Dual Address Cycle\n", err_print_prefix);
if (agperror & TITAN__PCHIP_AGPERROR__MWIN)
printk("%s Hit in Monster Window\n", err_print_prefix);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
static int
titan_parse_p_chip(int which, u64 serror, u64 gperror,
u64 aperror, u64 agperror, int print)
{
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
status |= titan_parse_p_serror(which, serror, print);
status |= titan_parse_p_perror(which, 0, gperror, print);
status |= titan_parse_p_perror(which, 1, aperror, print);
status |= titan_parse_p_agperror(which, agperror, print);
return status;
}
int
titan_process_logout_frame(struct el_common *mchk_header, int print)
{
struct el_TITAN_sysdata_mcheck *tmchk =
(struct el_TITAN_sysdata_mcheck *)
((unsigned long)mchk_header + mchk_header->sys_offset);
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
status |= titan_parse_c_misc(tmchk->c_misc, print);
status |= titan_parse_p_chip(0, tmchk->p0_serror, tmchk->p0_gperror,
tmchk->p0_aperror, tmchk->p0_agperror,
print);
status |= titan_parse_p_chip(1, tmchk->p1_serror, tmchk->p1_gperror,
tmchk->p1_aperror, tmchk->p1_agperror,
print);
return status;
}
void
titan_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
struct el_TITAN_sysdata_mcheck *tmchk =
(struct el_TITAN_sysdata_mcheck *)
((unsigned long)mchk_header + mchk_header->sys_offset);
u64 irqmask;
/*
* Mask of Titan interrupt sources which are reported as machine checks
*
* 63 - CChip Error
* 62 - PChip 0 H_Error
* 61 - PChip 1 H_Error
* 60 - PChip 0 C_Error
* 59 - PChip 1 C_Error
*/
#define TITAN_MCHECK_INTERRUPT_MASK 0xF800000000000000UL
/*
* Sync the processor
*/
mb();
draina();
/*
* Only handle system errors here
*/
if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR))
return ev6_machine_check(vector, la_ptr, regs);
/*
* It's a system error, handle it here
*
* The PALcode has already cleared the error, so just parse it
*/
/*
* Parse the logout frame without printing first. If the only error(s)
* found are classified as "dismissable", then just dismiss them and
* don't print any message
*/
if (titan_process_logout_frame(mchk_header, 0) !=
MCHK_DISPOSITION_DISMISS) {
char *saved_err_prefix = err_print_prefix;
err_print_prefix = KERN_CRIT;
/*
* Either a nondismissable error was detected or no
* recognized error was detected in the logout frame
* -- report the error in either case
*/
printk("%s"
"*System %s Error (Vector 0x%x) reported on CPU %d:\n",
err_print_prefix,
(vector == SCB_Q_SYSERR)?"Correctable":"Uncorrectable",
(unsigned int)vector, (int)smp_processor_id());
#ifdef CONFIG_VERBOSE_MCHECK
titan_process_logout_frame(mchk_header, 1);
dik_show_regs(regs, NULL);
#endif /* CONFIG_VERBOSE_MCHECK */
err_print_prefix = saved_err_prefix;
/*
* Convert any pending interrupts which report as system
* machine checks to interrupts
*/
irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
titan_dispatch_irqs(irqmask, regs);
}
/*
* Release the logout frame
*/
wrmces(0x7);
mb();
}
/*
* Subpacket Annotations
*/
static char *el_titan_pchip0_extended_annotation[] = {
"Subpacket Header", "P0_SCTL", "P0_SERREN",
"P0_APCTL", "P0_APERREN", "P0_AGPERREN",
"P0_ASPRST", "P0_AWSBA0", "P0_AWSBA1",
"P0_AWSBA2", "P0_AWSBA3", "P0_AWSM0",
"P0_AWSM1", "P0_AWSM2", "P0_AWSM3",
"P0_ATBA0", "P0_ATBA1", "P0_ATBA2",
"P0_ATBA3", "P0_GPCTL", "P0_GPERREN",
"P0_GSPRST", "P0_GWSBA0", "P0_GWSBA1",
"P0_GWSBA2", "P0_GWSBA3", "P0_GWSM0",
"P0_GWSM1", "P0_GWSM2", "P0_GWSM3",
"P0_GTBA0", "P0_GTBA1", "P0_GTBA2",
"P0_GTBA3", NULL
};
static char *el_titan_pchip1_extended_annotation[] = {
"Subpacket Header", "P1_SCTL", "P1_SERREN",
"P1_APCTL", "P1_APERREN", "P1_AGPERREN",
"P1_ASPRST", "P1_AWSBA0", "P1_AWSBA1",
"P1_AWSBA2", "P1_AWSBA3", "P1_AWSM0",
"P1_AWSM1", "P1_AWSM2", "P1_AWSM3",
"P1_ATBA0", "P1_ATBA1", "P1_ATBA2",
"P1_ATBA3", "P1_GPCTL", "P1_GPERREN",
"P1_GSPRST", "P1_GWSBA0", "P1_GWSBA1",
"P1_GWSBA2", "P1_GWSBA3", "P1_GWSM0",
"P1_GWSM1", "P1_GWSM2", "P1_GWSM3",
"P1_GTBA0", "P1_GTBA1", "P1_GTBA2",
"P1_GTBA3", NULL
};
static char *el_titan_memory_extended_annotation[] = {
"Subpacket Header", "AAR0", "AAR1",
"AAR2", "AAR3", "P0_SCTL",
"P0_GPCTL", "P0_APCTL", "P1_SCTL",
"P1_GPCTL", "P1_SCTL", NULL
};
static struct el_subpacket_annotation el_titan_annotations[] = {
SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED,
1,
"Titan PChip 0 Extended Frame",
el_titan_pchip0_extended_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED,
1,
"Titan PChip 1 Extended Frame",
el_titan_pchip1_extended_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED,
1,
"Titan Memory Extended Frame",
el_titan_memory_extended_annotation),
SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
EL_TYPE__TERMINATION__TERMINATION,
1,
"Termination Subpacket",
NULL)
};
static struct el_subpacket *
el_process_regatta_subpacket(struct el_subpacket *header)
{
int status;
if (header->class != EL_CLASS__REGATTA_FAMILY) {
printk("%s ** Unexpected header CLASS %d TYPE %d, aborting\n",
err_print_prefix,
header->class, header->type);
return NULL;
}
switch(header->type) {
case EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME:
case EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME:
case EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME:
case EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT:
case EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT:
printk("%s ** Occurred on CPU %d:\n",
err_print_prefix,
(int)header->by_type.regatta_frame.cpuid);
status = privateer_process_logout_frame((struct el_common *)
header->by_type.regatta_frame.data_start, 1);
break;
default:
printk("%s ** REGATTA TYPE %d SUBPACKET\n",
err_print_prefix, header->type);
el_annotate_subpacket(header);
break;
}
return (struct el_subpacket *)((unsigned long)header + header->length);
}
static struct el_subpacket_handler titan_subpacket_handler =
SUBPACKET_HANDLER_INIT(EL_CLASS__REGATTA_FAMILY,
el_process_regatta_subpacket);
void
titan_register_error_handlers(void)
{
int i;
for(i = 0;
i < sizeof(el_titan_annotations)/sizeof(el_titan_annotations[1]);
i++) {
cdl_register_subpacket_annotation(&el_titan_annotations[i]);
}
cdl_register_subpacket_handler(&titan_subpacket_handler);
}
#endif /* CONFIG_ALPHA_GENERIC || CONFIG_ALPHA_TITAN */
/*
* Privateer
*/
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_TITAN)
static int
privateer_process_680_frame(struct el_common *mchk_header, int print)
{
struct el_PRIVATEER_envdata_mcheck *emchk =
(struct el_PRIVATEER_envdata_mcheck *)
((unsigned long)mchk_header + mchk_header->sys_offset);
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
/* TODO - catagorize errors, for now, no error */
#ifdef CONFIG_VERBOSE_MCHECK
if (!print)
return status;
/* TODO - decode instead of just dumping... */
printk("%s Summary Flags: %016lx\n"
" CChip DIRx: %016lx\n"
" System Management IR: %016lx\n"
" CPU IR: %016lx\n"
" Power Supply IR: %016lx\n"
" LM78 Fault Status: %016lx\n"
" System Doors: %016lx\n"
" Temperature Warning: %016lx\n"
" Fan Control: %016lx\n"
" Fatal Power Down Code: %016lx\n",
err_print_prefix,
emchk->summary,
emchk->c_dirx,
emchk->smir,
emchk->cpuir,
emchk->psir,
emchk->fault,
emchk->sys_doors,
emchk->temp_warn,
emchk->fan_ctrl,
emchk->code);
#endif /* CONFIG_VERBOSE_MCHECK */
return status;
}
int
privateer_process_logout_frame(struct el_common *mchk_header, int print)
{
struct el_common_EV6_mcheck *ev6mchk =
(struct el_common_EV6_mcheck *)mchk_header;
int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
/*
* Machine check codes
*/
#define PRIVATEER_MCHK__CORR_ECC 0x86 /* 630 */
#define PRIVATEER_MCHK__DC_TAG_PERR 0x9E /* 630 */
#define PRIVATEER_MCHK__PAL_BUGCHECK 0x8E /* 670 */
#define PRIVATEER_MCHK__OS_BUGCHECK 0x90 /* 670 */
#define PRIVATEER_MCHK__PROC_HRD_ERR 0x98 /* 670 */
#define PRIVATEER_MCHK__ISTREAM_CMOV_PRX 0xA0 /* 670 */
#define PRIVATEER_MCHK__ISTREAM_CMOV_FLT 0xA2 /* 670 */
#define PRIVATEER_MCHK__SYS_HRD_ERR 0x202 /* 660 */
#define PRIVATEER_MCHK__SYS_CORR_ERR 0x204 /* 620 */
#define PRIVATEER_MCHK__SYS_ENVIRON 0x206 /* 680 */
switch(ev6mchk->MCHK_Code) {
/*
* Vector 630 - Processor, Correctable
*/
case PRIVATEER_MCHK__CORR_ECC:
case PRIVATEER_MCHK__DC_TAG_PERR:
/*
* Fall through to vector 670 for processing...
*/
/*
* Vector 670 - Processor, Uncorrectable
*/
case PRIVATEER_MCHK__PAL_BUGCHECK:
case PRIVATEER_MCHK__OS_BUGCHECK:
case PRIVATEER_MCHK__PROC_HRD_ERR:
case PRIVATEER_MCHK__ISTREAM_CMOV_PRX:
case PRIVATEER_MCHK__ISTREAM_CMOV_FLT:
status |= ev6_process_logout_frame(mchk_header, print);
break;
/*
* Vector 620 - System, Correctable
*/
case PRIVATEER_MCHK__SYS_CORR_ERR:
/*
* Fall through to vector 660 for processing...
*/
/*
* Vector 660 - System, Uncorrectable
*/
case PRIVATEER_MCHK__SYS_HRD_ERR:
status |= titan_process_logout_frame(mchk_header, print);
break;
/*
* Vector 680 - System, Environmental
*/
case PRIVATEER_MCHK__SYS_ENVIRON: /* System, Environmental */
status |= privateer_process_680_frame(mchk_header, print);
break;
/*
* Unknown
*/
default:
status |= MCHK_DISPOSITION_REPORT;
if (print) {
printk("%s** Unknown Error, frame follows\n",
err_print_prefix);
mchk_dump_logout_frame(mchk_header);
}
}
return status;
}
void
privateer_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
struct el_TITAN_sysdata_mcheck *tmchk =
(struct el_TITAN_sysdata_mcheck *)
(la_ptr + mchk_header->sys_offset);
u64 irqmask;
char *saved_err_prefix = err_print_prefix;
#define PRIVATEER_680_INTERRUPT_MASK (0xE00UL)
#define PRIVATEER_HOTPLUG_INTERRUPT_MASK (0xE00UL)
/*
* Sync the processor
*/
mb();
draina();
/*
* Only handle system events here
*/
if (vector != SCB_Q_SYSEVENT)
return titan_machine_check(vector, la_ptr, regs);
/*
* Report the event - System Events should be reported even if no
* error is indicated since the event could indicate the return
* to normal status.
*/
err_print_prefix = KERN_CRIT;
printk("%s*System Event (Vector 0x%x) reported on CPU %d:\n",
err_print_prefix,
(unsigned int)vector, (int)smp_processor_id());
privateer_process_680_frame(mchk_header, 1);
err_print_prefix = saved_err_prefix;
/*
* Convert any pending interrupts which report as 680 machine
* checks to interrupts
*/
irqmask = tmchk->c_dirx & PRIVATEER_680_INTERRUPT_MASK;
/*
* Dispatch the interrupt(s)
*/
titan_dispatch_irqs(irqmask, regs);
/*
* Release the logout frame
*/
wrmces(0x7);
mb();
}
#endif /* CONFIG_ALPHA_GENERIC || CONFIG_ALPHA_TITAN */
......@@ -213,7 +213,7 @@ setup_irq(unsigned int irq, struct irqaction * new)
static struct proc_dir_entry * root_irq_dir;
static struct proc_dir_entry * irq_dir[NR_IRQS];
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
static struct proc_dir_entry * smp_affinity_entry[NR_IRQS];
static char irq_user_affinity[NR_IRQS];
static unsigned long irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
......@@ -361,7 +361,7 @@ register_irq_proc (unsigned int irq)
/* create /proc/irq/1234 */
irq_dir[irq] = proc_mkdir(name, root_irq_dir);
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
/* create /proc/irq/1234/smp_affinity */
entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
......@@ -387,7 +387,7 @@ init_irq_proc (void)
/* create /proc/irq */
root_irq_dir = proc_mkdir("irq", 0);
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
/* create /proc/irq/prof_cpu_mask */
entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
......
......@@ -174,6 +174,7 @@ WEAK(sable_gamma_mv);
WEAK(shark_mv);
WEAK(sx164_mv);
WEAK(takara_mv);
WEAK(titan_mv);
WEAK(webbrick_mv);
WEAK(wildfire_mv);
WEAK(xl_mv);
......@@ -720,9 +721,9 @@ static char rawhide_names[][16] = {
static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
static char titan_names[][16] = {
"0", "Privateer"
"DEFAULT", "Privateer", "Falcon", "Granite"
};
static int titan_indices[] = {0,1};
static int titan_indices[] = {0,1,2,2,3};
static char tsunami_names[][16] = {
"0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
......@@ -814,8 +815,10 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
static struct alpha_machine_vector *titan_vecs[] __initdata =
{
NULL,
&titan_mv, /* default */
&privateer_mv, /* privateer */
&titan_mv, /* falcon */
&privateer_mv, /* granite */
};
static struct alpha_machine_vector *tsunami_vecs[] __initdata =
......@@ -881,6 +884,7 @@ get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
vec = eb66_vecs[eb66_indices[member]];
break;
case ST_DEC_TITAN:
vec = titan_vecs[0]; /* default */
if (member < N(titan_indices))
vec = titan_vecs[titan_indices[member]];
break;
......@@ -1024,6 +1028,7 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
*variation_name = rawhide_names[rawhide_indices[member]];
break;
case ST_DEC_TITAN:
*variation_name = titan_names[0]; /* default */
if (member < N(titan_indices))
*variation_name = titan_names[titan_indices[member]];
break;
......
......@@ -8,6 +8,8 @@
*
* Code supporting TITAN systems (EV6+TITAN), currently:
* Privateer
* Falcon
* Granite
*/
#include <linux/config.h>
......@@ -34,12 +36,26 @@
#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
#include "err_impl.h"
/* Note mask bit is true for ENABLED irqs. */
static unsigned long cached_irq_mask;
/* Titan boards handle at most four CPUs. */
static unsigned long cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
/*
* Titan generic
*/
/*
* Titan supports up to 4 CPUs
*/
static unsigned long titan_cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
/*
* Mask is set (1) if enabled
*/
static unsigned long titan_cached_irq_mask;
/*
* Need SMP-safe access to interrupt CSRs
*/
spinlock_t titan_irq_lock = SPIN_LOCK_UNLOCKED;
static void
......@@ -55,10 +71,10 @@ titan_update_irq_hw(unsigned long mask)
unsigned long mask0, mask1, mask2, mask3, dummy;
mask &= ~isa_enable;
mask0 = mask & cpu_irq_affinity[0];
mask1 = mask & cpu_irq_affinity[1];
mask2 = mask & cpu_irq_affinity[2];
mask3 = mask & cpu_irq_affinity[3];
mask0 = mask & titan_cpu_irq_affinity[0];
mask1 = mask & titan_cpu_irq_affinity[1];
mask2 = mask & titan_cpu_irq_affinity[2];
mask3 = mask & titan_cpu_irq_affinity[3];
if (bcpu == 0) mask0 |= isa_enable;
else if (bcpu == 1) mask1 |= isa_enable;
......@@ -97,79 +113,68 @@ titan_update_irq_hw(unsigned long mask)
}
static inline void
privateer_enable_irq(unsigned int irq)
titan_enable_irq(unsigned int irq)
{
spin_lock(&titan_irq_lock);
cached_irq_mask |= 1UL << (irq - 16);
titan_update_irq_hw(cached_irq_mask);
titan_cached_irq_mask |= 1UL << (irq - 16);
titan_update_irq_hw(titan_cached_irq_mask);
spin_unlock(&titan_irq_lock);
}
static inline void
privateer_disable_irq(unsigned int irq)
titan_disable_irq(unsigned int irq)
{
spin_lock(&titan_irq_lock);
cached_irq_mask &= ~(1UL << (irq - 16));
titan_update_irq_hw(cached_irq_mask);
titan_cached_irq_mask &= ~(1UL << (irq - 16));
titan_update_irq_hw(titan_cached_irq_mask);
spin_unlock(&titan_irq_lock);
}
static unsigned int
privateer_startup_irq(unsigned int irq)
titan_startup_irq(unsigned int irq)
{
privateer_enable_irq(irq);
titan_enable_irq(irq);
return 0; /* never anything pending */
}
static void
privateer_end_irq(unsigned int irq)
titan_end_irq(unsigned int irq)
{
if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
privateer_enable_irq(irq);
titan_enable_irq(irq);
}
static void
cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
{
int cpu;
for (cpu = 0; cpu < 4; cpu++) {
if (affinity & (1UL << cpu))
cpu_irq_affinity[cpu] |= 1UL << irq;
titan_cpu_irq_affinity[cpu] |= 1UL << irq;
else
cpu_irq_affinity[cpu] &= ~(1UL << irq);
titan_cpu_irq_affinity[cpu] &= ~(1UL << irq);
}
}
static void
privateer_set_affinity(unsigned int irq, unsigned long affinity)
titan_set_irq_affinity(unsigned int irq, unsigned long affinity)
{
spin_lock(&titan_irq_lock);
cpu_set_irq_affinity(irq - 16, affinity);
titan_update_irq_hw(cached_irq_mask);
titan_cpu_set_irq_affinity(irq - 16, affinity);
titan_update_irq_hw(titan_cached_irq_mask);
spin_unlock(&titan_irq_lock);
}
static struct hw_interrupt_type privateer_irq_type = {
.typename = "PRIVATEER",
.startup = privateer_startup_irq,
.shutdown = privateer_disable_irq,
.enable = privateer_enable_irq,
.disable = privateer_disable_irq,
.ack = privateer_disable_irq,
.end = privateer_end_irq,
.set_affinity = privateer_set_affinity,
};
static void
privateer_device_interrupt(unsigned long vector, struct pt_regs * regs)
titan_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
printk("privateer_device_interrupt: NOT IMPLEMENTED YET!! \n");
printk("titan_device_interrupt: NOT IMPLEMENTED YET!! \n");
}
static void
privateer_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
titan_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
int irq;
......@@ -188,181 +193,213 @@ init_titan_irqs(struct hw_interrupt_type * ops, int imin, int imax)
}
}
static struct hw_interrupt_type titan_irq_type = {
.typename = "TITAN",
.startup = titan_startup_irq,
.shutdown = titan_disable_irq,
.enable = titan_enable_irq,
.disable = titan_disable_irq,
.ack = titan_disable_irq,
.end = titan_end_irq,
.set_affinity = titan_set_irq_affinity,
};
static void
titan_intr_nop(int irq, void *dev_id, struct pt_regs *regs)
{
/*
* This is a NOP interrupt handler for the purposes of
* event counting -- just return.
*/
}
static void __init
privateer_init_irq(void)
titan_init_irq(void)
{
if (alpha_using_srm && !alpha_mv.device_interrupt)
alpha_mv.device_interrupt = titan_srm_device_interrupt;
if (!alpha_mv.device_interrupt)
alpha_mv.device_interrupt = titan_device_interrupt;
titan_update_irq_hw(0);
init_titan_irqs(&titan_irq_type, 16, 63 + 16);
}
static void __init
titan_legacy_init_irq(void)
{
/* init the legacy dma controller */
outb(0, DMA1_RESET_REG);
outb(0, DMA2_RESET_REG);
outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
outb(0, DMA2_MASK_REG);
if (alpha_using_srm)
alpha_mv.device_interrupt = privateer_srm_device_interrupt;
titan_update_irq_hw(0UL);
/* init the legacy irq controller */
init_i8259a_irqs();
init_titan_irqs(&privateer_irq_type, 16, 63 + 16);
/* init the titan irqs */
titan_init_irq();
}
void
titan_dispatch_irqs(u64 mask, struct pt_regs *regs)
{
unsigned long vector;
/*
* Mask down to those interrupts which are enable on this processor
*/
mask &= titan_cpu_irq_affinity[smp_processor_id()];
/*
* Dispatch all requested interrupts
*/
while(mask) {
/* convert to SRM vector... priority is <63> -> <0> */
__asm__("ctlz %1, %0" : "=r"(vector) : "r"(mask));
vector = 63 - vector;
mask &= ~(1UL << vector); /* clear it out */
vector = 0x900 + (vector << 4); /* convert to SRM vector */
/* dispatch it */
alpha_mv.device_interrupt(vector, regs);
}
}
/*
* Privateer PCI Fixup configuration.
*
* PCHIP 0 BUS 0 (Hose 0)
*
* IDSEL Dev What
* ----- --- ----
* 18 7 Embedded Southbridge
* 19 8 Slot 0
* 20 9 Slot 1
* 21 10 Slot 2
* 22 11 Slot 3
* 23 12 Embedded HotPlug controller
* 27 16 Embedded Southbridge IDE
* 29 18 Embedded Southbridge PMU
* 31 20 Embedded Southbridge USB
*
* PCHIP 1 BUS 0 (Hose 1)
*
* IDSEL Dev What
* ----- --- ----
* 12 1 Slot 0
* 13 2 Slot 1
* 17 6 Embedded hotPlug controller
*
* PCHIP 0 BUS 1 (Hose 2)
*
* IDSEL What
* ----- ----
* NONE AGP
*
* PCHIP 1 BUS 1 (Hose 3)
*
* IDSEL Dev What
* ----- --- ----
* 12 1 Slot 0
* 13 2 Slot 1
* 17 6 Embedded hotPlug controller
*
* Summary @ TITAN_CSR_DIM0:
* Bit Meaning
* 0-7 Unused
* 8 PCHIP 0 BUS 1 YUKON (if present)
* 9 PCHIP 1 BUS 1 YUKON
* 10 PCHIP 1 BUS 0 YUKON
* 11 PCHIP 0 BUS 0 YUKON
* 12 PCHIP 0 BUS 0 SLOT 2 INT A
* 13 PCHIP 0 BUS 0 SLOT 2 INT B
* 14 PCHIP 0 BUS 0 SLOT 2 INT C
* 15 PCHIP 0 BUS 0 SLOT 2 INT D
* 16 PCHIP 0 BUS 0 SLOT 3 INT A
* 17 PCHIP 0 BUS 0 SLOT 3 INT B
* 18 PCHIP 0 BUS 0 SLOT 3 INT C
* 19 PCHIP 0 BUS 0 SLOT 3 INT D
* 20 PCHIP 0 BUS 0 SLOT 0 INT A
* 21 PCHIP 0 BUS 0 SLOT 0 INT B
* 22 PCHIP 0 BUS 0 SLOT 0 INT C
* 23 PCHIP 0 BUS 0 SLOT 0 INT D
* 24 PCHIP 0 BUS 0 SLOT 1 INT A
* 25 PCHIP 0 BUS 0 SLOT 1 INT B
* 26 PCHIP 0 BUS 0 SLOT 1 INT C
* 27 PCHIP 0 BUS 0 SLOT 1 INT D
* 28 PCHIP 1 BUS 0 SLOT 0 INT A
* 29 PCHIP 1 BUS 0 SLOT 0 INT B
* 30 PCHIP 1 BUS 0 SLOT 0 INT C
* 31 PCHIP 1 BUS 0 SLOT 0 INT D
* 32 PCHIP 1 BUS 0 SLOT 1 INT A
* 33 PCHIP 1 BUS 0 SLOT 1 INT B
* 34 PCHIP 1 BUS 0 SLOT 1 INT C
* 35 PCHIP 1 BUS 0 SLOT 1 INT D
* 36 PCHIP 1 BUS 1 SLOT 0 INT A
* 37 PCHIP 1 BUS 1 SLOT 0 INT B
* 38 PCHIP 1 BUS 1 SLOT 0 INT C
* 39 PCHIP 1 BUS 1 SLOT 0 INT D
* 40 PCHIP 1 BUS 1 SLOT 1 INT A
* 41 PCHIP 1 BUS 1 SLOT 1 INT B
* 42 PCHIP 1 BUS 1 SLOT 1 INT C
* 43 PCHIP 1 BUS 1 SLOT 1 INT D
* 44 AGP INT A
* 45 AGP INT B
* 46-47 Unused
* 49 Reserved for Sleep mode
* 50 Temperature Warning (optional)
* 51 Power Warning (optional)
* 52 Reserved
* 53 South Bridge NMI
* 54 South Bridge SMI INT
* 55 South Bridge ISA Interrupt
* 56-58 Unused
* 59 PCHIP1_C_ERROR
* 60 PCHIP0_C_ERROR
* 61 PCHIP1_H_ERROR
* 62 PCHIP0_H_ERROR
* 63 Reserved
*
* Titan Family
*/
static int __init
privateer_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
static void __init
titan_late_init(void)
{
u8 irq;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
/*
* Enable the system error interrupts. These interrupts are
* all reported to the kernel as machine checks, so the handler
* is a nop so it can be called to count the individual events.
*/
request_irq(63+16, titan_intr_nop, SA_INTERRUPT,
"CChip Error", NULL);
request_irq(62+16, titan_intr_nop, SA_INTERRUPT,
"PChip 0 H_Error", NULL);
request_irq(61+16, titan_intr_nop, SA_INTERRUPT,
"PChip 1 H_Error", NULL);
request_irq(60+16, titan_intr_nop, SA_INTERRUPT,
"PChip 0 C_Error", NULL);
request_irq(59+16, titan_intr_nop, SA_INTERRUPT,
"PChip 1 C_Error", NULL);
/*
* Register our error handlers
*/
titan_register_error_handlers();
/*
* Check if the console left us any error logs
*/
cdl_check_console_data_log();
/* is it routed through ISA? */
if ((irq & 0xF0) == 0xE0)
return (int)irq;
return (int)irq + 16; /* HACK -- this better only be called once */
}
#ifdef CONFIG_VGA_HOSE
static struct pci_controller * __init
privateer_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
static int __devinit
titan_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
struct pci_controller *hose = h1;
int agp1, agp2;
/* which hose(s) are agp? */
agp1 = (0 != (TITAN_agp & (1 << h1->index)));
agp2 = (0 != (TITAN_agp & (1 << h2->index)));
hose = h1; /* default to h1 */
if (agp1 ^ agp2) {
if (agp2) hose = h2; /* take agp if only one */
} else if (h2->index < h1->index)
hose = h2; /* first hose if 2xpci or 2xagp */
return hose;
u8 intline;
int irq;
/* get the current intline */
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
irq = intline;
/* is it explicitly routed through ISA? */
if ((irq & 0xF0) == 0xE0)
return irq;
/* offset by 16 to make room for ISA interrupts 0 - 15 */
return irq + 16;
}
#endif
static void __init
privateer_init_pci(void)
titan_init_pci(void)
{
extern int pci_probe_only;
/*
* This isn't really the right place, but there's some init
* that needs to be done after everything is basically up.
*/
titan_late_init();
pci_probe_only = 1;
common_init_pci();
SMC669_Init(0);
#ifdef CONFIG_VGA_HOSE
locate_and_init_vga(privateer_vga_hose_select);
locate_and_init_vga(NULL);
#endif
}
void
privateer_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
/*
* Privateer
*/
static void __init
privateer_init_pci(void)
{
/* only handle system events here */
if (vector != SCB_Q_SYSEVENT)
return titan_machine_check(vector, la_ptr, regs);
/* it's a system event, handle it here */
printk("PRIVATEER 680 Machine Check on CPU %d\n", smp_processor_id());
/*
* Hook a couple of extra err interrupts that the
* common titan code won't
*/
request_irq(53+16, titan_intr_nop, SA_INTERRUPT,
"NMI", NULL);
request_irq(50+16, titan_intr_nop, SA_INTERRUPT,
"Temperature Warning", NULL);
/*
* Finish with the common version
*/
return titan_init_pci();
}
/*
* The System Vectors
*/
#if defined(CONFIG_ALPHA_CORE_AGP)
extern void *titan_agp_info(void);
#endif
struct alpha_machine_vector titan_mv __initmv = {
.vector_name = "TITAN",
DO_EV6_MMU,
DO_DEFAULT_RTC,
DO_TITAN_IO,
DO_TITAN_BUS,
.machine_check = titan_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 = TITAN_DAC_OFFSET,
.nr_irqs = 80, /* 64 + 16 */
/* device_interrupt will be filled in by titan_init_irq */
#if defined(CONFIG_ALPHA_CORE_AGP)
.agp_info = titan_agp_info,
#endif
.init_arch = titan_init_arch,
.init_irq = titan_legacy_init_irq,
.init_rtc = common_init_rtc,
.init_pci = titan_init_pci,
.kill_arch = titan_kill_arch,
.pci_map_irq = titan_map_irq,
.pci_swizzle = common_swizzle,
};
ALIAS_MV(titan)
struct alpha_machine_vector privateer_mv __initmv = {
.vector_name = "PRIVATEER",
DO_EV6_MMU,
......@@ -376,14 +413,21 @@ struct alpha_machine_vector privateer_mv __initmv = {
.pci_dac_offset = TITAN_DAC_OFFSET,
.nr_irqs = 80, /* 64 + 16 */
.device_interrupt = privateer_device_interrupt,
/* device_interrupt will be filled in by titan_init_irq */
#if defined(CONFIG_ALPHA_CORE_AGP)
.agp_info = titan_agp_info,
#endif
.init_arch = titan_init_arch,
.init_irq = privateer_init_irq,
.init_irq = titan_legacy_init_irq,
.init_rtc = common_init_rtc,
.init_pci = privateer_init_pci,
.kill_arch = titan_kill_arch,
.pci_map_irq = privateer_map_irq,
.pci_map_irq = titan_map_irq,
.pci_swizzle = common_swizzle,
};
ALIAS_MV(privateer)
/* No alpha_mv alias for privateer since we compile it
in unconditionally with titan; setup_arch knows how to cope. */
......@@ -2,6 +2,7 @@
#define __ALPHA_TITAN__H__
#include <linux/types.h>
#include <linux/pci.h>
#include <asm/compiler.h>
/*
......@@ -293,13 +294,15 @@ union TPAchipAGPERR {
* 2 - pachip 0 / A Port
* 3 - pachip 1 / A Port
*/
#define TITAN_HOSE(h) (((unsigned long)(h)) << 33)
#define TITAN_HOSE_SHIFT (33)
#define TITAN_HOSE(h) (((unsigned long)(h)) << TITAN_HOSE_SHIFT)
#define TITAN_BASE (IDENT_ADDR + TI_BIAS)
#define TITAN_MEM(h) (TITAN_BASE+TITAN_HOSE(h)+0x000000000UL)
#define _TITAN_IACK_SC(h) (TITAN_BASE+TITAN_HOSE(h)+0x1F8000000UL)
#define TITAN_IO(h) (TITAN_BASE+TITAN_HOSE(h)+0x1FC000000UL)
#define TITAN_CONF(h) (TITAN_BASE+TITAN_HOSE(h)+0x1FE000000UL)
#define TITAN_HOSE_MASK TITAN_HOSE(3)
#define TITAN_IACK_SC _TITAN_IACK_SC(0) /* hack! */
/*
......@@ -427,17 +430,8 @@ __EXTERN_INLINE void titan_outl(u32 b, unsigned long addr)
* Memory functions. all accesses are done through linear space.
*/
__EXTERN_INLINE unsigned long titan_ioremap(unsigned long addr,
unsigned long size
__attribute__((unused)))
{
return addr + TITAN_MEM_BIAS;
}
__EXTERN_INLINE void titan_iounmap(unsigned long addr)
{
return;
}
extern unsigned long titan_ioremap(unsigned long addr, unsigned long size);
extern void titan_iounmap(unsigned long addr);
__EXTERN_INLINE int titan_is_ioaddr(unsigned long addr)
{
......@@ -505,8 +499,8 @@ __EXTERN_INLINE void titan_writeq(u64 b, unsigned long addr)
#define __writew(x,a) titan_writew((x),(unsigned long)(a))
#define __writel(x,a) titan_writel((x),(unsigned long)(a))
#define __writeq(x,a) titan_writeq((x),(unsigned long)(a))
#define __ioremap(a,s) titan_ioremap((unsigned long)(a),(s))
#define __iounmap(a) titan_iounmap((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) titan_is_ioaddr((unsigned long)(a))
#define inb(port) __inb((port))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment