* PPC405GP: Spurious interrupt during handing level triggered interrupts
@ 2004-03-09 22:58 listmember
2004-03-10 16:30 ` Kenneth Johansson
0 siblings, 1 reply; 4+ messages in thread
From: listmember @ 2004-03-09 22:58 UTC (permalink / raw)
To: linuxppc-embedded
Cogent CSB272 (PPC405GP)
U-Boot 1.0.2 (CVS)
Linux 2.4.25-pre4 snapshot from linuxppc-2.4 BK tree (via rsync)
There are a couple of minor patches for getting Linux working with U-Boot.
I am working with an I2C device which notifies certain events via
interrupt. It holds the irq line low until its status register is read and
and interrupt is cleared at the device. There can be multiple I2C devices
of this type on the same IRQ (wire-ored).
Because, I2C is too slow, we do not clear he interrupt (at the device) at
kernel space. I've written a simple device driver so user process can be
notified of events using select() and handle the event in the user daemon.
The interrupt handler basically:
- disables the interrupts on the particular line via disable_irq()
- wakes up the process sleeping on select()
- returns from the handler routine.
User process then wakes up, communicates with i2c devices to find out
which one has a pending event and clears the event and re-enables the
interrupt on the particular line by making an ioctl call.
Now I am getting an extra spurious interrupt after I re-enable interrupts
after the interrupting device de-asserted the interrupt request.
My understanding is the following is happening:
- Interrupt is asserted
- Linux executes prolog code and acks interrupt
- Since the interrupt is level triggered, this ack is no-op
- ISR entered and disables the interrupt
- Interrupt is de-assered by "user" code
- Interrupt is re-enabled via ioctl
- However PPC405 had already latched IRQ so PPC405 UIC0_SR bit is still set.
- Because of UIC0_SR bit still set, another ISR braching is taken
- Linux ACK the interrupt (UICO_SR bit is now clear)
- ISR entered and disables the interrupt
- "user" code cannot locate any interrupting device.
- Interrupt is de-assered by ioctl and interrupts is re-enabled.
I think my problem is similar to what is described here:
http://lists.linuxppc.org/linuxppc-embedded/200306/msg00123.html
Now, to prevent the second spurious branching, I used ack_irq() call
(actuall macro) to manually ack the interrupt (before enabling interrupts
again in ioctl). It works this way.
Is this OK to use or is there a preferred way to do this?
Best regards,
Tolunay
Note: I know this will probably would not be an issue if I changed to edge
triggering but I am concerned about lost interrupts when using edge
triggers especially when I have multiple I2C devices on the same irq line.
** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: PPC405GP: Spurious interrupt during handing level triggered interrupts
2004-03-09 22:58 PPC405GP: Spurious interrupt during handing level triggered interrupts listmember
@ 2004-03-10 16:30 ` Kenneth Johansson
2004-03-11 0:14 ` listmember
0 siblings, 1 reply; 4+ messages in thread
From: Kenneth Johansson @ 2004-03-10 16:30 UTC (permalink / raw)
To: listmember@orkun.us; +Cc: linuxppc-embedded@lists.linuxppc.org
On Tue, 2004-03-09 at 23:58, listmember@orkun.us wrote:
> Now, to prevent the second spurious branching, I used ack_irq() call
> (actuall macro) to manually ack the interrupt (before enabling interrupts
> again in ioctl). It works this way.
>
> Is this OK to use or is there a preferred way to do this?
That's mainly what I do also.
I had this comment in the cvs log.
--
The status register was not reset by enable_irq so it
remembered the last one resulting in every interrupt
getting reported twice.
--
and the code that I used was
/* We have to do this manually as enable do not do this for us */
void mask_SR(int dev_irq){
int bit;
bit = (dev_irq-17) +25;
mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - bit)));
}
--
basically parts of what irq_ack would do (dev_irq is a privat number
local to this driver)
Perhaps the enable code should reset this bit also?? everyone that dose
this type of userspace driver is going to hit this problem.
** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: PPC405GP: Spurious interrupt during handing level triggered interrupts
2004-03-10 16:30 ` Kenneth Johansson
@ 2004-03-11 0:14 ` listmember
2004-03-11 17:13 ` Kenneth Johansson
0 siblings, 1 reply; 4+ messages in thread
From: listmember @ 2004-03-11 0:14 UTC (permalink / raw)
To: Kenneth Johansson; +Cc: linuxppc-embedded
Kenneth,
Thanks for replying. I was happy to find your earlier thread during my
list archive search. I though about using something like your sequence
below but finally settled in ack_irq().
> /* We have to do this manually as enable do not do this for us */
> void mask_SR(int dev_irq){
>
> int bit;
> bit = (dev_irq-17) +25;
>
> mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - bit)));
> }
> --
> basically parts of what irq_ack would do (dev_irq is a privat number
> local to this driver)
>
> Perhaps the enable code should reset this bit also?? everyone that dose
> this type of userspace driver is going to hit this problem.
I think for edge triggered interrupts this would not be desirable if a
driver has sections that it cannot handle interrupts safely and disables
interrupts during such processing. If an interrupt arrived when interrupts
were disabled and enable actually reset the bit the interrupt would be
lost.
However, I think, code could be enhanced to reset the SR bit, "only" for
level triggered interrupts and leave edge triggered interrupts alone. This
would require looking at UIC0_TR register as well.
Best regards,
Tolunay
** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: PPC405GP: Spurious interrupt during handing level triggered interrupts
2004-03-11 0:14 ` listmember
@ 2004-03-11 17:13 ` Kenneth Johansson
0 siblings, 0 replies; 4+ messages in thread
From: Kenneth Johansson @ 2004-03-11 17:13 UTC (permalink / raw)
To: listmember@orkun.us; +Cc: linuxppc-embedded@lists.linuxppc.org
On Thu, 2004-03-11 at 01:14, listmember@orkun.us wrote:
> Kenneth,
>
> However, I think, code could be enhanced to reset the SR bit, "only" for
> level triggered interrupts and leave edge triggered interrupts alone. This
> would require looking at UIC0_TR register as well.
Yes If you could do a patch for this for level triggered only it would
be good. I can't see this affecting anything negative so it should be no
problem getting it integrated.
** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2004-03-11 17:13 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-09 22:58 PPC405GP: Spurious interrupt during handing level triggered interrupts listmember
2004-03-10 16:30 ` Kenneth Johansson
2004-03-11 0:14 ` listmember
2004-03-11 17:13 ` Kenneth Johansson
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).