summaryrefslogtreecommitdiffstats
path: root/src/target/firmware/calypso/keypad.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/firmware/calypso/keypad.c')
-rw-r--r--src/target/firmware/calypso/keypad.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/target/firmware/calypso/keypad.c b/src/target/firmware/calypso/keypad.c
new file mode 100644
index 00000000..27f48c0b
--- /dev/null
+++ b/src/target/firmware/calypso/keypad.c
@@ -0,0 +1,165 @@
+/* Driver for the keypad attached to the TI Calypso */
+
+/* (C) 2010 by roh <roh@hyte.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <debug.h>
+#include <delay.h>
+#include <memory.h>
+#include <keypad.h>
+
+#include <calypso/irq.h>
+#include <abb/twl3025.h>
+
+
+#define KBR_LATCH_REG 0xfffe480a
+#define KBC_REG 0xfffe480c
+#define KBD_GPIO_INT 0xfffe4816
+#define KBD_GPIO_MASKIT 0xfffe4818
+
+static key_handler_t key_handler = NULL;
+
+void emit_key(uint8_t key, uint8_t state)
+{
+ printf("key=%u %s\n", key, state == PRESSED ? "pressed" : "released");
+
+ if (state == RELEASED)
+ if (key == KEY_POWER)
+ twl3025_power_off();
+
+ if(key_handler) {
+ key_handler(key, state);
+ }
+}
+
+volatile uint32_t lastbuttons;
+
+#define BTN_TO_KEY(name) \
+ ((diff & BTN_##name) == BTN_##name) \
+ { \
+ key = KEY_##name; \
+ diff = diff & ~BTN_##name; \
+ }
+
+void dispatch_buttons(uint32_t buttons)
+{
+ uint8_t state;
+
+ if (buttons == lastbuttons)
+ return;
+
+ if (buttons > lastbuttons)
+ state = PRESSED;
+ else
+ state = RELEASED;
+
+ uint32_t diff = buttons ^ lastbuttons;
+ uint8_t key=KEY_INV;
+
+ while (diff != 0)
+ {
+ if BTN_TO_KEY(POWER)
+ else if BTN_TO_KEY(0)
+ else if BTN_TO_KEY(1)
+ else if BTN_TO_KEY(2)
+ else if BTN_TO_KEY(3)
+ else if BTN_TO_KEY(4)
+ else if BTN_TO_KEY(5)
+ else if BTN_TO_KEY(6)
+ else if BTN_TO_KEY(7)
+ else if BTN_TO_KEY(8)
+ else if BTN_TO_KEY(9)
+ else if BTN_TO_KEY(STAR)
+ else if BTN_TO_KEY(HASH)
+ else if BTN_TO_KEY(MENU)
+ else if BTN_TO_KEY(LEFT_SB)
+ else if BTN_TO_KEY(RIGHT_SB)
+ else if BTN_TO_KEY(UP)
+ else if BTN_TO_KEY(DOWN)
+ else if BTN_TO_KEY(LEFT)
+ else if BTN_TO_KEY(RIGHT)
+ else if BTN_TO_KEY(OK)
+ else
+ {
+ printf("\nunknown keycode: 0x%08x\n", diff);
+ break;
+ }
+ if ( key == KEY_POWER )
+ diff = 0;
+ emit_key(key, state);
+ }
+ lastbuttons = buttons;
+}
+
+static void keypad_irq(enum irq_nr nr)
+{
+ keypad_scan();
+}
+
+void keypad_init()
+{
+ lastbuttons = 0;
+ writew(0, KBD_GPIO_MASKIT);
+ writew(0, KBC_REG);
+
+ 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)
+{
+ key_handler = handler;
+}
+
+void keypad_scan()
+{
+ uint16_t reg;
+ uint16_t col;
+ uint32_t buttons;
+
+// putchar('\n');
+ buttons = 0x0;
+ //scan for BTN_POWER
+ writew(0xff, KBC_REG);
+ delay_ms(1);
+ reg = readw(KBR_LATCH_REG);
+// printd("%02x ", (~reg & 0x1f));
+ buttons = buttons | ((~reg & 0x1f) << 20 );
+
+ //scan for muxed keys if not powerbtn
+ if ((~reg & 0x1f) != 0x10)
+ for (col=0;col<4;col++)
+ {
+ writew(0x1f & ~(0x1 << col ), KBC_REG);
+ delay_ms(1);
+ reg = readw(KBR_LATCH_REG);
+ buttons = buttons | ((~reg & 0x1f) << (col * 5 ));
+// printd("%02x ", (~reg & 0x1f));
+ }
+ //enable keypad irq via master 'or' gate (needs col lines low in idle to work)
+ writew(0, KBC_REG);
+ dispatch_buttons(buttons);
+
+}
+