]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/arm/common/time-acorn.c | |
3 | * | |
4 | * Copyright (c) 1996-2000 Russell King. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * Changelog: | |
11 | * 24-Sep-1996 RMK Created | |
12 | * 10-Oct-1996 RMK Brought up to date with arch-sa110eval | |
13 | * 04-Dec-1997 RMK Updated for new arch/arm/time.c | |
14 | * 13=Jun-2004 DS Moved to arch/arm/common b/c shared w/CLPS7500 | |
15 | */ | |
16 | #include <linux/timex.h> | |
17 | #include <linux/init.h> | |
18 | #include <linux/interrupt.h> | |
c4bfa28a | 19 | #include <linux/irq.h> |
fced80c7 | 20 | #include <linux/io.h> |
1da177e4 | 21 | |
a09e64fb | 22 | #include <mach/hardware.h> |
1da177e4 LT |
23 | #include <asm/hardware/ioc.h> |
24 | ||
25 | #include <asm/mach/time.h> | |
26 | ||
23c197b7 | 27 | static u32 ioc_timer_gettimeoffset(void) |
1da177e4 LT |
28 | { |
29 | unsigned int count1, count2, status; | |
30 | long offset; | |
31 | ||
32 | ioc_writeb (0, IOC_T0LATCH); | |
33 | barrier (); | |
34 | count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8); | |
35 | barrier (); | |
36 | status = ioc_readb(IOC_IRQREQA); | |
37 | barrier (); | |
38 | ioc_writeb (0, IOC_T0LATCH); | |
39 | barrier (); | |
40 | count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8); | |
41 | ||
42 | offset = count2; | |
43 | if (count2 < count1) { | |
44 | /* | |
45 | * We have not had an interrupt between reading count1 | |
46 | * and count2. | |
47 | */ | |
48 | if (status & (1 << 5)) | |
49 | offset -= LATCH; | |
50 | } else if (count2 > count1) { | |
51 | /* | |
52 | * We have just had another interrupt between reading | |
53 | * count1 and count2. | |
54 | */ | |
55 | offset -= LATCH; | |
56 | } | |
57 | ||
58 | offset = (LATCH - offset) * (tick_nsec / 1000); | |
23c197b7 | 59 | return ((offset + LATCH/2) / LATCH) * 1000; |
1da177e4 LT |
60 | } |
61 | ||
62 | void __init ioctime_init(void) | |
63 | { | |
64 | ioc_writeb(LATCH & 255, IOC_T0LTCHL); | |
65 | ioc_writeb(LATCH >> 8, IOC_T0LTCHH); | |
66 | ioc_writeb(0, IOC_T0GO); | |
67 | } | |
68 | ||
69 | static irqreturn_t | |
0cd61b68 | 70 | ioc_timer_interrupt(int irq, void *dev_id) |
1da177e4 | 71 | { |
0cd61b68 | 72 | timer_tick(); |
1da177e4 LT |
73 | return IRQ_HANDLED; |
74 | } | |
75 | ||
76 | static struct irqaction ioc_timer_irq = { | |
77 | .name = "timer", | |
52e405ea | 78 | .flags = IRQF_DISABLED, |
1da177e4 LT |
79 | .handler = ioc_timer_interrupt |
80 | }; | |
81 | ||
82 | /* | |
83 | * Set up timer interrupt. | |
84 | */ | |
6bb27d73 | 85 | void __init ioc_timer_init(void) |
1da177e4 | 86 | { |
23c197b7 | 87 | arch_gettimeoffset = ioc_timer_gettimeoffset; |
1da177e4 | 88 | ioctime_init(); |
927b6c4d | 89 | setup_irq(IRQ_TIMER0, &ioc_timer_irq); |
1da177e4 | 90 | } |