aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBin Meng <bin.meng@windriver.com>2021-01-26 14:00:03 +0800
committerAlistair Francis <alistair.francis@wdc.com>2021-03-04 09:43:29 -0500
commit722f1352b6c248ead94efd77ff5726aa0cba949b (patch)
tree5b66ed3f4a7400037ebd9bcfb19f453867c95776 /hw
parent145b299139da92fb1b1048b393865bc96597d6b9 (diff)
hw/riscv: sifive_u: Add QSPI2 controller and connect an SD card
This adds the QSPI2 controller to the SoC, and connects an SD card to it. The generation of corresponding device tree source fragment is also added. Specify machine property `msel` to 11 to boot the same upstream U-Boot SPL and payload image for the SiFive HiFive Unleashed board. Note subsequent payload is stored in the SD card image. $ qemu-system-riscv64 -nographic -M sifive_u,msel=11 -smp 5 -m 8G \ -bios u-boot-spl.bin -drive file=sdcard.img,if=sd Signed-off-by: Bin Meng <bin.meng@windriver.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20210126060007.12904-6-bmeng.cn@gmail.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/riscv/Kconfig1
-rw-r--r--hw/riscv/sifive_u.c43
2 files changed, 42 insertions, 2 deletions
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 6330297b4e..d139074b02 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -57,6 +57,7 @@ config SIFIVE_U
select SIFIVE_U_OTP
select SIFIVE_U_PRCI
select SSI_M25P80
+ select SSI_SD
select UNIMP
config SPIKE
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 43a0e983d2..6c1158a848 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -16,6 +16,7 @@
* 6) GEM (Gigabit Ethernet Controller) and management block
* 7) DMA (Direct Memory Access Controller)
* 8) SPI0 connected to an SPI flash
+ * 9) SPI2 connected to an SD card
*
* This board currently generates devicetree dynamically that indicates at least
* two harts and up to five harts.
@@ -77,6 +78,7 @@ static const struct MemmapEntry {
[SIFIVE_U_DEV_UART0] = { 0x10010000, 0x1000 },
[SIFIVE_U_DEV_UART1] = { 0x10011000, 0x1000 },
[SIFIVE_U_DEV_QSPI0] = { 0x10040000, 0x1000 },
+ [SIFIVE_U_DEV_QSPI2] = { 0x10050000, 0x1000 },
[SIFIVE_U_DEV_GPIO] = { 0x10060000, 0x1000 },
[SIFIVE_U_DEV_OTP] = { 0x10070000, 0x1000 },
[SIFIVE_U_DEV_GEM] = { 0x10090000, 0x2000 },
@@ -346,6 +348,31 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
g_free(nodename);
nodename = g_strdup_printf("/soc/spi@%lx",
+ (long)memmap[SIFIVE_U_DEV_QSPI2].base);
+ qemu_fdt_add_subnode(fdt, nodename);
+ qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 0);
+ qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1);
+ qemu_fdt_setprop_cells(fdt, nodename, "clocks",
+ prci_phandle, PRCI_CLK_TLCLK);
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_QSPI2_IRQ);
+ qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
+ qemu_fdt_setprop_cells(fdt, nodename, "reg",
+ 0x0, memmap[SIFIVE_U_DEV_QSPI2].base,
+ 0x0, memmap[SIFIVE_U_DEV_QSPI2].size);
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,spi0");
+ g_free(nodename);
+
+ nodename = g_strdup_printf("/soc/spi@%lx/mmc@0",
+ (long)memmap[SIFIVE_U_DEV_QSPI2].base);
+ qemu_fdt_add_subnode(fdt, nodename);
+ qemu_fdt_setprop(fdt, nodename, "disable-wp", NULL, 0);
+ qemu_fdt_setprop_cells(fdt, nodename, "voltage-ranges", 3300, 3300);
+ qemu_fdt_setprop_cell(fdt, nodename, "spi-max-frequency", 20000000);
+ qemu_fdt_setprop_cell(fdt, nodename, "reg", 0);
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "mmc-spi-slot");
+ g_free(nodename);
+
+ nodename = g_strdup_printf("/soc/spi@%lx",
(long)memmap[SIFIVE_U_DEV_QSPI0].base);
qemu_fdt_add_subnode(fdt, nodename);
qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 0);
@@ -469,8 +496,8 @@ static void sifive_u_machine_init(MachineState *machine)
uint32_t fdt_load_addr;
uint64_t kernel_entry;
DriveInfo *dinfo;
- DeviceState *flash_dev;
- qemu_irq flash_cs;
+ DeviceState *flash_dev, *sd_dev;
+ qemu_irq flash_cs, sd_cs;
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC);
@@ -616,6 +643,12 @@ static void sifive_u_machine_init(MachineState *machine)
flash_cs = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.spi0), 1, flash_cs);
+
+ /* Connect an SD card to SPI2 */
+ sd_dev = ssi_create_peripheral(s->soc.spi2.spi, "ssi-sd");
+
+ sd_cs = qdev_get_gpio_in_named(sd_dev, SSI_GPIO_CS, 0);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.spi2), 1, sd_cs);
}
static bool sifive_u_machine_get_start_in_flash(Object *obj, Error **errp)
@@ -726,6 +759,7 @@ static void sifive_u_soc_instance_init(Object *obj)
object_initialize_child(obj, "gpio", &s->gpio, TYPE_SIFIVE_GPIO);
object_initialize_child(obj, "pdma", &s->dma, TYPE_SIFIVE_PDMA);
object_initialize_child(obj, "spi0", &s->spi0, TYPE_SIFIVE_SPI);
+ object_initialize_child(obj, "spi2", &s->spi2, TYPE_SIFIVE_SPI);
}
static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
@@ -879,6 +913,11 @@ static void sifive_u_soc_realize(DeviceState *dev, Error **errp)
memmap[SIFIVE_U_DEV_QSPI0].base);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi0), 0,
qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_QSPI0_IRQ));
+ sysbus_realize(SYS_BUS_DEVICE(&s->spi2), errp);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi2), 0,
+ memmap[SIFIVE_U_DEV_QSPI2].base);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi2), 0,
+ qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_QSPI2_IRQ));
}
static Property sifive_u_soc_props[] = {