[U-Boot] [PATCH 00/20] dm: rtc: Add driver model support for real-time clocks

When driver model is used for I2C, the real-time clock functionality does not work (e.g. the 'date' command gives build errors when CONFIG_DM_I2C is defined). It is possible to work around this by using driver model I2C functions. But what is really needed is an RTC uclass.
This series: - renames some RTC functions to have an rtc_ prefix - adds sandbox support for RTC and an emulated I2C RTC device - adds a driver model RTC uclass and associated tests - corrects various minor driver model I2C issues that were discovered
With this it should be fairly easy to convert an existing RTC driver to driver model, but this series does not include that as I'm not sure if any of the boards I have include an RTC.
Simon Glass (20): dm: spi: Correct the comment on spi_get_ops() dm: i2c: sandbox: Add debugging to the speed limit dm: i2c: Add functions to read and write a register dm: i2c: Add an explicit test mode to the sandbox I2C driver fdt: Correct warning in fdt_setup_simplefb_node() dm: rtc: Rename gregorian day function dm: rtc: Rename to_tm() to rtc_to_tm() and add error code dm: rtc: Rename mktime() and reduce the number of parameters dm: Remove unnecessary types in bcd.h dm: rtc: Split structure definition into its own file dm: sandbox: Add os_localtime() to obtain the system time dm: rtc: Add a uclass for real-time clocks dm: rtc: sandbox: Add an emulated I2C RTC device dm: rtc: sandbox: Add a driver for the sandbox I2C RTC dm: rtc: Convert 'date' command to support driver model dm: net: rtc: Support using driver model for rtc in sntp dm: sandbox: dts: Add a real-time clock attached to I2C dm: rtc: sandbox: Enable real-time clock support dm: test: dts: Sort the aliases in the test device tree file dm: rtc: Add tests for real-time clocks
arch/sandbox/cpu/os.c | 18 +++ arch/sandbox/dts/sandbox.dts | 12 +- arch/sandbox/include/asm/rtc.h | 28 +++++ arch/sandbox/include/asm/test.h | 31 ++++++ common/cmd_date.c | 55 +++++++--- common/fdt_support.c | 2 +- common/image.c | 2 +- configs/sandbox_defconfig | 1 + drivers/i2c/i2c-uclass.c | 19 ++++ drivers/i2c/sandbox_i2c.c | 34 ++++-- drivers/rtc/Kconfig | 8 ++ drivers/rtc/Makefile | 4 + drivers/rtc/at91sam9_rtt.c | 5 +- drivers/rtc/bfin_rtc.c | 5 +- drivers/rtc/date.c | 38 ++++--- drivers/rtc/ds1306.c | 5 +- drivers/rtc/ds1374.c | 6 +- drivers/rtc/ftrtc010.c | 5 +- drivers/rtc/i2c_rtc_emul.c | 236 ++++++++++++++++++++++++++++++++++++++++ drivers/rtc/imxdi.c | 5 +- drivers/rtc/mc13xxx-rtc.c | 5 +- drivers/rtc/mcfrtc.c | 2 +- drivers/rtc/mpc8xx.c | 5 +- drivers/rtc/mx27rtc.c | 5 +- drivers/rtc/mxsrtc.c | 5 +- drivers/rtc/pl031.c | 5 +- drivers/rtc/rtc-uclass.c | 96 ++++++++++++++++ drivers/rtc/sandbox_rtc.c | 106 ++++++++++++++++++ include/bcd.h | 8 +- include/configs/sandbox.h | 1 + include/dm/uclass-id.h | 1 + include/i2c.h | 22 ++++ include/os.h | 11 ++ include/rtc.h | 197 ++++++++++++++++++++++++++++----- include/rtc_def.h | 36 ++++++ include/spi.h | 2 +- net/sntp.c | 14 ++- post/drivers/rtc.c | 28 +++-- test/dm/Makefile | 1 + test/dm/i2c.c | 8 ++ test/dm/rtc.c | 175 +++++++++++++++++++++++++++++ test/dm/test.dts | 26 ++++- 42 files changed, 1155 insertions(+), 123 deletions(-) create mode 100644 arch/sandbox/include/asm/rtc.h create mode 100644 drivers/rtc/i2c_rtc_emul.c create mode 100644 drivers/rtc/rtc-uclass.c create mode 100644 drivers/rtc/sandbox_rtc.c create mode 100644 include/rtc_def.h create mode 100644 test/dm/rtc.c

This comment should refer to SPI, not serial.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/spi.h b/include/spi.h index c58e453..aa0598b 100644 --- a/include/spi.h +++ b/include/spi.h @@ -612,7 +612,7 @@ int sandbox_spi_get_emul(struct sandbox_state *state, struct udevice *bus, struct udevice *slave, struct udevice **emulp);
-/* Access the serial operations for a device */ +/* Access the operations for a SPI device */ #define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops) #define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops) #endif /* CONFIG_DM_SPI */

On 21 April 2015 at 00:07, Simon Glass sjg@chromium.org wrote:
This comment should refer to SPI, not serial.
Signed-off-by: Simon Glass sjg@chromium.org
include/spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/spi.h b/include/spi.h index c58e453..aa0598b 100644 --- a/include/spi.h +++ b/include/spi.h @@ -612,7 +612,7 @@ int sandbox_spi_get_emul(struct sandbox_state *state, struct udevice *bus, struct udevice *slave, struct udevice **emulp);
-/* Access the serial operations for a device */ +/* Access the operations for a SPI device */ #define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops) #define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops)
#endif /* CONFIG_DM_SPI */
2.2.0.rc0.207.ga3a616c
Reviewed-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com
thanks!

On 22 April 2015 at 05:39, Jagan Teki jagannadh.teki@gmail.com wrote:
On 21 April 2015 at 00:07, Simon Glass sjg@chromium.org wrote:
This comment should refer to SPI, not serial.
Signed-off-by: Simon Glass sjg@chromium.org
include/spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/spi.h b/include/spi.h index c58e453..aa0598b 100644 --- a/include/spi.h +++ b/include/spi.h @@ -612,7 +612,7 @@ int sandbox_spi_get_emul(struct sandbox_state *state, struct udevice *bus, struct udevice *slave, struct udevice **emulp);
-/* Access the serial operations for a device */ +/* Access the operations for a SPI device */ #define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops) #define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops)
#endif /* CONFIG_DM_SPI */
2.2.0.rc0.207.ga3a616c
Reviewed-by: Jagannadha Sutradharudu Teki jagannadh.teki@gmail.com
Applied to u-boot-dm.

Print a debug() message with the I2C speed is exceeded.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/i2c/sandbox_i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c index d6adc0f..621caec 100644 --- a/drivers/i2c/sandbox_i2c.c +++ b/drivers/i2c/sandbox_i2c.c @@ -73,8 +73,10 @@ static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, * 400KHz for reads */ is_read = nmsgs > 1; - if (i2c->speed_hz > (is_read ? 400000 : 100000)) + if (i2c->speed_hz > (is_read ? 400000 : 100000)) { + debug("%s: Max speed exceeded\n", __func__); return -EINVAL; + } return ops->xfer(emul, msg, nmsgs); }

Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Print a debug() message with the I2C speed is exceeded.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/i2c/sandbox_i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c index d6adc0f..621caec 100644 --- a/drivers/i2c/sandbox_i2c.c +++ b/drivers/i2c/sandbox_i2c.c @@ -73,8 +73,10 @@ static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, * 400KHz for reads */ is_read = nmsgs > 1;
- if (i2c->speed_hz > (is_read ? 400000 : 100000))
- if (i2c->speed_hz > (is_read ? 400000 : 100000)) {
return -EINVAL;debug("%s: Max speed exceeded\n", __func__);
- }
Why different speeds for reading/writing?
bye, Heiko
return ops->xfer(emul, msg, nmsgs); }

Hi Heiko,
On 20 April 2015 at 23:04, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Print a debug() message with the I2C speed is exceeded.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/i2c/sandbox_i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c index d6adc0f..621caec 100644 --- a/drivers/i2c/sandbox_i2c.c +++ b/drivers/i2c/sandbox_i2c.c @@ -73,8 +73,10 @@ static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, * 400KHz for reads */ is_read = nmsgs > 1;
if (i2c->speed_hz > (is_read ? 400000 : 100000))
if (i2c->speed_hz > (is_read ? 400000 : 100000)) {
debug("%s: Max speed exceeded\n", __func__); return -EINVAL;
}
Why different speeds for reading/writing?
This is just test code - in fact a later patch adds a flag to enable it only when running tests. See test/dm/i2c.c.
Regards, Simon

Hello Simon,
Am 23.04.2015 17:12, schrieb Simon Glass:
Hi Heiko,
On 20 April 2015 at 23:04, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Print a debug() message with the I2C speed is exceeded.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/i2c/sandbox_i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c index d6adc0f..621caec 100644 --- a/drivers/i2c/sandbox_i2c.c +++ b/drivers/i2c/sandbox_i2c.c @@ -73,8 +73,10 @@ static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, * 400KHz for reads */ is_read = nmsgs > 1;
if (i2c->speed_hz > (is_read ? 400000 : 100000))
if (i2c->speed_hz > (is_read ? 400000 : 100000)) {
debug("%s: Max speed exceeded\n", __func__); return -EINVAL;
}
Why different speeds for reading/writing?
This is just test code - in fact a later patch adds a flag to enable it only when running tests. See test/dm/i2c.c.
Ah, thanks for the clarification, so:
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko

On 23 April 2015 at 23:14, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 23.04.2015 17:12, schrieb Simon Glass:
Hi Heiko,
On 20 April 2015 at 23:04, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Print a debug() message with the I2C speed is exceeded.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/i2c/sandbox_i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c index d6adc0f..621caec 100644 --- a/drivers/i2c/sandbox_i2c.c +++ b/drivers/i2c/sandbox_i2c.c @@ -73,8 +73,10 @@ static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, * 400KHz for reads */ is_read = nmsgs > 1;
if (i2c->speed_hz > (is_read ? 400000 : 100000))
if (i2c->speed_hz > (is_read ? 400000 : 100000)) {
debug("%s: Max speed exceeded\n", __func__); return -EINVAL;
}
Why different speeds for reading/writing?
This is just test code - in fact a later patch adds a flag to enable it only when running tests. See test/dm/i2c.c.
Ah, thanks for the clarification, so:
Acked-by: Heiko Schocher hs@denx.de
Applied to u-boot-dm.

Add driver model versions of the legacy functions to read and write a single byte register. These are a useful shortcut in many cases.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/i2c/i2c-uclass.c | 19 +++++++++++++++++++ include/i2c.h | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+)
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index f2e95c0..b8eb2d6 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -186,6 +186,25 @@ int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer, } }
+int dm_i2c_reg_read(struct udevice *dev, uint offset) +{ + uint8_t val; + int ret; + + ret = dm_i2c_read(dev, offset, &val, 1); + if (ret < 0) + return ret; + + return val; +} + +int dm_i2c_reg_write(struct udevice *dev, uint offset, uint value) +{ + uint8_t val = value; + + return dm_i2c_write(dev, offset, &val, 1); +} + /** * i2c_probe_chip() - probe for a chip on a bus * diff --git a/include/i2c.h b/include/i2c.h index 6fd73fa..d794057 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -124,6 +124,27 @@ int dm_i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags, struct udevice **devp);
/** + * dm_i2c_reg_read() - Read a value from an I2C register + * + * This reads a single value from the given address in an I2C chip + * + * @addr: Address to read from + * @return value read, or -ve on error + */ +int dm_i2c_reg_read(struct udevice *dev, uint offset); + +/** + * dm_i2c_reg_write() - Write a value to an I2C register + * + * This writes a single value to the given address in an I2C chip + * + * @addr: Address to write to + * @val: Value to write (normally a byte) + * @return 0 on success, -ve on error + */ +int dm_i2c_reg_write(struct udevice *dev, uint offset, unsigned int val); + +/** * dm_i2c_set_bus_speed() - set the speed of a bus * * @bus: Bus to adjust

Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Add driver model versions of the legacy functions to read and write a single byte register. These are a useful shortcut in many cases.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/i2c/i2c-uclass.c | 19 +++++++++++++++++++ include/i2c.h | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+)
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index f2e95c0..b8eb2d6 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -186,6 +186,25 @@ int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer, } }
+int dm_i2c_reg_read(struct udevice *dev, uint offset) +{
- uint8_t val;
- int ret;
- ret = dm_i2c_read(dev, offset, &val, 1);
- if (ret < 0)
return ret;
- return val;
+}
+int dm_i2c_reg_write(struct udevice *dev, uint offset, uint value) +{
- uint8_t val = value;
- return dm_i2c_write(dev, offset, &val, 1);
+}
- /**
- i2c_probe_chip() - probe for a chip on a bus
diff --git a/include/i2c.h b/include/i2c.h index 6fd73fa..d794057 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -124,6 +124,27 @@ int dm_i2c_probe(struct udevice *bus, uint chip_addr, uint chip_flags, struct udevice **devp);
/**
- dm_i2c_reg_read() - Read a value from an I2C register
- This reads a single value from the given address in an I2C chip
- @addr: Address to read from
- @return value read, or -ve on error
- */
+int dm_i2c_reg_read(struct udevice *dev, uint offset);
+/**
- dm_i2c_reg_write() - Write a value to an I2C register
- This writes a single value to the given address in an I2C chip
- @addr: Address to write to
- @val: Value to write (normally a byte)
- @return 0 on success, -ve on error
- */
+int dm_i2c_reg_write(struct udevice *dev, uint offset, unsigned int val);
+/**
- dm_i2c_set_bus_speed() - set the speed of a bus
- @bus: Bus to adjust

On 20 April 2015 at 23:05, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Add driver model versions of the legacy functions to read and write a single byte register. These are a useful shortcut in many cases.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/i2c/i2c-uclass.c | 19 +++++++++++++++++++ include/i2c.h | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+)
Acked-by: Heiko Schocher hs@denx.de
Applied to u-boot-dm. [snip]

At present this driver has a few test features. They are needed for running the driver model unit tests but are confusing and unnecessary if using sandbox at the command line. Add a flag to enable the test mode, and don't enable it by default.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/sandbox/include/asm/test.h | 10 ++++++++++ drivers/i2c/sandbox_i2c.c | 34 +++++++++++++++++++++++----------- include/i2c.h | 1 + test/dm/i2c.c | 8 ++++++++ 4 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index 8e490e9..d769780 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -17,6 +17,16 @@ #define SANDBOX_PCI_CLASS_CODE PCI_CLASS_CODE_COMM #define SANDBOX_PCI_CLASS_SUB_CODE PCI_CLASS_SUB_CODE_COMM_SERIAL
+/** + * sandbox_i2c_set_test_mode() - set test mode for running unit tests + * + * See sandbox_i2c_xfer() for the behaviour changes. + * + * @bus: sandbox I2C bus to adjust + * @test_mode: true to select test mode, false to run normally + */ +void sandbox_i2c_set_test_mode(struct udevice *bus, bool test_mode); + enum sandbox_i2c_eeprom_test_mode { SIE_TEST_MODE_NONE, /* Permits read/write of only one byte per I2C transaction */ diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c index 621caec..dd1c7e5 100644 --- a/drivers/i2c/sandbox_i2c.c +++ b/drivers/i2c/sandbox_i2c.c @@ -18,8 +18,8 @@
DECLARE_GLOBAL_DATA_PTR;
-struct dm_sandbox_i2c_emul_priv { - struct udevice *emul; +struct sandbox_i2c_priv { + bool test_mode; };
static int get_emul(struct udevice *dev, struct udevice **devp, @@ -47,17 +47,25 @@ static int get_emul(struct udevice *dev, struct udevice **devp, return 0; }
+void sandbox_i2c_set_test_mode(struct udevice *bus, bool test_mode) +{ + struct sandbox_i2c_priv *priv = dev_get_priv(bus); + + priv->test_mode = test_mode; +} + static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) { struct dm_i2c_bus *i2c = dev_get_uclass_priv(bus); + struct sandbox_i2c_priv *priv = dev_get_priv(bus); struct dm_i2c_ops *ops; struct udevice *emul, *dev; bool is_read; int ret;
/* Special test code to return success but with no emulation */ - if (msg->addr == SANDBOX_I2C_TEST_ADDR) + if (priv->test_mode && msg->addr == SANDBOX_I2C_TEST_ADDR) return 0;
ret = i2c_get_chip(bus, msg->addr, 1, &dev); @@ -68,15 +76,18 @@ static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, if (ret) return ret;
- /* - * For testing, don't allow writing above 100KHz for writes and - * 400KHz for reads - */ - is_read = nmsgs > 1; - if (i2c->speed_hz > (is_read ? 400000 : 100000)) { - debug("%s: Max speed exceeded\n", __func__); - return -EINVAL; + if (priv->test_mode) { + /* + * For testing, don't allow writing above 100KHz for writes and + * 400KHz for reads. + */ + is_read = nmsgs > 1; + if (i2c->speed_hz > (is_read ? 400000 : 100000)) { + debug("%s: Max speed exceeded\n", __func__); + return -EINVAL; + } } + return ops->xfer(emul, msg, nmsgs); }
@@ -94,4 +105,5 @@ U_BOOT_DRIVER(i2c_sandbox) = { .id = UCLASS_I2C, .of_match = sandbox_i2c_ids, .ops = &sandbox_i2c_ops, + .priv_auto_alloc_size = sizeof(struct sandbox_i2c_priv), }; diff --git a/include/i2c.h b/include/i2c.h index d794057..1e25986 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -54,6 +54,7 @@ struct dm_i2c_chip { uint flags; #ifdef CONFIG_SANDBOX struct udevice *emul; + bool test_mode; #endif };
diff --git a/test/dm/i2c.c b/test/dm/i2c.c index 541b73b..c5939a1 100644 --- a/test/dm/i2c.c +++ b/test/dm/i2c.c @@ -66,6 +66,9 @@ static int dm_test_i2c_speed(struct dm_test_state *dms) uint8_t buf[5];
ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); + + /* Use test mode so we create the required errors for invalid speeds */ + sandbox_i2c_set_test_mode(bus, true); ut_assertok(i2c_get_chip(bus, chip, 1, &dev)); ut_assertok(dm_i2c_set_bus_speed(bus, 100000)); ut_assertok(dm_i2c_read(dev, 0, buf, 5)); @@ -73,6 +76,7 @@ static int dm_test_i2c_speed(struct dm_test_state *dms) ut_asserteq(400000, dm_i2c_get_bus_speed(bus)); ut_assertok(dm_i2c_read(dev, 0, buf, 5)); ut_asserteq(-EINVAL, dm_i2c_write(dev, 0, buf, 5)); + sandbox_i2c_set_test_mode(bus, false);
return 0; } @@ -100,7 +104,11 @@ static int dm_test_i2c_probe_empty(struct dm_test_state *dms) struct udevice *bus, *dev;
ut_assertok(uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus)); + + /* Use test mode so that this chip address will always probe */ + sandbox_i2c_set_test_mode(bus, true); ut_assertok(dm_i2c_probe(bus, SANDBOX_I2C_TEST_ADDR, 0, &dev)); + sandbox_i2c_set_test_mode(bus, false);
return 0; }

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
At present this driver has a few test features. They are needed for running the driver model unit tests but are confusing and unnecessary if using sandbox at the command line. Add a flag to enable the test mode, and don't enable it by default.
Signed-off-by: Simon Glass sjg@chromium.org
arch/sandbox/include/asm/test.h | 10 ++++++++++ drivers/i2c/sandbox_i2c.c | 34 +++++++++++++++++++++++----------- include/i2c.h | 1 + test/dm/i2c.c | 8 ++++++++ 4 files changed, 42 insertions(+), 11 deletions(-)
Applied to u-boot-dm.

Adjust the printf() string to avoid a warning on sandbox.
Signed-off-by: Simon Glass sjg@chromium.org ---
common/fdt_support.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 8266bca..6211a82 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -1533,7 +1533,7 @@ int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width, if (ret < 0) return ret;
- snprintf(name, sizeof(name), "framebuffer@%llx", base_address); + snprintf(name, sizeof(name), "framebuffer@%" PRIx64, base_address); ret = fdt_set_name(fdt, node, name); if (ret < 0) return ret;

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Adjust the printf() string to avoid a warning on sandbox.
Signed-off-by: Simon Glass sjg@chromium.org
common/fdt_support.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Applied to u-boot-dm.

Change this function name to something more descriptive. Also return a failure code if it cannot calculate a correct value.
Signed-off-by: Simon Glass sjg@chromium.org ---
common/cmd_date.c | 2 +- drivers/rtc/date.c | 9 +++++++-- drivers/rtc/ds1306.c | 2 +- include/rtc.h | 12 +++++++++++- 4 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/common/cmd_date.c b/common/cmd_date.c index e349166..3b7ac3e 100644 --- a/common/cmd_date.c +++ b/common/cmd_date.c @@ -196,7 +196,7 @@ int mk_date (const char *datestr, struct rtc_time *tmp) tmp->tm_min = val;
/* calculate day of week */ - GregorianDay (tmp); + rtc_calc_weekday(tmp);
return (0); default: diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c index 15e6db0..2000565 100644 --- a/drivers/rtc/date.c +++ b/drivers/rtc/date.c @@ -11,6 +11,7 @@
#include <common.h> #include <command.h> +#include <errno.h> #include <rtc.h>
#if defined(CONFIG_CMD_DATE) || defined(CONFIG_TIMESTAMP) @@ -30,13 +31,15 @@ static int month_days[12] = { /* * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) */ -void GregorianDay(struct rtc_time * tm) +int rtc_calc_weekday(struct rtc_time *tm) { int leapsToDate; int lastYear; int day; int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
+ if (tm->tm_year < 1753) + return -EINVAL; lastYear=tm->tm_year-1;
/* @@ -64,6 +67,8 @@ void GregorianDay(struct rtc_time * tm) day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
tm->tm_wday=day%7; + + return 0; }
void to_tm(int tim, struct rtc_time * tm) @@ -101,7 +106,7 @@ void to_tm(int tim, struct rtc_time * tm) /* * Determine the day of week */ - GregorianDay(tm); + rtc_calc_weekday(tm); }
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c index 1ec1837..3fe6721 100644 --- a/drivers/rtc/ds1306.c +++ b/drivers/rtc/ds1306.c @@ -110,7 +110,7 @@ int rtc_get (struct rtc_time *tmp) immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */ udelay (10);
- GregorianDay (tmp); /* Determine the day of week */ + rtc_calc_weekday(tmp); /* Determine the day of week */
debug ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, diff --git a/include/rtc.h b/include/rtc.h index 54e361e..96c696a 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -45,7 +45,6 @@ int rtc_get (struct rtc_time *); int rtc_set (struct rtc_time *); void rtc_reset (void);
-void GregorianDay (struct rtc_time *); void to_tm (int, struct rtc_time *); unsigned long mktime (unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); @@ -87,4 +86,15 @@ void rtc_write32(int reg, u32 value); */ void rtc_init(void);
+/** + * rtc_calc_weekday() - Work out the weekday from a time + * + * This only works for the Gregorian calendar - i.e. after 1752 (in the UK). + * It sets time->tm_wdaay to the correct day of the week. + * + * @time: Time to inspect. tm_wday is updated + * @return 0 if OK, -EINVAL if the weekday could not be determined + */ +int rtc_calc_weekday(struct rtc_time *time); + #endif /* _RTC_H_ */

Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Change this function name to something more descriptive. Also return a failure code if it cannot calculate a correct value.
Signed-off-by: Simon Glass sjg@chromium.org
common/cmd_date.c | 2 +- drivers/rtc/date.c | 9 +++++++-- drivers/rtc/ds1306.c | 2 +- include/rtc.h | 12 +++++++++++- 4 files changed, 20 insertions(+), 5 deletions(-)
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko
diff --git a/common/cmd_date.c b/common/cmd_date.c index e349166..3b7ac3e 100644 --- a/common/cmd_date.c +++ b/common/cmd_date.c @@ -196,7 +196,7 @@ int mk_date (const char *datestr, struct rtc_time *tmp) tmp->tm_min = val;
/* calculate day of week */
GregorianDay (tmp);
rtc_calc_weekday(tmp);
return (0); default:
diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c index 15e6db0..2000565 100644 --- a/drivers/rtc/date.c +++ b/drivers/rtc/date.c @@ -11,6 +11,7 @@
#include <common.h> #include <command.h> +#include <errno.h> #include <rtc.h>
#if defined(CONFIG_CMD_DATE) || defined(CONFIG_TIMESTAMP) @@ -30,13 +31,15 @@ static int month_days[12] = { /*
- This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
*/ -void GregorianDay(struct rtc_time * tm) +int rtc_calc_weekday(struct rtc_time *tm) { int leapsToDate; int lastYear; int day; int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
if (tm->tm_year < 1753)
return -EINVAL;
lastYear=tm->tm_year-1;
/*
@@ -64,6 +67,8 @@ void GregorianDay(struct rtc_time * tm) day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
tm->tm_wday=day%7;
return 0; }
void to_tm(int tim, struct rtc_time * tm)
@@ -101,7 +106,7 @@ void to_tm(int tim, struct rtc_time * tm) /* * Determine the day of week */
- GregorianDay(tm);
rtc_calc_weekday(tm); }
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c index 1ec1837..3fe6721 100644 --- a/drivers/rtc/ds1306.c +++ b/drivers/rtc/ds1306.c @@ -110,7 +110,7 @@ int rtc_get (struct rtc_time *tmp) immap->im_cpm.cp_pbdat &= ~PB_SPI_CE; /* Disable DS1306 Chip */ udelay (10);
- GregorianDay (tmp); /* Determine the day of week */
rtc_calc_weekday(tmp); /* Determine the day of week */
debug ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
diff --git a/include/rtc.h b/include/rtc.h index 54e361e..96c696a 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -45,7 +45,6 @@ int rtc_get (struct rtc_time *); int rtc_set (struct rtc_time *); void rtc_reset (void);
-void GregorianDay (struct rtc_time *); void to_tm (int, struct rtc_time *); unsigned long mktime (unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); @@ -87,4 +86,15 @@ void rtc_write32(int reg, u32 value); */ void rtc_init(void);
+/**
- rtc_calc_weekday() - Work out the weekday from a time
- This only works for the Gregorian calendar - i.e. after 1752 (in the UK).
- It sets time->tm_wdaay to the correct day of the week.
- @time: Time to inspect. tm_wday is updated
- @return 0 if OK, -EINVAL if the weekday could not be determined
- */
+int rtc_calc_weekday(struct rtc_time *time);
- #endif /* _RTC_H_ */

On 20 April 2015 at 23:13, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Change this function name to something more descriptive. Also return a failure code if it cannot calculate a correct value.
Signed-off-by: Simon Glass sjg@chromium.org
common/cmd_date.c | 2 +- drivers/rtc/date.c | 9 +++++++-- drivers/rtc/ds1306.c | 2 +- include/rtc.h | 12 +++++++++++- 4 files changed, 20 insertions(+), 5 deletions(-)
Acked-by: Heiko Schocher hs@denx.de
Applied to u-boot-dm.

Rename this function so that it is clear that it is provided by the RTC. Also return an error when it cannot function as expected. This is unlikely to occur since it works for dates since 1752 and many RTCs do not support such old dates. Still it is better to be accurate.
Signed-off-by: Simon Glass sjg@chromium.org ---
common/image.c | 2 +- drivers/rtc/at91sam9_rtt.c | 2 +- drivers/rtc/bfin_rtc.c | 2 +- drivers/rtc/date.c | 8 ++++++-- drivers/rtc/ds1374.c | 2 +- drivers/rtc/ftrtc010.c | 2 +- drivers/rtc/imxdi.c | 2 +- drivers/rtc/mc13xxx-rtc.c | 2 +- drivers/rtc/mcfrtc.c | 2 +- drivers/rtc/mpc8xx.c | 2 +- drivers/rtc/mx27rtc.c | 2 +- drivers/rtc/mxsrtc.c | 2 +- drivers/rtc/pl031.c | 2 +- include/rtc.h | 15 ++++++++++++++- net/sntp.c | 2 +- post/drivers/rtc.c | 6 +++--- 16 files changed, 36 insertions(+), 19 deletions(-)
diff --git a/common/image.c b/common/image.c index abc0d89..fdec496 100644 --- a/common/image.c +++ b/common/image.c @@ -533,7 +533,7 @@ void genimg_print_time(time_t timestamp) #ifndef USE_HOSTCC struct rtc_time tm;
- to_tm(timestamp, &tm); + rtc_to_tm(timestamp, &tm); printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/drivers/rtc/at91sam9_rtt.c b/drivers/rtc/at91sam9_rtt.c index 714dd2a..d3cdee0 100644 --- a/drivers/rtc/at91sam9_rtt.c +++ b/drivers/rtc/at91sam9_rtt.c @@ -44,7 +44,7 @@ int rtc_get (struct rtc_time *tmp) } while (tim!=tim2); off = readl(&gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]); /* off==0 means time is invalid, but we ignore that */ - to_tm (tim+off, tmp); + rtc_to_tm(tim+off, tmp); return 0; }
diff --git a/drivers/rtc/bfin_rtc.c b/drivers/rtc/bfin_rtc.c index 4cf2d83..6cb1eba 100644 --- a/drivers/rtc/bfin_rtc.c +++ b/drivers/rtc/bfin_rtc.c @@ -114,7 +114,7 @@ int rtc_get(struct rtc_time *tmp)
/* Calculate the total number of seconds since epoch */ time_in_sec = (tm_sec) + MIN_TO_SECS(tm_min) + HRS_TO_SECS(tm_hr) + DAYS_TO_SECS(tm_day); - to_tm(time_in_sec, tmp); + rtc_to_tm(time_in_sec, tmp);
return 0; } diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c index 2000565..79beb94 100644 --- a/drivers/rtc/date.c +++ b/drivers/rtc/date.c @@ -71,7 +71,7 @@ int rtc_calc_weekday(struct rtc_time *tm) return 0; }
-void to_tm(int tim, struct rtc_time * tm) +int rtc_to_tm(int tim, struct rtc_time *tm) { register int i; register long hms, day; @@ -103,10 +103,14 @@ void to_tm(int tim, struct rtc_time * tm) /* Days are what is left over (+1) from all that. */ tm->tm_mday = day + 1;
+ /* Zero unused fields */ + tm->tm_yday = 0; + tm->tm_isdst = 0; + /* * Determine the day of week */ - rtc_calc_weekday(tm); + return rtc_calc_weekday(tm); }
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. diff --git a/drivers/rtc/ds1374.c b/drivers/rtc/ds1374.c index 427b1eb..04793b5 100644 --- a/drivers/rtc/ds1374.c +++ b/drivers/rtc/ds1374.c @@ -118,7 +118,7 @@ int rtc_get (struct rtc_time *tm){
DEBUGR ("Get RTC s since 1.1.1970: %ld\n", time1);
- to_tm(time1, tm); /* To Gregorian Date */ + rtc_to_tm(time1, tm); /* To Gregorian Date */
if (rtc_read(RTC_SR_ADDR) & RTC_SR_BIT_OSF) { printf ("### Warning: RTC oscillator has stopped\n"); diff --git a/drivers/rtc/ftrtc010.c b/drivers/rtc/ftrtc010.c index 713dad2..3c5d955 100644 --- a/drivers/rtc/ftrtc010.c +++ b/drivers/rtc/ftrtc010.c @@ -86,7 +86,7 @@ int rtc_get(struct rtc_time *tmp) now = ftrtc010_time() + readl(&rtc->record); #endif
- to_tm(now, tmp); + rtc_to_tm(now, tmp);
return 0; } diff --git a/drivers/rtc/imxdi.c b/drivers/rtc/imxdi.c index 0d7d736..e89034d 100644 --- a/drivers/rtc/imxdi.c +++ b/drivers/rtc/imxdi.c @@ -192,7 +192,7 @@ int rtc_get(struct rtc_time *tmp) }
now = __raw_readl(&data.regs->dtcmr); - to_tm(now, tmp); + rtc_to_tm(now, tmp);
err: return rc; diff --git a/drivers/rtc/mc13xxx-rtc.c b/drivers/rtc/mc13xxx-rtc.c index 528247a..30c4e66 100644 --- a/drivers/rtc/mc13xxx-rtc.c +++ b/drivers/rtc/mc13xxx-rtc.c @@ -36,7 +36,7 @@ int rtc_get(struct rtc_time *rtc)
tim = day1 * 86400 + time;
- to_tm(tim, rtc); + rtc_to_tm(tim, rtc);
rtc->tm_yday = 0; rtc->tm_isdst = 0; diff --git a/drivers/rtc/mcfrtc.c b/drivers/rtc/mcfrtc.c index 8961ca4..e02e297 100644 --- a/drivers/rtc/mcfrtc.c +++ b/drivers/rtc/mcfrtc.c @@ -38,7 +38,7 @@ int rtc_get(struct rtc_time *tmp) tim = (tim * 60) + rtc_mins; tim = (tim * 60) + rtc->seconds;
- to_tm(tim, tmp); + rtc_to_tm(tim, tmp);
tmp->tm_yday = 0; tmp->tm_isdst = 0; diff --git a/drivers/rtc/mpc8xx.c b/drivers/rtc/mpc8xx.c index d239dae..796295d 100644 --- a/drivers/rtc/mpc8xx.c +++ b/drivers/rtc/mpc8xx.c @@ -26,7 +26,7 @@ int rtc_get (struct rtc_time *tmp)
tim = immr->im_sit.sit_rtc;
- to_tm (tim, tmp); + rtc_to_tm(tim, tmp);
debug ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, diff --git a/drivers/rtc/mx27rtc.c b/drivers/rtc/mx27rtc.c index ae6595b..7ba74d3 100644 --- a/drivers/rtc/mx27rtc.c +++ b/drivers/rtc/mx27rtc.c @@ -30,7 +30,7 @@ int rtc_get(struct rtc_time *time)
sec += min * 60 + hour * 3600 + day * 24 * 3600;
- to_tm(sec, time); + rtc_to_tm(sec, time);
return 0; } diff --git a/drivers/rtc/mxsrtc.c b/drivers/rtc/mxsrtc.c index 32ba8a3..82c2fbf 100644 --- a/drivers/rtc/mxsrtc.c +++ b/drivers/rtc/mxsrtc.c @@ -43,7 +43,7 @@ int rtc_get(struct rtc_time *time) uint32_t secs;
secs = readl(&rtc_regs->hw_rtc_seconds); - to_tm(secs, time); + rtc_to_tm(secs, time);
return 0; } diff --git a/drivers/rtc/pl031.c b/drivers/rtc/pl031.c index c4d1259..e6c1a6c 100644 --- a/drivers/rtc/pl031.c +++ b/drivers/rtc/pl031.c @@ -97,7 +97,7 @@ int rtc_get(struct rtc_time *tmp)
tim = RTC_READ_REG(RTC_DR);
- to_tm (tim, tmp); + rtc_to_tm(tim, tmp);
debug ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, diff --git a/include/rtc.h b/include/rtc.h index 96c696a..4b7ce61 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -45,7 +45,6 @@ int rtc_get (struct rtc_time *); int rtc_set (struct rtc_time *); void rtc_reset (void);
-void to_tm (int, struct rtc_time *); unsigned long mktime (unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
@@ -97,4 +96,18 @@ void rtc_init(void); */ int rtc_calc_weekday(struct rtc_time *time);
+/** + * rtc_to_tm() - Convert a time_t value into a broken-out time + * + * The following fields are set up by this function: + * tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday + * + * Note that tm_yday and tm_isdst are set to 0. + * + * @time_t: Number of seconds since 1970-01-01 00:00:00 + * @time: Place to put the broken-out time + * @return 0 if OK, -EINVAL if the weekday could not be determined + */ +int rtc_to_tm(int time_t, struct rtc_time *time); + #endif /* _RTC_H_ */ diff --git a/net/sntp.c b/net/sntp.c index 6422eef..d7b9e55 100644 --- a/net/sntp.c +++ b/net/sntp.c @@ -68,7 +68,7 @@ static void sntp_handler(uchar *pkt, unsigned dest, struct in_addr sip, */ memcpy(&seconds, &rpktp->transmit_timestamp, sizeof(ulong));
- to_tm(ntohl(seconds) - 2208988800UL + net_ntp_time_offset, &tm); + rtc_to_tm(ntohl(seconds) - 2208988800UL + net_ntp_time_offset, &tm); #if defined(CONFIG_CMD_DATE) rtc_set(&tm); #endif diff --git a/post/drivers/rtc.c b/post/drivers/rtc.c index cd19f75..8d7a788 100644 --- a/post/drivers/rtc.c +++ b/post/drivers/rtc.c @@ -63,7 +63,7 @@ static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) tm->tm_min, tm->tm_sec) + sec; struct rtc_time ntm;
- to_tm (t, &ntm); + rtc_to_tm(t, &ntm);
rtc_set (&ntm); } @@ -119,7 +119,7 @@ int rtc_post_test (int flags) time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59); struct rtc_time tm;
- to_tm (t, &tm); + rtc_to_tm(t, &tm); rtc_set (&tm);
skipped++; @@ -143,7 +143,7 @@ int rtc_post_test (int flags) time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59); struct rtc_time tm;
- to_tm (t, &tm); + rtc_to_tm(t, &tm); rtc_set (&tm);
skipped++;

Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Rename this function so that it is clear that it is provided by the RTC. Also return an error when it cannot function as expected. This is unlikely to occur since it works for dates since 1752 and many RTCs do not support such old dates. Still it is better to be accurate.
Signed-off-by: Simon Glass sjg@chromium.org
common/image.c | 2 +- drivers/rtc/at91sam9_rtt.c | 2 +- drivers/rtc/bfin_rtc.c | 2 +- drivers/rtc/date.c | 8 ++++++-- drivers/rtc/ds1374.c | 2 +- drivers/rtc/ftrtc010.c | 2 +- drivers/rtc/imxdi.c | 2 +- drivers/rtc/mc13xxx-rtc.c | 2 +- drivers/rtc/mcfrtc.c | 2 +- drivers/rtc/mpc8xx.c | 2 +- drivers/rtc/mx27rtc.c | 2 +- drivers/rtc/mxsrtc.c | 2 +- drivers/rtc/pl031.c | 2 +- include/rtc.h | 15 ++++++++++++++- net/sntp.c | 2 +- post/drivers/rtc.c | 6 +++--- 16 files changed, 36 insertions(+), 19 deletions(-)
Thanks!
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko
diff --git a/common/image.c b/common/image.c index abc0d89..fdec496 100644 --- a/common/image.c +++ b/common/image.c @@ -533,7 +533,7 @@ void genimg_print_time(time_t timestamp) #ifndef USE_HOSTCC struct rtc_time tm;
- to_tm(timestamp, &tm);
- rtc_to_tm(timestamp, &tm); printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
diff --git a/drivers/rtc/at91sam9_rtt.c b/drivers/rtc/at91sam9_rtt.c index 714dd2a..d3cdee0 100644 --- a/drivers/rtc/at91sam9_rtt.c +++ b/drivers/rtc/at91sam9_rtt.c @@ -44,7 +44,7 @@ int rtc_get (struct rtc_time *tmp) } while (tim!=tim2); off = readl(&gpbr->reg[AT91_GPBR_INDEX_TIMEOFF]); /* off==0 means time is invalid, but we ignore that */
- to_tm (tim+off, tmp);
- rtc_to_tm(tim+off, tmp); return 0; }
diff --git a/drivers/rtc/bfin_rtc.c b/drivers/rtc/bfin_rtc.c index 4cf2d83..6cb1eba 100644 --- a/drivers/rtc/bfin_rtc.c +++ b/drivers/rtc/bfin_rtc.c @@ -114,7 +114,7 @@ int rtc_get(struct rtc_time *tmp)
/* Calculate the total number of seconds since epoch */ time_in_sec = (tm_sec) + MIN_TO_SECS(tm_min) + HRS_TO_SECS(tm_hr) + DAYS_TO_SECS(tm_day);
- to_tm(time_in_sec, tmp);
rtc_to_tm(time_in_sec, tmp);
return 0; }
diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c index 2000565..79beb94 100644 --- a/drivers/rtc/date.c +++ b/drivers/rtc/date.c @@ -71,7 +71,7 @@ int rtc_calc_weekday(struct rtc_time *tm) return 0; }
-void to_tm(int tim, struct rtc_time * tm) +int rtc_to_tm(int tim, struct rtc_time *tm) { register int i; register long hms, day; @@ -103,10 +103,14 @@ void to_tm(int tim, struct rtc_time * tm) /* Days are what is left over (+1) from all that. */ tm->tm_mday = day + 1;
- /* Zero unused fields */
- tm->tm_yday = 0;
- tm->tm_isdst = 0;
- /*
*/
- Determine the day of week
- rtc_calc_weekday(tm);
return rtc_calc_weekday(tm); }
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
diff --git a/drivers/rtc/ds1374.c b/drivers/rtc/ds1374.c index 427b1eb..04793b5 100644 --- a/drivers/rtc/ds1374.c +++ b/drivers/rtc/ds1374.c @@ -118,7 +118,7 @@ int rtc_get (struct rtc_time *tm){
DEBUGR ("Get RTC s since 1.1.1970: %ld\n", time1);
- to_tm(time1, tm); /* To Gregorian Date */
rtc_to_tm(time1, tm); /* To Gregorian Date */
if (rtc_read(RTC_SR_ADDR) & RTC_SR_BIT_OSF) { printf ("### Warning: RTC oscillator has stopped\n");
diff --git a/drivers/rtc/ftrtc010.c b/drivers/rtc/ftrtc010.c index 713dad2..3c5d955 100644 --- a/drivers/rtc/ftrtc010.c +++ b/drivers/rtc/ftrtc010.c @@ -86,7 +86,7 @@ int rtc_get(struct rtc_time *tmp) now = ftrtc010_time() + readl(&rtc->record); #endif
- to_tm(now, tmp);
rtc_to_tm(now, tmp);
return 0; }
diff --git a/drivers/rtc/imxdi.c b/drivers/rtc/imxdi.c index 0d7d736..e89034d 100644 --- a/drivers/rtc/imxdi.c +++ b/drivers/rtc/imxdi.c @@ -192,7 +192,7 @@ int rtc_get(struct rtc_time *tmp) }
now = __raw_readl(&data.regs->dtcmr);
- to_tm(now, tmp);
rtc_to_tm(now, tmp);
err: return rc;
diff --git a/drivers/rtc/mc13xxx-rtc.c b/drivers/rtc/mc13xxx-rtc.c index 528247a..30c4e66 100644 --- a/drivers/rtc/mc13xxx-rtc.c +++ b/drivers/rtc/mc13xxx-rtc.c @@ -36,7 +36,7 @@ int rtc_get(struct rtc_time *rtc)
tim = day1 * 86400 + time;
- to_tm(tim, rtc);
rtc_to_tm(tim, rtc);
rtc->tm_yday = 0; rtc->tm_isdst = 0;
diff --git a/drivers/rtc/mcfrtc.c b/drivers/rtc/mcfrtc.c index 8961ca4..e02e297 100644 --- a/drivers/rtc/mcfrtc.c +++ b/drivers/rtc/mcfrtc.c @@ -38,7 +38,7 @@ int rtc_get(struct rtc_time *tmp) tim = (tim * 60) + rtc_mins; tim = (tim * 60) + rtc->seconds;
- to_tm(tim, tmp);
rtc_to_tm(tim, tmp);
tmp->tm_yday = 0; tmp->tm_isdst = 0;
diff --git a/drivers/rtc/mpc8xx.c b/drivers/rtc/mpc8xx.c index d239dae..796295d 100644 --- a/drivers/rtc/mpc8xx.c +++ b/drivers/rtc/mpc8xx.c @@ -26,7 +26,7 @@ int rtc_get (struct rtc_time *tmp)
tim = immr->im_sit.sit_rtc;
- to_tm (tim, tmp);
rtc_to_tm(tim, tmp);
debug ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
diff --git a/drivers/rtc/mx27rtc.c b/drivers/rtc/mx27rtc.c index ae6595b..7ba74d3 100644 --- a/drivers/rtc/mx27rtc.c +++ b/drivers/rtc/mx27rtc.c @@ -30,7 +30,7 @@ int rtc_get(struct rtc_time *time)
sec += min * 60 + hour * 3600 + day * 24 * 3600;
- to_tm(sec, time);
rtc_to_tm(sec, time);
return 0; }
diff --git a/drivers/rtc/mxsrtc.c b/drivers/rtc/mxsrtc.c index 32ba8a3..82c2fbf 100644 --- a/drivers/rtc/mxsrtc.c +++ b/drivers/rtc/mxsrtc.c @@ -43,7 +43,7 @@ int rtc_get(struct rtc_time *time) uint32_t secs;
secs = readl(&rtc_regs->hw_rtc_seconds);
- to_tm(secs, time);
rtc_to_tm(secs, time);
return 0; }
diff --git a/drivers/rtc/pl031.c b/drivers/rtc/pl031.c index c4d1259..e6c1a6c 100644 --- a/drivers/rtc/pl031.c +++ b/drivers/rtc/pl031.c @@ -97,7 +97,7 @@ int rtc_get(struct rtc_time *tmp)
tim = RTC_READ_REG(RTC_DR);
- to_tm (tim, tmp);
rtc_to_tm(tim, tmp);
debug ( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
diff --git a/include/rtc.h b/include/rtc.h index 96c696a..4b7ce61 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -45,7 +45,6 @@ int rtc_get (struct rtc_time *); int rtc_set (struct rtc_time *); void rtc_reset (void);
-void to_tm (int, struct rtc_time *); unsigned long mktime (unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
@@ -97,4 +96,18 @@ void rtc_init(void); */ int rtc_calc_weekday(struct rtc_time *time);
+/**
- rtc_to_tm() - Convert a time_t value into a broken-out time
- The following fields are set up by this function:
- tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday
- Note that tm_yday and tm_isdst are set to 0.
- @time_t: Number of seconds since 1970-01-01 00:00:00
- @time: Place to put the broken-out time
- @return 0 if OK, -EINVAL if the weekday could not be determined
- */
+int rtc_to_tm(int time_t, struct rtc_time *time);
- #endif /* _RTC_H_ */
diff --git a/net/sntp.c b/net/sntp.c index 6422eef..d7b9e55 100644 --- a/net/sntp.c +++ b/net/sntp.c @@ -68,7 +68,7 @@ static void sntp_handler(uchar *pkt, unsigned dest, struct in_addr sip, */ memcpy(&seconds, &rpktp->transmit_timestamp, sizeof(ulong));
- to_tm(ntohl(seconds) - 2208988800UL + net_ntp_time_offset, &tm);
- rtc_to_tm(ntohl(seconds) - 2208988800UL + net_ntp_time_offset, &tm); #if defined(CONFIG_CMD_DATE) rtc_set(&tm); #endif
diff --git a/post/drivers/rtc.c b/post/drivers/rtc.c index cd19f75..8d7a788 100644 --- a/post/drivers/rtc.c +++ b/post/drivers/rtc.c @@ -63,7 +63,7 @@ static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) tm->tm_min, tm->tm_sec) + sec; struct rtc_time ntm;
- to_tm (t, &ntm);
rtc_to_tm(t, &ntm);
rtc_set (&ntm); }
@@ -119,7 +119,7 @@ int rtc_post_test (int flags) time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59); struct rtc_time tm;
to_tm (t, &tm);
rtc_to_tm(t, &tm);
rtc_set (&tm);
skipped++;
@@ -143,7 +143,7 @@ int rtc_post_test (int flags) time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59); struct rtc_time tm;
to_tm (t, &tm);
rtc_to_tm(t, &tm);
rtc_set (&tm);
skipped++;

On 20 April 2015 at 23:16, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Rename this function so that it is clear that it is provided by the RTC. Also return an error when it cannot function as expected. This is unlikely to occur since it works for dates since 1752 and many RTCs do not support such old dates. Still it is better to be accurate.
Signed-off-by: Simon Glass sjg@chromium.org
common/image.c | 2 +- drivers/rtc/at91sam9_rtt.c | 2 +- drivers/rtc/bfin_rtc.c | 2 +- drivers/rtc/date.c | 8 ++++++-- drivers/rtc/ds1374.c | 2 +- drivers/rtc/ftrtc010.c | 2 +- drivers/rtc/imxdi.c | 2 +- drivers/rtc/mc13xxx-rtc.c | 2 +- drivers/rtc/mcfrtc.c | 2 +- drivers/rtc/mpc8xx.c | 2 +- drivers/rtc/mx27rtc.c | 2 +- drivers/rtc/mxsrtc.c | 2 +- drivers/rtc/pl031.c | 2 +- include/rtc.h | 15 ++++++++++++++- net/sntp.c | 2 +- post/drivers/rtc.c | 6 +++--- 16 files changed, 36 insertions(+), 19 deletions(-)
Thanks!
Acked-by: Heiko Schocher hs@denx.de
Applied to u-boot-dm.

Most callers unpack the structure and pass each member. It seems better to pass the whole structure instead, as with the C library. Also add an rtc_ prefix.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/rtc/at91sam9_rtt.c | 3 +-- drivers/rtc/bfin_rtc.c | 3 +-- drivers/rtc/date.c | 23 ++++++++++++----------- drivers/rtc/ds1306.c | 3 +-- drivers/rtc/ds1374.c | 4 +--- drivers/rtc/ftrtc010.c | 3 +-- drivers/rtc/imxdi.c | 3 +-- drivers/rtc/mc13xxx-rtc.c | 3 +-- drivers/rtc/mpc8xx.c | 3 +-- drivers/rtc/mx27rtc.c | 3 +-- drivers/rtc/mxsrtc.c | 3 +-- drivers/rtc/pl031.c | 3 +-- include/rtc.h | 16 +++++++++++++--- post/drivers/rtc.c | 22 ++++++++++++++++++---- 14 files changed, 54 insertions(+), 41 deletions(-)
diff --git a/drivers/rtc/at91sam9_rtt.c b/drivers/rtc/at91sam9_rtt.c index d3cdee0..a684ad6 100644 --- a/drivers/rtc/at91sam9_rtt.c +++ b/drivers/rtc/at91sam9_rtt.c @@ -54,8 +54,7 @@ int rtc_set (struct rtc_time *tmp) at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR; ulong tim;
- tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + tim = rtc_mktime(tmp);
/* clear alarm, set prescaler to 32768, clear counter */ writel(32768+AT91_RTT_RTTRST, &rtt->mr); diff --git a/drivers/rtc/bfin_rtc.c b/drivers/rtc/bfin_rtc.c index 6cb1eba..a079a1d 100644 --- a/drivers/rtc/bfin_rtc.c +++ b/drivers/rtc/bfin_rtc.c @@ -67,8 +67,7 @@ int rtc_set(struct rtc_time *tmp) wait_for_complete();
/* Calculate number of seconds this incoming time represents */ - remain = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + remain = rtc_mktime(tmp);
/* Figure out how many days since epoch */ days = remain / NUM_SECS_IN_DAY; diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c index 79beb94..8c643a0 100644 --- a/drivers/rtc/date.c +++ b/drivers/rtc/date.c @@ -128,22 +128,23 @@ int rtc_to_tm(int tim, struct rtc_time *tm) * machines were long is 32-bit! (However, as time_t is signed, we * will already get problems at other places on 2038-01-19 03:14:08) */ -unsigned long -mktime (unsigned int year, unsigned int mon, - unsigned int day, unsigned int hour, - unsigned int min, unsigned int sec) +unsigned long rtc_mktime(const struct rtc_time *tm) { - if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + int mon = tm->tm_mon; + int year = tm->tm_year; + int days, hours; + + mon -= 2; + if (0 >= (int)mon) { /* 1..12 -> 11,12,1..10 */ mon += 12; /* Puts Feb last since it has leap day */ year -= 1; }
- return ((( - (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) + - year*365 - 719499 - )*24 + hour /* now have hours */ - )*60 + min /* now have minutes */ - )*60 + sec; /* finally seconds */ + days = (unsigned long)(year / 4 - year / 100 + year / 400 + + 367 * mon / 12 + tm->tm_mday) + + year * 365 - 719499; + hours = days * 24 + tm->tm_hour; + return (hours * 60 + tm->tm_min) * 60 + tm->tm_sec; }
#endif diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c index 3fe6721..7dd3e19 100644 --- a/drivers/rtc/ds1306.c +++ b/drivers/rtc/ds1306.c @@ -180,8 +180,7 @@ int rtc_set (struct rtc_time *tmp) { ulong tim;
- tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + tim = rtc_mktime(tmp);
immap->im_sitk.sitk_rtck = KAPWR_KEY; immap->im_sit.sit_rtc = tim; diff --git a/drivers/rtc/ds1374.c b/drivers/rtc/ds1374.c index 04793b5..7847357 100644 --- a/drivers/rtc/ds1374.c +++ b/drivers/rtc/ds1374.c @@ -147,9 +147,7 @@ int rtc_set (struct rtc_time *tmp){ if (tmp->tm_year < 1970 || tmp->tm_year > 2069) printf("WARNING: year should be between 1970 and 2069!\n");
- time = mktime(tmp->tm_year, tmp->tm_mon, - tmp->tm_mday, tmp->tm_hour, - tmp->tm_min, tmp->tm_sec); + time = rtc_mktime(tmp);
DEBUGR ("Set RTC s since 1.1.1970: %ld (0x%02lx)\n", time, time);
diff --git a/drivers/rtc/ftrtc010.c b/drivers/rtc/ftrtc010.c index 3c5d955..7d0cfb3 100644 --- a/drivers/rtc/ftrtc010.c +++ b/drivers/rtc/ftrtc010.c @@ -104,8 +104,7 @@ int rtc_set(struct rtc_time *tmp) tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- new = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour, - tmp->tm_min, tmp->tm_sec); + new = rtc_mktime(tmp);
now = ftrtc010_time();
diff --git a/drivers/rtc/imxdi.c b/drivers/rtc/imxdi.c index e89034d..17519ce 100644 --- a/drivers/rtc/imxdi.c +++ b/drivers/rtc/imxdi.c @@ -209,8 +209,7 @@ int rtc_set(struct rtc_time *tmp) goto err; }
- now = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + now = rtc_mktime(tmp); /* zero the fractional part first */ rc = DI_WRITE_WAIT(0, dtclr); if (rc == 0) diff --git a/drivers/rtc/mc13xxx-rtc.c b/drivers/rtc/mc13xxx-rtc.c index 30c4e66..3e46336 100644 --- a/drivers/rtc/mc13xxx-rtc.c +++ b/drivers/rtc/mc13xxx-rtc.c @@ -51,8 +51,7 @@ int rtc_set(struct rtc_time *rtc) if (!p) return -1;
- time = mktime(rtc->tm_year, rtc->tm_mon, rtc->tm_mday, - rtc->tm_hour, rtc->tm_min, rtc->tm_sec); + time = rtc_mktime(rtc); day = time / 86400; time %= 86400;
diff --git a/drivers/rtc/mpc8xx.c b/drivers/rtc/mpc8xx.c index 796295d..147a225 100644 --- a/drivers/rtc/mpc8xx.c +++ b/drivers/rtc/mpc8xx.c @@ -44,8 +44,7 @@ int rtc_set (struct rtc_time *tmp) tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + tim = rtc_mktime(tmp);
immr->im_sitk.sitk_rtck = KAPWR_KEY; immr->im_sit.sit_rtc = tim; diff --git a/drivers/rtc/mx27rtc.c b/drivers/rtc/mx27rtc.c index 7ba74d3..29ccdf1 100644 --- a/drivers/rtc/mx27rtc.c +++ b/drivers/rtc/mx27rtc.c @@ -40,8 +40,7 @@ int rtc_set(struct rtc_time *time) struct rtc_regs *rtc_regs = (struct rtc_regs *)IMX_RTC_BASE; uint32_t day, hour, min, sec;
- sec = mktime(time->tm_year, time->tm_mon, time->tm_mday, - time->tm_hour, time->tm_min, time->tm_sec); + sec = rtc_mktime(time);
day = sec / (24 * 3600); sec = sec % (24 * 3600); diff --git a/drivers/rtc/mxsrtc.c b/drivers/rtc/mxsrtc.c index 82c2fbf..6e32154 100644 --- a/drivers/rtc/mxsrtc.c +++ b/drivers/rtc/mxsrtc.c @@ -52,8 +52,7 @@ int rtc_set(struct rtc_time *time) { uint32_t secs;
- secs = mktime(time->tm_year, time->tm_mon, time->tm_mday, - time->tm_hour, time->tm_min, time->tm_sec); + secs = rtc_mktime(time);
return mxs_rtc_set_time(secs); } diff --git a/drivers/rtc/pl031.c b/drivers/rtc/pl031.c index e6c1a6c..fc83049 100644 --- a/drivers/rtc/pl031.c +++ b/drivers/rtc/pl031.c @@ -72,8 +72,7 @@ int rtc_set(struct rtc_time *tmp) }
/* Calculate number of seconds this incoming time represents */ - tim = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + tim = rtc_mktime(tmp);
RTC_WRITE_REG(RTC_LR, tim);
diff --git a/include/rtc.h b/include/rtc.h index 4b7ce61..b1a4bf0 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -45,9 +45,6 @@ int rtc_get (struct rtc_time *); int rtc_set (struct rtc_time *); void rtc_reset (void);
-unsigned long mktime (unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int); - /** * rtc_read8() - Read an 8-bit register * @@ -110,4 +107,17 @@ int rtc_calc_weekday(struct rtc_time *time); */ int rtc_to_tm(int time_t, struct rtc_time *time);
+/** + * rtc_mktime() - Convert a broken-out time into a time_t value + * + * The following fields need to be valid for this function to work: + * tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year + * + * Note that tm_wday and tm_yday are ignored. + * + * @time: Broken-out time to convert + * @return corresponding time_t value, seconds since 1970-01-01 00:00:00 + */ +unsigned long rtc_mktime(const struct rtc_time *time); + #endif /* _RTC_H_ */ diff --git a/post/drivers/rtc.c b/post/drivers/rtc.c index 8d7a788..c2e7391 100644 --- a/post/drivers/rtc.c +++ b/post/drivers/rtc.c @@ -59,8 +59,7 @@ static int rtc_post_skip (ulong * diff)
static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) { - time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, - tm->tm_min, tm->tm_sec) + sec; + time_t t = rtc_mktime(tm) + sec; struct rtc_time ntm;
rtc_to_tm(t, &ntm); @@ -116,9 +115,16 @@ int rtc_post_test (int flags) rtc_get (&svtm);
for (i = 0; i < 12; i++) { - time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59); + time_t t; struct rtc_time tm;
+ tm.tm_year = ynl; + tm.tm_mon = i + 1; + tm.tm_mday = daysnl[i]; + tm.tm_hour = 23; + tm.tm_min = 59; + tm.tm_sec = 59; + t = rtc_mktime(&tm); rtc_to_tm(t, &tm); rtc_set (&tm);
@@ -140,9 +146,17 @@ int rtc_post_test (int flags) }
for (i = 0; i < 12; i++) { - time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59); + time_t t; struct rtc_time tm;
+ tm.tm_year = yl; + tm.tm_mon = i + 1; + tm.tm_mday = daysl[i]; + tm.tm_hour = 23; + tm.tm_min = 59; + tm.tm_sec = 59; + t = rtc_mktime(&tm); + rtc_to_tm(t, &tm); rtc_set (&tm);

Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Most callers unpack the structure and pass each member. It seems better to pass the whole structure instead, as with the C library. Also add an rtc_ prefix.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/rtc/at91sam9_rtt.c | 3 +-- drivers/rtc/bfin_rtc.c | 3 +-- drivers/rtc/date.c | 23 ++++++++++++----------- drivers/rtc/ds1306.c | 3 +-- drivers/rtc/ds1374.c | 4 +--- drivers/rtc/ftrtc010.c | 3 +-- drivers/rtc/imxdi.c | 3 +-- drivers/rtc/mc13xxx-rtc.c | 3 +-- drivers/rtc/mpc8xx.c | 3 +-- drivers/rtc/mx27rtc.c | 3 +-- drivers/rtc/mxsrtc.c | 3 +-- drivers/rtc/pl031.c | 3 +-- include/rtc.h | 16 +++++++++++++--- post/drivers/rtc.c | 22 ++++++++++++++++++---- 14 files changed, 54 insertions(+), 41 deletions(-)
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko
diff --git a/drivers/rtc/at91sam9_rtt.c b/drivers/rtc/at91sam9_rtt.c index d3cdee0..a684ad6 100644 --- a/drivers/rtc/at91sam9_rtt.c +++ b/drivers/rtc/at91sam9_rtt.c @@ -54,8 +54,7 @@ int rtc_set (struct rtc_time *tmp) at91_gpbr_t *gpbr = (at91_gpbr_t *) ATMEL_BASE_GPBR; ulong tim;
- tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
tim = rtc_mktime(tmp);
/* clear alarm, set prescaler to 32768, clear counter */ writel(32768+AT91_RTT_RTTRST, &rtt->mr);
diff --git a/drivers/rtc/bfin_rtc.c b/drivers/rtc/bfin_rtc.c index 6cb1eba..a079a1d 100644 --- a/drivers/rtc/bfin_rtc.c +++ b/drivers/rtc/bfin_rtc.c @@ -67,8 +67,7 @@ int rtc_set(struct rtc_time *tmp) wait_for_complete();
/* Calculate number of seconds this incoming time represents */
- remain = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
remain = rtc_mktime(tmp);
/* Figure out how many days since epoch */ days = remain / NUM_SECS_IN_DAY;
diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c index 79beb94..8c643a0 100644 --- a/drivers/rtc/date.c +++ b/drivers/rtc/date.c @@ -128,22 +128,23 @@ int rtc_to_tm(int tim, struct rtc_time *tm)
- machines were long is 32-bit! (However, as time_t is signed, we
- will already get problems at other places on 2038-01-19 03:14:08)
*/ -unsigned long -mktime (unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
+unsigned long rtc_mktime(const struct rtc_time *tm) {
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- int mon = tm->tm_mon;
- int year = tm->tm_year;
- int days, hours;
- mon -= 2;
- if (0 >= (int)mon) { /* 1..12 -> 11,12,1..10 */ mon += 12; /* Puts Feb last since it has leap day */ year -= 1; }
- return (((
(unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
year*365 - 719499
)*24 + hour /* now have hours */
)*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
days = (unsigned long)(year / 4 - year / 100 + year / 400 +
367 * mon / 12 + tm->tm_mday) +
year * 365 - 719499;
hours = days * 24 + tm->tm_hour;
return (hours * 60 + tm->tm_min) * 60 + tm->tm_sec; }
#endif
diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c index 3fe6721..7dd3e19 100644 --- a/drivers/rtc/ds1306.c +++ b/drivers/rtc/ds1306.c @@ -180,8 +180,7 @@ int rtc_set (struct rtc_time *tmp) { ulong tim;
tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
tim = rtc_mktime(tmp);
immap->im_sitk.sitk_rtck = KAPWR_KEY; immap->im_sit.sit_rtc = tim;
diff --git a/drivers/rtc/ds1374.c b/drivers/rtc/ds1374.c index 04793b5..7847357 100644 --- a/drivers/rtc/ds1374.c +++ b/drivers/rtc/ds1374.c @@ -147,9 +147,7 @@ int rtc_set (struct rtc_time *tmp){ if (tmp->tm_year < 1970 || tmp->tm_year > 2069) printf("WARNING: year should be between 1970 and 2069!\n");
- time = mktime(tmp->tm_year, tmp->tm_mon,
tmp->tm_mday, tmp->tm_hour,
tmp->tm_min, tmp->tm_sec);
time = rtc_mktime(tmp);
DEBUGR ("Set RTC s since 1.1.1970: %ld (0x%02lx)\n", time, time);
diff --git a/drivers/rtc/ftrtc010.c b/drivers/rtc/ftrtc010.c index 3c5d955..7d0cfb3 100644 --- a/drivers/rtc/ftrtc010.c +++ b/drivers/rtc/ftrtc010.c @@ -104,8 +104,7 @@ int rtc_set(struct rtc_time *tmp) tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- new = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour,
tmp->tm_min, tmp->tm_sec);
new = rtc_mktime(tmp);
now = ftrtc010_time();
diff --git a/drivers/rtc/imxdi.c b/drivers/rtc/imxdi.c index e89034d..17519ce 100644 --- a/drivers/rtc/imxdi.c +++ b/drivers/rtc/imxdi.c @@ -209,8 +209,7 @@ int rtc_set(struct rtc_time *tmp) goto err; }
- now = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- now = rtc_mktime(tmp); /* zero the fractional part first */ rc = DI_WRITE_WAIT(0, dtclr); if (rc == 0)
diff --git a/drivers/rtc/mc13xxx-rtc.c b/drivers/rtc/mc13xxx-rtc.c index 30c4e66..3e46336 100644 --- a/drivers/rtc/mc13xxx-rtc.c +++ b/drivers/rtc/mc13xxx-rtc.c @@ -51,8 +51,7 @@ int rtc_set(struct rtc_time *rtc) if (!p) return -1;
- time = mktime(rtc->tm_year, rtc->tm_mon, rtc->tm_mday,
rtc->tm_hour, rtc->tm_min, rtc->tm_sec);
- time = rtc_mktime(rtc); day = time / 86400; time %= 86400;
diff --git a/drivers/rtc/mpc8xx.c b/drivers/rtc/mpc8xx.c index 796295d..147a225 100644 --- a/drivers/rtc/mpc8xx.c +++ b/drivers/rtc/mpc8xx.c @@ -44,8 +44,7 @@ int rtc_set (struct rtc_time *tmp) tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- tim = mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
tim = rtc_mktime(tmp);
immr->im_sitk.sitk_rtck = KAPWR_KEY; immr->im_sit.sit_rtc = tim;
diff --git a/drivers/rtc/mx27rtc.c b/drivers/rtc/mx27rtc.c index 7ba74d3..29ccdf1 100644 --- a/drivers/rtc/mx27rtc.c +++ b/drivers/rtc/mx27rtc.c @@ -40,8 +40,7 @@ int rtc_set(struct rtc_time *time) struct rtc_regs *rtc_regs = (struct rtc_regs *)IMX_RTC_BASE; uint32_t day, hour, min, sec;
- sec = mktime(time->tm_year, time->tm_mon, time->tm_mday,
time->tm_hour, time->tm_min, time->tm_sec);
sec = rtc_mktime(time);
day = sec / (24 * 3600); sec = sec % (24 * 3600);
diff --git a/drivers/rtc/mxsrtc.c b/drivers/rtc/mxsrtc.c index 82c2fbf..6e32154 100644 --- a/drivers/rtc/mxsrtc.c +++ b/drivers/rtc/mxsrtc.c @@ -52,8 +52,7 @@ int rtc_set(struct rtc_time *time) { uint32_t secs;
- secs = mktime(time->tm_year, time->tm_mon, time->tm_mday,
time->tm_hour, time->tm_min, time->tm_sec);
secs = rtc_mktime(time);
return mxs_rtc_set_time(secs); }
diff --git a/drivers/rtc/pl031.c b/drivers/rtc/pl031.c index e6c1a6c..fc83049 100644 --- a/drivers/rtc/pl031.c +++ b/drivers/rtc/pl031.c @@ -72,8 +72,7 @@ int rtc_set(struct rtc_time *tmp) }
/* Calculate number of seconds this incoming time represents */
- tim = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
tim = rtc_mktime(tmp);
RTC_WRITE_REG(RTC_LR, tim);
diff --git a/include/rtc.h b/include/rtc.h index 4b7ce61..b1a4bf0 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -45,9 +45,6 @@ int rtc_get (struct rtc_time *); int rtc_set (struct rtc_time *); void rtc_reset (void);
-unsigned long mktime (unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int);
- /**
- rtc_read8() - Read an 8-bit register
@@ -110,4 +107,17 @@ int rtc_calc_weekday(struct rtc_time *time); */ int rtc_to_tm(int time_t, struct rtc_time *time);
+/**
- rtc_mktime() - Convert a broken-out time into a time_t value
- The following fields need to be valid for this function to work:
- tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year
- Note that tm_wday and tm_yday are ignored.
- @time: Broken-out time to convert
- @return corresponding time_t value, seconds since 1970-01-01 00:00:00
- */
+unsigned long rtc_mktime(const struct rtc_time *time);
- #endif /* _RTC_H_ */
diff --git a/post/drivers/rtc.c b/post/drivers/rtc.c index 8d7a788..c2e7391 100644 --- a/post/drivers/rtc.c +++ b/post/drivers/rtc.c @@ -59,8 +59,7 @@ static int rtc_post_skip (ulong * diff)
static void rtc_post_restore (struct rtc_time *tm, unsigned int sec) {
- time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec) + sec;
time_t t = rtc_mktime(tm) + sec; struct rtc_time ntm;
rtc_to_tm(t, &ntm);
@@ -116,9 +115,16 @@ int rtc_post_test (int flags) rtc_get (&svtm);
for (i = 0; i < 12; i++) {
time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59);
time_t t;
struct rtc_time tm;
tm.tm_year = ynl;
tm.tm_mon = i + 1;
tm.tm_mday = daysnl[i];
tm.tm_hour = 23;
tm.tm_min = 59;
tm.tm_sec = 59;
t = rtc_mktime(&tm);
rtc_to_tm(t, &tm); rtc_set (&tm);
@@ -140,9 +146,17 @@ int rtc_post_test (int flags) }
for (i = 0; i < 12; i++) {
time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59);
time_t t;
struct rtc_time tm;
tm.tm_year = yl;
tm.tm_mon = i + 1;
tm.tm_mday = daysl[i];
tm.tm_hour = 23;
tm.tm_min = 59;
tm.tm_sec = 59;
t = rtc_mktime(&tm);
rtc_to_tm(t, &tm); rtc_set (&tm);

On 20 April 2015 at 23:17, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 20.04.2015 20:37, schrieb Simon Glass:
Most callers unpack the structure and pass each member. It seems better to pass the whole structure instead, as with the C library. Also add an rtc_ prefix.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/rtc/at91sam9_rtt.c | 3 +-- drivers/rtc/bfin_rtc.c | 3 +-- drivers/rtc/date.c | 23 ++++++++++++----------- drivers/rtc/ds1306.c | 3 +-- drivers/rtc/ds1374.c | 4 +--- drivers/rtc/ftrtc010.c | 3 +-- drivers/rtc/imxdi.c | 3 +-- drivers/rtc/mc13xxx-rtc.c | 3 +-- drivers/rtc/mpc8xx.c | 3 +-- drivers/rtc/mx27rtc.c | 3 +-- drivers/rtc/mxsrtc.c | 3 +-- drivers/rtc/pl031.c | 3 +-- include/rtc.h | 16 +++++++++++++--- post/drivers/rtc.c | 22 ++++++++++++++++++---- 14 files changed, 54 insertions(+), 41 deletions(-)
Acked-by: Heiko Schocher hs@denx.de
Applied to u-boot-dm.

We don't need to use u8, and if we avoid it, it isn't so much of a problem that rtc.h includes this header. With this change we can include rtc.h from sandbox files.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/bcd.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/include/bcd.h b/include/bcd.h index af4aa9c..9ecd328 100644 --- a/include/bcd.h +++ b/include/bcd.h @@ -10,14 +10,12 @@ #ifndef _BCD_H #define _BCD_H
-#include <linux/types.h> - -static inline unsigned int bcd2bin(u8 val) +static inline unsigned int bcd2bin(unsigned int val) { - return ((val) & 0x0f) + ((val) >> 4) * 10; + return ((val) & 0x0f) + ((val & 0xff) >> 4) * 10; }
-static inline u8 bin2bcd (unsigned int val) +static inline unsigned int bin2bcd(unsigned int val) { return (((val / 10) << 4) | (val % 10)); }

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
We don't need to use u8, and if we avoid it, it isn't so much of a problem that rtc.h includes this header. With this change we can include rtc.h from sandbox files.
Signed-off-by: Simon Glass sjg@chromium.org
include/bcd.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
Applied to u-boot-dm.

Move the definition of struct rtc_time into a separate file so that sandbox can include it without requiring common.h and the like.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/rtc.h | 26 +------------------------- include/rtc_def.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 25 deletions(-) create mode 100644 include/rtc_def.h
diff --git a/include/rtc.h b/include/rtc.h index b1a4bf0..2566c83 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -15,31 +15,7 @@ * it there instead of in evey single driver */
#include <bcd.h> - -/* - * The struct used to pass data from the generic interface code to - * the hardware dependend low-level code ande vice versa. Identical - * to struct rtc_time used by the Linux kernel. - * - * Note that there are small but significant differences to the - * common "struct time": - * - * struct time: struct rtc_time: - * tm_mon 0 ... 11 1 ... 12 - * tm_year years since 1900 years since 0 - */ - -struct rtc_time { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; -}; +#include <rtc_def.h>
int rtc_get (struct rtc_time *); int rtc_set (struct rtc_time *); diff --git a/include/rtc_def.h b/include/rtc_def.h new file mode 100644 index 0000000..6179797 --- /dev/null +++ b/include/rtc_def.h @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __rtc_def_h +#define __rtc_def_h + +/* + * The struct used to pass data from the generic interface code to + * the hardware dependend low-level code ande vice versa. Identical + * to struct rtc_time used by the Linux kernel. + * + * Note that there are small but significant differences to the + * common "struct time": + * + * struct time: struct rtc_time: + * tm_mon 0 ... 11 1 ... 12 + * tm_year years since 1900 years since 0 + */ + +struct rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +#endif

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Move the definition of struct rtc_time into a separate file so that sandbox can include it without requiring common.h and the like.
Signed-off-by: Simon Glass sjg@chromium.org
include/rtc.h | 26 +------------------------- include/rtc_def.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 25 deletions(-) create mode 100644 include/rtc_def.h
Applied to u-boot-dm.

Add a function to read the system time into U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/sandbox/cpu/os.c | 18 ++++++++++++++++++ include/os.h | 11 +++++++++++ 2 files changed, 29 insertions(+)
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 4d5f805..e6dd17e 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -24,6 +24,7 @@ #include <asm/sections.h> #include <asm/state.h> #include <os.h> +#include <rtc_def.h>
/* Operating System Interface */
@@ -537,3 +538,20 @@ int os_jump_to_image(const void *dest, int size)
return unlink(fname); } + +void os_localtime(struct rtc_time *rt) +{ + time_t t = time(NULL); + struct tm *tm; + + tm = localtime(&t); + rt->tm_sec = tm->tm_sec; + rt->tm_min = tm->tm_min; + rt->tm_hour = tm->tm_hour; + rt->tm_mday = tm->tm_mday; + rt->tm_mon = tm->tm_mon + 1; + rt->tm_year = tm->tm_year + 1900; + rt->tm_wday = tm->tm_wday; + rt->tm_yday = tm->tm_yday; + rt->tm_isdst = tm->tm_isdst; +} diff --git a/include/os.h b/include/os.h index a758f09..ffbdce8 100644 --- a/include/os.h +++ b/include/os.h @@ -13,6 +13,7 @@
#include <linux/types.h>
+struct rtc_time; struct sandbox_state;
/** @@ -277,4 +278,14 @@ int os_read_ram_buf(const char *fname); */ int os_jump_to_image(const void *dest, int size);
+/** + * Read the current system time + * + * This reads the current Local Time and places it into the provided + * structure. + * + * @param rt Place to put system time + */ +void os_localtime(struct rtc_time *rt); + #endif

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Add a function to read the system time into U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org
arch/sandbox/cpu/os.c | 18 ++++++++++++++++++ include/os.h | 11 +++++++++++ 2 files changed, 29 insertions(+)
Applied to u-boot-dm.

Add a uclass for real-time clocks which support getting the current time, setting it and resetting the chip to a known-working state. Some RTCs have additional registers which can be used to store settings, so also provide an interface to these.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/rtc/Kconfig | 8 +++ drivers/rtc/Makefile | 2 + drivers/rtc/rtc-uclass.c | 96 ++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/rtc.h | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 239 insertions(+) create mode 100644 drivers/rtc/rtc-uclass.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e69de29..bd63621 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -0,0 +1,8 @@ +config DM_RTC + bool "Enable Driver Model for RTC drivers" + depends on DM + help + Enable drver model for real-time-clock drivers. The RTC uclass + then provides the rtc_get()/rtc_set() interface, delegating to + drivers to perform the actual functions. See rtc.h for a + description of the API. diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index fdcbc00..61373b6 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -7,6 +7,8 @@
#ccflags-y += -DDEBUG
+obj-$(CONFIG_DM_RTC) += rtc-uclass.o + obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o obj-$(CONFIG_RTC_BFIN) += bfin_rtc.o obj-y += date.o diff --git a/drivers/rtc/rtc-uclass.c b/drivers/rtc/rtc-uclass.c new file mode 100644 index 0000000..fe74c69 --- /dev/null +++ b/drivers/rtc/rtc-uclass.c @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2015 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <rtc.h> + +int dm_rtc_get(struct udevice *dev, struct rtc_time *time) +{ + struct rtc_ops *ops = rtc_get_ops(dev); + + assert(ops); + if (!ops->get) + return -ENOSYS; + return ops->get(dev, time); +} + +int dm_rtc_set(struct udevice *dev, struct rtc_time *time) +{ + struct rtc_ops *ops = rtc_get_ops(dev); + + assert(ops); + if (!ops->set) + return -ENOSYS; + return ops->set(dev, time); +} + +int dm_rtc_reset(struct udevice *dev) +{ + struct rtc_ops *ops = rtc_get_ops(dev); + + assert(ops); + if (!ops->reset) + return -ENOSYS; + return ops->reset(dev); +} + +int rtc_read8(struct udevice *dev, unsigned int reg) +{ + struct rtc_ops *ops = rtc_get_ops(dev); + + assert(ops); + if (!ops->read8) + return -ENOSYS; + return ops->read8(dev, reg); +} + +int rtc_write8(struct udevice *dev, unsigned int reg, int val) +{ + struct rtc_ops *ops = rtc_get_ops(dev); + + assert(ops); + if (!ops->write8) + return -ENOSYS; + return ops->write8(dev, reg, val); +} + +int rtc_read32(struct udevice *dev, unsigned int reg, u32 *valuep) +{ + u32 value = 0; + int ret; + int i; + + for (i = 0; i < sizeof(value); i++) { + ret = rtc_read8(dev, reg + i); + if (ret) + return ret; + value |= ret << (i << 3); + } + + *valuep = value; + return 0; +} + +int rtc_write32(struct udevice *dev, unsigned int reg, u32 value) +{ + int i, ret; + + for (i = 0; i < sizeof(value); i++) { + ret = rtc_write8(dev, reg + i, (value >> (i << 3)) & 0xff); + if (ret) + return ret; + } + + return 0; +} + +UCLASS_DRIVER(rtc) = { + .name = "rtc", + .id = UCLASS_RTC, +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index fddfd35..92a2e4f 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -45,6 +45,7 @@ enum uclass_id { UCLASS_USB_HUB, /* USB hub */ UCLASS_USB_DEV_GENERIC, /* USB generic device */ UCLASS_MASS_STORAGE, /* Mass storage device */ + UCLASS_RTC, /* Real time clock device */
UCLASS_COUNT, UCLASS_INVALID = -1, diff --git a/include/rtc.h b/include/rtc.h index 2566c83..bd8621d 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -17,6 +17,137 @@ #include <bcd.h> #include <rtc_def.h>
+#ifdef CONFIG_DM_RTC + +struct rtc_ops { + /** + * get() - get the current time + * + * Returns the current time read from the RTC device. The driver + * is responsible for setting up every field in the structure. + * + * @dev: Device to read from + * @time: Place to put the time that is read + */ + int (*get)(struct udevice *dev, struct rtc_time *time); + + /** + * set() - set the current time + * + * Sets the time in the RTC device. The driver can expect every + * field to be set correctly. + * + * @dev: Device to read from + * @time: Time to write + */ + int (*set)(struct udevice *dev, const struct rtc_time *time); + + /** + * reset() - reset the RTC to a known-good state + * + * This function resets the RTC to a known-good state. The time may + * be unset by this method, so should be set after this method is + * called. + * + * @dev: Device to read from + * @return 0 if OK, -ve on error + */ + int (*reset)(struct udevice *dev); + + /** + * read8() - Read an 8-bit register + * + * @dev: Device to read from + * @reg: Register to read + * @return value read, or -ve on error + */ + int (*read8)(struct udevice *dev, unsigned int reg); + + /** + * write8() - Write an 8-bit register + * + * @dev: Device to write to + * @reg: Register to write + * @value: Value to write + * @return 0 if OK, -ve on error + */ + int (*write8)(struct udevice *dev, unsigned int reg, int val); +}; + +/* Access the operations for an RTC device */ +#define rtc_get_ops(dev) ((struct rtc_ops *)(dev)->driver->ops) + +/** + * dm_rtc_get() - Read the time from an RTC + * + * @dev: Device to read from + * @time: Place to put the current time + * @return 0 if OK, -ve on error + */ +int dm_rtc_get(struct udevice *dev, struct rtc_time *time); + +/** + * dm_rtc_put() - Write a time to an RTC + * + * @dev: Device to read from + * @time: Time to write into the RTC + * @return 0 if OK, -ve on error + */ +int dm_rtc_set(struct udevice *dev, struct rtc_time *time); + +/** + * dm_rtc_reset() - reset the RTC to a known-good state + * + * If the RTC appears to be broken (e.g. it is not counting up in seconds) + * it may need to be reset to a known good state. This function achieves this. + * After resetting the RTC the time should then be set to a known value by + * the caller. + * + * @dev: Device to read from + * @return 0 if OK, -ve on error + */ +int dm_rtc_reset(struct udevice *dev); + +/** + * rtc_read8() - Read an 8-bit register + * + * @dev: Device to read from + * @reg: Register to read + * @return value read, or -ve on error + */ +int rtc_read8(struct udevice *dev, unsigned int reg); + +/** + * rtc_write8() - Write an 8-bit register + * + * @dev: Device to write to + * @reg: Register to write + * @value: Value to write + * @return 0 if OK, -ve on error + */ +int rtc_write8(struct udevice *dev, unsigned int reg, int val); + +/** + * rtc_read32() - Read a 32-bit value from the RTC + * + * @dev: Device to read from + * @reg: Offset to start reading from + * @valuep: Place to put the value that is read + * @return 0 if OK, -ve on error + */ +int rtc_read32(struct udevice *dev, unsigned int reg, u32 *valuep); + +/** + * rtc_write32() - Write a 32-bit value to the RTC + * + * @dev: Device to write to + * @reg: Register to start writing to + * @value: Value to write + * @return 0 if OK, -ve on error + */ +int rtc_write32(struct udevice *dev, unsigned int reg, u32 value); + +#else int rtc_get (struct rtc_time *); int rtc_set (struct rtc_time *); void rtc_reset (void); @@ -57,6 +188,7 @@ void rtc_write32(int reg, u32 value); * rtc_init() - Set up the real time clock ready for use */ void rtc_init(void); +#endif
/** * rtc_calc_weekday() - Work out the weekday from a time

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Add a uclass for real-time clocks which support getting the current time, setting it and resetting the chip to a known-working state. Some RTCs have additional registers which can be used to store settings, so also provide an interface to these.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/rtc/Kconfig | 8 +++ drivers/rtc/Makefile | 2 + drivers/rtc/rtc-uclass.c | 96 ++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/rtc.h | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 239 insertions(+) create mode 100644 drivers/rtc/rtc-uclass.c
Applied to u-boot-dm.

Add a sandbox I2C emulation device which emulates a real-time clock. The clock works off an offset from the current system time, and supports setting and getting the clock, as well as access to byte-width regisers in the RTC. It does not support changing the system time.
This device can be used for testing the 'date' command on sandbox, as well as the RTC uclass.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/sandbox/include/asm/rtc.h | 28 +++++ arch/sandbox/include/asm/test.h | 21 ++++ drivers/rtc/Makefile | 1 + drivers/rtc/i2c_rtc_emul.c | 236 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 286 insertions(+) create mode 100644 arch/sandbox/include/asm/rtc.h create mode 100644 drivers/rtc/i2c_rtc_emul.c
diff --git a/arch/sandbox/include/asm/rtc.h b/arch/sandbox/include/asm/rtc.h new file mode 100644 index 0000000..5ed4584 --- /dev/null +++ b/arch/sandbox/include/asm/rtc.h @@ -0,0 +1,28 @@ +/* + * Simulate an I2C real time clock + * + * Copyright (c) 2015 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __asm_rtc_h +#define __asm_rtc_h + +/* Register numbers in the sandbox RTC */ +enum { + REG_SEC = 5, + REG_MIN, + REG_HOUR, + REG_MDAY, + REG_MON, + REG_YEAR, + REG_WDAY, + + REG_RESET = 0x20, + + REG_COUNT = 0x80, +}; + +#endif diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index d769780..df56d87 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -38,4 +38,25 @@ void sandbox_i2c_eeprom_set_test_mode(struct udevice *dev,
void sandbox_i2c_eeprom_set_offset_len(struct udevice *dev, int offset_len);
+/** + * sandbox_i2c_rtc_set_offset() - set the time offset from system/base time + * + * @dev: RTC device to adjust + * @use_system_time: true to use system time, false to use @base_time + * @offset: RTC offset from current system/base time (-1 for no + * change) + * @return old value of RTC offset + */ +long sandbox_i2c_rtc_set_offset(struct udevice *dev, bool use_system_time, + int offset); + +/** + * sandbox_i2c_rtc_get_set_base_time() - get and set the base time + * + * @dev: RTC device to adjust + * @base_time: New base system time (set to -1 for no change) + * @return old base time + */ +long sandbox_i2c_rtc_get_set_base_time(struct udevice *dev, long base_time); + #endif diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 61373b6..aeb705a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_RTC_DS164x) += ds164x.o obj-$(CONFIG_RTC_DS174x) += ds174x.o obj-$(CONFIG_RTC_DS3231) += ds3231.o obj-$(CONFIG_RTC_FTRTC010) += ftrtc010.o +obj-$(CONFIG_SANDBOX) += i2c_rtc_emul.o obj-$(CONFIG_RTC_IMXDI) += imxdi.o obj-$(CONFIG_RTC_ISL1208) += isl1208.o obj-$(CONFIG_RTC_M41T11) += m41t11.o diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c new file mode 100644 index 0000000..20827fd --- /dev/null +++ b/drivers/rtc/i2c_rtc_emul.c @@ -0,0 +1,236 @@ +/* + * Simulate an I2C real time clock + * + * Copyright (c) 2015 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * This is a test driver. It starts off with the current time of the machine, + * but also supports setting the time, using an offset from the current + * clock. This driver is only intended for testing, not accurate + * time-keeping. It does not change the system time. + */ + +#include <common.h> +#include <dm.h> +#include <fdtdec.h> +#include <i2c.h> +#include <os.h> +#include <rtc.h> +#include <asm/rtc.h> +#include <asm/test.h> + +#ifdef DEBUG +#define debug_buffer print_buffer +#else +#define debug_buffer(x, ...) +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/** + * struct sandbox_i2c_rtc_plat_data - platform data for the RTC + * + * @base_time: Base system time when RTC device was bound + * @offset: RTC offset from current system time + * @use_system_time: true to use system time, false to use @base_time + * @reg: Register values + */ +struct sandbox_i2c_rtc_plat_data { + long base_time; + long offset; + bool use_system_time; + u8 reg[REG_COUNT]; +}; + +struct sandbox_i2c_rtc { + unsigned int offset_secs; +}; + +long sandbox_i2c_rtc_set_offset(struct udevice *dev, bool use_system_time, + int offset) +{ + struct sandbox_i2c_rtc_plat_data *plat = dev_get_platdata(dev); + long old_offset; + + old_offset = plat->offset; + plat->use_system_time = use_system_time; + if (offset != -1) + plat->offset = offset; + + return old_offset; +} + +long sandbox_i2c_rtc_get_set_base_time(struct udevice *dev, long base_time) +{ + struct sandbox_i2c_rtc_plat_data *plat = dev_get_platdata(dev); + long old_base_time; + + old_base_time = plat->base_time; + if (base_time != -1) + plat->base_time = base_time; + + return old_base_time; +} + +static void reset_time(struct udevice *dev) +{ + struct sandbox_i2c_rtc_plat_data *plat = dev_get_platdata(dev); + struct rtc_time now; + + os_localtime(&now); + plat->base_time = rtc_mktime(&now); + plat->offset = 0; + plat->use_system_time = true; +} + +static int sandbox_i2c_rtc_get(struct udevice *dev, struct rtc_time *time) +{ + struct sandbox_i2c_rtc_plat_data *plat = dev_get_platdata(dev); + struct rtc_time tm_now; + long now; + + if (plat->use_system_time) { + os_localtime(&tm_now); + now = rtc_mktime(&tm_now); + } else { + now = plat->base_time; + } + + return rtc_to_tm(now + plat->offset, time); +} + +static int sandbox_i2c_rtc_set(struct udevice *dev, const struct rtc_time *time) +{ + struct sandbox_i2c_rtc_plat_data *plat = dev_get_platdata(dev); + struct rtc_time tm_now; + long now; + + if (plat->use_system_time) { + os_localtime(&tm_now); + now = rtc_mktime(&tm_now); + } else { + now = plat->base_time; + } + plat->offset = rtc_mktime(time) - now; + + return 0; +} + +/* Update the current time in the registers */ +static int sandbox_i2c_rtc_prepare_read(struct udevice *emul) +{ + struct sandbox_i2c_rtc_plat_data *plat = dev_get_platdata(emul); + struct rtc_time time; + int ret; + + ret = sandbox_i2c_rtc_get(emul, &time); + if (ret) + return ret; + + plat->reg[REG_SEC] = time.tm_sec; + plat->reg[REG_MIN] = time.tm_min; + plat->reg[REG_HOUR] = time.tm_hour; + plat->reg[REG_MDAY] = time.tm_mday; + plat->reg[REG_MON] = time.tm_mon; + plat->reg[REG_YEAR] = time.tm_year - 1900; + plat->reg[REG_WDAY] = time.tm_wday; + + return 0; +} + +static int sandbox_i2c_rtc_complete_write(struct udevice *emul) +{ + struct sandbox_i2c_rtc_plat_data *plat = dev_get_platdata(emul); + struct rtc_time time; + int ret; + + time.tm_sec = plat->reg[REG_SEC]; + time.tm_min = plat->reg[REG_MIN]; + time.tm_hour = plat->reg[REG_HOUR]; + time.tm_mday = plat->reg[REG_MDAY]; + time.tm_mon = plat->reg[REG_MON]; + time.tm_year = plat->reg[REG_YEAR] + 1900; + time.tm_wday = plat->reg[REG_WDAY]; + + ret = sandbox_i2c_rtc_set(emul, &time); + if (ret) + return ret; + + return 0; +} + +static int sandbox_i2c_rtc_xfer(struct udevice *emul, struct i2c_msg *msg, + int nmsgs) +{ + struct sandbox_i2c_rtc_plat_data *plat = dev_get_platdata(emul); + uint offset = 0; + int ret; + + debug("\n%s\n", __func__); + ret = sandbox_i2c_rtc_prepare_read(emul); + if (ret) + return ret; + for (; nmsgs > 0; nmsgs--, msg++) { + int len; + u8 *ptr; + + len = msg->len; + debug(" %s: msg->len=%d", + msg->flags & I2C_M_RD ? "read" : "write", + msg->len); + if (msg->flags & I2C_M_RD) { + debug(", offset %x, len %x: ", offset, len); + + /* Read the register */ + memcpy(msg->buf, plat->reg + offset, len); + memset(msg->buf + len, '\xff', msg->len - len); + debug_buffer(0, msg->buf, 1, msg->len, 0); + } else if (len >= 1) { + ptr = msg->buf; + offset = *ptr++ & (REG_COUNT - 1); + len--; + debug(", set offset %x: ", offset); + debug_buffer(0, msg->buf, 1, msg->len, 0); + + /* Write the register */ + memcpy(plat->reg + offset, ptr, len); + if (offset == REG_RESET) + reset_time(emul); + } + } + ret = sandbox_i2c_rtc_complete_write(emul); + if (ret) + return ret; + + return 0; +} + +struct dm_i2c_ops sandbox_i2c_rtc_emul_ops = { + .xfer = sandbox_i2c_rtc_xfer, +}; + +static int sandbox_i2c_rtc_bind(struct udevice *dev) +{ + reset_time(dev); + + return 0; +} + +static const struct udevice_id sandbox_i2c_rtc_ids[] = { + { .compatible = "sandbox,i2c-rtc" }, + { } +}; + +U_BOOT_DRIVER(sandbox_i2c_rtc_emul) = { + .name = "sandbox_i2c_rtc_emul", + .id = UCLASS_I2C_EMUL, + .of_match = sandbox_i2c_rtc_ids, + .bind = sandbox_i2c_rtc_bind, + .priv_auto_alloc_size = sizeof(struct sandbox_i2c_rtc), + .platdata_auto_alloc_size = sizeof(struct sandbox_i2c_rtc_plat_data), + .ops = &sandbox_i2c_rtc_emul_ops, +};

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Add a sandbox I2C emulation device which emulates a real-time clock. The clock works off an offset from the current system time, and supports setting and getting the clock, as well as access to byte-width regisers in the RTC. It does not support changing the system time.
This device can be used for testing the 'date' command on sandbox, as well as the RTC uclass.
Signed-off-by: Simon Glass sjg@chromium.org
arch/sandbox/include/asm/rtc.h | 28 +++++ arch/sandbox/include/asm/test.h | 21 ++++ drivers/rtc/Makefile | 1 + drivers/rtc/i2c_rtc_emul.c | 236 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 286 insertions(+) create mode 100644 arch/sandbox/include/asm/rtc.h create mode 100644 drivers/rtc/i2c_rtc_emul.c
Applied to u-boot-dm.

Add a driver which communicates with the sandbox I2C emulation RTC device and permits it to be used in U-Boot. This driver is very simple - it just reads and writes selected I2C registers in the device.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/rtc/Makefile | 3 ++ drivers/rtc/sandbox_rtc.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 drivers/rtc/sandbox_rtc.c
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index aeb705a..9077bb3 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -52,4 +52,7 @@ obj-$(CONFIG_RTC_RTC4543) += rtc4543.o obj-$(CONFIG_RTC_RV3029) += rv3029.o obj-$(CONFIG_RTC_RX8025) += rx8025.o obj-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o +ifdef CONFIG_DM_RTC +obj-$(CONFIG_SANDBOX) += sandbox_rtc.o +endif obj-$(CONFIG_RTC_X1205) += x1205.o diff --git a/drivers/rtc/sandbox_rtc.c b/drivers/rtc/sandbox_rtc.c new file mode 100644 index 0000000..f292fbe --- /dev/null +++ b/drivers/rtc/sandbox_rtc.c @@ -0,0 +1,106 @@ +/* + * (C) Copyright 2015 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <i2c.h> +#include <rtc.h> +#include <asm/rtc.h> + +#define REG_COUNT 0x80 + +static int sandbox_rtc_get(struct udevice *dev, struct rtc_time *time) +{ + time->tm_sec = dm_i2c_reg_read(dev, REG_SEC); + if (time->tm_sec < 0) + return time->tm_sec; + time->tm_min = dm_i2c_reg_read(dev, REG_MIN); + if (time->tm_min < 0) + return time->tm_min; + time->tm_hour = dm_i2c_reg_read(dev, REG_HOUR); + if (time->tm_hour < 0) + return time->tm_hour; + time->tm_mday = dm_i2c_reg_read(dev, REG_MDAY); + if (time->tm_mday < 0) + return time->tm_mday; + time->tm_mon = dm_i2c_reg_read(dev, REG_MON); + if (time->tm_mon < 0) + return time->tm_mon; + time->tm_year = dm_i2c_reg_read(dev, REG_YEAR); + if (time->tm_year < 0) + return time->tm_year; + time->tm_year += 1900; + time->tm_wday = dm_i2c_reg_read(dev, REG_WDAY); + if (time->tm_wday < 0) + return time->tm_wday; + + return 0; +} + +static int sandbox_rtc_set(struct udevice *dev, const struct rtc_time *time) +{ + int ret; + + ret = dm_i2c_reg_write(dev, REG_SEC, time->tm_sec); + if (ret < 0) + return ret; + ret = dm_i2c_reg_write(dev, REG_MIN, time->tm_min); + if (ret < 0) + return ret; + ret = dm_i2c_reg_write(dev, REG_HOUR, time->tm_hour); + if (ret < 0) + return ret; + ret = dm_i2c_reg_write(dev, REG_MDAY, time->tm_mday); + if (ret < 0) + return ret; + ret = dm_i2c_reg_write(dev, REG_MON, time->tm_mon); + if (ret < 0) + return ret; + ret = dm_i2c_reg_write(dev, REG_YEAR, time->tm_year - 1900); + if (ret < 0) + return ret; + ret = dm_i2c_reg_write(dev, REG_WDAY, time->tm_wday); + if (ret < 0) + return ret; + + return 0; +} + +static int sandbox_rtc_reset(struct udevice *dev) +{ + return dm_i2c_reg_write(dev, REG_RESET, 0); +} + +static int sandbox_rtc_read8(struct udevice *dev, unsigned int reg) +{ + return dm_i2c_reg_read(dev, reg); +} + +static int sandbox_rtc_write8(struct udevice *dev, unsigned int reg, int val) +{ + return dm_i2c_reg_write(dev, reg, val); +} + +static const struct rtc_ops sandbox_rtc_ops = { + .get = sandbox_rtc_get, + .set = sandbox_rtc_set, + .reset = sandbox_rtc_reset, + .read8 = sandbox_rtc_read8, + .write8 = sandbox_rtc_write8, +}; + +static const struct udevice_id sandbox_rtc_ids[] = { + { .compatible = "sandbox-rtc" }, + { } +}; + +U_BOOT_DRIVER(rtc_sandbox) = { + .name = "rtc-sandbox", + .id = UCLASS_RTC, + .of_match = sandbox_rtc_ids, + .ops = &sandbox_rtc_ops, +};

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Add a driver which communicates with the sandbox I2C emulation RTC device and permits it to be used in U-Boot. This driver is very simple - it just reads and writes selected I2C registers in the device.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/rtc/Makefile | 3 ++ drivers/rtc/sandbox_rtc.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 drivers/rtc/sandbox_rtc.c
Applied to u-boot-dm.

Adjust this command so that it supports using driver model for I2C, i.e. CONFIG_DM_I2C. This will permit it to be used in sandbox also.
Signed-off-by: Simon Glass sjg@chromium.org ---
common/cmd_date.c | 53 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 14 deletions(-)
diff --git a/common/cmd_date.c b/common/cmd_date.c index 3b7ac3e..d7690a0 100644 --- a/common/cmd_date.c +++ b/common/cmd_date.c @@ -10,6 +10,7 @@ */ #include <common.h> #include <command.h> +#include <dm.h> #include <rtc.h> #include <i2c.h>
@@ -31,10 +32,18 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct rtc_time tm; int rcode = 0; - int old_bus; + int old_bus __maybe_unused;
/* switch to correct I2C bus */ -#ifdef CONFIG_SYS_I2C +#ifdef CONFIG_DM_I2C + struct udevice *dev; + + rcode = uclass_get_device(UCLASS_RTC, 0, &dev); + if (rcode) { + printf("Cannot find RTC: err=%d\n", rcode); + return CMD_RET_FAILURE; + } +#elif defined(CONFIG_SYS_I2C) old_bus = i2c_get_bus_num(); i2c_set_bus_num(CONFIG_SYS_RTC_BUS_NUM); #else @@ -46,29 +55,45 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) case 2: /* set date & time */ if (strcmp(argv[1],"reset") == 0) { puts ("Reset RTC...\n"); - rtc_reset (); +#ifdef CONFIG_DM_I2C + rcode = dm_rtc_reset(dev); +#else + rtc_reset(); +#endif } else { /* initialize tm with current time */ - rcode = rtc_get (&tm); - - if(!rcode) { +#ifdef CONFIG_DM_I2C + rcode = dm_rtc_get(dev, &tm); +#else + rcode = rtc_get(&tm); +#endif + if (!rcode) { /* insert new date & time */ - if (mk_date (argv[1], &tm) != 0) { + if (mk_date(argv[1], &tm) != 0) { puts ("## Bad date format\n"); break; } /* and write to RTC */ - rcode = rtc_set (&tm); - if(rcode) - puts("## Set date failed\n"); +#ifdef CONFIG_DM_I2C + rcode = dm_rtc_set(dev, &tm); +#else + rcode = rtc_set(&tm); +#endif + if (rcode) { + printf("## Set date failed: err=%d\n", + rcode); + } } else { puts("## Get date failed\n"); } } /* FALL TROUGH */ case 1: /* get date & time */ - rcode = rtc_get (&tm); - +#ifdef CONFIG_DM_I2C + rcode = dm_rtc_get(dev, &tm); +#else + rcode = rtc_get(&tm); +#endif if (rcode) { puts("## Get date failed\n"); break; @@ -88,11 +113,11 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* switch back to original I2C bus */ #ifdef CONFIG_SYS_I2C i2c_set_bus_num(old_bus); -#else +#elif !defined(CONFIG_DM_I2C) I2C_SET_BUS(old_bus); #endif
- return rcode; + return rcode ? CMD_RET_FAILURE : 0; }
/*

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Adjust this command so that it supports using driver model for I2C, i.e. CONFIG_DM_I2C. This will permit it to be used in sandbox also.
Signed-off-by: Simon Glass sjg@chromium.org
common/cmd_date.c | 53 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 14 deletions(-)
Applied to u-boot-dm.

When setting the date, support driver model RTC also.
Signed-off-by: Simon Glass sjg@chromium.org ---
net/sntp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/net/sntp.c b/net/sntp.c index d7b9e55..9c8ee34 100644 --- a/net/sntp.c +++ b/net/sntp.c @@ -7,6 +7,7 @@
#include <common.h> #include <command.h> +#include <dm.h> #include <net.h> #include <rtc.h>
@@ -70,7 +71,18 @@ static void sntp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
rtc_to_tm(ntohl(seconds) - 2208988800UL + net_ntp_time_offset, &tm); #if defined(CONFIG_CMD_DATE) +# ifdef CONFIG_DM_RTC + struct udevice *dev; + int ret; + + ret = uclass_get_device(UCLASS_RTC, 0, &dev); + if (ret) + printf("SNTP: cannot find RTC: err=%d\n", ret); + else + dm_rtc_set(dev, &tm); +# else rtc_set(&tm); +# endif #endif printf("Date: %4d-%02d-%02d Time: %2d:%02d:%02d\n", tm.tm_year, tm.tm_mon, tm.tm_mday,

Hi Simon,
On Mon, Apr 20, 2015 at 1:37 PM, Simon Glass sjg@chromium.org wrote:
When setting the date, support driver model RTC also.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Joe Hershberger joe.hershberger@ni.com

On 20 April 2015 at 12:43, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Simon,
On Mon, Apr 20, 2015 at 1:37 PM, Simon Glass sjg@chromium.org wrote:
When setting the date, support driver model RTC also.
Signed-off-by: Simon Glass sjg@chromium.org
Acked-by: Joe Hershberger joe.hershberger@ni.com
Applied to u-boot-dm.

Add an emulated RTC device for sandbox, so that the 'date' command can be used.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/sandbox/dts/sandbox.dts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts index efa2097..82d186e 100644 --- a/arch/sandbox/dts/sandbox.dts +++ b/arch/sandbox/dts/sandbox.dts @@ -8,7 +8,9 @@
aliases { eth5 = "/eth@90000000"; + i2c0 = &i2c_0; pci0 = &pci; + rtc0 = &rtc_0; };
chosen { @@ -90,7 +92,7 @@ num-gpios = <10>; };
- i2c@0 { + i2c_0: i2c@0 { #address-cells = <1>; #size-cells = <0>; reg = <0 0>; @@ -105,6 +107,14 @@ sandbox,size = <128>; }; }; + + rtc_0: rtc@43 { + reg = <0x43>; + compatible = "sandbox-rtc"; + emul { + compatible = "sandbox,i2c-rtc"; + }; + }; };
spi@0 {

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Add an emulated RTC device for sandbox, so that the 'date' command can be used.
Signed-off-by: Simon Glass sjg@chromium.org
arch/sandbox/dts/sandbox.dts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
Applied to u-boot-dm.

Enable real-time-clock support in sandbox.
Signed-off-by: Simon Glass sjg@chromium.org ---
configs/sandbox_defconfig | 1 + drivers/rtc/Makefile | 2 -- include/configs/sandbox.h | 1 + 3 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 5de7fbe..759f53a 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -26,3 +26,4 @@ CONFIG_TPM_TIS_SANDBOX=y CONFIG_SOUND=y CONFIG_CMD_SOUND=y CONFIG_SOUND_SANDBOX=y +CONFIG_DM_RTC=y diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 9077bb3..3092de1 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -52,7 +52,5 @@ obj-$(CONFIG_RTC_RTC4543) += rtc4543.o obj-$(CONFIG_RTC_RV3029) += rv3029.o obj-$(CONFIG_RTC_RX8025) += rx8025.o obj-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o -ifdef CONFIG_DM_RTC obj-$(CONFIG_SANDBOX) += sandbox_rtc.o -endif obj-$(CONFIG_RTC_X1205) += x1205.o diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 0a36719..a5f245d 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -192,5 +192,6 @@
#define CONFIG_CMD_LZMADEC #define CONFIG_CMD_USB +#define CONFIG_CMD_DATE
#endif

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Enable real-time-clock support in sandbox.
Signed-off-by: Simon Glass sjg@chromium.org
configs/sandbox_defconfig | 1 + drivers/rtc/Makefile | 2 -- include/configs/sandbox.h | 1 + 3 files changed, 2 insertions(+), 2 deletions(-)
Applied to u-boot-dm.

Sort these aliases to avoid confusion as to what is present.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/dm/test.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/test/dm/test.dts b/test/dm/test.dts index d0c40be..dd6d0ac 100644 --- a/test/dm/test.dts +++ b/test/dm/test.dts @@ -8,18 +8,18 @@
aliases { console = &uart0; + eth0 = "/eth@10002000"; + eth5 = ð_5; i2c0 = "/i2c@0"; - spi0 = "/spi@0"; pci0 = &pci; - testfdt6 = "/e-test"; + spi0 = "/spi@0"; testbus3 = "/some-bus"; testfdt0 = "/some-bus/c-test@0"; testfdt1 = "/some-bus/c-test@1"; testfdt3 = "/b-test"; testfdt5 = "/some-bus/c-test@5"; + testfdt6 = "/e-test"; testfdt8 = "/a-test"; - eth0 = "/eth@10002000"; - eth5 = ð_5; usb0 = &usb_0; usb1 = &usb_1; usb2 = &usb_2;

Hi Simon,
On Mon, Apr 20, 2015 at 1:37 PM, Simon Glass sjg@chromium.org wrote:
Sort these aliases to avoid confusion as to what is present.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Joe Hershberger joe.hershberger@ni.com

On 21 April 2015 at 09:32, Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Simon,
On Mon, Apr 20, 2015 at 1:37 PM, Simon Glass sjg@chromium.org wrote:
Sort these aliases to avoid confusion as to what is present.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Joe Hershberger joe.hershberger@ni.com
Applied to u-boot-dm.

Add some simple tests to verify that the RTC uclass works correctly in U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org ---
test/dm/Makefile | 1 + test/dm/rtc.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/dm/test.dts | 18 ++++++ 3 files changed, 194 insertions(+) create mode 100644 test/dm/rtc.c
diff --git a/test/dm/Makefile b/test/dm/Makefile index fd9e29f..a0cc2c6 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_DM_ETH) += eth.o obj-$(CONFIG_DM_GPIO) += gpio.o obj-$(CONFIG_DM_I2C) += i2c.o obj-$(CONFIG_DM_PCI) += pci.o +obj-$(CONFIG_DM_RTC) += rtc.o obj-$(CONFIG_DM_SPI_FLASH) += sf.o obj-$(CONFIG_DM_SPI) += spi.o obj-$(CONFIG_DM_USB) += usb.o diff --git a/test/dm/rtc.c b/test/dm/rtc.c new file mode 100644 index 0000000..9397cf7 --- /dev/null +++ b/test/dm/rtc.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2015 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <dm.h> +#include <rtc.h> +#include <asm/io.h> +#include <dm/test.h> +#include <dm/ut.h> +#include <asm/test.h> + +/* Simple RTC sanity check */ +static int dm_test_rtc_base(struct dm_test_state *dms) +{ + struct udevice *dev; + + ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_RTC, 2, &dev)); + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev)); + + return 0; +} +DM_TEST(dm_test_rtc_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +static void show_time(const char *msg, struct rtc_time *time) +{ + printf("%s: %02d/%02d/%04d %02d:%02d:%02d\n", msg, + time->tm_mday, time->tm_mon, time->tm_year, + time->tm_hour, time->tm_min, time->tm_sec); +} + +static int cmp_times(struct rtc_time *expect, struct rtc_time *time, bool show) +{ + bool same; + + same = expect->tm_sec == time->tm_sec; + same &= expect->tm_min == time->tm_min; + same &= expect->tm_hour == time->tm_hour; + same &= expect->tm_mday == time->tm_mday; + same &= expect->tm_mon == time->tm_mon; + same &= expect->tm_year == time->tm_year; + if (!same && show) { + show_time("expected", expect); + show_time("actual", time); + } + + return same ? 0 : -EINVAL; +} + +/* Set and get the time */ +static int dm_test_rtc_set_get(struct dm_test_state *dms) +{ + struct rtc_time now, time, cmp; + struct udevice *dev, *emul; + long offset, old_offset, old_base_time; + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + ut_assertok(dm_rtc_get(dev, &now)); + + ut_assertok(device_find_first_child(dev, &emul)); + ut_assert(emul != NULL); + + /* Tell the RTC to go into manual mode */ + old_offset = sandbox_i2c_rtc_set_offset(emul, false, 0); + old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1); + + memset(&time, '\0', sizeof(time)); + time.tm_mday = 25; + time.tm_mon = 8; + time.tm_year = 2004; + time.tm_sec = 0; + time.tm_min = 18; + time.tm_hour = 18; + ut_assertok(dm_rtc_set(dev, &time)); + + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_assertok(cmp_times(&time, &cmp, true)); + + /* Increment by 1 second */ + offset = sandbox_i2c_rtc_set_offset(emul, false, 0); + sandbox_i2c_rtc_set_offset(emul, false, offset + 1); + + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_asserteq(1, cmp.tm_sec); + + /* Check against original offset */ + sandbox_i2c_rtc_set_offset(emul, false, old_offset); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_assertok(cmp_times(&now, &cmp, true)); + + /* Back to the original offset */ + sandbox_i2c_rtc_set_offset(emul, false, 0); + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + ut_assertok(cmp_times(&now, &cmp, true)); + + /* Increment the base time by 1 emul */ + sandbox_i2c_rtc_get_set_base_time(emul, old_base_time + 1); + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev, &cmp)); + if (now.tm_sec == 59) { + ut_asserteq(0, cmp.tm_sec); + } else { + ut_asserteq(now.tm_sec + 1, cmp.tm_sec); + } + + old_offset = sandbox_i2c_rtc_set_offset(emul, true, 0); + + return 0; +} +DM_TEST(dm_test_rtc_set_get, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Reset the time */ +static int dm_test_rtc_reset(struct dm_test_state *dms) +{ + struct rtc_time now; + struct udevice *dev, *emul; + long old_base_time, base_time; + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + ut_assertok(dm_rtc_get(dev, &now)); + + ut_assertok(device_find_first_child(dev, &emul)); + ut_assert(emul != NULL); + + old_base_time = sandbox_i2c_rtc_get_set_base_time(emul, 0); + + ut_asserteq(0, sandbox_i2c_rtc_get_set_base_time(emul, -1)); + + /* Resetting the RTC should put he base time back to normal */ + ut_assertok(dm_rtc_reset(dev)); + base_time = sandbox_i2c_rtc_get_set_base_time(emul, -1); + ut_asserteq(old_base_time, base_time); + + return 0; +} +DM_TEST(dm_test_rtc_reset, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Check that two RTC devices can be used independently */ +static int dm_test_rtc_dual(struct dm_test_state *dms) +{ + struct rtc_time now1, now2, cmp; + struct udevice *dev1, *dev2; + struct udevice *emul1, *emul2; + long offset; + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev1)); + ut_assertok(dm_rtc_get(dev1, &now1)); + ut_assertok(uclass_get_device(UCLASS_RTC, 1, &dev2)); + ut_assertok(dm_rtc_get(dev2, &now2)); + + ut_assertok(device_find_first_child(dev1, &emul1)); + ut_assert(emul1 != NULL); + ut_assertok(device_find_first_child(dev2, &emul2)); + ut_assert(emul2 != NULL); + + offset = sandbox_i2c_rtc_set_offset(emul1, false, -1); + sandbox_i2c_rtc_set_offset(emul2, false, offset + 1); + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev2, &cmp)); + ut_asserteq(-EINVAL, cmp_times(&now1, &cmp, false)); + + memset(&cmp, '\0', sizeof(cmp)); + ut_assertok(dm_rtc_get(dev1, &cmp)); + ut_assertok(cmp_times(&now1, &cmp, true)); + + return 0; +} +DM_TEST(dm_test_rtc_dual, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); diff --git a/test/dm/test.dts b/test/dm/test.dts index dd6d0ac..0085848 100644 --- a/test/dm/test.dts +++ b/test/dm/test.dts @@ -20,6 +20,8 @@ testfdt5 = "/some-bus/c-test@5"; testfdt6 = "/e-test"; testfdt8 = "/a-test"; + rtc0 = &rtc_0; + rtc1 = &rtc_1; usb0 = &usb_0; usb1 = &usb_1; usb2 = &usb_2; @@ -139,6 +141,22 @@ sandbox,size = <256>; }; }; + + rtc_0: rtc@43 { + reg = <0x43>; + compatible = "sandbox-rtc"; + emul { + compatible = "sandbox,i2c-rtc"; + }; + }; + + rtc_1: rtc@61 { + reg = <0x61>; + compatible = "sandbox-rtc"; + emul { + compatible = "sandbox,i2c-rtc"; + }; + }; };
pci: pci-controller {

On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
Add some simple tests to verify that the RTC uclass works correctly in U-Boot.
Signed-off-by: Simon Glass sjg@chromium.org
test/dm/Makefile | 1 + test/dm/rtc.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/dm/test.dts | 18 ++++++ 3 files changed, 194 insertions(+) create mode 100644 test/dm/rtc.c
Applied to u-boot-dm.

Hi,
On 20 April 2015 at 12:37, Simon Glass sjg@chromium.org wrote:
When driver model is used for I2C, the real-time clock functionality does not work (e.g. the 'date' command gives build errors when CONFIG_DM_I2C is defined). It is possible to work around this by using driver model I2C functions. But what is really needed is an RTC uclass.
This series:
- renames some RTC functions to have an rtc_ prefix
- adds sandbox support for RTC and an emulated I2C RTC device
- adds a driver model RTC uclass and associated tests
- corrects various minor driver model I2C issues that were discovered
With this it should be fairly easy to convert an existing RTC driver to driver model, but this series does not include that as I'm not sure if any of the boards I have include an RTC.
Simon Glass (20): dm: spi: Correct the comment on spi_get_ops() dm: i2c: sandbox: Add debugging to the speed limit dm: i2c: Add functions to read and write a register dm: i2c: Add an explicit test mode to the sandbox I2C driver fdt: Correct warning in fdt_setup_simplefb_node() dm: rtc: Rename gregorian day function dm: rtc: Rename to_tm() to rtc_to_tm() and add error code dm: rtc: Rename mktime() and reduce the number of parameters dm: Remove unnecessary types in bcd.h dm: rtc: Split structure definition into its own file dm: sandbox: Add os_localtime() to obtain the system time dm: rtc: Add a uclass for real-time clocks dm: rtc: sandbox: Add an emulated I2C RTC device dm: rtc: sandbox: Add a driver for the sandbox I2C RTC dm: rtc: Convert 'date' command to support driver model dm: net: rtc: Support using driver model for rtc in sntp dm: sandbox: dts: Add a real-time clock attached to I2C dm: rtc: sandbox: Enable real-time clock support dm: test: dts: Sort the aliases in the test device tree file dm: rtc: Add tests for real-time clocks
Thanks for the various reviews on this series. If there is nothing else, I will pull this in soon.
Regards, Simon

Bonjour Simon,
Le Tue, 28 Apr 2015 20:43:47 -0600, Simon Glass sjg@chromium.org a écrit :
Thanks for the various reviews on this series. If there is nothing else, I will pull this in soon.
Seems ok, apart from a few 'implicit declaration' warnings here that do not seem to have been seen by others:
common/cmd_date.c:65:4: attention : implicit declaration of function ‘rtc_set’ [-Wimplicit-function-declaration]
drivers/rtc/ds1374.c: In function ‘rtc_read’: drivers/rtc/ds1374.c:215:2: attention : implicit declaration of function ‘i2c_reg_read’ [-Wimplicit-function-declaration] drivers/rtc/ds1374.c: In function ‘rtc_write’: drivers/rtc/ds1374.c:222:3: attention : implicit declaration of function ‘i2c_reg_write’ [-Wimplicit-function-declaration]
Regards, Simon
Cordialement, Albert ARIBAUD 3ADEV

Hi Albert,
On 29 April 2015 at 01:09, Albert ARIBAUD albert.aribaud@3adev.fr wrote:
Bonjour Simon,
Le Tue, 28 Apr 2015 20:43:47 -0600, Simon Glass sjg@chromium.org a écrit :
Thanks for the various reviews on this series. If there is nothing else, I will pull this in soon.
Seems ok, apart from a few 'implicit declaration' warnings here that do not seem to have been seen by others:
common/cmd_date.c:65:4: attention : implicit declaration of function ‘rtc_set’ [-Wimplicit-function-declaration]
drivers/rtc/ds1374.c: In function ‘rtc_read’: drivers/rtc/ds1374.c:215:2: attention : implicit declaration of function ‘i2c_reg_read’ [-Wimplicit-function-declaration] drivers/rtc/ds1374.c: In function ‘rtc_write’: drivers/rtc/ds1374.c:222:3: attention : implicit declaration of function ‘i2c_reg_write’ [-Wimplicit-function-declaration]
That's because those functions are not defined in he compatibility layer. Presumably the build fails also?
I'll apply what I have (assuming I still don't see any build errors) and send out a patch for this.
Regards, Simon
participants (5)
-
Albert ARIBAUD
-
Heiko Schocher
-
Jagan Teki
-
Joe Hershberger
-
Simon Glass