Linux Driver - Problem with IRQ

Hey guys.

I’ve been trying to make the mSGDMA module send over an interrupt request to the processor. I’ll post below what I have done and then hopefully someone can help me debug or find out what might be happening.

Here is my modified Device Tree Source to include mSGDMA:

msgdma@0x100000000 { compatible = "altr,msgdma-15.0", "altr,msgdma-1.0"; reg = <0x00000001 0x00000000 0x00000020>, <0x00000001 0x00000020 0x00000010>; reg-names = "CSR", "Descriptor_Slave"; interrupt-parent = <&hps_0_arm_gic_0>; interrupts = <0 43 4>; clocks = <&clk_0>; }; //end msgdma@0x100000000 (modular_sgdma_dispatcher)

And this piece of code is “encapsulated” by the bridge node (shown below):

bridge@0xc0000000 { compatible = "altr,bridge-15.0", "simple-bus"; reg = <0xc0000000 0x20000000 0xff200000 0x200000>; reg-names = "axi_h2f", "axi_h2f_lw"; clocks = <&clk_0 &clk_0 &clk_0>; clock-names = "h2f_axi_clock", "h2f_lw_axi_clock", "f2h_sdram0_clock"; #address-cells = <0x2>; #size-cells = <0x1>; ranges = <0x00000000 0x00000000 0xc0000000 0x00010000>, <0x00000000 0x00010000 0xc0010000 0x00000010>, <0x00000001 0x00000000 0xff200000 0x00000020>, <0x00000001 0x00000020 0xff200020 0x00000010>, <0x00000001 0x00020000 0xff220000 0x00000008>, <0x00000001 0x00010000 0xff210000 0x00000008>, <0x00000001 0x00010040 0xff210040 0x00000010>, <0x00000001 0x00010080 0xff210080 0x00000010>, <0x00000001 0x000100c0 0xff2100c0 0x00000010>, <0x00000001 0x00000040 0xff200040 0x00000010>;

So basically the interrupt I expect to see while trying to register the ISR is the number 43 (in qsys I connect the irq sender to the f2h_irq0 port and the number it shows at the right half of qsys is 3, so everything seems to be normal here).

Also, I wrote down a driver to deal and to register an ISR:

[CODE]
#include <linux/module.h>#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/of.h>

#define DEVNAME “msgdma_driver”
#define IRQ_NUMBER 43 // msgdma irq number

/* Global variables */
//static int msgdma_demo_driver_irq_num;

/* Prototypes */
static struct platform_driver __platform_driver;

/* Interrupt Service Routine */

static irq_handler_t __msgdma__isr(int irq, void *dev_id)
{
printk(KERN_INFO DEVNAME “: ISR\n”);

return (irq_handler_t) IRQ_HANDLED;

}

/* Set up probe platform */

static int __driver_probe(struct platform_device* pdev)
{
int irq_num;
int ret_val;

printk(KERN_INFO "__driver_probe entered \n");


irq_num = platform_get_irq(pdev,0);


if(irq_num < 0)
{
    pr_err("IRQ not availabel\n");
    return -1;
}


printk(KERN_INFO DEVNAME ": IRQ about to be registered! Number: %d \n", irq_num);


ret_val= request_irq(irq_num,
                (irq_handler_t) __msgdma__isr,
                IRQF_SHARED, 
                DEVNAME, 
                (void *) __msgdma__isr
                );


if (ret_val==0)
    printk(KERN_INFO "__driver_probe registered - msgdma \n");
else 
    printk("__driver_probe encountered errors and could not register IRQ\n" );


return ret_val;

}

/* Remove Probe Platform */

static int __driver_remove(struct platform_device *pdev)
{
int irq_num;

pr_info("__driver_remove enter \n");


/* stop DMA */


irq_num = platform_get_irq(pdev, 0);


printk(KERN_INFO "test_int: IRQ %d 'bout to be freed \n", irq_num);
free_irq(IRQ_NUMBER,NULL);


return 0;

}

static const struct of_device_id __msgdma_driver_id[] = {
{.compatible = “altr,msgdma-15.0”, },
//{.compatible = “altr,msgdma-1.0”, },
{/* end of table */}
};

MODULE_DEVICE_TABLE(of, __msgdma_driver_id);

static struct platform_driver __platform_driver = {
.driver = {
.name = “msgdma-15.0”,
.owner = THIS_MODULE,
.of_match_table = __msgdma_driver_id,
},
.probe=__driver_probe,
.remove=__driver_remove
};

module_platform_driver(__platform_driver);

MODULE_LICENSE(“GPL”);
[/CODE]

Then when I run it I get the following output:

__driver_probe entered msgdma_driver: IRQ about to be registered! Number: 47 __driver_probe registered - msgdma

So basically the code registers the interrupt to the GIC number 47… and this is where this thing drives me crazy lol… I try then to run some code that sets up the tx interrupt in the msgdma registers but nothing happens. Anyone knows why this happens?

Hi,

Not sure if this will help you but I struggled to figure out how the f2h IRQs were mapped on the Arria10.

When I look at the Arria 10 TRM it says that the F2S_FPGA_IRQ0 is mapped to GIC interrupt 51 but if you use that in the linux device tree it doesn’t work. The reason for that is that the first 32 interruptions are used for “software generated interrupts” and “private peripheral interrupts” and can’t be used for externals peripherals. Therefore linux considers that the interrupt number 0 is really the 32nd on the GIC.

So in other words, I had to use subtract 32 to the “real” GIC IRQ number to get the value in the device tree. For an Arria 10 that puts F2S_FPGA_IRQ0 at 19 instead of 51.

Hey Lionel!

I have solved this issue last week… Even though the device tree IRQ says the msgdriver IRQ number is 43 I register it as IRQ 47 (as Linux returns it to me the number 47 when I run “platform_get_irq(pdev,0)”…). I don’t know why or how things get messed up, but I can get it to work correctly.

That’s strange. Well hopefully it’ll be useful for the next person having this issue!

1 Like