Commit dae98c27 authored by Matt Domsch's avatar Matt Domsch

Merge dell.com:/home/mdomsch/bk/linux-2.5

into dell.com:/home/mdomsch/bk/edd/linux-2.5-edd
parents b93c47a6 6a3354a9
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 58
SUBLEVEL = 59
EXTRAVERSION =
# *DOCUMENTATION*
......
......@@ -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
......@@ -75,7 +76,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".
......@@ -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
......@@ -238,6 +244,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"
......@@ -301,6 +309,11 @@ config PCI
information about which PCI hardware does work under Linux and which
doesn't.
config ALPHA_CORE_AGP
bool
depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
default y
config ALPHA_NONAME
bool
depends on ALPHA_BOOK1 || ALPHA_NONAME_CH
......@@ -387,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
......@@ -397,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
......@@ -419,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
......@@ -461,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
......
......@@ -6,7 +6,7 @@ EXTRA_TARGETS := head.o
EXTRA_AFLAGS := $(CFLAGS)
export-objs := alpha_ksyms.o
export-objs := alpha_ksyms.o core_marvel.o core_titan.o
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
......@@ -21,18 +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 += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
else
......@@ -41,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
......@@ -62,11 +64,13 @@ 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
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
......
/*
* linux/arch/alpha/kernel/core_marvel.c
*
* Code common to all Marvel based systems.
*/
#include <linux/config.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
#include <asm/core_marvel.h>
#undef __EXTERN_INLINE
#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 <linux/module.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>
#include <linux/bootmem.h>
#include "proto.h"
#include "pci_impl.h"
/*
* Debug helpers
*/
#define DEBUG_CONFIG 0
#if DEBUG_CONFIG
# define DBG_CFG(args) printk args
#else
# define DBG_CFG(args)
#endif
/*
* Private data
*/
static struct io7 *io7_head = NULL;
/*
* Helper functions
*/
static unsigned long __attribute__ ((unused))
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;
}
inline struct io7 *
marvel_next_io7(struct io7 *prev)
{
return (prev ? prev->next : io7_head);
}
struct io7 *
marvel_find_io7(int pe)
{
struct io7 *io7;
for (io7 = io7_head; io7 && io7->pe != pe; io7 = io7->next)
continue;
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 = -1UL;
csrs->POx_TLB_ERR.csr = -1UL;
csrs->POx_SPL_COMPLT.csr = -1UL;
csrs->POx_TRANS_SUM.csr = -1UL;
}
/*
* Then the common ones.
*/
p7csrs = IO7_PORT7_CSRS_KERN(io7->pe);
p7csrs->PO7_ERROR_SUM.csr = -1UL;
p7csrs->PO7_UNCRR_SYM.csr = -1UL;
p7csrs->PO7_CRRCT_SYM.csr = -1UL;
}
/*
* 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)
{
}
/*
* 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,
};
/*
* 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;
}
/*
* IO map support.
*/
unsigned long
marvel_ioremap(unsigned long addr, unsigned long size)
{
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));
}
#ifndef CONFIG_ALPHA_GENERIC
EXPORT_SYMBOL(marvel_ioremap);
EXPORT_SYMBOL(marvel_iounmap);
#endif
/*
* 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);
return (pu64[7] == 2);
}
/*
* 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;
}
/*
* 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 */
}
/*
* 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 = 0 /* FIXME: 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;
}
......@@ -5,15 +5,20 @@
*/
#include <linux/config.h>
#include <linux/module.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 <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 +30,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 +52,31 @@ struct
# define DBG_CFG(args)
#endif
/*
* Routines to access TIG registers.
*/
static inline volatile unsigned long *
mk_tig_addr(int offset)
{
return (volatile unsigned long *)(TITAN_TIG_SPACE + (offset << 6));
}
static inline u8
titan_read_tig(int offset, u8 value)
{
volatile unsigned long *tig_addr = mk_tig_addr(offset);
return (u8)(*tig_addr & 0xff);
}
static inline 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
......@@ -179,13 +207,16 @@ titan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
volatile unsigned long *csr;
unsigned long value;
/* Get the right hose */
/* Get the right hose. */
port = &pachip->g_port;
if (hose->index & 2)
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 +231,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,36 +242,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 +254,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 +286,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.
......@@ -310,39 +309,41 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
/*
* Set up the PCI to main memory translation windows.
*
* Note: Window 3 on Titan is Scatter-Gather ONLY
* 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. */
/* 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 +361,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 +414,15 @@ titan_init_arch(void)
ioport_resource.end = ~0UL;
iomem_resource.end = ~0UL;
/* Init the PA chip(s) */
/* 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
......@@ -417,8 +451,8 @@ titan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
if (pchip1_present) {
titan_kill_one_pachip_port(&pachip0->g_port, 1);
titan_kill_one_pachip_port(&pachip0->a_port, 3);
titan_kill_one_pachip_port(&pachip1->g_port, 1);
titan_kill_one_pachip_port(&pachip1->a_port, 3);
}
titan_kill_one_pachip_port(&pachip0->g_port, 0);
titan_kill_one_pachip_port(&pachip0->a_port, 2);
......@@ -430,38 +464,336 @@ 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)
vfree((void *)(PAGE_MASK & addr));
}
if (TITAN_cchip->csc.csr & 1L<<14)
titan_pci_clr_err_1(TITAN_pachip1);
#ifndef CONFIG_ALPHA_GENERIC
EXPORT_SYMBOL(titan_ioremap);
EXPORT_SYMBOL(titan_iounmap);
#endif
/*
* AGP GART Support.
*/
#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");
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;
process_mcheck_info(vector, la_ptr, regs, "TITAN",
mcheck_expected(smp_processor_id()));
/* 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)
{
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 = 0 /* FIXME: 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;
}
......@@ -357,7 +357,6 @@ void __init
tsunami_init_arch(void)
{
#ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
extern asmlinkage void entInt(void);
unsigned long tmp;
/* Ho hum.. init_arch is called before init_IRQ, but we need to be
......
......@@ -146,3 +146,17 @@ 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
*/
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_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"
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();
el_process_subpacket(el_ptr);
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();
}
/*
* 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"
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)
{
size_t i;
for (i = 0; i < ARRAY_SIZE (el_titan_annotations); i++)
cdl_register_subpacket_annotation(&el_titan_annotations[i]);
cdl_register_subpacket_handler(&titan_subpacket_handler);
}
/*
* Privateer
*/
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();
}
/*
* linux/arch/alpha/kernel/gct.c
*/
#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;
}
......@@ -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,16 +361,18 @@ register_irq_proc (unsigned int irq)
/* create /proc/irq/1234 */
irq_dir[irq] = proc_mkdir(name, root_irq_dir);
#ifdef CONFIG_SMP
/* create /proc/irq/1234/smp_affinity */
entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
#ifdef CONFIG_SMP
if (irq_desc[irq].handler->set_affinity) {
/* create /proc/irq/1234/smp_affinity */
entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
entry->nlink = 1;
entry->data = (void *)(long)irq;
entry->read_proc = irq_affinity_read_proc;
entry->write_proc = irq_affinity_write_proc;
entry->nlink = 1;
entry->data = (void *)(long)irq;
entry->read_proc = irq_affinity_read_proc;
entry->write_proc = irq_affinity_write_proc;
smp_affinity_entry[irq] = entry;
smp_affinity_entry[irq] = entry;
}
#endif
}
......@@ -387,7 +389,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);
......@@ -398,12 +400,16 @@ init_irq_proc (void)
#endif
/*
* Create entries for all existing IRQs.
* Create entries for all existing IRQs. If the number of IRQs
* is greater the 1/4 the total dynamic inode space for /proc,
* don't pollute the inode space
*/
for (i = 0; i < NR_IRQS; i++) {
if (irq_desc[i].handler == &no_irq_type)
continue;
register_irq_proc(i);
if (ACTUAL_NR_IRQS < (PROC_NDYNAMIC / 4)) {
for (i = 0; i < ACTUAL_NR_IRQS; i++) {
if (irq_desc[i].handler == &no_irq_type)
continue;
register_irq_proc(i);
}
}
}
......@@ -518,7 +524,7 @@ show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
#endif
for (i = 0; i < NR_IRQS; i++) {
for (i = 0; i < ACTUAL_NR_IRQS; i++) {
action = irq_desc[i].action;
if (!action)
continue;
......
......@@ -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.
*/
......@@ -63,6 +64,13 @@
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)
......@@ -109,6 +118,7 @@
#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)
......@@ -116,7 +126,6 @@
#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,
......
......@@ -825,7 +825,7 @@ extern struct timezone sys_tz;
extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
extern int do_getitimer(int which, struct itimerval *value);
extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
asmlinkage int sys_utimes(char *, struct timeval *);
extern asmlinkage int sys_utimes(char *, struct timeval *);
extern int do_adjtimex(struct timex *);
struct timeval32
......
......@@ -42,6 +42,8 @@ const char *const pci_mem_names[] = {
const char pci_hae0_name[] = "HAE0";
/* Indicate whether we respect the PCI setup left by console. */
int __initdata pci_probe_only;
/*
* The PCI controller list.
......@@ -270,7 +272,11 @@ pcibios_fixup_bus(struct pci_bus *bus)
end = hose->mem_space->start + pci_mem_end;
if (hose->mem_space->end > end)
hose->mem_space->end = end;
}
} else if (pci_probe_only &&
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pci_read_bridge_bases(bus);
pcibios_fixup_device_resources(dev, bus);
}
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
struct pci_dev *dev = pci_dev_b(ln);
......@@ -407,6 +413,30 @@ pcibios_set_master(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
}
static void __init
pcibios_claim_console_setup(void)
{
struct list_head *lb;
for(lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) {
struct pci_bus *b = pci_bus_b(lb);
struct list_head *ld;
for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
struct pci_dev *dev = pci_dev_b(ld);
int i;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
if (r->parent || !r->start || !r->flags)
continue;
pci_claim_resource(dev, i);
}
}
}
}
void __init
common_init_pci(void)
{
......@@ -424,7 +454,12 @@ common_init_pci(void)
next_busno += 1;
}
pci_assign_unassigned_resources();
if (pci_probe_only)
pcibios_claim_console_setup();
else /* FIXME: `else' will be removed when
pci_assign_unassigned_resources() is able to work
correctly with [partially] allocated PCI tree. */
pci_assign_unassigned_resources();
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
}
......
......@@ -150,6 +150,9 @@ struct pci_iommu_arena
extern struct pci_controller *hose_head, **hose_tail;
extern struct pci_controller *pci_isa_hose;
/* Indicate that we trust the console to configure things properly. */
extern int pci_probe_only;
extern void common_init_pci(void);
extern u8 common_swizzle(struct pci_dev *, u8 *);
extern struct pci_controller *alloc_pci_controller(void);
......
#include <linux/config.h>
/* Prototypes of functions used across modules here in this directory. */
#define vucp volatile unsigned char *
......@@ -41,6 +43,22 @@ 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);
extern struct _alpha_agp_info *marvel_agp_info(void);
struct io7 *marvel_find_io7(int pe);
struct io7 *marvel_next_io7(struct io7 *prev);
void io7_clear_errors(struct io7 *io7);
/* core_mcpcia.c */
extern struct pci_ops mcpcia_pci_ops;
extern void mcpcia_init_arch(void);
......@@ -68,6 +86,7 @@ extern void titan_init_arch(void);
extern void titan_kill_arch(int);
extern void titan_machine_check(u64, u64, struct pt_regs *);
extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct _alpha_agp_info *titan_agp_info(void);
/* core_tsunami.c */
extern struct pci_ops tsunami_pci_ops;
......@@ -149,10 +168,17 @@ extern int ptrace_cancel_bpt (struct task_struct *child);
extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15);
extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);
/* sys_titan.c */
extern void titan_dispatch_irqs(u64, struct pt_regs *);
/* ../mm/init.c */
extern void switch_to_system_map(void);
extern void srm_paging_stop(void);
/* ../mm/remap.c */
extern int __alpha_remap_area_pages(unsigned long, unsigned long,
unsigned long, unsigned long);
/* irq.c */
#ifdef CONFIG_SMP
......
......@@ -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);
......@@ -174,6 +175,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);
......@@ -288,7 +290,7 @@ setup_memory(void *kernel_end)
(hwrpb->mddt_offset + (unsigned long) hwrpb);
for_each_mem_cluster(memdesc, cluster, i) {
printk("memcluster %d, usage %01lx, start %8lu, end %8lu\n",
printk("memcluster %lu, usage %01lx, start %8lu, end %8lu\n",
i, cluster->usage, cluster->start_pfn,
cluster->start_pfn + cluster->numpages);
......@@ -695,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"};
......@@ -714,15 +716,20 @@ 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"
};
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",
......@@ -775,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 =
......@@ -812,10 +820,17 @@ 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 =
{
NULL,
&titan_mv, /* default */
&privateer_mv, /* privateer */
&titan_mv, /* falcon */
&privateer_mv, /* granite */
};
static struct alpha_machine_vector *tsunami_vecs[] __initdata =
......@@ -880,7 +895,12 @@ 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))
vec = titan_vecs[titan_indices[member]];
break;
......@@ -1019,11 +1039,16 @@ 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]];
break;
case ST_DEC_TITAN:
*variation_name = titan_names[0]; /* default */
if (member < N(titan_indices))
*variation_name = titan_names[titan_indices[member]];
break;
......
......@@ -83,7 +83,6 @@ cycles_t cacheflush_time;
unsigned long cache_decay_ticks;
extern void calibrate_delay(void);
extern asmlinkage void entInt(void);
......@@ -151,6 +150,9 @@ smp_callin(void)
/* Get our local ticker going. */
smp_setup_percpu_timer(cpuid);
/* Call platform-specific callin, if specified */
if (alpha_mv.smp_callin) alpha_mv.smp_callin();
/* All kernel threads share the same mm context. */
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
......
/*
* linux/arch/alpha/kernel/sys_marvel.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"
#if NR_IRQS < MARVEL_NR_IRQS
# error NR_IRQS < MARVEL_NR_IRQS !!!
#endif
/*
* Interrupt handling.
*/
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 &= MARVEL_IRQ_VEC_IRQ_MASK; /* not too many bits */
irq |= pid << MARVEL_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 >> MARVEL_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 &= MARVEL_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 << MARVEL_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 << MARVEL_IRQ_VEC_PE_SHIFT),
(irq + 16) | (io7->pe << MARVEL_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 << MARVEL_IRQ_VEC_PE_SHIFT; /* merge the pid */
return irq;
}
static void __init
marvel_init_pci(void)
{
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)
return;
/*
* 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);
}
/*
* System Vectors
*/
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,
.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)
......@@ -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;
......@@ -182,186 +187,209 @@ static void __init
init_titan_irqs(struct hw_interrupt_type * ops, int imin, int imax)
{
long i;
for(i = imin; i <= imax; ++i) {
for (i = imin; i <= imax; ++i) {
irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
irq_desc[i].handler = ops;
}
}
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
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
privateer_init_irq(void)
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)
{
/*
* 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
* The System Vectors.
*/
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 */
.agp_info = titan_agp_info,
.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",
......@@ -376,14 +404,18 @@ 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 */
.agp_info = titan_agp_info,
.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. */
......@@ -118,7 +118,7 @@ dik_show_trace(unsigned long *sp)
long i = 0;
printk("Trace:");
while (0x1ff8 & (unsigned long) sp) {
extern unsigned long _stext, _etext;
extern char _stext[], _etext[];
unsigned long tmp = *sp;
sp++;
if (tmp < (unsigned long) &_stext)
......
......@@ -2,6 +2,6 @@
# Makefile for the linux alpha-specific parts of the memory manager.
#
obj-y := init.o fault.o extable.o
obj-y := init.o fault.o extable.o remap.o
obj-$(CONFIG_DISCONTIGMEM) += numa.o
#include <linux/vmalloc.h>
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
/* called with the page_table_lock held */
static inline void
remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
unsigned long phys_addr, unsigned long flags)
{
unsigned long end;
unsigned long pfn;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
if (address >= end)
BUG();
pfn = phys_addr >> PAGE_SHIFT;
do {
if (!pte_none(*pte)) {
printk("remap_area_pte: page already exists\n");
BUG();
}
set_pte(pte, pfn_pte(pfn,
__pgprot(_PAGE_VALID | _PAGE_ASM |
_PAGE_KRE | _PAGE_KWE | flags)));
address += PAGE_SIZE;
pfn++;
pte++;
} while (address && (address < end));
}
/* called with the page_table_lock held */
static inline int
remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
unsigned long phys_addr, unsigned long flags)
{
unsigned long end;
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
phys_addr -= address;
if (address >= end)
BUG();
do {
pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
if (!pte)
return -ENOMEM;
remap_area_pte(pte, address, end - address,
address + phys_addr, flags);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
return 0;
}
int
__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
unsigned long size, unsigned long flags)
{
pgd_t * dir;
int error = 0;
unsigned long end = address + size;
phys_addr -= address;
dir = pgd_offset(&init_mm, address);
flush_cache_all();
if (address >= end)
BUG();
spin_lock(&init_mm.page_table_lock);
do {
pmd_t *pmd;
pmd = pmd_alloc(&init_mm, dir, address);
error = -ENOMEM;
if (!pmd)
break;
if (remap_area_pmd(pmd, address, end - address,
phys_addr + address, flags))
break;
error = 0;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));
spin_unlock(&init_mm.page_table_lock);
return error;
}
......@@ -11,7 +11,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/page.h> /* for BUG() */
#include <asm/bug.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
......
......@@ -91,15 +91,16 @@ void default_idle(void)
void cpu_idle(void)
{
/* endless idle loop with no priority at all */
preempt_disable();
while (1) {
void (*idle)(void) = pm_idle;
if (!idle)
idle = default_idle;
preempt_disable();
leds_event(led_idle_start);
while (!need_resched())
idle();
leds_event(led_idle_end);
preempt_enable();
schedule();
}
}
......
......@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
# Last update: Mon Dec 23 18:49:04 2002
# Last update: Mon Jan 13 22:55:16 2003
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
......@@ -198,7 +198,7 @@ omaha ARCH_OMAHA OMAHA 186
ta7 ARCH_TA7 TA7 187
nova SA1100_NOVA NOVA 188
hmk ARCH_HMK HMK 189
inphinity ARCH_INPHINITY INPHINITY 190
karo ARCH_KARO KARO 190
fester SA1100_FESTER FESTER 191
gpi ARCH_GPI GPI 192
smdk2410 ARCH_SMDK2410 SMDK2410 193
......@@ -273,3 +273,11 @@ prpmc1100 ARCH_PRPMC1100 PRPMC1100 261
at91rm9200dk ARCH_AT91RM9200DK AT91RM9200DK 262
armstick ARCH_ARMSTICK ARMSTICK 263
armonie ARCH_ARMONIE ARMONIE 264
mport1 ARCH_MPORT1 MPORT1 265
s3c5410 ARCH_S3C5410 S3C5410 266
zcp320a ARCH_ZCP320A ZCP320A 267
i_box ARCH_I_BOX I_BOX 268
stlc1502 ARCH_STLC1502 STLC1502 269
siren ARCH_SIREN SIREN 270
greenlake ARCH_GREENLAKE GREENLAKE 271
argus ARCH_ARGUS ARGUS 272
......@@ -1528,7 +1528,7 @@ static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
int fd1772_init(void)
{
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
int i;
int i, err = -ENOMEM;
if (!machine_is_archimedes())
return 0;
......@@ -1536,27 +1536,25 @@ int fd1772_init(void)
for (i = 0; i < FD_MAX_UNITS; i++) {
disks[i] = alloc_disk(1);
if (!disks[i])
goto out;
goto err_disk;
}
if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
err = register_blkdev(MAJOR_NR, "fd", &floppy_fops);
if (err) {
printk("Unable to get major %d for floppy\n", MAJOR_NR);
goto out;
goto err_disk;
}
err = -EBUSY;
if (request_dma(FLOPPY_DMA, "fd1772")) {
printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
unregister_blkdev(MAJOR_NR, "fd");
goto out;
goto err_blkdev;
};
if (request_dma(FIQ_FD1772, "fd1772 end")) {
printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
unregister_blkdev(MAJOR_NR, "fd");
free_dma(FLOPPY_DMA);
goto out;
goto err_dma1;
};
enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
/* initialize variables */
SelectedDrive = -1;
......@@ -1570,6 +1568,12 @@ int fd1772_init(void)
out of some special memory... */
DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */
#endif
err = -ENOMEM;
if (!DMAbuffer)
goto err_dma2;
enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
blk_init_queue(&floppy_queue, do_fd_request, &lock);
for (i = 0; i < FD_MAX_UNITS; i++) {
unit[i].track = -1;
......@@ -1590,8 +1594,18 @@ int fd1772_init(void)
config_types();
return 0;
out:
err_dma2:
free_dma(FIQ_FD1772);
err_dma1:
free_dma(FLOPPY_DMA);
err_blkdev:
unregister_blkdev(MAJOR_NR, "fd");
err_disk:
while (i--)
put_disk(disks[i]);
return 1;
return err;
}
......@@ -376,7 +376,7 @@ config IDEDMA_ONLYDISK
config BLK_DEV_IDEDMA
bool
depends on BLK_DEV_IDE
default BLK_DEV_IDEDMA_ICS if ARM
default BLK_DEV_IDEDMA_ICS if ARCH_ACORN
default BLK_DEV_IDEDMA_PMAC if ALL_PPC && BLK_DEV_IDE_PMAC
default BLK_DEV_IDEDMA_PCI if PCI && BLK_DEV_IDEPCI
......
......@@ -18,7 +18,7 @@ ifeq ($(CONFIG_FB),y)
obj-$(CONFIG_PPC) += macmodes.o
endif
obj-$(CONFIG_FB_ACORN) += acornfb.o
obj-$(CONFIG_FB_ACORN) += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_AMIGA) += amifb.o
obj-$(CONFIG_FB_PM2) += pm2fb.o
obj-$(CONFIG_FB_PM3) += pm3fb.o
......@@ -77,7 +77,7 @@ obj-$(CONFIG_FB_I810) += i810/ cfbfillrect.o cfbcopyarea.o \
obj-$(CONFIG_FB_SUN3) += sun3fb.o
obj-$(CONFIG_FB_HGA) += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_SA1100) += sa1100fb.o
obj-$(CONFIG_FB_SA1100) += sa1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_E1355) += epson1355fb.o
......
......@@ -12,6 +12,9 @@
* NOTE: Most of the modes with X!=640 will disappear shortly.
* NOTE: Startup setting of HS & VS polarity not supported.
* (do we need to support it if we're coming up in 640x480?)
*
* FIXME: (things broken by the "new improved" FBCON API)
* - Blanking 8bpp displays with VIDC
*/
#include <linux/config.h>
......@@ -33,14 +36,6 @@
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
#include <video/fbcon-cfb2.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb32.h>
#include "acornfb.h"
/*
......@@ -58,25 +53,7 @@
*/
#define DEFAULT_XRES 640
#define DEFAULT_YRES 480
/*
* The order here defines which BPP we
* pick depending on which resolutions
* we have configured.
*/
#if defined(FBCON_HAS_CFB4)
# define DEFAULT_BPP 4
#elif defined(FBCON_HAS_CFB8)
# define DEFAULT_BPP 8
#elif defined(FBCON_HAS_CFB16)
# define DEFAULT_BPP 16
#elif defined(FBCON_HAS_CFB2)
# define DEFAULT_BPP 2
#elif defined(FBCON_HAS_MFB)
# define DEFAULT_BPP 1
#else
#error No suitable framebuffers configured
#endif
#define DEFAULT_BPP 4
/*
* define this to debug the video mode selection
......@@ -99,13 +76,10 @@ static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
{ 30000, 70000, 60, 60, 0 }
};
static struct display global_disp;
static struct fb_info fb_info;
static struct acornfb_par current_par;
static struct vidc_timing current_vidc;
static struct fb_var_screeninfo __initdata init_var = {};
extern int acornfb_depth; /* set by setup.c */
extern unsigned int vram_size; /* set by setup.c */
#ifdef HAS_VIDC
......@@ -333,34 +307,26 @@ acornfb_set_timing(struct fb_var_screeninfo *var)
#endif
}
static inline void
acornfb_palette_write(u_int regno, union palette pal)
{
vidc_writel(pal.p);
}
static inline union palette
acornfb_palette_encode(u_int regno, u_int red, u_int green, u_int blue,
u_int trans)
static int
acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
union palette pal;
if (regno >= current_par.palette_size)
return 1;
pal.p = 0;
pal.vidc.reg = regno;
pal.vidc.red = red >> 12;
pal.vidc.green = green >> 12;
pal.vidc.blue = blue >> 12;
return pal;
}
static void
acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *trans)
{
*red = EXTEND4(current_par.palette[regno].vidc.red);
*green = EXTEND4(current_par.palette[regno].vidc.green);
*blue = EXTEND4(current_par.palette[regno].vidc.blue);
*trans = current_par.palette[regno].vidc.trans ? -1 : 0;
current_par.palette[regno] = pal;
vidc_writel(pal.p);
return 0;
}
#endif
......@@ -513,34 +479,66 @@ acornfb_set_timing(struct fb_info *info, struct fb_var_screeninfo *var)
#endif
}
static inline void
acornfb_palette_write(u_int regno, union palette pal)
{
vidc_writel(0x10000000 | regno);
vidc_writel(pal.p);
}
static inline union palette
acornfb_palette_encode(u_int regno, u_int red, u_int green, u_int blue,
u_int trans)
/*
* We have to take note of the VIDC20's 16-bit palette here.
* The VIDC20 looks up a 16 bit pixel as follows:
*
* bits 111111
* 5432109876543210
* red ++++++++ (8 bits, 7 to 0)
* green ++++++++ (8 bits, 11 to 4)
* blue ++++++++ (8 bits, 15 to 8)
*
* We use a pixel which looks like:
*
* bits 111111
* 5432109876543210
* red +++++ (5 bits, 4 to 0)
* green +++++ (5 bits, 9 to 5)
* blue +++++ (5 bits, 14 to 10)
*/
static int
acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
union palette pal;
int bpp = info->var.bits_per_pixel;
if (regno >= current_par.palette_size)
return 1;
pal.p = 0;
pal.vidc20.red = red >> 8;
pal.vidc20.green = green >> 8;
pal.vidc20.blue = blue >> 8;
return pal;
}
static void
acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *trans)
{
*red = EXTEND8(current_par.palette[regno].vidc20.red);
*green = EXTEND8(current_par.palette[regno].vidc20.green);
*blue = EXTEND8(current_par.palette[regno].vidc20.blue);
*trans = EXTEND4(current_par.palette[regno].vidc20.ext);
current_par.palette[regno] = pal;
if (bpp == 32 && regno < 16) {
current_par.cmap.cfb32[regno] =
regno | regno << 8 | regno << 16;
}
if (bpp == 16 && regno < 16) {
int i;
current_par.cmap.cfb16[regno] =
regno | regno << 5 | regno << 10;
pal.p = 0;
vidc_writel(0x10000000);
for (i = 0; i < 256; i += 1) {
pal.vidc20.red = current_par.palette[ i & 31].vidc20.red;
pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
pal.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
vidc_writel(pal.p);
/* Palette register pointer auto-increments */
}
} else {
vidc_writel(0x10000000 | regno);
vidc_writel(pal.p);
}
return 0;
}
#endif
......@@ -549,12 +547,9 @@ acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
* the resolution to fit the rules.
*/
static int
acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, int con)
acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, u_int fontht)
{
u_int font_line_len;
u_int fontht;
u_int sam_size, min_size, size;
u_int nr_y;
u_int font_line_len, sam_size, min_size, size, nr_y;
/* xres must be even */
var->xres = (var->xres + 1) & ~1;
......@@ -565,17 +560,6 @@ acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, int c
var->xres_virtual = var->xres;
var->xoffset = 0;
/*
* Find the font height
*/
if (con == -1)
fontht = fontheight(&global_disp);
else
fontht = fontheight(fb_display + con);
if (fontht == 0)
fontht = 8;
if (current_par.using_vram)
sam_size = current_par.vram_half_sam * 2;
else
......@@ -693,8 +677,8 @@ acornfb_validate_timing(struct fb_var_screeninfo *var,
static inline void
acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var)
{
int off = (var->yoffset * var->xres_virtual *
var->bits_per_pixel) >> 3;
u_int off = (var->yoffset * var->xres_virtual *
var->bits_per_pixel) >> 3;
#if defined(HAS_MEMC)
memc_write(VDMA_INIT, off >> 2);
......@@ -704,130 +688,27 @@ acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var)
}
static int
acornfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *trans, struct fb_info *info)
{
if (regno >= current_par.palette_size)
return 1;
acornfb_palette_decode(regno, red, green, blue, trans);
return 0;
}
/*
* We have to take note of the VIDC20's 16-bit palette here.
* The VIDC20 looks up a 16 bit pixel as follows:
*
* bits 111111
* 5432109876543210
* red ++++++++ (8 bits, 7 to 0)
* green ++++++++ (8 bits, 11 to 4)
* blue ++++++++ (8 bits, 15 to 8)
*
* We use a pixel which looks like:
*
* bits 111111
* 5432109876543210
* red +++++ (5 bits, 4 to 0)
* green +++++ (5 bits, 9 to 5)
* blue +++++ (5 bits, 14 to 10)
*/
static int
acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
union palette pal;
int bpp = fb_display[info->currcon].var.bits_per_pixel;
if (regno >= current_par.palette_size)
return 1;
pal = acornfb_palette_encode(regno, red, green, blue, trans);
current_par.palette[regno] = pal;
#ifdef FBCON_HAS_CFB32
if (bpp == 32 && regno < 16) {
current_par.cmap.cfb32[regno] =
regno | regno << 8 | regno << 16;
}
#endif
#ifdef FBCON_HAS_CFB16
if (bpp == 16 && regno < 16) {
int i;
current_par.cmap.cfb16[regno] =
regno | regno << 5 | regno << 10;
pal.p = 0;
vidc_writel(0x10000000);
for (i = 0; i < 256; i += 1) {
pal.vidc20.red = current_par.palette[ i & 31].vidc20.red;
pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
pal.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
vidc_writel(pal.p);
/* Palette register pointer auto-increments */
}
} else
#endif
acornfb_palette_write(regno, pal);
return 0;
}
static int
acornfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
int err = 0;
if (con == info->currcon)
err = fb_get_cmap(cmap, kspc, acornfb_getcolreg, info);
else if (fb_display[con].cmap.len)
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(current_par.palette_size),
cmap, kspc ? 0 : 2);
return err;
}
static int
acornfb_decode_var(struct fb_info *info, struct fb_var_screeninfo *var, int con)
acornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
u_int fontht;
int err;
#if defined(HAS_VIDC20)
var->red.offset = 0;
var->red.length = 8;
var->green = var->red;
var->blue = var->red;
var->transp.offset = 0;
var->transp.length = 4;
#elif defined(HAS_VIDC)
var->red.length = 4;
var->green = var->red;
var->blue = var->red;
var->transp.length = 1;
#endif
/*
* FIXME: Find the font height
*/
fontht = 8;
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_MFB
case 1:
break;
#endif
#ifdef FBCON_HAS_CFB2
case 2:
break;
#endif
#ifdef FBCON_HAS_CFB4
case 4:
break;
#endif
#ifdef FBCON_HAS_CFB8
case 8:
case 1: case 2: case 4: case 8:
var->red.offset = 0;
var->red.length = var->bits_per_pixel;
var->green = var->red;
var->blue = var->red;
var->transp.offset = 0;
var->transp.length = 0;
break;
#endif
#ifdef FBCON_HAS_CFB16
#ifdef HAS_VIDC20
case 16:
var->red.offset = 0;
var->red.length = 5;
......@@ -838,8 +719,7 @@ acornfb_decode_var(struct fb_info *info, struct fb_var_screeninfo *var, int con)
var->transp.offset = 15;
var->transp.length = 1;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
var->red.offset = 0;
var->red.length = 8;
......@@ -865,7 +745,7 @@ acornfb_decode_var(struct fb_info *info, struct fb_var_screeninfo *var, int con)
* Validate and adjust the resolution to
* match the video generator hardware.
*/
err = acornfb_adjust_timing(info, var, con);
err = acornfb_adjust_timing(info, var, fontht);
if (err)
return err;
......@@ -873,137 +753,61 @@ acornfb_decode_var(struct fb_info *info, struct fb_var_screeninfo *var, int con)
* Validate the timing against the
* monitor hardware.
*/
return acornfb_validate_timing(var, &fb_info.monspecs);
return acornfb_validate_timing(var, &info->monspecs);
}
static int
acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
static int acornfb_set_par(struct fb_info *info)
{
struct display *display;
unsigned int visual, chgvar = 0;
int err;
if (con >= 0)
display = fb_display + con;
else
display = &global_disp;
err = acornfb_decode_var(info, var, con);
if (err)
return err;
switch (var->activate & FB_ACTIVATE_MASK) {
case FB_ACTIVATE_TEST:
return 0;
case FB_ACTIVATE_NXTOPEN:
case FB_ACTIVATE_NOW:
break;
default:
return -EINVAL;
}
if (con >= 0) {
if (display->var.xres != var->xres)
chgvar = 1;
if (display->var.yres != var->yres)
chgvar = 1;
if (display->var.xres_virtual != var->xres_virtual)
chgvar = 1;
if (display->var.yres_virtual != var->yres_virtual)
chgvar = 1;
if (memcmp(&display->var.red, &var->red, sizeof(var->red)))
chgvar = 1;
if (memcmp(&display->var.green, &var->green, sizeof(var->green)))
chgvar = 1;
if (memcmp(&display->var.blue, &var->blue, sizeof(var->blue)))
chgvar = 1;
}
display->var = *var;
display->var.activate &= ~FB_ACTIVATE_ALL;
if (var->activate & FB_ACTIVATE_ALL)
global_disp.var = display->var;
switch (display->var.bits_per_pixel) {
#ifdef FBCON_HAS_MFB
switch (info->var.bits_per_pixel) {
case 1:
current_par.palette_size = 2;
display->dispsw = &fbcon_mfb;
visual = FB_VISUAL_MONO10;
info->fix.visual = FB_VISUAL_MONO10;
break;
#endif
#ifdef FBCON_HAS_CFB2
case 2:
current_par.palette_size = 4;
display->dispsw = &fbcon_cfb2;
visual = FB_VISUAL_PSEUDOCOLOR;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB4
case 4:
current_par.palette_size = 16;
display->dispsw = &fbcon_cfb4;
visual = FB_VISUAL_PSEUDOCOLOR;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB8
case 8:
current_par.palette_size = VIDC_PALETTE_SIZE;
display->dispsw = &fbcon_cfb8;
#ifdef HAS_VIDC
visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
#else
visual = FB_VISUAL_PSEUDOCOLOR;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
#endif
break;
#endif
#ifdef FBCON_HAS_CFB16
#ifdef HAS_VIDC20
case 16:
current_par.palette_size = 32;
display->dispsw = &fbcon_cfb16;
display->dispsw_data = current_par.cmap.cfb16;
visual = FB_VISUAL_DIRECTCOLOR;
info->pseudo_palette = current_par.cmap.cfb16;
info->fix.visual = FB_VISUAL_DIRECTCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
current_par.palette_size = VIDC_PALETTE_SIZE;
display->dispsw = &fbcon_cfb32;
display->dispsw_data = current_par.cmap.cfb32;
visual = FB_VISUAL_TRUECOLOR;
info->pseudo_palette = current_par.cmap.cfb32;
info->fix.visual = FB_VISUAL_TRUECOLOR;
break;
#endif
default:
display->dispsw = &fbcon_dummy;
visual = FB_VISUAL_MONO10;
break;
BUG();
}
display->next_line = (var->xres * var->bits_per_pixel) / 8;
display->can_soft_blank = visual == FB_VISUAL_PSEUDOCOLOR ? 1 : 0;
display->inverse = 0;
if (chgvar && info && info->changevar)
info->changevar(con);
if (con == info->currcon) {
struct fb_cmap *cmap;
unsigned long start, size;
int control;
info->fix.visual = visual;
info->fix.line_length = (info->var.xres * info->var.bits_per_pixel) / 8;
#if defined(HAS_MEMC)
start = 0;
size = info->fix.smem_len - VDMA_XFERSIZE;
control = 0;
{
unsigned long size = info->fix.smem_len - VDMA_XFERSIZE;
memc_write(VDMA_START, start);
memc_write(VDMA_START, 0);
memc_write(VDMA_END, size >> 2);
}
#elif defined(HAS_IOMD)
{
unsigned long start, size;
u_int control;
start = info->fix.smem_start;
size = current_par.screen_end;
......@@ -1019,80 +823,27 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
iomd_writel(start, IOMD_VIDSTART);
iomd_writel(size, IOMD_VIDEND);
iomd_writel(control, IOMD_VIDCR);
}
#endif
acornfb_update_dma(info, var);
acornfb_set_timing(info, var);
if (display->cmap.len)
cmap = &display->cmap;
else
cmap = fb_default_cmap(current_par.palette_size);
acornfb_update_dma(info, &info->var);
acornfb_set_timing(info, &info->var);
fb_set_cmap(cmap, 1, info);
}
return 0;
}
static int
acornfb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
u_int y_bottom;
if (var->xoffset)
return -EINVAL;
y_bottom = var->yoffset;
u_int y_bottom = var->yoffset;
if (!(var->vmode & FB_VMODE_YWRAP))
y_bottom += var->yres;
if (y_bottom > fb_display[con].var.yres_virtual)
return -EINVAL;
BUG_ON(y_bottom > var->yres_virtual);
acornfb_update_dma(info, var);
fb_display[con].var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
fb_display[con].var.vmode |= FB_VMODE_YWRAP;
else
fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
return 0;
}
static int
acornfb_blank(int blank, struct fb_info *info)
{
union palette p;
int i, bpp = fb_display[info->currcon].var.bits_per_pixel;
#ifdef FBCON_HAS_CFB16
if (bpp == 16) {
p.p = 0;
for (i = 0; i < 256; i++) {
if (blank)
p = acornfb_palette_encode(i, 0, 0, 0, 0);
else {
p.vidc20.red = current_par.palette[ i & 31].vidc20.red;
p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
p.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
}
acornfb_palette_write(i, current_par.palette[i]);
}
} else
#endif
{
for (i = 0; i < current_par.palette_size; i++) {
if (blank)
p = acornfb_palette_encode(i, 0, 0, 0, 0);
else
p = current_par.palette[i];
acornfb_palette_write(i, p);
}
}
return 0;
}
......@@ -1137,45 +888,16 @@ acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma
static struct fb_ops acornfb_ops = {
.owner = THIS_MODULE,
.fb_set_var = acornfb_set_var,
.fb_get_cmap = acornfb_get_cmap,
.fb_set_cmap = gen_set_cmap,
.fb_check_var = acornfb_check_var,
.fb_set_par = acornfb_set_par,
.fb_setcolreg = acornfb_setcolreg,
.fb_pan_display = acornfb_pan_display,
.fb_blank = acornfb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = acornfb_mmap,
};
static int
acornfb_updatevar(int con, struct fb_info *info)
{
if (con == info->currcon)
acornfb_update_dma(info, &fb_display[con].var);
return 0;
}
static int
acornfb_switch(int con, struct fb_info *info)
{
struct fb_cmap *cmap;
if (info->currcon >= 0) {
cmap = &fb_display[info->currcon].cmap;
if (cmap->len)
fb_get_cmap(cmap, 1, acornfb_getcolreg, info);
}
info->currcon = con;
fb_display[con].var.activate = FB_ACTIVATE_NOW;
acornfb_set_var(&fb_display[con].var, con, info);
return 0;
}
/*
* Everything after here is initialisation!!!
*/
......@@ -1248,8 +970,7 @@ acornfb_default_mode = {
.vmode = FB_VMODE_NONINTERLACED
};
static void __init
acornfb_init_fbinfo(void)
static void __init acornfb_init_fbinfo(void)
{
static int first = 1;
......@@ -1257,15 +978,8 @@ acornfb_init_fbinfo(void)
return;
first = 0;
strcpy(fb_info.modename, "Acorn");
strcpy(fb_info.fontname, "Acorn8x8");
fb_info.node = NODEV;
fb_info.fbops = &acornfb_ops;
fb_info.disp = &global_disp;
fb_info.changevar = NULL;
fb_info.switch_con = acornfb_switch;
fb_info.updatevar = acornfb_updatevar;
fb_info.flags = FBINFO_FLAG_DEFAULT;
strcpy(fb_info.fix.id, "Acorn");
......@@ -1277,28 +991,26 @@ acornfb_init_fbinfo(void)
fb_info.fix.line_length = 0;
fb_info.fix.accel = FB_ACCEL_NONE;
global_disp.dispsw = &fbcon_dummy;
/*
* setup initial parameters
*/
memset(&init_var, 0, sizeof(init_var));
memset(&fb_info.var, 0, sizeof(fb_info.var));
#if defined(HAS_VIDC20)
init_var.red.length = 8;
init_var.transp.length = 4;
fb_info.var.red.length = 8;
fb_info.var.transp.length = 4;
#elif defined(HAS_VIDC)
init_var.red.length = 4;
init_var.transp.length = 1;
fb_info.var.red.length = 4;
fb_info.var.transp.length = 1;
#endif
init_var.green = init_var.red;
init_var.blue = init_var.red;
init_var.nonstd = 0;
init_var.activate = FB_ACTIVATE_NOW;
init_var.height = -1;
init_var.width = -1;
init_var.vmode = FB_VMODE_NONINTERLACED;
init_var.accel_flags = FB_ACCELF_TEXT;
fb_info.var.green = fb_info.var.red;
fb_info.var.blue = fb_info.var.red;
fb_info.var.nonstd = 0;
fb_info.var.activate = FB_ACTIVATE_NOW;
fb_info.var.height = -1;
fb_info.var.width = -1;
fb_info.var.vmode = FB_VMODE_NONINTERLACED;
fb_info.var.accel_flags = FB_ACCELF_TEXT;
current_par.dram_size = 0;
current_par.montype = -1;
......@@ -1308,9 +1020,6 @@ acornfb_init_fbinfo(void)
/*
* setup acornfb options:
*
* font:fontname
* Set fontname
*
* mon:hmin-hmax:vmin-vmax:dpms:width:height
* Set monitor parameters:
* hmin = horizontal minimum frequency (Hz)
......@@ -1337,12 +1046,6 @@ acornfb_init_fbinfo(void)
* size can optionally be followed by 'M' or 'K' for
* MB or KB respectively.
*/
static void __init
acornfb_parse_font(char *opt)
{
strcpy(fb_info.fontname, opt);
}
static void __init
acornfb_parse_mon(char *opt)
{
......@@ -1373,12 +1076,12 @@ acornfb_parse_mon(char *opt)
if (*p != ':')
goto check_values;
init_var.width = simple_strtoul(p + 1, &p, 0);
fb_info.var.width = simple_strtoul(p + 1, &p, 0);
if (*p != ':')
goto check_values;
init_var.height = simple_strtoul(p + 1, NULL, 0);
fb_info.var.height = simple_strtoul(p + 1, NULL, 0);
check_values:
if (fb_info.monspecs.hfmax < fb_info.monspecs.hfmin ||
......@@ -1460,7 +1163,6 @@ static struct options {
char *name;
void (*parse)(char *opt);
} opt_table[] __initdata = {
{ "font", acornfb_parse_font },
{ "mon", acornfb_parse_mon },
{ "montype", acornfb_parse_montype },
{ "dram", acornfb_parse_dram },
......@@ -1658,7 +1360,7 @@ acornfb_init(void)
* the resolution, so we disable this feature.
*/
do {
rc = fb_find_mode(&init_var, &fb_info, NULL, modedb,
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
sizeof(modedb) / sizeof(*modedb),
&acornfb_default_mode, DEFAULT_BPP);
/*
......@@ -1667,7 +1369,7 @@ acornfb_init(void)
if (rc == 1)
break;
rc = fb_find_mode(&init_var, &fb_info, NULL, NULL, 0,
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
&acornfb_default_mode, DEFAULT_BPP);
/*
* If we found an exact match, all ok.
......@@ -1675,13 +1377,13 @@ acornfb_init(void)
if (rc == 1)
break;
rc = fb_find_mode(&init_var, &fb_info, NULL, modedb,
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,
sizeof(modedb) / sizeof(*modedb),
&acornfb_default_mode, DEFAULT_BPP);
if (rc)
break;
rc = fb_find_mode(&init_var, &fb_info, NULL, NULL, 0,
rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,
&acornfb_default_mode, DEFAULT_BPP);
} while (0);
......@@ -1694,17 +1396,17 @@ acornfb_init(void)
return -EINVAL;
}
h_sync = 1953125000 / init_var.pixclock;
h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin +
init_var.right_margin + init_var.hsync_len);
v_sync = h_sync / (init_var.yres + init_var.upper_margin +
init_var.lower_margin + init_var.vsync_len);
h_sync = 1953125000 / fb_info.var.pixclock;
h_sync = h_sync * 512 / (fb_info.var.xres + fb_info.var.left_margin +
fb_info.var.right_margin + fb_info.var.hsync_len);
v_sync = h_sync / (fb_info.var.yres + fb_info.var.upper_margin +
fb_info.var.lower_margin + fb_info.var.vsync_len);
printk(KERN_INFO "Acornfb: %dkB %cRAM, %s, using %dx%d, "
"%d.%03dkHz, %dHz\n",
fb_info.fix.smem_len / 1024,
current_par.using_vram ? 'V' : 'D',
VIDC_NAME, init_var.xres, init_var.yres,
VIDC_NAME, fb_info.var.xres, fb_info.var.yres,
h_sync / 1000, h_sync % 1000, v_sync);
printk(KERN_INFO "Acornfb: Monitor: %d.%03d-%d.%03dkHz, %d-%dHz%s\n",
......@@ -1713,7 +1415,7 @@ acornfb_init(void)
fb_info.monspecs.vfmin, fb_info.monspecs.vfmax,
fb_info.monspecs.dpms ? ", DPMS" : "");
if (acornfb_set_var(&init_var, -1, &fb_info))
if (fb_set_var(&fb_info.var, &fb_info))
printk(KERN_ERR "Acornfb: unable to set display parameters\n");
if (register_framebuffer(&fb_info) < 0)
......
......@@ -103,9 +103,6 @@ struct sa1100fb_info {
wait_queue_head_t ctrlr_wait;
struct work_struct task;
#ifdef CONFIG_PM
struct pm_dev *pm;
#endif
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
struct notifier_block freq_policy;
......@@ -128,6 +125,7 @@ struct sa1100fb_info {
#define C_REENABLE (4)
#define C_DISABLE_PM (5)
#define C_ENABLE_PM (6)
#define C_STARTUP (7)
#define SA1100_NAME "SA1100"
......
#ifndef AGP_H
#define AGP_H 1
#include <asm/io.h>
/* dummy for now */
#define map_page_into_agp(page)
......
#ifndef _ALPHA_AGP_BACKEND_H
#define _ALPHA_AGP_BACKEND_H 1
typedef union _alpha_agp_mode {
struct {
u32 rate : 3;
u32 reserved0 : 1;
u32 fw : 1;
u32 fourgb : 1;
u32 reserved1 : 2;
u32 enable : 1;
u32 sba : 1;
u32 reserved2 : 14;
u32 rq : 8;
} bits;
u32 lw;
} alpha_agp_mode;
typedef struct _alpha_agp_info {
enum chipset_type type;
struct pci_controller *hose;
struct {
dma_addr_t bus_base;
unsigned long size;
void *sysdata;
} aperture;
alpha_agp_mode capability;
alpha_agp_mode mode;
void *private;
struct alpha_agp_ops *ops;
} alpha_agp_info;
struct alpha_agp_ops {
int (*setup)(alpha_agp_info *);
void (*cleanup)(alpha_agp_info *);
int (*configure)(alpha_agp_info *);
int (*bind)(alpha_agp_info *, off_t, agp_memory *);
int (*unbind)(alpha_agp_info *, off_t, agp_memory *);
unsigned long (*translate)(alpha_agp_info *, dma_addr_t);
};
#endif /* _ALPHA_AGP_BACKEND_H */
/*
* 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 32 /* as long as we rely on 43-bit superpage */
#define MARVEL_IRQ_VEC_PE_SHIFT (10)
#define MARVEL_IRQ_VEC_IRQ_MASK ((1 << MARVEL_IRQ_VEC_PE_SHIFT) - 1)
#define MARVEL_NR_IRQS \
(16 + (MARVEL_MAX_PIDS * (1 << MARVEL_IRQ_VEC_PE_SHIFT)))
/*
* 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) marvel_inb((unsigned long)(p))
#define __inw(p) marvel_inw((unsigned long)(p))
#define __inl(p) marvel_inl((unsigned long)(p))
#define __outb(x,p) marvel_outb((x),(unsigned long)(p))
#define __outw(x,p) marvel_outw((x),(unsigned long)(p))
#define __outl(x,p) marvel_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) marvel_ioremap((unsigned long)(a),(s))
#define __iounmap(a) marvel_iounmap((unsigned long)(a))
#define __is_ioaddr(a) marvel_is_ioaddr((unsigned long)(a))
/* Disable direct inlining of these calls with the debug checks present. */
#if 0
#define __raw_readb(a) __readb(a)
#define __raw_readw(a) __readw(a)
#define __raw_readl(a) __readl(a)
#define __raw_readq(a) __readq(a)
#define __raw_writeb(v,a) __writeb(v,a)
#define __raw_writew(v,a) __writew(v,a)
#define __raw_writel(v,a) __writel(v,a)
#define __raw_writeq(v,a) __writeq(v,a)
#endif
#endif /* __WANT_IO_DEF */
#ifdef __IO_EXTERN_INLINE
# undef __EXTERN_INLINE
# undef __IO_EXTERN_INLINE
#endif
#endif /* __KERNEL__ */
#endif /* __ALPHA_MARVEL__H__ */
......@@ -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)
{
......
#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 */
......@@ -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
......
......@@ -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)
......
......@@ -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) /* marvel - 32 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) /* marvel - 32 pids*/
#else /* everyone else */
# define NR_IRQS 16
#endif
......
......@@ -22,6 +22,7 @@ struct linux_hose_info;
struct pci_dev;
struct pci_ops;
struct pci_controller;
struct _alpha_agp_info;
struct alpha_machine_vector
{
......@@ -80,6 +81,7 @@ struct alpha_machine_vector
void (*device_interrupt)(unsigned long vector, struct pt_regs *regs);
void (*machine_check)(u64 vector, u64 la, struct pt_regs *regs);
void (*smp_callin)(void);
void (*init_arch)(void);
void (*init_irq)(void);
void (*init_rtc)(void);
......@@ -90,6 +92,8 @@ struct alpha_machine_vector
int (*pci_map_irq)(struct pci_dev *, u8, u8);
struct pci_ops *pci_ops;
struct _alpha_agp_info *(*agp_info)(void);
const char *vector_name;
/* NUMA information */
......
......@@ -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
......
......@@ -46,6 +46,8 @@
#define __phys_to_virt__is_a_macro
#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
#define BUS_OFFSET (0x80000000UL)
/*
* Virtual view <-> DMA view memory address translations
* virt_to_bus: Used to translate the virtual address to an
......@@ -54,8 +56,8 @@
* to an address that the kernel can use.
*/
#define __virt_to_bus__is_a_macro
#define __virt_to_bus(x) (x - PAGE_OFFSET + INTEGRATOR_HDR0_SDRAM_BASE)
#define __virt_to_bus(x) (x - PAGE_OFFSET + BUS_OFFSET)
#define __bus_to_virt__is_a_macro
#define __bus_to_virt(x) (x - INTEGRATOR_HDR0_SDRAM_BASE + PAGE_OFFSET)
#define __bus_to_virt(x) (x - BUS_OFFSET + PAGE_OFFSET)
#endif
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