From: Mohamed ElSayed <m.elsayed4420@gmail.com>
To: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org, Mohamed ElSayed <m.elsayed4420@gmail.com>
Subject: [PATCH 6/8] tiva c general purpose timers implementation
Date: Wed, 17 May 2023 11:12:02 +0300 [thread overview]
Message-ID: <20230517081204.30333-7-m.elsayed4420@gmail.com> (raw)
In-Reply-To: <20230517081204.30333-1-m.elsayed4420@gmail.com>
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
hw/timer/tm4c123_gptm.c | 495 ++++++++++++++++++++++++++++++++
hw/timer/trace-events | 5 +
include/hw/timer/tm4c123_gptm.h | 131 +++++++++
3 files changed, 631 insertions(+)
create mode 100644 hw/timer/tm4c123_gptm.c
create mode 100644 include/hw/timer/tm4c123_gptm.h
diff --git a/hw/timer/tm4c123_gptm.c b/hw/timer/tm4c123_gptm.c
new file mode 100644
index 0000000000..bdbaff776c
--- /dev/null
+++ b/hw/timer/tm4c123_gptm.c
@@ -0,0 +1,495 @@
+/*
+ * TM4C123 General purpose timers
+ *
+ * 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 "hw/timer/tm4c123_gptm.h"
+#include "hw/irq.h"
+#include "trace.h"
+#include "qemu/timer.h"
+#include <time.h>
+
+#define LOG(mask, fmt, args...) qemu_log_mask(mask, "%s: " fmt, __func__, ## args)
+#define READONLY LOG(LOG_GUEST_ERROR, "0x%"HWADDR_PRIx" is a readonly field\n.", addr)
+
+static uint64_t ns_to_ticks(void *opaque, uint64_t ns, uint32_t prescaler)
+{
+ TM4C123GPTMState *s = opaque;
+
+ uint32_t freq = clock_get_hz(s->clk) / prescaler;
+ float sec = (float)ns / (float)NANOSECONDS_PER_SECOND;
+ return sec * freq;
+}
+
+static unsigned long ticks_to_time_ns(void *opaque, uint64_t ticks, uint32_t prescaler)
+{
+ TM4C123GPTMState *s = opaque;
+ uint32_t freq = clock_get_hz(s->clk) / prescaler;
+ return ((float)ticks / (float)freq) * NANOSECONDS_PER_SECOND;
+}
+
+static uint16_t get_timer_width(void *opaque)
+{
+ TM4C123GPTMState *s = opaque;
+ switch (s->mmio.addr) {
+ case TIMER0_32...TIMER5_32:
+ return TIMER_WIDTH_32;
+ case TIMER0_64...TIMER5_64:
+ return TIMER_WIDTH_64;
+ }
+ return 0;
+}
+
+static uint64_t build_interval_value(void *opaque)
+{
+ TM4C123GPTMState *s = opaque;
+ uint16_t timer_width = get_timer_width(s);
+ uint64_t interval_value = 0;
+ if (timer_width == TIMER_WIDTH_32) {
+ /* timer is in 32 bit mode or 32bit rtc*/
+ uint16_t upper16 = extract32(s->gptm_talir, 16, 16);
+ uint16_t lower16 = extract32(s->gptm_tblir, 0, 16);
+ interval_value = ((uint32_t)lower16 << 16) + upper16;
+ } else if (timer_width == TIMER_WIDTH_64) {
+ interval_value = ((uint64_t)s->gptm_talir << 32) + s->gptm_tblir;
+ }
+
+ trace_tm4c123_gptm_build_interval_value(s->gptm_talir, s->gptm_tblir, interval_value);
+ return interval_value;
+}
+
+static void set_timers(void *opaque)
+{
+ TM4C123GPTMState *s = opaque;
+ uint64_t interval_value;
+ uint16_t timer_width;
+ if (s->gptm_ctl & GPTM_TACTL_EN) {
+ timer_width = get_timer_width(s);
+ if (timer_width == TIMER_WIDTH_32) {
+ /* What is the mode of the timer? 16/32 */
+ if (s->gptm_cfg == 0x4) {
+ /* 16 bit mode */
+ interval_value = extract32(s->gptm_talir, 0, 16);
+ /* Start the timer? */
+ timer_mod(s->a, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks_to_time_ns(s, interval_value, s->gptm_tapr));
+ } else if (s->gptm_cfg == 0x1) {
+ /* 32 bit mode rtc */
+ interval_value = build_interval_value(s);
+ timer_mod(s->a, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ticks_to_time_ns(s, interval_value, s->gptm_tapr));
+ } else if (s->gptm_cfg == 0x0) {
+ /* 32 bit mode rtc */
+ interval_value = build_interval_value(s);
+ timer_mod(s->a, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks_to_time_ns(s, interval_value, s->gptm_tapr));
+ }
+ } else if (timer_width == TIMER_WIDTH_64) {
+ /* What is the mode of the timer? 32/64 */
+ if (s->gptm_cfg == 0) {
+ /* 64 bit mode */
+ interval_value = build_interval_value(s);
+ timer_mod(s->a, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks_to_time_ns(s, interval_value, s->gptm_tapr));
+ } else if (s->gptm_cfg == 0x1) {
+ /* 64 bit mode */
+ interval_value = build_interval_value(s);
+ timer_mod(s->a, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ticks_to_time_ns(s, interval_value, s->gptm_tapr));
+ } else if (s->gptm_cfg == 0x4) {
+ interval_value = s->gptm_talir;
+ timer_mod(s->a, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ticks_to_time_ns(s, interval_value, s->gptm_tapr));
+ }
+ }
+ } else if (s->gptm_ctl & GPTM_TBCTL_EN) {
+ timer_width = get_timer_width(s);
+ if (timer_width == TIMER_WIDTH_32) {
+ /* What is the mode of the timer? 16/32 */
+ if (s->gptm_cfg == 0x4) {
+ /* 16 bit mode */
+ interval_value = extract32(s->gptm_tblir, 0, 16);
+ /* Start the timer? */
+ timer_mod(s->b, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks_to_time_ns(s, interval_value, s->gptm_tbpr));
+ } else if (s->gptm_cfg == 0x01) {
+ /* 32 bit mode rtc */
+ interval_value = build_interval_value(s);
+ timer_mod(s->b,
+ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ticks_to_time_ns(s, interval_value, s->gptm_tbpr));
+ } else if (s->gptm_cfg == 0x00) {
+ /* 32 bit mode rtc */
+ interval_value = build_interval_value(s);
+ timer_mod(s->b,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks_to_time_ns(s, interval_value, s->gptm_tbpr));
+ }
+ } else if (timer_width == TIMER_WIDTH_64) {
+ /* What is the mode of the timer? 32/64 */
+ if (s->gptm_cfg == 0) {
+ /* 64 bit mode */
+ interval_value = build_interval_value(s);
+ timer_mod(s->b,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks_to_time_ns(s, interval_value, s->gptm_tbpr));
+ } else if (s->gptm_cfg == 0x1) {
+ /* 64 bit mode */
+ interval_value = build_interval_value(s);
+ timer_mod(s->b,
+ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ticks_to_time_ns(s, interval_value, s->gptm_tbpr));
+ } else if (s->gptm_cfg == 0x4) {
+ interval_value = s->gptm_tblir;
+ timer_mod(s->b,
+ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ticks_to_time_ns(s, interval_value, s->gptm_tbpr));
+ }
+ }
+ }
+}
+
+static bool gptm_clock_enabled(TM4C123SysCtlState *s, hwaddr addr)
+{
+ switch (addr) {
+ case TIMER0_32:
+ return test_bit(0, (const unsigned long *)&s->sysctl_rcgctimer);
+ break;
+ case TIMER1_32:
+ return test_bit(1, (const unsigned long *)&s->sysctl_rcgctimer);
+ break;
+ case TIMER2_32:
+ return test_bit(2, (const unsigned long *)&s->sysctl_rcgctimer);
+ break;
+ case TIMER3_32:
+ return test_bit(3, (const unsigned long *)&s->sysctl_rcgctimer);
+ break;
+ case TIMER4_32:
+ return test_bit(4, (const unsigned long *)&s->sysctl_rcgctimer);
+ break;
+ case TIMER5_32:
+ return test_bit(5, (const unsigned long *)&s->sysctl_rcgctimer);
+ break;
+ case TIMER0_64:
+ return test_bit(0, (const unsigned long *)&s->sysctl_rcgcwtimer);
+ break;
+ case TIMER1_64:
+ return test_bit(1, (const unsigned long *)&s->sysctl_rcgcwtimer);
+ break;
+ case TIMER2_64:
+ return test_bit(2, (const unsigned long *)&s->sysctl_rcgcwtimer);
+ break;
+ case TIMER3_64:
+ return test_bit(3, (const unsigned long *)&s->sysctl_rcgcwtimer);
+ break;
+ case TIMER4_64:
+ return test_bit(4, (const unsigned long *)&s->sysctl_rcgcwtimer);
+ break;
+ case TIMER5_64:
+ return test_bit(5, (const unsigned long *)&s->sysctl_rcgcwtimer);
+ break;
+ }
+ return false;
+}
+
+static void tm4c123_gptm_reset(DeviceState *dev)
+{
+ TM4C123GPTMState *s = TM4C123_GPTM(dev);
+
+ s->gptm_cfg = 0x00000000;
+ s->gptm_amr = 0x00000000;
+ s->gptm_bmr = 0x00000000;
+ s->gptm_ctl = 0x00000000;
+ s->gptm_sync = 0x00000000;
+ s->gptm_imr = 0x00000000;
+ s->gptm_ris = 0x00000000;
+ s->gptm_mis = 0x00000000;
+ s->gptm_icr = 0x00000000;
+ s->gptm_talir = 0xFFFFFFFF;
+ s->gptm_tblir = 0x00000000;
+ s->gptm_tamatchr = 0xFFFFFFFF;
+ s->gptm_tbmatchr = 0x00000000;
+ s->gptm_tapr = 0x00000000;
+ s->gptm_tbpr = 0x00000000;
+ s->gptm_tapmr = 0x00000000;
+ s->gptm_tbpmr = 0x00000000;
+ s->gptm_tar = 0xFFFFFFFF;
+ s->gptm_tbr = 0x00000000;
+ s->gptm_tav = 0xFFFFFFFF;
+ s->gptm_tbv = 0x00000000;
+ s->gptm_rtcpd = 0x00007FFF;
+ s->gptm_taps = 0x00000000;
+ s->gptm_tbps = 0x00000000;
+ s->gptm_tapv = 0x00000000;
+ s->gptm_tbpv = 0x00000000;
+ s->gptm_pp = 0x00000000;
+}
+
+static uint64_t tm4c123_gptm_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ TM4C123GPTMState *s = opaque;
+
+ if (!gptm_clock_enabled(s->sysctl, s->mmio.addr)) {
+ hw_error("GPTM module clock is not enabled");
+ }
+
+ trace_tm4c123_gptm_read(addr);
+
+ switch (addr) {
+ case GPTM_CFG:
+ return s->gptm_cfg;
+ case GPTM_AMR:
+ return s->gptm_amr;
+ case GPTM_BMR:
+ return s->gptm_bmr;
+ case GPTM_CTL:
+ return s->gptm_ctl;
+ case GPTM_SYNC:
+ return s->gptm_sync;
+ case GPTM_IMR:
+ return s->gptm_imr;
+ case GPTM_RIS:
+ return s->gptm_ris;
+ case GPTM_MIS:
+ return s->gptm_mis;
+ case GPTM_ICR:
+ return s->gptm_icr;
+ case GPTM_TALIR:
+ return s->gptm_talir;
+ case GPTM_TBLIR:
+ return s->gptm_tblir;
+ case GPTM_TAMATCHR:
+ return s->gptm_tamatchr;
+ case GPTM_TBMATCHR:
+ return s->gptm_tbmatchr;
+ case GPTM_TAPR:
+ return s->gptm_tapr;
+ case GPTM_TBPR:
+ return s->gptm_tbpr;
+ case GPTM_TAPMR:
+ return s->gptm_tapmr;
+ case GPTM_TBPMR:
+ return s->gptm_tbpmr;
+ case GPTM_TAR:
+ return s->gptm_tar;
+ case GPTM_TBR:
+ return s->gptm_tbr;
+ case GPTM_TAV:
+ if (get_timer_width(s) == TIMER_WIDTH_64 && s->gptm_cfg == 0) {
+ return extract64(
+ ns_to_ticks(s, s->a->expire_time - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), s->gptm_tapr),
+ 0, 31);
+ } else {
+ return ns_to_ticks(s, s->a->expire_time - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), s->gptm_tapr);
+ }
+ case GPTM_TBV:
+ if (get_timer_width(s) == TIMER_WIDTH_64 && s->gptm_cfg == 0) {
+ return extract64(
+ ns_to_ticks(s, s->a->expire_time - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), s->gptm_tapr),
+ 32, 64);
+ } else {
+ return ns_to_ticks(s, s->b->expire_time - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), s->gptm_tapr);
+ }
+ case GPTM_RTCPD:
+ return s->gptm_rtcpd;
+ case GPTM_TAPS:
+ return s->gptm_taps;
+ case GPTM_TBPS:
+ return s->gptm_tbps;
+ case GPTM_TAPV:
+ return s->gptm_tapv;
+ case GPTM_TBPV:
+ return s->gptm_tbpv;
+ case GPTM_PP:
+ return s->gptm_pp;
+ default:
+ LOG(LOG_GUEST_ERROR, "Bad address 0x%"HWADDR_PRIx"\n", addr);
+ }
+
+ return 0;
+}
+
+static void tm4c123_gptm_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size)
+{
+ TM4C123GPTMState *s = opaque;
+ uint32_t val32 = val64;
+
+ if (!gptm_clock_enabled(s->sysctl, s->mmio.addr)) {
+ hw_error("GPTM module clock is not enabled");
+ }
+
+ trace_tm4c123_gptm_write(addr, val32);
+
+ switch (addr) {
+ case GPTM_CFG:
+ s->gptm_cfg = val32;
+ break;
+ case GPTM_AMR:
+ s->gptm_amr = val32;
+ break;
+ case GPTM_BMR:
+ s->gptm_bmr = val32;
+ break;
+ case GPTM_CTL:
+ s->gptm_ctl = val32;
+ set_timers(s);
+ break;
+ case GPTM_SYNC:
+ s->gptm_sync = val32;
+ break;
+ case GPTM_IMR:
+ s->gptm_imr = val32;
+ break;
+ case GPTM_RIS:
+ READONLY;
+ break;
+ case GPTM_MIS:
+ s->gptm_mis = val32;
+ break;
+ case GPTM_ICR:
+ s->gptm_ris &= ~val32;
+ s->gptm_mis &= ~val32;
+ break;
+ case GPTM_TALIR:
+ s->gptm_talir = val32;
+ break;
+ case GPTM_TBLIR:
+ s->gptm_tblir = val32;
+ break;
+ case GPTM_TAMATCHR:
+ s->gptm_tamatchr = val32;
+ break;
+ case GPTM_TBMATCHR:
+ s->gptm_tbmatchr = val32;
+ break;
+ case GPTM_TAPR:
+ s->gptm_tapr = val32;
+ break;
+ case GPTM_TBPR:
+ s->gptm_tbpr = val32;
+ break;
+ case GPTM_TAPMR:
+ s->gptm_tapmr = val32;
+ break;
+ case GPTM_TBPMR:
+ s->gptm_tbpmr = val32;
+ break;
+ case GPTM_TAR:
+ READONLY;
+ break;
+ case GPTM_TBR:
+ READONLY;
+ break;
+ case GPTM_TAV:
+ s->gptm_tav = val32;
+ break;
+ case GPTM_TBV:
+ s->gptm_tbv = val32;
+ break;
+ case GPTM_RTCPD:
+ READONLY;
+ break;
+ case GPTM_TAPS:
+ READONLY;
+ break;
+ case GPTM_TBPS:
+ READONLY;
+ break;
+ case GPTM_TAPV:
+ READONLY;
+ break;
+ case GPTM_TBPV:
+ READONLY;
+ break;
+ case GPTM_PP:
+ READONLY;
+ break;
+ default:
+ LOG(LOG_GUEST_ERROR, "Bad address 0x%"HWADDR_PRIx"\n", addr);
+ }
+}
+
+static const MemoryRegionOps tm4c123_gptm_ops = {
+ .read = tm4c123_gptm_read,
+ .write = tm4c123_gptm_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void timer_a_callback(void *opaque)
+{
+ TM4C123GPTMState *s = opaque;
+
+ if (test_bit(0, (unsigned long *)&s->gptm_imr)) {
+ qemu_irq_pulse(s->irq_a);
+ set_bit(0, (unsigned long *)&s->gptm_mis);
+ }
+ set_bit(0, (unsigned long *)&s->gptm_ris);
+ if ((s->gptm_amr & 0x0000000F) == 0x2) {
+ set_timers(s);
+ }
+}
+
+static void timer_b_callback(void *opaque)
+{
+ TM4C123GPTMState *s = opaque;
+
+ if (test_bit(8, (unsigned long *)&s->gptm_imr)) {
+ qemu_irq_pulse(s->irq_b);
+ set_bit(8, (unsigned long *)&s->gptm_mis);
+ }
+ set_bit(8, (unsigned long *)&s->gptm_ris);
+ if ((s->gptm_bmr & 0x0000000F) == 0x2) {
+ set_timers(s);
+ }
+}
+
+static void tm4c123_gptm_init(Object *obj)
+{
+ TM4C123GPTMState *s = TM4C123_GPTM(obj);
+ s->clk = qdev_init_clock_in(DEVICE(s), "gptm_clock", NULL, NULL, 0);
+ s->a = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_a_callback, s);
+ s->b = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_b_callback, s);
+ timer_init_ns(s->a, QEMU_CLOCK_VIRTUAL, timer_a_callback, s);
+ timer_init_ns(s->b, QEMU_CLOCK_VIRTUAL, timer_b_callback, s);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq_a);
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq_b);
+ memory_region_init_io(&s->mmio, obj, &tm4c123_gptm_ops, s, TYPE_TM4C123_GPTM, 0xFFF);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void tm4c123_gptm_realize(DeviceState *dev, Error **errp)
+{
+ TM4C123GPTMState *s = TM4C123_GPTM(dev);
+ qdev_connect_clock_in(dev, "gptm_clock", qdev_get_clock_out(DEVICE(s->sysctl), "outclk"));
+
+}
+
+static void tm4c123_gptm_class_init(ObjectClass *kclass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(kclass);
+ dc->reset = tm4c123_gptm_reset;
+ dc->realize = tm4c123_gptm_realize;
+}
+
+static const TypeInfo tm4c123_gptm_info = {
+ .name = TYPE_TM4C123_GPTM,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TM4C123GPTMState),
+ .instance_init = tm4c123_gptm_init,
+ .class_init = tm4c123_gptm_class_init,
+};
+
+static void tm4c123_gptm_register_types(void)
+{
+ type_register_static(&tm4c123_gptm_info);
+}
+
+type_init(tm4c123_gptm_register_types)
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 3eccef8385..e40b445630 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -1,5 +1,10 @@
# See docs/devel/tracing.rst for syntax documentation.
+# tm4c123_gptm.c
+tm4c123_gptm_read(uint32_t offset) "offset: 0x%"PRIx32
+tm4c123_gptm_write(uint32_t offset, uint32_t value) "offset: 0x%"PRIx32" - value: 0x%"PRIx32
+tm4c123_gptm_build_interval_value(uint32_t talir, uint32_t tblir, uint64_t result) "TALIR: 0x%"PRIx32" - TBLIR: 0x%"PRIx32" - value: 0x%"PRIx64
+
# slavio_timer.c
slavio_timer_get_out(uint64_t limit, uint32_t counthigh, uint32_t count) "limit 0x%"PRIx64" count 0x%x0x%08x"
slavio_timer_irq(uint32_t counthigh, uint32_t count) "callback: count 0x%x0x%08x"
diff --git a/include/hw/timer/tm4c123_gptm.h b/include/hw/timer/tm4c123_gptm.h
new file mode 100644
index 0000000000..e86049f5c1
--- /dev/null
+++ b/include/hw/timer/tm4c123_gptm.h
@@ -0,0 +1,131 @@
+/*
+ * TM4C123 General purpose timers
+ *
+ * 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_GPTM_H
+#define HW_ARM_TM4C123_GPTM_H
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/misc/tm4c123_sysctl.h"
+#include "qemu/bitops.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "qom/object.h"
+
+#define TIMER_WIDTH_32 0x32B
+#define TIMER_WIDTH_64 0x64B
+
+#define TIMER0_32 0x40030000
+#define TIMER1_32 0x40031000
+#define TIMER2_32 0x40032000
+#define TIMER3_32 0x40033000
+#define TIMER4_32 0x40034000
+#define TIMER5_32 0x40035000
+
+#define TIMER0_64 0x40036000
+#define TIMER1_64 0x40037000
+#define TIMER2_64 0x4003C000
+#define TIMER3_64 0x4003D000
+#define TIMER4_64 0x4003E000
+#define TIMER5_64 0x4003F000
+
+#define GPTM_CFG 0x000
+#define GPTM_AMR 0x004
+#define GPTM_BMR 0x008
+#define GPTM_CTL 0x00C
+#define GPTM_SYNC 0x010
+#define GPTM_IMR 0x018
+#define GPTM_RIS 0x01C
+#define GPTM_MIS 0x020
+#define GPTM_ICR 0x024
+#define GPTM_TALIR 0x028
+#define GPTM_TBLIR 0x02C
+#define GPTM_TAMATCHR 0x030
+#define GPTM_TBMATCHR 0x034
+#define GPTM_TAPR 0x038
+#define GPTM_TBPR 0x03C
+#define GPTM_TAPMR 0x040
+#define GPTM_TBPMR 0x044
+#define GPTM_TAR 0x048
+#define GPTM_TBR 0x04C
+#define GPTM_TAV 0x050
+#define GPTM_TBV 0x054
+#define GPTM_RTCPD 0x058
+#define GPTM_TAPS 0x05C
+#define GPTM_TBPS 0x060
+#define GPTM_TAPV 0x064
+#define GPTM_TBPV 0x068
+#define GPTM_PP 0xFC0
+
+#define GPTM_TACTL_EN (1 << 0)
+#define GPTM_TBCTL_EN (1 << 8)
+#define GPTM_TAM_CD (1 << 4)
+#define GPTM_TAM_MODE_ONESHOT (1 << 1)
+#define GPTM_TAM_PERIODIC (1 << 2)
+
+#define TYPE_TM4C123_GPTM "tm4c123-gptm"
+
+OBJECT_DECLARE_SIMPLE_TYPE(TM4C123GPTMState, TM4C123_GPTM)
+
+struct TM4C123GPTMState {
+ SysBusDevice parent_obj;
+ MemoryRegion mmio;
+ qemu_irq irq_a;
+ qemu_irq irq_b;
+ TM4C123SysCtlState *sysctl;
+
+ uint32_t gptm_cfg;
+ uint32_t gptm_amr;
+ uint32_t gptm_bmr;
+ uint32_t gptm_ctl;
+ uint32_t gptm_sync;
+ uint32_t gptm_imr;
+ uint32_t gptm_ris;
+ uint32_t gptm_mis;
+ uint32_t gptm_icr;
+ uint32_t gptm_talir;
+ uint32_t gptm_tblir;
+ uint32_t gptm_tamatchr;
+ uint32_t gptm_tbmatchr;
+ uint32_t gptm_tapr;
+ uint32_t gptm_tbpr;
+ uint32_t gptm_tapmr;
+ uint32_t gptm_tbpmr;
+ uint32_t gptm_tar;
+ uint32_t gptm_tbr;
+ uint32_t gptm_tav;
+ uint32_t gptm_tbv;
+ uint32_t gptm_rtcpd;
+ uint32_t gptm_taps;
+ uint32_t gptm_tbps;
+ uint32_t gptm_tapv;
+ uint32_t gptm_tbpv;
+ uint32_t gptm_pp;
+ QEMUTimer *a;
+ QEMUTimer *b;
+ Clock* clk;
+};
+
+#endif
--
2.34.1
next prev parent reply other threads:[~2023-05-17 8:14 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-17 8:11 [PATCH 0/8] Tiva C Implementation Mohamed ElSayed
2023-05-17 8:11 ` [PATCH 1/8] The tivac board initial machine definition Mohamed ElSayed
2023-06-08 13:15 ` Peter Maydell
2023-05-17 8:11 ` [PATCH 2/8] tiva c usart module implementation Mohamed ElSayed
2023-06-08 13:36 ` Peter Maydell
2023-05-17 8:11 ` [PATCH 3/8] tiva c gpio implementation Mohamed ElSayed
2023-06-08 13:37 ` Peter Maydell
2023-05-17 8:12 ` [PATCH 4/8] tiva c sysctl implementation Mohamed ElSayed
2023-06-08 13:58 ` Peter Maydell
2023-05-17 8:12 ` [PATCH 5/8] tiva c watchdog timers implementation Mohamed ElSayed
2023-06-08 14:05 ` Peter Maydell
2023-05-17 8:12 ` Mohamed ElSayed [this message]
2023-06-08 14:28 ` [PATCH 6/8] tiva c general purpose " Peter Maydell
2023-05-17 8:12 ` [PATCH 7/8] tiva c board documentation Mohamed ElSayed
2023-06-08 14:11 ` Peter Maydell
2023-05-17 8:12 ` [PATCH 8/8] adding tiva c to the qemu build system and adding my info to the maintainers list Mohamed ElSayed
2023-06-08 14:16 ` Peter Maydell
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=20230517081204.30333-7-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 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).