Omap timestamp.stp

// omap_timestamp tapset

global trick

%{ %}
 * 1) include <../include/linux/clk.h>
 * 2) include <../arch/arm/include/asm/io.h>
 * 3) include <../arch/arm/plat-omap/include/plat/dmtimer.h>
 * 4) include <../arch/arm/plat-omap/include/plat/clock.h>

// Trick to force dependencies resolution when using plain C functions function timestamp_init { trick = 1; }

%{
 * 1) define TIMER32K_FREQ	32768

struct omap_dm_timer *gptimer;

/* * timer_init_32k * * Dummy init for 32k timer that simply returns the frequency of 32k timer timer. */ static inline int timer_init_32k(void) {	return TIMER32K_FREQ; }

/* * timer_init_gptimer * * Allocate and initialised a gptimer. On success return frequency of the * timer, otherwise return 0. */ unsigned long timer_init_gptimer(void) {	int prescaler = 0; unsigned long freq; struct clk *sys_clk;

gptimer = omap_dm_timer_request; if (!gptimer) return 0; if (omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK) < 0) return 0;

omap_dm_timer_set_prescaler(gptimer, prescaler);

sys_clk = clk_get(NULL, "sys_clkin_ck"); if (!sys_clk) return 0;

freq = (clk_get_rate(sys_clk) >> (prescaler + 1)); clk_put(sys_clk);

omap_dm_timer_set_load_start(gptimer, 1, 0);

return freq; }

/* * timer_free_gptimer * * Free the gptimer that was allocated. */ void timer_free_gptimer(void) {	if (gptimer) { omap_dm_timer_stop(gptimer); omap_dm_timer_free(gptimer); gptimer = 0; } }

/* * timer_get_ticks_gptimer * * Returns current tick count of a gptimer. */ static inline u32 timer_get_ticks_gptimer(void) {	if (gptimer) return omap_dm_timer_read_counter(gptimer); else return 0; }

/* * timer_ticksnsec * * @ticks - tick count * @freq - timer frequency * * Converts timer ticks into nanoseconds. */ static inline u64 timer_ticks2nsec(u32 ticks, unsigned long freq) {	return (u64)(((u64)ticks * (u64)(NSEC_PER_SEC/freq))); }

/* * timer_get_ticks_32k * * Returns current value of OMAP free running 32kHz timer counter. Unit is * ticks of 32kHz timer (i.e. 1/32768 sec). */ static inline u32 timer_get_ticks_32k(void) {	return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10); return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10); return omap_readl(OMAP54XX_32KSYNCT_BASE + 0x30); #error " OMAP RELEASE FAMILY IS NOT SPECIFIED, CONFIG_ARCH_OMAPX needed" } %}
 * 1) if defined(CONFIG_ARCH_OMAP3)
 * 1) elif defined(CONFIG_ARCH_OMAP4)
 * 1) elif defined(CONFIG_ARCH_OMAP5)
 * 1) else
 * 1) endif

function get_32k:long %{ /* pure */ /* unprivileged */ THIS->__retvalue = timer_get_ticks_32k; %}

// gettimeofday timestamping, which is internally based on 32kHz. Unit is in us: //  - you can use it directly: do probe begin { ref = get_timeofday_ref } then you can use get_timeofday(ref) //  - another solution is to read 32kHz and gettimeofday at beginning to compute the offset between the 2, then use 32kHz in kernel and gettimeofday in userspace %{ static inline u32 get_timeofday_ref(void) {	struct timeval tv; do_gettimeofday(&tv); return tv.tv_sec; } %}

function get_timeofday_ref:long %{ THIS->__retvalue = get_timeofday_ref; %}

%{ static inline u32 get_timeofday(u32 ref) {	struct timeval tv; do_gettimeofday(&tv); return (tv.tv_sec - ref) * 1000000 + tv.tv_usec; } %}

function get_timeofday:long (ref:long) %{ THIS->__retvalue = get_timeofday(THIS->ref); %}

function elapsed_t_mod32k(time2, time1) { return ((time2-time1) % (1 << 32)); }

// this function is used to do "perf" tool timestamping. get_32k + this function help computing time offset between the tools function sys_sched_clock:long %{ /* pure */ /* unprivileged */ THIS->__retvalue = (uint64_t) sched_clock; %}