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

Reply via email to