aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2014-03-05 11:35:53 +0000
committerPaul Burton <paul.burton@imgtec.com>2014-05-02 16:39:11 +0100
commit414408d0eedd782a397ba89fd8f732ffbd3acde8 (patch)
treea747abf36d79d04d5a916a4e6fc230ccdf1776e7
parentMIPS: mark GIC clockevent device with CLOCK_EVT_FEAT_C3STOP (diff)
downloadlinux-dev-414408d0eedd782a397ba89fd8f732ffbd3acde8.tar.xz
linux-dev-414408d0eedd782a397ba89fd8f732ffbd3acde8.zip
MIPS: allow GIC clockevent device config from other CPUs
This patch allows the GIC clockevent device for a CPU to be configured by another CPU. This makes GIC clockevent devices suitable for use as the tick broadcast device, where formerly the GIC timer local to the configuring CPU would have been configured incorrectly. Signed-off-by: Paul Burton <paul.burton@imgtec.com>
-rw-r--r--arch/mips/include/asm/gic.h1
-rw-r--r--arch/mips/kernel/cevt-gic.c2
-rw-r--r--arch/mips/kernel/irq-gic.c15
3 files changed, 17 insertions, 1 deletions
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 082716690589..10f6a99f92c2 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -380,6 +380,7 @@ extern unsigned int gic_compare_int (void);
extern cycle_t gic_read_count(void);
extern cycle_t gic_read_compare(void);
extern void gic_write_compare(cycle_t cnt);
+extern void gic_write_cpu_compare(cycle_t cnt, int cpu);
extern void gic_send_ipi(unsigned int intr);
extern unsigned int plat_ipi_call_int_xlate(unsigned int);
extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c
index 925bae559067..6093716980b9 100644
--- a/arch/mips/kernel/cevt-gic.c
+++ b/arch/mips/kernel/cevt-gic.c
@@ -26,7 +26,7 @@ static int gic_next_event(unsigned long delta, struct clock_event_device *evt)
cnt = gic_read_count();
cnt += (u64)delta;
- gic_write_compare(cnt);
+ gic_write_cpu_compare(cnt, cpumask_first(evt->cpumask));
res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0;
return res;
}
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index 8520dad6d4e3..88e4c323382c 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -54,6 +54,21 @@ void gic_write_compare(cycle_t cnt)
(int)(cnt & 0xffffffff));
}
+void gic_write_cpu_compare(cycle_t cnt, int cpu)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
+ GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
+ (int)(cnt >> 32));
+ GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
+ (int)(cnt & 0xffffffff));
+
+ local_irq_restore(flags);
+}
+
cycle_t gic_read_compare(void)
{
unsigned int hi, lo;