source: rtems/c/src/libchip/rtc/mc146818a.c @ 5fb56e6

4.104.114.84.95
Last change on this file since 5fb56e6 was 5fb56e6, checked in by Eric Norum <WENorum@…>, on 10/11/04 at 20:13:31

Don't get duplication rtc_probe() definitions.

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/*
2 *  This file interfaces with the real-time clock found in
3 *  a Motorola MC146818A (common on PC hardware)
4 *
5 *  Year 2K Notes:
6 *
7 *  This chip only uses a two digit field to store the year.  This
8 *  code uses the RTEMS Epoch as a pivot year.  This lets us map the
9 *  two digit year field as follows:
10 *
11 *    + two digit years 0-87 are mapped to 2000-2087.
12 *    + two digit years 88-99 are mapped to 1988-1999.
13 *
14 *  This is less than the time span supported by RTEMS.
15 *
16 *  COPYRIGHT (c) 1989-1999.
17 *  On-Line Applications Research Corporation (OAR).
18 *
19 *  The license and distribution terms for this file may be
20 *  found in the file LICENSE in this distribution or at
21 *  http://www.rtems.com/license/LICENSE.
22 *
23 *  $Id$
24 */
25#include <rtems.h>
26#include <libchip/rtc.h>
27#include <libchip/mc146818a.h>
28#include <bsp.h>
29
30#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
31#define To_BCD( _x )   ((((_x) / 10) << 4) + ((_x) % 10))
32
33/*
34 * See if chip is present
35 */
36boolean mc146818a_probe(
37  int minor
38)
39{
40  unsigned32     mc146818a;
41  getRegister_f  getReg;
42  unsigned32     value;
43
44  /*
45   * Verify that chip is present and that time is valid
46   */
47  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
48  getReg = RTC_Table[ minor ].getRegister;
49  value = (*getReg)( mc146818a, MC146818A_STATUSD );
50  if ((value == 0) || (value == 0xFF))
51    return FALSE;
52  return TRUE;
53}
54
55/*
56 * Initialize chip
57 */
58void mc146818a_initialize(
59  int minor
60)
61{
62  unsigned32     mc146818a;
63  getRegister_f  getReg;
64  setRegister_f  setReg;
65
66  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
67  getReg = RTC_Table[ minor ].getRegister;
68  setReg = RTC_Table[ minor ].setRegister;
69
70  (*setReg)( mc146818a, MC146818A_STATUSA, MC146818ASA_DIVIDER|MC146818ASA_1024 );
71  (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_24HR );
72}
73
74/*
75 * Read time from chip
76 */
77int mc146818a_get_time(
78  int                minor,
79  rtems_time_of_day *time
80)
81{
82  unsigned32     mc146818a;
83  getRegister_f  getReg;
84  unsigned32     value;
85  rtems_interrupt_level level;
86
87  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
88  getReg = RTC_Table[ minor ].getRegister;
89
90  /*
91   * No time if power failed
92   */
93  if (((*getReg)( mc146818a, MC146818A_STATUSD ) & MC146818ASD_PWR) == 0)
94    return -1;
95
96  /*
97   * Wait for time update to complete
98   */
99  rtems_interrupt_disable( level );
100  while (((*getReg)( mc146818a, MC146818A_STATUSA ) & MC146818ASA_TUP) != 0) {
101      rtems_interrupt_flash( level );
102  }
103 
104  /*
105   * Read the time (we have at least 244 usec to do this)
106   */
107  value = (*getReg)( mc146818a, MC146818A_YEAR );
108  value = From_BCD( value );
109  if ( value < 88 )
110    time->year = 2000 + value;
111  else
112    time->year = 1900 + value;
113
114  value = (*getReg)( mc146818a, MC146818A_MONTH );
115  time->month = From_BCD( value );
116
117  value = (*getReg)( mc146818a, MC146818A_DAY );
118  time->day = From_BCD( value );
119
120  value = (*getReg)( mc146818a, MC146818A_HRS );
121  time->hour = From_BCD( value );
122
123  value = (*getReg)( mc146818a, MC146818A_MIN );
124  time->minute = From_BCD( value );
125
126  value = (*getReg)( mc146818a, MC146818A_SEC );
127  rtems_interrupt_enable( level );
128  time->second = From_BCD( value );
129  time->ticks  = 0;
130
131  return 0;
132}
133
134/*
135 * Set time into chip
136 */
137int mc146818a_set_time(
138  int                minor,
139  rtems_time_of_day *time
140)
141{
142  unsigned32     mc146818a;
143  getRegister_f  getReg;
144  setRegister_f  setReg;
145
146  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
147  getReg = RTC_Table[ minor ].getRegister;
148  setReg = RTC_Table[ minor ].setRegister;
149
150  /*
151   * Stop the RTC
152   */
153  (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_HALT|MC146818ASB_24HR );
154 
155  if ( time->year >= 2088 )
156    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
157
158  (*setReg)( mc146818a, MC146818A_YEAR,  To_BCD(time->year % 100) );
159  (*setReg)( mc146818a, MC146818A_MONTH, To_BCD(time->month) );
160  (*setReg)( mc146818a, MC146818A_DAY,   To_BCD(time->day) );
161  (*setReg)( mc146818a, MC146818A_HRS,   To_BCD(time->hour) );
162  (*setReg)( mc146818a, MC146818A_MIN,   To_BCD(time->minute) );
163  (*setReg)( mc146818a, MC146818A_SEC,   To_BCD(time->second) );
164 
165  /*
166   * Restart the RTC
167   */
168  (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_24HR );
169  return 0;
170}
171
172/*
173 *  Driver function table
174 */
175rtc_fns mc146818a_fns = {
176  mc146818a_initialize,
177  mc146818a_get_time,
178  mc146818a_set_time
179};
Note: See TracBrowser for help on using the repository browser.