mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 17:24:17 +08:00
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:
parent
da5713ef03
commit
a1993055ef
@ -22,6 +22,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sh_intc.h>
|
||||
#include <mach/intc.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/mach-types.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 */
|
||||
}
|
||||
|
||||
#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 __iomem *gic_dist_base = __io(0xf0001000);
|
||||
void __iomem *gic_cpu_base = __io(0xf0000100);
|
||||
void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
|
||||
int k, n;
|
||||
|
||||
gic_init(0, 29, gic_dist_base, gic_cpu_base);
|
||||
gic_arch_extn.irq_set_wake = sh73a0_set_wake;
|
||||
|
||||
register_intc_controller(&intcs_desc);
|
||||
register_intc_controller(&intca_irq_pins_desc);
|
||||
|
||||
/* demux using INTEVTSA */
|
||||
sh73a0_intcs_cascade.name = "INTCS cascade";
|
||||
sh73a0_intcs_cascade.handler = sh73a0_intcs_demux;
|
||||
sh73a0_intcs_cascade.dev_id = intevtsa;
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
@ -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[] = {
|
||||
PINMUX_IRQ(EXT_IRQ(19), PORT9_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(1), PORT10_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(0), PORT11_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(18), PORT13_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(20), PORT14_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(21), PORT15_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(31), PORT26_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(30), PORT27_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(29), PORT28_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(22), PORT40_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(23), PORT53_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(10), PORT54_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(9), PORT56_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(26), PORT115_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(27), PORT116_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(28), PORT117_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(24), PORT118_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(6), PORT147_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(2), PORT149_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(7), PORT150_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(12), PORT156_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(4), PORT159_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(25), PORT164_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(8), PORT223_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(3), PORT224_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(5), PORT227_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(17), PORT234_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(11), PORT238_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(13), PORT239_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(16), PORT249_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(14), PORT251_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ(9), PORT308_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(1), PORT10_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(0), PORT11_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(18), PORT13_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(20), PORT14_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(21), PORT15_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(31), PORT26_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(30), PORT27_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(29), PORT28_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(22), PORT40_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(23), PORT53_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(10), PORT54_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(9), PORT56_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(26), PORT115_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(27), PORT116_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(28), PORT117_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(24), PORT118_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(6), PORT147_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(2), PORT149_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(7), PORT150_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(12), PORT156_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(4), PORT159_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(25), PORT164_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(8), PORT223_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(3), PORT224_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(5), PORT227_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(17), PORT234_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(11), PORT238_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(13), PORT239_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16H(16), PORT249_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(14), PORT251_FN0),
|
||||
PINMUX_IRQ(EXT_IRQ16L(9), PORT308_FN0),
|
||||
};
|
||||
|
||||
static struct pinmux_info sh73a0_pinmux_info = {
|
||||
|
Loading…
Reference in New Issue
Block a user