Skip to content

Commit

Permalink
Merge tag 'renesas-intc-external-irq2-for-v3.10' into soc-base
Browse files Browse the repository at this point in the history
Update for Renesas INTC External IRQ pin driver for v3.10

This adds support for shared interrupt lines to the
Renesas INTC External IRQ pin driver which has already
been queued up for v3.10 (tag renesas-intc-external-irq-for-v3.10).

The patch "irqchip: intc-irqpin: Add support for shared interrupt lines"
in renesas-intc-external-irq2-for-v3.10 is a dependency for
"ARM: shmobile: r8a7740: Migrate from INTC to GIC". That dependency is
the reason for this merge.
  • Loading branch information
Simon Horman committed Apr 2, 2013
2 parents d75bc78 + 427cc72 commit 4c82e45
Show file tree
Hide file tree
Showing 14 changed files with 1,115 additions and 128 deletions.
2 changes: 2 additions & 0 deletions arch/arm/mach-shmobile/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ config ARCH_SH73A0
select CPU_V7
select I2C
select SH_CLK_CPG
select RENESAS_INTC_IRQPIN

config ARCH_R8A7740
bool "R-Mobile A1 (R8A77400)"
Expand All @@ -31,6 +32,7 @@ config ARCH_R8A7779
select SH_CLK_CPG
select USB_ARCH_HAS_EHCI
select USB_ARCH_HAS_OHCI
select RENESAS_INTC_IRQPIN

config ARCH_EMEV2
bool "Emma Mobile EV2"
Expand Down
14 changes: 7 additions & 7 deletions arch/arm/mach-shmobile/board-kzm9g.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static struct resource smsc9221_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
.start = intcs_evt2irq(0x260), /* IRQ3 */
.start = irq_pin(3), /* IRQ3 */
.flags = IORESOURCE_IRQ,
},
};
Expand Down Expand Up @@ -115,7 +115,7 @@ static struct resource usb_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
.start = intcs_evt2irq(0x220), /* IRQ1 */
.start = irq_pin(1), /* IRQ1 */
.flags = IORESOURCE_IRQ,
},
};
Expand All @@ -138,7 +138,7 @@ struct usbhs_private {
struct renesas_usbhs_platform_info info;
};

#define IRQ15 intcs_evt2irq(0x03e0)
#define IRQ15 irq_pin(15)
#define USB_PHY_MODE (1 << 4)
#define USB_PHY_INT_EN ((1 << 3) | (1 << 2))
#define USB_PHY_ON (1 << 1)
Expand Down Expand Up @@ -563,25 +563,25 @@ static struct i2c_board_info i2c0_devices[] = {
},
{
I2C_BOARD_INFO("ak8975", 0x0c),
.irq = intcs_evt2irq(0x3380), /* IRQ28 */
.irq = irq_pin(28), /* IRQ28 */
},
{
I2C_BOARD_INFO("adxl34x", 0x1d),
.irq = intcs_evt2irq(0x3340), /* IRQ26 */
.irq = irq_pin(26), /* IRQ26 */
},
};

static struct i2c_board_info i2c1_devices[] = {
{
I2C_BOARD_INFO("st1232-ts", 0x55),
.irq = intcs_evt2irq(0x300), /* IRQ8 */
.irq = irq_pin(8), /* IRQ8 */
},
};

static struct i2c_board_info i2c3_devices[] = {
{
I2C_BOARD_INFO("pcf8575", 0x20),
.irq = intcs_evt2irq(0x3260), /* IRQ19 */
.irq = irq_pin(19), /* IRQ19 */
.platform_data = &pcf8575_pdata,
},
};
Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-shmobile/include/mach/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ extern void r8a7740_pm_init(void);

extern void r8a7779_init_delay(void);
extern void r8a7779_init_irq(void);
extern void r8a7779_init_irq_extpin(int irlm);
extern void r8a7779_init_irq_dt(void);
extern void r8a7779_map_io(void);
extern void r8a7779_earlytimer_init(void);
Expand Down
4 changes: 4 additions & 0 deletions arch/arm/mach-shmobile/include/mach/irqs.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@
#define INTCS_VECT(n, vect) INTC_VECT((n), INTCS_VECT_BASE + (vect))
#define intcs_evt2irq(evt) evt2irq(INTCS_VECT_BASE + (evt))

/* External IRQ pins */
#define IRQPIN_BASE 2000
#define irq_pin(nr) ((nr) + IRQPIN_BASE)

#endif /* __ASM_MACH_IRQS_H */
53 changes: 52 additions & 1 deletion arch/arm/mach-shmobile/intc-r8a7779.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/irqchip/arm-gic.h>
#include <mach/common.h>
#include <linux/platform_data/irq-renesas-intc-irqpin.h>
#include <linux/irqchip.h>
#include <mach/common.h>
#include <mach/intc.h>
#include <mach/irqs.h>
#include <mach/r8a7779.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
Expand All @@ -39,6 +42,54 @@
#define INT2NTSR0 IOMEM(0xfe700060)
#define INT2NTSR1 IOMEM(0xfe700064)

static struct renesas_intc_irqpin_config irqpin0_platform_data = {
.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
.sense_bitfield_width = 2,
};

static struct resource irqpin0_resources[] = {
DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
};

static struct platform_device irqpin0_device = {
.name = "renesas_intc_irqpin",
.id = 0,
.resource = irqpin0_resources,
.num_resources = ARRAY_SIZE(irqpin0_resources),
.dev = {
.platform_data = &irqpin0_platform_data,
},
};

void __init r8a7779_init_irq_extpin(int irlm)
{
void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
unsigned long tmp;

if (icr0) {
tmp = ioread32(icr0);
if (irlm)
tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
else
tmp &= ~(1 << 23); /* IRL mode - not supported */
tmp |= (1 << 21); /* LVLMODE = 1 */
iowrite32(tmp, icr0);
iounmap(icr0);

if (irlm)
platform_device_register(&irqpin0_device);
} else
pr_warn("r8a7779: unable to setup external irq pin mode\n");
}

static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
{
return 0; /* always allow wakeup */
Expand Down
117 changes: 0 additions & 117 deletions arch/arm/mach-shmobile/intc-sh73a0.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,108 +260,6 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
return 0; /* always allow wakeup */
}

#define RELOC_BASE 0x1200

/* INTCA IRQ pins at INTCS + RELOC_BASE 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);
}

#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 = sh73a0_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];

#define PINTER0_PHYS 0xe69000a0
#define PINTER1_PHYS 0xe69000a4
#define PINTER0_VIRT IOMEM(0xe69000a0)
Expand Down Expand Up @@ -422,13 +320,11 @@ void __init sh73a0_init_irq(void)
void __iomem *gic_dist_base = IOMEM(0xf0001000);
void __iomem *gic_cpu_base = IOMEM(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);
register_intc_controller(&intc_pint0_desc);
register_intc_controller(&intc_pint1_desc);

Expand All @@ -438,19 +334,6 @@ void __init sh73a0_init_irq(void)
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)));
WARN_ON(irq_alloc_desc_at(n, numa_node_id()) != n);
irq_set_chip_and_handler_name(n, &intca_gic_irq_chip,
handle_level_irq, "level");
set_irq_flags(n, IRQF_VALID); /* yuck */
}

/* PINT pins are sanely tied to the GIC as SPI */
sh73a0_pint0_cascade.name = "PINT0 cascade";
sh73a0_pint0_cascade.handler = sh73a0_pint0_demux;
Expand Down
Loading

0 comments on commit 4c82e45

Please sign in to comment.