All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel]  [PATCH v7 0/5] arm: kinetis_mk64fn1m0 machine
@ 2017-10-27 12:24 Gabriel Costa
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 1/5] arm: kinetis_k64_uart Gabriel Costa
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Gabriel Costa @ 2017-10-27 12:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, peter.maydell, f4bug, Gabriel Augusto Costa

From: Gabriel Augusto Costa <gabriel291075@gmail.com>

Hi everyone,

I made a new arm machine with some peripherals.
The machine is mk64fn1m0, a cortex-m4 microcontroller from NXP Kinetis family.
I have prepared a series of patchs to include this machine:

PATCH v5 n/5: It adds the machine and peripherals devices;
PATCH v6: It changes the Makes files to compile this machine.

This machine has been created based on K64P144M120SF5RM.pdf, stellaris and
stm32f205 machines, and reading the code of the other devices. Also, the
comments from community and special thanks to Peter Maydell, Philippe
Mathieu-Daude and Eric Blake.

The initial propose of this machine is execute a simple example, only
with UART0 in polling mode, and gradually adding other devices/peripherals to
this machine to allow execute an operating system like FreeRTOS or MQX.
Next step:
	-Execute an example of UART0 working with interruption.
	-Add a timer with interruption.

The code to test can be generated using MCUXpresso IDE v10.0.2_411, with the
option "Import SDK Examples", selecting "frdmk64f" family, driver_examples,
uart, polling.
The binary file generated is frdmk64f_driver_examples_uart_polling.axf and
can be executed in QEmu with this patch using the following command:
$qemu-system-arm -M mk64fn1m0 -kernel frdmk64f_driver_examples_uart_polling.axf
obs: I can send the file if someone want to test!

History:

PATCH V1: First try. Many errors, the patch is long with code style
	issues, change the files to executable. 
PATCH V2: the same mistakes.

PATCH V3: The patch was splitted in series of patch, without code style
 errors. I receive some tips about QEmu functions and others tips.
PATCH V4: Not send.

PATCH V5: Change the 0x%02X to HWADDR_PRIx on qemu_log_mask and added
	.valid.min_access_size and .valid.max_access_size
PATCH v6: misunderstood the process to add a new model, next patch will
	include the changes in the Makefile in the same patch version.
	
regards,

Gabriel Costa (5):
  arm: kinetis_k64_uart
  arm: kinetis_k64_mcg
  arm: kinetis_k64_pmux
  arm: kinetis_k64_system
  arm: kinetis_mk64fn1m0 machine

 default-configs/arm-softmmu.mak      |   1 +
 hw/arm/Makefile.objs                 |   1 +
 hw/arm/mk64fn1m0.c                   | 136 ++++++++++++++
 hw/char/Makefile.objs                |   1 +
 hw/char/kinetis_k64_uart.c           | 343 +++++++++++++++++++++++++++++++++++
 hw/misc/Makefile.objs                |   3 +
 hw/misc/kinetis_k64_mcg.c            | 208 +++++++++++++++++++++
 hw/misc/kinetis_k64_pmux.c           | 158 ++++++++++++++++
 hw/misc/kinetis_k64_system.c         | 274 ++++++++++++++++++++++++++++
 include/hw/char/kinetis_k64_uart.h   |  79 ++++++++
 include/hw/misc/kinetis_k64_mcg.h    |  43 +++++
 include/hw/misc/kinetis_k64_pmux.h   |  38 ++++
 include/hw/misc/kinetis_k64_system.h |  52 ++++++
 13 files changed, 1337 insertions(+)
 create mode 100644 hw/arm/mk64fn1m0.c
 create mode 100644 hw/char/kinetis_k64_uart.c
 create mode 100644 hw/misc/kinetis_k64_mcg.c
 create mode 100644 hw/misc/kinetis_k64_pmux.c
 create mode 100644 hw/misc/kinetis_k64_system.c
 create mode 100644 include/hw/char/kinetis_k64_uart.h
 create mode 100644 include/hw/misc/kinetis_k64_mcg.h
 create mode 100644 include/hw/misc/kinetis_k64_pmux.h
 create mode 100644 include/hw/misc/kinetis_k64_system.h

-- 
2.1.4

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

* [Qemu-devel]  [PATCH v7 1/5] arm: kinetis_k64_uart
  2017-10-27 12:24 [Qemu-devel] [PATCH v7 0/5] arm: kinetis_mk64fn1m0 machine Gabriel Costa
@ 2017-10-27 12:24 ` Gabriel Costa
  2017-11-21 14:13   ` Peter Maydell
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 2/5] arm: kinetis_k64_mcg Gabriel Costa
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Gabriel Costa @ 2017-10-27 12:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, peter.maydell, f4bug, Gabriel Augusto Costa

This Patch include kinetis_k64_uart.c/.h and Makefile.objs
uart means Universal Asynchronous Receiver/Transmitter (UART)
More information about this peripheral can be found at:
pag 1529, K64P144M120SF5RM.pdf.

Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
---
 hw/char/Makefile.objs              |   1 +
 hw/char/kinetis_k64_uart.c         | 343 +++++++++++++++++++++++++++++++++++++
 include/hw/char/kinetis_k64_uart.h |  79 +++++++++
 3 files changed, 423 insertions(+)
 create mode 100644 hw/char/kinetis_k64_uart.c
 create mode 100644 include/hw/char/kinetis_k64_uart.h

diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 1bcd37e..75b194c 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -31,3 +31,4 @@ common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o
 
 obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
 obj-$(CONFIG_TERMINAL3270) += terminal3270.o
+obj-$(CONFIG_KINETIS_K64) += kinetis_k64_uart.o
diff --git a/hw/char/kinetis_k64_uart.c b/hw/char/kinetis_k64_uart.c
new file mode 100644
index 0000000..0eb3dea
--- /dev/null
+++ b/hw/char/kinetis_k64_uart.c
@@ -0,0 +1,343 @@
+/*
+ * Kinetis K64 peripheral microcontroller emulation.
+ *
+ * Copyright (c) 2017 Advantech Wireless
+ * Written by Gabriel Costa <gabriel291075@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qemu/log.h"
+#include "hw/char/kinetis_k64_uart.h"
+
+static const VMStateDescription vmstate_kinetis_k64_uart = {
+    .name = TYPE_KINETIS_K64_UART,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(BDH, kinetis_k64_uart_state),
+        VMSTATE_UINT8(BDL, kinetis_k64_uart_state),
+        VMSTATE_UINT8(C1, kinetis_k64_uart_state),
+        VMSTATE_UINT8(C2, kinetis_k64_uart_state),
+        VMSTATE_UINT8(S1, kinetis_k64_uart_state),
+        VMSTATE_UINT8(S2, kinetis_k64_uart_state),
+        VMSTATE_UINT8(C3, kinetis_k64_uart_state),
+        VMSTATE_UINT8(D, kinetis_k64_uart_state),
+        VMSTATE_UINT8(MA1, kinetis_k64_uart_state),
+        VMSTATE_UINT8(MA2, kinetis_k64_uart_state),
+        VMSTATE_UINT8(C4, kinetis_k64_uart_state),
+        VMSTATE_UINT8(C5, kinetis_k64_uart_state),
+        VMSTATE_UINT8(ED, kinetis_k64_uart_state),
+        VMSTATE_UINT8(MODEM, kinetis_k64_uart_state),
+        VMSTATE_UINT8(IR, kinetis_k64_uart_state),
+        VMSTATE_UINT8(PFIFO, kinetis_k64_uart_state),
+        VMSTATE_UINT8(CFIFO, kinetis_k64_uart_state),
+        VMSTATE_UINT8(SFIFO, kinetis_k64_uart_state),
+        VMSTATE_UINT8(TWFIFO, kinetis_k64_uart_state),
+        VMSTATE_UINT8(TCFIFO, kinetis_k64_uart_state),
+        VMSTATE_UINT8(RWFIFO, kinetis_k64_uart_state),
+        VMSTATE_UINT8(RCFIFO, kinetis_k64_uart_state),
+        VMSTATE_UINT8(C7816, kinetis_k64_uart_state),
+        VMSTATE_UINT8(IE7816, kinetis_k64_uart_state),
+        VMSTATE_UINT8(IS7816, kinetis_k64_uart_state),
+        VMSTATE_UINT8(WP7816Tx, kinetis_k64_uart_state),
+        VMSTATE_UINT8(WN7816, kinetis_k64_uart_state),
+        VMSTATE_UINT8(WF7816, kinetis_k64_uart_state),
+        VMSTATE_UINT8(ET7816, kinetis_k64_uart_state),
+        VMSTATE_UINT8(TL7816, kinetis_k64_uart_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void kinetis_k64_uart_reset(DeviceState *dev)
+{
+    kinetis_k64_uart_state *s = KINETIS_K64_UART(dev);
+
+    s->BDH = 0x00;
+    s->BDL = 0x04;
+    s->C1 = 0x00;
+    s->C2 = 0x00;
+    s->S1 = 0xC0;
+    s->S2 = 0x00;
+    s->C3 = 0x00;
+    s->D = 0x00;
+    s->MA1 = 0x00;
+    s->MA2 = 0x00;
+    s->C4 = 0x00;
+    s->C5 = 0x00;
+    s->ED = 0x00;
+    s->MODEM = 0x00;
+    s->IR = 0x00;
+    s->PFIFO = 0x00;
+    s->CFIFO = 0x00;
+    s->SFIFO = 0xC0;
+    s->TWFIFO = 0x00;
+    s->TCFIFO = 0x00;
+    s->RWFIFO = 0x01;
+    s->RCFIFO = 0x00;
+    s->C7816 = 0x00;
+    s->IE7816 = 0x00;
+    s->IS7816 = 0x00;
+    s->WP7816Tx = 0x0A;
+    s->WN7816 = 0x00;
+    s->WF7816 = 0x01;
+    s->ET7816 = 0x00;
+    s->TL7816 = 0x00;
+
+    qemu_set_irq(s->irq, 0);
+}
+
+static void kinetis_k64_uart_write(void *opaque, hwaddr offset, uint64_t value,
+        unsigned size)
+{
+    kinetis_k64_uart_state *s = (kinetis_k64_uart_state *)opaque;
+
+    value &= 0xFF;
+
+    switch (offset) {
+    case 0x00:
+        s->BDH = value;
+        break;
+    case 0x01:
+        s->BDL = value;
+        break;
+    case 0x02:
+        s->C1 = value;
+        break;
+    case 0x03:
+        s->C2 = value;
+        break;
+    case 0x05:
+        s->S2 = value;
+        break;
+    case 0x06:
+        s->C3 = value;
+        break;
+    case 0x07:
+        s->D = value;
+        qemu_chr_fe_write_all(&s->chr, &s->D, 1);
+        break;
+    case 0x08:
+        s->MA1 = value;
+        break;
+    case 0x09:
+        s->MA2 = value;
+        break;
+    case 0x0A:
+        s->C4 = value;
+        break;
+    case 0x0B:
+        s->C5 = value;
+        break;
+    case 0x0D:
+        s->MODEM = value;
+        break;
+    case 0x0E:
+        s->IR = value;
+        break;
+    case 0x10:
+        s->PFIFO = value;
+        break;
+    case 0x11:
+        s->CFIFO = value;
+        break;
+    case 0x12:
+        s->SFIFO = value;
+        break;
+    case 0x13:
+        s->TWFIFO = value;
+        break;
+    case 0x15:
+        s->RWFIFO = value;
+        break;
+    case 0x18:
+        s->C7816 = value;
+        break;
+    case 0x19:
+        s->IE7816 = value;
+        break;
+    case 0x1A:
+        s->IS7816 = value;
+        break;
+    case 0x1B:
+        s->WP7816Tx = value;
+        break;
+    case 0x1C:
+        s->WN7816 = value;
+        break;
+    case 0x1D:
+        s->WF7816 = value;
+        break;
+    case 0x1E:
+        s->ET7816 = value;
+        break;
+    case 0x1F:
+        s->TL7816 = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "kinetis_k64_uart: write at bad offset %"HWADDR_PRIx"\n", offset);
+    }
+}
+
+static uint64_t kinetis_k64_uart_read(void *opaque, hwaddr offset,
+        unsigned size)
+{
+    kinetis_k64_uart_state *s = (kinetis_k64_uart_state *)opaque;
+
+    switch (offset) {
+    case 0x00:
+        return s->BDH;
+    case 0x01:
+        return s->BDL;
+    case 0x02:
+        return s->C1;
+    case 0x03:
+        return s->C2;
+    case 0x04:
+        return s->S1;
+    case 0x05:
+        return s->S2;
+    case 0x06:
+        return s->C3;
+    case 0x07:
+        s->RCFIFO = 0;
+        qemu_chr_fe_accept_input(&s->chr);
+        return s->D;
+    case 0x08:
+        return s->MA1;
+    case 0x09:
+        return s->MA2;
+    case 0x0A:
+        return s->C4;
+    case 0x0B:
+        return s->C5;
+    case 0x0C:
+        return s->ED;
+    case 0x0D:
+        return s->MODEM;
+    case 0x0E:
+        return s->IR;
+    case 0x10:
+        return s->PFIFO;
+    case 0x11:
+        return s->CFIFO;
+    case 0x12:
+        return s->SFIFO;
+    case 0x13:
+        return s->TWFIFO;
+    case 0x14:
+        return s->TCFIFO;
+    case 0x15:
+        return s->RWFIFO;
+    case 0x16:
+        return s->RCFIFO;
+    case 0x18:
+        return s->C7816;
+    case 0x19:
+        return s->IE7816;
+    case 0x1A:
+        return s->IS7816;
+    case 0x1B:
+        return s->WP7816Tx;
+    case 0x1C:
+        return s->WN7816;
+    case 0x1D:
+        return s->WF7816;
+    case 0x1E:
+        return s->ET7816;
+    case 0x1F:
+        return s->TL7816;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "kinetis_k64_uart: read at bad offset %"HWADDR_PRIx"\n", offset);
+        return 0;
+    }
+}
+
+static const MemoryRegionOps kinetis_k64_uart_ops = {
+    .read = kinetis_k64_uart_read,
+    .write = kinetis_k64_uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+};
+
+static int kinetis_k64_uart_can_receive(void *opaque)
+{
+    kinetis_k64_uart_state *s = (kinetis_k64_uart_state *)opaque;
+
+    if (s->RCFIFO == 0) {
+        return 1; /*Can read a byte*/
+    } else {
+        return 0; /*Cannot read a byte*/
+    }
+}
+
+static void kinetis_k64_uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+    kinetis_k64_uart_state *s = (kinetis_k64_uart_state *)opaque;
+
+    if (size > 0) {
+        if (buf != NULL) {
+            s->D = buf[0];
+            s->RCFIFO = 1;
+        }
+    }
+}
+
+static void kinetis_k64_uart_realize(DeviceState *dev, Error **errp)
+{
+    kinetis_k64_uart_state *s = KINETIS_K64_UART(dev);
+
+    qemu_chr_fe_set_handlers(&s->chr, kinetis_k64_uart_can_receive,
+                             kinetis_k64_uart_receive, NULL, NULL,
+                             s, NULL, true);
+}
+
+static Property kinetis_k64_uart_properties[] = {
+    DEFINE_PROP_CHR("chardev", kinetis_k64_uart_state, chr),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void kinetis_k64_uart_init(Object *obj)
+{
+    kinetis_k64_uart_state *s = KINETIS_K64_UART(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init_io(&s->iomem, obj, &kinetis_k64_uart_ops, s,
+            TYPE_KINETIS_K64_UART, 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+}
+
+static void kinetis_k64_uart_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_kinetis_k64_uart;
+    dc->reset = kinetis_k64_uart_reset;
+    dc->desc = "Kinetis K64 series UART";
+    dc->hotpluggable = false;
+    dc->props = kinetis_k64_uart_properties;
+    dc->realize = kinetis_k64_uart_realize;
+}
+
+static const TypeInfo kinetis_k64_uart_info = {
+    .name          = TYPE_KINETIS_K64_UART,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(kinetis_k64_uart_state),
+    .instance_init = kinetis_k64_uart_init,
+    .class_init    = kinetis_k64_uart_class_init,
+};
+
+static void kinetis_k64_uart_register_types(void)
+{
+    type_register_static(&kinetis_k64_uart_info);
+}
+
+type_init(kinetis_k64_uart_register_types)
diff --git a/include/hw/char/kinetis_k64_uart.h b/include/hw/char/kinetis_k64_uart.h
new file mode 100644
index 0000000..5b57d0d
--- /dev/null
+++ b/include/hw/char/kinetis_k64_uart.h
@@ -0,0 +1,79 @@
+/*
+ * Kinetis K64 peripheral microcontroller emulation.
+ *
+ * Copyright (c) 2017 Advantech Wireless
+ * Written by Gabriel Costa <gabriel291075@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+#ifndef KINETIS_UART_H
+#define KINETIS_UART_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "hw/hw.h"
+
+#define TYPE_KINETIS_K64_UART "kinetis_k64_uart"
+#define KINETIS_K64_UART(obj) \
+    OBJECT_CHECK(kinetis_k64_uart_state, (obj), TYPE_KINETIS_K64_UART)
+
+typedef struct {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+
+    uint8_t BDH;
+    uint8_t BDL;
+    uint8_t C1;
+    uint8_t C2;
+    uint8_t S1;
+    uint8_t S2;
+    uint8_t C3;
+    uint8_t D;
+    uint8_t MA1;
+    uint8_t MA2;
+    uint8_t C4;
+    uint8_t C5;
+    uint8_t ED;
+    uint8_t MODEM;
+    uint8_t IR;
+    uint8_t PFIFO;
+    uint8_t CFIFO;
+    uint8_t SFIFO;
+    uint8_t TWFIFO;
+    uint8_t TCFIFO;
+    uint8_t RWFIFO;
+    uint8_t RCFIFO;
+    uint8_t C7816;
+    uint8_t IE7816;
+    uint8_t IS7816;
+    uint8_t WP7816Tx;
+    uint8_t WN7816;
+    uint8_t WF7816;
+    uint8_t ET7816;
+    uint8_t TL7816;
+
+    qemu_irq irq;
+    CharBackend chr;
+} kinetis_k64_uart_state;
+
+static inline DeviceState *kinetis_k64_uart_create(hwaddr addr, qemu_irq irq,
+        Chardev *chr)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, TYPE_KINETIS_K64_UART);
+    qdev_prop_set_chr(dev, "chardev", chr);
+    qdev_init_nofail(dev);
+    s = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(s, 0, addr);
+    sysbus_connect_irq(s, 0, irq);
+
+    return dev;
+}
+
+#endif
-- 
2.1.4

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

* [Qemu-devel]  [PATCH v7 2/5] arm: kinetis_k64_mcg
  2017-10-27 12:24 [Qemu-devel] [PATCH v7 0/5] arm: kinetis_mk64fn1m0 machine Gabriel Costa
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 1/5] arm: kinetis_k64_uart Gabriel Costa
@ 2017-10-27 12:24 ` Gabriel Costa
  2017-11-21 14:38   ` Peter Maydell
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 4/5] arm: kinetis_k64_system Gabriel Costa
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Gabriel Costa @ 2017-10-27 12:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, peter.maydell, f4bug, Gabriel Augusto Costa

This Patch include kinetis_k64_mcg.c/.h
mcg means Multipurpose Clock Generator (MCG)
More information about this peripheral can be found at:
pag 579, K64P144M120SF5RM.pdf.

Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
---
 hw/misc/kinetis_k64_mcg.c         | 208 ++++++++++++++++++++++++++++++++++++++
 include/hw/misc/kinetis_k64_mcg.h |  43 ++++++++
 2 files changed, 251 insertions(+)
 create mode 100644 hw/misc/kinetis_k64_mcg.c
 create mode 100644 include/hw/misc/kinetis_k64_mcg.h

diff --git a/hw/misc/kinetis_k64_mcg.c b/hw/misc/kinetis_k64_mcg.c
new file mode 100644
index 0000000..37f4201
--- /dev/null
+++ b/hw/misc/kinetis_k64_mcg.c
@@ -0,0 +1,208 @@
+/*
+ * Kinetis K64 peripheral microcontroller emulation.
+ *
+ * Copyright (c) 2017 Advantech Wireless
+ * Written by Gabriel Costa <gabriel291075@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qemu/log.h"
+#include "hw/misc/kinetis_k64_mcg.h"
+
+static const VMStateDescription vmstate_kinetis_k64_mcg = {
+    .name = TYPE_KINETIS_K64_MCG,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(C1, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(C2, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(C3, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(C4, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(C5, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(C6, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(S, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(SC, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(ATCVH, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(ATCVL, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(C7, kinetis_k64_mcg_state),
+        VMSTATE_UINT8(C8, kinetis_k64_mcg_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void kinetis_k64_mcg_reset(DeviceState *dev)
+{
+    kinetis_k64_mcg_state *s = KINETIS_K64_MCG(dev);
+
+    s->C1 = 0x04;
+    s->C2 = 0x80;
+    s->C3 = 0x00;
+    s->C4 = 0x00;
+    s->C5 = 0x00;
+    s->C6 = 0x00;
+    s->S = 0x10;
+    s->SC = 0x02;
+    s->ATCVH = 0x00;
+    s->ATCVL = 0x00;
+    s->C7 = 0x00;
+    s->C8 = 0x80;
+}
+
+static void kinetis_k64_mcg_write(void *opaque, hwaddr offset, uint64_t value,
+        unsigned size)
+{
+    kinetis_k64_mcg_state *s = (kinetis_k64_mcg_state *)opaque;
+
+    value &= 0xFF;
+
+    switch (offset) {
+    case 0x00:
+        if (value & 1 << 2) { /*IREFS*/
+            s->S = 0;
+            s->S |= 1 << 3; /*10 Enconding 2 - External ref clk is selected*/
+        }
+        if ((s->C1 & 0x80) && (value >> 6 == 0)) {
+            s->S |= 1 << 2; /*11 Enconding 3 - Output of the PLL is selected*/
+        }
+        s->C1 = value;
+        break;
+    case 0x01:
+        s->C2 = value;
+        break;
+    case 0x02:
+        s->C3 = value;
+        break;
+    case 0x03:
+        s->C4 = value;
+        break;
+    case 0x04:
+        s->C5 = value;
+        if (s->C5 & 1 << 6) { /*PLLCLKEN0*/
+            s->S |= 1 << 6;  /*LOCK0*/
+        }
+        break;
+    case 0x05:
+        s->C6 = value;
+        if (s->C6 & 1 << 6) { /*PLLS*/
+            s->S |= 1 << 5;  /*PLLST*/
+        }
+        break;
+    case 0x06:
+        s->S = value;
+        break;
+    case 0x08:
+        s->SC = value;
+        break;
+    case 0x0A:
+        s->ATCVH = value;
+        break;
+    case 0x0B:
+        s->ATCVL = value;
+        break;
+    case 0x0C:
+        s->C7 = value;
+        break;
+    case 0x0D:
+        s->C8 = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "kinetis_k64_mcg: write at bad offset %"HWADDR_PRIx"\n", offset);
+    }
+}
+
+static uint64_t kinetis_k64_mcg_read(void *opaque, hwaddr offset, unsigned size)
+{
+    kinetis_k64_mcg_state *s = (kinetis_k64_mcg_state *)opaque;
+    uint8_t value;
+
+    switch (offset) {
+    case 0x00:
+        value = s->C1;
+        break;
+    case 0x01:
+        value = s->C2;
+        break;
+    case 0x02:
+        value = s->C3;
+        break;
+    case 0x03:
+        value = s->C4;
+        break;
+    case 0x04:
+        value = s->C5;
+        break;
+    case 0x05:
+        value = s->C6;
+        break;
+    case 0x06:
+        value = s->S;
+        break;
+    case 0x08:
+        value = s->SC;
+        break;
+    case 0x0A:
+        value = s->ATCVH;
+        break;
+    case 0x0B:
+        value = s->ATCVL;
+        break;
+    case 0x0C:
+        value = s->C7;
+        break;
+    case 0x0D:
+        value = s->C8;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "kinetis_k64_mcg: read at bad offset %"HWADDR_PRIx"\n", offset);
+        return 0;
+    }
+    return value;
+}
+
+static const MemoryRegionOps kinetis_k64_mcg_ops = {
+    .read = kinetis_k64_mcg_read,
+    .write = kinetis_k64_mcg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void kinetis_k64_mcg_init(Object *obj)
+{
+    kinetis_k64_mcg_state *s = KINETIS_K64_MCG(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init_io(&s->iomem, obj, &kinetis_k64_mcg_ops, s,
+            TYPE_KINETIS_K64_MCG, 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+}
+
+static void kinetis_k64_mcg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_kinetis_k64_mcg;
+    dc->reset = kinetis_k64_mcg_reset;
+    dc->desc = "Kinetis K64 series MCG";
+}
+
+static const TypeInfo kinetis_k64_mcg_info = {
+    .name          = TYPE_KINETIS_K64_MCG,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(kinetis_k64_mcg_state),
+    .instance_init = kinetis_k64_mcg_init,
+    .class_init    = kinetis_k64_mcg_class_init,
+};
+
+static void kinetis_k64_mcg_register_types(void)
+{
+    type_register_static(&kinetis_k64_mcg_info);
+}
+
+type_init(kinetis_k64_mcg_register_types)
diff --git a/include/hw/misc/kinetis_k64_mcg.h b/include/hw/misc/kinetis_k64_mcg.h
new file mode 100644
index 0000000..3f105c5
--- /dev/null
+++ b/include/hw/misc/kinetis_k64_mcg.h
@@ -0,0 +1,43 @@
+/*
+ * Kinetis K64 peripheral microcontroller emulation.
+ *
+ * Copyright (c) 2017 Advantech Wireless
+ * Written by Gabriel Costa <gabriel291075@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+#ifndef KINETIS_MCG_H
+#define KINETIS_MCG_H
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+
+#define TYPE_KINETIS_K64_MCG "kinetis_k64_mcg"
+#define KINETIS_K64_MCG(obj) \
+    OBJECT_CHECK(kinetis_k64_mcg_state, (obj), TYPE_KINETIS_K64_MCG)
+
+typedef struct {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+
+    uint8_t C1;
+    uint8_t C2;
+    uint8_t C3;
+    uint8_t C4;
+    uint8_t C5;
+    uint8_t C6;
+    uint8_t S;
+    uint8_t SC;
+    uint8_t ATCVH;
+    uint8_t ATCVL;
+    uint8_t C7;
+    uint8_t C8;
+
+    qemu_irq irq;
+} kinetis_k64_mcg_state;
+
+#endif
-- 
2.1.4

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

* [Qemu-devel]  [PATCH v7 4/5] arm: kinetis_k64_system
  2017-10-27 12:24 [Qemu-devel] [PATCH v7 0/5] arm: kinetis_mk64fn1m0 machine Gabriel Costa
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 1/5] arm: kinetis_k64_uart Gabriel Costa
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 2/5] arm: kinetis_k64_mcg Gabriel Costa
@ 2017-10-27 12:24 ` Gabriel Costa
  2017-11-21 14:55   ` Peter Maydell
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 5/5] arm: kinetis_mk64fn1m0 machine Gabriel Costa
       [not found] ` <1509107055-21978-4-git-send-email-costa@advantech.ca>
  4 siblings, 1 reply; 10+ messages in thread
From: Gabriel Costa @ 2017-10-27 12:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, peter.maydell, f4bug, Gabriel Augusto Costa

This Patch include kinetis_k64_system.c/.h and Makefile.objs
sim means System Integration Module (SIM)
More information about this peripheral can be found at:
pag 291, K64P144M120SF5RM.pdf.

Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
---
 hw/misc/Makefile.objs                |   3 +
 hw/misc/kinetis_k64_system.c         | 274 +++++++++++++++++++++++++++++++++++
 include/hw/misc/kinetis_k64_system.h |  52 +++++++
 3 files changed, 329 insertions(+)
 create mode 100644 hw/misc/kinetis_k64_system.c
 create mode 100644 include/hw/misc/kinetis_k64_system.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 19202d9..c5c8589 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -61,3 +61,6 @@ obj-$(CONFIG_AUX) += auxbus.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
 obj-y += mmio_interface.o
 obj-$(CONFIG_MSF2) += msf2-sysreg.o
+obj-$(CONFIG_KINETIS_K64) += kinetis_k64_mcg.o
+obj-$(CONFIG_KINETIS_K64) += kinetis_k64_pmux.o
+obj-$(CONFIG_KINETIS_K64) += kinetis_k64_system.o
diff --git a/hw/misc/kinetis_k64_system.c b/hw/misc/kinetis_k64_system.c
new file mode 100644
index 0000000..e547fe8
--- /dev/null
+++ b/hw/misc/kinetis_k64_system.c
@@ -0,0 +1,274 @@
+/*
+ * Kinetis K64 peripheral microcontroller emulation.
+ *
+ * Copyright (c) 2017 Advantech Wireless
+ * Written by Gabriel Costa <gabriel291075@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qemu/log.h"
+#include "hw/misc/kinetis_k64_system.h"
+
+static const VMStateDescription vmstate_kinetis_k64_sim = {
+    .name = TYPE_KINETIS_K64_SIM,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(SOPT1, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SOPT1CFG, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SOPT2, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SOPT4, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SOPT5, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SOPT7, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SDID, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SCGC1, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SCGC2, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SCGC3, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SCGC4, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SCGC5, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SCGC6, kinetis_k64_sim_state),
+        VMSTATE_UINT32(SCGC7, kinetis_k64_sim_state),
+        VMSTATE_UINT32(CLKDIV1, kinetis_k64_sim_state),
+        VMSTATE_UINT32(CLKDIV2, kinetis_k64_sim_state),
+        VMSTATE_UINT32(FCFG1, kinetis_k64_sim_state),
+        VMSTATE_UINT32(FCFG2, kinetis_k64_sim_state),
+        VMSTATE_UINT32(UIDH, kinetis_k64_sim_state),
+        VMSTATE_UINT32(UIDMH, kinetis_k64_sim_state),
+        VMSTATE_UINT32(UIDML, kinetis_k64_sim_state),
+        VMSTATE_UINT32(UIDL, kinetis_k64_sim_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void kinetis_k64_sim_reset(DeviceState *dev)
+{
+    kinetis_k64_sim_state *s = KINETIS_K64_SIM(dev);
+
+    s->SOPT1 = 0x00008000;
+    s->SOPT1CFG = 0x00000000;
+    s->SOPT2 = 0x00001000;
+    s->SOPT4 = 0x00000000;
+    s->SOPT5 = 0x00000000;
+    s->SOPT7 = 0x00000000;
+    s->SDID = 0x00000000;
+    s->SCGC1 = 0x00000000;
+    s->SCGC2 = 0x00000000;
+    s->SCGC3 = 0x00000000;
+    s->SCGC4 = 0xF0100030;
+    s->SCGC5 = 0x00040182;
+    s->SCGC6 = 0x40000001;
+    s->SCGC7 = 0x00000006;
+    s->CLKDIV1 = 0x00000000;
+    s->CLKDIV2 = 0x00000000;
+    s->FCFG1 = 0xFF000000;
+    s->FCFG2 = 0x00000000;
+    s->UIDH = 0x00000000;
+    s->UIDMH = 0x00000000;
+    s->UIDML = 0x00000000;
+    s->UIDL = 0x00000000;
+}
+
+static void kinetis_k64_sim_write(void *opaque, hwaddr offset, uint64_t value,
+        unsigned size)
+{
+    kinetis_k64_sim_state *s = (kinetis_k64_sim_state *)opaque;
+
+    value &= 0xFFFFFFFF;
+
+    switch (offset) {
+    case 0x0000:
+        s->SOPT1 = value;
+        break;
+    case 0x0004:
+        s->SOPT1CFG = value;
+        break;
+    case 0x1004:
+        s->SOPT2 = value;
+        break;
+    case 0x100C:
+        s->SOPT4 = value;
+        break;
+    case 0x1010:
+        s->SOPT5 = value;
+        break;
+    case 0x1018:
+        s->SOPT7 = value;
+        break;
+    case 0x1024:
+        s->SDID = value;
+        break;
+    case 0x1028:
+        s->SCGC1 = value;
+        break;
+    case 0x102C:
+        s->SCGC2 = value;
+        break;
+    case 0x1030:
+        s->SCGC3 = value;
+        break;
+    case 0x1034:
+        s->SCGC4 = value;
+        break;
+    case 0x1013:
+        s->SCGC5 = value;
+        break;
+    case 0x103C:
+        s->SCGC6 = value;
+        break;
+    case 0x1040:
+        s->SCGC7 = value;
+        break;
+    case 0x1044:
+        s->CLKDIV1 = value;
+        break;
+    case 0x1048:
+        s->CLKDIV2 = value;
+        break;
+    case 0x104C:
+        s->FCFG1 = value;
+        break;
+    case 0x1050:
+        s->FCFG2 = value;
+        break;
+    case 0x1054:
+        s->UIDH = value;
+        break;
+    case 0x1058:
+        s->UIDMH = value;
+        break;
+    case 0x105C:
+        s->UIDML = value;
+        break;
+    case 0x1060:
+        s->UIDL = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "kinetis_k64_sim: write at bad offset %"HWADDR_PRIx"\n", offset);
+    }
+}
+
+static uint64_t kinetis_k64_sim_read(void *opaque, hwaddr offset, unsigned size)
+{
+    kinetis_k64_sim_state *s = (kinetis_k64_sim_state *)opaque;
+    uint32_t value;
+
+    switch (offset) {
+    case 0x0000:
+        value = s->SOPT1;
+        break;
+    case 0x0004:
+        value = s->SOPT1CFG;
+        break;
+    case 0x1004:
+        value = s->SOPT2;
+        break;
+    case 0x100C:
+        value = s->SOPT4;
+        break;
+    case 0x1010:
+        value = s->SOPT5;
+        break;
+    case 0x1018:
+        value = s->SOPT7;
+        break;
+    case 0x1024:
+        value = s->SDID;
+        break;
+    case 0x1028:
+        value = s->SCGC1;
+        break;
+    case 0x102C:
+        value = s->SCGC2;
+        break;
+    case 0x1030:
+        value = s->SCGC3;
+        break;
+    case 0x1034:
+        value = s->SCGC4;
+        break;
+    case 0x1013:
+        value = s->SCGC5;
+        break;
+    case 0x103C:
+        value = s->SCGC6;
+        break;
+    case 0x1040:
+        value = s->SCGC7;
+        break;
+    case 0x1044:
+        value = s->CLKDIV1;
+        break;
+    case 0x1048:
+        value = s->CLKDIV2;
+        break;
+    case 0x104C:
+        value = s->FCFG1;
+        break;
+    case 0x1050:
+        value = s->FCFG2;
+        break;
+    case 0x1054:
+        value = s->UIDH;
+        break;
+    case 0x1058:
+        value = s->UIDMH;
+        break;
+    case 0x105C:
+        value = s->UIDML;
+        break;
+    case 0x1060:
+        value = s->UIDL;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "kinetis_k64_sim: read at bad offset %"HWADDR_PRIx"\n", offset);
+        return 0;
+    }
+    return value;
+}
+
+static const MemoryRegionOps kinetis_k64_sim_ops = {
+    .read = kinetis_k64_sim_read,
+    .write = kinetis_k64_sim_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void kinetis_k64_sim_init(Object *obj)
+{
+    kinetis_k64_sim_state *s = KINETIS_K64_SIM(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init_io(&s->iomem, obj, &kinetis_k64_sim_ops, s,
+            TYPE_KINETIS_K64_SIM, 0x2000);
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void kinetis_k64_sim_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_kinetis_k64_sim;
+    dc->reset = kinetis_k64_sim_reset;
+    dc->desc = "Kinetis K64 series SIM";
+}
+
+static const TypeInfo kinetis_k64_sim_info = {
+    .name          = TYPE_KINETIS_K64_SIM,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(kinetis_k64_sim_state),
+    .instance_init = kinetis_k64_sim_init,
+    .class_init    = kinetis_k64_sim_class_init,
+};
+
+static void kinetis_k64_sim_register_types(void)
+{
+    type_register_static(&kinetis_k64_sim_info);
+}
+
+type_init(kinetis_k64_sim_register_types)
diff --git a/include/hw/misc/kinetis_k64_system.h b/include/hw/misc/kinetis_k64_system.h
new file mode 100644
index 0000000..8774eaa
--- /dev/null
+++ b/include/hw/misc/kinetis_k64_system.h
@@ -0,0 +1,52 @@
+/*
+ * Kinetis K64 peripheral microcontroller emulation.
+ *
+ * Copyright (c) 2017 Advantech Wireless
+ * Written by Gabriel Costa <gabriel291075@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+#ifndef KINETIS_SYSTEM_H
+#define KINETIS_SYSTEM_H
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+
+#define TYPE_KINETIS_K64_SIM "kinetis_k64_sim"
+#define KINETIS_K64_SIM(obj) \
+    OBJECT_CHECK(kinetis_k64_sim_state, (obj), TYPE_KINETIS_K64_SIM)
+
+typedef struct {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+
+    uint32_t SOPT1;
+    uint32_t SOPT1CFG;
+    uint32_t SOPT2;
+    uint32_t SOPT4;
+    uint32_t SOPT5;
+    uint32_t SOPT7;
+    uint32_t SDID;
+    uint32_t SCGC1;
+    uint32_t SCGC2;
+    uint32_t SCGC3;
+    uint32_t SCGC4;
+    uint32_t SCGC5;
+    uint32_t SCGC6;
+    uint32_t SCGC7;
+    uint32_t CLKDIV1;
+    uint32_t CLKDIV2;
+    uint32_t FCFG1;
+    uint32_t FCFG2;
+    uint32_t UIDH;
+    uint32_t UIDMH;
+    uint32_t UIDML;
+    uint32_t UIDL;
+
+} kinetis_k64_sim_state;
+
+#endif
-- 
2.1.4

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

* [Qemu-devel]  [PATCH v7 5/5] arm: kinetis_mk64fn1m0 machine
  2017-10-27 12:24 [Qemu-devel] [PATCH v7 0/5] arm: kinetis_mk64fn1m0 machine Gabriel Costa
                   ` (2 preceding siblings ...)
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 4/5] arm: kinetis_k64_system Gabriel Costa
@ 2017-10-27 12:24 ` Gabriel Costa
  2017-11-21 15:02   ` Peter Maydell
       [not found] ` <1509107055-21978-4-git-send-email-costa@advantech.ca>
  4 siblings, 1 reply; 10+ messages in thread
From: Gabriel Costa @ 2017-10-27 12:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-arm, peter.maydell, f4bug, Gabriel Augusto Costa

This Patch include mk64fn1m0.c that describe the kinetis k64 machine and
some peripherals.
Also, include changes in Makefile.objs and arm-softmmu.mak to compile
this machine.

Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
---
 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Makefile.objs            |   1 +
 hw/arm/mk64fn1m0.c              | 136 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 138 insertions(+)
 create mode 100644 hw/arm/mk64fn1m0.c

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 5059d13..a835d4f 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -130,3 +130,4 @@ CONFIG_SMBIOS=y
 CONFIG_ASPEED_SOC=y
 CONFIG_GPIO_KEY=y
 CONFIG_MSF2=y
+CONFIG_KINETIS_K64=y
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2794e08..874a38a 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -20,3 +20,4 @@ obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
 obj-$(CONFIG_MPS2) += mps2.o
 obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
+obj-$(CONFIG_KINETIS_K64) += mk64fn1m0.o
diff --git a/hw/arm/mk64fn1m0.c b/hw/arm/mk64fn1m0.c
new file mode 100644
index 0000000..618791c
--- /dev/null
+++ b/hw/arm/mk64fn1m0.c
@@ -0,0 +1,136 @@
+/*
+ * Kinetis K64 MK64FN1M0 microcontroller emulation.
+ *
+ * Copyright (c) 2017 Advantech Wireless
+ * Written by Gabriel Costa <gabriel291075@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 or
+ *  (at your option) any later version.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "hw/ssi/ssi.h"
+#include "hw/arm/arm.h"
+#include "hw/devices.h"
+#include "qemu/timer.h"
+#include "hw/i2c/i2c.h"
+#include "net/net.h"
+#include "hw/boards.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/char/pl011.h"
+#include "hw/misc/unimp.h"
+#include "cpu.h"
+#include "hw/char/kinetis_k64_uart.h"
+#include "hw/misc/kinetis_k64_system.h"
+#include "hw/misc/kinetis_k64_mcg.h"
+#include "hw/misc/kinetis_k64_pmux.h"
+
+#define FLASH_SIZE              (1024 * 1024)
+#define FLASH_BASE_ADDRESS      (0x00000000)
+#define SRAM_SIZE               (192 * 1024)
+#define SRAM_BASE_ADDRESS       (0x20000000)
+
+#define NUM_IRQ_LINES 85
+
+/* System controller.  */
+
+static void do_sys_reset(void *opaque, int n, int level)
+{
+    if (level) {
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+    }
+}
+
+/* Interruptions at pag.77 of K64P144M120F5RM.pdf */
+
+static void mk64fn1m0_init_mach(MachineState *ms, const char *kernel_filename)
+{
+    DeviceState *nvic;
+
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+
+    memory_region_init_ram(flash, NULL, "k64.flash", FLASH_SIZE, &error_fatal);
+    memory_region_set_readonly(flash, true);
+    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
+    memory_region_init_ram(sram, NULL, "k64.sram", SRAM_SIZE, &error_fatal);
+    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
+    nvic = armv7m_init(system_memory, FLASH_SIZE, NUM_IRQ_LINES,
+            ms->kernel_filename, ms->cpu_type);
+    qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0,
+            qemu_allocate_irq(&do_sys_reset, NULL, 0));
+
+    sysbus_create_simple(TYPE_KINETIS_K64_SIM, 0x40048000, NULL);
+    sysbus_create_simple(TYPE_KINETIS_K64_MCG, 0x40064000, NULL);
+    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x40049000,
+            qdev_get_gpio_in(nvic, 59));
+    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x4004A000,
+            qdev_get_gpio_in(nvic, 60));
+    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x4004B000,
+            qdev_get_gpio_in(nvic, 61));
+    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x4004C000,
+            qdev_get_gpio_in(nvic, 62));
+    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x4004D000,
+            qdev_get_gpio_in(nvic, 63));
+    create_unimplemented_device("kinetis_k64_spi0",  0x4002C000, 0x1000);
+    create_unimplemented_device("kinetis_k64_spi1",  0x4002D000, 0x1000);
+    create_unimplemented_device("kinetis_k64_adc0",  0x4003B000, 0x1000);
+    create_unimplemented_device("kinetis_k64_dac",   0x4002F000, 0x1000);
+    create_unimplemented_device("kinetis_k64_i2c0",  0x40066000, 0x1000);
+    create_unimplemented_device("kinetis_k64_i2c1",  0x40067000, 0x1000);
+    kinetis_k64_uart_create(0x4006A000, qdev_get_gpio_in(nvic, 31),
+            serial_hds[0]);
+    create_unimplemented_device("kinetis_k64_uart1", 0x4006B000, 0x1000);
+    create_unimplemented_device("kinetis_k64_uart2", 0x4006C000, 0x1000);
+    create_unimplemented_device("kinetis_k64_uart3", 0x4006D000, 0x1000);
+    create_unimplemented_device("kinetis_k64_spi2",  0x400AC000, 0x1000);
+    create_unimplemented_device("kinetis_k64_adc1",  0x400BB000, 0x1000);
+    create_unimplemented_device("kinetis_k64_i2c2",  0x400E6000, 0x1000);
+    create_unimplemented_device("kinetis_k64_uart4", 0x400EA000, 0x1000);
+    create_unimplemented_device("kinetis_k64_uart5", 0x400EB000, 0x1000);
+    create_unimplemented_device("peripheral_brdg_0", 0x40000000, 0x1000);
+    create_unimplemented_device("Crossbar_Switch",   0x40004000, 0x1000);
+    create_unimplemented_device("DMA_Controller",    0x40008000, 0x1000);
+    create_unimplemented_device("DMA_Controller_t",  0x40009000, 0x1000);
+    create_unimplemented_device("FlexBus",           0x4000C000, 0x1000);
+    create_unimplemented_device("MPU",               0x4000D000, 0x1000);
+    create_unimplemented_device("Flash_mem_ctrl",    0x4001F000, 0x1000);
+    create_unimplemented_device("Flash_mem",         0x40020000, 0x1000);
+    create_unimplemented_device("DMA_ch_multiplx",   0x40021000, 0x1000);
+}
+
+static void mk64fn1m0_init(MachineState *machine)
+{
+    const char *kernel_filename = machine->kernel_filename;
+    mk64fn1m0_init_mach(machine, kernel_filename);
+}
+
+static void mk64fn1m0_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "Kinetis K64 MCU (Cortex-M4)";
+    mc->init = mk64fn1m0_init;
+    mc->ignore_memory_transaction_failures = true;
+    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
+    mc->max_cpus = 1;
+}
+
+static const TypeInfo mk64_type = {
+    .name = MACHINE_TYPE_NAME("mk64fn1m0"),
+    .parent = TYPE_MACHINE,
+    .class_init = mk64fn1m0_class_init,
+};
+
+static void mk64fn1m0_machine_init(void)
+{
+    type_register_static(&mk64_type);
+}
+
+type_init(mk64fn1m0_machine_init)
-- 
2.1.4

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

* Re: [Qemu-devel] [PATCH v7 1/5] arm: kinetis_k64_uart
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 1/5] arm: kinetis_k64_uart Gabriel Costa
@ 2017-11-21 14:13   ` Peter Maydell
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2017-11-21 14:13 UTC (permalink / raw)
  To: Gabriel Costa; +Cc: QEMU Developers, qemu-arm, Philippe Mathieu-Daudé

On 27 October 2017 at 13:24, Gabriel Costa <gabriel291075@gmail.com> wrote:

First, an apology for not having got back to this series sooner;
I've been busy with work for the upcoming 2.11 release.

> This Patch include kinetis_k64_uart.c/.h and Makefile.objs
> uart means Universal Asynchronous Receiver/Transmitter (UART)

You don't really need to say either of these things --
the git log --stat info tells people what files the patch
touches, and UART is a very common abbreviation.

"This patch implements the UART found in the Kinetis
K64 SoC family." or something similar will do.

> More information about this peripheral can be found at:
> pag 1529, K64P144M120SF5RM.pdf.

Is there a standard URL for this datasheet? (Google suggests
http://cache.freescale.com/files/microcontrollers/doc/ref_manual/K64P144M120SF5RM.pdf
perhaps?)

If so then you can quote that URL in the header comment at the top of
the file, so that future readers know where to get the datasheet.

My overall impression of this device model is that there's
an awful lot of unimplemented behaviour here. The code as
it stands is doing nothing except very basic send/receive
of characters when the guest uses the data register. The datasheet
says this device has FIFOs, interrupts and so on, but the
model is implementing none of that. We don't expect complete
emulation of all the obscure parts of the device, but I think
that FIFO and interrupt handling at least is pretty fundamental.
Logging (via qemu_log_mask(LOG_UNIMP, ...)) when the guest tries
to do something the model doesn't implement yet would also be
nice.

> Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
> ---
>  hw/char/Makefile.objs              |   1 +
>  hw/char/kinetis_k64_uart.c         | 343 +++++++++++++++++++++++++++++++++++++
>  include/hw/char/kinetis_k64_uart.h |  79 +++++++++
>  3 files changed, 423 insertions(+)
>  create mode 100644 hw/char/kinetis_k64_uart.c
>  create mode 100644 include/hw/char/kinetis_k64_uart.h
>
> diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
> index 1bcd37e..75b194c 100644
> --- a/hw/char/Makefile.objs
> +++ b/hw/char/Makefile.objs
> @@ -31,3 +31,4 @@ common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o
>
>  obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
>  obj-$(CONFIG_TERMINAL3270) += terminal3270.o
> +obj-$(CONFIG_KINETIS_K64) += kinetis_k64_uart.o
> diff --git a/hw/char/kinetis_k64_uart.c b/hw/char/kinetis_k64_uart.c
> new file mode 100644
> index 0000000..0eb3dea
> --- /dev/null
> +++ b/hw/char/kinetis_k64_uart.c
> @@ -0,0 +1,343 @@
> +/*
> + * Kinetis K64 peripheral microcontroller emulation.
> + *
> + * Copyright (c) 2017 Advantech Wireless
> + * Written by Gabriel Costa <gabriel291075@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 or
> + *  (at your option) any later version.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "qemu/log.h"
> +#include "hw/char/kinetis_k64_uart.h"
> +
> +static const VMStateDescription vmstate_kinetis_k64_uart = {
> +    .name = TYPE_KINETIS_K64_UART,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8(BDH, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(BDL, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(C1, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(C2, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(S1, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(S2, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(C3, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(D, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(MA1, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(MA2, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(C4, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(C5, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(ED, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(MODEM, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(IR, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(PFIFO, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(CFIFO, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(SFIFO, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(TWFIFO, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(TCFIFO, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(RWFIFO, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(RCFIFO, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(C7816, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(IE7816, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(IS7816, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(WP7816Tx, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(WN7816, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(WF7816, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(ET7816, kinetis_k64_uart_state),
> +        VMSTATE_UINT8(TL7816, kinetis_k64_uart_state),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void kinetis_k64_uart_reset(DeviceState *dev)
> +{
> +    kinetis_k64_uart_state *s = KINETIS_K64_UART(dev);
> +
> +    s->BDH = 0x00;
> +    s->BDL = 0x04;
> +    s->C1 = 0x00;
> +    s->C2 = 0x00;
> +    s->S1 = 0xC0;
> +    s->S2 = 0x00;
> +    s->C3 = 0x00;
> +    s->D = 0x00;
> +    s->MA1 = 0x00;
> +    s->MA2 = 0x00;
> +    s->C4 = 0x00;
> +    s->C5 = 0x00;
> +    s->ED = 0x00;
> +    s->MODEM = 0x00;
> +    s->IR = 0x00;
> +    s->PFIFO = 0x00;
> +    s->CFIFO = 0x00;
> +    s->SFIFO = 0xC0;
> +    s->TWFIFO = 0x00;
> +    s->TCFIFO = 0x00;
> +    s->RWFIFO = 0x01;
> +    s->RCFIFO = 0x00;
> +    s->C7816 = 0x00;
> +    s->IE7816 = 0x00;
> +    s->IS7816 = 0x00;
> +    s->WP7816Tx = 0x0A;
> +    s->WN7816 = 0x00;
> +    s->WF7816 = 0x01;
> +    s->ET7816 = 0x00;
> +    s->TL7816 = 0x00;
> +
> +    qemu_set_irq(s->irq, 0);
> +}
> +
> +static void kinetis_k64_uart_write(void *opaque, hwaddr offset, uint64_t value,
> +        unsigned size)
> +{
> +    kinetis_k64_uart_state *s = (kinetis_k64_uart_state *)opaque;
> +
> +    value &= 0xFF;
> +
> +    switch (offset) {
> +    case 0x00:
> +        s->BDH = value;
> +        break;
> +    case 0x01:
> +        s->BDL = value;
> +        break;
> +    case 0x02:
> +        s->C1 = value;
> +        break;
> +    case 0x03:
> +        s->C2 = value;
> +        break;
> +    case 0x05:
> +        s->S2 = value;
> +        break;
> +    case 0x06:
> +        s->C3 = value;
> +        break;
> +    case 0x07:
> +        s->D = value;
> +        qemu_chr_fe_write_all(&s->chr, &s->D, 1);

This is a blocking call. Most of our existing UART models are
still written this way, but it's a bit unfortunate as it means that
you can block the whole simulation if the thing on the other end
isn't accepting data.

The modern way to deal with this is to use qemu_chr_fe_write(),
which writes as many characters as it can without blocking,
and then if there's still pending data you can use
qemu_chr_fe_add_watch() to arrange to be called back when
you can try again. (This means you need to implement the
guest-facing FIFO and the status/interrupt bits for "FIFO is
full".) hw/char/cadence_uart.c (which has a FIFO) and
hw/char/cmsdk-apb-uart.c (which does not) are good examples
to look at.

> +        break;
> +    case 0x08:
> +        s->MA1 = value;
> +        break;
> +    case 0x09:
> +        s->MA2 = value;
> +        break;
> +    case 0x0A:
> +        s->C4 = value;
> +        break;
> +    case 0x0B:
> +        s->C5 = value;
> +        break;
> +    case 0x0D:
> +        s->MODEM = value;
> +        break;
> +    case 0x0E:
> +        s->IR = value;
> +        break;
> +    case 0x10:
> +        s->PFIFO = value;
> +        break;
> +    case 0x11:
> +        s->CFIFO = value;
> +        break;
> +    case 0x12:
> +        s->SFIFO = value;
> +        break;
> +    case 0x13:
> +        s->TWFIFO = value;
> +        break;
> +    case 0x15:
> +        s->RWFIFO = value;
> +        break;
> +    case 0x18:
> +        s->C7816 = value;
> +        break;
> +    case 0x19:
> +        s->IE7816 = value;
> +        break;
> +    case 0x1A:
> +        s->IS7816 = value;
> +        break;
> +    case 0x1B:
> +        s->WP7816Tx = value;
> +        break;
> +    case 0x1C:
> +        s->WN7816 = value;
> +        break;
> +    case 0x1D:
> +        s->WF7816 = value;
> +        break;
> +    case 0x1E:
> +        s->ET7816 = value;
> +        break;
> +    case 0x1F:
> +        s->TL7816 = value;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +            "kinetis_k64_uart: write at bad offset %"HWADDR_PRIx"\n", offset);
> +    }
> +}
> +
> +static uint64_t kinetis_k64_uart_read(void *opaque, hwaddr offset,
> +        unsigned size)
> +{
> +    kinetis_k64_uart_state *s = (kinetis_k64_uart_state *)opaque;
> +
> +    switch (offset) {
> +    case 0x00:
> +        return s->BDH;
> +    case 0x01:
> +        return s->BDL;
> +    case 0x02:
> +        return s->C1;
> +    case 0x03:
> +        return s->C2;
> +    case 0x04:
> +        return s->S1;
> +    case 0x05:
> +        return s->S2;
> +    case 0x06:
> +        return s->C3;
> +    case 0x07:
> +        s->RCFIFO = 0;
> +        qemu_chr_fe_accept_input(&s->chr);
> +        return s->D;
> +    case 0x08:
> +        return s->MA1;
> +    case 0x09:
> +        return s->MA2;
> +    case 0x0A:
> +        return s->C4;
> +    case 0x0B:
> +        return s->C5;
> +    case 0x0C:
> +        return s->ED;
> +    case 0x0D:
> +        return s->MODEM;
> +    case 0x0E:
> +        return s->IR;
> +    case 0x10:
> +        return s->PFIFO;
> +    case 0x11:
> +        return s->CFIFO;
> +    case 0x12:
> +        return s->SFIFO;
> +    case 0x13:
> +        return s->TWFIFO;
> +    case 0x14:
> +        return s->TCFIFO;
> +    case 0x15:
> +        return s->RWFIFO;
> +    case 0x16:
> +        return s->RCFIFO;
> +    case 0x18:
> +        return s->C7816;
> +    case 0x19:
> +        return s->IE7816;
> +    case 0x1A:
> +        return s->IS7816;
> +    case 0x1B:
> +        return s->WP7816Tx;
> +    case 0x1C:
> +        return s->WN7816;
> +    case 0x1D:
> +        return s->WF7816;
> +    case 0x1E:
> +        return s->ET7816;
> +    case 0x1F:
> +        return s->TL7816;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +            "kinetis_k64_uart: read at bad offset %"HWADDR_PRIx"\n", offset);
> +        return 0;
> +    }
> +}
> +
> +static const MemoryRegionOps kinetis_k64_uart_ops = {
> +    .read = kinetis_k64_uart_read,
> +    .write = kinetis_k64_uart_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .valid.min_access_size = 4,
> +    .valid.max_access_size = 4,
> +};
> +
> +static int kinetis_k64_uart_can_receive(void *opaque)
> +{
> +    kinetis_k64_uart_state *s = (kinetis_k64_uart_state *)opaque;
> +
> +    if (s->RCFIFO == 0) {
> +        return 1; /*Can read a byte*/
> +    } else {
> +        return 0; /*Cannot read a byte*/
> +    }

The comments aren't really necessary in my view, but if you
want to keep them, style says there should be spaces after /*
and before */.

> +}
> +
> +static void kinetis_k64_uart_receive(void *opaque, const uint8_t *buf, int size)
> +{
> +    kinetis_k64_uart_state *s = (kinetis_k64_uart_state *)opaque;
> +
> +    if (size > 0) {
> +        if (buf != NULL) {

You don't need to check these -- you can assume your caller
passes a non-NULL buffer and a positive size.

> +            s->D = buf[0];
> +            s->RCFIFO = 1;
> +        }
> +    }
> +}
> +
> +static void kinetis_k64_uart_realize(DeviceState *dev, Error **errp)
> +{
> +    kinetis_k64_uart_state *s = KINETIS_K64_UART(dev);
> +
> +    qemu_chr_fe_set_handlers(&s->chr, kinetis_k64_uart_can_receive,
> +                             kinetis_k64_uart_receive, NULL, NULL,
> +                             s, NULL, true);
> +}
> +
> +static Property kinetis_k64_uart_properties[] = {
> +    DEFINE_PROP_CHR("chardev", kinetis_k64_uart_state, chr),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void kinetis_k64_uart_init(Object *obj)
> +{
> +    kinetis_k64_uart_state *s = KINETIS_K64_UART(obj);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +
> +    memory_region_init_io(&s->iomem, obj, &kinetis_k64_uart_ops, s,
> +            TYPE_KINETIS_K64_UART, 0x1000);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +    sysbus_init_irq(sbd, &s->irq);

You create a single outbound IRQ line here, but the data sheet says
that each UART has two: one for status sources, and one for error sources.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 2/5] arm: kinetis_k64_mcg
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 2/5] arm: kinetis_k64_mcg Gabriel Costa
@ 2017-11-21 14:38   ` Peter Maydell
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2017-11-21 14:38 UTC (permalink / raw)
  To: Gabriel Costa; +Cc: QEMU Developers, qemu-arm, Philippe Mathieu-Daudé

On 27 October 2017 at 13:24, Gabriel Costa <gabriel291075@gmail.com> wrote:
> This Patch include kinetis_k64_mcg.c/.h
> mcg means Multipurpose Clock Generator (MCG)
> More information about this peripheral can be found at:
> pag 579, K64P144M120SF5RM.pdf.

"page"

(Some of the remarks about commit message phrasing for the UART
patch apply here too, though in this case it is worth
explaining what MCG stands for.


> Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
> ---
>  hw/misc/kinetis_k64_mcg.c         | 208 ++++++++++++++++++++++++++++++++++++++
>  include/hw/misc/kinetis_k64_mcg.h |  43 ++++++++
>  2 files changed, 251 insertions(+)
>  create mode 100644 hw/misc/kinetis_k64_mcg.c
>  create mode 100644 include/hw/misc/kinetis_k64_mcg.h
>
> diff --git a/hw/misc/kinetis_k64_mcg.c b/hw/misc/kinetis_k64_mcg.c
> new file mode 100644
> index 0000000..37f4201
> --- /dev/null
> +++ b/hw/misc/kinetis_k64_mcg.c
> @@ -0,0 +1,208 @@
> +/*
> + * Kinetis K64 peripheral microcontroller emulation.
> + *
> + * Copyright (c) 2017 Advantech Wireless
> + * Written by Gabriel Costa <gabriel291075@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 or
> + *  (at your option) any later version.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "qemu/log.h"
> +#include "hw/misc/kinetis_k64_mcg.h"
> +
> +static const VMStateDescription vmstate_kinetis_k64_mcg = {
> +    .name = TYPE_KINETIS_K64_MCG,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8(C1, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(C2, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(C3, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(C4, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(C5, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(C6, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(S, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(SC, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(ATCVH, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(ATCVL, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(C7, kinetis_k64_mcg_state),
> +        VMSTATE_UINT8(C8, kinetis_k64_mcg_state),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void kinetis_k64_mcg_reset(DeviceState *dev)
> +{
> +    kinetis_k64_mcg_state *s = KINETIS_K64_MCG(dev);
> +
> +    s->C1 = 0x04;
> +    s->C2 = 0x80;
> +    s->C3 = 0x00;
> +    s->C4 = 0x00;
> +    s->C5 = 0x00;
> +    s->C6 = 0x00;
> +    s->S = 0x10;

This is how the hardware resets, but the QEMU implementation
doesn't have to worry about the complexities of slow hardware
initialization or gaining and losing PLL locks. So you can also
set bits 6 and 1 here, indicating that we have instantaneously
initialized the oscillator and gained lock.

> +    s->SC = 0x02;
> +    s->ATCVH = 0x00;
> +    s->ATCVL = 0x00;
> +    s->C7 = 0x00;
> +    s->C8 = 0x80;
> +}
> +
> +static void kinetis_k64_mcg_write(void *opaque, hwaddr offset, uint64_t value,
> +        unsigned size)
> +{
> +    kinetis_k64_mcg_state *s = (kinetis_k64_mcg_state *)opaque;
> +
> +    value &= 0xFF;
> +
> +    switch (offset) {
> +    case 0x00:
> +        if (value & 1 << 2) { /*IREFS*/
> +            s->S = 0;
> +            s->S |= 1 << 3; /*10 Enconding 2 - External ref clk is selected*/

"Encoding". Spaces around the text inside /* */, please.

Why clear s->S to 0 and then OR something into it?

Surely we should just be changing the bits in s->S that we
need to affect, not touching all the others?

> +        }
> +        if ((s->C1 & 0x80) && (value >> 6 == 0)) {

Should we really be looking at the old value of C1 here,
rather than the one that's beeing written?

> +            s->S |= 1 << 2; /*11 Enconding 3 - Output of the PLL is selected*/

This will go wrong if some of the bits in this field of
s->S are already set.

What you want to do here is copy bit 2 of C1 into bit 4
of S, and copy bits [7:6] of C1 into bits [3:2] of S.
There are two ways to do that:

old fashioned way with bit ops:
   s->S &= ~c0;
   s->S |= (value >> 4);

better, more comprehensible way (these functions are declared
and documented in include/qemu/bitops.h):
   clks = extract32(value, 6, 2);
   s->S = deposit32(s->S, 2, 2, clks);

I don't object to using raw bitwise logic ops, but if you
want to do it that way you need to get it right...

Strongly consider using the REG32 and FIELD macros from
hw/registerfields.h as a way to define some symbolic
constants so you don't need to use hardcoded numbers for
bit positions and field widths.

> +        }
> +        s->C1 = value;
> +        break;
> +    case 0x01:
> +        s->C2 = value;
> +        break;
> +    case 0x02:
> +        s->C3 = value;
> +        break;
> +    case 0x03:
> +        s->C4 = value;
> +        break;
> +    case 0x04:
> +        s->C5 = value;
> +        if (s->C5 & 1 << 6) { /*PLLCLKEN0*/
> +            s->S |= 1 << 6;  /*LOCK0*/
> +        }

Please be consistent about whether you write the value to
the s->whatever field first and then update the status register,
or whether you update s->S based on value and then write
to s->whatever afterwards.

> +        break;
> +    case 0x05:
> +        s->C6 = value;
> +        if (s->C6 & 1 << 6) { /*PLLS*/
> +            s->S |= 1 << 5;  /*PLLST*/
> +        }
> +        break;
> +    case 0x06:
> +        s->S = value;

The data sheet says this register is read-only!

> +        break;
> +    case 0x08:
> +        s->SC = value;
> +        break;
> +    case 0x0A:
> +        s->ATCVH = value;
> +        break;
> +    case 0x0B:
> +        s->ATCVL = value;
> +        break;
> +    case 0x0C:
> +        s->C7 = value;
> +        break;
> +    case 0x0D:
> +        s->C8 = value;
> +        break;

Many of the bits in C7 and C8 are not writeable. Please check the
datasheet...

> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +            "kinetis_k64_mcg: write at bad offset %"HWADDR_PRIx"\n", offset);
> +    }
> +}
> +
> +static uint64_t kinetis_k64_mcg_read(void *opaque, hwaddr offset, unsigned size)
> +{
> +    kinetis_k64_mcg_state *s = (kinetis_k64_mcg_state *)opaque;
> +    uint8_t value;
> +
> +    switch (offset) {
> +    case 0x00:
> +        value = s->C1;
> +        break;
> +    case 0x01:
> +        value = s->C2;
> +        break;
> +    case 0x02:
> +        value = s->C3;
> +        break;
> +    case 0x03:
> +        value = s->C4;
> +        break;
> +    case 0x04:
> +        value = s->C5;
> +        break;
> +    case 0x05:
> +        value = s->C6;
> +        break;
> +    case 0x06:
> +        value = s->S;
> +        break;
> +    case 0x08:
> +        value = s->SC;
> +        break;
> +    case 0x0A:
> +        value = s->ATCVH;
> +        break;
> +    case 0x0B:
> +        value = s->ATCVL;
> +        break;
> +    case 0x0C:
> +        value = s->C7;
> +        break;
> +    case 0x0D:
> +        value = s->C8;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +            "kinetis_k64_mcg: read at bad offset %"HWADDR_PRIx"\n", offset);
> +        return 0;
> +    }
> +    return value;
> +}
> +
> +static const MemoryRegionOps kinetis_k64_mcg_ops = {
> +    .read = kinetis_k64_mcg_read,
> +    .write = kinetis_k64_mcg_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void kinetis_k64_mcg_init(Object *obj)
> +{
> +    kinetis_k64_mcg_state *s = KINETIS_K64_MCG(obj);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +
> +    memory_region_init_io(&s->iomem, obj, &kinetis_k64_mcg_ops, s,
> +            TYPE_KINETIS_K64_MCG, 0x1000);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +    sysbus_init_irq(sbd, &s->irq);

You create an interrupt line here but never do anything with it.
What is it for?

> +}
> +
> +static void kinetis_k64_mcg_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->vmsd = &vmstate_kinetis_k64_mcg;
> +    dc->reset = kinetis_k64_mcg_reset;
> +    dc->desc = "Kinetis K64 series MCG";
> +}
> +
> +static const TypeInfo kinetis_k64_mcg_info = {
> +    .name          = TYPE_KINETIS_K64_MCG,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(kinetis_k64_mcg_state),
> +    .instance_init = kinetis_k64_mcg_init,
> +    .class_init    = kinetis_k64_mcg_class_init,
> +};
> +
> +static void kinetis_k64_mcg_register_types(void)
> +{
> +    type_register_static(&kinetis_k64_mcg_info);
> +}
> +
> +type_init(kinetis_k64_mcg_register_types)
> diff --git a/include/hw/misc/kinetis_k64_mcg.h b/include/hw/misc/kinetis_k64_mcg.h
> new file mode 100644
> index 0000000..3f105c5
> --- /dev/null
> +++ b/include/hw/misc/kinetis_k64_mcg.h
> @@ -0,0 +1,43 @@
> +/*
> + * Kinetis K64 peripheral microcontroller emulation.
> + *
> + * Copyright (c) 2017 Advantech Wireless
> + * Written by Gabriel Costa <gabriel291075@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 or
> + *  (at your option) any later version.
> + */
> +
> +#ifndef KINETIS_MCG_H
> +#define KINETIS_MCG_H
> +
> +#include "hw/sysbus.h"
> +#include "hw/hw.h"
> +
> +#define TYPE_KINETIS_K64_MCG "kinetis_k64_mcg"
> +#define KINETIS_K64_MCG(obj) \
> +    OBJECT_CHECK(kinetis_k64_mcg_state, (obj), TYPE_KINETIS_K64_MCG)
> +
> +typedef struct {
> +    SysBusDevice parent_obj;
> +
> +    MemoryRegion iomem;
> +
> +    uint8_t C1;
> +    uint8_t C2;
> +    uint8_t C3;
> +    uint8_t C4;
> +    uint8_t C5;
> +    uint8_t C6;
> +    uint8_t S;
> +    uint8_t SC;
> +    uint8_t ATCVH;
> +    uint8_t ATCVL;
> +    uint8_t C7;
> +    uint8_t C8;

These should all be in lower case I think.

> +
> +    qemu_irq irq;
> +} kinetis_k64_mcg_state;

Structure and type names should be in CamelCase. Please check
the CODING_STYLE file.

> +
> +#endif
> --
> 2.1.4

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 3/5] arm: kinetis_k64_pmux
       [not found] ` <1509107055-21978-4-git-send-email-costa@advantech.ca>
@ 2017-11-21 14:50   ` Peter Maydell
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2017-11-21 14:50 UTC (permalink / raw)
  To: Gabriel Costa; +Cc: QEMU Developers, qemu-arm, Philippe Mathieu-Daudé

On 27 October 2017 at 13:24, Gabriel Costa <gabriel291075@gmail.com> wrote:
> This Patch include kinetis_k64_pmux.c/.h
> pmux is refered as Port Control and Interrupts (PORT)
> More information about this peripheral can be found at:
> pag 273, K64P144M120SF5RM.pdf.
>
> Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
> ---
>  hw/misc/kinetis_k64_pmux.c         | 158 +++++++++++++++++++++++++++++++++++++
>  include/hw/misc/kinetis_k64_pmux.h |  38 +++++++++
>  2 files changed, 196 insertions(+)
>  create mode 100644 hw/misc/kinetis_k64_pmux.c
>  create mode 100644 include/hw/misc/kinetis_k64_pmux.h
>
> diff --git a/hw/misc/kinetis_k64_pmux.c b/hw/misc/kinetis_k64_pmux.c
> new file mode 100644
> index 0000000..8346ef7
> --- /dev/null
> +++ b/hw/misc/kinetis_k64_pmux.c
> @@ -0,0 +1,158 @@
> +/*
> + * Kinetis K64 peripheral microcontroller emulation.
> + *
> + * Copyright (c) 2017 Advantech Wireless
> + * Written by Gabriel Costa <gabriel291075@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 or
> + *  (at your option) any later version.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "qemu/log.h"
> +#include "hw/misc/kinetis_k64_pmux.h"
> +
> +static const VMStateDescription vmstate_kinetis_k64_pmux = {
> +    .name = TYPE_KINETIS_K64_PMUX,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32_ARRAY(PCR, kinetis_k64_pmux_state, 32),

Please #define a symbolic constant for the size of this array.

> +        VMSTATE_UINT32(GPCLR, kinetis_k64_pmux_state),
> +        VMSTATE_UINT32(GPCHR, kinetis_k64_pmux_state),
> +        VMSTATE_UINT32(ISFR, kinetis_k64_pmux_state),
> +        VMSTATE_UINT32(DFER, kinetis_k64_pmux_state),
> +        VMSTATE_UINT32(DFCR, kinetis_k64_pmux_state),
> +        VMSTATE_UINT32(DFWR, kinetis_k64_pmux_state),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void kinetis_k64_pmux_reset(DeviceState *dev)
> +{
> +    kinetis_k64_pmux_state *s = KINETIS_K64_PMUX(dev);
> +    uint8_t cnt;
> +
> +    for (cnt = 0; cnt < 32; cnt++) {

"cnt < ARRAY_SIZE(s->PCR)" makes it clear you have
the right loop bound to not overrun the array.

> +        s->PCR[cnt] = 0x00000000;

Just say "0".

> +    }
> +    s->GPCLR = 0x00000000;
> +    s->GPCHR = 0x00000000;
> +    s->ISFR = 0x00000000;
> +    s->DFER = 0x00000000;
> +    s->DFCR = 0x00000000;
> +    s->DFWR = 0x00000000;
> +}
> +
> +static void kinetis_k64_pmux_write(void *opaque, hwaddr offset, uint64_t value,
> +        unsigned size)
> +{
> +    kinetis_k64_pmux_state *s = (kinetis_k64_pmux_state *)opaque;
> +
> +    value &= 0xFFFFFFFF;

This mask is unnecessary, because you are using the default
max_access_size for your MemoryRegionOps, which is 4.

(You should check whether this device permits byte accesses;
if not, consider setting min_access_size.)

> +    switch (offset) {
> +    case 0x00 ... 0x7C:
> +        s->PCR[offset >> 2] = value;

Some of the bits in these registers are read-only.

> +        break;
> +    case 0x80:
> +        s->GPCLR = value;
> +        break;
> +    case 0x84:
> +        s->GPCHR = value;
> +        break;
> +    case 0xA0:
> +        s->ISFR = value;

ISFR is write-1-to-clear, not this behaviour.

(Also, actual implementation of the interrupts seems to be missing.)

> +        break;
> +    case 0xC0:
> +        s->DFER = value;
> +        break;
> +    case 0xC4:
> +        s->DFCR = value;
> +        break;
> +    case 0xC8:
> +        s->DFWR = value;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +            "kinetis_k64_pmux: write at bad offset %"HWADDR_PRIx"\n", offset);
> +    }
> +}
> +
> +static uint64_t kinetis_k64_pmux_read(void *opaque, hwaddr offset,
> +        unsigned size)
> +{
> +    kinetis_k64_pmux_state *s = (kinetis_k64_pmux_state *)opaque;
> +    uint8_t value;
> +
> +    switch (offset) {
> +    case 0x00 ... 0x7C:
> +        value = s->PCR[offset >> 2];
> +        break;
> +    case 0x80:
> +        value = s->GPCLR;

This register is write-only (reads return 0), as is GPCHR. Check
the data sheet.

> +        break;
> +    case 0x84:
> +        value = s->GPCHR;
> +        break;
> +    case 0xA0:
> +        value = s->ISFR;
> +        break;
> +    case 0xC0:
> +        value = s->DFER;
> +        break;
> +    case 0xC4:
> +        value = s->DFCR;
> +        break;
> +    case 0xC8:
> +        value = s->DFWR;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +            "kinetis_k64_pmux: read at bad offset %"HWADDR_PRIx"\n", offset);
> +        return 0;
> +    }
> +    return value;
> +}
> +
> +static const MemoryRegionOps kinetis_k64_pmux_ops = {
> +    .read = kinetis_k64_pmux_read,
> +    .write = kinetis_k64_pmux_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void kinetis_k64_pmux_init(Object *obj)
> +{
> +    kinetis_k64_pmux_state *s = KINETIS_K64_PMUX(obj);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> +
> +    memory_region_init_io(&s->iomem, obj, &kinetis_k64_pmux_ops, s,
> +            TYPE_KINETIS_K64_PMUX, 0x1000);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +    sysbus_init_irq(sbd, &s->irq);

Again, you've defined an interrupt and done nothing with it.

> +}
> +
> +static void kinetis_k64_pmux_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->vmsd = &vmstate_kinetis_k64_pmux;
> +    dc->reset = kinetis_k64_pmux_reset;
> +    dc->desc = "Kinetis K64 series PMUX";
> +}
> +
> +static const TypeInfo kinetis_k64_pmux_info = {
> +    .name          = TYPE_KINETIS_K64_PMUX,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(kinetis_k64_pmux_state),
> +    .instance_init = kinetis_k64_pmux_init,
> +    .class_init    = kinetis_k64_pmux_class_init,
> +};
> +
> +static void kinetis_k64_pmux_register_types(void)
> +{
> +    type_register_static(&kinetis_k64_pmux_info);
> +}
> +
> +type_init(kinetis_k64_pmux_register_types)
> diff --git a/include/hw/misc/kinetis_k64_pmux.h b/include/hw/misc/kinetis_k64_pmux.h
> new file mode 100644
> index 0000000..49359ac
> --- /dev/null
> +++ b/include/hw/misc/kinetis_k64_pmux.h
> @@ -0,0 +1,38 @@
> +/*
> + * Kinetis K64 peripheral microcontroller emulation.
> + *
> + * Copyright (c) 2017 Advantech Wireless
> + * Written by Gabriel Costa <gabriel291075@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 or
> + *  (at your option) any later version.
> + */
> +
> +#ifndef KINETIS_PMUX_H
> +#define KINETIS_PMUX_H
> +
> +#include "hw/sysbus.h"
> +#include "hw/hw.h"
> +
> +#define TYPE_KINETIS_K64_PMUX "kinetis_k64_pmux"
> +#define KINETIS_K64_PMUX(obj) \
> +    OBJECT_CHECK(kinetis_k64_pmux_state, (obj), TYPE_KINETIS_K64_PMUX)
> +
> +typedef struct {
> +    SysBusDevice parent_obj;
> +
> +    MemoryRegion iomem;
> +
> +    uint32_t PCR[32];
> +    uint32_t GPCLR;
> +    uint32_t GPCHR;
> +    uint32_t ISFR;
> +    uint32_t DFER;
> +    uint32_t DFCR;
> +    uint32_t DFWR;
> +
> +    qemu_irq irq;
> +} kinetis_k64_pmux_state;

Same comments about coding style for struct and field names
as for other patches.

> +
> +#endif
> --
> 2.1.4
>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 4/5] arm: kinetis_k64_system
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 4/5] arm: kinetis_k64_system Gabriel Costa
@ 2017-11-21 14:55   ` Peter Maydell
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2017-11-21 14:55 UTC (permalink / raw)
  To: Gabriel Costa; +Cc: QEMU Developers, qemu-arm, Philippe Mathieu-Daudé

On 27 October 2017 at 13:24, Gabriel Costa <gabriel291075@gmail.com> wrote:
> This Patch include kinetis_k64_system.c/.h and Makefile.objs
> sim means System Integration Module (SIM)
> More information about this peripheral can be found at:
> pag 291, K64P144M120SF5RM.pdf.
>
> Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
> ---
>  hw/misc/Makefile.objs                |   3 +
>  hw/misc/kinetis_k64_system.c         | 274 +++++++++++++++++++++++++++++++++++
>  include/hw/misc/kinetis_k64_system.h |  52 +++++++
>  3 files changed, 329 insertions(+)
>  create mode 100644 hw/misc/kinetis_k64_system.c
>  create mode 100644 include/hw/misc/kinetis_k64_system.h
>
> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
> index 19202d9..c5c8589 100644
> --- a/hw/misc/Makefile.objs
> +++ b/hw/misc/Makefile.objs
> @@ -61,3 +61,6 @@ obj-$(CONFIG_AUX) += auxbus.o
>  obj-$(CONFIG_ASPEED_SOC) += aspeed_scu.o aspeed_sdmc.o
>  obj-y += mmio_interface.o
>  obj-$(CONFIG_MSF2) += msf2-sysreg.o
> +obj-$(CONFIG_KINETIS_K64) += kinetis_k64_mcg.o
> +obj-$(CONFIG_KINETIS_K64) += kinetis_k64_pmux.o
> +obj-$(CONFIG_KINETIS_K64) += kinetis_k64_system.o
> diff --git a/hw/misc/kinetis_k64_system.c b/hw/misc/kinetis_k64_system.c
> new file mode 100644
> index 0000000..e547fe8
> --- /dev/null
> +++ b/hw/misc/kinetis_k64_system.c
> @@ -0,0 +1,274 @@
> +/*
> + * Kinetis K64 peripheral microcontroller emulation.
> + *
> + * Copyright (c) 2017 Advantech Wireless
> + * Written by Gabriel Costa <gabriel291075@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 or
> + *  (at your option) any later version.
> + */

Looks like the same comments apply here as for the other devices:
 * coding conventions
 * read-only registers
 * read-only bits in registers

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v7 5/5] arm: kinetis_mk64fn1m0 machine
  2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 5/5] arm: kinetis_mk64fn1m0 machine Gabriel Costa
@ 2017-11-21 15:02   ` Peter Maydell
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Maydell @ 2017-11-21 15:02 UTC (permalink / raw)
  To: Gabriel Costa; +Cc: QEMU Developers, qemu-arm, Philippe Mathieu-Daudé

On 27 October 2017 at 13:24, Gabriel Costa <gabriel291075@gmail.com> wrote:
> This Patch include mk64fn1m0.c that describe the kinetis k64 machine and
> some peripherals.
> Also, include changes in Makefile.objs and arm-softmmu.mak to compile
> this machine.
>
> Signed-off-by: Gabriel Augusto Costa <gabriel291075@gmail.com>
> ---
>  default-configs/arm-softmmu.mak |   1 +
>  hw/arm/Makefile.objs            |   1 +
>  hw/arm/mk64fn1m0.c              | 136 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 138 insertions(+)
>  create mode 100644 hw/arm/mk64fn1m0.c
>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index 5059d13..a835d4f 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -130,3 +130,4 @@ CONFIG_SMBIOS=y
>  CONFIG_ASPEED_SOC=y
>  CONFIG_GPIO_KEY=y
>  CONFIG_MSF2=y
> +CONFIG_KINETIS_K64=y
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index 2794e08..874a38a 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -20,3 +20,4 @@ obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
>  obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
>  obj-$(CONFIG_MPS2) += mps2.o
>  obj-$(CONFIG_MSF2) += msf2-soc.o msf2-som.o
> +obj-$(CONFIG_KINETIS_K64) += mk64fn1m0.o
> diff --git a/hw/arm/mk64fn1m0.c b/hw/arm/mk64fn1m0.c
> new file mode 100644
> index 0000000..618791c
> --- /dev/null
> +++ b/hw/arm/mk64fn1m0.c
> @@ -0,0 +1,136 @@
> +/*
> + * Kinetis K64 MK64FN1M0 microcontroller emulation.
> + *
> + * Copyright (c) 2017 Advantech Wireless
> + * Written by Gabriel Costa <gabriel291075@gmail.com>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 or
> + *  (at your option) any later version.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/sysbus.h"
> +#include "hw/ssi/ssi.h"
> +#include "hw/arm/arm.h"
> +#include "hw/devices.h"
> +#include "qemu/timer.h"
> +#include "hw/i2c/i2c.h"
> +#include "net/net.h"
> +#include "hw/boards.h"
> +#include "qemu/log.h"
> +#include "exec/address-spaces.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/char/pl011.h"
> +#include "hw/misc/unimp.h"
> +#include "cpu.h"
> +#include "hw/char/kinetis_k64_uart.h"
> +#include "hw/misc/kinetis_k64_system.h"
> +#include "hw/misc/kinetis_k64_mcg.h"
> +#include "hw/misc/kinetis_k64_pmux.h"
> +
> +#define FLASH_SIZE              (1024 * 1024)
> +#define FLASH_BASE_ADDRESS      (0x00000000)
> +#define SRAM_SIZE               (192 * 1024)
> +#define SRAM_BASE_ADDRESS       (0x20000000)
> +
> +#define NUM_IRQ_LINES 85
> +
> +/* System controller.  */
> +
> +static void do_sys_reset(void *opaque, int n, int level)
> +{
> +    if (level) {
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> +    }
> +}
> +
> +/* Interruptions at pag.77 of K64P144M120F5RM.pdf */
> +
> +static void mk64fn1m0_init_mach(MachineState *ms, const char *kernel_filename)
> +{
> +    DeviceState *nvic;
> +
> +    MemoryRegion *system_memory = get_system_memory();
> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> +
> +    memory_region_init_ram(flash, NULL, "k64.flash", FLASH_SIZE, &error_fatal);
> +    memory_region_set_readonly(flash, true);

You could just use memory_region_init_rom() rather than _init_ram
and then set_readonly.

> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> +    memory_region_init_ram(sram, NULL, "k64.sram", SRAM_SIZE, &error_fatal);
> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +    nvic = armv7m_init(system_memory, FLASH_SIZE, NUM_IRQ_LINES,
> +            ms->kernel_filename, ms->cpu_type);
> +    qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0,
> +            qemu_allocate_irq(&do_sys_reset, NULL, 0));
> +
> +    sysbus_create_simple(TYPE_KINETIS_K64_SIM, 0x40048000, NULL);
> +    sysbus_create_simple(TYPE_KINETIS_K64_MCG, 0x40064000, NULL);
> +    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x40049000,
> +            qdev_get_gpio_in(nvic, 59));
> +    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x4004A000,
> +            qdev_get_gpio_in(nvic, 60));
> +    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x4004B000,
> +            qdev_get_gpio_in(nvic, 61));
> +    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x4004C000,
> +            qdev_get_gpio_in(nvic, 62));
> +    sysbus_create_simple(TYPE_KINETIS_K64_PMUX, 0x4004D000,
> +            qdev_get_gpio_in(nvic, 63));
> +    create_unimplemented_device("kinetis_k64_spi0",  0x4002C000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_spi1",  0x4002D000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_adc0",  0x4003B000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_dac",   0x4002F000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_i2c0",  0x40066000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_i2c1",  0x40067000, 0x1000);
> +    kinetis_k64_uart_create(0x4006A000, qdev_get_gpio_in(nvic, 31),
> +            serial_hds[0]);
> +    create_unimplemented_device("kinetis_k64_uart1", 0x4006B000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_uart2", 0x4006C000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_uart3", 0x4006D000, 0x1000);

Aren't all the UARTs the same? If they are, you might as well
create them all since you have the device model. If they're not,
have a comment explaining why you don't do that.

> +    create_unimplemented_device("kinetis_k64_spi2",  0x400AC000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_adc1",  0x400BB000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_i2c2",  0x400E6000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_uart4", 0x400EA000, 0x1000);
> +    create_unimplemented_device("kinetis_k64_uart5", 0x400EB000, 0x1000);
> +    create_unimplemented_device("peripheral_brdg_0", 0x40000000, 0x1000);
> +    create_unimplemented_device("Crossbar_Switch",   0x40004000, 0x1000);
> +    create_unimplemented_device("DMA_Controller",    0x40008000, 0x1000);
> +    create_unimplemented_device("DMA_Controller_t",  0x40009000, 0x1000);
> +    create_unimplemented_device("FlexBus",           0x4000C000, 0x1000);
> +    create_unimplemented_device("MPU",               0x4000D000, 0x1000);
> +    create_unimplemented_device("Flash_mem_ctrl",    0x4001F000, 0x1000);
> +    create_unimplemented_device("Flash_mem",         0x40020000, 0x1000);
> +    create_unimplemented_device("DMA_ch_multiplx",   0x40021000, 0x1000);
> +}
> +
> +static void mk64fn1m0_init(MachineState *machine)
> +{
> +    const char *kernel_filename = machine->kernel_filename;
> +    mk64fn1m0_init_mach(machine, kernel_filename);
> +}
> +
> +static void mk64fn1m0_class_init(ObjectClass *oc, void *data)
> +{
> +    MachineClass *mc = MACHINE_CLASS(oc);
> +
> +    mc->desc = "Kinetis K64 MCU (Cortex-M4)";
> +    mc->init = mk64fn1m0_init;
> +    mc->ignore_memory_transaction_failures = true;

New board models must not set this flag -- it is strictly for
legacy models that are already in the QEMU tree.

> +    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
> +    mc->max_cpus = 1;
> +}
> +
> +static const TypeInfo mk64_type = {
> +    .name = MACHINE_TYPE_NAME("mk64fn1m0"),
> +    .parent = TYPE_MACHINE,
> +    .class_init = mk64fn1m0_class_init,
> +};
> +
> +static void mk64fn1m0_machine_init(void)
> +{
> +    type_register_static(&mk64_type);
> +}
> +
> +type_init(mk64fn1m0_machine_init)
> --
> 2.1.4


thanks
-- PMM

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

end of thread, other threads:[~2017-11-21 15:02 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-27 12:24 [Qemu-devel] [PATCH v7 0/5] arm: kinetis_mk64fn1m0 machine Gabriel Costa
2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 1/5] arm: kinetis_k64_uart Gabriel Costa
2017-11-21 14:13   ` Peter Maydell
2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 2/5] arm: kinetis_k64_mcg Gabriel Costa
2017-11-21 14:38   ` Peter Maydell
2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 4/5] arm: kinetis_k64_system Gabriel Costa
2017-11-21 14:55   ` Peter Maydell
2017-10-27 12:24 ` [Qemu-devel] [PATCH v7 5/5] arm: kinetis_mk64fn1m0 machine Gabriel Costa
2017-11-21 15:02   ` Peter Maydell
     [not found] ` <1509107055-21978-4-git-send-email-costa@advantech.ca>
2017-11-21 14:50   ` [Qemu-devel] [PATCH v7 3/5] arm: kinetis_k64_pmux Peter Maydell

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.