summaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel/t2.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/kernel/t2.c')
-rw-r--r--arch/alpha/kernel/t2.c229
1 files changed, 138 insertions, 91 deletions
diff --git a/arch/alpha/kernel/t2.c b/arch/alpha/kernel/t2.c
index 398aaebb5..69ca71404 100644
--- a/arch/alpha/kernel/t2.c
+++ b/arch/alpha/kernel/t2.c
@@ -8,8 +8,8 @@
*
*/
#include <linux/kernel.h>
+#include <linux/config.h>
#include <linux/types.h>
-#include <linux/bios32.h>
#include <linux/pci.h>
#include <linux/sched.h>
@@ -19,17 +19,14 @@
#include <asm/ptrace.h>
#include <asm/mmu_context.h>
-/* NOTE: Herein are back-to-back mb insns. They are magic.
- A plausable explanation is that the i/o controler does not properly
- handle the system transaction. Another involves timing. Ho hum. */
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the i/o controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
extern struct hwrpb_struct *hwrpb;
extern asmlinkage void wrmces(unsigned long mces);
-extern asmlinkage unsigned long whami(void);
-extern int alpha_sys_type;
-
-#define CPUID whami()
-
/*
* Machine check reasons. Defined according to PALcode sources
@@ -62,10 +59,14 @@ extern int alpha_sys_type;
#define vulp volatile unsigned long *
#define vuip volatile unsigned int *
-static volatile unsigned int T2_mcheck_expected = 0;
-static volatile unsigned int T2_mcheck_taken = 0;
-static unsigned long T2_jd;
+static volatile unsigned int T2_mcheck_expected[NR_CPUS];
+static volatile unsigned int T2_mcheck_taken[NR_CPUS];
+#ifdef CONFIG_ALPHA_SRM_SETUP
+unsigned int T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT;
+unsigned int T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT;
+unsigned long t2_sm_base;
+#endif /* SRM_SETUP */
/*
* Given a bus, device, and function number, compute resulting
@@ -145,8 +146,10 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
static unsigned int conf_read(unsigned long addr, unsigned char type1)
{
unsigned long flags;
- unsigned int stat0, value;
- unsigned int t2_cfg = 0; /* to keep gcc quiet */
+ unsigned int stat0, value, cpu;
+ unsigned long t2_cfg = 0; /* to keep gcc quiet */
+
+ cpu = smp_processor_id();
save_flags(flags); /* avoid getting hit by machine check */
cli();
@@ -155,43 +158,41 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
#if 0
/* reset status register to avoid losing errors: */
- stat0 = *(vuip)T2_IOCSR;
- *(vuip)T2_IOCSR = stat0;
+ stat0 = *(vulp)T2_IOCSR;
+ *(vulp)T2_IOCSR = stat0;
mb();
DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0));
+#endif
/* if Type1 access, must set T2 CFG */
if (type1) {
- t2_cfg = *(vuip)T2_IOC_CFG;
+ t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
+ *(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg;
mb();
- *(vuip)T2_IOC_CFG = t2_cfg | 1;
DBG(("conf_read: TYPE1 access\n"));
}
mb();
draina();
-#endif
- T2_mcheck_expected = 1;
- T2_mcheck_taken = 0;
+ T2_mcheck_expected[cpu] = 1;
+ T2_mcheck_taken[cpu] = 0;
mb();
/* access configuration space: */
value = *(vuip)addr;
mb();
mb(); /* magic */
- if (T2_mcheck_taken) {
- T2_mcheck_taken = 0;
+ if (T2_mcheck_taken[cpu]) {
+ T2_mcheck_taken[cpu] = 0;
value = 0xffffffffU;
mb();
}
- T2_mcheck_expected = 0;
+ T2_mcheck_expected[cpu] = 0;
mb();
-#if 0
- /* if Type1 access, must reset IOC CFG so normal IO space ops work */
+ /* if Type1 access, must reset T2 CFG so normal IO space ops work */
if (type1) {
- *(vuip)T2_IOC_CFG = t2_cfg & ~1;
+ *(vulp)T2_HAE_3 = t2_cfg;
mb();
}
-#endif
DBG(("conf_read(): finished\n"));
restore_flags(flags);
@@ -203,44 +204,45 @@ static void conf_write(unsigned long addr, unsigned int value,
unsigned char type1)
{
unsigned long flags;
- unsigned int stat0;
- unsigned int t2_cfg = 0; /* to keep gcc quiet */
+ unsigned int stat0, cpu;
+ unsigned long t2_cfg = 0; /* to keep gcc quiet */
+
+ cpu = smp_processor_id();
save_flags(flags); /* avoid getting hit by machine check */
cli();
#if 0
/* reset status register to avoid losing errors: */
- stat0 = *(vuip)T2_IOCSR;
- *(vuip)T2_IOCSR = stat0;
+ stat0 = *(vulp)T2_IOCSR;
+ *(vulp)T2_IOCSR = stat0;
mb();
DBG(("conf_write: T2 ERR was 0x%x\n", stat0));
+#endif
/* if Type1 access, must set T2 CFG */
if (type1) {
- t2_cfg = *(vuip)T2_IOC_CFG;
+ t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
+ *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL;
mb();
- *(vuip)T2_IOC_CFG = t2_cfg | 1;
DBG(("conf_write: TYPE1 access\n"));
}
+ mb();
draina();
-#endif
- T2_mcheck_expected = 1;
+ T2_mcheck_expected[cpu] = 1;
mb();
/* access configuration space: */
*(vuip)addr = value;
mb();
mb(); /* magic */
- T2_mcheck_expected = 0;
+ T2_mcheck_expected[cpu] = 0;
mb();
-#if 0
- /* if Type1 access, must reset IOC CFG so normal IO space ops work */
+ /* if Type1 access, must reset T2 CFG so normal IO space ops work */
if (type1) {
- *(vuip)T2_IOC_CFG = t2_cfg & ~1;
+ *(vulp)T2_HAE_3 = t2_cfg;
mb();
}
-#endif
DBG(("conf_write(): finished\n"));
restore_flags(flags);
}
@@ -362,17 +364,21 @@ int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
unsigned long t2_init(unsigned long mem_start, unsigned long mem_end)
{
- unsigned int t2_err;
- struct percpu_struct *cpu;
- int i;
+ unsigned long t2_err;
+ unsigned int i;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ T2_mcheck_expected[i] = 0;
+ T2_mcheck_taken[i] = 0;
+ }
#if 0
/*
* Set up error reporting.
*/
- t2_err = *(vuip)T2_IOCSR ;
+ t2_err = *(vulp)T2_IOCSR ;
t2_err |= (0x1 << 7) ; /* master abort */
- *(vuip)T2_IOC_T2_ERR = t2_err ;
+ *(vulp)T2_IOCSR = t2_err ;
mb() ;
#endif
@@ -388,6 +394,42 @@ unsigned long t2_init(unsigned long mem_start, unsigned long mem_end)
*(vulp)T2_TBASE2);
#endif
+#ifdef CONFIG_ALPHA_SRM_SETUP
+ /* check window 1 for enabled and mapped to 0 */
+ if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18)) &&
+ (*(vulp)T2_TBASE1 == 0))
+ {
+ T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE += 0x00100000UL;
+/* DISABLE window 2!! ?? */
+#if 1
+ printk("t2_init: using Window 1 settings\n");
+ printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)T2_WBASE1,
+ *(vulp)T2_WMASK1,
+ *(vulp)T2_TBASE1);
+#endif
+ }
+ else /* check window 2 for enabled and mapped to 0 */
+ if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18)) &&
+ (*(vulp)T2_TBASE2 == 0))
+ {
+ T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE += 0x00100000UL;
+/* DISABLE window 1!! ?? */
+#if 1
+ printk("t2_init: using Window 2 settings\n");
+ printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)T2_WBASE2,
+ *(vulp)T2_WMASK2,
+ *(vulp)T2_TBASE2);
+#endif
+ }
+ else /* we must use our defaults... */
+#endif /* SRM_SETUP */
+ {
/*
* Set up the PCI->physical memory translation windows.
* For now, window 2 is disabled. In the future, we may
@@ -396,13 +438,13 @@ unsigned long t2_init(unsigned long mem_start, unsigned long mem_end)
*/
/* WARNING!! must correspond to the DMA_WIN params!!! */
- *(vuip)T2_WBASE1 = 0x400807ffU;
- *(vuip)T2_WMASK1 = 0x3ff00000U;
- *(vuip)T2_TBASE1 = 0;
-
- *(vuip)T2_WBASE2 = 0x0;
+ *(vulp)T2_WBASE1 = 0x400807ffU;
+ *(vulp)T2_WMASK1 = 0x3ff00000U;
+ *(vulp)T2_TBASE1 = 0;
- *(vuip)T2_HBASE = 0x0;
+ *(vulp)T2_WBASE2 = 0x0;
+ *(vulp)T2_HBASE = 0x0;
+ }
/*
* check ASN in HWRPB for validity, report if bad
@@ -420,41 +462,43 @@ unsigned long t2_init(unsigned long mem_start, unsigned long mem_end)
* what ARC or SRM might have left behind...
*/
{
-#if 0
- printk("T2_init: HAE1 was 0x%lx\n", *(vulp)T2_HAE_1);
- printk("T2_init: HAE2 was 0x%lx\n", *(vulp)T2_HAE_2);
- printk("T2_init: HAE3 was 0x%lx\n", *(vulp)T2_HAE_3);
- printk("T2_init: HAE4 was 0x%lx\n", *(vulp)T2_HAE_4);
+ unsigned long t2_hae_1 = *(vulp)T2_HAE_1;
+ unsigned long t2_hae_2 = *(vulp)T2_HAE_2;
+ unsigned long t2_hae_3 = *(vulp)T2_HAE_3;
+ unsigned long t2_hae_4 = *(vulp)T2_HAE_4;
+#if 1
+ printk("T2_init: HAE1 was 0x%lx\n", t2_hae_1);
+ printk("T2_init: HAE2 was 0x%lx\n", t2_hae_2);
+ printk("T2_init: HAE3 was 0x%lx\n", t2_hae_3);
+ printk("T2_init: HAE4 was 0x%lx\n", t2_hae_4);
#endif
+#ifdef CONFIG_ALPHA_SRM_SETUP
+ /*
+ * sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * see include/asm-alpha/t2.h for the SPARSE mem read/write
+ */
+ t2_sm_base = (t2_hae_1 << 27) & 0xf8000000UL;
+ /*
+ Set the HAE cache, so that setup_arch() code
+ will use the SRM setting always. Our readb/writeb
+ code in .h expects never to have to change
+ the contents of the HAE.
+ */
+ hae.cache = t2_hae_1;
+#else /* SRM_SETUP */
+ *(vulp)T2_HAE_1 = 0; mb();
+ *(vulp)T2_HAE_2 = 0; mb();
+ *(vulp)T2_HAE_3 = 0; mb();
#if 0
- *(vuip)T2_HAE_1 = 0; mb();
- *(vuip)T2_HAE_2 = 0; mb();
- *(vuip)T2_HAE_3 = 0; mb();
- *(vuip)T2_HAE_4 = 0; mb();
+ *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
#endif
+#endif /* SRM_SETUP */
}
-#if 1
- if (hwrpb->nr_processors > 1) {
- printk("T2_init: nr_processors 0x%lx\n",
- hwrpb->nr_processors);
- printk("T2_init: processor_size 0x%lx\n",
- hwrpb->processor_size);
- printk("T2_init: processor_offset 0x%lx\n",
- hwrpb->processor_offset);
-
- cpu = (struct percpu_struct *)
- ((char*)hwrpb + hwrpb->processor_offset);
-
- for (i = 0; i < hwrpb->nr_processors; i++ ) {
- printk("T2_init: CPU 0x%x: flags 0x%lx type 0x%lx\n",
- i, cpu->flags, cpu->type);
- cpu = (struct percpu_struct *)
- ((char *)cpu + hwrpb->processor_size);
- }
- }
-#endif
-
return mem_start;
}
@@ -469,17 +513,19 @@ static struct sable_cpu_csr *sable_cpu_regs[4] = {
int t2_clear_errors(void)
{
+ unsigned int cpu = smp_processor_id();
+
DBGMC(("???????? t2_clear_errors\n"));
- sable_cpu_regs[CPUID]->sic &= ~SIC_SEIC;
+ sable_cpu_regs[cpu]->sic &= ~SIC_SEIC;
/*
* clear cpu errors
*/
- sable_cpu_regs[CPUID]->bcce |= sable_cpu_regs[CPUID]->bcce;
- sable_cpu_regs[CPUID]->cbe |= sable_cpu_regs[CPUID]->cbe;
- sable_cpu_regs[CPUID]->bcue |= sable_cpu_regs[CPUID]->bcue;
- sable_cpu_regs[CPUID]->dter |= sable_cpu_regs[CPUID]->dter;
+ sable_cpu_regs[cpu]->bcce |= sable_cpu_regs[cpu]->bcce;
+ sable_cpu_regs[cpu]->cbe |= sable_cpu_regs[cpu]->cbe;
+ sable_cpu_regs[cpu]->bcue |= sable_cpu_regs[cpu]->bcue;
+ sable_cpu_regs[cpu]->dter |= sable_cpu_regs[cpu]->dter;
*(vulp)T2_CERR1 |= *(vulp)T2_CERR1;
*(vulp)T2_PERR1 |= *(vulp)T2_PERR1;
@@ -499,6 +545,7 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr,
const char * reason;
char buf[128];
long i;
+ unsigned int cpu = smp_processor_id();
DBGMC(("t2_machine_check: vector=0x%lx la_ptr=0x%lx\n",
vector, la_ptr));
@@ -516,7 +563,7 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr,
DBGMC((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset,
mchk_header->elfl_sysoffset));
- DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected));
+ DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected[cpu]));
#ifdef DEBUG_DUMP
{
@@ -537,11 +584,11 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr,
*/
mb();
mb(); /* magic */
- if (T2_mcheck_expected/* && (mchk_sysdata->epic_dcsr && 0x0c00UL)*/) {
+ if (T2_mcheck_expected[cpu]) {
DBGMC(("T2 machine check expected\n"));
- T2_mcheck_taken = 1;
+ T2_mcheck_taken[cpu] = 1;
t2_clear_errors();
- T2_mcheck_expected = 0;
+ T2_mcheck_expected[cpu] = 0;
mb();
mb(); /* magic */
wrmces(rdmces()|1);/* ??? */