@@ -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
@@ -0,0 +1,187 @@
+/*
+ * (C) Copyright 2014
+ * Dvorkin Dmitry, Tibbo Tech., dvorkin@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)
+{