mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-26 22:48:23 +00:00
bsps: Move libchip to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
3
bsps/shared/dev/rtc/README.ds1643
Normal file
3
bsps/shared/dev/rtc/README.ds1643
Normal file
@@ -0,0 +1,3 @@
|
||||
The Mostek M48T08 is compatible with the Dallas Semiconductor DS1643. Please
|
||||
use that driver.
|
||||
|
||||
48
bsps/shared/dev/rtc/README.icm7170
Normal file
48
bsps/shared/dev/rtc/README.icm7170
Normal file
@@ -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.
|
||||
|
||||
44
bsps/shared/dev/rtc/README.m48t08
Normal file
44
bsps/shared/dev/rtc/README.m48t08
Normal file
@@ -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.
|
||||
|
||||
1
bsps/shared/dev/rtc/README.m48t18
Normal file
1
bsps/shared/dev/rtc/README.m48t18
Normal file
@@ -0,0 +1 @@
|
||||
This is supported by the m48t08 driver.
|
||||
1
bsps/shared/dev/rtc/README.mc146818a
Normal file
1
bsps/shared/dev/rtc/README.mc146818a
Normal file
@@ -0,0 +1 @@
|
||||
This is supported by the mc146818a driver.
|
||||
33
bsps/shared/dev/rtc/STATUS
Normal file
33
bsps/shared/dev/rtc/STATUS
Normal file
@@ -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.
|
||||
|
||||
461
bsps/shared/dev/rtc/ds1375.c
Normal file
461
bsps/shared/dev/rtc/ds1375.c
Normal file
@@ -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,
|
||||
};
|
||||
168
bsps/shared/dev/rtc/icm7170.c
Normal file
168
bsps/shared/dev/rtc/icm7170.c
Normal file
@@ -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
|
||||
};
|
||||
60
bsps/shared/dev/rtc/icm7170_reg.c
Normal file
60
bsps/shared/dev/rtc/icm7170_reg.c
Normal file
@@ -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;
|
||||
}
|
||||
20
bsps/shared/dev/rtc/icm7170_reg2.c
Normal file
20
bsps/shared/dev/rtc/icm7170_reg2.c
Normal file
@@ -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"
|
||||
20
bsps/shared/dev/rtc/icm7170_reg4.c
Normal file
20
bsps/shared/dev/rtc/icm7170_reg4.c
Normal file
@@ -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"
|
||||
20
bsps/shared/dev/rtc/icm7170_reg8.c
Normal file
20
bsps/shared/dev/rtc/icm7170_reg8.c
Normal file
@@ -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"
|
||||
161
bsps/shared/dev/rtc/m48t08.c
Normal file
161
bsps/shared/dev/rtc/m48t08.c
Normal file
@@ -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
|
||||
};
|
||||
60
bsps/shared/dev/rtc/m48t08_reg.c
Normal file
60
bsps/shared/dev/rtc/m48t08_reg.c
Normal file
@@ -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;
|
||||
}
|
||||
20
bsps/shared/dev/rtc/m48t08_reg2.c
Normal file
20
bsps/shared/dev/rtc/m48t08_reg2.c
Normal file
@@ -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"
|
||||
20
bsps/shared/dev/rtc/m48t08_reg4.c
Normal file
20
bsps/shared/dev/rtc/m48t08_reg4.c
Normal file
@@ -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"
|
||||
20
bsps/shared/dev/rtc/m48t08_reg8.c
Normal file
20
bsps/shared/dev/rtc/m48t08_reg8.c
Normal file
@@ -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"
|
||||
180
bsps/shared/dev/rtc/mc146818a.c
Normal file
180
bsps/shared/dev/rtc/mc146818a.c
Normal file
@@ -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
|
||||
};
|
||||
56
bsps/shared/dev/rtc/mc146818a_ioreg.c
Normal file
56
bsps/shared/dev/rtc/mc146818a_ioreg.c
Normal file
@@ -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
|
||||
21
bsps/shared/dev/rtc/rtcprobe.c
Normal file
21
bsps/shared/dev/rtc/rtcprobe.c
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user