Instantiate both E2000 MCI controllers at their low-peripheral
addresses, route their interrupts to the GIC, and create an SD
card on each exported bus. Map legacy IF_SD backends by controller
index so firmware and Linux use the same board-visible media topology.

Keep the broad unimplemented aperture underneath the concrete
devices and make SD the machine's default block interface.

Signed-off-by: Bin Meng <[email protected]>
---

 hw/arm/Kconfig         |  1 +
 hw/arm/phytium_e2000.c | 65 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 99a5799b22..9358a47b8a 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -136,6 +136,7 @@ config PHYTIUM_E2000
     select PCI_EXPRESS
     select PCI_EXPRESS_GENERIC_BRIDGE
     select PL011
+    select SD
     select UNIMP
 
 config REALVIEW
diff --git a/hw/arm/phytium_e2000.c b/hw/arm/phytium_e2000.c
index aac798aa07..88307184e9 100644
--- a/hw/arm/phytium_e2000.c
+++ b/hw/arm/phytium_e2000.c
@@ -28,6 +28,8 @@
 #include "hw/misc/unimp.h"
 #include "hw/pci/pci.h"
 #include "hw/pci-host/gpex.h"
+#include "hw/sd/phytium_e2000_mci.h"
+#include "hw/sd/sd.h"
 #include "qobject/qlist.h"
 #include "qom/object.h"
 #include "target/arm/cpu.h"
@@ -40,12 +42,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(PhytiumE2000State, PHYTIUM_PI)
 #define PHYTIUM_E2000_NUM_CPUS        4
 #define PHYTIUM_E2000_NUM_IRQS        256
 
+#define PHYTIUM_E2000_NUM_MCIS        2
 #define PHYTIUM_E2000_NUM_UARTS       7
 
 #define PHYTIUM_E2000_GTIMER_HZ       50000000
 
 enum {
     PHYTIUM_E2000_LOW_PERIPH,
+    PHYTIUM_E2000_MCI0,
+    PHYTIUM_E2000_MCI1,
     PHYTIUM_E2000_UART0,
     PHYTIUM_E2000_UART1,
     PHYTIUM_E2000_UART2,
@@ -73,6 +78,7 @@ struct PhytiumE2000State {
     MachineState parent;
     struct arm_boot_info bootinfo;
     DeviceState *gic;
+    PhytiumE2000MciState *mci[PHYTIUM_E2000_NUM_MCIS];
     MemoryRegion ram_low;
     MemoryRegion ram_high;
 };
@@ -84,6 +90,8 @@ struct PhytiumE2000State {
  */
 static const MemMapEntry phytium_e2000_memmap[] = {
     [PHYTIUM_E2000_LOW_PERIPH] =     { 0x28000000, 0x00100000 },
+    [PHYTIUM_E2000_MCI0] =           { 0x28000000, 0x00001000 },
+    [PHYTIUM_E2000_MCI1] =           { 0x28001000, 0x00001000 },
     [PHYTIUM_E2000_UART0] =          { 0x2800c000, 0x00001000 },
     [PHYTIUM_E2000_UART1] =          { 0x2800d000, 0x00001000 },
     [PHYTIUM_E2000_UART2] =          { 0x2800e000, 0x00001000 },
@@ -107,6 +115,11 @@ static const MemMapEntry phytium_e2000_memmap[] = {
     [PHYTIUM_E2000_RAM_HIGH] =       { 0x2000000000ULL, 0x180000000ULL },
 };
 
+static const int phytium_e2000_mci_irqmap[] = {
+    [0] = 72,
+    [1] = 73,
+};
+
 static const int phytium_e2000_uart_irqmap[] = {
     [0] = 83,
     [1] = 84,
@@ -324,6 +337,55 @@ static void phytium_e2000_create_pcie(PhytiumE2000State *s)
     }
 }
 
+static BlockBackend *phytium_e2000_sd_blk(int index)
+{
+    DriveInfo *dinfo = drive_get(IF_SD, 0, index);
+
+    return dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+}
+
+static void phytium_e2000_attach_sd_card(DwMciState *mci, int index)
+{
+    BlockBackend *blk = phytium_e2000_sd_blk(index);
+    BusState *bus = BUS(dw_mci_get_bus(mci));
+    DeviceState *card;
+
+    /*
+     * Always instantiate the socket-level card object. A missing backend then
+     * behaves as an empty slot, while if=sd,index=N gives firmware a real SD
+     * card on the matching physical MCI controller.
+     */
+    card = qdev_new(TYPE_SD_CARD);
+    qdev_prop_set_drive_err(card, "drive", blk, &error_fatal);
+    qdev_realize_and_unref(card, bus, &error_fatal);
+}
+
+static void phytium_e2000_create_mci(PhytiumE2000State *s, int index)
+{
+    PhytiumE2000MciState *mci =
+        PHYTIUM_E2000_MCI(qdev_new(TYPE_PHYTIUM_E2000_MCI));
+    DeviceState *dev = DEVICE(mci);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    MemoryRegion *iomem;
+    int map_idx = PHYTIUM_E2000_MCI0 + index;
+    g_autofree char *name = g_strdup_printf("mci%d", index);
+
+    /*
+     * MCI0 and MCI1 occupy the first two pages of the broad low-peripheral
+     * placeholder. Use a higher overlap priority so real command and data
+     * accesses reach the controller model.
+     */
+    s->mci[index] = mci;
+    object_property_add_child(OBJECT(s), name, OBJECT(mci));
+    sysbus_realize_and_unref(sbd, &error_fatal);
+    iomem = sysbus_mmio_get_region(sbd, 0);
+    memory_region_add_subregion_overlap(
+        get_system_memory(), phytium_e2000_memmap[map_idx].base, iomem, 1);
+    sysbus_connect_irq(sbd, 0,
+        qdev_get_gpio_in(s->gic, phytium_e2000_mci_irqmap[index]));
+    phytium_e2000_attach_sd_card(DW_MCI(mci), index);
+}
+
 static void phytium_e2000_create_unimplemented(void)
 {
     /*
@@ -443,6 +505,9 @@ static void phytium_pi_init(MachineState *ms)
     phytium_e2000_create_cpus(s);
     phytium_e2000_create_gic(s);
 
+    for (i = 0; i < PHYTIUM_E2000_NUM_MCIS; i++) {
+        phytium_e2000_create_mci(s, i);
+    }
     for (i = 0; i < PHYTIUM_E2000_NUM_UARTS; i++) {
         phytium_e2000_create_uart(s, i);
     }
-- 
2.53.0


Reply via email to