source: rtems/c/src/lib/libbsp/powerpc/ppcn_60x/tod/tod.c @ f05b2ac

4.104.114.84.95
Last change on this file since f05b2ac was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

  • Property mode set to 100644
File size: 12.2 KB
Line 
1/*
2 *  COPYRIGHT (c) 1998 by Radstone Technology
3 *
4 *
5 * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
6 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
7 * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
8 * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
9 *
10 * You are hereby granted permission to use, copy, modify, and distribute
11 * this file, provided that this notice, plus the above copyright notice
12 * and disclaimer, appears in all copies. Radstone Technology will provide
13 * no support for this code.
14 *
15 */
16
17#define MIN_YEAR 1996
18
19#include <stdlib.h>
20#include "bsp.h"
21#include "cmos.h"
22#include "../nvram/mk48t18.h"
23
24#define Bin2BCD(Value) (((Value / 10) << 4) | (Value % 10))
25#define BCD2Bin(BcdValue) ((BcdValue >> 4) * 10 + (BcdValue & 0x0f))
26
27/*
28 * Private types
29 */
30typedef
31void
32(*PTIMESET)
33(
34        rtems_time_of_day *pTOD
35);
36
37typedef
38boolean
39(*PTIMEGET)
40(
41        rtems_time_of_day *pTOD
42);
43
44typedef struct _TIME_ENTRY_TABLE
45{
46    PTIMESET    SetTime;
47    PTIMEGET    GetTime;
48} TIME_ENTRY_TABLE, *PTIME_ENTRY_TABLE;
49
50/*
51 * Private routines
52 */
53
54/*
55 * DS1385 specific routines
56 */
57static void timeDsSet(rtems_time_of_day *pTOD);
58static boolean timeDsGet(rtems_time_of_day *pTOD);
59
60/*
61 * MK48T18 specific routines
62 */
63static void timeMkSet(rtems_time_of_day *pTOD);
64static boolean timeMkGet(rtems_time_of_day *pTOD);
65
66TIME_ENTRY_TABLE timeDsTable =
67{
68        timeDsSet,
69        timeDsGet
70};
71
72TIME_ENTRY_TABLE timeMkTable =
73{
74        timeMkSet,
75        timeMkGet
76};
77
78/*
79 * Private variables
80 */
81static PTIME_ENTRY_TABLE pTimeFunc;
82
83/*
84 * Mutual-exclusion semaphore
85 */
86static rtems_id semRTC;
87
88/*
89 * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
90 */
91uint8_t
92GregorianDay(rtems_time_of_day *pTOD)
93{
94        boolean isLeap;
95        unsigned long leapsToDate;
96        unsigned long lastYear;
97        unsigned long day;
98        unsigned long MonthOffset[] = { 0, 31, 59, 90, 120, 151,
99                                        181, 212, 243, 273, 304, 334 };
100
101        lastYear=pTOD->year-1;
102
103        /*
104         * Number of leap corrections to apply up to end of last year
105         */
106        leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
107
108        /*
109         * This year is a leap year if it is divisible by 4 except when it is
110         * divisible by 100 unless it is divisible by 400
111         *
112         * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
113         */
114        isLeap = (pTOD->year%4==0) &&
115                         ((pTOD->year%100!=0) || (pTOD->year%400==0));
116
117        if(isLeap && (pTOD->month>2))
118        {
119                day=1;
120        }
121        else
122        {
123                day=0;
124        }
125
126        day += lastYear*365 + leapsToDate + MonthOffset[pTOD->month-1] +
127                   pTOD->day;
128
129        return((uint8_t)(day%7));
130}
131
132void
133DsWriteRawClockRegister (
134        uint8_t         Register,
135        uint8_t         Value
136)
137
138/*++
139
140Routine Description:
141
142    This routine reads the specified realtime clock register.
143
144    This function was added to bridge the BCD format of the IBM roms
145    and the binary formate of NT
146
147Arguments:
148
149    Register - Supplies the number of the register whose value is read.
150
151Return Value:
152
153    The value of the register is returned as the function value.
154
155--*/
156
157{
158        outport_byte((uint8_t*)RTC_PORT, Register & 0x7f);
159
160        /* Read the realtime clock register value. */
161
162        outport_byte((uint8_t*)(RTC_PORT + 1), Value);
163        return;
164}
165
166uint8_t
167DsReadRawClockRegister (
168        uint8_t         Register
169)
170
171/*++
172
173Routine Description:
174
175    This routine reads the specified realtime clock register.
176
177    This function was added to bridge the BCD format of the IBM roms
178    and the binary formate of NT
179
180Arguments:
181
182    Register - Supplies the number of the register whose value is read.
183
184Return Value:
185
186    The value of the register is returned as the function value.
187
188--*/
189
190{
191        uint8_t         ucDataByte;
192
193        outport_byte((uint8_t*)RTC_PORT, Register & 0x7f);
194
195        /* Read the realtime clock register value. */
196
197        inport_byte((uint8_t*)(RTC_PORT + 1), ucDataByte);
198        return ucDataByte;
199}
200
201void
202DsWriteClockRegister (
203        uint8_t         Register,
204        uint8_t         Value
205)
206
207/*++
208
209Routine Description:
210
211    This routine writes the specified value to the specified realtime
212    clock register.
213
214Arguments:
215
216    Register - Supplies the number of the register whose value is written.
217
218    Value - Supplies the value that is written to the specified register.
219
220Return Value:
221
222    The value of the register is returned as the function value.
223
224--*/
225
226{
227        uint8_t         BcdValue;
228
229        BcdValue = Bin2BCD(Value);
230        DsWriteRawClockRegister(Register, BcdValue);
231        return;
232}
233
234uint8_t
235DsReadClockRegister (
236        uint8_t         Register
237)
238
239/*++
240
241Routine Description:
242
243    This routine reads the specified realtime clock register.
244
245Arguments:
246
247    Register - Supplies the number of the register whose value is read.
248
249Return Value:
250
251    The value of the register is returned as the function value.
252
253--*/
254
255{
256        uint8_t         BcdValue;
257
258        BcdValue =  DsReadRawClockRegister(Register);
259        return BCD2Bin(BcdValue);
260}
261
262void
263timeDsSet (
264    rtems_time_of_day *pTOD
265    )
266
267/*++
268
269Routine Description:
270
271    This routine sets the realtime clock.
272
273    N.B. This routine assumes that the caller has provided any required
274        synchronization to set the realtime clock information.
275
276Arguments:
277
278    pTOD - Supplies a pointer to a time structure that specifies the
279        realtime clock information.
280
281Return Value:
282
283    If the power to the realtime clock has not failed, then the time
284    values are written to the realtime clock and a value of TRUE is
285    returned. Otherwise, a value of FALSE is returned.
286
287--*/
288
289{
290        uint8_t         ucDataByte;
291        PCMOS_MAP pCMOS = (PCMOS_MAP)0;
292
293        /* If the realtime clock battery is still functioning, then write */
294        /* the realtime clock values, and return a function value of TRUE. */
295        /* Otherwise, return a function value of FALSE. */
296
297        ucDataByte = DsReadRawClockRegister(RTC_CONTROL_REGISTERD);
298        if (ucDataByte&DS1385_REGD_VALID)
299        {
300                /* Set the realtime clock control to set the time. */
301
302                ucDataByte = DS1385_REGB_HOURS_FMT | DS1385_REGB_SET_TIME;
303                DsWriteRawClockRegister(RTC_CONTROL_REGISTERB, ucDataByte);
304
305                /* Write the realtime clock values. */
306
307                DsWriteClockRegister(RTC_YEAR,
308                                     (uint8_t)(pTOD->year%100));
309                if(pTOD->year>=100)
310                {
311                        DsWriteClockRegister((uint8_t)
312                                             ((unsigned long)&pCMOS->Century),
313                                             pTOD->year/100);
314                }
315                DsWriteClockRegister(RTC_MONTH,
316                                     (uint8_t)pTOD->month);
317                DsWriteClockRegister(RTC_DAY_OF_MONTH,
318                                     (uint8_t)pTOD->day);
319                DsWriteClockRegister(RTC_DAY_OF_WEEK,
320                                     (uint8_t)
321                                     (GregorianDay(pTOD) + 1));
322                DsWriteClockRegister(RTC_HOUR,
323                                     (uint8_t)pTOD->hour);
324                DsWriteClockRegister(RTC_MINUTE,
325                                     (uint8_t)pTOD->minute);
326                DsWriteClockRegister(RTC_SECOND,
327                                     (uint8_t)pTOD->second);
328
329                /* Set the realtime clock control to update the time. */
330
331                ucDataByte &= ~DS1385_REGB_SET_TIME;
332                DsWriteRawClockRegister(RTC_CONTROL_REGISTERB, ucDataByte);
333                return;
334
335        }
336        else
337        {
338                return;
339        }
340}
341
342boolean
343timeDsGet (
344    rtems_time_of_day *pTOD
345    )
346
347/*++
348
349Routine Description:
350
351    This routine queries the realtime clock.
352
353Arguments:
354
355    pTOD - Supplies a pointer to a time structure that receives
356        the realtime clock information.
357
358Return Value:
359
360    If the power to the realtime clock has not failed, then the time
361    values are read from the realtime clock and a value of TRUE is
362    returned. Otherwise, a value of FALSE is returned.
363
364--*/
365
366{
367        uint8_t         ucDataByte;
368        PCMOS_MAP pCMOS = (PCMOS_MAP)0;
369
370        /* If the realtime clock battery is still functioning, then read */
371        /* the realtime clock values, and return a function value of TRUE. */
372        /* Otherwise, return a function value of FALSE. */
373
374        ucDataByte = DsReadRawClockRegister(RTC_CONTROL_REGISTERD);
375        if(ucDataByte&DS1385_REGD_VALID)
376        {
377                /* Wait until the realtime clock is not being updated. */
378
379                do
380                {
381                        ucDataByte=DsReadRawClockRegister(RTC_CONTROL_REGISTERA);
382                } while (ucDataByte&DS1385_REGA_UIP);
383
384                /* Read the realtime clock values. */
385
386                pTOD->year=(uint16_t)
387                                  (DsReadClockRegister(
388                                   (uint8_t)
389                                   (unsigned long)&pCMOS->Century)
390                                  *100 + DsReadClockRegister(RTC_YEAR));
391                pTOD->month=DsReadClockRegister(RTC_MONTH);
392                pTOD->day=DsReadClockRegister(RTC_DAY_OF_MONTH);
393                pTOD->hour=DsReadClockRegister(RTC_HOUR);
394                pTOD->minute=DsReadClockRegister(RTC_MINUTE);
395                pTOD->second=DsReadClockRegister(RTC_SECOND);
396                return TRUE;
397        }
398        else
399        {
400                return FALSE;
401        }
402}
403
404void
405timeMkSet (
406    rtems_time_of_day *pTOD
407    )
408
409/*++
410
411Routine Description:
412
413    This routine sets the realtime clock.
414
415    N.B. This routine assumes that the caller has provided any required
416        synchronization to set the realtime clock information.
417
418Arguments:
419
420    pTOD - Supplies a pointer to a time structure that specifies the
421        realtime clock information.
422
423Return Value:
424
425    If the power to the realtime clock has not failed, then the time
426    values are written to the realtime clock and a value of TRUE is
427    returned. Otherwise, a value of FALSE is returned.
428
429--*/
430
431{
432        PMK48T18_NVRAM_MAP pNvRAM = MK48T18_BASE;
433
434        /*
435         * Set the RTC into write mode
436         */
437        pNvRAM->CMOS.Control|=MK48T18_CTRL_WRITE;
438        EIEIO;
439
440        /*
441         * Write the realtime clock values.
442         */
443
444        pNvRAM->CMOS.Year = (uint8_t)Bin2BCD(pTOD->year%100);
445        if(pTOD->year>=100)
446        {
447            pNvRAM->CMOS.Century=(uint8_t)
448                                 Bin2BCD(pTOD->year/100);
449        }
450        pNvRAM->CMOS.Month  = (uint8_t)Bin2BCD(pTOD->month);
451        pNvRAM->CMOS.Date   = (uint8_t)Bin2BCD(pTOD->day);
452        pNvRAM->CMOS.Day    = (uint8_t)(GregorianDay(pTOD) + 1);
453        pNvRAM->CMOS.Hour   = (uint8_t)Bin2BCD(pTOD->hour);
454        pNvRAM->CMOS.Minute = (uint8_t)Bin2BCD(pTOD->minute);
455        pNvRAM->CMOS.Second = (uint8_t)Bin2BCD(pTOD->second);
456
457        /*
458         * Set the realtime clock control to update the time.
459         */
460
461        EIEIO;
462        pNvRAM->CMOS.Control&=~MK48T18_CTRL_WRITE;
463}
464
465boolean
466timeMkGet (
467    rtems_time_of_day *pTOD
468    )
469
470/*++
471
472Routine Description:
473
474    This routine queries the realtime clock.
475
476    N.B. This routine is required to provide any synchronization necessary
477         to query the realtime clock information.
478
479Arguments:
480
481    pTOD - Supplies a pointer to a time structure that receives
482        the realtime clock information.
483
484Return Value:
485
486    If the power to the realtime clock has not failed, then the time
487    values are read from the realtime clock and a value of TRUE is
488    returned. Otherwise, a value of FALSE is returned.
489
490--*/
491
492{
493        PMK48T18_NVRAM_MAP pNvRAM = MK48T18_BASE;
494
495        /*
496         * Set the RTC into read mode
497         */
498        pNvRAM->CMOS.Control|=MK48T18_CTRL_READ;
499        EIEIO;
500
501        /*
502         * Read the realtime clock values.
503         */
504
505        pTOD->year = (uint16_t)(100*BCD2Bin(pNvRAM->CMOS.Century)+
506                                              BCD2Bin(pNvRAM->CMOS.Year));
507        pTOD->month = (uint8_t)BCD2Bin(pNvRAM->CMOS.Month);
508        pTOD->day = (uint8_t)BCD2Bin(pNvRAM->CMOS.Date);
509        pTOD->hour = (uint8_t)BCD2Bin(pNvRAM->CMOS.Hour);
510        pTOD->minute = (uint8_t)BCD2Bin(pNvRAM->CMOS.Minute);
511        pTOD->second = (uint8_t)BCD2Bin(pNvRAM->CMOS.Second);
512
513        /*
514         * Set the realtime clock control to normal mode.
515         */
516        EIEIO;
517        pNvRAM->CMOS.Control&=~MK48T18_CTRL_READ;
518
519        return TRUE;
520}
521
522/*
523 * Set up entry table
524 */
525void
526InitializeRTC(void)
527{
528        rtems_status_code sc;
529
530        switch(ucSystemType)
531        {
532                case SYS_TYPE_PPC1:
533                {
534                        if(ucBoardRevMaj<5)
535                        {
536                                pTimeFunc=&timeDsTable;
537                                break;
538                        }
539                        /*
540                         * For the 005 and later drop through to the PPC1a support
541                         */
542                }
543
544                case SYS_TYPE_PPC1a:
545                {
546                        pTimeFunc=&timeMkTable;
547                        break;
548                }
549
550                default:
551                {
552                        pTimeFunc=&timeDsTable;
553                        break;
554                }
555        }
556
557        /*
558         * Set up mutex semaphore
559         */
560        sc = rtems_semaphore_create (
561                rtems_build_name ('R', 'T', 'C', 's'),
562                1,
563                RTEMS_BINARY_SEMAPHORE |
564                RTEMS_INHERIT_PRIORITY |
565                RTEMS_PRIORITY,
566                RTEMS_NO_PRIORITY,
567                &semRTC);
568        if (sc != RTEMS_SUCCESSFUL)
569        {
570                rtems_fatal_error_occurred (sc);
571        }
572}
573
574void setRealTimeToRTEMS()
575{
576        rtems_time_of_day rtc_tod;
577
578        rtems_semaphore_obtain(semRTC, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
579        (pTimeFunc->GetTime)(&rtc_tod);
580        rtems_semaphore_release(semRTC);
581
582        /*
583         * Millenium fix...
584         *
585         * If year is earlier than MIN_YEAR then assume the clock has wrapped from
586         * 1999 to 1900 so advance by a century
587         */
588        if(rtc_tod.year<MIN_YEAR)
589        {
590                rtc_tod.year+=100;
591                rtems_semaphore_obtain(semRTC, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
592                (pTimeFunc->SetTime)(&rtc_tod);
593                rtems_semaphore_release(semRTC);
594        }
595
596        rtc_tod.ticks=0;
597
598        rtems_clock_set( &rtc_tod );
599}
600
601void setRealTimeFromRTEMS()
602{
603        rtems_time_of_day rtems_tod;
604
605        rtems_clock_get( RTEMS_CLOCK_GET_TOD, &rtems_tod );
606        rtems_semaphore_obtain(semRTC, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
607        (pTimeFunc->SetTime)(&rtems_tod);
608        rtems_semaphore_release(semRTC);
609}
610
611int checkRealTime()
612{
613  return 0;
614}
Note: See TracBrowser for help on using the repository browser.