[U-Boot] [PATCH] drivers/rtc: add support for MCP7941x RTCs
Philip Paeps
philip at paeps.cx
Thu Mar 6 23:26:32 CET 2014
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 <philip at 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
More information about the U-Boot
mailing list