All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Implement something
@ 2022-11-30  4:12 Evgeny Ermakov
  2022-11-30  4:12 ` [PATCH 1/2] hw/char: Add STM32F7 peripheral: USART Evgeny Ermakov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Evgeny Ermakov @ 2022-11-30  4:12 UTC (permalink / raw)
  To: qemu-devel, Evgeny Ermakov

Hello!

Evgeny Ermakov (2):
  hw/char: Add STM32F7 peripheral: USART
  hw/input: Add FT5336 touch controller

 include/hw/char/stm32f7xx_usart.h |  30 +++
 include/hw/input/ft5336.h         |  14 ++
 hw/char/stm32f7xx_usart.c         | 361 ++++++++++++++++++++++++++++++
 hw/input/ft5336.c                 | 357 +++++++++++++++++++++++++++++
 hw/arm/Kconfig                    |   1 +
 hw/char/Kconfig                   |   3 +
 hw/char/meson.build               |   1 +
 hw/char/trace-events              |   4 +
 hw/input/Kconfig                  |   4 +
 hw/input/meson.build              |   2 +
 10 files changed, 777 insertions(+)
 create mode 100644 include/hw/char/stm32f7xx_usart.h
 create mode 100644 include/hw/input/ft5336.h
 create mode 100644 hw/char/stm32f7xx_usart.c
 create mode 100644 hw/input/ft5336.c

-- 
2.38.1



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] hw/char: Add STM32F7 peripheral: USART
  2022-11-30  4:12 [PATCH 0/2] Implement something Evgeny Ermakov
@ 2022-11-30  4:12 ` Evgeny Ermakov
  2022-11-30  4:12 ` [PATCH 2/2] hw/input: Add FT5336 touch controller Evgeny Ermakov
  2022-11-30  4:17 ` [PATCH 0/2] Implement something Evgeny Ermakov
  2 siblings, 0 replies; 4+ messages in thread
From: Evgeny Ermakov @ 2022-11-30  4:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Evgeny Ermakov

Signed-off-by: Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
---
 include/hw/char/stm32f7xx_usart.h |  30 +++
 hw/char/stm32f7xx_usart.c         | 361 ++++++++++++++++++++++++++++++
 hw/arm/Kconfig                    |   1 +
 hw/char/Kconfig                   |   3 +
 hw/char/meson.build               |   1 +
 hw/char/trace-events              |   4 +
 6 files changed, 400 insertions(+)
 create mode 100644 include/hw/char/stm32f7xx_usart.h
 create mode 100644 hw/char/stm32f7xx_usart.c

diff --git a/include/hw/char/stm32f7xx_usart.h b/include/hw/char/stm32f7xx_usart.h
new file mode 100644
index 0000000000..ec005be8d8
--- /dev/null
+++ b/include/hw/char/stm32f7xx_usart.h
@@ -0,0 +1,30 @@
+/*
+ * STM32F7XX Universal synchronous/asynchronous receiver transmitter (USART)
+ *
+ * Copyright (c) 2022 Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_CHAR_STM32F7XX_USART_H
+#define HW_CHAR_STM32F7XX_USART_H
+
+#include "hw/arm/stm32f.h"
+#include "chardev/char-fe.h"
+
+#define TYPE_STM32F7XX_USART "stm32f7xx-usart"
+OBJECT_DECLARE_SIMPLE_TYPE(STM32F7XXUSARTState, STM32F7XX_USART)
+
+#define STM32F7XX_USART_R_MAX 11
+
+struct STM32F7XXUSARTState {
+    /*< private >*/
+    STM32FPeripheralState parent_obj;
+
+    uint32_t regs[STM32F7XX_USART_R_MAX];
+
+    CharBackend chr;
+    qemu_irq irq;
+};
+
+#endif /* HW_CHAR_STM32F7XX_USART_H */
diff --git a/hw/char/stm32f7xx_usart.c b/hw/char/stm32f7xx_usart.c
new file mode 100644
index 0000000000..122781705a
--- /dev/null
+++ b/hw/char/stm32f7xx_usart.c
@@ -0,0 +1,361 @@
+/*
+ * STM32F7XX Universal synchronous/asynchronous receiver transmitter (USART)
+ *
+ * Reference documents:
+ *   - Reference manual RM0385
+ *       "STM32F75xxx and stm32f74xxx advanced Arm(R)-based 32-bit MCUs"
+ *   - Reference manual RM0410
+ *       "STM32F76xxx and STM32F77xxx advanced Arm(R)-based 32-bit MCUs"
+ *
+ * Copyright (c) 2022 Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/char/stm32f7xx_usart.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "trace.h"
+
+#ifndef STM_USART_ERR_DEBUG
+#define STM_USART_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...)                   \
+    do {                                                \
+        if (STM_USART_ERR_DEBUG >= lvl) {               \
+            qemu_log("%s: " fmt, __func__, ## args);    \
+        }                                               \
+    } while (0)
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+REG32(CR1,         0x00)
+    /* reserved: 31:29, 1 */
+    FIELD(CR1,        M1,             28, 1)
+    FIELD(CR1,        EOBIE,          27, 1)
+    FIELD(CR1,        RTOIE,          26, 1)
+    FIELD(CR1,        DEAT,           21, 5)
+    FIELD(CR1,        DEDT,           16, 5)
+    FIELD(CR1,        OVER8,          15, 1)
+    FIELD(CR1,        CMIE,           14, 1)
+    FIELD(CR1,        MME,            13, 1)
+    FIELD(CR1,        M0,             12, 1)
+    FIELD(CR1,        WAKE,           11, 1)
+    FIELD(CR1,        PCE,            10, 1)
+    FIELD(CR1,        PS,              9, 1)
+    FIELD(CR1,        PEIE,            8, 1)
+    FIELD(CR1,        TXEIE,           7, 1)
+    FIELD(CR1,        TCIE,            6, 1)
+    FIELD(CR1,        RXNEIE,          5, 1)
+    FIELD(CR1,        IDLEIE,          4, 1)
+    FIELD(CR1,        TE,              3, 1)
+    FIELD(CR1,        RE,              2, 1)
+    FIELD(CR1,        UE,              0, 1)
+REG32(CR2,         0x04)
+    /* reserved: 7, 3:0 */
+    FIELD(CR2,        ADD,            24, 8)
+    FIELD(CR2,        RTOEN,          23, 1)
+    FIELD(CR2,        ABRMOD,         21, 2)
+    FIELD(CR2,        ABREN,          20, 1)
+    FIELD(CR2,        MSBFIRST,       19, 1)
+    FIELD(CR2,        DATAINV,        18, 1)
+    FIELD(CR2,        TXINV,          17, 1)
+    FIELD(CR2,        RXINV,          16, 1)
+    FIELD(CR2,        SWAP,           15, 1)
+    FIELD(CR2,        LINEN,          14, 1)
+    FIELD(CR2,        STOP,           12, 2)
+    FIELD(CR2,        CLKEN,          11, 1)
+    FIELD(CR2,        CPOL,           10, 1)
+    FIELD(CR2,        CPHA,            9, 1)
+    FIELD(CR2,        LBCL,            8, 1)
+    FIELD(CR2,        LBDIE,           6, 1)
+    FIELD(CR2,        LBDL,            5, 1)
+    FIELD(CR2,        ADDM7,           4, 1)
+REG32(CR3,         0x08)
+    /* reserved: 31:25, 16 */
+    FIELD(CR3,        TCBGTIE,        24, 1)
+    FIELD(CR3,        UCESM,          23, 1)
+    FIELD(CR3,        WUFIE,          22, 1)
+    FIELD(CR3,        WUS,            20, 2)
+    FIELD(CR3,        SCARCNT,        17, 3)
+    FIELD(CR3,        DEP,            15, 1)
+    FIELD(CR3,        DEM,            14, 1)
+    FIELD(CR3,        DDRE,           13, 1)
+    FIELD(CR3,        OVRDIS,         12, 1)
+    FIELD(CR3,        ONEBIT,         11, 1)
+    FIELD(CR3,        CTSIE,          10, 1)
+    FIELD(CR3,        CTSE,            9, 1)
+    FIELD(CR3,        RTSE,            8, 1)
+    FIELD(CR3,        DMAT,            7, 1)
+    FIELD(CR3,        DMAR,            6, 1)
+    FIELD(CR3,        SCEN,            5, 1)
+    FIELD(CR3,        NACK,            4, 1)
+    FIELD(CR3,        HDSEL,           3, 1)
+    FIELD(CR3,        IRLP,            2, 1)
+    FIELD(CR3,        IREN,            1, 1)
+    FIELD(CR3,        EIE,             0, 1)
+REG32(BRR,         0x0c)
+    /* reserved: 31:16 */
+    FIELD(BRR,        BRR,             0, 15)
+REG32(GTPR,        0x10)
+    /* reserved: 31:16 */
+    FIELD(GTPR,       GT,              8, 8)
+    FIELD(GTPR,       PSC,             0, 8)
+REG32(RTOR,        0x14)
+    FIELD(RTOR,       BLEN,           24, 8)
+    FIELD(RTOR,       RTO,             0, 24)
+REG32(RQR,         0x18)
+    /* reserved: 31:5 */
+    FIELD(RQR,        TXFRQ,           4, 1)
+    FIELD(RQR,        RXFRQ,           3, 1)
+    FIELD(RQR,        MMRQ,            2, 1)
+    FIELD(RQR,        SBKRQ,           1, 1)
+    FIELD(RQR,        ABRRQ,           0, 1)
+REG32(ISR,         0x1c)
+    /* reserved: 31:26, 24:23, 13 */
+    FIELD(ISR,        TCBGT,          25, 1)
+    FIELD(ISR,        REACK,          22, 1)
+    FIELD(ISR,        TEACK,          21, 1)
+    FIELD(ISR,        WUF,            20, 1)
+    FIELD(ISR,        RWU,            19, 1)
+    FIELD(ISR,        SBKF,           18, 1)
+    FIELD(ISR,        CMF,            17, 1)
+    FIELD(ISR,        BUSY,           16, 1)
+    FIELD(ISR,        ABRF,           15, 1)
+    FIELD(ISR,        ABRE,           14, 1)
+    FIELD(ISR,        EOBF,           12, 1)
+    FIELD(ISR,        RTOF,           11, 1)
+    FIELD(ISR,        CTS,            10, 1)
+    FIELD(ISR,        CTSIF,           9, 1)
+    FIELD(ISR,        LBDF,            8, 1)
+    FIELD(ISR,        TXE,             7, 1)
+    FIELD(ISR,        TC,              6, 1)
+    FIELD(ISR,        RXNE,            5, 1)
+    FIELD(ISR,        IDLE,            4, 1)
+    FIELD(ISR,        ORE,             3, 1)
+    FIELD(ISR,        NF,              2, 1)
+    FIELD(ISR,        FE,              1, 1)
+    FIELD(ISR,        PE,              0, 1)
+REG32(ICR,         0x20)
+    /* reserved: 31:21, 19:18, 16:13, 10, 5 */
+    FIELD(ICR,        WUCF,           20, 1)
+    FIELD(ICR,        CMCF,           17, 1)
+    FIELD(ICR,        EOBCF,          12, 1)
+    FIELD(ICR,        RTOCF,          11, 1)
+    FIELD(ICR,        CTSCF,           9, 1)
+    FIELD(ICR,        LBDCF,           8, 1)
+    FIELD(ICR,        TCBGTCF,         7, 1)
+    FIELD(ICR,        TCCF,            6, 1)
+    FIELD(ICR,        IDLECF,          4, 1)
+    FIELD(ICR,        ORECF,           3, 1)
+    FIELD(ICR,        NCF,             2, 1)
+    FIELD(ICR,        FECF,            1, 1)
+    FIELD(ICR,        PECF,            0, 1)
+REG32(RDR,         0x24)
+    /* reserved: 31:9 */
+    FIELD(RDR,        RDR,             0, 9)
+REG32(TDR,         0x28)
+    /* reserved: 31:9 */
+    FIELD(TDR,        TDR,             0, 9)
+
+
+static int stm32f7xx_usart_can_receive(void *opaque)
+{
+    /* STM32F7XXUSARTState *s = opaque; */
+
+    /* if (!(s->usart_sr & USART_SR_RXNE)) { */
+    /*     return 1; */
+    /* } */
+
+    return 0;
+}
+
+static void stm32f7xx_usart_receive(void *opaque, const uint8_t *buf, int size)
+{
+#if 0
+    STM32F7XXUSARTState *s = opaque;
+
+    if (!(s->usart_cr1 & USART_CR1_UE && s->usart_cr1 & USART_CR1_RE)) {
+        /* USART not enabled - drop the chars */
+        DB_PRINT("Dropping the chars\n");
+        return;
+    }
+
+    s->usart_dr = *buf;
+    s->usart_sr |= USART_SR_RXNE;
+
+    if (s->usart_cr1 & USART_CR1_RXNEIE) {
+        qemu_set_irq(s->irq, 1);
+    }
+
+    DB_PRINT("Receiving: %c\n", s->usart_dr);
+#endif
+}
+
+static uint32_t stm32f7xx_usart_read(void *opaque, hwaddr addr,
+                                     unsigned int size)
+{
+    STM32F7XXUSARTState *s = opaque;
+
+    trace_stm32f7xx_usart_read(addr);
+
+    switch (addr) {
+    case A_CR1:
+        return s->regs[R_CR1];
+    case A_CR2:
+        return s->regs[R_CR2];
+    case A_CR3:
+        return s->regs[R_CR3];
+    case A_BRR:
+        return s->regs[R_BRR];
+    case A_GTPR:
+        return s->regs[R_GTPR];
+    case A_RTOR:
+        return s->regs[R_RTOR];
+    case A_RQR:
+        return s->regs[R_RQR];
+    case A_ISR:
+        return s->regs[R_ISR];
+    case A_ICR:
+        return s->regs[R_ICR];
+    case A_RDR:
+        return s->regs[R_RDR];
+    case A_TDR:
+        return s->regs[R_TDR];
+    default:
+        STM32F_LOG_BAD_OFFSET();
+        break;
+    }
+
+    return 0;
+}
+
+static void stm32f7xx_usart_write(void *opaque, hwaddr addr,
+                                  uint32_t value, unsigned int size)
+{
+    STM32F7XXUSARTState *s = opaque;
+    /* unsigned char ch; */
+
+    trace_stm32f7xx_usart_write(addr, value);
+
+    switch (addr) {
+    case A_CR1:
+        s->regs[R_CR1] = value;
+        break;
+    case A_CR2:
+        s->regs[R_CR2] = value;
+        break;
+    case A_CR3:
+        s->regs[R_CR3] = value;
+        break;
+    case A_BRR:
+        s->regs[R_BRR] = value;
+        break;
+    case A_GTPR:
+        s->regs[R_GTPR] = value;
+        break;
+    case A_RTOR:
+        s->regs[R_RTOR] = value;
+        break;
+    case A_RQR:
+        s->regs[R_RQR] = value;
+        break;
+    case A_ISR:
+        s->regs[R_ISR] = value;
+        break;
+    case A_ICR:
+        s->regs[R_ICR] = value;
+        break;
+    case A_RDR:
+        s->regs[R_RDR] = value;
+        break;
+    case A_TDR:
+        if (value < 0xf000) {
+            uint8_t ch = value;
+            /* XXX this blocks entire thread. Rewrite to use
+             * qemu_chr_fe_write and background I/O callbacks */
+            qemu_chr_fe_write_all(&s->chr, &ch, 1);
+            /* XXX I/O are currently synchronous, making it impossible for
+               software to observe transient states where TXE or TC aren't
+               set. Unlike TXE however, which is read-only, software may
+               clear TC by writing 0 to the SR register, so set it again
+               on each write. */
+            /* s->usart_sr |= USART_SR_TC; */
+        }
+        break;
+    default:
+        STM32F_LOG_BAD_OFFSET();
+        break;
+    }
+}
+
+static void stm32f7xx_usart_reset_enter(Object *obj, ResetType type)
+{
+    STM32F7XXUSARTState *s = STM32F7XX_USART(obj);
+
+    memset(s->regs, 0, sizeof(s->regs));
+    s->regs[R_ISR] = 0x020000c0;
+}
+
+static void stm32f7xx_usart_reset_exit(Object *obj)
+{
+    STM32F7XXUSARTState *s = STM32F7XX_USART(obj);
+
+    qemu_set_irq(s->irq, 0);
+}
+
+static void stm32f7xx_usart_init(Object *obj)
+{
+    STM32F7XXUSARTState *s = STM32F7XX_USART(obj);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+}
+
+static void stm32f7xx_usart_realize(DeviceState *dev, Error **errp)
+{
+    STM32F7XXUSARTState *s = STM32F7XX_USART(dev);
+
+    qemu_chr_fe_set_handlers(&s->chr, stm32f7xx_usart_can_receive,
+                             stm32f7xx_usart_receive, NULL, NULL,
+                             s, NULL, true);
+}
+
+static Property stm32f7xx_usart_properties[] = {
+    DEFINE_PROP_CHR("chardev", STM32F7XXUSARTState, chr),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void stm32f7xx_usart_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    STM32FPeripheralClass *pc = STM32F_PERIPHERAL_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->realize = stm32f7xx_usart_realize;
+    device_class_set_props(dc, stm32f7xx_usart_properties);
+    rc->phases.enter = stm32f7xx_usart_reset_enter;
+    rc->phases.exit = stm32f7xx_usart_reset_exit;
+    pc->mmio_size = 0x400;
+    pc->mmio_read = stm32f7xx_usart_read;
+    pc->mmio_write = stm32f7xx_usart_write;
+}
+
+static const TypeInfo stm32f7xx_usart_info = {
+    .name          = TYPE_STM32F7XX_USART,
+    .parent        = TYPE_STM32F_PERIPHERAL,
+    .instance_size = sizeof(STM32F7XXUSARTState),
+    .instance_init = stm32f7xx_usart_init,
+    .class_init    = stm32f7xx_usart_class_init,
+};
+
+static void stm32f7xx_usart_register_types(void)
+{
+    type_register_static(&stm32f7xx_usart_info);
+}
+
+type_init(stm32f7xx_usart_register_types)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index c2f6e748b0..02dfbcb99a 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -376,6 +376,7 @@ config STM32F405_SOC
 config STM32F7XX_SOC
     bool
     select STM32F
+    select STM32F7XX_USART
 
 config XLNX_ZYNQMP_ARM
     bool
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 6b6cf2fc1d..22b1cf8062 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -41,6 +41,9 @@ config VIRTIO_SERIAL
 config STM32F2XX_USART
     bool
 
+config STM32F7XX_USART
+    bool
+
 config CMSDK_APB_UART
     bool
 
diff --git a/hw/char/meson.build b/hw/char/meson.build
index 7b594f51b8..6230750375 100644
--- a/hw/char/meson.build
+++ b/hw/char/meson.build
@@ -31,6 +31,7 @@ softmmu_ss.add(when: 'CONFIG_RENESAS_SCI', if_true: files('renesas_sci.c'))
 softmmu_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c'))
 softmmu_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c'))
 softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
+softmmu_ss.add(when: 'CONFIG_STM32F7XX_USART', if_true: files('stm32f7xx_usart.c'))
 softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
 
 specific_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 2ecb36232e..41fa3c0b46 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -105,3 +105,7 @@ cadence_uart_baudrate(unsigned baudrate) "baudrate %u"
 # sh_serial.c
 sh_serial_read(char *id, unsigned size, uint64_t offs, uint64_t val) " %s size %d offs 0x%02" PRIx64 " -> 0x%02" PRIx64
 sh_serial_write(char *id, unsigned size, uint64_t offs, uint64_t val) "%s size %d offs 0x%02" PRIx64 " <- 0x%02" PRIx64
+
+# stm32f7xx_usart.c
+stm32f7xx_usart_read(uint64_t addr) " addr: 0x%02" PRIx64
+stm32f7xx_usart_write(uint64_t addr, uint64_t data) "addr: 0x%02" PRIx64 " val: 0x%" PRIx64
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] hw/input: Add FT5336 touch controller
  2022-11-30  4:12 [PATCH 0/2] Implement something Evgeny Ermakov
  2022-11-30  4:12 ` [PATCH 1/2] hw/char: Add STM32F7 peripheral: USART Evgeny Ermakov
@ 2022-11-30  4:12 ` Evgeny Ermakov
  2022-11-30  4:17 ` [PATCH 0/2] Implement something Evgeny Ermakov
  2 siblings, 0 replies; 4+ messages in thread
From: Evgeny Ermakov @ 2022-11-30  4:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Evgeny Ermakov

Signed-off-by: Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
---
 include/hw/input/ft5336.h |  14 ++
 hw/input/ft5336.c         | 357 ++++++++++++++++++++++++++++++++++++++
 hw/input/Kconfig          |   4 +
 hw/input/meson.build      |   2 +
 4 files changed, 377 insertions(+)
 create mode 100644 include/hw/input/ft5336.h
 create mode 100644 hw/input/ft5336.c

diff --git a/include/hw/input/ft5336.h b/include/hw/input/ft5336.h
new file mode 100644
index 0000000000..7bef3f9efb
--- /dev/null
+++ b/include/hw/input/ft5336.h
@@ -0,0 +1,14 @@
+/*
+ * FT5336 touch controller
+ *
+ * Copyright (c) 2022 Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_INPUT_FT5336_H
+#define HW_INPUT_FT5336_H
+
+#define TYPE_FT5336 "ft5336"
+
+#endif
diff --git a/hw/input/ft5336.c b/hw/input/ft5336.c
new file mode 100644
index 0000000000..bacf79201a
--- /dev/null
+++ b/hw/input/ft5336.c
@@ -0,0 +1,357 @@
+/*
+ * FT5336 touch controller
+ *
+ * Copyright (c) 2022 Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/input/ft5336.h"
+#include "hw/i2c/i2c.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "ui/input.h"
+#include "qom/object.h"
+
+OBJECT_DECLARE_SIMPLE_TYPE(FT5336TouchState, FT5336)
+
+struct FT5336TouchState {
+    I2CSlave parent_obj;
+
+    uint8_t i2c_cycle;
+    uint8_t reg;
+
+    qemu_irq irq;
+
+    int32_t abs_x;
+    int32_t abs_y;
+    uint16_t touch_x;
+    uint16_t touch_y;
+    bool touch_press;
+
+    bool inte;
+};
+
+/* I2C Slave address of touchscreen FocalTech FT5336 */
+#define FT5336_I2C_SLAVE_ADDRESS            0x70
+
+/* Maximum border values of the touchscreen pad */
+#define FT5336_MAX_WIDTH                    ((uint16_t)480)     /* Touchscreen pad max width   */
+#define FT5336_MAX_HEIGHT                   ((uint16_t)272)     /* Touchscreen pad max height  */
+
+/* Max detectable simultaneous touches */
+#define FT5336_MAX_DETECTABLE_TOUCH         0x05
+
+
+enum {
+    FT5336_P_XH               = 0x00,
+    FT5336_P_XL               = 0x01,
+    FT5336_P_YH               = 0x02,
+    FT5336_P_YL               = 0x03,
+   /* Values Pn_XH and Pn_YH related */
+#define FT5336_TOUCH_EVT_FLAG_PRESS_DOWN    0x00
+#define FT5336_TOUCH_EVT_FLAG_LIFT_UP       0x01
+#define FT5336_TOUCH_EVT_FLAG_CONTACT       0x02
+#define FT5336_TOUCH_EVT_FLAG_NO_EVENT      0x03
+
+    FT5336_P_WEIGHT           = 0x04,
+    /* Values Pn_WEIGHT related  */
+#define FT5336_TOUCH_WEIGHT_MASK            0xFF
+#define FT5336_TOUCH_WEIGHT_SHIFT           0x00
+
+    FT5336_P_MISC             = 0x05
+    /* Values related to FT5336_Pn_MISC_REG */
+#define FT5336_TOUCH_AREA_MASK              (0x04 << 4))
+#define FT5336_TOUCH_AREA_SHIFT             0x04
+};
+
+enum {
+    FT5336_R_MODE               = 0x00,
+#define FT5336_DEV_MODE_WORKING             0x00
+#define FT5336_DEV_MODE_FACTORY             0x04
+
+#define FT5336_DEV_MODE_MASK                0x07
+#define FT5336_DEV_MODE_SHIFT               0x04
+
+    FT5336_R_GEST_ID            = 0x01,
+#define FT5336_GEST_ID_NO_GESTURE           0x00
+#define FT5336_GEST_ID_MOVE_UP              0x10
+#define FT5336_GEST_ID_MOVE_RIGHT           0x14
+#define FT5336_GEST_ID_MOVE_DOWN            0x18
+#define FT5336_GEST_ID_MOVE_LEFT            0x1C
+#define FT5336_GEST_ID_SINGLE_CLICK         0x20
+#define FT5336_GEST_ID_DOUBLE_CLICK         0x22
+#define FT5336_GEST_ID_ROTATE_CLOCKWISE     0x28
+#define FT5336_GEST_ID_ROTATE_C_CLOCKWISE   0x29
+#define FT5336_GEST_ID_ZOOM_IN              0x40
+#define FT5336_GEST_ID_ZOOM_OUT             0x49
+
+    FT5336_R_STAT               = 0x02,
+#define FT5336_TD_STAT_MASK                 0x0F
+#define FT5336_TD_STAT_SHIFT                0x00
+
+    FT5336_R_P1_BASE            = 0x03,
+    FT5336_R_P2_BASE            = 0x09,
+    FT5336_R_P3_BASE            = 0x0f,
+    FT5336_R_P4_BASE            = 0x15,
+    FT5336_R_P5_BASE            = 0x1b,
+    FT5336_R_P6_BASE            = 0x21,
+    FT5336_R_P7_BASE            = 0x27,
+    FT5336_R_P8_BASE            = 0x2d,
+    FT5336_R_P9_BASE            = 0x33,
+    FT5336_R_P10_BASE           = 0x39,
+
+#define FT5336_TOUCH_EVT_FLAG_SHIFT         0x06
+#define FT5336_TOUCH_EVT_FLAG_MASK          (3 << FT5336_TOUCH_EVT_FLAG_SHIFT))
+
+#define FT5336_TOUCH_POS_MSB_MASK           0x0F
+#define FT5336_TOUCH_POS_MSB_SHIFT          0x00
+
+    /* Values Pn_XL and Pn_YL related */
+#define FT5336_TOUCH_POS_LSB_MASK           0xFF
+#define FT5336_TOUCH_POS_LSB_SHIFT          0x00
+
+    FT5336_R_TH_GROUP           = 0x80,
+    /* Values FT5336_TH_GROUP_REG : threshold related  */
+#define FT5336_THRESHOLD_MASK               0xFF
+#define FT5336_THRESHOLD_SHIFT              0x00
+
+    FT5336_R_TH_DIFF            = 0x85,
+
+    FT5336_R_CTRL               = 0x86,
+    /* Values related to FT5336_CTRL_REG */
+
+    /* Will keep the Active mode when there is no touching */
+#define FT5336_CTRL_KEEP_ACTIVE_MODE        0x00
+
+    /* Switching from Active mode to Monitor mode automatically when there is no touching */
+#define FT5336_CTRL_KEEP_AUTO_SWITCH_MONITOR_MODE  0x01
+    FT5336_R_TIMEENTERMONITOR   = 0x87,
+    FT5336_R_PERIODACTIVE       = 0x88,
+    FT5336_R_PERIODMONITOR      = 0x89,
+    FT5336_R_RADIAN_VALUE       = 0x91,
+    FT5336_R_OFFSET_LEFT_RIGHT  = 0x92,
+    FT5336_R_OFFSET_UP_DOWN     = 0x93,
+    FT5336_R_DISTANCE_LEFT      = 0x94,
+    FT5336_R_DISTANCE_UP_DOWN   = 0x95,
+    FT5336_R_DISTANCE_ZOOM      = 0x96,
+
+    FT5336_R_LIB_VER_H          = 0xa1,
+    FT5336_R_LIB_VER_L          = 0xa2,
+    FT5336_R_CIPHER             = 0xa3,
+
+    FT5336_R_GMODE              = 0xa4,
+#define FT5336_G_MODE_INTERRUPT_MASK        0x03
+#define FT5336_G_MODE_INTERRUPT_SHIFT       0x00
+
+    /* Possible values of FT5336_GMODE_REG */
+#define FT5336_G_MODE_INTERRUPT_POLLING     0x00
+#define FT5336_G_MODE_INTERRUPT_TRIGGER     0x01
+
+    FT5336_R_PWR_MODE           = 0xa5,
+    FT5336_R_FIRMID             = 0xa6,
+
+    FT5336_R_CHIP_ID            = 0xa8,
+    /*  Possible values of FT5336_CHIP_ID_REG */
+#define FT5336_ID_VALUE                     0x51
+
+    FT5336_R_RELEASE_CODE_ID    = 0xaf,
+    /* Release code version */
+#define FT5336_RELEASE_CODE_ID_REG          0xAF
+
+    FT5336_R_STATE              = 0xbc,
+};
+
+
+static uint8_t ft5336_touch_read(FT5336TouchState *s, int reg, int byte)
+{
+    switch (reg) {
+    case FT5336_R_CHIP_ID:
+        return FT5336_ID_VALUE;
+    case FT5336_R_STAT:
+        return s->touch_press ? 1 : 0;
+    case FT5336_R_P1_BASE:
+        switch (byte) {
+        case FT5336_P_XH: return extract16(s->touch_x, 8, 8);
+        case FT5336_P_XL: return extract16(s->touch_x, 0, 8);
+        case FT5336_P_YH: return extract16(s->touch_y, 8, 8);
+        case FT5336_P_YL: return extract16(s->touch_y, 0, 8);
+        default:
+            return 0;
+        }
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: unknown register %02x\n", __func__, reg);
+        return 0;
+    }
+}
+
+static void ft5336_touch_write(FT5336TouchState *s, int reg, int byte, uint8_t value)
+{
+    switch (reg) {
+    case FT5336_R_GMODE:
+        s->inte = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: unknown register %02x\n", __func__, reg);
+        break;
+    }
+}
+
+static int ft5336_i2c_event(I2CSlave *i2c, enum i2c_event event)
+{
+    FT5336TouchState *s = FT5336(i2c);
+
+    switch (event) {
+    case I2C_START_RECV:
+    case I2C_START_SEND:
+        s->i2c_cycle = 0;
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static uint8_t ft5336_i2c_recv(I2CSlave *i2c)
+{
+    FT5336TouchState *s = FT5336(i2c);
+
+    return ft5336_touch_read(s, s->reg, s->i2c_cycle++);
+}
+
+static int ft5336_i2c_send(I2CSlave *i2c, uint8_t data)
+{
+    FT5336TouchState *s = FT5336(i2c);
+
+    if (!s->i2c_cycle) {
+        s->reg = data;
+    } else {
+        ft5336_touch_write(s, s->reg, s->i2c_cycle - 1, data);
+    }
+    s->i2c_cycle++;
+
+    return 0;
+}
+
+static void ft5336_input_event(DeviceState *dev, QemuConsole *src,
+                               InputEvent *evt)
+{
+    FT5336TouchState *s = FT5336(dev);
+    InputBtnEvent *btn = NULL;
+    InputMoveEvent *move = NULL;
+
+    switch (evt->type) {
+    case INPUT_EVENT_KIND_BTN:
+        btn = evt->u.btn.data;
+        s->touch_press = btn->down;
+        break;
+    case INPUT_EVENT_KIND_ABS:
+        move = evt->u.rel.data;
+        if (move->axis == INPUT_AXIS_X) {
+            s->abs_x = move->value;
+        } else if (move->axis == INPUT_AXIS_Y) {
+            s->abs_y = move->value;
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+static void ft5336_input_sync(DeviceState *dev)
+{
+    FT5336TouchState *s = FT5336(dev);;
+
+    s->touch_x = qemu_input_scale_axis(s->abs_x,
+                                       INPUT_EVENT_ABS_MIN,
+                                       INPUT_EVENT_ABS_MAX, 0, 1777);
+    s->touch_y = qemu_input_scale_axis(s->abs_y,
+                                       INPUT_EVENT_ABS_MIN,
+                                       INPUT_EVENT_ABS_MAX, 0, 1023);
+
+    if (s->touch_press) {
+        if (s->inte) {
+            qemu_irq_pulse(s->irq);
+        }
+    }
+}
+
+static QemuInputHandler ft5336_input_handler = {
+    .name = "QEMU FT5336-driven Touchscreen",
+    .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
+    .event = ft5336_input_event,
+    .sync = ft5336_input_sync
+};
+
+static void ft5336_touch_reset_enter(Object *obj, ResetType type)
+{
+    FT5336TouchState *s = FT5336(obj);
+
+    s->inte = false;
+}
+
+static void ft5336_realize(DeviceState *dev, Error **errp)
+{
+    FT5336TouchState *s = FT5336(dev);
+    qdev_init_gpio_out(dev, &s->irq, 1);
+
+    qemu_input_handler_register((DeviceState *) s, &ft5336_input_handler);
+}
+
+static int ft5336_touch_post_load(void *opaque, int version_id)
+{
+    /* FT5336TouchState *s = opaque; */
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_ft5336_touch = {
+    .name = TYPE_FT5336,
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .post_load = ft5336_touch_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_I2C_SLAVE(parent_obj, FT5336TouchState),
+        VMSTATE_UINT8(i2c_cycle, FT5336TouchState),
+        VMSTATE_UINT8(reg, FT5336TouchState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void ft5336_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->realize = ft5336_realize;
+    dc->vmsd = &vmstate_ft5336_touch;
+    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
+    rc->phases.enter = ft5336_touch_reset_enter;
+
+    sc->event = ft5336_i2c_event;
+    sc->recv = ft5336_i2c_recv;
+    sc->send = ft5336_i2c_send;
+}
+
+static const TypeInfo ft5336_info = {
+    .name          = TYPE_FT5336,
+    .parent        = TYPE_I2C_SLAVE,
+    .instance_size = sizeof(FT5336TouchState),
+    .class_init    = ft5336_class_init
+};
+
+static void ft5336_register_types(void)
+{
+    type_register_static(&ft5336_info);
+}
+
+type_init(ft5336_register_types)
diff --git a/hw/input/Kconfig b/hw/input/Kconfig
index 55865bb386..73a6f67216 100644
--- a/hw/input/Kconfig
+++ b/hw/input/Kconfig
@@ -46,3 +46,7 @@ config TSC210X
 
 config LASIPS2
     select PS2
+
+config FT5336
+    bool
+    depends on I2C
diff --git a/hw/input/meson.build b/hw/input/meson.build
index 8deb011d4a..c892ecbeb7 100644
--- a/hw/input/meson.build
+++ b/hw/input/meson.build
@@ -16,3 +16,5 @@ softmmu_ss.add(when: 'CONFIG_VHOST_USER_INPUT', if_true: files('vhost-user-input
 softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_keypad.c'))
 softmmu_ss.add(when: 'CONFIG_TSC210X', if_true: files('tsc210x.c'))
 softmmu_ss.add(when: 'CONFIG_LASIPS2', if_true: files('lasips2.c'))
+
+softmmu_ss.add(when: 'CONFIG_FT5336', if_true: files('ft5336.c'))
-- 
2.38.1



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] Implement something
  2022-11-30  4:12 [PATCH 0/2] Implement something Evgeny Ermakov
  2022-11-30  4:12 ` [PATCH 1/2] hw/char: Add STM32F7 peripheral: USART Evgeny Ermakov
  2022-11-30  4:12 ` [PATCH 2/2] hw/input: Add FT5336 touch controller Evgeny Ermakov
@ 2022-11-30  4:17 ` Evgeny Ermakov
  2 siblings, 0 replies; 4+ messages in thread
From: Evgeny Ermakov @ 2022-11-30  4:17 UTC (permalink / raw)
  To: qemu-devel

Evgeny Ermakov <evgeny.v.ermakov@gmail.com> writes:

Oops, sorry. Ignore this, I sent it by mistake.

> Hello!
>
> Evgeny Ermakov (2):
>   hw/char: Add STM32F7 peripheral: USART
>   hw/input: Add FT5336 touch controller
>
>  include/hw/char/stm32f7xx_usart.h |  30 +++
>  include/hw/input/ft5336.h         |  14 ++
>  hw/char/stm32f7xx_usart.c         | 361 ++++++++++++++++++++++++++++++
>  hw/input/ft5336.c                 | 357 +++++++++++++++++++++++++++++
>  hw/arm/Kconfig                    |   1 +
>  hw/char/Kconfig                   |   3 +
>  hw/char/meson.build               |   1 +
>  hw/char/trace-events              |   4 +
>  hw/input/Kconfig                  |   4 +
>  hw/input/meson.build              |   2 +
>  10 files changed, 777 insertions(+)
>  create mode 100644 include/hw/char/stm32f7xx_usart.h
>  create mode 100644 include/hw/input/ft5336.h
>  create mode 100644 hw/char/stm32f7xx_usart.c
>  create mode 100644 hw/input/ft5336.c
>
> -- 
> 2.38.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-11-30  4:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-30  4:12 [PATCH 0/2] Implement something Evgeny Ermakov
2022-11-30  4:12 ` [PATCH 1/2] hw/char: Add STM32F7 peripheral: USART Evgeny Ermakov
2022-11-30  4:12 ` [PATCH 2/2] hw/input: Add FT5336 touch controller Evgeny Ermakov
2022-11-30  4:17 ` [PATCH 0/2] Implement something Evgeny Ermakov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.