linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V8 0/6] C-SKY(csky) Linux Kernel Port
@ 2018-09-20  5:39 Guo Ren
  2018-09-20  5:39 ` [PATCH V8 1/6] csky/dma: bugfix dma_sync_for_cpu/device Guo Ren
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Guo Ren @ 2018-09-20  5:39 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, arnd, robh, sfr
  Cc: linux-kernel, devicetree, linux-arch, c-sky_gcc_upstream,
	gnu-csky, green.hu, Guo Ren

Because I've sent to Stephen Roth with the linux-4.19-rc3 git-tree for
linux-next, I shouldn't rebase any more.
https://github.com/c-sky/csky-linux.git#linux-next

This patchset include mptimer and mpintc drivers and fixup:

 - Fixup smp IPI's problems found by Marc Zyngier
 - Add irq-csky-mpintc.c patch in this patchset
 - Add mptimer.c patch in this patchset 
 - Fixup dma_sync_for_cpu/device in dma-mapping.c

Guo Ren (6):
  csky/dma: bugfix dma_sync_for_cpu/device
  csky: remove irq_mapping from smp.c
  irqchip: add C-SKY SMP interrupt controller
  dt-bindings: interrupt-controller: C-SKY SMP intc
  clocksource: add C-SKY SMP timer
  dt-bindings: timer: C-SKY Multi-processor timer

 .../bindings/interrupt-controller/csky,mpintc.txt  |  40 +++++
 .../devicetree/bindings/timer/csky,mptimer.txt     |  46 +++++
 arch/csky/include/asm/smp.h                        |   4 +-
 arch/csky/kernel/smp.c                             |  27 ++-
 arch/csky/mm/dma-mapping.c                         |   5 +-
 drivers/clocksource/Kconfig                        |   8 +
 drivers/clocksource/Makefile                       |   1 +
 drivers/clocksource/csky_mptimer.c                 | 178 +++++++++++++++++++
 drivers/irqchip/Kconfig                            |   8 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-csky-mpintc.c                  | 195 +++++++++++++++++++++
 include/linux/cpuhotplug.h                         |   1 +
 12 files changed, 503 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
 create mode 100644 Documentation/devicetree/bindings/timer/csky,mptimer.txt
 create mode 100644 drivers/clocksource/csky_mptimer.c
 create mode 100644 drivers/irqchip/irq-csky-mpintc.c

-- 
2.7.4


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

* [PATCH V8 1/6] csky/dma: bugfix dma_sync_for_cpu/device
  2018-09-20  5:39 [PATCH V8 0/6] C-SKY(csky) Linux Kernel Port Guo Ren
@ 2018-09-20  5:39 ` Guo Ren
  2018-09-20  5:39 ` [PATCH V8 2/6] csky: remove irq_mapping from smp.c Guo Ren
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Guo Ren @ 2018-09-20  5:39 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, arnd, robh, sfr
  Cc: linux-kernel, devicetree, linux-arch, c-sky_gcc_upstream,
	gnu-csky, green.hu, Guo Ren

ref: https://lkml.org/lkml/2018/5/18/1068

        map             for_cpu         for_device      unmap
TO_DEV  writeback       none            writeback       none
TO_CPU  invalidate      invalidate*     invalidate      invalidate*
BIDIR   writeback       invalidate      writeback       invalidate

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/mm/dma-mapping.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/csky/mm/dma-mapping.c b/arch/csky/mm/dma-mapping.c
index 16c2087..30a2041 100644
--- a/arch/csky/mm/dma-mapping.c
+++ b/arch/csky/mm/dma-mapping.c
@@ -217,7 +217,8 @@ void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
 		break;
 	case DMA_FROM_DEVICE:
 	case DMA_BIDIRECTIONAL:
-		BUG();
+		dma_wbinv_range(vaddr + offset, vaddr + offset + size);
+		break;
 	default:
 		BUG();
 	}
@@ -240,7 +241,7 @@ void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
 
 	switch (dir) {
 	case DMA_TO_DEVICE:
-		BUG();
+		break;
 	case DMA_FROM_DEVICE:
 	case DMA_BIDIRECTIONAL:
 		dma_wbinv_range(vaddr + offset, vaddr + offset + size);
-- 
2.7.4


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

* [PATCH V8 2/6] csky: remove irq_mapping from smp.c
  2018-09-20  5:39 [PATCH V8 0/6] C-SKY(csky) Linux Kernel Port Guo Ren
  2018-09-20  5:39 ` [PATCH V8 1/6] csky/dma: bugfix dma_sync_for_cpu/device Guo Ren
@ 2018-09-20  5:39 ` Guo Ren
  2018-09-20  5:39 ` [PATCH V8 3/6] irqchip: add C-SKY SMP interrupt controller Guo Ren
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Guo Ren @ 2018-09-20  5:39 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, arnd, robh, sfr
  Cc: linux-kernel, devicetree, linux-arch, c-sky_gcc_upstream,
	gnu-csky, green.hu, Guo Ren

 - Add irq_mapping return check
 - Move IPI_IRQ into irq-driver
 - remove irq_mapping from smp.c to irq-driver
 - Add set_ipi_irq_mapping api to irq-driver
 - update asm/smp.h

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/include/asm/smp.h |  4 +++-
 arch/csky/kernel/smp.c      | 27 +++++++++++++++++++--------
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/arch/csky/include/asm/smp.h b/arch/csky/include/asm/smp.h
index 9a53abf..f3e4f24 100644
--- a/arch/csky/include/asm/smp.h
+++ b/arch/csky/include/asm/smp.h
@@ -17,7 +17,9 @@ void arch_send_call_function_ipi_mask(struct cpumask *mask);
 
 void arch_send_call_function_single_ipi(int cpu);
 
-void __init set_send_ipi(void (*func)(const unsigned long *, unsigned long));
+void __init set_send_ipi(void (*func)(const unsigned long *));
+
+void __init set_ipi_irq_mapping(int (*func)(void));
 
 #define raw_smp_processor_id()	(current_thread_info()->cpu)
 
diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c
index 522c73f..14877e2 100644
--- a/arch/csky/kernel/smp.c
+++ b/arch/csky/kernel/smp.c
@@ -20,8 +20,6 @@
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 
-#define IPI_IRQ	15
-
 static struct {
 	unsigned long bits ____cacheline_aligned;
 } ipi_data[NR_CPUS] __cacheline_aligned;
@@ -56,9 +54,9 @@ static irqreturn_t handle_ipi(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static void (*send_arch_ipi)(const unsigned long *mask, unsigned long irq) = NULL;
+static void (*send_arch_ipi)(const unsigned long *mask) = NULL;
 
-void __init set_send_ipi(void (*func)(const unsigned long *, unsigned long))
+void __init set_send_ipi(void (*func)(const unsigned long *))
 {
 	if (send_arch_ipi)
 		return;
@@ -75,7 +73,7 @@ send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
 		set_bit(operation, &ipi_data[i].bits);
 
 	smp_mb();
-	send_arch_ipi(cpumask_bits(to_whom), IPI_IRQ);
+	send_arch_ipi(cpumask_bits(to_whom));
 }
 
 void arch_send_call_function_ipi_mask(struct cpumask *mask)
@@ -115,19 +113,32 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 }
 
 static int ipi_dummy_dev;
+static int ipi_irq;
 
 void __init enable_smp_ipi(void)
 {
-	enable_percpu_irq(IPI_IRQ, 0);
+	enable_percpu_irq(ipi_irq, 0);
+}
+
+static int (*arch_ipi_irq_mapping)(void) = NULL;
+
+void __init set_ipi_irq_mapping(int (*func)(void))
+{
+	if (arch_ipi_irq_mapping)
+		return;
+
+	arch_ipi_irq_mapping = func;
 }
 
 void __init setup_smp_ipi(void)
 {
 	int rc;
 
-	irq_create_mapping(NULL, IPI_IRQ);
+	ipi_irq = arch_ipi_irq_mapping();
+	if (ipi_irq == 0)
+		panic("%s IRQ mapping failed\n", __func__);
 
-	rc = request_percpu_irq(IPI_IRQ, handle_ipi, "IPI Interrupt", &ipi_dummy_dev);
+	rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt", &ipi_dummy_dev);
 	if (rc)
 		panic("%s IRQ request failed\n", __func__);
 
-- 
2.7.4


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

* [PATCH V8 3/6] irqchip: add C-SKY SMP interrupt controller
  2018-09-20  5:39 [PATCH V8 0/6] C-SKY(csky) Linux Kernel Port Guo Ren
  2018-09-20  5:39 ` [PATCH V8 1/6] csky/dma: bugfix dma_sync_for_cpu/device Guo Ren
  2018-09-20  5:39 ` [PATCH V8 2/6] csky: remove irq_mapping from smp.c Guo Ren
@ 2018-09-20  5:39 ` Guo Ren
  2018-09-20  5:39 ` [PATCH V8 4/6] dt-bindings: interrupt-controller: C-SKY SMP intc Guo Ren
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Guo Ren @ 2018-09-20  5:39 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, arnd, robh, sfr
  Cc: linux-kernel, devicetree, linux-arch, c-sky_gcc_upstream,
	gnu-csky, green.hu, Guo Ren

 - Irq-csky-mpintc is C-SKY smp system interrupt controller and it
   could support 16 soft irqs, 16 private irqs, and 992 max common
   irqs.

Changelog:
 - Move IPI_IRQ into the driver
 - Remove irq_set_default_host() and use set_ipi_irq_mapping()
 - Change name with upstream feed-back
 - Change irq map, reserve soft_irq & private_irq space
 - Add License and Copyright
 - Support set_affinity for irq balance in SMP

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 drivers/irqchip/Kconfig           |   8 ++
 drivers/irqchip/Makefile          |   1 +
 drivers/irqchip/irq-csky-mpintc.c | 195 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 204 insertions(+)
 create mode 100644 drivers/irqchip/irq-csky-mpintc.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 383e7b7..92e1c20 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -371,6 +371,14 @@ config QCOM_PDC
 	  Power Domain Controller driver to manage and configure wakeup
 	  IRQs for Qualcomm Technologies Inc (QTI) mobile chips.
 
+config CSKY_MPINTC
+	bool "C-SKY Multi Processor Interrupt Controller"
+	depends on CSKY
+	help
+	  Say yes here to enable C-SKY SMP interrupt controller driver used
+	  for C-SKY SMP system. In fact it's not mmio map and it use ld/st
+	  to visit the controller's register inside CPU.
+
 endmenu
 
 config SIFIVE_PLIC
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index fbd1ec8..6b739ea 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -87,4 +87,5 @@ obj-$(CONFIG_MESON_IRQ_GPIO)		+= irq-meson-gpio.o
 obj-$(CONFIG_GOLDFISH_PIC) 		+= irq-goldfish-pic.o
 obj-$(CONFIG_NDS32)			+= irq-ativic32.o
 obj-$(CONFIG_QCOM_PDC)			+= qcom-pdc.o
+obj-$(CONFIG_CSKY_MPINTC)		+= irq-csky-mpintc.o
 obj-$(CONFIG_SIFIVE_PLIC)		+= irq-sifive-plic.o
diff --git a/drivers/irqchip/irq-csky-mpintc.c b/drivers/irqchip/irq-csky-mpintc.c
new file mode 100644
index 0000000..2b424d27
--- /dev/null
+++ b/drivers/irqchip/irq-csky-mpintc.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+#include <asm/reg_ops.h>
+#include <asm/smp.h>
+
+static struct irq_domain *root_domain;
+static void __iomem *INTCG_base;
+static void __iomem *INTCL_base;
+
+#define IPI_IRQ		15
+#define INTC_IRQS	256
+#define COMM_IRQ_BASE	32
+
+#define INTCG_SIZE	0x8000
+#define INTCL_SIZE	0x1000
+#define INTC_SIZE	INTCL_SIZE*nr_cpu_ids + INTCG_SIZE
+
+#define INTCG_ICTLR	0x0
+#define INTCG_CICFGR	0x100
+#define INTCG_CIDSTR	0x1000
+
+#define INTCL_PICTLR	0x0
+#define INTCL_SIGR	0x60
+#define INTCL_HPPIR	0x68
+#define INTCL_RDYIR	0x6c
+#define INTCL_SENR	0xa0
+#define INTCL_CENR	0xa4
+#define INTCL_CACR	0xb4
+
+static DEFINE_PER_CPU(void __iomem *, intcl_reg);
+
+static void csky_mpintc_handler(struct pt_regs *regs)
+{
+	void __iomem *reg_base = this_cpu_read(intcl_reg);
+
+	do {
+		handle_domain_irq(root_domain,
+				  readl_relaxed(reg_base + INTCL_RDYIR),
+				  regs);
+	} while (readl_relaxed(reg_base + INTCL_HPPIR) & BIT(31));
+}
+
+static void csky_mpintc_enable(struct irq_data *d)
+{
+	void __iomem *reg_base = this_cpu_read(intcl_reg);
+
+	writel_relaxed(d->hwirq, reg_base + INTCL_SENR);
+}
+
+static void csky_mpintc_disable(struct irq_data *d)
+{
+	void __iomem *reg_base = this_cpu_read(intcl_reg);
+
+	writel_relaxed(d->hwirq, reg_base + INTCL_CENR);
+}
+
+static void csky_mpintc_eoi(struct irq_data *d)
+{
+	void __iomem *reg_base = this_cpu_read(intcl_reg);
+
+	writel_relaxed(d->hwirq, reg_base + INTCL_CACR);
+}
+
+#ifdef CONFIG_SMP
+static int csky_irq_set_affinity(struct irq_data *d,
+				 const struct cpumask *mask_val,
+				 bool force)
+{
+	unsigned int cpu;
+	unsigned int offset = 4 * (d->hwirq - COMM_IRQ_BASE);
+
+	if (!force)
+		cpu = cpumask_any_and(mask_val, cpu_online_mask);
+	else
+		cpu = cpumask_first(mask_val);
+
+	if (cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	/* Enable interrupt destination */
+	cpu |= BIT(31);
+
+	writel_relaxed(cpu, INTCG_base + INTCG_CIDSTR + offset);
+
+	irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
+	return IRQ_SET_MASK_OK_DONE;
+}
+#endif
+
+static struct irq_chip csky_irq_chip = {
+	.name           = "C-SKY SMP Intc",
+	.irq_eoi	= csky_mpintc_eoi,
+	.irq_enable	= csky_mpintc_enable,
+	.irq_disable	= csky_mpintc_disable,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = csky_irq_set_affinity,
+#endif
+};
+
+static int csky_irqdomain_map(struct irq_domain *d, unsigned int irq,
+			      irq_hw_number_t hwirq)
+{
+	if(hwirq < COMM_IRQ_BASE) {
+		irq_set_percpu_devid(irq);
+		irq_set_chip_and_handler(irq, &csky_irq_chip, handle_percpu_irq);
+	} else {
+		irq_set_chip_and_handler(irq, &csky_irq_chip, handle_fasteoi_irq);
+	}
+
+	return 0;
+}
+
+static const struct irq_domain_ops csky_irqdomain_ops = {
+	.map	= csky_irqdomain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+#ifdef CONFIG_SMP
+static void csky_mpintc_send_ipi(const unsigned long *mask)
+{
+	void __iomem *reg_base = this_cpu_read(intcl_reg);
+
+	/*
+	 * INTCL_SIGR[3:0] INTID
+	 * INTCL_SIGR[8:15] CPUMASK
+	 */
+	writel_relaxed((*mask) << 8 | IPI_IRQ, reg_base + INTCL_SIGR);
+}
+
+static int csky_mpintc_ipi_irq_mapping(void)
+{
+	return irq_create_mapping(root_domain, IPI_IRQ);
+}
+#endif
+
+/* C-SKY multi processor interrupt controller */
+static int __init
+csky_mpintc_init(struct device_node *node, struct device_node *parent)
+{
+	unsigned int cpu, nr_irq;
+	int ret;
+
+	if (parent)
+		return 0;
+
+	ret = of_property_read_u32(node, "csky,num-irqs", &nr_irq);
+	if (ret < 0)
+		nr_irq = INTC_IRQS;
+
+	if (INTCG_base == NULL) {
+		INTCG_base = ioremap(mfcr("cr<31, 14>"), INTC_SIZE);
+		if (INTCG_base == NULL)
+			return -EIO;
+
+		INTCL_base = INTCG_base + INTCG_SIZE;
+
+		writel_relaxed(BIT(0), INTCG_base + INTCG_ICTLR);
+	}
+
+	root_domain = irq_domain_add_linear(node, nr_irq, &csky_irqdomain_ops,
+					    NULL);
+	if (!root_domain)
+		return -ENXIO;
+
+	/* for every cpu */
+	for_each_present_cpu(cpu) {
+		per_cpu(intcl_reg, cpu) = INTCL_base + (INTCL_SIZE * cpu);
+		writel_relaxed(BIT(0), per_cpu(intcl_reg, cpu) + INTCL_PICTLR);
+	}
+
+	set_handle_irq(&csky_mpintc_handler);
+
+#ifdef CONFIG_SMP
+	set_send_ipi(&csky_mpintc_send_ipi);
+
+	set_ipi_irq_mapping(&csky_mpintc_ipi_irq_mapping);
+#endif
+
+	return 0;
+}
+IRQCHIP_DECLARE(csky_mpintc, "csky,mpintc", csky_mpintc_init);
-- 
2.7.4


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

* [PATCH V8 4/6] dt-bindings: interrupt-controller: C-SKY SMP intc
  2018-09-20  5:39 [PATCH V8 0/6] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (2 preceding siblings ...)
  2018-09-20  5:39 ` [PATCH V8 3/6] irqchip: add C-SKY SMP interrupt controller Guo Ren
@ 2018-09-20  5:39 ` Guo Ren
  2018-09-20  5:39 ` [PATCH V8 5/6] clocksource: add C-SKY SMP timer Guo Ren
  2018-09-20  5:39 ` [PATCH V8 6/6] dt-bindings: timer: C-SKY Multi-processor timer Guo Ren
  5 siblings, 0 replies; 8+ messages in thread
From: Guo Ren @ 2018-09-20  5:39 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, arnd, robh, sfr
  Cc: linux-kernel, devicetree, linux-arch, c-sky_gcc_upstream,
	gnu-csky, green.hu, Guo Ren

 - Dt-bindings doc about C-SKY Multi-processors interrupt controller.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 .../bindings/interrupt-controller/csky,mpintc.txt  | 40 ++++++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
new file mode 100644
index 0000000..9cdad74
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
@@ -0,0 +1,40 @@
+===========================================
+C-SKY Multi-processors Interrupt Controller
+===========================================
+
+C-SKY Multi-processors Interrupt Controller is designed for ck807/ck810/ck860
+SMP soc, and it also could be used in non-SMP system.
+
+Interrupt number definition:
+
+  0-15  : software irq, and we use 15 as our IPI_IRQ.
+ 16-31  : private  irq, and we use 16 as the co-processor timer.
+ 31-1024: common irq for soc ip.
+
+=============================
+intc node bindings definition
+=============================
+
+	Description: Describes SMP interrupt controller
+
+	PROPERTIES
+
+	- compatible
+		Usage: required
+		Value type: <string>
+		Definition: must be "csky,mpintc"
+	- interrupt-cells
+		Usage: required
+		Value type: <u32>
+		Definition: must be <1>
+	- interrupt-controller:
+		Usage: required
+
+Examples:
+---------
+
+	intc: interrupt-controller {
+		compatible = "csky,mpintc";
+		#interrupt-cells = <1>;
+		interrupt-controller;
+	};
-- 
2.7.4


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

* [PATCH V8 5/6] clocksource: add C-SKY SMP timer
  2018-09-20  5:39 [PATCH V8 0/6] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (3 preceding siblings ...)
  2018-09-20  5:39 ` [PATCH V8 4/6] dt-bindings: interrupt-controller: C-SKY SMP intc Guo Ren
@ 2018-09-20  5:39 ` Guo Ren
  2018-09-20  5:54   ` Guo Ren
  2018-09-20  5:39 ` [PATCH V8 6/6] dt-bindings: timer: C-SKY Multi-processor timer Guo Ren
  5 siblings, 1 reply; 8+ messages in thread
From: Guo Ren @ 2018-09-20  5:39 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, arnd, robh, sfr
  Cc: linux-kernel, devicetree, linux-arch, c-sky_gcc_upstream,
	gnu-csky, green.hu, Guo Ren

This timer is used by SMP system and use mfcr/mtcr instruction
to access the regs.

Changelog:
 - Add CPUHP_AP_CSKY_TIMER_STARTING in cpuhotplug.h
 - Support csky mp timer alpha version.
 - Just use low-counter with 32bit width as clocksource.
 - Coding convention with upstream feed-back.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 drivers/clocksource/Kconfig        |   8 ++
 drivers/clocksource/Makefile       |   1 +
 drivers/clocksource/csky_mptimer.c | 178 +++++++++++++++++++++++++++++++++++++
 include/linux/cpuhotplug.h         |   1 +
 4 files changed, 188 insertions(+)
 create mode 100644 drivers/clocksource/csky_mptimer.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a11f4ba..51286be 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -609,6 +609,14 @@ config ATCPIT100_TIMER
 	help
 	  This option enables support for the Andestech ATCPIT100 timers.
 
+config CSKY_MPTIMER
+	bool "C-SKY Multi Processor Timer"
+	depends on CSKY
+	select TIMER_OF
+	help
+	  Say yes here to enable C-SKY SMP timer driver used for C-SKY SMP
+	  system.
+
 config RISCV_TIMER
 	bool "Timer for the RISC-V platform"
 	depends on RISCV
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index db51b24..848c676 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -79,3 +79,4 @@ obj-$(CONFIG_CLKSRC_ST_LPC)		+= clksrc_st_lpc.o
 obj-$(CONFIG_X86_NUMACHIP)		+= numachip.o
 obj-$(CONFIG_ATCPIT100_TIMER)		+= timer-atcpit100.o
 obj-$(CONFIG_RISCV_TIMER)		+= riscv_timer.o
+obj-$(CONFIG_CSKY_MPTIMER)		+= csky_mptimer.o
diff --git a/drivers/clocksource/csky_mptimer.c b/drivers/clocksource/csky_mptimer.c
new file mode 100644
index 0000000..c6d5db1
--- /dev/null
+++ b/drivers/clocksource/csky_mptimer.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched_clock.h>
+#include <linux/cpu.h>
+#include <asm/reg_ops.h>
+
+#include "timer-of.h"
+
+#define PTIM_CCVR	"cr<3, 14>"
+#define PTIM_CTLR	"cr<0, 14>"
+#define PTIM_LVR	"cr<6, 14>"
+#define PTIM_TSR	"cr<1, 14>"
+
+static int csky_mptimer_set_next_event(unsigned long delta, struct clock_event_device *ce)
+{
+	mtcr(PTIM_LVR, delta);
+
+	return 0;
+}
+
+static int csky_mptimer_shutdown(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 0);
+
+	return 0;
+}
+
+static int csky_mptimer_oneshot(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 1);
+
+	return 0;
+}
+
+static int csky_mptimer_oneshot_stopped(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 0);
+
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct timer_of, csky_to) = {
+	.flags					= TIMER_OF_CLOCK,
+	.clkevt = {
+		.rating				= 300,
+		.features			= CLOCK_EVT_FEAT_PERCPU |
+						  CLOCK_EVT_FEAT_ONESHOT,
+		.set_state_shutdown		= csky_mptimer_shutdown,
+		.set_state_oneshot		= csky_mptimer_oneshot,
+		.set_state_oneshot_stopped	= csky_mptimer_oneshot_stopped,
+		.set_next_event			= csky_mptimer_set_next_event,
+	},
+	.of_irq = {
+		.flags				= IRQF_TIMER,
+		.percpu				= 1,
+	},
+};
+
+static irqreturn_t timer_interrupt(int irq, void *dev)
+{
+	struct timer_of *to = this_cpu_ptr(&csky_to);
+
+	mtcr(PTIM_TSR, 0);
+
+	to->clkevt.event_handler(&to->clkevt);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * clock event for percpu
+ */
+static int csky_mptimer_starting_cpu(unsigned int cpu)
+{
+	struct timer_of *to = per_cpu_ptr(&csky_to, cpu);
+
+	to->clkevt.cpumask = cpumask_of(cpu);
+
+	clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 2, ULONG_MAX);
+
+	enable_percpu_irq(timer_of_irq(to), 0);
+
+	return 0;
+}
+
+static int csky_mptimer_dying_cpu(unsigned int cpu)
+{
+	struct timer_of *to = per_cpu_ptr(&csky_to, cpu);
+
+	disable_percpu_irq(timer_of_irq(to));
+
+	return 0;
+}
+
+/*
+ * clock source
+ */
+static u64 sched_clock_read(void)
+{
+	return (u64) mfcr(PTIM_CCVR);
+}
+
+static u64 clksrc_read(struct clocksource *c)
+{
+	return (u64) mfcr(PTIM_CCVR);
+}
+
+struct clocksource csky_clocksource = {
+	.name	= "csky",
+	.rating	= 400,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+	.read	= clksrc_read,
+};
+
+#define CPUHP_AP_CSKY_TIMER_STARTING CPUHP_AP_RISCV_TIMER_STARTING
+
+static int __init csky_mptimer_init(struct device_node *np)
+{
+	int ret, cpu;
+	struct timer_of *to;
+	int rate = 0;
+	int irq	 = 0;
+
+	/*
+	 * Csky_mptimer is designed for C-SKY SMP multi-processors and
+	 * every core has it's own private irq and regs for clkevt and
+	 * clksrc.
+	 *
+	 * The regs is accessed by cpu instruction: mfcr/mtcr instead of
+	 * mmio map style. So we needn't mmio-address in dts, but we still
+	 * need to give clk and irq number.
+	 *
+	 * We use private irq for the mptimer and irq number is the same
+	 * for every core. So we use request_percpu_irq() in timer_of_init.
+	 */
+
+	for_each_possible_cpu(cpu) {
+		to = per_cpu_ptr(&csky_to, cpu);
+
+		if (cpu == 0) {
+			to->flags	  |= TIMER_OF_IRQ;
+			to->of_irq.handler = timer_interrupt;
+
+			ret = timer_of_init(np, to);
+			if (ret)
+				return ret;
+
+			rate	= timer_of_rate(to);
+			irq	= to->of_irq.irq;
+		} else {
+			ret = timer_of_init(np, to);
+			if (ret)
+				return ret;
+
+			to->of_clk.rate	= rate;
+			to->of_irq.irq	= irq;
+		}
+	}
+
+	ret = cpuhp_setup_state(CPUHP_AP_CSKY_TIMER_STARTING,
+				"clockevents/csky/timer:starting",
+				csky_mptimer_starting_cpu,
+				csky_mptimer_dying_cpu);
+	if (ret) {
+		pr_err("%s: Failed to cpuhp_setup_state.\n", __func__);
+		return ret;
+	}
+
+	clocksource_register_hz(&csky_clocksource, rate);
+	sched_clock_register(sched_clock_read, 32, rate);
+
+	return 0;
+}
+TIMER_OF_DECLARE(csky_mptimer, "csky,mptimer", csky_mptimer_init);
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index caf40ad..e0cd2ba 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -126,6 +126,7 @@ enum cpuhp_state {
 	CPUHP_AP_MIPS_GIC_TIMER_STARTING,
 	CPUHP_AP_ARC_TIMER_STARTING,
 	CPUHP_AP_RISCV_TIMER_STARTING,
+	CPUHP_AP_CSKY_TIMER_STARTING,
 	CPUHP_AP_KVM_STARTING,
 	CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING,
 	CPUHP_AP_KVM_ARM_VGIC_STARTING,
-- 
2.7.4


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

* [PATCH V8 6/6] dt-bindings: timer: C-SKY Multi-processor timer
  2018-09-20  5:39 [PATCH V8 0/6] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (4 preceding siblings ...)
  2018-09-20  5:39 ` [PATCH V8 5/6] clocksource: add C-SKY SMP timer Guo Ren
@ 2018-09-20  5:39 ` Guo Ren
  5 siblings, 0 replies; 8+ messages in thread
From: Guo Ren @ 2018-09-20  5:39 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, arnd, robh, sfr
  Cc: linux-kernel, devicetree, linux-arch, c-sky_gcc_upstream,
	gnu-csky, green.hu, Guo Ren

 - Dt-bingdings doc for C-SKY SMP system setting.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 .../devicetree/bindings/timer/csky,mptimer.txt     | 46 ++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/csky,mptimer.txt

diff --git a/Documentation/devicetree/bindings/timer/csky,mptimer.txt b/Documentation/devicetree/bindings/timer/csky,mptimer.txt
new file mode 100644
index 0000000..1e7e31d
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/csky,mptimer.txt
@@ -0,0 +1,46 @@
+============================
+C-SKY Multi-processors Timer
+============================
+
+C-SKY multi-processors timer is designed for C-SKY SMP system and the
+regs is accessed by cpu co-processor 4 registers with mtcr/mfcr.
+
+ - PTIM_CTLR "cr<0, 14>" Control reg to start reset timer.
+ - PTIM_TSR  "cr<1, 14>" Interrupt cleanup status reg.
+ - PTIM_CCVR "cr<3, 14>" Current counter value reg.
+ - PTIM_LVR  "cr<6, 14>" Window value reg to triger next event.
+
+==============================
+timer node bindings definition
+==============================
+
+	Description: Describes SMP timer
+
+	PROPERTIES
+
+	- compatible
+		Usage: required
+		Value type: <string>
+		Definition: must be "csky,mptimer"
+	- clocks
+		Usage: required
+		Value type: <node>
+		Definition: must be input clk node
+	- interrupts
+		Usage: required
+		Value type: <u32>
+		Definition: must be timer irq num defined by soc
+	- interrupt-parent:
+		Usage: required
+		Value type: <node>
+		Definition: must be interrupt controller node
+
+Examples:
+---------
+
+	timer: timer {
+		compatible = "csky,mptimer";
+		clocks = <&dummy_apb_clk>;
+		interrupts = <16>;
+		interrupt-parent = <&intc>;
+	};
-- 
2.7.4


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

* Re: [PATCH V8 5/6] clocksource: add C-SKY SMP timer
  2018-09-20  5:39 ` [PATCH V8 5/6] clocksource: add C-SKY SMP timer Guo Ren
@ 2018-09-20  5:54   ` Guo Ren
  0 siblings, 0 replies; 8+ messages in thread
From: Guo Ren @ 2018-09-20  5:54 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, arnd, robh, sfr
  Cc: linux-kernel, devicetree, linux-arch, c-sky_gcc_upstream,
	gnu-csky, green.hu

On Thu, Sep 20, 2018 at 01:39:31PM +0800, Guo Ren wrote:
> +struct clocksource csky_clocksource = {
> +	.name	= "csky",
> +	.rating	= 400,
> +	.mask	= CLOCKSOURCE_MASK(32),
> +	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
> +	.read	= clksrc_read,
> +};
> +
> +#define CPUHP_AP_CSKY_TIMER_STARTING CPUHP_AP_RISCV_TIMER_STARTING
My fault, forget delete the line above.

 Guo Ren

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

end of thread, other threads:[~2018-09-20  5:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-20  5:39 [PATCH V8 0/6] C-SKY(csky) Linux Kernel Port Guo Ren
2018-09-20  5:39 ` [PATCH V8 1/6] csky/dma: bugfix dma_sync_for_cpu/device Guo Ren
2018-09-20  5:39 ` [PATCH V8 2/6] csky: remove irq_mapping from smp.c Guo Ren
2018-09-20  5:39 ` [PATCH V8 3/6] irqchip: add C-SKY SMP interrupt controller Guo Ren
2018-09-20  5:39 ` [PATCH V8 4/6] dt-bindings: interrupt-controller: C-SKY SMP intc Guo Ren
2018-09-20  5:39 ` [PATCH V8 5/6] clocksource: add C-SKY SMP timer Guo Ren
2018-09-20  5:54   ` Guo Ren
2018-09-20  5:39 ` [PATCH V8 6/6] dt-bindings: timer: C-SKY Multi-processor timer Guo Ren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).