Loading drivers/irqchip/Kconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ config ARM_GIC_V3_ITS config ARM_NVIC config ARM_NVIC bool bool select IRQ_DOMAIN select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP config ARM_VIC config ARM_VIC Loading drivers/irqchip/irq-nvic.c +27 −1 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,31 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs) handle_IRQ(irq, 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, static int __init nvic_of_init(struct device_node *node, struct device_node *parent) struct device_node *parent) { { Loading @@ -70,7 +95,8 @@ static int __init nvic_of_init(struct device_node *node, irqs = NVIC_MAX_IRQ; irqs = NVIC_MAX_IRQ; nvic_irq_domain = 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) { if (!nvic_irq_domain) { pr_warn("Failed to allocate irq domain\n"); pr_warn("Failed to allocate irq domain\n"); return -ENOMEM; return -ENOMEM; Loading drivers/irqchip/irq-vf610-mscm-ir.c +17 −6 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,7 @@ struct vf610_mscm_ir_chip_data { void __iomem *mscm_ir_base; void __iomem *mscm_ir_base; u16 cpu_mask; u16 cpu_mask; u16 saved_irsprc[MSCM_IRSPRC_NUM]; u16 saved_irsprc[MSCM_IRSPRC_NUM]; bool is_nvic; }; }; static struct vf610_mscm_ir_chip_data *mscm_ir_data; static struct vf610_mscm_ir_chip_data *mscm_ir_data; Loading Loading @@ -101,7 +102,7 @@ static void vf610_mscm_ir_enable(struct irq_data *data) writew_relaxed(chip_data->cpu_mask, writew_relaxed(chip_data->cpu_mask, chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq)); 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) static void vf610_mscm_ir_disable(struct irq_data *data) Loading @@ -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)); 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 = { static struct irq_chip vf610_mscm_ir_irq_chip = { Loading Loading @@ -143,10 +144,17 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi domain->host_data); domain->host_data); gic_data.np = domain->parent->of_node; gic_data.np = domain->parent->of_node; 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_count = 3; gic_data.args[0] = GIC_SPI; gic_data.args[0] = GIC_SPI; gic_data.args[1] = irq_data->args[0]; gic_data.args[1] = irq_data->args[0]; gic_data.args[2] = irq_data->args[1]; gic_data.args[2] = irq_data->args[1]; } return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data); return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data); } } Loading Loading @@ -198,6 +206,9 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node, goto out_unmap; 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); cpu_pm_register_notifier(&mscm_ir_notifier_block); return 0; return 0; Loading include/linux/irq.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -458,6 +458,8 @@ extern void handle_nested_irq(unsigned int irq); extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY #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 void irq_chip_ack_parent(struct irq_data *data); extern int irq_chip_retrigger_hierarchy(struct irq_data *data); extern int irq_chip_retrigger_hierarchy(struct irq_data *data); extern void irq_chip_mask_parent(struct irq_data *data); extern void irq_chip_mask_parent(struct irq_data *data); Loading include/linux/irqdomain.h +4 −4 Original line number Original line Diff line number Diff line Loading @@ -258,6 +258,10 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr, /* V2 interfaces to support hierarchy IRQ domains. */ /* V2 interfaces to support hierarchy IRQ domains. */ extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, unsigned int virq); 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 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent, extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent, unsigned int flags, unsigned int size, unsigned int flags, unsigned int size, Loading @@ -281,10 +285,6 @@ extern int irq_domain_set_hwirq_and_chip(struct irq_domain *domain, irq_hw_number_t hwirq, irq_hw_number_t hwirq, struct irq_chip *chip, struct irq_chip *chip, void *chip_data); 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_reset_irq_data(struct irq_data *irq_data); extern void irq_domain_free_irqs_common(struct irq_domain *domain, extern void irq_domain_free_irqs_common(struct irq_domain *domain, unsigned int virq, unsigned int virq, Loading Loading
drivers/irqchip/Kconfig +1 −0 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ config ARM_GIC_V3_ITS config ARM_NVIC config ARM_NVIC bool bool select IRQ_DOMAIN select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP config ARM_VIC config ARM_VIC Loading
drivers/irqchip/irq-nvic.c +27 −1 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,31 @@ nvic_handle_irq(irq_hw_number_t hwirq, struct pt_regs *regs) handle_IRQ(irq, 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, static int __init nvic_of_init(struct device_node *node, struct device_node *parent) struct device_node *parent) { { Loading @@ -70,7 +95,8 @@ static int __init nvic_of_init(struct device_node *node, irqs = NVIC_MAX_IRQ; irqs = NVIC_MAX_IRQ; nvic_irq_domain = 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) { if (!nvic_irq_domain) { pr_warn("Failed to allocate irq domain\n"); pr_warn("Failed to allocate irq domain\n"); return -ENOMEM; return -ENOMEM; Loading
drivers/irqchip/irq-vf610-mscm-ir.c +17 −6 Original line number Original line Diff line number Diff line Loading @@ -47,6 +47,7 @@ struct vf610_mscm_ir_chip_data { void __iomem *mscm_ir_base; void __iomem *mscm_ir_base; u16 cpu_mask; u16 cpu_mask; u16 saved_irsprc[MSCM_IRSPRC_NUM]; u16 saved_irsprc[MSCM_IRSPRC_NUM]; bool is_nvic; }; }; static struct vf610_mscm_ir_chip_data *mscm_ir_data; static struct vf610_mscm_ir_chip_data *mscm_ir_data; Loading Loading @@ -101,7 +102,7 @@ static void vf610_mscm_ir_enable(struct irq_data *data) writew_relaxed(chip_data->cpu_mask, writew_relaxed(chip_data->cpu_mask, chip_data->mscm_ir_base + MSCM_IRSPRC(hwirq)); 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) static void vf610_mscm_ir_disable(struct irq_data *data) Loading @@ -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)); 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 = { static struct irq_chip vf610_mscm_ir_irq_chip = { Loading Loading @@ -143,10 +144,17 @@ static int vf610_mscm_ir_domain_alloc(struct irq_domain *domain, unsigned int vi domain->host_data); domain->host_data); gic_data.np = domain->parent->of_node; gic_data.np = domain->parent->of_node; 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_count = 3; gic_data.args[0] = GIC_SPI; gic_data.args[0] = GIC_SPI; gic_data.args[1] = irq_data->args[0]; gic_data.args[1] = irq_data->args[0]; gic_data.args[2] = irq_data->args[1]; gic_data.args[2] = irq_data->args[1]; } return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data); return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_data); } } Loading Loading @@ -198,6 +206,9 @@ static int __init vf610_mscm_ir_of_init(struct device_node *node, goto out_unmap; 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); cpu_pm_register_notifier(&mscm_ir_notifier_block); return 0; return 0; Loading
include/linux/irq.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -458,6 +458,8 @@ extern void handle_nested_irq(unsigned int irq); extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg); #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY #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 void irq_chip_ack_parent(struct irq_data *data); extern int irq_chip_retrigger_hierarchy(struct irq_data *data); extern int irq_chip_retrigger_hierarchy(struct irq_data *data); extern void irq_chip_mask_parent(struct irq_data *data); extern void irq_chip_mask_parent(struct irq_data *data); Loading
include/linux/irqdomain.h +4 −4 Original line number Original line Diff line number Diff line Loading @@ -258,6 +258,10 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr, /* V2 interfaces to support hierarchy IRQ domains. */ /* V2 interfaces to support hierarchy IRQ domains. */ extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, unsigned int virq); 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 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent, extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent, unsigned int flags, unsigned int size, unsigned int flags, unsigned int size, Loading @@ -281,10 +285,6 @@ extern int irq_domain_set_hwirq_and_chip(struct irq_domain *domain, irq_hw_number_t hwirq, irq_hw_number_t hwirq, struct irq_chip *chip, struct irq_chip *chip, void *chip_data); 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_reset_irq_data(struct irq_data *irq_data); extern void irq_domain_free_irqs_common(struct irq_domain *domain, extern void irq_domain_free_irqs_common(struct irq_domain *domain, unsigned int virq, unsigned int virq, Loading