1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/types.h>
14#include <linux/mc146818rtc.h>
15#include <linux/interrupt.h>
16#include <linux/init.h>
17#include <linux/rtc.h>
18#include <linux/bcd.h>
19#include <linux/delay.h>
20#include <linux/export.h>
21
22#include <asm/atariints.h>
23
24DEFINE_SPINLOCK(rtc_lock);
25EXPORT_SYMBOL_GPL(rtc_lock);
26
27void __init
28atari_sched_init(irq_handler_t timer_routine)
29{
30
31 st_mfp.tim_dt_c = INT_TICKS;
32
33 st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
34
35 if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
36 "timer", timer_routine))
37 pr_err("Couldn't register timer interrupt\n");
38}
39
40
41
42#define TICK_SIZE 10000
43
44
45unsigned long atari_gettimeoffset (void)
46{
47 unsigned long ticks, offset = 0;
48
49
50 ticks = st_mfp.tim_dt_c;
51
52 if (ticks > INT_TICKS - INT_TICKS / 50)
53
54 if (st_mfp.int_pn_b & (1 << 5))
55 offset = TICK_SIZE;
56
57 ticks = INT_TICKS - ticks;
58 ticks = ticks * 10000L / INT_TICKS;
59
60 return ticks + offset;
61}
62
63
64static void mste_read(struct MSTE_RTC *val)
65{
66#define COPY(v) val->v=(mste_rtc.v & 0xf)
67 do {
68 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
69 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
70 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
71 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
72 COPY(year_tens) ;
73
74 } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
75#undef COPY
76}
77
78static void mste_write(struct MSTE_RTC *val)
79{
80#define COPY(v) mste_rtc.v=val->v
81 do {
82 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
83 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
84 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
85 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
86 COPY(year_tens) ;
87
88 } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
89#undef COPY
90}
91
92#define RTC_READ(reg) \
93 ({ unsigned char __val; \
94 (void) atari_writeb(reg,&tt_rtc.regsel); \
95 __val = tt_rtc.data; \
96 __val; \
97 })
98
99#define RTC_WRITE(reg,val) \
100 do { \
101 atari_writeb(reg,&tt_rtc.regsel); \
102 tt_rtc.data = (val); \
103 } while(0)
104
105
106#define HWCLK_POLL_INTERVAL 5
107
108int atari_mste_hwclk( int op, struct rtc_time *t )
109{
110 int hour, year;
111 int hr24=0;
112 struct MSTE_RTC val;
113
114 mste_rtc.mode=(mste_rtc.mode | 1);
115 hr24=mste_rtc.mon_tens & 1;
116 mste_rtc.mode=(mste_rtc.mode & ~1);
117
118 if (op) {
119
120
121 val.sec_ones = t->tm_sec % 10;
122 val.sec_tens = t->tm_sec / 10;
123 val.min_ones = t->tm_min % 10;
124 val.min_tens = t->tm_min / 10;
125 hour = t->tm_hour;
126 if (!hr24) {
127 if (hour > 11)
128 hour += 20 - 12;
129 if (hour == 0 || hour == 20)
130 hour += 12;
131 }
132 val.hr_ones = hour % 10;
133 val.hr_tens = hour / 10;
134 val.day_ones = t->tm_mday % 10;
135 val.day_tens = t->tm_mday / 10;
136 val.mon_ones = (t->tm_mon+1) % 10;
137 val.mon_tens = (t->tm_mon+1) / 10;
138 year = t->tm_year - 80;
139 val.year_ones = year % 10;
140 val.year_tens = year / 10;
141 val.weekday = t->tm_wday;
142 mste_write(&val);
143 mste_rtc.mode=(mste_rtc.mode | 1);
144 val.year_ones = (year % 4);
145 mste_rtc.mode=(mste_rtc.mode & ~1);
146 }
147 else {
148 mste_read(&val);
149 t->tm_sec = val.sec_ones + val.sec_tens * 10;
150 t->tm_min = val.min_ones + val.min_tens * 10;
151 hour = val.hr_ones + val.hr_tens * 10;
152 if (!hr24) {
153 if (hour == 12 || hour == 12 + 20)
154 hour -= 12;
155 if (hour >= 20)
156 hour += 12 - 20;
157 }
158 t->tm_hour = hour;
159 t->tm_mday = val.day_ones + val.day_tens * 10;
160 t->tm_mon = val.mon_ones + val.mon_tens * 10 - 1;
161 t->tm_year = val.year_ones + val.year_tens * 10 + 80;
162 t->tm_wday = val.weekday;
163 }
164 return 0;
165}
166
167int atari_tt_hwclk( int op, struct rtc_time *t )
168{
169 int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0;
170 unsigned long flags;
171 unsigned char ctrl;
172 int pm = 0;
173
174 ctrl = RTC_READ(RTC_CONTROL);
175
176
177 if (op) {
178
179
180 sec = t->tm_sec;
181 min = t->tm_min;
182 hour = t->tm_hour;
183 day = t->tm_mday;
184 mon = t->tm_mon + 1;
185 year = t->tm_year - atari_rtc_year_offset;
186 wday = t->tm_wday + (t->tm_wday >= 0);
187
188 if (!(ctrl & RTC_24H)) {
189 if (hour > 11) {
190 pm = 0x80;
191 if (hour != 12)
192 hour -= 12;
193 }
194 else if (hour == 0)
195 hour = 12;
196 }
197
198 if (!(ctrl & RTC_DM_BINARY)) {
199 sec = bin2bcd(sec);
200 min = bin2bcd(min);
201 hour = bin2bcd(hour);
202 day = bin2bcd(day);
203 mon = bin2bcd(mon);
204 year = bin2bcd(year);
205 if (wday >= 0)
206 wday = bin2bcd(wday);
207 }
208 }
209
210
211
212
213
214
215
216
217
218
219
220
221
222 while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
223 if (in_atomic() || irqs_disabled())
224 mdelay(1);
225 else
226 schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
227 }
228
229 local_irq_save(flags);
230 RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
231 if (!op) {
232 sec = RTC_READ( RTC_SECONDS );
233 min = RTC_READ( RTC_MINUTES );
234 hour = RTC_READ( RTC_HOURS );
235 day = RTC_READ( RTC_DAY_OF_MONTH );
236 mon = RTC_READ( RTC_MONTH );
237 year = RTC_READ( RTC_YEAR );
238 wday = RTC_READ( RTC_DAY_OF_WEEK );
239 }
240 else {
241 RTC_WRITE( RTC_SECONDS, sec );
242 RTC_WRITE( RTC_MINUTES, min );
243 RTC_WRITE( RTC_HOURS, hour + pm);
244 RTC_WRITE( RTC_DAY_OF_MONTH, day );
245 RTC_WRITE( RTC_MONTH, mon );
246 RTC_WRITE( RTC_YEAR, year );
247 if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday );
248 }
249 RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET );
250 local_irq_restore(flags);
251
252 if (!op) {
253
254
255 if (hour & 0x80) {
256 hour &= ~0x80;
257 pm = 1;
258 }
259
260 if (!(ctrl & RTC_DM_BINARY)) {
261 sec = bcd2bin(sec);
262 min = bcd2bin(min);
263 hour = bcd2bin(hour);
264 day = bcd2bin(day);
265 mon = bcd2bin(mon);
266 year = bcd2bin(year);
267 wday = bcd2bin(wday);
268 }
269
270 if (!(ctrl & RTC_24H)) {
271 if (!pm && hour == 12)
272 hour = 0;
273 else if (pm && hour != 12)
274 hour += 12;
275 }
276
277 t->tm_sec = sec;
278 t->tm_min = min;
279 t->tm_hour = hour;
280 t->tm_mday = day;
281 t->tm_mon = mon - 1;
282 t->tm_year = year + atari_rtc_year_offset;
283 t->tm_wday = wday - 1;
284 }
285
286 return( 0 );
287}
288
289
290int atari_mste_set_clock_mmss (unsigned long nowtime)
291{
292 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
293 struct MSTE_RTC val;
294 unsigned char rtc_minutes;
295
296 mste_read(&val);
297 rtc_minutes= val.min_ones + val.min_tens * 10;
298 if ((rtc_minutes < real_minutes
299 ? real_minutes - rtc_minutes
300 : rtc_minutes - real_minutes) < 30)
301 {
302 val.sec_ones = real_seconds % 10;
303 val.sec_tens = real_seconds / 10;
304 val.min_ones = real_minutes % 10;
305 val.min_tens = real_minutes / 10;
306 mste_write(&val);
307 }
308 else
309 return -1;
310 return 0;
311}
312
313int atari_tt_set_clock_mmss (unsigned long nowtime)
314{
315 int retval = 0;
316 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
317 unsigned char save_control, save_freq_select, rtc_minutes;
318
319 save_control = RTC_READ (RTC_CONTROL);
320 RTC_WRITE (RTC_CONTROL, save_control | RTC_SET);
321
322 save_freq_select = RTC_READ (RTC_FREQ_SELECT);
323 RTC_WRITE (RTC_FREQ_SELECT, save_freq_select | RTC_DIV_RESET2);
324
325 rtc_minutes = RTC_READ (RTC_MINUTES);
326 if (!(save_control & RTC_DM_BINARY))
327 rtc_minutes = bcd2bin(rtc_minutes);
328
329
330
331
332 if ((rtc_minutes < real_minutes
333 ? real_minutes - rtc_minutes
334 : rtc_minutes - real_minutes) < 30)
335 {
336 if (!(save_control & RTC_DM_BINARY))
337 {
338 real_seconds = bin2bcd(real_seconds);
339 real_minutes = bin2bcd(real_minutes);
340 }
341 RTC_WRITE (RTC_SECONDS, real_seconds);
342 RTC_WRITE (RTC_MINUTES, real_minutes);
343 }
344 else
345 retval = -1;
346
347 RTC_WRITE (RTC_FREQ_SELECT, save_freq_select);
348 RTC_WRITE (RTC_CONTROL, save_control);
349 return retval;
350}
351
352
353
354
355
356
357
358