From ac1bdbf22bebabfee150bb5c33a02c4d0119d185 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 25 Jan 2018 14:10:44 +0200 Subject: gpu: host1x: Add Tegra194 support The host1x hardware found on Tegra194 is mostly backwards compatible with the version found on Tegra186, with the notable exceptions of the increased number of syncpoints and mlocks. In addition, some rarely used features such as syncpoint wait bases were dropped and some registers had to move around to accomodate the increased number of syncpoints. Signed-off-by: Thierry Reding --- drivers/gpu/host1x/dev.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/gpu/host1x/dev.c') diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index de6bc4e7fa23..419d8929a98f 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -44,6 +44,7 @@ #include "hw/host1x04.h" #include "hw/host1x05.h" #include "hw/host1x06.h" +#include "hw/host1x07.h" void host1x_hypervisor_writel(struct host1x *host1x, u32 v, u32 r) { @@ -130,7 +131,19 @@ static const struct host1x_info host1x06_info = { .has_hypervisor = true, }; +static const struct host1x_info host1x07_info = { + .nb_channels = 63, + .nb_pts = 704, + .nb_mlocks = 32, + .nb_bases = 0, + .init = host1x07_init, + .sync_offset = 0x0, + .dma_mask = DMA_BIT_MASK(40), + .has_hypervisor = true, +}; + static const struct of_device_id host1x_of_match[] = { + { .compatible = "nvidia,tegra194-host1x", .data = &host1x07_info, }, { .compatible = "nvidia,tegra186-host1x", .data = &host1x06_info, }, { .compatible = "nvidia,tegra210-host1x", .data = &host1x05_info, }, { .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, }, -- cgit v1.2.3 From 6841482b82e5ba8a403559cbc0c15706624db17a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 1 Feb 2019 14:28:22 +0100 Subject: gpu: host1x: Set up stream ID table In order to enable the MMIO path stream ID protection provided by the incarnation of host1x found in Tegra186 and later, the host1x must be provided with the list of stream ID register offsets for each of its clients. Some clients (such as VIC) have multiple stream ID registers that are assumed to be contiguous. The host1x is programmed with the base offset and a limit which provide the range of registers that the host1x needs to monitor for writes. Signed-off-by: Thierry Reding --- drivers/gpu/host1x/dev.c | 38 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/host1x/dev.h | 8 ++++++++ 2 files changed, 46 insertions(+) (limited to 'drivers/gpu/host1x/dev.c') diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 419d8929a98f..4c044ee54fe6 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -120,6 +120,15 @@ static const struct host1x_info host1x05_info = { .dma_mask = DMA_BIT_MASK(34), }; +static const struct host1x_sid_entry tegra186_sid_table[] = { + { + /* VIC */ + .base = 0x1af0, + .offset = 0x30, + .limit = 0x34 + }, +}; + static const struct host1x_info host1x06_info = { .nb_channels = 63, .nb_pts = 576, @@ -129,6 +138,17 @@ static const struct host1x_info host1x06_info = { .sync_offset = 0x0, .dma_mask = DMA_BIT_MASK(34), .has_hypervisor = true, + .num_sid_entries = ARRAY_SIZE(tegra186_sid_table), + .sid_table = tegra186_sid_table, +}; + +static const struct host1x_sid_entry tegra194_sid_table[] = { + { + /* VIC */ + .base = 0x1af0, + .offset = 0x30, + .limit = 0x34 + }, }; static const struct host1x_info host1x07_info = { @@ -140,6 +160,8 @@ static const struct host1x_info host1x07_info = { .sync_offset = 0x0, .dma_mask = DMA_BIT_MASK(40), .has_hypervisor = true, + .num_sid_entries = ARRAY_SIZE(tegra194_sid_table), + .sid_table = tegra194_sid_table, }; static const struct of_device_id host1x_of_match[] = { @@ -154,6 +176,19 @@ static const struct of_device_id host1x_of_match[] = { }; MODULE_DEVICE_TABLE(of, host1x_of_match); +static void host1x_setup_sid_table(struct host1x *host) +{ + const struct host1x_info *info = host->info; + unsigned int i; + + for (i = 0; i < info->num_sid_entries; i++) { + const struct host1x_sid_entry *entry = &info->sid_table[i]; + + host1x_hypervisor_writel(host, entry->offset, entry->base); + host1x_hypervisor_writel(host, entry->limit, entry->base + 4); + } +} + static int host1x_probe(struct platform_device *pdev) { struct host1x *host; @@ -316,6 +351,9 @@ skip_iommu: host1x_debug_init(host); + if (host->info->has_hypervisor) + host1x_setup_sid_table(host); + err = host1x_register(host); if (err < 0) goto fail_deinit_intr; diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 36f44ffebe73..05216a7e4830 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -94,6 +94,12 @@ struct host1x_intr_ops { int (*free_syncpt_irq)(struct host1x *host); }; +struct host1x_sid_entry { + unsigned int base; + unsigned int offset; + unsigned int limit; +}; + struct host1x_info { unsigned int nb_channels; /* host1x: number of channels supported */ unsigned int nb_pts; /* host1x: number of syncpoints supported */ @@ -103,6 +109,8 @@ struct host1x_info { unsigned int sync_offset; /* offset of syncpoint registers */ u64 dma_mask; /* mask of addressable memory */ bool has_hypervisor; /* has hypervisor registers */ + unsigned int num_sid_entries; + const struct host1x_sid_entry *sid_table; }; struct host1x { -- cgit v1.2.3 From 38fabcc953883741313d707a919326f77c2d7214 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 1 Feb 2019 14:28:27 +0100 Subject: gpu: host1x: Restrict IOVA space to DMA mask On Tegra186 and later, the ARM SMMU provides an input address space that is 48 bits wide. However, memory clients can only address up to 40 bits. If the geometry is used as-is, allocations of IOVA space can end up in a region that is not addressable by the memory clients. To fix this, restrict the IOVA space to the DMA mask of the host1x device. Signed-off-by: Thierry Reding --- drivers/gpu/host1x/dev.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/host1x/dev.c') diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 4c044ee54fe6..544b67f2b3ff 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -283,6 +283,8 @@ static int host1x_probe(struct platform_device *pdev) host->group = iommu_group_get(&pdev->dev); if (host->group) { struct iommu_domain_geometry *geometry; + u64 mask = dma_get_mask(host->dev); + dma_addr_t start, end; unsigned long order; err = iova_cache_get(); @@ -310,11 +312,12 @@ static int host1x_probe(struct platform_device *pdev) } geometry = &host->domain->geometry; + start = geometry->aperture_start & mask; + end = geometry->aperture_end & mask; order = __ffs(host->domain->pgsize_bitmap); - init_iova_domain(&host->iova, 1UL << order, - geometry->aperture_start >> order); - host->iova_end = geometry->aperture_end; + init_iova_domain(&host->iova, 1UL << order, start >> order); + host->iova_end = end; } skip_iommu: -- cgit v1.2.3 From 8de896eb206fea3caa26b5fc8e637934d8486f0f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 1 Feb 2019 14:28:28 +0100 Subject: gpu: host1x: Support 40-bit addressing on Tegra186 The host1x and clients instantiated on Tegra186 support addressing 40 bits of memory. Signed-off-by: Thierry Reding --- drivers/gpu/host1x/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/host1x/dev.c') diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 544b67f2b3ff..ee3c7b81a29d 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -136,7 +136,7 @@ static const struct host1x_info host1x06_info = { .nb_bases = 16, .init = host1x06_init, .sync_offset = 0x0, - .dma_mask = DMA_BIT_MASK(34), + .dma_mask = DMA_BIT_MASK(40), .has_hypervisor = true, .num_sid_entries = ARRAY_SIZE(tegra186_sid_table), .sid_table = tegra186_sid_table, -- cgit v1.2.3