@ -16,28 +16,16 @@
# include <common.h>
# include <command.h>
# include <dm.h>
# include <rtc.h>
# include <i2c.h>
# if defined(CONFIG_CMD_DATE)
/*---------------------------------------------------------------------*/
# undef DEBUG_RTC
# ifdef DEBUG_RTC
# define DEBUGR(fmt,args...) printf(fmt ,##args)
# else
# define DEBUGR(fmt,args...)
# endif
/*---------------------------------------------------------------------*/
# ifndef CONFIG_SYS_I2C_RTC_ADDR
# define CONFIG_SYS_I2C_RTC_ADDR 0x68
# endif
# if defined(CONFIG_RTC_DS1307) && (CONFIG_SYS_I2C_SPEED > 100000)
# error The DS1307 is specified only up to 100kHz!
# endif
enum ds_type {
ds_1307 ,
ds_1337 ,
ds_1340 ,
mcp794xx ,
} ;
/*
* RTC register addresses
@ -62,6 +50,28 @@
# define MCP7941X_BIT_ST 0x80
# define MCP7941X_BIT_VBATEN 0x08
# ifndef CONFIG_DM_RTC
# if defined(CONFIG_CMD_DATE)
/*---------------------------------------------------------------------*/
# undef DEBUG_RTC
# ifdef DEBUG_RTC
# define DEBUGR(fmt, args...) printf(fmt, ##args)
# else
# define DEBUGR(fmt, args...)
# endif
/*---------------------------------------------------------------------*/
# ifndef CONFIG_SYS_I2C_RTC_ADDR
# define CONFIG_SYS_I2C_RTC_ADDR 0x68
# endif
# if defined(CONFIG_RTC_DS1307) && (CONFIG_SYS_I2C_SPEED > 100000)
# error The DS1307 is specified only up to 100kHz!
# endif
static uchar rtc_read ( uchar reg ) ;
static void rtc_write ( uchar reg , uchar val ) ;
@ -211,4 +221,163 @@ static void rtc_write (uchar reg, uchar val)
{
i2c_reg_write ( CONFIG_SYS_I2C_RTC_ADDR , reg , val ) ;
}
# endif
# endif /* CONFIG_CMD_DATE*/
# endif /* !CONFIG_DM_RTC */
# ifdef CONFIG_DM_RTC
static int ds1307_rtc_set ( struct udevice * dev , const struct rtc_time * tm )
{
int ret ;
uchar buf [ 7 ] ;
enum ds_type type = dev_get_driver_data ( dev ) ;
debug ( " Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d \n " ,
tm - > tm_year , tm - > tm_mon , tm - > tm_mday , tm - > tm_wday ,
tm - > tm_hour , tm - > tm_min , tm - > tm_sec ) ;
if ( tm - > tm_year < 1970 | | tm - > tm_year > 2069 )
printf ( " WARNING: year should be between 1970 and 2069! \n " ) ;
buf [ RTC_YR_REG_ADDR ] = bin2bcd ( tm - > tm_year % 100 ) ;
buf [ RTC_MON_REG_ADDR ] = bin2bcd ( tm - > tm_mon ) ;
buf [ RTC_DAY_REG_ADDR ] = bin2bcd ( tm - > tm_wday + 1 ) ;
buf [ RTC_DATE_REG_ADDR ] = bin2bcd ( tm - > tm_mday ) ;
buf [ RTC_HR_REG_ADDR ] = bin2bcd ( tm - > tm_hour ) ;
buf [ RTC_MIN_REG_ADDR ] = bin2bcd ( tm - > tm_min ) ;
buf [ RTC_SEC_REG_ADDR ] = bin2bcd ( tm - > tm_sec ) ;
if ( type = = mcp794xx ) {
buf [ RTC_DAY_REG_ADDR ] | = MCP7941X_BIT_VBATEN ;
buf [ RTC_SEC_REG_ADDR ] | = MCP7941X_BIT_ST ;
}
ret = dm_i2c_write ( dev , 0 , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
return ret ;
return 0 ;
}
static int ds1307_rtc_get ( struct udevice * dev , struct rtc_time * tm )
{
int ret ;
uchar buf [ 7 ] ;
enum ds_type type = dev_get_driver_data ( dev ) ;
read_rtc :
ret = dm_i2c_read ( dev , 0 , buf , sizeof ( buf ) ) ;
if ( ret < 0 )
return ret ;
if ( type = = ds_1307 ) {
if ( buf [ RTC_SEC_REG_ADDR ] & RTC_SEC_BIT_CH ) {
printf ( " ### Warning: RTC oscillator has stopped \n " ) ;
/* clear the CH flag */
buf [ RTC_SEC_REG_ADDR ] & = ~ RTC_SEC_BIT_CH ;
dm_i2c_reg_write ( dev , RTC_SEC_REG_ADDR ,
buf [ RTC_SEC_REG_ADDR ] ) ;
return - 1 ;
}
}
if ( type = = mcp794xx ) {
/* make sure that the backup battery is enabled */
if ( ! ( buf [ RTC_DAY_REG_ADDR ] & MCP7941X_BIT_VBATEN ) ) {
dm_i2c_reg_write ( dev , RTC_DAY_REG_ADDR ,
buf [ RTC_DAY_REG_ADDR ] |
MCP7941X_BIT_VBATEN ) ;
}
/* clock halted? turn it on, so clock can tick. */
if ( ! ( buf [ RTC_SEC_REG_ADDR ] & MCP7941X_BIT_ST ) ) {
dm_i2c_reg_write ( dev , RTC_SEC_REG_ADDR ,
MCP7941X_BIT_ST ) ;
printf ( " Started RTC \n " ) ;
goto read_rtc ;
}
}
tm - > tm_sec = bcd2bin ( buf [ RTC_SEC_REG_ADDR ] & 0x7F ) ;
tm - > tm_min = bcd2bin ( buf [ RTC_MIN_REG_ADDR ] & 0x7F ) ;
tm - > tm_hour = bcd2bin ( buf [ RTC_HR_REG_ADDR ] & 0x3F ) ;
tm - > tm_mday = bcd2bin ( buf [ RTC_DATE_REG_ADDR ] & 0x3F ) ;
tm - > tm_mon = bcd2bin ( buf [ RTC_MON_REG_ADDR ] & 0x1F ) ;
tm - > tm_year = bcd2bin ( buf [ RTC_YR_REG_ADDR ] ) +
( bcd2bin ( buf [ RTC_YR_REG_ADDR ] ) > = 70 ?
1900 : 2000 ) ;
tm - > tm_wday = bcd2bin ( ( buf [ RTC_DAY_REG_ADDR ] - 1 ) & 0x07 ) ;
tm - > tm_yday = 0 ;
tm - > tm_isdst = 0 ;
debug ( " Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d \n " ,
tm - > tm_year , tm - > tm_mon , tm - > tm_mday , tm - > tm_wday ,
tm - > tm_hour , tm - > tm_min , tm - > tm_sec ) ;
return 0 ;
}
static int ds1307_rtc_reset ( struct udevice * dev )
{
int ret ;
struct rtc_time tmp = {
. tm_year = 1970 ,
. tm_mon = 1 ,
. tm_mday = 1 ,
. tm_hour = 0 ,
. tm_min = 0 ,
. tm_sec = 0 ,
} ;
/* clear Clock Halt */
ret = dm_i2c_reg_write ( dev , RTC_SEC_REG_ADDR , 0x00 ) ;
if ( ret < 0 )
return ret ;
ret = dm_i2c_reg_write ( dev , RTC_CTL_REG_ADDR ,
RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 |
RTC_CTL_BIT_RS0 ) ;
if ( ret < 0 )
return ret ;
ret = ds1307_rtc_set ( dev , & tmp ) ;
if ( ret < 0 )
return ret ;
debug ( " RTC: %4d-%02d-%02d %2d:%02d:%02d UTC \n " ,
tmp . tm_year , tmp . tm_mon , tmp . tm_mday ,
tmp . tm_hour , tmp . tm_min , tmp . tm_sec ) ;
return 0 ;
}
static int ds1307_probe ( struct udevice * dev )
{
i2c_set_chip_flags ( dev , DM_I2C_CHIP_RD_ADDRESS |
DM_I2C_CHIP_WR_ADDRESS ) ;
return 0 ;
}
static const struct rtc_ops ds1307_rtc_ops = {
. get = ds1307_rtc_get ,
. set = ds1307_rtc_set ,
. reset = ds1307_rtc_reset ,
} ;
static const struct udevice_id ds1307_rtc_ids [ ] = {
{ . compatible = " dallas,ds1307 " , . data = ds_1307 } ,
{ . compatible = " dallas,ds1337 " , . data = ds_1337 } ,
{ . compatible = " dallas,ds1340 " , . data = ds_1340 } ,
{ . compatible = " microchip,mcp7941x " , . data = mcp794xx } ,
{ }
} ;
U_BOOT_DRIVER ( rtc_ds1307 ) = {
. name = " rtc-ds1307 " ,
. id = UCLASS_RTC ,
. probe = ds1307_probe ,
. of_match = ds1307_rtc_ids ,
. ops = & ds1307_rtc_ops ,
} ;
# endif /* CONFIG_DM_RTC */