Add the 'clemente-bmc' machine type, an AST2600-based BMC, modelled
from its device tree (aspeed-bmc-facebook-clemente.dts).

The board uses TMP75, TMP1075, LM75B and TMP421 temperature sensors,
PCA9535, PCA9554 and PCA9555 IO expanders, PCA9546 and PCA9548 I2C
muxes, AT24C EEPROMs and a DS1338 RTC.

Every device the Clemente device tree describes and QEMU already models
is instantiated. The remaining ones (LM5066I power monitors, MAX31790
fan controllers, MAX1363 ADCs, RAA228004 voltage regulators, the
SLB9670 SPI TPM, SSIF-BMC and MCTP) have no QEMU model and are left
documented as comments.

Signed-off-by: Emmanuel Blot <[email protected]>
---
 docs/system/arm/aspeed.rst       |   1 +
 hw/arm/aspeed_ast2600_clemente.c | 232 +++++++++++++++++++++++++++++++++++++++
 hw/arm/meson.build               |   1 +
 3 files changed, 234 insertions(+)

diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst
index bbd3d9cdf4..db0035189b 100644
--- a/docs/system/arm/aspeed.rst
+++ b/docs/system/arm/aspeed.rst
@@ -34,6 +34,7 @@ AST2600 SoC based machines :
 - ``bletchley-bmc``        Facebook Bletchley BMC
 - ``fby35-bmc``            Facebook fby35 BMC
 - ``catalina-bmc``         Facebook Catalina BMC
+- ``clemente-bmc``         Facebook Clemente BMC
 - ``sanmiguel-bmc``        Facebook SanMiguel BMC
 - ``anacapa-bmc``          Facebook Anacapa BMC
 - ``minerva-bmc``          Facebook Minerva BMC
diff --git a/hw/arm/aspeed_ast2600_clemente.c b/hw/arm/aspeed_ast2600_clemente.c
new file mode 100644
index 0000000000..bf5a13bc49
--- /dev/null
+++ b/hw/arm/aspeed_ast2600_clemente.c
@@ -0,0 +1,232 @@
+/*
+ * Facebook Clemente BMC
+ *
+ * Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Current limitations: the following devices from the device tree have no
+ * QEMU model and are therefore not emulated:
+ *   - ti,lm5066i power monitors
+ *   - maxim,max31790 fan controllers
+ *   - maxim,max1363 ADCs (leak sensors)
+ *   - renesas,raa228004 voltage regulators
+ *   - infineon,slb9670 TPM (SPI)
+ *   - ssif-bmc SSIF interface
+ *   - mctp-i2c-controller MCTP endpoints
+ */
+
+#include "qemu/osdep.h"
+#include "hw/arm/aspeed.h"
+#include "hw/arm/aspeed_soc.h"
+#include "hw/i2c/i2c_mux_pca954x.h"
+#include "hw/gpio/pca9552.h"
+#include "hw/gpio/pca9554.h"
+#include "hw/nvram/eeprom_at24c.h"
+#include "hw/rtc/ds1338.h"
+#include "hw/sensor/tmp105.h"
+#include "hw/sensor/tmp421.h"
+
+/* Clemente hardware values. */
+#define CLEMENTE_BMC_HW_STRAP1 0x00002002
+#define CLEMENTE_BMC_HW_STRAP2 0x00000800
+#define CLEMENTE_BMC_RAM_SIZE (2 * GiB)
+
+/*
+ * E1.S backplane hanging off a PCA9546 channel: an FRU EEPROM plus a
+ * second PCA9546 fronting per-drive NVMe SSD FRU EEPROMs.
+ */
+static void clemente_e1s_backplane_init(I2CBus *bus)
+{
+    /* eeprom@56 - atmel,24c128 */
+    at24c_eeprom_init(bus, 0x56, 16 * KiB);
+
+    /* i2c-mux@74 - PCA9546 */
+    I2CSlave *mux = i2c_slave_create_simple(bus, TYPE_PCA9546, 0x74);
+    /* eeprom@53 - atmel,24c02, channels 0 and 2 */
+    at24c_eeprom_init(pca954x_i2c_get_bus(mux, 0), 0x53, 256);
+    at24c_eeprom_init(pca954x_i2c_get_bus(mux, 2), 0x53, 256);
+}
+
+/*
+ * IO Mezzanine hanging off a PCA9546 channel: an I/O expander plus the
+ * mezzanine and OSFP FRU EEPROMs.
+ */
+static void clemente_io_mezz_init(I2CBus *bus, uint8_t exp_addr)
+{
+    /* gpio@20/21 - nxp,pca9535 */
+    i2c_slave_create_simple(bus, TYPE_PCA9535, exp_addr);
+    /* eeprom@50 - atmel,24c64 (mezzanine FRU) */
+    at24c_eeprom_init(bus, 0x50, 8 * KiB);
+    /* eeprom@52 - atmel,24c128 (OSFP FRU) */
+    at24c_eeprom_init(bus, 0x52, 16 * KiB);
+}
+
+static void clemente_bmc_i2c_init(AspeedMachineState *bmc)
+{
+    /* Reference: aspeed-bmc-facebook-clemente.dts */
+
+    AspeedSoCState *soc = bmc->soc;
+    I2CBus *i2c[16] = {};
+    I2CSlave *i2c_mux;
+
+    for (unsigned idx = 0; idx < ARRAY_SIZE(i2c); idx++) {
+        i2c[idx] = aspeed_i2c_get_bus(&soc->i2c, idx);
+    }
+
+    /* &i2c0 */
+    /* i2c-mux@71 (PCA9546) */
+    i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x71);
+    /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */
+    clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1));
+
+    /* i2c-mux@72 (PCA9546) */
+    i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x72);
+    /* channel 1 - IO Mezz 0 (io_expander7 @20) */
+    clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x20);
+
+    /* i2c-mux@73 (PCA9546) - channels empty */
+    i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x73);
+
+    /* i2c-mux@75 (PCA9546) */
+    i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x75);
+    /* channel 1 - HDD FRU eeprom@56 and E1.S backplane */
+    clemente_e1s_backplane_init(pca954x_i2c_get_bus(i2c_mux, 1));
+
+    /* i2c-mux@76 (PCA9546) */
+    i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x76);
+    /* channel 1 - IO Mezz 1 (io_expander8 @21) */
+    clemente_io_mezz_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x21);
+
+    /* i2c-mux@77 (PCA9546) */
+    i2c_mux = i2c_slave_create_simple(i2c[0], TYPE_PCA9546, 0x77);
+    /* channel 1 - boot drive FRU eeprom@53 */
+    at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 1), 0x53, 256);
+
+    /* &i2c1 */
+    /* power-monitor@12/14 - ti,lm5066i (no model) */
+    /* fan-controller@20/23/2c/2f - maxim,max31790 (no model) */
+    /* adc@34/35 - maxim,max1363 (no model) */
+    /* temperature-sensor@4e - ti,tmp1075 */
+    i2c_slave_create_simple(i2c[1], TYPE_TMP1075, 0x4e);
+    /* eeprom@50 - atmel,24c02 (PDB FRU) */
+    at24c_eeprom_init(i2c[1], 0x50, 256);
+    /* vrm@60/61 - renesas,raa228004 (no model) */
+    /* i2c-mux@70 (PCA9548) - interposer */
+    i2c_mux = i2c_slave_create_simple(i2c[1], TYPE_PCA9548, 0x70);
+    /* channel 5 - interposer */
+    /* temperature-sensor@4f - ti,tmp75 */
+    i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), TYPE_TMP75, 0x4f);
+    /* eeprom@54 - atmel,24c64 */
+    at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 5), 0x54, 8 * KiB);
+    /* channel 6 - io_expander5 gpio@27 - nxp,pca9554 */
+    i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6),
+                            TYPE_PCA9554, 0x27);
+    /* channel 7 - FIO */
+    /* temperature-sensor@4b - ti,tmp75 */
+    i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), TYPE_TMP75, 0x4b);
+    /* eeprom@51 - atmel,24c64 */
+    at24c_eeprom_init(pca954x_i2c_get_bus(i2c_mux, 7), 0x51, 8 * KiB);
+
+    /* &i2c2 */
+    /* gpio@20/21/27 - nxp,pca9555 */
+    i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x20);
+    i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x21);
+    i2c_slave_create_simple(i2c[2], TYPE_PCA9555, 0x27);
+    /* eeprom@50/51 - atmel,24c64 (module aux) */
+    at24c_eeprom_init(i2c[2], 0x50, 8 * KiB);
+    at24c_eeprom_init(i2c[2], 0x51, 8 * KiB);
+
+    /* &i2c3 - empty */
+    /* &i2c4 - empty */
+    /* &i2c5 - empty */
+
+    /* &i2c6 */
+    /* gpio@21 - nxp,pca9555 */
+    i2c_slave_create_simple(i2c[6], TYPE_PCA9555, 0x21);
+    /* rtc@6f - nuvoton,nct3018y */
+    i2c_slave_create_simple(i2c[6], TYPE_DS1338, 0x6f);
+
+    /* &i2c7 - empty */
+    /* &i2c8 - empty */
+
+    /* &i2c9 */
+    /* temperature-sensor@4b - national,lm75b */
+    i2c_slave_create_simple(i2c[9], TYPE_LM75B, 0x4b);
+    /* gpio@4f - nxp,pca9555 */
+    i2c_slave_create_simple(i2c[9], TYPE_PCA9555, 0x4f);
+    /* eeprom@50 - atmel,24c64 (SCM FRU) */
+    at24c_eeprom_init(i2c[9], 0x50, 8 * KiB);
+    /* eeprom@56 - atmel,24c64 (BSM FRU) */
+    at24c_eeprom_init(i2c[9], 0x56, 8 * KiB);
+
+    /* &i2c10 */
+    /* mctp@10 - mctp-i2c-controller (no model) */
+    /* temperature-sensor@1f - ti,tmp421 (OCP NIC0) */
+    i2c_slave_create_simple(i2c[10], TYPE_TMP421, 0x1f);
+    /* eeprom@50 - atmel,24c64 (OCP NIC0 FRU) */
+    at24c_eeprom_init(i2c[10], 0x50, 8 * KiB);
+
+    /* &i2c11 */
+    /* ssif-bmc@10 - ssif-bmc (no model) */
+
+    /* &i2c12 */
+    /* eeprom@50 - atmel,24c64 (HPM 1 FRU) */
+    at24c_eeprom_init(i2c[12], 0x50, 8 * KiB);
+    /* eeprom@54/55 - atmel,24c02 (CBC 2/3 FRU) */
+    at24c_eeprom_init(i2c[12], 0x54, 256);
+    at24c_eeprom_init(i2c[12], 0x55, 256);
+
+    /* &i2c13 */
+    /* eeprom@50 - atmel,24c64 (HPM FRU) */
+    at24c_eeprom_init(i2c[13], 0x50, 8 * KiB);
+    /* eeprom@54/55 - atmel,24c02 (CBC 0/1 FRU) */
+    at24c_eeprom_init(i2c[13], 0x54, 256);
+    at24c_eeprom_init(i2c[13], 0x55, 256);
+    /* eeprom@57 - atmel,24c02 (HMC FRU) */
+    at24c_eeprom_init(i2c[13], 0x57, 256);
+
+    /* &i2c14 */
+    /* gpio@10/11/12/13/14 - nxp,pca9555 (PDB CPLD) */
+    i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x10);
+    i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x11);
+    i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x12);
+    i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x13);
+    i2c_slave_create_simple(i2c[14], TYPE_PCA9555, 0x14);
+
+    /* &i2c15 */
+    /* mctp@10 - mctp-i2c-controller (no model) */
+    /* temperature-sensor@1f - ti,tmp421 (OCP NIC1) */
+    i2c_slave_create_simple(i2c[15], TYPE_TMP421, 0x1f);
+    /* eeprom@52 - atmel,24c64 (OCP NIC1 FRU) */
+    at24c_eeprom_init(i2c[15], 0x52, 8 * KiB);
+}
+
+static void aspeed_machine_clemente_class_init(ObjectClass *oc,
+                                               const void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+    AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
+
+    mc->desc       = "Facebook Clemente BMC (Cortex-A7)";
+    amc->soc_name  = "ast2600-a3";
+    amc->hw_strap1 = CLEMENTE_BMC_HW_STRAP1;
+    amc->hw_strap2 = CLEMENTE_BMC_HW_STRAP2;
+    amc->fmc_model = "mx66l1g45g";
+    amc->spi_model = NULL;
+    amc->num_cs    = 2;
+    amc->macs_mask = ASPEED_MAC2_ON | ASPEED_MAC3_ON;
+    amc->i2c_init  = clemente_bmc_i2c_init;
+    mc->default_ram_size = CLEMENTE_BMC_RAM_SIZE;
+    aspeed_machine_class_init_cpus_defaults(mc);
+}
+
+static const TypeInfo aspeed_ast2600_clemente_types[] = {
+    {
+        .name          = MACHINE_TYPE_NAME("clemente-bmc"),
+        .parent        = TYPE_ASPEED_MACHINE,
+        .class_init    = aspeed_machine_clemente_class_init,
+    }
+};
+
+DEFINE_TYPES(aspeed_ast2600_clemente_types)
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index a9e8270b85..4189de2aaa 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -59,6 +59,7 @@ arm_common_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
   'aspeed_ast2600_anacapa.c',
   'aspeed_ast2600_bletchley.c',
   'aspeed_ast2600_catalina.c',
+  'aspeed_ast2600_clemente.c',
   'aspeed_ast2600_evb.c',
   'aspeed_ast2600_fby35.c',
   'aspeed_ast2600_fuji.c',

-- 
2.53.0-Meta


Reply via email to