summaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel/core_apecs.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
commitd6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch)
treee2be02f33984c48ec019c654051d27964e42c441 /arch/alpha/kernel/core_apecs.c
parent609d1e803baf519487233b765eb487f9ec227a18 (diff)
Merge with 2.3.19.
Diffstat (limited to 'arch/alpha/kernel/core_apecs.c')
-rw-r--r--arch/alpha/kernel/core_apecs.c325
1 files changed, 115 insertions, 210 deletions
diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c
index fa23a4cf6..46378b762 100644
--- a/arch/alpha/kernel/core_apecs.c
+++ b/arch/alpha/kernel/core_apecs.c
@@ -1,22 +1,24 @@
/*
* linux/arch/alpha/kernel/core_apecs.c
*
- * Code common to all APECS core logic chips.
- *
* Rewritten for Apecs from the lca.c from:
*
* Written by David Mosberger (davidm@cs.arizona.edu) with some code
* taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
* bios code.
+ *
+ * Code common to all APECS core logic chips.
*/
+
#include <linux/kernel.h>
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/ptrace.h>
+#include <asm/smp.h>
+#include <asm/pci.h>
#define __EXTERN_INLINE inline
#include <asm/io.h>
@@ -24,6 +26,7 @@
#undef __EXTERN_INLINE
#include "proto.h"
+#include "pci_impl.h"
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
@@ -35,19 +38,16 @@
* BIOS32-style PCI interface:
*/
-#ifdef DEBUG
-# define DBG(args) printk args
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
+# define DBGC(args) printk args
#else
-# define DBG(args)
+# define DBGC(args)
#endif
#define vuip volatile unsigned int *
-volatile unsigned int apecs_mcheck_expected = 0;
-volatile unsigned int apecs_mcheck_taken = 0;
-static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
-
-
/*
* Given a bus, device, and function number, compute resulting
* configuration space address and setup the APECS_HAXR2 register
@@ -91,14 +91,16 @@ static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
*/
static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
unsigned char *type1)
{
unsigned long addr;
+ u8 bus = dev->bus->number;
+ u8 device_fn = dev->devfn;
- DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
- " pci_addr=0x%p, type1=0x%p)\n",
- bus, device_fn, where, pci_addr, type1));
+ DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+ " pci_addr=0x%p, type1=0x%p)\n",
+ bus, device_fn, where, pci_addr, type1));
if (bus == 0) {
int device = device_fn >> 3;
@@ -106,8 +108,8 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
/* type 0 configuration cycle: */
if (device > 20) {
- DBG(("mk_conf_addr: device (%d) > 20, returning -1\n",
- device));
+ DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n",
+ device));
return -1;
}
@@ -119,7 +121,7 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
addr = (bus << 16) | (device_fn << 8) | (where);
}
*pci_addr = addr;
- DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
return 0;
}
@@ -132,25 +134,25 @@ conf_read(unsigned long addr, unsigned char type1)
__save_and_cli(flags); /* avoid getting hit by machine check */
- DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+ DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
/* Reset status register to avoid losing errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
*(vuip)APECS_IOC_DCSR = stat0;
mb();
- DBG(("conf_read: APECS DCSR was 0x%x\n", stat0));
+ DBGC(("conf_read: APECS DCSR was 0x%x\n", stat0));
/* If Type1 access, must set HAE #2. */
if (type1) {
haxr2 = *(vuip)APECS_IOC_HAXR2;
mb();
*(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
- DBG(("conf_read: TYPE1 access\n"));
+ DBGC(("conf_read: TYPE1 access\n"));
}
draina();
- apecs_mcheck_expected = 1;
- apecs_mcheck_taken = 0;
+ mcheck_expected(0) = 1;
+ mcheck_taken(0) = 0;
mb();
/* Access configuration space. */
@@ -159,12 +161,12 @@ conf_read(unsigned long addr, unsigned char type1)
asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
: "$9", "$10", "$11", "$12", "$13", "$14", "memory");
- if (apecs_mcheck_taken) {
- apecs_mcheck_taken = 0;
+ if (mcheck_taken(0)) {
+ mcheck_taken(0) = 0;
value = 0xffffffffU;
mb();
}
- apecs_mcheck_expected = 0;
+ mcheck_expected(0) = 0;
mb();
#if 1
@@ -178,7 +180,7 @@ conf_read(unsigned long addr, unsigned char type1)
/* Now look for any errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
- DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0));
+ DBGC(("conf_read: APECS DCSR after read 0x%x\n", stat0));
/* Is any error bit set? */
if (stat0 & 0xffe0U) {
@@ -214,7 +216,6 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
__save_and_cli(flags); /* avoid getting hit by machine check */
-
/* Reset status register to avoid losing errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
*(vuip)APECS_IOC_DCSR = stat0;
@@ -228,14 +229,14 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
}
draina();
- apecs_mcheck_expected = 1;
+ mcheck_expected(0) = 1;
mb();
/* Access configuration space. */
*(vuip)addr = value;
mb();
mb(); /* magic */
- apecs_mcheck_expected = 0;
+ mcheck_expected(0) = 0;
mb();
#if 1
@@ -272,162 +273,106 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
__restore_flags(flags);
}
-int
-apecs_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
- struct linux_hose_info *hose)
+static int
+apecs_read_config_byte(struct pci_dev *dev, int where, u8 *value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
-
+ addr = (pci_addr << 5) + 0x00 + APECS_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
-
return PCIBIOS_SUCCESSFUL;
}
-int
-apecs_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
- struct linux_hose_info *hose)
+static int
+apecs_read_config_word(struct pci_dev *dev, int where, u16 *value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x08;
-
+ addr = (pci_addr << 5) + 0x08 + APECS_CONF;
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-int
-apecs_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
- struct linux_hose_info *hose)
+static int
+apecs_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x18;
+ addr = (pci_addr << 5) + 0x18 + APECS_CONF;
*value = conf_read(addr, type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-apecs_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
- struct linux_hose_info *hose)
+static int
+apecs_write_config(struct pci_dev *dev, int where, u32 value, long mask)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
+ unsigned long addr, pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ if (mk_conf_addr(dev, where, &pci_addr, &type1))
return PCIBIOS_DEVICE_NOT_FOUND;
- addr |= (pci_addr << 5) + 0x00;
+ addr = (pci_addr << 5) + mask + APECS_CONF;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-int
-apecs_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
- struct linux_hose_info *hose)
+static int
+apecs_write_config_byte(struct pci_dev *dev, int where, u8 value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+ return apecs_write_config(dev, where, value, 0x00);
}
-int
-apecs_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
- struct linux_hose_info *hose)
+static int
+apecs_write_config_word(struct pci_dev *dev, int where, u16 value)
{
- unsigned long addr = APECS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
- return PCIBIOS_DEVICE_NOT_FOUND;
+ return apecs_write_config(dev, where, value, 0x08);
+}
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
+static int
+apecs_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+ return apecs_write_config(dev, where, value, 0x18);
}
+struct pci_ops apecs_pci_ops =
+{
+ read_byte: apecs_read_config_byte,
+ read_word: apecs_read_config_word,
+ read_dword: apecs_read_config_dword,
+ write_byte: apecs_write_config_byte,
+ write_word: apecs_write_config_word,
+ write_dword: apecs_write_config_dword
+};
+
void __init
apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
- switch (alpha_use_srm_setup)
- {
- default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
- /* Check window 1 for enabled and mapped to 0. */
- if ((*(vuip)APECS_IOC_PB1R & (1U<<19))
- && (*(vuip)APECS_IOC_TB1R == 0)) {
- APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U;
- APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U;
- APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("apecs_init: using Window 1 settings\n");
- printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n",
- *(vuip)APECS_IOC_PB1R,
- *(vuip)APECS_IOC_PM1R,
- *(vuip)APECS_IOC_TB1R);
-#endif
- break;
- }
+ struct pci_controler *hose;
- /* Check window 2 for enabled and mapped to 0. */
- if ((*(vuip)APECS_IOC_PB2R & (1U<<19))
- && (*(vuip)APECS_IOC_TB2R == 0)) {
- APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U;
- APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U;
- APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("apecs_init: using Window 2 settings\n");
- printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n",
- *(vuip)APECS_IOC_PB2R,
- *(vuip)APECS_IOC_PM2R,
- *(vuip)APECS_IOC_TB2R);
-#endif
- break;
- }
-
- /* Otherwise, we must use our defaults. */
- APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT;
- APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
-#endif
- case 0:
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 2 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA. Window 1
- * goes at 1 GB and is 1 GB large.
- */
- *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
-
- *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
- *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
- *(vuip)APECS_IOC_TB1R = 0;
- break;
- }
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 2 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA. Window 1
+ * goes at 1 GB and is 1 GB large.
+ */
+ *(vuip)APECS_IOC_PB1R = 1UL << 19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
+ *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
+ *(vuip)APECS_IOC_TB1R = 0;
+
+ *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
/*
* Finally, clear the HAXR2 register, which gets used
@@ -435,23 +380,35 @@ apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
* we want to use it, and we do not want to depend on
* what ARC or SRM might have left behind...
*/
- *(vuip)APECS_IOC_HAXR2 = 0; mb();
+ *(vuip)APECS_IOC_HAXR2 = 0;
+ mb();
+
+ /*
+ * Create our single hose.
+ */
+
+ hose = alloc_pci_controler(mem_start);
+ hose->io_space = &ioport_resource;
+ hose->mem_space = &iomem_resource;
+ hose->config_space = APECS_CONF;
+ hose->index = 0;
}
-int
+void
apecs_pci_clr_err(void)
{
- apecs_jd = *(vuip)APECS_IOC_DCSR;
- if (apecs_jd & 0xffe0L) {
- apecs_jd1 = *(vuip)APECS_IOC_SEAR;
- *(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L;
- apecs_jd = *(vuip)APECS_IOC_DCSR;
+ unsigned int jd;
+
+ jd = *(vuip)APECS_IOC_DCSR;
+ if (jd & 0xffe0L) {
+ *(vuip)APECS_IOC_SEAR;
+ *(vuip)APECS_IOC_DCSR = jd | 0xffe1L;
mb();
+ *(vuip)APECS_IOC_DCSR;
}
*(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
- apecs_jd2 = *(vuip)APECS_IOC_TBIA;
mb();
- return 0;
+ *(vuip)APECS_IOC_TBIA;
}
void
@@ -461,8 +418,6 @@ apecs_machine_check(unsigned long vector, unsigned long la_ptr,
struct el_common *mchk_header;
struct el_apecs_procdata *mchk_procdata;
struct el_apecs_sysdata_mcheck *mchk_sysdata;
- unsigned long *ptr;
- int i;
mchk_header = (struct el_common *)la_ptr;
@@ -473,66 +428,16 @@ apecs_machine_check(unsigned long vector, unsigned long la_ptr,
mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
(la_ptr + mchk_header->sys_offset);
-#ifdef DEBUG
- printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
- printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset);
- printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear);
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
- }
-#endif
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
+ /* Clear the error before any reporting. */
+ mb();
+ mb(); /* magic */
+ draina();
+ apecs_pci_clr_err();
+ wrmces(0x7); /* reset machine check pending flag */
+ mb();
- if (apecs_mcheck_expected
- && (mchk_sysdata->epic_dcsr & 0x0c00UL)) {
- apecs_mcheck_expected = 0;
- apecs_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- apecs_pci_clr_err();
- wrmces(0x7);
- mb();
- draina();
- DBG(("apecs_machine_check: EXPECTED\n"));
- }
- else if (vector == 0x620 || vector == 0x630) {
- /* Disable correctable from now on. */
- wrmces(0x1f);
- mb();
- draina();
- printk("apecs_machine_check: HW correctable (0x%lx)\n",
- vector);
- }
- else {
- printk(KERN_CRIT "APECS machine check:\n");
- printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
- printk(KERN_CRIT
- " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset);
- printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n",
- apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear);
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%lx %lx %lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
- }
-#if 0
- /* doesn't work with MILO */
- show_regs(regs);
-#endif
- }
+ process_mcheck_info(vector, la_ptr, regs, "APECS",
+ (mcheck_expected(0)
+ && (mchk_sysdata->epic_dcsr & 0x0c00UL)));
}