Alper Nebi Yasak has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/80369?usp=email )
Change subject: drivers/qemu/fw_cfg: Support architectures using MMIO ......................................................................
drivers/qemu/fw_cfg: Support architectures using MMIO
The QEMU firmware configuration device can be used with non-x86 VMs as well, but its driver needs to use MMIO at a platform-specific address.
Use preprocessor directives to limit port-based IO instructions to x86, and implement MMIO access as the alternative. Require specifying the driver's base address as a kconfig option on non-x86 platforms, similar to how PCI ECAM address is handled.
Change-Id: Iacab3f6959cb6af747fde8a5af5cb35ce2bca512 Signed-off-by: Alper Nebi Yasak alpernebiyasak@gmail.com --- M src/drivers/emulation/qemu/Kconfig M src/drivers/emulation/qemu/fw_cfg.c 2 files changed, 49 insertions(+), 11 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/69/80369/1
diff --git a/src/drivers/emulation/qemu/Kconfig b/src/drivers/emulation/qemu/Kconfig index 31f5389..96c719a 100644 --- a/src/drivers/emulation/qemu/Kconfig +++ b/src/drivers/emulation/qemu/Kconfig @@ -27,8 +27,15 @@
config DRIVERS_EMULATION_QEMU_FW_CFG bool "QEMU firmware configuration driver" - depends on CPU_QEMU_X86 + depends on VENDOR_EMULATION help Driver for QEMU-specific device that passes various config information to the firmware including e.g. ACPI and SMBIOS tables. + +config QEMU_FW_CFG_BASE_ADDRESS + hex + depends on DRIVERS_EMULATION_QEMU_FW_CFG && !CPU_QEMU_X86 + help + Platform dependent base address of the MMIO (and DMA) + registers for the QEMU firmware configuration device. diff --git a/src/drivers/emulation/qemu/fw_cfg.c b/src/drivers/emulation/qemu/fw_cfg.c index 5457fb6..714abfb 100644 --- a/src/drivers/emulation/qemu/fw_cfg.c +++ b/src/drivers/emulation/qemu/fw_cfg.c @@ -5,16 +5,29 @@ #include <string.h> #include <smbios.h> #include <console/console.h> +#if CONFIG(CPU_QEMU_X86) #include <arch/io.h> +#else +#include <arch/mmio.h> +#endif #include <acpi/acpi.h> #include <commonlib/endian.h> #include <fw_cfg.h> #include <fw_cfg_if.h>
-#define FW_CFG_PORT_CTL 0x0510 -#define FW_CFG_PORT_DATA 0x0511 -#define FW_CFG_DMA_ADDR_HIGH 0x0514 -#define FW_CFG_DMA_ADDR_LOW 0x0518 +#if !CONFIG(CPU_QEMU_X86) && CONFIG_QEMU_FW_CFG_BASE_ADDRESS == 0 +#error "CONFIG_QEMU_FW_CFG_BASE_ADDRESS undefined!" +#endif + +#define FW_CFG_X86_PORT_CTL 0x0510 +#define FW_CFG_X86_PORT_DATA 0x0511 +#define FW_CFG_X86_DMA_ADDR_HIGH 0x0514 +#define FW_CFG_X86_DMA_ADDR_LOW 0x0518 + +#define FW_CFG_CTL_ADDR (CONFIG_QEMU_FW_CFG_BASE_ADDRESS + 8) +#define FW_CFG_DATA_ADDR (CONFIG_QEMU_FW_CFG_BASE_ADDRESS + 0) +#define FW_CFG_DMA_ADDR_HIGH (CONFIG_QEMU_FW_CFG_BASE_ADDRESS + 16) +#define FW_CFG_DMA_ADDR_LOW (CONFIG_QEMU_FW_CFG_BASE_ADDRESS + 20)
static int fw_cfg_detected; static uint8_t fw_ver; @@ -45,16 +58,27 @@ { if (fw_ver & FW_CFG_VERSION_DMA) fw_cfg_dma(FW_CFG_DMA_CTL_SELECT | entry << 16, NULL, 0); - else - outw(entry, FW_CFG_PORT_CTL); + else { +#if CONFIG(CPU_QEMU_X86) + outw(entry, FW_CFG_X86_PORT_CTL); +#else + write16((void *)FW_CFG_CTL_ADDR, be16_to_cpu(entry)); +#endif + } }
static void fw_cfg_read(void *dst, int dstlen) { if (fw_ver & FW_CFG_VERSION_DMA) fw_cfg_dma(FW_CFG_DMA_CTL_READ, dst, dstlen); - else - insb(FW_CFG_PORT_DATA, dst, dstlen); + else { +#if CONFIG(CPU_QEMU_X86) + insb(FW_CFG_X86_PORT_DATA, dst, dstlen); +#else + for (int i = 0; i < dstlen; i++) + ((uint8_t *)dst)[i] = read8((void *)FW_CFG_DATA_ADDR); +#endif + } }
void fw_cfg_get(uint16_t entry, void *dst, int dstlen) @@ -528,10 +552,17 @@ dma_desc_addr_hi = sizeof(uintptr_t) > sizeof(uint32_t) ? (uint32_t)(dma_desc_addr >> 32) : 0;
+#if CONFIG(CPU_QEMU_X86) // Skip writing high half if unnecessary. if (dma_desc_addr_hi) - outl(be32_to_cpu(dma_desc_addr_hi), FW_CFG_DMA_ADDR_HIGH); - outl(be32_to_cpu(dma_desc_addr_lo), FW_CFG_DMA_ADDR_LOW); + outl(be32_to_cpu(dma_desc_addr_hi), FW_CFG_X86_DMA_ADDR_HIGH); + outl(be32_to_cpu(dma_desc_addr_lo), FW_CFG_X86_DMA_ADDR_LOW); +#else + // Skip writing high half if unnecessary. + if (dma_desc_addr_hi) + write32((void *)FW_CFG_DMA_ADDR_HIGH, be32_to_cpu(dma_desc_addr_hi)); + write32((void *)FW_CFG_DMA_ADDR_LOW, be32_to_cpu(dma_desc_addr_lo)); +#endif
while (be32_to_cpu(dma.control) & ~FW_CFG_DMA_CTL_ERROR) ;