* [PATCH V2 01/10] microblaze: irqchip: Move intc driver to irqchip [not found] <1471527804-26175-1-git-send-email-Zubair.Kakakhel@imgtec.com> @ 2016-08-18 13:43 ` Zubair Lutfullah Kakakhel 2016-08-26 14:13 ` Marc Zyngier 2016-08-18 13:43 ` [PATCH V2 05/10] MIPS: xilfpga: Update DT node and specify uart irq Zubair Lutfullah Kakakhel ` (4 subsequent siblings) 5 siblings, 1 reply; 7+ messages in thread From: Zubair Lutfullah Kakakhel @ 2016-08-18 13:43 UTC (permalink / raw) To: monstr, ralf, tglx Cc: jason, marc.zyngier, linux-mips, linux-kernel, netdev, Zubair.Kakakhel The Xilinx AXI Interrupt Controller IP block is used by the MIPS based xilfpga platform. Move the interrupt controller code out of arch/microblaze so that it can be used by everyone Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> --- V1 -> V2 Renamed irq-xilinx to irq-axi-intc Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC Patch is now without rename flag so as to facilitate review --- arch/microblaze/Kconfig | 1 + arch/microblaze/kernel/Makefile | 2 +- arch/microblaze/kernel/intc.c | 196 ---------------------------------------- drivers/irqchip/Kconfig | 4 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-axi-intc.c | 196 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 203 insertions(+), 197 deletions(-) delete mode 100644 arch/microblaze/kernel/intc.c create mode 100644 drivers/irqchip/irq-axi-intc.c diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 86f6572..a9ddcaa 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -27,6 +27,7 @@ config MICROBLAZE select HAVE_MEMBLOCK_NODE_MAP select HAVE_OPROFILE select IRQ_DOMAIN + select XILINX_AXI_INTC select MODULES_USE_ELF_RELA select OF select OF_EARLY_FLATTREE diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index f08baca..e098381 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -15,7 +15,7 @@ endif extra-y := head.o vmlinux.lds obj-y += dma.o exceptions.o \ - hw_exception_handler.o intc.o irq.o \ + hw_exception_handler.o irq.o \ platform.o process.o prom.o ptrace.o \ reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c deleted file mode 100644 index 90bec7d..0000000 --- a/arch/microblaze/kernel/intc.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu> - * Copyright (C) 2012-2013 Xilinx, Inc. - * Copyright (C) 2007-2009 PetaLogix - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include <linux/irqdomain.h> -#include <linux/irq.h> -#include <linux/irqchip.h> -#include <linux/of_address.h> -#include <linux/io.h> -#include <linux/bug.h> - -static void __iomem *intc_baseaddr; - -/* No one else should require these constants, so define them locally here. */ -#define ISR 0x00 /* Interrupt Status Register */ -#define IPR 0x04 /* Interrupt Pending Register */ -#define IER 0x08 /* Interrupt Enable Register */ -#define IAR 0x0c /* Interrupt Acknowledge Register */ -#define SIE 0x10 /* Set Interrupt Enable bits */ -#define CIE 0x14 /* Clear Interrupt Enable bits */ -#define IVR 0x18 /* Interrupt Vector Register */ -#define MER 0x1c /* Master Enable Register */ - -#define MER_ME (1<<0) -#define MER_HIE (1<<1) - -static unsigned int (*read_fn)(void __iomem *); -static void (*write_fn)(u32, void __iomem *); - -static void intc_write32(u32 val, void __iomem *addr) -{ - iowrite32(val, addr); -} - -static unsigned int intc_read32(void __iomem *addr) -{ - return ioread32(addr); -} - -static void intc_write32_be(u32 val, void __iomem *addr) -{ - iowrite32be(val, addr); -} - -static unsigned int intc_read32_be(void __iomem *addr) -{ - return ioread32be(addr); -} - -static void intc_enable_or_unmask(struct irq_data *d) -{ - unsigned long mask = 1 << d->hwirq; - - pr_debug("enable_or_unmask: %ld\n", d->hwirq); - - /* ack level irqs because they can't be acked during - * ack function since the handle_level_irq function - * acks the irq before calling the interrupt handler - */ - if (irqd_is_level_type(d)) - write_fn(mask, intc_baseaddr + IAR); - - write_fn(mask, intc_baseaddr + SIE); -} - -static void intc_disable_or_mask(struct irq_data *d) -{ - pr_debug("disable: %ld\n", d->hwirq); - write_fn(1 << d->hwirq, intc_baseaddr + CIE); -} - -static void intc_ack(struct irq_data *d) -{ - pr_debug("ack: %ld\n", d->hwirq); - write_fn(1 << d->hwirq, intc_baseaddr + IAR); -} - -static void intc_mask_ack(struct irq_data *d) -{ - unsigned long mask = 1 << d->hwirq; - - pr_debug("disable_and_ack: %ld\n", d->hwirq); - write_fn(mask, intc_baseaddr + CIE); - write_fn(mask, intc_baseaddr + IAR); -} - -static struct irq_chip intc_dev = { - .name = "Xilinx INTC", - .irq_unmask = intc_enable_or_unmask, - .irq_mask = intc_disable_or_mask, - .irq_ack = intc_ack, - .irq_mask_ack = intc_mask_ack, -}; - -static struct irq_domain *root_domain; - -unsigned int get_irq(void) -{ - unsigned int hwirq, irq = -1; - - hwirq = read_fn(intc_baseaddr + IVR); - if (hwirq != -1U) - irq = irq_find_mapping(root_domain, hwirq); - - pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq); - - return irq; -} - -static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -{ - u32 intr_mask = (u32)d->host_data; - - if (intr_mask & (1 << hw)) { - irq_set_chip_and_handler_name(irq, &intc_dev, - handle_edge_irq, "edge"); - irq_clear_status_flags(irq, IRQ_LEVEL); - } else { - irq_set_chip_and_handler_name(irq, &intc_dev, - handle_level_irq, "level"); - irq_set_status_flags(irq, IRQ_LEVEL); - } - return 0; -} - -static const struct irq_domain_ops xintc_irq_domain_ops = { - .xlate = irq_domain_xlate_onetwocell, - .map = xintc_map, -}; - -static int __init xilinx_intc_of_init(struct device_node *intc, - struct device_node *parent) -{ - u32 nr_irq, intr_mask; - int ret; - - intc_baseaddr = of_iomap(intc, 0); - BUG_ON(!intc_baseaddr); - - ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq); - if (ret < 0) { - pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__); - return ret; - } - - ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask); - if (ret < 0) { - pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__); - return ret; - } - - if (intr_mask >> nr_irq) - pr_warn("%s: mismatch in kind-of-intr param\n", __func__); - - pr_info("%s: num_irq=%d, edge=0x%x\n", - intc->full_name, nr_irq, intr_mask); - - write_fn = intc_write32; - read_fn = intc_read32; - - /* - * Disable all external interrupts until they are - * explicity requested. - */ - write_fn(0, intc_baseaddr + IER); - - /* Acknowledge any pending interrupts just in case. */ - write_fn(0xffffffff, intc_baseaddr + IAR); - - /* Turn on the Master Enable. */ - write_fn(MER_HIE | MER_ME, intc_baseaddr + MER); - if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) { - write_fn = intc_write32_be; - read_fn = intc_read32_be; - write_fn(MER_HIE | MER_ME, intc_baseaddr + MER); - } - - /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm - * lazy and Michal can clean it up to something nicer when he tests - * and commits this patch. ~~gcl */ - root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops, - (void *)intr_mask); - - irq_set_default_host(root_domain); - - return 0; -} - -IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init); diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 7f87289..4429888 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -203,6 +203,10 @@ config XTENSA_MX bool select IRQ_DOMAIN +config XILINX_AXI_INTC + bool + select IRQ_DOMAIN + config IRQ_CROSSBAR bool help diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 4c203b6..bf21f55 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o +obj-$(CONFIG_XILINX_AXI_INTC) += irq-axi-intc.o obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o diff --git a/drivers/irqchip/irq-axi-intc.c b/drivers/irqchip/irq-axi-intc.c new file mode 100644 index 0000000..90bec7d --- /dev/null +++ b/drivers/irqchip/irq-axi-intc.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2012-2013 Xilinx, Inc. + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/irqdomain.h> +#include <linux/irq.h> +#include <linux/irqchip.h> +#include <linux/of_address.h> +#include <linux/io.h> +#include <linux/bug.h> + +static void __iomem *intc_baseaddr; + +/* No one else should require these constants, so define them locally here. */ +#define ISR 0x00 /* Interrupt Status Register */ +#define IPR 0x04 /* Interrupt Pending Register */ +#define IER 0x08 /* Interrupt Enable Register */ +#define IAR 0x0c /* Interrupt Acknowledge Register */ +#define SIE 0x10 /* Set Interrupt Enable bits */ +#define CIE 0x14 /* Clear Interrupt Enable bits */ +#define IVR 0x18 /* Interrupt Vector Register */ +#define MER 0x1c /* Master Enable Register */ + +#define MER_ME (1<<0) +#define MER_HIE (1<<1) + +static unsigned int (*read_fn)(void __iomem *); +static void (*write_fn)(u32, void __iomem *); + +static void intc_write32(u32 val, void __iomem *addr) +{ + iowrite32(val, addr); +} + +static unsigned int intc_read32(void __iomem *addr) +{ + return ioread32(addr); +} + +static void intc_write32_be(u32 val, void __iomem *addr) +{ + iowrite32be(val, addr); +} + +static unsigned int intc_read32_be(void __iomem *addr) +{ + return ioread32be(addr); +} + +static void intc_enable_or_unmask(struct irq_data *d) +{ + unsigned long mask = 1 << d->hwirq; + + pr_debug("enable_or_unmask: %ld\n", d->hwirq); + + /* ack level irqs because they can't be acked during + * ack function since the handle_level_irq function + * acks the irq before calling the interrupt handler + */ + if (irqd_is_level_type(d)) + write_fn(mask, intc_baseaddr + IAR); + + write_fn(mask, intc_baseaddr + SIE); +} + +static void intc_disable_or_mask(struct irq_data *d) +{ + pr_debug("disable: %ld\n", d->hwirq); + write_fn(1 << d->hwirq, intc_baseaddr + CIE); +} + +static void intc_ack(struct irq_data *d) +{ + pr_debug("ack: %ld\n", d->hwirq); + write_fn(1 << d->hwirq, intc_baseaddr + IAR); +} + +static void intc_mask_ack(struct irq_data *d) +{ + unsigned long mask = 1 << d->hwirq; + + pr_debug("disable_and_ack: %ld\n", d->hwirq); + write_fn(mask, intc_baseaddr + CIE); + write_fn(mask, intc_baseaddr + IAR); +} + +static struct irq_chip intc_dev = { + .name = "Xilinx INTC", + .irq_unmask = intc_enable_or_unmask, + .irq_mask = intc_disable_or_mask, + .irq_ack = intc_ack, + .irq_mask_ack = intc_mask_ack, +}; + +static struct irq_domain *root_domain; + +unsigned int get_irq(void) +{ + unsigned int hwirq, irq = -1; + + hwirq = read_fn(intc_baseaddr + IVR); + if (hwirq != -1U) + irq = irq_find_mapping(root_domain, hwirq); + + pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq); + + return irq; +} + +static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +{ + u32 intr_mask = (u32)d->host_data; + + if (intr_mask & (1 << hw)) { + irq_set_chip_and_handler_name(irq, &intc_dev, + handle_edge_irq, "edge"); + irq_clear_status_flags(irq, IRQ_LEVEL); + } else { + irq_set_chip_and_handler_name(irq, &intc_dev, + handle_level_irq, "level"); + irq_set_status_flags(irq, IRQ_LEVEL); + } + return 0; +} + +static const struct irq_domain_ops xintc_irq_domain_ops = { + .xlate = irq_domain_xlate_onetwocell, + .map = xintc_map, +}; + +static int __init xilinx_intc_of_init(struct device_node *intc, + struct device_node *parent) +{ + u32 nr_irq, intr_mask; + int ret; + + intc_baseaddr = of_iomap(intc, 0); + BUG_ON(!intc_baseaddr); + + ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq); + if (ret < 0) { + pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__); + return ret; + } + + ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask); + if (ret < 0) { + pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__); + return ret; + } + + if (intr_mask >> nr_irq) + pr_warn("%s: mismatch in kind-of-intr param\n", __func__); + + pr_info("%s: num_irq=%d, edge=0x%x\n", + intc->full_name, nr_irq, intr_mask); + + write_fn = intc_write32; + read_fn = intc_read32; + + /* + * Disable all external interrupts until they are + * explicity requested. + */ + write_fn(0, intc_baseaddr + IER); + + /* Acknowledge any pending interrupts just in case. */ + write_fn(0xffffffff, intc_baseaddr + IAR); + + /* Turn on the Master Enable. */ + write_fn(MER_HIE | MER_ME, intc_baseaddr + MER); + if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) { + write_fn = intc_write32_be; + read_fn = intc_read32_be; + write_fn(MER_HIE | MER_ME, intc_baseaddr + MER); + } + + /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm + * lazy and Michal can clean it up to something nicer when he tests + * and commits this patch. ~~gcl */ + root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops, + (void *)intr_mask); + + irq_set_default_host(root_domain); + + return 0; +} + +IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init); -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH V2 01/10] microblaze: irqchip: Move intc driver to irqchip 2016-08-18 13:43 ` [PATCH V2 01/10] microblaze: irqchip: Move intc driver to irqchip Zubair Lutfullah Kakakhel @ 2016-08-26 14:13 ` Marc Zyngier 0 siblings, 0 replies; 7+ messages in thread From: Marc Zyngier @ 2016-08-26 14:13 UTC (permalink / raw) To: Zubair Lutfullah Kakakhel Cc: monstr, ralf, tglx, jason, linux-mips, linux-kernel, netdev On Thu, 18 Aug 2016 14:43:15 +0100 Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> wrote: Hi Zubair, Thanks for the heads up, comments below. > The Xilinx AXI Interrupt Controller IP block is used by the MIPS > based xilfpga platform. > > Move the interrupt controller code out of arch/microblaze so that > it can be used by everyone > > Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> > > --- > V1 -> V2 > > Renamed irq-xilinx to irq-axi-intc > Renamed CONFIG_XILINX_INTC to CONFIG_XILINX_AXI_INTC > Patch is now without rename flag so as to facilitate review > --- > arch/microblaze/Kconfig | 1 + > arch/microblaze/kernel/Makefile | 2 +- > arch/microblaze/kernel/intc.c | 196 ---------------------------------------- > drivers/irqchip/Kconfig | 4 + > drivers/irqchip/Makefile | 1 + > drivers/irqchip/irq-axi-intc.c | 196 ++++++++++++++++++++++++++++++++++++++++ > 6 files changed, 203 insertions(+), 197 deletions(-) > delete mode 100644 arch/microblaze/kernel/intc.c > create mode 100644 drivers/irqchip/irq-axi-intc.c > [...] diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig > index 7f87289..4429888 100644 > --- a/drivers/irqchip/Kconfig > +++ b/drivers/irqchip/Kconfig > @@ -203,6 +203,10 @@ config XTENSA_MX > bool > select IRQ_DOMAIN > > +config XILINX_AXI_INTC > + bool > + select IRQ_DOMAIN > + > config IRQ_CROSSBAR > bool > help > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile > index 4c203b6..bf21f55 100644 > --- a/drivers/irqchip/Makefile > +++ b/drivers/irqchip/Makefile > @@ -51,6 +51,7 @@ obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o > obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o > obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o > obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o > +obj-$(CONFIG_XILINX_AXI_INTC) += irq-axi-intc.o > obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o > obj-$(CONFIG_SOC_VF610) += irq-vf610-mscm-ir.o > obj-$(CONFIG_BCM6345_L1_IRQ) += irq-bcm6345-l1.o > diff --git a/drivers/irqchip/irq-axi-intc.c b/drivers/irqchip/irq-axi-intc.c > new file mode 100644 > index 0000000..90bec7d > --- /dev/null > +++ b/drivers/irqchip/irq-axi-intc.c > @@ -0,0 +1,196 @@ > +/* > + * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu> > + * Copyright (C) 2012-2013 Xilinx, Inc. > + * Copyright (C) 2007-2009 PetaLogix > + * Copyright (C) 2006 Atmark Techno, Inc. > + * > + * This file is subject to the terms and conditions of the GNU General Public > + * License. See the file "COPYING" in the main directory of this archive > + * for more details. > + */ > + > +#include <linux/irqdomain.h> > +#include <linux/irq.h> > +#include <linux/irqchip.h> > +#include <linux/of_address.h> > +#include <linux/io.h> > +#include <linux/bug.h> > + > +static void __iomem *intc_baseaddr; > + > +/* No one else should require these constants, so define them locally here. */ > +#define ISR 0x00 /* Interrupt Status Register */ > +#define IPR 0x04 /* Interrupt Pending Register */ > +#define IER 0x08 /* Interrupt Enable Register */ > +#define IAR 0x0c /* Interrupt Acknowledge Register */ > +#define SIE 0x10 /* Set Interrupt Enable bits */ > +#define CIE 0x14 /* Clear Interrupt Enable bits */ > +#define IVR 0x18 /* Interrupt Vector Register */ > +#define MER 0x1c /* Master Enable Register */ > + > +#define MER_ME (1<<0) > +#define MER_HIE (1<<1) > + > +static unsigned int (*read_fn)(void __iomem *); > +static void (*write_fn)(u32, void __iomem *); > + > +static void intc_write32(u32 val, void __iomem *addr) > +{ > + iowrite32(val, addr); > +} > + > +static unsigned int intc_read32(void __iomem *addr) > +{ > + return ioread32(addr); > +} > + > +static void intc_write32_be(u32 val, void __iomem *addr) > +{ > + iowrite32be(val, addr); > +} > + > +static unsigned int intc_read32_be(void __iomem *addr) > +{ > + return ioread32be(addr); > +} > + > +static void intc_enable_or_unmask(struct irq_data *d) > +{ > + unsigned long mask = 1 << d->hwirq; > + > + pr_debug("enable_or_unmask: %ld\n", d->hwirq); > + > + /* ack level irqs because they can't be acked during > + * ack function since the handle_level_irq function > + * acks the irq before calling the interrupt handler > + */ > + if (irqd_is_level_type(d)) > + write_fn(mask, intc_baseaddr + IAR); > + > + write_fn(mask, intc_baseaddr + SIE); > +} > + > +static void intc_disable_or_mask(struct irq_data *d) > +{ > + pr_debug("disable: %ld\n", d->hwirq); > + write_fn(1 << d->hwirq, intc_baseaddr + CIE); > +} > + > +static void intc_ack(struct irq_data *d) > +{ > + pr_debug("ack: %ld\n", d->hwirq); > + write_fn(1 << d->hwirq, intc_baseaddr + IAR); > +} > + > +static void intc_mask_ack(struct irq_data *d) > +{ > + unsigned long mask = 1 << d->hwirq; > + > + pr_debug("disable_and_ack: %ld\n", d->hwirq); > + write_fn(mask, intc_baseaddr + CIE); > + write_fn(mask, intc_baseaddr + IAR); > +} > + > +static struct irq_chip intc_dev = { > + .name = "Xilinx INTC", > + .irq_unmask = intc_enable_or_unmask, > + .irq_mask = intc_disable_or_mask, > + .irq_ack = intc_ack, > + .irq_mask_ack = intc_mask_ack, > +}; > + > +static struct irq_domain *root_domain; > + > +unsigned int get_irq(void) Does this need to be global? It doesn't seem to be used in this patch... > +{ > + unsigned int hwirq, irq = -1; > + > + hwirq = read_fn(intc_baseaddr + IVR); > + if (hwirq != -1U) > + irq = irq_find_mapping(root_domain, hwirq); > + > + pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq); > + > + return irq; > +} > + > +static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) > +{ > + u32 intr_mask = (u32)d->host_data; > + > + if (intr_mask & (1 << hw)) { > + irq_set_chip_and_handler_name(irq, &intc_dev, > + handle_edge_irq, "edge"); > + irq_clear_status_flags(irq, IRQ_LEVEL); > + } else { > + irq_set_chip_and_handler_name(irq, &intc_dev, > + handle_level_irq, "level"); > + irq_set_status_flags(irq, IRQ_LEVEL); > + } > + return 0; > +} > + > +static const struct irq_domain_ops xintc_irq_domain_ops = { > + .xlate = irq_domain_xlate_onetwocell, > + .map = xintc_map, > +}; > + > +static int __init xilinx_intc_of_init(struct device_node *intc, > + struct device_node *parent) > +{ > + u32 nr_irq, intr_mask; > + int ret; > + > + intc_baseaddr = of_iomap(intc, 0); > + BUG_ON(!intc_baseaddr); > + > + ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq); > + if (ret < 0) { > + pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__); > + return ret; > + } > + > + ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask); > + if (ret < 0) { > + pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__); > + return ret; > + } > + > + if (intr_mask >> nr_irq) > + pr_warn("%s: mismatch in kind-of-intr param\n", __func__); > + > + pr_info("%s: num_irq=%d, edge=0x%x\n", > + intc->full_name, nr_irq, intr_mask); > + > + write_fn = intc_write32; > + read_fn = intc_read32; > + > + /* > + * Disable all external interrupts until they are > + * explicity requested. > + */ > + write_fn(0, intc_baseaddr + IER); > + > + /* Acknowledge any pending interrupts just in case. */ > + write_fn(0xffffffff, intc_baseaddr + IAR); > + > + /* Turn on the Master Enable. */ > + write_fn(MER_HIE | MER_ME, intc_baseaddr + MER); > + if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) { > + write_fn = intc_write32_be; > + read_fn = intc_read32_be; > + write_fn(MER_HIE | MER_ME, intc_baseaddr + MER); > + } > + > + /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm > + * lazy and Michal can clean it up to something nicer when he tests > + * and commits this patch. ~~gcl */ > + root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops, > + (void *)intr_mask); Since you're now reworking this driver, how about addressing this ugliness? You could store the intr_mask together with intc_baseaddr, and the read/write functions in a global structure, and pass a pointer to it? That would make the code a bit nicer... > + > + irq_set_default_host(root_domain); > + > + return 0; > +} > + > +IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init); Is "lnx,xps-intc-1.00.a" the only supported interrupt controller? Or is there something slightly more generic than this one? Thanks, M. -- Jazz is not dead. It just smells funny. ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH V2 05/10] MIPS: xilfpga: Update DT node and specify uart irq [not found] <1471527804-26175-1-git-send-email-Zubair.Kakakhel@imgtec.com> 2016-08-18 13:43 ` [PATCH V2 01/10] microblaze: irqchip: Move intc driver to irqchip Zubair Lutfullah Kakakhel @ 2016-08-18 13:43 ` Zubair Lutfullah Kakakhel 2016-08-18 13:43 ` [PATCH V2 07/10] net: ethernet: xilinx: Generate random mac if none found Zubair Lutfullah Kakakhel ` (3 subsequent siblings) 5 siblings, 0 replies; 7+ messages in thread From: Zubair Lutfullah Kakakhel @ 2016-08-18 13:43 UTC (permalink / raw) To: monstr, ralf, tglx Cc: jason, marc.zyngier, linux-mips, linux-kernel, netdev, Zubair.Kakakhel Update the DT node with the UART irq Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> --- V1 -> V2 No change --- arch/mips/boot/dts/xilfpga/nexys4ddr.dts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/mips/boot/dts/xilfpga/nexys4ddr.dts b/arch/mips/boot/dts/xilfpga/nexys4ddr.dts index 8db660b..d285c8d 100644 --- a/arch/mips/boot/dts/xilfpga/nexys4ddr.dts +++ b/arch/mips/boot/dts/xilfpga/nexys4ddr.dts @@ -50,6 +50,9 @@ reg-offset = <0x1000>; clocks = <&ext>; + + interrupt-parent = <&axi_intc>; + interrupts = <0>; }; }; -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH V2 07/10] net: ethernet: xilinx: Generate random mac if none found [not found] <1471527804-26175-1-git-send-email-Zubair.Kakakhel@imgtec.com> 2016-08-18 13:43 ` [PATCH V2 01/10] microblaze: irqchip: Move intc driver to irqchip Zubair Lutfullah Kakakhel 2016-08-18 13:43 ` [PATCH V2 05/10] MIPS: xilfpga: Update DT node and specify uart irq Zubair Lutfullah Kakakhel @ 2016-08-18 13:43 ` Zubair Lutfullah Kakakhel 2016-08-18 13:43 ` [PATCH V2 10/10] MIPS: xilfpga: Update defconfig Zubair Lutfullah Kakakhel ` (2 subsequent siblings) 5 siblings, 0 replies; 7+ messages in thread From: Zubair Lutfullah Kakakhel @ 2016-08-18 13:43 UTC (permalink / raw) To: monstr, ralf, tglx Cc: jason, marc.zyngier, linux-mips, linux-kernel, netdev, Zubair.Kakakhel At the moment, if the emaclite device doesn't find a mac address from any source, it simply uses 0x0 with a warning printed. Instead of using a 0x0 mac address, use a randomly generated one. Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> --- V1 -> V2 New patch --- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c index 3cee84a..22e5a5a 100644 --- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c +++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c @@ -1134,8 +1134,10 @@ static int xemaclite_of_probe(struct platform_device *ofdev) if (mac_address) /* Set the MAC address. */ memcpy(ndev->dev_addr, mac_address, ETH_ALEN); - else - dev_warn(dev, "No MAC address found\n"); + else { + dev_warn(dev, "No MAC address found. Generating Random one\n"); + eth_hw_addr_random(ndev); + } /* Clear the Tx CSR's in case this is a restart */ __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET); -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH V2 10/10] MIPS: xilfpga: Update defconfig [not found] <1471527804-26175-1-git-send-email-Zubair.Kakakhel@imgtec.com> ` (2 preceding siblings ...) 2016-08-18 13:43 ` [PATCH V2 07/10] net: ethernet: xilinx: Generate random mac if none found Zubair Lutfullah Kakakhel @ 2016-08-18 13:43 ` Zubair Lutfullah Kakakhel 2016-08-26 13:41 ` [PATCH V2 00/10] microblaze/MIPS: xilfpga: intc and peripheral Zubair Lutfullah Kakakhel [not found] ` <1471527804-26175-3-git-send-email-Zubair.Kakakhel@imgtec.com> 5 siblings, 0 replies; 7+ messages in thread From: Zubair Lutfullah Kakakhel @ 2016-08-18 13:43 UTC (permalink / raw) To: monstr, ralf, tglx Cc: jason, marc.zyngier, linux-mips, linux-kernel, netdev, Zubair.Kakakhel Update defconfig to enable emaclite, i2c, temp sensor found on the xilfpga platform Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> --- V1 -> V2 No change --- arch/mips/configs/xilfpga_defconfig | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/arch/mips/configs/xilfpga_defconfig b/arch/mips/configs/xilfpga_defconfig index ed1dce3..829c637 100644 --- a/arch/mips/configs/xilfpga_defconfig +++ b/arch/mips/configs/xilfpga_defconfig @@ -7,6 +7,12 @@ CONFIG_EMBEDDED=y CONFIG_SLAB=y # CONFIG_BLOCK is not set # CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IPV6 is not set +# CONFIG_WIRELESS is not set # CONFIG_UEVENT_HELPER is not set CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y @@ -14,6 +20,30 @@ CONFIG_DEVTMPFS_MOUNT=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FW_LOADER is not set # CONFIG_ALLOW_DEV_COREDUMP is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_CORE is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_XILINX_EMACLITE=y +CONFIG_SMSC_PHY=y +# CONFIG_WLAN is not set # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set @@ -25,13 +55,18 @@ CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_XILINX=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_XILINX=y -# CONFIG_HWMON is not set +CONFIG_SENSORS_ADT7410=y # CONFIG_USB_SUPPORT is not set # CONFIG_MIPS_PLATFORM_DEVICES is not set # CONFIG_IOMMU_SUPPORT is not set # CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_PANIC_ON_OOPS=y # CONFIG_SCHED_DEBUG is not set -- 1.9.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH V2 00/10] microblaze/MIPS: xilfpga: intc and peripheral [not found] <1471527804-26175-1-git-send-email-Zubair.Kakakhel@imgtec.com> ` (3 preceding siblings ...) 2016-08-18 13:43 ` [PATCH V2 10/10] MIPS: xilfpga: Update defconfig Zubair Lutfullah Kakakhel @ 2016-08-26 13:41 ` Zubair Lutfullah Kakakhel [not found] ` <1471527804-26175-3-git-send-email-Zubair.Kakakhel@imgtec.com> 5 siblings, 0 replies; 7+ messages in thread From: Zubair Lutfullah Kakakhel @ 2016-08-26 13:41 UTC (permalink / raw) To: monstr, ralf, tglx; +Cc: jason, marc.zyngier, linux-mips, linux-kernel, netdev Hi, On 08/18/2016 02:43 PM, Zubair Lutfullah Kakakhel wrote: > Hi, > > The MIPS based Xilfpga platform uses the axi interrupt controller > daisy chained to the MIPS microAptiv cpu interrupt controller. > This patch series moves the axi interrupt controller driver out > of arch/microblaze to drivers/irqchip. This makes it usable by > MIPS. The rest of the series basically enables drivers and adds dt > nodes. > > Would make sense for this to go via the MIPS tree. > Hence, ACKs from microblaze. irqchip and net welcome. > > Compile tested on microblaze-el only! > Based on v4.8-rc2 Ping. Would be nice to see this in for v4.9. Thanks ZubairLK > > Regards, > ZubairLK > > V1 -> V2 > Resubmitting without truncating the diff output for file moves > Removed accidental local mac address entry > Individual logs have more detail > > Zubair Lutfullah Kakakhel (10): > microblaze: irqchip: Move intc driver to irqchip > irqchip: xilinx: Add support for parent intc > MIPS: xilfpga: Use irqchip_init instead of the legacy way > MIPS: xilfpga: Use Xilinx AXI Interrupt Controller > MIPS: xilfpga: Update DT node and specify uart irq > MIPS: Xilfpga: Add DT node for AXI I2C > net: ethernet: xilinx: Generate random mac if none found > net: ethernet: xilinx: Enable emaclite for MIPS > MIPS: xilfpga: Add DT node for AXI emaclite > MIPS: xilfpga: Update defconfig > > arch/microblaze/Kconfig | 1 + > arch/microblaze/kernel/Makefile | 2 +- > arch/microblaze/kernel/intc.c | 196 ----------------------- > arch/mips/Kconfig | 1 + > arch/mips/boot/dts/xilfpga/nexys4ddr.dts | 63 ++++++++ > arch/mips/configs/xilfpga_defconfig | 37 ++++- > arch/mips/xilfpga/intc.c | 7 +- > drivers/irqchip/Kconfig | 4 + > drivers/irqchip/Makefile | 1 + > drivers/irqchip/irq-axi-intc.c | 222 ++++++++++++++++++++++++++ > drivers/net/ethernet/xilinx/Kconfig | 4 +- > drivers/net/ethernet/xilinx/xilinx_emaclite.c | 6 +- > 12 files changed, 337 insertions(+), 207 deletions(-) > delete mode 100644 arch/microblaze/kernel/intc.c > create mode 100644 drivers/irqchip/irq-axi-intc.c > ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <1471527804-26175-3-git-send-email-Zubair.Kakakhel@imgtec.com>]
* Re: [PATCH V2 02/10] irqchip: xilinx: Add support for parent intc [not found] ` <1471527804-26175-3-git-send-email-Zubair.Kakakhel@imgtec.com> @ 2016-08-26 14:23 ` Marc Zyngier 0 siblings, 0 replies; 7+ messages in thread From: Marc Zyngier @ 2016-08-26 14:23 UTC (permalink / raw) To: Zubair Lutfullah Kakakhel Cc: monstr, ralf, tglx, jason, linux-mips, linux-kernel, netdev On Thu, 18 Aug 2016 14:43:16 +0100 Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> wrote: > The MIPS based xilfpga platform has the following IRQ structure > > Peripherals --> xilinx_intcontroller -> mips_cpu_int controller > > Add support for the driver to chain the irq handler > > Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> > > --- > V1 -> V2 > > No change > --- > drivers/irqchip/irq-axi-intc.c | 28 +++++++++++++++++++++++++++- > 1 file changed, 27 insertions(+), 1 deletion(-) > > diff --git a/drivers/irqchip/irq-axi-intc.c b/drivers/irqchip/irq-axi-intc.c > index 90bec7d..a0be6fa 100644 > --- a/drivers/irqchip/irq-axi-intc.c > +++ b/drivers/irqchip/irq-axi-intc.c > @@ -15,6 +15,7 @@ > #include <linux/of_address.h> > #include <linux/io.h> > #include <linux/bug.h> > +#include <linux/of_irq.h> > > static void __iomem *intc_baseaddr; > > @@ -135,11 +136,26 @@ static const struct irq_domain_ops xintc_irq_domain_ops = { > .map = xintc_map, > }; > > +static void xil_intc_irq_handler(struct irq_desc *desc) > +{ > + u32 pending = get_irq(); > + > + if (pending != -1U) { > + while (true) { > + pending = get_irq(); > + generic_handle_irq(pending); > + if (pending == -1U) Erm... So even when pending is -1, you're calling generic_handle_irq? This doesn't seem right. You're also missing the chained_irq_enter/exit calls around this loop. Overall, this should be rewritten in a less cumbersome way. Something like: do { u32 pending; pending = get_irq(); if (pending == ~0) break; generic_handle_irq(pending); } while (true); > + break; > + } > + } > +} > + > static int __init xilinx_intc_of_init(struct device_node *intc, > struct device_node *parent) > { > u32 nr_irq, intr_mask; > - int ret; > + int ret, irq; > + struct device_node *parent_node; > > intc_baseaddr = of_iomap(intc, 0); > BUG_ON(!intc_baseaddr); > @@ -188,6 +204,16 @@ static int __init xilinx_intc_of_init(struct device_node *intc, > root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops, > (void *)intr_mask); > > + parent_node = of_irq_find_parent(intc); You already have the parent node as an argument to the function. Why do you need to do that again? > + if (parent_node) { > + irq = irq_of_parse_and_map(intc, 0); > + if (irq) > + irq_set_chained_handler_and_data(irq, > + xil_intc_irq_handler, > + root_domain); > + > + } > + > irq_set_default_host(root_domain); > > return 0; Thanks, M. -- Jazz is not dead. It just smells funny. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2016-08-26 14:23 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1471527804-26175-1-git-send-email-Zubair.Kakakhel@imgtec.com>
2016-08-18 13:43 ` [PATCH V2 01/10] microblaze: irqchip: Move intc driver to irqchip Zubair Lutfullah Kakakhel
2016-08-26 14:13 ` Marc Zyngier
2016-08-18 13:43 ` [PATCH V2 05/10] MIPS: xilfpga: Update DT node and specify uart irq Zubair Lutfullah Kakakhel
2016-08-18 13:43 ` [PATCH V2 07/10] net: ethernet: xilinx: Generate random mac if none found Zubair Lutfullah Kakakhel
2016-08-18 13:43 ` [PATCH V2 10/10] MIPS: xilfpga: Update defconfig Zubair Lutfullah Kakakhel
2016-08-26 13:41 ` [PATCH V2 00/10] microblaze/MIPS: xilfpga: intc and peripheral Zubair Lutfullah Kakakhel
[not found] ` <1471527804-26175-3-git-send-email-Zubair.Kakakhel@imgtec.com>
2016-08-26 14:23 ` [PATCH V2 02/10] irqchip: xilinx: Add support for parent intc Marc Zyngier
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox