[PATCH v4] input: MXC: add mxc-keypad driver to support the Keypad Port present in the mxc application processors family.
Alberto Panizzo
maramaopercheseimorto at gmail.com
Wed Jan 27 14:43:39 EST 2010
Hi Dmitry,
On mer, 2010-01-27 at 10:33 -0800, Dmitry Torokhov wrote:
> Hi Alberto,
>
> On Wed, Jan 27, 2010 at 06:50:44PM +0100, Alberto Panizzo wrote:
> > The MXC family of Application Processors is shipped with a Keypad Port
> > supported now by this driver.
> >
> > The peripheral can control up to an 8x8 matrix key pad where all the scanning
> > procedure is done via software.
> >
> > The hardware provide two interrupts: one for a key pressed (KDI) and one for
> > all key releases (KRI). There is also a simple circuit for glitch reduction
> > (said for synchronization) made by two series of 3 D-latches clocked by the
> > keypad-clock that stabilize the interrupts sources.
> > KDI and KRI are fired only if the respective conditions are maintained for at
> > last 4 keypad-clock cycle.
> >
> > Those simple synchronization circuits are used also for multiple key pressures:
> > between a KDI and a KRI the driver reset the sync circuit and re-enable the KDI
> > interrupt so after 3 keypad-clock cycle another KDI is fired making possible to
> > repeat the matrix scan operation.
> >
> > This algorithm is done through the interrupt management code and delayed by a
> > proper (and longer) debounce interval controlled by the platform initialization.
> > If a key is pressed for a lot of time, the driver relaxes the interrupt re-enabling
> > procedure to not over load the cpu in a long time keypad interaction.
> >
>
> I was looking at the debounce logic and I am not quite sure about it.
> Normally you have 2 ways for dealing with jitter:
>
> 1. You let interrupts to come in and reschedule the scan until they stop
> arriving. Then to tak ethe stable reading.
>
> 2. You inhibit interrupt, take a reading and schedule another reading in
> the future. If they match you decide that reading is stable otherwise
> you schedule another reading.
>
> In your case you seem to be simply postponing the reading but this does
> not guarantee that the reading is stable.
Yes, because of the glitch suppression circuit, I suppose that when
an interrupt arrive, it is a key pressure for sure.
Then I assume that the matrix will be stable after a proper debounce
time (test look fine with 20 ms).
1 should be a more accurate way, I can study an implementation.
>
> I also do not think that yopu need 2 timers - you can easily requeue
> currently running timer.
The first version I made was with one timer: if for too many repeating
interrupts the matrix state do not change, the scanning procedure was
scheduled with a summed delay.
It resulted in a degradation of responsiveness and more key pressure
losing. It is a better choice to let the scanning procedure near the
interrupt.
Changing the timer handler over the time? Would be acceptable?
>
> BTW, you need to pay close attention to the races between re-enabling
> intterrupts (form the timer context) and inhibiting interrupts when you
> close the device. Currently there is a race - if you close the device
> while scan is scheduled the timer will re-enable them again. You disable
> all rows so I am not sure if it is possible for interrupts to be raised
> again at this point, but if it is, then you porbbaly need a spinlock
> there.
This is a true race condition that I've not caught!
>
> > +
> > +static void mxc_keypad_relax_timer_handler(unsigned long data)
> > +{
> > + struct mxc_keypad *keypad = (struct mxc_keypad *) data;
> > + unsigned short reg_val;
> > +
> > + /* 10. Clear KPKD and KPKR status bits
> > + * Set the KPKR sync chain and clear the KPKD sync chain */
> > + reg_val = readw(keypad->mmio_base + KPSR);
> > + reg_val |= KBD_STAT_KPKD | KBD_STAT_KPKR |
> > + KBD_STAT_KDSC | KBD_STAT_KRSS;
> > + writew(reg_val, keypad->mmio_base + KPSR);
> > +
> > + /* Re enable interrupts and clear sync reset bits.
> > + * Next KDI is used for detect multiple pressures. */
> > + reg_val = readw(keypad->mmio_base + KPSR);
> > + reg_val &= ~(KBD_STAT_KDSC | KBD_STAT_KRSS);
> > + writew(reg_val, keypad->mmio_base + KPSR);
> > +
> > + reg_val |= KBD_STAT_KDIE | KBD_STAT_KRIE;
> > + if (keypad->irq_type == MXC_IRQ_KRI)
> > + reg_val &= ~KBD_STAT_KRIE;
>
> So we are keeping the press interrupt always... As far as I understand
> this will cause us to effectively poll the matrix as long as at least
> one key is pressed. Why do we even need to bother with release interrupt
> then?
>
> Thanks.
I always keep the press interrupt because of matrix-rescan in a long
time pressure of a key, to find multiple key pressures.
Resetting the press interrupt synchronization chain will reset also
the interrupt status bit, and if the press condition hold for the next
3*keypad_clock_periods, it is fired another press interrupt.
I can think at an architecture that after a key pressure event
continually reschedule a matrix scan in the future to look for changes
in the matrix until all keys are released.. but need a consistent
analysis of timings.
More information about the linux-arm-kernel
mailing list