Commit 251efb26 authored by Gilles Chanteperdrix's avatar Gilles Chanteperdrix Committed by Philippe Gerum

clocksource: imx/gpt: ipipe: add support for user-visible TSC

Expose the clocksource to userland processes via the ARM-specific
user-TSC interface.
parent ad9366e0
......@@ -16,6 +16,8 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/ipipe.h>
#include <linux/ipipe_tickdev.h>
#include <soc/imx/timer.h>
/*
......@@ -61,6 +63,9 @@
struct imx_timer {
enum imx_gpt_type type;
#ifdef CONFIG_IPIPE
unsigned long pbase;
#endif
void __iomem *base;
int irq;
struct clk *clk_per;
......@@ -265,6 +270,30 @@ static int mxc_set_oneshot(struct clock_event_device *ced)
return 0;
}
#ifdef CONFIG_IPIPE
static struct imx_timer *global_imx_timer;
static void mxc_timer_ack(void)
{
global_imx_timer->gpt->gpt_irq_acknowledge(global_imx_timer);
}
static struct __ipipe_tscinfo tsc_info = {
.type = IPIPE_TSC_TYPE_FREERUNNING,
.u = {
{
.mask = 0xffffffff,
},
},
};
static struct ipipe_timer mxc_itimer = {
.ack = mxc_timer_ack,
};
#endif
/*
* IRQ handler for the timer
*/
......@@ -276,7 +305,8 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
tstat = readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat);
imxtm->gpt->gpt_irq_acknowledge(imxtm);
if (!clockevent_ipipe_stolen(ced))
imxtm->gpt->gpt_irq_acknowledge(imxtm);
ced->event_handler(ced);
......@@ -297,6 +327,9 @@ static int __init mxc_clockevent_init(struct imx_timer *imxtm)
ced->rating = 200;
ced->cpumask = cpumask_of(0);
ced->irq = imxtm->irq;
#ifdef CONFIG_IPIPE
ced->ipipe_timer = &mxc_itimer;
#endif
clockevents_config_and_register(ced, clk_get_rate(imxtm->clk_per),
0xff, 0xfffffffe);
......@@ -436,6 +469,17 @@ static int __init _mxc_timer_init(struct imx_timer *imxtm)
if (ret)
return ret;
#ifdef CONFIG_IPIPE
tsc_info.u.counter_paddr = imxtm->pbase + imxtm->gpt->reg_tcn;
tsc_info.counter_vaddr = (unsigned long)imxtm->base + imxtm->gpt->reg_tcn;
tsc_info.freq = clk_get_rate(imxtm->clk_per);
__ipipe_tsc_register(&tsc_info);
mxc_itimer.irq = imxtm->irq;
mxc_itimer.freq = clk_get_rate(imxtm->clk_per);
mxc_itimer.min_delay_ticks = ipipe_timer_ns2ticks(&mxc_itimer, 2000);
global_imx_timer = imxtm;
#endif /* CONFIG_IPIPE */
return mxc_clockevent_init(imxtm);
}
......@@ -451,6 +495,9 @@ void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type)
imxtm->base = ioremap(pbase, SZ_4K);
BUG_ON(!imxtm->base);
#ifdef CONFIG_IPIPE
imxtm->pbase = pbase;
#endif
imxtm->type = type;
imxtm->irq = irq;
......@@ -462,6 +509,7 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t
{
struct imx_timer *imxtm;
static int initialized;
struct resource res;
int ret;
/* Support one instance only */
......@@ -480,6 +528,13 @@ static int __init mxc_timer_init_dt(struct device_node *np, enum imx_gpt_type t
if (imxtm->irq <= 0)
return -EINVAL;
if (of_address_to_resource(np, 0, &res))
res.start = 0;
#ifdef CONFIG_IPIPE
imxtm->pbase = res.start;
#endif
imxtm->clk_ipg = of_clk_get_by_name(np, "ipg");
/* Try osc_per first, and fall back to per otherwise */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment