Skip to content

Commit

Permalink
Merge tag 'irqchip-core-4.1-2' of git://git.infradead.org/users/jcoop…
Browse files Browse the repository at this point in the history
…er/linux into irq/core

irqchip core changes for v4.1 (round 2) from Jason Cooper

 - gic
    - Tolerate uni-processor systems better in gic_get_cpumask()

 - mvebu
    - Handle per-cpu interrupts properly
    - Enable PMU interrupts
    - Enable wakeup source

 - vybrid
    - Add MSCM interrupt router

 - renesas
    - Add PM and wakeup support
  • Loading branch information
Thomas Gleixner committed Apr 11, 2015
2 parents fdb7144 + 7822335 commit 425b655
Show file tree
Hide file tree
Showing 12 changed files with 396 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Freescale Vybrid Miscellaneous System Control - CPU Configuration

The MSCM IP contains multiple sub modules, this binding describes the first
block of registers which contains CPU configuration information.

Required properties:
- compatible: "fsl,vf610-mscm-cpucfg", "syscon"
- reg: the register range of the MSCM CPU configuration registers

Example:
mscm_cpucfg: cpucfg@40001000 {
compatible = "fsl,vf610-mscm-cpucfg", "syscon";
reg = <0x40001000 0x800>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Freescale Vybrid Miscellaneous System Control - Interrupt Router

The MSCM IP contains multiple sub modules, this binding describes the second
block of registers which control the interrupt router. The interrupt router
allows to configure the recipient of each peripheral interrupt. Furthermore
it controls the directed processor interrupts. The module is available in all
Vybrid SoC's but is only really useful in dual core configurations (VF6xx
which comes with a Cortex-A5/Cortex-M4 combination).

Required properties:
- compatible: "fsl,vf610-mscm-ir"
- reg: the register range of the MSCM Interrupt Router
- fsl,cpucfg: The handle to the MSCM CPU configuration node, required
to get the current CPU ID
- interrupt-controller: Identifies the node as an interrupt controller
- #interrupt-cells: Two cells, interrupt number and cells.
The hardware interrupt number according to interrupt
assignment of the interrupt router is required.
Flags get passed only when using GIC as parent. Flags
encoding as documented by the GIC bindings.
- interrupt-parent: Should be the phandle for the interrupt controller of
the CPU the device tree is intended to be used on. This
is either the node of the GIC or NVIC controller.

Example:
mscm_ir: interrupt-controller@40001800 {
compatible = "fsl,vf610-mscm-ir";
reg = <0x40001800 0x400>;
fsl,cpucfg = <&mscm_cpucfg>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&intc>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ Required properties:

- compatible: has to be "renesas,irqc-<soctype>", "renesas,irqc" as fallback.
Examples with soctypes are:
- "renesas,irqc-r8a73a4" (R-Mobile AP6)
- "renesas,irqc-r8a73a4" (R-Mobile APE6)
- "renesas,irqc-r8a7790" (R-Car H2)
- "renesas,irqc-r8a7791" (R-Car M2-W)
- "renesas,irqc-r8a7792" (R-Car V2H)
- "renesas,irqc-r8a7793" (R-Car M2-N)
- "renesas,irqc-r8a7794" (R-Car E2)
- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
interrupts.txt in this directory
- clocks: Must contain a reference to the functional clock.

Optional properties:

Expand All @@ -29,4 +30,5 @@ Example:
<0 1 IRQ_TYPE_LEVEL_HIGH>,
<0 2 IRQ_TYPE_LEVEL_HIGH>,
<0 3 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp4_clks R8A7790_CLK_IRQC>;
};
1 change: 1 addition & 0 deletions arch/arm/mach-imx/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ config SOC_IMX6SX

config SOC_VF610
bool "Vybrid Family VF610 support"
select IRQ_DOMAIN_HIERARCHY
select ARM_GIC
select PINCTRL_VF610
select PL310_ERRATA_769419 if CACHE_L2X0
Expand Down
1 change: 1 addition & 0 deletions drivers/irqchip/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ 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_SOC_VF610) += irq-vf610-mscm-ir.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
Expand Down
89 changes: 58 additions & 31 deletions drivers/irqchip/irq-armada-370-xp.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
/* Interrupt Controller Registers Map */
#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48)
#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C)
#define ARMADA_370_XP_INT_FABRIC_MASK_OFFS (0x54)
#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu)

#define ARMADA_370_XP_INT_CONTROL (0x00)
#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30)
Expand All @@ -56,6 +58,7 @@
#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28)

#define ARMADA_370_XP_TIMER0_PER_CPU_IRQ (5)
#define ARMADA_370_XP_FABRIC_IRQ (3)

#define IPI_DOORBELL_START (0)
#define IPI_DOORBELL_END (8)
Expand All @@ -77,6 +80,17 @@ static DEFINE_MUTEX(msi_used_lock);
static phys_addr_t msi_doorbell_addr;
#endif

static inline bool is_percpu_irq(irq_hw_number_t irq)
{
switch (irq) {
case ARMADA_370_XP_TIMER0_PER_CPU_IRQ:
case ARMADA_370_XP_FABRIC_IRQ:
return true;
default:
return false;
}
}

/*
* In SMP mode:
* For shared global interrupts, mask/unmask global enable bit
Expand All @@ -86,7 +100,7 @@ static void armada_370_xp_irq_mask(struct irq_data *d)
{
irq_hw_number_t hwirq = irqd_to_hwirq(d);

if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
if (!is_percpu_irq(hwirq))
writel(hwirq, main_int_base +
ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
else
Expand All @@ -98,7 +112,7 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
{
irq_hw_number_t hwirq = irqd_to_hwirq(d);

if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
if (!is_percpu_irq(hwirq))
writel(hwirq, main_int_base +
ARMADA_370_XP_INT_SET_ENABLE_OFFS);
else
Expand Down Expand Up @@ -281,20 +295,21 @@ static struct irq_chip armada_370_xp_irq_chip = {
#ifdef CONFIG_SMP
.irq_set_affinity = armada_xp_set_affinity,
#endif
.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
};

static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
unsigned int virq, irq_hw_number_t hw)
{
armada_370_xp_irq_mask(irq_get_irq_data(virq));
if (hw != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
if (!is_percpu_irq(hw))
writel(hw, per_cpu_int_base +
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
else
writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
irq_set_status_flags(virq, IRQ_LEVEL);

if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) {
if (is_percpu_irq(hw)) {
irq_set_percpu_devid(virq);
irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
handle_percpu_devid_irq);
Expand All @@ -308,28 +323,6 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
return 0;
}

#ifdef CONFIG_SMP
static void armada_mpic_send_doorbell(const struct cpumask *mask,
unsigned int irq)
{
int cpu;
unsigned long map = 0;

/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
map |= 1 << cpu_logical_map(cpu);

/*
* Ensure that stores to Normal memory are visible to the
* other CPUs before issuing the IPI.
*/
dsb();

/* submit softirq */
writel((map << 8) | irq, main_int_base +
ARMADA_370_XP_SW_TRIG_INT_OFFS);
}

static void armada_xp_mpic_smp_cpu_init(void)
{
u32 control;
Expand All @@ -352,11 +345,44 @@ static void armada_xp_mpic_smp_cpu_init(void)
writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
}

static void armada_xp_mpic_perf_init(void)
{
unsigned long cpuid = cpu_logical_map(smp_processor_id());

/* Enable Performance Counter Overflow interrupts */
writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid),
per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS);
}

#ifdef CONFIG_SMP
static void armada_mpic_send_doorbell(const struct cpumask *mask,
unsigned int irq)
{
int cpu;
unsigned long map = 0;

/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
map |= 1 << cpu_logical_map(cpu);

/*
* Ensure that stores to Normal memory are visible to the
* other CPUs before issuing the IPI.
*/
dsb();

/* submit softirq */
writel((map << 8) | irq, main_int_base +
ARMADA_370_XP_SW_TRIG_INT_OFFS);
}

static int armada_xp_mpic_secondary_init(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) {
armada_xp_mpic_perf_init();
armada_xp_mpic_smp_cpu_init();
}

return NOTIFY_OK;
}
Expand All @@ -369,8 +395,10 @@ static struct notifier_block armada_370_xp_mpic_cpu_notifier = {
static int mpic_cascaded_secondary_init(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) {
armada_xp_mpic_perf_init();
enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);
}

return NOTIFY_OK;
}
Expand All @@ -379,7 +407,6 @@ static struct notifier_block mpic_cascaded_cpu_notifier = {
.notifier_call = mpic_cascaded_secondary_init,
.priority = 100,
};

#endif /* CONFIG_SMP */

static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
Expand Down Expand Up @@ -588,9 +615,9 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,

BUG_ON(!armada_370_xp_mpic_domain);

#ifdef CONFIG_SMP
/* Setup for the boot CPU */
armada_xp_mpic_perf_init();
armada_xp_mpic_smp_cpu_init();
#endif

armada_370_xp_msi_init(node, main_int_res.start);

Expand Down
4 changes: 2 additions & 2 deletions drivers/irqchip/irq-digicolor.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ static void __exception_irq_entry digicolor_handle_irq(struct pt_regs *regs)
} while (1);
}

static void digicolor_set_gc(void __iomem *reg_base, unsigned irq_base,
unsigned en_reg, unsigned ack_reg)
static void __init digicolor_set_gc(void __iomem *reg_base, unsigned irq_base,
unsigned en_reg, unsigned ack_reg)
{
struct irq_chip_generic *gc;

Expand Down
2 changes: 1 addition & 1 deletion drivers/irqchip/irq-gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic)
break;
}

if (!mask)
if (!mask && num_possible_cpus() > 1)
pr_crit("GIC CPU mask not found - kernel will fail to boot.\n");

return mask;
Expand Down
21 changes: 21 additions & 0 deletions drivers/irqchip/irq-mips-gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,27 @@ cycle_t gic_read_compare(void)

return (((cycle_t) hi) << 32) + lo;
}

void gic_start_count(void)
{
u32 gicconfig;

/* Start the counter */
gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG));
gicconfig &= ~(1 << GIC_SH_CONFIG_COUNTSTOP_SHF);
gic_write(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
}

void gic_stop_count(void)
{
u32 gicconfig;

/* Stop the counter */
gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG));
gicconfig |= 1 << GIC_SH_CONFIG_COUNTSTOP_SHF;
gic_write(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
}

#endif

static bool gic_local_irq_is_routable(int intr)
Expand Down
Loading

0 comments on commit 425b655

Please sign in to comment.