From patchwork Tue Feb 25 23:45:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 204234 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AFC3EC4BA09 for ; Tue, 25 Feb 2020 23:46:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 68B8724653 for ; Tue, 25 Feb 2020 23:46:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="xG4wENx7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729481AbgBYXqe (ORCPT ); Tue, 25 Feb 2020 18:46:34 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:36704 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729472AbgBYXqd (ORCPT ); Tue, 25 Feb 2020 18:46:33 -0500 Received: by mail-wm1-f68.google.com with SMTP id p17so1095984wma.1 for ; Tue, 25 Feb 2020 15:46:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=XIU8Pa5Hn5jXxFR25TfmB4RjSIHQ+Lzh4Ql4O7TZCC8=; b=xG4wENx7kwGwWPyzdO0XqTKSLYTgeSIVEDyaamPoxoJgeV6PlQrXotUIpFhjI+hPKP APpxSMM0a3gio3jYrrScofUs5SsyODm0psqWhZLs0N7iok3VSFamvysRfdbfc/2nyTH5 tphcG4daAyVK0JW3AAolAj3V8vWUy03F7VscKQjmXPclHRVwcfZ8gf0OvzgRwdk4CK0T 1+5tyv2GMcl0SNyaE7uvKjxxcXtq9ev6VI3+bcuUhrVBDMsF29vkmJiLBLKX1aGTMuXY MLL5xIjBdsSgiefYUzYAZQZFgjZoOFdqJz3lMWpnfk5QlWKfjH0ERg/fWxO6fP/YzH6o bJcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=XIU8Pa5Hn5jXxFR25TfmB4RjSIHQ+Lzh4Ql4O7TZCC8=; b=eUfPLQNqn2TasAhLEtVa5vk/xJ3m1VA+bdsT4S8QJlFp0lHr+/lrM+iTLJt9TzhPwJ By/enbmT3B38XViwZtic8L9j93IibPIYVXg2ck15Gsn1FbtO8q+h7r6PXuZqCaBssW1o EMcL87VfeldpqsXXJkH6vqLg5JW6HYZfI1qZyyl8BJRbDvqHg64zVnkGTO6hQ7k0ga4c tT1OA3LN6rPwQ28S7M+pLXIb7EFhDCh15D0rXL6h1BkYmlx1QCbGoBaLF0EtqbFm2vxy 6T0VgS/rPq42MpyFM58v5V4eK0uuG5gp9J79/jz0SgQIJRWFkSxkUfkXV/h/DWWQsRRo xRaw== X-Gm-Message-State: APjAAAUg8rKPsI2RhNVQX/inrjJc0ArDBHbjsPdR5YocXx4Lnr1WZYL5 FBUjiZu4eboeO2EBkKwtEMdt3A== X-Google-Smtp-Source: APXvYqykHcpq0cBZVIt0YqYOgT76H2k10o8/YcUPPKK35C0J1eJf8wblbbyjiL6fPY7HgkhEoeTHUQ== X-Received: by 2002:a1c:a553:: with SMTP id o80mr1554222wme.94.1582674391293; Tue, 25 Feb 2020 15:46:31 -0800 (PST) Received: from linaro.org ([2a00:23c5:6815:3901:186c:5f6c:221d:5ce]) by smtp.gmail.com with ESMTPSA id t133sm356278wmf.31.2020.02.25.15.46.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 15:46:30 -0800 (PST) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, coresight@lists.linaro.org, linux-doc@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org, mathieu.poirier@linaro.org, suzuki.poulose@arm.com, robh+dt@kernel.org, maxime@cerno.tech, liviu.dudau@arm.com, sudeep.holla@arm.com, lorenzo.pieralisi@arm.com, agross@kernel.org, corbet@lwn.net, Mike Leach Subject: [PATCH v10 01/15] coresight: cti: Initial CoreSight CTI Driver Date: Tue, 25 Feb 2020 23:45:57 +0000 Message-Id: <20200225234611.11067-2-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200225234611.11067-1-mike.leach@linaro.org> References: <20200225234611.11067-1-mike.leach@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This introduces a baseline CTI driver and associated configuration files. Uses the platform agnostic naming standard for CoreSight devices, along with a generic platform probing method that currently supports device tree descriptions, but allows for the ACPI bindings to be added once these have been defined for the CTI devices. Driver will probe for the device on the AMBA bus, and load the CTI driver on CoreSight ID match to CTI IDs in tables. Initial sysfs support for enable / disable provided. Default CTI interconnection data is generated based on hardware register signal counts, with no additional connection information. Signed-off-by: Mike Leach Reviewed-by: Mathieu Poirier Reviewed-by: Suzuki K Poulose --- drivers/hwtracing/coresight/Kconfig | 12 + drivers/hwtracing/coresight/Makefile | 3 + .../coresight/coresight-cti-platform.c | 53 +++ .../hwtracing/coresight/coresight-cti-sysfs.c | 72 +++ drivers/hwtracing/coresight/coresight-cti.c | 446 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-cti.h | 186 ++++++++ drivers/hwtracing/coresight/coresight.c | 3 + include/linux/coresight.h | 23 + 8 files changed, 798 insertions(+) create mode 100644 drivers/hwtracing/coresight/coresight-cti-platform.c create mode 100644 drivers/hwtracing/coresight/coresight-cti-sysfs.c create mode 100644 drivers/hwtracing/coresight/coresight-cti.c create mode 100644 drivers/hwtracing/coresight/coresight-cti.h diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 6ff30e25af55..45d3822c8c8c 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -110,4 +110,16 @@ 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 (CTI) driver" + depends on ARM || ARM64 + help + This driver provides support for CoreSight CTI and CTM components. + These provide hardware triggering events between CoreSight trace + source and sink components. These can be used to halt trace or + inject events into the trace stream. CTI also provides a software + control to trigger the same halt events. This can provide fast trace + halt compared to disabling sources and sinks normally in driver + software. + endif diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 3c0ac421e211..0e3e72f0f510 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -17,3 +17,6 @@ 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 \ + coresight-cti-platform.o \ + coresight-cti-sysfs.o diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c new file mode 100644 index 000000000000..665be86c585d --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, The Linaro Limited. All rights reserved. + */ + +#include + +#include "coresight-cti.h" + +/* get the hardware configuration & connection data. */ +int cti_plat_get_hw_data(struct device *dev, + struct cti_drvdata *drvdata) +{ + int rc = 0; + struct cti_device *cti_dev = &drvdata->ctidev; + + /* if no connections, just add a single default based on max IN-OUT */ + if (cti_dev->nr_trig_con == 0) + rc = cti_add_default_connection(dev, drvdata); + return rc; +} + +struct coresight_platform_data * +coresight_cti_get_platform_data(struct device *dev) +{ + int ret = -ENOENT; + struct coresight_platform_data *pdata = NULL; + struct fwnode_handle *fwnode = dev_fwnode(dev); + struct cti_drvdata *drvdata = dev_get_drvdata(dev); + + if (IS_ERR_OR_NULL(fwnode)) + goto error; + + /* + * Alloc platform data but leave it zero init. CTI does not use the + * same connection infrastructuree as trace path components but an + * empty struct enables us to use the standard coresight component + * registration code. + */ + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + ret = -ENOMEM; + goto error; + } + + /* get some CTI specifics */ + ret = cti_plat_get_hw_data(dev, drvdata); + + if (!ret) + return pdata; +error: + return ERR_PTR(ret); +} diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c new file mode 100644 index 000000000000..a832b8c6b866 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#include + +#include "coresight-cti.h" + +/* basic attributes */ +static ssize_t enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int enable_req; + bool enabled, powered; + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + ssize_t size = 0; + + enable_req = atomic_read(&drvdata->config.enable_req_count); + spin_lock(&drvdata->spinlock); + powered = drvdata->config.hw_powered; + enabled = drvdata->config.hw_enabled; + spin_unlock(&drvdata->spinlock); + + if (powered) { + size = scnprintf(buf, PAGE_SIZE, "cti %s; powered;\n", + enabled ? "enabled" : "disabled"); + } else { + size = scnprintf(buf, PAGE_SIZE, "cti %s; unpowered;\n", + enable_req ? "enable req" : "disabled"); + } + return size; +} + +static ssize_t enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + unsigned long val; + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + + if (val) + ret = cti_enable(drvdata->csdev); + else + ret = cti_disable(drvdata->csdev); + if (ret) + return ret; + return size; +} +static DEVICE_ATTR_RW(enable); + +/* attribute and group sysfs tables. */ +static struct attribute *coresight_cti_attrs[] = { + &dev_attr_enable.attr, + NULL, +}; + +static const struct attribute_group coresight_cti_group = { + .attrs = coresight_cti_attrs, +}; + +const struct attribute_group *coresight_cti_groups[] = { + &coresight_cti_group, + NULL, +}; diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c new file mode 100644 index 000000000000..c71b72d12534 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -0,0 +1,446 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#include "coresight-cti.h" + +/** + * CTI devices can be associated with a PE, or be connected to CoreSight + * hardware. We have a list of all CTIs irrespective of CPU bound or + * otherwise. + * + * We assume that the non-CPU CTIs are always powered as we do with sinks etc. + * + * We leave the client to figure out if all the CTIs are interconnected with + * the same CTM, in general this is the case but does not always have to be. + */ + +/* net of CTI devices connected via CTM */ +LIST_HEAD(ect_net); + +/* protect the list */ +static DEFINE_MUTEX(ect_mutex); + +#define csdev_to_cti_drvdata(csdev) \ + dev_get_drvdata(csdev->dev.parent) + +/* + * CTI naming. CTI bound to cores will have the name cti_cpu where + * N is the CPU ID. System CTIs will have the name cti_sys where I + * is an index allocated by order of discovery. + * + * CTI device name list - for CTI not bound to cores. + */ +DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys"); + +/* write set of regs to hardware - call with spinlock claimed */ +void cti_write_all_hw_regs(struct cti_drvdata *drvdata) +{ + struct cti_config *config = &drvdata->config; + int i; + + CS_UNLOCK(drvdata->base); + + /* disable CTI before writing registers */ + writel_relaxed(0, drvdata->base + CTICONTROL); + + /* write the CTI trigger registers */ + for (i = 0; i < config->nr_trig_max; i++) { + writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i)); + writel_relaxed(config->ctiouten[i], + drvdata->base + CTIOUTEN(i)); + } + + /* other regs */ + writel_relaxed(config->ctigate, drvdata->base + CTIGATE); + writel_relaxed(config->asicctl, drvdata->base + ASICCTL); + writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET); + + /* re-enable CTI */ + writel_relaxed(1, drvdata->base + CTICONTROL); + + CS_LOCK(drvdata->base); +} + +static void cti_enable_hw_smp_call(void *info) +{ + struct cti_drvdata *drvdata = info; + + cti_write_all_hw_regs(drvdata); +} + +/* write regs to hardware and enable */ +static int cti_enable_hw(struct cti_drvdata *drvdata) +{ + struct cti_config *config = &drvdata->config; + struct device *dev = &drvdata->csdev->dev; + int rc = 0; + + pm_runtime_get_sync(dev->parent); + spin_lock(&drvdata->spinlock); + + /* no need to do anything if enabled or unpowered*/ + if (config->hw_enabled || !config->hw_powered) + goto cti_state_unchanged; + + /* claim the device */ + rc = coresight_claim_device(drvdata->base); + if (rc) + goto cti_err_not_enabled; + + if (drvdata->ctidev.cpu >= 0) { + rc = smp_call_function_single(drvdata->ctidev.cpu, + cti_enable_hw_smp_call, + drvdata, 1); + if (rc) + goto cti_err_not_enabled; + } else { + cti_write_all_hw_regs(drvdata); + } + + config->hw_enabled = true; + atomic_inc(&drvdata->config.enable_req_count); + spin_unlock(&drvdata->spinlock); + return rc; + +cti_state_unchanged: + atomic_inc(&drvdata->config.enable_req_count); + + /* cannot enable due to error */ +cti_err_not_enabled: + spin_unlock(&drvdata->spinlock); + pm_runtime_put(dev->parent); + return rc; +} + +/* disable hardware */ +static int cti_disable_hw(struct cti_drvdata *drvdata) +{ + struct cti_config *config = &drvdata->config; + struct device *dev = &drvdata->csdev->dev; + + spin_lock(&drvdata->spinlock); + + /* check refcount - disable on 0 */ + if (atomic_dec_return(&drvdata->config.enable_req_count) > 0) + goto cti_not_disabled; + + /* no need to do anything if disabled or cpu unpowered */ + if (!config->hw_enabled || !config->hw_powered) + goto cti_not_disabled; + + CS_UNLOCK(drvdata->base); + + /* disable CTI */ + writel_relaxed(0, drvdata->base + CTICONTROL); + config->hw_enabled = false; + + coresight_disclaim_device_unlocked(drvdata->base); + CS_LOCK(drvdata->base); + spin_unlock(&drvdata->spinlock); + pm_runtime_put(dev); + return 0; + + /* not disabled this call */ +cti_not_disabled: + spin_unlock(&drvdata->spinlock); + return 0; +} + +/* + * Look at the HW DEVID register for some of the HW settings. + * DEVID[15:8] - max number of in / out triggers. + */ +#define CTI_DEVID_MAXTRIGS(devid_val) ((int) BMVAL(devid_val, 8, 15)) + +/* DEVID[19:16] - number of CTM channels */ +#define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19)) + +static void cti_set_default_config(struct device *dev, + struct cti_drvdata *drvdata) +{ + struct cti_config *config = &drvdata->config; + u32 devid; + + devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID); + config->nr_trig_max = CTI_DEVID_MAXTRIGS(devid); + + /* + * no current hardware should exceed this, but protect the driver + * in case of fault / out of spec hw + */ + if (config->nr_trig_max > CTIINOUTEN_MAX) { + dev_warn_once(dev, + "Limiting HW MaxTrig value(%d) to driver max(%d)\n", + config->nr_trig_max, CTIINOUTEN_MAX); + config->nr_trig_max = CTIINOUTEN_MAX; + } + + config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid); + + /* Most regs default to 0 as zalloc'ed except...*/ + config->trig_filter_enable = true; + config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0); + atomic_set(&config->enable_req_count, 0); +} + +/* + * Add a connection entry to the list of connections for this + * CTI device. + */ +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata, + struct cti_trig_con *tc, + struct coresight_device *csdev, + const char *assoc_dev_name) +{ + struct cti_device *cti_dev = &drvdata->ctidev; + + tc->con_dev = csdev; + /* + * Prefer actual associated CS device dev name to supplied value - + * which is likely to be node name / other conn name. + */ + if (csdev) + tc->con_dev_name = dev_name(&csdev->dev); + else if (assoc_dev_name != NULL) { + tc->con_dev_name = devm_kstrdup(dev, + assoc_dev_name, GFP_KERNEL); + if (!tc->con_dev_name) + return -ENOMEM; + } + list_add_tail(&tc->node, &cti_dev->trig_cons); + cti_dev->nr_trig_con++; + + /* add connection usage bit info to overall info */ + drvdata->config.trig_in_use |= tc->con_in->used_mask; + drvdata->config.trig_out_use |= tc->con_out->used_mask; + + return 0; +} + +/* create a trigger connection with appropriately sized signal groups */ +struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, + int out_sigs) +{ + struct cti_trig_con *tc = NULL; + struct cti_trig_grp *in = NULL, *out = NULL; + + tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL); + if (!tc) + return tc; + + in = devm_kzalloc(dev, + offsetof(struct cti_trig_grp, sig_types[in_sigs]), + GFP_KERNEL); + if (!in) + return NULL; + + out = devm_kzalloc(dev, + offsetof(struct cti_trig_grp, sig_types[out_sigs]), + GFP_KERNEL); + if (!out) + return NULL; + + tc->con_in = in; + tc->con_out = out; + tc->con_in->nr_sigs = in_sigs; + tc->con_out->nr_sigs = out_sigs; + return tc; +} + +/* + * Add a default connection if nothing else is specified. + * single connection based on max in/out info, no assoc device + */ +int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata) +{ + int ret = 0; + int n_trigs = drvdata->config.nr_trig_max; + u32 n_trig_mask = GENMASK(n_trigs - 1, 0); + struct cti_trig_con *tc = NULL; + + /* + * Assume max trigs for in and out, + * all used, default sig types allocated + */ + tc = cti_allocate_trig_con(dev, n_trigs, n_trigs); + if (!tc) + return -ENOMEM; + + tc->con_in->used_mask = n_trig_mask; + tc->con_out->used_mask = n_trig_mask; + ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default"); + return ret; +} + +/** cti ect operations **/ +int cti_enable(struct coresight_device *csdev) +{ + struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev); + + return cti_enable_hw(drvdata); +} + +int cti_disable(struct coresight_device *csdev) +{ + struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev); + + return cti_disable_hw(drvdata); +} + +const struct coresight_ops_ect cti_ops_ect = { + .enable = cti_enable, + .disable = cti_disable, +}; + +const struct coresight_ops cti_ops = { + .ect_ops = &cti_ops_ect, +}; + +/* + * Free up CTI specific resources + * called by dev->release, need to call down to underlying csdev release. + */ +static void cti_device_release(struct device *dev) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_drvdata *ect_item, *ect_tmp; + + mutex_lock(&ect_mutex); + + /* remove from the list */ + list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) { + if (ect_item == drvdata) { + list_del(&ect_item->node); + break; + } + } + mutex_unlock(&ect_mutex); + + if (drvdata->csdev_release) + drvdata->csdev_release(dev); +} + +static int cti_probe(struct amba_device *adev, const struct amba_id *id) +{ + int ret = 0; + void __iomem *base; + struct device *dev = &adev->dev; + struct cti_drvdata *drvdata = NULL; + struct coresight_desc cti_desc; + struct coresight_platform_data *pdata = NULL; + struct resource *res = &adev->res; + + /* driver data*/ + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) { + ret = -ENOMEM; + dev_info(dev, "%s, mem err\n", __func__); + goto err_out; + } + + /* Validity for the resource is already checked by the AMBA core */ + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) { + ret = PTR_ERR(base); + dev_err(dev, "%s, remap err\n", __func__); + goto err_out; + } + drvdata->base = base; + + dev_set_drvdata(dev, drvdata); + + /* default CTI device info */ + drvdata->ctidev.cpu = -1; + drvdata->ctidev.nr_trig_con = 0; + drvdata->ctidev.ctm_id = 0; + INIT_LIST_HEAD(&drvdata->ctidev.trig_cons); + + spin_lock_init(&drvdata->spinlock); + + /* initialise CTI driver config values */ + cti_set_default_config(dev, drvdata); + + pdata = coresight_cti_get_platform_data(dev); + if (IS_ERR(pdata)) { + dev_err(dev, "coresight_cti_get_platform_data err\n"); + ret = PTR_ERR(pdata); + goto err_out; + } + + /* default to powered - could change on PM notifications */ + drvdata->config.hw_powered = true; + + /* set up device name - will depend if cpu bound or otherwise */ + if (drvdata->ctidev.cpu >= 0) + cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d", + drvdata->ctidev.cpu); + else + cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev); + if (!cti_desc.name) { + ret = -ENOMEM; + goto err_out; + } + + /* set up coresight component description */ + cti_desc.pdata = pdata; + cti_desc.type = CORESIGHT_DEV_TYPE_ECT; + cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI; + cti_desc.ops = &cti_ops; + cti_desc.groups = coresight_cti_groups; + cti_desc.dev = dev; + drvdata->csdev = coresight_register(&cti_desc); + if (IS_ERR(drvdata->csdev)) { + ret = PTR_ERR(drvdata->csdev); + goto err_out; + } + + /* add to list of CTI devices */ + mutex_lock(&ect_mutex); + list_add(&drvdata->node, &ect_net); + mutex_unlock(&ect_mutex); + + /* set up release chain */ + drvdata->csdev_release = drvdata->csdev->dev.release; + drvdata->csdev->dev.release = cti_device_release; + + /* all done - dec pm refcount */ + pm_runtime_put(&adev->dev); + dev_info(&drvdata->csdev->dev, "CTI initialized\n"); + return 0; + +err_out: + return ret; +} + +static struct amba_cs_uci_id uci_id_cti[] = { + { + /* CTI UCI data */ + .devarch = 0x47701a14, /* CTI v2 */ + .devarch_mask = 0xfff0ffff, + .devtype = 0x00000014, /* maj(0x4-debug) min(0x1-ECT) */ + } +}; + +static const struct amba_id cti_ids[] = { + CS_AMBA_ID(0x000bb906), /* Coresight CTI (SoC 400), C-A72, C-A57 */ + CS_AMBA_ID(0x000bb922), /* CTI - C-A8 */ + CS_AMBA_ID(0x000bb9a8), /* CTI - C-A53 */ + CS_AMBA_ID(0x000bb9aa), /* CTI - C-A73 */ + CS_AMBA_UCI_ID(0x000bb9da, uci_id_cti), /* CTI - C-A35 */ + CS_AMBA_UCI_ID(0x000bb9ed, uci_id_cti), /* Coresight CTI (SoC 600) */ + { 0, 0}, +}; + +static struct amba_driver cti_driver = { + .drv = { + .name = "coresight-cti", + .owner = THIS_MODULE, + .suppress_bind_attrs = true, + }, + .probe = cti_probe, + .id_table = cti_ids, +}; +builtin_amba_driver(cti_driver); diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h new file mode 100644 index 000000000000..d0ac90f49544 --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 Linaro Limited, All rights reserved. + * Author: Mike Leach + */ + +#ifndef _CORESIGHT_CORESIGHT_CTI_H +#define _CORESIGHT_CORESIGHT_CTI_H + +#include +#include +#include "coresight-priv.h" + +/* + * Device registers + * 0x000 - 0x144: CTI programming and status + * 0xEDC - 0xEF8: CTI integration test. + * 0xF00 - 0xFFC: Coresight management registers. + */ +/* CTI programming registers */ +#define CTICONTROL 0x000 +#define CTIINTACK 0x010 +#define CTIAPPSET 0x014 +#define CTIAPPCLEAR 0x018 +#define CTIAPPPULSE 0x01C +#define CTIINEN(n) (0x020 + (4 * n)) +#define CTIOUTEN(n) (0x0A0 + (4 * n)) +#define CTITRIGINSTATUS 0x130 +#define CTITRIGOUTSTATUS 0x134 +#define CTICHINSTATUS 0x138 +#define CTICHOUTSTATUS 0x13C +#define CTIGATE 0x140 +#define ASICCTL 0x144 +/* Integration test registers */ +#define ITCHINACK 0xEDC /* WO CTI CSSoc 400 only*/ +#define ITTRIGINACK 0xEE0 /* WO CTI CSSoc 400 only*/ +#define ITCHOUT 0xEE4 /* WO RW-600 */ +#define ITTRIGOUT 0xEE8 /* WO RW-600 */ +#define ITCHOUTACK 0xEEC /* RO CTI CSSoc 400 only*/ +#define ITTRIGOUTACK 0xEF0 /* RO CTI CSSoc 400 only*/ +#define ITCHIN 0xEF4 /* RO */ +#define ITTRIGIN 0xEF8 /* RO */ +/* management registers */ +#define CTIDEVAFF0 0xFA8 +#define CTIDEVAFF1 0xFAC + +/* + * CTI CSSoc 600 has a max of 32 trigger signals per direction. + * CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def. + * Max of in and out defined in the DEVID register. + * - pick up actual number used from .dts parameters if present. + */ +#define CTIINOUTEN_MAX 32 + +/** + * Group of related trigger signals + * + * @nr_sigs: number of signals in the group. + * @used_mask: bitmask representing the signal indexes in the group. + * @sig_types: array of types for the signals, length nr_sigs. + */ +struct cti_trig_grp { + int nr_sigs; + u32 used_mask; + int sig_types[]; +}; + +/** + * Trigger connection - connection between a CTI and other (coresight) device + * lists input and output trigger signals for the device + * + * @con_in: connected CTIIN signals for the device. + * @con_out: connected CTIOUT signals for the device. + * @con_dev: coresight device connected to the CTI, NULL if not CS device + * @con_dev_name: name of connected device (CS or CPU) + * @node: entry node in list of connections. + */ +struct cti_trig_con { + struct cti_trig_grp *con_in; + struct cti_trig_grp *con_out; + struct coresight_device *con_dev; + const char *con_dev_name; + struct list_head node; +}; + +/** + * struct cti_device - description of CTI device properties. + * + * @nt_trig_con: Number of external devices connected to this device. + * @ctm_id: which CTM this device is connected to (by default it is + * assumed there is a single CTM per SoC, ID 0). + * @trig_cons: list of connections to this device. + * @cpu: CPU ID if associated with CPU, -1 otherwise. + */ +struct cti_device { + int nr_trig_con; + u32 ctm_id; + struct list_head trig_cons; + int cpu; +}; + +/** + * struct cti_config - configuration of the CTI device hardware + * + * @nr_trig_max: Max number of trigger signals implemented on device. + * (max of trig_in or trig_out) - from ID register. + * @nr_ctm_channels: number of available CTM channels - from ID register. + * @enable_req_count: CTI is enabled alongside >=1 associated devices. + * @hw_enabled: true if hw is currently enabled. + * @hw_powered: true if associated cpu powered on, or no cpu. + * @trig_in_use: bitfield of in triggers registered as in use. + * @trig_out_use: bitfield of out triggers registered as in use. + * @trig_out_filter: bitfield of out triggers that are blocked if filter + * enabled. Typically this would be dbgreq / restart on + * a core CTI. + * @trig_filter_enable: 1 if filtering enabled. + * @xtrig_rchan_sel: channel selection for xtrigger connection show. + * @ctiappset: CTI Software application channel set. + * @ctiinout_sel: register selector for INEN and OUTEN regs. + * @ctiinen: enable input trigger to a channel. + * @ctiouten: enable output trigger from a channel. + * @ctigate: gate channel output from CTI to CTM. + * @asicctl: asic control register. + */ +struct cti_config { + /* hardware description */ + int nr_ctm_channels; + int nr_trig_max; + + /* cti enable control */ + atomic_t enable_req_count; + bool hw_enabled; + bool hw_powered; + + /* registered triggers and filtering */ + u32 trig_in_use; + u32 trig_out_use; + u32 trig_out_filter; + bool trig_filter_enable; + u8 xtrig_rchan_sel; + + /* cti cross trig programmable regs */ + u32 ctiappset; + u8 ctiinout_sel; + u32 ctiinen[CTIINOUTEN_MAX]; + u32 ctiouten[CTIINOUTEN_MAX]; + u32 ctigate; + u32 asicctl; +}; + +/** + * struct cti_drvdata - specifics for the CTI device + * @base: Memory mapped base address for this component.. + * @csdev: Standard CoreSight device information. + * @ctidev: Extra information needed by the CTI/CTM framework. + * @spinlock: Control data access to one at a time. + * @config: Configuration data for this CTI device. + * @node: List entry of this device in the list of CTI devices. + * @csdev_release: release function for underlying coresight_device. + */ +struct cti_drvdata { + void __iomem *base; + struct coresight_device *csdev; + struct cti_device ctidev; + spinlock_t spinlock; + struct cti_config config; + struct list_head node; + void (*csdev_release)(struct device *dev); +}; + +/* private cti driver fns & vars */ +extern const struct attribute_group *coresight_cti_groups[]; +int cti_add_default_connection(struct device *dev, + struct cti_drvdata *drvdata); +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata, + struct cti_trig_con *tc, + struct coresight_device *csdev, + const char *assoc_dev_name); +struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, + int out_sigs); +int cti_enable(struct coresight_device *csdev); +int cti_disable(struct coresight_device *csdev); +struct coresight_platform_data * +coresight_cti_get_platform_data(struct device *dev); + +#endif /* _CORESIGHT_CORESIGHT_CTI_H */ diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index ef20f74c85fa..1a5fdf2710ff 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -955,6 +955,9 @@ static struct device_type coresight_dev_type[] = { { .name = "helper", }, + { + .name = "ect", + }, }; static void coresight_device_release(struct device *dev) diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 44e552de419c..b3e582d96a34 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -41,6 +41,7 @@ enum coresight_dev_type { CORESIGHT_DEV_TYPE_LINKSINK, CORESIGHT_DEV_TYPE_SOURCE, CORESIGHT_DEV_TYPE_HELPER, + CORESIGHT_DEV_TYPE_ECT, }; enum coresight_dev_subtype_sink { @@ -68,6 +69,12 @@ enum coresight_dev_subtype_helper { CORESIGHT_DEV_SUBTYPE_HELPER_CATU, }; +/* Embedded Cross Trigger (ECT) sub-types */ +enum coresight_dev_subtype_ect { + CORESIGHT_DEV_SUBTYPE_ECT_NONE, + CORESIGHT_DEV_SUBTYPE_ECT_CTI, +}; + /** * union coresight_dev_subtype - further characterisation of a type * @sink_subtype: type of sink this component is, as defined @@ -78,6 +85,8 @@ enum coresight_dev_subtype_helper { * by @coresight_dev_subtype_source. * @helper_subtype: type of helper this component is, as defined * by @coresight_dev_subtype_helper. + * @ect_subtype: type of cross trigger this component is, as + * defined by @coresight_dev_subtype_ect */ union coresight_dev_subtype { /* We have some devices which acts as LINK and SINK */ @@ -87,6 +96,7 @@ union coresight_dev_subtype { }; enum coresight_dev_subtype_source source_subtype; enum coresight_dev_subtype_helper helper_subtype; + enum coresight_dev_subtype_ect ect_subtype; }; /** @@ -196,6 +206,7 @@ static struct coresight_dev_list (var) = { \ #define sink_ops(csdev) csdev->ops->sink_ops #define link_ops(csdev) csdev->ops->link_ops #define helper_ops(csdev) csdev->ops->helper_ops +#define ect_ops(csdev) csdev->ops->ect_ops /** * struct coresight_ops_sink - basic operations for a sink @@ -262,11 +273,23 @@ struct coresight_ops_helper { int (*disable)(struct coresight_device *csdev, void *data); }; +/** + * struct coresight_ops_ect - Ops for an embedded cross trigger device + * + * @enable : Enable the device + * @disable : Disable the device + */ +struct coresight_ops_ect { + int (*enable)(struct coresight_device *csdev); + int (*disable)(struct coresight_device *csdev); +}; + struct coresight_ops { const struct coresight_ops_sink *sink_ops; const struct coresight_ops_link *link_ops; const struct coresight_ops_source *source_ops; const struct coresight_ops_helper *helper_ops; + const struct coresight_ops_ect *ect_ops; }; #ifdef CONFIG_CORESIGHT From patchwork Tue Feb 25 23:46:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 204229 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 62518C4BA0B for ; Tue, 25 Feb 2020 23:46:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1D9BF21927 for ; Tue, 25 Feb 2020 23:46:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="vpygi7O/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728865AbgBYXqi (ORCPT ); Tue, 25 Feb 2020 18:46:38 -0500 Received: from mail-wr1-f68.google.com ([209.85.221.68]:41275 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729513AbgBYXqi (ORCPT ); Tue, 25 Feb 2020 18:46:38 -0500 Received: by mail-wr1-f68.google.com with SMTP id v4so748830wrs.8 for ; Tue, 25 Feb 2020 15:46:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/hmK8ozpjgWrUPPLRxuFws/yab2ZXjdbgaAdirdJ8Ls=; b=vpygi7O/Q6vjKqbgTNbzEOvao95g1mjiIqPRO5F6h27ufwbKMehfNWbJg4Brb5Ht2M t9nSTPJRP0QPvKXy/U3eXcHWIX3r4W44QLdFb9NC70UvMZGTQMykgnFhcOsx2T6rkNKI gLVu32ClAlP82Iqz6xnPveV3h+4YjfhRpr8HX2SLajE3J0O4NDj9B9Ve811BipeZUKBF WFwrrJZxw9E2svGSLqAQpBzQPzSRaQprGxUk3zCWi9oYn3cJNieVcJErAznGDgHLmO6s vTgEqRwtFsDbFq6EQ8AkMKu5Hd+kVOVcxnqCQA5oZ7N8TOFy06YsYVMDzOJ+uVtDCD8c ehFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/hmK8ozpjgWrUPPLRxuFws/yab2ZXjdbgaAdirdJ8Ls=; b=FKBA3HzcJtw0KSczWIjoZbfMY67waEa6UR++xiW8s/rtF1JBZ8rQaU810dMSnXzS9O khikd4vTtsW9mqUvAdHsNXgqHGPwB7MruUaIT+bP5UD7PUle/mOxxWknc4Ga4O4BkYU6 rrBpBZ2JsuUN1j4wzbVos0Y3NYnINLrm/xCS4sNVt3I0HAbEKA2uUcCDcI3YWraksnQI D6tluOKLtojR0IP7lbSMfmMJdFxaSXI/FecGji5OeKKUG6je1mqcf95MCB4uum9daXGe RCAjjbRUjOkxH5mrO3a6BIRjdA54OGM8P/LoQ8ZSt+wpg2HTHP2XGKWz97pnWphB/TE+ dcBQ== X-Gm-Message-State: APjAAAUcgfJxgrDir7LDZVwaX1IA7zEcjoGybWQuVidcG7xXcDS133eE PmvZYB2cCMFflKqX/XqFpVoZ4DajoOg= X-Google-Smtp-Source: APXvYqy2jqvxmEJ/C70XhE7l+zFg5yRK6TZm101W3HHJxXmPEmVQYxns9VOrgusvcqicLmOETnYzMw== X-Received: by 2002:adf:e949:: with SMTP id m9mr1644360wrn.342.1582674394918; Tue, 25 Feb 2020 15:46:34 -0800 (PST) Received: from linaro.org ([2a00:23c5:6815:3901:186c:5f6c:221d:5ce]) by smtp.gmail.com with ESMTPSA id t133sm356278wmf.31.2020.02.25.15.46.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 15:46:34 -0800 (PST) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, coresight@lists.linaro.org, linux-doc@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org, mathieu.poirier@linaro.org, suzuki.poulose@arm.com, robh+dt@kernel.org, maxime@cerno.tech, liviu.dudau@arm.com, sudeep.holla@arm.com, lorenzo.pieralisi@arm.com, agross@kernel.org, corbet@lwn.net, Mike Leach Subject: [PATCH v10 04/15] coresight: cti: Add sysfs trigger / channel programming API Date: Tue, 25 Feb 2020 23:46:00 +0000 Message-Id: <20200225234611.11067-5-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200225234611.11067-1-mike.leach@linaro.org> References: <20200225234611.11067-1-mike.leach@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Adds a user API to allow programming of CTI by trigger ID and channel number. This will take the channel and trigger ID supplied by the user and program the appropriate register values. Signed-off-by: Mike Leach Reviewed-by: Mathieu Poirier Reviewed-by: Suzuki K Poulose --- .../hwtracing/coresight/coresight-cti-sysfs.c | 349 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-cti.c | 147 ++++++++ drivers/hwtracing/coresight/coresight-cti.h | 32 ++ 3 files changed, 528 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index f687e07b68b0..37e71724b67b 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -463,6 +463,349 @@ static struct attribute *coresight_cti_regs_attrs[] = { NULL, }; +/* CTI channel x-trigger programming */ +static int +cti_trig_op_parse(struct device *dev, enum cti_chan_op op, + enum cti_trig_dir dir, const char *buf, size_t size) +{ + u32 chan_idx; + u32 trig_idx; + int items, err = -EINVAL; + + /* extract chan idx and trigger idx */ + items = sscanf(buf, "%d %d", &chan_idx, &trig_idx); + if (items == 2) { + err = cti_channel_trig_op(dev, op, dir, chan_idx, trig_idx); + if (!err) + err = size; + } + return err; +} + +static ssize_t trigin_attach_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + return cti_trig_op_parse(dev, CTI_CHAN_ATTACH, CTI_TRIG_IN, + buf, size); +} +static DEVICE_ATTR_WO(trigin_attach); + +static ssize_t trigin_detach_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + return cti_trig_op_parse(dev, CTI_CHAN_DETACH, CTI_TRIG_IN, + buf, size); +} +static DEVICE_ATTR_WO(trigin_detach); + +static ssize_t trigout_attach_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + return cti_trig_op_parse(dev, CTI_CHAN_ATTACH, CTI_TRIG_OUT, + buf, size); +} +static DEVICE_ATTR_WO(trigout_attach); + +static ssize_t trigout_detach_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + return cti_trig_op_parse(dev, CTI_CHAN_DETACH, CTI_TRIG_OUT, + buf, size); +} +static DEVICE_ATTR_WO(trigout_detach); + + +static ssize_t chan_gate_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int err = 0, channel = 0; + + if (kstrtoint(buf, 0, &channel)) + return -EINVAL; + + err = cti_channel_gate_op(dev, CTI_GATE_CHAN_ENABLE, channel); + return err ? err : size; +} + +static ssize_t chan_gate_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_config *cfg = &drvdata->config; + unsigned long ctigate_bitmask = cfg->ctigate; + int size = 0; + + if (cfg->ctigate == 0) + size = scnprintf(buf, PAGE_SIZE, "\n"); + else + size = bitmap_print_to_pagebuf(true, buf, &ctigate_bitmask, + cfg->nr_ctm_channels); + return size; +} +static DEVICE_ATTR_RW(chan_gate_enable); + +static ssize_t chan_gate_disable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int err = 0, channel = 0; + + if (kstrtoint(buf, 0, &channel)) + return -EINVAL; + + err = cti_channel_gate_op(dev, CTI_GATE_CHAN_DISABLE, channel); + return err ? err : size; +} +static DEVICE_ATTR_WO(chan_gate_disable); + +static int +chan_op_parse(struct device *dev, enum cti_chan_set_op op, const char *buf) +{ + int err = 0, channel = 0; + + if (kstrtoint(buf, 0, &channel)) + return -EINVAL; + + err = cti_channel_setop(dev, op, channel); + return err; + +} + +static ssize_t chan_set_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int err = chan_op_parse(dev, CTI_CHAN_SET, buf); + + return err ? err : size; +} +static DEVICE_ATTR_WO(chan_set); + +static ssize_t chan_clear_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int err = chan_op_parse(dev, CTI_CHAN_CLR, buf); + + return err ? err : size; +} +static DEVICE_ATTR_WO(chan_clear); + +static ssize_t chan_pulse_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int err = chan_op_parse(dev, CTI_CHAN_PULSE, buf); + + return err ? err : size; +} +static DEVICE_ATTR_WO(chan_pulse); + +static ssize_t trig_filter_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + u32 val; + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + + spin_lock(&drvdata->spinlock); + val = drvdata->config.trig_filter_enable; + spin_unlock(&drvdata->spinlock); + return scnprintf(buf, PAGE_SIZE, "%d\n", val); +} + +static ssize_t trig_filter_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned long val; + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->config.trig_filter_enable = !!val; + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_RW(trig_filter_enable); + +static ssize_t trigout_filtered_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_config *cfg = &drvdata->config; + int size = 0, nr_trig_max = cfg->nr_trig_max; + unsigned long mask = cfg->trig_out_filter; + + if (mask) + size = bitmap_print_to_pagebuf(true, buf, &mask, nr_trig_max); + return size; +} +static DEVICE_ATTR_RO(trigout_filtered); + +/* clear all xtrigger / channel programming */ +static ssize_t chan_xtrigs_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int i; + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_config *config = &drvdata->config; + + spin_lock(&drvdata->spinlock); + + /* clear the CTI trigger / channel programming registers */ + for (i = 0; i < config->nr_trig_max; i++) { + config->ctiinen[i] = 0; + config->ctiouten[i] = 0; + } + + /* clear the other regs */ + config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0); + config->asicctl = 0; + config->ctiappset = 0; + config->ctiinout_sel = 0; + config->xtrig_rchan_sel = 0; + + /* if enabled then write through */ + if (cti_active(config)) + cti_write_all_hw_regs(drvdata); + + spin_unlock(&drvdata->spinlock); + return size; +} +static DEVICE_ATTR_WO(chan_xtrigs_reset); + +/* + * Write to select a channel to view, read to display the + * cross triggers for the selected channel. + */ +static ssize_t chan_xtrigs_view_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned long val; + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + + if (kstrtoul(buf, 0, &val)) + return -EINVAL; + if (val > (drvdata->config.nr_ctm_channels - 1)) + return -EINVAL; + + spin_lock(&drvdata->spinlock); + drvdata->config.xtrig_rchan_sel = val; + spin_unlock(&drvdata->spinlock); + return size; +} + +static ssize_t chan_xtrigs_view_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_config *cfg = &drvdata->config; + int used = 0, reg_idx; + int buf_sz = PAGE_SIZE; + u32 chan_mask = BIT(cfg->xtrig_rchan_sel); + + used += scnprintf(buf, buf_sz, "[%d] IN: ", cfg->xtrig_rchan_sel); + for (reg_idx = 0; + reg_idx < drvdata->config.nr_trig_max; + reg_idx++) { + if (chan_mask & cfg->ctiinen[reg_idx]) { + used += scnprintf(buf + used, buf_sz - used, "%d ", + reg_idx); + } + } + + used += scnprintf(buf + used, buf_sz - used, "OUT: "); + for (reg_idx = 0; + reg_idx < drvdata->config.nr_trig_max; + reg_idx++) { + if (chan_mask & cfg->ctiouten[reg_idx]) { + used += scnprintf(buf + used, buf_sz - used, "%d ", + reg_idx); + } + } + used += scnprintf(buf + used, buf_sz - used, "\n"); + return used; +} +static DEVICE_ATTR_RW(chan_xtrigs_view); + +static ssize_t print_chan_list(struct device *dev, + char *buf, bool inuse) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_config *config = &drvdata->config; + int size, i; + unsigned long inuse_bits = 0, chan_mask; + + /* scan regs to get bitmap of channels in use. */ + spin_lock(&drvdata->spinlock); + for (i = 0; i < config->nr_trig_max; i++) { + inuse_bits |= config->ctiinen[i]; + inuse_bits |= config->ctiouten[i]; + } + spin_unlock(&drvdata->spinlock); + + /* inverse bits if printing free channels */ + if (!inuse) + inuse_bits = ~inuse_bits; + + /* list of channels, or 'none' */ + chan_mask = GENMASK(config->nr_ctm_channels - 1, 0); + if (inuse_bits & chan_mask) + size = bitmap_print_to_pagebuf(true, buf, &inuse_bits, + config->nr_ctm_channels); + else + size = scnprintf(buf, PAGE_SIZE, "\n"); + return size; +} + +static ssize_t chan_inuse_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return print_chan_list(dev, buf, true); +} +static DEVICE_ATTR_RO(chan_inuse); + +static ssize_t chan_free_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return print_chan_list(dev, buf, false); +} +static DEVICE_ATTR_RO(chan_free); + +static struct attribute *coresight_cti_channel_attrs[] = { + &dev_attr_trigin_attach.attr, + &dev_attr_trigin_detach.attr, + &dev_attr_trigout_attach.attr, + &dev_attr_trigout_detach.attr, + &dev_attr_trig_filter_enable.attr, + &dev_attr_trigout_filtered.attr, + &dev_attr_chan_gate_enable.attr, + &dev_attr_chan_gate_disable.attr, + &dev_attr_chan_set.attr, + &dev_attr_chan_clear.attr, + &dev_attr_chan_pulse.attr, + &dev_attr_chan_inuse.attr, + &dev_attr_chan_free.attr, + &dev_attr_chan_xtrigs_view.attr, + &dev_attr_chan_xtrigs_reset.attr, + NULL, +}; + /* sysfs groups */ static const struct attribute_group coresight_cti_group = { .attrs = coresight_cti_attrs, @@ -478,9 +821,15 @@ static const struct attribute_group coresight_cti_regs_group = { .name = "regs", }; +static const struct attribute_group coresight_cti_channels_group = { + .attrs = coresight_cti_channel_attrs, + .name = "channels", +}; + const struct attribute_group *coresight_cti_groups[] = { &coresight_cti_group, &coresight_cti_mgmt_group, &coresight_cti_regs_group, + &coresight_cti_channels_group, NULL, }; diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index e0748cc92384..b8c94027fed0 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -294,6 +294,153 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata) return ret; } +/** cti channel api **/ +/* attach/detach channel from trigger - write through if enabled. */ +int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, + enum cti_trig_dir direction, u32 channel_idx, + u32 trigger_idx) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_config *config = &drvdata->config; + u32 trig_bitmask; + u32 chan_bitmask; + u32 reg_value; + int reg_offset; + + /* ensure indexes in range */ + if ((channel_idx >= config->nr_ctm_channels) || + (trigger_idx >= config->nr_trig_max)) + return -EINVAL; + + trig_bitmask = BIT(trigger_idx); + + /* ensure registered triggers and not out filtered */ + if (direction == CTI_TRIG_IN) { + if (!(trig_bitmask & config->trig_in_use)) + return -EINVAL; + } else { + if (!(trig_bitmask & config->trig_out_use)) + return -EINVAL; + + if ((config->trig_filter_enable) && + (config->trig_out_filter & trig_bitmask)) + return -EINVAL; + } + + /* update the local register values */ + chan_bitmask = BIT(channel_idx); + reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) : + CTIOUTEN(trigger_idx)); + + spin_lock(&drvdata->spinlock); + + /* read - modify write - the trigger / channel enable value */ + reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] : + config->ctiouten[trigger_idx]; + if (op == CTI_CHAN_ATTACH) + reg_value |= chan_bitmask; + else + reg_value &= ~chan_bitmask; + + /* write local copy */ + if (direction == CTI_TRIG_IN) + config->ctiinen[trigger_idx] = reg_value; + else + config->ctiouten[trigger_idx] = reg_value; + + /* write through if enabled */ + if (cti_active(config)) + cti_write_single_reg(drvdata, reg_offset, reg_value); + spin_unlock(&drvdata->spinlock); + return 0; +} + +int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op, + u32 channel_idx) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_config *config = &drvdata->config; + u32 chan_bitmask; + u32 reg_value; + int err = 0; + + if (channel_idx >= config->nr_ctm_channels) + return -EINVAL; + + chan_bitmask = BIT(channel_idx); + + spin_lock(&drvdata->spinlock); + reg_value = config->ctigate; + switch (op) { + case CTI_GATE_CHAN_ENABLE: + reg_value |= chan_bitmask; + break; + + case CTI_GATE_CHAN_DISABLE: + reg_value &= ~chan_bitmask; + break; + + default: + err = -EINVAL; + break; + } + if (err == 0) { + config->ctigate = reg_value; + if (cti_active(config)) + cti_write_single_reg(drvdata, CTIGATE, reg_value); + } + spin_unlock(&drvdata->spinlock); + return err; +} + +int cti_channel_setop(struct device *dev, enum cti_chan_set_op op, + u32 channel_idx) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct cti_config *config = &drvdata->config; + u32 chan_bitmask; + u32 reg_value; + u32 reg_offset; + int err = 0; + + if (channel_idx >= config->nr_ctm_channels) + return -EINVAL; + + chan_bitmask = BIT(channel_idx); + + spin_lock(&drvdata->spinlock); + reg_value = config->ctiappset; + switch (op) { + case CTI_CHAN_SET: + config->ctiappset |= chan_bitmask; + reg_value = config->ctiappset; + reg_offset = CTIAPPSET; + break; + + case CTI_CHAN_CLR: + config->ctiappset &= ~chan_bitmask; + reg_value = chan_bitmask; + reg_offset = CTIAPPCLEAR; + break; + + case CTI_CHAN_PULSE: + config->ctiappset &= ~chan_bitmask; + reg_value = chan_bitmask; + reg_offset = CTIAPPPULSE; + break; + + default: + err = -EINVAL; + break; + } + + if ((err == 0) && cti_active(config)) + cti_write_single_reg(drvdata, reg_offset, reg_value); + spin_unlock(&drvdata->spinlock); + + return err; +} + /** cti ect operations **/ int cti_enable(struct coresight_device *csdev) { diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index 35eb77b276c4..f664b4bb4644 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -168,6 +168,30 @@ struct cti_drvdata { void (*csdev_release)(struct device *dev); }; +/* + * Channel operation types. + */ +enum cti_chan_op { + CTI_CHAN_ATTACH, + CTI_CHAN_DETACH, +}; + +enum cti_trig_dir { + CTI_TRIG_IN, + CTI_TRIG_OUT, +}; + +enum cti_chan_gate_op { + CTI_GATE_CHAN_ENABLE, + CTI_GATE_CHAN_DISABLE, +}; + +enum cti_chan_set_op { + CTI_CHAN_SET, + CTI_CHAN_CLR, + CTI_CHAN_PULSE, +}; + /* private cti driver fns & vars */ extern const struct attribute_group *coresight_cti_groups[]; int cti_add_default_connection(struct device *dev, @@ -180,8 +204,16 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs, int out_sigs); int cti_enable(struct coresight_device *csdev); int cti_disable(struct coresight_device *csdev); +void cti_write_all_hw_regs(struct cti_drvdata *drvdata); void cti_write_intack(struct device *dev, u32 ackval); void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value); +int cti_channel_trig_op(struct device *dev, enum cti_chan_op op, + enum cti_trig_dir direction, u32 channel_idx, + u32 trigger_idx); +int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op, + u32 channel_idx); +int cti_channel_setop(struct device *dev, enum cti_chan_set_op op, + u32 channel_idx); struct coresight_platform_data * coresight_cti_get_platform_data(struct device *dev); From patchwork Tue Feb 25 23:46:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 204233 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0891FC4BA14 for ; Tue, 25 Feb 2020 23:46:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C14892072D for ; Tue, 25 Feb 2020 23:46:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="ebQwmFzh" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729566AbgBYXql (ORCPT ); Tue, 25 Feb 2020 18:46:41 -0500 Received: from mail-wr1-f67.google.com ([209.85.221.67]:35283 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729543AbgBYXqk (ORCPT ); Tue, 25 Feb 2020 18:46:40 -0500 Received: by mail-wr1-f67.google.com with SMTP id w12so792439wrt.2 for ; Tue, 25 Feb 2020 15:46:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/8jY15B3jg+dOEXGPWEr/eswdwAs6rpSaZh6D8u8fRo=; b=ebQwmFzhJOHokQ22fDgCiUUqthCserSNItrGSz5aNK2Vnzo2L+HD2DTLzUai5p46bb 3Dr0yscPoT+eNhKM/lBEaHYzQdDectyuFyNV1Ts6v0j+IsrL+xmWlijt9nFbVFK6VeYW xIW6pSmR1arP59fpnVtOfSrxNKDZpPV+w7fqA0LpFQFBfuBEz3Of++iCve8nNGXtXwB0 aBeVt06eyPt2Xp7wLB3BbYNm6fa9k+7oXAiYVS9HuHMloTu606OS/Y3YsKTDzWHjxlUh W9KtW0LAZJEVSP3TP2u9DOWeKefV9sHvJpq29fMNETRWutePDc/3qL/1VQalf9e0zWQa 0Hhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/8jY15B3jg+dOEXGPWEr/eswdwAs6rpSaZh6D8u8fRo=; b=nU3uNWblgxgFSVoGLmTQt1soCu1IBABF5UGGbWgEz/oGTBRTOOBrvHqzJRqHvCNFWm r9ncirxxENX1oMfU87IGh6lktOdw/YW0No3f+wgjqYEfyPPZc0VGYEm8Xyk6fiIc343a eactzvenq9iSNzas1RW3mTB27qR0+wZA9LyT3Xbz8Lz10Id1QrS0spnD2HIUzBFsMHaN CX1S3qsT51hDXRivjT+UzlYdSaf7kpg1Smf1PAqoVysbh89NDyFjbeZvOw2HnJWDRWnM HWWqhLWjh32C6EZUnDMaUFh6gMdTAewyip91SjdsEhDmkdsDoA/yOKUIJdS2rbpT4ig/ QTLg== X-Gm-Message-State: APjAAAVX3qne33Mg4DSzoRQyaT/dYxpZ35WmAhSixz50uOX1nqvISPfG 3MPTftr/DNhiYDN/VHaazZaSeg== X-Google-Smtp-Source: APXvYqzqZM9jSQAsR8CX0dw+00Uz9WaAMXKUmSjEz9jGYOHO2CXICeTMdbxWGoBIDzAPosLh+Qn+Hg== X-Received: by 2002:adf:f20b:: with SMTP id p11mr1421462wro.195.1582674397584; Tue, 25 Feb 2020 15:46:37 -0800 (PST) Received: from linaro.org ([2a00:23c5:6815:3901:186c:5f6c:221d:5ce]) by smtp.gmail.com with ESMTPSA id t133sm356278wmf.31.2020.02.25.15.46.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 15:46:36 -0800 (PST) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, coresight@lists.linaro.org, linux-doc@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org, mathieu.poirier@linaro.org, suzuki.poulose@arm.com, robh+dt@kernel.org, maxime@cerno.tech, liviu.dudau@arm.com, sudeep.holla@arm.com, lorenzo.pieralisi@arm.com, agross@kernel.org, corbet@lwn.net, Mike Leach Subject: [PATCH v10 06/15] coresight: cti: Add device tree support for v8 arch CTI Date: Tue, 25 Feb 2020 23:46:02 +0000 Message-Id: <20200225234611.11067-7-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200225234611.11067-1-mike.leach@linaro.org> References: <20200225234611.11067-1-mike.leach@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The v8 architecture defines the relationship between a PE, its optional ETM and a CTI. Unlike non-architectural CTIs which are implementation defined, this has a fixed set of connections which can therefore be represented as a simple tag in the device tree. This patch defines the tags needed to create an entry for this PE/ETM/CTI relationship, and provides functionality to implement the connection model in the CTI driver. Signed-off-by: Mike Leach Reviewed-by: Mathieu Poirier Reviewed-by: Suzuki K Poulose --- .../coresight/coresight-cti-platform.c | 205 ++++++++++++++++++ .../hwtracing/coresight/coresight-platform.c | 20 ++ drivers/hwtracing/coresight/coresight-priv.h | 2 + drivers/hwtracing/coresight/coresight.c | 12 +- 4 files changed, 230 insertions(+), 9 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c index 665be86c585d..36a276eda50a 100644 --- a/drivers/hwtracing/coresight/coresight-cti-platform.c +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -3,10 +3,208 @@ * Copyright (c) 2019, The Linaro Limited. All rights reserved. */ +#include #include #include "coresight-cti.h" +/* Number of CTI signals in the v8 architecturally defined connection */ +#define NR_V8PE_IN_SIGS 2 +#define NR_V8PE_OUT_SIGS 3 +#define NR_V8ETM_INOUT_SIGS 4 + +/* CTI device tree connection property keywords */ +#define CTI_DT_V8ARCH_COMPAT "arm,coresight-cti-v8-arch" +#define CTI_DT_CSDEV_ASSOC "arm,cs-dev-assoc" + +#ifdef CONFIG_OF +/* + * CTI can be bound to a CPU, or a system device. + * CPU can be declared at the device top level or in a connections node + * so need to check relative to node not device. + */ +static int of_cti_get_cpu_at_node(const struct device_node *node) +{ + int cpu; + struct device_node *dn; + + if (node == NULL) + return -1; + + dn = of_parse_phandle(node, "cpu", 0); + /* CTI affinity defaults to no cpu */ + if (!dn) + return -1; + cpu = of_cpu_node_to_id(dn); + of_node_put(dn); + + /* No Affinity if no cpu nodes are found */ + return (cpu < 0) ? -1 : cpu; +} + +#else +static int of_cti_get_cpu_at_node(const struct device_node *node) +{ + return -1; +} + +#endif + +/* + * CTI can be bound to a CPU, or a system device. + * CPU can be declared at the device top level or in a connections node + * so need to check relative to node not device. + */ +static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode) +{ + if (is_of_node(fwnode)) + return of_cti_get_cpu_at_node(to_of_node(fwnode)); + return -1; +} + +const char *cti_plat_get_node_name(struct fwnode_handle *fwnode) +{ + if (is_of_node(fwnode)) + return of_node_full_name(to_of_node(fwnode)); + return "unknown"; +} + +/* + * Extract a name from the fwnode. + * If the device associated with the node is a coresight_device, then return + * that name and the coresight_device pointer, otherwise return the node name. + */ +static const char * +cti_plat_get_csdev_or_node_name(struct fwnode_handle *fwnode, + struct coresight_device **csdev) +{ + const char *name = NULL; + *csdev = coresight_find_csdev_by_fwnode(fwnode); + if (*csdev) + name = dev_name(&(*csdev)->dev); + else + name = cti_plat_get_node_name(fwnode); + return name; +} + +static int cti_plat_create_v8_etm_connection(struct device *dev, + struct cti_drvdata *drvdata) +{ + int ret = -ENOMEM, i; + struct fwnode_handle *root_fwnode, *cs_fwnode; + const char *assoc_name = NULL; + struct coresight_device *csdev; + struct cti_trig_con *tc = NULL; + + root_fwnode = dev_fwnode(dev); + if (IS_ERR_OR_NULL(root_fwnode)) + return -EINVAL; + + /* Can optionally have an etm node - return if not */ + cs_fwnode = fwnode_find_reference(root_fwnode, CTI_DT_CSDEV_ASSOC, 0); + if (IS_ERR_OR_NULL(cs_fwnode)) + return 0; + + /* allocate memory */ + tc = cti_allocate_trig_con(dev, NR_V8ETM_INOUT_SIGS, + NR_V8ETM_INOUT_SIGS); + if (!tc) + goto create_v8_etm_out; + + /* build connection data */ + tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */ + tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */ + + /* + * The EXTOUT type signals from the ETM are connected to a set of input + * triggers on the CTI, the EXTIN being connected to output triggers. + */ + for (i = 0; i < NR_V8ETM_INOUT_SIGS; i++) { + tc->con_in->sig_types[i] = ETM_EXTOUT; + tc->con_out->sig_types[i] = ETM_EXTIN; + } + + /* + * We look to see if the ETM coresight device associated with this + * handle has been registered with the system - i.e. probed before + * this CTI. If so csdev will be non NULL and we can use the device + * name and pass the csdev to the connection entry function where + * the association will be recorded. + * If not, then simply record the name in the connection data, the + * probing of the ETM will call into the CTI driver API to update the + * association then. + */ + assoc_name = cti_plat_get_csdev_or_node_name(cs_fwnode, &csdev); + ret = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name); + +create_v8_etm_out: + fwnode_handle_put(cs_fwnode); + return ret; +} + +/* + * Create an architecturally defined v8 connection + * must have a cpu, can have an ETM. + */ +static int cti_plat_create_v8_connections(struct device *dev, + struct cti_drvdata *drvdata) +{ + struct cti_device *cti_dev = &drvdata->ctidev; + struct cti_trig_con *tc = NULL; + int cpuid = 0; + char cpu_name_str[16]; + int ret = -ENOMEM; + + /* Must have a cpu node */ + cpuid = cti_plat_get_cpu_at_node(dev_fwnode(dev)); + if (cpuid < 0) { + dev_warn(dev, + "ARM v8 architectural CTI connection: missing cpu\n"); + return -EINVAL; + } + cti_dev->cpu = cpuid; + + /* Allocate the v8 cpu connection memory */ + tc = cti_allocate_trig_con(dev, NR_V8PE_IN_SIGS, NR_V8PE_OUT_SIGS); + if (!tc) + goto of_create_v8_out; + + /* Set the v8 PE CTI connection data */ + tc->con_in->used_mask = 0x3; /* sigs <0 1> */ + tc->con_in->sig_types[0] = PE_DBGTRIGGER; + tc->con_in->sig_types[1] = PE_PMUIRQ; + tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */ + tc->con_out->sig_types[0] = PE_EDBGREQ; + tc->con_out->sig_types[1] = PE_DBGRESTART; + tc->con_out->sig_types[2] = PE_CTIIRQ; + scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid); + + ret = cti_add_connection_entry(dev, drvdata, tc, NULL, cpu_name_str); + if (ret) + goto of_create_v8_out; + + /* Create the v8 ETM associated connection */ + ret = cti_plat_create_v8_etm_connection(dev, drvdata); + if (ret) + goto of_create_v8_out; + + /* filter pe_edbgreq - PE trigout sig <0> */ + drvdata->config.trig_out_filter |= 0x1; + +of_create_v8_out: + return ret; +} + +static int cti_plat_check_v8_arch_compatible(struct device *dev) +{ + struct fwnode_handle *fwnode = dev_fwnode(dev); + + if (is_of_node(fwnode)) + return of_device_is_compatible(to_of_node(fwnode), + CTI_DT_V8ARCH_COMPAT); + return 0; +} + /* get the hardware configuration & connection data. */ int cti_plat_get_hw_data(struct device *dev, struct cti_drvdata *drvdata) @@ -14,6 +212,13 @@ int cti_plat_get_hw_data(struct device *dev, int rc = 0; struct cti_device *cti_dev = &drvdata->ctidev; + /* check for a v8 architectural CTI device */ + if (cti_plat_check_v8_arch_compatible(dev)) { + rc = cti_plat_create_v8_connections(dev, drvdata); + if (rc) + return rc; + } + /* if no connections, just add a single default based on max IN-OUT */ if (cti_dev->nr_trig_con == 0) rc = cti_add_default_connection(dev, drvdata); diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 3c5bee429105..43418a2126ff 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -57,6 +57,26 @@ coresight_find_device_by_fwnode(struct fwnode_handle *fwnode) return bus_find_device_by_fwnode(&amba_bustype, fwnode); } +/* + * Find a registered coresight device from a device fwnode. + * The node info is associated with the AMBA parent, but the + * csdev keeps a copy so iterate round the coresight bus to + * find the device. + */ +struct coresight_device * +coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode) +{ + struct device *dev; + struct coresight_device *csdev = NULL; + + dev = bus_find_device_by_fwnode(&coresight_bustype, r_fwnode); + if (dev) { + csdev = to_coresight_device(dev); + put_device(dev); + } + return csdev; +} + #ifdef CONFIG_OF static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep) { diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index aba6b789c969..357ffef7b825 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -202,5 +202,7 @@ static inline void *coresight_get_uci_data(const struct amba_id *id) } void coresight_release_platform_data(struct coresight_platform_data *pdata); +struct coresight_device * +coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode); #endif diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 1a5fdf2710ff..39a5d9f7a395 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1030,17 +1030,11 @@ static void coresight_fixup_device_conns(struct coresight_device *csdev) for (i = 0; i < csdev->pdata->nr_outport; i++) { struct coresight_connection *conn = &csdev->pdata->conns[i]; - struct device *dev = NULL; - dev = bus_find_device_by_fwnode(&coresight_bustype, conn->child_fwnode); - if (dev) { - conn->child_dev = to_coresight_device(dev); - /* and put reference from 'bus_find_device()' */ - put_device(dev); - } else { + conn->child_dev = + coresight_find_csdev_by_fwnode(conn->child_fwnode); + if (!conn->child_dev) csdev->orphan = true; - conn->child_dev = NULL; - } } } From patchwork Tue Feb 25 23:46:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 204228 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 98868C4BA15 for ; Tue, 25 Feb 2020 23:46:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 635DF21D7E for ; Tue, 25 Feb 2020 23:46:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="JwrTW+NZ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726827AbgBYXql (ORCPT ); Tue, 25 Feb 2020 18:46:41 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:43967 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729537AbgBYXql (ORCPT ); Tue, 25 Feb 2020 18:46:41 -0500 Received: by mail-wr1-f66.google.com with SMTP id r11so735042wrq.10 for ; Tue, 25 Feb 2020 15:46:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=IlHE1TPPaatr6L2aGQ0CeRRs3v4udZLopKfPEEns2S4=; b=JwrTW+NZcTFIA5N3SktvYN3UBhFwNlu07WRZl0En4IMZWlIUDZkIuIT7r5izynS5+P 1stqFPYge89bkl7cqkhZD0XGUWLOCjRbZcLOkqye+lwFg5iswz1aVKMwxv0BfdHuzF4o n+xIC8P7vtuBH+BEYP/hCLRa1BJjgXB+jQZiVWb0HVezJU8nlmVZZYxEy1gS6rh9ePJX 8Q4o9WjLNncoB55yW7QGjN/GDz4mzvX1C4AG5oydlFXmF93SObyqHE8A/9rNbxSS43r7 buQkYyUj/zqHL1pH5SHjdkMUew7PWSBA5VPLGyPWP49VcMS3Tn68gwyS69LK79++zaIx 3HnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=IlHE1TPPaatr6L2aGQ0CeRRs3v4udZLopKfPEEns2S4=; b=ZrVjdBU1WvkibP6RWCOYH0iyUpZEk6vS/gZujnnalh712F/lzXocf3xm9R3+YKe0we W2R1QZKgutMdqygWoayANeNuiy1uQoX88ZzifIdVdljWTWPhq54cSn1Vcr91pASYzgd8 S+FpDmsxcinJTN/MxpOY8+L6ypgbRwFyG5dll2fPMTCFd9Zwd0K4w+4vsNzLw179gXRZ xRGzFz2lLlqMYpSBWqE4c90BlPrQrgsI1/74jftOaQNqFqsVi0qjwFdBuDKXMN8fGqxa 5/S+7CsHxykTiirCRY+w9o2pwcgZYOiYSb8EXi1/fmk5AoI4zf/vyOZ5skO1G57uyXOz eDIQ== X-Gm-Message-State: APjAAAW0tCmMn1aI1A7ljgh0YCfkOSxazDRMAKe9TwCtrsrEpBePBVcD T5+7gv/+cVobzP8YL4T2ZKMe/JCREW8= X-Google-Smtp-Source: APXvYqyqZX1+jH7rjl21aePSLaWzWGhd0N49gtekJchip0l+aXY8PxMgUfktMdj83L864q2A+Hi14Q== X-Received: by 2002:adf:ea42:: with SMTP id j2mr1439978wrn.377.1582674398750; Tue, 25 Feb 2020 15:46:38 -0800 (PST) Received: from linaro.org ([2a00:23c5:6815:3901:186c:5f6c:221d:5ce]) by smtp.gmail.com with ESMTPSA id t133sm356278wmf.31.2020.02.25.15.46.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 15:46:38 -0800 (PST) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, coresight@lists.linaro.org, linux-doc@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org, mathieu.poirier@linaro.org, suzuki.poulose@arm.com, robh+dt@kernel.org, maxime@cerno.tech, liviu.dudau@arm.com, sudeep.holla@arm.com, lorenzo.pieralisi@arm.com, agross@kernel.org, corbet@lwn.net, Mike Leach Subject: [PATCH v10 07/15] coresight: cti: Add device tree support for custom CTI Date: Tue, 25 Feb 2020 23:46:03 +0000 Message-Id: <20200225234611.11067-8-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200225234611.11067-1-mike.leach@linaro.org> References: <20200225234611.11067-1-mike.leach@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Adds support for CTIs whose connections are implementation defined at hardware design time, and not constrained by v8 architecture. These CTIs have no standard connection setup, all the settings have to be defined in the device tree files. The patch creates a set of connections and trigger signals based on the information provided. Signed-off-by: Mike Leach Reviewed-by: Mathieu Poirier Reviewed-by: Suzuki K Poulose --- .../coresight/coresight-cti-platform.c | 235 +++++++++++++++++- .../hwtracing/coresight/coresight-cti-sysfs.c | 11 + 2 files changed, 242 insertions(+), 4 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c index 36a276eda50a..b44d83142b62 100644 --- a/drivers/hwtracing/coresight/coresight-cti-platform.c +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c @@ -13,9 +13,19 @@ #define NR_V8PE_OUT_SIGS 3 #define NR_V8ETM_INOUT_SIGS 4 +/* CTI device tree trigger connection node keyword */ +#define CTI_DT_CONNS "trig-conns" + /* CTI device tree connection property keywords */ #define CTI_DT_V8ARCH_COMPAT "arm,coresight-cti-v8-arch" #define CTI_DT_CSDEV_ASSOC "arm,cs-dev-assoc" +#define CTI_DT_TRIGIN_SIGS "arm,trig-in-sigs" +#define CTI_DT_TRIGOUT_SIGS "arm,trig-out-sigs" +#define CTI_DT_TRIGIN_TYPES "arm,trig-in-types" +#define CTI_DT_TRIGOUT_TYPES "arm,trig-out-types" +#define CTI_DT_FILTER_OUT_SIGS "arm,trig-filters" +#define CTI_DT_CONN_NAME "arm,trig-conn-name" +#define CTI_DT_CTM_ID "arm,cti-ctm-id" #ifdef CONFIG_OF /* @@ -87,6 +97,14 @@ cti_plat_get_csdev_or_node_name(struct fwnode_handle *fwnode, return name; } +static bool cti_plat_node_name_eq(struct fwnode_handle *fwnode, + const char *name) +{ + if (is_of_node(fwnode)) + return of_node_name_eq(to_of_node(fwnode), name); + return false; +} + static int cti_plat_create_v8_etm_connection(struct device *dev, struct cti_drvdata *drvdata) { @@ -205,6 +223,211 @@ static int cti_plat_check_v8_arch_compatible(struct device *dev) return 0; } +static int cti_plat_count_sig_elements(const struct fwnode_handle *fwnode, + const char *name) +{ + int nr_elem = fwnode_property_count_u32(fwnode, name); + + return (nr_elem < 0 ? 0 : nr_elem); +} + +static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp, + const struct fwnode_handle *fwnode, + const char *grp_name) +{ + int idx, err = 0; + u32 *values; + + if (!tgrp->nr_sigs) + return 0; + + values = kcalloc(tgrp->nr_sigs, sizeof(u32), GFP_KERNEL); + if (!values) + return -ENOMEM; + + err = fwnode_property_read_u32_array(fwnode, grp_name, + values, tgrp->nr_sigs); + + if (!err) { + /* set the signal usage mask */ + for (idx = 0; idx < tgrp->nr_sigs; idx++) + tgrp->used_mask |= BIT(values[idx]); + } + + kfree(values); + return err; +} + +static int cti_plat_read_trig_types(struct cti_trig_grp *tgrp, + const struct fwnode_handle *fwnode, + const char *type_name) +{ + int items, err = 0, nr_sigs; + u32 *values = NULL, i; + + /* allocate an array according to number of signals in connection */ + nr_sigs = tgrp->nr_sigs; + if (!nr_sigs) + return 0; + + /* see if any types have been included in the device description */ + items = cti_plat_count_sig_elements(fwnode, type_name); + if (items > nr_sigs) + return -EINVAL; + + /* need an array to store the values iff there are any */ + if (items) { + values = kcalloc(items, sizeof(u32), GFP_KERNEL); + if (!values) + return -ENOMEM; + + err = fwnode_property_read_u32_array(fwnode, type_name, + values, items); + if (err) + goto read_trig_types_out; + } + + /* + * Match type id to signal index, 1st type to 1st index etc. + * If fewer types than signals default remainder to GEN_IO. + */ + for (i = 0; i < nr_sigs; i++) { + if (i < items) { + tgrp->sig_types[i] = + values[i] < CTI_TRIG_MAX ? values[i] : GEN_IO; + } else { + tgrp->sig_types[i] = GEN_IO; + } + } + +read_trig_types_out: + kfree(values); + return err; +} + +static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata, + const struct fwnode_handle *fwnode) +{ + struct cti_trig_grp *tg = NULL; + int err = 0, nr_filter_sigs; + + nr_filter_sigs = cti_plat_count_sig_elements(fwnode, + CTI_DT_FILTER_OUT_SIGS); + if (nr_filter_sigs == 0) + return 0; + + if (nr_filter_sigs > drvdata->config.nr_trig_max) + return -EINVAL; + + tg = kzalloc(sizeof(*tg), GFP_KERNEL); + if (!tg) + return -ENOMEM; + + err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS); + if (!err) + drvdata->config.trig_out_filter |= tg->used_mask; + + kfree(tg); + return err; +} + +static int cti_plat_create_connection(struct device *dev, + struct cti_drvdata *drvdata, + struct fwnode_handle *fwnode) +{ + struct cti_trig_con *tc = NULL; + int cpuid = -1, err = 0; + struct fwnode_handle *cs_fwnode = NULL; + struct coresight_device *csdev = NULL; + const char *assoc_name = "unknown"; + char cpu_name_str[16]; + int nr_sigs_in, nr_sigs_out; + + /* look to see how many in and out signals we have */ + nr_sigs_in = cti_plat_count_sig_elements(fwnode, CTI_DT_TRIGIN_SIGS); + nr_sigs_out = cti_plat_count_sig_elements(fwnode, CTI_DT_TRIGOUT_SIGS); + + if ((nr_sigs_in > drvdata->config.nr_trig_max) || + (nr_sigs_out > drvdata->config.nr_trig_max)) + return -EINVAL; + + tc = cti_allocate_trig_con(dev, nr_sigs_in, nr_sigs_out); + if (!tc) + return -ENOMEM; + + /* look for the signals properties. */ + err = cti_plat_read_trig_group(tc->con_in, fwnode, + CTI_DT_TRIGIN_SIGS); + if (err) + goto create_con_err; + + err = cti_plat_read_trig_types(tc->con_in, fwnode, + CTI_DT_TRIGIN_TYPES); + if (err) + goto create_con_err; + + err = cti_plat_read_trig_group(tc->con_out, fwnode, + CTI_DT_TRIGOUT_SIGS); + if (err) + goto create_con_err; + + err = cti_plat_read_trig_types(tc->con_out, fwnode, + CTI_DT_TRIGOUT_TYPES); + if (err) + goto create_con_err; + + err = cti_plat_process_filter_sigs(drvdata, fwnode); + if (err) + goto create_con_err; + + /* read the connection name if set - may be overridden by later */ + fwnode_property_read_string(fwnode, CTI_DT_CONN_NAME, &assoc_name); + + /* associated cpu ? */ + cpuid = cti_plat_get_cpu_at_node(fwnode); + if (cpuid >= 0) { + drvdata->ctidev.cpu = cpuid; + scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid); + assoc_name = cpu_name_str; + } else { + /* associated device ? */ + cs_fwnode = fwnode_find_reference(fwnode, + CTI_DT_CSDEV_ASSOC, 0); + if (!IS_ERR_OR_NULL(cs_fwnode)) { + assoc_name = cti_plat_get_csdev_or_node_name(cs_fwnode, + &csdev); + fwnode_handle_put(cs_fwnode); + } + } + /* set up a connection */ + err = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name); + +create_con_err: + return err; +} + +static int cti_plat_create_impdef_connections(struct device *dev, + struct cti_drvdata *drvdata) +{ + int rc = 0; + struct fwnode_handle *fwnode = dev_fwnode(dev); + struct fwnode_handle *child = NULL; + + if (IS_ERR_OR_NULL(fwnode)) + return -EINVAL; + + fwnode_for_each_child_node(fwnode, child) { + if (cti_plat_node_name_eq(child, CTI_DT_CONNS)) + rc = cti_plat_create_connection(dev, drvdata, + child); + if (rc != 0) + break; + } + fwnode_handle_put(child); + + return rc; +} + /* get the hardware configuration & connection data. */ int cti_plat_get_hw_data(struct device *dev, struct cti_drvdata *drvdata) @@ -212,12 +435,16 @@ int cti_plat_get_hw_data(struct device *dev, int rc = 0; struct cti_device *cti_dev = &drvdata->ctidev; + /* get any CTM ID - defaults to 0 */ + device_property_read_u32(dev, CTI_DT_CTM_ID, &cti_dev->ctm_id); + /* check for a v8 architectural CTI device */ - if (cti_plat_check_v8_arch_compatible(dev)) { + if (cti_plat_check_v8_arch_compatible(dev)) rc = cti_plat_create_v8_connections(dev, drvdata); - if (rc) - return rc; - } + else + rc = cti_plat_create_impdef_connections(dev, drvdata); + if (rc) + return rc; /* if no connections, just add a single default based on max IN-OUT */ if (cti_dev->nr_trig_con == 0) diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 37e71724b67b..8af1986ed69f 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -56,9 +56,20 @@ static ssize_t enable_store(struct device *dev, } static DEVICE_ATTR_RW(enable); +static ssize_t ctmid_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); + + return scnprintf(buf, PAGE_SIZE, "%d\n", drvdata->ctidev.ctm_id); +} +static DEVICE_ATTR_RO(ctmid); + /* attribute and group sysfs tables. */ static struct attribute *coresight_cti_attrs[] = { &dev_attr_enable.attr, + &dev_attr_ctmid.attr, NULL, }; From patchwork Tue Feb 25 23:46:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 204230 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 078BDC4BA18 for ; Tue, 25 Feb 2020 23:46:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B9B212072D for ; Tue, 25 Feb 2020 23:46:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="zauK0FtL" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729537AbgBYXqn (ORCPT ); Tue, 25 Feb 2020 18:46:43 -0500 Received: from mail-wm1-f65.google.com ([209.85.128.65]:34978 "EHLO mail-wm1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729583AbgBYXqm (ORCPT ); Tue, 25 Feb 2020 18:46:42 -0500 Received: by mail-wm1-f65.google.com with SMTP id m3so1108088wmi.0 for ; Tue, 25 Feb 2020 15:46:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2qEp/D+9yuBgF/W82BOJFjUuAwwA09bi5pMAqZ4u9Eo=; b=zauK0FtLGwxBxbbeR/Wd8e4pi5SA/CLujlBFJHdjJ+XeUYcYfkw+B0oTrHSRBN9HVB HbNhX6agtVVo0Z1N4TNGS1hSq6wn0NZjUtalDzanC/CkK1loNRxcJ7Ls8w75zVbuR3N0 efNGOeaFOBEUdALoTfv7ktzdqrYz0yh+fUrCQxbGidXamJE+BzFhoHhvi8SEOA40mrui AOmweScfbd6BsmB42G6Nt8GYWtukSbfa6jPvkTFvbidqyyOl1O/pDLbmd41LQqeK1on/ fEClA2GIrnMLapIJGANlkeSjjynebAUEeXo2BTUktxrKHv1OiBE9FjoMQRR6FJ0DBV1r doTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2qEp/D+9yuBgF/W82BOJFjUuAwwA09bi5pMAqZ4u9Eo=; b=RKGa9J0giwPMoptp8d9Gm1TEVt2cF+8sMXRcyPpmNBxAUlHWqe/aFWKWWOyWJpx1mY ACFGKv/rWst8JdZCl1NtSQpBAS/TB542xGf17EzaXfgwJy9xPTlZ0w/hDcW/f8bSpQt0 0dSVC24297fploycppHsPy0cYsoUrcVgcq4Qk9CWHs9SVAqsFTiqaBkU0PVjDuqlceXx P4wrdV1E3CEDM25J07EZGiJBum2keXBzmlcl0m02Nw7pKLeToYTzH2GoTp+b/rTZb3go wMpdX3cktJdxIk/qEzn4EL/40IBsk9iLEMOzskeS1+IcY4RnTrhl6/cNQUeUU/02tSyd yiSA== X-Gm-Message-State: APjAAAVqVvpj+oN1W2Lhx+sc3ebsaMUUPwhJPul3DsLfryPMIeUa4AB+ bOkoO5KYepZwhE7FV3hKmsd2tw== X-Google-Smtp-Source: APXvYqw+pW4tP7XwRTclhiOvQzonFLlJcUSggnWvC+RDRZ0ZAuK1NypAUYZXrvtRwLyOLv3JTLMTWA== X-Received: by 2002:a05:600c:34d:: with SMTP id u13mr1623866wmd.77.1582674399963; Tue, 25 Feb 2020 15:46:39 -0800 (PST) Received: from linaro.org ([2a00:23c5:6815:3901:186c:5f6c:221d:5ce]) by smtp.gmail.com with ESMTPSA id t133sm356278wmf.31.2020.02.25.15.46.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 15:46:39 -0800 (PST) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, coresight@lists.linaro.org, linux-doc@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org, mathieu.poirier@linaro.org, suzuki.poulose@arm.com, robh+dt@kernel.org, maxime@cerno.tech, liviu.dudau@arm.com, sudeep.holla@arm.com, lorenzo.pieralisi@arm.com, agross@kernel.org, corbet@lwn.net, Mike Leach Subject: [PATCH v10 08/15] coresight: cti: Enable CTI associated with devices Date: Tue, 25 Feb 2020 23:46:04 +0000 Message-Id: <20200225234611.11067-9-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200225234611.11067-1-mike.leach@linaro.org> References: <20200225234611.11067-1-mike.leach@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The CoreSight subsystem enables a path of devices from source to sink. Any CTI devices associated with the path devices must be enabled at the same time. This patch adds an associated coresight_device element to the main coresight device structure, and uses this to create associations between the CTI and other devices based on the device tree data. The associated device element is used to enable CTI in conjunction with the path elements. CTI devices are reference counted so where a single CTI is associated with multiple elements on the path, it will be enabled on the first associated device enable, and disabled with the last associated device disable. Signed-off-by: Mike Leach Reviewed-by: Mathieu Poirier Reviewed-by: Suzuki K Poulose --- drivers/hwtracing/coresight/coresight-cti.c | 125 +++++++++++++++++++ drivers/hwtracing/coresight/coresight-cti.h | 1 + drivers/hwtracing/coresight/coresight-priv.h | 12 ++ drivers/hwtracing/coresight/coresight.c | 71 ++++++++++- include/linux/coresight.h | 4 + 5 files changed, 208 insertions(+), 5 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index b8c94027fed0..2fc68760efbe 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -4,6 +4,7 @@ * Author: Mike Leach */ +#include #include "coresight-cti.h" /** @@ -441,6 +442,127 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op, return err; } +/* + * Look for a matching connection device name in the list of connections. + * If found then swap in the csdev name, set trig con association pointer + * and return found. + */ +static bool +cti_match_fixup_csdev(struct cti_device *ctidev, const char *node_name, + struct coresight_device *csdev) +{ + struct cti_trig_con *tc; + + list_for_each_entry(tc, &ctidev->trig_cons, node) { + if (tc->con_dev_name) { + if (!strcmp(node_name, tc->con_dev_name)) { + /* match: so swap in csdev name & dev */ + tc->con_dev_name = dev_name(&csdev->dev); + tc->con_dev = csdev; + return true; + } + } + } + return false; +} + +/* + * Search the cti list to add an associated CTI into the supplied CS device + * This will set the association if CTI declared before the CS device. + * (called from coresight_register() with coresight_mutex locked). + */ +void cti_add_assoc_to_csdev(struct coresight_device *csdev) +{ + struct cti_drvdata *ect_item; + struct cti_device *ctidev; + const char *node_name = NULL; + + /* protect the list */ + mutex_lock(&ect_mutex); + + /* exit if current is an ECT device.*/ + if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net)) + goto cti_add_done; + + /* if we didn't find the csdev previously we used the fwnode name */ + node_name = cti_plat_get_node_name(dev_fwnode(csdev->dev.parent)); + if (!node_name) + goto cti_add_done; + + /* for each CTI in list... */ + list_for_each_entry(ect_item, &ect_net, node) { + ctidev = &ect_item->ctidev; + if (cti_match_fixup_csdev(ctidev, node_name, csdev)) { + /* + * if we found a matching csdev then update the ECT + * association pointer for the device with this CTI. + */ + csdev->ect_dev = ect_item->csdev; + break; + } + } +cti_add_done: + mutex_unlock(&ect_mutex); +} +EXPORT_SYMBOL_GPL(cti_add_assoc_to_csdev); + +/* + * Removing the associated devices is easier. + * A CTI will not have a value for csdev->ect_dev. + */ +void cti_remove_assoc_from_csdev(struct coresight_device *csdev) +{ + struct cti_drvdata *ctidrv; + struct cti_trig_con *tc; + struct cti_device *ctidev; + + mutex_lock(&ect_mutex); + if (csdev->ect_dev) { + ctidrv = csdev_to_cti_drvdata(csdev->ect_dev); + ctidev = &ctidrv->ctidev; + list_for_each_entry(tc, &ctidev->trig_cons, node) { + if (tc->con_dev == csdev->ect_dev) { + tc->con_dev = NULL; + break; + } + } + csdev->ect_dev = NULL; + } + mutex_unlock(&ect_mutex); +} +EXPORT_SYMBOL_GPL(cti_remove_assoc_from_csdev); + +/* + * Update the cross references where the associated device was found + * while we were building the connection info. This will occur if the + * assoc device was registered before the CTI. + */ +static void cti_update_conn_xrefs(struct cti_drvdata *drvdata) +{ + struct cti_trig_con *tc; + struct cti_device *ctidev = &drvdata->ctidev; + + list_for_each_entry(tc, &ctidev->trig_cons, node) { + if (tc->con_dev) + /* set tc->con_dev->ect_dev */ + coresight_set_assoc_ectdev_mutex(tc->con_dev, + drvdata->csdev); + } +} + +static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata) +{ + struct cti_trig_con *tc; + struct cti_device *ctidev = &drvdata->ctidev; + + list_for_each_entry(tc, &ctidev->trig_cons, node) { + if (tc->con_dev) { + coresight_set_assoc_ectdev_mutex(tc->con_dev, + NULL); + } + } +} + /** cti ect operations **/ int cti_enable(struct coresight_device *csdev) { @@ -475,6 +597,7 @@ static void cti_device_release(struct device *dev) struct cti_drvdata *ect_item, *ect_tmp; mutex_lock(&ect_mutex); + cti_remove_conn_xrefs(drvdata); /* remove from the list */ list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) { @@ -566,6 +689,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) /* add to list of CTI devices */ mutex_lock(&ect_mutex); list_add(&drvdata->node, &ect_net); + /* set any cross references */ + cti_update_conn_xrefs(drvdata); mutex_unlock(&ect_mutex); /* set up release chain */ diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h index f664b4bb4644..ca277633b04f 100644 --- a/drivers/hwtracing/coresight/coresight-cti.h +++ b/drivers/hwtracing/coresight/coresight-cti.h @@ -216,6 +216,7 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op, u32 channel_idx); struct coresight_platform_data * coresight_cti_get_platform_data(struct device *dev); +const char *cti_plat_get_node_name(struct fwnode_handle *fwnode); /* cti powered and enabled */ static inline bool cti_active(struct cti_config *cfg) diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 357ffef7b825..890f9a5c97c6 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -162,6 +162,16 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; } static inline int etm_writel_cp14(u32 off, u32 val) { return 0; } #endif +#ifdef CONFIG_CORESIGHT_CTI +extern void cti_add_assoc_to_csdev(struct coresight_device *csdev); +extern void cti_remove_assoc_from_csdev(struct coresight_device *csdev); + +#else +static inline void cti_add_assoc_to_csdev(struct coresight_device *csdev) {} +static inline void +cti_remove_assoc_from_csdev(struct coresight_device *csdev) {} +#endif + /* * Macros and inline functions to handle CoreSight UCI data and driver * private data in AMBA ID table entries, and extract data values. @@ -204,5 +214,7 @@ static inline void *coresight_get_uci_data(const struct amba_id *id) void coresight_release_platform_data(struct coresight_platform_data *pdata); struct coresight_device * coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode); +void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev, + struct coresight_device *ect_csdev); #endif diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 39a5d9f7a395..c71553c09f8e 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -216,6 +216,44 @@ void coresight_disclaim_device(void __iomem *base) CS_LOCK(base); } +/* enable or disable an associated CTI device of the supplied CS device */ +static int +coresight_control_assoc_ectdev(struct coresight_device *csdev, bool enable) +{ + int ect_ret = 0; + struct coresight_device *ect_csdev = csdev->ect_dev; + + if (!ect_csdev) + return 0; + + if (enable) { + if (ect_ops(ect_csdev)->enable) + ect_ret = ect_ops(ect_csdev)->enable(ect_csdev); + } else { + if (ect_ops(ect_csdev)->disable) + ect_ret = ect_ops(ect_csdev)->disable(ect_csdev); + } + + /* output warning if ECT enable is preventing trace operation */ + if (ect_ret) + dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n", + dev_name(&ect_csdev->dev), + enable ? "enable" : "disable"); + return ect_ret; +} + +/* + * Set the associated ect / cti device while holding the coresight_mutex + * to avoid a race with coresight_enable that may try to use this value. + */ +void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev, + struct coresight_device *ect_csdev) +{ + mutex_lock(&coresight_mutex); + csdev->ect_dev = ect_csdev; + mutex_unlock(&coresight_mutex); +} + static int coresight_enable_sink(struct coresight_device *csdev, u32 mode, void *data) { @@ -228,9 +266,14 @@ static int coresight_enable_sink(struct coresight_device *csdev, if (!sink_ops(csdev)->enable) return -EINVAL; - ret = sink_ops(csdev)->enable(csdev, mode, data); + ret = coresight_control_assoc_ectdev(csdev, true); if (ret) return ret; + ret = sink_ops(csdev)->enable(csdev, mode, data); + if (ret) { + coresight_control_assoc_ectdev(csdev, false); + return ret; + } csdev->enable = true; return 0; @@ -246,6 +289,7 @@ static void coresight_disable_sink(struct coresight_device *csdev) ret = sink_ops(csdev)->disable(csdev); if (ret) return; + coresight_control_assoc_ectdev(csdev, false); csdev->enable = false; } @@ -269,8 +313,15 @@ static int coresight_enable_link(struct coresight_device *csdev, if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0) return outport; - if (link_ops(csdev)->enable) - ret = link_ops(csdev)->enable(csdev, inport, outport); + if (link_ops(csdev)->enable) { + ret = coresight_control_assoc_ectdev(csdev, true); + if (!ret) { + ret = link_ops(csdev)->enable(csdev, inport, outport); + if (ret) + coresight_control_assoc_ectdev(csdev, false); + } + } + if (!ret) csdev->enable = true; @@ -300,8 +351,10 @@ static void coresight_disable_link(struct coresight_device *csdev, nr_conns = 1; } - if (link_ops(csdev)->disable) + if (link_ops(csdev)->disable) { link_ops(csdev)->disable(csdev, inport, outport); + coresight_control_assoc_ectdev(csdev, false); + } for (i = 0; i < nr_conns; i++) if (atomic_read(&csdev->refcnt[i]) != 0) @@ -322,9 +375,14 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode) if (!csdev->enable) { if (source_ops(csdev)->enable) { - ret = source_ops(csdev)->enable(csdev, NULL, mode); + ret = coresight_control_assoc_ectdev(csdev, true); if (ret) return ret; + ret = source_ops(csdev)->enable(csdev, NULL, mode); + if (ret) { + coresight_control_assoc_ectdev(csdev, false); + return ret; + }; } csdev->enable = true; } @@ -347,6 +405,7 @@ static bool coresight_disable_source(struct coresight_device *csdev) if (atomic_dec_return(csdev->refcnt) == 0) { if (source_ops(csdev)->disable) source_ops(csdev)->disable(csdev, NULL); + coresight_control_assoc_ectdev(csdev, false); csdev->enable = false; } return !csdev->enable; @@ -964,6 +1023,7 @@ static void coresight_device_release(struct device *dev) { struct coresight_device *csdev = to_coresight_device(dev); + cti_remove_assoc_from_csdev(csdev); fwnode_handle_put(csdev->dev.fwnode); kfree(csdev->refcnt); kfree(csdev); @@ -1246,6 +1306,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) coresight_fixup_device_conns(csdev); coresight_fixup_orphan_conns(csdev); + cti_add_assoc_to_csdev(csdev); mutex_unlock(&coresight_mutex); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index b3e582d96a34..193cc9dbf448 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -163,6 +163,8 @@ struct coresight_connection { * activated but not yet enabled. Enabling for a _sink_ * appens when a source has been selected for that it. * @ea: Device attribute for sink representation under PMU directory. + * @ect_dev: Associated cross trigger device. Not part of the trace data + * path or connections. */ struct coresight_device { struct coresight_platform_data *pdata; @@ -176,6 +178,8 @@ struct coresight_device { /* sink specific fields */ bool activated; /* true only if a sink is part of a path */ struct dev_ext_attribute *ea; + /* cross trigger handling */ + struct coresight_device *ect_dev; }; /* From patchwork Tue Feb 25 23:46:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 204232 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2D40C4BA1D for ; Tue, 25 Feb 2020 23:46:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B89D521927 for ; Tue, 25 Feb 2020 23:46:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="wzceJTsb" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729653AbgBYXqv (ORCPT ); Tue, 25 Feb 2020 18:46:51 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:39667 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729617AbgBYXqu (ORCPT ); Tue, 25 Feb 2020 18:46:50 -0500 Received: by mail-wm1-f68.google.com with SMTP id c84so1082934wme.4 for ; Tue, 25 Feb 2020 15:46:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=BucIs76BJlau9NCsGrtA8TwA9hcR+pRMGii5xstBwn8=; b=wzceJTsbO+TdAD1Cyu8CIArkKYxAT4kIWMrsPNw4gSGcXpDEenp71agJitRrCXHFyn 9o3rXuvGiE045zMRDbJSicui7t2CJ/ksZyAmPgdxl1+knGxo0hwedGO6NfTEaGV8H5t4 dgCn0i8vR55Jg1XjP0ybrZoPAcWgmucAmNFNXfZQ04bPB/w/gKN5vtzJVL6BAsVCzPsK BElY1uNGTzTEy/TFcGPivSk7BlhvowmL8MGsbFcNd5/HUGB75i0ti5IGu8xVhVczTPTb bHr+ZAGvSmvHUxGasLKSzgjIHInn6W9jyG6c8DEfO+nQoJgTS1y/ZcXwbvV2lgYf87I7 z1pg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=BucIs76BJlau9NCsGrtA8TwA9hcR+pRMGii5xstBwn8=; b=EwSwLFKmCC7gG8EU/SmFHpWLqfNFqqz1QyusvHrUmVzeFNDyIH7f0bqw369joc9+6j UbjeT4kXpMc5kplzTaews+bKfsKlvTO7Ua4XYFOr7Pn3iT5vsK+2wdzpqimK62O86WEQ 1sJ6z0k7JQEiUhyGFJidK9/V+BbZdUSYWesO+o95VJ3QGAnnxEApE220bTQ0v5B/iRKB eLmQ+M82yniugxVJnhKg9CFjVKQwg6keOU5hf5CH9kZ3kKSNogvPk9rClJWfOmjmBNuh E2kCO3F4z9Lfx6rWRlqhXsACsK2qBQWPb54O8M4vhpV98hHsZtjGZqYy7ToC99YM6icM ZLHQ== X-Gm-Message-State: APjAAAUEnuKKq+UV6hlOZQN9tmAshohcOaUFKPhQ/DgIjGg0J5ZZXlJB cjuE8A3PKFPlOZSy+dMidP5ZA3erz70= X-Google-Smtp-Source: APXvYqxXwufDMPen0Os3XKpr8yPA7jzlpKAFED+1rNntaV5cx/AhnzCfSXa2mq1QbkR9fG45ilgHOg== X-Received: by 2002:a1c:208a:: with SMTP id g132mr1462656wmg.143.1582674408254; Tue, 25 Feb 2020 15:46:48 -0800 (PST) Received: from linaro.org ([2a00:23c5:6815:3901:186c:5f6c:221d:5ce]) by smtp.gmail.com with ESMTPSA id t133sm356278wmf.31.2020.02.25.15.46.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 15:46:47 -0800 (PST) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, coresight@lists.linaro.org, linux-doc@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org, mathieu.poirier@linaro.org, suzuki.poulose@arm.com, robh+dt@kernel.org, maxime@cerno.tech, liviu.dudau@arm.com, sudeep.holla@arm.com, lorenzo.pieralisi@arm.com, agross@kernel.org, corbet@lwn.net, Mike Leach Subject: [PATCH v10 12/15] dt-bindings: hisilicon: Add CTI bindings for hi-6220 Date: Tue, 25 Feb 2020 23:46:08 +0000 Message-Id: <20200225234611.11067-13-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200225234611.11067-1-mike.leach@linaro.org> References: <20200225234611.11067-1-mike.leach@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Adds in CTI device tree information for the Hikey620 board. Signed-off-by: Mike Leach Reviewed-by: Mathieu Poirier Tested-by: Leo Yan --- .../boot/dts/hisilicon/hi6220-coresight.dtsi | 130 ++++++++++++++++-- 1 file changed, 122 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi index 651771a73ed6..27f067e87601 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi @@ -213,7 +213,7 @@ }; }; - etm@f659c000 { + etm0: etm@f659c000 { compatible = "arm,coresight-etm4x", "arm,primecell"; reg = <0 0xf659c000 0 0x1000>; @@ -232,7 +232,7 @@ }; }; - etm@f659d000 { + etm1: etm@f659d000 { compatible = "arm,coresight-etm4x", "arm,primecell"; reg = <0 0xf659d000 0 0x1000>; @@ -251,7 +251,7 @@ }; }; - etm@f659e000 { + etm2: etm@f659e000 { compatible = "arm,coresight-etm4x", "arm,primecell"; reg = <0 0xf659e000 0 0x1000>; @@ -270,7 +270,7 @@ }; }; - etm@f659f000 { + etm3: etm@f659f000 { compatible = "arm,coresight-etm4x", "arm,primecell"; reg = <0 0xf659f000 0 0x1000>; @@ -289,7 +289,7 @@ }; }; - etm@f65dc000 { + etm4: etm@f65dc000 { compatible = "arm,coresight-etm4x", "arm,primecell"; reg = <0 0xf65dc000 0 0x1000>; @@ -308,7 +308,7 @@ }; }; - etm@f65dd000 { + etm5: etm@f65dd000 { compatible = "arm,coresight-etm4x", "arm,primecell"; reg = <0 0xf65dd000 0 0x1000>; @@ -327,7 +327,7 @@ }; }; - etm@f65de000 { + etm6: etm@f65de000 { compatible = "arm,coresight-etm4x", "arm,primecell"; reg = <0 0xf65de000 0 0x1000>; @@ -346,7 +346,7 @@ }; }; - etm@f65df000 { + etm7: etm@f65df000 { compatible = "arm,coresight-etm4x", "arm,primecell"; reg = <0 0xf65df000 0 0x1000>; @@ -364,5 +364,119 @@ }; }; }; + + /* System CTIs */ + /* CTI 0 - TMC and TPIU connections */ + cti@f6403000 { + compatible = "arm,coresight-cti", "arm,primecell"; + reg = <0 0xf6403000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + }; + + /* CTI - CPU-0 */ + cti@f6598000 { + compatible = "arm,coresight-cti-v8-arch", "arm,coresight-cti", + "arm,primecell"; + reg = <0 0xf6598000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + + cpu = <&cpu0>; + arm,cs-dev-assoc = <&etm0>; + }; + + /* CTI - CPU-1 */ + cti@f6599000 { + compatible = "arm,coresight-cti-v8-arch", "arm,coresight-cti", + "arm,primecell"; + reg = <0 0xf6599000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + + cpu = <&cpu1>; + arm,cs-dev-assoc = <&etm1>; + }; + + /* CTI - CPU-2 */ + cti@f659a000 { + compatible = "arm,coresight-cti-v8-arch", "arm,coresight-cti", + "arm,primecell"; + reg = <0 0xf659a000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + + cpu = <&cpu2>; + arm,cs-dev-assoc = <&etm2>; + }; + + /* CTI - CPU-3 */ + cti@f659b000 { + compatible = "arm,coresight-cti-v8-arch", "arm,coresight-cti", + "arm,primecell"; + reg = <0 0xf659b000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + + cpu = <&cpu3>; + arm,cs-dev-assoc = <&etm3>; + }; + + /* CTI - CPU-4 */ + cti@f65d8000 { + compatible = "arm,coresight-cti-v8-arch", "arm,coresight-cti", + "arm,primecell"; + reg = <0 0xf65d8000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + + cpu = <&cpu4>; + arm,cs-dev-assoc = <&etm4>; + }; + + /* CTI - CPU-5 */ + cti@f65d9000 { + compatible = "arm,coresight-cti-v8-arch", "arm,coresight-cti", + "arm,primecell"; + reg = <0 0xf65d9000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + + cpu = <&cpu5>; + arm,cs-dev-assoc = <&etm5>; + }; + + /* CTI - CPU-6 */ + cti@f65da000 { + compatible = "arm,coresight-cti-v8-arch", "arm,coresight-cti", + "arm,primecell"; + reg = <0 0xf65da000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + + cpu = <&cpu6>; + arm,cs-dev-assoc = <&etm6>; + }; + + /* CTI - CPU-7 */ + cti@f65db000 { + compatible = "arm,coresight-cti-v8-arch", "arm,coresight-cti", + "arm,primecell"; + reg = <0 0xf65db000 0 0x1000>; + + clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>; + clock-names = "apb_pclk"; + + cpu = <&cpu7>; + arm,cs-dev-assoc = <&etm7>; + }; }; }; From patchwork Tue Feb 25 23:46:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 204231 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F448C4BA19 for ; Tue, 25 Feb 2020 23:46:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 23A4921927 for ; Tue, 25 Feb 2020 23:46:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="nVUraBxb" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729631AbgBYXqy (ORCPT ); Tue, 25 Feb 2020 18:46:54 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:38424 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729613AbgBYXqy (ORCPT ); Tue, 25 Feb 2020 18:46:54 -0500 Received: by mail-wm1-f68.google.com with SMTP id a9so1086968wmj.3 for ; Tue, 25 Feb 2020 15:46:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=K/OQ1Jgex7gK828pBxgz7p1Ugpl7TPPOgqjJJN6erjc=; b=nVUraBxbJKkaPFCjPytTTh/YfSsf1RvTOFOCuOJX2oLryitwK46Ga8mVQ+pNT084+x D5LiTLHKAJUDVTWGqnzrOfkkJJvYVG5VBF21v7i3iX9nq4GSf6UG5VK1qrxsFS2tpOkB U2XLtyjjtzt9lVzCz3W+lKUXsGwf0omxKgAjXcP6TVfUVL0pZxDDMNNg1vcPNLVIQ0Bd 2TlHAzkVmSo0Rf2QoKMWzoN5Lk/cuR5jUvsncb2sFliLdMZW0o75jZ6esGnLtXByh6WO Iz0e2ld1kk59/b2ZC2i2OOd28DS+xPff9yDMny8m33aq1opGY70fahsmFlGxNRQ5f0xk t+VA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=K/OQ1Jgex7gK828pBxgz7p1Ugpl7TPPOgqjJJN6erjc=; b=fyZnPSgRFFgYEe2wj4AOafyqMVIqP1kjqL/gDYh/hSqfCn4CCBFLtRKBHH7/HEx7+U I+geR7JItohvxmmPxO4e7aHWccYtkeIJNTrx6WZLklc0jQ4kSBqPnF2hz/exefPyy8gk XxFrCRvAaDZc8lRZLk4tqpIScwFIXdvqtpWR/mbXHpj0ucMGulWB8kJPgH/eAKu4NlQr 5x/Xr6k3NiCaHaoUENenEQiEaiL/damf2LYZLBmxAKc/pU4DeTrQaV7j7j2mlEVnCcl0 EcxV3noPfGHoHvpjqQ8YFC+6DOQziEJk/L1ylXBV/JVrbiVKWKcU/vMCYVySWOClA0Sr nppQ== X-Gm-Message-State: APjAAAU2SOgBZV+YXpy3NEtJ4MP8yHMEu1aqAvSH5RezK1DHx3GRUX5a 4V4jjxYUhKLPA+Cl7ZjtrdK8qw== X-Google-Smtp-Source: APXvYqz+D71iATXM8+5498XmjPrVNOEv+QvmeehX5g1+lJv3PGOJ0TuC212DvYtuNjcJpaiqdQQtLg== X-Received: by 2002:a05:600c:2c4d:: with SMTP id r13mr987795wmg.112.1582674410694; Tue, 25 Feb 2020 15:46:50 -0800 (PST) Received: from linaro.org ([2a00:23c5:6815:3901:186c:5f6c:221d:5ce]) by smtp.gmail.com with ESMTPSA id t133sm356278wmf.31.2020.02.25.15.46.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Feb 2020 15:46:50 -0800 (PST) From: Mike Leach To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, coresight@lists.linaro.org, linux-doc@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org, mathieu.poirier@linaro.org, suzuki.poulose@arm.com, robh+dt@kernel.org, maxime@cerno.tech, liviu.dudau@arm.com, sudeep.holla@arm.com, lorenzo.pieralisi@arm.com, agross@kernel.org, corbet@lwn.net, Mike Leach Subject: [PATCH v10 14/15] docs: sysfs: coresight: Add sysfs ABI documentation for CTI Date: Tue, 25 Feb 2020 23:46:10 +0000 Message-Id: <20200225234611.11067-15-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200225234611.11067-1-mike.leach@linaro.org> References: <20200225234611.11067-1-mike.leach@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add API usage document for sysfs API in CTI driver. Signed-off-by: Mike Leach --- .../testing/sysfs-bus-coresight-devices-cti | 221 ++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-cti diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti new file mode 100644 index 000000000000..5ed54d196a17 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti @@ -0,0 +1,221 @@ +What: /sys/bus/coresight/devices//enable +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Enable/Disable the CTI hardware. + +What: /sys/bus/coresight/devices//ctmid +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) Display the associated CTM ID + +What: /sys/bus/coresight/devices//nr_trigger_cons +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) Number of devices connected to triggers on this CTI + +What: /sys/bus/coresight/devices//triggers/name +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) Name of connected device + +What: /sys/bus/coresight/devices//triggers/in_signals +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) Input trigger signals from connected device + +What: /sys/bus/coresight/devices//triggers/in_types +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) Functional types for the input trigger signals + from connected device + +What: /sys/bus/coresight/devices//triggers/out_signals +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) Output trigger signals to connected device + +What: /sys/bus/coresight/devices//triggers/out_types +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) Functional types for the output trigger signals + to connected device + +What: /sys/bus/coresight/devices//regs/inout_sel +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Select the index for inen and outen registers. + +What: /sys/bus/coresight/devices//regs/inen +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Read or write the CTIINEN register selected by inout_sel. + +What: /sys/bus/coresight/devices//regs/outen +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Read or write the CTIOUTEN register selected by inout_sel. + +What: /sys/bus/coresight/devices//regs/gate +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Read or write CTIGATE register. + +What: /sys/bus/coresight/devices//regs/asicctl +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Read or write ASICCTL register. + +What: /sys/bus/coresight/devices//regs/intack +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Write the INTACK register. + +What: /sys/bus/coresight/devices//regs/appset +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Set CTIAPPSET register to activate channel. Read back to + determine current value of register. + +What: /sys/bus/coresight/devices//regs/appclear +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Write APPCLEAR register to deactivate channel. + +What: /sys/bus/coresight/devices//regs/apppulse +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Write APPPULSE to pulse a channel active for one clock + cycle. + +What: /sys/bus/coresight/devices//regs/chinstatus +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) Read current status of channel inputs. + +What: /sys/bus/coresight/devices//regs/choutstatus +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) read current status of channel outputs. + +What: /sys/bus/coresight/devices//regs/triginstatus +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) read current status of input trigger signals + +What: /sys/bus/coresight/devices//regs/trigoutstatus +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) read current status of output trigger signals. + +What: /sys/bus/coresight/devices//channels/trigin_attach +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Attach a CTI input trigger to a CTM channel. + +What: /sys/bus/coresight/devices//channels/trigin_detach +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Detach a CTI input trigger from a CTM channel. + +What: /sys/bus/coresight/devices//channels/trigout_attach +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Attach a CTI output trigger to a CTM channel. + +What: /sys/bus/coresight/devices//channels/trigout_detach +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Detach a CTI output trigger from a CTM channel. + +What: /sys/bus/coresight/devices//channels/chan_gate_enable +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Enable CTIGATE for single channel (W) or list enabled + channels through the gate (R). + +What: /sys/bus/coresight/devices//channels/chan_gate_disable +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Disable CTIGATE for single channel. + +What: /sys/bus/coresight/devices//channels/chan_set +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Activate a single channel. + +What: /sys/bus/coresight/devices//channels/chan_clear +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Deactivate a single channel. + +What: /sys/bus/coresight/devices//channels/chan_pulse +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Pulse a single channel - activate for a single clock cycle. + +What: /sys/bus/coresight/devices//channels/trigout_filtered +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) List of output triggers filtered across all connections. + +What: /sys/bus/coresight/devices//channels/trig_filter_enable +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Enable or disable trigger output signal filtering. + +What: /sys/bus/coresight/devices//channels/chan_inuse +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) show channels with at least one attached trigger signal. + +What: /sys/bus/coresight/devices//channels/chan_free +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (R) show channels with no attached trigger signals. + +What: /sys/bus/coresight/devices//channels/chan_xtrigs_view +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (RW) Write channel number to select a channel to view, read to + see triggers attached to selected channel on this CTI. + +What: /sys/bus/coresight/devices//channels/chan_xtrigs_reset +Date: Jan 2020 +KernelVersion 5.6 +Contact: Mike Leach or Mathieu Poirier +Description: (W) Clear all channel / trigger programming.