diff options
Diffstat (limited to 'arch/mips/vr4181/common/time.c')
-rw-r--r-- | arch/mips/vr4181/common/time.c | 145 |
1 files changed, 0 insertions, 145 deletions
diff --git a/arch/mips/vr4181/common/time.c b/arch/mips/vr4181/common/time.c deleted file mode 100644 index 17814076b6f4..000000000000 --- a/arch/mips/vr4181/common/time.c +++ /dev/null | |||
@@ -1,145 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: jsun@mvista.com or jsun@junsun.net | ||
4 | * | ||
5 | * rtc and time ops for vr4181. Part of code is drived from | ||
6 | * linux-vr, originally written by Bradley D. LaRonde & Michael Klar. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/param.h> /* for HZ */ | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | |||
21 | #include <asm/system.h> | ||
22 | #include <asm/time.h> | ||
23 | |||
24 | #include <asm/vr4181/vr4181.h> | ||
25 | |||
26 | #define COUNTS_PER_JIFFY ((32768 + HZ/2) / HZ) | ||
27 | |||
28 | /* | ||
29 | * RTC ops | ||
30 | */ | ||
31 | |||
32 | DEFINE_SPINLOCK(rtc_lock); | ||
33 | |||
34 | /* per VR41xx docs, bad data can be read if between 2 counts */ | ||
35 | static inline unsigned short | ||
36 | read_time_reg(volatile unsigned short *reg) | ||
37 | { | ||
38 | unsigned short value; | ||
39 | do { | ||
40 | value = *reg; | ||
41 | barrier(); | ||
42 | } while (value != *reg); | ||
43 | return value; | ||
44 | } | ||
45 | |||
46 | static unsigned long | ||
47 | vr4181_rtc_get_time(void) | ||
48 | { | ||
49 | unsigned short regh, regm, regl; | ||
50 | |||
51 | // why this crazy order, you ask? to guarantee that neither m | ||
52 | // nor l wrap before all 3 read | ||
53 | do { | ||
54 | regm = read_time_reg(VR4181_ETIMEMREG); | ||
55 | barrier(); | ||
56 | regh = read_time_reg(VR4181_ETIMEHREG); | ||
57 | barrier(); | ||
58 | regl = read_time_reg(VR4181_ETIMELREG); | ||
59 | } while (regm != read_time_reg(VR4181_ETIMEMREG)); | ||
60 | return ((regh << 17) | (regm << 1) | (regl >> 15)); | ||
61 | } | ||
62 | |||
63 | static int | ||
64 | vr4181_rtc_set_time(unsigned long timeval) | ||
65 | { | ||
66 | unsigned short intreg; | ||
67 | unsigned long flags; | ||
68 | |||
69 | spin_lock_irqsave(&rtc_lock, flags); | ||
70 | intreg = *VR4181_RTCINTREG & 0x05; | ||
71 | barrier(); | ||
72 | *VR4181_ETIMELREG = timeval << 15; | ||
73 | *VR4181_ETIMEMREG = timeval >> 1; | ||
74 | *VR4181_ETIMEHREG = timeval >> 17; | ||
75 | barrier(); | ||
76 | // assume that any ints that just triggered are invalid, since the | ||
77 | // time value is written non-atomically in 3 separate regs | ||
78 | *VR4181_RTCINTREG = 0x05 ^ intreg; | ||
79 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | |||
85 | /* | ||
86 | * timer interrupt routine (wrapper) | ||
87 | * | ||
88 | * we need our own interrupt routine because we need to clear | ||
89 | * RTC1 interrupt. | ||
90 | */ | ||
91 | static void | ||
92 | vr4181_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
93 | { | ||
94 | /* Clear the interrupt. */ | ||
95 | *VR4181_RTCINTREG = 0x2; | ||
96 | |||
97 | /* call the generic one */ | ||
98 | timer_interrupt(irq, dev_id, regs); | ||
99 | } | ||
100 | |||
101 | |||
102 | /* | ||
103 | * vr4181_time_init: | ||
104 | * | ||
105 | * We pick the following choices: | ||
106 | * . we use elapsed timer as the RTC. We set some reasonable init data since | ||
107 | * it does not persist across reset | ||
108 | * . we use RTC1 as the system timer interrupt source. | ||
109 | * . we use CPU counter for fast_gettimeoffset and we calivrate the cpu | ||
110 | * frequency. In other words, we use calibrate_div64_gettimeoffset(). | ||
111 | * . we use our own timer interrupt routine which clears the interrupt | ||
112 | * and then calls the generic high-level timer interrupt routine. | ||
113 | * | ||
114 | */ | ||
115 | |||
116 | extern int setup_irq(unsigned int irq, struct irqaction *irqaction); | ||
117 | |||
118 | static void | ||
119 | vr4181_timer_setup(struct irqaction *irq) | ||
120 | { | ||
121 | /* over-write the handler to be our own one */ | ||
122 | irq->handler = vr4181_timer_interrupt; | ||
123 | |||
124 | /* sets up the frequency */ | ||
125 | *VR4181_RTCL1LREG = COUNTS_PER_JIFFY; | ||
126 | *VR4181_RTCL1HREG = 0; | ||
127 | |||
128 | /* and ack any pending ints */ | ||
129 | *VR4181_RTCINTREG = 0x2; | ||
130 | |||
131 | /* setup irqaction */ | ||
132 | setup_irq(VR4181_IRQ_INT1, irq); | ||
133 | |||
134 | } | ||
135 | |||
136 | void | ||
137 | vr4181_init_time(void) | ||
138 | { | ||
139 | /* setup hookup functions */ | ||
140 | rtc_get_time = vr4181_rtc_get_time; | ||
141 | rtc_set_time = vr4181_rtc_set_time; | ||
142 | |||
143 | board_timer_setup = vr4181_timer_setup; | ||
144 | } | ||
145 | |||