This source file includes following definitions.
- timer_interrupt
- mktime
- clock_probe
- time_init
- do_gettimeofday
- do_settimeofday
- set_rtc_mmss
1
2
3
4
5
6
7
8 #include <linux/errno.h>
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/param.h>
12 #include <linux/string.h>
13 #include <linux/mm.h>
14 #include <linux/timex.h>
15
16 #include <asm/oplib.h>
17 #include <asm/segment.h>
18 #include <asm/timer.h>
19 #include <asm/mostek.h>
20 #include <asm/system.h>
21 #include <asm/irq.h>
22 #include <asm/io.h>
23
24 #define TIMER_IRQ 10
25
26 enum sparc_clock_type sp_clock_typ;
27 struct mostek48t02 *mstk48t02_regs = 0;
28 struct mostek48t08 *mstk48t08_regs = 0;
29 volatile unsigned int *master_l10_limit = 0;
30 volatile unsigned int *master_l10_counter = 0;
31 struct sun4m_timer_regs *sun4m_timers;
32
33 static int set_rtc_mmss(unsigned long);
34
35
36
37
38
39 void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
40 {
41
42 static long last_rtc_update=0;
43 volatile unsigned int clear_intr;
44
45
46 clear_intr = *master_l10_limit;
47
48 do_timer(regs);
49
50
51 if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
52 xtime.tv_usec > 500000 - (tick >> 1) &&
53 xtime.tv_usec < 500000 + (tick >> 1))
54 if (set_rtc_mmss(xtime.tv_sec) == 0)
55 last_rtc_update = xtime.tv_sec;
56 else
57 last_rtc_update = xtime.tv_sec - 600;
58 }
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 static inline unsigned long mktime(unsigned int year, unsigned int mon,
76 unsigned int day, unsigned int hour,
77 unsigned int min, unsigned int sec)
78 {
79 if (0 >= (int) (mon -= 2)) {
80 mon += 12;
81 year -= 1;
82 }
83 return (((
84 (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
85 year*365 - 719499
86 )*24 + hour
87 )*60 + min
88 )*60 + sec;
89 }
90
91
92 volatile unsigned int foo_limit;
93
94 static void clock_probe(void)
95 {
96 char node_str[128];
97 register int node, type;
98 struct linux_prom_registers clk_reg[2];
99
100
101
102
103
104 node = 0;
105 if(sparc_cpu_model == sun4) {
106 printk("clock_probe: No SUN4 Clock/Timer support yet...\n");
107 return;
108 }
109 if(sparc_cpu_model == sun4c) node=prom_getchild(prom_root_node);
110 else
111 if(sparc_cpu_model == sun4m)
112 node=prom_getchild(prom_searchsiblings(prom_getchild(prom_root_node), "obio"));
113 type = 0;
114 sp_clock_typ = MSTK_INVALID;
115 for(;;) {
116 prom_getstring(node, "model", node_str, sizeof(node_str));
117 if(strcmp(node_str, "mk48t02") == 0) {
118 sp_clock_typ = MSTK48T02;
119 if(prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
120 printk("clock_probe: FAILED!\n");
121 halt();
122 }
123 prom_apply_obio_ranges(clk_reg, 1);
124
125 mstk48t02_regs = (struct mostek48t02 *)
126 sparc_alloc_io((void *) clk_reg[0].phys_addr,
127 (void *) 0, sizeof(*mstk48t02_regs),
128 "clock", clk_reg[0].which_io, 0x0);
129 mstk48t08_regs = 0;
130 break;
131 }
132
133 if(strcmp(node_str, "mk48t08") == 0) {
134 sp_clock_typ = MSTK48T08;
135 if(prom_getproperty(node, "reg", (char *) clk_reg,
136 sizeof(clk_reg)) == -1) {
137 printk("clock_probe: FAILED!\n");
138 halt();
139 }
140 prom_apply_obio_ranges(clk_reg, 1);
141
142 mstk48t08_regs = (struct mostek48t08 *)
143 sparc_alloc_io((void *) clk_reg[0].phys_addr,
144 (void *) 0, sizeof(*mstk48t08_regs),
145 "clock", clk_reg[0].which_io, 0x0);
146
147 mstk48t02_regs = &mstk48t08_regs->regs;
148 break;
149 }
150
151 node = prom_getsibling(node);
152 if(node == 0) {
153 printk("Aieee, could not find timer chip type\n");
154 return;
155 }
156 }
157
158 if(sparc_cpu_model == sun4c) {
159
160
161
162 sun4c_timers = sparc_alloc_io ((void *) SUN4C_TIMER_PHYSADDR, 0,
163 sizeof(struct sun4c_timer_info),
164 "timer", 0x0, 0x0);
165
166
167
168
169
170 sun4c_timers->timer_limit10 = (((1000000/HZ) + 1) << 10);
171 master_l10_limit = &(sun4c_timers->timer_limit10);
172 master_l10_counter = &(sun4c_timers->cur_count10);
173 } else {
174
175
176
177
178
179 int reg_count;
180 struct linux_prom_registers cnt_regs[PROMREG_MAX];
181 volatile unsigned long *real_limit;
182 int obio_node, cnt_node;
183
184 cnt_node = 0;
185 if((obio_node =
186 prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 ||
187 (obio_node = prom_getchild (obio_node)) == 0 ||
188 (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) {
189 prom_printf("Cannot find /obio/counter node\n");
190 prom_halt();
191 }
192 reg_count = prom_getproperty(cnt_node, "reg",
193 (void *) cnt_regs, sizeof(cnt_regs));
194 reg_count = (reg_count/sizeof(struct linux_prom_registers));
195
196
197 prom_apply_obio_ranges(cnt_regs, reg_count);
198
199
200 sparc_alloc_io(cnt_regs[0].phys_addr, 0,
201 PAGE_SIZE*NCPUS, "counters_percpu",
202 cnt_regs[0].which_io, 0x0);
203
204
205 sun4m_timers = sparc_alloc_io(cnt_regs[reg_count-1].phys_addr, 0,
206 cnt_regs[reg_count-1].reg_size,
207 "counters_system",
208 cnt_regs[reg_count-1].which_io, 0x0);
209
210 real_limit = &sun4m_timers->l10_timer_limit;
211 if(reg_count < 4) {
212
213 real_limit = (volatile unsigned long *) sun4m_timers;
214 }
215
216
217 foo_limit = (volatile) *real_limit;
218
219
220 master_l10_limit = real_limit;
221 master_l10_counter = real_limit + 1;
222 *master_l10_limit = (((1000000/HZ) + 1) << 10);
223 }
224 }
225
226 #ifndef BCD_TO_BIN
227 #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
228 #endif
229
230 #ifndef BIN_TO_BCD
231 #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
232 #endif
233
234 void time_init(void)
235 {
236 unsigned int year, mon, day, hour, min, sec;
237 struct mostek48t02 *mregs;
238
239 clock_probe();
240
241 enable_irq(TIMER_IRQ);
242 mregs = mstk48t02_regs;
243 if(!mregs) {
244 prom_printf("Something wrong, clock regs not mapped yet.\n");
245 prom_halt();
246 }
247 mregs->creg |= MSTK_CREG_READ;
248 sec = BCD_TO_BIN(mregs->sec);
249 min = BCD_TO_BIN(mregs->min);
250 hour = BCD_TO_BIN(mregs->hour);
251 day = BCD_TO_BIN(mregs->dom);
252 mon = BCD_TO_BIN(mregs->mnth);
253 year = (BCD_TO_BIN(mregs->yr) + MSTK_YR_ZERO);
254 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
255 xtime.tv_usec = 0;
256 mregs->creg &= ~MSTK_CREG_READ;
257 return;
258 }
259
260 void do_gettimeofday(struct timeval *tv)
261 {
262 unsigned long flags;
263
264 save_flags(flags);
265 cli();
266 *tv = xtime;
267 restore_flags(flags);
268 }
269
270 void do_settimeofday(struct timeval *tv)
271 {
272 cli();
273 xtime = *tv;
274 time_state = TIME_BAD;
275 time_maxerror = 0x70000000;
276 time_esterror = 0x70000000;
277 sti();
278 }
279
280 static int set_rtc_mmss(unsigned long nowtime)
281 {
282 int retval = 0;
283 int real_seconds, real_minutes, mostek_minutes;
284 struct mostek48t02 *mregs = mstk48t02_regs;
285
286 if(!mregs)
287 retval = -1;
288 else {
289 mregs->creg |= MSTK_CREG_READ;
290 mostek_minutes = BCD_TO_BIN(mregs->min);
291 mregs->creg &= ~MSTK_CREG_READ;
292
293 real_seconds = nowtime % 60;
294 real_minutes = nowtime / 60;
295 if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
296 real_minutes += 30;
297 real_minutes %= 60;
298 if (abs(real_minutes - mostek_minutes) < 30) {
299 mregs->creg |= MSTK_CREG_WRITE;
300 mregs->sec = real_seconds;
301 mregs->min = real_minutes;
302 mregs->creg &= ~MSTK_CREG_WRITE;
303 } else
304 retval = -1;
305 }
306
307 return retval;
308 }