181ffb18cSAlban Bedel /* 281ffb18cSAlban Bedel * Atheros AR71xx/AR724x/AR913x specific interrupt handling 381ffb18cSAlban Bedel * 481ffb18cSAlban Bedel * Copyright (C) 2015 Alban Bedel <albeu@free.fr> 581ffb18cSAlban Bedel * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 681ffb18cSAlban Bedel * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 781ffb18cSAlban Bedel * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 881ffb18cSAlban Bedel * 981ffb18cSAlban Bedel * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 1081ffb18cSAlban Bedel * 1181ffb18cSAlban Bedel * This program is free software; you can redistribute it and/or modify it 1281ffb18cSAlban Bedel * under the terms of the GNU General Public License version 2 as published 1381ffb18cSAlban Bedel * by the Free Software Foundation. 1481ffb18cSAlban Bedel */ 1581ffb18cSAlban Bedel 1681ffb18cSAlban Bedel #include <linux/interrupt.h> 1781ffb18cSAlban Bedel #include <linux/irqchip.h> 1881ffb18cSAlban Bedel #include <linux/of.h> 1981ffb18cSAlban Bedel 2081ffb18cSAlban Bedel #include <asm/irq_cpu.h> 2181ffb18cSAlban Bedel #include <asm/mach-ath79/ath79.h> 2281ffb18cSAlban Bedel 2381ffb18cSAlban Bedel /* 2481ffb18cSAlban Bedel * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for 2581ffb18cSAlban Bedel * these devices typically allocate coherent DMA memory, however the 2681ffb18cSAlban Bedel * DMA controller may still have some unsynchronized data in the FIFO. 2781ffb18cSAlban Bedel * Issue a flush in the handlers to ensure that the driver sees 2881ffb18cSAlban Bedel * the update. 2981ffb18cSAlban Bedel * 3081ffb18cSAlban Bedel * This array map the interrupt lines to the DDR write buffer channels. 3181ffb18cSAlban Bedel */ 3281ffb18cSAlban Bedel 3381ffb18cSAlban Bedel static unsigned irq_wb_chan[8] = { 3481ffb18cSAlban Bedel -1, -1, -1, -1, -1, -1, -1, -1, 3581ffb18cSAlban Bedel }; 3681ffb18cSAlban Bedel 3781ffb18cSAlban Bedel asmlinkage void plat_irq_dispatch(void) 3881ffb18cSAlban Bedel { 3981ffb18cSAlban Bedel unsigned long pending; 4081ffb18cSAlban Bedel int irq; 4181ffb18cSAlban Bedel 4281ffb18cSAlban Bedel pending = read_c0_status() & read_c0_cause() & ST0_IM; 4381ffb18cSAlban Bedel 4481ffb18cSAlban Bedel if (!pending) { 4581ffb18cSAlban Bedel spurious_interrupt(); 4681ffb18cSAlban Bedel return; 4781ffb18cSAlban Bedel } 4881ffb18cSAlban Bedel 4981ffb18cSAlban Bedel pending >>= CAUSEB_IP; 5081ffb18cSAlban Bedel while (pending) { 5181ffb18cSAlban Bedel irq = fls(pending) - 1; 5281ffb18cSAlban Bedel if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1) 5381ffb18cSAlban Bedel ath79_ddr_wb_flush(irq_wb_chan[irq]); 5481ffb18cSAlban Bedel do_IRQ(MIPS_CPU_IRQ_BASE + irq); 5581ffb18cSAlban Bedel pending &= ~BIT(irq); 5681ffb18cSAlban Bedel } 5781ffb18cSAlban Bedel } 5881ffb18cSAlban Bedel 5981ffb18cSAlban Bedel static int __init ar79_cpu_intc_of_init( 6081ffb18cSAlban Bedel struct device_node *node, struct device_node *parent) 6181ffb18cSAlban Bedel { 6281ffb18cSAlban Bedel int err, i, count; 6381ffb18cSAlban Bedel 6481ffb18cSAlban Bedel /* Fill the irq_wb_chan table */ 6581ffb18cSAlban Bedel count = of_count_phandle_with_args( 6681ffb18cSAlban Bedel node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); 6781ffb18cSAlban Bedel 6881ffb18cSAlban Bedel for (i = 0; i < count; i++) { 6981ffb18cSAlban Bedel struct of_phandle_args args; 7081ffb18cSAlban Bedel u32 irq = i; 7181ffb18cSAlban Bedel 7281ffb18cSAlban Bedel of_property_read_u32_index( 7381ffb18cSAlban Bedel node, "qca,ddr-wb-channel-interrupts", i, &irq); 7481ffb18cSAlban Bedel if (irq >= ARRAY_SIZE(irq_wb_chan)) 7581ffb18cSAlban Bedel continue; 7681ffb18cSAlban Bedel 7781ffb18cSAlban Bedel err = of_parse_phandle_with_args( 7881ffb18cSAlban Bedel node, "qca,ddr-wb-channels", 7981ffb18cSAlban Bedel "#qca,ddr-wb-channel-cells", 8081ffb18cSAlban Bedel i, &args); 8181ffb18cSAlban Bedel if (err) 8281ffb18cSAlban Bedel return err; 8381ffb18cSAlban Bedel 8481ffb18cSAlban Bedel irq_wb_chan[irq] = args.args[0]; 8581ffb18cSAlban Bedel } 8681ffb18cSAlban Bedel 8781ffb18cSAlban Bedel return mips_cpu_irq_of_init(node, parent); 8881ffb18cSAlban Bedel } 8981ffb18cSAlban Bedel IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", 9081ffb18cSAlban Bedel ar79_cpu_intc_of_init); 9181ffb18cSAlban Bedel 9281ffb18cSAlban Bedel void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3) 9381ffb18cSAlban Bedel { 9481ffb18cSAlban Bedel irq_wb_chan[2] = irq_wb_chan2; 9581ffb18cSAlban Bedel irq_wb_chan[3] = irq_wb_chan3; 9681ffb18cSAlban Bedel mips_cpu_irq_init(); 9781ffb18cSAlban Bedel } 98