Commit a700f3594d63a85af196ac64984f7375d903afad

Authored by Paul Mundt
Committed by Paul Mundt
1 parent 4588214526

sh: Kill off timer_ops get_frequency().

We're not using this anywhere these days, kill it off.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

Showing 2 changed files with 2 additions and 62 deletions Inline Diff

arch/sh/kernel/timers/timer-tmu.c
1 /* 1 /*
2 * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support 2 * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
3 * 3 *
4 * Copyright (C) 2005 Paul Mundt 4 * Copyright (C) 2005 Paul Mundt
5 * 5 *
6 * TMU handling code hacked out of arch/sh/kernel/time.c 6 * TMU handling code hacked out of arch/sh/kernel/time.c
7 * 7 *
8 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka 8 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
9 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> 9 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
10 * Copyright (C) 2002, 2003, 2004 Paul Mundt 10 * Copyright (C) 2002, 2003, 2004 Paul Mundt
11 * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> 11 * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
12 * 12 *
13 * This file is subject to the terms and conditions of the GNU General Public 13 * This file is subject to the terms and conditions of the GNU General Public
14 * License. See the file "COPYING" in the main directory of this archive 14 * License. See the file "COPYING" in the main directory of this archive
15 * for more details. 15 * for more details.
16 */ 16 */
17 #include <linux/init.h> 17 #include <linux/init.h>
18 #include <linux/kernel.h> 18 #include <linux/kernel.h>
19 #include <linux/interrupt.h> 19 #include <linux/interrupt.h>
20 #include <linux/spinlock.h> 20 #include <linux/spinlock.h>
21 #include <linux/seqlock.h> 21 #include <linux/seqlock.h>
22 #include <asm/timer.h> 22 #include <asm/timer.h>
23 #include <asm/rtc.h> 23 #include <asm/rtc.h>
24 #include <asm/io.h> 24 #include <asm/io.h>
25 #include <asm/irq.h> 25 #include <asm/irq.h>
26 #include <asm/clock.h> 26 #include <asm/clock.h>
27 27
28 #define TMU_TOCR_INIT 0x00 28 #define TMU_TOCR_INIT 0x00
29 #define TMU0_TCR_INIT 0x0020 29 #define TMU0_TCR_INIT 0x0020
30 #define TMU_TSTR_INIT 1 30 #define TMU_TSTR_INIT 1
31 31
32 #define TMU0_TCR_CALIB 0x0000 32 #define TMU0_TCR_CALIB 0x0000
33 33
34 static DEFINE_SPINLOCK(tmu0_lock); 34 static DEFINE_SPINLOCK(tmu0_lock);
35 35
36 static unsigned long tmu_timer_get_offset(void) 36 static unsigned long tmu_timer_get_offset(void)
37 { 37 {
38 int count; 38 int count;
39 unsigned long flags; 39 unsigned long flags;
40 40
41 static int count_p = 0x7fffffff; /* for the first call after boot */ 41 static int count_p = 0x7fffffff; /* for the first call after boot */
42 static unsigned long jiffies_p = 0; 42 static unsigned long jiffies_p = 0;
43 43
44 /* 44 /*
45 * cache volatile jiffies temporarily; we have IRQs turned off. 45 * cache volatile jiffies temporarily; we have IRQs turned off.
46 */ 46 */
47 unsigned long jiffies_t; 47 unsigned long jiffies_t;
48 48
49 spin_lock_irqsave(&tmu0_lock, flags); 49 spin_lock_irqsave(&tmu0_lock, flags);
50 /* timer count may underflow right here */ 50 /* timer count may underflow right here */
51 count = ctrl_inl(TMU0_TCNT); /* read the latched count */ 51 count = ctrl_inl(TMU0_TCNT); /* read the latched count */
52 52
53 jiffies_t = jiffies; 53 jiffies_t = jiffies;
54 54
55 /* 55 /*
56 * avoiding timer inconsistencies (they are rare, but they happen)... 56 * avoiding timer inconsistencies (they are rare, but they happen)...
57 * there is one kind of problem that must be avoided here: 57 * there is one kind of problem that must be avoided here:
58 * 1. the timer counter underflows 58 * 1. the timer counter underflows
59 */ 59 */
60 60
61 if (jiffies_t == jiffies_p) { 61 if (jiffies_t == jiffies_p) {
62 if (count > count_p) { 62 if (count > count_p) {
63 /* the nutcase */ 63 /* the nutcase */
64 if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ 64 if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
65 count -= LATCH; 65 count -= LATCH;
66 } else { 66 } else {
67 printk("%s (): hardware timer problem?\n", 67 printk("%s (): hardware timer problem?\n",
68 __FUNCTION__); 68 __FUNCTION__);
69 } 69 }
70 } 70 }
71 } else 71 } else
72 jiffies_p = jiffies_t; 72 jiffies_p = jiffies_t;
73 73
74 count_p = count; 74 count_p = count;
75 spin_unlock_irqrestore(&tmu0_lock, flags); 75 spin_unlock_irqrestore(&tmu0_lock, flags);
76 76
77 count = ((LATCH-1) - count) * TICK_SIZE; 77 count = ((LATCH-1) - count) * TICK_SIZE;
78 count = (count + LATCH/2) / LATCH; 78 count = (count + LATCH/2) / LATCH;
79 79
80 return count; 80 return count;
81 } 81 }
82 82
83 static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id, 83 static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id,
84 struct pt_regs *regs) 84 struct pt_regs *regs)
85 { 85 {
86 unsigned long timer_status; 86 unsigned long timer_status;
87 87
88 /* Clear UNF bit */ 88 /* Clear UNF bit */
89 timer_status = ctrl_inw(TMU0_TCR); 89 timer_status = ctrl_inw(TMU0_TCR);
90 timer_status &= ~0x100; 90 timer_status &= ~0x100;
91 ctrl_outw(timer_status, TMU0_TCR); 91 ctrl_outw(timer_status, TMU0_TCR);
92 92
93 /* 93 /*
94 * Here we are in the timer irq handler. We just have irqs locally 94 * Here we are in the timer irq handler. We just have irqs locally
95 * disabled but we don't know if the timer_bh is running on the other 95 * disabled but we don't know if the timer_bh is running on the other
96 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need 96 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
97 * the irq version of write_lock because as just said we have irq 97 * the irq version of write_lock because as just said we have irq
98 * locally disabled. -arca 98 * locally disabled. -arca
99 */ 99 */
100 write_seqlock(&xtime_lock); 100 write_seqlock(&xtime_lock);
101 handle_timer_tick(regs); 101 handle_timer_tick(regs);
102 write_sequnlock(&xtime_lock); 102 write_sequnlock(&xtime_lock);
103 103
104 return IRQ_HANDLED; 104 return IRQ_HANDLED;
105 } 105 }
106 106
107 static struct irqaction tmu_irq = { 107 static struct irqaction tmu_irq = {
108 .name = "timer", 108 .name = "timer",
109 .handler = tmu_timer_interrupt, 109 .handler = tmu_timer_interrupt,
110 .flags = IRQF_DISABLED, 110 .flags = IRQF_DISABLED,
111 .mask = CPU_MASK_NONE, 111 .mask = CPU_MASK_NONE,
112 }; 112 };
113 113
114 /*
115 * Hah! We'll see if this works (switching from usecs to nsecs).
116 */
117 static unsigned long tmu_timer_get_frequency(void)
118 {
119 u32 freq;
120 struct timespec ts1, ts2;
121 unsigned long diff_nsec;
122 unsigned long factor;
123
124 /* Setup the timer: We don't want to generate interrupts, just
125 * have it count down at its natural rate.
126 */
127 ctrl_outb(0, TMU_TSTR);
128 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
129 ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
130 #endif
131 ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
132 ctrl_outl(0xffffffff, TMU0_TCOR);
133 ctrl_outl(0xffffffff, TMU0_TCNT);
134
135 rtc_sh_get_time(&ts2);
136
137 do {
138 rtc_sh_get_time(&ts1);
139 } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
140
141 /* actually start the timer */
142 ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
143
144 do {
145 rtc_sh_get_time(&ts2);
146 } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
147
148 freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
149 if (ts2.tv_nsec < ts1.tv_nsec) {
150 ts2.tv_nsec += 1000000000;
151 ts2.tv_sec--;
152 }
153
154 diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
155
156 /* this should work well if the RTC has a precision of n Hz, where
157 * n is an integer. I don't think we have to worry about the other
158 * cases. */
159 factor = (1000000000 + diff_nsec/2) / diff_nsec;
160
161 if (factor * diff_nsec > 1100000000 ||
162 factor * diff_nsec < 900000000)
163 panic("weird RTC (diff_nsec %ld)", diff_nsec);
164
165 return freq * factor;
166 }
167
168 static void tmu_clk_init(struct clk *clk) 114 static void tmu_clk_init(struct clk *clk)
169 { 115 {
170 u8 divisor = TMU0_TCR_INIT & 0x7; 116 u8 divisor = TMU0_TCR_INIT & 0x7;
171 ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); 117 ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
172 clk->rate = clk->parent->rate / (4 << (divisor << 1)); 118 clk->rate = clk->parent->rate / (4 << (divisor << 1));
173 } 119 }
174 120
175 static void tmu_clk_recalc(struct clk *clk) 121 static void tmu_clk_recalc(struct clk *clk)
176 { 122 {
177 u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; 123 u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
178 clk->rate = clk->parent->rate / (4 << (divisor << 1)); 124 clk->rate = clk->parent->rate / (4 << (divisor << 1));
179 } 125 }
180 126
181 static struct clk_ops tmu_clk_ops = { 127 static struct clk_ops tmu_clk_ops = {
182 .init = tmu_clk_init, 128 .init = tmu_clk_init,
183 .recalc = tmu_clk_recalc, 129 .recalc = tmu_clk_recalc,
184 }; 130 };
185 131
186 static struct clk tmu0_clk = { 132 static struct clk tmu0_clk = {
187 .name = "tmu0_clk", 133 .name = "tmu0_clk",
188 .ops = &tmu_clk_ops, 134 .ops = &tmu_clk_ops,
189 }; 135 };
190 136
191 static int tmu_timer_start(void) 137 static int tmu_timer_start(void)
192 { 138 {
193 ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); 139 ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
194 return 0; 140 return 0;
195 } 141 }
196 142
197 static int tmu_timer_stop(void) 143 static int tmu_timer_stop(void)
198 { 144 {
199 ctrl_outb(0, TMU_TSTR); 145 ctrl_outb(0, TMU_TSTR);
200 return 0; 146 return 0;
201 } 147 }
202 148
203 static int tmu_timer_init(void) 149 static int tmu_timer_init(void)
204 { 150 {
205 unsigned long interval; 151 unsigned long interval;
206 152
207 setup_irq(TIMER_IRQ, &tmu_irq); 153 setup_irq(TIMER_IRQ, &tmu_irq);
208 154
209 tmu0_clk.parent = clk_get("module_clk"); 155 tmu0_clk.parent = clk_get("module_clk");
210 156
211 /* Start TMU0 */ 157 /* Start TMU0 */
212 tmu_timer_stop(); 158 tmu_timer_stop();
213 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) 159 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
214 ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); 160 ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
215 #endif 161 #endif
216 162
217 clk_register(&tmu0_clk); 163 clk_register(&tmu0_clk);
218 clk_enable(&tmu0_clk); 164 clk_enable(&tmu0_clk);
219 165
220 interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; 166 interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ;
221 printk(KERN_INFO "Interval = %ld\n", interval); 167 printk(KERN_INFO "Interval = %ld\n", interval);
222 168
223 ctrl_outl(interval, TMU0_TCOR); 169 ctrl_outl(interval, TMU0_TCOR);
224 ctrl_outl(interval, TMU0_TCNT); 170 ctrl_outl(interval, TMU0_TCNT);
225 171
226 tmu_timer_start(); 172 tmu_timer_start();
227 173
228 return 0; 174 return 0;
229 } 175 }
230 176
231 struct sys_timer_ops tmu_timer_ops = { 177 struct sys_timer_ops tmu_timer_ops = {
232 .init = tmu_timer_init, 178 .init = tmu_timer_init,
233 .start = tmu_timer_start, 179 .start = tmu_timer_start,
234 .stop = tmu_timer_stop, 180 .stop = tmu_timer_stop,
235 .get_frequency = tmu_timer_get_frequency, 181 #ifndef CONFIG_GENERIC_TIME
236 .get_offset = tmu_timer_get_offset, 182 .get_offset = tmu_timer_get_offset,
183 #endif
237 }; 184 };
238 185
239 struct sys_timer tmu_timer = { 186 struct sys_timer tmu_timer = {
240 .name = "tmu", 187 .name = "tmu",
241 .ops = &tmu_timer_ops, 188 .ops = &tmu_timer_ops,
242 }; 189 };
243 190
include/asm-sh/timer.h
1 #ifndef __ASM_SH_TIMER_H 1 #ifndef __ASM_SH_TIMER_H
2 #define __ASM_SH_TIMER_H 2 #define __ASM_SH_TIMER_H
3 3
4 #include <linux/sysdev.h> 4 #include <linux/sysdev.h>
5 #include <asm/cpu/timer.h> 5 #include <asm/cpu/timer.h>
6 6
7 struct sys_timer_ops { 7 struct sys_timer_ops {
8 int (*init)(void); 8 int (*init)(void);
9 int (*start)(void); 9 int (*start)(void);
10 int (*stop)(void); 10 int (*stop)(void);
11 #ifndef CONFIG_GENERIC_TIME 11 #ifndef CONFIG_GENERIC_TIME
12 unsigned long (*get_offset)(void); 12 unsigned long (*get_offset)(void);
13 #endif 13 #endif
14 unsigned long (*get_frequency)(void);
15 }; 14 };
16 15
17 struct sys_timer { 16 struct sys_timer {
18 const char *name; 17 const char *name;
19 18
20 struct sys_device dev; 19 struct sys_device dev;
21 struct sys_timer_ops *ops; 20 struct sys_timer_ops *ops;
22 }; 21 };
23 22
24 #define TICK_SIZE (tick_nsec / 1000) 23 #define TICK_SIZE (tick_nsec / 1000)
25 24
26 extern struct sys_timer tmu_timer; 25 extern struct sys_timer tmu_timer;
27 extern struct sys_timer *sys_timer; 26 extern struct sys_timer *sys_timer;
28 27
29 #ifndef CONFIG_GENERIC_TIME 28 #ifndef CONFIG_GENERIC_TIME
30 static inline unsigned long get_timer_offset(void) 29 static inline unsigned long get_timer_offset(void)
31 { 30 {
32 return sys_timer->ops->get_offset(); 31 return sys_timer->ops->get_offset();
33 } 32 }
34 #endif 33 #endif
35
36 static inline unsigned long get_timer_frequency(void)
37 {
38 return sys_timer->ops->get_frequency();
39 }
40 34
41 /* arch/sh/kernel/timers/timer.c */ 35 /* arch/sh/kernel/timers/timer.c */
42 struct sys_timer *get_sys_timer(void); 36 struct sys_timer *get_sys_timer(void);
43 37
44 /* arch/sh/kernel/time.c */ 38 /* arch/sh/kernel/time.c */
45 void handle_timer_tick(struct pt_regs *); 39 void handle_timer_tick(struct pt_regs *);
46 40
47 #endif /* __ASM_SH_TIMER_H */ 41 #endif /* __ASM_SH_TIMER_H */
48 42
49 43