---
(no changes since v3)
Changes in v3:
- New
docs/system/riscv/sifive_u.rst | 2 +-
include/hw/riscv/sifive_u.h | 3 +++
hw/riscv/sifive_u.c | 30 +++++++++++++-----------------
hw/riscv/Kconfig | 1 +
4 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
index 0e4dcf3e70..e91853ffe2 100644
--- a/docs/system/riscv/sifive_u.rst
+++ b/docs/system/riscv/sifive_u.rst
@@ -14,7 +14,7 @@ The ``sifive_u`` machine supports the following devices:
* Core Local Interruptor (CLINT)
* Platform-Level Interrupt Controller (PLIC)
* Power, Reset, Clock, Interrupt (PRCI)
-* L2 Loosely Integrated Memory (L2-LIM)
+* L2 cache controller, including L2-LIM and L2-Zero windows
* DDR memory controller
* 2 UARTs
* 1 GEM Ethernet controller
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index aed966a62d..be5e6232ce 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -28,6 +28,7 @@
#include "hw/gpio/sifive_gpio.h"
#include "hw/misc/sifive_u_otp.h"
#include "hw/misc/sifive_u_prci.h"
+#include "hw/misc/sifive_l2cc.h"
#include "hw/ssi/sifive_spi.h"
#include "hw/timer/sifive_pwm.h"
@@ -45,6 +46,7 @@ typedef struct SiFiveUSoCState {
RISCVHartArrayState e_cpus;
RISCVHartArrayState u_cpus;
DeviceState *plic;
+ SiFiveL2CCState l2cc;
SiFiveUPRCIState prci;
SIFIVEGPIOState gpio;
SiFiveUOTPState otp;
@@ -82,6 +84,7 @@ enum {
SIFIVE_U_DEV_L2CC,
SIFIVE_U_DEV_PDMA,
SIFIVE_U_DEV_L2LIM,
+ SIFIVE_U_DEV_L2ZERO,
SIFIVE_U_DEV_PLIC,
SIFIVE_U_DEV_PRCI,
SIFIVE_U_DEV_UART0,
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 1ac0d1bbd9..3603cc2aa2 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -73,6 +73,7 @@ static const MemMapEntry sifive_u_memmap[] = {
[SIFIVE_U_DEV_L2CC] = { 0x2010000, 0x1000 },
[SIFIVE_U_DEV_PDMA] = { 0x3000000, 0x100000 },
[SIFIVE_U_DEV_L2LIM] = { 0x8000000, 0x200000 },
+ [SIFIVE_U_DEV_L2ZERO] = { 0xa000000, 0x200000 },
[SIFIVE_U_DEV_PLIC] = { 0xc000000, 0x4000000 },
[SIFIVE_U_DEV_PRCI] = { 0x10000000, 0x1000 },
[SIFIVE_U_DEV_UART0] = { 0x10010000, 0x1000 },
@@ -715,6 +716,10 @@ static void sifive_u_soc_instance_init(Object *obj)
object_initialize_child(obj, "gem", &s->gem, TYPE_CADENCE_GEM);
object_initialize_child(obj, "gpio", &s->gpio, TYPE_SIFIVE_GPIO);
object_initialize_child(obj, "pdma", &s->dma, TYPE_SIFIVE_PDMA);
+ object_initialize_child(obj, "l2-cache-controller", &s->l2cc,
+ TYPE_SIFIVE_L2CC);
+ qdev_prop_set_uint64(DEVICE(&s->l2cc), "zero-size",
+ sifive_u_memmap[SIFIVE_U_DEV_L2ZERO].size);
object_initialize_child(obj, "spi0", &s->spi0, TYPE_SIFIVE_SPI);
object_initialize_child(obj, "spi2", &s->spi2, TYPE_SIFIVE_SPI);
object_initialize_child(obj, "pwm0", &s->pwm[0], TYPE_SIFIVE_PWM);
@@ -728,7 +733,6 @@ static void sifive_u_soc_realize(DeviceState *dev, Error
**errp)
const MemMapEntry *memmap = sifive_u_memmap;
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
- MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
char *plic_hart_config;
int i, j;
@@ -754,19 +758,14 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_MROM].base,
mask_rom);
- /*
- * Add L2-LIM at reset size.
- * This should be reduced in size as the L2 Cache Controller WayEnable
- * register is incremented. Unfortunately I don't see a nice (or any) way
- * to handle reducing or blocking out the L2 LIM while still allowing it
- * be re returned to all enabled after a reset. For the time being, just
- * leave it enabled all the time. This won't break anything, but will be
- * too generous to misbehaving guests.
- */
- memory_region_init_ram(l2lim_mem, NULL, "riscv.sifive.u.l2lim",
- memmap[SIFIVE_U_DEV_L2LIM].size, &error_fatal);
- memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_L2LIM].base,
- l2lim_mem);
+ /* L2 cache controller, LIM, and Zero windows */
+ sysbus_realize(SYS_BUS_DEVICE(&s->l2cc), &error_fatal);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->l2cc), SIFIVE_L2CC_MMIO_REGS,
+ memmap[SIFIVE_U_DEV_L2CC].base);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->l2cc), SIFIVE_L2CC_MMIO_LIM,
+ memmap[SIFIVE_U_DEV_L2LIM].base);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->l2cc), SIFIVE_L2CC_MMIO_ZERO,
+ memmap[SIFIVE_U_DEV_L2ZERO].base);
/* create PLIC hart topology configuration string */
plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus);
@@ -868,9 +867,6 @@ static void sifive_u_soc_realize(DeviceState *dev, Error
**errp)
create_unimplemented_device("riscv.sifive.u.dmc",
memmap[SIFIVE_U_DEV_DMC].base, memmap[SIFIVE_U_DEV_DMC].size);
- create_unimplemented_device("riscv.sifive.u.l2cc",
- memmap[SIFIVE_U_DEV_L2CC].base, memmap[SIFIVE_U_DEV_L2CC].size);
-
sysbus_realize(SYS_BUS_DEVICE(&s->spi0), errp);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi0), 0,
memmap[SIFIVE_U_DEV_QSPI0].base);
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 46a499f70f..b2b816de6a 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -99,6 +99,7 @@ config SIFIVE_U
select CPU_CLUSTER
select DEVICE_TREE
select RISCV_ACLINT
+ select SIFIVE_L2CC
select SIFIVE_GPIO
select SIFIVE_PDMA
select SIFIVE_PLIC