Hi Kuan-Jui,

On 18/6/26 12:12, Kuan-Jui Chiu wrote:
Enable SD host controller into Axiado AX3000 SoC to load kernel and rootfs
from eMMC.

Signed-off-by: Kuan-Jui Chiu <[email protected]>
Reviewed-by: Peter Maydell <[email protected]>
---
  hw/arm/Kconfig              |  1 +
  hw/arm/ax3000-soc.c         | 18 ++++++++++++++++++
  include/hw/arm/ax3000-soc.h |  7 +++++++
  3 files changed, 26 insertions(+)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 866e4b14e6f..13c0b44a180 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -724,4 +724,5 @@ config AXIADO_SOC
      select ARM_GIC
      select CADENCE # UART
      select AXIADO_CLK
+    select AXIADO_SDHCI
      select UNIMP
diff --git a/hw/arm/ax3000-soc.c b/hw/arm/ax3000-soc.c
index 9a01d23bcc6..159385cf913 100644
--- a/hw/arm/ax3000-soc.c
+++ b/hw/arm/ax3000-soc.c
@@ -35,6 +35,7 @@ static void ax3000_init(Object *obj)
      }
object_initialize_child(obj, "clk", &s->ax3000_clk, TYPE_AX3000_CLK);
+    object_initialize_child(obj, "sdhci0", &s->sdhci0, TYPE_AXIADO_SDHCI);
  }
static void ax3000_realize(DeviceState *dev, Error **errp)
@@ -165,6 +166,23 @@ static void ax3000_realize(DeviceState *dev, Error **errp)
          return;
      }
      sysbus_mmio_map(SYS_BUS_DEVICE(&s->ax3000_clk), 0, AX3000_PLL_BASE);
+
+    /* SDHCI */
+    sdhci0_sbd = SYS_BUS_DEVICE(&s->sdhci0);
+    if (!sysbus_realize(sdhci0_sbd, errp)) {
+        return;
+    }
+
+    sysbus_mmio_map(sdhci0_sbd, 0, AX3000_SDHCI0_BASE);
+    sysbus_mmio_map(sdhci0_sbd, 1, AX3000_EMMC_PHY_BASE);
+    sysbus_connect_irq(sdhci0_sbd, 0,
+                       qdev_get_gpio_in(gic_dev, AX3000_SDHCI0_IRQ));

So there is no link between the SDHCI and the PHY. Thus no need for a
particular AXIADO_SDHCI, simply instantiate a generic SDHCI here, and
register the MMIO region for the PHY.

in ax3000_init():

    object_initialize_child(obj, "sdhci[0]", &s->sdhci[0],
                            TYPE_SYSBUS_SDHCI);

and in ax3000_realize():

    object_property_set_uint(OBJECT(&s->sdhci[0]), "sd-spec-version", 3,
                             &error_abort);
    object_property_set_uint(OBJECT(&s->sdhci[0]), "capareg",
                             0x216737eed0b0, &error_abort);

    if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci[0]), errp)) {
        return;
    }
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[0]), 0,
                       qdev_get_gpio_in(gic_dev, AX3000_SDHCI0_IRQ));
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[0]),
                    0, AX3000_SDHCI0_BASE);

Then you simply map the state-less eMMC PHY region:

    memory_region_init_io(&s->emmc_phy, OBJECT(s), &emmc_phy_ops, s,
                          "axiado.emmc-phy", 0x1000);
    memory_region_add_subregion(get_system_memory(),
                                AX3000_EMMC_PHY_BASE, &s->emmc_phy);

+
+    card = qdev_new(TYPE_SD_CARD);
+    qdev_prop_set_drive_err(card, "drive",
+                            blk_by_legacy_dinfo((drive_get(IF_SD, 0, 0))),
+                            &error_fatal);
+    qdev_realize_and_unref(card, s->sdhci0.sd_bus, &error_fatal);
  }
static void ax3000_class_init(ObjectClass *oc, const void *data)
diff --git a/include/hw/arm/ax3000-soc.h b/include/hw/arm/ax3000-soc.h
index 329aa4e7698..52b47aa8294 100644
--- a/include/hw/arm/ax3000-soc.h
+++ b/include/hw/arm/ax3000-soc.h
@@ -13,6 +13,7 @@
  #include "hw/intc/arm_gicv3_common.h"
  #include "hw/char/cadence_uart.h"
  #include "hw/misc/axiado_clk.h"
+#include "hw/sd/axiado_sdhci.h"
  #include "hw/core/sysbus.h"
  #include "qemu/units.h"
@@ -34,6 +35,9 @@ OBJECT_DECLARE_TYPE(Ax3000SoCState, Ax3000SoCClass, AX3000_SOC)
  #define AX3000_UART2_BASE       0x80620000
  #define AX3000_UART3_BASE       0x80520800
+#define AX3000_SDHCI0_BASE 0x86000000
+#define AX3000_EMMC_PHY_BASE    0x80801C00
+
  #define AX3000_TIMER_CTRL       0x8A020000
  #define AX3000_PLL_BASE         0x80000000
@@ -52,6 +56,7 @@ typedef struct Ax3000SoCState {
      MemoryRegion        dram[AX3000_NUM_BANKS];
      Ax3000ClkState      ax3000_clk;
      CadenceUARTState    uart[AX3000_NUM_UARTS];
+    AxiadoSDHCIState    sdhci0;
  } Ax3000SoCState;
typedef struct Ax3000SoCClass {
@@ -65,6 +70,8 @@ enum Ax3000Irqs {
      AX3000_UART1_IRQ    = 113,
      AX3000_UART2_IRQ    = 114,
      AX3000_UART3_IRQ    = 170,
+
+    AX3000_SDHCI0_IRQ   = 123,
  };
#endif /* AXIADO_AX3000_H */


Reply via email to