GPIO to IRQ

Hi,

I am currently learning how to process interrupts in kernel module
generated by GPIO pins on BB xM. In my particular case I am using GPIO
143 configured as input. The question which puzzled me is how to
calculate the IRQ number which corresponds to this pin? I would really
appreciate if someone can explain or point me to the place to read
about it. I've browsed through TRM but did not found such information
there (or maybe I just overlooked it).

After some unsuccessful attempts to deduce the IRQ number I finally
just called gpio_to_irq(143); from <linux/gpio.h> and got 303 as a
return value which is complete mystery for me :slight_smile: . In addition, it
does not work as expected but it might be because of wrong pin
configuration. So if someone knows how to get 303 (or whatever is the
proper IRQ number) knowing the GPIO number is 143 i would appreciate
any explanations.

Thank you,
Andrey.

https://www.kernel.org/doc/Documentation/gpio.txt

gpio_to_irq() is the right function. GPIO numbers and IRQ numbers come
from different sets of numbers and basically have no correlation, the
gpio_to_irq() function maps them together.

Do you have the pin-mux setup correctly for the pin you want to use?
Have you called request_irq(), gpio_direction_XXX(), and gpio_export()?
Have you specified what kind of GPIO state you want to cause the
interrupt (ie: IRQF_TRIGGER_FALLING)?

As I understand it, the order should be:
1. Setup pin-mux
2. gpio_request() the pin
3. gpio_direction_input()
4. request_irq(gpio_to_irq(), ..., IRQF_TRIGGER_XXXX, ...)

LDDv3 [1] can be helpful, too.

[1]:https://lwn.net/Kernel/LDD3/

-Andrew

Thank you Andrew for the quick response!

gpio_to_irq() is the right function. GPIO numbers and IRQ numbers come
from different sets of numbers and basically have no correlation, the
gpio_to_irq() function maps them together.

There are several reasons why I am not using gpio* functions (whether
it makes sense or not is a different discussion). Independent of that,
I just want to understand how gpio number to irq number mapping is
organized. Let's say, as if I would need to write gpio_to_irq()
funciton myself. I was expecting some kind of calculations involving
gpio number, bunk number, some base offset, etc. but was unable to
find it. That is why I asked for pointers in the mail list.

Regards,
Andrey.

There are several reasons why I am not using gpio* functions (whether
it makes sense or not is a different discussion). Independent of
that, I just want to understand how gpio number to irq number
mapping is organized. Let's say, as if I would need to write
gpio_to_irq() funciton myself. I was expecting some kind of
calculations involving gpio number, bunk number, some base offset,
etc. but was unable to find it. That is why I asked for pointers in
the mail list.

Can you explain why you don't want to use the gpio* functions? They
work rather well.

I am writing Xenomai (xenomai.org) realtime driver (RTDM) to handle
quadrature encoders. This is rather new area for me and I am learning.
My reasons to avoid gpio* functions was the uncertainty if calling
Linux kernel functions (like gpio*) will cause the context switch from
real-time domain to non-real-time. That is why, for the first
prototype I decide to avoid these functions completely and configure
pins myself which works fine for output.

Now I want to handle rotary encoder inputs and need to react on
interrupts triggered by the gpio pins. Xenomai's RTDM API offers own
set of functions (similar to kernel's functions) to register interrupt
handlers. But, of course, I need to supply the IRQ number. And this is
where my original question came from.

If you're curious as to what they do, use the source! :slight_smile:

Sure. But I was hope to find some plain text explanations before
diving in the sources.

Thanks,
Andrey.

Hi Andrey,

OMAP TRM won’t describe the Linux interrupt number. How Linux translates this interrupt to its IRQ number is some BSP business that is beyond my knowledge.

But if you are interested in OMAP itself, you can search for “interrupt mapping” in the TRM. It shows you how the 6 GPIO modules are tied to the MPU and IVA with IRQ lines. So, each 32 GPIO lines (one GPIO module) has one MPU IRQ line. From the IRQSTATUS (not 100% sure about the reg name at the moment) of this GPIO module, the kernel (or ISR for bare system) can identify the GPIO line that is the source of the interrupt.

Linux kernel hides all this and abstracts the complexities in just an IRQ number.

I hope thjs helps.

-H

Hi Hesham,

OMAP TRM won't describe the Linux interrupt number. How Linux translates
this interrupt to its IRQ number is some BSP business that is beyond my
knowledge.

But if you are interested in OMAP itself, you can search for "interrupt
mapping" in the TRM. It shows you how the 6 GPIO modules are tied to the MPU
and IVA with IRQ lines. So, each 32 GPIO lines (one GPIO module) has one MPU
IRQ line. From the IRQSTATUS (not 100% sure about the reg name at the
moment) of this GPIO module, the kernel (or ISR for bare system) can
identify the GPIO line that is the source of the interrupt.

Linux kernel hides all this and abstracts the complexities in just an IRQ
number.

Thanks for your comments! It seams like the only way to understand it
is to look through the kernel sources :slight_smile: .

Thanks,
Andrey.

Hi Hesham,

OMAP TRM won’t describe the Linux interrupt number. How Linux translates
this interrupt to its IRQ number is some BSP business that is beyond my
knowledge.

But if you are interested in OMAP itself, you can search for “interrupt
mapping” in the TRM. It shows you how the 6 GPIO modules are tied to the MPU
and IVA with IRQ lines. So, each 32 GPIO lines (one GPIO module) has one MPU
IRQ line. From the IRQSTATUS (not 100% sure about the reg name at the
moment) of this GPIO module, the kernel (or ISR for bare system) can
identify the GPIO line that is the source of the interrupt.

Linux kernel hides all this and abstracts the complexities in just an IRQ
number.

Thanks for your comments! It seams like the only way to understand it
is to look through the kernel sources :slight_smile: .

Hi Andrey,

Did you get to the bottom of this? I am trying to do some interrupt driven programming on the BeagleBone with Xenomai as well. I have a reasonable understanding of how to set-up the pins by directly editing the CPU registers so that they can generate the interrupts, but just like you have no idea how to compute the IRQ number.

Thanks!
Stefan

Hi Stefan,

Did you get to the bottom of this? I am trying to do some interrupt driven
programming on the BeagleBone with Xenomai as well. I have a reasonable
understanding of how to set-up the pins by directly editing the CPU
registers so that they can generate the interrupts, but just like you have
no idea how to compute the IRQ number.

I decide to stick with kernel gpio library which offers this
functionality and stop my attempts to find out how the mapping is done
by kernel. My tests did not show any side effects or disadvantages of
using it with Xenomai. So I would recommend just to use gpio_to_irq()
function for this purpose.

Regards,
Andrey.

Hi Stefan,

Did you get to the bottom of this? I am trying to do some interrupt driven
programming on the BeagleBone with Xenomai as well. I have a reasonable
understanding of how to set-up the pins by directly editing the CPU
registers so that they can generate the interrupts, but just like you have
no idea how to compute the IRQ number.

I decide to stick with kernel gpio library which offers this
functionality and stop my attempts to find out how the mapping is done
by kernel. My tests did not show any side effects or disadvantages of
using it with Xenomai. So I would recommend just to use gpio_to_irq()
function for this purpose.

Thanks!

I have a follow up question. I could not find an example of how to handle interrupts in kernel space, only in user space.

After writing to the important registers to enable the hardware interrupt generation, I am thinking of doing the following in the kernel module initialization function:

rt_intr_create(&intr, &intrName, irqNumber, irq_Function, NULL, 0);

where irqNumber will be supplied by the gpio_to_irq() function. Is there anything special about the irq serving function (irq_Function), is there some prototype out there that I could look at (I could not find anything apart from this: http://www.cs.ru.nl/lab/xenomai/exercises/ex09/Exercise-9.html )?

Thanks again!

Stefan

After writing to the important registers to enable the hardware interrupt
generation, I am thinking of doing the following in the kernel module
initialization function:

rt_intr_create(&intr, &intrName, irqNumber, irq_Function, NULL, 0);

AFAIK, it is recommendet to use RTDM API for xenomai kernel modules.
That is why, rtdm_irq_request(...) is the way to register interrupt
handler.

is there
some prototype out there that I could look at (I could not find anything
apart from this:
http://www.cs.ru.nl/lab/xenomai/exercises/ex09/Exercise-9.html )?

I think RT serial driver is a good example to begin:
YOUR_XENO_DIR/ksrc/drivers/serial/*

Regards,
Andrey.

After writing to the important registers to enable the hardware interrupt
generation, I am thinking of doing the following in the kernel module
initialization function:

rt_intr_create(&intr, &intrName, irqNumber, irq_Function, NULL, 0);

AFAIK, it is recommendet to use RTDM API for xenomai kernel modules.
That is why, rtdm_irq_request(…) is the way to register interrupt
handler.

is there
some prototype out there that I could look at (I could not find anything
apart from this:
http://www.cs.ru.nl/lab/xenomai/exercises/ex09/Exercise-9.html )?

I think RT serial driver is a good example to begin:
YOUR_XENO_DIR/ksrc/drivers/serial/*

Thanks again! I did have a wander through the code, and I’ve so far come up with the following:

rtdm_irq_request followed by enabling the correct GPIO_IRQSTATUS_SET_0 and GPIO_RISINGDETECT bits.

Is there anything that I am missing here?

Checking the /proc/interrupts and /proc/xenomai/irq does not show the interrupts being registered after the kernel driver is loaded.

Thanks!

– Stefan

Thanks again! I did have a wander through the code, and I've so far come up
with the following:

rtdm_irq_request followed by enabling the correct GPIO_IRQSTATUS_SET_0 and
GPIO_RISINGDETECT bits.

Is there anything that I am missing here?

I think you should also set GPIO direction to IN.

Regards,
Andrey.

Thanks again! I did have a wander through the code, and I’ve so far come up
with the following:

rtdm_irq_request followed by enabling the correct GPIO_IRQSTATUS_SET_0 and
GPIO_RISINGDETECT bits.

Is there anything that I am missing here?

I think you should also set GPIO direction to IN.

Sorry, I did do that by writing 0xFFFFFFFF to the GPIO_OE register.

One thing I noticed though is that the status of GPIO_IRQSTATUS_SET_0 did not change after my write to it.

However, all of the above should not affect whether the IRQ is registered or not, just whether it is generated, right?

Hi guys!

I’ve started experimenting talking between two BeagleBones, and am using interrupt to pass two different types of data.

However, it seems to me if you try to transmit a word and a flag on one GPIO bank from BeagleBone 1 and use the flag as an interrupt on the BeagleBone 2 to read the data, this does not trigger the interrupt. Sending just the flag, however does trigger the interrupt. What is the reason for this?

Also, would sending the interrupt on a different bank, solve the problem?

Kind Regards,
Stefan