All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] hw/char: Add Altera JTAG UART emulation
@ 2019-01-29  9:51 Tobias Klauser
  2019-01-29 10:19 ` Peter Maydell
  0 siblings, 1 reply; 3+ messages in thread
From: Tobias Klauser @ 2019-01-29  9:51 UTC (permalink / raw)
  To: Chris Wulff, Marek Vasut, Marc-André Lureau, Paolo Bonzini
  Cc: Peter Maydell, Juro Bystricky, qemu-devel

Add the Altera JTAG UART model.

Hardware emulation based on:
https://www.altera.com/en_US/pdfs/literature/ug/ug_embedded_ip.pdf
(Please see "Register Map" on page 65)

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
Acked-by: Marek Vasut <marex@denx.de>
Tested-by: Tobias Klauser <tklauser@distanz.ch>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---

Re-submit of a patch originally submitted by Juro Bystricky in 2017.
Adjusted to compile against latest master.

 default-configs/nios2-softmmu.mak |   1 +
 hw/char/Makefile.objs             |   1 +
 hw/char/altera_juart.c            | 286 ++++++++++++++++++++++++++++++
 include/hw/char/altera_juart.h    |  46 +++++
 4 files changed, 334 insertions(+)
 create mode 100644 hw/char/altera_juart.c
 create mode 100644 include/hw/char/altera_juart.h

diff --git a/default-configs/nios2-softmmu.mak b/default-configs/nios2-softmmu.mak
index 74dc70caaef0..61598465c11d 100644
--- a/default-configs/nios2-softmmu.mak
+++ b/default-configs/nios2-softmmu.mak
@@ -4,3 +4,4 @@ CONFIG_NIOS2=y
 CONFIG_SERIAL=y
 CONFIG_PTIMER=y
 CONFIG_ALTERA_TIMER=y
+CONFIG_ALTERA_JUART=y
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index c4947d7ae7b4..289622f72104 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -30,6 +30,7 @@ common-obj-$(CONFIG_LM32) += lm32_juart.o
 common-obj-$(CONFIG_LM32) += lm32_uart.o
 common-obj-$(CONFIG_MILKYMIST) += milkymist-uart.o
 common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o
+common-obj-$(CONFIG_ALTERA_JUART) += altera_juart.o
 
 obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o
 obj-$(CONFIG_TERMINAL3270) += terminal3270.o
diff --git a/hw/char/altera_juart.c b/hw/char/altera_juart.c
new file mode 100644
index 000000000000..6ef41afdb953
--- /dev/null
+++ b/hw/char/altera_juart.c
@@ -0,0 +1,286 @@
+/*
+ * QEMU model of the Altera JTAG UART.
+ *
+ * Copyright (c) 2016-2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Altera JTAG UART hardware registers are described in:
+ * https://www.altera.com/en_US/pdfs/literature/ug/ug_embedded_ip.pdf
+ * (In particular "Register Map" on page 65)
+ */
+
+#include "qemu/osdep.h"
+#include "chardev/char-serial.h"
+#include "hw/char/altera_juart.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+
+/* Data register */
+#define OFFSET_R_DATA   0
+#define DATA_RVALID     BIT(15)
+#define DATA_RAVAIL     0xFFFF0000
+
+/* Control register */
+#define OFFSET_R_CONTROL 4
+#define CONTROL_RE      BIT(0)
+#define CONTROL_WE      BIT(1)
+#define CONTROL_RI      BIT(8)
+#define CONTROL_WI      BIT(9)
+#define CONTROL_AC      BIT(10)
+#define CONTROL_WSPACE  0xFFFF0000
+
+#define CONTROL_WMASK (CONTROL_RE | CONTROL_WE | CONTROL_AC)
+
+#define TYPE_ALTERA_JUART "altera-juart"
+#define ALTERA_JUART(obj) \
+    OBJECT_CHECK(AlteraJUARTState, (obj), TYPE_ALTERA_JUART)
+
+/* Two registers 4 bytes wide each */
+#define ALTERA_JTAG_UART_REGS_MEM_SIZE  (2 * 4)
+
+/*
+ * The JTAG UART core generates an interrupt when either of the individual
+ * interrupt conditions is pending and enabled.
+ */
+static void altera_juart_update_irq(AlteraJUARTState *s)
+{
+    unsigned int irq;
+
+    irq = ((s->jcontrol & CONTROL_WE) && (s->jcontrol & CONTROL_WI)) ||
+          ((s->jcontrol & CONTROL_RE) && (s->jcontrol & CONTROL_RI));
+
+    qemu_set_irq(s->irq, irq);
+}
+
+static uint64_t altera_juart_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    AlteraJUARTState *s = opaque;
+    uint32_t r;
+
+    switch (addr) {
+    case OFFSET_R_DATA:
+        r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & (s->rx_fifo_size - 1)];
+        if (s->rx_fifo_len) {
+            s->rx_fifo_len--;
+            qemu_chr_fe_accept_input(&s->chr);
+            s->jdata = r | DATA_RVALID | (s->rx_fifo_len << 16);
+            s->jcontrol |= CONTROL_RI;
+        } else {
+            s->jdata = 0;
+            s->jcontrol &= ~CONTROL_RI;
+        }
+
+        altera_juart_update_irq(s);
+        return s->jdata;
+
+    case OFFSET_R_CONTROL:
+        return s->jcontrol;
+    }
+
+    return 0;
+}
+
+static void altera_juart_write(void *opaque, hwaddr addr,
+                               uint64_t value, unsigned int size)
+{
+    AlteraJUARTState *s = opaque;
+    unsigned char c;
+
+    switch (addr) {
+    case OFFSET_R_DATA:
+        c = value & 0xFF;
+        s->jcontrol |= CONTROL_WI;
+        s->jdata = c;
+        qemu_chr_fe_write(&s->chr, &c, 1);
+        altera_juart_update_irq(s);
+        break;
+
+    case OFFSET_R_CONTROL:
+        /* Only RE and WE are writable */
+        value &= CONTROL_WMASK;
+        s->jcontrol &= ~CONTROL_WMASK;
+        s->jcontrol |= value;
+
+        /* Writing 1 to AC clears it to 0 */
+        if (value & CONTROL_AC) {
+            s->jcontrol &= ~CONTROL_AC;
+        }
+        altera_juart_update_irq(s);
+        break;
+    }
+}
+
+static int altera_juart_can_receive(void *opaque)
+{
+    AlteraJUARTState *s = opaque;
+    return s->rx_fifo_size - s->rx_fifo_len;
+}
+
+static void altera_juart_receive(void *opaque, const uint8_t *buf, int size)
+{
+    int i;
+    AlteraJUARTState *s = opaque;
+
+    for (i = 0; i < size; i++) {
+        s->rx_fifo[s->rx_fifo_pos] = buf[i];
+        s->rx_fifo_pos++;
+        s->rx_fifo_pos &= (s->rx_fifo_size - 1);
+        s->rx_fifo_len++;
+    }
+    s->jcontrol |= CONTROL_RI;
+    altera_juart_update_irq(s);
+}
+
+static void altera_juart_event(void *opaque, int event)
+{
+}
+
+static void altera_juart_reset(DeviceState *d)
+{
+    AlteraJUARTState *s = ALTERA_JUART(d);
+
+    s->jdata = 0;
+
+    /* The number of spaces available in the write FIFO */
+    s->jcontrol = s->rx_fifo_size << 16;
+    s->rx_fifo_pos = 0;
+    s->rx_fifo_len = 0;
+}
+
+static const MemoryRegionOps juart_ops = {
+    .read = altera_juart_read,
+    .write = altera_juart_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void altera_juart_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    AlteraJUARTState *s = ALTERA_JUART(obj);
+
+    memory_region_init_io(&s->mmio, OBJECT(s), &juart_ops, s,
+                    TYPE_ALTERA_JUART, ALTERA_JTAG_UART_REGS_MEM_SIZE);
+    sysbus_init_mmio(sbd, &s->mmio);
+    sysbus_init_irq(sbd, &s->irq);
+}
+
+void altera_juart_create(int channel, const hwaddr addr, qemu_irq irq, uint32_t fifo_sz)
+{
+    DeviceState *dev;
+    SysBusDevice *bus;
+    Chardev *chr;
+    const char chr_name[] = "juart";
+    char label[ARRAY_SIZE(chr_name) + 1];
+
+    dev = qdev_create(NULL, TYPE_ALTERA_JUART);
+
+    if (channel >= serial_max_hds()) {
+        error_report("Only %d serial ports are supported by QEMU",
+                     serial_max_hds());
+        exit(1);
+    }
+
+    chr = serial_hd(channel);
+    if (!chr) {
+        snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, channel);
+        chr = qemu_chr_new(label, "null");
+        if (!chr) {
+            error_report("Failed to assign serial port to altera %s", label);
+            exit(1);
+        }
+    }
+    qdev_prop_set_chr(dev, "chardev", chr);
+
+    /*
+     * FIFO size can be set from 8 to 32,768 bytes.
+     * Only powers of two are allowed.
+     */
+    if (fifo_sz < 8 || fifo_sz > 32768 || (fifo_sz & ~(1 << ctz32(fifo_sz)))) {
+        error_report("juart%d: Invalid FIFO size. [%u]", channel, fifo_sz);
+        exit(1);
+    }
+
+    qdev_prop_set_uint32(dev, "fifo-size", fifo_sz);
+    bus = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+
+    if (addr != (hwaddr)-1) {
+        sysbus_mmio_map(bus, 0, addr);
+    }
+
+    sysbus_connect_irq(bus, 0, irq);
+}
+
+static const VMStateDescription vmstate_altera_juart = {
+    .name = "altera-juart" ,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(jdata, AlteraJUARTState),
+        VMSTATE_UINT32(jcontrol, AlteraJUARTState),
+        VMSTATE_VBUFFER_UINT32(rx_fifo, AlteraJUARTState, 1, NULL, rx_fifo_size),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void altera_juart_realize(DeviceState *dev, Error **errp)
+{
+    AlteraJUARTState *s = ALTERA_JUART(dev);
+    qemu_chr_fe_set_handlers(&s->chr,
+                             altera_juart_can_receive,
+                             altera_juart_receive,
+                             altera_juart_event,
+                             NULL, s, NULL, true);
+    s->rx_fifo = g_malloc(s->rx_fifo_size);
+}
+
+static void altera_juart_unrealize(DeviceState *dev, Error **errp)
+{
+    AlteraJUARTState *s = ALTERA_JUART(dev);
+    g_free(s->rx_fifo);
+}
+
+static Property altera_juart_props[] = {
+    DEFINE_PROP_CHR("chardev", AlteraJUARTState, chr),
+    DEFINE_PROP_UINT32("fifo-size", AlteraJUARTState, rx_fifo_size,
+                                        ALTERA_JUART_DEFAULT_FIFO_SIZE),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_juart_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = altera_juart_realize;
+    dc->unrealize = altera_juart_unrealize;
+    dc->props = altera_juart_props;
+    dc->vmsd = &vmstate_altera_juart;
+    dc->reset = altera_juart_reset;
+    dc->desc = "Altera JTAG UART";
+}
+
+static const TypeInfo altera_juart_info = {
+    .name          = TYPE_ALTERA_JUART,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AlteraJUARTState),
+    .instance_init = altera_juart_init,
+    .class_init    = altera_juart_class_init,
+};
+
+static void altera_juart_register(void)
+{
+    type_register_static(&altera_juart_info);
+}
+
+type_init(altera_juart_register)
diff --git a/include/hw/char/altera_juart.h b/include/hw/char/altera_juart.h
new file mode 100644
index 000000000000..fcf7a602523d
--- /dev/null
+++ b/include/hw/char/altera_juart.h
@@ -0,0 +1,46 @@
+/*
+ * Altera JTAG UART emulation
+ *
+ * Copyright (c) 2016-2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ALTERA_JUART_H
+#define ALTERA_JUART_H
+
+#include "chardev/char-fe.h"
+#include "hw/sysbus.h"
+
+/*
+ * The read and write FIFO depths can be set from 8 to 32,768 bytes.
+ * Only powers of two are allowed. A depth of 64 is generally optimal for
+ * performance, and larger values are rarely necessary.
+ */
+
+#define ALTERA_JUART_DEFAULT_FIFO_SIZE 64
+
+typedef struct AlteraJUARTState {
+    SysBusDevice busdev;
+    MemoryRegion mmio;
+    CharBackend chr;
+    qemu_irq irq;
+
+    unsigned int rx_fifo_size;
+    unsigned int rx_fifo_pos;
+    unsigned int rx_fifo_len;
+    uint32_t jdata;
+    uint32_t jcontrol;
+    uint8_t *rx_fifo;
+} AlteraJUARTState;
+
+void altera_juart_create(int channel, const hwaddr addr, qemu_irq irq,
+                         uint32_t fifo_size);
+
+#endif /* ALTERA_JUART_H */
-- 
2.20.0

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

* Re: [Qemu-devel] [PATCH] hw/char: Add Altera JTAG UART emulation
  2019-01-29  9:51 [Qemu-devel] [PATCH] hw/char: Add Altera JTAG UART emulation Tobias Klauser
@ 2019-01-29 10:19 ` Peter Maydell
  2019-01-29 10:32   ` Tobias Klauser
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Maydell @ 2019-01-29 10:19 UTC (permalink / raw)
  To: Tobias Klauser
  Cc: Chris Wulff, Marek Vasut, Marc-André Lureau, Paolo Bonzini,
	Juro Bystricky, QEMU Developers

On Tue, 29 Jan 2019 at 09:51, Tobias Klauser <tklauser@distanz.ch> wrote:
>
> Add the Altera JTAG UART model.
>
> Hardware emulation based on:
> https://www.altera.com/en_US/pdfs/literature/ug/ug_embedded_ip.pdf
> (Please see "Register Map" on page 65)
>
> Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
> Acked-by: Marek Vasut <marex@denx.de>
> Tested-by: Tobias Klauser <tklauser@distanz.ch>
> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>

Do you also have a patch which makes one of the QEMU machine
models use this new device ?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH] hw/char: Add Altera JTAG UART emulation
  2019-01-29 10:19 ` Peter Maydell
@ 2019-01-29 10:32   ` Tobias Klauser
  0 siblings, 0 replies; 3+ messages in thread
From: Tobias Klauser @ 2019-01-29 10:32 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Chris Wulff, Marek Vasut, Marc-André Lureau, Paolo Bonzini,
	Juro Bystricky, QEMU Developers

On 2019-01-29 at 11:19:02 +0100, Peter Maydell <peter.maydell@linaro.org> wrote:
> On Tue, 29 Jan 2019 at 09:51, Tobias Klauser <tklauser@distanz.ch> wrote:
> >
> > Add the Altera JTAG UART model.
> >
> > Hardware emulation based on:
> > https://www.altera.com/en_US/pdfs/literature/ug/ug_embedded_ip.pdf
> > (Please see "Register Map" on page 65)
> >
> > Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
> > Acked-by: Marek Vasut <marex@denx.de>
> > Tested-by: Tobias Klauser <tklauser@distanz.ch>
> > Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
> 
> Do you also have a patch which makes one of the QEMU machine
> models use this new device ?

Yes, I have a patch (which needs some adjustments) to add the 3c120 Nios
devboard which will use this UART.

It could also be used with the 10m50 as it was used in version 15 of the
hardware reference design provided by Altera [1]. Though it seems it is
no longer used in version 16 of the reference design [2].

[1]
https://rocketboards.org/foswiki/view/Documentation/AlteraMAX1010M50RevCDevelopmentKitLinuxSetupUsingMAX10GHRDVersion151
[2]
https://rocketboards.org/foswiki/Documentation/AlteraMAX1010M50RevCDevelopmentKitLinuxSetupV160

Thanks
Tobias

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

end of thread, other threads:[~2019-01-29 10:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-29  9:51 [Qemu-devel] [PATCH] hw/char: Add Altera JTAG UART emulation Tobias Klauser
2019-01-29 10:19 ` Peter Maydell
2019-01-29 10:32   ` Tobias Klauser

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.