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!

Reply

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

Accepted Solution Solved
Observer
Posts: 63
Registered: ‎04-05-2016
Accepted Solution

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

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


Accepted Solutions
Observer
Posts: 63
Registered: ‎04-05-2016

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

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.

 

View solution in original post


All Replies
Xilinx Employee
Posts: 1,128
Registered: ‎07-01-2010

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

@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.
----------------------------------------------------------------------------------------
Adventurer
Posts: 74
Registered: ‎12-03-2015

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

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

 

Observer
Posts: 63
Registered: ‎04-05-2016

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

@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.

Adventurer
Posts: 74
Registered: ‎12-03-2015

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

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

Observer
Posts: 63
Registered: ‎04-05-2016

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

@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

Observer
Posts: 63
Registered: ‎04-05-2016

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

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.

 

Newbie
Posts: 1
Registered: ‎05-19-2016

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

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
Explorer
Posts: 218
Registered: ‎11-22-2015

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

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

Observer
Posts: 63
Registered: ‎04-05-2016

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

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.