Omap timestamp.stp
From OMAPpedia
(Difference between revisions)
| Line 1: | Line 1: | ||
<pre> | <pre> | ||
| + | // omap_timestamp tapset | ||
| + | |||
| + | global trick | ||
| + | |||
%{ | %{ | ||
| + | #include <../include/linux/clk.h> | ||
#include <../arch/arm/include/asm/io.h> | #include <../arch/arm/include/asm/io.h> | ||
| + | #include <../arch/arm/plat-omap/include/plat/dmtimer.h> | ||
| + | #include <../arch/arm/plat-omap/include/plat/clock.h> | ||
%} | %} | ||
| + | |||
| + | // Trick to force dependencies resolution when using plain C functions | ||
| + | function timestamp_init() { | ||
| + | trick = 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) | ||
| + | { | ||
| + | #if defined(CONFIG_ARCH_OMAP3) | ||
| + | return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10); | ||
| + | #elif defined(CONFIG_ARCH_OMAP4) | ||
| + | return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10); | ||
| + | #elif defined(CONFIG_ARCH_OMAP5) | ||
| + | return omap_readl(OMAP54XX_32KSYNCT_BASE + 0x30); | ||
#else | #else | ||
| - | + | #error " OMAP RELEASE FAMILY IS NOT SPECIFIED, CONFIG_ARCH_OMAPX needed" | |
#endif | #endif | ||
| + | } | ||
%} | %} | ||
function get_32k:long () %{ /* pure */ /* unprivileged */ | 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) { | function elapsed_t_mod32k(time2, time1) { | ||
| Line 35: | Line 160: | ||
} | } | ||
| - | // this function is used to "perf" tool timestamping. get_32k() + this function help computing time offset between the tools | + | // 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 */ | function sys_sched_clock:long () %{ /* pure */ /* unprivileged */ | ||
THIS->__retvalue = (uint64_t) sched_clock(); | THIS->__retvalue = (uint64_t) sched_clock(); | ||
| - | %} | + | %}</pre> |
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
| - | </pre> | + | |
[[Category:Patches and Release]] | [[Category:Patches and Release]] | ||
Latest revision as of 21:49, 5 April 2012
// omap_timestamp tapset
global trick
%{
#include <../include/linux/clk.h>
#include <../arch/arm/include/asm/io.h>
#include <../arch/arm/plat-omap/include/plat/dmtimer.h>
#include <../arch/arm/plat-omap/include/plat/clock.h>
%}
// Trick to force dependencies resolution when using plain C functions
function timestamp_init() {
trick = 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)
{
#if defined(CONFIG_ARCH_OMAP3)
return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10);
#elif defined(CONFIG_ARCH_OMAP4)
return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10);
#elif defined(CONFIG_ARCH_OMAP5)
return omap_readl(OMAP54XX_32KSYNCT_BASE + 0x30);
#else
#error " OMAP RELEASE FAMILY IS NOT SPECIFIED, CONFIG_ARCH_OMAPX needed"
#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();
%}