Skip to content

Commit

Permalink
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tip/tip

Pull irq core updates from Thomas Gleixner:
 "This is the first (boring) part of irq updates:

   - support for big endian I/O accessors in the generic irq chip

   - cleanup of brcmstb/bcm7120 drivers so they can be reused for non
     ARM SoCs

   - the usual pile of fixes and updates for the various ARM irq chips"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (25 commits)
  irqchip: dw-apb-ictl: Add PM support
  irqchip: dw-apb-ictl: Enable IRQ_GC_MASK_CACHE_PER_TYPE
  irqchip: dw-apb-ictl: Always use use {readl|writel}_relaxed
  ARM: orion: convert the irq_reg_{readl,writel} calls to the new API
  irqchip: atmel-aic: Add missing entry for rm9200 irq fixups
  irqchip: atmel-aic: Rename at91sam9_aic_irq_fixup for naming consistency
  irqchip: atmel-aic: Add specific irq fixup function for sam9g45 and sam9rl
  irqchip: atmel-aic: Add irq fixups for at91sam926x SoCs
  irqchip: atmel-aic: Add irq fixup for RTT block
  irqchip: brcmstb-l2: Convert driver to use irq_reg_{readl,writel}
  irqchip: bcm7120-l2: Convert driver to use irq_reg_{readl,writel}
  irqchip: bcm7120-l2: Decouple driver from brcmstb-l2
  irqchip: bcm7120-l2: Extend driver to support 64+ bit controllers
  irqchip: bcm7120-l2: Use gc->mask_cache to simplify suspend/resume functions
  irqchip: bcm7120-l2: Fix missing nibble in gc->unused mask
  irqchip: bcm7120-l2: Make sure all register accesses use base+offset
  irqchip: bcm7120-l2, brcmstb-l2: Remove ARM Kconfig dependency
  irqchip: bcm7120-l2: Eliminate bad IRQ check
  irqchip: brcmstb-l2: Eliminate dependency on ARM code
  genirq: Generic chip: Add big endian I/O accessors
  ...
  • Loading branch information
torvalds committed Dec 10, 2014
2 parents a157508 + 1655b05 commit ecb50f0
Show file tree
Hide file tree
Showing 18 changed files with 345 additions and 188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ Such an interrupt controller has the following hardware design:
or if they will output an interrupt signal at this 2nd level interrupt
controller, in particular for UARTs

- not all 32-bits within the interrupt controller actually map to an interrupt
- typically has one 32-bit enable word and one 32-bit status word, but on
some hardware may have more than one enable/status pair

- no atomic set/clear operations

- not all bits within the interrupt controller actually map to an interrupt

The typical hardware layout for this controller is represented below:

Expand Down Expand Up @@ -48,7 +53,9 @@ The typical hardware layout for this controller is represented below:
Required properties:

- compatible: should be "brcm,bcm7120-l2-intc"
- reg: specifies the base physical address and size of the registers
- reg: specifies the base physical address and size of the registers;
multiple pairs may be specified, with the first pair handling IRQ offsets
0..31 and the second pair handling 32..63
- interrupt-controller: identifies the node as an interrupt controller
- #interrupt-cells: specifies the number of cells needed to encode an interrupt
source, should be 1.
Expand All @@ -59,18 +66,21 @@ Required properties:
- brcm,int-map-mask: 32-bits bit mask describing how many and which interrupts
are wired to this 2nd level interrupt controller, and how they match their
respective interrupt parents. Should match exactly the number of interrupts
specified in the 'interrupts' property.
specified in the 'interrupts' property, multiplied by the number of
enable/status register pairs implemented by this controller. For
multiple parent IRQs with multiple enable/status words, this looks like:
<irq0_w0 irq0_w1 irq1_w0 irq1_w1 ...>

Optional properties:

- brcm,irq-can-wake: if present, this means the L2 controller can be used as a
wakeup source for system suspend/resume.

- brcm,int-fwd-mask: if present, a 32-bits bit mask to configure for the
interrupts which have a mux gate, typically UARTs. Setting these bits will
make their respective interrupts outputs bypass this 2nd level interrupt
controller completely, it completely transparent for the interrupt controller
parent
- brcm,int-fwd-mask: if present, a bit mask to configure the interrupts which
have a mux gate, typically UARTs. Setting these bits will make their
respective interrupt outputs bypass this 2nd level interrupt controller
completely; it is completely transparent for the interrupt controller
parent. This should have one 32-bit word per enable/status pair.

Example:

Expand Down
1 change: 1 addition & 0 deletions arch/arm/mach-bcm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ config ARCH_BRCMSTB
select HAVE_ARM_ARCH_TIMER
select BRCMSTB_GISB_ARB
select BRCMSTB_L2_IRQ
select BCM7120_L2_IRQ
help
Say Y if you intend to run the kernel on a Broadcom ARM-based STB
chipset.
Expand Down
8 changes: 4 additions & 4 deletions arch/arm/plat-orion/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,9 +505,9 @@ static void orion_gpio_unmask_irq(struct irq_data *d)
u32 mask = d->mask;

irq_gc_lock(gc);
reg_val = irq_reg_readl(gc->reg_base + ct->regs.mask);
reg_val = irq_reg_readl(gc, ct->regs.mask);
reg_val |= mask;
irq_reg_writel(reg_val, gc->reg_base + ct->regs.mask);
irq_reg_writel(gc, reg_val, ct->regs.mask);
irq_gc_unlock(gc);
}

Expand All @@ -519,9 +519,9 @@ static void orion_gpio_mask_irq(struct irq_data *d)
u32 reg_val;

irq_gc_lock(gc);
reg_val = irq_reg_readl(gc->reg_base + ct->regs.mask);
reg_val = irq_reg_readl(gc, ct->regs.mask);
reg_val &= ~mask;
irq_reg_writel(reg_val, gc->reg_base + ct->regs.mask);
irq_reg_writel(gc, reg_val, ct->regs.mask);
irq_gc_unlock(gc);
}

Expand Down
7 changes: 6 additions & 1 deletion drivers/irqchip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,19 @@ config ATMEL_AIC5_IRQ
select MULTI_IRQ_HANDLER
select SPARSE_IRQ

config BCM7120_L2_IRQ
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN

config BRCMSTB_L2_IRQ
bool
depends on ARM
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN

config DW_APB_ICTL
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN

config IMGPDC_IRQ
Expand Down
4 changes: 2 additions & 2 deletions drivers/irqchip/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o
obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o
obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o
obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o \
irq-bcm7120-l2.o
obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o
obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o
obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-armada-370-xp.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ static int armada_xp_set_affinity(struct irq_data *d,
writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
raw_spin_unlock(&irq_controller_lock);

return 0;
return IRQ_SET_MASK_OK;
}
#endif

Expand Down
26 changes: 26 additions & 0 deletions drivers/irqchip/irq-atmel-aic-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,32 @@ void __init aic_common_rtc_irq_fixup(struct device_node *root)
iounmap(regs);
}

#define AT91_RTT_MR 0x00 /* Real-time Mode Register */
#define AT91_RTT_ALMIEN (1 << 16) /* Alarm Interrupt Enable */
#define AT91_RTT_RTTINCIEN (1 << 17) /* Real Time Timer Increment Interrupt Enable */

void __init aic_common_rtt_irq_fixup(struct device_node *root)
{
struct device_node *np;
void __iomem *regs;

/*
* The at91sam9263 SoC has 2 instances of the RTT block, hence we
* iterate over the DT to find each occurrence.
*/
for_each_compatible_node(np, NULL, "atmel,at91sam9260-rtt") {
regs = of_iomap(np, 0);
if (!regs)
continue;

writel(readl(regs + AT91_RTT_MR) &
~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN),
regs + AT91_RTT_MR);

iounmap(regs);
}
}

void __init aic_common_irq_fixup(const struct of_device_id *matches)
{
struct device_node *root = of_find_node_by_path("/");
Expand Down
2 changes: 2 additions & 0 deletions drivers/irqchip/irq-atmel-aic-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node,

void __init aic_common_rtc_irq_fixup(struct device_node *root);

void __init aic_common_rtt_irq_fixup(struct device_node *root);

void __init aic_common_irq_fixup(const struct of_device_id *matches);

#endif /* __IRQ_ATMEL_AIC_COMMON_H */
66 changes: 41 additions & 25 deletions drivers/irqchip/irq-atmel-aic.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ aic_handle(struct pt_regs *regs)
u32 irqnr;
u32 irqstat;

irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR);
irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR);
irqnr = irq_reg_readl(gc, AT91_AIC_IVR);
irqstat = irq_reg_readl(gc, AT91_AIC_ISR);

if (!irqstat)
irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
irq_reg_writel(gc, 0, AT91_AIC_EOICR);
else
handle_domain_irq(aic_domain, irqnr, regs);
}
Expand All @@ -80,7 +80,7 @@ static int aic_retrigger(struct irq_data *d)

/* Enable interrupt on AIC5 */
irq_gc_lock(gc);
irq_reg_writel(d->mask, gc->reg_base + AT91_AIC_ISCR);
irq_reg_writel(gc, d->mask, AT91_AIC_ISCR);
irq_gc_unlock(gc);

return 0;
Expand All @@ -92,12 +92,12 @@ static int aic_set_type(struct irq_data *d, unsigned type)
unsigned int smr;
int ret;

smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(d->hwirq));
smr = irq_reg_readl(gc, AT91_AIC_SMR(d->hwirq));
ret = aic_common_set_type(d, type, &smr);
if (ret)
return ret;

irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(d->hwirq));
irq_reg_writel(gc, smr, AT91_AIC_SMR(d->hwirq));

return 0;
}
Expand All @@ -108,8 +108,8 @@ static void aic_suspend(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);

irq_gc_lock(gc);
irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IDCR);
irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IECR);
irq_reg_writel(gc, gc->mask_cache, AT91_AIC_IDCR);
irq_reg_writel(gc, gc->wake_active, AT91_AIC_IECR);
irq_gc_unlock(gc);
}

Expand All @@ -118,8 +118,8 @@ static void aic_resume(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);

irq_gc_lock(gc);
irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IDCR);
irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IECR);
irq_reg_writel(gc, gc->wake_active, AT91_AIC_IDCR);
irq_reg_writel(gc, gc->mask_cache, AT91_AIC_IECR);
irq_gc_unlock(gc);
}

Expand All @@ -128,8 +128,8 @@ static void aic_pm_shutdown(struct irq_data *d)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);

irq_gc_lock(gc);
irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
irq_reg_writel(gc, 0xffffffff, AT91_AIC_IDCR);
irq_reg_writel(gc, 0xffffffff, AT91_AIC_ICCR);
irq_gc_unlock(gc);
}
#else
Expand All @@ -148,24 +148,24 @@ static void __init aic_hw_init(struct irq_domain *domain)
* will not Lock out nIRQ
*/
for (i = 0; i < 8; i++)
irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
irq_reg_writel(gc, 0, AT91_AIC_EOICR);

/*
* Spurious Interrupt ID in Spurious Vector Register.
* When there is no current interrupt, the IRQ Vector Register
* reads the value stored in AIC_SPU
*/
irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_SPU);
irq_reg_writel(gc, 0xffffffff, AT91_AIC_SPU);

/* No debugging in AIC: Debug (Protect) Control Register */
irq_reg_writel(0, gc->reg_base + AT91_AIC_DCR);
irq_reg_writel(gc, 0, AT91_AIC_DCR);

/* Disable and clear all interrupts initially */
irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
irq_reg_writel(gc, 0xffffffff, AT91_AIC_IDCR);
irq_reg_writel(gc, 0xffffffff, AT91_AIC_ICCR);

for (i = 0; i < 32; i++)
irq_reg_writel(i, gc->reg_base + AT91_AIC_SVR(i));
irq_reg_writel(gc, i, AT91_AIC_SVR(i));
}

static int aic_irq_domain_xlate(struct irq_domain *d,
Expand Down Expand Up @@ -195,10 +195,10 @@ static int aic_irq_domain_xlate(struct irq_domain *d,
gc = dgc->gc[idx];

irq_gc_lock(gc);
smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(*out_hwirq));
smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq));
ret = aic_common_set_priority(intspec[2], &smr);
if (!ret)
irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(*out_hwirq));
irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq));
irq_gc_unlock(gc);

return ret;
Expand All @@ -209,16 +209,32 @@ static const struct irq_domain_ops aic_irq_ops = {
.xlate = aic_irq_domain_xlate,
};

static void __init at91sam9_aic_irq_fixup(struct device_node *root)
static void __init at91rm9200_aic_irq_fixup(struct device_node *root)
{
aic_common_rtc_irq_fixup(root);
}

static void __init at91sam9260_aic_irq_fixup(struct device_node *root)
{
aic_common_rtt_irq_fixup(root);
}

static void __init at91sam9g45_aic_irq_fixup(struct device_node *root)
{
aic_common_rtc_irq_fixup(root);
aic_common_rtt_irq_fixup(root);
}

static const struct of_device_id __initdata aic_irq_fixups[] = {
{ .compatible = "atmel,at91sam9g45", .data = at91sam9_aic_irq_fixup },
{ .compatible = "atmel,at91sam9n12", .data = at91sam9_aic_irq_fixup },
{ .compatible = "atmel,at91sam9rl", .data = at91sam9_aic_irq_fixup },
{ .compatible = "atmel,at91sam9x5", .data = at91sam9_aic_irq_fixup },
{ .compatible = "atmel,at91rm9200", .data = at91rm9200_aic_irq_fixup },
{ .compatible = "atmel,at91sam9g45", .data = at91sam9g45_aic_irq_fixup },
{ .compatible = "atmel,at91sam9n12", .data = at91rm9200_aic_irq_fixup },
{ .compatible = "atmel,at91sam9rl", .data = at91sam9g45_aic_irq_fixup },
{ .compatible = "atmel,at91sam9x5", .data = at91rm9200_aic_irq_fixup },
{ .compatible = "atmel,at91sam9260", .data = at91sam9260_aic_irq_fixup },
{ .compatible = "atmel,at91sam9261", .data = at91sam9260_aic_irq_fixup },
{ .compatible = "atmel,at91sam9263", .data = at91sam9260_aic_irq_fixup },
{ .compatible = "atmel,at91sam9g20", .data = at91sam9260_aic_irq_fixup },
{ /* sentinel */ },
};

Expand Down
Loading

0 comments on commit ecb50f0

Please sign in to comment.