diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 0903f7451b25b..f720c050e57a3 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -156,6 +156,57 @@ static void acpi_dsdt_add_virtio(Aml *scope, } } +static void acpi_dsdt_add_ehci(Aml *scope, const MemMapEntry *ehci_memmap, + uint32_t ehci_irq) +{ + Aml *dev = aml_device("USB0"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0D20"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + Aml *crs = aml_resource_template(); + aml_append(crs, + aml_memory32_fixed(ehci_memmap->base, + ehci_memmap->size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &ehci_irq, 1)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} + +static void acpi_dsdt_add_mmci(Aml *scope, const MemMapEntry *sdhci_memmap, + uint32_t sdhci_irq) +{ + Aml *dev = aml_device("SDC1"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0D40"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + Aml *crs = aml_resource_template(); + aml_append(crs, + aml_memory32_fixed(sdhci_memmap->base, + sdhci_memmap->size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &sdhci_irq, 1)); + aml_append(dev, aml_name_decl("_CRS", crs)); + + /* Add a child device that represents the SD card, + which is marked as non-removable */ + Aml *carddev = aml_device("SDMM"); + + Aml *adr = aml_method("_ADR", 0, AML_NOTSERIALIZED); + aml_append(adr, aml_return(aml_int(0))); + + Aml *rmv = aml_method("_RMV", 0, AML_NOTSERIALIZED); + aml_append(rmv, aml_return(aml_int(0))); + + aml_append(carddev, adr); + aml_append(carddev, rmv); + aml_append(dev, carddev); + + aml_append(scope, dev); +} + // static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, // uint32_t irq, bool use_highmem, bool highmem_ecam, // VirtMachineState *vms) @@ -869,6 +920,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); // acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), // vms->highmem, vms->highmem_ecam, vms); + acpi_dsdt_add_ehci(scope, &memmap[VIRT_EHCI], irqmap[VIRT_EHCI] + ARM_SPI_BASE); + acpi_dsdt_add_mmci(scope, &memmap[VIRT_SDHCI], irqmap[VIRT_SDHCI] + ARM_SPI_BASE); if (vms->acpi_dev) { build_ged_aml(scope, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(vms->acpi_dev), diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 4463ce0c45eb7..76123e568f942 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -78,6 +78,7 @@ #include "hw/virtio/virtio-iommu.h" #include "hw/char/pl011.h" #include "qemu/guest-random.h" +#include "hw/sd/sdhci.h" #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -153,6 +154,8 @@ static const MemMapEntry base_memmap[] = { [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 }, + [VIRT_EHCI] = { 0x090c0000, 0x00010000 }, + [VIRT_SDHCI] = { 0x090d0000, 0x00010000 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, @@ -189,6 +192,8 @@ static const int a15irqmap[] = { [VIRT_GPIO] = 7, [VIRT_SECURE_UART] = 8, [VIRT_ACPI_GED] = 9, + [VIRT_EHCI] = 11, + [VIRT_SDHCI] = 12, [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ @@ -1289,6 +1294,44 @@ static void create_pcie_irq_map(const MachineState *ms, 0x7 /* PCI irq */); } +static void create_ehci(const VirtMachineState *vms) +{ + hwaddr base = vms->memmap[VIRT_EHCI].base; + int irq = vms->irqmap[VIRT_EHCI]; + + sysbus_create_simple("platform-ehci-usb", base, + qdev_get_gpio_in(vms->gic, irq)); +} + +static void create_sdhci(const VirtMachineState *vms) +{ + + hwaddr base = vms->memmap[VIRT_SDHCI].base; + int irq = vms->irqmap[VIRT_SDHCI]; + DeviceState *dev; + SysBusDevice *busdev; + DriveInfo *di; + BlockBackend *blk; + DeviceState *carddev; + + dev = qdev_new(TYPE_SYSBUS_SDHCI); + qdev_prop_set_uint64(dev, "capareg", VIRT_SDHCI_CAPABILITIES); + + busdev = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(busdev, &error_fatal); + sysbus_mmio_map(busdev, 0, base); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(vms->gic, irq)); + + + di = drive_get_next(IF_SD); + blk = di ? blk_by_legacy_dinfo(di) : NULL; + carddev = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive(carddev, "drive", blk); + qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"), + &error_fatal); + +} + static void create_smmu(const VirtMachineState *vms, PCIBus *bus) { @@ -2150,6 +2193,12 @@ static void machvirt_init(MachineState *machine) */ create_virtio_devices(vms); + /* Create platform EHCI controller device */ + create_ehci(vms); + + /* Create platform SD host controller device */ + create_sdhci(vms); + vms->fw_cfg = create_fw_cfg(vms, &address_space_memory); rom_set_fw(vms->fw_cfg); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index dc6b66ffc8f8c..a0b439752cec0 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -70,6 +70,8 @@ enum { VIRT_GIC_REDIST, VIRT_SMMU, VIRT_UART, + VIRT_EHCI, + VIRT_SDHCI, VIRT_MMIO, VIRT_RTC, VIRT_FW_CFG, @@ -175,6 +177,9 @@ struct VirtMachineState { #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) +/* Copied from EXYNOS4210_SDHCI_CAPABILITIES */ +#define VIRT_SDHCI_CAPABILITIES 0x05E80080 + #define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE)