From 97a86de205e003a88d22e4b043706b207ec1ea04 Mon Sep 17 00:00:00 2001
From: Michal Demin <michaldemin@gmail.com>
Date: Sat, 29 Jan 2011 17:30:22 +0100
Subject: [PATCH 2/2] Add interrupt support for GPIOs

Signed-off-by: Michal Demin <michaldemin@gmail.com>
---
 src/target/firmware/board/compal_e99/init.c  |   16 +++++++
 src/target/firmware/calypso/keypad.c         |   58 ++++++++++++++++++++++----
 src/target/firmware/include/calypso/keypad.h |   13 ++++++
 3 files changed, 79 insertions(+), 8 deletions(-)
 create mode 100644 src/target/firmware/include/calypso/keypad.h

diff --git a/src/target/firmware/board/compal_e99/init.c b/src/target/firmware/board/compal_e99/init.c
index a8b8759..72cadcb 100644
--- a/src/target/firmware/board/compal_e99/init.c
+++ b/src/target/firmware/board/compal_e99/init.c
@@ -48,6 +48,7 @@
 #include <display.h>
 
 #define ASIC_CONF_REG	0xfffef008
+#define IO_CONF_REG   0xfffef00a
 
 static void board_io_init(void)
 {
@@ -61,6 +62,12 @@ static void board_io_init(void)
 	reg |= (1 << 13) | (1 << 14);
 	writew(reg, ASIC_CONF_REG);
 
+	/* enable IO(4) */
+	/* TODO: move to gpio_config */
+	reg = readw(IO_CONF_REG);
+	reg |= 1;
+	writew(reg, IO_CONF_REG);
+
 	/* LCD Set I/O(3) to output mode and enable C155 backlight (IO1) */
 	/* FIXME: Put the display backlight control to backlight.c */
 	gpio_config(GPIO_PIN(3) | GPIO_PIN(1), GPIO_MODE_OUTPUT);
@@ -70,6 +77,11 @@ static void board_io_init(void)
 	gpio_write(GPIO_PIN(3), GPIO_RESET);
 }
 
+static void gpio_test(void)
+{
+	printf("interrupt from music chip\n");
+}
+
 void board_init(void)
 {
 	/* Disable watchdog (compal loader leaves it enabled) */
@@ -130,6 +142,10 @@ void board_init(void)
 	/* Initialize keypad driver */
 	keypad_init(1);
 
+	/* Enable interrupt on IO(4) - Midi chip */
+	/* TODO: replace function - once driver is ready */
+	gpio_set_handler(gpio_test, 4, GPIO_INT_FALLING);
+
 	/* Initialize ABB driver (uses SPI) */
 	twl3025_init();
 }
diff --git a/src/target/firmware/calypso/keypad.c b/src/target/firmware/calypso/keypad.c
index fd4e0ff..9b71473 100644
--- a/src/target/firmware/calypso/keypad.c
+++ b/src/target/firmware/calypso/keypad.c
@@ -30,6 +30,8 @@
 #include <keypad.h>
 
 #include <calypso/irq.h>
+#include <calypso/keypad.h>
+#include <calypso/gpio.h>
 #include <abb/twl3025.h>
 
 
@@ -109,26 +111,66 @@ void dispatch_buttons(uint32_t buttons)
 static uint8_t	polling = 0;
 static uint8_t  with_interrupts = 0;
 
+void keypad_mask_irq(uint8_t irq)
+{
+	uint16_t mask;
+
+	mask = readw(KBD_GPIO_MASKIT);
+	mask |= irq;
+	writew(mask, KBD_GPIO_MASKIT); 
+}
+
+void keypad_unmask_irq(uint8_t irq)
+{
+	uint16_t mask;
+
+	mask = readw(KBD_GPIO_MASKIT);
+	mask &= ~irq;
+	writew(mask, KBD_GPIO_MASKIT); 
+}
+
 static void keypad_irq(__unused enum irq_nr nr)
 {
-	/* enable polling */
-	polling = 1;
-	irq_disable(IRQ_KEYPAD_GPIO);
+	uint16_t ints;
+	uint16_t mask;
+	uint16_t tmp;
+
+	/* FIXME: do we have to check against mask? */
+	ints = readw(KBD_GPIO_INT);
+	mask = readw(KBD_GPIO_MASKIT);
+
+	/* NOTE: interrupts are active low in datasheet - incorrect ! */
+	tmp = ints & ~mask;
+	printd("i %d m %d t %d\n", ints & 3, mask & 3, tmp & 3);
+
+	if (tmp & GPIO_INT) {
+		gpio_isr();
+	}
+
+	if (tmp & KBD_INT) {
+		/* enable polling */
+		polling = 1;
+		keypad_mask_irq(KBD_INT);
+	}
 }
 
 void keypad_init(uint8_t interrupts)
 {
 	lastbuttons = 0;
 	polling = 0;
-	writew(0, KBD_GPIO_MASKIT);
+
+	/* mask GPIO and Keypad interrupts by default */
+	writew(KBD_INT | GPIO_INT, KBD_GPIO_MASKIT);
 	writew(0, KBC_REG);
 
 	if(interrupts) {
 		with_interrupts = 1;
-		irq_register_handler(IRQ_KEYPAD_GPIO, &keypad_irq);
-		irq_config(IRQ_KEYPAD_GPIO, 0, 0, 0);
-		irq_enable(IRQ_KEYPAD_GPIO);
+		keypad_unmask_irq(KBD_INT);
 	}
+
+	irq_register_handler(IRQ_KEYPAD_GPIO, &keypad_irq);
+	irq_config(IRQ_KEYPAD_GPIO, 0, 0, 0);
+	irq_enable(IRQ_KEYPAD_GPIO);
 }
 
 void keypad_set_handler(key_handler_t handler)
@@ -156,7 +198,7 @@ void keypad_poll()
 	/* enable keypad irq after the signal settles */
 	if (polling == 3) {
 		if(with_interrupts) {
-			irq_enable(IRQ_KEYPAD_GPIO);
+			keypad_unmask_irq(KBD_INT);
 			polling = 0;
 		} else {
 			polling = 1;
diff --git a/src/target/firmware/include/calypso/keypad.h b/src/target/firmware/include/calypso/keypad.h
new file mode 100644
index 0000000..c0f07b0
--- /dev/null
+++ b/src/target/firmware/include/calypso/keypad.h
@@ -0,0 +1,13 @@
+#ifndef _CALYPSO_KEYPAD_H
+#define _CALYPSO_KEYPAD_H
+
+enum keypad_gpio_interrupts {
+	KBD_INT = 1,
+	GPIO_INT = 2
+};
+
+void keypad_mask_irq(uint8_t irq);
+void keypad_unmask_irq(uint8_t irq);
+
+#endif
+
-- 
1.7.3.1

