This patch implements the Instruction Cache Controller for the MAX78000 SOC
Signed-off-by: Jackson Donaldson <jc...@duck.com> --- hw/arm/Kconfig | 1 + hw/arm/max78000_soc.c | 20 ++++++-- hw/misc/Kconfig | 3 ++ hw/misc/max78000_icc.c | 89 ++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/arm/max78000_soc.h | 6 +++ include/hw/misc/max78000_icc.h | 34 +++++++++++++ 7 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 hw/misc/max78000_icc.c create mode 100644 include/hw/misc/max78000_icc.h diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 1c365d1115..3f23af3244 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -367,6 +367,7 @@ config ALLWINNER_R40 config MAX78000_SOC bool select ARM_V7M + select MAX78000_ICC config RASPI bool diff --git a/hw/arm/max78000_soc.c b/hw/arm/max78000_soc.c index 64578438bd..4d598bddd4 100644 --- a/hw/arm/max78000_soc.c +++ b/hw/arm/max78000_soc.c @@ -16,12 +16,19 @@ #include "hw/qdev-clock.h" #include "hw/misc/unimp.h" +static const uint32_t max78000_icc_addr[] = {0x4002a000, 0x4002a800}; + static void max78000_soc_initfn(Object *obj) { MAX78000State *s = MAX78000_SOC(obj); + int i; object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M); + for (i = 0; i < MAX78000_NUM_ICC; i++) { + object_initialize_child(obj, "icc[*]", &s->icc[i], TYPE_MAX78000_ICC); + } + s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0); s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0); } @@ -30,8 +37,9 @@ static void max78000_soc_realize(DeviceState *dev_soc, Error **errp) { MAX78000State *s = MAX78000_SOC(dev_soc); MemoryRegion *system_memory = get_system_memory(); - DeviceState *armv7m; + DeviceState *dev, *armv7m; Error *err = NULL; + int i; /* * We use s->refclk internally and only define it with qdev_init_clock_in() @@ -87,6 +95,13 @@ static void max78000_soc_realize(DeviceState *dev_soc, Error **errp) return; } + for (i = 0; i < MAX78000_NUM_ICC; i++) { + dev = DEVICE(&(s->icc[i])); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, max78000_icc_addr[i]); + } + + create_unimplemented_device("globalControl", 0x40000000, 0x400); create_unimplemented_device("systemInterface", 0x40000400, 0x400); create_unimplemented_device("functionControl", 0x40000800, 0x3400); @@ -120,9 +135,6 @@ static void max78000_soc_realize(DeviceState *dev_soc, Error **errp) create_unimplemented_device("standardDMA", 0x40028000, 0x1000); create_unimplemented_device("flashController0", 0x40029000, 0x400); - create_unimplemented_device("icc0", 0x4002a000, 0x800); - create_unimplemented_device("icc1", 0x4002a800, 0x800); - create_unimplemented_device("adc", 0x40034000, 0x1000); create_unimplemented_device("pulseTrainEngine", 0x4003c000, 0xa0); create_unimplemented_device("oneWireMaster", 0x4003d000, 0x1000); diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index ec0fa5aa9f..781bcf74cc 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -47,6 +47,9 @@ config A9SCU config ARM11SCU bool +config MAX78000_ICC + bool + config MOS6522 bool diff --git a/hw/misc/max78000_icc.c b/hw/misc/max78000_icc.c new file mode 100644 index 0000000000..3eacf6bd1b --- /dev/null +++ b/hw/misc/max78000_icc.c @@ -0,0 +1,89 @@ +/* + * MAX78000 Instruction Cache + * + * Copyright (c) 2025 Jackson Donaldson <jc...@duck.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "trace.h" +#include "hw/irq.h" +#include "migration/vmstate.h" +#include "hw/misc/max78000_icc.h" + + +static uint64_t max78000_icc_read(void *opaque, hwaddr addr, + unsigned int size) +{ + Max78000IccState *s = opaque; + switch (addr) { + case ICC_INFO:{ + return s->info; + } + case ICC_SZ:{ + return s->sz; + } + case ICC_CTRL:{ + return s->ctrl; + } + case ICC_INVALIDATE:{ + return s->invalidate; + } + default:{ + return 0; + } + } +} + +static void max78000_icc_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + Max78000IccState *s = opaque; + + switch (addr) { + case ICC_CTRL:{ + s->ctrl = 0x10000 + (val64 & 1); + break; + } + case ICC_INVALIDATE:{ + s->ctrl = s->ctrl | 0x80; + } + } +} + +static const MemoryRegionOps stm32f4xx_exti_ops = { + .read = max78000_icc_read, + .write = max78000_icc_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void max78000_icc_init(Object *obj) +{ + Max78000IccState *s = MAX78000_ICC(obj); + s->info = 0; + s->sz = 0x10000010; + s->ctrl = 0x10000; + s->invalidate = 0; + + + memory_region_init_io(&s->mmio, obj, &stm32f4xx_exti_ops, s, + TYPE_MAX78000_ICC, 0x800); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + +} + +static const TypeInfo max78000_icc_info = { + .name = TYPE_MAX78000_ICC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Max78000IccState), + .instance_init = max78000_icc_init, +}; + +static void max78000_icc_register_types(void) +{ + type_register_static(&max78000_icc_info); +} + +type_init(max78000_icc_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 6d47de482c..a21a994ff8 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -70,6 +70,7 @@ system_ss.add(when: 'CONFIG_IMX', if_true: files( 'imx_ccm.c', 'imx_rngc.c', )) +system_ss.add(when: 'CONFIG_MAX78000_ICC', if_true: files('max78000_icc.c')) system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files( 'npcm_clk.c', 'npcm_gcr.c', diff --git a/include/hw/arm/max78000_soc.h b/include/hw/arm/max78000_soc.h index 0e6def295d..207a4da68a 100644 --- a/include/hw/arm/max78000_soc.h +++ b/include/hw/arm/max78000_soc.h @@ -11,6 +11,7 @@ #include "hw/or-irq.h" #include "hw/arm/armv7m.h" +#include "hw/misc/max78000_icc.h" #include "qom/object.h" #define TYPE_MAX78000_SOC "max78000-soc" @@ -21,6 +22,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(MAX78000State, MAX78000_SOC) #define SRAM_BASE_ADDRESS 0x20000000 #define SRAM_SIZE (128 * 1024) +/* The MAX78k has 2 instruction caches; only icc0 matters, icc1 is for RISC */ +#define MAX78000_NUM_ICC 2 + struct MAX78000State { SysBusDevice parent_obj; @@ -29,6 +33,8 @@ struct MAX78000State { MemoryRegion sram; MemoryRegion flash; + Max78000IccState icc[MAX78000_NUM_ICC]; + Clock *sysclk; Clock *refclk; }; diff --git a/include/hw/misc/max78000_icc.h b/include/hw/misc/max78000_icc.h new file mode 100644 index 0000000000..fe9228e25d --- /dev/null +++ b/include/hw/misc/max78000_icc.h @@ -0,0 +1,34 @@ +/* + * MAX78000 Instruction Cache + * + * Copyright (c) 2025 Jackson Donaldson <jc...@duck.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_MAX78000_ICC_H +#define HW_MAX78000_ICC_H + +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_MAX78000_ICC "max78000-icc" +OBJECT_DECLARE_SIMPLE_TYPE(Max78000IccState, MAX78000_ICC) + +#define ICC_INFO 0x0 +#define ICC_SZ 0x4 +#define ICC_CTRL 0x100 +#define ICC_INVALIDATE 0x700 + +struct Max78000IccState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + + uint32_t info; + uint32_t sz; + uint32_t ctrl; + uint32_t invalidate; +}; + +#endif -- 2.34.1