From: Nicolin Chen <[email protected]> Add initial Tegra241 CMDQV support by wiring up initialization and IOMMUFD backed vIOMMU allocation. The CMDQV MMIO region and IRQ are registered, while register handling remains a stub and will be completed in subsequent patches.
Signed-off-by: Nicolin Chen <[email protected]> Signed-off-by: Shameer Kolothum <[email protected]> --- hw/arm/tegra241-cmdqv.c | 55 ++++++++++++++++++++++++++++++++++++++--- hw/arm/tegra241-cmdqv.h | 19 ++++++++++++++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/hw/arm/tegra241-cmdqv.c b/hw/arm/tegra241-cmdqv.c index 6f30ca035b..596b1c5595 100644 --- a/hw/arm/tegra241-cmdqv.c +++ b/hw/arm/tegra241-cmdqv.c @@ -13,6 +13,16 @@ #include "smmuv3-accel.h" #include "tegra241-cmdqv.h" +static uint64_t tegra241_cmdqv_read(void *opaque, hwaddr offset, unsigned size) +{ + return 0; +} + +static void tegra241_cmdqv_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ +} + static void tegra241_cmdqv_free_veventq(SMMUv3State *s) { } @@ -25,24 +35,61 @@ static bool tegra241_cmdqv_alloc_veventq(SMMUv3State *s, Error **errp) static void tegra241_cmdqv_free_viommu(SMMUv3State *s) { + SMMUv3AccelState *accel = s->s_accel; + IOMMUFDViommu *viommu = accel->viommu; + + if (!viommu) { + return; + } + iommufd_backend_free_id(viommu->iommufd, viommu->viommu_id); } static bool tegra241_cmdqv_alloc_viommu(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *idev, uint32_t *out_viommu_id, Error **errp) { - error_setg(errp, "NVIDIA Tegra241 CMDQV is unsupported"); - return false; + Tegra241CMDQV *cmdqv = s->s_accel->cmdqv; + + if (!iommufd_backend_alloc_viommu(idev->iommufd, idev->devid, + IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV, + idev->hwpt_id, &cmdqv->cmdqv_data, + sizeof(cmdqv->cmdqv_data), out_viommu_id, + errp)) { + error_append_hint(errp, "Tegra241 CMDQV support unavailable"); + return false; + } + return true; } static void tegra241_cmdqv_reset(SMMUv3State *s) { } +static const MemoryRegionOps mmio_cmdqv_ops = { + .read = tegra241_cmdqv_read, + .write = tegra241_cmdqv_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static bool tegra241_cmdqv_init(SMMUv3State *s, Error **errp) { - error_setg(errp, "NVIDIA Tegra241 CMDQV is unsupported"); - return false; + SysBusDevice *sbd = SYS_BUS_DEVICE(OBJECT(s)); + SMMUv3AccelState *accel = s->s_accel; + Tegra241CMDQV *cmdqv; + + if (!accel) { + error_setg(errp, "Tegra241 CMDQV requires SMMUv3 acceleration"); + return false; + } + + cmdqv = g_new0(Tegra241CMDQV, 1); + memory_region_init_io(&cmdqv->mmio_cmdqv, OBJECT(s), &mmio_cmdqv_ops, cmdqv, + "tegra241-cmdqv", TEGRA241_CMDQV_IO_LEN); + sysbus_init_mmio(sbd, &cmdqv->mmio_cmdqv); + sysbus_init_irq(sbd, &cmdqv->irq); + cmdqv->s_accel = accel; + accel->cmdqv = cmdqv; + return true; } static const SMMUv3AccelCmdqvOps tegra241_cmdqv_ops_impl = { diff --git a/hw/arm/tegra241-cmdqv.h b/hw/arm/tegra241-cmdqv.h index 81c9deb384..6ea0087f61 100644 --- a/hw/arm/tegra241-cmdqv.h +++ b/hw/arm/tegra241-cmdqv.h @@ -10,8 +10,27 @@ #ifndef HW_TEGRA241_CMDQV_H #define HW_TEGRA241_CMDQV_H +#include "smmuv3-accel.h" #include CONFIG_DEVICES +/* + * Tegra241 CMDQV MMIO layout (64KB pages): + * + * 0x00000: Global CMDQV registers + * 0x10000: Global VCMDQ registers, page 0 + * 0x20000: Global VCMDQ registers, page 1 + * 0x30000: VINTF0 logical VCMDQ registers, page 0 + * 0x40000: VINTF0 logical VCMDQ registers, page 1 + */ +#define TEGRA241_CMDQV_IO_LEN 0x50000 + +typedef struct Tegra241CMDQV { + struct iommu_viommu_tegra241_cmdqv cmdqv_data; + SMMUv3AccelState *s_accel; + MemoryRegion mmio_cmdqv; + qemu_irq irq; +} Tegra241CMDQV; + #ifdef CONFIG_TEGRA241_CMDQV const SMMUv3AccelCmdqvOps *tegra241_cmdqv_ops(void); #else -- 2.43.0
