Loading drivers/hwtracing/coresight/Kconfig +72 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,15 @@ menuconfig CORESIGHT trace source gets enabled. if CORESIGHT config CORESIGHT_QGKI bool "Enable coresight for QGKI or debug variant" depends on QGKI help This enables CoreSight drivers with QGKI flag. When this flag is enabled, it is safe to assume that the build is a Non GKI build. It can be either QGKI build or a debug build. If this flag is enabled, all the ABI compatibilities are not applicable. config CORESIGHT_LINKS_AND_SINKS bool "CoreSight Link and Sink drivers" help Loading Loading @@ -110,6 +119,69 @@ config CORESIGHT_CPU_DEBUG properly, please refer Documentation/trace/coresight-cpu-debug.rst for detailed description and the example for usage. config CORESIGHT_CTI bool "CoreSight Cross Trigger Interface driver" help This driver provides support for Cross Trigger Interface that is used to input or output i.e. pass cross trigger events from one hardware component to another. It can also be used to pass software generated events. config CORESIGHT_CTI_SAVE_DISABLE bool "Turn off CTI save and restore" depends on CORESIGHT_CTI help Turns off CoreSight CTI save and restore support for cpu CTIs. This avoids voting for the clocks during probe as well as the associated save and restore latency at the cost of breaking cpu CTI support on targets where cpu CTIs have to be preserved across power collapse. If unsure, say 'N' here to avoid breaking cpu CTI support. config CORESIGHT_TPDA bool "CoreSight Trace, Profiling & Diagnostics Aggregator driver" help This driver provides support for configuring aggregator. This is primarily useful for pulling the data sets from one or more attached monitors and pushing the resultant data out. Multiple monitors are connected on different input ports of TPDA. config CORESIGHT_TPDM bool "CoreSight Trace, Profiling & Diagnostics Monitor driver" help This driver provides support for configuring monitor. Monitors are primarily responsible for data set collection and support the ability to collect any permutation of data set types. Monitors are also responsible for interaction with system cross triggering. config CORESIGHT_TPDM_DEFAULT_ENABLE bool "Turn on TPDM tracing by default" depends on CORESIGHT_TPDM help Turns on CoreSight TPDM tracing for different data set types by default. Otherwise, tracing is disabled by default but can be enabled via sysfs. If unsure, say 'N' here to avoid potential power and performance penalty. config CORESIGHT_CSR bool "CoreSight Slave Register driver" help This driver provides support for CoreSight Slave Register block that hosts miscellaneous configuration registers. Those configuration registers can be used to control, various coresight configurations. config CORESIGHT_HWEVENT bool "CoreSight Hardware Event driver" depends on CORESIGHT_STM select CORESIGHT_CSR help This driver provides support for monitoring and tracing CoreSight Hardware Event across STM interface. It configures Coresight Hardware Event mux control registers to select hardware events based on user input. config CORESIGHT_TPDA bool "CoreSight Trace, Profiling & Diagnostics Aggregator driver" help Loading drivers/hwtracing/coresight/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \ obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o obj-$(CONFIG_CORESIGHT_TPDM) += coresight-tpdm.o obj-$(CONFIG_CORESIGHT_HWEVENT) += coresight-hwevent.o Loading drivers/hwtracing/coresight/coresight-cti.c 0 → 100644 +1566 −0 File added.Preview size limit exceeded, changes collapsed. Show changes drivers/hwtracing/coresight/coresight-platform.c +71 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2012, The Linux Foundation. All rights reserved. * Copyright (c) 2012, 2019 The Linux Foundation. All rights reserved. */ #include <linux/acpi.h> Loading Loading @@ -184,6 +184,9 @@ static int of_coresight_parse_endpoint(struct device *dev, struct of_endpoint endpoint, rendpoint; struct device_node *rparent = NULL; struct device_node *rep = NULL; #ifdef CONFIG_CORESIGHT_QGKI struct device_node *sn = NULL; #endif struct device *rdev = NULL; struct fwnode_handle *rdev_fwnode; Loading Loading @@ -223,6 +226,15 @@ static int of_coresight_parse_endpoint(struct device *dev, */ conn->child_fwnode = fwnode_handle_get(rdev_fwnode); conn->child_port = rendpoint.port; #ifdef CONFIG_CORESIGHT_QGKI conn->source_name = NULL; sn = of_parse_phandle(ep, "source", 0); if (sn) { ret = of_property_read_string(sn, "coresight-name", &conn->source_name); of_node_put(sn); } #endif /* Connection record updated */ ret = 1; } while (0); Loading @@ -233,7 +245,60 @@ static int of_coresight_parse_endpoint(struct device *dev, return ret; } #ifdef CONFIG_CORESIGHT_QGKI static struct coresight_reg_clk * of_coresight_get_reg_clk(struct device *dev, const struct device_node *node) { struct coresight_reg_clk *reg_clk; const char *clk_name, *reg_name; int nr_reg, nr_clk, i, ret; nr_reg = of_property_count_strings(node, "qcom,proxy-regs"); nr_clk = of_property_count_strings(node, "qcom,proxy-clks"); if (!nr_reg && !nr_clk) return NULL; reg_clk = devm_kzalloc(dev, sizeof(*reg_clk), GFP_KERNEL); if (!reg_clk) return ERR_PTR(-ENOMEM); reg_clk->nr_reg = nr_reg; reg_clk->nr_clk = nr_clk; if (nr_reg > 0) { reg_clk->reg = devm_kzalloc(dev, nr_reg * sizeof(reg_clk->reg), GFP_KERNEL); if (!reg_clk->reg) return ERR_PTR(-ENOMEM); for (i = 0; i < nr_reg; i++) { ret = of_property_read_string_index(node, "qcom,proxy-regs", i, ®_name); if (ret) return ERR_PTR(ret); reg_clk->reg[i] = devm_regulator_get(dev, reg_name); if (IS_ERR(reg_clk->reg[i])) return ERR_PTR(-EINVAL); } } if (nr_clk > 0) { reg_clk->clk = devm_kzalloc(dev, nr_clk * sizeof(reg_clk->clk), GFP_KERNEL); if (!reg_clk->clk) return ERR_PTR(-ENOMEM); for (i = 0; i < nr_clk; i++) { ret = of_property_read_string_index(node, "qcom,proxy-clks", i, &clk_name); if (ret) return ERR_PTR(ret); reg_clk->clk[i] = devm_clk_get(dev, clk_name); if (IS_ERR(reg_clk->clk[i])) return ERR_PTR(-EINVAL); } } return reg_clk; } #endif static int of_get_coresight_platform_data(struct device *dev, struct coresight_platform_data *pdata) { Loading @@ -244,6 +309,11 @@ static int of_get_coresight_platform_data(struct device *dev, bool legacy_binding = false; struct device_node *node = dev->of_node; #ifdef CONFIG_CORESIGHT_QGKI pdata->reg_clk = of_coresight_get_reg_clk(dev, node); if (IS_ERR(pdata->reg_clk)) return PTR_ERR(pdata->reg_clk); #endif /* Get the number of input and output port for this component */ of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport); Loading drivers/hwtracing/coresight/coresight.c +138 −17 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/of_platform.h> #include <linux/delay.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> #include "coresight-etm-perf.h" #include "coresight-priv.h" Loading Loading @@ -54,6 +55,8 @@ static LIST_HEAD(cs_active_paths); */ const u32 barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; static struct coresight_device *coresight_get_source(struct list_head *path); static int coresight_id_match(struct device *dev, void *data) { int trace_id, i_trace_id; Loading Loading @@ -93,6 +96,39 @@ static int coresight_source_is_unique(struct coresight_device *csdev) csdev, coresight_id_match); } /** * coresight_source_filter - checks whether the connection matches the source * of path if connection is binded to specific source. * @path: The list of devices * @conn: The connection of one outport * * Return zero if the connection doesn't have a source binded or source of the * path matches the source binds to connection. */ #ifdef CONFIG_CORESIGHT_QGKI static int coresight_source_filter(struct list_head *path, struct coresight_connection *conn) { int ret = 0; struct coresight_device *source = NULL; if (conn->source_name == NULL) return ret; source = coresight_get_source(path); if (source == NULL) return ret; return strcmp(conn->source_name, dev_name(&source->dev)); } #else static int coresight_source_filter(struct list_head *path, struct coresight_connection *conn) { return 0; } #endif static int coresight_reset_sink(struct device *dev, void *data) { struct coresight_device *csdev = to_coresight_device(dev); Loading @@ -110,14 +146,71 @@ static void coresight_reset_all_sink(void) bus_for_each_dev(&coresight_bustype, NULL, NULL, coresight_reset_sink); } #ifdef CONFIG_CORESIGHT_QGKI int coresight_enable_reg_clk(struct coresight_device *csdev) { struct coresight_reg_clk *reg_clk = csdev->reg_clk; int ret; int i, j; if (IS_ERR_OR_NULL(reg_clk)) return -EINVAL; for (i = 0; i < reg_clk->nr_reg; i++) { ret = regulator_enable(reg_clk->reg[i]); if (ret) goto err_regs; } for (j = 0; j < reg_clk->nr_clk; j++) { ret = clk_prepare_enable(reg_clk->clk[j]); if (ret) goto err_clks; } return 0; err_clks: for (j--; j >= 0; j--) clk_disable_unprepare(reg_clk->clk[j]); err_regs: for (i--; i >= 0; i--) regulator_disable(reg_clk->reg[i]); return ret; } EXPORT_SYMBOL(coresight_enable_reg_clk); void coresight_disable_reg_clk(struct coresight_device *csdev) { struct coresight_reg_clk *reg_clk = csdev->reg_clk; int i; if (IS_ERR_OR_NULL(reg_clk)) return; for (i = reg_clk->nr_clk - 1; i >= 0; i--) clk_disable_unprepare(reg_clk->clk[i]); for (i = reg_clk->nr_reg - 1; i >= 0; i--) regulator_disable(reg_clk->reg[i]); } EXPORT_SYMBOL(coresight_disable_reg_clk); #else int coresight_enable_reg_clk(struct coresight_device *csdev) { return 0; } void coresight_disable_reg_clk(struct coresight_device *csdev) { } #endif static int coresight_find_link_inport(struct coresight_device *csdev, struct coresight_device *parent) struct coresight_device *parent, struct list_head *path) { int i; struct coresight_connection *conn; for (i = 0; i < parent->pdata->nr_outport; i++) { conn = &parent->pdata->conns[i]; if (coresight_source_filter(path, conn)) continue; if (conn->child_dev == csdev) return conn->child_port; } Loading @@ -129,13 +222,16 @@ static int coresight_find_link_inport(struct coresight_device *csdev, } static int coresight_find_link_outport(struct coresight_device *csdev, struct coresight_device *child) struct coresight_device *child, struct list_head *path) { int i; struct coresight_connection *conn; for (i = 0; i < csdev->pdata->nr_outport; i++) { conn = &csdev->pdata->conns[i]; if (coresight_source_filter(path, conn)) continue; if (conn->child_dev == child) return conn->outport; } Loading Loading @@ -244,9 +340,12 @@ static int coresight_enable_sink(struct coresight_device *csdev, if (!sink_ops(csdev)->enable) return -EINVAL; coresight_enable_reg_clk(csdev); ret = sink_ops(csdev)->enable(csdev, mode, data); if (ret) if (ret) { coresight_disable_reg_clk(csdev); return ret; } csdev->enable = true; return 0; Loading @@ -262,13 +361,15 @@ static void coresight_disable_sink(struct coresight_device *csdev) ret = sink_ops(csdev)->disable(csdev); if (ret) return; coresight_disable_reg_clk(csdev); csdev->activated = false; csdev->enable = false; } static int coresight_enable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child) struct coresight_device *child, struct list_head *path) { int ret; int link_subtype; Loading @@ -277,8 +378,8 @@ static int coresight_enable_link(struct coresight_device *csdev, if (!parent || !child) return -EINVAL; inport = coresight_find_link_inport(csdev, parent); outport = coresight_find_link_outport(csdev, child); inport = coresight_find_link_inport(csdev, parent, path); outport = coresight_find_link_outport(csdev, child, path); link_subtype = csdev->subtype.link_subtype; if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) Loading @@ -293,8 +394,10 @@ static int coresight_enable_link(struct coresight_device *csdev, if (atomic_inc_return(&csdev->refcnt[refport]) == 1) { if (link_ops(csdev)->enable) { coresight_enable_reg_clk(csdev); ret = link_ops(csdev)->enable(csdev, inport, outport); if (ret) { coresight_disable_reg_clk(csdev); atomic_dec(&csdev->refcnt[refport]); return ret; } Loading @@ -308,7 +411,8 @@ static int coresight_enable_link(struct coresight_device *csdev, static void coresight_disable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child) struct coresight_device *child, struct list_head *path) { int i, nr_conns; int link_subtype; Loading @@ -317,8 +421,8 @@ static void coresight_disable_link(struct coresight_device *csdev, if (!parent || !child) return; inport = coresight_find_link_inport(csdev, parent); outport = coresight_find_link_outport(csdev, child); inport = coresight_find_link_inport(csdev, parent, path); outport = coresight_find_link_outport(csdev, child, path); link_subtype = csdev->subtype.link_subtype; if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { Loading @@ -333,8 +437,10 @@ static void coresight_disable_link(struct coresight_device *csdev, } if (atomic_dec_return(&csdev->refcnt[refport]) == 0) { if (link_ops(csdev)->disable) if (link_ops(csdev)->disable) { link_ops(csdev)->disable(csdev, inport, outport); coresight_disable_reg_clk(csdev); } } for (i = 0; i < nr_conns; i++) Loading @@ -356,10 +462,13 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode) if (!csdev->enable) { if (source_ops(csdev)->enable) { coresight_enable_reg_clk(csdev); ret = source_ops(csdev)->enable(csdev, NULL, mode); if (ret) if (ret) { coresight_disable_reg_clk(csdev); return ret; } } csdev->enable = true; } Loading @@ -379,8 +488,10 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode) static bool coresight_disable_source(struct coresight_device *csdev) { if (atomic_dec_return(csdev->refcnt) == 0) { if (source_ops(csdev)->disable) if (source_ops(csdev)->disable) { source_ops(csdev)->disable(csdev, NULL); coresight_disable_reg_clk(csdev); } csdev->enable = false; } return !csdev->enable; Loading Loading @@ -430,7 +541,7 @@ static void coresight_disable_path_from(struct list_head *path, case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; coresight_disable_link(csdev, parent, child); coresight_disable_link(csdev, parent, child, path); break; default: break; Loading Loading @@ -484,7 +595,7 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data) case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; ret = coresight_enable_link(csdev, parent, child); ret = coresight_enable_link(csdev, parent, child, path); if (ret) goto err; break; Loading Loading @@ -667,7 +778,8 @@ static void coresight_drop_device(struct coresight_device *csdev) */ static int _coresight_build_path(struct coresight_device *csdev, struct coresight_device *sink, struct list_head *path) struct list_head *path, struct coresight_device *source) { int i; bool found = false; Loading @@ -682,8 +794,14 @@ static int _coresight_build_path(struct coresight_device *csdev, struct coresight_device *child_dev; child_dev = csdev->pdata->conns[i].child_dev; #ifdef CONFIG_CORESIGHT_QGKI if (csdev->pdata->conns[i].source_name && strcmp(csdev->pdata->conns[i].source_name, dev_name(&source->dev))) continue; #endif if (child_dev && _coresight_build_path(child_dev, sink, path) == 0) { _coresight_build_path(child_dev, sink, path, source) == 0) { found = true; break; } Loading Loading @@ -725,7 +843,7 @@ struct list_head *coresight_build_path(struct coresight_device *source, INIT_LIST_HEAD(path); rc = _coresight_build_path(source, sink, path); rc = _coresight_build_path(source, sink, path, source); if (rc) { kfree(path); return ERR_PTR(rc); Loading Loading @@ -1302,6 +1420,9 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) csdev->subtype = desc->subtype; csdev->ops = desc->ops; csdev->orphan = false; #ifdef CONFIG_CORESIGHT_QGKI csdev->reg_clk = desc->pdata->reg_clk; #endif csdev->dev.type = &coresight_dev_type[desc->type]; csdev->dev.groups = desc->groups; Loading Loading
drivers/hwtracing/coresight/Kconfig +72 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,15 @@ menuconfig CORESIGHT trace source gets enabled. if CORESIGHT config CORESIGHT_QGKI bool "Enable coresight for QGKI or debug variant" depends on QGKI help This enables CoreSight drivers with QGKI flag. When this flag is enabled, it is safe to assume that the build is a Non GKI build. It can be either QGKI build or a debug build. If this flag is enabled, all the ABI compatibilities are not applicable. config CORESIGHT_LINKS_AND_SINKS bool "CoreSight Link and Sink drivers" help Loading Loading @@ -110,6 +119,69 @@ config CORESIGHT_CPU_DEBUG properly, please refer Documentation/trace/coresight-cpu-debug.rst for detailed description and the example for usage. config CORESIGHT_CTI bool "CoreSight Cross Trigger Interface driver" help This driver provides support for Cross Trigger Interface that is used to input or output i.e. pass cross trigger events from one hardware component to another. It can also be used to pass software generated events. config CORESIGHT_CTI_SAVE_DISABLE bool "Turn off CTI save and restore" depends on CORESIGHT_CTI help Turns off CoreSight CTI save and restore support for cpu CTIs. This avoids voting for the clocks during probe as well as the associated save and restore latency at the cost of breaking cpu CTI support on targets where cpu CTIs have to be preserved across power collapse. If unsure, say 'N' here to avoid breaking cpu CTI support. config CORESIGHT_TPDA bool "CoreSight Trace, Profiling & Diagnostics Aggregator driver" help This driver provides support for configuring aggregator. This is primarily useful for pulling the data sets from one or more attached monitors and pushing the resultant data out. Multiple monitors are connected on different input ports of TPDA. config CORESIGHT_TPDM bool "CoreSight Trace, Profiling & Diagnostics Monitor driver" help This driver provides support for configuring monitor. Monitors are primarily responsible for data set collection and support the ability to collect any permutation of data set types. Monitors are also responsible for interaction with system cross triggering. config CORESIGHT_TPDM_DEFAULT_ENABLE bool "Turn on TPDM tracing by default" depends on CORESIGHT_TPDM help Turns on CoreSight TPDM tracing for different data set types by default. Otherwise, tracing is disabled by default but can be enabled via sysfs. If unsure, say 'N' here to avoid potential power and performance penalty. config CORESIGHT_CSR bool "CoreSight Slave Register driver" help This driver provides support for CoreSight Slave Register block that hosts miscellaneous configuration registers. Those configuration registers can be used to control, various coresight configurations. config CORESIGHT_HWEVENT bool "CoreSight Hardware Event driver" depends on CORESIGHT_STM select CORESIGHT_CSR help This driver provides support for monitoring and tracing CoreSight Hardware Event across STM interface. It configures Coresight Hardware Event mux control registers to select hardware events based on user input. config CORESIGHT_TPDA bool "CoreSight Trace, Profiling & Diagnostics Aggregator driver" help Loading
drivers/hwtracing/coresight/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \ obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o obj-$(CONFIG_CORESIGHT_TPDM) += coresight-tpdm.o obj-$(CONFIG_CORESIGHT_HWEVENT) += coresight-hwevent.o Loading
drivers/hwtracing/coresight/coresight-cti.c 0 → 100644 +1566 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
drivers/hwtracing/coresight/coresight-platform.c +71 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2012, The Linux Foundation. All rights reserved. * Copyright (c) 2012, 2019 The Linux Foundation. All rights reserved. */ #include <linux/acpi.h> Loading Loading @@ -184,6 +184,9 @@ static int of_coresight_parse_endpoint(struct device *dev, struct of_endpoint endpoint, rendpoint; struct device_node *rparent = NULL; struct device_node *rep = NULL; #ifdef CONFIG_CORESIGHT_QGKI struct device_node *sn = NULL; #endif struct device *rdev = NULL; struct fwnode_handle *rdev_fwnode; Loading Loading @@ -223,6 +226,15 @@ static int of_coresight_parse_endpoint(struct device *dev, */ conn->child_fwnode = fwnode_handle_get(rdev_fwnode); conn->child_port = rendpoint.port; #ifdef CONFIG_CORESIGHT_QGKI conn->source_name = NULL; sn = of_parse_phandle(ep, "source", 0); if (sn) { ret = of_property_read_string(sn, "coresight-name", &conn->source_name); of_node_put(sn); } #endif /* Connection record updated */ ret = 1; } while (0); Loading @@ -233,7 +245,60 @@ static int of_coresight_parse_endpoint(struct device *dev, return ret; } #ifdef CONFIG_CORESIGHT_QGKI static struct coresight_reg_clk * of_coresight_get_reg_clk(struct device *dev, const struct device_node *node) { struct coresight_reg_clk *reg_clk; const char *clk_name, *reg_name; int nr_reg, nr_clk, i, ret; nr_reg = of_property_count_strings(node, "qcom,proxy-regs"); nr_clk = of_property_count_strings(node, "qcom,proxy-clks"); if (!nr_reg && !nr_clk) return NULL; reg_clk = devm_kzalloc(dev, sizeof(*reg_clk), GFP_KERNEL); if (!reg_clk) return ERR_PTR(-ENOMEM); reg_clk->nr_reg = nr_reg; reg_clk->nr_clk = nr_clk; if (nr_reg > 0) { reg_clk->reg = devm_kzalloc(dev, nr_reg * sizeof(reg_clk->reg), GFP_KERNEL); if (!reg_clk->reg) return ERR_PTR(-ENOMEM); for (i = 0; i < nr_reg; i++) { ret = of_property_read_string_index(node, "qcom,proxy-regs", i, ®_name); if (ret) return ERR_PTR(ret); reg_clk->reg[i] = devm_regulator_get(dev, reg_name); if (IS_ERR(reg_clk->reg[i])) return ERR_PTR(-EINVAL); } } if (nr_clk > 0) { reg_clk->clk = devm_kzalloc(dev, nr_clk * sizeof(reg_clk->clk), GFP_KERNEL); if (!reg_clk->clk) return ERR_PTR(-ENOMEM); for (i = 0; i < nr_clk; i++) { ret = of_property_read_string_index(node, "qcom,proxy-clks", i, &clk_name); if (ret) return ERR_PTR(ret); reg_clk->clk[i] = devm_clk_get(dev, clk_name); if (IS_ERR(reg_clk->clk[i])) return ERR_PTR(-EINVAL); } } return reg_clk; } #endif static int of_get_coresight_platform_data(struct device *dev, struct coresight_platform_data *pdata) { Loading @@ -244,6 +309,11 @@ static int of_get_coresight_platform_data(struct device *dev, bool legacy_binding = false; struct device_node *node = dev->of_node; #ifdef CONFIG_CORESIGHT_QGKI pdata->reg_clk = of_coresight_get_reg_clk(dev, node); if (IS_ERR(pdata->reg_clk)) return PTR_ERR(pdata->reg_clk); #endif /* Get the number of input and output port for this component */ of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport); Loading
drivers/hwtracing/coresight/coresight.c +138 −17 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/of_platform.h> #include <linux/delay.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> #include "coresight-etm-perf.h" #include "coresight-priv.h" Loading Loading @@ -54,6 +55,8 @@ static LIST_HEAD(cs_active_paths); */ const u32 barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; static struct coresight_device *coresight_get_source(struct list_head *path); static int coresight_id_match(struct device *dev, void *data) { int trace_id, i_trace_id; Loading Loading @@ -93,6 +96,39 @@ static int coresight_source_is_unique(struct coresight_device *csdev) csdev, coresight_id_match); } /** * coresight_source_filter - checks whether the connection matches the source * of path if connection is binded to specific source. * @path: The list of devices * @conn: The connection of one outport * * Return zero if the connection doesn't have a source binded or source of the * path matches the source binds to connection. */ #ifdef CONFIG_CORESIGHT_QGKI static int coresight_source_filter(struct list_head *path, struct coresight_connection *conn) { int ret = 0; struct coresight_device *source = NULL; if (conn->source_name == NULL) return ret; source = coresight_get_source(path); if (source == NULL) return ret; return strcmp(conn->source_name, dev_name(&source->dev)); } #else static int coresight_source_filter(struct list_head *path, struct coresight_connection *conn) { return 0; } #endif static int coresight_reset_sink(struct device *dev, void *data) { struct coresight_device *csdev = to_coresight_device(dev); Loading @@ -110,14 +146,71 @@ static void coresight_reset_all_sink(void) bus_for_each_dev(&coresight_bustype, NULL, NULL, coresight_reset_sink); } #ifdef CONFIG_CORESIGHT_QGKI int coresight_enable_reg_clk(struct coresight_device *csdev) { struct coresight_reg_clk *reg_clk = csdev->reg_clk; int ret; int i, j; if (IS_ERR_OR_NULL(reg_clk)) return -EINVAL; for (i = 0; i < reg_clk->nr_reg; i++) { ret = regulator_enable(reg_clk->reg[i]); if (ret) goto err_regs; } for (j = 0; j < reg_clk->nr_clk; j++) { ret = clk_prepare_enable(reg_clk->clk[j]); if (ret) goto err_clks; } return 0; err_clks: for (j--; j >= 0; j--) clk_disable_unprepare(reg_clk->clk[j]); err_regs: for (i--; i >= 0; i--) regulator_disable(reg_clk->reg[i]); return ret; } EXPORT_SYMBOL(coresight_enable_reg_clk); void coresight_disable_reg_clk(struct coresight_device *csdev) { struct coresight_reg_clk *reg_clk = csdev->reg_clk; int i; if (IS_ERR_OR_NULL(reg_clk)) return; for (i = reg_clk->nr_clk - 1; i >= 0; i--) clk_disable_unprepare(reg_clk->clk[i]); for (i = reg_clk->nr_reg - 1; i >= 0; i--) regulator_disable(reg_clk->reg[i]); } EXPORT_SYMBOL(coresight_disable_reg_clk); #else int coresight_enable_reg_clk(struct coresight_device *csdev) { return 0; } void coresight_disable_reg_clk(struct coresight_device *csdev) { } #endif static int coresight_find_link_inport(struct coresight_device *csdev, struct coresight_device *parent) struct coresight_device *parent, struct list_head *path) { int i; struct coresight_connection *conn; for (i = 0; i < parent->pdata->nr_outport; i++) { conn = &parent->pdata->conns[i]; if (coresight_source_filter(path, conn)) continue; if (conn->child_dev == csdev) return conn->child_port; } Loading @@ -129,13 +222,16 @@ static int coresight_find_link_inport(struct coresight_device *csdev, } static int coresight_find_link_outport(struct coresight_device *csdev, struct coresight_device *child) struct coresight_device *child, struct list_head *path) { int i; struct coresight_connection *conn; for (i = 0; i < csdev->pdata->nr_outport; i++) { conn = &csdev->pdata->conns[i]; if (coresight_source_filter(path, conn)) continue; if (conn->child_dev == child) return conn->outport; } Loading Loading @@ -244,9 +340,12 @@ static int coresight_enable_sink(struct coresight_device *csdev, if (!sink_ops(csdev)->enable) return -EINVAL; coresight_enable_reg_clk(csdev); ret = sink_ops(csdev)->enable(csdev, mode, data); if (ret) if (ret) { coresight_disable_reg_clk(csdev); return ret; } csdev->enable = true; return 0; Loading @@ -262,13 +361,15 @@ static void coresight_disable_sink(struct coresight_device *csdev) ret = sink_ops(csdev)->disable(csdev); if (ret) return; coresight_disable_reg_clk(csdev); csdev->activated = false; csdev->enable = false; } static int coresight_enable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child) struct coresight_device *child, struct list_head *path) { int ret; int link_subtype; Loading @@ -277,8 +378,8 @@ static int coresight_enable_link(struct coresight_device *csdev, if (!parent || !child) return -EINVAL; inport = coresight_find_link_inport(csdev, parent); outport = coresight_find_link_outport(csdev, child); inport = coresight_find_link_inport(csdev, parent, path); outport = coresight_find_link_outport(csdev, child, path); link_subtype = csdev->subtype.link_subtype; if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) Loading @@ -293,8 +394,10 @@ static int coresight_enable_link(struct coresight_device *csdev, if (atomic_inc_return(&csdev->refcnt[refport]) == 1) { if (link_ops(csdev)->enable) { coresight_enable_reg_clk(csdev); ret = link_ops(csdev)->enable(csdev, inport, outport); if (ret) { coresight_disable_reg_clk(csdev); atomic_dec(&csdev->refcnt[refport]); return ret; } Loading @@ -308,7 +411,8 @@ static int coresight_enable_link(struct coresight_device *csdev, static void coresight_disable_link(struct coresight_device *csdev, struct coresight_device *parent, struct coresight_device *child) struct coresight_device *child, struct list_head *path) { int i, nr_conns; int link_subtype; Loading @@ -317,8 +421,8 @@ static void coresight_disable_link(struct coresight_device *csdev, if (!parent || !child) return; inport = coresight_find_link_inport(csdev, parent); outport = coresight_find_link_outport(csdev, child); inport = coresight_find_link_inport(csdev, parent, path); outport = coresight_find_link_outport(csdev, child, path); link_subtype = csdev->subtype.link_subtype; if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { Loading @@ -333,8 +437,10 @@ static void coresight_disable_link(struct coresight_device *csdev, } if (atomic_dec_return(&csdev->refcnt[refport]) == 0) { if (link_ops(csdev)->disable) if (link_ops(csdev)->disable) { link_ops(csdev)->disable(csdev, inport, outport); coresight_disable_reg_clk(csdev); } } for (i = 0; i < nr_conns; i++) Loading @@ -356,10 +462,13 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode) if (!csdev->enable) { if (source_ops(csdev)->enable) { coresight_enable_reg_clk(csdev); ret = source_ops(csdev)->enable(csdev, NULL, mode); if (ret) if (ret) { coresight_disable_reg_clk(csdev); return ret; } } csdev->enable = true; } Loading @@ -379,8 +488,10 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode) static bool coresight_disable_source(struct coresight_device *csdev) { if (atomic_dec_return(csdev->refcnt) == 0) { if (source_ops(csdev)->disable) if (source_ops(csdev)->disable) { source_ops(csdev)->disable(csdev, NULL); coresight_disable_reg_clk(csdev); } csdev->enable = false; } return !csdev->enable; Loading Loading @@ -430,7 +541,7 @@ static void coresight_disable_path_from(struct list_head *path, case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; coresight_disable_link(csdev, parent, child); coresight_disable_link(csdev, parent, child, path); break; default: break; Loading Loading @@ -484,7 +595,7 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data) case CORESIGHT_DEV_TYPE_LINK: parent = list_prev_entry(nd, link)->csdev; child = list_next_entry(nd, link)->csdev; ret = coresight_enable_link(csdev, parent, child); ret = coresight_enable_link(csdev, parent, child, path); if (ret) goto err; break; Loading Loading @@ -667,7 +778,8 @@ static void coresight_drop_device(struct coresight_device *csdev) */ static int _coresight_build_path(struct coresight_device *csdev, struct coresight_device *sink, struct list_head *path) struct list_head *path, struct coresight_device *source) { int i; bool found = false; Loading @@ -682,8 +794,14 @@ static int _coresight_build_path(struct coresight_device *csdev, struct coresight_device *child_dev; child_dev = csdev->pdata->conns[i].child_dev; #ifdef CONFIG_CORESIGHT_QGKI if (csdev->pdata->conns[i].source_name && strcmp(csdev->pdata->conns[i].source_name, dev_name(&source->dev))) continue; #endif if (child_dev && _coresight_build_path(child_dev, sink, path) == 0) { _coresight_build_path(child_dev, sink, path, source) == 0) { found = true; break; } Loading Loading @@ -725,7 +843,7 @@ struct list_head *coresight_build_path(struct coresight_device *source, INIT_LIST_HEAD(path); rc = _coresight_build_path(source, sink, path); rc = _coresight_build_path(source, sink, path, source); if (rc) { kfree(path); return ERR_PTR(rc); Loading Loading @@ -1302,6 +1420,9 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) csdev->subtype = desc->subtype; csdev->ops = desc->ops; csdev->orphan = false; #ifdef CONFIG_CORESIGHT_QGKI csdev->reg_clk = desc->pdata->reg_clk; #endif csdev->dev.type = &coresight_dev_type[desc->type]; csdev->dev.groups = desc->groups; Loading