source: rtems/c/src/libchip/rtc/mc146818a.c @ 6640459d

4.104.114.95
Last change on this file since 6640459d was 6640459d, checked in by Ralf Corsepius <ralf.corsepius@…>, on Sep 7, 2008 at 3:44:14 AM

Convert to "bool".

  • Property mode set to 100644
File size: 4.2 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
29#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
30#define To_BCD( _x )   ((((_x) / 10) << 4) + ((_x) % 10))
31
32/*
33 * See if chip is present
34 */
35bool mc146818a_probe(
36  int minor
37)
38{
39  uint32_t     mc146818a;
40  getRegister_f  getReg;
41  uint32_t     value;
42
43  /*
44   * Verify that chip is present and that time is valid
45   */
46  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
47  getReg = RTC_Table[ minor ].getRegister;
48  value = (*getReg)( mc146818a, MC146818A_STATUSD );
49  if ((value == 0) || (value == 0xFF))
50    return false;
51  return true;
52}
53
54/*
55 * Initialize chip
56 */
57void mc146818a_initialize(
58  int minor
59)
60{
61  uint32_t     mc146818a;
62  getRegister_f  getReg;
63  setRegister_f  setReg;
64
65  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
66  getReg = RTC_Table[ minor ].getRegister;
67  setReg = RTC_Table[ minor ].setRegister;
68
69  (*setReg)( mc146818a, MC146818A_STATUSA, MC146818ASA_DIVIDER|MC146818ASA_1024 );
70  (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_24HR );
71}
72
73/*
74 * Read time from chip
75 */
76int mc146818a_get_time(
77  int                minor,
78  rtems_time_of_day *time
79)
80{
81  uint32_t     mc146818a;
82  getRegister_f  getReg;
83  uint32_t     value;
84  rtems_interrupt_level level;
85
86  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
87  getReg = RTC_Table[ minor ].getRegister;
88
89  /*
90   * No time if power failed
91   */
92  if (((*getReg)( mc146818a, MC146818A_STATUSD ) & MC146818ASD_PWR) == 0)
93    return -1;
94
95  /*
96   * Wait for time update to complete
97   */
98  rtems_interrupt_disable( level );
99  while (((*getReg)( mc146818a, MC146818A_STATUSA ) & MC146818ASA_TUP) != 0) {
100      rtems_interrupt_flash( level );
101  }
102 
103  /*
104   * Read the time (we have at least 244 usec to do this)
105   */
106  value = (*getReg)( mc146818a, MC146818A_YEAR );
107  value = From_BCD( value );
108  if ( value < 88 )
109    time->year = 2000 + value;
110  else
111    time->year = 1900 + value;
112
113  value = (*getReg)( mc146818a, MC146818A_MONTH );
114  time->month = From_BCD( value );
115
116  value = (*getReg)( mc146818a, MC146818A_DAY );
117  time->day = From_BCD( value );
118
119  value = (*getReg)( mc146818a, MC146818A_HRS );
120  time->hour = From_BCD( value );
121
122  value = (*getReg)( mc146818a, MC146818A_MIN );
123  time->minute = From_BCD( value );
124
125  value = (*getReg)( mc146818a, MC146818A_SEC );
126  rtems_interrupt_enable( level );
127  time->second = From_BCD( value );
128  time->ticks  = 0;
129
130  return 0;
131}
132
133/*
134 * Set time into chip
135 */
136int mc146818a_set_time(
137  int                minor,
138  rtems_time_of_day *time
139)
140{
141  uint32_t     mc146818a;
142  getRegister_f  getReg;
143  setRegister_f  setReg;
144
145  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
146  getReg = RTC_Table[ minor ].getRegister;
147  setReg = RTC_Table[ minor ].setRegister;
148
149  /*
150   * Stop the RTC
151   */
152  (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_HALT|MC146818ASB_24HR );
153 
154  if ( time->year >= 2088 )
155    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
156
157  (*setReg)( mc146818a, MC146818A_YEAR,  To_BCD(time->year % 100) );
158  (*setReg)( mc146818a, MC146818A_MONTH, To_BCD(time->month) );
159  (*setReg)( mc146818a, MC146818A_DAY,   To_BCD(time->day) );
160  (*setReg)( mc146818a, MC146818A_HRS,   To_BCD(time->hour) );
161  (*setReg)( mc146818a, MC146818A_MIN,   To_BCD(time->minute) );
162  (*setReg)( mc146818a, MC146818A_SEC,   To_BCD(time->second) );
163 
164  /*
165   * Restart the RTC
166   */
167  (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_24HR );
168  return 0;
169}
170
171/*
172 *  Driver function table
173 */
174rtc_fns mc146818a_fns = {
175  mc146818a_initialize,
176  mc146818a_get_time,
177  mc146818a_set_time
178};
Note: See TracBrowser for help on using the repository browser.