The Microchip MCP7941x series of chips are very similar to Maxim's DS1307 but have some important differences:
o I2C address 0x6f rather than 0x68 o The oscillator start bit logic is reversed o VBATEN bit to enable a power-fail time-stamp o SQWE is bit 6 of the control register, not bit 4 Adapt the DS1307 driver to support these chips. Signed-off-by: Philip Paeps <phi...@paeps.cx> --- README | 1 + drivers/rtc/Makefile | 1 + drivers/rtc/ds1307.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/README b/README index 216f0c7..830379d 100644 --- a/README +++ b/README @@ -1111,6 +1111,7 @@ The following options need to be configured: CONFIG_RTC_DS164x - use Dallas DS164x RTC CONFIG_RTC_ISL1208 - use Intersil ISL1208 RTC CONFIG_RTC_MAX6900 - use Maxim, Inc. MAX6900 RTC + CONFIG_RTC_MCP7941X - use Microchip MCP7941x RTC CONFIG_SYS_RTC_DS1337_NOOSC - Turn off the OSC output for DS1337 CONFIG_SYS_RV3029_TCR - enable trickle charger on RV3029 RTC. diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 003d322..49451d9 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_RTC_DS1302) += ds1302.o obj-$(CONFIG_RTC_DS1306) += ds1306.o obj-$(CONFIG_RTC_DS1307) += ds1307.o obj-$(CONFIG_RTC_DS1338) += ds1307.o +obj-$(CONFIG_RTC_MCP7941X) += ds1307.o obj-$(CONFIG_RTC_DS1337) += ds1337.o obj-$(CONFIG_RTC_DS1374) += ds1374.o obj-$(CONFIG_RTC_DS1388) += ds1337.o diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c index 1a2bad3..cbbdf9c 100644 --- a/drivers/rtc/ds1307.c +++ b/drivers/rtc/ds1307.c @@ -32,13 +32,21 @@ /*---------------------------------------------------------------------*/ #ifndef CONFIG_SYS_I2C_RTC_ADDR -# define CONFIG_SYS_I2C_RTC_ADDR 0x68 +# ifdef CONFIG_RTC_MCP7941X +# define CONFIG_SYS_I2C_RTC_ADDR 0x6f +# else +# define CONFIG_SYS_I2C_RTC_ADDR 0x68 +# endif #endif #if defined(CONFIG_RTC_DS1307) && (CONFIG_SYS_I2C_SPEED > 100000) # error The DS1307 is specified only up to 100kHz! #endif +#if defined(CONFIG_RTC_MCP7941X) && (CONFIG_SYS_I2C_SPEED > 400000) +# error The MCP7941x is specified only up to 400kHz! +#endif + /* * RTC register addresses */ @@ -51,11 +59,20 @@ #define RTC_YR_REG_ADDR 0x06 #define RTC_CTL_REG_ADDR 0x07 +#ifdef CONFIG_RTC_MCP7941X +#define RTC_SEC_BIT_ST 0x80 /* Oscillator start (in reg 0) */ +#define RTC_DAY_BIT_VBATEN 0x08 /* VBAT enable (in register 3) */ +#else #define RTC_SEC_BIT_CH 0x80 /* Clock Halt (in Register 0) */ +#endif #define RTC_CTL_BIT_RS0 0x01 /* Rate select 0 */ #define RTC_CTL_BIT_RS1 0x02 /* Rate select 1 */ +#ifdef CONFIG_RTC_MCP7941X +#define RTC_CTL_BIT_SQWE 0x40 /* Square Wave Enable */ +#else #define RTC_CTL_BIT_SQWE 0x10 /* Square Wave Enable */ +#endif #define RTC_CTL_BIT_OUT 0x80 /* Output Control */ static uchar rtc_read (uchar reg); @@ -81,6 +98,19 @@ int rtc_get (struct rtc_time *tmp) "hr: %02x min: %02x sec: %02x\n", year, mon, mday, wday, hour, min, sec); +#ifdef CONFIG_RTC_MCP7941X + if (!(wday & RTC_DAY_BIT_VBATEN)) { + printf ("### Warning: VBAT not enabled - enabling\n"); + rtc_write (RTC_DAY_REG_ADDR, + rtc_read (RTC_DAY_REG_ADDR) | RTC_DAY_BIT_VBATEN); + } + if (!(sec & RTC_SEC_BIT_ST)) { + printf ("### Warning: RTC oscillator has stopped\n"); + rtc_write (RTC_SEC_REG_ADDR, + rtc_read (RTC_SEC_REG_ADDR) | RTC_SEC_BIT_ST); + rel = -1; + } +#else if (sec & RTC_SEC_BIT_CH) { printf ("### Warning: RTC oscillator has stopped\n"); /* clear the CH flag */ @@ -88,6 +118,7 @@ int rtc_get (struct rtc_time *tmp) rtc_read (RTC_SEC_REG_ADDR) & ~RTC_SEC_BIT_CH); rel = -1; } +#endif tmp->tm_sec = bcd2bin (sec & 0x7F); tmp->tm_min = bcd2bin (min & 0x7F); @@ -121,11 +152,21 @@ int rtc_set (struct rtc_time *tmp) rtc_write (RTC_YR_REG_ADDR, bin2bcd (tmp->tm_year % 100)); rtc_write (RTC_MON_REG_ADDR, bin2bcd (tmp->tm_mon)); +#ifdef CONFIG_RTC_MCP7941X + /* Don't clobber the VBATEN bit. */ + rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1) | RTC_DAY_BIT_VBATEN); +#else rtc_write (RTC_DAY_REG_ADDR, bin2bcd (tmp->tm_wday + 1)); +#endif rtc_write (RTC_DATE_REG_ADDR, bin2bcd (tmp->tm_mday)); rtc_write (RTC_HR_REG_ADDR, bin2bcd (tmp->tm_hour)); rtc_write (RTC_MIN_REG_ADDR, bin2bcd (tmp->tm_min)); +#ifdef CONFIG_RTC_MCP7941X + /* Don't clobber the ST bit. */ + rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec) | RTC_SEC_BIT_ST); +#else rtc_write (RTC_SEC_REG_ADDR, bin2bcd (tmp->tm_sec)); +#endif return 0; } @@ -142,7 +183,13 @@ void rtc_reset (void) { struct rtc_time tmp; +#ifdef CONFIG_RTC_MCP7941X + /* Set the oscillator start and VBATEN bits. */ + rtc_write (RTC_SEC_REG_ADDR, RTC_SEC_BIT_ST); + rtc_write (RTC_DAY_REG_ADDR, RTC_DAY_BIT_VBATEN); +#else rtc_write (RTC_SEC_REG_ADDR, 0x00); /* clearing Clock Halt */ +#endif rtc_write (RTC_CTL_REG_ADDR, RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 | RTC_CTL_BIT_RS0); tmp.tm_year = 1970; -- 1.7.10.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot