msm: coresight: Add coresight support for bus profiling
Add ability to collect bus profiling data by registering
with Coresight module.
Change-Id: Ia4015c3c4adff3e296638f89368b988d50ee5d27
Signed-off-by: Gagan Mac <gmac@codeaurora.org>
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index d435e2b..e785c00 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -3,6 +3,7 @@
#
obj-y += msm_bus_core.o msm_bus_fabric.o msm_bus_config.o msm_bus_arb.o
obj-y += msm_bus_bimc.o msm_bus_noc.o
+obj-$(CONFIG_CORESIGHT) += msm_buspm_coresight.o
obj-$(CONFIG_OF) += msm_bus_of.o
obj-$(CONFIG_MSM_RPM) += msm_bus_rpm.o
obj-$(CONFIG_MSM_RPM_SMD) += msm_bus_rpm_smd.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 8c3e3d3..20380cf 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -261,6 +261,21 @@
}
#endif
+#ifdef CONFIG_CORESIGHT
+int msmbus_coresight_init(struct platform_device *pdev);
+void msmbus_coresight_remove(struct platform_device *pdev);
+#else
+int msmbus_coresight_init(struct platform_device *pdev)
+{
+ return 0;
+}
+
+void msmbus_coresight_remove(struct platform_device *pdev)
+{
+}
+#endif
+
+
#ifdef CONFIG_OF
struct msm_bus_fabric_registration
*msm_bus_of_get_fab_data(struct platform_device *pdev);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index dd00aad..0d28e9d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -789,6 +789,9 @@
}
}
+ if (msmbus_coresight_init(pdev))
+ pr_warn("Coresight support absent for bus: %d\n", pdata->id);
+
return ret;
err:
kfree(fabric->info.node_info);
@@ -804,6 +807,7 @@
int ret = 0;
fabdev = platform_get_drvdata(pdev);
+ msmbus_coresight_remove(pdev);
msm_bus_fabric_device_unregister(fabdev);
fabric = to_msm_bus_fabric(fabdev);
msm_bus_dbg_commit_data(fabric->fabdev.name, NULL, 0, 0, 0,
diff --git a/arch/arm/mach-msm/msm_bus/msm_buspm_coresight.c b/arch/arm/mach-msm/msm_bus/msm_buspm_coresight.c
new file mode 100644
index 0000000..6dbe954
--- /dev/null
+++ b/arch/arm/mach-msm/msm_bus/msm_buspm_coresight.c
@@ -0,0 +1,159 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+#include <linux/memory_alloc.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+struct msmbus_coresight_drvdata {
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct clk *clk;
+ const char *clk_name;
+ const char *clknode;
+};
+
+static int msmbus_coresight_enable(struct coresight_device *csdev)
+{
+ struct msmbus_coresight_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ return clk_prepare_enable(drvdata->clk);
+}
+
+static void msmbus_coresight_disable(struct coresight_device *csdev)
+{
+ struct msmbus_coresight_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ clk_disable_unprepare(drvdata->clk);
+}
+
+static const struct coresight_ops_source msmbus_coresight_source_ops = {
+ .enable = msmbus_coresight_enable,
+ .disable = msmbus_coresight_disable,
+};
+
+static const struct coresight_ops msmbus_coresight_cs_ops = {
+ .source_ops = &msmbus_coresight_source_ops,
+};
+
+void msmbus_coresight_remove(struct platform_device *pdev)
+{
+ struct msmbus_coresight_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ msmbus_coresight_disable(drvdata->csdev);
+ coresight_unregister(drvdata->csdev);
+ devm_kfree(&pdev->dev, drvdata);
+ platform_set_drvdata(pdev, NULL);
+}
+EXPORT_SYMBOL(msmbus_coresight_remove);
+
+static int buspm_of_get_clk(struct device_node *of_node,
+ struct msmbus_coresight_drvdata *drvdata)
+{
+ if (of_property_read_string(of_node, "qcom,fabclk-dual",
+ &drvdata->clk_name)) {
+ pr_err("Error: Unable to find clock from of_node\n");
+ return -EINVAL;
+ }
+
+ if (of_property_read_string(of_node, "label", &drvdata->clknode)) {
+ pr_err("Error: Unable to find clock-node from of_node\n");
+ return -EINVAL;
+ }
+
+ drvdata->clk = clk_get_sys(drvdata->clknode, drvdata->clk_name);
+ if (IS_ERR(drvdata->clk)) {
+ pr_err("Error: clk_get_sys failed for: %s\n",
+ drvdata->clknode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int msmbus_coresight_init(struct platform_device *pdev)
+{
+ int ret;
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct msmbus_coresight_drvdata *drvdata;
+ struct coresight_desc *desc;
+
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata) {
+ pr_err("coresight: Alloc for drvdata failed\n");
+ return -ENOMEM;
+ }
+
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+ ret = buspm_of_get_clk(pdev->dev.of_node, drvdata);
+ if (ret) {
+ pr_err("Error getting clocks\n");
+ ret = -ENXIO;
+ goto err1;
+ }
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc) {
+ pr_err("coresight: Error allocating memory\n");
+ ret = -ENOMEM;
+ goto err1;
+ }
+
+ desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
+ desc->ops = &msmbus_coresight_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev)) {
+ pr_err("coresight: Coresight register failed\n");
+ ret = PTR_ERR(drvdata->csdev);
+ goto err0;
+ }
+
+ dev_info(dev, "msmbus_coresight initialized\n");
+
+ return 0;
+err0:
+ devm_kfree(dev, desc);
+err1:
+ devm_kfree(dev, drvdata);
+ platform_set_drvdata(pdev, NULL);
+ return ret;
+}
+EXPORT_SYMBOL(msmbus_coresight_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM BusPM CoreSight Driver");