Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

coresight: tmc: Support atclk

The atclk is an optional clock for the CoreSight TMC, but the driver
misses to initialize it. In most cases, TMC shares the atclk clock with
other CoreSight components. Since these components enable the clock
before the TMC device is initialized, the TMC continues properly,
which is why we don’t observe any lockup issues.

This change enables atclk in probe of the TMC driver. Given the clock
is optional, it is possible to return NULL if the clock does not exist.
IS_ERR() is tolerant for this case.

Dynamically disable and enable atclk during suspend and resume. The
clock pointers will never be error values if the driver has successfully
probed, and the case of a NULL pointer case will be handled by the clock
core layer. The driver data is always valid after probe. Therefore,
remove the related checks. Also in the resume flow adds error handling.

Fixes: bc4bf7fe98da ("coresight-tmc: add CoreSight TMC driver")
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-1-1dfe10bb3f6f@arm.com

authored by

Leo Yan and committed by
Suzuki K Poulose
8a790269 dcdc42f5

+19 -5
+17 -5
drivers/hwtracing/coresight/coresight-tmc-core.c
··· 779 779 struct coresight_desc desc = { 0 }; 780 780 struct coresight_dev_list *dev_list = NULL; 781 781 782 + drvdata->atclk = devm_clk_get_optional_enabled(dev, "atclk"); 783 + if (IS_ERR(drvdata->atclk)) 784 + return PTR_ERR(drvdata->atclk); 785 + 782 786 ret = -ENOMEM; 783 787 784 788 /* Validity for the resource is already checked by the AMBA core */ ··· 1014 1010 { 1015 1011 struct tmc_drvdata *drvdata = dev_get_drvdata(dev); 1016 1012 1017 - if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk)) 1018 - clk_disable_unprepare(drvdata->pclk); 1013 + clk_disable_unprepare(drvdata->atclk); 1014 + clk_disable_unprepare(drvdata->pclk); 1015 + 1019 1016 return 0; 1020 1017 } 1021 1018 1022 1019 static int tmc_runtime_resume(struct device *dev) 1023 1020 { 1024 1021 struct tmc_drvdata *drvdata = dev_get_drvdata(dev); 1022 + int ret; 1025 1023 1026 - if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk)) 1027 - clk_prepare_enable(drvdata->pclk); 1028 - return 0; 1024 + ret = clk_prepare_enable(drvdata->pclk); 1025 + if (ret) 1026 + return ret; 1027 + 1028 + ret = clk_prepare_enable(drvdata->atclk); 1029 + if (ret) 1030 + clk_disable_unprepare(drvdata->pclk); 1031 + 1032 + return ret; 1029 1033 } 1030 1034 #endif 1031 1035
+2
drivers/hwtracing/coresight/coresight-tmc.h
··· 210 210 211 211 /** 212 212 * struct tmc_drvdata - specifics associated to an TMC component 213 + * @atclk: optional clock for the core parts of the TMC. 213 214 * @pclk: APB clock if present, otherwise NULL 214 215 * @base: memory mapped base address for this component. 215 216 * @csdev: component vitals needed by the framework. ··· 245 244 * Used by ETR/ETF. 246 245 */ 247 246 struct tmc_drvdata { 247 + struct clk *atclk; 248 248 struct clk *pclk; 249 249 void __iomem *base; 250 250 struct coresight_device *csdev;