Skip to content

Commit

Permalink
ARM: S3C24XX: add support for second irq set of S3C2416
Browse files Browse the repository at this point in the history
The S3C2416 has a separate second interrupt register-set to support
additional irqs. This patch adds the necessary constants and registers
the irq handlers for it.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
  • Loading branch information
Heiko Stuebner authored and Kukjin Kim committed May 19, 2012
1 parent 2de05a5 commit 0e944e2
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 1 deletion.
15 changes: 14 additions & 1 deletion arch/arm/mach-s3c24xx/include/mach/irqs.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@
#define IRQ_S32416_WDT S3C2410_IRQSUB(27)
#define IRQ_S32416_AC97 S3C2410_IRQSUB(28)

/* second interrupt-register of s3c2416/s3c2450 */

#define S3C2416_IRQ(x) S3C2410_IRQ((x) + 54 + 29)
#define IRQ_S3C2416_2D S3C2416_IRQ(0)
#define IRQ_S3C2416_IIC1 S3C2416_IRQ(1)
#define IRQ_S3C2416_RESERVED2 S3C2416_IRQ(2)
#define IRQ_S3C2416_RESERVED3 S3C2416_IRQ(3)
#define IRQ_S3C2416_PCM0 S3C2416_IRQ(4)
#define IRQ_S3C2416_PCM1 S3C2416_IRQ(5)
#define IRQ_S3C2416_I2S0 S3C2416_IRQ(6)
#define IRQ_S3C2416_I2S1 S3C2416_IRQ(7)

/* extra irqs for s3c2440 */

Expand Down Expand Up @@ -175,7 +186,9 @@
#define IRQ_S3C2443_WDT S3C2410_IRQSUB(27)
#define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28)

#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416)
#if defined(CONFIG_CPU_S3C2416)
#define NR_IRQS (IRQ_S3C2416_I2S1 + 1)
#elif defined(CONFIG_CPU_S3C2443)
#define NR_IRQS (IRQ_S3C2443_AC97+1)
#else
#define NR_IRQS (IRQ_S3C2440_AC97+1)
Expand Down
98 changes: 98 additions & 0 deletions arch/arm/mach-s3c24xx/irq-s3c2416.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/syscore_ops.h>

#include <mach/hardware.h>
#include <asm/irq.h>
Expand Down Expand Up @@ -192,6 +193,43 @@ static struct irq_chip s3c2416_irq_uart3 = {
.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 __init s3c2416_add_sub(unsigned int base,
Expand All @@ -213,6 +251,42 @@ static int __init s3c2416_add_sub(unsigned int base,
return 0;
}

static void __init 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 __init s3c2416_irq_add(struct device *dev,
struct subsys_interface *sif)
{
Expand All @@ -232,6 +306,8 @@ static int __init s3c2416_irq_add(struct device *dev,
&s3c2416_irq_wdtac97,
IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);

s3c2416_irq_add_second();

return 0;
}

Expand All @@ -248,3 +324,25 @@ static int __init s3c2416_irq_init(void)

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
1 change: 1 addition & 0 deletions arch/arm/mach-s3c24xx/s3c2416.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ int __init s3c2416_init(void)
register_syscore_ops(&s3c2416_pm_syscore_ops);
#endif
register_syscore_ops(&s3c24xx_irq_syscore_ops);
register_syscore_ops(&s3c2416_irq_syscore_ops);

return device_register(&s3c2416_dev);
}
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/plat-samsung/include/plat/s3c2416.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ extern void s3c2416_init_clocks(int xtal);
extern int s3c2416_baseclk_add(void);

extern void s3c2416_restart(char mode, const char *cmd);

extern struct syscore_ops s3c2416_irq_syscore_ops;

#else
#define s3c2416_init_clocks NULL
#define s3c2416_init_uarts NULL
Expand Down

0 comments on commit 0e944e2

Please sign in to comment.