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: 
Explorer
Explorer
15,433 Views
Registered: ‎04-05-2016

IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

Hello,

 

I have a driver ( .ko file ) that works perfectly fine in version 3.17 of the kernel ( something like 2014.2 of the Xilinx tools ).

 

As I am moving the files forward to the 4.4 kernel( something like 2015.4 of the Xilinx tooks ), I don't see any interrupts firing in /proc/interrupts

 

I have confirmed the interrupts are actually happening using ILA in Vivado.

 

The immediate difference that I noticed was that the 4th column in /proc/interrupts reads"zynq-gpio" rather than "GIC".

 

I do not have a DTS entry for the driver, as it is was not needed.  I went as far as creating an entry and reading the IRQ number that way, and it still does not work.

 

Again, this *does* work in 3.17.

 

Based off of many of the Xilinx driver source files, I can not find anything immediately apparent that I am doing differently with interrupts.

 

Could someone point me in the correct direction to get this to work?  It appears that there was the beginning of a conversation here:

 

https://forums.xilinx.com/t5/Embedded-Linux/How-to-use-fabric-interrupts-on-Zynq-with-Linux/td-p/635066

 

... however there is no resolution.  It seems like @mad_hdl was getting close, however the "work around" seemed very hackerish.


I think it has got to do with the IRQ not showing up as  "GIC", but as "zynq-gpio" in /proc/interrupts, but I don't know enough about the interrupt system to debug that.  I would assume that if I do ...

 

rval = request_irq(
         IRQ_NUMBER, // IRQ_F2P[0], so SPI 61, translated to 29 ( SPI # - 32 )
         interrupt_handler, // driver interrupt function
         IRQF_TRIGGER_HIGH, // trigger on a value of high
         STR_ID_IRQ, // string name of IRQ ( shows up in /proc/interrupts
         &dev_struct // my device struct
);

... with IRQ_NUMBER set to 29, that everything should work just fine.  But, that does not appear to be the case .....

 

I find it hard to believe that @mad_hdl and I are the only two people with this problem.  Any support is greatly appreciated.

 

Thanks,

 

-TD

0 Kudos
1 Solution

Accepted Solutions
Explorer
Explorer
28,225 Views
Registered: ‎04-05-2016

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

I had a hunch ( based on other forum posts ) that the answer to this issue was due to a translation/offset in the "new" way the GIC was implemented.

 

I switched over my module to a platform_driver, and was successful.  By using this code (note: not full code for the driver, and hacked around to be generic, but it should show you the path to take) I was able to get interrupts working as expected.

 

struct mydriver_dm
{
   void __iomem *    membase; // ioremapped kernel virtual address
   dev_t             dev_num; // dynamically allocated device number
   struct cdev       c_dev;   // character device
   struct class *    class;   // sysfs class for this device
   struct device *   pdev;    // device
   int               irq; // the IRQ number ( note: this will NOT be the value from the DTS entry )
};

static struct mydriver_dm dm;

static int mydriver_of_probe(struct platform_device *ofdev)
{

   int irq;
   struct resource *res;

   res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);
   if (!res) {
      printk(KERN_INFO "could not get platform IRQ resource.\n");
      goto fail_irq;
   }

   // save the returned IRQ
   dm.irq = res->start;

   printk(KERN_INFO "IRQ read form DTS entry as %d\n", dm.irq);

   rval = request_irq(dm.irq, mydriver_interrupt, 0 , "mydriver, &dm);
   if(rval)
   {
      printk(KERN_INFO "can't get assigned irq: %d\n", dm.irq);
      goto fail_irq;
   }

   /* do all the other things you need to for your driver here */

   return 0;

fail_irq:
   return -1

}

static int mydriver_of_remove(struct platform_device *of_dev)
{
    free_irq(dm.irq, &dm);
}

static irqreturn_t mydriver_interrupt(int irq, void * arg2)
{
    /* service iterrupt here */
}

static const struct of_device_id mydriver_of_match[] = {
   { .compatible = "mycompany,mydriver", },
   { /* end of list */ },
};
MODULE_DEVICE_TABLE(of, mydriver_of_match);

static struct platform_driver mydrive_of_driver = {
   .probe      = mydrive_of_probe,
   .remove     = mydrive_of_remove,
   .driver = {
      .name = "mydrive",
      .owner = THIS_MODULE,
      .of_match_table = mydrive_of_match,
   },
};

module_platform_driver(mydrive_of_driver);

With a DTS entry of:

 

      mydriver@83C00000 {
            compatible = "mycompany,mydriver";
            interrupt-parent = < 0x3 >;
            interrupts = < 0 29 4 >;
            reg = < 0x83C00000 0x1000 >;
    };

where the 0x83C0000 is the address from the Addresses tab in Vivado, and the 0x1000 is the address range.

 

For interrupts = < 0 29 4 >, 0 is defining it as a SPI ( general purpose ) interrupt, 29 is the LSB of IRQ_F2P ( TRM says 61, subtract 32 ), and 4 is level-high triggered.

 

Take a look at any of the Xilinx drivers to see good examples of how platform drivers should be written when your hardware can just disapear ( PL reprogrammed ).  The drivers/net/ethernet/xilinx_emaclite.c file is a good place to start.

The answer here is that the GIC is no longer mapped to the values represented in the TRM, or that number minus 32.  The mapping is not static, and needs to be requested from the platform_device.  An easy way to do that is in the _prob() function in a platform_driver.

 

18 Replies
Xilinx Employee
Xilinx Employee
15,293 Views
Registered: ‎07-01-2010

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

@timduffy

 

Are you using Zynq or ZynqMP in this case?  I have seen a  similar issue with 2015.4 for ZynqMP interrupt.

 

Can you share the device-tree for the same?

 

Reference: http://www.wiki.xilinx.com/Linux+GPIO+Driver

 

Regards,

Achutha

 

---------------------------------------------------------------------------------------------
Kindly note- Please mark the Answer as "Accept as solution" if information provided is helpful.

Give Kudos to a post which you think is helpful and reply oriented.
----------------------------------------------------------------------------------------
0 Kudos
Adventurer
Adventurer
15,276 Views
Registered: ‎12-03-2015

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

Hi,

 

I have seen this before. The problem was the mapping of GIC interrupts changed. The PL interrupts connected to the IRQ_F2P port [15:0] are now mapped to [91:84] for the MSB, and [68:61] for the LSB. I have an UARTLite connected to GIC line 0 which is mapped to 61 on the PS. Something connected to GIC 15 will be 91 on the PS. The device tree enty will have 32 subtracted from this so it will show up as 29. My entry in system-top.dts for the uart-lite interrupt:

 

&axi_uartlite_0 {
interrupt-parent = <&intc>;
interrupts = <0 29 1>;
};

Ron

 

0 Kudos
Explorer
Explorer
15,270 Views
Registered: ‎04-05-2016

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

@achutha,

 

Thank you for your response.

 

I am using the Zynq-7000.  I didn't have a DTS entry ( as per my post stated ) in the 3.17 kernel, so I see no reason why I would need one in the 4.4 kernel ( and if I do, then I'd like to see the documentation from Xilinx explaining why ).

I'm unsure what the reference link is for.  I am not using the GPIO at all in my design.  I am using the IRQ_F2P for interrupts, which should be using the GIC, not the GPIO.


@rgrossman,

 

Thank you for your response.  I did see that the mapping for the IRQ_F2P is split, and requires the -32 ( per the Zynq-7000 TRM ).  I have tried both 29 and 61 in my kernel module, and have verified using ILA that the interrupt goes high into the LSB of the IRQ_F2P input on the PS7.  The interrupt handler in the kernel module never sees it, though, and when I > cat /proc/interrupts I do not see the interrupt increasing ( I suspect because it is not the correct number ... ).

 

It's frustrating when things don't work when moving form one version of software to anther, however I do understand how things can get overlooked.  The kernel is not simple software.  The thing that is frustrating is that I can't seem to find any documentation from Xilinx on this.  I just refuse to believe I'm the only one who has seen this issue when moving to the latest kernel version ...

 

Again, thank you both for your responses.

0 Kudos
Adventurer
Adventurer
15,259 Views
Registered: ‎12-03-2015

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

Hi Tim,

 

I did some digging and found a post that I read a couple of weeks ago that seems close to your problem. The problem was, 

"The new GIC driver moves to the irq_domain architecture in drivers/irqchip."

The link to the thread: here.

 

Ron

0 Kudos
Explorer
Explorer
15,253 Views
Registered: ‎04-05-2016

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

@rgrossman,

 

I did come across that thread.  These as well:

 

Here is another person with the same issue:

And another person:

 
I see no reason why the DTS would be invovled at all.  The TRM says that 61 is the LSB of the IRQ_F2P port, and to subtract 32 from it to get to the SPI kernel IRQ.  Thus ...
 
 interrupts = <0 29 4>;

 

Should produce a line in /proc/interupts that is mapping the GIC to interupt 29, and thus fire my interrupt handler specified in the request_irq() call.  That is not happening.

 

One thing I am thinking is that I do not use the .probe() function in my device driver.  Possible I need to do that in teh 4.4?

 

Thanks,

 

-TD

0 Kudos
Explorer
Explorer
28,226 Views
Registered: ‎04-05-2016

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

I had a hunch ( based on other forum posts ) that the answer to this issue was due to a translation/offset in the "new" way the GIC was implemented.

 

I switched over my module to a platform_driver, and was successful.  By using this code (note: not full code for the driver, and hacked around to be generic, but it should show you the path to take) I was able to get interrupts working as expected.

 

struct mydriver_dm
{
   void __iomem *    membase; // ioremapped kernel virtual address
   dev_t             dev_num; // dynamically allocated device number
   struct cdev       c_dev;   // character device
   struct class *    class;   // sysfs class for this device
   struct device *   pdev;    // device
   int               irq; // the IRQ number ( note: this will NOT be the value from the DTS entry )
};

static struct mydriver_dm dm;

static int mydriver_of_probe(struct platform_device *ofdev)
{

   int irq;
   struct resource *res;

   res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);
   if (!res) {
      printk(KERN_INFO "could not get platform IRQ resource.\n");
      goto fail_irq;
   }

   // save the returned IRQ
   dm.irq = res->start;

   printk(KERN_INFO "IRQ read form DTS entry as %d\n", dm.irq);

   rval = request_irq(dm.irq, mydriver_interrupt, 0 , "mydriver, &dm);
   if(rval)
   {
      printk(KERN_INFO "can't get assigned irq: %d\n", dm.irq);
      goto fail_irq;
   }

   /* do all the other things you need to for your driver here */

   return 0;

fail_irq:
   return -1

}

static int mydriver_of_remove(struct platform_device *of_dev)
{
    free_irq(dm.irq, &dm);
}

static irqreturn_t mydriver_interrupt(int irq, void * arg2)
{
    /* service iterrupt here */
}

static const struct of_device_id mydriver_of_match[] = {
   { .compatible = "mycompany,mydriver", },
   { /* end of list */ },
};
MODULE_DEVICE_TABLE(of, mydriver_of_match);

static struct platform_driver mydrive_of_driver = {
   .probe      = mydrive_of_probe,
   .remove     = mydrive_of_remove,
   .driver = {
      .name = "mydrive",
      .owner = THIS_MODULE,
      .of_match_table = mydrive_of_match,
   },
};

module_platform_driver(mydrive_of_driver);

With a DTS entry of:

 

      mydriver@83C00000 {
            compatible = "mycompany,mydriver";
            interrupt-parent = < 0x3 >;
            interrupts = < 0 29 4 >;
            reg = < 0x83C00000 0x1000 >;
    };

where the 0x83C0000 is the address from the Addresses tab in Vivado, and the 0x1000 is the address range.

 

For interrupts = < 0 29 4 >, 0 is defining it as a SPI ( general purpose ) interrupt, 29 is the LSB of IRQ_F2P ( TRM says 61, subtract 32 ), and 4 is level-high triggered.

 

Take a look at any of the Xilinx drivers to see good examples of how platform drivers should be written when your hardware can just disapear ( PL reprogrammed ).  The drivers/net/ethernet/xilinx_emaclite.c file is a good place to start.

The answer here is that the GIC is no longer mapped to the values represented in the TRM, or that number minus 32.  The mapping is not static, and needs to be requested from the platform_device.  An easy way to do that is in the _prob() function in a platform_driver.

 

Visitor francky400
Visitor
14,880 Views
Registered: ‎05-19-2016

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

Hello timduffy,

 

I am deseperate to obtain interuption handling like this discution --> zynq PL to PS interrupts (IRQ_F2P 61) with new linux kernel with no static irq mapping.

 

I have try to follow you platfom driver example but it is very difficult for me.

Please have you a complete platform driver code for a simple Vivado Zynq project with a "AXI TIMER" like the image attacher for example.

The AXI TIMER0 is mapped to 0x4280_0000 and irq is connected to IRQ_F2P0 (IRQ61)

The AXI TIMER1 is mapped to 0x4281_0000 and irq is connected to IRQ_F2P1 (IRQ62)

 

Best Regards

Please help me

 

Franck

axiTimer.jpg
0 Kudos
Explorer
Explorer
14,870 Views
Registered: ‎11-22-2015

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

Hi,

 

  If you generate your DTS with the HDF file and the dts branch that matches your kernel you should get a devicetree entry that will give you the correct mapping.  Then you can get the correct value in your kernel driver by parsing the devicetree.   Did you try something like this?

  I just connected up a AXI-GPIO block with interrupt enabled to IRQ_F2P and didn't have to do anything special to get this to work as a userspace interrupt.

 

jeff

0 Kudos
Explorer
Explorer
14,836 Views
Registered: ‎04-05-2016

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution
Jeff,

If you read my own response posted 05-11-2016 09:50 AM, that is exactly what I did. The problem arose with the change in 3.19 on how interrupts were being handled in the kernel. Previously the IRQ in the DTS file was the same IRQ number you needed to request in your driver. Today in the kernel that is not the case. You must parse the IRQ using the .probe() function and the platform_get_resource(ofdev, IORESOURCE_IRQ, 0) function.

@francky400,

If you post a separate forum post I will do my best to answer your question there.
0 Kudos
Explorer
Explorer
10,989 Views
Registered: ‎11-22-2015

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution
 

That was supposed to be directed at @francky400.  

 

However, are you saying you previously hardcoded the value in the devicetree into your driver instead of parsing the the devicetree? 

 

jeff

0 Kudos
Participant danwwright
Participant
7,400 Views
Registered: ‎10-12-2014

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

I too am facing this exact same issue- no fabric interrupts seen after the move to kernel 4.4.  I've read the solution from  timduffy but when I add the platform_get_resource() call to my driver probe() function it always returns NULL.  I'm guessing that this is because my device tree is deficient somehow.  My issue is how to correctly remedy this.

 

My driver has built into it Xilinx SDK code for speaking with:

axi_dma (3 instances)

axi_gpio (1 instance), and

axi_uartlite  (1 instance).

All 5 of these interrupts I would like to map to my driver.

 

My device tree was generated by "petalinux-config --get-hw-description=hw-description" using the .hdf exported from my Vivado design and so the generated pl.dtsi has device tree entries that contain all the particulars needed to make the kernel aware of their existence.

 

My challenge is how to compose a correct device tree entry to make the system aware that all of these "belong to" my driver so that (presumably) the platform_get_resource() call in my driver probe() function will no longer be returning NULL and so I can complete the fix that timduffy recommends.

 

Can anyone point me to an example of such a device tree example?  The example would beed to show hos all 5 of there relevant interrupts can all be forwarded to the specified driver.  Thanks!

 

 

 

0 Kudos
Visitor grobins
Visitor
7,288 Views
Registered: ‎10-11-2016

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

I discovered that in 4.4 (or whenever this changed), IRQ 61 now maps to 166, and 62 to 167. If instead of doing request_irq(61, ...) I do request_irq(166, ...) I get interrupts from fabric.

 

I went the LONG way about this reading the posts on this topic and then changing my driver to a platform driver and putting the interrupt in the device tree using IRQs 29 and 30 as I read on here. I then noticed doing either of these calls returned 166:

pl_irq0 = platform_get_irq(pdev, 0);
pl_irq0 = irq_of_parse_and_map(dev->of_node, 0);

 

So when I simply do request_irq(166, ...) and to cat /proc/interrupts I get this for my interrupt:

166:  0   0   GIC  61 Level   mypl0

Instead of the weird assignment on zynq_gpio 39 before.

 

So long story short, what is this strange magic mapping of 61 --> 166? We just add 105? Where does 105 come from? And is this predictable?

0 Kudos
Visitor grobins
Visitor
7,270 Views
Registered: ‎10-11-2016

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

I found out to some extent where the mapping comes from, the IRQ domain mapping. If you build the kernel with CONFIG_IRQ_DOMAIN_DEBUG=y, then mount -t debugfs none /sys/kernel/debug, then cat /sys/kernel/debug/irq_domain_mapping, you'll see the linux IRQ number in first column and the HW IRQ number (in hex) in second column. The domain being "GIC".

 

The F2P IRQ gets added to the domain table only if it is defined in the device tree for some device you make up (device tree number needs to be hwirq-32). So you can't go and request 166 (in my case) unless it has been mapped by something (reference code in kernel/irq/irqdomain.c). And 166 only works for my device tree, I think it is added more or less in order of definition of the various devices and skips the disabled ones.

 

I haven't quite figured out yet why 7 GIC interrupts map to linux IRQ 16-22, causing the GPIO interrupts to start at 23, end at 140 (there are 118 for zynq), then GIC starts again at 141.

0 Kudos
Adventurer
Adventurer
6,137 Views
Registered: ‎06-05-2014

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

@grobins I tried you cat /sys/kernel/debug/irq_domain_mapping and I see at the end

 

 49  0x00042  GIC              0xc068afa4     *    LINEAR          GIC

 

which I think is my uartlite I have on the 9th pin of my zynq pl2ps interrupt. I would think this would be 84-32=52 but the above doesn't seem to match up. 

 

On the 4.4 kernel what should the entry in the device tree be for the GIC 84 entry?

0 Kudos
Visitor gsanthar06
Visitor
3,029 Views
Registered: ‎04-04-2018

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

Can you tell me where to find the address for interrupt handler to be entered in device tree.

what is that address which should be entered in device tree for interrupt handler for private interrupt like CORE0_nIRQ

0 Kudos
Adventurer
Adventurer
3,015 Views
Registered: ‎10-04-2017

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

The interrupt handler is in the software, there is nothing in the devicetree that deals with the interrupt handler.  You write the interrupt handler and register that function when you call request_irq.  

 

jeff

 

0 Kudos
Visitor gsanthar06
Visitor
2,980 Views
Registered: ‎04-04-2018

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution
Thanks Jeff,

In my driver when I call request_irq I get the below error. I cant find why I get this error. what is the significance of error -22

[ 4663.413126] <1>Hello module world.
[ 4663.413168] <1>Module parameters were (0xdeadbeef) and "default"
[ 4663.413405] irqsfp 43c00000.irqsfp: Device Tree Probing
[ 4663.413471] irqsfp 43c00000.irqsfp: testmodule: Could not allocate interrupt 169.
[ 4663.413524] irqsfp: probe of 43c00000.irqsfp failed with error -22

0 Kudos
Visitor sisxy
Visitor
2,911 Views
Registered: ‎04-18-2018

Re: IRQF2P Interupt not being seen in driver when moving to 4.4, but works in 3.17

Jump to solution

hi,

I have the same problems with you ,and I have followed your steps,but when I install the .ko module,the module did not execute the mydriver_of_probe().why?

Thanks!

 

 

 

0 Kudos