hw/arm/sysbus-fdt: enable vfio-calxeda-xgmac dynamic instantiation
This patch allows the instantiation of the vfio-calxeda-xgmac device from the QEMU command line (-device vfio-calxeda-xgmac,host="<device>"). A specialized device tree node is created for the guest, containing compat, dma-coherent, reg and interrupts properties. Signed-off-by: Eric Auger <eric.auger@linaro.org> Acked-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1434455898-17895-1-git-send-email-eric.auger@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
ba890a9b25
commit
decf4f807b
@ -26,6 +26,9 @@
|
|||||||
#include "sysemu/device_tree.h"
|
#include "sysemu/device_tree.h"
|
||||||
#include "hw/platform-bus.h"
|
#include "hw/platform-bus.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "hw/vfio/vfio-platform.h"
|
||||||
|
#include "hw/vfio/vfio-calxeda-xgmac.h"
|
||||||
|
#include "hw/arm/fdt.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* internal struct that contains the information to create dynamic
|
* internal struct that contains the information to create dynamic
|
||||||
@ -53,11 +56,81 @@ typedef struct NodeCreationPair {
|
|||||||
int (*add_fdt_node_fn)(SysBusDevice *sbdev, void *opaque);
|
int (*add_fdt_node_fn)(SysBusDevice *sbdev, void *opaque);
|
||||||
} NodeCreationPair;
|
} NodeCreationPair;
|
||||||
|
|
||||||
|
/* Device Specific Code */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add_calxeda_midway_xgmac_fdt_node
|
||||||
|
*
|
||||||
|
* Generates a simple node with following properties:
|
||||||
|
* compatible string, regs, interrupts, dma-coherent
|
||||||
|
*/
|
||||||
|
static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
|
||||||
|
{
|
||||||
|
PlatformBusFDTData *data = opaque;
|
||||||
|
PlatformBusDevice *pbus = data->pbus;
|
||||||
|
void *fdt = data->fdt;
|
||||||
|
const char *parent_node = data->pbus_node_name;
|
||||||
|
int compat_str_len, i, ret = -1;
|
||||||
|
char *nodename;
|
||||||
|
uint32_t *irq_attr, *reg_attr;
|
||||||
|
uint64_t mmio_base, irq_number;
|
||||||
|
VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
|
||||||
|
VFIODevice *vbasedev = &vdev->vbasedev;
|
||||||
|
|
||||||
|
mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
|
||||||
|
nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
|
||||||
|
vbasedev->name, mmio_base);
|
||||||
|
qemu_fdt_add_subnode(fdt, nodename);
|
||||||
|
|
||||||
|
compat_str_len = strlen(vdev->compat) + 1;
|
||||||
|
qemu_fdt_setprop(fdt, nodename, "compatible",
|
||||||
|
vdev->compat, compat_str_len);
|
||||||
|
|
||||||
|
qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
|
||||||
|
|
||||||
|
reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
|
||||||
|
for (i = 0; i < vbasedev->num_regions; i++) {
|
||||||
|
mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
|
||||||
|
reg_attr[2 * i] = cpu_to_be32(mmio_base);
|
||||||
|
reg_attr[2 * i + 1] = cpu_to_be32(
|
||||||
|
memory_region_size(&vdev->regions[i]->mem));
|
||||||
|
}
|
||||||
|
ret = qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
|
||||||
|
vbasedev->num_regions * 2 * sizeof(uint32_t));
|
||||||
|
if (ret) {
|
||||||
|
error_report("could not set reg property of node %s", nodename);
|
||||||
|
goto fail_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
|
||||||
|
for (i = 0; i < vbasedev->num_irqs; i++) {
|
||||||
|
irq_number = platform_bus_get_irqn(pbus, sbdev , i)
|
||||||
|
+ data->irq_start;
|
||||||
|
irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
|
||||||
|
irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
|
||||||
|
irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
||||||
|
}
|
||||||
|
ret = qemu_fdt_setprop(fdt, nodename, "interrupts",
|
||||||
|
irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
|
||||||
|
if (ret) {
|
||||||
|
error_report("could not set interrupts property of node %s",
|
||||||
|
nodename);
|
||||||
|
}
|
||||||
|
g_free(irq_attr);
|
||||||
|
fail_reg:
|
||||||
|
g_free(reg_attr);
|
||||||
|
g_free(nodename);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* list of supported dynamic sysbus devices */
|
/* list of supported dynamic sysbus devices */
|
||||||
static const NodeCreationPair add_fdt_node_functions[] = {
|
static const NodeCreationPair add_fdt_node_functions[] = {
|
||||||
|
{TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node},
|
||||||
{"", NULL}, /* last element */
|
{"", NULL}, /* last element */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Generic Code */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add_fdt_node - add the device tree node of a dynamic sysbus device
|
* add_fdt_node - add the device tree node of a dynamic sysbus device
|
||||||
*
|
*
|
||||||
|
@ -47,21 +47,11 @@
|
|||||||
#include "hw/arm/virt-acpi-build.h"
|
#include "hw/arm/virt-acpi-build.h"
|
||||||
#include "hw/arm/sysbus-fdt.h"
|
#include "hw/arm/sysbus-fdt.h"
|
||||||
#include "hw/platform-bus.h"
|
#include "hw/platform-bus.h"
|
||||||
|
#include "hw/arm/fdt.h"
|
||||||
|
|
||||||
/* Number of external interrupt lines to configure the GIC with */
|
/* Number of external interrupt lines to configure the GIC with */
|
||||||
#define NUM_IRQS 256
|
#define NUM_IRQS 256
|
||||||
|
|
||||||
#define GIC_FDT_IRQ_TYPE_SPI 0
|
|
||||||
#define GIC_FDT_IRQ_TYPE_PPI 1
|
|
||||||
|
|
||||||
#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
|
|
||||||
#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
|
|
||||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
|
|
||||||
#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
|
|
||||||
|
|
||||||
#define GIC_FDT_IRQ_PPI_CPU_START 8
|
|
||||||
#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
|
|
||||||
|
|
||||||
#define PLATFORM_BUS_NUM_IRQS 64
|
#define PLATFORM_BUS_NUM_IRQS 64
|
||||||
|
|
||||||
static ARMPlatformBusSystemParams platform_bus_params;
|
static ARMPlatformBusSystemParams platform_bus_params;
|
||||||
|
34
include/hw/arm/fdt.h
Normal file
34
include/hw/arm/fdt.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Linaro Limited
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2 or later, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Define macros useful when building ARM device tree nodes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QEMU_ARM_FDT_H
|
||||||
|
#define QEMU_ARM_FDT_H
|
||||||
|
|
||||||
|
#define GIC_FDT_IRQ_TYPE_SPI 0
|
||||||
|
#define GIC_FDT_IRQ_TYPE_PPI 1
|
||||||
|
|
||||||
|
#define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
|
||||||
|
#define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
|
||||||
|
#define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4
|
||||||
|
#define GIC_FDT_IRQ_FLAGS_LEVEL_LO 8
|
||||||
|
|
||||||
|
#define GIC_FDT_IRQ_PPI_CPU_START 8
|
||||||
|
#define GIC_FDT_IRQ_PPI_CPU_WIDTH 8
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user