OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [ppcn_60x/] [tod/] [tod.c] - Rev 846

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 *  COPYRIGHT (c) 1998 by Radstone Technology
 *
 *
 * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
 * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
 *
 * You are hereby granted permission to use, copy, modify, and distribute
 * this file, provided that this notice, plus the above copyright notice
 * and disclaimer, appears in all copies. Radstone Technology will provide
 * no support for this code.
 *
 */
 
#define MIN_YEAR 1996
 
#include <stdlib.h>
#include "bsp.h"
#include "cmos.h"
#include "../nvram/mk48t18.h"
 
#define Bin2BCD(Value) (((Value / 10) << 4) | (Value % 10))
#define BCD2Bin(BcdValue) ((BcdValue >> 4) * 10 + (BcdValue & 0x0f))
 
/*
 * Private types
 */
typedef
void
(*PTIMESET)
(
	rtems_time_of_day *pTOD
);
 
typedef
boolean
(*PTIMEGET)
(
	rtems_time_of_day *pTOD
);
 
typedef struct _TIME_ENTRY_TABLE
{
    PTIMESET	SetTime;
    PTIMEGET	GetTime;
} TIME_ENTRY_TABLE, *PTIME_ENTRY_TABLE;
 
/*
 * Private routines
 */
 
/*
 * DS1385 specific routines
 */
static void timeDsSet(rtems_time_of_day *pTOD);
static boolean timeDsGet(rtems_time_of_day *pTOD);
 
/*
 * MK48T18 specific routines
 */
static void timeMkSet(rtems_time_of_day *pTOD);
static boolean timeMkGet(rtems_time_of_day *pTOD);
 
TIME_ENTRY_TABLE timeDsTable =
{
	timeDsSet,
	timeDsGet
};
 
TIME_ENTRY_TABLE timeMkTable =
{
	timeMkSet,
	timeMkGet
};
 
/*
 * Private variables
 */
static PTIME_ENTRY_TABLE pTimeFunc;
 
/*
 * Mutual-exclusion semaphore
 */
static rtems_id	semRTC;
 
/*
 * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
 */
rtems_unsigned8 
GregorianDay(rtems_time_of_day *pTOD)
{
	boolean isLeap;
	unsigned long leapsToDate;
	unsigned long lastYear;
	unsigned long day;
	unsigned long MonthOffset[] = { 0, 31, 59, 90, 120, 151,
					181, 212, 243, 273, 304, 334 };
 
	lastYear=pTOD->year-1;
 
	/*
	 * Number of leap corrections to apply up to end of last year
	 */
	leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
 
	/*
	 * This year is a leap year if it is divisible by 4 except when it is
	 * divisible by 100 unless it is divisible by 400
	 *
	 * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
	 */
	isLeap = (pTOD->year%4==0) &&
			 ((pTOD->year%100!=0) || (pTOD->year%400==0));
 
	if(isLeap && (pTOD->month>2))
	{
		day=1;
	}
	else
	{
		day=0;
	}
 
	day += lastYear*365 + leapsToDate + MonthOffset[pTOD->month-1] +
		   pTOD->day;
 
	return((rtems_unsigned8)(day%7));
}
 
void
DsWriteRawClockRegister (
	rtems_unsigned8 Register,
	rtems_unsigned8 Value
)
 
/*++
 
Routine Description:
 
    This routine reads the specified realtime clock register.
 
    This function was added to bridge the BCD format of the IBM roms
    and the binary formate of NT
 
 
Arguments:
 
    Register - Supplies the number of the register whose value is read.
 
Return Value:
 
    The value of the register is returned as the function value.
 
--*/
 
{
	outport_byte((rtems_unsigned8 *)RTC_PORT, Register & 0x7f);
 
	/* Read the realtime clock register value. */
 
	outport_byte((rtems_unsigned8 *)(RTC_PORT + 1), Value);
	return;
}
 
rtems_unsigned8
DsReadRawClockRegister (
	rtems_unsigned8 Register
)
 
/*++
 
Routine Description:
 
    This routine reads the specified realtime clock register.
 
    This function was added to bridge the BCD format of the IBM roms
    and the binary formate of NT
 
 
Arguments:
 
    Register - Supplies the number of the register whose value is read.
 
Return Value:
 
    The value of the register is returned as the function value.
 
--*/
 
{
	rtems_unsigned8 ucDataByte;
 
	outport_byte((rtems_unsigned8 *)RTC_PORT, Register & 0x7f);
 
	/* Read the realtime clock register value. */
 
	inport_byte((rtems_unsigned8 *)(RTC_PORT + 1), ucDataByte);
	return ucDataByte;
}
 
void
DsWriteClockRegister (
	rtems_unsigned8 Register,
	rtems_unsigned8 Value
)
 
/*++
 
Routine Description:
 
    This routine writes the specified value to the specified realtime
    clock register.
 
Arguments:
 
    Register - Supplies the number of the register whose value is written.
 
    Value - Supplies the value that is written to the specified register.
 
Return Value:
 
    The value of the register is returned as the function value.
 
--*/
 
{
	rtems_unsigned8 BcdValue;
 
	BcdValue = Bin2BCD(Value);
	DsWriteRawClockRegister(Register, BcdValue);
	return;
}
 
rtems_unsigned8
DsReadClockRegister (
	rtems_unsigned8 Register
)
 
/*++
 
Routine Description:
 
    This routine reads the specified realtime clock register.
 
Arguments:
 
    Register - Supplies the number of the register whose value is read.
 
Return Value:
 
    The value of the register is returned as the function value.
 
--*/
 
{
	rtems_unsigned8 BcdValue;
 
	BcdValue =  DsReadRawClockRegister(Register);
	return BCD2Bin(BcdValue);
}
 
void
timeDsSet (
    rtems_time_of_day *pTOD
    )
 
/*++
 
Routine Description:
 
    This routine sets the realtime clock.
 
    N.B. This routine assumes that the caller has provided any required
        synchronization to set the realtime clock information.
 
Arguments:
 
    pTOD - Supplies a pointer to a time structure that specifies the
        realtime clock information.
 
Return Value:
 
    If the power to the realtime clock has not failed, then the time
    values are written to the realtime clock and a value of TRUE is
    returned. Otherwise, a value of FALSE is returned.
 
--*/
 
{
	rtems_unsigned8 ucDataByte;
	PCMOS_MAP pCMOS = (PCMOS_MAP)0;
 
	/* If the realtime clock battery is still functioning, then write */
	/* the realtime clock values, and return a function value of TRUE. */
	/* Otherwise, return a function value of FALSE. */
 
	ucDataByte = DsReadRawClockRegister(RTC_CONTROL_REGISTERD);
	if (ucDataByte&DS1385_REGD_VALID)
	{
		/* Set the realtime clock control to set the time. */
 
		ucDataByte = DS1385_REGB_HOURS_FMT | DS1385_REGB_SET_TIME;
		DsWriteRawClockRegister(RTC_CONTROL_REGISTERB, ucDataByte);
 
		/* Write the realtime clock values. */
 
		DsWriteClockRegister(RTC_YEAR,
				     (rtems_unsigned8)(pTOD->year%100));
		if(pTOD->year>=100)
		{
			DsWriteClockRegister((rtems_unsigned8)
					     ((unsigned long)&pCMOS->Century),
					     pTOD->year/100);
		}
		DsWriteClockRegister(RTC_MONTH,
				     (rtems_unsigned8)pTOD->month);
		DsWriteClockRegister(RTC_DAY_OF_MONTH,
				     (rtems_unsigned8)pTOD->day);
		DsWriteClockRegister(RTC_DAY_OF_WEEK,
				     (rtems_unsigned8)
				     (GregorianDay(pTOD) + 1));
		DsWriteClockRegister(RTC_HOUR,
				     (rtems_unsigned8)pTOD->hour);
		DsWriteClockRegister(RTC_MINUTE,
				     (rtems_unsigned8)pTOD->minute);
		DsWriteClockRegister(RTC_SECOND,
				     (rtems_unsigned8)pTOD->second);
 
		/* Set the realtime clock control to update the time. */
 
		ucDataByte &= ~DS1385_REGB_SET_TIME;
		DsWriteRawClockRegister(RTC_CONTROL_REGISTERB, ucDataByte);
		return;
 
	}
	else
	{
		return;
	}
}
 
boolean
timeDsGet (
    rtems_time_of_day *pTOD
    )
 
/*++
 
Routine Description:
 
    This routine queries the realtime clock.
 
Arguments:
 
    pTOD - Supplies a pointer to a time structure that receives
        the realtime clock information.
 
Return Value:
 
    If the power to the realtime clock has not failed, then the time
    values are read from the realtime clock and a value of TRUE is
    returned. Otherwise, a value of FALSE is returned.
 
--*/
 
{
	rtems_unsigned8 ucDataByte;
	PCMOS_MAP pCMOS = (PCMOS_MAP)0;
 
	/* If the realtime clock battery is still functioning, then read */
	/* the realtime clock values, and return a function value of TRUE. */
	/* Otherwise, return a function value of FALSE. */
 
	ucDataByte = DsReadRawClockRegister(RTC_CONTROL_REGISTERD);
	if(ucDataByte&DS1385_REGD_VALID)
	{
		/* Wait until the realtime clock is not being updated. */
 
		do
		{
			ucDataByte=DsReadRawClockRegister(RTC_CONTROL_REGISTERA);
		} while (ucDataByte&DS1385_REGA_UIP);
 
		/* Read the realtime clock values. */
 
		pTOD->year=(rtems_unsigned16)
				  (DsReadClockRegister(
				   (rtems_unsigned8)
				   (unsigned long)&pCMOS->Century)
				  *100 + DsReadClockRegister(RTC_YEAR));
		pTOD->month=DsReadClockRegister(RTC_MONTH);
		pTOD->day=DsReadClockRegister(RTC_DAY_OF_MONTH);
		pTOD->hour=DsReadClockRegister(RTC_HOUR);
		pTOD->minute=DsReadClockRegister(RTC_MINUTE);
		pTOD->second=DsReadClockRegister(RTC_SECOND);
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}
 
void
timeMkSet (
    rtems_time_of_day *pTOD
    )
 
/*++
 
Routine Description:
 
    This routine sets the realtime clock.
 
    N.B. This routine assumes that the caller has provided any required
        synchronization to set the realtime clock information.
 
Arguments:
 
    pTOD - Supplies a pointer to a time structure that specifies the
        realtime clock information.
 
Return Value:
 
    If the power to the realtime clock has not failed, then the time
    values are written to the realtime clock and a value of TRUE is
    returned. Otherwise, a value of FALSE is returned.
 
--*/
 
{
	PMK48T18_NVRAM_MAP pNvRAM = MK48T18_BASE;
 
	/*
	 * Set the RTC into write mode
	 */
	pNvRAM->CMOS.Control|=MK48T18_CTRL_WRITE;
	EIEIO;
 
	/*
	 * Write the realtime clock values.
	 */
 
	pNvRAM->CMOS.Year = (rtems_unsigned8)Bin2BCD(pTOD->year%100);
	if(pTOD->year>=100)
	{
	    pNvRAM->CMOS.Century=(rtems_unsigned8)
	    			 Bin2BCD(pTOD->year/100);
	}
	pNvRAM->CMOS.Month  = (rtems_unsigned8)Bin2BCD(pTOD->month);
	pNvRAM->CMOS.Date   = (rtems_unsigned8)Bin2BCD(pTOD->day);
	pNvRAM->CMOS.Day    = (rtems_unsigned8)(GregorianDay(pTOD) + 1);
	pNvRAM->CMOS.Hour   = (rtems_unsigned8)Bin2BCD(pTOD->hour);
	pNvRAM->CMOS.Minute = (rtems_unsigned8)Bin2BCD(pTOD->minute);
	pNvRAM->CMOS.Second = (rtems_unsigned8)Bin2BCD(pTOD->second);
 
	/*
	 * Set the realtime clock control to update the time.
	 */
 
	EIEIO;
	pNvRAM->CMOS.Control&=~MK48T18_CTRL_WRITE;
}
 
boolean
timeMkGet (
    rtems_time_of_day *pTOD
    )
 
/*++
 
Routine Description:
 
    This routine queries the realtime clock.
 
    N.B. This routine is required to provide any synchronization necessary
         to query the realtime clock information.
 
Arguments:
 
    pTOD - Supplies a pointer to a time structure that receives
        the realtime clock information.
 
Return Value:
 
    If the power to the realtime clock has not failed, then the time
    values are read from the realtime clock and a value of TRUE is
    returned. Otherwise, a value of FALSE is returned.
 
--*/
 
{
	PMK48T18_NVRAM_MAP pNvRAM = MK48T18_BASE;
 
	/*
	 * Set the RTC into read mode
	 */
	pNvRAM->CMOS.Control|=MK48T18_CTRL_READ;
	EIEIO;
 
	/*
	 * Read the realtime clock values.
	 */
 
	pTOD->year = (rtems_unsigned16)(100*BCD2Bin(pNvRAM->CMOS.Century)+
					      BCD2Bin(pNvRAM->CMOS.Year));
	pTOD->month = (rtems_unsigned8)BCD2Bin(pNvRAM->CMOS.Month);
	pTOD->day = (rtems_unsigned8)BCD2Bin(pNvRAM->CMOS.Date);
	pTOD->hour = (rtems_unsigned8)BCD2Bin(pNvRAM->CMOS.Hour);
	pTOD->minute = (rtems_unsigned8)BCD2Bin(pNvRAM->CMOS.Minute);
	pTOD->second = (rtems_unsigned8)BCD2Bin(pNvRAM->CMOS.Second);
 
	/*
	 * Set the realtime clock control to normal mode.
	 */
	EIEIO;
	pNvRAM->CMOS.Control&=~MK48T18_CTRL_READ;
 
	return TRUE;
}
 
/*
 * Set up entry table
 */
void
InitializeRTC(void)
{
	rtems_status_code sc;
 
	switch(ucSystemType)
	{
		case SYS_TYPE_PPC1:
		{
			if(ucBoardRevMaj<5)
			{
				pTimeFunc=&timeDsTable;
				break;
			}
			/*
			 * For the 005 and later drop through to the PPC1a support
			 */
		}
 
		case SYS_TYPE_PPC1a:
		{
			pTimeFunc=&timeMkTable;
			break;
		}
 
		default:
		{
			pTimeFunc=&timeDsTable;
			break;
		}
	}
 
	/*
	 * Set up mutex semaphore
	 */
	sc = rtems_semaphore_create (
		rtems_build_name ('R', 'T', 'C', 's'),
		1,
		RTEMS_BINARY_SEMAPHORE |
		RTEMS_INHERIT_PRIORITY |
		RTEMS_PRIORITY,
		RTEMS_NO_PRIORITY,
		&semRTC);
	if (sc != RTEMS_SUCCESSFUL)
	{
		rtems_fatal_error_occurred (sc);
	}
}
 
void setRealTimeToRTEMS()
{
	rtems_time_of_day rtc_tod;
 
	rtems_semaphore_obtain(semRTC, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
	(pTimeFunc->GetTime)(&rtc_tod);
	rtems_semaphore_release(semRTC);
 
	/*
	 * Millenium fix...
	 *
	 * If year is earlier than MIN_YEAR then assume the clock has wrapped from
	 * 1999 to 1900 so advance by a century
	 */
	if(rtc_tod.year<MIN_YEAR)
	{
		rtc_tod.year+=100;
		rtems_semaphore_obtain(semRTC, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
		(pTimeFunc->SetTime)(&rtc_tod);
		rtems_semaphore_release(semRTC);
	}
 
	rtc_tod.ticks=0;
 
	rtems_clock_set( &rtc_tod );
}
 
void setRealTimeFromRTEMS()
{
	rtems_time_of_day rtems_tod;
 
	rtems_clock_get( RTEMS_CLOCK_GET_TOD, &rtems_tod );
	rtems_semaphore_obtain(semRTC, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
	(pTimeFunc->SetTime)(&rtems_tod);
	rtems_semaphore_release(semRTC);
}
 
 
int checkRealTime()
{
  return 0;
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.