UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor charleswr
Visitor
719 Views
Registered: ‎01-09-2018

Interrupts from FPGA not show in Linux

I am using a Zynq-7000 and Linux 4.9.0 and am having trouble catching custom hardware interrupts in a Linux driver.
 
Whenever the FPGA is ready to send data to my software, it is supposed to issue and interrupt request with the ID 94.  However, whenever I register for that interrupt with my driver, nothing happens. I am almost certain that the interrupt is being sent because I can see it being done when monitoring the FPGA over the JTAG interface.
 
I found some utilities in https://github.com/Xilinx/linux-xlnx/blob/master/drivers/irqchip/irq-gic.c like 'gic_peek_irq' to look at Generic Interrupt Controller (GIC) registers but no guide on how to use them.

 

  • What am I missing? Is there something else other than the “mysoftip” entry I need to add to the device tree?
  • How do I use tools in irq-gic.c to look at the GIC and figure out what interrupt signals it is receiving?
  • Is there a way to see ALL interrupt signals going to the GIC, regardless of whether or not anything has registered for them?

 

 

Device Tree:
 

/dts-v1/;
 
/ {
        compatible = "xlnx,zynq-7000";
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        interrupt-parent = <0x1>;
        model = "ags,FMC";
 
        aliases {
                ethernet0 = "/amba@0/eth@e000b000";
                serial0 = "/amba@0/uart@e0001000";
        };
 
        cpus {
                #address-cells = <0x1>;
                #size-cells = <0x0>;
 
                cpu@0 {
                        bus-handle = <0x2>;
                        clock-latency = <0x3e8>;
                        clocks = <0x3 0x3>;
                        compatible = "arm,cortex-a9";
                        device_type = "cpu";
                        interrupt-handle = <0x1>;
                        operating-points = <0xa2c2b 0xf4240 0x51616 0xf4240 0x3640f 0xf4240>;
                        reg = <0x0>;
                };
 
                cpu@1 {
                        bus-handle = <0x2>;
                        clocks = <0x3 0x3>;
                        compatible = "arm,cortex-a9";
                        device_type = "cpu";
                        interrupt-handle = <0x1>;
                        reg = <0x1>;
                };
        };
 
        pmu {
                compatible = "arm,cortex-a9-pmu";
                interrupts = <0x0 0x5 0x4 0x0 0x6 0x4>;
                interrupt-parent = <0x1>;
                reg = <0xf8891000 0x1000 0xf8893000 0x1000>;
                reg-names = "cpu0", "cpu1";
        };
 
        amba@0 {
                compatible = "simple-bus";
                #address-cells = <0x1>;
                #size-cells = <0x1>;
                ranges;
                linux,phandle = <0x2>;
                phandle = <0x2>;
 
                intc@f8f01000 {
                        interrupt-controller;
                        compatible = "arm,cortex-a9-gic";
                        #interrupt-cells = <0x3>;
                        reg = <0xf8f01000 0x1000 0xf8f00100 0x100>;
                        linux,phandle = <0x1>;
                        phandle = <0x1>;
                };
 
                pl310@f8f02000 {
                        compatible = "arm,pl310-cache";
                        cache-unified;
                        cache-level = <0x2>;
                        reg = <0xf8f02000 0x1000>;
                        arm,data-latency = <0x3 0x2 0x2>;
                        arm,tag-latency = <0x2 0x2 0x2>;
                };
 
                uart@e0001000 {
                        interrupt-parent = <0x1>;
                        compatible = "xlnx,xuartps", "cdns,uart-r1p8";
                        clocks = <0x3 0x18 0x3 0x29>;
                        clock-names = "uart_clk", "pclk";
                        reg = <0xe0001000 0x1000>;
                        interrupts = <0x0 0x32 0x4>;
                        port-number = <0x0>;
                        current-speed = <0x1c200>;
                        device_type = "serial";
                };
 
                ps7-dma@f8003000 {
                        #dma-cells = <0x1>;
                        #dma-channels = <0x8>;
                        #dma-requests = <0x4>;
                        compatible = "arm,primecell", "arm,pl330";
                        interrupt-parent = <0x1>;
                        interrupts = <0x0 0xd 0x4 0x0 0xe 0x4 0x0 0xf 0x4 0x0 0x10 0x4 0x0 0x11 0x4 0x0 0x28 0x4 0x0 0x29 0x4 0x0 0x2a 0x4 0x0 0x2b 0x4>;
                        reg = <0xf8003000 0x1000>;
                        clocks = <0x3 0x1b>;
                        clock-names = "apb_pclk";
                        linux,phandle = <0x11>;
                        phandle = <0x11>;
                };
 
                slcr@f8000000 {
                        #address-cells = <0x1>;
                        #size-cells = <0x1>;
                        compatible = "xlnx,zynq-slcr", "syscon";
                        reg = <0xf8000000 0x1000>;
                        ranges;
 
                        clkc {
                                #clock-cells = <0x1>;
                                clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x", "dci", "lqspi", "smc", "pcap", "gem0", "gem1", "fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1", "sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1", "dma", "usb0_aper", "usb1_aper", "gem0_aper", "gem1_aper", "sdio0_aper", "sdio1_aper", "spi0_aper", "spi1_aper", "can0_aper", "can1_aper", "i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper", "gpio_aper", "lqspi_aper", "smc_aper", "swdt", "dbg_trc", "dbg_apb";
                                compatible = "xlnx,ps7-clkc";
                                ps-clk-frequency = <0x1fca055>;
                                fclk-enable = <0xf>;
                                reg = <0x100 0x100>;
                                linux,phandle = <0x3>;
                                phandle = <0x3>;
                        };
                };
 
                timer@0xf8001000 {
                        compatible = "cdns,ttc";
                        reg = <0xf8001000 0x1000>;
                        interrupts = <0x0 0xa 0x4 0x0 0xb 0x4 0x0 0xc 0x4>;
                        interrupt-parent = <0x1>;
                        clocks = <0x3 0x6>;
                };
 
                timer@f8f00600 {
                        compatible = "arm,cortex-a9-twd-timer";
                        reg = <0xf8f00600 0x20>;
                        interrupts = <0x1 0xd 0x301>;
                        clocks = <0x3 0x4>;
                        interrupt-parent = <0x1>;
                };
 
                swdt@f8005000 {
                        device_type = "watchdog";
                        compatible = "xlnx,ps7-wdt-1.00.a", "xlnx,zynq-wdt-1.00.a";
                        reg = <0xf8005000 0x100>;
                        interrupts = <0x0 0x9 0x4>;
                        interrupt-parent = <0x1>;
                        clocks = <0x3 0x2d>;
                        reset = <0x0>;
                        timeout = <0xa>;
                };
 
                scuwdt@f8f00620 {
                        device_type = "watchdog";
                        compatible = "arm,mpcore_wdt";
                        reg = <0xf8f00620 0x20>;
                        clocks = <0x3 0x4>;
                        reset = <0x1>;
                };
 
                eth@e000b000 {
                        compatible = "xlnx,ps7-ethernet-1.00.a";
                        reg = <0xe000b000 0x1000>;
                        interrupts = <0x0 0x16 0x4>;
                        interrupt-parent = <0x1>;
                        #address-cells = <0x1>;
                        #size-cells = <0x0>;
                        clock-names = "ref_clk", "aper_clk";
                        clocks = <0x3 0xd 0x3 0x1e>;
                        xlnx,enet-clk-freq-hz = <0x17d7840>;
                        xlnx,enet-reset = "MIO 11";
                        xlnx,enet-slcr-1000mbps-div0 = <0x8>;
                        xlnx,enet-slcr-1000mbps-div1 = <0x1>;
                        xlnx,enet-slcr-100mbps-div0 = <0x8>;
                        xlnx,enet-slcr-100mbps-div1 = <0x5>;
                        xlnx,enet-slcr-10mbps-div0 = <0x8>;
                        xlnx,enet-slcr-10mbps-div1 = <0x32>;
                        xlnx,eth-mode = <0x1>;
                        xlnx,has-mdio = <0x1>;
                        xlnx,ptp-enet-clock = <0x69f6bcb>;
                        phy-handle = <0x4>;
                        phy-mode = "rgmii-id";
 
                        phy@0 {
                                compatible = "marvell,88e1510";
                                device_type = "ethernet-phy";
                                reg = <0x0>;
                                marvell,reg-init = <0x3 0x10 0xff00 0x1e 0x3 0x11 0xfff0 0x0>;
                                linux,phandle = <0x4>;
                                phandle = <0x4>;
                        };
                };
 
                gpio@e000a000 {
                        compatible = "xlnx,ps7-gpio-1.00.a", "xlnx,zynq-gpio-1.00.a", "xlnx,zynq-gpio-1.0";
                        reg = <0xe000a000 0x1000>;
                        interrupts = <0x0 0x14 0x4>;
                        interrupt-parent = <0x1>;
                        clocks = <0x3 0x2a>;
                        gpio-controller;
                        #gpio-cells = <0x2>;
                        interrupt-controller;
                        #interrupt-cells = <0x2>;
                        linux,phandle = <0x5>;
                        phandle = <0x5>;
                };
 
                sdhci@e0100000 {
                        compatible = "xlnx,ps7-sdio-1.00.a", "arasan,sdhci-8.9a";
                        reg = <0xe0100000 0x1000>;
                        interrupts = <0x0 0x18 0x4>;
                        interrupt-parent = <0x1>;
                        clock-names = "clk_xin", "clk_ahb";
                        clocks = <0x3 0x15 0x3 0x20>;
                        xlnx,has-cd = <0x1>;
                        clock-frequency = <0x2faf080>;
                        status = "okay";
                        disable-wp;
                };
 
                i2c@e0004000 {
                        compatible = "cdns,i2c-r1p10";
                        clocks = <0x3 0x26>;
                        interrupt-parent = <0x1>;
                        interrupts = <0x0 0x19 0x4>;
                        reg = <0xe0004000 0x1000>;
                        clock-frequency = <0x61a80>;
                        #address-cells = <0x1>;
                        #size-cells = <0x0>;
                };
 
                spi@e0006000 {
                        compatible = "cdns,spi-r1p6", "xlnx,zynq-spi-1.00.a", "xlnx,ps7-spi-1.00.a";
                        interrupt-parent = <0x1>;
                        interrupts = <0x0 0x1a 0x4>;
                        clock-names = "ref_clk", "aper_clk", "pclk";
                        clocks = <0x3 0x19 0x3 0x22 0x3 0x22>;
                        num-chip-select = <0x4>;
                        reg = <0xe0006000 0x1000>;
                        speed-hz = <0x5f5e100>;
                        #address-cells = <0x1>;
                        #size-cells = <0x0>;
                        status = "okay";
 
 
                        spidev@0 {
                                compatible = "spidev";
                                reg = <0x00000000>;
                                spi-max-frequency = <0x017d7840>;
                        };
                };
 
                spi@e0007000 {
                        compatible = "cdns,spi-r1p6", "xlnx,zynq-spi-1.00.a", "xlnx,ps7-spi-1.00.a";
                        interrupt-parent = <0x1>;
                        interrupts = <0x0 0x31 0x4>;
                        clock-names = "ref_clk", "aper_clk", "pclk";
                        clocks = <0x3 0x1a 0x3 0x23 0x3 0x23>;
                        num-chip-select = <0x3>;
                        is-decoded-cs = <0x0>;
                        reg = <0xe0007000 0x1000>;
                        speed-hz = <0x1e8480>;
                        #address-cells = <0x1>;
                        #size-cells = <0x0>;
 
                        spidev@0 {
                                compatible = "spidev";
                                reg = <0x0>;
                                spi-max-frequency = <0x1e8480>;
                        };
 
                        spidev@1 {
                                compatible = "spidev";
                                reg = <0x1>;
                                spi-max-frequency = <0x1e8480>;
                        };
 
                        spidev@2 {
                                compatible = "spidev";
                                reg = <0x2>;
                                spi-max-frequency = <0x1e8480>;
                        };
                };
 
                devcfg@f8007000 {
                        compatible = "xlnx,zynq-devcfg-1.0";
                        reg = <0xf8007000 0x100>;
                        interrupts = <0x0 0x8 0x4>;
                        interrupt-parent = <0x1>;
                        clocks = <0x3 0xc 0x3 0xf 0x3 0x10 0x3 0x11 0x3 0x12>;
                        clock-names = "ref_clk", "fclk0", "fclk1", "fclk2", "fclk3";
                };
 
                efuse: efuse@f800d000 {
                        compatible = "xlnx,zynq-efuse";
                        reg = <0xf800d000 0x20>;
                };
 
                xadc@f8007100 {
                        compatible = "xlnx,zynq-xadc-1.00.a", "xlnx,ps7-xadc-1.00.a";
                        reg = <0xf8007100 0x20>;
                        interrupts = <0x0 0x7 0x4>;
                        interrupt-parent = <0x1>;
                        clocks = <0x3 0xc>;
                };
 
                ps7-ddrc@f8006000 {
                        compatible = "xlnx,zynq-ddrc-a05", "xlnx,ps7-ddrc-1.00.a", "xlnx,ps7-ddrc", "xlnx,zynq-ddrc-1.0";
                        reg = <0xf8006000 0x1000>;
                        xlnx,has-ecc = <0x0>;
                };
 
                ps7-ocm@f800c000 {
                        compatible = "xlnx,ps7-ocmc-1.00.a", "xlnx,zynq-ocmc-1.0";
                        interrupt-parent = <0x1>;
                        interrupts = <0x0 0x3 0x4>;
                        reg = <0xf800c000 0x1000>;
                };
 
        };
 
        memory {
                device_type = "memory";
                reg = <0x0 0x40000000>;
        };
 
    chosen {
                                linux,stdout-path = "/amba@0/uart@E0001000";
                };
 
                clocks {
 
                                clock@0 {
                                                #clock-cells = <0x0>;
                                                compatible = "fixed-clock";
                                                clock-frequency = <0x2625a00>;
                                                clock-output-names = "ad9361_ext_refclk";
                                                linux,phandle = <0x6>;
                                                phandle = <0x6>;
                                };
 
                                clock@1 {
                                                #clock-cells = <0x0>;
                                                compatible = "fixed-clock";
                                                clock-frequency = <0x16e3600>;
                                                clock-output-names = "24MHz";
                                                linux,phandle = <0x8>;
                                                phandle = <0x8>;
                                };
 
                                clock@2 {
                                                compatible = "gpio-gate-clock";
                                                clocks = <0x8>;
                                                #clock-cells = <0x0>;
                                                enable-gpios = <0x5 0x9 0x1>;
                                };
 
                                clock@3 {
                                                #clock-cells = <0x0>;
                                                compatible = "fixed-clock";
                                                clock-frequency = <0x17d7840>;
                                                clock-output-names = "ad9517_refclk";
                                                linux,phandle = <0x7>;
                                                phandle = <0x7>;
                                };
                };
 
        fpga-axi@0 {
                compatible = "simple-bus";
                #address-cells = <0x1>;
                #size-cells = <0x1>;
                ranges;
 
                dma@7c400000 {
                        compatible = "adi,axi-dmac-1.00.a";
                        reg = <0x7c400000 0x10000>;
                        #dma-cells = <0x1>;
                        interrupts = <0x0 0x39 0x0>;
                        clocks = <0x3 0x10>;
                        linux,phandle = <0x9>;
                        phandle = <0x9>;
 
                        dma-channel {
                                adi,source-bus-width = <0x40>;
                                adi,destination-bus-width = <0x40>;
                                adi,type = <0x0>;
                        };
                };
 
                dma@7c420000 {
                        compatible = "adi,axi-dmac-1.00.a";
                        reg = <0x7c420000 0x10000>;
                        #dma-cells = <0x1>;
                        interrupts = <0x0 0x38 0x0>;
                        clocks = <0x3 0x10>;
                        linux,phandle = <0xb>;
                        phandle = <0xb>;
 
                        dma-channel {
                                adi,source-bus-width = <0x40>;
                                adi,destination-bus-width = <0x40>;
                                adi,type = <0x1>;
                                adi,cyclic;
                        };
                };
 
                cf-ad9361-lpc@79020000 {
                        compatible = "adi,axi-ad9361-6.00.a";
                        reg = <0x79020000 0x6000>;
                        dmas = <0x9 0x0>;
                        dma-names = "rx";
                        spibus-connected = <0xa>;
                };
 
                cf-ad9361-dds-core-lpc@79024000 {
                        compatible = "adi,axi-ad9361-dds-6.00.a";
                        reg = <0x79024000 0x1000>;
                        clocks = <0xa 0xd>;
                        clock-names = "sampl_clk";
                        dmas = <0xb 0x0>;
                        dma-names = "tx";
                };
                efuse@f800d000 {
                        compatable = "xlnx,zynq-efuse";
                        reg = <0xf800d000 0x20>;
                };
                mysoftip {
                    compatible = "xlnx,socfpga-mysoftip";
                    interrupts = <0 94 4>;
                    interrupt-parent = <0x1>
                } ;
        };
};

 

Driver:

 

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/of.h>
 
#define DEVNAME "test_int"
 
static irq_handler_t __test_isr(int irq,void *dev_id,struct pt_regs *regs){
                printk(KERN_INFO DEVNAME":ISR\n");
 
                return(irq_handler_t)IRQ_HANDLED;
}
 
static int __test_int_driver_probe(struct platform_device *pdev){
                int irq_num;
 
                irq_num=94
                printk(KERN_INFO DEVNAME": IRQ %d about to be registered!\n",irq_num);
 
                return request_irq(irq_num,(irq_handler_t)__test_isr,0,DEVNAME,NULL);
}
 
static int __test_int_driver_remove(struct platform_device *pdev){
                int irq_num;
 
                irq_num=94;
 
                printk(KERN_INFO"test_int: IRQ %d about to be freed!\n",irq_num);
 
                free_irq(irq_num,NULL);
 
                return 0;
}
 
 
static const struct of_device_id __test_int_driver_id[]={
{.compatible="xlnx,socfpga-mysoftip"},
{}
};
 
static struct platform_driver __test_int_driver={
.driver={
.name=DEVNAME,
.owner=THIS_MODULE,
.of_match_table=of_match_ptr(__test_int_driver_id),
},
.probe=__test_int_driver_probe,
.remove=__test_int_driver_remove
};
 
module_platform_driver(__test_int_driver);
 
MODULE_LICENSE("GPL");
 

 

Makefile:

obj-m+=test_int.o
 
all:
                make -C /lib/modules/`uname -r`/build M=$(PWD) modules
 
clean:
                make -C /lib/modules/`uname -r`/build M=$(PWD) clean

/proc/interrupts

        CPU0       CPU1
 16:          0          0     GIC-0  43 Level     ttc_clockevent
 17:     334371     362985     GIC-0  29 Edge      twd
 20:      17036          0     GIC-0  82 Level     xuartps
 21:          0          0     GIC-0  45 Level     f8003000.ps7-dma
 22:          0          0     GIC-0  46 Level     f8003000.ps7-dma
 23:          0          0     GIC-0  47 Level     f8003000.ps7-dma
 24:          0          0     GIC-0  48 Level     f8003000.ps7-dma
 25:          0          0     GIC-0  49 Level     f8003000.ps7-dma
 26:          0          0     GIC-0  72 Level     f8003000.ps7-dma
 27:          0          0     GIC-0  73 Level     f8003000.ps7-dma
 28:          0          0     GIC-0  74 Level     f8003000.ps7-dma
 29:          0          0     GIC-0  75 Level     f8003000.ps7-dma
 33:       1388          0     GIC-0  54 Level     eth0
 35:      14840          0     GIC-0  56 Level     mmc0
 36:          0          0     GIC-0  57 Level     cdns-i2c
 37:      15135          0     GIC-0  58 Level     e0006000.spi
 38:         12          0     GIC-0  81 Level     e0007000.spi
 39:        204          0     GIC-0  40 Level     f8007000.devcfg
 40:         43          0     GIC-0  39 Level     f8007100.xadc
 41:          0          0     GIC-0  89 Edge      7c400000.dma
 42:          0          0     GIC-0  88 Edge      7c420000.dma
 94:          0          0  zynq-gpio  47 Level     test_int


 

0 Kudos
1 Reply
Explorer
Explorer
695 Views
Registered: ‎10-04-2017

Re: Interrupts from FPGA not show in Linux

The irq in the devicetree is not the irq number in the driver, don't hardcode it like that. Instead. look up your node in the devicetree and use the of API to get the irq number that works in the driver.
0 Kudos