diff --git a/hw/timer/esp32s3_timg.c b/hw/timer/esp32s3_timg.c new file mode 100644 index 0000000000..37460937cc --- /dev/null +++ b/hw/timer/esp32s3_timg.c @@ -0,0 +1,32 @@ +/* + * ESP32-S3 "Timer Group" peripheral + * + * Copyright (c) 2025 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "hw/timer/esp32s3_timg.h" + +static void esp32s3_timg_class_init(ObjectClass *klass, void *data) +{ + ESPTimgClass* esp = ESP_TIMG_CLASS(klass); + esp->m_has_t1 = true; +} + +static const TypeInfo esp32s3_timg_info = { + .name = TYPE_ESP32S3_TIMG, + .parent = TYPE_ESP_TIMG, + .instance_size = sizeof(ESP32S3TimgState), + .class_size = sizeof(ESP32S3TimgClass), + .class_init = esp32s3_timg_class_init, +}; + +static void esp32s3_timg_register_types(void) +{ + type_register_static(&esp32s3_timg_info); +} + +type_init(esp32s3_timg_register_types) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index b09e8c1c6a..efca79ff53 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -37,7 +37,8 @@ system_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files( 'esp32c3_systimer.c' )) system_ss.add(when: 'CONFIG_XTENSA_ESP32S3', if_true: files( - 'esp32c3_timg.c', + 'esp_timg.c', + 'esp32s3_timg.c', 'esp_systimer.c', 'esp32s3_systimer.c' )) diff --git a/hw/xtensa/esp32s3.c b/hw/xtensa/esp32s3.c index 8c9ecc131e..b241dd7cd8 100644 --- a/hw/xtensa/esp32s3.c +++ b/hw/xtensa/esp32s3.c @@ -57,7 +57,7 @@ #include "hw/misc/esp32s3_rsa.h" #include "hw/misc/esp32s3_hmac.h" #include "hw/misc/esp32s3_ds.h" -#include "hw/timer/esp32c3_timg.h" +#include "hw/timer/esp32s3_timg.h" #include "hw/timer/esp32s3_systimer.h" #include "hw/gpio/esp32s3_gpio.h" #include "hw/misc/esp32s3_xts_aes.h" @@ -142,7 +142,7 @@ typedef struct Esp32s3SocState { ESP32S3PmsState pms; ESP32S3XtsAesState xts_aes; - ESP32C3TimgState timg[2]; + ESP32S3TimgState timg[2]; ESP32S3SysTimerState systimer; ESP32C3UsbJtagState jtag; @@ -614,8 +614,8 @@ static void esp32s3_machine_init(MachineState *machine) object_initialize_child(OBJECT(ss), "pms", &ss->pms, TYPE_ESP32S3_PMS); object_initialize_child(OBJECT(ss), "xts_aes", &ss->xts_aes, TYPE_ESP32S3_XTS_AES); - object_initialize_child(OBJECT(ss), "timg0", &ss->timg[0], TYPE_ESP32C3_TIMG); - object_initialize_child(OBJECT(ss), "timg1", &ss->timg[1], TYPE_ESP32C3_TIMG); + object_initialize_child(OBJECT(ss), "timg0", &ss->timg[0], TYPE_ESP32S3_TIMG); + object_initialize_child(OBJECT(ss), "timg1", &ss->timg[1], TYPE_ESP32S3_TIMG); object_initialize_child(OBJECT(ss), "systimer", &ss->systimer, TYPE_ESP32S3_SYSTIMER); object_initialize_child(OBJECT(ss), "rgb", &ss->rgb, TYPE_ESP_RGB); @@ -693,10 +693,13 @@ static void esp32s3_machine_init(MachineState *machine) MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ss->timg[0]), 0); memory_region_add_subregion_overlap(sys_mem, DR_REG_TIMERGROUP0_BASE, mr, 0); /* Connect the T0 interrupt line to the interrupt matrix */ - qdev_connect_gpio_out_named(DEVICE(&ss->timg[0]), ESP32C3_T0_IRQ_INTERRUPT, 0, + qdev_connect_gpio_out_named(DEVICE(&ss->timg[0]), ESP32S3_T0_IRQ_INTERRUPT, 0, qdev_get_gpio_in(intmatrix_dev, ETS_TG0_T0_LEVEL_INTR_SOURCE)); + /* Connect the T1 interrupt line to the interrupt matrix */ + qdev_connect_gpio_out_named(DEVICE(&ss->timg[0]), ESP32S3_T1_IRQ_INTERRUPT, 0, + qdev_get_gpio_in(intmatrix_dev, ETS_TG0_T1_LEVEL_INTR_SOURCE)); /* Connect the Watchdog interrupt line to the interrupt matrix */ - qdev_connect_gpio_out_named(DEVICE(&ss->timg[0]), ESP32C3_WDT_IRQ_INTERRUPT, 0, + qdev_connect_gpio_out_named(DEVICE(&ss->timg[0]), ESP32S3_WDT_IRQ_INTERRUPT, 0, qdev_get_gpio_in(intmatrix_dev, ETS_TG0_WDT_LEVEL_INTR_SOURCE)); } { @@ -704,9 +707,13 @@ static void esp32s3_machine_init(MachineState *machine) MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ss->timg[1]), 0); memory_region_add_subregion_overlap(sys_mem, DR_REG_TIMERGROUP1_BASE, mr, 0); /* Connect the T0 interrupt line to the interrupt matrix */ - qdev_connect_gpio_out_named(DEVICE(&ss->timg[1]), ESP32C3_T0_IRQ_INTERRUPT, 0, + qdev_connect_gpio_out_named(DEVICE(&ss->timg[1]), ESP32S3_T0_IRQ_INTERRUPT, 0, qdev_get_gpio_in(intmatrix_dev, ETS_TG1_T0_LEVEL_INTR_SOURCE)); - qdev_connect_gpio_out_named(DEVICE(&ss->timg[1]), ESP32C3_WDT_IRQ_INTERRUPT, 0, + /* Connect the T1 interrupt line to the interrupt matrix */ + qdev_connect_gpio_out_named(DEVICE(&ss->timg[1]), ESP32S3_T1_IRQ_INTERRUPT, 0, + qdev_get_gpio_in(intmatrix_dev, ETS_TG1_T1_LEVEL_INTR_SOURCE)); + /* Connect the Watchdog interrupt line to the interrupt matrix */ + qdev_connect_gpio_out_named(DEVICE(&ss->timg[1]), ESP32S3_WDT_IRQ_INTERRUPT, 0, qdev_get_gpio_in(intmatrix_dev, ETS_TG1_WDT_LEVEL_INTR_SOURCE)); } diff --git a/include/hw/timer/esp32s3_timg.h b/include/hw/timer/esp32s3_timg.h new file mode 100644 index 0000000000..ddb006299e --- /dev/null +++ b/include/hw/timer/esp32s3_timg.h @@ -0,0 +1,20 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/timer/esp_timg.h" + + +#define TYPE_ESP32S3_TIMG "timer.esp32s3.timg" +#define ESP32S3_TIMG(obj) OBJECT_CHECK(ESP32S3TimgState, (obj), TYPE_ESP32S3_TIMG) +#define ESP32S3_TIMG_GET_CLASS(obj) OBJECT_GET_CLASS(ESP32S3TimgClass, obj, TYPE_ESP32S3_TIMG) +#define ESP32S3_TIMG_CLASS(klass) OBJECT_CLASS_CHECK(ESP32S3TimgClass, klass, TYPE_ESP32S3_TIMG) + + +#define ESP32S3_T0_IRQ_INTERRUPT ESP_T0_IRQ_INTERRUPT +#define ESP32S3_T1_IRQ_INTERRUPT ESP_T1_IRQ_INTERRUPT +#define ESP32S3_WDT_IRQ_INTERRUPT ESP_WDT_IRQ_INTERRUPT +#define ESP32S3_WDT_IRQ_RESET ESP_WDT_IRQ_RESET + + +typedef ESPTimgState ESP32S3TimgState; +typedef ESPTimgClass ESP32S3TimgClass;