mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 21:59:12 -04:00
Merge "msm: kgsl: Cleanup iommu device tree probe"
This commit is contained in:
commit
ecac8a0e7f
4 changed files with 61 additions and 88 deletions
|
|
@ -1404,6 +1404,9 @@ static int adreno_probe(struct platform_device *pdev)
|
|||
|
||||
device->pwrctrl.bus_width = adreno_dev->gpucore->bus_width;
|
||||
|
||||
device->mmu.secured = (IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) &&
|
||||
ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION));
|
||||
|
||||
status = kgsl_device_platform_probe(device);
|
||||
if (status) {
|
||||
device->pdev = NULL;
|
||||
|
|
@ -1419,18 +1422,6 @@ static int adreno_probe(struct platform_device *pdev)
|
|||
adreno_rscc_probe(device);
|
||||
|
||||
adreno_isense_probe(device);
|
||||
/*
|
||||
* qcom,iommu-secure-id is used to identify MMUs that can handle secure
|
||||
* content but that is only part of the story - the GPU also has to be
|
||||
* able to handle secure content. Unfortunately in a classic catch-22
|
||||
* we cannot identify the GPU until after the DT is parsed. tl;dr -
|
||||
* check the GPU capabilities here and modify mmu->secured accordingly
|
||||
*/
|
||||
|
||||
#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER)
|
||||
if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION))
|
||||
device->mmu.secured = false;
|
||||
#endif
|
||||
|
||||
if (ADRENO_FEATURE(adreno_dev, ADRENO_IOCOHERENT))
|
||||
device->mmu.features |= KGSL_MMU_IO_COHERENT;
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ static void _detach_pt(struct kgsl_iommu_pt *iommu_pt,
|
|||
struct kgsl_iommu_context *ctx)
|
||||
{
|
||||
if (iommu_pt->attached) {
|
||||
iommu_detach_device(iommu_pt->domain, ctx->dev);
|
||||
iommu_detach_device(iommu_pt->domain, &ctx->pdev->dev);
|
||||
iommu_pt->attached = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ static int _attach_pt(struct kgsl_iommu_pt *iommu_pt,
|
|||
if (iommu_pt->attached)
|
||||
return 0;
|
||||
|
||||
ret = iommu_attach_device(iommu_pt->domain, ctx->dev);
|
||||
ret = iommu_attach_device(iommu_pt->domain, &ctx->pdev->dev);
|
||||
|
||||
if (ret == 0)
|
||||
iommu_pt->attached = true;
|
||||
|
|
@ -935,7 +935,7 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
|
|||
struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
|
||||
struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
|
||||
|
||||
iommu_pt = _alloc_pt(ctx->dev, mmu, pt);
|
||||
iommu_pt = _alloc_pt(&ctx->pdev->dev, mmu, pt);
|
||||
|
||||
if (IS_ERR(iommu_pt))
|
||||
return PTR_ERR(iommu_pt);
|
||||
|
|
@ -1016,7 +1016,7 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
|
|||
if (!mmu->secured)
|
||||
return -EPERM;
|
||||
|
||||
iommu_pt = _alloc_pt(ctx->dev, mmu, pt);
|
||||
iommu_pt = _alloc_pt(&ctx->pdev->dev, mmu, pt);
|
||||
|
||||
if (IS_ERR(iommu_pt))
|
||||
return PTR_ERR(iommu_pt);
|
||||
|
|
@ -1058,7 +1058,7 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
|
|||
int dynamic = 1;
|
||||
unsigned int cb_num = ctx->cb_num;
|
||||
|
||||
iommu_pt = _alloc_pt(ctx->dev, mmu, pt);
|
||||
iommu_pt = _alloc_pt(&ctx->pdev->dev, mmu, pt);
|
||||
|
||||
if (IS_ERR(iommu_pt))
|
||||
return PTR_ERR(iommu_pt);
|
||||
|
|
@ -1165,6 +1165,9 @@ static void _detach_context(struct kgsl_iommu_context *ctx)
|
|||
_detach_pt(iommu_pt, ctx);
|
||||
|
||||
ctx->default_pt = NULL;
|
||||
platform_device_put(ctx->pdev);
|
||||
|
||||
ctx->pdev = NULL;
|
||||
}
|
||||
|
||||
static void kgsl_iommu_close(struct kgsl_mmu *mmu)
|
||||
|
|
@ -1196,6 +1199,9 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu)
|
|||
__free_page(kgsl_dummy_page);
|
||||
kgsl_dummy_page = NULL;
|
||||
}
|
||||
|
||||
of_platform_depopulate(&iommu->pdev->dev);
|
||||
platform_device_put(iommu->pdev);
|
||||
}
|
||||
|
||||
static int kgsl_iommu_init(struct kgsl_mmu *mmu)
|
||||
|
|
@ -1332,7 +1338,7 @@ static int _setup_secure_context(struct kgsl_mmu *mmu)
|
|||
|
||||
struct kgsl_iommu_pt *iommu_pt;
|
||||
|
||||
if (ctx->dev == NULL || !mmu->secured)
|
||||
if (!ctx->pdev || !mmu->secured)
|
||||
return 0;
|
||||
|
||||
if (mmu->securepagetable == NULL)
|
||||
|
|
@ -2229,65 +2235,37 @@ static bool kgsl_iommu_addr_in_range(struct kgsl_pagetable *pagetable,
|
|||
return false;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
int id;
|
||||
char *name;
|
||||
} kgsl_iommu_cbs[] = {
|
||||
{ KGSL_IOMMU_CONTEXT_USER, "gfx3d_user", },
|
||||
{ KGSL_IOMMU_CONTEXT_SECURE, "gfx3d_secure" },
|
||||
{ KGSL_IOMMU_CONTEXT_SECURE, "gfx3d_secure_alt" },
|
||||
};
|
||||
|
||||
static int _kgsl_iommu_cb_probe(struct kgsl_device *device,
|
||||
struct kgsl_iommu *iommu, struct device_node *node)
|
||||
static int kgsl_iommu_probe_child(struct kgsl_device *device,
|
||||
struct device_node *parent, int id, const char *name)
|
||||
{
|
||||
struct platform_device *pdev = of_find_device_by_node(node);
|
||||
struct kgsl_iommu_context *ctx = NULL;
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
int i;
|
||||
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
|
||||
struct device_node *node = of_find_node_by_name(parent, name);
|
||||
struct platform_device *pdev;
|
||||
struct device_node *phandle;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(kgsl_iommu_cbs); i++) {
|
||||
if (!strcmp(node->name, kgsl_iommu_cbs[i].name)) {
|
||||
int id = kgsl_iommu_cbs[i].id;
|
||||
if (!node)
|
||||
return -ENOENT;
|
||||
|
||||
if (ADRENO_QUIRK(adreno_dev,
|
||||
ADRENO_QUIRK_MMU_SECURE_CB_ALT)) {
|
||||
if (!strcmp(node->name, "gfx3d_secure"))
|
||||
continue;
|
||||
} else if (!strcmp(node->name, "gfx3d_secure_alt"))
|
||||
continue;
|
||||
pdev = of_find_device_by_node(node);
|
||||
|
||||
ctx = &iommu->ctx[id];
|
||||
ctx->id = id;
|
||||
ctx->cb_num = -1;
|
||||
ctx->name = kgsl_iommu_cbs[i].name;
|
||||
iommu->ctx[id].id = id;
|
||||
iommu->ctx[id].cb_num = -1;
|
||||
iommu->ctx[id].name = name;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
iommu->ctx[id].kgsldev = device;
|
||||
|
||||
if (ctx == NULL) {
|
||||
dev_info(device->dev,
|
||||
"dt: Unused context label %s\n", node->name);
|
||||
return 0;
|
||||
}
|
||||
iommu->ctx[id].pdev = pdev;
|
||||
|
||||
if (ctx->id == KGSL_IOMMU_CONTEXT_SECURE)
|
||||
device->mmu.secured = true;
|
||||
phandle = of_parse_phandle(node, "iommus", 0);
|
||||
|
||||
ctx->kgsldev = device;
|
||||
if (phandle && of_device_is_compatible(phandle, "qcom,qsmmu-v500"))
|
||||
device->mmu.subtype = KGSL_IOMMU_SMMU_V500;
|
||||
|
||||
/* arm-smmu driver we'll have the right device pointer here. */
|
||||
if (of_find_property(node, "iommus", NULL)) {
|
||||
ctx->dev = &pdev->dev;
|
||||
} else {
|
||||
ctx->dev = kgsl_mmu_get_ctx(ctx->name);
|
||||
of_node_put(phandle);
|
||||
|
||||
if (IS_ERR(ctx->dev))
|
||||
return PTR_ERR(ctx->dev);
|
||||
}
|
||||
of_dma_configure(&pdev->dev, node, true);
|
||||
|
||||
of_dma_configure(ctx->dev, node, true);
|
||||
of_node_put(node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2305,13 +2283,15 @@ static int _kgsl_iommu_probe(struct kgsl_device *device,
|
|||
const char *cname;
|
||||
struct property *prop;
|
||||
u32 reg_val[2];
|
||||
int i = 0;
|
||||
int i = 0, ret;
|
||||
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
|
||||
struct device_node *child, *iommu_node = NULL;
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
struct platform_device *pdev = of_find_device_by_node(node);
|
||||
|
||||
memset(iommu, 0, sizeof(*iommu));
|
||||
|
||||
iommu->pdev = pdev;
|
||||
|
||||
if (of_property_read_u32_array(node, "reg", reg_val, 2)) {
|
||||
dev_err(device->dev,
|
||||
"dt: Unable to read KGSL IOMMU register range\n");
|
||||
|
|
@ -2326,10 +2306,12 @@ static int _kgsl_iommu_probe(struct kgsl_device *device,
|
|||
if (IS_ERR(c)) {
|
||||
dev_err(device->dev,
|
||||
"dt: Couldn't get clock: %s\n", cname);
|
||||
platform_device_put(pdev);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (i >= KGSL_IOMMU_MAX_CLKS) {
|
||||
dev_err(device->dev, "dt: too many clocks defined.\n");
|
||||
platform_device_put(pdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2345,25 +2327,28 @@ static int _kgsl_iommu_probe(struct kgsl_device *device,
|
|||
/* Fill out the rest of the devices in the node */
|
||||
of_platform_populate(node, NULL, NULL, &pdev->dev);
|
||||
|
||||
for_each_child_of_node(node, child) {
|
||||
int ret;
|
||||
/* The "user" device always needs to be present */
|
||||
ret = kgsl_iommu_probe_child(device, node, KGSL_IOMMU_CONTEXT_USER,
|
||||
"gfx3d_user");
|
||||
|
||||
if (!of_device_is_compatible(child, "qcom,smmu-kgsl-cb"))
|
||||
continue;
|
||||
if (!ret && device->mmu.secured) {
|
||||
const char *name = "gfx3d_secure";
|
||||
|
||||
ret = _kgsl_iommu_cb_probe(device, iommu, child);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_MMU_SECURE_CB_ALT))
|
||||
name = "gfx3d_secure_alt";
|
||||
|
||||
if (!iommu_node)
|
||||
iommu_node = of_parse_phandle(child, "iommus", 0);
|
||||
/* Secure context bank devices are optional */
|
||||
if (kgsl_iommu_probe_child(device, node,
|
||||
KGSL_IOMMU_CONTEXT_SECURE, name))
|
||||
device->mmu.secured = false;
|
||||
}
|
||||
|
||||
if (iommu_node &&
|
||||
of_device_is_compatible(iommu_node, "qcom,qsmmu-v500"))
|
||||
device->mmu.subtype = KGSL_IOMMU_SMMU_V500;
|
||||
if (ret) {
|
||||
of_platform_depopulate(&pdev->dev);
|
||||
platform_device_put(pdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ enum kgsl_iommu_context_id {
|
|||
/*
|
||||
* struct kgsl_iommu_context - Structure holding data about an iommu context
|
||||
* bank
|
||||
* @dev: pointer to the iommu context's device
|
||||
* @pdev: pointer to the iommu context's platform device
|
||||
* @name: context name
|
||||
* @id: The id of the context, used for deciding how it is used.
|
||||
* @cb_num: The hardware context bank number, used for calculating register
|
||||
|
|
@ -92,7 +92,7 @@ enum kgsl_iommu_context_id {
|
|||
* it may be changed by self programming.
|
||||
*/
|
||||
struct kgsl_iommu_context {
|
||||
struct device *dev;
|
||||
struct platform_device *pdev;
|
||||
const char *name;
|
||||
enum kgsl_iommu_context_id id;
|
||||
unsigned int cb_num;
|
||||
|
|
@ -122,6 +122,8 @@ struct kgsl_iommu {
|
|||
atomic_t clk_enable_count;
|
||||
struct clk *clks[KGSL_IOMMU_MAX_CLKS];
|
||||
struct kgsl_memdesc *smmu_info;
|
||||
/** @pdev: Pointer to the platform device for the IOMMU device */
|
||||
struct platform_device *pdev;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -344,9 +344,4 @@ kgsl_mmu_pagetable_get_contextidr(struct kgsl_pagetable *pagetable)
|
|||
*/
|
||||
u64 kgsl_mmu_get_global_base(struct kgsl_device *device);
|
||||
|
||||
static inline struct device *kgsl_mmu_get_ctx(const char *name)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
#endif /* __KGSL_MMU_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue