From e4d06e39530559513c7e335ef7ca4675f8146220 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 16 Feb 2007 12:12:31 +0100 Subject: [ARM] 4198/2: S3C2443: arch/arm/mach-s3c2443 and related support Add arch/arm/mach-s3c2443 for support of the Samsung S3C2443 SoC This patch adds the core CPU support, clock framework, times and initial IRQ support, as well as adding the directory into the build tree. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2443/irq.c | 130 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 arch/arm/mach-s3c2443/irq.c (limited to 'arch/arm/mach-s3c2443/irq.c') diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c new file mode 100644 index 00000000000..f7058823a0e --- /dev/null +++ b/arch/arm/mach-s3c2443/irq.c @@ -0,0 +1,130 @@ +/* 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 +#include + +/* WDT/AC97 */ + +static void s3c_irq_demux_wdtac97(unsigned int irq, + struct irq_desc *desc) +{ + unsigned int subsrc, submsk; + struct irq_desc *mydesc; + + /* 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 >>= 27; + subsrc &= 3; + + if (subsrc != 0) { + if (subsrc & 1) { + mydesc = irq_desc + IRQ_S3C2443_WDT; + desc_handle_irq(IRQ_S3C2443_WDT, mydesc); + } + if (subsrc & 2) { + mydesc = irq_desc + IRQ_S3C2443_AC97; + desc_handle_irq(IRQ_S3C2443_AC97, mydesc); + } + } +} + + +#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0)) + +static void +s3c_irq_wdtac97_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<27); +} + +static void +s3c_irq_wdtac97_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_WDT); +} + +static void +s3c_irq_wdtac97_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<27); +} + +static struct irq_chip s3c_irq_wdtac97 = { + .mask = s3c_irq_wdtac97_mask, + .unmask = s3c_irq_wdtac97_unmask, + .ack = s3c_irq_wdtac97_ack, +}; + +static int s3c2443_irq_add(struct sys_device *sysdev) +{ + unsigned int irqno; + + printk("S3C2443: IRQ Support\n"); + + /* add new chained handler for wdt, ac7 */ + + set_irq_chip(IRQ_WDT, &s3c_irq_level_chip); + set_irq_handler(IRQ_WDT, handle_level_irq); + set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97); + + for (irqno = IRQ_S3C2443_WDT; irqno <= IRQ_S3C2443_AC97; irqno++) { + set_irq_chip(irqno, &s3c_irq_wdtac97); + set_irq_handler(irqno, handle_level_irq); + set_irq_flags(irqno, IRQF_VALID); + } + + return 0; +} + +static struct sysdev_driver s3c2443_irq_driver = { + .add = s3c2443_irq_add, +}; + +static int s3c2443_irq_init(void) +{ + return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_irq_driver); +} + +arch_initcall(s3c2443_irq_init); + -- cgit v1.2.3 From 72262e8b19034d2605d452d91717d56738598707 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 16 Feb 2007 13:02:42 +0100 Subject: [ARM] 4202/2: S3C2443: IRQ sub source handlers Add IRQ handlers for the IRQs which originate from the sub-interrupt register on the S3C2443 Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2443/irq.c | 238 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 199 insertions(+), 39 deletions(-) (limited to 'arch/arm/mach-s3c2443/irq.c') diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c index f7058823a0e..7a45b6dcb73 100644 --- a/arch/arm/mach-s3c2443/irq.c +++ b/arch/arm/mach-s3c2443/irq.c @@ -39,12 +39,12 @@ #include #include -/* WDT/AC97 */ +#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) -static void s3c_irq_demux_wdtac97(unsigned int irq, - struct irq_desc *desc) +static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) { unsigned int subsrc, submsk; + unsigned int end; struct irq_desc *mydesc; /* read the current pending interrupts, and the mask @@ -53,63 +53,199 @@ static void s3c_irq_demux_wdtac97(unsigned int irq, subsrc = __raw_readl(S3C2410_SUBSRCPND); submsk = __raw_readl(S3C2410_INTSUBMSK); - subsrc &= ~submsk; - subsrc >>= 27; - subsrc &= 3; - - if (subsrc != 0) { - if (subsrc & 1) { - mydesc = irq_desc + IRQ_S3C2443_WDT; - desc_handle_irq(IRQ_S3C2443_WDT, mydesc); - } - if (subsrc & 2) { - mydesc = irq_desc + IRQ_S3C2443_AC97; - desc_handle_irq(IRQ_S3C2443_AC97, mydesc); - } + subsrc &= ~submsk; + subsrc >>= (irq - S3C2410_IRQSUB(0)); + subsrc &= (1 << len)-1; + + end = len + irq; + mydesc = irq_desc + irq; + + for (; irq < end && subsrc; irq++) { + if (subsrc & 1) + desc_handle_irq(irq, mydesc); + + mydesc++; + 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_WDT (1UL << (IRQ_WDT - IRQ_EINT0)) +#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) +#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) -static void -s3c_irq_wdtac97_mask(unsigned int irqno) +static void s3c2443_irq_wdtac97_mask(unsigned int irqno) { - s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<27); + s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97); } -static void -s3c_irq_wdtac97_unmask(unsigned int irqno) +static void s3c2443_irq_wdtac97_unmask(unsigned int irqno) { - s3c_irqsub_unmask(irqno, INTMSK_WDT); + s3c_irqsub_unmask(irqno, INTMSK_WDTAC97); } -static void -s3c_irq_wdtac97_ack(unsigned int irqno) +static void s3c2443_irq_wdtac97_ack(unsigned int irqno) { - s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<27); + s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97); } -static struct irq_chip s3c_irq_wdtac97 = { - .mask = s3c_irq_wdtac97_mask, - .unmask = s3c_irq_wdtac97_unmask, - .ack = s3c_irq_wdtac97_ack, +static struct irq_chip s3c2443_irq_wdtac97 = { + .mask = s3c2443_irq_wdtac97_mask, + .unmask = s3c2443_irq_wdtac97_unmask, + .ack = s3c2443_irq_wdtac97_ack, }; -static int s3c2443_irq_add(struct sys_device *sysdev) + +/* LCD sub interrupts */ + +static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) { - unsigned int irqno; + s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4); +} - printk("S3C2443: IRQ Support\n"); +#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) +#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) + +static void s3c2443_irq_lcd_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD); +} + +static void s3c2443_irq_lcd_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_LCD); +} + +static void s3c2443_irq_lcd_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD); +} + +static struct irq_chip s3c2443_irq_lcd = { + .mask = s3c2443_irq_lcd_mask, + .unmask = s3c2443_irq_lcd_unmask, + .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_DMA1, 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(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA); +} + +static void s3c2443_irq_dma_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_DMA); +} + +static void s3c2443_irq_dma_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA); +} + +static struct irq_chip s3c2443_irq_dma = { + .mask = s3c2443_irq_dma_mask, + .unmask = s3c2443_irq_dma_unmask, + .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_UART3, 3); +} - /* add new chained handler for wdt, ac7 */ +#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) +#define SUBMSK_UART3 (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) - set_irq_chip(IRQ_WDT, &s3c_irq_level_chip); - set_irq_handler(IRQ_WDT, handle_level_irq); - set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97); - for (irqno = IRQ_S3C2443_WDT; irqno <= IRQ_S3C2443_AC97; irqno++) { - set_irq_chip(irqno, &s3c_irq_wdtac97); +static void s3c2443_irq_uart3_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3); +} + +static void s3c2443_irq_uart3_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_UART3); +} + +static void s3c2443_irq_uart3_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3); +} + +static struct irq_chip s3c2443_irq_uart3 = { + .mask = s3c2443_irq_uart3_mask, + .unmask = s3c2443_irq_uart3_unmask, + .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(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_CAM, SUBMSK_CAM); +} + +static void s3c2443_irq_cam_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_CAM); +} + +static void s3c2443_irq_cam_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_CAM, SUBMSK_CAM); +} + +static struct irq_chip s3c2443_irq_cam = { + .mask = s3c2443_irq_cam_mask, + .unmask = s3c2443_irq_cam_unmask, + .ack = s3c2443_irq_cam_ack, +}; + +/* IRQ initialisation code */ + +static int __init 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; + + set_irq_chip(base, &s3c_irq_level_chip); + set_irq_handler(base, handle_level_irq); + set_irq_chained_handler(base, demux); + + for (irqno = start; irqno <= end; irqno++) { + set_irq_chip(irqno, chip); set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } @@ -117,6 +253,30 @@ static int s3c2443_irq_add(struct sys_device *sysdev) return 0; } +static int s3c2443_irq_add(struct sys_device *sysdev) +{ + 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 sysdev_driver s3c2443_irq_driver = { .add = s3c2443_irq_add, }; -- cgit v1.2.3