From: Rosen Penev Date: Sat, 18 Apr 2026 01:07:20 +0000 (-0700) Subject: ath79: move intc driver out of patch X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86cc4d84bb988436dfeb3e7befefa3ebff7b5940;p=thirdparty%2Fopenwrt.git ath79: move intc driver out of patch This driver has been attempted to be upstreamed once and never again. Keep it local to make modification easier. Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/22981 Signed-off-by: Jonas Jelonek --- diff --git a/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c new file mode 100644 index 00000000000..4d06a3e8298 --- /dev/null +++ b/target/linux/ath79/files/drivers/irqchip/irq-ath79-intc.c @@ -0,0 +1,142 @@ +/* + * Atheros AR71xx/AR724x/AR913x specific interrupt handling + * + * Copyright (C) 2018 John Crispin + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define ATH79_MAX_INTC_CASCADE 3 + +struct ath79_intc { + struct irq_chip chip; + u32 irq; + u32 pending_mask; + u32 int_status; + u32 irq_mask[ATH79_MAX_INTC_CASCADE]; + u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; +}; + +static void ath79_intc_irq_handler(struct irq_desc *desc) +{ + struct irq_domain *domain = irq_desc_get_handler_data(desc); + struct ath79_intc *intc = domain->host_data; + u32 pending; + + pending = ath79_reset_rr(intc->int_status); + pending &= intc->pending_mask; + + if (pending) { + int i; + + for (i = 0; i < domain->hwirq_max; i++) + if (pending & intc->irq_mask[i]) { + if (intc->irq_wb_chan[i] != 0xffffffff) + ath79_ddr_wb_flush(intc->irq_wb_chan[i]); + generic_handle_irq(irq_find_mapping(domain, i)); + } + } else { + spurious_interrupt(); + } +} + +static void ath79_intc_irq_enable(struct irq_data *d) +{ + struct ath79_intc *intc = d->domain->host_data; + enable_irq(intc->irq); +} + +static void ath79_intc_irq_disable(struct irq_data *d) +{ + struct ath79_intc *intc = d->domain->host_data; + disable_irq(intc->irq); +} + +static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +{ + struct ath79_intc *intc = d->host_data; + + irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); + + return 0; +} + +static const struct irq_domain_ops ath79_irq_domain_ops = { + .xlate = irq_domain_xlate_onecell, + .map = ath79_intc_map, +}; + +static int __init ath79_intc_of_init( + struct device_node *node, struct device_node *parent) +{ + struct irq_domain *domain; + struct ath79_intc *intc; + int cnt, cntwb, i, err; + + cnt = of_property_count_u32_elems(node, "qca,pending-bits"); + if (cnt > ATH79_MAX_INTC_CASCADE) + panic("Too many INTC pending bits\n"); + + intc = kzalloc(sizeof(*intc), GFP_KERNEL); + if (!intc) + panic("Failed to allocate INTC memory\n"); + intc->chip = dummy_irq_chip; + intc->chip.name = "INTC"; + intc->chip.irq_disable = ath79_intc_irq_disable; + intc->chip.irq_enable = ath79_intc_irq_enable; + + if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { + panic("Missing address of interrupt status register\n"); + } + + of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); + for (i = 0; i < cnt; i++) { + intc->pending_mask |= intc->irq_mask[i]; + intc->irq_wb_chan[i] = 0xffffffff; + } + + cntwb = of_count_phandle_with_args( + node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); + + for (i = 0; i < cntwb; i++) { + struct of_phandle_args args; + u32 irq = i; + + of_property_read_u32_index( + node, "qca,ddr-wb-channel-interrupts", i, &irq); + if (irq >= ATH79_MAX_INTC_CASCADE) + continue; + + err = of_parse_phandle_with_args( + node, "qca,ddr-wb-channels", + "#qca,ddr-wb-channel-cells", + i, &args); + if (err) + return err; + + intc->irq_wb_chan[irq] = args.args[0]; + } + + intc->irq = irq_of_parse_and_map(node, 0); + if (!intc->irq) + panic("Failed to get INTC IRQ"); + + domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); + irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); + + return 0; +} +IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", + ath79_intc_of_init); diff --git a/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch index ceda511c21a..4d0cadc7e6f 100644 --- a/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch +++ b/target/linux/ath79/patches-6.12/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -21,148 +21,3 @@ Signed-off-by: John Crispin obj-$(CONFIG_ATH79) += irq-ath79-misc.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o ---- /dev/null -+++ b/drivers/irqchip/irq-ath79-intc.c -@@ -0,0 +1,142 @@ -+/* -+ * Atheros AR71xx/AR724x/AR913x specific interrupt handling -+ * -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define ATH79_MAX_INTC_CASCADE 3 -+ -+struct ath79_intc { -+ struct irq_chip chip; -+ u32 irq; -+ u32 pending_mask; -+ u32 int_status; -+ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; -+ u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; -+}; -+ -+static void ath79_intc_irq_handler(struct irq_desc *desc) -+{ -+ struct irq_domain *domain = irq_desc_get_handler_data(desc); -+ struct ath79_intc *intc = domain->host_data; -+ u32 pending; -+ -+ pending = ath79_reset_rr(intc->int_status); -+ pending &= intc->pending_mask; -+ -+ if (pending) { -+ int i; -+ -+ for (i = 0; i < domain->hwirq_max; i++) -+ if (pending & intc->irq_mask[i]) { -+ if (intc->irq_wb_chan[i] != 0xffffffff) -+ ath79_ddr_wb_flush(intc->irq_wb_chan[i]); -+ generic_handle_irq(irq_find_mapping(domain, i)); -+ } -+ } else { -+ spurious_interrupt(); -+ } -+} -+ -+static void ath79_intc_irq_enable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ enable_irq(intc->irq); -+} -+ -+static void ath79_intc_irq_disable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ disable_irq(intc->irq); -+} -+ -+static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ath79_intc *intc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ath79_irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ath79_intc_map, -+}; -+ -+static int __init ath79_intc_of_init( -+ struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct ath79_intc *intc; -+ int cnt, cntwb, i, err; -+ -+ cnt = of_property_count_u32_elems(node, "qca,pending-bits"); -+ if (cnt > ATH79_MAX_INTC_CASCADE) -+ panic("Too many INTC pending bits\n"); -+ -+ intc = kzalloc(sizeof(*intc), GFP_KERNEL); -+ if (!intc) -+ panic("Failed to allocate INTC memory\n"); -+ intc->chip = dummy_irq_chip; -+ intc->chip.name = "INTC"; -+ intc->chip.irq_disable = ath79_intc_irq_disable; -+ intc->chip.irq_enable = ath79_intc_irq_enable; -+ -+ if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { -+ panic("Missing address of interrupt status register\n"); -+ } -+ -+ of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); -+ for (i = 0; i < cnt; i++) { -+ intc->pending_mask |= intc->irq_mask[i]; -+ intc->irq_wb_chan[i] = 0xffffffff; -+ } -+ -+ cntwb = of_count_phandle_with_args( -+ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); -+ -+ for (i = 0; i < cntwb; i++) { -+ struct of_phandle_args args; -+ u32 irq = i; -+ -+ of_property_read_u32_index( -+ node, "qca,ddr-wb-channel-interrupts", i, &irq); -+ if (irq >= ATH79_MAX_INTC_CASCADE) -+ continue; -+ -+ err = of_parse_phandle_with_args( -+ node, "qca,ddr-wb-channels", -+ "#qca,ddr-wb-channel-cells", -+ i, &args); -+ if (err) -+ return err; -+ -+ intc->irq_wb_chan[irq] = args.args[0]; -+ } -+ -+ intc->irq = irq_of_parse_and_map(node, 0); -+ if (!intc->irq) -+ panic("Failed to get INTC IRQ"); -+ -+ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); -+ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); -+ -+ return 0; -+} -+IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", -+ ath79_intc_of_init); diff --git a/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch index ceda511c21a..4d0cadc7e6f 100644 --- a/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch +++ b/target/linux/ath79/patches-6.18/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -21,148 +21,3 @@ Signed-off-by: John Crispin obj-$(CONFIG_ATH79) += irq-ath79-misc.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o ---- /dev/null -+++ b/drivers/irqchip/irq-ath79-intc.c -@@ -0,0 +1,142 @@ -+/* -+ * Atheros AR71xx/AR724x/AR913x specific interrupt handling -+ * -+ * Copyright (C) 2018 John Crispin -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define ATH79_MAX_INTC_CASCADE 3 -+ -+struct ath79_intc { -+ struct irq_chip chip; -+ u32 irq; -+ u32 pending_mask; -+ u32 int_status; -+ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; -+ u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; -+}; -+ -+static void ath79_intc_irq_handler(struct irq_desc *desc) -+{ -+ struct irq_domain *domain = irq_desc_get_handler_data(desc); -+ struct ath79_intc *intc = domain->host_data; -+ u32 pending; -+ -+ pending = ath79_reset_rr(intc->int_status); -+ pending &= intc->pending_mask; -+ -+ if (pending) { -+ int i; -+ -+ for (i = 0; i < domain->hwirq_max; i++) -+ if (pending & intc->irq_mask[i]) { -+ if (intc->irq_wb_chan[i] != 0xffffffff) -+ ath79_ddr_wb_flush(intc->irq_wb_chan[i]); -+ generic_handle_irq(irq_find_mapping(domain, i)); -+ } -+ } else { -+ spurious_interrupt(); -+ } -+} -+ -+static void ath79_intc_irq_enable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ enable_irq(intc->irq); -+} -+ -+static void ath79_intc_irq_disable(struct irq_data *d) -+{ -+ struct ath79_intc *intc = d->domain->host_data; -+ disable_irq(intc->irq); -+} -+ -+static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ struct ath79_intc *intc = d->host_data; -+ -+ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops ath79_irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = ath79_intc_map, -+}; -+ -+static int __init ath79_intc_of_init( -+ struct device_node *node, struct device_node *parent) -+{ -+ struct irq_domain *domain; -+ struct ath79_intc *intc; -+ int cnt, cntwb, i, err; -+ -+ cnt = of_property_count_u32_elems(node, "qca,pending-bits"); -+ if (cnt > ATH79_MAX_INTC_CASCADE) -+ panic("Too many INTC pending bits\n"); -+ -+ intc = kzalloc(sizeof(*intc), GFP_KERNEL); -+ if (!intc) -+ panic("Failed to allocate INTC memory\n"); -+ intc->chip = dummy_irq_chip; -+ intc->chip.name = "INTC"; -+ intc->chip.irq_disable = ath79_intc_irq_disable; -+ intc->chip.irq_enable = ath79_intc_irq_enable; -+ -+ if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { -+ panic("Missing address of interrupt status register\n"); -+ } -+ -+ of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); -+ for (i = 0; i < cnt; i++) { -+ intc->pending_mask |= intc->irq_mask[i]; -+ intc->irq_wb_chan[i] = 0xffffffff; -+ } -+ -+ cntwb = of_count_phandle_with_args( -+ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); -+ -+ for (i = 0; i < cntwb; i++) { -+ struct of_phandle_args args; -+ u32 irq = i; -+ -+ of_property_read_u32_index( -+ node, "qca,ddr-wb-channel-interrupts", i, &irq); -+ if (irq >= ATH79_MAX_INTC_CASCADE) -+ continue; -+ -+ err = of_parse_phandle_with_args( -+ node, "qca,ddr-wb-channels", -+ "#qca,ddr-wb-channel-cells", -+ i, &args); -+ if (err) -+ return err; -+ -+ intc->irq_wb_chan[irq] = args.args[0]; -+ } -+ -+ intc->irq = irq_of_parse_and_map(node, 0); -+ if (!intc->irq) -+ panic("Failed to get INTC IRQ"); -+ -+ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); -+ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); -+ -+ return 0; -+} -+IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", -+ ath79_intc_of_init);