Skip to contentSkip to conversation

RTC support for NXP LPC18xx family

PATCH Superseded Joachim Eastwood 3 participants 8 messages May 15, 2015 – May 16, 2015

Subsystems (3)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover RTC support for NXP LPC18xx family

This patch set adds support for the RTC found on many NXP devices including LPC24xx/178x/18xx/43xx. The RTC provides calendar and clock functionality together with periodic tick and alarm interrupt support.

The driver is a rework of an old driver by Kevin Wells. It has been modified to support modern resource allocation, device tree and generally cleaned up.

This version address the comments from Josh Cartwright and Alexandre Belloni.

changes since v1:
- s/lpc2k/lpc24xx for better consistency
- fix Kconfig entry
- drop support for old versions for the ip block

Patch set is based on Linux v4.1-rc1.

Base support for the NXP LPC18xx family can be found here:
http://marc.info/?l=linux-arm-kernel&m=143016894704253&w=2

Joachim Eastwood (2):
rtc: add rtc-lpc24xx driver
doc: dt: add documentation for nxp,lpc1788-rtc

 .../devicetree/bindings/rtc/nxp,lpc1788-rtc.txt    |  21 ++
 drivers/rtc/Kconfig                                |  13 +
 drivers/rtc/Makefile                               |   1 +
 drivers/rtc/rtc-lpc24xx.c                          | 341 +++++++++++++++++++++
 4 files changed, 376 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/nxp,lpc1788-rtc.txt
 create mode 100644 drivers/rtc/rtc-lpc24xx.c
Signature · 1 line
1.8.0
#1 lore raw

PATCH v2 1/2 rtc: add rtc-lpc24xx driver

Add driver for the RTC found on NXP LPC24xx/178x/18xx/43xx devices. The RTC provides calendar and clock functionality together with periodic tick and alarm interrupt support.

---
 drivers/rtc/Kconfig       |  13 ++
 drivers/rtc/Makefile      |   1 +
 drivers/rtc/rtc-lpc24xx.c | 341 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 355 insertions(+)
 create mode 100644 drivers/rtc/rtc-lpc24xx.c
drivers/rtc/Kconfig +13 -0
index 6149ae01e11f..279342e8168b 100644
@@ -1427,6 +1427,19 @@ config RTC_DRV_JZ4740
 	  This driver can also be buillt as a module. If so, the module
 	  will be called rtc-jz4740.
 
+config RTC_DRV_LPC24XX
+	depends on ARCH_LPC18XX || COMPILE_TEST
+	depends on HAS_IOMEM
+	depends on OF
+	tristate "NXP LPC24xx RTC"
+	help
+	  This enables support for the NXP RTC found which can be found on
+	  LPC24xx/178x/18xx/43xx devices.
+
+	  If you have one of the devices above enable this driver to use
+	  the hardware RTC. This driver can also be buillt as a module. If
+	  so, the module will be called rtc-lpc24xx.
+
 config RTC_DRV_LPC32XX
 	depends on ARCH_LPC32XX
 	tristate "NXP LPC32XX RTC"
drivers/rtc/Makefile +1 -0
index c31731c29762..8687a2e13247 100644
@@ -73,6 +73,7 @@ obj-$(CONFIG_RTC_DRV_ISL12022)	+= rtc-isl12022.o
 obj-$(CONFIG_RTC_DRV_ISL12057)	+= rtc-isl12057.o
 obj-$(CONFIG_RTC_DRV_JZ4740)	+= rtc-jz4740.o
 obj-$(CONFIG_RTC_DRV_LP8788)	+= rtc-lp8788.o
+obj-$(CONFIG_RTC_DRV_LPC24XX)	+= rtc-lpc24xx.o
 obj-$(CONFIG_RTC_DRV_LPC32XX)	+= rtc-lpc32xx.o
 obj-$(CONFIG_RTC_DRV_LOONGSON1)	+= rtc-ls1x.o
 obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
drivers/rtc/rtc-lpc24xx.c new file +341 -0

341 lines not on this page · raw message

Signature · 1 line
1.8.0
#2 lore raw

PATCH v2 1/2 rtc: add rtc-lpc24xx driver

Hello again,

Quoted 6 lines · Joachim Eastwood

Add driver for the RTC found on NXP LPC24xx/178x/18xx/43xx devices. The RTC provides calendar and clock functionality together with periodic tick and alarm interrupt support.

---

[..]

drivers/rtc/Kconfig config RTC_DRV_JZ4740 · line 1437

Quoted 13 lines

+++ b/drivers/rtc/Kconfig

drivers/rtc/Kconfig +8 -0
@@ -1427,6 +1427,19 @@ config RTC_DRV_JZ4740
 	  This driver can also be buillt as a module. If so, the module
 	  will be called rtc-jz4740.
 
+config RTC_DRV_LPC24XX
+	depends on ARCH_LPC18XX || COMPILE_TEST
+	depends on HAS_IOMEM
+	depends on OF
+	tristate "NXP LPC24xx RTC"
+	help
+	  This enables support for the NXP RTC found which can be found on
+	  LPC24xx/178x/18xx/43xx devices.

Is this still true?

Quoted 11 lines
drivers/rtc/Kconfig +5 -0
+
+	  If you have one of the devices above enable this driver to use
+	  the hardware RTC. This driver can also be buillt as a module. If
+	  so, the module will be called rtc-lpc24xx.
+
 config RTC_DRV_LPC32XX
 	depends on ARCH_LPC32XX
 	tristate "NXP LPC32XX RTC"
drivers/rtc/Makefile +0 -1
index c31731c29762..8687a2e13247 100644
--- a/drivers/rtc/Makefile

[..]

Quoted 15 lines
drivers/rtc/Makefile +15 -0
+static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+	u32 ct0, ct1, ct2;
+
+	ct0 = rtc_readl(rtc, LPC24XX_CTIME0);
+	ct1 = rtc_readl(rtc, LPC24XX_CTIME1);
+	ct2 = rtc_readl(rtc, LPC24XX_CTIME2);
+
+	tm->tm_sec  = CT0_SECS(ct0);
+	tm->tm_min  = CT0_MINS(ct0);
+	tm->tm_hour = CT0_HOURS(ct0);
+	tm->tm_wday = CT0_DOW(ct0);
+	tm->tm_mon  = CT1_MONTH(ct1);
+	tm->tm_mday = CT1_DOM(ct1);

drivers/rtc/Makefile

Quoted 10 lines
drivers/rtc/Makefile +10 -0
+	tm->tm_year = CT1_YEAR(ct1);
+	tm->tm_yday = CT2_DOY(ct2);
+
+	if (rtc_valid_tm(tm) < 0) {
+		dev_warn(dev, "retrieved date and time is invalid\n");
+		rtc_time64_to_tm(0, tm);
+		lpc24xx_rtc_set_time(dev, tm);
+	}
+
+	return 0;

Forcing the read time to be the epoch on failure seems like a pretty poor way to handle errors, in my opinion.

Why not trickle an error up to the rtc class driver?

Actually, the class driver is already doing a rtc_valid_tm() check, so that shouldn't even be necessary. Just read your time here, and let the upper layer take care of handling an invalid time (and properly propagating an error up the stack).

Josh
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150515/7f3b602d/attachment.sig>

#3 lore raw

PATCH v2 1/2 rtc: add rtc-lpc24xx driver

Quoted 15 lines · Josh Cartwright

Hello again,

Quoted 6 lines · Joachim Eastwood

Add driver for the RTC found on NXP LPC24xx/178x/18xx/43xx devices. The RTC provides calendar and clock functionality together with periodic tick and alarm interrupt support.

---

[..]

Quoted 5 lines

+++ b/drivers/rtc/Kconfig

drivers/rtc/Kconfig +0 -0
@@ -1427,6 +1427,19 @@ config RTC_DRV_JZ4740
        This driver can also be buillt as a module. If so, the module
        will be called rtc-jz4740.
 
Quoted 10 lines

drivers/rtc/Kconfig config RTC_DRV_JZ4740 · line 1437

Quoted 8 lines
drivers/rtc/Kconfig +8 -0
+config RTC_DRV_LPC24XX
+     depends on ARCH_LPC18XX || COMPILE_TEST
+     depends on HAS_IOMEM
+     depends on OF
+     tristate "NXP LPC24xx RTC"
+     help
+       This enables support for the NXP RTC found which can be found on
+       LPC24xx/178x/18xx/43xx devices.

Is this still true?

I guess I should have updated the Kconfig text when I removed the LPC24xx bits.

I'll put something this in the next version:
tristate "NXP LPC178x/18xx/43xx RTC"
...
help
This enables support for the NXP RTC found which can be found on LPC178x/18xx/43xx devices.

Quoted 32 lines
Quoted 11 lines
drivers/rtc/Kconfig +5 -0
+
+       If you have one of the devices above enable this driver to use
+       the hardware RTC. This driver can also be buillt as a module. If
+       so, the module will be called rtc-lpc24xx.
+
 config RTC_DRV_LPC32XX
      depends on ARCH_LPC32XX
      tristate "NXP LPC32XX RTC"
drivers/rtc/Makefile +0 -1
index c31731c29762..8687a2e13247 100644
--- a/drivers/rtc/Makefile

[..]

Quoted 20 lines
drivers/rtc/Makefile +20 -0
+static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+     struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+     u32 ct0, ct1, ct2;
+
+     ct0 = rtc_readl(rtc, LPC24XX_CTIME0);
+     ct1 = rtc_readl(rtc, LPC24XX_CTIME1);
+     ct2 = rtc_readl(rtc, LPC24XX_CTIME2);
+
+     tm->tm_sec  = CT0_SECS(ct0);
+     tm->tm_min  = CT0_MINS(ct0);
+     tm->tm_hour = CT0_HOURS(ct0);
+     tm->tm_wday = CT0_DOW(ct0);
+     tm->tm_mon  = CT1_MONTH(ct1);
+     tm->tm_mday = CT1_DOM(ct1);
+     tm->tm_year = CT1_YEAR(ct1);
+     tm->tm_yday = CT2_DOY(ct2);
+
+     if (rtc_valid_tm(tm) < 0) {
+             dev_warn(dev, "retrieved date and time is invalid\n");
Quoted 8 lines

drivers/rtc/Makefile

Quoted 5 lines
drivers/rtc/Makefile +5 -0
+             rtc_time64_to_tm(0, tm);
+             lpc24xx_rtc_set_time(dev, tm);
+     }
+
+     return 0;

Forcing the read time to be the epoch on failure seems like a pretty poor way to handle errors, in my opinion.

When the device doesn't have battery the CTIME registers contains an invalid value. So if you don't set them to something valid you will get a warning each time you try to read the RTC. To "fix" that problem I set the time at epoch which make the CTIME registers to contain a valid value. Since the value is already useless I think setting it to epoch is an improvement in this case.

I guess it deserves a comment in the driver.

Quoted 1 line

Why not trickle an error up to the rtc class driver?

Because the rtc class will never correct the CTIME register values and will complain each time lpc24xx_rtc_read_time() is called. Of course if a user set the time from user space the register value is also corrected.

Quoted 4 lines

Actually, the class driver is already doing a rtc_valid_tm() check, so that shouldn't even be necessary. Just read your time here, and let the upper layer take care of handling an invalid time (and properly propagating an error up the stack).

Thanks for taking the time to look at the patch again.

regards,
Joachim Eastwood

#4 lore raw

PATCH v2 1/2 rtc: add rtc-lpc24xx driver

Quoted 10 lines · Joachim Eastwood
Quoted 9 lines · Josh Cartwright

Hello again,

Quoted 6 lines · Joachim Eastwood

Add driver for the RTC found on NXP LPC24xx/178x/18xx/43xx devices. The RTC provides calendar and clock functionality together with periodic tick and alarm interrupt support.

---

[..]

Quoted 29 lines
Quoted 20 lines
Quoted 20 lines
drivers/rtc/rtc-lpc24xx.c new file +20 -0
+static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+     struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+     u32 ct0, ct1, ct2;
+
+     ct0 = rtc_readl(rtc, LPC24XX_CTIME0);
+     ct1 = rtc_readl(rtc, LPC24XX_CTIME1);
+     ct2 = rtc_readl(rtc, LPC24XX_CTIME2);
+
+     tm->tm_sec  = CT0_SECS(ct0);
+     tm->tm_min  = CT0_MINS(ct0);
+     tm->tm_hour = CT0_HOURS(ct0);
+     tm->tm_wday = CT0_DOW(ct0);
+     tm->tm_mon  = CT1_MONTH(ct1);
+     tm->tm_mday = CT1_DOM(ct1);
+     tm->tm_year = CT1_YEAR(ct1);
+     tm->tm_yday = CT2_DOY(ct2);
+
+     if (rtc_valid_tm(tm) < 0) {
+             dev_warn(dev, "retrieved date and time is invalid\n");
Quoted 8 lines

drivers/rtc/rtc-lpc24xx.c line 132

Quoted 5 lines
drivers/rtc/rtc-lpc24xx.c new file +5 -0
+             rtc_time64_to_tm(0, tm);
+             lpc24xx_rtc_set_time(dev, tm);
+     }
+
+     return 0;

Forcing the read time to be the epoch on failure seems like a pretty poor way to handle errors, in my opinion.

Quoted 6 lines

When the device doesn't have battery the CTIME registers contains an invalid value. So if you don't set them to something valid you will get a warning each time you try to read the RTC. To "fix" that problem I set the time at epoch which make the CTIME registers to contain a valid value. Since the value is already useless I think setting it to epoch is an improvement in this case.

I see. I think doing this setting in your read_time callback is the wrong place to do this check. I'm thinking a better place for it would be in your driver's probe().

Quoted 1 line

I guess it deserves a comment in the driver.

Yes, I agree.

Josh
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150515/ab41cd33/attachment.sig>

#5 lore raw

PATCH v2 1/2 rtc: add rtc-lpc24xx driver

Quoted 48 lines · Josh Cartwright
Quoted 10 lines · Joachim Eastwood
Quoted 9 lines · Josh Cartwright

Hello again,

Quoted 6 lines · Joachim Eastwood

Add driver for the RTC found on NXP LPC24xx/178x/18xx/43xx devices. The RTC provides calendar and clock functionality together with periodic tick and alarm interrupt support.

---

[..]

Quoted 29 lines
Quoted 20 lines
Quoted 20 lines
drivers/rtc/rtc-lpc24xx.c new file +20 -0
+static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+     struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+     u32 ct0, ct1, ct2;
+
+     ct0 = rtc_readl(rtc, LPC24XX_CTIME0);
+     ct1 = rtc_readl(rtc, LPC24XX_CTIME1);
+     ct2 = rtc_readl(rtc, LPC24XX_CTIME2);
+
+     tm->tm_sec  = CT0_SECS(ct0);
+     tm->tm_min  = CT0_MINS(ct0);
+     tm->tm_hour = CT0_HOURS(ct0);
+     tm->tm_wday = CT0_DOW(ct0);
+     tm->tm_mon  = CT1_MONTH(ct1);
+     tm->tm_mday = CT1_DOM(ct1);
+     tm->tm_year = CT1_YEAR(ct1);
+     tm->tm_yday = CT2_DOY(ct2);
+
+     if (rtc_valid_tm(tm) < 0) {
+             dev_warn(dev, "retrieved date and time is invalid\n");
Quoted 8 lines

drivers/rtc/rtc-lpc24xx.c line 132

Quoted 5 lines
drivers/rtc/rtc-lpc24xx.c new file +5 -0
+             rtc_time64_to_tm(0, tm);
+             lpc24xx_rtc_set_time(dev, tm);
+     }
+
+     return 0;

Forcing the read time to be the epoch on failure seems like a pretty poor way to handle errors, in my opinion.

Quoted 6 lines

When the device doesn't have battery the CTIME registers contains an invalid value. So if you don't set them to something valid you will get a warning each time you try to read the RTC. To "fix" that problem I set the time at epoch which make the CTIME registers to contain a valid value. Since the value is already useless I think setting it to epoch is an improvement in this case.

Quoted 3 lines

I see. I think doing this setting in your read_time callback is the wrong place to do this check. I'm thinking a better place for it would be in your driver's probe().

That is a good idea. I'll move the check to probe instead.

Quoted 3 lines
Quoted 1 line

I guess it deserves a comment in the driver.

Yes, I agree.

I'll add it in the next version.

regards,
Joachim Eastwood

#6 lore raw

PATCH v2 1/2 rtc: add rtc-lpc24xx driver

Quoted 49 lines · Joachim Eastwood
Quoted 48 lines · Josh Cartwright
Quoted 10 lines · Joachim Eastwood
Quoted 9 lines · Josh Cartwright

Hello again,

Quoted 6 lines · Joachim Eastwood

Add driver for the RTC found on NXP LPC24xx/178x/18xx/43xx devices. The RTC provides calendar and clock functionality together with periodic tick and alarm interrupt support.

---

[..]

Quoted 35 lines
Quoted 20 lines
Quoted 20 lines
drivers/rtc/rtc-lpc24xx.c new file +20 -0
+static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+     struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+     u32 ct0, ct1, ct2;
+
+     ct0 = rtc_readl(rtc, LPC24XX_CTIME0);
+     ct1 = rtc_readl(rtc, LPC24XX_CTIME1);
+     ct2 = rtc_readl(rtc, LPC24XX_CTIME2);
+
+     tm->tm_sec  = CT0_SECS(ct0);
+     tm->tm_min  = CT0_MINS(ct0);
+     tm->tm_hour = CT0_HOURS(ct0);
+     tm->tm_wday = CT0_DOW(ct0);
+     tm->tm_mon  = CT1_MONTH(ct1);
+     tm->tm_mday = CT1_DOM(ct1);
+     tm->tm_year = CT1_YEAR(ct1);
+     tm->tm_yday = CT2_DOY(ct2);
+
+     if (rtc_valid_tm(tm) < 0) {
+             dev_warn(dev, "retrieved date and time is invalid\n");
Quoted 8 lines

drivers/rtc/rtc-lpc24xx.c line 132

Quoted 5 lines
drivers/rtc/rtc-lpc24xx.c new file +5 -0
+             rtc_time64_to_tm(0, tm);
+             lpc24xx_rtc_set_time(dev, tm);
+     }
+
+     return 0;

Forcing the read time to be the epoch on failure seems like a pretty poor way to handle errors, in my opinion.

When the device doesn't have battery the CTIME registers contains an invalid value. So if you don't set them to something valid you will get a warning each time you try to read the RTC. To "fix" that problem I set the time at epoch which make the CTIME registers to contain a valid value. Since the value is already useless I think setting it to epoch is an improvement in this case.

Quoted 6 lines
Quoted 3 lines

I see. I think doing this setting in your read_time callback is the wrong place to do this check. I'm thinking a better place for it would be in your driver's probe().

That is a good idea. I'll move the check to probe instead.

Actually, it is never a good idea to set the time to epoch at all because then userspace, will assume that the time is valid. You should return an error until userspace sets the time. You can drop the dev_warn and simply return rtc_valid_tm(tm);

Signature · 3 lines
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
#7 lore raw

PATCH v2 2/2 doc: dt: add documentation for nxp,lpc1788-rtc

In reply to Joachim Eastwood
---
 .../devicetree/bindings/rtc/nxp,lpc1788-rtc.txt     | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/nxp,lpc1788-rtc.txt
Documentation/devicetree/bindings/rtc/nxp,lpc1788-rtc.txt new file +21 -0
new file mode 100644
index 000000000000..ad41a040432c
@@ -0,0 +1,21 @@
+NXP LPC1788 real-time clock
+
+The LPC1788 RTC provides calendar and clock functionality
+together with periodic tick and alarm interrupt support.
+
+Required properties:
+- compatible	: must contain "nxp,lpc1788-rtc"
+- reg		: Specifies base physical address and size of the registers.
+- interrupts	: A single interrupt specifier.
+- clocks	: Must contain entries for rtc and register clock
+- clock-names	: Must contain "rtc" and "reg"
+  See ../clocks/clock-bindings.txt for details.
+
+Example:
+rtc: rtc at 40046000 {
+	compatible = "nxp,lpc1788-rtc";
+	reg = <0x40046000 0x1000>;
+	interrupts = <47>;
+	clocks = <&creg_clk 0>, <&ccu1 CLK_CPU_BUS>;
+	clock-names = "rtc", "reg";
+};
Signature · 1 line
1.8.0