diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:18:27 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:19:04 +0200 |
commit | 6ac1ef482d7ae0c690f1640bf6eb818ff9a2d91e (patch) | |
tree | 021cc9f6b477146fcebe6f3be4752abfa2ba18a9 /arch/arm/mach-rpc/time.c | |
parent | 682968e0c425c60f0dde37977e5beb2b12ddc4cc (diff) | |
parent | a385ec4f11bdcf81af094c03e2444ee9b7fad2e5 (diff) |
Merge branch 'perf/core' into perf/uprobes
Merge in latest upstream (and the latest perf development tree),
to prepare for tooling changes, and also to pick up v3.4 MM
changes that the uprobes code needs to take care of.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/arm/mach-rpc/time.c')
-rw-r--r-- | arch/arm/mach-rpc/time.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c new file mode 100644 index 00000000000..581fca934bb --- /dev/null +++ b/arch/arm/mach-rpc/time.c @@ -0,0 +1,95 @@ +/* + * linux/arch/arm/common/time-acorn.c + * + * Copyright (c) 1996-2000 Russell King. + * + * 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. + * + * Changelog: + * 24-Sep-1996 RMK Created + * 10-Oct-1996 RMK Brought up to date with arch-sa110eval + * 04-Dec-1997 RMK Updated for new arch/arm/time.c + * 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500 + */ +#include <linux/timex.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <asm/hardware/ioc.h> + +#include <asm/mach/time.h> + +unsigned long ioc_timer_gettimeoffset(void) +{ + unsigned int count1, count2, status; + long offset; + + ioc_writeb (0, IOC_T0LATCH); + barrier (); + count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8); + barrier (); + status = ioc_readb(IOC_IRQREQA); + barrier (); + ioc_writeb (0, IOC_T0LATCH); + barrier (); + count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8); + + offset = count2; + if (count2 < count1) { + /* + * We have not had an interrupt between reading count1 + * and count2. + */ + if (status & (1 << 5)) + offset -= LATCH; + } else if (count2 > count1) { + /* + * We have just had another interrupt between reading + * count1 and count2. + */ + offset -= LATCH; + } + + offset = (LATCH - offset) * (tick_nsec / 1000); + return (offset + LATCH/2) / LATCH; +} + +void __init ioctime_init(void) +{ + ioc_writeb(LATCH & 255, IOC_T0LTCHL); + ioc_writeb(LATCH >> 8, IOC_T0LTCHH); + ioc_writeb(0, IOC_T0GO); +} + +static irqreturn_t +ioc_timer_interrupt(int irq, void *dev_id) +{ + timer_tick(); + return IRQ_HANDLED; +} + +static struct irqaction ioc_timer_irq = { + .name = "timer", + .flags = IRQF_DISABLED, + .handler = ioc_timer_interrupt +}; + +/* + * Set up timer interrupt. + */ +static void __init ioc_timer_init(void) +{ + ioctime_init(); + setup_irq(IRQ_TIMER0, &ioc_timer_irq); +} + +struct sys_timer ioc_timer = { + .init = ioc_timer_init, + .offset = ioc_timer_gettimeoffset, +}; + |