Commit 8b824476 authored by Ben Dooks's avatar Ben Dooks Committed by Russell King

[ARM PATCH] 1991/1: S3C2410 - irq updates

Patch from Ben Dooks

This patch adds the following

- demux of the adc/touchscreen irqs
- fix to allow setting of the external irq type

Updated version of 1975/1

Thanks to Roc Wu, and Arnaud Patard for finding and fixing
parent 3fd91b59
/* linux/arch/arm/mach-s3c2410/irq.c
*
* Copyright (c) 2003 Simtec Electronics
* Copyright (c) 2003,2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
......@@ -17,6 +17,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Changelog:
*
* 22-Jul-2004 Ben Dooks <ben@simtec.co.uk>
* Fixed compile warnings
*
* 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn>
* Fixed s3c_extirq_type
*
* 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
* Addition of ADC/TC demux
*/
......@@ -34,7 +44,7 @@
#include <asm/mach/irq.h>
#include <asm/arch/regs-irq.h>
#include <asm/arch/regs-lcd.h>
#include <asm/arch/regs-gpio.h>
#if 0
#include <asm/debug-ll.h>
......@@ -177,12 +187,77 @@ s3c_irqext_unmask(unsigned int irqno)
s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
}
/* todo - put type handler in here */
static int
s3c_irqext_type(unsigned int irq, unsigned int type)
{
irqdbf("s3c_irqext_type: called for irq %d, type %d\n", irq, type);
unsigned long extint_reg;
unsigned long gpcon_reg;
unsigned long gpcon_offset, extint_offset;
unsigned long newvalue = 0, value;
if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT7))
{
gpcon_reg = S3C2410_GPFCON;
extint_reg = S3C2410_EXTINT0;
gpcon_offset = (irq - IRQ_EINT0) * 2;
extint_offset = (irq - IRQ_EINT0) * 4;
}
else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
{
gpcon_reg = S3C2410_GPGCON;
extint_reg = S3C2410_EXTINT1;
gpcon_offset = (irq - IRQ_EINT8) * 2;
extint_offset = (irq - IRQ_EINT8) * 4;
}
else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
{
gpcon_reg = S3C2410_GPGCON;
extint_reg = S3C2410_EXTINT2;
gpcon_offset = (irq - IRQ_EINT8) * 2;
extint_offset = (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);
__raw_writel(value, gpcon_reg);
/* Set the external interrupt to pointed trigger type */
switch (type)
{
case IRQT_NOEDGE:
printk(KERN_WARNING "No edge setting!\n");
break;
case IRQT_RISING:
newvalue = S3C2410_EXTINT_RISEEDGE;
break;
case IRQT_FALLING:
newvalue = S3C2410_EXTINT_FALLEDGE;
break;
case IRQT_BOTHEDGE:
newvalue = S3C2410_EXTINT_BOTHEDGE;
break;
case IRQT_LOW:
newvalue = S3C2410_EXTINT_LOWLEV;
break;
case IRQT_HIGH:
newvalue = S3C2410_EXTINT_HILEV;
break;
default:
printk(KERN_ERR "No such irq type %d", type);
return -1;
}
value = __raw_readl(extint_reg);
value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
__raw_writel(value, extint_reg);
return 0;
}
......@@ -368,37 +443,37 @@ static struct irqchip s3c_irq_adc = {
.ack = s3c_irq_adc_ack,
};
#if 0
/* LCD (todo) */
static void
s3c_irq_lcd_mask(unsigned int irqno)
/* irq demux for adc */
static void s3c_irq_demux_adc(unsigned int irq,
struct irqdesc *desc,
struct pt_regs *regs)
{
unsigned int subsrc, submsk;
unsigned int offset = 9;
struct irqdesc *mydesc;
}
static void
s3c_irq_lcd_unmask(unsigned int irqno)
{
/* read the current pending interrupts, and the mask
* for what it is available */
}
subsrc = __raw_readl(S3C2410_SUBSRCPND);
submsk = __raw_readl(S3C2410_INTSUBMSK);
static void
s3c_irq_lcd_ack(unsigned int irqno)
{
subsrc &= ~submsk;
subsrc >>= offset;
subsrc &= 3;
if (subsrc != 0) {
if (subsrc & 1) {
mydesc = irq_desc + IRQ_TC;
mydesc->handle( IRQ_TC, mydesc, regs);
}
if (subsrc & 2) {
mydesc = irq_desc + IRQ_ADC;
mydesc->handle(IRQ_ADC, mydesc, regs);
}
}
}
static struct irqchip s3c_irq_lcd = {
.mask = s3c_irq_lcd_mask,
.unmask = s3c_irq_lcd_unmask,
.ack = s3c_irq_lcd_ack,
};
#endif
/* irq demux */
static void s3c_irq_demux_uart(unsigned int start,
struct pt_regs *regs)
{
......@@ -466,7 +541,10 @@ s3c_irq_demux_uart2(unsigned int irq,
s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
}
/* s3c2410_init_irq
*
* Initialise S3C2410 IRQ system
*/
void __init s3c2410_init_irq(void)
{
......@@ -509,7 +587,7 @@ void __init s3c2410_init_irq(void)
irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
for (irqno = IRQ_EINT0; irqno < IRQ_ADCPARENT; irqno++) {
for (irqno = IRQ_EINT0; irqno <= IRQ_ADCPARENT; irqno++) {
/* set all the s3c2410 internal irqs */
switch (irqno) {
......@@ -549,8 +627,7 @@ void __init s3c2410_init_irq(void)
set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
//set_irq_chained_handler(IRQ_LCD, s3c_irq_demux_);
//set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_);
set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
/* external interrupts */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment