From c7ae23947d1afdfdccf282cd4199b1dde285df2d Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Tue, 25 Feb 2020 13:33:13 -0700 Subject: [PATCH 1/2] msm: kgsl: Minor cleanups for kgsl bus probe The KGSL bus probe was not quite resilient for a deferred probe. Move a memory allocation to devm and make sure that the interconnect handle is properly put away on failure. Change-Id: Ic0dedbad261c483a157161a43da0b54459ed46ff Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.c | 28 ++++++++++++++-------------- drivers/gpu/msm/kgsl_bus.c | 9 ++------- drivers/gpu/msm/kgsl_gmu.c | 6 +++--- drivers/gpu/msm/kgsl_rgmu.c | 9 ++++++++- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 844870daac37..fccb227e2bc3 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1462,10 +1462,8 @@ static int adreno_probe(struct platform_device *pdev) } status = kgsl_bus_init(device, pdev); - if (status) { - device->pdev = NULL; - return status; - } + if (status) + goto err; /* * Probe/init GMU after initial gpu power probe @@ -1473,10 +1471,8 @@ static int adreno_probe(struct platform_device *pdev) * needs GMU initialized. */ status = gmu_core_probe(device); - if (status) { - device->pdev = NULL; - return status; - } + if (status) + goto err; /* * The SMMU APIs use unsigned long for virtual addresses which means @@ -1492,10 +1488,8 @@ static int adreno_probe(struct platform_device *pdev) ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)); status = kgsl_device_platform_probe(device); - if (status) { - device->pdev = NULL; - return status; - } + if (status) + goto err; /* Probe for the optional CX_DBGC block */ adreno_cx_dbgc_probe(device); @@ -1521,8 +1515,7 @@ static int adreno_probe(struct platform_device *pdev) status = PTR_ERR_OR_ZERO(device->memstore); if (status) { kgsl_device_platform_remove(device); - device->pdev = NULL; - return status; + goto err; } /* Initialize the snapshot engine */ @@ -1580,6 +1573,13 @@ static int adreno_probe(struct platform_device *pdev) #endif return 0; +err: + device->pdev = NULL; + + gmu_core_remove(device); + kgsl_bus_close(device); + + return status; } static void _adreno_free_memories(struct adreno_device *adreno_dev) diff --git a/drivers/gpu/msm/kgsl_bus.c b/drivers/gpu/msm/kgsl_bus.c index bddf3de31e97..d50e3e916da8 100644 --- a/drivers/gpu/msm/kgsl_bus.c +++ b/drivers/gpu/msm/kgsl_bus.c @@ -118,7 +118,7 @@ u32 *kgsl_bus_get_table(struct platform_device *pdev, if (num <= 0) return ERR_PTR(-EINVAL); - levels = kcalloc(num, sizeof(*levels), GFP_KERNEL); + levels = devm_kcalloc(&pdev->dev, num, sizeof(*levels), GFP_KERNEL); if (!levels) return ERR_PTR(-ENOMEM); @@ -172,10 +172,5 @@ done: void kgsl_bus_close(struct kgsl_device *device) { - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - - kfree(pwr->ddr_table); - - /* FIXME: Make sure icc put can handle NULL or IS_ERR */ - icc_put(pwr->icc_path); + icc_put(device->pwrctrl.icc_path); } diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index 13432796a4a3..3920ad43a359 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -945,7 +945,7 @@ static int gmu_bus_vote_init(struct kgsl_device *device) if (count > 0) cnoc = build_rpmh_bw_votes(a660_cnoc_bcms, ARRAY_SIZE(a660_cnoc_bcms), cnoc_table, count); - kfree(cnoc_table); + devm_kfree(&device->pdev->dev, cnoc_table); if (IS_ERR(cnoc)) { free_rpmh_bw_votes(ddr); @@ -1746,8 +1746,8 @@ static void gmu_remove(struct kgsl_device *device) gmu->cx_gdsc = NULL; } - device->gmu_core.flags = 0; - device->gmu_core.ptr = NULL; + memset(&device->gmu_core, 0, sizeof(device->gmu_core)); + gmu->pdev = NULL; kfree(gmu); } diff --git a/drivers/gpu/msm/kgsl_rgmu.c b/drivers/gpu/msm/kgsl_rgmu.c index 40d5d8af0adb..0cc78e3ce50e 100644 --- a/drivers/gpu/msm/kgsl_rgmu.c +++ b/drivers/gpu/msm/kgsl_rgmu.c @@ -447,9 +447,16 @@ static bool rgmu_regulator_isenabled(struct kgsl_device *device) return (rgmu->gx_gdsc && regulator_is_enabled(rgmu->gx_gdsc)); } +static void rgmu_remove(struct kgsl_device *device) +{ + rgmu_stop(device); + + memset(&device->gmu_core, 0, sizeof(device->gmu_core)); +} + struct gmu_core_ops rgmu_ops = { .probe = rgmu_probe, - .remove = rgmu_stop, + .remove = rgmu_remove, .init = rgmu_init, .start = rgmu_start, .stop = rgmu_stop, From 0c46c9a35b89b9ae9b3b29c61c490c8cbcc28a95 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 24 Feb 2020 12:26:23 -0700 Subject: [PATCH 2/2] msm: kgsl: Move GMU to a component device Traditionally the GMU/RGMU device has been a child of the adreno device and probed manually. That has worked despite the fact that the GMU/RGMU device has resources of its own and it really should be a top level platform device. Finally do the right thing, make GMU a top level platform device and driver and bind it to Adreno as a component. This will make sure we get the advantages of all of the platform level initialization without having to code in half a dozen hacks to make everything work and then break again next kernel version. Change-Id: Ic0dedbadf6776e1a4f5e0eb1e093241e5103b3ff Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.c | 86 ++++++++++++++++++++++----- drivers/gpu/msm/kgsl.c | 2 - drivers/gpu/msm/kgsl_gmu.c | 100 ++++++++++++++++++++------------ drivers/gpu/msm/kgsl_gmu_core.c | 67 ++++++++------------- drivers/gpu/msm/kgsl_gmu_core.h | 21 ++----- drivers/gpu/msm/kgsl_rgmu.c | 61 ++++++++++++++++--- 6 files changed, 217 insertions(+), 120 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index fccb227e2bc3..203521d9ce7c 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. */ +#include #include #include #include @@ -1415,8 +1416,9 @@ static void adreno_setup_device(struct adreno_device *adreno_dev) } } -static int adreno_probe(struct platform_device *pdev) +static int adreno_bind(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); const struct of_device_id *of_id; struct adreno_device *adreno_dev; struct kgsl_device *device; @@ -1435,6 +1437,8 @@ static int adreno_probe(struct platform_device *pdev) device = KGSL_DEVICE(adreno_dev); + dev_set_drvdata(dev, device); + device->pdev = pdev; if (adreno_is_gpu_disabled(adreno_dev)) { @@ -1466,13 +1470,14 @@ static int adreno_probe(struct platform_device *pdev) goto err; /* - * Probe/init GMU after initial gpu power probe - * Another part of GPU power probe in platform_probe - * needs GMU initialized. + * Bind the GMU components (if applicable) before doing the KGSL + * platform probe */ - status = gmu_core_probe(device); - if (status) - goto err; + status = component_bind_all(dev, NULL); + if (status) { + kgsl_bus_close(device); + return status; + } /* * The SMMU APIs use unsigned long for virtual addresses which means @@ -1576,7 +1581,7 @@ static int adreno_probe(struct platform_device *pdev) err: device->pdev = NULL; - gmu_core_remove(device); + component_unbind_all(dev, NULL); kgsl_bus_close(device); return status; @@ -1598,8 +1603,9 @@ static void _adreno_free_memories(struct adreno_device *adreno_dev) adreno_dev->gpmu_cmds = NULL; } -static int adreno_remove(struct platform_device *pdev) +static void adreno_unbind(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); const struct of_device_id *of_id; struct adreno_device *adreno_dev; struct kgsl_device *device; @@ -1607,7 +1613,7 @@ static int adreno_remove(struct platform_device *pdev) of_id = of_match_device(adreno_match_table, &pdev->dev); if (!of_id) - return -EINVAL; + return; adreno_dev = (struct adreno_device *) of_id->data; device = KGSL_DEVICE(adreno_dev); @@ -1653,12 +1659,10 @@ static int adreno_remove(struct platform_device *pdev) kgsl_device_platform_remove(device); - gmu_core_remove(device); + component_unbind_all(dev, NULL); clear_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv); clear_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv); - - return 0; } static int adreno_pm_resume(struct device *dev) @@ -3882,6 +3886,60 @@ static const struct kgsl_functable adreno_functable = { .is_hwcg_on = adreno_is_hwcg_on, }; +static const struct component_master_ops adreno_ops = { + .bind = adreno_bind, + .unbind = adreno_unbind, +}; + +static const struct of_device_id adreno_gmu_match[] = { + { .compatible = "qcom,gpu-gmu" }, + { .compatible = "qcom,gpu-rgmu" }, + {}, +}; + +static int _compare_of(struct device *dev, void *data) +{ + return (dev->of_node == data); +} + +static void _release_of(struct device *dev, void *data) +{ + of_node_put(data); +} + +static void adreno_add_gmu_components(struct device *dev, + struct component_match **match) +{ + struct device_node *node; + + node = of_find_matching_node(NULL, adreno_gmu_match); + if (!node) + return; + + if (!of_device_is_available(node)) { + of_node_put(node); + return; + } + + component_match_add_release(dev, match, _release_of, + _compare_of, node); +} + +static int adreno_probe(struct platform_device *pdev) +{ + struct component_match *match = NULL; + + adreno_add_gmu_components(&pdev->dev, &match); + + return component_master_add_with_match(&pdev->dev, &adreno_ops, match); +} + +static int adreno_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &adreno_ops); + return 0; +} + static const struct dev_pm_ops adreno_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(adreno_pm_suspend, adreno_pm_resume) }; @@ -3905,6 +3963,7 @@ static int __init kgsl_3d_init(void) if (ret) return ret; + gmu_core_register(); ret = platform_driver_register(&adreno_platform_driver); if (ret) kgsl_core_exit(); @@ -3915,6 +3974,7 @@ static int __init kgsl_3d_init(void) static void __exit kgsl_3d_exit(void) { platform_driver_unregister(&adreno_platform_driver); + gmu_core_unregister(); kgsl_core_exit(); } diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index c24713fc3833..694ceda008c8 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -4776,8 +4776,6 @@ static int _register_device(struct kgsl_device *device) device->dev->dma_mask = &dma_mask; set_dma_ops(device->dev, NULL); - - dev_set_drvdata(&device->pdev->dev, device); return 0; } diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index 3920ad43a359..a5d5a86cd5df 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -1296,8 +1297,9 @@ static int gmu_bus_set(struct kgsl_device *device, int buslevel, return ret; } -/* Do not access any GMU registers in GMU probe function */ -static int gmu_probe(struct kgsl_device *device, struct device_node *node) +static struct gmu_core_ops gmu_ops; + +static int gmu_probe(struct kgsl_device *device, struct platform_device *pdev) { struct gmu_device *gmu; struct kgsl_hfi *hfi; @@ -1305,35 +1307,28 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i = 0, ret = -ENXIO, index; - gmu = kzalloc(sizeof(struct gmu_device), GFP_KERNEL); - - if (gmu == NULL) + gmu = devm_kzalloc(&pdev->dev, sizeof(*gmu), GFP_KERNEL); + if (!gmu) return -ENOMEM; - gmu->pdev = of_find_device_by_node(node); - if (!gmu->pdev) { - kfree(gmu); - return -EINVAL; - } + gmu->pdev = pdev; device->gmu_core.ptr = (void *)gmu; hfi = &gmu->hfi; gmu->load_mode = TCM_BOOT; - of_dma_configure(&gmu->pdev->dev, node, true); - dma_set_coherent_mask(&gmu->pdev->dev, DMA_BIT_MASK(64)); gmu->pdev->dev.dma_mask = &gmu->pdev->dev.coherent_dma_mask; set_dma_ops(&gmu->pdev->dev, NULL); /* Set up GMU regulators */ - ret = gmu_regulators_probe(gmu, node); + ret = gmu_regulators_probe(gmu, pdev->dev.of_node); if (ret) - goto error; + return ret; ret = devm_clk_bulk_get_all(&gmu->pdev->dev, &gmu->clks); if (ret < 0) - goto error; + return ret; gmu->num_clks = ret; @@ -1341,12 +1336,11 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) gmu->gmu_clk = kgsl_of_clk_by_name(gmu->clks, gmu->num_clks, "gmu_clk"); if (!gmu->gmu_clk) { dev_err(&gmu->pdev->dev, "Couldn't get gmu_clk\n"); - ret = -ENODEV; - goto error; + return -ENODEV; } /* Set up GMU IOMMU and shared memory with GMU */ - ret = gmu_iommu_init(gmu, node); + ret = gmu_iommu_init(gmu, pdev->dev.of_node); if (ret) goto error; @@ -1421,12 +1415,14 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node) else gmu->idle_level = GPU_HW_ACTIVE; - gmu_acd_probe(device, gmu, node); + gmu_acd_probe(device, gmu, pdev->dev.of_node); if (gmu_core_scales_bandwidth(device)) pwr->bus_set = gmu_bus_set; set_bit(GMU_ENABLED, &device->gmu_core.flags); + + device->gmu_core.core_ops = &gmu_ops; device->gmu_core.dev_ops = &adreno_a6xx_gmudev; return 0; @@ -1729,27 +1725,12 @@ static void gmu_remove(struct kgsl_device *device) clear_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag); - if (gmu->fw_image) { + if (gmu->fw_image) release_firmware(gmu->fw_image); - gmu->fw_image = NULL; - } gmu_memory_close(gmu); - if (gmu->gx_gdsc) { - devm_regulator_put(gmu->gx_gdsc); - gmu->gx_gdsc = NULL; - } - - if (gmu->cx_gdsc) { - devm_regulator_put(gmu->cx_gdsc); - gmu->cx_gdsc = NULL; - } - memset(&device->gmu_core, 0, sizeof(device->gmu_core)); - - gmu->pdev = NULL; - kfree(gmu); } static bool gmu_regulator_isenabled(struct kgsl_device *device) @@ -1759,9 +1740,7 @@ static bool gmu_regulator_isenabled(struct kgsl_device *device) return (gmu->gx_gdsc && regulator_is_enabled(gmu->gx_gdsc)); } -struct gmu_core_ops gmu_ops = { - .probe = gmu_probe, - .remove = gmu_remove, +static struct gmu_core_ops gmu_ops = { .init = gmu_init, .start = gmu_start, .stop = gmu_stop, @@ -1771,3 +1750,48 @@ struct gmu_core_ops gmu_ops = { .suspend = gmu_suspend, .acd_set = gmu_acd_set, }; + +static int kgsl_gmu_bind(struct device *dev, struct device *master, void *data) +{ + struct kgsl_device *device = dev_get_drvdata(master); + + return gmu_probe(device, to_platform_device(dev)); +} + +static void kgsl_gmu_unbind(struct device *dev, struct device *master, + void *data) +{ + struct kgsl_device *device = dev_get_drvdata(master); + + gmu_remove(device); +} + +static const struct component_ops kgsl_gmu_ops = { + .bind = kgsl_gmu_bind, + .unbind = kgsl_gmu_unbind, +}; + +static int kgsl_gmu_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &kgsl_gmu_ops); +} + +static int kgsl_gmu_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &kgsl_gmu_ops); + return 0; +} + +static const struct of_device_id kgsl_gmu_match_table[] = { + { .compatible = "qcom,gpu-gmu" }, + { }, +}; + +struct platform_driver kgsl_gmu_driver = { + .probe = kgsl_gmu_probe, + .remove = kgsl_gmu_remove, + .driver = { + .name = "kgsl-gmu", + .of_match_table = kgsl_gmu_match_table, + }, +}; diff --git a/drivers/gpu/msm/kgsl_gmu_core.c b/drivers/gpu/msm/kgsl_gmu_core.c index 441a996c1f16..81414d8ae594 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.c +++ b/drivers/gpu/msm/kgsl_gmu_core.c @@ -10,13 +10,10 @@ #include "kgsl_gmu_core.h" #include "kgsl_trace.h" -static const struct { - char *compat; - struct gmu_core_ops *core_ops; - enum gmu_coretype type; -} gmu_subtypes[] = { - {"qcom,gpu-gmu", &gmu_ops, GMU_CORE_TYPE_CM3}, - {"qcom,gpu-rgmu", &rgmu_ops, GMU_CORE_TYPE_PCC}, +static const struct of_device_id gmu_match_table[] = { + { .compatible = "qcom,gpu-gmu", .data = &kgsl_gmu_driver }, + { .compatible = "qcom,gpu-rgmu", .data = &kgsl_rgmu_driver }, + {}, }; struct oob_entry { @@ -40,50 +37,32 @@ const char *gmu_core_oob_type_str(enum oob_request req) return "UNKNOWN"; } -int gmu_core_probe(struct kgsl_device *device) +void __init gmu_core_register(void) { + const struct of_device_id *match; struct device_node *node; - struct gmu_core_ops *gmu_core_ops; - int i = 0, ret = -ENXIO; - device->gmu_core.flags = ADRENO_FEATURE(ADRENO_DEVICE(device), - ADRENO_GPMU) ? BIT(GMU_GPMU) : 0; + node = of_find_matching_node_and_match(NULL, gmu_match_table, + &match); + if (!node) + return; - for (i = 0; i < ARRAY_SIZE(gmu_subtypes); i++) { - node = of_find_compatible_node(device->pdev->dev.of_node, - NULL, gmu_subtypes[i].compat); - - if (node != NULL) { - gmu_core_ops = gmu_subtypes[i].core_ops; - device->gmu_core.type = gmu_subtypes[i].type; - break; - } - } - - /* No GMU in dt, no worries...hopefully */ - if (node == NULL) { - /* If we are trying to use GPMU and no GMU, that's bad */ - if (device->gmu_core.flags & BIT(GMU_GPMU)) - return ret; - /* Otherwise it's ok and nothing to do */ - return 0; - } - - if (gmu_core_ops && gmu_core_ops->probe) { - ret = gmu_core_ops->probe(device, node); - if (ret == 0) - device->gmu_core.core_ops = gmu_core_ops; - } - - return ret; + platform_driver_register((struct platform_driver *) match->data); + of_node_put(node); } -void gmu_core_remove(struct kgsl_device *device) +void __exit gmu_core_unregister(void) { - struct gmu_core_ops *gmu_core_ops = GMU_CORE_OPS(device); + const struct of_device_id *match; + struct device_node *node; - if (gmu_core_ops && gmu_core_ops->remove) - gmu_core_ops->remove(device); + node = of_find_matching_node_and_match(NULL, gmu_match_table, + &match); + if (!node) + return; + + platform_driver_unregister((struct platform_driver *) match->data); + of_node_put(node); } bool gmu_core_isenabled(struct kgsl_device *device) @@ -93,7 +72,7 @@ bool gmu_core_isenabled(struct kgsl_device *device) bool gmu_core_gpmu_isenabled(struct kgsl_device *device) { - return test_bit(GMU_GPMU, &device->gmu_core.flags); + return (device->gmu_core.core_ops != NULL); } bool gmu_core_scales_bandwidth(struct kgsl_device *device) diff --git a/drivers/gpu/msm/kgsl_gmu_core.h b/drivers/gpu/msm/kgsl_gmu_core.h index 8c231650cf52..45280614dc9f 100644 --- a/drivers/gpu/msm/kgsl_gmu_core.h +++ b/drivers/gpu/msm/kgsl_gmu_core.h @@ -39,18 +39,10 @@ enum gmu_core_flags { GMU_HFI_ON, GMU_FAULT, GMU_DCVS_REPLAY, - GMU_GPMU, GMU_ENABLED, GMU_RSCC_SLEEP_SEQ_DONE, }; -/* GMU Types */ -enum gmu_coretype { - GMU_CORE_TYPE_CM3 = 1, /* Cortex M3 core */ - GMU_CORE_TYPE_PCC = 2, /* Power collapsible controller */ - GMU_CORE_TYPE_NONE, /* No GMU */ -}; - /* * OOB requests values. These range from 0 to 7 and then * the BIT() offset into the actual value is calculated @@ -109,8 +101,6 @@ struct kgsl_device; struct kgsl_snapshot; struct gmu_core_ops { - int (*probe)(struct kgsl_device *device, struct device_node *node); - void (*remove)(struct kgsl_device *device); int (*dcvs_set)(struct kgsl_device *device, int gpu_pwrlevel, int bus_level); int (*init)(struct kgsl_device *device); @@ -169,15 +159,16 @@ struct gmu_core_device { struct gmu_core_ops *core_ops; struct gmu_dev_ops *dev_ops; unsigned long flags; - enum gmu_coretype type; }; -extern struct gmu_core_ops gmu_ops; -extern struct gmu_core_ops rgmu_ops; +extern struct platform_driver kgsl_gmu_driver; +extern struct platform_driver kgsl_rgmu_driver; /* GMU core functions */ -int gmu_core_probe(struct kgsl_device *device); -void gmu_core_remove(struct kgsl_device *device); + +void __init gmu_core_register(void); +void __exit gmu_core_unregister(void); + int gmu_core_init(struct kgsl_device *device); int gmu_core_start(struct kgsl_device *device); void gmu_core_stop(struct kgsl_device *device); diff --git a/drivers/gpu/msm/kgsl_rgmu.c b/drivers/gpu/msm/kgsl_rgmu.c index 0cc78e3ce50e..008589ddae3f 100644 --- a/drivers/gpu/msm/kgsl_rgmu.c +++ b/drivers/gpu/msm/kgsl_rgmu.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -271,11 +272,12 @@ error: rgmu_snapshot(device); } +static struct gmu_core_ops rgmu_ops; + /* Do not access any RGMU registers in RGMU probe function */ -static int rgmu_probe(struct kgsl_device *device, struct device_node *node) +static int rgmu_probe(struct kgsl_device *device, struct platform_device *pdev) { struct rgmu_device *rgmu; - struct platform_device *pdev = of_find_device_by_node(node); struct resource *res; int ret = -ENXIO; @@ -287,12 +289,11 @@ static int rgmu_probe(struct kgsl_device *device, struct device_node *node) rgmu->pdev = pdev; /* Set up RGMU regulators */ - ret = rgmu_regulators_probe(rgmu, node); + ret = rgmu_regulators_probe(rgmu, pdev->dev.of_node); if (ret) return ret; - /* Set up RGMU clocks */ - ret = rgmu_clocks_probe(rgmu, node); + ret = rgmu_clocks_probe(rgmu, pdev->dev.of_node); if (ret) return ret; @@ -343,6 +344,7 @@ static int rgmu_probe(struct kgsl_device *device, struct device_node *node) rgmu->idle_level = GPU_HW_ACTIVE; set_bit(GMU_ENABLED, &device->gmu_core.flags); + device->gmu_core.core_ops = &rgmu_ops; device->gmu_core.dev_ops = &adreno_a6xx_rgmudev; return 0; @@ -454,9 +456,7 @@ static void rgmu_remove(struct kgsl_device *device) memset(&device->gmu_core, 0, sizeof(device->gmu_core)); } -struct gmu_core_ops rgmu_ops = { - .probe = rgmu_probe, - .remove = rgmu_remove, +static struct gmu_core_ops rgmu_ops = { .init = rgmu_init, .start = rgmu_start, .stop = rgmu_stop, @@ -465,3 +465,48 @@ struct gmu_core_ops rgmu_ops = { .regulator_isenabled = rgmu_regulator_isenabled, .suspend = rgmu_suspend, }; + +static int kgsl_rgmu_bind(struct device *dev, struct device *master, void *data) +{ + struct kgsl_device *device = dev_get_drvdata(master); + + return rgmu_probe(device, to_platform_device(dev)); +} + +static void kgsl_rgmu_unbind(struct device *dev, struct device *master, + void *data) +{ + struct kgsl_device *device = dev_get_drvdata(master); + + rgmu_remove(device); +} + +static const struct component_ops kgsl_rgmu_ops = { + .bind = kgsl_rgmu_bind, + .unbind = kgsl_rgmu_unbind, +}; + +static int kgsl_rgmu_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &kgsl_rgmu_ops); +} + +static int kgsl_rgmu_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &kgsl_rgmu_ops); + return 0; +} + +static const struct of_device_id kgsl_rgmu_match_table[] = { + { .compatible = "qcom,gpu-rgmu" }, + { }, +}; + +struct platform_driver kgsl_rgmu_driver = { + .probe = kgsl_rgmu_probe, + .remove = kgsl_rgmu_remove, + .driver = { + .name = "kgsl-rgmu", + .of_match_table = kgsl_rgmu_match_table, + }, +};