diff options
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/clock.c | 84 | ||||
-rw-r--r-- | cpu/arm920t/Makefile | 2 | ||||
-rw-r--r-- | cpu/arm920t/imx/interrupts.c | 52 | ||||
-rw-r--r-- | include/clock.h | 29 |
5 files changed, 133 insertions, 35 deletions
diff --git a/common/Makefile b/common/Makefile index 99f514e44b..854b085839 100644 --- a/common/Makefile +++ b/common/Makefile @@ -84,6 +84,7 @@ obj-y += cmd_universe.o obj-y += exports.o obj-y += main.o obj-y += s_record.o +obj-y += clock.o # obj-y += spartan3.o # obj-y += spartan2.o diff --git a/common/clock.c b/common/clock.c new file mode 100644 index 0000000000..2e4e9d7dfc --- /dev/null +++ b/common/clock.c @@ -0,0 +1,84 @@ +#include <common.h> +#include <asm-generic/div64.h> +#include <clock.h> + +static struct clocksource *current_clock; +static uint64_t time_ns; + +/** + * get_time_ns - get current timestamp in nanoseconds + */ +uint64_t get_time_ns(void) +{ + struct clocksource *cs = current_clock; + uint64_t cycle_now, cycle_delta; + uint64_t ns_offset; + + /* read clocksource: */ + cycle_now = cs->read(); + + /* calculate the delta since the last call: */ + cycle_delta = (cycle_now - cs->cycle_last) & cs->mask; + + /* convert to nanoseconds: */ + ns_offset = cyc2ns(cs, cycle_delta); + + cs->cycle_last = cycle_now; + + time_ns += ns_offset; + return time_ns; +} + +/** + * clocksource_hz2mult - calculates mult from hz and shift + * @hz: Clocksource frequency in Hz + * @shift_constant: Clocksource shift factor + * + * Helper functions that converts a hz counter + * frequency to a timsource multiplier, given the + * clocksource shift value + */ +uint32_t clocksource_hz2mult(uint32_t hz, uint32_t shift_constant) +{ + /* hz = cyc/(Billion ns) + * mult/2^shift = ns/cyc + * mult = ns/cyc * 2^shift + * mult = 1Billion/hz * 2^shift + * mult = 1000000000 * 2^shift / hz + * mult = (1000000000<<shift) / hz + */ + uint64_t tmp = ((uint64_t)1000000000) << shift_constant; + + tmp += hz/2; /* round for do_div */ + do_div(tmp, hz); + + return (uint32_t)tmp; +} + +int is_timeout(uint64_t start_ns, uint64_t time_offset_ns) +{ + if (start_ns + time_offset_ns < get_time_ns()) + return 1; + else + return 0; +} + +void udelay(unsigned long usecs) +{ + uint64_t start = get_time_ns(); + + while(!is_timeout(start, usecs * 1000)); +} + +void mdelay(unsigned long msecs) +{ + uint64_t start = get_time_ns(); + + while(!is_timeout(start, msecs * 1000000)); +} + +int init_clock(struct clocksource *cs) +{ + current_clock = cs; + return 0; +} diff --git a/cpu/arm920t/Makefile b/cpu/arm920t/Makefile index 79228b62e4..a05788504c 100644 --- a/cpu/arm920t/Makefile +++ b/cpu/arm920t/Makefile @@ -1,3 +1,3 @@ obj-y += cpu.o interrupts.o -head-y += start.o +obj-y += start.o obj-y += imx/
\ No newline at end of file diff --git a/cpu/arm920t/imx/interrupts.c b/cpu/arm920t/imx/interrupts.c index 633d345d82..cad88564dd 100644 --- a/cpu/arm920t/imx/interrupts.c +++ b/cpu/arm920t/imx/interrupts.c @@ -30,11 +30,23 @@ */ #include <common.h> -#if defined (CONFIG_IMX) - +#include <clock.h> #include <arm920t.h> #include <asm/arch/imx-regs.h> +#define CLOCK_TICK_RATE 1000000 + +uint64_t imx_clocksource_read(void) +{ + return TCN1; +} + +static struct clocksource cs = { + .read = imx_clocksource_read, + .mask = 0xffffffff, + .shift = 10, +}; + int interrupt_init (void) { int i; @@ -44,39 +56,13 @@ int interrupt_init (void) TPRER1 = get_PERCLK1() / 1000000; /* 1 MHz */ TCTL1 |= TCTL_FRR | (1<<1); /* Freerun Mode, PERCLK1 input */ - reset_timer_masked(); - - return (0); -} - -/* - * timer without interrupts - */ - -void reset_timer (void) -{ - reset_timer_masked (); -} - -ulong get_timer (ulong base) -{ - return get_timer_masked (); -} - -void set_timer (ulong t) -{ - /* nop */ -} - -void reset_timer_masked (void) -{ TCTL1 &= ~TCTL_TEN; TCTL1 |= TCTL_TEN; /* Enable timer */ -} -ulong get_timer_masked (void) -{ - return TCN1; + cs.mult = clocksource_hz2mult(CLOCK_TICK_RATE, cs.shift); + init_clock(&cs); + + return 0; } /* @@ -97,5 +83,3 @@ void reset_cpu (ulong ignored) while (1); /*NOTREACHED*/ } - -#endif /* defined (CONFIG_IMX) */ diff --git a/include/clock.h b/include/clock.h new file mode 100644 index 0000000000..a8920f1107 --- /dev/null +++ b/include/clock.h @@ -0,0 +1,29 @@ + +struct clocksource { + uint32_t shift; + uint32_t mult; + uint64_t (*read)(void); + uint64_t cycle_last; + uint64_t mask; + +}; + +inline uint32_t cyc2ns(struct clocksource *cs, uint64_t cycles) +{ + uint64_t ret = cycles; + ret = (ret * cs->mult) >> cs->shift; + return ret; +} + +int init_clock(struct clocksource *); + +uint64_t get_time_ns(void); + +uint32_t clocksource_hz2mult(uint32_t hz, uint32_t shift_constant); + +int is_timeout(uint64_t start_ns, uint64_t time_offset_ns); + +// void udelay(unsigned long usecs); + +void mdelay(unsigned long msecs); + |