summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/dec/ioasic-irq.c8
-rw-r--r--arch/mips/dec/time.c22
-rw-r--r--arch/mips/include/asm/dec/ioasic.h4
-rw-r--r--arch/mips/kernel/csrc-ioasic.c8
-rw-r--r--arch/mips/kernel/smp-cmp.c13
-rw-r--r--arch/mips/kernel/vpe.c2
-rw-r--r--drivers/net/ethernet/amd/declance.c1
7 files changed, 50 insertions, 8 deletions
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
index 824e08c..4b3e3a4 100644
--- a/arch/mips/dec/ioasic-irq.c
+++ b/arch/mips/dec/ioasic-irq.c
@@ -51,6 +51,14 @@ static struct irq_chip ioasic_irq_type = {
.irq_unmask = unmask_ioasic_irq,
};
+void clear_ioasic_dma_irq(unsigned int irq)
+{
+ u32 sir;
+
+ sir = ~(1 << (irq - ioasic_irq_base));
+ ioasic_write(IO_REG_SIR, sir);
+}
+
static struct irq_chip ioasic_dma_irq_type = {
.name = "IO-ASIC-DMA",
.irq_ack = ack_ioasic_irq,
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index 56ebc7f..1914e56 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -125,12 +125,16 @@ int rtc_mips_set_mmss(unsigned long nowtime)
void __init plat_time_init(void)
{
+ int ioasic_clock = 0;
u32 start, end;
int i = HZ / 8;
/* Set up the rate of periodic DS1287 interrupts. */
ds1287_set_base_clock(HZ);
+ /* On some I/O ASIC systems we have the I/O ASIC's counter. */
+ if (IOASIC)
+ ioasic_clock = dec_ioasic_clocksource_init() == 0;
if (cpu_has_counter) {
ds1287_timer_state();
while (!ds1287_timer_state())
@@ -147,9 +151,21 @@ void __init plat_time_init(void)
mips_hpt_frequency = (end - start) * 8;
printk(KERN_INFO "MIPS counter frequency %dHz\n",
mips_hpt_frequency);
- } else if (IOASIC)
- /* For pre-R4k systems we use the I/O ASIC's counter. */
- dec_ioasic_clocksource_init();
+
+ /*
+ * All R4k DECstations suffer from the CP0 Count erratum,
+ * so we can't use the timer as a clock source, and a clock
+ * event both at a time. An accurate wall clock is more
+ * important than a high-precision interval timer so only
+ * use the timer as a clock source, and not a clock event
+ * if there's no I/O ASIC counter available to serve as a
+ * clock source.
+ */
+ if (!ioasic_clock) {
+ init_r4k_clocksource();
+ mips_hpt_frequency = 0;
+ }
+ }
ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]);
}
diff --git a/arch/mips/include/asm/dec/ioasic.h b/arch/mips/include/asm/dec/ioasic.h
index 98badd6..a6e505a 100644
--- a/arch/mips/include/asm/dec/ioasic.h
+++ b/arch/mips/include/asm/dec/ioasic.h
@@ -31,8 +31,10 @@ static inline u32 ioasic_read(unsigned int reg)
return ioasic_base[reg / 4];
}
+extern void clear_ioasic_dma_irq(unsigned int irq);
+
extern void init_ioasic_irqs(int base);
-extern void dec_ioasic_clocksource_init(void);
+extern int dec_ioasic_clocksource_init(void);
#endif /* __ASM_DEC_IOASIC_H */
diff --git a/arch/mips/kernel/csrc-ioasic.c b/arch/mips/kernel/csrc-ioasic.c
index 87e88fe..6cbbf6e 100644
--- a/arch/mips/kernel/csrc-ioasic.c
+++ b/arch/mips/kernel/csrc-ioasic.c
@@ -37,7 +37,7 @@ static struct clocksource clocksource_dec = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
-void __init dec_ioasic_clocksource_init(void)
+int __init dec_ioasic_clocksource_init(void)
{
unsigned int freq;
u32 start, end;
@@ -56,8 +56,14 @@ void __init dec_ioasic_clocksource_init(void)
end = dec_ioasic_hpt_read(&clocksource_dec);
freq = (end - start) * 8;
+
+ /* An early revision of the I/O ASIC didn't have the counter. */
+ if (!freq)
+ return -ENXIO;
+
printk(KERN_INFO "I/O ASIC clock frequency %dHz\n", freq);
clocksource_dec.rating = 200 + freq / 10000000;
clocksource_register_hz(&clocksource_dec, freq);
+ return 0;
}
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index c2e5d74..5969f1e 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -99,7 +99,9 @@ static void cmp_init_secondary(void)
c->core = (read_c0_ebase() >> 1) & 0x1ff;
#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
- c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE;
+ if (cpu_has_mipsmt)
+ c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) &
+ TCBIND_CURVPE;
#endif
#ifdef CONFIG_MIPS_MT_SMTC
c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
@@ -177,9 +179,16 @@ void __init cmp_smp_setup(void)
}
if (cpu_has_mipsmt) {
- unsigned int nvpe, mvpconf0 = read_c0_mvpconf0();
+ unsigned int nvpe = 1;
+#ifdef CONFIG_MIPS_MT_SMP
+ unsigned int mvpconf0 = read_c0_mvpconf0();
+
+ nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+#elif defined(CONFIG_MIPS_MT_SMTC)
+ unsigned int mvpconf0 = read_c0_mvpconf0();
nvpe = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+#endif
smp_num_siblings = nvpe;
}
pr_info("Detected %i available secondary CPU(s)\n", ncpu);
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index faf84c5..59b2b3c 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1368,7 +1368,7 @@ out_einval:
}
static DEVICE_ATTR_RW(ntcs);
-static struct attribute vpe_attrs[] = {
+static struct attribute *vpe_attrs[] = {
&dev_attr_kill.attr,
&dev_attr_ntcs.attr,
NULL,
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
index 3d86ffe..94edc9c 100644
--- a/drivers/net/ethernet/amd/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -725,6 +725,7 @@ static irqreturn_t lance_dma_merr_int(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
+ clear_ioasic_dma_irq(irq);
printk(KERN_ERR "%s: DMA error\n", dev->name);
return IRQ_HANDLED;
}
OpenPOWER on IntegriCloud