void __iomem *mtu_base; /* ssigned by machine code */
+/*
+ * Kernel assumes that sched_clock can be called early
+ * but the MTU may not yet be initialized.
+ */
+static cycle_t nmdk_read_timer_dummy(struct clocksource *cs)
+{
+ return 0;
+}
+
/* clocksource: MTU decrements, so we negate the value being read. */
static cycle_t nmdk_read_timer(struct clocksource *cs)
{
static struct clocksource nmdk_clksrc = {
.name = "mtu_0",
.rating = 200,
- .read = nmdk_read_timer,
+ .read = nmdk_read_timer_dummy,
.mask = CLOCKSOURCE_MASK(32),
.shift = 20,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
+/*
+ * Override the global weak sched_clock symbol with this
+ * local implementation which uses the clocksource to get some
+ * better resolution when scheduling the kernel. We accept that
+ * this wraps around for now, since it is just a relative time
+ * stamp. (Inspired by OMAP implementation.)
+ */
+unsigned long long notrace sched_clock(void)
+{
+ return clocksource_cyc2ns(nmdk_clksrc.read(
+ &nmdk_clksrc),
+ nmdk_clksrc.mult,
+ nmdk_clksrc.shift);
+}
+
/* Clockevent device: use one-shot mode */
static void nmdk_clkevt_mode(enum clock_event_mode mode,
struct clock_event_device *dev)
writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift);
+ /* Now the scheduling clock is ready */
+ nmdk_clksrc.read = nmdk_read_timer;
if (clocksource_register(&nmdk_clksrc))
pr_err("timer: failed to initialize clock source %s\n",