OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [m68k/] [atari/] [time.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/arch/m68k/atari/time.c
3
 *
4
 * Atari time and real time clock stuff
5
 *
6
 * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
7
 *
8
 * This file is subject to the terms and conditions of the GNU General Public
9
 * License.  See the file COPYING in the main directory of this archive
10
 * for more details.
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
 
19
#include <asm/atariints.h>
20
 
21
void __init
22
atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
23
{
24
    /* set Timer C data Register */
25
    mfp.tim_dt_c = INT_TICKS;
26
    /* start timer C, div = 1:100 */
27
    mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
28
    /* install interrupt service routine for MFP Timer C */
29
    request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
30
                "timer", timer_routine);
31
}
32
 
33
/* ++andreas: gettimeoffset fixed to check for pending interrupt */
34
 
35
#define TICK_SIZE 10000
36
 
37
/* This is always executed with interrupts disabled.  */
38
unsigned long atari_gettimeoffset (void)
39
{
40
  unsigned long ticks, offset = 0;
41
 
42
  /* read MFP timer C current value */
43
  ticks = mfp.tim_dt_c;
44
  /* The probability of underflow is less than 2% */
45
  if (ticks > INT_TICKS - INT_TICKS / 50)
46
    /* Check for pending timer interrupt */
47
    if (mfp.int_pn_b & (1 << 5))
48
      offset = TICK_SIZE;
49
 
50
  ticks = INT_TICKS - ticks;
51
  ticks = ticks * 10000L / INT_TICKS;
52
 
53
  return ticks + offset;
54
}
55
 
56
 
57
static void mste_read(struct MSTE_RTC *val)
58
{
59
#define COPY(v) val->v=(mste_rtc.v & 0xf)
60
        do {
61
                COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
62
                COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
63
                COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
64
                COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
65
                COPY(year_tens) ;
66
        /* prevent from reading the clock while it changed */
67
        } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
68
#undef COPY
69
}
70
 
71
static void mste_write(struct MSTE_RTC *val)
72
{
73
#define COPY(v) mste_rtc.v=val->v
74
        do {
75
                COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
76
                COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
77
                COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
78
                COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
79
                COPY(year_tens) ;
80
        /* prevent from writing the clock while it changed */
81
        } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
82
#undef COPY
83
}
84
 
85
#define RTC_READ(reg)                           \
86
    ({  unsigned char   __val;                  \
87
                (void) atari_writeb(reg,&tt_rtc.regsel);        \
88
                __val = tt_rtc.data;            \
89
                __val;                          \
90
        })
91
 
92
#define RTC_WRITE(reg,val)                      \
93
    do {                                        \
94
                atari_writeb(reg,&tt_rtc.regsel);       \
95
                tt_rtc.data = (val);            \
96
        } while(0)
97
 
98
 
99
void atari_mste_gettod (int *yearp, int *monp, int *dayp,
100
                        int *hourp, int *minp, int *secp)
101
{
102
    int hr24=0, hour;
103
    struct MSTE_RTC val;
104
 
105
    mste_rtc.mode=(mste_rtc.mode | 1);
106
    hr24=mste_rtc.mon_tens & 1;
107
    mste_rtc.mode=(mste_rtc.mode & ~1);
108
 
109
    mste_read(&val);
110
    *secp = val.sec_ones + val.sec_tens * 10;
111
    *minp = val.min_ones + val.min_tens * 10;
112
    hour = val.hr_ones + val.hr_tens * 10;
113
    if (!hr24) {
114
        if (hour == 12 || hour == 12 + 20)
115
            hour -= 12;
116
        if (hour >= 20)
117
            hour += 12 - 20;
118
    }
119
    *hourp = hour;
120
    *dayp = val.day_ones + val.day_tens * 10;
121
    *monp = val.mon_ones + val.mon_tens * 10;
122
    *yearp = val.year_ones + val.year_tens * 10 + 80;
123
}
124
 
125
 
126
void atari_tt_gettod (int *yearp, int *monp, int *dayp,
127
                      int *hourp, int *minp, int *secp)
128
{
129
    unsigned char       ctrl;
130
    int hour, pm;
131
 
132
    while (!(RTC_READ(RTC_FREQ_SELECT) & RTC_UIP)) ;
133
    while (RTC_READ(RTC_FREQ_SELECT) & RTC_UIP) ;
134
 
135
    *secp  = RTC_READ(RTC_SECONDS);
136
    *minp  = RTC_READ(RTC_MINUTES);
137
    hour = RTC_READ(RTC_HOURS);
138
    *dayp  = RTC_READ(RTC_DAY_OF_MONTH);
139
    *monp  = RTC_READ(RTC_MONTH);
140
    *yearp = RTC_READ(RTC_YEAR);
141
    pm = hour & 0x80;
142
    hour &= ~0x80;
143
 
144
    ctrl = RTC_READ(RTC_CONTROL);
145
 
146
    if (!(ctrl & RTC_DM_BINARY)) {
147
        BCD_TO_BIN(*secp);
148
        BCD_TO_BIN(*minp);
149
        BCD_TO_BIN(hour);
150
        BCD_TO_BIN(*dayp);
151
        BCD_TO_BIN(*monp);
152
        BCD_TO_BIN(*yearp);
153
    }
154
    if (!(ctrl & RTC_24H)) {
155
        if (!pm && hour == 12)
156
            hour = 0;
157
        else if (pm && hour != 12)
158
            hour += 12;
159
    }
160
    *hourp = hour;
161
 
162
    /* Adjust values (let the setup valid) */
163
    *yearp += atari_rtc_year_offset;
164
}
165
 
166
#define HWCLK_POLL_INTERVAL     5
167
 
168
int atari_mste_hwclk( int op, struct rtc_time *t )
169
{
170
    int hour, year;
171
    int hr24=0;
172
    struct MSTE_RTC val;
173
 
174
    mste_rtc.mode=(mste_rtc.mode | 1);
175
    hr24=mste_rtc.mon_tens & 1;
176
    mste_rtc.mode=(mste_rtc.mode & ~1);
177
 
178
    if (op) {
179
        /* write: prepare values */
180
 
181
        val.sec_ones = t->tm_sec % 10;
182
        val.sec_tens = t->tm_sec / 10;
183
        val.min_ones = t->tm_min % 10;
184
        val.min_tens = t->tm_min / 10;
185
        hour = t->tm_hour;
186
        if (!hr24) {
187
            if (hour > 11)
188
                hour += 20 - 12;
189
            if (hour == 0 || hour == 20)
190
                hour += 12;
191
        }
192
        val.hr_ones = hour % 10;
193
        val.hr_tens = hour / 10;
194
        val.day_ones = t->tm_mday % 10;
195
        val.day_tens = t->tm_mday / 10;
196
        val.mon_ones = (t->tm_mon+1) % 10;
197
        val.mon_tens = (t->tm_mon+1) / 10;
198
        year = t->tm_year - 80;
199
        val.year_ones = year % 10;
200
        val.year_tens = year / 10;
201
        val.weekday = t->tm_wday;
202
        mste_write(&val);
203
        mste_rtc.mode=(mste_rtc.mode | 1);
204
        val.year_ones = (year % 4);     /* leap year register */
205
        mste_rtc.mode=(mste_rtc.mode & ~1);
206
    }
207
    else {
208
        mste_read(&val);
209
        t->tm_sec = val.sec_ones + val.sec_tens * 10;
210
        t->tm_min = val.min_ones + val.min_tens * 10;
211
        hour = val.hr_ones + val.hr_tens * 10;
212
        if (!hr24) {
213
            if (hour == 12 || hour == 12 + 20)
214
                hour -= 12;
215
            if (hour >= 20)
216
                hour += 12 - 20;
217
        }
218
        t->tm_hour = hour;
219
        t->tm_mday = val.day_ones + val.day_tens * 10;
220
        t->tm_mon  = val.mon_ones + val.mon_tens * 10 - 1;
221
        t->tm_year = val.year_ones + val.year_tens * 10 + 80;
222
        t->tm_wday = val.weekday;
223
    }
224
    return 0;
225
}
226
 
227
int atari_tt_hwclk( int op, struct rtc_time *t )
228
{
229
    int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0;
230
    unsigned long       flags;
231
    unsigned char       ctrl;
232
    int pm = 0;
233
 
234
    ctrl = RTC_READ(RTC_CONTROL); /* control registers are
235
                                   * independent from the UIP */
236
 
237
    if (op) {
238
        /* write: prepare values */
239
 
240
        sec  = t->tm_sec;
241
        min  = t->tm_min;
242
        hour = t->tm_hour;
243
        day  = t->tm_mday;
244
        mon  = t->tm_mon + 1;
245
        year = t->tm_year - atari_rtc_year_offset;
246
        wday = t->tm_wday + (t->tm_wday >= 0);
247
 
248
        if (!(ctrl & RTC_24H)) {
249
            if (hour > 11) {
250
                pm = 0x80;
251
                if (hour != 12)
252
                    hour -= 12;
253
            }
254
            else if (hour == 0)
255
                hour = 12;
256
        }
257
 
258
        if (!(ctrl & RTC_DM_BINARY)) {
259
            BIN_TO_BCD(sec);
260
            BIN_TO_BCD(min);
261
            BIN_TO_BCD(hour);
262
            BIN_TO_BCD(day);
263
            BIN_TO_BCD(mon);
264
            BIN_TO_BCD(year);
265
            if (wday >= 0) BIN_TO_BCD(wday);
266
        }
267
    }
268
 
269
    /* Reading/writing the clock registers is a bit critical due to
270
     * the regular update cycle of the RTC. While an update is in
271
     * progress, registers 0..9 shouldn't be touched.
272
     * The problem is solved like that: If an update is currently in
273
     * progress (the UIP bit is set), the process sleeps for a while
274
     * (50ms). This really should be enough, since the update cycle
275
     * normally needs 2 ms.
276
     * If the UIP bit reads as 0, we have at least 244 usecs until the
277
     * update starts. This should be enough... But to be sure,
278
     * additionally the RTC_SET bit is set to prevent an update cycle.
279
     */
280
 
281
    while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
282
        current->state = TASK_INTERRUPTIBLE;
283
        schedule_timeout(HWCLK_POLL_INTERVAL);
284
    }
285
 
286
    save_flags(flags);
287
    cli();
288
    RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
289
    if (!op) {
290
        sec  = RTC_READ( RTC_SECONDS );
291
        min  = RTC_READ( RTC_MINUTES );
292
        hour = RTC_READ( RTC_HOURS );
293
        day  = RTC_READ( RTC_DAY_OF_MONTH );
294
        mon  = RTC_READ( RTC_MONTH );
295
        year = RTC_READ( RTC_YEAR );
296
        wday = RTC_READ( RTC_DAY_OF_WEEK );
297
    }
298
    else {
299
        RTC_WRITE( RTC_SECONDS, sec );
300
        RTC_WRITE( RTC_MINUTES, min );
301
        RTC_WRITE( RTC_HOURS, hour + pm);
302
        RTC_WRITE( RTC_DAY_OF_MONTH, day );
303
        RTC_WRITE( RTC_MONTH, mon );
304
        RTC_WRITE( RTC_YEAR, year );
305
        if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday );
306
    }
307
    RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET );
308
    restore_flags(flags);
309
 
310
    if (!op) {
311
        /* read: adjust values */
312
 
313
        if (hour & 0x80) {
314
            hour &= ~0x80;
315
            pm = 1;
316
        }
317
 
318
        if (!(ctrl & RTC_DM_BINARY)) {
319
            BCD_TO_BIN(sec);
320
            BCD_TO_BIN(min);
321
            BCD_TO_BIN(hour);
322
            BCD_TO_BIN(day);
323
            BCD_TO_BIN(mon);
324
            BCD_TO_BIN(year);
325
            BCD_TO_BIN(wday);
326
        }
327
 
328
        if (!(ctrl & RTC_24H)) {
329
            if (!pm && hour == 12)
330
                hour = 0;
331
            else if (pm && hour != 12)
332
                hour += 12;
333
        }
334
 
335
        t->tm_sec  = sec;
336
        t->tm_min  = min;
337
        t->tm_hour = hour;
338
        t->tm_mday = day;
339
        t->tm_mon  = mon - 1;
340
        t->tm_year = year + atari_rtc_year_offset;
341
        t->tm_wday = wday - 1;
342
    }
343
 
344
    return( 0 );
345
}
346
 
347
 
348
int atari_mste_set_clock_mmss (unsigned long nowtime)
349
{
350
    short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
351
    struct MSTE_RTC val;
352
    unsigned char rtc_minutes;
353
 
354
    mste_read(&val);
355
    rtc_minutes= val.min_ones + val.min_tens * 10;
356
    if ((rtc_minutes < real_minutes
357
         ? real_minutes - rtc_minutes
358
         : rtc_minutes - real_minutes) < 30)
359
    {
360
        val.sec_ones = real_seconds % 10;
361
        val.sec_tens = real_seconds / 10;
362
        val.min_ones = real_minutes % 10;
363
        val.min_tens = real_minutes / 10;
364
        mste_write(&val);
365
    }
366
    else
367
        return -1;
368
    return 0;
369
}
370
 
371
int atari_tt_set_clock_mmss (unsigned long nowtime)
372
{
373
    int retval = 0;
374
    short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
375
    unsigned char save_control, save_freq_select, rtc_minutes;
376
 
377
    save_control = RTC_READ (RTC_CONTROL); /* tell the clock it's being set */
378
    RTC_WRITE (RTC_CONTROL, save_control | RTC_SET);
379
 
380
    save_freq_select = RTC_READ (RTC_FREQ_SELECT); /* stop and reset prescaler */
381
    RTC_WRITE (RTC_FREQ_SELECT, save_freq_select | RTC_DIV_RESET2);
382
 
383
    rtc_minutes = RTC_READ (RTC_MINUTES);
384
    if (!(save_control & RTC_DM_BINARY))
385
        BCD_TO_BIN (rtc_minutes);
386
 
387
    /* Since we're only adjusting minutes and seconds, don't interfere
388
       with hour overflow.  This avoids messing with unknown time zones
389
       but requires your RTC not to be off by more than 30 minutes.  */
390
    if ((rtc_minutes < real_minutes
391
         ? real_minutes - rtc_minutes
392
         : rtc_minutes - real_minutes) < 30)
393
        {
394
            if (!(save_control & RTC_DM_BINARY))
395
                {
396
                    BIN_TO_BCD (real_seconds);
397
                    BIN_TO_BCD (real_minutes);
398
                }
399
            RTC_WRITE (RTC_SECONDS, real_seconds);
400
            RTC_WRITE (RTC_MINUTES, real_minutes);
401
        }
402
    else
403
        retval = -1;
404
 
405
    RTC_WRITE (RTC_FREQ_SELECT, save_freq_select);
406
    RTC_WRITE (RTC_CONTROL, save_control);
407
    return retval;
408
}
409
 
410
/*
411
 * Local variables:
412
 *  c-indent-level: 4
413
 *  tab-width: 8
414
 * End:
415
 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.