From: Mohamed ElSayed <m.elsayed4420@gmail.com>
To: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org, Mohamed ElSayed <m.elsayed4420@gmail.com>
Subject: [PULL 2/8] tivac usart module implementation
Date: Tue, 16 May 2023 10:29:53 +0300 [thread overview]
Message-ID: <20230516072959.49994-3-m.elsayed4420@gmail.com> (raw)
In-Reply-To: <20230516072959.49994-1-m.elsayed4420@gmail.com>
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
hw/char/tm4c123_usart.c | 387 ++++++++++++++++++++++++++++++++
include/hw/char/tm4c123_usart.h | 124 ++++++++++
2 files changed, 511 insertions(+)
create mode 100644 hw/char/tm4c123_usart.c
create mode 100644 include/hw/char/tm4c123_usart.h
diff --git a/hw/char/tm4c123_usart.c b/hw/char/tm4c123_usart.c
new file mode 100644
index 0000000000..cafca02b97
--- /dev/null
+++ b/hw/char/tm4c123_usart.c
@@ -0,0 +1,387 @@
+/*
+ * TM4C123 USART
+ *
+ * Copyright (c) 2023 Mohamed ElSayed <m.elsayed4420@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/char/tm4c123_usart.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+
+#define LOG(fmt, args...) qemu_log("%s: " fmt, __func__, ## args)
+#define READONLY LOG("0x%"HWADDR_PRIx" is a readonly field\n.", addr)
+
+static bool usart_clock_enabled(TM4C123SysCtlState *s, hwaddr addr)
+{
+ switch(addr) {
+ case USART_0:
+ return (s->sysctl_rcgcuart & (1 << 0));
+ break;
+ case USART_1:
+ return (s->sysctl_rcgcuart & (1 << 1));
+ break;
+ case USART_2:
+ return (s->sysctl_rcgcuart & (1 << 2));
+ break;
+ case USART_3:
+ return (s->sysctl_rcgcuart & (1 << 3));
+ break;
+ case USART_4:
+ return (s->sysctl_rcgcuart & (1 << 4));
+ break;
+ case USART_5:
+ return (s->sysctl_rcgcuart & (1 << 5));
+ break;
+ case USART_6:
+ return (s->sysctl_rcgcuart & (1 << 6));
+ break;
+ case USART_7:
+ return (s->sysctl_rcgcuart & (1 << 7));
+ break;
+ }
+ return false;
+}
+
+
+static int tm4c123_usart_can_receive(void* opaque)
+{
+ TM4C123USARTState *s = opaque;
+
+ if (!(s->usart_fr & USART_FR_RXFF)) {
+ //the module can receive data.
+ return 1;
+ }
+ return 0;
+}
+
+static void tm4c123_usart_receive(void *opaque, const uint8_t *buf, int size)
+{
+ TM4C123USARTState *s = opaque;
+
+ if (!(s->usart_ctl & USART_CR_EN && s->usart_ctl & USART_CR_RXE)) {
+ //the module is not enabled
+ LOG("The module is not enbled\n");
+ return;
+ }
+
+ s->usart_dr = *buf;
+ s->usart_ctl &= ~USART_FR_RXFE;
+
+ if (s->usart_im & USART_IM_RXIM) {
+ qemu_set_irq(s->irq, 1);
+ }
+
+ LOG("Receiving: %c\n", s->usart_dr);
+}
+
+static void tm4c123_usart_reset(DeviceState *dev)
+{
+ TM4C123USARTState *s = TM4C123_USART(dev);
+
+ s->usart_dr = 0x00000000;
+ s->usart_rsr = 0x00000000;
+ s->usart_fr = 0x00000090;
+ s->usart_ilpr = 0x00000000;
+ s->usart_ibrd = 0x00000000;
+ s->usart_fbrd = 0x00000000;
+ s->usart_lcrh = 0x00000000;
+ s->usart_ctl = 0x00000300;
+ s->usart_ifls = 0x00000012;
+ s->usart_im = 0x00000000;
+ s->usart_ris = 0x00000000;
+ s->usart_mis = 0x00000000;
+ s->usart_icr = 0x00000000;
+ s->usart_dma_ctl = 0x00000000;
+ s->usart_9bit_addr = 0x00000000;
+ s->usart_9bit_mask = 0x000000FF;
+ s->usart_pp = 0x00000003;
+ s->usart_cc = 0x00000000;
+ s->usart_per_id4 = 0x00000000;
+ s->usart_per_id5 = 0x00000000;
+ s->usart_per_id6 = 0x00000000;
+ s->usart_per_id7 = 0x00000000;
+ s->usart_per_id0 = 0x00000060;
+ s->usart_per_id1 = 0x00000000;
+ s->usart_per_id2 = 0x00000018;
+ s->usart_per_id3 = 0x00000001;
+ s->usart_pcell_id0 = 0x0000000D;
+ s->usart_pcell_id1 = 0x000000F0;
+ s->usart_pcell_id2 = 0x00000005;
+ s->usart_pcell_id3 = 0x000000B1;
+
+ qemu_set_irq(s->irq, 0);
+}
+
+static uint64_t tm4c123_usart_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ TM4C123USARTState *s = opaque;
+
+ if (!usart_clock_enabled(s->sysctl, s->mmio.addr)) {
+ hw_error("USART module clock is not enabled");
+ }
+
+ trace_tm4c123_usart_read(addr);
+
+ switch(addr) {
+ case USART_DR:
+ return s->usart_dr;
+ case USART_RSR:
+ return s->usart_rsr;
+ case USART_FR:
+ return s->usart_fr;
+ case USART_ILPR:
+ return s->usart_ilpr;
+ case USART_IBRD:
+ return s->usart_ibrd;
+ case USART_FBRD:
+ return s->usart_fbrd;
+ case USART_LCRH:
+ return s->usart_lcrh;
+ case USART_CTL:
+ return s->usart_ctl;
+ case USART_IFLS:
+ return s->usart_ifls;
+ case USART_IM:
+ return s->usart_im;
+ case USART_RIS:
+ return s->usart_ris;
+ case USART_MIS:
+ return s->usart_mis;
+ case USART_ICR:
+ return s->usart_icr;
+ case USART_DMA_CTL:
+ return s->usart_dma_ctl;
+ case USART_9BIT_ADDR:
+ return s->usart_9bit_addr;
+ case USART_9BIT_MASK:
+ return s->usart_9bit_mask;
+ case USART_PP:
+ return s->usart_pp;
+ case USART_CC:
+ return s->usart_cc;
+ case USART_PER_ID4:
+ return s->usart_per_id4;
+ case USART_PER_ID5:
+ return s->usart_per_id5;
+ case USART_PER_ID6:
+ return s->usart_per_id6;
+ case USART_PER_ID7:
+ return s->usart_per_id7;
+ case USART_PER_ID0:
+ return s->usart_per_id0;
+ case USART_PER_ID1:
+ return s->usart_per_id1;
+ case USART_PER_ID2:
+ return s->usart_per_id2;
+ case USART_PER_ID3:
+ return s->usart_per_id3;
+ case USART_PCELL_ID0:
+ return s->usart_pcell_id0;
+ case USART_PCELL_ID1:
+ return s->usart_pcell_id1;
+ case USART_PCELL_ID2:
+ return s->usart_pcell_id2;
+ case USART_PCELL_ID3:
+ return s->usart_pcell_id3;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+ return 0;
+ }
+
+ return 0;
+}
+
+static void tm4c123_usart_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size)
+{
+ TM4C123USARTState *s = opaque;
+ uint32_t val32 = val64;
+ unsigned char ch;
+
+ if (!usart_clock_enabled(s->sysctl, s->mmio.addr)) {
+ hw_error("USART module clock is not enabled");
+ }
+
+ trace_tm4c123_usart_write(addr, val32);
+
+ switch(addr) {
+ case USART_DR:
+ s->usart_dr = val32;
+ if (val32 < 0xF000) {
+ ch = val32;
+ qemu_chr_fe_write_all(&s->chr, &ch, 1);
+ }
+ break;
+ case USART_RSR:
+ s->usart_rsr = val32;
+ break;
+ case USART_FR:
+ READONLY;
+ break;
+ case USART_ILPR:
+ s->usart_ilpr = val32;
+ break;
+ case USART_IBRD:
+ s->usart_ibrd = val32;
+ break;
+ case USART_FBRD:
+ s->usart_fbrd = val32;
+ break;
+ case USART_LCRH:
+ s->usart_lcrh = val32;
+ break;
+ case USART_CTL:
+ s->usart_ctl = val32;
+ break;
+ case USART_IFLS:
+ s->usart_ifls = val32;
+ break;
+ case USART_IM:
+ s->usart_im = val32;
+ break;
+ case USART_RIS:
+ READONLY;
+ break;
+ case USART_MIS:
+ READONLY;
+ break;
+ case USART_ICR:
+ s->usart_icr = val32;
+ break;
+ case USART_DMA_CTL:
+ s->usart_dma_ctl = val32;
+ break;
+ case USART_9BIT_ADDR:
+ s->usart_9bit_addr = val32;
+ break;
+ case USART_9BIT_MASK:
+ s->usart_9bit_mask = val32;
+ break;
+ case USART_PP:
+ READONLY;
+ break;
+ case USART_CC:
+ s->usart_cc = val32;
+ break;
+ case USART_PER_ID4:
+ READONLY;
+ break;
+ case USART_PER_ID5:
+ READONLY;
+ break;
+ case USART_PER_ID6:
+ READONLY;
+ break;
+ case USART_PER_ID7:
+ READONLY;
+ break;
+ case USART_PER_ID0:
+ READONLY;
+ break;
+ case USART_PER_ID1:
+ READONLY;
+ break;
+ case USART_PER_ID2:
+ READONLY;
+ break;
+ case USART_PER_ID3:
+ READONLY;
+ break;
+ case USART_PCELL_ID0:
+ READONLY;
+ break;
+ case USART_PCELL_ID1:
+ READONLY;
+ break;
+ case USART_PCELL_ID2:
+ READONLY;
+ break;
+ case USART_PCELL_ID3:
+ READONLY;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+ return;
+ }
+
+ return;
+}
+
+static const MemoryRegionOps tm4c123_usart_ops = {
+ .read = tm4c123_usart_read,
+ .write = tm4c123_usart_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static Property tm4c123_usart_properties[] = {
+ DEFINE_PROP_CHR("chardev", TM4C123USARTState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tm4c123_usart_init(Object *obj)
+{
+ TM4C123USARTState *s = TM4C123_USART(obj);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+
+ memory_region_init_io(&s->mmio, obj, &tm4c123_usart_ops, s,
+ TYPE_TM4C123_USART, 0xFFF);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void tm4c123_usart_realize(DeviceState *dev, Error **errp)
+{
+ TM4C123USARTState *s = TM4C123_USART(dev);
+
+ qemu_chr_fe_set_handlers(&s->chr, tm4c123_usart_can_receive,
+ tm4c123_usart_receive, NULL, NULL,
+ s, NULL, true);
+}
+
+static void tm4c123_usart_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = tm4c123_usart_reset;
+ device_class_set_props(dc, tm4c123_usart_properties);
+ dc->realize = tm4c123_usart_realize;
+}
+
+static const TypeInfo tm4c123_usart_info = {
+ .name = TYPE_TM4C123_USART,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TM4C123USARTState),
+ .instance_init = tm4c123_usart_init,
+ .class_init = tm4c123_usart_class_init,
+};
+
+static void tm4c123_usart_register_types(void)
+{
+ type_register_static(&tm4c123_usart_info);
+}
+
+type_init(tm4c123_usart_register_types)
diff --git a/include/hw/char/tm4c123_usart.h b/include/hw/char/tm4c123_usart.h
new file mode 100644
index 0000000000..be98eb3948
--- /dev/null
+++ b/include/hw/char/tm4c123_usart.h
@@ -0,0 +1,124 @@
+/*
+ * TM4C123 USART
+ *
+ * Copyright (c) 2023 Mohamed ElSayed <m.elsayed4420@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_TM4C123_USART_H
+#define HW_ARM_TM4C123_USART_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "chardev/char-fe.h"
+#include "hw/misc/tm4c123_sysctl.h"
+
+#define USART_DR 0x000
+#define USART_RSR 0x004
+#define USART_FR 0x018
+#define USART_ILPR 0x020
+#define USART_IBRD 0x024
+#define USART_FBRD 0x028
+#define USART_LCRH 0x02C
+#define USART_CTL 0x030
+#define USART_IFLS 0x034
+#define USART_IM 0x038
+#define USART_RIS 0x03C
+#define USART_MIS 0x040
+#define USART_ICR 0x044
+#define USART_DMA_CTL 0x048
+#define USART_9BIT_ADDR 0x0A4
+#define USART_9BIT_MASK 0x0A8
+#define USART_PP 0xFC0
+#define USART_CC 0xFC8
+#define USART_PER_ID4 0x0FD0
+#define USART_PER_ID5 0xFD4
+#define USART_PER_ID6 0xFD8
+#define USART_PER_ID7 0xFDC
+#define USART_PER_ID0 0xFE0
+#define USART_PER_ID1 0xFE4
+#define USART_PER_ID2 0xFE8
+#define USART_PER_ID3 0xFEC
+#define USART_PCELL_ID0 0xFF0
+#define USART_PCELL_ID1 0xFF4
+#define USART_PCELL_ID2 0xFF8
+#define USART_PCELL_ID3 0xFFC
+
+#define USART_FR_RXFF (1 << 6)
+#define USART_FR_TXFF (1 << 5)
+#define USART_FR_RXFE (1 << 4)
+#define USART_FR_BUSY (1 << 3)
+#define USART_CR_RXE (1 << 9)
+#define USART_CR_EN (1 << 0)
+#define USART_IM_RXIM (1 << 4)
+
+#define USART_0 0x4000C000
+#define USART_1 0x4000D000
+#define USART_2 0x4000E000
+#define USART_3 0x4000F000
+#define USART_4 0x40010000
+#define USART_5 0x40011000
+#define USART_6 0x40012000
+#define USART_7 0x40013000
+#define TYPE_TM4C123_USART "tm4c123-usart"
+
+OBJECT_DECLARE_SIMPLE_TYPE(TM4C123USARTState, TM4C123_USART)
+
+struct TM4C123USARTState {
+ SysBusDevice parent_obj;
+ MemoryRegion mmio;
+
+ uint32_t usart_dr;
+ uint32_t usart_rsr;
+ uint32_t usart_fr;
+ uint32_t usart_ilpr;
+ uint32_t usart_ibrd;
+ uint32_t usart_fbrd;
+ uint32_t usart_lcrh;
+ uint32_t usart_ctl;
+ uint32_t usart_ifls;
+ uint32_t usart_im;
+ uint32_t usart_ris;
+ uint32_t usart_mis;
+ uint32_t usart_icr;
+ uint32_t usart_dma_ctl;
+ uint32_t usart_9bit_addr;
+ uint32_t usart_9bit_mask;
+ uint32_t usart_pp;
+ uint32_t usart_cc;
+ uint32_t usart_per_id4;
+ uint32_t usart_per_id5;
+ uint32_t usart_per_id6;
+ uint32_t usart_per_id7;
+ uint32_t usart_per_id0;
+ uint32_t usart_per_id1;
+ uint32_t usart_per_id2;
+ uint32_t usart_per_id3;
+ uint32_t usart_pcell_id0;
+ uint32_t usart_pcell_id1;
+ uint32_t usart_pcell_id2;
+ uint32_t usart_pcell_id3;
+
+ CharBackend chr;
+ qemu_irq irq;
+ TM4C123SysCtlState *sysctl;
+};
+
+#endif
--
2.34.1
next prev parent reply other threads:[~2023-05-16 7:31 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-16 7:29 [PULL SUBSYSTEM arm 0/8] TivaC Implementation Mohamed ElSayed
2023-05-16 7:29 ` [PULL 1/8] the tivac machine def init commit Mohamed ElSayed
2023-05-16 7:29 ` Mohamed ElSayed [this message]
2023-05-16 7:29 ` [PULL 3/8] tivac gpio module implementation Mohamed ElSayed
2023-05-16 7:29 ` [PULL 4/8] tivac system control implementation Mohamed ElSayed
2023-05-16 7:29 ` [PULL 5/8] tivac general purpose timers implementation Mohamed ElSayed
2023-05-16 7:29 ` [PULL 6/8] tivac watchdog " Mohamed ElSayed
2023-05-16 7:29 ` [PULL 7/8] editing the meson and KConfig files to add tivac to qemu build system Mohamed ElSayed
2023-05-16 7:29 ` [PULL 8/8] code style fixes Mohamed ElSayed
2023-05-16 9:00 ` [PULL SUBSYSTEM arm 0/8] TivaC Implementation Alex Bennée
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230516072959.49994-3-m.elsayed4420@gmail.com \
--to=m.elsayed4420@gmail.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.