summaryrefslogtreecommitdiff
path: root/arch/openrisc/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/openrisc/kernel/time.c')
-rw-r--r--arch/openrisc/kernel/time.c107
1 files changed, 54 insertions, 53 deletions
diff --git a/arch/openrisc/kernel/time.c b/arch/openrisc/kernel/time.c
index 7c52e9494a8d..764c7bfb5df3 100644
--- a/arch/openrisc/kernel/time.c
+++ b/arch/openrisc/kernel/time.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* OpenRISC time.c
*
@@ -7,11 +8,6 @@
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
*/
#include <linux/kernel.h>
@@ -24,11 +20,21 @@
#include <linux/clockchips.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/of_clk.h>
#include <asm/cpuinfo.h>
+#include <asm/time.h>
-static int openrisc_timer_set_next_event(unsigned long delta,
- struct clock_event_device *dev)
+irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs);
+
+/* Test the timer ticks to count, used in sync routine */
+inline void openrisc_timer_set(unsigned long count)
+{
+ mtspr(SPR_TTCR, count);
+}
+
+/* Set the timer to trigger in delta cycles */
+inline void openrisc_timer_set_next(unsigned long delta)
{
u32 c;
@@ -44,31 +50,13 @@ static int openrisc_timer_set_next_event(unsigned long delta,
* Keep timer in continuous mode always.
*/
mtspr(SPR_TTMR, SPR_TTMR_CR | SPR_TTMR_IE | c);
-
- return 0;
}
-static void openrisc_timer_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int openrisc_timer_set_next_event(unsigned long delta,
+ struct clock_event_device *dev)
{
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- pr_debug(KERN_INFO "%s: periodic\n", __func__);
- BUG();
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- pr_debug(KERN_INFO "%s: oneshot\n", __func__);
- break;
- case CLOCK_EVT_MODE_UNUSED:
- pr_debug(KERN_INFO "%s: unused\n", __func__);
- break;
- case CLOCK_EVT_MODE_SHUTDOWN:
- pr_debug(KERN_INFO "%s: shutdown\n", __func__);
- break;
- case CLOCK_EVT_MODE_RESUME:
- pr_debug(KERN_INFO "%s: resume\n", __func__);
- break;
- }
+ openrisc_timer_set_next(delta);
+ return 0;
}
/* This is the clock event device based on the OR1K tick timer.
@@ -76,14 +64,32 @@ static void openrisc_timer_set_mode(enum clock_event_mode mode,
* timers) we cannot enable the PERIODIC feature. The tick timer can run using
* one-shot events, so no problem.
*/
+static DEFINE_PER_CPU(struct clock_event_device, clockevent_openrisc_timer);
-static struct clock_event_device clockevent_openrisc_timer = {
- .name = "openrisc_timer_clockevent",
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .rating = 300,
- .set_next_event = openrisc_timer_set_next_event,
- .set_mode = openrisc_timer_set_mode,
-};
+void openrisc_clockevent_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *evt =
+ &per_cpu(clockevent_openrisc_timer, cpu);
+ struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[cpu];
+
+ mtspr(SPR_TTMR, SPR_TTMR_CR);
+
+#ifdef CONFIG_SMP
+ evt->broadcast = tick_broadcast;
+#endif
+ evt->name = "openrisc_timer_clockevent",
+ evt->features = CLOCK_EVT_FEAT_ONESHOT,
+ evt->rating = 300,
+ evt->set_next_event = openrisc_timer_set_next_event,
+
+ evt->cpumask = cpumask_of(cpu);
+
+ /* We only have 28 bits */
+ clockevents_config_and_register(evt, cpuinfo->clock_frequency,
+ 100, 0x0fffffff);
+
+}
static inline void timer_ack(void)
{
@@ -107,7 +113,9 @@ static inline void timer_ack(void)
irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
- struct clock_event_device *evt = &clockevent_openrisc_timer;
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *evt =
+ &per_cpu(clockevent_openrisc_timer, cpu);
timer_ack();
@@ -123,27 +131,15 @@ irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs)
return IRQ_HANDLED;
}
-static __init void openrisc_clockevent_init(void)
-{
- clockevent_openrisc_timer.cpumask = cpumask_of(0);
-
- /* We only have 28 bits */
- clockevents_config_and_register(&clockevent_openrisc_timer,
- cpuinfo.clock_frequency,
- 100, 0x0fffffff);
-
-}
-
-/**
+/*
* Clocksource: Based on OpenRISC timer/counter
*
* This sets up the OpenRISC Tick Timer as a clock source. The tick timer
* is 32 bits wide and runs at the CPU clock frequency.
*/
-
-static cycle_t openrisc_timer_read(struct clocksource *cs)
+static u64 openrisc_timer_read(struct clocksource *cs)
{
- return (cycle_t) mfspr(SPR_TTCR);
+ return (u64) mfspr(SPR_TTCR);
}
static struct clocksource openrisc_timer = {
@@ -156,7 +152,9 @@ static struct clocksource openrisc_timer = {
static int __init openrisc_timer_init(void)
{
- if (clocksource_register_hz(&openrisc_timer, cpuinfo.clock_frequency))
+ struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[smp_processor_id()];
+
+ if (clocksource_register_hz(&openrisc_timer, cpuinfo->clock_frequency))
panic("failed to register clocksource");
/* Enable the incrementer: 'continuous' mode with interrupt disabled */
@@ -175,4 +173,7 @@ void __init time_init(void)
openrisc_timer_init();
openrisc_clockevent_init();
+
+ of_clk_init(NULL);
+ timer_probe();
}