@@ -6,6 +6,7 @@ config CSKY
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_SYNC_DMA_FOR_CPU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
+ select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_WANT_FRAME_POINTERS if !CPU_CK610
@@ -19,6 +20,7 @@ config CSKY
select IRQ_DOMAIN
select HANDLE_DOMAIN_IRQ
select DW_APB_TIMER_OF
+ select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_IOREMAP
select GENERIC_LIB_ASHLDI3
select GENERIC_LIB_ASHRDI3
@@ -8,6 +8,7 @@
#include <linux/kernel_stat.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
+#include <linux/clockchips.h>
#include <linux/percpu.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -32,6 +33,7 @@ enum ipi_message_type {
IPI_RESCHEDULE,
IPI_CALL_FUNC,
IPI_IRQ_WORK,
+ IPI_TIMER,
IPI_MAX
};
@@ -67,6 +69,13 @@ static irqreturn_t handle_ipi(int irq, void *dev)
irq_work_run();
}
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+ if (ops & (1 << IPI_TIMER)) {
+ stats[IPI_TIMER]++;
+ tick_receive_broadcast();
+ }
+#endif
+
BUG_ON((ops >> IPI_MAX) != 0);
}
@@ -102,6 +111,7 @@ static const char * const ipi_names[] = {
[IPI_RESCHEDULE] = "Rescheduling interrupts",
[IPI_CALL_FUNC] = "Function call interrupts",
[IPI_IRQ_WORK] = "Irq work interrupts",
+ [IPI_TIMER] = "Timer broadcast interrupts",
};
int arch_show_interrupts(struct seq_file *p, int prec)
@@ -130,6 +140,13 @@ void arch_send_call_function_single_ipi(int cpu)
send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
}
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+void tick_broadcast(const struct cpumask *mask)
+{
+ send_ipi_message(mask, IPI_TIMER);
+}
+#endif
+
static void ipi_stop(void *unused)
{
while (1);