diff options
author | Johann Neuhauser <johann@it-neuhauser.de> | 2018-06-18 19:15:21 +0200 |
---|---|---|
committer | John Crispin <john@phrozen.org> | 2018-06-20 11:12:00 +0200 |
commit | c7efc93509cbdf1471b06d20439dc23bcaa875d5 (patch) | |
tree | d98454a665b97b4fcdc2dedf1aa2383c8ff8b95d /target/linux | |
parent | 189815462cda469f6bba2609d65a4591f83418e1 (diff) | |
download | upstream-c7efc93509cbdf1471b06d20439dc23bcaa875d5.tar.gz upstream-c7efc93509cbdf1471b06d20439dc23bcaa875d5.tar.bz2 upstream-c7efc93509cbdf1471b06d20439dc23bcaa875d5.zip |
ath79: fix irq-ath79-intc driver and add support for other ath79 SoCs
Add the missing enable and disable function.
Remove dummy mask and unmask function and use the one provided by
irq_dummy_chip.
Allow interrupt status register being defined from dts.
Add ddr_wb_flush for ar934x/qca953x.
Rename controller name to qca,ar9340-intc because this design was
first introduced in AR934x.
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
Signed-off-by: Johann Neuhauser <johann@it-neuhauser.de>
Diffstat (limited to 'target/linux')
-rw-r--r-- | target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch | 66 |
1 files changed, 52 insertions, 14 deletions
diff --git a/target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch index 72a7a5ee29..ae3e6c068d 100644 --- a/target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch +++ b/target/linux/ath79/patches-4.14/0007-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -23,7 +23,7 @@ Signed-off-by: John Crispin <john@phrozen.org> obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o --- /dev/null +++ b/drivers/irqchip/irq-ath79-intc.c -@@ -0,0 +1,104 @@ +@@ -0,0 +1,142 @@ +/* + * Atheros AR71xx/AR724x/AR913x specific interrupt handling + * @@ -50,7 +50,9 @@ Signed-off-by: John Crispin <john@phrozen.org> + 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) @@ -59,26 +61,33 @@ Signed-off-by: John Crispin <john@phrozen.org> + struct ath79_intc *intc = domain->host_data; + u32 pending; + -+ pending = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS); ++ 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 (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_unmask(struct irq_data *d) ++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_mask(struct irq_data *d) ++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) @@ -95,27 +104,56 @@ Signed-off-by: John Crispin <john@phrozen.org> + .map = ath79_intc_map, +}; + -+static int __init qca9556_intc_of_init( ++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, i; ++ int cnt, cntwb, i, err; + -+ cnt = of_property_count_u32_elems(node, "qcom,pending-bits"); ++ 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_unmask = ath79_intc_irq_unmask, -+ intc->chip.irq_mask = ath79_intc_irq_mask, ++ intc->chip.irq_disable = ath79_intc_irq_disable; ++ intc->chip.irq_enable = ath79_intc_irq_enable; + -+ of_property_read_u32_array(node, "qcom,pending-bits", intc->irq_mask, cnt); -+ for (i = 0; i < cnt; i++) ++ 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) @@ -126,5 +164,5 @@ Signed-off-by: John Crispin <john@phrozen.org> + + return 0; +} -+IRQCHIP_DECLARE(qca9556_intc, "qcom,qca9556-intc", -+ qca9556_intc_of_init); ++IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", ++ ath79_intc_of_init); |