From 1f629b7a3ced8e73784a9ae3b0d9039496878f18 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:22 -0800 Subject: ARM: S3C24XX: transform irq handling into a declarative form The irqs available on the machine and even the bit settings in the irq registers differ a lot through all the s3c24xx subarchitectures. This results in each subarch having its own irq init which adds its specific irqs to the base ones created in plat-s3c24xx/irq.c. This of course makes a future move to devicetree hard to implement. Therefore this patch transforms the base irq handling to a declarative style, where the irq types as well as its parent/child relationship gets read from a predefined datastructure, which later on can hopefully be easily represented in devicetree too. It should also be easy to include the subarch specific irqs here in later patches, reducing code size and duplication. It should not affect anything outside of the file, as the original irq numbers and their handling are preserved (hopefully) correctly. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index eef3b6a..3bb5c8f 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -9,6 +9,7 @@ config PLAT_S3C24XX select ARCH_REQUIRE_GPIOLIB select NO_IOPORT select S3C_DEV_NAND + select IRQ_DOMAIN help Base platform code for any Samsung S3C24XX device diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index fe57bbb..cdf1e92 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -1,7 +1,9 @@ -/* linux/arch/arm/plat-s3c24xx/irq.c +/* + * S3C24XX IRQ handling * * Copyright (c) 2003-2004 Simtec Electronics * Ben Dooks + * Copyright (c) 2012 Heiko Stuebner * * 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 @@ -12,175 +14,124 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include +#include +#include #include #include #include #include +#include -#include #include -#include +#include +#include #include +#include #include #include -static void -s3c_irq_mask(struct irq_data *data) -{ - unsigned int irqno = data->irq - IRQ_EINT0; - unsigned long mask; - - mask = __raw_readl(S3C2410_INTMSK); - mask |= 1UL << irqno; - __raw_writel(mask, S3C2410_INTMSK); -} - -static inline void -s3c_irq_ack(struct irq_data *data) -{ - unsigned long bitval = 1UL << (data->irq - IRQ_EINT0); - - __raw_writel(bitval, S3C2410_SRCPND); - __raw_writel(bitval, S3C2410_INTPND); -} - -static inline void -s3c_irq_maskack(struct irq_data *data) -{ - unsigned long bitval = 1UL << (data->irq - IRQ_EINT0); - unsigned long mask; +#define S3C_IRQTYPE_NONE 0 +#define S3C_IRQTYPE_EINT 1 +#define S3C_IRQTYPE_EDGE 2 +#define S3C_IRQTYPE_LEVEL 3 - mask = __raw_readl(S3C2410_INTMSK); - __raw_writel(mask|bitval, S3C2410_INTMSK); +struct s3c_irq_data { + unsigned int type; + unsigned long parent_irq; - __raw_writel(bitval, S3C2410_SRCPND); - __raw_writel(bitval, S3C2410_INTPND); -} - - -static void -s3c_irq_unmask(struct irq_data *data) -{ - unsigned int irqno = data->irq; - unsigned long mask; - - if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23) - irqdbf2("s3c_irq_unmask %d\n", irqno); - - irqno -= IRQ_EINT0; - - mask = __raw_readl(S3C2410_INTMSK); - mask &= ~(1UL << irqno); - __raw_writel(mask, S3C2410_INTMSK); -} - -struct irq_chip s3c_irq_level_chip = { - .name = "s3c-level", - .irq_ack = s3c_irq_maskack, - .irq_mask = s3c_irq_mask, - .irq_unmask = s3c_irq_unmask, - .irq_set_wake = s3c_irq_wake + /* data gets filled during init */ + struct s3c_irq_intc *intc; + unsigned long sub_bits; + struct s3c_irq_intc *sub_intc; }; -struct irq_chip s3c_irq_chip = { - .name = "s3c", - .irq_ack = s3c_irq_ack, - .irq_mask = s3c_irq_mask, - .irq_unmask = s3c_irq_unmask, - .irq_set_wake = s3c_irq_wake +/* + * Sructure holding the controller data + * @reg_pending register holding pending irqs + * @reg_intpnd special register intpnd in main intc + * @reg_mask mask register + * @domain irq_domain of the controller + * @parent parent controller for ext and sub irqs + * @irqs irq-data, always s3c_irq_data[32] + */ +struct s3c_irq_intc { + void __iomem *reg_pending; + void __iomem *reg_intpnd; + void __iomem *reg_mask; + struct irq_domain *domain; + struct s3c_irq_intc *parent; + struct s3c_irq_data *irqs; }; -static void -s3c_irqext_mask(struct irq_data *data) +static void s3c_irq_mask(struct irq_data *data) { - unsigned int irqno = data->irq - EXTINT_OFF; + struct s3c_irq_intc *intc = data->domain->host_data; + struct s3c_irq_intc *parent_intc = intc->parent; + struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq]; + struct s3c_irq_data *parent_data; unsigned long mask; + unsigned int irqno; + + mask = __raw_readl(intc->reg_mask); + mask |= (1UL << data->hwirq); + __raw_writel(mask, intc->reg_mask); + + if (parent_intc && irq_data->parent_irq) { + parent_data = &parent_intc->irqs[irq_data->parent_irq]; - mask = __raw_readl(S3C24XX_EINTMASK); - mask |= ( 1UL << irqno); - __raw_writel(mask, S3C24XX_EINTMASK); + /* check to see if we need to mask the parent IRQ */ + if ((mask & parent_data->sub_bits) == parent_data->sub_bits) { + irqno = irq_find_mapping(parent_intc->domain, + irq_data->parent_irq); + s3c_irq_mask(irq_get_irq_data(irqno)); + } + } } -static void -s3c_irqext_ack(struct irq_data *data) +static void s3c_irq_unmask(struct irq_data *data) { - unsigned long req; - unsigned long bit; + struct s3c_irq_intc *intc = data->domain->host_data; + struct s3c_irq_intc *parent_intc = intc->parent; + struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq]; unsigned long mask; + unsigned int irqno; - bit = 1UL << (data->irq - EXTINT_OFF); - - mask = __raw_readl(S3C24XX_EINTMASK); - - __raw_writel(bit, S3C24XX_EINTPEND); - - req = __raw_readl(S3C24XX_EINTPEND); - req &= ~mask; - - /* not sure if we should be acking the parent irq... */ + mask = __raw_readl(intc->reg_mask); + mask &= ~(1UL << data->hwirq); + __raw_writel(mask, intc->reg_mask); - if (data->irq <= IRQ_EINT7) { - if ((req & 0xf0) == 0) - s3c_irq_ack(irq_get_irq_data(IRQ_EINT4t7)); - } else { - if ((req >> 8) == 0) - s3c_irq_ack(irq_get_irq_data(IRQ_EINT8t23)); + if (parent_intc && irq_data->parent_irq) { + irqno = irq_find_mapping(parent_intc->domain, + irq_data->parent_irq); + s3c_irq_unmask(irq_get_irq_data(irqno)); } } -static void -s3c_irqext_unmask(struct irq_data *data) +static inline void s3c_irq_ack(struct irq_data *data) { - unsigned int irqno = data->irq - EXTINT_OFF; - unsigned long mask; + struct s3c_irq_intc *intc = data->domain->host_data; + unsigned long bitval = 1UL << data->hwirq; - mask = __raw_readl(S3C24XX_EINTMASK); - mask &= ~(1UL << irqno); - __raw_writel(mask, S3C24XX_EINTMASK); + __raw_writel(bitval, intc->reg_pending); + if (intc->reg_intpnd) + __raw_writel(bitval, intc->reg_intpnd); } -int -s3c_irqext_type(struct irq_data *data, unsigned int type) +static int s3c_irqext_type_set(void __iomem *gpcon_reg, + void __iomem *extint_reg, + unsigned long gpcon_offset, + unsigned long extint_offset, + unsigned int type) { - void __iomem *extint_reg; - void __iomem *gpcon_reg; - unsigned long gpcon_offset, extint_offset; unsigned long newvalue = 0, value; - if ((data->irq >= IRQ_EINT0) && (data->irq <= IRQ_EINT3)) { - gpcon_reg = S3C2410_GPFCON; - extint_reg = S3C24XX_EXTINT0; - gpcon_offset = (data->irq - IRQ_EINT0) * 2; - extint_offset = (data->irq - IRQ_EINT0) * 4; - } else if ((data->irq >= IRQ_EINT4) && (data->irq <= IRQ_EINT7)) { - gpcon_reg = S3C2410_GPFCON; - extint_reg = S3C24XX_EXTINT0; - gpcon_offset = (data->irq - (EXTINT_OFF)) * 2; - extint_offset = (data->irq - (EXTINT_OFF)) * 4; - } else if ((data->irq >= IRQ_EINT8) && (data->irq <= IRQ_EINT15)) { - gpcon_reg = S3C2410_GPGCON; - extint_reg = S3C24XX_EXTINT1; - gpcon_offset = (data->irq - IRQ_EINT8) * 2; - extint_offset = (data->irq - IRQ_EINT8) * 4; - } else if ((data->irq >= IRQ_EINT16) && (data->irq <= IRQ_EINT23)) { - gpcon_reg = S3C2410_GPGCON; - extint_reg = S3C24XX_EXTINT2; - gpcon_offset = (data->irq - IRQ_EINT8) * 2; - extint_offset = (data->irq - IRQ_EINT16) * 4; - } else { - return -1; - } - /* Set the GPIO to external interrupt mode */ value = __raw_readl(gpcon_reg); value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset); @@ -190,7 +141,7 @@ s3c_irqext_type(struct irq_data *data, unsigned int type) switch (type) { case IRQ_TYPE_NONE: - printk(KERN_WARNING "No edge setting!\n"); + pr_warn("No edge setting!\n"); break; case IRQ_TYPE_EDGE_RISING: @@ -214,8 +165,8 @@ s3c_irqext_type(struct irq_data *data, unsigned int type) break; default: - printk(KERN_ERR "No such irq type %d", type); - return -1; + pr_err("No such irq type %d", type); + return -EINVAL; } value = __raw_readl(extint_reg); @@ -225,265 +176,113 @@ s3c_irqext_type(struct irq_data *data, unsigned int type) return 0; } -static struct irq_chip s3c_irqext_chip = { - .name = "s3c-ext", - .irq_mask = s3c_irqext_mask, - .irq_unmask = s3c_irqext_unmask, - .irq_ack = s3c_irqext_ack, - .irq_set_type = s3c_irqext_type, - .irq_set_wake = s3c_irqext_wake -}; - -static struct irq_chip s3c_irq_eint0t4 = { - .name = "s3c-ext0", - .irq_ack = s3c_irq_ack, - .irq_mask = s3c_irq_mask, - .irq_unmask = s3c_irq_unmask, - .irq_set_wake = s3c_irq_wake, - .irq_set_type = s3c_irqext_type, -}; - -/* mask values for the parent registers for each of the interrupt types */ - -#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0)) -#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0)) -#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0)) -#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0)) - - -/* UART0 */ - -static void -s3c_irq_uart0_mask(struct irq_data *data) +/* FIXME: make static when it's out of plat-samsung/irq.h */ +int s3c_irqext_type(struct irq_data *data, unsigned int type) { - s3c_irqsub_mask(data->irq, INTMSK_UART0, 7); -} + void __iomem *extint_reg; + void __iomem *gpcon_reg; + unsigned long gpcon_offset, extint_offset; -static void -s3c_irq_uart0_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_UART0); -} + if ((data->hwirq >= 4) && (data->hwirq <= 7)) { + gpcon_reg = S3C2410_GPFCON; + extint_reg = S3C24XX_EXTINT0; + gpcon_offset = (data->hwirq) * 2; + extint_offset = (data->hwirq) * 4; + } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) { + gpcon_reg = S3C2410_GPGCON; + extint_reg = S3C24XX_EXTINT1; + gpcon_offset = (data->hwirq - 8) * 2; + extint_offset = (data->hwirq - 8) * 4; + } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) { + gpcon_reg = S3C2410_GPGCON; + extint_reg = S3C24XX_EXTINT2; + gpcon_offset = (data->hwirq - 8) * 2; + extint_offset = (data->hwirq - 16) * 4; + } else { + return -EINVAL; + } -static void -s3c_irq_uart0_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_UART0, 7); + return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset, + extint_offset, type); } -static struct irq_chip s3c_irq_uart0 = { - .name = "s3c-uart0", - .irq_mask = s3c_irq_uart0_mask, - .irq_unmask = s3c_irq_uart0_unmask, - .irq_ack = s3c_irq_uart0_ack, -}; - -/* UART1 */ - -static void -s3c_irq_uart1_mask(struct irq_data *data) +static int s3c_irqext0_type(struct irq_data *data, unsigned int type) { - s3c_irqsub_mask(data->irq, INTMSK_UART1, 7 << 3); -} + void __iomem *extint_reg; + void __iomem *gpcon_reg; + unsigned long gpcon_offset, extint_offset; -static void -s3c_irq_uart1_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_UART1); -} + if ((data->hwirq >= 0) && (data->hwirq <= 3)) { + gpcon_reg = S3C2410_GPFCON; + extint_reg = S3C24XX_EXTINT0; + gpcon_offset = (data->hwirq) * 2; + extint_offset = (data->hwirq) * 4; + } else { + return -EINVAL; + } -static void -s3c_irq_uart1_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_UART1, 7 << 3); + return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset, + extint_offset, type); } -static struct irq_chip s3c_irq_uart1 = { - .name = "s3c-uart1", - .irq_mask = s3c_irq_uart1_mask, - .irq_unmask = s3c_irq_uart1_unmask, - .irq_ack = s3c_irq_uart1_ack, +struct irq_chip s3c_irq_chip = { + .name = "s3c", + .irq_ack = s3c_irq_ack, + .irq_mask = s3c_irq_mask, + .irq_unmask = s3c_irq_unmask, + .irq_set_wake = s3c_irq_wake }; -/* UART2 */ - -static void -s3c_irq_uart2_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_UART2, 7 << 6); -} - -static void -s3c_irq_uart2_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_UART2); -} - -static void -s3c_irq_uart2_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_UART2, 7 << 6); -} - -static struct irq_chip s3c_irq_uart2 = { - .name = "s3c-uart2", - .irq_mask = s3c_irq_uart2_mask, - .irq_unmask = s3c_irq_uart2_unmask, - .irq_ack = s3c_irq_uart2_ack, +struct irq_chip s3c_irq_level_chip = { + .name = "s3c-level", + .irq_mask = s3c_irq_mask, + .irq_unmask = s3c_irq_unmask, + .irq_ack = s3c_irq_ack, }; -/* ADC and Touchscreen */ - -static void -s3c_irq_adc_mask(struct irq_data *d) -{ - s3c_irqsub_mask(d->irq, INTMSK_ADCPARENT, 3 << 9); -} - -static void -s3c_irq_adc_unmask(struct irq_data *d) -{ - s3c_irqsub_unmask(d->irq, INTMSK_ADCPARENT); -} - -static void -s3c_irq_adc_ack(struct irq_data *d) -{ - s3c_irqsub_ack(d->irq, INTMSK_ADCPARENT, 3 << 9); -} - -static struct irq_chip s3c_irq_adc = { - .name = "s3c-adc", - .irq_mask = s3c_irq_adc_mask, - .irq_unmask = s3c_irq_adc_unmask, - .irq_ack = s3c_irq_adc_ack, +static struct irq_chip s3c_irqext_chip = { + .name = "s3c-ext", + .irq_mask = s3c_irq_mask, + .irq_unmask = s3c_irq_unmask, + .irq_ack = s3c_irq_ack, + .irq_set_type = s3c_irqext_type, + .irq_set_wake = s3c_irqext_wake }; -/* irq demux for adc */ -static void s3c_irq_demux_adc(unsigned int irq, - struct irq_desc *desc) -{ - unsigned int subsrc, submsk; - unsigned int offset = 9; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - subsrc &= ~submsk; - subsrc >>= offset; - subsrc &= 3; - - if (subsrc != 0) { - if (subsrc & 1) { - generic_handle_irq(IRQ_TC); - } - if (subsrc & 2) { - generic_handle_irq(IRQ_ADC); - } - } -} - -static void s3c_irq_demux_uart(unsigned int start) -{ - unsigned int subsrc, submsk; - unsigned int offset = start - IRQ_S3CUART_RX0; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n", - start, offset, subsrc, submsk); - - subsrc &= ~submsk; - subsrc >>= offset; - subsrc &= 7; - - if (subsrc != 0) { - if (subsrc & 1) - generic_handle_irq(start); - - if (subsrc & 2) - generic_handle_irq(start+1); - - if (subsrc & 4) - generic_handle_irq(start+2); - } -} - -/* uart demux entry points */ - -static void -s3c_irq_demux_uart0(unsigned int irq, - struct irq_desc *desc) -{ - irq = irq; - s3c_irq_demux_uart(IRQ_S3CUART_RX0); -} - -static void -s3c_irq_demux_uart1(unsigned int irq, - struct irq_desc *desc) -{ - irq = irq; - s3c_irq_demux_uart(IRQ_S3CUART_RX1); -} - -static void -s3c_irq_demux_uart2(unsigned int irq, - struct irq_desc *desc) -{ - irq = irq; - s3c_irq_demux_uart(IRQ_S3CUART_RX2); -} +static struct irq_chip s3c_irq_eint0t4 = { + .name = "s3c-ext0", + .irq_ack = s3c_irq_ack, + .irq_mask = s3c_irq_mask, + .irq_unmask = s3c_irq_unmask, + .irq_set_wake = s3c_irq_wake, + .irq_set_type = s3c_irqext0_type, +}; -static void -s3c_irq_demux_extint8(unsigned int irq, - struct irq_desc *desc) +static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc) { - unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); - unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); - - eintpnd &= ~eintmsk; - eintpnd &= ~0xff; /* ignore lower irqs */ - - /* we may as well handle all the pending IRQs here */ - - while (eintpnd) { - irq = __ffs(eintpnd); - eintpnd &= ~(1<irq_data.domain->host_data; + struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq]; + struct s3c_irq_intc *sub_intc = irq_data->sub_intc; + unsigned long src; + unsigned long msk; + unsigned int n; + + chained_irq_enter(chip, desc); + + src = __raw_readl(sub_intc->reg_pending); + msk = __raw_readl(sub_intc->reg_mask); + + src &= ~msk; + src &= irq_data->sub_bits; + + while (src) { + n = __ffs(src); + src &= ~(1 << n); + generic_handle_irq(irq_find_mapping(sub_intc->domain, n)); } -} - -static void -s3c_irq_demux_extint4t7(unsigned int irq, - struct irq_desc *desc) -{ - unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); - unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); - - eintpnd &= ~eintmsk; - eintpnd &= 0xff; /* only lower irqs */ - - /* we may as well handle all the pending IRQs here */ - - while (eintpnd) { - irq = __ffs(eintpnd); - eintpnd &= ~(1<host_data; + struct s3c_irq_data *irq_data = &intc->irqs[hw]; + struct s3c_irq_intc *parent_intc; + struct s3c_irq_data *parent_irq_data; + unsigned int irqno; + + if (!intc) { + pr_err("irq-s3c24xx: no controller found for hwirq %lu\n", hw); + return -EINVAL; + } - last = 0; - for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C24XX_EINTPEND); + if (!irq_data) { + pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", hw); + return -EINVAL; + } - if (pend == 0 || pend == last) - break; + /* attach controller pointer to irq_data */ + irq_data->intc = intc; - __raw_writel(pend, S3C24XX_EINTPEND); - printk("irq: clearing pending ext status %08x\n", (int)pend); - last = pend; + /* set handler and flags */ + switch (irq_data->type) { + case S3C_IRQTYPE_NONE: + return 0; + case S3C_IRQTYPE_EINT: + if (irq_data->parent_irq) + irq_set_chip_and_handler(virq, &s3c_irqext_chip, + handle_edge_irq); + else + irq_set_chip_and_handler(virq, &s3c_irq_eint0t4, + handle_edge_irq); + break; + case S3C_IRQTYPE_EDGE: + if (irq_data->parent_irq) + irq_set_chip_and_handler(virq, &s3c_irq_level_chip, + handle_edge_irq); + else + irq_set_chip_and_handler(virq, &s3c_irq_chip, + handle_edge_irq); + break; + case S3C_IRQTYPE_LEVEL: + if (irq_data->parent_irq) + irq_set_chip_and_handler(virq, &s3c_irq_level_chip, + handle_level_irq); + else + irq_set_chip_and_handler(virq, &s3c_irq_chip, + handle_level_irq); + break; + default: + pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type); + return -EINVAL; } + set_irq_flags(virq, IRQF_VALID); + + if (irq_data->parent_irq) { + parent_intc = intc->parent; + if (!parent_intc) { + pr_err("irq-s3c24xx: no parent controller found for hwirq %lu\n", + hw); + goto err; + } - last = 0; - for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C2410_INTPND); + parent_irq_data = &parent_intc->irqs[irq_data->parent_irq]; + if (!irq_data) { + pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", + hw); + goto err; + } - if (pend == 0 || pend == last) - break; + parent_irq_data->sub_intc = intc; + parent_irq_data->sub_bits |= (1UL << hw); - __raw_writel(pend, S3C2410_SRCPND); - __raw_writel(pend, S3C2410_INTPND); - printk("irq: clearing pending status %08x\n", (int)pend); - last = pend; + /* attach the demuxer to the parent irq */ + irqno = irq_find_mapping(parent_intc->domain, + irq_data->parent_irq); + if (!irqno) { + pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n", + irq_data->parent_irq); + goto err; + } + irq_set_chained_handler(irqno, s3c_irq_demux); } - last = 0; - for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C2410_SUBSRCPND); + return 0; - if (pend == 0 || pend == last) - break; +err: + set_irq_flags(virq, 0); - printk("irq: clearing subpending status %08x\n", (int)pend); - __raw_writel(pend, S3C2410_SUBSRCPND); - last = pend; - } + /* the only error can result from bad mapping data*/ + return -EINVAL; +} - /* register the main interrupts */ +static struct irq_domain_ops s3c24xx_irq_ops = { + .map = s3c24xx_irq_map, + .xlate = irq_domain_xlate_twocell, +}; - irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); +static void s3c24xx_clear_intc(struct s3c_irq_intc *intc) +{ + void __iomem *reg_source; + unsigned long pend; + unsigned long last; + int i; - for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) { - /* set all the s3c2410 internal irqs */ + /* if intpnd is set, read the next pending irq from there */ + reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending; - switch (irqno) { - /* deal with the special IRQs (cascaded) */ + last = 0; + for (i = 0; i < 4; i++) { + pend = __raw_readl(reg_source); - case IRQ_EINT4t7: - case IRQ_EINT8t23: - case IRQ_UART0: - case IRQ_UART1: - case IRQ_UART2: - case IRQ_ADCPARENT: - irq_set_chip_and_handler(irqno, &s3c_irq_level_chip, - handle_level_irq); + if (pend == 0 || pend == last) break; - case IRQ_RESERVED6: - case IRQ_RESERVED24: - /* no IRQ here */ - break; + __raw_writel(pend, intc->reg_pending); + if (intc->reg_intpnd) + __raw_writel(pend, intc->reg_intpnd); - default: - //irqdbf("registering irq %d (s3c irq)\n", irqno); - irq_set_chip_and_handler(irqno, &s3c_irq_chip, - handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } + pr_info("irq: clearing pending status %08x\n", (int)pend); + last = pend; } +} - /* setup the cascade irq handlers */ - - irq_set_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7); - irq_set_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8); +struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np, + struct s3c_irq_data *irq_data, + struct s3c_irq_intc *parent, + unsigned long address) +{ + struct s3c_irq_intc *intc; + void __iomem *base = (void *)0xf6000000; /* static mapping */ + int irq_num; + int irq_start; + int irq_offset; + int ret; + + intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL); + if (!intc) + return ERR_PTR(-ENOMEM); + + intc->irqs = irq_data; + + if (parent) + intc->parent = parent; + + /* select the correct data for the controller. + * Need to hard code the irq num start and offset + * to preserve the static mapping for now + */ + switch (address) { + case 0x4a000000: + pr_debug("irq: found main intc\n"); + intc->reg_pending = base; + intc->reg_mask = base + 0x08; + intc->reg_intpnd = base + 0x10; + irq_num = 32; + irq_start = S3C2410_IRQ(0); + irq_offset = 0; + break; + case 0x4a000018: + pr_debug("irq: found subintc\n"); + intc->reg_pending = base + 0x18; + intc->reg_mask = base + 0x1c; + irq_num = 29; + irq_start = S3C2410_IRQSUB(0); + irq_offset = 0; + break; + case 0x4a000040: + pr_debug("irq: found intc2\n"); + intc->reg_pending = base + 0x40; + intc->reg_mask = base + 0x48; + intc->reg_intpnd = base + 0x50; + irq_num = 8; + irq_start = S3C2416_IRQ(0); + irq_offset = 0; + break; + case 0x560000a4: + pr_debug("irq: found eintc\n"); + base = (void *)0xfd000000; + + intc->reg_mask = base + 0xa4; + intc->reg_pending = base + 0x08; + irq_num = 20; + irq_start = S3C2410_IRQ(32); + irq_offset = 4; + break; + default: + pr_err("irq: unsupported controller address\n"); + ret = -EINVAL; + goto err; + } - irq_set_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); - irq_set_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); - irq_set_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); - irq_set_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); + /* now that all the data is complete, init the irq-domain */ + s3c24xx_clear_intc(intc); + intc->domain = irq_domain_add_legacy(np, irq_num, irq_start, + irq_offset, &s3c24xx_irq_ops, + intc); + if (!intc->domain) { + pr_err("irq: could not create irq-domain\n"); + ret = -EINVAL; + goto err; + } - /* external interrupts */ + return intc; - for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { - irqdbf("registering irq %d (ext int)\n", irqno); - irq_set_chip_and_handler(irqno, &s3c_irq_eint0t4, - handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } +err: + kfree(intc); + return ERR_PTR(ret); +} - for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { - irqdbf("registering irq %d (extended s3c irq)\n", irqno); - irq_set_chip_and_handler(irqno, &s3c_irqext_chip, - handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } +/* s3c24xx_init_irq + * + * Initialise S3C2410 IRQ system +*/ - /* register the uart interrupts */ +static struct s3c_irq_data init_base[32] = { + { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ + { .type = S3C_IRQTYPE_NONE, }, /* reserved */ + { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ + { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ + { .type = S3C_IRQTYPE_EDGE, }, /* WDT */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ + { .type = S3C_IRQTYPE_EDGE, }, /* LCD */ + { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */ + { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */ + { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */ + { .type = S3C_IRQTYPE_EDGE, }, /* SDI */ + { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ + { .type = S3C_IRQTYPE_NONE, }, /* reserved */ + { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ + { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ + { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ + { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ + { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ +}; - irqdbf("s3c2410: registering external interrupts\n"); +static struct s3c_irq_data init_eint[32] = { + { .type = S3C_IRQTYPE_NONE, }, /* reserved */ + { .type = S3C_IRQTYPE_NONE, }, /* reserved */ + { .type = S3C_IRQTYPE_NONE, }, /* reserved */ + { .type = S3C_IRQTYPE_NONE, }, /* reserved */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */ + { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */ +}; - for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { - irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); - irq_set_chip_and_handler(irqno, &s3c_irq_uart0, - handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } +static struct s3c_irq_data init_subint[32] = { + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ + { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ + { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ +}; - for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { - irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); - irq_set_chip_and_handler(irqno, &s3c_irq_uart1, - handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } +void __init s3c24xx_init_irq(void) +{ + struct s3c_irq_intc *main_intc; - for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { - irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); - irq_set_chip_and_handler(irqno, &s3c_irq_uart2, - handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } +#ifdef CONFIG_FIQ + init_FIQ(FIQ_START); +#endif - for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { - irqdbf("registering irq %d (s3c adc irq)\n", irqno); - irq_set_chip_and_handler(irqno, &s3c_irq_adc, handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); + main_intc = s3c24xx_init_intc(NULL, &init_base[0], NULL, 0x4a000000); + if (IS_ERR(main_intc)) { + pr_err("irq: could not create main interrupt controller\n"); + return; } - irqdbf("s3c2410: registered interrupt handlers\n"); + s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018); + s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); } struct syscore_ops s3c24xx_irq_syscore_ops = { -- cgit v0.10.2 From d8fdec168542971f6ffbf0883c8be2e9bbb22ca6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:22 -0800 Subject: ARM: S3C24XX: Move irq syscore-ops to irq-pm With this the definition of s3c24xx_irq_syscore_ops can also move to common.h from plat/pm.h and the definitions of s3c24xx_irq_suspend and s3c24xx_irq_resume are also not necessary anymore in plat/pm.h Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index c2f596e..ed6276f 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h @@ -15,4 +15,6 @@ void s3c2410_restart(char mode, const char *cmd); void s3c244x_restart(char mode, const char *cmd); +extern struct syscore_ops s3c24xx_irq_syscore_ops; + #endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */ diff --git a/arch/arm/mach-s3c24xx/irq-pm.c b/arch/arm/mach-s3c24xx/irq-pm.c index 0efb2e2..d48126d 100644 --- a/arch/arm/mach-s3c24xx/irq-pm.c +++ b/arch/arm/mach-s3c24xx/irq-pm.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -64,7 +65,7 @@ static unsigned long save_extint[3]; static unsigned long save_eintflt[4]; static unsigned long save_eintmask; -int s3c24xx_irq_suspend(void) +static int s3c24xx_irq_suspend(void) { unsigned int i; @@ -80,7 +81,7 @@ int s3c24xx_irq_suspend(void) return 0; } -void s3c24xx_irq_resume(void) +static void s3c24xx_irq_resume(void) { unsigned int i; @@ -93,3 +94,8 @@ void s3c24xx_irq_resume(void) s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); __raw_writel(save_eintmask, S3C24XX_EINTMASK); } + +struct syscore_ops s3c24xx_irq_syscore_ops = { + .suspend = s3c24xx_irq_suspend, + .resume = s3c24xx_irq_resume, +}; diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c index a3c5cb0..9ebef95 100644 --- a/arch/arm/mach-s3c24xx/s3c2410.c +++ b/arch/arm/mach-s3c24xx/s3c2410.c @@ -49,6 +49,8 @@ #include #include +#include "common.h" + /* Initial IO mappings */ static struct map_desc s3c2410_iodesc[] __initdata = { @@ -182,8 +184,8 @@ int __init s3c2410_init(void) #ifdef CONFIG_PM register_syscore_ops(&s3c2410_pm_syscore_ops); -#endif register_syscore_ops(&s3c24xx_irq_syscore_ops); +#endif return device_register(&s3c2410_dev); } diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c index c511a22..ec0b318 100644 --- a/arch/arm/mach-s3c24xx/s3c2412.c +++ b/arch/arm/mach-s3c24xx/s3c2412.c @@ -47,6 +47,7 @@ #include #include +#include "common.h" #include "regs-dsc.h" #define S3C2412_SWRST (S3C24XX_VA_CLKPWR + 0x30) @@ -245,8 +246,8 @@ int __init s3c2412_init(void) #ifdef CONFIG_PM register_syscore_ops(&s3c2412_pm_syscore_ops); -#endif register_syscore_ops(&s3c24xx_irq_syscore_ops); +#endif return device_register(&s3c2412_dev); } diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index 77ee0b7..e30476d 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c @@ -63,6 +63,8 @@ #include #include +#include "common.h" + static struct map_desc s3c2416_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), IODESC_ENT(CLKPWR), @@ -105,9 +107,9 @@ int __init s3c2416_init(void) #ifdef CONFIG_PM register_syscore_ops(&s3c2416_pm_syscore_ops); -#endif register_syscore_ops(&s3c24xx_irq_syscore_ops); register_syscore_ops(&s3c2416_irq_syscore_ops); +#endif return device_register(&s3c2416_dev); } diff --git a/arch/arm/mach-s3c24xx/s3c2440.c b/arch/arm/mach-s3c24xx/s3c2440.c index 2b3dddb..559e394 100644 --- a/arch/arm/mach-s3c24xx/s3c2440.c +++ b/arch/arm/mach-s3c24xx/s3c2440.c @@ -40,6 +40,8 @@ #include #include +#include "common.h" + static struct device s3c2440_dev = { .bus = &s3c2440_subsys, }; @@ -57,9 +59,9 @@ int __init s3c2440_init(void) #ifdef CONFIG_PM register_syscore_ops(&s3c2410_pm_syscore_ops); + register_syscore_ops(&s3c24xx_irq_syscore_ops); #endif register_syscore_ops(&s3c244x_pm_syscore_ops); - register_syscore_ops(&s3c24xx_irq_syscore_ops); /* register our system device for everything else */ diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c index 22cb7c9..f732826 100644 --- a/arch/arm/mach-s3c24xx/s3c2442.c +++ b/arch/arm/mach-s3c24xx/s3c2442.c @@ -51,6 +51,8 @@ #include #include +#include "common.h" + /* S3C2442 extended clock support */ static unsigned long s3c2442_camif_upll_round(struct clk *clk, @@ -172,9 +174,9 @@ int __init s3c2442_init(void) #ifdef CONFIG_PM register_syscore_ops(&s3c2410_pm_syscore_ops); + register_syscore_ops(&s3c24xx_irq_syscore_ops); #endif register_syscore_ops(&s3c244x_pm_syscore_ops); - register_syscore_ops(&s3c24xx_irq_syscore_ops); return device_register(&s3c2442_dev); } diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index cdf1e92..259d0e4 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -627,8 +626,3 @@ void __init s3c24xx_init_irq(void) s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018); s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); } - -struct syscore_ops s3c24xx_irq_syscore_ops = { - .suspend = s3c24xx_irq_suspend, - .resume = s3c24xx_irq_resume, -}; diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index 887a0c9..f6fcade 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h @@ -109,17 +109,11 @@ extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count); #ifdef CONFIG_PM extern int s3c_irq_wake(struct irq_data *data, unsigned int state); extern int s3c_irqext_wake(struct irq_data *data, unsigned int state); -extern int s3c24xx_irq_suspend(void); -extern void s3c24xx_irq_resume(void); #else #define s3c_irq_wake NULL #define s3c_irqext_wake NULL -#define s3c24xx_irq_suspend NULL -#define s3c24xx_irq_resume NULL #endif -extern struct syscore_ops s3c24xx_irq_syscore_ops; - /* PM debug functions */ #ifdef CONFIG_SAMSUNG_PM_DEBUG -- cgit v0.10.2 From b4a343e5b333ca02f7731c824b600fe64d8ce28c Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:22 -0800 Subject: ARM: S3C24XX: Modify s3c_irq_wake to use the hwirq property This gets rid of the use of static irq mappings there. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c24xx/irq-pm.c b/arch/arm/mach-s3c24xx/irq-pm.c index d48126d..640ec91 100644 --- a/arch/arm/mach-s3c24xx/irq-pm.c +++ b/arch/arm/mach-s3c24xx/irq-pm.c @@ -30,18 +30,18 @@ * set bit to 1 in allow bitfield to enable the wakeup settings on it */ -unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL; +unsigned long s3c_irqwake_intallow = 1L << 30 | 0xfL; unsigned long s3c_irqwake_eintallow = 0x0000fff0L; int s3c_irq_wake(struct irq_data *data, unsigned int state) { - unsigned long irqbit = 1 << (data->irq - IRQ_EINT0); + unsigned long irqbit = 1 << data->hwirq; if (!(s3c_irqwake_intallow & irqbit)) return -ENOENT; - printk(KERN_INFO "wake %s for irq %d\n", - state ? "enabled" : "disabled", data->irq); + pr_info("wake %s for hwirq %lu\n", + state ? "enabled" : "disabled", data->hwirq); if (!state) s3c_irqwake_intmask |= irqbit; -- cgit v0.10.2 From ef602eb53c84100ab801ffa3a11ea02315fe38a8 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:22 -0800 Subject: ARM: S3C24XX: move s3c2416 irq init to common irq code This is needed to further clean up the irq init. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 08b87cd..68d134f 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o -obj-$(CONFIG_CPU_S3C2416) += s3c2416.o irq-s3c2416.o clock-s3c2416.o +obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock-s3c2416.o obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o obj-$(CONFIG_CPU_S3C2440) += s3c2440.o irq-s3c2440.o clock-s3c2440.o diff --git a/arch/arm/mach-s3c24xx/irq-pm.c b/arch/arm/mach-s3c24xx/irq-pm.c index 640ec91..e119959 100644 --- a/arch/arm/mach-s3c24xx/irq-pm.c +++ b/arch/arm/mach-s3c24xx/irq-pm.c @@ -99,3 +99,26 @@ struct syscore_ops s3c24xx_irq_syscore_ops = { .suspend = s3c24xx_irq_suspend, .resume = s3c24xx_irq_resume, }; + +#ifdef CONFIG_CPU_S3C2416 +static struct sleep_save s3c2416_irq_save[] = { + SAVE_ITEM(S3C2416_INTMSK2), +}; + +static int s3c2416_irq_suspend(void) +{ + s3c_pm_do_save(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save)); + + return 0; +} + +static void s3c2416_irq_resume(void) +{ + s3c_pm_do_restore(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save)); +} + +struct syscore_ops s3c2416_irq_syscore_ops = { + .suspend = s3c2416_irq_suspend, + .resume = s3c2416_irq_resume, +}; +#endif diff --git a/arch/arm/mach-s3c24xx/irq-s3c2416.c b/arch/arm/mach-s3c24xx/irq-s3c2416.c deleted file mode 100644 index ff141b0..0000000 --- a/arch/arm/mach-s3c24xx/irq-s3c2416.c +++ /dev/null @@ -1,348 +0,0 @@ -/* linux/arch/arm/mach-s3c2416/irq.c - * - * Copyright (c) 2009 Yauhen Kharuzhy , - * as part of OpenInkpot project - * Copyright (c) 2009 Promwad Innovation Company - * Yauhen Kharuzhy - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) - -static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len) -{ - unsigned int subsrc, submsk; - unsigned int end; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - subsrc &= ~submsk; - subsrc >>= (irq - S3C2410_IRQSUB(0)); - subsrc &= (1 << len)-1; - - end = len + irq; - - for (; irq < end && subsrc; irq++) { - if (subsrc & 1) - generic_handle_irq(irq); - - subsrc >>= 1; - } -} - -/* WDT/AC97 sub interrupts */ - -static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) -{ - s3c2416_irq_demux(IRQ_S3C2443_WDT, 4); -} - -#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) -#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) - -static void s3c2416_irq_wdtac97_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); -} - -static void s3c2416_irq_wdtac97_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); -} - -static void s3c2416_irq_wdtac97_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); -} - -static struct irq_chip s3c2416_irq_wdtac97 = { - .irq_mask = s3c2416_irq_wdtac97_mask, - .irq_unmask = s3c2416_irq_wdtac97_unmask, - .irq_ack = s3c2416_irq_wdtac97_ack, -}; - -/* LCD sub interrupts */ - -static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) -{ - s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4); -} - -#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) -#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) - -static void s3c2416_irq_lcd_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); -} - -static void s3c2416_irq_lcd_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_LCD); -} - -static void s3c2416_irq_lcd_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); -} - -static struct irq_chip s3c2416_irq_lcd = { - .irq_mask = s3c2416_irq_lcd_mask, - .irq_unmask = s3c2416_irq_lcd_unmask, - .irq_ack = s3c2416_irq_lcd_ack, -}; - -/* DMA sub interrupts */ - -static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc) -{ - s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6); -} - -#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) -#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) - - -static void s3c2416_irq_dma_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); -} - -static void s3c2416_irq_dma_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_DMA); -} - -static void s3c2416_irq_dma_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); -} - -static struct irq_chip s3c2416_irq_dma = { - .irq_mask = s3c2416_irq_dma_mask, - .irq_unmask = s3c2416_irq_dma_unmask, - .irq_ack = s3c2416_irq_dma_ack, -}; - -/* UART3 sub interrupts */ - -static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) -{ - s3c2416_irq_demux(IRQ_S3C2443_RX3, 3); -} - -#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) -#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) - -static void s3c2416_irq_uart3_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); -} - -static void s3c2416_irq_uart3_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_UART3); -} - -static void s3c2416_irq_uart3_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); -} - -static struct irq_chip s3c2416_irq_uart3 = { - .irq_mask = s3c2416_irq_uart3_mask, - .irq_unmask = s3c2416_irq_uart3_unmask, - .irq_ack = s3c2416_irq_uart3_ack, -}; - -/* second interrupt register */ - -static inline void s3c2416_irq_ack_second(struct irq_data *data) -{ - unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); - - __raw_writel(bitval, S3C2416_SRCPND2); - __raw_writel(bitval, S3C2416_INTPND2); -} - -static void s3c2416_irq_mask_second(struct irq_data *data) -{ - unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); - unsigned long mask; - - mask = __raw_readl(S3C2416_INTMSK2); - mask |= bitval; - __raw_writel(mask, S3C2416_INTMSK2); -} - -static void s3c2416_irq_unmask_second(struct irq_data *data) -{ - unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); - unsigned long mask; - - mask = __raw_readl(S3C2416_INTMSK2); - mask &= ~bitval; - __raw_writel(mask, S3C2416_INTMSK2); -} - -struct irq_chip s3c2416_irq_second = { - .irq_ack = s3c2416_irq_ack_second, - .irq_mask = s3c2416_irq_mask_second, - .irq_unmask = s3c2416_irq_unmask_second, -}; - - -/* IRQ initialisation code */ - -static int s3c2416_add_sub(unsigned int base, - void (*demux)(unsigned int, - struct irq_desc *), - struct irq_chip *chip, - unsigned int start, unsigned int end) -{ - unsigned int irqno; - - irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); - irq_set_chained_handler(base, demux); - - for (irqno = start; irqno <= end; irqno++) { - irq_set_chip_and_handler(irqno, chip, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - return 0; -} - -static void s3c2416_irq_add_second(void) -{ - unsigned long pend; - unsigned long last; - int irqno; - int i; - - /* first, clear all interrupts pending... */ - last = 0; - for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C2416_INTPND2); - - if (pend == 0 || pend == last) - break; - - __raw_writel(pend, S3C2416_SRCPND2); - __raw_writel(pend, S3C2416_INTPND2); - printk(KERN_INFO "irq: clearing pending status %08x\n", - (int)pend); - last = pend; - } - - for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) { - switch (irqno) { - case IRQ_S3C2416_RESERVED2: - case IRQ_S3C2416_RESERVED3: - /* no IRQ here */ - break; - default: - irq_set_chip_and_handler(irqno, &s3c2416_irq_second, - handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } - } -} - -static int s3c2416_irq_add(struct device *dev, - struct subsys_interface *sif) -{ - printk(KERN_INFO "S3C2416: IRQ Support\n"); - - s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd, - IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4); - - s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma, - &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); - - s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3, - &s3c2416_irq_uart3, - IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); - - s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97, - &s3c2416_irq_wdtac97, - IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); - - s3c2416_irq_add_second(); - - return 0; -} - -static struct subsys_interface s3c2416_irq_interface = { - .name = "s3c2416_irq", - .subsys = &s3c2416_subsys, - .add_dev = s3c2416_irq_add, -}; - -static int __init s3c2416_irq_init(void) -{ - return subsys_interface_register(&s3c2416_irq_interface); -} - -arch_initcall(s3c2416_irq_init); - -#ifdef CONFIG_PM -static struct sleep_save irq_save[] = { - SAVE_ITEM(S3C2416_INTMSK2), -}; - -int s3c2416_irq_suspend(void) -{ - s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); - - return 0; -} - -void s3c2416_irq_resume(void) -{ - s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); -} - -struct syscore_ops s3c2416_irq_syscore_ops = { - .suspend = s3c2416_irq_suspend, - .resume = s3c2416_irq_resume, -}; -#endif diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 259d0e4..e432144 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -626,3 +626,289 @@ void __init s3c24xx_init_irq(void) s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018); s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); } + +#ifdef CONFIG_CPU_S3C2416 +#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) + +static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len) +{ + unsigned int subsrc, submsk; + unsigned int end; + + /* read the current pending interrupts, and the mask + * for what it is available */ + + subsrc = __raw_readl(S3C2410_SUBSRCPND); + submsk = __raw_readl(S3C2410_INTSUBMSK); + + subsrc &= ~submsk; + subsrc >>= (irq - S3C2410_IRQSUB(0)); + subsrc &= (1 << len)-1; + + end = len + irq; + + for (; irq < end && subsrc; irq++) { + if (subsrc & 1) + generic_handle_irq(irq); + + subsrc >>= 1; + } +} + +/* WDT/AC97 sub interrupts */ + +static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) +{ + s3c2416_irq_demux(IRQ_S3C2443_WDT, 4); +} + +#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) +#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) + +static void s3c2416_irq_wdtac97_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); +} + +static void s3c2416_irq_wdtac97_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); +} + +static void s3c2416_irq_wdtac97_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); +} + +static struct irq_chip s3c2416_irq_wdtac97 = { + .irq_mask = s3c2416_irq_wdtac97_mask, + .irq_unmask = s3c2416_irq_wdtac97_unmask, + .irq_ack = s3c2416_irq_wdtac97_ack, +}; + +/* LCD sub interrupts */ + +static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) +{ + s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4); +} + +#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) +#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) + +static void s3c2416_irq_lcd_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); +} + +static void s3c2416_irq_lcd_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_LCD); +} + +static void s3c2416_irq_lcd_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); +} + +static struct irq_chip s3c2416_irq_lcd = { + .irq_mask = s3c2416_irq_lcd_mask, + .irq_unmask = s3c2416_irq_lcd_unmask, + .irq_ack = s3c2416_irq_lcd_ack, +}; + +/* DMA sub interrupts */ + +static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc) +{ + s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6); +} + +#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) +#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) + + +static void s3c2416_irq_dma_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); +} + +static void s3c2416_irq_dma_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_DMA); +} + +static void s3c2416_irq_dma_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); +} + +static struct irq_chip s3c2416_irq_dma = { + .irq_mask = s3c2416_irq_dma_mask, + .irq_unmask = s3c2416_irq_dma_unmask, + .irq_ack = s3c2416_irq_dma_ack, +}; + +/* UART3 sub interrupts */ + +static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) +{ + s3c2416_irq_demux(IRQ_S3C2443_RX3, 3); +} + +#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) +#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) + +static void s3c2416_irq_uart3_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); +} + +static void s3c2416_irq_uart3_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_UART3); +} + +static void s3c2416_irq_uart3_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); +} + +static struct irq_chip s3c2416_irq_uart3 = { + .irq_mask = s3c2416_irq_uart3_mask, + .irq_unmask = s3c2416_irq_uart3_unmask, + .irq_ack = s3c2416_irq_uart3_ack, +}; + +/* second interrupt register */ + +static inline void s3c2416_irq_ack_second(struct irq_data *data) +{ + unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); + + __raw_writel(bitval, S3C2416_SRCPND2); + __raw_writel(bitval, S3C2416_INTPND2); +} + +static void s3c2416_irq_mask_second(struct irq_data *data) +{ + unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); + unsigned long mask; + + mask = __raw_readl(S3C2416_INTMSK2); + mask |= bitval; + __raw_writel(mask, S3C2416_INTMSK2); +} + +static void s3c2416_irq_unmask_second(struct irq_data *data) +{ + unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); + unsigned long mask; + + mask = __raw_readl(S3C2416_INTMSK2); + mask &= ~bitval; + __raw_writel(mask, S3C2416_INTMSK2); +} + +static struct irq_chip s3c2416_irq_second = { + .irq_ack = s3c2416_irq_ack_second, + .irq_mask = s3c2416_irq_mask_second, + .irq_unmask = s3c2416_irq_unmask_second, +}; + + +/* IRQ initialisation code */ + +static int s3c2416_add_sub(unsigned int base, + void (*demux)(unsigned int, + struct irq_desc *), + struct irq_chip *chip, + unsigned int start, unsigned int end) +{ + unsigned int irqno; + + irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); + irq_set_chained_handler(base, demux); + + for (irqno = start; irqno <= end; irqno++) { + irq_set_chip_and_handler(irqno, chip, handle_level_irq); + set_irq_flags(irqno, IRQF_VALID); + } + + return 0; +} + +static void s3c2416_irq_add_second(void) +{ + unsigned long pend; + unsigned long last; + int irqno; + int i; + + /* first, clear all interrupts pending... */ + last = 0; + for (i = 0; i < 4; i++) { + pend = __raw_readl(S3C2416_INTPND2); + + if (pend == 0 || pend == last) + break; + + __raw_writel(pend, S3C2416_SRCPND2); + __raw_writel(pend, S3C2416_INTPND2); + printk(KERN_INFO "irq: clearing pending status %08x\n", + (int)pend); + last = pend; + } + + for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) { + switch (irqno) { + case IRQ_S3C2416_RESERVED2: + case IRQ_S3C2416_RESERVED3: + /* no IRQ here */ + break; + default: + irq_set_chip_and_handler(irqno, &s3c2416_irq_second, + handle_edge_irq); + set_irq_flags(irqno, IRQF_VALID); + } + } +} + +static int s3c2416_irq_add(struct device *dev, + struct subsys_interface *sif) +{ + printk(KERN_INFO "S3C2416: IRQ Support\n"); + + s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd, + IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4); + + s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma, + &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); + + s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3, + &s3c2416_irq_uart3, + IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); + + s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97, + &s3c2416_irq_wdtac97, + IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); + + s3c2416_irq_add_second(); + + return 0; +} + +static struct subsys_interface s3c2416_irq_interface = { + .name = "s3c2416_irq", + .subsys = &s3c2416_subsys, + .add_dev = s3c2416_irq_add, +}; + +static int __init s3c2416_irq_init(void) +{ + return subsys_interface_register(&s3c2416_irq_interface); +} + +arch_initcall(s3c2416_irq_init); + +#endif -- cgit v0.10.2 From 4a282dd3b616a1e7a7f170973ed2a12332544dc3 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:22 -0800 Subject: ARM: S3C24XX: modify s3c2416 irq init to initialize all irqs Previously the irq init used s3c24xx_init_irq and an additional arch_initcall to add the cpu specific irqs. To be able to simplyfy the irq init later, create a new function s3c416_init_irq, which then calls s3c24xx_init_irq but also adds the cpu specific irqs. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index 7de4120..2abb66f 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -250,7 +250,7 @@ MACHINE_START(SMDK2416, "SMDK2416") /* Maintainer: Yauhen Kharuzhy */ .atag_offset = 0x100, - .init_irq = s3c24xx_init_irq, + .init_irq = s3c2416_init_irq, .map_io = smdk2416_map_io, .init_machine = smdk2416_machine_init, .timer = &s3c24xx_timer, diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index e432144..5b325b2 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -874,10 +874,11 @@ static void s3c2416_irq_add_second(void) } } -static int s3c2416_irq_add(struct device *dev, - struct subsys_interface *sif) +void __init s3c2416_init_irq(void) { - printk(KERN_INFO "S3C2416: IRQ Support\n"); + pr_info("S3C2416: IRQ Support\n"); + + s3c24xx_init_irq(); s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd, IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4); @@ -894,21 +895,6 @@ static int s3c2416_irq_add(struct device *dev, IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); s3c2416_irq_add_second(); - - return 0; } -static struct subsys_interface s3c2416_irq_interface = { - .name = "s3c2416_irq", - .subsys = &s3c2416_subsys, - .add_dev = s3c2416_irq_add, -}; - -static int __init s3c2416_irq_init(void) -{ - return subsys_interface_register(&s3c2416_irq_interface); -} - -arch_initcall(s3c2416_irq_init); - #endif diff --git a/arch/arm/plat-samsung/include/plat/s3c2416.h b/arch/arm/plat-samsung/include/plat/s3c2416.h index 7178e33..f27399a 100644 --- a/arch/arm/plat-samsung/include/plat/s3c2416.h +++ b/arch/arm/plat-samsung/include/plat/s3c2416.h @@ -25,6 +25,7 @@ extern int s3c2416_baseclk_add(void); extern void s3c2416_restart(char mode, const char *cmd); +extern void s3c2416_init_irq(void); extern struct syscore_ops s3c2416_irq_syscore_ops; #else -- cgit v0.10.2 From 20f6c781c7d801e142fccbc04ec9c6dc639f5943 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:22 -0800 Subject: ARM: S3C24XX: transform s3c2416 irqs into new structure Share the common irq code by simply defining a correct mapping declaration for the s3c2416. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 5b325b2..21b2c9d 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -352,7 +352,8 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq, handle_edge_irq); break; case S3C_IRQTYPE_EDGE: - if (irq_data->parent_irq) + if (irq_data->parent_irq || + intc->reg_pending == S3C2416_SRCPND2) irq_set_chip_and_handler(virq, &s3c_irq_level_chip, handle_edge_irq); else @@ -628,273 +629,104 @@ void __init s3c24xx_init_irq(void) } #ifdef CONFIG_CPU_S3C2416 -#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) - -static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len) -{ - unsigned int subsrc, submsk; - unsigned int end; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - subsrc &= ~submsk; - subsrc >>= (irq - S3C2410_IRQSUB(0)); - subsrc &= (1 << len)-1; - - end = len + irq; - - for (; irq < end && subsrc; irq++) { - if (subsrc & 1) - generic_handle_irq(irq); - - subsrc >>= 1; - } -} - -/* WDT/AC97 sub interrupts */ - -static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) -{ - s3c2416_irq_demux(IRQ_S3C2443_WDT, 4); -} - -#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) -#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) - -static void s3c2416_irq_wdtac97_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); -} - -static void s3c2416_irq_wdtac97_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); -} - -static void s3c2416_irq_wdtac97_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); -} - -static struct irq_chip s3c2416_irq_wdtac97 = { - .irq_mask = s3c2416_irq_wdtac97_mask, - .irq_unmask = s3c2416_irq_wdtac97_unmask, - .irq_ack = s3c2416_irq_wdtac97_ack, -}; - -/* LCD sub interrupts */ - -static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) -{ - s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4); -} - -#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) -#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) - -static void s3c2416_irq_lcd_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); -} - -static void s3c2416_irq_lcd_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_LCD); -} - -static void s3c2416_irq_lcd_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); -} - -static struct irq_chip s3c2416_irq_lcd = { - .irq_mask = s3c2416_irq_lcd_mask, - .irq_unmask = s3c2416_irq_lcd_unmask, - .irq_ack = s3c2416_irq_lcd_ack, -}; - -/* DMA sub interrupts */ - -static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc) -{ - s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6); -} - -#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) -#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) - - -static void s3c2416_irq_dma_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); -} - -static void s3c2416_irq_dma_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_DMA); -} - -static void s3c2416_irq_dma_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); -} - -static struct irq_chip s3c2416_irq_dma = { - .irq_mask = s3c2416_irq_dma_mask, - .irq_unmask = s3c2416_irq_dma_unmask, - .irq_ack = s3c2416_irq_dma_ack, +static struct s3c_irq_data init_s3c2416base[32] = { + { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ + { .type = S3C_IRQTYPE_NONE, }, /* reserved */ + { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ + { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ + { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ + { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ + { .type = S3C_IRQTYPE_NONE, }, /* reserved */ + { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ + { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ + { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ + { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ + { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ + { .type = S3C_IRQTYPE_NONE, }, + { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ + { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ }; -/* UART3 sub interrupts */ - -static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) -{ - s3c2416_irq_demux(IRQ_S3C2443_RX3, 3); -} - -#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) -#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) - -static void s3c2416_irq_uart3_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); -} - -static void s3c2416_irq_uart3_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_UART3); -} - -static void s3c2416_irq_uart3_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); -} - -static struct irq_chip s3c2416_irq_uart3 = { - .irq_mask = s3c2416_irq_uart3_mask, - .irq_unmask = s3c2416_irq_uart3_unmask, - .irq_ack = s3c2416_irq_uart3_ack, +static struct s3c_irq_data init_s3c2416subint[32] = { + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ + { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ + { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ + { .type = S3C_IRQTYPE_NONE }, /* reserved */ + { .type = S3C_IRQTYPE_NONE }, /* reserved */ + { .type = S3C_IRQTYPE_NONE }, /* reserved */ + { .type = S3C_IRQTYPE_NONE }, /* reserved */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ }; -/* second interrupt register */ - -static inline void s3c2416_irq_ack_second(struct irq_data *data) -{ - unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); - - __raw_writel(bitval, S3C2416_SRCPND2); - __raw_writel(bitval, S3C2416_INTPND2); -} - -static void s3c2416_irq_mask_second(struct irq_data *data) -{ - unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); - unsigned long mask; - - mask = __raw_readl(S3C2416_INTMSK2); - mask |= bitval; - __raw_writel(mask, S3C2416_INTMSK2); -} - -static void s3c2416_irq_unmask_second(struct irq_data *data) -{ - unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); - unsigned long mask; - - mask = __raw_readl(S3C2416_INTMSK2); - mask &= ~bitval; - __raw_writel(mask, S3C2416_INTMSK2); -} - -static struct irq_chip s3c2416_irq_second = { - .irq_ack = s3c2416_irq_ack_second, - .irq_mask = s3c2416_irq_mask_second, - .irq_unmask = s3c2416_irq_unmask_second, +static struct s3c_irq_data init_s3c2416_second[32] = { + { .type = S3C_IRQTYPE_EDGE }, /* 2D */ + { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */ + { .type = S3C_IRQTYPE_NONE }, /* reserved */ + { .type = S3C_IRQTYPE_NONE }, /* reserved */ + { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */ + { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */ + { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */ + { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */ }; - -/* IRQ initialisation code */ - -static int s3c2416_add_sub(unsigned int base, - void (*demux)(unsigned int, - struct irq_desc *), - struct irq_chip *chip, - unsigned int start, unsigned int end) -{ - unsigned int irqno; - - irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); - irq_set_chained_handler(base, demux); - - for (irqno = start; irqno <= end; irqno++) { - irq_set_chip_and_handler(irqno, chip, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - return 0; -} - -static void s3c2416_irq_add_second(void) -{ - unsigned long pend; - unsigned long last; - int irqno; - int i; - - /* first, clear all interrupts pending... */ - last = 0; - for (i = 0; i < 4; i++) { - pend = __raw_readl(S3C2416_INTPND2); - - if (pend == 0 || pend == last) - break; - - __raw_writel(pend, S3C2416_SRCPND2); - __raw_writel(pend, S3C2416_INTPND2); - printk(KERN_INFO "irq: clearing pending status %08x\n", - (int)pend); - last = pend; - } - - for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) { - switch (irqno) { - case IRQ_S3C2416_RESERVED2: - case IRQ_S3C2416_RESERVED3: - /* no IRQ here */ - break; - default: - irq_set_chip_and_handler(irqno, &s3c2416_irq_second, - handle_edge_irq); - set_irq_flags(irqno, IRQF_VALID); - } - } -} - void __init s3c2416_init_irq(void) { - pr_info("S3C2416: IRQ Support\n"); - - s3c24xx_init_irq(); + struct s3c_irq_intc *main_intc; - s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd, - IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4); + pr_info("S3C2416: IRQ Support\n"); - s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma, - &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); +#ifdef CONFIG_FIQ + init_FIQ(FIQ_START); +#endif - s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3, - &s3c2416_irq_uart3, - IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); + main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000); + if (IS_ERR(main_intc)) { + pr_err("irq: could not create main interrupt controller\n"); + return; + } - s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97, - &s3c2416_irq_wdtac97, - IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); + s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); + s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018); - s3c2416_irq_add_second(); + s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040); } #endif -- cgit v0.10.2 From 6b6289171bfdee905608f5d6cbb3eb79b04fdd03 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:22 -0800 Subject: ARM: S3C24XX: move s3c2443 irq code to irq.c Prequisite for further optimizations. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 68d134f..1d67582 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile @@ -39,7 +39,7 @@ obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o -obj-$(CONFIG_CPU_S3C2443) += s3c2443.o irq-s3c2443.o clock-s3c2443.o +obj-$(CONFIG_CPU_S3C2443) += s3c2443.o clock-s3c2443.o # PM diff --git a/arch/arm/mach-s3c24xx/irq-s3c2443.c b/arch/arm/mach-s3c24xx/irq-s3c2443.c deleted file mode 100644 index 5e69109..0000000 --- a/arch/arm/mach-s3c24xx/irq-s3c2443.c +++ /dev/null @@ -1,281 +0,0 @@ -/* linux/arch/arm/mach-s3c2443/irq.c - * - * Copyright (c) 2007 Simtec Electronics - * Ben Dooks - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) - -static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) -{ - unsigned int subsrc, submsk; - unsigned int end; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - subsrc &= ~submsk; - subsrc >>= (irq - S3C2410_IRQSUB(0)); - subsrc &= (1 << len)-1; - - end = len + irq; - - for (; irq < end && subsrc; irq++) { - if (subsrc & 1) - generic_handle_irq(irq); - - subsrc >>= 1; - } -} - -/* WDT/AC97 sub interrupts */ - -static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2443_WDT, 4); -} - -#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) -#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) - -static void s3c2443_irq_wdtac97_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); -} - -static void s3c2443_irq_wdtac97_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); -} - -static void s3c2443_irq_wdtac97_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); -} - -static struct irq_chip s3c2443_irq_wdtac97 = { - .irq_mask = s3c2443_irq_wdtac97_mask, - .irq_unmask = s3c2443_irq_wdtac97_unmask, - .irq_ack = s3c2443_irq_wdtac97_ack, -}; - -/* LCD sub interrupts */ - -static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4); -} - -#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) -#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) - -static void s3c2443_irq_lcd_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); -} - -static void s3c2443_irq_lcd_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_LCD); -} - -static void s3c2443_irq_lcd_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); -} - -static struct irq_chip s3c2443_irq_lcd = { - .irq_mask = s3c2443_irq_lcd_mask, - .irq_unmask = s3c2443_irq_lcd_unmask, - .irq_ack = s3c2443_irq_lcd_ack, -}; - -/* DMA sub interrupts */ - -static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2443_DMA0, 6); -} - -#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) -#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) - -static void s3c2443_irq_dma_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); -} - -static void s3c2443_irq_dma_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_DMA); -} - -static void s3c2443_irq_dma_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); -} - -static struct irq_chip s3c2443_irq_dma = { - .irq_mask = s3c2443_irq_dma_mask, - .irq_unmask = s3c2443_irq_dma_unmask, - .irq_ack = s3c2443_irq_dma_ack, -}; - -/* UART3 sub interrupts */ - -static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2443_RX3, 3); -} - -#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) -#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) - -static void s3c2443_irq_uart3_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); -} - -static void s3c2443_irq_uart3_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_UART3); -} - -static void s3c2443_irq_uart3_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); -} - -static struct irq_chip s3c2443_irq_uart3 = { - .irq_mask = s3c2443_irq_uart3_mask, - .irq_unmask = s3c2443_irq_uart3_unmask, - .irq_ack = s3c2443_irq_uart3_ack, -}; - -/* CAM sub interrupts */ - -static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4); -} - -#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) -#define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P) - -static void s3c2443_irq_cam_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_CAM, SUBMSK_CAM); -} - -static void s3c2443_irq_cam_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_CAM); -} - -static void s3c2443_irq_cam_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_CAM, SUBMSK_CAM); -} - -static struct irq_chip s3c2443_irq_cam = { - .irq_mask = s3c2443_irq_cam_mask, - .irq_unmask = s3c2443_irq_cam_unmask, - .irq_ack = s3c2443_irq_cam_ack, -}; - -/* IRQ initialisation code */ - -static int s3c2443_add_sub(unsigned int base, - void (*demux)(unsigned int, - struct irq_desc *), - struct irq_chip *chip, - unsigned int start, unsigned int end) -{ - unsigned int irqno; - - irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); - irq_set_chained_handler(base, demux); - - for (irqno = start; irqno <= end; irqno++) { - irq_set_chip_and_handler(irqno, chip, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - return 0; -} - -static int s3c2443_irq_add(struct device *dev, - struct subsys_interface *sif) -{ - printk("S3C2443: IRQ Support\n"); - - s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam, - IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P); - - s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd, - IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4); - - s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma, - &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); - - s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3, - &s3c2443_irq_uart3, - IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); - - s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97, - &s3c2443_irq_wdtac97, - IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); - - return 0; -} - -static struct subsys_interface s3c2443_irq_interface = { - .name = "s3c2443_irq", - .subsys = &s3c2443_subsys, - .add_dev = s3c2443_irq_add, -}; - -static int __init s3c2443_irq_init(void) -{ - return subsys_interface_register(&s3c2443_irq_interface); -} - -arch_initcall(s3c2443_irq_init); - diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 21b2c9d..6f24e23 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -730,3 +730,246 @@ void __init s3c2416_init_irq(void) } #endif + +#ifdef CONFIG_CPU_S3C2443 +#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) + +static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) +{ + unsigned int subsrc, submsk; + unsigned int end; + + /* read the current pending interrupts, and the mask + * for what it is available */ + + subsrc = __raw_readl(S3C2410_SUBSRCPND); + submsk = __raw_readl(S3C2410_INTSUBMSK); + + subsrc &= ~submsk; + subsrc >>= (irq - S3C2410_IRQSUB(0)); + subsrc &= (1 << len)-1; + + end = len + irq; + + for (; irq < end && subsrc; irq++) { + if (subsrc & 1) + generic_handle_irq(irq); + + subsrc >>= 1; + } +} + +/* WDT/AC97 sub interrupts */ + +static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) +{ + s3c2443_irq_demux(IRQ_S3C2443_WDT, 4); +} + +#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) +#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) + +static void s3c2443_irq_wdtac97_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); +} + +static void s3c2443_irq_wdtac97_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); +} + +static void s3c2443_irq_wdtac97_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); +} + +static struct irq_chip s3c2443_irq_wdtac97 = { + .irq_mask = s3c2443_irq_wdtac97_mask, + .irq_unmask = s3c2443_irq_wdtac97_unmask, + .irq_ack = s3c2443_irq_wdtac97_ack, +}; + +/* LCD sub interrupts */ + +static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) +{ + s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4); +} + +#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) +#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) + +static void s3c2443_irq_lcd_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); +} + +static void s3c2443_irq_lcd_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_LCD); +} + +static void s3c2443_irq_lcd_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); +} + +static struct irq_chip s3c2443_irq_lcd = { + .irq_mask = s3c2443_irq_lcd_mask, + .irq_unmask = s3c2443_irq_lcd_unmask, + .irq_ack = s3c2443_irq_lcd_ack, +}; + +/* DMA sub interrupts */ + +static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc) +{ + s3c2443_irq_demux(IRQ_S3C2443_DMA0, 6); +} + +#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) +#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) + +static void s3c2443_irq_dma_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); +} + +static void s3c2443_irq_dma_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_DMA); +} + +static void s3c2443_irq_dma_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); +} + +static struct irq_chip s3c2443_irq_dma = { + .irq_mask = s3c2443_irq_dma_mask, + .irq_unmask = s3c2443_irq_dma_unmask, + .irq_ack = s3c2443_irq_dma_ack, +}; + +/* UART3 sub interrupts */ + +static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) +{ + s3c2443_irq_demux(IRQ_S3C2443_RX3, 3); +} + +#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) +#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) + +static void s3c2443_irq_uart3_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); +} + +static void s3c2443_irq_uart3_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_UART3); +} + +static void s3c2443_irq_uart3_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); +} + +static struct irq_chip s3c2443_irq_uart3 = { + .irq_mask = s3c2443_irq_uart3_mask, + .irq_unmask = s3c2443_irq_uart3_unmask, + .irq_ack = s3c2443_irq_uart3_ack, +}; + +/* CAM sub interrupts */ + +static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc) +{ + s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4); +} + +#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) +#define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P) + +static void s3c2443_irq_cam_mask(struct irq_data *data) +{ + s3c_irqsub_mask(data->irq, INTMSK_CAM, SUBMSK_CAM); +} + +static void s3c2443_irq_cam_unmask(struct irq_data *data) +{ + s3c_irqsub_unmask(data->irq, INTMSK_CAM); +} + +static void s3c2443_irq_cam_ack(struct irq_data *data) +{ + s3c_irqsub_maskack(data->irq, INTMSK_CAM, SUBMSK_CAM); +} + +static struct irq_chip s3c2443_irq_cam = { + .irq_mask = s3c2443_irq_cam_mask, + .irq_unmask = s3c2443_irq_cam_unmask, + .irq_ack = s3c2443_irq_cam_ack, +}; + +/* IRQ initialisation code */ + +static int s3c2443_add_sub(unsigned int base, + void (*demux)(unsigned int, + struct irq_desc *), + struct irq_chip *chip, + unsigned int start, unsigned int end) +{ + unsigned int irqno; + + irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); + irq_set_chained_handler(base, demux); + + for (irqno = start; irqno <= end; irqno++) { + irq_set_chip_and_handler(irqno, chip, handle_level_irq); + set_irq_flags(irqno, IRQF_VALID); + } + + return 0; +} + +static int s3c2443_irq_add(struct device *dev, + struct subsys_interface *sif) +{ + printk("S3C2443: IRQ Support\n"); + + s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam, + IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P); + + s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd, + IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4); + + s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma, + &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); + + s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3, + &s3c2443_irq_uart3, + IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); + + s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97, + &s3c2443_irq_wdtac97, + IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); + + return 0; +} + +static struct subsys_interface s3c2443_irq_interface = { + .name = "s3c2443_irq", + .subsys = &s3c2443_subsys, + .add_dev = s3c2443_irq_add, +}; + +static int __init s3c2443_irq_init(void) +{ + return subsys_interface_register(&s3c2443_irq_interface); +} + +arch_initcall(s3c2443_irq_init); +#endif -- cgit v0.10.2 From b499b7a87117c6ec45f5d4f73ac6a643b1709292 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:23 -0800 Subject: ARM: S3C24XX: modify s3c2443 irq init to initialize all irqs Previously the irq init used s3c24xx_init_irq and an additional arch_initcall to add the cpu specific irqs. To be able to simplyfy the irq init later, create a new function s3c2443_init_irq, which then calls s3c24xx_init_irq but also adds the cpu specific irqs. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c index c6d1a03..8b65a54 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2443.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c @@ -140,7 +140,7 @@ MACHINE_START(SMDK2443, "SMDK2443") /* Maintainer: Ben Dooks */ .atag_offset = 0x100, - .init_irq = s3c24xx_init_irq, + .init_irq = s3c2443_init_irq, .map_io = smdk2443_map_io, .init_machine = smdk2443_machine_init, .timer = &s3c24xx_timer, diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 6f24e23..f9ce39c 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -935,10 +935,11 @@ static int s3c2443_add_sub(unsigned int base, return 0; } -static int s3c2443_irq_add(struct device *dev, - struct subsys_interface *sif) +void __init s3c2443_init_irq(void) { - printk("S3C2443: IRQ Support\n"); + pr_info("S3C2443: IRQ Support\n"); + + s3c24xx_init_irq(); s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam, IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P); @@ -956,20 +957,5 @@ static int s3c2443_irq_add(struct device *dev, s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97, &s3c2443_irq_wdtac97, IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); - - return 0; } - -static struct subsys_interface s3c2443_irq_interface = { - .name = "s3c2443_irq", - .subsys = &s3c2443_subsys, - .add_dev = s3c2443_irq_add, -}; - -static int __init s3c2443_irq_init(void) -{ - return subsys_interface_register(&s3c2443_irq_interface); -} - -arch_initcall(s3c2443_irq_init); #endif diff --git a/arch/arm/plat-samsung/include/plat/s3c2443.h b/arch/arm/plat-samsung/include/plat/s3c2443.h index a5b794f..71b88ec 100644 --- a/arch/arm/plat-samsung/include/plat/s3c2443.h +++ b/arch/arm/plat-samsung/include/plat/s3c2443.h @@ -25,6 +25,8 @@ extern void s3c2443_init_clocks(int xtal); extern int s3c2443_baseclk_add(void); extern void s3c2443_restart(char mode, const char *cmd); + +extern void s3c2443_init_irq(void); #else #define s3c2443_init_clocks NULL #define s3c2443_init_uarts NULL -- cgit v0.10.2 From f44ddba3635e35317057e976888d4a12dcb0f842 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 29 Jan 2013 10:25:23 -0800 Subject: ARM: S3C24XX: transform s3c2443 subirqs into new structure Share the common irq code by simply defining a correct mapping declaration for the s3c2443. Signed-off-by: Heiko Stuebner Signed-off-by: Kukjin Kim diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index f9ce39c..cb9f5e0 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -732,230 +732,91 @@ void __init s3c2416_init_irq(void) #endif #ifdef CONFIG_CPU_S3C2443 -#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) - -static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) -{ - unsigned int subsrc, submsk; - unsigned int end; - - /* read the current pending interrupts, and the mask - * for what it is available */ - - subsrc = __raw_readl(S3C2410_SUBSRCPND); - submsk = __raw_readl(S3C2410_INTSUBMSK); - - subsrc &= ~submsk; - subsrc >>= (irq - S3C2410_IRQSUB(0)); - subsrc &= (1 << len)-1; - - end = len + irq; - - for (; irq < end && subsrc; irq++) { - if (subsrc & 1) - generic_handle_irq(irq); - - subsrc >>= 1; - } -} - -/* WDT/AC97 sub interrupts */ - -static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2443_WDT, 4); -} - -#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) -#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) - -static void s3c2443_irq_wdtac97_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); -} - -static void s3c2443_irq_wdtac97_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); -} - -static void s3c2443_irq_wdtac97_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); -} - -static struct irq_chip s3c2443_irq_wdtac97 = { - .irq_mask = s3c2443_irq_wdtac97_mask, - .irq_unmask = s3c2443_irq_wdtac97_unmask, - .irq_ack = s3c2443_irq_wdtac97_ack, -}; - -/* LCD sub interrupts */ - -static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4); -} - -#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) -#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) - -static void s3c2443_irq_lcd_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); -} - -static void s3c2443_irq_lcd_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_LCD); -} - -static void s3c2443_irq_lcd_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); -} - -static struct irq_chip s3c2443_irq_lcd = { - .irq_mask = s3c2443_irq_lcd_mask, - .irq_unmask = s3c2443_irq_lcd_unmask, - .irq_ack = s3c2443_irq_lcd_ack, -}; - -/* DMA sub interrupts */ - -static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2443_DMA0, 6); -} - -#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) -#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) - -static void s3c2443_irq_dma_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); -} - -static void s3c2443_irq_dma_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_DMA); -} - -static void s3c2443_irq_dma_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); -} - -static struct irq_chip s3c2443_irq_dma = { - .irq_mask = s3c2443_irq_dma_mask, - .irq_unmask = s3c2443_irq_dma_unmask, - .irq_ack = s3c2443_irq_dma_ack, -}; - -/* UART3 sub interrupts */ - -static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2443_RX3, 3); -} - -#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) -#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) - -static void s3c2443_irq_uart3_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); -} - -static void s3c2443_irq_uart3_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_UART3); -} - -static void s3c2443_irq_uart3_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); -} - -static struct irq_chip s3c2443_irq_uart3 = { - .irq_mask = s3c2443_irq_uart3_mask, - .irq_unmask = s3c2443_irq_uart3_unmask, - .irq_ack = s3c2443_irq_uart3_ack, +static struct s3c_irq_data init_s3c2443base[32] = { + { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ + { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */ + { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ + { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ + { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ + { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ + { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ + { .type = S3C_IRQTYPE_EDGE, }, /* CFON */ + { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ + { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ + { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ + { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ + { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ + { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ + { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ + { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ + { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ }; -/* CAM sub interrupts */ -static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc) -{ - s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4); -} - -#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) -#define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P) - -static void s3c2443_irq_cam_mask(struct irq_data *data) -{ - s3c_irqsub_mask(data->irq, INTMSK_CAM, SUBMSK_CAM); -} - -static void s3c2443_irq_cam_unmask(struct irq_data *data) -{ - s3c_irqsub_unmask(data->irq, INTMSK_CAM); -} - -static void s3c2443_irq_cam_ack(struct irq_data *data) -{ - s3c_irqsub_maskack(data->irq, INTMSK_CAM, SUBMSK_CAM); -} - -static struct irq_chip s3c2443_irq_cam = { - .irq_mask = s3c2443_irq_cam_mask, - .irq_unmask = s3c2443_irq_cam_unmask, - .irq_ack = s3c2443_irq_cam_ack, +static struct s3c_irq_data init_s3c2443subint[32] = { + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ + { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ + { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */ + { .type = S3C_IRQTYPE_NONE }, /* reserved */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ + { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ }; -/* IRQ initialisation code */ - -static int s3c2443_add_sub(unsigned int base, - void (*demux)(unsigned int, - struct irq_desc *), - struct irq_chip *chip, - unsigned int start, unsigned int end) -{ - unsigned int irqno; - - irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); - irq_set_chained_handler(base, demux); - - for (irqno = start; irqno <= end; irqno++) { - irq_set_chip_and_handler(irqno, chip, handle_level_irq); - set_irq_flags(irqno, IRQF_VALID); - } - - return 0; -} - void __init s3c2443_init_irq(void) { - pr_info("S3C2443: IRQ Support\n"); - - s3c24xx_init_irq(); - - s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam, - IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P); + struct s3c_irq_intc *main_intc; - s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd, - IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4); + pr_info("S3C2443: IRQ Support\n"); - s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma, - &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); +#ifdef CONFIG_FIQ + init_FIQ(FIQ_START); +#endif - s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3, - &s3c2443_irq_uart3, - IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); + main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000); + if (IS_ERR(main_intc)) { + pr_err("irq: could not create main interrupt controller\n"); + return; + } - s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97, - &s3c2443_irq_wdtac97, - IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); + s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); + s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018); } #endif -- cgit v0.10.2