ARM: mach-shmobile: Use common INTC IRQ code on sh73a0

Improve IRQ triggering support by making use of the macro
INTC_IRQ_PINS_32() for INTCA on sh73a0. Unfortunately it
is not as easy as just using the macro as-is, we need to
do mask and unmaks in the GIC but configure other bits
and ack in INTCA. Update GPIO IRQ mappings while at it.

Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Magnus Damm 2011-10-12 16:21:42 +09:00 committed by Paul Mundt
parent da5713ef03
commit a1993055ef
2 changed files with 157 additions and 33 deletions

View File

@ -22,6 +22,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sh_intc.h> #include <linux/sh_intc.h>
#include <mach/intc.h>
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
@ -255,20 +256,141 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
return 0; /* always allow wakeup */ return 0; /* always allow wakeup */
} }
#define RELOC_BASE 0x1000
/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */
#define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
INTCS_VECT_RELOC, "sh73a0-intca-irq-pins");
static int to_gic_irq(struct irq_data *data)
{
unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE;
if (vect >= 0x3200)
vect -= 0x3000;
else
vect -= 0x0200;
return gic_spi((vect >> 5) + 1);
}
static int to_intca_reloc_irq(struct irq_data *data)
{
return data->irq + (RELOC_BASE >> 5);
}
#define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq))
#define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p)
static void intca_gic_enable(struct irq_data *data)
{
irq_cb(irq_unmask, to_intca_reloc_irq(data));
irq_cb(irq_unmask, to_gic_irq(data));
}
static void intca_gic_disable(struct irq_data *data)
{
irq_cb(irq_mask, to_gic_irq(data));
irq_cb(irq_mask, to_intca_reloc_irq(data));
}
static void intca_gic_mask_ack(struct irq_data *data)
{
irq_cb(irq_mask, to_gic_irq(data));
irq_cb(irq_mask_ack, to_intca_reloc_irq(data));
}
static void intca_gic_eoi(struct irq_data *data)
{
irq_cb(irq_eoi, to_gic_irq(data));
}
static int intca_gic_set_type(struct irq_data *data, unsigned int type)
{
return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type);
}
static int intca_gic_set_wake(struct irq_data *data, unsigned int on)
{
return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on);
}
#ifdef CONFIG_SMP
static int intca_gic_set_affinity(struct irq_data *data,
const struct cpumask *cpumask,
bool force)
{
return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force);
}
#endif
struct irq_chip intca_gic_irq_chip = {
.name = "INTCA-GIC",
.irq_mask = intca_gic_disable,
.irq_unmask = intca_gic_enable,
.irq_mask_ack = intca_gic_mask_ack,
.irq_eoi = intca_gic_eoi,
.irq_enable = intca_gic_enable,
.irq_disable = intca_gic_disable,
.irq_shutdown = intca_gic_disable,
.irq_set_type = intca_gic_set_type,
.irq_set_wake = intca_gic_set_wake,
#ifdef CONFIG_SMP
.irq_set_affinity = intca_gic_set_affinity,
#endif
};
static int to_intc_vect(int irq)
{
unsigned int irq_pin = irq - gic_spi(1);
unsigned int offs;
if (irq_pin < 16)
offs = 0x0200;
else
offs = 0x3000;
return offs + (irq_pin << 5);
}
static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id)
{
generic_handle_irq(intcs_evt2irq(to_intc_vect(irq)));
return IRQ_HANDLED;
}
static struct irqaction sh73a0_irq_pin_cascade[32];
void __init sh73a0_init_irq(void) void __init sh73a0_init_irq(void)
{ {
void __iomem *gic_dist_base = __io(0xf0001000); void __iomem *gic_dist_base = __io(0xf0001000);
void __iomem *gic_cpu_base = __io(0xf0000100); void __iomem *gic_cpu_base = __io(0xf0000100);
void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
int k, n;
gic_init(0, 29, gic_dist_base, gic_cpu_base); gic_init(0, 29, gic_dist_base, gic_cpu_base);
gic_arch_extn.irq_set_wake = sh73a0_set_wake; gic_arch_extn.irq_set_wake = sh73a0_set_wake;
register_intc_controller(&intcs_desc); register_intc_controller(&intcs_desc);
register_intc_controller(&intca_irq_pins_desc);
/* demux using INTEVTSA */ /* demux using INTEVTSA */
sh73a0_intcs_cascade.name = "INTCS cascade"; sh73a0_intcs_cascade.name = "INTCS cascade";
sh73a0_intcs_cascade.handler = sh73a0_intcs_demux; sh73a0_intcs_cascade.handler = sh73a0_intcs_demux;
sh73a0_intcs_cascade.dev_id = intevtsa; sh73a0_intcs_cascade.dev_id = intevtsa;
setup_irq(gic_spi(50), &sh73a0_intcs_cascade); setup_irq(gic_spi(50), &sh73a0_intcs_cascade);
/* IRQ pins require special handling through INTCA and GIC */
for (k = 0; k < 32; k++) {
sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade";
sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux;
setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]);
n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k)));
irq_set_chip_and_handler_name(n, &intca_gic_irq_chip,
handle_level_irq, "level");
set_irq_flags(n, IRQF_VALID); /* yuck */
}
} }

View File

@ -2766,41 +2766,43 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
{ }, { },
}; };
#define EXT_IRQ(n) gic_spi((n) + 1) /* GIC SPI starting from 1 for IRQ0 */ /* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */
#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5))
#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5))
static struct pinmux_irq pinmux_irqs[] = { static struct pinmux_irq pinmux_irqs[] = {
PINMUX_IRQ(EXT_IRQ(19), PORT9_FN0), PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),
PINMUX_IRQ(EXT_IRQ(1), PORT10_FN0), PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0),
PINMUX_IRQ(EXT_IRQ(0), PORT11_FN0), PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0),
PINMUX_IRQ(EXT_IRQ(18), PORT13_FN0), PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0),
PINMUX_IRQ(EXT_IRQ(20), PORT14_FN0), PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0),
PINMUX_IRQ(EXT_IRQ(21), PORT15_FN0), PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0),
PINMUX_IRQ(EXT_IRQ(31), PORT26_FN0), PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0),
PINMUX_IRQ(EXT_IRQ(30), PORT27_FN0), PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0),
PINMUX_IRQ(EXT_IRQ(29), PORT28_FN0), PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0),
PINMUX_IRQ(EXT_IRQ(22), PORT40_FN0), PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0),
PINMUX_IRQ(EXT_IRQ(23), PORT53_FN0), PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0),
PINMUX_IRQ(EXT_IRQ(10), PORT54_FN0), PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0),
PINMUX_IRQ(EXT_IRQ(9), PORT56_FN0), PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0),
PINMUX_IRQ(EXT_IRQ(26), PORT115_FN0), PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0),
PINMUX_IRQ(EXT_IRQ(27), PORT116_FN0), PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0),
PINMUX_IRQ(EXT_IRQ(28), PORT117_FN0), PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0),
PINMUX_IRQ(EXT_IRQ(24), PORT118_FN0), PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0),
PINMUX_IRQ(EXT_IRQ(6), PORT147_FN0), PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0),
PINMUX_IRQ(EXT_IRQ(2), PORT149_FN0), PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0),
PINMUX_IRQ(EXT_IRQ(7), PORT150_FN0), PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0),
PINMUX_IRQ(EXT_IRQ(12), PORT156_FN0), PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0),
PINMUX_IRQ(EXT_IRQ(4), PORT159_FN0), PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0),
PINMUX_IRQ(EXT_IRQ(25), PORT164_FN0), PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0),
PINMUX_IRQ(EXT_IRQ(8), PORT223_FN0), PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0),
PINMUX_IRQ(EXT_IRQ(3), PORT224_FN0), PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0),
PINMUX_IRQ(EXT_IRQ(5), PORT227_FN0), PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0),
PINMUX_IRQ(EXT_IRQ(17), PORT234_FN0), PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0),
PINMUX_IRQ(EXT_IRQ(11), PORT238_FN0), PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0),
PINMUX_IRQ(EXT_IRQ(13), PORT239_FN0), PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0),
PINMUX_IRQ(EXT_IRQ(16), PORT249_FN0), PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0),
PINMUX_IRQ(EXT_IRQ(14), PORT251_FN0), PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0),
PINMUX_IRQ(EXT_IRQ(9), PORT308_FN0), PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0),
}; };
static struct pinmux_info sh73a0_pinmux_info = { static struct pinmux_info sh73a0_pinmux_info = {