#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
+#include <linux/spinlock.h>
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
#include <asm/arch/hardware.h>
int irq;
unsigned int rows;
unsigned int cols;
+ int suspended;
+ spinlock_t suspend_lock;
};
DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
struct pt_regs *regs)
{
struct omap_kp *omap_kp = dev_id;
+ unsigned long flags;
+
+ spin_lock_irqsave(&omap_kp->suspend_lock, flags);
+ if (omap_kp->suspended) {
+ spin_unlock_irqrestore(&omap_kp->suspend_lock, flags);
+ return IRQ_HANDLED;
+ }
+ spin_unlock_irqrestore(&omap_kp->suspend_lock, flags);
/* disable keyboard interrupt and schedule for handling */
if (cpu_is_omap24xx()) {
#ifdef CONFIG_PM
static int omap_kp_suspend(struct platform_device *dev, pm_message_t state)
{
- /* Nothing yet */
+ struct omap_kp *omap_kp = platform_get_drvdata(dev);
+ unsigned long flags;
+ spin_lock_irqsave(&omap_kp->suspend_lock, flags);
+
+ /*
+ * Re-enable the interrupt in case it has been masked by the
+ * handler and a key is still pressed. We need the interrupt
+ * to wake us up from suspended.
+ */
+ if (cpu_class_is_omap1())
+ omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+ omap_kp->suspended = 1;
+
+ spin_unlock_irqrestore(&omap_kp->suspend_lock, flags);
return 0;
}
static int omap_kp_resume(struct platform_device *dev)
{
- /* Nothing yet */
+ struct omap_kp *omap_kp = platform_get_drvdata(dev);
+ omap_kp->suspended = 0;
return 0;
}
#else
}
}
+ spin_lock_init(&omap_kp->suspend_lock);
+ omap_kp->suspended = 0;
+
init_timer(&omap_kp->timer);
omap_kp->timer.function = omap_kp_timer;
omap_kp->timer.data = (unsigned long) omap_kp;