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/config.h>
9 #include <linux/errno.h>
10 #include <linux/sched.h>
11 #include <linux/kernel.h>
12 #include <linux/param.h>
13 #include <linux/string.h>
14 #include <linux/mm.h>
15 #include <linux/timex.h>
16
17 #include <asm/oplib.h>
18 #include <asm/segment.h>
19 #include <asm/timer.h>
20 #include <asm/mostek.h>
21 #include <asm/system.h>
22 #include <asm/irq.h>
23 #include <asm/io.h>
24
25 enum sparc_clock_type sp_clock_typ;
26 struct mostek48t02 *mstk48t02_regs = 0;
27 struct mostek48t08 *mstk48t08_regs = 0;
28 static int set_rtc_mmss(unsigned long);
29
30
31
32
33
34 void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
35 {
36
37 static long last_rtc_update=0;
38
39 clear_clock_irq();
40
41 do_timer(regs);
42
43
44 if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
45 xtime.tv_usec > 500000 - (tick >> 1) &&
46 xtime.tv_usec < 500000 + (tick >> 1))
47 if (set_rtc_mmss(xtime.tv_sec) == 0)
48 last_rtc_update = xtime.tv_sec;
49 else
50 last_rtc_update = xtime.tv_sec - 600;
51 }
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 static inline unsigned long mktime(unsigned int year, unsigned int mon,
69 unsigned int day, unsigned int hour,
70 unsigned int min, unsigned int sec)
71 {
72 if (0 >= (int) (mon -= 2)) {
73 mon += 12;
74 year -= 1;
75 }
76 return (((
77 (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
78 year*365 - 719499
79 )*24 + hour
80 )*60 + min
81 )*60 + sec;
82 }
83
84
85 volatile unsigned int foo_limit;
86
87 static void clock_probe(void)
88 {
89 char node_str[128];
90 register int node, type;
91 struct linux_prom_registers clk_reg[2];
92
93
94
95
96 node = 0;
97 if(sparc_cpu_model == sun4) {
98 printk("clock_probe: No SUN4 Clock/Timer support yet...\n");
99 return;
100 }
101 if(sparc_cpu_model == sun4c)
102 node = prom_getchild(prom_root_node);
103 else
104 if(sparc_cpu_model == sun4m)
105 node=prom_getchild(prom_searchsiblings(prom_getchild(prom_root_node), "obio"));
106 type = 0;
107 sp_clock_typ = MSTK_INVALID;
108 for(;;) {
109 prom_getstring(node, "model", node_str, sizeof(node_str));
110 if(strcmp(node_str, "mk48t02") == 0) {
111 sp_clock_typ = MSTK48T02;
112 if(prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
113 printk("clock_probe: FAILED!\n");
114 halt();
115 }
116 prom_apply_obio_ranges(clk_reg, 1);
117
118 mstk48t02_regs = (struct mostek48t02 *)
119 sparc_alloc_io((void *) clk_reg[0].phys_addr,
120 (void *) 0, sizeof(*mstk48t02_regs),
121 "clock", clk_reg[0].which_io, 0x0);
122 mstk48t08_regs = 0;
123 break;
124 }
125
126 if(strcmp(node_str, "mk48t08") == 0) {
127 sp_clock_typ = MSTK48T08;
128 if(prom_getproperty(node, "reg", (char *) clk_reg,
129 sizeof(clk_reg)) == -1) {
130 printk("clock_probe: FAILED!\n");
131 halt();
132 }
133 prom_apply_obio_ranges(clk_reg, 1);
134
135 mstk48t08_regs = (struct mostek48t08 *)
136 sparc_alloc_io((void *) clk_reg[0].phys_addr,
137 (void *) 0, sizeof(*mstk48t08_regs),
138 "clock", clk_reg[0].which_io, 0x0);
139
140 mstk48t02_regs = &mstk48t08_regs->regs;
141 break;
142 }
143
144 node = prom_getsibling(node);
145 if(node == 0) {
146 printk("Aieee, could not find timer chip type\n");
147 return;
148 }
149 }
150 }
151
152 #ifndef BCD_TO_BIN
153 #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
154 #endif
155
156 #ifndef BIN_TO_BCD
157 #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
158 #endif
159
160 void time_init(void)
161 {
162 unsigned int year, mon, day, hour, min, sec;
163 struct mostek48t02 *mregs;
164
165 #if CONFIG_AP1000
166 init_timers(timer_interrupt);
167 return;
168 #endif
169
170 clock_probe();
171 init_timers(timer_interrupt);
172
173 mregs = mstk48t02_regs;
174 if(!mregs) {
175 prom_printf("Something wrong, clock regs not mapped yet.\n");
176 prom_halt();
177 }
178 mregs->creg |= MSTK_CREG_READ;
179 sec = BCD_TO_BIN(mregs->sec);
180 min = BCD_TO_BIN(mregs->min);
181 hour = BCD_TO_BIN(mregs->hour);
182 day = BCD_TO_BIN(mregs->dom);
183 mon = BCD_TO_BIN(mregs->mnth);
184 year = (BCD_TO_BIN(mregs->yr) + MSTK_YR_ZERO);
185 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
186 xtime.tv_usec = 0;
187 mregs->creg &= ~MSTK_CREG_READ;
188 return;
189 }
190
191
192 void do_gettimeofday(struct timeval *tv)
193 {
194 unsigned long flags;
195
196 save_flags(flags);
197 cli();
198 #if CONFIG_AP1000
199 ap_gettimeofday(&xtime);
200 #endif
201 *tv = xtime;
202 restore_flags(flags);
203 }
204
205 void do_settimeofday(struct timeval *tv)
206 {
207 cli();
208 xtime = *tv;
209 time_state = TIME_BAD;
210 time_maxerror = 0x70000000;
211 time_esterror = 0x70000000;
212 sti();
213 }
214
215 static int set_rtc_mmss(unsigned long nowtime)
216 {
217 int retval = 0;
218 int real_seconds, real_minutes, mostek_minutes;
219 struct mostek48t02 *mregs = mstk48t02_regs;
220
221 if(!mregs)
222 retval = -1;
223 else {
224 mregs->creg |= MSTK_CREG_READ;
225 mostek_minutes = BCD_TO_BIN(mregs->min);
226 mregs->creg &= ~MSTK_CREG_READ;
227
228 real_seconds = nowtime % 60;
229 real_minutes = nowtime / 60;
230 if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
231 real_minutes += 30;
232 real_minutes %= 60;
233 if (abs(real_minutes - mostek_minutes) < 30) {
234 mregs->creg |= MSTK_CREG_WRITE;
235 mregs->sec = real_seconds;
236 mregs->min = real_minutes;
237 mregs->creg &= ~MSTK_CREG_WRITE;
238 } else
239 retval = -1;
240 }
241
242 return retval;
243 }