From 29322a8d3df22392135993e7feeab1dd6f847e85 Mon Sep 17 00:00:00 2001 From: Eric Norum Date: Mon, 11 Oct 2004 15:00:23 +0000 Subject: Add libchip driver for Motorola MC146818A time-of-day clock chip. Modify i386/pc386 BSP to use this driver. --- c/src/libchip/Makefile.am | 5 +- c/src/libchip/rtc/README.mc146818a | 5 + c/src/libchip/rtc/mc146818a.c | 179 ++++++++++++++++++++++++++++++++++++ c/src/libchip/rtc/mc146818a.h | 67 ++++++++++++++ c/src/libchip/rtc/mc146818a_ioreg.c | 45 +++++++++ c/src/libchip/rtc/rtc.h | 3 +- 6 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 c/src/libchip/rtc/README.mc146818a create mode 100644 c/src/libchip/rtc/mc146818a.c create mode 100644 c/src/libchip/rtc/mc146818a.h create mode 100644 c/src/libchip/rtc/mc146818a_ioreg.c (limited to 'c/src/libchip') diff --git a/c/src/libchip/Makefile.am b/c/src/libchip/Makefile.am index 66e917074c..ded7c067f0 100644 --- a/c/src/libchip/Makefile.am +++ b/c/src/libchip/Makefile.am @@ -66,14 +66,15 @@ EXTRA_DIST += network/README network/README.cs8900 network/README.dec21140 \ # rtc if LIBCHIP -include_libchip_HEADERS += rtc/rtc.h rtc/icm7170.h rtc/m48t08.h +include_libchip_HEADERS += rtc/rtc.h rtc/icm7170.h rtc/m48t08.h rtc/mc146818a.h EXTRA_LIBRARIES += librtcio.a CLEANFILES += librtcio.a librtcio_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V) librtcio_a_SOURCES = rtc/rtcprobe.c rtc/icm7170.c rtc/icm7170_reg.c \ rtc/icm7170_reg2.c rtc/icm7170_reg4.c rtc/icm7170_reg8.c rtc/m48t08.c \ - rtc/m48t08_reg.c rtc/m48t08_reg2.c rtc/m48t08_reg4.c rtc/m48t08_reg8.c + rtc/m48t08_reg.c rtc/m48t08_reg2.c rtc/m48t08_reg4.c rtc/m48t08_reg8.c \ + rtc/mc146818a.c rtc/mc146818a_ioreg.c EXTRA_LIBRARIES += librtcio_g.a CLEANFILES += librtcio_g.a diff --git a/c/src/libchip/rtc/README.mc146818a b/c/src/libchip/rtc/README.mc146818a new file mode 100644 index 0000000000..674e7f6212 --- /dev/null +++ b/c/src/libchip/rtc/README.mc146818a @@ -0,0 +1,5 @@ +# +# $Id$ +# + +This is supported by the mc146818a driver. diff --git a/c/src/libchip/rtc/mc146818a.c b/c/src/libchip/rtc/mc146818a.c new file mode 100644 index 0000000000..6fdf1ee228 --- /dev/null +++ b/c/src/libchip/rtc/mc146818a.c @@ -0,0 +1,179 @@ +/* + * 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.com/license/LICENSE. + * + * $Id$ + */ +#include +#include +#include +#include + +#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F)) +#define To_BCD( _x ) ((((_x) / 10) << 4) + ((_x) % 10)) + +/* + * See if chip is present + */ +boolean rtc_probe( + int minor +) +{ + unsigned32 mc146818a; + getRegister_f getReg; + unsigned32 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 + */ +void mc146818a_initialize( + int minor +) +{ + unsigned32 mc146818a; + getRegister_f getReg; + setRegister_f setReg; + + mc146818a = RTC_Table[ minor ].ulCtrlPort1; + getReg = RTC_Table[ minor ].getRegister; + setReg = RTC_Table[ minor ].setRegister; + + (*setReg)( mc146818a, MC146818A_STATUSA, MC146818ASA_DIVIDER|MC146818ASA_1024 ); + (*setReg)( mc146818a, MC146818A_STATUSB, MC146818ASB_24HR ); +} + +/* + * Read time from chip + */ +int mc146818a_get_time( + int minor, + rtems_time_of_day *time +) +{ + unsigned32 mc146818a; + getRegister_f getReg; + unsigned32 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 + */ +int mc146818a_set_time( + int minor, + rtems_time_of_day *time +) +{ + unsigned32 mc146818a; + getRegister_f getReg; + setRegister_f setReg; + + mc146818a = RTC_Table[ minor ].ulCtrlPort1; + getReg = RTC_Table[ minor ].getRegister; + 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/c/src/libchip/rtc/mc146818a.h b/c/src/libchip/rtc/mc146818a.h new file mode 100644 index 0000000000..7ce3b60885 --- /dev/null +++ b/c/src/libchip/rtc/mc146818a.h @@ -0,0 +1,67 @@ +/* + * This file contains the definitions for the following real-time clocks: + * + * + Motorola MC146818A + * + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef __LIBCHIP_MC146818A_h +#define __LIBCHIP_MC146818A_h + +/* + * Register addresses within chip + */ +#define MC146818A_SEC 0x00 /* seconds */ +#define MC146818A_SECALRM 0x01 /* seconds alarm */ +#define MC146818A_MIN 0x02 /* minutes */ +#define MC146818A_MINALRM 0x03 /* minutes alarm */ +#define MC146818A_HRS 0x04 /* hours */ +#define MC146818A_HRSALRM 0x05 /* hours alarm */ +#define MC146818A_WDAY 0x06 /* week day */ +#define MC146818A_DAY 0x07 /* day of month */ +#define MC146818A_MONTH 0x08 /* month of year */ +#define MC146818A_YEAR 0x09 /* month of year */ + +#define MC146818A_STATUSA 0x0a /* status register A */ +#define MC146818ASA_TUP 0x80 /* time update in progress */ +#define MC146818ASA_DIVIDER 0x20 /* divider for 32768 crystal */ +#define MC146818ASA_1024 0x06 /* divide to 1024 Hz */ + +#define MC146818A_STATUSB 0x0b /* status register B */ +#define MC146818ASB_DST 0x01 /* Daylight Savings Time */ +#define MC146818ASB_24HR 0x02 /* 0 = 12 hours, 1 = 24 hours */ +#define MC146818ASB_HALT 0x80 /* stop clock updates */ + +#define MC146818A_STATUSD 0x0d /* status register D */ +#define MC146818ASD_PWR 0x80 /* clock lost power */ + + +/* + * Driver function table + */ +extern rtc_fns mc146818a_fns; + +/* + * Default register access routines + */ +unsigned32 mc146818a_get_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +); + +void mc146818a_set_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned32 ucData +); + +#endif +/* end of include file */ diff --git a/c/src/libchip/rtc/mc146818a_ioreg.c b/c/src/libchip/rtc/mc146818a_ioreg.c new file mode 100644 index 0000000000..0ccd398c9d --- /dev/null +++ b/c/src/libchip/rtc/mc146818a_ioreg.c @@ -0,0 +1,45 @@ +/* + * 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.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include + +unsigned32 mc146818a_get_register( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum +) +{ + unsigned8 val; + unsigned8 tmp; + + 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( + unsigned32 ulCtrlPort, + unsigned8 ucRegNum, + unsigned32 ucData +) +{ + outport_byte( ulCtrlPort, ucRegNum ); + outport_byte( ulCtrlPort+1, (unsigned8)ucData ); +} diff --git a/c/src/libchip/rtc/rtc.h b/c/src/libchip/rtc/rtc.h index 8d2f37d2e1..545e5fb82c 100644 --- a/c/src/libchip/rtc/rtc.h +++ b/c/src/libchip/rtc/rtc.h @@ -32,7 +32,8 @@ typedef struct _rtc_fns { typedef enum { RTC_M48T08, /* SGS-Thomsom M48T08 or M48T18 */ RTC_ICM7170, /* Harris ICM-7170 */ - RTC_CUSTOM /* BSP specific driver */ + RTC_CUSTOM, /* BSP specific driver */ + RTC_MC146818A /* Motorola MC146818A */ } rtc_devs; /* -- cgit v1.2.3