Refactor the OSPI controller creation using the VersalMap structure.
Note that the connection to the PMC IOU SLCR is removed for now and will
be re-added by next commits.
Signed-off-by: Luc Michel <luc.michel@amd.com>
---
include/hw/arm/xlnx-versal.h | 12 +--
hw/arm/xlnx-versal-virt.c | 41 ++++------
hw/arm/xlnx-versal.c | 142 ++++++++++++++++++++---------------
3 files changed, 98 insertions(+), 97 deletions(-)
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 79ca9b13321..b7ef255d6fd 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -18,12 +18,10 @@
#include "hw/or-irq.h"
#include "hw/intc/arm_gicv3.h"
#include "hw/rtc/xlnx-zynqmp-rtc.h"
#include "qom/object.h"
#include "hw/nvram/xlnx-bbram.h"
-#include "hw/ssi/xlnx-versal-ospi.h"
-#include "hw/dma/xlnx_csu_dma.h"
#include "hw/misc/xlnx-versal-crl.h"
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
#include "hw/misc/xlnx-versal-trng.h"
#include "net/can_emu.h"
#include "hw/misc/xlnx-versal-cfu.h"
@@ -86,18 +84,10 @@ struct Versal {
/* The Platform Management Controller subsystem. */
struct {
struct {
XlnxVersalPmcIouSlcr slcr;
-
- struct {
- XlnxVersalOspi ospi;
- XlnxCSUDMA dma_src;
- XlnxCSUDMA dma_dst;
- MemoryRegion linear_mr;
- OrIRQState irq_orgate;
- } ospi;
} iou;
XlnxZynqMPRTC rtc;
XlnxVersalTRng trng;
XlnxBBRam bbram;
@@ -134,10 +124,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
s->cfg.fdt = fdt;
}
void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
+void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
+ BlockBackend *blk);
int versal_get_num_can(VersalVersion version);
int versal_get_num_sdhci(VersalVersion version);
/* Memory-map and IRQ definitions. Copied a subset from
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index d3c84d1955a..43f3c3d0be9 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -46,12 +46,12 @@ struct VersalVirt {
CanBusState **canbus;
struct {
bool secure;
+ char *ospi_model;
} cfg;
- char *ospi_model;
};
static void fdt_create(VersalVirt *s)
{
MachineClass *mc = MACHINE_GET_CLASS(s);
@@ -379,19 +379,19 @@ static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
static char *versal_get_ospi_model(Object *obj, Error **errp)
{
VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
- return g_strdup(s->ospi_model);
+ return g_strdup(s->cfg.ospi_model);
}
static void versal_set_ospi_model(Object *obj, const char *value, Error **errp)
{
VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
- g_free(s->ospi_model);
- s->ospi_model = g_strdup(value);
+ g_free(s->cfg.ospi_model);
+ s->cfg.ospi_model = g_strdup(value);
}
static void versal_virt_init(MachineState *machine)
{
@@ -480,42 +480,31 @@ static void versal_virt_init(MachineState *machine)
s->binfo.dtb_limit = 0x1000000;
}
arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
- BusState *spi_bus;
- DeviceState *flash_dev;
ObjectClass *flash_klass;
- qemu_irq cs_line;
DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
+ BlockBackend *blk;
+ const char *mdl;
- spi_bus = qdev_get_child_bus(DEVICE(&s->soc.pmc.iou.ospi), "spi0");
-
- if (s->ospi_model) {
- flash_klass = object_class_by_name(s->ospi_model);
+ if (s->cfg.ospi_model) {
+ flash_klass = object_class_by_name(s->cfg.ospi_model);
if (!flash_klass ||
object_class_is_abstract(flash_klass) ||
!object_class_dynamic_cast(flash_klass, TYPE_M25P80)) {
error_report("'%s' is either abstract or"
- " not a subtype of m25p80", s->ospi_model);
+ " not a subtype of m25p80", s->cfg.ospi_model);
exit(1);
}
+ mdl = s->cfg.ospi_model;
+ } else {
+ mdl = "mt35xu01g";
}
- flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g");
-
- if (dinfo) {
- qdev_prop_set_drive_err(flash_dev, "drive",
- blk_by_legacy_dinfo(dinfo), &error_fatal);
- }
- qdev_prop_set_uint8(flash_dev, "cs", i);
- qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
-
- cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
-
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.pmc.iou.ospi),
- i + 1, cs_line);
+ blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+ versal_ospi_create_flash(&s->soc, i, mdl, blk);
}
}
static void versal_virt_machine_instance_init(Object *obj)
{
@@ -540,11 +529,11 @@ static void versal_virt_machine_instance_init(Object *obj)
static void versal_virt_machine_finalize(Object *obj)
{
VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
- g_free(s->ospi_model);
+ g_free(s->cfg.ospi_model);
g_free(s->canbus);
}
static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
{
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index ed202b0fcda..58176fa11e5 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -32,10 +32,11 @@
#include "hw/net/cadence_gem.h"
#include "hw/dma/xlnx-zdma.h"
#include "hw/misc/xlnx-versal-xramc.h"
#include "hw/usb/xlnx-usb-subsystem.h"
#include "hw/nvram/xlnx-versal-efuse.h"
+#include "hw/ssi/xlnx-versal-ospi.h"
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
#define GEM_REVISION 0x40070106
@@ -93,10 +94,19 @@ typedef struct VersalMap {
struct VersalEfuseMap {
uint64_t ctrl;
uint64_t cache;
int irq;
} efuse;
+
+ struct VersalOspiMap {
+ uint64_t ctrl;
+ uint64_t dac;
+ uint64_t dac_sz;
+ uint64_t dma_src;
+ uint64_t dma_dst;
+ int irq;
+ } ospi;
} VersalMap;
static const VersalMap VERSAL_MAP = {
.uart[0] = { 0xff000000, 18 },
.uart[1] = { 0xff010000, 19 },
@@ -126,10 +136,17 @@ static const VersalMap VERSAL_MAP = {
.usb[0] = { .xhci = 0xfe200000, .ctrl = 0xff9d0000, .irq = 22 },
.num_usb = 1,
.efuse = { .ctrl = 0xf1240000, .cache = 0xf1250000, .irq = 139 },
+
+ .ospi = {
+ .ctrl = 0xf1010000,
+ .dac = 0xc0000000, .dac_sz = 0x20000000,
+ .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
+ .irq = 124,
+ },
};
static const VersalMap *VERSION_TO_MAP[] = {
[VERSAL_VER_VERSAL] = &VERSAL_MAP,
};
@@ -807,99 +824,78 @@ static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
sysbus_connect_irq(sbd, 0,
qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2));
}
-static void versal_create_ospi(Versal *s, qemu_irq *pic)
+static DeviceState *versal_create_ospi(Versal *s,
+ const struct VersalOspiMap *map)
{
SysBusDevice *sbd;
MemoryRegion *mr_dac;
- qemu_irq ospi_mux_sel;
- DeviceState *orgate;
+ DeviceState *dev, *dma_dst, *dma_src, *orgate;
+ MemoryRegion *linear_mr = g_new(MemoryRegion, 1);
- memory_region_init(&s->pmc.iou.ospi.linear_mr, OBJECT(s),
- "versal-ospi-linear-mr" , MM_PMC_OSPI_DAC_SIZE);
+ dev = qdev_new(TYPE_XILINX_VERSAL_OSPI);
+ object_property_add_child(OBJECT(s), "ospi", OBJECT(dev));
- object_initialize_child(OBJECT(s), "versal-ospi", &s->pmc.iou.ospi.ospi,
- TYPE_XILINX_VERSAL_OSPI);
+ memory_region_init(linear_mr, OBJECT(dev), "linear-mr", map->dac_sz);
- mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 1);
- memory_region_add_subregion(&s->pmc.iou.ospi.linear_mr, 0x0, mr_dac);
+ mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
+ memory_region_add_subregion(linear_mr, 0x0, mr_dac);
/* Create the OSPI destination DMA */
- object_initialize_child(OBJECT(s), "versal-ospi-dma-dst",
- &s->pmc.iou.ospi.dma_dst,
- TYPE_XLNX_CSU_DMA);
+ dma_dst = qdev_new(TYPE_XLNX_CSU_DMA);
+ object_property_add_child(OBJECT(dev), "dma-dst-dev", OBJECT(dma_dst));
+ object_property_set_link(OBJECT(dma_dst), "dma",
+ OBJECT(get_system_memory()), &error_abort);
- object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_dst),
- "dma", OBJECT(get_system_memory()),
- &error_abort);
+ sbd = SYS_BUS_DEVICE(dma_dst);
+ sysbus_realize_and_unref(sbd, &error_fatal);
- sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst);
- sysbus_realize(sbd, &error_fatal);
-
- memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_DST,
+ memory_region_add_subregion(&s->mr_ps, map->dma_dst,
sysbus_mmio_get_region(sbd, 0));
/* Create the OSPI source DMA */
- object_initialize_child(OBJECT(s), "versal-ospi-dma-src",
- &s->pmc.iou.ospi.dma_src,
- TYPE_XLNX_CSU_DMA);
+ dma_src = qdev_new(TYPE_XLNX_CSU_DMA);
+ object_property_add_child(OBJECT(dev), "dma-src-dev", OBJECT(dma_src));
- object_property_set_bool(OBJECT(&s->pmc.iou.ospi.dma_src), "is-dst",
- false, &error_abort);
+ object_property_set_bool(OBJECT(dma_src), "is-dst", false, &error_abort);
- object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
- "dma", OBJECT(mr_dac), &error_abort);
-
- object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
- "stream-connected-dma",
- OBJECT(&s->pmc.iou.ospi.dma_dst),
+ object_property_set_link(OBJECT(dma_src), "dma", OBJECT(mr_dac),
&error_abort);
- sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src);
- sysbus_realize(sbd, &error_fatal);
+ object_property_set_link(OBJECT(dma_src), "stream-connected-dma",
+ OBJECT(dma_dst), &error_abort);
- memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_SRC,
+ sbd = SYS_BUS_DEVICE(dma_src);
+ sysbus_realize_and_unref(sbd, &error_fatal);
+
+ memory_region_add_subregion(&s->mr_ps, map->dma_src,
sysbus_mmio_get_region(sbd, 0));
/* Realize the OSPI */
- object_property_set_link(OBJECT(&s->pmc.iou.ospi.ospi), "dma-src",
- OBJECT(&s->pmc.iou.ospi.dma_src), &error_abort);
+ object_property_set_link(OBJECT(dev), "dma-src",
+ OBJECT(dma_src), &error_abort);
- sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi);
- sysbus_realize(sbd, &error_fatal);
+ sbd = SYS_BUS_DEVICE(dev);
+ sysbus_realize_and_unref(sbd, &error_fatal);
- memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI,
+ memory_region_add_subregion(&s->mr_ps, map->ctrl,
sysbus_mmio_get_region(sbd, 0));
- memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DAC,
- &s->pmc.iou.ospi.linear_mr);
-
- /* ospi_mux_sel */
- ospi_mux_sel = qdev_get_gpio_in_named(DEVICE(&s->pmc.iou.ospi.ospi),
- "ospi-mux-sel", 0);
- qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "ospi-mux-sel", 0,
- ospi_mux_sel);
+ memory_region_add_subregion(&s->mr_ps, map->dac,
+ linear_mr);
/* OSPI irq */
- object_initialize_child(OBJECT(s), "ospi-irq-orgate",
- &s->pmc.iou.ospi.irq_orgate, TYPE_OR_IRQ);
- object_property_set_int(OBJECT(&s->pmc.iou.ospi.irq_orgate),
- "num-lines", NUM_OSPI_IRQ_LINES, &error_fatal);
+ orgate = create_or_gate(s, OBJECT(dev), "irq-orgate", NUM_OSPI_IRQ_LINES,
+ map->irq);
- orgate = DEVICE(&s->pmc.iou.ospi.irq_orgate);
- qdev_realize(orgate, NULL, &error_fatal);
+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(orgate, 0));
+ sysbus_connect_irq(SYS_BUS_DEVICE(dma_src), 0, qdev_get_gpio_in(orgate, 1));
+ sysbus_connect_irq(SYS_BUS_DEVICE(dma_dst), 0, qdev_get_gpio_in(orgate, 2));
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 0,
- qdev_get_gpio_in(orgate, 0));
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src), 0,
- qdev_get_gpio_in(orgate, 1));
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst), 0,
- qdev_get_gpio_in(orgate, 2));
-
- qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
+ return dev;
}
static void versal_create_cfu(Versal *s, qemu_irq *pic)
{
SysBusDevice *sbd;
@@ -1256,17 +1252,17 @@ static void versal_realize(DeviceState *dev, Error **errp)
for (i = 0; i < map->num_usb; i++) {
versal_create_usb(s, &map->usb[i]);
}
versal_create_efuse(s, &map->efuse);
+ versal_create_ospi(s, &map->ospi);
versal_create_pmc_apb_irq_orgate(s, pic);
versal_create_rtc(s, pic);
versal_create_trng(s, pic);
versal_create_bbram(s, pic);
versal_create_pmc_iou_slcr(s, pic);
- versal_create_ospi(s, pic);
versal_create_crl(s, pic);
versal_create_cfu(s, pic);
versal_map_ddr(s);
versal_unimp(s);
@@ -1308,10 +1304,34 @@ void versal_efuse_attach_drive(Versal *s, BlockBackend *blk)
}
qdev_prop_set_drive(efuse, "drive", blk);
}
+void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
+ BlockBackend *blk)
+{
+ BusState *spi_bus;
+ DeviceState *flash, *ospi;
+ qemu_irq cs_line;
+
+ ospi = DEVICE(versal_get_child(s, "ospi"));
+ spi_bus = qdev_get_child_bus(ospi, "spi0");
+
+ flash = qdev_new(flash_mdl);
+
+ if (blk) {
+ qdev_prop_set_drive_err(flash, "drive", blk, &error_fatal);
+ }
+ qdev_prop_set_uint8(flash, "cs", flash_idx);
+ qdev_realize_and_unref(flash, spi_bus, &error_fatal);
+
+ cs_line = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(ospi),
+ flash_idx + 1, cs_line);
+}
+
int versal_get_num_can(VersalVersion version)
{
const VersalMap *map = VERSION_TO_MAP[version];
return map->num_canfd;
--
2.50.0
On Wed, Jul 16, 2025 at 11:53:54AM +0200, Luc Michel wrote:
> Refactor the OSPI controller creation using the VersalMap structure.
>
> Note that the connection to the PMC IOU SLCR is removed for now and will
> be re-added by next commits.
>
> Signed-off-by: Luc Michel <luc.michel@amd.com>
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
> ---
> include/hw/arm/xlnx-versal.h | 12 +--
> hw/arm/xlnx-versal-virt.c | 41 ++++------
> hw/arm/xlnx-versal.c | 142 ++++++++++++++++++++---------------
> 3 files changed, 98 insertions(+), 97 deletions(-)
>
> diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
> index 79ca9b13321..b7ef255d6fd 100644
> --- a/include/hw/arm/xlnx-versal.h
> +++ b/include/hw/arm/xlnx-versal.h
> @@ -18,12 +18,10 @@
> #include "hw/or-irq.h"
> #include "hw/intc/arm_gicv3.h"
> #include "hw/rtc/xlnx-zynqmp-rtc.h"
> #include "qom/object.h"
> #include "hw/nvram/xlnx-bbram.h"
> -#include "hw/ssi/xlnx-versal-ospi.h"
> -#include "hw/dma/xlnx_csu_dma.h"
> #include "hw/misc/xlnx-versal-crl.h"
> #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
> #include "hw/misc/xlnx-versal-trng.h"
> #include "net/can_emu.h"
> #include "hw/misc/xlnx-versal-cfu.h"
> @@ -86,18 +84,10 @@ struct Versal {
>
> /* The Platform Management Controller subsystem. */
> struct {
> struct {
> XlnxVersalPmcIouSlcr slcr;
> -
> - struct {
> - XlnxVersalOspi ospi;
> - XlnxCSUDMA dma_src;
> - XlnxCSUDMA dma_dst;
> - MemoryRegion linear_mr;
> - OrIRQState irq_orgate;
> - } ospi;
> } iou;
>
> XlnxZynqMPRTC rtc;
> XlnxVersalTRng trng;
> XlnxBBRam bbram;
> @@ -134,10 +124,12 @@ static inline void versal_set_fdt(Versal *s, void *fdt)
> s->cfg.fdt = fdt;
> }
>
> void versal_sdhci_plug_card(Versal *s, int sd_idx, BlockBackend *blk);
> void versal_efuse_attach_drive(Versal *s, BlockBackend *blk);
> +void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
> + BlockBackend *blk);
>
> int versal_get_num_can(VersalVersion version);
> int versal_get_num_sdhci(VersalVersion version);
>
> /* Memory-map and IRQ definitions. Copied a subset from
> diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
> index d3c84d1955a..43f3c3d0be9 100644
> --- a/hw/arm/xlnx-versal-virt.c
> +++ b/hw/arm/xlnx-versal-virt.c
> @@ -46,12 +46,12 @@ struct VersalVirt {
>
> CanBusState **canbus;
>
> struct {
> bool secure;
> + char *ospi_model;
> } cfg;
> - char *ospi_model;
> };
>
> static void fdt_create(VersalVirt *s)
> {
> MachineClass *mc = MACHINE_GET_CLASS(s);
> @@ -379,19 +379,19 @@ static void sd_plug_card(VersalVirt *s, int idx, DriveInfo *di)
>
> static char *versal_get_ospi_model(Object *obj, Error **errp)
> {
> VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
>
> - return g_strdup(s->ospi_model);
> + return g_strdup(s->cfg.ospi_model);
> }
>
> static void versal_set_ospi_model(Object *obj, const char *value, Error **errp)
> {
> VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
>
> - g_free(s->ospi_model);
> - s->ospi_model = g_strdup(value);
> + g_free(s->cfg.ospi_model);
> + s->cfg.ospi_model = g_strdup(value);
> }
>
>
> static void versal_virt_init(MachineState *machine)
> {
> @@ -480,42 +480,31 @@ static void versal_virt_init(MachineState *machine)
> s->binfo.dtb_limit = 0x1000000;
> }
> arm_load_kernel(&s->soc.fpd.apu.cpu[0], machine, &s->binfo);
>
> for (i = 0; i < XLNX_VERSAL_NUM_OSPI_FLASH; i++) {
> - BusState *spi_bus;
> - DeviceState *flash_dev;
> ObjectClass *flash_klass;
> - qemu_irq cs_line;
> DriveInfo *dinfo = drive_get(IF_MTD, 0, i);
> + BlockBackend *blk;
> + const char *mdl;
>
> - spi_bus = qdev_get_child_bus(DEVICE(&s->soc.pmc.iou.ospi), "spi0");
> -
> - if (s->ospi_model) {
> - flash_klass = object_class_by_name(s->ospi_model);
> + if (s->cfg.ospi_model) {
> + flash_klass = object_class_by_name(s->cfg.ospi_model);
> if (!flash_klass ||
> object_class_is_abstract(flash_klass) ||
> !object_class_dynamic_cast(flash_klass, TYPE_M25P80)) {
> error_report("'%s' is either abstract or"
> - " not a subtype of m25p80", s->ospi_model);
> + " not a subtype of m25p80", s->cfg.ospi_model);
> exit(1);
> }
> + mdl = s->cfg.ospi_model;
> + } else {
> + mdl = "mt35xu01g";
> }
>
> - flash_dev = qdev_new(s->ospi_model ? s->ospi_model : "mt35xu01g");
> -
> - if (dinfo) {
> - qdev_prop_set_drive_err(flash_dev, "drive",
> - blk_by_legacy_dinfo(dinfo), &error_fatal);
> - }
> - qdev_prop_set_uint8(flash_dev, "cs", i);
> - qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
> -
> - cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
> -
> - sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.pmc.iou.ospi),
> - i + 1, cs_line);
> + blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
> + versal_ospi_create_flash(&s->soc, i, mdl, blk);
> }
> }
>
> static void versal_virt_machine_instance_init(Object *obj)
> {
> @@ -540,11 +529,11 @@ static void versal_virt_machine_instance_init(Object *obj)
>
> static void versal_virt_machine_finalize(Object *obj)
> {
> VersalVirt *s = XLNX_VERSAL_VIRT_MACHINE(obj);
>
> - g_free(s->ospi_model);
> + g_free(s->cfg.ospi_model);
> g_free(s->canbus);
> }
>
> static void versal_virt_machine_class_init(ObjectClass *oc, const void *data)
> {
> diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
> index ed202b0fcda..58176fa11e5 100644
> --- a/hw/arm/xlnx-versal.c
> +++ b/hw/arm/xlnx-versal.c
> @@ -32,10 +32,11 @@
> #include "hw/net/cadence_gem.h"
> #include "hw/dma/xlnx-zdma.h"
> #include "hw/misc/xlnx-versal-xramc.h"
> #include "hw/usb/xlnx-usb-subsystem.h"
> #include "hw/nvram/xlnx-versal-efuse.h"
> +#include "hw/ssi/xlnx-versal-ospi.h"
>
> #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
> #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
> #define GEM_REVISION 0x40070106
>
> @@ -93,10 +94,19 @@ typedef struct VersalMap {
> struct VersalEfuseMap {
> uint64_t ctrl;
> uint64_t cache;
> int irq;
> } efuse;
> +
> + struct VersalOspiMap {
> + uint64_t ctrl;
> + uint64_t dac;
> + uint64_t dac_sz;
> + uint64_t dma_src;
> + uint64_t dma_dst;
> + int irq;
> + } ospi;
> } VersalMap;
>
> static const VersalMap VERSAL_MAP = {
> .uart[0] = { 0xff000000, 18 },
> .uart[1] = { 0xff010000, 19 },
> @@ -126,10 +136,17 @@ static const VersalMap VERSAL_MAP = {
>
> .usb[0] = { .xhci = 0xfe200000, .ctrl = 0xff9d0000, .irq = 22 },
> .num_usb = 1,
>
> .efuse = { .ctrl = 0xf1240000, .cache = 0xf1250000, .irq = 139 },
> +
> + .ospi = {
> + .ctrl = 0xf1010000,
> + .dac = 0xc0000000, .dac_sz = 0x20000000,
> + .dma_src = 0xf1011000, .dma_dst = 0xf1011800,
> + .irq = 124,
> + },
> };
>
> static const VersalMap *VERSION_TO_MAP[] = {
> [VERSAL_VER_VERSAL] = &VERSAL_MAP,
> };
> @@ -807,99 +824,78 @@ static void versal_create_pmc_iou_slcr(Versal *s, qemu_irq *pic)
>
> sysbus_connect_irq(sbd, 0,
> qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 2));
> }
>
> -static void versal_create_ospi(Versal *s, qemu_irq *pic)
> +static DeviceState *versal_create_ospi(Versal *s,
> + const struct VersalOspiMap *map)
> {
> SysBusDevice *sbd;
> MemoryRegion *mr_dac;
> - qemu_irq ospi_mux_sel;
> - DeviceState *orgate;
> + DeviceState *dev, *dma_dst, *dma_src, *orgate;
> + MemoryRegion *linear_mr = g_new(MemoryRegion, 1);
>
> - memory_region_init(&s->pmc.iou.ospi.linear_mr, OBJECT(s),
> - "versal-ospi-linear-mr" , MM_PMC_OSPI_DAC_SIZE);
> + dev = qdev_new(TYPE_XILINX_VERSAL_OSPI);
> + object_property_add_child(OBJECT(s), "ospi", OBJECT(dev));
>
> - object_initialize_child(OBJECT(s), "versal-ospi", &s->pmc.iou.ospi.ospi,
> - TYPE_XILINX_VERSAL_OSPI);
> + memory_region_init(linear_mr, OBJECT(dev), "linear-mr", map->dac_sz);
>
> - mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 1);
> - memory_region_add_subregion(&s->pmc.iou.ospi.linear_mr, 0x0, mr_dac);
> + mr_dac = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
> + memory_region_add_subregion(linear_mr, 0x0, mr_dac);
>
> /* Create the OSPI destination DMA */
> - object_initialize_child(OBJECT(s), "versal-ospi-dma-dst",
> - &s->pmc.iou.ospi.dma_dst,
> - TYPE_XLNX_CSU_DMA);
> + dma_dst = qdev_new(TYPE_XLNX_CSU_DMA);
> + object_property_add_child(OBJECT(dev), "dma-dst-dev", OBJECT(dma_dst));
> + object_property_set_link(OBJECT(dma_dst), "dma",
> + OBJECT(get_system_memory()), &error_abort);
>
> - object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_dst),
> - "dma", OBJECT(get_system_memory()),
> - &error_abort);
> + sbd = SYS_BUS_DEVICE(dma_dst);
> + sysbus_realize_and_unref(sbd, &error_fatal);
>
> - sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst);
> - sysbus_realize(sbd, &error_fatal);
> -
> - memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_DST,
> + memory_region_add_subregion(&s->mr_ps, map->dma_dst,
> sysbus_mmio_get_region(sbd, 0));
>
> /* Create the OSPI source DMA */
> - object_initialize_child(OBJECT(s), "versal-ospi-dma-src",
> - &s->pmc.iou.ospi.dma_src,
> - TYPE_XLNX_CSU_DMA);
> + dma_src = qdev_new(TYPE_XLNX_CSU_DMA);
> + object_property_add_child(OBJECT(dev), "dma-src-dev", OBJECT(dma_src));
>
> - object_property_set_bool(OBJECT(&s->pmc.iou.ospi.dma_src), "is-dst",
> - false, &error_abort);
> + object_property_set_bool(OBJECT(dma_src), "is-dst", false, &error_abort);
>
> - object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
> - "dma", OBJECT(mr_dac), &error_abort);
> -
> - object_property_set_link(OBJECT(&s->pmc.iou.ospi.dma_src),
> - "stream-connected-dma",
> - OBJECT(&s->pmc.iou.ospi.dma_dst),
> + object_property_set_link(OBJECT(dma_src), "dma", OBJECT(mr_dac),
> &error_abort);
>
> - sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src);
> - sysbus_realize(sbd, &error_fatal);
> + object_property_set_link(OBJECT(dma_src), "stream-connected-dma",
> + OBJECT(dma_dst), &error_abort);
>
> - memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DMA_SRC,
> + sbd = SYS_BUS_DEVICE(dma_src);
> + sysbus_realize_and_unref(sbd, &error_fatal);
> +
> + memory_region_add_subregion(&s->mr_ps, map->dma_src,
> sysbus_mmio_get_region(sbd, 0));
>
> /* Realize the OSPI */
> - object_property_set_link(OBJECT(&s->pmc.iou.ospi.ospi), "dma-src",
> - OBJECT(&s->pmc.iou.ospi.dma_src), &error_abort);
> + object_property_set_link(OBJECT(dev), "dma-src",
> + OBJECT(dma_src), &error_abort);
>
> - sbd = SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi);
> - sysbus_realize(sbd, &error_fatal);
> + sbd = SYS_BUS_DEVICE(dev);
> + sysbus_realize_and_unref(sbd, &error_fatal);
>
> - memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI,
> + memory_region_add_subregion(&s->mr_ps, map->ctrl,
> sysbus_mmio_get_region(sbd, 0));
>
> - memory_region_add_subregion(&s->mr_ps, MM_PMC_OSPI_DAC,
> - &s->pmc.iou.ospi.linear_mr);
> -
> - /* ospi_mux_sel */
> - ospi_mux_sel = qdev_get_gpio_in_named(DEVICE(&s->pmc.iou.ospi.ospi),
> - "ospi-mux-sel", 0);
> - qdev_connect_gpio_out_named(DEVICE(&s->pmc.iou.slcr), "ospi-mux-sel", 0,
> - ospi_mux_sel);
> + memory_region_add_subregion(&s->mr_ps, map->dac,
> + linear_mr);
>
> /* OSPI irq */
> - object_initialize_child(OBJECT(s), "ospi-irq-orgate",
> - &s->pmc.iou.ospi.irq_orgate, TYPE_OR_IRQ);
> - object_property_set_int(OBJECT(&s->pmc.iou.ospi.irq_orgate),
> - "num-lines", NUM_OSPI_IRQ_LINES, &error_fatal);
> + orgate = create_or_gate(s, OBJECT(dev), "irq-orgate", NUM_OSPI_IRQ_LINES,
> + map->irq);
>
> - orgate = DEVICE(&s->pmc.iou.ospi.irq_orgate);
> - qdev_realize(orgate, NULL, &error_fatal);
> + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(orgate, 0));
> + sysbus_connect_irq(SYS_BUS_DEVICE(dma_src), 0, qdev_get_gpio_in(orgate, 1));
> + sysbus_connect_irq(SYS_BUS_DEVICE(dma_dst), 0, qdev_get_gpio_in(orgate, 2));
>
> - sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.ospi), 0,
> - qdev_get_gpio_in(orgate, 0));
> - sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_src), 0,
> - qdev_get_gpio_in(orgate, 1));
> - sysbus_connect_irq(SYS_BUS_DEVICE(&s->pmc.iou.ospi.dma_dst), 0,
> - qdev_get_gpio_in(orgate, 2));
> -
> - qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
> + return dev;
> }
>
> static void versal_create_cfu(Versal *s, qemu_irq *pic)
> {
> SysBusDevice *sbd;
> @@ -1256,17 +1252,17 @@ static void versal_realize(DeviceState *dev, Error **errp)
> for (i = 0; i < map->num_usb; i++) {
> versal_create_usb(s, &map->usb[i]);
> }
>
> versal_create_efuse(s, &map->efuse);
> + versal_create_ospi(s, &map->ospi);
>
> versal_create_pmc_apb_irq_orgate(s, pic);
> versal_create_rtc(s, pic);
> versal_create_trng(s, pic);
> versal_create_bbram(s, pic);
> versal_create_pmc_iou_slcr(s, pic);
> - versal_create_ospi(s, pic);
> versal_create_crl(s, pic);
> versal_create_cfu(s, pic);
> versal_map_ddr(s);
> versal_unimp(s);
>
> @@ -1308,10 +1304,34 @@ void versal_efuse_attach_drive(Versal *s, BlockBackend *blk)
> }
>
> qdev_prop_set_drive(efuse, "drive", blk);
> }
>
> +void versal_ospi_create_flash(Versal *s, int flash_idx, const char *flash_mdl,
> + BlockBackend *blk)
> +{
> + BusState *spi_bus;
> + DeviceState *flash, *ospi;
> + qemu_irq cs_line;
> +
> + ospi = DEVICE(versal_get_child(s, "ospi"));
> + spi_bus = qdev_get_child_bus(ospi, "spi0");
> +
> + flash = qdev_new(flash_mdl);
> +
> + if (blk) {
> + qdev_prop_set_drive_err(flash, "drive", blk, &error_fatal);
> + }
> + qdev_prop_set_uint8(flash, "cs", flash_idx);
> + qdev_realize_and_unref(flash, spi_bus, &error_fatal);
> +
> + cs_line = qdev_get_gpio_in_named(flash, SSI_GPIO_CS, 0);
> +
> + sysbus_connect_irq(SYS_BUS_DEVICE(ospi),
> + flash_idx + 1, cs_line);
> +}
> +
> int versal_get_num_can(VersalVersion version)
> {
> const VersalMap *map = VERSION_TO_MAP[version];
>
> return map->num_canfd;
> --
> 2.50.0
>
© 2016 - 2025 Red Hat, Inc.