Hello,
I have some difficulties and using interrupt handler with powerpc, mpc8349, on linux.
In datasheet is shows that there are 8 external interrupts, named irq0-7. We need to use IRQ4.
I don't see the interrupt listed in /proc/interrupts
# cat /proc/interrupts
CPU0
16: 93 IPIC 9 Level serial
18: 0 IPIC 14 Level i2c-mpc
19: 0 IPIC 15 Level i2c-mpc
21: 0 IPIC 18 Level phy_interrupt
32: 0 IPIC 32 Level eth0_g0_tx
33: 14 IPIC 33 Level eth0_g0_rx
34: 0 IPIC 34 Level eth0_g0_er
35: 0 IPIC 35 Level eth1_g0_tx
36: 0 IPIC 36 Level eth1_g0_rx
37: 0 IPIC 37 Level eth1_g0_er
LOC: 60756 Local timer interrupts for timer event device
LOC: 1 Local timer interrupts for others
SPU: 0 Spurious interrupts
PMI: 0 Performance monitoring interrupts
MCE: 0 Machine check exceptions
I have tried to add it in dts (Is that required?), but I still don't see any change in /proc/interrupts:
intc@0{
compatible = "intc";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <4 0x8>; <- is this the way to define IRQ4 ?
};
I've then added the following in the driver, but I also fails:
np = of_find_node_by_name(NULL,"hello"); | |
if (np == NULL) | |
{ | |
printk("Error node not found\n"); | |
} | |
printk("Node np = 0x%0x\n",np); <-- Node np = 0xdfffe2f0 | |
virq = irq_of_parse_and_map(np,0); | |
// | |
printk(" VIRQ: %d \n" , virq); <-- virq = 0 !!?? | |
if (0 > (error=request_irq(virq, &hello_IRQHandler, IRQF_SHARED, "hello", &value))) { | |
printk(KERN_WARNING"hello_IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error); | |
return -1; <-- request_irq return -22 .... | |
} |
Thank you for any idea,
Ran
Solved! Go to Solution.
There are several problems:
1. The node name of_find_node_by_name() searches for ("hello"), does not match the name of the node defined above ("intc"), so
the function finds some another node.
2. There is no 'interrupt-parent' property in the 'intc@0' node, so it is not clear to what interrupt controller it connects.
3. The interrupt number in the 'interrupts' property is invalid. Refer to MPC8349EARM, Table 8-6 for interrupt numbers coding.
Have a great day,
Platon
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
There are several problems:
1. The node name of_find_node_by_name() searches for ("hello"), does not match the name of the node defined above ("intc"), so
the function finds some another node.
2. There is no 'interrupt-parent' property in the 'intc@0' node, so it is not clear to what interrupt controller it connects.
3. The interrupt number in the 'interrupts' property is invalid. Refer to MPC8349EARM, Table 8-6 for interrupt numbers coding.
Have a great day,
Platon
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Platon,
You are correct, I've made the relevant changes.
And the request_irq return success now.
But I only did not understand your comment about the invalid number:
We are using external IRQ #4.
What is the problem with the following:
intc4@0{ | ||
compatible = "intc4"; | ||
#address-cells = <1>; | ||
#size-cells = <0>; | ||
reg = <0 0x1000>; | ||
interrupts = <4 0x8> ; | ||
interrupt-parent = <&ipic>; | ||
}; |
Regards,
Ran
Look at table 8-6 as was suggested. External IRQ4 is IPIC interrupt 20. Also check that you have the right level/sense -- is this interrupt level triggered and active low?
Hello,
I still have some issue with the IRQ.
Though it seemed that the registration is successful, I still don't get any of the external interrupt handler called.
After forcing interrupt and checking SEMSR register I see that I have a pending IRQ #2, but the handler was not called.
This are the steps:
1. in DTS (using all external IRQ #0-7):
intc0@0{
compatible = "intc0";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <0 0x8> ;
interrupt-parent = <&ipic>;
};
intc1@0{
compatible = "intc1";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <1 0x8> ;
interrupt-parent = <&ipic>;
};
intc2@0{
compatible = "intc2";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <2 0x8> ;
interrupt-parent = <&ipic>;
};
intc3@0{
compatible = "intc3";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <3 0x8> ;
interrupt-parent = <&ipic>;
};
intc4@0{
compatible = "intc4";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <4 0x8> ;
interrupt-parent = <&ipic>;
};
intc5@0{
compatible = "intc5";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <5 0x8> ;
interrupt-parent = <&ipic>;
};
intc6@0{
compatible = "intc6";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <6 0x8> ;
interrupt-parent = <&ipic>;
};
intc7@0{
compatible = "intc7";
#address-cells = <1>;
#size-cells = <0>;
reg = <0 0x1000>;
interrupts = <7 0x8> ;
interrupt-parent = <&ipic>;
};
2. registration in kernel for all interrupts:
np = of_find_node_by_name(NULL,"intc0");
if (np == NULL)
{
printk("Error node not found\n");
}
printk("Node np = 0x%0x\n",np);
virq = irq_of_parse_and_map(np,0);
printk(KERN_INFO"IRQHandler: ISR Setup VIRQ: %d \n" , virq);
if (0 > (error=request_irq(virq, &IRQHandler, 0, "intc0", &value))) {
printk(KERN_WARNING"IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error);
return -1;
}
np = of_find_node_by_name(NULL,"intc1");
if (np == NULL)
{
printk("Error node not found\n");
}
printk("Node np = 0x%0x\n",np);
virq = irq_of_parse_and_map(np,0);
printk(KERN_INFO"IRQHandler: ISR Setup VIRQ: %d \n" , virq);
if (0 > (error=request_irq(virq, &IRQHandler, 0, "intc1", &value))) {
printk(KERN_WARNING"IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error);
return -1;
}
np = of_find_node_by_name(NULL,"intc2");
if (np == NULL)
{
printk("Error node not found\n");
}
printk("Node np = 0x%0x\n",np);
virq = irq_of_parse_and_map(np,0);
printk(KERN_INFO"IRQHandler: ISR Setup VIRQ: %d \n" , virq);
if (0 > (error=request_irq(virq, &IRQHandler, 0, "intc2", &value))) {
printk(KERN_WARNING"IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error);
return -1;
}
np = of_find_node_by_name(NULL,"intc3");
if (np == NULL)
{
printk("Error node not found\n");
}
printk("Node np = 0x%0x\n",np);
virq = irq_of_parse_and_map(np,0);
printk(KERN_INFO"IRQHandler: ISR Setup VIRQ: %d \n" , virq);
if (0 > (error=request_irq(virq, &IRQHandler, 0, "intc3", &value))) {
printk(KERN_WARNING"IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error);
return -1;
}
np = of_find_node_by_name(NULL,"intc4");
if (np == NULL)
{
printk("Error node not found\n");
}
printk("Node np = 0x%0x\n",np);
virq = irq_of_parse_and_map(np,0);
printk(KERN_INFO"IRQHandler: ISR Setup VIRQ: %d \n" , virq);
if (0 > (error=request_irq(virq, &IRQHandler, 0, "intc4", &value))) {
printk(KERN_WARNING"IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error);
return -1;
}
np = of_find_node_by_name(NULL,"intc5");
if (np == NULL)
{
printk("Error node not found\n");
}
printk("Node np = 0x%0x\n",np);
virq = irq_of_parse_and_map(np,0);
printk(KERN_INFO"IRQHandler: ISR Setup VIRQ: %d \n" , virq);
if (0 > (error=request_irq(virq, &IRQHandler, 0, "intc5", &value))) {
printk(KERN_WARNING"IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error);
return -1;
}
np = of_find_node_by_name(NULL,"intc6");
if (np == NULL)
{
printk("Error node not found\n");
}
printk("Node np = 0x%0x\n",np);
virq = irq_of_parse_and_map(np,0);
printk(KERN_INFO"IRQHandler: ISR Setup VIRQ: %d \n" , virq);
if (0 > (error=request_irq(virq, &IRQHandler, 0, "intc6", &value))) {
printk(KERN_WARNING"IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error);
return -1;
}
np = of_find_node_by_name(NULL,"intc7");
if (np == NULL)
{
printk("Error node not found\n");
}
printk("Node np = 0x%0x\n",np);
virq = irq_of_parse_and_map(np,0);
printk(KERN_INFO"IRQHandler: ISR Setup VIRQ: %d \n" , virq);
if (0 > (error=request_irq(virq, &IRQHandler, 0, "intc7", &value))) {
printk(KERN_WARNING"IRQHandler: Init: Unable to allocate IRQ error = %d\n\n", error);
return -1;
}
3. interrupt handler code:
int newval = 0;
static irqreturn_t hello_IRQHandler(int irq, void *dev_id)
{
unsigned int status;
struct timespec curr_tm;
printk("key_irq!!!!!\n");
return IRQ_HANDLED;
}
4. in boot I get print which show success with request_irq():
intc_init
Node np = 0xdfffe078
IRQHandler: ISR Setup VIRQ: 20
Node np = 0xdfffe180
IRQHandler: ISR Setup VIRQ: 21
Node np = 0xdfffe288
IRQHandler: ISR Setup VIRQ: 22
Node np = 0xdfffe390
IRQHandler: ISR Setup VIRQ: 23
Node np = 0xdfffe498
IRQHandler: ISR Setup VIRQ: 24
Node np = 0xdfffe5a0
IRQHandler: ISR Setup VIRQ: 25
Node np = 0xdfffe6a8
IRQHandler: ISR Setup VIRQ: 26
Node np = 0xdfffe7b0
IRQHandler: ISR Setup VIRQ: 27
TCP: cubic registered
NET: Registered protocol family 17
5. forcing interrupt in IRQ #2, or #4 result in SEPNR change, but there is no printing from interrupt handler
6. validation in SEPNR register that interrupt was received:
# devmem2 0xe000072c
/dev/mem opened.
Memory mapped at address 0xb7b80000.
Value at address 0xE000072C (0xb7b8072c): 0x20000000
Thank you for any suggestion,
Ran
Again, you are using invalid interrupt numbers in the device tree. Look at table 8-6 in the SoC reference manual.
Platon, Scott,
Thank you very much!!
Finally the interrupt handler is called. Table 8-6 information was essential.
Regards,
Ran
Hi,
So it make sense now.
I got the following printings in code
...
intc_init
Node np = 0xdfffe078
IRQHandler: ISR Setup VIRQ: 20
....
Which says that virq is 20, which fits the external irq number 4.
Thanks for the assistance,
Ran