Skip to contentSkip to conversation

add mxc driver for i.MX53 SRTC

PATCH Superseded [email protected] 6 participants 22 messages Dec 5, 2017 – Dec 15, 2017

Subsystems (4)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover add mxc driver for i.MX53 SRTC

From: Patrick Bruenn <[email protected]>

Neither rtc-imxdi, rtc-mxc nor rtc-snvs are compatible with i.MX53.

This is driver enables support for the low power domain SRTC features:
- 32-bit MSB of non-rollover time counter
- 32-bit alarm register

Based on:
http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/drivers/rtc/rtc-mxc_v2.c?h=imx_2.6.35_11.09.01

v2:
- have seperate patches for dt-binding, CONFIG option, imx53.dtsi and driver
- add SPDX-License-Identifier and cleanup copyright notice
- replace __raw_readl/writel() with readl/writel()
- fix PM_SLEEP callbacks
- add CONFIG_RTC_DRV_MXC_V2 to build rtc-mxc_v2.c
- remove misleading or obvious comments and fix style of the remaining
- avoid endless loop while waiting for hw
- implement consistent locking; make spinlock a member of dev struct
- enable clk only for register accesses
- remove all udelay() calls since they are obsolete or redundant (we are already waiting for register flags to change)
- init platform_data before registering irq callback
- let set_time() fail, when 32 bit rtc counter exceeded
- make names more consistent
- cleanup and reorder includes
- cleanup and remove unused defines

To: Alessandro Zummo <[email protected]>
To: Alexandre Belloni <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Mark Rutland <[email protected]> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc: linux-rtc at vger.kernel.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
Cc: devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc: linux-kernel at vger.kernel.org (open list)
Cc: Fabio Estevam <[email protected]>
Cc: Juergen Borleis <[email protected]>
Cc: Noel Vellemans <[email protected]>
Cc: Shawn Guo <[email protected]>
Cc: Sascha Hauer <[email protected]> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc: Russell King <[email protected]> (maintainer:ARM PORT)
Cc: linux-arm-kernel at lists.infradead.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)

Cc Philippe Ombredanne <[email protected]>
Cc Lothar Wa?mann <[email protected]>

Patrick Bruenn (5):
dt-bindings: rtc: add bindings for i.MX53 SRTC
ARM: dts: imx53: add srtc node
rtc: mxc_v2: add driver for i.MX53 SRTC
ARM: imx_v4_v5_defconfig: enable RTC_DRV_MXC_V2
rtc: add mxc driver for i.MX53 SRTC

 .../devicetree/bindings/rtc/rtc-mxc_v2.txt         |  17 +
 arch/arm/boot/dts/imx53.dtsi                       |   4 +-
 arch/arm/configs/imx_v4_v5_defconfig               |   1 +
 drivers/rtc/Kconfig                                |  10 +
 drivers/rtc/Makefile                               |   1 +
 drivers/rtc/rtc-mxc_v2.c                           | 433 +++++++++++++++++++++
 6 files changed, 463 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt
 create mode 100644 drivers/rtc/rtc-mxc_v2.c
Signature · 1 line
2.11.0
#1 lore raw

PATCH v2 1/5 dt-bindings: rtc: add bindings for i.MX53 SRTC

From: Patrick Bruenn <[email protected]>

Document the binding for i.MX53 SRTC implemented by rtc-mxc_v2

---

To: Alessandro Zummo <[email protected]>
To: Alexandre Belloni <[email protected]>

Cc Rob Herring <[email protected]>
Cc Mark Rutland <[email protected]> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-rtc at vger.kernel.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
Cc devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-kernel at vger.kernel.org (open list)
Cc Fabio Estevam <[email protected]>
Cc Juergen Borleis <[email protected]>
Cc Noel Vellemans <[email protected]>
Cc Shawn Guo <[email protected]>
Cc Sascha Hauer <[email protected]> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc Russell King <[email protected]> (maintainer:ARM PORT)
Cc linux-arm-kernel at lists.infradead.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc Philippe Ombredanne <[email protected]>
Cc Lothar Wa?mann <[email protected]>
---
 Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +17 -0
new file mode 100644
index 000000000000..796e7f4995db
@@ -0,0 +1,17 @@
+* i.MX53 Real Time Clock controller
+
+Required properties:
+- compatible: should be: "fsl,imx53-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- clocks: should contain the phandle for the rtc clock
+- interrupts: rtc alarm interrupt
+
+Example:
+
+srtc at 53fa4000 {
+	compatible = "fsl,imx53-rtc";
+	reg = <0x53fa4000 0x4000>;
+	interrupts = <24>;
+	clocks = <&clks IMX5_CLK_SRTC_GATE>;
+};
Signature · 1 line
2.11.0
maintainer
#2 lore raw

Re: [PATCH v2 1/5] dt-bindings: rtc: add bindings for i.MX53 SRTC

Quoted 37 lines · linux-kernel-dev at beckhoff.com

From: Patrick Bruenn <[email protected]>

Document the binding for i.MX53 SRTC implemented by rtc-mxc_v2

---

To: Alessandro Zummo <[email protected]>
To: Alexandre Belloni <[email protected]>

Cc Rob Herring <[email protected]>
Cc Mark Rutland <[email protected]> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-rtc at vger.kernel.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
Cc devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-kernel at vger.kernel.org (open list)
Cc Fabio Estevam <[email protected]>
Cc Juergen Borleis <[email protected]>
Cc Noel Vellemans <[email protected]>
Cc Shawn Guo <[email protected]>
Cc Sascha Hauer <[email protected]> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc Russell King <[email protected]> (maintainer:ARM PORT)
Cc linux-arm-kernel at lists.infradead.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc Philippe Ombredanne <[email protected]>
Cc Lothar Wa?mann <[email protected]>
---
 Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +0 -0
new file mode 100644
index 000000000000..796e7f4995db

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt line 7

Quoted 7 lines
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +7 -0
@@ -0,0 +1,17 @@
+* i.MX53 Real Time Clock controller
+
+Required properties:
+- compatible: should be: "fsl,imx53-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- clocks: should contain the phandle for the rtc clock

Shouldn't there be more than 1 here. From what I remember, the ipg clock and the 32k clock?

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt line 12

Quoted 5 lines
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +5 -0
+- interrupts: rtc alarm interrupt
+
+Example:
+
+srtc at 53fa4000 {

rtc at ...

Quoted 7 lines
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +5 -1
+	compatible = "fsl,imx53-rtc";
+	reg = <0x53fa4000 0x4000>;
+	interrupts = <24>;
+	clocks = <&clks IMX5_CLK_SRTC_GATE>;
+};
--

2.11.0

#3 lore raw

RE: [PATCH v2 1/5] dt-bindings: rtc: add bindings for i.MX53 SRTC

Quoted 14 lines

From: Rob Herring [mailto:robh at kernel.org]
Sent: Mittwoch, 6. Dezember 2017 22:55

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt line 5

Quoted 9 lines · linux-kernel-dev at beckhoff.com

From: Patrick Bruenn <[email protected]>

+++ b/Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +5 -0
@@ -0,0 +1,17 @@
+* i.MX53 Real Time Clock controller
+
+Required properties:
+- compatible: should be: "fsl,imx53-rtc"
+- reg: physical base address of the controller and length of memory

mapped

Quoted 5 lines

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt line 7

Quoted 2 lines
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +2 -0
+  region.
+- clocks: should contain the phandle for the rtc clock

Shouldn't there be more than 1 here. From what I remember, the ipg clock and the 32k clock?

Yes, you are right. But if I am reading the original Freescale driver and the reference manual correctly, the second clock is always active.
Section "72.3.1.1 Clocks" from the reference manual [1] reads:
"SRTC runs on two clock sources, high frequency peripherals clock and low frequency timers clock. The high frequency peripheral IP clock is used by the SRTC peripheral bus interface, control and status registers. The low frequency 32.768 kHz clock is the always-active clock used by the SRTC timers..."

That's why I would only include one clock . Should I change this?

Quoted 9 lines

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt line 12

Quoted 6 lines
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +5 -0
+- interrupts: rtc alarm interrupt
+
+Example:
+
+srtc at 53fa4000 {

rtc at ...

The rtc for which this series adds support is embedded within a function block called "Secure Real Time Clock". This driver doesn't utilize all of the hardware features by now. But maybe someone else wants to extend the functionalities, later. For that possibility I wanted to name the node "srtc". Should I still change this?

I believe you have a much better understanding of what should be done here. I don't want to argue with you, just thought you might not had that information. So if I am wrong just tell me and I will change it without further "complaining".

Thank you for taking the time,
Patrick

[1] https://cache.freescale.com/files/32bit/doc/ref_manual/iMX53RM.pdf

---
Beckhoff Automation GmbH & Co. KG | Managing Director: Dipl. Phys. Hans Beckhoff Registered office: Verl, Germany | Register court: Guetersloh HRA 7075

reviewer
#4 lore raw

Re: [PATCH v2 1/5] dt-bindings: rtc: add bindings for i.MX53 SRTC

Hi Patrick,

Quoted 7 lines · Patrick Br?nn
Quoted 2 lines

rtc at ...

The rtc for which this series adds support is embedded within a function block called "Secure Real Time Clock". This driver doesn't utilize all of the hardware features by now. But maybe someone else wants to extend the functionalities, later. For that possibility I wanted to name the node "srtc". Should I still change this?

Quoted 5 lines

I believe you have a much better understanding of what should be done here. I don't want to argue with you, just thought you might not had that information. So if I am wrong just tell me and I will change it without further "complaining".

From the Devicetree Specification document:

"Generic Names Recommendation

The name of a node should be somewhat generic, reflecting the function of the device and not its precise program-
ming model. If appropriate, the name should be one of the following choices:
...
rtc
"

So better use 'rtc' as suggested by Rob.

#5 lore raw

RE: [PATCH v2 1/5] dt-bindings: rtc: add bindings for i.MX53 SRTC

Quoted 4 lines

From: Fabio Estevam [mailto:festevam at gmail.com]
Sent: Dienstag, 12. Dezember 2017 00:08
Hi Patrick,

Hi Fabio,

Quoted 23 lines
Quoted 3 lines · Patrick Br?nn
Quoted 2 lines

rtc at ...

The rtc for which this series adds support is embedded within a function

block called

Quoted 1 line

"Secure Real Time Clock". This driver doesn't utilize all of the hardware

features by

Quoted 2 lines

now. But maybe someone else wants to extend the functionalities, later. For that possibility I wanted to name the node "srtc". Should I still change

this?

Quoted 2 lines

I believe you have a much better understanding of what should be done

here. I don't

Quoted 1 line

want to argue with you, just thought you might not had that information. So

if I am

Quoted 1 line

wrong just tell me and I will change it without further "complaining".

From the Devicetree Specification document:

"Generic Names Recommendation

Quoted 8 lines

The name of a node should be somewhat generic, reflecting the function of the device and not its precise program-
ming model. If appropriate, the name should be one of the following choices:
...
rtc
"

So better use 'rtc' as suggested by Rob.

Thanks for this clarification. I will wait a few days for more comments on the rest of the driver and then send a v4.

Regards, Patrick
Beckhoff Automation GmbH & Co. KG | Managing Director: Dipl. Phys. Hans Beckhoff Registered office: Verl, Germany | Register court: Guetersloh HRA 7075

maintainer
#6 lore raw

Re: [PATCH v2 1/5] dt-bindings: rtc: add bindings for i.MX53 SRTC

In reply to Patrick Brünn
Quoted 27 lines · Patrick Br?nn
Quoted 14 lines

From: Rob Herring [mailto:robh at kernel.org]
Sent: Mittwoch, 6. Dezember 2017 22:55

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt line 5

Quoted 9 lines · linux-kernel-dev at beckhoff.com

From: Patrick Bruenn <[email protected]>

+++ b/Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +5 -0
@@ -0,0 +1,17 @@
+* i.MX53 Real Time Clock controller
+
+Required properties:
+- compatible: should be: "fsl,imx53-rtc"
+- reg: physical base address of the controller and length of memory

mapped

Quoted 5 lines

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt line 7

Quoted 2 lines
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +2 -0
+  region.
+- clocks: should contain the phandle for the rtc clock

Shouldn't there be more than 1 here. From what I remember, the ipg clock and the 32k clock?

Yes, you are right. But if I am reading the original Freescale driver and the reference manual correctly, the second clock is always active.
Section "72.3.1.1 Clocks" from the reference manual [1] reads:
"SRTC runs on two clock sources, high frequency peripherals clock and low frequency timers clock. The high frequency peripheral IP clock is used by the SRTC peripheral bus interface, control and status registers. The low frequency 32.768 kHz clock is the always-active clock used by the SRTC timers..."

Quoted 1 line

That's why I would only include one clock . Should I change this?

Some chips supported 32.0kHz and 32.768kHz low freq clocks, so you'd need to be able to query what the frequency is even if you don't need to enable the clock, but maybe that may be gone in MX53. I don't remember.

Quoted 8 lines
Quoted 8 lines

Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt line 12

Quoted 5 lines
Documentation/devicetree/bindings/rtc/rtc-mxc_v2.txt new file +5 -0
+- interrupts: rtc alarm interrupt
+
+Example:
+
+srtc at 53fa4000 {

rtc at ...

Quoted 8 lines

The rtc for which this series adds support is embedded within a function block called "Secure Real Time Clock". This driver doesn't utilize all of the hardware features by now. But maybe someone else wants to extend the functionalities, later. For that possibility I wanted to name the node "srtc". Should I still change this?

I believe you have a much better understanding of what should be done here. I don't want to argue with you, just thought you might not had that information. So if I am wrong just tell me and I will change it without further "complaining".

Node names should be generic for the class of h/w they are. So yes, it should be "rtc".

Rob

#7 lore raw

PATCH v2 2/5 ARM: dts: imx53: add srtc node

In reply to [email protected]

From: Patrick Bruenn <[email protected]>

rtc-mxc_v2 driver will add support for the i.MX53 SRTC

---

To: Shawn Guo <[email protected]>
To: Sascha Hauer <[email protected]> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)

Cc Alessandro Zummo <[email protected]>
Cc Alexandre Belloni <[email protected]>
Cc Rob Herring <[email protected]>
Cc Mark Rutland <[email protected]> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-rtc at vger.kernel.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
Cc devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-kernel at vger.kernel.org (open list)
Cc Fabio Estevam <[email protected]>
Cc Juergen Borleis <[email protected]>
Cc Noel Vellemans <[email protected]>
Cc Russell King <[email protected]> (maintainer:ARM PORT)
Cc linux-arm-kernel at lists.infradead.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc Philippe Ombredanne <[email protected]>
Cc Lothar Wa?mann <[email protected]>
---
 arch/arm/boot/dts/imx53.dtsi | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
arch/arm/boot/dts/imx53.dtsi +1 -3
index 589a67c5f796..e4ca9d9ba2fe 100644
@@ -434,12 +434,10 @@
 			};
 
 			srtc: srtc at 53fa4000 {
-				compatible = "fsl,imx53-rtc", "fsl,imx25-rtc";
+				compatible = "fsl,imx53-rtc";
 				reg = <0x53fa4000 0x4000>;
 				interrupts = <24>;
-				interrupt-parent = <&tzic>;
 				clocks = <&clks IMX5_CLK_SRTC_GATE>;
-				clock-names = "ipg";
 			};
 
 			iomuxc: iomuxc at 53fa8000 {
Signature · 1 line
2.11.0
reviewer
#8 lore raw

Re: [PATCH v2 2/5] ARM: dts: imx53: add srtc node

arch/arm/boot/dts/imx53.dtsi line 442

Quoted 8 lines · On Tue, Dec 5, 2017 at 12:06 PM, <[email protected]> wrote:
                        srtc: srtc at 53fa4000 {
arch/arm/boot/dts/imx53.dtsi +1 -3
-                               compatible = "fsl,imx53-rtc", "fsl,imx25-rtc";
+                               compatible = "fsl,imx53-rtc";
                                reg = <0x53fa4000 0x4000>;
                                interrupts = <24>;
-                               interrupt-parent = <&tzic>;
                                clocks = <&clks IMX5_CLK_SRTC_GATE>;
-                               clock-names = "ipg";

srtc node has been removed in linux-next.

You need to re-add it.

#9 lore raw

RE: [PATCH v2 2/5] ARM: dts: imx53: add srtc node

Quoted 13 lines

From: Fabio Estevam [mailto:festevam at gmail.com]
Sent: Dienstag, 5. Dezember 2017 15:14

arch/arm/boot/dts/imx53.dtsi line 442

Quoted 8 lines · On Tue, Dec 5, 2017 at 12:06 PM, <[email protected]> wrote:
                        srtc: srtc at 53fa4000 {
arch/arm/boot/dts/imx53.dtsi +1 -3
-                               compatible = "fsl,imx53-rtc", "fsl,imx25-rtc";
+                               compatible = "fsl,imx53-rtc";
                                reg = <0x53fa4000 0x4000>;
                                interrupts = <24>;
-                               interrupt-parent = <&tzic>;
                                clocks = <&clks IMX5_CLK_SRTC_GATE>;
-                               clock-names = "ipg";
Quoted 3 lines

srtc node has been removed in linux-next.

You need to re-add it.

Thanks for this super-fast responses!
I will wait a few days for more reviewers and then integrate your comments in a v3. If nothing major show up I will wait until the imx53.dtsi revert landed in Linus tree.

Best regards,
Patrick

Beckhoff Automation GmbH & Co. KG | Managing Director: Dipl. Phys. Hans Beckhoff Registered office: Verl, Germany | Register court: Guetersloh HRA 7075

reviewer
#10 lore raw

Re: [PATCH v2 2/5] ARM: dts: imx53: add srtc node

Quoted 1 line · Patrick Br?nn

I will wait a few days for more reviewers and then integrate your comments in a v3. If nothing major show up I will wait until the imx53.dtsi revert landed in Linus tree.

It is in Linus' tree now as commit e501506d3ea0 ("Revert "ARM: dts:
imx53: add srtc node"").

#11 lore raw

PATCH v2 3/5 rtc: mxc_v2: add driver for i.MX53 SRTC

In reply to [email protected]

From: Patrick Bruenn <[email protected]>

Add RTC_DRV_MXC_V2 config option

---

To: Alessandro Zummo <[email protected]>
To: Alexandre Belloni <[email protected]>

Cc Rob Herring <[email protected]>
Cc Mark Rutland <[email protected]> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-rtc at vger.kernel.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
Cc devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-kernel at vger.kernel.org (open list)
Cc Fabio Estevam <[email protected]>
Cc Juergen Borleis <[email protected]>
Cc Noel Vellemans <[email protected]>
Cc Shawn Guo <[email protected]>
Cc Sascha Hauer <[email protected]> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc Russell King <[email protected]> (maintainer:ARM PORT)
Cc linux-arm-kernel at lists.infradead.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc Philippe Ombredanne <[email protected]>
Cc Lothar Wa?mann <[email protected]>
---
 drivers/rtc/Kconfig | 10 ++++++++++
 1 file changed, 10 insertions(+)
drivers/rtc/Kconfig +10 -0
index b59a31b079a5..440edebf5c71 100644
@@ -1689,6 +1689,16 @@ config RTC_DRV_MXC
 	   This driver can also be built as a module, if so, the module
 	   will be called "rtc-mxc".
 
+config RTC_DRV_MXC_V2
+	tristate "Freescale MXC Real Time Clock for i.MX53"
+	depends on ARCH_MXC
+	help
+	   If you say yes here you get support for the Freescale MXC
+	   SRTC module in i.MX53 processor.
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-mxc_v2".
+
 config RTC_DRV_SNVS
 	tristate "Freescale SNVS RTC support"
 	select REGMAP_MMIO
Signature · 1 line
2.11.0
#13 lore raw

PATCH v2 4/5 ARM: imx_v4_v5_defconfig: enable RTC_DRV_MXC_V2

In reply to [email protected]

From: Patrick Bruenn <[email protected]>

Enable SRTC driver for i.MX53 in default config

---

To: Shawn Guo <[email protected]>
To: Sascha Hauer <[email protected]> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)

Cc Alessandro Zummo <[email protected]>
Cc Alexandre Belloni <[email protected]>
Cc Rob Herring <[email protected]>
Cc Mark Rutland <[email protected]> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-rtc at vger.kernel.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
Cc devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc linux-kernel at vger.kernel.org (open list)
Cc Fabio Estevam <[email protected]>
Cc Juergen Borleis <[email protected]>
Cc Noel Vellemans <[email protected]>
Cc Russell King <[email protected]> (maintainer:ARM PORT)
Cc linux-arm-kernel at lists.infradead.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc Philippe Ombredanne <[email protected]>
Cc Lothar Wa?mann <[email protected]>
---
 arch/arm/configs/imx_v4_v5_defconfig | 1 +
 1 file changed, 1 insertion(+)
arch/arm/configs/imx_v4_v5_defconfig +1 -0
index ca0f13cafe38..b48efd5ff8a7 100644
@@ -167,6 +167,7 @@ CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_IMXDI=y
 CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
+CONFIG_RTC_DRV_MXC_V2=y
 CONFIG_DMADEVICES=y
 CONFIG_IMX_DMA=y
 CONFIG_IMX_SDMA=y
Signature · 1 line
2.11.0
reviewer
#14 lore raw

Re: [PATCH v2 4/5] ARM: imx_v4_v5_defconfig: enable RTC_DRV_MXC_V2

Hi Patrick,

Quoted 1 line · On Tue, Dec 5, 2017 at 12:06 PM, <[email protected]> wrote:
 arch/arm/configs/imx_v4_v5_defconfig | 1 +

i.mx53 uses imx_v6_v7_defconfig, not imx_v4_v5_defconfig.

#15 lore raw

PATCH v2 5/5 rtc: add mxc driver for i.MX53 SRTC

In reply to [email protected]

From: Patrick Bruenn <[email protected]>

Neither rtc-imxdi, rtc-mxc nor rtc-snvs are compatible with i.MX53.

This is driver enables support for the low power domain SRTC features:
- 32-bit MSB of non-rollover time counter
- 32-bit alarm register

Based on:
http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/drivers/rtc/rtc-mxc_v2.c?h=imx_2.6.35_11.09.01

---

v2:
- have seperate patches for dt-binding, CONFIG option, imx53.dtsi and driver
- add SPDX-License-Identifier and cleanup copyright notice
- replace __raw_readl/writel() with readl/writel()
- fix PM_SLEEP callbacks
- add CONFIG_RTC_DRV_MXC_V2 to build rtc-mxc_v2.c
- remove misleading or obvious comments and fix style of the remaining
- avoid endless loop while waiting for hw
- implement consistent locking; make spinlock a member of dev struct
- enable clk only for register accesses
- remove all udelay() calls since they are obsolete or redundant (we are already waiting for register flags to change)
- init platform_data before registering irq callback
- let set_time() fail, when 32 bit rtc counter exceeded
- make names more consistent
- cleanup and reorder includes
- cleanup and remove unused defines

To: Alessandro Zummo <[email protected]>
To: Alexandre Belloni <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Mark Rutland <[email protected]> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc: linux-rtc at vger.kernel.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
Cc: devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc: linux-kernel at vger.kernel.org (open list)
Cc: Fabio Estevam <[email protected]>
Cc: Juergen Borleis <[email protected]>
Cc: Noel Vellemans <[email protected]>
Cc: Shawn Guo <[email protected]>
Cc: Sascha Hauer <[email protected]> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc: Russell King <[email protected]> (maintainer:ARM PORT)
Cc: linux-arm-kernel at lists.infradead.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)

Cc Philippe Ombredanne <[email protected]>
Cc Lothar Wa?mann <[email protected]>
---
 drivers/rtc/Makefile     |   1 +
 drivers/rtc/rtc-mxc_v2.c | 433 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 434 insertions(+)
 create mode 100644 drivers/rtc/rtc-mxc_v2.c
drivers/rtc/Makefile +1 -0
index f2f50c11dc38..dcf60e61ae5c 100644
@@ -106,6 +106,7 @@ obj-$(CONFIG_RTC_DRV_MT6397)	+= rtc-mt6397.o
 obj-$(CONFIG_RTC_DRV_MT7622)	+= rtc-mt7622.o
 obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
 obj-$(CONFIG_RTC_DRV_MXC)	+= rtc-mxc.o
+obj-$(CONFIG_RTC_DRV_MXC_V2)	+= rtc-mxc_v2.o
 obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o
 obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
 obj-$(CONFIG_RTC_DRV_OPAL)	+= rtc-opal.o
drivers/rtc/rtc-mxc_v2.c new file +433 -0

433 lines not on this page · raw message

Signature · 1 line
2.11.0
maintainer
#16 lore raw

Re: [PATCH v2 5/5] rtc: add mxc driver for i.MX53 SRTC

Quoted 153 lines · linux-kernel-dev at beckhoff.com

From: Patrick Bruenn <[email protected]>

Neither rtc-imxdi, rtc-mxc nor rtc-snvs are compatible with i.MX53.

This is driver enables support for the low power domain SRTC features:
- 32-bit MSB of non-rollover time counter
- 32-bit alarm register

Based on:
http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/drivers/rtc/rtc-mxc_v2.c?h=imx_2.6.35_11.09.01

---

v2:
- have seperate patches for dt-binding, CONFIG option, imx53.dtsi and driver
- add SPDX-License-Identifier and cleanup copyright notice
- replace __raw_readl/writel() with readl/writel()
- fix PM_SLEEP callbacks
- add CONFIG_RTC_DRV_MXC_V2 to build rtc-mxc_v2.c
- remove misleading or obvious comments and fix style of the remaining
- avoid endless loop while waiting for hw
- implement consistent locking; make spinlock a member of dev struct
- enable clk only for register accesses
- remove all udelay() calls since they are obsolete or redundant (we are already waiting for register flags to change)
- init platform_data before registering irq callback
- let set_time() fail, when 32 bit rtc counter exceeded
- make names more consistent
- cleanup and reorder includes
- cleanup and remove unused defines

To: Alessandro Zummo <[email protected]>
To: Alexandre Belloni <[email protected]>
Cc: Rob Herring <[email protected]>
Cc: Mark Rutland <[email protected]> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc: linux-rtc at vger.kernel.org (open list:REAL TIME CLOCK (RTC) SUBSYSTEM)
Cc: devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Cc: linux-kernel at vger.kernel.org (open list)
Cc: Fabio Estevam <[email protected]>
Cc: Juergen Borleis <[email protected]>
Cc: Noel Vellemans <[email protected]>
Cc: Shawn Guo <[email protected]>
Cc: Sascha Hauer <[email protected]> (maintainer:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)
Cc: Russell King <[email protected]> (maintainer:ARM PORT)
Cc: linux-arm-kernel at lists.infradead.org (moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE)

Cc Philippe Ombredanne <[email protected]>
Cc Lothar Wa?mann <[email protected]>
---
 drivers/rtc/Makefile     |   1 +
 drivers/rtc/rtc-mxc_v2.c | 433 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 434 insertions(+)
 create mode 100644 drivers/rtc/rtc-mxc_v2.c
drivers/rtc/Makefile +1 -0
index f2f50c11dc38..dcf60e61ae5c 100644
@@ -106,6 +106,7 @@ obj-$(CONFIG_RTC_DRV_MT6397)	+= rtc-mt6397.o
 obj-$(CONFIG_RTC_DRV_MT7622)	+= rtc-mt7622.o
 obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
 obj-$(CONFIG_RTC_DRV_MXC)	+= rtc-mxc.o
+obj-$(CONFIG_RTC_DRV_MXC_V2)	+= rtc-mxc_v2.o
 obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o
 obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
 obj-$(CONFIG_RTC_DRV_OPAL)	+= rtc-opal.o
drivers/rtc/rtc-mxc_v2.c new file +79 -0
new file mode 100644
index 000000000000..c5a6d2c293bb
@@ -0,0 +1,433 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Real Time Clock (RTC) Driver for i.MX53
+ * Copyright (c) 2004-2011 Freescale Semiconductor, Inc.
+ * Copyright (c) 2017 Beckhoff Automation GmbH & Co. KG
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+#define SRTC_LPPDR_INIT       0x41736166	/* init for glitch detect */
+
+#define SRTC_LPCR_EN_LP       BIT(3)	/* lp enable */
+#define SRTC_LPCR_WAE         BIT(4)	/* lp wakeup alarm enable */
+#define SRTC_LPCR_ALP         BIT(7)	/* lp alarm flag */
+#define SRTC_LPCR_NSA         BIT(11)	/* lp non secure access */
+#define SRTC_LPCR_NVE         BIT(14)	/* lp non valid state exit bit */
+#define SRTC_LPCR_IE          BIT(15)	/* lp init state exit bit */
+
+#define SRTC_LPSR_ALP         BIT(3)	/* lp alarm flag */
+#define SRTC_LPSR_NVES        BIT(14)	/* lp non-valid state exit status */
+#define SRTC_LPSR_IES         BIT(15)	/* lp init state exit status */
+
+#define SRTC_LPSCMR	0x00	/* LP Secure Counter MSB Reg */
+#define SRTC_LPSCLR	0x04	/* LP Secure Counter LSB Reg */
+#define SRTC_LPSAR	0x08	/* LP Secure Alarm Reg */
+#define SRTC_LPCR	0x10	/* LP Control Reg */
+#define SRTC_LPSR	0x14	/* LP Status Reg */
+#define SRTC_LPPDR	0x18	/* LP Power Supply Glitch Detector Reg */
+
+/* max. number of retries to read registers, 120 was max during test */
+#define REG_READ_TIMEOUT 2000
+
+struct mxc_rtc_data {
+	struct rtc_device *rtc;
+	void __iomem *ioaddr;
+	struct clk *clk;
+	spinlock_t lock; /* protects register access */
+	int irq;
+};
+
+/*
+ * This function does write synchronization for writes to the lp srtc block.
+ * To take care of the asynchronous CKIL clock, all writes from the IP domain
+ * will be synchronized to the CKIL domain.
+ * The caller should hold the pdata->lock
+ */
+static inline void mxc_rtc_sync_lp_locked(void __iomem *ioaddr)
+{
+	unsigned int i;
+
+	/* Wait for 3 CKIL cycles */
+	for (i = 0; i < 3; i++) {
+		const u32 count = readl(ioaddr + SRTC_LPSCLR);
+		unsigned int timeout = REG_READ_TIMEOUT;
+
+		while ((readl(ioaddr + SRTC_LPSCLR)) == count) {
+			if (!--timeout) {
+				pr_err("SRTC_LPSCLR stuck! Check your hw.\n");
+				return;
+			}
+		}
+	}
+}
+
+/*
+ * This function updates the RTC alarm registers and then clears all the
+ * interrupt status bits.
+ * The caller should hold the pdata->lock
+ *
+ * @param  alrm         the new alarm value to be updated in the RTC
+ *
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_write_alarm_locked(struct mxc_rtc_data *const pdata,
+				      struct rtc_time *alarm_tm)

drivers/rtc/rtc-mxc_v2.c line 89

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+{
+	void __iomem *const ioaddr = pdata->ioaddr;
+	unsigned long time;
+
+	rtc_tm_to_time(alarm_tm, &time);
+
+	if (time > U32_MAX) {
+		pr_err("Hopefully I am out of service by then :-(\n");
+		return -EINVAL;
+	}

This will never happen as on your target hardware unsigned long is a 32bit type. Not sure what is best to do here. Maybe you should test the return value of rtc_tm_to_time. ATM it returns 0 unconditionally, but rtc_tm_to_time could detect when the input time doesn't fit into its return type and return an error in this case.
Also I just realized that it's unsigned and only overflows in the year 2106. I'm most likely dead then so I don't care that much ;)

Quoted 16 lines
drivers/rtc/rtc-mxc_v2.c new file +16 -0
+
+	writel((u32)time, ioaddr + SRTC_LPSAR);
+
+	/* clear alarm interrupt status bit */
+	writel(SRTC_LPSR_ALP, ioaddr + SRTC_LPSR);
+
+	mxc_rtc_sync_lp_locked(ioaddr);
+	return 0;
+}
+
+/* This function is the RTC interrupt service routine. */
+static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	struct mxc_rtc_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;

drivers/rtc/rtc-mxc_v2.c line 115

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+	unsigned long flags;
+	u32 events = 0;
+	u32 lp_status;
+	u32 lp_cr;
+
+	spin_lock_irqsave(&pdata->lock, flags);
+	if (clk_prepare_enable(pdata->clk)) {
+		spin_unlock_irqrestore(&pdata->lock, flags);
+		return IRQ_NONE;
+	}

You are not allowed to do a clk_prepare under a spinlock. That was the original reason to split enabling a clk into clk_prepare and clk_enable. Everything that can block is done in clk_prepare and only non blocking things are done in clk_enable.
If you want to enable/disable the clock on demand you can clk_prepare() in probe and clk_enable when you actually need it.

Quoted 60 lines
drivers/rtc/rtc-mxc_v2.c new file +60 -0
+
+	lp_status = readl(ioaddr + SRTC_LPSR);
+	lp_cr = readl(ioaddr + SRTC_LPCR);
+
+	/* update irq data & counter */
+	if (lp_status & SRTC_LPSR_ALP) {
+		if (lp_cr & SRTC_LPCR_ALP)
+			events = (RTC_AF | RTC_IRQF);
+
+		/* disable further lp alarm interrupts */
+		lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
+	}
+
+	/* Update interrupt enables */
+	writel(lp_cr, ioaddr + SRTC_LPCR);
+
+	/* clear interrupt status */
+	writel(lp_status, ioaddr + SRTC_LPSR);
+
+	mxc_rtc_sync_lp_locked(ioaddr);
+	rtc_update_irq(pdata->rtc, 1, events);
+	clk_disable_unprepare(pdata->clk);
+	spin_unlock_irqrestore(&pdata->lock, flags);
+	return IRQ_HANDLED;
+}
+
+/*
+ * Enable clk and aquire spinlock
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_lock(struct mxc_rtc_data *const pdata)
+{
+	int ret;
+
+	spin_lock_irq(&pdata->lock);
+	ret = clk_prepare_enable(pdata->clk);
+	if (ret) {
+		spin_unlock_irq(&pdata->lock);
+		return ret;
+	}
+	return 0;
+}
+
+static int mxc_rtc_unlock(struct mxc_rtc_data *const pdata)
+{
+	clk_disable_unprepare(pdata->clk);
+	spin_unlock_irq(&pdata->lock);
+	return 0;
+}
+
+/*
+ * This function reads the current RTC time into tm in Gregorian date.
+ *
+ * @param  tm           contains the RTC time value upon return
+ *
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mxc_rtc_data *pdata = dev_get_drvdata(dev);

drivers/rtc/rtc-mxc_v2.c line 185

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+	time_t now;
+	int ret = mxc_rtc_lock(pdata);
+
+	if (ret)
+		return ret;
+
+	now = readl(pdata->ioaddr + SRTC_LPSCMR);
+	rtc_time_to_tm(now, tm);
+	ret = rtc_valid_tm(tm);
+	mxc_rtc_unlock(pdata);

I don't think this needs to be locked.

Quoted 89 lines
drivers/rtc/rtc-mxc_v2.c new file +89 -0
+	return ret;
+}
+
+/*
+ * This function sets the internal RTC time based on tm in Gregorian date.
+ *
+ * @param  tm           the time value to be set in the RTC
+ *
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+	time64_t time = rtc_tm_to_time64(tm);
+	int ret;
+
+	if (time > U32_MAX) {
+		dev_err(dev, "RTC exceeded by %llus\n", time - U32_MAX);
+		return -EINVAL;
+	}
+
+	ret = mxc_rtc_lock(pdata);
+	if (ret)
+		return ret;
+
+	writel(time, pdata->ioaddr + SRTC_LPSCMR);
+	mxc_rtc_sync_lp_locked(pdata->ioaddr);
+	return mxc_rtc_unlock(pdata);
+}
+
+/*
+ * This function reads the current alarm value into the passed in \b alrm
+ * argument. It updates the \b alrm's pending field value based on the whether
+ * an alarm interrupt occurs or not.
+ *
+ * @param  alrm         contains the RTC alarm value upon return
+ *
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	int ret;
+
+	ret = mxc_rtc_lock(pdata);
+	if (ret)
+		return ret;
+
+	rtc_time_to_tm(readl(ioaddr + SRTC_LPSAR), &alrm->time);
+	alrm->pending = !!(readl(ioaddr + SRTC_LPSR) & SRTC_LPSR_ALP);
+	return mxc_rtc_unlock(pdata);
+}
+
+/*
+ * Enable/Disable alarm interrupt
+ * The caller should hold the pdata->lock
+ */
+static void mxc_rtc_alarm_irq_enable_locked(struct mxc_rtc_data *pdata,
+					    unsigned int enable)
+{
+	u32 lp_cr = readl(pdata->ioaddr + SRTC_LPCR);
+
+	if (enable)
+		lp_cr |= (SRTC_LPCR_ALP | SRTC_LPCR_WAE);
+	else
+		lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
+
+	writel(lp_cr, pdata->ioaddr + SRTC_LPCR);
+}
+
+static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+	struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+	int ret = mxc_rtc_lock(pdata);
+
+	if (ret)
+		return ret;
+
+	mxc_rtc_alarm_irq_enable_locked(pdata, enable);
+	return mxc_rtc_unlock(pdata);
+}
+
+/*
+ * This function sets the RTC alarm based on passed in alrm.
+ *
+ * @param  alrm         the alarm value to be set in the RTC
+ *
+ * @return  0 if successful; non-zero otherwise.

drivers/rtc/rtc-mxc_v2.c line 284

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+ */
+static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+	int ret = mxc_rtc_lock(pdata);
+
+	if (ret)
+		return ret;
+
+	ret = mxc_rtc_write_alarm_locked(pdata, &alrm->time);

Is it worth it to make this a separate function?

Quoted 13 lines
drivers/rtc/rtc-mxc_v2.c new file +13 -0
+	if (!ret) {
+		mxc_rtc_alarm_irq_enable_locked(pdata, alrm->enabled);
+		mxc_rtc_sync_lp_locked(pdata->ioaddr);
+	}
+	mxc_rtc_unlock(pdata);
+	return ret;
+}
+
+static const struct rtc_class_ops mxc_rtc_ops = {
+	.read_time = mxc_rtc_read_time,
+	.set_time = mxc_rtc_set_time,
+	.read_alarm = mxc_rtc_read_alarm,
+	.set_alarm = mxc_rtc_set_alarm,

drivers/rtc/rtc-mxc_v2.c line 307

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+	.alarm_irq_enable = mxc_rtc_alarm_irq_enable,
+};
+
+static int mxc_rtc_wait_for_flag(void *__iomem ioaddr, int flag)
+{
+	unsigned int timeout = REG_READ_TIMEOUT;
+
+	while (!(readl(ioaddr) & flag)) {
+		if (!--timeout) {
+			pr_err("Wait timeout for 0x%x@%p!\n", flag, ioaddr);

Please use dev_* functions for printing. In this case the message should probably be printed from the caller.

Quoted 42 lines
drivers/rtc/rtc-mxc_v2.c new file +42 -0
+			return -EBUSY;
+		}
+	}
+	return 0;
+}
+
+static int mxc_rtc_probe(struct platform_device *pdev)
+{
+	struct mxc_rtc_data *pdata;
+	struct resource *res;
+	void __iomem *ioaddr;
+	int ret = 0;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pdata->ioaddr))
+		return PTR_ERR(pdata->ioaddr);
+
+	ioaddr = pdata->ioaddr;
+
+	pdata->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(pdata->clk)) {
+		dev_err(&pdev->dev, "unable to get rtc clock!\n");
+		return PTR_ERR(pdata->clk);
+	}
+
+	spin_lock_init(&pdata->lock);
+	pdata->irq = platform_get_irq(pdev, 0);
+	if (pdata->irq < 0)
+		return pdata->irq;
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	ret = clk_prepare_enable(pdata->clk);
+	if (ret)

drivers/rtc/rtc-mxc_v2.c

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+		return ret;
+	/* initialize glitch detect */
+	writel(SRTC_LPPDR_INIT, ioaddr + SRTC_LPPDR);
+
+	/* clear lp interrupt status */
+	writel(0xFFFFFFFF, ioaddr + SRTC_LPSR);
+
+	/* move out of init state */
+	writel((SRTC_LPCR_IE | SRTC_LPCR_NSA), ioaddr + SRTC_LPCR);
+	xc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_IES);

If this can fail, shouldn't you test for an error?

drivers/rtc/rtc-mxc_v2.c line 364

Quoted 5 lines
drivers/rtc/rtc-mxc_v2.c new file +5 -0
+
+	/* move out of non-valid state */
+	writel((SRTC_LPCR_IE | SRTC_LPCR_NVE | SRTC_LPCR_NSA |
+		SRTC_LPCR_EN_LP), ioaddr + SRTC_LPCR);
+	mxc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_NVES);

dito

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#17 lore raw

Re: [PATCH v2 5/5] rtc: add mxc driver for i.MX53 SRTC

Quoted 22 lines · Sascha Hauer
Quoted 11 lines
drivers/rtc/rtc-mxc_v2.c new file +11 -0
+/*
+ * This function updates the RTC alarm registers and then clears all the
+ * interrupt status bits.
+ * The caller should hold the pdata->lock
+ *
+ * @param  alrm         the new alarm value to be updated in the RTC
+ *
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_write_alarm_locked(struct mxc_rtc_data *const pdata,
+				      struct rtc_time *alarm_tm)

drivers/rtc/rtc-mxc_v2.c line 89

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+{
+	void __iomem *const ioaddr = pdata->ioaddr;
+	unsigned long time;
+
+	rtc_tm_to_time(alarm_tm, &time);
+
+	if (time > U32_MAX) {
+		pr_err("Hopefully I am out of service by then :-(\n");
+		return -EINVAL;
+	}
Quoted 8 lines

This will never happen as on your target hardware unsigned long is a 32bit type. Not sure what is best to do here. Maybe you should test the return value of rtc_tm_to_time. ATM it returns 0 unconditionally, but rtc_tm_to_time could detect when the input time doesn't fit into its return type and return an error in this case.
Also I just realized that it's unsigned and only overflows in the year 2106. I'm most likely dead then so I don't care that much ;)

One solution is to use the 64bit version instead so it doesn't overflow. This makes the time > U32_MAX work.
Also, I'll send (hopefully soon) a series adding proper range checking for the whole RTC subsystem. And yes, it not urgent as I don't think I will care so much in 2106 too ;)

Quoted 11 lines
Quoted 11 lines
drivers/rtc/rtc-mxc_v2.c new file +11 -0
+/*
+ * This function reads the current RTC time into tm in Gregorian date.
+ *
+ * @param  tm           contains the RTC time value upon return
+ *
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+	time_t now;
Quoted 8 lines

drivers/rtc/rtc-mxc_v2.c line 184

Quoted 8 lines
drivers/rtc/rtc-mxc_v2.c new file +8 -0
+	int ret = mxc_rtc_lock(pdata);
+
+	if (ret)
+		return ret;
+
+	now = readl(pdata->ioaddr + SRTC_LPSCMR);
+	rtc_time_to_tm(now, tm);
+	ret = rtc_valid_tm(tm);

This check is useless for two reasons: you know that rtc_time_to_tm will generate a valid tm and the core always checks the tm anyway.

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

RE: [PATCH v2 5/5] rtc: add mxc driver for i.MX53 SRTC

Quoted 34 lines

From: Alexandre Belloni [mailto:alexandre.belloni at free-electrons.com]
Sent: Mittwoch, 6. Dezember 2017 09:58

Quoted 22 lines · Sascha Hauer
Quoted 11 lines
drivers/rtc/rtc-mxc_v2.c new file +11 -0
+/*
+ * This function updates the RTC alarm registers and then clears all the
+ * interrupt status bits.
+ * The caller should hold the pdata->lock
+ *
+ * @param  alrm         the new alarm value to be updated in the RTC
+ *
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_write_alarm_locked(struct mxc_rtc_data *const pdata,
+                                struct rtc_time *alarm_tm)

drivers/rtc/rtc-mxc_v2.c line 89

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+{
+  void __iomem *const ioaddr = pdata->ioaddr;
+  unsigned long time;
+
+  rtc_tm_to_time(alarm_tm, &time);
+
+  if (time > U32_MAX) {
+          pr_err("Hopefully I am out of service by then :-(\n");
+          return -EINVAL;
+  }
Quoted 8 lines

This will never happen as on your target hardware unsigned long is a 32bit type. Not sure what is best to do here. Maybe you should test the return value of rtc_tm_to_time. ATM it returns 0 unconditionally, but rtc_tm_to_time could detect when the input time doesn't fit into its return type and return an error in this case.
Also I just realized that it's unsigned and only overflows in the year 2106. I'm most likely dead then so I don't care that much ;)

Quoted 6 lines

One solution is to use the 64bit version instead so it doesn't overflow. This makes the time > U32_MAX work.
Also, I'll send (hopefully soon) a series adding proper range checking for the whole RTC subsystem. And yes, it not urgent as I don't think I will care so much in 2106 too ;)

I just noticed that in mxc_rtc_set_time() I am using the 64bit version. After thinking a while about this issue, I think the 64bit version is better suited for my use case. It makes explicitly clear that I need to push the time into a 32bit hw register and "unsigned long" is just by accident the correct size for me.

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
drivers/rtc/rtc-mxc_v2.c new file +14 -0
+/*
+ * This function reads the current RTC time into tm in Gregorian date.
+ *
+ * @param  tm           contains the RTC time value upon return
+ *
+ * @return  0 if successful; non-zero otherwise.
+ */
+static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+  struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+  time_t now;
+  int ret = mxc_rtc_lock(pdata);
+
+  if (ret)
Quoted 8 lines
Quoted 5 lines

drivers/rtc/rtc-mxc_v2.c line 184

Quoted 5 lines
drivers/rtc/rtc-mxc_v2.c new file +5 -0
+          return ret;
+
+  now = readl(pdata->ioaddr + SRTC_LPSCMR);
+  rtc_time_to_tm(now, tm);
+  ret = rtc_valid_tm(tm);

This check is useless for two reasons: you know that rtc_time_to_tm will generate a valid tm and the core always checks the tm anyway.

I will remove this with the next version

Thanks for your time and help,
Patrick

Beckhoff Automation GmbH & Co. KG | Managing Director: Dipl. Phys. Hans Beckhoff Registered office: Verl, Germany | Register court: Guetersloh HRA 7075

#19 lore raw

RE: [PATCH v2 5/5] rtc: add mxc driver for i.MX53 SRTC

In reply to Sascha Hauer
Quoted 17 lines

From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Mittwoch, 6. Dezember 2017 09:36

drivers/rtc/rtc-mxc_v2.c line 89

Quoted 12 lines · linux-kernel-dev at beckhoff.com
drivers/rtc/rtc-mxc_v2.c new file +12 -0
+static int mxc_rtc_write_alarm_locked(struct mxc_rtc_data *const pdata,
+                                  struct rtc_time *alarm_tm)
+{
+    void __iomem *const ioaddr = pdata->ioaddr;
+    unsigned long time;
+
+    rtc_tm_to_time(alarm_tm, &time);
+
+    if (time > U32_MAX) {
+            pr_err("Hopefully I am out of service by then :-(\n");
+            return -EINVAL;
+    }
Quoted 8 lines

This will never happen as on your target hardware unsigned long is a 32bit type. Not sure what is best to do here. Maybe you should test the return value of rtc_tm_to_time. ATM it returns 0 unconditionally, but rtc_tm_to_time could detect when the input time doesn't fit into its return type and return an error in this case.
Also I just realized that it's unsigned and only overflows in the year 2106. I'm most likely dead then so I don't care that much ;)

please see my response to Alexandre's follow up

Quoted 15 lines
Quoted 15 lines
drivers/rtc/rtc-mxc_v2.c new file +15 -0
+/* This function is the RTC interrupt service routine. */
+static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
+{
+    struct platform_device *pdev = dev_id;
+    struct mxc_rtc_data *pdata = platform_get_drvdata(pdev);
+    void __iomem *ioaddr = pdata->ioaddr;
+    unsigned long flags;
+    u32 events = 0;
+    u32 lp_status;
+    u32 lp_cr;
+
+    spin_lock_irqsave(&pdata->lock, flags);
+    if (clk_prepare_enable(pdata->clk)) {
+            spin_unlock_irqrestore(&pdata->lock, flags);
+            return IRQ_NONE;
Quoted 9 lines
Quoted 1 line

+ }

You are not allowed to do a clk_prepare under a spinlock. That was the original reason to split enabling a clk into clk_prepare and clk_enable. Everything that can block is done in clk_prepare and only non blocking things are done in clk_enable.
If you want to enable/disable the clock on demand you can clk_prepare() in probe and clk_enable when you actually need it.

Thanks for clarification. To be honest when I read Lothar's suggestion it was the first time I thought about the idea of keeping the clk disabled most of the time. I am not very experienced with this. But a rtctest loop run for hours so I assume it would be okay to keep the clk disabled until hw access. If there is no objection from somebody who knows the i.MX53 SRTC HW better, I will stick to the clock on demand model and make sure I avoid blocking.

Quoted 8 lines
Quoted 8 lines
drivers/rtc/rtc-mxc_v2.c new file +8 -0
+
+static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+    struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+    time_t now;
+    int ret = mxc_rtc_lock(pdata);
+
+    if (ret)
Quoted 8 lines

drivers/rtc/rtc-mxc_v2.c line 185

Quoted 6 lines
drivers/rtc/rtc-mxc_v2.c new file +6 -0
+            return ret;
+
+    now = readl(pdata->ioaddr + SRTC_LPSCMR);
+    rtc_time_to_tm(now, tm);
+    ret = rtc_valid_tm(tm);
+    mxc_rtc_unlock(pdata);

I don't think this needs to be locked.

I will change this to only enable the clock for the readl()

Quoted 11 lines

drivers/rtc/rtc-mxc_v2.c line 284

Quoted 9 lines
drivers/rtc/rtc-mxc_v2.c new file +9 -0
+static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+    struct mxc_rtc_data *pdata = dev_get_drvdata(dev);
+    int ret = mxc_rtc_lock(pdata);
+
+    if (ret)
+            return ret;
+
+    ret = mxc_rtc_write_alarm_locked(pdata, &alrm->time);

Is it worth it to make this a separate function?

Maybe not, I think it is an artifact from a refactoring. I will reconsider this for the next version.

Quoted 19 lines
Quoted 19 lines
drivers/rtc/rtc-mxc_v2.c new file +18 -0
+    if (!ret) {
+            mxc_rtc_alarm_irq_enable_locked(pdata, alrm->enabled);
+            mxc_rtc_sync_lp_locked(pdata->ioaddr);
+    }
+    mxc_rtc_unlock(pdata);
+    return ret;
+}
+
+static const struct rtc_class_ops mxc_rtc_ops = {
+    .read_time = mxc_rtc_read_time,
+    .set_time = mxc_rtc_set_time,
+    .read_alarm = mxc_rtc_read_alarm,
+    .set_alarm = mxc_rtc_set_alarm,
+    .alarm_irq_enable = mxc_rtc_alarm_irq_enable,
+};
+
+static int mxc_rtc_wait_for_flag(void *__iomem ioaddr, int flag)
+{
Quoted 8 lines

drivers/rtc/rtc-mxc_v2.c line 307

Quoted 5 lines
drivers/rtc/rtc-mxc_v2.c new file +5 -0
+    unsigned int timeout = REG_READ_TIMEOUT;
+
+    while (!(readl(ioaddr) & flag)) {
+            if (!--timeout) {
+                    pr_err("Wait timeout for 0x%x@%p!\n", flag, ioaddr);

Please use dev_* functions for printing. In this case the message should probably be printed from the caller.

Do you have a link at hand about dev_* vs. pr_*? I just choose pr_err here, because I would have to change the functions signature to get a device. However, I will drop the message and move it to the caller.

Quoted 8 lines

drivers/rtc/rtc-mxc_v2.c

Quoted 6 lines
drivers/rtc/rtc-mxc_v2.c new file +6 -0
+    /* clear lp interrupt status */
+    writel(0xFFFFFFFF, ioaddr + SRTC_LPSR);
+
+    /* move out of init state */
+    writel((SRTC_LPCR_IE | SRTC_LPCR_NSA), ioaddr + SRTC_LPCR);
+    xc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_IES);

If this can fail, shouldn't you test for an error?

very probably

Quoted 7 lines

drivers/rtc/rtc-mxc_v2.c line 364

Quoted 5 lines
drivers/rtc/rtc-mxc_v2.c new file +5 -0
+
+    /* move out of non-valid state */
+    writel((SRTC_LPCR_IE | SRTC_LPCR_NVE | SRTC_LPCR_NSA |
+            SRTC_LPCR_EN_LP), ioaddr + SRTC_LPCR);
+    mxc_rtc_wait_for_flag(ioaddr + SRTC_LPSR, SRTC_LPSR_NVES);

dito

sure

Thanks,
Patrick
---
Beckhoff Automation GmbH & Co. KG | Managing Director: Dipl. Phys. Hans Beckhoff Registered office: Verl, Germany | Register court: Guetersloh HRA 7075

maintainer
#20 lore raw

Re: [PATCH v2 5/5] rtc: add mxc driver for i.MX53 SRTC

Quoted 14 lines · Patrick Br?nn
Quoted 4 lines

From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: Mittwoch, 6. Dezember 2017 09:36
On Tue, Dec 05, 2017 at 03:06:46PM +0100, linux-kernel-dev at beckhoff.com wrote:

Quoted 10 lines

drivers/rtc/rtc-mxc_v2.c line 307

Quoted 7 lines
drivers/rtc/rtc-mxc_v2.c new file +7 -0
+static int mxc_rtc_wait_for_flag(void *__iomem ioaddr, int flag)
+{
+    unsigned int timeout = REG_READ_TIMEOUT;
+
+    while (!(readl(ioaddr) & flag)) {
+            if (!--timeout) {
+                    pr_err("Wait timeout for 0x%x@%p!\n", flag, ioaddr);

Please use dev_* functions for printing. In this case the message should probably be printed from the caller.

Quoted 3 lines

Do you have a link at hand about dev_* vs. pr_*? I just choose pr_err here, because I would have to change the functions signature to get a device. However, I will drop the message and move it to the caller.

No, I don't have a link. However, a message printed with pr_err comes with absolutely no context, so without grepping the source you do not get a clue which device has a problem. You could add more context using some prefix either to each message or by using

#define pr_fmt(fmt) "mydriver: " fmt

but then you still not know which instance the message throws. Using dev_* just does the right thing without much thinking.

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#21 lore raw

Re: [PATCH v2 5/5] rtc: add mxc driver for i.MX53 SRTC

In reply to [email protected]
Quoted 14 lines · linux-kernel-dev at beckhoff.com
drivers/rtc/rtc-mxc_v2.c new file +14 -0
+/* This function is the RTC interrupt service routine. */
+static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	struct mxc_rtc_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	unsigned long flags;
+	u32 events = 0;
+	u32 lp_status;
+	u32 lp_cr;
+
+	spin_lock_irqsave(&pdata->lock, flags);
+	if (clk_prepare_enable(pdata->clk)) {
+		spin_unlock_irqrestore(&pdata->lock, flags);

drivers/rtc/rtc-mxc_v2.c line 123

Quoted 10 lines
drivers/rtc/rtc-mxc_v2.c new file +10 -0
+		return IRQ_NONE;
+	}
+
+	lp_status = readl(ioaddr + SRTC_LPSR);
+	lp_cr = readl(ioaddr + SRTC_LPCR);
+
+	/* update irq data & counter */
+	if (lp_status & SRTC_LPSR_ALP) {
+		if (lp_cr & SRTC_LPCR_ALP)
+			events = (RTC_AF | RTC_IRQF);

I would just call rtc_update_irq here...

drivers/rtc/rtc-mxc_v2.c line 136

Quoted 13 lines
drivers/rtc/rtc-mxc_v2.c new file +13 -0
+
+		/* disable further lp alarm interrupts */
+		lp_cr &= ~(SRTC_LPCR_ALP | SRTC_LPCR_WAE);
+	}
+
+	/* Update interrupt enables */
+	writel(lp_cr, ioaddr + SRTC_LPCR);
+
+	/* clear interrupt status */
+	writel(lp_status, ioaddr + SRTC_LPSR);
+
+	mxc_rtc_sync_lp_locked(ioaddr);
+	rtc_update_irq(pdata->rtc, 1, events);

... because calling it here with events == 0 will result in a lot of work for nothing (the core will walk through the timers and set the alarm again).

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