[U-Boot] tps65910x I2C RTC driver

Dvorkin Dmitry dvorkin at tibbo.com
Sun Oct 19 15:52:13 CEST 2014


Hello!

We are developing new board based on TI am33xx. (I'll send patch for 
this new board later.) It have not internal RTC and we're using the one 
from TPS65910 connected by I2C bus.
May I add this patch to U-Boot source? Thank you.

diff -urN ./drivers/rtc/Makefile ./drivers/rtc/Makefile
--- ./drivers/rtc/Makefile    2014-10-19 17:34:01.447832596 +0400
+++ ./drivers/rtc/Makefile    2014-10-19 16:29:36.650930289 +0400
@@ -49,4 +49,5 @@
  obj-$(CONFIG_RTC_RV3029) += rv3029.o
  obj-$(CONFIG_RTC_RX8025) += rx8025.o
  obj-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o
+obj-$(CONFIG_RTC_TPS65910X) += tps65910x.o
  obj-$(CONFIG_RTC_X1205) += x1205.o
diff -urN ./drivers/rtc/tps65910x.c ./drivers/rtc/tps65910x.c
--- ./drivers/rtc/tps65910x.c    1970-01-01 03:00:00.000000000 +0300
+++ ./drivers/rtc/tps65910x.c    2014-10-19 17:32:02.725481183 +0400
@@ -0,0 +1,187 @@
+/*
+ * (C) Copyright 2014
+ * Dvorkin Dmitry, Tibbo Tech., dvorkin at tibbo.com.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/*
+ * Date & Time support (no alarms) for
+ * TPS65910, TPS65910x Real Time Clock on I2C.
+ * http://www.ti.com/lit/ds/symlink/tps65910a3.pdf
+ * based on ds1307.c
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+#include <i2c.h>
+#include <power/tps65910.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
+/*---------------------------------------------------------------------*/
+
+/* usually TPS65910_CTRL_I2C_ADDR = 0x2D */
+#ifndef CONFIG_SYS_I2C_RTC_ADDR
+#define CONFIG_SYS_I2C_RTC_ADDR TPS65910_CTRL_I2C_ADDR
+#endif
+
+/*
+ * RTC register addresses
+ */
+#define RTC_SEC_REG_ADDR    0x00
+#define RTC_MIN_REG_ADDR    0x01
+#define RTC_HR_REG_ADDR        0x02
+#define RTC_MDAY_REG_ADDR    0x03
+#define RTC_MON_REG_ADDR    0x04
+#define RTC_YR_REG_ADDR        0x05
+#define RTC_WDAY_REG_ADDR    0x06
+
+#define RTC_CONTROL_REG        0x10
+#define RTC_STATUS_REG        0x11
+
+static uchar rtc_read( uchar _reg);
+static void rtc_write( uchar _reg, uchar _val);
+
+/*
+ * Get the current time from the RTC
+ */
+int rtc_get( struct rtc_time *_tmp)
+{
+    int rel = 0;
+    uchar sec, min, hour, mday, mon, year, wday;
+    uchar status;
+#ifdef CONFIG_SYS_I2C_RTC_BUS
+    unsigned int oldbus = i2c_get_bus_num();
+    i2c_set_bus_num( CONFIG_SYS_I2C_RTC_BUS);
+    DEBUGR( "%s() old bus:%d set bus:%d\n", __FUNCTION__, oldbus, 
CONFIG_SYS_I2C_RTC_BUS);
+#endif
+
+    sec    = rtc_read( RTC_SEC_REG_ADDR);
+    min    = rtc_read( RTC_MIN_REG_ADDR);
+    hour    = rtc_read( RTC_HR_REG_ADDR);
+    mday    = rtc_read( RTC_MDAY_REG_ADDR);
+    mon    = rtc_read( RTC_MON_REG_ADDR);
+    year    = rtc_read( RTC_YR_REG_ADDR);
+    wday    = rtc_read( RTC_WDAY_REG_ADDR);
+    DEBUGR( "Get RTC year: %02x mon: %02x mday: %02x wday: %02x "
+        "hr: %02x min: %02x sec: %02x\n",
+        year, mon, day, wday, hour, min, sec);
+    /* check if clock started */
+    status    = rtc_read( RTC_STATUS_REG);
+    if ( !( status & 0x80)) {
+        printf( "### Warning: RTC oscillator has stopped\n");
+        rel = -1;
+    }
+    _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) + ( bcd2bin( year) >= 70 ? 1900 : 2000);
+    _tmp->tm_wday = bcd2bin( ( wday - 1) & 0x07);
+    _tmp->tm_yday = 0;
+    _tmp->tm_isdst= 0;
+    DEBUGR( "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);
+#ifdef CONFIG_SYS_I2C_RTC_BUS
+    DEBUGR( "%s() set i2c bus back to:%d\n", __FUNCTION__, oldbus);
+    i2c_set_bus_num( oldbus);
+#endif
+    return rel;
+}
+
+/*
+ * Set the RTC
+ */
+int rtc_set( struct rtc_time *_tmp)
+{
+#ifdef CONFIG_SYS_I2C_RTC_BUS
+    unsigned int oldbus = i2c_get_bus_num();
+    i2c_set_bus_num( CONFIG_SYS_I2C_RTC_BUS);
+    DEBUGR( "%s() old bus:%d set bus:%d\n", __FUNCTION__, oldbus, 
CONFIG_SYS_I2C_RTC_BUS);
+#endif
+    DEBUGR( "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);
+    if (_tmp->tm_year < 1970 || _tmp->tm_year > 2069)
+        printf( "WARNING: year should be between 1970 and 2069!\n");
+    rtc_write( RTC_YR_REG_ADDR, bin2bcd( _tmp->tm_year % 100));
+    rtc_write( RTC_MON_REG_ADDR, bin2bcd( _tmp->tm_mon));
+    rtc_write( RTC_WDAY_REG_ADDR, bin2bcd( _tmp->tm_wday + 1));
+    rtc_write( RTC_MDAY_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));
+    rtc_write( RTC_SEC_REG_ADDR, bin2bcd( _tmp->tm_sec));
+#ifdef CONFIG_SYS_I2C_RTC_BUS
+    DEBUGR( "%s() set i2c bus back to:%d\n", __FUNCTION__, oldbus);
+    i2c_set_bus_num( oldbus);
+#endif
+    return 0;
+}
+
+/*
+ * Reset the RTC. We setting the date back to 1970-01-01.
+ */
+void rtc_reset( void)
+{
+    struct rtc_time tmp;
+    uchar state;
+#ifdef CONFIG_SYS_I2C_RTC_BUS
+    unsigned int oldbus = i2c_get_bus_num();
+    i2c_set_bus_num( CONFIG_SYS_I2C_RTC_BUS);
+    DEBUGR( "%s() old bus:%d set bus:%d\n", __FUNCTION__, oldbus, 
CONFIG_SYS_I2C_RTC_BUS);
+#endif
+    /* switch clock to external generator */
+    rtc_write( TPS65910_DEVCTRL_REG, 0x00);
+    /* set date/time */
+    tmp.tm_year = 1970;
+    tmp.tm_mon = 1;
+    tmp.tm_mday= 1;
+    tmp.tm_hour = 0;
+    tmp.tm_min = 0;
+    tmp.tm_sec = 0;
+    rtc_set(&tmp);
+    /* start clock */
+    rtc_write( RTC_CONTROL_REG, ( rtc_read( RTC_CONTROL_REG) | 0x01));
+    /* check if clock started */
+    state    = rtc_read( RTC_STATUS_REG);
+    if ( !( state & 0x80)) {
+        printf( "### Warning: RTC not started on reset\n");
+    }
+    printf( "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);
+#ifdef CONFIG_SYS_I2C_RTC_BUS
+    DEBUGR( "%s() set i2c bus back to:%d\n", __FUNCTION__, oldbus);
+    i2c_set_bus_num( oldbus);
+#endif
+    return;
+}
+
+
+/*
+ * Helper functions
+ */
+
+static
+uchar rtc_read( uchar _reg)
+{
+    return (i2c_reg_read (CONFIG_SYS_I2C_RTC_ADDR, _reg));
+}
+
+static void rtc_write( uchar _reg, uchar _val)
+{
+    i2c_reg_write( CONFIG_SYS_I2C_RTC_ADDR, _reg, _val);
+}
+#endif



More information about the U-Boot mailing list