External IRQ with mpc8xxx in linux

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

External IRQ with mpc8xxx in linux

Jump to solution
2,888 Views
rans
Senior Contributor I

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

0 Kudos
1 Solution
1,626 Views
bpe
NXP Employee
NXP Employee

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!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

7 Replies
1,627 Views
bpe
NXP Employee
NXP Employee

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!
-----------------------------------------------------------------------------------------------------------------------

1,626 Views
rans
Senior Contributor I

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

0 Kudos
1,626 Views
scottwood
NXP Employee
NXP Employee

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?

0 Kudos
1,626 Views
rans
Senior Contributor I

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

0 Kudos
1,626 Views
scottwood
NXP Employee
NXP Employee

Again, you are using invalid interrupt numbers in the device tree.  Look at table 8-6 in the SoC reference manual.

0 Kudos
1,626 Views
rans
Senior Contributor I

Platon, Scott,

Thank you very much!!

Finally the interrupt handler is called. Table 8-6 information was essential.

Regards,

Ran

0 Kudos
1,626 Views
rans
Senior Contributor I

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

0 Kudos