blob: c93fac9fa0a951afc1cdc5224d733eb909ec0a2b [file] [log] [blame]
/**
* OMAP gptimer based event monitor driver for oprofile
*
* Copyright (C) 2009 Nokia Corporation
* Author: Siarhei Siamashka <siarhei.siamashka@nokia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/types.h>
#include <linux/oprofile.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <mach/dmtimer.h>
#include "op_counter.h"
#include "op_arm_model.h"
static struct omap_dm_timer *gptimer;
static int gptimer_init(void)
{
return 0;
}
static int gptimer_setup(void)
{
return 0;
}
static irqreturn_t gptimer_interrupt(int irq, void *arg)
{
omap_dm_timer_write_status(gptimer, OMAP_TIMER_INT_OVERFLOW);
oprofile_add_sample(get_irq_regs(), 0);
return IRQ_HANDLED;
}
static int gptimer_start(void)
{
int err;
u32 count = counter_config[0].count;
BUG_ON(gptimer != NULL);
/* First try to request timers from CORE power domain for OMAP3 */
if (cpu_is_omap34xx()) {
gptimer = omap_dm_timer_request_specific(10);
if (gptimer == NULL)
gptimer = omap_dm_timer_request_specific(11);
}
/* Just any timer would be fine */
if (gptimer == NULL)
gptimer = omap_dm_timer_request();
if (gptimer == NULL)
return -ENODEV;
omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
err = request_irq(omap_dm_timer_get_irq(gptimer), gptimer_interrupt,
IRQF_DISABLED, "oprofile gptimer", NULL);
if (err) {
omap_dm_timer_free(gptimer);
gptimer = NULL;
printk(KERN_ERR "oprofile: unable to request gptimer IRQ\n");
return err;
}
if (count < 1)
count = 1;
omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - count);
omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
return 0;
}
static void gptimer_stop(void)
{
omap_dm_timer_set_int_enable(gptimer, 0);
free_irq(omap_dm_timer_get_irq(gptimer), NULL);
omap_dm_timer_free(gptimer);
gptimer = NULL;
}
struct op_arm_model_spec op_omap_gptimer_spec = {
.init = gptimer_init,
.num_counters = 1,
.setup_ctrs = gptimer_setup,
.start = gptimer_start,
.stop = gptimer_stop,
.name = "timer",
};