Skip to contentSkip to conversation

ARM: dts: Change dw-apb-timer-osc and dw-apb-timer-sp to just dw-apb-timer

PATCH New dinguyen at altera.com 5 participants 7 messages Aug 14, 2013 – Aug 21, 2013

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/2 ARM: dts: Change dw-apb-timer-osc and dw-apb-timer-sp to just dw-apb-timer

From: Dinh Nguyen <[email protected]>

"dw-apb-timer-osc" and "dw-apb-timer-sp" are the same implementation of the DW APB timer, just fed by different clocks. Thus, deprecate both "dw-apb-timer-osc" and "dw-apb-timer-sp" in lieu of "dw-apb-timer",

Clean up the timer entries for socfpga by removing timer<n> and set the correct clocks for the timers.

CC Rob Herring <[email protected]>
Cc Pawel Moll <[email protected]>
Cc Mark Rutland <[email protected]>
Cc Stephen Warren <[email protected]>
Cc Ian Campbell <[email protected]>
CC Arnd Bergmann <[email protected]>
Cc Olof Johansson <[email protected]>
CC Jamie Iles <[email protected]>
Cc John Stultz <[email protected]>
Cc Heiko Stuebner <[email protected]>
Cc Pavel Machek <[email protected]>
Cc devicetree at vger.kernel.org
Cc linux-arm-kernel at lists.infradead.org

v2:
- Deprecate the "dw-apb-timer-osc" and "dw-apb-timer-sp" but maintain backwards compatibility in the driver.

---
 Documentation/devicetree/bindings/rtc/dw-apb.txt |   32 ++++++----------------
 arch/arm/boot/dts/socfpga.dtsi                   |   24 ++++++++--------
 arch/arm/boot/dts/socfpga_cyclone5.dts           |    8 +++---
 arch/arm/boot/dts/socfpga_vt.dts                 |    8 +++---
 4 files changed, 29 insertions(+), 43 deletions(-)
Documentation/devicetree/bindings/rtc/dw-apb.txt +9 -23
index eb2327b..38060c5 100644
@@ -1,7 +1,8 @@
 * Designware APB timer
 
 Required properties:
-- compatible: "snps,dw-apb-timer-sp" or "snps,dw-apb-timer-osc"
+- compatible: "snps,dw-apb-timer-sp" or "snps,dw-apb-timer-osc" <DEPRECATED>
+- compatible: "snps,dw-apb-timer"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: IRQ line for the timer.
@@ -20,25 +21,10 @@ systems may use one.
 
 
 Example:
-
-		timer1: timer at ffc09000 {
-				compatible = "snps,dw-apb-timer-sp";
-				interrupts = <0 168 4>;
-				clock-frequency = <200000000>;
-				reg = <0xffc09000 0x1000>;
-			};
-
-		timer2: timer at ffd00000 {
-				compatible = "snps,dw-apb-timer-osc";
-				interrupts = <0 169 4>;
-				clock-frequency = <200000000>;
-				reg = <0xffd00000 0x1000>;
-			};
-
-		timer3: timer at ffe00000 {
-				compatible = "snps,dw-apb-timer-osc";
-				interrupts = <0 170 4>;
-				reg = <0xffe00000 0x1000>;
-				clocks = <&timer_clk>, <&timer_pclk>;
-				clock-names = "timer", "pclk";
-			};
+	timer at ffe00000 {
+		compatible = "snps,dw-apb-timer";
+		interrupts = <0 170 4>;
+		reg = <0xffe00000 0x1000>;
+		clocks = <&timer_clk>, <&timer_pclk>;
+		clock-names = "timer", "pclk";
+	};
arch/arm/boot/dts/socfpga.dtsi +12 -12
index 9706767..03845cb 100644
@@ -26,10 +26,6 @@
 		ethernet1 = &gmac1;
 		serial0 = &uart0;
 		serial1 = &uart1;
-		timer0 = &timer0;
-		timer1 = &timer1;
-		timer2 = &timer2;
-		timer3 = &timer3;
 	};
 
 	cpus {
@@ -486,28 +482,32 @@
 			interrupts = <1 13 0xf04>;
 		};
 
-		timer0: timer0 at ffc08000 {
-			compatible = "snps,dw-apb-timer-sp";
+		timer at ffc08000 {
+			compatible = "snps,dw-apb-timer";
 			interrupts = <0 167 4>;
 			reg = <0xffc08000 0x1000>;
+			clocks = <&osc>;
 		};
 
-		timer1: timer1 at ffc09000 {
-			compatible = "snps,dw-apb-timer-sp";
+		timer at ffc09000 {
+			compatible = "snps,dw-apb-timer";
 			interrupts = <0 168 4>;
 			reg = <0xffc09000 0x1000>;
+			clocks = <&osc>;
 		};
 
-		timer2: timer2 at ffd00000 {
-			compatible = "snps,dw-apb-timer-osc";
+		timer at ffd00000 {
+			compatible = "snps,dw-apb-timer";
 			interrupts = <0 169 4>;
 			reg = <0xffd00000 0x1000>;
+			clocks = <&l4_sp_clk>;
 		};
 
-		timer3: timer3 at ffd01000 {
-			compatible = "snps,dw-apb-timer-osc";
+		timer at ffd01000 {
+			compatible = "snps,dw-apb-timer";
 			interrupts = <0 170 4>;
 			reg = <0xffd01000 0x1000>;
+			clocks = <&l4_sp_clk>;
 		};
 
 		uart0: serial0 at ffc02000 {
arch/arm/boot/dts/socfpga_cyclone5.dts +4 -4
index 698dde9..c1af01c 100644
@@ -67,19 +67,19 @@
 			};
 		};
 
-		timer0 at ffc08000 {
+		timer at ffc08000 {
 			clock-frequency = <100000000>;
 		};
 
-		timer1 at ffc09000 {
+		timer at ffc09000 {
 			clock-frequency = <100000000>;
 		};
 
-		timer2 at ffd00000 {
+		timer at ffd00000 {
 			clock-frequency = <25000000>;
 		};
 
-		timer3 at ffd01000 {
+		timer at ffd01000 {
 			clock-frequency = <25000000>;
 		};
 
arch/arm/boot/dts/socfpga_vt.dts +4 -4
index 6f23121..72ff14c 100644
@@ -57,19 +57,19 @@
 			};
 		};
 
-		timer0 at ffc08000 {
+		timer at ffc08000 {
 			clock-frequency = <7000000>;
 		};
 
-		timer1 at ffc09000 {
+		timer at ffc09000 {
 			clock-frequency = <7000000>;
 		};
 
-		timer2 at ffd00000 {
+		timer at ffd00000 {
 			clock-frequency = <7000000>;
 		};
 
-		timer3 at ffd01000 {
+		timer at ffd01000 {
 			clock-frequency = <7000000>;
 		};
 
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH v2 2/2 clocksource: dw_apb_timer_of: Fix read_sched_clock

From: Dinh Nguyen <[email protected]>

The read_sched_clock should return the ~value because the clock is a countdown implementation. read_sched_clock() should be the same as __apbt_read_clocksource().

If a separate timer for the sched_clock exist, then read_sched_clock() will return an incorrect value. The (sched_io_base + 0x4) needs to be in the function for both cases.

Maintain backwards compatibility for "dw-apb-timer-sp" and "dw-apb-timer-osc".

CC Rob Herring <[email protected]>
CC Arnd Bergmann <[email protected]>
Cc Olof Johansson <[email protected]>
CC Jamie Iles <[email protected]>
Cc John Stultz <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Pavel Machek <[email protected]>
Cc Heiko Stuebner <[email protected]>
Cc linux-arm-kernel at lists.infradead.org

v2:
- Maintain backwards compatibility for "dw-apb-timer-sp" and "dw-apb-timer-osc".

---
 drivers/clocksource/dw_apb_timer_of.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/clocksource/dw_apb_timer_of.c +5 -4
index 4cbae4f..72ce4bb 100644
@@ -102,18 +102,17 @@ static void add_clocksource(struct device_node *source_timer)
 	 * timer is found. sched_io_base then points to the current_value
 	 * register of the clocksource timer.
 	 */
-	sched_io_base = iobase + 0x04;
+	sched_io_base = iobase;
 	sched_rate = rate;
 }
 
 static u32 read_sched_clock(void)
 {
-	return __raw_readl(sched_io_base);
+	return ~__raw_readl(sched_io_base + 0x4);
 }
 
 static const struct of_device_id sptimer_ids[] __initconst = {
 	{ .compatible = "picochip,pc3x2-rtc" },
-	{ .compatible = "snps,dw-apb-timer-sp" },
 	{ /* Sentinel */ },
 };
 
@@ -153,4 +152,6 @@ static void __init dw_apb_timer_init(struct device_node *timer)
 	num_called++;
 }
 CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
+CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH v2 2/2 clocksource: dw_apb_timer_of: Fix read_sched_clock

drivers/clocksource/dw_apb_timer_of.c static void add_clocksource(struct device_node *source_timer) · line 111

Quoted 9 lines · On Thu, Aug 15, 2013 at 1:29 AM, <[email protected]> wrote:
drivers/clocksource/dw_apb_timer_of.c +2 -2
-       sched_io_base = iobase + 0x04;
+       sched_io_base = iobase;
        sched_rate = rate;
 }
 
 static u32 read_sched_clock(void)
 {
-       return __raw_readl(sched_io_base);
+       return ~__raw_readl(sched_io_base + 0x4);

So what about #define what 0x04 is?

#define MY_FOO_REGISTER_OFFSET 0x04

raw_readl(sched_io_base + MY_FOO_REGISTER_OFFSET);

You get the idea.

Yours,
Linus Walleij

#3 lore raw

PATCH v2 2/2 clocksource: dw_apb_timer_of: Fix read_sched_clock

Quoted 12 lines · Linus Walleij

drivers/clocksource/dw_apb_timer_of.c static void add_clocksource(struct device_node *source_timer) · line 111

Quoted 9 lines · On Thu, Aug 15, 2013 at 1:29 AM, <[email protected]> wrote:
drivers/clocksource/dw_apb_timer_of.c +2 -2
-       sched_io_base = iobase + 0x04;
+       sched_io_base = iobase;
        sched_rate = rate;
 }
 
 static u32 read_sched_clock(void)
 {
-       return __raw_readl(sched_io_base);
+       return ~__raw_readl(sched_io_base + 0x4);
Quoted 5 lines

So what about #define what 0x04 is?

#define MY_FOO_REGISTER_OFFSET 0x04

raw_readl(sched_io_base + MY_FOO_REGISTER_OFFSET);

That define is already there, #define APBTMR_N_CURRENT_VALUE 0x04, but it is in .c file, not in header.

Actually I believe I had patch that did that, and it was even applied, but it clashed with same other patches, and was dropped. (It is below, for reference).

Currently, the code _does not work_, and we have three platforms using it. It would be good to solve this now, and polish it later.

Pavel

#4 lore raw

PATCH v2 2/2 clocksource: dw_apb_timer_of: Fix read_sched_clock

Quoted 13 lines · ZY - pavel
Quoted 12 lines · Linus Walleij
Quoted 9 lines · On Thu, Aug 15, 2013 at 1:29 AM, <[email protected]> wrote:
drivers/clocksource/dw_apb_timer_of.c +2 -2
-       sched_io_base = iobase + 0x04;
+       sched_io_base = iobase;
        sched_rate = rate;
 }
 
 static u32 read_sched_clock(void)
 {
-       return __raw_readl(sched_io_base);
+       return ~__raw_readl(sched_io_base + 0x4);
Quoted 8 lines
Quoted 5 lines

So what about #define what 0x04 is?

#define MY_FOO_REGISTER_OFFSET 0x04

raw_readl(sched_io_base + MY_FOO_REGISTER_OFFSET);

That define is already there, #define APBTMR_N_CURRENT_VALUE 0x04, but it is in .c file, not in header.

I'll send a V2 that will address this comment and Stephen Warren's.

Dinh

Quoted 206 lines

Actually I believe I had patch that did that, and it was even applied, but it clashed with same other patches, and was dropped. (It is below, for reference).

Currently, the code _does not work_, and we have three platforms using it. It would be good to solve this now, and polish it later.

Pavel

From pavel at denx.de Tue May 7 22:11:26 2013
Date: Tue, 7 May 2013 22:11:26 +0200
From: Pavel Machek <[email protected]>
To: John Stultz <[email protected]>
Cc: Arnd Bergmann <[email protected]>, tglx at linutronix.de,
Jamie Iles <[email protected]>, dinguyen at altera.com, wd at denx.de, linux-arm-kernel at lists.infradead.org, olof at lixom.net, kernel list <[email protected]>
Subject: Re: dw_apb_timer_of.c: remove parts that were picoxcell-specific
Message-ID: <[email protected]>
References: <[email protected]>
<[email protected]> <[email protected]> <[email protected]> <[email protected]> <[email protected]>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <[email protected]>
User-Agent: Mutt/1.5.20 (2009-06-14)
Status: RO
Content-Length: 4987
Lines: 170

Hi!

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

So I guess it should go through the timekeeping tree...?

I would prefer that, but we can also take it through arm-soc, it doesn't really matter.

I see no response from timekeeping people... so if you could take it, that would be great.

I don't think the original patch ever made it to my inbox.

For some reason, I cced johnstul at us.ibm.com. (I guess get_maintainer.pl? But it seems to behave now.) Anyway, patch is below...

It would be great if you could apply it... Thanks,
Pavel

----

It seems we made a mistake when creating dw_apb_timer_of.c:
picoxcell sched_clock had parts that were not related to dw_apb_timer, yet we moved them to dw_apb_timer_of, and tried to use them on socfpga.

This results in system where user/system time is not measured properly, as demonstrated by

    time dd if=/dev/urandom of=/dev/zero bs=100000 count=100

So this patch switches sched_clock to hardware that exists on both platforms, and adds missing of_node_put() in dw_apb_timer_init().

arch/arm/mach-picoxcell/common.h +0 -2
index 481b42a..237fb3b 100644
@@ -12,6 +12,4 @@
 
 #include <asm/mach/time.h>
 
-extern void dw_apb_timer_init(void);
-
 #endif /* __PICOXCELL_COMMON_H__ */
drivers/clocksource/dw_apb_timer.c +0 -6
index 8c2a35f..460ac99 100644
@@ -21,12 +21,6 @@
 #define APBT_MIN_PERIOD			4
 #define APBT_MIN_DELTA_USEC		200
 
-#define APBTMR_N_LOAD_COUNT		0x00
-#define APBTMR_N_CURRENT_VALUE		0x04
-#define APBTMR_N_CONTROL		0x08
-#define APBTMR_N_EOI			0x0c
-#define APBTMR_N_INT_STATUS		0x10
-
 #define APBTMRS_INT_STATUS		0xa0
 #define APBTMRS_EOI			0xa4
 #define APBTMRS_RAW_INT_STATUS		0xa8
drivers/clocksource/dw_apb_timer_of.c +23 -29
index ab09ed3..0fa3104 100644
@@ -57,6 +57,15 @@ static void add_clockevent(struct device_node *event_timer)
 	dw_apb_clockevent_register(ced);
 }
 
+static void __iomem *sched_io_base;
+
+/* This is actually same as __apbt_read_clocksource(), but with
+   different interface */
+static u32 read_sched_clock_sptimer(void)
+{
+	return ~__raw_readl(sched_io_base + APBTMR_N_CURRENT_VALUE);
+}
+
 static void add_clocksource(struct device_node *source_timer)
 {
 	void __iomem *iobase;
@@ -71,41 +80,27 @@ static void add_clocksource(struct device_node *source_timer)
 
 	dw_apb_clocksource_start(cs);
 	dw_apb_clocksource_register(cs);
-}
 
-static void __iomem *sched_io_base;
-
-static u32 read_sched_clock(void)
-{
-	return __raw_readl(sched_io_base);
+	sched_io_base = iobase;
+	setup_sched_clock(read_sched_clock_sptimer, 32, rate);
 }
 
-static const struct of_device_id sptimer_ids[] __initconst = {
-	{ .compatible = "picochip,pc3x2-rtc" },
+static const struct of_device_id osctimer_ids[] __initconst = {
+	{ .compatible = "picochip,pc3x2-timer" },
+	{ .compatible = "snps,dw-apb-timer-osc" },
 	{ .compatible = "snps,dw-apb-timer-sp" },
-	{ /* Sentinel */ },
+	{  /* Sentinel */ },
 };
 
-static void init_sched_clock(void)
-{
-	struct device_node *sched_timer;
-	u32 rate;
-
-	sched_timer = of_find_matching_node(NULL, sptimer_ids);
-	if (!sched_timer)
-		panic("No RTC for sched clock to use");
+/*
+   You don't have to use dw_apb_timer for scheduler clock,
+   this should also work fine on arm:
 
-	timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
-	of_node_put(sched_timer);
+  twd_local_timer_of_register();
+  arch_timer_of_register();                 
+  arch_timer_sched_clock_init();
+*/
 
-	setup_sched_clock(read_sched_clock, 32, rate);
-}
-
-static const struct of_device_id osctimer_ids[] __initconst = {
-	{ .compatible = "picochip,pc3x2-timer" },
-	{ .compatible = "snps,dw-apb-timer-osc" },
-	{},
-};
 
 void __init dw_apb_timer_init(void)
 {
@@ -121,7 +116,6 @@ void __init dw_apb_timer_init(void)
 		panic("No timer for clocksource");
 	add_clocksource(source_timer);
 
+	of_node_put(event_timer);
 	of_node_put(source_timer);
-
-	init_sched_clock();
 }
include/linux/dw_apb_timer.h +6 -0
index dd755ce..a64c987 100644
@@ -17,6 +17,12 @@
 #include <linux/clocksource.h>
 #include <linux/interrupt.h>
 
+#define APBTMR_N_LOAD_COUNT		0x00
+#define APBTMR_N_CURRENT_VALUE		0x04
+#define APBTMR_N_CONTROL		0x08
+#define APBTMR_N_EOI			0x0c
+#define APBTMR_N_INT_STATUS		0x10
+
 #define APBTMRS_REG_SIZE       0x14
 
 struct dw_apb_timer {
Signature · 3 lines
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#5 lore raw

PATCH v2 2/2 clocksource: dw_apb_timer_of: Fix read_sched_clock

Quoted 13 lines · Dinh Nguyen
Quoted 12 lines · ZY - pavel
Quoted 11 lines · Linus Walleij
Quoted 9 lines · On Thu, Aug 15, 2013 at 1:29 AM, <[email protected]> wrote:
drivers/clocksource/dw_apb_timer_of.c +2 -2
-       sched_io_base = iobase + 0x04;
+       sched_io_base = iobase;
        sched_rate = rate;
 }
 
 static u32 read_sched_clock(void)
 {
-       return __raw_readl(sched_io_base);
+       return ~__raw_readl(sched_io_base + 0x4);
Quoted 8 lines
Quoted 7 lines
Quoted 5 lines

So what about #define what 0x04 is?

#define MY_FOO_REGISTER_OFFSET 0x04

raw_readl(sched_io_base + MY_FOO_REGISTER_OFFSET);

That define is already there, #define APBTMR_N_CURRENT_VALUE 0x04, but it is in .c file, not in header.

I'll send a V2 that will address this comment and Stephen Warren's.

Please be sure to CC Daniel Lezcano <[email protected]> on future versions as he's now maintaining the drivers/clocksource directory.

thanks
-john

#6 lore raw

PATCH v2 1/2 ARM: dts: Change dw-apb-timer-osc and dw-apb-timer-sp to just dw-apb-timer

In reply to dinguyen at altera.com
Quoted 8 lines · dinguyen at altera.com

From: Dinh Nguyen <[email protected]>

"dw-apb-timer-osc" and "dw-apb-timer-sp" are the same implementation of the DW APB timer, just fed by different clocks. Thus, deprecate both "dw-apb-timer-osc" and "dw-apb-timer-sp" in lieu of "dw-apb-timer",

Clean up the timer entries for socfpga by removing timer<n> and set the correct clocks for the timers.

Hmm. That sounds like a separate patch. Cleanup isn't the same as adding new DT compatible values...

Documentation/devicetree/bindings/rtc/dw-apb.txt line 5

Quoted 6 lines
Documentation/devicetree/bindings/rtc/dw-apb.txt +2 -1
 
 Required properties:
-- compatible: "snps,dw-apb-timer-sp" or "snps,dw-apb-timer-osc"
+- compatible: "snps,dw-apb-timer-sp" or "snps,dw-apb-timer-osc" <DEPRECATED>
+- compatible: "snps,dw-apb-timer"

It's slightly unclear whether "snps,dw-apb-timer-sp" is deprecated. Also, listing the non-deprecated values first would be a good hint to people which they should use. How about:

compatible: One of:

	"snps,dw-apb-timer"
	"snps,dw-apb-timer-sp" <DEPRECATED>
	"snps,dw-apb-timer-osc" <DEPRECATED>