[U-Boot] [PATCH v1 0/2] DS1307 RTC update

The first patch is the addition of a KConfig option for the date command. I haven't updated any boards to use the new option due to the sheer number of boards that would affect. It's probably better if board maintainers switch if/when they're ready.
The second patch is the change I really want to see. As it allows me to switch a board I'm working on over to the driver model. I've tried to replicate the non-DM version of the driver faithfully but I've only got access to a ds1340 device so I can't be sure that the mcp7941x specific code is correct.
Chris Packham (2): cmd: add Kconfig option for 'date' command rtc: Add DM support to ds1307
cmd/Kconfig | 6 ++ drivers/rtc/Kconfig | 7 ++ drivers/rtc/ds1307.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 190 insertions(+), 19 deletions(-)

Signed-off-by: Chris Packham judge.packham@gmail.com ---
cmd/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/cmd/Kconfig b/cmd/Kconfig index 13dc46a..1aaf8c5 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -676,6 +676,12 @@ config CMD_LED with led on/off/togle/blink. Any LED drivers can be controlled with this command, e.g. led_gpio.
+config CMD_DATE + bool "date" + help + Enable the 'date' command for getting/setting the time/date in RTC + devices. + config CMD_TIME bool "time" help

Add an implementation of the ds1307 driver that uses the driver model i2c APIs.
Signed-off-by: Chris Packham judge.packham@gmail.com
---
drivers/rtc/Kconfig | 7 ++ drivers/rtc/ds1307.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 184 insertions(+), 19 deletions(-)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index cb79a01..d06130c7 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -23,4 +23,11 @@ config RTC_PCF2127 has a selectable I2C-bus or SPI-bus, a backup battery switch-over circuit, a programmable watchdog function, a timestamp function, and many other features.
+config RTC_DS1307 + bool "Enable DS1307 driver" + depends on DM_RTC + help + Support for Dallas Semiconductor (now Maxim) DS1307 and DS1338/9 and + compatible Real Time Clock devices. + endmenu diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c index 3be1da6..68d1b65 100644 --- a/drivers/rtc/ds1307.c +++ b/drivers/rtc/ds1307.c @@ -16,29 +16,12 @@
#include <common.h> #include <command.h> +#include <dm.h> #include <rtc.h> #include <i2c.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 -/*---------------------------------------------------------------------*/ - -#ifndef CONFIG_SYS_I2C_RTC_ADDR -# define CONFIG_SYS_I2C_RTC_ADDR 0x68 -#endif - -#if defined(CONFIG_RTC_DS1307) && (CONFIG_SYS_I2C_SPEED > 100000) -# error The DS1307 is specified only up to 100kHz! -#endif - /* * RTC register addresses */ @@ -62,6 +45,26 @@ #define MCP7941X_BIT_ST 0x80 #define MCP7941X_BIT_VBATEN 0x08
+#ifndef CONFIG_DM_RTC + +/*---------------------------------------------------------------------*/ +#undef DEBUG_RTC + +#ifdef DEBUG_RTC +#define DEBUGR(fmt, args...) printf(fmt, ##args) +#else +#define DEBUGR(fmt, args...) +#endif +/*---------------------------------------------------------------------*/ + +#ifndef CONFIG_SYS_I2C_RTC_ADDR +# define CONFIG_SYS_I2C_RTC_ADDR 0x68 +#endif + +#if defined(CONFIG_RTC_DS1307) && (CONFIG_SYS_I2C_SPEED > 100000) +# error The DS1307 is specified only up to 100kHz! +#endif + static uchar rtc_read (uchar reg); static void rtc_write (uchar reg, uchar val);
@@ -211,4 +214,159 @@ static void rtc_write (uchar reg, uchar val) { i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val); } -#endif + +#else +static int ds1307_rtc_set(struct udevice *dev, const struct rtc_time *tm) +{ + int ret; + uchar buf[7]; + + debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + if (tm->tm_year < 1970 || tm->tm_year > 2069) + printf("WARNING: year should be between 1970 and 2069!\n"); + + buf[RTC_YR_REG_ADDR] = bin2bcd(tm->tm_year % 100); + buf[RTC_MON_REG_ADDR] = bin2bcd(tm->tm_mon); + buf[RTC_DAY_REG_ADDR] = bin2bcd(tm->tm_wday + 1); + buf[RTC_DATE_REG_ADDR] = bin2bcd(tm->tm_mday); + buf[RTC_HR_REG_ADDR] = bin2bcd(tm->tm_hour); + buf[RTC_MIN_REG_ADDR] = bin2bcd(tm->tm_min); + buf[RTC_SEC_REG_ADDR] = bin2bcd(tm->tm_sec); + + if (of_device_is_compatible(dev, "microchip,mcp7941x")) { + buf[RTC_DAY_REG_ADDR] |= MCP7941X_BIT_VBATEN; + buf[RTC_SEC_REG_ADDR] |= MCP7941X_BIT_ST; + } + + ret = dm_i2c_write(dev, 0, buf, sizeof(buf)); + if (ret < 0) + return ret; + + return 0; +} + +static int ds1307_rtc_get(struct udevice *dev, struct rtc_time *tm) +{ + int ret; + uchar buf[7]; + +read_rtc: + ret = dm_i2c_read(dev, 0, buf, sizeof(buf)); + if (ret < 0) + return ret; + + if (of_device_is_compatible(dev, "dallas,ds1307")) { + if (buf[RTC_SEC_REG_ADDR] & RTC_SEC_BIT_CH) { + printf("### Warning: RTC oscillator has stopped\n"); + /* clear the CH flag */ + buf[RTC_SEC_REG_ADDR] &= ~RTC_SEC_BIT_CH; + dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, + buf[RTC_SEC_REG_ADDR]); + return -1; + } + } + + if (of_device_is_compatible(dev, "dallas,mcp7941x")) { + /* make sure that the backup battery is enabled */ + if (!(buf[RTC_DAY_REG_ADDR] & MCP7941X_BIT_VBATEN)) { + dm_i2c_reg_write(dev, RTC_DAY_REG_ADDR, + buf[RTC_DAY_REG_ADDR] | + MCP7941X_BIT_VBATEN); + } + + /* clock halted? turn it on, so clock can tick. */ + if (!(buf[RTC_SEC_REG_ADDR] & MCP7941X_BIT_ST)) { + dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, + MCP7941X_BIT_ST); + printf("Started RTC\n"); + goto read_rtc; + } + } + + tm->tm_sec = bcd2bin(buf[RTC_SEC_REG_ADDR] & 0x7F); + tm->tm_min = bcd2bin(buf[RTC_MIN_REG_ADDR] & 0x7F); + tm->tm_hour = bcd2bin(buf[RTC_HR_REG_ADDR] & 0x3F); + tm->tm_mday = bcd2bin(buf[RTC_DATE_REG_ADDR] & 0x3F); + tm->tm_mon = bcd2bin(buf[RTC_MON_REG_ADDR] & 0x1F); + tm->tm_year = bcd2bin(buf[RTC_YR_REG_ADDR]) + + (bcd2bin(buf[RTC_YR_REG_ADDR]) >= 70 ? + 1900 : 2000); + tm->tm_wday = bcd2bin((buf[RTC_DAY_REG_ADDR] - 1) & 0x07); + tm->tm_yday = 0; + tm->tm_isdst = 0; + + debug("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return 0; +} + +static int ds1307_rtc_reset(struct udevice *dev) +{ + int ret; + struct rtc_time tmp = { + .tm_year = 1970, + .tm_mon = 1, + .tm_mday = 1, + .tm_hour = 0, + .tm_min = 0, + .tm_sec = 0, + }; + + /* clear Clock Halt */ + ret = dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, 0x00); + if (ret < 0) + return ret; + ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, + RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 | + RTC_CTL_BIT_RS0); + if (ret < 0) + return ret; + + ret = ds1307_rtc_set(dev, &tmp); + if (ret < 0) + return ret; + + debug("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); + + return 0; +} + +static int ds1307_probe(struct udevice *dev) +{ + i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS | + DM_I2C_CHIP_WR_ADDRESS); + + return 0; +} + +static const struct rtc_ops ds1307_rtc_ops = { + .get = ds1307_rtc_get, + .set = ds1307_rtc_set, + .reset = ds1307_rtc_reset, +}; + +static const struct udevice_id ds1307_rtc_ids[] = { + { .compatible = "dallas,ds1307" }, + { .compatible = "dallas,ds1337" }, + { .compatible = "dallas,ds1340" }, + { .compatible = "microchip,mcp7941x" }, + { } +}; + +U_BOOT_DRIVER(rtc_ds1307) = { + .name = "rtc-ds1307", + .id = UCLASS_RTC, + .probe = ds1307_probe, + .of_match = ds1307_rtc_ids, + .ops = &ds1307_rtc_ops, +}; +#endif /* CONFIG_DM_RTC */ + +#endif /* CONFIG_CMD_DATE*/

+Tom
Hi Chris,
On 21 April 2017 at 10:27, Chris Packham judge.packham@gmail.com wrote:
The first patch is the addition of a KConfig option for the date command. I haven't updated any boards to use the new option due to the sheer number of boards that would affect. It's probably better if board maintainers switch if/when they're ready.
You should be able to use moveconfig.py to do this automatically.
I'm not sure of the best method here.
Tom, do you expect people to run the tool or are you doing this yourself before you apply it?
The second patch is the change I really want to see. As it allows me to switch a board I'm working on over to the driver model. I've tried to replicate the non-DM version of the driver faithfully but I've only got access to a ds1340 device so I can't be sure that the mcp7941x specific code is correct.
Chris Packham (2): cmd: add Kconfig option for 'date' command rtc: Add DM support to ds1307
cmd/Kconfig | 6 ++ drivers/rtc/Kconfig | 7 ++ drivers/rtc/ds1307.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 190 insertions(+), 19 deletions(-)
-- 2.10.1
Regards, Simon

On Sun, Apr 23, 2017 at 09:38:58PM -0600, Simon Glass wrote:
+Tom
Hi Chris,
On 21 April 2017 at 10:27, Chris Packham judge.packham@gmail.com wrote:
The first patch is the addition of a KConfig option for the date command. I haven't updated any boards to use the new option due to the sheer number of boards that would affect. It's probably better if board maintainers switch if/when they're ready.
You should be able to use moveconfig.py to do this automatically.
I'm not sure of the best method here.
Tom, do you expect people to run the tool or are you doing this yourself before you apply it?
It depends greatly on the complexity. I appreciate it when people do it and this is probably an easy one to move. Thanks!
participants (3)
-
Chris Packham
-
Simon Glass
-
Tom Rini