summaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel/sys_dp264.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/kernel/sys_dp264.c')
-rw-r--r--arch/alpha/kernel/sys_dp264.c237
1 files changed, 159 insertions, 78 deletions
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index f0ef47183..fbebdd5a5 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -8,6 +8,7 @@
* Code supporting the DP264 (EV6+TSUNAMI).
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
@@ -27,72 +28,150 @@
#include <asm/hwrpb.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-/*
- * HACK ALERT! only the boot cpu is used for interrupts.
- */
+static unsigned long cached_irq_mask;
+
+
+#define TSUNAMI_SET_IRQ_MASK(cpu, value) \
+do { \
+ volatile unsigned long *csr; \
+ csr = &TSUNAMI_cchip->dim##cpu##.csr; \
+ *csr = (value); \
+ mb(); \
+ *csr; \
+} while(0)
+
+static inline void
+do_flush_irq_mask(unsigned long value)
+{
+ switch (TSUNAMI_bootcpu) {
+ case 0:
+ TSUNAMI_SET_IRQ_MASK(0, value);
+ break;
+ case 1:
+ TSUNAMI_SET_IRQ_MASK(1, value);
+ break;
+ case 2:
+ TSUNAMI_SET_IRQ_MASK(2, value);
+ break;
+ case 3:
+ TSUNAMI_SET_IRQ_MASK(3, value);
+ break;
+ }
+}
+
+#ifdef CONFIG_SMP
+static inline void
+do_flush_smp_irq_mask(unsigned long value)
+{
+ extern unsigned long cpu_present_mask;
+ unsigned long other_cpus = cpu_present_mask & ~(1L << TSUNAMI_bootcpu);
+
+ if (other_cpus & 1)
+ TSUNAMI_SET_IRQ_MASK(0, value);
+ if (other_cpus & 2)
+ TSUNAMI_SET_IRQ_MASK(1, value);
+ if (other_cpus & 4)
+ TSUNAMI_SET_IRQ_MASK(2, value);
+ if (other_cpus & 8)
+ TSUNAMI_SET_IRQ_MASK(3, value);
+}
+#endif
static void
-dp264_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+dp264_flush_irq_mask(unsigned long mask)
{
- volatile unsigned long *csr;
+ unsigned long value;
- if (TSUNAMI_bootcpu < 2) {
- if (!TSUNAMI_bootcpu)
- csr = &TSUNAMI_cchip->dim0.csr;
- else
- csr = &TSUNAMI_cchip->dim1.csr;
- } else {
- if (TSUNAMI_bootcpu == 2)
- csr = &TSUNAMI_cchip->dim2.csr;
- else
- csr = &TSUNAMI_cchip->dim3.csr;
- }
+#ifdef CONFIG_SMP
+ do_flush_smp_irq_mask(mask);
+#endif
- *csr = ~mask;
- mb();
- *csr;
+ value = mask | (1UL << 55) | 0xffff; /* isa irqs always enabled */
+ do_flush_irq_mask(value);
+}
- if (irq < 16) {
- if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
- }
+static void
+clipper_flush_irq_mask(unsigned long mask)
+{
+ unsigned long value;
+
+ value = mask >> 16;
+#ifdef CONFIG_SMP
+ do_flush_smp_irq_mask(value);
+#endif
+
+ value = value | (1UL << 55); /* master ISA enable */
+ do_flush_irq_mask(value);
+}
+
+static inline void
+dp264_enable_irq(unsigned int irq)
+{
+ cached_irq_mask |= 1UL << irq;
+ dp264_flush_irq_mask(cached_irq_mask);
}
static void
-clipper_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+dp264_disable_irq(unsigned int irq)
{
- if (irq >= 16) {
- volatile unsigned long *csr;
-
- if (TSUNAMI_bootcpu < 2)
- if (!TSUNAMI_bootcpu)
- csr = &TSUNAMI_cchip->dim0.csr;
- else
- csr = &TSUNAMI_cchip->dim1.csr;
- else
- if (TSUNAMI_bootcpu == 2)
- csr = &TSUNAMI_cchip->dim2.csr;
- else
- csr = &TSUNAMI_cchip->dim3.csr;
-
- *csr = (~mask >> 16) | (1UL << 55); /* master ISA enable */
- mb();
- *csr;
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
+ cached_irq_mask &= ~(1UL << irq);
+ dp264_flush_irq_mask(cached_irq_mask);
+}
+
+static unsigned int
+dp264_startup_irq(unsigned int irq)
+{
+ dp264_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static inline void
+clipper_enable_irq(unsigned int irq)
+{
+ cached_irq_mask |= 1UL << irq;
+ clipper_flush_irq_mask(cached_irq_mask);
}
static void
+clipper_disable_irq(unsigned int irq)
+{
+ cached_irq_mask &= ~(1UL << irq);
+ clipper_flush_irq_mask(cached_irq_mask);
+}
+
+static unsigned int
+clipper_startup_irq(unsigned int irq)
+{
+ clipper_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type dp264_irq_type = {
+ typename: "DP264",
+ startup: dp264_startup_irq,
+ shutdown: dp264_disable_irq,
+ enable: dp264_enable_irq,
+ disable: dp264_disable_irq,
+ ack: dp264_disable_irq,
+ end: dp264_enable_irq,
+};
+
+static struct hw_interrupt_type clipper_irq_type = {
+ typename: "CLIPPER",
+ startup: clipper_startup_irq,
+ shutdown: clipper_disable_irq,
+ enable: clipper_enable_irq,
+ disable: clipper_disable_irq,
+ ack: clipper_disable_irq,
+ end: clipper_enable_irq,
+};
+
+static void
dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
#if 1
@@ -126,9 +205,9 @@ dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
static void
dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
+ int irq;
- ack = irq = (vector - 0x800) >> 4;
+ irq = (vector - 0x800) >> 4;
/*
* The SRM console reports PCI interrupts with a vector calculated by:
@@ -142,17 +221,17 @@ dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
* so we don't count them.
*/
if (irq >= 32)
- ack = irq = irq - 16;
+ irq -= 16;
- handle_irq(irq, ack, regs);
+ handle_irq(irq, regs);
}
static void
clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
+ int irq;
- ack = irq = (vector - 0x800) >> 4;
+ irq = (vector - 0x800) >> 4;
/*
* The SRM console reports PCI interrupts with a vector calculated by:
@@ -166,7 +245,19 @@ clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
*
* Eg IRQ 24 is DRIR bit 8, etc, etc
*/
- handle_irq(irq, ack, regs);
+ handle_irq(irq, regs);
+}
+
+static void __init
+init_tsunami_irqs(struct hw_interrupt_type * ops)
+{
+ long i;
+
+ /* Only irqs between 16 and 47 are tsunami irqs. */
+ for (i = 16; i < 48; ++i) {
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+ irq_desc[i].handler = ops;
+ }
}
static void __init
@@ -180,10 +271,11 @@ dp264_init_irq(void)
if (alpha_using_srm)
alpha_mv.device_interrupt = dp264_srm_device_interrupt;
- dp264_update_irq_hw(16, alpha_irq_mask, 0);
+ dp264_flush_irq_mask(0UL);
- enable_irq(55); /* Enable ISA interrupt controller. */
- enable_irq(2);
+ init_i8259a_irqs();
+ init_rtc_irq();
+ init_tsunami_irqs(&dp264_irq_type);
}
static void __init
@@ -197,10 +289,11 @@ clipper_init_irq(void)
if (alpha_using_srm)
alpha_mv.device_interrupt = clipper_srm_device_interrupt;
- clipper_update_irq_hw(16, alpha_irq_mask, 0);
+ clipper_flush_irq_mask(0UL);
- enable_irq(55); /* Enable ISA interrupt controller. */
- enable_irq(2);
+ init_i8259a_irqs();
+ init_rtc_irq();
+ init_tsunami_irqs(&clipper_irq_type);
}
@@ -431,14 +524,11 @@ struct alpha_machine_vector dp264_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: dp264_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: dp264_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: dp264_map_irq,
@@ -458,14 +548,11 @@ struct alpha_machine_vector monet_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: dp264_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: monet_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: monet_map_irq,
@@ -484,14 +571,11 @@ struct alpha_machine_vector webbrick_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: dp264_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: webbrick_map_irq,
@@ -510,14 +594,11 @@ struct alpha_machine_vector clipper_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: clipper_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: clipper_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: clipper_map_irq,