diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-03 07:20:11 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-04 10:13:28 +0200 |
commit | 27de4e1fb8bcdbdd8cb882fc0d7a2c152b4e027a (patch) | |
tree | def0664dcddc53fd5d599b455c64f76ca2293606 /bsps/shared/dev/rtc | |
parent | bsps: Move config macros to RTEMS_BSP_CONFIGURE (diff) | |
download | rtems-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.ds1643 | 3 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/README.icm7170 | 48 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/README.m48t08 | 44 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/README.m48t18 | 1 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/README.mc146818a | 1 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/STATUS | 33 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/ds1375.c | 461 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/icm7170.c | 168 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/icm7170_reg.c | 60 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/icm7170_reg2.c | 20 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/icm7170_reg4.c | 20 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/icm7170_reg8.c | 20 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/m48t08.c | 161 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/m48t08_reg.c | 60 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/m48t08_reg2.c | 20 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/m48t08_reg4.c | 20 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/m48t08_reg8.c | 20 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/mc146818a.c | 180 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/mc146818a_ioreg.c | 56 | ||||
-rw-r--r-- | bsps/shared/dev/rtc/rtcprobe.c | 21 |
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; +} |