Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e944e27 authored by Heiko Stuebner's avatar Heiko Stuebner Committed by Kukjin Kim
Browse files

ARM: S3C24XX: add support for second irq set of S3C2416



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: default avatarHeiko Stuebner <heiko@sntech.de>
Signed-off-by: default avatarKukjin Kim <kgene.kim@samsung.com>
parent 2de05a57
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -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 */

@@ -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)
+98 −0
Original line number Diff line number Diff line
@@ -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>
@@ -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,
@@ -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)
{
@@ -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;
}

@@ -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 −0
Original line number Diff line number Diff line
@@ -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);
}
+3 −0
Original line number Diff line number Diff line
@@ -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