* [PULL 1/8] the tivac machine def init commit
2023-05-16 7:29 [PULL SUBSYSTEM arm 0/8] TivaC Implementation Mohamed ElSayed
@ 2023-05-16 7:29 ` Mohamed ElSayed
2023-05-16 7:29 ` [PULL 2/8] tivac usart module implementation Mohamed ElSayed
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Mohamed ElSayed @ 2023-05-16 7:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Mohamed ElSayed
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
hw/arm/tivac.c | 56 ++++++
hw/arm/tm4c123gh6pm_soc.c | 274 ++++++++++++++++++++++++++++++
include/hw/arm/tm4c123gh6pm_soc.h | 71 ++++++++
3 files changed, 401 insertions(+)
create mode 100644 hw/arm/tivac.c
create mode 100644 hw/arm/tm4c123gh6pm_soc.c
create mode 100644 include/hw/arm/tm4c123gh6pm_soc.h
diff --git a/hw/arm/tivac.c b/hw/arm/tivac.c
new file mode 100644
index 0000000000..5d917a8f9e
--- /dev/null
+++ b/hw/arm/tivac.c
@@ -0,0 +1,56 @@
+/*
+ * TivaC Board Implementation
+ *
+ * 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 "qapi/error.h"
+#include "hw/boards.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-clock.h"
+#include "qemu/error-report.h"
+#include "hw/arm/tm4c123gh6pm_soc.h"
+#include "hw/arm/boot.h"
+
+
+/* Main SYSCLK frequency in Hz (24MHz) */
+#define SYSCLK_FRQ 24000000ULL
+
+static void tivac_init(MachineState *machine)
+{
+ DeviceState *dev;
+ dev = qdev_new(TYPE_TM4C123GH6PM_SOC);
+
+ qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+ armv7m_load_kernel(ARM_CPU(first_cpu),
+ machine->kernel_filename,
+ 0, FLASH_SIZE);
+}
+
+static void tivac_machine_init(MachineClass *mc)
+{
+ mc->desc = "Tiva C (Cortex-M4)";
+ mc->init = tivac_init;
+}
+DEFINE_MACHINE("tivac", tivac_machine_init)
diff --git a/hw/arm/tm4c123gh6pm_soc.c b/hw/arm/tm4c123gh6pm_soc.c
new file mode 100644
index 0000000000..da08eefc33
--- /dev/null
+++ b/hw/arm/tm4c123gh6pm_soc.c
@@ -0,0 +1,274 @@
+/*
+ * TM4C123GH6PM SoC
+ *
+ * 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 "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/arm/boot.h"
+#include "exec/address-spaces.h"
+#include "hw/arm/tm4c123gh6pm_soc.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-clock.h"
+#include "hw/misc/unimp.h"
+#include "sysemu/sysemu.h"
+
+static const uint32_t gpio_addrs[GPIO_COUNT] = {
+ 0x40004000,
+ 0x40005000,
+ 0x40006000,
+ 0x40007000,
+ 0x40024000,
+ 0x40025000
+};
+
+static const uint32_t usart_addrs[USART_COUNT] = {
+ 0x4000C000,
+ 0x4000D000,
+ 0x4000E000,
+ 0x4000F000,
+ 0x40010000,
+ 0x40011000,
+ 0x40012000,
+ 0x40013000
+};
+
+static const uint32_t wdt_addrs[WDT_COUNT] = {
+ 0x40000000,
+ 0x40001000
+};
+
+static const uint32_t gptm_addrs[GPTM_COUNT] = {
+ 0x40030000,
+ 0x40031000,
+ 0x40032000,
+ 0x40033000,
+ 0x40034000,
+ 0x40035000,
+ 0x40036000,
+ 0x40037000,
+ 0x4003C800,
+ 0x4003D000,
+ 0x4003E000,
+ 0x4003F000,
+};
+
+static const uint16_t usart_irqs[USART_COUNT] = {5, 6, 33, 59, 60, 61, 62, 63};
+static const uint16_t gpio_irqs[GPIO_COUNT] = {0, 1, 2, 3, 4, 30};
+static const uint16_t wdt_irqs[WDT_COUNT] = {18, 18};
+static const uint16_t gptm_irqs[GPTM_COUNT * 2] = {
+ 19, 20, 21, 22, 23, 24, 35, 36, 70, 71, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105};
+
+static void tm4c123gh6pm_soc_initfn(Object *obj)
+{
+ int i;
+ TM4C123GH6PMState *s = TM4C123GH6PM_SOC(obj);
+
+ object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M);
+ object_initialize_child(obj, "sysctl", &s->sysctl, TYPE_TM4C123_SYSCTL);
+
+ for (i = 0; i < USART_COUNT; i++) {
+ object_initialize_child(obj, "usart[*]", &s->usart[i], TYPE_TM4C123_USART);
+ }
+
+ for (i = 0; i < GPIO_COUNT; i++) {
+ object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_TM4C123_GPIO);
+ }
+
+ for (i = 0; i < WDT_COUNT; i++) {
+ object_initialize_child(obj, "watchdog-timer[*]", &s->wdt[i], TYPE_TM4C123_WATCHDOG);
+ }
+
+ for (i = 0; i < GPTM_COUNT; i++) {
+ object_initialize_child(obj, "gptm[*]", &s->gptm[i], TYPE_TM4C123_GPTM);
+ }
+}
+
+static void tm4c123gh6pm_soc_realize(DeviceState *dev_soc, Error **errp)
+{
+ TM4C123GH6PMState *s = TM4C123GH6PM_SOC(dev_soc);
+ DeviceState *armv7m;
+ DeviceState *dev;
+ SysBusDevice *busdev;
+ int i;
+
+ MemoryRegion *system_memory = get_system_memory();
+
+ //init flash memory
+ memory_region_init_rom(
+ &s->flash, OBJECT(dev_soc),
+ "TM4C123GH6PM.flash", FLASH_SIZE, &error_fatal
+ );
+ memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash);
+
+ //init sram and the sram alias region
+ memory_region_init_ram(
+ &s->sram, OBJECT(dev_soc),
+ "TM4C123GH6PM.sram", SRAM_SIZE, &error_fatal);
+ memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
+
+ /* Init ARMv7m */
+ armv7m = DEVICE(&s->armv7m);
+ qdev_prop_set_uint32(armv7m, "num-irq", 138);
+ qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
+ qdev_prop_set_bit(armv7m, "enable-bitband", true);
+ qdev_connect_clock_in(armv7m, "cpuclk", s->sysctl.mainclk);
+ qdev_connect_clock_in(armv7m, "refclk", s->sysctl.mainclk);
+ object_property_set_link(OBJECT(&s->armv7m), "memory",
+ OBJECT(get_system_memory()), &error_abort);
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
+ return;
+ }
+
+ /* USART */
+ for (i = 0; i < USART_COUNT; i++) {
+ dev = DEVICE(&(s->usart[i]));
+ s->usart[i].sysctl = &s->sysctl;
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->usart[i]), errp)) {
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, usart_addrs[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irqs[i]));
+ }
+
+ /* GPIO */
+ for (i = 0; i < GPIO_COUNT; i++) {
+ dev = DEVICE(&(s->gpio[i]));
+ s->gpio[i].sysctl = &s->sysctl;
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), errp)) {
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, gpio_addrs[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, gpio_irqs[i]));
+ }
+
+ /* Watchdog Timers */
+ for (i = 0; i < WDT_COUNT; i++) {
+ dev = DEVICE(&(s->wdt[i]));
+ s->wdt[i].sysctl = &s->sysctl;
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, wdt_addrs[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, wdt_irqs[i]));
+ }
+
+ /* General purpose timers */
+ int j = 0;
+ for (i = 0, j = 0; i < GPTM_COUNT; i++, j+=2) {
+ dev = DEVICE(&(s->gptm[i]));
+ s->gptm[i].sysctl = &s->sysctl;
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gptm[i]), errp)) {
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, gptm_addrs[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, gptm_irqs[j]));
+ sysbus_connect_irq(busdev, 1, qdev_get_gpio_in(armv7m, gptm_irqs[j+1]));
+ }
+
+ /* SYSCTL */
+ dev = DEVICE(&(s->sysctl));
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysctl), errp)) {
+ return;
+ }
+ busdev = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(busdev, 0, SYSCTL_ADDR);
+
+
+ create_unimplemented_device("SSI_0", 0x40008000, 0xFFF);
+ create_unimplemented_device("SSI_1", 0x40009000, 0xFFF);
+ create_unimplemented_device("SSI_2", 0x4000A000, 0xFFF);
+ create_unimplemented_device("SSI_3", 0x4000B000, 0xFFF);
+
+ create_unimplemented_device("I2C_0", 0x40020000, 0xFFF);
+ create_unimplemented_device("I2C_1", 0x40021000, 0xFFF);
+ create_unimplemented_device("I2C_2", 0x40022000, 0xFFF);
+ create_unimplemented_device("I2C_3", 0x40023000, 0xFFF);
+
+ create_unimplemented_device("PWM_0", 0x40028000, 0xFFF);
+ create_unimplemented_device("PWM_1", 0x40029000, 0xFFF);
+
+ create_unimplemented_device("QEI_0", 0x4002C000, 0xFFF);
+ create_unimplemented_device("QEI_1", 0x4002D000, 0xFFF);
+
+ create_unimplemented_device("ADC_0", 0x40038000, 0xFFF);
+ create_unimplemented_device("ADC_1", 0x40039000, 0xFFF);
+
+ create_unimplemented_device("ANALOG_CMP", 0x4003C000, 0xFFF);
+
+ create_unimplemented_device("CAN_0", 0x40040000, 0xFFF);
+ create_unimplemented_device("CAN_1", 0x40041000, 0xFFF);
+
+ create_unimplemented_device("USB", 0x40050000, 0xFFF);
+
+ create_unimplemented_device("GPIO_A_AHB", 0x40058000, 0xFFF);
+ create_unimplemented_device("GPIO_B_AHB", 0x40059000, 0xFFF);
+ create_unimplemented_device("GPIO_C_AHB", 0x4005A000, 0xFFF);
+ create_unimplemented_device("GPIO_D_AHB", 0x4005B000, 0xFFF);
+ create_unimplemented_device("GPIO_E_AHB", 0x4005C000, 0xFFF);
+ create_unimplemented_device("GPIO_F_AHB", 0x4005D000, 0xFFF);
+
+ create_unimplemented_device("EEPROM", 0x400AF000, 0xFFF);
+ create_unimplemented_device("SYS_EXC", 0x400F9000, 0xFFF);
+ create_unimplemented_device("HIBERNATION_MOD", 0x400FC000, 0xFFF);
+ create_unimplemented_device("FLASH_CONT", 0x400FD000, 0xFFF);
+ create_unimplemented_device("SYS_CONT", 0x400FE000, 0xFFF);
+
+ create_unimplemented_device("uDMA", 0x400FF000, 0xFFF);
+}
+
+static Property tm4c123gh6pm_soc_properties[] = {
+ DEFINE_PROP_STRING("cpu-type", TM4C123GH6PMState, cpu_type),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tm4c123gh6pm_soc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = tm4c123gh6pm_soc_realize;
+ device_class_set_props(dc, tm4c123gh6pm_soc_properties);
+}
+
+static const TypeInfo tm4c123gh6pm_soc_info = {
+ .name = TYPE_TM4C123GH6PM_SOC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TM4C123GH6PMState),
+ .instance_init = tm4c123gh6pm_soc_initfn,
+ .class_init = tm4c123gh6pm_soc_class_init,
+};
+
+static void tm4c123gh6pm_soc_types(void)
+{
+ type_register_static(&tm4c123gh6pm_soc_info);
+}
+
+
+type_init(tm4c123gh6pm_soc_types)
diff --git a/include/hw/arm/tm4c123gh6pm_soc.h b/include/hw/arm/tm4c123gh6pm_soc.h
new file mode 100644
index 0000000000..1841483a78
--- /dev/null
+++ b/include/hw/arm/tm4c123gh6pm_soc.h
@@ -0,0 +1,71 @@
+/*
+ * TM4C123GH6PM SoC
+ *
+ * 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_TM4C123GH6PM_SOC_H
+#define HW_ARM_TM4C123GH6PM_SOC_H
+
+#include "hw/arm/armv7m.h"
+#include "qom/object.h"
+#include "hw/clock.h"
+#include "hw/char/tm4c123_usart.h"
+#include "hw/misc/tm4c123_sysctl.h"
+#include "hw/gpio/tm4c123_gpio.h"
+#include "hw/watchdog/tm4c123_watchdog.h"
+#include "hw/timer/tm4c123_gptm.h"
+
+#define TYPE_TM4C123GH6PM_SOC "tm4c123gh6pm-soc"
+
+OBJECT_DECLARE_SIMPLE_TYPE(TM4C123GH6PMState, TM4C123GH6PM_SOC)
+
+#define FLASH_BASE_ADDRESS 0x00000000
+#define FLASH_SIZE (256 * 1024)
+#define SRAM_BASE_ADDRESS 0x20000000
+#define SRAM_SIZE (32 * 1024)
+
+#define SYSCTL_ADDR 0x400FE000
+
+#define USART_COUNT 8
+#define GPIO_COUNT 6
+#define WDT_COUNT 2
+#define GPTM_COUNT 12
+
+struct TM4C123GH6PMState {
+ SysBusDevice parent_obj;
+
+ char *cpu_type;
+
+ ARMv7MState armv7m;
+
+ TM4C123USARTState usart[USART_COUNT];
+ TM4C123SysCtlState sysctl;
+ TM4C123GPIOState gpio[GPIO_COUNT];
+ TM4C123WatchdogState wdt[WDT_COUNT];
+ TM4C123GPTMState gptm[GPTM_COUNT];
+
+ MemoryRegion sram;
+ MemoryRegion alias_region;
+ MemoryRegion flash;
+};
+
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PULL 2/8] tivac usart module implementation
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
2023-05-16 7:29 ` [PULL 3/8] tivac gpio " Mohamed ElSayed
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Mohamed ElSayed @ 2023-05-16 7:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Mohamed ElSayed
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
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PULL 3/8] tivac gpio module implementation
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 ` [PULL 2/8] tivac usart module implementation Mohamed ElSayed
@ 2023-05-16 7:29 ` Mohamed ElSayed
2023-05-16 7:29 ` [PULL 4/8] tivac system control implementation Mohamed ElSayed
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Mohamed ElSayed @ 2023-05-16 7:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Mohamed ElSayed
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
hw/gpio/tm4c123_gpio.c | 372 +++++++++++++++++++++++++++++++++
include/hw/gpio/tm4c123_gpio.h | 127 +++++++++++
2 files changed, 499 insertions(+)
create mode 100644 hw/gpio/tm4c123_gpio.c
create mode 100644 include/hw/gpio/tm4c123_gpio.h
diff --git a/hw/gpio/tm4c123_gpio.c b/hw/gpio/tm4c123_gpio.c
new file mode 100644
index 0000000000..7fbe04bd77
--- /dev/null
+++ b/hw/gpio/tm4c123_gpio.c
@@ -0,0 +1,372 @@
+/*
+ * TM4C123 GPIO
+ *
+ * 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/gpio/tm4c123_gpio.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/misc/tm4c123_sysctl.h"
+#include "qemu/bitops.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 gpio_clock_enabled(TM4C123SysCtlState *s, hwaddr addr)
+{
+ switch(addr) {
+ case GPIO_A:
+ return test_bit(0, (const unsigned long*)&s->sysctl_rcgcgpio);
+ break;
+ case GPIO_B:
+ return test_bit(1, (const unsigned long*)&s->sysctl_rcgcgpio);
+ break;
+ case GPIO_C:
+ return test_bit(2, (const unsigned long*)&s->sysctl_rcgcgpio);
+ break;
+ case GPIO_D:
+ return test_bit(3, (const unsigned long*)&s->sysctl_rcgcgpio);
+ break;
+ case GPIO_E:
+ return test_bit(4, (const unsigned long*)&s->sysctl_rcgcgpio);
+ break;
+ case GPIO_F:
+ return test_bit(5, (const unsigned long*)&s->sysctl_rcgcgpio);
+ break;
+ }
+ return false;
+}
+
+static void tm4c123_gpio_reset(DeviceState *dev)
+{
+ TM4C123GPIOState *s = TM4C123_GPIO(dev);
+
+ s->gpio_data = 0x00000000;
+ s->gpio_dir = 0x00000000;
+ s->gpio_is = 0x00000000;
+ s->gpio_ibe = 0x00000000;
+ s->gpio_iev = 0x00000000;
+ s->gpio_im = 0x00000000;
+ s->gpio_ris = 0x00000000;
+ s->gpio_mis = 0x00000000;
+ s->gpio_icr = 0x00000000;
+ s->gpio_afsel = 0x00000000;
+ s->gpio_dr2r = 0x000000FF;
+ s->gpio_dr4r = 0x00000000;
+ s->gpio_dr8r = 0x00000000;
+ s->gpio_odr = 0x00000000;
+ s->gpio_pur = 0x00000000;
+ s->gpio_pdr = 0x00000000;
+ s->gpio_slr = 0x00000000;
+ s->gpio_den = 0x00000000;
+ s->gpio_lock = 0x00000001;
+ s->gpio_ocr = 0x00000000;
+ s->gpio_amsel = 0x00000000;
+ s->gpio_pctl = 0x00000000;
+ s->gpio_adcctl = 0x00000000;
+ s->gpio_dmactl = 0x00000000;
+ s->gpio_per_id4 = 0x00000000;
+ s->gpio_per_id5 = 0x00000000;
+ s->gpio_per_id6 = 0x00000000;
+ s->gpio_per_id7 = 0x00000000;
+ s->gpio_per_id0 = 0x00000061;
+ s->gpio_per_id1 = 0x00000000;
+ s->gpio_per_id2 = 0x00000018;
+ s->gpio_per_id3 = 0x00000001;
+ s->gpio_pcell_id0 = 0x0000000D;
+ s->gpio_pcell_id1 = 0x000000F0;
+ s->gpio_pcell_id2 = 0x00000005;
+ s->gpio_pcell_id3 = 0x000000B1;
+}
+
+static void tm4c123_gpio_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size)
+{
+ TM4C123GPIOState *s = opaque;
+ uint32_t val32 = val64;
+
+ if (!gpio_clock_enabled(s->sysctl, s->mmio.addr)) {
+ hw_error("GPIO module clock is not enabled");
+ }
+ trace_tm4c123_gpio_write(addr, val32);
+
+ switch(addr) {
+ case GPIO_DATA:
+ {
+ uint32_t rising_edge = (val32 ^ s->gpio_data) & val32;
+ //level detection
+ s->gpio_mis = s->gpio_is & s->gpio_iev & val32;
+ s->gpio_mis |= s->gpio_is & ~(s->gpio_iev | val32);
+ s->gpio_mis &= s->gpio_im;
+
+ //edge detection
+ //both edges
+ s->gpio_mis |= (s->gpio_is | s->gpio_ibe) & (~s->gpio_is);
+ //rising edge
+ s->gpio_mis |= (~(s->gpio_is | s->gpio_ibe | s->gpio_iev)) & rising_edge;
+ //falling edge
+ s->gpio_mis |= ~(s->gpio_is | s->gpio_ibe | s->gpio_iev | rising_edge);
+ s->gpio_mis &= s->gpio_im;
+ s->gpio_ris |= s->gpio_mis & val32;
+
+ s->gpio_data = val32;
+ if (s->gpio_im != 0)
+ qemu_irq_pulse(s->irq);
+ }
+ break;
+ case GPIO_DIR:
+ s->gpio_dir = val32;
+ break;
+ case GPIO_IS:
+ s->gpio_is = val32;
+ break;
+ case GPIO_IBE:
+ s->gpio_ibe = val32;
+ break;
+ case GPIO_IEV:
+ s->gpio_iev = val32;
+ break;
+ case GPIO_IM:
+ s->gpio_im = val32;
+ break;
+ case GPIO_RIS:
+ s->gpio_ris = val32;
+ break;
+ case GPIO_MIS:
+ READONLY;
+ break;
+ case GPIO_ICR:
+ s->gpio_mis ^= val32;
+ s->gpio_ris ^= val32;
+ s->gpio_icr = val32;
+ break;
+ case GPIO_AFSEL:
+ s->gpio_afsel = val32;
+ break;
+ case GPIO_DR2R:
+ s->gpio_dr2r = val32;
+ break;
+ case GPIO_DR4R:
+ s->gpio_dr4r = val32;
+ break;
+ case GPIO_DR8R:
+ s->gpio_dr8r = val32;
+ break;
+ case GPIO_ODR:
+ s->gpio_odr = val32;
+ break;
+ case GPIO_PUR:
+ s->gpio_pur = val32;
+ break;
+ case GPIO_PDR:
+ s->gpio_pdr = val32;
+ break;
+ case GPIO_SLR:
+ s->gpio_slr = val32;
+ break;
+ case GPIO_DEN:
+ s->gpio_den = val32;
+ break;
+ case GPIO_LOCK:
+ s->gpio_lock = val32;
+ break;
+ case GPIO_OCR:
+ s->gpio_ocr = val32;
+ break;
+ case GPIO_AMSEL:
+ s->gpio_amsel = val32;
+ break;
+ case GPIO_PCTL:
+ s->gpio_pctl = val32;
+ break;
+ case GPIO_ADCCTL:
+ s->gpio_adcctl = val32;
+ break;
+ case GPIO_DMACTL:
+ s->gpio_dmactl = val32;
+ break;
+ case GPIO_PER_ID4:
+ READONLY;
+ break;
+ case GPIO_PER_ID5:
+ READONLY;
+ break;
+ case GPIO_PER_ID6:
+ READONLY;
+ break;
+ case GPIO_PER_ID7:
+ READONLY;
+ break;
+ case GPIO_PER_ID0:
+ READONLY;
+ break;
+ case GPIO_PER_ID1:
+ READONLY;
+ break;
+ case GPIO_PER_ID2:
+ READONLY;
+ break;
+ case GPIO_PER_ID3:
+ READONLY;
+ break;
+ case GPIO_PCELL_ID0:
+ READONLY;
+ break;
+ case GPIO_PCELL_ID1:
+ READONLY;
+ break;
+ case GPIO_PCELL_ID2:
+ READONLY;
+ break;
+ case GPIO_PCELL_ID3:
+ READONLY;
+ break;
+ default:
+ LOG("Bad address 0x%"HWADDR_PRIx"\n", addr);
+ }
+}
+
+static uint64_t tm4c123_gpio_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ TM4C123GPIOState *s = opaque;
+
+ trace_tm4c123_gpio_read(addr);
+
+ if (!gpio_clock_enabled(s->sysctl, s->mmio.addr)) {
+ hw_error("GPIO module clock is not enabled");
+ }
+
+ switch(addr) {
+ case GPIO_DATA:
+ return s->gpio_data;
+ case GPIO_DIR:
+ return s->gpio_dir;
+ case GPIO_IS:
+ return s->gpio_is;
+ case GPIO_IBE:
+ return s->gpio_ibe;
+ case GPIO_IEV:
+ return s->gpio_iev;
+ case GPIO_IM:
+ return s->gpio_im;
+ case GPIO_RIS:
+ return s->gpio_ris;
+ case GPIO_MIS:
+ return s->gpio_mis;
+ case GPIO_ICR:
+ return s->gpio_icr;
+ case GPIO_AFSEL:
+ return s->gpio_afsel;
+ case GPIO_DR2R:
+ return s->gpio_dr2r;
+ case GPIO_DR4R:
+ return s->gpio_dr4r;
+ case GPIO_DR8R:
+ return s->gpio_dr8r;
+ case GPIO_ODR:
+ return s->gpio_odr;
+ case GPIO_PUR:
+ return s->gpio_pur;
+ case GPIO_PDR:
+ return s->gpio_pdr;
+ case GPIO_SLR:
+ return s->gpio_slr;
+ case GPIO_DEN:
+ return s->gpio_den;
+ case GPIO_LOCK:
+ return s->gpio_lock;
+ case GPIO_OCR:
+ return s->gpio_ocr;
+ case GPIO_AMSEL:
+ return s->gpio_amsel;
+ case GPIO_PCTL:
+ return s->gpio_pctl;
+ case GPIO_ADCCTL:
+ return s->gpio_adcctl;
+ case GPIO_DMACTL:
+ return s->gpio_dmactl;
+ case GPIO_PER_ID4:
+ return s->gpio_per_id4;
+ case GPIO_PER_ID5:
+ return s->gpio_per_id5;
+ case GPIO_PER_ID6:
+ return s->gpio_per_id6;
+ case GPIO_PER_ID7:
+ return s->gpio_per_id7;
+ case GPIO_PER_ID0:
+ return s->gpio_per_id0;
+ case GPIO_PER_ID1:
+ return s->gpio_per_id1;
+ case GPIO_PER_ID2:
+ return s->gpio_per_id2;
+ case GPIO_PER_ID3:
+ return s->gpio_per_id3;
+ case GPIO_PCELL_ID0:
+ return s->gpio_pcell_id0;
+ case GPIO_PCELL_ID1:
+ return s->gpio_pcell_id1;
+ case GPIO_PCELL_ID2:
+ return s->gpio_pcell_id2;
+ case GPIO_PCELL_ID3:
+ return s->gpio_pcell_id3;
+ default:
+ LOG("Bad address 0x%"HWADDR_PRIx"\n", addr);
+ }
+ return 0;
+}
+
+static const MemoryRegionOps tm4c123_gpio_ops = {
+ .read = tm4c123_gpio_read,
+ .write = tm4c123_gpio_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void tm4c123_gpio_init(Object *obj)
+{
+ TM4C123GPIOState *s = TM4C123_GPIO(obj);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+ memory_region_init_io(&s->mmio, obj, &tm4c123_gpio_ops, s, TYPE_TM4C123_GPIO, 0xFFF);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void tm4c123_gpio_class_init(ObjectClass *kclass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(kclass);
+ dc->reset = tm4c123_gpio_reset;
+}
+
+static const TypeInfo tm4c123_gpio_info = {
+ .name = TYPE_TM4C123_GPIO,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TM4C123GPIOState),
+ .instance_init = tm4c123_gpio_init,
+ .class_init = tm4c123_gpio_class_init,
+};
+
+static void tm4c123_gpio_register_types(void)
+{
+ type_register_static(&tm4c123_gpio_info);
+}
+
+type_init(tm4c123_gpio_register_types)
diff --git a/include/hw/gpio/tm4c123_gpio.h b/include/hw/gpio/tm4c123_gpio.h
new file mode 100644
index 0000000000..5162e7bd53
--- /dev/null
+++ b/include/hw/gpio/tm4c123_gpio.h
@@ -0,0 +1,127 @@
+/*
+ * TM4C123 GPIO
+ *
+ * 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_GPIO_H
+#define HW_ARM_TM4C123_GPIO_H
+
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "qom/object.h"
+#include "hw/misc/tm4c123_sysctl.h"
+
+/* #define GPIO_DATA 0x00 */
+#define GPIO_DATA 0x3FC
+#define GPIO_DIR 0x400
+#define GPIO_IS 0x404
+#define GPIO_IBE 0x408
+#define GPIO_IEV 0x40C
+#define GPIO_IM 0x410
+#define GPIO_RIS 0x414
+#define GPIO_MIS 0x418
+#define GPIO_ICR 0x41C
+#define GPIO_AFSEL 0x420
+#define GPIO_DR2R 0x500
+#define GPIO_DR4R 0x504
+#define GPIO_DR8R 0x508
+#define GPIO_ODR 0x50C
+#define GPIO_PUR 0x510
+#define GPIO_PDR 0x514
+#define GPIO_SLR 0x518
+#define GPIO_DEN 0x51C
+#define GPIO_LOCK 0x520
+#define GPIO_OCR 0x524
+#define GPIO_AMSEL 0x528
+#define GPIO_PCTL 0x52C
+#define GPIO_ADCCTL 0x530
+#define GPIO_DMACTL 0x534
+#define GPIO_PER_ID4 0xFD0
+#define GPIO_PER_ID5 0xFD4
+#define GPIO_PER_ID6 0xFD8
+#define GPIO_PER_ID7 0xFDC
+#define GPIO_PER_ID0 0XFE0
+#define GPIO_PER_ID1 0xFE4
+#define GPIO_PER_ID2 0xFE8
+#define GPIO_PER_ID3 0xFEC
+#define GPIO_PCELL_ID0 0xFF0
+#define GPIO_PCELL_ID1 0xFF4
+#define GPIO_PCELL_ID2 0xFF8
+#define GPIO_PCELL_ID3 0xFFC
+
+#define GPIO_A 0x40004000
+#define GPIO_B 0x40005000
+#define GPIO_C 0x40006000
+#define GPIO_D 0x40007000
+#define GPIO_E 0x40024000
+#define GPIO_F 0x40025000
+
+#define TYPE_TM4C123_GPIO "tm4c123-gpio"
+
+OBJECT_DECLARE_SIMPLE_TYPE(TM4C123GPIOState, TM4C123_GPIO)
+
+struct TM4C123GPIOState {
+ SysBusDevice parent_obj;
+ MemoryRegion mmio;
+
+ uint32_t gpio_data;
+ uint32_t gpio_dir;
+ uint32_t gpio_is;
+ uint32_t gpio_ibe;
+ uint32_t gpio_iev;
+ uint32_t gpio_im;
+ uint32_t gpio_ris;
+ uint32_t gpio_mis;
+ uint32_t gpio_icr;
+ uint32_t gpio_afsel;
+ uint32_t gpio_dr2r;
+ uint32_t gpio_dr4r;
+ uint32_t gpio_dr8r;
+ uint32_t gpio_odr;
+ uint32_t gpio_pur;
+ uint32_t gpio_pdr;
+ uint32_t gpio_slr;
+ uint32_t gpio_den;
+ uint32_t gpio_lock;
+ uint32_t gpio_ocr;
+ uint32_t gpio_amsel;
+ uint32_t gpio_pctl;
+ uint32_t gpio_adcctl;
+ uint32_t gpio_dmactl;
+ uint32_t gpio_per_id4;
+ uint32_t gpio_per_id5;
+ uint32_t gpio_per_id6;
+ uint32_t gpio_per_id7;
+ uint32_t gpio_per_id0;
+ uint32_t gpio_per_id1;
+ uint32_t gpio_per_id2;
+ uint32_t gpio_per_id3;
+ uint32_t gpio_pcell_id0;
+ uint32_t gpio_pcell_id1;
+ uint32_t gpio_pcell_id2;
+ uint32_t gpio_pcell_id3;
+
+ qemu_irq irq;
+ TM4C123SysCtlState *sysctl;
+};
+
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PULL 4/8] tivac system control implementation
2023-05-16 7:29 [PULL SUBSYSTEM arm 0/8] TivaC Implementation Mohamed ElSayed
` (2 preceding siblings ...)
2023-05-16 7:29 ` [PULL 3/8] tivac gpio " Mohamed ElSayed
@ 2023-05-16 7:29 ` Mohamed ElSayed
2023-05-16 7:29 ` [PULL 5/8] tivac general purpose timers implementation Mohamed ElSayed
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Mohamed ElSayed @ 2023-05-16 7:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Mohamed ElSayed
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
hw/misc/tm4c123_sysctl.c | 989 +++++++++++++++++++++++++++++++
include/hw/misc/tm4c123_sysctl.h | 307 ++++++++++
2 files changed, 1296 insertions(+)
create mode 100644 hw/misc/tm4c123_sysctl.c
create mode 100644 include/hw/misc/tm4c123_sysctl.h
diff --git a/hw/misc/tm4c123_sysctl.c b/hw/misc/tm4c123_sysctl.c
new file mode 100644
index 0000000000..9bce30eb73
--- /dev/null
+++ b/hw/misc/tm4c123_sysctl.c
@@ -0,0 +1,989 @@
+/*
+ * TM4C123 SYSCTL
+ *
+ * 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/misc/tm4c123_sysctl.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 void tm4c123_sysctl_update_system_clock(void *opaque)
+{
+ TM4C123SysCtlState *s = opaque;
+
+ uint32_t RCC_Val = s->sysctl_rcc;
+ uint32_t RCC2_Val = s->sysctl_rcc2;
+
+ uint32_t __CORE_CLK_PRE;
+ uint32_t __CORE_CLK;
+
+ if (RCC2_Val & (1UL << 31)) { /* is rcc2 used? */
+ if (RCC2_Val & (1UL << 11)) { /* check BYPASS */
+ if (((RCC2_Val >> 4) & 0x07) == 0x0) {
+ if (((RCC_Val >> 6) & 0x1F) == 0x0) {
+ __CORE_CLK_PRE = 1000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x1) {
+ __CORE_CLK_PRE = 1843200UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x2) {
+ __CORE_CLK_PRE = 2000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x3) {
+ __CORE_CLK_PRE = 2457600UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x4) {
+ __CORE_CLK_PRE = 3579545UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x5) {
+ __CORE_CLK_PRE = 3686400UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x6) {
+ __CORE_CLK_PRE = 4000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x7) {
+ __CORE_CLK_PRE = 4096000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x8) {
+ __CORE_CLK_PRE = 4915200UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x9) {
+ __CORE_CLK_PRE = 5000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0xA) {
+ __CORE_CLK_PRE = 5120000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0xB) {
+ __CORE_CLK_PRE = 6000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0xC) {
+ __CORE_CLK_PRE = 6144000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0xD) {
+ __CORE_CLK_PRE = 7372800UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0xE) {
+ __CORE_CLK_PRE = 8000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0xF) {
+ __CORE_CLK_PRE = 8192000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x10) {
+ __CORE_CLK_PRE = 10000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x11) {
+ __CORE_CLK_PRE = 12000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x12) {
+ __CORE_CLK_PRE = 12288000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x13) {
+ __CORE_CLK_PRE = 13560000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x14) {
+ __CORE_CLK_PRE = 14318180UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x15) {
+ __CORE_CLK_PRE = 16000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x16) {
+ __CORE_CLK_PRE = 16384000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x17) {
+ __CORE_CLK_PRE = 18000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x18) {
+ __CORE_CLK_PRE = 20000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x19) {
+ __CORE_CLK_PRE = 24000000UL;
+ } else if (((RCC_Val >> 6) & 0x1F) == 0x1A) {
+ __CORE_CLK_PRE = 25000000UL;
+ } else {
+ __CORE_CLK_PRE = 0UL;
+ }
+ __CORE_CLK = __CORE_CLK_PRE / 2UL; /* divide by 2 since BYPASS is set */
+ } else { /* PLL is used */
+ uint32_t __PLL_MULT = ((RCC2_Val >> 4) & 0x1F) + 2;
+ uint32_t __PLL_DIV = ((RCC2_Val >> 0) & 0x3F) + 1;
+ uint32_t __PLL_SOURCE = ((RCC2_Val >> 13) & 0x01);
+ if (__PLL_SOURCE == 0) { /* source is XTAL */
+ __CORE_CLK_PRE = (XTALI * __PLL_MULT) / __PLL_DIV;
+ } else { /* source is internal oscillator */
+ __CORE_CLK_PRE = (16000000UL * __PLL_MULT) / __PLL_DIV; /* internal oscillator frequency is 16MHz */
+ }
+ __CORE_CLK = __CORE_CLK_PRE / 2UL; /* divide by 2 since BYPASS is set */
+ }
+ } else { /* BYPASS is not set */
+ uint32_t __SYS_DIV = ((RCC2_Val >> 22) & 0x7F) + 1;
+ uint32_t __PLL_MULT = ((RCC2_Val >> 4) & 0x1F) + 2;
+ uint32_t __PLL_DIV = ((RCC2_Val >> 0) & 0x3F) + 1;
+ uint32_t __PLL_SOURCE = ((RCC2_Val >> 13) & 0x01);
+ if (__PLL_SOURCE == 0) { /* source is XTAL */
+ __CORE_CLK_PRE = (XTALI * __PLL_MULT) / __PLL_DIV;
+ } else { /* source is internal oscillator */
+ __CORE_CLK_PRE = (16000000UL * __PLL_MULT) / __PLL_DIV; /* internal oscillator frequency is 16MHz */
+ }
+ __CORE_CLK = __CORE_CLK_PRE / __SYS_DIV;
+ }
+ } else { /* rcc2 is not used */
+ if (((RCC_Val >> 16) & 0x01) == 0x01) { /* check USESYSCLK */
+ if (((RCC_Val >> 23) & 0x01) == 0x01) { /* check BYPASS */
+ __CORE_CLK_PRE = XTALI;
+ } else { /* PLL is used */
+ uint32_t __PLL_MULT = ((RCC_Val >> 18) & 0x1F) + 2;
+ uint32_t __PLL_DIV = ((RCC_Val >> 12) & 0x3F) + 1;
+ uint32_t __PLL_SOURCE = ((RCC_Val >> 16) & 0x01);
+ if (__PLL_SOURCE == 0) { /* source is XTAL */
+ __CORE_CLK_PRE = (XTALI * __PLL_MULT) / __PLL_DIV;
+ } else { /* source is internal oscillator */
+ __CORE_CLK_PRE = (16000000UL * __PLL_MULT) / __PLL_DIV; /* internal oscillator frequency is 16MHz */
+ }
+ }
+ } else { /* USESYSCLK bit is not set */
+ __CORE_CLK_PRE = 16000000UL; /* default to internal oscillator frequency */
+ }
+ __CORE_CLK = __CORE_CLK_PRE / 1UL; /* no division needed since BYPASS is not set */
+ }
+ trace_tm4c123_sysctl_update_system_clock(__CORE_CLK);
+ clock_update_hz(s->mainclk, __CORE_CLK);
+}
+
+static void tm4c123_sysctl_reset(DeviceState *dev)
+{
+ TM4C123SysCtlState *s = TM4C123_SYSCTL(dev);
+
+ s->sysctl_did0 = 0x00000000;
+ s->sysctl_did1 = 0x10A1606E;
+ s->sysctl_pborctl = 0x00000000;
+ s->sysctl_ris = 0x00000000;
+ s->sysctl_imc = 0x00000000;
+ s->sysctl_misc = 0x00000000;
+ s->sysctl_resc = 0x00000000;
+ s->sysctl_rcc = 0x078E3AD1;
+ s->sysctl_gpiohbctl = 0x00007E00;
+ s->sysctl_rcc2 = 0x07C06810;
+ s->sysctl_moscctl = 0x00000000;
+ s->sysctl_dslpclkcfg = 0x07800000;
+ s->sysctl_sysprop = 0x00001D31;
+ s->sysctl_piosccal = 0x00000000;
+ s->sysctl_pioscstat = 0x00000040;
+ s->sysctl_pllfreq0 = 0x00000032;
+ s->sysctl_pllfreq1 = 0x00000001;
+ s->sysctl_pllstat = 0x00000000;
+ s->sysctl_slppwrcfg = 0x00000000;
+ s->sysctl_dslppwrcfg = 0x00000000;
+ s->sysctl_ldospctl = 0x00000018;
+ s->sysctl_ldospcal = 0x00001818;
+ s->sysctl_ldodpctl = 0x00000012;
+ s->sysctl_ldodpcal = 0x00001212;
+ s->sysctl_sdpmst = 0x00000000;
+ s->sysctl_ppwd = 0x00000003;
+ s->sysctl_pptimer = 0x0000003F;
+ s->sysctl_ppgpio = 0x0000003F;
+ s->sysctl_ppdma = 0x00000001;
+ s->sysctl_pphib = 0x00000001;
+ s->sysctl_ppuart = 0x000000FF;
+ s->sysctl_ppsi = 0x0000000F;
+ s->sysctl_ppi2c = 0x0000000F;
+ s->sysctl_ppusb = 0x00000001;
+ s->sysctl_ppcan = 0x00000003;
+ s->sysctl_ppadc = 0x00000003;
+ s->sysctl_ppacmp = 0x00000001;
+ s->sysctl_pppwm = 0x00000003;
+ s->sysctl_ppqei = 0x00000003;
+ s->sysctl_ppeeprom = 0x00000001;
+ s->sysctl_ppwtimer = 0x0000003F;
+ s->sysctl_srwd = 0x00000000;
+ s->sysctl_srtimer = 0x00000000;
+ s->sysctl_srgpio = 0x00000000;
+ s->sysctl_srdma = 0x00000000;
+ s->sysctl_srhib = 0x00000000;
+ s->sysctl_sruart = 0x00000000;
+ s->sysctl_srssi = 0x00000000;
+ s->sysctl_sri2c = 0x00000000;
+ s->sysctl_srusb = 0x00000000;
+ s->sysctl_srcan = 0x00000000;
+ s->sysctl_sradc = 0x00000000;
+ s->sysctl_sracmp = 0x00000000;
+ s->sysctl_srpwm = 0x00000000;
+ s->sysctl_srqei = 0x00000000;
+ s->sysctl_sreeprom = 0x00000000;
+ s->sysctl_srwtimer = 0x00000000;
+ s->sysctl_rcgcwd = 0x00000000;
+ s->sysctl_rcgctimer = 0x00000000;
+ s->sysctl_rcgcgpio = 0x00000000;
+ s->sysctl_rcgcdma = 0x00000000;
+ s->sysctl_rcgchib = 0x00000001;
+ s->sysctl_rcgcuart = 0x00000000;
+ s->sysctl_rcgcssi = 0x00000000;
+ s->sysctl_rcgci2c = 0x00000000;
+ s->sysctl_rcgcusb = 0x00000000;
+ s->sysctl_rcgccan = 0x00000000;
+ s->sysctl_rcgcadc = 0x00000000;
+ s->sysctl_rcgcacmp = 0x00000000;
+ s->sysctl_rcgcpwm = 0x00000000;
+ s->sysctl_rcgcqei = 0x00000000;
+ s->sysctl_rcgceeprom = 0x00000000;
+ s->sysctl_rcgcwtimer = 0x00000000;
+ s->sysctl_scgcwd = 0x00000000;
+ s->sysctl_scgctimer = 0x00000000;
+ s->sysctl_scgcgpio = 0x00000000;
+ s->sysctl_scgcdma = 0x00000000;
+ s->sysctl_scgchib = 0x00000001;
+ s->sysctl_scgcuart = 0x00000000;
+ s->sysctl_scgcssi = 0x00000000;
+ s->sysctl_scgci2c = 0x00000000;
+ s->sysctl_scgcusb = 0x00000000;
+ s->sysctl_scgccan = 0x00000000;
+ s->sysctl_scgcadc = 0x00000000;
+ s->sysctl_scgcacmp = 0x00000000;
+ s->sysctl_scgcpwm = 0x00000000;
+ s->sysctl_scgcqei = 0x00000000;
+ s->sysctl_scgceeprom = 0x00000000;
+ s->sysctl_scgcwtimer = 0x00000000;
+ s->sysctl_dcgcwd = 0x00000000;
+ s->sysctl_dcgctimer = 0x00000000;
+ s->sysctl_dcgcgpio = 0x00000000;
+ s->sysctl_dcgcdma = 0x00000000;
+ s->sysctl_dcgchib = 0x00000001;
+ s->sysctl_dcgcuart = 0x00000000;
+ s->sysctl_dcgcssi = 0x00000000;
+ s->sysctl_dcgci2c = 0x00000000;
+ s->sysctl_dcgcusb = 0x00000000;
+ s->sysctl_dcgccan = 0x00000000;
+ s->sysctl_dcgcadc = 0x00000000;
+ s->sysctl_dcgcacmp = 0x00000000;
+ s->sysctl_dcgcpwm = 0x00000000;
+ s->sysctl_dcgcqei = 0x00000000;
+ s->sysctl_dcgceeprom = 0x00000000;
+ s->sysctl_dcgcwtime = 0x00000000;
+ s->sysctl_prwd = 0x00000000;
+ s->sysctl_prtimer = 0x00000000;
+ s->sysctl_prgpio = 0x00000000;
+ s->sysctl_prdma = 0x00000000;
+ s->sysctl_prhib = 0x00000001;
+ s->sysctl_pruart = 0x00000000;
+ s->sysctl_prssi = 0x00000000;
+ s->sysctl_pri2c = 0x00000000;
+ s->sysctl_prusb = 0x00000000;
+ s->sysctl_prcan = 0x00000000;
+ s->sysctl_pradc = 0x00000000;
+ s->sysctl_pracmp = 0x00000000;
+ s->sysctl_prpwm = 0x00000000;
+ s->sysctl_prqei = 0x00000000;
+ s->sysctl_preeprom = 0x00000000;
+ s->sysctl_prwtimer = 0x00000000;
+}
+
+static void tm4c123_sysctl_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size)
+{
+ TM4C123SysCtlState *s = opaque;
+ uint32_t val32 = val64;
+
+ trace_tm4c123_sysctl_write(addr, val32);
+
+ switch(addr) {
+ case SYSCTL_DID0:
+ READONLY;
+ break;
+ case SYSCTL_DID1:
+ READONLY;
+ break;
+ case SYSCTL_PBORCTL:
+ s->sysctl_pborctl = val32;
+ break;
+ case SYSCTL_RIS:
+ READONLY;
+ break;
+ case SYSCTL_IMC:
+ s->sysctl_imc = val32;
+ /*
+ * setting the MISC
+ */
+ s->sysctl_misc = val32;
+ break;
+ case SYSCTL_MISC:
+ s->sysctl_misc = val32;
+ break;
+ case SYSCTL_RESC:
+ s->sysctl_resc = val32;
+ break;
+ case SYSCTL_RCC:
+ s->sysctl_rcc = val32;
+ /*
+ * Setting the SYSCTL_RIS manually for now.
+ */
+ if (s->sysctl_rcc & SYSCTL_RCC_PWRDN && !(s->sysctl_rcc2 & SYSCTL_RCC2_USERCC2)) {
+ s->sysctl_ris |= SYSCTL_RIS_PLLRIS;
+ }
+ tm4c123_sysctl_update_system_clock(s);
+ break;
+ case SYSCTL_GPIOHBCTL:
+ s->sysctl_gpiohbctl = val32;
+ break;
+ case SYSCTL_RCC2:
+ s->sysctl_rcc2 = val32;
+ /*
+ * Setting the SYSCTL_RIS manually for now.
+ */
+ if (s->sysctl_rcc2 & SYSCTL_RCC2_USERCC2 && !(s->sysctl_rcc2 & SYSCTL_RCC2_PWRDN2)) {
+ s->sysctl_ris |= SYSCTL_RIS_PLLRIS;
+ }
+ tm4c123_sysctl_update_system_clock(s);
+ break;
+ case SYSCTL_MOSCCTL:
+ s->sysctl_moscctl = val32;
+ break;
+ case SYSCTL_DSLPCLKCFG:
+ s->sysctl_dslpclkcfg = val32;
+ break;
+ case SYSCTL_SYSPROP:
+ READONLY;
+ break;
+ case SYSCTL_PIOSCCAL:
+ s->sysctl_piosccal = val32;
+ break;
+ case SYSCTL_PIOSCSTAT:
+ READONLY;
+ break;
+ case SYSCTL_PLLFREQ0:
+ READONLY;
+ break;
+ case SYSCTL_PLLFREQ1:
+ READONLY;
+ break;
+ case SYSCTL_PLLSTAT:
+ READONLY;
+ break;
+ case SYSCTL_SLPPWRCFG:
+ s->sysctl_slppwrcfg = val32;
+ break;
+ case SYSCTL_DSLPPWRCFG:
+ s->sysctl_dslppwrcfg = val32;
+ break;
+ case SYSCTL_LDOSPCTL:
+ s->sysctl_ldospctl = val32;
+ break;
+ case SYSCTL_LDOSPCAL:
+ READONLY;
+ break;
+ case SYSCTL_LDODPCTL:
+ s->sysctl_ldodpctl = val32;
+ break;
+ case SYSCTL_LDODPCAL:
+ READONLY;
+ break;
+ case SYSCTL_SDPMST:
+ s->sysctl_sdpmst = val32;
+ break;
+ case SYSCTL_PPWD:
+ READONLY;
+ break;
+ case SYSCTL_PPTIMER:
+ READONLY;
+ break;
+ case SYSCTL_PPGPIO:
+ READONLY;
+ break;
+ case SYSCTL_PPDMA:
+ READONLY;
+ break;
+ case SYSCTL_PPHIB:
+ READONLY;
+ break;
+ case SYSCTL_PPUART:
+ READONLY;
+ break;
+ case SYSCTL_PPSI:
+ READONLY;
+ break;
+ case SYSCTL_PPI2C:
+ READONLY;
+ break;
+ case SYSCTL_PPUSB:
+ READONLY;
+ break;
+ case SYSCTL_PPCAN:
+ READONLY;
+ break;
+ case SYSCTL_PPADC:
+ READONLY;
+ break;
+ case SYSCTL_PPACMP:
+ READONLY;
+ break;
+ case SYSCTL_PPPWM:
+ READONLY;
+ break;
+ case SYSCTL_PPQEI:
+ READONLY;
+ break;
+ case SYSCTL_PPEEPROM:
+ READONLY;
+ break;
+ case SYSCTL_PPWTIMER:
+ READONLY;
+ break;
+ case SYSCTL_SRWD:
+ s->sysctl_srwd = val32;
+ break;
+ case SYSCTL_SRTIMER:
+ s->sysctl_srtimer = val32;
+ break;
+ case SYSCTL_SRGPIO:
+ s->sysctl_srgpio = val32;
+ break;
+ case SYSCTL_SRDMA:
+ s->sysctl_srdma = val32;
+ break;
+ case SYSCTL_SRHIB:
+ s->sysctl_srhib = val32;
+ break;
+ case SYSCTL_SRUART:
+ s->sysctl_sruart = val32;
+ break;
+ case SYSCTL_SRSSI:
+ s->sysctl_srssi = val32;
+ break;
+ case SYSCTL_SRI2C:
+ s->sysctl_sri2c = val32;
+ break;
+ case SYSCTL_SRUSB:
+ s->sysctl_srusb = val32;
+ break;
+ case SYSCTL_SRCAN:
+ s->sysctl_srcan = val32;
+ break;
+ case SYSCTL_SRADC:
+ s->sysctl_sradc = val32;
+ break;
+ case SYSCTL_SRACMP:
+ s->sysctl_sracmp = val32;
+ break;
+ case SYSCTL_SRPWM:
+ s->sysctl_srpwm = val32;
+ break;
+ case SYSCTL_SRQEI:
+ s->sysctl_srqei = val32;
+ break;
+ case SYSCTL_SREEPROM:
+ s->sysctl_sreeprom = val32;
+ break;
+ case SYSCTL_SRWTIMER:
+ s->sysctl_srwtimer = val32;
+ break;
+ case SYSCTL_RCGCWD:
+ s->sysctl_rcgcwd = val32;
+ break;
+ case SYSCTL_RCGCTIMER:
+ s->sysctl_rcgctimer = val32;
+ break;
+ case SYSCTL_RCGCGPIO:
+ s->sysctl_rcgcgpio = val32;
+ s->sysctl_prgpio = val32;
+ break;
+ case SYSCTL_RCGCDMA:
+ s->sysctl_rcgcdma = val32;
+ s->sysctl_prdma = val32;
+ break;
+ case SYSCTL_RCGCHIB:
+ s->sysctl_rcgchib = val32;
+ s->sysctl_prhib = val32;
+ break;
+ case SYSCTL_RCGCUART:
+ s->sysctl_rcgcuart = val32;
+ s->sysctl_pruart = val32;
+ break;
+ case SYSCTL_RCGCSSI:
+ s->sysctl_rcgcssi = val32;
+ s->sysctl_prssi = val32;
+ break;
+ case SYSCTL_RCGCI2C:
+ s->sysctl_rcgci2c = val32;
+ s->sysctl_pri2c = val32;
+ break;
+ case SYSCTL_RCGCUSB:
+ s->sysctl_rcgcusb = val32;
+ s->sysctl_prusb = val32;
+ break;
+ case SYSCTL_RCGCCAN:
+ s->sysctl_rcgccan = val32;
+ s->sysctl_prcan = val32;
+ break;
+ case SYSCTL_RCGCADC:
+ s->sysctl_rcgcadc = val32;
+ s->sysctl_pradc = val32;
+ break;
+ case SYSCTL_RCGCACMP:
+ s->sysctl_rcgcacmp = val32;
+ s->sysctl_pracmp = val32;
+ break;
+ case SYSCTL_RCGCPWM:
+ s->sysctl_rcgcpwm = val32;
+ s->sysctl_prpwm = val32;
+ break;
+ case SYSCTL_RCGCQEI:
+ s->sysctl_rcgcqei = val32;
+ s->sysctl_prqei = val32;
+ break;
+ case SYSCTL_RCGCEEPROM:
+ s->sysctl_rcgceeprom = val32;
+ s->sysctl_preeprom = val32;
+ break;
+ case SYSCTL_RCGCWTIMER:
+ s->sysctl_rcgcwtimer = val32;
+ s->sysctl_prwtimer = val32;
+ break;
+ case SYSCTL_SCGCWD:
+ s->sysctl_scgcwd = val32;
+ break;
+ case SYSCTL_SCGCTIMER:
+ s->sysctl_scgctimer = val32;
+ break;
+ case SYSCTL_SCGCGPIO:
+ s->sysctl_scgcgpio = val32;
+ break;
+ case SYSCTL_SCGCDMA:
+ s->sysctl_scgcdma = val32;
+ break;
+ case SYSCTL_SCGCHIB:
+ s->sysctl_scgchib = val32;
+ break;
+ case SYSCTL_SCGCUART:
+ s->sysctl_scgcuart = val32;
+ break;
+ case SYSCTL_SCGCSSI:
+ s->sysctl_scgcssi = val32;
+ break;
+ case SYSCTL_SCGCI2C:
+ s->sysctl_scgci2c = val32;
+ break;
+ case SYSCTL_SCGCUSB:
+ s->sysctl_scgcusb = val32;
+ break;
+ case SYSCTL_SCGCCAN:
+ s->sysctl_scgccan = val32;
+ break;
+ case SYSCTL_SCGCADC:
+ s->sysctl_scgcadc = val32;
+ break;
+ case SYSCTL_SCGCACMP:
+ s->sysctl_scgcacmp = val32;
+ break;
+ case SYSCTL_SCGCPWM:
+ s->sysctl_scgcpwm = val32;
+ break;
+ case SYSCTL_SCGCQEI:
+ s->sysctl_scgcqei = val32;
+ break;
+ case SYSCTL_SCGCEEPROM:
+ s->sysctl_scgceeprom = val32;
+ break;
+ case SYSCTL_SCGCWTIMER:
+ s->sysctl_scgcwtimer = val32;
+ break;
+ case SYSCTL_DCGCWD:
+ s->sysctl_dcgcwd = val32;
+ break;
+ case SYSCTL_DCGCTIMER:
+ s->sysctl_dcgctimer = val32;
+ break;
+ case SYSCTL_DCGCGPIO:
+ s->sysctl_dcgcgpio = val32;
+ break;
+ case SYSCTL_DCGCDMA:
+ s->sysctl_dcgcdma = val32;
+ break;
+ case SYSCTL_DCGCHIB:
+ s->sysctl_dcgchib = val32;
+ break;
+ case SYSCTL_DCGCUART:
+ s->sysctl_dcgcuart = val32;
+ break;
+ case SYSCTL_DCGCSSI:
+ s->sysctl_dcgcssi = val32;
+ break;
+ case SYSCTL_DCGCI2C:
+ s->sysctl_dcgci2c = val32;
+ break;
+ case SYSCTL_DCGCUSB:
+ s->sysctl_dcgcusb = val32;
+ break;
+ case SYSCTL_DCGCCAN:
+ s->sysctl_dcgccan = val32;
+ break;
+ case SYSCTL_DCGCADC:
+ s->sysctl_dcgcadc = val32;
+ break;
+ case SYSCTL_DCGCACMP:
+ s->sysctl_dcgcacmp = val32;
+ break;
+ case SYSCTL_DCGCPWM:
+ s->sysctl_dcgcpwm = val32;
+ break;
+ case SYSCTL_DCGCQEI:
+ s->sysctl_dcgcqei = val32;
+ break;
+ case SYSCTL_DCGCEEPROM:
+ s->sysctl_dcgceeprom = val32;
+ break;
+ case SYSCTL_DCGCWTIME:
+ s->sysctl_dcgcwtime = val32;
+ break;
+ case SYSCTL_PRWD:
+ READONLY;
+ break;
+ case SYSCTL_PRTIMER:
+ READONLY;
+ break;
+ case SYSCTL_PRGPIO:
+ READONLY;
+ break;
+ case SYSCTL_PRDMA:
+ READONLY;
+ break;
+ case SYSCTL_PRHIB:
+ READONLY;
+ break;
+ case SYSCTL_PRUART:
+ READONLY;
+ break;
+ case SYSCTL_PRSSI:
+ READONLY;
+ break;
+ case SYSCTL_PRI2C:
+ READONLY;
+ break;
+ case SYSCTL_PRUSB:
+ READONLY;
+ break;
+ case SYSCTL_PRCAN:
+ READONLY;
+ break;
+ case SYSCTL_PRADC:
+ READONLY;
+ break;
+ case SYSCTL_PRACMP:
+ READONLY;
+ break;
+ case SYSCTL_PRPWM:
+ READONLY;
+ break;
+ case SYSCTL_PRQEI:
+ READONLY;
+ break;
+ case SYSCTL_PREEPROM:
+ READONLY;
+ break;
+ case SYSCTL_PRWTIMER:
+ READONLY;
+ break;
+ default:
+ LOG("Bad address 0x%"HWADDR_PRIx"\n", addr);
+ break;
+ }
+}
+
+static uint64_t tm4c123_sysctl_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ TM4C123SysCtlState *s = opaque;
+
+ trace_tm4c123_sysctl_read(addr);
+
+ switch(addr) {
+ case SYSCTL_DID0:
+ return s->sysctl_did0;
+ case SYSCTL_DID1:
+ return s->sysctl_did1;
+ case SYSCTL_PBORCTL:
+ return s->sysctl_pborctl;
+ case SYSCTL_RIS:
+ return s->sysctl_ris;
+ case SYSCTL_IMC:
+ return s->sysctl_imc;
+ case SYSCTL_MISC:
+ return s->sysctl_misc;
+ case SYSCTL_RESC:
+ return s->sysctl_resc;
+ case SYSCTL_RCC:
+ return s->sysctl_rcc;
+ case SYSCTL_GPIOHBCTL:
+ return s->sysctl_gpiohbctl;
+ case SYSCTL_RCC2:
+ return s->sysctl_rcc2;
+ case SYSCTL_MOSCCTL:
+ return s->sysctl_moscctl;
+ case SYSCTL_DSLPCLKCFG:
+ return s->sysctl_dslpclkcfg;
+ case SYSCTL_SYSPROP:
+ return s->sysctl_sysprop;
+ case SYSCTL_PIOSCCAL:
+ return s->sysctl_piosccal;
+ case SYSCTL_PIOSCSTAT:
+ return s->sysctl_pioscstat;
+ case SYSCTL_PLLFREQ0:
+ return s->sysctl_pllfreq0;
+ case SYSCTL_PLLFREQ1:
+ return s->sysctl_pllfreq1;
+ case SYSCTL_PLLSTAT:
+ return s->sysctl_pllstat;
+ case SYSCTL_SLPPWRCFG:
+ return s->sysctl_slppwrcfg;
+ case SYSCTL_DSLPPWRCFG:
+ return s->sysctl_dslppwrcfg;
+ case SYSCTL_LDOSPCTL:
+ return s->sysctl_ldospctl;
+ case SYSCTL_LDOSPCAL:
+ return s->sysctl_ldospcal;
+ case SYSCTL_LDODPCTL:
+ return s->sysctl_ldodpctl;
+ case SYSCTL_LDODPCAL:
+ return s->sysctl_ldodpcal;
+ case SYSCTL_SDPMST:
+ return s->sysctl_sdpmst;
+ case SYSCTL_PPWD:
+ return s->sysctl_ppwd;
+ case SYSCTL_PPTIMER:
+ return s->sysctl_pptimer;
+ case SYSCTL_PPGPIO:
+ return s->sysctl_ppgpio;
+ case SYSCTL_PPDMA:
+ return s->sysctl_ppdma;
+ case SYSCTL_PPHIB:
+ return s->sysctl_pphib;
+ case SYSCTL_PPUART:
+ return s->sysctl_ppuart;
+ case SYSCTL_PPSI:
+ return s->sysctl_ppsi;
+ case SYSCTL_PPI2C:
+ return s->sysctl_ppi2c;
+ case SYSCTL_PPUSB:
+ return s->sysctl_ppusb;
+ case SYSCTL_PPCAN:
+ return s->sysctl_ppcan;
+ case SYSCTL_PPADC:
+ return s->sysctl_ppadc;
+ case SYSCTL_PPACMP:
+ return s->sysctl_ppacmp;
+ case SYSCTL_PPPWM:
+ return s->sysctl_pppwm;
+ case SYSCTL_PPQEI:
+ return s->sysctl_ppqei;
+ case SYSCTL_PPEEPROM:
+ return s->sysctl_ppeeprom;
+ case SYSCTL_PPWTIMER:
+ return s->sysctl_ppwtimer;
+ case SYSCTL_SRWD:
+ return s->sysctl_srwd;
+ case SYSCTL_SRTIMER:
+ return s->sysctl_srtimer;
+ case SYSCTL_SRGPIO:
+ return s->sysctl_srgpio;
+ case SYSCTL_SRDMA:
+ return s->sysctl_srdma;
+ case SYSCTL_SRHIB:
+ return s->sysctl_srhib;
+ case SYSCTL_SRUART:
+ return s->sysctl_sruart;
+ case SYSCTL_SRSSI:
+ return s->sysctl_srssi;
+ case SYSCTL_SRI2C:
+ return s->sysctl_sri2c;
+ case SYSCTL_SRUSB:
+ return s->sysctl_srusb;
+ case SYSCTL_SRCAN:
+ return s->sysctl_srcan;
+ case SYSCTL_SRADC:
+ return s->sysctl_sradc;
+ case SYSCTL_SRACMP:
+ return s->sysctl_sracmp;
+ case SYSCTL_SRPWM:
+ return s->sysctl_srpwm;
+ case SYSCTL_SRQEI:
+ return s->sysctl_srqei;
+ case SYSCTL_SREEPROM:
+ return s->sysctl_sreeprom;
+ case SYSCTL_SRWTIMER:
+ return s->sysctl_srwtimer;
+ case SYSCTL_RCGCWD:
+ return s->sysctl_rcgcwd;
+ case SYSCTL_RCGCTIMER:
+ return s->sysctl_rcgctimer;
+ case SYSCTL_RCGCGPIO:
+ return s->sysctl_rcgcgpio;
+ case SYSCTL_RCGCDMA:
+ return s->sysctl_rcgcdma;
+ case SYSCTL_RCGCHIB:
+ return s->sysctl_rcgchib;
+ case SYSCTL_RCGCUART:
+ return s->sysctl_rcgcuart;
+ case SYSCTL_RCGCSSI:
+ return s->sysctl_rcgcssi;
+ case SYSCTL_RCGCI2C:
+ return s->sysctl_rcgci2c;
+ case SYSCTL_RCGCUSB:
+ return s->sysctl_rcgcusb;
+ case SYSCTL_RCGCCAN:
+ return s->sysctl_rcgccan;
+ case SYSCTL_RCGCADC:
+ return s->sysctl_rcgcadc;
+ case SYSCTL_RCGCACMP:
+ return s->sysctl_rcgcacmp;
+ case SYSCTL_RCGCPWM:
+ return s->sysctl_rcgcpwm;
+ case SYSCTL_RCGCQEI:
+ return s->sysctl_rcgcqei;
+ case SYSCTL_RCGCEEPROM:
+ return s->sysctl_rcgceeprom;
+ case SYSCTL_RCGCWTIMER:
+ return s->sysctl_rcgcwtimer;
+ case SYSCTL_SCGCWD:
+ return s->sysctl_scgcwd;
+ case SYSCTL_SCGCTIMER:
+ return s->sysctl_scgctimer;
+ case SYSCTL_SCGCGPIO:
+ return s->sysctl_scgcgpio;
+ case SYSCTL_SCGCDMA:
+ return s->sysctl_scgcdma;
+ case SYSCTL_SCGCHIB:
+ return s->sysctl_scgchib;
+ case SYSCTL_SCGCUART:
+ return s->sysctl_scgcuart;
+ case SYSCTL_SCGCSSI:
+ return s->sysctl_scgcssi;
+ case SYSCTL_SCGCI2C:
+ return s->sysctl_scgci2c;
+ case SYSCTL_SCGCUSB:
+ return s->sysctl_scgcusb;
+ case SYSCTL_SCGCCAN:
+ return s->sysctl_scgccan;
+ case SYSCTL_SCGCADC:
+ return s->sysctl_scgcadc;
+ case SYSCTL_SCGCACMP:
+ return s->sysctl_scgcacmp;
+ case SYSCTL_SCGCPWM:
+ return s->sysctl_scgcpwm;
+ case SYSCTL_SCGCQEI:
+ return s->sysctl_scgcqei;
+ case SYSCTL_SCGCEEPROM:
+ return s->sysctl_scgceeprom;
+ case SYSCTL_SCGCWTIMER:
+ return s->sysctl_scgcwtimer;
+ case SYSCTL_DCGCWD:
+ return s->sysctl_dcgcwd;
+ case SYSCTL_DCGCTIMER:
+ return s->sysctl_dcgctimer;
+ case SYSCTL_DCGCGPIO:
+ return s->sysctl_dcgcgpio;
+ case SYSCTL_DCGCDMA:
+ return s->sysctl_dcgcdma;
+ case SYSCTL_DCGCHIB:
+ return s->sysctl_dcgchib;
+ case SYSCTL_DCGCUART:
+ return s->sysctl_dcgcuart;
+ case SYSCTL_DCGCSSI:
+ return s->sysctl_dcgcssi;
+ case SYSCTL_DCGCI2C:
+ return s->sysctl_dcgci2c;
+ case SYSCTL_DCGCUSB:
+ return s->sysctl_dcgcusb;
+ case SYSCTL_DCGCCAN:
+ return s->sysctl_dcgccan;
+ case SYSCTL_DCGCADC:
+ return s->sysctl_dcgcadc;
+ case SYSCTL_DCGCACMP:
+ return s->sysctl_dcgcacmp;
+ case SYSCTL_DCGCPWM:
+ return s->sysctl_dcgcpwm;
+ case SYSCTL_DCGCQEI:
+ return s->sysctl_dcgcqei;
+ case SYSCTL_DCGCEEPROM:
+ return s->sysctl_dcgceeprom;
+ case SYSCTL_DCGCWTIME:
+ return s->sysctl_dcgcwtime;
+ case SYSCTL_PRWD:
+ return s->sysctl_prwd;
+ case SYSCTL_PRTIMER:
+ return s->sysctl_prtimer;
+ case SYSCTL_PRGPIO:
+ return s->sysctl_prgpio;
+ case SYSCTL_PRDMA:
+ return s->sysctl_prdma;
+ case SYSCTL_PRHIB:
+ return s->sysctl_prhib;
+ case SYSCTL_PRUART:
+ return s->sysctl_pruart;
+ case SYSCTL_PRSSI:
+ return s->sysctl_prssi;
+ case SYSCTL_PRI2C:
+ return s->sysctl_pri2c;
+ case SYSCTL_PRUSB:
+ return s->sysctl_prusb;
+ case SYSCTL_PRCAN:
+ return s->sysctl_prcan;
+ case SYSCTL_PRADC:
+ return s->sysctl_pradc;
+ case SYSCTL_PRACMP:
+ return s->sysctl_pracmp;
+ case SYSCTL_PRPWM:
+ return s->sysctl_prpwm;
+ case SYSCTL_PRQEI:
+ return s->sysctl_prqei;
+ case SYSCTL_PREEPROM:
+ return s->sysctl_preeprom;
+ case SYSCTL_PRWTIMER:
+ return s->sysctl_prwtimer;
+ default:
+ LOG("Bad address 0x%"HWADDR_PRIx"\n", addr);
+ break;
+ }
+ return 0;
+}
+
+static const MemoryRegionOps tm4c123_sysctl_ops = {
+ .read = tm4c123_sysctl_read,
+ .write = tm4c123_sysctl_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void tm4c123_sysctl_init(Object *obj)
+{
+ TM4C123SysCtlState *s = TM4C123_SYSCTL(obj);
+
+ s->mainclk = clock_new(OBJECT(s), "main-clk");
+ clock_set_hz(s->mainclk, 1000*1000);
+ s->outclk = qdev_init_clock_out(DEVICE(s), "outclk");
+ clock_set_source(s->outclk, s->mainclk);
+
+ memory_region_init_io(&s->mmio, obj, &tm4c123_sysctl_ops, s, TYPE_TM4C123_SYSCTL, 0xFFF);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void tm4c123_sysctl_realize(DeviceState *dev, Error **errp)
+{
+ TM4C123SysCtlState *s = TM4C123_SYSCTL(dev);
+ tm4c123_sysctl_update_system_clock(s);
+
+}
+
+static void tm4c123_sysctl_class_init(ObjectClass *kclass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(kclass);
+ dc->reset = tm4c123_sysctl_reset;
+ dc->realize = tm4c123_sysctl_realize;
+}
+
+static const TypeInfo tm4c123_sysctl_info = {
+ .name = TYPE_TM4C123_SYSCTL,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TM4C123SysCtlState),
+ .instance_init = tm4c123_sysctl_init,
+ .class_init = tm4c123_sysctl_class_init,
+};
+
+static void tm4c123_sysctl_register_types(void)
+{
+ type_register_static(&tm4c123_sysctl_info);
+}
+
+type_init(tm4c123_sysctl_register_types)
diff --git a/include/hw/misc/tm4c123_sysctl.h b/include/hw/misc/tm4c123_sysctl.h
new file mode 100644
index 0000000000..a8219a8693
--- /dev/null
+++ b/include/hw/misc/tm4c123_sysctl.h
@@ -0,0 +1,307 @@
+/*
+ * TM4C123 SYSCTL
+ *
+ * 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_SYSCTL_H
+#define HW_ARM_TM4C123_SYSCTL_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/clock.h"
+#include "hw/qdev-clock.h"
+#include "qapi/error.h"
+
+#define XTALM (16000000UL) /* Main oscillator freq */
+#define XTALI (16000000UL) /* Internal oscillator freq */
+#define XTAL30K ( 30000UL) /* Internal 30K oscillator freq */
+#define XTAL32K ( 32768UL) /* external 32K oscillator freq */
+
+#define PLL_CLK (400000000UL)
+#define ADC_CLK (PLL_CLK/25)
+#define CAN_CLK (PLL_CLK/50)
+
+#define SYSCTL_DID0 0x000
+#define SYSCTL_DID1 0x004
+#define SYSCTL_PBORCTL 0x030
+#define SYSCTL_RIS 0x050
+#define SYSCTL_IMC 0x054
+#define SYSCTL_MISC 0x058
+#define SYSCTL_RESC 0x05C
+#define SYSCTL_RCC 0x060
+#define SYSCTL_GPIOHBCTL 0x06C
+#define SYSCTL_RCC2 0x070
+#define SYSCTL_MOSCCTL 0x07C
+#define SYSCTL_DSLPCLKCFG 0x144
+#define SYSCTL_SYSPROP 0x14C
+#define SYSCTL_PIOSCCAL 0x150
+#define SYSCTL_PIOSCSTAT 0x154
+#define SYSCTL_PLLFREQ0 0x160
+#define SYSCTL_PLLFREQ1 0x164
+#define SYSCTL_PLLSTAT 0x168
+#define SYSCTL_SLPPWRCFG 0x188
+#define SYSCTL_DSLPPWRCFG 0x18C
+#define SYSCTL_LDOSPCTL 0x1B4
+#define SYSCTL_LDOSPCAL 0x1B8
+#define SYSCTL_LDODPCTL 0x1Bc
+#define SYSCTL_LDODPCAL 0x1C0
+#define SYSCTL_SDPMST 0x1CC
+#define SYSCTL_PPWD 0x300
+#define SYSCTL_PPTIMER 0x304
+#define SYSCTL_PPGPIO 0x308
+#define SYSCTL_PPDMA 0x30C
+#define SYSCTL_PPHIB 0x314
+#define SYSCTL_PPUART 0x318
+#define SYSCTL_PPSI 0x31C
+#define SYSCTL_PPI2C 0x320
+#define SYSCTL_PPUSB 0x328
+#define SYSCTL_PPCAN 0x334
+#define SYSCTL_PPADC 0x338
+#define SYSCTL_PPACMP 0x33C
+#define SYSCTL_PPPWM 0x340
+#define SYSCTL_PPQEI 0x344
+#define SYSCTL_PPEEPROM 0x358
+#define SYSCTL_PPWTIMER 0x35C
+#define SYSCTL_SRWD 0x500
+#define SYSCTL_SRTIMER 0x504
+#define SYSCTL_SRGPIO 0x508
+#define SYSCTL_SRDMA 0x50C
+#define SYSCTL_SRHIB 0x514
+#define SYSCTL_SRUART 0x518
+#define SYSCTL_SRSSI 0x51C
+#define SYSCTL_SRI2C 0x520
+#define SYSCTL_SRUSB 0x528
+#define SYSCTL_SRCAN 0x534
+#define SYSCTL_SRADC 0x538
+#define SYSCTL_SRACMP 0x53C
+#define SYSCTL_SRPWM 0x540
+#define SYSCTL_SRQEI 0x544
+#define SYSCTL_SREEPROM 0x558
+#define SYSCTL_SRWTIMER 0x55C
+#define SYSCTL_RCGCWD 0x600
+#define SYSCTL_RCGCTIMER 0x604
+#define SYSCTL_RCGCGPIO 0x608
+#define SYSCTL_RCGCDMA 0x60C
+#define SYSCTL_RCGCHIB 0x614
+#define SYSCTL_RCGCUART 0x618
+#define SYSCTL_RCGCSSI 0x61C
+#define SYSCTL_RCGCI2C 0x620
+#define SYSCTL_RCGCUSB 0x628
+#define SYSCTL_RCGCCAN 0x634
+#define SYSCTL_RCGCADC 0x638
+#define SYSCTL_RCGCACMP 0x63C
+#define SYSCTL_RCGCPWM 0x640
+#define SYSCTL_RCGCQEI 0x644
+#define SYSCTL_RCGCEEPROM 0x658
+#define SYSCTL_RCGCWTIMER 0x65C
+#define SYSCTL_SCGCWD 0x700
+#define SYSCTL_SCGCTIMER 0x704
+#define SYSCTL_SCGCGPIO 0x708
+#define SYSCTL_SCGCDMA 0x70C
+#define SYSCTL_SCGCHIB 0x714
+#define SYSCTL_SCGCUART 0x718
+#define SYSCTL_SCGCSSI 0x71C
+#define SYSCTL_SCGCI2C 0x720
+#define SYSCTL_SCGCUSB 0x728
+#define SYSCTL_SCGCCAN 0x734
+#define SYSCTL_SCGCADC 0x738
+#define SYSCTL_SCGCACMP 0x73C
+#define SYSCTL_SCGCPWM 0x740
+#define SYSCTL_SCGCQEI 0x744
+#define SYSCTL_SCGCEEPROM 0x758
+#define SYSCTL_SCGCWTIMER 0x75C
+#define SYSCTL_DCGCWD 0x800
+#define SYSCTL_DCGCTIMER 0x804
+#define SYSCTL_DCGCGPIO 0x808
+#define SYSCTL_DCGCDMA 0x80C
+#define SYSCTL_DCGCHIB 0x814
+#define SYSCTL_DCGCUART 0x818
+#define SYSCTL_DCGCSSI 0x81C
+#define SYSCTL_DCGCI2C 0x820
+#define SYSCTL_DCGCUSB 0x828
+#define SYSCTL_DCGCCAN 0x834
+#define SYSCTL_DCGCADC 0x838
+#define SYSCTL_DCGCACMP 0x83C
+#define SYSCTL_DCGCPWM 0x840
+#define SYSCTL_DCGCQEI 0x844
+#define SYSCTL_DCGCEEPROM 0x858
+#define SYSCTL_DCGCWTIME 0x85C
+#define SYSCTL_PRWD 0xA00
+#define SYSCTL_PRTIMER 0xA04
+#define SYSCTL_PRGPIO 0xA08
+#define SYSCTL_PRDMA 0xA0C
+#define SYSCTL_PRHIB 0xA14
+#define SYSCTL_PRUART 0xA18
+#define SYSCTL_PRSSI 0xA1C
+#define SYSCTL_PRI2C 0xA20
+#define SYSCTL_PRUSB 0xA28
+#define SYSCTL_PRCAN 0xA34
+#define SYSCTL_PRADC 0xA38
+#define SYSCTL_PRACMP 0xA3C
+#define SYSCTL_PRPWM 0xA40
+#define SYSCTL_PRQEI 0xA44
+#define SYSCTL_PREEPROM 0xA58
+#define SYSCTL_PRWTIMER 0xA5C
+
+
+#define SYSCTL_RCC_PWRDN (1 << 13)
+#define SYSCTL_RCC2_PWRDN2 (1 << 13)
+#define SYSCTL_RCC2_USERCC2 (1 << 31)
+#define SYSCTL_RIS_PLLRIS (1 << 6)
+
+#define TYPE_TM4C123_SYSCTL "tm4c123-sysctl"
+OBJECT_DECLARE_SIMPLE_TYPE(TM4C123SysCtlState, TM4C123_SYSCTL)
+
+struct TM4C123SysCtlState {
+
+ SysBusDevice parent_obj;
+ MemoryRegion mmio;
+
+ uint32_t sysctl_did0;
+ uint32_t sysctl_did1;
+ uint32_t sysctl_pborctl;
+ uint32_t sysctl_ris;
+ uint32_t sysctl_imc;
+ uint32_t sysctl_misc;
+ uint32_t sysctl_resc;
+ uint32_t sysctl_rcc;
+ uint32_t sysctl_gpiohbctl;
+ uint32_t sysctl_rcc2;
+ uint32_t sysctl_moscctl;
+ uint32_t sysctl_dslpclkcfg;
+ uint32_t sysctl_sysprop;
+ uint32_t sysctl_piosccal;
+ uint32_t sysctl_pioscstat;
+ uint32_t sysctl_pllfreq0;
+ uint32_t sysctl_pllfreq1;
+ uint32_t sysctl_pllstat;
+ uint32_t sysctl_slppwrcfg;
+ uint32_t sysctl_dslppwrcfg;
+ uint32_t sysctl_ldospctl;
+ uint32_t sysctl_ldospcal;
+ uint32_t sysctl_ldodpctl;
+ uint32_t sysctl_ldodpcal;
+ uint32_t sysctl_sdpmst;
+ uint32_t sysctl_ppwd;
+ uint32_t sysctl_pptimer;
+ uint32_t sysctl_ppgpio;
+ uint32_t sysctl_ppdma;
+ uint32_t sysctl_pphib;
+ uint32_t sysctl_ppuart;
+ uint32_t sysctl_ppsi;
+ uint32_t sysctl_ppi2c;
+ uint32_t sysctl_ppusb;
+ uint32_t sysctl_ppcan;
+ uint32_t sysctl_ppadc;
+ uint32_t sysctl_ppacmp;
+ uint32_t sysctl_pppwm;
+ uint32_t sysctl_ppqei;
+ uint32_t sysctl_ppeeprom;
+ uint32_t sysctl_ppwtimer;
+ uint32_t sysctl_srwd;
+ uint32_t sysctl_srtimer;
+ uint32_t sysctl_srgpio;
+ uint32_t sysctl_srdma;
+ uint32_t sysctl_srhib;
+ uint32_t sysctl_sruart;
+ uint32_t sysctl_srssi;
+ uint32_t sysctl_sri2c;
+ uint32_t sysctl_srusb;
+ uint32_t sysctl_srcan;
+ uint32_t sysctl_sradc;
+ uint32_t sysctl_sracmp;
+ uint32_t sysctl_srpwm;
+ uint32_t sysctl_srqei;
+ uint32_t sysctl_sreeprom;
+ uint32_t sysctl_srwtimer;
+ uint32_t sysctl_rcgcwd;
+ uint32_t sysctl_rcgctimer;
+ uint32_t sysctl_rcgcgpio;
+ uint32_t sysctl_rcgcdma;
+ uint32_t sysctl_rcgchib;
+ uint32_t sysctl_rcgcuart;
+ uint32_t sysctl_rcgcssi;
+ uint32_t sysctl_rcgci2c;
+ uint32_t sysctl_rcgcusb;
+ uint32_t sysctl_rcgccan;
+ uint32_t sysctl_rcgcadc;
+ uint32_t sysctl_rcgcacmp;
+ uint32_t sysctl_rcgcpwm;
+ uint32_t sysctl_rcgcqei;
+ uint32_t sysctl_rcgceeprom;
+ uint32_t sysctl_rcgcwtimer;
+ uint32_t sysctl_scgcwd;
+ uint32_t sysctl_scgctimer;
+ uint32_t sysctl_scgcgpio;
+ uint32_t sysctl_scgcdma;
+ uint32_t sysctl_scgchib;
+ uint32_t sysctl_scgcuart;
+ uint32_t sysctl_scgcssi;
+ uint32_t sysctl_scgci2c;
+ uint32_t sysctl_scgcusb;
+ uint32_t sysctl_scgccan;
+ uint32_t sysctl_scgcadc;
+ uint32_t sysctl_scgcacmp;
+ uint32_t sysctl_scgcpwm;
+ uint32_t sysctl_scgcqei;
+ uint32_t sysctl_scgceeprom;
+ uint32_t sysctl_scgcwtimer;
+ uint32_t sysctl_dcgcwd;
+ uint32_t sysctl_dcgctimer;
+ uint32_t sysctl_dcgcgpio;
+ uint32_t sysctl_dcgcdma;
+ uint32_t sysctl_dcgchib;
+ uint32_t sysctl_dcgcuart;
+ uint32_t sysctl_dcgcssi;
+ uint32_t sysctl_dcgci2c;
+ uint32_t sysctl_dcgcusb;
+ uint32_t sysctl_dcgccan;
+ uint32_t sysctl_dcgcadc;
+ uint32_t sysctl_dcgcacmp;
+ uint32_t sysctl_dcgcpwm;
+ uint32_t sysctl_dcgcqei;
+ uint32_t sysctl_dcgceeprom;
+ uint32_t sysctl_dcgcwtime;
+ uint32_t sysctl_prwd;
+ uint32_t sysctl_prtimer;
+ uint32_t sysctl_prgpio;
+ uint32_t sysctl_prdma;
+ uint32_t sysctl_prhib;
+ uint32_t sysctl_pruart;
+ uint32_t sysctl_prssi;
+ uint32_t sysctl_pri2c;
+ uint32_t sysctl_prusb;
+ uint32_t sysctl_prcan;
+ uint32_t sysctl_pradc;
+ uint32_t sysctl_pracmp;
+ uint32_t sysctl_prpwm;
+ uint32_t sysctl_prqei;
+ uint32_t sysctl_preeprom;
+ uint32_t sysctl_prwtimer;
+
+ Clock* mainclk;
+ Clock* outclk;
+
+};
+
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PULL 5/8] tivac general purpose timers implementation
2023-05-16 7:29 [PULL SUBSYSTEM arm 0/8] TivaC Implementation Mohamed ElSayed
` (3 preceding siblings ...)
2023-05-16 7:29 ` [PULL 4/8] tivac system control implementation Mohamed ElSayed
@ 2023-05-16 7:29 ` Mohamed ElSayed
2023-05-16 7:29 ` [PULL 6/8] tivac watchdog " Mohamed ElSayed
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Mohamed ElSayed @ 2023-05-16 7:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Mohamed ElSayed
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
hw/timer/tm4c123_gptm.c | 529 ++++++++++++++++++++++++++++++++
include/hw/timer/tm4c123_gptm.h | 131 ++++++++
2 files changed, 660 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..69f84ee0ec
--- /dev/null
+++ b/hw/timer/tm4c123_gptm.c
@@ -0,0 +1,529 @@
+/*
+ * 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(fmt, args...) qemu_log("%s: " fmt, __func__, ## args)
+#define READONLY LOG("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 void log_message(const char *message)
+{
+ uint64_t ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+ time_t seconds = ns / 1000000000;
+ struct tm *timeinfo = localtime(&seconds);
+ char buffer[80];
+ strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeinfo);
+ LOG("[%s] %s\n", buffer, message);
+}
+
+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));
+ LOG("Timer A/16 is running\n");
+ }
+ 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));
+ LOG("Timer A/32 RTC is running\n");
+ }
+ 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));
+ LOG("Timer A/32 is running\n");
+ }
+ }
+ 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));
+ LOG("Timer A/64 is running\n");
+ }
+ 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));
+ LOG("Timer A/64 RTC is running\n");
+ }
+ 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));
+ LOG("Timer A/32 RTC is running\n");
+ }
+ }
+ }
+ 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));
+ LOG("Timer B/16 is running\n");
+ }
+ 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));
+ LOG("Timer B/32 RTC is running\n");
+ }
+ 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));
+ LOG("Timer B/32 RTC is running\n");
+ }
+ }
+ 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));
+ LOG("Timer A/64 is running\n");
+ }
+ 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));
+ LOG("Timer A/64 RTC is running\n");
+ }
+ 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));
+ LOG("Timer A/32 RTC is running\n");
+ }
+ }
+ }
+}
+
+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_tabr);
+ }
+ 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("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("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;
+
+ log_message("timer A\n");
+
+ 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;
+ log_message("timer B\n");
+
+ 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/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
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PULL 6/8] tivac watchdog timers implementation
2023-05-16 7:29 [PULL SUBSYSTEM arm 0/8] TivaC Implementation Mohamed ElSayed
` (4 preceding siblings ...)
2023-05-16 7:29 ` [PULL 5/8] tivac general purpose timers implementation Mohamed ElSayed
@ 2023-05-16 7:29 ` 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
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Mohamed ElSayed @ 2023-05-16 7:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Mohamed ElSayed
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
hw/watchdog/tm4c123_watchdog.c | 298 +++++++++++++++++++++++++
include/hw/watchdog/tm4c123_watchdog.h | 97 ++++++++
2 files changed, 395 insertions(+)
create mode 100644 hw/watchdog/tm4c123_watchdog.c
create mode 100644 include/hw/watchdog/tm4c123_watchdog.h
diff --git a/hw/watchdog/tm4c123_watchdog.c b/hw/watchdog/tm4c123_watchdog.c
new file mode 100644
index 0000000000..cd064c5343
--- /dev/null
+++ b/hw/watchdog/tm4c123_watchdog.c
@@ -0,0 +1,298 @@
+/*
+ * TM4C123 Watchdog 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 "qemu/osdep.h"
+#include "hw/watchdog/tm4c123_watchdog.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-clock.h"
+#include "sysemu/runstate.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/nmi.h"
+#include "trace.h"
+
+#define READONLY LOG("0x%"HWADDR_PRIx" is a readonly field\n.", addr)
+#define LOG(fmt, args...) qemu_log("%s: " fmt, __func__, ## args)
+
+static bool locked = false;
+
+static void tm4c123_wdt_expired(void *opaque)
+{
+ TM4C123WatchdogState *s = opaque;
+ /*if this is the first timeout/the ris is not cleared */
+ if (!test_bit(0, (const unsigned long*)&s->wdt_mis)) {
+ set_bit(0, (unsigned long*)&s->wdt_mis);
+ nmi_monitor_handle(0, NULL);
+ qemu_irq_pulse(s->irq);
+ }
+ else {
+ if (test_bit(1, (const unsigned long*)&s->wdt_ctl))
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ else {
+ nmi_monitor_handle(0, NULL);
+ qemu_irq_pulse(s->irq);
+ }
+ }
+}
+
+static bool wdt_clock_enabled(TM4C123SysCtlState *s, hwaddr addr)
+{
+ switch(addr) {
+ case WDT_0:
+ return (s->sysctl_rcgcwd & (1 << 0));
+ break;
+ case WDT_1:
+ return (s->sysctl_rcgcwd & (1 << 1));
+ break;
+ }
+ return false;
+}
+
+static void tm4c123_wdt_reset(DeviceState *dev)
+{
+ TM4C123WatchdogState *s = TM4C123_WATCHDOG(dev);
+
+ s->wdt_load = 0xFFFFFFFF;
+ s->wdt_value = 0xFFFFFFFF;
+ s->wdt_ctl = (s->mmio.addr == WDT_0 ? 0x00000000 : 0x80000000);
+ s->wdt_icr = 0x00000000;
+ s->wdt_ris = 0x00000000;
+ s->wdt_mis = 0x00000000;
+ s->wdt_test = 0x00000000;
+ s->wdt_lock = 0x00000000;
+ s->wdt_per_id4 = 0x00000000;
+ s->wdt_per_id5 = 0x00000000;
+ s->wdt_per_id6 = 0x00000000;
+ s->wdt_per_id7 = 0x00000000;
+ s->wdt_per_id0 = 0x00000005;
+ s->wdt_per_id1 = 0x00000018;
+ s->wdt_per_id2 = 0x00000018;
+ s->wdt_per_id3 = 0x00000001;
+ s->wdt_pcell_id0 = 0x0000000D;
+ s->wdt_pcell_id1 = 0x000000F0;
+ s->wdt_pcell_id2 = 0x00000006;
+ s->wdt_pcell_id3 = 0x000000B1;
+}
+
+static uint64_t tm4c123_wdt_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ TM4C123WatchdogState *s = opaque;
+
+ if (!wdt_clock_enabled(s->sysctl, s->mmio.addr)) {
+ hw_error("Watchdog timer module clock is not enabled");
+ }
+
+ switch(addr) {
+ case WDT_LOAD:
+ return s->wdt_load;
+ case WDT_VALUE:
+ return ptimer_get_count(s->timer);
+ case WDT_CTL:
+ return s->wdt_ctl;
+ case WDT_ICR:
+ return s->wdt_icr;
+ case WDT_RIS:
+ return s->wdt_ris;
+ case WDT_MIS:
+ return s->wdt_mis;
+ case WDT_TEST:
+ return s->wdt_test;
+ case WDT_LOCK:
+ return s->wdt_lock;
+ case WDT_PER_ID4:
+ return s->wdt_per_id4;
+ case WDT_PER_ID5:
+ return s->wdt_per_id5;
+ case WDT_PER_ID6:
+ return s->wdt_per_id6;
+ case WDT_PER_ID7:
+ return s->wdt_per_id7;
+ case WDT_PER_ID0:
+ return s->wdt_per_id0;
+ case WDT_PER_ID1:
+ return s->wdt_per_id1;
+ case WDT_PER_ID2:
+ return s->wdt_per_id2;
+ case WDT_PER_ID3:
+ return s->wdt_per_id3;
+ case WDT_PCELL_ID0:
+ return s->wdt_pcell_id0;
+ case WDT_PCELL_ID1:
+ return s->wdt_pcell_id1;
+ case WDT_PCELL_ID2:
+ return s->wdt_pcell_id2;
+ case WDT_PCELL_ID3:
+ return s->wdt_pcell_id3;
+ default:
+ LOG("Bad address 0x%"HWADDR_PRIx"\n", addr);
+ }
+ return 0;
+}
+
+static void tm4c123_wdt_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size)
+{
+ TM4C123WatchdogState *s = opaque;
+ uint32_t val32 = val64;
+
+ trace_tm4c123_wdt_write(addr, val64);
+ if (!wdt_clock_enabled(s->sysctl, s->mmio.addr)) {
+ hw_error("Watchdog module clock is not enabled");
+ }
+
+ switch(addr) {
+ case WDT_LOAD:
+ s->wdt_load = val32;
+ locked = true;
+ s->wdt_ctl |= WDT_CTL_INTEN;
+ ptimer_transaction_begin(s->timer);
+ ptimer_set_count(s->timer, s->wdt_load);
+ ptimer_set_limit(s->timer, s->wdt_load, 1);
+ ptimer_run(s->timer, 0);
+ ptimer_transaction_commit(s->timer);
+ break;
+ case WDT_VALUE:
+ READONLY;
+ break;
+ case WDT_CTL:
+ s->wdt_ctl = val32;
+ break;
+ case WDT_ICR:
+ ptimer_transaction_begin(s->timer);
+ ptimer_set_limit(s->timer, s->wdt_load, 1);
+ ptimer_transaction_commit(s->timer);
+ clear_bit(0, (unsigned long*)&s->wdt_ris);
+ clear_bit(0, (unsigned long*)&s->wdt_mis);
+ s->wdt_icr = val32;
+ break;
+ case WDT_RIS:
+ READONLY;
+ break;
+ case WDT_MIS:
+ READONLY;
+ break;
+ case WDT_TEST:
+ s->wdt_test = val32;
+ break;
+ case WDT_LOCK:
+ /* The actual hardware never locks the module */
+ if (val32 == UNLOCK_VALUE) {
+ locked = false;
+ s->wdt_lock = 0;
+ }
+ break;
+ case WDT_PER_ID4:
+ READONLY;
+ break;
+ case WDT_PER_ID5:
+ READONLY;
+ break;
+ case WDT_PER_ID6:
+ READONLY;
+ break;
+ case WDT_PER_ID7:
+ READONLY;
+ break;
+ case WDT_PER_ID0:
+ READONLY;
+ break;
+ case WDT_PER_ID1:
+ READONLY;
+ break;
+ case WDT_PER_ID2:
+ READONLY;
+ break;
+ case WDT_PER_ID3:
+ READONLY;
+ break;
+ case WDT_PCELL_ID0:
+ READONLY;
+ break;
+ case WDT_PCELL_ID1:
+ READONLY;
+ break;
+ case WDT_PCELL_ID2:
+ READONLY;
+ break;
+ case WDT_PCELL_ID3:
+ READONLY;
+ break;
+ default:
+ LOG("Bad address 0x%"HWADDR_PRIx"\n", addr);
+ }
+}
+
+const struct MemoryRegionOps tm4c123_wdt_ops = {
+ .read = tm4c123_wdt_read,
+ .write = tm4c123_wdt_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void tm4c123_wdt_init(Object *obj)
+{
+ TM4C123WatchdogState *s = TM4C123_WATCHDOG(obj);
+
+ s->wdt_clock = qdev_init_clock_in(DEVICE(s), "wdt_clock", NULL, NULL, 0);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+ memory_region_init_io(&s->mmio, obj, &tm4c123_wdt_ops, s, TYPE_TM4C123_WATCHDOG, 0xFFF);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+}
+
+static void tm4c123_wdt_realize(DeviceState *dev, Error **errp)
+{
+ TM4C123WatchdogState *s = TM4C123_WATCHDOG(dev);
+ qdev_connect_clock_in(dev, "wdt_clock", qdev_get_clock_out(DEVICE(s->sysctl), "outclk"));
+
+ s->timer = ptimer_init(tm4c123_wdt_expired, s,
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
+
+ ptimer_transaction_begin(s->timer);
+ ptimer_set_period_from_clock(s->timer, s->wdt_clock, 1);
+ ptimer_set_limit(s->timer, 0xFFFFFFFF, 0);
+ ptimer_transaction_commit(s->timer);
+}
+
+static void tm4c123_wdt_class_init(ObjectClass *kclass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(kclass);
+ dc->realize = tm4c123_wdt_realize;
+ dc->reset = tm4c123_wdt_reset;
+}
+
+static const TypeInfo tm4c123_wdt_info = {
+ .name = TYPE_TM4C123_WATCHDOG,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TM4C123WatchdogState),
+ .instance_init = tm4c123_wdt_init,
+ .class_init = tm4c123_wdt_class_init,
+};
+
+static void tm4c123_wdt_register_types(void)
+{
+ type_register_static(&tm4c123_wdt_info);
+}
+
+type_init(tm4c123_wdt_register_types)
diff --git a/include/hw/watchdog/tm4c123_watchdog.h b/include/hw/watchdog/tm4c123_watchdog.h
new file mode 100644
index 0000000000..2621b5d805
--- /dev/null
+++ b/include/hw/watchdog/tm4c123_watchdog.h
@@ -0,0 +1,97 @@
+/*
+ * TM4C123 Watchdog 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_WATCHDOG_H
+#define HW_ARM_TM4C123_WATCHDOG_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+#include "hw/misc/tm4c123_sysctl.h"
+#include "hw/ptimer.h"
+
+#define WDT_0 0x40000000
+#define WDT_1 0x40001000
+
+#define WDT_LOAD 0x000
+#define WDT_VALUE 0x004
+#define WDT_CTL 0x008
+#define WDT_ICR 0x00C
+#define WDT_RIS 0x010
+#define WDT_MIS 0x014
+#define WDT_TEST 0x418
+#define WDT_LOCK 0xC00
+#define WDT_PER_ID4 0xFD0
+#define WDT_PER_ID5 0xFD4
+#define WDT_PER_ID6 0xFD8
+#define WDT_PER_ID7 0xFDC
+#define WDT_PER_ID0 0xFE0
+#define WDT_PER_ID1 0xFE4
+#define WDT_PER_ID2 0xFE8
+#define WDT_PER_ID3 0xFEC
+#define WDT_PCELL_ID0 0xFF0
+#define WDT_PCELL_ID1 0xFF4
+#define WDT_PCELL_ID2 0xFF8
+#define WDT_PCELL_ID3 0xFFC
+
+#define UNLOCK_VALUE 0x1ACCE551
+
+#define WDT_CTL_INTEN (1 << 0)
+#define WDT_CTL_INTTYPE (1 << 2)
+
+#define TYPE_TM4C123_WATCHDOG "tm4c123-watchdog"
+
+OBJECT_DECLARE_SIMPLE_TYPE(TM4C123WatchdogState, TM4C123_WATCHDOG)
+
+struct TM4C123WatchdogState {
+ SysBusDevice parent_obj;
+ MemoryRegion mmio;
+ qemu_irq irq;
+ struct ptimer_state *timer;
+ TM4C123SysCtlState* sysctl;
+
+ uint32_t wdt_load;
+ uint32_t wdt_value;
+ uint32_t wdt_ctl;
+ uint32_t wdt_icr;
+ uint32_t wdt_ris;
+ uint32_t wdt_mis;
+ uint32_t wdt_test;
+ uint32_t wdt_lock;
+ uint32_t wdt_per_id4;
+ uint32_t wdt_per_id5;
+ uint32_t wdt_per_id6;
+ uint32_t wdt_per_id7;
+ uint32_t wdt_per_id0;
+ uint32_t wdt_per_id1;
+ uint32_t wdt_per_id2;
+ uint32_t wdt_per_id3;
+ uint32_t wdt_pcell_id0;
+ uint32_t wdt_pcell_id1;
+ uint32_t wdt_pcell_id2;
+ uint32_t wdt_pcell_id3;
+
+ Clock* wdt_clock;
+};
+
+#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PULL 7/8] editing the meson and KConfig files to add tivac to qemu build system
2023-05-16 7:29 [PULL SUBSYSTEM arm 0/8] TivaC Implementation Mohamed ElSayed
` (5 preceding siblings ...)
2023-05-16 7:29 ` [PULL 6/8] tivac watchdog " Mohamed ElSayed
@ 2023-05-16 7:29 ` 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
8 siblings, 0 replies; 10+ messages in thread
From: Mohamed ElSayed @ 2023-05-16 7:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Mohamed ElSayed
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
.gitignore | 1 +
README.rst | 150 ++----------------------
configs/devices/arm-softmmu/default.mak | 1 +
hw/arm/Kconfig | 13 ++
hw/arm/meson.build | 3 +
hw/char/Kconfig | 3 +
hw/char/meson.build | 1 +
hw/char/trace-events | 4 +
hw/gpio/Kconfig | 3 +
hw/gpio/meson.build | 1 +
hw/gpio/trace-events | 4 +
hw/misc/Kconfig | 3 +
hw/misc/meson.build | 1 +
hw/misc/trace-events | 5 +
hw/timer/Kconfig | 3 +
hw/timer/meson.build | 1 +
hw/timer/trace-events | 5 +
hw/watchdog/Kconfig | 3 +
hw/watchdog/meson.build | 1 +
hw/watchdog/trace-events | 3 +
20 files changed, 72 insertions(+), 137 deletions(-)
diff --git a/.gitignore b/.gitignore
index 1ea59f4819..009ab2ee4b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
.gdb_history
cscope.*
tags
+compile_commands.json
TAGS
GPATH
GRTAGS
diff --git a/README.rst b/README.rst
index 21df79ef43..37ea8cb56c 100644
--- a/README.rst
+++ b/README.rst
@@ -1,46 +1,8 @@
===========
-QEMU README
+QEMU_TivaC README
===========
-QEMU is a generic and open source machine & userspace emulator and
-virtualizer.
-
-QEMU is capable of emulating a complete machine in software without any
-need for hardware virtualization support. By using dynamic translation,
-it achieves very good performance. QEMU can also integrate with the Xen
-and KVM hypervisors to provide emulated hardware while allowing the
-hypervisor to manage the CPU. With hypervisor support, QEMU can achieve
-near native performance for CPUs. When QEMU emulates CPUs directly it is
-capable of running operating systems made for one machine (e.g. an ARMv7
-board) on a different machine (e.g. an x86_64 PC board).
-
-QEMU is also capable of providing userspace API virtualization for Linux
-and BSD kernel interfaces. This allows binaries compiled against one
-architecture ABI (e.g. the Linux PPC64 ABI) to be run on a host using a
-different architecture ABI (e.g. the Linux x86_64 ABI). This does not
-involve any hardware emulation, simply CPU and syscall emulation.
-
-QEMU aims to fit into a variety of use cases. It can be invoked directly
-by users wishing to have full control over its behaviour and settings.
-It also aims to facilitate integration into higher level management
-layers, by providing a stable command line interface and monitor API.
-It is commonly invoked indirectly via the libvirt library when using
-open source applications such as oVirt, OpenStack and virt-manager.
-
-QEMU as a whole is released under the GNU General Public License,
-version 2. For full licensing details, consult the LICENSE file.
-
-
-Documentation
-=============
-
-Documentation can be found hosted online at
-`<https://www.qemu.org/documentation/>`_. The documentation for the
-current development version that is available at
-`<https://www.qemu.org/docs/master/>`_ is generated from the ``docs/``
-folder in the source tree, and is built by `Sphinx
-<https://www.sphinx-doc.org/en/master/>`_.
-
+QEMU_TivaC aims to provide a TivaC support for the QEMU project. The project is far from being complete (so far) but im working on it.
Building
========
@@ -52,9 +14,11 @@ of other UNIX targets. The simple steps to build QEMU are:
.. code-block:: shell
+ git clone git@github.com:moesay/qemu_TivaC.git
+ cd qemu_TivaC
mkdir build
cd build
- ../configure
+ ../configure --target-list=arm-softmmu
make
Additional information can also be found online via the QEMU website:
@@ -64,108 +28,20 @@ Additional information can also be found online via the QEMU website:
* `<https://wiki.qemu.org/Hosts/W32>`_
-Submitting patches
-==================
-
-The QEMU source code is maintained under the GIT version control system.
-
-.. code-block:: shell
-
- git clone https://gitlab.com/qemu-project/qemu.git
-
-When submitting patches, one common approach is to use 'git
-format-patch' and/or 'git send-email' to format & send the mail to the
-qemu-devel@nongnu.org mailing list. All patches submitted must contain
-a 'Signed-off-by' line from the author. Patches should follow the
-guidelines set out in the `style section
-<https://www.qemu.org/docs/master/devel/style.html>`_ of
-the Developers Guide.
-
-Additional information on submitting patches can be found online via
-the QEMU website
-
-* `<https://wiki.qemu.org/Contribute/SubmitAPatch>`_
-* `<https://wiki.qemu.org/Contribute/TrivialPatches>`_
+Usage
+=====
-The QEMU website is also maintained under source control.
+After building QEMU_TivaC, you can use it with gdb through the provided gdbstub.
.. code-block:: shell
- git clone https://gitlab.com/qemu-project/qemu-web.git
+ qemu-system-arm -M tivac -kernel <your elf file path> -s -S -D log_file.txt -d unimp -serial file:qemu_serial_op.txt -monitor stdio -nographic
-* `<https://www.qemu.org/2017/02/04/the-new-qemu-website-is-up/>`_
-
-A 'git-publish' utility was created to make above process less
-cumbersome, and is highly recommended for making regular contributions,
-or even just for sending consecutive patch series revisions. It also
-requires a working 'git send-email' setup, and by default doesn't
-automate everything, so you may want to go through the above steps
-manually for once.
-
-For installation instructions, please go to
-
-* `<https://github.com/stefanha/git-publish>`_
-
-The workflow with 'git-publish' is:
+Now, QEMU_TivaC is ready to be attached to gdb. In a different terminal run arm gdb and attach QEMU_TivaC to it.
.. code-block:: shell
- $ git checkout master -b my-feature
- $ # work on new commits, add your 'Signed-off-by' lines to each
- $ git publish
-
-Your patch series will be sent and tagged as my-feature-v1 if you need to refer
-back to it in the future.
-
-Sending v2:
-
-.. code-block:: shell
-
- $ git checkout my-feature # same topic branch
- $ # making changes to the commits (using 'git rebase', for example)
- $ git publish
-
-Your patch series will be sent with 'v2' tag in the subject and the git tip
-will be tagged as my-feature-v2.
-
-Bug reporting
-=============
-
-The QEMU project uses GitLab issues to track bugs. Bugs
-found when running code built from QEMU git or upstream released sources
-should be reported via:
-
-* `<https://gitlab.com/qemu-project/qemu/-/issues>`_
-
-If using QEMU via an operating system vendor pre-built binary package, it
-is preferable to report bugs to the vendor's own bug tracker first. If
-the bug is also known to affect latest upstream code, it can also be
-reported via GitLab.
-
-For additional information on bug reporting consult:
-
-* `<https://wiki.qemu.org/Contribute/ReportABug>`_
-
-
-ChangeLog
-=========
-
-For version history and release notes, please visit
-`<https://wiki.qemu.org/ChangeLog/>`_ or look at the git history for
-more detailed information.
-
-
-Contact
-=======
-
-The QEMU community can be contacted in a number of ways, with the two
-main methods being email and IRC
-
-* `<mailto:qemu-devel@nongnu.org>`_
-* `<https://lists.nongnu.org/mailman/listinfo/qemu-devel>`_
-* #qemu on irc.oftc.net
-
-Information on additional methods of contacting the community can be
-found online via the QEMU website:
+ arm-none-eabi-gdb <your elf file path>
+ (gdb) target remote :1234
-* `<https://wiki.qemu.org/Contribute/StartHere>`_
+For the original QEMU readme, go to `<https://github.com/qemu/qemu>`_
diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-softmmu/default.mak
index 1b49a7830c..d3490f6d11 100644
--- a/configs/devices/arm-softmmu/default.mak
+++ b/configs/devices/arm-softmmu/default.mak
@@ -43,3 +43,4 @@ CONFIG_FSL_IMX6UL=y
CONFIG_SEMIHOSTING=y
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
CONFIG_ALLWINNER_H3=y
+CONFIG_TIVAC=y
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index b53bd7f0b2..ef8046ab1b 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -581,3 +581,16 @@ config ARMSSE
select UNIMP
select SSE_COUNTER
select SSE_TIMER
+
+config TM4C123GH6PM_SOC
+ bool
+ select ARM_V7M
+ select TM4C123_USART
+ select TM4C123_SYSCTL
+ select TM4C123_GPIO
+ select TM4C123_WDT
+ select TM4C123_GPTM
+
+config TIVAC
+ bool
+ select TM4C123GH6PM_SOC
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index b545ba0e4f..29503388a5 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -62,10 +62,13 @@ arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
+arm_ss.add(when: 'CONFIG_TM4C123GH6PM_SOC', if_true: files('tm4c123gh6pm_soc.c'))
+arm_ss.add(when: 'CONFIG_TIVAC', if_true: files('tivac.c'))
softmmu_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
softmmu_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c'))
softmmu_ss.add(when: 'CONFIG_TOSA', if_true: files('tosa.c'))
+
hw_arch += {'arm': arm_ss}
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 6b6cf2fc1d..88da979b75 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -71,3 +71,6 @@ config GOLDFISH_TTY
config SHAKTI_UART
bool
+
+config TM4C123_USART
+ bool
diff --git a/hw/char/meson.build b/hw/char/meson.build
index 0807e00ae4..8461748c8d 100644
--- a/hw/char/meson.build
+++ b/hw/char/meson.build
@@ -33,6 +33,7 @@ softmmu_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c'))
softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
softmmu_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
+softmmu_ss.add(when: 'CONFIG_TM4C123_USART', if_true: files('tm4c123_usart.c'))
softmmu_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c'))
specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c'))
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 2ecb36232e..47b7e3b772 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -1,5 +1,9 @@
# See docs/devel/tracing.rst for syntax documentation.
+# tm4c123_usart.c
+tm4c123_usart_read(uint64_t offset) " offset: 0x%" PRIu64
+tm4c123_usart_write(uint64_t offset, uint64_t value) " offset: 0x%" PRIu64 " - value: 0x%" PRIu64
+
# parallel.c
parallel_ioport_read(const char *desc, uint16_t addr, uint8_t value) "read [%s] addr 0x%02x val 0x%02x"
parallel_ioport_write(const char *desc, uint16_t addr, uint8_t value) "write [%s] addr 0x%02x val 0x%02x"
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
index d2cf3accc8..1b843d669a 100644
--- a/hw/gpio/Kconfig
+++ b/hw/gpio/Kconfig
@@ -16,3 +16,6 @@ config GPIO_PWR
config SIFIVE_GPIO
bool
+
+config TM4C123_GPIO
+ bool
diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build
index b726e6d27a..b253e8ce67 100644
--- a/hw/gpio/meson.build
+++ b/hw/gpio/meson.build
@@ -12,3 +12,4 @@ softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gpio.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c'))
softmmu_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c'))
+softmmu_ss.add(when: 'CONFIG_TM4C123_GPIO', if_true: files('tm4c123_gpio.c'))
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
index 9736b362ac..22d282495d 100644
--- a/hw/gpio/trace-events
+++ b/hw/gpio/trace-events
@@ -1,5 +1,9 @@
# See docs/devel/tracing.rst for syntax documentation.
+# tm4c123_gpio.c
+tm4c123_gpio_read(uint64_t offset) " offset: 0x%" PRIx64
+tm4c123_gpio_write(uint64_t offset, uint64_t value) " offset: 0x%" PRIx64 " - value: 0x%" PRIx64
+
# npcm7xx_gpio.c
npcm7xx_gpio_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
npcm7xx_gpio_write(const char *id, uint64_t offset, uint64_t value) "%s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 2ef5781ef8..c8be9ae285 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -180,4 +180,7 @@ config AXP209_PMU
bool
depends on I2C
+config TM4C123_SYSCTL
+ bool
+
source macio/Kconfig
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index a40245ad44..95ddb4b1b4 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -141,3 +141,4 @@ softmmu_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
# HPPA devices
softmmu_ss.add(when: 'CONFIG_LASI', if_true: files('lasi.c'))
+softmmu_ss.add(when: 'CONFIG_TM4C123_SYSCTL', if_true: files('tm4c123_sysctl.c'))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index c47876a902..0c40b49457 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -1,5 +1,10 @@
# See docs/devel/tracing.rst for syntax documentation.
+# tm4c123_sysctl.c
+tm4c123_sysctl_read(uint64_t offset) " offset: 0x%" PRIu64
+tm4c123_sysctl_write(uint64_t offset, uint64_t value) " offset: 0x%" PRIu64 " - value: 0x%"PRIu64
+tm4c123_sysctl_update_system_clock(uint32_t value) "New clock value = %"PRIu32" Hz"
+
# allwinner-cpucfg.c
allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIx32
allwinner_cpucfg_read(uint64_t offset, uint64_t data, unsigned size) "offset 0x%" PRIx64 " data 0x%" PRIx64 " size %" PRIu32
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
index 010be7ed1f..aaf42e3f3f 100644
--- a/hw/timer/Kconfig
+++ b/hw/timer/Kconfig
@@ -60,3 +60,6 @@ config STELLARIS_GPTM
config AVR_TIMER16
bool
+
+config TM4C123_GPTM
+ bool
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
index 03092e2ceb..118593e959 100644
--- a/hw/timer/meson.build
+++ b/hw/timer/meson.build
@@ -36,5 +36,6 @@ softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c'))
softmmu_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c'))
+softmmu_ss.add(when: 'CONFIG_TM4C123_GPTM', if_true: files('tm4c123_gptm.c'))
specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c'))
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/hw/watchdog/Kconfig b/hw/watchdog/Kconfig
index 861fd00334..ada7163055 100644
--- a/hw/watchdog/Kconfig
+++ b/hw/watchdog/Kconfig
@@ -24,3 +24,6 @@ config WDT_SBSA
config ALLWINNER_WDT
bool
select PTIMER
+
+config TM4C123_WDT
+ bool
diff --git a/hw/watchdog/meson.build b/hw/watchdog/meson.build
index 5dcd4fbe2f..cc48d2dec9 100644
--- a/hw/watchdog/meson.build
+++ b/hw/watchdog/meson.build
@@ -7,4 +7,5 @@ softmmu_ss.add(when: 'CONFIG_WDT_DIAG288', if_true: files('wdt_diag288.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('wdt_aspeed.c'))
softmmu_ss.add(when: 'CONFIG_WDT_IMX2', if_true: files('wdt_imx2.c'))
softmmu_ss.add(when: 'CONFIG_WDT_SBSA', if_true: files('sbsa_gwdt.c'))
+softmmu_ss.add(when: 'CONFIG_TM4C123_WDT', if_true: files('tm4c123_watchdog.c'))
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_watchdog.c'))
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
index 2739570652..802aed4a6f 100644
--- a/hw/watchdog/trace-events
+++ b/hw/watchdog/trace-events
@@ -1,5 +1,8 @@
# See docs/devel/tracing.rst for syntax documentation.
+# tm4c123_wdt.c
+tm4c123_wdt_write(uint64_t offset, uint64_t data) "TM4C123-WDT Write: [ Offset 0x%" PRIx64 " - Data 0x%" PRIx64 "]"
+
# allwinner-wdt.c
allwinner_wdt_read(uint64_t offset, uint64_t data, unsigned size) "Allwinner watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
allwinner_wdt_write(uint64_t offset, uint64_t data, unsigned size) "Allwinner watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PULL 8/8] code style fixes
2023-05-16 7:29 [PULL SUBSYSTEM arm 0/8] TivaC Implementation Mohamed ElSayed
` (6 preceding siblings ...)
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 ` Mohamed ElSayed
2023-05-16 9:00 ` [PULL SUBSYSTEM arm 0/8] TivaC Implementation Alex Bennée
8 siblings, 0 replies; 10+ messages in thread
From: Mohamed ElSayed @ 2023-05-16 7:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Mohamed ElSayed
Signed-off-by: Mohamed ElSayed <m.elsayed4420@gmail.com>
---
hw/arm/tm4c123gh6pm_soc.c | 14 ++--
hw/char/tm4c123_usart.c | 28 +++----
hw/misc/tm4c123_sysctl.c | 6 +-
hw/timer/tm4c123_gptm.c | 134 ++++++++++++---------------------
hw/watchdog/tm4c123_watchdog.c | 25 +++---
5 files changed, 85 insertions(+), 122 deletions(-)
diff --git a/hw/arm/tm4c123gh6pm_soc.c b/hw/arm/tm4c123gh6pm_soc.c
index da08eefc33..7afaa6653b 100644
--- a/hw/arm/tm4c123gh6pm_soc.c
+++ b/hw/arm/tm4c123gh6pm_soc.c
@@ -89,7 +89,8 @@ static void tm4c123gh6pm_soc_initfn(Object *obj)
object_initialize_child(obj, "sysctl", &s->sysctl, TYPE_TM4C123_SYSCTL);
for (i = 0; i < USART_COUNT; i++) {
- object_initialize_child(obj, "usart[*]", &s->usart[i], TYPE_TM4C123_USART);
+ object_initialize_child(obj, "usart[*]",
+ &s->usart[i], TYPE_TM4C123_USART);
}
for (i = 0; i < GPIO_COUNT; i++) {
@@ -97,7 +98,8 @@ static void tm4c123gh6pm_soc_initfn(Object *obj)
}
for (i = 0; i < WDT_COUNT; i++) {
- object_initialize_child(obj, "watchdog-timer[*]", &s->wdt[i], TYPE_TM4C123_WATCHDOG);
+ object_initialize_child(obj, "watchdog-timer[*]",
+ &s->wdt[i], TYPE_TM4C123_WATCHDOG);
}
for (i = 0; i < GPTM_COUNT; i++) {
@@ -115,14 +117,14 @@ static void tm4c123gh6pm_soc_realize(DeviceState *dev_soc, Error **errp)
MemoryRegion *system_memory = get_system_memory();
- //init flash memory
+ /* init flash memory */
memory_region_init_rom(
&s->flash, OBJECT(dev_soc),
"TM4C123GH6PM.flash", FLASH_SIZE, &error_fatal
);
memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash);
- //init sram and the sram alias region
+ /* init sram and the sram alias region */
memory_region_init_ram(
&s->sram, OBJECT(dev_soc),
"TM4C123GH6PM.sram", SRAM_SIZE, &error_fatal);
@@ -181,7 +183,7 @@ static void tm4c123gh6pm_soc_realize(DeviceState *dev_soc, Error **errp)
/* General purpose timers */
int j = 0;
- for (i = 0, j = 0; i < GPTM_COUNT; i++, j+=2) {
+ for (i = 0, j = 0; i < GPTM_COUNT; i++, j += 2) {
dev = DEVICE(&(s->gptm[i]));
s->gptm[i].sysctl = &s->sysctl;
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gptm[i]), errp)) {
@@ -190,7 +192,7 @@ static void tm4c123gh6pm_soc_realize(DeviceState *dev_soc, Error **errp)
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, gptm_addrs[i]);
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, gptm_irqs[j]));
- sysbus_connect_irq(busdev, 1, qdev_get_gpio_in(armv7m, gptm_irqs[j+1]));
+ sysbus_connect_irq(busdev, 1, qdev_get_gpio_in(armv7m, gptm_irqs[j + 1]));
}
/* SYSCTL */
diff --git a/hw/char/tm4c123_usart.c b/hw/char/tm4c123_usart.c
index cafca02b97..ed20eedb4c 100644
--- a/hw/char/tm4c123_usart.c
+++ b/hw/char/tm4c123_usart.c
@@ -36,42 +36,41 @@
static bool usart_clock_enabled(TM4C123SysCtlState *s, hwaddr addr)
{
- switch(addr) {
+ switch (addr) {
case USART_0:
- return (s->sysctl_rcgcuart & (1 << 0));
+ return s->sysctl_rcgcuart & (1 << 0);
break;
case USART_1:
- return (s->sysctl_rcgcuart & (1 << 1));
+ return s->sysctl_rcgcuart & (1 << 1);
break;
case USART_2:
- return (s->sysctl_rcgcuart & (1 << 2));
+ return s->sysctl_rcgcuart & (1 << 2);
break;
case USART_3:
- return (s->sysctl_rcgcuart & (1 << 3));
+ return s->sysctl_rcgcuart & (1 << 3);
break;
case USART_4:
- return (s->sysctl_rcgcuart & (1 << 4));
+ return s->sysctl_rcgcuart & (1 << 4);
break;
case USART_5:
- return (s->sysctl_rcgcuart & (1 << 5));
+ return s->sysctl_rcgcuart & (1 << 5);
break;
case USART_6:
- return (s->sysctl_rcgcuart & (1 << 6));
+ return s->sysctl_rcgcuart & (1 << 6);
break;
case USART_7:
- return (s->sysctl_rcgcuart & (1 << 7));
+ return s->sysctl_rcgcuart & (1 << 7);
break;
}
return false;
}
-static int tm4c123_usart_can_receive(void* opaque)
+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;
@@ -82,7 +81,6 @@ 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;
}
@@ -93,8 +91,6 @@ static void tm4c123_usart_receive(void *opaque, const uint8_t *buf, int size)
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)
@@ -145,7 +141,7 @@ static uint64_t tm4c123_usart_read(void *opaque, hwaddr addr, unsigned int size)
trace_tm4c123_usart_read(addr);
- switch(addr) {
+ switch (addr) {
case USART_DR:
return s->usart_dr;
case USART_RSR:
@@ -227,7 +223,7 @@ static void tm4c123_usart_write(void *opaque, hwaddr addr, uint64_t val64, unsig
trace_tm4c123_usart_write(addr, val32);
- switch(addr) {
+ switch (addr) {
case USART_DR:
s->usart_dr = val32;
if (val32 < 0xF000) {
diff --git a/hw/misc/tm4c123_sysctl.c b/hw/misc/tm4c123_sysctl.c
index 9bce30eb73..c07c734df5 100644
--- a/hw/misc/tm4c123_sysctl.c
+++ b/hw/misc/tm4c123_sysctl.c
@@ -282,7 +282,7 @@ static void tm4c123_sysctl_write(void *opaque, hwaddr addr, uint64_t val64, unsi
trace_tm4c123_sysctl_write(addr, val32);
- switch(addr) {
+ switch (addr) {
case SYSCTL_DID0:
READONLY;
break;
@@ -690,7 +690,7 @@ static uint64_t tm4c123_sysctl_read(void *opaque, hwaddr addr, unsigned int size
trace_tm4c123_sysctl_read(addr);
- switch(addr) {
+ switch (addr) {
case SYSCTL_DID0:
return s->sysctl_did0;
case SYSCTL_DID1:
@@ -951,7 +951,7 @@ static void tm4c123_sysctl_init(Object *obj)
TM4C123SysCtlState *s = TM4C123_SYSCTL(obj);
s->mainclk = clock_new(OBJECT(s), "main-clk");
- clock_set_hz(s->mainclk, 1000*1000);
+ clock_set_hz(s->mainclk, 1000 * 1000);
s->outclk = qdev_init_clock_out(DEVICE(s), "outclk");
clock_set_source(s->outclk, s->mainclk);
diff --git a/hw/timer/tm4c123_gptm.c b/hw/timer/tm4c123_gptm.c
index 69f84ee0ec..b1a8600d80 100644
--- a/hw/timer/tm4c123_gptm.c
+++ b/hw/timer/tm4c123_gptm.c
@@ -44,23 +44,13 @@ static unsigned long ticks_to_time_ns(void *opaque, uint64_t ticks, uint32_t pre
{
TM4C123GPTMState *s = opaque;
uint32_t freq = clock_get_hz(s->clk) / prescaler;
- return (((float)ticks / (float)freq) * NANOSECONDS_PER_SECOND);
-}
-
-static void log_message(const char *message)
-{
- uint64_t ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
- time_t seconds = ns / 1000000000;
- struct tm *timeinfo = localtime(&seconds);
- char buffer[80];
- strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", timeinfo);
- LOG("[%s] %s\n", buffer, message);
+ return ((float)ticks / (float)freq) * NANOSECONDS_PER_SECOND;
}
static uint16_t get_timer_width(void *opaque)
{
TM4C123GPTMState *s = opaque;
- switch(s->mmio.addr) {
+ switch (s->mmio.addr) {
case TIMER0_32...TIMER5_32:
return TIMER_WIDTH_32;
case TIMER0_64...TIMER5_64:
@@ -79,8 +69,7 @@ static uint64_t build_interval_value(void *opaque)
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) {
+ } else if (timer_width == TIMER_WIDTH_64) {
interval_value = ((uint64_t)s->gptm_talir << 32) + s->gptm_tblir;
}
@@ -102,43 +91,31 @@ static void set_timers(void *opaque)
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));
- LOG("Timer A/16 is running\n");
- }
- else if (s->gptm_cfg == 0x1) {
+ } 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));
- LOG("Timer A/32 RTC is running\n");
- }
- else if (s->gptm_cfg == 0x0) {
+ } 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));
- LOG("Timer A/32 is running\n");
}
- }
- else if (timer_width == TIMER_WIDTH_64) {
+ } 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));
- LOG("Timer A/64 is running\n");
- }
- else if (s->gptm_cfg == 0x1) {
+ } 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));
- LOG("Timer A/64 RTC is running\n");
- }
- else if (s->gptm_cfg == 0x4) {
+ } 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));
- LOG("Timer A/32 RTC is running\n");
}
}
- }
- else if (s->gptm_ctl & GPTM_TBCTL_EN) {
+ } 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 */
@@ -147,39 +124,33 @@ static void set_timers(void *opaque)
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));
- LOG("Timer B/16 is running\n");
- }
- else if (s->gptm_cfg == 0x01) {
+ } 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));
- LOG("Timer B/32 RTC is running\n");
- }
- else if (s->gptm_cfg == 0x00) {
+ 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));
- LOG("Timer B/32 RTC is running\n");
+ 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) {
+ } 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));
- LOG("Timer A/64 is running\n");
- }
- else if (s->gptm_cfg == 0x1) {
+ 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));
- LOG("Timer A/64 RTC is running\n");
- }
- else if (s->gptm_cfg == 0x4) {
+ 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));
- LOG("Timer A/32 RTC is running\n");
+ timer_mod(s->b,
+ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ticks_to_time_ns(s, interval_value, s->gptm_tbpr));
}
}
}
@@ -187,48 +158,48 @@ static void set_timers(void *opaque)
static bool gptm_clock_enabled(TM4C123SysCtlState *s, hwaddr addr)
{
- switch(addr) {
+ switch (addr) {
case TIMER0_32:
- return test_bit(0, (const unsigned long*)&s->sysctl_rcgctimer);
+ return test_bit(0, (const unsigned long *)&s->sysctl_rcgctimer);
break;
case TIMER1_32:
- return test_bit(1, (const unsigned long*)&s->sysctl_rcgctimer);
+ return test_bit(1, (const unsigned long *)&s->sysctl_rcgctimer);
break;
case TIMER2_32:
- return test_bit(2, (const unsigned long*)&s->sysctl_rcgctimer);
+ return test_bit(2, (const unsigned long *)&s->sysctl_rcgctimer);
break;
case TIMER3_32:
- return test_bit(3, (const unsigned long*)&s->sysctl_rcgctimer);
+ return test_bit(3, (const unsigned long *)&s->sysctl_rcgctimer);
break;
case TIMER4_32:
- return test_bit(4, (const unsigned long*)&s->sysctl_rcgctimer);
+ return test_bit(4, (const unsigned long *)&s->sysctl_rcgctimer);
break;
case TIMER5_32:
- return test_bit(5, (const unsigned long*)&s->sysctl_rcgctimer);
+ return test_bit(5, (const unsigned long *)&s->sysctl_rcgctimer);
break;
case TIMER0_64:
- return test_bit(0, (const unsigned long*)&s->sysctl_rcgcwtimer);
+ return test_bit(0, (const unsigned long *)&s->sysctl_rcgcwtimer);
break;
case TIMER1_64:
- return test_bit(1, (const unsigned long*)&s->sysctl_rcgcwtimer);
+ return test_bit(1, (const unsigned long *)&s->sysctl_rcgcwtimer);
break;
case TIMER2_64:
- return test_bit(2, (const unsigned long*)&s->sysctl_rcgcwtimer);
+ return test_bit(2, (const unsigned long *)&s->sysctl_rcgcwtimer);
break;
case TIMER3_64:
- return test_bit(3, (const unsigned long*)&s->sysctl_rcgcwtimer);
+ return test_bit(3, (const unsigned long *)&s->sysctl_rcgcwtimer);
break;
case TIMER4_64:
- return test_bit(4, (const unsigned long*)&s->sysctl_rcgcwtimer);
+ return test_bit(4, (const unsigned long *)&s->sysctl_rcgcwtimer);
break;
case TIMER5_64:
- return test_bit(5, (const unsigned long*)&s->sysctl_rcgcwtimer);
+ return test_bit(5, (const unsigned long *)&s->sysctl_rcgcwtimer);
break;
}
return false;
}
-static void tm4c123_gptm_reset(DeviceState* dev)
+static void tm4c123_gptm_reset(DeviceState *dev)
{
TM4C123GPTMState *s = TM4C123_GPTM(dev);
@@ -271,7 +242,7 @@ static uint64_t tm4c123_gptm_read(void *opaque, hwaddr addr, unsigned int size)
trace_tm4c123_gptm_read(addr);
- switch(addr) {
+ switch (addr) {
case GPTM_CFG:
return s->gptm_cfg;
case GPTM_AMR:
@@ -315,8 +286,7 @@ static uint64_t tm4c123_gptm_read(void *opaque, hwaddr addr, unsigned int size)
return extract64(
ns_to_ticks(s, s->a->expire_time - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), s->gptm_tapr),
0, 31);
- }
- else {
+ } else {
return ns_to_ticks(s, s->a->expire_time - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), s->gptm_tapr);
}
case GPTM_TBV:
@@ -324,9 +294,8 @@ static uint64_t tm4c123_gptm_read(void *opaque, hwaddr addr, unsigned int size)
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_tabr);
+ } 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;
@@ -358,7 +327,7 @@ static void tm4c123_gptm_write(void *opaque, hwaddr addr, uint64_t val64, unsign
trace_tm4c123_gptm_write(addr, val32);
- switch(addr) {
+ switch (addr) {
case GPTM_CFG:
s->gptm_cfg = val32;
break;
@@ -457,13 +426,11 @@ static void timer_a_callback(void *opaque)
{
TM4C123GPTMState *s = opaque;
- log_message("timer A\n");
-
- if (test_bit(0, (unsigned long*)&s->gptm_imr)) {
+ 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_mis);
}
- set_bit(0, (unsigned long*)&s->gptm_ris);
+ set_bit(0, (unsigned long *)&s->gptm_ris);
if ((s->gptm_amr & 0x0000000F) == 0x2) {
set_timers(s);
}
@@ -472,13 +439,12 @@ static void timer_a_callback(void *opaque)
static void timer_b_callback(void *opaque)
{
TM4C123GPTMState *s = opaque;
- log_message("timer B\n");
- if (test_bit(8, (unsigned long*)&s->gptm_imr)) {
+ 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_mis);
}
- set_bit(8, (unsigned long*)&s->gptm_ris);
+ set_bit(8, (unsigned long *)&s->gptm_ris);
if ((s->gptm_bmr & 0x0000000F) == 0x2) {
set_timers(s);
}
@@ -486,7 +452,7 @@ static void timer_b_callback(void *opaque)
static void tm4c123_gptm_init(Object *obj)
{
- TM4C123GPTMState*s = TM4C123_GPTM(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);
diff --git a/hw/watchdog/tm4c123_watchdog.c b/hw/watchdog/tm4c123_watchdog.c
index cd064c5343..50fd08318f 100644
--- a/hw/watchdog/tm4c123_watchdog.c
+++ b/hw/watchdog/tm4c123_watchdog.c
@@ -36,19 +36,18 @@
#define READONLY LOG("0x%"HWADDR_PRIx" is a readonly field\n.", addr)
#define LOG(fmt, args...) qemu_log("%s: " fmt, __func__, ## args)
-static bool locked = false;
+static bool locked;
static void tm4c123_wdt_expired(void *opaque)
{
TM4C123WatchdogState *s = opaque;
/*if this is the first timeout/the ris is not cleared */
- if (!test_bit(0, (const unsigned long*)&s->wdt_mis)) {
- set_bit(0, (unsigned long*)&s->wdt_mis);
+ if (!test_bit(0, (const unsigned long *)&s->wdt_mis)) {
+ set_bit(0, (unsigned long *)&s->wdt_mis);
nmi_monitor_handle(0, NULL);
qemu_irq_pulse(s->irq);
- }
- else {
- if (test_bit(1, (const unsigned long*)&s->wdt_ctl))
+ } else {
+ if (test_bit(1, (const unsigned long *)&s->wdt_ctl))
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
else {
nmi_monitor_handle(0, NULL);
@@ -59,12 +58,12 @@ static void tm4c123_wdt_expired(void *opaque)
static bool wdt_clock_enabled(TM4C123SysCtlState *s, hwaddr addr)
{
- switch(addr) {
+ switch (addr) {
case WDT_0:
- return (s->sysctl_rcgcwd & (1 << 0));
+ return s->sysctl_rcgcwd & (1 << 0);
break;
case WDT_1:
- return (s->sysctl_rcgcwd & (1 << 1));
+ return s->sysctl_rcgcwd & (1 << 1);
break;
}
return false;
@@ -104,7 +103,7 @@ static uint64_t tm4c123_wdt_read(void *opaque, hwaddr addr, unsigned int size)
hw_error("Watchdog timer module clock is not enabled");
}
- switch(addr) {
+ switch (addr) {
case WDT_LOAD:
return s->wdt_load;
case WDT_VALUE:
@@ -161,7 +160,7 @@ static void tm4c123_wdt_write(void *opaque, hwaddr addr, uint64_t val64, unsigne
hw_error("Watchdog module clock is not enabled");
}
- switch(addr) {
+ switch (addr) {
case WDT_LOAD:
s->wdt_load = val32;
locked = true;
@@ -182,8 +181,8 @@ static void tm4c123_wdt_write(void *opaque, hwaddr addr, uint64_t val64, unsigne
ptimer_transaction_begin(s->timer);
ptimer_set_limit(s->timer, s->wdt_load, 1);
ptimer_transaction_commit(s->timer);
- clear_bit(0, (unsigned long*)&s->wdt_ris);
- clear_bit(0, (unsigned long*)&s->wdt_mis);
+ clear_bit(0, (unsigned long *)&s->wdt_ris);
+ clear_bit(0, (unsigned long *)&s->wdt_mis);
s->wdt_icr = val32;
break;
case WDT_RIS:
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PULL SUBSYSTEM arm 0/8] TivaC Implementation
2023-05-16 7:29 [PULL SUBSYSTEM arm 0/8] TivaC Implementation Mohamed ElSayed
` (7 preceding siblings ...)
2023-05-16 7:29 ` [PULL 8/8] code style fixes Mohamed ElSayed
@ 2023-05-16 9:00 ` Alex Bennée
8 siblings, 0 replies; 10+ messages in thread
From: Alex Bennée @ 2023-05-16 9:00 UTC (permalink / raw)
To: Mohamed ElSayed; +Cc: qemu-arm, qemu-devel
Mohamed ElSayed <m.elsayed4420@gmail.com> writes:
> ***
> This is an implementation for the TivaC board.
> For now it models the system control block, the general purpose I/O, the general purpose timers, the watchdog timers and the usart module.
>
> The code is available at https://github.com/moesay/qemu_TivaC.git
> ***
Hi Mohamed,
I'm afraid this pull request won't get processed. Pull requests are sent
by maintainers who are listed in the MAINTAINERS file with signed PRs.
If you want to get support for the TivacC board up-streamed you should
post a series of patches and participate in code review. We have some
general guidance for the process here:
https://qemu.readthedocs.io/en/latest/devel/submitting-a-patch.html
A couple of general points to get you started:
- patch 7
This is obviously wrong as it updates the project README with your
personal fork information.
- patch 8
code format fixes to your own code should be folded into the relevant commit
- use of qemu_log
direct use of qemu_log is discouraged. Generally for devices you
would be using qemu_log_mask with LOG_UNIMP or LOG_GUEST_ERROR as
appropriate. Think about if the log point would be better handled at
a tracepoint (or removed completely if it was a debugging aid during
development).
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 10+ messages in thread