diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/rtc/ds1307.c | 69 | ||||
-rw-r--r-- | drivers/rtc/emul_rtc.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-uclass.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rx8025.c | 166 |
5 files changed, 121 insertions, 119 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index b6692e62df1..71777cdd05f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -136,6 +136,7 @@ config RTC_RX8010SJ config RTC_RX8025 bool "Enable RX8025 driver" + depends on DM_RTC help Support for Epson RX8025 Real Time Clock devices. diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c index 2015ce9bbcd..3be97c9d933 100644 --- a/drivers/rtc/ds1307.c +++ b/drivers/rtc/ds1307.c @@ -43,11 +43,21 @@ enum ds_type { #define RTC_SEC_BIT_CH 0x80 /* Clock Halt (in Register 0) */ +/* DS1307-specific bits */ #define RTC_CTL_BIT_RS0 0x01 /* Rate select 0 */ #define RTC_CTL_BIT_RS1 0x02 /* Rate select 1 */ #define RTC_CTL_BIT_SQWE 0x10 /* Square Wave Enable */ #define RTC_CTL_BIT_OUT 0x80 /* Output Control */ +/* DS1337-specific bits */ +#define DS1337_CTL_BIT_RS1 0x08 /* Rate select 1 */ +#define DS1337_CTL_BIT_RS2 0x10 /* Rate select 2 */ +#define DS1337_CTL_BIT_EOSC 0x80 /* Enable Oscillator */ + +/* DS1340-specific bits */ +#define DS1340_SEC_BIT_EOSC 0x80 /* Enable Oscillator */ +#define DS1340_CTL_BIT_OUT 0x80 /* Output Control */ + /* MCP7941X-specific bits */ #define MCP7941X_BIT_ST 0x80 #define MCP7941X_BIT_VBATEN 0x08 @@ -261,9 +271,25 @@ read_rtc: buf[RTC_SEC_REG_ADDR]); return -1; } - } - - if (type == m41t11) { + } else if (type == ds_1337) { + if (buf[RTC_CTL_REG_ADDR] & DS1337_CTL_BIT_EOSC) { + printf("### Warning: RTC oscillator has stopped\n"); + /* clear the not oscillator enable (~EOSC) flag */ + buf[RTC_CTL_REG_ADDR] &= ~DS1337_CTL_BIT_EOSC; + dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, + buf[RTC_CTL_REG_ADDR]); + return -1; + } + } else if (type == ds_1340) { + if (buf[RTC_SEC_REG_ADDR] & DS1340_SEC_BIT_EOSC) { + printf("### Warning: RTC oscillator has stopped\n"); + /* clear the not oscillator enable (~EOSC) flag */ + buf[RTC_SEC_REG_ADDR] &= ~DS1340_SEC_BIT_EOSC; + dm_i2c_reg_write(dev, RTC_SEC_REG_ADDR, + buf[RTC_SEC_REG_ADDR]); + return -1; + } + } else if (type == m41t11) { /* clock halted? turn it on, so clock can tick. */ if (buf[RTC_SEC_REG_ADDR] & RTC_SEC_BIT_CH) { buf[RTC_SEC_REG_ADDR] &= ~RTC_SEC_BIT_CH; @@ -273,9 +299,7 @@ read_rtc: buf[RTC_SEC_REG_ADDR]); goto read_rtc; } - } - - if (type == mcp794xx) { + } else if (type == mcp794xx) { /* 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, @@ -314,18 +338,37 @@ read_rtc: static int ds1307_rtc_reset(struct udevice *dev) { int ret; + enum ds_type type = dev_get_driver_data(dev); - /* clear Clock Halt */ + /* + * reset clock/oscillator in the seconds register: + * on DS1307 bit 7 enables Clock Halt (CH), + * on DS1340 bit 7 disables the oscillator (not EOSC) + * on MCP794xx bit 7 enables Start Oscillator (ST) + */ 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; - return 0; + if (type == ds_1307) { + /* Write control register in order to enable square-wave + * output (SQWE) and set a default rate of 32.768kHz (RS1|RS0). + */ + ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, + RTC_CTL_BIT_SQWE | RTC_CTL_BIT_RS1 | + RTC_CTL_BIT_RS0); + } else if (type == ds_1337) { + /* Write control register in order to enable oscillator output + * (not EOSC) and set a default rate of 32.768kHz (RS2|RS1). + */ + ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, + DS1337_CTL_BIT_RS2 | DS1337_CTL_BIT_RS1); + } else if (type == ds_1340 || type == mcp794xx || type == m41t11) { + /* Reset clock calibration, frequency test and output level. */ + ret = dm_i2c_reg_write(dev, RTC_CTL_REG_ADDR, 0x00); + } + + return ret; } static int ds1307_probe(struct udevice *dev) diff --git a/drivers/rtc/emul_rtc.c b/drivers/rtc/emul_rtc.c index 8f0e1ab5ac6..6f47d82522b 100644 --- a/drivers/rtc/emul_rtc.c +++ b/drivers/rtc/emul_rtc.c @@ -9,8 +9,8 @@ #include <div64.h> #include <dm.h> #include <env.h> -#include <generated/timestamp_autogenerated.h> #include <rtc.h> +#include <timestamp.h> /** * struct emul_rtc - private data for emulated RTC driver diff --git a/drivers/rtc/rtc-uclass.c b/drivers/rtc/rtc-uclass.c index 321b8732ed9..e5ae6ea4d5f 100644 --- a/drivers/rtc/rtc-uclass.c +++ b/drivers/rtc/rtc-uclass.c @@ -177,7 +177,7 @@ UCLASS_DRIVER(rtc) = { .name = "rtc", .id = UCLASS_RTC, .flags = DM_UC_FLAG_SEQ_ALIAS, -#if !CONFIG_IS_ENABLED(OF_PLATDATA) +#if CONFIG_IS_ENABLED(OF_REAL) .post_bind = dm_scan_fdt_dev, #endif }; diff --git a/drivers/rtc/rx8025.c b/drivers/rtc/rx8025.c index e717dcbbfe3..1394c2306a4 100644 --- a/drivers/rtc/rx8025.c +++ b/drivers/rtc/rx8025.c @@ -24,22 +24,11 @@ #endif /*---------------------------------------------------------------------*/ -#ifndef CONFIG_SYS_I2C_RTC_ADDR -# define CONFIG_SYS_I2C_RTC_ADDR 0x32 -#endif - -#ifdef CONFIG_DM_RTC -#define DEV_TYPE struct udevice -#else -/* Local udevice */ -struct ludevice { - u8 chip; +enum rx_model { + model_rx_8025, + model_rx_8035, }; -#define DEV_TYPE struct ludevice - -#endif - /* * RTC register addresses */ @@ -50,6 +39,7 @@ struct ludevice { #define RTC_DATE_REG_ADDR 0x04 #define RTC_MON_REG_ADDR 0x05 #define RTC_YR_REG_ADDR 0x06 +#define RTC_OFFSET_REG_ADDR 0x07 #define RTC_CTL1_REG_ADDR 0x0e #define RTC_CTL2_REG_ADDR 0x0f @@ -74,39 +64,36 @@ struct ludevice { * address in a first cycle that is terminated by * a STOP condition. The chips needs a 'restart' * sequence (start sequence without a prior stop). - * This driver has been written for a 4xx board. - * U-Boot's 4xx i2c driver is currently not capable - * to generate such cycles to some work arounds - * are used. */ -/* static uchar rtc_read (uchar reg); */ -#ifdef CONFIG_DM_RTC -/* - * on mpc85xx based board with DM and offset len 1 - * accessing rtc works fine. May we can drop this ? - */ #define rtc_read(reg) buf[(reg) & 0xf] -#else -#define rtc_read(reg) buf[((reg) + 1) & 0xf] -#endif -static int rtc_write(DEV_TYPE *dev, uchar reg, uchar val); +static int rtc_write(struct udevice *dev, uchar reg, uchar val); + +static int rx8025_is_osc_stopped(enum rx_model model, int ctrl2) +{ + int xstp = ctrl2 & RTC_CTL2_BIT_XST; + /* XSTP bit has different polarity on RX-8025 vs RX-8035. + * RX-8025: 0 == oscillator stopped + * RX-8035: 1 == oscillator stopped + */ + + if (model == model_rx_8025) + xstp = !xstp; + + return xstp; +} /* * Get the current time from the RTC */ -static int rx8025_rtc_get(DEV_TYPE *dev, struct rtc_time *tmp) +static int rx8025_rtc_get(struct udevice *dev, struct rtc_time *tmp) { int rel = 0; uchar sec, min, hour, mday, wday, mon, year, ctl2; uchar buf[16]; -#ifdef CONFIG_DM_RTC if (dm_i2c_read(dev, 0, buf, sizeof(buf))) { -#else - if (i2c_read(dev->chip, 0, 0, buf, 16)) { -#endif printf("Error reading from RTC\n"); return -EIO; } @@ -134,8 +121,7 @@ static int rx8025_rtc_get(DEV_TYPE *dev, struct rtc_time *tmp) printf("RTC: voltage drop detected\n"); rel = -1; } - - if (!(ctl2 & RTC_CTL2_BIT_XST)) { + if (rx8025_is_osc_stopped(dev->driver_data, ctl2)) { printf("RTC: oscillator stop detected\n"); rel = -1; } @@ -165,8 +151,21 @@ static int rx8025_rtc_get(DEV_TYPE *dev, struct rtc_time *tmp) /* * Set the RTC */ -static int rx8025_rtc_set(DEV_TYPE *dev, const struct rtc_time *tmp) +static int rx8025_rtc_set(struct udevice *dev, const struct rtc_time *tmp) { + /* To work around the read/write cycle issue mentioned + * at the top of this file, write all the time registers + * in one I2C transaction + */ + u8 write_op[8]; + + /* 2412 flag must be set before doing a RTC write, + * otherwise the seconds and minute register + * will be cleared when the flag is set + */ + if (rtc_write(dev, RTC_CTL1_REG_ADDR, RTC_CTL1_BIT_2412)) + return -EIO; + 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); @@ -174,50 +173,38 @@ static int rx8025_rtc_set(DEV_TYPE *dev, const struct rtc_time *tmp) if (tmp->tm_year < 1970 || tmp->tm_year > 2069) printf("WARNING: year should be between 1970 and 2069!\n"); - if (rtc_write(dev, RTC_YR_REG_ADDR, bin2bcd(tmp->tm_year % 100))) - return -EIO; - - if (rtc_write(dev, RTC_MON_REG_ADDR, bin2bcd(tmp->tm_mon))) - return -EIO; - - if (rtc_write(dev, RTC_DAY_REG_ADDR, bin2bcd(tmp->tm_wday))) - return -EIO; - - if (rtc_write(dev, RTC_DATE_REG_ADDR, bin2bcd(tmp->tm_mday))) - return -EIO; + write_op[RTC_SEC_REG_ADDR] = bin2bcd(tmp->tm_sec); + write_op[RTC_MIN_REG_ADDR] = bin2bcd(tmp->tm_min); + write_op[RTC_HR_REG_ADDR] = bin2bcd(tmp->tm_hour); + write_op[RTC_DAY_REG_ADDR] = bin2bcd(tmp->tm_wday); + write_op[RTC_DATE_REG_ADDR] = bin2bcd(tmp->tm_mday); + write_op[RTC_MON_REG_ADDR] = bin2bcd(tmp->tm_mon); + write_op[RTC_YR_REG_ADDR] = bin2bcd(tmp->tm_year % 100); + write_op[RTC_OFFSET_REG_ADDR] = 0; - if (rtc_write(dev, RTC_HR_REG_ADDR, bin2bcd(tmp->tm_hour))) - return -EIO; - - if (rtc_write(dev, RTC_MIN_REG_ADDR, bin2bcd(tmp->tm_min))) - return -EIO; - - if (rtc_write(dev, RTC_SEC_REG_ADDR, bin2bcd(tmp->tm_sec))) - return -EIO; - - return rtc_write(dev, RTC_CTL1_REG_ADDR, RTC_CTL1_BIT_2412); + return dm_i2c_write(dev, 0, &write_op[0], 8); } /* * Reset the RTC */ -static int rx8025_rtc_reset(DEV_TYPE *dev) +static int rx8025_rtc_reset(struct udevice *dev) { uchar buf[16]; uchar ctl2; -#ifdef CONFIG_DM_RTC if (dm_i2c_read(dev, 0, buf, sizeof(buf))) { -#else - if (i2c_read(dev->chip, 0, 0, buf, 16)) { -#endif printf("Error reading from RTC\n"); return -EIO; } ctl2 = rtc_read(RTC_CTL2_REG_ADDR); ctl2 &= ~(RTC_CTL2_BIT_PON | RTC_CTL2_BIT_VDET); - ctl2 |= RTC_CTL2_BIT_XST | RTC_CTL2_BIT_VDSL; + + if (dev->driver_data == model_rx_8035) + ctl2 &= ~(RTC_CTL2_BIT_XST); + else + ctl2 |= RTC_CTL2_BIT_XST; return rtc_write(dev, RTC_CTL2_REG_ADDR, ctl2); } @@ -225,17 +212,16 @@ static int rx8025_rtc_reset(DEV_TYPE *dev) /* * Helper functions */ -static int rtc_write(DEV_TYPE *dev, uchar reg, uchar val) +static int rtc_write(struct udevice *dev, uchar reg, uchar val) { - uchar buf[2]; - buf[0] = reg << 4; - buf[1] = val; - -#ifdef CONFIG_DM_RTC - if (dm_i2c_write(dev, 0, buf, 2)) { -#else - if (i2c_write(dev->chip, 0, 0, buf, 2) != 0) { -#endif + /* The RX8025/RX8035 uses the top 4 bits of the + * 'offset' byte as the start register address, + * and the bottom 4 bits as a 'transfer' mode setting + * (only applicable for reads) + */ + u8 offset = (reg << 4); + + if (dm_i2c_reg_write(dev, offset, val)) { printf("Error writing to RTC\n"); return -EIO; } @@ -243,7 +229,6 @@ static int rtc_write(DEV_TYPE *dev, uchar reg, uchar val) return 0; } -#ifdef CONFIG_DM_RTC static int rx8025_probe(struct udevice *dev) { uchar buf[16]; @@ -265,42 +250,15 @@ static const struct rtc_ops rx8025_rtc_ops = { }; static const struct udevice_id rx8025_rtc_ids[] = { - { .compatible = "epson,rx8025" }, + { .compatible = "epson,rx8025", .data = model_rx_8025 }, + { .compatible = "epson,rx8035", .data = model_rx_8035 }, { } }; -U_BOOT_DRIVER(rx8010sj_rtc) = { +U_BOOT_DRIVER(rx8025_rtc) = { .name = "rx8025_rtc", .id = UCLASS_RTC, .probe = rx8025_probe, .of_match = rx8025_rtc_ids, .ops = &rx8025_rtc_ops, }; -#else -int rtc_get(struct rtc_time *tm) -{ - struct ludevice dev = { - .chip = CONFIG_SYS_I2C_RTC_ADDR, - }; - - return rx8025_rtc_get(&dev, tm); -} - -int rtc_set(struct rtc_time *tm) -{ - struct ludevice dev = { - .chip = CONFIG_SYS_I2C_RTC_ADDR, - }; - - return rx8025_rtc_set(&dev, tm); -} - -void rtc_reset(void) -{ - struct ludevice dev = { - .chip = CONFIG_SYS_I2C_RTC_ADDR, - }; - - rx8025_rtc_reset(&dev); -} -#endif |