Skip to content

Commit

Permalink
[ARM] pxa: integrate low IRQ chip (ICIP) and high IRQ chip (ICIP2) in…
Browse files Browse the repository at this point in the history
…to one

This makes the code better organized and simplified a bit.  The change
will lose a bit of performance when performing IRQ ack/mask/unmask,but
that's not too much after checking the result binary.

This patch also removes the ugly #ifdef CONFIG_PXA27x .. #endif by
carefully not to access those pxa{27x,3xx} specific registers, this
is done by keeping an internal IRQ number variable.  The pxa-regs.h
is also modified so registers for IRQ > PXA_IRQ(31) are made public
even if CONFIG_PXA{27x,3xx} isn't defined (for pxa25x's sake)

The incorrect assumption in the original code that internal irq starts
from 0 is also corrected by comparing with PXA_IRQ(0).

"struct sys_device" for the IRQ are reduced into one single device on
pxa{27x,3xx}.

Signed-off-by: eric miao <eric.miao@marvell.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
eric miao authored and Russell King committed Apr 19, 2008
1 parent e3630db commit f6fb7af
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 105 deletions.
3 changes: 1 addition & 2 deletions arch/arm/mach-pxa/generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
struct sys_timer;

extern struct sys_timer pxa_timer;
extern void __init pxa_init_irq_low(void);
extern void __init pxa_init_irq_high(void);
extern void __init pxa_init_irq(int irq_nr);
extern void __init pxa_init_irq_gpio(int gpio_nr);
extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
extern void __init pxa_init_gpio_set_wake(int (*set_wake)(unsigned int, unsigned int));
Expand Down
117 changes: 33 additions & 84 deletions arch/arm/mach-pxa/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,92 +24,57 @@

#include "generic.h"

#define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f)
#define _ICMR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR))
#define _ICLR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR))

/*
* This is for peripheral IRQs internal to the PXA chip.
*/

static void pxa_mask_low_irq(unsigned int irq)
static int pxa_internal_irq_nr;

static void pxa_mask_irq(unsigned int irq)
{
ICMR &= ~(1 << irq);
_ICMR(irq) &= ~(1 << IRQ_BIT(irq));
}

static void pxa_unmask_low_irq(unsigned int irq)
static void pxa_unmask_irq(unsigned int irq)
{
ICMR |= (1 << irq);
_ICMR(irq) |= 1 << IRQ_BIT(irq);
}

static struct irq_chip pxa_internal_chip_low = {
static struct irq_chip pxa_internal_irq_chip = {
.name = "SC",
.ack = pxa_mask_low_irq,
.mask = pxa_mask_low_irq,
.unmask = pxa_unmask_low_irq,
.ack = pxa_mask_irq,
.mask = pxa_mask_irq,
.unmask = pxa_unmask_irq,
};

void __init pxa_init_irq_low(void)
void __init pxa_init_irq(int irq_nr)
{
int irq;

/* disable all IRQs */
ICMR = 0;
pxa_internal_irq_nr = irq_nr;

/* all IRQs are IRQ, not FIQ */
ICLR = 0;
for (irq = 0; irq < irq_nr; irq += 32) {
_ICMR(irq) = 0; /* disable all IRQs */
_ICLR(irq) = 0; /* all IRQs are IRQ, not FIQ */
}

/* only unmasked interrupts kick us out of idle */
ICCR = 1;

for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
set_irq_chip(irq, &pxa_internal_chip_low);
set_irq_handler(irq, handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
}
}

#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)

/*
* This is for the second set of internal IRQs as found on the PXA27x.
*/

static void pxa_mask_high_irq(unsigned int irq)
{
ICMR2 &= ~(1 << (irq - 32));
}

static void pxa_unmask_high_irq(unsigned int irq)
{
ICMR2 |= (1 << (irq - 32));
}

static struct irq_chip pxa_internal_chip_high = {
.name = "SC-hi",
.ack = pxa_mask_high_irq,
.mask = pxa_mask_high_irq,
.unmask = pxa_unmask_high_irq,
};

void __init pxa_init_irq_high(void)
{
int irq;

ICMR2 = 0;
ICLR2 = 0;

for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
set_irq_chip(irq, &pxa_internal_chip_high);
for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) {
set_irq_chip(irq, &pxa_internal_irq_chip);
set_irq_handler(irq, handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
}
}
#endif

void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
{
pxa_internal_chip_low.set_wake = set_wake;
#ifdef CONFIG_PXA27x
pxa_internal_chip_high.set_wake = set_wake;
#endif
pxa_internal_irq_chip.set_wake = set_wake;
pxa_init_gpio_set_wake(set_wake);
}

Expand All @@ -118,42 +83,26 @@ static unsigned long saved_icmr[2];

static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
{
switch (dev->id) {
case 0:
saved_icmr[0] = ICMR;
ICMR = 0;
break;
#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
case 1:
saved_icmr[1] = ICMR2;
ICMR2 = 0;
break;
#endif
default:
return -EINVAL;
int i, irq = PXA_IRQ(0);

for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
saved_icmr[i] = _ICMR(irq);
_ICMR(irq) = 0;
}

return 0;
}

static int pxa_irq_resume(struct sys_device *dev)
{
switch (dev->id) {
case 0:
ICMR = saved_icmr[0];
ICLR = 0;
ICCR = 1;
break;
#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
case 1:
ICMR2 = saved_icmr[1];
ICLR2 = 0;
break;
#endif
default:
return -EINVAL;
int i, irq = PXA_IRQ(0);

for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
_ICMR(irq) = saved_icmr[i];
_ICLR(irq) = 0;
}

ICCR = 1;
return 0;
}
#else
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-pxa/pxa25x.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ static int pxa25x_set_wake(unsigned int irq, unsigned int on)

void __init pxa25x_init_irq(void)
{
pxa_init_irq_low();
pxa_init_irq(32);
pxa_init_irq_gpio(85);
pxa_init_irq_set_wake(pxa25x_set_wake);
}
Expand Down
7 changes: 1 addition & 6 deletions arch/arm/mach-pxa/pxa27x.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,7 @@ static int pxa27x_set_wake(unsigned int irq, unsigned int on)

void __init pxa27x_init_irq(void)
{
pxa_init_irq_low();
pxa_init_irq_high();
pxa_init_irq(34);
pxa_init_irq_gpio(128);
pxa_init_irq_set_wake(pxa27x_set_wake);
}
Expand Down Expand Up @@ -389,10 +388,6 @@ static struct platform_device *devices[] __initdata = {

static struct sys_device pxa27x_sysdev[] = {
{
.id = 0,
.cls = &pxa_irq_sysclass,
}, {
.id = 1,
.cls = &pxa_irq_sysclass,
}, {
.cls = &pxa_gpio_sysclass,
Expand Down
7 changes: 1 addition & 6 deletions arch/arm/mach-pxa/pxa3xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,7 @@ void __init pxa3xx_init_irq(void)
value |= (1 << 6);
__asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));

pxa_init_irq_low();
pxa_init_irq_high();
pxa_init_irq(56);
pxa_init_irq_gpio(128);
pxa3xx_init_irq_pm();
}
Expand All @@ -538,10 +537,6 @@ static struct platform_device *devices[] __initdata = {

static struct sys_device pxa3xx_sysdev[] = {
{
.id = 0,
.cls = &pxa_irq_sysclass,
}, {
.id = 1,
.cls = &pxa_irq_sysclass,
}, {
.cls = &pxa_gpio_sysclass,
Expand Down
11 changes: 5 additions & 6 deletions include/asm-arm/arch-pxa/pxa-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,11 @@
#define ICPR __REG(0x40D00010) /* Interrupt Controller Pending Register */
#define ICCR __REG(0x40D00014) /* Interrupt Controller Control Register */

#define ICIP2 __REG(0x40D0009C) /* Interrupt Controller IRQ Pending Register 2 */
#define ICMR2 __REG(0x40D000A0) /* Interrupt Controller Mask Register 2 */
#define ICLR2 __REG(0x40D000A4) /* Interrupt Controller Level Register 2 */
#define ICFP2 __REG(0x40D000A8) /* Interrupt Controller FIQ Pending Register 2 */
#define ICPR2 __REG(0x40D000AC) /* Interrupt Controller Pending Register 2 */

/*
* General Purpose I/O
Expand Down Expand Up @@ -1200,12 +1205,6 @@

/* Interrupt Controller */

#define ICIP2 __REG(0x40D0009C) /* Interrupt Controller IRQ Pending Register 2 */
#define ICMR2 __REG(0x40D000A0) /* Interrupt Controller Mask Register 2 */
#define ICLR2 __REG(0x40D000A4) /* Interrupt Controller Level Register 2 */
#define ICFP2 __REG(0x40D000A8) /* Interrupt Controller FIQ Pending Register 2 */
#define ICPR2 __REG(0x40D000AC) /* Interrupt Controller Pending Register 2 */

#define _GPLR(x) __REG2(0x40E00000, ((x) & 0x60) >> 3)
#define _GPDR(x) __REG2(0x40E0000C, ((x) & 0x60) >> 3)
#define _GPSR(x) __REG2(0x40E00018, ((x) & 0x60) >> 3)
Expand Down

0 comments on commit f6fb7af

Please sign in to comment.