Linux-ARM-Kernel Archive on lore.kernel.org
 help / Atom feed
* [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support
@ 2019-02-03 21:41 Linus Walleij
  2019-02-03 21:41 ` [PATCH 01/17 v1] ARM: ixp4xx: Convert to MULTI_IRQ_HANDLER Linus Walleij
                   ` (16 more replies)
  0 siblings, 17 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Tim Harvey, Linus Walleij, Arnd Bergmann

This modernizes the IXP4xx platform and adds initial Device Tree
Support. We migrate to MULTI_IRQ_HANDLER, bumps the IRQs to
offset 16, converts to SPARSE_IRQ, then we add proper subsystem
drivers in each subsystem for irqchip, GPIO and clocksource and
switch over to using these new drivers.

Then we add DT bindings to all of these aforementioned drivers,
add add support for probing each from device tree (keeping the
boardfile path).

Then we add Device Tree boot support.

The last patch shows how some basic (working) device trees will
look.

We will not delete any boardfiles until we support the
corresponding board fully with a device tree, which requires
things like PCI support which we can work on using this as
a base.

A working set of base patches that boots to prompto from
initramfs on NSLU2 and GW2358-4 is provided on this branch:
https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git/log/?h=ixp4

I am now collecting feedback and ACKs for the patches. I aim
to create a branch in the GPIO tree and ask the ARM SoC tree
to pull it in. It will be best to keep all patches in one
branch since I mess with MAINTAINERS after each commit (as
requested by checkpatch!).

Obviously I am looking for the IXP4xx maintainers to review
and consent to this change or I cannot move ahead. I think
it is best that I queue up a branch and send to ARM SoC
but if you IXP4xx folks want to do it in some other way
I am happy to hear.

Linus Walleij (17):
  ARM: ixp4xx: Convert to MULTI_IRQ_HANDLER
  ARM: ixp4xx: Pass IRQ resource to beeper
  ARM: ixp4xx: Convert to SPARSE_IRQ
  irqchip: Add driver for IXP4xx
  gpio: ixp4xx: Add driver for the IXP4xx GPIO
  ARM: ixp4xx: Switch to use new IRQ+GPIO drivers
  clocksource/drivers/ixp4xx: Add driver
  ARM: ixp4xx: Switch to use new timer driver
  irqchip: ixp4xx: Add DT bindings
  irqchip: ixp4xx: Add OF initialization support
  clocksource/drivers/ixp4xx: Add DT bindings
  clocksource/drivers/ixp4xx: Add OF initialization support
  gpio: ixp4xx: Add DT bindings
  gpio: ixp4xx: Add OF probing support
  ARM: ixp4xx: Add DT bindings
  ARM: ixp4xx: Add device tree boot support
  RFC: ARM: dts: Add some initial IXP4xx device trees

 .../devicetree/bindings/arm/intel-ixp4xx.yaml |  22 +
 .../bindings/gpio/intel,ixp4xx-gpio.txt       |  38 ++
 .../intel,ixp4xx-interrupt.txt                |  33 ++
 .../bindings/timer/intel,ixp4xx-timer.txt     |  18 +
 MAINTAINERS                                   |   9 +
 arch/arm/Kconfig                              |   5 +-
 arch/arm/boot/dts/Makefile                    |   3 +
 .../boot/dts/intel-ixp42x-linksys-nslu2.dts   | 111 ++++
 arch/arm/boot/dts/intel-ixp42x.dtsi           |  25 +
 .../dts/intel-ixp43x-gateworks-gw2358-4.dts   |  96 ++++
 arch/arm/boot/dts/intel-ixp43x.dtsi           |  15 +
 arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi    |  34 ++
 arch/arm/boot/dts/intel-ixp4xx.dtsi           |  58 +++
 arch/arm/mach-ixp4xx/Kconfig                  |  14 +
 arch/arm/mach-ixp4xx/Makefile                 |   3 +
 arch/arm/mach-ixp4xx/avila-pci.c              |   2 +
 arch/arm/mach-ixp4xx/avila-setup.c            |   2 +
 arch/arm/mach-ixp4xx/common.c                 | 426 ++--------------
 arch/arm/mach-ixp4xx/coyote-pci.c             |   2 +
 arch/arm/mach-ixp4xx/coyote-setup.c           |   2 +
 arch/arm/mach-ixp4xx/dsmg600-pci.c            |   2 +
 arch/arm/mach-ixp4xx/dsmg600-setup.c          |   5 +-
 arch/arm/mach-ixp4xx/fsg-pci.c                |   2 +
 arch/arm/mach-ixp4xx/fsg-setup.c              |   2 +
 arch/arm/mach-ixp4xx/gateway7001-pci.c        |   2 +
 arch/arm/mach-ixp4xx/gateway7001-setup.c      |   2 +
 arch/arm/mach-ixp4xx/gtwx5715-pci.c           |   2 +
 arch/arm/mach-ixp4xx/gtwx5715-setup.c         |   2 +
 .../mach-ixp4xx/include/mach/entry-macro.S    |  41 --
 arch/arm/mach-ixp4xx/include/mach/irqs.h      |  75 ---
 .../mach-ixp4xx/include/mach/ixp4xx-regs.h    |  89 ----
 arch/arm/mach-ixp4xx/irqs.h                   |  68 +++
 arch/arm/mach-ixp4xx/ixdp425-pci.c            |   2 +
 arch/arm/mach-ixp4xx/ixdp425-setup.c          |   2 +
 arch/arm/mach-ixp4xx/ixdpg425-pci.c           |   2 +
 arch/arm/mach-ixp4xx/ixp4xx-of.c              |  49 ++
 arch/arm/mach-ixp4xx/ixp4xx_npe.c             |   5 +
 arch/arm/mach-ixp4xx/ixp4xx_qmgr.c            |   7 +
 arch/arm/mach-ixp4xx/nas100d-pci.c            |   2 +
 arch/arm/mach-ixp4xx/nas100d-setup.c          |   5 +-
 arch/arm/mach-ixp4xx/nslu2-pci.c              |   2 +
 arch/arm/mach-ixp4xx/nslu2-setup.c            |  12 +-
 arch/arm/mach-ixp4xx/wg302v2-pci.c            |   2 +
 arch/arm/mach-ixp4xx/wg302v2-setup.c          |   2 +
 drivers/clocksource/Kconfig                   |   7 +
 drivers/clocksource/Makefile                  |   1 +
 drivers/clocksource/timer-ixp4xx.c            | 284 +++++++++++
 drivers/gpio/Kconfig                          |  12 +
 drivers/gpio/Makefile                         |   1 +
 drivers/gpio/gpio-ixp4xx.c                    | 473 ++++++++++++++++++
 drivers/input/misc/ixp4xx-beeper.c            |  20 +-
 drivers/irqchip/Kconfig                       |   6 +
 drivers/irqchip/Makefile                      |   1 +
 drivers/irqchip/irq-ixp4xx.c                  | 405 +++++++++++++++
 drivers/net/ethernet/xscale/ixp4xx_eth.c      |  10 +
 drivers/watchdog/ixp4xx_wdt.c                 |   9 +
 include/linux/irqchip/irq-ixp4xx.h            |  12 +
 include/linux/platform_data/timer-ixp4xx.h    |  11 +
 58 files changed, 1940 insertions(+), 614 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
 create mode 100644 Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
 create mode 100644 Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt
 create mode 100644 arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts
 create mode 100644 arch/arm/boot/dts/intel-ixp42x.dtsi
 create mode 100644 arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358-4.dts
 create mode 100644 arch/arm/boot/dts/intel-ixp43x.dtsi
 create mode 100644 arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi
 create mode 100644 arch/arm/boot/dts/intel-ixp4xx.dtsi
 delete mode 100644 arch/arm/mach-ixp4xx/include/mach/entry-macro.S
 delete mode 100644 arch/arm/mach-ixp4xx/include/mach/irqs.h
 create mode 100644 arch/arm/mach-ixp4xx/irqs.h
 create mode 100644 arch/arm/mach-ixp4xx/ixp4xx-of.c
 create mode 100644 drivers/clocksource/timer-ixp4xx.c
 create mode 100644 drivers/gpio/gpio-ixp4xx.c
 create mode 100644 drivers/irqchip/irq-ixp4xx.c
 create mode 100644 include/linux/irqchip/irq-ixp4xx.h
 create mode 100644 include/linux/platform_data/timer-ixp4xx.h

-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 01/17 v1] ARM: ixp4xx: Convert to MULTI_IRQ_HANDLER
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-03 21:41 ` [PATCH 02/17 v1] ARM: ixp4xx: Pass IRQ resource to beeper Linus Walleij
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Tim Harvey, Linus Walleij, Arnd Bergmann

This rewrites the IXP4xx to use MULTI_IRQ_HANDLER and
create an irqdomain for the irqchip in the platform. We
convert the timer to request the interrupt like any other
driver in the process.

We bump all IRQs to 16+offset to avoid using IRQ 0 and
set NR_IRQS to 512 (the default for most systems).
This conveniently fits with the first 16 IRQs being
pre-allocated when using SPARSE_IRQ.

This is a prerequisite for SPARSE_IRQ and DT boot.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/Kconfig                              |   1 +
 arch/arm/mach-ixp4xx/common.c                 | 109 +++++++++++++-----
 .../mach-ixp4xx/include/mach/entry-macro.S    |  41 -------
 arch/arm/mach-ixp4xx/include/mach/irqs.h      |  95 ++++++++-------
 4 files changed, 126 insertions(+), 120 deletions(-)
 delete mode 100644 arch/arm/mach-ixp4xx/include/mach/entry-macro.S

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 664e918e2624..0bdcacd40591 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -431,6 +431,7 @@ config ARCH_IXP4XX
 	select CPU_XSCALE
 	select DMABOUNCE if PCI
 	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_MULTI_HANDLER
 	select GPIOLIB
 	select HAVE_PCI
 	select NEED_MACH_IO_H
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 846e033c56fa..58a1b851425e 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -31,12 +31,14 @@
 #include <linux/cpu.h>
 #include <linux/pci.h>
 #include <linux/sched_clock.h>
+#include <linux/bitops.h>
 #include <mach/udc.h>
 #include <mach/hardware.h>
 #include <mach/io.h>
 #include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/exception.h>
 #include <asm/irq.h>
 #include <asm/system_misc.h>
 #include <asm/mach/map.h>
@@ -54,6 +56,7 @@
 				       (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
 			(IXP4XX_OST_RELOAD_MASK + 1)
 
+static struct irq_domain *ixp4xx_irqdomain;
 static void __init ixp4xx_clocksource_init(void);
 static void __init ixp4xx_clockevent_init(void);
 static struct clock_event_device clockevent_ixp4xx;
@@ -166,16 +169,17 @@ static int ixp4xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
 
 static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
 {
-	int line = irq2gpio[d->irq];
+	int line = irq2gpio[d->hwirq];
 	u32 int_style;
 	enum ixp4xx_irq_type irq_type;
 	volatile u32 *int_reg;
 
 	/*
 	 * Only for GPIO IRQs
+	 * all other IRQs are simply active low
 	 */
 	if (line < 0)
-		return -EINVAL;
+		return 0;
 
 	switch (type){
 	case IRQ_TYPE_EDGE_BOTH:
@@ -203,9 +207,9 @@ static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
 	}
 
 	if (irq_type == IXP4XX_IRQ_EDGE)
-		ixp4xx_irq_edge |= (1 << d->irq);
+		ixp4xx_irq_edge |= (1 << d->hwirq);
 	else
-		ixp4xx_irq_edge &= ~(1 << d->irq);
+		ixp4xx_irq_edge &= ~(1 << d->hwirq);
 
 	if (line >= 8) {	/* pins 8-15 */
 		line -= 8;
@@ -224,22 +228,22 @@ static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
 	*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
 
 	/* Configure the line as an input */
-	gpio_line_config(irq2gpio[d->irq], IXP4XX_GPIO_IN);
+	gpio_line_config(irq2gpio[d->hwirq], IXP4XX_GPIO_IN);
 
 	return 0;
 }
 
 static void ixp4xx_irq_mask(struct irq_data *d)
 {
-	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32)
-		*IXP4XX_ICMR2 &= ~(1 << (d->irq - 32));
+	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->hwirq >= 32)
+		*IXP4XX_ICMR2 &= ~(1 << (d->hwirq - 32));
 	else
-		*IXP4XX_ICMR &= ~(1 << d->irq);
+		*IXP4XX_ICMR &= ~(1 << d->hwirq);
 }
 
 static void ixp4xx_irq_ack(struct irq_data *d)
 {
-	int line = (d->irq < 32) ? irq2gpio[d->irq] : -1;
+	int line = (d->hwirq < 32) ? irq2gpio[d->hwirq] : -1;
 
 	if (line >= 0)
 		*IXP4XX_GPIO_GPISR = (1 << line);
@@ -251,13 +255,13 @@ static void ixp4xx_irq_ack(struct irq_data *d)
  */
 static void ixp4xx_irq_unmask(struct irq_data *d)
 {
-	if (!(ixp4xx_irq_edge & (1 << d->irq)))
+	if (!(ixp4xx_irq_edge & (1 << d->hwirq)))
 		ixp4xx_irq_ack(d);
 
-	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32)
-		*IXP4XX_ICMR2 |= (1 << (d->irq - 32));
+	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->hwirq >= 32)
+		*IXP4XX_ICMR2 |= (1 << (d->hwirq - 32));
 	else
-		*IXP4XX_ICMR |= (1 << d->irq);
+		*IXP4XX_ICMR |= (1 << d->hwirq);
 }
 
 static struct irq_chip ixp4xx_irq_chip = {
@@ -268,9 +272,50 @@ static struct irq_chip ixp4xx_irq_chip = {
 	.irq_set_type	= ixp4xx_set_irq_type,
 };
 
+asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs)
+{
+	unsigned long status;
+	int i;
+
+	status = *IXP4XX_ICIP;
+
+	for_each_set_bit(i, &status, 32)
+		handle_domain_irq(ixp4xx_irqdomain, i, regs);
+
+	/*
+	 * IXP465/IXP435 has an upper IRQ status register
+	 */
+	if ((cpu_is_ixp46x() || cpu_is_ixp43x())) {
+		status = *IXP4XX_ICIP2;
+		for_each_set_bit(i, &status, 32)
+			handle_domain_irq(ixp4xx_irqdomain, i + 32, regs);
+	}
+}
+
+static int ixp4xx_irqdomain_map(struct irq_domain *d, unsigned int irq,
+				irq_hw_number_t hwirq)
+{
+	irq_set_chip_data(irq, &ixp4xx_irq_chip);
+	irq_set_chip_and_handler(irq, &ixp4xx_irq_chip, handle_level_irq);
+	irq_set_probe(irq);
+
+	return 0;
+}
+
+static void ixp4xx_irqdomain_unmap(struct irq_domain *d, unsigned int irq)
+{
+	irq_set_chip_and_handler(irq, NULL, NULL);
+	irq_set_chip_data(irq, NULL);
+}
+
+static const struct irq_domain_ops ixp4xx_irqdomain_ops = {
+	.map = ixp4xx_irqdomain_map,
+	.unmap = ixp4xx_irqdomain_unmap,
+};
+
 void __init ixp4xx_init_irq(void)
 {
-	int i = 0;
+	int nr_irqs;
 
 	/*
 	 * ixp4xx does not implement the XScale PWRMODE register
@@ -290,14 +335,21 @@ void __init ixp4xx_init_irq(void)
 
 		/* Disable upper 32 interrupts */
 		*IXP4XX_ICMR2 = 0x00;
+
+		nr_irqs = 64;
+	} else {
+		nr_irqs = 32;
 	}
 
-        /* Default to all level triggered */
-	for(i = 0; i < NR_IRQS; i++) {
-		irq_set_chip_and_handler(i, &ixp4xx_irq_chip,
-					 handle_level_irq);
-		irq_clear_status_flags(i, IRQ_NOREQUEST);
+	ixp4xx_irqdomain = irq_domain_add_simple(NULL, nr_irqs, IRQ_IXP4XX_BASE,
+						 &ixp4xx_irqdomain_ops,
+						 NULL);
+	if (!ixp4xx_irqdomain) {
+		pr_crit("can not add primary irqdomain\n");
+		return;
 	}
+
+	set_handle_irq(ixp4xx_handle_irq);
 }
 
 
@@ -319,13 +371,6 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static struct irqaction ixp4xx_timer_irq = {
-	.name		= "timer1",
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= ixp4xx_timer_interrupt,
-	.dev_id		= &clockevent_ixp4xx,
-};
-
 void __init ixp4xx_timer_init(void)
 {
 	/* Reset/disable counter */
@@ -337,9 +382,6 @@ void __init ixp4xx_timer_init(void)
 	/* Reset time-stamp counter */
 	*IXP4XX_OSTS = 0;
 
-	/* Connect the interrupt handler and enable the interrupt */
-	setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq);
-
 	ixp4xx_clocksource_init();
 	ixp4xx_clockevent_init();
 }
@@ -574,7 +616,16 @@ static struct clock_event_device clockevent_ixp4xx = {
 
 static void __init ixp4xx_clockevent_init(void)
 {
+	int ret;
+
 	clockevent_ixp4xx.cpumask = cpumask_of(0);
+	clockevent_ixp4xx.irq = IRQ_IXP4XX_TIMER1;
+	ret = request_irq(IRQ_IXP4XX_TIMER1, ixp4xx_timer_interrupt,
+			  IRQF_TIMER, "IXP4XX-TIMER1", &clockevent_ixp4xx);
+	if (ret) {
+		pr_crit("no timer IRQ\n");
+		return;
+	}
 	clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ,
 					0xf, 0xfffffffe);
 }
diff --git a/arch/arm/mach-ixp4xx/include/mach/entry-macro.S b/arch/arm/mach-ixp4xx/include/mach/entry-macro.S
deleted file mode 100644
index 79adf83e2c3d..000000000000
--- a/arch/arm/mach-ixp4xx/include/mach/entry-macro.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for IXP4xx-based platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <mach/hardware.h>
-
-		.macro  get_irqnr_preamble, base, tmp
-		.endm
-
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		ldr	\irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET)
-		ldr	\irqstat, [\irqstat]		@ get interrupts
-		cmp	\irqstat, #0
-		beq	1001f				@ upper IRQ?
-		clz     \irqnr, \irqstat
-		mov     \base, #31
-		sub     \irqnr, \base, \irqnr
-		b	1002f				@ lower IRQ being
-							@ handled
-
-1001:
-		/*
-		 * IXP465/IXP435 has an upper IRQ status register
-		 */
-#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X)
-		ldr	\irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP2_OFFSET)
-		ldr	\irqstat, [\irqstat]		@ get upper interrupts
-		mov	\irqnr, #63
-		clz	\irqstat, \irqstat
- 		cmp	\irqstat, #32
-		subne	\irqnr, \irqnr, \irqstat
-#endif
-1002:
-		.endm
-
-
diff --git a/arch/arm/mach-ixp4xx/include/mach/irqs.h b/arch/arm/mach-ixp4xx/include/mach/irqs.h
index 7e6d4cce7c27..dadcd4ddb0a9 100644
--- a/arch/arm/mach-ixp4xx/include/mach/irqs.h
+++ b/arch/arm/mach-ixp4xx/include/mach/irqs.h
@@ -15,60 +15,55 @@
 #ifndef _ARCH_IXP4XX_IRQS_H_
 #define _ARCH_IXP4XX_IRQS_H_
 
-#define IRQ_IXP4XX_NPEA		0
-#define IRQ_IXP4XX_NPEB		1
-#define IRQ_IXP4XX_NPEC		2
-#define IRQ_IXP4XX_QM1		3
-#define IRQ_IXP4XX_QM2		4
-#define IRQ_IXP4XX_TIMER1	5
-#define IRQ_IXP4XX_GPIO0	6
-#define IRQ_IXP4XX_GPIO1	7
-#define IRQ_IXP4XX_PCI_INT	8
-#define IRQ_IXP4XX_PCI_DMA1	9
-#define IRQ_IXP4XX_PCI_DMA2	10
-#define IRQ_IXP4XX_TIMER2	11
-#define IRQ_IXP4XX_USB		12
-#define IRQ_IXP4XX_UART2	13
-#define IRQ_IXP4XX_TIMESTAMP	14
-#define IRQ_IXP4XX_UART1	15
-#define IRQ_IXP4XX_WDOG		16
-#define IRQ_IXP4XX_AHB_PMU	17
-#define IRQ_IXP4XX_XSCALE_PMU	18
-#define IRQ_IXP4XX_GPIO2	19
-#define IRQ_IXP4XX_GPIO3	20
-#define IRQ_IXP4XX_GPIO4	21
-#define IRQ_IXP4XX_GPIO5	22
-#define IRQ_IXP4XX_GPIO6	23
-#define IRQ_IXP4XX_GPIO7	24
-#define IRQ_IXP4XX_GPIO8	25
-#define IRQ_IXP4XX_GPIO9	26
-#define IRQ_IXP4XX_GPIO10	27
-#define IRQ_IXP4XX_GPIO11	28
-#define IRQ_IXP4XX_GPIO12	29
-#define IRQ_IXP4XX_SW_INT1	30
-#define IRQ_IXP4XX_SW_INT2	31
-#define IRQ_IXP4XX_USB_HOST	32
-#define IRQ_IXP4XX_I2C		33
-#define IRQ_IXP4XX_SSP		34
-#define IRQ_IXP4XX_TSYNC	35
-#define IRQ_IXP4XX_EAU_DONE	36
-#define IRQ_IXP4XX_SHA_DONE	37
-#define IRQ_IXP4XX_SWCP_PE	58
-#define IRQ_IXP4XX_QM_PE	60
-#define IRQ_IXP4XX_MCU_ECC	61
-#define IRQ_IXP4XX_EXP_PE	62
+#define IRQ_IXP4XX_BASE		16
+
+#define IRQ_IXP4XX_NPEA		(IRQ_IXP4XX_BASE + 0)
+#define IRQ_IXP4XX_NPEB		(IRQ_IXP4XX_BASE + 1)
+#define IRQ_IXP4XX_NPEC		(IRQ_IXP4XX_BASE + 2)
+#define IRQ_IXP4XX_QM1		(IRQ_IXP4XX_BASE + 3)
+#define IRQ_IXP4XX_QM2		(IRQ_IXP4XX_BASE + 4)
+#define IRQ_IXP4XX_TIMER1	(IRQ_IXP4XX_BASE + 5)
+#define IRQ_IXP4XX_GPIO0	(IRQ_IXP4XX_BASE + 6)
+#define IRQ_IXP4XX_GPIO1	(IRQ_IXP4XX_BASE + 7)
+#define IRQ_IXP4XX_PCI_INT	(IRQ_IXP4XX_BASE + 8)
+#define IRQ_IXP4XX_PCI_DMA1	(IRQ_IXP4XX_BASE + 9)
+#define IRQ_IXP4XX_PCI_DMA2	(IRQ_IXP4XX_BASE + 10)
+#define IRQ_IXP4XX_TIMER2	(IRQ_IXP4XX_BASE + 11)
+#define IRQ_IXP4XX_USB		(IRQ_IXP4XX_BASE + 12)
+#define IRQ_IXP4XX_UART2	(IRQ_IXP4XX_BASE + 13)
+#define IRQ_IXP4XX_TIMESTAMP	(IRQ_IXP4XX_BASE + 14)
+#define IRQ_IXP4XX_UART1	(IRQ_IXP4XX_BASE + 15)
+#define IRQ_IXP4XX_WDOG		(IRQ_IXP4XX_BASE + 16)
+#define IRQ_IXP4XX_AHB_PMU	(IRQ_IXP4XX_BASE + 17)
+#define IRQ_IXP4XX_XSCALE_PMU	(IRQ_IXP4XX_BASE + 18)
+#define IRQ_IXP4XX_GPIO2	(IRQ_IXP4XX_BASE + 19)
+#define IRQ_IXP4XX_GPIO3	(IRQ_IXP4XX_BASE + 20)
+#define IRQ_IXP4XX_GPIO4	(IRQ_IXP4XX_BASE + 21)
+#define IRQ_IXP4XX_GPIO5	(IRQ_IXP4XX_BASE + 22)
+#define IRQ_IXP4XX_GPIO6	(IRQ_IXP4XX_BASE + 23)
+#define IRQ_IXP4XX_GPIO7	(IRQ_IXP4XX_BASE + 24)
+#define IRQ_IXP4XX_GPIO8	(IRQ_IXP4XX_BASE + 25)
+#define IRQ_IXP4XX_GPIO9	(IRQ_IXP4XX_BASE + 26)
+#define IRQ_IXP4XX_GPIO10	(IRQ_IXP4XX_BASE + 27)
+#define IRQ_IXP4XX_GPIO11	(IRQ_IXP4XX_BASE + 28)
+#define IRQ_IXP4XX_GPIO12	(IRQ_IXP4XX_BASE + 29)
+#define IRQ_IXP4XX_SW_INT1	(IRQ_IXP4XX_BASE + 30)
+#define IRQ_IXP4XX_SW_INT2	(IRQ_IXP4XX_BASE + 31)
+#define IRQ_IXP4XX_USB_HOST	(IRQ_IXP4XX_BASE + 32)
+#define IRQ_IXP4XX_I2C		(IRQ_IXP4XX_BASE + 33)
+#define IRQ_IXP4XX_SSP		(IRQ_IXP4XX_BASE + 34)
+#define IRQ_IXP4XX_TSYNC	(IRQ_IXP4XX_BASE + 35)
+#define IRQ_IXP4XX_EAU_DONE	(IRQ_IXP4XX_BASE + 36)
+#define IRQ_IXP4XX_SHA_DONE	(IRQ_IXP4XX_BASE + 37)
+#define IRQ_IXP4XX_SWCP_PE	(IRQ_IXP4XX_BASE + 58)
+#define IRQ_IXP4XX_QM_PE	(IRQ_IXP4XX_BASE + 60)
+#define IRQ_IXP4XX_MCU_ECC	(IRQ_IXP4XX_BASE + 61)
+#define IRQ_IXP4XX_EXP_PE	(IRQ_IXP4XX_BASE + 62)
 
 #define _IXP4XX_GPIO_IRQ(n)	(IRQ_IXP4XX_GPIO ## n)
 #define IXP4XX_GPIO_IRQ(n)	_IXP4XX_GPIO_IRQ(n)
 
-/*
- * Only first 32 sources are valid if running on IXP42x systems
- */
-#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X)
-#define NR_IRQS			64
-#else
-#define NR_IRQS			32
-#endif
+#define NR_IRQS 512
 
 #define	XSCALE_PMU_IRQ		(IRQ_IXP4XX_XSCALE_PMU)
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 02/17 v1] ARM: ixp4xx: Pass IRQ resource to beeper
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
  2019-02-03 21:41 ` [PATCH 01/17 v1] ARM: ixp4xx: Convert to MULTI_IRQ_HANDLER Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-03 21:41 ` [PATCH 03/17 v1] ARM: ixp4xx: Convert to SPARSE_IRQ Linus Walleij
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Tim Harvey, Linus Walleij, Arnd Bergmann

All IXP4xx devices except the beeper passes the IRQ as a
resource, augment the NSLU2 beeper to do the same.

This is a prerequisite for SPARSE_IRQ.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ixp4xx/nslu2-setup.c | 10 +++++++++-
 drivers/input/misc/ixp4xx-beeper.c | 20 +++++++++++++++-----
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 341b263482ef..7c2b6604187e 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -125,10 +125,18 @@ static struct platform_device nslu2_i2c_gpio = {
 	},
 };
 
+static struct resource nslu2_beeper_resources[] = {
+	{
+		.start	= IRQ_IXP4XX_TIMER2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 static struct platform_device nslu2_beeper = {
 	.name			= "ixp4xx-beeper",
 	.id			= NSLU2_GPIO_BUZZ,
-	.num_resources		= 0,
+	.resource		= nslu2_beeper_resources,
+	.num_resources		= ARRAY_SIZE(nslu2_beeper_resources),
 };
 
 static struct resource nslu2_uart_resources[] = {
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index 1fe149f3def2..4776273fa10b 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -30,6 +30,8 @@ MODULE_ALIAS("platform:ixp4xx-beeper");
 
 static DEFINE_SPINLOCK(beep_lock);
 
+static int ixp4xx_timer2_irq;
+
 static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)
 {
 	unsigned long flags;
@@ -90,6 +92,7 @@ static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)
 static int ixp4xx_spkr_probe(struct platform_device *dev)
 {
 	struct input_dev *input_dev;
+	int irq;
 	int err;
 
 	input_dev = input_allocate_device();
@@ -110,15 +113,22 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)
 	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
 	input_dev->event = ixp4xx_spkr_event;
 
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		err = irq;
+		goto err_free_device;
+	}
+
 	err = gpio_request(dev->id, "ixp4-beeper");
 	if (err)
 		goto err_free_device;
 
-	err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
+	err = request_irq(irq, &ixp4xx_spkr_interrupt,
 			  IRQF_NO_SUSPEND, "ixp4xx-beeper",
 			  (void *) dev->id);
 	if (err)
 		goto err_free_gpio;
+	ixp4xx_timer2_irq = irq;
 
 	err = input_register_device(input_dev);
 	if (err)
@@ -129,7 +139,7 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)
 	return 0;
 
  err_free_irq:
-	free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id);
+	free_irq(irq, (void *)dev->id);
  err_free_gpio:
 	gpio_free(dev->id);
  err_free_device:
@@ -146,10 +156,10 @@ static int ixp4xx_spkr_remove(struct platform_device *dev)
 	input_unregister_device(input_dev);
 
 	/* turn the speaker off */
-	disable_irq(IRQ_IXP4XX_TIMER2);
+	disable_irq(ixp4xx_timer2_irq);
 	ixp4xx_spkr_control(pin, 0);
 
-	free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id);
+	free_irq(ixp4xx_timer2_irq, (void *)dev->id);
 	gpio_free(dev->id);
 
 	return 0;
@@ -161,7 +171,7 @@ static void ixp4xx_spkr_shutdown(struct platform_device *dev)
 	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
 
 	/* turn off the speaker */
-	disable_irq(IRQ_IXP4XX_TIMER2);
+	disable_irq(ixp4xx_timer2_irq);
 	ixp4xx_spkr_control(pin, 0);
 }
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 03/17 v1] ARM: ixp4xx: Convert to SPARSE_IRQ
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
  2019-02-03 21:41 ` [PATCH 01/17 v1] ARM: ixp4xx: Convert to MULTI_IRQ_HANDLER Linus Walleij
  2019-02-03 21:41 ` [PATCH 02/17 v1] ARM: ixp4xx: Pass IRQ resource to beeper Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-03 21:41 ` [PATCH 04/17 v1] irqchip: Add driver for IXP4xx Linus Walleij
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Tim Harvey, Linus Walleij, Arnd Bergmann

This localizes the <mach/irqs.h> header to the mach-ixp4xx
directory, removes NR_IRQS and switches IXP4xx over to using
SPARSE_IRQ.

This is a prerequisite for DT support.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/Kconfig                               | 1 +
 arch/arm/mach-ixp4xx/avila-pci.c               | 2 ++
 arch/arm/mach-ixp4xx/avila-setup.c             | 2 ++
 arch/arm/mach-ixp4xx/common.c                  | 2 ++
 arch/arm/mach-ixp4xx/coyote-pci.c              | 2 ++
 arch/arm/mach-ixp4xx/coyote-setup.c            | 2 ++
 arch/arm/mach-ixp4xx/dsmg600-pci.c             | 2 ++
 arch/arm/mach-ixp4xx/dsmg600-setup.c           | 2 ++
 arch/arm/mach-ixp4xx/fsg-pci.c                 | 2 ++
 arch/arm/mach-ixp4xx/fsg-setup.c               | 2 ++
 arch/arm/mach-ixp4xx/gateway7001-pci.c         | 2 ++
 arch/arm/mach-ixp4xx/gateway7001-setup.c       | 2 ++
 arch/arm/mach-ixp4xx/gtwx5715-pci.c            | 2 ++
 arch/arm/mach-ixp4xx/gtwx5715-setup.c          | 2 ++
 arch/arm/mach-ixp4xx/{include/mach => }/irqs.h | 2 --
 arch/arm/mach-ixp4xx/ixdp425-pci.c             | 2 ++
 arch/arm/mach-ixp4xx/ixdp425-setup.c           | 2 ++
 arch/arm/mach-ixp4xx/ixdpg425-pci.c            | 2 ++
 arch/arm/mach-ixp4xx/ixp4xx_qmgr.c             | 2 ++
 arch/arm/mach-ixp4xx/nas100d-pci.c             | 2 ++
 arch/arm/mach-ixp4xx/nas100d-setup.c           | 2 ++
 arch/arm/mach-ixp4xx/nslu2-pci.c               | 2 ++
 arch/arm/mach-ixp4xx/nslu2-setup.c             | 2 ++
 arch/arm/mach-ixp4xx/wg302v2-pci.c             | 2 ++
 arch/arm/mach-ixp4xx/wg302v2-setup.c           | 2 ++
 25 files changed, 47 insertions(+), 2 deletions(-)
 rename arch/arm/mach-ixp4xx/{include/mach => }/irqs.h (99%)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0bdcacd40591..de2a5647e85d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -435,6 +435,7 @@ config ARCH_IXP4XX
 	select GPIOLIB
 	select HAVE_PCI
 	select NEED_MACH_IO_H
+	select SPARSE_IRQ
 	select USB_EHCI_BIG_ENDIAN_DESC
 	select USB_EHCI_BIG_ENDIAN_MMIO
 	help
diff --git a/arch/arm/mach-ixp4xx/avila-pci.c b/arch/arm/mach-ixp4xx/avila-pci.c
index 548c7d43ade6..9c834f0f4231 100644
--- a/arch/arm/mach-ixp4xx/avila-pci.c
+++ b/arch/arm/mach-ixp4xx/avila-pci.c
@@ -27,6 +27,8 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define AVILA_MAX_DEV	4
 #define LOFT_MAX_DEV	6
 #define IRQ_LINES	4
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
index 44cbbce6bda6..1981b33109cb 100644
--- a/arch/arm/mach-ixp4xx/avila-setup.c
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -28,6 +28,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define AVILA_SDA_PIN	7
 #define AVILA_SCL_PIN	6
 
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 58a1b851425e..aa8fd248c125 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -45,6 +45,8 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#include "irqs.h"
+
 #define IXP4XX_TIMER_FREQ 66666000
 
 /*
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index 5d14ce2aee6d..a16c35d2bb96 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -23,6 +23,8 @@
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 #define SLOT0_DEVID	14
 #define SLOT1_DEVID	15
 
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 7e40fe70933b..7ca43ca2816d 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -25,6 +25,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define COYOTE_IDE_BASE_PHYS	IXP4XX_EXP_BUS_BASE(3)
 #define COYOTE_IDE_BASE_VIRT	0xFFFE1000
 #define COYOTE_IDE_REGION_SIZE	0x1000
diff --git a/arch/arm/mach-ixp4xx/dsmg600-pci.c b/arch/arm/mach-ixp4xx/dsmg600-pci.c
index 8dca76937723..6899023bd1b7 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-pci.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-pci.c
@@ -22,6 +22,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV		4
 #define IRQ_LINES	3
 
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 397190f3a8da..0daaede8fb6d 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -35,6 +35,8 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
 
+#include "irqs.h"
+
 #define DSMG600_SDA_PIN		5
 #define DSMG600_SCL_PIN		4
 
diff --git a/arch/arm/mach-ixp4xx/fsg-pci.c b/arch/arm/mach-ixp4xx/fsg-pci.c
index fd4a8625b4ae..6c08bb9d9807 100644
--- a/arch/arm/mach-ixp4xx/fsg-pci.c
+++ b/arch/arm/mach-ixp4xx/fsg-pci.c
@@ -22,6 +22,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV		3
 #define IRQ_LINES	3
 
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
index f0a152e365b1..648932d8d7a8 100644
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ b/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -29,6 +29,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define FSG_SDA_PIN		12
 #define FSG_SCL_PIN		13
 
diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c
index d9d6cc089707..903c75330b76 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-pci.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c
@@ -27,6 +27,8 @@
 
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 void __init gateway7001_pci_preinit(void)
 {
 	irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
index 1be6faf6da9a..678e7dfff0e5 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -28,6 +28,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 static struct flash_platform_data gateway7001_flash_data = {
 	.map_name	= "cfi_probe",
 	.width		= 2,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
index 551d114c9e14..1223d160448f 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
@@ -30,6 +30,8 @@
 #include <mach/hardware.h>
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 #define SLOT0_DEVID	0
 #define SLOT1_DEVID	1
 #define INTA		10 /* slot 1 has INTA and INTB crossed */
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 16a12994fb53..5dbdde8e2338 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -36,6 +36,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 /* GPIO 5,6,7 and 12 are hard wired to the Kendin KS8995M Switch
    and operate as an SPI type interface.  The details of the interface
    are available on Kendin/Micrel's web site. */
diff --git a/arch/arm/mach-ixp4xx/include/mach/irqs.h b/arch/arm/mach-ixp4xx/irqs.h
similarity index 99%
rename from arch/arm/mach-ixp4xx/include/mach/irqs.h
rename to arch/arm/mach-ixp4xx/irqs.h
index dadcd4ddb0a9..6b7f220cf9e0 100644
--- a/arch/arm/mach-ixp4xx/include/mach/irqs.h
+++ b/arch/arm/mach-ixp4xx/irqs.h
@@ -63,8 +63,6 @@
 #define _IXP4XX_GPIO_IRQ(n)	(IRQ_IXP4XX_GPIO ## n)
 #define IXP4XX_GPIO_IRQ(n)	_IXP4XX_GPIO_IRQ(n)
 
-#define NR_IRQS 512
-
 #define	XSCALE_PMU_IRQ		(IRQ_IXP4XX_XSCALE_PMU)
 
 #endif
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index 318424dd3c50..c1340465b2ea 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -24,6 +24,8 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV		4
 #define IRQ_LINES	4
 
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 57d7df79d838..6f0f7ed18ea8 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -32,6 +32,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define IXDP425_SDA_PIN		7
 #define IXDP425_SCL_PIN		6
 
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index 1f8717ba13dc..ac0e9bc6eb4d 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -23,6 +23,8 @@
 
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 void __init ixdpg425_pci_preinit(void)
 {
 	irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
index 9d1b6b7c394c..4c7c960e1b4c 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -14,6 +14,8 @@
 #include <linux/module.h>
 #include <mach/qmgr.h>
 
+#include "irqs.h"
+
 static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
 static struct resource *mem_res;
 static spinlock_t qmgr_lock;
diff --git a/arch/arm/mach-ixp4xx/nas100d-pci.c b/arch/arm/mach-ixp4xx/nas100d-pci.c
index 8f0eba0a6800..925ef805f966 100644
--- a/arch/arm/mach-ixp4xx/nas100d-pci.c
+++ b/arch/arm/mach-ixp4xx/nas100d-pci.c
@@ -21,6 +21,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV		3
 #define IRQ_LINES	3
 
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 4138d6aa4c52..9d67f8de0772 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -34,6 +34,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 #define NAS100D_SDA_PIN		5
 #define NAS100D_SCL_PIN		6
 
diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c
index 032defe111aa..d69ee4066d20 100644
--- a/arch/arm/mach-ixp4xx/nslu2-pci.c
+++ b/arch/arm/mach-ixp4xx/nslu2-pci.c
@@ -21,6 +21,8 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include "irqs.h"
+
 #define MAX_DEV		3
 #define IRQ_LINES	3
 
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 7c2b6604187e..ee1877fcfafe 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -32,6 +32,8 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/time.h>
 
+#include "irqs.h"
+
 #define NSLU2_SDA_PIN		7
 #define NSLU2_SCL_PIN		6
 
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c
index c92e5b82af36..cf83f7e24179 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-pci.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c
@@ -27,6 +27,8 @@
 
 #include <asm/mach/pci.h>
 
+#include "irqs.h"
+
 void __init wg302v2_pci_preinit(void)
 {
 	irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
index 90b3c604e8b6..8711e299229b 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -29,6 +29,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
+#include "irqs.h"
+
 static struct flash_platform_data wg302v2_flash_data = {
 	.map_name	= "cfi_probe",
 	.width		= 2,
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (2 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 03/17 v1] ARM: ixp4xx: Convert to SPARSE_IRQ Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-11 15:30   ` Marc Zyngier
  2019-02-03 21:41 ` [PATCH 05/17 v1] gpio: ixp4xx: Add driver for the IXP4xx GPIO Linus Walleij
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Jason Cooper, Arnd Bergmann, Marc Zyngier, Tim Harvey,
	Olof Johansson, Thomas Gleixner, Linus Walleij

The IXP4xx (arch/arm/mach-ixp4xx) is an old Intel XScale
platform that has very wide deployment and use.

As part of modernizing the platform, we need to implement a
proper irqchip in the irqchip subsystem.

The IXP4xx irqchip is tightly jotted together with the GPIO
controller, and wheras in the past we would deal with this
complex logic by adding necessarily different code, we can
nowadays modernize it using a hierarchical irqchip.

The actual IXP4 irqchip is a simple active low level IRQ
controller, whereas the GPIO functionality resides in a
different memory area and adds edge trigger support for
the interrupts.

The interrupts from GPIO lines 0..12 are 1:1 mapped to
a fixed set of hardware IRQs on this IRQchip, so we
expect the child GPIO interrupt controller to go in and
allocate descriptors for these interrupts.

For the other interrupts, as we do not yet have DT
support for this platform, we create a linear irqdomain
and then go in and allocate the IRQs that the legacy
boards use. This code will be removed on the DT probe
path when we add DT support to the platform.

We add some translation code for supporting DT
translations for the fwnodes, but we leave most of that
for later.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
irqchip maintainers: I am requesting an ACK for this once
you're happy with the driver, as I intend to merge all of
this IXP4xx rework through ARM SoC.
---
 MAINTAINERS                        |   2 +
 drivers/irqchip/Kconfig            |   6 +
 drivers/irqchip/Makefile           |   1 +
 drivers/irqchip/irq-ixp4xx.c       | 360 +++++++++++++++++++++++++++++
 include/linux/irqchip/irq-ixp4xx.h |  12 +
 5 files changed, 381 insertions(+)
 create mode 100644 drivers/irqchip/irq-ixp4xx.c
 create mode 100644 include/linux/irqchip/irq-ixp4xx.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 32d444476a90..0d48faa3e635 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1651,6 +1651,8 @@ M:	Krzysztof Halasa <khalasa@piap.pl>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-ixp4xx/
+F:	drivers/irqchip/irq-ixp4xx.c
+F:	include/linux/irqchip/irq-ixp4xx.h
 
 ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
 M:	Jonathan Cameron <jic23@cam.ac.uk>
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 3d1e60779078..c7e09913826b 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -150,6 +150,12 @@ config IMGPDC_IRQ
 	select GENERIC_IRQ_CHIP
 	select IRQ_DOMAIN
 
+config IXP4XX_IRQ
+	bool
+	select IRQ_DOMAIN
+	select GENERIC_IRQ_MULTI_HANDLER
+	select SPARSE_IRQ
+
 config MADERA_IRQ
 	tristate
 
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c93713d24b86..06139d612108 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_ATMEL_AIC5_IRQ)	+= irq-atmel-aic-common.o irq-atmel-aic5.o
 obj-$(CONFIG_I8259)			+= irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU)		+= irq-mips-cpu.o
+obj-$(CONFIG_IXP4XX_IRQ)		+= irq-ixp4xx.o
 obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
 obj-$(CONFIG_JCORE_AIC)			+= irq-jcore-aic.o
 obj-$(CONFIG_RDA_INTC)			+= irq-rda-intc.o
diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c
new file mode 100644
index 000000000000..7deaf0f82a53
--- /dev/null
+++ b/drivers/irqchip/irq-ixp4xx.c
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * irqchip for the IXP4xx interrupt controller
+ * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * Based on arch/arm/mach-ixp4xx/common.c
+ * Copyright 2002 (C) Intel Corporation
+ * Copyright 2003-2004 (C) MontaVista, Software, Inc.
+ * Copyright (C) Deepak Saxena <dsaxena@plexity.net>
+ */
+#include <linux/bitops.h>
+#include <linux/gpio/driver.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/irq-ixp4xx.h>
+#include <linux/irqdomain.h>
+#include <linux/platform_device.h>
+#include <linux/cpu.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#define IXP4XX_ICPR	0x00 /* Interrupt Status */
+#define IXP4XX_ICMR	0x04 /* Interrupt Enable */
+#define IXP4XX_ICLR	0x08 /* Interrupt IRQ/FIQ Select */
+#define IXP4XX_ICIP	0x0C /* IRQ Status */
+#define IXP4XX_ICFP	0x10 /* FIQ Status */
+#define IXP4XX_ICHR	0x14 /* Interrupt Priority */
+#define IXP4XX_ICIH	0x18 /* IRQ Highest Pri Int */
+#define IXP4XX_ICFH	0x1C /* FIQ Highest Pri Int */
+
+/* IXP43x and IXP46x-only */
+#define	IXP4XX_ICPR2	0x20 /* Interrupt Status 2 */
+#define	IXP4XX_ICMR2	0x24 /* Interrupt Enable 2 */
+#define	IXP4XX_ICLR2	0x28 /* Interrupt IRQ/FIQ Select 2 */
+#define IXP4XX_ICIP2	0x2C /* IRQ Status */
+#define IXP4XX_ICFP2	0x30 /* FIQ Status */
+#define IXP4XX_ICEEN	0x34 /* Error High Pri Enable */
+
+/**
+ * struct ixp4xx_irq - state container for the Faraday IRQ controller
+ * @irqbase: IRQ controller memory base in virtual memory
+ * @is_356: if this is an IXP43x, IXP45x or IX46x SoC (with 64 IRQs)
+ * @irqchip: irqchip for this instance
+ * @domain: IRQ domain for this instance
+ */
+struct ixp4xx_irq {
+	void __iomem *irqbase;
+	bool is_356;
+	struct irq_chip irqchip;
+	struct irq_domain *domain;
+};
+
+/* Local static state container */
+static struct ixp4xx_irq ixirq;
+
+/* GPIO Clocks */
+#define IXP4XX_GPIO_CLK_0		14
+#define IXP4XX_GPIO_CLK_1		15
+
+static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
+{
+	/* All are level active high (asserted) here */
+	return 0;
+}
+
+static void ixp4xx_irq_mask(struct irq_data *d)
+{
+	struct ixp4xx_irq *ixi = irq_data_get_irq_chip_data(d);
+	u32 val;
+
+	if (ixi->is_356 && d->hwirq >= 32) {
+		val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2);
+		val &= ~BIT(d->hwirq - 32);
+		__raw_writel(val, ixi->irqbase + IXP4XX_ICMR2);
+	} else {
+		val = __raw_readl(ixi->irqbase + IXP4XX_ICMR);
+		val &= ~BIT(d->hwirq);
+		__raw_writel(val, ixi->irqbase + IXP4XX_ICMR);
+	}
+}
+
+/*
+ * Level triggered interrupts on GPIO lines can only be cleared when the
+ * interrupt condition disappears.
+ */
+static void ixp4xx_irq_unmask(struct irq_data *d)
+{
+	struct ixp4xx_irq *ixi = irq_data_get_irq_chip_data(d);
+	u32 val;
+
+	if (ixi->is_356 && d->hwirq >= 32) {
+		val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2);
+		val |= BIT(d->hwirq - 32);
+		__raw_writel(val, ixi->irqbase + IXP4XX_ICMR2);
+	} else {
+		val = __raw_readl(ixi->irqbase + IXP4XX_ICMR);
+		val |= BIT(d->hwirq);
+		__raw_writel(val, ixi->irqbase + IXP4XX_ICMR);
+	}
+}
+
+asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs)
+{
+	struct ixp4xx_irq *ixi = &ixirq;
+	unsigned long status;
+	int i;
+
+	status = __raw_readl(ixi->irqbase + IXP4XX_ICIP);
+	for_each_set_bit(i, &status, 32)
+		handle_domain_irq(ixi->domain, i, regs);
+
+	/*
+	 * IXP465/IXP435 has an upper IRQ status register
+	 */
+	if (ixi->is_356) {
+		status = __raw_readl(ixi->irqbase + IXP4XX_ICIP2);
+		for_each_set_bit(i, &status, 32)
+			handle_domain_irq(ixi->domain, i + 32, regs);
+	}
+}
+
+static int ixp4xx_irq_domain_translate(struct irq_domain *domain,
+				       struct irq_fwspec *fwspec,
+				       unsigned long *hwirq,
+				       unsigned int *type)
+{
+	/* We support standard DT translation */
+	if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		return 0;
+	}
+
+	if (is_fwnode_irqchip(fwspec->fwnode)) {
+		if (fwspec->param_count != 2)
+			return -EINVAL;
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		WARN_ON(*type == IRQ_TYPE_NONE);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int ixp4xx_irq_domain_alloc(struct irq_domain *d,
+				   unsigned int irq, unsigned int nr_irqs,
+				   void *data)
+{
+	struct ixp4xx_irq *ixi = d->host_data;
+	irq_hw_number_t hwirq;
+	unsigned int type = IRQ_TYPE_NONE;
+	struct irq_fwspec *fwspec = data;
+	int ret;
+	int i;
+
+	ret = ixp4xx_irq_domain_translate(d, fwspec, &hwirq, &type);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < nr_irqs; i++) {
+		/*
+		 * TODO: after converting IXP4xx to only device tree, set
+		 * handle_bad_irq as default handler and assume all consumers
+		 * call .set_type() as this is provided in the second cell in
+		 * the device tree phandle.
+		 */
+		irq_domain_set_info(d,
+				    irq + i,
+				    hwirq + i,
+				    &ixi->irqchip,
+				    ixi,
+				    handle_level_irq,
+				    NULL, NULL);
+		irq_set_probe(irq + i);
+	}
+
+	return 0;
+}
+
+/*
+ * This needs to be a hierarchical irqdomain to work well with the
+ * GPIO irqchip (which is lower in the hierarchy)
+ */
+static const struct irq_domain_ops ixp4xx_irqdomain_ops = {
+	.translate = ixp4xx_irq_domain_translate,
+	.alloc = ixp4xx_irq_domain_alloc,
+	.free = irq_domain_free_irqs_common,
+};
+
+/**
+ * ixp4xx_get_irq_domain() - retrieve the ixp4xx irq domain
+ *
+ * This function will go away when we transition to DT probing.
+ */
+struct irq_domain *ixp4xx_get_irq_domain(void)
+{
+	struct ixp4xx_irq *ixi = &ixirq;
+
+	return ixi->domain;
+}
+EXPORT_SYMBOL_GPL(ixp4xx_get_irq_domain);
+
+/*
+ * This is the Linux IRQ to hwirq mapping table. This goes away when
+ * we have DT support as all IRQ resources are defined in the device
+ * tree. It will register all the IRQs that are not used by the hierarchical
+ * GPIO IRQ chip. The "holes" inbetween these IRQs will be requested by
+ * the GPIO driver using . This is a step-gap solution.
+ */
+struct ixp4xx_irq_chunk {
+	int irq;
+	int hwirq;
+	int nr_irqs;
+};
+
+static const struct ixp4xx_irq_chunk ixp4xx_irq_chunks[] = {
+	{
+		.irq = 16,
+		.hwirq = 0,
+		.nr_irqs = 6,
+	},
+	{
+		.irq = 24,
+		.hwirq = 8,
+		.nr_irqs = 11,
+	},
+	{
+		.irq = 46,
+		.hwirq = 30,
+		.nr_irqs = 2,
+	},
+	/* Only on the 436 variants */
+	{
+		.irq = 48,
+		.hwirq = 32,
+		.nr_irqs = 10,
+	},
+};
+
+/**
+ * ixp4x_irq_setup() - Common setup code for the IXP4xx interrupt controller
+ * @ixi: State container
+ * @irqbase: Virtual memory base for the interrupt controller
+ * @fwnode: Corresponding fwnode abstraction for this controller
+ * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant
+ */
+static int ixp4xx_irq_setup(struct ixp4xx_irq *ixi,
+			    void __iomem *irqbase,
+			    struct fwnode_handle *fwnode,
+			    bool is_356)
+{
+	int nr_irqs;
+
+	ixi->irqbase = irqbase;
+	ixi->is_356 = is_356;
+
+	/* Route all sources to IRQ instead of FIQ */
+	__raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR);
+
+	/* Disable all interrupts */
+	__raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR);
+
+	if (is_356) {
+		/* Route upper 32 sources to IRQ instead of FIQ */
+		__raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR2);
+
+		/* Disable upper 32 interrupts */
+		__raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR2);
+
+		nr_irqs = 64;
+	} else {
+		nr_irqs = 32;
+	}
+
+	ixi->irqchip.name = "IXP4xx";
+	ixi->irqchip.irq_mask = ixp4xx_irq_mask;
+	ixi->irqchip.irq_unmask	= ixp4xx_irq_unmask;
+	ixi->irqchip.irq_set_type = ixp4xx_set_irq_type;
+
+	ixi->domain = irq_domain_create_linear(fwnode, nr_irqs,
+					       &ixp4xx_irqdomain_ops,
+					       ixi);
+	if (!ixi->domain) {
+		pr_crit("IXP4XX: can not add primary irqdomain\n");
+		return -ENODEV;
+	}
+
+	set_handle_irq(ixp4xx_handle_irq);
+
+	return 0;
+}
+
+/**
+ * ixp4xx_irq_init() - Function to initialize the irqchip from boardfiles
+ * @irqbase: physical base for the irq controller
+ * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant
+ */
+void __init ixp4xx_irq_init(resource_size_t irqbase,
+			    bool is_356)
+{
+	struct ixp4xx_irq *ixi = &ixirq;
+	void __iomem *base;
+	struct fwnode_handle *fwnode;
+	struct irq_fwspec fwspec;
+	int nr_chunks;
+	int ret;
+	int i;
+
+	base = ioremap(irqbase, 0x100);
+	if (!base) {
+		pr_crit("IXP4XX: could not ioremap interrupt controller\n");
+		return;
+	}
+	fwnode = irq_domain_alloc_fwnode(base);
+	if (!fwnode) {
+		pr_crit("IXP4XX: no domain handle\n");
+		return;
+	}
+	ret = ixp4xx_irq_setup(ixi, base, fwnode, is_356);
+	if (ret) {
+		pr_crit("IXP4XX: failed to set up irqchip\n");
+		irq_domain_free_fwnode(fwnode);
+	}
+
+	nr_chunks = ARRAY_SIZE(ixp4xx_irq_chunks);
+	if (!is_356)
+		nr_chunks--;
+
+	/*
+	 * After adding OF support, this is no longer needed: irqs
+	 * will be allocated for the respective fwnodes.
+	 */
+	for (i = 0; i < nr_chunks; i++) {
+		const struct ixp4xx_irq_chunk *chunk = &ixp4xx_irq_chunks[i];
+
+		pr_info("Allocate Linux IRQs %d..%d HW IRQs %d..%d\n",
+			chunk->irq, chunk->irq + chunk->nr_irqs - 1,
+			chunk->hwirq, chunk->hwirq + chunk->nr_irqs - 1);
+		fwspec.fwnode = fwnode;
+		fwspec.param[0] = chunk->hwirq;
+		fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
+		fwspec.param_count = 2;
+		ret = __irq_domain_alloc_irqs(ixi->domain,
+					      chunk->irq,
+					      chunk->nr_irqs,
+					      NUMA_NO_NODE,
+					      &fwspec,
+					      false,
+					      NULL);
+		if (ret < 0) {
+			pr_crit("IXP4XX: can not allocate irqs in hierarchy %d\n",
+				ret);
+			return;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(ixp4xx_irq_init);
diff --git a/include/linux/irqchip/irq-ixp4xx.h b/include/linux/irqchip/irq-ixp4xx.h
new file mode 100644
index 000000000000..9395917d6936
--- /dev/null
+++ b/include/linux/irqchip/irq-ixp4xx.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __IRQ_IXP4XX_H
+#define __IRQ_IXP4XX_H
+
+#include <linux/ioport.h>
+struct irq_domain;
+
+void ixp4xx_irq_init(resource_size_t irqbase,
+		     bool is_356);
+struct irq_domain *ixp4xx_get_irq_domain(void);
+
+#endif /* __IRQ_IXP4XX_H */
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 05/17 v1] gpio: ixp4xx: Add driver for the IXP4xx GPIO
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (3 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 04/17 v1] irqchip: Add driver for IXP4xx Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-06 16:03   ` Bartosz Golaszewski
  2019-02-03 21:41 ` [PATCH 06/17 v1] ARM: ixp4xx: Switch to use new IRQ+GPIO drivers Linus Walleij
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Bartosz Golaszewski, Tim Harvey, Linus Walleij,
	Arnd Bergmann

This adds a driver for the IXP4xx GPIO block found in
the Intel XScale IXP4xx systems.

The GPIO part of this block is pretty straight-forward and
just uses the generic MMIO GPIO library.

The irqchip side of this driver is hierarchical where
the main irqchip will receive a processed level trigger
in response to the edge detector of the GPIO block,
so for this reason the v2 version of the irqdomain API
is used (as well as in the parent IXP4xx irqchip) and
masking, unmasking and setting up the type on IRQ
happens on several levels.

Currently this GPIO controller will grab the parent
irqdomain using a special function, but as the platform
move toward device tree probing, this will not be needed:
we can just look up the parent irqdomain from the device
tree.

Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Bartosz: looking for your ACK on this, it'd be good if
the other GPIO maintainer is aligned with my ideas here.
I intend to merge this through the ARM SoC tree.
---
 MAINTAINERS                |   1 +
 drivers/gpio/Kconfig       |  12 +
 drivers/gpio/Makefile      |   1 +
 drivers/gpio/gpio-ixp4xx.c | 443 +++++++++++++++++++++++++++++++++++++
 4 files changed, 457 insertions(+)
 create mode 100644 drivers/gpio/gpio-ixp4xx.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0d48faa3e635..6c161bd82238 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1651,6 +1651,7 @@ M:	Krzysztof Halasa <khalasa@piap.pl>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-ixp4xx/
+F:	drivers/gpio/gpio-ixp4xx.c
 F:	drivers/irqchip/irq-ixp4xx.c
 F:	include/linux/irqchip/irq-ixp4xx.h
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 699a8118c433..fe4a47e49a24 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -286,6 +286,18 @@ config GPIO_IOP
 
 	  If unsure, say N.
 
+config GPIO_IXP4XX
+	bool "Intel IXP4xx GPIO"
+	depends on ARCH_IXP4XX || COMPILE_TEST
+	select GPIO_GENERIC
+	select IRQ_DOMAIN
+	select IRQ_DOMAIN_HIERARCHY
+	help
+	  Say yes here to support the GPIO functionality of a number of Intel
+	  IXP4xx series of chips.
+
+	  If unsure, say N.
+
 config GPIO_LOONGSON
 	bool "Loongson-2/3 GPIO support"
 	depends on CPU_LOONGSON2 || CPU_LOONGSON3
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 0568bbe6fe68..cf66523b5eec 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_GPIO_HLWD)		+= gpio-hlwd.o
 obj-$(CONFIG_HTC_EGPIO)		+= gpio-htc-egpio.o
 obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
 obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
+obj-$(CONFIG_GPIO_IXP4XX)	+= gpio-ixp4xx.o
 obj-$(CONFIG_GPIO_IT87)		+= gpio-it87.o
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
 obj-$(CONFIG_GPIO_KEMPLD)	+= gpio-kempld.o
diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
new file mode 100644
index 000000000000..44c24948379d
--- /dev/null
+++ b/drivers/gpio/gpio-ixp4xx.c
@@ -0,0 +1,443 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IXP4 GPIO driver
+ * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * based on previous work and know-how from:
+ * Deepak Saxena <dsaxena@plexity.net>
+ */
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+/* Include that go away with DT transition */
+#include <linux/irqchip/irq-ixp4xx.h>
+#include <asm/mach-types.h>
+
+#define IXP4XX_GPIO_GPOUTR	0x00
+#define IXP4XX_GPIO_GPOER	0x04
+#define IXP4XX_GPIO_GPINR	0x08
+#define IXP4XX_GPIO_GPISR	0x0C
+#define IXP4XX_GPIO_GPIT1R	0x10
+#define IXP4XX_GPIO_GPIT2R	0x14
+#define IXP4XX_GPIO_GPCLKR	0x18
+#define IXP4XX_GPIO_GPDBSELR	0x1C
+
+/*
+ * The hardware uses 3 bits to indicate interrupt "style".
+ * we clear and set these three bits accordingly. The lower 24
+ * bits in two registers (GPIT1R and GPIT2R) are used to set up
+ * the style for 8 lines each for a total of 16 GPIO lines.
+ */
+#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH	0x0
+#define IXP4XX_GPIO_STYLE_ACTIVE_LOW	0x1
+#define IXP4XX_GPIO_STYLE_RISING_EDGE	0x2
+#define IXP4XX_GPIO_STYLE_FALLING_EDGE	0x3
+#define IXP4XX_GPIO_STYLE_TRANSITIONAL	0x4
+#define IXP4XX_GPIO_STYLE_MASK		0x7
+#define IXP4XX_GPIO_STYLE_SIZE		3
+
+/**
+ * struct ixp4xx_gpio - IXP4 GPIO state container
+ * @dev: containing device for this instance
+ * @fwnode: the fwnode for this GPIO chip
+ * @gc: gpiochip for this instance
+ * @domain: irqdomain for this chip instance
+ * @base: remapped I/O-memory base
+ * @irq_edge: Each bit represents an IRQ: 1: edge-triggered,
+ * 0: level triggered
+ */
+struct ixp4xx_gpio {
+	struct device *dev;
+	struct fwnode_handle *fwnode;
+	struct gpio_chip gc;
+	struct irq_domain *domain;
+	void __iomem *base;
+	unsigned long long irq_edge;
+};
+
+/**
+ * struct ixp4xx_gpio_map - IXP4 GPIO to parent IRQ map
+ * @gpio_offset: offset of the IXP4 GPIO line
+ * @parent_hwirq: hwirq on the parent IRQ controller
+ */
+struct ixp4xx_gpio_map {
+	int gpio_offset;
+	int parent_hwirq;
+};
+
+/* GPIO lines 0..12 have corresponding IRQs, GPIOs 13..15 have no IRQs */
+const struct ixp4xx_gpio_map ixp4xx_gpiomap[] = {
+	{ .gpio_offset = 0, .parent_hwirq = 6 },
+	{ .gpio_offset = 1, .parent_hwirq = 7 },
+	{ .gpio_offset = 2, .parent_hwirq = 19 },
+	{ .gpio_offset = 3, .parent_hwirq = 20 },
+	{ .gpio_offset = 4, .parent_hwirq = 21 },
+	{ .gpio_offset = 5, .parent_hwirq = 22 },
+	{ .gpio_offset = 6, .parent_hwirq = 23 },
+	{ .gpio_offset = 7, .parent_hwirq = 24 },
+	{ .gpio_offset = 8, .parent_hwirq = 25 },
+	{ .gpio_offset = 9, .parent_hwirq = 26 },
+	{ .gpio_offset = 10, .parent_hwirq = 27 },
+	{ .gpio_offset = 11, .parent_hwirq = 28 },
+	{ .gpio_offset = 12, .parent_hwirq = 29 },
+};
+
+static void ixp4xx_gpio_irq_ack(struct irq_data *d)
+{
+	struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+
+	__raw_writel(BIT(d->hwirq), g->base + IXP4XX_GPIO_GPISR);
+}
+
+static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
+{
+	struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+
+	/* ACK when unmasking if not edge-triggered */
+	if (!(g->irq_edge & BIT(d->hwirq)))
+		ixp4xx_gpio_irq_ack(d);
+
+	irq_chip_unmask_parent(d);
+}
+
+static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
+	int line = d->hwirq;
+	u32 int_style;
+	unsigned long flags;
+	u32 int_reg;
+	u32 val;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_BOTH:
+		irq_set_handler_locked(d, handle_edge_irq);
+		int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
+		g->irq_edge |= BIT(d->hwirq);
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		irq_set_handler_locked(d, handle_edge_irq);
+		int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
+		g->irq_edge |= BIT(d->hwirq);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		irq_set_handler_locked(d, handle_edge_irq);
+		int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
+		g->irq_edge |= BIT(d->hwirq);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		irq_set_handler_locked(d, handle_level_irq);
+		int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
+		g->irq_edge &= ~BIT(d->hwirq);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		irq_set_handler_locked(d, handle_level_irq);
+		int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
+		g->irq_edge &= ~BIT(d->hwirq);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (line >= 8) {
+		/* pins 8-15 */
+		line -= 8;
+		int_reg = IXP4XX_GPIO_GPIT2R;
+	} else {
+		/* pins 0-7 */
+		int_reg = IXP4XX_GPIO_GPIT1R;
+	}
+
+	spin_lock_irqsave(&g->gc.bgpio_lock, flags);
+
+	/* Clear the style for the appropriate pin */
+	val = __raw_readl(g->base + int_reg);
+	val &= ~(IXP4XX_GPIO_STYLE_MASK << (line * IXP4XX_GPIO_STYLE_SIZE));
+	__raw_writel(val, g->base + int_reg);
+
+	__raw_writel(BIT(line), g->base + IXP4XX_GPIO_GPISR);
+
+	/* Set the new style */
+	val = __raw_readl(g->base + int_reg);
+	val |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
+	__raw_writel(val, g->base + int_reg);
+
+	/* Force-configure this line as an input */
+	val = __raw_readl(g->base + IXP4XX_GPIO_GPOER);
+	val |= BIT(d->hwirq);
+	__raw_writel(val, g->base + IXP4XX_GPIO_GPOER);
+
+	spin_unlock_irqrestore(&g->gc.bgpio_lock, flags);
+
+	/* This parent only accept level high (asserted) */
+	return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
+}
+
+static struct irq_chip ixp4xx_gpio_irqchip = {
+	.name = "IXP4GPIO",
+	.irq_ack = ixp4xx_gpio_irq_ack,
+	.irq_mask = irq_chip_mask_parent,
+	.irq_unmask = ixp4xx_gpio_irq_unmask,
+	.irq_set_type = ixp4xx_gpio_irq_set_type,
+};
+
+static int ixp4xx_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
+{
+	struct ixp4xx_gpio *g = gpiochip_get_data(gc);
+	struct irq_fwspec fwspec;
+
+	fwspec.fwnode = g->fwnode;
+	fwspec.param_count = 2;
+	fwspec.param[0] = offset;
+	fwspec.param[1] = IRQ_TYPE_NONE;
+
+	return irq_create_fwspec_mapping(&fwspec);
+}
+
+static int ixp4xx_gpio_irq_domain_translate(struct irq_domain *domain,
+					    struct irq_fwspec *fwspec,
+					    unsigned long *hwirq,
+					    unsigned int *type)
+{
+
+	/* We support standard DT translation */
+	if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		return 0;
+	}
+
+	/* This goes away when we transition to DT */
+	if (is_fwnode_irqchip(fwspec->fwnode)) {
+		if (fwspec->param_count != 2)
+			return -EINVAL;
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		WARN_ON(*type == IRQ_TYPE_NONE);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int ixp4xx_gpio_irq_domain_alloc(struct irq_domain *d,
+					unsigned int irq, unsigned int nr_irqs,
+					void *data)
+{
+	struct ixp4xx_gpio *g = d->host_data;
+	irq_hw_number_t hwirq;
+	unsigned int type = IRQ_TYPE_NONE;
+	struct irq_fwspec *fwspec = data;
+	int ret;
+	int i;
+
+	ret = ixp4xx_gpio_irq_domain_translate(d, fwspec, &hwirq, &type);
+	if (ret)
+		return ret;
+
+	dev_dbg(g->dev, "allocate IRQ %d..%d, hwirq %lu..%lu\n",
+		irq, irq + nr_irqs - 1,
+		hwirq, hwirq + nr_irqs - 1);
+
+	for (i = 0; i < nr_irqs; i++) {
+		struct irq_fwspec parent_fwspec;
+		const struct ixp4xx_gpio_map *map;
+		int j;
+
+		/* Not all lines support IRQs */
+		for (j = 0; j < ARRAY_SIZE(ixp4xx_gpiomap); j++) {
+			map = &ixp4xx_gpiomap[j];
+			if (map->gpio_offset == hwirq)
+				break;
+		}
+		if (j == ARRAY_SIZE(ixp4xx_gpiomap)) {
+			dev_err(g->dev, "can't look up hwirq %lu\n", hwirq);
+			return -EINVAL;
+		}
+		dev_dbg(g->dev, "found parent hwirq %u\n", map->parent_hwirq);
+
+		/*
+		 * We set handle_bad_irq because the .set_type() should
+		 * always be invoked and set the right type of handler.
+		 */
+		irq_domain_set_info(d,
+				    irq + i,
+				    hwirq + i,
+				    &ixp4xx_gpio_irqchip,
+				    g,
+				    handle_bad_irq,
+				    NULL, NULL);
+		irq_set_probe(irq + i);
+
+		/*
+		 * Create a IRQ fwspec to send up to the parent irqdomain:
+		 * specify the hwirq we address on the parent and tie it
+		 * all together up the chain.
+		 */
+		parent_fwspec.fwnode = d->parent->fwnode;
+		parent_fwspec.param_count = 2;
+		parent_fwspec.param[0] = map->parent_hwirq;
+		/* This parent only handles asserted level IRQs */
+		parent_fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
+		dev_dbg(g->dev, "alloc_irqs_parent for %d parent hwirq %d\n",
+			irq + i, map->parent_hwirq);
+		ret = irq_domain_alloc_irqs_parent(d, irq + i, 1,
+						   &parent_fwspec);
+		if (ret)
+			dev_err(g->dev,
+				"failed to allocate parent hwirq %d for hwirq %lu\n",
+				map->parent_hwirq, hwirq);
+	}
+
+	return 0;
+}
+
+static const struct irq_domain_ops ixp4xx_gpio_irqdomain_ops = {
+	.translate = ixp4xx_gpio_irq_domain_translate,
+	.alloc = ixp4xx_gpio_irq_domain_alloc,
+	.free = irq_domain_free_irqs_common,
+};
+
+static int ixp4xx_gpio_probe(struct platform_device *pdev)
+{
+	unsigned long flags;
+	struct device *dev = &pdev->dev;
+	struct irq_domain *parent;
+	struct resource *res;
+	struct ixp4xx_gpio *g;
+	int ret;
+	int i;
+
+	g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
+	if (!g)
+		return -ENOMEM;
+	g->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	g->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(g->base)) {
+		dev_err(dev, "ioremap error\n");
+		return PTR_ERR(g->base);
+	}
+
+	/*
+	 * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on
+	 * specific machines.
+	 */
+	if (machine_is_dsmg600() || machine_is_nas100d())
+		__raw_writel(0x0, g->base + IXP4XX_GPIO_GPCLKR);
+
+	/*
+	 * This is a very special big-endian ARM issue: when the IXP4xx is
+	 * run in big endian mode, all registers in the machine are switched
+	 * around to the CPU-native endianness. As you see mostly in the
+	 * driver we use __raw_readl()/__raw_writel() to access the registers
+	 * in the appropriate order. With the GPIO library we need to specify
+	 * byte order explicitly, so this flag needs to be set when compiling
+	 * for big endian.
+	 */
+#if defined(CONFIG_CPU_BIG_ENDIAN)
+	flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
+#else
+	flags = 0;
+#endif
+
+	/* Populate and register gpio chip */
+	ret = bgpio_init(&g->gc, dev, 4,
+			 g->base + IXP4XX_GPIO_GPINR,
+			 g->base + IXP4XX_GPIO_GPOUTR,
+			 NULL,
+			 NULL,
+			 g->base + IXP4XX_GPIO_GPOER,
+			 flags);
+	if (ret) {
+		dev_err(dev, "unable to init generic GPIO\n");
+		return ret;
+	}
+	g->gc.to_irq = ixp4xx_gpio_to_irq;
+	g->gc.ngpio = 16;
+	g->gc.label = "IXP4XX_GPIO_CHIP";
+	/*
+	 * TODO: when we have migrated to device tree and all GPIOs
+	 * are fetched using phandles, set this to -1 to get rid of
+	 * the fixed gpiochip base.
+	 */
+	g->gc.base = 0;
+	g->gc.parent = &pdev->dev;
+	g->gc.owner = THIS_MODULE;
+
+	ret = devm_gpiochip_add_data(dev, &g->gc, g);
+	if (ret) {
+		dev_err(dev, "failed to add SoC gpiochip\n");
+		return ret;
+	}
+
+	/*
+	 * When we convert to device tree we will simply look up the
+	 * parent irqdomain using irq_find_host(parent) as parent comes
+	 * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
+	 * the fwnode. For now we need this boardfile style code.
+	 */
+	parent = ixp4xx_get_irq_domain();
+	g->fwnode = irq_domain_alloc_fwnode(g->base);
+	if (!g->fwnode) {
+		dev_err(dev, "no domain base\n");
+		return -ENODEV;
+	}
+	g->domain = irq_domain_create_hierarchy(parent,
+						IRQ_DOMAIN_FLAG_HIERARCHY,
+						ARRAY_SIZE(ixp4xx_gpiomap),
+						g->fwnode,
+						&ixp4xx_gpio_irqdomain_ops,
+						g);
+	if (!g->domain) {
+		irq_domain_free_fwnode(g->fwnode);
+		dev_err(dev, "no hierarchical irq domain\n");
+		return ret;
+	}
+
+	/*
+	 * After adding OF support, this is no longer needed: irqs
+	 * will be allocated for the respective fwnodes.
+	 */
+	for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
+		const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
+		struct irq_fwspec fwspec;
+
+		fwspec.fwnode = g->fwnode;
+		/* This is the hwirq for the GPIO line side of things */
+		fwspec.param[0] = map->gpio_offset;
+		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+		fwspec.param_count = 2;
+		ret = __irq_domain_alloc_irqs(g->domain,
+					      -1, /* just pick something */
+					      1,
+					      NUMA_NO_NODE,
+					      &fwspec,
+					      false,
+					      NULL);
+		if (ret < 0) {
+			irq_domain_free_fwnode(g->fwnode);
+			dev_err(dev,
+				"can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
+				map->gpio_offset, map->parent_hwirq, ret);
+			return ret;
+		}
+	}
+
+	platform_set_drvdata(pdev, g);
+	dev_info(dev, "IXP4 GPIO @%p registered\n", g->base);
+
+	return 0;
+}
+
+static struct platform_driver ixp4xx_gpio_driver = {
+	.driver = {
+		.name		= "ixp4xx-gpio",
+	},
+	.probe = ixp4xx_gpio_probe,
+};
+builtin_platform_driver(ixp4xx_gpio_driver);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 06/17 v1] ARM: ixp4xx: Switch to use new IRQ+GPIO drivers
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (4 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 05/17 v1] gpio: ixp4xx: Add driver for the IXP4xx GPIO Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-03 21:41 ` [PATCH 07/17 v1] clocksource/drivers/ixp4xx: Add driver Linus Walleij
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Jason Cooper, Arnd Bergmann, Marc Zyngier, Tim Harvey,
	Bartosz Golaszewski, Olof Johansson, Thomas Gleixner,
	Linus Walleij

This deletes the old irq+gpiochip combo from the IXP4xx
machine and switches it over to use the new drivers merged
in respective subsystem.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
IRQ+GPIO folks: here you see how I activate those new
drivers. Intended to be merged through ARM SoC.
---
 arch/arm/Kconfig                              |   3 +-
 arch/arm/mach-ixp4xx/common.c                 | 318 ++----------------
 arch/arm/mach-ixp4xx/dsmg600-setup.c          |   3 -
 .../mach-ixp4xx/include/mach/ixp4xx-regs.h    |  89 -----
 arch/arm/mach-ixp4xx/nas100d-setup.c          |   3 -
 5 files changed, 24 insertions(+), 392 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index de2a5647e85d..f6345594cef0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -432,10 +432,11 @@ config ARCH_IXP4XX
 	select DMABOUNCE if PCI
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_MULTI_HANDLER
+	select GPIO_IXP4XX
 	select GPIOLIB
 	select HAVE_PCI
+	select IXP4XX_IRQ
 	select NEED_MACH_IO_H
-	select SPARSE_IRQ
 	select USB_EHCI_BIG_ENDIAN_DESC
 	select USB_EHCI_BIG_ENDIAN_MMIO
 	help
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index aa8fd248c125..71683dfc48f9 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -27,11 +27,11 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 #include <linux/export.h>
-#include <linux/gpio/driver.h>
 #include <linux/cpu.h>
 #include <linux/pci.h>
 #include <linux/sched_clock.h>
 #include <linux/bitops.h>
+#include <linux/irqchip/irq-ixp4xx.h>
 #include <mach/udc.h>
 #include <mach/hardware.h>
 #include <mach/io.h>
@@ -58,7 +58,6 @@
 				       (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
 			(IXP4XX_OST_RELOAD_MASK + 1)
 
-static struct irq_domain *ixp4xx_irqdomain;
 static void __init ixp4xx_clocksource_init(void);
 static void __init ixp4xx_clockevent_init(void);
 static struct clock_event_device clockevent_ixp4xx;
@@ -95,266 +94,18 @@ void __init ixp4xx_map_io(void)
   	iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc));
 }
 
-/*
- * GPIO-functions
- */
-/*
- * The following converted to the real HW bits the gpio_line_config
- */
-/* GPIO pin types */
-#define IXP4XX_GPIO_OUT 		0x1
-#define IXP4XX_GPIO_IN  		0x2
-
-/* GPIO signal types */
-#define IXP4XX_GPIO_LOW			0
-#define IXP4XX_GPIO_HIGH		1
-
-/* GPIO Clocks */
-#define IXP4XX_GPIO_CLK_0		14
-#define IXP4XX_GPIO_CLK_1		15
-
-static void gpio_line_config(u8 line, u32 direction)
-{
-	if (direction == IXP4XX_GPIO_IN)
-		*IXP4XX_GPIO_GPOER |= (1 << line);
-	else
-		*IXP4XX_GPIO_GPOER &= ~(1 << line);
-}
-
-static void gpio_line_get(u8 line, int *value)
-{
-	*value = (*IXP4XX_GPIO_GPINR >> line) & 0x1;
-}
-
-static void gpio_line_set(u8 line, int value)
-{
-	if (value == IXP4XX_GPIO_HIGH)
-	    *IXP4XX_GPIO_GPOUTR |= (1 << line);
-	else if (value == IXP4XX_GPIO_LOW)
-	    *IXP4XX_GPIO_GPOUTR &= ~(1 << line);
-}
-
-/*************************************************************************
- * IXP4xx chipset IRQ handling
- *
- * TODO: GPIO IRQs should be marked invalid until the user of the IRQ
- *       (be it PCI or something else) configures that GPIO line
- *       as an IRQ.
- **************************************************************************/
-enum ixp4xx_irq_type {
-	IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
-};
-
-/* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */
-static unsigned long long ixp4xx_irq_edge = 0;
-
-/*
- * IRQ -> GPIO mapping table
- */
-static signed char irq2gpio[32] = {
-	-1, -1, -1, -1, -1, -1,  0,  1,
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1,  2,  3,  4,  5,  6,
-	 7,  8,  9, 10, 11, 12, -1, -1,
-};
-
-static int ixp4xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
-{
-	int irq;
-
-	for (irq = 0; irq < 32; irq++) {
-		if (irq2gpio[irq] == gpio)
-			return irq;
-	}
-	return -EINVAL;
-}
-
-static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
-{
-	int line = irq2gpio[d->hwirq];
-	u32 int_style;
-	enum ixp4xx_irq_type irq_type;
-	volatile u32 *int_reg;
-
-	/*
-	 * Only for GPIO IRQs
-	 * all other IRQs are simply active low
-	 */
-	if (line < 0)
-		return 0;
-
-	switch (type){
-	case IRQ_TYPE_EDGE_BOTH:
-		int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
-		irq_type = IXP4XX_IRQ_EDGE;
-		break;
-	case IRQ_TYPE_EDGE_RISING:
-		int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
-		irq_type = IXP4XX_IRQ_EDGE;
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
-		irq_type = IXP4XX_IRQ_EDGE;
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
-		irq_type = IXP4XX_IRQ_LEVEL;
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
-		irq_type = IXP4XX_IRQ_LEVEL;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (irq_type == IXP4XX_IRQ_EDGE)
-		ixp4xx_irq_edge |= (1 << d->hwirq);
-	else
-		ixp4xx_irq_edge &= ~(1 << d->hwirq);
-
-	if (line >= 8) {	/* pins 8-15 */
-		line -= 8;
-		int_reg = IXP4XX_GPIO_GPIT2R;
-	} else {		/* pins 0-7 */
-		int_reg = IXP4XX_GPIO_GPIT1R;
-	}
-
-	/* Clear the style for the appropriate pin */
-	*int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
-	    		(line * IXP4XX_GPIO_STYLE_SIZE));
-
-	*IXP4XX_GPIO_GPISR = (1 << line);
-
-	/* Set the new style */
-	*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
-
-	/* Configure the line as an input */
-	gpio_line_config(irq2gpio[d->hwirq], IXP4XX_GPIO_IN);
-
-	return 0;
-}
-
-static void ixp4xx_irq_mask(struct irq_data *d)
-{
-	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->hwirq >= 32)
-		*IXP4XX_ICMR2 &= ~(1 << (d->hwirq - 32));
-	else
-		*IXP4XX_ICMR &= ~(1 << d->hwirq);
-}
-
-static void ixp4xx_irq_ack(struct irq_data *d)
-{
-	int line = (d->hwirq < 32) ? irq2gpio[d->hwirq] : -1;
-
-	if (line >= 0)
-		*IXP4XX_GPIO_GPISR = (1 << line);
-}
-
-/*
- * Level triggered interrupts on GPIO lines can only be cleared when the
- * interrupt condition disappears.
- */
-static void ixp4xx_irq_unmask(struct irq_data *d)
-{
-	if (!(ixp4xx_irq_edge & (1 << d->hwirq)))
-		ixp4xx_irq_ack(d);
-
-	if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->hwirq >= 32)
-		*IXP4XX_ICMR2 |= (1 << (d->hwirq - 32));
-	else
-		*IXP4XX_ICMR |= (1 << d->hwirq);
-}
-
-static struct irq_chip ixp4xx_irq_chip = {
-	.name		= "IXP4xx",
-	.irq_ack	= ixp4xx_irq_ack,
-	.irq_mask	= ixp4xx_irq_mask,
-	.irq_unmask	= ixp4xx_irq_unmask,
-	.irq_set_type	= ixp4xx_set_irq_type,
-};
-
-asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs)
-{
-	unsigned long status;
-	int i;
-
-	status = *IXP4XX_ICIP;
-
-	for_each_set_bit(i, &status, 32)
-		handle_domain_irq(ixp4xx_irqdomain, i, regs);
-
-	/*
-	 * IXP465/IXP435 has an upper IRQ status register
-	 */
-	if ((cpu_is_ixp46x() || cpu_is_ixp43x())) {
-		status = *IXP4XX_ICIP2;
-		for_each_set_bit(i, &status, 32)
-			handle_domain_irq(ixp4xx_irqdomain, i + 32, regs);
-	}
-}
-
-static int ixp4xx_irqdomain_map(struct irq_domain *d, unsigned int irq,
-				irq_hw_number_t hwirq)
-{
-	irq_set_chip_data(irq, &ixp4xx_irq_chip);
-	irq_set_chip_and_handler(irq, &ixp4xx_irq_chip, handle_level_irq);
-	irq_set_probe(irq);
-
-	return 0;
-}
-
-static void ixp4xx_irqdomain_unmap(struct irq_domain *d, unsigned int irq)
-{
-	irq_set_chip_and_handler(irq, NULL, NULL);
-	irq_set_chip_data(irq, NULL);
-}
-
-static const struct irq_domain_ops ixp4xx_irqdomain_ops = {
-	.map = ixp4xx_irqdomain_map,
-	.unmap = ixp4xx_irqdomain_unmap,
-};
-
 void __init ixp4xx_init_irq(void)
 {
-	int nr_irqs;
-
 	/*
 	 * ixp4xx does not implement the XScale PWRMODE register
 	 * so it must not call cpu_do_idle().
 	 */
 	cpu_idle_poll_ctrl(true);
 
-	/* Route all sources to IRQ instead of FIQ */
-	*IXP4XX_ICLR = 0x0;
-
-	/* Disable all interrupt */
-	*IXP4XX_ICMR = 0x0; 
-
-	if (cpu_is_ixp46x() || cpu_is_ixp43x()) {
-		/* Route upper 32 sources to IRQ instead of FIQ */
-		*IXP4XX_ICLR2 = 0x00;
-
-		/* Disable upper 32 interrupts */
-		*IXP4XX_ICMR2 = 0x00;
-
-		nr_irqs = 64;
-	} else {
-		nr_irqs = 32;
-	}
-
-	ixp4xx_irqdomain = irq_domain_add_simple(NULL, nr_irqs, IRQ_IXP4XX_BASE,
-						 &ixp4xx_irqdomain_ops,
-						 NULL);
-	if (!ixp4xx_irqdomain) {
-		pr_crit("can not add primary irqdomain\n");
-		return;
-	}
-
-	set_handle_irq(ixp4xx_handle_irq);
+	ixp4xx_irq_init(IXP4XX_INTC_BASE_PHYS,
+			(cpu_is_ixp46x() || cpu_is_ixp43x()));
 }
 
-
 /*************************************************************************
  * IXP4xx timer tick
  * We use OS timer1 on the CPU for the timer tick and the timestamp 
@@ -408,6 +159,24 @@ static struct resource ixp4xx_udc_resources[] = {
 	},
 };
 
+static struct resource ixp4xx_gpio_resource[] = {
+	{
+		.start = IXP4XX_GPIO_BASE_PHYS,
+		.end = IXP4XX_GPIO_BASE_PHYS + 0xfff,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device ixp4xx_gpio_device = {
+	.name           = "ixp4xx-gpio",
+	.id             = -1,
+	.dev = {
+		.coherent_dma_mask      = DMA_BIT_MASK(32),
+	},
+	.resource = ixp4xx_gpio_resource,
+	.num_resources  = ARRAY_SIZE(ixp4xx_gpio_resource),
+};
+
 /*
  * USB device controller. The IXP4xx uses the same controller as PXA25X,
  * so we just use the same device.
@@ -423,6 +192,7 @@ static struct platform_device ixp4xx_udc_device = {
 };
 
 static struct platform_device *ixp4xx_devices[] __initdata = {
+	&ixp4xx_gpio_device,
 	&ixp4xx_udc_device,
 };
 
@@ -457,56 +227,12 @@ static struct platform_device *ixp46x_devices[] __initdata = {
 unsigned long ixp4xx_exp_bus_size;
 EXPORT_SYMBOL(ixp4xx_exp_bus_size);
 
-static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
-{
-	gpio_line_config(gpio, IXP4XX_GPIO_IN);
-
-	return 0;
-}
-
-static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
-					int level)
-{
-	gpio_line_set(gpio, level);
-	gpio_line_config(gpio, IXP4XX_GPIO_OUT);
-
-	return 0;
-}
-
-static int ixp4xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
-{
-	int value;
-
-	gpio_line_get(gpio, &value);
-
-	return value;
-}
-
-static void ixp4xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio,
-				  int value)
-{
-	gpio_line_set(gpio, value);
-}
-
-static struct gpio_chip ixp4xx_gpio_chip = {
-	.label			= "IXP4XX_GPIO_CHIP",
-	.direction_input	= ixp4xx_gpio_direction_input,
-	.direction_output	= ixp4xx_gpio_direction_output,
-	.get			= ixp4xx_gpio_get_value,
-	.set			= ixp4xx_gpio_set_value,
-	.to_irq			= ixp4xx_gpio_to_irq,
-	.base			= 0,
-	.ngpio			= 16,
-};
-
 void __init ixp4xx_sys_init(void)
 {
 	ixp4xx_exp_bus_size = SZ_16M;
 
 	platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
 
-	gpiochip_add_data(&ixp4xx_gpio_chip, NULL);
-
 	if (cpu_is_ixp46x()) {
 		int region;
 
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 0daaede8fb6d..4d4c62fced71 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -270,9 +270,6 @@ static void __init dsmg600_init(void)
 {
 	ixp4xx_sys_init();
 
-	/* Make sure that GPIO14 and GPIO15 are not used as clocks */
-	*IXP4XX_GPIO_GPCLKR = 0;
-
 	dsmg600_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
 	dsmg600_flash_resource.end =
 		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
index b7ddd27419c2..459abe2eb4b5 100644
--- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
+++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
@@ -147,95 +147,6 @@
 #define IXP4XX_I2C_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x11000)
 #define IXP4XX_SSP_BASE_VIRT		(IXP4XX_PERIPHERAL_BASE_VIRT + 0x12000)
 
-/*
- * Constants to make it easy to access  Interrupt Controller registers
- */
-#define IXP4XX_ICPR_OFFSET	0x00 /* Interrupt Status */
-#define IXP4XX_ICMR_OFFSET	0x04 /* Interrupt Enable */
-#define IXP4XX_ICLR_OFFSET	0x08 /* Interrupt IRQ/FIQ Select */
-#define IXP4XX_ICIP_OFFSET      0x0C /* IRQ Status */
-#define IXP4XX_ICFP_OFFSET	0x10 /* FIQ Status */
-#define IXP4XX_ICHR_OFFSET	0x14 /* Interrupt Priority */
-#define IXP4XX_ICIH_OFFSET	0x18 /* IRQ Highest Pri Int */
-#define IXP4XX_ICFH_OFFSET	0x1C /* FIQ Highest Pri Int */
-
-/*
- * IXP465-only
- */
-#define	IXP4XX_ICPR2_OFFSET	0x20 /* Interrupt Status 2 */
-#define	IXP4XX_ICMR2_OFFSET	0x24 /* Interrupt Enable 2 */
-#define	IXP4XX_ICLR2_OFFSET	0x28 /* Interrupt IRQ/FIQ Select 2 */
-#define IXP4XX_ICIP2_OFFSET     0x2C /* IRQ Status */
-#define IXP4XX_ICFP2_OFFSET	0x30 /* FIQ Status */
-#define IXP4XX_ICEEN_OFFSET	0x34 /* Error High Pri Enable */
-
-
-/*
- * Interrupt Controller Register Definitions.
- */
-
-#define IXP4XX_INTC_REG(x) ((volatile u32 *)(IXP4XX_INTC_BASE_VIRT+(x)))
-
-#define IXP4XX_ICPR	IXP4XX_INTC_REG(IXP4XX_ICPR_OFFSET)
-#define IXP4XX_ICMR     IXP4XX_INTC_REG(IXP4XX_ICMR_OFFSET)
-#define IXP4XX_ICLR     IXP4XX_INTC_REG(IXP4XX_ICLR_OFFSET)
-#define IXP4XX_ICIP     IXP4XX_INTC_REG(IXP4XX_ICIP_OFFSET)
-#define IXP4XX_ICFP     IXP4XX_INTC_REG(IXP4XX_ICFP_OFFSET)
-#define IXP4XX_ICHR     IXP4XX_INTC_REG(IXP4XX_ICHR_OFFSET)
-#define IXP4XX_ICIH     IXP4XX_INTC_REG(IXP4XX_ICIH_OFFSET) 
-#define IXP4XX_ICFH     IXP4XX_INTC_REG(IXP4XX_ICFH_OFFSET)
-#define IXP4XX_ICPR2	IXP4XX_INTC_REG(IXP4XX_ICPR2_OFFSET)
-#define IXP4XX_ICMR2    IXP4XX_INTC_REG(IXP4XX_ICMR2_OFFSET)
-#define IXP4XX_ICLR2    IXP4XX_INTC_REG(IXP4XX_ICLR2_OFFSET)
-#define IXP4XX_ICIP2    IXP4XX_INTC_REG(IXP4XX_ICIP2_OFFSET)
-#define IXP4XX_ICFP2    IXP4XX_INTC_REG(IXP4XX_ICFP2_OFFSET)
-#define IXP4XX_ICEEN    IXP4XX_INTC_REG(IXP4XX_ICEEN_OFFSET)
-                                                                                
-/*
- * Constants to make it easy to access GPIO registers
- */
-#define IXP4XX_GPIO_GPOUTR_OFFSET       0x00
-#define IXP4XX_GPIO_GPOER_OFFSET        0x04
-#define IXP4XX_GPIO_GPINR_OFFSET        0x08
-#define IXP4XX_GPIO_GPISR_OFFSET        0x0C
-#define IXP4XX_GPIO_GPIT1R_OFFSET	0x10
-#define IXP4XX_GPIO_GPIT2R_OFFSET	0x14
-#define IXP4XX_GPIO_GPCLKR_OFFSET	0x18
-#define IXP4XX_GPIO_GPDBSELR_OFFSET	0x1C
-
-/* 
- * GPIO Register Definitions.
- * [Only perform 32bit reads/writes]
- */
-#define IXP4XX_GPIO_REG(x) ((volatile u32 *)(IXP4XX_GPIO_BASE_VIRT+(x)))
-
-#define IXP4XX_GPIO_GPOUTR	IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOUTR_OFFSET)
-#define IXP4XX_GPIO_GPOER       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOER_OFFSET)
-#define IXP4XX_GPIO_GPINR       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPINR_OFFSET)
-#define IXP4XX_GPIO_GPISR       IXP4XX_GPIO_REG(IXP4XX_GPIO_GPISR_OFFSET)
-#define IXP4XX_GPIO_GPIT1R      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT1R_OFFSET)
-#define IXP4XX_GPIO_GPIT2R      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT2R_OFFSET)
-#define IXP4XX_GPIO_GPCLKR      IXP4XX_GPIO_REG(IXP4XX_GPIO_GPCLKR_OFFSET)
-#define IXP4XX_GPIO_GPDBSELR    IXP4XX_GPIO_REG(IXP4XX_GPIO_GPDBSELR_OFFSET)
-
-/*
- * GPIO register bit definitions
- */
-
-/* Interrupt styles
- */
-#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH	0x0
-#define IXP4XX_GPIO_STYLE_ACTIVE_LOW	0x1
-#define IXP4XX_GPIO_STYLE_RISING_EDGE	0x2
-#define IXP4XX_GPIO_STYLE_FALLING_EDGE	0x3
-#define IXP4XX_GPIO_STYLE_TRANSITIONAL	0x4
-
-/* 
- * Mask used to clear interrupt styles 
- */
-#define IXP4XX_GPIO_STYLE_CLEAR		0x7
-#define IXP4XX_GPIO_STYLE_SIZE		3
-
 /*
  * Constants to make it easy to access Timer Control/Status registers
  */
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 9d67f8de0772..c142cfa8c5d6 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -281,9 +281,6 @@ static void __init nas100d_init(void)
 
 	ixp4xx_sys_init();
 
-	/* gpio 14 and 15 are _not_ clocks */
-	*IXP4XX_GPIO_GPCLKR = 0;
-
 	nas100d_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
 	nas100d_flash_resource.end =
 		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 07/17 v1] clocksource/drivers/ixp4xx: Add driver
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (5 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 06/17 v1] ARM: ixp4xx: Switch to use new IRQ+GPIO drivers Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-03 21:41 ` [PATCH 08/17 v1] ARM: ixp4xx: Switch to use new timer driver Linus Walleij
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Arnd Bergmann, Tim Harvey, Daniel Lezcano, Olof Johansson,
	Thomas Gleixner, Linus Walleij

This adds a new slightly rewritten timer driver for the
Intel IXP4xx clocksource, clockevent and delay timer.

Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Clocksource/timer maintainers: I am requesting an ACK for
this once you're happy with the driver, as I intend to
merge all of this IXP4xx rework through ARM SoC.
---
 MAINTAINERS                                |   2 +
 drivers/clocksource/Kconfig                |   7 +
 drivers/clocksource/Makefile               |   1 +
 drivers/clocksource/timer-ixp4xx.c         | 249 +++++++++++++++++++++
 include/linux/platform_data/timer-ixp4xx.h |  11 +
 5 files changed, 270 insertions(+)
 create mode 100644 drivers/clocksource/timer-ixp4xx.c
 create mode 100644 include/linux/platform_data/timer-ixp4xx.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6c161bd82238..a2fb67b75026 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1651,9 +1651,11 @@ M:	Krzysztof Halasa <khalasa@piap.pl>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-ixp4xx/
+F:	drivers/clocksource/timer-ixp4xx.c
 F:	drivers/gpio/gpio-ixp4xx.c
 F:	drivers/irqchip/irq-ixp4xx.c
 F:	include/linux/irqchip/irq-ixp4xx.h
+F:	include/linux/platform_data/timer-ixp4xx.h
 
 ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
 M:	Jonathan Cameron <jic23@cam.ac.uk>
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index a9e26f6a81a1..d290d6c6576d 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -69,6 +69,13 @@ config FTTMR010_TIMER
 	  Enables support for the Faraday Technology timer block
 	  FTTMR010.
 
+config IXP4XX_TIMER
+	bool "Intel XScale IXP4xx timer driver" if COMPILE_TEST
+	depends on HAS_IOMEM
+	select CLKSRC_MMIO
+	help
+	  Enables support for the Intel XScale IXP4xx SoC timer.
+
 config ROCKCHIP_TIMER
 	bool "Rockchip timer driver" if COMPILE_TEST
 	depends on ARM || ARM64
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index cdd210ff89ea..18158257ebb3 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_OMAP_DM_TIMER)	+= timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
 obj-$(CONFIG_DW_APB_TIMER_OF)	+= dw_apb_timer_of.o
 obj-$(CONFIG_FTTMR010_TIMER)	+= timer-fttmr010.o
+obj-$(CONFIG_IXP4XX_TIMER)	+= timer-ixp4xx.o
 obj-$(CONFIG_ROCKCHIP_TIMER)      += timer-rockchip.o
 obj-$(CONFIG_CLKSRC_NOMADIK_MTU)	+= nomadik-mtu.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
diff --git a/drivers/clocksource/timer-ixp4xx.c b/drivers/clocksource/timer-ixp4xx.c
new file mode 100644
index 000000000000..fa78f80792db
--- /dev/null
+++ b/drivers/clocksource/timer-ixp4xx.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IXP4 timer driver
+ * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * Based on arch/arm/mach-ixp4xx/common.c
+ * Copyright 2002 (C) Intel Corporation
+ * Copyright 2003-2004 (C) MontaVista, Software, Inc.
+ * Copyright (C) Deepak Saxena <dsaxena@plexity.net>
+ */
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/sched_clock.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+/* Goes away with OF conversion */
+#include <linux/platform_data/timer-ixp4xx.h>
+
+/*
+ * Constants to make it easy to access Timer Control/Status registers
+ */
+#define IXP4XX_OSTS_OFFSET	0x00  /* Continuous Timestamp */
+#define IXP4XX_OST1_OFFSET	0x04  /* Timer 1 Timestamp */
+#define IXP4XX_OSRT1_OFFSET	0x08  /* Timer 1 Reload */
+#define IXP4XX_OST2_OFFSET	0x0C  /* Timer 2 Timestamp */
+#define IXP4XX_OSRT2_OFFSET	0x10  /* Timer 2 Reload */
+#define IXP4XX_OSWT_OFFSET	0x14  /* Watchdog Timer */
+#define IXP4XX_OSWE_OFFSET	0x18  /* Watchdog Enable */
+#define IXP4XX_OSWK_OFFSET	0x1C  /* Watchdog Key */
+#define IXP4XX_OSST_OFFSET	0x20  /* Timer Status */
+
+/*
+ * Timer register values and bit definitions
+ */
+#define IXP4XX_OST_ENABLE		0x00000001
+#define IXP4XX_OST_ONE_SHOT		0x00000002
+/* Low order bits of reload value ignored */
+#define IXP4XX_OST_RELOAD_MASK		0x00000003
+#define IXP4XX_OST_DISABLED		0x00000000
+#define IXP4XX_OSST_TIMER_1_PEND	0x00000001
+#define IXP4XX_OSST_TIMER_2_PEND	0x00000002
+#define IXP4XX_OSST_TIMER_TS_PEND	0x00000004
+#define IXP4XX_OSST_TIMER_WDOG_PEND	0x00000008
+#define IXP4XX_OSST_TIMER_WARM_RESET	0x00000010
+
+#define	IXP4XX_WDT_KEY			0x0000482E
+#define	IXP4XX_WDT_RESET_ENABLE		0x00000001
+#define	IXP4XX_WDT_IRQ_ENABLE		0x00000002
+#define	IXP4XX_WDT_COUNT_ENABLE		0x00000004
+
+struct ixp4xx_timer {
+	void __iomem *base;
+	unsigned int tick_rate;
+	u32 latch;
+	struct clock_event_device clkevt;
+#ifdef CONFIG_ARM
+	struct delay_timer delay_timer;
+#endif
+};
+
+/*
+ * A local singleton used by sched_clock and delay timer reads, which are
+ * fast and stateless
+ */
+static struct ixp4xx_timer *local_ixp4xx_timer;
+
+static inline struct ixp4xx_timer *
+to_ixp4xx_timer(struct clock_event_device *evt)
+{
+	return container_of(evt, struct ixp4xx_timer, clkevt);
+}
+
+static u64 notrace ixp4xx_read_sched_clock(void)
+{
+	return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET);
+}
+
+static u64 ixp4xx_clocksource_read(struct clocksource *c)
+{
+	return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET);
+}
+
+static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
+{
+	struct ixp4xx_timer *tmr = dev_id;
+	struct clock_event_device *evt = &tmr->clkevt;
+
+	/* Clear Pending Interrupt */
+	__raw_writel(IXP4XX_OSST_TIMER_1_PEND,
+		     tmr->base + IXP4XX_OSST_OFFSET);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static int ixp4xx_set_next_event(unsigned long cycles,
+				 struct clock_event_device *evt)
+{
+	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+	u32 val;
+
+	val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
+	/* Keep enable/oneshot bits */
+	val &= IXP4XX_OST_RELOAD_MASK;
+	__raw_writel((cycles & ~IXP4XX_OST_RELOAD_MASK) | val,
+		     tmr->base + IXP4XX_OSRT1_OFFSET);
+
+	return 0;
+}
+
+static int ixp4xx_shutdown(struct clock_event_device *evt)
+{
+	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+	u32 val;
+
+	val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
+	val &= ~IXP4XX_OST_ENABLE;
+	__raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
+
+	return 0;
+}
+
+static int ixp4xx_set_oneshot(struct clock_event_device *evt)
+{
+	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+
+	__raw_writel(IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT,
+		     tmr->base + IXP4XX_OSRT1_OFFSET);
+
+	return 0;
+}
+
+static int ixp4xx_set_periodic(struct clock_event_device *evt)
+{
+	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+	u32 val;
+
+	val = tmr->latch & ~IXP4XX_OST_RELOAD_MASK;
+	val |= IXP4XX_OST_ENABLE;
+	__raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
+
+	return 0;
+}
+
+static int ixp4xx_resume(struct clock_event_device *evt)
+{
+	struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
+	u32 val;
+
+	val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
+	val |= IXP4XX_OST_ENABLE;
+	__raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
+
+	return 0;
+}
+
+/*
+ * IXP4xx timer tick
+ * We use OS timer1 on the CPU for the timer tick and the timestamp
+ * counter as a source of real clock ticks to account for missed jiffies.
+ */
+static __init int ixp4xx_timer_register(void __iomem *base,
+					int timer_irq,
+					unsigned int timer_freq)
+{
+	struct ixp4xx_timer *tmr;
+	int ret;
+
+	tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
+	if (!tmr)
+		return -ENOMEM;
+	tmr->base = base;
+	tmr->tick_rate = timer_freq;
+
+	/*
+	 * The timer register doesn't allow to specify the two least
+	 * significant bits of the timeout value and assumes them being zero.
+	 * So make sure the latch is the best value with the two least
+	 * significant bits unset.
+	 */
+	tmr->latch = DIV_ROUND_CLOSEST(timer_freq,
+				       (IXP4XX_OST_RELOAD_MASK + 1) * HZ)
+		* (IXP4XX_OST_RELOAD_MASK + 1);
+
+	local_ixp4xx_timer = tmr;
+
+	/* Reset/disable counter */
+	__raw_writel(0, tmr->base + IXP4XX_OSRT1_OFFSET);
+
+	/* Clear any pending interrupt on timer 1 */
+	__raw_writel(IXP4XX_OSST_TIMER_1_PEND,
+		     tmr->base + IXP4XX_OSST_OFFSET);
+
+	/* Reset time-stamp counter */
+	__raw_writel(0, tmr->base + IXP4XX_OSTS_OFFSET);
+
+	clocksource_mmio_init(NULL, "OSTS", timer_freq, 200, 32,
+			      ixp4xx_clocksource_read);
+
+	tmr->clkevt.name = "ixp4xx timer1";
+	tmr->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	tmr->clkevt.rating = 200;
+	tmr->clkevt.set_state_shutdown = ixp4xx_shutdown;
+	tmr->clkevt.set_state_periodic = ixp4xx_set_periodic;
+	tmr->clkevt.set_state_oneshot = ixp4xx_set_oneshot;
+	tmr->clkevt.tick_resume = ixp4xx_resume;
+	tmr->clkevt.set_next_event = ixp4xx_set_next_event;
+	tmr->clkevt.cpumask = cpumask_of(0);
+	tmr->clkevt.irq = timer_irq;
+	ret = request_irq(timer_irq, ixp4xx_timer_interrupt,
+			  IRQF_TIMER, "IXP4XX-TIMER1", tmr);
+	if (ret) {
+		pr_crit("no timer IRQ\n");
+		return -ENODEV;
+	}
+	clockevents_config_and_register(&tmr->clkevt, timer_freq,
+					0xf, 0xfffffffe);
+
+#ifdef CONFIG_ARM
+	sched_clock_register(ixp4xx_read_sched_clock, 32, timer_freq);
+#endif
+
+	return 0;
+}
+
+/**
+ * ixp4xx_timer_setup() - Timer setup function to be called from boardfiles
+ * @timerbase: physical base of timer block
+ * @timer_irq: Linux IRQ number for the timer
+ * @timer_freq: Fixed frequency of the timer
+ */
+void __init ixp4xx_timer_setup(resource_size_t timerbase,
+			       int timer_irq,
+			       unsigned int timer_freq)
+{
+	void __iomem *base;
+
+	base = ioremap(timerbase, 0x100);
+	if (!base) {
+		pr_crit("IXP4xx: can't remap timer\n");
+		return;
+	}
+	ixp4xx_timer_register(base, timer_irq, timer_freq);
+}
+EXPORT_SYMBOL_GPL(ixp4xx_timer_setup);
diff --git a/include/linux/platform_data/timer-ixp4xx.h b/include/linux/platform_data/timer-ixp4xx.h
new file mode 100644
index 000000000000..ee92ae7edaed
--- /dev/null
+++ b/include/linux/platform_data/timer-ixp4xx.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __TIMER_IXP4XX_H
+#define __TIMER_IXP4XX_H
+
+#include <linux/ioport.h>
+
+void __init ixp4xx_timer_setup(resource_size_t timerbase,
+			       int timer_irq,
+			       unsigned int timer_freq);
+
+#endif
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 08/17 v1] ARM: ixp4xx: Switch to use new timer driver
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (6 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 07/17 v1] clocksource/drivers/ixp4xx: Add driver Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-03 21:41 ` [PATCH 09/17 v1] irqchip: ixp4xx: Add DT bindings Linus Walleij
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Arnd Bergmann, Tim Harvey, Daniel Lezcano, Olof Johansson,
	Thomas Gleixner, Linus Walleij

This augments the IXP4xx to select and use the new
timer driver in drivers/clocksource and removes the old
code in the machine.

Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Clocksource/timer maintainers: here you see how I activate
this new driver. Intended to be merged through ARM SoC.
---
 arch/arm/Kconfig              |   2 +-
 arch/arm/mach-ixp4xx/common.c | 153 +---------------------------------
 2 files changed, 5 insertions(+), 150 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f6345594cef0..9f70d7e032d6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -427,7 +427,6 @@ config ARCH_IXP4XX
 	depends on MMU
 	select ARCH_HAS_DMA_SET_COHERENT_MASK
 	select ARCH_SUPPORTS_BIG_ENDIAN
-	select CLKSRC_MMIO
 	select CPU_XSCALE
 	select DMABOUNCE if PCI
 	select GENERIC_CLOCKEVENTS
@@ -436,6 +435,7 @@ config ARCH_IXP4XX
 	select GPIOLIB
 	select HAVE_PCI
 	select IXP4XX_IRQ
+	select IXP4XX_TIMER
 	select NEED_MACH_IO_H
 	select USB_EHCI_BIG_ENDIAN_DESC
 	select USB_EHCI_BIG_ENDIAN_MMIO
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 71683dfc48f9..fc4c9b21ca96 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -22,9 +22,6 @@
 #include <linux/serial_core.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
-#include <linux/time.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
 #include <linux/io.h>
 #include <linux/export.h>
 #include <linux/cpu.h>
@@ -32,6 +29,7 @@
 #include <linux/sched_clock.h>
 #include <linux/bitops.h>
 #include <linux/irqchip/irq-ixp4xx.h>
+#include <linux/platform_data/timer-ixp4xx.h>
 #include <mach/udc.h>
 #include <mach/hardware.h>
 #include <mach/io.h>
@@ -49,19 +47,6 @@
 
 #define IXP4XX_TIMER_FREQ 66666000
 
-/*
- * The timer register doesn't allow to specify the two least significant bits of
- * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is
- * the best value with the two least significant bits unset.
- */
-#define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \
-				       (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \
-			(IXP4XX_OST_RELOAD_MASK + 1)
-
-static void __init ixp4xx_clocksource_init(void);
-static void __init ixp4xx_clockevent_init(void);
-static struct clock_event_device clockevent_ixp4xx;
-
 /*************************************************************************
  * IXP4xx chipset I/O mapping
  *************************************************************************/
@@ -106,37 +91,11 @@ void __init ixp4xx_init_irq(void)
 			(cpu_is_ixp46x() || cpu_is_ixp43x()));
 }
 
-/*************************************************************************
- * IXP4xx timer tick
- * We use OS timer1 on the CPU for the timer tick and the timestamp 
- * counter as a source of real clock ticks to account for missed jiffies.
- *************************************************************************/
-
-static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = dev_id;
-
-	/* Clear Pending Interrupt by writing '1' to it */
-	*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
 void __init ixp4xx_timer_init(void)
 {
-	/* Reset/disable counter */
-	*IXP4XX_OSRT1 = 0;
-
-	/* Clear Pending Interrupt by writing '1' to it */
-	*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
-
-	/* Reset time-stamp counter */
-	*IXP4XX_OSTS = 0;
-
-	ixp4xx_clocksource_init();
-	ixp4xx_clockevent_init();
+	return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS,
+				  IRQ_IXP4XX_TIMER1,
+				  IXP4XX_TIMER_FREQ);
 }
 
 static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
@@ -251,112 +210,8 @@ void __init ixp4xx_sys_init(void)
 			ixp4xx_exp_bus_size >> 20);
 }
 
-/*
- * sched_clock()
- */
-static u64 notrace ixp4xx_read_sched_clock(void)
-{
-	return *IXP4XX_OSTS;
-}
-
-/*
- * clocksource
- */
-
-static u64 ixp4xx_clocksource_read(struct clocksource *c)
-{
-	return *IXP4XX_OSTS;
-}
-
 unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
 EXPORT_SYMBOL(ixp4xx_timer_freq);
-static void __init ixp4xx_clocksource_init(void)
-{
-	sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq);
-
-	clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32,
-			ixp4xx_clocksource_read);
-}
-
-/*
- * clockevents
- */
-static int ixp4xx_set_next_event(unsigned long evt,
-				 struct clock_event_device *unused)
-{
-	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
-
-	*IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts;
-
-	return 0;
-}
-
-static int ixp4xx_shutdown(struct clock_event_device *evt)
-{
-	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
-	unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
-
-	opts &= ~IXP4XX_OST_ENABLE;
-	*IXP4XX_OSRT1 = osrt | opts;
-	return 0;
-}
-
-static int ixp4xx_set_oneshot(struct clock_event_device *evt)
-{
-	unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT;
-	unsigned long osrt = 0;
-
-	/* period set by 'set next_event' */
-	*IXP4XX_OSRT1 = osrt | opts;
-	return 0;
-}
-
-static int ixp4xx_set_periodic(struct clock_event_device *evt)
-{
-	unsigned long opts = IXP4XX_OST_ENABLE;
-	unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK;
-
-	*IXP4XX_OSRT1 = osrt | opts;
-	return 0;
-}
-
-static int ixp4xx_resume(struct clock_event_device *evt)
-{
-	unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK;
-	unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK;
-
-	opts |= IXP4XX_OST_ENABLE;
-	*IXP4XX_OSRT1 = osrt | opts;
-	return 0;
-}
-
-static struct clock_event_device clockevent_ixp4xx = {
-	.name			= "ixp4xx timer1",
-	.features		= CLOCK_EVT_FEAT_PERIODIC |
-				  CLOCK_EVT_FEAT_ONESHOT,
-	.rating			= 200,
-	.set_state_shutdown	= ixp4xx_shutdown,
-	.set_state_periodic	= ixp4xx_set_periodic,
-	.set_state_oneshot	= ixp4xx_set_oneshot,
-	.tick_resume		= ixp4xx_resume,
-	.set_next_event		= ixp4xx_set_next_event,
-};
-
-static void __init ixp4xx_clockevent_init(void)
-{
-	int ret;
-
-	clockevent_ixp4xx.cpumask = cpumask_of(0);
-	clockevent_ixp4xx.irq = IRQ_IXP4XX_TIMER1;
-	ret = request_irq(IRQ_IXP4XX_TIMER1, ixp4xx_timer_interrupt,
-			  IRQF_TIMER, "IXP4XX-TIMER1", &clockevent_ixp4xx);
-	if (ret) {
-		pr_crit("no timer IRQ\n");
-		return;
-	}
-	clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ,
-					0xf, 0xfffffffe);
-}
 
 void ixp4xx_restart(enum reboot_mode mode, const char *cmd)
 {
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 09/17 v1] irqchip: ixp4xx: Add DT bindings
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (7 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 08/17 v1] ARM: ixp4xx: Switch to use new timer driver Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-18 21:25   ` Rob Herring
  2019-02-03 21:41 ` [PATCH 10/17 v1] irqchip: ixp4xx: Add OF initialization support Linus Walleij
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: devicetree, Jason Cooper, Arnd Bergmann, Marc Zyngier,
	Tim Harvey, Olof Johansson, Thomas Gleixner, Linus Walleij

This adds device tree bindings for the IXP4xx interrupt
controller. It's a standard 2-cell controller.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: devicetree@vger.kernel.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
irqchip maintainers: I am requesting an ACK for this once
you're happy with the bindings, as I intend to merge all of
this IXP4xx rework through ARM SoC.
---
 .../intel,ixp4xx-interrupt.txt                | 33 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
new file mode 100644
index 000000000000..70ee93b9a6c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
@@ -0,0 +1,33 @@
+* Intel IXP4xx XScale Networking Processors Interrupt Controller
+
+This interrupt controller is found in the Intel IXP4xx processors.
+Some processors have 32 interrupts, some have up to 64 interrupts.
+The exact number of interrupts is determined from the compatible
+string.
+
+The distinct IXP4xx families with different interrupt controller
+variations are IXP42x, IXP43x, IXP45x and IXP46x. Those four
+families were the only ones to reach the developer and consumer
+market.
+
+Required properties:
+- compatible: must be one of
+  "intel,ixp42x-interrupt"
+  "intel,ixp43x-interrupt"
+  "intel,ixp45x-interrupt"
+  "intel,ixp46x-interrupt"
+- reg: The register bank for the interrupt controller.
+- interrupt-controller: Identifies the node as an interrupt controller
+- #interrupt-cells: The number of cells to define the interrupts.
+  Must be <2>. The bindings follows the standard binding for controllers
+  with two cells specified in
+  interrupt-controller/interrupts.txt
+
+Example:
+
+intcon: interrupt-controller@c8003000 {
+	compatible = "intel,ixp43x-interrupt";
+	reg = <0xc8003000 0x100>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index a2fb67b75026..ec318f09540c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1650,6 +1650,7 @@ M:	Imre Kaloz <kaloz@openwrt.org>
 M:	Krzysztof Halasa <khalasa@piap.pl>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
+F:	Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
 F:	arch/arm/mach-ixp4xx/
 F:	drivers/clocksource/timer-ixp4xx.c
 F:	drivers/gpio/gpio-ixp4xx.c
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 10/17 v1] irqchip: ixp4xx: Add OF initialization support
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (8 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 09/17 v1] irqchip: ixp4xx: Add DT bindings Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-03 21:41 ` [PATCH 11/17 v1] clocksource/drivers/ixp4xx: Add DT bindings Linus Walleij
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Jason Cooper, Arnd Bergmann, Marc Zyngier, Tim Harvey,
	Olof Johansson, Thomas Gleixner, Linus Walleij

This adds support for probing and settin up the IXP4xx
irqchip from device tree.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
irqchip maintainers: I am requesting an ACK for this once
you're happy with the driver, as I intend to merge all of
this IXP4xx rework through ARM SoC.
---
 drivers/irqchip/irq-ixp4xx.c | 45 ++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c
index 7deaf0f82a53..741774264f37 100644
--- a/drivers/irqchip/irq-ixp4xx.c
+++ b/drivers/irqchip/irq-ixp4xx.c
@@ -15,6 +15,9 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip/irq-ixp4xx.h>
 #include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
 
@@ -358,3 +361,45 @@ void __init ixp4xx_irq_init(resource_size_t irqbase,
 	}
 }
 EXPORT_SYMBOL_GPL(ixp4xx_irq_init);
+
+#ifdef CONFIG_OF
+int __init ixp4xx_of_init_irq(struct device_node *np,
+			      struct device_node *parent)
+{
+	struct ixp4xx_irq *ixi = &ixirq;
+	void __iomem *base;
+	struct fwnode_handle *fwnode;
+	bool is_356;
+	int ret;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_crit("IXP4XX: could not ioremap interrupt controller\n");
+		return -ENODEV;
+	}
+	fwnode = of_node_to_fwnode(np);
+	if (!fwnode) {
+		pr_crit("IXP4XX: no domain handle\n");
+		return -ENODEV;
+	}
+
+	/* These chip variants have 64 interrupts */
+	is_356 = of_device_is_compatible(np, "intel,ixp43x-interrupt") ||
+		of_device_is_compatible(np, "intel,ixp45x-interrupt") ||
+		of_device_is_compatible(np, "intel,ixp46x-interrupt");
+
+	ret = ixp4xx_irq_setup(ixi, base, fwnode, is_356);
+	if (ret)
+		pr_crit("IXP4XX: failed to set up irqchip\n");
+
+	return ret;
+}
+IRQCHIP_DECLARE(ixp42x, "intel,ixp42x-interrupt",
+		ixp4xx_of_init_irq);
+IRQCHIP_DECLARE(ixp43x, "intel,ixp43x-interrupt",
+		ixp4xx_of_init_irq);
+IRQCHIP_DECLARE(ixp45x, "intel,ixp45x-interrupt",
+		ixp4xx_of_init_irq);
+IRQCHIP_DECLARE(ixp46x, "intel,ixp46x-interrupt",
+		ixp4xx_of_init_irq);
+#endif
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 11/17 v1] clocksource/drivers/ixp4xx: Add DT bindings
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (9 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 10/17 v1] irqchip: ixp4xx: Add OF initialization support Linus Walleij
@ 2019-02-03 21:41 ` Linus Walleij
  2019-02-18 21:26   ` Rob Herring
  2019-02-03 21:42 ` [PATCH 12/17 v1] clocksource/drivers/ixp4xx: Add OF initialization support Linus Walleij
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:41 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: devicetree, Arnd Bergmann, Tim Harvey, Daniel Lezcano,
	Olof Johansson, Thomas Gleixner, Linus Walleij

This adds device tree bindings for the Intel IXP4xx
timers.

Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: devicetree@vger.kernel.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Clocksource/timer maintainers: I am requesting an ACK for
this once you're happy with the bindings, as I intend to
merge all of this IXP4xx rework through ARM SoC.
---
 .../bindings/timer/intel,ixp4xx-timer.txt      | 18 ++++++++++++++++++
 MAINTAINERS                                    |  1 +
 2 files changed, 19 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt b/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt
new file mode 100644
index 000000000000..5b93477bb6ed
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt
@@ -0,0 +1,18 @@
+Intel IXP4xx XScale Networking Processors Timers
+
+This timer is found in the Intel IXP4xx processors.
+
+Required properties:
+
+- compatible : Must be
+  "intel,ixp4xx-timer"
+- reg : Should contain registers location and length
+- interrupts : Should contain the two timer interrupts
+
+Example:
+
+timer@c8005000 {
+	compatible = "intel,ixp4xx-timer";
+	reg = <0xc8005000 0x100>;
+	interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index ec318f09540c..775a623dc91d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1651,6 +1651,7 @@ M:	Krzysztof Halasa <khalasa@piap.pl>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
+F:	Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt
 F:	arch/arm/mach-ixp4xx/
 F:	drivers/clocksource/timer-ixp4xx.c
 F:	drivers/gpio/gpio-ixp4xx.c
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 12/17 v1] clocksource/drivers/ixp4xx: Add OF initialization support
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (10 preceding siblings ...)
  2019-02-03 21:41 ` [PATCH 11/17 v1] clocksource/drivers/ixp4xx: Add DT bindings Linus Walleij
@ 2019-02-03 21:42 ` Linus Walleij
  2019-02-11 11:26   ` Daniel Lezcano
  2019-02-03 21:42 ` [PATCH 13/17 v1] gpio: ixp4xx: Add DT bindings Linus Walleij
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Arnd Bergmann, Tim Harvey, Daniel Lezcano, Olof Johansson,
	Thomas Gleixner, Linus Walleij

This adds support for setting up the IXP4xx timer driver from
device tree.

Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Clocksource/timer maintainers: I am requesting an ACK for
this once you're happy with the driver, as I intend to
merge all of this IXP4xx rework through ARM SoC.
---
 drivers/clocksource/timer-ixp4xx.c | 35 ++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/clocksource/timer-ixp4xx.c b/drivers/clocksource/timer-ixp4xx.c
index fa78f80792db..404445bc11ea 100644
--- a/drivers/clocksource/timer-ixp4xx.c
+++ b/drivers/clocksource/timer-ixp4xx.c
@@ -16,6 +16,8 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 /* Goes away with OF conversion */
 #include <linux/platform_data/timer-ixp4xx.h>
 
@@ -247,3 +249,36 @@ void __init ixp4xx_timer_setup(resource_size_t timerbase,
 	ixp4xx_timer_register(base, timer_irq, timer_freq);
 }
 EXPORT_SYMBOL_GPL(ixp4xx_timer_setup);
+
+#ifdef CONFIG_OF
+static __init int ixp4xx_of_timer_init(struct device_node *np)
+{
+	void __iomem *base;
+	int irq;
+	int ret;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_crit("IXP4xx: can't remap timer\n");
+		return -ENODEV;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq <= 0) {
+		pr_err("Can't parse IRQ\n");
+		ret = -EINVAL;
+		goto out_unmap;
+	}
+
+	/* TODO: get some fixed clocks into the device tree */
+	ret = ixp4xx_timer_register(base, irq, 66666000);
+	if (ret)
+		goto out_unmap;
+	return 0;
+
+out_unmap:
+	iounmap(base);
+	return ret;
+}
+TIMER_OF_DECLARE(ixp4xx, "intel,ixp4xx-timer", ixp4xx_of_timer_init);
+#endif
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 13/17 v1] gpio: ixp4xx: Add DT bindings
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (11 preceding siblings ...)
  2019-02-03 21:42 ` [PATCH 12/17 v1] clocksource/drivers/ixp4xx: Add OF initialization support Linus Walleij
@ 2019-02-03 21:42 ` Linus Walleij
  2019-02-06 16:05   ` Bartosz Golaszewski
  2019-02-18 21:27   ` Rob Herring
  2019-02-03 21:42 ` [PATCH 14/17 v1] gpio: ixp4xx: Add OF probing support Linus Walleij
                   ` (3 subsequent siblings)
  16 siblings, 2 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: devicetree, Arnd Bergmann, Tim Harvey, Bartosz Golaszewski,
	Olof Johansson, Linus Walleij

This adds DT bindings for the IXP4xx GPIO controller.

Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Cc: devicetree@vger.kernel.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Bartosz: looking for your ACK on this, it'd be good if
the other GPIO maintainer is aligned with my ideas here.
I intend to merge this through the ARM SoC tree.
---
 .../bindings/gpio/intel,ixp4xx-gpio.txt       | 38 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 39 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt

diff --git a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
new file mode 100644
index 000000000000..8dc41ed99685
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
@@ -0,0 +1,38 @@
+Intel IXP4xx XScale Networking Processors GPIO
+
+This GPIO controller is found in the Intel IXP4xx processors.
+It supports 16 GPIO lines.
+
+The interrupt portions of the GPIO controller is hierarchical:
+the synchronous edge detector is part of the GPIO block, but the
+actual enabling/disabling of the interrupt line is done in the
+main IXP4xx interrupt controller which has a 1:1 mapping for
+the first 12 GPIO lines to 12 system interrupts.
+
+The remaining 4 GPIO lines can not be used for receiving
+interrupts.
+
+The interrupt parent of this GPIO controller must be the
+IXP4xx interrupt controller.
+
+Required properties:
+
+- compatible : Should be
+  "intel,ixp4xx-gpio"
+- reg : Should contain registers location and length
+- gpio-controller : marks this as a GPIO controller
+- #gpio-cells : Should be 2, see gpio/gpio.txt
+- interrupt-controller : marks this as an interrupt controller
+- #interrupt-cells : a standard two-cell interrupt, see
+  interrupt-controller/interrupts.txt
+
+Example:
+
+gpio0: gpio@c8004000 {
+	compatible = "intel,ixp4xx-gpio";
+	reg = <0xc8004000 0x1000>;
+	gpio-controller;
+	#gpio-cells = <2>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 775a623dc91d..57d098b85523 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1650,6 +1650,7 @@ M:	Imre Kaloz <kaloz@openwrt.org>
 M:	Krzysztof Halasa <khalasa@piap.pl>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
+F:	Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
 F:	Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
 F:	Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt
 F:	arch/arm/mach-ixp4xx/
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 14/17 v1] gpio: ixp4xx: Add OF probing support
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (12 preceding siblings ...)
  2019-02-03 21:42 ` [PATCH 13/17 v1] gpio: ixp4xx: Add DT bindings Linus Walleij
@ 2019-02-03 21:42 ` Linus Walleij
  2019-02-06 16:13   ` Bartosz Golaszewski
  2019-02-03 21:42 ` [PATCH 15/17 v1] ARM: ixp4xx: Add DT bindings Linus Walleij
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Bartosz Golaszewski, Tim Harvey, Linus Walleij,
	Arnd Bergmann

This adds device tree probe and registration support for
the IXP4xx GPIO driver.

Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Bartosz: looking for your ACK on this, it'd be good if
the other GPIO maintainer is aligned with my ideas here.
I intend to merge this through the ARM SoC tree.
---
 drivers/gpio/gpio-ixp4xx.c | 84 ++++++++++++++++++++++++++------------
 1 file changed, 57 insertions(+), 27 deletions(-)

diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
index 44c24948379d..38a77c8e0c9c 100644
--- a/drivers/gpio/gpio-ixp4xx.c
+++ b/drivers/gpio/gpio-ixp4xx.c
@@ -11,6 +11,7 @@
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/irqchip.h>
+#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/bitops.h>
 /* Include that go away with DT transition */
@@ -305,6 +306,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
 {
 	unsigned long flags;
 	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
 	struct irq_domain *parent;
 	struct resource *res;
 	struct ixp4xx_gpio *g;
@@ -381,11 +383,27 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
 	 * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
 	 * the fwnode. For now we need this boardfile style code.
 	 */
-	parent = ixp4xx_get_irq_domain();
-	g->fwnode = irq_domain_alloc_fwnode(g->base);
-	if (!g->fwnode) {
-		dev_err(dev, "no domain base\n");
-		return -ENODEV;
+	if (np) {
+		struct device_node *irq_parent;
+
+		irq_parent = of_irq_find_parent(np);
+		if (!irq_parent) {
+			dev_err(dev, "no IRQ parent node\n");
+			return -ENODEV;
+		}
+		parent = irq_find_host(irq_parent);
+		if (!parent) {
+			dev_err(dev, "no IRQ parent domain\n");
+			return -ENODEV;
+		}
+		g->fwnode = of_node_to_fwnode(np);
+	} else {
+		parent = ixp4xx_get_irq_domain();
+		g->fwnode = irq_domain_alloc_fwnode(g->base);
+		if (!g->fwnode) {
+			dev_err(dev, "no domain base\n");
+			return -ENODEV;
+		}
 	}
 	g->domain = irq_domain_create_hierarchy(parent,
 						IRQ_DOMAIN_FLAG_HIERARCHY,
@@ -403,28 +421,31 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
 	 * After adding OF support, this is no longer needed: irqs
 	 * will be allocated for the respective fwnodes.
 	 */
-	for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
-		const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
-		struct irq_fwspec fwspec;
-
-		fwspec.fwnode = g->fwnode;
-		/* This is the hwirq for the GPIO line side of things */
-		fwspec.param[0] = map->gpio_offset;
-		fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
-		fwspec.param_count = 2;
-		ret = __irq_domain_alloc_irqs(g->domain,
-					      -1, /* just pick something */
-					      1,
-					      NUMA_NO_NODE,
-					      &fwspec,
-					      false,
-					      NULL);
-		if (ret < 0) {
-			irq_domain_free_fwnode(g->fwnode);
-			dev_err(dev,
-				"can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
-				map->gpio_offset, map->parent_hwirq, ret);
-			return ret;
+	if (!np) {
+		for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
+			const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
+			struct irq_fwspec fwspec;
+
+			fwspec.fwnode = g->fwnode;
+			/* This is the hwirq for the GPIO line side of things */
+			fwspec.param[0] = map->gpio_offset;
+			fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+			fwspec.param_count = 2;
+			ret = __irq_domain_alloc_irqs(g->domain,
+						      -1, /* just pick something */
+						      1,
+						      NUMA_NO_NODE,
+						      &fwspec,
+						      false,
+						      NULL);
+			if (ret < 0) {
+				irq_domain_free_fwnode(g->fwnode);
+				dev_err(dev,
+					"can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
+					map->gpio_offset, map->parent_hwirq,
+					ret);
+				return ret;
+			}
 		}
 	}
 
@@ -434,9 +455,18 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id ixp4xx_gpio_of_match[] = {
+	{
+		.compatible = "intel,ixp4xx-gpio",
+	},
+	{},
+};
+
+
 static struct platform_driver ixp4xx_gpio_driver = {
 	.driver = {
 		.name		= "ixp4xx-gpio",
+		.of_match_table = of_match_ptr(ixp4xx_gpio_of_match),
 	},
 	.probe = ixp4xx_gpio_probe,
 };
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 15/17 v1] ARM: ixp4xx: Add DT bindings
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (13 preceding siblings ...)
  2019-02-03 21:42 ` [PATCH 14/17 v1] gpio: ixp4xx: Add OF probing support Linus Walleij
@ 2019-02-03 21:42 ` Linus Walleij
  2019-02-04 15:16   ` Rob Herring
  2019-02-03 21:42 ` [PATCH 16/17 v1] ARM: ixp4xx: Add device tree boot support Linus Walleij
  2019-02-03 21:42 ` [PATCH 17/17 v1] RFC: ARM: dts: Add some initial IXP4xx device trees Linus Walleij
  16 siblings, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, devicetree, Tim Harvey, Linus Walleij, Arnd Bergmann

This adds initial device tree bindings for the IXP4xx machines.
This time I tried something wild and crazy and try to make proper
JSON-style YAML bindings for the top level.

Cc: devicetree@vger.kernel.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
I have no clear idea on how to auto-test this schema for validity,
since it is a bit of a new thing I hope to figure it out as
we go.
---
 .../devicetree/bindings/arm/intel-ixp4xx.yaml | 22 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml

diff --git a/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml b/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
new file mode 100644
index 000000000000..da5f6ffe6f2d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/intel-ixp4xx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Intel IXP4xx Device Tree Bindings
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - linksys,nslu2
+          - const: intel,ixp42x
+      - items:
+          - enum:
+              - gateworks,gw2358-4
+          - const: intel,ixp43x
diff --git a/MAINTAINERS b/MAINTAINERS
index 57d098b85523..c4ca249a2075 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1650,6 +1650,7 @@ M:	Imre Kaloz <kaloz@openwrt.org>
 M:	Krzysztof Halasa <khalasa@piap.pl>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
+F:	Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
 F:	Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
 F:	Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
 F:	Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 16/17 v1] ARM: ixp4xx: Add device tree boot support
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (14 preceding siblings ...)
  2019-02-03 21:42 ` [PATCH 15/17 v1] ARM: ixp4xx: Add DT bindings Linus Walleij
@ 2019-02-03 21:42 ` Linus Walleij
  2019-02-03 21:42 ` [PATCH 17/17 v1] RFC: ARM: dts: Add some initial IXP4xx device trees Linus Walleij
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Tim Harvey, Linus Walleij, Arnd Bergmann

This adds a minimal support for booting IXP4xx systems
from device tree.

We have to add hacks to the QMGR, NPE and notably also
ethernet and watchdog drivers so that they don't crash
the platform: these drivers are unconditionally starting
to grab regions of statically remapped IO space with no
concern of the device model or other platforms.

We will go in and properly fix these drivers as we go
along but for now this hack gets us to a place where we
can start working on proper device tree support for these
platforms.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ixp4xx/Kconfig             | 14 +++++++
 arch/arm/mach-ixp4xx/Makefile            |  3 ++
 arch/arm/mach-ixp4xx/ixp4xx-of.c         | 49 ++++++++++++++++++++++++
 arch/arm/mach-ixp4xx/ixp4xx_npe.c        |  5 +++
 arch/arm/mach-ixp4xx/ixp4xx_qmgr.c       |  5 +++
 drivers/net/ethernet/xscale/ixp4xx_eth.c | 10 +++++
 drivers/watchdog/ixp4xx_wdt.c            |  9 +++++
 7 files changed, 95 insertions(+)
 create mode 100644 arch/arm/mach-ixp4xx/ixp4xx-of.c

diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index fea008123eb1..0973270f4863 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -4,6 +4,20 @@ menu "Intel IXP4xx Implementation Options"
 
 comment "IXP4xx Platforms"
 
+config MACH_IXP4XX_OF
+	bool
+	prompt "Devce Tree IXP4xx boards"
+	default y
+	select ARM_APPENDED_DTB # Old Redboot bootloaders deployed
+	select I2C
+	select I2C_IOP3XX
+	select PCI
+	select SERIAL_OF_PLATFORM
+	select TIMER_OF
+	select USE_OF
+	help
+	  Say 'Y' here to support Device Tree-based IXP4xx platforms.
+
 config MACH_NSLU2
 	bool
 	prompt "Linksys NSLU2"
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index f09994500a34..5f63b3012826 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -6,6 +6,9 @@
 obj-pci-y	:=
 obj-pci-n	:=
 
+# Device tree platform
+obj-pci-$(CONFIG_MACH_IXP4XX_OF)	+= ixp4xx-of.o
+
 obj-pci-$(CONFIG_ARCH_IXDP4XX)		+= ixdp425-pci.o
 obj-pci-$(CONFIG_MACH_AVILA)		+= avila-pci.o
 obj-pci-$(CONFIG_MACH_IXDPG425)		+= ixdpg425-pci.o
diff --git a/arch/arm/mach-ixp4xx/ixp4xx-of.c b/arch/arm/mach-ixp4xx/ixp4xx-of.c
new file mode 100644
index 000000000000..17540fb9b5e7
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/ixp4xx-of.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IXP4xx Device Tree boot support
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+
+#ifdef CONFIG_DEBUG_UART_8250
+/* This is needed for LL-debug/earlyprintk/debug-macro.S */
+static struct map_desc ixp4xx_of_io_desc[] __initdata = {
+	{
+		.virtual = CONFIG_DEBUG_UART_VIRT,
+		.pfn = __phys_to_pfn(CONFIG_DEBUG_UART_PHYS),
+		.length = SZ_4K,
+		.type = MT_DEVICE,
+	},
+};
+
+static void __init ixp4xx_of_map_io(void)
+{
+	iotable_init(ixp4xx_of_io_desc, ARRAY_SIZE(ixp4xx_of_io_desc));
+}
+#else
+#define ixp4xx_of_map_io NULL
+#endif
+
+/*
+ * We handle 4 differen SoC families. These compatible strings are enough
+ * to provide the core so that different boards can add their more detailed
+ * specifics.
+ */
+static const char *ixp4xx_of_board_compat[] = {
+	"intel,ixp42x",
+	"intel,ixp43x",
+	"intel,ixp45x",
+	"intel,ixp46x",
+	NULL,
+};
+
+DT_MACHINE_START(IXP4XX_DT, "IXP4xx (Device Tree)")
+	.map_io		= ixp4xx_of_map_io,
+	.dt_compat	= ixp4xx_of_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
index d4eb09a62863..e0ce22cd9bfc 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <mach/npe.h>
 
 #define DEBUG_MSG			0
@@ -688,6 +689,10 @@ static int __init npe_init_module(void)
 
 	int i, found = 0;
 
+	/* This driver does not work with device tree */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	for (i = 0; i < NPE_COUNT; i++) {
 		struct npe *npe = &npe_tab[i];
 		if (!(ixp4xx_read_feature_bits() &
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
index 4c7c960e1b4c..2665347a2c6f 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -12,6 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <mach/qmgr.h>
 
 #include "irqs.h"
@@ -289,6 +290,10 @@ static int qmgr_init(void)
 	int i, err;
 	irq_handler_t handler1, handler2;
 
+	/* This driver does not work with device tree */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
 				     IXP4XX_QMGR_REGION_SIZE,
 				     "IXP4xx Queue Manager");
diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index aee55c03def0..7ad3c3b56a77 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -31,6 +31,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/net_tstamp.h>
+#include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/platform_device.h>
 #include <linux/ptp_classify.h>
@@ -1497,6 +1498,15 @@ static struct platform_driver ixp4xx_eth_driver = {
 static int __init eth_init_module(void)
 {
 	int err;
+
+	/*
+	 * FIXME: we bail out on device tree boot but this really needs
+	 * to be fixed in a nicer way: this registers the MDIO bus before
+	 * even matching the driver infrastructure, we should only probe
+	 * detected hardware.
+	 */
+	if (of_have_populated_dt())
+		return -ENODEV;
 	if ((err = ixp4xx_mdio_register()))
 		return err;
 	return platform_driver_register(&ixp4xx_eth_driver);
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c
index f20cc53ff719..a80449bb36f0 100644
--- a/drivers/watchdog/ixp4xx_wdt.c
+++ b/drivers/watchdog/ixp4xx_wdt.c
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/of.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
@@ -176,6 +177,14 @@ static int __init ixp4xx_wdt_init(void)
 {
 	int ret;
 
+	/*
+	 * FIXME: we bail out on device tree boot but this really needs
+	 * to be fixed in a nicer way: this registers the MDIO bus before
+	 * even matching the driver infrastructure, we should only probe
+	 * detected hardware.
+	 */
+	if (of_have_populated_dt())
+		return -ENODEV;
 	if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
 		pr_err("Rev. A0 IXP42x CPU detected - watchdog disabled\n");
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 17/17 v1] RFC: ARM: dts: Add some initial IXP4xx device trees
  2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
                   ` (15 preceding siblings ...)
  2019-02-03 21:42 ` [PATCH 16/17 v1] ARM: ixp4xx: Add device tree boot support Linus Walleij
@ 2019-02-03 21:42 ` Linus Walleij
  16 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-03 21:42 UTC (permalink / raw)
  To: linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Tim Harvey, Linus Walleij, Arnd Bergmann

This adds a device tree for the IXP4xx-based Linksys
NSLU2 and Gateworks GW2358-4 which is one platform in the
Gateworks Cambria family.

These will be the first IXP4xx device tree platforms.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
Since several of the DT bindings in these trees are not
yet reviewed or merged upstream, this patch is RFC
only, presented to make the review of the rest of the
series readable.
---
 arch/arm/boot/dts/Makefile                    |   3 +
 .../boot/dts/intel-ixp42x-linksys-nslu2.dts   | 111 ++++++++++++++++++
 arch/arm/boot/dts/intel-ixp42x.dtsi           |  25 ++++
 .../dts/intel-ixp43x-gateworks-gw2358-4.dts   |  96 +++++++++++++++
 arch/arm/boot/dts/intel-ixp43x.dtsi           |  15 +++
 arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi    |  34 ++++++
 arch/arm/boot/dts/intel-ixp4xx.dtsi           |  58 +++++++++
 7 files changed, 342 insertions(+)
 create mode 100644 arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts
 create mode 100644 arch/arm/boot/dts/intel-ixp42x.dtsi
 create mode 100644 arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358-4.dts
 create mode 100644 arch/arm/boot/dts/intel-ixp43x.dtsi
 create mode 100644 arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi
 create mode 100644 arch/arm/boot/dts/intel-ixp4xx.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index bd40148a15b2..31001e1203c7 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -227,6 +227,9 @@ dtb-$(CONFIG_ARCH_HIX5HD2) += \
 dtb-$(CONFIG_ARCH_INTEGRATOR) += \
 	integratorap.dtb \
 	integratorcp.dtb
+dtb-$(CONFIG_ARCH_IXP4XX) += \
+	intel-ixp42x-linksys-nslu2.dtb \
+	intel-ixp43x-gateworks-gw2358-4.dtb
 dtb-$(CONFIG_ARCH_KEYSTONE) += \
 	keystone-k2hk-evm.dtb \
 	keystone-k2l-evm.dtb \
diff --git a/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts b/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts
new file mode 100644
index 000000000000..e74ee624dce4
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Linksys NSLU2
+ */
+
+/dts-v1/;
+
+#include "intel-ixp42x.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Linksys NSLU2 (Network Storage Link for USB 2.0 Disk Drives)";
+	compatible = "linksys,nslu2", "intel,ixp42x";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	memory@0 {
+		/* 32 MB SDRAM */
+		device_type = "memory";
+		reg = <0x00000000 0x2000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 root=/dev/mtdblock2 rw rootfstype=squashfs,jffs2 rootwait";
+		stdout-path = "uart0:115200n8";
+	};
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led-status {
+			label = "nslu2:red:status";
+			gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+		led-ready {
+			label = "nslu2:green:ready";
+			gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+		led-disk-1 {
+			label = "nslu2:green:disk-1";
+			gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+		led-disk-2 {
+			label = "nslu2:green:disk-2";
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		button-power {
+			wakeup-source;
+			linux,code = <KEY_POWER>;
+			label = "power";
+			gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+		};
+		button-reset {
+			wakeup-source;
+			linux,code = <KEY_ESC>;
+			label = "reset";
+			gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-i2c {
+		compatible = "i2c-gpio";
+		sda-gpios = <&gpio0 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+		scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rtc@6f {
+			compatible = "xicor,x1205";
+			reg = <0x6f>;
+		};
+	};
+
+	gpio-poweroff {
+		compatible = "gpio-poweroff";
+		gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
+		timeout-ms = <5000>;
+	};
+
+	/* The first 16MB region on the expansion bus */
+	flash@50000000 {
+		compatible = "intel,ixp4xx-flash", "cfi-flash";
+		bank-width = <2>;
+		/*
+		 * 8 MB of Flash in 0x20000 byte blocks
+		 * mapped in at 0x50000000
+		 */
+		reg = <0x50000000 0x800000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partitions {
+			compatible = "redboot-fis";
+			/* Eraseblock at 0x7e0000 */
+			fis-index-block = <0x3f>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/intel-ixp42x.dtsi b/arch/arm/boot/dts/intel-ixp42x.dtsi
new file mode 100644
index 000000000000..ee736411c603
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp42x.dtsi
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Intel XScale Network Processors
+ * in the IXP 42x series. This series has 32 interrupts.
+ */
+#include "intel-ixp4xx.dtsi"
+
+/ {
+	soc {
+		interrupt-controller@c8003000 {
+			compatible = "intel,ixp42x-interrupt";
+		};
+
+		/*
+		 * This is the USB Device Mode (UDC) controller, which is used
+		 * to present the IXP4xx as a device on a USB bus.
+		 */
+		usb@c800b000 {
+			compatible = "intel,ixp4xx-udc";
+			reg = <0xc800b000 0x1000>;
+			interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358-4.dts b/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358-4.dts
new file mode 100644
index 000000000000..3f072760aca0
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358-4.dts
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Gateworks IXP43x-based Cambria GW2358-4
+ */
+
+/dts-v1/;
+
+#include "intel-ixp43x.dtsi"
+
+/ {
+	model = "Gateworks Cambria GW2358-4";
+	compatible = "gateworks,gw2358-4", "intel,ixp43x";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	memory@0 {
+		/* 128 MB SDRAM */
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 root=/dev/mtdblock2 rw rootfstype=squashfs,jffs2 rootwait";
+		stdout-path = "uart0:115200n8";
+	};
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		led-user {
+			label = "gw2385-4:greep:LED";
+			gpios = <&pld1 0 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+
+	gpio-i2c {
+		compatible = "i2c-gpio";
+		sda-gpios = <&gpio0 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+		scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		hwmon@28 {
+			compatible = "adi,ad7418";
+			reg = <0x28>;
+		};
+		rtc: ds1672@68 {
+			compatible = "dallas,ds1672";
+			reg = <0x68>;
+		};
+		eeprom@51 {
+			compatible = "atmel,24c08";
+			reg = <0x51>;
+			pagesize = <16>;
+			size = <1024>;
+			read-only;
+		};
+		pld0: pld@56 {
+			compatible = "gateworks,pld-gpio";
+			reg = <0x56>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+		/* This PLD just handles the LED and user button */
+		pld1: pld@57 {
+			compatible = "gateworks,pld-gpio";
+			reg = <0x57>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+
+	flash@50000000 {
+		compatible = "intel,ixp4xx-flash", "cfi-flash";
+		bank-width = <2>;
+		/*
+		 * 32 MB of Flash in 0x20000 byte blocks
+		 * mapped in at 0x50000000
+		 */
+		reg = <0x50000000 0x2000000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partitions {
+			compatible = "redboot-fis";
+			/* Eraseblock at 0x1fe0000 */
+			fis-index-block = <0xff>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/intel-ixp43x.dtsi b/arch/arm/boot/dts/intel-ixp43x.dtsi
new file mode 100644
index 000000000000..dea1517d4feb
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp43x.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Intel XScale Network Processors
+ * in the IXP 43x series. This series has 64 interrupts and adds a few more
+ * peripherals over the 42x series.
+ */
+#include "intel-ixp4xx.dtsi"
+
+/ {
+	soc {
+		interrupt-controller@c8003000 {
+			compatible = "intel,ixp43x-interrupt";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi b/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi
new file mode 100644
index 000000000000..ea08e5458977
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Intel XScale Network Processors
+ * in the IXP45x and IXP46x series. This series has 64 interrupts and adds a
+ * few more peripherals over the 42x and 43x series so this extends the
+ * basic IXP4xx DTSI.
+ */
+#include "intel-ixp4xx.dtsi"
+
+/ {
+	soc {
+		interrupt-controller@c8003000 {
+			compatible = "intel,ixp43x-interrupt";
+		};
+
+		/*
+		 * This is the USB Device Mode (UDC) controller, which is used
+		 * to present the IXP4xx as a device on a USB bus.
+		 */
+		usb@c800b000 {
+			compatible = "intel,ixp4xx-udc";
+			reg = <0xc800b000 0x1000>;
+			interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		i2c@c8011000 {
+			compatible = "intel,ixp4xx-i2c";
+			reg = <0xc8011000 0x18>;
+			interrupts = <33 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/intel-ixp4xx.dtsi b/arch/arm/boot/dts/intel-ixp4xx.dtsi
new file mode 100644
index 000000000000..9a08213697a2
--- /dev/null
+++ b/arch/arm/boot/dts/intel-ixp4xx.dtsi
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for Intel XScale Network Processors
+ * in the IXP 4xx series.
+ */
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "simple-bus";
+		interrupt-parent = <&intcon>;
+
+		uart0: serial@c8000000 {
+			compatible = "intel,xscale-uart";
+			reg = <0xc8000000 0x1000>;
+			/*
+			 * The reg-offset and reg-shift is a side effect
+			 * of running the platform in big endian mode.
+			 */
+			reg-offset = <3>;
+			reg-shift = <2>;
+			interrupts = <15 IRQ_TYPE_LEVEL_HIGH>;
+			clock-frequency = <14745600>;
+			no-loopback-test;
+		};
+
+		gpio0: gpio@c8004000 {
+			compatible = "intel,ixp4xx-gpio";
+			reg = <0xc8004000 0x1000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		intcon: interrupt-controller@c8003000 {
+			/*
+			 * Note: no compatible string. The subvariant of the
+			 * chip needs to define what version it is. The
+			 * location of the interrupt controller is fixed in
+			 * memory across all variants.
+			 */
+			reg = <0xc8003000 0x100>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		timer@c8005000 {
+			compatible = "intel,ixp4xx-timer";
+			reg = <0xc8005000 0x100>;
+			interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+		};
+	};
+};
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 15/17 v1] ARM: ixp4xx: Add DT bindings
  2019-02-03 21:42 ` [PATCH 15/17 v1] ARM: ixp4xx: Add DT bindings Linus Walleij
@ 2019-02-04 15:16   ` Rob Herring
  2019-02-08 19:37     ` Linus Walleij
  0 siblings, 1 reply; 40+ messages in thread
From: Rob Herring @ 2019-02-04 15:16 UTC (permalink / raw)
  To: Linus Walleij
  Cc: devicetree, Arnd Bergmann, Tim Harvey, Krzysztof Halasa,
	Olof Johansson, Imre Kaloz,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Sun, Feb 3, 2019 at 3:42 PM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> This adds initial device tree bindings for the IXP4xx machines.
> This time I tried something wild and crazy and try to make proper
> JSON-style YAML bindings for the top level.
>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> I have no clear idea on how to auto-test this schema for validity,
> since it is a bit of a new thing I hope to figure it out as
> we go.

Is Documentation/devicetree/writing-schema.md missing something on how to?

The DT patchwork instance will have test results too, but in this case
it couldn't apply the patch since MAINTAINERS has a dependency...

> ---
>  .../devicetree/bindings/arm/intel-ixp4xx.yaml | 22 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 23 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml

In any case, the manual checker thinks this looks fine.

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 05/17 v1] gpio: ixp4xx: Add driver for the IXP4xx GPIO
  2019-02-03 21:41 ` [PATCH 05/17 v1] gpio: ixp4xx: Add driver for the IXP4xx GPIO Linus Walleij
@ 2019-02-06 16:03   ` Bartosz Golaszewski
  0 siblings, 0 replies; 40+ messages in thread
From: Bartosz Golaszewski @ 2019-02-06 16:03 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Arnd Bergmann, Tim Harvey, Krzysztof Halasa, Olof Johansson,
	Imre Kaloz, arm-soc

niedz., 3 lut 2019 o 22:42 Linus Walleij <linus.walleij@linaro.org> napisał(a):
>
> This adds a driver for the IXP4xx GPIO block found in
> the Intel XScale IXP4xx systems.
>
> The GPIO part of this block is pretty straight-forward and
> just uses the generic MMIO GPIO library.
>
> The irqchip side of this driver is hierarchical where
> the main irqchip will receive a processed level trigger
> in response to the edge detector of the GPIO block,
> so for this reason the v2 version of the irqdomain API
> is used (as well as in the parent IXP4xx irqchip) and
> masking, unmasking and setting up the type on IRQ
> happens on several levels.
>
> Currently this GPIO controller will grab the parent
> irqdomain using a special function, but as the platform
> move toward device tree probing, this will not be needed:
> we can just look up the parent irqdomain from the device
> tree.
>
> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Bartosz: looking for your ACK on this, it'd be good if
> the other GPIO maintainer is aligned with my ideas here.
> I intend to merge this through the ARM SoC tree.
> ---

Linus,

My remarks are below. Mostly just nits (feel free to ignore) or
questions that I'd like clarified.

>  MAINTAINERS                |   1 +
>  drivers/gpio/Kconfig       |  12 +
>  drivers/gpio/Makefile      |   1 +
>  drivers/gpio/gpio-ixp4xx.c | 443 +++++++++++++++++++++++++++++++++++++
>  4 files changed, 457 insertions(+)
>  create mode 100644 drivers/gpio/gpio-ixp4xx.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0d48faa3e635..6c161bd82238 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1651,6 +1651,7 @@ M:        Krzysztof Halasa <khalasa@piap.pl>
>  L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
>  S:     Maintained
>  F:     arch/arm/mach-ixp4xx/
> +F:     drivers/gpio/gpio-ixp4xx.c
>  F:     drivers/irqchip/irq-ixp4xx.c
>  F:     include/linux/irqchip/irq-ixp4xx.h
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 699a8118c433..fe4a47e49a24 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -286,6 +286,18 @@ config GPIO_IOP
>
>           If unsure, say N.
>
> +config GPIO_IXP4XX
> +       bool "Intel IXP4xx GPIO"
> +       depends on ARCH_IXP4XX || COMPILE_TEST
> +       select GPIO_GENERIC
> +       select IRQ_DOMAIN
> +       select IRQ_DOMAIN_HIERARCHY
> +       help
> +         Say yes here to support the GPIO functionality of a number of Intel
> +         IXP4xx series of chips.
> +
> +         If unsure, say N.
> +
>  config GPIO_LOONGSON
>         bool "Loongson-2/3 GPIO support"
>         depends on CPU_LOONGSON2 || CPU_LOONGSON3
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index 0568bbe6fe68..cf66523b5eec 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -60,6 +60,7 @@ obj-$(CONFIG_GPIO_HLWD)               += gpio-hlwd.o
>  obj-$(CONFIG_HTC_EGPIO)                += gpio-htc-egpio.o
>  obj-$(CONFIG_GPIO_ICH)         += gpio-ich.o
>  obj-$(CONFIG_GPIO_IOP)         += gpio-iop.o
> +obj-$(CONFIG_GPIO_IXP4XX)      += gpio-ixp4xx.o
>  obj-$(CONFIG_GPIO_IT87)                += gpio-it87.o
>  obj-$(CONFIG_GPIO_JANZ_TTL)    += gpio-janz-ttl.o
>  obj-$(CONFIG_GPIO_KEMPLD)      += gpio-kempld.o
> diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
> new file mode 100644
> index 000000000000..44c24948379d
> --- /dev/null
> +++ b/drivers/gpio/gpio-ixp4xx.c
> @@ -0,0 +1,443 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * IXP4 GPIO driver
> + * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
> + *
> + * based on previous work and know-how from:
> + * Deepak Saxena <dsaxena@plexity.net>
> + */

Just a nit, but I'd add a newline between the includes and the header.
Also: C++ style comment for the header.

> +#include <linux/gpio/driver.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip.h>
> +#include <linux/platform_device.h>
> +#include <linux/bitops.h>
> +/* Include that go away with DT transition */
> +#include <linux/irqchip/irq-ixp4xx.h>

I think a newline between linux/ and asm/ includes is a good rule.

> +#include <asm/mach-types.h>
> +
> +#define IXP4XX_GPIO_GPOUTR     0x00
> +#define IXP4XX_GPIO_GPOER      0x04
> +#define IXP4XX_GPIO_GPINR      0x08
> +#define IXP4XX_GPIO_GPISR      0x0C
> +#define IXP4XX_GPIO_GPIT1R     0x10
> +#define IXP4XX_GPIO_GPIT2R     0x14
> +#define IXP4XX_GPIO_GPCLKR     0x18
> +#define IXP4XX_GPIO_GPDBSELR   0x1C
> +

Since these are registers offsets - maybe the prefix could be
IXP4XX_GPIO_REG_* or IXP4XX_GPIO_OFF_*? I think it's more readable.

> +/*
> + * The hardware uses 3 bits to indicate interrupt "style".
> + * we clear and set these three bits accordingly. The lower 24
> + * bits in two registers (GPIT1R and GPIT2R) are used to set up
> + * the style for 8 lines each for a total of 16 GPIO lines.
> + */
> +#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH  0x0
> +#define IXP4XX_GPIO_STYLE_ACTIVE_LOW   0x1
> +#define IXP4XX_GPIO_STYLE_RISING_EDGE  0x2
> +#define IXP4XX_GPIO_STYLE_FALLING_EDGE 0x3
> +#define IXP4XX_GPIO_STYLE_TRANSITIONAL 0x4
> +#define IXP4XX_GPIO_STYLE_MASK         0x7

I'd use GENMASK(2, 0) here.

> +#define IXP4XX_GPIO_STYLE_SIZE         3
> +
> +/**
> + * struct ixp4xx_gpio - IXP4 GPIO state container
> + * @dev: containing device for this instance
> + * @fwnode: the fwnode for this GPIO chip
> + * @gc: gpiochip for this instance
> + * @domain: irqdomain for this chip instance
> + * @base: remapped I/O-memory base
> + * @irq_edge: Each bit represents an IRQ: 1: edge-triggered,
> + * 0: level triggered
> + */
> +struct ixp4xx_gpio {
> +       struct device *dev;
> +       struct fwnode_handle *fwnode;
> +       struct gpio_chip gc;
> +       struct irq_domain *domain;
> +       void __iomem *base;
> +       unsigned long long irq_edge;
> +};
> +
> +/**
> + * struct ixp4xx_gpio_map - IXP4 GPIO to parent IRQ map
> + * @gpio_offset: offset of the IXP4 GPIO line
> + * @parent_hwirq: hwirq on the parent IRQ controller
> + */
> +struct ixp4xx_gpio_map {
> +       int gpio_offset;
> +       int parent_hwirq;
> +};
> +
> +/* GPIO lines 0..12 have corresponding IRQs, GPIOs 13..15 have no IRQs */
> +const struct ixp4xx_gpio_map ixp4xx_gpiomap[] = {
> +       { .gpio_offset = 0, .parent_hwirq = 6 },
> +       { .gpio_offset = 1, .parent_hwirq = 7 },
> +       { .gpio_offset = 2, .parent_hwirq = 19 },
> +       { .gpio_offset = 3, .parent_hwirq = 20 },
> +       { .gpio_offset = 4, .parent_hwirq = 21 },
> +       { .gpio_offset = 5, .parent_hwirq = 22 },
> +       { .gpio_offset = 6, .parent_hwirq = 23 },
> +       { .gpio_offset = 7, .parent_hwirq = 24 },
> +       { .gpio_offset = 8, .parent_hwirq = 25 },
> +       { .gpio_offset = 9, .parent_hwirq = 26 },
> +       { .gpio_offset = 10, .parent_hwirq = 27 },
> +       { .gpio_offset = 11, .parent_hwirq = 28 },
> +       { .gpio_offset = 12, .parent_hwirq = 29 },
> +};
> +
> +static void ixp4xx_gpio_irq_ack(struct irq_data *d)
> +{
> +       struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
> +
> +       __raw_writel(BIT(d->hwirq), g->base + IXP4XX_GPIO_GPISR);
> +}
> +
> +static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
> +{
> +       struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
> +
> +       /* ACK when unmasking if not edge-triggered */
> +       if (!(g->irq_edge & BIT(d->hwirq)))
> +               ixp4xx_gpio_irq_ack(d);
> +
> +       irq_chip_unmask_parent(d);
> +}
> +
> +static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)
> +{
> +       struct ixp4xx_gpio *g = irq_data_get_irq_chip_data(d);
> +       int line = d->hwirq;
> +       u32 int_style;
> +       unsigned long flags;
> +       u32 int_reg;
> +       u32 val;
> +

I'm personally a fan of putting variables of the same type in the same
line and arranging them in reverse-christmas tree order, but feel free
to ignore it.

> +       switch (type) {
> +       case IRQ_TYPE_EDGE_BOTH:
> +               irq_set_handler_locked(d, handle_edge_irq);
> +               int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
> +               g->irq_edge |= BIT(d->hwirq);
> +               break;
> +       case IRQ_TYPE_EDGE_RISING:
> +               irq_set_handler_locked(d, handle_edge_irq);
> +               int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
> +               g->irq_edge |= BIT(d->hwirq);
> +               break;
> +       case IRQ_TYPE_EDGE_FALLING:
> +               irq_set_handler_locked(d, handle_edge_irq);
> +               int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
> +               g->irq_edge |= BIT(d->hwirq);
> +               break;
> +       case IRQ_TYPE_LEVEL_HIGH:
> +               irq_set_handler_locked(d, handle_level_irq);
> +               int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
> +               g->irq_edge &= ~BIT(d->hwirq);
> +               break;
> +       case IRQ_TYPE_LEVEL_LOW:
> +               irq_set_handler_locked(d, handle_level_irq);
> +               int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
> +               g->irq_edge &= ~BIT(d->hwirq);
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       if (line >= 8) {
> +               /* pins 8-15 */
> +               line -= 8;
> +               int_reg = IXP4XX_GPIO_GPIT2R;
> +       } else {
> +               /* pins 0-7 */
> +               int_reg = IXP4XX_GPIO_GPIT1R;
> +       }
> +
> +       spin_lock_irqsave(&g->gc.bgpio_lock, flags);
> +
> +       /* Clear the style for the appropriate pin */
> +       val = __raw_readl(g->base + int_reg);
> +       val &= ~(IXP4XX_GPIO_STYLE_MASK << (line * IXP4XX_GPIO_STYLE_SIZE));
> +       __raw_writel(val, g->base + int_reg);

I know you're not using regmap, because this driver's based on
gpio-mmio, but I'm wondering if you could maybe wrap those three
operations in a helper wrapper e.g. ixp4xx_update_reg() or something
to make it easier to read. Same below.

> +
> +       __raw_writel(BIT(line), g->base + IXP4XX_GPIO_GPISR);
> +
> +       /* Set the new style */
> +       val = __raw_readl(g->base + int_reg);
> +       val |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
> +       __raw_writel(val, g->base + int_reg);
> +
> +       /* Force-configure this line as an input */
> +       val = __raw_readl(g->base + IXP4XX_GPIO_GPOER);
> +       val |= BIT(d->hwirq);
> +       __raw_writel(val, g->base + IXP4XX_GPIO_GPOER);
> +
> +       spin_unlock_irqrestore(&g->gc.bgpio_lock, flags);
> +
> +       /* This parent only accept level high (asserted) */
> +       return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
> +}
> +
> +static struct irq_chip ixp4xx_gpio_irqchip = {
> +       .name = "IXP4GPIO",
> +       .irq_ack = ixp4xx_gpio_irq_ack,
> +       .irq_mask = irq_chip_mask_parent,
> +       .irq_unmask = ixp4xx_gpio_irq_unmask,
> +       .irq_set_type = ixp4xx_gpio_irq_set_type,
> +};

I assume this device cannot have multiple instances, so it's safe to
have a static irqchip?

> +
> +static int ixp4xx_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
> +{
> +       struct ixp4xx_gpio *g = gpiochip_get_data(gc);
> +       struct irq_fwspec fwspec;
> +
> +       fwspec.fwnode = g->fwnode;
> +       fwspec.param_count = 2;
> +       fwspec.param[0] = offset;
> +       fwspec.param[1] = IRQ_TYPE_NONE;
> +
> +       return irq_create_fwspec_mapping(&fwspec);
> +}
> +

This is were I start to struggle. I'm still not very well versed in
irq domain hierarchies yet. You already explain the concept in the
commit message, but it would be great if you could add a comment
describing the technical details of implementation here and in other
related callbacks. The whole fwspec thingy is not very obvious and it
would serve as an example for the future.

> +static int ixp4xx_gpio_irq_domain_translate(struct irq_domain *domain,
> +                                           struct irq_fwspec *fwspec,
> +                                           unsigned long *hwirq,
> +                                           unsigned int *type)
> +{
> +
> +       /* We support standard DT translation */
> +       if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
> +               *hwirq = fwspec->param[0];
> +               *type = fwspec->param[1];
> +               return 0;
> +       }

This logic is a bit non-intuitive - maybe you could first check for
error conditions and then do any processing?

> +
> +       /* This goes away when we transition to DT */
> +       if (is_fwnode_irqchip(fwspec->fwnode)) {
> +               if (fwspec->param_count != 2)
> +                       return -EINVAL;
> +               *hwirq = fwspec->param[0];
> +               *type = fwspec->param[1];
> +               WARN_ON(*type == IRQ_TYPE_NONE);
> +               return 0;
> +       }
> +       return -EINVAL;
> +}
> +
> +static int ixp4xx_gpio_irq_domain_alloc(struct irq_domain *d,
> +                                       unsigned int irq, unsigned int nr_irqs,
> +                                       void *data)
> +{
> +       struct ixp4xx_gpio *g = d->host_data;
> +       irq_hw_number_t hwirq;
> +       unsigned int type = IRQ_TYPE_NONE;
> +       struct irq_fwspec *fwspec = data;
> +       int ret;
> +       int i;
> +
> +       ret = ixp4xx_gpio_irq_domain_translate(d, fwspec, &hwirq, &type);
> +       if (ret)
> +               return ret;
> +
> +       dev_dbg(g->dev, "allocate IRQ %d..%d, hwirq %lu..%lu\n",
> +               irq, irq + nr_irqs - 1,
> +               hwirq, hwirq + nr_irqs - 1);
> +
> +       for (i = 0; i < nr_irqs; i++) {
> +               struct irq_fwspec parent_fwspec;
> +               const struct ixp4xx_gpio_map *map;
> +               int j;
> +
> +               /* Not all lines support IRQs */
> +               for (j = 0; j < ARRAY_SIZE(ixp4xx_gpiomap); j++) {
> +                       map = &ixp4xx_gpiomap[j];
> +                       if (map->gpio_offset == hwirq)
> +                               break;
> +               }
> +               if (j == ARRAY_SIZE(ixp4xx_gpiomap)) {
> +                       dev_err(g->dev, "can't look up hwirq %lu\n", hwirq);
> +                       return -EINVAL;
> +               }
> +               dev_dbg(g->dev, "found parent hwirq %u\n", map->parent_hwirq);
> +
> +               /*
> +                * We set handle_bad_irq because the .set_type() should
> +                * always be invoked and set the right type of handler.
> +                */
> +               irq_domain_set_info(d,
> +                                   irq + i,
> +                                   hwirq + i,
> +                                   &ixp4xx_gpio_irqchip,
> +                                   g,
> +                                   handle_bad_irq,
> +                                   NULL, NULL);
> +               irq_set_probe(irq + i);
> +
> +               /*
> +                * Create a IRQ fwspec to send up to the parent irqdomain:
> +                * specify the hwirq we address on the parent and tie it
> +                * all together up the chain.
> +                */
> +               parent_fwspec.fwnode = d->parent->fwnode;
> +               parent_fwspec.param_count = 2;
> +               parent_fwspec.param[0] = map->parent_hwirq;
> +               /* This parent only handles asserted level IRQs */
> +               parent_fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
> +               dev_dbg(g->dev, "alloc_irqs_parent for %d parent hwirq %d\n",
> +                       irq + i, map->parent_hwirq);
> +               ret = irq_domain_alloc_irqs_parent(d, irq + i, 1,
> +                                                  &parent_fwspec);
> +               if (ret)
> +                       dev_err(g->dev,
> +                               "failed to allocate parent hwirq %d for hwirq %lu\n",
> +                               map->parent_hwirq, hwirq);
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct irq_domain_ops ixp4xx_gpio_irqdomain_ops = {
> +       .translate = ixp4xx_gpio_irq_domain_translate,
> +       .alloc = ixp4xx_gpio_irq_domain_alloc,
> +       .free = irq_domain_free_irqs_common,
> +};
> +
> +static int ixp4xx_gpio_probe(struct platform_device *pdev)
> +{
> +       unsigned long flags;
> +       struct device *dev = &pdev->dev;
> +       struct irq_domain *parent;
> +       struct resource *res;
> +       struct ixp4xx_gpio *g;
> +       int ret;
> +       int i;
> +
> +       g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
> +       if (!g)
> +               return -ENOMEM;
> +       g->dev = dev;
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       g->base = devm_ioremap_resource(dev, res);
> +       if (IS_ERR(g->base)) {
> +               dev_err(dev, "ioremap error\n");
> +               return PTR_ERR(g->base);
> +       }
> +
> +       /*
> +        * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on
> +        * specific machines.
> +        */
> +       if (machine_is_dsmg600() || machine_is_nas100d())
> +               __raw_writel(0x0, g->base + IXP4XX_GPIO_GPCLKR);
> +
> +       /*
> +        * This is a very special big-endian ARM issue: when the IXP4xx is
> +        * run in big endian mode, all registers in the machine are switched
> +        * around to the CPU-native endianness. As you see mostly in the
> +        * driver we use __raw_readl()/__raw_writel() to access the registers
> +        * in the appropriate order. With the GPIO library we need to specify
> +        * byte order explicitly, so this flag needs to be set when compiling
> +        * for big endian.
> +        */
> +#if defined(CONFIG_CPU_BIG_ENDIAN)
> +       flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
> +#else
> +       flags = 0;
> +#endif
> +
> +       /* Populate and register gpio chip */
> +       ret = bgpio_init(&g->gc, dev, 4,
> +                        g->base + IXP4XX_GPIO_GPINR,
> +                        g->base + IXP4XX_GPIO_GPOUTR,
> +                        NULL,
> +                        NULL,
> +                        g->base + IXP4XX_GPIO_GPOER,
> +                        flags);
> +       if (ret) {
> +               dev_err(dev, "unable to init generic GPIO\n");
> +               return ret;
> +       }
> +       g->gc.to_irq = ixp4xx_gpio_to_irq;
> +       g->gc.ngpio = 16;
> +       g->gc.label = "IXP4XX_GPIO_CHIP";
> +       /*
> +        * TODO: when we have migrated to device tree and all GPIOs
> +        * are fetched using phandles, set this to -1 to get rid of
> +        * the fixed gpiochip base.
> +        */
> +       g->gc.base = 0;
> +       g->gc.parent = &pdev->dev;
> +       g->gc.owner = THIS_MODULE;
> +
> +       ret = devm_gpiochip_add_data(dev, &g->gc, g);
> +       if (ret) {
> +               dev_err(dev, "failed to add SoC gpiochip\n");
> +               return ret;
> +       }
> +
> +       /*
> +        * When we convert to device tree we will simply look up the
> +        * parent irqdomain using irq_find_host(parent) as parent comes
> +        * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
> +        * the fwnode. For now we need this boardfile style code.
> +        */
> +       parent = ixp4xx_get_irq_domain();
> +       g->fwnode = irq_domain_alloc_fwnode(g->base);
> +       if (!g->fwnode) {
> +               dev_err(dev, "no domain base\n");
> +               return -ENODEV;
> +       }
> +       g->domain = irq_domain_create_hierarchy(parent,
> +                                               IRQ_DOMAIN_FLAG_HIERARCHY,
> +                                               ARRAY_SIZE(ixp4xx_gpiomap),
> +                                               g->fwnode,
> +                                               &ixp4xx_gpio_irqdomain_ops,
> +                                               g);
> +       if (!g->domain) {
> +               irq_domain_free_fwnode(g->fwnode);
> +               dev_err(dev, "no hierarchical irq domain\n");
> +               return ret;
> +       }
> +
> +       /*
> +        * After adding OF support, this is no longer needed: irqs
> +        * will be allocated for the respective fwnodes.
> +        */
> +       for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
> +               const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
> +               struct irq_fwspec fwspec;
> +
> +               fwspec.fwnode = g->fwnode;
> +               /* This is the hwirq for the GPIO line side of things */
> +               fwspec.param[0] = map->gpio_offset;
> +               fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
> +               fwspec.param_count = 2;
> +               ret = __irq_domain_alloc_irqs(g->domain,
> +                                             -1, /* just pick something */
> +                                             1,
> +                                             NUMA_NO_NODE,
> +                                             &fwspec,
> +                                             false,
> +                                             NULL);
> +               if (ret < 0) {
> +                       irq_domain_free_fwnode(g->fwnode);
> +                       dev_err(dev,
> +                               "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
> +                               map->gpio_offset, map->parent_hwirq, ret);
> +                       return ret;
> +               }
> +       }
> +
> +       platform_set_drvdata(pdev, g);
> +       dev_info(dev, "IXP4 GPIO @%p registered\n", g->base);
> +
> +       return 0;
> +}
> +

Don't you need to dispose of the domain in the remove callback? They
don't seem to have devm_ variants yet.

> +static struct platform_driver ixp4xx_gpio_driver = {
> +       .driver = {
> +               .name           = "ixp4xx-gpio",
> +       },
> +       .probe = ixp4xx_gpio_probe,
> +};
> +builtin_platform_driver(ixp4xx_gpio_driver);
> --
> 2.20.1
>

Best regards,
Bartosz Golaszewski

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 13/17 v1] gpio: ixp4xx: Add DT bindings
  2019-02-03 21:42 ` [PATCH 13/17 v1] gpio: ixp4xx: Add DT bindings Linus Walleij
@ 2019-02-06 16:05   ` Bartosz Golaszewski
  2019-02-18 21:27   ` Rob Herring
  1 sibling, 0 replies; 40+ messages in thread
From: Bartosz Golaszewski @ 2019-02-06 16:05 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-devicetree, Arnd Bergmann, Tim Harvey, Krzysztof Halasa,
	Olof Johansson, Imre Kaloz, arm-soc

niedz., 3 lut 2019 o 22:42 Linus Walleij <linus.walleij@linaro.org> napisał(a):
>
> This adds DT bindings for the IXP4xx GPIO controller.
>
> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Bartosz: looking for your ACK on this, it'd be good if
> the other GPIO maintainer is aligned with my ideas here.
> I intend to merge this through the ARM SoC tree.
> ---
>  .../bindings/gpio/intel,ixp4xx-gpio.txt       | 38 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
>
> diff --git a/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
> new file mode 100644
> index 000000000000..8dc41ed99685
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
> @@ -0,0 +1,38 @@
> +Intel IXP4xx XScale Networking Processors GPIO
> +
> +This GPIO controller is found in the Intel IXP4xx processors.
> +It supports 16 GPIO lines.
> +
> +The interrupt portions of the GPIO controller is hierarchical:
> +the synchronous edge detector is part of the GPIO block, but the
> +actual enabling/disabling of the interrupt line is done in the
> +main IXP4xx interrupt controller which has a 1:1 mapping for
> +the first 12 GPIO lines to 12 system interrupts.
> +
> +The remaining 4 GPIO lines can not be used for receiving
> +interrupts.
> +
> +The interrupt parent of this GPIO controller must be the
> +IXP4xx interrupt controller.
> +
> +Required properties:
> +
> +- compatible : Should be
> +  "intel,ixp4xx-gpio"
> +- reg : Should contain registers location and length
> +- gpio-controller : marks this as a GPIO controller
> +- #gpio-cells : Should be 2, see gpio/gpio.txt
> +- interrupt-controller : marks this as an interrupt controller
> +- #interrupt-cells : a standard two-cell interrupt, see
> +  interrupt-controller/interrupts.txt
> +
> +Example:
> +
> +gpio0: gpio@c8004000 {
> +       compatible = "intel,ixp4xx-gpio";
> +       reg = <0xc8004000 0x1000>;
> +       gpio-controller;
> +       #gpio-cells = <2>;
> +       interrupt-controller;
> +       #interrupt-cells = <2>;
> +};
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 775a623dc91d..57d098b85523 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1650,6 +1650,7 @@ M:        Imre Kaloz <kaloz@openwrt.org>
>  M:     Krzysztof Halasa <khalasa@piap.pl>
>  L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
>  S:     Maintained
> +F:     Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
>  F:     Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
>  F:     Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt
>  F:     arch/arm/mach-ixp4xx/
> --
> 2.20.1
>

Looks good to me.

Reviewed-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 14/17 v1] gpio: ixp4xx: Add OF probing support
  2019-02-03 21:42 ` [PATCH 14/17 v1] gpio: ixp4xx: Add OF probing support Linus Walleij
@ 2019-02-06 16:13   ` Bartosz Golaszewski
  0 siblings, 0 replies; 40+ messages in thread
From: Bartosz Golaszewski @ 2019-02-06 16:13 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Arnd Bergmann, Tim Harvey, Krzysztof Halasa, Olof Johansson,
	Imre Kaloz, arm-soc

niedz., 3 lut 2019 o 22:42 Linus Walleij <linus.walleij@linaro.org> napisał(a):
>
> This adds device tree probe and registration support for
> the IXP4xx GPIO driver.
>

What is the reason for not merging it with the patch adding the driver?

> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Bartosz: looking for your ACK on this, it'd be good if
> the other GPIO maintainer is aligned with my ideas here.
> I intend to merge this through the ARM SoC tree.
> ---
>  drivers/gpio/gpio-ixp4xx.c | 84 ++++++++++++++++++++++++++------------
>  1 file changed, 57 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
> index 44c24948379d..38a77c8e0c9c 100644
> --- a/drivers/gpio/gpio-ixp4xx.c
> +++ b/drivers/gpio/gpio-ixp4xx.c
> @@ -11,6 +11,7 @@
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/irqchip.h>
> +#include <linux/of_irq.h>
>  #include <linux/platform_device.h>
>  #include <linux/bitops.h>
>  /* Include that go away with DT transition */
> @@ -305,6 +306,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
>  {
>         unsigned long flags;
>         struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
>         struct irq_domain *parent;
>         struct resource *res;
>         struct ixp4xx_gpio *g;
> @@ -381,11 +383,27 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
>          * from IRQCHIP_DECLARE(), then use of_node_to_fwnode() to get
>          * the fwnode. For now we need this boardfile style code.
>          */

Is this comment still valid after this patch?  Or is this maybe
incomplete DT support (probing only)? If so it need clarifying.

> -       parent = ixp4xx_get_irq_domain();
> -       g->fwnode = irq_domain_alloc_fwnode(g->base);
> -       if (!g->fwnode) {
> -               dev_err(dev, "no domain base\n");
> -               return -ENODEV;
> +       if (np) {
> +               struct device_node *irq_parent;
> +
> +               irq_parent = of_irq_find_parent(np);
> +               if (!irq_parent) {
> +                       dev_err(dev, "no IRQ parent node\n");
> +                       return -ENODEV;
> +               }
> +               parent = irq_find_host(irq_parent);
> +               if (!parent) {
> +                       dev_err(dev, "no IRQ parent domain\n");
> +                       return -ENODEV;
> +               }
> +               g->fwnode = of_node_to_fwnode(np);
> +       } else {
> +               parent = ixp4xx_get_irq_domain();
> +               g->fwnode = irq_domain_alloc_fwnode(g->base);
> +               if (!g->fwnode) {
> +                       dev_err(dev, "no domain base\n");
> +                       return -ENODEV;
> +               }
>         }
>         g->domain = irq_domain_create_hierarchy(parent,
>                                                 IRQ_DOMAIN_FLAG_HIERARCHY,
> @@ -403,28 +421,31 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
>          * After adding OF support, this is no longer needed: irqs
>          * will be allocated for the respective fwnodes.
>          */

Same with the comment here.

> -       for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
> -               const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
> -               struct irq_fwspec fwspec;
> -
> -               fwspec.fwnode = g->fwnode;
> -               /* This is the hwirq for the GPIO line side of things */
> -               fwspec.param[0] = map->gpio_offset;
> -               fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
> -               fwspec.param_count = 2;
> -               ret = __irq_domain_alloc_irqs(g->domain,
> -                                             -1, /* just pick something */
> -                                             1,
> -                                             NUMA_NO_NODE,
> -                                             &fwspec,
> -                                             false,
> -                                             NULL);
> -               if (ret < 0) {
> -                       irq_domain_free_fwnode(g->fwnode);
> -                       dev_err(dev,
> -                               "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
> -                               map->gpio_offset, map->parent_hwirq, ret);
> -                       return ret;
> +       if (!np) {
> +               for (i = 0; i < ARRAY_SIZE(ixp4xx_gpiomap); i++) {
> +                       const struct ixp4xx_gpio_map *map = &ixp4xx_gpiomap[i];
> +                       struct irq_fwspec fwspec;
> +
> +                       fwspec.fwnode = g->fwnode;
> +                       /* This is the hwirq for the GPIO line side of things */
> +                       fwspec.param[0] = map->gpio_offset;
> +                       fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
> +                       fwspec.param_count = 2;
> +                       ret = __irq_domain_alloc_irqs(g->domain,
> +                                                     -1, /* just pick something */
> +                                                     1,
> +                                                     NUMA_NO_NODE,
> +                                                     &fwspec,
> +                                                     false,
> +                                                     NULL);
> +                       if (ret < 0) {
> +                               irq_domain_free_fwnode(g->fwnode);
> +                               dev_err(dev,
> +                                       "can not allocate irq for GPIO line %d parent hwirq %d in hierarchy domain: %d\n",
> +                                       map->gpio_offset, map->parent_hwirq,
> +                                       ret);
> +                               return ret;
> +                       }
>                 }
>         }
>
> @@ -434,9 +455,18 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
>         return 0;
>  }
>
> +static const struct of_device_id ixp4xx_gpio_of_match[] = {
> +       {
> +               .compatible = "intel,ixp4xx-gpio",
> +       },
> +       {},
> +};
> +
> +
>  static struct platform_driver ixp4xx_gpio_driver = {
>         .driver = {
>                 .name           = "ixp4xx-gpio",
> +               .of_match_table = of_match_ptr(ixp4xx_gpio_of_match),
>         },
>         .probe = ixp4xx_gpio_probe,
>  };
> --
> 2.20.1
>

Bart

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 15/17 v1] ARM: ixp4xx: Add DT bindings
  2019-02-04 15:16   ` Rob Herring
@ 2019-02-08 19:37     ` Linus Walleij
  0 siblings, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-08 19:37 UTC (permalink / raw)
  To: Rob Herring
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Arnd Bergmann, Tim Harvey, Krzysztof Halasa, Olof Johansson,
	Imre Kaloz,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Mon, Feb 4, 2019 at 4:16 PM Rob Herring <robh@kernel.org> wrote:
> On Sun, Feb 3, 2019 at 3:42 PM Linus Walleij <linus.walleij@linaro.org> wrote:
> >
> > This adds initial device tree bindings for the IXP4xx machines.
> > This time I tried something wild and crazy and try to make proper
> > JSON-style YAML bindings for the top level.
> >
> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> > ---
> > I have no clear idea on how to auto-test this schema for validity,
> > since it is a bit of a new thing I hope to figure it out as
> > we go.
>
> Is Documentation/devicetree/writing-schema.md missing something on how to?

Yay! Now I finally got around to testing this, and it really works smooth!

I already had it help me find issues with my device trees and all.
This is really paying off from day one, a bit of threshold but it
delivers.

Yours,
Linus Walleij

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 12/17 v1] clocksource/drivers/ixp4xx: Add OF initialization support
  2019-02-03 21:42 ` [PATCH 12/17 v1] clocksource/drivers/ixp4xx: Add OF initialization support Linus Walleij
@ 2019-02-11 11:26   ` Daniel Lezcano
  0 siblings, 0 replies; 40+ messages in thread
From: Daniel Lezcano @ 2019-02-11 11:26 UTC (permalink / raw)
  To: Linus Walleij, linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Tim Harvey, Thomas Gleixner, Arnd Bergmann

On 03/02/2019 22:42, Linus Walleij wrote:
> This adds support for setting up the IXP4xx timer driver from
> device tree.
> 
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Clocksource/timer maintainers: I am requesting an ACK for
> this once you're happy with the driver, as I intend to
> merge all of this IXP4xx rework through ARM SoC.

Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>

> ---
>  drivers/clocksource/timer-ixp4xx.c | 35 ++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/drivers/clocksource/timer-ixp4xx.c b/drivers/clocksource/timer-ixp4xx.c
> index fa78f80792db..404445bc11ea 100644
> --- a/drivers/clocksource/timer-ixp4xx.c
> +++ b/drivers/clocksource/timer-ixp4xx.c
> @@ -16,6 +16,8 @@
>  #include <linux/slab.h>
>  #include <linux/bitops.h>
>  #include <linux/delay.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
>  /* Goes away with OF conversion */
>  #include <linux/platform_data/timer-ixp4xx.h>
>  
> @@ -247,3 +249,36 @@ void __init ixp4xx_timer_setup(resource_size_t timerbase,
>  	ixp4xx_timer_register(base, timer_irq, timer_freq);
>  }
>  EXPORT_SYMBOL_GPL(ixp4xx_timer_setup);
> +
> +#ifdef CONFIG_OF
> +static __init int ixp4xx_of_timer_init(struct device_node *np)
> +{
> +	void __iomem *base;
> +	int irq;
> +	int ret;
> +
> +	base = of_iomap(np, 0);
> +	if (!base) {
> +		pr_crit("IXP4xx: can't remap timer\n");
> +		return -ENODEV;
> +	}
> +
> +	irq = irq_of_parse_and_map(np, 0);
> +	if (irq <= 0) {
> +		pr_err("Can't parse IRQ\n");
> +		ret = -EINVAL;
> +		goto out_unmap;
> +	}
> +
> +	/* TODO: get some fixed clocks into the device tree */
> +	ret = ixp4xx_timer_register(base, irq, 66666000);
> +	if (ret)
> +		goto out_unmap;
> +	return 0;
> +
> +out_unmap:
> +	iounmap(base);
> +	return ret;
> +}
> +TIMER_OF_DECLARE(ixp4xx, "intel,ixp4xx-timer", ixp4xx_of_timer_init);
> +#endif
> 


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


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-03 21:41 ` [PATCH 04/17 v1] irqchip: Add driver for IXP4xx Linus Walleij
@ 2019-02-11 15:30   ` Marc Zyngier
  2019-02-11 20:58     ` Linus Walleij
  0 siblings, 1 reply; 40+ messages in thread
From: Marc Zyngier @ 2019-02-11 15:30 UTC (permalink / raw)
  To: Linus Walleij, linux-arm-kernel, Imre Kaloz, Krzysztof Halasa
  Cc: Olof Johansson, Tim Harvey, Thomas Gleixner, Jason Cooper, Arnd Bergmann

Hi Linus,

On 03/02/2019 21:41, Linus Walleij wrote:
> The IXP4xx (arch/arm/mach-ixp4xx) is an old Intel XScale
> platform that has very wide deployment and use.
> 
> As part of modernizing the platform, we need to implement a
> proper irqchip in the irqchip subsystem.
> 
> The IXP4xx irqchip is tightly jotted together with the GPIO
> controller, and wheras in the past we would deal with this

nit: whereas

> complex logic by adding necessarily different code, we can
> nowadays modernize it using a hierarchical irqchip.
> 
> The actual IXP4 irqchip is a simple active low level IRQ
> controller, whereas the GPIO functionality resides in a
> different memory area and adds edge trigger support for
> the interrupts.
> 
> The interrupts from GPIO lines 0..12 are 1:1 mapped to
> a fixed set of hardware IRQs on this IRQchip, so we
> expect the child GPIO interrupt controller to go in and
> allocate descriptors for these interrupts.
> 
> For the other interrupts, as we do not yet have DT
> support for this platform, we create a linear irqdomain
> and then go in and allocate the IRQs that the legacy
> boards use. This code will be removed on the DT probe
> path when we add DT support to the platform.
> 
> We add some translation code for supporting DT
> translations for the fwnodes, but we leave most of that
> for later.
> 
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> irqchip maintainers: I am requesting an ACK for this once
> you're happy with the driver, as I intend to merge all of
> this IXP4xx rework through ARM SoC.
> ---
>  MAINTAINERS                        |   2 +
>  drivers/irqchip/Kconfig            |   6 +
>  drivers/irqchip/Makefile           |   1 +
>  drivers/irqchip/irq-ixp4xx.c       | 360 +++++++++++++++++++++++++++++
>  include/linux/irqchip/irq-ixp4xx.h |  12 +
>  5 files changed, 381 insertions(+)
>  create mode 100644 drivers/irqchip/irq-ixp4xx.c
>  create mode 100644 include/linux/irqchip/irq-ixp4xx.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 32d444476a90..0d48faa3e635 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1651,6 +1651,8 @@ M:	Krzysztof Halasa <khalasa@piap.pl>
>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
>  S:	Maintained
>  F:	arch/arm/mach-ixp4xx/
> +F:	drivers/irqchip/irq-ixp4xx.c
> +F:	include/linux/irqchip/irq-ixp4xx.h
>  
>  ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
>  M:	Jonathan Cameron <jic23@cam.ac.uk>
> diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
> index 3d1e60779078..c7e09913826b 100644
> --- a/drivers/irqchip/Kconfig
> +++ b/drivers/irqchip/Kconfig
> @@ -150,6 +150,12 @@ config IMGPDC_IRQ
>  	select GENERIC_IRQ_CHIP
>  	select IRQ_DOMAIN
>  
> +config IXP4XX_IRQ
> +	bool
> +	select IRQ_DOMAIN
> +	select GENERIC_IRQ_MULTI_HANDLER
> +	select SPARSE_IRQ
> +
>  config MADERA_IRQ
>  	tristate
>  
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index c93713d24b86..06139d612108 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -41,6 +41,7 @@ obj-$(CONFIG_ATMEL_AIC5_IRQ)	+= irq-atmel-aic-common.o irq-atmel-aic5.o
>  obj-$(CONFIG_I8259)			+= irq-i8259.o
>  obj-$(CONFIG_IMGPDC_IRQ)		+= irq-imgpdc.o
>  obj-$(CONFIG_IRQ_MIPS_CPU)		+= irq-mips-cpu.o
> +obj-$(CONFIG_IXP4XX_IRQ)		+= irq-ixp4xx.o
>  obj-$(CONFIG_SIRF_IRQ)			+= irq-sirfsoc.o
>  obj-$(CONFIG_JCORE_AIC)			+= irq-jcore-aic.o
>  obj-$(CONFIG_RDA_INTC)			+= irq-rda-intc.o
> diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c
> new file mode 100644
> index 000000000000..7deaf0f82a53
> --- /dev/null
> +++ b/drivers/irqchip/irq-ixp4xx.c
> @@ -0,0 +1,360 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * irqchip for the IXP4xx interrupt controller
> + * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
> + *
> + * Based on arch/arm/mach-ixp4xx/common.c
> + * Copyright 2002 (C) Intel Corporation
> + * Copyright 2003-2004 (C) MontaVista, Software, Inc.
> + * Copyright (C) Deepak Saxena <dsaxena@plexity.net>
> + */
> +#include <linux/bitops.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/irq.h>
> +#include <linux/io.h>
> +#include <linux/irqchip.h>
> +#include <linux/irqchip/irq-ixp4xx.h>
> +#include <linux/irqdomain.h>
> +#include <linux/platform_device.h>
> +#include <linux/cpu.h>
> +
> +#include <asm/exception.h>
> +#include <asm/mach/irq.h>
> +
> +#define IXP4XX_ICPR	0x00 /* Interrupt Status */
> +#define IXP4XX_ICMR	0x04 /* Interrupt Enable */
> +#define IXP4XX_ICLR	0x08 /* Interrupt IRQ/FIQ Select */
> +#define IXP4XX_ICIP	0x0C /* IRQ Status */
> +#define IXP4XX_ICFP	0x10 /* FIQ Status */
> +#define IXP4XX_ICHR	0x14 /* Interrupt Priority */
> +#define IXP4XX_ICIH	0x18 /* IRQ Highest Pri Int */
> +#define IXP4XX_ICFH	0x1C /* FIQ Highest Pri Int */
> +
> +/* IXP43x and IXP46x-only */
> +#define	IXP4XX_ICPR2	0x20 /* Interrupt Status 2 */
> +#define	IXP4XX_ICMR2	0x24 /* Interrupt Enable 2 */
> +#define	IXP4XX_ICLR2	0x28 /* Interrupt IRQ/FIQ Select 2 */
> +#define IXP4XX_ICIP2	0x2C /* IRQ Status */
> +#define IXP4XX_ICFP2	0x30 /* FIQ Status */
> +#define IXP4XX_ICEEN	0x34 /* Error High Pri Enable */
> +
> +/**
> + * struct ixp4xx_irq - state container for the Faraday IRQ controller
> + * @irqbase: IRQ controller memory base in virtual memory
> + * @is_356: if this is an IXP43x, IXP45x or IX46x SoC (with 64 IRQs)
> + * @irqchip: irqchip for this instance
> + * @domain: IRQ domain for this instance
> + */
> +struct ixp4xx_irq {
> +	void __iomem *irqbase;
> +	bool is_356;
> +	struct irq_chip irqchip;
> +	struct irq_domain *domain;
> +};
> +
> +/* Local static state container */
> +static struct ixp4xx_irq ixirq;
> +
> +/* GPIO Clocks */
> +#define IXP4XX_GPIO_CLK_0		14
> +#define IXP4XX_GPIO_CLK_1		15
> +
> +static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
> +{
> +	/* All are level active high (asserted) here */

It'd be good to return an error if type isn't LEVEL_HIGH.

> +	return 0;
> +}
> +
> +static void ixp4xx_irq_mask(struct irq_data *d)
> +{
> +	struct ixp4xx_irq *ixi = irq_data_get_irq_chip_data(d);
> +	u32 val;
> +
> +	if (ixi->is_356 && d->hwirq >= 32) {
> +		val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2);
> +		val &= ~BIT(d->hwirq - 32);
> +		__raw_writel(val, ixi->irqbase + IXP4XX_ICMR2);
> +	} else {
> +		val = __raw_readl(ixi->irqbase + IXP4XX_ICMR);
> +		val &= ~BIT(d->hwirq);
> +		__raw_writel(val, ixi->irqbase + IXP4XX_ICMR);
> +	}
> +}

This probably comes from the original code, but I'd like to be able to
use a LE kernel on this HW (full disclosure: I have some of this crap
stashed somewhere in the basement... ;-).

How about using something that enforces the endianness of the accesses,
as I suspect the bus is hardcoded to BE? ioread32be/iowrite32be springs
to mind, and I can see the current IXP4xx code provides such an
implementation in its own io.h (which you may have to make private).

> +
> +/*
> + * Level triggered interrupts on GPIO lines can only be cleared when the
> + * interrupt condition disappears.
> + */
> +static void ixp4xx_irq_unmask(struct irq_data *d)
> +{
> +	struct ixp4xx_irq *ixi = irq_data_get_irq_chip_data(d);
> +	u32 val;
> +
> +	if (ixi->is_356 && d->hwirq >= 32) {
> +		val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2);
> +		val |= BIT(d->hwirq - 32);
> +		__raw_writel(val, ixi->irqbase + IXP4XX_ICMR2);
> +	} else {
> +		val = __raw_readl(ixi->irqbase + IXP4XX_ICMR);
> +		val |= BIT(d->hwirq);
> +		__raw_writel(val, ixi->irqbase + IXP4XX_ICMR);
> +	}
> +}

Same here, as well as all the other places sporting a __raw_ accessor.

> +
> +asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs)
> +{
> +	struct ixp4xx_irq *ixi = &ixirq;
> +	unsigned long status;
> +	int i;
> +
> +	status = __raw_readl(ixi->irqbase + IXP4XX_ICIP);
> +	for_each_set_bit(i, &status, 32)
> +		handle_domain_irq(ixi->domain, i, regs);
> +
> +	/*
> +	 * IXP465/IXP435 has an upper IRQ status register
> +	 */
> +	if (ixi->is_356) {
> +		status = __raw_readl(ixi->irqbase + IXP4XX_ICIP2);
> +		for_each_set_bit(i, &status, 32)
> +			handle_domain_irq(ixi->domain, i + 32, regs);
> +	}
> +}
> +
> +static int ixp4xx_irq_domain_translate(struct irq_domain *domain,
> +				       struct irq_fwspec *fwspec,
> +				       unsigned long *hwirq,
> +				       unsigned int *type)
> +{
> +	/* We support standard DT translation */
> +	if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) {
> +		*hwirq = fwspec->param[0];
> +		*type = fwspec->param[1];
> +		return 0;
> +	}
> +
> +	if (is_fwnode_irqchip(fwspec->fwnode)) {
> +		if (fwspec->param_count != 2)
> +			return -EINVAL;
> +		*hwirq = fwspec->param[0];
> +		*type = fwspec->param[1];
> +		WARN_ON(*type == IRQ_TYPE_NONE);
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int ixp4xx_irq_domain_alloc(struct irq_domain *d,
> +				   unsigned int irq, unsigned int nr_irqs,
> +				   void *data)
> +{
> +	struct ixp4xx_irq *ixi = d->host_data;
> +	irq_hw_number_t hwirq;
> +	unsigned int type = IRQ_TYPE_NONE;
> +	struct irq_fwspec *fwspec = data;
> +	int ret;
> +	int i;
> +
> +	ret = ixp4xx_irq_domain_translate(d, fwspec, &hwirq, &type);
> +	if (ret)
> +		return ret;
> +
> +	for (i = 0; i < nr_irqs; i++) {
> +		/*
> +		 * TODO: after converting IXP4xx to only device tree, set
> +		 * handle_bad_irq as default handler and assume all consumers
> +		 * call .set_type() as this is provided in the second cell in
> +		 * the device tree phandle.
> +		 */
> +		irq_domain_set_info(d,
> +				    irq + i,
> +				    hwirq + i,
> +				    &ixi->irqchip,
> +				    ixi,
> +				    handle_level_irq,
> +				    NULL, NULL);
> +		irq_set_probe(irq + i);
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * This needs to be a hierarchical irqdomain to work well with the
> + * GPIO irqchip (which is lower in the hierarchy)
> + */
> +static const struct irq_domain_ops ixp4xx_irqdomain_ops = {
> +	.translate = ixp4xx_irq_domain_translate,
> +	.alloc = ixp4xx_irq_domain_alloc,
> +	.free = irq_domain_free_irqs_common,
> +};
> +
> +/**
> + * ixp4xx_get_irq_domain() - retrieve the ixp4xx irq domain
> + *
> + * This function will go away when we transition to DT probing.
> + */
> +struct irq_domain *ixp4xx_get_irq_domain(void)
> +{
> +	struct ixp4xx_irq *ixi = &ixirq;
> +
> +	return ixi->domain;
> +}
> +EXPORT_SYMBOL_GPL(ixp4xx_get_irq_domain);
> +
> +/*
> + * This is the Linux IRQ to hwirq mapping table. This goes away when
> + * we have DT support as all IRQ resources are defined in the device
> + * tree. It will register all the IRQs that are not used by the hierarchical
> + * GPIO IRQ chip. The "holes" inbetween these IRQs will be requested by
> + * the GPIO driver using . This is a step-gap solution.
> + */
> +struct ixp4xx_irq_chunk {
> +	int irq;
> +	int hwirq;
> +	int nr_irqs;
> +};
> +
> +static const struct ixp4xx_irq_chunk ixp4xx_irq_chunks[] = {
> +	{
> +		.irq = 16,
> +		.hwirq = 0,
> +		.nr_irqs = 6,
> +	},
> +	{
> +		.irq = 24,
> +		.hwirq = 8,
> +		.nr_irqs = 11,
> +	},
> +	{
> +		.irq = 46,
> +		.hwirq = 30,
> +		.nr_irqs = 2,
> +	},
> +	/* Only on the 436 variants */
> +	{
> +		.irq = 48,
> +		.hwirq = 32,
> +		.nr_irqs = 10,
> +	},
> +};
> +
> +/**
> + * ixp4x_irq_setup() - Common setup code for the IXP4xx interrupt controller
> + * @ixi: State container
> + * @irqbase: Virtual memory base for the interrupt controller
> + * @fwnode: Corresponding fwnode abstraction for this controller
> + * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant
> + */
> +static int ixp4xx_irq_setup(struct ixp4xx_irq *ixi,
> +			    void __iomem *irqbase,
> +			    struct fwnode_handle *fwnode,
> +			    bool is_356)
> +{
> +	int nr_irqs;
> +
> +	ixi->irqbase = irqbase;
> +	ixi->is_356 = is_356;
> +
> +	/* Route all sources to IRQ instead of FIQ */
> +	__raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR);
> +
> +	/* Disable all interrupts */
> +	__raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR);
> +
> +	if (is_356) {
> +		/* Route upper 32 sources to IRQ instead of FIQ */
> +		__raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR2);
> +
> +		/* Disable upper 32 interrupts */
> +		__raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR2);
> +
> +		nr_irqs = 64;
> +	} else {
> +		nr_irqs = 32;
> +	}
> +
> +	ixi->irqchip.name = "IXP4xx";
> +	ixi->irqchip.irq_mask = ixp4xx_irq_mask;
> +	ixi->irqchip.irq_unmask	= ixp4xx_irq_unmask;
> +	ixi->irqchip.irq_set_type = ixp4xx_set_irq_type;

Aren't you guaranteed to only have one such irqchip? If so, this could
become a static const object, instead of allocating it dynamically. Not
a big deal though.

> +
> +	ixi->domain = irq_domain_create_linear(fwnode, nr_irqs,
> +					       &ixp4xx_irqdomain_ops,
> +					       ixi);
> +	if (!ixi->domain) {
> +		pr_crit("IXP4XX: can not add primary irqdomain\n");
> +		return -ENODEV;
> +	}
> +
> +	set_handle_irq(ixp4xx_handle_irq);
> +
> +	return 0;
> +}
> +
> +/**
> + * ixp4xx_irq_init() - Function to initialize the irqchip from boardfiles
> + * @irqbase: physical base for the irq controller
> + * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant
> + */
> +void __init ixp4xx_irq_init(resource_size_t irqbase,
> +			    bool is_356)
> +{
> +	struct ixp4xx_irq *ixi = &ixirq;
> +	void __iomem *base;
> +	struct fwnode_handle *fwnode;
> +	struct irq_fwspec fwspec;
> +	int nr_chunks;
> +	int ret;
> +	int i;
> +
> +	base = ioremap(irqbase, 0x100);
> +	if (!base) {
> +		pr_crit("IXP4XX: could not ioremap interrupt controller\n");
> +		return;
> +	}
> +	fwnode = irq_domain_alloc_fwnode(base);

I assume this is a temporary solution until the SoC gains a DT port (and
the irqchip a DT node)?

> +	if (!fwnode) {
> +		pr_crit("IXP4XX: no domain handle\n");
> +		return;
> +	}
> +	ret = ixp4xx_irq_setup(ixi, base, fwnode, is_356);
> +	if (ret) {
> +		pr_crit("IXP4XX: failed to set up irqchip\n");
> +		irq_domain_free_fwnode(fwnode);
> +	}
> +
> +	nr_chunks = ARRAY_SIZE(ixp4xx_irq_chunks);
> +	if (!is_356)
> +		nr_chunks--;
> +
> +	/*
> +	 * After adding OF support, this is no longer needed: irqs
> +	 * will be allocated for the respective fwnodes.
> +	 */
> +	for (i = 0; i < nr_chunks; i++) {
> +		const struct ixp4xx_irq_chunk *chunk = &ixp4xx_irq_chunks[i];
> +
> +		pr_info("Allocate Linux IRQs %d..%d HW IRQs %d..%d\n",
> +			chunk->irq, chunk->irq + chunk->nr_irqs - 1,
> +			chunk->hwirq, chunk->hwirq + chunk->nr_irqs - 1);
> +		fwspec.fwnode = fwnode;
> +		fwspec.param[0] = chunk->hwirq;
> +		fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
> +		fwspec.param_count = 2;
> +		ret = __irq_domain_alloc_irqs(ixi->domain,
> +					      chunk->irq,
> +					      chunk->nr_irqs,
> +					      NUMA_NO_NODE,
> +					      &fwspec,
> +					      false,
> +					      NULL);
> +		if (ret < 0) {
> +			pr_crit("IXP4XX: can not allocate irqs in hierarchy %d\n",
> +				ret);
> +			return;
> +		}
> +	}
> +}
> +EXPORT_SYMBOL_GPL(ixp4xx_irq_init);
> diff --git a/include/linux/irqchip/irq-ixp4xx.h b/include/linux/irqchip/irq-ixp4xx.h
> new file mode 100644
> index 000000000000..9395917d6936
> --- /dev/null
> +++ b/include/linux/irqchip/irq-ixp4xx.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __IRQ_IXP4XX_H
> +#define __IRQ_IXP4XX_H
> +
> +#include <linux/ioport.h>
> +struct irq_domain;
> +
> +void ixp4xx_irq_init(resource_size_t irqbase,
> +		     bool is_356);
> +struct irq_domain *ixp4xx_get_irq_domain(void);
> +
> +#endif /* __IRQ_IXP4XX_H */
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-11 15:30   ` Marc Zyngier
@ 2019-02-11 20:58     ` Linus Walleij
  2019-02-11 22:11       ` Marc Zyngier
  0 siblings, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2019-02-11 20:58 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Jason Cooper, Arnd Bergmann, Tim Harvey, Krzysztof Halasa,
	Olof Johansson, Thomas Gleixner, Imre Kaloz, Linux ARM

On Mon, Feb 11, 2019 at 4:30 PM Marc Zyngier <marc.zyngier@arm.com> wrote:

> > +static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
> > +{
> > +     /* All are level active high (asserted) here */
>
> It'd be good to return an error if type isn't LEVEL_HIGH.

OK

> > +     if (ixi->is_356 && d->hwirq >= 32) {
> > +             val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2);
> > +             val &= ~BIT(d->hwirq - 32);
> > +             __raw_writel(val, ixi->irqbase + IXP4XX_ICMR2);
> > +     } else {
> > +             val = __raw_readl(ixi->irqbase + IXP4XX_ICMR);
> > +             val &= ~BIT(d->hwirq);
> > +             __raw_writel(val, ixi->irqbase + IXP4XX_ICMR);
> > +     }
> > +}
>
> This probably comes from the original code, but I'd like to be able to
> use a LE kernel on this HW (full disclosure: I have some of this crap
> stashed somewhere in the basement... ;-).

It will work. One reason I am refactoring and preserving IXP4xx
is this stuff from the datasheet:

Ambient Air Temperature (Extended)  -40° C to 85° C
Ambient Air Temperature (Commercial) 0° C to 70° C
MTBF: 60 Years at 55°C

And I don't think there is any big difference between the "extended"
and "commercial" version of this SoC, they all come in the same
sturdy packaging too. Diamonds and IXP4xx are forever.

> How about using something that enforces the endianness of the accesses,
> as I suspect the bus is hardcoded to BE?

So, IIUC (Krzysztof can confirm) IXP4xx works like this that when the
CPU is brought up in LE mode, all bytes on the address bus are
swizzled so that the access can always use the CPU native
endianness.

Isn't it crazy :D

This means __raw_writel() will always do the right thing, because
that uses native endianness, and that is why it is used quite a lot
in IXP4xx drivers.

If you want full control you need to define local helpers for
everything that change behaviour at compile-time such as:

static void foo_writel(u32 val, __iomem void *addr)
{
#if defined(CONFIG_CPU_BIG_ENDIAN)
   iowrite32be(val, addr);
#else
    writel(val, addr);
#endif
}

Which will have the same effect as __raw_writel().

So that is why we use the (ugly) macro __raw_writel() a lot
in IXP4xx drivers.

> ioread32be/iowrite32be springs
> to mind, and I can see the current IXP4xx code provides such an
> implementation in its own io.h (which you may have to make private).

The stuf in <mach/io.h> is there for indirect PCI, which is
another unrelated oddity. PCI devices are always LE (as is
proper). It is there because the PCI host on the IXP4xx can
only access > 64MB PCI memory space with certain quirks that
no other PCI host controller needs.

I will get to this when I try to move that driver to drivers/pci ...
It's unrelated to this business however.

> > +     ixi->irqchip.name = "IXP4xx";
> > +     ixi->irqchip.irq_mask = ixp4xx_irq_mask;
> > +     ixi->irqchip.irq_unmask = ixp4xx_irq_unmask;
> > +     ixi->irqchip.irq_set_type = ixp4xx_set_irq_type;
>
> Aren't you guaranteed to only have one such irqchip? If so, this could
> become a static const object, instead of allocating it dynamically. Not
> a big deal though.

Force of habit. Comes from the GPIO side of things where we
never know how many instances there are of stuff, if it's OK
I'd like to keep it.

> > +     fwnode = irq_domain_alloc_fwnode(base);
>
> I assume this is a temporary solution until the SoC gains a DT port (and
> the irqchip a DT node)?

Yes, see the later DT patch that passes the parent as
fwnode, once all boards are converted we can drop this.

BTW here is how I then use the hierarchical parent in the
GPIO chip:
https://marc.info/?l=linux-arm-kernel&m=154923023907623&w=2
https://marc.info/?l=linux-arm-kernel&m=154923038707686&w=2

Yours,
Linus Walleij

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-11 20:58     ` Linus Walleij
@ 2019-02-11 22:11       ` Marc Zyngier
  2019-02-18  7:06         ` khalasa
  2019-02-18  9:18         ` Arnd Bergmann
  0 siblings, 2 replies; 40+ messages in thread
From: Marc Zyngier @ 2019-02-11 22:11 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jason Cooper, Arnd Bergmann, Tim Harvey, Krzysztof Halasa,
	Olof Johansson, Thomas Gleixner, Imre Kaloz, Linux ARM

On Mon, 11 Feb 2019 21:58:41 +0100
Linus Walleij <linus.walleij@linaro.org> wrote:

> On Mon, Feb 11, 2019 at 4:30 PM Marc Zyngier <marc.zyngier@arm.com> wrote:

[...]

> > How about using something that enforces the endianness of the accesses,
> > as I suspect the bus is hardcoded to BE?  
> 
> So, IIUC (Krzysztof can confirm) IXP4xx works like this that when the
> CPU is brought up in LE mode, all bytes on the address bus are
> swizzled so that the access can always use the CPU native
> endianness.
> 
> Isn't it crazy :D

It's spelled BE32! ;-) I vaguely remember doing some of that on vulcan,
but that's a decade ago, and I've paged it out... ;-)

> This means __raw_writel() will always do the right thing, because
> that uses native endianness, and that is why it is used quite a lot
> in IXP4xx drivers.

OK, it now makes some sense. Maybe a comment somewhere will help if
someone tries to reverse engineer it again in the next decade!

> > Aren't you guaranteed to only have one such irqchip? If so, this could
> > become a static const object, instead of allocating it dynamically. Not
> > a big deal though.  
> 
> Force of habit. Comes from the GPIO side of things where we
> never know how many instances there are of stuff, if it's OK
> I'd like to keep it.

No problem.

> 
> > > +     fwnode = irq_domain_alloc_fwnode(base);  
> >
> > I assume this is a temporary solution until the SoC gains a DT port (and
> > the irqchip a DT node)?  
> 
> Yes, see the later DT patch that passes the parent as
> fwnode, once all boards are converted we can drop this.
> 
> BTW here is how I then use the hierarchical parent in the
> GPIO chip:
> https://marc.info/?l=linux-arm-kernel&m=154923023907623&w=2
> https://marc.info/?l=linux-arm-kernel&m=154923038707686&w=2

Looks pretty cool, and surely even better once entirely converted to DT
(I'm sure I can revive this FSG-3 that has been collecting dust on the
shelf for a number of years).

Please CC me on the whole series next time you respin it!

Thanks,

	M.
-- 
Without deviation from the norm, progress is not possible.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-11 22:11       ` Marc Zyngier
@ 2019-02-18  7:06         ` khalasa
  2019-02-18  7:16           ` Linus Walleij
  2019-02-18  9:18         ` Arnd Bergmann
  1 sibling, 1 reply; 40+ messages in thread
From: khalasa @ 2019-02-18  7:06 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Jason Cooper, Arnd Bergmann, Linus Walleij, Olof Johansson,
	Thomas Gleixner, Imre Kaloz, Tim Harvey, Linux ARM

Marc Zyngier <marc.zyngier@arm.com> writes:

> It's spelled BE32! ;-) I vaguely remember doing some of that on vulcan,
> but that's a decade ago, and I've paged it out... ;-)

Right. It's also called value-preserving (where the "value" must 32-bit
and aligned on 32-bit boundary) or (double) word invariant.

Since most of these accesses are natural 32-bit registers and (almost)
none are ASCII/byte-style, it makes sense. IIRC the PCI has its own
rules, though.
-- 
Krzysztof Halasa

Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-18  7:06         ` khalasa
@ 2019-02-18  7:16           ` Linus Walleij
  2019-02-18  7:35             ` khalasa
  2019-02-18  9:40             ` Arnd Bergmann
  0 siblings, 2 replies; 40+ messages in thread
From: Linus Walleij @ 2019-02-18  7:16 UTC (permalink / raw)
  To: Krzysztof Hałasa
  Cc: Jason Cooper, Arnd Bergmann, Marc Zyngier, Tim Harvey,
	Olof Johansson, Thomas Gleixner, Imre Kaloz, Linux ARM

On Mon, Feb 18, 2019 at 8:06 AM Krzysztof Hałasa <khalasa@piap.pl> wrote:
> Marc Zyngier <marc.zyngier@arm.com> writes:
>
> > It's spelled BE32! ;-) I vaguely remember doing some of that on vulcan,
> > but that's a decade ago, and I've paged it out... ;-)
>
> Right. It's also called value-preserving (where the "value" must 32-bit
> and aligned on 32-bit boundary) or (double) word invariant.
>
> Since most of these accesses are natural 32-bit registers and (almost)
> none are ASCII/byte-style, it makes sense. IIRC the PCI has its own
> rules, though.

IIUC PCI should always be LE and readl() writel() always read/write
in LE. But I see PCI on the IXP4xx is a special history so I am going to
experience it in all its glory now that I start looking at it.

Thanks,
Linus Walleij

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-18  7:16           ` Linus Walleij
@ 2019-02-18  7:35             ` khalasa
  2019-02-18  9:40             ` Arnd Bergmann
  1 sibling, 0 replies; 40+ messages in thread
From: khalasa @ 2019-02-18  7:35 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jason Cooper, Arnd Bergmann, Marc Zyngier, Tim Harvey,
	Olof Johansson, Thomas Gleixner, Imre Kaloz, Linux ARM

Linus Walleij <linus.walleij@linaro.org> writes:

> IIUC PCI should always be LE and readl() writel() always read/write
> in LE. But I see PCI on the IXP4xx is a special history so I am going to
> experience it in all its glory now that I start looking at it.

Oh yeah. BTW obviously readl() and writel() do the right thing on IXP4xx
(otherwise the drivers wouldn't work) and the byte operations work as
well. That's why the internal stuff uses __raw_{readl,writel}() and
the PCI uses readl/writel() and so on (which corrects for endianness
on BE).
-- 
Krzysztof Halasa

Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-11 22:11       ` Marc Zyngier
  2019-02-18  7:06         ` khalasa
@ 2019-02-18  9:18         ` Arnd Bergmann
  1 sibling, 0 replies; 40+ messages in thread
From: Arnd Bergmann @ 2019-02-18  9:18 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Jason Cooper, Linus Walleij, Krzysztof Halasa, Olof Johansson,
	Thomas Gleixner, Imre Kaloz, Tim Harvey, Linux ARM

On Mon, Feb 11, 2019 at 11:12 PM Marc Zyngier <marc.zyngier@arm.com> wrote:
>
> On Mon, 11 Feb 2019 21:58:41 +0100
> Linus Walleij <linus.walleij@linaro.org> wrote:
>
> > On Mon, Feb 11, 2019 at 4:30 PM Marc Zyngier <marc.zyngier@arm.com> wrote:
>
> [...]
>
> > > How about using something that enforces the endianness of the accesses,
> > > as I suspect the bus is hardcoded to BE?
> >
> > So, IIUC (Krzysztof can confirm) IXP4xx works like this that when the
> > CPU is brought up in LE mode, all bytes on the address bus are
> > swizzled so that the access can always use the CPU native
> > endianness.
> >
> > Isn't it crazy :D
>
> It's spelled BE32! ;-) I vaguely remember doing some of that on vulcan,
> but that's a decade ago, and I've paged it out... ;-)
>
> > This means __raw_writel() will always do the right thing, because
> > that uses native endianness, and that is why it is used quite a lot
> > in IXP4xx drivers.
>
> OK, it now makes some sense. Maybe a comment somewhere will help if
> someone tries to reverse engineer it again in the next decade!

I think the best way forward would be to change all the
__raw_readl()/__raw_writel() in ixp4xx specific drivers to a new
accessor that is defined as a trivial wrapper around __raw_readl()/
__raw_writel() but that is explicitly defined as

- always accessing a 32-bit word in native endianess
- only valid on ixp4xx on-chip registers (not PCI)
- containing the required barriers (if any)

In my mental model of the I/O accessors, readl/writel are used
for (little-endian) MMIO register accesses, while __raw_readl()/__raw_writel()
can only be used in portable code on byte streams in memory behind
a bus, not on registers. The way ixp4xx works fits into neither of those
two, so we should not use them here. I also think it's a bug to
use 8-bit or 16-bit accessors for internal registers on ixp4xx, so
having a pair of special helpers makes it impossible to do so.

      Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-18  7:16           ` Linus Walleij
  2019-02-18  7:35             ` khalasa
@ 2019-02-18  9:40             ` Arnd Bergmann
  2019-02-18 12:03               ` khalasa
  1 sibling, 1 reply; 40+ messages in thread
From: Arnd Bergmann @ 2019-02-18  9:40 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Jason Cooper, Marc Zyngier, Tim Harvey, Krzysztof Hałasa,
	Olof Johansson, Thomas Gleixner, Imre Kaloz, Linux ARM

On Mon, Feb 18, 2019 at 8:17 AM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> On Mon, Feb 18, 2019 at 8:06 AM Krzysztof Hałasa <khalasa@piap.pl> wrote:
> > Marc Zyngier <marc.zyngier@arm.com> writes:
> >
> > > It's spelled BE32! ;-) I vaguely remember doing some of that on vulcan,
> > > but that's a decade ago, and I've paged it out... ;-)
> >
> > Right. It's also called value-preserving (where the "value" must 32-bit
> > and aligned on 32-bit boundary) or (double) word invariant.
> >
> > Since most of these accesses are natural 32-bit registers and (almost)
> > none are ASCII/byte-style, it makes sense. IIRC the PCI has its own
> > rules, though.
>
> IIUC PCI should always be LE and readl() writel() always read/write
> in LE. But I see PCI on the IXP4xx is a special history so I am going to
> experience it in all its glory now that I start looking at it.

I found a document that explains some of the more obscure details
of this chip (among a lot of the general concepts), in particular how
you can configure memory regions as either BE, LE-data-coherent or
LE-address-coherent, and the byte swap on PCI depending on that:

https://www.intel.com/content/www/us/en/intelligent-systems/previous-generation/ixp4xx-ixc1100-big-endian-little-endian-modes-app-note.html

      Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-18  9:40             ` Arnd Bergmann
@ 2019-02-18 12:03               ` khalasa
  2019-02-18 12:44                 ` Arnd Bergmann
  0 siblings, 1 reply; 40+ messages in thread
From: khalasa @ 2019-02-18 12:03 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Jason Cooper, Marc Zyngier, Linus Walleij, Olof Johansson,
	Thomas Gleixner, Imre Kaloz, Tim Harvey, Linux ARM

Arnd Bergmann <arnd@arndb.de> writes:

> I found a document that explains some of the more obscure details
> of this chip (among a lot of the general concepts), in particular how
> you can configure memory regions as either BE, LE-data-coherent or
> LE-address-coherent, and the byte swap on PCI depending on that:

There is also a problem with certain devices (certain old US Robotics
access servers?) using IXP425 rev. A0. Those first chips don't have the
LE data coherent mode.
We (= the official Linux kernel) don't use LE data coherent mode at all,
though I have had a patch (not very clean) which could do that.
-- 
Krzysztof Halasa

Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-18 12:03               ` khalasa
@ 2019-02-18 12:44                 ` Arnd Bergmann
  2019-02-19  6:51                   ` khalasa
  0 siblings, 1 reply; 40+ messages in thread
From: Arnd Bergmann @ 2019-02-18 12:44 UTC (permalink / raw)
  To: Krzysztof Hałasa
  Cc: Jason Cooper, Marc Zyngier, Linus Walleij, Olof Johansson,
	Thomas Gleixner, Imre Kaloz, Tim Harvey, Linux ARM

On Mon, Feb 18, 2019 at 1:03 PM Krzysztof Hałasa <khalasa@piap.pl> wrote:
>
> Arnd Bergmann <arnd@arndb.de> writes:
>
> > I found a document that explains some of the more obscure details
> > of this chip (among a lot of the general concepts), in particular how
> > you can configure memory regions as either BE, LE-data-coherent or
> > LE-address-coherent, and the byte swap on PCI depending on that:
>
> There is also a problem with certain devices (certain old US Robotics
> access servers?) using IXP425 rev. A0. Those first chips don't have the
> LE data coherent mode.
> We (= the official Linux kernel) don't use LE data coherent mode at all,
> though I have had a patch (not very clean) which could do that.

It does sound appealing to move to data coherent mode, since that is
closer to what we have elsewhere. Maybe we can finally work that out
and then allow a little-endian multiplatform configuration to include
ixp4xx.

I have two questions about this:

- I have a vague memory that only specific revisions actually require
  the PCI indirect mode. Is it the same chip revision A0 of IXP425
  that requires both pci-indirect and address-coherent mode, or are
  there other combinations?

- How much would it hurt actual users to drop support for both
  features? I.e. do we know of anyone using the affected chips
  (and still doing updates), or are the remaining ixp4xx systems
  generally using the later chip revision?

      Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 09/17 v1] irqchip: ixp4xx: Add DT bindings
  2019-02-03 21:41 ` [PATCH 09/17 v1] irqchip: ixp4xx: Add DT bindings Linus Walleij
@ 2019-02-18 21:25   ` Rob Herring
  0 siblings, 0 replies; 40+ messages in thread
From: Rob Herring @ 2019-02-18 21:25 UTC (permalink / raw)
  To: Linus Walleij
  Cc: devicetree, Jason Cooper, Arnd Bergmann, Marc Zyngier,
	Tim Harvey, Krzysztof Halasa, Olof Johansson, Thomas Gleixner,
	Imre Kaloz,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Sun, Feb 3, 2019 at 3:42 PM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> This adds device tree bindings for the IXP4xx interrupt
> controller. It's a standard 2-cell controller.

Not required, but writing as a schema would be great. Looks like it
would be straight forward.

> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> irqchip maintainers: I am requesting an ACK for this once
> you're happy with the bindings, as I intend to merge all of
> this IXP4xx rework through ARM SoC.
> ---
>  .../intel,ixp4xx-interrupt.txt                | 33 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 34 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
>
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
> new file mode 100644
> index 000000000000..70ee93b9a6c0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.txt
> @@ -0,0 +1,33 @@
> +* Intel IXP4xx XScale Networking Processors Interrupt Controller
> +
> +This interrupt controller is found in the Intel IXP4xx processors.
> +Some processors have 32 interrupts, some have up to 64 interrupts.
> +The exact number of interrupts is determined from the compatible
> +string.
> +
> +The distinct IXP4xx families with different interrupt controller
> +variations are IXP42x, IXP43x, IXP45x and IXP46x. Those four
> +families were the only ones to reach the developer and consumer
> +market.
> +
> +Required properties:
> +- compatible: must be one of
> +  "intel,ixp42x-interrupt"
> +  "intel,ixp43x-interrupt"
> +  "intel,ixp45x-interrupt"
> +  "intel,ixp46x-interrupt"

While we normally don't allow wildcards, I'm guessing this is all so
old^W mature that it will be fine.

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 11/17 v1] clocksource/drivers/ixp4xx: Add DT bindings
  2019-02-03 21:41 ` [PATCH 11/17 v1] clocksource/drivers/ixp4xx: Add DT bindings Linus Walleij
@ 2019-02-18 21:26   ` Rob Herring
  2019-02-18 22:10     ` Daniel Lezcano
  0 siblings, 1 reply; 40+ messages in thread
From: Rob Herring @ 2019-02-18 21:26 UTC (permalink / raw)
  To: Linus Walleij
  Cc: devicetree, Arnd Bergmann, Tim Harvey, Daniel Lezcano,
	Krzysztof Halasa, Olof Johansson, Thomas Gleixner, Imre Kaloz,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Sun, Feb 3, 2019 at 3:42 PM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> This adds device tree bindings for the Intel IXP4xx
> timers.
>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Clocksource/timer maintainers: I am requesting an ACK for
> this once you're happy with the bindings, as I intend to
> merge all of this IXP4xx rework through ARM SoC.
> ---
>  .../bindings/timer/intel,ixp4xx-timer.txt      | 18 ++++++++++++++++++
>  MAINTAINERS                                    |  1 +
>  2 files changed, 19 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt

Same wish and comments here...

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 13/17 v1] gpio: ixp4xx: Add DT bindings
  2019-02-03 21:42 ` [PATCH 13/17 v1] gpio: ixp4xx: Add DT bindings Linus Walleij
  2019-02-06 16:05   ` Bartosz Golaszewski
@ 2019-02-18 21:27   ` Rob Herring
  1 sibling, 0 replies; 40+ messages in thread
From: Rob Herring @ 2019-02-18 21:27 UTC (permalink / raw)
  To: Linus Walleij
  Cc: devicetree, Arnd Bergmann, Tim Harvey, Bartosz Golaszewski,
	Krzysztof Halasa, Olof Johansson, Imre Kaloz,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Sun, Feb 3, 2019 at 3:42 PM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> This adds DT bindings for the IXP4xx GPIO controller.
>
> Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> Bartosz: looking for your ACK on this, it'd be good if
> the other GPIO maintainer is aligned with my ideas here.
> I intend to merge this through the ARM SoC tree.
> ---
>  .../bindings/gpio/intel,ixp4xx-gpio.txt       | 38 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 39 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 11/17 v1] clocksource/drivers/ixp4xx: Add DT bindings
  2019-02-18 21:26   ` Rob Herring
@ 2019-02-18 22:10     ` Daniel Lezcano
  0 siblings, 0 replies; 40+ messages in thread
From: Daniel Lezcano @ 2019-02-18 22:10 UTC (permalink / raw)
  To: Rob Herring, Linus Walleij
  Cc: devicetree, Arnd Bergmann, Tim Harvey, Krzysztof Halasa,
	Olof Johansson, Thomas Gleixner, Imre Kaloz,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On 18/02/2019 22:26, Rob Herring wrote:
> On Sun, Feb 3, 2019 at 3:42 PM Linus Walleij <linus.walleij@linaro.org> wrote:
>>
>> This adds device tree bindings for the Intel IXP4xx
>> timers.
>>
>> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: devicetree@vger.kernel.org
>> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
>> ---
>> Clocksource/timer maintainers: I am requesting an ACK for
>> this once you're happy with the bindings, as I intend to
>> merge all of this IXP4xx rework through ARM SoC.
>> ---
>>  .../bindings/timer/intel,ixp4xx-timer.txt      | 18 ++++++++++++++++++
>>  MAINTAINERS                                    |  1 +
>>  2 files changed, 19 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.txt
> 
> Same wish and comments here...
> 
> Reviewed-by: Rob Herring <robh@kernel.org>

Thanks,

Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>


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


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-18 12:44                 ` Arnd Bergmann
@ 2019-02-19  6:51                   ` khalasa
  2019-02-19  9:46                     ` Arnd Bergmann
  0 siblings, 1 reply; 40+ messages in thread
From: khalasa @ 2019-02-19  6:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Jason Cooper, Marc Zyngier, Linus Walleij, Olof Johansson,
	Thomas Gleixner, Imre Kaloz, Tim Harvey, Linux ARM

Arnd Bergmann <arnd@arndb.de> writes:

> - I have a vague memory that only specific revisions actually require
>   the PCI indirect mode. Is it the same chip revision A0 of IXP425
>   that requires both pci-indirect and address-coherent mode, or are
>   there other combinations?

IIRC, all chips support indirect PCI. Perhaps there are some changes
about LE mode on the PCI, but that's it.

Most boards don't need indirect PCI. It's only needed when there is more
than 64 MB of PCI address space to be used - IIRC IXP4xx have 4 direct
PCI memory access windows, and each is 16 MB in size.
I remember I needed indirect PCI for use with a (SiS?) VGA card, it had
(I guess) 128 MB of RAM. I think indirect PCI means the memory can't be
really mapped, it can only be accessed using readl() and friends (which
are then converted into register accesses resulting in the actual MMIO).
Even with indirect PCI, 64 MB can be accessed directly (though I think
we don't support it).

This is different from the bus mastering access to the main RAM - I
think only the first 64 MB can be used for PCI BM DMA. This limitation,
IIRC, doesn't apply to internal devices (Ethernet etc).

> - How much would it hurt actual users to drop support for both
>   features? I.e. do we know of anyone using the affected chips
>   (and still doing updates), or are the remaining ixp4xx systems
>   generally using the later chip revision?

Most chips are B0+, though there are (were) certain A0 platforms.
I don't have any idea about their current use.
-- 
Krzysztof Halasa

Industrial Research Institute for Automation and Measurements PIAP
Al. Jerozolimskie 202, 02-486 Warsaw, Poland

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 04/17 v1] irqchip: Add driver for IXP4xx
  2019-02-19  6:51                   ` khalasa
@ 2019-02-19  9:46                     ` Arnd Bergmann
  0 siblings, 0 replies; 40+ messages in thread
From: Arnd Bergmann @ 2019-02-19  9:46 UTC (permalink / raw)
  To: Krzysztof Hałasa
  Cc: Jason Cooper, Marc Zyngier, Linus Walleij, Olof Johansson,
	Thomas Gleixner, Imre Kaloz, Tim Harvey, Linux ARM

On Tue, Feb 19, 2019 at 7:51 AM Krzysztof Hałasa <khalasa@piap.pl> wrote:
> Arnd Bergmann <arnd@arndb.de> writes:
> > - I have a vague memory that only specific revisions actually require
> >   the PCI indirect mode. Is it the same chip revision A0 of IXP425
> >   that requires both pci-indirect and address-coherent mode, or are
> >   there other combinations?
>
> IIRC, all chips support indirect PCI. Perhaps there are some changes
> about LE mode on the PCI, but that's it.
>
> Most boards don't need indirect PCI. It's only needed when there is more
> than 64 MB of PCI address space to be used - IIRC IXP4xx have 4 direct
> PCI memory access windows, and each is 16 MB in size.
> I remember I needed indirect PCI for use with a (SiS?) VGA card, it had
> (I guess) 128 MB of RAM. I think indirect PCI means the memory can't be
> really mapped, it can only be accessed using readl() and friends (which
> are then converted into register accesses resulting in the actual MMIO).
> Even with indirect PCI, 64 MB can be accessed directly (though I think
> we don't support it).
>
> This is different from the bus mastering access to the main RAM - I
> think only the first 64 MB can be used for PCI BM DMA. This limitation,
> IIRC, doesn't apply to internal devices (Ethernet etc).

Thanks a lot for this background, that helps a lot. We actually
have a more general implementation of this (indirect mmio and pio)
in arch/powerpc/kernel/io-workarounds.c, and I was considering
whether we can make that architecture independent code and
reuse it here as well.

Looking at the powerpc implementation however, I see two other
problems:

- the way it is implemented requires using some spare address
  bits on a 64-bit pointer, so that would have to be change a lot
  to work on a 32-bit architecture
- the MMIO workarounds don't really work for a VGA card
  in general since you cannot map the frame buffer into user
  space, so the application of that is still a bit limited. I suspect
  you would have had the same problem with the existing
  ixp4xx code as well, depending on how the driver implements
  user space graphics.

We could still consider using it on Allwinner H6, which is a 64-bit
chip that is even more limited (only 64 /KB/ can be mapped at a
time).

> > - How much would it hurt actual users to drop support for both
> >   features? I.e. do we know of anyone using the affected chips
> >   (and still doing updates), or are the remaining ixp4xx systems
> >   generally using the later chip revision?
>
> Most chips are B0+, though there are (were) certain A0 platforms.
> I don't have any idea about their current use.

Ok, fair enough.

     Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, back to index

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-03 21:41 [PATCH 00/17 v1] ARM: ixp4xx: Modernize and DT support Linus Walleij
2019-02-03 21:41 ` [PATCH 01/17 v1] ARM: ixp4xx: Convert to MULTI_IRQ_HANDLER Linus Walleij
2019-02-03 21:41 ` [PATCH 02/17 v1] ARM: ixp4xx: Pass IRQ resource to beeper Linus Walleij
2019-02-03 21:41 ` [PATCH 03/17 v1] ARM: ixp4xx: Convert to SPARSE_IRQ Linus Walleij
2019-02-03 21:41 ` [PATCH 04/17 v1] irqchip: Add driver for IXP4xx Linus Walleij
2019-02-11 15:30   ` Marc Zyngier
2019-02-11 20:58     ` Linus Walleij
2019-02-11 22:11       ` Marc Zyngier
2019-02-18  7:06         ` khalasa
2019-02-18  7:16           ` Linus Walleij
2019-02-18  7:35             ` khalasa
2019-02-18  9:40             ` Arnd Bergmann
2019-02-18 12:03               ` khalasa
2019-02-18 12:44                 ` Arnd Bergmann
2019-02-19  6:51                   ` khalasa
2019-02-19  9:46                     ` Arnd Bergmann
2019-02-18  9:18         ` Arnd Bergmann
2019-02-03 21:41 ` [PATCH 05/17 v1] gpio: ixp4xx: Add driver for the IXP4xx GPIO Linus Walleij
2019-02-06 16:03   ` Bartosz Golaszewski
2019-02-03 21:41 ` [PATCH 06/17 v1] ARM: ixp4xx: Switch to use new IRQ+GPIO drivers Linus Walleij
2019-02-03 21:41 ` [PATCH 07/17 v1] clocksource/drivers/ixp4xx: Add driver Linus Walleij
2019-02-03 21:41 ` [PATCH 08/17 v1] ARM: ixp4xx: Switch to use new timer driver Linus Walleij
2019-02-03 21:41 ` [PATCH 09/17 v1] irqchip: ixp4xx: Add DT bindings Linus Walleij
2019-02-18 21:25   ` Rob Herring
2019-02-03 21:41 ` [PATCH 10/17 v1] irqchip: ixp4xx: Add OF initialization support Linus Walleij
2019-02-03 21:41 ` [PATCH 11/17 v1] clocksource/drivers/ixp4xx: Add DT bindings Linus Walleij
2019-02-18 21:26   ` Rob Herring
2019-02-18 22:10     ` Daniel Lezcano
2019-02-03 21:42 ` [PATCH 12/17 v1] clocksource/drivers/ixp4xx: Add OF initialization support Linus Walleij
2019-02-11 11:26   ` Daniel Lezcano
2019-02-03 21:42 ` [PATCH 13/17 v1] gpio: ixp4xx: Add DT bindings Linus Walleij
2019-02-06 16:05   ` Bartosz Golaszewski
2019-02-18 21:27   ` Rob Herring
2019-02-03 21:42 ` [PATCH 14/17 v1] gpio: ixp4xx: Add OF probing support Linus Walleij
2019-02-06 16:13   ` Bartosz Golaszewski
2019-02-03 21:42 ` [PATCH 15/17 v1] ARM: ixp4xx: Add DT bindings Linus Walleij
2019-02-04 15:16   ` Rob Herring
2019-02-08 19:37     ` Linus Walleij
2019-02-03 21:42 ` [PATCH 16/17 v1] ARM: ixp4xx: Add device tree boot support Linus Walleij
2019-02-03 21:42 ` [PATCH 17/17 v1] RFC: ARM: dts: Add some initial IXP4xx device trees Linus Walleij

Linux-ARM-Kernel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-arm-kernel/0 linux-arm-kernel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-arm-kernel linux-arm-kernel/ https://lore.kernel.org/linux-arm-kernel \
		linux-arm-kernel@lists.infradead.org infradead-linux-arm-kernel@archiver.kernel.org
	public-inbox-index linux-arm-kernel


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.infradead.lists.linux-arm-kernel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox