bsps: Move libchip to bsps

This patch is a part of the BSP source reorganization.

Update #3285.
This commit is contained in:
Sebastian Huber
2018-04-03 07:20:11 +02:00
parent 8621ed3806
commit 27de4e1fb8
83 changed files with 55 additions and 91 deletions

View File

@@ -0,0 +1,3 @@
The Mostek M48T08 is compatible with the Dallas Semiconductor DS1643. Please
use that driver.

View 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.

View 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.

View File

@@ -0,0 +1 @@
This is supported by the m48t08 driver.

View File

@@ -0,0 +1 @@
This is supported by the mc146818a driver.

View 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.

View 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,
};

View 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
};

View 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;
}

View 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"

View 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"

View 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"

View 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
};

View 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;
}

View 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"

View 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"

View 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"

View 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
};

View 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

View 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;
}