Replace the two unimplemented K230 SD controller regions with K230 SDHCI
devices.  Map them at 0x91580000 and 0x91581000 and connect their
interrupts to PLIC inputs 142 and 144 respectively.

Create an SD card on each controller when a corresponding
-drive if=sd,index=N backend is provided.

Update the K230 machine documentation to list the controllers as
supported and remove the instructions that disabled the SDHCI device
tree nodes before booting Linux.

Signed-off-by: Xin Xie <[email protected]>
---
 docs/system/riscv/k230.rst |  6 ++----
 hw/riscv/Kconfig           |  1 +
 hw/riscv/k230.c            | 34 ++++++++++++++++++++++++++++++----
 include/hw/riscv/k230.h    |  4 ++++
 4 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/docs/system/riscv/k230.rst b/docs/system/riscv/k230.rst
index cea8202e55..6e8286a0df 100644
--- a/docs/system/riscv/k230.rst
+++ b/docs/system/riscv/k230.rst
@@ -20,6 +20,7 @@ The ``k230`` machine supports the following devices:
 * Platform-Level Interrupt Controller (PLIC)
 * 2 K230 Watchdog Timer
 * 5 UART
+* 2 SDHCI controllers
 
 Boot options
 ------------
@@ -100,14 +101,11 @@ Press Enter to stop autoboot. At the U-Boot prompt, run 
these commands:
    K230# fdt resize 8192
    K230# fdt set /chosen linux,initrd-start <0x0 0xa100000>
    K230# fdt set /chosen linux,initrd-end <0x0 ${INITRD_END}>
-   K230# fdt set /soc/sdhci0@91580000 status disabled
-   K230# fdt set /soc/sdhci1@91581000 status disabled
    K230# bootm 0xc100000 - 0xa000000
 
 Use ``setenv`` so ``bootm`` writes the kernel command line into
 ``/chosen/bootargs``. The ``fdt`` commands select the loaded DTB, add space for
-edits, describe the initrd range in ``/chosen``, and disable SDHCI nodes 
because
-this machine does not emulate those controllers yet. Replace ``${INITRD_END}``
+edits, and describe the initrd range in ``/chosen``. Replace ``${INITRD_END}``
 with the host-calculated value above when typing the command. ``cma=0`` avoids
 the SDK kernel reserving too much of the little-core memory window for 
initramfs
 boot.
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index de37c08cae..e4a0616c16 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -162,3 +162,4 @@ config K230
     select SERIAL_MM
     select UNIMP
     select K230_WDT
+    select K230_SDHCI
diff --git a/hw/riscv/k230.c b/hw/riscv/k230.c
index 656f28190c..7ea69084ae 100644
--- a/hw/riscv/k230.c
+++ b/hw/riscv/k230.c
@@ -110,6 +110,8 @@ static void k230_soc_init(Object *obj)
     object_initialize_child(obj, "c908-cpu", cpu0, TYPE_RISCV_HART_ARRAY);
     object_initialize_child(obj, "k230-wdt0", &s->wdt[0], TYPE_K230_WDT);
     object_initialize_child(obj, "k230-wdt1", &s->wdt[1], TYPE_K230_WDT);
+    object_initialize_child(obj, "sdhci0", &s->sdhci[0], TYPE_K230_SDHCI);
+    object_initialize_child(obj, "sdhci1", &s->sdhci[1], TYPE_K230_SDHCI);
 
     qdev_prop_set_uint32(DEVICE(cpu0), "hartid-base", 0);
     qdev_prop_set_string(DEVICE(cpu0), "cpu-type", TYPE_RISCV_CPU_THEAD_C908);
@@ -343,11 +345,21 @@ static void k230_soc_realize(DeviceState *dev, Error 
**errp)
     create_unimplemented_device("usb1", memmap[K230_DEV_USB1].base,
                                 memmap[K230_DEV_USB1].size);
 
-    create_unimplemented_device("sd0", memmap[K230_DEV_SD0].base,
-                                memmap[K230_DEV_SD0].size);
+    for (int i = 0; i < 2; i++) {
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->sdhci[i]), errp)) {
+            return;
+        }
+    }
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[0]), 0,
+                    memmap[K230_DEV_SD0].base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[0]), 0,
+                       qdev_get_gpio_in(s->c908_plic, K230_SD0_IRQ));
 
-    create_unimplemented_device("sd1", memmap[K230_DEV_SD1].base,
-                                memmap[K230_DEV_SD1].size);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[1]), 0,
+                    memmap[K230_DEV_SD1].base);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[1]), 0,
+                       qdev_get_gpio_in(s->c908_plic, K230_SD1_IRQ));
 
     create_unimplemented_device("qspi0", memmap[K230_DEV_QSPI0].base,
                                 memmap[K230_DEV_QSPI0].size);
@@ -490,6 +502,20 @@ static void k230_machine_init(MachineState *machine)
                             TYPE_RISCV_K230_SOC);
     qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
 
+    for (int i = 0; i < 2; i++) {
+        DriveInfo *dinfo = drive_get(IF_SD, 0, i);
+        DeviceState *card;
+
+        if (!dinfo) {
+            continue;
+        }
+
+        card = qdev_new(TYPE_SD_CARD);
+        qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+                                &error_fatal);
+        qdev_realize_and_unref(card, s->soc.sdhci[i].bus, &error_fatal);
+    }
+
     /* Data Memory */
     memory_region_add_subregion(sys_mem, memmap[K230_DEV_DDRC].base,
                                 machine->ram);
diff --git a/include/hw/riscv/k230.h b/include/hw/riscv/k230.h
index 592e1c26bf..8e73366e56 100644
--- a/include/hw/riscv/k230.h
+++ b/include/hw/riscv/k230.h
@@ -18,6 +18,7 @@
 #include "hw/core/boards.h"
 #include "hw/riscv/riscv_hart.h"
 #include "hw/watchdog/k230_wdt.h"
+#include "hw/sd/k230_sdhci.h"
 
 #define C908_CPU_HARTID   (0)
 
@@ -33,6 +34,7 @@ typedef struct K230SoCState {
     RISCVHartArrayState c908_cpu; /* Small core */
 
     K230WdtState wdt[2];
+    K230SDHCIState sdhci[2];
     MemoryRegion sram;
     MemoryRegion bootrom;
 
@@ -129,6 +131,8 @@ enum {
     K230_UART4_IRQ  = 20,
     K230_WDT0_IRQ   = 107,
     K230_WDT1_IRQ   = 108,
+    K230_SD0_IRQ    = 142,
+    K230_SD1_IRQ    = 144,
 };
 
 #define K230_UART_COUNT 5
-- 
2.43.0


Reply via email to