Skip to contentSkip to conversation

clocksource: sunxi: Timer fixes and cleanup

PATCH Superseded Maxime Ripard 6 participants 36 messages Jun 26, 2013 – Jun 28, 2013 1 message not in the archive

Subsystems (2)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

cover clocksource: sunxi: Timer fixes and cleanup

Hi everyone,

The first timer code we merged when adding support for the A13 some time back was mostly a clean up from the source drop we had, without any documentation. This happened to work, but the code merged in turned out to be far from perfect, and had several flaws.

This patchset hopefully fixes these flaws, and cleanup most of the driver as well, to end up in an almost complete rewrite of it (even though it's not that long).

It also finally adds a clocksource from the free running counter found in the A10/A13 SoCs.

These flaws have all been spotted when trying to add the A31 support, work that is still ongoing, but will hopefully benefit from this patchset as well.

Thanks,
Maxime

Maxime Ripard (8):
clocksource: sun4i: Use the BIT macros where possible
clocksource: sun4i: Add clocksource and sched clock drivers
clocksource: sun4i: Don't forget to enable the clock we use
clocksource: sun4i: Fix the next event code
clocksource: sun4i: Factor out some timer code
clocksource: sun4i: Remove TIMER_SCAL variable
clocksource: sun4i: Cleanup parent clock setup
clocksource: sun4i: Fix bug when switching from periodic to oneshot
modes

 drivers/clocksource/sun4i_timer.c | 107 ++++++++++++++++++++++++++------------
 1 file changed, 75 insertions(+), 32 deletions(-)
Signature · 1 line
1.8.3.1
#1 lore raw

PATCH 1/8 clocksource: sun4i: Use the BIT macros where possible

---
 drivers/clocksource/sun4i_timer.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/clocksource/sun4i_timer.c +4 -4
index d4674e7..bdf34d9 100644
@@ -24,12 +24,12 @@
 #include <linux/of_irq.h>
 
 #define TIMER_IRQ_EN_REG	0x00
-#define TIMER_IRQ_EN(val)		(1 << val)
+#define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
 #define TIMER_CTL_REG(val)	(0x10 * val + 0x10)
-#define TIMER_CTL_ENABLE		(1 << 0)
-#define TIMER_CTL_AUTORELOAD		(1 << 1)
-#define TIMER_CTL_ONESHOT		(1 << 7)
+#define TIMER_CTL_ENABLE		BIT(0)
+#define TIMER_CTL_AUTORELOAD		BIT(1)
+#define TIMER_CTL_ONESHOT		BIT(7)
 #define TIMER_INTVAL_REG(val)	(0x10 * val + 0x14)
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
Signature · 1 line
1.8.3.1
#2 lore raw

PATCH 2/8 clocksource: sun4i: Add clocksource and sched clock drivers

In reply to Maxime Ripard

The A10 and the A13 has a 64 bits free running counter that we can use as a clocksource and a sched clock, that were both not used yet on these platforms.

---
 drivers/clocksource/sun4i_timer.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/clocksource/sun4i_timer.c +27 -0
index bdf34d9..1d2eaa0 100644
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
+#include <asm/sched_clock.h>
+
 #define TIMER_IRQ_EN_REG	0x00
 #define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
@@ -34,6 +36,11 @@
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
 #define TIMER_SCAL		16
+#define TIMER_CNT64_CTL_REG	0xa0
+#define TIMER_CNT64_CTL_CLR		BIT(0)
+#define TIMER_CNT64_CTL_RL		BIT(1)
+#define TIMER_CNT64_LOW_REG	0xa4
+#define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
 
@@ -96,6 +103,20 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
+static u32 sun4i_timer_sched_read(void)
+{
+	u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);
+	writel(reg | TIMER_CNT64_CTL_RL, timer_base + TIMER_CNT64_CTL_REG);
+	while (readl(timer_base + TIMER_CNT64_CTL_REG) & TIMER_CNT64_CTL_REG);
+
+	return readl(timer_base + TIMER_CNT64_LOW_REG);
+}
+
+static cycle_t sun4i_timer_clksrc_read(struct clocksource *c)
+{
+	return sun4i_timer_sched_read();
+}
+
 static void __init sun4i_timer_init(struct device_node *node)
 {
 	unsigned long rate = 0;
@@ -117,6 +138,12 @@ static void __init sun4i_timer_init(struct device_node *node)
 
 	rate = clk_get_rate(clk);
 
+	writel(TIMER_CNT64_CTL_CLR, timer_base + TIMER_CNT64_CTL_REG);
+	setup_sched_clock(sun4i_timer_sched_read, 32, clk_get_rate(clk));
+	clocksource_mmio_init(timer_base + TIMER_CNT64_LOW_REG, node->name,
+			      clk_get_rate(clk), 300, 32,
+			      sun4i_timer_clksrc_read);
+
 	writel(rate / (TIMER_SCAL * HZ),
 	       timer_base + TIMER_INTVAL_REG(0));
 
Signature · 1 line
1.8.3.1
#3 lore raw

Re: [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Quoted 35 lines · Maxime Ripard

The A10 and the A13 has a 64 bits free running counter that we can use as a clocksource and a sched clock, that were both not used yet on these platforms.

---
 drivers/clocksource/sun4i_timer.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/clocksource/sun4i_timer.c +7 -0
index bdf34d9..1d2eaa0 100644
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
+#include <asm/sched_clock.h>
+
 #define TIMER_IRQ_EN_REG	0x00
 #define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
@@ -34,6 +36,11 @@
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
 #define TIMER_SCAL		16
+#define TIMER_CNT64_CTL_REG	0xa0
+#define TIMER_CNT64_CTL_CLR		BIT(0)
+#define TIMER_CNT64_CTL_RL		BIT(1)
+#define TIMER_CNT64_LOW_REG	0xa4
+#define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
 

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 110

Quoted 8 lines
drivers/clocksource/sun4i_timer.c +5 -0
@@ -96,6 +103,20 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
+static u32 sun4i_timer_sched_read(void)
+{
+	u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);
+	writel(reg | TIMER_CNT64_CTL_RL, timer_base + TIMER_CNT64_CTL_REG);
+	while (readl(timer_base + TIMER_CNT64_CTL_REG) & TIMER_CNT64_CTL_REG);

Isn't a cpu_relax missing here ?

Quoted 13 lines
drivers/clocksource/sun4i_timer.c +9 -0
+
+	return readl(timer_base + TIMER_CNT64_LOW_REG);
+}
+
+static cycle_t sun4i_timer_clksrc_read(struct clocksource *c)
+{
+	return sun4i_timer_sched_read();
+}
+
 static void __init sun4i_timer_init(struct device_node *node)
 {
 	unsigned long rate = 0;

drivers/clocksource/sun4i_timer.c static void __init sun4i_timer_init(struct device_node *node) · line 147

Quoted 10 lines
drivers/clocksource/sun4i_timer.c +6 -0
@@ -117,6 +138,12 @@ static void __init sun4i_timer_init(struct device_node *node)
 
 	rate = clk_get_rate(clk);
 
+	writel(TIMER_CNT64_CTL_CLR, timer_base + TIMER_CNT64_CTL_REG);
+	setup_sched_clock(sun4i_timer_sched_read, 32, clk_get_rate(clk));
+	clocksource_mmio_init(timer_base + TIMER_CNT64_LOW_REG, node->name,
+			      clk_get_rate(clk), 300, 32,
+			      sun4i_timer_clksrc_read);
+
 	writel(rate / (TIMER_SCAL * HZ),

DIV_ROUND_CLOSEST(rate, (TIMER_SCAL * HZ)), ?

Quoted 1 line
drivers/clocksource/sun4i_timer.c +0 -0
 	       timer_base + TIMER_INTVAL_REG(0));
Signature · 5 lines
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#4 lore raw

Re: [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Hi Daniel,

Quoted 39 lines · Daniel Lezcano
Quoted 38 lines · Maxime Ripard

The A10 and the A13 has a 64 bits free running counter that we can use as a clocksource and a sched clock, that were both not used yet on these platforms.

---
 drivers/clocksource/sun4i_timer.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/clocksource/sun4i_timer.c +7 -0
index bdf34d9..1d2eaa0 100644
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
+#include <asm/sched_clock.h>
+
 #define TIMER_IRQ_EN_REG	0x00
 #define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
@@ -34,6 +36,11 @@
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
 #define TIMER_SCAL		16
+#define TIMER_CNT64_CTL_REG	0xa0
+#define TIMER_CNT64_CTL_CLR		BIT(0)
+#define TIMER_CNT64_CTL_RL		BIT(1)
+#define TIMER_CNT64_LOW_REG	0xa4
+#define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
 
@@ -96,6 +103,20 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
Quoted 7 lines

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 110

Quoted 5 lines
drivers/clocksource/sun4i_timer.c +5 -0
+static u32 sun4i_timer_sched_read(void)
+{
+	u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);
+	writel(reg | TIMER_CNT64_CTL_RL, timer_base + TIMER_CNT64_CTL_REG);
+	while (readl(timer_base + TIMER_CNT64_CTL_REG) & TIMER_CNT64_CTL_REG);

Isn't a cpu_relax missing here ?

Right.

The AND is wrong as well, it should be TIMER_CNT64_CTL_RL, not the reg offset.

Quoted 10 lines

drivers/clocksource/sun4i_timer.c static void __init sun4i_timer_init(struct device_node *node) · line 147

Quoted 8 lines
drivers/clocksource/sun4i_timer.c +6 -0
+	writel(TIMER_CNT64_CTL_CLR, timer_base + TIMER_CNT64_CTL_REG);
+	setup_sched_clock(sun4i_timer_sched_read, 32, clk_get_rate(clk));
+	clocksource_mmio_init(timer_base + TIMER_CNT64_LOW_REG, node->name,
+			      clk_get_rate(clk), 300, 32,
+			      sun4i_timer_clksrc_read);
+
 	writel(rate / (TIMER_SCAL * HZ),

DIV_ROUND_CLOSEST(rate, (TIMER_SCAL * HZ)), ?

It's actually fixed in a later patch, but yes.

Thanks!
Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130627/b138f901/attachment.sig>
#5 lore raw

Re: [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

In reply to Maxime Ripard

Hi Maxime,

Quoted 14 lines · Maxime Ripard

The A10 and the A13 has a 64 bits free running counter that we can use as a clocksource and a sched clock, that were both not used yet on these platforms.

---
 drivers/clocksource/sun4i_timer.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/clocksource/sun4i_timer.c +0 -0
index bdf34d9..1d2eaa0 100644

drivers/clocksource/sun4i_timer.c line 26

Quoted 4 lines
drivers/clocksource/sun4i_timer.c +1 -0
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
+#include <asm/sched_clock.h>

In the tip.git tree (and -next) this header is moved to <linux/sched_clock.h> in 38ff87f77a (sched_clock: Make ARM's sched_clock generic for all architectures).

Quoted 17 lines
drivers/clocksource/sun4i_timer.c +6 -0
+
 #define TIMER_IRQ_EN_REG	0x00
 #define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
@@ -34,6 +36,11 @@
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
 #define TIMER_SCAL		16
+#define TIMER_CNT64_CTL_REG	0xa0
+#define TIMER_CNT64_CTL_CLR		BIT(0)
+#define TIMER_CNT64_CTL_RL		BIT(1)
+#define TIMER_CNT64_LOW_REG	0xa4
+#define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
 

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 106

Quoted 4 lines
drivers/clocksource/sun4i_timer.c +1 -0
@@ -96,6 +103,20 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
+static u32 sun4i_timer_sched_read(void)

You commit message mentions "64 bits free running counter", but this one only returns 32 bit.

baruch

Quoted 29 lines
drivers/clocksource/sun4i_timer.c +19 -0
+{
+	u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);
+	writel(reg | TIMER_CNT64_CTL_RL, timer_base + TIMER_CNT64_CTL_REG);
+	while (readl(timer_base + TIMER_CNT64_CTL_REG) & TIMER_CNT64_CTL_REG);
+
+	return readl(timer_base + TIMER_CNT64_LOW_REG);
+}
+
+static cycle_t sun4i_timer_clksrc_read(struct clocksource *c)
+{
+	return sun4i_timer_sched_read();
+}
+
 static void __init sun4i_timer_init(struct device_node *node)
 {
 	unsigned long rate = 0;
@@ -117,6 +138,12 @@ static void __init sun4i_timer_init(struct device_node *node)
 
 	rate = clk_get_rate(clk);
 
+	writel(TIMER_CNT64_CTL_CLR, timer_base + TIMER_CNT64_CTL_REG);
+	setup_sched_clock(sun4i_timer_sched_read, 32, clk_get_rate(clk));
+	clocksource_mmio_init(timer_base + TIMER_CNT64_LOW_REG, node->name,
+			      clk_get_rate(clk), 300, 32,
+			      sun4i_timer_clksrc_read);
+
 	writel(rate / (TIMER_SCAL * HZ),
 	       timer_base + TIMER_INTVAL_REG(0));
 
Signature · 3 lines
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
#6 lore raw

Re: [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Hi Baruch,

Quoted 20 lines · Baruch Siach

Hi Maxime,

Quoted 17 lines · Maxime Ripard

The A10 and the A13 has a 64 bits free running counter that we can use as a clocksource and a sched clock, that were both not used yet on these platforms.

---
 drivers/clocksource/sun4i_timer.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/clocksource/sun4i_timer.c +0 -0
index bdf34d9..1d2eaa0 100644
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
Quoted 5 lines

drivers/clocksource/sun4i_timer.c line 26

Quoted 1 line
drivers/clocksource/sun4i_timer.c +1 -0
+#include <asm/sched_clock.h>

In the tip.git tree (and -next) this header is moved to <linux/sched_clock.h> in 38ff87f77a (sched_clock: Make ARM's sched_clock generic for all architectures).

Ah, good to know. Thanks!

Quoted 16 lines
Quoted 16 lines
drivers/clocksource/sun4i_timer.c +6 -0
+
 #define TIMER_IRQ_EN_REG	0x00
 #define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
@@ -34,6 +36,11 @@
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
 #define TIMER_SCAL		16
+#define TIMER_CNT64_CTL_REG	0xa0
+#define TIMER_CNT64_CTL_CLR		BIT(0)
+#define TIMER_CNT64_CTL_RL		BIT(1)
+#define TIMER_CNT64_LOW_REG	0xa4
+#define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
 
Quoted 8 lines

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 106

Quoted 5 lines
drivers/clocksource/sun4i_timer.c +1 -0
@@ -96,6 +103,20 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
+static u32 sun4i_timer_sched_read(void)

You commit message mentions "64 bits free running counter", but this one only returns 32 bit.

Yeah, the callback setup by setup_sched_clock is supposed to be returning a u32, and clocksource_mmio_init only accepts up to 32 bits as well, so I'm only using the lower 32bits of this 64 bits counter.

I'll amend the commit log to state this.

Thanks!
Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130627/0a28a285/attachment.sig>
#7 lore raw

Re: [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Hi Maxime,

Quoted 4 lines · Maxime Ripard
Quoted 3 lines · Baruch Siach
Quoted 1 line · Maxime Ripard

+static u32 sun4i_timer_sched_read(void)

Quoted 8 lines
Quoted 2 lines

You commit message mentions "64 bits free running counter", but this one only returns 32 bit.

Yeah, the callback setup by setup_sched_clock is supposed to be returning a u32, and clocksource_mmio_init only accepts up to 32 bits as well, so I'm only using the lower 32bits of this 64 bits counter.

I'll amend the commit log to state this.

But using 64 bit counter for sched_clock is much easier that using 32 bit one. You can either wait for the rest of Stephen's patch set
(http://thread.gmane.org/gmane.linux.ports.arm.msm/4092) before adding 64 bit, or you can just make the trivial change to the now generic sched_clock code.

baruch

Signature · 3 lines
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
#8 lore raw

Re: [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Hi Baruch,

Quoted 8 lines · Baruch Siach
Quoted 7 lines · Maxime Ripard
Quoted 5 lines · Baruch Siach
Quoted 1 line · Maxime Ripard

+static u32 sun4i_timer_sched_read(void)

You commit message mentions "64 bits free running counter", but this one only returns 32 bit.

Quoted 7 lines
Quoted 5 lines

Yeah, the callback setup by setup_sched_clock is supposed to be returning a u32, and clocksource_mmio_init only accepts up to 32 bits as well, so I'm only using the lower 32bits of this 64 bits counter.

I'll amend the commit log to state this.

But using 64 bit counter for sched_clock is much easier that using 32 bit one.

Easier in what aspect? Both API looks similar.

Quoted 3 lines

You can either wait for the rest of Stephen's patch set
(http://thread.gmane.org/gmane.linux.ports.arm.msm/4092) before adding 64 bit, or you can just make the trivial change to the now generic sched_clock code.

I'll wait for the Stephen's patches to be merged then, and add support for 64bits counters to clocksource_mmio_init.

Thanks!
Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130627/7719f97c/attachment.sig>
#9 lore raw

Re: [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Hi Maxime,

Quoted 13 lines · Maxime Ripard
Quoted 12 lines · Baruch Siach
Quoted 11 lines · Maxime Ripard
Quoted 5 lines · Baruch Siach
Quoted 1 line · Maxime Ripard

+static u32 sun4i_timer_sched_read(void)

You commit message mentions "64 bits free running counter", but this one only returns 32 bit.

Yeah, the callback setup by setup_sched_clock is supposed to be returning a u32, and clocksource_mmio_init only accepts up to 32 bits as well, so I'm only using the lower 32bits of this 64 bits counter.

Quoted 5 lines
Quoted 3 lines
Quoted 1 line

I'll amend the commit log to state this.

But using 64 bit counter for sched_clock is much easier that using 32 bit one.

Easier in what aspect? Both API looks similar.

You can just implement your own simple sched_clock() that just returns the current value of this 64 bit counter, and do away with all the tricky code in kernel/time/sched_clock.c (in tip.git) that is needed to make the 32 -> 64 extension safe. This is not compatible with multi-platform kernel, though.

Quoted 7 lines
Quoted 4 lines

You can either wait for the rest of Stephen's patch set
(http://thread.gmane.org/gmane.linux.ports.arm.msm/4092) before adding 64 bit, or you can just make the trivial change to the now generic sched_clock code.

I'll wait for the Stephen's patches to be merged then, and add support for 64bits counters to clocksource_mmio_init.

Sound reasonable.

baruch

Signature · 3 lines
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
#10 lore raw

Re: [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Quoted 18 lines · Baruch Siach

Hi Maxime,

Quoted 15 lines · Maxime Ripard
Quoted 14 lines · Baruch Siach
Quoted 12 lines · Maxime Ripard
Quoted 5 lines · Baruch Siach
Quoted 1 line · Maxime Ripard

+static u32 sun4i_timer_sched_read(void)

You commit message mentions "64 bits free running counter", but this one only returns 32 bit.

Yeah, the callback setup by setup_sched_clock is supposed to be returning a u32, and clocksource_mmio_init only accepts up to 32 bits as well, so I'm only using the lower 32bits of this 64 bits counter.

I'll amend the commit log to state this.

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

But using 64 bit counter for sched_clock is much easier that using 32 bit one.

Easier in what aspect? Both API looks similar.

You can just implement your own simple sched_clock() that just returns the current value of this 64 bit counter, and do away with all the tricky code in kernel/time/sched_clock.c (in tip.git) that is needed to make the 32 -> 64 extension safe. This is not compatible with multi-platform kernel, though.

Which is a deal-breaker for us.

I'll use the setup_sched_clock_64 introduced by Stephen then :)

Thanks for the time you took to review these patches!

Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130627/4b45de4e/attachment.sig>
#11 lore raw

Re: [linux-sunxi] [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

In reply to Maxime Ripard
Quoted 35 lines · On Wed, 26 Jun 2013 23:16:55 +0200 Maxime Ripard…

The A10 and the A13 has a 64 bits free running counter that we can use as a clocksource and a sched clock, that were both not used yet on these platforms.

---
 drivers/clocksource/sun4i_timer.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/clocksource/sun4i_timer.c +7 -0
index bdf34d9..1d2eaa0 100644
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
+#include <asm/sched_clock.h>
+
 #define TIMER_IRQ_EN_REG	0x00
 #define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
@@ -34,6 +36,11 @@
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
 #define TIMER_SCAL		16
+#define TIMER_CNT64_CTL_REG	0xa0
+#define TIMER_CNT64_CTL_CLR		BIT(0)
+#define TIMER_CNT64_CTL_RL		BIT(1)
+#define TIMER_CNT64_LOW_REG	0xa4
+#define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
 

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 108

Quoted 6 lines
drivers/clocksource/sun4i_timer.c +3 -0
@@ -96,6 +103,20 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
+static u32 sun4i_timer_sched_read(void)
+{
+	u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);

If we can be absolutely sure that nothing else may ever change the TIMER_CNT64_CTL_REG, then its default value can be probably cached instead of doing expensive read from the hardware register each time?

The gettimeofday() abusers will feel a bit less pain. ARM does not currently enjoy the VDSO optimized gettimeofday, so the software which has been only tested on x86 may get a nasty surprise (an order of magnitude higher gettimeofday overhead).

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 110

Quoted 2 lines
drivers/clocksource/sun4i_timer.c +2 -0
+	writel(reg | TIMER_CNT64_CTL_RL, timer_base + TIMER_CNT64_CTL_REG);
+	while (readl(timer_base + TIMER_CNT64_CTL_REG) & TIMER_CNT64_CTL_REG);

Some may think that this particular loop looks like a performance bottleneck, but it is very rarely run for more than one iteration. In fact, most of the time it just happens to be a single HW register read.

Quoted 25 lines
drivers/clocksource/sun4i_timer.c +15 -0
+
+	return readl(timer_base + TIMER_CNT64_LOW_REG);
+}
+
+static cycle_t sun4i_timer_clksrc_read(struct clocksource *c)
+{
+	return sun4i_timer_sched_read();
+}
+
 static void __init sun4i_timer_init(struct device_node *node)
 {
 	unsigned long rate = 0;
@@ -117,6 +138,12 @@ static void __init sun4i_timer_init(struct device_node *node)
 
 	rate = clk_get_rate(clk);
 
+	writel(TIMER_CNT64_CTL_CLR, timer_base + TIMER_CNT64_CTL_REG);
+	setup_sched_clock(sun4i_timer_sched_read, 32, clk_get_rate(clk));
+	clocksource_mmio_init(timer_base + TIMER_CNT64_LOW_REG, node->name,
+			      clk_get_rate(clk), 300, 32,
+			      sun4i_timer_clksrc_read);
+
 	writel(rate / (TIMER_SCAL * HZ),
 	       timer_base + TIMER_INTVAL_REG(0));
 
Signature · 2 lines
Best regards,
Siarhei Siamashka
#12 lore raw

Re: [linux-sunxi] [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Hi Siarhei,

Quoted 41 lines · Siarhei Siamashka
Quoted 38 lines · On Wed, 26 Jun 2013 23:16:55 +0200 Maxime Ripard…

The A10 and the A13 has a 64 bits free running counter that we can use as a clocksource and a sched clock, that were both not used yet on these platforms.

---
 drivers/clocksource/sun4i_timer.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/clocksource/sun4i_timer.c +7 -0
index bdf34d9..1d2eaa0 100644
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
+#include <asm/sched_clock.h>
+
 #define TIMER_IRQ_EN_REG	0x00
 #define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
@@ -34,6 +36,11 @@
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
 #define TIMER_SCAL		16
+#define TIMER_CNT64_CTL_REG	0xa0
+#define TIMER_CNT64_CTL_CLR		BIT(0)
+#define TIMER_CNT64_CTL_RL		BIT(1)
+#define TIMER_CNT64_LOW_REG	0xa4
+#define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
 
@@ -96,6 +103,20 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
Quoted 8 lines

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 108

Quoted 3 lines
drivers/clocksource/sun4i_timer.c +3 -0
+static u32 sun4i_timer_sched_read(void)
+{
+	u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);

If we can be absolutely sure that nothing else may ever change the TIMER_CNT64_CTL_REG, then its default value can be probably cached instead of doing expensive read from the hardware register each time?

Since it's a free-running counter, its value will always change, so the caching will bring no additions at all, right?

Quoted 5 lines

The gettimeofday() abusers will feel a bit less pain. ARM does not currently enjoy the VDSO optimized gettimeofday, so the software which has been only tested on x86 may get a nasty surprise (an order of magnitude higher gettimeofday overhead).

Quoted 7 lines

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 110

Quoted 2 lines
drivers/clocksource/sun4i_timer.c +2 -0
+	writel(reg | TIMER_CNT64_CTL_RL, timer_base + TIMER_CNT64_CTL_REG);
+	while (readl(timer_base + TIMER_CNT64_CTL_REG) & TIMER_CNT64_CTL_REG);

Some may think that this particular loop looks like a performance bottleneck, but it is very rarely run for more than one iteration. In fact, most of the time it just happens to be a single HW register read.

Thanks for your insight on this.

It does make me more eager to merge the simpler approach first, and then try to take some shortcuts if needed and safe enough.

Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130627/046606b3/attachment.sig>
#13 lore raw

Re: [linux-sunxi] [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Quoted 53 lines · On Thu, 27 Jun 2013 19:02:28 +0200 Maxime Ripard…

Hi Siarhei,

Quoted 41 lines · Siarhei Siamashka
Quoted 38 lines · On Wed, 26 Jun 2013 23:16:55 +0200 Maxime Ripard…

The A10 and the A13 has a 64 bits free running counter that we can use as a clocksource and a sched clock, that were both not used yet on these platforms.

---
 drivers/clocksource/sun4i_timer.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
drivers/clocksource/sun4i_timer.c +7 -0
index bdf34d9..1d2eaa0 100644
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
+#include <asm/sched_clock.h>
+
 #define TIMER_IRQ_EN_REG	0x00
 #define TIMER_IRQ_EN(val)		BIT(val)
 #define TIMER_IRQ_ST_REG	0x04
@@ -34,6 +36,11 @@
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
 #define TIMER_SCAL		16
+#define TIMER_CNT64_CTL_REG	0xa0
+#define TIMER_CNT64_CTL_CLR		BIT(0)
+#define TIMER_CNT64_CTL_RL		BIT(1)
+#define TIMER_CNT64_LOW_REG	0xa4
+#define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
 
@@ -96,6 +103,20 @@ static struct irqaction sun4i_timer_irq = {
 	.dev_id = &sun4i_clockevent,
 };
 
Quoted 8 lines

drivers/clocksource/sun4i_timer.c static struct irqaction sun4i_timer_irq = { · line 108

Quoted 3 lines
drivers/clocksource/sun4i_timer.c +3 -0
+static u32 sun4i_timer_sched_read(void)
+{
+	u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);

If we can be absolutely sure that nothing else may ever change the TIMER_CNT64_CTL_REG, then its default value can be probably cached instead of doing expensive read from the hardware register each time?

Quoted 2 lines

Since it's a free-running counter, its value will always change, so the caching will bring no additions at all, right?

Sorry, 'caching' was not a very good description for something that is already a compile time constant. I mean just replace

    u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);

with

    u32 reg = TIMER_CNT64_CTL_CLR;

Because we know that the TIMER_CNT64_CTL_REG is already supposed to have the default TIMER_CNT64_CTL_CLR value (initialized in the 'sun4i_timer_init' function) between calls to 'sun4i_timer_sched_read'. Inside of 'sun4i_timer_sched_read' we set an extra TIMER_CNT64_CTL_RL bit in this register, but wait until it clears, effectively reverting TIMER_CNT64_CTL_REG register back to the default TIMER_CNT64_CTL_CLR value.

Removing this extra HW register read can save roughly a hundred of CPU cycles here and provide a ~10% overall improvement for gettimeofday (these estimates are based on the earlier benchmarks done with the Allwinner 3.4 kernel).

Or maybe I'm overlooking something?

Signature · 2 lines
Best regards,
Siarhei Siamashka
#14 lore raw

Re: [linux-sunxi] [PATCH 2/8] clocksource: sun4i: Add clocksource and sched clock drivers

Hi Siarhei,

Quoted 25 lines
Quoted 7 lines
Quoted 4 lines

If we can be absolutely sure that nothing else may ever change the TIMER_CNT64_CTL_REG, then its default value can be probably cached instead of doing expensive read from the hardware register each time?

Since it's a free-running counter, its value will always change, so the caching will bring no additions at all, right?

Sorry, 'caching' was not a very good description for something that is already a compile time constant. I mean just replace

    u32 reg = readl(timer_base + TIMER_CNT64_CTL_REG);

with

    u32 reg = TIMER_CNT64_CTL_CLR;

Because we know that the TIMER_CNT64_CTL_REG is already supposed to have the default TIMER_CNT64_CTL_CLR value (initialized in the 'sun4i_timer_init' function) between calls to 'sun4i_timer_sched_read'. Inside of 'sun4i_timer_sched_read' we set an extra TIMER_CNT64_CTL_RL bit in this register, but wait until it clears, effectively reverting TIMER_CNT64_CTL_REG register back to the default TIMER_CNT64_CTL_CLR value.

Quoted 6 lines

Removing this extra HW register read can save roughly a hundred of CPU cycles here and provide a ~10% overall improvement for gettimeofday (these estimates are based on the earlier benchmarks done with the Allwinner 3.4 kernel).

Or maybe I'm overlooking something?

Ah, I get what you mean now. We don't even need to bother about TIMER_CNT64_CTL_CLR now, since it's suppose to be cleared once the counter is reset.

However, I'd very much prefer to take the safer approach for now, and try to optimise afterwards.

Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130628/844d3b16/attachment.sig>
#15 lore raw

PATCH 3/8 clocksource: sun4i: Don't forget to enable the clock we use

In reply to Maxime Ripard

Even if in our case, this clock was non-gatable, used as a parent clock for several IPs, it still is a good idea to enable it.

---
 drivers/clocksource/sun4i_timer.c | 1 +
 1 file changed, 1 insertion(+)
drivers/clocksource/sun4i_timer.c +1 -0
index 1d2eaa0..8bd66df 100644
@@ -135,6 +135,7 @@ static void __init sun4i_timer_init(struct device_node *node)
 	clk = of_clk_get(node, 0);
 	if (IS_ERR(clk))
 		panic("Can't get timer clock");
+	clk_prepare_enable(clk);
 
 	rate = clk_get_rate(clk);
 
Signature · 1 line
1.8.3.1
#16 lore raw

PATCH 4/8 clocksource: sun4i: Fix the next event code

In reply to Maxime Ripard

The next_event logic was setting the next interval to fire in the current timer value instead of the interval value register, which is obviously wrong. Plus the logic to set the actual value was wrong as well, so this code has always been broken.

---
 drivers/clocksource/sun4i_timer.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/clocksource/sun4i_timer.c +9 -3
index 8bd66df..032e504 100644
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/clockchips.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqreturn.h>
@@ -69,9 +70,14 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode,
 static int sun4i_clkevt_next_event(unsigned long evt,
 				   struct clock_event_device *unused)
 {
-	u32 u = readl(timer_base + TIMER_CTL_REG(0));
-	writel(evt, timer_base + TIMER_CNTVAL_REG(0));
-	writel(u | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD,
+	u32 val = readl(timer_base + TIMER_CTL_REG(0));
+	writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0));
+	udelay(1);
+
+	writel(evt, timer_base + TIMER_INTVAL_REG(0));
+
+	val = readl(timer_base + TIMER_CTL_REG(0));
+	writel(val | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD,
 	       timer_base + TIMER_CTL_REG(0));
 
 	return 0;
Signature · 1 line
1.8.3.1
#17 lore raw

PATCH 5/8 clocksource: sun4i: Factor out some timer code

In reply to Maxime Ripard

The set_next_event and set_mode callbacks share a lot of common code we can easily factor to avoid duplication and mistakes.

---
 drivers/clocksource/sun4i_timer.c | 48 ++++++++++++++++++++++++++-------------
 1 file changed, 32 insertions(+), 16 deletions(-)
drivers/clocksource/sun4i_timer.c +32 -16
index 032e504..7f3b248 100644
@@ -45,24 +45,46 @@
 
 static void __iomem *timer_base;
 
+static void sun4i_clkevt_time_stop(void)
+{
+	u32 val = readl(timer_base + TIMER_CTL_REG(0));
+	writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0));
+	udelay(1);
+}
+
+static void sun4i_clkevt_time_setup(unsigned long delay)
+{
+	writel(delay, timer_base + TIMER_INTVAL_REG(0));
+}
+
+static void sun4i_clkevt_time_start(bool periodic)
+{
+	u32 val = readl(timer_base + TIMER_CTL_REG(0));
+
+	if (periodic)
+		val &= ~TIMER_CTL_ONESHOT;
+	else
+		val |= TIMER_CTL_ONESHOT;
+
+	writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0));
+}
+
 static void sun4i_clkevt_mode(enum clock_event_mode mode,
 			      struct clock_event_device *clk)
 {
-	u32 u = readl(timer_base + TIMER_CTL_REG(0));
-
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
-		u &= ~(TIMER_CTL_ONESHOT);
-		writel(u | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0));
+		sun4i_clkevt_time_stop();
+		sun4i_clkevt_time_start(true);
 		break;
-
 	case CLOCK_EVT_MODE_ONESHOT:
-		writel(u | TIMER_CTL_ONESHOT, timer_base + TIMER_CTL_REG(0));
+		sun4i_clkevt_time_stop();
+		sun4i_clkevt_time_start(false);
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	default:
-		writel(u & ~(TIMER_CTL_ENABLE), timer_base + TIMER_CTL_REG(0));
+		sun4i_clkevt_time_stop();
 		break;
 	}
 }
@@ -70,15 +92,9 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode,
 static int sun4i_clkevt_next_event(unsigned long evt,
 				   struct clock_event_device *unused)
 {
-	u32 val = readl(timer_base + TIMER_CTL_REG(0));
-	writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0));
-	udelay(1);
-
-	writel(evt, timer_base + TIMER_INTVAL_REG(0));
-
-	val = readl(timer_base + TIMER_CTL_REG(0));
-	writel(val | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD,
-	       timer_base + TIMER_CTL_REG(0));
+	sun4i_clkevt_time_stop();
+	sun4i_clkevt_time_setup(evt);
+	sun4i_clkevt_time_start(false);
 
 	return 0;
 }
Signature · 1 line
1.8.3.1
#18 lore raw

PATCH 6/8 clocksource: sun4i: Remove TIMER_SCAL variable

In reply to Maxime Ripard

The prescaler is only used when using the internal low frequency oscillator (at 32kHz). Since we're using the higher frequency oscillator at 24MHz, we can just remove it.

---
 drivers/clocksource/sun4i_timer.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/clocksource/sun4i_timer.c +3 -7
index 7f3b248..912d3e0 100644
@@ -36,7 +36,6 @@
 #define TIMER_INTVAL_REG(val)	(0x10 * val + 0x14)
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
 
-#define TIMER_SCAL		16
 #define TIMER_CNT64_CTL_REG	0xa0
 #define TIMER_CNT64_CTL_CLR		BIT(0)
 #define TIMER_CNT64_CTL_RL		BIT(1)
@@ -141,7 +140,6 @@ static cycle_t sun4i_timer_clksrc_read(struct clocksource *c)
 
 static void __init sun4i_timer_init(struct device_node *node)
 {
-	unsigned long rate = 0;
 	struct clk *clk;
 	int ret, irq;
 	u32 val;
@@ -159,15 +157,13 @@ static void __init sun4i_timer_init(struct device_node *node)
 		panic("Can't get timer clock");
 	clk_prepare_enable(clk);
 
-	rate = clk_get_rate(clk);
-
 	writel(TIMER_CNT64_CTL_CLR, timer_base + TIMER_CNT64_CTL_REG);
 	setup_sched_clock(sun4i_timer_sched_read, 32, clk_get_rate(clk));
 	clocksource_mmio_init(timer_base + TIMER_CNT64_LOW_REG, node->name,
 			      clk_get_rate(clk), 300, 32,
 			      sun4i_timer_clksrc_read);
 
-	writel(rate / (TIMER_SCAL * HZ),
+	writel(clk_get_rate(clk) / HZ,
 	       timer_base + TIMER_INTVAL_REG(0));
 
 	/* set clock source to HOSC, 16 pre-division */
@@ -191,8 +187,8 @@ static void __init sun4i_timer_init(struct device_node *node)
 
 	sun4i_clockevent.cpumask = cpumask_of(0);
 
-	clockevents_config_and_register(&sun4i_clockevent, rate / TIMER_SCAL,
-					0x1, 0xff);
+	clockevents_config_and_register(&sun4i_clockevent, clk_get_rate(clk),
+					0x1, 0xffffffff);
 }
 CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer",
 		       sun4i_timer_init);
Signature · 1 line
1.8.3.1
#19 lore raw

PATCH 7/8 clocksource: sun4i: Cleanup parent clock setup

In reply to Maxime Ripard

The current bring-up code for the timer was overly complicated. The only thing we need is actually which clock we want to use as source and that's pretty much all. Let's keep it that way.

---
 drivers/clocksource/sun4i_timer.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)
drivers/clocksource/sun4i_timer.c +5 -10
index 912d3e0..98e38a6 100644
@@ -32,6 +32,9 @@
 #define TIMER_CTL_REG(val)	(0x10 * val + 0x10)
 #define TIMER_CTL_ENABLE		BIT(0)
 #define TIMER_CTL_AUTORELOAD		BIT(1)
+#define TIMER_CTL_CLK_SRC(val)		(((val) & 0x3) << 2)
+#define TIMER_CTL_CLK_SRC_OSC24M		(1)
+#define TIMER_CTL_CLK_PRES(val)		(((val) & 0x7) << 4)
 #define TIMER_CTL_ONESHOT		BIT(7)
 #define TIMER_INTVAL_REG(val)	(0x10 * val + 0x14)
 #define TIMER_CNTVAL_REG(val)	(0x10 * val + 0x18)
@@ -166,16 +169,8 @@ static void __init sun4i_timer_init(struct device_node *node)
 	writel(clk_get_rate(clk) / HZ,
 	       timer_base + TIMER_INTVAL_REG(0));
 
-	/* set clock source to HOSC, 16 pre-division */
-	val = readl(timer_base + TIMER_CTL_REG(0));
-	val &= ~(0x07 << 4);
-	val &= ~(0x03 << 2);
-	val |= (4 << 4) | (1 << 2);
-	writel(val, timer_base + TIMER_CTL_REG(0));
-
-	/* set mode to auto reload */
-	val = readl(timer_base + TIMER_CTL_REG(0));
-	writel(val | TIMER_CTL_AUTORELOAD, timer_base + TIMER_CTL_REG(0));
+	writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M) | TIMER_CTL_AUTORELOAD,
+	       timer_base + TIMER_CTL_REG(0));
 
 	ret = setup_irq(irq, &sun4i_timer_irq);
 	if (ret)
Signature · 1 line
1.8.3.1
#20 lore raw

PATCH 8/8 clocksource: sun4i: Fix bug when switching from periodic to oneshot modes

In reply to Maxime Ripard

The interval was firing at was set up at probe time, and only changed in the set_next_event, and never changed back, which is not really what is expected.

When enabling the periodic mode, now set an interval to tick every jiffy.

---
 drivers/clocksource/sun4i_timer.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/clocksource/sun4i_timer.c +6 -4
index 98e38a6..b7e1f9e 100644
@@ -46,6 +46,7 @@
 #define TIMER_CNT64_HIGH_REG	0xa8
 
 static void __iomem *timer_base;
+static u32 ticks_per_jiffy;
 
 static void sun4i_clkevt_time_stop(void)
 {
@@ -68,7 +69,8 @@ static void sun4i_clkevt_time_start(bool periodic)
 	else
 		val |= TIMER_CTL_ONESHOT;
 
-	writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0));
+	writel(val | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD,
+	       timer_base + TIMER_CTL_REG(0));
 }
 
 static void sun4i_clkevt_mode(enum clock_event_mode mode,
@@ -77,6 +79,7 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode,
 	switch (mode) {
 	case CLOCK_EVT_MODE_PERIODIC:
 		sun4i_clkevt_time_stop();
+		sun4i_clkevt_time_setup(ticks_per_jiffy);
 		sun4i_clkevt_time_start(true);
 		break;
 	case CLOCK_EVT_MODE_ONESHOT:
@@ -166,10 +169,9 @@ static void __init sun4i_timer_init(struct device_node *node)
 			      clk_get_rate(clk), 300, 32,
 			      sun4i_timer_clksrc_read);
 
-	writel(clk_get_rate(clk) / HZ,
-	       timer_base + TIMER_INTVAL_REG(0));
+	ticks_per_jiffy = DIV_ROUND_UP(clk_get_rate(clk), HZ);
 
-	writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M) | TIMER_CTL_AUTORELOAD,
+	writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
 	       timer_base + TIMER_CTL_REG(0));
 
 	ret = setup_irq(irq, &sun4i_timer_irq);
Signature · 1 line
1.8.3.1
#21 lore raw
In reply to Maxime Ripard

Hi,

Quoted 2 lines · Maxime Ripard

Hi everyone,

<snip>

Quoted 2 lines

It also finally adds a clocksource from the free running counter found in the A10/A13 SoCs.

Hmm, have you benchmarked this? There have been reports from linux-sunxi kernel users (xbmc project) that the waiting for the latch is quite slow. Note we don't have anything better yet in the linux-sunxi kernel.

Regards,

Hans

#22 lore raw
Quoted 6 lines · Hans de Goede

Hi,

Quoted 2 lines · Maxime Ripard

Hi everyone,

Quoted 8 lines

<snip>

Quoted 2 lines

It also finally adds a clocksource from the free running counter found in the A10/A13 SoCs.

Hmm, have you benchmarked this? There have been reports from linux-sunxi kernel users (xbmc project) that the waiting for the latch is quite slow. Note we don't have anything better yet in the linux-sunxi kernel.

No. I didn't.

Do you have any pointers to these discussions?

Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130627/01305c94/attachment.sig>
#23 lore raw

Hi,

Quoted 12 lines · Maxime Ripard
Quoted 11 lines · Hans de Goede

Hi,

Quoted 2 lines · Maxime Ripard

Hi everyone,

<snip>

Quoted 2 lines

It also finally adds a clocksource from the free running counter found in the A10/A13 SoCs.

Quoted 8 lines
Quoted 3 lines

Hmm, have you benchmarked this? There have been reports from linux-sunxi kernel users (xbmc project) that the waiting for the latch is quite slow. Note we don't have anything better yet in the linux-sunxi kernel.

No. I didn't.

Do you have any pointers to these discussions?

The original discussion should be somewhere here:
https://groups.google.com/forum/#!forum/linux-sunxi

But I could not find it (it is probably hidden under an unlogical subject).

Looking at my own notes (a small TODO file), I've
written down that the reporter reports:

-current clocksource can cause us to run with interrupts disabled for 17%
of the time, see "perf top" output

This is with a workload which does a lot of gettimeofday calls.

I notice that unlike the sunxi-3.4 code you don't do any locking, so how do you stop 2 clocksource calls from racing (and thus getting a possible wrong value because of things not being properly latched) ?

Regards,

Hans

#24 lore raw
Quoted 21 lines · Hans de Goede

Hi,

Quoted 18 lines · Maxime Ripard
Quoted 6 lines · Hans de Goede

Hi,

Quoted 2 lines · Maxime Ripard

Hi everyone,

Quoted 8 lines

<snip>

Quoted 2 lines

It also finally adds a clocksource from the free running counter found in the A10/A13 SoCs.

Hmm, have you benchmarked this? There have been reports from linux-sunxi kernel users (xbmc project) that the waiting for the latch is quite slow. Note we don't have anything better yet in the linux-sunxi kernel.

No. I didn't.

Quoted 8 lines
Quoted 2 lines

Do you have any pointers to these discussions?

The original discussion should be somewhere here:
https://groups.google.com/forum/#!forum/linux-sunxi

But I could not find it (it is probably hidden under an unlogical subject).

I searched a bit and it seems to be that discussion:
https://groups.google.com/d/msg/linux-sunxi/gaTDngPT7Is/oeLtWb1N1wIJ

Quoted 8 lines

Looking at my own notes (a small TODO file), I've
written down that the reporter reports:

-current clocksource can cause us to run with interrupts disabled for 17%
of the time, see "perf top" output

This is with a workload which does a lot of gettimeofday calls.

Siarhei however notes that even higher-end SoCs like the exynos5 have similar performances with that regard. So I'm not sure we can do something about it, except what is suggested in the above mail, which looks rather unsafe.

Anyway, like you said, we have no easy other solution, and we lacked such support until now.

So why not merge this code for now, and try to optimise it later if we find it's needed.

Quoted 4 lines

I notice that unlike the sunxi-3.4 code you don't do any locking, so how do you stop 2 clocksource calls from racing (and thus getting a possible wrong value because of things not being properly latched) ?

Hmm, right. I'll add a spinlock.

Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130627/9055044f/attachment.sig>
#25 lore raw

Hi,

Quoted 48 lines · Maxime Ripard
Quoted 21 lines · Hans de Goede

Hi,

Quoted 18 lines · Maxime Ripard
Quoted 6 lines · Hans de Goede

Hi,

Quoted 2 lines · Maxime Ripard

Hi everyone,

Quoted 8 lines

<snip>

Quoted 2 lines

It also finally adds a clocksource from the free running counter found in the A10/A13 SoCs.

Hmm, have you benchmarked this? There have been reports from linux-sunxi kernel users (xbmc project) that the waiting for the latch is quite slow. Note we don't have anything better yet in the linux-sunxi kernel.

No. I didn't.

Quoted 8 lines
Quoted 2 lines

Do you have any pointers to these discussions?

The original discussion should be somewhere here:
https://groups.google.com/forum/#!forum/linux-sunxi

But I could not find it (it is probably hidden under an unlogical subject).

I searched a bit and it seems to be that discussion:
https://groups.google.com/d/msg/linux-sunxi/gaTDngPT7Is/oeLtWb1N1wIJ

Quoted 8 lines

Looking at my own notes (a small TODO file), I've
written down that the reporter reports:

-current clocksource can cause us to run with interrupts disabled for 17%
of the time, see "perf top" output

This is with a workload which does a lot of gettimeofday calls.

Siarhei however notes that even higher-end SoCs like the exynos5 have similar performances with that regard. So I'm not sure we can do something about it, except what is suggested in the above mail, which looks rather unsafe.

Quoted 5 lines

Anyway, like you said, we have no easy other solution, and we lacked such support until now.

So why not merge this code for now, and try to optimise it later if we find it's needed.

That is fine with me, I just wanted to share that this has shown as a bottleneck in some benchmarks in case anyone has a clever idea to fix it ...

Regards,

Hans

#26 lore raw

Hi Hans,

Quoted 8 lines · Hans de Goede
Quoted 8 lines

Siarhei however notes that even higher-end SoCs like the exynos5 have similar performances with that regard. So I'm not sure we can do something about it, except what is suggested in the above mail, which looks rather unsafe.

Anyway, like you said, we have no easy other solution, and we lacked such support until now.

Quoted 6 lines
Quoted 2 lines

So why not merge this code for now, and try to optimise it later if we find it's needed.

That is fine with me, I just wanted to share that this has shown as a bottleneck in some benchmarks in case anyone has a clever idea to fix it ...

And you were right, since I wasn't aware of such discussion.

Thanks!
Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130628/57aa2e25/attachment.sig>
#27 lore raw
In reply to Maxime Ripard
Quoted 7 lines · On Thu, 27 Jun 2013 18:54:36 +0200 Maxime Ripard…
Quoted 4 lines · Hans de Goede

I notice that unlike the sunxi-3.4 code you don't do any locking, so how do you stop 2 clocksource calls from racing (and thus getting a possible wrong value because of things not being properly latched) ?

Hmm, right. I'll add a spinlock.

I think the best would be to ask the Allwinner people (it's good to have them in CC, right?) whether anything wrong can happen because of "things not being properly latched".

The A10 manual from http://free-electrons.com/~maxime/pub/datasheet/
does not seem to contain any details about what bad things may happen if we try to read CNT64_LO_REG while latching is still in progress and CNT64_RL_EN bit in CNT64_CTRL_REG has not changed to zero yet. I can imagine the following possible scenarios:
1. We read either the old stale CNT64_LO_REG value or the new correct value.
2. We read either the old stale CNT64_LO_REG value or the new correct value, or some random garbage.
3. The processor may deadlock, eat your dog, or do some other nasty thing.

In the case of 1, we probably can get away without using any spinlocks?

Signature · 2 lines
Best regards,
Siarhei Siamashka
#28 lore raw

Hi,

Quoted 27 lines · Siarhei Siamashka
Quoted 7 lines · On Thu, 27 Jun 2013 18:54:36 +0200 Maxime Ripard…
Quoted 4 lines · Hans de Goede

I notice that unlike the sunxi-3.4 code you don't do any locking, so how do you stop 2 clocksource calls from racing (and thus getting a possible wrong value because of things not being properly latched) ?

Hmm, right. I'll add a spinlock.

I think the best would be to ask the Allwinner people (it's good to have them in CC, right?) whether anything wrong can happen because of "things not being properly latched".

The A10 manual from http://free-electrons.com/~maxime/pub/datasheet/
does not seem to contain any details about what bad things may happen if we try to read CNT64_LO_REG while latching is still in progress and CNT64_RL_EN bit in CNT64_CTRL_REG has not changed to zero yet. I can imagine the following possible scenarios:
1. We read either the old stale CNT64_LO_REG value or the new correct value.
2. We read either the old stale CNT64_LO_REG value or the new correct value, or some random garbage.
3. The processor may deadlock, eat your dog, or do some other nasty thing.

Quoted 1 line

In the case of 1, we probably can get away without using any spinlocks?

No, because if ie CNT64_LO_REG old is 0xffffffff and CNT64_LO_REG new is say 0x00000001, and we do get the new CNT64_HI_REG things will break.

Regards,

Hans

A message that is not in the archive (sent off-list or not yet received): [email protected]

#30 lore raw

cover clocksource: sunxi: Timer fixes and cleanup

Quoted 14 lines · On Fri, 28 Jun 2013 09:43:37 +0800 ?? <[email protected]> wrote:
Quoted 12 lines

The A10 manual from http://free-electrons.com/~maxime/pub/datasheet/
does not seem to contain any details about what bad things may happen if we try to read CNT64_LO_REG while latching is still in progress and CNT64_RL_EN bit in CNT64_CTRL_REG has not changed to zero yet. I can imagine the following possible scenarios:
1. We read either the old stale CNT64_LO_REG value or the new correct value.
2. We read either the old stale CNT64_LO_REG value or the new correct value, or some random garbage.
3. The processor may deadlock, eat your dog, or do some other nasty thing.

Quoted 1 line

In the case of 1, we probably can get away without using any spinlocks?

Quoted 10 lines

About the 64bits counter, the latch bit is needed because of the asynchronous circuit. The internal circuit of 64bits counter is working under 24Mhz clock, and CNT_LO/HI is read with APB clock. So the clock synchronize is needed. The function of the latch is synchronous the 64bits counter from 24Mhz clock domain to APB clock domain. So, if the latch is not completely, value of the CNT_LO/HI maybe a random value, because some bits are latched, but others are not. So, the CNT_LO/HI should be read after latch is completely. The latch just takes 3 cycles of 24Mhz clock, the time is nearly 0.125 micro-second.

Thanks for the clarification! It is very much appreciated.

So basically we get scenario 2, which still allows some optimizations compared to scenario 3. On single-core systems (Allwinner A10), it probably makes sense to avoid spinlocks overhead and just place the critical code between LDREX and STREX instructions (or whatever higher level wrappers are available for them). In the case of contention and reading non-latched garbage value from CNT64_LO_REG (or from CNT64_LO_REG/CNT64_HI_REG pair if we go 64-bit), this critical block of code can be just retried again until it eventually succeeds.

Signature · 2 lines
Best regards,
Siarhei Siamashka
#31 lore raw
Quoted 28 lines · Siarhei Siamashka
Quoted 14 lines · On Fri, 28 Jun 2013 09:43:37 +0800 ?? <[email protected]> wrote:
Quoted 12 lines

The A10 manual from http://free-electrons.com/~maxime/pub/datasheet/
does not seem to contain any details about what bad things may happen if we try to read CNT64_LO_REG while latching is still in progress and CNT64_RL_EN bit in CNT64_CTRL_REG has not changed to zero yet. I can imagine the following possible scenarios:
1. We read either the old stale CNT64_LO_REG value or the new correct value.
2. We read either the old stale CNT64_LO_REG value or the new correct value, or some random garbage.
3. The processor may deadlock, eat your dog, or do some other nasty thing.

Quoted 1 line

In the case of 1, we probably can get away without using any spinlocks?

Quoted 10 lines

About the 64bits counter, the latch bit is needed because of the asynchronous circuit. The internal circuit of 64bits counter is working under 24Mhz clock, and CNT_LO/HI is read with APB clock. So the clock synchronize is needed. The function of the latch is synchronous the 64bits counter from 24Mhz clock domain to APB clock domain. So, if the latch is not completely, value of the CNT_LO/HI maybe a random value, because some bits are latched, but others are not. So, the CNT_LO/HI should be read after latch is completely. The latch just takes 3 cycles of 24Mhz clock, the time is nearly 0.125 micro-second.

Quoted 5 lines

Thanks for the clarification! It is very much appreciated.

So basically we get scenario 2, which still allows some optimizations compared to scenario 3. On single-core systems (Allwinner A10), it probably makes sense to avoid spinlocks overhead and just place

Spinlocks are NOPs on UP and just disable preemption, but they provide you the same ordering guarantees as spinlocks on SMP. So no special case optimization necessary.

Thanks,

tglx

#32 lore raw
Quoted 31 lines · On Fri, 28 Jun 2013 12:26:10 +0200 (CEST) Thomas Gleixner <[email protected]>…
Quoted 30 lines · Siarhei Siamashka
Quoted 14 lines · On Fri, 28 Jun 2013 09:43:37 +0800 ?? <[email protected]> wrote:
Quoted 12 lines

The A10 manual from http://free-electrons.com/~maxime/pub/datasheet/
does not seem to contain any details about what bad things may happen if we try to read CNT64_LO_REG while latching is still in progress and CNT64_RL_EN bit in CNT64_CTRL_REG has not changed to zero yet. I can imagine the following possible scenarios:
1. We read either the old stale CNT64_LO_REG value or the new correct value.
2. We read either the old stale CNT64_LO_REG value or the new correct value, or some random garbage.
3. The processor may deadlock, eat your dog, or do some other nasty thing.

Quoted 1 line

In the case of 1, we probably can get away without using any spinlocks?

Quoted 10 lines

About the 64bits counter, the latch bit is needed because of the asynchronous circuit. The internal circuit of 64bits counter is working under 24Mhz clock, and CNT_LO/HI is read with APB clock. So the clock synchronize is needed. The function of the latch is synchronous the 64bits counter from 24Mhz clock domain to APB clock domain. So, if the latch is not completely, value of the CNT_LO/HI maybe a random value, because some bits are latched, but others are not. So, the CNT_LO/HI should be read after latch is completely. The latch just takes 3 cycles of 24Mhz clock, the time is nearly 0.125 micro-second.

Thanks for the clarification! It is very much appreciated.

Quoted 7 lines
Quoted 3 lines

So basically we get scenario 2, which still allows some optimizations compared to scenario 3. On single-core systems (Allwinner A10), it probably makes sense to avoid spinlocks overhead and just place

Spinlocks are NOPs on UP and just disable preemption, but they provide you the same ordering guarantees as spinlocks on SMP. So no special case optimization necessary.

Still I would not want some high priority and latency sensitive junk (such as pulseaudio for example) not to get scheduled at the right time because of some low priority gettimeofday spammer application. The time spent latching and reading these counters is non negligible.

Though I agree Maxime that first we need an initial implementation, which just works safely. And then we can optimize it by testing real use cases and providing the relevant benchmark numbers. Knowing the precise details about the hardware helps.

But enough bikeshedding, it's time for me to shut up :)

Signature · 2 lines
Best regards,
Siarhei Siamashka
#33 lore raw

cover clocksource: sunxi: Timer fixes and cleanup

In reply to a message not in the archive
Quoted 24 lines · On Fri, 28 Jun 2013 09:43:37 +0800 ?? <[email protected]> wrote:
Quoted 12 lines

The A10 manual from http://free-electrons.com/~maxime/pub/datasheet/
does not seem to contain any details about what bad things may happen if we try to read CNT64_LO_REG while latching is still in progress and CNT64_RL_EN bit in CNT64_CTRL_REG has not changed to zero yet. I can imagine the following possible scenarios:
1. We read either the old stale CNT64_LO_REG value or the new correct value.
2. We read either the old stale CNT64_LO_REG value or the new correct value, or some random garbage.
3. The processor may deadlock, eat your dog, or do some other nasty thing.

Quoted 1 line

In the case of 1, we probably can get away without using any spinlocks?

About the 64bits counter, the latch bit is needed because of the asynchronous circuit. The internal circuit of 64bits counter is working under 24Mhz clock, and CNT_LO/HI is read with APB clock. So the clock synchronize is needed. The function of the latch is synchronous the 64bits counter from 24Mhz clock domain to APB clock domain. So, if the latch is not completely, value of the CNT_LO/HI maybe a random value, because some bits are latched, but others are not. So, the CNT_LO/HI should be read after latch is completely. The latch just takes 3 cycles of 24Mhz clock, the time is nearly 0.125 micro-second.

[...]

Quoted 1 line

NOTICE: This e-mail and any included attachments are intended only for the sole use of named and intended recipient (s) only. If you are the named and intended recipient, please note that the information contained in this email and its embedded files are confidential and privileged. If you are neither the intended nor named recipient, you are hereby notified that any unauthorized review, use, disclosure, dissemination, distribution, or copying of this communication, or any of its contents, is strictly prohibited. Please reply to the sender and destroy the original message and all your records of this message (whether electronic or otherwise). Furthermore, you should not disclose to any other person, use, copy or disseminate the contents of this e-mail and/or the documents accompanying it.

Ugh, just spotted this at the bottom.

I believe that by sending this information to LKML and the other public mailing lists, the intended recipient is "the whole world", hence most of the stated clauses (for example related to "any other person") can be safely optimized out. Still this does not sound very nice. I hope that the original intention was to authorize sharing and using this information. Please correct me if I'm wrong.

Signature · 2 lines
Best regards,
Siarhei Siamashka
#34 lore raw
Quoted 14 lines · Siarhei Siamashka
Quoted 5 lines

NOTICE: This e-mail and any included attachments are intended only for the sole use of named and intended recipient (s) only. If you are the named and intended recipient, please note that the information contained in this email and its embedded files are confidential and privileged. If you are neither the intended nor

Quoted 8 lines

named recipient, you are hereby notified that any unauthorized review, use, disclosure, dissemination, distribution, or copying of this communication, or any of its contents, is strictly prohibited. Please reply to the sender and destroy the original message and all your records of this message (whether electronic or otherwise). Furthermore, you should not disclose to any other person, use, copy or disseminate the contents of this e-mail and/or the documents accompanying it.

Quoted 8 lines

Ugh, just spotted this at the bottom.

I believe that by sending this information to LKML and the other public mailing lists, the intended recipient is "the whole world", hence most of the stated clauses (for example related to "any other person") can be safely optimized out. Still this does not sound very nice. I hope that the original intention was to authorize sharing and using this information. Please correct me if I'm wrong.

Come on. This is obviously an automated addition made by the SMTP server. While it definitely is ironic since it is sent to a public mailing list, is your comment here really needed?

Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130628/fc2f7d1e/attachment.sig>
#35 lore raw
In reply to a message not in the archive
Quoted 14 lines · ??
Quoted 12 lines

The A10 manual from http://free-electrons.com/~maxime/pub/datasheet/
does not seem to contain any details about what bad things may happen if we try to read CNT64_LO_REG while latching is still in progress and CNT64_RL_EN bit in CNT64_CTRL_REG has not changed to zero yet. I can imagine the following possible scenarios:
1. We read either the old stale CNT64_LO_REG value or the new correct value.
2. We read either the old stale CNT64_LO_REG value or the new correct value, or some random garbage.
3. The processor may deadlock, eat your dog, or do some other nasty thing.

Quoted 1 line

In the case of 1, we probably can get away without using any spinlocks?

Quoted 9 lines

About the 64bits counter, the latch bit is needed because of the asynchronous circuit. The internal circuit of 64bits counter is working under 24Mhz clock, and CNT_LO/HI is read with APB clock. So the clock synchronize is needed. The function of the latch is synchronous the 64bits counter from 24Mhz clock domain to APB clock domain. So, if the latch is not completely, value of the CNT_LO/HI maybe a random value, because some bits are latched, but others are not. So, the CNT_LO/HI should be read after latch is completely.
The latch just takes 3 cycles of 24Mhz clock, the time is nearly 0.125 micro-second.

I really wonder why we're trying to use that timer. AFAICT the A10 has another six 32bit timers which do not have this restriction and the clocksoure/sched_clock implementation works nicely with 32 bits. So what's the point of using that 64 bit counter if it's horrible to access?

Thanks,

tglx

#36 lore raw

Hi Thomas,

Quoted 25 lines · Thomas Gleixner
Quoted 14 lines · ??
Quoted 12 lines

The A10 manual from http://free-electrons.com/~maxime/pub/datasheet/
does not seem to contain any details about what bad things may happen if we try to read CNT64_LO_REG while latching is still in progress and CNT64_RL_EN bit in CNT64_CTRL_REG has not changed to zero yet. I can imagine the following possible scenarios:
1. We read either the old stale CNT64_LO_REG value or the new correct value.
2. We read either the old stale CNT64_LO_REG value or the new correct value, or some random garbage.
3. The processor may deadlock, eat your dog, or do some other nasty thing.

Quoted 1 line

In the case of 1, we probably can get away without using any spinlocks?

Quoted 9 lines

About the 64bits counter, the latch bit is needed because of the asynchronous circuit. The internal circuit of 64bits counter is working under 24Mhz clock, and CNT_LO/HI is read with APB clock. So the clock synchronize is needed. The function of the latch is synchronous the 64bits counter from 24Mhz clock domain to APB clock domain. So, if the latch is not completely, value of the CNT_LO/HI maybe a random value, because some bits are latched, but others are not. So, the CNT_LO/HI should be read after latch is completely.
The latch just takes 3 cycles of 24Mhz clock, the time is nearly 0.125 micro-second.

Quoted 5 lines

I really wonder why we're trying to use that timer. AFAICT the A10 has another six 32bit timers which do not have this restriction and the clocksoure/sched_clock implementation works nicely with 32 bits. So what's the point of using that 64 bit counter if it's horrible to access?

Yes, you're right. I actually wanted at first not to use a timer for this since we had a counter to do just that.

But that's true that actually using a timer would make the code simpler and presumably faster as well.

I'll change this in the v2.

Thanks,
Maxime

Signature · 10 lines
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130628/3705a440/attachment.sig>