diff --git a/.gitignore b/.gitignore index 0c5af83aa7454..74bb71abe2635 100644 --- a/.gitignore +++ b/.gitignore @@ -161,3 +161,6 @@ trace-dtrace-root.dtrace trace-ust-all.h trace-ust-all.c /target/arm/decode-sve.inc.c +storage-daemon/ +qemu-storage-daemon +roms diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000..60ea50e2a0a56 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.3) +project(qemu_dev) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +file(GLOB_RECURSE src "*.c" "*.h") + +set(SOURCES ${src}) +add_library(qemu_dev ${SOURCES}) +target_include_directories(qemu_dev PUBLIC "include" "target/arm" "") diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 534a6a119e5d7..fa34cd80718ef 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -54,3 +54,7 @@ obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o obj-$(CONFIG_ARM_SMMUV3) += smmu-common.o smmuv3.o obj-$(CONFIG_FSL_IMX6UL) += fsl-imx6ul.o mcimx6ul-evk.o obj-$(CONFIG_NRF51_SOC) += nrf51_soc.o +obj-y += amazfit.o +obj-y += da1469x/soc.o +obj-y += da1469x/qspi.o +obj-y += da1469x/timer.o diff --git a/hw/arm/amazfit.c b/hw/arm/amazfit.c new file mode 100644 index 0000000000000..437635643f62a --- /dev/null +++ b/hw/arm/amazfit.c @@ -0,0 +1,48 @@ +#include "qemu/osdep.h" +#include "hw/misc/unimp.h" +#include "hw/sysbus.h" +#include "hw/arm/armv7m.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/arm/boot.h" +#include "sysemu/sysemu.h" +#include "exec/address-spaces.h" +#include "hw/loader.h" +#include "hw/arm/da1469x/soc.h" +#include "qemu/log.h" +#include "hw/ssi/ssi.h" + +static void bip_s_init(MachineState *machine) { + DeviceState *dev; + dev = qdev_create(NULL, TYPE_DA1469X_SOC); + object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal); + + DA1469xState *soc = DA1469X_SOC(dev); + + /* --- QSPI Flash --------------------------------------------- */ + SSIBus *qspi = (SSIBus *) qdev_get_child_bus(DEVICE(&soc->qspi), "spi"); + DeviceState *qspi_flash = ssi_create_slave_no_init(qspi, "GD25LQ64C"); + DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); + if (dinfo) { + qdev_prop_set_drive(qspi_flash, "drive", blk_by_legacy_dinfo(dinfo), &error_fatal); + } + qdev_init_nofail(qspi_flash); + + qemu_irq cs_line = qdev_get_gpio_in_named(qspi_flash, SSI_GPIO_CS, 0); + sysbus_connect_irq(SYS_BUS_DEVICE(&soc->qspi), 1, cs_line); + + load_image_targphys("/Users/Marijn/Downloads/tonlesap_202006191826_2.1.1.16_tonlesap.img", 0x0, 0x8192 * 1024); + load_image_targphys("otp.bin", 0x10080000, 64 * 1024); + + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + 0x8192 * 1024); +} + +static void bip_s_machine_class_init(MachineClass *mc) +{ + mc->desc = "Amazfit Bip S"; + mc->init = bip_s_init; + mc->ignore_memory_transaction_failures = true; +} + +DEFINE_MACHINE("bip-s", bip_s_machine_class_init) diff --git a/hw/arm/da1469x/qspi.c b/hw/arm/da1469x/qspi.c new file mode 100644 index 0000000000000..c86c8a715faa4 --- /dev/null +++ b/hw/arm/da1469x/qspi.c @@ -0,0 +1,214 @@ +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/qdev-properties.h" +#include "qspi.h" +#include "qemu/log.h" +#include "hw/ssi/ssi.h" +#include "hw/irq.h" + +static const int QSPIC_CTRLBUS_REG = 0x00; +static const int QSPIC_CTRLMODE_REG = 0x04; +static const int QSPIC_BURSTCMDA_REG = 0x0C; +static const int QSPIC_BURSTCMDB_REG = 0x10; +static const int QSPIC_WRITEDATA_REG = 0x18; +static const int QSPIC_READDATA_REG = 0x1C; +static const int QSPIC_ERASECMDA_REG = 0x28; +static const int QSPIC_ERASECMDB_REG = 0x2C; +static const int QSPIC_BURSTBRK_REG = 0x30; +static const int QSPIC_STATUSCMD_REG = 0x34; + +static void da1469x_qspi_set_cs(DA1469xQspiState *s, bool low) { + qemu_set_irq(s->cs_line, !low); +} + +static uint64_t da1469x_qspic_read(void *opaque, hwaddr addr, unsigned size) { + DA1469xQspiState *s = opaque; + + if (addr == QSPIC_READDATA_REG && size == 1) { + uint32_t ret = ssi_transfer(s->spi, 0); + printf("[QSPI] - read -> 0x%X\n", ret); + return ret; + } + + switch (addr) { + case QSPIC_CTRLMODE_REG: { + int out = 0; + out |= s->AUTO_MD << 0; + out |= s->CLK_MD << 1; + out |= s->IO2_OEN << 2; + out |= s->IO3_OEN << 3; + out |= s->IO2_DAT << 4; + out |= s->IO3_DAT << 5; + out |= s->HRDY_MD << 6; + out |= s->RXD_NEG << 7; + out |= s->RPIPE_EN << 8; + out |= s->PCLK_MD << 9; + + out |= s->BUF_LIM_EN << 12; + out |= s->USE_32BA << 13; + return out; + } + case QSPIC_BURSTCMDA_REG: + case QSPIC_BURSTCMDB_REG: + case QSPIC_READDATA_REG: + case QSPIC_ERASECMDB_REG: + case QSPIC_BURSTBRK_REG: + case QSPIC_STATUSCMD_REG: + break; + + // For write + case QSPIC_WRITEDATA_REG: + break; + + default: + printf("READ case 0x%X:\n", addr); + } + return 0; +} + +static void da1469x_qspic_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { + + DA1469xQspiState *s = DA1469XQSPI(opaque); + + if (addr == QSPIC_WRITEDATA_REG) { + for (int i = 0; i < size; i++) { + uint8_t byte = (value >> (8 * i)) & 0xff; + uint32_t ret = ssi_transfer(s->spi, byte); + printf("[QSPI] - write 0x%X -> 0x%X\n", byte, ret); + } + return; + } + + switch (addr) { + case QSPIC_CTRLBUS_REG: + if (value & (1 << 0)) + qemu_log_mask(LOG_GUEST_ERROR, "QSPIC_SET_SINGLE\n"); + if (value & (1 << 1)) + qemu_log_mask(LOG_GUEST_ERROR, "QSPIC_SET_DUAL\n"); + if (value & (1 << 2)) + qemu_log_mask(LOG_GUEST_ERROR, "QSPIC_SET_QUAD\n"); + if (value & (1 << 3)) { + // QSPIC_EN_CS + printf("[QSPI] CS_LOW\n"); + da1469x_qspi_set_cs(opaque, true); + } + if (value & (1 << 4)) { + // QSPIC_DIS_CS + printf("[QSPI] CS_HIGH\n"); + da1469x_qspi_set_cs(opaque, false); + } + break; + + case QSPIC_STATUSCMD_REG: + case QSPIC_CTRLMODE_REG: + case QSPIC_ERASECMDB_REG: + case QSPIC_WRITEDATA_REG: + case QSPIC_BURSTCMDB_REG: + case QSPIC_ERASECMDA_REG: + case QSPIC_BURSTBRK_REG: + case QSPIC_BURSTCMDA_REG: { + uint64_t old = da1469x_qspic_read(opaque, addr, size); + qemu_log_mask(LOG_GUEST_ERROR, + "%"HWADDR_PRIx": 0x%X -> 0x%X (size: %d)\n", addr, old, value, size); + + } + + break; + + default: + printf("WRITE case 0x%X:\n", addr); + } +} + +static const MemoryRegionOps da1469x_qspic_ops = { + .read = da1469x_qspic_read, + .write = da1469x_qspic_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +#define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */ +static uint64_t da1469x_qspi_read(void *opaque, hwaddr addr, unsigned size) { + DA1469xQspiState *s = DA1469XQSPI(opaque); + + da1469x_qspi_set_cs(opaque, true); + + ssi_transfer(s->spi, SPI_OP_READ); + ssi_transfer(s->spi, (addr >> 16) & 0xff); + ssi_transfer(s->spi, (addr >> 8) & 0xff); + ssi_transfer(s->spi, (addr & 0xff)); + + uint64_t ret = 0; + for (int i = 0; i < size; i++) { + ret |= ssi_transfer(s->spi, 0x0) << (8 * i); + } + + da1469x_qspi_set_cs(opaque, false); + return ret; +} +static void da1469x_qspi_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { + +} + +static const MemoryRegionOps da1469x_qspi_ops = { + .read = da1469x_qspi_read, + .write = da1469x_qspi_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void da1469x_qspi_reset(DeviceState *dev) { + DA1469xQspiState *s = DA1469XQSPI(dev); + + s->AUTO_MD = 0; + s->CLK_MD = 0; + s->IO2_OEN = 0; + s->IO3_OEN = 0; + s->IO2_DAT = 0; + s->IO3_DAT = 0; + s->HRDY_MD = 0; + s->RXD_NEG = 0; + s->RPIPE_EN = 0; + s->PCLK_MD = 0; + s->BUF_LIM_EN = 0; + s->USE_32BA = 0; +} + +static void da1469x_qspi_init(Object *obj) { +} + +static void da1469x_qspi_realize(DeviceState *dev, Error **errp) { + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + DA1469xQspiState *s = DA1469XQSPI(dev); + + memory_region_init_io(&s->control, dev, &da1469x_qspic_ops, s, "QSPIC", 0x100); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->control); + + memory_region_init_io(&s->iomem, dev, &da1469x_qspi_ops, s, "QSPI", 0x2000000); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + + s->spi = ssi_create_bus(DEVICE(dev), "spi"); + + sysbus_init_irq(sbd, &s->_irq); + ssi_auto_connect_slaves(DEVICE(dev), &s->cs_line, s->spi); + sysbus_init_irq(sbd, &s->cs_line); +} + +static void da1469x_qspi_class_init(ObjectClass *klass, void *data) { + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = da1469x_qspi_reset; + dc->realize = da1469x_qspi_realize; +} + +static const TypeInfo da1469x_qspi_info = { + .name = TYPE_DA1469X_QSPI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(DA1469xQspiState), + .class_init = da1469x_qspi_class_init, + .instance_init = da1469x_qspi_init, +}; + +static void da1469x_qspi_register_types(void) { + type_register_static(&da1469x_qspi_info); +} + +type_init(da1469x_qspi_register_types) \ No newline at end of file diff --git a/hw/arm/da1469x/qspi.h b/hw/arm/da1469x/qspi.h new file mode 100644 index 0000000000000..24516c6364798 --- /dev/null +++ b/hw/arm/da1469x/qspi.h @@ -0,0 +1,32 @@ +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/qdev-properties.h" + +#define TYPE_DA1469X_QSPI "da1469x.qspi" +#define DA1469XQSPI(obj) OBJECT_CHECK(DA1469xQspiState, \ + (obj), TYPE_DA1469X_QSPI) + +typedef struct { + SysBusDevice parent_obj; + MemoryRegion control; + MemoryRegion iomem; + SSIBus *spi; + qemu_irq _irq; + + int AUTO_MD; + int CLK_MD; + int IO2_OEN; + int IO3_OEN; + int IO2_DAT; + int IO3_DAT; + int HRDY_MD; + + int RPIPE_EN; + int RXD_NEG; + int PCLK_MD; + int BUF_LIM_EN; + int USE_32BA; + + bool cs; + qemu_irq cs_line; +} DA1469xQspiState; diff --git a/hw/arm/da1469x/soc.c b/hw/arm/da1469x/soc.c new file mode 100644 index 0000000000000..e6dc023bf37ee --- /dev/null +++ b/hw/arm/da1469x/soc.c @@ -0,0 +1,669 @@ + +#include "qemu/osdep.h" +#include "hw/misc/unimp.h" +#include "hw/sysbus.h" +#include "hw/arm/armv7m.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/arm/boot.h" +#include "sysemu/sysemu.h" +#include "exec/address-spaces.h" +#include "hw/loader.h" +#include "qemu/log.h" +#include "hw/arm/da1469x/soc.h" + +static const int SRAM_BASE_ADDRESS = 0x20000000; +static const int OTPC_BASE = 0x30070000; +static const int MEMORY_QSPIF_S_BASE = 0x36000000; +static const int QSPIC_BASE = 0x38000000; +static const int CRG_TOP_BASE = 0x50000000; +static const int WAKEUP_BASE = 0x50000100; +static const int PDC_BASE = 0x50000200; +static const int DCDC_BASE = 0x50000300; +static const int RTC_BASE = 0x50000400; +static const int SYS_WDOG_BASE = 0x50000700; +static const int CRG_XTAL_BASE = 0x50010000; +static const int TIMER_BASE = 0x50010200; +static const int TIMER2_BASE = 0x50010300; +static const int SDADC_BASE = 0x50020800; +static const int CRG_COM_BASE = 0x50020900; +static const int GPIO_BASE = 0x50020A00; +static const int PWMLED_BASE = 0x50030500; +static const int GPADC_BASE = 0x50030900; +static const int LRA_BASE = 0x50030A00; +static const int CHIP_VERSION_BASE = 0x50040200; +static const int GPREG_BASE = 0x50040300; +static const int CHARGER_BASE = 0x50040400; +static const int CRG_SYS_BASE = 0x50040500; +static const int TIMER3_BASE = 0x50040A00; +static const int TIMER4_BASE = 0x50040B00; +static const int MEMCTRL_BASE = 0x50050000; + +static const uint32_t timer_addr[DA1469X_NUM_TIMERS] = { + TIMER_BASE, TIMER2_BASE, TIMER3_BASE, TIMER4_BASE +}; +static const int timer_irq[DA1469X_NUM_TIMERS] = {16, 17, 34, 35}; + +bool POWER_IS_UP = 1; +bool DBG_IS_ACTIVE = 0; +bool COM_IS_UP = 0; +bool COM_IS_DOWN = 1; +bool TIM_IS_UP = 0; +bool TIM_IS_DOWN = 1; +bool MEM_IS_UP = 1; +bool MEM_IS_DOWN = 0; +bool SYS_IS_UP = 1; +bool SYS_IS_DOWN = 0; +bool PER_IS_UP = 1; +bool PER_IS_DOWN = 0; +bool RAD_IS_UP = 1; +bool RAD_IS_DOWN = 0; + +#define SYS_STAT_OFFSET 0x28 + +#define SYS_STAT_POWER_IS_UP_BIT 13 +#define SYS_STAT_DBG_IS_ACTIVE_BIT 12 +#define SYS_STAT_COM_IS_UP_BIT 11 +#define SYS_STAT_COM_IS_DOWN_BIT 10 +#define SYS_STAT_TIM_IS_UP_BIT 9 +#define SYS_STAT_TIM_IS_DOWN_BIT 8 +#define SYS_STAT_MEM_IS_UP_BIT 7 +#define SYS_STAT_MEM_IS_DOWN_BIT 6 +#define SYS_STAT_SYS_IS_UP_BIT 5 +#define SYS_STAT_SYS_IS_DOWN_BIT 4 +#define SYS_STAT_PER_IS_UP_BIT 3 +#define SYS_STAT_PER_IS_DOWN_BIT 2 +#define SYS_STAT_RAD_IS_UP_BIT 1 +#define SYS_STAT_RAD_IS_DOWN_BIT 0 + +#define SYS_STAT_POWER_IS_UP (1U << SYS_STAT_POWER_IS_UP_BIT) +#define SYS_STAT_DBG_IS_ACTIVE (1U << SYS_STAT_DBG_IS_ACTIVE_BIT) +#define SYS_STAT_COM_IS_UP (1U << SYS_STAT_COM_IS_UP_BIT) +#define SYS_STAT_COM_IS_DOWN (1U << SYS_STAT_COM_IS_DOWN_BIT) +#define SYS_STAT_TIM_IS_UP (1U << SYS_STAT_TIM_IS_UP_BIT) +#define SYS_STAT_TIM_IS_DOWN (1U << SYS_STAT_TIM_IS_DOWN_BIT) +#define SYS_STAT_MEM_IS_UP (1U << SYS_STAT_MEM_IS_UP_BIT) +#define SYS_STAT_MEM_IS_DOWN (1U << SYS_STAT_MEM_IS_DOWN_BIT) +#define SYS_STAT_SYS_IS_UP (1U << SYS_STAT_SYS_IS_UP_BIT) +#define SYS_STAT_SYS_IS_DOWN (1U << SYS_STAT_SYS_IS_DOWN_BIT) +#define SYS_STAT_PER_IS_UP (1U << SYS_STAT_PER_IS_UP_BIT) +#define SYS_STAT_PER_IS_DOWN (1U << SYS_STAT_PER_IS_DOWN_BIT) +#define SYS_STAT_RAD_IS_UP (1U << SYS_STAT_RAD_IS_UP_BIT) +#define SYS_STAT_RAD_IS_DOWN (1U << SYS_STAT_RAD_IS_DOWN_BIT) + +#define PMU_CTRL_OFFSET 0x20 + +#define PMU_CTRL_ENABLE_CLKLESS_BIT 8 +#define PMU_CTRL_RETAIN_CACHE_BIT 7 +#define PMU_CTRL_SYS_SLEEP_BIT 6 +#define PMU_CTRL_RESET_ON_WAKEUP_BIT 5 +#define PMU_CTRL_MAP_BANDGAP_EN_BIT 4 +#define PMU_CTRL_COM_SLEEP_BIT 3 +#define PMU_CTRL_TIM_SLEEP_BIT 2 +#define PMU_CTRL_RADIO_SLEEP_BIT 1 +#define PMU_CTRL_PERIPH_SLEEP_BIT 0 +#define PMU_CTRL_ENABLE_CLKLESS (1U << PMU_CTRL_ENABLE_CLKLESS_BIT) +#define PMU_CTRL_RETAIN_CACHE (1U << PMU_CTRL_RETAIN_CACHE_BIT) +#define PMU_CTRL_SYS_SLEEP (1U << PMU_CTRL_SYS_SLEEP_BIT) +#define PMU_CTRL_RESET_ON_WAKEUP (1U << PMU_CTRL_RESET_ON_WAKEUP_BIT) +#define PMU_CTRL_MAP_BANDGAP_EN (1U << PMU_CTRL_MAP_BANDGAP_EN_BIT) +#define PMU_CTRL_COM_SLEEP (1U << PMU_CTRL_COM_SLEEP_BIT) +#define PMU_CTRL_TIM_SLEEP (1U << PMU_CTRL_TIM_SLEEP_BIT) +#define PMU_CTRL_RADIO_SLEEP (1U << PMU_CTRL_RADIO_SLEEP_BIT) +#define PMU_CTRL_PERIPH_SLEEP (1U << PMU_CTRL_PERIPH_SLEEP_BIT) + +#define CLK_CTRL_OFFSET 0x14 +#define CLK_CTRL_SYS_RUNNING_AT_PLL96M_BIT 15 +#define CLK_CTRL_SYS_RUNNING_AT_RC32M_BIT 14 +#define CLK_CTRL_SYS_RUNNING_AT_XTAL32M_BIT 13 +#define CLK_CTRL_SYS_RUNNING_AT_LP_CLK_BIT 12 +#define CLK_CTRL_SYS_CLK_SEL_BIT 0 + +#define CLK_SWITCH2XTAL_OFFSET 0x1C +#define CLK_SWITCH2XTAL_SWITCH2XTAL_BIT 0 +#define CLK_SWITCH2XTAL_SWITCH2XTAL (1U << CLK_SWITCH2XTAL_SWITCH2XTAL_BIT) + +bool pd_power = true; +bool pd_com = false; +bool pd_tim = false; +bool pd_mem = true; +bool pd_sys = true; +bool pd_per = false; +bool pd_rad = false; + +typedef enum sys_clk_is_type { + XTAL32M = 0, + RC32M = 1, + LowPower = 2, + PLL96Mhz = 3, +} sys_clk_is_t; + +sys_clk_is_t syc_clk = RC32M; + +static uint32_t getValue(hwaddr offset) { + switch (offset) { + + case CLK_CTRL_OFFSET: { + uint32_t out = 0; + out |= syc_clk << CLK_CTRL_SYS_CLK_SEL_BIT; + out |= 1 << 6; + + if (syc_clk == PLL96Mhz) + out |= 1U << CLK_CTRL_SYS_RUNNING_AT_PLL96M_BIT; + if (syc_clk == XTAL32M) + out |= 1U << CLK_CTRL_SYS_RUNNING_AT_XTAL32M_BIT; + if (syc_clk == RC32M) + out |= 1U << CLK_CTRL_SYS_RUNNING_AT_RC32M_BIT; + if (syc_clk == LowPower) + out |= 1U << CLK_CTRL_SYS_RUNNING_AT_LP_CLK_BIT; + + return out; + } + + case SYS_STAT_OFFSET: { + uint32_t out = 0; + + out |= pd_power ? SYS_STAT_POWER_IS_UP : 0; + out |= pd_com ? SYS_STAT_COM_IS_UP : SYS_STAT_COM_IS_DOWN; + out |= pd_tim ? SYS_STAT_TIM_IS_UP : SYS_STAT_TIM_IS_DOWN; + out |= pd_mem ? SYS_STAT_MEM_IS_UP : SYS_STAT_MEM_IS_DOWN; + out |= pd_sys ? SYS_STAT_SYS_IS_UP : SYS_STAT_SYS_IS_DOWN; + out |= pd_per ? SYS_STAT_PER_IS_UP : SYS_STAT_PER_IS_DOWN; + out |= pd_rad ? SYS_STAT_RAD_IS_UP : SYS_STAT_RAD_IS_DOWN; + return out; + } + + case PMU_CTRL_OFFSET: { + uint32_t out = 0; + + out |= pd_com == false ? PMU_CTRL_COM_SLEEP : 0; + out |= pd_tim == false ? PMU_CTRL_TIM_SLEEP : 0; + out |= pd_rad == false ? PMU_CTRL_RADIO_SLEEP : 0; + out |= pd_per == false ? PMU_CTRL_PERIPH_SLEEP : 0; + return out; + } + } + + return 0; +} + +static uint64_t pxa2xx_pic_mem_read(void *opaque, hwaddr offset, + unsigned size) { + + switch (offset) { + case 0x00: + case 0x10: + case 0x24: + case 0x3C: + case 0x40: + case 0x44: + case 0x48: + case 0x50: + case 0x60: + case 0x64: + case 0x78: + case 0x84: + case 0xbc: + case 0xf0: + case 0xF8: + case SYS_STAT_OFFSET: + case PMU_CTRL_OFFSET: + case CLK_CTRL_OFFSET: + return getValue(offset); + + default: + qemu_log_mask(LOG_UNIMP, "%s: unknown register 0x%02" HWADDR_PRIx "\n", + __func__, offset); + } + return 0; +} + +static void pxa2xx_pic_mem_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) { + + switch (offset) { + case 0x00: + case 0x10: + case 0x24: + case 0x3c: + case 0x40: + case 0x44: + case 0x48: + case 0x50: + case 0x60: + case 0x64: + case 0x74: + case 0x78: + case 0x80: + case 0x84: + case 0xa4: + case 0xc0: + case 0xf0: + case 0xf8: + case SYS_STAT_OFFSET: + case PMU_CTRL_OFFSET: + case CLK_CTRL_OFFSET: { + uint32_t current = getValue(offset);; +// printf("Write 0x%08llX to 0x%llX (was 0x%08X)\n", value, offset + 0x50000000, current); + break; + } + + default: + qemu_log_mask(LOG_UNIMP, "%s: unknown register 0x%02" HWADDR_PRIx "\n", + __func__, offset); + break; + } + + switch (offset) { + case PMU_CTRL_OFFSET: + pd_com = (value & PMU_CTRL_COM_SLEEP) ? false : true; + pd_rad = (value & PMU_CTRL_RADIO_SLEEP) ? false : true; + pd_per = (value & PMU_CTRL_PERIPH_SLEEP) ? false : true; + pd_tim = (value & PMU_CTRL_TIM_SLEEP) ? false : true; + break; + + case CLK_CTRL_OFFSET: +// syc_clk = (value >> CLK_CTRL_SYS_CLK_SEL_BIT) & 0b11; + break; + + case CLK_SWITCH2XTAL_OFFSET: + if (value & CLK_SWITCH2XTAL_SWITCH2XTAL) + syc_clk = XTAL32M; + break; + + } +} + +static const MemoryRegionOps crg_aon_ops = { + .read = pxa2xx_pic_mem_read, + .write = pxa2xx_pic_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +/** + * OTPC + */ + +#define OTPC 0x30070000 + +typedef enum { + HW_OTPC_MODE_PDOWN = 0, /**< OTP cell and LDO are inactive*/ + HW_OTPC_MODE_DSTBY = 1, /**< OTP cell is powered on LDO is inactive*/ + HW_OTPC_MODE_STBY = 2, /**< OTP cell and LDO are powered on, chip select is deactivated*/ + HW_OTPC_MODE_READ = 3, /**< OTP cell can be read*/ + HW_OTPC_MODE_PROG = 4, /**< OTP cell can be programmed*/ + HW_OTPC_MODE_PVFY = 5, /**< OTP cell can be read in PVFY margin read mode*/ + HW_OTPC_MODE_RINI = 6 /**< OTP cell can be read in RINI margin read mode*/ +} HW_OTPC_MODE; + +// Mode register +#define OTPC_MODE_REG 0x00 +#define OTPC_MODE_MODE_BIT 0 + +// Status register +#define OTPC_STAT_REG 0x04 + +// The address of the word that will be programmed, when the PROG mode is used. +#define OTPC_PADDR_REG 0x08 + +// The 32-bit word that will be programmed, when the PROG mode is used. +#define OTPC_PWORD_REG 0x0C + +// Various timing parameters of the OTP cell. +#define OTPC_TIM1_REG 0x10 + +// Various timing parameters of the OTP cell. +#define OTPC_TIM2_REG 0x14 + +HW_OTPC_MODE otpc_mode; + +static uint64_t otpc_mem_read(void *opaque, hwaddr offset, unsigned size) { + + switch (offset) { + case OTPC_MODE_REG: + return otpc_mode; + + case OTPC_STAT_REG: { + uint32_t out = 0; + out |= 1 << 0; + out |= 1 << 1; + out |= 1 << 2; + + return out; + } + } + + return 0; +} + +static void otpc_mem_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) { + switch (offset) { + case OTPC_MODE_REG: + otpc_mode = (value >> OTPC_MODE_MODE_BIT) & 0b111; + break; + } +} + +static const MemoryRegionOps otpc_ops = { + .read = otpc_mem_read, + .write = otpc_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + + +/** + * CRG_XTAL + */ + +#define PLL_SYS_CTRL1_REG 0x60 +#define CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_SEL_MIN_CUR_INT_BIT 14 +#define CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_PRE_DIV_BIT 11 +#define CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_N_DIV_BIT 4 +#define CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_VREF_HOLD_BIT 3 +#define CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_ENABLE_BIT 2 +#define CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_EN_BIT 1 +#define CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_ENABLE (1U << CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_ENABLE_BIT) +#define CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_EN (1U << CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_EN_BIT) + +#define PLL_SYS_STATUS_REG 0x70 +#define CRG_XTAL_PLL_SYS_STATUS_REG_LDO_PLL_OK_BIT 15 +#define CRG_XTAL_PLL_SYS_STATUS_REG_PLL_CALIBRATION_END_BIT 11 +#define CRG_XTAL_PLL_SYS_STATUS_REG_PLL_BEST_MIN_CUR_BIT 5 +#define CRG_XTAL_PLL_SYS_STATUS_REG_PLL_LOCK_FINE_BIT 0 + +bool ldoPllOn = false; +bool pllOn = false; + +static uint64_t crg_xtal_mem_read(void *opaque, hwaddr offset, unsigned size) { + + switch (offset) { + case PLL_SYS_CTRL1_REG: { + uint32_t out = 0; + out |= 1 << CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_SEL_MIN_CUR_INT_BIT; + out |= 2 << 12; + out |= 1 << CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_PRE_DIV_BIT; + out |= 6 << CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_N_DIV_BIT; + out |= 0 << CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_VREF_HOLD_BIT; + if (ldoPllOn) + out |= 1 << CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_ENABLE_BIT; + if (pllOn) + out |= 1 << CRG_XTAL_PLL_SYS_CTRL1_REG_PLL_EN_BIT; + + return out; + } + case PLL_SYS_STATUS_REG: { + uint32_t out = 0; + if (ldoPllOn) + out |= 1 << CRG_XTAL_PLL_SYS_STATUS_REG_LDO_PLL_OK_BIT; + if (false) { + out |= 1 << CRG_XTAL_PLL_SYS_STATUS_REG_PLL_CALIBRATION_END_BIT; + out |= 1 << CRG_XTAL_PLL_SYS_STATUS_REG_PLL_BEST_MIN_CUR_BIT; + out |= 1 << CRG_XTAL_PLL_SYS_STATUS_REG_PLL_LOCK_FINE_BIT; + } + + return out; + } + } + + return 0; +} + +static void crg_xtal_mem_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { + switch (offset) { + case PLL_SYS_CTRL1_REG: + if (value & CRG_XTAL_PLL_SYS_CTRL1_REG_LDO_PLL_ENABLE) { + ldoPllOn = true; + } else { + ldoPllOn = false; + } + break; + } +} +static const MemoryRegionOps crg_xtal_ops = { + .read = crg_xtal_mem_read, + .write = crg_xtal_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + + +/** + * SDADC + */ + +#define SDADC_RESULT_REG 0x18 + +static uint64_t sdadc_mem_read(void *opaque, hwaddr offset, unsigned size) { + switch (offset) { + case SDADC_RESULT_REG: + return 37000; + } + + return 0; +} + +static void sdadc_mem_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { + +} + +static const MemoryRegionOps sdadc_ops = { + .read = sdadc_mem_read, + .write = sdadc_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +/** + * MEMCTRL + */ + +#define CMI_CODE_BASE_REG 0x20 +#define CMI_DATA_BASE_REG 0x24 +#define CMI_SHARED_BASE_REG 0x28 +#define CMI_END_REG 0x2C +#define SNC_BASE_REG 0x30 +#define BUSY_SET_REG 0x74 +#define BUSY_RESET_REG 0x78 +#define BUSY_STAT_REG 0x7C + + +typedef enum { + HW_BSR_MASTER_NONE = 0, + HW_BSR_MASTER_SNC = 1, + HW_BSR_MASTER_SYSCPU = 2, + HW_BSR_MASTER_CMAC = 3, +} HW_BSR_MASTER_ID; + +static HW_BSR_MASTER_ID bsr[16] = {0}; + +static uint64_t memctrl_mem_read(void *opaque, hwaddr offset, unsigned size) { + + switch (offset) { + case BUSY_STAT_REG: { + uint32_t out = 0; + for (int i = 0; i < 16; i++) { + out |= bsr[i] << i * 2; + } + return out; + } + default: + printf("[MEMCTRL] Unknown read: 0x%"HWADDR_PRIx"\n", offset); + } + return 0; +} + +static void memctrl_mem_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { + switch (offset) { + case CMI_CODE_BASE_REG: + case CMI_DATA_BASE_REG: + case CMI_SHARED_BASE_REG: + case CMI_END_REG: + case SNC_BASE_REG: + break; + + case BUSY_RESET_REG: { + for (int i = 0; i < 16; i++) { + int newVal = (value >> (i * 2)) & 0b11; + if (newVal == bsr[i]) { + bsr[i] = HW_BSR_MASTER_NONE; + } + } + break; + } + + case BUSY_SET_REG: { + for (int i = 0; i < 16; i++) { + HW_BSR_MASTER_ID newVal = (value >> (i * 2)) & 0b11; + if (newVal != HW_BSR_MASTER_NONE) { + if (bsr[i] == HW_BSR_MASTER_NONE) { + bsr[i] = newVal; + } + } + } + break; + } + + default: + printf("[MEMCTRL] Unknown write: 0x%"HWADDR_PRIx"\n", offset); + break; + + break; + } +} + +static const MemoryRegionOps memctrl_ops = { + .read = memctrl_mem_read, + .write = memctrl_mem_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +/** + * Machine + */ + +static inline void create_unimplemented_layer(const char *name, hwaddr base, hwaddr size) { + DeviceState *dev = qdev_create(NULL, TYPE_UNIMPLEMENTED_DEVICE); + + qdev_prop_set_string(dev, "name", name); + qdev_prop_set_uint64(dev, "size", size); + qdev_init_nofail(dev); + + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, base, -900); +} + +static void da1469x_soc_initfn(Object *obj) { + DA1469xState *s = DA1469X_SOC(obj); + + sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m), TYPE_ARMV7M); + + sysbus_init_child_obj(obj, "qspi", &s->qspi, sizeof(s->qspi), TYPE_DA1469X_QSPI); + + for (int i = 0; i < DA1469X_NUM_TIMERS; i++) { + sysbus_init_child_obj(obj, "timer[*]", &s->timer[i], sizeof(s->timer[i]), TYPE_DA1469X_TIMER); + } +} + +static void da1469x_soc_realize(DeviceState *dev_soc, Error **errp) { + Error *err = NULL; + DA1469xState *bip = DA1469X_SOC(dev_soc); + + MemoryRegion *system_memory = get_system_memory(); + + DeviceState *armv7m = DEVICE(&bip->armv7m); + qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m33")); + object_property_set_link(OBJECT(&bip->armv7m), OBJECT(get_system_memory()), "memory", &error_abort); + object_property_set_bool(OBJECT(&bip->armv7m), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + + memory_region_init_ram(&bip->flash, NULL, "flash", 0x20000000, &err); + if (err != NULL) { + return; + } + memory_region_set_readonly(&bip->flash, true); + memory_region_add_subregion(system_memory, 0x00000000, &bip->flash); + + memory_region_init_ram(&bip->sysram, NULL, "system", 512 * 1024, &error_fatal); + memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &bip->sysram); + + create_unimplemented_device("PSRAM", 0x00000000, 0xFFFFFFFF); + + create_unimplemented_device("WKUP", WAKEUP_BASE, 0x100); + create_unimplemented_device("RTC", RTC_BASE, 0x100); + create_unimplemented_device("PWMWLED", PWMLED_BASE, 0x100); + create_unimplemented_device("CRG_2", CRG_SYS_BASE, 0x100); + create_unimplemented_device("LRA", LRA_BASE, 0x100); + create_unimplemented_device("CHIP_VERSION", CHIP_VERSION_BASE, 0x100); + create_unimplemented_device("CRG_COM", CRG_COM_BASE, 0x100); + create_unimplemented_device("GPIO", GPIO_BASE, 0x200); + create_unimplemented_device("GPADC", GPADC_BASE, 0x100); + create_unimplemented_device("DCDC", DCDC_BASE, 0x100); + create_unimplemented_device("SYS_WDOG", SYS_WDOG_BASE, 0x100); + create_unimplemented_device("GPREG", GPREG_BASE, 0x100); + create_unimplemented_device("CHARGER", CHARGER_BASE, 0x100); + create_unimplemented_device("MEMCTRL", MEMCTRL_BASE, 0x100); + + // Power Domains Controller + create_unimplemented_layer("PDC", PDC_BASE, 0x100); + + static uint32_t memctrl_val = 0xffffffff; + memory_region_init_io(&bip->memctrl, NULL, &memctrl_ops, &memctrl_val, "MEMCTRL", 0x100); + memory_region_add_subregion(system_memory, MEMCTRL_BASE, &bip->memctrl); + + static uint32_t sdadc_val = 0xffffffff; + memory_region_init_io(&bip->sdadc, NULL, &sdadc_ops, &sdadc_val, "SDADC", 0x100); + memory_region_add_subregion(system_memory, SDADC_BASE, &bip->sdadc); + + static uint32_t crg_aon_val = 0xffffffff; + memory_region_init_io(&bip->crg_aon, NULL, &crg_aon_ops, &crg_aon_val, "crc", 0x100); + memory_region_add_subregion(system_memory, CRG_TOP_BASE, &bip->crg_aon); + + static uint32_t crg_xtal_val = 0xffffffff; + memory_region_init_io(&bip->crg_xtal, NULL, &crg_xtal_ops, &crg_xtal_val, "crg_xtal", 0x100); + memory_region_add_subregion(system_memory, CRG_XTAL_BASE, &bip->crg_xtal); + + static uint32_t otpc_val = 0xffffffff; + memory_region_init_io(&bip->otpc_c, NULL, &otpc_ops, &otpc_val, "otpc", 0x80000); + memory_region_add_subregion(system_memory, OTPC_BASE, &bip->otpc_c); + + + DeviceState *dev = DEVICE(&(bip->qspi)); + object_property_set_bool(OBJECT(&bip->qspi), true, "realized", &err); + SysBusDevice *busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, QSPIC_BASE); + sysbus_mmio_map(busdev, 1, MEMORY_QSPIF_S_BASE); + + /* Timer 2 to 4 */ + for (int i = 1; i < DA1469X_NUM_TIMERS; i++) { + DeviceState *dev = DEVICE(&(bip->timer[i])); + object_property_set_bool(OBJECT(&bip->timer[i]), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + SysBusDevice *busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, timer_addr[i]); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i])); + } +} + +static void da1469x_soc_class_init(ObjectClass *klass, void *data) { + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = da1469x_soc_realize; +} + +static const TypeInfo da1469x_soc_info = { + .name = TYPE_DA1469X_SOC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(DA1469xState), + .instance_init = da1469x_soc_initfn, + .class_init = da1469x_soc_class_init, +}; + +static void da1469x_soc_types(void) { + type_register_static(&da1469x_soc_info); +} + +type_init(da1469x_soc_types) diff --git a/hw/arm/da1469x/soc.h b/hw/arm/da1469x/soc.h new file mode 100644 index 0000000000000..72bacbdfd0d96 --- /dev/null +++ b/hw/arm/da1469x/soc.h @@ -0,0 +1,30 @@ +#ifndef HW_ARM_STM32F205_SOC_H +#define HW_ARM_STM32F205_SOC_H + +#include "hw/arm/da1469x/qspi.h" +#include "hw/arm/da1469x/timer.h" + +#define TYPE_DA1469X_SOC "da1469x-soc" +#define DA1469X_SOC(obj) \ + OBJECT_CHECK(DA1469xState, obj, TYPE_DA1469X_SOC) + +#define DA1469X_NUM_TIMERS 4 + +typedef struct { + SysBusDevice parent_obj; + + ARMv7MState armv7m; + MemoryRegion flash; + MemoryRegion sysram; + + MemoryRegion crg_aon; + MemoryRegion sdadc; + MemoryRegion crg_xtal; + MemoryRegion otpc_c; + MemoryRegion memctrl; + + DA1469xQspiState qspi; + DA1469xTimerState timer[DA1469X_NUM_TIMERS]; +} DA1469xState; + +#endif diff --git a/hw/arm/da1469x/timer.c b/hw/arm/da1469x/timer.c new file mode 100644 index 0000000000000..b72709653a8b9 --- /dev/null +++ b/hw/arm/da1469x/timer.c @@ -0,0 +1,153 @@ +#include + +#include "qemu/osdep.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "timer.h" +#include "qemu/log.h" + +#ifndef STM_TIMER_ERR_DEBUG +#define STM_TIMER_ERR_DEBUG 1 +#endif + +#define DB_PRINT_L(lvl, fmt, args...) do { \ + if (STM_TIMER_ERR_DEBUG >= lvl) { \ + qemu_log("%s: " fmt, __func__, ## args); \ + } \ +} while (0) + +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) + +#define TIMER_CTRL_REG 0x00 +#define TIMER_TIMER_VAL_REG 0x04 +#define TIMER_STATUS_REG 0x08 +#define TIMER_GPIO1_CONF_REG 0x0C +#define TIMER_GPIO2_CONF_REG 0x10 +#define TIMER_RELOAD_REG 0x14 +// reserved +#define TIMER_PRESCALER_REG 0x1C +#define TIMER_CAPTURE_GPIO1_REG 0x20 +#define TIMER_CAPTURE_GPIO2_REG 0x24 +#define TIMER_PRESCALER_VAL_REG 0x28 +#define TIMER_PWM_FREQ_REG 0x2C +#define TIMER_PWM_DC_REG 0x30 +#define TIMER_CLEAR_IRQ_REG 0x34 + +static void da1469x_timer_set_alarm(DA1469xTimerState *s, int64_t now) { + + int stepsize = NANOSECONDS_PER_SECOND ; + timer_mod(s->timer, stepsize); +} + +static void da1469x_timer_interrupt(void *opaque) { + DA1469xTimerState *s = opaque; + + qemu_irq_pulse(s->irq); +} +static void da1469x_timer_reset(DeviceState *dev) { + +} +static uint64_t da1469x_timer_read(void *opaque, hwaddr offset, + unsigned size) { + + switch (offset) { + case TIMER_CTRL_REG: + case TIMER_TIMER_VAL_REG: + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, offset); + }; + return 0; +} + +static void da1469x_timer_write(void *opaque, hwaddr offset, + uint64_t val64, unsigned size) { + DA1469xTimerState *s = opaque; + uint32_t value = val64; + DB_PRINT("Write 0x%x, 0x%"HWADDR_PRIx"\n", value, offset); + + switch (offset) { + case TIMER_CTRL_REG: + s->en = (value >> 0u) & 1u; + s->oneshot_mode = (value >> 1u) & 1u; + s->count_down = (value >> 2u) & 1u; + s->IN1_EVENT_FALL_EN = (value >> 3u) & 1u; + s->IN2_EVENT_FALL_EN = (value >> 4u) & 1u; + s->IRQ_EN = (value >> 5u) & 1u; + s->FREE_RUN_MODE_EN = (value >> 6u) & 1u; + s->SYS_CLK_EN = (value >> 7u) & 1u; + s->CLK_EN = (value >> 8u) & 1u; + break; + case TIMER_GPIO1_CONF_REG: + s->gpio1_conf = value & 0x3Fu; + break; + case TIMER_GPIO2_CONF_REG: + s->gpio2_conf = value & 0x3Fu; + break; + case TIMER_RELOAD_REG: + s->reload = value & 0xFFFFFFu; + break; + case TIMER_PRESCALER_REG: + s->prescaler = value & 0x1Fu; + case TIMER_CLEAR_IRQ_REG: + // Write any value clear interrupt + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, offset); + }; + + if (s->en) { + da1469x_timer_set_alarm(s, s->hit_time); + da1469x_timer_set_alarm(s, s->hit_time); + } +} + +static const MemoryRegionOps da1469x_timer_ops = { + .read = da1469x_timer_read, + .write = da1469x_timer_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static Property da1469x_timer_properties[] = { +// DEFINE_PROP_UINT64("clock-frequency", DA1469xTimerState , +// freq_hz, 1000000000), + DEFINE_PROP_END_OF_LIST(), +}; + +static void da1469x_timer_init(Object *obj) { + DA1469xTimerState *s = DA1469XTIMER(obj); + + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); + + memory_region_init_io(&s->iomem, obj, &da1469x_timer_ops, s, "da1469x_timer", 0x100); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static void da1469x_timer_realize(DeviceState *dev, Error **errp) { + DA1469xTimerState *s = DA1469XTIMER(dev); + s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, da1469x_timer_interrupt, s); +} + +static void da1469x_timer_class_init(ObjectClass *klass, void *data) { + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = da1469x_timer_reset; + device_class_set_props(dc, da1469x_timer_properties); + dc->realize = da1469x_timer_realize; +} + +static const TypeInfo da1469x_timer_info = { + .name = TYPE_DA1469X_TIMER, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(DA1469xTimerState), + .instance_init = da1469x_timer_init, + .class_init = da1469x_timer_class_init, +}; + +static void da1469x_timer_register_types(void) { + type_register_static(&da1469x_timer_info); +} + +type_init(da1469x_timer_register_types) diff --git a/hw/arm/da1469x/timer.h b/hw/arm/da1469x/timer.h new file mode 100644 index 0000000000000..d878ec7c8fa70 --- /dev/null +++ b/hw/arm/da1469x/timer.h @@ -0,0 +1,32 @@ + + +#include "hw/sysbus.h" +#include "qemu/timer.h" + +#define TYPE_DA1469X_TIMER "da1469x-timer" +#define DA1469XTIMER(obj) OBJECT_CHECK(DA1469xTimerState, \ + (obj), TYPE_DA1469X_TIMER) + +typedef struct { + SysBusDevice parent_obj; + + QEMUTimer *timer; + qemu_irq irq; + MemoryRegion iomem; + + uint32_t gpio1_conf; + uint32_t gpio2_conf; + uint32_t reload; + uint32_t prescaler; + uint32_t en; + uint32_t CLK_EN; + uint32_t FREE_RUN_MODE_EN; + uint32_t SYS_CLK_EN; + uint32_t IN2_EVENT_FALL_EN; + uint32_t IN1_EVENT_FALL_EN; + uint32_t oneshot_mode; + uint32_t count_down; + uint32_t IRQ_EN; + + int64_t hit_time; +} DA1469xTimerState; \ No newline at end of file diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index 82270884416e3..7a6ce54f18736 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -201,6 +201,7 @@ static const FlashPartInfo known_devices[] = { /* GigaDevice */ { INFO("gd25q32", 0xc84016, 0, 64 << 10, 64, ER_4K) }, { INFO("gd25q64", 0xc84017, 0, 64 << 10, 128, ER_4K) }, + { INFO("GD25LQ64C", 0xc86017, 0, 64 << 10, 128, ER_4K) }, /* Intel/Numonyx -- xxxs33b */ { INFO("160s33b", 0x898911, 0, 64 << 10, 32, 0) },