* [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL
@ 2022-04-06 17:42 Edgar E. Iglesias
2022-04-06 17:43 ` [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster Edgar E. Iglesias
` (4 more replies)
0 siblings, 5 replies; 14+ messages in thread
From: Edgar E. Iglesias @ 2022-04-06 17:42 UTC (permalink / raw)
To: qemu-devel
Cc: edgar.iglesias, peter.maydell, luc, fkonrad, edgar.iglesias,
sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson,
f4bug, francisco.iglesias, qemu-arm
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
This adds the Versal Cortex-R5s in the Real-Time Processing Unit
(RPU) subsystem.
A model of the Clock/Reset Low-power domain (CRL) is also added
allowing runtime release of the Cortex-R5s. The RPU subsystem
is largely missing but has enough to run simple bare-metal R5
apps.
Cheers,
Edgar
Edgar E. Iglesias (4):
hw/arm: versal: Create an APU CPU Cluster
hw/arm: versal: Add the Cortex-R5Fs
hw/misc: Add a model of the Xilinx Versal CRL
hw/arm: versal: Connect the CRL
hw/arm/xlnx-versal-virt.c | 6 +-
hw/arm/xlnx-versal.c | 99 ++++++-
hw/misc/meson.build | 1 +
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
include/hw/arm/xlnx-versal.h | 16 ++
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
6 files changed, 772 insertions(+), 6 deletions(-)
create mode 100644 hw/misc/xlnx-versal-crl.c
create mode 100644 include/hw/misc/xlnx-versal-crl.h
--
2.25.1
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster 2022-04-06 17:42 [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Edgar E. Iglesias @ 2022-04-06 17:43 ` Edgar E. Iglesias 2022-04-07 7:42 ` Frederic Konrad 2022-04-07 9:24 ` Francisco Iglesias 2022-04-06 17:43 ` [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs Edgar E. Iglesias ` (3 subsequent siblings) 4 siblings, 2 replies; 14+ messages in thread From: Edgar E. Iglesias @ 2022-04-06 17:43 UTC (permalink / raw) To: qemu-devel Cc: edgar.iglesias, peter.maydell, luc, fkonrad, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, f4bug, francisco.iglesias, qemu-arm From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> Create an APU CPU Cluster. This is in preparation to add the RPU. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> --- hw/arm/xlnx-versal.c | 9 ++++++++- include/hw/arm/xlnx-versal.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 2551dfc22d..4415ee413f 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -34,10 +34,15 @@ static void versal_create_apu_cpus(Versal *s) { int i; + object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster, + TYPE_CPU_CLUSTER); + qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0); + for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) { Object *obj; - object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i], + object_initialize_child(OBJECT(&s->fpd.apu.cluster), + "apu-cpu[*]", &s->fpd.apu.cpu[i], XLNX_VERSAL_ACPU_TYPE); obj = OBJECT(&s->fpd.apu.cpu[i]); if (i) { @@ -52,6 +57,8 @@ static void versal_create_apu_cpus(Versal *s) &error_abort); qdev_realize(DEVICE(obj), NULL, &error_fatal); } + + qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal); } static void versal_create_apu_gic(Versal *s, qemu_irq *pic) diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 0728316ec7..d2d3028e18 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -14,6 +14,7 @@ #include "hw/sysbus.h" #include "hw/arm/boot.h" +#include "hw/cpu/cluster.h" #include "hw/or-irq.h" #include "hw/sd/sdhci.h" #include "hw/intc/arm_gicv3.h" @@ -49,6 +50,7 @@ struct Versal { struct { struct { MemoryRegion mr; + CPUClusterState cluster; ARMCPU cpu[XLNX_VERSAL_NR_ACPUS]; GICv3State gic; } apu; -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* RE: [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster 2022-04-06 17:43 ` [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster Edgar E. Iglesias @ 2022-04-07 7:42 ` Frederic Konrad 2022-04-07 9:24 ` Francisco Iglesias 1 sibling, 0 replies; 14+ messages in thread From: Frederic Konrad @ 2022-04-07 7:42 UTC (permalink / raw) To: Edgar Iglesias, qemu-devel@nongnu.org Cc: Francisco Eduardo Iglesias, peter.maydell@linaro.org, luc@lmichel.fr, edgar.iglesias@amd.com, frasse.iglesias@gmail.com, alistair@alistair23.me, richard.henderson@linaro.org, f4bug@amsat.org, Sai Pavan Boddu, Edgar Iglesias, qemu-arm@nongnu.org -----Original Message----- From: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Sent: 06 April 2022 18:43 To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org; peter.maydell@linaro.org; richard.henderson@linaro.org; alistair@alistair23.me; luc@lmichel.fr; f4bug@amsat.org; frasse.iglesias@gmail.com; Francisco Eduardo Iglesias <figlesia@xilinx.com>; Sai Pavan Boddu <saipava@xilinx.com>; Frederic Konrad <fkonrad@xilinx.com>; Edgar Iglesias <edgari@xilinx.com>; edgar.iglesias@amd.com Subject: [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> Create an APU CPU Cluster. This is in preparation to add the RPU. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> --- hw/arm/xlnx-versal.c | 9 ++++++++- include/hw/arm/xlnx-versal.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 2551dfc22d..4415ee413f 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -34,10 +34,15 @@ static void versal_create_apu_cpus(Versal *s) { int i; + object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster, + TYPE_CPU_CLUSTER); + qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0); + for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) { Object *obj; - object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i], + object_initialize_child(OBJECT(&s->fpd.apu.cluster), + "apu-cpu[*]", &s->fpd.apu.cpu[i], XLNX_VERSAL_ACPU_TYPE); obj = OBJECT(&s->fpd.apu.cpu[i]); if (i) { @@ -52,6 +57,8 @@ static void versal_create_apu_cpus(Versal *s) &error_abort); qdev_realize(DEVICE(obj), NULL, &error_fatal); } + + qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal); } static void versal_create_apu_gic(Versal *s, qemu_irq *pic) diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 0728316ec7..d2d3028e18 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -14,6 +14,7 @@ #include "hw/sysbus.h" #include "hw/arm/boot.h" +#include "hw/cpu/cluster.h" #include "hw/or-irq.h" #include "hw/sd/sdhci.h" #include "hw/intc/arm_gicv3.h" @@ -49,6 +50,7 @@ struct Versal { struct { struct { MemoryRegion mr; + CPUClusterState cluster; ARMCPU cpu[XLNX_VERSAL_NR_ACPUS]; GICv3State gic; } apu; -- 2.25.1 Reviewed-by: Frederic Konrad <fkonrad@amd.com> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster 2022-04-06 17:43 ` [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster Edgar E. Iglesias 2022-04-07 7:42 ` Frederic Konrad @ 2022-04-07 9:24 ` Francisco Iglesias 1 sibling, 0 replies; 14+ messages in thread From: Francisco Iglesias @ 2022-04-07 9:24 UTC (permalink / raw) To: Edgar E. Iglesias Cc: peter.maydell, luc, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, qemu-devel, f4bug, fkonrad, qemu-arm On Wed, Apr 06, 2022 at 06:43:00PM +0100, Edgar E. Iglesias wrote: > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> > > Create an APU CPU Cluster. This is in preparation to add the RPU. > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com> > --- > hw/arm/xlnx-versal.c | 9 ++++++++- > include/hw/arm/xlnx-versal.h | 2 ++ > 2 files changed, 10 insertions(+), 1 deletion(-) > > diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c > index 2551dfc22d..4415ee413f 100644 > --- a/hw/arm/xlnx-versal.c > +++ b/hw/arm/xlnx-versal.c > @@ -34,10 +34,15 @@ static void versal_create_apu_cpus(Versal *s) > { > int i; > > + object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster, > + TYPE_CPU_CLUSTER); > + qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0); > + > for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) { > Object *obj; > > - object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i], > + object_initialize_child(OBJECT(&s->fpd.apu.cluster), > + "apu-cpu[*]", &s->fpd.apu.cpu[i], > XLNX_VERSAL_ACPU_TYPE); > obj = OBJECT(&s->fpd.apu.cpu[i]); > if (i) { > @@ -52,6 +57,8 @@ static void versal_create_apu_cpus(Versal *s) > &error_abort); > qdev_realize(DEVICE(obj), NULL, &error_fatal); > } > + > + qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal); > } > > static void versal_create_apu_gic(Versal *s, qemu_irq *pic) > diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h > index 0728316ec7..d2d3028e18 100644 > --- a/include/hw/arm/xlnx-versal.h > +++ b/include/hw/arm/xlnx-versal.h > @@ -14,6 +14,7 @@ > > #include "hw/sysbus.h" > #include "hw/arm/boot.h" > +#include "hw/cpu/cluster.h" > #include "hw/or-irq.h" > #include "hw/sd/sdhci.h" > #include "hw/intc/arm_gicv3.h" > @@ -49,6 +50,7 @@ struct Versal { > struct { > struct { > MemoryRegion mr; > + CPUClusterState cluster; > ARMCPU cpu[XLNX_VERSAL_NR_ACPUS]; > GICv3State gic; > } apu; > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs 2022-04-06 17:42 [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Edgar E. Iglesias 2022-04-06 17:43 ` [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster Edgar E. Iglesias @ 2022-04-06 17:43 ` Edgar E. Iglesias 2022-04-07 7:52 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 2022-04-06 17:43 ` [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL Edgar E. Iglesias ` (2 subsequent siblings) 4 siblings, 2 replies; 14+ messages in thread From: Edgar E. Iglesias @ 2022-04-06 17:43 UTC (permalink / raw) To: qemu-devel Cc: edgar.iglesias, peter.maydell, luc, fkonrad, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, f4bug, francisco.iglesias, qemu-arm From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit) subsystem. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> --- hw/arm/xlnx-versal-virt.c | 6 +++--- hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++ include/hw/arm/xlnx-versal.h | 10 ++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 7c7baff8b7..66a2de7e13 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -721,9 +721,9 @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data) mc->desc = "Xilinx Versal Virtual development board"; mc->init = versal_virt_init; - mc->min_cpus = XLNX_VERSAL_NR_ACPUS; - mc->max_cpus = XLNX_VERSAL_NR_ACPUS; - mc->default_cpus = XLNX_VERSAL_NR_ACPUS; + mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; + mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; + mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; mc->no_cdrom = true; mc->default_ram_id = "ddr"; } diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 4415ee413f..ebad8dbb6d 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -25,6 +25,7 @@ #include "hw/sysbus.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 #define VERSAL_NUM_PMC_APB_IRQS 3 @@ -130,6 +131,35 @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic) } } +static void versal_create_rpu_cpus(Versal *s) +{ + int i; + + object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster, + TYPE_CPU_CLUSTER); + qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1); + + for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) { + Object *obj; + + object_initialize_child(OBJECT(&s->lpd.rpu.cluster), + "rpu-cpu[*]", &s->lpd.rpu.cpu[i], + XLNX_VERSAL_RCPU_TYPE); + obj = OBJECT(&s->lpd.rpu.cpu[i]); + object_property_set_bool(obj, "start-powered-off", true, + &error_abort); + + object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort); + object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu), + &error_abort); + object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr), + &error_abort); + qdev_realize(DEVICE(obj), NULL, &error_fatal); + } + + qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal); +} + static void versal_create_uarts(Versal *s, qemu_irq *pic) { int i; @@ -638,6 +668,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_apu_cpus(s); versal_create_apu_gic(s, pic); + versal_create_rpu_cpus(s); versal_create_uarts(s, pic); versal_create_usbs(s, pic); versal_create_gems(s, pic); @@ -659,6 +690,8 @@ static void versal_realize(DeviceState *dev, Error **errp) memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0); memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0); + memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0, + &s->lpd.rpu.mr_ps_alias, 0); } static void versal_init(Object *obj) @@ -666,7 +699,10 @@ static void versal_init(Object *obj) Versal *s = XLNX_VERSAL(obj); memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX); + memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX); memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX); + memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s), + "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX); } static Property versal_properties[] = { diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index d2d3028e18..155e8c4b8c 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -35,6 +35,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) #define XLNX_VERSAL_NR_ACPUS 2 +#define XLNX_VERSAL_NR_RCPUS 2 #define XLNX_VERSAL_NR_UARTS 2 #define XLNX_VERSAL_NR_GEMS 2 #define XLNX_VERSAL_NR_ADMAS 8 @@ -73,6 +74,15 @@ struct Versal { VersalUsb2 usb; } iou; + /* Real-time Processing Unit. */ + struct { + MemoryRegion mr; + MemoryRegion mr_ps_alias; + + CPUClusterState cluster; + ARMCPU cpu[XLNX_VERSAL_NR_RCPUS]; + } rpu; + struct { qemu_or_irq irq_orgate; XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM]; -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* RE: [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs 2022-04-06 17:43 ` [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs Edgar E. Iglesias @ 2022-04-07 7:52 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 1 sibling, 0 replies; 14+ messages in thread From: Frederic Konrad @ 2022-04-07 7:52 UTC (permalink / raw) To: Edgar Iglesias, qemu-devel@nongnu.org Cc: Francisco Eduardo Iglesias, peter.maydell@linaro.org, luc@lmichel.fr, edgar.iglesias@amd.com, frasse.iglesias@gmail.com, alistair@alistair23.me, richard.henderson@linaro.org, f4bug@amsat.org, Sai Pavan Boddu, Edgar Iglesias, qemu-arm@nongnu.org -----Original Message----- From: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Sent: 06 April 2022 18:43 To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org; peter.maydell@linaro.org; richard.henderson@linaro.org; alistair@alistair23.me; luc@lmichel.fr; f4bug@amsat.org; frasse.iglesias@gmail.com; Francisco Eduardo Iglesias <figlesia@xilinx.com>; Sai Pavan Boddu <saipava@xilinx.com>; Frederic Konrad <fkonrad@xilinx.com>; Edgar Iglesias <edgari@xilinx.com>; edgar.iglesias@amd.com Subject: [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit) subsystem. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> --- hw/arm/xlnx-versal-virt.c | 6 +++--- hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++ include/hw/arm/xlnx-versal.h | 10 ++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 7c7baff8b7..66a2de7e13 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -721,9 +721,9 @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data) mc->desc = "Xilinx Versal Virtual development board"; mc->init = versal_virt_init; - mc->min_cpus = XLNX_VERSAL_NR_ACPUS; - mc->max_cpus = XLNX_VERSAL_NR_ACPUS; - mc->default_cpus = XLNX_VERSAL_NR_ACPUS; + mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; + mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; + mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; mc->no_cdrom = true; mc->default_ram_id = "ddr"; } diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 4415ee413f..ebad8dbb6d 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -25,6 +25,7 @@ #include "hw/sysbus.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 #define VERSAL_NUM_PMC_APB_IRQS 3 @@ -130,6 +131,35 @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic) } } +static void versal_create_rpu_cpus(Versal *s) { + int i; + + object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster, + TYPE_CPU_CLUSTER); + qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1); + + for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) { + Object *obj; + + object_initialize_child(OBJECT(&s->lpd.rpu.cluster), + "rpu-cpu[*]", &s->lpd.rpu.cpu[i], + XLNX_VERSAL_RCPU_TYPE); + obj = OBJECT(&s->lpd.rpu.cpu[i]); + object_property_set_bool(obj, "start-powered-off", true, + &error_abort); + + object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort); + object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu), + &error_abort); + object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr), + &error_abort); + qdev_realize(DEVICE(obj), NULL, &error_fatal); + } + + qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal); } + static void versal_create_uarts(Versal *s, qemu_irq *pic) { int i; @@ -638,6 +668,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_apu_cpus(s); versal_create_apu_gic(s, pic); + versal_create_rpu_cpus(s); versal_create_uarts(s, pic); versal_create_usbs(s, pic); versal_create_gems(s, pic); @@ -659,6 +690,8 @@ static void versal_realize(DeviceState *dev, Error **errp) memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0); memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0); + memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0, + &s->lpd.rpu.mr_ps_alias, 0); } static void versal_init(Object *obj) @@ -666,7 +699,10 @@ static void versal_init(Object *obj) Versal *s = XLNX_VERSAL(obj); memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX); + memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX); memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX); + memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s), + "mr-rpu-ps-alias", &s->mr_ps, 0, + UINT64_MAX); } static Property versal_properties[] = { diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index d2d3028e18..155e8c4b8c 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -35,6 +35,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) #define XLNX_VERSAL_NR_ACPUS 2 +#define XLNX_VERSAL_NR_RCPUS 2 #define XLNX_VERSAL_NR_UARTS 2 #define XLNX_VERSAL_NR_GEMS 2 #define XLNX_VERSAL_NR_ADMAS 8 @@ -73,6 +74,15 @@ struct Versal { VersalUsb2 usb; } iou; + /* Real-time Processing Unit. */ + struct { + MemoryRegion mr; + MemoryRegion mr_ps_alias; + + CPUClusterState cluster; + ARMCPU cpu[XLNX_VERSAL_NR_RCPUS]; + } rpu; + struct { qemu_or_irq irq_orgate; XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM]; -- 2.25.1 Reviewed-by: Frederic Konrad <fkonrad@amd.com> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs 2022-04-06 17:43 ` [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs Edgar E. Iglesias 2022-04-07 7:52 ` Frederic Konrad @ 2022-04-07 9:25 ` Francisco Iglesias 1 sibling, 0 replies; 14+ messages in thread From: Francisco Iglesias @ 2022-04-07 9:25 UTC (permalink / raw) To: Edgar E. Iglesias Cc: peter.maydell, luc, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, qemu-devel, f4bug, fkonrad, qemu-arm On Wed, Apr 06, 2022 at 06:43:01PM +0100, Edgar E. Iglesias wrote: > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> > > Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit) > subsystem. > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com> > --- > hw/arm/xlnx-versal-virt.c | 6 +++--- > hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++ > include/hw/arm/xlnx-versal.h | 10 ++++++++++ > 3 files changed, 49 insertions(+), 3 deletions(-) > > diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c > index 7c7baff8b7..66a2de7e13 100644 > --- a/hw/arm/xlnx-versal-virt.c > +++ b/hw/arm/xlnx-versal-virt.c > @@ -721,9 +721,9 @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data) > > mc->desc = "Xilinx Versal Virtual development board"; > mc->init = versal_virt_init; > - mc->min_cpus = XLNX_VERSAL_NR_ACPUS; > - mc->max_cpus = XLNX_VERSAL_NR_ACPUS; > - mc->default_cpus = XLNX_VERSAL_NR_ACPUS; > + mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; > + mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; > + mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS; > mc->no_cdrom = true; > mc->default_ram_id = "ddr"; > } > diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c > index 4415ee413f..ebad8dbb6d 100644 > --- a/hw/arm/xlnx-versal.c > +++ b/hw/arm/xlnx-versal.c > @@ -25,6 +25,7 @@ > #include "hw/sysbus.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 > > #define VERSAL_NUM_PMC_APB_IRQS 3 > @@ -130,6 +131,35 @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic) > } > } > > +static void versal_create_rpu_cpus(Versal *s) > +{ > + int i; > + > + object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster, > + TYPE_CPU_CLUSTER); > + qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1); > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) { > + Object *obj; > + > + object_initialize_child(OBJECT(&s->lpd.rpu.cluster), > + "rpu-cpu[*]", &s->lpd.rpu.cpu[i], > + XLNX_VERSAL_RCPU_TYPE); > + obj = OBJECT(&s->lpd.rpu.cpu[i]); > + object_property_set_bool(obj, "start-powered-off", true, > + &error_abort); > + > + object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort); > + object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu), > + &error_abort); > + object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr), > + &error_abort); > + qdev_realize(DEVICE(obj), NULL, &error_fatal); > + } > + > + qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal); > +} > + > static void versal_create_uarts(Versal *s, qemu_irq *pic) > { > int i; > @@ -638,6 +668,7 @@ static void versal_realize(DeviceState *dev, Error **errp) > > versal_create_apu_cpus(s); > versal_create_apu_gic(s, pic); > + versal_create_rpu_cpus(s); > versal_create_uarts(s, pic); > versal_create_usbs(s, pic); > versal_create_gems(s, pic); > @@ -659,6 +690,8 @@ static void versal_realize(DeviceState *dev, Error **errp) > > memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0); > memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0); > + memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0, > + &s->lpd.rpu.mr_ps_alias, 0); > } > > static void versal_init(Object *obj) > @@ -666,7 +699,10 @@ static void versal_init(Object *obj) > Versal *s = XLNX_VERSAL(obj); > > memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX); > + memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX); > memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX); > + memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s), > + "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX); > } > > static Property versal_properties[] = { > diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h > index d2d3028e18..155e8c4b8c 100644 > --- a/include/hw/arm/xlnx-versal.h > +++ b/include/hw/arm/xlnx-versal.h > @@ -35,6 +35,7 @@ > OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) > > #define XLNX_VERSAL_NR_ACPUS 2 > +#define XLNX_VERSAL_NR_RCPUS 2 > #define XLNX_VERSAL_NR_UARTS 2 > #define XLNX_VERSAL_NR_GEMS 2 > #define XLNX_VERSAL_NR_ADMAS 8 > @@ -73,6 +74,15 @@ struct Versal { > VersalUsb2 usb; > } iou; > > + /* Real-time Processing Unit. */ > + struct { > + MemoryRegion mr; > + MemoryRegion mr_ps_alias; > + > + CPUClusterState cluster; > + ARMCPU cpu[XLNX_VERSAL_NR_RCPUS]; > + } rpu; > + > struct { > qemu_or_irq irq_orgate; > XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM]; > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL 2022-04-06 17:42 [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Edgar E. Iglesias 2022-04-06 17:43 ` [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster Edgar E. Iglesias 2022-04-06 17:43 ` [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs Edgar E. Iglesias @ 2022-04-06 17:43 ` Edgar E. Iglesias 2022-04-07 8:22 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 2022-04-06 17:43 ` [PATCH v1 4/4] hw/arm: versal: Connect the CRL Edgar E. Iglesias 2022-04-11 10:49 ` [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Peter Maydell 4 siblings, 2 replies; 14+ messages in thread From: Edgar E. Iglesias @ 2022-04-06 17:43 UTC (permalink / raw) To: qemu-devel Cc: edgar.iglesias, peter.maydell, luc, fkonrad, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, f4bug, francisco.iglesias, qemu-arm From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> Add a model of the Xilinx Versal CRL. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> --- hw/misc/meson.build | 1 + hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++ include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++ 3 files changed, 657 insertions(+) create mode 100644 hw/misc/xlnx-versal-crl.c create mode 100644 include/hw/misc/xlnx-versal-crl.h diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 6fb69612e0..2ff05c7afa 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -86,6 +86,7 @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c')) specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c')) +specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c')) softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-versal-xramc.c', 'xlnx-versal-pmc-iou-slcr.c', diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c new file mode 100644 index 0000000000..767106b7a3 --- /dev/null +++ b/hw/misc/xlnx-versal-crl.c @@ -0,0 +1,421 @@ +/* + * QEMU model of the Clock-Reset-LPD (CRL). + * + * Copyright (c) 2022 Advanced Micro Devices, Inc. + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Written by Edgar E. Iglesias <edgar.iglesias@amd.com> + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/bitops.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/register.h" +#include "hw/resettable.h" + +#include "target/arm/arm-powerctl.h" +#include "hw/misc/xlnx-versal-crl.h" + +#ifndef XLNX_VERSAL_CRL_ERR_DEBUG +#define XLNX_VERSAL_CRL_ERR_DEBUG 0 +#endif + +static void crl_update_irq(XlnxVersalCRL *s) +{ + bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK]; + qemu_set_irq(s->irq, pending); +} + +static void crl_status_postw(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + crl_update_irq(s); +} + +static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + uint32_t val = val64; + + s->regs[R_IR_MASK] &= ~val; + crl_update_irq(s); + return 0; +} + +static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + uint32_t val = val64; + + s->regs[R_IR_MASK] |= val; + crl_update_irq(s); + return 0; +} + +static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev, + bool rst_old, bool rst_new) +{ + device_cold_reset(dev); +} + +static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu, + bool rst_old, bool rst_new) +{ + if (rst_new) { + arm_set_cpu_off(armcpu->mp_affinity); + } else { + arm_set_cpu_on_and_reset(armcpu->mp_affinity); + } +} + +#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \ + bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \ + bool new_f = FIELD_EX32(new_val, reg, f); \ + \ + /* Detect edges. */ \ + if (dev && old_f != new_f) { \ + crl_reset_ ## type(s, dev, old_f, new_f); \ + } \ +} + +static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + + REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]); + REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]); + return val64; +} + +static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + int i; + + /* A single register fans out to all ADMA reset inputs. */ + for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) { + REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]); + } + return val64; +} + +static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + + REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]); + return val64; +} + +static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + + REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]); + return val64; +} + +static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + + REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]); + return val64; +} + +static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + + REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]); + return val64; +} + +static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); + + REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb); + return val64; +} + +static const RegisterAccessInfo crl_regs_info[] = { + { .name = "ERR_CTRL", .addr = A_ERR_CTRL, + },{ .name = "IR_STATUS", .addr = A_IR_STATUS, + .w1c = 0x1, + .post_write = crl_status_postw, + },{ .name = "IR_MASK", .addr = A_IR_MASK, + .reset = 0x1, + .ro = 0x1, + },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE, + .pre_write = crl_enable_prew, + },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE, + .pre_write = crl_disable_prew, + },{ .name = "WPROT", .addr = A_WPROT, + },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN, + .reset = 0x1, + .rsvd = 0xe, + },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL, + .reset = 0x24809, + .rsvd = 0xf88c00f6, + },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG, + .reset = 0x2000000, + .rsvd = 0x1801210, + },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG, + .rsvd = 0x7e330000, + },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS, + .reset = R_PLL_STATUS_RPLL_STABLE_MASK | + R_PLL_STATUS_RPLL_LOCK_MASK, + .rsvd = 0xfa, + .ro = 0x5, + },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL, + .reset = 0x2000100, + .rsvd = 0xfdfc00ff, + },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL, + .reset = 0x6000300, + .rsvd = 0xf9fc00f8, + },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL, + .reset = 0x2000800, + .rsvd = 0xfdfc00f8, + },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL, + .reset = 0xe000300, + .rsvd = 0xe1fc00f8, + },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL, + .reset = 0x2000500, + .rsvd = 0xfdfc00f8, + },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL, + .reset = 0xe000a00, + .rsvd = 0xf1fc00f8, + },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL, + .reset = 0xe000a00, + .rsvd = 0xf1fc00f8, + },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL, + .reset = 0x300, + .rsvd = 0xfdfc00f8, + },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL, + .reset = 0x2001900, + .rsvd = 0xfdfc00f8, + },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL, + .reset = 0xc00, + .rsvd = 0xfdfc00f8, + },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL, + .reset = 0xc00, + .rsvd = 0xfdfc00f8, + },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL, + .reset = 0x600, + .rsvd = 0xfdfc00f8, + },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL, + .reset = 0x600, + .rsvd = 0xfdfc00f8, + },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL, + .reset = 0xc00, + .rsvd = 0xfdfc00f8, + },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL, + .reset = 0xc00, + .rsvd = 0xfdfc00f8, + },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL, + .reset = 0xc00, + .rsvd = 0xfdfc00f8, + },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL, + .reset = 0xc00, + .rsvd = 0xfdfc00f8, + },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL, + .reset = 0x300, + .rsvd = 0xfdfc00f8, + },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL, + .reset = 0x2000c00, + .rsvd = 0xfdfc00f8, + },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK, + },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL, + .reset = 0xf04, + .rsvd = 0xfffc00f8, + },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL, + .reset = 0x300, + .rsvd = 0xfdfc00f8, + },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL, + .reset = 0x300, + .rsvd = 0xfdfc00f8, + },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL, + .reset = 0x3c00, + .rsvd = 0xfdfc00f8, + },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5, + .reset = 0x17, + .rsvd = 0x8, + .pre_write = crl_rst_r5_prew, + },{ .name = "RST_ADMA", .addr = A_RST_ADMA, + .reset = 0x1, + .pre_write = crl_rst_adma_prew, + },{ .name = "RST_GEM0", .addr = A_RST_GEM0, + .reset = 0x1, + .pre_write = crl_rst_gem0_prew, + },{ .name = "RST_GEM1", .addr = A_RST_GEM1, + .reset = 0x1, + .pre_write = crl_rst_gem1_prew, + },{ .name = "RST_SPARE", .addr = A_RST_SPARE, + .reset = 0x1, + },{ .name = "RST_USB0", .addr = A_RST_USB0, + .reset = 0x1, + .pre_write = crl_rst_usb_prew, + },{ .name = "RST_UART0", .addr = A_RST_UART0, + .reset = 0x1, + .pre_write = crl_rst_uart0_prew, + },{ .name = "RST_UART1", .addr = A_RST_UART1, + .reset = 0x1, + .pre_write = crl_rst_uart1_prew, + },{ .name = "RST_SPI0", .addr = A_RST_SPI0, + .reset = 0x1, + },{ .name = "RST_SPI1", .addr = A_RST_SPI1, + .reset = 0x1, + },{ .name = "RST_CAN0", .addr = A_RST_CAN0, + .reset = 0x1, + },{ .name = "RST_CAN1", .addr = A_RST_CAN1, + .reset = 0x1, + },{ .name = "RST_I2C0", .addr = A_RST_I2C0, + .reset = 0x1, + },{ .name = "RST_I2C1", .addr = A_RST_I2C1, + .reset = 0x1, + },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD, + .reset = 0x33, + .rsvd = 0xcc, + },{ .name = "RST_GPIO", .addr = A_RST_GPIO, + .reset = 0x1, + },{ .name = "RST_TTC", .addr = A_RST_TTC, + .reset = 0xf, + },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP, + .reset = 0x1, + },{ .name = "RST_SWDT", .addr = A_RST_SWDT, + .reset = 0x1, + },{ .name = "RST_OCM", .addr = A_RST_OCM, + },{ .name = "RST_IPI", .addr = A_RST_IPI, + },{ .name = "RST_FPD", .addr = A_RST_FPD, + .reset = 0x3, + },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE, + .reset = 0x1, + .rsvd = 0xf8, + } +}; + +static void crl_reset_enter(Object *obj, ResetType type) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { + register_reset(&s->regs_info[i]); + } +} + +static void crl_reset_hold(Object *obj) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); + + crl_update_irq(s); +} + +static const MemoryRegionOps crl_ops = { + .read = register_read_memory, + .write = register_write_memory, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + +static void crl_init(Object *obj) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + int i; + + s->reg_array = + register_init_block32(DEVICE(obj), crl_regs_info, + ARRAY_SIZE(crl_regs_info), + s->regs_info, s->regs, + &crl_ops, + XLNX_VERSAL_CRL_ERR_DEBUG, + CRL_R_MAX * 4); + sysbus_init_mmio(sbd, &s->reg_array->mem); + sysbus_init_irq(sbd, &s->irq); + + for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) { + object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU, + (Object **)&s->cfg.cpu_r5[i], + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); + } + + for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) { + object_property_add_link(obj, "adma[*]", TYPE_DEVICE, + (Object **)&s->cfg.adma[i], + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); + } + + for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) { + object_property_add_link(obj, "uart[*]", TYPE_DEVICE, + (Object **)&s->cfg.uart[i], + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); + } + + for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) { + object_property_add_link(obj, "gem[*]", TYPE_DEVICE, + (Object **)&s->cfg.gem[i], + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); + } + + object_property_add_link(obj, "usb", TYPE_DEVICE, + (Object **)&s->cfg.gem[i], + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_STRONG); +} + +static void crl_finalize(Object *obj) +{ + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); + register_finalize_block(s->reg_array); +} + +static const VMStateDescription vmstate_crl = { + .name = TYPE_XLNX_VERSAL_CRL, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX), + VMSTATE_END_OF_LIST(), + } +}; + +static void crl_class_init(ObjectClass *klass, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_crl; + + rc->phases.enter = crl_reset_enter; + rc->phases.hold = crl_reset_hold; +} + +static const TypeInfo crl_info = { + .name = TYPE_XLNX_VERSAL_CRL, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(XlnxVersalCRL), + .class_init = crl_class_init, + .instance_init = crl_init, + .instance_finalize = crl_finalize, +}; + +static void crl_register_types(void) +{ + type_register_static(&crl_info); +} + +type_init(crl_register_types) diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h new file mode 100644 index 0000000000..2857f4169a --- /dev/null +++ b/include/hw/misc/xlnx-versal-crl.h @@ -0,0 +1,235 @@ +/* + * QEMU model of the Clock-Reset-LPD (CRL). + * + * Copyright (c) 2022 Xilinx Inc. + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com> + */ +#ifndef HW_MISC_XLNX_VERSAL_CRL_H +#define HW_MISC_XLNX_VERSAL_CRL_H + +#include "hw/sysbus.h" +#include "hw/register.h" +#include "target/arm/cpu.h" + +#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl" +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL) + +REG32(ERR_CTRL, 0x0) + FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1) +REG32(IR_STATUS, 0x4) + FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1) +REG32(IR_MASK, 0x8) + FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1) +REG32(IR_ENABLE, 0xc) + FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1) +REG32(IR_DISABLE, 0x10) + FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1) +REG32(WPROT, 0x1c) + FIELD(WPROT, ACTIVE, 0, 1) +REG32(PLL_CLK_OTHER_DMN, 0x20) + FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1) +REG32(RPLL_CTRL, 0x40) + FIELD(RPLL_CTRL, POST_SRC, 24, 3) + FIELD(RPLL_CTRL, PRE_SRC, 20, 3) + FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2) + FIELD(RPLL_CTRL, FBDIV, 8, 8) + FIELD(RPLL_CTRL, BYPASS, 3, 1) + FIELD(RPLL_CTRL, RESET, 0, 1) +REG32(RPLL_CFG, 0x44) + FIELD(RPLL_CFG, LOCK_DLY, 25, 7) + FIELD(RPLL_CFG, LOCK_CNT, 13, 10) + FIELD(RPLL_CFG, LFHF, 10, 2) + FIELD(RPLL_CFG, CP, 5, 4) + FIELD(RPLL_CFG, RES, 0, 4) +REG32(RPLL_FRAC_CFG, 0x48) + FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1) + FIELD(RPLL_FRAC_CFG, SEED, 22, 3) + FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1) + FIELD(RPLL_FRAC_CFG, ORDER, 18, 1) + FIELD(RPLL_FRAC_CFG, DATA, 0, 16) +REG32(PLL_STATUS, 0x50) + FIELD(PLL_STATUS, RPLL_STABLE, 2, 1) + FIELD(PLL_STATUS, RPLL_LOCK, 0, 1) +REG32(RPLL_TO_XPD_CTRL, 0x100) + FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1) + FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10) +REG32(LPD_TOP_SWITCH_CTRL, 0x104) + FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1) + FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1) + FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10) + FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3) +REG32(LPD_LSBUS_CTRL, 0x108) + FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1) + FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10) + FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3) +REG32(CPU_R5_CTRL, 0x10c) + FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1) + FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1) + FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1) + FIELD(CPU_R5_CTRL, CLKACT, 25, 1) + FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10) + FIELD(CPU_R5_CTRL, SRCSEL, 0, 3) +REG32(IOU_SWITCH_CTRL, 0x114) + FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1) + FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10) + FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3) +REG32(GEM0_REF_CTRL, 0x118) + FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1) + FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1) + FIELD(GEM0_REF_CTRL, CLKACT, 25, 1) + FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10) + FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3) +REG32(GEM1_REF_CTRL, 0x11c) + FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1) + FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1) + FIELD(GEM1_REF_CTRL, CLKACT, 25, 1) + FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10) + FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3) +REG32(GEM_TSU_REF_CTRL, 0x120) + FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1) + FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10) + FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3) +REG32(USB0_BUS_REF_CTRL, 0x124) + FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1) + FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10) + FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3) +REG32(UART0_REF_CTRL, 0x128) + FIELD(UART0_REF_CTRL, CLKACT, 25, 1) + FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10) + FIELD(UART0_REF_CTRL, SRCSEL, 0, 3) +REG32(UART1_REF_CTRL, 0x12c) + FIELD(UART1_REF_CTRL, CLKACT, 25, 1) + FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10) + FIELD(UART1_REF_CTRL, SRCSEL, 0, 3) +REG32(SPI0_REF_CTRL, 0x130) + FIELD(SPI0_REF_CTRL, CLKACT, 25, 1) + FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10) + FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3) +REG32(SPI1_REF_CTRL, 0x134) + FIELD(SPI1_REF_CTRL, CLKACT, 25, 1) + FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10) + FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3) +REG32(CAN0_REF_CTRL, 0x138) + FIELD(CAN0_REF_CTRL, CLKACT, 25, 1) + FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10) + FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3) +REG32(CAN1_REF_CTRL, 0x13c) + FIELD(CAN1_REF_CTRL, CLKACT, 25, 1) + FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10) + FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3) +REG32(I2C0_REF_CTRL, 0x140) + FIELD(I2C0_REF_CTRL, CLKACT, 25, 1) + FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10) + FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3) +REG32(I2C1_REF_CTRL, 0x144) + FIELD(I2C1_REF_CTRL, CLKACT, 25, 1) + FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10) + FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3) +REG32(DBG_LPD_CTRL, 0x148) + FIELD(DBG_LPD_CTRL, CLKACT, 25, 1) + FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10) + FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3) +REG32(TIMESTAMP_REF_CTRL, 0x14c) + FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1) + FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10) + FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3) +REG32(CRL_SAFETY_CHK, 0x150) +REG32(PSM_REF_CTRL, 0x154) + FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10) + FIELD(PSM_REF_CTRL, SRCSEL, 0, 3) +REG32(DBG_TSTMP_CTRL, 0x158) + FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1) + FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10) + FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3) +REG32(CPM_TOPSW_REF_CTRL, 0x15c) + FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1) + FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10) + FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3) +REG32(USB3_DUAL_REF_CTRL, 0x160) + FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1) + FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10) + FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3) +REG32(RST_CPU_R5, 0x300) + FIELD(RST_CPU_R5, RESET_PGE, 4, 1) + FIELD(RST_CPU_R5, RESET_AMBA, 2, 1) + FIELD(RST_CPU_R5, RESET_CPU1, 1, 1) + FIELD(RST_CPU_R5, RESET_CPU0, 0, 1) +REG32(RST_ADMA, 0x304) + FIELD(RST_ADMA, RESET, 0, 1) +REG32(RST_GEM0, 0x308) + FIELD(RST_GEM0, RESET, 0, 1) +REG32(RST_GEM1, 0x30c) + FIELD(RST_GEM1, RESET, 0, 1) +REG32(RST_SPARE, 0x310) + FIELD(RST_SPARE, RESET, 0, 1) +REG32(RST_USB0, 0x314) + FIELD(RST_USB0, RESET, 0, 1) +REG32(RST_UART0, 0x318) + FIELD(RST_UART0, RESET, 0, 1) +REG32(RST_UART1, 0x31c) + FIELD(RST_UART1, RESET, 0, 1) +REG32(RST_SPI0, 0x320) + FIELD(RST_SPI0, RESET, 0, 1) +REG32(RST_SPI1, 0x324) + FIELD(RST_SPI1, RESET, 0, 1) +REG32(RST_CAN0, 0x328) + FIELD(RST_CAN0, RESET, 0, 1) +REG32(RST_CAN1, 0x32c) + FIELD(RST_CAN1, RESET, 0, 1) +REG32(RST_I2C0, 0x330) + FIELD(RST_I2C0, RESET, 0, 1) +REG32(RST_I2C1, 0x334) + FIELD(RST_I2C1, RESET, 0, 1) +REG32(RST_DBG_LPD, 0x338) + FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1) + FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1) + FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1) + FIELD(RST_DBG_LPD, RESET, 0, 1) +REG32(RST_GPIO, 0x33c) + FIELD(RST_GPIO, RESET, 0, 1) +REG32(RST_TTC, 0x344) + FIELD(RST_TTC, TTC3_RESET, 3, 1) + FIELD(RST_TTC, TTC2_RESET, 2, 1) + FIELD(RST_TTC, TTC1_RESET, 1, 1) + FIELD(RST_TTC, TTC0_RESET, 0, 1) +REG32(RST_TIMESTAMP, 0x348) + FIELD(RST_TIMESTAMP, RESET, 0, 1) +REG32(RST_SWDT, 0x34c) + FIELD(RST_SWDT, RESET, 0, 1) +REG32(RST_OCM, 0x350) + FIELD(RST_OCM, RESET, 0, 1) +REG32(RST_IPI, 0x354) + FIELD(RST_IPI, RESET, 0, 1) +REG32(RST_SYSMON, 0x358) + FIELD(RST_SYSMON, SEQ_RST, 1, 1) + FIELD(RST_SYSMON, CFG_RST, 0, 1) +REG32(RST_FPD, 0x360) + FIELD(RST_FPD, SRST, 1, 1) + FIELD(RST_FPD, POR, 0, 1) +REG32(PSM_RST_MODE, 0x370) + FIELD(PSM_RST_MODE, WAKEUP, 2, 1) + FIELD(PSM_RST_MODE, RST_MODE, 0, 2) + +#define CRL_R_MAX (R_PSM_RST_MODE + 1) + +#define RPU_MAX_CPU 2 + +struct XlnxVersalCRL { + SysBusDevice parent_obj; + qemu_irq irq; + + struct { + ARMCPU *cpu_r5[RPU_MAX_CPU]; + DeviceState *adma[8]; + DeviceState *uart[2]; + DeviceState *gem[2]; + DeviceState *usb; + } cfg; + + RegisterInfoArray *reg_array; + uint32_t regs[CRL_R_MAX]; + RegisterInfo regs_info[CRL_R_MAX]; +}; +#endif -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* RE: [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL 2022-04-06 17:43 ` [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL Edgar E. Iglesias @ 2022-04-07 8:22 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 1 sibling, 0 replies; 14+ messages in thread From: Frederic Konrad @ 2022-04-07 8:22 UTC (permalink / raw) To: Edgar Iglesias, qemu-devel@nongnu.org Cc: Francisco Eduardo Iglesias, peter.maydell@linaro.org, luc@lmichel.fr, edgar.iglesias@amd.com, frasse.iglesias@gmail.com, alistair@alistair23.me, richard.henderson@linaro.org, f4bug@amsat.org, Sai Pavan Boddu, Edgar Iglesias, qemu-arm@nongnu.org > -----Original Message----- > From: Edgar E. Iglesias <edgar.iglesias@xilinx.com> > Sent: 06 April 2022 18:43 > To: qemu-devel@nongnu.org > Cc: qemu-arm@nongnu.org; peter.maydell@linaro.org; > richard.henderson@linaro.org; alistair@alistair23.me; luc@lmichel.fr; > f4bug@amsat.org; frasse.iglesias@gmail.com; Francisco Eduardo Iglesias > <figlesia@xilinx.com>; Sai Pavan Boddu <saipava@xilinx.com>; Frederic > Konrad <fkonrad@xilinx.com>; Edgar Iglesias <edgari@xilinx.com>; > edgar.iglesias@amd.com > Subject: [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL > > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> > > Add a model of the Xilinx Versal CRL. > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> > --- > hw/misc/meson.build | 1 + > hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++ > include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++ > 3 files changed, 657 insertions(+) > create mode 100644 hw/misc/xlnx-versal-crl.c > create mode 100644 include/hw/misc/xlnx-versal-crl.h > > diff --git a/hw/misc/meson.build b/hw/misc/meson.build > index 6fb69612e0..2ff05c7afa 100644 > --- a/hw/misc/meson.build > +++ b/hw/misc/meson.build > @@ -86,6 +86,7 @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: > files('slavio_misc.c')) > softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) > specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx- > zynqmp-crf.c')) > specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx- > zynqmp-apu-ctrl.c')) > +specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal- > crl.c')) > softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( > 'xlnx-versal-xramc.c', > 'xlnx-versal-pmc-iou-slcr.c', > diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c > new file mode 100644 > index 0000000000..767106b7a3 > --- /dev/null > +++ b/hw/misc/xlnx-versal-crl.c > @@ -0,0 +1,421 @@ > +/* > + * QEMU model of the Clock-Reset-LPD (CRL). > + * > + * Copyright (c) 2022 Advanced Micro Devices, Inc. > + * SPDX-License-Identifier: GPL-2.0-or-later > + * > + * Written by Edgar E. Iglesias <edgar.iglesias@amd.com> > + */ > + > +#include "qemu/osdep.h" > +#include "qapi/error.h" > +#include "qemu/log.h" > +#include "qemu/bitops.h" > +#include "migration/vmstate.h" > +#include "hw/qdev-properties.h" > +#include "hw/sysbus.h" > +#include "hw/irq.h" > +#include "hw/register.h" > +#include "hw/resettable.h" > + > +#include "target/arm/arm-powerctl.h" > +#include "hw/misc/xlnx-versal-crl.h" > + > +#ifndef XLNX_VERSAL_CRL_ERR_DEBUG > +#define XLNX_VERSAL_CRL_ERR_DEBUG 0 > +#endif > + > +static void crl_update_irq(XlnxVersalCRL *s) > +{ > + bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK]; > + qemu_set_irq(s->irq, pending); > +} > + > +static void crl_status_postw(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + crl_update_irq(s); > +} > + > +static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + uint32_t val = val64; > + > + s->regs[R_IR_MASK] &= ~val; > + crl_update_irq(s); > + return 0; > +} > + > +static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + uint32_t val = val64; > + > + s->regs[R_IR_MASK] |= val; > + crl_update_irq(s); > + return 0; > +} > + > +static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev, > + bool rst_old, bool rst_new) > +{ > + device_cold_reset(dev); > +} > + > +static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu, > + bool rst_old, bool rst_new) > +{ > + if (rst_new) { > + arm_set_cpu_off(armcpu->mp_affinity); > + } else { > + arm_set_cpu_on_and_reset(armcpu->mp_affinity); > + } > +} > + > +#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \ > + bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \ > + bool new_f = FIELD_EX32(new_val, reg, f); \ > + \ > + /* Detect edges. */ \ > + if (dev && old_f != new_f) { \ > + crl_reset_ ## type(s, dev, old_f, new_f); \ > + } \ > +} > + > +static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s- > >cfg.cpu_r5[0]); > + REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s- > >cfg.cpu_r5[1]); > + return val64; > +} > + > +static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + int i; > + > + /* A single register fans out to all ADMA reset inputs. */ > + for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) { > + REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]); > + } > + return val64; > +} > + > +static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]); > + return val64; > +} > + > +static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]); > + return val64; > +} > + > +static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]); > + return val64; > +} > + > +static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]); > + return val64; > +} > + > +static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb); > + return val64; > +} > + > +static const RegisterAccessInfo crl_regs_info[] = { > + { .name = "ERR_CTRL", .addr = A_ERR_CTRL, > + },{ .name = "IR_STATUS", .addr = A_IR_STATUS, > + .w1c = 0x1, > + .post_write = crl_status_postw, > + },{ .name = "IR_MASK", .addr = A_IR_MASK, > + .reset = 0x1, > + .ro = 0x1, > + },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE, > + .pre_write = crl_enable_prew, > + },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE, > + .pre_write = crl_disable_prew, > + },{ .name = "WPROT", .addr = A_WPROT, > + },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN, > + .reset = 0x1, > + .rsvd = 0xe, > + },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL, > + .reset = 0x24809, > + .rsvd = 0xf88c00f6, > + },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG, > + .reset = 0x2000000, > + .rsvd = 0x1801210, > + },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG, > + .rsvd = 0x7e330000, > + },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS, > + .reset = R_PLL_STATUS_RPLL_STABLE_MASK | > + R_PLL_STATUS_RPLL_LOCK_MASK, > + .rsvd = 0xfa, > + .ro = 0x5, > + },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL, > + .reset = 0x2000100, > + .rsvd = 0xfdfc00ff, > + },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = > A_LPD_TOP_SWITCH_CTRL, > + .reset = 0x6000300, > + .rsvd = 0xf9fc00f8, > + },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL, > + .reset = 0x2000800, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL, > + .reset = 0xe000300, > + .rsvd = 0xe1fc00f8, > + },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL, > + .reset = 0x2000500, > + .rsvd = 0xfdfc00f8, > + },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL, > + .reset = 0xe000a00, > + .rsvd = 0xf1fc00f8, > + },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL, > + .reset = 0xe000a00, > + .rsvd = 0xf1fc00f8, > + },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL, > + .reset = 0x300, > + .rsvd = 0xfdfc00f8, > + },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL, > + .reset = 0x2001900, > + .rsvd = 0xfdfc00f8, > + },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL, > + .reset = 0x600, > + .rsvd = 0xfdfc00f8, > + },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL, > + .reset = 0x600, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL, > + .reset = 0x300, > + .rsvd = 0xfdfc00f8, > + },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL, > + .reset = 0x2000c00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK, > + },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL, > + .reset = 0xf04, > + .rsvd = 0xfffc00f8, > + },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL, > + .reset = 0x300, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CPM_TOPSW_REF_CTRL", .addr = > A_CPM_TOPSW_REF_CTRL, > + .reset = 0x300, > + .rsvd = 0xfdfc00f8, > + },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL, > + .reset = 0x3c00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5, > + .reset = 0x17, > + .rsvd = 0x8, > + .pre_write = crl_rst_r5_prew, > + },{ .name = "RST_ADMA", .addr = A_RST_ADMA, > + .reset = 0x1, > + .pre_write = crl_rst_adma_prew, > + },{ .name = "RST_GEM0", .addr = A_RST_GEM0, > + .reset = 0x1, > + .pre_write = crl_rst_gem0_prew, > + },{ .name = "RST_GEM1", .addr = A_RST_GEM1, > + .reset = 0x1, > + .pre_write = crl_rst_gem1_prew, > + },{ .name = "RST_SPARE", .addr = A_RST_SPARE, > + .reset = 0x1, > + },{ .name = "RST_USB0", .addr = A_RST_USB0, > + .reset = 0x1, > + .pre_write = crl_rst_usb_prew, > + },{ .name = "RST_UART0", .addr = A_RST_UART0, > + .reset = 0x1, > + .pre_write = crl_rst_uart0_prew, > + },{ .name = "RST_UART1", .addr = A_RST_UART1, > + .reset = 0x1, > + .pre_write = crl_rst_uart1_prew, > + },{ .name = "RST_SPI0", .addr = A_RST_SPI0, > + .reset = 0x1, > + },{ .name = "RST_SPI1", .addr = A_RST_SPI1, > + .reset = 0x1, > + },{ .name = "RST_CAN0", .addr = A_RST_CAN0, > + .reset = 0x1, > + },{ .name = "RST_CAN1", .addr = A_RST_CAN1, > + .reset = 0x1, > + },{ .name = "RST_I2C0", .addr = A_RST_I2C0, > + .reset = 0x1, > + },{ .name = "RST_I2C1", .addr = A_RST_I2C1, > + .reset = 0x1, > + },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD, > + .reset = 0x33, > + .rsvd = 0xcc, > + },{ .name = "RST_GPIO", .addr = A_RST_GPIO, > + .reset = 0x1, > + },{ .name = "RST_TTC", .addr = A_RST_TTC, > + .reset = 0xf, > + },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP, > + .reset = 0x1, > + },{ .name = "RST_SWDT", .addr = A_RST_SWDT, > + .reset = 0x1, > + },{ .name = "RST_OCM", .addr = A_RST_OCM, > + },{ .name = "RST_IPI", .addr = A_RST_IPI, > + },{ .name = "RST_FPD", .addr = A_RST_FPD, > + .reset = 0x3, > + },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE, > + .reset = 0x1, > + .rsvd = 0xf8, > + } > +}; > + > +static void crl_reset_enter(Object *obj, ResetType type) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); > + unsigned int i; > + > + for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { > + register_reset(&s->regs_info[i]); > + } > +} > + > +static void crl_reset_hold(Object *obj) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); > + > + crl_update_irq(s); > +} > + > +static const MemoryRegionOps crl_ops = { > + .read = register_read_memory, > + .write = register_write_memory, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .valid = { > + .min_access_size = 4, > + .max_access_size = 4, > + }, > +}; > + > +static void crl_init(Object *obj) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); > + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); > + int i; > + > + s->reg_array = > + register_init_block32(DEVICE(obj), crl_regs_info, > + ARRAY_SIZE(crl_regs_info), > + s->regs_info, s->regs, > + &crl_ops, > + XLNX_VERSAL_CRL_ERR_DEBUG, > + CRL_R_MAX * 4); > + sysbus_init_mmio(sbd, &s->reg_array->mem); > + sysbus_init_irq(sbd, &s->irq); > + > + for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) { > + object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU, > + (Object **)&s->cfg.cpu_r5[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) { > + object_property_add_link(obj, "adma[*]", TYPE_DEVICE, > + (Object **)&s->cfg.adma[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) { > + object_property_add_link(obj, "uart[*]", TYPE_DEVICE, > + (Object **)&s->cfg.uart[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) { > + object_property_add_link(obj, "gem[*]", TYPE_DEVICE, > + (Object **)&s->cfg.gem[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > + } > + > + object_property_add_link(obj, "usb", TYPE_DEVICE, > + (Object **)&s->cfg.gem[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > +} > + > +static void crl_finalize(Object *obj) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); > + register_finalize_block(s->reg_array); > +} > + > +static const VMStateDescription vmstate_crl = { > + .name = TYPE_XLNX_VERSAL_CRL, > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX), > + VMSTATE_END_OF_LIST(), > + } > +}; > + > +static void crl_class_init(ObjectClass *klass, void *data) > +{ > + ResettableClass *rc = RESETTABLE_CLASS(klass); > + DeviceClass *dc = DEVICE_CLASS(klass); > + > + dc->vmsd = &vmstate_crl; > + > + rc->phases.enter = crl_reset_enter; > + rc->phases.hold = crl_reset_hold; > +} > + > +static const TypeInfo crl_info = { > + .name = TYPE_XLNX_VERSAL_CRL, > + .parent = TYPE_SYS_BUS_DEVICE, > + .instance_size = sizeof(XlnxVersalCRL), > + .class_init = crl_class_init, > + .instance_init = crl_init, > + .instance_finalize = crl_finalize, > +}; > + > +static void crl_register_types(void) > +{ > + type_register_static(&crl_info); > +} > + > +type_init(crl_register_types) > diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal- > crl.h > new file mode 100644 > index 0000000000..2857f4169a > --- /dev/null > +++ b/include/hw/misc/xlnx-versal-crl.h > @@ -0,0 +1,235 @@ > +/* > + * QEMU model of the Clock-Reset-LPD (CRL). > + * > + * Copyright (c) 2022 Xilinx Inc. > + * SPDX-License-Identifier: GPL-2.0-or-later > + * > + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com> > + */ > +#ifndef HW_MISC_XLNX_VERSAL_CRL_H > +#define HW_MISC_XLNX_VERSAL_CRL_H > + > +#include "hw/sysbus.h" > +#include "hw/register.h" > +#include "target/arm/cpu.h" > + > +#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl" > +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL) > + > +REG32(ERR_CTRL, 0x0) > + FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1) > +REG32(IR_STATUS, 0x4) > + FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1) > +REG32(IR_MASK, 0x8) > + FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1) > +REG32(IR_ENABLE, 0xc) > + FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1) > +REG32(IR_DISABLE, 0x10) > + FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1) > +REG32(WPROT, 0x1c) > + FIELD(WPROT, ACTIVE, 0, 1) > +REG32(PLL_CLK_OTHER_DMN, 0x20) > + FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1) > +REG32(RPLL_CTRL, 0x40) > + FIELD(RPLL_CTRL, POST_SRC, 24, 3) > + FIELD(RPLL_CTRL, PRE_SRC, 20, 3) > + FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2) > + FIELD(RPLL_CTRL, FBDIV, 8, 8) > + FIELD(RPLL_CTRL, BYPASS, 3, 1) > + FIELD(RPLL_CTRL, RESET, 0, 1) > +REG32(RPLL_CFG, 0x44) > + FIELD(RPLL_CFG, LOCK_DLY, 25, 7) > + FIELD(RPLL_CFG, LOCK_CNT, 13, 10) > + FIELD(RPLL_CFG, LFHF, 10, 2) > + FIELD(RPLL_CFG, CP, 5, 4) > + FIELD(RPLL_CFG, RES, 0, 4) > +REG32(RPLL_FRAC_CFG, 0x48) > + FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1) > + FIELD(RPLL_FRAC_CFG, SEED, 22, 3) > + FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1) > + FIELD(RPLL_FRAC_CFG, ORDER, 18, 1) > + FIELD(RPLL_FRAC_CFG, DATA, 0, 16) > +REG32(PLL_STATUS, 0x50) > + FIELD(PLL_STATUS, RPLL_STABLE, 2, 1) > + FIELD(PLL_STATUS, RPLL_LOCK, 0, 1) > +REG32(RPLL_TO_XPD_CTRL, 0x100) > + FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1) > + FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10) > +REG32(LPD_TOP_SWITCH_CTRL, 0x104) > + FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1) > + FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1) > + FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10) > + FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3) > +REG32(LPD_LSBUS_CTRL, 0x108) > + FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1) > + FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10) > + FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3) > +REG32(CPU_R5_CTRL, 0x10c) > + FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1) > + FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1) > + FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1) > + FIELD(CPU_R5_CTRL, CLKACT, 25, 1) > + FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10) > + FIELD(CPU_R5_CTRL, SRCSEL, 0, 3) > +REG32(IOU_SWITCH_CTRL, 0x114) > + FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1) > + FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10) > + FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3) > +REG32(GEM0_REF_CTRL, 0x118) > + FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1) > + FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1) > + FIELD(GEM0_REF_CTRL, CLKACT, 25, 1) > + FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3) > +REG32(GEM1_REF_CTRL, 0x11c) > + FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1) > + FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1) > + FIELD(GEM1_REF_CTRL, CLKACT, 25, 1) > + FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3) > +REG32(GEM_TSU_REF_CTRL, 0x120) > + FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1) > + FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3) > +REG32(USB0_BUS_REF_CTRL, 0x124) > + FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1) > + FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3) > +REG32(UART0_REF_CTRL, 0x128) > + FIELD(UART0_REF_CTRL, CLKACT, 25, 1) > + FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(UART0_REF_CTRL, SRCSEL, 0, 3) > +REG32(UART1_REF_CTRL, 0x12c) > + FIELD(UART1_REF_CTRL, CLKACT, 25, 1) > + FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(UART1_REF_CTRL, SRCSEL, 0, 3) > +REG32(SPI0_REF_CTRL, 0x130) > + FIELD(SPI0_REF_CTRL, CLKACT, 25, 1) > + FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3) > +REG32(SPI1_REF_CTRL, 0x134) > + FIELD(SPI1_REF_CTRL, CLKACT, 25, 1) > + FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3) > +REG32(CAN0_REF_CTRL, 0x138) > + FIELD(CAN0_REF_CTRL, CLKACT, 25, 1) > + FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3) > +REG32(CAN1_REF_CTRL, 0x13c) > + FIELD(CAN1_REF_CTRL, CLKACT, 25, 1) > + FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3) > +REG32(I2C0_REF_CTRL, 0x140) > + FIELD(I2C0_REF_CTRL, CLKACT, 25, 1) > + FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3) > +REG32(I2C1_REF_CTRL, 0x144) > + FIELD(I2C1_REF_CTRL, CLKACT, 25, 1) > + FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3) > +REG32(DBG_LPD_CTRL, 0x148) > + FIELD(DBG_LPD_CTRL, CLKACT, 25, 1) > + FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10) > + FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3) > +REG32(TIMESTAMP_REF_CTRL, 0x14c) > + FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1) > + FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3) > +REG32(CRL_SAFETY_CHK, 0x150) > +REG32(PSM_REF_CTRL, 0x154) > + FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(PSM_REF_CTRL, SRCSEL, 0, 3) > +REG32(DBG_TSTMP_CTRL, 0x158) > + FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1) > + FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10) > + FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3) > +REG32(CPM_TOPSW_REF_CTRL, 0x15c) > + FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1) > + FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3) > +REG32(USB3_DUAL_REF_CTRL, 0x160) > + FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1) > + FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3) > +REG32(RST_CPU_R5, 0x300) > + FIELD(RST_CPU_R5, RESET_PGE, 4, 1) > + FIELD(RST_CPU_R5, RESET_AMBA, 2, 1) > + FIELD(RST_CPU_R5, RESET_CPU1, 1, 1) > + FIELD(RST_CPU_R5, RESET_CPU0, 0, 1) > +REG32(RST_ADMA, 0x304) > + FIELD(RST_ADMA, RESET, 0, 1) > +REG32(RST_GEM0, 0x308) > + FIELD(RST_GEM0, RESET, 0, 1) > +REG32(RST_GEM1, 0x30c) > + FIELD(RST_GEM1, RESET, 0, 1) > +REG32(RST_SPARE, 0x310) > + FIELD(RST_SPARE, RESET, 0, 1) > +REG32(RST_USB0, 0x314) > + FIELD(RST_USB0, RESET, 0, 1) > +REG32(RST_UART0, 0x318) > + FIELD(RST_UART0, RESET, 0, 1) > +REG32(RST_UART1, 0x31c) > + FIELD(RST_UART1, RESET, 0, 1) > +REG32(RST_SPI0, 0x320) > + FIELD(RST_SPI0, RESET, 0, 1) > +REG32(RST_SPI1, 0x324) > + FIELD(RST_SPI1, RESET, 0, 1) > +REG32(RST_CAN0, 0x328) > + FIELD(RST_CAN0, RESET, 0, 1) > +REG32(RST_CAN1, 0x32c) > + FIELD(RST_CAN1, RESET, 0, 1) > +REG32(RST_I2C0, 0x330) > + FIELD(RST_I2C0, RESET, 0, 1) > +REG32(RST_I2C1, 0x334) > + FIELD(RST_I2C1, RESET, 0, 1) > +REG32(RST_DBG_LPD, 0x338) > + FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1) > + FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1) > + FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1) > + FIELD(RST_DBG_LPD, RESET, 0, 1) > +REG32(RST_GPIO, 0x33c) > + FIELD(RST_GPIO, RESET, 0, 1) > +REG32(RST_TTC, 0x344) > + FIELD(RST_TTC, TTC3_RESET, 3, 1) > + FIELD(RST_TTC, TTC2_RESET, 2, 1) > + FIELD(RST_TTC, TTC1_RESET, 1, 1) > + FIELD(RST_TTC, TTC0_RESET, 0, 1) > +REG32(RST_TIMESTAMP, 0x348) > + FIELD(RST_TIMESTAMP, RESET, 0, 1) > +REG32(RST_SWDT, 0x34c) > + FIELD(RST_SWDT, RESET, 0, 1) > +REG32(RST_OCM, 0x350) > + FIELD(RST_OCM, RESET, 0, 1) > +REG32(RST_IPI, 0x354) > + FIELD(RST_IPI, RESET, 0, 1) > +REG32(RST_SYSMON, 0x358) > + FIELD(RST_SYSMON, SEQ_RST, 1, 1) > + FIELD(RST_SYSMON, CFG_RST, 0, 1) > +REG32(RST_FPD, 0x360) > + FIELD(RST_FPD, SRST, 1, 1) > + FIELD(RST_FPD, POR, 0, 1) > +REG32(PSM_RST_MODE, 0x370) > + FIELD(PSM_RST_MODE, WAKEUP, 2, 1) > + FIELD(PSM_RST_MODE, RST_MODE, 0, 2) > + > +#define CRL_R_MAX (R_PSM_RST_MODE + 1) > + > +#define RPU_MAX_CPU 2 > + > +struct XlnxVersalCRL { > + SysBusDevice parent_obj; > + qemu_irq irq; > + > + struct { > + ARMCPU *cpu_r5[RPU_MAX_CPU]; > + DeviceState *adma[8]; > + DeviceState *uart[2]; > + DeviceState *gem[2]; > + DeviceState *usb; > + } cfg; > + > + RegisterInfoArray *reg_array; > + uint32_t regs[CRL_R_MAX]; > + RegisterInfo regs_info[CRL_R_MAX]; > +}; > +#endif > -- > 2.25.1 Looks ok to me: Reviewed-by: Frederic Konrad <fkonrad@amd.com> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL 2022-04-06 17:43 ` [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL Edgar E. Iglesias 2022-04-07 8:22 ` Frederic Konrad @ 2022-04-07 9:25 ` Francisco Iglesias 1 sibling, 0 replies; 14+ messages in thread From: Francisco Iglesias @ 2022-04-07 9:25 UTC (permalink / raw) To: Edgar E. Iglesias Cc: peter.maydell, luc, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, qemu-devel, f4bug, fkonrad, qemu-arm On Wed, Apr 06, 2022 at 06:43:02PM +0100, Edgar E. Iglesias wrote: > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> > > Add a model of the Xilinx Versal CRL. > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com> > --- > hw/misc/meson.build | 1 + > hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++ > include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++ > 3 files changed, 657 insertions(+) > create mode 100644 hw/misc/xlnx-versal-crl.c > create mode 100644 include/hw/misc/xlnx-versal-crl.h > > diff --git a/hw/misc/meson.build b/hw/misc/meson.build > index 6fb69612e0..2ff05c7afa 100644 > --- a/hw/misc/meson.build > +++ b/hw/misc/meson.build > @@ -86,6 +86,7 @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c')) > softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c')) > specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c')) > specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c')) > +specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c')) > softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( > 'xlnx-versal-xramc.c', > 'xlnx-versal-pmc-iou-slcr.c', > diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c > new file mode 100644 > index 0000000000..767106b7a3 > --- /dev/null > +++ b/hw/misc/xlnx-versal-crl.c > @@ -0,0 +1,421 @@ > +/* > + * QEMU model of the Clock-Reset-LPD (CRL). > + * > + * Copyright (c) 2022 Advanced Micro Devices, Inc. > + * SPDX-License-Identifier: GPL-2.0-or-later > + * > + * Written by Edgar E. Iglesias <edgar.iglesias@amd.com> > + */ > + > +#include "qemu/osdep.h" > +#include "qapi/error.h" > +#include "qemu/log.h" > +#include "qemu/bitops.h" > +#include "migration/vmstate.h" > +#include "hw/qdev-properties.h" > +#include "hw/sysbus.h" > +#include "hw/irq.h" > +#include "hw/register.h" > +#include "hw/resettable.h" > + > +#include "target/arm/arm-powerctl.h" > +#include "hw/misc/xlnx-versal-crl.h" > + > +#ifndef XLNX_VERSAL_CRL_ERR_DEBUG > +#define XLNX_VERSAL_CRL_ERR_DEBUG 0 > +#endif > + > +static void crl_update_irq(XlnxVersalCRL *s) > +{ > + bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK]; > + qemu_set_irq(s->irq, pending); > +} > + > +static void crl_status_postw(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + crl_update_irq(s); > +} > + > +static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + uint32_t val = val64; > + > + s->regs[R_IR_MASK] &= ~val; > + crl_update_irq(s); > + return 0; > +} > + > +static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + uint32_t val = val64; > + > + s->regs[R_IR_MASK] |= val; > + crl_update_irq(s); > + return 0; > +} > + > +static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev, > + bool rst_old, bool rst_new) > +{ > + device_cold_reset(dev); > +} > + > +static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu, > + bool rst_old, bool rst_new) > +{ > + if (rst_new) { > + arm_set_cpu_off(armcpu->mp_affinity); > + } else { > + arm_set_cpu_on_and_reset(armcpu->mp_affinity); > + } > +} > + > +#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \ > + bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \ > + bool new_f = FIELD_EX32(new_val, reg, f); \ > + \ > + /* Detect edges. */ \ > + if (dev && old_f != new_f) { \ > + crl_reset_ ## type(s, dev, old_f, new_f); \ > + } \ > +} > + > +static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]); > + REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]); > + return val64; > +} > + > +static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + int i; > + > + /* A single register fans out to all ADMA reset inputs. */ > + for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) { > + REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]); > + } > + return val64; > +} > + > +static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]); > + return val64; > +} > + > +static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]); > + return val64; > +} > + > +static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]); > + return val64; > +} > + > +static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]); > + return val64; > +} > + > +static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque); > + > + REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb); > + return val64; > +} > + > +static const RegisterAccessInfo crl_regs_info[] = { > + { .name = "ERR_CTRL", .addr = A_ERR_CTRL, > + },{ .name = "IR_STATUS", .addr = A_IR_STATUS, > + .w1c = 0x1, > + .post_write = crl_status_postw, > + },{ .name = "IR_MASK", .addr = A_IR_MASK, > + .reset = 0x1, > + .ro = 0x1, > + },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE, > + .pre_write = crl_enable_prew, > + },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE, > + .pre_write = crl_disable_prew, > + },{ .name = "WPROT", .addr = A_WPROT, > + },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN, > + .reset = 0x1, > + .rsvd = 0xe, > + },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL, > + .reset = 0x24809, > + .rsvd = 0xf88c00f6, > + },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG, > + .reset = 0x2000000, > + .rsvd = 0x1801210, > + },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG, > + .rsvd = 0x7e330000, > + },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS, > + .reset = R_PLL_STATUS_RPLL_STABLE_MASK | > + R_PLL_STATUS_RPLL_LOCK_MASK, > + .rsvd = 0xfa, > + .ro = 0x5, > + },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL, > + .reset = 0x2000100, > + .rsvd = 0xfdfc00ff, > + },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL, > + .reset = 0x6000300, > + .rsvd = 0xf9fc00f8, > + },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL, > + .reset = 0x2000800, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL, > + .reset = 0xe000300, > + .rsvd = 0xe1fc00f8, > + },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL, > + .reset = 0x2000500, > + .rsvd = 0xfdfc00f8, > + },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL, > + .reset = 0xe000a00, > + .rsvd = 0xf1fc00f8, > + },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL, > + .reset = 0xe000a00, > + .rsvd = 0xf1fc00f8, > + },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL, > + .reset = 0x300, > + .rsvd = 0xfdfc00f8, > + },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL, > + .reset = 0x2001900, > + .rsvd = 0xfdfc00f8, > + },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL, > + .reset = 0x600, > + .rsvd = 0xfdfc00f8, > + },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL, > + .reset = 0x600, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL, > + .reset = 0xc00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL, > + .reset = 0x300, > + .rsvd = 0xfdfc00f8, > + },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL, > + .reset = 0x2000c00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK, > + },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL, > + .reset = 0xf04, > + .rsvd = 0xfffc00f8, > + },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL, > + .reset = 0x300, > + .rsvd = 0xfdfc00f8, > + },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL, > + .reset = 0x300, > + .rsvd = 0xfdfc00f8, > + },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL, > + .reset = 0x3c00, > + .rsvd = 0xfdfc00f8, > + },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5, > + .reset = 0x17, > + .rsvd = 0x8, > + .pre_write = crl_rst_r5_prew, > + },{ .name = "RST_ADMA", .addr = A_RST_ADMA, > + .reset = 0x1, > + .pre_write = crl_rst_adma_prew, > + },{ .name = "RST_GEM0", .addr = A_RST_GEM0, > + .reset = 0x1, > + .pre_write = crl_rst_gem0_prew, > + },{ .name = "RST_GEM1", .addr = A_RST_GEM1, > + .reset = 0x1, > + .pre_write = crl_rst_gem1_prew, > + },{ .name = "RST_SPARE", .addr = A_RST_SPARE, > + .reset = 0x1, > + },{ .name = "RST_USB0", .addr = A_RST_USB0, > + .reset = 0x1, > + .pre_write = crl_rst_usb_prew, > + },{ .name = "RST_UART0", .addr = A_RST_UART0, > + .reset = 0x1, > + .pre_write = crl_rst_uart0_prew, > + },{ .name = "RST_UART1", .addr = A_RST_UART1, > + .reset = 0x1, > + .pre_write = crl_rst_uart1_prew, > + },{ .name = "RST_SPI0", .addr = A_RST_SPI0, > + .reset = 0x1, > + },{ .name = "RST_SPI1", .addr = A_RST_SPI1, > + .reset = 0x1, > + },{ .name = "RST_CAN0", .addr = A_RST_CAN0, > + .reset = 0x1, > + },{ .name = "RST_CAN1", .addr = A_RST_CAN1, > + .reset = 0x1, > + },{ .name = "RST_I2C0", .addr = A_RST_I2C0, > + .reset = 0x1, > + },{ .name = "RST_I2C1", .addr = A_RST_I2C1, > + .reset = 0x1, > + },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD, > + .reset = 0x33, > + .rsvd = 0xcc, > + },{ .name = "RST_GPIO", .addr = A_RST_GPIO, > + .reset = 0x1, > + },{ .name = "RST_TTC", .addr = A_RST_TTC, > + .reset = 0xf, > + },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP, > + .reset = 0x1, > + },{ .name = "RST_SWDT", .addr = A_RST_SWDT, > + .reset = 0x1, > + },{ .name = "RST_OCM", .addr = A_RST_OCM, > + },{ .name = "RST_IPI", .addr = A_RST_IPI, > + },{ .name = "RST_FPD", .addr = A_RST_FPD, > + .reset = 0x3, > + },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE, > + .reset = 0x1, > + .rsvd = 0xf8, > + } > +}; > + > +static void crl_reset_enter(Object *obj, ResetType type) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); > + unsigned int i; > + > + for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { > + register_reset(&s->regs_info[i]); > + } > +} > + > +static void crl_reset_hold(Object *obj) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); > + > + crl_update_irq(s); > +} > + > +static const MemoryRegionOps crl_ops = { > + .read = register_read_memory, > + .write = register_write_memory, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .valid = { > + .min_access_size = 4, > + .max_access_size = 4, > + }, > +}; > + > +static void crl_init(Object *obj) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); > + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); > + int i; > + > + s->reg_array = > + register_init_block32(DEVICE(obj), crl_regs_info, > + ARRAY_SIZE(crl_regs_info), > + s->regs_info, s->regs, > + &crl_ops, > + XLNX_VERSAL_CRL_ERR_DEBUG, > + CRL_R_MAX * 4); > + sysbus_init_mmio(sbd, &s->reg_array->mem); > + sysbus_init_irq(sbd, &s->irq); > + > + for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) { > + object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU, > + (Object **)&s->cfg.cpu_r5[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) { > + object_property_add_link(obj, "adma[*]", TYPE_DEVICE, > + (Object **)&s->cfg.adma[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) { > + object_property_add_link(obj, "uart[*]", TYPE_DEVICE, > + (Object **)&s->cfg.uart[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) { > + object_property_add_link(obj, "gem[*]", TYPE_DEVICE, > + (Object **)&s->cfg.gem[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > + } > + > + object_property_add_link(obj, "usb", TYPE_DEVICE, > + (Object **)&s->cfg.gem[i], > + qdev_prop_allow_set_link_before_realize, > + OBJ_PROP_LINK_STRONG); > +} > + > +static void crl_finalize(Object *obj) > +{ > + XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj); > + register_finalize_block(s->reg_array); > +} > + > +static const VMStateDescription vmstate_crl = { > + .name = TYPE_XLNX_VERSAL_CRL, > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX), > + VMSTATE_END_OF_LIST(), > + } > +}; > + > +static void crl_class_init(ObjectClass *klass, void *data) > +{ > + ResettableClass *rc = RESETTABLE_CLASS(klass); > + DeviceClass *dc = DEVICE_CLASS(klass); > + > + dc->vmsd = &vmstate_crl; > + > + rc->phases.enter = crl_reset_enter; > + rc->phases.hold = crl_reset_hold; > +} > + > +static const TypeInfo crl_info = { > + .name = TYPE_XLNX_VERSAL_CRL, > + .parent = TYPE_SYS_BUS_DEVICE, > + .instance_size = sizeof(XlnxVersalCRL), > + .class_init = crl_class_init, > + .instance_init = crl_init, > + .instance_finalize = crl_finalize, > +}; > + > +static void crl_register_types(void) > +{ > + type_register_static(&crl_info); > +} > + > +type_init(crl_register_types) > diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h > new file mode 100644 > index 0000000000..2857f4169a > --- /dev/null > +++ b/include/hw/misc/xlnx-versal-crl.h > @@ -0,0 +1,235 @@ > +/* > + * QEMU model of the Clock-Reset-LPD (CRL). > + * > + * Copyright (c) 2022 Xilinx Inc. > + * SPDX-License-Identifier: GPL-2.0-or-later > + * > + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com> > + */ > +#ifndef HW_MISC_XLNX_VERSAL_CRL_H > +#define HW_MISC_XLNX_VERSAL_CRL_H > + > +#include "hw/sysbus.h" > +#include "hw/register.h" > +#include "target/arm/cpu.h" > + > +#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl" > +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL) > + > +REG32(ERR_CTRL, 0x0) > + FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1) > +REG32(IR_STATUS, 0x4) > + FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1) > +REG32(IR_MASK, 0x8) > + FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1) > +REG32(IR_ENABLE, 0xc) > + FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1) > +REG32(IR_DISABLE, 0x10) > + FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1) > +REG32(WPROT, 0x1c) > + FIELD(WPROT, ACTIVE, 0, 1) > +REG32(PLL_CLK_OTHER_DMN, 0x20) > + FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1) > +REG32(RPLL_CTRL, 0x40) > + FIELD(RPLL_CTRL, POST_SRC, 24, 3) > + FIELD(RPLL_CTRL, PRE_SRC, 20, 3) > + FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2) > + FIELD(RPLL_CTRL, FBDIV, 8, 8) > + FIELD(RPLL_CTRL, BYPASS, 3, 1) > + FIELD(RPLL_CTRL, RESET, 0, 1) > +REG32(RPLL_CFG, 0x44) > + FIELD(RPLL_CFG, LOCK_DLY, 25, 7) > + FIELD(RPLL_CFG, LOCK_CNT, 13, 10) > + FIELD(RPLL_CFG, LFHF, 10, 2) > + FIELD(RPLL_CFG, CP, 5, 4) > + FIELD(RPLL_CFG, RES, 0, 4) > +REG32(RPLL_FRAC_CFG, 0x48) > + FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1) > + FIELD(RPLL_FRAC_CFG, SEED, 22, 3) > + FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1) > + FIELD(RPLL_FRAC_CFG, ORDER, 18, 1) > + FIELD(RPLL_FRAC_CFG, DATA, 0, 16) > +REG32(PLL_STATUS, 0x50) > + FIELD(PLL_STATUS, RPLL_STABLE, 2, 1) > + FIELD(PLL_STATUS, RPLL_LOCK, 0, 1) > +REG32(RPLL_TO_XPD_CTRL, 0x100) > + FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1) > + FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10) > +REG32(LPD_TOP_SWITCH_CTRL, 0x104) > + FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1) > + FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1) > + FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10) > + FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3) > +REG32(LPD_LSBUS_CTRL, 0x108) > + FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1) > + FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10) > + FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3) > +REG32(CPU_R5_CTRL, 0x10c) > + FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1) > + FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1) > + FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1) > + FIELD(CPU_R5_CTRL, CLKACT, 25, 1) > + FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10) > + FIELD(CPU_R5_CTRL, SRCSEL, 0, 3) > +REG32(IOU_SWITCH_CTRL, 0x114) > + FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1) > + FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10) > + FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3) > +REG32(GEM0_REF_CTRL, 0x118) > + FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1) > + FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1) > + FIELD(GEM0_REF_CTRL, CLKACT, 25, 1) > + FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3) > +REG32(GEM1_REF_CTRL, 0x11c) > + FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1) > + FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1) > + FIELD(GEM1_REF_CTRL, CLKACT, 25, 1) > + FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3) > +REG32(GEM_TSU_REF_CTRL, 0x120) > + FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1) > + FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3) > +REG32(USB0_BUS_REF_CTRL, 0x124) > + FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1) > + FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3) > +REG32(UART0_REF_CTRL, 0x128) > + FIELD(UART0_REF_CTRL, CLKACT, 25, 1) > + FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(UART0_REF_CTRL, SRCSEL, 0, 3) > +REG32(UART1_REF_CTRL, 0x12c) > + FIELD(UART1_REF_CTRL, CLKACT, 25, 1) > + FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(UART1_REF_CTRL, SRCSEL, 0, 3) > +REG32(SPI0_REF_CTRL, 0x130) > + FIELD(SPI0_REF_CTRL, CLKACT, 25, 1) > + FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3) > +REG32(SPI1_REF_CTRL, 0x134) > + FIELD(SPI1_REF_CTRL, CLKACT, 25, 1) > + FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3) > +REG32(CAN0_REF_CTRL, 0x138) > + FIELD(CAN0_REF_CTRL, CLKACT, 25, 1) > + FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3) > +REG32(CAN1_REF_CTRL, 0x13c) > + FIELD(CAN1_REF_CTRL, CLKACT, 25, 1) > + FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3) > +REG32(I2C0_REF_CTRL, 0x140) > + FIELD(I2C0_REF_CTRL, CLKACT, 25, 1) > + FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3) > +REG32(I2C1_REF_CTRL, 0x144) > + FIELD(I2C1_REF_CTRL, CLKACT, 25, 1) > + FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3) > +REG32(DBG_LPD_CTRL, 0x148) > + FIELD(DBG_LPD_CTRL, CLKACT, 25, 1) > + FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10) > + FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3) > +REG32(TIMESTAMP_REF_CTRL, 0x14c) > + FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1) > + FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3) > +REG32(CRL_SAFETY_CHK, 0x150) > +REG32(PSM_REF_CTRL, 0x154) > + FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(PSM_REF_CTRL, SRCSEL, 0, 3) > +REG32(DBG_TSTMP_CTRL, 0x158) > + FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1) > + FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10) > + FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3) > +REG32(CPM_TOPSW_REF_CTRL, 0x15c) > + FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1) > + FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3) > +REG32(USB3_DUAL_REF_CTRL, 0x160) > + FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1) > + FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10) > + FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3) > +REG32(RST_CPU_R5, 0x300) > + FIELD(RST_CPU_R5, RESET_PGE, 4, 1) > + FIELD(RST_CPU_R5, RESET_AMBA, 2, 1) > + FIELD(RST_CPU_R5, RESET_CPU1, 1, 1) > + FIELD(RST_CPU_R5, RESET_CPU0, 0, 1) > +REG32(RST_ADMA, 0x304) > + FIELD(RST_ADMA, RESET, 0, 1) > +REG32(RST_GEM0, 0x308) > + FIELD(RST_GEM0, RESET, 0, 1) > +REG32(RST_GEM1, 0x30c) > + FIELD(RST_GEM1, RESET, 0, 1) > +REG32(RST_SPARE, 0x310) > + FIELD(RST_SPARE, RESET, 0, 1) > +REG32(RST_USB0, 0x314) > + FIELD(RST_USB0, RESET, 0, 1) > +REG32(RST_UART0, 0x318) > + FIELD(RST_UART0, RESET, 0, 1) > +REG32(RST_UART1, 0x31c) > + FIELD(RST_UART1, RESET, 0, 1) > +REG32(RST_SPI0, 0x320) > + FIELD(RST_SPI0, RESET, 0, 1) > +REG32(RST_SPI1, 0x324) > + FIELD(RST_SPI1, RESET, 0, 1) > +REG32(RST_CAN0, 0x328) > + FIELD(RST_CAN0, RESET, 0, 1) > +REG32(RST_CAN1, 0x32c) > + FIELD(RST_CAN1, RESET, 0, 1) > +REG32(RST_I2C0, 0x330) > + FIELD(RST_I2C0, RESET, 0, 1) > +REG32(RST_I2C1, 0x334) > + FIELD(RST_I2C1, RESET, 0, 1) > +REG32(RST_DBG_LPD, 0x338) > + FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1) > + FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1) > + FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1) > + FIELD(RST_DBG_LPD, RESET, 0, 1) > +REG32(RST_GPIO, 0x33c) > + FIELD(RST_GPIO, RESET, 0, 1) > +REG32(RST_TTC, 0x344) > + FIELD(RST_TTC, TTC3_RESET, 3, 1) > + FIELD(RST_TTC, TTC2_RESET, 2, 1) > + FIELD(RST_TTC, TTC1_RESET, 1, 1) > + FIELD(RST_TTC, TTC0_RESET, 0, 1) > +REG32(RST_TIMESTAMP, 0x348) > + FIELD(RST_TIMESTAMP, RESET, 0, 1) > +REG32(RST_SWDT, 0x34c) > + FIELD(RST_SWDT, RESET, 0, 1) > +REG32(RST_OCM, 0x350) > + FIELD(RST_OCM, RESET, 0, 1) > +REG32(RST_IPI, 0x354) > + FIELD(RST_IPI, RESET, 0, 1) > +REG32(RST_SYSMON, 0x358) > + FIELD(RST_SYSMON, SEQ_RST, 1, 1) > + FIELD(RST_SYSMON, CFG_RST, 0, 1) > +REG32(RST_FPD, 0x360) > + FIELD(RST_FPD, SRST, 1, 1) > + FIELD(RST_FPD, POR, 0, 1) > +REG32(PSM_RST_MODE, 0x370) > + FIELD(PSM_RST_MODE, WAKEUP, 2, 1) > + FIELD(PSM_RST_MODE, RST_MODE, 0, 2) > + > +#define CRL_R_MAX (R_PSM_RST_MODE + 1) > + > +#define RPU_MAX_CPU 2 > + > +struct XlnxVersalCRL { > + SysBusDevice parent_obj; > + qemu_irq irq; > + > + struct { > + ARMCPU *cpu_r5[RPU_MAX_CPU]; > + DeviceState *adma[8]; > + DeviceState *uart[2]; > + DeviceState *gem[2]; > + DeviceState *usb; > + } cfg; > + > + RegisterInfoArray *reg_array; > + uint32_t regs[CRL_R_MAX]; > + RegisterInfo regs_info[CRL_R_MAX]; > +}; > +#endif > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v1 4/4] hw/arm: versal: Connect the CRL 2022-04-06 17:42 [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Edgar E. Iglesias ` (2 preceding siblings ...) 2022-04-06 17:43 ` [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL Edgar E. Iglesias @ 2022-04-06 17:43 ` Edgar E. Iglesias 2022-04-07 8:57 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 2022-04-11 10:49 ` [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Peter Maydell 4 siblings, 2 replies; 14+ messages in thread From: Edgar E. Iglesias @ 2022-04-06 17:43 UTC (permalink / raw) To: qemu-devel Cc: edgar.iglesias, peter.maydell, luc, fkonrad, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, f4bug, francisco.iglesias, qemu-arm From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> Connect the CRL (Clock Reset LPD) to the Versal SoC. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> --- hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++-- include/hw/arm/xlnx-versal.h | 4 +++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index ebad8dbb6d..57276e1506 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -539,6 +539,57 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic) qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]); } +static void versal_create_crl(Versal *s, qemu_irq *pic) +{ + SysBusDevice *sbd; + int i; + + object_initialize_child(OBJECT(s), "crl", &s->lpd.crl, + TYPE_XLNX_VERSAL_CRL); + sbd = SYS_BUS_DEVICE(&s->lpd.crl); + + for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) { + g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i); + + object_property_set_link(OBJECT(&s->lpd.crl), + name, OBJECT(&s->lpd.rpu.cpu[i]), + &error_abort); + } + + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) { + g_autofree gchar *name = g_strdup_printf("gem[%d]", i); + + object_property_set_link(OBJECT(&s->lpd.crl), + name, OBJECT(&s->lpd.iou.gem[i]), + &error_abort); + } + + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) { + g_autofree gchar *name = g_strdup_printf("adma[%d]", i); + + object_property_set_link(OBJECT(&s->lpd.crl), + name, OBJECT(&s->lpd.iou.adma[i]), + &error_abort); + } + + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) { + g_autofree gchar *name = g_strdup_printf("uart[%d]", i); + + object_property_set_link(OBJECT(&s->lpd.crl), + name, OBJECT(&s->lpd.iou.uart[i]), + &error_abort); + } + + object_property_set_link(OBJECT(&s->lpd.crl), + "usb", OBJECT(&s->lpd.iou.usb), + &error_abort); + + sysbus_realize(sbd, &error_fatal); + memory_region_add_subregion(&s->mr_ps, MM_CRL, + sysbus_mmio_get_region(sbd, 0)); + sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]); +} + /* This takes the board allocated linear DDR memory and creates aliases * for each split DDR range/aperture on the Versal address map. */ @@ -622,8 +673,6 @@ static void versal_unimp(Versal *s) versal_unimp_area(s, "psm", &s->mr_ps, MM_PSM_START, MM_PSM_END - MM_PSM_START); - versal_unimp_area(s, "crl", &s->mr_ps, - MM_CRL, MM_CRL_SIZE); versal_unimp_area(s, "crf", &s->mr_ps, MM_FPD_CRF, MM_FPD_CRF_SIZE); versal_unimp_area(s, "apu", &s->mr_ps, @@ -681,6 +730,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_efuse(s, pic); versal_create_pmc_iou_slcr(s, pic); versal_create_ospi(s, pic); + versal_create_crl(s, pic); versal_map_ddr(s); versal_unimp(s); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 155e8c4b8c..cbe8a19c10 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -29,6 +29,7 @@ #include "hw/nvram/xlnx-versal-efuse.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" #define TYPE_XLNX_VERSAL "xlnx-versal" @@ -87,6 +88,8 @@ struct Versal { qemu_or_irq irq_orgate; XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM]; } xram; + + XlnxVersalCRL crl; } lpd; /* The Platform Management Controller subsystem. */ @@ -127,6 +130,7 @@ struct Versal { #define VERSAL_TIMER_NS_EL1_IRQ 14 #define VERSAL_TIMER_NS_EL2_IRQ 10 +#define VERSAL_CRL_IRQ 10 #define VERSAL_UART0_IRQ_0 18 #define VERSAL_UART1_IRQ_0 19 #define VERSAL_USB0_IRQ_0 22 -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* RE: [PATCH v1 4/4] hw/arm: versal: Connect the CRL 2022-04-06 17:43 ` [PATCH v1 4/4] hw/arm: versal: Connect the CRL Edgar E. Iglesias @ 2022-04-07 8:57 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 1 sibling, 0 replies; 14+ messages in thread From: Frederic Konrad @ 2022-04-07 8:57 UTC (permalink / raw) To: Edgar Iglesias, qemu-devel@nongnu.org Cc: Francisco Eduardo Iglesias, peter.maydell@linaro.org, luc@lmichel.fr, edgar.iglesias@amd.com, frasse.iglesias@gmail.com, alistair@alistair23.me, richard.henderson@linaro.org, f4bug@amsat.org, Sai Pavan Boddu, Edgar Iglesias, qemu-arm@nongnu.org > -----Original Message----- > From: Edgar E. Iglesias <edgar.iglesias@xilinx.com> > Sent: 06 April 2022 18:43 > To: qemu-devel@nongnu.org > Cc: qemu-arm@nongnu.org; peter.maydell@linaro.org; > richard.henderson@linaro.org; alistair@alistair23.me; luc@lmichel.fr; > f4bug@amsat.org; frasse.iglesias@gmail.com; Francisco Eduardo Iglesias > <figlesia@xilinx.com>; Sai Pavan Boddu <saipava@xilinx.com>; Frederic > Konrad <fkonrad@xilinx.com>; Edgar Iglesias <edgari@xilinx.com>; > edgar.iglesias@amd.com > Subject: [PATCH v1 4/4] hw/arm: versal: Connect the CRL > > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> > > Connect the CRL (Clock Reset LPD) to the Versal SoC. > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> > --- > hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++-- > include/hw/arm/xlnx-versal.h | 4 +++ > 2 files changed, 56 insertions(+), 2 deletions(-) > > diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c > index ebad8dbb6d..57276e1506 100644 > --- a/hw/arm/xlnx-versal.c > +++ b/hw/arm/xlnx-versal.c > @@ -539,6 +539,57 @@ static void versal_create_ospi(Versal *s, qemu_irq > *pic) > qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]); > } > > +static void versal_create_crl(Versal *s, qemu_irq *pic) > +{ > + SysBusDevice *sbd; > + int i; > + > + object_initialize_child(OBJECT(s), "crl", &s->lpd.crl, > + TYPE_XLNX_VERSAL_CRL); > + sbd = SYS_BUS_DEVICE(&s->lpd.crl); > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) { > + g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i); > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + name, OBJECT(&s->lpd.rpu.cpu[i]), > + &error_abort); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) { > + g_autofree gchar *name = g_strdup_printf("gem[%d]", i); > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + name, OBJECT(&s->lpd.iou.gem[i]), > + &error_abort); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) { > + g_autofree gchar *name = g_strdup_printf("adma[%d]", i); > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + name, OBJECT(&s->lpd.iou.adma[i]), > + &error_abort); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) { > + g_autofree gchar *name = g_strdup_printf("uart[%d]", i); > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + name, OBJECT(&s->lpd.iou.uart[i]), > + &error_abort); > + } > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + "usb", OBJECT(&s->lpd.iou.usb), > + &error_abort); > + > + sysbus_realize(sbd, &error_fatal); > + memory_region_add_subregion(&s->mr_ps, MM_CRL, > + sysbus_mmio_get_region(sbd, 0)); > + sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]); > +} > + > /* This takes the board allocated linear DDR memory and creates aliases > * for each split DDR range/aperture on the Versal address map. > */ > @@ -622,8 +673,6 @@ static void versal_unimp(Versal *s) > > versal_unimp_area(s, "psm", &s->mr_ps, > MM_PSM_START, MM_PSM_END - MM_PSM_START); > - versal_unimp_area(s, "crl", &s->mr_ps, > - MM_CRL, MM_CRL_SIZE); > versal_unimp_area(s, "crf", &s->mr_ps, > MM_FPD_CRF, MM_FPD_CRF_SIZE); > versal_unimp_area(s, "apu", &s->mr_ps, > @@ -681,6 +730,7 @@ static void versal_realize(DeviceState *dev, Error > **errp) > versal_create_efuse(s, pic); > versal_create_pmc_iou_slcr(s, pic); > versal_create_ospi(s, pic); > + versal_create_crl(s, pic); > versal_map_ddr(s); > versal_unimp(s); > > diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h > index 155e8c4b8c..cbe8a19c10 100644 > --- a/include/hw/arm/xlnx-versal.h > +++ b/include/hw/arm/xlnx-versal.h > @@ -29,6 +29,7 @@ > #include "hw/nvram/xlnx-versal-efuse.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" > > #define TYPE_XLNX_VERSAL "xlnx-versal" > @@ -87,6 +88,8 @@ struct Versal { > qemu_or_irq irq_orgate; > XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM]; > } xram; > + > + XlnxVersalCRL crl; > } lpd; > > /* The Platform Management Controller subsystem. */ > @@ -127,6 +130,7 @@ struct Versal { > #define VERSAL_TIMER_NS_EL1_IRQ 14 > #define VERSAL_TIMER_NS_EL2_IRQ 10 > > +#define VERSAL_CRL_IRQ 10 > #define VERSAL_UART0_IRQ_0 18 > #define VERSAL_UART1_IRQ_0 19 > #define VERSAL_USB0_IRQ_0 22 > -- > 2.25.1 Reviewed-by: Frederic Konrad <fkonrad@amd.com> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 4/4] hw/arm: versal: Connect the CRL 2022-04-06 17:43 ` [PATCH v1 4/4] hw/arm: versal: Connect the CRL Edgar E. Iglesias 2022-04-07 8:57 ` Frederic Konrad @ 2022-04-07 9:25 ` Francisco Iglesias 1 sibling, 0 replies; 14+ messages in thread From: Francisco Iglesias @ 2022-04-07 9:25 UTC (permalink / raw) To: Edgar E. Iglesias Cc: peter.maydell, luc, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, qemu-devel, f4bug, fkonrad, qemu-arm On Wed, Apr 06, 2022 at 06:43:03PM +0100, Edgar E. Iglesias wrote: > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> > > Connect the CRL (Clock Reset LPD) to the Versal SoC. > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com> > --- > hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++-- > include/hw/arm/xlnx-versal.h | 4 +++ > 2 files changed, 56 insertions(+), 2 deletions(-) > > diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c > index ebad8dbb6d..57276e1506 100644 > --- a/hw/arm/xlnx-versal.c > +++ b/hw/arm/xlnx-versal.c > @@ -539,6 +539,57 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic) > qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]); > } > > +static void versal_create_crl(Versal *s, qemu_irq *pic) > +{ > + SysBusDevice *sbd; > + int i; > + > + object_initialize_child(OBJECT(s), "crl", &s->lpd.crl, > + TYPE_XLNX_VERSAL_CRL); > + sbd = SYS_BUS_DEVICE(&s->lpd.crl); > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) { > + g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i); > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + name, OBJECT(&s->lpd.rpu.cpu[i]), > + &error_abort); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) { > + g_autofree gchar *name = g_strdup_printf("gem[%d]", i); > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + name, OBJECT(&s->lpd.iou.gem[i]), > + &error_abort); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) { > + g_autofree gchar *name = g_strdup_printf("adma[%d]", i); > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + name, OBJECT(&s->lpd.iou.adma[i]), > + &error_abort); > + } > + > + for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) { > + g_autofree gchar *name = g_strdup_printf("uart[%d]", i); > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + name, OBJECT(&s->lpd.iou.uart[i]), > + &error_abort); > + } > + > + object_property_set_link(OBJECT(&s->lpd.crl), > + "usb", OBJECT(&s->lpd.iou.usb), > + &error_abort); > + > + sysbus_realize(sbd, &error_fatal); > + memory_region_add_subregion(&s->mr_ps, MM_CRL, > + sysbus_mmio_get_region(sbd, 0)); > + sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]); > +} > + > /* This takes the board allocated linear DDR memory and creates aliases > * for each split DDR range/aperture on the Versal address map. > */ > @@ -622,8 +673,6 @@ static void versal_unimp(Versal *s) > > versal_unimp_area(s, "psm", &s->mr_ps, > MM_PSM_START, MM_PSM_END - MM_PSM_START); > - versal_unimp_area(s, "crl", &s->mr_ps, > - MM_CRL, MM_CRL_SIZE); > versal_unimp_area(s, "crf", &s->mr_ps, > MM_FPD_CRF, MM_FPD_CRF_SIZE); > versal_unimp_area(s, "apu", &s->mr_ps, > @@ -681,6 +730,7 @@ static void versal_realize(DeviceState *dev, Error **errp) > versal_create_efuse(s, pic); > versal_create_pmc_iou_slcr(s, pic); > versal_create_ospi(s, pic); > + versal_create_crl(s, pic); > versal_map_ddr(s); > versal_unimp(s); > > diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h > index 155e8c4b8c..cbe8a19c10 100644 > --- a/include/hw/arm/xlnx-versal.h > +++ b/include/hw/arm/xlnx-versal.h > @@ -29,6 +29,7 @@ > #include "hw/nvram/xlnx-versal-efuse.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" > > #define TYPE_XLNX_VERSAL "xlnx-versal" > @@ -87,6 +88,8 @@ struct Versal { > qemu_or_irq irq_orgate; > XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM]; > } xram; > + > + XlnxVersalCRL crl; > } lpd; > > /* The Platform Management Controller subsystem. */ > @@ -127,6 +130,7 @@ struct Versal { > #define VERSAL_TIMER_NS_EL1_IRQ 14 > #define VERSAL_TIMER_NS_EL2_IRQ 10 > > +#define VERSAL_CRL_IRQ 10 > #define VERSAL_UART0_IRQ_0 18 > #define VERSAL_UART1_IRQ_0 19 > #define VERSAL_USB0_IRQ_0 22 > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL 2022-04-06 17:42 [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Edgar E. Iglesias ` (3 preceding siblings ...) 2022-04-06 17:43 ` [PATCH v1 4/4] hw/arm: versal: Connect the CRL Edgar E. Iglesias @ 2022-04-11 10:49 ` Peter Maydell 4 siblings, 0 replies; 14+ messages in thread From: Peter Maydell @ 2022-04-11 10:49 UTC (permalink / raw) To: Edgar E. Iglesias Cc: luc, fkonrad, edgar.iglesias, sai.pavan.boddu, frasse.iglesias, alistair, richard.henderson, qemu-devel, f4bug, francisco.iglesias, qemu-arm On Wed, 6 Apr 2022 at 18:43, Edgar E. Iglesias <edgar.iglesias@xilinx.com> wrote: > > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> > > This adds the Versal Cortex-R5s in the Real-Time Processing Unit > (RPU) subsystem. > > A model of the Clock/Reset Low-power domain (CRL) is also added > allowing runtime release of the Cortex-R5s. The RPU subsystem > is largely missing but has enough to run simple bare-metal R5 > apps. > Applied to target-arm.next for 7.1, thanks. -- PMM ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2022-04-11 10:53 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-04-06 17:42 [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Edgar E. Iglesias 2022-04-06 17:43 ` [PATCH v1 1/4] hw/arm: versal: Create an APU CPU Cluster Edgar E. Iglesias 2022-04-07 7:42 ` Frederic Konrad 2022-04-07 9:24 ` Francisco Iglesias 2022-04-06 17:43 ` [PATCH v1 2/4] hw/arm: versal: Add the Cortex-R5Fs Edgar E. Iglesias 2022-04-07 7:52 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 2022-04-06 17:43 ` [PATCH v1 3/4] hw/misc: Add a model of the Xilinx Versal CRL Edgar E. Iglesias 2022-04-07 8:22 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 2022-04-06 17:43 ` [PATCH v1 4/4] hw/arm: versal: Connect the CRL Edgar E. Iglesias 2022-04-07 8:57 ` Frederic Konrad 2022-04-07 9:25 ` Francisco Iglesias 2022-04-11 10:49 ` [PATCH v1 0/4] hw/arm: versal: Add Cortex-R5s and CRL Peter Maydell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).