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>
This commit is contained in:
parent
145b299139
commit
722f1352b6
@ -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
|
||||
|
@ -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 },
|
||||
@ -345,6 +347,31 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
||||
"sifive,fu540-c000-ccache");
|
||||
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);
|
||||
@ -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[] = {
|
||||
|
@ -47,6 +47,7 @@ typedef struct SiFiveUSoCState {
|
||||
SiFiveUOTPState otp;
|
||||
SiFivePDMAState dma;
|
||||
SiFiveSPIState spi0;
|
||||
SiFiveSPIState spi2;
|
||||
CadenceGEMState gem;
|
||||
|
||||
uint32_t serial;
|
||||
@ -85,6 +86,7 @@ enum {
|
||||
SIFIVE_U_DEV_UART1,
|
||||
SIFIVE_U_DEV_GPIO,
|
||||
SIFIVE_U_DEV_QSPI0,
|
||||
SIFIVE_U_DEV_QSPI2,
|
||||
SIFIVE_U_DEV_OTP,
|
||||
SIFIVE_U_DEV_DMC,
|
||||
SIFIVE_U_DEV_FLASH0,
|
||||
@ -99,6 +101,7 @@ enum {
|
||||
SIFIVE_U_L2CC_IRQ2 = 3,
|
||||
SIFIVE_U_UART0_IRQ = 4,
|
||||
SIFIVE_U_UART1_IRQ = 5,
|
||||
SIFIVE_U_QSPI2_IRQ = 6,
|
||||
SIFIVE_U_GPIO_IRQ0 = 7,
|
||||
SIFIVE_U_GPIO_IRQ1 = 8,
|
||||
SIFIVE_U_GPIO_IRQ2 = 9,
|
||||
|
Loading…
Reference in New Issue
Block a user