mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-15 13:22:55 +00:00
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irqchip updates from Ingo Molnar: "Various irqchip driver updates, plus a genirq core update that allows the initial spreading of irqs amonst CPUs without having to do it from user-space" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: genirq: Fix null pointer reference in irq_set_affinity_hint() irqchip: gic: Allow interrupt level to be set for PPIs irqchip: mips-gic: Handle pending interrupts once in __gic_irq_dispatch() irqchip: Conexant CX92755 interrupts controller driver irqchip: Devicetree: document Conexant Digicolor irq binding irqchip: omap-intc: Remove unused legacy interface for omap2 irqchip: omap-intc: Fix support for dm814 and dm816 irqchip: mtk-sysirq: Get irq number from register resource size irqchip: renesas-intc-irqpin: r8a7779 IRLM setup support genirq: Set initial affinity in irq_set_affinity_hint()
This commit is contained in:
commit
3c6847eaa3
@ -32,12 +32,16 @@ Main node required properties:
|
||||
The 3rd cell is the flags, encoded as follows:
|
||||
bits[3:0] trigger type and level flags.
|
||||
1 = low-to-high edge triggered
|
||||
2 = high-to-low edge triggered
|
||||
2 = high-to-low edge triggered (invalid for SPIs)
|
||||
4 = active high level-sensitive
|
||||
8 = active low level-sensitive
|
||||
8 = active low level-sensitive (invalid for SPIs).
|
||||
bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of
|
||||
the 8 possible cpus attached to the GIC. A bit set to '1' indicated
|
||||
the interrupt is wired to that CPU. Only valid for PPI interrupts.
|
||||
Also note that the configurability of PPI interrupts is IMPLEMENTATION
|
||||
DEFINED and as such not guaranteed to be present (most SoC available
|
||||
in 2014 seem to ignore the setting of this flag and use the hardware
|
||||
default value).
|
||||
|
||||
- reg : Specifies base physical address(s) and size of the GIC registers. The
|
||||
first region is the GIC distributor register base and size. The 2nd region is
|
||||
|
@ -0,0 +1,21 @@
|
||||
Conexant Digicolor Interrupt Controller
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "cnxt,cx92755-ic"
|
||||
- reg : Specifies base physical address and size of the interrupt controller
|
||||
registers (IC) area
|
||||
- interrupt-controller : Identifies the node as an interrupt controller
|
||||
- #interrupt-cells : Specifies the number of cells needed to encode an
|
||||
interrupt source. The value shall be 1.
|
||||
- syscon: A phandle to the syscon node describing UC registers
|
||||
|
||||
Example:
|
||||
|
||||
intc: interrupt-controller@f0000040 {
|
||||
compatible = "cnxt,cx92755-ic";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <0xf0000040 0x40>;
|
||||
syscon = <&uc_regs>;
|
||||
};
|
@ -9,6 +9,11 @@ Required properties:
|
||||
- "renesas,intc-irqpin-r8a7778" (R-Car M1A)
|
||||
- "renesas,intc-irqpin-r8a7779" (R-Car H1)
|
||||
- "renesas,intc-irqpin-sh73a0" (SH-Mobile AG5)
|
||||
|
||||
- reg: Base address and length of each register bank used by the external
|
||||
IRQ pins driven by the interrupt controller hardware module. The base
|
||||
addresses, length and number of required register banks varies with soctype.
|
||||
|
||||
- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
|
||||
interrupts.txt in this directory
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
Omap2/3 intc controller
|
||||
|
||||
On TI omap2 and 3 the intc interrupt controller can provide
|
||||
96 or 128 IRQ signals to the ARM host depending on the SoC.
|
||||
|
||||
Required Properties:
|
||||
- compatible: should be one of
|
||||
"ti,omap2-intc"
|
||||
"ti,omap3-intc"
|
||||
"ti,dm814-intc"
|
||||
"ti,dm816-intc"
|
||||
"ti,am33xx-intc"
|
||||
|
||||
- interrupt-controller : Identifies the node as an interrupt controller
|
||||
- #interrupt-cells : Specifies the number of cells needed to encode interrupt
|
||||
source, should be 1 for intc
|
||||
- interrupts: interrupt reference to primary interrupt controller
|
||||
|
||||
Please refer to interrupts.txt in this directory for details of the common
|
||||
Interrupt Controllers bindings used by client devices.
|
||||
|
||||
Example:
|
||||
intc: interrupt-controller@48200000 {
|
||||
compatible = "ti,omap3-intc";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <0x48200000 0x1000>;
|
||||
};
|
@ -42,3 +42,4 @@ obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o
|
||||
obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o
|
||||
obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o
|
||||
obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o
|
||||
obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o
|
||||
|
120
drivers/irqchip/irq-digicolor.c
Normal file
120
drivers/irqchip/irq-digicolor.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Conexant Digicolor SoCs IRQ chip driver
|
||||
*
|
||||
* Author: Baruch Siach <baruch@tkos.co.il>
|
||||
*
|
||||
* Copyright (C) 2014 Paradox Innovation Ltd.
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <asm/exception.h>
|
||||
|
||||
#include "irqchip.h"
|
||||
|
||||
#define UC_IRQ_CONTROL 0x04
|
||||
|
||||
#define IC_FLAG_CLEAR_LO 0x00
|
||||
#define IC_FLAG_CLEAR_XLO 0x04
|
||||
#define IC_INT0ENABLE_LO 0x10
|
||||
#define IC_INT0ENABLE_XLO 0x14
|
||||
#define IC_INT0STATUS_LO 0x18
|
||||
#define IC_INT0STATUS_XLO 0x1c
|
||||
|
||||
static struct irq_domain *digicolor_irq_domain;
|
||||
|
||||
static void __exception_irq_entry digicolor_handle_irq(struct pt_regs *regs)
|
||||
{
|
||||
struct irq_domain_chip_generic *dgc = digicolor_irq_domain->gc;
|
||||
struct irq_chip_generic *gc = dgc->gc[0];
|
||||
u32 status, hwirq;
|
||||
|
||||
do {
|
||||
status = irq_reg_readl(gc, IC_INT0STATUS_LO);
|
||||
if (status) {
|
||||
hwirq = ffs(status) - 1;
|
||||
} else {
|
||||
status = irq_reg_readl(gc, IC_INT0STATUS_XLO);
|
||||
if (status)
|
||||
hwirq = ffs(status) - 1 + 32;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
handle_domain_irq(digicolor_irq_domain, hwirq, regs);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static void digicolor_set_gc(void __iomem *reg_base, unsigned irq_base,
|
||||
unsigned en_reg, unsigned ack_reg)
|
||||
{
|
||||
struct irq_chip_generic *gc;
|
||||
|
||||
gc = irq_get_domain_generic_chip(digicolor_irq_domain, irq_base);
|
||||
gc->reg_base = reg_base;
|
||||
gc->chip_types[0].regs.ack = ack_reg;
|
||||
gc->chip_types[0].regs.mask = en_reg;
|
||||
gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
|
||||
gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
|
||||
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
|
||||
}
|
||||
|
||||
static int __init digicolor_of_init(struct device_node *node,
|
||||
struct device_node *parent)
|
||||
{
|
||||
static void __iomem *reg_base;
|
||||
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
|
||||
struct regmap *ucregs;
|
||||
int ret;
|
||||
|
||||
reg_base = of_iomap(node, 0);
|
||||
if (!reg_base) {
|
||||
pr_err("%s: unable to map IC registers\n", node->full_name);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* disable all interrupts */
|
||||
writel(0, reg_base + IC_INT0ENABLE_LO);
|
||||
writel(0, reg_base + IC_INT0ENABLE_XLO);
|
||||
|
||||
ucregs = syscon_regmap_lookup_by_phandle(node, "syscon");
|
||||
if (IS_ERR(ucregs)) {
|
||||
pr_err("%s: unable to map UC registers\n", node->full_name);
|
||||
return PTR_ERR(ucregs);
|
||||
}
|
||||
/* channel 1, regular IRQs */
|
||||
regmap_write(ucregs, UC_IRQ_CONTROL, 1);
|
||||
|
||||
digicolor_irq_domain =
|
||||
irq_domain_add_linear(node, 64, &irq_generic_chip_ops, NULL);
|
||||
if (!digicolor_irq_domain) {
|
||||
pr_err("%s: unable to create IRQ domain\n", node->full_name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = irq_alloc_domain_generic_chips(digicolor_irq_domain, 32, 1,
|
||||
"digicolor_irq", handle_level_irq,
|
||||
clr, 0, 0);
|
||||
if (ret) {
|
||||
pr_err("%s: unable to allocate IRQ gc\n", node->full_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
digicolor_set_gc(reg_base, 0, IC_INT0ENABLE_LO, IC_FLAG_CLEAR_LO);
|
||||
digicolor_set_gc(reg_base, 32, IC_INT0ENABLE_XLO, IC_FLAG_CLEAR_XLO);
|
||||
|
||||
set_handle_irq(digicolor_handle_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
IRQCHIP_DECLARE(conexant_digicolor_ic, "cnxt,cx92755-ic", digicolor_of_init);
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include "irq-gic-common.h"
|
||||
|
||||
void gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
int gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
void __iomem *base, void (*sync_access)(void))
|
||||
{
|
||||
u32 enablemask = 1 << (irq % 32);
|
||||
@ -29,16 +29,17 @@ void gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
u32 confmask = 0x2 << ((irq % 16) * 2);
|
||||
u32 confoff = (irq / 16) * 4;
|
||||
bool enabled = false;
|
||||
u32 val;
|
||||
u32 val, oldval;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Read current configuration register, and insert the config
|
||||
* for "irq", depending on "type".
|
||||
*/
|
||||
val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
|
||||
if (type == IRQ_TYPE_LEVEL_HIGH)
|
||||
val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
|
||||
if (type & IRQ_TYPE_LEVEL_MASK)
|
||||
val &= ~confmask;
|
||||
else if (type == IRQ_TYPE_EDGE_RISING)
|
||||
else if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
val |= confmask;
|
||||
|
||||
/*
|
||||
@ -54,15 +55,20 @@ void gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
|
||||
/*
|
||||
* Write back the new configuration, and possibly re-enable
|
||||
* the interrupt.
|
||||
* the interrupt. If we tried to write a new configuration and failed,
|
||||
* return an error.
|
||||
*/
|
||||
writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
|
||||
if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val && val != oldval)
|
||||
ret = -EINVAL;
|
||||
|
||||
if (enabled)
|
||||
writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
|
||||
|
||||
if (sync_access)
|
||||
sync_access();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __init gic_dist_config(void __iomem *base, int gic_irqs,
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
void gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
int gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
void __iomem *base, void (*sync_access)(void));
|
||||
void gic_dist_config(void __iomem *base, int gic_irqs,
|
||||
void (*sync_access)(void));
|
||||
|
@ -238,7 +238,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
|
||||
if (irq < 16)
|
||||
return -EINVAL;
|
||||
|
||||
if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
|
||||
/* SPIs have restrictions on the supported types */
|
||||
if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
|
||||
type != IRQ_TYPE_EDGE_RISING)
|
||||
return -EINVAL;
|
||||
|
||||
if (gic_irq_in_rdist(d)) {
|
||||
@ -249,9 +251,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
|
||||
rwp_wait = gic_dist_wait_for_rwp;
|
||||
}
|
||||
|
||||
gic_configure_irq(irq, type, base, rwp_wait);
|
||||
|
||||
return 0;
|
||||
return gic_configure_irq(irq, type, base, rwp_wait);
|
||||
}
|
||||
|
||||
static u64 gic_mpidr_to_affinity(u64 mpidr)
|
||||
|
@ -188,12 +188,15 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
void __iomem *base = gic_dist_base(d);
|
||||
unsigned int gicirq = gic_irq(d);
|
||||
int ret;
|
||||
|
||||
/* Interrupt configuration for SGIs can't be changed */
|
||||
if (gicirq < 16)
|
||||
return -EINVAL;
|
||||
|
||||
if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
|
||||
/* SPIs have restrictions on the supported types */
|
||||
if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
|
||||
type != IRQ_TYPE_EDGE_RISING)
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&irq_controller_lock);
|
||||
@ -201,11 +204,11 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
|
||||
if (gic_arch_extn.irq_set_type)
|
||||
gic_arch_extn.irq_set_type(d, type);
|
||||
|
||||
gic_configure_irq(gicirq, type, base, NULL);
|
||||
ret = gic_configure_irq(gicirq, type, base, NULL);
|
||||
|
||||
raw_spin_unlock(&irq_controller_lock);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gic_retrigger(struct irq_data *d)
|
||||
|
@ -120,21 +120,24 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
void __iomem *base = hip04_dist_base(d);
|
||||
unsigned int irq = hip04_irq(d);
|
||||
int ret;
|
||||
|
||||
/* Interrupt configuration for SGIs can't be changed */
|
||||
if (irq < 16)
|
||||
return -EINVAL;
|
||||
|
||||
if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
|
||||
/* SPIs have restrictions on the supported types */
|
||||
if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
|
||||
type != IRQ_TYPE_EDGE_RISING)
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&irq_controller_lock);
|
||||
|
||||
gic_configure_irq(irq, type, base, NULL);
|
||||
ret = gic_configure_irq(irq, type, base, NULL);
|
||||
|
||||
raw_spin_unlock(&irq_controller_lock);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -235,9 +235,9 @@ int gic_get_c0_perfcount_int(void)
|
||||
GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR));
|
||||
}
|
||||
|
||||
static unsigned int gic_get_int(void)
|
||||
static void gic_handle_shared_int(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int i, intr, virq;
|
||||
unsigned long *pcpu_mask;
|
||||
unsigned long pending_reg, intrmask_reg;
|
||||
DECLARE_BITMAP(pending, GIC_MAX_INTRS);
|
||||
@ -259,7 +259,16 @@ static unsigned int gic_get_int(void)
|
||||
bitmap_and(pending, pending, intrmask, gic_shared_intrs);
|
||||
bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs);
|
||||
|
||||
return find_first_bit(pending, gic_shared_intrs);
|
||||
intr = find_first_bit(pending, gic_shared_intrs);
|
||||
while (intr != gic_shared_intrs) {
|
||||
virq = irq_linear_revmap(gic_irq_domain,
|
||||
GIC_SHARED_TO_HWIRQ(intr));
|
||||
do_IRQ(virq);
|
||||
|
||||
/* go to next pending bit */
|
||||
bitmap_clear(pending, intr, 1);
|
||||
intr = find_first_bit(pending, gic_shared_intrs);
|
||||
}
|
||||
}
|
||||
|
||||
static void gic_mask_irq(struct irq_data *d)
|
||||
@ -386,16 +395,26 @@ static struct irq_chip gic_edge_irq_controller = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static unsigned int gic_get_local_int(void)
|
||||
static void gic_handle_local_int(void)
|
||||
{
|
||||
unsigned long pending, masked;
|
||||
unsigned int intr, virq;
|
||||
|
||||
pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
|
||||
masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
|
||||
|
||||
bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
|
||||
|
||||
return find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
|
||||
intr = find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
|
||||
while (intr != GIC_NUM_LOCAL_INTRS) {
|
||||
virq = irq_linear_revmap(gic_irq_domain,
|
||||
GIC_LOCAL_TO_HWIRQ(intr));
|
||||
do_IRQ(virq);
|
||||
|
||||
/* go to next pending bit */
|
||||
bitmap_clear(&pending, intr, 1);
|
||||
intr = find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
|
||||
}
|
||||
}
|
||||
|
||||
static void gic_mask_local_irq(struct irq_data *d)
|
||||
@ -454,19 +473,8 @@ static struct irq_chip gic_all_vpes_local_irq_controller = {
|
||||
|
||||
static void __gic_irq_dispatch(void)
|
||||
{
|
||||
unsigned int intr, virq;
|
||||
|
||||
while ((intr = gic_get_local_int()) != GIC_NUM_LOCAL_INTRS) {
|
||||
virq = irq_linear_revmap(gic_irq_domain,
|
||||
GIC_LOCAL_TO_HWIRQ(intr));
|
||||
do_IRQ(virq);
|
||||
}
|
||||
|
||||
while ((intr = gic_get_int()) != gic_shared_intrs) {
|
||||
virq = irq_linear_revmap(gic_irq_domain,
|
||||
GIC_SHARED_TO_HWIRQ(intr));
|
||||
do_IRQ(virq);
|
||||
}
|
||||
gic_handle_local_int();
|
||||
gic_handle_shared_int();
|
||||
}
|
||||
|
||||
static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc)
|
||||
|
@ -23,8 +23,6 @@
|
||||
|
||||
#include "irqchip.h"
|
||||
|
||||
#define MT6577_SYS_INTPOL_NUM (224)
|
||||
|
||||
struct mtk_sysirq_chip_data {
|
||||
spinlock_t lock;
|
||||
void __iomem *intpol_base;
|
||||
@ -124,7 +122,8 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
|
||||
{
|
||||
struct irq_domain *domain, *domain_parent;
|
||||
struct mtk_sysirq_chip_data *chip_data;
|
||||
int ret = 0;
|
||||
int ret, size, intpol_num;
|
||||
struct resource res;
|
||||
|
||||
domain_parent = irq_find_host(parent);
|
||||
if (!domain_parent) {
|
||||
@ -132,19 +131,24 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(node, 0, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
|
||||
if (!chip_data)
|
||||
return -ENOMEM;
|
||||
|
||||
chip_data->intpol_base = of_io_request_and_map(node, 0, "intpol");
|
||||
if (IS_ERR(chip_data->intpol_base)) {
|
||||
size = resource_size(&res);
|
||||
intpol_num = size * 8;
|
||||
chip_data->intpol_base = ioremap(res.start, size);
|
||||
if (!chip_data->intpol_base) {
|
||||
pr_err("mtk_sysirq: unable to map sysirq register\n");
|
||||
ret = PTR_ERR(chip_data->intpol_base);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
domain = irq_domain_add_hierarchy(domain_parent, 0,
|
||||
MT6577_SYS_INTPOL_NUM, node,
|
||||
domain = irq_domain_add_hierarchy(domain_parent, 0, intpol_num, node,
|
||||
&sysirq_domain_ops, chip_data);
|
||||
if (!domain) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -364,14 +364,6 @@ out:
|
||||
omap_ack_irq(NULL);
|
||||
}
|
||||
|
||||
void __init omap2_init_irq(void)
|
||||
{
|
||||
omap_nr_irqs = 96;
|
||||
omap_nr_pending = 3;
|
||||
omap_init_irq(OMAP24XX_IC_BASE, NULL);
|
||||
set_handle_irq(omap_intc_handle_irq);
|
||||
}
|
||||
|
||||
void __init omap3_init_irq(void)
|
||||
{
|
||||
omap_nr_irqs = 96;
|
||||
@ -380,14 +372,6 @@ void __init omap3_init_irq(void)
|
||||
set_handle_irq(omap_intc_handle_irq);
|
||||
}
|
||||
|
||||
void __init ti81xx_init_irq(void)
|
||||
{
|
||||
omap_nr_irqs = 96;
|
||||
omap_nr_pending = 4;
|
||||
omap_init_irq(OMAP34XX_IC_BASE, NULL);
|
||||
set_handle_irq(omap_intc_handle_irq);
|
||||
}
|
||||
|
||||
static int __init intc_of_init(struct device_node *node,
|
||||
struct device_node *parent)
|
||||
{
|
||||
@ -399,7 +383,9 @@ static int __init intc_of_init(struct device_node *node,
|
||||
if (WARN_ON(!node))
|
||||
return -ENODEV;
|
||||
|
||||
if (of_device_is_compatible(node, "ti,am33xx-intc")) {
|
||||
if (of_device_is_compatible(node, "ti,dm814-intc") ||
|
||||
of_device_is_compatible(node, "ti,dm816-intc") ||
|
||||
of_device_is_compatible(node, "ti,am33xx-intc")) {
|
||||
omap_nr_irqs = 128;
|
||||
omap_nr_pending = 4;
|
||||
}
|
||||
@ -415,4 +401,6 @@ static int __init intc_of_init(struct device_node *node,
|
||||
|
||||
IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init);
|
||||
IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init);
|
||||
IRQCHIP_DECLARE(dm814x_intc, "ti,dm814-intc", intc_of_init);
|
||||
IRQCHIP_DECLARE(dm816x_intc, "ti,dm816-intc", intc_of_init);
|
||||
IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init);
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_data/irq-renesas-intc-irqpin.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
@ -40,7 +41,9 @@
|
||||
#define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */
|
||||
#define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */
|
||||
#define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */
|
||||
#define INTC_IRQPIN_REG_NR 5
|
||||
#define INTC_IRQPIN_REG_NR_MANDATORY 5
|
||||
#define INTC_IRQPIN_REG_IRLM 5 /* ICR0 with IRLM bit (optional) */
|
||||
#define INTC_IRQPIN_REG_NR 6
|
||||
|
||||
/* INTC external IRQ PIN hardware register access:
|
||||
*
|
||||
@ -82,6 +85,10 @@ struct intc_irqpin_priv {
|
||||
u8 shared_irq_mask;
|
||||
};
|
||||
|
||||
struct intc_irqpin_irlm_config {
|
||||
unsigned int irlm_bit;
|
||||
};
|
||||
|
||||
static unsigned long intc_irqpin_read32(void __iomem *iomem)
|
||||
{
|
||||
return ioread32(iomem);
|
||||
@ -345,10 +352,23 @@ static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
static const struct intc_irqpin_irlm_config intc_irqpin_irlm_r8a7779 = {
|
||||
.irlm_bit = 23, /* ICR0.IRLM0 */
|
||||
};
|
||||
|
||||
static const struct of_device_id intc_irqpin_dt_ids[] = {
|
||||
{ .compatible = "renesas,intc-irqpin", },
|
||||
{ .compatible = "renesas,intc-irqpin-r8a7779",
|
||||
.data = &intc_irqpin_irlm_r8a7779 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
|
||||
|
||||
static int intc_irqpin_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct renesas_intc_irqpin_config *pdata = dev->platform_data;
|
||||
const struct of_device_id *of_id;
|
||||
struct intc_irqpin_priv *p;
|
||||
struct intc_irqpin_iomem *i;
|
||||
struct resource *io[INTC_IRQPIN_REG_NR];
|
||||
@ -391,10 +411,11 @@ static int intc_irqpin_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
/* get hold of manadatory IOMEM */
|
||||
/* get hold of register banks */
|
||||
memset(io, 0, sizeof(io));
|
||||
for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
|
||||
io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k);
|
||||
if (!io[k]) {
|
||||
if (!io[k] && k < INTC_IRQPIN_REG_NR_MANDATORY) {
|
||||
dev_err(dev, "not enough IOMEM resources\n");
|
||||
ret = -EINVAL;
|
||||
goto err0;
|
||||
@ -422,6 +443,10 @@ static int intc_irqpin_probe(struct platform_device *pdev)
|
||||
for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
|
||||
i = &p->iomem[k];
|
||||
|
||||
/* handle optional registers */
|
||||
if (!io[k])
|
||||
continue;
|
||||
|
||||
switch (resource_size(io[k])) {
|
||||
case 1:
|
||||
i->width = 8;
|
||||
@ -448,6 +473,19 @@ static int intc_irqpin_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
/* configure "individual IRQ mode" where needed */
|
||||
of_id = of_match_device(intc_irqpin_dt_ids, dev);
|
||||
if (of_id && of_id->data) {
|
||||
const struct intc_irqpin_irlm_config *irlm_config = of_id->data;
|
||||
|
||||
if (io[INTC_IRQPIN_REG_IRLM])
|
||||
intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_IRLM,
|
||||
irlm_config->irlm_bit,
|
||||
1, 1);
|
||||
else
|
||||
dev_warn(dev, "unable to select IRLM mode\n");
|
||||
}
|
||||
|
||||
/* mask all interrupts using priority */
|
||||
for (k = 0; k < p->number_of_irqs; k++)
|
||||
intc_irqpin_mask_unmask_prio(p, k, 1);
|
||||
@ -550,12 +588,6 @@ static int intc_irqpin_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id intc_irqpin_dt_ids[] = {
|
||||
{ .compatible = "renesas,intc-irqpin", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
|
||||
|
||||
static struct platform_driver intc_irqpin_device_driver = {
|
||||
.probe = intc_irqpin_probe,
|
||||
.remove = intc_irqpin_remove,
|
||||
|
@ -18,9 +18,7 @@
|
||||
#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_OMAP_INTC_H
|
||||
#define __INCLUDE_LINUX_IRQCHIP_IRQ_OMAP_INTC_H
|
||||
|
||||
void omap2_init_irq(void);
|
||||
void omap3_init_irq(void);
|
||||
void ti81xx_init_irq(void);
|
||||
|
||||
int omap_irq_pending(void);
|
||||
void omap_intc_save_context(void);
|
||||
|
@ -243,6 +243,9 @@ int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
|
||||
return -EINVAL;
|
||||
desc->affinity_hint = m;
|
||||
irq_put_desc_unlock(desc, flags);
|
||||
/* set the initial affinity to prevent every interrupt being on CPU0 */
|
||||
if (m)
|
||||
__irq_set_affinity(irq, m, false);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_set_affinity_hint);
|
||||
|
Loading…
Reference in New Issue
Block a user