* [Qemu-devel] [PATCH] nios2: Add Altera JTAG UART emulation
@ 2017-02-12 18:55 Juro Bystricky
2017-02-12 23:10 ` Marek Vasut
0 siblings, 1 reply; 5+ messages in thread
From: Juro Bystricky @ 2017-02-12 18:55 UTC (permalink / raw)
To: qemu-devel; +Cc: marex, crwulff, jurobystricky, fred.konrad, Juro Bystricky
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>
---
V2: - Removed link to hw specs(checkpatch: line over 90 characters)
V3: - New link to do hw specs
V4: - Modified check for correct fifo size
- Made fifo_size a property
- Use register offsets instead of register indeces
- Removed redundant test for fifo overflow
- Modified commit message
V5: - definine ALTERA_JTAG_UART_REGS_MEM_SIZE
- Modified commit message
- Replaced DEFAULT_FIFO_SIZE by ALTERA_JUART_DEFAULT_FIFO_SIZE
- Modified test for fifo size
- Simplified error message in altera_juart_create().
---
default-configs/nios2-softmmu.mak | 1 +
hw/char/Makefile.objs | 1 +
hw/char/altera_juart.c | 282 ++++++++++++++++++++++++++++++++++++++
include/hw/char/altera_juart.h | 46 +++++++
4 files changed, 330 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 74dc70c..6159846 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 6ea76fe..f0d0e25 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -27,5 +27,6 @@ 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
diff --git a/hw/char/altera_juart.c b/hw/char/altera_juart.c
new file mode 100644
index 0000000..584f73b
--- /dev/null
+++ b/hw/char/altera_juart.c
@@ -0,0 +1,282 @@
+/*
+ * 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 "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;
+ /*
+ * We do not decrement the write fifo,
+ * we "tranmsmit" instanteniously, CONTROL_WI always asserted
+ */
+ 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 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 int altera_juart_can_receive(void *opaque)
+{
+ AlteraJUARTState *s = opaque;
+ return s->rx_fifo_size - s->rx_fifo_len;
+}
+
+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_size)
+{
+ 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 >= MAX_SERIAL_PORTS) {
+ error_report("Only %d serial ports are supported by QEMU",
+ MAX_SERIAL_PORTS);
+ exit(1);
+ }
+
+ chr = serial_hds[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_size < 8 || fifo_size > 3276 || (fifo_size & ~(1 << ctz32(fifo_size)))) {
+ error_report("juart%d: Invalid FIFO size. [%u]", channel, fifo_size);
+ exit(1);
+ }
+
+ qdev_prop_set_uint32(dev, "fifo-size", fifo_size);
+ 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, 0, 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, 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 0000000..972984e
--- /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 "hw/sysbus.h"
+#include "sysemu/char.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.7.4
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH] nios2: Add Altera JTAG UART emulation
2017-02-12 18:55 [Qemu-devel] [PATCH] nios2: Add Altera JTAG UART emulation Juro Bystricky
@ 2017-02-12 23:10 ` Marek Vasut
2017-02-13 0:55 ` Bystricky, Juro
0 siblings, 1 reply; 5+ messages in thread
From: Marek Vasut @ 2017-02-12 23:10 UTC (permalink / raw)
To: Juro Bystricky, qemu-devel; +Cc: crwulff, jurobystricky, fred.konrad
On 02/12/2017 07:55 PM, Juro Bystricky wrote:
Subject should contain [PATCH v5] ...
> 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)
[...]
> +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;
> + /*
> + * We do not decrement the write fifo,
> + * we "tranmsmit" instanteniously, CONTROL_WI always asserted
Nit, fix this comment (transmit, instantly) and it's alignment.
I don't quite understand what this comment is trying to tell me though.
> + */
> + 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;
> + }
> +}
[...]
> +void altera_juart_create(int channel, const hwaddr addr, qemu_irq irq, uint32_t fifo_size)
> +{
> + 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 >= MAX_SERIAL_PORTS) {
> + error_report("Only %d serial ports are supported by QEMU",
> + MAX_SERIAL_PORTS);
> + exit(1);
> + }
> +
> + chr = serial_hds[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_size < 8 || fifo_size > 3276 || (fifo_size & ~(1 << ctz32(fifo_size)))) {
32768 , not 3276 ...
> + error_report("juart%d: Invalid FIFO size. [%u]", channel, fifo_size);
> + exit(1);
> + }
> +
> + qdev_prop_set_uint32(dev, "fifo-size", fifo_size);
> + 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);
> +}
[...]
> +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);
Fix the alignment here so it doesn't look so braindead, align under the
first open parenthesis.
> +#endif /* ALTERA_JUART_H */
>
--
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH] nios2: Add Altera JTAG UART emulation
2017-02-12 23:10 ` Marek Vasut
@ 2017-02-13 0:55 ` Bystricky, Juro
0 siblings, 0 replies; 5+ messages in thread
From: Bystricky, Juro @ 2017-02-13 0:55 UTC (permalink / raw)
To: Marek Vasut, qemu-devel@nongnu.org
Cc: crwulff@gmail.com, jurobystricky@hotmail.com,
fred.konrad@greensocs.com
> Subject should contain [PATCH v5] ...
mea culpa, to my defense I did specify --subject-prefix="PATCH v5"
but did not realize "git send-email file.patch" seems to ignore it
Normally I do something like this (which works fine):
"git send-email -1 --subject-prefix="PATCH v5"
[...]
> > + * We do not decrement the write fifo,
> > + * we "tranmsmit" instanteniously, CONTROL_WI always asserted
>
> Nit, fix this comment (transmit, instantly) and it's alignment.
>
> I don't quite understand what this comment is trying to tell me though.
>
comment removed as too confusing
> > + /*
> > + * FIFO size can be set from 8 to 32,768 bytes.
> > + * Only powers of two are allowed.
> > + */
> > + if (fifo_size < 8 || fifo_size > 3276 || (fifo_size & ~(1 <<
> ctz32(fifo_size)))) {
>
> 32768 , not 3276 ...
Thanks, good catch. Fixed.
[...]
> > +void altera_juart_create(int channel, const hwaddr addr, qemu_irq irq,
> > + uint32_t
> fifo_size);
>
> Fix the alignment here so it doesn't look so braindead, align under the
> first open parenthesis.
>
Fixed
Thanks
Juro
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH] nios2: Add Altera JTAG UART emulation
@ 2017-02-08 21:27 Juro Bystricky
2017-02-08 21:38 ` no-reply
0 siblings, 1 reply; 5+ messages in thread
From: Juro Bystricky @ 2017-02-08 21:27 UTC (permalink / raw)
To: qemu-devel; +Cc: marex, crwulff, jurobystricky, Juro Bystricky
Hardware emulation based on:
https://www.altera.com/en_US/pdfs/literature/ug/ug_embedded_ip.pdf
Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
---
default-configs/nios2-softmmu.mak | 1 +
hw/char/Makefile.objs | 1 +
hw/char/altera_juart.c | 267 ++++++++++++++++++++++++++++++++++++++
include/hw/char/altera_juart.h | 44 +++++++
4 files changed, 313 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 74dc70c..6159846 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 6ea76fe..f0d0e25 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -27,5 +27,6 @@ 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
diff --git a/hw/char/altera_juart.c b/hw/char/altera_juart.c
new file mode 100644
index 0000000..886ded5
--- /dev/null
+++ b/hw/char/altera_juart.c
@@ -0,0 +1,267 @@
+/*
+ * 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.cn/content/dam/altera-www/global/zh_CN/pdfs/literature/ug/ug_embedded_ip.pdf
+ */
+
+#include "qemu/osdep.h"
+#include "hw/char/altera_juart.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+
+/* Data register */
+#define R_DATA 0
+#define DATA_RVALID BIT(15)
+#define DATA_RAVAIL 0xFFFF0000
+
+/* Control register */
+#define R_CONTROL 1
+#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)
+
+/*
+ * 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;
+
+ addr >>= 2;
+
+ switch (addr) {
+ case R_DATA:
+ r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & (FIFO_LENGTH - 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 R_CONTROL:
+ return s->jcontrol;
+ }
+
+ return 0;
+}
+
+static void altera_juart_write(void *opaque, hwaddr addr,
+ uint64_t val64, unsigned int size)
+{
+ AlteraJUARTState *s = opaque;
+ uint32_t value = val64;
+ unsigned char c;
+
+ addr >>= 2;
+
+ switch (addr) {
+ case R_DATA:
+ c = value & 0xFF;
+ /*
+ * We do not decrement the write fifo,
+ * we "tranmsmit" instanteniously, CONTROL_WI always asserted
+ */
+ s->jcontrol |= CONTROL_WI;
+ s->jdata = c;
+ qemu_chr_fe_write(&s->chr, &c, 1);
+ altera_juart_update_irq(s);
+ break;
+
+ case 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 void altera_juart_receive(void *opaque, const uint8_t *buf, int size)
+{
+ int i;
+ AlteraJUARTState *s = opaque;
+
+ if (s->rx_fifo_len >= FIFO_LENGTH) {
+ fprintf(stderr, "WARNING: UART dropped char.\n");
+ return;
+ }
+
+ for (i = 0; i < size; i++) {
+ s->rx_fifo[s->rx_fifo_pos] = buf[i];
+ s->rx_fifo_pos++;
+ s->rx_fifo_pos &= (FIFO_LENGTH - 1);
+ s->rx_fifo_len++;
+ }
+ s->jcontrol |= CONTROL_RI;
+ altera_juart_update_irq(s);
+}
+
+static int altera_juart_can_receive(void *opaque)
+{
+ AlteraJUARTState *s = opaque;
+ return FIFO_LENGTH - s->rx_fifo_len;
+}
+
+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 = FIFO_LENGTH << 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, 2 * 4);
+ sysbus_init_mmio(sbd, &s->mmio);
+ sysbus_init_irq(sbd, &s->irq);
+}
+
+void altera_juart_create(int channel, const hwaddr addr, qemu_irq irq)
+{
+ 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 >= MAX_SERIAL_PORTS) {
+ error_report("Only %d serial ports are supported by QEMU",
+ MAX_SERIAL_PORTS);
+ exit(1);
+ }
+
+ chr = serial_hds[channel];
+ if (!chr) {
+ snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, channel);
+ chr = qemu_chr_new(label, "null");
+ if (!(chr)) {
+ error_report("Can't assign serial port to altera juart%d", channel);
+ exit(1);
+ }
+ }
+
+ qdev_prop_set_chr(dev, "chardev", chr);
+ 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_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, NULL, s, NULL, true);
+}
+
+static Property altera_juart_props[] = {
+ DEFINE_PROP_CHR("chardev", AlteraJUARTState, chr),
+ 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->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 0000000..8a9c892
--- /dev/null
+++ b/include/hw/char/altera_juart.h
@@ -0,0 +1,44 @@
+/*
+ * 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 "hw/sysbus.h"
+#include "sysemu/char.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 FIFO_LENGTH 64
+
+typedef struct AlteraJUARTState {
+ SysBusDevice busdev;
+ MemoryRegion mmio;
+ CharBackend chr;
+ qemu_irq irq;
+
+ unsigned int rx_fifo_pos;
+ unsigned int rx_fifo_len;
+ uint32_t jdata;
+ uint32_t jcontrol;
+ uint8_t rx_fifo[FIFO_LENGTH];
+} AlteraJUARTState;
+
+void altera_juart_create(int channel, const hwaddr addr, qemu_irq irq);
+
+#endif /* ALTERA_JUART_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH] nios2: Add Altera JTAG UART emulation
2017-02-08 21:27 Juro Bystricky
@ 2017-02-08 21:38 ` no-reply
0 siblings, 0 replies; 5+ messages in thread
From: no-reply @ 2017-02-08 21:38 UTC (permalink / raw)
To: juro.bystricky; +Cc: famz, qemu-devel, marex, jurobystricky, crwulff
Hi,
Your series seems to have some coding style problems. See output below for
more information:
Subject: [Qemu-devel] [PATCH] nios2: Add Altera JTAG UART emulation
Type: series
Message-id: 1486589255-24577-1-git-send-email-juro.bystricky@intel.com
=== TEST SCRIPT BEGIN ===
#!/bin/bash
BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0
# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True
commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done
exit $failed
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
- [tag update] patchew/1486569864-17005-1-git-send-email-armbru@redhat.com -> patchew/1486569864-17005-1-git-send-email-armbru@redhat.com
* [new tag] patchew/1486589255-24577-1-git-send-email-juro.bystricky@intel.com -> patchew/1486589255-24577-1-git-send-email-juro.bystricky@intel.com
- [tag update] patchew/20170207005930.28327-1-laurent@vivier.eu -> patchew/20170207005930.28327-1-laurent@vivier.eu
Switched to a new branch 'test'
9d70265 nios2: Add Altera JTAG UART emulation
=== OUTPUT BEGIN ===
Checking PATCH 1/1: nios2: Add Altera JTAG UART emulation...
ERROR: line over 90 characters
#52: FILE: hw/char/altera_juart.c:15:
+ * https://www.altera.com.cn/content/dam/altera-www/global/zh_CN/pdfs/literature/ug/ug_embedded_ip.pdf
total: 1 errors, 0 warnings, 321 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-02-13 0:55 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-12 18:55 [Qemu-devel] [PATCH] nios2: Add Altera JTAG UART emulation Juro Bystricky
2017-02-12 23:10 ` Marek Vasut
2017-02-13 0:55 ` Bystricky, Juro
-- strict thread matches above, loose matches on Subject: below --
2017-02-08 21:27 Juro Bystricky
2017-02-08 21:38 ` no-reply
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).