Commit ad9366e0 authored by Gilles Chanteperdrix's avatar Gilles Chanteperdrix Committed by Philippe Gerum

clocksource: sp804: ipipe: add support for user-visible TSC

Expose the clocksource to userland processes via the ARM-specific
user-TSC interface.
parent b9f77b00
......@@ -30,11 +30,25 @@
#include <linux/of_clk.h>
#include <linux/of_irq.h>
#include <linux/sched_clock.h>
#include <linux/module.h>
#include <linux/ipipe.h>
#include <linux/ipipe_tickdev.h>
#include <clocksource/timer-sp804.h>
#include "timer-sp.h"
#ifdef CONFIG_IPIPE
static struct __ipipe_tscinfo tsc_info = {
.type = IPIPE_TSC_TYPE_FREERUNNING_COUNTDOWN,
.u = {
{
.mask = 0xffffffff,
},
},
};
#endif /* CONFIG_IPIPE */
static long __init sp804_get_clock_rate(struct clk *clk)
{
long rate;
......@@ -79,6 +93,7 @@ void __init sp804_timer_disable(void __iomem *base)
}
int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
unsigned long phys,
const char *name,
struct clk *clk,
int use_sched_clock)
......@@ -113,6 +128,12 @@ int __init __sp804_clocksource_and_sched_clock_init(void __iomem *base,
sched_clock_register(sp804_read, 32, rate);
}
#ifdef CONFIG_IPIPE
tsc_info.freq = rate;
tsc_info.counter_vaddr = (unsigned long)base + TIMER_VALUE;
tsc_info.u.counter_paddr = phys + TIMER_VALUE;
__ipipe_tsc_register(&tsc_info);
#endif
return 0;
}
......@@ -227,6 +248,7 @@ static int __init sp804_of_init(struct device_node *np)
u32 irq_num = 0;
struct clk *clk1, *clk2;
const char *name = of_get_property(np, "compatible", NULL);
struct resource res;
base = of_iomap(np, 0);
if (!base)
......@@ -260,6 +282,9 @@ static int __init sp804_of_init(struct device_node *np)
if (irq <= 0)
goto err;
if (of_address_to_resource(np, 0, &res))
res.start = 0;
of_property_read_u32(np, "arm,sp804-has-irq", &irq_num);
if (irq_num == 2) {
......@@ -267,7 +292,7 @@ static int __init sp804_of_init(struct device_node *np)
if (ret)
goto err;
ret = __sp804_clocksource_and_sched_clock_init(base, name, clk1, 1);
ret = __sp804_clocksource_and_sched_clock_init(base, res.start, name, clk1, 1);
if (ret)
goto err;
} else {
......@@ -277,7 +302,7 @@ static int __init sp804_of_init(struct device_node *np)
goto err;
ret =__sp804_clocksource_and_sched_clock_init(base + TIMER_2_BASE,
name, clk2, 1);
res.start, name, clk2, 1);
if (ret)
goto err;
}
......@@ -297,6 +322,7 @@ static int __init integrator_cp_of_init(struct device_node *np)
int irq, ret = -EINVAL;
const char *name = of_get_property(np, "compatible", NULL);
struct clk *clk;
struct resource res;
base = of_iomap(np, 0);
if (!base) {
......@@ -316,8 +342,11 @@ static int __init integrator_cp_of_init(struct device_node *np)
if (init_count == 2 || !of_device_is_available(np))
goto err;
if (of_address_to_resource(np, 0, &res))
res.start = 0;
if (!init_count) {
ret = __sp804_clocksource_and_sched_clock_init(base, name, clk, 0);
ret = __sp804_clocksource_and_sched_clock_init(base, res.start, name, clk, 0);
if (ret)
goto err;
} else {
......
......@@ -5,20 +5,23 @@
struct clk;
int __sp804_clocksource_and_sched_clock_init(void __iomem *,
unsigned long phys,
const char *, struct clk *, int);
int __sp804_clockevents_init(void __iomem *, unsigned int,
struct clk *, const char *);
void sp804_timer_disable(void __iomem *);
static inline void sp804_clocksource_init(void __iomem *base, const char *name)
static inline void sp804_clocksource_init(void __iomem *base, unsigned long phys,
const char *name)
{
__sp804_clocksource_and_sched_clock_init(base, name, NULL, 0);
__sp804_clocksource_and_sched_clock_init(base, phys, name, NULL, 0);
}
static inline void sp804_clocksource_and_sched_clock_init(void __iomem *base,
unsigned long phys,
const char *name)
{
__sp804_clocksource_and_sched_clock_init(base, name, NULL, 1);
__sp804_clocksource_and_sched_clock_init(base, phys, name, NULL, 1);
}
static inline void sp804_clockevents_init(void __iomem *base, unsigned int irq, const char *name)
......
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