relationship between controller interrupt no and interrupt no in linux kernel - linux

I am developing our own CAN kernel module in i.mx6 processor. Now we want to write ISR for CAN TX and RX. We are able to write ISR, but my question is for register my ISR using request_irq function, what is the irq no i have to give. What is the relation between interrupt no specified in controller datasheet and irq no in the above function.
Thanks in advance,
NSN

Are we talking about on-chip FlexCAN or is this an externally connected CAN controller like MCP2515? There is already a FlexCAN driver available in the kernel. For on-chip peripherals the IRQ's are already defined in the Technical Reference Manual. For iMX6D/Q have a look at Chapter 3 Interrupts and DMA events. The interrupts are specified in device tree and retrieved using request_irq. For a CAN controller, let's say connected over SPI, a GPIO can be used as interrupt and the interrupt would be specified in device tree using "interrupt-parents" and "interrupts" property.
For the exact relation, let's consider an example. The CAN1 node is here with the "interrupts" property having a number of 110. If you look at Section 3 of TRM, FlexCAN1 is suppose to have an IRQ number of 142. Since the ARM Cortex A9 domain numbers start from 32, just subtract this from 142 to get the number of 110.
Edit: Seems I was not fully clear and talked from the device tree POV. The IRQ number for request_irq should have come from a call to platform_get_irq which returns Linux IRQ numbers. Also see this.

Related

How linux know which irq number should be used?

I am not a driver programmer, I don't have a clear picture of how linux assign irq number for pcie devices.
From an NIC driver example, it seems Linux already know which irq number should be used before the function of 'probe' or 'open' was excuted.
ex:
https://github.com/torvalds/linux/blob/4608f064532c28c0ea3c03fe26a3a5909852811a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c#L6608
err = ixgbe_request_irq(adapter);
ixgbe can get irq number by using the data of the 'adapter' variable, it means the irq value already inside adapter structure, it is not a generated number, it is an already existed value.
if it is read from pci/pcie configuration space, wasn't it very easy to conflict with other devices?
if it is generated/arrange by kernel, how the irq number already inside the 'adapter' variable? ( or it is assigned by BIOS ? )
For interrupt for MSI, it seems generated by kernel ??

Determining Interrupt index in Linux kernel 4+

I have an interrupt connected to the GIC of an ARM processor in a Xilinx Zynq-7000. Previously, the recommended way to use an interrupt in Linux would be to use
request_irq(INTERRUPT_INDEX,interrupt_handler,0,DEVICE_NAME,DEVICE_ID);
where INTERRUPT_INDEX would be a number you could obtain from your hw_definition file.
However, in more recent Linux kernels, apparently IRQs use virtual indicies, which means the number listed in the hw_definition file no longer corresponds to the interrupt I am trying to monitor.
How can I determine the proper values to use for INTERRUPT_INDEX, DEVICE_NAME, and DEVICE_ID in order to register an interrupt handler to a given GIC interrupt?

How can I know which interrupt line is shared or not, and which interrupt line is free in Linux?

I am going to write a PCIe base serial I/O card driver in Linux.
As per my knowledge through the configuration space, it provides the interrupt line, and through the IRQF_SHARED flag we are able to share the interrupt handler with that corresponding IRQ line.
But my confusion is how can I know which line is shared or not shared?
For a device driver, there is no useful way (and especially no portable way) to find out if the interrupt line is actually shared, and this could change at any time by loading/unloading other drivers.
PCI drivers must always assume that their interrupt might be shared.
Note: PCI Express devices are supposed to support MSIs (message-signaled interrupts), which are never shared.
Your driver should enable MSIs if at all possible.
However, it is not guaranteeed that the system supports them.
Kernel-assisted probing
The Linux kernel offers a low-level facility for probing the interrupt number. It works
for only nonshared interrupts, but most hardware that is capable of working in a
shared interrupt mode provides better ways of finding the configured interrupt num-
ber anyway. The facility consists of two functions, declared in <linux/interrupt.h>
(which also describes the probing machinery):
unsigned long probe_irq_on(void);
This function returns a bit mask of unassigned interrupts. The driver must pre-
serve the returned bit mask, and pass it to probe_irq_off later. After this call, the
driver should arrange for its device to generate at least one interrupt.
int probe_irq_off(unsigned long);
After the device has requested an interrupt, the driver calls this function, passing
as its argument the bit mask previously returned by probe_irq_on. probe_irq_off
returns the number of the interrupt that was issued after “probe_on.” If no inter-
rupts occurred, 0 is returned (therefore, IRQ 0 can’t be probed for, but no cus-
tom device can use it on any of the supported architectures anyway). If more than
one interrupt occurred (ambiguous detection), probe_irq_off returns a negative
value.
The programmer should be careful to enable interrupts on the device after the call to
probe_irq_on and to disable them before calling probe_irq_off. Additionally, you
must remember to service the pending interrupt in your device after probe_irq_off.
Run cat /proc/interrupt. In the rightmost column of the output you should see your device on one of the interrupts lines. If it's shared you'll see other devices assigned to that interrupt as well.

ARM Cortex M3 GPIO Interrupts - One ISR per port with 8 pins - How to handle all pins?

I'm using the Luminary LM3S8962 micro-controller and its included Library Guide, but this should be relevant to any ARM Cortex-M3s that have Nested Vector Interrupts.
You can only register one interrupt service routine function with an entire GPIO Port. A GPIO port typically has 8 pins on it, each of which can be configured with an interrupt. For each pin, you can test whether or not an interrupt "happened" on it (is pending), right? and for each pin you can clear a pending interrupt, right?
If a pin on the GPIO port triggers the ISR then the processor is in the ISR. Then what happens if another pin on the same port triggers an interrupt while we're in the ISR? We assume the code detects what pins have pending interrupts.
- Is this ISR interrupted and a new one begins, with the same code, but an updated PinInterruptStatus register ? (I hope not)
- Is this ISR executed until completion, immediately executing the interrupt for the other pin right afterward? (I know ARM Cortex M3 implements tail-chaining of interrupts)
- Or must there be a while loop that loops until all the pins have been cleared, clearing a pin after it has been processed?
maybe this will help:
http://www.ti.com/lit/gpn/lm3s8962
As stated in the comment: generally ISRs should take steps to prevent reentrancy. In something like a PIC, this could be as simple as disabling the interrupt at the "top" of the ISR, and enabling the interrupt at the "bottom". The M3's NVIC is a bit more complicated. This white paper (http://www.arm.com/files/pdf/IntroToCortex-M3.pdf) states the following on p.7:
The NVIC supports nesting (stacking) of interrupts, allowing an
interrupt to be serviced earlier by exerting higher priority. It also
supports dynamic reprioritisation of interrupts. Priority levels can
be changed by software during run time. Interrupts that are being
serviced are blocked from further activation until the interrupt
service routine is completed, so their priority can be changed without
risk of accidental re-entry.
The above discussion directly addresses the possibility of same interrupt reentrancy, and it also introduces the concept of prioritization to handle interrupts of higher priority interrupting your ISR.
This reference is pretty good: http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/DUI0552A_cortex_m3_dgug.pdf. On p. 4-9, you'll find instructions to enable/disable interrupts. On page 4-6, you'll find a description of the Interrupt Clear-pending Registers. Using these, you can determine what interrupts are pending. If you really want to get fancy with interrupt enable/disable control, check out the BASEPRI and BASEPRO_MAX registers.
Having said that, I'm not sure I agree with your statement that your question is relevant to any Cortex-M3. Keil (my flavor of Cortex-M3) mentions that the EXTI (external interrupt controller) handles GPIO pin interrupts. Interestingly, the ARM documentation briefly discusses "EXTI", but does not refer to it as a "controller" like the Keil STM32 documentation. A quick google on "STM32 EXTI" yeilds lots of hits, a similar search on "Luminary EXTI" does not yield much. Given that, I'm guessing that this particular controller is one of the peripheral devices that ARM leaves to 3rd parties.
This document
bolsters that view: http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00171190.pdf. There are several AFIO_EXTI registers mentioned here. These permit the mapping of GPIO lines to interrupts. Unfortunately, I can't find anything similar in the Luminary documentation.
So...what does this mean? It looks like you only have port-level granularity for your interrupt. Thus, your ISR will have to determine which pin transitioned (assuming your are looking for edges). Good luck!
In Cortex-M3, if two interrupts are the same priority (for all GPIO pins), the former will not be interrupted. The interrupt comes later will be in pending state.
When a GPIO interrupt occurs you can check the GPIO Interrupt Status for Rising/Falling IO0IntEnR/IO0IntEnF (depending on ) for the corresponding bit to find the pin that causes the interrupt.

Mapping DMA interrupts in the linux kernel

I'm writing a kernel module for a powerpc SoC which contains a DMA controller. I want to map the DMA interrupts in the linux kernel. my DMA structure has two interrupts:
struct dma
{
u32 dma1;
u32 dma2;
}*dma;
I have memory mapped the DMA structure in the Kernel. I have used the function irq_of_parse_and_map() to get the virq number to the corresponding interrupts.
dma->dma1=irq_of_parse_and_map(ofdev->node,0);
dma->dma2=irq_of_parse_and_map(ofdev->node,1);
but i cant get the virq numbers for the above interrupts. What APIs might be available to access the VIRQ numbers?
PowerPC based system uses a Device Tree Blob (DTB), also referred as Device Tree Source (DTS), which is a database that represents the hardware components (Processor Configuration, Buses, Peripherals etc...) on a given board. Linux kernel during its bootup expects certain information on the hardware that it runs on. Hardware information is passed from DTB to kernel by the bootloader software (eg: u-boot) as per Open Firmware standard. Once kernel get the hardware information, it will do all the software setup as a part of the kernel initilization routine.
From here on if any kernel software component (eg: device driver) needs hardware detail, it should get it from the kernel by using a set of Open Firmware Standard Binary Interfaces. Some of them are listed below:
of_register_platform_driver() - Register driver for device
of_unregister_platform_driver() - Unregister driver for device
of_address_to_resource() - Obtain physical address of peripheral
of_get_property() - Find property with a given name for a given node
of_find_node_by_phandle() - Find a node given a phandle
irq_of_parse_and_map() - Parse and map an interrupt into linux virq space
of_irq_to_resourse() - Obtain virtual IRQ of peripheral
...
...
Now coming to the problem raised here. irq_of_parse_and_map() is used to parse and map an interrupt into linux virq space. Usually this will be done by the Interrupt Controller device driver of the system. Once the interrupt mapping is done, you can get the Interrupt Source virq by referring to of_irq_to_resource() call. This step will be required for registering interrupt handler to the interrupt source. So try using of_irq_to_resource() instead of irq_of_parse_and_map().
Ref:
Device Tree Blob: http://www.informit.com/articles/article.aspx?p=1647051&seqNum=5
Open Firmware: http://www.openfirmware.org/
OF IRQ Interface: linux-2.6/drivers/of/irq.c

Resources