@@ -28,7 +28,6 @@ static const struct acpi_device_id amba_id_list[] = {
{"ARMHC979", 0}, /* ARM CoreSight TPIU */
{"ARMHC97C", 0}, /* ARM CoreSight SoC-400 TMC, SoC-600 ETF/ETB */
{"ARMHC9CA", 0}, /* ARM CoreSight CATU */
- {"ARMHC9FF", 0}, /* ARM CoreSight Dynamic Funnel */
{"", 0},
};
@@ -36,6 +36,7 @@ DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel");
* struct funnel_drvdata - specifics associated to a funnel component
* @base: memory mapped base address for this component.
* @atclk: optional clock for the core parts of the funnel.
+ * @pclk: APB clock if present, otherwise NULL
* @csdev: component vitals needed by the framework.
* @priority: port selection order.
* @spinlock: serialize enable/disable operations.
@@ -43,6 +44,7 @@ DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel");
struct funnel_drvdata {
void __iomem *base;
struct clk *atclk;
+ struct clk *pclk;
struct coresight_device *csdev;
unsigned long priority;
spinlock_t spinlock;
@@ -236,6 +238,10 @@ static int funnel_probe(struct device *dev, struct resource *res)
return ret;
}
+ drvdata->pclk = coresight_get_enable_apb_pclk(dev);
+ if (IS_ERR(drvdata->pclk))
+ return -ENODEV;
+
/*
* Map the device base for dynamic-funnel, which has been
* validated by AMBA core.
@@ -272,12 +278,13 @@ static int funnel_probe(struct device *dev, struct resource *res)
goto out_disable_clk;
}
- pm_runtime_put(dev);
ret = 0;
out_disable_clk:
if (ret && !IS_ERR_OR_NULL(drvdata->atclk))
clk_disable_unprepare(drvdata->atclk);
+ if (ret && !IS_ERR_OR_NULL(drvdata->pclk))
+ clk_disable_unprepare(drvdata->pclk);
return ret;
}
@@ -298,6 +305,9 @@ static int funnel_runtime_suspend(struct device *dev)
if (drvdata && !IS_ERR(drvdata->atclk))
clk_disable_unprepare(drvdata->atclk);
+ if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
+ clk_disable_unprepare(drvdata->pclk);
+
return 0;
}
@@ -308,6 +318,8 @@ static int funnel_runtime_resume(struct device *dev)
if (drvdata && !IS_ERR(drvdata->atclk))
clk_prepare_enable(drvdata->atclk);
+ if (drvdata && !IS_ERR_OR_NULL(drvdata->pclk))
+ clk_prepare_enable(drvdata->pclk);
return 0;
}
#endif
@@ -316,55 +328,61 @@ static const struct dev_pm_ops funnel_dev_pm_ops = {
SET_RUNTIME_PM_OPS(funnel_runtime_suspend, funnel_runtime_resume, NULL)
};
-static int static_funnel_probe(struct platform_device *pdev)
+static int funnel_platform_probe(struct platform_device *pdev)
{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int ret;
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
- /* Static funnel do not have programming base */
- ret = funnel_probe(&pdev->dev, NULL);
-
- if (ret) {
- pm_runtime_put_noidle(&pdev->dev);
+ ret = funnel_probe(&pdev->dev, res);
+ pm_runtime_put(&pdev->dev);
+ if (ret)
pm_runtime_disable(&pdev->dev);
- }
return ret;
}
-static void static_funnel_remove(struct platform_device *pdev)
+static void funnel_platform_remove(struct platform_device *pdev)
{
+ struct funnel_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
+
+ if (WARN_ON(!drvdata))
+ return;
+
funnel_remove(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ if (!IS_ERR_OR_NULL(drvdata->pclk))
+ clk_put(drvdata->pclk);
}
-static const struct of_device_id static_funnel_match[] = {
+static const struct of_device_id funnel_match[] = {
{.compatible = "arm,coresight-static-funnel"},
{}
};
-MODULE_DEVICE_TABLE(of, static_funnel_match);
+MODULE_DEVICE_TABLE(of, funnel_match);
#ifdef CONFIG_ACPI
-static const struct acpi_device_id static_funnel_ids[] = {
- {"ARMHC9FE", 0, 0, 0},
+static const struct acpi_device_id funnel_acpi_ids[] = {
+ {"ARMHC9FE", 0, 0, 0}, /* ARM Coresight Static Funnel */
+ {"ARMHC9FF", 0, 0, 0}, /* ARM CoreSight Dynamic Funnel */
{},
};
-MODULE_DEVICE_TABLE(acpi, static_funnel_ids);
+MODULE_DEVICE_TABLE(acpi, funnel_acpi_ids);
#endif
-static struct platform_driver static_funnel_driver = {
- .probe = static_funnel_probe,
- .remove_new = static_funnel_remove,
- .driver = {
- .name = "coresight-static-funnel",
+static struct platform_driver funnel_driver = {
+ .probe = funnel_platform_probe,
+ .remove_new = funnel_platform_remove,
+ .driver = {
+ .name = "coresight-funnel",
/* THIS_MODULE is taken care of by platform_driver_register() */
- .of_match_table = static_funnel_match,
- .acpi_match_table = ACPI_PTR(static_funnel_ids),
+ .of_match_table = funnel_match,
+ .acpi_match_table = ACPI_PTR(funnel_acpi_ids),
.pm = &funnel_dev_pm_ops,
.suppress_bind_attrs = true,
},
@@ -373,7 +391,13 @@ static struct platform_driver static_funnel_driver = {
static int dynamic_funnel_probe(struct amba_device *adev,
const struct amba_id *id)
{
- return funnel_probe(&adev->dev, &adev->res);
+ int ret;
+
+ ret = funnel_probe(&adev->dev, &adev->res);
+ if (!ret)
+ pm_runtime_put(&adev->dev);
+
+ return ret;
}
static void dynamic_funnel_remove(struct amba_device *adev)
@@ -410,12 +434,12 @@ static struct amba_driver dynamic_funnel_driver = {
static int __init funnel_init(void)
{
- return coresight_init_driver("funnel", &dynamic_funnel_driver, &static_funnel_driver);
+ return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver);
}
static void __exit funnel_exit(void)
{
- coresight_remove_driver(&dynamic_funnel_driver, &static_funnel_driver);
+ coresight_remove_driver(&dynamic_funnel_driver, &funnel_driver);
}
module_init(funnel_init);