* mv-linux: Problem to implement custom driver interrupt handling
@ 2006-02-06 13:31 Eckart Göhler
2006-02-06 15:14 ` Andrei Konovalov
0 siblings, 1 reply; 4+ messages in thread
From: Eckart Göhler @ 2006-02-06 13:31 UTC (permalink / raw)
To: linuxppc-embedded
Hi,
We try to run montavista Linux pro 3.1 on an ml300 like embedded system
on an Virtex V2-Pro system. The system works fine with UART, Xilinx enet
driver (booting with Das U-Boot).
Now we try to implement some custom GPIO driver that must be triggered
from outside interrupts. Polling for data works fine but the handler for
HW-timer interrupts does behaves strange.
The relevant Linux driver part that requests the interrupt and starts
the timer look like below.
Installing such a driver works but
- No report of driver interrupt called is sent
- installing the driver results in a system that almost gets stuck and
has poor response (~sec) till the driver is rmmodded.
Checking the implementation with native Xilinx example timer application
works fine, provided the Xilinx exception handling is implemented.
Its not clear for me whether on ppc environment something specific must
be done for custom interrupts, though implementation of
xilinx_enet/xilinx_uartlite does not hint for something specific.
sincerely
eckart goehler
-----------------------------------------------------------------(snip)
// driver snippet that reacts on timer interrupts:
// timer\interrupt base addresses, modified by ioremap:
unsigned long timer_base, interrupt_base;
/* interrupt handler: */
static
void drv_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
{
printk(KERN_INFO DEVICE_NAME "interrupt occurred\n");
}
static int __init drv_init_module(void)
{
interrupt_base = (unsigned long)
ioremap(XPAR_INTC_BASEADDR,XPAR_INTC_HIGHADDR-XPAR_INTC_BASEADDR);
timer_base = (unsigned long)
ioremap(XPAR_TIMER_BASEADDR,XPAR_TIMER_HIGHADDR-XPAR_TIMER_BASEADDR);
// install interrupt handler:
if (request_irq(DRV_IRQ, commdrv_interrupt_handler,
0, DEVICE_NAME, NULL)
)
{
printk(KERN_INFO DEVICE_NAME ": can¢t get assigned irq %i\n",
COMM_IRQ
);
}
else { /* enable interrupt */
printk(KERN_INFO DEVICE_NAME ": interrupt installed\n");
/* Start the interrupt controller */
XIntc_mMasterEnable(interrupt_base);
// here: enable timer interrupt:
/* Set the number of cycles the timer counts before interrupting */
XTmrCtr_mSetLoadReg(timer_base, 0, TIMER_VALUE * 80000000l);
printk(KERN_INFO DEVICE_NAME ": clear timer\n");
/* Reset the timers, and clear interrupts */
XTmrCtr_mSetControlStatusReg(timer_base, 0, XTC_CSR_INT_OCCURED_MASK
| XTC_CSR_LOAD_MASK );
printk(KERN_INFO DEVICE_NAME ": enable interrupt\n");
/* Enable timer interrupts in the interrupt controller */
XIntc_mEnableIntr(interrupt_base, DRV_IRQ_MASK);
//printk(KERN_INFO DEVICE_NAME ": start timer\n");
/* Start the timers */
XTmrCtr_mSetControlStatusReg(timer_base, 0, XTC_CSR_ENABLE_TMR_MASK
| XTC_CSR_ENABLE_INT_MASK
| XTC_CSR_AUTO_RELOAD_MASK |
XTC_CSR_DOWN_COUNT_MASK);
}
}
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: mv-linux: Problem to implement custom driver interrupt handling
2006-02-06 13:31 mv-linux: Problem to implement custom driver interrupt handling Eckart Göhler
@ 2006-02-06 15:14 ` Andrei Konovalov
2006-02-10 15:25 ` Eckart Göhler
0 siblings, 1 reply; 4+ messages in thread
From: Andrei Konovalov @ 2006-02-06 15:14 UTC (permalink / raw)
To: Eckart Göhler; +Cc: linuxppc-embedded
Hi,
In the Linux driver you should not access the interrupt controller directly.
The relevant XIntc_* calls are done by arch/ppc/syslib/xilinx_pic.c code.
E.g. the particular interrupt is unmasked when one calls request_irq().
Few more comments below.
Thanks,
Andrei
Eckart Göhler wrote:
> Hi,
>
> We try to run montavista Linux pro 3.1 on an ml300 like embedded system
> on an Virtex V2-Pro system. The system works fine with UART, Xilinx enet
> driver (booting with Das U-Boot).
> Now we try to implement some custom GPIO driver that must be triggered
> from outside interrupts. Polling for data works fine but the handler for
> HW-timer interrupts does behaves strange.
>
> The relevant Linux driver part that requests the interrupt and starts
> the timer look like below.
>
> Installing such a driver works but
> - No report of driver interrupt called is sent
> - installing the driver results in a system that almost gets stuck and
> has poor response (~sec) till the driver is rmmodded.
>
> Checking the implementation with native Xilinx example timer application
> works fine, provided the Xilinx exception handling is implemented.
>
> Its not clear for me whether on ppc environment something specific must
> be done for custom interrupts, though implementation of
> xilinx_enet/xilinx_uartlite does not hint for something specific.
>
>
> sincerely
>
> eckart goehler
>
>
> -----------------------------------------------------------------(snip)
>
> // driver snippet that reacts on timer interrupts:
>
> // timer\interrupt base addresses, modified by ioremap:
> unsigned long timer_base, interrupt_base;
>
>
> /* interrupt handler: */
> static
> void drv_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
> {
> printk(KERN_INFO DEVICE_NAME "interrupt occurred\n");
Most probably you should clear the interrupt source here.
Otherwise you could get back into the interrupt handler as
soon as you return from it due to the interrupt request still
being active.
> }
>
>
>
> static int __init drv_init_module(void)
> {
>
> interrupt_base = (unsigned long)
> ioremap(XPAR_INTC_BASEADDR,XPAR_INTC_HIGHADDR-XPAR_INTC_BASEADDR);
> timer_base = (unsigned long)
> ioremap(XPAR_TIMER_BASEADDR,XPAR_TIMER_HIGHADDR-XPAR_TIMER_BASEADDR);
>
> // install interrupt handler:
> if (request_irq(DRV_IRQ, commdrv_interrupt_handler,
> 0, DEVICE_NAME, NULL)
> )
You call request_irq() (i.e. unmask this interrupt) too early.
Configure the timer first.
> {
> printk(KERN_INFO DEVICE_NAME ": can¢t get assigned irq %i\n",
> COMM_IRQ
> );
> }
> else { /* enable interrupt */
>
> printk(KERN_INFO DEVICE_NAME ": interrupt installed\n");
>
> /* Start the interrupt controller */
> XIntc_mMasterEnable(interrupt_base);
- must not be used in the driver
> // here: enable timer interrupt:
> /* Set the number of cycles the timer counts before interrupting */
> XTmrCtr_mSetLoadReg(timer_base, 0, TIMER_VALUE * 80000000l);
>
>
> printk(KERN_INFO DEVICE_NAME ": clear timer\n");
>
> /* Reset the timers, and clear interrupts */
> XTmrCtr_mSetControlStatusReg(timer_base, 0, XTC_CSR_INT_OCCURED_MASK
> | XTC_CSR_LOAD_MASK );
>
> printk(KERN_INFO DEVICE_NAME ": enable interrupt\n");
>
> /* Enable timer interrupts in the interrupt controller */
>
> XIntc_mEnableIntr(interrupt_base, DRV_IRQ_MASK);
- must not be used in the driver. Unmasking the interrupt is done inside request_irq().
> //printk(KERN_INFO DEVICE_NAME ": start timer\n");
> /* Start the timers */
> XTmrCtr_mSetControlStatusReg(timer_base, 0, XTC_CSR_ENABLE_TMR_MASK
> | XTC_CSR_ENABLE_INT_MASK
> | XTC_CSR_AUTO_RELOAD_MASK |
> XTC_CSR_DOWN_COUNT_MASK);
>
> }
> }
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: mv-linux: Problem to implement custom driver interrupt handling
2006-02-06 15:14 ` Andrei Konovalov
@ 2006-02-10 15:25 ` Eckart Göhler
2006-02-10 19:13 ` Andrei Konovalov
0 siblings, 1 reply; 4+ messages in thread
From: Eckart Göhler @ 2006-02-10 15:25 UTC (permalink / raw)
To: Andrei Konovalov; +Cc: linuxppc-embedded
Andrei Konovalov wrote:
> Hi,
>
> In the Linux driver you should not access the interrupt controller
> directly.
> The relevant XIntc_* calls are done by arch/ppc/syslib/xilinx_pic.c code.
> E.g. the particular interrupt is unmasked when one calls request_irq().
>
> Few more comments below.
Hi,
Thanks a lot. Actually I inserted the low-level code below after
request_irq() did not work. The note about xilinx_pic.c code (that is
located in my implementation in arch/ppc/kernel/xilinx_pic.c) lead me to
the problem origin that should be reported here for the community (which
I presume already know the very fact):
The interrupt numbering generated by the EDK is opposite to the one used
by linux, i.e. interrupt number 4 reported in EDK-generated
xparameters.h/xparameters_ml300.h becomes 31-4 = 27 when using request_irq.
Therefore the handler was not called because he was attached to the
wrong interrupt, and also was not able to reset the interrupt pending
flag, that must be done as you noted below.
cheers
eckart
>
>
> Thanks,
> Andrei
>
>
> Eckart Göhler wrote:
>> Hi,
>>
>> We try to run montavista Linux pro 3.1 on an ml300 like embedded
>> system on an Virtex V2-Pro system. The system works fine with UART,
>> Xilinx enet
>> driver (booting with Das U-Boot).
>> Now we try to implement some custom GPIO driver that must be triggered
>> from outside interrupts. Polling for data works fine but the handler
>> for HW-timer interrupts does behaves strange.
>>
>> The relevant Linux driver part that requests the interrupt and starts
>> the timer look like below.
>>
>> Installing such a driver works but
>> - No report of driver interrupt called is sent
>> - installing the driver results in a system that almost gets stuck and
>> has poor response (~sec) till the driver is rmmodded.
>>
>> Checking the implementation with native Xilinx example timer
>> application works fine, provided the Xilinx exception handling is
>> implemented.
>>
>> Its not clear for me whether on ppc environment something specific
>> must be done for custom interrupts, though implementation of
>> xilinx_enet/xilinx_uartlite does not hint for something specific.
>>
>>
>> sincerely
>>
>> eckart goehler
>>
>>
>> -----------------------------------------------------------------(snip)
>>
>> // driver snippet that reacts on timer interrupts:
>>
>> // timer\interrupt base addresses, modified by ioremap:
>> unsigned long timer_base, interrupt_base;
>>
>>
>> /* interrupt handler: */
>> static
>> void drv_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs)
>> {
>> printk(KERN_INFO DEVICE_NAME "interrupt occurred\n");
>
> Most probably you should clear the interrupt source here.
> Otherwise you could get back into the interrupt handler as
> soon as you return from it due to the interrupt request still
> being active.
>
>> }
>>
>>
>>
>> static int __init drv_init_module(void)
>> {
>>
>> interrupt_base = (unsigned long)
>> ioremap(XPAR_INTC_BASEADDR,XPAR_INTC_HIGHADDR-XPAR_INTC_BASEADDR);
>> timer_base = (unsigned long)
>> ioremap(XPAR_TIMER_BASEADDR,XPAR_TIMER_HIGHADDR-XPAR_TIMER_BASEADDR);
>>
>> // install interrupt handler:
>> if (request_irq(DRV_IRQ, commdrv_interrupt_handler,
>> 0, DEVICE_NAME, NULL)
>> )
>
> You call request_irq() (i.e. unmask this interrupt) too early.
> Configure the timer first.
>
>> {
>> printk(KERN_INFO DEVICE_NAME ": can¢t get assigned irq %i\n",
>> COMM_IRQ
>> );
>> }
>> else { /* enable interrupt */
>>
>> printk(KERN_INFO DEVICE_NAME ": interrupt installed\n");
>>
>> /* Start the interrupt controller */
>> XIntc_mMasterEnable(interrupt_base);
>
> - must not be used in the driver
>
>> // here: enable timer interrupt:
>> /* Set the number of cycles the timer counts before interrupting */
>> XTmrCtr_mSetLoadReg(timer_base, 0, TIMER_VALUE * 80000000l);
>>
>>
>> printk(KERN_INFO DEVICE_NAME ": clear timer\n");
>>
>> /* Reset the timers, and clear interrupts */
>> XTmrCtr_mSetControlStatusReg(timer_base, 0, XTC_CSR_INT_OCCURED_MASK
>> | XTC_CSR_LOAD_MASK );
>>
>> printk(KERN_INFO DEVICE_NAME ": enable interrupt\n");
>>
>> /* Enable timer interrupts in the interrupt controller */
>>
>> XIntc_mEnableIntr(interrupt_base, DRV_IRQ_MASK);
>
> - must not be used in the driver. Unmasking the interrupt is done inside
> request_irq().
>
>> //printk(KERN_INFO DEVICE_NAME ": start timer\n");
>> /* Start the timers */
>> XTmrCtr_mSetControlStatusReg(timer_base, 0, XTC_CSR_ENABLE_TMR_MASK
>> | XTC_CSR_ENABLE_INT_MASK
>> | XTC_CSR_AUTO_RELOAD_MASK |
>> XTC_CSR_DOWN_COUNT_MASK);
>>
>> }
>> }
>>
>> _______________________________________________
>> Linuxppc-embedded mailing list
>> Linuxppc-embedded@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
>
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: mv-linux: Problem to implement custom driver interrupt handling
2006-02-10 15:25 ` Eckart Göhler
@ 2006-02-10 19:13 ` Andrei Konovalov
0 siblings, 0 replies; 4+ messages in thread
From: Andrei Konovalov @ 2006-02-10 19:13 UTC (permalink / raw)
To: Eckart Göhler; +Cc: linuxppc-embedded
Eckart Göhler wrote:
>
> Andrei Konovalov wrote:
> > Hi,
> >
> > In the Linux driver you should not access the interrupt controller
> > directly.
> > The relevant XIntc_* calls are done by arch/ppc/syslib/xilinx_pic.c
> code.
> > E.g. the particular interrupt is unmasked when one calls request_irq().
> >
> > Few more comments below.
>
>
> Hi,
>
> Thanks a lot. Actually I inserted the low-level code below after
> request_irq() did not work. The note about xilinx_pic.c code (that is
> located in my implementation in arch/ppc/kernel/xilinx_pic.c) lead me to
Correct. arch/ppc/syslib/xilinx_pic.c is the 2.6 kernel case.
> the problem origin that should be reported here for the community (which
> I presume already know the very fact):
> The interrupt numbering generated by the EDK is opposite to the one used
> by linux, i.e. interrupt number 4 reported in EDK-generated
> xparameters.h/xparameters_ml300.h becomes 31-4 = 27 when using request_irq.
Yes, this is true for 2.4 kernels.
In 2.6 the "natural" irq numbering is used.
I.e. for irq number of 4 (as per xparameters.h) one should pass
to request_irq()
31-4 = 27 if using 2.4 kernel
and
4 if using 2.6 kernel.
Thanks,
Andrei
> Therefore the handler was not called because he was attached to the
> wrong interrupt, and also was not able to reset the interrupt pending
> flag, that must be done as you noted below.
>
> cheers
>
> eckart
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2006-02-10 19:22 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-06 13:31 mv-linux: Problem to implement custom driver interrupt handling Eckart Göhler
2006-02-06 15:14 ` Andrei Konovalov
2006-02-10 15:25 ` Eckart Göhler
2006-02-10 19:13 ` Andrei Konovalov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).