coresight: Appropriately disable trace bus clocks

Some CoreSight components have trace bus clocks 'atclk' and are enabled
using clk_prepare_enable().  These clocks are not disabled when modules
exit.

As atclk is optional, use devm_clk_get_optional_enabled() to manage it.
The benefit is the driver model layer can automatically disable and
release clocks.

Check the returned value with IS_ERR() to detect errors but leave the
NULL pointer case if the clock is not found.  And remove the error
handling codes which are no longer needed.

Fixes: d1839e6877 ("coresight: etm: retrieve and handle atclk")
Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
Reviewed-by: Yeoreum Yun <yeoreum.yun@arm.com>
Tested-by: James Clark <james.clark@linaro.org>
Signed-off-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20250731-arm_cs_fix_clock_v4-v6-5-1dfe10bb3f6f@arm.com
This commit is contained in:
Leo Yan 2025-07-31 13:23:41 +01:00 committed by Suzuki K Poulose
parent 1abc1b212e
commit a8f2d480f1
6 changed files with 34 additions and 74 deletions

View File

@ -730,12 +730,10 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
if (!drvdata)
return -ENOMEM;
drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
if (!IS_ERR(drvdata->atclk)) {
ret = clk_prepare_enable(drvdata->atclk);
if (ret)
return ret;
}
drvdata->atclk = devm_clk_get_optional_enabled(dev, "atclk");
if (IS_ERR(drvdata->atclk))
return PTR_ERR(drvdata->atclk);
dev_set_drvdata(dev, drvdata);
/* validity for the resource is already checked by the AMBA core */

View File

@ -832,12 +832,9 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&drvdata->spinlock);
drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
if (!IS_ERR(drvdata->atclk)) {
ret = clk_prepare_enable(drvdata->atclk);
if (ret)
return ret;
}
drvdata->atclk = devm_clk_get_optional_enabled(dev, "atclk");
if (IS_ERR(drvdata->atclk))
return PTR_ERR(drvdata->atclk);
drvdata->cpu = coresight_get_cpu(dev);
if (drvdata->cpu < 0)

View File

@ -213,7 +213,6 @@ ATTRIBUTE_GROUPS(coresight_funnel);
static int funnel_probe(struct device *dev, struct resource *res)
{
int ret;
void __iomem *base;
struct coresight_platform_data *pdata = NULL;
struct funnel_drvdata *drvdata;
@ -231,12 +230,9 @@ static int funnel_probe(struct device *dev, struct resource *res)
if (!drvdata)
return -ENOMEM;
drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */
if (!IS_ERR(drvdata->atclk)) {
ret = clk_prepare_enable(drvdata->atclk);
if (ret)
return ret;
}
drvdata->atclk = devm_clk_get_optional_enabled(dev, "atclk");
if (IS_ERR(drvdata->atclk))
return PTR_ERR(drvdata->atclk);
drvdata->pclk = coresight_get_enable_apb_pclk(dev);
if (IS_ERR(drvdata->pclk))
@ -248,10 +244,8 @@ static int funnel_probe(struct device *dev, struct resource *res)
*/
if (res) {
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base)) {
ret = PTR_ERR(base);
goto out_disable_clk;
}
if (IS_ERR(base))
return PTR_ERR(base);
drvdata->base = base;
desc.groups = coresight_funnel_groups;
desc.access = CSDEV_ACCESS_IOMEM(base);
@ -261,10 +255,9 @@ static int funnel_probe(struct device *dev, struct resource *res)
dev_set_drvdata(dev, drvdata);
pdata = coresight_get_platform_data(dev);
if (IS_ERR(pdata)) {
ret = PTR_ERR(pdata);
goto out_disable_clk;
}
if (IS_ERR(pdata))
return PTR_ERR(pdata);
dev->platform_data = pdata;
raw_spin_lock_init(&drvdata->spinlock);
@ -274,17 +267,10 @@ static int funnel_probe(struct device *dev, struct resource *res)
desc.pdata = pdata;
desc.dev = dev;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
goto out_disable_clk;
}
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
ret = 0;
out_disable_clk:
if (ret && !IS_ERR_OR_NULL(drvdata->atclk))
clk_disable_unprepare(drvdata->atclk);
return ret;
return 0;
}
static int funnel_remove(struct device *dev)

View File

@ -219,7 +219,6 @@ static const struct attribute_group *replicator_groups[] = {
static int replicator_probe(struct device *dev, struct resource *res)
{
int ret = 0;
struct coresight_platform_data *pdata = NULL;
struct replicator_drvdata *drvdata;
struct coresight_desc desc = { 0 };
@ -238,12 +237,9 @@ static int replicator_probe(struct device *dev, struct resource *res)
if (!drvdata)
return -ENOMEM;
drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */
if (!IS_ERR(drvdata->atclk)) {
ret = clk_prepare_enable(drvdata->atclk);
if (ret)
return ret;
}
drvdata->atclk = devm_clk_get_optional_enabled(dev, "atclk");
if (IS_ERR(drvdata->atclk))
return PTR_ERR(drvdata->atclk);
drvdata->pclk = coresight_get_enable_apb_pclk(dev);
if (IS_ERR(drvdata->pclk))
@ -255,10 +251,8 @@ static int replicator_probe(struct device *dev, struct resource *res)
*/
if (res) {
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base)) {
ret = PTR_ERR(base);
goto out_disable_clk;
}
if (IS_ERR(base))
return PTR_ERR(base);
drvdata->base = base;
desc.groups = replicator_groups;
desc.access = CSDEV_ACCESS_IOMEM(base);
@ -272,10 +266,8 @@ static int replicator_probe(struct device *dev, struct resource *res)
dev_set_drvdata(dev, drvdata);
pdata = coresight_get_platform_data(dev);
if (IS_ERR(pdata)) {
ret = PTR_ERR(pdata);
goto out_disable_clk;
}
if (IS_ERR(pdata))
return PTR_ERR(pdata);
dev->platform_data = pdata;
raw_spin_lock_init(&drvdata->spinlock);
@ -286,17 +278,11 @@ static int replicator_probe(struct device *dev, struct resource *res)
desc.dev = dev;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
goto out_disable_clk;
}
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
replicator_reset(drvdata);
out_disable_clk:
if (ret && !IS_ERR_OR_NULL(drvdata->atclk))
clk_disable_unprepare(drvdata->atclk);
return ret;
return 0;
}
static int replicator_remove(struct device *dev)

View File

@ -842,12 +842,9 @@ static int __stm_probe(struct device *dev, struct resource *res)
if (!drvdata)
return -ENOMEM;
drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */
if (!IS_ERR(drvdata->atclk)) {
ret = clk_prepare_enable(drvdata->atclk);
if (ret)
return ret;
}
drvdata->atclk = devm_clk_get_optional_enabled(dev, "atclk");
if (IS_ERR(drvdata->atclk))
return PTR_ERR(drvdata->atclk);
drvdata->pclk = coresight_get_enable_apb_pclk(dev);
if (IS_ERR(drvdata->pclk))

View File

@ -128,7 +128,6 @@ static const struct coresight_ops tpiu_cs_ops = {
static int __tpiu_probe(struct device *dev, struct resource *res)
{
int ret;
void __iomem *base;
struct coresight_platform_data *pdata = NULL;
struct tpiu_drvdata *drvdata;
@ -144,12 +143,9 @@ static int __tpiu_probe(struct device *dev, struct resource *res)
spin_lock_init(&drvdata->spinlock);
drvdata->atclk = devm_clk_get(dev, "atclk"); /* optional */
if (!IS_ERR(drvdata->atclk)) {
ret = clk_prepare_enable(drvdata->atclk);
if (ret)
return ret;
}
drvdata->atclk = devm_clk_get_optional_enabled(dev, "atclk");
if (IS_ERR(drvdata->atclk))
return PTR_ERR(drvdata->atclk);
drvdata->pclk = coresight_get_enable_apb_pclk(dev);
if (IS_ERR(drvdata->pclk))