All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Add clockevet for timer-nps driver to NPS400 SoC
@ 2016-10-13 14:52 ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-13 14:52 UTC (permalink / raw)
  To: robh+dt, mark.rutland
  Cc: daniel.lezcano, tglx, devicetree, linux-kernel, Noam Camus

From: Noam Camus <noamca@mellanox.com>

In first version of this driver we supported clocksource for the NPS400.
The support for clockevent was taken from Synopsys ARC timer driver.
This was good for working with our simulator of NPS400.
However in NPS400 ASIC the timers behave differently than simulation.
The timers in ASIC are shared between all threads whithin a core
and hence need different driver to support this behaviour.

The idea of this design is that we got 16 HW threads per core
each represented at bimask in a shared register in this core.
So when thread wants that next clockevent expiration will produce
timer interrupt to itself the correspondance bit in this register
should be set.
So theoretically if all 16 bits are set then all HW threads will get
timer interrupt on next expiration of timer 0.

Note that we use Synopsys ARC design naming convention for the timers
where:
timer0 is used for clockevents
timer1 is used for clocksource.

Noam Camus (3):
  soc: Support for NPS HW scheduling
  ARC: [plat-eznps] remove macros for timer0 TSI
  clocksource: Add clockevent support to NPS400 driver

 .../bindings/timer/ezchip,nps400-timer.txt         |   15 --
 .../bindings/timer/ezchip,nps400-timer0.txt        |   17 ++
 .../bindings/timer/ezchip,nps400-timer1.txt        |   15 ++
 arch/arc/plat-eznps/include/plat/ctop.h            |    2 -
 drivers/clocksource/timer-nps.c                    |  239 +++++++++++++++++++-
 include/soc/nps/mtm.h                              |   61 +++++
 6 files changed, 322 insertions(+), 27 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
 create mode 100644 include/soc/nps/mtm.h

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 0/3] Add clockevet for timer-nps driver to NPS400 SoC
@ 2016-10-13 14:52 ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-13 14:52 UTC (permalink / raw)
  To: robh+dt, mark.rutland
  Cc: daniel.lezcano, tglx, devicetree, linux-kernel, Noam Camus

From: Noam Camus <noamca@mellanox.com>

In first version of this driver we supported clocksource for the NPS400.
The support for clockevent was taken from Synopsys ARC timer driver.
This was good for working with our simulator of NPS400.
However in NPS400 ASIC the timers behave differently than simulation.
The timers in ASIC are shared between all threads whithin a core
and hence need different driver to support this behaviour.

The idea of this design is that we got 16 HW threads per core
each represented at bimask in a shared register in this core.
So when thread wants that next clockevent expiration will produce
timer interrupt to itself the correspondance bit in this register
should be set.
So theoretically if all 16 bits are set then all HW threads will get
timer interrupt on next expiration of timer 0.

Note that we use Synopsys ARC design naming convention for the timers
where:
timer0 is used for clockevents
timer1 is used for clocksource.

Noam Camus (3):
  soc: Support for NPS HW scheduling
  ARC: [plat-eznps] remove macros for timer0 TSI
  clocksource: Add clockevent support to NPS400 driver

 .../bindings/timer/ezchip,nps400-timer.txt         |   15 --
 .../bindings/timer/ezchip,nps400-timer0.txt        |   17 ++
 .../bindings/timer/ezchip,nps400-timer1.txt        |   15 ++
 arch/arc/plat-eznps/include/plat/ctop.h            |    2 -
 drivers/clocksource/timer-nps.c                    |  239 +++++++++++++++++++-
 include/soc/nps/mtm.h                              |   61 +++++
 6 files changed, 322 insertions(+), 27 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
 create mode 100644 include/soc/nps/mtm.h

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/3] soc: Support for NPS HW scheduling
@ 2016-10-13 14:52   ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-13 14:52 UTC (permalink / raw)
  To: robh+dt, mark.rutland
  Cc: daniel.lezcano, tglx, devicetree, linux-kernel, Noam Camus

From: Noam Camus <noamca@mellanox.com>

This header file is for NPS400 SoC.
It includes macros for save/restore of HW scheduling.
Control is done by writing core functional registers.
This code was moved from arc/plat-eznps so it can be used
from driver/clocksourec/, available only for CONFIG_EZNPS_MTM_EXT.

Signed-off-by: Noam Camus <noamca@mellanox.com>
---
 include/soc/nps/mtm.h |   61 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 61 insertions(+), 0 deletions(-)
 create mode 100644 include/soc/nps/mtm.h

diff --git a/include/soc/nps/mtm.h b/include/soc/nps/mtm.h
new file mode 100644
index 0000000..9327010
--- /dev/null
+++ b/include/soc/nps/mtm.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SOC_NPS_MTM_H
+#define SOC_NPS_MTM_H
+
+#define CTOP_INST_HWSCHD_OFF_R3                 0x3B6F00BF
+#define CTOP_INST_HWSCHD_RESTORE_R3             0x3E6F70C3
+
+#define DEFINE_SCHD_FLAG(type, name)    type name
+
+static inline void hw_schd_save(unsigned int *flags)
+{
+	__asm__ __volatile__(
+	"       .word %1\n"
+	"       st r3,[%0]\n"
+	:
+	: "r"(flags), "i"(CTOP_INST_HWSCHD_OFF_R3)
+	: "r3", "memory");
+}
+
+static inline void hw_schd_restore(unsigned int flags)
+{
+	__asm__ __volatile__(
+	"       mov r3, %0\n"
+	"       .word %1\n"
+	:
+	: "r"(flags), "i"(CTOP_INST_HWSCHD_RESTORE_R3)
+	: "r3");
+}
+
+#endif /* SOC_NPS_MTM_H */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 1/3] soc: Support for NPS HW scheduling
@ 2016-10-13 14:52   ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-13 14:52 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
  Cc: daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
	tglx-hfZtesqFncYOwBW4kG4KsQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Noam Camus

From: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

This header file is for NPS400 SoC.
It includes macros for save/restore of HW scheduling.
Control is done by writing core functional registers.
This code was moved from arc/plat-eznps so it can be used
from driver/clocksourec/, available only for CONFIG_EZNPS_MTM_EXT.

Signed-off-by: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 include/soc/nps/mtm.h |   61 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 61 insertions(+), 0 deletions(-)
 create mode 100644 include/soc/nps/mtm.h

diff --git a/include/soc/nps/mtm.h b/include/soc/nps/mtm.h
new file mode 100644
index 0000000..9327010
--- /dev/null
+++ b/include/soc/nps/mtm.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef SOC_NPS_MTM_H
+#define SOC_NPS_MTM_H
+
+#define CTOP_INST_HWSCHD_OFF_R3                 0x3B6F00BF
+#define CTOP_INST_HWSCHD_RESTORE_R3             0x3E6F70C3
+
+#define DEFINE_SCHD_FLAG(type, name)    type name
+
+static inline void hw_schd_save(unsigned int *flags)
+{
+	__asm__ __volatile__(
+	"       .word %1\n"
+	"       st r3,[%0]\n"
+	:
+	: "r"(flags), "i"(CTOP_INST_HWSCHD_OFF_R3)
+	: "r3", "memory");
+}
+
+static inline void hw_schd_restore(unsigned int flags)
+{
+	__asm__ __volatile__(
+	"       mov r3, %0\n"
+	"       .word %1\n"
+	:
+	: "r"(flags), "i"(CTOP_INST_HWSCHD_RESTORE_R3)
+	: "r3");
+}
+
+#endif /* SOC_NPS_MTM_H */
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/3] ARC: [plat-eznps] remove macros for timer0 TSI
  2016-10-13 14:52 ` Noam Camus
@ 2016-10-13 14:52   ` Noam Camus
  -1 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-13 14:52 UTC (permalink / raw)
  To: robh+dt, mark.rutland
  Cc: daniel.lezcano, tglx, devicetree, linux-kernel, Noam Camus

From: Noam Camus <noamca@mellanox.com>

Now it is defined at include/soc/nps/mtm.h
It will be used by module from driver/clocksource/

Signed-off-by: Noam Camus <noamca@mellanox.com>
---
 arch/arc/plat-eznps/include/plat/ctop.h |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
index 9d6718c..ee2e32d 100644
--- a/arch/arc/plat-eznps/include/plat/ctop.h
+++ b/arch/arc/plat-eznps/include/plat/ctop.h
@@ -46,9 +46,7 @@
 #define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
 
 /* EZchip core instructions */
-#define CTOP_INST_HWSCHD_OFF_R3			0x3B6F00BF
 #define CTOP_INST_HWSCHD_OFF_R4			0x3C6F00BF
-#define CTOP_INST_HWSCHD_RESTORE_R3		0x3E6F70C3
 #define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
 #define CTOP_INST_SCHD_RW			0x3E6F7004
 #define CTOP_INST_SCHD_RD			0x3E6F7084
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/3] ARC: [plat-eznps] remove macros for timer0 TSI
@ 2016-10-13 14:52   ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-13 14:52 UTC (permalink / raw)
  To: robh+dt, mark.rutland
  Cc: daniel.lezcano, tglx, devicetree, linux-kernel, Noam Camus

From: Noam Camus <noamca@mellanox.com>

Now it is defined at include/soc/nps/mtm.h
It will be used by module from driver/clocksource/

Signed-off-by: Noam Camus <noamca@mellanox.com>
---
 arch/arc/plat-eznps/include/plat/ctop.h |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
index 9d6718c..ee2e32d 100644
--- a/arch/arc/plat-eznps/include/plat/ctop.h
+++ b/arch/arc/plat-eznps/include/plat/ctop.h
@@ -46,9 +46,7 @@
 #define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
 
 /* EZchip core instructions */
-#define CTOP_INST_HWSCHD_OFF_R3			0x3B6F00BF
 #define CTOP_INST_HWSCHD_OFF_R4			0x3C6F00BF
-#define CTOP_INST_HWSCHD_RESTORE_R3		0x3E6F70C3
 #define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
 #define CTOP_INST_SCHD_RW			0x3E6F7004
 #define CTOP_INST_SCHD_RD			0x3E6F7084
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
@ 2016-10-13 14:52   ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-13 14:52 UTC (permalink / raw)
  To: robh+dt, mark.rutland
  Cc: daniel.lezcano, tglx, devicetree, linux-kernel, Noam Camus, John Stultz

From: Noam Camus <noamca@mellanox.com>

Till now we used clockevent from generic ARC driver.
This was enough as long as we worked with simple multicore SoC.
When we are working with multithread SoC each HW thread can be
scheduled to receive timer interrupt using timer mask register
(TSI1).

This patch will provide a way to control clock events per
HW thread.

Driver can be used from device tree by:
compatible = "ezchip,nps400-timer0" <-- for clocksource
compatible = "ezchip,nps400-timer1" <-- for clockevent

Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Signed-off-by: Noam Camus <noamca@mellanox.com>
---
 .../bindings/timer/ezchip,nps400-timer.txt         |   15 --
 .../bindings/timer/ezchip,nps400-timer0.txt        |   17 ++
 .../bindings/timer/ezchip,nps400-timer1.txt        |   15 ++
 drivers/clocksource/timer-nps.c                    |  239 +++++++++++++++++++-
 4 files changed, 261 insertions(+), 25 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt

diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
deleted file mode 100644
index c8c03d7..0000000
--- a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-NPS Network Processor
-
-Required properties:
-
-- compatible :	should be "ezchip,nps400-timer"
-
-Clocks required for compatible = "ezchip,nps400-timer":
-- clocks : Must contain a single entry describing the clock input
-
-Example:
-
-timer {
-	compatible = "ezchip,nps400-timer";
-	clocks = <&sysclk>;
-};
diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
new file mode 100644
index 0000000..e3cfce8
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
@@ -0,0 +1,17 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer0"
+
+Clocks required for compatible = "ezchip,nps400-timer0":
+- interrupts : The interrupt of the first timer
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer0";
+	interrupts = <3>;
+	clocks = <&sysclk>;
+};
diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
new file mode 100644
index 0000000..c0ab419
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
@@ -0,0 +1,15 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer1"
+
+Clocks required for compatible = "ezchip,nps400-timer1":
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer1";
+	clocks = <&sysclk>;
+};
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
index 70c149a..6134dd2 100644
--- a/drivers/clocksource/timer-nps.c
+++ b/drivers/clocksource/timer-nps.c
@@ -46,7 +46,7 @@
 /* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */
 static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly;
 
-static unsigned long nps_timer_rate;
+static unsigned long nps_timer1_freq;
 
 static cycle_t nps_clksrc_read(struct clocksource *clksrc)
 {
@@ -55,11 +55,17 @@ static cycle_t nps_clksrc_read(struct clocksource *clksrc)
 	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
 }
 
-static int __init nps_setup_clocksource(struct device_node *node,
-					struct clk *clk)
+static void __init nps_setup_clocksource(struct device_node *node)
 {
+	struct clk *clk;
 	int ret, cluster;
 
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk)) {
+		pr_err("Can't get timer clock.\n");
+		return;
+	}
+
 	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
 		nps_msu_reg_low_addr[cluster] =
 			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
@@ -71,10 +77,10 @@ static int __init nps_setup_clocksource(struct device_node *node,
 		return ret;
 	}
 
-	nps_timer_rate = clk_get_rate(clk);
+	nps_timer1_freq = clk_get_rate(clk);
 
-	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick",
-				    nps_timer_rate, 301, 32, nps_clksrc_read);
+	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "nps-tick",
+				    nps_timer1_freq, 301, 32, nps_clksrc_read);
 	if (ret) {
 		pr_err("Couldn't register clock source.\n");
 		clk_disable_unprepare(clk);
@@ -83,9 +89,199 @@ static int __init nps_setup_clocksource(struct device_node *node,
 	return ret;
 }
 
-static int __init nps_timer_init(struct device_node *node)
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer1",
+		       nps_setup_clocksource);
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#include <soc/nps/mtm.h>
+
+/* Timer related Aux registers */
+#define AUX_REG_TIMER0_TSI	0xFFFFF850	/* timer 0 HW threads mask */
+#define NPS_REG_TIMER0_LIMIT	0x23		/* timer 0 limit */
+#define NPS_REG_TIMER0_CTRL	0x22		/* timer 0 control */
+#define NPS_REG_TIMER0_CNT	0x21		/* timer 0 count */
+
+#define TIMER0_CTRL_IE	(1 << 0) /* Interrupt when Count reaches limit */
+#define TIMER0_CTRL_NH	(1 << 1) /* Count only when CPU NOT halted */
+
+#define NPS_TIMER_MAX	0xFFFFFFFF
+
+static unsigned long nps_timer0_freq;
+static unsigned long nps_timer0_irq;
+
+/*
+ * Arm the timer to interrupt after @cycles
+ */
+static void nps_clkevent_timer_event_setup(unsigned int cycles)
+{
+	write_aux_reg(NPS_REG_TIMER0_LIMIT, cycles);
+	write_aux_reg(NPS_REG_TIMER0_CNT, 0);   /* start from 0 */
+
+	write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+}
+
+static void nps_clkevent_rm_thread(bool remove_thread)
+{
+	unsigned int cflags;
+	unsigned int enabled_threads;
+	unsigned long flags;
+	int thread;
+
+	local_irq_save(flags);
+	hw_schd_save(&cflags);
+
+	enabled_threads = read_aux_reg(AUX_REG_TIMER0_TSI);
+
+	/* remove thread from TSI1 */
+	if (remove_thread) {
+		thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+		enabled_threads &= ~(1 << thread);
+		write_aux_reg(AUX_REG_TIMER0_TSI, enabled_threads);
+	}
+
+	/* Re-arm the timer if needed */
+	if (!enabled_threads)
+		write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_NH);
+	else
+		write_aux_reg(NPS_REG_TIMER0_CTRL,
+			      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+	local_irq_restore(flags);
+}
+
+static void nps_clkevent_add_thread(bool set_event)
+{
+	int thread;
+	unsigned int cflags, enabled_threads;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	hw_schd_save(&cflags);
+
+	/* add thread to TSI1 */
+	thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+	enabled_threads = read_aux_reg(AUX_REG_TIMER0_TSI);
+	enabled_threads |= (1 << thread);
+	write_aux_reg(AUX_REG_TIMER0_TSI, enabled_threads);
+
+	/* set next timer event */
+	if (set_event)
+		write_aux_reg(NPS_REG_TIMER0_CTRL,
+			      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+	local_irq_restore(flags);
+}
+
+static int nps_clkevent_set_next_event(unsigned long delta,
+				       struct clock_event_device *dev)
+{
+	struct irq_desc *desc = irq_to_desc(nps_timer0_irq);
+	struct irq_chip *chip = irq_data_get_irq_chip(&desc->irq_data);
+
+	nps_clkevent_add_thread(true);
+	chip->irq_unmask(&desc->irq_data);
+
+	return 0;
+}
+
+/*
+ * Whenever anyone tries to change modes, we just mask interrupts
+ * and wait for the next event to get set.
+ */
+static int nps_clkevent_timer_shutdown(struct clock_event_device *dev)
+{
+	struct irq_desc *desc = irq_to_desc(nps_timer0_irq);
+	struct irq_chip *chip = irq_data_get_irq_chip(&desc->irq_data);
+
+	chip->irq_mask(&desc->irq_data);
+
+	return 0;
+}
+
+static int nps_clkevent_set_periodic(struct clock_event_device *dev)
 {
+	nps_clkevent_add_thread(false);
+	if (read_aux_reg(CTOP_AUX_THREAD_ID) == 0)
+		nps_clkevent_timer_event_setup(nps_timer0_freq / HZ);
+
+	return 0;
+}
+
+static int nps_clkevent_set_oneshot(struct clock_event_device *dev)
+{
+	nps_clkevent_rm_thread(true);
+	nps_clkevent_timer_shutdown(dev);
+
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
+	.name				=	"NPS Timer0",
+	.features			=	CLOCK_EVT_FEAT_ONESHOT |
+						CLOCK_EVT_FEAT_PERIODIC,
+	.rating				=	300,
+	.set_next_event			=	nps_clkevent_set_next_event,
+	.set_state_periodic		=	nps_clkevent_set_periodic,
+	.set_state_oneshot		=	nps_clkevent_set_oneshot,
+	.set_state_oneshot_stopped	=	nps_clkevent_timer_shutdown,
+	.set_state_shutdown		=	nps_clkevent_timer_shutdown,
+	.tick_resume			=	nps_clkevent_timer_shutdown,
+};
+
+static irqreturn_t timer_irq_handler(int irq, void *dev_id)
+{
+	/*
+	 * Note that generic IRQ core could have passed @evt for @dev_id if
+	 * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
+	 */
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+	int irq_reenable = clockevent_state_periodic(evt);
+
+	nps_clkevent_rm_thread(!irq_reenable);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static int nps_timer_cpu_notify(struct notifier_block *self,
+				unsigned long action, void *hcpu)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		clockevents_config_and_register(evt, nps_timer0_freq,
+						0, ULONG_MAX);
+		enable_percpu_irq(nps_timer0_irq, 0);
+		break;
+	case CPU_DYING:
+		disable_percpu_irq(nps_timer0_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block nps_timer_cpu_nb = {
+	.notifier_call = nps_timer_cpu_notify,
+};
+
+static void __init nps_setup_clockevent(struct device_node *node)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
 	struct clk *clk;
+	int ret;
+
+	nps_timer0_irq = irq_of_parse_and_map(node, 0);
+	if (nps_timer0_irq <= 0) {
+		pr_err("Can't parse IRQ");
+		return;
+	}
 
 	clk = of_clk_get(node, 0);
 	if (IS_ERR(clk)) {
@@ -93,8 +289,31 @@ static int __init nps_timer_init(struct device_node *node)
 		return PTR_ERR(clk);
 	}
 
-	return nps_setup_clocksource(node, clk);
+	register_cpu_notifier(&nps_timer_cpu_nb);
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clock\n");
+		return;
+	}
+
+	nps_timer0_freq = clk_get_rate(clk);
+	evt->irq = nps_timer0_irq;
+	evt->cpumask = cpumask_of(smp_processor_id());
+	clockevents_config_and_register(evt, nps_timer0_freq,
+					0, NPS_TIMER_MAX);
+
+	/* Needs apriori irq_set_percpu_devid() done in intc map function */
+	ret = request_percpu_irq(nps_timer0_irq, timer_irq_handler,
+				 "Timer0 (per-cpu-tick)", evt);
+	if (ret) {
+		pr_err("Couldn't request irq\n");
+		clk_disable_unprepare(clk);
+	}
+
+	enable_percpu_irq(nps_timer0_irq, 0);
 }
 
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
-		       nps_timer_init);
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clkevt, "ezchip,nps400-timer0",
+		       nps_setup_clockevent);
+#endif /* CONFIG_EZNPS_MTM_EXT */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
@ 2016-10-13 14:52   ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-13 14:52 UTC (permalink / raw)
  To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
  Cc: daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
	tglx-hfZtesqFncYOwBW4kG4KsQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Noam Camus, John Stultz

From: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>

Till now we used clockevent from generic ARC driver.
This was enough as long as we worked with simple multicore SoC.
When we are working with multithread SoC each HW thread can be
scheduled to receive timer interrupt using timer mask register
(TSI1).

This patch will provide a way to control clock events per
HW thread.

Driver can be used from device tree by:
compatible = "ezchip,nps400-timer0" <-- for clocksource
compatible = "ezchip,nps400-timer1" <-- for clockevent

Cc: Daniel Lezcano <daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
Cc: John Stultz <john.stultz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
 .../bindings/timer/ezchip,nps400-timer.txt         |   15 --
 .../bindings/timer/ezchip,nps400-timer0.txt        |   17 ++
 .../bindings/timer/ezchip,nps400-timer1.txt        |   15 ++
 drivers/clocksource/timer-nps.c                    |  239 +++++++++++++++++++-
 4 files changed, 261 insertions(+), 25 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt

diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
deleted file mode 100644
index c8c03d7..0000000
--- a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-NPS Network Processor
-
-Required properties:
-
-- compatible :	should be "ezchip,nps400-timer"
-
-Clocks required for compatible = "ezchip,nps400-timer":
-- clocks : Must contain a single entry describing the clock input
-
-Example:
-
-timer {
-	compatible = "ezchip,nps400-timer";
-	clocks = <&sysclk>;
-};
diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
new file mode 100644
index 0000000..e3cfce8
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
@@ -0,0 +1,17 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer0"
+
+Clocks required for compatible = "ezchip,nps400-timer0":
+- interrupts : The interrupt of the first timer
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer0";
+	interrupts = <3>;
+	clocks = <&sysclk>;
+};
diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
new file mode 100644
index 0000000..c0ab419
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
@@ -0,0 +1,15 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer1"
+
+Clocks required for compatible = "ezchip,nps400-timer1":
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer1";
+	clocks = <&sysclk>;
+};
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
index 70c149a..6134dd2 100644
--- a/drivers/clocksource/timer-nps.c
+++ b/drivers/clocksource/timer-nps.c
@@ -46,7 +46,7 @@
 /* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */
 static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly;
 
-static unsigned long nps_timer_rate;
+static unsigned long nps_timer1_freq;
 
 static cycle_t nps_clksrc_read(struct clocksource *clksrc)
 {
@@ -55,11 +55,17 @@ static cycle_t nps_clksrc_read(struct clocksource *clksrc)
 	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
 }
 
-static int __init nps_setup_clocksource(struct device_node *node,
-					struct clk *clk)
+static void __init nps_setup_clocksource(struct device_node *node)
 {
+	struct clk *clk;
 	int ret, cluster;
 
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk)) {
+		pr_err("Can't get timer clock.\n");
+		return;
+	}
+
 	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
 		nps_msu_reg_low_addr[cluster] =
 			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
@@ -71,10 +77,10 @@ static int __init nps_setup_clocksource(struct device_node *node,
 		return ret;
 	}
 
-	nps_timer_rate = clk_get_rate(clk);
+	nps_timer1_freq = clk_get_rate(clk);
 
-	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick",
-				    nps_timer_rate, 301, 32, nps_clksrc_read);
+	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "nps-tick",
+				    nps_timer1_freq, 301, 32, nps_clksrc_read);
 	if (ret) {
 		pr_err("Couldn't register clock source.\n");
 		clk_disable_unprepare(clk);
@@ -83,9 +89,199 @@ static int __init nps_setup_clocksource(struct device_node *node,
 	return ret;
 }
 
-static int __init nps_timer_init(struct device_node *node)
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer1",
+		       nps_setup_clocksource);
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#include <soc/nps/mtm.h>
+
+/* Timer related Aux registers */
+#define AUX_REG_TIMER0_TSI	0xFFFFF850	/* timer 0 HW threads mask */
+#define NPS_REG_TIMER0_LIMIT	0x23		/* timer 0 limit */
+#define NPS_REG_TIMER0_CTRL	0x22		/* timer 0 control */
+#define NPS_REG_TIMER0_CNT	0x21		/* timer 0 count */
+
+#define TIMER0_CTRL_IE	(1 << 0) /* Interrupt when Count reaches limit */
+#define TIMER0_CTRL_NH	(1 << 1) /* Count only when CPU NOT halted */
+
+#define NPS_TIMER_MAX	0xFFFFFFFF
+
+static unsigned long nps_timer0_freq;
+static unsigned long nps_timer0_irq;
+
+/*
+ * Arm the timer to interrupt after @cycles
+ */
+static void nps_clkevent_timer_event_setup(unsigned int cycles)
+{
+	write_aux_reg(NPS_REG_TIMER0_LIMIT, cycles);
+	write_aux_reg(NPS_REG_TIMER0_CNT, 0);   /* start from 0 */
+
+	write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+}
+
+static void nps_clkevent_rm_thread(bool remove_thread)
+{
+	unsigned int cflags;
+	unsigned int enabled_threads;
+	unsigned long flags;
+	int thread;
+
+	local_irq_save(flags);
+	hw_schd_save(&cflags);
+
+	enabled_threads = read_aux_reg(AUX_REG_TIMER0_TSI);
+
+	/* remove thread from TSI1 */
+	if (remove_thread) {
+		thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+		enabled_threads &= ~(1 << thread);
+		write_aux_reg(AUX_REG_TIMER0_TSI, enabled_threads);
+	}
+
+	/* Re-arm the timer if needed */
+	if (!enabled_threads)
+		write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_NH);
+	else
+		write_aux_reg(NPS_REG_TIMER0_CTRL,
+			      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+	local_irq_restore(flags);
+}
+
+static void nps_clkevent_add_thread(bool set_event)
+{
+	int thread;
+	unsigned int cflags, enabled_threads;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	hw_schd_save(&cflags);
+
+	/* add thread to TSI1 */
+	thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+	enabled_threads = read_aux_reg(AUX_REG_TIMER0_TSI);
+	enabled_threads |= (1 << thread);
+	write_aux_reg(AUX_REG_TIMER0_TSI, enabled_threads);
+
+	/* set next timer event */
+	if (set_event)
+		write_aux_reg(NPS_REG_TIMER0_CTRL,
+			      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+	local_irq_restore(flags);
+}
+
+static int nps_clkevent_set_next_event(unsigned long delta,
+				       struct clock_event_device *dev)
+{
+	struct irq_desc *desc = irq_to_desc(nps_timer0_irq);
+	struct irq_chip *chip = irq_data_get_irq_chip(&desc->irq_data);
+
+	nps_clkevent_add_thread(true);
+	chip->irq_unmask(&desc->irq_data);
+
+	return 0;
+}
+
+/*
+ * Whenever anyone tries to change modes, we just mask interrupts
+ * and wait for the next event to get set.
+ */
+static int nps_clkevent_timer_shutdown(struct clock_event_device *dev)
+{
+	struct irq_desc *desc = irq_to_desc(nps_timer0_irq);
+	struct irq_chip *chip = irq_data_get_irq_chip(&desc->irq_data);
+
+	chip->irq_mask(&desc->irq_data);
+
+	return 0;
+}
+
+static int nps_clkevent_set_periodic(struct clock_event_device *dev)
 {
+	nps_clkevent_add_thread(false);
+	if (read_aux_reg(CTOP_AUX_THREAD_ID) == 0)
+		nps_clkevent_timer_event_setup(nps_timer0_freq / HZ);
+
+	return 0;
+}
+
+static int nps_clkevent_set_oneshot(struct clock_event_device *dev)
+{
+	nps_clkevent_rm_thread(true);
+	nps_clkevent_timer_shutdown(dev);
+
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
+	.name				=	"NPS Timer0",
+	.features			=	CLOCK_EVT_FEAT_ONESHOT |
+						CLOCK_EVT_FEAT_PERIODIC,
+	.rating				=	300,
+	.set_next_event			=	nps_clkevent_set_next_event,
+	.set_state_periodic		=	nps_clkevent_set_periodic,
+	.set_state_oneshot		=	nps_clkevent_set_oneshot,
+	.set_state_oneshot_stopped	=	nps_clkevent_timer_shutdown,
+	.set_state_shutdown		=	nps_clkevent_timer_shutdown,
+	.tick_resume			=	nps_clkevent_timer_shutdown,
+};
+
+static irqreturn_t timer_irq_handler(int irq, void *dev_id)
+{
+	/*
+	 * Note that generic IRQ core could have passed @evt for @dev_id if
+	 * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
+	 */
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+	int irq_reenable = clockevent_state_periodic(evt);
+
+	nps_clkevent_rm_thread(!irq_reenable);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static int nps_timer_cpu_notify(struct notifier_block *self,
+				unsigned long action, void *hcpu)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		clockevents_config_and_register(evt, nps_timer0_freq,
+						0, ULONG_MAX);
+		enable_percpu_irq(nps_timer0_irq, 0);
+		break;
+	case CPU_DYING:
+		disable_percpu_irq(nps_timer0_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block nps_timer_cpu_nb = {
+	.notifier_call = nps_timer_cpu_notify,
+};
+
+static void __init nps_setup_clockevent(struct device_node *node)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
 	struct clk *clk;
+	int ret;
+
+	nps_timer0_irq = irq_of_parse_and_map(node, 0);
+	if (nps_timer0_irq <= 0) {
+		pr_err("Can't parse IRQ");
+		return;
+	}
 
 	clk = of_clk_get(node, 0);
 	if (IS_ERR(clk)) {
@@ -93,8 +289,31 @@ static int __init nps_timer_init(struct device_node *node)
 		return PTR_ERR(clk);
 	}
 
-	return nps_setup_clocksource(node, clk);
+	register_cpu_notifier(&nps_timer_cpu_nb);
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clock\n");
+		return;
+	}
+
+	nps_timer0_freq = clk_get_rate(clk);
+	evt->irq = nps_timer0_irq;
+	evt->cpumask = cpumask_of(smp_processor_id());
+	clockevents_config_and_register(evt, nps_timer0_freq,
+					0, NPS_TIMER_MAX);
+
+	/* Needs apriori irq_set_percpu_devid() done in intc map function */
+	ret = request_percpu_irq(nps_timer0_irq, timer_irq_handler,
+				 "Timer0 (per-cpu-tick)", evt);
+	if (ret) {
+		pr_err("Couldn't request irq\n");
+		clk_disable_unprepare(clk);
+	}
+
+	enable_percpu_irq(nps_timer0_irq, 0);
 }
 
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
-		       nps_timer_init);
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clkevt, "ezchip,nps400-timer0",
+		       nps_setup_clockevent);
+#endif /* CONFIG_EZNPS_MTM_EXT */
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
  2016-10-13 14:52   ` Noam Camus
  (?)
@ 2016-10-18 13:57   ` Rob Herring
  2016-10-18 14:32       ` Noam Camus
  2016-10-18 14:51       ` Noam Camus
  -1 siblings, 2 replies; 18+ messages in thread
From: Rob Herring @ 2016-10-18 13:57 UTC (permalink / raw)
  To: Noam Camus
  Cc: mark.rutland, daniel.lezcano, tglx, devicetree, linux-kernel,
	John Stultz

On Thu, Oct 13, 2016 at 05:52:30PM +0300, Noam Camus wrote:
> From: Noam Camus <noamca@mellanox.com>
> 
> Till now we used clockevent from generic ARC driver.
> This was enough as long as we worked with simple multicore SoC.
> When we are working with multithread SoC each HW thread can be
> scheduled to receive timer interrupt using timer mask register
> (TSI1).
> 
> This patch will provide a way to control clock events per
> HW thread.
> 
> Driver can be used from device tree by:
> compatible = "ezchip,nps400-timer0" <-- for clocksource
> compatible = "ezchip,nps400-timer1" <-- for clockevent

You're letting Linux details define the binding. Are these blocks 
different (the block itself, not connections to the block like 
interrupts)?

If you need a particular timer instance to be used, then describe 
whatever is the difference in the h/w.  For example, the clockevent 
timer has to be the timer with an interrupt.

Rob

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
  2016-10-18 13:57   ` Rob Herring
@ 2016-10-18 14:32       ` Noam Camus
  2016-10-18 14:51       ` Noam Camus
  1 sibling, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-18 14:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: mark.rutland, daniel.lezcano, tglx, devicetree, linux-kernel,
	John Stultz

> From: Rob Herring [mailto:robh@kernel.org] 
> Sent: Tuesday, October 18, 2016 4:57 PM

>> 
>> Driver can be used from device tree by:
>> compatible = "ezchip,nps400-timer0" <-- for clocksource compatible = 
>> "ezchip,nps400-timer1" <-- for clockevent

>You're letting Linux details define the binding. Are these blocks different (the block itself, not connections to >the block like interrupts)?


>If you need a particular timer instance to be used, then describe whatever is the difference in the h/w.  For >example, the clockevent timer has to be the timer with an interrupt.

Yes, blocks are different.
The difference is that only second timer instance are actually producing timer interrupt served by Linux for the clockevent framework.
Please note that the numbering used here for timer (i.e. 0 or 1) are derived from HW blocks and are not any Linux detail I used for binding definition (It is a note at this patch set cover letter).

Noam

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
@ 2016-10-18 14:32       ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-18 14:32 UTC (permalink / raw)
  To: Rob Herring
  Cc: mark.rutland-5wv7dgnIgG8, daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
	tglx-hfZtesqFncYOwBW4kG4KsQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, John Stultz

> From: Rob Herring [mailto:robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org] 
> Sent: Tuesday, October 18, 2016 4:57 PM

>> 
>> Driver can be used from device tree by:
>> compatible = "ezchip,nps400-timer0" <-- for clocksource compatible = 
>> "ezchip,nps400-timer1" <-- for clockevent

>You're letting Linux details define the binding. Are these blocks different (the block itself, not connections to >the block like interrupts)?


>If you need a particular timer instance to be used, then describe whatever is the difference in the h/w.  For >example, the clockevent timer has to be the timer with an interrupt.

Yes, blocks are different.
The difference is that only second timer instance are actually producing timer interrupt served by Linux for the clockevent framework.
Please note that the numbering used here for timer (i.e. 0 or 1) are derived from HW blocks and are not any Linux detail I used for binding definition (It is a note at this patch set cover letter).

Noam
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
  2016-10-18 13:57   ` Rob Herring
@ 2016-10-18 14:51       ` Noam Camus
  2016-10-18 14:51       ` Noam Camus
  1 sibling, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-18 14:51 UTC (permalink / raw)
  To: Rob Herring
  Cc: mark.rutland, daniel.lezcano, tglx, devicetree, linux-kernel,
	John Stultz

>From: Noam Camus 
>Sent: Tuesday, October 18, 2016 5:33 PM


>>You're letting Linux details define the binding. Are these blocks different (the block itself, not connections to >the block like interrupts)?


>>If you need a particular timer instance to be used, then describe whatever is the difference in the h/w.  For >example, the clockevent timer has to be the timer with an interrupt.

>Yes, blocks are different.
>The difference is that only second timer instance are actually producing timer interrupt served by Linux for the clockevent framework.
>Please note that the numbering used here for timer (i.e. 0 or 1) are derived from HW blocks and are not any Linux detail I used for binding definition (It is a note at this patch set cover letter).

The timers actually are: first instance (timer 0) for clockevents and second instance (timer 1) for clocksource.
Sorry for the confusion.

Noam

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
@ 2016-10-18 14:51       ` Noam Camus
  0 siblings, 0 replies; 18+ messages in thread
From: Noam Camus @ 2016-10-18 14:51 UTC (permalink / raw)
  To: Rob Herring
  Cc: mark.rutland-5wv7dgnIgG8, daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
	tglx-hfZtesqFncYOwBW4kG4KsQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, John Stultz

>From: Noam Camus 
>Sent: Tuesday, October 18, 2016 5:33 PM


>>You're letting Linux details define the binding. Are these blocks different (the block itself, not connections to >the block like interrupts)?


>>If you need a particular timer instance to be used, then describe whatever is the difference in the h/w.  For >example, the clockevent timer has to be the timer with an interrupt.

>Yes, blocks are different.
>The difference is that only second timer instance are actually producing timer interrupt served by Linux for the clockevent framework.
>Please note that the numbering used here for timer (i.e. 0 or 1) are derived from HW blocks and are not any Linux detail I used for binding definition (It is a note at this patch set cover letter).

The timers actually are: first instance (timer 0) for clockevents and second instance (timer 1) for clocksource.
Sorry for the confusion.

Noam
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/3] soc: Support for NPS HW scheduling
  2016-10-13 14:52   ` Noam Camus
  (?)
@ 2016-10-21 13:52   ` Daniel Lezcano
  -1 siblings, 0 replies; 18+ messages in thread
From: Daniel Lezcano @ 2016-10-21 13:52 UTC (permalink / raw)
  To: Noam Camus; +Cc: robh+dt, mark.rutland, tglx, devicetree, linux-kernel

On Thu, Oct 13, 2016 at 05:52:28PM +0300, Noam Camus wrote:
> From: Noam Camus <noamca@mellanox.com>
> 
> This header file is for NPS400 SoC.
> It includes macros for save/restore of HW scheduling.
> Control is done by writing core functional registers.
> This code was moved from arc/plat-eznps so it can be used
> from driver/clocksourec/, available only for CONFIG_EZNPS_MTM_EXT.

drivers/clocksource

> Signed-off-by: Noam Camus <noamca@mellanox.com>
> ---
>  include/soc/nps/mtm.h |   61 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 61 insertions(+), 0 deletions(-)
>  create mode 100644 include/soc/nps/mtm.h
> 
> diff --git a/include/soc/nps/mtm.h b/include/soc/nps/mtm.h
> new file mode 100644
> index 0000000..9327010
> --- /dev/null
> +++ b/include/soc/nps/mtm.h
> @@ -0,0 +1,61 @@
> +/*
> + * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#ifndef SOC_NPS_MTM_H
> +#define SOC_NPS_MTM_H
> +
> +#define CTOP_INST_HWSCHD_OFF_R3                 0x3B6F00BF
> +#define CTOP_INST_HWSCHD_RESTORE_R3             0x3E6F70C3
> +
> +#define DEFINE_SCHD_FLAG(type, name)    type name

What is the purpose of this macro ?

> +static inline void hw_schd_save(unsigned int *flags)
> +{
> +	__asm__ __volatile__(
> +	"       .word %1\n"
> +	"       st r3,[%0]\n"
> +	:
> +	: "r"(flags), "i"(CTOP_INST_HWSCHD_OFF_R3)
> +	: "r3", "memory");
> +}
> +
> +static inline void hw_schd_restore(unsigned int flags)
> +{
> +	__asm__ __volatile__(
> +	"       mov r3, %0\n"
> +	"       .word %1\n"
> +	:
> +	: "r"(flags), "i"(CTOP_INST_HWSCHD_RESTORE_R3)
> +	: "r3");
> +}
> +
> +#endif /* SOC_NPS_MTM_H */
> -- 
> 1.7.1
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] ARC: [plat-eznps] remove macros for timer0 TSI
@ 2016-10-21 14:12     ` Daniel Lezcano
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Lezcano @ 2016-10-21 14:12 UTC (permalink / raw)
  To: Noam Camus; +Cc: robh+dt, mark.rutland, tglx, devicetree, linux-kernel

On Thu, Oct 13, 2016 at 05:52:29PM +0300, Noam Camus wrote:
> From: Noam Camus <noamca@mellanox.com>
> 
> Now it is defined at include/soc/nps/mtm.h
> It will be used by module from driver/clocksource/
> 

This patch should be folded with the previous one in order to prevent
to break the git bisecting, otherwise there will be duplicate macros
at some point, leading to a compilation failure.


> Signed-off-by: Noam Camus <noamca@mellanox.com>
> ---
>  arch/arc/plat-eznps/include/plat/ctop.h |    2 --
>  1 files changed, 0 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
> index 9d6718c..ee2e32d 100644
> --- a/arch/arc/plat-eznps/include/plat/ctop.h
> +++ b/arch/arc/plat-eznps/include/plat/ctop.h
> @@ -46,9 +46,7 @@
>  #define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
>  
>  /* EZchip core instructions */
> -#define CTOP_INST_HWSCHD_OFF_R3			0x3B6F00BF
>  #define CTOP_INST_HWSCHD_OFF_R4			0x3C6F00BF
> -#define CTOP_INST_HWSCHD_RESTORE_R3		0x3E6F70C3
>  #define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
>  #define CTOP_INST_SCHD_RW			0x3E6F7004
>  #define CTOP_INST_SCHD_RD			0x3E6F7084
> -- 
> 1.7.1
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] ARC: [plat-eznps] remove macros for timer0 TSI
@ 2016-10-21 14:12     ` Daniel Lezcano
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Lezcano @ 2016-10-21 14:12 UTC (permalink / raw)
  To: Noam Camus
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	tglx-hfZtesqFncYOwBW4kG4KsQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Thu, Oct 13, 2016 at 05:52:29PM +0300, Noam Camus wrote:
> From: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> Now it is defined at include/soc/nps/mtm.h
> It will be used by module from driver/clocksource/
> 

This patch should be folded with the previous one in order to prevent
to break the git bisecting, otherwise there will be duplicate macros
at some point, leading to a compilation failure.


> Signed-off-by: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---
>  arch/arc/plat-eznps/include/plat/ctop.h |    2 --
>  1 files changed, 0 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
> index 9d6718c..ee2e32d 100644
> --- a/arch/arc/plat-eznps/include/plat/ctop.h
> +++ b/arch/arc/plat-eznps/include/plat/ctop.h
> @@ -46,9 +46,7 @@
>  #define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
>  
>  /* EZchip core instructions */
> -#define CTOP_INST_HWSCHD_OFF_R3			0x3B6F00BF
>  #define CTOP_INST_HWSCHD_OFF_R4			0x3C6F00BF
> -#define CTOP_INST_HWSCHD_RESTORE_R3		0x3E6F70C3
>  #define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
>  #define CTOP_INST_SCHD_RW			0x3E6F7004
>  #define CTOP_INST_SCHD_RD			0x3E6F7084
> -- 
> 1.7.1
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
@ 2016-10-21 15:08     ` Daniel Lezcano
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Lezcano @ 2016-10-21 15:08 UTC (permalink / raw)
  To: Noam Camus
  Cc: robh+dt, mark.rutland, tglx, devicetree, linux-kernel, John Stultz

On Thu, Oct 13, 2016 at 05:52:30PM +0300, Noam Camus wrote:
> From: Noam Camus <noamca@mellanox.com>
> 
> Till now we used clockevent from generic ARC driver.
> This was enough as long as we worked with simple multicore SoC.
> When we are working with multithread SoC each HW thread can be
> scheduled to receive timer interrupt using timer mask register
> (TSI1).
> 
> This patch will provide a way to control clock events per
> HW thread.

The description is not very clear. Can you elaborate ?
 
> Driver can be used from device tree by:
> compatible = "ezchip,nps400-timer0" <-- for clocksource
> compatible = "ezchip,nps400-timer1" <-- for clockevent
> 
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: John Stultz <john.stultz@linaro.org>
> Signed-off-by: Noam Camus <noamca@mellanox.com>
> ---

[ ... ]

> -static int __init nps_setup_clocksource(struct device_node *node,
> -					struct clk *clk)
> +static void __init nps_setup_clocksource(struct device_node *node)

CLOCKSOURCE_OF_DECLARE is expecting an int __init (*func)(struct device_node *)

This function returns void at the beginning then it is not changed and returns
an error value.

linux/drivers/clocksource/timer-nps.c: In function ‘nps_setup_clocksource’:
linux/drivers/clocksource/timer-nps.c:77:10: warning: ‘return’ with a value, in function returning void
   return ret;
          ^
linux/drivers/clocksource/timer-nps.c:89:9: warning: ‘return’ with a value, in function returning void
  return ret;
         ^
linux/drivers/clocksource/timer-nps.c: At top level:
linux/drivers/clocksource/timer-nps.c:92:216: warning: comparison of distinct pointer types lacks a cast

Don't submit changes which are not correctly compiled / tested, except you want to live
dangerously and watch your karma collapse.

I will let you fix this before reviewing the patches in details.

BTW, have a look at the hotplug callbacks, they changed to a finite state machine [1] and their usage
changed [2].

  -- Daniel

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=710d60cbf1b312a8075a2158cbfbbd9c66132dcc
[2] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=eb0a9d8c672dc01db41352afa646405d035ee7a4

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver
@ 2016-10-21 15:08     ` Daniel Lezcano
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Lezcano @ 2016-10-21 15:08 UTC (permalink / raw)
  To: Noam Camus
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	tglx-hfZtesqFncYOwBW4kG4KsQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, John Stultz

On Thu, Oct 13, 2016 at 05:52:30PM +0300, Noam Camus wrote:
> From: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> Till now we used clockevent from generic ARC driver.
> This was enough as long as we worked with simple multicore SoC.
> When we are working with multithread SoC each HW thread can be
> scheduled to receive timer interrupt using timer mask register
> (TSI1).
> 
> This patch will provide a way to control clock events per
> HW thread.

The description is not very clear. Can you elaborate ?
 
> Driver can be used from device tree by:
> compatible = "ezchip,nps400-timer0" <-- for clocksource
> compatible = "ezchip,nps400-timer1" <-- for clockevent
> 
> Cc: Daniel Lezcano <daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> Cc: John Stultz <john.stultz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Signed-off-by: Noam Camus <noamca-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---

[ ... ]

> -static int __init nps_setup_clocksource(struct device_node *node,
> -					struct clk *clk)
> +static void __init nps_setup_clocksource(struct device_node *node)

CLOCKSOURCE_OF_DECLARE is expecting an int __init (*func)(struct device_node *)

This function returns void at the beginning then it is not changed and returns
an error value.

linux/drivers/clocksource/timer-nps.c: In function ‘nps_setup_clocksource’:
linux/drivers/clocksource/timer-nps.c:77:10: warning: ‘return’ with a value, in function returning void
   return ret;
          ^
linux/drivers/clocksource/timer-nps.c:89:9: warning: ‘return’ with a value, in function returning void
  return ret;
         ^
linux/drivers/clocksource/timer-nps.c: At top level:
linux/drivers/clocksource/timer-nps.c:92:216: warning: comparison of distinct pointer types lacks a cast

Don't submit changes which are not correctly compiled / tested, except you want to live
dangerously and watch your karma collapse.

I will let you fix this before reviewing the patches in details.

BTW, have a look at the hotplug callbacks, they changed to a finite state machine [1] and their usage
changed [2].

  -- Daniel

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=710d60cbf1b312a8075a2158cbfbbd9c66132dcc
[2] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=eb0a9d8c672dc01db41352afa646405d035ee7a4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2016-10-21 15:09 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-13 14:52 [PATCH 0/3] Add clockevet for timer-nps driver to NPS400 SoC Noam Camus
2016-10-13 14:52 ` Noam Camus
2016-10-13 14:52 ` [PATCH 1/3] soc: Support for NPS HW scheduling Noam Camus
2016-10-13 14:52   ` Noam Camus
2016-10-21 13:52   ` Daniel Lezcano
2016-10-13 14:52 ` [PATCH 2/3] ARC: [plat-eznps] remove macros for timer0 TSI Noam Camus
2016-10-13 14:52   ` Noam Camus
2016-10-21 14:12   ` Daniel Lezcano
2016-10-21 14:12     ` Daniel Lezcano
2016-10-13 14:52 ` [PATCH 3/3] clocksource: Add clockevent support to NPS400 driver Noam Camus
2016-10-13 14:52   ` Noam Camus
2016-10-18 13:57   ` Rob Herring
2016-10-18 14:32     ` Noam Camus
2016-10-18 14:32       ` Noam Camus
2016-10-18 14:51     ` Noam Camus
2016-10-18 14:51       ` Noam Camus
2016-10-21 15:08   ` Daniel Lezcano
2016-10-21 15:08     ` Daniel Lezcano

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.