All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/20] Adding plat-eznps to ARC
@ 2015-12-27 13:23 ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

v5:
1) irqchip -- work with handle_domain_irq(), and remove use of irq_set_default_host()
2) clocksource -- initialize clockevents as well by parsing interrupts node of DT
3) Do not use IPI with irq generic infrastructure

v4:
1) irqchip -- use irq_domain_add_linear()
2) clocksource -- use of_clk_get()
3) New header at include/soc use by platform and drivers
4) update DTS file for above fixed drivers

v3:
1)	irqchip: use MACROS instead of structures to decribe
	registers.
2)	clocksource: use 32bit counter and avoid 2 halfs read
	of 64bit dance.

v2:
1)	Remove out of tree platform include path
2)	Move atomic/bitop/cmpxchg for platform to end.
	Remove macro duplication.
	Fix some bad implementation.
3)	define cpu_relax_lowlatency() for platform.
4)	rename init_irq_cpu() to init_per_cpu()
	reorder call to init_per_cpu() for secondary
	use it instead of init_cpu_smp().
5)	set res_service to call stext
6)	fix build failure for CTOP_AUX_BASE at assembly code
7)	Use ilog2 for mtm_init_nat()
8)	Add CLKSRC_NPS option to Kconfig
	change nps_clksrc_read() to be more readable.

General summay:
This set introduce new platform to ARC architecture.
Platform name called "eznps" for working with EZchip NPS400
Network Proccessor.
NPS400 is targeted to service "fast path" network applications.

NPS400 got mesh of 256 extended ARC cores (AKA CTOP), each core
got 16 HW threads. This is basically SMT core where at any point of
time only one HW thread is active.
Each core have HW scheduler that round robin between eligible HW
threads. Totaly, kernel sees 4096 CPUs which I belive is a high record.
There is no cache coherency between cores so generic user applications
and kernel do not use D$.

Cores got special memory mappings for huge pages (8MB).
Mapping is static and should provide application enough memory without
any "TLB miss". This mapping is on top of TLB mapping.

This is a basic set that will later be followed with additional
set of patches with all advanced features.

Many thanks to all people helping to make this happen.

Regards,
Noam Camus

Noam Camus (19):
  Documentation: Add EZchip vendor to binding list
  soc: Support for EZchip SoC
  ARC: [plat-eznps] define IPI_IRQ
  clocksource: Add NPS400 timers driver
  irqchip: add nps Internal and external irqchips
  ARC: Set vmalloc size from configuration
  ARC: rwlock: disable interrupts in !LLSC variant
  ARC: Mark secondary cpu online only after all HW setup is done
  ARC: IRQ: use device tree to get timer device configuration
  ARC: IRQ: do not use hwirq directly at arch_do_IRQ()
  ARC: IPI: do not use generic IRQ domain
  ARC: [plat-eznps] Add eznps board defconfig and dts
  ARC: [plat-eznps] Add eznps platform
  ARC: [plat-eznps] Use dedicated user stack top
  ARC: [plat-eznps] Use dedicated atomic/bitops/cmpxchg
  ARC: [plat-eznps] Use dedicated SMP barriers
  ARC: [plat-eznps] Use dedicated identity auxiliary register.
  ARC: [plat-eznps] Use dedicated COMMAND_LINE_SIZE
  ARC: Add eznps platform to Kconfig and Makefile

Tal Zilcer (1):
  ARC: [plat-eznps] Use dedicated cpu_relax()

 Documentation/devicetree/bindings/arc/eznps.txt    |    7 +
 .../interrupt-controller/ezchip,nps400-ic.txt      |   17 ++
 .../bindings/timer/ezchip,nps400-timer.txt         |   17 ++
 .../devicetree/bindings/vendor-prefixes.txt        |    1 +
 MAINTAINERS                                        |    6 +
 arch/arc/Kconfig                                   |   10 +
 arch/arc/Makefile                                  |    5 +
 arch/arc/boot/dts/eznps.dts                        |   94 +++++++++
 arch/arc/configs/nps_defconfig                     |   85 +++++++++
 arch/arc/include/asm/Kbuild                        |    1 -
 arch/arc/include/asm/atomic.h                      |   79 ++++++++-
 arch/arc/include/asm/barrier.h                     |    8 +
 arch/arc/include/asm/bitops.h                      |   54 ++++++
 arch/arc/include/asm/cmpxchg.h                     |   87 +++++++--
 arch/arc/include/asm/entry-compact.h               |    8 +
 arch/arc/include/asm/hardirq.h                     |   22 +++
 arch/arc/include/asm/irq.h                         |    9 +
 arch/arc/include/asm/pgtable.h                     |    2 +-
 arch/arc/include/asm/processor.h                   |   36 +++-
 arch/arc/include/asm/setup.h                       |    4 +
 arch/arc/include/asm/smp.h                         |    6 +
 arch/arc/include/asm/spinlock.h                    |   14 ++
 arch/arc/kernel/ctx_sw.c                           |   13 ++
 arch/arc/kernel/irq.c                              |   25 +++
 arch/arc/kernel/setup.c                            |    1 -
 arch/arc/kernel/smp.c                              |   39 ++++-
 arch/arc/kernel/time.c                             |    8 +
 arch/arc/mm/tlb.c                                  |   12 ++
 arch/arc/plat-eznps/Kconfig                        |   34 ++++
 arch/arc/plat-eznps/Makefile                       |    7 +
 arch/arc/plat-eznps/entry.S                        |   70 +++++++
 arch/arc/plat-eznps/include/plat/ctop.h            |  198 +++++++++++++++++++
 arch/arc/plat-eznps/include/plat/mtm.h             |   60 ++++++
 arch/arc/plat-eznps/include/plat/smp.h             |   26 +++
 arch/arc/plat-eznps/mtm.c                          |  133 +++++++++++++
 arch/arc/plat-eznps/platform.c                     |  102 ++++++++++
 arch/arc/plat-eznps/smp.c                          |  154 +++++++++++++++
 drivers/clocksource/Kconfig                        |    7 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/timer-nps.c                    |  199 ++++++++++++++++++++
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-eznps.c                        |  139 ++++++++++++++
 include/soc/nps/common.h                           |  123 ++++++++++++
 43 files changed, 1893 insertions(+), 31 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arc/eznps.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 arch/arc/boot/dts/eznps.dts
 create mode 100644 arch/arc/configs/nps_defconfig
 create mode 100644 arch/arc/include/asm/hardirq.h
 create mode 100644 arch/arc/plat-eznps/Kconfig
 create mode 100644 arch/arc/plat-eznps/Makefile
 create mode 100644 arch/arc/plat-eznps/entry.S
 create mode 100644 arch/arc/plat-eznps/include/plat/ctop.h
 create mode 100644 arch/arc/plat-eznps/include/plat/mtm.h
 create mode 100644 arch/arc/plat-eznps/include/plat/smp.h
 create mode 100644 arch/arc/plat-eznps/mtm.c
 create mode 100644 arch/arc/plat-eznps/platform.c
 create mode 100644 arch/arc/plat-eznps/smp.c
 create mode 100644 drivers/clocksource/timer-nps.c
 create mode 100644 drivers/irqchip/irq-eznps.c
 create mode 100644 include/soc/nps/common.h


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

* [PATCH v5 00/20] Adding plat-eznps to ARC
@ 2015-12-27 13:23 ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

v5:
1) irqchip -- work with handle_domain_irq(), and remove use of irq_set_default_host()
2) clocksource -- initialize clockevents as well by parsing interrupts node of DT
3) Do not use IPI with irq generic infrastructure

v4:
1) irqchip -- use irq_domain_add_linear()
2) clocksource -- use of_clk_get()
3) New header at include/soc use by platform and drivers
4) update DTS file for above fixed drivers

v3:
1)	irqchip: use MACROS instead of structures to decribe
	registers.
2)	clocksource: use 32bit counter and avoid 2 halfs read
	of 64bit dance.

v2:
1)	Remove out of tree platform include path
2)	Move atomic/bitop/cmpxchg for platform to end.
	Remove macro duplication.
	Fix some bad implementation.
3)	define cpu_relax_lowlatency() for platform.
4)	rename init_irq_cpu() to init_per_cpu()
	reorder call to init_per_cpu() for secondary
	use it instead of init_cpu_smp().
5)	set res_service to call stext
6)	fix build failure for CTOP_AUX_BASE at assembly code
7)	Use ilog2 for mtm_init_nat()
8)	Add CLKSRC_NPS option to Kconfig
	change nps_clksrc_read() to be more readable.

General summay:
This set introduce new platform to ARC architecture.
Platform name called "eznps" for working with EZchip NPS400
Network Proccessor.
NPS400 is targeted to service "fast path" network applications.

NPS400 got mesh of 256 extended ARC cores (AKA CTOP), each core
got 16 HW threads. This is basically SMT core where at any point of
time only one HW thread is active.
Each core have HW scheduler that round robin between eligible HW
threads. Totaly, kernel sees 4096 CPUs which I belive is a high record.
There is no cache coherency between cores so generic user applications
and kernel do not use D$.

Cores got special memory mappings for huge pages (8MB).
Mapping is static and should provide application enough memory without
any "TLB miss". This mapping is on top of TLB mapping.

This is a basic set that will later be followed with additional
set of patches with all advanced features.

Many thanks to all people helping to make this happen.

Regards,
Noam Camus

Noam Camus (19):
  Documentation: Add EZchip vendor to binding list
  soc: Support for EZchip SoC
  ARC: [plat-eznps] define IPI_IRQ
  clocksource: Add NPS400 timers driver
  irqchip: add nps Internal and external irqchips
  ARC: Set vmalloc size from configuration
  ARC: rwlock: disable interrupts in !LLSC variant
  ARC: Mark secondary cpu online only after all HW setup is done
  ARC: IRQ: use device tree to get timer device configuration
  ARC: IRQ: do not use hwirq directly at arch_do_IRQ()
  ARC: IPI: do not use generic IRQ domain
  ARC: [plat-eznps] Add eznps board defconfig and dts
  ARC: [plat-eznps] Add eznps platform
  ARC: [plat-eznps] Use dedicated user stack top
  ARC: [plat-eznps] Use dedicated atomic/bitops/cmpxchg
  ARC: [plat-eznps] Use dedicated SMP barriers
  ARC: [plat-eznps] Use dedicated identity auxiliary register.
  ARC: [plat-eznps] Use dedicated COMMAND_LINE_SIZE
  ARC: Add eznps platform to Kconfig and Makefile

Tal Zilcer (1):
  ARC: [plat-eznps] Use dedicated cpu_relax()

 Documentation/devicetree/bindings/arc/eznps.txt    |    7 +
 .../interrupt-controller/ezchip,nps400-ic.txt      |   17 ++
 .../bindings/timer/ezchip,nps400-timer.txt         |   17 ++
 .../devicetree/bindings/vendor-prefixes.txt        |    1 +
 MAINTAINERS                                        |    6 +
 arch/arc/Kconfig                                   |   10 +
 arch/arc/Makefile                                  |    5 +
 arch/arc/boot/dts/eznps.dts                        |   94 +++++++++
 arch/arc/configs/nps_defconfig                     |   85 +++++++++
 arch/arc/include/asm/Kbuild                        |    1 -
 arch/arc/include/asm/atomic.h                      |   79 ++++++++-
 arch/arc/include/asm/barrier.h                     |    8 +
 arch/arc/include/asm/bitops.h                      |   54 ++++++
 arch/arc/include/asm/cmpxchg.h                     |   87 +++++++--
 arch/arc/include/asm/entry-compact.h               |    8 +
 arch/arc/include/asm/hardirq.h                     |   22 +++
 arch/arc/include/asm/irq.h                         |    9 +
 arch/arc/include/asm/pgtable.h                     |    2 +-
 arch/arc/include/asm/processor.h                   |   36 +++-
 arch/arc/include/asm/setup.h                       |    4 +
 arch/arc/include/asm/smp.h                         |    6 +
 arch/arc/include/asm/spinlock.h                    |   14 ++
 arch/arc/kernel/ctx_sw.c                           |   13 ++
 arch/arc/kernel/irq.c                              |   25 +++
 arch/arc/kernel/setup.c                            |    1 -
 arch/arc/kernel/smp.c                              |   39 ++++-
 arch/arc/kernel/time.c                             |    8 +
 arch/arc/mm/tlb.c                                  |   12 ++
 arch/arc/plat-eznps/Kconfig                        |   34 ++++
 arch/arc/plat-eznps/Makefile                       |    7 +
 arch/arc/plat-eznps/entry.S                        |   70 +++++++
 arch/arc/plat-eznps/include/plat/ctop.h            |  198 +++++++++++++++++++
 arch/arc/plat-eznps/include/plat/mtm.h             |   60 ++++++
 arch/arc/plat-eznps/include/plat/smp.h             |   26 +++
 arch/arc/plat-eznps/mtm.c                          |  133 +++++++++++++
 arch/arc/plat-eznps/platform.c                     |  102 ++++++++++
 arch/arc/plat-eznps/smp.c                          |  154 +++++++++++++++
 drivers/clocksource/Kconfig                        |    7 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/timer-nps.c                    |  199 ++++++++++++++++++++
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-eznps.c                        |  139 ++++++++++++++
 include/soc/nps/common.h                           |  123 ++++++++++++
 43 files changed, 1893 insertions(+), 31 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arc/eznps.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 arch/arc/boot/dts/eznps.dts
 create mode 100644 arch/arc/configs/nps_defconfig
 create mode 100644 arch/arc/include/asm/hardirq.h
 create mode 100644 arch/arc/plat-eznps/Kconfig
 create mode 100644 arch/arc/plat-eznps/Makefile
 create mode 100644 arch/arc/plat-eznps/entry.S
 create mode 100644 arch/arc/plat-eznps/include/plat/ctop.h
 create mode 100644 arch/arc/plat-eznps/include/plat/mtm.h
 create mode 100644 arch/arc/plat-eznps/include/plat/smp.h
 create mode 100644 arch/arc/plat-eznps/mtm.c
 create mode 100644 arch/arc/plat-eznps/platform.c
 create mode 100644 arch/arc/plat-eznps/smp.c
 create mode 100644 drivers/clocksource/timer-nps.c
 create mode 100644 drivers/irqchip/irq-eznps.c
 create mode 100644 include/soc/nps/common.h

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

* [PATCH v5 01/20] Documentation: Add EZchip vendor to binding list
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus,
	Pawel Moll

From: Noam Camus <noamc@ezchip.com>

Add EZchip to vendor prefixes list.
EZchip introduce the NPS platform for the ARC architecture.

Signed-off-by: Noam Camus <noamc@ezchip.com>
Acked-by: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
---
 Documentation/devicetree/bindings/arc/eznps.txt    |    7 +++++++
 .../devicetree/bindings/vendor-prefixes.txt        |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arc/eznps.txt

diff --git a/Documentation/devicetree/bindings/arc/eznps.txt b/Documentation/devicetree/bindings/arc/eznps.txt
new file mode 100644
index 0000000..1aa50c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arc/eznps.txt
@@ -0,0 +1,7 @@
+EZchip NPS Network Processor Platforms Device Tree Bindings
+---------------------------------------------------------------------------
+
+Appliance main board with NPS400 ASIC.
+
+Required root node properties:
+    - compatible = "ezchip,arc-nps";
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..d7bff8a 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -82,6 +82,7 @@ eukrea  Eukréa Electromatique
 everest	Everest Semiconductor Co. Ltd.
 everspin	Everspin Technologies, Inc.
 excito	Excito
+ezchip	EZchip Semiconductor
 fcs	Fairchild Semiconductor
 firefly	Firefly
 focaltech	FocalTech Systems Co.,Ltd
-- 
1.7.1


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

* [PATCH v5 01/20] Documentation: Add EZchip vendor to binding list
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

Add EZchip to vendor prefixes list.
EZchip introduce the NPS platform for the ARC architecture.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Acked-by: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
---
 Documentation/devicetree/bindings/arc/eznps.txt    |    7 +++++++
 .../devicetree/bindings/vendor-prefixes.txt        |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arc/eznps.txt

diff --git a/Documentation/devicetree/bindings/arc/eznps.txt b/Documentation/devicetree/bindings/arc/eznps.txt
new file mode 100644
index 0000000..1aa50c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/arc/eznps.txt
@@ -0,0 +1,7 @@
+EZchip NPS Network Processor Platforms Device Tree Bindings
+---------------------------------------------------------------------------
+
+Appliance main board with NPS400 ASIC.
+
+Required root node properties:
+    - compatible = "ezchip,arc-nps";
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 55df1d4..d7bff8a 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -82,6 +82,7 @@ eukrea  Eukr??a Electromatique
 everest	Everest Semiconductor Co. Ltd.
 everspin	Everspin Technologies, Inc.
 excito	Excito
+ezchip	EZchip Semiconductor
 fcs	Fairchild Semiconductor
 firefly	Firefly
 focaltech	FocalTech Systems Co.,Ltd
-- 
1.7.1

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

* [PATCH v5 02/20] soc: Support for EZchip SoC
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

This header file is for NPS400 SoC.
It includes macros for accessing memory mapped registers.
These are functional registers that core can use to configure SoC.

Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 include/soc/nps/common.h |  123 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 123 insertions(+), 0 deletions(-)
 create mode 100644 include/soc/nps/common.h

diff --git a/include/soc/nps/common.h b/include/soc/nps/common.h
new file mode 100644
index 0000000..3bc30a8
--- /dev/null
+++ b/include/soc/nps/common.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef SOC_NPS_COMMON_H
+#define SOC_NPS_COMMON_H
+
+#define NPS_HOST_REG_BASE			0xF6000000
+#define CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST	0x5B60
+#define CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM	0x00010422
+
+#ifndef __ASSEMBLY__
+/* CPU global ID */
+struct global_id {
+	union {
+		struct {
+#ifdef CONFIG_EZNPS_MTM_EXT
+			u32 __reserved:20, cluster:4, core:4, thread:4;
+#else
+			u32 __reserved:24, cluster:4, core:4;
+#endif
+		};
+		u32 value;
+	};
+};
+
+/*
+ * Convert logical to physical CPU IDs
+ *
+ * The conversion swap bits 1 and 2 of cluster id (out of 4 bits)
+ * Now quad of logical clusters id's are adjacent physically,
+ * and not like the id's physically came with each cluster.
+ * Below table is 4x4 mesh of core clusters as it layout on chip.
+ * Cluster ids are in format: logical (physical)
+ *
+ *    -----------------   ------------------
+ * 3 |  5 (3)   7 (7)  | | 13 (11)   15 (15)|
+ *
+ * 2 |  4 (2)   6 (6)  | | 12 (10)   14 (14)|
+ *    -----------------   ------------------
+ * 1 |  1 (1)   3 (5)  | |  9  (9)   11 (13)|
+ *
+ * 0 |  0 (0)   2 (4)  | |  8  (8)   10 (12)|
+ *    -----------------   ------------------
+ *       0       1            2        3
+ */
+static inline int nps_cluster_logic_to_phys(int cluster)
+{
+	 __asm__ __volatile__(
+	"       mov r3,%0\n"
+	"       .short %1\n"
+	"       .word %2\n"
+	"       mov %0,r3\n"
+	: "+r"(cluster)
+	: "i"(CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST),
+	  "i"(CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM)
+	: "r3");
+
+	return cluster;
+}
+
+#define NPS_CPU_TO_CLUSTER_NUM(cpu) \
+	({ struct global_id gid; gid.value = cpu; \
+		nps_cluster_logic_to_phys(gid.cluster); })
+
+struct nps_host_reg_address {
+	union {
+		struct {
+			u32 base:8, cl_x:4, cl_y:4,
+			blkid:6, reg:8, __reserved:2;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_address_non_cl {
+	union {
+		struct {
+			u32 base:7, blkid:11, reg:12, __reserved:2;
+		};
+		u32 value;
+	};
+};
+
+static inline void *nps_host_reg_non_cl(u32 blkid, u32 reg)
+{
+	struct nps_host_reg_address_non_cl reg_address;
+
+	reg_address.value = NPS_HOST_REG_BASE;
+	reg_address.blkid = blkid;
+	reg_address.reg = reg;
+
+	return (void *)reg_address.value;
+}
+
+static inline void *nps_host_reg(u32 cpu, u32 blkid, u32 reg)
+{
+	struct nps_host_reg_address reg_address;
+	u32 cl = NPS_CPU_TO_CLUSTER_NUM(cpu);
+
+	reg_address.value = NPS_HOST_REG_BASE;
+	reg_address.cl_x  = (cl >> 2) & 0x3;
+	reg_address.cl_y  = cl & 0x3;
+	reg_address.blkid = blkid;
+	reg_address.reg   = reg;
+
+	return (void *)reg_address.value;
+}
+#endif /* __ASSEMBLY__ */
+
+#endif /* SOC_NPS_COMMON_H */
-- 
1.7.1


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

* [PATCH v5 02/20] soc: Support for EZchip SoC
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

This header file is for NPS400 SoC.
It includes macros for accessing memory mapped registers.
These are functional registers that core can use to configure SoC.

Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 include/soc/nps/common.h |  123 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 123 insertions(+), 0 deletions(-)
 create mode 100644 include/soc/nps/common.h

diff --git a/include/soc/nps/common.h b/include/soc/nps/common.h
new file mode 100644
index 0000000..3bc30a8
--- /dev/null
+++ b/include/soc/nps/common.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef SOC_NPS_COMMON_H
+#define SOC_NPS_COMMON_H
+
+#define NPS_HOST_REG_BASE			0xF6000000
+#define CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST	0x5B60
+#define CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM	0x00010422
+
+#ifndef __ASSEMBLY__
+/* CPU global ID */
+struct global_id {
+	union {
+		struct {
+#ifdef CONFIG_EZNPS_MTM_EXT
+			u32 __reserved:20, cluster:4, core:4, thread:4;
+#else
+			u32 __reserved:24, cluster:4, core:4;
+#endif
+		};
+		u32 value;
+	};
+};
+
+/*
+ * Convert logical to physical CPU IDs
+ *
+ * The conversion swap bits 1 and 2 of cluster id (out of 4 bits)
+ * Now quad of logical clusters id's are adjacent physically,
+ * and not like the id's physically came with each cluster.
+ * Below table is 4x4 mesh of core clusters as it layout on chip.
+ * Cluster ids are in format: logical (physical)
+ *
+ *    -----------------   ------------------
+ * 3 |  5 (3)   7 (7)  | | 13 (11)   15 (15)|
+ *
+ * 2 |  4 (2)   6 (6)  | | 12 (10)   14 (14)|
+ *    -----------------   ------------------
+ * 1 |  1 (1)   3 (5)  | |  9  (9)   11 (13)|
+ *
+ * 0 |  0 (0)   2 (4)  | |  8  (8)   10 (12)|
+ *    -----------------   ------------------
+ *       0       1            2        3
+ */
+static inline int nps_cluster_logic_to_phys(int cluster)
+{
+	 __asm__ __volatile__(
+	"       mov r3,%0\n"
+	"       .short %1\n"
+	"       .word %2\n"
+	"       mov %0,r3\n"
+	: "+r"(cluster)
+	: "i"(CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST),
+	  "i"(CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM)
+	: "r3");
+
+	return cluster;
+}
+
+#define NPS_CPU_TO_CLUSTER_NUM(cpu) \
+	({ struct global_id gid; gid.value = cpu; \
+		nps_cluster_logic_to_phys(gid.cluster); })
+
+struct nps_host_reg_address {
+	union {
+		struct {
+			u32 base:8, cl_x:4, cl_y:4,
+			blkid:6, reg:8, __reserved:2;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_address_non_cl {
+	union {
+		struct {
+			u32 base:7, blkid:11, reg:12, __reserved:2;
+		};
+		u32 value;
+	};
+};
+
+static inline void *nps_host_reg_non_cl(u32 blkid, u32 reg)
+{
+	struct nps_host_reg_address_non_cl reg_address;
+
+	reg_address.value = NPS_HOST_REG_BASE;
+	reg_address.blkid = blkid;
+	reg_address.reg = reg;
+
+	return (void *)reg_address.value;
+}
+
+static inline void *nps_host_reg(u32 cpu, u32 blkid, u32 reg)
+{
+	struct nps_host_reg_address reg_address;
+	u32 cl = NPS_CPU_TO_CLUSTER_NUM(cpu);
+
+	reg_address.value = NPS_HOST_REG_BASE;
+	reg_address.cl_x  = (cl >> 2) & 0x3;
+	reg_address.cl_y  = cl & 0x3;
+	reg_address.blkid = blkid;
+	reg_address.reg   = reg;
+
+	return (void *)reg_address.value;
+}
+#endif /* __ASSEMBLY__ */
+
+#endif /* SOC_NPS_COMMON_H */
-- 
1.7.1

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

* [PATCH v5 03/20] ARC: [plat-eznps] define IPI_IRQ
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

We add IPI irq definition to be used later by any
irqchip such NPS400 IC.

Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 arch/arc/include/asm/irq.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index 4fd7d62..c5f8f0f 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -16,7 +16,11 @@
 #ifdef CONFIG_ISA_ARCOMPACT
 #define TIMER0_IRQ      3
 #define TIMER1_IRQ      4
+#if defined(CONFIG_SMP) && defined(CONFIG_ARC_PLAT_EZNPS)
+#define IPI_IRQ         5
+#else
 #define IPI_IRQ		(NR_CPU_IRQS-1) /* dummy to enable SMP build for up hardware */
+#endif
 #else
 #define TIMER0_IRQ      16
 #define TIMER1_IRQ      17
-- 
1.7.1


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

* [PATCH v5 03/20] ARC: [plat-eznps] define IPI_IRQ
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

We add IPI irq definition to be used later by any
irqchip such NPS400 IC.

Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 arch/arc/include/asm/irq.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index 4fd7d62..c5f8f0f 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -16,7 +16,11 @@
 #ifdef CONFIG_ISA_ARCOMPACT
 #define TIMER0_IRQ      3
 #define TIMER1_IRQ      4
+#if defined(CONFIG_SMP) && defined(CONFIG_ARC_PLAT_EZNPS)
+#define IPI_IRQ         5
+#else
 #define IPI_IRQ		(NR_CPU_IRQS-1) /* dummy to enable SMP build for up hardware */
+#endif
 #else
 #define TIMER0_IRQ      16
 #define TIMER1_IRQ      17
-- 
1.7.1

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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus,
	Rob Herring, Thomas Gleixner, John Stultz

From: Noam Camus <noamc@ezchip.com>

Add internal tick generator which is shared by all cores.
Each cluster of cores view it through dedicated address.
This is used for SMP system where all CPUs synced by same
clock source.

Signed-off-by: Noam Camus <noamc@ezchip.com>
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>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
---
 .../bindings/timer/ezchip,nps400-timer.txt         |   17 ++
 drivers/clocksource/Kconfig                        |    7 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/timer-nps.c                    |  199 ++++++++++++++++++++
 4 files changed, 224 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 drivers/clocksource/timer-nps.c

diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
new file mode 100644
index 0000000..eeb26d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
@@ -0,0 +1,17 @@
+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
+- interrupts : The interrupt of the first timer
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer";
+	clocks = <&sysclk>;
+	interrupts = <3>;
+};
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 2eb5f0e..859e83d 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -132,6 +132,13 @@ config CLKSRC_TI_32K
 	  This option enables support for Texas Instruments 32.768 Hz clocksource
 	  available on many OMAP-like platforms.
 
+config CLKSRC_NPS
+	bool "NPS400 clocksource driver" if COMPILE_TEST
+	select CLKSRC_OF if OF
+	help
+	  NPS400 clocksource support.
+	  Got 64 bit counter with update rate up to 1000MHz.
+
 config CLKSRC_STM32
 	bool "Clocksource for STM32 SoCs" if !ARCH_STM32
 	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 56bd16e..056cffd 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
 obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
 obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
+obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
new file mode 100644
index 0000000..b3fc9ba
--- /dev/null
+++ b/drivers/clocksource/timer-nps.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/cpu.h>
+#include <soc/nps/common.h>
+
+#define NPS_MSU_TICK_LOW	0xC8
+#define NPS_CLUSTER_OFFSET	8
+#define NPS_CLUSTER_NUM		16
+
+/* 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 TIMER_CTRL_IE           (1 << 0) /* Interupt when Count reachs limit */
+#define TIMER_CTRL_NH           (1 << 1) /* Count only when CPU NOT halted */
+
+/* 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 int nps_timer_irq;
+
+static cycle_t nps_clksrc_read(struct clocksource *clksrc)
+{
+	int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET;
+
+	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
+}
+
+static struct clocksource nps_counter = {
+	.name	= "EZnps-tick",
+	.rating = 301,
+	.read   = nps_clksrc_read,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void nps_timer_event_setup(unsigned int cycles)
+{
+	write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
+	write_aux_reg(ARC_REG_TIMER0_CNT, 0);   /* start from 0 */
+
+	write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
+}
+
+static int nps_clkevent_set_next_event(unsigned long delta,
+				       struct clock_event_device *dev)
+{
+	nps_timer_event_setup(delta);
+	return 0;
+}
+
+static int nps_clkevent_set_periodic(struct clock_event_device *dev)
+{
+	/*
+	 * At X Hz, 1 sec = 1000ms -> X cycles;
+	 *                    10ms -> X / 100 cycles
+	 */
+	nps_timer_event_setup(nps_timer_rate / HZ);
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
+	.name			= "nps_sys_timer",
+	.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,
+};
+
+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->irq = nps_timer_irq;
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	/*
+	 * Grab cpu pointer in each case to avoid spurious
+	 * preemptible warnings
+	 */
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		enable_percpu_irq(nps_timer_irq, 0);
+		clockevents_config_and_register(evt, nps_timer_rate,
+						0, ULONG_MAX);
+		break;
+	case CPU_DYING:
+		disable_percpu_irq(nps_timer_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block nps_timer_cpu_nb = {
+	.notifier_call = nps_timer_cpu_notify,
+};
+
+static irqreturn_t nps_timer_irq_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+	int irq_reenable = clockevent_state_periodic(evt);
+
+	/*
+	 * Any write to CTRL reg ACks the interrupt, we rewrite the
+	 * Count when [N]ot [H]alted bit.
+	 * And re-arm it if perioid by [I]nterrupt [E]nable bit
+	 */
+	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static void __init nps_setup_clocksource(struct device_node *node,
+					 struct clk *clk, int irq)
+{
+	struct clocksource *clksrc = &nps_counter;
+	int ret, cluster;
+
+	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
+		nps_msu_reg_low_addr[cluster] =
+			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
+				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		pr_err("Couldn't enable parent clock\n");
+
+	nps_timer_rate = clk_get_rate(clk);
+
+	ret = clocksource_register_hz(clksrc, nps_timer_rate);
+	if (ret)
+		pr_err("Couldn't register clock source.\n");
+}
+
+static void __init nps_setup_clockevents(struct device_node *node,
+					 struct clk *clk, int irq)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+	int ret;
+
+	register_cpu_notifier(&nps_timer_cpu_nb);
+
+	evt->irq = irq;
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(evt, nps_timer_rate, 0, ULONG_MAX);
+
+	enable_percpu_irq(irq, 0);
+
+	ret = request_percpu_irq(irq, nps_timer_irq_handler,
+				 "timer", evt);
+	if (ret)
+		pr_err("Unable to register interrupt\n");
+}
+
+static void __init nps_timer_init(struct device_node *node)
+{
+	struct clk *clk;
+
+	nps_timer_irq = irq_of_parse_and_map(node, 0);
+	if (nps_timer_irq <= 0)
+		panic("Can't parse IRQ");
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk))
+		panic("Can't get timer clock");
+
+	nps_setup_clocksource(node, clk, nps_timer_irq);
+	nps_setup_clockevents(node, clk, nps_timer_irq);
+}
+
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
+		       nps_timer_init);
-- 
1.7.1


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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

Add internal tick generator which is shared by all cores.
Each cluster of cores view it through dedicated address.
This is used for SMP system where all CPUs synced by same
clock source.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: John Stultz <john.stultz at linaro.org>
Acked-by: Vineet Gupta <vgupta at synopsys.com>
---
 .../bindings/timer/ezchip,nps400-timer.txt         |   17 ++
 drivers/clocksource/Kconfig                        |    7 +
 drivers/clocksource/Makefile                       |    1 +
 drivers/clocksource/timer-nps.c                    |  199 ++++++++++++++++++++
 4 files changed, 224 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
 create mode 100644 drivers/clocksource/timer-nps.c

diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
new file mode 100644
index 0000000..eeb26d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
@@ -0,0 +1,17 @@
+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
+- interrupts : The interrupt of the first timer
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer";
+	clocks = <&sysclk>;
+	interrupts = <3>;
+};
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 2eb5f0e..859e83d 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -132,6 +132,13 @@ config CLKSRC_TI_32K
 	  This option enables support for Texas Instruments 32.768 Hz clocksource
 	  available on many OMAP-like platforms.
 
+config CLKSRC_NPS
+	bool "NPS400 clocksource driver" if COMPILE_TEST
+	select CLKSRC_OF if OF
+	help
+	  NPS400 clocksource support.
+	  Got 64 bit counter with update rate up to 1000MHz.
+
 config CLKSRC_STM32
 	bool "Clocksource for STM32 SoCs" if !ARCH_STM32
 	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 56bd16e..056cffd 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
 obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
 obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
+obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
new file mode 100644
index 0000000..b3fc9ba
--- /dev/null
+++ b/drivers/clocksource/timer-nps.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/cpu.h>
+#include <soc/nps/common.h>
+
+#define NPS_MSU_TICK_LOW	0xC8
+#define NPS_CLUSTER_OFFSET	8
+#define NPS_CLUSTER_NUM		16
+
+/* 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 TIMER_CTRL_IE           (1 << 0) /* Interupt when Count reachs limit */
+#define TIMER_CTRL_NH           (1 << 1) /* Count only when CPU NOT halted */
+
+/* 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 int nps_timer_irq;
+
+static cycle_t nps_clksrc_read(struct clocksource *clksrc)
+{
+	int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET;
+
+	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
+}
+
+static struct clocksource nps_counter = {
+	.name	= "EZnps-tick",
+	.rating = 301,
+	.read   = nps_clksrc_read,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void nps_timer_event_setup(unsigned int cycles)
+{
+	write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
+	write_aux_reg(ARC_REG_TIMER0_CNT, 0);   /* start from 0 */
+
+	write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
+}
+
+static int nps_clkevent_set_next_event(unsigned long delta,
+				       struct clock_event_device *dev)
+{
+	nps_timer_event_setup(delta);
+	return 0;
+}
+
+static int nps_clkevent_set_periodic(struct clock_event_device *dev)
+{
+	/*
+	 * At X Hz, 1 sec = 1000ms -> X cycles;
+	 *                    10ms -> X / 100 cycles
+	 */
+	nps_timer_event_setup(nps_timer_rate / HZ);
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
+	.name			= "nps_sys_timer",
+	.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,
+};
+
+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->irq = nps_timer_irq;
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	/*
+	 * Grab cpu pointer in each case to avoid spurious
+	 * preemptible warnings
+	 */
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		enable_percpu_irq(nps_timer_irq, 0);
+		clockevents_config_and_register(evt, nps_timer_rate,
+						0, ULONG_MAX);
+		break;
+	case CPU_DYING:
+		disable_percpu_irq(nps_timer_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block nps_timer_cpu_nb = {
+	.notifier_call = nps_timer_cpu_notify,
+};
+
+static irqreturn_t nps_timer_irq_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+	int irq_reenable = clockevent_state_periodic(evt);
+
+	/*
+	 * Any write to CTRL reg ACks the interrupt, we rewrite the
+	 * Count when [N]ot [H]alted bit.
+	 * And re-arm it if perioid by [I]nterrupt [E]nable bit
+	 */
+	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static void __init nps_setup_clocksource(struct device_node *node,
+					 struct clk *clk, int irq)
+{
+	struct clocksource *clksrc = &nps_counter;
+	int ret, cluster;
+
+	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
+		nps_msu_reg_low_addr[cluster] =
+			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
+				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		pr_err("Couldn't enable parent clock\n");
+
+	nps_timer_rate = clk_get_rate(clk);
+
+	ret = clocksource_register_hz(clksrc, nps_timer_rate);
+	if (ret)
+		pr_err("Couldn't register clock source.\n");
+}
+
+static void __init nps_setup_clockevents(struct device_node *node,
+					 struct clk *clk, int irq)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+	int ret;
+
+	register_cpu_notifier(&nps_timer_cpu_nb);
+
+	evt->irq = irq;
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(evt, nps_timer_rate, 0, ULONG_MAX);
+
+	enable_percpu_irq(irq, 0);
+
+	ret = request_percpu_irq(irq, nps_timer_irq_handler,
+				 "timer", evt);
+	if (ret)
+		pr_err("Unable to register interrupt\n");
+}
+
+static void __init nps_timer_init(struct device_node *node)
+{
+	struct clk *clk;
+
+	nps_timer_irq = irq_of_parse_and_map(node, 0);
+	if (nps_timer_irq <= 0)
+		panic("Can't parse IRQ");
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk))
+		panic("Can't get timer clock");
+
+	nps_setup_clocksource(node, clk, nps_timer_irq);
+	nps_setup_clockevents(node, clk, nps_timer_irq);
+}
+
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
+		       nps_timer_init);
-- 
1.7.1

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

* [PATCH v5 05/20] irqchip: add nps Internal and external irqchips
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus,
	Thomas Gleixner, Jason Cooper

From: Noam Camus <noamc@ezchip.com>

Adding EZchip NPS400 support.
NPS internal interrupts are internally handled at
Multi Thread Manager (MTM) that is signaled for deactivating
an interrupt.
External interrupts is handled also at Global Interrupt
Controller (GIC) e.g. serial and network devices.

Signed-off-by: Noam Camus <noamc@ezchip.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
 .../interrupt-controller/ezchip,nps400-ic.txt      |   17 +++
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-eznps.c                        |  139 ++++++++++++++++++++
 3 files changed, 157 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
 create mode 100644 drivers/irqchip/irq-eznps.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
new file mode 100644
index 0000000..888b2b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
@@ -0,0 +1,17 @@
+EZchip NPS Interrupt Controller
+
+Required properties:
+
+- compatible : should be "ezchip,nps400-ic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+
+
+Example:
+
+intc: interrupt-controller {
+	compatible = "ezchip,nps400-ic";
+	interrupt-controller;
+	#interrupt-cells = <1>;
+};
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f..b95b954 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
 obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
+obj-$(CONFIG_ARC_PLAT_EZNPS)		+= irq-eznps.o
diff --git a/drivers/irqchip/irq-eznps.c b/drivers/irqchip/irq-eznps.c
new file mode 100644
index 0000000..5a5d649
--- /dev/null
+++ b/drivers/irqchip/irq-eznps.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <asm/irq.h>
+
+/*
+ * NPS400 core includes an Interrupt Controller (IC) support.
+ * All cores can deactivate level irqs at first level control
+ * at cores mesh layer called MTM.
+ * For devices out side chip e.g. uart, network there is another
+ * level called Global Interrupt Manager (GIM).
+ * This second level can control level and edge interrupt.
+ *
+ * NOTE: AUX_IENABLE and CTOP_AUX_IACK are auxiliary registers
+ * with private HW copy per CPU.
+ */
+
+static void nps400_irq_mask(struct irq_data *irqd)
+{
+	unsigned int ienb;
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	ienb = read_aux_reg(AUX_IENABLE);
+	ienb &= ~(1 << irq);
+	write_aux_reg(AUX_IENABLE, ienb);
+}
+
+static void nps400_irq_unmask(struct irq_data *irqd)
+{
+	unsigned int ienb;
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	ienb = read_aux_reg(AUX_IENABLE);
+	ienb |= (1 << irq);
+	write_aux_reg(AUX_IENABLE, ienb);
+}
+
+static void nps400_irq_eoi_global(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+
+	/* Don't ack before all device access attempts are done */
+	mb();
+
+	__asm__ __volatile__ (
+	"       .word %0\n"
+	:
+	: "i"(CTOP_INST_RSPI_GIC_0_R12)
+	: "memory");
+}
+
+static void nps400_irq_eoi(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+}
+
+static struct irq_chip nps400_irq_chip_fasteoi = {
+	.name		= "NPS400 IC Global",
+	.irq_mask	= nps400_irq_mask,
+	.irq_unmask	= nps400_irq_unmask,
+	.irq_eoi	= nps400_irq_eoi_global,
+};
+
+static struct irq_chip nps400_irq_chip_percpu = {
+	.name		= "NPS400 IC",
+	.irq_mask	= nps400_irq_mask,
+	.irq_unmask	= nps400_irq_unmask,
+	.irq_eoi	= nps400_irq_eoi,
+};
+
+static int nps400_irq_map(struct irq_domain *d, unsigned int virq,
+			  irq_hw_number_t hw)
+{
+	switch (hw) {
+	case TIMER0_IRQ:
+		irq_set_percpu_devid(virq);
+		irq_set_chip_and_handler(virq, &nps400_irq_chip_percpu,
+					 handle_percpu_devid_irq);
+	break;
+	default:
+		irq_set_chip_and_handler(virq, &nps400_irq_chip_fasteoi,
+					 handle_fasteoi_irq);
+	break;
+	}
+
+	return 0;
+}
+
+static const struct irq_domain_ops nps400_irq_ops = {
+	.xlate = irq_domain_xlate_onecell,
+	.map = nps400_irq_map,
+};
+
+static struct irq_domain *nps400_root_domain;
+
+static void nps400_handle_irq(unsigned int hwirq, struct pt_regs *regs)
+{
+	handle_domain_irq(nps400_root_domain, hwirq, regs);
+}
+
+static int __init nps400_of_init(struct device_node *node,
+				 struct device_node *parent)
+{
+	if (parent)
+		panic("DeviceTree incore ic not a root irq controller\n");
+
+	nps400_root_domain = irq_domain_add_linear(node, NR_CPU_IRQS,
+						   &nps400_irq_ops, NULL);
+
+	if (!nps400_root_domain)
+		panic("nps400 root irq domain not avail\n");
+
+	set_handle_irq(nps400_handle_irq);
+
+	return 0;
+}
+IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
-- 
1.7.1


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

* [PATCH v5 05/20] irqchip: add nps Internal and external irqchips
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

Adding EZchip NPS400 support.
NPS internal interrupts are internally handled at
Multi Thread Manager (MTM) that is signaled for deactivating
an interrupt.
External interrupts is handled also at Global Interrupt
Controller (GIC) e.g. serial and network devices.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Jason Cooper <jason at lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier at arm.com>
---
 .../interrupt-controller/ezchip,nps400-ic.txt      |   17 +++
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-eznps.c                        |  139 ++++++++++++++++++++
 3 files changed, 157 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
 create mode 100644 drivers/irqchip/irq-eznps.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
new file mode 100644
index 0000000..888b2b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
@@ -0,0 +1,17 @@
+EZchip NPS Interrupt Controller
+
+Required properties:
+
+- compatible : should be "ezchip,nps400-ic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+
+
+Example:
+
+intc: interrupt-controller {
+	compatible = "ezchip,nps400-ic";
+	interrupt-controller;
+	#interrupt-cells = <1>;
+};
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f..b95b954 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC)		+= irq-renesas-h8s.o
 obj-$(CONFIG_ARCH_SA1100)		+= irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)			+= irq-imx-gpcv2.o
+obj-$(CONFIG_ARC_PLAT_EZNPS)		+= irq-eznps.o
diff --git a/drivers/irqchip/irq-eznps.c b/drivers/irqchip/irq-eznps.c
new file mode 100644
index 0000000..5a5d649
--- /dev/null
+++ b/drivers/irqchip/irq-eznps.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <asm/irq.h>
+
+/*
+ * NPS400 core includes an Interrupt Controller (IC) support.
+ * All cores can deactivate level irqs at first level control
+ * at cores mesh layer called MTM.
+ * For devices out side chip e.g. uart, network there is another
+ * level called Global Interrupt Manager (GIM).
+ * This second level can control level and edge interrupt.
+ *
+ * NOTE: AUX_IENABLE and CTOP_AUX_IACK are auxiliary registers
+ * with private HW copy per CPU.
+ */
+
+static void nps400_irq_mask(struct irq_data *irqd)
+{
+	unsigned int ienb;
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	ienb = read_aux_reg(AUX_IENABLE);
+	ienb &= ~(1 << irq);
+	write_aux_reg(AUX_IENABLE, ienb);
+}
+
+static void nps400_irq_unmask(struct irq_data *irqd)
+{
+	unsigned int ienb;
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	ienb = read_aux_reg(AUX_IENABLE);
+	ienb |= (1 << irq);
+	write_aux_reg(AUX_IENABLE, ienb);
+}
+
+static void nps400_irq_eoi_global(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+
+	/* Don't ack before all device access attempts are done */
+	mb();
+
+	__asm__ __volatile__ (
+	"       .word %0\n"
+	:
+	: "i"(CTOP_INST_RSPI_GIC_0_R12)
+	: "memory");
+}
+
+static void nps400_irq_eoi(struct irq_data *irqd)
+{
+	unsigned int irq = irqd_to_hwirq(irqd);
+
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+}
+
+static struct irq_chip nps400_irq_chip_fasteoi = {
+	.name		= "NPS400 IC Global",
+	.irq_mask	= nps400_irq_mask,
+	.irq_unmask	= nps400_irq_unmask,
+	.irq_eoi	= nps400_irq_eoi_global,
+};
+
+static struct irq_chip nps400_irq_chip_percpu = {
+	.name		= "NPS400 IC",
+	.irq_mask	= nps400_irq_mask,
+	.irq_unmask	= nps400_irq_unmask,
+	.irq_eoi	= nps400_irq_eoi,
+};
+
+static int nps400_irq_map(struct irq_domain *d, unsigned int virq,
+			  irq_hw_number_t hw)
+{
+	switch (hw) {
+	case TIMER0_IRQ:
+		irq_set_percpu_devid(virq);
+		irq_set_chip_and_handler(virq, &nps400_irq_chip_percpu,
+					 handle_percpu_devid_irq);
+	break;
+	default:
+		irq_set_chip_and_handler(virq, &nps400_irq_chip_fasteoi,
+					 handle_fasteoi_irq);
+	break;
+	}
+
+	return 0;
+}
+
+static const struct irq_domain_ops nps400_irq_ops = {
+	.xlate = irq_domain_xlate_onecell,
+	.map = nps400_irq_map,
+};
+
+static struct irq_domain *nps400_root_domain;
+
+static void nps400_handle_irq(unsigned int hwirq, struct pt_regs *regs)
+{
+	handle_domain_irq(nps400_root_domain, hwirq, regs);
+}
+
+static int __init nps400_of_init(struct device_node *node,
+				 struct device_node *parent)
+{
+	if (parent)
+		panic("DeviceTree incore ic not a root irq controller\n");
+
+	nps400_root_domain = irq_domain_add_linear(node, NR_CPU_IRQS,
+						   &nps400_irq_ops, NULL);
+
+	if (!nps400_root_domain)
+		panic("nps400 root irq domain not avail\n");
+
+	set_handle_irq(nps400_handle_irq);
+
+	return 0;
+}
+IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
-- 
1.7.1

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

* [PATCH v5 06/20] ARC: Set vmalloc size from configuration
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

User space use lower 2G of the virtual address space.
However kernel steals upper 512M of this space.
This stolen space is used partially for vmalloc and the rest
serves as gutter between kernel and user space.
The vmalloc size is depend on NR_CPUS since "per cpu" mechanism
use vmalloc to allocate chunks for its use.

Historically vmalloc size was 256M however it is not enough in
case of many CPUs e.g. 4K CPUs. For such case an extra 192M is
allocated.
We are setting default vmalloc size to be 256M, any addtional
space will be taken from kernel/user gutter.

This introduce build error since PGDIR_SIZE() cannot use "1UL"
ibecause it is called from mm/tlbex.S by VMALLOC_START.
Using _BITUL() solves this build error.

Signed-off-by: Noam Camus <noamc@ezchip.com>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/Kconfig                 |    8 ++++++++
 arch/arc/include/asm/pgtable.h   |    2 +-
 arch/arc/include/asm/processor.h |   10 +++++-----
 arch/arc/mm/tlb.c                |    6 ++++++
 4 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 6312f60..7be1020 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -469,6 +469,14 @@ config ARCH_PHYS_ADDR_T_64BIT
 config ARCH_DMA_ADDR_T_64BIT
 	bool
 
+config ARC_VMALLOC_SIZE
+	hex "Vmalloc size (MB)"
+	range 0 512
+	default "256"
+	help
+	  By default equals to 256MB and the rest of 512MB is
+	  left for gutter between kernel and user space.
+
 config ARC_CURR_IN_REG
 	bool "Dedicate Register r25 for current_task pointer"
 	default y
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
index 57af2f0..372a282 100644
--- a/arch/arc/include/asm/pgtable.h
+++ b/arch/arc/include/asm/pgtable.h
@@ -210,7 +210,7 @@
 #define BITS_FOR_PGD	(32 - BITS_FOR_PTE - BITS_IN_PAGE)
 
 #define PGDIR_SHIFT	(32 - BITS_FOR_PGD)
-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)	/* vaddr span, not PDG sz */
+#define PGDIR_SIZE	_BITUL(PGDIR_SHIFT)	/* vaddr span, not PDG sz */
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
 #define	PTRS_PER_PTE	_BITUL(BITS_FOR_PTE)
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 1d694c1..8a77ccd 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -109,18 +109,18 @@ extern unsigned int get_wchan(struct task_struct *p);
  * 0xC000_0000		0xFFFF_FFFF	(peripheral uncached space)
  * -----------------------------------------------------------------------------
  */
-#define VMALLOC_START	0x70000000
 
 /*
  * 1 PGDIR_SIZE each for fixmap/pkmap, 2 PGDIR_SIZE gutter
  * See asm/highmem.h for details
  */
-#define VMALLOC_SIZE	(PAGE_OFFSET - VMALLOC_START - PGDIR_SIZE * 4)
-#define VMALLOC_END	(VMALLOC_START + VMALLOC_SIZE)
+#define VMALLOC_END	(PAGE_OFFSET - PGDIR_SIZE * 4)
+#define VMALLOC_SIZE	(CONFIG_ARC_VMALLOC_SIZE << 20)
+#define VMALLOC_START	(VMALLOC_END - VMALLOC_SIZE)
 
-#define USER_KERNEL_GUTTER    0x10000000
+#define TASK_SIZE	0x60000000
 
-#define TASK_SIZE	(VMALLOC_START - USER_KERNEL_GUTTER)
+#define USER_KERNEL_GUTTER    (VMALLOC_START - TASK_SIZE)
 
 #define STACK_TOP       TASK_SIZE
 #define STACK_TOP_MAX   STACK_TOP
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index daf2bf5..843e1a5 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -814,6 +814,12 @@ void arc_mmu_init(void)
 
 	printk(arc_mmu_mumbojumbo(0, str, sizeof(str)));
 
+	/*
+	 * vmalloc size (in MB) sanity check,
+	 * Can't be done in processor.h due to header include depenedencies
+	 */
+	BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_VMALLOC_SIZE << 20), PMD_SIZE));
+
 	/* For efficiency sake, kernel is compile time built for a MMU ver
 	 * This must match the hardware it is running on.
 	 * Linux built for MMU V2, if run on MMU V1 will break down because V1
-- 
1.7.1


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

* [PATCH v5 06/20] ARC: Set vmalloc size from configuration
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

User space use lower 2G of the virtual address space.
However kernel steals upper 512M of this space.
This stolen space is used partially for vmalloc and the rest
serves as gutter between kernel and user space.
The vmalloc size is depend on NR_CPUS since "per cpu" mechanism
use vmalloc to allocate chunks for its use.

Historically vmalloc size was 256M however it is not enough in
case of many CPUs e.g. 4K CPUs. For such case an extra 192M is
allocated.
We are setting default vmalloc size to be 256M, any addtional
space will be taken from kernel/user gutter.

This introduce build error since PGDIR_SIZE() cannot use "1UL"
ibecause it is called from mm/tlbex.S by VMALLOC_START.
Using _BITUL() solves this build error.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Acked-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/Kconfig                 |    8 ++++++++
 arch/arc/include/asm/pgtable.h   |    2 +-
 arch/arc/include/asm/processor.h |   10 +++++-----
 arch/arc/mm/tlb.c                |    6 ++++++
 4 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 6312f60..7be1020 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -469,6 +469,14 @@ config ARCH_PHYS_ADDR_T_64BIT
 config ARCH_DMA_ADDR_T_64BIT
 	bool
 
+config ARC_VMALLOC_SIZE
+	hex "Vmalloc size (MB)"
+	range 0 512
+	default "256"
+	help
+	  By default equals to 256MB and the rest of 512MB is
+	  left for gutter between kernel and user space.
+
 config ARC_CURR_IN_REG
 	bool "Dedicate Register r25 for current_task pointer"
 	default y
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
index 57af2f0..372a282 100644
--- a/arch/arc/include/asm/pgtable.h
+++ b/arch/arc/include/asm/pgtable.h
@@ -210,7 +210,7 @@
 #define BITS_FOR_PGD	(32 - BITS_FOR_PTE - BITS_IN_PAGE)
 
 #define PGDIR_SHIFT	(32 - BITS_FOR_PGD)
-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)	/* vaddr span, not PDG sz */
+#define PGDIR_SIZE	_BITUL(PGDIR_SHIFT)	/* vaddr span, not PDG sz */
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
 #define	PTRS_PER_PTE	_BITUL(BITS_FOR_PTE)
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 1d694c1..8a77ccd 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -109,18 +109,18 @@ extern unsigned int get_wchan(struct task_struct *p);
  * 0xC000_0000		0xFFFF_FFFF	(peripheral uncached space)
  * -----------------------------------------------------------------------------
  */
-#define VMALLOC_START	0x70000000
 
 /*
  * 1 PGDIR_SIZE each for fixmap/pkmap, 2 PGDIR_SIZE gutter
  * See asm/highmem.h for details
  */
-#define VMALLOC_SIZE	(PAGE_OFFSET - VMALLOC_START - PGDIR_SIZE * 4)
-#define VMALLOC_END	(VMALLOC_START + VMALLOC_SIZE)
+#define VMALLOC_END	(PAGE_OFFSET - PGDIR_SIZE * 4)
+#define VMALLOC_SIZE	(CONFIG_ARC_VMALLOC_SIZE << 20)
+#define VMALLOC_START	(VMALLOC_END - VMALLOC_SIZE)
 
-#define USER_KERNEL_GUTTER    0x10000000
+#define TASK_SIZE	0x60000000
 
-#define TASK_SIZE	(VMALLOC_START - USER_KERNEL_GUTTER)
+#define USER_KERNEL_GUTTER    (VMALLOC_START - TASK_SIZE)
 
 #define STACK_TOP       TASK_SIZE
 #define STACK_TOP_MAX   STACK_TOP
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index daf2bf5..843e1a5 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -814,6 +814,12 @@ void arc_mmu_init(void)
 
 	printk(arc_mmu_mumbojumbo(0, str, sizeof(str)));
 
+	/*
+	 * vmalloc size (in MB) sanity check,
+	 * Can't be done in processor.h due to header include depenedencies
+	 */
+	BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_VMALLOC_SIZE << 20), PMD_SIZE));
+
 	/* For efficiency sake, kernel is compile time built for a MMU ver
 	 * This must match the hardware it is running on.
 	 * Linux built for MMU V2, if run on MMU V1 will break down because V1
-- 
1.7.1

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

* [PATCH v5 07/20] ARC: rwlock: disable interrupts in !LLSC variant
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

If we hold rwlock and interrupt occures we may
end up spinning on it for ever during softirq.
Note that this lock is an internal lock
and since the lock is free to be used from any context,
the lock needs to be IRQ-safe.

Below you may see an example for interrupt we get while
nl_table_lock is holding its rw->lock_mutex and we spinned
on it for ever.

The concept for the fix was taken from SPARC.

[2015-05-12 19:16:12] Stack Trace:
[2015-05-12 19:16:12]   arc_unwind_core+0xb8/0x11c
[2015-05-12 19:16:12]   dump_stack+0x68/0xac
[2015-05-12 19:16:12]   _raw_read_lock+0xa8/0xac
[2015-05-12 19:16:12]   netlink_broadcast_filtered+0x56/0x35c
[2015-05-12 19:16:12]   nlmsg_notify+0x42/0xa4
[2015-05-12 19:16:13]   neigh_update+0x1fe/0x44c
[2015-05-12 19:16:13]   neigh_event_ns+0x40/0xa4
[2015-05-12 19:16:13]   arp_process+0x46e/0x5a8
[2015-05-12 19:16:13]   __netif_receive_skb_core+0x358/0x500
[2015-05-12 19:16:13]   process_backlog+0x92/0x154
[2015-05-12 19:16:13]   net_rx_action+0xb8/0x188
[2015-05-12 19:16:13]   __do_softirq+0xda/0x1d8
[2015-05-12 19:16:14]   irq_exit+0x8a/0x8c
[2015-05-12 19:16:14]   arch_do_IRQ+0x6c/0xa8
[2015-05-12 19:16:14]   handle_interrupt_level1+0xe4/0xf0

Signed-off-by: Noam Camus <noamc@ezchip.com>
Acked-by: Peter Zijlstra <peterz@infradead.org>
---
 arch/arc/include/asm/spinlock.h |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/spinlock.h b/arch/arc/include/asm/spinlock.h
index db8c59d..800e7c4 100644
--- a/arch/arc/include/asm/spinlock.h
+++ b/arch/arc/include/asm/spinlock.h
@@ -610,7 +610,9 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
 static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
 	int ret = 0;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 
 	/*
@@ -623,6 +625,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 	}
 
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 
 	smp_mb();
 	return ret;
@@ -632,7 +635,9 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
 	int ret = 0;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 
 	/*
@@ -646,6 +651,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 		ret = 1;
 	}
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 
 	return ret;
 }
@@ -664,16 +670,24 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 
 static inline void arch_read_unlock(arch_rwlock_t *rw)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 	rw->counter++;
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 }
 
 static inline void arch_write_unlock(arch_rwlock_t *rw)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 	rw->counter = __ARCH_RW_LOCK_UNLOCKED__;
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 }
 
 #endif
-- 
1.7.1


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

* [PATCH v5 07/20] ARC: rwlock: disable interrupts in !LLSC variant
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

If we hold rwlock and interrupt occures we may
end up spinning on it for ever during softirq.
Note that this lock is an internal lock
and since the lock is free to be used from any context,
the lock needs to be IRQ-safe.

Below you may see an example for interrupt we get while
nl_table_lock is holding its rw->lock_mutex and we spinned
on it for ever.

The concept for the fix was taken from SPARC.

[2015-05-12 19:16:12] Stack Trace:
[2015-05-12 19:16:12]   arc_unwind_core+0xb8/0x11c
[2015-05-12 19:16:12]   dump_stack+0x68/0xac
[2015-05-12 19:16:12]   _raw_read_lock+0xa8/0xac
[2015-05-12 19:16:12]   netlink_broadcast_filtered+0x56/0x35c
[2015-05-12 19:16:12]   nlmsg_notify+0x42/0xa4
[2015-05-12 19:16:13]   neigh_update+0x1fe/0x44c
[2015-05-12 19:16:13]   neigh_event_ns+0x40/0xa4
[2015-05-12 19:16:13]   arp_process+0x46e/0x5a8
[2015-05-12 19:16:13]   __netif_receive_skb_core+0x358/0x500
[2015-05-12 19:16:13]   process_backlog+0x92/0x154
[2015-05-12 19:16:13]   net_rx_action+0xb8/0x188
[2015-05-12 19:16:13]   __do_softirq+0xda/0x1d8
[2015-05-12 19:16:14]   irq_exit+0x8a/0x8c
[2015-05-12 19:16:14]   arch_do_IRQ+0x6c/0xa8
[2015-05-12 19:16:14]   handle_interrupt_level1+0xe4/0xf0

Signed-off-by: Noam Camus <noamc at ezchip.com>
Acked-by: Peter Zijlstra <peterz at infradead.org>
---
 arch/arc/include/asm/spinlock.h |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/spinlock.h b/arch/arc/include/asm/spinlock.h
index db8c59d..800e7c4 100644
--- a/arch/arc/include/asm/spinlock.h
+++ b/arch/arc/include/asm/spinlock.h
@@ -610,7 +610,9 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
 static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
 	int ret = 0;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 
 	/*
@@ -623,6 +625,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 	}
 
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 
 	smp_mb();
 	return ret;
@@ -632,7 +635,9 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
 	int ret = 0;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 
 	/*
@@ -646,6 +651,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 		ret = 1;
 	}
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 
 	return ret;
 }
@@ -664,16 +670,24 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 
 static inline void arch_read_unlock(arch_rwlock_t *rw)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 	rw->counter++;
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 }
 
 static inline void arch_write_unlock(arch_rwlock_t *rw)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 	rw->counter = __ARCH_RW_LOCK_UNLOCKED__;
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 }
 
 #endif
-- 
1.7.1

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

* [PATCH v5 08/20] ARC: Mark secondary cpu online only after all HW setup is done
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

In SMP setup, master loops for each_present_cpu calling cpu_up().
For ARC it returns as soon as new cpu's status becomes online,
However secondary may still do HW initializing,
machine or platform hook level.

So turn secondary online only after all HW setup is done.
Signed-off-by: Noam Camus <noamc@ezchip.com>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/kernel/smp.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index ef6e9e1..2cfe135 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -126,11 +126,6 @@ void start_kernel_secondary(void)
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
 
-	notify_cpu_starting(cpu);
-	set_cpu_online(cpu, true);
-
-	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
-
 	/* Some SMP H/w setup - for each cpu */
 	if (plat_smp_ops.init_per_cpu)
 		plat_smp_ops.init_per_cpu(cpu);
@@ -138,6 +133,11 @@ void start_kernel_secondary(void)
 	if (machine_desc->init_per_cpu)
 		machine_desc->init_per_cpu(cpu);
 
+	notify_cpu_starting(cpu);
+	set_cpu_online(cpu, true);
+
+	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
+
 	arc_local_timer_setup();
 
 	local_irq_enable();
-- 
1.7.1


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

* [PATCH v5 08/20] ARC: Mark secondary cpu online only after all HW setup is done
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

In SMP setup, master loops for each_present_cpu calling cpu_up().
For ARC it returns as soon as new cpu's status becomes online,
However secondary may still do HW initializing,
machine or platform hook level.

So turn secondary online only after all HW setup is done.
Signed-off-by: Noam Camus <noamc at ezchip.com>
Acked-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/kernel/smp.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index ef6e9e1..2cfe135 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -126,11 +126,6 @@ void start_kernel_secondary(void)
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
 
-	notify_cpu_starting(cpu);
-	set_cpu_online(cpu, true);
-
-	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
-
 	/* Some SMP H/w setup - for each cpu */
 	if (plat_smp_ops.init_per_cpu)
 		plat_smp_ops.init_per_cpu(cpu);
@@ -138,6 +133,11 @@ void start_kernel_secondary(void)
 	if (machine_desc->init_per_cpu)
 		machine_desc->init_per_cpu(cpu);
 
+	notify_cpu_starting(cpu);
+	set_cpu_online(cpu, true);
+
+	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
+
 	arc_local_timer_setup();
 
 	local_irq_enable();
-- 
1.7.1

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

* [PATCH v5 09/20] ARC: IRQ: use device tree to get timer device configuration
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

We've designated:
TIMER0 for events (clockevents)
TIMER1 for free running (clocksource)

Till now timer configuration was done on arch/arc/kernel/time.c
with constant values.

This commit add device tree support so we can do this work
at dedicated clocksource driver which parse the DT blob.

Such driver will get clocksource rate as well as interrupt line
from DT and use them for setting clocksourcse and clockevents.

Note that lately called of_clk_init() is moved before we call
clocksource_probe() since at that time device from DT
need a "provider" (clocks) which will be available only after
we call to of_clk_init().

Signed-off-by: Noam Camus <noamc@ezchip.com>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/kernel/setup.c |    1 -
 arch/arc/kernel/smp.c   |    2 ++
 arch/arc/kernel/time.c  |    8 ++++++++
 3 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index e1b8744..4681e9c 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -433,7 +433,6 @@ void __init setup_arch(char **cmdline_p)
 
 static int __init customize_machine(void)
 {
-	of_clk_init(NULL);
 	/*
 	 * Traverses flattened DeviceTree - registering platform devices
 	 * (if any) complete with their resources
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index 2cfe135..ec6a5c1 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -138,7 +138,9 @@ void start_kernel_secondary(void)
 
 	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
 
+#ifndef CONFIG_CLKSRC_OF
 	arc_local_timer_setup();
+#endif
 
 	local_irq_enable();
 	preempt_disable();
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index dfad287..be6dd9e 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/timex.h>
 #include <linux/profile.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <asm/irq.h>
@@ -283,6 +284,13 @@ void __init time_init(void)
 		 */
 		clocksource_register_hz(&arc_counter, arc_get_core_freq());
 
+#ifdef CONFIG_COMMON_CLK
+	of_clk_init(NULL);
+#endif
+#ifdef CONFIG_CLKSRC_OF
+	clocksource_probe();
+#else
 	/* sets up the periodic event timer */
 	arc_local_timer_setup();
+#endif
 }
-- 
1.7.1


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

* [PATCH v5 09/20] ARC: IRQ: use device tree to get timer device configuration
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

We've designated:
TIMER0 for events (clockevents)
TIMER1 for free running (clocksource)

Till now timer configuration was done on arch/arc/kernel/time.c
with constant values.

This commit add device tree support so we can do this work
at dedicated clocksource driver which parse the DT blob.

Such driver will get clocksource rate as well as interrupt line
from DT and use them for setting clocksourcse and clockevents.

Note that lately called of_clk_init() is moved before we call
clocksource_probe() since at that time device from DT
need a "provider" (clocks) which will be available only after
we call to of_clk_init().

Signed-off-by: Noam Camus <noamc at ezchip.com>
Acked-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/kernel/setup.c |    1 -
 arch/arc/kernel/smp.c   |    2 ++
 arch/arc/kernel/time.c  |    8 ++++++++
 3 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index e1b8744..4681e9c 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -433,7 +433,6 @@ void __init setup_arch(char **cmdline_p)
 
 static int __init customize_machine(void)
 {
-	of_clk_init(NULL);
 	/*
 	 * Traverses flattened DeviceTree - registering platform devices
 	 * (if any) complete with their resources
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index 2cfe135..ec6a5c1 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -138,7 +138,9 @@ void start_kernel_secondary(void)
 
 	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
 
+#ifndef CONFIG_CLKSRC_OF
 	arc_local_timer_setup();
+#endif
 
 	local_irq_enable();
 	preempt_disable();
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index dfad287..be6dd9e 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/timex.h>
 #include <linux/profile.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <asm/irq.h>
@@ -283,6 +284,13 @@ void __init time_init(void)
 		 */
 		clocksource_register_hz(&arc_counter, arc_get_core_freq());
 
+#ifdef CONFIG_COMMON_CLK
+	of_clk_init(NULL);
+#endif
+#ifdef CONFIG_CLKSRC_OF
+	clocksource_probe();
+#else
 	/* sets up the periodic event timer */
 	arc_local_timer_setup();
+#endif
 }
-- 
1.7.1

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

* [PATCH v5 10/20] ARC: IRQ: do not use hwirq directly at arch_do_IRQ()
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

ARC uses hwirq at arch_do_IRQ() to pass into generic_handle_irq().
This is wrong since we need first to reverse map it into virq.

Happily, if we use handle_domain_irq() we get all we need.

Just like ARM I created a pointer to handler that should be filled
by an interrupt controller driver from driver/irqchip/

Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 arch/arc/Kconfig           |    1 +
 arch/arc/include/asm/irq.h |    5 +++++
 arch/arc/kernel/irq.c      |   14 ++++++++++++++
 3 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 7be1020..079946e 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -32,6 +32,7 @@ config ARC
 	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
 	select IRQ_DOMAIN
+	select HANDLE_DOMAIN_IRQ if ARC_PLAT_EZNPS
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
 	select OF
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index c5f8f0f..64226c9 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -36,4 +36,9 @@ void arc_request_percpu_irq(int irq, int cpu,
                             irqreturn_t (*isr)(int irq, void *dev),
                             const char *irq_nm, void *percpu_dev);
 
+#ifdef CONFIG_HANDLE_DOMAIN_IRQ
+extern void set_handle_irq(void (*handle_irq)(unsigned int hwirq,
+					      struct pt_regs *));
+#endif
+
 #endif
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index ba17f85..7ae5411 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -41,6 +41,7 @@ void __init init_IRQ(void)
  * "C" Entry point for any ARC ISR, called from low level vector handler
  * @irq is the vector number read from ICAUSE reg of on-chip intc
  */
+#ifndef CONFIG_HANDLE_DOMAIN_IRQ
 void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
@@ -50,6 +51,19 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 	irq_exit();
 	set_irq_regs(old_regs);
 }
+#else
+void (*handle_arch_irq)(unsigned int hwirq, struct pt_regs *) = NULL;
+void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+	handle_arch_irq(irq, regs);
+}
+
+void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
+					      struct pt_regs *))
+{
+	handle_arch_irq = handle_irq;
+}
+#endif
 
 /*
  * API called for requesting percpu interrupts - called by each CPU
-- 
1.7.1


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

* [PATCH v5 10/20] ARC: IRQ: do not use hwirq directly at arch_do_IRQ()
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

ARC uses hwirq at arch_do_IRQ() to pass into generic_handle_irq().
This is wrong since we need first to reverse map it into virq.

Happily, if we use handle_domain_irq() we get all we need.

Just like ARM I created a pointer to handler that should be filled
by an interrupt controller driver from driver/irqchip/

Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 arch/arc/Kconfig           |    1 +
 arch/arc/include/asm/irq.h |    5 +++++
 arch/arc/kernel/irq.c      |   14 ++++++++++++++
 3 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 7be1020..079946e 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -32,6 +32,7 @@ config ARC
 	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
 	select IRQ_DOMAIN
+	select HANDLE_DOMAIN_IRQ if ARC_PLAT_EZNPS
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
 	select OF
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index c5f8f0f..64226c9 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -36,4 +36,9 @@ void arc_request_percpu_irq(int irq, int cpu,
                             irqreturn_t (*isr)(int irq, void *dev),
                             const char *irq_nm, void *percpu_dev);
 
+#ifdef CONFIG_HANDLE_DOMAIN_IRQ
+extern void set_handle_irq(void (*handle_irq)(unsigned int hwirq,
+					      struct pt_regs *));
+#endif
+
 #endif
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index ba17f85..7ae5411 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -41,6 +41,7 @@ void __init init_IRQ(void)
  * "C" Entry point for any ARC ISR, called from low level vector handler
  * @irq is the vector number read from ICAUSE reg of on-chip intc
  */
+#ifndef CONFIG_HANDLE_DOMAIN_IRQ
 void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
@@ -50,6 +51,19 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 	irq_exit();
 	set_irq_regs(old_regs);
 }
+#else
+void (*handle_arch_irq)(unsigned int hwirq, struct pt_regs *) = NULL;
+void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+	handle_arch_irq(irq, regs);
+}
+
+void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
+					      struct pt_regs *))
+{
+	handle_arch_irq = handle_irq;
+}
+#endif
 
 /*
  * API called for requesting percpu interrupts - called by each CPU
-- 
1.7.1

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

* [PATCH v5 11/20] ARC: IPI: do not use generic IRQ domain
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

This behaviour is the desired one as been seen on other arch's.

We do not use generic irq domain and hence hwirq number is used
directly by our code without any mapping to virq.
In order to add IPI status to /proc/interrupts we use
hardirq macros also we define arch_show_interrupts().

Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 arch/arc/include/asm/Kbuild    |    1 -
 arch/arc/include/asm/hardirq.h |   22 ++++++++++++++++++++++
 arch/arc/include/asm/smp.h     |    6 ++++++
 arch/arc/kernel/irq.c          |   13 ++++++++++++-
 arch/arc/kernel/smp.c          |   27 +++++++++++++++++++++++++++
 5 files changed, 67 insertions(+), 2 deletions(-)
 create mode 100644 arch/arc/include/asm/hardirq.h

diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0b10ef2..bbc3e4a 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -10,7 +10,6 @@ generic-y += errno.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += ftrace.h
-generic-y += hardirq.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
diff --git a/arch/arc/include/asm/hardirq.h b/arch/arc/include/asm/hardirq.h
new file mode 100644
index 0000000..e83aa88
--- /dev/null
+++ b/arch/arc/include/asm/hardirq.h
@@ -0,0 +1,22 @@
+#ifndef __ASM_ARC_HARDIRQ_H
+#define __ASM_ARC_HARDIRQ_H
+
+#include <linux/cache.h>
+#include <linux/threads.h>
+
+typedef struct {
+	unsigned int __softirq_pending;
+#ifdef CONFIG_SMP
+	unsigned int ipi_irqs;
+#endif
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+#include <linux/irq.h>
+
+static inline void ack_bad_irq(unsigned int irq)
+{
+	printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
+}
+
+#endif /* __ASM_ARC_HARDIRQ_H */
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index 9913804..9e4ec48 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -14,12 +14,16 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/threads.h>
+#include <asm/ptrace.h>
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
 /* including cpumask.h leads to cyclic deps hence this Forward declaration */
 struct cpumask;
 
+/* including seq_file.h leads to cyclic deps hence this Forward declaration */
+struct seq_file;
+
 /*
  * APIs provided by arch SMP code to generic code
  */
@@ -32,6 +36,8 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 extern void __init smp_init_cpus(void);
 extern void first_lines_of_secondary(void);
 extern const char *arc_platform_smp_cpuinfo(void);
+extern void arch_do_IPI(unsigned int irq, struct pt_regs *regs);
+extern void show_ipi_list(struct seq_file *, int);
 
 /*
  * API expected BY platform smp code (FROM arch smp code)
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 7ae5411..c8d3c3d 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -55,7 +55,10 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 void (*handle_arch_irq)(unsigned int hwirq, struct pt_regs *) = NULL;
 void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
-	handle_arch_irq(irq, regs);
+	if (irq == IPI_IRQ)
+		arch_do_IPI(irq, regs);
+	else
+		handle_arch_irq(irq, regs);
 }
 
 void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
@@ -65,6 +68,14 @@ void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
 }
 #endif
 
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+#ifdef CONFIG_SMP
+	show_ipi_list(p, prec);
+#endif
+	return 0;
+}
+
 /*
  * API called for requesting percpu interrupts - called by each CPU
  *  - For boot CPU, actually request the IRQ with genirq core + enables
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index ec6a5c1..8d37906 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -22,6 +22,7 @@
 #include <linux/atomic.h>
 #include <linux/cpumask.h>
 #include <linux/reboot.h>
+#include <linux/seq_file.h>
 #include <asm/processor.h>
 #include <asm/setup.h>
 #include <asm/mach_desc.h>
@@ -349,6 +350,32 @@ irqreturn_t do_IPI(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+void arch_do_IPI(unsigned int irq, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+	unsigned int cpu = smp_processor_id();
+
+	__IRQ_STAT(cpu, ipi_irqs)++;
+
+	irq_enter();
+	do_IPI(irq, NULL);
+	irq_exit();
+
+	set_irq_regs(old_regs);
+}
+
+void show_ipi_list(struct seq_file *p, int prec)
+{
+	unsigned int cpu;
+
+	seq_printf(p, "%*s: ", prec - 1, "IPI");
+
+	for_each_online_cpu(cpu)
+		seq_printf(p, "%10u ", __IRQ_STAT(cpu, ipi_irqs));
+
+	seq_printf(p, " %s\n", "IPI");
+}
+
 /*
  * API called by platform code to hookup arch-common ISR to their IPI IRQ
  */
-- 
1.7.1


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

* [PATCH v5 11/20] ARC: IPI: do not use generic IRQ domain
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

This behaviour is the desired one as been seen on other arch's.

We do not use generic irq domain and hence hwirq number is used
directly by our code without any mapping to virq.
In order to add IPI status to /proc/interrupts we use
hardirq macros also we define arch_show_interrupts().

Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 arch/arc/include/asm/Kbuild    |    1 -
 arch/arc/include/asm/hardirq.h |   22 ++++++++++++++++++++++
 arch/arc/include/asm/smp.h     |    6 ++++++
 arch/arc/kernel/irq.c          |   13 ++++++++++++-
 arch/arc/kernel/smp.c          |   27 +++++++++++++++++++++++++++
 5 files changed, 67 insertions(+), 2 deletions(-)
 create mode 100644 arch/arc/include/asm/hardirq.h

diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0b10ef2..bbc3e4a 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -10,7 +10,6 @@ generic-y += errno.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += ftrace.h
-generic-y += hardirq.h
 generic-y += hw_irq.h
 generic-y += ioctl.h
 generic-y += ioctls.h
diff --git a/arch/arc/include/asm/hardirq.h b/arch/arc/include/asm/hardirq.h
new file mode 100644
index 0000000..e83aa88
--- /dev/null
+++ b/arch/arc/include/asm/hardirq.h
@@ -0,0 +1,22 @@
+#ifndef __ASM_ARC_HARDIRQ_H
+#define __ASM_ARC_HARDIRQ_H
+
+#include <linux/cache.h>
+#include <linux/threads.h>
+
+typedef struct {
+	unsigned int __softirq_pending;
+#ifdef CONFIG_SMP
+	unsigned int ipi_irqs;
+#endif
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+#include <linux/irq.h>
+
+static inline void ack_bad_irq(unsigned int irq)
+{
+	printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
+}
+
+#endif /* __ASM_ARC_HARDIRQ_H */
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index 9913804..9e4ec48 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -14,12 +14,16 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/threads.h>
+#include <asm/ptrace.h>
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
 /* including cpumask.h leads to cyclic deps hence this Forward declaration */
 struct cpumask;
 
+/* including seq_file.h leads to cyclic deps hence this Forward declaration */
+struct seq_file;
+
 /*
  * APIs provided by arch SMP code to generic code
  */
@@ -32,6 +36,8 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 extern void __init smp_init_cpus(void);
 extern void first_lines_of_secondary(void);
 extern const char *arc_platform_smp_cpuinfo(void);
+extern void arch_do_IPI(unsigned int irq, struct pt_regs *regs);
+extern void show_ipi_list(struct seq_file *, int);
 
 /*
  * API expected BY platform smp code (FROM arch smp code)
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 7ae5411..c8d3c3d 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -55,7 +55,10 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 void (*handle_arch_irq)(unsigned int hwirq, struct pt_regs *) = NULL;
 void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
-	handle_arch_irq(irq, regs);
+	if (irq == IPI_IRQ)
+		arch_do_IPI(irq, regs);
+	else
+		handle_arch_irq(irq, regs);
 }
 
 void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
@@ -65,6 +68,14 @@ void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
 }
 #endif
 
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+#ifdef CONFIG_SMP
+	show_ipi_list(p, prec);
+#endif
+	return 0;
+}
+
 /*
  * API called for requesting percpu interrupts - called by each CPU
  *  - For boot CPU, actually request the IRQ with genirq core + enables
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index ec6a5c1..8d37906 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -22,6 +22,7 @@
 #include <linux/atomic.h>
 #include <linux/cpumask.h>
 #include <linux/reboot.h>
+#include <linux/seq_file.h>
 #include <asm/processor.h>
 #include <asm/setup.h>
 #include <asm/mach_desc.h>
@@ -349,6 +350,32 @@ irqreturn_t do_IPI(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+void arch_do_IPI(unsigned int irq, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+	unsigned int cpu = smp_processor_id();
+
+	__IRQ_STAT(cpu, ipi_irqs)++;
+
+	irq_enter();
+	do_IPI(irq, NULL);
+	irq_exit();
+
+	set_irq_regs(old_regs);
+}
+
+void show_ipi_list(struct seq_file *p, int prec)
+{
+	unsigned int cpu;
+
+	seq_printf(p, "%*s: ", prec - 1, "IPI");
+
+	for_each_online_cpu(cpu)
+		seq_printf(p, "%10u ", __IRQ_STAT(cpu, ipi_irqs));
+
+	seq_printf(p, " %s\n", "IPI");
+}
+
 /*
  * API called by platform code to hookup arch-common ISR to their IPI IRQ
  */
-- 
1.7.1

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

* [PATCH v5 12/20] ARC: [plat-eznps] Add eznps board defconfig and dts
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

Adding default configuration file and DTS file

Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 arch/arc/boot/dts/eznps.dts    |   94 ++++++++++++++++++++++++++++++++++++++++
 arch/arc/configs/nps_defconfig |   85 ++++++++++++++++++++++++++++++++++++
 2 files changed, 179 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/boot/dts/eznps.dts
 create mode 100644 arch/arc/configs/nps_defconfig

diff --git a/arch/arc/boot/dts/eznps.dts b/arch/arc/boot/dts/eznps.dts
new file mode 100644
index 0000000..2434948
--- /dev/null
+++ b/arch/arc/boot/dts/eznps.dts
@@ -0,0 +1,94 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "ezchip,arc-nps";
+	clock-frequency = <83333333>;	/* 83.333333 MHZ */
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+	present-cpus = "0-1,16-17";
+	possible-cpus = "0-4095";
+
+	aliases {
+		ethernet0 = &gmac0;
+		pll = &sysclk;
+	};
+
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32be,0xf7209000,115200n8 console=ttyS0,115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;	/* 512M */
+	};
+
+	clocks {
+		sysclk: sysclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <83333333>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* child and parent address space 1:1 mapped */
+		ranges;
+
+		intc: interrupt-controller {
+			compatible = "ezchip,nps400-ic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		timer {
+			compatible = "ezchip,nps400-timer";
+			clocks = <&sysclk>;
+			clock-names="sysclk";
+			interrupts = <3>;
+		};
+
+		uart@f7209000 {
+			compatible = "snps,dw-apb-uart";
+			device_type = "serial";
+			reg = <0xf7209000 0x100>;
+			interrupts = <6>;
+			clocks = <&sysclk>;
+			clock-names="baudclk";
+			baud = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			native-endian;
+		};
+
+		gmac0: ethernet@f7470000 {
+			compatible = "ezchip,nps-mgt-enet";
+			reg = <0xf7470000 0x1940>;
+			interrupts = <7>;
+			/* Filled in by U-Boot */
+			mac-address = [ 00 C0 00 F0 04 03 ];
+		};
+	};
+};
diff --git a/arch/arc/configs/nps_defconfig b/arch/arc/configs/nps_defconfig
new file mode 100644
index 0000000..13a67ac
--- /dev/null
+++ b/arch/arc/configs/nps_defconfig
@@ -0,0 +1,85 @@
+CONFIG_CROSS_COMPILE="arceb-linux-"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARC_PLAT_EZNPS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4096
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+# CONFIG_ARC_CACHE_PAGES is not set
+# CONFIG_ARC_HAS_LLSC is not set
+CONFIG_ARC_VMALLOC_SIZE=192
+CONFIG_ARC_EMUL_UNALIGNED=y
+CONFIG_ARC_UBOOT_SUPPORT=y
+CONFIG_PREEMPT=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=2048
+CONFIG_NETDEVICES=y
+CONFIG_NETCONSOLE=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
-- 
1.7.1


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

* [PATCH v5 12/20] ARC: [plat-eznps] Add eznps board defconfig and dts
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

Adding default configuration file and DTS file

Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 arch/arc/boot/dts/eznps.dts    |   94 ++++++++++++++++++++++++++++++++++++++++
 arch/arc/configs/nps_defconfig |   85 ++++++++++++++++++++++++++++++++++++
 2 files changed, 179 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/boot/dts/eznps.dts
 create mode 100644 arch/arc/configs/nps_defconfig

diff --git a/arch/arc/boot/dts/eznps.dts b/arch/arc/boot/dts/eznps.dts
new file mode 100644
index 0000000..2434948
--- /dev/null
+++ b/arch/arc/boot/dts/eznps.dts
@@ -0,0 +1,94 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "ezchip,arc-nps";
+	clock-frequency = <83333333>;	/* 83.333333 MHZ */
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+	present-cpus = "0-1,16-17";
+	possible-cpus = "0-4095";
+
+	aliases {
+		ethernet0 = &gmac0;
+		pll = &sysclk;
+	};
+
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32be,0xf7209000,115200n8 console=ttyS0,115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;	/* 512M */
+	};
+
+	clocks {
+		sysclk: sysclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <83333333>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* child and parent address space 1:1 mapped */
+		ranges;
+
+		intc: interrupt-controller {
+			compatible = "ezchip,nps400-ic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		timer {
+			compatible = "ezchip,nps400-timer";
+			clocks = <&sysclk>;
+			clock-names="sysclk";
+			interrupts = <3>;
+		};
+
+		uart at f7209000 {
+			compatible = "snps,dw-apb-uart";
+			device_type = "serial";
+			reg = <0xf7209000 0x100>;
+			interrupts = <6>;
+			clocks = <&sysclk>;
+			clock-names="baudclk";
+			baud = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			native-endian;
+		};
+
+		gmac0: ethernet at f7470000 {
+			compatible = "ezchip,nps-mgt-enet";
+			reg = <0xf7470000 0x1940>;
+			interrupts = <7>;
+			/* Filled in by U-Boot */
+			mac-address = [ 00 C0 00 F0 04 03 ];
+		};
+	};
+};
diff --git a/arch/arc/configs/nps_defconfig b/arch/arc/configs/nps_defconfig
new file mode 100644
index 0000000..13a67ac
--- /dev/null
+++ b/arch/arc/configs/nps_defconfig
@@ -0,0 +1,85 @@
+CONFIG_CROSS_COMPILE="arceb-linux-"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARC_PLAT_EZNPS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4096
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+# CONFIG_ARC_CACHE_PAGES is not set
+# CONFIG_ARC_HAS_LLSC is not set
+CONFIG_ARC_VMALLOC_SIZE=192
+CONFIG_ARC_EMUL_UNALIGNED=y
+CONFIG_ARC_UBOOT_SUPPORT=y
+CONFIG_PREEMPT=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=2048
+CONFIG_NETDEVICES=y
+CONFIG_NETCONSOLE=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
-- 
1.7.1

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

* [PATCH v5 13/20] ARC: [plat-eznps] Add eznps platform
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

This platform include boards:
	Hardware Emulator (HE)
	Simulator based upon nSIM.

Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 MAINTAINERS                             |    6 +
 arch/arc/plat-eznps/Kconfig             |   34 ++++++
 arch/arc/plat-eznps/Makefile            |    7 +
 arch/arc/plat-eznps/entry.S             |   70 +++++++++++
 arch/arc/plat-eznps/include/plat/ctop.h |  198 +++++++++++++++++++++++++++++++
 arch/arc/plat-eznps/include/plat/mtm.h  |   60 +++++++++
 arch/arc/plat-eznps/include/plat/smp.h  |   26 ++++
 arch/arc/plat-eznps/mtm.c               |  133 +++++++++++++++++++++
 arch/arc/plat-eznps/platform.c          |  102 ++++++++++++++++
 arch/arc/plat-eznps/smp.c               |  154 ++++++++++++++++++++++++
 10 files changed, 790 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/plat-eznps/Kconfig
 create mode 100644 arch/arc/plat-eznps/Makefile
 create mode 100644 arch/arc/plat-eznps/entry.S
 create mode 100644 arch/arc/plat-eznps/include/plat/ctop.h
 create mode 100644 arch/arc/plat-eznps/include/plat/mtm.h
 create mode 100644 arch/arc/plat-eznps/include/plat/smp.h
 create mode 100644 arch/arc/plat-eznps/mtm.c
 create mode 100644 arch/arc/plat-eznps/platform.c
 create mode 100644 arch/arc/plat-eznps/smp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 233f834..004e70e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4260,6 +4260,12 @@ S:	Maintained
 F:	drivers/video/fbdev/exynos/exynos_mipi*
 F:	include/video/exynos_mipi*
 
+EZchip NPS platform support
+M:	Noam Camus <noamc@ezchip.com>
+S:	Supported
+F:	arch/arc/plat-eznps
+F:	arch/arc/boot/dts/eznps.dts
+
 F71805F HARDWARE MONITORING DRIVER
 M:	Jean Delvare <jdelvare@suse.com>
 L:	lm-sensors@lm-sensors.org
diff --git a/arch/arc/plat-eznps/Kconfig b/arch/arc/plat-eznps/Kconfig
new file mode 100644
index 0000000..051fdca
--- /dev/null
+++ b/arch/arc/plat-eznps/Kconfig
@@ -0,0 +1,34 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+menuconfig ARC_PLAT_EZNPS
+	bool "\"EZchip\" ARC dev platform"
+	select ARC_HAS_COH_CACHES if SMP
+	select CPU_BIG_ENDIAN
+	select CLKSRC_NPS
+	select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET
+	help
+	  Support for EZchip development platforms,
+	  based on ARC700 cores.
+	  We handle few flavours:
+	    - Hardware Emulator AKA HE which is FPGA based chasis
+	    - Simulator based on MetaWare nSIM
+	    - NPS400 chip based on ASIC
+
+config EZNPS_MTM_EXT
+	bool "ARC-EZchip MTM Extensions"
+	select CPUMASK_OFFSTACK
+	depends on ARC_PLAT_EZNPS && SMP
+	default y
+	help
+	  Here we add new hierarchy for CPUs topology.
+	  We got:
+		Core
+		Thread
+	  At the new thread level each CPU represent one HW thread.
+	  At highest hierarchy each core contain 16 threads,
+	  any of them seem like CPU from Linux point of view.
+	  All threads within same core share the execution unit of the
+	  core and HW scheduler round robin between them.
diff --git a/arch/arc/plat-eznps/Makefile b/arch/arc/plat-eznps/Makefile
new file mode 100644
index 0000000..21091b1
--- /dev/null
+++ b/arch/arc/plat-eznps/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := entry.o platform.o
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_EZNPS_MTM_EXT) += mtm.o
diff --git a/arch/arc/plat-eznps/entry.S b/arch/arc/plat-eznps/entry.S
new file mode 100644
index 0000000..328261c
--- /dev/null
+++ b/arch/arc/plat-eznps/entry.S
@@ -0,0 +1,70 @@
+/*******************************************************************************
+
+  EZNPS CPU startup Code
+  Copyright(c) 2012 EZchip Technologies.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+  more details.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+*******************************************************************************/
+#include <linux/linkage.h>
+#include <asm/entry.h>
+#include <asm/cache.h>
+#include <plat/ctop.h>
+
+	.cpu A7
+
+	.section .init.text, "ax",@progbits
+	.align 1024	; HW requierment for restart first PC
+
+ENTRY(res_service)
+#ifdef CONFIG_EZNPS_MTM_EXT
+	; There is no work for HW thread id != 0
+	lr	r3, [CTOP_AUX_THREAD_ID]
+	cmp	r3, 0
+	jne	stext
+#endif
+
+#ifdef CONFIG_ARC_HAS_DCACHE
+	; With no cache coherency mechanism D$ need to be used very carefully.
+	; Address space:
+	; 0G-2G: We disable CONFIG_ARC_CACHE_PAGES.
+	; 2G-3G: We disable D$ by setting this bit.
+	; 3G-4G: D$ is disabled by architecture.
+	; FMT are huge pages for user application reside at 0-2G.
+	; Only FMT left as one who can use D$ where each such page got
+	; disable/enable bit for cachability.
+	; Programmer will use FMT pages for private data so cache coherency
+	; would not be a problem.
+	; First thing we invalidate D$
+	sr	1, [ARC_REG_DC_IVDC]
+	sr	HW_COMPLY_KRN_NOT_D_CACHED, [CTOP_AUX_HW_COMPLY]
+#endif
+
+#ifdef CONFIG_SMP
+	; We set logical cpuid to be used by GET_CPUID
+	; We do not use physical cpuid since we want ids to be continious when
+	; it comes to cpus on the same quad cluster.
+	; This is useful for applications that used shared resources of a quad
+	; cluster such SRAMS.
+	lr 	r3, [CTOP_AUX_CORE_ID]
+	sr	r3, [CTOP_AUX_LOGIC_CORE_ID]
+	lr	r3, [CTOP_AUX_CLUSTER_ID]
+	; Set logical is acheived by swap of 2 middle bits of cluster id (4 bit)
+	; r3 is used since we use short instruction and we need q-class reg
+	.short	CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST
+	.word 	CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM
+	 sr	r3, [CTOP_AUX_LOGIC_CLUSTER_ID]
+#endif
+
+	j	stext
+END(res_service)
diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
new file mode 100644
index 0000000..5844913
--- /dev/null
+++ b/arch/arc/plat-eznps/include/plat/ctop.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef _PLAT_EZNPS_CTOP_H
+#define _PLAT_EZNPS_CTOP_H
+
+#include <soc/nps/common.h>
+
+/* core auxiliary registers */
+#ifdef __ASSEMBLY__
+#define CTOP_AUX_BASE				(-0x800)
+#else
+#define CTOP_AUX_BASE				0xFFFFF800
+#endif
+
+#define CTOP_AUX_GLOBAL_ID			(CTOP_AUX_BASE + 0x000)
+#define CTOP_AUX_CLUSTER_ID			(CTOP_AUX_BASE + 0x004)
+#define CTOP_AUX_CORE_ID			(CTOP_AUX_BASE + 0x008)
+#define CTOP_AUX_THREAD_ID			(CTOP_AUX_BASE + 0x00C)
+#define CTOP_AUX_LOGIC_GLOBAL_ID		(CTOP_AUX_BASE + 0x010)
+#define CTOP_AUX_LOGIC_CLUSTER_ID		(CTOP_AUX_BASE + 0x014)
+#define CTOP_AUX_LOGIC_CORE_ID			(CTOP_AUX_BASE + 0x018)
+#define CTOP_AUX_MT_CTRL			(CTOP_AUX_BASE + 0x020)
+#define CTOP_AUX_HW_COMPLY			(CTOP_AUX_BASE + 0x024)
+#define CTOP_AUX_LPC				(CTOP_AUX_BASE + 0x030)
+#define CTOP_AUX_EFLAGS				(CTOP_AUX_BASE + 0x080)
+#define CTOP_AUX_IACK				(CTOP_AUX_BASE + 0x088)
+#define CTOP_AUX_GPA1				(CTOP_AUX_BASE + 0x08C)
+#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		0x3E6F7083
+#define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
+#define CTOP_INST_SCHD_RW			0x3E6F7004
+#define CTOP_INST_SCHD_RD			0x3E6F7084
+#define CTOP_INST_ASRI_0_R3			0x3B56003E
+#define CTOP_INST_XEX_DI_R2_R2_R3		0x4A664C00
+#define CTOP_INST_EXC_DI_R2_R2_R3		0x4A664C01
+#define CTOP_INST_AADD_DI_R2_R2_R3		0x4A664C02
+#define CTOP_INST_AAND_DI_R2_R2_R3		0x4A664C04
+#define CTOP_INST_AOR_DI_R2_R2_R3		0x4A664C05
+#define CTOP_INST_AXOR_DI_R2_R2_R3		0x4A664C06
+#define CTOP_INST_RSPI_GIC_0_R12		0x3C56117E
+
+/* Do not use D$ for address in 2G-3G */
+#define HW_COMPLY_KRN_NOT_D_CACHED		_BITUL(28)
+
+#define NPS_MSU_BLKID				0x018
+#define NPS_MSU_EN_CFG				0x80
+#define NPS_CRG_BLKID				0x480
+#define NPS_CRG_SYNC_BIT			_BITUL(0)
+#define NPS_GIM_BLKID				0x5C0
+
+/* GIM registers and fields*/
+#define NPS_GIM_UART_LINE			_BITUL(7)
+#define NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE	_BITUL(10)
+#define NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE	_BITUL(11)
+#define NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE	_BITUL(25)
+#define NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE	_BITUL(26)
+
+#ifndef __ASSEMBLY__
+/* Functional registers definition */
+struct nps_host_reg_mtm_cfg {
+	union {
+		struct {
+			u32 gen:1, gdis:1, clk_gate_dis:1, asb:1,
+			__reserved:9, nat:3, ten:16;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_mtm_cpu_cfg {
+	union {
+		struct {
+			u32 csa:22, dmsid:6, __reserved:3, cs:1;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_thr_init {
+	union {
+		struct {
+			u32 str:1, __reserved:27, thr_id:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_thr_init_sts {
+	union {
+		struct {
+			u32 bsy:1, err:1, __reserved:26, thr_id:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_msu_en_cfg {
+	union {
+		struct {
+			u32     __reserved1:11,
+			rtc_en:1, ipc_en:1, gim_1_en:1,
+			gim_0_en:1, ipi_en:1, buff_e_rls_bmuw:1,
+			buff_e_alc_bmuw:1, buff_i_rls_bmuw:1, buff_i_alc_bmuw:1,
+			buff_e_rls_bmue:1, buff_e_alc_bmue:1, buff_i_rls_bmue:1,
+			buff_i_alc_bmue:1, __reserved2:1, buff_e_pre_en:1,
+			buff_i_pre_en:1, pmuw_ja_en:1, pmue_ja_en:1,
+			pmuw_nj_en:1, pmue_nj_en:1, msu_en:1;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_gim_p_int_dst {
+	union {
+		struct {
+			u32 int_out_en:1, __reserved1:4,
+			is:1, intm:2, __reserved2:4,
+			nid:4, __reserved3:4, cid:4,
+			 __reserved4:4, tid:4;
+		};
+		u32 value;
+	};
+};
+
+/* AUX registers definition */
+struct nps_host_reg_aux_udmc {
+	union {
+		struct {
+			u32 dcp:1, cme:1, __reserved:20, nat:3,
+			__reserved2:5, dcas:3;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_mt_ctrl {
+	union {
+		struct {
+			u32 mten:1, hsen:1, scd:1, sten:1,
+			st_cnt:8, __reserved:8,
+			hs_cnt:8, __reserved1:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_hw_comply {
+	union {
+		struct {
+			u32 me:1, le:1, te:1, knc:1, __reserved:28;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_lpc {
+	union {
+		struct {
+			u32 mep:1, __reserved:31;
+		};
+		u32 value;
+	};
+};
+
+/* CRG registers */
+#define REG_GEN_PURP_0          nps_host_reg_non_cl(NPS_CRG_BLKID, 0x1BF)
+
+/* GIM registers */
+#define REG_GIM_P_INT_EN_0      nps_host_reg_non_cl(NPS_GIM_BLKID, 0x100)
+#define REG_GIM_P_INT_POL_0     nps_host_reg_non_cl(NPS_GIM_BLKID, 0x110)
+#define REG_GIM_P_INT_SENS_0    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x114)
+#define REG_GIM_P_INT_BLK_0     nps_host_reg_non_cl(NPS_GIM_BLKID, 0x118)
+#define REG_GIM_P_INT_DST_10    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13A)
+#define REG_GIM_P_INT_DST_11    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13B)
+#define REG_GIM_P_INT_DST_25    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x149)
+#define REG_GIM_P_INT_DST_26    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x14A)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PLAT_EZNPS_CTOP_H */
diff --git a/arch/arc/plat-eznps/include/plat/mtm.h b/arch/arc/plat-eznps/include/plat/mtm.h
new file mode 100644
index 0000000..29b91b5
--- /dev/null
+++ b/arch/arc/plat-eznps/include/plat/mtm.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef _PLAT_EZNPS_MTM_H
+#define _PLAT_EZNPS_MTM_H
+
+#include <plat/ctop.h>
+
+static inline void *nps_mtm_reg_addr(u32 cpu, u32 reg)
+{
+	struct global_id gid;
+	u32 core, blkid;
+
+	gid.value = cpu;
+	core = gid.core;
+	blkid = (((core & 0x0C) << 2) | (core & 0x03));
+
+	return nps_host_reg(cpu, blkid, reg);
+}
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#define NPS_CPU_TO_THREAD_NUM(cpu) \
+	({ struct global_id gid; gid.value = cpu; gid.thread; })
+
+/* MTM registers */
+#define MTM_CFG(cpu)			nps_mtm_reg_addr(cpu, 0x81)
+#define MTM_THR_INIT(cpu)		nps_mtm_reg_addr(cpu, 0x92)
+#define MTM_THR_INIT_STS(cpu)		nps_mtm_reg_addr(cpu, 0x93)
+
+#define get_thread(map) map.thread
+#define eznps_max_cpus 4096
+#define eznps_cpus_per_cluster	256
+
+void mtm_enable_core(unsigned int cpu);
+int mtm_enable_thread(int cpu);
+#else /* !CONFIG_EZNPS_MTM_EXT */
+
+#define get_thread(map) 0
+#define eznps_max_cpus 256
+#define eznps_cpus_per_cluster	16
+#define mtm_enable_core(cpu)
+#define mtm_enable_thread(cpu) 1
+#define NPS_CPU_TO_THREAD_NUM(cpu) 0
+
+#endif /* CONFIG_EZNPS_MTM_EXT */
+
+#endif /* _PLAT_EZNPS_MTM_H */
diff --git a/arch/arc/plat-eznps/include/plat/smp.h b/arch/arc/plat-eznps/include/plat/smp.h
new file mode 100644
index 0000000..06b59bd
--- /dev/null
+++ b/arch/arc/plat-eznps/include/plat/smp.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef __PLAT_EZNPS_SMP_H
+#define __PLAT_EZNPS_SMP_H
+
+#ifdef CONFIG_SMP
+
+extern void res_service(void);
+
+#endif /* CONFIG_SMP */
+
+#endif
diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c
new file mode 100644
index 0000000..aaaaffd
--- /dev/null
+++ b/arch/arc/plat-eznps/mtm.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/log2.h>
+#include <asm/arcregs.h>
+#include <plat/mtm.h>
+#include <plat/smp.h>
+
+#define MT_CTRL_HS_CNT		0xFF
+#define MT_CTRL_ST_CNT		0xF
+#define NPS_NUM_HW_THREADS	0x10
+
+static void mtm_init_nat(int cpu)
+{
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+	struct nps_host_reg_aux_udmc udmc;
+	int log_nat, nat = 0, i, t;
+
+	/* Iterate core threads and update nat */
+	for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
+		nat += test_bit(t, cpumask_bits(cpu_possible_mask));
+
+	log_nat = ilog2(nat);
+
+	udmc.value = read_aux_reg(CTOP_AUX_UDMC);
+	udmc.nat = log_nat;
+	write_aux_reg(CTOP_AUX_UDMC, udmc.value);
+
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.nat = log_nat;
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+}
+
+static void mtm_init_thread(int cpu)
+{
+	int i, tries = 5;
+	struct nps_host_reg_thr_init thr_init;
+	struct nps_host_reg_thr_init_sts thr_init_sts;
+
+	/* Set thread init register */
+	thr_init.value = 0;
+	iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
+	thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
+	thr_init.str = 1;
+	iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
+
+	/* Poll till thread init is done */
+	for (i = 0; i < tries; i++) {
+		thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
+		if (thr_init_sts.thr_id == thr_init.thr_id) {
+			if (thr_init_sts.bsy)
+				continue;
+			else if (thr_init_sts.err)
+				pr_warn("Failed to thread init cpu %u\n", cpu);
+			break;
+		}
+
+		pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
+		break;
+	}
+
+	if (i == tries)
+		pr_warn("Got thread init timeout for cpu %u\n", cpu);
+}
+
+int mtm_enable_thread(int cpu)
+{
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
+		return 1;
+
+	/* Enable thread in mtm */
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+
+	return 0;
+}
+
+void mtm_enable_core(unsigned int cpu)
+{
+	int i;
+	struct nps_host_reg_aux_mt_ctrl mt_ctrl;
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
+		return;
+
+	/* Initialize Number of Active Threads */
+	mtm_init_nat(cpu);
+
+	/* Initialize mtm_cfg */
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.ten = 1;
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+
+	/* Initialize all other threads in core */
+	for (i = 1; i < NPS_NUM_HW_THREADS; i++)
+		mtm_init_thread(cpu + i);
+
+
+	/* Enable HW schedule, stall counter, mtm */
+	mt_ctrl.value = 0;
+	mt_ctrl.hsen = 1;
+	mt_ctrl.hs_cnt = MT_CTRL_HS_CNT;
+	mt_ctrl.sten = 1;
+	mt_ctrl.st_cnt = MT_CTRL_ST_CNT;
+	mt_ctrl.mten = 1;
+	write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
+
+	/*
+	 * HW scheduling mechanism will start working
+	 * Only after call to instruction "schd.rw".
+	 * cpu_relax() calls "schd.rw" instruction.
+	 */
+	cpu_relax();
+}
diff --git a/arch/arc/plat-eznps/platform.c b/arch/arc/plat-eznps/platform.c
new file mode 100644
index 0000000..7ad6d2b
--- /dev/null
+++ b/arch/arc/plat-eznps/platform.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/mach_desc.h>
+#include <plat/mtm.h>
+
+static void __init eznps_configure_msu(void)
+{
+	int cpu;
+	struct nps_host_reg_msu_en_cfg msu_en_cfg = {.value = 0};
+
+	msu_en_cfg.msu_en = 1;
+	msu_en_cfg.ipi_en = 1;
+	msu_en_cfg.gim_0_en = 1;
+	msu_en_cfg.gim_1_en = 1;
+
+	/* enable IPI and GIM messages on all clusters */
+	for (cpu = 0 ; cpu < eznps_max_cpus; cpu += eznps_cpus_per_cluster)
+		iowrite32be(msu_en_cfg.value,
+			    nps_host_reg(cpu, NPS_MSU_BLKID, NPS_MSU_EN_CFG));
+}
+
+static void __init eznps_configure_gim(void)
+{
+	u32 reg_value;
+	u32 gim_int_lines;
+	struct nps_host_reg_gim_p_int_dst gim_p_int_dst = {.value = 0};
+
+	gim_int_lines = NPS_GIM_UART_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE;
+
+	/*
+	 * IRQ polarity
+	 * low or high level
+	 * negative or positive edge
+	 */
+	reg_value = ioread32be(REG_GIM_P_INT_POL_0);
+	reg_value &= ~gim_int_lines;
+	iowrite32be(reg_value, REG_GIM_P_INT_POL_0);
+
+	/* IRQ type level or edge */
+	reg_value = ioread32be(REG_GIM_P_INT_SENS_0);
+	reg_value |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
+	reg_value |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
+	iowrite32be(reg_value, REG_GIM_P_INT_SENS_0);
+
+	/*
+	 * GIM interrupt select type for
+	 * dbg_lan TX and RX interrupts
+	 * should be type 1
+	 * type 0 = IRQ line 6
+	 * type 1 = IRQ line 7
+	 */
+	gim_p_int_dst.is = 1;
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_10);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_11);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_25);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_26);
+
+	/*
+	 * CTOP IRQ lines should be defined
+	 * as blocking in GIM
+	*/
+	iowrite32be(gim_int_lines, REG_GIM_P_INT_BLK_0);
+
+	/* enable CTOP IRQ lines in GIM */
+	iowrite32be(gim_int_lines, REG_GIM_P_INT_EN_0);
+}
+
+static void __init eznps_early_init(void)
+{
+	eznps_configure_msu();
+	eznps_configure_gim();
+}
+
+static const char *eznps_compat[] __initconst = {
+	"ezchip,arc-nps",
+	NULL,
+};
+
+MACHINE_START(NPS, "nps")
+	.dt_compat	= eznps_compat,
+	.init_early	= eznps_early_init,
+MACHINE_END
diff --git a/arch/arc/plat-eznps/smp.c b/arch/arc/plat-eznps/smp.c
new file mode 100644
index 0000000..8f2d6af
--- /dev/null
+++ b/arch/arc/plat-eznps/smp.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/smp.h>
+#include <linux/of_fdt.h>
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <asm/irq.h>
+#include <plat/ctop.h>
+#include <plat/smp.h>
+#include <plat/mtm.h>
+
+#define NPS_DEFAULT_MSID	0x34
+#define NPS_MTM_CPU_CFG		0x90
+
+static char smp_cpuinfo_buf[128] = {"Extn [EZNPS-SMP]\t: On\n"};
+
+/* Get cpu map from device tree */
+static int __init eznps_get_map(const char *name, struct cpumask *cpumask)
+{
+	unsigned long dt_root = of_get_flat_dt_root();
+	const char *buf;
+
+	buf = of_get_flat_dt_prop(dt_root, name, NULL);
+	if (!buf)
+		return 1;
+
+	cpulist_parse(buf, cpumask);
+
+	return 0;
+}
+
+/* Update board cpu maps */
+static void __init eznps_init_cpumasks(void)
+{
+	struct cpumask cpumask;
+
+	if (eznps_get_map("present-cpus", &cpumask)) {
+		pr_err("Failed to get present-cpus from dtb");
+		return;
+	}
+	init_cpu_present(&cpumask);
+
+	if (eznps_get_map("possible-cpus", &cpumask)) {
+		pr_err("Failed to get possible-cpus from dtb");
+		return;
+	}
+	init_cpu_possible(&cpumask);
+}
+
+static void eznps_init_core(unsigned int cpu)
+{
+	u32 sync_value;
+	struct nps_host_reg_aux_hw_comply hw_comply;
+	struct nps_host_reg_aux_lpc lpc;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
+		return;
+
+	hw_comply.value = read_aux_reg(CTOP_AUX_HW_COMPLY);
+	hw_comply.me  = 1;
+	hw_comply.le  = 1;
+	hw_comply.te  = 1;
+	write_aux_reg(CTOP_AUX_HW_COMPLY, hw_comply.value);
+
+	/* Enable MMU clock */
+	lpc.mep = 1;
+	write_aux_reg(CTOP_AUX_LPC, lpc.value);
+
+	/* Boot CPU only */
+	if (!cpu) {
+		/* Write to general purpose register in CRG */
+		sync_value = ioread32be(REG_GEN_PURP_0);
+		sync_value |= NPS_CRG_SYNC_BIT;
+		iowrite32be(sync_value, REG_GEN_PURP_0);
+	}
+}
+
+/*
+ * Master kick starting another CPU
+ */
+static void __init eznps_smp_wakeup_cpu(int cpu, unsigned long pc)
+{
+	struct nps_host_reg_mtm_cpu_cfg cpu_cfg;
+
+	if (mtm_enable_thread(cpu) == 0)
+		return;
+
+	/* set PC, dmsid, and start CPU */
+	cpu_cfg.value = (u32)res_service;
+	cpu_cfg.dmsid = NPS_DEFAULT_MSID;
+	cpu_cfg.cs = 1;
+	iowrite32be(cpu_cfg.value, nps_mtm_reg_addr(cpu, NPS_MTM_CPU_CFG));
+}
+
+static void eznps_ipi_send(int cpu)
+{
+	struct global_id gid;
+	struct {
+		union {
+			struct {
+				u32 num:8, cluster:8, core:8, thread:8;
+			};
+			u32 value;
+		};
+	} ipi;
+
+	gid.value = cpu;
+	ipi.thread = get_thread(gid);
+	ipi.core = gid.core;
+	ipi.cluster = nps_cluster_logic_to_phys(gid.cluster);
+	ipi.num = IPI_IRQ;
+
+	__asm__ __volatile__(
+	"	mov r3, %0\n"
+	"	.word %1\n"
+	:
+	: "r"(ipi.value), "i"(CTOP_INST_ASRI_0_R3)
+	: "r3");
+}
+
+static void eznps_init_per_cpu(int cpu)
+{
+	eznps_init_core(cpu);
+	mtm_enable_core(cpu);
+}
+
+static void eznps_ipi_clear(int irq)
+{
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+}
+
+struct plat_smp_ops plat_smp_ops = {
+	.info		= smp_cpuinfo_buf,
+	.init_early_smp	= eznps_init_cpumasks,
+	.cpu_kick	= eznps_smp_wakeup_cpu,
+	.ipi_send	= eznps_ipi_send,
+	.init_per_cpu	= eznps_init_per_cpu,
+	.ipi_clear	= eznps_ipi_clear,
+};
+
-- 
1.7.1


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

* [PATCH v5 13/20] ARC: [plat-eznps] Add eznps platform
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

This platform include boards:
	Hardware Emulator (HE)
	Simulator based upon nSIM.

Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 MAINTAINERS                             |    6 +
 arch/arc/plat-eznps/Kconfig             |   34 ++++++
 arch/arc/plat-eznps/Makefile            |    7 +
 arch/arc/plat-eznps/entry.S             |   70 +++++++++++
 arch/arc/plat-eznps/include/plat/ctop.h |  198 +++++++++++++++++++++++++++++++
 arch/arc/plat-eznps/include/plat/mtm.h  |   60 +++++++++
 arch/arc/plat-eznps/include/plat/smp.h  |   26 ++++
 arch/arc/plat-eznps/mtm.c               |  133 +++++++++++++++++++++
 arch/arc/plat-eznps/platform.c          |  102 ++++++++++++++++
 arch/arc/plat-eznps/smp.c               |  154 ++++++++++++++++++++++++
 10 files changed, 790 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/plat-eznps/Kconfig
 create mode 100644 arch/arc/plat-eznps/Makefile
 create mode 100644 arch/arc/plat-eznps/entry.S
 create mode 100644 arch/arc/plat-eznps/include/plat/ctop.h
 create mode 100644 arch/arc/plat-eznps/include/plat/mtm.h
 create mode 100644 arch/arc/plat-eznps/include/plat/smp.h
 create mode 100644 arch/arc/plat-eznps/mtm.c
 create mode 100644 arch/arc/plat-eznps/platform.c
 create mode 100644 arch/arc/plat-eznps/smp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 233f834..004e70e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4260,6 +4260,12 @@ S:	Maintained
 F:	drivers/video/fbdev/exynos/exynos_mipi*
 F:	include/video/exynos_mipi*
 
+EZchip NPS platform support
+M:	Noam Camus <noamc at ezchip.com>
+S:	Supported
+F:	arch/arc/plat-eznps
+F:	arch/arc/boot/dts/eznps.dts
+
 F71805F HARDWARE MONITORING DRIVER
 M:	Jean Delvare <jdelvare at suse.com>
 L:	lm-sensors at lm-sensors.org
diff --git a/arch/arc/plat-eznps/Kconfig b/arch/arc/plat-eznps/Kconfig
new file mode 100644
index 0000000..051fdca
--- /dev/null
+++ b/arch/arc/plat-eznps/Kconfig
@@ -0,0 +1,34 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+menuconfig ARC_PLAT_EZNPS
+	bool "\"EZchip\" ARC dev platform"
+	select ARC_HAS_COH_CACHES if SMP
+	select CPU_BIG_ENDIAN
+	select CLKSRC_NPS
+	select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET
+	help
+	  Support for EZchip development platforms,
+	  based on ARC700 cores.
+	  We handle few flavours:
+	    - Hardware Emulator AKA HE which is FPGA based chasis
+	    - Simulator based on MetaWare nSIM
+	    - NPS400 chip based on ASIC
+
+config EZNPS_MTM_EXT
+	bool "ARC-EZchip MTM Extensions"
+	select CPUMASK_OFFSTACK
+	depends on ARC_PLAT_EZNPS && SMP
+	default y
+	help
+	  Here we add new hierarchy for CPUs topology.
+	  We got:
+		Core
+		Thread
+	  At the new thread level each CPU represent one HW thread.
+	  At highest hierarchy each core contain 16 threads,
+	  any of them seem like CPU from Linux point of view.
+	  All threads within same core share the execution unit of the
+	  core and HW scheduler round robin between them.
diff --git a/arch/arc/plat-eznps/Makefile b/arch/arc/plat-eznps/Makefile
new file mode 100644
index 0000000..21091b1
--- /dev/null
+++ b/arch/arc/plat-eznps/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := entry.o platform.o
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_EZNPS_MTM_EXT) += mtm.o
diff --git a/arch/arc/plat-eznps/entry.S b/arch/arc/plat-eznps/entry.S
new file mode 100644
index 0000000..328261c
--- /dev/null
+++ b/arch/arc/plat-eznps/entry.S
@@ -0,0 +1,70 @@
+/*******************************************************************************
+
+  EZNPS CPU startup Code
+  Copyright(c) 2012 EZchip Technologies.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+  more details.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+*******************************************************************************/
+#include <linux/linkage.h>
+#include <asm/entry.h>
+#include <asm/cache.h>
+#include <plat/ctop.h>
+
+	.cpu A7
+
+	.section .init.text, "ax", at progbits
+	.align 1024	; HW requierment for restart first PC
+
+ENTRY(res_service)
+#ifdef CONFIG_EZNPS_MTM_EXT
+	; There is no work for HW thread id != 0
+	lr	r3, [CTOP_AUX_THREAD_ID]
+	cmp	r3, 0
+	jne	stext
+#endif
+
+#ifdef CONFIG_ARC_HAS_DCACHE
+	; With no cache coherency mechanism D$ need to be used very carefully.
+	; Address space:
+	; 0G-2G: We disable CONFIG_ARC_CACHE_PAGES.
+	; 2G-3G: We disable D$ by setting this bit.
+	; 3G-4G: D$ is disabled by architecture.
+	; FMT are huge pages for user application reside at 0-2G.
+	; Only FMT left as one who can use D$ where each such page got
+	; disable/enable bit for cachability.
+	; Programmer will use FMT pages for private data so cache coherency
+	; would not be a problem.
+	; First thing we invalidate D$
+	sr	1, [ARC_REG_DC_IVDC]
+	sr	HW_COMPLY_KRN_NOT_D_CACHED, [CTOP_AUX_HW_COMPLY]
+#endif
+
+#ifdef CONFIG_SMP
+	; We set logical cpuid to be used by GET_CPUID
+	; We do not use physical cpuid since we want ids to be continious when
+	; it comes to cpus on the same quad cluster.
+	; This is useful for applications that used shared resources of a quad
+	; cluster such SRAMS.
+	lr 	r3, [CTOP_AUX_CORE_ID]
+	sr	r3, [CTOP_AUX_LOGIC_CORE_ID]
+	lr	r3, [CTOP_AUX_CLUSTER_ID]
+	; Set logical is acheived by swap of 2 middle bits of cluster id (4 bit)
+	; r3 is used since we use short instruction and we need q-class reg
+	.short	CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST
+	.word 	CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM
+	 sr	r3, [CTOP_AUX_LOGIC_CLUSTER_ID]
+#endif
+
+	j	stext
+END(res_service)
diff --git a/arch/arc/plat-eznps/include/plat/ctop.h b/arch/arc/plat-eznps/include/plat/ctop.h
new file mode 100644
index 0000000..5844913
--- /dev/null
+++ b/arch/arc/plat-eznps/include/plat/ctop.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef _PLAT_EZNPS_CTOP_H
+#define _PLAT_EZNPS_CTOP_H
+
+#include <soc/nps/common.h>
+
+/* core auxiliary registers */
+#ifdef __ASSEMBLY__
+#define CTOP_AUX_BASE				(-0x800)
+#else
+#define CTOP_AUX_BASE				0xFFFFF800
+#endif
+
+#define CTOP_AUX_GLOBAL_ID			(CTOP_AUX_BASE + 0x000)
+#define CTOP_AUX_CLUSTER_ID			(CTOP_AUX_BASE + 0x004)
+#define CTOP_AUX_CORE_ID			(CTOP_AUX_BASE + 0x008)
+#define CTOP_AUX_THREAD_ID			(CTOP_AUX_BASE + 0x00C)
+#define CTOP_AUX_LOGIC_GLOBAL_ID		(CTOP_AUX_BASE + 0x010)
+#define CTOP_AUX_LOGIC_CLUSTER_ID		(CTOP_AUX_BASE + 0x014)
+#define CTOP_AUX_LOGIC_CORE_ID			(CTOP_AUX_BASE + 0x018)
+#define CTOP_AUX_MT_CTRL			(CTOP_AUX_BASE + 0x020)
+#define CTOP_AUX_HW_COMPLY			(CTOP_AUX_BASE + 0x024)
+#define CTOP_AUX_LPC				(CTOP_AUX_BASE + 0x030)
+#define CTOP_AUX_EFLAGS				(CTOP_AUX_BASE + 0x080)
+#define CTOP_AUX_IACK				(CTOP_AUX_BASE + 0x088)
+#define CTOP_AUX_GPA1				(CTOP_AUX_BASE + 0x08C)
+#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		0x3E6F7083
+#define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
+#define CTOP_INST_SCHD_RW			0x3E6F7004
+#define CTOP_INST_SCHD_RD			0x3E6F7084
+#define CTOP_INST_ASRI_0_R3			0x3B56003E
+#define CTOP_INST_XEX_DI_R2_R2_R3		0x4A664C00
+#define CTOP_INST_EXC_DI_R2_R2_R3		0x4A664C01
+#define CTOP_INST_AADD_DI_R2_R2_R3		0x4A664C02
+#define CTOP_INST_AAND_DI_R2_R2_R3		0x4A664C04
+#define CTOP_INST_AOR_DI_R2_R2_R3		0x4A664C05
+#define CTOP_INST_AXOR_DI_R2_R2_R3		0x4A664C06
+#define CTOP_INST_RSPI_GIC_0_R12		0x3C56117E
+
+/* Do not use D$ for address in 2G-3G */
+#define HW_COMPLY_KRN_NOT_D_CACHED		_BITUL(28)
+
+#define NPS_MSU_BLKID				0x018
+#define NPS_MSU_EN_CFG				0x80
+#define NPS_CRG_BLKID				0x480
+#define NPS_CRG_SYNC_BIT			_BITUL(0)
+#define NPS_GIM_BLKID				0x5C0
+
+/* GIM registers and fields*/
+#define NPS_GIM_UART_LINE			_BITUL(7)
+#define NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE	_BITUL(10)
+#define NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE	_BITUL(11)
+#define NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE	_BITUL(25)
+#define NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE	_BITUL(26)
+
+#ifndef __ASSEMBLY__
+/* Functional registers definition */
+struct nps_host_reg_mtm_cfg {
+	union {
+		struct {
+			u32 gen:1, gdis:1, clk_gate_dis:1, asb:1,
+			__reserved:9, nat:3, ten:16;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_mtm_cpu_cfg {
+	union {
+		struct {
+			u32 csa:22, dmsid:6, __reserved:3, cs:1;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_thr_init {
+	union {
+		struct {
+			u32 str:1, __reserved:27, thr_id:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_thr_init_sts {
+	union {
+		struct {
+			u32 bsy:1, err:1, __reserved:26, thr_id:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_msu_en_cfg {
+	union {
+		struct {
+			u32     __reserved1:11,
+			rtc_en:1, ipc_en:1, gim_1_en:1,
+			gim_0_en:1, ipi_en:1, buff_e_rls_bmuw:1,
+			buff_e_alc_bmuw:1, buff_i_rls_bmuw:1, buff_i_alc_bmuw:1,
+			buff_e_rls_bmue:1, buff_e_alc_bmue:1, buff_i_rls_bmue:1,
+			buff_i_alc_bmue:1, __reserved2:1, buff_e_pre_en:1,
+			buff_i_pre_en:1, pmuw_ja_en:1, pmue_ja_en:1,
+			pmuw_nj_en:1, pmue_nj_en:1, msu_en:1;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_gim_p_int_dst {
+	union {
+		struct {
+			u32 int_out_en:1, __reserved1:4,
+			is:1, intm:2, __reserved2:4,
+			nid:4, __reserved3:4, cid:4,
+			 __reserved4:4, tid:4;
+		};
+		u32 value;
+	};
+};
+
+/* AUX registers definition */
+struct nps_host_reg_aux_udmc {
+	union {
+		struct {
+			u32 dcp:1, cme:1, __reserved:20, nat:3,
+			__reserved2:5, dcas:3;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_mt_ctrl {
+	union {
+		struct {
+			u32 mten:1, hsen:1, scd:1, sten:1,
+			st_cnt:8, __reserved:8,
+			hs_cnt:8, __reserved1:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_hw_comply {
+	union {
+		struct {
+			u32 me:1, le:1, te:1, knc:1, __reserved:28;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_lpc {
+	union {
+		struct {
+			u32 mep:1, __reserved:31;
+		};
+		u32 value;
+	};
+};
+
+/* CRG registers */
+#define REG_GEN_PURP_0          nps_host_reg_non_cl(NPS_CRG_BLKID, 0x1BF)
+
+/* GIM registers */
+#define REG_GIM_P_INT_EN_0      nps_host_reg_non_cl(NPS_GIM_BLKID, 0x100)
+#define REG_GIM_P_INT_POL_0     nps_host_reg_non_cl(NPS_GIM_BLKID, 0x110)
+#define REG_GIM_P_INT_SENS_0    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x114)
+#define REG_GIM_P_INT_BLK_0     nps_host_reg_non_cl(NPS_GIM_BLKID, 0x118)
+#define REG_GIM_P_INT_DST_10    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13A)
+#define REG_GIM_P_INT_DST_11    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13B)
+#define REG_GIM_P_INT_DST_25    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x149)
+#define REG_GIM_P_INT_DST_26    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x14A)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PLAT_EZNPS_CTOP_H */
diff --git a/arch/arc/plat-eznps/include/plat/mtm.h b/arch/arc/plat-eznps/include/plat/mtm.h
new file mode 100644
index 0000000..29b91b5
--- /dev/null
+++ b/arch/arc/plat-eznps/include/plat/mtm.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef _PLAT_EZNPS_MTM_H
+#define _PLAT_EZNPS_MTM_H
+
+#include <plat/ctop.h>
+
+static inline void *nps_mtm_reg_addr(u32 cpu, u32 reg)
+{
+	struct global_id gid;
+	u32 core, blkid;
+
+	gid.value = cpu;
+	core = gid.core;
+	blkid = (((core & 0x0C) << 2) | (core & 0x03));
+
+	return nps_host_reg(cpu, blkid, reg);
+}
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#define NPS_CPU_TO_THREAD_NUM(cpu) \
+	({ struct global_id gid; gid.value = cpu; gid.thread; })
+
+/* MTM registers */
+#define MTM_CFG(cpu)			nps_mtm_reg_addr(cpu, 0x81)
+#define MTM_THR_INIT(cpu)		nps_mtm_reg_addr(cpu, 0x92)
+#define MTM_THR_INIT_STS(cpu)		nps_mtm_reg_addr(cpu, 0x93)
+
+#define get_thread(map) map.thread
+#define eznps_max_cpus 4096
+#define eznps_cpus_per_cluster	256
+
+void mtm_enable_core(unsigned int cpu);
+int mtm_enable_thread(int cpu);
+#else /* !CONFIG_EZNPS_MTM_EXT */
+
+#define get_thread(map) 0
+#define eznps_max_cpus 256
+#define eznps_cpus_per_cluster	16
+#define mtm_enable_core(cpu)
+#define mtm_enable_thread(cpu) 1
+#define NPS_CPU_TO_THREAD_NUM(cpu) 0
+
+#endif /* CONFIG_EZNPS_MTM_EXT */
+
+#endif /* _PLAT_EZNPS_MTM_H */
diff --git a/arch/arc/plat-eznps/include/plat/smp.h b/arch/arc/plat-eznps/include/plat/smp.h
new file mode 100644
index 0000000..06b59bd
--- /dev/null
+++ b/arch/arc/plat-eznps/include/plat/smp.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef __PLAT_EZNPS_SMP_H
+#define __PLAT_EZNPS_SMP_H
+
+#ifdef CONFIG_SMP
+
+extern void res_service(void);
+
+#endif /* CONFIG_SMP */
+
+#endif
diff --git a/arch/arc/plat-eznps/mtm.c b/arch/arc/plat-eznps/mtm.c
new file mode 100644
index 0000000..aaaaffd
--- /dev/null
+++ b/arch/arc/plat-eznps/mtm.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/log2.h>
+#include <asm/arcregs.h>
+#include <plat/mtm.h>
+#include <plat/smp.h>
+
+#define MT_CTRL_HS_CNT		0xFF
+#define MT_CTRL_ST_CNT		0xF
+#define NPS_NUM_HW_THREADS	0x10
+
+static void mtm_init_nat(int cpu)
+{
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+	struct nps_host_reg_aux_udmc udmc;
+	int log_nat, nat = 0, i, t;
+
+	/* Iterate core threads and update nat */
+	for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
+		nat += test_bit(t, cpumask_bits(cpu_possible_mask));
+
+	log_nat = ilog2(nat);
+
+	udmc.value = read_aux_reg(CTOP_AUX_UDMC);
+	udmc.nat = log_nat;
+	write_aux_reg(CTOP_AUX_UDMC, udmc.value);
+
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.nat = log_nat;
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+}
+
+static void mtm_init_thread(int cpu)
+{
+	int i, tries = 5;
+	struct nps_host_reg_thr_init thr_init;
+	struct nps_host_reg_thr_init_sts thr_init_sts;
+
+	/* Set thread init register */
+	thr_init.value = 0;
+	iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
+	thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
+	thr_init.str = 1;
+	iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
+
+	/* Poll till thread init is done */
+	for (i = 0; i < tries; i++) {
+		thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
+		if (thr_init_sts.thr_id == thr_init.thr_id) {
+			if (thr_init_sts.bsy)
+				continue;
+			else if (thr_init_sts.err)
+				pr_warn("Failed to thread init cpu %u\n", cpu);
+			break;
+		}
+
+		pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
+		break;
+	}
+
+	if (i == tries)
+		pr_warn("Got thread init timeout for cpu %u\n", cpu);
+}
+
+int mtm_enable_thread(int cpu)
+{
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
+		return 1;
+
+	/* Enable thread in mtm */
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+
+	return 0;
+}
+
+void mtm_enable_core(unsigned int cpu)
+{
+	int i;
+	struct nps_host_reg_aux_mt_ctrl mt_ctrl;
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
+		return;
+
+	/* Initialize Number of Active Threads */
+	mtm_init_nat(cpu);
+
+	/* Initialize mtm_cfg */
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.ten = 1;
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+
+	/* Initialize all other threads in core */
+	for (i = 1; i < NPS_NUM_HW_THREADS; i++)
+		mtm_init_thread(cpu + i);
+
+
+	/* Enable HW schedule, stall counter, mtm */
+	mt_ctrl.value = 0;
+	mt_ctrl.hsen = 1;
+	mt_ctrl.hs_cnt = MT_CTRL_HS_CNT;
+	mt_ctrl.sten = 1;
+	mt_ctrl.st_cnt = MT_CTRL_ST_CNT;
+	mt_ctrl.mten = 1;
+	write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
+
+	/*
+	 * HW scheduling mechanism will start working
+	 * Only after call to instruction "schd.rw".
+	 * cpu_relax() calls "schd.rw" instruction.
+	 */
+	cpu_relax();
+}
diff --git a/arch/arc/plat-eznps/platform.c b/arch/arc/plat-eznps/platform.c
new file mode 100644
index 0000000..7ad6d2b
--- /dev/null
+++ b/arch/arc/plat-eznps/platform.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/mach_desc.h>
+#include <plat/mtm.h>
+
+static void __init eznps_configure_msu(void)
+{
+	int cpu;
+	struct nps_host_reg_msu_en_cfg msu_en_cfg = {.value = 0};
+
+	msu_en_cfg.msu_en = 1;
+	msu_en_cfg.ipi_en = 1;
+	msu_en_cfg.gim_0_en = 1;
+	msu_en_cfg.gim_1_en = 1;
+
+	/* enable IPI and GIM messages on all clusters */
+	for (cpu = 0 ; cpu < eznps_max_cpus; cpu += eznps_cpus_per_cluster)
+		iowrite32be(msu_en_cfg.value,
+			    nps_host_reg(cpu, NPS_MSU_BLKID, NPS_MSU_EN_CFG));
+}
+
+static void __init eznps_configure_gim(void)
+{
+	u32 reg_value;
+	u32 gim_int_lines;
+	struct nps_host_reg_gim_p_int_dst gim_p_int_dst = {.value = 0};
+
+	gim_int_lines = NPS_GIM_UART_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE;
+
+	/*
+	 * IRQ polarity
+	 * low or high level
+	 * negative or positive edge
+	 */
+	reg_value = ioread32be(REG_GIM_P_INT_POL_0);
+	reg_value &= ~gim_int_lines;
+	iowrite32be(reg_value, REG_GIM_P_INT_POL_0);
+
+	/* IRQ type level or edge */
+	reg_value = ioread32be(REG_GIM_P_INT_SENS_0);
+	reg_value |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
+	reg_value |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
+	iowrite32be(reg_value, REG_GIM_P_INT_SENS_0);
+
+	/*
+	 * GIM interrupt select type for
+	 * dbg_lan TX and RX interrupts
+	 * should be type 1
+	 * type 0 = IRQ line 6
+	 * type 1 = IRQ line 7
+	 */
+	gim_p_int_dst.is = 1;
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_10);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_11);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_25);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_26);
+
+	/*
+	 * CTOP IRQ lines should be defined
+	 * as blocking in GIM
+	*/
+	iowrite32be(gim_int_lines, REG_GIM_P_INT_BLK_0);
+
+	/* enable CTOP IRQ lines in GIM */
+	iowrite32be(gim_int_lines, REG_GIM_P_INT_EN_0);
+}
+
+static void __init eznps_early_init(void)
+{
+	eznps_configure_msu();
+	eznps_configure_gim();
+}
+
+static const char *eznps_compat[] __initconst = {
+	"ezchip,arc-nps",
+	NULL,
+};
+
+MACHINE_START(NPS, "nps")
+	.dt_compat	= eznps_compat,
+	.init_early	= eznps_early_init,
+MACHINE_END
diff --git a/arch/arc/plat-eznps/smp.c b/arch/arc/plat-eznps/smp.c
new file mode 100644
index 0000000..8f2d6af
--- /dev/null
+++ b/arch/arc/plat-eznps/smp.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/smp.h>
+#include <linux/of_fdt.h>
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <asm/irq.h>
+#include <plat/ctop.h>
+#include <plat/smp.h>
+#include <plat/mtm.h>
+
+#define NPS_DEFAULT_MSID	0x34
+#define NPS_MTM_CPU_CFG		0x90
+
+static char smp_cpuinfo_buf[128] = {"Extn [EZNPS-SMP]\t: On\n"};
+
+/* Get cpu map from device tree */
+static int __init eznps_get_map(const char *name, struct cpumask *cpumask)
+{
+	unsigned long dt_root = of_get_flat_dt_root();
+	const char *buf;
+
+	buf = of_get_flat_dt_prop(dt_root, name, NULL);
+	if (!buf)
+		return 1;
+
+	cpulist_parse(buf, cpumask);
+
+	return 0;
+}
+
+/* Update board cpu maps */
+static void __init eznps_init_cpumasks(void)
+{
+	struct cpumask cpumask;
+
+	if (eznps_get_map("present-cpus", &cpumask)) {
+		pr_err("Failed to get present-cpus from dtb");
+		return;
+	}
+	init_cpu_present(&cpumask);
+
+	if (eznps_get_map("possible-cpus", &cpumask)) {
+		pr_err("Failed to get possible-cpus from dtb");
+		return;
+	}
+	init_cpu_possible(&cpumask);
+}
+
+static void eznps_init_core(unsigned int cpu)
+{
+	u32 sync_value;
+	struct nps_host_reg_aux_hw_comply hw_comply;
+	struct nps_host_reg_aux_lpc lpc;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
+		return;
+
+	hw_comply.value = read_aux_reg(CTOP_AUX_HW_COMPLY);
+	hw_comply.me  = 1;
+	hw_comply.le  = 1;
+	hw_comply.te  = 1;
+	write_aux_reg(CTOP_AUX_HW_COMPLY, hw_comply.value);
+
+	/* Enable MMU clock */
+	lpc.mep = 1;
+	write_aux_reg(CTOP_AUX_LPC, lpc.value);
+
+	/* Boot CPU only */
+	if (!cpu) {
+		/* Write to general purpose register in CRG */
+		sync_value = ioread32be(REG_GEN_PURP_0);
+		sync_value |= NPS_CRG_SYNC_BIT;
+		iowrite32be(sync_value, REG_GEN_PURP_0);
+	}
+}
+
+/*
+ * Master kick starting another CPU
+ */
+static void __init eznps_smp_wakeup_cpu(int cpu, unsigned long pc)
+{
+	struct nps_host_reg_mtm_cpu_cfg cpu_cfg;
+
+	if (mtm_enable_thread(cpu) == 0)
+		return;
+
+	/* set PC, dmsid, and start CPU */
+	cpu_cfg.value = (u32)res_service;
+	cpu_cfg.dmsid = NPS_DEFAULT_MSID;
+	cpu_cfg.cs = 1;
+	iowrite32be(cpu_cfg.value, nps_mtm_reg_addr(cpu, NPS_MTM_CPU_CFG));
+}
+
+static void eznps_ipi_send(int cpu)
+{
+	struct global_id gid;
+	struct {
+		union {
+			struct {
+				u32 num:8, cluster:8, core:8, thread:8;
+			};
+			u32 value;
+		};
+	} ipi;
+
+	gid.value = cpu;
+	ipi.thread = get_thread(gid);
+	ipi.core = gid.core;
+	ipi.cluster = nps_cluster_logic_to_phys(gid.cluster);
+	ipi.num = IPI_IRQ;
+
+	__asm__ __volatile__(
+	"	mov r3, %0\n"
+	"	.word %1\n"
+	:
+	: "r"(ipi.value), "i"(CTOP_INST_ASRI_0_R3)
+	: "r3");
+}
+
+static void eznps_init_per_cpu(int cpu)
+{
+	eznps_init_core(cpu);
+	mtm_enable_core(cpu);
+}
+
+static void eznps_ipi_clear(int irq)
+{
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+}
+
+struct plat_smp_ops plat_smp_ops = {
+	.info		= smp_cpuinfo_buf,
+	.init_early_smp	= eznps_init_cpumasks,
+	.cpu_kick	= eznps_smp_wakeup_cpu,
+	.ipi_send	= eznps_ipi_send,
+	.init_per_cpu	= eznps_init_per_cpu,
+	.ipi_clear	= eznps_ipi_clear,
+};
+
-- 
1.7.1

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

* [PATCH v5 14/20] ARC: [plat-eznps] Use dedicated user stack top
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

NPS use special mapping right below TASK_SIZE.
Hence we need to lower STACK_TOP so that user stack won't
overlap NPS special mapping.

Signed-off-by: Noam Camus <noamc@ezchip.com>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/processor.h |   17 +++++++++++++++++
 arch/arc/mm/tlb.c                |    6 ++++++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 8a77ccd..41142ab 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -122,7 +122,24 @@ extern unsigned int get_wchan(struct task_struct *p);
 
 #define USER_KERNEL_GUTTER    (VMALLOC_START - TASK_SIZE)
 
+#ifdef CONFIG_ARC_PLAT_EZNPS
+/* NPS architecture defines special window of 129M in user address space for
+ * special memory areas, when accessing this window the MMU do not use TLB.
+ * Instead MMU direct the access to:
+ * 0x57f00000:0x57ffffff -- 1M of closely coupled memory (aka CMEM)
+ * 0x58000000:0x5fffffff -- 16 huge pages, 8M each, with fixed map (aka FMTs)
+ *
+ * CMEM - is the fastest memory we got and its size is 16K.
+ * FMT  - is used to map either to internal/external memory.
+ * Internal memory is the second fast memory and its size is 16M
+ * External memory is the biggest memory (16G) and also the slowest.
+ *
+ * STACK_TOP need to be PMD align (21bit) that is why we supply 0x57e00000.
+ */
+#define STACK_TOP       0x57e00000
+#else /* CONFIG_ARC_PLAT_EZNPS */
 #define STACK_TOP       TASK_SIZE
+#endif /* CONFIG_ARC_PLAT_EZNPS */
 #define STACK_TOP_MAX   STACK_TOP
 
 /* This decides where the kernel will search for a free chunk of vm
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 843e1a5..01f85e5 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -820,6 +820,12 @@ void arc_mmu_init(void)
 	 */
 	BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_VMALLOC_SIZE << 20), PMD_SIZE));
 
+	/*
+	 * stack top size sanity check,
+	 * Can't be done in processor.h due to header include depenedencies
+	 */
+	BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE));
+
 	/* For efficiency sake, kernel is compile time built for a MMU ver
 	 * This must match the hardware it is running on.
 	 * Linux built for MMU V2, if run on MMU V1 will break down because V1
-- 
1.7.1


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

* [PATCH v5 14/20] ARC: [plat-eznps] Use dedicated user stack top
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

NPS use special mapping right below TASK_SIZE.
Hence we need to lower STACK_TOP so that user stack won't
overlap NPS special mapping.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Acked-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/include/asm/processor.h |   17 +++++++++++++++++
 arch/arc/mm/tlb.c                |    6 ++++++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 8a77ccd..41142ab 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -122,7 +122,24 @@ extern unsigned int get_wchan(struct task_struct *p);
 
 #define USER_KERNEL_GUTTER    (VMALLOC_START - TASK_SIZE)
 
+#ifdef CONFIG_ARC_PLAT_EZNPS
+/* NPS architecture defines special window of 129M in user address space for
+ * special memory areas, when accessing this window the MMU do not use TLB.
+ * Instead MMU direct the access to:
+ * 0x57f00000:0x57ffffff -- 1M of closely coupled memory (aka CMEM)
+ * 0x58000000:0x5fffffff -- 16 huge pages, 8M each, with fixed map (aka FMTs)
+ *
+ * CMEM - is the fastest memory we got and its size is 16K.
+ * FMT  - is used to map either to internal/external memory.
+ * Internal memory is the second fast memory and its size is 16M
+ * External memory is the biggest memory (16G) and also the slowest.
+ *
+ * STACK_TOP need to be PMD align (21bit) that is why we supply 0x57e00000.
+ */
+#define STACK_TOP       0x57e00000
+#else /* CONFIG_ARC_PLAT_EZNPS */
 #define STACK_TOP       TASK_SIZE
+#endif /* CONFIG_ARC_PLAT_EZNPS */
 #define STACK_TOP_MAX   STACK_TOP
 
 /* This decides where the kernel will search for a free chunk of vm
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 843e1a5..01f85e5 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -820,6 +820,12 @@ void arc_mmu_init(void)
 	 */
 	BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_VMALLOC_SIZE << 20), PMD_SIZE));
 
+	/*
+	 * stack top size sanity check,
+	 * Can't be done in processor.h due to header include depenedencies
+	 */
+	BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE));
+
 	/* For efficiency sake, kernel is compile time built for a MMU ver
 	 * This must match the hardware it is running on.
 	 * Linux built for MMU V2, if run on MMU V1 will break down because V1
-- 
1.7.1

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

* [PATCH v5 15/20] ARC: [plat-eznps] Use dedicated atomic/bitops/cmpxchg
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

We need our own implementaions since we lack LLSC support.
Our extended ISA provided with optimized solution for all 32bit
operations we see in these three headers.
Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 arch/arc/include/asm/atomic.h  |   79 +++++++++++++++++++++++++++++++++++-
 arch/arc/include/asm/bitops.h  |   54 +++++++++++++++++++++++++
 arch/arc/include/asm/cmpxchg.h |   87 +++++++++++++++++++++++++++++++++-------
 3 files changed, 202 insertions(+), 18 deletions(-)

diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h
index 7730d30..a626996 100644
--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -17,6 +17,7 @@
 #include <asm/barrier.h>
 #include <asm/smp.h>
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 #define atomic_read(v)  READ_ONCE((v)->counter)
 
 #ifdef CONFIG_ARC_HAS_LLSC
@@ -180,12 +181,84 @@ ATOMIC_OP(andnot, &= ~, bic)
 ATOMIC_OP(or, |=, or)
 ATOMIC_OP(xor, ^=, xor)
 
-#undef ATOMIC_OPS
-#undef ATOMIC_OP_RETURN
-#undef ATOMIC_OP
 #undef SCOND_FAIL_RETRY_VAR_DEF
 #undef SCOND_FAIL_RETRY_ASM
 #undef SCOND_FAIL_RETRY_VARS
+#else /* CONFIG_ARC_PLAT_EZNPS */
+static inline int atomic_read(const atomic_t *v)
+{
+	int temp;
+
+	__asm__ __volatile__(
+	"	ld.di %0, [%1]"
+	: "=r"(temp)
+	: "r"(&v->counter)
+	: "memory");
+	return temp;
+}
+
+static inline void atomic_set(atomic_t *v, int i)
+{
+	__asm__ __volatile__(
+	"	st.di %0,[%1]"
+	:
+	: "r"(i), "r"(&v->counter)
+	: "memory");
+}
+
+#define ATOMIC_OP(op, c_op, asm_op)					\
+static inline void atomic_##op(int i, atomic_t *v)			\
+{									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	:								\
+	: "r"(i), "r"(&v->counter), "i"(asm_op)				\
+	: "r2", "r3", "memory");					\
+}									\
+
+#define ATOMIC_OP_RETURN(op, c_op, asm_op)				\
+static inline int atomic_##op##_return(int i, atomic_t *v)		\
+{									\
+	unsigned int temp = i;						\
+									\
+	/* Explicit full memory barrier needed before/after */		\
+	smp_mb();							\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	"	mov %0, r2"						\
+	: "+r"(temp)							\
+	: "r"(&v->counter), "i"(asm_op)					\
+	: "r2", "r3", "memory");					\
+									\
+	smp_mb();							\
+									\
+	temp c_op i;							\
+									\
+	return temp;							\
+}
+
+#define ATOMIC_OPS(op, c_op, asm_op)					\
+	ATOMIC_OP(op, c_op, asm_op)					\
+	ATOMIC_OP_RETURN(op, c_op, asm_op)
+
+ATOMIC_OPS(add, +=, CTOP_INST_AADD_DI_R2_R2_R3)
+#define atomic_sub(i, v) atomic_add(-(i), (v))
+#define atomic_sub_return(i, v) atomic_add_return(-(i), (v))
+
+ATOMIC_OP(and, &=, CTOP_INST_AAND_DI_R2_R2_R3)
+#define atomic_andnot(mask, v) atomic_and(~(mask), (v))
+ATOMIC_OP(or, |=, CTOP_INST_AOR_DI_R2_R2_R3)
+ATOMIC_OP(xor, ^=, CTOP_INST_AXOR_DI_R2_R2_R3)
+#endif /* CONFIG_ARC_PLAT_EZNPS */
+
+#undef ATOMIC_OPS
+#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP
 
 /**
  * __atomic_add_unless - add unless the number is a given value
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index 57c1f33..5a29185 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -22,6 +22,7 @@
 #include <asm/smp.h>
 #endif
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 #if defined(CONFIG_ARC_HAS_LLSC)
 
 /*
@@ -155,6 +156,53 @@ static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *
 }
 
 #endif /* CONFIG_ARC_HAS_LLSC */
+#else /* CONFIG_ARC_PLAT_EZNPS */
+#define BIT_OP(op, c_op, asm_op)					\
+static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
+{									\
+	m += nr >> 5;							\
+									\
+	nr = (1UL << (nr & 0x1f));					\
+	if (asm_op == CTOP_INST_AAND_DI_R2_R2_R3)			\
+		nr = ~nr;						\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"	.word %2\n"						\
+	:								\
+	: "r"(nr), "r"(m), "i"(asm_op)					\
+	: "r2", "r3", "memory");					\
+}
+
+#define TEST_N_BIT_OP(op, c_op, asm_op)					\
+static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
+{									\
+	unsigned long old;						\
+									\
+	m += nr >> 5;							\
+									\
+	nr = old = (1UL << (nr & 0x1f));				\
+	if (asm_op == CTOP_INST_AAND_DI_R2_R2_R3)			\
+		old = ~old;						\
+									\
+	/* Explicit full memory barrier needed before/after */		\
+	smp_mb();							\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	"	mov %0, r2"						\
+	: "+r"(old)							\
+	: "r"(m), "i"(asm_op)						\
+	: "r2", "r3", "memory");					\
+									\
+	smp_mb();							\
+									\
+	return (old & nr) != 0;					\
+}
+#endif /* CONFIG_ARC_PLAT_EZNPS */
 
 /***************************************
  * Non atomic variants
@@ -196,9 +244,15 @@ static inline int __test_and_##op##_bit(unsigned long nr, volatile unsigned long
 	/* __test_and_set_bit(), __test_and_clear_bit(), __test_and_change_bit() */\
 	__TEST_N_BIT_OP(op, c_op, asm_op)
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 BIT_OPS(set, |, bset)
 BIT_OPS(clear, & ~, bclr)
 BIT_OPS(change, ^, bxor)
+#else
+BIT_OPS(set, |, CTOP_INST_AOR_DI_R2_R2_R3)
+BIT_OPS(clear, & ~, CTOP_INST_AAND_DI_R2_R2_R3)
+BIT_OPS(change, ^, CTOP_INST_AXOR_DI_R2_R2_R3)
+#endif
 
 /*
  * This routine doesn't need to be atomic.
diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h
index af7a2db..6d320d3 100644
--- a/arch/arc/include/asm/cmpxchg.h
+++ b/arch/arc/include/asm/cmpxchg.h
@@ -14,6 +14,7 @@
 #include <asm/barrier.h>
 #include <asm/smp.h>
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 #ifdef CONFIG_ARC_HAS_LLSC
 
 static inline unsigned long
@@ -66,21 +67,6 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
 
 #endif /* CONFIG_ARC_HAS_LLSC */
 
-#define cmpxchg(ptr, o, n) ((typeof(*(ptr)))__cmpxchg((ptr), \
-				(unsigned long)(o), (unsigned long)(n)))
-
-/*
- * Since not supported natively, ARC cmpxchg() uses atomic_ops_lock (UP/SMP)
- * just to gaurantee semantics.
- * atomic_cmpxchg() needs to use the same locks as it's other atomic siblings
- * which also happens to be atomic_ops_lock.
- *
- * Thus despite semantically being different, implementation of atomic_cmpxchg()
- * is same as cmpxchg().
- */
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-
-
 /*
  * xchg (reg with memory) based on "Native atomic" EX insn
  */
@@ -143,6 +129,63 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
 
 #endif
 
+#else /* CONFIG_ARC_PLAT_EZNPS */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
+{
+	/*
+	 * Explicit full memory barrier needed before/after
+	 */
+	smp_mb();
+
+	write_aux_reg(CTOP_AUX_GPA1, expected);
+
+	__asm__ __volatile__(
+	"	mov r2, %0\n"
+	"	mov r3, %1\n"
+	"	.word %2\n"
+	"	mov %0, r2"
+	: "+r"(new)
+	: "r"(ptr), "i"(CTOP_INST_EXC_DI_R2_R2_R3)
+	: "r2", "r3", "memory");
+
+	smp_mb();
+
+	return new;
+}
+
+static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
+				   int size)
+{
+	extern unsigned long __xchg_bad_pointer(void);
+
+	switch (size) {
+	case 4:
+		/*
+		 * Explicit full memory barrier needed before/after
+		 */
+		smp_mb();
+
+		__asm__ __volatile__(
+		"	mov r2, %0\n"
+		"	mov r3, %1\n"
+		"	.word %2\n"
+		"	mov %0, r2\n"
+		: "+r"(val)
+		: "r"(ptr), "i"(CTOP_INST_XEX_DI_R2_R2_R3)
+		: "r2", "r3", "memory");
+
+		smp_mb();
+
+		return val;
+	}
+	return __xchg_bad_pointer();
+}
+
+#define xchg(ptr, with) ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), \
+						 sizeof(*(ptr))))
+#endif /* CONFIG_ARC_PLAT_EZNPS */
+
 /*
  * "atomic" variant of xchg()
  * REQ: It needs to follow the same serialization rules as other atomic_xxx()
@@ -158,4 +201,18 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
  */
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
+#define cmpxchg(ptr, o, n) ((typeof(*(ptr)))__cmpxchg((ptr), \
+				(unsigned long)(o), (unsigned long)(n)))
+
+/*
+ * Since not supported natively, ARC cmpxchg() uses atomic_ops_lock (UP/SMP)
+ * just to gaurantee semantics.
+ * atomic_cmpxchg() needs to use the same locks as it's other atomic siblings
+ * which also happens to be atomic_ops_lock.
+ *
+ * Thus despite semantically being different, implementation of atomic_cmpxchg()
+ * is same as cmpxchg().
+ */
+#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+
 #endif
-- 
1.7.1


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

* [PATCH v5 15/20] ARC: [plat-eznps] Use dedicated atomic/bitops/cmpxchg
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

We need our own implementaions since we lack LLSC support.
Our extended ISA provided with optimized solution for all 32bit
operations we see in these three headers.
Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 arch/arc/include/asm/atomic.h  |   79 +++++++++++++++++++++++++++++++++++-
 arch/arc/include/asm/bitops.h  |   54 +++++++++++++++++++++++++
 arch/arc/include/asm/cmpxchg.h |   87 +++++++++++++++++++++++++++++++++-------
 3 files changed, 202 insertions(+), 18 deletions(-)

diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h
index 7730d30..a626996 100644
--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -17,6 +17,7 @@
 #include <asm/barrier.h>
 #include <asm/smp.h>
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 #define atomic_read(v)  READ_ONCE((v)->counter)
 
 #ifdef CONFIG_ARC_HAS_LLSC
@@ -180,12 +181,84 @@ ATOMIC_OP(andnot, &= ~, bic)
 ATOMIC_OP(or, |=, or)
 ATOMIC_OP(xor, ^=, xor)
 
-#undef ATOMIC_OPS
-#undef ATOMIC_OP_RETURN
-#undef ATOMIC_OP
 #undef SCOND_FAIL_RETRY_VAR_DEF
 #undef SCOND_FAIL_RETRY_ASM
 #undef SCOND_FAIL_RETRY_VARS
+#else /* CONFIG_ARC_PLAT_EZNPS */
+static inline int atomic_read(const atomic_t *v)
+{
+	int temp;
+
+	__asm__ __volatile__(
+	"	ld.di %0, [%1]"
+	: "=r"(temp)
+	: "r"(&v->counter)
+	: "memory");
+	return temp;
+}
+
+static inline void atomic_set(atomic_t *v, int i)
+{
+	__asm__ __volatile__(
+	"	st.di %0,[%1]"
+	:
+	: "r"(i), "r"(&v->counter)
+	: "memory");
+}
+
+#define ATOMIC_OP(op, c_op, asm_op)					\
+static inline void atomic_##op(int i, atomic_t *v)			\
+{									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	:								\
+	: "r"(i), "r"(&v->counter), "i"(asm_op)				\
+	: "r2", "r3", "memory");					\
+}									\
+
+#define ATOMIC_OP_RETURN(op, c_op, asm_op)				\
+static inline int atomic_##op##_return(int i, atomic_t *v)		\
+{									\
+	unsigned int temp = i;						\
+									\
+	/* Explicit full memory barrier needed before/after */		\
+	smp_mb();							\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	"	mov %0, r2"						\
+	: "+r"(temp)							\
+	: "r"(&v->counter), "i"(asm_op)					\
+	: "r2", "r3", "memory");					\
+									\
+	smp_mb();							\
+									\
+	temp c_op i;							\
+									\
+	return temp;							\
+}
+
+#define ATOMIC_OPS(op, c_op, asm_op)					\
+	ATOMIC_OP(op, c_op, asm_op)					\
+	ATOMIC_OP_RETURN(op, c_op, asm_op)
+
+ATOMIC_OPS(add, +=, CTOP_INST_AADD_DI_R2_R2_R3)
+#define atomic_sub(i, v) atomic_add(-(i), (v))
+#define atomic_sub_return(i, v) atomic_add_return(-(i), (v))
+
+ATOMIC_OP(and, &=, CTOP_INST_AAND_DI_R2_R2_R3)
+#define atomic_andnot(mask, v) atomic_and(~(mask), (v))
+ATOMIC_OP(or, |=, CTOP_INST_AOR_DI_R2_R2_R3)
+ATOMIC_OP(xor, ^=, CTOP_INST_AXOR_DI_R2_R2_R3)
+#endif /* CONFIG_ARC_PLAT_EZNPS */
+
+#undef ATOMIC_OPS
+#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP
 
 /**
  * __atomic_add_unless - add unless the number is a given value
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index 57c1f33..5a29185 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -22,6 +22,7 @@
 #include <asm/smp.h>
 #endif
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 #if defined(CONFIG_ARC_HAS_LLSC)
 
 /*
@@ -155,6 +156,53 @@ static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *
 }
 
 #endif /* CONFIG_ARC_HAS_LLSC */
+#else /* CONFIG_ARC_PLAT_EZNPS */
+#define BIT_OP(op, c_op, asm_op)					\
+static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
+{									\
+	m += nr >> 5;							\
+									\
+	nr = (1UL << (nr & 0x1f));					\
+	if (asm_op == CTOP_INST_AAND_DI_R2_R2_R3)			\
+		nr = ~nr;						\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"	.word %2\n"						\
+	:								\
+	: "r"(nr), "r"(m), "i"(asm_op)					\
+	: "r2", "r3", "memory");					\
+}
+
+#define TEST_N_BIT_OP(op, c_op, asm_op)					\
+static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
+{									\
+	unsigned long old;						\
+									\
+	m += nr >> 5;							\
+									\
+	nr = old = (1UL << (nr & 0x1f));				\
+	if (asm_op == CTOP_INST_AAND_DI_R2_R2_R3)			\
+		old = ~old;						\
+									\
+	/* Explicit full memory barrier needed before/after */		\
+	smp_mb();							\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	"	mov %0, r2"						\
+	: "+r"(old)							\
+	: "r"(m), "i"(asm_op)						\
+	: "r2", "r3", "memory");					\
+									\
+	smp_mb();							\
+									\
+	return (old & nr) != 0;					\
+}
+#endif /* CONFIG_ARC_PLAT_EZNPS */
 
 /***************************************
  * Non atomic variants
@@ -196,9 +244,15 @@ static inline int __test_and_##op##_bit(unsigned long nr, volatile unsigned long
 	/* __test_and_set_bit(), __test_and_clear_bit(), __test_and_change_bit() */\
 	__TEST_N_BIT_OP(op, c_op, asm_op)
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 BIT_OPS(set, |, bset)
 BIT_OPS(clear, & ~, bclr)
 BIT_OPS(change, ^, bxor)
+#else
+BIT_OPS(set, |, CTOP_INST_AOR_DI_R2_R2_R3)
+BIT_OPS(clear, & ~, CTOP_INST_AAND_DI_R2_R2_R3)
+BIT_OPS(change, ^, CTOP_INST_AXOR_DI_R2_R2_R3)
+#endif
 
 /*
  * This routine doesn't need to be atomic.
diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h
index af7a2db..6d320d3 100644
--- a/arch/arc/include/asm/cmpxchg.h
+++ b/arch/arc/include/asm/cmpxchg.h
@@ -14,6 +14,7 @@
 #include <asm/barrier.h>
 #include <asm/smp.h>
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 #ifdef CONFIG_ARC_HAS_LLSC
 
 static inline unsigned long
@@ -66,21 +67,6 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
 
 #endif /* CONFIG_ARC_HAS_LLSC */
 
-#define cmpxchg(ptr, o, n) ((typeof(*(ptr)))__cmpxchg((ptr), \
-				(unsigned long)(o), (unsigned long)(n)))
-
-/*
- * Since not supported natively, ARC cmpxchg() uses atomic_ops_lock (UP/SMP)
- * just to gaurantee semantics.
- * atomic_cmpxchg() needs to use the same locks as it's other atomic siblings
- * which also happens to be atomic_ops_lock.
- *
- * Thus despite semantically being different, implementation of atomic_cmpxchg()
- * is same as cmpxchg().
- */
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-
-
 /*
  * xchg (reg with memory) based on "Native atomic" EX insn
  */
@@ -143,6 +129,63 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
 
 #endif
 
+#else /* CONFIG_ARC_PLAT_EZNPS */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
+{
+	/*
+	 * Explicit full memory barrier needed before/after
+	 */
+	smp_mb();
+
+	write_aux_reg(CTOP_AUX_GPA1, expected);
+
+	__asm__ __volatile__(
+	"	mov r2, %0\n"
+	"	mov r3, %1\n"
+	"	.word %2\n"
+	"	mov %0, r2"
+	: "+r"(new)
+	: "r"(ptr), "i"(CTOP_INST_EXC_DI_R2_R2_R3)
+	: "r2", "r3", "memory");
+
+	smp_mb();
+
+	return new;
+}
+
+static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
+				   int size)
+{
+	extern unsigned long __xchg_bad_pointer(void);
+
+	switch (size) {
+	case 4:
+		/*
+		 * Explicit full memory barrier needed before/after
+		 */
+		smp_mb();
+
+		__asm__ __volatile__(
+		"	mov r2, %0\n"
+		"	mov r3, %1\n"
+		"	.word %2\n"
+		"	mov %0, r2\n"
+		: "+r"(val)
+		: "r"(ptr), "i"(CTOP_INST_XEX_DI_R2_R2_R3)
+		: "r2", "r3", "memory");
+
+		smp_mb();
+
+		return val;
+	}
+	return __xchg_bad_pointer();
+}
+
+#define xchg(ptr, with) ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), \
+						 sizeof(*(ptr))))
+#endif /* CONFIG_ARC_PLAT_EZNPS */
+
 /*
  * "atomic" variant of xchg()
  * REQ: It needs to follow the same serialization rules as other atomic_xxx()
@@ -158,4 +201,18 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
  */
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 
+#define cmpxchg(ptr, o, n) ((typeof(*(ptr)))__cmpxchg((ptr), \
+				(unsigned long)(o), (unsigned long)(n)))
+
+/*
+ * Since not supported natively, ARC cmpxchg() uses atomic_ops_lock (UP/SMP)
+ * just to gaurantee semantics.
+ * atomic_cmpxchg() needs to use the same locks as it's other atomic siblings
+ * which also happens to be atomic_ops_lock.
+ *
+ * Thus despite semantically being different, implementation of atomic_cmpxchg()
+ * is same as cmpxchg().
+ */
+#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+
 #endif
-- 
1.7.1

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

* [PATCH v5 16/20] ARC: [plat-eznps] Use dedicated SMP barriers
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus,
	Peter Zijlstra

From: Noam Camus <noamc@ezchip.com>

NPS device got 256 cores and each got 16 HW threads (SMT).
We use EZchip dedicated ISA to trigger HW scheduler of the
core that current HW thread belongs to.
This scheduling makes sure that data beyond barrier is available
to all HW threads in core and by that to all in device (4K).

Signed-off-by: Noam Camus <noamc@ezchip.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
 arch/arc/include/asm/barrier.h |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h
index a720998..a559732 100644
--- a/arch/arc/include/asm/barrier.h
+++ b/arch/arc/include/asm/barrier.h
@@ -34,6 +34,7 @@
 
 #ifdef CONFIG_ISA_ARCOMPACT
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 /*
  * ARCompact based cores (ARC700) only have SYNC instruction which is super
  * heavy weight as it flushes the pipeline as well.
@@ -41,6 +42,13 @@
  */
 
 #define mb()	asm volatile("sync\n" : : : "memory")
+#else /* CONFIG_ARC_PLAT_EZNPS */
+
+#include <plat/ctop.h>
+#define mb()	asm volatile (".word %0" : : "i"(CTOP_INST_SCHD_RW) : "memory")
+#define rmb()	asm volatile (".word %0" : : "i"(CTOP_INST_SCHD_RD) : "memory")
+#endif /* CONFIG_ARC_PLAT_EZNPS */
+
 #endif
 
 #include <asm-generic/barrier.h>
-- 
1.7.1


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

* [PATCH v5 16/20] ARC: [plat-eznps] Use dedicated SMP barriers
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

NPS device got 256 cores and each got 16 HW threads (SMT).
We use EZchip dedicated ISA to trigger HW scheduler of the
core that current HW thread belongs to.
This scheduling makes sure that data beyond barrier is available
to all HW threads in core and by that to all in device (4K).

Signed-off-by: Noam Camus <noamc at ezchip.com>
Cc: Peter Zijlstra <peterz at infradead.org>
---
 arch/arc/include/asm/barrier.h |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h
index a720998..a559732 100644
--- a/arch/arc/include/asm/barrier.h
+++ b/arch/arc/include/asm/barrier.h
@@ -34,6 +34,7 @@
 
 #ifdef CONFIG_ISA_ARCOMPACT
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 /*
  * ARCompact based cores (ARC700) only have SYNC instruction which is super
  * heavy weight as it flushes the pipeline as well.
@@ -41,6 +42,13 @@
  */
 
 #define mb()	asm volatile("sync\n" : : : "memory")
+#else /* CONFIG_ARC_PLAT_EZNPS */
+
+#include <plat/ctop.h>
+#define mb()	asm volatile (".word %0" : : "i"(CTOP_INST_SCHD_RW) : "memory")
+#define rmb()	asm volatile (".word %0" : : "i"(CTOP_INST_SCHD_RD) : "memory")
+#endif /* CONFIG_ARC_PLAT_EZNPS */
+
 #endif
 
 #include <asm-generic/barrier.h>
-- 
1.7.1

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

* [PATCH v5 17/20] ARC: [plat-eznps] Use dedicated identity auxiliary register.
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

With generic "identity" num of CPUs is limited to 256 (8 bit).
We use our alternative AUX register GLOBAL_ID (12 bit).
Now we can support up to 4096 CPUs.

Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 arch/arc/include/asm/entry-compact.h |    8 ++++++++
 arch/arc/kernel/ctx_sw.c             |   13 +++++++++++++
 2 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h
index 1aff3be..bf9a6a1 100644
--- a/arch/arc/include/asm/entry-compact.h
+++ b/arch/arc/include/asm/entry-compact.h
@@ -35,6 +35,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/irqflags-compact.h>
 #include <asm/thread_info.h>	/* For THREAD_SIZE */
+#include <plat/ctop.h>
 
 /*--------------------------------------------------------------
  * Switch to Kernel Mode stack if SP points to User Mode stack
@@ -298,9 +299,16 @@
 
 /* Get CPU-ID of this core */
 .macro  GET_CPU_ID  reg
+#ifdef CONFIG_ARC_PLAT_EZNPS
+	lr  \reg, [CTOP_AUX_LOGIC_GLOBAL_ID]
+#ifndef CONFIG_EZNPS_MTM_EXT
+	lsr \reg, \reg, 4
+#endif
+#else
 	lr  \reg, [identity]
 	lsr \reg, \reg, 8
 	bmsk \reg, \reg, 7
+#endif
 .endm
 
 #endif  /* __ASM_ARC_ENTRY_COMPACT_H */
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c
index 5d446df..6f4cb0d 100644
--- a/arch/arc/kernel/ctx_sw.c
+++ b/arch/arc/kernel/ctx_sw.c
@@ -16,6 +16,9 @@
 
 #include <asm/asm-offsets.h>
 #include <linux/sched.h>
+#ifdef CONFIG_ARC_PLAT_EZNPS
+#include <plat/ctop.h>
+#endif
 
 #define KSP_WORD_OFF 	((TASK_THREAD + THREAD_KSP) / 4)
 
@@ -67,9 +70,16 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
 #ifndef CONFIG_SMP
 		"st  %2, [@_current_task]	\n\t"
 #else
+#ifdef CONFIG_ARC_PLAT_EZNPS
+		"lr   r24, [%4]		\n\t"
+#ifndef CONFIG_EZNPS_MTM_EXT
+		"lsr  r24, r24, 4		\n\t"
+#endif
+#else
 		"lr   r24, [identity]		\n\t"
 		"lsr  r24, r24, 8		\n\t"
 		"bmsk r24, r24, 7		\n\t"
+#endif
 		"add2 r24, @_current_task, r24	\n\t"
 		"st   %2,  [r24]		\n\t"
 #endif
@@ -107,6 +117,9 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
 
 		: "=r"(tmp)
 		: "n"(KSP_WORD_OFF), "r"(next), "r"(prev)
+#ifdef CONFIG_ARC_PLAT_EZNPS
+		, "i"(CTOP_AUX_LOGIC_GLOBAL_ID)
+#endif
 		: "blink"
 	);
 
-- 
1.7.1


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

* [PATCH v5 17/20] ARC: [plat-eznps] Use dedicated identity auxiliary register.
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

With generic "identity" num of CPUs is limited to 256 (8 bit).
We use our alternative AUX register GLOBAL_ID (12 bit).
Now we can support up to 4096 CPUs.

Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 arch/arc/include/asm/entry-compact.h |    8 ++++++++
 arch/arc/kernel/ctx_sw.c             |   13 +++++++++++++
 2 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h
index 1aff3be..bf9a6a1 100644
--- a/arch/arc/include/asm/entry-compact.h
+++ b/arch/arc/include/asm/entry-compact.h
@@ -35,6 +35,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/irqflags-compact.h>
 #include <asm/thread_info.h>	/* For THREAD_SIZE */
+#include <plat/ctop.h>
 
 /*--------------------------------------------------------------
  * Switch to Kernel Mode stack if SP points to User Mode stack
@@ -298,9 +299,16 @@
 
 /* Get CPU-ID of this core */
 .macro  GET_CPU_ID  reg
+#ifdef CONFIG_ARC_PLAT_EZNPS
+	lr  \reg, [CTOP_AUX_LOGIC_GLOBAL_ID]
+#ifndef CONFIG_EZNPS_MTM_EXT
+	lsr \reg, \reg, 4
+#endif
+#else
 	lr  \reg, [identity]
 	lsr \reg, \reg, 8
 	bmsk \reg, \reg, 7
+#endif
 .endm
 
 #endif  /* __ASM_ARC_ENTRY_COMPACT_H */
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c
index 5d446df..6f4cb0d 100644
--- a/arch/arc/kernel/ctx_sw.c
+++ b/arch/arc/kernel/ctx_sw.c
@@ -16,6 +16,9 @@
 
 #include <asm/asm-offsets.h>
 #include <linux/sched.h>
+#ifdef CONFIG_ARC_PLAT_EZNPS
+#include <plat/ctop.h>
+#endif
 
 #define KSP_WORD_OFF 	((TASK_THREAD + THREAD_KSP) / 4)
 
@@ -67,9 +70,16 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
 #ifndef CONFIG_SMP
 		"st  %2, [@_current_task]	\n\t"
 #else
+#ifdef CONFIG_ARC_PLAT_EZNPS
+		"lr   r24, [%4]		\n\t"
+#ifndef CONFIG_EZNPS_MTM_EXT
+		"lsr  r24, r24, 4		\n\t"
+#endif
+#else
 		"lr   r24, [identity]		\n\t"
 		"lsr  r24, r24, 8		\n\t"
 		"bmsk r24, r24, 7		\n\t"
+#endif
 		"add2 r24, @_current_task, r24	\n\t"
 		"st   %2,  [r24]		\n\t"
 #endif
@@ -107,6 +117,9 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
 
 		: "=r"(tmp)
 		: "n"(KSP_WORD_OFF), "r"(next), "r"(prev)
+#ifdef CONFIG_ARC_PLAT_EZNPS
+		, "i"(CTOP_AUX_LOGIC_GLOBAL_ID)
+#endif
 		: "blink"
 	);
 
-- 
1.7.1

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

* [PATCH v5 18/20] ARC: [plat-eznps] Use dedicated cpu_relax()
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Tal Zilcer,
	Noam Camus, Peter Zijlstra

From: Tal Zilcer <talz@ezchip.com>

Since the CTOP is SMT hardware multi-threaded, we need to hint
the HW that now will be a very good time to do a hardware
thread context switching. This is done by issuing the schd.rw
instruction (binary coded here so as to not require specific
revision of GCC to build the kernel).
sched.rw means that Thread becomes eligible for execution by
the threads scheduler after all pending read/write
transactions were completed.

Implementing cpu_relax_lowlatency() with barrier()
Since with current semantics of cpu_relax() it may take a
while till yielded CPU will get back.

Signed-off-by: Noam Camus <noamc@ezchip.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/processor.h |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 41142ab..974b878 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -57,9 +57,18 @@ struct task_struct;
  * A lot of busy-wait loops in SMP are based off of non-volatile data otherwise
  * get optimised away by gcc
  */
+#ifndef CONFIG_EZNPS_MTM_EXT
 #define cpu_relax()	__asm__ __volatile__ ("" : : : "memory")
+#else
+#define cpu_relax()     \
+	__asm__ __volatile__ (".word %0" : : "i"(CTOP_INST_SCHD_RW) : "memory")
+#endif
 
+#ifndef CONFIG_EZNPS_MTM_EXT
 #define cpu_relax_lowlatency() cpu_relax()
+#else
+#define cpu_relax_lowlatency() barrier()
+#endif
 
 #define copy_segments(tsk, mm)      do { } while (0)
 #define release_segments(mm)        do { } while (0)
-- 
1.7.1


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

* [PATCH v5 18/20] ARC: [plat-eznps] Use dedicated cpu_relax()
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Tal Zilcer <talz@ezchip.com>

Since the CTOP is SMT hardware multi-threaded, we need to hint
the HW that now will be a very good time to do a hardware
thread context switching. This is done by issuing the schd.rw
instruction (binary coded here so as to not require specific
revision of GCC to build the kernel).
sched.rw means that Thread becomes eligible for execution by
the threads scheduler after all pending read/write
transactions were completed.

Implementing cpu_relax_lowlatency() with barrier()
Since with current semantics of cpu_relax() it may take a
while till yielded CPU will get back.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Acked-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/include/asm/processor.h |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index 41142ab..974b878 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -57,9 +57,18 @@ struct task_struct;
  * A lot of busy-wait loops in SMP are based off of non-volatile data otherwise
  * get optimised away by gcc
  */
+#ifndef CONFIG_EZNPS_MTM_EXT
 #define cpu_relax()	__asm__ __volatile__ ("" : : : "memory")
+#else
+#define cpu_relax()     \
+	__asm__ __volatile__ (".word %0" : : "i"(CTOP_INST_SCHD_RW) : "memory")
+#endif
 
+#ifndef CONFIG_EZNPS_MTM_EXT
 #define cpu_relax_lowlatency() cpu_relax()
+#else
+#define cpu_relax_lowlatency() barrier()
+#endif
 
 #define copy_segments(tsk, mm)      do { } while (0)
 #define release_segments(mm)        do { } while (0)
-- 
1.7.1

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

* [PATCH v5 19/20] ARC: [plat-eznps] Use dedicated COMMAND_LINE_SIZE
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

The default 256 bytes sometimes is just not enough.
We usually provide earlycon=... and console=... and ip=...
All this and more may need more room.

Signed-off-by: Noam Camus <noamc@ezchip.com>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/setup.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
index 3078466..48b37c6 100644
--- a/arch/arc/include/asm/setup.h
+++ b/arch/arc/include/asm/setup.h
@@ -12,7 +12,11 @@
 #include <linux/types.h>
 #include <uapi/asm/setup.h>
 
+#ifdef CONFIG_ARC_PLAT_EZNPS
+#define COMMAND_LINE_SIZE 2048
+#else
 #define COMMAND_LINE_SIZE 256
+#endif
 
 /*
  * Data structure to map a ID to string
-- 
1.7.1


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

* [PATCH v5 19/20] ARC: [plat-eznps] Use dedicated COMMAND_LINE_SIZE
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

The default 256 bytes sometimes is just not enough.
We usually provide earlycon=... and console=... and ip=...
All this and more may need more room.

Signed-off-by: Noam Camus <noamc at ezchip.com>
Acked-by: Vineet Gupta <vgupta at synopsys.com>
---
 arch/arc/include/asm/setup.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
index 3078466..48b37c6 100644
--- a/arch/arc/include/asm/setup.h
+++ b/arch/arc/include/asm/setup.h
@@ -12,7 +12,11 @@
 #include <linux/types.h>
 #include <uapi/asm/setup.h>
 
+#ifdef CONFIG_ARC_PLAT_EZNPS
+#define COMMAND_LINE_SIZE 2048
+#else
 #define COMMAND_LINE_SIZE 256
+#endif
 
 /*
  * Data structure to map a ID to string
-- 
1.7.1

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

* [PATCH v5 20/20] ARC: Add eznps platform to Kconfig and Makefile
  2015-12-27 13:23 ` Noam Camus
@ 2015-12-27 13:23   ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier, Noam Camus

From: Noam Camus <noamc@ezchip.com>

This commit should be left last since only now eznps platform
is in state which one can actually use.
Signed-off-by: Noam Camus <noamc@ezchip.com>
---
 arch/arc/Kconfig  |    1 +
 arch/arc/Makefile |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 079946e..9d828a3 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -92,6 +92,7 @@ source "arch/arc/plat-sim/Kconfig"
 source "arch/arc/plat-tb10x/Kconfig"
 source "arch/arc/plat-axs10x/Kconfig"
 #New platform adds here
+source "arch/arc/plat-eznps/Kconfig"
 
 endmenu
 
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index aeb1902..6212fea 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -99,6 +99,11 @@ core-y		+= arch/arc/boot/dts/
 core-$(CONFIG_ARC_PLAT_SIM)	+= arch/arc/plat-sim/
 core-$(CONFIG_ARC_PLAT_TB10X)	+= arch/arc/plat-tb10x/
 core-$(CONFIG_ARC_PLAT_AXS10X)	+= arch/arc/plat-axs10x/
+core-$(CONFIG_ARC_PLAT_EZNPS)	+= arch/arc/plat-eznps/
+
+ifdef CONFIG_ARC_PLAT_EZNPS
+KBUILD_CPPFLAGS += -I$(srctree)/arch/arc/plat-eznps/include
+endif
 
 drivers-$(CONFIG_OPROFILE)	+= arch/arc/oprofile/
 
-- 
1.7.1


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

* [PATCH v5 20/20] ARC: Add eznps platform to Kconfig and Makefile
@ 2015-12-27 13:23   ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 13:23 UTC (permalink / raw)
  To: linux-snps-arc

From: Noam Camus <noamc@ezchip.com>

This commit should be left last since only now eznps platform
is in state which one can actually use.
Signed-off-by: Noam Camus <noamc at ezchip.com>
---
 arch/arc/Kconfig  |    1 +
 arch/arc/Makefile |    5 +++++
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 079946e..9d828a3 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -92,6 +92,7 @@ source "arch/arc/plat-sim/Kconfig"
 source "arch/arc/plat-tb10x/Kconfig"
 source "arch/arc/plat-axs10x/Kconfig"
 #New platform adds here
+source "arch/arc/plat-eznps/Kconfig"
 
 endmenu
 
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index aeb1902..6212fea 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -99,6 +99,11 @@ core-y		+= arch/arc/boot/dts/
 core-$(CONFIG_ARC_PLAT_SIM)	+= arch/arc/plat-sim/
 core-$(CONFIG_ARC_PLAT_TB10X)	+= arch/arc/plat-tb10x/
 core-$(CONFIG_ARC_PLAT_AXS10X)	+= arch/arc/plat-axs10x/
+core-$(CONFIG_ARC_PLAT_EZNPS)	+= arch/arc/plat-eznps/
+
+ifdef CONFIG_ARC_PLAT_EZNPS
+KBUILD_CPPFLAGS += -I$(srctree)/arch/arc/plat-eznps/include
+endif
 
 drivers-$(CONFIG_OPROFILE)	+= arch/arc/oprofile/
 
-- 
1.7.1

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

* Re: [PATCH v5 04/20] clocksource: Add NPS400 timers driver
  2015-12-27 13:23   ` Noam Camus
@ 2015-12-27 14:55     ` kbuild test robot
  -1 siblings, 0 replies; 72+ messages in thread
From: kbuild test robot @ 2015-12-27 14:55 UTC (permalink / raw)
  To: Noam Camus
  Cc: kbuild-all, linux-snps-arc, linux-kernel, cmetcalf,
	daniel.lezcano, marc.zyngier, Noam Camus, Rob Herring,
	Thomas Gleixner, John Stultz

[-- Attachment #1: Type: text/plain, Size: 6378 bytes --]

[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
Hi Noam,

[auto build test ERROR on arc/for-next]
[also build test ERROR on v4.4-rc6 next-20151223]

url:    https://github.com/0day-ci/linux/commits/Noam-Camus/Adding-plat-eznps-to-ARC/20151227-220433
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc for-next
config: i386-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/clocksource/timer-nps.c: In function 'nps_timer_event_setup':
>> drivers/clocksource/timer-nps.c:60:2: error: implicit declaration of function 'write_aux_reg' [-Werror=implicit-function-declaration]
     write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
     ^
   drivers/clocksource/timer-nps.c: In function 'nps_timer_cpu_notify':
>> drivers/clocksource/timer-nps.c:106:3: error: implicit declaration of function 'enable_percpu_irq' [-Werror=implicit-function-declaration]
      enable_percpu_irq(nps_timer_irq, 0);
      ^
>> drivers/clocksource/timer-nps.c:111:3: error: implicit declaration of function 'disable_percpu_irq' [-Werror=implicit-function-declaration]
      disable_percpu_irq(nps_timer_irq);
      ^
   drivers/clocksource/timer-nps.c: In function 'nps_setup_clocksource':
   drivers/clocksource/timer-nps.c:148:6: error: 'NPS_MSU_BLKID' undeclared (first use in this function)
         NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
         ^
   drivers/clocksource/timer-nps.c:148:6: note: each undeclared identifier is reported only once for each function it appears in
   drivers/clocksource/timer-nps.c: In function 'nps_setup_clockevents':
>> drivers/clocksource/timer-nps.c:176:8: error: implicit declaration of function 'request_percpu_irq' [-Werror=implicit-function-declaration]
     ret = request_percpu_irq(irq, nps_timer_irq_handler,
           ^
   cc1: some warnings being treated as errors

vim +/write_aux_reg +60 drivers/clocksource/timer-nps.c

    54		.mask   = CLOCKSOURCE_MASK(32),
    55		.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
    56	};
    57	
    58	static void nps_timer_event_setup(unsigned int cycles)
    59	{
  > 60		write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
    61		write_aux_reg(ARC_REG_TIMER0_CNT, 0);   /* start from 0 */
    62	
    63		write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
    64	}
    65	
    66	static int nps_clkevent_set_next_event(unsigned long delta,
    67					       struct clock_event_device *dev)
    68	{
    69		nps_timer_event_setup(delta);
    70		return 0;
    71	}
    72	
    73	static int nps_clkevent_set_periodic(struct clock_event_device *dev)
    74	{
    75		/*
    76		 * At X Hz, 1 sec = 1000ms -> X cycles;
    77		 *                    10ms -> X / 100 cycles
    78		 */
    79		nps_timer_event_setup(nps_timer_rate / HZ);
    80		return 0;
    81	}
    82	
    83	static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
    84		.name			= "nps_sys_timer",
    85		.features               = CLOCK_EVT_FEAT_ONESHOT |
    86					  CLOCK_EVT_FEAT_PERIODIC,
    87		.rating                 = 300,
    88		.set_next_event         = nps_clkevent_set_next_event,
    89		.set_state_periodic     = nps_clkevent_set_periodic,
    90	};
    91	
    92	static int nps_timer_cpu_notify(struct notifier_block *self,
    93					unsigned long action, void *hcpu)
    94	{
    95		struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
    96	
    97		evt->irq = nps_timer_irq;
    98		evt->cpumask = cpumask_of(smp_processor_id());
    99	
   100		/*
   101		 * Grab cpu pointer in each case to avoid spurious
   102		 * preemptible warnings
   103		 */
   104		switch (action & ~CPU_TASKS_FROZEN) {
   105		case CPU_STARTING:
 > 106			enable_percpu_irq(nps_timer_irq, 0);
   107			clockevents_config_and_register(evt, nps_timer_rate,
   108							0, ULONG_MAX);
   109			break;
   110		case CPU_DYING:
 > 111			disable_percpu_irq(nps_timer_irq);
   112			break;
   113		}
   114	
   115		return NOTIFY_OK;
   116	}
   117	
   118	static struct notifier_block nps_timer_cpu_nb = {
   119		.notifier_call = nps_timer_cpu_notify,
   120	};
   121	
   122	static irqreturn_t nps_timer_irq_handler(int irq, void *dev_id)
   123	{
   124		struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
   125		int irq_reenable = clockevent_state_periodic(evt);
   126	
   127		/*
   128		 * Any write to CTRL reg ACks the interrupt, we rewrite the
   129		 * Count when [N]ot [H]alted bit.
   130		 * And re-arm it if perioid by [I]nterrupt [E]nable bit
   131		 */
   132		write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
   133	
   134		evt->event_handler(evt);
   135	
   136		return IRQ_HANDLED;
   137	}
   138	
   139	static void __init nps_setup_clocksource(struct device_node *node,
   140						 struct clk *clk, int irq)
   141	{
   142		struct clocksource *clksrc = &nps_counter;
   143		int ret, cluster;
   144	
   145		for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
   146			nps_msu_reg_low_addr[cluster] =
   147				nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
   148					 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
   149	
   150		ret = clk_prepare_enable(clk);
   151		if (ret)
   152			pr_err("Couldn't enable parent clock\n");
   153	
   154		nps_timer_rate = clk_get_rate(clk);
   155	
   156		ret = clocksource_register_hz(clksrc, nps_timer_rate);
   157		if (ret)
   158			pr_err("Couldn't register clock source.\n");
   159	}
   160	
   161	static void __init nps_setup_clockevents(struct device_node *node,
   162						 struct clk *clk, int irq)
   163	{
   164		struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
   165		int ret;
   166	
   167		register_cpu_notifier(&nps_timer_cpu_nb);
   168	
   169		evt->irq = irq;
   170		evt->cpumask = cpumask_of(smp_processor_id());
   171	
   172		clockevents_config_and_register(evt, nps_timer_rate, 0, ULONG_MAX);
   173	
   174		enable_percpu_irq(irq, 0);
   175	
 > 176		ret = request_percpu_irq(irq, nps_timer_irq_handler,
   177					 "timer", evt);
   178		if (ret)
   179			pr_err("Unable to register interrupt\n");

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 52554 bytes --]

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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
@ 2015-12-27 14:55     ` kbuild test robot
  0 siblings, 0 replies; 72+ messages in thread
From: kbuild test robot @ 2015-12-27 14:55 UTC (permalink / raw)
  To: linux-snps-arc

[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
Hi Noam,

[auto build test ERROR on arc/for-next]
[also build test ERROR on v4.4-rc6 next-20151223]

url:    https://github.com/0day-ci/linux/commits/Noam-Camus/Adding-plat-eznps-to-ARC/20151227-220433
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc for-next
config: i386-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/clocksource/timer-nps.c: In function 'nps_timer_event_setup':
>> drivers/clocksource/timer-nps.c:60:2: error: implicit declaration of function 'write_aux_reg' [-Werror=implicit-function-declaration]
     write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
     ^
   drivers/clocksource/timer-nps.c: In function 'nps_timer_cpu_notify':
>> drivers/clocksource/timer-nps.c:106:3: error: implicit declaration of function 'enable_percpu_irq' [-Werror=implicit-function-declaration]
      enable_percpu_irq(nps_timer_irq, 0);
      ^
>> drivers/clocksource/timer-nps.c:111:3: error: implicit declaration of function 'disable_percpu_irq' [-Werror=implicit-function-declaration]
      disable_percpu_irq(nps_timer_irq);
      ^
   drivers/clocksource/timer-nps.c: In function 'nps_setup_clocksource':
   drivers/clocksource/timer-nps.c:148:6: error: 'NPS_MSU_BLKID' undeclared (first use in this function)
         NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
         ^
   drivers/clocksource/timer-nps.c:148:6: note: each undeclared identifier is reported only once for each function it appears in
   drivers/clocksource/timer-nps.c: In function 'nps_setup_clockevents':
>> drivers/clocksource/timer-nps.c:176:8: error: implicit declaration of function 'request_percpu_irq' [-Werror=implicit-function-declaration]
     ret = request_percpu_irq(irq, nps_timer_irq_handler,
           ^
   cc1: some warnings being treated as errors

vim +/write_aux_reg +60 drivers/clocksource/timer-nps.c

    54		.mask   = CLOCKSOURCE_MASK(32),
    55		.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
    56	};
    57	
    58	static void nps_timer_event_setup(unsigned int cycles)
    59	{
  > 60		write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
    61		write_aux_reg(ARC_REG_TIMER0_CNT, 0);   /* start from 0 */
    62	
    63		write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
    64	}
    65	
    66	static int nps_clkevent_set_next_event(unsigned long delta,
    67					       struct clock_event_device *dev)
    68	{
    69		nps_timer_event_setup(delta);
    70		return 0;
    71	}
    72	
    73	static int nps_clkevent_set_periodic(struct clock_event_device *dev)
    74	{
    75		/*
    76		 * At X Hz, 1 sec = 1000ms -> X cycles;
    77		 *                    10ms -> X / 100 cycles
    78		 */
    79		nps_timer_event_setup(nps_timer_rate / HZ);
    80		return 0;
    81	}
    82	
    83	static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
    84		.name			= "nps_sys_timer",
    85		.features               = CLOCK_EVT_FEAT_ONESHOT |
    86					  CLOCK_EVT_FEAT_PERIODIC,
    87		.rating                 = 300,
    88		.set_next_event         = nps_clkevent_set_next_event,
    89		.set_state_periodic     = nps_clkevent_set_periodic,
    90	};
    91	
    92	static int nps_timer_cpu_notify(struct notifier_block *self,
    93					unsigned long action, void *hcpu)
    94	{
    95		struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
    96	
    97		evt->irq = nps_timer_irq;
    98		evt->cpumask = cpumask_of(smp_processor_id());
    99	
   100		/*
   101		 * Grab cpu pointer in each case to avoid spurious
   102		 * preemptible warnings
   103		 */
   104		switch (action & ~CPU_TASKS_FROZEN) {
   105		case CPU_STARTING:
 > 106			enable_percpu_irq(nps_timer_irq, 0);
   107			clockevents_config_and_register(evt, nps_timer_rate,
   108							0, ULONG_MAX);
   109			break;
   110		case CPU_DYING:
 > 111			disable_percpu_irq(nps_timer_irq);
   112			break;
   113		}
   114	
   115		return NOTIFY_OK;
   116	}
   117	
   118	static struct notifier_block nps_timer_cpu_nb = {
   119		.notifier_call = nps_timer_cpu_notify,
   120	};
   121	
   122	static irqreturn_t nps_timer_irq_handler(int irq, void *dev_id)
   123	{
   124		struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
   125		int irq_reenable = clockevent_state_periodic(evt);
   126	
   127		/*
   128		 * Any write to CTRL reg ACks the interrupt, we rewrite the
   129		 * Count when [N]ot [H]alted bit.
   130		 * And re-arm it if perioid by [I]nterrupt [E]nable bit
   131		 */
   132		write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
   133	
   134		evt->event_handler(evt);
   135	
   136		return IRQ_HANDLED;
   137	}
   138	
   139	static void __init nps_setup_clocksource(struct device_node *node,
   140						 struct clk *clk, int irq)
   141	{
   142		struct clocksource *clksrc = &nps_counter;
   143		int ret, cluster;
   144	
   145		for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
   146			nps_msu_reg_low_addr[cluster] =
   147				nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
   148					 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
   149	
   150		ret = clk_prepare_enable(clk);
   151		if (ret)
   152			pr_err("Couldn't enable parent clock\n");
   153	
   154		nps_timer_rate = clk_get_rate(clk);
   155	
   156		ret = clocksource_register_hz(clksrc, nps_timer_rate);
   157		if (ret)
   158			pr_err("Couldn't register clock source.\n");
   159	}
   160	
   161	static void __init nps_setup_clockevents(struct device_node *node,
   162						 struct clk *clk, int irq)
   163	{
   164		struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
   165		int ret;
   166	
   167		register_cpu_notifier(&nps_timer_cpu_nb);
   168	
   169		evt->irq = irq;
   170		evt->cpumask = cpumask_of(smp_processor_id());
   171	
   172		clockevents_config_and_register(evt, nps_timer_rate, 0, ULONG_MAX);
   173	
   174		enable_percpu_irq(irq, 0);
   175	
 > 176		ret = request_percpu_irq(irq, nps_timer_irq_handler,
   177					 "timer", evt);
   178		if (ret)
   179			pr_err("Unable to register interrupt\n");

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 52554 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-snps-arc/attachments/20151227/e70423e8/attachment-0001.obj>

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

* Re: [PATCH v5 04/20] clocksource: Add NPS400 timers driver
  2015-12-27 14:55     ` kbuild test robot
@ 2015-12-27 21:41       ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 21:41 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, linux-snps-arc, linux-kernel, Chris Metcalf,
	daniel.lezcano, marc.zyngier, Rob Herring, Thomas Gleixner,
	John Stultz

>From: kbuild test robot <lkp@intel.com>
>Sent: Sunday, December 27, 2015 4:55 PM

>[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
>Hi Noam,

>[auto build test ERROR on arc/for-next]
>[also build test ERROR on v4.4-rc6 next-20151223]

>url:    https://github.com/0day-ci/linux/commits/Noam-Camus/Adding-plat-eznps-to-ARC/20151227-220433
>base:   https://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc for-next
>config: i386-allmodconfig (attached as .config)
>reproduce:
>       # save the attached .config to linux build tree
>      make ARCH=i386

This is meant for ARC only (not i386), I will add to the Kconfig file a dependency on my platform. 

-Noam

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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
@ 2015-12-27 21:41       ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-27 21:41 UTC (permalink / raw)
  To: linux-snps-arc

>From: kbuild test robot <lkp at intel.com>
>Sent: Sunday, December 27, 2015 4:55 PM

>[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
>Hi Noam,

>[auto build test ERROR on arc/for-next]
>[also build test ERROR on v4.4-rc6 next-20151223]

>url:    https://github.com/0day-ci/linux/commits/Noam-Camus/Adding-plat-eznps-to-ARC/20151227-220433
>base:   https://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc for-next
>config: i386-allmodconfig (attached as .config)
>reproduce:
>       # save the attached .config to linux build tree
>      make ARCH=i386

This is meant for ARC only (not i386), I will add to the Kconfig file a dependency on my platform. 

-Noam

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

* Re: [PATCH v5 04/20] clocksource: Add NPS400 timers driver
  2015-12-27 21:41       ` Noam Camus
@ 2015-12-28  9:00         ` Daniel Lezcano
  -1 siblings, 0 replies; 72+ messages in thread
From: Daniel Lezcano @ 2015-12-28  9:00 UTC (permalink / raw)
  To: Noam Camus, kbuild test robot
  Cc: kbuild-all, linux-snps-arc, linux-kernel, Chris Metcalf,
	marc.zyngier, Rob Herring, Thomas Gleixner, John Stultz

On 12/27/2015 10:41 PM, Noam Camus wrote:
>> From: kbuild test robot <lkp@intel.com>
>> Sent: Sunday, December 27, 2015 4:55 PM
>
>> [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
>> Hi Noam,
>
>> [auto build test ERROR on arc/for-next]
>> [also build test ERROR on v4.4-rc6 next-20151223]
>
>> url:    https://github.com/0day-ci/linux/commits/Noam-Camus/Adding-plat-eznps-to-ARC/20151227-220433
>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc for-next
>> config: i386-allmodconfig (attached as .config)
>> reproduce:
>>        # save the attached .config to linux build tree
>>       make ARCH=i386
>
> This is meant for ARC only (not i386), I will add to the Kconfig file a dependency on my platform.

Hi Noam,

for compilation test coverage it would be nice to not restrict the to 
ARC only but change the write_aux_reg to a common name across the 
different arch if possible.

   -- Daniel


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

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


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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
@ 2015-12-28  9:00         ` Daniel Lezcano
  0 siblings, 0 replies; 72+ messages in thread
From: Daniel Lezcano @ 2015-12-28  9:00 UTC (permalink / raw)
  To: linux-snps-arc

On 12/27/2015 10:41 PM, Noam Camus wrote:
>> From: kbuild test robot <lkp at intel.com>
>> Sent: Sunday, December 27, 2015 4:55 PM
>
>> [if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
>> Hi Noam,
>
>> [auto build test ERROR on arc/for-next]
>> [also build test ERROR on v4.4-rc6 next-20151223]
>
>> url:    https://github.com/0day-ci/linux/commits/Noam-Camus/Adding-plat-eznps-to-ARC/20151227-220433
>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc for-next
>> config: i386-allmodconfig (attached as .config)
>> reproduce:
>>        # save the attached .config to linux build tree
>>       make ARCH=i386
>
> This is meant for ARC only (not i386), I will add to the Kconfig file a dependency on my platform.

Hi Noam,

for compilation test coverage it would be nice to not restrict the to 
ARC only but change the write_aux_reg to a common name across the 
different arch if possible.

   -- Daniel


-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

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

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

* Re: [PATCH v5 04/20] clocksource: Add NPS400 timers driver
  2015-12-28  9:00         ` Daniel Lezcano
@ 2015-12-28 10:35           ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-28 10:35 UTC (permalink / raw)
  To: Daniel Lezcano, Noam Camus, kbuild test robot
  Cc: kbuild-all, linux-snps-arc, linux-kernel, Chris Metcalf,
	marc.zyngier, Rob Herring, Thomas Gleixner, John Stultz

On Monday 28 December 2015 02:30 PM, Daniel Lezcano wrote:
>>> reproduce:
>>>        # save the attached .config to linux build tree
>>>       make ARCH=i386
>>
>> This is meant for ARC only (not i386), I will add to the Kconfig file a
>> dependency on my platform.
> 
> Hi Noam,
> 
> for compilation test coverage it would be nice to not restrict the to ARC only but
> change the write_aux_reg to a common name across the different arch if possible.
> 
>   -- Daniel

Hi Daniel,

AUX registers is a ARC specific mechanism used to access some of the core
functionality (intc, caches, ....) which other arches likely do via MMIO. I don't
think a generic abstraction exists. And IMHO it doesn't make sense to invent one
given this may not map directly to other arches.

This was one of the key reasons arc intc/timers were not added to drivers/* in
first place.

I do agree with compilation test coverage aspect though.
Maybe we add a *hack* to include/soc/nps/common.h

#ifndef __ARC__
#define  write_aux_reg(r, v)
#define  read_aux_reg(r) 0
#endif

What say you ?

-Vineet

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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
@ 2015-12-28 10:35           ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-28 10:35 UTC (permalink / raw)
  To: linux-snps-arc

On Monday 28 December 2015 02:30 PM, Daniel Lezcano wrote:
>>> reproduce:
>>>        # save the attached .config to linux build tree
>>>       make ARCH=i386
>>
>> This is meant for ARC only (not i386), I will add to the Kconfig file a
>> dependency on my platform.
> 
> Hi Noam,
> 
> for compilation test coverage it would be nice to not restrict the to ARC only but
> change the write_aux_reg to a common name across the different arch if possible.
> 
>   -- Daniel

Hi Daniel,

AUX registers is a ARC specific mechanism used to access some of the core
functionality (intc, caches, ....) which other arches likely do via MMIO. I don't
think a generic abstraction exists. And IMHO it doesn't make sense to invent one
given this may not map directly to other arches.

This was one of the key reasons arc intc/timers were not added to drivers/* in
first place.

I do agree with compilation test coverage aspect though.
Maybe we add a *hack* to include/soc/nps/common.h

#ifndef __ARC__
#define  write_aux_reg(r, v)
#define  read_aux_reg(r) 0
#endif

What say you ?

-Vineet

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

* Re: [PATCH v5 04/20] clocksource: Add NPS400 timers driver
  2015-12-28 10:35           ` Vineet Gupta
@ 2015-12-28 10:55             ` Daniel Lezcano
  -1 siblings, 0 replies; 72+ messages in thread
From: Daniel Lezcano @ 2015-12-28 10:55 UTC (permalink / raw)
  To: Vineet Gupta, Noam Camus
  Cc: linux-snps-arc, linux-kernel, Chris Metcalf, marc.zyngier,
	Rob Herring, Thomas Gleixner, John Stultz

On 12/28/2015 11:35 AM, Vineet Gupta wrote:
> On Monday 28 December 2015 02:30 PM, Daniel Lezcano wrote:
>>>> reproduce:
>>>>         # save the attached .config to linux build tree
>>>>        make ARCH=i386
>>>
>>> This is meant for ARC only (not i386), I will add to the Kconfig file a
>>> dependency on my platform.
>>
>> Hi Noam,
>>
>> for compilation test coverage it would be nice to not restrict the to ARC only but
>> change the write_aux_reg to a common name across the different arch if possible.
>>
>>    -- Daniel
>
> Hi Daniel,
>
> AUX registers is a ARC specific mechanism used to access some of the core
> functionality (intc, caches, ....) which other arches likely do via MMIO. I don't
> think a generic abstraction exists. And IMHO it doesn't make sense to invent one
> given this may not map directly to other arches.
>
> This was one of the key reasons arc intc/timers were not added to drivers/* in
> first place.
>
> I do agree with compilation test coverage aspect though.
> Maybe we add a *hack* to include/soc/nps/common.h
>
> #ifndef __ARC__
> #define  write_aux_reg(r, v)
> #define  read_aux_reg(r) 0
> #endif
>
> What say you ?

Yes that's an alternative.

Perhaps instead of the __ARC__:

/*
  * Define dummy macros to let different architectures to
  * compile test some drivers, eg. the timer.
  */
#ifndef write_aux_reg
#define write_aux_reg(r, v)
#endif

#ifndef read_aux_reg
#define read_aux_reg(r) 0
#endif

Now that header must be included always *after* asm/arcregs.h.

Not sure this kind of implicit ordering is not prone to bug.

-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

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


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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
@ 2015-12-28 10:55             ` Daniel Lezcano
  0 siblings, 0 replies; 72+ messages in thread
From: Daniel Lezcano @ 2015-12-28 10:55 UTC (permalink / raw)
  To: linux-snps-arc

On 12/28/2015 11:35 AM, Vineet Gupta wrote:
> On Monday 28 December 2015 02:30 PM, Daniel Lezcano wrote:
>>>> reproduce:
>>>>         # save the attached .config to linux build tree
>>>>        make ARCH=i386
>>>
>>> This is meant for ARC only (not i386), I will add to the Kconfig file a
>>> dependency on my platform.
>>
>> Hi Noam,
>>
>> for compilation test coverage it would be nice to not restrict the to ARC only but
>> change the write_aux_reg to a common name across the different arch if possible.
>>
>>    -- Daniel
>
> Hi Daniel,
>
> AUX registers is a ARC specific mechanism used to access some of the core
> functionality (intc, caches, ....) which other arches likely do via MMIO. I don't
> think a generic abstraction exists. And IMHO it doesn't make sense to invent one
> given this may not map directly to other arches.
>
> This was one of the key reasons arc intc/timers were not added to drivers/* in
> first place.
>
> I do agree with compilation test coverage aspect though.
> Maybe we add a *hack* to include/soc/nps/common.h
>
> #ifndef __ARC__
> #define  write_aux_reg(r, v)
> #define  read_aux_reg(r) 0
> #endif
>
> What say you ?

Yes that's an alternative.

Perhaps instead of the __ARC__:

/*
  * Define dummy macros to let different architectures to
  * compile test some drivers, eg. the timer.
  */
#ifndef write_aux_reg
#define write_aux_reg(r, v)
#endif

#ifndef read_aux_reg
#define read_aux_reg(r) 0
#endif

Now that header must be included always *after* asm/arcregs.h.

Not sure this kind of implicit ordering is not prone to bug.

-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

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

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

* Re: [PATCH v5 04/20] clocksource: Add NPS400 timers driver
  2015-12-28 10:55             ` Daniel Lezcano
@ 2015-12-28 11:11               ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-28 11:11 UTC (permalink / raw)
  To: Daniel Lezcano, Noam Camus
  Cc: marc.zyngier, linux-kernel, Chris Metcalf, Rob Herring,
	John Stultz, Thomas Gleixner, linux-snps-arc

On Monday 28 December 2015 04:25 PM, Daniel Lezcano wrote:
> On 12/28/2015 11:35 AM, Vineet Gupta wrote:
>> On Monday 28 December 2015 02:30 PM, Daniel Lezcano wrote:
>>>>> reproduce:
>>>>>         # save the attached .config to linux build tree
>>>>>        make ARCH=i386
>>>>
>>>> This is meant for ARC only (not i386), I will add to the Kconfig file a
>>>> dependency on my platform.
>>>
>>> Hi Noam,
>>>
>>> for compilation test coverage it would be nice to not restrict the to ARC only but
>>> change the write_aux_reg to a common name across the different arch if possible.
>>>
>>>    -- Daniel
>>
>> Hi Daniel,
>>
>> AUX registers is a ARC specific mechanism used to access some of the core
>> functionality (intc, caches, ....) which other arches likely do via MMIO. I don't
>> think a generic abstraction exists. And IMHO it doesn't make sense to invent one
>> given this may not map directly to other arches.
>>
>> This was one of the key reasons arc intc/timers were not added to drivers/* in
>> first place.
>>
>> I do agree with compilation test coverage aspect though.
>> Maybe we add a *hack* to include/soc/nps/common.h
>>
>> #ifndef __ARC__
>> #define  write_aux_reg(r, v)
>> #define  read_aux_reg(r) 0
>> #endif
>>
>> What say you ?
> 
> Yes that's an alternative.
> 
> Perhaps instead of the __ARC__:
> 
> /*
>  * Define dummy macros to let different architectures to
>  * compile test some drivers, eg. the timer.
>  */
> #ifndef write_aux_reg
> #define write_aux_reg(r, v)
> #endif
> 
> #ifndef read_aux_reg
> #define read_aux_reg(r) 0
> #endif
> 
> Now that header must be included always *after* asm/arcregs.h.
> 
> Not sure this kind of implicit ordering is not prone to bug.

Indeed, this all seems too fragile. The main point here is to allow building of
this code on !ARC and that can simply be done with my original proposal, w/o
adding any other ordering rules/dependencies for ARC builds !

-Vineet



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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
@ 2015-12-28 11:11               ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-28 11:11 UTC (permalink / raw)
  To: linux-snps-arc

On Monday 28 December 2015 04:25 PM, Daniel Lezcano wrote:
> On 12/28/2015 11:35 AM, Vineet Gupta wrote:
>> On Monday 28 December 2015 02:30 PM, Daniel Lezcano wrote:
>>>>> reproduce:
>>>>>         # save the attached .config to linux build tree
>>>>>        make ARCH=i386
>>>>
>>>> This is meant for ARC only (not i386), I will add to the Kconfig file a
>>>> dependency on my platform.
>>>
>>> Hi Noam,
>>>
>>> for compilation test coverage it would be nice to not restrict the to ARC only but
>>> change the write_aux_reg to a common name across the different arch if possible.
>>>
>>>    -- Daniel
>>
>> Hi Daniel,
>>
>> AUX registers is a ARC specific mechanism used to access some of the core
>> functionality (intc, caches, ....) which other arches likely do via MMIO. I don't
>> think a generic abstraction exists. And IMHO it doesn't make sense to invent one
>> given this may not map directly to other arches.
>>
>> This was one of the key reasons arc intc/timers were not added to drivers/* in
>> first place.
>>
>> I do agree with compilation test coverage aspect though.
>> Maybe we add a *hack* to include/soc/nps/common.h
>>
>> #ifndef __ARC__
>> #define  write_aux_reg(r, v)
>> #define  read_aux_reg(r) 0
>> #endif
>>
>> What say you ?
> 
> Yes that's an alternative.
> 
> Perhaps instead of the __ARC__:
> 
> /*
>  * Define dummy macros to let different architectures to
>  * compile test some drivers, eg. the timer.
>  */
> #ifndef write_aux_reg
> #define write_aux_reg(r, v)
> #endif
> 
> #ifndef read_aux_reg
> #define read_aux_reg(r) 0
> #endif
> 
> Now that header must be included always *after* asm/arcregs.h.
> 
> Not sure this kind of implicit ordering is not prone to bug.

Indeed, this all seems too fragile. The main point here is to allow building of
this code on !ARC and that can simply be done with my original proposal, w/o
adding any other ordering rules/dependencies for ARC builds !

-Vineet

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

* Re: [PATCH v5 09/20] ARC: IRQ: use device tree to get timer device configuration
  2015-12-27 13:23   ` Noam Camus
@ 2015-12-28 11:42     ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-28 11:42 UTC (permalink / raw)
  To: Noam Camus, linux-snps-arc
  Cc: marc.zyngier, cmetcalf, daniel.lezcano, linux-kernel

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc@ezchip.com>
> 
> We've designated:
> TIMER0 for events (clockevents)
> TIMER1 for free running (clocksource)
> 
> Till now timer configuration was done on arch/arc/kernel/time.c
> with constant values.
> 
> This commit add device tree support so we can do this work
> at dedicated clocksource driver which parse the DT blob.
> 
> Such driver will get clocksource rate as well as interrupt line
> from DT and use them for setting clocksourcse and clockevents.
> 
> Note that lately called of_clk_init() is moved before we call
> clocksource_probe() since at that time device from DT
> need a "provider" (clocks) which will be available only after
> we call to of_clk_init().
> 
> Signed-off-by: Noam Camus <noamc@ezchip.com>
> Acked-by: Vineet Gupta <vgupta@synopsys.com>

For patches which change semantically, ACK should not be copied over from prev
version. I do have some reservation with this patch.

I think we should just fix ARC once and for all by removing the legacy
registration. This would be a flag day change but I think we should be fine !
No point in keeping 2 implementations !

@Noam let me take a stab at it - OK !

-Vineet




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

* [PATCH v5 09/20] ARC: IRQ: use device tree to get timer device configuration
@ 2015-12-28 11:42     ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-28 11:42 UTC (permalink / raw)
  To: linux-snps-arc

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>
> 
> We've designated:
> TIMER0 for events (clockevents)
> TIMER1 for free running (clocksource)
> 
> Till now timer configuration was done on arch/arc/kernel/time.c
> with constant values.
> 
> This commit add device tree support so we can do this work
> at dedicated clocksource driver which parse the DT blob.
> 
> Such driver will get clocksource rate as well as interrupt line
> from DT and use them for setting clocksourcse and clockevents.
> 
> Note that lately called of_clk_init() is moved before we call
> clocksource_probe() since at that time device from DT
> need a "provider" (clocks) which will be available only after
> we call to of_clk_init().
> 
> Signed-off-by: Noam Camus <noamc at ezchip.com>
> Acked-by: Vineet Gupta <vgupta at synopsys.com>

For patches which change semantically, ACK should not be copied over from prev
version. I do have some reservation with this patch.

I think we should just fix ARC once and for all by removing the legacy
registration. This would be a flag day change but I think we should be fine !
No point in keeping 2 implementations !

@Noam let me take a stab at it - OK !

-Vineet

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

* Re: [PATCH v5 05/20] irqchip: add nps Internal and external irqchips
  2015-12-27 13:23   ` Noam Camus
@ 2015-12-30 10:08     ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 10:08 UTC (permalink / raw)
  To: Noam Camus, linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier,
	Thomas Gleixner, Jason Cooper

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc@ezchip.com>

[snip..]

> +
> +static int nps400_irq_map(struct irq_domain *d, unsigned int virq,
> +			  irq_hw_number_t hw)
> +{
> +	switch (hw) {
> +	case TIMER0_IRQ:
> +		irq_set_percpu_devid(virq);
> +		irq_set_chip_and_handler(virq, &nps400_irq_chip_percpu,
> +					 handle_percpu_devid_irq);
> +	break;
> +	default:
> +		irq_set_chip_and_handler(virq, &nps400_irq_chip_fasteoi,
> +					 handle_fasteoi_irq);
> +	break;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops nps400_irq_ops = {
> +	.xlate = irq_domain_xlate_onecell,
> +	.map = nps400_irq_map,
> +};
> +
> +static struct irq_domain *nps400_root_domain;
> +
> +static void nps400_handle_irq(unsigned int hwirq, struct pt_regs *regs)
> +{
> +	handle_domain_irq(nps400_root_domain, hwirq, regs);
> +}
> +
> +static int __init nps400_of_init(struct device_node *node,
> +				 struct device_node *parent)
> +{
> +	if (parent)
> +		panic("DeviceTree incore ic not a root irq controller\n");
> +
> +	nps400_root_domain = irq_domain_add_linear(node, NR_CPU_IRQS,
> +						   &nps400_irq_ops, NULL);
> +
> +	if (!nps400_root_domain)
> +		panic("nps400 root irq domain not avail\n");
> +
> +	set_handle_irq(nps400_handle_irq);


Your series is NOT bisectable - u introduce this call later in series.
But do you need this song and dance anyways. Will handle_domain_irq() NOT work for
ARC in general for the core intc which are instantiated in legacy domain !

I'm ok with extra cost per int handling - given it is the right thing to do which
we've been missing so far !


> +
> +	return 0;
> +}
> +IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
> 


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

* [PATCH v5 05/20] irqchip: add nps Internal and external irqchips
@ 2015-12-30 10:08     ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 10:08 UTC (permalink / raw)
  To: linux-snps-arc

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>

[snip..]

> +
> +static int nps400_irq_map(struct irq_domain *d, unsigned int virq,
> +			  irq_hw_number_t hw)
> +{
> +	switch (hw) {
> +	case TIMER0_IRQ:
> +		irq_set_percpu_devid(virq);
> +		irq_set_chip_and_handler(virq, &nps400_irq_chip_percpu,
> +					 handle_percpu_devid_irq);
> +	break;
> +	default:
> +		irq_set_chip_and_handler(virq, &nps400_irq_chip_fasteoi,
> +					 handle_fasteoi_irq);
> +	break;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct irq_domain_ops nps400_irq_ops = {
> +	.xlate = irq_domain_xlate_onecell,
> +	.map = nps400_irq_map,
> +};
> +
> +static struct irq_domain *nps400_root_domain;
> +
> +static void nps400_handle_irq(unsigned int hwirq, struct pt_regs *regs)
> +{
> +	handle_domain_irq(nps400_root_domain, hwirq, regs);
> +}
> +
> +static int __init nps400_of_init(struct device_node *node,
> +				 struct device_node *parent)
> +{
> +	if (parent)
> +		panic("DeviceTree incore ic not a root irq controller\n");
> +
> +	nps400_root_domain = irq_domain_add_linear(node, NR_CPU_IRQS,
> +						   &nps400_irq_ops, NULL);
> +
> +	if (!nps400_root_domain)
> +		panic("nps400 root irq domain not avail\n");
> +
> +	set_handle_irq(nps400_handle_irq);


Your series is NOT bisectable - u introduce this call later in series.
But do you need this song and dance anyways. Will handle_domain_irq() NOT work for
ARC in general for the core intc which are instantiated in legacy domain !

I'm ok with extra cost per int handling - given it is the right thing to do which
we've been missing so far !


> +
> +	return 0;
> +}
> +IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
> 

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

* Re: [PATCH v5 10/20] ARC: IRQ: do not use hwirq directly at arch_do_IRQ()
  2015-12-27 13:23   ` Noam Camus
@ 2015-12-30 10:10     ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 10:10 UTC (permalink / raw)
  To: Noam Camus, linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc@ezchip.com>
> 
> ARC uses hwirq at arch_do_IRQ() to pass into generic_handle_irq().
> This is wrong since we need first to reverse map it into virq.
> 
> Happily, if we use handle_domain_irq() we get all we need.
> 
> Just like ARM I created a pointer to handler that should be filled
> by an interrupt controller driver from driver/irqchip/
> 
> Signed-off-by: Noam Camus <noamc@ezchip.com>
> ---
>  arch/arc/Kconfig           |    1 +
>  arch/arc/include/asm/irq.h |    5 +++++
>  arch/arc/kernel/irq.c      |   14 ++++++++++++++
>  3 files changed, 20 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> index 7be1020..079946e 100644
> --- a/arch/arc/Kconfig
> +++ b/arch/arc/Kconfig
> @@ -32,6 +32,7 @@ config ARC
>  	select HAVE_OPROFILE
>  	select HAVE_PERF_EVENTS
>  	select IRQ_DOMAIN
> +	select HANDLE_DOMAIN_IRQ if ARC_PLAT_EZNPS

On same lines as prev comment - just do this unconditionally for ARC port -
assuming this works with legacy domain as well.


>  	select MODULES_USE_ELF_RELA
>  	select NO_BOOTMEM
>  	select OF
> diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
> index c5f8f0f..64226c9 100644
> --- a/arch/arc/include/asm/irq.h
> +++ b/arch/arc/include/asm/irq.h
> @@ -36,4 +36,9 @@ void arc_request_percpu_irq(int irq, int cpu,
>                              irqreturn_t (*isr)(int irq, void *dev),
>                              const char *irq_nm, void *percpu_dev);
>  
> +#ifdef CONFIG_HANDLE_DOMAIN_IRQ
> +extern void set_handle_irq(void (*handle_irq)(unsigned int hwirq,
> +					      struct pt_regs *));
> +#endif

Not needed !

> +
>  #endif
> diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
> index ba17f85..7ae5411 100644
> --- a/arch/arc/kernel/irq.c
> +++ b/arch/arc/kernel/irq.c
> @@ -41,6 +41,7 @@ void __init init_IRQ(void)
>   * "C" Entry point for any ARC ISR, called from low level vector handler
>   * @irq is the vector number read from ICAUSE reg of on-chip intc
>   */
> +#ifndef CONFIG_HANDLE_DOMAIN_IRQ
>  void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
>  {
>  	struct pt_regs *old_regs = set_irq_regs(regs);
> @@ -50,6 +51,19 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
>  	irq_exit();
>  	set_irq_regs(old_regs);
>  }
> +#else
> +void (*handle_arch_irq)(unsigned int hwirq, struct pt_regs *) = NULL;
> +void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
> +{
> +	handle_arch_irq(irq, regs);
> +}
> +
> +void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
> +					      struct pt_regs *))
> +{
> +	handle_arch_irq = handle_irq;
> +}
> +#endif
>  
>  /*
>   * API called for requesting percpu interrupts - called by each CPU
> 


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

* [PATCH v5 10/20] ARC: IRQ: do not use hwirq directly at arch_do_IRQ()
@ 2015-12-30 10:10     ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 10:10 UTC (permalink / raw)
  To: linux-snps-arc

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>
> 
> ARC uses hwirq at arch_do_IRQ() to pass into generic_handle_irq().
> This is wrong since we need first to reverse map it into virq.
> 
> Happily, if we use handle_domain_irq() we get all we need.
> 
> Just like ARM I created a pointer to handler that should be filled
> by an interrupt controller driver from driver/irqchip/
> 
> Signed-off-by: Noam Camus <noamc at ezchip.com>
> ---
>  arch/arc/Kconfig           |    1 +
>  arch/arc/include/asm/irq.h |    5 +++++
>  arch/arc/kernel/irq.c      |   14 ++++++++++++++
>  3 files changed, 20 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> index 7be1020..079946e 100644
> --- a/arch/arc/Kconfig
> +++ b/arch/arc/Kconfig
> @@ -32,6 +32,7 @@ config ARC
>  	select HAVE_OPROFILE
>  	select HAVE_PERF_EVENTS
>  	select IRQ_DOMAIN
> +	select HANDLE_DOMAIN_IRQ if ARC_PLAT_EZNPS

On same lines as prev comment - just do this unconditionally for ARC port -
assuming this works with legacy domain as well.


>  	select MODULES_USE_ELF_RELA
>  	select NO_BOOTMEM
>  	select OF
> diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
> index c5f8f0f..64226c9 100644
> --- a/arch/arc/include/asm/irq.h
> +++ b/arch/arc/include/asm/irq.h
> @@ -36,4 +36,9 @@ void arc_request_percpu_irq(int irq, int cpu,
>                              irqreturn_t (*isr)(int irq, void *dev),
>                              const char *irq_nm, void *percpu_dev);
>  
> +#ifdef CONFIG_HANDLE_DOMAIN_IRQ
> +extern void set_handle_irq(void (*handle_irq)(unsigned int hwirq,
> +					      struct pt_regs *));
> +#endif

Not needed !

> +
>  #endif
> diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
> index ba17f85..7ae5411 100644
> --- a/arch/arc/kernel/irq.c
> +++ b/arch/arc/kernel/irq.c
> @@ -41,6 +41,7 @@ void __init init_IRQ(void)
>   * "C" Entry point for any ARC ISR, called from low level vector handler
>   * @irq is the vector number read from ICAUSE reg of on-chip intc
>   */
> +#ifndef CONFIG_HANDLE_DOMAIN_IRQ
>  void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
>  {
>  	struct pt_regs *old_regs = set_irq_regs(regs);
> @@ -50,6 +51,19 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
>  	irq_exit();
>  	set_irq_regs(old_regs);
>  }
> +#else
> +void (*handle_arch_irq)(unsigned int hwirq, struct pt_regs *) = NULL;
> +void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
> +{
> +	handle_arch_irq(irq, regs);
> +}
> +
> +void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
> +					      struct pt_regs *))
> +{
> +	handle_arch_irq = handle_irq;
> +}
> +#endif
>  
>  /*
>   * API called for requesting percpu interrupts - called by each CPU
> 

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

* Re: [PATCH v5 11/20] ARC: IPI: do not use generic IRQ domain
  2015-12-27 13:23   ` Noam Camus
@ 2015-12-30 10:13     ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 10:13 UTC (permalink / raw)
  To: Noam Camus, linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc@ezchip.com>
> 
> This behaviour is the desired one as been seen on other arch's.
> 
> We do not use generic irq domain and hence hwirq number is used
> directly by our code without any mapping to virq.
> In order to add IPI status to /proc/interrupts we use
> hardirq macros also we define arch_show_interrupts().
> 
> Signed-off-by: Noam Camus <noamc@ezchip.com>
> ---
>  arch/arc/include/asm/Kbuild    |    1 -
>  arch/arc/include/asm/hardirq.h |   22 ++++++++++++++++++++++
>  arch/arc/include/asm/smp.h     |    6 ++++++
>  arch/arc/kernel/irq.c          |   13 ++++++++++++-
>  arch/arc/kernel/smp.c          |   27 +++++++++++++++++++++++++++
>  5 files changed, 67 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arc/include/asm/hardirq.h
> 
> diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
> index 0b10ef2..bbc3e4a 100644
> --- a/arch/arc/include/asm/Kbuild
> +++ b/arch/arc/include/asm/Kbuild
> @@ -10,7 +10,6 @@ generic-y += errno.h
>  generic-y += fb.h
>  generic-y += fcntl.h
>  generic-y += ftrace.h
> -generic-y += hardirq.h

So this is going backwards - copy/paste generic code into arch header
I don't understand why you need this !


>  generic-y += hw_irq.h
>  generic-y += ioctl.h
>  generic-y += ioctls.h
> diff --git a/arch/arc/include/asm/hardirq.h b/arch/arc/include/asm/hardirq.h
> new file mode 100644
> index 0000000..e83aa88
> --- /dev/null
> +++ b/arch/arc/include/asm/hardirq.h
> @@ -0,0 +1,22 @@
> +#ifndef __ASM_ARC_HARDIRQ_H
> +#define __ASM_ARC_HARDIRQ_H
> +
> +#include <linux/cache.h>
> +#include <linux/threads.h>
> +
> +typedef struct {
> +	unsigned int __softirq_pending;
> +#ifdef CONFIG_SMP
> +	unsigned int ipi_irqs;
> +#endif
> +} ____cacheline_aligned irq_cpustat_t;
> +
> +#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
> +#include <linux/irq.h>
> +
> +static inline void ack_bad_irq(unsigned int irq)
> +{
> +	printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
> +}
> +
> +#endif /* __ASM_ARC_HARDIRQ_H */
> diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
> index 9913804..9e4ec48 100644
> --- a/arch/arc/include/asm/smp.h
> +++ b/arch/arc/include/asm/smp.h
> @@ -14,12 +14,16 @@
>  #include <linux/types.h>
>  #include <linux/init.h>
>  #include <linux/threads.h>
> +#include <asm/ptrace.h>
>  
>  #define raw_smp_processor_id() (current_thread_info()->cpu)
>  
>  /* including cpumask.h leads to cyclic deps hence this Forward declaration */
>  struct cpumask;
>  
> +/* including seq_file.h leads to cyclic deps hence this Forward declaration */
> +struct seq_file;
> +
>  /*
>   * APIs provided by arch SMP code to generic code
>   */
> @@ -32,6 +36,8 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
>  extern void __init smp_init_cpus(void);
>  extern void first_lines_of_secondary(void);
>  extern const char *arc_platform_smp_cpuinfo(void);
> +extern void arch_do_IPI(unsigned int irq, struct pt_regs *regs);
> +extern void show_ipi_list(struct seq_file *, int);
>  
>  /*
>   * API expected BY platform smp code (FROM arch smp code)
> diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
> index 7ae5411..c8d3c3d 100644
> --- a/arch/arc/kernel/irq.c
> +++ b/arch/arc/kernel/irq.c
> @@ -55,7 +55,10 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
>  void (*handle_arch_irq)(unsigned int hwirq, struct pt_regs *) = NULL;
>  void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
>  {
> -	handle_arch_irq(irq, regs);
> +	if (irq == IPI_IRQ)
> +		arch_do_IPI(irq, regs);
> +	else
> +		handle_arch_irq(irq, regs);
>  }
>  
>  void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
> @@ -65,6 +68,14 @@ void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
>  }
>  #endif
>  
> +int arch_show_interrupts(struct seq_file *p, int prec)
> +{
> +#ifdef CONFIG_SMP
> +	show_ipi_list(p, prec);
> +#endif
> +	return 0;
> +}
> +
>  /*
>   * API called for requesting percpu interrupts - called by each CPU
>   *  - For boot CPU, actually request the IRQ with genirq core + enables
> diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
> index ec6a5c1..8d37906 100644
> --- a/arch/arc/kernel/smp.c
> +++ b/arch/arc/kernel/smp.c
> @@ -22,6 +22,7 @@
>  #include <linux/atomic.h>
>  #include <linux/cpumask.h>
>  #include <linux/reboot.h>
> +#include <linux/seq_file.h>
>  #include <asm/processor.h>
>  #include <asm/setup.h>
>  #include <asm/mach_desc.h>
> @@ -349,6 +350,32 @@ irqreturn_t do_IPI(int irq, void *dev_id)
>  	return IRQ_HANDLED;
>  }
>  
> +void arch_do_IPI(unsigned int irq, struct pt_regs *regs)
> +{
> +	struct pt_regs *old_regs = set_irq_regs(regs);
> +	unsigned int cpu = smp_processor_id();
> +
> +	__IRQ_STAT(cpu, ipi_irqs)++;
> +
> +	irq_enter();
> +	do_IPI(irq, NULL);
> +	irq_exit();
> +
> +	set_irq_regs(old_regs);
> +}

WHY ?


> +
> +void show_ipi_list(struct seq_file *p, int prec)
> +{
> +	unsigned int cpu;
> +
> +	seq_printf(p, "%*s: ", prec - 1, "IPI");
> +
> +	for_each_online_cpu(cpu)
> +		seq_printf(p, "%10u ", __IRQ_STAT(cpu, ipi_irqs));
> +
> +	seq_printf(p, " %s\n", "IPI");
> +}
> +
>  /*
>   * API called by platform code to hookup arch-common ISR to their IPI IRQ
>   */
> 


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

* [PATCH v5 11/20] ARC: IPI: do not use generic IRQ domain
@ 2015-12-30 10:13     ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 10:13 UTC (permalink / raw)
  To: linux-snps-arc

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>
> 
> This behaviour is the desired one as been seen on other arch's.
> 
> We do not use generic irq domain and hence hwirq number is used
> directly by our code without any mapping to virq.
> In order to add IPI status to /proc/interrupts we use
> hardirq macros also we define arch_show_interrupts().
> 
> Signed-off-by: Noam Camus <noamc at ezchip.com>
> ---
>  arch/arc/include/asm/Kbuild    |    1 -
>  arch/arc/include/asm/hardirq.h |   22 ++++++++++++++++++++++
>  arch/arc/include/asm/smp.h     |    6 ++++++
>  arch/arc/kernel/irq.c          |   13 ++++++++++++-
>  arch/arc/kernel/smp.c          |   27 +++++++++++++++++++++++++++
>  5 files changed, 67 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arc/include/asm/hardirq.h
> 
> diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
> index 0b10ef2..bbc3e4a 100644
> --- a/arch/arc/include/asm/Kbuild
> +++ b/arch/arc/include/asm/Kbuild
> @@ -10,7 +10,6 @@ generic-y += errno.h
>  generic-y += fb.h
>  generic-y += fcntl.h
>  generic-y += ftrace.h
> -generic-y += hardirq.h

So this is going backwards - copy/paste generic code into arch header
I don't understand why you need this !


>  generic-y += hw_irq.h
>  generic-y += ioctl.h
>  generic-y += ioctls.h
> diff --git a/arch/arc/include/asm/hardirq.h b/arch/arc/include/asm/hardirq.h
> new file mode 100644
> index 0000000..e83aa88
> --- /dev/null
> +++ b/arch/arc/include/asm/hardirq.h
> @@ -0,0 +1,22 @@
> +#ifndef __ASM_ARC_HARDIRQ_H
> +#define __ASM_ARC_HARDIRQ_H
> +
> +#include <linux/cache.h>
> +#include <linux/threads.h>
> +
> +typedef struct {
> +	unsigned int __softirq_pending;
> +#ifdef CONFIG_SMP
> +	unsigned int ipi_irqs;
> +#endif
> +} ____cacheline_aligned irq_cpustat_t;
> +
> +#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
> +#include <linux/irq.h>
> +
> +static inline void ack_bad_irq(unsigned int irq)
> +{
> +	printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
> +}
> +
> +#endif /* __ASM_ARC_HARDIRQ_H */
> diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
> index 9913804..9e4ec48 100644
> --- a/arch/arc/include/asm/smp.h
> +++ b/arch/arc/include/asm/smp.h
> @@ -14,12 +14,16 @@
>  #include <linux/types.h>
>  #include <linux/init.h>
>  #include <linux/threads.h>
> +#include <asm/ptrace.h>
>  
>  #define raw_smp_processor_id() (current_thread_info()->cpu)
>  
>  /* including cpumask.h leads to cyclic deps hence this Forward declaration */
>  struct cpumask;
>  
> +/* including seq_file.h leads to cyclic deps hence this Forward declaration */
> +struct seq_file;
> +
>  /*
>   * APIs provided by arch SMP code to generic code
>   */
> @@ -32,6 +36,8 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
>  extern void __init smp_init_cpus(void);
>  extern void first_lines_of_secondary(void);
>  extern const char *arc_platform_smp_cpuinfo(void);
> +extern void arch_do_IPI(unsigned int irq, struct pt_regs *regs);
> +extern void show_ipi_list(struct seq_file *, int);
>  
>  /*
>   * API expected BY platform smp code (FROM arch smp code)
> diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
> index 7ae5411..c8d3c3d 100644
> --- a/arch/arc/kernel/irq.c
> +++ b/arch/arc/kernel/irq.c
> @@ -55,7 +55,10 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
>  void (*handle_arch_irq)(unsigned int hwirq, struct pt_regs *) = NULL;
>  void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
>  {
> -	handle_arch_irq(irq, regs);
> +	if (irq == IPI_IRQ)
> +		arch_do_IPI(irq, regs);
> +	else
> +		handle_arch_irq(irq, regs);
>  }
>  
>  void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
> @@ -65,6 +68,14 @@ void __init set_handle_irq(void (*handle_irq)(unsigned int hwirq,
>  }
>  #endif
>  
> +int arch_show_interrupts(struct seq_file *p, int prec)
> +{
> +#ifdef CONFIG_SMP
> +	show_ipi_list(p, prec);
> +#endif
> +	return 0;
> +}
> +
>  /*
>   * API called for requesting percpu interrupts - called by each CPU
>   *  - For boot CPU, actually request the IRQ with genirq core + enables
> diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
> index ec6a5c1..8d37906 100644
> --- a/arch/arc/kernel/smp.c
> +++ b/arch/arc/kernel/smp.c
> @@ -22,6 +22,7 @@
>  #include <linux/atomic.h>
>  #include <linux/cpumask.h>
>  #include <linux/reboot.h>
> +#include <linux/seq_file.h>
>  #include <asm/processor.h>
>  #include <asm/setup.h>
>  #include <asm/mach_desc.h>
> @@ -349,6 +350,32 @@ irqreturn_t do_IPI(int irq, void *dev_id)
>  	return IRQ_HANDLED;
>  }
>  
> +void arch_do_IPI(unsigned int irq, struct pt_regs *regs)
> +{
> +	struct pt_regs *old_regs = set_irq_regs(regs);
> +	unsigned int cpu = smp_processor_id();
> +
> +	__IRQ_STAT(cpu, ipi_irqs)++;
> +
> +	irq_enter();
> +	do_IPI(irq, NULL);
> +	irq_exit();
> +
> +	set_irq_regs(old_regs);
> +}

WHY ?


> +
> +void show_ipi_list(struct seq_file *p, int prec)
> +{
> +	unsigned int cpu;
> +
> +	seq_printf(p, "%*s: ", prec - 1, "IPI");
> +
> +	for_each_online_cpu(cpu)
> +		seq_printf(p, "%10u ", __IRQ_STAT(cpu, ipi_irqs));
> +
> +	seq_printf(p, " %s\n", "IPI");
> +}
> +
>  /*
>   * API called by platform code to hookup arch-common ISR to their IPI IRQ
>   */
> 

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

* Re: [PATCH v5 05/20] irqchip: add nps Internal and external irqchips
  2015-12-27 13:23   ` Noam Camus
@ 2015-12-30 10:41     ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 10:41 UTC (permalink / raw)
  To: Noam Camus, linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier,
	Thomas Gleixner, Jason Cooper

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc@ezchip.com>

...

> +static struct irq_domain *nps400_root_domain;

This can simply be a local var now !

> +static void nps400_handle_irq(unsigned int hwirq, struct pt_regs *regs)
> +{
> +	handle_domain_irq(nps400_root_domain, hwirq, regs);
> +}
> +
> +static int __init nps400_of_init(struct device_node *node,
> +				 struct device_node *parent)
> +{
> +	if (parent)
> +		panic("DeviceTree incore ic not a root irq controller\n");
> +
> +	nps400_root_domain = irq_domain_add_linear(node, NR_CPU_IRQS,
> +						   &nps400_irq_ops, NULL);
> +
> +	if (!nps400_root_domain)
> +		panic("nps400 root irq domain not avail\n");
> +
> +	set_handle_irq(nps400_handle_irq);
> +
> +	return 0;
> +}
> +IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
> 


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

* [PATCH v5 05/20] irqchip: add nps Internal and external irqchips
@ 2015-12-30 10:41     ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 10:41 UTC (permalink / raw)
  To: linux-snps-arc

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>

...

> +static struct irq_domain *nps400_root_domain;

This can simply be a local var now !

> +static void nps400_handle_irq(unsigned int hwirq, struct pt_regs *regs)
> +{
> +	handle_domain_irq(nps400_root_domain, hwirq, regs);
> +}
> +
> +static int __init nps400_of_init(struct device_node *node,
> +				 struct device_node *parent)
> +{
> +	if (parent)
> +		panic("DeviceTree incore ic not a root irq controller\n");
> +
> +	nps400_root_domain = irq_domain_add_linear(node, NR_CPU_IRQS,
> +						   &nps400_irq_ops, NULL);
> +
> +	if (!nps400_root_domain)
> +		panic("nps400 root irq domain not avail\n");
> +
> +	set_handle_irq(nps400_handle_irq);
> +
> +	return 0;
> +}
> +IRQCHIP_DECLARE(ezchip_nps400_ic, "ezchip,nps400-ic", nps400_of_init);
> 

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

* Re: [PATCH v5 09/20] ARC: IRQ: use device tree to get timer device configuration
  2015-12-27 13:23   ` Noam Camus
@ 2015-12-30 11:20     ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 11:20 UTC (permalink / raw)
  To: Noam Camus, linux-snps-arc
  Cc: marc.zyngier, cmetcalf, daniel.lezcano, linux-kernel, Alexey Brodkin

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc@ezchip.com>
> 
> We've designated:
> TIMER0 for events (clockevents)
> TIMER1 for free running (clocksource)
> 
> Till now timer configuration was done on arch/arc/kernel/time.c
> with constant values.
> 
> This commit add device tree support so we can do this work
> at dedicated clocksource driver which parse the DT blob.
> 
> Such driver will get clocksource rate as well as interrupt line
> from DT and use them for setting clocksourcse and clockevents.

Rephrase above part please...

Enable DT based clocksources/clockevents to be probed on ARC. Both clk and IRQ are
furnished by DT.

> 
> Note that lately called of_clk_init() is moved before we call
> clocksource_probe() since at that time device from DT
> need a "provider" (clocks) which will be available only after
> we call to of_clk_init().

Rephrase...

Also move of_clk_init() from a late'ish arch_initcall into time_init() to ensure
clocksource_probe() gets the "provide" clocks.


> 
> Signed-off-by: Noam Camus <noamc@ezchip.com>
> Acked-by: Vineet Gupta <vgupta@synopsys.com>
> ---
>  arch/arc/kernel/setup.c |    1 -
>  arch/arc/kernel/smp.c   |    2 ++
>  arch/arc/kernel/time.c  |    8 ++++++++
>  3 files changed, 10 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
> index e1b8744..4681e9c 100644
> --- a/arch/arc/kernel/setup.c
> +++ b/arch/arc/kernel/setup.c
> @@ -433,7 +433,6 @@ void __init setup_arch(char **cmdline_p)
>  
>  static int __init customize_machine(void)
>  {
> -	of_clk_init(NULL);
>  	/*
>  	 * Traverses flattened DeviceTree - registering platform devices
>  	 * (if any) complete with their resources
> diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
> index 2cfe135..ec6a5c1 100644
> --- a/arch/arc/kernel/smp.c
> +++ b/arch/arc/kernel/smp.c
> @@ -138,7 +138,9 @@ void start_kernel_secondary(void)
>  
>  	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
>  
> +#ifndef CONFIG_CLKSRC_OF
>  	arc_local_timer_setup();
> +#endif
>  
>  	local_irq_enable();
>  	preempt_disable();
> diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
> index dfad287..be6dd9e 100644
> --- a/arch/arc/kernel/time.c
> +++ b/arch/arc/kernel/time.c
> @@ -38,6 +38,7 @@
>  #include <linux/init.h>
>  #include <linux/timex.h>
>  #include <linux/profile.h>
> +#include <linux/clk-provider.h>
>  #include <linux/clocksource.h>
>  #include <linux/clockchips.h>
>  #include <asm/irq.h>
> @@ -283,6 +284,13 @@ void __init time_init(void)
>  		 */
>  		clocksource_register_hz(&arc_counter, arc_get_core_freq());
>  
> +#ifdef CONFIG_COMMON_CLK
> +	of_clk_init(NULL);
> +#endif
> +#ifdef CONFIG_CLKSRC_OF
> +	clocksource_probe();
> +#else

You don't need the #ifdef for both as stub versions already exist.

>  	/* sets up the periodic event timer */
>  	arc_local_timer_setup();

simply do #ifndef CONFIG_CLKSRC_OF just as you do above.

I wanted to remove arc_local_timer_setup from ARC altogether and just switch over
to DT, but it seems I first need to figure out how the timer clk will work with
existing *hack* in plat-axs where we change the clk value for SMP / QUAD configs.

Perhaps needs a clk driver !


> +#endif
>  }
> 

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

* [PATCH v5 09/20] ARC: IRQ: use device tree to get timer device configuration
@ 2015-12-30 11:20     ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2015-12-30 11:20 UTC (permalink / raw)
  To: linux-snps-arc

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>
> 
> We've designated:
> TIMER0 for events (clockevents)
> TIMER1 for free running (clocksource)
> 
> Till now timer configuration was done on arch/arc/kernel/time.c
> with constant values.
> 
> This commit add device tree support so we can do this work
> at dedicated clocksource driver which parse the DT blob.
> 
> Such driver will get clocksource rate as well as interrupt line
> from DT and use them for setting clocksourcse and clockevents.

Rephrase above part please...

Enable DT based clocksources/clockevents to be probed on ARC. Both clk and IRQ are
furnished by DT.

> 
> Note that lately called of_clk_init() is moved before we call
> clocksource_probe() since at that time device from DT
> need a "provider" (clocks) which will be available only after
> we call to of_clk_init().

Rephrase...

Also move of_clk_init() from a late'ish arch_initcall into time_init() to ensure
clocksource_probe() gets the "provide" clocks.


> 
> Signed-off-by: Noam Camus <noamc at ezchip.com>
> Acked-by: Vineet Gupta <vgupta at synopsys.com>
> ---
>  arch/arc/kernel/setup.c |    1 -
>  arch/arc/kernel/smp.c   |    2 ++
>  arch/arc/kernel/time.c  |    8 ++++++++
>  3 files changed, 10 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
> index e1b8744..4681e9c 100644
> --- a/arch/arc/kernel/setup.c
> +++ b/arch/arc/kernel/setup.c
> @@ -433,7 +433,6 @@ void __init setup_arch(char **cmdline_p)
>  
>  static int __init customize_machine(void)
>  {
> -	of_clk_init(NULL);
>  	/*
>  	 * Traverses flattened DeviceTree - registering platform devices
>  	 * (if any) complete with their resources
> diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
> index 2cfe135..ec6a5c1 100644
> --- a/arch/arc/kernel/smp.c
> +++ b/arch/arc/kernel/smp.c
> @@ -138,7 +138,9 @@ void start_kernel_secondary(void)
>  
>  	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
>  
> +#ifndef CONFIG_CLKSRC_OF
>  	arc_local_timer_setup();
> +#endif
>  
>  	local_irq_enable();
>  	preempt_disable();
> diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
> index dfad287..be6dd9e 100644
> --- a/arch/arc/kernel/time.c
> +++ b/arch/arc/kernel/time.c
> @@ -38,6 +38,7 @@
>  #include <linux/init.h>
>  #include <linux/timex.h>
>  #include <linux/profile.h>
> +#include <linux/clk-provider.h>
>  #include <linux/clocksource.h>
>  #include <linux/clockchips.h>
>  #include <asm/irq.h>
> @@ -283,6 +284,13 @@ void __init time_init(void)
>  		 */
>  		clocksource_register_hz(&arc_counter, arc_get_core_freq());
>  
> +#ifdef CONFIG_COMMON_CLK
> +	of_clk_init(NULL);
> +#endif
> +#ifdef CONFIG_CLKSRC_OF
> +	clocksource_probe();
> +#else

You don't need the #ifdef for both as stub versions already exist.

>  	/* sets up the periodic event timer */
>  	arc_local_timer_setup();

simply do #ifndef CONFIG_CLKSRC_OF just as you do above.

I wanted to remove arc_local_timer_setup from ARC altogether and just switch over
to DT, but it seems I first need to figure out how the timer clk will work with
existing *hack* in plat-axs where we change the clk value for SMP / QUAD configs.

Perhaps needs a clk driver !


> +#endif
>  }
> 

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

* Re: [PATCH v5 11/20] ARC: IPI: do not use generic IRQ domain
  2015-12-30 10:13     ` Vineet Gupta
@ 2015-12-31  5:14       ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-31  5:14 UTC (permalink / raw)
  To: Vineet Gupta, linux-snps-arc
  Cc: linux-kernel, Chris Metcalf, daniel.lezcano, marc.zyngier

>From: Vineet Gupta <Vineet.Gupta1@synopsys.com>
>Sent: Wednesday, December 30, 2015 12:13 PM

>>  generic-y += fb.h
>>  generic-y += fcntl.h
>>  generic-y += ftrace.h
>> -generic-y += hardirq.h

>So this is going backwards - copy/paste generic code into arch header
I don't understand why you need this !

I need an extra field (ipi_irqs) at struct irq_cpustat_t and I cannot do this at asm-generic.

See below that how I use it to save and show status for each cpu

>> +void arch_do_IPI(unsigned int irq, struct pt_regs *regs)
>> +{
>> +     struct pt_regs *old_regs = set_irq_regs(regs);
>> +     unsigned int cpu = smp_processor_id();
>> +
>> +     __IRQ_STAT(cpu, ipi_irqs)++;
>> +
>> +     irq_enter();
>> +     do_IPI(irq, NULL);
>> +     irq_exit();
>> +
>> +     set_irq_regs(old_regs);
>> +}

>WHY ?

Please explain

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

* [PATCH v5 11/20] ARC: IPI: do not use generic IRQ domain
@ 2015-12-31  5:14       ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-31  5:14 UTC (permalink / raw)
  To: linux-snps-arc

>From: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
>Sent: Wednesday, December 30, 2015 12:13 PM

>>  generic-y += fb.h
>>  generic-y += fcntl.h
>>  generic-y += ftrace.h
>> -generic-y += hardirq.h

>So this is going backwards - copy/paste generic code into arch header
I don't understand why you need this !

I need an extra field (ipi_irqs) at struct irq_cpustat_t and I cannot do this at asm-generic.

See below that how I use it to save and show status for each cpu

>> +void arch_do_IPI(unsigned int irq, struct pt_regs *regs)
>> +{
>> +     struct pt_regs *old_regs = set_irq_regs(regs);
>> +     unsigned int cpu = smp_processor_id();
>> +
>> +     __IRQ_STAT(cpu, ipi_irqs)++;
>> +
>> +     irq_enter();
>> +     do_IPI(irq, NULL);
>> +     irq_exit();
>> +
>> +     set_irq_regs(old_regs);
>> +}

>WHY ?

Please explain

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

* Re: [PATCH v5 10/20] ARC: IRQ: do not use hwirq directly at arch_do_IRQ()
  2015-12-30 10:10     ` Vineet Gupta
@ 2015-12-31  5:21       ` Noam Camus
  -1 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-31  5:21 UTC (permalink / raw)
  To: Vineet Gupta, linux-snps-arc
  Cc: linux-kernel, Chris Metcalf, daniel.lezcano, marc.zyngier

>From: Vineet Gupta <Vineet.Gupta1@synopsys.com>
>Sent: Wednesday, December 30, 2015 12:10 PM

>> --- a/arch/arc/Kconfig
>> +++ b/arch/arc/Kconfig
>> @@ -32,6 +32,7 @@ config ARC
>>       select HAVE_OPROFILE
>>       select HAVE_PERF_EVENTS
>>       select IRQ_DOMAIN
>> +     select HANDLE_DOMAIN_IRQ if ARC_PLAT_EZNPS

>On same lines as prev comment - just do this unconditionally for ARC port -
assuming this works with legacy domain as well.

Yes it should work for legacy domain.
On the other hand I can select it at the driver Kconfig itself and remove this line altogether.


>>
>> +#ifdef CONFIG_HANDLE_DOMAIN_IRQ
>> +extern void set_handle_irq(void (*handle_irq)(unsigned int hwirq,
>> +                                           struct pt_regs *));
>> +#endif

>Not needed !

I need to have it since we do not know at arch/arc/kernel/irq.c what is the domain allocated by the timer driver


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

* [PATCH v5 10/20] ARC: IRQ: do not use hwirq directly at arch_do_IRQ()
@ 2015-12-31  5:21       ` Noam Camus
  0 siblings, 0 replies; 72+ messages in thread
From: Noam Camus @ 2015-12-31  5:21 UTC (permalink / raw)
  To: linux-snps-arc

>From: Vineet Gupta <Vineet.Gupta1 at synopsys.com>
>Sent: Wednesday, December 30, 2015 12:10 PM

>> --- a/arch/arc/Kconfig
>> +++ b/arch/arc/Kconfig
>> @@ -32,6 +32,7 @@ config ARC
>>       select HAVE_OPROFILE
>>       select HAVE_PERF_EVENTS
>>       select IRQ_DOMAIN
>> +     select HANDLE_DOMAIN_IRQ if ARC_PLAT_EZNPS

>On same lines as prev comment - just do this unconditionally for ARC port -
assuming this works with legacy domain as well.

Yes it should work for legacy domain.
On the other hand I can select it at the driver Kconfig itself and remove this line altogether.


>>
>> +#ifdef CONFIG_HANDLE_DOMAIN_IRQ
>> +extern void set_handle_irq(void (*handle_irq)(unsigned int hwirq,
>> +                                           struct pt_regs *));
>> +#endif

>Not needed !

I need to have it since we do not know at arch/arc/kernel/irq.c what is the domain allocated by the timer driver

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

* Re: [PATCH v5 04/20] clocksource: Add NPS400 timers driver
  2015-12-27 13:23   ` Noam Camus
@ 2016-01-01 10:31     ` Vineet Gupta
  -1 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2016-01-01 10:31 UTC (permalink / raw)
  To: Noam Camus, linux-snps-arc
  Cc: linux-kernel, cmetcalf, daniel.lezcano, marc.zyngier,
	Rob Herring, Thomas Gleixner, John Stultz

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc@ezchip.com>
> 
> Add internal tick generator which is shared by all cores.
> Each cluster of cores view it through dedicated address.
> This is used for SMP system where all CPUs synced by same
> clock source.
> 
> Signed-off-by: Noam Camus <noamc@ezchip.com>
> 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>
> Acked-by: Vineet Gupta <vgupta@synopsys.com>

Not quite.

Also it would help if your individual patches record which changed vs. prev
version (vs. doing that just in cover letter).

So this patch is no longer clocksource as you introduce clockevent as well.
And that is a verbose copy/paste of clockevent in arch/arc/kerne/time.c
I do understand why you did this - since ARC timers have not been DT enabled so
far. But the copy/paste is simply *wrong*.

I'm doing a mini-series which fixes the issue at heart.

It will be a series with incremental changes so we clearly see what is being done.

> ---
>  .../bindings/timer/ezchip,nps400-timer.txt         |   17 ++
>  drivers/clocksource/Kconfig                        |    7 +
>  drivers/clocksource/Makefile                       |    1 +
>  drivers/clocksource/timer-nps.c                    |  199 ++++++++++++++++++++
>  4 files changed, 224 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
>  create mode 100644 drivers/clocksource/timer-nps.c
> 
> diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
> new file mode 100644
> index 0000000..eeb26d7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
> @@ -0,0 +1,17 @@
> +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
> +- interrupts : The interrupt of the first timer
> +
> +Example:
> +
> +timer {
> +	compatible = "ezchip,nps400-timer";
> +	clocks = <&sysclk>;
> +	interrupts = <3>;
> +};
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 2eb5f0e..859e83d 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -132,6 +132,13 @@ config CLKSRC_TI_32K
>  	  This option enables support for Texas Instruments 32.768 Hz clocksource
>  	  available on many OMAP-like platforms.
>  
> +config CLKSRC_NPS
> +	bool "NPS400 clocksource driver" if COMPILE_TEST
> +	select CLKSRC_OF if OF
> +	help
> +	  NPS400 clocksource support.
> +	  Got 64 bit counter with update rate up to 1000MHz.
> +
>  config CLKSRC_STM32
>  	bool "Clocksource for STM32 SoCs" if !ARCH_STM32
>  	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 56bd16e..056cffd 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
>  obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
>  obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
>  obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
> +obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
>  
>  obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
>  obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
> diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
> new file mode 100644
> index 0000000..b3fc9ba
> --- /dev/null
> +++ b/drivers/clocksource/timer-nps.c
> @@ -0,0 +1,199 @@
> +/*
> + * Copyright(c) 2015 EZchip Technologies.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * The full GNU General Public License is included in this distribution in
> + * the file called "COPYING".
> + */
> +
> +#include <linux/clocksource.h>
> +#include <linux/clockchips.h>
> +#include <linux/clk.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/cpu.h>
> +#include <soc/nps/common.h>
> +
> +#define NPS_MSU_TICK_LOW	0xC8
> +#define NPS_CLUSTER_OFFSET	8
> +#define NPS_CLUSTER_NUM		16
> +
> +/* 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 TIMER_CTRL_IE           (1 << 0) /* Interupt when Count reachs limit */
> +#define TIMER_CTRL_NH           (1 << 1) /* Count only when CPU NOT halted */
> +
> +/* 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 int nps_timer_irq;
> +
> +static cycle_t nps_clksrc_read(struct clocksource *clksrc)
> +{
> +	int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET;
> +
> +	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
> +}
> +
> +static struct clocksource nps_counter = {
> +	.name	= "EZnps-tick",
> +	.rating = 301,
> +	.read   = nps_clksrc_read,
> +	.mask   = CLOCKSOURCE_MASK(32),
> +	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
> +};
> +
> +static void nps_timer_event_setup(unsigned int cycles)
> +{
> +	write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
> +	write_aux_reg(ARC_REG_TIMER0_CNT, 0);   /* start from 0 */
> +
> +	write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
> +}
> +
> +static int nps_clkevent_set_next_event(unsigned long delta,
> +				       struct clock_event_device *dev)
> +{
> +	nps_timer_event_setup(delta);
> +	return 0;
> +}
> +
> +static int nps_clkevent_set_periodic(struct clock_event_device *dev)
> +{
> +	/*
> +	 * At X Hz, 1 sec = 1000ms -> X cycles;
> +	 *                    10ms -> X / 100 cycles
> +	 */
> +	nps_timer_event_setup(nps_timer_rate / HZ);
> +	return 0;
> +}
> +
> +static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
> +	.name			= "nps_sys_timer",
> +	.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,
> +};
> +
> +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->irq = nps_timer_irq;
> +	evt->cpumask = cpumask_of(smp_processor_id());
> +
> +	/*
> +	 * Grab cpu pointer in each case to avoid spurious
> +	 * preemptible warnings
> +	 */
> +	switch (action & ~CPU_TASKS_FROZEN) {
> +	case CPU_STARTING:
> +		enable_percpu_irq(nps_timer_irq, 0);
> +		clockevents_config_and_register(evt, nps_timer_rate,
> +						0, ULONG_MAX);
> +		break;
> +	case CPU_DYING:
> +		disable_percpu_irq(nps_timer_irq);
> +		break;
> +	}
> +
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block nps_timer_cpu_nb = {
> +	.notifier_call = nps_timer_cpu_notify,
> +};
> +
> +static irqreturn_t nps_timer_irq_handler(int irq, void *dev_id)
> +{
> +	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
> +	int irq_reenable = clockevent_state_periodic(evt);
> +
> +	/*
> +	 * Any write to CTRL reg ACks the interrupt, we rewrite the
> +	 * Count when [N]ot [H]alted bit.
> +	 * And re-arm it if perioid by [I]nterrupt [E]nable bit
> +	 */
> +	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
> +
> +	evt->event_handler(evt);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void __init nps_setup_clocksource(struct device_node *node,
> +					 struct clk *clk, int irq)
> +{
> +	struct clocksource *clksrc = &nps_counter;
> +	int ret, cluster;
> +
> +	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
> +		nps_msu_reg_low_addr[cluster] =
> +			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
> +				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
> +
> +	ret = clk_prepare_enable(clk);
> +	if (ret)
> +		pr_err("Couldn't enable parent clock\n");
> +
> +	nps_timer_rate = clk_get_rate(clk);
> +
> +	ret = clocksource_register_hz(clksrc, nps_timer_rate);
> +	if (ret)
> +		pr_err("Couldn't register clock source.\n");
> +}
> +
> +static void __init nps_setup_clockevents(struct device_node *node,
> +					 struct clk *clk, int irq)
> +{
> +	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
> +	int ret;
> +
> +	register_cpu_notifier(&nps_timer_cpu_nb);
> +
> +	evt->irq = irq;
> +	evt->cpumask = cpumask_of(smp_processor_id());
> +
> +	clockevents_config_and_register(evt, nps_timer_rate, 0, ULONG_MAX);
> +
> +	enable_percpu_irq(irq, 0);
> +
> +	ret = request_percpu_irq(irq, nps_timer_irq_handler,
> +				 "timer", evt);
> +	if (ret)
> +		pr_err("Unable to register interrupt\n");
> +}
> +
> +static void __init nps_timer_init(struct device_node *node)
> +{
> +	struct clk *clk;
> +
> +	nps_timer_irq = irq_of_parse_and_map(node, 0);
> +	if (nps_timer_irq <= 0)
> +		panic("Can't parse IRQ");
> +
> +	clk = of_clk_get(node, 0);
> +	if (IS_ERR(clk))
> +		panic("Can't get timer clock");
> +
> +	nps_setup_clocksource(node, clk, nps_timer_irq);
> +	nps_setup_clockevents(node, clk, nps_timer_irq);
> +}
> +
> +CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
> +		       nps_timer_init);
> 


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

* [PATCH v5 04/20] clocksource: Add NPS400 timers driver
@ 2016-01-01 10:31     ` Vineet Gupta
  0 siblings, 0 replies; 72+ messages in thread
From: Vineet Gupta @ 2016-01-01 10:31 UTC (permalink / raw)
  To: linux-snps-arc

On Sunday 27 December 2015 06:53 PM, Noam Camus wrote:
> From: Noam Camus <noamc at ezchip.com>
> 
> Add internal tick generator which is shared by all cores.
> Each cluster of cores view it through dedicated address.
> This is used for SMP system where all CPUs synced by same
> clock source.
> 
> Signed-off-by: Noam Camus <noamc at ezchip.com>
> Cc: Daniel Lezcano <daniel.lezcano at linaro.org>
> Cc: Rob Herring <robh+dt at kernel.org>
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: John Stultz <john.stultz at linaro.org>
> Acked-by: Vineet Gupta <vgupta at synopsys.com>

Not quite.

Also it would help if your individual patches record which changed vs. prev
version (vs. doing that just in cover letter).

So this patch is no longer clocksource as you introduce clockevent as well.
And that is a verbose copy/paste of clockevent in arch/arc/kerne/time.c
I do understand why you did this - since ARC timers have not been DT enabled so
far. But the copy/paste is simply *wrong*.

I'm doing a mini-series which fixes the issue at heart.

It will be a series with incremental changes so we clearly see what is being done.

> ---
>  .../bindings/timer/ezchip,nps400-timer.txt         |   17 ++
>  drivers/clocksource/Kconfig                        |    7 +
>  drivers/clocksource/Makefile                       |    1 +
>  drivers/clocksource/timer-nps.c                    |  199 ++++++++++++++++++++
>  4 files changed, 224 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
>  create mode 100644 drivers/clocksource/timer-nps.c
> 
> diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
> new file mode 100644
> index 0000000..eeb26d7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
> @@ -0,0 +1,17 @@
> +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
> +- interrupts : The interrupt of the first timer
> +
> +Example:
> +
> +timer {
> +	compatible = "ezchip,nps400-timer";
> +	clocks = <&sysclk>;
> +	interrupts = <3>;
> +};
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 2eb5f0e..859e83d 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -132,6 +132,13 @@ config CLKSRC_TI_32K
>  	  This option enables support for Texas Instruments 32.768 Hz clocksource
>  	  available on many OMAP-like platforms.
>  
> +config CLKSRC_NPS
> +	bool "NPS400 clocksource driver" if COMPILE_TEST
> +	select CLKSRC_OF if OF
> +	help
> +	  NPS400 clocksource support.
> +	  Got 64 bit counter with update rate up to 1000MHz.
> +
>  config CLKSRC_STM32
>  	bool "Clocksource for STM32 SoCs" if !ARCH_STM32
>  	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 56bd16e..056cffd 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.o
>  obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
>  obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
>  obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
> +obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
>  
>  obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
>  obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
> diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
> new file mode 100644
> index 0000000..b3fc9ba
> --- /dev/null
> +++ b/drivers/clocksource/timer-nps.c
> @@ -0,0 +1,199 @@
> +/*
> + * Copyright(c) 2015 EZchip Technologies.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * The full GNU General Public License is included in this distribution in
> + * the file called "COPYING".
> + */
> +
> +#include <linux/clocksource.h>
> +#include <linux/clockchips.h>
> +#include <linux/clk.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/cpu.h>
> +#include <soc/nps/common.h>
> +
> +#define NPS_MSU_TICK_LOW	0xC8
> +#define NPS_CLUSTER_OFFSET	8
> +#define NPS_CLUSTER_NUM		16
> +
> +/* 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 TIMER_CTRL_IE           (1 << 0) /* Interupt when Count reachs limit */
> +#define TIMER_CTRL_NH           (1 << 1) /* Count only when CPU NOT halted */
> +
> +/* 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 int nps_timer_irq;
> +
> +static cycle_t nps_clksrc_read(struct clocksource *clksrc)
> +{
> +	int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET;
> +
> +	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
> +}
> +
> +static struct clocksource nps_counter = {
> +	.name	= "EZnps-tick",
> +	.rating = 301,
> +	.read   = nps_clksrc_read,
> +	.mask   = CLOCKSOURCE_MASK(32),
> +	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
> +};
> +
> +static void nps_timer_event_setup(unsigned int cycles)
> +{
> +	write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
> +	write_aux_reg(ARC_REG_TIMER0_CNT, 0);   /* start from 0 */
> +
> +	write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
> +}
> +
> +static int nps_clkevent_set_next_event(unsigned long delta,
> +				       struct clock_event_device *dev)
> +{
> +	nps_timer_event_setup(delta);
> +	return 0;
> +}
> +
> +static int nps_clkevent_set_periodic(struct clock_event_device *dev)
> +{
> +	/*
> +	 * At X Hz, 1 sec = 1000ms -> X cycles;
> +	 *                    10ms -> X / 100 cycles
> +	 */
> +	nps_timer_event_setup(nps_timer_rate / HZ);
> +	return 0;
> +}
> +
> +static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
> +	.name			= "nps_sys_timer",
> +	.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,
> +};
> +
> +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->irq = nps_timer_irq;
> +	evt->cpumask = cpumask_of(smp_processor_id());
> +
> +	/*
> +	 * Grab cpu pointer in each case to avoid spurious
> +	 * preemptible warnings
> +	 */
> +	switch (action & ~CPU_TASKS_FROZEN) {
> +	case CPU_STARTING:
> +		enable_percpu_irq(nps_timer_irq, 0);
> +		clockevents_config_and_register(evt, nps_timer_rate,
> +						0, ULONG_MAX);
> +		break;
> +	case CPU_DYING:
> +		disable_percpu_irq(nps_timer_irq);
> +		break;
> +	}
> +
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block nps_timer_cpu_nb = {
> +	.notifier_call = nps_timer_cpu_notify,
> +};
> +
> +static irqreturn_t nps_timer_irq_handler(int irq, void *dev_id)
> +{
> +	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
> +	int irq_reenable = clockevent_state_periodic(evt);
> +
> +	/*
> +	 * Any write to CTRL reg ACks the interrupt, we rewrite the
> +	 * Count when [N]ot [H]alted bit.
> +	 * And re-arm it if perioid by [I]nterrupt [E]nable bit
> +	 */
> +	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
> +
> +	evt->event_handler(evt);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void __init nps_setup_clocksource(struct device_node *node,
> +					 struct clk *clk, int irq)
> +{
> +	struct clocksource *clksrc = &nps_counter;
> +	int ret, cluster;
> +
> +	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
> +		nps_msu_reg_low_addr[cluster] =
> +			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
> +				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
> +
> +	ret = clk_prepare_enable(clk);
> +	if (ret)
> +		pr_err("Couldn't enable parent clock\n");
> +
> +	nps_timer_rate = clk_get_rate(clk);
> +
> +	ret = clocksource_register_hz(clksrc, nps_timer_rate);
> +	if (ret)
> +		pr_err("Couldn't register clock source.\n");
> +}
> +
> +static void __init nps_setup_clockevents(struct device_node *node,
> +					 struct clk *clk, int irq)
> +{
> +	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
> +	int ret;
> +
> +	register_cpu_notifier(&nps_timer_cpu_nb);
> +
> +	evt->irq = irq;
> +	evt->cpumask = cpumask_of(smp_processor_id());
> +
> +	clockevents_config_and_register(evt, nps_timer_rate, 0, ULONG_MAX);
> +
> +	enable_percpu_irq(irq, 0);
> +
> +	ret = request_percpu_irq(irq, nps_timer_irq_handler,
> +				 "timer", evt);
> +	if (ret)
> +		pr_err("Unable to register interrupt\n");
> +}
> +
> +static void __init nps_timer_init(struct device_node *node)
> +{
> +	struct clk *clk;
> +
> +	nps_timer_irq = irq_of_parse_and_map(node, 0);
> +	if (nps_timer_irq <= 0)
> +		panic("Can't parse IRQ");
> +
> +	clk = of_clk_get(node, 0);
> +	if (IS_ERR(clk))
> +		panic("Can't get timer clock");
> +
> +	nps_setup_clocksource(node, clk, nps_timer_irq);
> +	nps_setup_clockevents(node, clk, nps_timer_irq);
> +}
> +
> +CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
> +		       nps_timer_init);
> 

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

end of thread, other threads:[~2016-01-01 10:32 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-27 13:23 [PATCH v5 00/20] Adding plat-eznps to ARC Noam Camus
2015-12-27 13:23 ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 01/20] Documentation: Add EZchip vendor to binding list Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 02/20] soc: Support for EZchip SoC Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 03/20] ARC: [plat-eznps] define IPI_IRQ Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 04/20] clocksource: Add NPS400 timers driver Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 14:55   ` kbuild test robot
2015-12-27 14:55     ` kbuild test robot
2015-12-27 21:41     ` Noam Camus
2015-12-27 21:41       ` Noam Camus
2015-12-28  9:00       ` Daniel Lezcano
2015-12-28  9:00         ` Daniel Lezcano
2015-12-28 10:35         ` Vineet Gupta
2015-12-28 10:35           ` Vineet Gupta
2015-12-28 10:55           ` Daniel Lezcano
2015-12-28 10:55             ` Daniel Lezcano
2015-12-28 11:11             ` Vineet Gupta
2015-12-28 11:11               ` Vineet Gupta
2016-01-01 10:31   ` Vineet Gupta
2016-01-01 10:31     ` Vineet Gupta
2015-12-27 13:23 ` [PATCH v5 05/20] irqchip: add nps Internal and external irqchips Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-30 10:08   ` Vineet Gupta
2015-12-30 10:08     ` Vineet Gupta
2015-12-30 10:41   ` Vineet Gupta
2015-12-30 10:41     ` Vineet Gupta
2015-12-27 13:23 ` [PATCH v5 06/20] ARC: Set vmalloc size from configuration Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 07/20] ARC: rwlock: disable interrupts in !LLSC variant Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 08/20] ARC: Mark secondary cpu online only after all HW setup is done Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 09/20] ARC: IRQ: use device tree to get timer device configuration Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-28 11:42   ` Vineet Gupta
2015-12-28 11:42     ` Vineet Gupta
2015-12-30 11:20   ` Vineet Gupta
2015-12-30 11:20     ` Vineet Gupta
2015-12-27 13:23 ` [PATCH v5 10/20] ARC: IRQ: do not use hwirq directly at arch_do_IRQ() Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-30 10:10   ` Vineet Gupta
2015-12-30 10:10     ` Vineet Gupta
2015-12-31  5:21     ` Noam Camus
2015-12-31  5:21       ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 11/20] ARC: IPI: do not use generic IRQ domain Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-30 10:13   ` Vineet Gupta
2015-12-30 10:13     ` Vineet Gupta
2015-12-31  5:14     ` Noam Camus
2015-12-31  5:14       ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 12/20] ARC: [plat-eznps] Add eznps board defconfig and dts Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 13/20] ARC: [plat-eznps] Add eznps platform Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 14/20] ARC: [plat-eznps] Use dedicated user stack top Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 15/20] ARC: [plat-eznps] Use dedicated atomic/bitops/cmpxchg Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 16/20] ARC: [plat-eznps] Use dedicated SMP barriers Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 17/20] ARC: [plat-eznps] Use dedicated identity auxiliary register Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 18/20] ARC: [plat-eznps] Use dedicated cpu_relax() Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 19/20] ARC: [plat-eznps] Use dedicated COMMAND_LINE_SIZE Noam Camus
2015-12-27 13:23   ` Noam Camus
2015-12-27 13:23 ` [PATCH v5 20/20] ARC: Add eznps platform to Kconfig and Makefile Noam Camus
2015-12-27 13:23   ` Noam Camus

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.