summaryrefslogtreecommitdiffstats
path: root/bsps/shared/dev/rtc
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-03 07:20:11 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-04 10:13:28 +0200
commit27de4e1fb8bcdbdd8cb882fc0d7a2c152b4e027a (patch)
treedef0664dcddc53fd5d599b455c64f76ca2293606 /bsps/shared/dev/rtc
parentbsps: Move config macros to RTEMS_BSP_CONFIGURE (diff)
downloadrtems-27de4e1fb8bcdbdd8cb882fc0d7a2c152b4e027a.tar.bz2
bsps: Move libchip to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps/shared/dev/rtc')
-rw-r--r--bsps/shared/dev/rtc/README.ds16433
-rw-r--r--bsps/shared/dev/rtc/README.icm717048
-rw-r--r--bsps/shared/dev/rtc/README.m48t0844
-rw-r--r--bsps/shared/dev/rtc/README.m48t181
-rw-r--r--bsps/shared/dev/rtc/README.mc146818a1
-rw-r--r--bsps/shared/dev/rtc/STATUS33
-rw-r--r--bsps/shared/dev/rtc/ds1375.c461
-rw-r--r--bsps/shared/dev/rtc/icm7170.c168
-rw-r--r--bsps/shared/dev/rtc/icm7170_reg.c60
-rw-r--r--bsps/shared/dev/rtc/icm7170_reg2.c20
-rw-r--r--bsps/shared/dev/rtc/icm7170_reg4.c20
-rw-r--r--bsps/shared/dev/rtc/icm7170_reg8.c20
-rw-r--r--bsps/shared/dev/rtc/m48t08.c161
-rw-r--r--bsps/shared/dev/rtc/m48t08_reg.c60
-rw-r--r--bsps/shared/dev/rtc/m48t08_reg2.c20
-rw-r--r--bsps/shared/dev/rtc/m48t08_reg4.c20
-rw-r--r--bsps/shared/dev/rtc/m48t08_reg8.c20
-rw-r--r--bsps/shared/dev/rtc/mc146818a.c180
-rw-r--r--bsps/shared/dev/rtc/mc146818a_ioreg.c56
-rw-r--r--bsps/shared/dev/rtc/rtcprobe.c21
20 files changed, 1417 insertions, 0 deletions
diff --git a/bsps/shared/dev/rtc/README.ds1643 b/bsps/shared/dev/rtc/README.ds1643
new file mode 100644
index 0000000000..a3a38605c8
--- /dev/null
+++ b/bsps/shared/dev/rtc/README.ds1643
@@ -0,0 +1,3 @@
+The Mostek M48T08 is compatible with the Dallas Semiconductor DS1643. Please
+use that driver.
+
diff --git a/bsps/shared/dev/rtc/README.icm7170 b/bsps/shared/dev/rtc/README.icm7170
new file mode 100644
index 0000000000..d4ecff570f
--- /dev/null
+++ b/bsps/shared/dev/rtc/README.icm7170
@@ -0,0 +1,48 @@
+
+Configuration Table Use
+=======================
+
+sDeviceName
+
+ The name of this device.
+
+deviceType
+
+ This field must be RTC_ICM7170.
+
+pDeviceFns
+
+ The device interface control table. This must be icm7170_fns.
+
+deviceProbe
+
+ This is the address of the routine which probes to see if the device
+ is present.
+
+pDeviceParams
+
+ This field specifies the clock frequency. It may be one of the
+ following:
+ ICM7170_AT_32_KHZ
+ ICM7170_AT_1_MHZ
+ ICM7170_AT_2_MHZ
+ ICM7170_AT_4_MHZ
+
+ulCtrlPort1
+
+ This field is the base address of the RTC area of the chip.
+
+ulCtrlPort2
+
+ This field is ignored.
+
+ulDataPort
+
+ This field is ignored.
+
+
+getRegister
+setRegister
+
+ These follow standard conventions.
+
diff --git a/bsps/shared/dev/rtc/README.m48t08 b/bsps/shared/dev/rtc/README.m48t08
new file mode 100644
index 0000000000..25c032e85e
--- /dev/null
+++ b/bsps/shared/dev/rtc/README.m48t08
@@ -0,0 +1,44 @@
+
+Configuration Table Use
+=======================
+
+sDeviceName
+
+ The name of this device.
+
+deviceType
+
+ This field must be RTC_M48T08.
+
+pDeviceFns
+
+ The device interface control table. This must be m48t08_fns.
+
+deviceProbe
+
+ This is the address of the routine which probes to see if the device
+ is present.
+
+pDeviceParams
+
+ This is ignored and should be NULL.
+
+ulCtrlPort1
+
+ This field is the base address of the RTC area of the chip. The
+ NVRAM portion of the chip is ignored.
+
+ulCtrlPort2
+
+ This field is ignored.
+
+ulDataPort
+
+ This field is ignored.
+
+
+getRegister
+setRegister
+
+ These follow standard conventions.
+
diff --git a/bsps/shared/dev/rtc/README.m48t18 b/bsps/shared/dev/rtc/README.m48t18
new file mode 100644
index 0000000000..0925c62115
--- /dev/null
+++ b/bsps/shared/dev/rtc/README.m48t18
@@ -0,0 +1 @@
+This is supported by the m48t08 driver.
diff --git a/bsps/shared/dev/rtc/README.mc146818a b/bsps/shared/dev/rtc/README.mc146818a
new file mode 100644
index 0000000000..e9a9c86447
--- /dev/null
+++ b/bsps/shared/dev/rtc/README.mc146818a
@@ -0,0 +1 @@
+This is supported by the mc146818a driver.
diff --git a/bsps/shared/dev/rtc/STATUS b/bsps/shared/dev/rtc/STATUS
new file mode 100644
index 0000000000..a6d5c41cd5
--- /dev/null
+++ b/bsps/shared/dev/rtc/STATUS
@@ -0,0 +1,33 @@
+General
+=======
+
++ It would be nice to utilize the interrupt capabilities of some
+ RTC parts. This could be used to trigger checking the software
+ clock against the hardware clock.
+
++ The periodic capability of most RTCs is not suitable for use
+ as a general purpose flexible clock tick source. For example,
+ many RTCs generate only a handful of periods with 100 Hz being the
+ most frequent.
+
++ The tick field is not set on get. Anything smaller than a second
+ is ignored on set and get operations.
+
++ Day of week is ignored since RTEMS does not set it internally.
+
++ There is no attempt in RTEMS to know about time zones.
+
+Harris ICM7170
+==============
+
++ Tested on a DMV177.
+
++ Interrupt capabilities are ignored.
+
+Mostek 48T08
+============
+
++ Untested.
+
++ NVRAM is ignored.
+
diff --git a/bsps/shared/dev/rtc/ds1375.c b/bsps/shared/dev/rtc/ds1375.c
new file mode 100644
index 0000000000..4a23a0044b
--- /dev/null
+++ b/bsps/shared/dev/rtc/ds1375.c
@@ -0,0 +1,461 @@
+/* Driver for the Maxim 1375 i2c RTC (TOD only; very simple...) */
+
+/*
+ * Authorship
+ * ----------
+ * This software was created by
+ *
+ * Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The software was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+/* This driver uses the file-system interface to the i2c bus */
+
+#include <unistd.h> /* write, read, close */
+
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <rtems/rtc.h>
+#include <rtems/score/sysstate.h>
+#include <libchip/rtc.h>
+#include <libchip/ds1375-rtc.h>
+
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+
+#define STATIC static
+#undef DEBUG
+
+/* The RTC driver routines are possibly called during
+ * system initialization -- that would be prior to opening
+ * the console. At this point it is not safe to use stdio
+ * (printf, perror etc.).
+ * Our file descriptors may even be 0..2
+ */
+#define STDIOSAFE(fmt,args...) \
+ do { \
+ if ( _System_state_Is_up( _System_state_Get() ) ) { \
+ fprintf(stderr,fmt,args); \
+ } else { \
+ printk(fmt,args); \
+ } \
+ } while (0)
+
+
+STATIC uint8_t ds1375_bcd2bin(uint8_t x)
+{
+ uint8_t h = x & 0xf0;
+
+ /* 8*hi + 2*hi + lo */
+ return ( h >> 1 ) + ( h >> 3 ) + ( x & 0xf );
+}
+
+STATIC uint8_t ds1375_bin2bcd(uint8_t x)
+{
+ uint8_t h = x/10;
+
+ return ( h << 4 ) + ( x - ( ( h << 3 ) + ( h << 1 ) ) );
+}
+
+/*
+ * Register Definitions and Access Macros
+ *
+ * The xxx_REG macros are offsets into the register files
+ * The xxx_OFF macros are offsets into a in-memory buffer
+ * starting at the seconds (for the 1375 both,
+ * _REG and _OFF happen to be identical).
+ */
+#define DS1375_SEC_REG 0x0
+#define DS1375_SEC_OFF (DS1375_SEC_REG-DS1375_SEC_REG)
+/* Extract seconds and convert to binary */
+#define DS1375_SEC(x) ds1375_bcd2bin( ((x)[DS1375_SEC_OFF]) & 0x7f )
+
+#define DS1375_MIN_REG 0x1
+#define DS1375_MIN_OFF (DS1375_MIN_REG-DS1375_SEC_REG)
+/* Extract minutes and convert to binary */
+#define DS1375_MIN(x) ds1375_bcd2bin( ((x)[DS1375_MIN_OFF]) & 0x7f )
+
+#define DS1375_HR_REG 0x2
+#define DS1375_HR_OFF (DS1375_HR_REG-DS1375_SEC_REG)
+#define DS1375_HR_1224 (1<<6)
+#define DS1375_HR_AMPM (1<<5)
+/* Are hours in AM/PM representation ? */
+#define DS1375_IS_AMPM(x) (DS1375_HR_1224 & ((x)[DS1375_HR_OFF]))
+/* Are we PM ? */
+#define DS1375_IS_PM(x) (DS1375_HR_AMPM & ((x)[DS1375_HR_OFF]))
+/* Extract hours (12h mode) and convert to binary */
+#define DS1375_HR_12(x) ds1375_bcd2bin( ((x)[DS1375_HR_OFF]) & 0x1f )
+/* Extract hours (24h mode) and convert to binary */
+#define DS1375_HR_24(x) ds1375_bcd2bin( ((x)[DS1375_HR_OFF]) & 0x3f )
+
+#define DS1375_DAY_REG 0x3
+#define DS1375_DAY_OFF (DS1375_DAY_REG-DS1375_SEC_REG)
+#define DS1375_DAT_REG 0x4
+#define DS1375_DAT_OFF (DS1375_DAT_REG-DS1375_SEC_REG)
+/* Extract date and convert to binary */
+#define DS1375_DAT(x) ds1375_bcd2bin( ((x)[DS1375_DAT_OFF]) & 0x3f )
+#define DS1375_MON_REG 0x5
+#define DS1375_MON_OFF (DS1375_MON_REG-DS1375_SEC_REG)
+#define DS1375_MON_CTRY (1<<7)
+/* Is century bit set ? */
+#define DS1375_IS_CTRY(x) (((x)[DS1375_MON_OFF]) & DS1375_MON_CTRY)
+/* Extract month and convert to binary */
+#define DS1375_MON(x) ds1375_bcd2bin( ((x)[DS1375_MON_OFF]) & 0x1f )
+
+#define DS1375_YR_REG 0x6
+#define DS1375_YR_OFF (DS1375_YR_REG-DS1375_SEC_REG)
+/* Extract year and convert to binary */
+#define DS1375_YR(x) ds1375_bcd2bin( ((x)[DS1375_YR_OFF]) & 0xff )
+
+/* CR Register and bit definitions */
+#define DS1375_CR_REG 0xe
+#define DS1375_CR_ECLK (1<<7)
+#define DS1375_CR_CLKSEL1 (1<<6)
+#define DS1375_CR_CLKSEL0 (1<<5)
+#define DS1375_CR_RS2 (1<<4)
+#define DS1375_CR_RS1 (1<<3)
+#define DS1375_CR_INTCN (1<<2)
+#define DS1375_CR_A2IE (1<<1)
+#define DS1375_CR_A1IE (1<<0)
+
+#define DS1375_CSR_REG 0xf
+
+/* User SRAM (8 bytes) */
+#define DS1375_RAM 0x10 /* start of 8 bytes user ram */
+
+/* Access Primitives */
+
+STATIC int rd_bytes(
+ int fd,
+ uint32_t off,
+ uint8_t *buf,
+ int len
+)
+{
+ uint8_t ptr = off;
+
+ return 1 == write( fd, &ptr, 1 ) && len == read( fd, buf, len ) ? 0 : -1;
+}
+
+STATIC int wr_bytes(
+ int fd,
+ uint32_t off,
+ uint8_t *buf,
+ int len
+)
+{
+ uint8_t d[ len + 1 ];
+
+ /* Must not break up writing of the register pointer and
+ * the data to-be-written into multiple write() calls
+ * because every 'write()' operation sends START and
+ * the chip interprets the first byte after START as
+ * the register pointer.
+ */
+
+ d[0] = off;
+ memcpy( d + 1, buf, len );
+
+ return len + 1 == write( fd, d, len + 1 ) ? 0 : -1;
+}
+
+/* Helpers */
+
+static int getfd(
+ int minor
+)
+{
+ return open( (const char *)RTC_Table[minor].ulCtrlPort1, O_RDWR );
+}
+
+/* Driver Access Functions */
+
+STATIC void ds1375_initialize(
+ int minor
+)
+{
+ int fd;
+ uint8_t cr;
+
+ if ( ( fd = getfd( minor ) ) >= 0 ) {
+ if ( 0 == rd_bytes( fd, DS1375_CR_REG, &cr, 1 ) ) {
+ /* make sure clock is enabled */
+ if ( ! ( DS1375_CR_ECLK & cr ) ) {
+ cr |= DS1375_CR_ECLK;
+ wr_bytes( fd, DS1375_CR_REG, &cr, 1 );
+ }
+ }
+ close( fd );
+ }
+
+}
+
+STATIC int ds1375_get_time(
+ int minor,
+ rtems_time_of_day *time
+)
+{
+ int rval = -1;
+ int fd;
+ uint8_t buf[DS1375_YR_REG + 1 - DS1375_SEC_REG];
+
+ if ( time && ( ( fd = getfd( minor ) ) >= 0 ) ) {
+ if ( 0 == rd_bytes( fd, DS1375_SEC_REG, buf, sizeof(buf) ) ) {
+ time->year = DS1375_IS_CTRY( buf ) ? 2000 : 1900;
+ time->year += DS1375_YR ( buf );
+ time->month = DS1375_MON( buf );
+ time->day = DS1375_DAT( buf ); /* DAY is weekday */
+
+ if ( DS1375_IS_AMPM( buf ) ) {
+ time->hour = DS1375_HR_12 ( buf );
+ if ( DS1375_IS_PM( buf ) )
+ time->hour += 12;
+ } else {
+ time->hour = DS1375_HR_24 ( buf );
+ }
+
+ time->minute = DS1375_MIN( buf );
+ time->second = DS1375_SEC( buf );
+ time->ticks = 0;
+ rval = 0;
+ }
+ close( fd );
+ }
+ return rval;
+}
+
+STATIC int ds1375_set_time(
+ int minor,
+ const rtems_time_of_day *time
+)
+{
+ int rval = -1;
+ int fd = -1;
+ time_t secs;
+ struct tm tm;
+ uint8_t buf[DS1375_YR_REG + 1 - DS1375_SEC_REG];
+ uint8_t cr = 0xff;
+
+ /*
+ * The clock hardware maintains the day-of-week as a separate counter
+ * so we must compute it ourselves (rtems_time_of_day doesn't come
+ * with a day of week).
+ */
+ secs = _TOD_To_seconds( time );
+ /* we're only interested in tm_wday... */
+ gmtime_r( &secs, &tm );
+
+ buf[DS1375_SEC_OFF] = ds1375_bin2bcd( time->second );
+ buf[DS1375_MIN_OFF] = ds1375_bin2bcd( time->minute );
+ /* bin2bcd(hour) implicitly selects 24h mode since ms-bit is clear */
+ buf[DS1375_HR_OFF] = ds1375_bin2bcd( time->hour );
+ buf[DS1375_DAY_OFF] = tm.tm_wday + 1;
+ buf[DS1375_DAT_OFF] = ds1375_bin2bcd( time->day );
+ buf[DS1375_MON_OFF] = ds1375_bin2bcd( time->month );
+
+ if ( time->year >= 2000 ) {
+ buf[DS1375_YR_OFF] = ds1375_bin2bcd( time->year - 2000 );
+ buf[DS1375_MON_OFF] |= DS1375_MON_CTRY;
+ } else {
+ buf[DS1375_YR_OFF] = ds1375_bin2bcd( time->year - 1900 );
+ }
+
+ /*
+ * Stop clock; update registers and restart. This is slightly
+ * slower than just writing everyting but if we did that we
+ * could get inconsistent registers if this routine would not
+ * complete in less than 1s (says the datasheet) and we don't
+ * know if we are going to be pre-empted for some time...
+ */
+ if ( ( fd = getfd( minor ) ) < 0 ) {
+ goto cleanup;
+ }
+
+ if ( rd_bytes( fd, DS1375_CR_REG, &cr, 1 ) )
+ goto cleanup;
+
+ cr &= ~DS1375_CR_ECLK;
+
+ /* This stops the clock */
+ if ( wr_bytes( fd, DS1375_CR_REG, &cr, 1 ) )
+ goto cleanup;
+
+ /* write new contents */
+ if ( wr_bytes( fd, DS1375_SEC_REG, buf, sizeof(buf) ) )
+ goto cleanup;
+
+ rval = 0;
+
+cleanup:
+ if ( fd >= 0 ) {
+ if ( ! ( DS1375_CR_ECLK & cr ) ) {
+ /* start clock; this handles some cases of failure
+ * after stopping the clock by restarting it again
+ */
+ cr |= DS1375_CR_ECLK;
+ if ( wr_bytes( fd, DS1375_CR_REG, &cr, 1 ) )
+ rval = -1;
+ }
+ close( fd );
+ }
+ return rval;
+}
+
+/* Debugging / Testing */
+
+#ifdef DEBUG
+
+/* Don't forget to set "TZ" when using these test routines */
+
+/* What is rtems_time_of_day good for ? Why not use std types ? */
+
+uint32_t
+ds1375_get_time_tst()
+{
+rtems_time_of_day rtod;
+time_t secs;
+
+ ds1375_get_time( 0, &rtod );
+ secs = _TOD_To_seconds( &rtod );
+ printf( "%s\n", ctime( &secs ) );
+ return secs;
+}
+
+int
+ds1375_set_time_tst( const char *datstr, rtems_time_of_day *prt )
+{
+struct tm tm;
+time_t secs;
+rtems_time_of_day rt;
+
+ if ( !datstr )
+ return -1;
+
+ if ( ! strptime( datstr, "%Y-%m-%d/%T", &tm ) )
+ return -2;
+
+ if ( ! prt )
+ prt = &rt;
+
+ secs = mktime( &tm );
+
+ /* convert to UTC */
+ gmtime_r( &secs, &tm );
+
+ printf("Y: %"PRIu32" ", (prt->year = tm.tm_year + 1900) );
+ printf("M: %"PRIu32" ", (prt->month = tm.tm_mon + 1) );
+ printf("D: %"PRIu32" ", (prt->day = tm.tm_mday ) );
+ printf("h: %"PRIu32" ", (prt->hour = tm.tm_hour ) );
+ printf("m: %"PRIu32" ", (prt->minute = tm.tm_min ) );
+ printf("s: %"PRIu32"\n", (prt->second = tm.tm_sec ) );
+ prt->ticks = 0;
+
+ return ( prt == &rt ) ? ds1375_set_time( 0, &rt ) : 0;
+}
+
+#endif
+
+
+uint32_t
+rtc_ds1375_get_register( uintptr_t port, uint8_t reg )
+{
+int fd;
+uint8_t v;
+uint32_t rval = -1;
+
+ if ( ( fd = open( (const char*)port, O_RDWR ) ) >= 0 ) {
+
+ if ( 0 == rd_bytes( fd, reg, &v, 1 ) ) {
+ rval = v;
+ }
+ close( fd );
+ }
+
+ return rval;
+}
+
+void
+rtc_ds1375_set_register( uintptr_t port, uint8_t reg, uint32_t value )
+{
+int fd;
+uint8_t v = value;
+
+ if ( ( fd = open( (const char*)port, O_RDWR ) ) >= 0 ) {
+ wr_bytes( fd, reg, &v, 1 );
+ close( fd );
+ }
+
+}
+
+bool rtc_ds1375_device_probe(
+ int minor
+)
+{
+ int fd;
+
+ if ( ( fd = getfd( minor ) ) < 0 ) {
+ STDIOSAFE( "ds1375_probe (open): %s\n", strerror( errno ) );
+ return false;
+ }
+
+ /* Try to set file pointer */
+ if ( 0 != wr_bytes( fd, DS1375_SEC_REG, 0, 0 ) ) {
+ STDIOSAFE( "ds1375_probe (wr_bytes): %s\n", strerror( errno ) );
+ close( fd );
+ return false;
+ }
+
+ if ( close( fd ) ) {
+ STDIOSAFE( "ds1375_probe (close): %s\n", strerror( errno ) );
+ return false;
+ }
+
+ return true;
+}
+
+rtc_fns rtc_ds1375_fns = {
+ .deviceInitialize = ds1375_initialize,
+ .deviceGetTime = ds1375_get_time,
+ .deviceSetTime = ds1375_set_time,
+};
diff --git a/bsps/shared/dev/rtc/icm7170.c b/bsps/shared/dev/rtc/icm7170.c
new file mode 100644
index 0000000000..1cc9e980f7
--- /dev/null
+++ b/bsps/shared/dev/rtc/icm7170.c
@@ -0,0 +1,168 @@
+/*
+ * This file interfaces with the real-time clock found in
+ * a Harris ICM7170
+ *
+ * Year 2K Notes:
+ *
+ * This chip only uses a two digit field to store the year. This
+ * code uses the RTEMS Epoch as a pivot year. This lets us map the
+ * two digit year field as follows:
+ *
+ * + two digit years 0-87 are mapped to 2000-2087.
+ * + two digit years 88-99 are mapped to 1988-1999.
+ *
+ * This is less than the time span supported by RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <libchip/rtc.h>
+#include <libchip/icm7170.h>
+
+/*
+ * Control register bits
+ */
+
+/* XXX */
+
+/*
+ * icm7170_initialize
+ */
+
+static void icm7170_initialize(
+ int minor
+)
+{
+ uintptr_t icm7170;
+ setRegister_f setReg;
+ uintptr_t clock;
+
+ icm7170 = RTC_Table[ minor ].ulCtrlPort1;
+ setReg = RTC_Table[ minor ].setRegister;
+
+ /*
+ * Initialize the RTC with the proper clock frequency
+ */
+
+ clock = (uintptr_t) RTC_Table[ minor ].pDeviceParams;
+ (*setReg)( icm7170, ICM7170_CONTROL, 0x0c | clock );
+}
+
+/*
+ * icm7170_get_time
+ */
+
+static int icm7170_get_time(
+ int minor,
+ rtems_time_of_day *time
+)
+{
+ uint32_t icm7170;
+ getRegister_f getReg;
+ uint32_t year;
+
+ icm7170 = RTC_Table[ minor ].ulCtrlPort1;
+ getReg = RTC_Table[ minor ].getRegister;
+
+ /*
+ * Put the RTC into read mode
+ */
+
+ (void) (*getReg)( icm7170, ICM7170_COUNTER_HUNDREDTHS );
+
+ /*
+ * Now get the time
+ */
+
+
+ year = (*getReg)( icm7170, ICM7170_YEAR );
+ if ( year < 88 )
+ year += 2000;
+ else
+ year += 1900;
+
+ time->year = year;
+ time->month = (*getReg)( icm7170, ICM7170_MONTH );
+ time->day = (*getReg)( icm7170, ICM7170_DATE );
+ time->hour = (*getReg)( icm7170, ICM7170_HOUR );
+ time->minute = (*getReg)( icm7170, ICM7170_MINUTE );
+ time->second = (*getReg)( icm7170, ICM7170_SECOND );
+
+ time->ticks = 0;
+
+ /*
+ * Put the RTC back into normal mode.
+ */
+
+ (void) (*getReg)( icm7170, ICM7170_COUNTER_HUNDREDTHS );
+
+ return 0;
+}
+
+/*
+ * icm7170_set_time
+ */
+
+static int icm7170_set_time(
+ int minor,
+ const rtems_time_of_day *time
+)
+{
+ uintptr_t icm7170;
+ setRegister_f setReg;
+ uint32_t year;
+ uintptr_t clock;
+
+ icm7170 = RTC_Table[ minor ].ulCtrlPort1;
+ setReg = RTC_Table[ minor ].setRegister;
+ clock = (uintptr_t) RTC_Table[ minor ].pDeviceParams;
+
+ year = time->year;
+
+ if ( year >= 2088 )
+ rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
+
+ if ( year >= 2000 )
+ year -= 2000;
+ else
+ year -= 1900;
+
+ (*setReg)( icm7170, ICM7170_CONTROL, 0x04 | clock );
+
+ (*setReg)( icm7170, ICM7170_YEAR, year );
+ (*setReg)( icm7170, ICM7170_MONTH, time->month );
+ (*setReg)( icm7170, ICM7170_DATE, time->day );
+ (*setReg)( icm7170, ICM7170_HOUR, time->hour );
+ (*setReg)( icm7170, ICM7170_MINUTE, time->minute );
+ (*setReg)( icm7170, ICM7170_SECOND, time->second );
+
+ /*
+ * This is not really right.
+ */
+
+ (*setReg)( icm7170, ICM7170_DAY_OF_WEEK, 1 );
+
+ /*
+ * Put the RTC back into normal mode.
+ */
+
+ (*setReg)( icm7170, ICM7170_CONTROL, 0x0c | clock );
+
+ return 0;
+}
+
+/*
+ * Driver function table
+ */
+
+rtc_fns icm7170_fns = {
+ icm7170_initialize,
+ icm7170_get_time,
+ icm7170_set_time
+};
diff --git a/bsps/shared/dev/rtc/icm7170_reg.c b/bsps/shared/dev/rtc/icm7170_reg.c
new file mode 100644
index 0000000000..747f1f218d
--- /dev/null
+++ b/bsps/shared/dev/rtc/icm7170_reg.c
@@ -0,0 +1,60 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the icm7170 chip if accesses to the chip are as follows:
+ *
+ * + registers are accessed as bytes
+ * + registers are only byte-aligned (no address gaps)
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <libchip/rtc.h>
+#include <libchip/icm7170.h>
+
+#ifndef _ICM7170_MULTIPLIER
+#define _ICM7170_MULTIPLIER 1
+#define _ICM7170_NAME(_X) _X
+#define _ICM7170_TYPE uint8_t
+#endif
+
+#define CALCULATE_REGISTER_ADDRESS( _base, _reg ) \
+ (_ICM7170_TYPE *)((_base) + ((_reg) * _ICM7170_MULTIPLIER ))
+
+/*
+ * ICM7170 Get Register Routine
+ */
+
+uint32_t _ICM7170_NAME(icm7170_get_register)(
+ uintptr_t ulCtrlPort,
+ uint8_t ucRegNum
+)
+{
+ _ICM7170_TYPE *port;
+
+ port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
+
+ return *port;
+}
+
+/*
+ * ICM7170 Set Register Routine
+ */
+
+void _ICM7170_NAME(icm7170_set_register)(
+ uintptr_t ulCtrlPort,
+ uint8_t ucRegNum,
+ uint32_t ucData
+)
+{
+ _ICM7170_TYPE *port;
+
+ port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
+
+ *port = ucData;
+}
diff --git a/bsps/shared/dev/rtc/icm7170_reg2.c b/bsps/shared/dev/rtc/icm7170_reg2.c
new file mode 100644
index 0000000000..179d76c6f5
--- /dev/null
+++ b/bsps/shared/dev/rtc/icm7170_reg2.c
@@ -0,0 +1,20 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the icm7170 chip if accesses to the chip are as follows:
+ *
+ * + registers are accessed as bytes
+ * + registers are on 16-bit boundaries
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#define _ICM7170_MULTIPLIER 2
+#define _ICM7170_NAME(_X) _X##_2
+#define _ICM7170_TYPE uint8_t
+
+#include "icm7170_reg.c"
diff --git a/bsps/shared/dev/rtc/icm7170_reg4.c b/bsps/shared/dev/rtc/icm7170_reg4.c
new file mode 100644
index 0000000000..dada40961c
--- /dev/null
+++ b/bsps/shared/dev/rtc/icm7170_reg4.c
@@ -0,0 +1,20 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the icm7170 chip if accesses to the chip are as follows:
+ *
+ * + registers are accessed as bytes
+ * + registers are on 32-bit boundaries
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#define _ICM7170_MULTIPLIER 4
+#define _ICM7170_NAME(_X) _X##_4
+#define _ICM7170_TYPE uint8_t
+
+#include "icm7170_reg.c"
diff --git a/bsps/shared/dev/rtc/icm7170_reg8.c b/bsps/shared/dev/rtc/icm7170_reg8.c
new file mode 100644
index 0000000000..a1fb1a5ea2
--- /dev/null
+++ b/bsps/shared/dev/rtc/icm7170_reg8.c
@@ -0,0 +1,20 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the icm7170 chip if accesses to the chip are as follows:
+ *
+ * + registers are accessed as bytes
+ * + registers are on 64-bit boundaries
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#define _ICM7170_MULTIPLIER 8
+#define _ICM7170_NAME(_X) _X##_8
+#define _ICM7170_TYPE uint8_t
+
+#include "icm7170_reg.c"
diff --git a/bsps/shared/dev/rtc/m48t08.c b/bsps/shared/dev/rtc/m48t08.c
new file mode 100644
index 0000000000..3b600bd995
--- /dev/null
+++ b/bsps/shared/dev/rtc/m48t08.c
@@ -0,0 +1,161 @@
+/*
+ * This file interfaces with the real-time clock found in
+ * a Mostek M48T08 or M48T18 or compatibles.
+ *
+ * Year 2K Notes:
+ *
+ * This chip only uses a two digit field to store the year. This
+ * code uses the RTEMS Epoch as a pivot year. This lets us map the
+ * two digit year field as follows:
+ *
+ * + two digit years 0-87 are mapped to 2000-2087.
+ * + two digit years 88-99 are mapped to 1988-1999.
+ *
+ * This is less than the time span supported by RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <libchip/rtc.h>
+#include <libchip/m48t08.h>
+
+/*
+ * Control register bits
+ */
+
+#define M48T08_CONTROL_WRITE 0x80
+#define M48T08_CONTROL_READ 0x40
+#define M48T08_CONTROL_SIGN 0x20
+
+/*
+ * m48t08_initialize
+ */
+
+static void m48t08_initialize(
+ int minor
+)
+{
+}
+
+/*
+ * m48t08_get_time
+ */
+
+#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
+#define To_BCD( _x ) ((((_x) / 10) << 4) + ((_x) % 10))
+
+static int m48t08_get_time(
+ int minor,
+ rtems_time_of_day *time
+)
+{
+ uint32_t m48t08;
+ getRegister_f getReg;
+ setRegister_f setReg;
+ uint8_t controlReg;
+ uint32_t value1;
+ uint32_t value2;
+
+ m48t08 = RTC_Table[ minor ].ulCtrlPort1;
+ getReg = RTC_Table[ minor ].getRegister;
+ setReg = RTC_Table[ minor ].setRegister;
+
+ /*
+ * Put the RTC into read mode
+ */
+
+ controlReg = (*getReg)( m48t08, M48T08_CONTROL );
+ (*setReg)( m48t08, M48T08_CONTROL, controlReg | M48T08_CONTROL_READ );
+
+ value1 = (*getReg)( m48t08, M48T08_YEAR );
+ value2 = From_BCD( value1 );
+ if ( value2 < 88 )
+ time->year = 2000 + value2;
+ else
+ time->year = 1900 + value2;
+
+ value1 = (*getReg)( m48t08, M48T08_MONTH );
+ time->month = From_BCD( value1 );
+
+ value1 = (*getReg)( m48t08, M48T08_DATE );
+ time->day = From_BCD( value1 );
+
+ value1 = (*getReg)( m48t08, M48T08_HOUR );
+ time->hour = From_BCD( value1 );
+
+ value1 = (*getReg)( m48t08, M48T08_MINUTE );
+ time->minute = From_BCD( value1 );
+
+ value1 = (*getReg)( m48t08, M48T08_SECOND );
+ time->second = From_BCD( value1 );
+
+ time->ticks = 0;
+
+ /*
+ * Put the RTC back into normal mode.
+ */
+
+ (*setReg)( m48t08, M48T08_CONTROL, controlReg );
+
+ return 0;
+}
+
+/*
+ * m48t08_set_time
+ */
+
+static int m48t08_set_time(
+ int minor,
+ const rtems_time_of_day *time
+)
+{
+ uint32_t m48t08;
+ getRegister_f getReg;
+ setRegister_f setReg;
+ uint8_t controlReg;
+
+ m48t08 = RTC_Table[ minor ].ulCtrlPort1;
+ getReg = RTC_Table[ minor ].getRegister;
+ setReg = RTC_Table[ minor ].setRegister;
+
+ /*
+ * Put the RTC into read mode
+ */
+
+ controlReg = (*getReg)( m48t08, M48T08_CONTROL );
+ (*setReg)( m48t08, M48T08_CONTROL, controlReg | M48T08_CONTROL_WRITE );
+
+ if ( time->year >= 2088 )
+ rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
+
+ (*setReg)( m48t08, M48T08_YEAR, To_BCD(time->year % 100) );
+ (*setReg)( m48t08, M48T08_MONTH, To_BCD(time->month) );
+ (*setReg)( m48t08, M48T08_DATE, To_BCD(time->day) );
+ (*setReg)( m48t08, M48T08_HOUR, To_BCD(time->hour) );
+ (*setReg)( m48t08, M48T08_MINUTE, To_BCD(time->minute) );
+ (*setReg)( m48t08, M48T08_SECOND, To_BCD(time->second) );
+
+ /*
+ * Put the RTC back into normal mode.
+ */
+
+ (*setReg)( m48t08, M48T08_CONTROL, controlReg );
+
+ return 0;
+}
+
+/*
+ * Driver function table
+ */
+
+rtc_fns m48t08_fns = {
+ m48t08_initialize,
+ m48t08_get_time,
+ m48t08_set_time
+};
diff --git a/bsps/shared/dev/rtc/m48t08_reg.c b/bsps/shared/dev/rtc/m48t08_reg.c
new file mode 100644
index 0000000000..2174496fda
--- /dev/null
+++ b/bsps/shared/dev/rtc/m48t08_reg.c
@@ -0,0 +1,60 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the m48t08 chip if accesses to the chip are as follows:
+ *
+ * + registers are accessed as bytes
+ * + registers are only byte-aligned (no address gaps)
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <libchip/rtc.h>
+#include <libchip/m48t08.h>
+
+#ifndef _M48T08_MULTIPLIER
+#define _M48T08_MULTIPLIER 1
+#define _M48T08_NAME(_X) _X
+#define _M48T08_TYPE uint8_t
+#endif
+
+#define CALCULATE_REGISTER_ADDRESS( _base, _reg ) \
+ (_M48T08_TYPE *)((_base) + ((_reg) * _M48T08_MULTIPLIER ))
+
+/*
+ * M48T08 Get Register Routine
+ */
+
+uint32_t _M48T08_NAME(m48t08_get_register)(
+ uintptr_t ulCtrlPort,
+ uint8_t ucRegNum
+)
+{
+ _M48T08_TYPE *port;
+
+ port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
+
+ return *port;
+}
+
+/*
+ * M48T08 Set Register Routine
+ */
+
+void _M48T08_NAME(m48t08_set_register)(
+ uintptr_t ulCtrlPort,
+ uint8_t ucRegNum,
+ uint32_t ucData
+)
+{
+ _M48T08_TYPE *port;
+
+ port = CALCULATE_REGISTER_ADDRESS( ulCtrlPort, ucRegNum );
+
+ *port = ucData;
+}
diff --git a/bsps/shared/dev/rtc/m48t08_reg2.c b/bsps/shared/dev/rtc/m48t08_reg2.c
new file mode 100644
index 0000000000..87d2041946
--- /dev/null
+++ b/bsps/shared/dev/rtc/m48t08_reg2.c
@@ -0,0 +1,20 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the m48t08 chip if accesses to the chip are as follows:
+ *
+ * + registers are accessed as bytes
+ * + registers are on 16-bit boundaries
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#define _M48T08_MULTIPLIER 2
+#define _M48T08_NAME(_X) _X##_2
+#define _M48T08_TYPE uint8_t
+
+#include "m48t08_reg.c"
diff --git a/bsps/shared/dev/rtc/m48t08_reg4.c b/bsps/shared/dev/rtc/m48t08_reg4.c
new file mode 100644
index 0000000000..2203249503
--- /dev/null
+++ b/bsps/shared/dev/rtc/m48t08_reg4.c
@@ -0,0 +1,20 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the m48t08 chip if accesses to the chip are as follows:
+ *
+ * + registers are accessed as bytes
+ * + registers are on 32-bit boundaries
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#define _M48T08_MULTIPLIER 4
+#define _M48T08_NAME(_X) _X##_4
+#define _M48T08_TYPE uint8_t
+
+#include "m48t08_reg.c"
diff --git a/bsps/shared/dev/rtc/m48t08_reg8.c b/bsps/shared/dev/rtc/m48t08_reg8.c
new file mode 100644
index 0000000000..83044d752b
--- /dev/null
+++ b/bsps/shared/dev/rtc/m48t08_reg8.c
@@ -0,0 +1,20 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the m48t08 chip if accesses to the chip are as follows:
+ *
+ * + registers are accessed as bytes
+ * + registers are on 64-bit boundaries
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#define _M48T08_MULTIPLIER 8
+#define _M48T08_NAME(_X) _X##_8
+#define _M48T08_TYPE uint8_t
+
+#include "m48t08_reg.c"
diff --git a/bsps/shared/dev/rtc/mc146818a.c b/bsps/shared/dev/rtc/mc146818a.c
new file mode 100644
index 0000000000..2720ce5e8a
--- /dev/null
+++ b/bsps/shared/dev/rtc/mc146818a.c
@@ -0,0 +1,180 @@
+/*
+ * This file interfaces with the real-time clock found in
+ * a Motorola MC146818A (common on PC hardware)
+ *
+ * Year 2K Notes:
+ *
+ * This chip only uses a two digit field to store the year. This
+ * code uses the RTEMS Epoch as a pivot year. This lets us map the
+ * two digit year field as follows:
+ *
+ * + two digit years 0-87 are mapped to 2000-2087.
+ * + two digit years 88-99 are mapped to 1988-1999.
+ *
+ * This is less than the time span supported by RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+#include <rtems.h>
+#include <libchip/rtc.h>
+#include <libchip/mc146818a.h>
+
+#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
+#define To_BCD( _x ) ((((_x) / 10) << 4) + ((_x) % 10))
+
+/*
+ * See if chip is present
+ */
+bool mc146818a_probe(
+ int minor
+)
+{
+ uint32_t mc146818a;
+ getRegister_f getReg;
+ uint32_t value;
+
+ /*
+ * Verify that chip is present and that time is valid
+ */
+ mc146818a = RTC_Table[ minor ].ulCtrlPort1;
+ getReg = RTC_Table[ minor ].getRegister;
+ value = (*getReg)( mc146818a, MC146818A_STATUSD );
+ if ((value == 0) || (value == 0xFF))
+ return false;
+ return true;
+}
+
+/*
+ * Initialize chip
+ */
+static void mc146818a_initialize(
+ int minor
+)
+{
+ uintptr_t mc146818a;
+ setRegister_f setReg;
+
+ mc146818a = RTC_Table[ minor ].ulCtrlPort1;
+ setReg = RTC_Table[ minor ].setRegister;
+
+ (*setReg)(
+ mc146818a,
+ MC146818A_STATUSA,
+ MC146818ASA_DIVIDER|MC146818ASA_1024
+ );
+ (*setReg)(
+ mc146818a,
+ MC146818A_STATUSB,
+ MC146818ASB_24HR
+ );
+}
+
+/*
+ * Read time from chip
+ */
+static int mc146818a_get_time(
+ int minor,
+ rtems_time_of_day *time
+)
+{
+ uintptr_t mc146818a;
+ getRegister_f getReg;
+ uint32_t value;
+ rtems_interrupt_level level;
+
+ mc146818a = RTC_Table[ minor ].ulCtrlPort1;
+ getReg = RTC_Table[ minor ].getRegister;
+
+ /*
+ * No time if power failed
+ */
+ if (((*getReg)( mc146818a, MC146818A_STATUSD ) & MC146818ASD_PWR) == 0)
+ return -1;
+
+ /*
+ * Wait for time update to complete
+ */
+ rtems_interrupt_disable( level );
+ while (((*getReg)( mc146818a, MC146818A_STATUSA ) & MC146818ASA_TUP) != 0) {
+ rtems_interrupt_flash( level );
+ }
+
+ /*
+ * Read the time (we have at least 244 usec to do this)
+ */
+ value = (*getReg)( mc146818a, MC146818A_YEAR );
+ value = From_BCD( value );
+ if ( value < 88 )
+ time->year = 2000 + value;
+ else
+ time->year = 1900 + value;
+
+ value = (*getReg)( mc146818a, MC146818A_MONTH );
+ time->month = From_BCD( value );
+
+ value = (*getReg)( mc146818a, MC146818A_DAY );
+ time->day = From_BCD( value );
+
+ value = (*getReg)( mc146818a, MC146818A_HRS );
+ time->hour = From_BCD( value );
+
+ value = (*getReg)( mc146818a, MC146818A_MIN );
+ time->minute = From_BCD( value );
+
+ value = (*getReg)( mc146818a, MC146818A_SEC );
+ rtems_interrupt_enable( level );
+ time->second = From_BCD( value );
+ time->ticks = 0;
+
+ return 0;
+}
+
+/*
+ * Set time into chip
+ */
+static int mc146818a_set_time(
+ int minor,
+ const rtems_time_of_day *time
+)
+{
+ uint32_t mc146818a;
+ setRegister_f setReg;
+
+ mc146818a = RTC_Table[ minor ].ulCtrlPort1;
+ setReg = RTC_Table[ minor ].setRegister;
+
+ /*
+ * Stop the RTC
+ */
+ (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_HALT|MC146818ASB_24HR );
+
+ if ( time->year >= 2088 )
+ rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
+
+ (*setReg)( mc146818a, MC146818A_YEAR, To_BCD(time->year % 100) );
+ (*setReg)( mc146818a, MC146818A_MONTH, To_BCD(time->month) );
+ (*setReg)( mc146818a, MC146818A_DAY, To_BCD(time->day) );
+ (*setReg)( mc146818a, MC146818A_HRS, To_BCD(time->hour) );
+ (*setReg)( mc146818a, MC146818A_MIN, To_BCD(time->minute) );
+ (*setReg)( mc146818a, MC146818A_SEC, To_BCD(time->second) );
+
+ /*
+ * Restart the RTC
+ */
+ (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_24HR );
+ return 0;
+}
+
+/*
+ * Driver function table
+ */
+rtc_fns mc146818a_fns = {
+ mc146818a_initialize,
+ mc146818a_get_time,
+ mc146818a_set_time
+};
diff --git a/bsps/shared/dev/rtc/mc146818a_ioreg.c b/bsps/shared/dev/rtc/mc146818a_ioreg.c
new file mode 100644
index 0000000000..4c438a516a
--- /dev/null
+++ b/bsps/shared/dev/rtc/mc146818a_ioreg.c
@@ -0,0 +1,56 @@
+/*
+ * This file contains a typical set of register access routines which may be
+ * used with the MC146818A chip if accesses to the chip are as follows:
+ *
+ * + registers are in I/O space
+ * + registers are accessed as bytes
+ * + registers are only byte-aligned (no address gaps)
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <libchip/rtc.h>
+#include <libchip/mc146818a.h>
+
+/*
+ * At this point, not all CPUs or BSPs have defined in/out port routines.
+ */
+#if defined(__i386__) || defined(__PPC__)
+#if defined(inport_byte)
+uint32_t mc146818a_get_register(
+ uintptr_t ulCtrlPort,
+ uint8_t ucRegNum
+)
+{
+ uint8_t val;
+ uint8_t tmp;
+
+ (void) tmp; /* eliminate warning for set but not used */
+
+ outport_byte( ulCtrlPort, ucRegNum );
+ inport_byte( 0x84, tmp ); /* Hack a delay to give chip time to settle */
+ inport_byte( ulCtrlPort+1, val );
+ inport_byte( 0x84, tmp ); /* Hack a delay to give chip time to settle */
+ return val;
+}
+
+void mc146818a_set_register(
+ uintptr_t ulCtrlPort,
+ uint8_t ucRegNum,
+ uint32_t ucData
+)
+{
+ outport_byte( ulCtrlPort, ucRegNum );
+ outport_byte( ulCtrlPort+1, (uint8_t)ucData );
+}
+#endif
+#endif
diff --git a/bsps/shared/dev/rtc/rtcprobe.c b/bsps/shared/dev/rtc/rtcprobe.c
new file mode 100644
index 0000000000..71472ffd7c
--- /dev/null
+++ b/bsps/shared/dev/rtc/rtcprobe.c
@@ -0,0 +1,21 @@
+/*
+ * This file contains the default Real-Time Clock probe routine.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <libchip/rtc.h>
+
+
+bool rtc_probe(
+ int minor
+)
+{
+ return true;
+}