Skip to content

Commit

Permalink
dw_apb_timer_of.c: Remove parts that were picoxcell-specific
Browse files Browse the repository at this point in the history
It seems we made a mistake when creating dw_apb_timer_of.c:
picoxcell sched_clock had parts that were not related to
dw_apb_timer, yet we moved them to dw_apb_timer_of, and tried to
use them on socfpga.

This results in system where user/system time is not measured
properly, as demonstrated by

    time dd if=/dev/urandom of=/dev/zero bs=100000 count=100

So this patch switches sched_clock to hardware that exists on both
platforms, and adds missing of_node_put() in dw_apb_timer_init().

Signed-off-by: Pavel Machek <pavel@denx.de>
Acked-by: Jamie Iles <jamie@jamieiles.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
  • Loading branch information
Pavel Machek authored and John Stultz committed May 28, 2013
1 parent 35b2108 commit 55a68c2
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 37 deletions.
2 changes: 0 additions & 2 deletions arch/arm/mach-picoxcell/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,4 @@

#include <asm/mach/time.h>

extern void dw_apb_timer_init(void);

#endif /* __PICOXCELL_COMMON_H__ */
6 changes: 0 additions & 6 deletions drivers/clocksource/dw_apb_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@
#define APBT_MIN_PERIOD 4
#define APBT_MIN_DELTA_USEC 200

#define APBTMR_N_LOAD_COUNT 0x00
#define APBTMR_N_CURRENT_VALUE 0x04
#define APBTMR_N_CONTROL 0x08
#define APBTMR_N_EOI 0x0c
#define APBTMR_N_INT_STATUS 0x10

#define APBTMRS_INT_STATUS 0xa0
#define APBTMRS_EOI 0xa4
#define APBTMRS_RAW_INT_STATUS 0xa8
Expand Down
52 changes: 23 additions & 29 deletions drivers/clocksource/dw_apb_timer_of.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ static void add_clockevent(struct device_node *event_timer)
dw_apb_clockevent_register(ced);
}

static void __iomem *sched_io_base;

/* This is actually same as __apbt_read_clocksource(), but with
different interface */
static u32 read_sched_clock_sptimer(void)
{
return ~__raw_readl(sched_io_base + APBTMR_N_CURRENT_VALUE);
}

static void add_clocksource(struct device_node *source_timer)
{
void __iomem *iobase;
Expand All @@ -71,41 +80,27 @@ static void add_clocksource(struct device_node *source_timer)

dw_apb_clocksource_start(cs);
dw_apb_clocksource_register(cs);
}

static void __iomem *sched_io_base;

static u32 read_sched_clock(void)
{
return __raw_readl(sched_io_base);
sched_io_base = iobase;
setup_sched_clock(read_sched_clock_sptimer, 32, rate);
}

static const struct of_device_id sptimer_ids[] __initconst = {
{ .compatible = "picochip,pc3x2-rtc" },
static const struct of_device_id osctimer_ids[] __initconst = {
{ .compatible = "picochip,pc3x2-timer" },
{ .compatible = "snps,dw-apb-timer-osc" },
{ .compatible = "snps,dw-apb-timer-sp" },
{ /* Sentinel */ },
{ /* Sentinel */ },
};

static void init_sched_clock(void)
{
struct device_node *sched_timer;
u32 rate;

sched_timer = of_find_matching_node(NULL, sptimer_ids);
if (!sched_timer)
panic("No RTC for sched clock to use");
/*
You don't have to use dw_apb_timer for scheduler clock,
this should also work fine on arm:
timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
of_node_put(sched_timer);
twd_local_timer_of_register();
arch_timer_of_register();
arch_timer_sched_clock_init();
*/

setup_sched_clock(read_sched_clock, 32, rate);
}

static const struct of_device_id osctimer_ids[] __initconst = {
{ .compatible = "picochip,pc3x2-timer" },
{ .compatible = "snps,dw-apb-timer-osc" },
{},
};

void __init dw_apb_timer_init(void)
{
Expand All @@ -121,7 +116,6 @@ void __init dw_apb_timer_init(void)
panic("No timer for clocksource");
add_clocksource(source_timer);

of_node_put(event_timer);
of_node_put(source_timer);

init_sched_clock();
}
6 changes: 6 additions & 0 deletions include/linux/dw_apb_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
#include <linux/clocksource.h>
#include <linux/interrupt.h>

#define APBTMR_N_LOAD_COUNT 0x00
#define APBTMR_N_CURRENT_VALUE 0x04
#define APBTMR_N_CONTROL 0x08
#define APBTMR_N_EOI 0x0c
#define APBTMR_N_INT_STATUS 0x10

#define APBTMRS_REG_SIZE 0x14

struct dw_apb_timer {
Expand Down

0 comments on commit 55a68c2

Please sign in to comment.