QEMU-Arm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Bin Meng <bin.meng@processmission.com>
To: QEMU <qemu-devel@nongnu.org>
Cc: Peter Maydell <peter.maydell@linaro.org>, qemu-arm@nongnu.org
Subject: [PATCH v2 15/32] hw/arm: phytium: Integrate the Phytium E2000 PBR
Date: Tue,  8 Sep 2026 18:41:24 +0800	[thread overview]
Message-ID: <20260908104159.1621764-16-bin.meng@processmission.com> (raw)
In-Reply-To: <20260908104159.1621764-1-bin.meng@processmission.com>

Instantiate PBR in the E2000 SoC, map its status and boot memories,
provide the heterogeneous MPIDR topology, and connect all SoC-owned
CPU objects for reset-time handoff.

Have the Phytium Pi machine select SD0 and pass its board backend into
the SoC. Explicitly reject unsupported -bios and pflash interfaces.

Signed-off-by: Bin Meng <bin.meng@processmission.com>

---

Changes in v2:
- Connect PBR to the SoC-owned CPU children
- Let the machine configure the SoC-owned PBR backend

 include/hw/arm/phytium_e2000.h | 11 +++++
 hw/arm/phytium_e2000.c         | 74 +++++++++++++++++++++++++++++++++-
 hw/arm/phytium_e2000_machine.c | 26 ++++++++++--
 3 files changed, 107 insertions(+), 4 deletions(-)

diff --git a/include/hw/arm/phytium_e2000.h b/include/hw/arm/phytium_e2000.h
index 92b39129ba..6199bb7b5c 100644
--- a/include/hw/arm/phytium_e2000.h
+++ b/include/hw/arm/phytium_e2000.h
@@ -14,6 +14,7 @@
 
 #include "hw/arm/boot.h"
 #include "hw/core/sysbus.h"
+#include "hw/misc/phytium_e2000_pbr.h"
 #include "hw/net/cadence_gem.h"
 #include "hw/sd/phytium_e2000_mci.h"
 #include "hw/ssi/phytium_qspi.h"
@@ -67,14 +68,23 @@ struct PhytiumE2000SoCState {
 
     DeviceState *gic;
     PhytiumE2000QSPIState *qspi;
+    PhytiumE2000PBRState *pbr;
     PhytiumE2000MciState *mci[PHYTIUM_E2000_NUM_MCIS];
     CadenceGEMState *gem[PHYTIUM_E2000_NUM_GEMS];
     ARMCPU cpu[PHYTIUM_E2000_NUM_CPUS];
     MemoryRegion scp_sram;
+
+    const char *pbr_boot_mode;
+    BlockBackend *boot_blk;
+    uint64_t ram_size;
     unsigned int num_cpus;
+    bool firmware_loaded;
 };
 
 void phytium_e2000_soc_configure(PhytiumE2000SoCState *s,
+                                 const char *pbr_boot_mode,
+                                 BlockBackend *boot_blk,
+                                 uint64_t ram_size,
                                  unsigned int num_cpus);
 void phytium_e2000_soc_cpu_topology(unsigned int index,
                                     uint64_t *mp_affinity,
@@ -82,6 +92,7 @@ void phytium_e2000_soc_cpu_topology(unsigned int index,
                                     int64_t *core_id);
 ARMCPU *phytium_e2000_soc_cpu(PhytiumE2000SoCState *s,
                               unsigned int index);
+bool phytium_e2000_soc_firmware_loaded(PhytiumE2000SoCState *s);
 void phytium_e2000_soc_attach_sd_card(PhytiumE2000SoCState *s,
                                       unsigned int index,
                                       BlockBackend *blk);
diff --git a/hw/arm/phytium_e2000.c b/hw/arm/phytium_e2000.c
index 3e30d112f7..6818d081b3 100644
--- a/hw/arm/phytium_e2000.c
+++ b/hw/arm/phytium_e2000.c
@@ -23,6 +23,7 @@
 #include "hw/intc/arm_gicv3_its_common.h"
 #include "hw/misc/phytium_e2000_ddr.h"
 #include "hw/misc/phytium_e2000_mhu.h"
+#include "hw/misc/phytium_e2000_pbr.h"
 #include "hw/misc/unimp.h"
 #include "hw/net/cadence_gem.h"
 #include "hw/pci/pci.h"
@@ -224,6 +225,17 @@ static void phytium_e2000_configure_cpu(ARMCPU *cpu,
     }
 }
 
+static uint64_t phytium_e2000_cpu_mp_affinity(unsigned int cpu)
+{
+    /*
+     * E2000Q exposes one core in each of the first two clusters and two cores
+     * in the third cluster. Firmware stores these MPIDRs in its parameter
+     * tables, so a linear CPU index is not a valid affinity value.
+     */
+    g_assert(cpu < ARRAY_SIZE(phytium_e2000_cpu_config));
+    return phytium_e2000_cpu_config[cpu].mp_affinity;
+}
+
 static void phytium_e2000_create_its(PhytiumE2000SoCState *s)
 {
     DeviceState *dev = qdev_new(its_class_name());
@@ -483,6 +495,39 @@ static void phytium_e2000_create_qspi(PhytiumE2000SoCState *s)
         phytium_e2000_memmap[PHYTIUM_E2000_QSPI_DIRECT].base, 2);
 }
 
+static bool phytium_e2000_create_pbr(PhytiumE2000SoCState *s)
+{
+    DeviceState *dev = qdev_new(TYPE_PHYTIUM_E2000_PBR);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    uint64_t cpu_mpidrs[PHYTIUM_E2000_NUM_CPUS];
+    int i;
+
+    for (i = 0; i < s->num_cpus; i++) {
+        cpu_mpidrs[i] = phytium_e2000_cpu_mp_affinity(i);
+    }
+
+    qdev_prop_set_string(dev, "boot-mode", s->pbr_boot_mode);
+    phytium_e2000_pbr_configure(PHYTIUM_E2000_PBR(dev), s->boot_blk,
+                                phytium_e2000_memmap[PHYTIUM_E2000_RAM].base,
+                                s->ram_size, cpu_mpidrs, s->num_cpus);
+
+    /*
+     * PBR owns the status snapshot and both boot memories. The status block
+     * overlaps the broad board-control placeholder and therefore needs the
+     * higher mapping priority used by the previous status-only device.
+     */
+    object_property_add_child(OBJECT(s), "pbr", OBJECT(dev));
+    sysbus_realize_and_unref(sbd, &error_fatal);
+    sysbus_mmio_map_overlap(sbd, 0, PHYTIUM_E2000_PBR_STATUS_BASE, 2);
+    sysbus_mmio_map(sbd, 1,
+                    phytium_e2000_memmap[PHYTIUM_E2000_BOOT_SRAM].base);
+    sysbus_mmio_map(sbd, 2,
+                    phytium_e2000_memmap[PHYTIUM_E2000_BOOT_IACC].base);
+    s->pbr = PHYTIUM_E2000_PBR(dev);
+
+    return phytium_e2000_pbr_firmware_loaded(s->pbr);
+}
+
 static void phytium_e2000_create_ddr_status(PhytiumE2000SoCState *s)
 {
     DeviceState *dev = qdev_new(TYPE_PHYTIUM_E2000_DDR);
@@ -572,23 +617,40 @@ static void phytium_e2000_create_cpus(PhytiumE2000SoCState *s)
                                 config->mp_affinity, &error_abort);
         object_property_set_int(cpuobj, "cntfrq", PHYTIUM_E2000_GTIMER_HZ,
                                 &error_abort);
-        if (object_property_find(cpuobj, "has_el3")) {
+        if (!s->firmware_loaded && object_property_find(cpuobj, "has_el3")) {
             /*
              * The generic-loader U-Boot path starts after the EL3 firmware
              * stages that normally provide the Phytium SMC services.
              */
             object_property_set_bool(cpuobj, "has_el3", false, &error_abort);
         }
+        /*
+         * PBR releases only the primary MPIDR named in the firmware parameter
+         * header. Secondary CPUs remain powered off for later firmware or
+         * PSCI bring-up.
+         */
+        if (s->firmware_loaded &&
+            i != phytium_e2000_pbr_primary_cpu(s->pbr)) {
+            object_property_set_bool(cpuobj, "start-powered-off", true,
+                                     &error_abort);
+        }
         object_property_set_link(cpuobj, "memory", OBJECT(get_system_memory()),
                                  &error_abort);
         cs->cpu_index = i;
         qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
+        phytium_e2000_pbr_connect_cpu(s->pbr, i, cs);
     }
 }
 
 void phytium_e2000_soc_configure(PhytiumE2000SoCState *s,
+                                 const char *pbr_boot_mode,
+                                 BlockBackend *boot_blk,
+                                 uint64_t ram_size,
                                  unsigned int num_cpus)
 {
+    s->pbr_boot_mode = pbr_boot_mode;
+    s->boot_blk = boot_blk;
+    s->ram_size = ram_size;
     s->num_cpus = num_cpus;
 }
 
@@ -613,6 +675,11 @@ ARMCPU *phytium_e2000_soc_cpu(PhytiumE2000SoCState *s,
     return &s->cpu[index];
 }
 
+bool phytium_e2000_soc_firmware_loaded(PhytiumE2000SoCState *s)
+{
+    return s->firmware_loaded;
+}
+
 void phytium_e2000_soc_attach_sd_card(PhytiumE2000SoCState *s,
                                       unsigned int index,
                                       BlockBackend *blk)
@@ -643,9 +710,14 @@ static void phytium_e2000_soc_realize(DeviceState *dev, Error **errp)
                    PHYTIUM_E2000_NUM_CPUS);
         return;
     }
+    if (!s->pbr_boot_mode) {
+        error_setg(errp, "E2000 SoC boot mode is not configured");
+        return;
+    }
 
     phytium_e2000_create_unimplemented(s);
     phytium_e2000_create_qspi(s);
+    s->firmware_loaded = phytium_e2000_create_pbr(s);
     phytium_e2000_create_cpus(s);
     phytium_e2000_create_gic(s);
 
diff --git a/hw/arm/phytium_e2000_machine.c b/hw/arm/phytium_e2000_machine.c
index 7397c58a78..3ab82c5fff 100644
--- a/hw/arm/phytium_e2000_machine.c
+++ b/hw/arm/phytium_e2000_machine.c
@@ -53,6 +53,15 @@ static void phytium_e2000_attach_sd_cards(PhytiumPiMachineState *s)
     }
 }
 
+static void phytium_e2000_reject_legacy_firmware(MachineState *ms)
+{
+    if (ms->firmware || drive_get(IF_PFLASH, 0, 0)) {
+        error_report("phytium-pi: -bios and pflash firmware are not "
+                     "supported; use an if=sd,index=0 image");
+        exit(1);
+    }
+}
+
 static void phytium_e2000_create_ram(PhytiumPiMachineState *s)
 {
     MachineState *ms = MACHINE(s);
@@ -83,6 +92,8 @@ static void phytium_e2000_create_ram(PhytiumPiMachineState *s)
 static void phytium_pi_init(MachineState *ms)
 {
     PhytiumPiMachineState *s = PHYTIUM_PI(ms);
+    BlockBackend *boot_blk;
+    bool firmware_loaded;
 
     /*
      * KVM cannot provide the heterogeneous FTC CPU configuration applied to
@@ -107,20 +118,25 @@ static void phytium_pi_init(MachineState *ms)
         exit(1);
     }
 
+    phytium_e2000_reject_legacy_firmware(ms);
     phytium_e2000_create_ram(s);
+    boot_blk = ms->kernel_filename ? NULL : phytium_e2000_sd_blk(0);
 
     object_initialize_child(OBJECT(s), "soc", &s->soc,
                             TYPE_PHYTIUM_E2000_SOC);
-    phytium_e2000_soc_configure(&s->soc, ms->smp.cpus);
+    phytium_e2000_soc_configure(&s->soc,
+                                PHYTIUM_E2000_PBR_BOOT_MODE_SD0,
+                                boot_blk, ms->ram_size, ms->smp.cpus);
     sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);
     phytium_e2000_attach_sd_cards(s);
 
+    firmware_loaded = phytium_e2000_soc_firmware_loaded(&s->soc);
     s->bootinfo.ram_size = ms->ram_size;
     s->bootinfo.board_id = -1;
     s->bootinfo.loader_start =
         phytium_e2000_memmap[PHYTIUM_E2000_RAM].base;
     s->bootinfo.psci_conduit = QEMU_PSCI_CONDUIT_SMC;
-    s->bootinfo.firmware_loaded = false;
+    s->bootinfo.firmware_loaded = firmware_loaded;
     arm_load_kernel(phytium_e2000_soc_cpu(&s->soc, 0), ms, &s->bootinfo);
 }
 
@@ -167,7 +183,11 @@ static void phytium_pi_class_init(ObjectClass *oc, const void *data)
     mc->valid_cpu_types = valid_cpu_types;
     mc->max_cpus = PHYTIUM_E2000_NUM_CPUS;
     mc->default_cpus = PHYTIUM_E2000_NUM_CPUS;
-    mc->default_ram_size = 1 * GiB;
+    /*
+     * PBF/BL1 relocates to 0xf8c40000, which is outside a 1 GiB RAM window
+     * starting at 0x80000000. Two GiB is the minimum useful firmware default.
+     */
+    mc->default_ram_size = 2 * GiB;
     mc->default_ram_id = "phytium-e2000.ram";
     mc->minimum_page_bits = 12;
     mc->block_default_type = IF_SD;
-- 
2.53.0



  parent reply	other threads:[~2026-09-08 10:46 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-08 10:41 [PATCH v2 00/32] hw/arm: Add Phytium E2000Q SoC and board support Bin Meng
2026-09-08 10:41 ` [PATCH v2 01/32] hw/arm: Add Phytium E2000 SoC and Phytium Pi machine Bin Meng
2026-09-08 10:41 ` [PATCH v2 02/32] hw/arm: phytium: Add Phytium E2000 PCIe host Bin Meng
2026-09-08 10:41 ` [PATCH v2 04/32] hw/sd: Add Phytium E2000 MCI controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 05/32] hw/arm: phytium: Connect Phytium E2000 MCI controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 07/32] hw/arm: phytium: Connect Phytium E2000 GEM controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 08/32] hw/misc: Add Phytium E2000 DDR controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 09/32] hw/arm: phytium: Connect the " Bin Meng
2026-09-08 10:41 ` [PATCH v2 10/32] hw/misc: Add Phytium E2000 MHU doorbell Bin Meng
2026-09-08 10:41 ` [PATCH v2 11/32] hw/arm: phytium: Connect the Phytium E2000 MHU Bin Meng
2026-09-08 10:41 ` [PATCH v2 12/32] hw/ssi: Add Phytium E2000 QSPI controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 13/32] hw/arm: phytium: Connect the " Bin Meng
2026-09-08 10:41 ` [PATCH v2 14/32] hw/misc: Add Phytium E2000 PBR model Bin Meng
2026-09-08 10:41 ` Bin Meng [this message]
2026-09-08 10:41 ` [PATCH v2 16/32] hw/arm: phytium: Add Phytium E2000 control region placeholders Bin Meng
2026-09-08 10:41 ` [PATCH v2 17/32] hw/misc: Support Phytium E2000 SCMI CPU power control Bin Meng
2026-09-08 10:41 ` [PATCH v2 18/32] hw/arm: phytium: Select the Phytium E2000 PBR boot medium Bin Meng
2026-09-08 10:41 ` [PATCH v2 19/32] hw/arm: phytium: Connect the Phytium E2000 I2C controller Bin Meng
2026-09-08 10:41 ` [PATCH v2 20/32] hw/arm: phytium: Add Phytium E2000 xHCI controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 21/32] hw/misc: Model the Phytium E2000 random generator Bin Meng
2026-09-08 10:41 ` [PATCH v2 22/32] hw/arm: phytium: Connect " Bin Meng
2026-09-08 10:41 ` [PATCH v2 23/32] hw/arm: phytium: Support Phytium E2000 direct Linux boot Bin Meng
2026-09-08 10:41 ` [PATCH v2 24/32] hw/arm: phytium: Add Phytium E2000Q COMe machine Bin Meng
2026-09-08 10:41 ` [PATCH v2 26/32] hw/arm: phytium: Connect the Phytium E2000Q COMe QSPI flash Bin Meng
2026-09-08 10:41 ` [PATCH v2 27/32] hw/arm: phytium: Add Phytium E2000 AHCI controllers Bin Meng
2026-09-08 10:41 ` [PATCH v2 28/32] hw/arm: Add Phytium E2000 Linux SCMI channel Bin Meng
2026-09-08 10:41 ` [PATCH v2 29/32] hw/arm: phytium: Connect the Phytium E2000 SMMUv3 Bin Meng
2026-09-08 10:41 ` [PATCH v2 30/32] docs/system/arm: Document Phytium E2000 machines Bin Meng
2026-09-08 10:41 ` [PATCH v2 31/32] tests/functional/aarch64: Add Phytium Pi boot tests Bin Meng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260908104159.1621764-16-bin.meng@processmission.com \
    --to=bin.meng@processmission.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox