From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtpbg150.qq.com (smtpbg150.qq.com [18.132.163.193]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5565D1DA23 for ; Tue, 14 Apr 2026 03:43:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.132.163.193 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776138221; cv=none; b=XDDpb4EEwoEB6SgY36eM05yEvXmhWHSVLwXLxyJ51410I0jiC3yWyf9ytAVbR4MANxW7gPDi7tSJVGUxVlf++X8awazCVHhZoge/400rDTyTyXtq6ALHCdPUoHhmXbEpZcckhmYFRovVdRITyqqxptw9Xo2NXrsO/H1gTwqFqyc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776138221; c=relaxed/simple; bh=828WWat1Xj4zjsKFUNTU5lpw2X6njlApBMRUGcspKNE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZTRJqgjQZ5uxpq5bact4IFNyIA6iTVMOMt5/CzejWW94gA/tQ6f4RxAXrGh2vAmxfPHCDfOiEFRw4RPn8fpdciX74y5wHrxkV/em02eJdP3xZIjxlJbglexhbSLjASHAtwLLJtCcWpLqGcdPN+uxjwXVAh3cuBCQ0IV2eU6KnbY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.spacemit.com; spf=none smtp.mailfrom=linux.spacemit.com; dkim=pass (1024-bit key) header.d=linux.spacemit.com header.i=@linux.spacemit.com header.b=wjkF2TKO; arc=none smtp.client-ip=18.132.163.193 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.spacemit.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.spacemit.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.spacemit.com header.i=@linux.spacemit.com header.b="wjkF2TKO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.spacemit.com; s=mxsw2412; t=1776138137; bh=fiydWjDmo6mxg8g0lJHP5DHClz75B9Sfp0H5veYkkTE=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=wjkF2TKOjii5WBzudnU+nCSkqQXx8fqjYyK8lFJvuDHM0THLdGR8chkYwBmcDb2tz iXupKu9e7s3lcB0tlsGnUmYzLWFkp3s1CYqLKOTFwFl4oNvFgbdbF7nT+MwsIkUr0s 7KifWNqT8QCoRWg7WoqDmEuTV272wItOK0R8SgDg= X-QQ-mid: zesmtpsz5t1776138131t86ef943c X-QQ-Originating-IP: 57ysNez3/Fjz0GpYSZnkWeRb8mTL8sRweOCs59F/pfk= Received: from snode5.. ( [61.145.255.150]) by bizesmtp.qq.com (ESMTP) with id ; Tue, 14 Apr 2026 11:42:09 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 8828968199206424823 EX-QQ-RecipientCnt: 26 From: Zane Leung To: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, palmer@dabbelt.com, pjw@kernel.org, gregkh@linuxfoundation.org, alexander.shishkin@linux.intel.com, irogers@google.com Cc: coresight@lists.linaro.org, peterz@infradead.org, mingo@redhat.com, namhyung@kernel.org, mark.rutland@arm.com, jolsa@kernel.org, adrian.hunter@intel.com, kan.liang@linux.intel.com, mchitale@gmail.com, anup@brainfault.org, atish.patra@linux.dev, andrew.jones@oss.qualcomm.com, sunilvl@oss.qualcomm.com, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, anup.patel@oss.qualcomm.com, mayuresh.chitale@oss.qualcomm.com, zhuangqiubin@linux.spacemit.com Subject: [RFC PATCH 04/12] coresight: Add RISC-V Trace Funnel driver Date: Tue, 14 Apr 2026 11:41:45 +0800 Message-Id: <20260414034153.3272485-5-liangzhen@linux.spacemit.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260414034153.3272485-1-liangzhen@linux.spacemit.com> References: <20260414034153.3272485-1-liangzhen@linux.spacemit.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpsz:linux.spacemit.com:qybglogicsvrgz:qybglogicsvrgz6b-0 X-QQ-XMAILINFO: Nao9u9SdMvQSTMSWKjgfgwG97sPlh9bnkM9KUKvw/nkwVkF4dwhXe23T zj3KBfQdcVntDhK61BTRDRv3oG9gkQshRcO61y38y6hdo+3DaReZmK+0sAI0qgJcXJVYQHP SZbBbJslgPhkVeOc+nyyshbqtcr6noHkyLIuI9XLcOv88UQOBtqfhbnQEk41ISjNILN1E7G F9YTRMveCeEoa8OgJwMfVhrnGv4q39jwe4uyInUHHgt0Bhkddc2i9neESG/xWe8PxzGo3MM OolTxQGW/dXUan0O0Wuo6wrHk0SgVjPcy8/4T0C4wSyLQP28lVCKPbAAJXBZ/1Gqx899dnL 7YU9SZBfCgl6zEvcJ6pXBGgyWGbEgpOVm1Ojg0989lDQIpcsFxWTp1kG8In2Xx16uyY8iFv ZQyMBXuyzjORC0hSjp5SQMVWsoHtKRa96CoTj8w6z1U20+0qAbQwgrr9Upq9HcILbPLaiyM y1uBhXx8Raf7ViYwGntgl9Obwt2i+xXXK/rIrvbKBje+6bk/2ZxjmdO09JdlkJy/WwpKe/T vs7NyKPMp3MmugScs1xR6+6jcextWKZSHPBruJqotV4gSFnxF8Fy+QTb3OHoJMJznmPDazx 9XbVBUYVdflejWECipgSm56MEphlzAtHwoe4hB0XGR6pLhDYOymqw3er5E986Z5C0n0jKeB h7GxBMOUpEBX9Gq1qRB422Y5JNTd477FlhRfrj6NckfU83DMEscWQcxmSwJZbccpGizYENe N3BOZJXfqD8Rmqr9d99kE6Ta/91CEjRTo5qE311fRuf/22S3PAqX0XHLpIyYQBIj35ztmXg 54rpCZN5XJzRdVICcMtcT/CcN9Vbw4E7l3e+qdJnxkQbSE5Q5Di60Ocur7WkiVM747vcYSM CIcyVNHl0zvS2cmQZhCF+r0miPV1ROllFSL/NyDjH+KTD8vVWdC2ZIqAjYfixfEqYhwA6BI e+ZAlei0w7u0jHQMDGb5gDObx1SZuI/JDoFhQpoaODw4R2gNRz2Sbj7VT3ceFxWqzkOvUAQ sod2Pe3za5+cxyui+rUX70DwvS93I4LHQ9+tUFFZGoO5+0h6hqn/hvZXdj91bNtQg2bzc2N +oL2VCSz2yEZAo9ymnijTyYkIqmbz4+DRuuUXv4Fy4wCnOoJDivUIrYGxhEMGyqPMVgPbmQ ypZJ X-QQ-XMRINFO: OD9hHCdaPRBwH5bRRRw8tsiH4UAatJqXfg== X-QQ-RECHKSPAM: 0 From: liangzhen Add initial implementation of RISC-V trace funnel driver. The funnel is defined in the RISC-V Trace Control Interface specification. Signed-off-by: liangzhen --- drivers/hwtracing/coresight/Kconfig | 12 + drivers/hwtracing/coresight/Makefile | 1 + drivers/hwtracing/coresight/rvtrace-funnel.c | 244 +++++++++++++++++++ drivers/hwtracing/coresight/rvtrace-funnel.h | 31 +++ 4 files changed, 288 insertions(+) create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.c create mode 100644 drivers/hwtracing/coresight/rvtrace-funnel.h diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index 3e46728f2482..8381a84e2699 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -288,9 +288,21 @@ config RVTRACE dynamically aggregated with CoreSight trace infrastructure at run time to form a complete trace path. +config RVTRACE_FUNNEL + tristate "RISCV Trace Funnel driver" + depends on RVTRACE + help + his driver provides support for the Trace Funnel driver. The Funnel + aggregates the trace from each of its inputs and sends the combined + trace stream to its designated Trace Sink or ATB Bridge. + + To compile this driver as a module, choose M here: the module + will be called rvtrace-funnel. + config RVTRACE_ENCODER tristate "RISCV Trace Encoder driver" depends on RVTRACE + select RVTRACE_FUNNEL help This driver provides support for the Trace Encoder module, tracing the instructions that a processor is executing. This is primarily diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile index 9a526b1fb95a..409a0abf0642 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -59,5 +59,6 @@ coresight-ctcu-y := coresight-ctcu-core.o obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o obj-$(CONFIG_RVTRACE) += rvtrace.o rvtrace-y := rvtrace-core.o +obj-$(CONFIG_RVTRACE_FUNNEL) += rvtrace-funnel.o obj-$(CONFIG_RVTRACE_ENCODER) += rvtrace-encoder.o rvtrace-encoder-y := rvtrace-encoder-core.o rvtrace-encoder-sysfs.o diff --git a/drivers/hwtracing/coresight/rvtrace-funnel.c b/drivers/hwtracing/coresight/rvtrace-funnel.c new file mode 100644 index 000000000000..0dc7799a64ac --- /dev/null +++ b/drivers/hwtracing/coresight/rvtrace-funnel.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright(C) 2026 Spacemit Limited. All rights reserved. + */ + +#include +#include +#include +#include + +#include "coresight-priv.h" +#include "rvtrace-funnel.h" + +DEFINE_CORESIGHT_DEVLIST(funnel_devs, "rvtrace_funnel"); + +static int funnel_enable_hw(struct rvtrace_component *comp, int port) +{ + u32 disinput; + int ret = 0; + struct funnel_data *funnel_data = rvtrace_component_data(comp); + + if (!comp->was_reset) { + ret = rvtrace_component_reset(comp); + if (ret) + goto done; + } + + disinput = readl_relaxed(comp->base + RVTRACE_FUNNEL_DISINPUT_OFFSET); + disinput &= ~(1 << port); + writel_relaxed(disinput, comp->base + RVTRACE_FUNNEL_DISINPUT_OFFSET); + ret = rvtrace_poll_bit(comp, RVTRACE_FUNNEL_DISINPUT_OFFSET, port, 0); + if (ret) + goto done; + + if (!funnel_data->was_enabled) { + ret = rvtrace_enable_component(comp); + if (ret) + goto done; + } + +done: + return ret; +} + +static int funnel_enable(struct coresight_device *csdev, + struct coresight_connection *in, + struct coresight_connection *out) +{ + int ret = 0; + struct rvtrace_component *comp = dev_get_drvdata(csdev->dev.parent); + struct funnel_data *funnel_data = rvtrace_component_data(comp); + unsigned long flags; + bool first_enable = false; + + spin_lock_irqsave(&funnel_data->spinlock, flags); + if (in->dest_refcnt == 0) { + ret = funnel_enable_hw(comp, in->dest_port); + if (!ret) + first_enable = true; + } + if (!ret) { + in->dest_refcnt++; + funnel_data->input_refcnt++; + } + + if (first_enable) + dev_dbg(&csdev->dev, "Trace funnel inport %d enabled\n", + in->dest_port); + + spin_unlock_irqrestore(&funnel_data->spinlock, flags); + + return ret; +} + +static void funnel_disable_hw(struct rvtrace_component *comp, int inport) +{ + struct funnel_data *funnel_data = rvtrace_component_data(comp); + + if (--funnel_data->input_refcnt != 0) + return; + + writel_relaxed(RVTRACE_FUNNEL_DISINPUT_MASK, comp->base + RVTRACE_FUNNEL_DISINPUT_OFFSET); + + if (rvtrace_disable_component(comp)) + dev_err(&funnel_data->csdev->dev, + "timeout while waiting for Trace Funnel to be disabled\n"); + + if (rvtrace_comp_is_empty(comp)) + dev_err(&funnel_data->csdev->dev, + "timeout while waiting for Trace Funnel internal buffers become empty\n"); +} + +static void funnel_disable(struct coresight_device *csdev, + struct coresight_connection *in, + struct coresight_connection *out) +{ + struct rvtrace_component *comp = dev_get_drvdata(csdev->dev.parent); + struct funnel_data *funnel_data = rvtrace_component_data(comp); + unsigned long flags; + bool last_disable = false; + + spin_lock_irqsave(&funnel_data->spinlock, flags); + if (--in->dest_refcnt == 0) { + funnel_disable_hw(comp, in->dest_port); + last_disable = true; + } + spin_unlock_irqrestore(&funnel_data->spinlock, flags); + + if (last_disable) + dev_dbg(&csdev->dev, "Trace funnel inport %d disabled\n", + in->dest_port); + + if (funnel_data->input_refcnt == 0) + dev_dbg(&csdev->dev, "Trace funnel disabled\n"); +} + +static const struct coresight_ops_link funnel_link_ops = { + .enable = funnel_enable, + .disable = funnel_disable, +}; + +static const struct coresight_ops funnel_cs_ops = { + .link_ops = &funnel_link_ops, +}; + +static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned long val; + struct rvtrace_component *comp = dev_get_drvdata(dev->parent); + struct funnel_data *funnel_data = rvtrace_component_data(comp); + unsigned long flags; + + if (kstrtoul(buf, 16, &val)) + return -EINVAL; + + spin_lock_irqsave(&funnel_data->spinlock, flags); + + if (val) { + if (rvtrace_component_reset(comp)) { + comp->was_reset = false; + spin_unlock_irqrestore(&funnel_data->spinlock, flags); + return -EINVAL; + } + } + + spin_unlock_irqrestore(&funnel_data->spinlock, flags); + + return size; +} +static DEVICE_ATTR_WO(reset); + +static ssize_t cpu_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned long val; + struct rvtrace_component *comp = dev_get_drvdata(dev->parent); + + val = comp->cpu; + return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); +} +static DEVICE_ATTR_RO(cpu); + +static struct attribute *trace_funnel_attrs[] = { + coresight_simple_reg32(control, RVTRACE_COMPONENT_CTRL_OFFSET), + coresight_simple_reg32(impl, RVTRACE_COMPONENT_IMPL_OFFSET), + coresight_simple_reg32(disinput, RVTRACE_FUNNEL_DISINPUT_OFFSET), + &dev_attr_reset.attr, + &dev_attr_cpu.attr, + NULL, +}; +ATTRIBUTE_GROUPS(trace_funnel); + +static int funnel_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct coresight_platform_data *pdata; + struct funnel_data *funnel_data; + struct rvtrace_component *comp; + struct coresight_desc desc = { 0 }; + + comp = rvtrace_register_component(pdev); + if (IS_ERR(comp)) + return PTR_ERR(comp); + + funnel_data = devm_kzalloc(dev, sizeof(*funnel_data), GFP_KERNEL); + if (!funnel_data) + return -ENOMEM; + + spin_lock_init(&funnel_data->spinlock); + + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + pdev->dev.platform_data = pdata; + + platform_set_drvdata(pdev, comp); + + desc.name = coresight_alloc_device_name(&funnel_devs, dev); + desc.access = CSDEV_ACCESS_IOMEM(comp->base); + desc.type = CORESIGHT_DEV_TYPE_LINK; + desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG; + desc.ops = &funnel_cs_ops; + desc.pdata = pdata; + desc.dev = dev; + desc.groups = trace_funnel_groups; + funnel_data->csdev = coresight_register(&desc); + if (IS_ERR(funnel_data->csdev)) + return PTR_ERR(funnel_data->csdev); + + comp->id.data = funnel_data; + + dev_dbg(dev, "Trace Funnel initialized\n"); + + return 0; +} + +static void funnel_remove(struct platform_device *pdev) +{ + struct rvtrace_component *comp = platform_get_drvdata(pdev); + struct funnel_data *funnel_data = rvtrace_component_data(comp); + + coresight_unregister(funnel_data->csdev); +} + +static const struct of_device_id funnel_match[] = { + {.compatible = "riscv,trace-funnel"}, + {}, +}; + +static struct platform_driver funnel_driver = { + .probe = funnel_probe, + .remove = funnel_remove, + .driver = { + .name = "trace-funnel", + .of_match_table = funnel_match, + }, +}; + +module_platform_driver(funnel_driver); + +MODULE_DESCRIPTION("RISC-V Trace funnel driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwtracing/coresight/rvtrace-funnel.h b/drivers/hwtracing/coresight/rvtrace-funnel.h new file mode 100644 index 000000000000..e5247e6c1bf5 --- /dev/null +++ b/drivers/hwtracing/coresight/rvtrace-funnel.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright(C) 2026 Spacemit Limited. All rights reserved. + */ + +#ifndef _RVTRACE_FUNNEL_H +#define _RVTRACE_FUNNEL_H + +#include +#include + +/* Disable Individual Funnel Inputs */ +#define RVTRACE_FUNNEL_DISINPUT_OFFSET 0x008 +#define RVTRACE_FUNNEL_DISINPUT_MASK 0xffff + +/** + * struct funnel_data - specifics associated to a Trace Funnel component + * @csdev: Component vitals needed by the framework. + * @spinlock: Only one at a time pls. + * @was_enabled: Flag showing whether the Trace Funnel was enabled. + * @input_refcnt: Record the number of funnel inputs + */ +struct funnel_data { + struct coresight_device *csdev; + spinlock_t spinlock; + bool was_enabled; + u32 input_refcnt; + u32 disintput; +}; + +#endif -- 2.34.1