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