mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq updates from Thomas Gleixner: "The irq departement delivers: - plug a potential race related to chained interrupt handlers - core updates which address the needs of the x86 irqdomain conversion - new irqchip callback to support affinity settings for VCPUs - the usual pile of updates to interrupt chip drivers - a few helper functions to allow further cleanups and simplifications I have a largish pile of coccinelle scripted/verified cleanups and simplifications pending on top of that, but I prefer to send that towards the end of the merge window when the arch/driver changes have hit your tree to avoid API change wreckage as far as possible" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (34 commits) genirq: Remove bogus restriction in irq_move_mask_irq() irqchip: atmel-aic5: Add sama5d2 support irq: spear-shirq: Fix race in installing chained IRQ handler irq: irq-keystone: Fix race in installing chained IRQ handler gpio: gpio-tegra: Fix race in installing chained IRQ handler gpio: gpio-mxs: Fix race in installing chained IRQ handler gpio: gpio-mxc: Fix race in installing chained IRQ handler ARM: gemini: Fix race in installing GPIO chained IRQ handler GPU: ipu: Fix race in installing IPU chained IRQ handler ARM: sa1100: convert SA11x0 related code to use new chained handler helper irq: Add irq_set_chained_handler_and_data() irqchip: exynos-combiner: Save IRQ enable set on suspend genirq: Introduce helper function irq_data_get_affinity_mask() genirq: Introduce helper function irq_data_get_node() genirq: Introduce struct irq_common_data to host shared irq data genirq: Prevent crash in irq_move_irq() genirq: Enhance irq_data_to_desc() to support hierarchy irqdomain irqchip: gic: Simplify gic_configure_irq by using IRQCHIP_SET_TYPE_MASKED irqchip: renesas: intc-irqpin: Improve binding documentation genirq: Set IRQCHIP_SKIP_SET_WAKE for no_irq_chip ...
This commit is contained in:
commit
407a2c7205
@ -2,7 +2,7 @@
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "atmel,<chip>-aic"
|
||||
<chip> can be "at91rm9200", "sama5d3" or "sama5d4"
|
||||
<chip> can be "at91rm9200", "sama5d2", "sama5d3" or "sama5d4"
|
||||
- interrupt-controller: Identifies the node as an interrupt controller.
|
||||
- interrupt-parent: For single AIC system, it is an empty property.
|
||||
- #interrupt-cells: The number of cells to define the interrupts. It should be 3.
|
||||
|
@ -13,9 +13,12 @@ Required properties:
|
||||
- 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-controller: Identifies the node as an interrupt controller.
|
||||
- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
|
||||
interrupts.txt in this directory
|
||||
interrupts.txt in this directory.
|
||||
- interrupts: Must contain a list of interrupt specifiers. For each interrupt
|
||||
provided by this irqpin controller instance, there must be one entry,
|
||||
referring to the corresponding parent interrupt.
|
||||
|
||||
Optional properties:
|
||||
|
||||
@ -25,3 +28,35 @@ Optional properties:
|
||||
if different from the default 4 bits
|
||||
- control-parent: disable and enable interrupts on the parent interrupt
|
||||
controller, needed for some broken implementations
|
||||
- clocks: Must contain a reference to the functional clock. This property is
|
||||
mandatory if the hardware implements a controllable functional clock for
|
||||
the irqpin controller instance.
|
||||
- power-domains: Must contain a reference to the power domain. This property is
|
||||
mandatory if the irqpin controller instance is part of a controllable power
|
||||
domain.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
irqpin1: interrupt-controller@e6900004 {
|
||||
compatible = "renesas,intc-irqpin-r8a7740",
|
||||
"renesas,intc-irqpin";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <0xe6900004 4>,
|
||||
<0xe6900014 4>,
|
||||
<0xe6900024 1>,
|
||||
<0xe6900044 1>,
|
||||
<0xe6900064 1>;
|
||||
interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH
|
||||
0 149 IRQ_TYPE_LEVEL_HIGH
|
||||
0 149 IRQ_TYPE_LEVEL_HIGH
|
||||
0 149 IRQ_TYPE_LEVEL_HIGH
|
||||
0 149 IRQ_TYPE_LEVEL_HIGH
|
||||
0 149 IRQ_TYPE_LEVEL_HIGH
|
||||
0 149 IRQ_TYPE_LEVEL_HIGH
|
||||
0 149 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&mstp2_clks R8A7740_CLK_INTCA>;
|
||||
power-domains = <&pd_a4s>;
|
||||
};
|
||||
|
@ -501,8 +501,8 @@ static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
|
||||
* Register SA1111 interrupt
|
||||
*/
|
||||
irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
|
||||
irq_set_handler_data(sachip->irq, sachip);
|
||||
irq_set_chained_handler(sachip->irq, sa1111_irq_handler);
|
||||
irq_set_chained_handler_and_data(sachip->irq, sa1111_irq_handler,
|
||||
sachip);
|
||||
|
||||
dev_info(sachip->dev, "Providing IRQ%u-%u\n",
|
||||
sachip->irq_base, sachip->irq_base + SA1111_IRQ_NR - 1);
|
||||
@ -836,8 +836,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
|
||||
clk_unprepare(sachip->clk);
|
||||
|
||||
if (sachip->irq != NO_IRQ) {
|
||||
irq_set_chained_handler(sachip->irq, NULL);
|
||||
irq_set_handler_data(sachip->irq, NULL);
|
||||
irq_set_chained_handler_and_data(sachip->irq, NULL, NULL);
|
||||
irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
|
||||
|
||||
release_mem_region(sachip->phys + SA1111_INTC, 512);
|
||||
|
@ -223,8 +223,8 @@ void __init gemini_gpio_init(void)
|
||||
set_irq_flags(j, IRQF_VALID);
|
||||
}
|
||||
|
||||
irq_set_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
|
||||
irq_set_handler_data(IRQ_GPIO(i), (void *)i);
|
||||
irq_set_chained_handler_and_data(IRQ_GPIO(i), gpio_irq_handler,
|
||||
(void *)i);
|
||||
}
|
||||
|
||||
BUG_ON(gpiochip_add(&gemini_gpio_chip));
|
||||
|
@ -327,8 +327,7 @@ static int neponset_probe(struct platform_device *dev)
|
||||
irq_set_chip(d->irq_base + NEP_IRQ_SA1111, &nochip);
|
||||
|
||||
irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
|
||||
irq_set_handler_data(irq, d);
|
||||
irq_set_chained_handler(irq, neponset_irq_handler);
|
||||
irq_set_chained_handler_and_data(irq, neponset_irq_handler, d);
|
||||
|
||||
/*
|
||||
* We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
|
||||
|
@ -437,14 +437,13 @@ static int mxc_gpio_probe(struct platform_device *pdev)
|
||||
irq_set_chained_handler(port->irq, mx2_gpio_irq_handler);
|
||||
} else {
|
||||
/* setup one handler for each entry */
|
||||
irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
|
||||
irq_set_handler_data(port->irq, port);
|
||||
if (port->irq_high > 0) {
|
||||
irq_set_chained_handler_and_data(port->irq,
|
||||
mx3_gpio_irq_handler, port);
|
||||
if (port->irq_high > 0)
|
||||
/* setup handler for GPIO 16 to 31 */
|
||||
irq_set_chained_handler(port->irq_high,
|
||||
mx3_gpio_irq_handler);
|
||||
irq_set_handler_data(port->irq_high, port);
|
||||
}
|
||||
irq_set_chained_handler_and_data(port->irq_high,
|
||||
mx3_gpio_irq_handler,
|
||||
port);
|
||||
}
|
||||
|
||||
err = bgpio_init(&port->bgc, &pdev->dev, 4,
|
||||
|
@ -320,8 +320,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)
|
||||
mxs_gpio_init_gc(port, irq_base);
|
||||
|
||||
/* setup one handler for each entry */
|
||||
irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
|
||||
irq_set_handler_data(port->irq, port);
|
||||
irq_set_chained_handler_and_data(port->irq, mxs_gpio_irq_handler,
|
||||
port);
|
||||
|
||||
err = bgpio_init(&port->bgc, &pdev->dev, 4,
|
||||
port->base + PINCTRL_DIN(port),
|
||||
|
@ -515,8 +515,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < tegra_gpio_bank_count; i++) {
|
||||
bank = &tegra_gpio_banks[i];
|
||||
|
||||
irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler);
|
||||
irq_set_handler_data(bank->irq, bank);
|
||||
irq_set_chained_handler_and_data(bank->irq,
|
||||
tegra_gpio_irq_handler, bank);
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
spin_lock_init(&bank->lvl_lock[j]);
|
||||
|
@ -1119,10 +1119,9 @@ static int ipu_irq_init(struct ipu_soc *ipu)
|
||||
ct->regs.mask = IPU_INT_CTRL(i / 32);
|
||||
}
|
||||
|
||||
irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler);
|
||||
irq_set_handler_data(ipu->irq_sync, ipu);
|
||||
irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler);
|
||||
irq_set_handler_data(ipu->irq_err, ipu);
|
||||
irq_set_chained_handler_and_data(ipu->irq_sync, ipu_irq_handler, ipu);
|
||||
irq_set_chained_handler_and_data(ipu->irq_err, ipu_err_irq_handler,
|
||||
ipu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1131,10 +1130,8 @@ static void ipu_irq_exit(struct ipu_soc *ipu)
|
||||
{
|
||||
int i, irq;
|
||||
|
||||
irq_set_chained_handler(ipu->irq_err, NULL);
|
||||
irq_set_handler_data(ipu->irq_err, NULL);
|
||||
irq_set_chained_handler(ipu->irq_sync, NULL);
|
||||
irq_set_handler_data(ipu->irq_sync, NULL);
|
||||
irq_set_chained_handler_and_data(ipu->irq_err, NULL, NULL);
|
||||
irq_set_chained_handler_and_data(ipu->irq_sync, NULL, NULL);
|
||||
|
||||
/* TODO: remove irq_domain_generic_chips */
|
||||
|
||||
|
@ -30,6 +30,7 @@ config ARM_GIC_V3_ITS
|
||||
config ARM_NVIC
|
||||
bool
|
||||
select IRQ_DOMAIN
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
select GENERIC_IRQ_CHIP
|
||||
|
||||
config ARM_VIC
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -34,9 +35,14 @@ struct combiner_chip_data {
|
||||
unsigned int irq_mask;
|
||||
void __iomem *base;
|
||||
unsigned int parent_irq;
|
||||
#ifdef CONFIG_PM
|
||||
u32 pm_save;
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct combiner_chip_data *combiner_data;
|
||||
static struct irq_domain *combiner_irq_domain;
|
||||
static unsigned int max_nr = 20;
|
||||
|
||||
static inline void __iomem *combiner_base(struct irq_data *data)
|
||||
{
|
||||
@ -164,18 +170,16 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops combiner_irq_domain_ops = {
|
||||
static const struct irq_domain_ops combiner_irq_domain_ops = {
|
||||
.xlate = combiner_irq_domain_xlate,
|
||||
.map = combiner_irq_domain_map,
|
||||
};
|
||||
|
||||
static void __init combiner_init(void __iomem *combiner_base,
|
||||
struct device_node *np,
|
||||
unsigned int max_nr)
|
||||
struct device_node *np)
|
||||
{
|
||||
int i, irq;
|
||||
unsigned int nr_irq;
|
||||
struct combiner_chip_data *combiner_data;
|
||||
|
||||
nr_irq = max_nr * IRQ_IN_COMBINER;
|
||||
|
||||
@ -201,11 +205,59 @@ static void __init combiner_init(void __iomem *combiner_base,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/**
|
||||
* combiner_suspend - save interrupt combiner state before suspend
|
||||
*
|
||||
* Save the interrupt enable set register for all combiner groups since
|
||||
* the state is lost when the system enters into a sleep state.
|
||||
*
|
||||
*/
|
||||
static int combiner_suspend(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max_nr; i++)
|
||||
combiner_data[i].pm_save =
|
||||
__raw_readl(combiner_data[i].base + COMBINER_ENABLE_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* combiner_resume - restore interrupt combiner state after resume
|
||||
*
|
||||
* Restore the interrupt enable set register for all combiner groups since
|
||||
* the state is lost when the system enters into a sleep state on suspend.
|
||||
*
|
||||
*/
|
||||
static void combiner_resume(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max_nr; i++) {
|
||||
__raw_writel(combiner_data[i].irq_mask,
|
||||
combiner_data[i].base + COMBINER_ENABLE_CLEAR);
|
||||
__raw_writel(combiner_data[i].pm_save,
|
||||
combiner_data[i].base + COMBINER_ENABLE_SET);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#define combiner_suspend NULL
|
||||
#define combiner_resume NULL
|
||||
#endif
|
||||
|
||||
static struct syscore_ops combiner_syscore_ops = {
|
||||
.suspend = combiner_suspend,
|
||||
.resume = combiner_resume,
|
||||
};
|
||||
|
||||
static int __init combiner_of_init(struct device_node *np,
|
||||
struct device_node *parent)
|
||||
{
|
||||
void __iomem *combiner_base;
|
||||
unsigned int max_nr = 20;
|
||||
|
||||
combiner_base = of_iomap(np, 0);
|
||||
if (!combiner_base) {
|
||||
@ -219,7 +271,9 @@ static int __init combiner_of_init(struct device_node *np,
|
||||
__func__, max_nr);
|
||||
}
|
||||
|
||||
combiner_init(combiner_base, np, max_nr);
|
||||
combiner_init(combiner_base, np);
|
||||
|
||||
register_syscore_ops(&combiner_syscore_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -409,7 +409,7 @@ static struct notifier_block mpic_cascaded_cpu_notifier = {
|
||||
};
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
|
||||
static const struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
|
||||
.map = armada_370_xp_mpic_irq_map,
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
|
@ -339,6 +339,15 @@ static int __init aic5_of_init(struct device_node *node,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NR_SAMA5D2_IRQS 77
|
||||
|
||||
static int __init sama5d2_aic5_of_init(struct device_node *node,
|
||||
struct device_node *parent)
|
||||
{
|
||||
return aic5_of_init(node, parent, NR_SAMA5D2_IRQS);
|
||||
}
|
||||
IRQCHIP_DECLARE(sama5d2_aic5, "atmel,sama5d2-aic", sama5d2_aic5_of_init);
|
||||
|
||||
#define NR_SAMA5D3_IRQS 48
|
||||
|
||||
static int __init sama5d3_aic5_of_init(struct device_node *node,
|
||||
|
@ -135,7 +135,7 @@ static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops armctrl_ops = {
|
||||
static const struct irq_domain_ops armctrl_ops = {
|
||||
.xlate = armctrl_xlate
|
||||
};
|
||||
|
||||
|
@ -24,11 +24,8 @@
|
||||
int gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
void __iomem *base, void (*sync_access)(void))
|
||||
{
|
||||
u32 enablemask = 1 << (irq % 32);
|
||||
u32 enableoff = (irq / 32) * 4;
|
||||
u32 confmask = 0x2 << ((irq % 16) * 2);
|
||||
u32 confoff = (irq / 16) * 4;
|
||||
bool enabled = false;
|
||||
u32 val, oldval;
|
||||
int ret = 0;
|
||||
|
||||
@ -42,17 +39,6 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
else if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
val |= confmask;
|
||||
|
||||
/*
|
||||
* As recommended by the spec, disable the interrupt before changing
|
||||
* the configuration
|
||||
*/
|
||||
if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
|
||||
writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
|
||||
if (sync_access)
|
||||
sync_access();
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write back the new configuration, and possibly re-enable
|
||||
* the interrupt. If we tried to write a new configuration and failed,
|
||||
@ -62,9 +48,6 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
|
||||
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();
|
||||
|
||||
|
@ -658,6 +658,7 @@ static struct irq_chip gic_chip = {
|
||||
.irq_set_affinity = gic_set_affinity,
|
||||
.irq_get_irqchip_state = gic_irq_get_irqchip_state,
|
||||
.irq_set_irqchip_state = gic_irq_set_irqchip_state,
|
||||
.flags = IRQCHIP_SET_TYPE_MASKED,
|
||||
};
|
||||
|
||||
#define GIC_ID_NR (1U << gic_data.rdists.id_bits)
|
||||
|
@ -324,6 +324,7 @@ static struct irq_chip gic_chip = {
|
||||
#endif
|
||||
.irq_get_irqchip_state = gic_irq_get_irqchip_state,
|
||||
.irq_set_irqchip_state = gic_irq_set_irqchip_state,
|
||||
.flags = IRQCHIP_SET_TYPE_MASKED,
|
||||
};
|
||||
|
||||
void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
|
||||
|
@ -202,6 +202,7 @@ static struct irq_chip hip04_irq_chip = {
|
||||
#ifdef CONFIG_SMP
|
||||
.irq_set_affinity = hip04_irq_set_affinity,
|
||||
#endif
|
||||
.flags = IRQCHIP_SET_TYPE_MASKED,
|
||||
};
|
||||
|
||||
static u16 hip04_get_cpumask(struct hip04_irq_data *intc)
|
||||
|
@ -131,7 +131,7 @@ static int keystone_irq_map(struct irq_domain *h, unsigned int virq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops keystone_irq_ops = {
|
||||
static const struct irq_domain_ops keystone_irq_ops = {
|
||||
.map = keystone_irq_map,
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
@ -184,8 +184,7 @@ static int keystone_irq_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, kirq);
|
||||
|
||||
irq_set_chained_handler(kirq->irq, keystone_irq_handler);
|
||||
irq_set_handler_data(kirq->irq, kirq);
|
||||
irq_set_chained_handler_and_data(kirq->irq, keystone_irq_handler, kirq);
|
||||
|
||||
/* clear all source bits */
|
||||
keystone_irq_writel(kirq, ~0x0);
|
||||
|
@ -746,7 +746,7 @@ static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops gic_irq_domain_ops = {
|
||||
static const struct irq_domain_ops gic_irq_domain_ops = {
|
||||
.map = gic_irq_domain_map,
|
||||
.xlate = gic_irq_domain_xlate,
|
||||
};
|
||||
|
@ -111,7 +111,7 @@ static int mtk_sysirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops sysirq_domain_ops = {
|
||||
static const struct irq_domain_ops sysirq_domain_ops = {
|
||||
.xlate = mtk_sysirq_domain_xlate,
|
||||
.alloc = mtk_sysirq_domain_alloc,
|
||||
.free = irq_domain_free_irqs_common,
|
||||
@ -144,7 +144,7 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
|
||||
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);
|
||||
ret = -ENXIO;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops icoll_irq_domain_ops = {
|
||||
static const struct irq_domain_ops icoll_irq_domain_ops = {
|
||||
.map = icoll_irq_domain_map,
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
|
@ -49,6 +49,31 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs)
|
||||
handle_IRQ(irq, regs);
|
||||
}
|
||||
|
||||
static int nvic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs, void *arg)
|
||||
{
|
||||
int i, ret;
|
||||
irq_hw_number_t hwirq;
|
||||
unsigned int type = IRQ_TYPE_NONE;
|
||||
struct of_phandle_args *irq_data = arg;
|
||||
|
||||
ret = irq_domain_xlate_onecell(domain, irq_data->np, irq_data->args,
|
||||
irq_data->args_count, &hwirq, &type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < nr_irqs; i++)
|
||||
irq_map_generic_chip(domain, virq + i, hwirq + i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops nvic_irq_domain_ops = {
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
.alloc = nvic_irq_domain_alloc,
|
||||
.free = irq_domain_free_irqs_top,
|
||||
};
|
||||
|
||||
static int __init nvic_of_init(struct device_node *node,
|
||||
struct device_node *parent)
|
||||
{
|
||||
@ -70,7 +95,8 @@ static int __init nvic_of_init(struct device_node *node,
|
||||
irqs = NVIC_MAX_IRQ;
|
||||
|
||||
nvic_irq_domain =
|
||||
irq_domain_add_linear(node, irqs, &irq_generic_chip_ops, NULL);
|
||||
irq_domain_add_linear(node, irqs, &nvic_irq_domain_ops, NULL);
|
||||
|
||||
if (!nvic_irq_domain) {
|
||||
pr_warn("Failed to allocate irq domain\n");
|
||||
return -ENOMEM;
|
||||
|
@ -347,7 +347,7 @@ static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
|
||||
static const struct irq_domain_ops intc_irqpin_irq_domain_ops = {
|
||||
.map = intc_irqpin_irq_domain_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/irq-renesas-irqc.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */
|
||||
@ -62,7 +61,6 @@ struct irqc_priv {
|
||||
void __iomem *iomem;
|
||||
void __iomem *cpu_int_base;
|
||||
struct irqc_irq irq[IRQC_IRQ_MAX];
|
||||
struct renesas_irqc_config config;
|
||||
unsigned int number_of_irqs;
|
||||
struct platform_device *pdev;
|
||||
struct irq_chip irq_chip;
|
||||
@ -168,14 +166,13 @@ static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops irqc_irq_domain_ops = {
|
||||
static const struct irq_domain_ops irqc_irq_domain_ops = {
|
||||
.map = irqc_irq_domain_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
static int irqc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct renesas_irqc_config *pdata = pdev->dev.platform_data;
|
||||
struct irqc_priv *p;
|
||||
struct resource *io;
|
||||
struct resource *irq;
|
||||
@ -191,10 +188,6 @@ static int irqc_probe(struct platform_device *pdev)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* deal with driver instance configuration */
|
||||
if (pdata)
|
||||
memcpy(&p->config, pdata, sizeof(*pdata));
|
||||
|
||||
p->pdev = pdev;
|
||||
platform_set_drvdata(pdev, p);
|
||||
|
||||
@ -251,8 +244,7 @@ static int irqc_probe(struct platform_device *pdev)
|
||||
irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND;
|
||||
|
||||
p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
|
||||
p->number_of_irqs,
|
||||
p->config.irq_base,
|
||||
p->number_of_irqs, 0,
|
||||
&irqc_irq_domain_ops, p);
|
||||
if (!p->irq_domain) {
|
||||
ret = -ENXIO;
|
||||
@ -272,13 +264,6 @@ static int irqc_probe(struct platform_device *pdev)
|
||||
|
||||
dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
|
||||
|
||||
/* warn in case of mismatch if irq base is specified */
|
||||
if (p->config.irq_base) {
|
||||
if (p->config.irq_base != p->irq[0].domain_irq)
|
||||
dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
|
||||
p->config.irq_base, p->irq[0].domain_irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
err3:
|
||||
while (--k >= 0)
|
||||
|
@ -502,7 +502,7 @@ err:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops s3c24xx_irq_ops = {
|
||||
static const struct irq_domain_ops s3c24xx_irq_ops = {
|
||||
.map = s3c24xx_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
@ -1228,7 +1228,7 @@ static int s3c24xx_irq_xlate_of(struct irq_domain *d, struct device_node *n,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops s3c24xx_irq_ops_of = {
|
||||
static const struct irq_domain_ops s3c24xx_irq_ops_of = {
|
||||
.map = s3c24xx_irq_map_of,
|
||||
.xlate = s3c24xx_irq_xlate_of,
|
||||
};
|
||||
|
@ -89,7 +89,7 @@ static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops sun4i_irq_ops = {
|
||||
static const struct irq_domain_ops sun4i_irq_ops = {
|
||||
.map = sun4i_irq_map,
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
|
@ -132,7 +132,7 @@ static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops fpga_irqdomain_ops = {
|
||||
static const struct irq_domain_ops fpga_irqdomain_ops = {
|
||||
.map = fpga_irqdomain_map,
|
||||
.xlate = irq_domain_xlate_onetwocell,
|
||||
};
|
||||
|
@ -47,6 +47,7 @@ struct vf610_mscm_ir_chip_data {
|
||||
void __iomem *mscm_ir_base;
|
||||
u16 cpu_mask;
|
||||
u16 saved_irsprc[MSCM_IRSPRC_NUM];
|
||||
bool is_nvic;
|
||||
};
|
||||
|
||||
static struct vf610_mscm_ir_chip_data *mscm_ir_data;
|
||||
@ -101,7 +102,7 @@ static void vf610_mscm_ir_enable(struct irq_data *data)
|
||||
writew_relaxed(chip_data->cpu_mask,
|
||||
chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq));
|
||||
|
||||
irq_chip_unmask_parent(data);
|
||||
irq_chip_enable_parent(data);
|
||||
}
|
||||
|
||||
static void vf610_mscm_ir_disable(struct irq_data *data)
|
||||
@ -111,7 +112,7 @@ static void vf610_mscm_ir_disable(struct irq_data *data)
|
||||
|
||||
writew_relaxed(0x0, chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq));
|
||||
|
||||
irq_chip_mask_parent(data);
|
||||
irq_chip_disable_parent(data);
|
||||
}
|
||||
|
||||
static struct irq_chip vf610_mscm_ir_irq_chip = {
|
||||
@ -143,10 +144,17 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi
|
||||
domain->host_data);
|
||||
|
||||
gic_data.np = domain->parent->of_node;
|
||||
gic_data.args_count = 3;
|
||||
gic_data.args[0] = GIC_SPI;
|
||||
gic_data.args[1] = irq_data->args[0];
|
||||
gic_data.args[2] = irq_data->args[1];
|
||||
|
||||
if (mscm_ir_data->is_nvic) {
|
||||
gic_data.args_count = 1;
|
||||
gic_data.args[0] = irq_data->args[0];
|
||||
} else {
|
||||
gic_data.args_count = 3;
|
||||
gic_data.args[0] = GIC_SPI;
|
||||
gic_data.args[1] = irq_data->args[0];
|
||||
gic_data.args[2] = irq_data->args[1];
|
||||
}
|
||||
|
||||
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data);
|
||||
}
|
||||
|
||||
@ -174,10 +182,9 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node,
|
||||
return -ENOMEM;
|
||||
|
||||
mscm_ir_data->mscm_ir_base = of_io_request_and_map(node, 0, "mscm-ir");
|
||||
|
||||
if (!mscm_ir_data->mscm_ir_base) {
|
||||
if (IS_ERR(mscm_ir_data->mscm_ir_base)) {
|
||||
pr_err("vf610_mscm_ir: unable to map mscm register\n");
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(mscm_ir_data->mscm_ir_base);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
@ -199,6 +206,9 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node,
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(domain->parent->of_node, "arm,armv7m-nvic"))
|
||||
mscm_ir_data->is_nvic = true;
|
||||
|
||||
cpu_pm_register_notifier(&mscm_ir_notifier_block);
|
||||
|
||||
return 0;
|
||||
|
@ -256,7 +256,7 @@ static void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
|
||||
} while (handled);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops vic_irqdomain_ops = {
|
||||
static const struct irq_domain_ops vic_irqdomain_ops = {
|
||||
.map = vic_irqdomain_map,
|
||||
.xlate = irq_domain_xlate_onetwocell,
|
||||
};
|
||||
|
@ -173,7 +173,7 @@ static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_domain_ops vt8500_irq_domain_ops = {
|
||||
static const struct irq_domain_ops vt8500_irq_domain_ops = {
|
||||
.map = vt8500_irq_map,
|
||||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
|
@ -207,8 +207,7 @@ static void __init spear_shirq_register(struct spear_shirq *shirq,
|
||||
if (!shirq->irq_chip)
|
||||
return;
|
||||
|
||||
irq_set_chained_handler(parent_irq, shirq_handler);
|
||||
irq_set_handler_data(parent_irq, shirq);
|
||||
irq_set_chained_handler_and_data(parent_irq, shirq_handler, shirq);
|
||||
|
||||
for (i = 0; i < shirq->nr_irqs; i++) {
|
||||
irq_set_chip_and_handler(shirq->virq_base + i,
|
||||
|
@ -566,8 +566,7 @@ static int ucb1x00_probe(struct mcp *mcp)
|
||||
}
|
||||
|
||||
irq_set_irq_type(ucb->irq, IRQ_TYPE_EDGE_RISING);
|
||||
irq_set_handler_data(ucb->irq, ucb);
|
||||
irq_set_chained_handler(ucb->irq, ucb1x00_irq);
|
||||
irq_set_chained_handler_and_data(ucb->irq, ucb1x00_irq, ucb);
|
||||
|
||||
if (pdata && pdata->gpio_base) {
|
||||
ucb->gpio.label = dev_name(&ucb->dev);
|
||||
|
@ -126,13 +126,21 @@ struct msi_desc;
|
||||
struct irq_domain;
|
||||
|
||||
/**
|
||||
* struct irq_data - per irq and irq chip data passed down to chip functions
|
||||
* struct irq_common_data - per irq data shared by all irqchips
|
||||
* @state_use_accessors: status information for irq chip functions.
|
||||
* Use accessor functions to deal with it
|
||||
*/
|
||||
struct irq_common_data {
|
||||
unsigned int state_use_accessors;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct irq_data - per irq chip data passed down to chip functions
|
||||
* @mask: precomputed bitmask for accessing the chip registers
|
||||
* @irq: interrupt number
|
||||
* @hwirq: hardware interrupt number, local to the interrupt domain
|
||||
* @node: node index useful for balancing
|
||||
* @state_use_accessors: status information for irq chip functions.
|
||||
* Use accessor functions to deal with it
|
||||
* @common: point to data shared by all irqchips
|
||||
* @chip: low level interrupt hardware access
|
||||
* @domain: Interrupt translation domain; responsible for mapping
|
||||
* between hwirq number and linux irq number.
|
||||
@ -153,7 +161,7 @@ struct irq_data {
|
||||
unsigned int irq;
|
||||
unsigned long hwirq;
|
||||
unsigned int node;
|
||||
unsigned int state_use_accessors;
|
||||
struct irq_common_data *common;
|
||||
struct irq_chip *chip;
|
||||
struct irq_domain *domain;
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
@ -166,7 +174,7 @@ struct irq_data {
|
||||
};
|
||||
|
||||
/*
|
||||
* Bit masks for irq_data.state
|
||||
* Bit masks for irq_common_data.state_use_accessors
|
||||
*
|
||||
* IRQD_TRIGGER_MASK - Mask for the trigger type bits
|
||||
* IRQD_SETAFFINITY_PENDING - Affinity setting is pending
|
||||
@ -198,34 +206,36 @@ enum {
|
||||
IRQD_WAKEUP_ARMED = (1 << 19),
|
||||
};
|
||||
|
||||
#define __irqd_to_state(d) ((d)->common->state_use_accessors)
|
||||
|
||||
static inline bool irqd_is_setaffinity_pending(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_SETAFFINITY_PENDING;
|
||||
return __irqd_to_state(d) & IRQD_SETAFFINITY_PENDING;
|
||||
}
|
||||
|
||||
static inline bool irqd_is_per_cpu(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_PER_CPU;
|
||||
return __irqd_to_state(d) & IRQD_PER_CPU;
|
||||
}
|
||||
|
||||
static inline bool irqd_can_balance(struct irq_data *d)
|
||||
{
|
||||
return !(d->state_use_accessors & (IRQD_PER_CPU | IRQD_NO_BALANCING));
|
||||
return !(__irqd_to_state(d) & (IRQD_PER_CPU | IRQD_NO_BALANCING));
|
||||
}
|
||||
|
||||
static inline bool irqd_affinity_was_set(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_AFFINITY_SET;
|
||||
return __irqd_to_state(d) & IRQD_AFFINITY_SET;
|
||||
}
|
||||
|
||||
static inline void irqd_mark_affinity_was_set(struct irq_data *d)
|
||||
{
|
||||
d->state_use_accessors |= IRQD_AFFINITY_SET;
|
||||
__irqd_to_state(d) |= IRQD_AFFINITY_SET;
|
||||
}
|
||||
|
||||
static inline u32 irqd_get_trigger_type(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_TRIGGER_MASK;
|
||||
return __irqd_to_state(d) & IRQD_TRIGGER_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -233,43 +243,43 @@ static inline u32 irqd_get_trigger_type(struct irq_data *d)
|
||||
*/
|
||||
static inline void irqd_set_trigger_type(struct irq_data *d, u32 type)
|
||||
{
|
||||
d->state_use_accessors &= ~IRQD_TRIGGER_MASK;
|
||||
d->state_use_accessors |= type & IRQD_TRIGGER_MASK;
|
||||
__irqd_to_state(d) &= ~IRQD_TRIGGER_MASK;
|
||||
__irqd_to_state(d) |= type & IRQD_TRIGGER_MASK;
|
||||
}
|
||||
|
||||
static inline bool irqd_is_level_type(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_LEVEL;
|
||||
return __irqd_to_state(d) & IRQD_LEVEL;
|
||||
}
|
||||
|
||||
static inline bool irqd_is_wakeup_set(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_WAKEUP_STATE;
|
||||
return __irqd_to_state(d) & IRQD_WAKEUP_STATE;
|
||||
}
|
||||
|
||||
static inline bool irqd_can_move_in_process_context(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_MOVE_PCNTXT;
|
||||
return __irqd_to_state(d) & IRQD_MOVE_PCNTXT;
|
||||
}
|
||||
|
||||
static inline bool irqd_irq_disabled(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_IRQ_DISABLED;
|
||||
return __irqd_to_state(d) & IRQD_IRQ_DISABLED;
|
||||
}
|
||||
|
||||
static inline bool irqd_irq_masked(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_IRQ_MASKED;
|
||||
return __irqd_to_state(d) & IRQD_IRQ_MASKED;
|
||||
}
|
||||
|
||||
static inline bool irqd_irq_inprogress(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_IRQ_INPROGRESS;
|
||||
return __irqd_to_state(d) & IRQD_IRQ_INPROGRESS;
|
||||
}
|
||||
|
||||
static inline bool irqd_is_wakeup_armed(struct irq_data *d)
|
||||
{
|
||||
return d->state_use_accessors & IRQD_WAKEUP_ARMED;
|
||||
return __irqd_to_state(d) & IRQD_WAKEUP_ARMED;
|
||||
}
|
||||
|
||||
|
||||
@ -280,12 +290,12 @@ static inline bool irqd_is_wakeup_armed(struct irq_data *d)
|
||||
*/
|
||||
static inline void irqd_set_chained_irq_inprogress(struct irq_data *d)
|
||||
{
|
||||
d->state_use_accessors |= IRQD_IRQ_INPROGRESS;
|
||||
__irqd_to_state(d) |= IRQD_IRQ_INPROGRESS;
|
||||
}
|
||||
|
||||
static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
|
||||
{
|
||||
d->state_use_accessors &= ~IRQD_IRQ_INPROGRESS;
|
||||
__irqd_to_state(d) &= ~IRQD_IRQ_INPROGRESS;
|
||||
}
|
||||
|
||||
static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
|
||||
@ -462,6 +472,8 @@ extern void handle_nested_irq(unsigned int irq);
|
||||
|
||||
extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
extern void irq_chip_enable_parent(struct irq_data *data);
|
||||
extern void irq_chip_disable_parent(struct irq_data *data);
|
||||
extern void irq_chip_ack_parent(struct irq_data *data);
|
||||
extern int irq_chip_retrigger_hierarchy(struct irq_data *data);
|
||||
extern void irq_chip_mask_parent(struct irq_data *data);
|
||||
@ -523,6 +535,15 @@ irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
|
||||
__irq_set_handler(irq, handle, 1, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a highlevel chained flow handler and its data for a given IRQ.
|
||||
* (a chained handler is automatically enabled and set to
|
||||
* IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
|
||||
*/
|
||||
void
|
||||
irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
|
||||
void *data);
|
||||
|
||||
void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set);
|
||||
|
||||
static inline void irq_set_status_flags(unsigned int irq, unsigned long set)
|
||||
@ -630,6 +651,23 @@ static inline u32 irq_get_trigger_type(unsigned int irq)
|
||||
return d ? irqd_get_trigger_type(d) : 0;
|
||||
}
|
||||
|
||||
static inline int irq_data_get_node(struct irq_data *d)
|
||||
{
|
||||
return d->node;
|
||||
}
|
||||
|
||||
static inline struct cpumask *irq_get_affinity_mask(int irq)
|
||||
{
|
||||
struct irq_data *d = irq_get_irq_data(irq);
|
||||
|
||||
return d ? d->affinity : NULL;
|
||||
}
|
||||
|
||||
static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
|
||||
{
|
||||
return d->affinity;
|
||||
}
|
||||
|
||||
unsigned int arch_dynirq_lower_bound(unsigned int from);
|
||||
|
||||
int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
|
||||
|
@ -17,7 +17,7 @@ struct pt_regs;
|
||||
|
||||
/**
|
||||
* struct irq_desc - interrupt descriptor
|
||||
* @irq_data: per irq and chip data passed down to chip functions
|
||||
* @irq_common_data: per irq and chip data passed down to chip functions
|
||||
* @kstat_irqs: irq stats per cpu
|
||||
* @handle_irq: highlevel irq-events handler
|
||||
* @preflow_handler: handler called before the flow handler (currently used by sparc)
|
||||
@ -47,6 +47,7 @@ struct pt_regs;
|
||||
* @name: flow handler name for /proc/interrupts output
|
||||
*/
|
||||
struct irq_desc {
|
||||
struct irq_common_data irq_common_data;
|
||||
struct irq_data irq_data;
|
||||
unsigned int __percpu *kstat_irqs;
|
||||
irq_flow_handler_t handle_irq;
|
||||
|
@ -258,6 +258,10 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
|
||||
/* V2 interfaces to support hierarchy IRQ domains. */
|
||||
extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
|
||||
unsigned int virq);
|
||||
extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
|
||||
irq_hw_number_t hwirq, struct irq_chip *chip,
|
||||
void *chip_data, irq_flow_handler_t handler,
|
||||
void *handler_data, const char *handler_name);
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
|
||||
unsigned int flags, unsigned int size,
|
||||
@ -281,10 +285,6 @@ extern int irq_domain_set_hwirq_and_chip(struct irq_domain *domain,
|
||||
irq_hw_number_t hwirq,
|
||||
struct irq_chip *chip,
|
||||
void *chip_data);
|
||||
extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
|
||||
irq_hw_number_t hwirq, struct irq_chip *chip,
|
||||
void *chip_data, irq_flow_handler_t handler,
|
||||
void *handler_data, const char *handler_name);
|
||||
extern void irq_domain_reset_irq_data(struct irq_data *irq_data);
|
||||
extern void irq_domain_free_irqs_common(struct irq_domain *domain,
|
||||
unsigned int virq,
|
||||
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Renesas IRQC Driver
|
||||
*
|
||||
* Copyright (C) 2013 Magnus Damm
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __IRQ_RENESAS_IRQC_H__
|
||||
#define __IRQ_RENESAS_IRQC_H__
|
||||
|
||||
struct renesas_irqc_config {
|
||||
unsigned int irq_base;
|
||||
};
|
||||
|
||||
#endif /* __IRQ_RENESAS_IRQC_H__ */
|
@ -719,15 +719,9 @@ void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
|
||||
}
|
||||
|
||||
void
|
||||
__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
|
||||
const char *name)
|
||||
__irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
|
||||
int is_chained, const char *name)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
|
||||
|
||||
if (!desc)
|
||||
return;
|
||||
|
||||
if (!handle) {
|
||||
handle = handle_bad_irq;
|
||||
} else {
|
||||
@ -749,13 +743,13 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
|
||||
* right away.
|
||||
*/
|
||||
if (WARN_ON(is_chained))
|
||||
goto out;
|
||||
return;
|
||||
/* Try the parent */
|
||||
irq_data = irq_data->parent_data;
|
||||
}
|
||||
#endif
|
||||
if (WARN_ON(!irq_data || irq_data->chip == &no_irq_chip))
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Uninstall? */
|
||||
@ -774,11 +768,40 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
|
||||
irq_settings_set_nothread(desc);
|
||||
irq_startup(desc, true);
|
||||
}
|
||||
out:
|
||||
}
|
||||
|
||||
void
|
||||
__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
|
||||
const char *name)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
|
||||
|
||||
if (!desc)
|
||||
return;
|
||||
|
||||
__irq_do_set_handler(desc, handle, is_chained, name);
|
||||
irq_put_desc_busunlock(desc, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__irq_set_handler);
|
||||
|
||||
void
|
||||
irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
|
||||
void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
|
||||
|
||||
if (!desc)
|
||||
return;
|
||||
|
||||
__irq_do_set_handler(desc, handle, 1, NULL);
|
||||
desc->irq_data.handler_data = data;
|
||||
|
||||
irq_put_desc_busunlock(desc, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_set_chained_handler_and_data);
|
||||
|
||||
void
|
||||
irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
|
||||
irq_flow_handler_t handle, const char *name)
|
||||
@ -875,6 +898,34 @@ void irq_cpu_offline(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
|
||||
/**
|
||||
* irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if
|
||||
* NULL)
|
||||
* @data: Pointer to interrupt specific data
|
||||
*/
|
||||
void irq_chip_enable_parent(struct irq_data *data)
|
||||
{
|
||||
data = data->parent_data;
|
||||
if (data->chip->irq_enable)
|
||||
data->chip->irq_enable(data);
|
||||
else
|
||||
data->chip->irq_unmask(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_chip_disable_parent - Disable the parent interrupt (defaults to mask if
|
||||
* NULL)
|
||||
* @data: Pointer to interrupt specific data
|
||||
*/
|
||||
void irq_chip_disable_parent(struct irq_data *data)
|
||||
{
|
||||
data = data->parent_data;
|
||||
if (data->chip->irq_disable)
|
||||
data->chip->irq_disable(data);
|
||||
else
|
||||
data->chip->irq_mask(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_chip_ack_parent - Acknowledge the parent interrupt
|
||||
* @data: Pointer to interrupt specific data
|
||||
|
@ -104,7 +104,7 @@ int devm_request_any_context_irq(struct device *dev, unsigned int irq,
|
||||
return -ENOMEM;
|
||||
|
||||
rc = request_any_context_irq(irq, handler, irqflags, devname, dev_id);
|
||||
if (rc) {
|
||||
if (rc < 0) {
|
||||
devres_free(dr);
|
||||
return rc;
|
||||
}
|
||||
@ -113,7 +113,7 @@ int devm_request_any_context_irq(struct device *dev, unsigned int irq,
|
||||
dr->dev_id = dev_id;
|
||||
devres_add(dev, dr);
|
||||
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_request_any_context_irq);
|
||||
|
||||
|
@ -42,6 +42,7 @@ struct irq_chip no_irq_chip = {
|
||||
.irq_enable = noop,
|
||||
.irq_disable = noop,
|
||||
.irq_ack = ack_bad,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -360,7 +360,7 @@ static struct lock_class_key irq_nested_lock_class;
|
||||
int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
|
||||
irq_hw_number_t hw_irq)
|
||||
{
|
||||
struct irq_data *data = irq_get_irq_data(virq);
|
||||
struct irq_data *data = irq_domain_get_irq_data(d, virq);
|
||||
struct irq_domain_chip_generic *dgc = d->gc;
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_chip_type *ct;
|
||||
@ -405,8 +405,7 @@ int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
|
||||
else
|
||||
data->mask = 1 << idx;
|
||||
|
||||
irq_set_chip_and_handler(virq, chip, ct->handler);
|
||||
irq_set_chip_data(virq, gc);
|
||||
irq_domain_set_info(d, virq, hw_irq, chip, gc, ct->handler, NULL, NULL);
|
||||
irq_modify_status(virq, dgc->irq_flags_to_clear, dgc->irq_flags_to_set);
|
||||
return 0;
|
||||
}
|
||||
|
@ -168,27 +168,27 @@ irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags)
|
||||
*/
|
||||
static inline void irqd_set_move_pending(struct irq_data *d)
|
||||
{
|
||||
d->state_use_accessors |= IRQD_SETAFFINITY_PENDING;
|
||||
__irqd_to_state(d) |= IRQD_SETAFFINITY_PENDING;
|
||||
}
|
||||
|
||||
static inline void irqd_clr_move_pending(struct irq_data *d)
|
||||
{
|
||||
d->state_use_accessors &= ~IRQD_SETAFFINITY_PENDING;
|
||||
__irqd_to_state(d) &= ~IRQD_SETAFFINITY_PENDING;
|
||||
}
|
||||
|
||||
static inline void irqd_clear(struct irq_data *d, unsigned int mask)
|
||||
{
|
||||
d->state_use_accessors &= ~mask;
|
||||
__irqd_to_state(d) &= ~mask;
|
||||
}
|
||||
|
||||
static inline void irqd_set(struct irq_data *d, unsigned int mask)
|
||||
{
|
||||
d->state_use_accessors |= mask;
|
||||
__irqd_to_state(d) |= mask;
|
||||
}
|
||||
|
||||
static inline bool irqd_has_set(struct irq_data *d, unsigned int mask)
|
||||
{
|
||||
return d->state_use_accessors & mask;
|
||||
return __irqd_to_state(d) & mask;
|
||||
}
|
||||
|
||||
static inline void kstat_incr_irqs_this_cpu(unsigned int irq, struct irq_desc *desc)
|
||||
@ -197,6 +197,11 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq, struct irq_desc *d
|
||||
__this_cpu_inc(kstat.irqs_sum);
|
||||
}
|
||||
|
||||
static inline int irq_desc_get_node(struct irq_desc *desc)
|
||||
{
|
||||
return irq_data_get_node(&desc->irq_data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
bool irq_pm_check_wakeup(struct irq_desc *desc);
|
||||
void irq_pm_install_action(struct irq_desc *desc, struct irqaction *action);
|
||||
|
@ -59,16 +59,10 @@ static void desc_smp_init(struct irq_desc *desc, int node)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int desc_node(struct irq_desc *desc)
|
||||
{
|
||||
return desc->irq_data.node;
|
||||
}
|
||||
|
||||
#else
|
||||
static inline int
|
||||
alloc_masks(struct irq_desc *desc, gfp_t gfp, int node) { return 0; }
|
||||
static inline void desc_smp_init(struct irq_desc *desc, int node) { }
|
||||
static inline int desc_node(struct irq_desc *desc) { return 0; }
|
||||
#endif
|
||||
|
||||
static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
|
||||
@ -76,6 +70,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
|
||||
{
|
||||
int cpu;
|
||||
|
||||
desc->irq_data.common = &desc->irq_common_data;
|
||||
desc->irq_data.irq = irq;
|
||||
desc->irq_data.chip = &no_irq_chip;
|
||||
desc->irq_data.chip_data = NULL;
|
||||
@ -299,7 +294,7 @@ static void free_desc(unsigned int irq)
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||
desc_set_defaults(irq, desc, desc_node(desc), NULL);
|
||||
desc_set_defaults(irq, desc, irq_desc_get_node(desc), NULL);
|
||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
@ -619,7 +614,7 @@ unsigned int kstat_irqs(unsigned int irq)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
int cpu;
|
||||
int sum = 0;
|
||||
unsigned int sum = 0;
|
||||
|
||||
if (!desc || !desc->kstat_irqs)
|
||||
return 0;
|
||||
@ -639,7 +634,7 @@ unsigned int kstat_irqs(unsigned int irq)
|
||||
*/
|
||||
unsigned int kstat_irqs_usr(unsigned int irq)
|
||||
{
|
||||
int sum;
|
||||
unsigned int sum;
|
||||
|
||||
irq_lock_sparse();
|
||||
sum = kstat_irqs(irq);
|
||||
|
@ -830,10 +830,12 @@ static struct irq_data *irq_domain_insert_irq_data(struct irq_domain *domain,
|
||||
{
|
||||
struct irq_data *irq_data;
|
||||
|
||||
irq_data = kzalloc_node(sizeof(*irq_data), GFP_KERNEL, child->node);
|
||||
irq_data = kzalloc_node(sizeof(*irq_data), GFP_KERNEL,
|
||||
irq_data_get_node(child));
|
||||
if (irq_data) {
|
||||
child->parent_data = irq_data;
|
||||
irq_data->irq = child->irq;
|
||||
irq_data->common = child->common;
|
||||
irq_data->node = child->node;
|
||||
irq_data->domain = domain;
|
||||
}
|
||||
@ -1232,6 +1234,27 @@ struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
|
||||
return (irq_data && irq_data->domain == domain) ? irq_data : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_domain_set_info - Set the complete data for a @virq in @domain
|
||||
* @domain: Interrupt domain to match
|
||||
* @virq: IRQ number
|
||||
* @hwirq: The hardware interrupt number
|
||||
* @chip: The associated interrupt chip
|
||||
* @chip_data: The associated interrupt chip data
|
||||
* @handler: The interrupt flow handler
|
||||
* @handler_data: The interrupt flow handler data
|
||||
* @handler_name: The interrupt handler name
|
||||
*/
|
||||
void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
|
||||
irq_hw_number_t hwirq, struct irq_chip *chip,
|
||||
void *chip_data, irq_flow_handler_t handler,
|
||||
void *handler_data, const char *handler_name)
|
||||
{
|
||||
irq_set_chip_and_handler_name(virq, chip, handler, handler_name);
|
||||
irq_set_chip_data(virq, chip_data);
|
||||
irq_set_handler_data(virq, handler_data);
|
||||
}
|
||||
|
||||
static void irq_domain_check_hierarchy(struct irq_domain *domain)
|
||||
{
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ static int
|
||||
setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
|
||||
{
|
||||
struct cpumask *set = irq_default_affinity;
|
||||
int node = desc->irq_data.node;
|
||||
int node = irq_desc_get_node(desc);
|
||||
|
||||
/* Excludes PER_CPU and NO_BALANCE interrupts */
|
||||
if (!irq_can_set_affinity(irq))
|
||||
|
@ -12,16 +12,16 @@ void irq_move_masked_irq(struct irq_data *idata)
|
||||
if (likely(!irqd_is_setaffinity_pending(&desc->irq_data)))
|
||||
return;
|
||||
|
||||
irqd_clr_move_pending(&desc->irq_data);
|
||||
|
||||
/*
|
||||
* Paranoia: cpu-local interrupts shouldn't be calling in here anyway.
|
||||
*/
|
||||
if (!irqd_can_balance(&desc->irq_data)) {
|
||||
if (irqd_is_per_cpu(&desc->irq_data)) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
irqd_clr_move_pending(&desc->irq_data);
|
||||
|
||||
if (unlikely(cpumask_empty(desc->pending_mask)))
|
||||
return;
|
||||
|
||||
|
@ -124,7 +124,7 @@ static void msi_domain_free(struct irq_domain *domain, unsigned int virq,
|
||||
irq_domain_free_irqs_top(domain, virq, nr_irqs);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops msi_domain_ops = {
|
||||
static const struct irq_domain_ops msi_domain_ops = {
|
||||
.alloc = msi_domain_alloc,
|
||||
.free = msi_domain_free,
|
||||
.activate = msi_domain_activate,
|
||||
|
@ -123,6 +123,8 @@ void suspend_device_irqs(void)
|
||||
unsigned long flags;
|
||||
bool sync;
|
||||
|
||||
if (irq_settings_is_nested_thread(desc))
|
||||
continue;
|
||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||
sync = suspend_device_irq(desc, irq);
|
||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||
@ -163,6 +165,8 @@ static void resume_irqs(bool want_early)
|
||||
|
||||
if (!is_early && want_early)
|
||||
continue;
|
||||
if (irq_settings_is_nested_thread(desc))
|
||||
continue;
|
||||
|
||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||
resume_irq(desc, irq);
|
||||
|
@ -241,7 +241,7 @@ static int irq_node_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc((long) m->private);
|
||||
|
||||
seq_printf(m, "%d\n", desc->irq_data.node);
|
||||
seq_printf(m, "%d\n", irq_desc_get_node(desc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user