[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 19/20] arm: add Faraday FTKBC010 support for A369
From: |
Kuo-Jung Su |
Subject: |
[Qemu-devel] [PATCH v2 19/20] arm: add Faraday FTKBC010 support for A369 |
Date: |
Fri, 25 Jan 2013 16:19:55 +0800 |
From: Kuo-Jung Su <address@hidden>
Faraday keyboard/mouse controller (FTKBC010) is compliant with the
IBM PS/2 interface. The interface uses the bidirectional clock and
data lines to perform the half-duplex synchronous serial interface.
It also provides the configurable scan matrix for the embedded or
external keypad. FTKBC010 performs a serial-to-parallel conversion
to receive the data from the keyboard/mouse interface, and a
parallel-to-serial conversion for transmitting the data to the
keyboard/mouse interface.
Signed-off-by: Kuo-Jung Su <address@hidden>
---
hw/ftkbc010.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 226 insertions(+)
create mode 100644 hw/ftkbc010.c
diff --git a/hw/ftkbc010.c b/hw/ftkbc010.c
new file mode 100644
index 0000000..c142bd0
--- /dev/null
+++ b/hw/ftkbc010.c
@@ -0,0 +1,226 @@
+/*
+ * Faraday FTKBC010 emulator for A369.
+ *
+ * Copyright (c) 2012 Faraday Technology
+ * Written by Dante Su <address@hidden>
+ *
+ * This code is licensed under the GPL v2.
+ */
+
+#include "hw.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysbus.h"
+#include "ui/console.h"
+#include "devices.h"
+
+/* Key codes */
+#define KEYCODE_ESC 1
+#define KEYCODE_BACKSPACE 14
+#define KEYCODE_ENTER 28
+#define KEYCODE_SPACE 57
+#define KEYCODE_MENU 139 /* Menu (show menu) */
+
+#define TYPE_FTKBC010 "ftkbc010"
+
+typedef struct Ftkbc010State {
+ SysBusDevice busdev;
+ MemoryRegion iomem;
+ qemu_irq irq;
+
+ int x;
+ int y;
+
+ /* HW registers */
+ uint32_t cr;
+ uint32_t isr;
+} ftkbc010_state;
+
+#define FTKBC010(obj) \
+ OBJECT_CHECK(ftkbc010_state, obj, TYPE_FTKBC010)
+
+static void ftkbc010_update(ftkbc010_state *s)
+{
+ uint32_t ier = 0;
+
+ /* keypad interrupt */
+ ier |= (s->cr & (1 << 8)) ? (1 << 2) : 0;
+ /* tx interrupt */
+ ier |= (s->cr & (1 << 3)) ? (1 << 1) : 0;
+ /* rx interrupt */
+ ier |= (s->cr & (1 << 4)) ? (1 << 0) : 0;
+
+ if (ier & s->isr) {
+ qemu_irq_raise(s->irq);
+ } else {
+ qemu_irq_lower(s->irq);
+ }
+}
+
+static uint64_t ftkbc010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+ ftkbc010_state *s = FTKBC010(opaque);
+
+ switch (addr) {
+ case 0x00:
+ return s->cr;
+ case 0x10:
+ return s->isr;
+ case 0x30:
+ return ~(1 << s->x);
+ case 0x34:
+ return ~(1 << s->y);
+ case 0x50: /* revision */
+ return 0x00010403;
+ case 0x54: /* feature */
+ return 0x00000808;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void ftkbc010_mem_write(void *opaque,
+ hwaddr addr,
+ uint64_t val,
+ unsigned size)
+{
+ ftkbc010_state *s = FTKBC010(opaque);
+
+ switch (addr) {
+ case 0x00:
+ s->cr = (uint32_t)val;
+ /* if ftkbc010 enabled */
+ if (!(s->cr & (1 << 2))) {
+ break;
+ }
+ /* if keypad interrupt cleared */
+ if (s->cr & (1 << 10)) {
+ s->cr &= ~(1 << 10);
+ s->isr &= ~(1 << 2);
+ }
+ /* if rx interrupt cleared */
+ if (s->cr & (1 << 7)) {
+ s->cr &= ~(1 << 7);
+ s->isr &= ~(1 << 0);
+ }
+ /* if tx interrupt cleared */
+ if (s->cr & (1 << 6)) {
+ s->cr &= ~(1 << 6);
+ s->isr &= ~(1 << 1);
+ }
+ ftkbc010_update(s);
+ break;
+ default:
+ break;
+ }
+}
+
+static const MemoryRegionOps ftkbc010_mem_ops = {
+ .read = ftkbc010_mem_read,
+ .write = ftkbc010_mem_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void ftkbc010_key_event(void *opaque, int scancode)
+{
+ ftkbc010_state *s = FTKBC010(opaque);
+ int released = 0;
+
+ /* key release from qemu */
+ if (scancode & 0x80) {
+ released = 1;
+ }
+
+ /* strip qemu key release bit */
+ scancode &= ~0x80;
+
+ /* keypad interrupt */
+ if (!released && (s->cr & (1 << 8))) {
+ switch (scancode) {
+ case KEYCODE_ESC:
+ case KEYCODE_BACKSPACE:
+ s->x = 1;
+ break;
+ case KEYCODE_ENTER:
+ case KEYCODE_MENU:
+ case KEYCODE_SPACE:
+ s->x = 3;
+ break;
+ default:
+ s->x = 2; /* KEY_HOME */
+ break;
+ }
+ s->y = 0;
+ s->isr |= (1 << 2);
+ ftkbc010_update(s);
+ }
+}
+
+static void ftkbc010_reset(DeviceState *ds)
+{
+ SysBusDevice *busdev = SYS_BUS_DEVICE(ds);
+ ftkbc010_state *s = FTKBC010(FROM_SYSBUS(ftkbc010_state, busdev));
+
+ qemu_irq_lower(s->irq);
+}
+
+static int ftkbc010_init(SysBusDevice *dev)
+{
+ ftkbc010_state *s = FTKBC010(FROM_SYSBUS(ftkbc010_state, dev));
+
+ s->cr = 0;
+ s->isr = 0;
+ s->x = 0;
+ s->y = 0;
+
+ memory_region_init_io(&s->iomem,
+ &ftkbc010_mem_ops,
+ s,
+ TYPE_FTKBC010,
+ 0x1000);
+ sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_irq(dev, &s->irq);
+
+ qemu_add_kbd_event_handler(ftkbc010_key_event, s);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_ftkbc010 = {
+ .name = TYPE_FTKBC010,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cr, ftkbc010_state),
+ VMSTATE_UINT32(isr, ftkbc010_state),
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
+static void ftkbc010_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->init = ftkbc010_init;
+ dc->desc = TYPE_FTKBC010;
+ dc->vmsd = &vmstate_ftkbc010;
+ dc->reset = ftkbc010_reset;
+}
+
+static const TypeInfo ftkbc010_info = {
+ .name = TYPE_FTKBC010,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(ftkbc010_state),
+ .class_init = ftkbc010_class_init,
+};
+
+static void ftkbc010_register_types(void)
+{
+ type_register_static(&ftkbc010_info);
+}
+
+type_init(ftkbc010_register_types)
--
1.7.9.5
- [Qemu-devel] [PATCH v2 09/20] arm: add Faraday FTNANDC021 nand flash controller support, (continued)
- [Qemu-devel] [PATCH v2 09/20] arm: add Faraday FTNANDC021 nand flash controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 08/20] arm: add Faraday FTLCDC200 LCD controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 10/20] arm: add Faraday FTSDC010 MMC/SD controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 11/20] arm: add Faraday FTTSC010 touchscreen controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 12/20] arm: add Faraday FTSSP010 multi-function controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 16/20] arm: add Faraday FTTMR010 timer support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 15/20] arm: add Faraday FTWDT010 watchdog timer support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 13/20] arm: add Faraday FTSPI020 spi flash controller support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 19/20] arm: add Faraday FTKBC010 support for A369,
Kuo-Jung Su <=
[Qemu-devel] [PATCH v2 18/20] arm: add Faraday FTINTC020 interrupt controller, Kuo-Jung Su, 2013/01/25
[Qemu-devel] [PATCH v2 20/20] arm: add generic ROM model for Faraday SoC platforms, Kuo-Jung Su, 2013/01/25
[Qemu-devel] [PATCH v2 14/20] arm: add Faraday FTRTC011 RTC timer support, Kuo-Jung Su, 2013/01/25