source: rtems/bsps/shared/dev/rtc/mc146818a.c

Last change on this file was d6ebf40, checked in by Joel Sherrill <joel@…>, on 06/14/22 at 17:15:38

bsps/shared/*: Change license to BSD-2

Updates #3053.

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/*
4 *  This file interfaces with the real-time clock found in
5 *  a Motorola MC146818A (common on PC hardware)
6 *
7 *  Year 2K Notes:
8 *
9 *  This chip only uses a two digit field to store the year.  This
10 *  code uses the RTEMS Epoch as a pivot year.  This lets us map the
11 *  two digit year field as follows:
12 *
13 *    + two digit years 0-87 are mapped to 2000-2087.
14 *    + two digit years 88-99 are mapped to 1988-1999.
15 *
16 *  This is less than the time span supported by RTEMS.
17 *
18 *  COPYRIGHT (c) 1989-1999.
19 *  On-Line Applications Research Corporation (OAR).
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 *    notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 *    notice, this list of conditions and the following disclaimer in the
28 *    documentation and/or other materials provided with the distribution.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 * POSSIBILITY OF SUCH DAMAGE.
41 */
42#include <rtems.h>
43#include <libchip/rtc.h>
44#include <libchip/mc146818a.h>
45
46#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
47#define To_BCD( _x )   ((((_x) / 10) << 4) + ((_x) % 10))
48
49/*
50 * See if chip is present
51 */
52bool mc146818a_probe(
53  int minor
54)
55{
56  uint32_t     mc146818a;
57  getRegister_f  getReg;
58  uint32_t     value;
59
60  /*
61   * Verify that chip is present and that time is valid
62   */
63  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
64  getReg = RTC_Table[ minor ].getRegister;
65  value = (*getReg)( mc146818a, MC146818A_STATUSD );
66  if ((value == 0) || (value == 0xFF))
67    return false;
68  return true;
69}
70
71/*
72 * Initialize chip
73 */
74static void mc146818a_initialize(
75  int minor
76)
77{
78  uintptr_t      mc146818a;
79  setRegister_f  setReg;
80
81  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
82  setReg = RTC_Table[ minor ].setRegister;
83
84  (*setReg)(
85    mc146818a,
86    MC146818A_STATUSA,
87    MC146818ASA_DIVIDER|MC146818ASA_1024
88  );
89  (*setReg)(
90    mc146818a,
91    MC146818A_STATUSB,
92    MC146818ASB_24HR
93  );
94}
95
96/*
97 * Read time from chip
98 */
99static int mc146818a_get_time(
100  int                minor,
101  rtems_time_of_day *time
102)
103{
104  uintptr_t             mc146818a;
105  getRegister_f         getReg;
106  uint32_t              value;
107  rtems_interrupt_level level;
108
109  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
110  getReg = RTC_Table[ minor ].getRegister;
111
112  /*
113   * No time if power failed
114   */
115  if (((*getReg)( mc146818a, MC146818A_STATUSD ) & MC146818ASD_PWR) == 0)
116    return -1;
117
118  /*
119   * Wait for time update to complete
120   */
121  rtems_interrupt_disable( level );
122  while (((*getReg)( mc146818a, MC146818A_STATUSA ) & MC146818ASA_TUP) != 0) {
123      rtems_interrupt_flash( level );
124  }
125
126  /*
127   * Read the time (we have at least 244 usec to do this)
128   */
129  value = (*getReg)( mc146818a, MC146818A_YEAR );
130  value = From_BCD( value );
131  if ( value < 88 )
132    time->year = 2000 + value;
133  else
134    time->year = 1900 + value;
135
136  value = (*getReg)( mc146818a, MC146818A_MONTH );
137  time->month = From_BCD( value );
138
139  value = (*getReg)( mc146818a, MC146818A_DAY );
140  time->day = From_BCD( value );
141
142  value = (*getReg)( mc146818a, MC146818A_HRS );
143  time->hour = From_BCD( value );
144
145  value = (*getReg)( mc146818a, MC146818A_MIN );
146  time->minute = From_BCD( value );
147
148  value = (*getReg)( mc146818a, MC146818A_SEC );
149  rtems_interrupt_enable( level );
150  time->second = From_BCD( value );
151  time->ticks  = 0;
152
153  return 0;
154}
155
156/*
157 * Set time into chip
158 */
159static int mc146818a_set_time(
160  int                      minor,
161  const rtems_time_of_day *time
162)
163{
164  uint32_t     mc146818a;
165  setRegister_f  setReg;
166
167  mc146818a = RTC_Table[ minor ].ulCtrlPort1;
168  setReg = RTC_Table[ minor ].setRegister;
169
170  /*
171   * Stop the RTC
172   */
173  (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_HALT|MC146818ASB_24HR );
174
175  if ( time->year >= 2088 )
176    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
177
178  (*setReg)( mc146818a, MC146818A_YEAR,  To_BCD(time->year % 100) );
179  (*setReg)( mc146818a, MC146818A_MONTH, To_BCD(time->month) );
180  (*setReg)( mc146818a, MC146818A_DAY,   To_BCD(time->day) );
181  (*setReg)( mc146818a, MC146818A_HRS,   To_BCD(time->hour) );
182  (*setReg)( mc146818a, MC146818A_MIN,   To_BCD(time->minute) );
183  (*setReg)( mc146818a, MC146818A_SEC,   To_BCD(time->second) );
184
185  /*
186   * Restart the RTC
187   */
188  (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_24HR );
189  return 0;
190}
191
192/*
193 *  Driver function table
194 */
195rtc_fns mc146818a_fns = {
196  mc146818a_initialize,
197  mc146818a_get_time,
198  mc146818a_set_time
199};
Note: See TracBrowser for help on using the repository browser.