2016-11-03 21:32:11

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 00/10] Move ARC timer code into drivers/clocksource/

Hi,

This series addresses the long pending move of ARC timer code into
drivers/clocksource/.

Thx,
-Vineet

v1 -> v2

- Now 10 patches instead of 9 to handle BIG ENDIAN in arch agnostic way

- Moved fix for RTC (v1 2/9) ahead of queue (v2 1/10) to allow for easier
stable backport

- Folded the Kconfig items for RTC and GFRC into single ARC_TIMERS_64BIT
So no special casing for UP/SMP in Kconfig.
Driver already handles the UP vs. SMP at runtime as needed

- convert WARN() to pr_warn() [Daniel]
- Use of _BITUL() vs. constant 0x8000_0000 [Daniel]
- changelog spellos: [Daniel]
s/depedency/dependency/
s/seperate/separate/


v1: http://lists.infradead.org/pipermail/linux-snps-arc/2016-October/001676.html

Vineet Gupta (10):
ARC: timer: rtc: implement read loop in "C" vs. inline asm
ARC: timer: gfrc, rtc: deuglify big endian code
ARC: timer: gfrc, rtc: Read BCR to detect whether hardware exists ...
ARC: timer: gfrc: boot print alongside other timers
ARC: time: move time_init() out of the driver
ARC: timer: Build gfrc, rtc under same option (64-bit timers)
ARC: breakout aux handling into a separate header
ARC: move mcip.h into include/soc and adjust the includes
ARC: breakout timer include code into separate header ...
clocksource: import ARC timer driver

MAINTAINERS | 1 +
arch/arc/Kconfig | 13 +--
arch/arc/configs/nsimosci_hs_smp_defconfig | 2 +-
arch/arc/configs/vdk_hs38_smp_defconfig | 2 +-
arch/arc/include/asm/arcregs.h | 94 +--------------
arch/arc/kernel/Makefile | 2 +-
arch/arc/kernel/mcip.c | 2 +-
arch/arc/kernel/setup.c | 17 ++-
arch/arc/plat-axs10x/axs10x.c | 2 +-
drivers/clocksource/Kconfig | 19 +++
drivers/clocksource/Makefile | 1 +
.../time.c => drivers/clocksource/arc_timer.c | 129 +++++++--------------
include/soc/arc/aux.h | 52 +++++++++
{arch/arc/include/asm => include/soc/arc}/mcip.h | 10 +-
include/soc/arc/timers.h | 38 ++++++
include/soc/nps/common.h | 4 +-
16 files changed, 181 insertions(+), 207 deletions(-)
rename arch/arc/kernel/time.c => drivers/clocksource/arc_timer.c (71%)
create mode 100644 include/soc/arc/aux.h
rename {arch/arc/include/asm => include/soc/arc}/mcip.h (95%)
create mode 100644 include/soc/arc/timers.h

--
2.7.4


2016-11-03 21:32:18

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 07/10] ARC: breakout aux handling into a separate header

ARC timers use aux registers for programming and this paves way for
moving ARC timer drivers into drivers/clocksource

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/include/asm/arcregs.h | 85 +-----------------------------------------
arch/arc/include/asm/mcip.h | 2 +-
include/soc/arc/aux.h | 52 ++++++++++++++++++++++++++
include/soc/nps/common.h | 4 +-
4 files changed, 56 insertions(+), 87 deletions(-)
create mode 100644 include/soc/arc/aux.h

diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 7f3f9f63708c..ccf5dc96713b 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -110,90 +110,7 @@

#ifndef __ASSEMBLY__

-/*
- ******************************************************************
- * Inline ASM macros to read/write AUX Regs
- * Essentially invocation of lr/sr insns from "C"
- */
-
-#if 1
-
-#define read_aux_reg(reg) __builtin_arc_lr(reg)
-
-/* gcc builtin sr needs reg param to be long immediate */
-#define write_aux_reg(reg_immed, val) \
- __builtin_arc_sr((unsigned int)(val), reg_immed)
-
-#else
-
-#define read_aux_reg(reg) \
-({ \
- unsigned int __ret; \
- __asm__ __volatile__( \
- " lr %0, [%1]" \
- : "=r"(__ret) \
- : "i"(reg)); \
- __ret; \
-})
-
-/*
- * Aux Reg address is specified as long immediate by caller
- * e.g.
- * write_aux_reg(0x69, some_val);
- * This generates tightest code.
- */
-#define write_aux_reg(reg_imm, val) \
-({ \
- __asm__ __volatile__( \
- " sr %0, [%1] \n" \
- : \
- : "ir"(val), "i"(reg_imm)); \
-})
-
-/*
- * Aux Reg address is specified in a variable
- * * e.g.
- * reg_num = 0x69
- * write_aux_reg2(reg_num, some_val);
- * This has to generate glue code to load the reg num from
- * memory to a reg hence not recommended.
- */
-#define write_aux_reg2(reg_in_var, val) \
-({ \
- unsigned int tmp; \
- \
- __asm__ __volatile__( \
- " ld %0, [%2] \n\t" \
- " sr %1, [%0] \n\t" \
- : "=&r"(tmp) \
- : "r"(val), "memory"(&reg_in_var)); \
-})
-
-#endif
-
-#define READ_BCR(reg, into) \
-{ \
- unsigned int tmp; \
- tmp = read_aux_reg(reg); \
- if (sizeof(tmp) == sizeof(into)) { \
- into = *((typeof(into) *)&tmp); \
- } else { \
- extern void bogus_undefined(void); \
- bogus_undefined(); \
- } \
-}
-
-#define WRITE_AUX(reg, into) \
-{ \
- unsigned int tmp; \
- if (sizeof(tmp) == sizeof(into)) { \
- tmp = (*(unsigned int *)&(into)); \
- write_aux_reg(reg, tmp); \
- } else { \
- extern void bogus_undefined(void); \
- bogus_undefined(); \
- } \
-}
+#include <soc/arc/aux.h>

/* Helpers */
#define TO_KB(bytes) ((bytes) >> 10)
diff --git a/arch/arc/include/asm/mcip.h b/arch/arc/include/asm/mcip.h
index c8fbe4114bad..fc28d0944801 100644
--- a/arch/arc/include/asm/mcip.h
+++ b/arch/arc/include/asm/mcip.h
@@ -13,7 +13,7 @@

#ifdef CONFIG_ISA_ARCV2

-#include <asm/arcregs.h>
+#include <soc/arc/aux.h>

#define ARC_REG_MCIP_BCR 0x0d0
#define ARC_REG_MCIP_CMD 0x600
diff --git a/include/soc/arc/aux.h b/include/soc/arc/aux.h
new file mode 100644
index 000000000000..8c41c096a51b
--- /dev/null
+++ b/include/soc/arc/aux.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016-2017 Synopsys, Inc. (http://www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __SOC_ARC_AUX_H__
+#define __SOC_ARC_AUX_H__
+
+#ifdef CONFIG_ARC
+
+#define read_aux_reg(r) __builtin_arc_lr(r)
+
+/* gcc builtin sr needs reg param to be long immediate */
+#define write_aux_reg(r, v) __builtin_arc_sr((unsigned int)(v), r)
+
+#else
+
+#define read_aux_reg(r) 0
+#define write_aux_reg(r, v)
+
+#endif
+
+#define READ_BCR(reg, into) \
+{ \
+ unsigned int tmp; \
+ tmp = read_aux_reg(reg); \
+ if (sizeof(tmp) == sizeof(into)) { \
+ into = *((typeof(into) *)&tmp); \
+ } else { \
+ extern void bogus_undefined(void); \
+ bogus_undefined(); \
+ } \
+}
+
+#define WRITE_AUX(reg, into) \
+{ \
+ unsigned int tmp; \
+ if (sizeof(tmp) == sizeof(into)) { \
+ tmp = (*(unsigned int *)&(into)); \
+ write_aux_reg(reg, tmp); \
+ } else { \
+ extern void bogus_undefined(void); \
+ bogus_undefined(); \
+ } \
+}
+
+
+#endif
diff --git a/include/soc/nps/common.h b/include/soc/nps/common.h
index 9b1d43d671a3..b7ba05b3993f 100644
--- a/include/soc/nps/common.h
+++ b/include/soc/nps/common.h
@@ -47,6 +47,8 @@

#ifndef __ASSEMBLY__

+#include <soc/arc/aux.h>
+
/* In order to increase compilation test coverage */
#ifdef CONFIG_ARC
static inline void nps_ack_gic(void)
@@ -59,8 +61,6 @@ static inline void nps_ack_gic(void)
}
#else
static inline void nps_ack_gic(void) { }
-#define write_aux_reg(r, v)
-#define read_aux_reg(r) 0
#endif

/* CPU global ID */
--
2.7.4

2016-11-03 21:32:17

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 08/10] ARC: move mcip.h into include/soc and adjust the includes

Also remove the dependency on ARCv2, to increase compile coverage for
!ARCV2 builds

Acked-by: Daniel Lezcano <[email protected]>
Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/kernel/mcip.c | 2 +-
arch/arc/kernel/time.c | 2 +-
arch/arc/plat-axs10x/axs10x.c | 2 +-
{arch/arc/include/asm => include/soc/arc}/mcip.h | 8 ++------
4 files changed, 5 insertions(+), 9 deletions(-)
rename {arch/arc/include/asm => include/soc/arc}/mcip.h (96%)

diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index c424d5abc318..0651e0a2e8b1 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -11,8 +11,8 @@
#include <linux/smp.h>
#include <linux/irq.h>
#include <linux/spinlock.h>
+#include <soc/arc/mcip.h>
#include <asm/irqflags-arcv2.h>
-#include <asm/mcip.h>
#include <asm/setup.h>

static DEFINE_RAW_SPINLOCK(mcip_lock);
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 9bb7e3105ca9..f0b6e6bc1e36 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -40,7 +40,7 @@
#include <asm/irq.h>
#include <asm/arcregs.h>

-#include <asm/mcip.h>
+#include <soc/arc/mcip.h>

/* Timer related Aux registers */
#define ARC_REG_TIMER0_LIMIT 0x23 /* timer 0 limit */
diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c
index 86548701023c..38ff349d7f2a 100644
--- a/arch/arc/plat-axs10x/axs10x.c
+++ b/arch/arc/plat-axs10x/axs10x.c
@@ -21,7 +21,7 @@
#include <asm/asm-offsets.h>
#include <asm/io.h>
#include <asm/mach_desc.h>
-#include <asm/mcip.h>
+#include <soc/arc/mcip.h>

#define AXS_MB_CGU 0xE0010000
#define AXS_MB_CREG 0xE0011000
diff --git a/arch/arc/include/asm/mcip.h b/include/soc/arc/mcip.h
similarity index 96%
rename from arch/arc/include/asm/mcip.h
rename to include/soc/arc/mcip.h
index fc28d0944801..6902c2a8bd23 100644
--- a/arch/arc/include/asm/mcip.h
+++ b/include/soc/arc/mcip.h
@@ -8,10 +8,8 @@
* published by the Free Software Foundation.
*/

-#ifndef __ASM_MCIP_H
-#define __ASM_MCIP_H
-
-#ifdef CONFIG_ISA_ARCV2
+#ifndef __SOC_ARC_MCIP_H
+#define __SOC_ARC_MCIP_H

#include <soc/arc/aux.h>

@@ -103,5 +101,3 @@ static inline void __mcip_cmd_data(unsigned int cmd, unsigned int param,
}

#endif
-
-#endif
--
2.7.4

2016-11-03 21:32:42

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 05/10] ARC: time: move time_init() out of the driver

to allow future git mv of the driver into drivers/clocksource

Acked-by: Daniel Lezcano <[email protected]>
Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/kernel/setup.c | 11 +++++++++++
arch/arc/kernel/time.c | 9 ---------
2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 595d06900061..5865bd34a7fa 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -10,6 +10,8 @@
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/root_dev.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
#include <linux/console.h>
#include <linux/module.h>
#include <linux/cpu.h>
@@ -449,6 +451,15 @@ void __init setup_arch(char **cmdline_p)
arc_unwind_init();
}

+/*
+ * Called from start_kernel() - boot CPU only
+ */
+void __init time_init(void)
+{
+ of_clk_init(NULL);
+ clocksource_probe();
+}
+
static int __init customize_machine(void)
{
if (machine_desc->init_machine)
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index d2335ca49c80..05a583414c65 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -365,12 +365,3 @@ static int __init arc_of_timer_init(struct device_node *np)
return ret;
}
CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
-
-/*
- * Called from start_kernel() - boot CPU only
- */
-void __init time_init(void)
-{
- of_clk_init(NULL);
- clocksource_probe();
-}
--
2.7.4

2016-11-03 21:32:51

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 03/10] ARC: timer: gfrc, rtc: Read BCR to detect whether hardware exists ...

... don't rely on cpuinfo populated in arc boot code. This paves way for
moving this code in drivers/clocksource/

And while at it, convert the WARN() to pr_warn() as sugested by Daniel

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/kernel/time.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 71bcdc1f9bd0..d2335ca49c80 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -111,11 +111,14 @@ static struct clocksource arc_counter_gfrc = {

static int __init arc_cs_setup_gfrc(struct device_node *node)
{
- int exists = cpuinfo_arc700[0].extn.gfrc;
+ struct mcip_bcr mp;
int ret;

- if (WARN(!exists, "Global-64-bit-Ctr clocksource not detected"))
+ READ_BCR(ARC_REG_MCIP_BCR, mp);
+ if (!mp.gfrc) {
+ pr_warn("Global-64-bit-Ctr clocksource not detected");
return -ENXIO;
+ }

ret = arc_get_timer_clk(node);
if (ret)
@@ -163,15 +166,20 @@ static struct clocksource arc_counter_rtc = {

static int __init arc_cs_setup_rtc(struct device_node *node)
{
- int exists = cpuinfo_arc700[smp_processor_id()].extn.rtc;
+ struct bcr_timer timer;
int ret;

- if (WARN(!exists, "Local-64-bit-Ctr clocksource not detected"))
+ READ_BCR(ARC_REG_TIMERS_BCR, timer);
+ if (!timer.rtc) {
+ pr_warn("Local-64-bit-Ctr clocksource not detected");
return -ENXIO;
+ }

/* Local to CPU hence not usable in SMP */
- if (WARN(IS_ENABLED(CONFIG_SMP), "Local-64-bit-Ctr not usable in SMP"))
+ if (IS_ENABLED(CONFIG_SMP)) {
+ pr_warn("Local-64-bit-Ctr not usable in SMP");
return -EINVAL;
+ }

ret = arc_get_timer_clk(node);
if (ret)
--
2.7.4

2016-11-03 21:33:06

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 04/10] ARC: timer: gfrc: boot print alongside other timers

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/kernel/setup.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 0385df77a697..595d06900061 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -234,11 +234,11 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
is_isa_arcompact() ? "ARCompact" : "ARCv2",
IS_AVAIL1(cpu->isa.be, "[Big-Endian]"));

- n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
+ n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s%s%s\nISA Extn\t: ",
IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
IS_AVAIL1(cpu->extn.timer1, "Timer1 "),
- IS_AVAIL2(cpu->extn.rtc, "Local-64-bit-Ctr ",
- CONFIG_ARC_HAS_RTC));
+ IS_AVAIL2(cpu->extn.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_HAS_RTC),
+ IS_AVAIL2(cpu->extn.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_HAS_GFRC));

n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s",
IS_AVAIL2(cpu->isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC),
--
2.7.4

2016-11-03 21:32:41

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 06/10] ARC: timer: Build gfrc, rtc under same option (64-bit timers)

The original distinction was done as they were deveoped at different
times and primarily becuse they are specific to UP (RTC) and SMP (GFRC).

But given that driver now handles that at runtime, (i.e. not allowing
RTC as clocksource in SMP), we can simplify things a bit.

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/Kconfig | 10 ++--------
arch/arc/configs/nsimosci_hs_smp_defconfig | 2 +-
arch/arc/configs/vdk_hs38_smp_defconfig | 2 +-
arch/arc/kernel/setup.c | 4 ++--
arch/arc/kernel/time.c | 6 +-----
5 files changed, 7 insertions(+), 17 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index bd204bfa29ed..bde3e558d8bc 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -410,15 +410,9 @@ config ARC_HAS_DIV_REM
bool "Insn: div, divu, rem, remu"
default y

-config ARC_HAS_RTC
- bool "Local 64-bit r/o cycle counter"
- default n
- depends on !SMP
-
-config ARC_HAS_GFRC
- bool "SMP synchronized 64-bit cycle counter"
+config ARC_TIMERS_64BIT
+ bool "64-bit r/o cycle counters RTC (up) and GFRC (smp)"
default y
- depends on SMP

config ARC_NUMBER_OF_INTERRUPTS
int "Number of interrupts"
diff --git a/arch/arc/configs/nsimosci_hs_smp_defconfig b/arch/arc/configs/nsimosci_hs_smp_defconfig
index 6da71ba253a9..155add7761ed 100644
--- a/arch/arc/configs/nsimosci_hs_smp_defconfig
+++ b/arch/arc/configs/nsimosci_hs_smp_defconfig
@@ -21,7 +21,7 @@ CONFIG_MODULES=y
CONFIG_ARC_PLAT_SIM=y
CONFIG_ISA_ARCV2=y
CONFIG_SMP=y
-# CONFIG_ARC_HAS_GFRC is not set
+# CONFIG_ARC_TIMERS_64BIT is not set
CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs_idu"
CONFIG_PREEMPT=y
# CONFIG_COMPACTION is not set
diff --git a/arch/arc/configs/vdk_hs38_smp_defconfig b/arch/arc/configs/vdk_hs38_smp_defconfig
index 969b206d6c67..573028f19de7 100644
--- a/arch/arc/configs/vdk_hs38_smp_defconfig
+++ b/arch/arc/configs/vdk_hs38_smp_defconfig
@@ -15,7 +15,7 @@ CONFIG_ARC_PLAT_AXS10X=y
CONFIG_AXS103=y
CONFIG_ISA_ARCV2=y
CONFIG_SMP=y
-# CONFIG_ARC_HAS_GFRC is not set
+# CONFIG_ARC_TIMERS_64BIT is not set
CONFIG_ARC_UBOOT_SUPPORT=y
CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38_smp"
CONFIG_PREEMPT=y
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 5865bd34a7fa..3093fa898a23 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -239,8 +239,8 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s%s%s\nISA Extn\t: ",
IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
IS_AVAIL1(cpu->extn.timer1, "Timer1 "),
- IS_AVAIL2(cpu->extn.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_HAS_RTC),
- IS_AVAIL2(cpu->extn.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_HAS_GFRC));
+ IS_AVAIL2(cpu->extn.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_TIMERS_64BIT),
+ IS_AVAIL2(cpu->extn.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_TIMERS_64BIT));

n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s",
IS_AVAIL2(cpu->isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC),
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 05a583414c65..9bb7e3105ca9 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -81,7 +81,7 @@ static int noinline arc_get_timer_clk(struct device_node *node)

/********** Clock Source Device *********/

-#ifdef CONFIG_ARC_HAS_GFRC
+#ifdef CONFIG_ARC_TIMERS_64BIT

static cycle_t arc_read_gfrc(struct clocksource *cs)
{
@@ -128,10 +128,6 @@ static int __init arc_cs_setup_gfrc(struct device_node *node)
}
CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);

-#endif
-
-#ifdef CONFIG_ARC_HAS_RTC
-
#define AUX_RTC_CTRL 0x103
#define AUX_RTC_LOW 0x104
#define AUX_RTC_HIGH 0x105
--
2.7.4

2016-11-03 21:33:31

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 02/10] ARC: timer: gfrc, rtc: deuglify big endian code

A standard "C" shift will be handled appropriately by the compiler
dependin gon the endian used fo rbuild. So we don't need the
explicit distinction in code

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/kernel/time.c | 30 ++++++++----------------------
1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 1a117b999c0c..71bcdc1f9bd0 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -86,26 +86,19 @@ static int noinline arc_get_timer_clk(struct device_node *node)
static cycle_t arc_read_gfrc(struct clocksource *cs)
{
unsigned long flags;
- union {
-#ifdef CONFIG_CPU_BIG_ENDIAN
- struct { u32 h, l; };
-#else
- struct { u32 l, h; };
-#endif
- cycle_t full;
- } stamp;
+ u32 l, h;

local_irq_save(flags);

__mcip_cmd(CMD_GFRC_READ_LO, 0);
- stamp.l = read_aux_reg(ARC_REG_MCIP_READBACK);
+ l = read_aux_reg(ARC_REG_MCIP_READBACK);

__mcip_cmd(CMD_GFRC_READ_HI, 0);
- stamp.h = read_aux_reg(ARC_REG_MCIP_READBACK);
+ h = read_aux_reg(ARC_REG_MCIP_READBACK);

local_irq_restore(flags);

- return stamp.full;
+ return (((cycle_t)h) << 32) | l;
}

static struct clocksource arc_counter_gfrc = {
@@ -143,14 +136,7 @@ CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);
static cycle_t arc_read_rtc(struct clocksource *cs)
{
unsigned long status;
- union {
-#ifdef CONFIG_CPU_BIG_ENDIAN
- struct { u32 high, low; };
-#else
- struct { u32 low, high; };
-#endif
- cycle_t full;
- } stamp;
+ u32 l, h;

/*
* hardware has an internal state machine which tracks readout of
@@ -159,12 +145,12 @@ static cycle_t arc_read_rtc(struct clocksource *cs)
* - high increments after low has been read
*/
do {
- stamp.low = read_aux_reg(AUX_RTC_LOW);
- stamp.high = read_aux_reg(AUX_RTC_HIGH);
+ l = read_aux_reg(AUX_RTC_LOW);
+ h = read_aux_reg(AUX_RTC_HIGH);
status = read_aux_reg(AUX_RTC_CTRL);
} while (!(status & _BITUL(31)));

- return stamp.full;
+ return (((cycle_t)h) << 32) | l;
}

static struct clocksource arc_counter_rtc = {
--
2.7.4

2016-11-03 21:33:45

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 10/10] clocksource: import ARC timer driver

This adds support for

- CONFIG_ARC_TIMERS : legacy 32-bit TIMER0 and TIMER1 which count UP
from @CNT to @LIMIT, before optionally triggering an interrupt.
These are programmed using ARC auxiliary register interface.
These are present in all ARC cores (ARC700 and ARC HS38)
TIMER0 serves as clockevent for all ARC linux builds.
TIMER1 is used for clocksource in arc700 builds.

- CONFIG_ARC_TIMERS_64BIT: 64-bit counters, RTC and GFRC found in
ARC HS38 cores. These are independnet IP blocks with different
programming model respectively.

Signed-off-by: Vineet Gupta <[email protected]>
---
MAINTAINERS | 1 +
arch/arc/Kconfig | 7 ++----
arch/arc/kernel/Makefile | 2 +-
drivers/clocksource/Kconfig | 19 ++++++++++++++
drivers/clocksource/Makefile | 1 +
.../time.c => drivers/clocksource/arc_timer.c | 29 ++++++----------------
6 files changed, 31 insertions(+), 28 deletions(-)
rename arch/arc/kernel/time.c => drivers/clocksource/arc_timer.c (90%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3d838cf49f81..57b56ff1dd68 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11632,6 +11632,7 @@ S: Supported
F: arch/arc/
F: Documentation/devicetree/bindings/arc/*
F: Documentation/devicetree/bindings/interrupt-controller/snps,arc*
+F: drivers/clocksource/arc_timer.c
F: drivers/tty/serial/arc_uart.c
T: git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index bde3e558d8bc..ab12723d39a0 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -8,9 +8,9 @@

config ARC
def_bool y
+ select ARC_TIMERS
select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
select BUILDTIME_EXTABLE_SORT
- select CLKSRC_OF
select CLONE_BACKWARDS
select COMMON_CLK
select GENERIC_ATOMIC64 if !ISA_ARCV2 || !(ARC_HAS_LL64 && ARC_HAS_LLSC)
@@ -115,6 +115,7 @@ config ISA_ARCOMPACT

config ISA_ARCV2
bool "ARC ISA v2"
+ select ARC_TIMERS_64BIT
help
ISA for the Next Generation ARC-HS cores

@@ -410,10 +411,6 @@ config ARC_HAS_DIV_REM
bool "Insn: div, divu, rem, remu"
default y

-config ARC_TIMERS_64BIT
- bool "64-bit r/o cycle counters RTC (up) and GFRC (smp)"
- default y
-
config ARC_NUMBER_OF_INTERRUPTS
int "Number of interrupts"
range 8 240
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index cfcdedf52ff8..8942c5c3b4c5 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -8,7 +8,7 @@
# Pass UTS_MACHINE for user_regset definition
CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'

-obj-y := arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
+obj-y := arcksyms.o setup.o irq.o reset.o ptrace.o process.o devtree.o
obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o
obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o intc-compact.o
obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index e2c6e43cf8ca..a53bd50164e7 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -282,6 +282,25 @@ config CLKSRC_MPS2
select CLKSRC_MMIO
select CLKSRC_OF

+config ARC_TIMERS
+ bool "Support for 32-bit TIMERn counters in ARC Cores" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ select CLKSRC_OF
+ help
+ These are legacy 32-bit TIMER0 and TIMER1 counters found on all ARC cores
+ (ARC700 as well as ARC HS38).
+ TIMER0 serves as clockevent while TIMER1 provides clocksource
+
+config ARC_TIMERS_64BIT
+ bool "Support for 64-bit counters in ARC HS38 cores" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ select CLKSRC_OF
+ help
+ This enables 2 different 64-bit timers: RTC (for UP) and GFRC (for SMP)
+ RTC is implemented inside the core, while GFRC sits outside the core in
+ ARConnect IP block. Driver automatically picks one of them for clocksource
+ as appropriate.
+
config ARM_ARCH_TIMER
bool
select CLKSRC_OF if OF
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index cf87f407f1ad..a14111e1f087 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o
obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o

+obj-$(CONFIG_ARC_TIMERS) += arc_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
obj-$(CONFIG_ARMV7M_SYSTICK) += armv7m_systick.o
diff --git a/arch/arc/kernel/time.c b/drivers/clocksource/arc_timer.c
similarity index 90%
rename from arch/arc/kernel/time.c
rename to drivers/clocksource/arc_timer.c
index 878c71dda8b9..cb13d9490208 100644
--- a/arch/arc/kernel/time.c
+++ b/drivers/clocksource/arc_timer.c
@@ -1,32 +1,18 @@
/*
+ * Copyright (C) 2016-17 Synopsys, Inc. (http://www.synopsys.com)
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (http://www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
- *
- * vineetg: Jan 1011
- * -sched_clock( ) no longer jiffies based. Uses the same clocksource
- * as gtod
- *
- * Rajeshwarr/Vineetg: Mar 2008
- * -Implemented CONFIG_GENERIC_TIME (rather deleted arch specific code)
- * for arch independent gettimeofday()
- * -Implemented CONFIG_GENERIC_CLOCKEVENTS as base for hrtimers
- *
- * Vineetg: Mar 2008: Forked off from time.c which now is time-jiff.c
*/

-/* ARC700 has two 32bit independent prog Timers: TIMER0 and TIMER1
- * Each can programmed to go from @count to @limit and optionally
- * interrupt when that happens.
- * A write to Control Register clears the Interrupt
- *
- * We've designated TIMER0 for events (clockevents)
- * while TIMER1 for free running (clocksource)
+/* ARC700 has two 32bit independent prog Timers: TIMER0 and TIMER1, Each can be
+ * programmed to go from @count to @limit and optionally interrupt.
+ * We've designated TIMER0 for clockevents and TIMER1 for clocksource
*
- * Newer ARC700 cores have 64bit clk fetching RTSC insn, preferred over TIMER1
- * which however is currently broken
+ * ARCv2 based HS38 cores have RTC (in-core) and GFRC (inside ARConnect/MCIP)
+ * which are suitable for UP and SMP based clocksources respectively
*/

#include <linux/interrupt.h>
@@ -37,7 +23,6 @@
#include <linux/cpu.h>
#include <linux/of.h>
#include <linux/of_irq.h>
-#include <asm/irq.h>

#include <soc/arc/timers.h>
#include <soc/arc/mcip.h>
@@ -263,7 +248,7 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id)
* irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
*/
struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
- int irq_reenable = clockevent_state_periodic(evt);
+ int irq_reenable __maybe_unused = clockevent_state_periodic(evt);

/*
* Any write to CTRL reg ACks the interrupt, we rewrite the
--
2.7.4

2016-11-03 21:33:37

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 01/10] ARC: timer: rtc: implement read loop in "C" vs. inline asm

The current code doesn't even compile ....

CC: [email protected]
Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/kernel/time.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index f927b8dc6edd..1a117b999c0c 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -152,14 +152,17 @@ static cycle_t arc_read_rtc(struct clocksource *cs)
cycle_t full;
} stamp;

-
- __asm__ __volatile(
- "1: \n"
- " lr %0, [AUX_RTC_LOW] \n"
- " lr %1, [AUX_RTC_HIGH] \n"
- " lr %2, [AUX_RTC_CTRL] \n"
- " bbit0.nt %2, 31, 1b \n"
- : "=r" (stamp.low), "=r" (stamp.high), "=r" (status));
+ /*
+ * hardware has an internal state machine which tracks readout of
+ * low/high and updates the CTRL.status if
+ * - interrupt/exception taken between the two reads
+ * - high increments after low has been read
+ */
+ do {
+ stamp.low = read_aux_reg(AUX_RTC_LOW);
+ stamp.high = read_aux_reg(AUX_RTC_HIGH);
+ status = read_aux_reg(AUX_RTC_CTRL);
+ } while (!(status & _BITUL(31)));

return stamp.full;
}
--
2.7.4

2016-11-03 21:33:44

by Vineet Gupta

[permalink] [raw]
Subject: [PATCH v2 09/10] ARC: breakout timer include code into separate header ...

... which allows for use in drivers/clocksource later

Signed-off-by: Vineet Gupta <[email protected]>
---
arch/arc/include/asm/arcregs.h | 9 +--------
arch/arc/kernel/time.c | 18 +++---------------
include/soc/arc/timers.h | 38 ++++++++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+), 23 deletions(-)
create mode 100644 include/soc/arc/timers.h

diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index ccf5dc96713b..a17aa4558832 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -20,7 +20,6 @@
#define ARC_REG_FP_V2_BCR 0xc8 /* ARCv2 FPU */
#define ARC_REG_SLC_BCR 0xce
#define ARC_REG_DCCM_BUILD 0x74 /* DCCM size (common) */
-#define ARC_REG_TIMERS_BCR 0x75
#define ARC_REG_AP_BCR 0x76
#define ARC_REG_ICCM_BUILD 0x78 /* ICCM size (common) */
#define ARC_REG_XY_MEM_BCR 0x79
@@ -206,13 +205,7 @@ struct bcr_fp_arcv2 {
#endif
};

-struct bcr_timer {
-#ifdef CONFIG_CPU_BIG_ENDIAN
- unsigned int pad2:15, rtsc:1, pad1:5, rtc:1, t1:1, t0:1, ver:8;
-#else
- unsigned int ver:8, t0:1, t1:1, rtc:1, pad1:5, rtsc:1, pad2:15;
-#endif
-};
+#include <soc/arc/timers.h>

struct bcr_bpu_arcompact {
#ifdef CONFIG_CPU_BIG_ENDIAN
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index f0b6e6bc1e36..878c71dda8b9 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -38,22 +38,10 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <asm/irq.h>
-#include <asm/arcregs.h>

+#include <soc/arc/timers.h>
#include <soc/arc/mcip.h>

-/* Timer related Aux registers */
-#define ARC_REG_TIMER0_LIMIT 0x23 /* timer 0 limit */
-#define ARC_REG_TIMER0_CTRL 0x22 /* timer 0 control */
-#define ARC_REG_TIMER0_CNT 0x21 /* timer 0 count */
-#define ARC_REG_TIMER1_LIMIT 0x102 /* timer 1 limit */
-#define ARC_REG_TIMER1_CTRL 0x101 /* timer 1 control */
-#define ARC_REG_TIMER1_CNT 0x100 /* timer 1 count */
-
-#define TIMER_CTRL_IE (1 << 0) /* Interrupt when Count reaches limit */
-#define TIMER_CTRL_NH (1 << 1) /* Count only when CPU NOT halted */
-
-#define ARC_TIMER_MAX 0xFFFFFFFF

static unsigned long arc_timer_freq;

@@ -218,7 +206,7 @@ static int __init arc_cs_setup_timer1(struct device_node *node)
if (ret)
return ret;

- write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
+ write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMERN_MAX);
write_aux_reg(ARC_REG_TIMER1_CNT, 0);
write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);

@@ -296,7 +284,7 @@ static int arc_timer_starting_cpu(unsigned int cpu)

evt->cpumask = cpumask_of(smp_processor_id());

- clockevents_config_and_register(evt, arc_timer_freq, 0, ARC_TIMER_MAX);
+ clockevents_config_and_register(evt, arc_timer_freq, 0, ARC_TIMERN_MAX);
enable_percpu_irq(arc_timer_irq, 0);
return 0;
}
diff --git a/include/soc/arc/timers.h b/include/soc/arc/timers.h
new file mode 100644
index 000000000000..a20ed2fbc432
--- /dev/null
+++ b/include/soc/arc/timers.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016-17 Synopsys, Inc. (http://www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SOC_ARC_TIMERS_H
+#define __SOC_ARC_TIMERS_H
+
+#include <soc/arc/aux.h>
+
+/* Timer related Aux registers */
+#define ARC_REG_TIMER0_LIMIT 0x23 /* timer 0 limit */
+#define ARC_REG_TIMER0_CTRL 0x22 /* timer 0 control */
+#define ARC_REG_TIMER0_CNT 0x21 /* timer 0 count */
+#define ARC_REG_TIMER1_LIMIT 0x102 /* timer 1 limit */
+#define ARC_REG_TIMER1_CTRL 0x101 /* timer 1 control */
+#define ARC_REG_TIMER1_CNT 0x100 /* timer 1 count */
+
+/* CTRL reg bits */
+#define TIMER_CTRL_IE (1 << 0) /* Interrupt when Count reaches limit */
+#define TIMER_CTRL_NH (1 << 1) /* Count only when CPU NOT halted */
+
+#define ARC_TIMERN_MAX 0xFFFFFFFF
+
+#define ARC_REG_TIMERS_BCR 0x75
+
+struct bcr_timer {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ unsigned int pad2:15, rtsc:1, pad1:5, rtc:1, t1:1, t0:1, ver:8;
+#else
+ unsigned int ver:8, t0:1, t1:1, rtc:1, pad1:5, rtsc:1, pad2:15;
+#endif
+};
+
+#endif
--
2.7.4

2016-11-03 21:52:32

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 01/10] ARC: timer: rtc: implement read loop in "C" vs. inline asm

On Thu, Nov 03, 2016 at 02:31:32PM -0700, Vineet Gupta wrote:
> The current code doesn't even compile ....

Give a better description in the log, especially if this patch is supposed to
go to stable@

> CC: [email protected]
> Signed-off-by: Vineet Gupta <[email protected]>
> ---
> arch/arc/kernel/time.c | 19 +++++++++++--------
> 1 file changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
> index f927b8dc6edd..1a117b999c0c 100644
> --- a/arch/arc/kernel/time.c
> +++ b/arch/arc/kernel/time.c
> @@ -152,14 +152,17 @@ static cycle_t arc_read_rtc(struct clocksource *cs)
> cycle_t full;
> } stamp;
>
> -
> - __asm__ __volatile(
> - "1: \n"
> - " lr %0, [AUX_RTC_LOW] \n"
> - " lr %1, [AUX_RTC_HIGH] \n"
> - " lr %2, [AUX_RTC_CTRL] \n"
> - " bbit0.nt %2, 31, 1b \n"
> - : "=r" (stamp.low), "=r" (stamp.high), "=r" (status));
> + /*
> + * hardware has an internal state machine which tracks readout of
> + * low/high and updates the CTRL.status if
> + * - interrupt/exception taken between the two reads
> + * - high increments after low has been read
> + */
> + do {
> + stamp.low = read_aux_reg(AUX_RTC_LOW);
> + stamp.high = read_aux_reg(AUX_RTC_HIGH);
> + status = read_aux_reg(AUX_RTC_CTRL);
> + } while (!(status & _BITUL(31)));

Is the condition correct ? If I refer to your previous answer, the bit will be
set for status if the counter wrapped up. So in this case, we won't exit the
loop until we wrap up, no ?

> return stamp.full;
> }
> --
> 2.7.4
>

2016-11-03 21:55:13

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 02/10] ARC: timer: gfrc, rtc: deuglify big endian code

On Thu, Nov 03, 2016 at 02:31:33PM -0700, Vineet Gupta wrote:
> A standard "C" shift will be handled appropriately by the compiler
> dependin gon the endian used fo rbuild. So we don't need the

s/dependin gon/depending on/
s/fo rbuild/for build/

> explicit distinction in code
>
> Signed-off-by: Vineet Gupta <[email protected]>
> ---

2016-11-03 22:13:14

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 06/10] ARC: timer: Build gfrc, rtc under same option (64-bit timers)

On Thu, Nov 03, 2016 at 02:31:37PM -0700, Vineet Gupta wrote:
> The original distinction was done as they were deveoped at different

s/deveoped/developed/

> times and primarily becuse they are specific to UP (RTC) and SMP (GFRC).

s/becuse/because/

>
> But given that driver now handles that at runtime, (i.e. not allowing
> RTC as clocksource in SMP), we can simplify things a bit.
>
> Signed-off-by: Vineet Gupta <[email protected]>
> ---

2016-11-03 22:19:02

by Vineet Gupta

[permalink] [raw]
Subject: Re: [PATCH v2 02/10] ARC: timer: gfrc, rtc: deuglify big endian code

On 11/03/2016 02:55 PM, Daniel Lezcano wrote:
> On Thu, Nov 03, 2016 at 02:31:33PM -0700, Vineet Gupta wrote:
>> A standard "C" shift will be handled appropriately by the compiler
>> dependin gon the endian used fo rbuild. So we don't need the
>
> s/dependin gon/depending on/
> s/fo rbuild/for build/

Sorry for fat fingering those. Fixed now.

>
>> explicit distinction in code
>>
>> Signed-off-by: Vineet Gupta <[email protected]>
>> ---
>

2016-11-03 22:23:26

by Vineet Gupta

[permalink] [raw]
Subject: Re: [PATCH v2 01/10] ARC: timer: rtc: implement read loop in "C" vs. inline asm

On 11/03/2016 02:52 PM, Daniel Lezcano wrote:
> On Thu, Nov 03, 2016 at 02:31:32PM -0700, Vineet Gupta wrote:
>> The current code doesn't even compile ....
>
> Give a better description in the log, especially if this patch is supposed to
> go to stable@

OK.

>
>> CC: [email protected]
>> Signed-off-by: Vineet Gupta <[email protected]>
>> ---
>> arch/arc/kernel/time.c | 19 +++++++++++--------
>> 1 file changed, 11 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
>> index f927b8dc6edd..1a117b999c0c 100644
>> --- a/arch/arc/kernel/time.c
>> +++ b/arch/arc/kernel/time.c
>> @@ -152,14 +152,17 @@ static cycle_t arc_read_rtc(struct clocksource *cs)
>> cycle_t full;
>> } stamp;
>>
>> -
>> - __asm__ __volatile(
>> - "1: \n"
>> - " lr %0, [AUX_RTC_LOW] \n"
>> - " lr %1, [AUX_RTC_HIGH] \n"
>> - " lr %2, [AUX_RTC_CTRL] \n"
>> - " bbit0.nt %2, 31, 1b \n"
>> - : "=r" (stamp.low), "=r" (stamp.high), "=r" (status));
>> + /*
>> + * hardware has an internal state machine which tracks readout of
>> + * low/high and updates the CTRL.status if
>> + * - interrupt/exception taken between the two reads
>> + * - high increments after low has been read
>> + */
>> + do {
>> + stamp.low = read_aux_reg(AUX_RTC_LOW);
>> + stamp.high = read_aux_reg(AUX_RTC_HIGH);
>> + status = read_aux_reg(AUX_RTC_CTRL);
>> + } while (!(status & _BITUL(31)));
>
> Is the condition correct ? If I refer to your previous answer, the bit will be
> set for status if the counter wrapped up. So in this case, we won't exit the
> loop until we wrap up, no ?

No thats not what I meant. Bit being set there means things are fine (no interrupt
taken, no increment of high after low was readetc). All I changed here was use of
0x8000_0000 to the macro. BBIT0 in assembler means branch if bit was clear.

>
>> return stamp.full;
>> }
>> --
>> 2.7.4
>>

2016-11-03 22:36:01

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 01/10] ARC: timer: rtc: implement read loop in "C" vs. inline asm

On Thu, Nov 03, 2016 at 03:23:09PM -0700, Vineet Gupta wrote:
> On 11/03/2016 02:52 PM, Daniel Lezcano wrote:
> > On Thu, Nov 03, 2016 at 02:31:32PM -0700, Vineet Gupta wrote:
> >> The current code doesn't even compile ....
> >
> > Give a better description in the log, especially if this patch is supposed to
> > go to stable@
>
> OK.

[ ... ]

> > Is the condition correct ? If I refer to your previous answer, the bit will be
> > set for status if the counter wrapped up. So in this case, we won't exit the
> > loop until we wrap up, no ?
>
> No thats not what I meant. Bit being set there means things are fine (no interrupt
> taken, no increment of high after low was readetc). All I changed here was use of
> 0x8000_0000 to the macro. BBIT0 in assembler means branch if bit was clear.

Fair enough. So the logic is inverted 'status' == 0 means 'not fine'.

2016-11-03 22:38:15

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 10/10] clocksource: import ARC timer driver

On Thu, Nov 03, 2016 at 02:31:41PM -0700, Vineet Gupta wrote:
> This adds support for
>
> - CONFIG_ARC_TIMERS : legacy 32-bit TIMER0 and TIMER1 which count UP
> from @CNT to @LIMIT, before optionally triggering an interrupt.
> These are programmed using ARC auxiliary register interface.
> These are present in all ARC cores (ARC700 and ARC HS38)
> TIMER0 serves as clockevent for all ARC linux builds.
> TIMER1 is used for clocksource in arc700 builds.
>
> - CONFIG_ARC_TIMERS_64BIT: 64-bit counters, RTC and GFRC found in
> ARC HS38 cores. These are independnet IP blocks with different
> programming model respectively.
>
> Signed-off-by: Vineet Gupta <[email protected]>
> ---

[ ... ]

> #include <linux/of_irq.h>
> -#include <asm/irq.h>
>
> #include <soc/arc/timers.h>
> #include <soc/arc/mcip.h>
> @@ -263,7 +248,7 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id)
> * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
> */
> struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
> - int irq_reenable = clockevent_state_periodic(evt);
> + int irq_reenable __maybe_unused = clockevent_state_periodic(evt);

Why is needed __maybe_unused ? I see in the previous driver 'irq_reenable' is
used or is there a change in the previous patches I missed ?

2016-11-03 22:44:38

by Vineet Gupta

[permalink] [raw]
Subject: Re: [PATCH v2 01/10] ARC: timer: rtc: implement read loop in "C" vs. inline asm

On 11/03/2016 03:35 PM, Daniel Lezcano wrote:
> On Thu, Nov 03, 2016 at 03:23:09PM -0700, Vineet Gupta wrote:
>> On 11/03/2016 02:52 PM, Daniel Lezcano wrote:
>>> On Thu, Nov 03, 2016 at 02:31:32PM -0700, Vineet Gupta wrote:
>>>> The current code doesn't even compile ....
>>>
>>> Give a better description in the log, especially if this patch is supposed to
>>> go to stable@
>>
>> OK.
>
> [ ... ]

Here's what I added

---->
ARC: timer: rtc: implement read loop in "C" vs. inline asm

The current code doesn't even compile as somehow the inline assembly
can't see the register names defined as ARC_RTC_*
I'm pretty sure It worked when I first got it merged, but the tools were
definitely different then.

So better to write this in "C" anyways.


>
>>> Is the condition correct ? If I refer to your previous answer, the bit will be
>>> set for status if the counter wrapped up. So in this case, we won't exit the
>>> loop until we wrap up, no ?
>>
>> No thats not what I meant. Bit being set there means things are fine (no interrupt
>> taken, no increment of high after low was readetc). All I changed here was use of
>> 0x8000_0000 to the macro. BBIT0 in assembler means branch if bit was clear.
>
> Fair enough. So the logic is inverted 'status' == 0 means 'not fine'.

Indeed !

2016-11-03 22:47:00

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 01/10] ARC: timer: rtc: implement read loop in "C" vs. inline asm

On Thu, Nov 03, 2016 at 03:44:24PM -0700, Vineet Gupta wrote:
> On 11/03/2016 03:35 PM, Daniel Lezcano wrote:
> > On Thu, Nov 03, 2016 at 03:23:09PM -0700, Vineet Gupta wrote:
> >> On 11/03/2016 02:52 PM, Daniel Lezcano wrote:
> >>> On Thu, Nov 03, 2016 at 02:31:32PM -0700, Vineet Gupta wrote:
> >>>> The current code doesn't even compile ....
> >>>
> >>> Give a better description in the log, especially if this patch is supposed to
> >>> go to stable@
> >>
> >> OK.
> >
> > [ ... ]
>
> Here's what I added
>
> ---->
> ARC: timer: rtc: implement read loop in "C" vs. inline asm
>
> The current code doesn't even compile as somehow the inline assembly
> can't see the register names defined as ARC_RTC_*
> I'm pretty sure It worked when I first got it merged, but the tools were
> definitely different then.
>
> So better to write this in "C" anyways.

Acked-by: Daniel Lezcano <[email protected]>

2016-11-03 22:52:55

by Vineet Gupta

[permalink] [raw]
Subject: Re: [PATCH v2 10/10] clocksource: import ARC timer driver

On 11/03/2016 03:38 PM, Daniel Lezcano wrote:
> On Thu, Nov 03, 2016 at 02:31:41PM -0700, Vineet Gupta wrote:
>> This adds support for
>>
>> - CONFIG_ARC_TIMERS : legacy 32-bit TIMER0 and TIMER1 which count UP
>> from @CNT to @LIMIT, before optionally triggering an interrupt.
>> These are programmed using ARC auxiliary register interface.
>> These are present in all ARC cores (ARC700 and ARC HS38)
>> TIMER0 serves as clockevent for all ARC linux builds.
>> TIMER1 is used for clocksource in arc700 builds.
>>
>> - CONFIG_ARC_TIMERS_64BIT: 64-bit counters, RTC and GFRC found in
>> ARC HS38 cores. These are independnet IP blocks with different
>> programming model respectively.
>>
>> Signed-off-by: Vineet Gupta <[email protected]>
>> ---
>
> [ ... ]
>
>> #include <linux/of_irq.h>
>> -#include <asm/irq.h>
>>
>> #include <soc/arc/timers.h>
>> #include <soc/arc/mcip.h>
>> @@ -263,7 +248,7 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id)
>> * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
>> */
>> struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
>> - int irq_reenable = clockevent_state_periodic(evt);
>> + int irq_reenable __maybe_unused = clockevent_state_periodic(evt);
>
> Why is needed __maybe_unused ? I see in the previous driver 'irq_reenable' is
> used or is there a change in the previous patches I missed ?

This is needed when not building for CONFIG_ARC (saw this when building for ARM)
write_aux_reg() becomes a no-op which causes a warning:

write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);

2016-11-03 23:01:56

by Daniel Lezcano

[permalink] [raw]
Subject: Re: [PATCH v2 10/10] clocksource: import ARC timer driver

On Thu, Nov 03, 2016 at 03:50:21PM -0700, Vineet Gupta wrote:
> On 11/03/2016 03:38 PM, Daniel Lezcano wrote:
> > On Thu, Nov 03, 2016 at 02:31:41PM -0700, Vineet Gupta wrote:
> >> This adds support for
> >>
> >> - CONFIG_ARC_TIMERS : legacy 32-bit TIMER0 and TIMER1 which count UP
> >> from @CNT to @LIMIT, before optionally triggering an interrupt.
> >> These are programmed using ARC auxiliary register interface.
> >> These are present in all ARC cores (ARC700 and ARC HS38)
> >> TIMER0 serves as clockevent for all ARC linux builds.
> >> TIMER1 is used for clocksource in arc700 builds.
> >>
> >> - CONFIG_ARC_TIMERS_64BIT: 64-bit counters, RTC and GFRC found in
> >> ARC HS38 cores. These are independnet IP blocks with different
> >> programming model respectively.
> >>
> >> Signed-off-by: Vineet Gupta <[email protected]>
> >> ---
> >
> > [ ... ]
> >
> >> #include <linux/of_irq.h>
> >> -#include <asm/irq.h>
> >>
> >> #include <soc/arc/timers.h>
> >> #include <soc/arc/mcip.h>
> >> @@ -263,7 +248,7 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id)
> >> * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
> >> */
> >> struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
> >> - int irq_reenable = clockevent_state_periodic(evt);
> >> + int irq_reenable __maybe_unused = clockevent_state_periodic(evt);
> >
> > Why is needed __maybe_unused ? I see in the previous driver 'irq_reenable' is
> > used or is there a change in the previous patches I missed ?
>
> This is needed when not building for CONFIG_ARC (saw this when building for ARM)
> write_aux_reg() becomes a no-op which causes a warning:
>
> write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);

Instead of adding the __maybe_unused, changing in patch 7/10:

#define read_aux_reg(r) 0
#define write_aux_reg(r, v)

by

static inline int read_aux_reg(void *)
{
return 0;
}

static inline void write_aux_reg(void *, u32)
{
;
}

Should fix the warning.

2016-11-03 23:07:03

by Vineet Gupta

[permalink] [raw]
Subject: Re: [PATCH v2 10/10] clocksource: import ARC timer driver

On 11/03/2016 04:01 PM, Daniel Lezcano wrote:
> On Thu, Nov 03, 2016 at 03:50:21PM -0700, Vineet Gupta wrote:
>> On 11/03/2016 03:38 PM, Daniel Lezcano wrote:
>>> On Thu, Nov 03, 2016 at 02:31:41PM -0700, Vineet Gupta wrote:
>>>> This adds support for
>>>>
>>>> - CONFIG_ARC_TIMERS : legacy 32-bit TIMER0 and TIMER1 which count UP
>>>> from @CNT to @LIMIT, before optionally triggering an interrupt.
>>>> These are programmed using ARC auxiliary register interface.
>>>> These are present in all ARC cores (ARC700 and ARC HS38)
>>>> TIMER0 serves as clockevent for all ARC linux builds.
>>>> TIMER1 is used for clocksource in arc700 builds.
>>>>
>>>> - CONFIG_ARC_TIMERS_64BIT: 64-bit counters, RTC and GFRC found in
>>>> ARC HS38 cores. These are independnet IP blocks with different
>>>> programming model respectively.
>>>>
>>>> Signed-off-by: Vineet Gupta <[email protected]>
>>>> ---
>>>
>>> [ ... ]
>>>
>>>> #include <linux/of_irq.h>
>>>> -#include <asm/irq.h>
>>>>
>>>> #include <soc/arc/timers.h>
>>>> #include <soc/arc/mcip.h>
>>>> @@ -263,7 +248,7 @@ static irqreturn_t timer_irq_handler(int irq, void *dev_id)
>>>> * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
>>>> */
>>>> struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
>>>> - int irq_reenable = clockevent_state_periodic(evt);
>>>> + int irq_reenable __maybe_unused = clockevent_state_periodic(evt);
>>>
>>> Why is needed __maybe_unused ? I see in the previous driver 'irq_reenable' is
>>> used or is there a change in the previous patches I missed ?
>>
>> This is needed when not building for CONFIG_ARC (saw this when building for ARM)
>> write_aux_reg() becomes a no-op which causes a warning:
>>
>> write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
>
> Instead of adding the __maybe_unused, changing in patch 7/10:
>
> #define read_aux_reg(r) 0
> #define write_aux_reg(r, v)
>
> by
>
> static inline int read_aux_reg(void *)
> {
> return 0;
> }
>
> static inline void write_aux_reg(void *, u32)
> {
> ;
> }
>
> Should fix the warning.

Good point, slight mod preferred as @reg argument is not really a MMIO register so
not a pointer but a number instead so I'd prefer u32 for that as well.

2016-11-04 17:58:17

by Alexey Brodkin

[permalink] [raw]
Subject: RE: [PATCH v2 01/10] ARC: timer: rtc: implement read loop in "C" vs. inline asm

Hi Vineet,

> -----Original Message-----
> From: Vineet Gupta [mailto:[email protected]]
> Sent: Friday, November 04, 2016 12:32 AM
> To: Daniel Lezcano <[email protected]>
> Cc: Noam Camus <[email protected]>; [email protected]; [email protected]; [email protected];
> [email protected]; Vineet Gupta <[email protected]>; [email protected]
> Subject: [PATCH v2 01/10] ARC: timer: rtc: implement read loop in "C" vs. inline asm
>
> The current code doesn't even compile ....
>
> CC: [email protected]
> Signed-off-by: Vineet Gupta <[email protected]>
> ---
> arch/arc/kernel/time.c | 19 +++++++++++--------
> 1 file changed, 11 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
> index f927b8dc6edd..1a117b999c0c 100644
> --- a/arch/arc/kernel/time.c
> +++ b/arch/arc/kernel/time.c
> @@ -152,14 +152,17 @@ static cycle_t arc_read_rtc(struct clocksource *cs)
> cycle_t full;
> } stamp;
>
> -
> - __asm__ __volatile(
> - "1: \n"
> - " lr %0, [AUX_RTC_LOW] \n"
> - " lr %1, [AUX_RTC_HIGH] \n"
> - " lr %2, [AUX_RTC_CTRL] \n"
> - " bbit0.nt %2, 31, 1b \n"
> - : "=r" (stamp.low), "=r" (stamp.high), "=r" (status));
> + /*
> + * hardware has an internal state machine which tracks readout of
> + * low/high and updates the CTRL.status if
> + * - interrupt/exception taken between the two reads
> + * - high increments after low has been read
> + */
> + do {
> + stamp.low = read_aux_reg(AUX_RTC_LOW);
> + stamp.high = read_aux_reg(AUX_RTC_HIGH);
> + status = read_aux_reg(AUX_RTC_CTRL);
> + } while (!(status & _BITUL(31)));

I think original Daniel's comment was about constant value used here.
Now with "_BITUL" it already looks much better but IMHO it would be even better if
31 gets converted here to something like:
------------------------>8--------------------
#define RTC_CTRL_A1_OFFSET 31
------------------------>8--------------------

-Alexey

2016-11-04 18:12:35

by Alexey Brodkin

[permalink] [raw]
Subject: RE: [PATCH v2 02/10] ARC: timer: gfrc, rtc: deuglify big endian code

Hi Vineet,

A couple of misspellings in the commit message below.

> -----Original Message-----
> From: Vineet Gupta [mailto:[email protected]]
> Sent: Friday, November 04, 2016 12:32 AM
> To: Daniel Lezcano <[email protected]>
> Cc: Noam Camus <[email protected]>; [email protected]; [email protected]; [email protected];
> [email protected]; Vineet Gupta <[email protected]>
> Subject: [PATCH v2 02/10] ARC: timer: gfrc, rtc: deuglify big endian code
>
> A standard "C" shift will be handled appropriately by the compiler
> dependin gon the endian used fo rbuild. So we don't need the

"depending on", "used for build".

-Alexey