From 44e08e7099c8de226606cfc989b45d6fa27f507f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sun, 24 May 2015 16:11:31 +0100 Subject: MIPS/IRQCHIP: Move Ingenic SoC intc driver to drivers/irqchip Move the driver for Ingenic SoC interrupt controllers into drivers/irqchip where it belongs. Signed-off-by: Paul Burton Cc: Lars-Peter Clausen Cc: Thomas Gleixner Cc: Jason Cooper Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: Brian Norris Patchwork: https://patchwork.linux-mips.org/patch/10147/ Signed-off-by: Ralf Baechle --- arch/mips/jz4740/Makefile | 2 +- arch/mips/jz4740/gpio.c | 3 +- arch/mips/jz4740/irq.c | 178 ---------------------------------------- arch/mips/jz4740/irq.h | 23 ------ drivers/irqchip/Kconfig | 5 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-ingenic.c | 177 +++++++++++++++++++++++++++++++++++++++ include/linux/irqchip/ingenic.h | 23 ++++++ 8 files changed, 208 insertions(+), 204 deletions(-) delete mode 100644 arch/mips/jz4740/irq.c delete mode 100644 arch/mips/jz4740/irq.h create mode 100644 drivers/irqchip/irq-ingenic.c create mode 100644 include/linux/irqchip/ingenic.h diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile index 28e5535dfa9e..6cf5dd42fa34 100644 --- a/arch/mips/jz4740/Makefile +++ b/arch/mips/jz4740/Makefile @@ -4,7 +4,7 @@ # Object file lists. -obj-y += prom.o irq.o time.o reset.o setup.o \ +obj-y += prom.o time.o reset.o setup.o \ gpio.o clock.o platform.o timer.o serial.o obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c index 994a7dfe6f22..54c80d42a88d 100644 --- a/arch/mips/jz4740/gpio.c +++ b/arch/mips/jz4740/gpio.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -28,8 +29,6 @@ #include -#include "irq.h" - #define JZ4740_GPIO_BASE_A (32*0) #define JZ4740_GPIO_BASE_B (32*1) #define JZ4740_GPIO_BASE_C (32*2) diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c deleted file mode 100644 index 64b4c3639280..000000000000 --- a/arch/mips/jz4740/irq.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2009-2010, Lars-Peter Clausen - * JZ4740 platform IRQ support - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "irq.h" - -#include "../../drivers/irqchip/irqchip.h" - -struct ingenic_intc_data { - void __iomem *base; - unsigned num_chips; -}; - -#define JZ_REG_INTC_STATUS 0x00 -#define JZ_REG_INTC_MASK 0x04 -#define JZ_REG_INTC_SET_MASK 0x08 -#define JZ_REG_INTC_CLEAR_MASK 0x0c -#define JZ_REG_INTC_PENDING 0x10 -#define CHIP_SIZE 0x20 - -static irqreturn_t intc_cascade(int irq, void *data) -{ - struct ingenic_intc_data *intc = irq_get_handler_data(irq); - uint32_t irq_reg; - unsigned i; - - for (i = 0; i < intc->num_chips; i++) { - irq_reg = readl(intc->base + (i * CHIP_SIZE) + - JZ_REG_INTC_PENDING); - if (!irq_reg) - continue; - - generic_handle_irq(__fls(irq_reg) + (i * 32) + JZ4740_IRQ_BASE); - } - - return IRQ_HANDLED; -} - -static void intc_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask) -{ - struct irq_chip_regs *regs = &gc->chip_types->regs; - - writel(mask, gc->reg_base + regs->enable); - writel(~mask, gc->reg_base + regs->disable); -} - -void ingenic_intc_irq_suspend(struct irq_data *data) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); - intc_irq_set_mask(gc, gc->wake_active); -} - -void ingenic_intc_irq_resume(struct irq_data *data) -{ - struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); - intc_irq_set_mask(gc, gc->mask_cache); -} - -static struct irqaction intc_cascade_action = { - .handler = intc_cascade, - .name = "SoC intc cascade interrupt", -}; - -static int __init ingenic_intc_of_init(struct device_node *node, - unsigned num_chips) -{ - struct ingenic_intc_data *intc; - struct irq_chip_generic *gc; - struct irq_chip_type *ct; - struct irq_domain *domain; - int parent_irq, err = 0; - unsigned i; - - intc = kzalloc(sizeof(*intc), GFP_KERNEL); - if (!intc) { - err = -ENOMEM; - goto out_err; - } - - parent_irq = irq_of_parse_and_map(node, 0); - if (!parent_irq) { - err = -EINVAL; - goto out_free; - } - - err = irq_set_handler_data(parent_irq, intc); - if (err) - goto out_unmap_irq; - - intc->num_chips = num_chips; - intc->base = of_iomap(node, 0); - if (!intc->base) { - err = -ENODEV; - goto out_unmap_irq; - } - - for (i = 0; i < num_chips; i++) { - /* Mask all irqs */ - writel(0xffffffff, intc->base + (i * CHIP_SIZE) + - JZ_REG_INTC_SET_MASK); - - gc = irq_alloc_generic_chip("INTC", 1, - JZ4740_IRQ_BASE + (i * 32), - intc->base + (i * CHIP_SIZE), - handle_level_irq); - - gc->wake_enabled = IRQ_MSK(32); - - ct = gc->chip_types; - ct->regs.enable = JZ_REG_INTC_CLEAR_MASK; - ct->regs.disable = JZ_REG_INTC_SET_MASK; - ct->chip.irq_unmask = irq_gc_unmask_enable_reg; - ct->chip.irq_mask = irq_gc_mask_disable_reg; - ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; - ct->chip.irq_set_wake = irq_gc_set_wake; - ct->chip.irq_suspend = ingenic_intc_irq_suspend; - ct->chip.irq_resume = ingenic_intc_irq_resume; - - irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, - IRQ_NOPROBE | IRQ_LEVEL); - } - - domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0, - &irq_domain_simple_ops, NULL); - if (!domain) - pr_warn("unable to register IRQ domain\n"); - - setup_irq(parent_irq, &intc_cascade_action); - return 0; - -out_unmap_irq: - irq_dispose_mapping(parent_irq); -out_free: - kfree(intc); -out_err: - return err; -} - -static int __init intc_1chip_of_init(struct device_node *node, - struct device_node *parent) -{ - return ingenic_intc_of_init(node, 1); -} -IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init); - -static int __init intc_2chip_of_init(struct device_node *node, - struct device_node *parent) -{ - return ingenic_intc_of_init(node, 2); -} -IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init); -IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init); -IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init); diff --git a/arch/mips/jz4740/irq.h b/arch/mips/jz4740/irq.h deleted file mode 100644 index 601d5274ac69..000000000000 --- a/arch/mips/jz4740/irq.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2010, Lars-Peter Clausen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef __MIPS_JZ4740_IRQ_H__ -#define __MIPS_JZ4740_IRQ_H__ - -#include - -extern void ingenic_intc_irq_suspend(struct irq_data *data); -extern void ingenic_intc_irq_resume(struct irq_data *data); - -#endif diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 2b7531e0e84c..746daf37454c 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -163,3 +163,8 @@ config KEYSTONE_IRQ config MIPS_GIC bool select MIPS_CM + +config INGENIC_IRQ + bool + depends on MACH_INGENIC + default y diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 129cde1ff5a7..db014e8e12c9 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -48,3 +48,4 @@ obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o +obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o diff --git a/drivers/irqchip/irq-ingenic.c b/drivers/irqchip/irq-ingenic.c new file mode 100644 index 000000000000..005de3f932ae --- /dev/null +++ b/drivers/irqchip/irq-ingenic.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2009-2010, Lars-Peter Clausen + * JZ4740 platform IRQ support + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "irqchip.h" + +struct ingenic_intc_data { + void __iomem *base; + unsigned num_chips; +}; + +#define JZ_REG_INTC_STATUS 0x00 +#define JZ_REG_INTC_MASK 0x04 +#define JZ_REG_INTC_SET_MASK 0x08 +#define JZ_REG_INTC_CLEAR_MASK 0x0c +#define JZ_REG_INTC_PENDING 0x10 +#define CHIP_SIZE 0x20 + +static irqreturn_t intc_cascade(int irq, void *data) +{ + struct ingenic_intc_data *intc = irq_get_handler_data(irq); + uint32_t irq_reg; + unsigned i; + + for (i = 0; i < intc->num_chips; i++) { + irq_reg = readl(intc->base + (i * CHIP_SIZE) + + JZ_REG_INTC_PENDING); + if (!irq_reg) + continue; + + generic_handle_irq(__fls(irq_reg) + (i * 32) + JZ4740_IRQ_BASE); + } + + return IRQ_HANDLED; +} + +static void intc_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask) +{ + struct irq_chip_regs *regs = &gc->chip_types->regs; + + writel(mask, gc->reg_base + regs->enable); + writel(~mask, gc->reg_base + regs->disable); +} + +void ingenic_intc_irq_suspend(struct irq_data *data) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); + intc_irq_set_mask(gc, gc->wake_active); +} + +void ingenic_intc_irq_resume(struct irq_data *data) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); + intc_irq_set_mask(gc, gc->mask_cache); +} + +static struct irqaction intc_cascade_action = { + .handler = intc_cascade, + .name = "SoC intc cascade interrupt", +}; + +static int __init ingenic_intc_of_init(struct device_node *node, + unsigned num_chips) +{ + struct ingenic_intc_data *intc; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + struct irq_domain *domain; + int parent_irq, err = 0; + unsigned i; + + intc = kzalloc(sizeof(*intc), GFP_KERNEL); + if (!intc) { + err = -ENOMEM; + goto out_err; + } + + parent_irq = irq_of_parse_and_map(node, 0); + if (!parent_irq) { + err = -EINVAL; + goto out_free; + } + + err = irq_set_handler_data(parent_irq, intc); + if (err) + goto out_unmap_irq; + + intc->num_chips = num_chips; + intc->base = of_iomap(node, 0); + if (!intc->base) { + err = -ENODEV; + goto out_unmap_irq; + } + + for (i = 0; i < num_chips; i++) { + /* Mask all irqs */ + writel(0xffffffff, intc->base + (i * CHIP_SIZE) + + JZ_REG_INTC_SET_MASK); + + gc = irq_alloc_generic_chip("INTC", 1, + JZ4740_IRQ_BASE + (i * 32), + intc->base + (i * CHIP_SIZE), + handle_level_irq); + + gc->wake_enabled = IRQ_MSK(32); + + ct = gc->chip_types; + ct->regs.enable = JZ_REG_INTC_CLEAR_MASK; + ct->regs.disable = JZ_REG_INTC_SET_MASK; + ct->chip.irq_unmask = irq_gc_unmask_enable_reg; + ct->chip.irq_mask = irq_gc_mask_disable_reg; + ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; + ct->chip.irq_set_wake = irq_gc_set_wake; + ct->chip.irq_suspend = ingenic_intc_irq_suspend; + ct->chip.irq_resume = ingenic_intc_irq_resume; + + irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, + IRQ_NOPROBE | IRQ_LEVEL); + } + + domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0, + &irq_domain_simple_ops, NULL); + if (!domain) + pr_warn("unable to register IRQ domain\n"); + + setup_irq(parent_irq, &intc_cascade_action); + return 0; + +out_unmap_irq: + irq_dispose_mapping(parent_irq); +out_free: + kfree(intc); +out_err: + return err; +} + +static int __init intc_1chip_of_init(struct device_node *node, + struct device_node *parent) +{ + return ingenic_intc_of_init(node, 1); +} +IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init); + +static int __init intc_2chip_of_init(struct device_node *node, + struct device_node *parent) +{ + return ingenic_intc_of_init(node, 2); +} +IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init); +IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init); +IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init); diff --git a/include/linux/irqchip/ingenic.h b/include/linux/irqchip/ingenic.h new file mode 100644 index 000000000000..0ee319a4029d --- /dev/null +++ b/include/linux/irqchip/ingenic.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010, Lars-Peter Clausen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __LINUX_IRQCHIP_INGENIC_H__ +#define __LINUX_IRQCHIP_INGENIC_H__ + +#include + +extern void ingenic_intc_irq_suspend(struct irq_data *data); +extern void ingenic_intc_irq_resume(struct irq_data *data); + +#endif -- cgit v1.2.3