Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1227698 > unrolled thread

[PATCH v2 0/2] changelog

Started byOleksij Rempel <linux@rempel-privat.de>
First post2015-09-18 11:20 +0200
Last post2015-09-18 12:30 +0200
Articles 15 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/2] changelog Oleksij Rempel <linux@rempel-privat.de> - 2015-09-18 11:20 +0200
    [PATCH v2 1/2] ARM: irqchip: mxs: prepare driver for HW with different offsets Oleksij Rempel <linux@rempel-privat.de> - 2015-09-18 11:20 +0200
      Re: [PATCH v2 1/2] ARM: irqchip: mxs: prepare driver for HW with  different offsets Thomas Gleixner <tglx@linutronix.de> - 2015-09-18 12:30 +0200
    [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support Oleksij Rempel <linux@rempel-privat.de> - 2015-09-18 11:30 +0200
      Re: Possible Spam [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale  ASM9260 support Marc Zyngier <marc.zyngier@arm.com> - 2015-09-18 12:50 +0200
        Re: Possible Spam [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale  ASM9260 support Oleksij Rempel <linux@rempel-privat.de> - 2015-09-19 08:00 +0200
          Re: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support Marc Zyngier <marc.zyngier@arm.com> - 2015-09-20 13:30 +0200
            Re: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support Oleksij Rempel <linux@rempel-privat.de> - 2015-09-20 16:00 +0200
            Re: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260  support Thomas Gleixner <tglx@linutronix.de> - 2015-09-21 11:10 +0200
            [PATCH v3 0/2] Add support for ASM9260 interrupt controller Oleksij Rempel <linux@rempel-privat.de> - 2015-09-21 14:00 +0200
              [PATCH v3 2/2] ARM: irqchip: mxs: add Alphascale ASM9260 support Oleksij Rempel <linux@rempel-privat.de> - 2015-09-21 14:00 +0200
              [PATCH v3 1/2] ARM: irqchip: mxs: prepare driver for HW with different offsets Oleksij Rempel <linux@rempel-privat.de> - 2015-09-21 14:00 +0200
    [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support Oleksij Rempel <linux@rempel-privat.de> - 2015-09-18 11:50 +0200
    Re: [PATCH v2 0/2] changelog Marc Zyngier <marc.zyngier@arm.com> - 2015-09-18 12:20 +0200
    Re: [PATCH v2 0/2] changelog Thomas Gleixner <tglx@linutronix.de> - 2015-09-18 12:30 +0200

#1227698 — [PATCH v2 0/2] changelog

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-18 11:20 +0200
Subject[PATCH v2 0/2] changelog
Message-ID<q9ZZL-6Jw-5@gated-at.bofh.it>
v2:
- move some parts from patch 2 to 1
- make separate irq_chip for ICOLL and ASM9260 

Oleksij Rempel (2):
  ARM: irqchip: mxs: prepare driver for HW with different offsets
  ARM: irqchip: mxs: add Alpascale ASM9260 support

 drivers/irqchip/Kconfig                    |   5 +
 drivers/irqchip/Makefile                   |   2 +-
 drivers/irqchip/alphascale_asm9260-icoll.h | 109 +++++++++++++++++
 drivers/irqchip/irq-mxs.c                  | 188 ++++++++++++++++++++++++++---
 4 files changed, 286 insertions(+), 18 deletions(-)
 create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h

-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1227703 — [PATCH v2 1/2] ARM: irqchip: mxs: prepare driver for HW with different offsets

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-18 11:20 +0200
Subject[PATCH v2 1/2] ARM: irqchip: mxs: prepare driver for HW with different offsets
Message-ID<q9ZZM-6Jw-19@gated-at.bofh.it>
In reply to#1227698
Some HW has similar functionality but different register offsets.
Make sure we can change offsets dynamically.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 drivers/irqchip/irq-mxs.c | 83 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 67 insertions(+), 16 deletions(-)

diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 1faf812..14374de 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -28,18 +28,39 @@
 #include <linux/stmp_device.h>
 #include <asm/exception.h>
 
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+#define SET_REG 4
+#define CLR_REG 8
+
 #define HW_ICOLL_VECTOR				0x0000
 #define HW_ICOLL_LEVELACK			0x0010
 #define HW_ICOLL_CTRL				0x0020
 #define HW_ICOLL_STAT_OFFSET			0x0070
-#define HW_ICOLL_INTERRUPTn_SET(n)		(0x0124 + (n) * 0x10)
-#define HW_ICOLL_INTERRUPTn_CLR(n)		(0x0128 + (n) * 0x10)
-#define BM_ICOLL_INTERRUPTn_ENABLE		0x00000004
+#define HW_ICOLL_INTERRUPT0			0x0120
+#define HW_ICOLL_INTERRUPTn(n)			((n) * 0x10)
+#define BM_ICOLL_INTR_ENABLE			BIT(2)
 #define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0	0x1
 
 #define ICOLL_NUM_IRQS		128
 
-static void __iomem *icoll_base;
+struct icoll_priv {
+	void __iomem *vector;
+	void __iomem *levelack;
+	void __iomem *ctrl;
+	void __iomem *stat;
+	void __iomem *intr;
+	/* number of interrupts per register */
+	int intr_per_reg;
+	void __iomem *clear;
+};
+
+static struct icoll_priv icoll_priv;
 static struct irq_domain *icoll_domain;
 
 static void icoll_ack_irq(struct irq_data *d)
@@ -50,19 +71,19 @@ static void icoll_ack_irq(struct irq_data *d)
 	 * BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 unconditionally.
 	 */
 	__raw_writel(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0,
-			icoll_base + HW_ICOLL_LEVELACK);
+			icoll_priv.levelack);
 }
 
 static void icoll_mask_irq(struct irq_data *d)
 {
-	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
+	__raw_writel(BM_ICOLL_INTR_ENABLE,
+			icoll_priv.intr + CLR_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
 static void icoll_unmask_irq(struct irq_data *d)
 {
-	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
+	__raw_writel(BM_ICOLL_INTR_ENABLE,
+			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
 static struct irq_chip mxs_icoll_chip = {
@@ -75,8 +96,8 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 {
 	u32 irqnr;
 
-	irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
-	__raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
+	irqnr = __raw_readl(icoll_priv.stat);
+	__raw_writel(irqnr, icoll_priv.vector);
 	handle_domain_irq(icoll_domain, irqnr, regs);
 }
 
@@ -94,20 +115,50 @@ static const struct irq_domain_ops icoll_irq_domain_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
 
+static void __init icoll_add_domain(struct device_node *np,
+			  int num)
+{
+	icoll_domain = irq_domain_add_linear(np, num,
+					     &icoll_irq_domain_ops, NULL);
+
+	if (!icoll_domain)
+		panic("%s: unable add irq domain", np->full_name);
+	irq_set_default_host(icoll_domain);
+	set_handle_irq(icoll_handle_irq);
+}
+
+static void __iomem * __init icoll_init_iobase(struct device_node *np)
+{
+	void __iomem *icoll_base;
+
+	icoll_base = of_io_request_and_map(np, 0, np->name);
+	if (!icoll_base)
+		panic("%s: unable to map resource", np->full_name);
+	return icoll_base;
+}
+
 static int __init icoll_of_init(struct device_node *np,
 			  struct device_node *interrupt_parent)
 {
-	icoll_base = of_iomap(np, 0);
-	WARN_ON(!icoll_base);
+	void __iomem *icoll_base;
+
+	icoll_base		= icoll_init_iobase(np);
+	icoll_priv.vector	= icoll_base + HW_ICOLL_VECTOR;
+	icoll_priv.levelack	= icoll_base + HW_ICOLL_LEVELACK;
+	icoll_priv.ctrl		= icoll_base + HW_ICOLL_CTRL;
+	icoll_priv.stat		= icoll_base + HW_ICOLL_STAT_OFFSET;
+	icoll_priv.intr		= icoll_base + HW_ICOLL_INTERRUPT0;
+	icoll_priv.intr_per_reg	= 1;
+	icoll_priv.clear	= NULL;
 
 	/*
 	 * Interrupt Collector reset, which initializes the priority
 	 * for each irq to level 0.
 	 */
-	stmp_reset_block(icoll_base + HW_ICOLL_CTRL);
+	stmp_reset_block(icoll_priv.ctrl);
+
+	icoll_add_domain(np, ICOLL_NUM_IRQS);
 
-	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
-					     &icoll_irq_domain_ops, NULL);
 	return icoll_domain ? 0 : -ENODEV;
 }
 IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1227751 — Re: [PATCH v2 1/2] ARM: irqchip: mxs: prepare driver for HW with different offsets

FromThomas Gleixner <tglx@linutronix.de>
Date2015-09-18 12:30 +0200
SubjectRe: [PATCH v2 1/2] ARM: irqchip: mxs: prepare driver for HW with different offsets
Message-ID<qa15x-8i7-27@gated-at.bofh.it>
In reply to#1227703
On Fri, 18 Sep 2015, Oleksij Rempel wrote:

> Some HW has similar functionality but different register offsets.
> Make sure we can change offsets dynamically.

You forgot to mention the other preparatory changes.

Thanks,

	tglx
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1227709 — [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-18 11:30 +0200
Subject[PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support
Message-ID<qa09s-6UG-17@gated-at.bofh.it>
In reply to#1227698
From: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>

Freescale iMX23/iMX28 and Alphascale ASM9260 have similar
interrupt collectors. It makes easy to reuse irq-mxs code for ASM9260.
Differences between this devices are fallowing:
- different register offsets
- different count of intterupt lines per register
- ASM9260 don't provide reset bit
- ASM9260 don't support FIQ.

Signed-off-by: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>
---
 drivers/irqchip/Kconfig                    |   5 ++
 drivers/irqchip/Makefile                   |   2 +-
 drivers/irqchip/alphascale_asm9260-icoll.h | 109 +++++++++++++++++++++++++++++
 drivers/irqchip/irq-mxs.c                  | 106 +++++++++++++++++++++++++++-
 4 files changed, 220 insertions(+), 2 deletions(-)
 create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 27b52c8..0dfd840 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -187,3 +187,8 @@ config IMX_GPCV2
 	select IRQ_DOMAIN
 	help
 	  Enables the wakeup IRQs for IMX platforms with GPCv2 block
+
+config IRQ_MXS
+	def_bool y if MACH_ASM9260 || ARCH_MXS
+	select IRQ_DOMAIN
+	select STMP_DEVICE
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index bb3048f..177f78f 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
 obj-$(CONFIG_ARCH_HIP04)		+= irq-hip04.o
 obj-$(CONFIG_ARCH_MMP)			+= irq-mmp.o
 obj-$(CONFIG_ARCH_MVEBU)		+= irq-armada-370-xp.o
-obj-$(CONFIG_ARCH_MXS)			+= irq-mxs.o
+obj-$(CONFIG_IRQ_MXS)			+= irq-mxs.o
 obj-$(CONFIG_ARCH_TEGRA)		+= irq-tegra.o
 obj-$(CONFIG_ARCH_S3C24XX)		+= irq-s3c24xx.o
 obj-$(CONFIG_DW_APB_ICTL)		+= irq-dw-apb-ictl.o
diff --git a/drivers/irqchip/alphascale_asm9260-icoll.h b/drivers/irqchip/alphascale_asm9260-icoll.h
new file mode 100644
index 0000000..5cec108
--- /dev/null
+++ b/drivers/irqchip/alphascale_asm9260-icoll.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _ALPHASCALE_ASM9260_ICOLL_H
+#define _ALPHASCALE_ASM9260_ICOLL_H
+
+#define ASM9260_NUM_IRQS		64
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+
+#define ASM9260_HW_ICOLL_VECTOR				0x0000
+/*
+ * bits 31:2
+ * This register presents the vector address for the interrupt currently
+ * active on the CPU IRQ input. Writing to this register notifies the
+ * interrupt collector that the interrupt service routine for the current
+ * interrupt has been entered.
+ * The exception trap should have a LDPC instruction from this address:
+ * LDPC ASM9260_HW_ICOLL_VECTOR_ADDR; IRQ exception at 0xffff0018
+ */
+
+/*
+ * The Interrupt Collector Level Acknowledge Register is used by software to
+ * indicate the completion of an interrupt on a specific level.
+ * This register is written at the very end of an interrupt service routine. If
+ * nesting is used then the CPU irq must be turned on before writing to this
+ * register to avoid a race condition in the CPU interrupt hardware.
+ */
+#define ASM9260_HW_ICOLL_LEVELACK			0x0010
+#define ASM9260_BM_LEVELn(nr)				BIT(nr)
+
+#define ASM9260_HW_ICOLL_CTRL				0x0020
+/*
+ * ASM9260_BM_CTRL_SFTRST and ASM9260_BM_CTRL_CLKGATE are not available on
+ * asm9260.
+ */
+#define ASM9260_BM_CTRL_SFTRST				BIT(31)
+#define ASM9260_BM_CTRL_CLKGATE				BIT(30)
+/* disable interrupt level nesting */
+#define ASM9260_BM_CTRL_NO_NESTING			BIT(19)
+/*
+ * Set this bit to one enable the RISC32-style read side effect associated with
+ * the vector address register. In this mode, interrupt in-service is signaled
+ * by the read of the ASM9260_HW_ICOLL_VECTOR register to acquire the interrupt
+ * vector address. Set this bit to zero for normal operation, in which the ISR
+ * signals in-service explicitly by means of a write to the
+ * ASM9260_HW_ICOLL_VECTOR register.
+ * 0 - Must Write to Vector register to go in-service.
+ * 1 - Go in-service as a read side effect
+ */
+#define ASM9260_BM_CTRL_ARM_RSE_MODE			BIT(18)
+#define ASM9260_BM_CTRL_IRQ_ENABLE			BIT(16)
+
+#define ASM9260_HW_ICOLL_STAT_OFFSET			0x0030
+/*
+ * bits 5:0
+ * Vector number of current interrupt. Multiply by 4 and add to vector base
+ * address to obtain the value in ASM9260_HW_ICOLL_VECTOR.
+ */
+
+/*
+ * RAW0 and RAW1 provides a read-only view of the raw interrupt request lines
+ * coming from various parts of the chip. Its purpose is to improve diagnostic
+ * observability.
+ */
+#define ASM9260_HW_ICOLL_RAW0				0x0040
+#define ASM9260_HW_ICOLL_RAW1				0x0050
+
+#define ASM9260_HW_ICOLL_INTERRUPT0			0x0060
+#define ASM9260_HW_ICOLL_INTERRUPTn(n)		(0x0060 + ((n) >> 2) * 0x10)
+/*
+ * WARNING: Modifying the priority of an enabled interrupt may result in
+ * undefined behavior.
+ */
+#define ASM9260_BM_INT_PRIORITY_MASK			0x3
+#define ASM9260_BM_INT_ENABLE				BIT(2)
+#define ASM9260_BM_INT_SOFTIRQ				BIT(3)
+
+#define ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)		(((n) & 0x3) << 3)
+#define ASM9260_BM_ICOLL_INTERRUPTn_ENABLE(n)		(1 << (2 + \
+			ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)))
+
+#define ASM9260_HW_ICOLL_VBASE				0x0160
+/*
+ * bits 31:2
+ * This bitfield holds the upper 30 bits of the base address of the vector
+ * table.
+ */
+
+#define ASM9260_HW_ICOLL_CLEAR0				0x01d0
+#define ASM9260_HW_ICOLL_CLEAR1				0x01e0
+#define ASM9260_HW_ICOLL_CLEARn(n)			(((n >> 5) * 0x10) \
+							+ SET_REG)
+#define ASM9260_BM_CLEAR_BIT(n)				BIT(n & 0x1f)
+
+/* Scratchpad */
+#define ASM9260_HW_ICOLL_UNDEF_VECTOR			0x01f0
+#endif
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 14374de..1470087 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *	Add Alphascale ASM9260 support.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,6 +30,8 @@
 #include <linux/stmp_device.h>
 #include <asm/exception.h>
 
+#include "alphascale_asm9260-icoll.h"
+
 /*
  * this device provide 4 offsets for each register:
  * 0x0 - plain read write mode
@@ -49,6 +53,11 @@
 
 #define ICOLL_NUM_IRQS		128
 
+enum icoll_type {
+	ICOLL,
+	ASM9260_ICOLL,
+};
+
 struct icoll_priv {
 	void __iomem *vector;
 	void __iomem *levelack;
@@ -58,10 +67,38 @@ struct icoll_priv {
 	/* number of interrupts per register */
 	int intr_per_reg;
 	void __iomem *clear;
+	enum icoll_type type;
 };
 
 static struct icoll_priv icoll_priv;
 static struct irq_domain *icoll_domain;
+static DEFINE_RAW_SPINLOCK(icoll_lock);
+
+/* calculate bit offset depending on number of intterupt per register */
+static u32 icoll_intr_bitshift(struct irq_data *d, u32 bit)
+{
+	/*
+	 * We expect intr_per_reg to be 4 or 1, it means
+	 * "n" will be 3 or 0.
+	 */
+	int n = icoll_priv.intr_per_reg - 1;
+
+	/*
+	 * If n = 0, "bit" is never shifted.
+	 * If n = 3, mask lower part of hwirq to convert it
+	 * in 0, 1, 2 or 3 and then multiply it by 8 (or shift by 3)
+	 */
+	return bit << ((d->hwirq & n) << n);
+}
+
+/* calculate mem offset depending on number of intterupt per register */
+static void __iomem *icoll_intr_reg(struct irq_data *d)
+{
+	int n = icoll_priv.intr_per_reg >> 1;
+
+	/* offset = hwirq / intr_per_reg * 0x10 */
+	return icoll_priv.intr + ((d->hwirq >> n) * 0x10);
+}
 
 static void icoll_ack_irq(struct irq_data *d)
 {
@@ -86,12 +123,38 @@ static void icoll_unmask_irq(struct irq_data *d)
 			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
+static void asm9260_mask_irq(struct irq_data *d)
+{
+	raw_spin_lock(&icoll_lock);
+	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+			icoll_intr_reg(d) + CLR_REG);
+	raw_spin_unlock(&icoll_lock);
+}
+
+static void asm9260_unmask_irq(struct irq_data *d)
+{
+	raw_spin_lock(&icoll_lock);
+	__raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
+		     icoll_priv.clear +
+		     ASM9260_HW_ICOLL_CLEARn(d->hwirq));
+
+	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+			icoll_intr_reg(d) + SET_REG);
+	raw_spin_unlock(&icoll_lock);
+}
+
 static struct irq_chip mxs_icoll_chip = {
 	.irq_ack = icoll_ack_irq,
 	.irq_mask = icoll_mask_irq,
 	.irq_unmask = icoll_unmask_irq,
 };
 
+static struct irq_chip asm9260_icoll_chip = {
+	.irq_ack = icoll_ack_irq,
+	.irq_mask = asm9260_mask_irq,
+	.irq_unmask = asm9260_unmask_irq,
+};
+
 asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 {
 	u32 irqnr;
@@ -104,7 +167,14 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
 				irq_hw_number_t hw)
 {
-	irq_set_chip_and_handler(virq, &mxs_icoll_chip, handle_level_irq);
+	struct irq_chip *chip;
+
+	if (icoll_priv.type == ICOLL)
+		chip = &mxs_icoll_chip;
+	else
+		chip = &asm9260_icoll_chip;
+
+	irq_set_chip_and_handler(virq, chip, handle_level_irq);
 	set_irq_flags(virq, IRQF_VALID);
 
 	return 0;
@@ -142,6 +212,8 @@ static int __init icoll_of_init(struct device_node *np,
 {
 	void __iomem *icoll_base;
 
+	icoll_priv.type = ICOLL;
+
 	icoll_base		= icoll_init_iobase(np);
 	icoll_priv.vector	= icoll_base + HW_ICOLL_VECTOR;
 	icoll_priv.levelack	= icoll_base + HW_ICOLL_LEVELACK;
@@ -162,3 +234,35 @@ static int __init icoll_of_init(struct device_node *np,
 	return icoll_domain ? 0 : -ENODEV;
 }
 IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
+
+static int __init asm9260_of_init(struct device_node *np,
+			  struct device_node *interrupt_parent)
+{
+	void __iomem *icoll_base;
+	int i;
+
+	icoll_priv.type = ASM9260_ICOLL;
+
+	icoll_base = icoll_init_iobase(np);
+	icoll_priv.vector	= icoll_base + ASM9260_HW_ICOLL_VECTOR;
+	icoll_priv.levelack	= icoll_base + ASM9260_HW_ICOLL_LEVELACK;
+	icoll_priv.ctrl		= icoll_base + ASM9260_HW_ICOLL_CTRL;
+	icoll_priv.stat		= icoll_base + ASM9260_HW_ICOLL_STAT_OFFSET;
+	icoll_priv.intr		= icoll_base + ASM9260_HW_ICOLL_INTERRUPT0;
+	icoll_priv.intr_per_reg	= 4;
+	icoll_priv.clear	= icoll_base + ASM9260_HW_ICOLL_CLEAR0;
+
+	writel_relaxed(ASM9260_BM_CTRL_IRQ_ENABLE,
+			icoll_priv.ctrl);
+	/*
+	 * ASM9260 don't provide reset bit. So, we need to set level 0
+	 * manually.
+	 */
+	for (i = 0; i < 16 * 0x10; i += 0x10)
+		writel(0, icoll_priv.intr + i);
+
+	icoll_add_domain(np, ASM9260_NUM_IRQS);
+
+	return icoll_domain ? 0 : -ENODEV;
+}
+IRQCHIP_DECLARE(asm9260, "alphascale,asm9260-icoll", asm9260_of_init);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1227762 — Re: Possible Spam [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support

FromMarc Zyngier <marc.zyngier@arm.com>
Date2015-09-18 12:50 +0200
SubjectRe: Possible Spam [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support
Message-ID<qa1oS-cV-13@gated-at.bofh.it>
In reply to#1227709
On Fri, 18 Sep 2015 11:18:42 +0200
Oleksij Rempel <linux@rempel-privat.de> wrote:

> From: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>
> 
> Freescale iMX23/iMX28 and Alphascale ASM9260 have similar

Is it Alphascale or Alpascale? You may need to fix the patch title.

> interrupt collectors. It makes easy to reuse irq-mxs code for ASM9260.
> Differences between this devices are fallowing:
> - different register offsets
> - different count of intterupt lines per register
> - ASM9260 don't provide reset bit
> - ASM9260 don't support FIQ.
> 
> Signed-off-by: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>
> ---
>  drivers/irqchip/Kconfig                    |   5 ++
>  drivers/irqchip/Makefile                   |   2 +-
>  drivers/irqchip/alphascale_asm9260-icoll.h | 109 +++++++++++++++++++++++++++++
>  drivers/irqchip/irq-mxs.c                  | 106 +++++++++++++++++++++++++++-
>  4 files changed, 220 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h
> 

[...]

> diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
> index 14374de..1470087 100644
> --- a/drivers/irqchip/irq-mxs.c
> +++ b/drivers/irqchip/irq-mxs.c
> @@ -1,5 +1,7 @@
>  /*
>   * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
> + * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
> + *	Add Alphascale ASM9260 support.
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License as published by
> @@ -28,6 +30,8 @@
>  #include <linux/stmp_device.h>
>  #include <asm/exception.h>
>  
> +#include "alphascale_asm9260-icoll.h"
> +
>  /*
>   * this device provide 4 offsets for each register:
>   * 0x0 - plain read write mode
> @@ -49,6 +53,11 @@
>  
>  #define ICOLL_NUM_IRQS		128
>  
> +enum icoll_type {
> +	ICOLL,
> +	ASM9260_ICOLL,
> +};
> +
>  struct icoll_priv {
>  	void __iomem *vector;
>  	void __iomem *levelack;
> @@ -58,10 +67,38 @@ struct icoll_priv {
>  	/* number of interrupts per register */
>  	int ;
>  	void __iomem *clear;
> +	enum icoll_type type;
>  };
>  
>  static struct icoll_priv icoll_priv;
>  static struct irq_domain *icoll_domain;
> +static DEFINE_RAW_SPINLOCK(icoll_lock);
> +
> +/* calculate bit offset depending on number of intterupt per register */
> +static u32 icoll_intr_bitshift(struct irq_data *d, u32 bit)
> +{
> +	/*
> +	 * We expect intr_per_reg to be 4 or 1, it means
> +	 * "n" will be 3 or 0.
> +	 */
> +	int n = icoll_priv.intr_per_reg - 1;
> +
> +	/*
> +	 * If n = 0, "bit" is never shifted.
> +	 * If n = 3, mask lower part of hwirq to convert it
> +	 * in 0, 1, 2 or 3 and then multiply it by 8 (or shift by 3)
> +	 */
> +	return bit << ((d->hwirq & n) << n);
> +}
> +
> +/* calculate mem offset depending on number of intterupt per register */
> +static void __iomem *icoll_intr_reg(struct irq_data *d)
> +{
> +	int n = icoll_priv.intr_per_reg >> 1;
> +
> +	/* offset = hwirq / intr_per_reg * 0x10 */
> +	return icoll_priv.intr + ((d->hwirq >> n) * 0x10);
> +}

Please correct me if I'm wrong, but it looks like these function are
only useful when used on ams9260. So why do we need intr_per_reg at
all? MXS doesn't need it (always 1), and ams9260 always need it (always
4). Save yourself some previous cycles and simplify the whole thing.

>  
>  static void icoll_ack_irq(struct irq_data *d)
>  {
> @@ -86,12 +123,38 @@ static void icoll_unmask_irq(struct irq_data *d)
>  			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
>  }
>  
> +static void asm9260_mask_irq(struct irq_data *d)
> +{
> +	raw_spin_lock(&icoll_lock);
> +	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
> +			icoll_intr_reg(d) + CLR_REG);
> +	raw_spin_unlock(&icoll_lock);
> +}
> +
> +static void asm9260_unmask_irq(struct irq_data *d)
> +{
> +	raw_spin_lock(&icoll_lock);
> +	__raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
> +		     icoll_priv.clear +
> +		     ASM9260_HW_ICOLL_CLEARn(d->hwirq));
> +
> +	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
> +			icoll_intr_reg(d) + SET_REG);
> +	raw_spin_unlock(&icoll_lock);
> +}

Can you please explain the rational for this lock? mask/unmask use
different registers, and it is not obvious to me what race you are
trying to avoid here.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1228401 — Re: Possible Spam [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-19 08:00 +0200
SubjectRe: Possible Spam [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support
Message-ID<qajlM-Pt-5@gated-at.bofh.it>
In reply to#1227762

[Multipart message — attachments visible in raw view] — view raw

Am 18.09.2015 um 12:42 schrieb Marc Zyngier:
> On Fri, 18 Sep 2015 11:18:42 +0200
> Oleksij Rempel <linux@rempel-privat.de> wrote:
> 
>> From: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>
>>
>> Freescale iMX23/iMX28 and Alphascale ASM9260 have similar
> 
> Is it Alphascale or Alpascale? You may need to fix the patch title.

ok.

> 
>> interrupt collectors. It makes easy to reuse irq-mxs code for ASM9260.
>> Differences between this devices are fallowing:
>> - different register offsets
>> - different count of intterupt lines per register
>> - ASM9260 don't provide reset bit
>> - ASM9260 don't support FIQ.
>>
>> Signed-off-by: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>
>> ---
>>  drivers/irqchip/Kconfig                    |   5 ++
>>  drivers/irqchip/Makefile                   |   2 +-
>>  drivers/irqchip/alphascale_asm9260-icoll.h | 109 +++++++++++++++++++++++++++++
>>  drivers/irqchip/irq-mxs.c                  | 106 +++++++++++++++++++++++++++-
>>  4 files changed, 220 insertions(+), 2 deletions(-)
>>  create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h
>>
> 
> [...]
> 
>> diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
>> index 14374de..1470087 100644
>> --- a/drivers/irqchip/irq-mxs.c
>> +++ b/drivers/irqchip/irq-mxs.c
>> @@ -1,5 +1,7 @@
>>  /*
>>   * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
>> + * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
>> + *	Add Alphascale ASM9260 support.
>>   *
>>   * This program is free software; you can redistribute it and/or modify
>>   * it under the terms of the GNU General Public License as published by
>> @@ -28,6 +30,8 @@
>>  #include <linux/stmp_device.h>
>>  #include <asm/exception.h>
>>  
>> +#include "alphascale_asm9260-icoll.h"
>> +
>>  /*
>>   * this device provide 4 offsets for each register:
>>   * 0x0 - plain read write mode
>> @@ -49,6 +53,11 @@
>>  
>>  #define ICOLL_NUM_IRQS		128
>>  
>> +enum icoll_type {
>> +	ICOLL,
>> +	ASM9260_ICOLL,
>> +};
>> +
>>  struct icoll_priv {
>>  	void __iomem *vector;
>>  	void __iomem *levelack;
>> @@ -58,10 +67,38 @@ struct icoll_priv {
>>  	/* number of interrupts per register */
>>  	int ;
>>  	void __iomem *clear;
>> +	enum icoll_type type;
>>  };
>>  
>>  static struct icoll_priv icoll_priv;
>>  static struct irq_domain *icoll_domain;
>> +static DEFINE_RAW_SPINLOCK(icoll_lock);
>> +
>> +/* calculate bit offset depending on number of intterupt per register */
>> +static u32 icoll_intr_bitshift(struct irq_data *d, u32 bit)
>> +{
>> +	/*
>> +	 * We expect intr_per_reg to be 4 or 1, it means
>> +	 * "n" will be 3 or 0.
>> +	 */
>> +	int n = icoll_priv.intr_per_reg - 1;
>> +
>> +	/*
>> +	 * If n = 0, "bit" is never shifted.
>> +	 * If n = 3, mask lower part of hwirq to convert it
>> +	 * in 0, 1, 2 or 3 and then multiply it by 8 (or shift by 3)
>> +	 */
>> +	return bit << ((d->hwirq & n) << n);
>> +}
>> +
>> +/* calculate mem offset depending on number of intterupt per register */
>> +static void __iomem *icoll_intr_reg(struct irq_data *d)
>> +{
>> +	int n = icoll_priv.intr_per_reg >> 1;
>> +
>> +	/* offset = hwirq / intr_per_reg * 0x10 */
>> +	return icoll_priv.intr + ((d->hwirq >> n) * 0x10);
>> +}
> 
> Please correct me if I'm wrong, but it looks like these function are
> only useful when used on ams9260. So why do we need intr_per_reg at
> all? MXS doesn't need it (always 1), and ams9260 always need it (always
> 4). Save yourself some previous cycles and simplify the whole thing.

ok.

>>  
>>  static void icoll_ack_irq(struct irq_data *d)
>>  {
>> @@ -86,12 +123,38 @@ static void icoll_unmask_irq(struct irq_data *d)
>>  			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
>>  }
>>  
>> +static void asm9260_mask_irq(struct irq_data *d)
>> +{
>> +	raw_spin_lock(&icoll_lock);
>> +	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
>> +			icoll_intr_reg(d) + CLR_REG);
>> +	raw_spin_unlock(&icoll_lock);
>> +}
>> +
>> +static void asm9260_unmask_irq(struct irq_data *d)
>> +{
>> +	raw_spin_lock(&icoll_lock);
>> +	__raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
>> +		     icoll_priv.clear +
>> +		     ASM9260_HW_ICOLL_CLEARn(d->hwirq));
>> +
>> +	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
>> +			icoll_intr_reg(d) + SET_REG);
>> +	raw_spin_unlock(&icoll_lock);
>> +}
> 
> Can you please explain the rational for this lock? mask/unmask use
> different registers, and it is not obvious to me what race you are
> trying to avoid here.

Uff... in one of earliest reviews i was asked to add lock..
I also was asked to add asm9260 to some existing driver. Not sure if it
is still making sense.

-- 
Regards,
Oleksij

[toc] | [prev] | [next] | [standalone]


#1228870 — Re: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support

FromMarc Zyngier <marc.zyngier@arm.com>
Date2015-09-20 13:30 +0200
SubjectRe: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support
Message-ID<qaKYF-6RH-3@gated-at.bofh.it>
In reply to#1228401
On Sat, 19 Sep 2015 07:53:34 +0200
Oleksij Rempel <linux@rempel-privat.de> wrote:

> Am 18.09.2015 um 12:42 schrieb Marc Zyngier:
> > On Fri, 18 Sep 2015 11:18:42 +0200
> > Oleksij Rempel <linux@rempel-privat.de> wrote:
>

[...]

> >> +static void asm9260_mask_irq(struct irq_data *d)
> >> +{
> >> +	raw_spin_lock(&icoll_lock);
> >> +	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
> >> +			icoll_intr_reg(d) + CLR_REG);
> >> +	raw_spin_unlock(&icoll_lock);
> >> +}
> >> +
> >> +static void asm9260_unmask_irq(struct irq_data *d)
> >> +{
> >> +	raw_spin_lock(&icoll_lock);
> >> +	__raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
> >> +		     icoll_priv.clear +
> >> +		     ASM9260_HW_ICOLL_CLEARn(d->hwirq));
> >> +
> >> +	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
> >> +			icoll_intr_reg(d) + SET_REG);
> >> +	raw_spin_unlock(&icoll_lock);
> >> +}
> > 
> > Can you please explain the rational for this lock? mask/unmask use
> > different registers, and it is not obvious to me what race you are
> > trying to avoid here.
> 
> Uff... in one of earliest reviews i was asked to add lock..
> I also was asked to add asm9260 to some existing driver. Not sure if it
> is still making sense.

Adding or removing a lock is not about what people ask you to do. It is
about requirements dictated by either the HW (you need to perform
a given sequence atomically with respect to another code sequence), the
kernel, or both. So I'd like to understand what is the underlying
reason for this lock. It is not disabling interrupts, so it could end
up being called in an interrupt context -> deadlock.

So either the HW requires it and you have the wrong accessors, or it
doesn't, and you can remove it. Either way, we need to know.

	M.
-- 
Jazz is not dead. It just smells funny.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1228888 — Re: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-20 16:00 +0200
SubjectRe: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support
Message-ID<qaNjQ-1Dx-21@gated-at.bofh.it>
In reply to#1228870

[Multipart message — attachments visible in raw view] — view raw

Am 20.09.2015 um 13:28 schrieb Marc Zyngier:
> On Sat, 19 Sep 2015 07:53:34 +0200
> Oleksij Rempel <linux@rempel-privat.de> wrote:
> 
>> Am 18.09.2015 um 12:42 schrieb Marc Zyngier:
>>> On Fri, 18 Sep 2015 11:18:42 +0200
>>> Oleksij Rempel <linux@rempel-privat.de> wrote:
>>
> 
> [...]
> 
>>>> +static void asm9260_mask_irq(struct irq_data *d)
>>>> +{
>>>> +	raw_spin_lock(&icoll_lock);
>>>> +	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
>>>> +			icoll_intr_reg(d) + CLR_REG);
>>>> +	raw_spin_unlock(&icoll_lock);
>>>> +}
>>>> +
>>>> +static void asm9260_unmask_irq(struct irq_data *d)
>>>> +{
>>>> +	raw_spin_lock(&icoll_lock);
>>>> +	__raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
>>>> +		     icoll_priv.clear +
>>>> +		     ASM9260_HW_ICOLL_CLEARn(d->hwirq));
>>>> +
>>>> +	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
>>>> +			icoll_intr_reg(d) + SET_REG);
>>>> +	raw_spin_unlock(&icoll_lock);
>>>> +}
>>>
>>> Can you please explain the rational for this lock? mask/unmask use
>>> different registers, and it is not obvious to me what race you are
>>> trying to avoid here.
>>
>> Uff... in one of earliest reviews i was asked to add lock..
>> I also was asked to add asm9260 to some existing driver. Not sure if it
>> is still making sense.
> 
> Adding or removing a lock is not about what people ask you to do. It is
> about requirements dictated by either the HW (you need to perform
> a given sequence atomically with respect to another code sequence), the
> kernel, or both. So I'd like to understand what is the underlying
> reason for this lock. It is not disabling interrupts, so it could end
> up being called in an interrupt context -> deadlock.

You right.

> So either the HW requires it and you have the wrong accessors, or it
> doesn't, and you can remove it. Either way, we need to know.
> 
> 	M.

I don't see any need to lock it.

-- 
Regards,
Oleksij

[toc] | [prev] | [next] | [standalone]


#1229132 — Re: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support

FromThomas Gleixner <tglx@linutronix.de>
Date2015-09-21 11:10 +0200
SubjectRe: [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support
Message-ID<qb5gL-297-17@gated-at.bofh.it>
In reply to#1228870
On Sun, 20 Sep 2015, Marc Zyngier wrote:
> > Uff... in one of earliest reviews i was asked to add lock..
> > I also was asked to add asm9260 to some existing driver. Not sure if it
> > is still making sense.
> 
> Adding or removing a lock is not about what people ask you to do. It is
> about requirements dictated by either the HW (you need to perform
> a given sequence atomically with respect to another code sequence), the
> kernel, or both. So I'd like to understand what is the underlying
> reason for this lock. It is not disabling interrupts, so it could end
> up being called in an interrupt context -> deadlock.

The callback is always called with interrupts disabled, so that's a
non issue. But still, the rationale for that lock is unclear.

Thanks,

	tglx

 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1229236 — [PATCH v3 0/2] Add support for ASM9260 interrupt controller

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-21 14:00 +0200
Subject[PATCH v3 0/2] Add support for ASM9260 interrupt controller
Message-ID<qb7Vf-5JD-7@gated-at.bofh.it>
In reply to#1228870
v2:
- move icoll_init_iobasea and icoll_add_domain to preparation patch
- add enum icoll_type
- make separate irq_chip for ICOLL and ASM9260 

v3:
- fix typo in subject: Alp_h_ascale
- remove "intr_per_reg", it is not used any more. It will also
	save some CPU cycles
- remove spin locks. It was a bad idea.

Oleksij Rempel (2):
  ARM: irqchip: mxs: prepare driver for HW with different offsets
  ARM: irqchip: mxs: add Alphascale ASM9260 support

 drivers/irqchip/Kconfig                    |   5 +
 drivers/irqchip/Makefile                   |   2 +-
 drivers/irqchip/alphascale_asm9260-icoll.h | 109 ++++++++++++++++++
 drivers/irqchip/irq-mxs.c                  | 171 ++++++++++++++++++++++++++---
 4 files changed, 269 insertions(+), 18 deletions(-)
 create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h

-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1229237 — [PATCH v3 2/2] ARM: irqchip: mxs: add Alphascale ASM9260 support

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-21 14:00 +0200
Subject[PATCH v3 2/2] ARM: irqchip: mxs: add Alphascale ASM9260 support
Message-ID<qb7Vf-5JD-9@gated-at.bofh.it>
In reply to#1229236
From: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>

Freescale iMX23/iMX28 and Alphascale ASM9260 have similar
interrupt collectors. It makes easy to reuse irq-mxs code for ASM9260.
Differences between this devices are fallowing:
- different register offsets
- different count of intterupt lines per register
- ASM9260 don't provide reset bit
- ASM9260 don't support FIQ.

Signed-off-by: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>
---
 drivers/irqchip/Kconfig                    |   5 ++
 drivers/irqchip/Makefile                   |   2 +-
 drivers/irqchip/alphascale_asm9260-icoll.h | 109 +++++++++++++++++++++++++++++
 drivers/irqchip/irq-mxs.c                  |  94 +++++++++++++++++++++++--
 4 files changed, 205 insertions(+), 5 deletions(-)
 create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 27b52c8..0dfd840 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -187,3 +187,8 @@ config IMX_GPCV2
 	select IRQ_DOMAIN
 	help
 	  Enables the wakeup IRQs for IMX platforms with GPCv2 block
+
+config IRQ_MXS
+	def_bool y if MACH_ASM9260 || ARCH_MXS
+	select IRQ_DOMAIN
+	select STMP_DEVICE
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index bb3048f..177f78f 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
 obj-$(CONFIG_ARCH_HIP04)		+= irq-hip04.o
 obj-$(CONFIG_ARCH_MMP)			+= irq-mmp.o
 obj-$(CONFIG_ARCH_MVEBU)		+= irq-armada-370-xp.o
-obj-$(CONFIG_ARCH_MXS)			+= irq-mxs.o
+obj-$(CONFIG_IRQ_MXS)			+= irq-mxs.o
 obj-$(CONFIG_ARCH_TEGRA)		+= irq-tegra.o
 obj-$(CONFIG_ARCH_S3C24XX)		+= irq-s3c24xx.o
 obj-$(CONFIG_DW_APB_ICTL)		+= irq-dw-apb-ictl.o
diff --git a/drivers/irqchip/alphascale_asm9260-icoll.h b/drivers/irqchip/alphascale_asm9260-icoll.h
new file mode 100644
index 0000000..5cec108
--- /dev/null
+++ b/drivers/irqchip/alphascale_asm9260-icoll.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _ALPHASCALE_ASM9260_ICOLL_H
+#define _ALPHASCALE_ASM9260_ICOLL_H
+
+#define ASM9260_NUM_IRQS		64
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+
+#define ASM9260_HW_ICOLL_VECTOR				0x0000
+/*
+ * bits 31:2
+ * This register presents the vector address for the interrupt currently
+ * active on the CPU IRQ input. Writing to this register notifies the
+ * interrupt collector that the interrupt service routine for the current
+ * interrupt has been entered.
+ * The exception trap should have a LDPC instruction from this address:
+ * LDPC ASM9260_HW_ICOLL_VECTOR_ADDR; IRQ exception at 0xffff0018
+ */
+
+/*
+ * The Interrupt Collector Level Acknowledge Register is used by software to
+ * indicate the completion of an interrupt on a specific level.
+ * This register is written at the very end of an interrupt service routine. If
+ * nesting is used then the CPU irq must be turned on before writing to this
+ * register to avoid a race condition in the CPU interrupt hardware.
+ */
+#define ASM9260_HW_ICOLL_LEVELACK			0x0010
+#define ASM9260_BM_LEVELn(nr)				BIT(nr)
+
+#define ASM9260_HW_ICOLL_CTRL				0x0020
+/*
+ * ASM9260_BM_CTRL_SFTRST and ASM9260_BM_CTRL_CLKGATE are not available on
+ * asm9260.
+ */
+#define ASM9260_BM_CTRL_SFTRST				BIT(31)
+#define ASM9260_BM_CTRL_CLKGATE				BIT(30)
+/* disable interrupt level nesting */
+#define ASM9260_BM_CTRL_NO_NESTING			BIT(19)
+/*
+ * Set this bit to one enable the RISC32-style read side effect associated with
+ * the vector address register. In this mode, interrupt in-service is signaled
+ * by the read of the ASM9260_HW_ICOLL_VECTOR register to acquire the interrupt
+ * vector address. Set this bit to zero for normal operation, in which the ISR
+ * signals in-service explicitly by means of a write to the
+ * ASM9260_HW_ICOLL_VECTOR register.
+ * 0 - Must Write to Vector register to go in-service.
+ * 1 - Go in-service as a read side effect
+ */
+#define ASM9260_BM_CTRL_ARM_RSE_MODE			BIT(18)
+#define ASM9260_BM_CTRL_IRQ_ENABLE			BIT(16)
+
+#define ASM9260_HW_ICOLL_STAT_OFFSET			0x0030
+/*
+ * bits 5:0
+ * Vector number of current interrupt. Multiply by 4 and add to vector base
+ * address to obtain the value in ASM9260_HW_ICOLL_VECTOR.
+ */
+
+/*
+ * RAW0 and RAW1 provides a read-only view of the raw interrupt request lines
+ * coming from various parts of the chip. Its purpose is to improve diagnostic
+ * observability.
+ */
+#define ASM9260_HW_ICOLL_RAW0				0x0040
+#define ASM9260_HW_ICOLL_RAW1				0x0050
+
+#define ASM9260_HW_ICOLL_INTERRUPT0			0x0060
+#define ASM9260_HW_ICOLL_INTERRUPTn(n)		(0x0060 + ((n) >> 2) * 0x10)
+/*
+ * WARNING: Modifying the priority of an enabled interrupt may result in
+ * undefined behavior.
+ */
+#define ASM9260_BM_INT_PRIORITY_MASK			0x3
+#define ASM9260_BM_INT_ENABLE				BIT(2)
+#define ASM9260_BM_INT_SOFTIRQ				BIT(3)
+
+#define ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)		(((n) & 0x3) << 3)
+#define ASM9260_BM_ICOLL_INTERRUPTn_ENABLE(n)		(1 << (2 + \
+			ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)))
+
+#define ASM9260_HW_ICOLL_VBASE				0x0160
+/*
+ * bits 31:2
+ * This bitfield holds the upper 30 bits of the base address of the vector
+ * table.
+ */
+
+#define ASM9260_HW_ICOLL_CLEAR0				0x01d0
+#define ASM9260_HW_ICOLL_CLEAR1				0x01e0
+#define ASM9260_HW_ICOLL_CLEARn(n)			(((n >> 5) * 0x10) \
+							+ SET_REG)
+#define ASM9260_BM_CLEAR_BIT(n)				BIT(n & 0x1f)
+
+/* Scratchpad */
+#define ASM9260_HW_ICOLL_UNDEF_VECTOR			0x01f0
+#endif
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 14374de..88c2bcd 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *	Add Alphascale ASM9260 support.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,6 +30,8 @@
 #include <linux/stmp_device.h>
 #include <asm/exception.h>
 
+#include "alphascale_asm9260-icoll.h"
+
 /*
  * this device provide 4 offsets for each register:
  * 0x0 - plain read write mode
@@ -49,20 +53,41 @@
 
 #define ICOLL_NUM_IRQS		128
 
+enum icoll_type {
+	ICOLL,
+	ASM9260_ICOLL,
+};
+
 struct icoll_priv {
 	void __iomem *vector;
 	void __iomem *levelack;
 	void __iomem *ctrl;
 	void __iomem *stat;
 	void __iomem *intr;
-	/* number of interrupts per register */
-	int intr_per_reg;
 	void __iomem *clear;
+	enum icoll_type type;
 };
 
 static struct icoll_priv icoll_priv;
 static struct irq_domain *icoll_domain;
 
+/* calculate bit offset depending on number of intterupt per register */
+static u32 icoll_intr_bitshift(struct irq_data *d, u32 bit)
+{
+	/*
+	 * mask lower part of hwirq to convert it
+	 * in 0, 1, 2 or 3 and then multiply it by 8 (or shift by 3)
+	 */
+	return bit << ((d->hwirq & 3) << 3);
+}
+
+/* calculate mem offset depending on number of intterupt per register */
+static void __iomem *icoll_intr_reg(struct irq_data *d)
+{
+	/* offset = hwirq / intr_per_reg * 0x10 */
+	return icoll_priv.intr + ((d->hwirq >> 2) * 0x10);
+}
+
 static void icoll_ack_irq(struct irq_data *d)
 {
 	/*
@@ -86,12 +111,34 @@ static void icoll_unmask_irq(struct irq_data *d)
 			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
+static void asm9260_mask_irq(struct irq_data *d)
+{
+	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+			icoll_intr_reg(d) + CLR_REG);
+}
+
+static void asm9260_unmask_irq(struct irq_data *d)
+{
+	__raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
+		     icoll_priv.clear +
+		     ASM9260_HW_ICOLL_CLEARn(d->hwirq));
+
+	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+			icoll_intr_reg(d) + SET_REG);
+}
+
 static struct irq_chip mxs_icoll_chip = {
 	.irq_ack = icoll_ack_irq,
 	.irq_mask = icoll_mask_irq,
 	.irq_unmask = icoll_unmask_irq,
 };
 
+static struct irq_chip asm9260_icoll_chip = {
+	.irq_ack = icoll_ack_irq,
+	.irq_mask = asm9260_mask_irq,
+	.irq_unmask = asm9260_unmask_irq,
+};
+
 asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 {
 	u32 irqnr;
@@ -104,7 +151,14 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
 				irq_hw_number_t hw)
 {
-	irq_set_chip_and_handler(virq, &mxs_icoll_chip, handle_level_irq);
+	struct irq_chip *chip;
+
+	if (icoll_priv.type == ICOLL)
+		chip = &mxs_icoll_chip;
+	else
+		chip = &asm9260_icoll_chip;
+
+	irq_set_chip_and_handler(virq, chip, handle_level_irq);
 	set_irq_flags(virq, IRQF_VALID);
 
 	return 0;
@@ -142,13 +196,14 @@ static int __init icoll_of_init(struct device_node *np,
 {
 	void __iomem *icoll_base;
 
+	icoll_priv.type = ICOLL;
+
 	icoll_base		= icoll_init_iobase(np);
 	icoll_priv.vector	= icoll_base + HW_ICOLL_VECTOR;
 	icoll_priv.levelack	= icoll_base + HW_ICOLL_LEVELACK;
 	icoll_priv.ctrl		= icoll_base + HW_ICOLL_CTRL;
 	icoll_priv.stat		= icoll_base + HW_ICOLL_STAT_OFFSET;
 	icoll_priv.intr		= icoll_base + HW_ICOLL_INTERRUPT0;
-	icoll_priv.intr_per_reg	= 1;
 	icoll_priv.clear	= NULL;
 
 	/*
@@ -162,3 +217,34 @@ static int __init icoll_of_init(struct device_node *np,
 	return icoll_domain ? 0 : -ENODEV;
 }
 IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
+
+static int __init asm9260_of_init(struct device_node *np,
+			  struct device_node *interrupt_parent)
+{
+	void __iomem *icoll_base;
+	int i;
+
+	icoll_priv.type = ASM9260_ICOLL;
+
+	icoll_base = icoll_init_iobase(np);
+	icoll_priv.vector	= icoll_base + ASM9260_HW_ICOLL_VECTOR;
+	icoll_priv.levelack	= icoll_base + ASM9260_HW_ICOLL_LEVELACK;
+	icoll_priv.ctrl		= icoll_base + ASM9260_HW_ICOLL_CTRL;
+	icoll_priv.stat		= icoll_base + ASM9260_HW_ICOLL_STAT_OFFSET;
+	icoll_priv.intr		= icoll_base + ASM9260_HW_ICOLL_INTERRUPT0;
+	icoll_priv.clear	= icoll_base + ASM9260_HW_ICOLL_CLEAR0;
+
+	writel_relaxed(ASM9260_BM_CTRL_IRQ_ENABLE,
+			icoll_priv.ctrl);
+	/*
+	 * ASM9260 don't provide reset bit. So, we need to set level 0
+	 * manually.
+	 */
+	for (i = 0; i < 16 * 0x10; i += 0x10)
+		writel(0, icoll_priv.intr + i);
+
+	icoll_add_domain(np, ASM9260_NUM_IRQS);
+
+	return icoll_domain ? 0 : -ENODEV;
+}
+IRQCHIP_DECLARE(asm9260, "alphascale,asm9260-icoll", asm9260_of_init);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1229239 — [PATCH v3 1/2] ARM: irqchip: mxs: prepare driver for HW with different offsets

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-21 14:00 +0200
Subject[PATCH v3 1/2] ARM: irqchip: mxs: prepare driver for HW with different offsets
Message-ID<qb7Vh-5JD-23@gated-at.bofh.it>
In reply to#1229236
Some HW has similar functionality but different register offsets.
Make sure we can change offsets dynamically.

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 drivers/irqchip/irq-mxs.c | 83 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 67 insertions(+), 16 deletions(-)

diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 1faf812..14374de 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -28,18 +28,39 @@
 #include <linux/stmp_device.h>
 #include <asm/exception.h>
 
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+#define SET_REG 4
+#define CLR_REG 8
+
 #define HW_ICOLL_VECTOR				0x0000
 #define HW_ICOLL_LEVELACK			0x0010
 #define HW_ICOLL_CTRL				0x0020
 #define HW_ICOLL_STAT_OFFSET			0x0070
-#define HW_ICOLL_INTERRUPTn_SET(n)		(0x0124 + (n) * 0x10)
-#define HW_ICOLL_INTERRUPTn_CLR(n)		(0x0128 + (n) * 0x10)
-#define BM_ICOLL_INTERRUPTn_ENABLE		0x00000004
+#define HW_ICOLL_INTERRUPT0			0x0120
+#define HW_ICOLL_INTERRUPTn(n)			((n) * 0x10)
+#define BM_ICOLL_INTR_ENABLE			BIT(2)
 #define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0	0x1
 
 #define ICOLL_NUM_IRQS		128
 
-static void __iomem *icoll_base;
+struct icoll_priv {
+	void __iomem *vector;
+	void __iomem *levelack;
+	void __iomem *ctrl;
+	void __iomem *stat;
+	void __iomem *intr;
+	/* number of interrupts per register */
+	int intr_per_reg;
+	void __iomem *clear;
+};
+
+static struct icoll_priv icoll_priv;
 static struct irq_domain *icoll_domain;
 
 static void icoll_ack_irq(struct irq_data *d)
@@ -50,19 +71,19 @@ static void icoll_ack_irq(struct irq_data *d)
 	 * BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0 unconditionally.
 	 */
 	__raw_writel(BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0,
-			icoll_base + HW_ICOLL_LEVELACK);
+			icoll_priv.levelack);
 }
 
 static void icoll_mask_irq(struct irq_data *d)
 {
-	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
+	__raw_writel(BM_ICOLL_INTR_ENABLE,
+			icoll_priv.intr + CLR_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
 static void icoll_unmask_irq(struct irq_data *d)
 {
-	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
+	__raw_writel(BM_ICOLL_INTR_ENABLE,
+			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
 static struct irq_chip mxs_icoll_chip = {
@@ -75,8 +96,8 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 {
 	u32 irqnr;
 
-	irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
-	__raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
+	irqnr = __raw_readl(icoll_priv.stat);
+	__raw_writel(irqnr, icoll_priv.vector);
 	handle_domain_irq(icoll_domain, irqnr, regs);
 }
 
@@ -94,20 +115,50 @@ static const struct irq_domain_ops icoll_irq_domain_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
 
+static void __init icoll_add_domain(struct device_node *np,
+			  int num)
+{
+	icoll_domain = irq_domain_add_linear(np, num,
+					     &icoll_irq_domain_ops, NULL);
+
+	if (!icoll_domain)
+		panic("%s: unable add irq domain", np->full_name);
+	irq_set_default_host(icoll_domain);
+	set_handle_irq(icoll_handle_irq);
+}
+
+static void __iomem * __init icoll_init_iobase(struct device_node *np)
+{
+	void __iomem *icoll_base;
+
+	icoll_base = of_io_request_and_map(np, 0, np->name);
+	if (!icoll_base)
+		panic("%s: unable to map resource", np->full_name);
+	return icoll_base;
+}
+
 static int __init icoll_of_init(struct device_node *np,
 			  struct device_node *interrupt_parent)
 {
-	icoll_base = of_iomap(np, 0);
-	WARN_ON(!icoll_base);
+	void __iomem *icoll_base;
+
+	icoll_base		= icoll_init_iobase(np);
+	icoll_priv.vector	= icoll_base + HW_ICOLL_VECTOR;
+	icoll_priv.levelack	= icoll_base + HW_ICOLL_LEVELACK;
+	icoll_priv.ctrl		= icoll_base + HW_ICOLL_CTRL;
+	icoll_priv.stat		= icoll_base + HW_ICOLL_STAT_OFFSET;
+	icoll_priv.intr		= icoll_base + HW_ICOLL_INTERRUPT0;
+	icoll_priv.intr_per_reg	= 1;
+	icoll_priv.clear	= NULL;
 
 	/*
 	 * Interrupt Collector reset, which initializes the priority
 	 * for each irq to level 0.
 	 */
-	stmp_reset_block(icoll_base + HW_ICOLL_CTRL);
+	stmp_reset_block(icoll_priv.ctrl);
+
+	icoll_add_domain(np, ICOLL_NUM_IRQS);
 
-	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
-					     &icoll_irq_domain_ops, NULL);
 	return icoll_domain ? 0 : -ENODEV;
 }
 IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1227716 — [PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support

FromOleksij Rempel <linux@rempel-privat.de>
Date2015-09-18 11:50 +0200
Subject[PATCH v2 2/2] ARM: irqchip: mxs: add Alpascale ASM9260 support
Message-ID<qa0sN-7jM-5@gated-at.bofh.it>
In reply to#1227698
From: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>

Freescale iMX23/iMX28 and Alphascale ASM9260 have similar
interrupt collectors. It makes easy to reuse irq-mxs code for ASM9260.
Differences between this devices are fallowing:
- different register offsets
- different count of intterupt lines per register
- ASM9260 don't provide reset bit
- ASM9260 don't support FIQ.

Signed-off-by: Oleksij Rempel <external.Oleksij.Rempel@de.bosch.com>
---
 drivers/irqchip/Kconfig                    |   5 ++
 drivers/irqchip/Makefile                   |   2 +-
 drivers/irqchip/alphascale_asm9260-icoll.h | 109 +++++++++++++++++++++++++++++
 drivers/irqchip/irq-mxs.c                  | 106 +++++++++++++++++++++++++++-
 4 files changed, 220 insertions(+), 2 deletions(-)
 create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 27b52c8..0dfd840 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -187,3 +187,8 @@ config IMX_GPCV2
 	select IRQ_DOMAIN
 	help
 	  Enables the wakeup IRQs for IMX platforms with GPCv2 block
+
+config IRQ_MXS
+	def_bool y if MACH_ASM9260 || ARCH_MXS
+	select IRQ_DOMAIN
+	select STMP_DEVICE
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index bb3048f..177f78f 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
 obj-$(CONFIG_ARCH_HIP04)		+= irq-hip04.o
 obj-$(CONFIG_ARCH_MMP)			+= irq-mmp.o
 obj-$(CONFIG_ARCH_MVEBU)		+= irq-armada-370-xp.o
-obj-$(CONFIG_ARCH_MXS)			+= irq-mxs.o
+obj-$(CONFIG_IRQ_MXS)			+= irq-mxs.o
 obj-$(CONFIG_ARCH_TEGRA)		+= irq-tegra.o
 obj-$(CONFIG_ARCH_S3C24XX)		+= irq-s3c24xx.o
 obj-$(CONFIG_DW_APB_ICTL)		+= irq-dw-apb-ictl.o
diff --git a/drivers/irqchip/alphascale_asm9260-icoll.h b/drivers/irqchip/alphascale_asm9260-icoll.h
new file mode 100644
index 0000000..5cec108
--- /dev/null
+++ b/drivers/irqchip/alphascale_asm9260-icoll.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _ALPHASCALE_ASM9260_ICOLL_H
+#define _ALPHASCALE_ASM9260_ICOLL_H
+
+#define ASM9260_NUM_IRQS		64
+/*
+ * this device provide 4 offsets for each register:
+ * 0x0 - plain read write mode
+ * 0x4 - set mode, OR logic.
+ * 0x8 - clr mode, XOR logic.
+ * 0xc - togle mode.
+ */
+
+#define ASM9260_HW_ICOLL_VECTOR				0x0000
+/*
+ * bits 31:2
+ * This register presents the vector address for the interrupt currently
+ * active on the CPU IRQ input. Writing to this register notifies the
+ * interrupt collector that the interrupt service routine for the current
+ * interrupt has been entered.
+ * The exception trap should have a LDPC instruction from this address:
+ * LDPC ASM9260_HW_ICOLL_VECTOR_ADDR; IRQ exception at 0xffff0018
+ */
+
+/*
+ * The Interrupt Collector Level Acknowledge Register is used by software to
+ * indicate the completion of an interrupt on a specific level.
+ * This register is written at the very end of an interrupt service routine. If
+ * nesting is used then the CPU irq must be turned on before writing to this
+ * register to avoid a race condition in the CPU interrupt hardware.
+ */
+#define ASM9260_HW_ICOLL_LEVELACK			0x0010
+#define ASM9260_BM_LEVELn(nr)				BIT(nr)
+
+#define ASM9260_HW_ICOLL_CTRL				0x0020
+/*
+ * ASM9260_BM_CTRL_SFTRST and ASM9260_BM_CTRL_CLKGATE are not available on
+ * asm9260.
+ */
+#define ASM9260_BM_CTRL_SFTRST				BIT(31)
+#define ASM9260_BM_CTRL_CLKGATE				BIT(30)
+/* disable interrupt level nesting */
+#define ASM9260_BM_CTRL_NO_NESTING			BIT(19)
+/*
+ * Set this bit to one enable the RISC32-style read side effect associated with
+ * the vector address register. In this mode, interrupt in-service is signaled
+ * by the read of the ASM9260_HW_ICOLL_VECTOR register to acquire the interrupt
+ * vector address. Set this bit to zero for normal operation, in which the ISR
+ * signals in-service explicitly by means of a write to the
+ * ASM9260_HW_ICOLL_VECTOR register.
+ * 0 - Must Write to Vector register to go in-service.
+ * 1 - Go in-service as a read side effect
+ */
+#define ASM9260_BM_CTRL_ARM_RSE_MODE			BIT(18)
+#define ASM9260_BM_CTRL_IRQ_ENABLE			BIT(16)
+
+#define ASM9260_HW_ICOLL_STAT_OFFSET			0x0030
+/*
+ * bits 5:0
+ * Vector number of current interrupt. Multiply by 4 and add to vector base
+ * address to obtain the value in ASM9260_HW_ICOLL_VECTOR.
+ */
+
+/*
+ * RAW0 and RAW1 provides a read-only view of the raw interrupt request lines
+ * coming from various parts of the chip. Its purpose is to improve diagnostic
+ * observability.
+ */
+#define ASM9260_HW_ICOLL_RAW0				0x0040
+#define ASM9260_HW_ICOLL_RAW1				0x0050
+
+#define ASM9260_HW_ICOLL_INTERRUPT0			0x0060
+#define ASM9260_HW_ICOLL_INTERRUPTn(n)		(0x0060 + ((n) >> 2) * 0x10)
+/*
+ * WARNING: Modifying the priority of an enabled interrupt may result in
+ * undefined behavior.
+ */
+#define ASM9260_BM_INT_PRIORITY_MASK			0x3
+#define ASM9260_BM_INT_ENABLE				BIT(2)
+#define ASM9260_BM_INT_SOFTIRQ				BIT(3)
+
+#define ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)		(((n) & 0x3) << 3)
+#define ASM9260_BM_ICOLL_INTERRUPTn_ENABLE(n)		(1 << (2 + \
+			ASM9260_BM_ICOLL_INTERRUPTn_SHIFT(n)))
+
+#define ASM9260_HW_ICOLL_VBASE				0x0160
+/*
+ * bits 31:2
+ * This bitfield holds the upper 30 bits of the base address of the vector
+ * table.
+ */
+
+#define ASM9260_HW_ICOLL_CLEAR0				0x01d0
+#define ASM9260_HW_ICOLL_CLEAR1				0x01e0
+#define ASM9260_HW_ICOLL_CLEARn(n)			(((n >> 5) * 0x10) \
+							+ SET_REG)
+#define ASM9260_BM_CLEAR_BIT(n)				BIT(n & 0x1f)
+
+/* Scratchpad */
+#define ASM9260_HW_ICOLL_UNDEF_VECTOR			0x01f0
+#endif
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 14374de..1470087 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2014 Oleksij Rempel <linux@rempel-privat.de>
+ *	Add Alphascale ASM9260 support.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,6 +30,8 @@
 #include <linux/stmp_device.h>
 #include <asm/exception.h>
 
+#include "alphascale_asm9260-icoll.h"
+
 /*
  * this device provide 4 offsets for each register:
  * 0x0 - plain read write mode
@@ -49,6 +53,11 @@
 
 #define ICOLL_NUM_IRQS		128
 
+enum icoll_type {
+	ICOLL,
+	ASM9260_ICOLL,
+};
+
 struct icoll_priv {
 	void __iomem *vector;
 	void __iomem *levelack;
@@ -58,10 +67,38 @@ struct icoll_priv {
 	/* number of interrupts per register */
 	int intr_per_reg;
 	void __iomem *clear;
+	enum icoll_type type;
 };
 
 static struct icoll_priv icoll_priv;
 static struct irq_domain *icoll_domain;
+static DEFINE_RAW_SPINLOCK(icoll_lock);
+
+/* calculate bit offset depending on number of intterupt per register */
+static u32 icoll_intr_bitshift(struct irq_data *d, u32 bit)
+{
+	/*
+	 * We expect intr_per_reg to be 4 or 1, it means
+	 * "n" will be 3 or 0.
+	 */
+	int n = icoll_priv.intr_per_reg - 1;
+
+	/*
+	 * If n = 0, "bit" is never shifted.
+	 * If n = 3, mask lower part of hwirq to convert it
+	 * in 0, 1, 2 or 3 and then multiply it by 8 (or shift by 3)
+	 */
+	return bit << ((d->hwirq & n) << n);
+}
+
+/* calculate mem offset depending on number of intterupt per register */
+static void __iomem *icoll_intr_reg(struct irq_data *d)
+{
+	int n = icoll_priv.intr_per_reg >> 1;
+
+	/* offset = hwirq / intr_per_reg * 0x10 */
+	return icoll_priv.intr + ((d->hwirq >> n) * 0x10);
+}
 
 static void icoll_ack_irq(struct irq_data *d)
 {
@@ -86,12 +123,38 @@ static void icoll_unmask_irq(struct irq_data *d)
 			icoll_priv.intr + SET_REG + HW_ICOLL_INTERRUPTn(d->hwirq));
 }
 
+static void asm9260_mask_irq(struct irq_data *d)
+{
+	raw_spin_lock(&icoll_lock);
+	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+			icoll_intr_reg(d) + CLR_REG);
+	raw_spin_unlock(&icoll_lock);
+}
+
+static void asm9260_unmask_irq(struct irq_data *d)
+{
+	raw_spin_lock(&icoll_lock);
+	__raw_writel(ASM9260_BM_CLEAR_BIT(d->hwirq),
+		     icoll_priv.clear +
+		     ASM9260_HW_ICOLL_CLEARn(d->hwirq));
+
+	__raw_writel(icoll_intr_bitshift(d, BM_ICOLL_INTR_ENABLE),
+			icoll_intr_reg(d) + SET_REG);
+	raw_spin_unlock(&icoll_lock);
+}
+
 static struct irq_chip mxs_icoll_chip = {
 	.irq_ack = icoll_ack_irq,
 	.irq_mask = icoll_mask_irq,
 	.irq_unmask = icoll_unmask_irq,
 };
 
+static struct irq_chip asm9260_icoll_chip = {
+	.irq_ack = icoll_ack_irq,
+	.irq_mask = asm9260_mask_irq,
+	.irq_unmask = asm9260_unmask_irq,
+};
+
 asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 {
 	u32 irqnr;
@@ -104,7 +167,14 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
 				irq_hw_number_t hw)
 {
-	irq_set_chip_and_handler(virq, &mxs_icoll_chip, handle_level_irq);
+	struct irq_chip *chip;
+
+	if (icoll_priv.type == ICOLL)
+		chip = &mxs_icoll_chip;
+	else
+		chip = &asm9260_icoll_chip;
+
+	irq_set_chip_and_handler(virq, chip, handle_level_irq);
 	set_irq_flags(virq, IRQF_VALID);
 
 	return 0;
@@ -142,6 +212,8 @@ static int __init icoll_of_init(struct device_node *np,
 {
 	void __iomem *icoll_base;
 
+	icoll_priv.type = ICOLL;
+
 	icoll_base		= icoll_init_iobase(np);
 	icoll_priv.vector	= icoll_base + HW_ICOLL_VECTOR;
 	icoll_priv.levelack	= icoll_base + HW_ICOLL_LEVELACK;
@@ -162,3 +234,35 @@ static int __init icoll_of_init(struct device_node *np,
 	return icoll_domain ? 0 : -ENODEV;
 }
 IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
+
+static int __init asm9260_of_init(struct device_node *np,
+			  struct device_node *interrupt_parent)
+{
+	void __iomem *icoll_base;
+	int i;
+
+	icoll_priv.type = ASM9260_ICOLL;
+
+	icoll_base = icoll_init_iobase(np);
+	icoll_priv.vector	= icoll_base + ASM9260_HW_ICOLL_VECTOR;
+	icoll_priv.levelack	= icoll_base + ASM9260_HW_ICOLL_LEVELACK;
+	icoll_priv.ctrl		= icoll_base + ASM9260_HW_ICOLL_CTRL;
+	icoll_priv.stat		= icoll_base + ASM9260_HW_ICOLL_STAT_OFFSET;
+	icoll_priv.intr		= icoll_base + ASM9260_HW_ICOLL_INTERRUPT0;
+	icoll_priv.intr_per_reg	= 4;
+	icoll_priv.clear	= icoll_base + ASM9260_HW_ICOLL_CLEAR0;
+
+	writel_relaxed(ASM9260_BM_CTRL_IRQ_ENABLE,
+			icoll_priv.ctrl);
+	/*
+	 * ASM9260 don't provide reset bit. So, we need to set level 0
+	 * manually.
+	 */
+	for (i = 0; i < 16 * 0x10; i += 0x10)
+		writel(0, icoll_priv.intr + i);
+
+	icoll_add_domain(np, ASM9260_NUM_IRQS);
+
+	return icoll_domain ? 0 : -ENODEV;
+}
+IRQCHIP_DECLARE(asm9260, "alphascale,asm9260-icoll", asm9260_of_init);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1227745

FromMarc Zyngier <marc.zyngier@arm.com>
Date2015-09-18 12:20 +0200
Message-ID<qa0VQ-86U-21@gated-at.bofh.it>
In reply to#1227698
On Fri, 18 Sep 2015 11:18:40 +0200
Oleksij Rempel <linux@rempel-privat.de> wrote:

Hi Oleksij,

> v2:
> - move some parts from patch 2 to 1
> - make separate irq_chip for ICOLL and ASM9260 
> 
> Oleksij Rempel (2):
>   ARM: irqchip: mxs: prepare driver for HW with different offsets
>   ARM: irqchip: mxs: add Alpascale ASM9260 support
> 
>  drivers/irqchip/Kconfig                    |   5 +
>  drivers/irqchip/Makefile                   |   2 +-
>  drivers/irqchip/alphascale_asm9260-icoll.h | 109 +++++++++++++++++
>  drivers/irqchip/irq-mxs.c                  | 188 ++++++++++++++++++++++++++---
>  4 files changed, 286 insertions(+), 18 deletions(-)
>  create mode 100644 drivers/irqchip/alphascale_asm9260-icoll.h
> 

Next time, please add a sensible title to your cover letter. Something
like "Add support for ASM9260 interrupt controller". "changelog" is
hardly a useful subject when you're dealing with a few dozen of patches
at the same time.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1227750

FromThomas Gleixner <tglx@linutronix.de>
Date2015-09-18 12:30 +0200
Message-ID<qa15w-8i7-13@gated-at.bofh.it>
In reply to#1227698
On Fri, 18 Sep 2015, Oleksij Rempel wrote:

'changelog' is not really a descriptive subject line for a cover
letter.

Thanks,

	tglx
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web