All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V9 0/8] C-SKY(csky) Linux Kernel Drivers
@ 2018-10-01  1:35 ` Guo Ren
  0 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:35 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

From "PATCH V5 00/30] C-SKY(csky) Linux Kernel Port" I seperated the
drivers from the patchset. I've sent driver patches with "V5 V6 V7 V8".

Now is V9. The changelog is in every patch.

Perhaps I should seperate driver patchset earlier and the csky port patchset
is too big now.

Any feedback is welcome, thx for all people review my patchset.

Best Regards

Guo Ren (8):
  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
  dt-bindings: interrupt-controller: C-SKY APB intc
  irqchip: add C-SKY APB bus interrupt controller
  dt-bindings: timer: gx6605s SOC timer
  clocksource: add gx6605s SOC system timer

 .../interrupt-controller/csky,apb-intc.txt         |  62 +++++
 .../bindings/interrupt-controller/csky,mpintc.txt  |  40 ++++
 .../bindings/timer/csky,gx6605s-timer.txt          |  42 ++++
 .../devicetree/bindings/timer/csky,mptimer.txt     |  42 ++++
 drivers/clocksource/Kconfig                        |  16 ++
 drivers/clocksource/Makefile                       |   2 +
 drivers/clocksource/csky_mptimer.c                 | 176 ++++++++++++++
 drivers/clocksource/timer-gx6605s.c                | 150 ++++++++++++
 drivers/irqchip/Kconfig                            |  16 ++
 drivers/irqchip/Makefile                           |   2 +
 drivers/irqchip/irq-csky-apb-intc.c                | 260 +++++++++++++++++++++
 drivers/irqchip/irq-csky-mpintc.c                  | 195 ++++++++++++++++
 include/linux/cpuhotplug.h                         |   1 +
 13 files changed, 1004 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/csky,apb-intc.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
 create mode 100644 Documentation/devicetree/bindings/timer/csky,gx6605s-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/csky,mptimer.txt
 create mode 100644 drivers/clocksource/csky_mptimer.c
 create mode 100644 drivers/clocksource/timer-gx6605s.c
 create mode 100644 drivers/irqchip/irq-csky-apb-intc.c
 create mode 100644 drivers/irqchip/irq-csky-mpintc.c

-- 
2.7.4


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

* [PATCH V9 0/8] C-SKY(csky) Linux Kernel Drivers
@ 2018-10-01  1:35 ` Guo Ren
  0 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:35 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

>From "PATCH V5 00/30] C-SKY(csky) Linux Kernel Port" I seperated the
drivers from the patchset. I've sent driver patches with "V5 V6 V7 V8".

Now is V9. The changelog is in every patch.

Perhaps I should seperate driver patchset earlier and the csky port patchset
is too big now.

Any feedback is welcome, thx for all people review my patchset.

Best Regards

Guo Ren (8):
  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
  dt-bindings: interrupt-controller: C-SKY APB intc
  irqchip: add C-SKY APB bus interrupt controller
  dt-bindings: timer: gx6605s SOC timer
  clocksource: add gx6605s SOC system timer

 .../interrupt-controller/csky,apb-intc.txt         |  62 +++++
 .../bindings/interrupt-controller/csky,mpintc.txt  |  40 ++++
 .../bindings/timer/csky,gx6605s-timer.txt          |  42 ++++
 .../devicetree/bindings/timer/csky,mptimer.txt     |  42 ++++
 drivers/clocksource/Kconfig                        |  16 ++
 drivers/clocksource/Makefile                       |   2 +
 drivers/clocksource/csky_mptimer.c                 | 176 ++++++++++++++
 drivers/clocksource/timer-gx6605s.c                | 150 ++++++++++++
 drivers/irqchip/Kconfig                            |  16 ++
 drivers/irqchip/Makefile                           |   2 +
 drivers/irqchip/irq-csky-apb-intc.c                | 260 +++++++++++++++++++++
 drivers/irqchip/irq-csky-mpintc.c                  | 195 ++++++++++++++++
 include/linux/cpuhotplug.h                         |   1 +
 13 files changed, 1004 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/csky,apb-intc.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/csky,mpintc.txt
 create mode 100644 Documentation/devicetree/bindings/timer/csky,gx6605s-timer.txt
 create mode 100644 Documentation/devicetree/bindings/timer/csky,mptimer.txt
 create mode 100644 drivers/clocksource/csky_mptimer.c
 create mode 100644 drivers/clocksource/timer-gx6605s.c
 create mode 100644 drivers/irqchip/irq-csky-apb-intc.c
 create mode 100644 drivers/irqchip/irq-csky-mpintc.c

-- 
2.7.4

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

* [PATCH V9 1/8] irqchip: add C-SKY SMP interrupt controller
  2018-10-01  1:35 ` Guo Ren
  (?)
@ 2018-10-01  1:35 ` Guo Ren
  -1 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:35 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, 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] 14+ messages in thread

* [PATCH V9 2/8] dt-bindings: interrupt-controller: C-SKY SMP intc
  2018-10-01  1:35 ` Guo Ren
  (?)
  (?)
@ 2018-10-01  1:35 ` Guo Ren
  -1 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:35 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

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

Changelog:
 - Should be: '#interrupt-cells' not 'interrupt-cells'

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..ab921f1
--- /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] 14+ messages in thread

* [PATCH V9 3/8] clocksource: add C-SKY SMP timer
  2018-10-01  1:35 ` Guo Ren
                   ` (2 preceding siblings ...)
  (?)
@ 2018-10-01  1:35 ` Guo Ren
  2018-10-01  9:14   ` Daniel Lezcano
  -1 siblings, 1 reply; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:35 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

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

Changelog:
 - Remove #define CPUHP_AP_CSKY_TIMER_STARTING
 - 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 | 176 +++++++++++++++++++++++++++++++++++++
 include/linux/cpuhotplug.h         |   1 +
 4 files changed, 186 insertions(+)
 create mode 100644 drivers/clocksource/csky_mptimer.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a11f4ba..a28043f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -620,4 +620,12 @@ config RISCV_TIMER
 	  is accessed via both the SBI and the rdcycle instruction.  This is
 	  required for all RISC-V systems.
 
+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.
+
 endmenu
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..9dc3cfb
--- /dev/null
+++ b/drivers/clocksource/csky_mptimer.c
@@ -0,0 +1,176 @@
+// 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,
+};
+
+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] 14+ messages in thread

* [PATCH V9 4/8] dt-bindings: timer: C-SKY Multi-processor timer
  2018-10-01  1:35 ` Guo Ren
                   ` (3 preceding siblings ...)
  (?)
@ 2018-10-01  1:35 ` Guo Ren
  -1 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:35 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

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

Changelog:
 - Drop the interrupt-parent.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 .../devicetree/bindings/timer/csky,mptimer.txt     | 42 ++++++++++++++++++++++
 1 file changed, 42 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..15cfec0
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/csky,mptimer.txt
@@ -0,0 +1,42 @@
+============================
+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
+
+Examples:
+---------
+
+	timer: timer {
+		compatible = "csky,mptimer";
+		clocks = <&dummy_apb_clk>;
+		interrupts = <16>;
+		interrupt-parent = <&intc>;
+	};
-- 
2.7.4


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

* [PATCH V9 5/8] dt-bindings: interrupt-controller: C-SKY APB intc
  2018-10-01  1:35 ` Guo Ren
                   ` (4 preceding siblings ...)
  (?)
@ 2018-10-01  1:36 ` Guo Ren
  -1 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:36 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

 - Dt-bindings doc about C-SKY apb bus interrupt controller.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
 .../interrupt-controller/csky,apb-intc.txt         | 62 ++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/csky,apb-intc.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/csky,apb-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/csky,apb-intc.txt
new file mode 100644
index 0000000..44286dc
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/csky,apb-intc.txt
@@ -0,0 +1,62 @@
+==============================
+C-SKY APB Interrupt Controller
+==============================
+
+C-SKY APB Interrupt Controller is a simple soc interrupt controller
+on the apb bus and we only use it as root irq controller.
+
+ - csky,apb-intc is used in a lot of csky fpgas and socs, it support 64 irq nums.
+ - csky,dual-apb-intc consists of 2 apb-intc and 128 irq nums supported.
+ - csky,gx6605s-intc is gx6605s soc internal irq interrupt controller, 64 irq nums.
+
+=============================
+intc node bindings definition
+=============================
+
+	Description: Describes APB interrupt controller
+
+	PROPERTIES
+
+	- compatible
+		Usage: required
+		Value type: <string>
+		Definition: must be "csky,apb-intc"
+				    "csky,dual-apb-intc"
+				    "csky,gx6605s-intc"
+	- #interrupt-cells
+		Usage: required
+		Value type: <u32>
+		Definition: must be <1>
+	- reg
+		Usage: required
+		Value type: <u32 u32>
+		Definition: <phyaddr size> in soc from cpu view
+	- interrupt-controller:
+		Usage: required
+	- csky,support-pulse-signal:
+		Usage: select
+		Description: to support pulse signal flag
+
+Examples:
+---------
+
+	intc: interrupt-controller@500000 {
+		compatible = "csky,apb-intc";
+		#interrupt-cells = <1>;
+		reg = <0x00500000 0x400>;
+		interrupt-controller;
+	};
+
+	intc: interrupt-controller@500000 {
+		compatible = "csky,dual-apb-intc";
+		#interrupt-cells = <1>;
+		reg = <0x00500000 0x400>;
+		interrupt-controller;
+	};
+
+	intc: interrupt-controller@500000 {
+		compatible = "csky,gx6605s-intc";
+		#interrupt-cells = <1>;
+		reg = <0x00500000 0x400>;
+		interrupt-controller;
+	};
-- 
2.7.4


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

* [PATCH V9 6/8] irqchip: add C-SKY APB bus interrupt controller
  2018-10-01  1:35 ` Guo Ren
                   ` (5 preceding siblings ...)
  (?)
@ 2018-10-01  1:36 ` Guo Ren
  -1 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:36 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

 - irq-csky-apb-intc is a simple SOC interrupt controller which is
   used in a lot of C-SKY CPU SOC products.

Changelog:
 - use "bool ret" instead of "int ret"
 - add support-pulse-signal in irq-csky-apb-intc.c
 - change name with upstream feed-back
 - add INTC_IFR to clear irq-pending
 - remove CSKY_VECIRQ_LEGENCY
 - change to generic irq chip framework
 - add License and Copyright
 - use irq_domain_add_linear instead of leagcy

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

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 92e1c20..bf12549 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -379,6 +379,14 @@ config CSKY_MPINTC
 	  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.
 
+config CSKY_APB_INTC
+	bool "C-SKY APB Interrupt Controller"
+	depends on CSKY
+	help
+	  Say yes here to enable C-SKY APB interrupt controller driver used
+	  by C-SKY single core SOC system. It use mmio map apb-bus to visit
+	  the controller's register.
+
 endmenu
 
 config SIFIVE_PLIC
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 6b739ea..72eaf53 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -88,4 +88,5 @@ 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_CSKY_APB_INTC)		+= irq-csky-apb-intc.o
 obj-$(CONFIG_SIFIVE_PLIC)		+= irq-sifive-plic.o
diff --git a/drivers/irqchip/irq-csky-apb-intc.c b/drivers/irqchip/irq-csky-apb-intc.c
new file mode 100644
index 0000000..cfe32a7
--- /dev/null
+++ b/drivers/irqchip/irq-csky-apb-intc.c
@@ -0,0 +1,260 @@
+// 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>
+
+#define INTC_IRQS		64
+
+#define CK_INTC_ICR		0x00
+#define CK_INTC_PEN31_00	0x14
+#define CK_INTC_PEN63_32	0x2c
+#define CK_INTC_NEN31_00	0x10
+#define CK_INTC_NEN63_32	0x28
+#define CK_INTC_SOURCE		0x40
+#define CK_INTC_DUAL_BASE	0x100
+
+#define GX_INTC_PEN31_00	0x00
+#define GX_INTC_PEN63_32	0x04
+#define GX_INTC_NEN31_00	0x40
+#define GX_INTC_NEN63_32	0x44
+#define GX_INTC_NMASK31_00	0x50
+#define GX_INTC_NMASK63_32	0x54
+#define GX_INTC_SOURCE		0x60
+
+static void __iomem *reg_base;
+static struct irq_domain *root_domain;
+
+static int nr_irq = INTC_IRQS;
+
+/*
+ * When controller support pulse signal, the PEN_reg will hold on signal
+ * without software trigger.
+ *
+ * So, to support pulse signal we need to clear IFR_reg and the address of
+ * IFR_offset is NEN_offset - 8.
+ */
+static void irq_ck_mask_set_bit(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
+	unsigned long ifr = ct->regs.mask - 8;
+	u32 mask = d->mask;
+
+	irq_gc_lock(gc);
+	*ct->mask_cache |= mask;
+	irq_reg_writel(gc, *ct->mask_cache, ct->regs.mask);
+	irq_reg_writel(gc, irq_reg_readl(gc, ifr) & ~mask, ifr);
+	irq_gc_unlock(gc);
+}
+
+static void __init ck_set_gc(struct device_node *node, void __iomem *reg_base,
+			     u32 mask_reg, u32 irq_base)
+{
+	struct irq_chip_generic *gc;
+
+	gc = irq_get_domain_generic_chip(root_domain, irq_base);
+	gc->reg_base = reg_base;
+	gc->chip_types[0].regs.mask = mask_reg;
+	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
+	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
+
+	if (of_find_property(node, "csky,support-pulse-signal", NULL))
+		gc->chip_types[0].chip.irq_unmask = irq_ck_mask_set_bit;
+}
+
+static inline u32 build_channel_val(u32 idx, u32 magic)
+{
+	u32 res;
+
+	/*
+	 * Set the same index for each channel
+	 */
+	res = idx | (idx << 8) | (idx << 16) | (idx << 24);
+
+	/*
+	 * Set the channel magic number in descending order.
+	 * The magic is 0x00010203 for ck-intc
+	 * The magic is 0x03020100 for gx6605s-intc
+	 */
+	return res | magic;
+}
+
+static inline void setup_irq_channel(u32 magic, void __iomem *reg_addr)
+{
+	u32 i;
+
+	/* Setup 64 channel slots */
+	for (i = 0; i < INTC_IRQS; i += 4) {
+		writel_relaxed(build_channel_val(i, magic), reg_addr + i);
+	}
+}
+
+static int __init
+ck_intc_init_comm(struct device_node *node, struct device_node *parent)
+{
+	int ret;
+
+	if (parent) {
+		pr_err("C-SKY Intc not a root irq controller\n");
+		return -EINVAL;
+	}
+
+	reg_base = of_iomap(node, 0);
+	if (!reg_base) {
+		pr_err("C-SKY Intc unable to map: %p.\n", node);
+		return -EINVAL;
+	}
+
+	root_domain = irq_domain_add_linear(node, nr_irq, &irq_generic_chip_ops, NULL);
+	if (!root_domain) {
+		pr_err("C-SKY Intc irq_domain_add failed.\n");
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(root_domain, 32, 1,
+					     "csky_intc", handle_level_irq,
+					     IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
+					     0, 0);
+	if (ret) {
+		pr_err("C-SKY Intc irq_alloc_gc failed.\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq, u32 irq_base)
+{
+	u32 irq;
+
+	if (hwirq == 0) return 0;
+
+	while (hwirq) {
+		irq = __ffs(hwirq);
+		hwirq &= ~BIT(irq);
+		handle_domain_irq(root_domain, irq_base + irq, regs);
+	}
+
+	return 1;
+}
+
+/* gx6605s 64 irqs interrupt controller */
+static void gx_irq_handler(struct pt_regs *regs)
+{
+	bool ret;
+
+	do {
+		ret  = handle_irq_perbit(regs ,readl_relaxed(reg_base + GX_INTC_PEN31_00), 0);
+		ret |= handle_irq_perbit(regs ,readl_relaxed(reg_base + GX_INTC_PEN63_32), 32);
+	} while(ret);
+}
+
+static int __init
+gx_intc_init(struct device_node *node, struct device_node *parent)
+{
+	int ret;
+
+	ret = ck_intc_init_comm(node, parent);
+	if (ret)
+		return ret;
+
+	/* Initial enable reg to disable all interrupts */
+	writel_relaxed(0x0, reg_base + GX_INTC_NEN31_00);
+	writel_relaxed(0x0, reg_base + GX_INTC_NEN63_32);
+
+	/* Initial mask reg with all unmasked, becasue we only use enalbe reg */
+	writel_relaxed(0x0, reg_base + GX_INTC_NMASK31_00);
+	writel_relaxed(0x0, reg_base + GX_INTC_NMASK63_32);
+
+	setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE);
+
+	ck_set_gc(node, reg_base, GX_INTC_NEN31_00, 0);
+	ck_set_gc(node, reg_base, GX_INTC_NEN63_32, 32);
+
+	set_handle_irq(gx_irq_handler);
+
+	return 0;
+}
+IRQCHIP_DECLARE(csky_gx6605s_intc, "csky,gx6605s-intc", gx_intc_init);
+
+/* C-SKY simple 64 irqs interrupt controller, dual-together could support 128 irqs */
+static void ck_irq_handler(struct pt_regs *regs)
+{
+	bool ret;
+
+	do {
+		/* handle 0 - 31 irqs */
+		ret  = handle_irq_perbit(regs, readl_relaxed(reg_base + CK_INTC_PEN31_00), 0);
+		ret |= handle_irq_perbit(regs, readl_relaxed(reg_base + CK_INTC_PEN63_32), 32);
+
+		if (nr_irq == INTC_IRQS) continue;
+
+		/* handle 64 - 127 irqs */
+		ret |= handle_irq_perbit(regs,
+			   readl_relaxed(reg_base + CK_INTC_PEN31_00 + CK_INTC_DUAL_BASE), 64);
+		ret |= handle_irq_perbit(regs,
+			   readl_relaxed(reg_base + CK_INTC_PEN63_32 + CK_INTC_DUAL_BASE), 96);
+	} while(ret);
+}
+
+static int __init
+ck_intc_init(struct device_node *node, struct device_node *parent)
+{
+	int ret;
+
+	ret = ck_intc_init_comm(node, parent);
+	if (ret)
+		return ret;
+
+	/* Initial enable reg to disable all interrupts */
+	writel_relaxed(0, reg_base + CK_INTC_NEN31_00);
+	writel_relaxed(0, reg_base + CK_INTC_NEN63_32);
+
+	/* Enable irq intc */
+	writel_relaxed(BIT(31), reg_base + CK_INTC_ICR);
+
+	ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0);
+	ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32);
+
+	setup_irq_channel(0x00010203, reg_base + CK_INTC_SOURCE);
+
+	set_handle_irq(ck_irq_handler);
+
+	return 0;
+}
+IRQCHIP_DECLARE(ck_intc, "csky,apb-intc", ck_intc_init);
+
+static int __init
+ck_dual_intc_init(struct device_node *node, struct device_node *parent)
+{
+	int ret;
+
+	/* dual-apb-intc up to 128 irq sources*/
+	nr_irq = INTC_IRQS * 2;
+
+	ret = ck_intc_init(node, parent);
+	if (ret)
+		return ret;
+
+	/* Initial enable reg to disable all interrupts */
+	writel_relaxed(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE);
+	writel_relaxed(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE);
+
+	ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64);
+	ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96);
+
+	setup_irq_channel(0x00010203, reg_base + CK_INTC_SOURCE + CK_INTC_DUAL_BASE);
+
+	return 0;
+}
+IRQCHIP_DECLARE(ck_dual_intc, "csky,dual-apb-intc", ck_dual_intc_init);
-- 
2.7.4


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

* [PATCH V9 7/8] dt-bindings: timer: gx6605s SOC timer
  2018-10-01  1:35 ` Guo Ren
                   ` (6 preceding siblings ...)
  (?)
@ 2018-10-01  1:36 ` Guo Ren
  -1 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:36 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

 - Dt-bindings doc for gx6605s SOC's system timer.

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
 .../bindings/timer/csky,gx6605s-timer.txt          | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/csky,gx6605s-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/csky,gx6605s-timer.txt b/Documentation/devicetree/bindings/timer/csky,gx6605s-timer.txt
new file mode 100644
index 0000000..6b04344
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/csky,gx6605s-timer.txt
@@ -0,0 +1,42 @@
+=================
+gx6605s SOC Timer
+=================
+
+The timer is used in gx6605s soc as system timer and the driver
+contain clk event and clk source.
+
+==============================
+timer node bindings definition
+==============================
+
+	Description: Describes gx6605s SOC timer
+
+	PROPERTIES
+
+	- compatible
+		Usage: required
+		Value type: <string>
+		Definition: must be "csky,gx6605s-timer"
+	- reg
+		Usage: required
+		Value type: <u32 u32>
+		Definition: <phyaddr size> in soc from cpu view
+	- clocks
+		Usage: required
+		Value type: phandle + clock specifier cells
+		Definition: must be input clk node
+	- interrupt
+		Usage: required
+		Value type: <u32>
+		Definition: must be timer irq num defined by soc
+
+Examples:
+---------
+
+	timer0: timer@20a000 {
+		compatible = "csky,gx6605s-timer";
+		reg = <0x0020a000 0x400>;
+		clocks = <&dummy_apb_clk>;
+		interrupts = <10>;
+		interrupt-parent = <&intc>;
+	};
-- 
2.7.4


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

* [PATCH V9 8/8] clocksource: add gx6605s SOC system timer
  2018-10-01  1:35 ` Guo Ren
                   ` (7 preceding siblings ...)
  (?)
@ 2018-10-01  1:36 ` Guo Ren
  -1 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-01  1:36 UTC (permalink / raw)
  To: tglx, jason, marc.zyngier, robh+dt, mark.rutland, daniel.lezcano,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree, Guo Ren

Changelog:
 - Add COMIPLE_TEST in Kconfig
 - no cast is needed for "struct clock_event_device *ce = dev"
 - remove: extra space after (u64)
 - Add License and Copyright
 - Use timer-of framework
 - Change name with upstream feedback
 - Use clksource_mmio framework

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 drivers/clocksource/Kconfig         |   8 ++
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-gx6605s.c | 150 ++++++++++++++++++++++++++++++++++++
 3 files changed, 159 insertions(+)
 create mode 100644 drivers/clocksource/timer-gx6605s.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a28043f..3dc24ca 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -628,4 +628,12 @@ config CSKY_MPTIMER
 	  Say yes here to enable C-SKY SMP timer driver used for C-SKY SMP
 	  system.
 
+config GX6605S_TIMER
+	bool "Gx6605s SOC system timer driver" if COMPILE_TEST
+	depends on CSKY
+	select CLKSRC_MMIO
+	select TIMER_OF
+	help
+	  This option enables support for gx6605s SOC's timer.
+
 endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 848c676..7a1b0f4 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -80,3 +80,4 @@ 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
+obj-$(CONFIG_GX6605S_TIMER)		+= timer-gx6605s.o
diff --git a/drivers/clocksource/timer-gx6605s.c b/drivers/clocksource/timer-gx6605s.c
new file mode 100644
index 0000000..3974ede
--- /dev/null
+++ b/drivers/clocksource/timer-gx6605s.c
@@ -0,0 +1,150 @@
+// 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 "timer-of.h"
+
+#define CLKSRC_OFFSET	0x40
+
+#define TIMER_STATUS	0x00
+#define TIMER_VALUE	0x04
+#define TIMER_CONTRL	0x10
+#define TIMER_CONFIG	0x20
+#define TIMER_DIV	0x24
+#define TIMER_INI	0x28
+
+#define GX6605S_STATUS_CLR	BIT(0)
+#define GX6605S_CONTRL_RST	BIT(0)
+#define GX6605S_CONTRL_START	BIT(1)
+#define GX6605S_CONFIG_EN	BIT(0)
+#define GX6605S_CONFIG_IRQ_EN	BIT(1)
+
+static irqreturn_t gx6605s_timer_interrupt(int irq, void *dev)
+{
+	struct clock_event_device *ce = dev;
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	writel_relaxed(GX6605S_STATUS_CLR, base + TIMER_STATUS);
+
+	ce->event_handler(ce);
+
+	return IRQ_HANDLED;
+}
+
+static int gx6605s_timer_set_oneshot(struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	/* reset and stop counter */
+	writel_relaxed(GX6605S_CONTRL_RST, base + TIMER_CONTRL);
+
+	/* enable with irq and start */
+	writel_relaxed(GX6605S_CONFIG_EN | GX6605S_CONFIG_IRQ_EN, base + TIMER_CONFIG);
+
+	return 0;
+}
+
+static int gx6605s_timer_set_next_event(unsigned long delta, struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	/* use reset to pause timer */
+	writel_relaxed(GX6605S_CONTRL_RST, base + TIMER_CONTRL);
+
+	/* config next timeout value */
+	writel_relaxed(ULONG_MAX - delta, base + TIMER_INI);
+	writel_relaxed(GX6605S_CONTRL_START, base + TIMER_CONTRL);
+
+	return 0;
+}
+
+static int gx6605s_timer_shutdown(struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	writel_relaxed(0, base + TIMER_CONTRL);
+	writel_relaxed(0, base + TIMER_CONFIG);
+
+	return 0;
+}
+
+static struct timer_of to = {
+	.flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
+	.clkevt = {
+		.rating			= 300,
+		.features		= CLOCK_EVT_FEAT_DYNIRQ |
+					  CLOCK_EVT_FEAT_ONESHOT,
+		.set_state_shutdown	= gx6605s_timer_shutdown,
+		.set_state_oneshot	= gx6605s_timer_set_oneshot,
+		.set_next_event		= gx6605s_timer_set_next_event,
+		.cpumask		= cpu_possible_mask,
+	},
+	.of_irq = {
+		.handler		= gx6605s_timer_interrupt,
+		.flags			= IRQF_TIMER | IRQF_IRQPOLL,
+	},
+};
+
+static u64 notrace gx6605s_sched_clock_read(void)
+{
+	void __iomem *base;
+
+	base = timer_of_base(&to) + CLKSRC_OFFSET;
+
+	return (u64)readl_relaxed(base + TIMER_VALUE);
+}
+
+static void gx6605s_clkevt_init(void __iomem *base)
+{
+	writel_relaxed(0, base + TIMER_DIV);
+	writel_relaxed(0, base + TIMER_CONFIG);
+
+	clockevents_config_and_register(&to.clkevt, timer_of_rate(&to), 2, ULONG_MAX);
+}
+
+static int gx6605s_clksrc_init(void __iomem *base)
+{
+	writel_relaxed(0, base + TIMER_DIV);
+	writel_relaxed(0, base + TIMER_INI);
+
+	writel_relaxed(GX6605S_CONTRL_RST, base + TIMER_CONTRL);
+
+	writel_relaxed(GX6605S_CONFIG_EN, base + TIMER_CONFIG);
+
+	writel_relaxed(GX6605S_CONTRL_START, base + TIMER_CONTRL);
+
+	sched_clock_register(gx6605s_sched_clock_read, 32, timer_of_rate(&to));
+
+	return clocksource_mmio_init(base + TIMER_VALUE, "gx6605s", timer_of_rate(&to),
+				     200, 32, clocksource_mmio_readl_up);
+}
+
+static int __init gx6605s_timer_init(struct device_node *np)
+{
+	int ret;
+
+	/*
+	 * The timer driver is for nationalchip gx6605s SOC and there are two same timer
+	 * in gx6605s. We use one for clkevt and another for clksrc.
+	 *
+	 * The timer is mmio map to access, so we need give mmio addres in dts.
+	 *
+	 * It provides a 32bit countup timer and interrupt will be caused by count-overflow.
+	 * So we need set-next-event by ULONG_MAX - delta in TIMER_INI reg.
+	 *
+	 * The counter at 0x0  offset is clock event.
+	 * The counter at 0x40 offset is clock source.
+	 * They are the same in hardware, just different used by driver.
+	 */
+	ret = timer_of_init(np, &to);
+	if (ret)
+		return ret;
+
+	gx6605s_clkevt_init(timer_of_base(&to));
+
+	return gx6605s_clksrc_init(timer_of_base(&to) + CLKSRC_OFFSET);
+}
+TIMER_OF_DECLARE(csky_gx6605s_timer, "csky,gx6605s-timer", gx6605s_timer_init);
-- 
2.7.4


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

* Re: [PATCH V9 3/8] clocksource: add C-SKY SMP timer
  2018-10-01  1:35 ` [PATCH V9 3/8] clocksource: add C-SKY SMP timer Guo Ren
@ 2018-10-01  9:14   ` Daniel Lezcano
  2018-10-02  5:40     ` Guo Ren
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Lezcano @ 2018-10-01  9:14 UTC (permalink / raw)
  To: Guo Ren, tglx, jason, marc.zyngier, robh+dt, mark.rutland,
	anurup.m, Jonathan.Cameron, will.deacon, zhangshaokun, jhogan,
	paul.burton, peterz, f.fainelli, arnd
  Cc: linux-kernel, devicetree

On 01/10/2018 03:35, Guo Ren wrote:
> This timer is used by SMP system and use mfcr/mtcr instruction
> to access the regs.
> 
> Changelog:
>  - Remove #define CPUHP_AP_CSKY_TIMER_STARTING
>  - 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 | 176 +++++++++++++++++++++++++++++++++++++
>  include/linux/cpuhotplug.h         |   1 +
>  4 files changed, 186 insertions(+)
>  create mode 100644 drivers/clocksource/csky_mptimer.c
> 
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index a11f4ba..a28043f 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -620,4 +620,12 @@ config RISCV_TIMER
>  	  is accessed via both the SBI and the rdcycle instruction.  This is
>  	  required for all RISC-V systems.
>  
> +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.
> +
>  endmenu

The same rule applies here for COMPILE_TEST.

And please rename the file: timer-mp-csky.c

> 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..9dc3cfb
> --- /dev/null
> +++ b/drivers/clocksource/csky_mptimer.c
> @@ -0,0 +1,176 @@
> +// 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,
> +	},

See comment in the init function.

> +};
> +
> +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);

extra space

> +}
> +
> +static u64 clksrc_read(struct clocksource *c)
> +{
> +	return (u64) mfcr(PTIM_CCVR);

extra space

> +}
> +
> +struct clocksource csky_clocksource = {
> +	.name	= "csky",
> +	.rating	= 400,
> +	.mask	= CLOCKSOURCE_MASK(32),
> +	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
> +	.read	= clksrc_read,
> +};
> +
> +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.
> +	 */
> +

extra line

> +	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;
> +		}
> +	}


Isn't possible to replace this loop which is a bit confusing by:

 - no irq flag specified for timer-of
 - request irq before

So we end up with:

	irq = irq_of_parse_and_map(np, 0);
	if (irq <= 0)
		return -EINVAL;

	ret = request_irq(irq, csky_timer_interrupt,
			IRQF_TIMER | IRQF_PERCPU,
                        "csky_mp_timer", &csky_to));
	if (ret)
		return ret;

	for_each_possible_cpu(cpu) {
		to = per_cpu_ptr(&csky_to, cpu);
		ret = timer_of_init(np, to);
		if (ret)
			goto rollback;
	}

Alternatively, you can remove the timer_of struct and instantiate the
percpu stuff in cpuhp callbacks (cf. jcore_pit).


> +	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,
> 


-- 
 <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] 14+ messages in thread

* Re: [PATCH V9 3/8] clocksource: add C-SKY SMP timer
  2018-10-01  9:14   ` Daniel Lezcano
@ 2018-10-02  5:40     ` Guo Ren
  2018-10-02  7:59       ` Daniel Lezcano
  0 siblings, 1 reply; 14+ messages in thread
From: Guo Ren @ 2018-10-02  5:40 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: tglx, jason, marc.zyngier, robh+dt, mark.rutland, anurup.m,
	Jonathan.Cameron, will.deacon, zhangshaokun, jhogan, paul.burton,
	peterz, f.fainelli, arnd, linux-kernel, devicetree

On Mon, Oct 01, 2018 at 11:14:14AM +0200, Daniel Lezcano wrote:
> On 01/10/2018 03:35, Guo Ren wrote:
> > This timer is used by SMP system and use mfcr/mtcr instruction
> > to access the regs.
> > 
> > Changelog:
> >  - Remove #define CPUHP_AP_CSKY_TIMER_STARTING
> >  - 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 | 176 +++++++++++++++++++++++++++++++++++++
> >  include/linux/cpuhotplug.h         |   1 +
> >  4 files changed, 186 insertions(+)
> >  create mode 100644 drivers/clocksource/csky_mptimer.c
> > 
> > diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> > index a11f4ba..a28043f 100644
> > --- a/drivers/clocksource/Kconfig
> > +++ b/drivers/clocksource/Kconfig
> > @@ -620,4 +620,12 @@ config RISCV_TIMER
> >  	  is accessed via both the SBI and the rdcycle instruction.  This is
> >  	  required for all RISC-V systems.
> >  
> > +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.
> > +
> >  endmenu
> 
> The same rule applies here for COMPILE_TEST.
Ok

> And please rename the file: timer-mp-csky.c
Ok

> > +	return (u64) mfcr(PTIM_CCVR);
> 
> extra space
Ok

> 
> > +}
> > +
> > +static u64 clksrc_read(struct clocksource *c)
> > +{
> > +	return (u64) mfcr(PTIM_CCVR);
> 
> extra space
Ok

> > +	 */
> > +
> 
> extra line
Ok

> 
> > +	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;
> > +		}
> > +	}
> 
> 
> Isn't possible to replace this loop which is a bit confusing by:
> 
>  - no irq flag specified for timer-of
>  - request irq before
Ok, but I've a bit different :)
 
> So we end up with:
> 
> 	irq = irq_of_parse_and_map(np, 0);
> 	if (irq <= 0)
> 		return -EINVAL;
		panic();
I want a panic here. Return will make debug confused and directly tell
the people where is wrong. It's root-timer for us and it must bootup.

If it's a co-timer, I also think return is good.

> 
> 	ret = request_irq(irq, csky_timer_interrupt,
> 			IRQF_TIMER | IRQF_PERCPU,
>                         "csky_mp_timer", &csky_to));
	ret = request_percpu_irq(irq, csky_timer_interrupt,
			"csky_mp_timer", &csky_to);
I'll use request_percpu_irq the same as in timer_of and I've tested it's
Ok.

> 	if (ret)
> 		return ret;
Pls let me panic here.

> 
> 	for_each_possible_cpu(cpu) {
> 		to = per_cpu_ptr(&csky_to, cpu);
> 		ret = timer_of_init(np, to);
> 		if (ret)
> 			goto rollback;
		Pls let me panic here.
> 	}

Best Regards
 Guo Ren

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

* Re: [PATCH V9 3/8] clocksource: add C-SKY SMP timer
  2018-10-02  5:40     ` Guo Ren
@ 2018-10-02  7:59       ` Daniel Lezcano
  2018-10-04 16:14         ` Guo Ren
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Lezcano @ 2018-10-02  7:59 UTC (permalink / raw)
  To: Guo Ren
  Cc: tglx, jason, marc.zyngier, robh+dt, mark.rutland, anurup.m,
	Jonathan.Cameron, will.deacon, zhangshaokun, jhogan, paul.burton,
	peterz, f.fainelli, arnd, linux-kernel, devicetree

On 02/10/2018 07:40, Guo Ren wrote:
[ ... ]

>>
>> 	irq = irq_of_parse_and_map(np, 0);
>> 	if (irq <= 0)
>> 		return -EINVAL;
> 		panic();
> I want a panic here. Return will make debug confused and directly tell
> the people where is wrong. It's root-timer for us and it must bootup.
> 
> If it's a co-timer, I also think return is good.

We don't need a panic in case of failure. If the board as an alternate
timer it should be able to boot, that is the general rule of thumb for
these drivers in this directory.

The init timer functions will be called via the timer_probe() which
browse the timer_of_table (the one with all entries for the
TIMER_OF_DECLARE macros).

You can see in the code below (from timer_probe.c), there is an error
message emitted if the driver fails to initialize and another one much
stronger if no timer was initialize.

This is enough trace IMO.

void __init timer_probe(void)
{
        struct device_node *np;
        const struct of_device_id *match;
        of_init_fn_1_ret init_func_ret;
        unsigned timers = 0;
        int ret;

        for_each_matching_node_and_match(np, __timer_of_table, &match) {
                if (!of_device_is_available(np))
                        continue;

                init_func_ret = match->data;

                ret = init_func_ret(np);
                if (ret) {
                        pr_err("Failed to initialize '%pOF': %d\n", np,
ret);
                        continue;
                }

                timers++;
        }

        timers += acpi_probe_device_table(timer);

        if (!timers)
                pr_crit("%s: no matching timers found\n", __func__);
}




-- 
 <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] 14+ messages in thread

* Re: [PATCH V9 3/8] clocksource: add C-SKY SMP timer
  2018-10-02  7:59       ` Daniel Lezcano
@ 2018-10-04 16:14         ` Guo Ren
  0 siblings, 0 replies; 14+ messages in thread
From: Guo Ren @ 2018-10-04 16:14 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: tglx, jason, marc.zyngier, robh+dt, mark.rutland, anurup.m,
	Jonathan.Cameron, will.deacon, zhangshaokun, jhogan, paul.burton,
	peterz, f.fainelli, arnd, linux-kernel, devicetree

On Tue, Oct 02, 2018 at 09:59:42AM +0200, Daniel Lezcano wrote:
> On 02/10/2018 07:40, Guo Ren wrote:
> [ ... ]
> 
> >>
> >> 	irq = irq_of_parse_and_map(np, 0);
> >> 	if (irq <= 0)
> >> 		return -EINVAL;
> > 		panic();
> > I want a panic here. Return will make debug confused and directly tell
> > the people where is wrong. It's root-timer for us and it must bootup.
> > 
> > If it's a co-timer, I also think return is good.
> 
> We don't need a panic in case of failure. If the board as an alternate
> timer it should be able to boot, that is the general rule of thumb for
> these drivers in this directory.
> 
> The init timer functions will be called via the timer_probe() which
> browse the timer_of_table (the one with all entries for the
> TIMER_OF_DECLARE macros).
> 
> You can see in the code below (from timer_probe.c), there is an error
> message emitted if the driver fails to initialize and another one much
> stronger if no timer was initialize.
> 
> This is enough trace IMO.
> 
> void __init timer_probe(void)
> {
>         struct device_node *np;
>         const struct of_device_id *match;
>         of_init_fn_1_ret init_func_ret;
>         unsigned timers = 0;
>         int ret;
> 
>         for_each_matching_node_and_match(np, __timer_of_table, &match) {
>                 if (!of_device_is_available(np))
>                         continue;
> 
>                 init_func_ret = match->data;
> 
>                 ret = init_func_ret(np);
>                 if (ret) {
>                         pr_err("Failed to initialize '%pOF': %d\n", np,
> ret);
>                         continue;
>                 }
> 
>                 timers++;
Ok, let other timers boot up as possible and no panic for csky timer.

 Guo Ren

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

end of thread, other threads:[~2018-10-04 16:14 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-01  1:35 [PATCH V9 0/8] C-SKY(csky) Linux Kernel Drivers Guo Ren
2018-10-01  1:35 ` Guo Ren
2018-10-01  1:35 ` [PATCH V9 1/8] irqchip: add C-SKY SMP interrupt controller Guo Ren
2018-10-01  1:35 ` [PATCH V9 2/8] dt-bindings: interrupt-controller: C-SKY SMP intc Guo Ren
2018-10-01  1:35 ` [PATCH V9 3/8] clocksource: add C-SKY SMP timer Guo Ren
2018-10-01  9:14   ` Daniel Lezcano
2018-10-02  5:40     ` Guo Ren
2018-10-02  7:59       ` Daniel Lezcano
2018-10-04 16:14         ` Guo Ren
2018-10-01  1:35 ` [PATCH V9 4/8] dt-bindings: timer: C-SKY Multi-processor timer Guo Ren
2018-10-01  1:36 ` [PATCH V9 5/8] dt-bindings: interrupt-controller: C-SKY APB intc Guo Ren
2018-10-01  1:36 ` [PATCH V9 6/8] irqchip: add C-SKY APB bus interrupt controller Guo Ren
2018-10-01  1:36 ` [PATCH V9 7/8] dt-bindings: timer: gx6605s SOC timer Guo Ren
2018-10-01  1:36 ` [PATCH V9 8/8] clocksource: add gx6605s SOC system timer Guo Ren

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.