@ -9,10 +9,9 @@
* Date & Time support for the MC146818 ( PIXX4 ) RTC
*/
/*#define DEBUG*/
# include <common.h>
# include <command.h>
# include <dm.h>
# include <rtc.h>
# if defined(__I386__) || defined(CONFIG_MALTA)
@ -24,9 +23,9 @@
# if defined(CONFIG_CMD_DATE)
/* Set this to 1 to clear the CMOS RAM */
# define CLEAR_CMOS 0
# define CLEAR_CMOS 0
# define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70
# define RTC_PORT_MC146818 CONFIG_SYS_ISA_IO_BASE_ADDRESS + 0x70
# define RTC_SECONDS 0x00
# define RTC_SECONDS_ALARM 0x01
# define RTC_MINUTES 0x02
@ -37,10 +36,10 @@
# define RTC_DATE_OF_MONTH 0x07
# define RTC_MONTH 0x08
# define RTC_YEAR 0x09
# define RTC_CONFIG_A 0x0A
# define RTC_CONFIG_B 0x0B
# define RTC_CONFIG_C 0x0C
# define RTC_CONFIG_D 0x0D
# define RTC_CONFIG_A 0x0a
# define RTC_CONFIG_B 0x0b
# define RTC_CONFIG_C 0x0c
# define RTC_CONFIG_D 0x0d
# define RTC_REG_SIZE 0x80
# define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5)
@ -50,89 +49,7 @@
# define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80
/* ------------------------------------------------------------------------- */
int rtc_get ( struct rtc_time * tmp )
{
uchar sec , min , hour , mday , wday , mon , year ;
/* here check if rtc can be accessed */
while ( ( rtc_read8 ( RTC_CONFIG_A ) & 0x80 ) = = 0x80 ) ;
sec = rtc_read8 ( RTC_SECONDS ) ;
min = rtc_read8 ( RTC_MINUTES ) ;
hour = rtc_read8 ( RTC_HOURS ) ;
mday = rtc_read8 ( RTC_DATE_OF_MONTH ) ;
wday = rtc_read8 ( RTC_DAY_OF_WEEK ) ;
mon = rtc_read8 ( RTC_MONTH ) ;
year = rtc_read8 ( RTC_YEAR ) ;
# ifdef RTC_DEBUG
printf ( " Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x "
" hr: %02x min: %02x sec: %02x \n " ,
year , mon , mday , wday ,
hour , min , sec ) ;
printf ( " Alarms: month: %02x hour: %02x min: %02x sec: %02x \n " ,
rtc_read8 ( RTC_CONFIG_D ) & 0x3F ,
rtc_read8 ( RTC_HOURS_ALARM ) ,
rtc_read8 ( RTC_MINUTES_ALARM ) ,
rtc_read8 ( RTC_SECONDS_ALARM ) ) ;
# endif
tmp - > tm_sec = bcd2bin ( sec & 0x7F ) ;
tmp - > tm_min = bcd2bin ( min & 0x7F ) ;
tmp - > tm_hour = bcd2bin ( hour & 0x3F ) ;
tmp - > tm_mday = bcd2bin ( mday & 0x3F ) ;
tmp - > tm_mon = bcd2bin ( mon & 0x1F ) ;
tmp - > tm_year = bcd2bin ( year ) ;
tmp - > tm_wday = bcd2bin ( wday & 0x07 ) ;
if ( tmp - > tm_year < 70 )
tmp - > tm_year + = 2000 ;
else
tmp - > tm_year + = 1900 ;
tmp - > tm_yday = 0 ;
tmp - > tm_isdst = 0 ;
# ifdef RTC_DEBUG
printf ( " Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d \n " ,
tmp - > tm_year , tmp - > tm_mon , tmp - > tm_mday , tmp - > tm_wday ,
tmp - > tm_hour , tmp - > tm_min , tmp - > tm_sec ) ;
# endif
return 0 ;
}
int rtc_set ( struct rtc_time * tmp )
{
# ifdef RTC_DEBUG
printf ( " Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d \n " ,
tmp - > tm_year , tmp - > tm_mon , tmp - > tm_mday , tmp - > tm_wday ,
tmp - > tm_hour , tmp - > tm_min , tmp - > tm_sec ) ;
# endif
rtc_write8 ( RTC_CONFIG_B , 0x82 ) ; /* disable the RTC to update the regs */
rtc_write8 ( RTC_YEAR , bin2bcd ( tmp - > tm_year % 100 ) ) ;
rtc_write8 ( RTC_MONTH , bin2bcd ( tmp - > tm_mon ) ) ;
rtc_write8 ( RTC_DAY_OF_WEEK , bin2bcd ( tmp - > tm_wday ) ) ;
rtc_write8 ( RTC_DATE_OF_MONTH , bin2bcd ( tmp - > tm_mday ) ) ;
rtc_write8 ( RTC_HOURS , bin2bcd ( tmp - > tm_hour ) ) ;
rtc_write8 ( RTC_MINUTES , bin2bcd ( tmp - > tm_min ) ) ;
rtc_write8 ( RTC_SECONDS , bin2bcd ( tmp - > tm_sec ) ) ;
rtc_write8 ( RTC_CONFIG_B , 0x02 ) ; /* enable the RTC to update the regs */
return 0 ;
}
void rtc_reset ( void )
{
rtc_write8 ( RTC_CONFIG_B , 0x82 ) ; /* disable the RTC to update the regs */
rtc_write8 ( RTC_CONFIG_A , 0x20 ) ; /* Normal OP */
rtc_write8 ( RTC_CONFIG_B , 0x00 ) ;
rtc_write8 ( RTC_CONFIG_B , 0x00 ) ;
rtc_write8 ( RTC_CONFIG_B , 0x02 ) ; /* enable the RTC to update the regs */
}
/* ------------------------------------------------------------------------- */
/*
* use direct memory access
*/
int rtc_read8 ( int reg )
static int mc146818_read8 ( int reg )
{
# ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
return in8 ( CONFIG_SYS_RTC_REG_BASE_ADDR + reg ) ;
@ -149,7 +66,7 @@ int rtc_read8(int reg)
# endif
}
void rtc _write8( int reg , uchar val )
static void mc146818 _write8( int reg , uchar val )
{
# ifdef CONFIG_SYS_RTC_REG_BASE_ADDR
out8 ( CONFIG_SYS_RTC_REG_BASE_ADDR + reg , val ) ;
@ -165,26 +82,93 @@ void rtc_write8(int reg, uchar val)
# endif
}
u32 rtc_read32 ( int reg )
static int mc146818_get ( struct rtc_time * tmp )
{
u32 value = 0 ;
int i ;
uchar sec , min , hour , mday , wday , mon , year ;
for ( i = 0 ; i < sizeof ( value ) ; i + + )
value | = rtc_read8 ( reg + i ) < < ( i < < 3 ) ;
/* here check if rtc can be accessed */
while ( ( mc146818_read8 ( RTC_CONFIG_A ) & 0x80 ) = = 0x80 )
;
sec = mc146818_read8 ( RTC_SECONDS ) ;
min = mc146818_read8 ( RTC_MINUTES ) ;
hour = mc146818_read8 ( RTC_HOURS ) ;
mday = mc146818_read8 ( RTC_DATE_OF_MONTH ) ;
wday = mc146818_read8 ( RTC_DAY_OF_WEEK ) ;
mon = mc146818_read8 ( RTC_MONTH ) ;
year = mc146818_read8 ( RTC_YEAR ) ;
# ifdef RTC_DEBUG
printf ( " Get RTC year: %02x mon/cent: %02x mday: %02x wday: %02x hr: %02x min: %02x sec: %02x \n " ,
year , mon , mday , wday , hour , min , sec ) ;
printf ( " Alarms: month: %02x hour: %02x min: %02x sec: %02x \n " ,
mc146818_read8 ( RTC_CONFIG_D ) & 0x3f ,
mc146818_read8 ( RTC_HOURS_ALARM ) ,
mc146818_read8 ( RTC_MINUTES_ALARM ) ,
mc146818_read8 ( RTC_SECONDS_ALARM ) ) ;
# endif
tmp - > tm_sec = bcd2bin ( sec & 0x7f ) ;
tmp - > tm_min = bcd2bin ( min & 0x7f ) ;
tmp - > tm_hour = bcd2bin ( hour & 0x3f ) ;
tmp - > tm_mday = bcd2bin ( mday & 0x3f ) ;
tmp - > tm_mon = bcd2bin ( mon & 0x1f ) ;
tmp - > tm_year = bcd2bin ( year ) ;
tmp - > tm_wday = bcd2bin ( wday & 0x07 ) ;
if ( tmp - > tm_year < 70 )
tmp - > tm_year + = 2000 ;
else
tmp - > tm_year + = 1900 ;
return value ;
tmp - > tm_yday = 0 ;
tmp - > tm_isdst = 0 ;
# ifdef RTC_DEBUG
printf ( " Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d \n " ,
tmp - > tm_year , tmp - > tm_mon , tmp - > tm_mday , tmp - > tm_wday ,
tmp - > tm_hour , tmp - > tm_min , tmp - > tm_sec ) ;
# endif
return 0 ;
}
void rtc_write32 ( int reg , u32 value )
static int mc146818_set ( struct rtc_time * tmp )
{
int i ;
# ifdef RTC_DEBUG
printf ( " Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d \n " ,
tmp - > tm_year , tmp - > tm_mon , tmp - > tm_mday , tmp - > tm_wday ,
tmp - > tm_hour , tmp - > tm_min , tmp - > tm_sec ) ;
# endif
/* Disable the RTC to update the regs */
mc146818_write8 ( RTC_CONFIG_B , 0x82 ) ;
for ( i = 0 ; i < sizeof ( value ) ; i + + )
rtc_write8 ( reg + i , ( value > > ( i < < 3 ) ) & 0xff ) ;
mc146818_write8 ( RTC_YEAR , bin2bcd ( tmp - > tm_year % 100 ) ) ;
mc146818_write8 ( RTC_MONTH , bin2bcd ( tmp - > tm_mon ) ) ;
mc146818_write8 ( RTC_DAY_OF_WEEK , bin2bcd ( tmp - > tm_wday ) ) ;
mc146818_write8 ( RTC_DATE_OF_MONTH , bin2bcd ( tmp - > tm_mday ) ) ;
mc146818_write8 ( RTC_HOURS , bin2bcd ( tmp - > tm_hour ) ) ;
mc146818_write8 ( RTC_MINUTES , bin2bcd ( tmp - > tm_min ) ) ;
mc146818_write8 ( RTC_SECONDS , bin2bcd ( tmp - > tm_sec ) ) ;
/* Enable the RTC to update the regs */
mc146818_write8 ( RTC_CONFIG_B , 0x02 ) ;
return 0 ;
}
void rtc_init ( void )
static void mc146818_reset ( void )
{
/* Disable the RTC to update the regs */
mc146818_write8 ( RTC_CONFIG_B , 0x82 ) ;
/* Normal OP */
mc146818_write8 ( RTC_CONFIG_A , 0x20 ) ;
mc146818_write8 ( RTC_CONFIG_B , 0x00 ) ;
mc146818_write8 ( RTC_CONFIG_B , 0x00 ) ;
/* Enable the RTC to update the regs */
mc146818_write8 ( RTC_CONFIG_B , 0x02 ) ;
}
static void mc146818_init ( void )
{
# if CLEAR_CMOS
int i ;
@ -198,14 +182,126 @@ void rtc_init(void)
# endif
/* Setup the real time clock */
rtc _write8( RTC_CONFIG_B , RTC_CONFIG_B_24H ) ;
mc146818 _write8( RTC_CONFIG_B , RTC_CONFIG_B_24H ) ;
/* Setup the frequency it operates at */
rtc _write8( RTC_CONFIG_A , RTC_CONFIG_A_REF_CLCK_32KHZ |
RTC_CONFIG_A_RATE_1024HZ ) ;
mc146818 _write8( RTC_CONFIG_A , RTC_CONFIG_A_REF_CLCK_32KHZ |
RTC_CONFIG_A_RATE_1024HZ ) ;
/* Ensure all reserved bits are 0 in register D */
rtc _write8( RTC_CONFIG_D , RTC_CONFIG_D_VALID_RAM_AND_TIME ) ;
mc146818 _write8( RTC_CONFIG_D , RTC_CONFIG_D_VALID_RAM_AND_TIME ) ;
/* Clear any pending interrupts */
rtc _read8( RTC_CONFIG_C ) ;
mc146818 _read8( RTC_CONFIG_C ) ;
}
# endif
# ifdef CONFIG_DM_RTC
static int rtc_mc146818_get ( struct udevice * dev , struct rtc_time * time )
{
return mc146818_get ( time ) ;
}
static int rtc_mc146818_set ( struct udevice * dev , const struct rtc_time * time )
{
return mc146818_set ( ( struct rtc_time * ) time ) ;
}
static int rtc_mc146818_reset ( struct udevice * dev )
{
mc146818_reset ( ) ;
return 0 ;
}
static int rtc_mc146818_read8 ( struct udevice * dev , unsigned int reg )
{
return mc146818_read8 ( reg ) ;
}
static int rtc_mc146818_write8 ( struct udevice * dev , unsigned int reg , int val )
{
mc146818_write8 ( reg , val ) ;
return 0 ;
}
static int rtc_mc146818_bind ( struct udevice * dev )
{
mc146818_init ( ) ;
return 0 ;
}
static const struct rtc_ops rtc_mc146818_ops = {
. get = rtc_mc146818_get ,
. set = rtc_mc146818_set ,
. reset = rtc_mc146818_reset ,
. read8 = rtc_mc146818_read8 ,
. write8 = rtc_mc146818_write8 ,
} ;
static const struct udevice_id rtc_mc146818_ids [ ] = {
{ . compatible = " motorola,mc146818 " } ,
{ }
} ;
U_BOOT_DRIVER ( rtc_mc146818 ) = {
. name = " rtc_mc146818 " ,
. id = UCLASS_RTC ,
. of_match = rtc_mc146818_ids ,
. bind = rtc_mc146818_bind ,
. ops = & rtc_mc146818_ops ,
} ;
# else /* !CONFIG_DM_RTC */
int rtc_get ( struct rtc_time * tmp )
{
return mc146818_get ( tmp ) ;
}
int rtc_set ( struct rtc_time * tmp )
{
return mc146818_set ( tmp ) ;
}
void rtc_reset ( void )
{
mc146818_reset ( ) ;
}
int rtc_read8 ( int reg )
{
return mc146818_read8 ( reg ) ;
}
void rtc_write8 ( int reg , uchar val )
{
mc146818_write8 ( reg , val ) ;
}
u32 rtc_read32 ( int reg )
{
u32 value = 0 ;
int i ;
for ( i = 0 ; i < sizeof ( value ) ; i + + )
value | = rtc_read8 ( reg + i ) < < ( i < < 3 ) ;
return value ;
}
void rtc_write32 ( int reg , u32 value )
{
int i ;
for ( i = 0 ; i < sizeof ( value ) ; i + + )
rtc_write8 ( reg + i , ( value > > ( i < < 3 ) ) & 0xff ) ;
}
void rtc_init ( void )
{
mc146818_init ( ) ;
}
# endif /* CONFIG_DM_RTC */