From af2a177038b69763dda7a74879d6b3a45830d0f9 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Tue, 19 Nov 2024 07:05:02 +0000 Subject: [PATCH] gpu: host1x: Retrieve syncpoint shim information Retrieve information for the memory syncpoint shim from the device tree and add an interface to provide the information to other drivers. The memory syncpoint shim is a special area on the data backbone, where each memory page corresponds to a host1x syncpoint. Reading the page returns the value of the syncpoint, and writing to it increments the syncpoint by one. Jira HOSTX-5722 Bug 4919132 Change-Id: Ie892abd754f7543fbc56844dcc40cab3f837e305 Signed-off-by: Mikko Perttunen Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3252025 GVS: buildbot_gerritrpt Reviewed-by: Santosh BS --- drivers/gpu/host1x/dev.c | 48 +++++++++++++++++++ drivers/gpu/host1x/dev.h | 4 ++ .../gpu/host1x/include/linux/host1x-next.h | 3 ++ drivers/gpu/host1x/syncpt.c | 14 ++++++ 4 files changed, 69 insertions(+) diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index fd91fafb..94d53c12 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -937,6 +938,49 @@ static int host1x_get_syncpt_pools(struct host1x *host) return 0; } +static int host1x_get_syncpt_shim(struct host1x *host) +{ + struct device_node *np = host->dev->of_node, *shim_np; + u64 base, size; + int err; + + shim_np = of_parse_phandle(np, "nvidia,syncpoint-shim", 0); + if (!shim_np) + return 0; + +#ifdef NV_OF_PROPERTY_READ_REG_PRESENT + err = of_property_read_reg(shim_np, 0, &base, &size); + of_node_put(shim_np); + if (err) { + dev_err(host->dev, "syncpoint shim node has invalid reg property: %d\n", err); + return err; + } +#else + { + u32 data[4]; + err = of_property_read_u32_array(shim_np, "reg", data, ARRAY_SIZE(data)); + of_node_put(shim_np); + if (err) { + dev_err(host->dev, "syncpoint shim has invalid reg property: %d\n", err); + return err; + } + + base = data[1]; + size = data[3]; + } +#endif + + host->shim_stride = size / host->info->nb_pts; + if (host->shim_stride != 0x1000 && host->shim_stride != 0x10000) { + dev_err(host->dev, "syncpoint shim has unexpected stride %u\n", host->shim_stride); + return err; + } + + host->shim_base = base; + + return 0; +} + static int host1x_probe(struct platform_device *pdev) { struct resource *res; @@ -1038,6 +1082,10 @@ static int host1x_probe(struct platform_device *pdev) if (err) return err; + err = host1x_get_syncpt_shim(host); + if (err) + return err; + host->clk = devm_clk_get_optional(&pdev->dev, "host1x"); if (!host->clk) host->clk = devm_clk_get(&pdev->dev, NULL); diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 3ce77045..3e94ef51 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -169,6 +169,10 @@ struct host1x { struct host1x_syncpt_pool *pools; unsigned int num_pools; + /* Syncpoint shim */ + phys_addr_t shim_base; + u32 shim_stride; + struct iommu_group *group; struct iommu_domain *domain; struct iova_domain iova; diff --git a/drivers/gpu/host1x/include/linux/host1x-next.h b/drivers/gpu/host1x/include/linux/host1x-next.h index 66b684dd..19a2b3b3 100644 --- a/drivers/gpu/host1x/include/linux/host1x-next.h +++ b/drivers/gpu/host1x/include/linux/host1x-next.h @@ -257,6 +257,9 @@ u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base); void host1x_syncpt_release_vblank_reservation(struct host1x_client *client, u32 syncpt_id); +int host1x_syncpt_get_shim_info(struct host1x *host, phys_addr_t *base, u32 *stride, + u32 *num_syncpts); + struct dma_fence *host1x_fence_create(struct host1x_syncpt *sp, u32 threshold, bool timeout); int host1x_fence_extract(struct dma_fence *fence, u32 *id, u32 *threshold); diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index eb59bd92..57fe545c 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -587,3 +587,17 @@ void host1x_syncpt_release_vblank_reservation(struct host1x_client *client, kref_put(&host->syncpt[syncpt_id].ref, do_nothing); } EXPORT_SYMBOL(host1x_syncpt_release_vblank_reservation); + +int host1x_syncpt_get_shim_info(struct host1x *host, phys_addr_t *base, u32 *stride, + u32 *num_syncpts) +{ + if (!host->shim_base) + return -ENODEV; + + *base = host->shim_base; + *stride = host->shim_stride; + *num_syncpts = host->info->nb_pts; + + return 0; +} +EXPORT_SYMBOL(host1x_syncpt_get_shim_info); \ No newline at end of file