Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
time.c
Go to the documentation of this file.
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>
19 #include <linux/irq.h>
20 #include <linux/io.h>
21 
22 #include <mach/hardware.h>
23 #include <asm/hardware/ioc.h>
24 
25 #include <asm/mach/time.h>
26 
27 unsigned long ioc_timer_gettimeoffset(void)
28 {
29  unsigned int count1, count2, status;
30  long offset;
31 
33  barrier ();
34  count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
35  barrier ();
36  status = ioc_readb(IOC_IRQREQA);
37  barrier ();
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);
59  return (offset + LATCH/2) / LATCH;
60 }
61 
62 void __init ioctime_init(void)
63 {
66  ioc_writeb(0, IOC_T0GO);
67 }
68 
69 static irqreturn_t
70 ioc_timer_interrupt(int irq, void *dev_id)
71 {
72  timer_tick();
73  return IRQ_HANDLED;
74 }
75 
76 static struct irqaction ioc_timer_irq = {
77  .name = "timer",
78  .flags = IRQF_DISABLED,
79  .handler = ioc_timer_interrupt
80 };
81 
82 /*
83  * Set up timer interrupt.
84  */
85 static void __init ioc_timer_init(void)
86 {
87  ioctime_init();
88  setup_irq(IRQ_TIMER0, &ioc_timer_irq);
89 }
90 
91 struct sys_timer ioc_timer = {
92  .init = ioc_timer_init,
93  .offset = ioc_timer_gettimeoffset,
94 };
95