From: Carsten Emde <C.Emde@osadl.org> Date: Sun, 31 May 2015 12:32:11 +0100 Subject: Clocksource: Add sched_clock to Atmel TCB clocksource The default sched_clock provides a maximum resolution of 1 ms which normally is not sufficient to investigate scheduling related irregularities - more so, if a low-latency or even a real-time kernel is used. Therefore, register the Atmel TCB clocksource that provides a resolution of 63 ns as sched_clock. Signed-off-by: Carsten Emde <C.Emde@osadl.org> --- drivers/clocksource/tcb_clksrc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) Index: linux-3.18.13-rt10-r7s4/drivers/clocksource/tcb_clksrc.c =================================================================== @ linux-3.18.13-rt10-r7s4/drivers/clocksource/tcb_clksrc.c:13 @ #include <linux/io.h> #include <linux/platform_device.h> #include <linux/atmel_tc.h> +#include <linux/sched_clock.h> +#define DEBUG /* * We're configured to use a specific TC block, one that's not hooked @ linux-3.18.13-rt10-r7s4/drivers/clocksource/tcb_clksrc.c:74 @ static struct clocksource clksrc = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static u64 sched_clock_get_cycles(void) +{ + return (u64) clksrc.read(NULL); +} + #ifdef CONFIG_GENERIC_CLOCKEVENTS struct tc_clkevt_device { @ linux-3.18.13-rt10-r7s4/drivers/clocksource/tcb_clksrc.c:283 @ static int __init tcb_clksrc_init(void) int clk32k_divisor_idx = -1; int i; int ret; + unsigned long flags; tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK); if (!tc) { @ linux-3.18.13-rt10-r7s4/drivers/clocksource/tcb_clksrc.c:350 @ static int __init tcb_clksrc_init(void) if (ret) goto err_disable_t1; + local_irq_save(flags); + sched_clock_register(sched_clock_get_cycles, 32, divided_rate); + local_irq_restore(flags); + /* channel 2: periodic and oneshot timer support */ ret = setup_clkevents(tc, clk32k_divisor_idx); if (ret)