Add sysfs attribute support for RISC-V trace encoder components in the platform driver. The encoder attribute groups are now assigned to pdata->groups based on component type during registration, enabling encoder configuration through sysfs interfaces.
Signed-off-by: Zane Leung liangzhen@linux.spacemit.com --- drivers/hwtracing/gtrace/Makefile | 1 + ...trace-encoder.c => rvtrace-encoder-core.c} | 117 +++++-- .../hwtracing/gtrace/rvtrace-encoder-sysfs.c | 290 ++++++++++++++++++ drivers/hwtracing/gtrace/rvtrace-encoder.h | 53 ++++ drivers/hwtracing/gtrace/rvtrace-platform.c | 8 + drivers/hwtracing/gtrace/rvtrace.h | 3 + 6 files changed, 438 insertions(+), 34 deletions(-) rename drivers/hwtracing/gtrace/{rvtrace-encoder.c => rvtrace-encoder-core.c} (60%) create mode 100644 drivers/hwtracing/gtrace/rvtrace-encoder-sysfs.c create mode 100644 drivers/hwtracing/gtrace/rvtrace-encoder.h
diff --git a/drivers/hwtracing/gtrace/Makefile b/drivers/hwtracing/gtrace/Makefile index ff79a49bdb5e..87cb5add78d4 100644 --- a/drivers/hwtracing/gtrace/Makefile +++ b/drivers/hwtracing/gtrace/Makefile @@ -6,4 +6,5 @@ gtrace-$(CONFIG_OF) += gtrace-of.o
obj-$(CONFIG_RVTRACE) += rvtrace-platform.o obj-$(CONFIG_RVTRACE_ENCODER) += rvtrace-encoder.o +rvtrace-encoder-y := rvtrace-encoder-core.o rvtrace-encoder-sysfs.o obj-$(CONFIG_RVTRACE_RAMSINK) += rvtrace-ramsink.o diff --git a/drivers/hwtracing/gtrace/rvtrace-encoder.c b/drivers/hwtracing/gtrace/rvtrace-encoder-core.c similarity index 60% rename from drivers/hwtracing/gtrace/rvtrace-encoder.c rename to drivers/hwtracing/gtrace/rvtrace-encoder-core.c index f24780b1ca1e..01925ebdfbde 100644 --- a/drivers/hwtracing/gtrace/rvtrace-encoder.c +++ b/drivers/hwtracing/gtrace/rvtrace-encoder-core.c @@ -10,28 +10,13 @@ #include <linux/minmax.h> #include <linux/slab.h> #include <linux/types.h> +#include <linux/bitfield.h> #include "rvtrace.h" +#include "rvtrace-encoder.h"
-#define RVTRACE_COMPONENT_CTRL_ITRACE_SHIFT 2 -#define RVTRACE_COMPONENT_CTRL_INSTMODE_MASK 0x7 -#define RVTRACE_COMPONENT_CTRL_INSTMODE_SHIFT 4 -#define RVTRACE_COMPONENT_CTRL_INSTMODE_OPIT 0x6 -#define RVTRACE_COMPONENT_CTRL_INHIBITSRC_SHIFT 15 -#define RVTRACE_COMPONENT_CTRL_FORMAT_MASK 0x7 -#define RVTRACE_COMPONENT_CTRL_FORMAT_SHIFT 24 -#define RVTRACE_COMPONENT_CTRL_FORMAT_ETRACE 0x0 -#define RVTRACE_COMPONENT_CTRL_FORMAT_NTRACE 0x1 - -#define RVTRACE_ENCODER_INSTFEAT_OFFSET 0x8 -#define RVTRACE_ENCODER_INSTFEAT_SRCID_MASK 0xfff -#define RVTRACE_ENCODER_INSTFEAT_SRCID_SHIFT 16 -#define RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK 0xf -#define RVTRACE_ENCODER_INSTFEAT_SRCBITS_SHIFT 28 -#define RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAX 12 - -struct rvtrace_encoder_priv { - u32 srcbits; -}; +static int boot_enable; +module_param(boot_enable, int, 0444); +MODULE_PARM_DESC(boot_enable, "Enable tracing on boot");
/* * Set the srcid and clear trTeInhibitSrc bit so that the emitted trace messages carry @@ -42,10 +27,10 @@ static void rvtrace_encoder_set_srcid(struct gtrace_platform_data *pdata, u32 sr u32 val;
val = gtrace_read32(pdata, RVTRACE_ENCODER_INSTFEAT_OFFSET); - val &= ~(RVTRACE_ENCODER_INSTFEAT_SRCID_MASK << RVTRACE_ENCODER_INSTFEAT_SRCID_SHIFT); - val &= ~(RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK << RVTRACE_ENCODER_INSTFEAT_SRCBITS_SHIFT); - val |= pdata->bound_cpu << RVTRACE_ENCODER_INSTFEAT_SRCID_SHIFT; - val |= srcbits << RVTRACE_ENCODER_INSTFEAT_SRCBITS_SHIFT; + val &= ~RVTRACE_ENCODER_INSTFEAT_SRCID_MASK; + val &= ~RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK; + val |= FIELD_PREP(RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK, srcbits); + val |= FIELD_PREP(RVTRACE_ENCODER_INSTFEAT_SRCID_MASK, pdata->bound_cpu); gtrace_write32(pdata, val, RVTRACE_ENCODER_INSTFEAT_OFFSET);
val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET); @@ -53,11 +38,32 @@ static void rvtrace_encoder_set_srcid(struct gtrace_platform_data *pdata, u32 sr gtrace_write32(pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET); }
+static void rvtrace_encoder_get_syncmode_hw(struct gtrace_platform_data *pdata, + bool *syncmode_hw) +{ + u32 ctrl, val; + enum rvtrace_encoder_syncmode mode; + + ctrl = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET); + + for (mode = RVTRACE_ENCODER_SYNCMODE_OFF; mode < RVTRACE_ENCODER_SYNCMODE_MAX; mode++) { + val = ctrl & ~RVTRACE_COMPONENT_CTRL_SYNCMODE_MASK; + val |= FIELD_PREP(RVTRACE_COMPONENT_CTRL_SYNCMODE_MASK, mode); + gtrace_write32(pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET); + val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET); + val = FIELD_GET(RVTRACE_COMPONENT_CTRL_SYNCMODE_MASK, val); + syncmode_hw[mode] = (mode == val); + } + + gtrace_write32(pdata, ctrl, RVTRACE_COMPONENT_CTRL_OFFSET); +} + static int rvtrace_encoder_probe(struct gtrace_component *comp) { struct gtrace_platform_data *pdata = comp->pdata; struct rvtrace_encoder_priv *priv; u32 val, hw_srcbits, srcbits; + int ret;
if (pdata->bound_cpu < 0) { dev_err(&comp->dev, "cpu property missing. Please fix firmware.\n"); @@ -68,6 +74,28 @@ static int rvtrace_encoder_probe(struct gtrace_component *comp) if (!priv) return -ENOMEM;
+ /* Get trTeFormat */ + val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET); + priv->format = FIELD_GET(RVTRACE_COMPONENT_CTRL_FORMAT_MASK, val); + if (priv->format > GTRACE_FORMAT_NTRACE) { + dev_err(&comp->dev, "unsupported trace format %d\n", priv->format); + return -EINVAL; + } + + /* Get trTeInstSyncMode */ + priv->syncmode = FIELD_GET(RVTRACE_COMPONENT_CTRL_SYNCMODE_MASK, val); + rvtrace_encoder_get_syncmode_hw(pdata, priv->syncmode_hw); + + /* Check if trTeContext is hardwired to 0 */ + val |= BIT(RVTRACE_COMPONENT_CTRL_CONTEXT_SHIFT); + gtrace_write32(pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET); + val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET); + if (val & BIT(RVTRACE_COMPONENT_CTRL_CONTEXT_SHIFT)) { + priv->has_context = true; + val &= ~BIT(RVTRACE_COMPONENT_CTRL_CONTEXT_SHIFT); + gtrace_write32(pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET); + } + /* Check if trTeInhibitSrc is hardwired to 1 */ val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET); val &= ~BIT(RVTRACE_COMPONENT_CTRL_INHIBITSRC_SHIFT); @@ -76,14 +104,16 @@ static int rvtrace_encoder_probe(struct gtrace_component *comp) if (!(val & BIT(RVTRACE_COMPONENT_CTRL_INHIBITSRC_SHIFT))) { /* Probe how many bits can trTeSrcID span in the emitted Trace messages */ val = gtrace_read32(pdata, RVTRACE_ENCODER_INSTFEAT_OFFSET); - val |= (RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK << - RVTRACE_ENCODER_INSTFEAT_SRCBITS_SHIFT); - gtrace_write32(pdata, val, RVTRACE_ENCODER_INSTFEAT_OFFSET); - val = gtrace_read32(pdata, RVTRACE_ENCODER_INSTFEAT_OFFSET); - hw_srcbits = (val >> RVTRACE_ENCODER_INSTFEAT_SRCBITS_SHIFT) & - RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK; + hw_srcbits = RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAX; + do { + val &= ~RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK; + val |= FIELD_PREP(RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK, hw_srcbits); + gtrace_write32(pdata, val, RVTRACE_ENCODER_INSTFEAT_OFFSET); + val = gtrace_read32(pdata, RVTRACE_ENCODER_INSTFEAT_OFFSET); + if (FIELD_GET(RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK, val) == hw_srcbits) + break; + } while (--hw_srcbits); /* Determine if there are sufficient bits to hold max cpus */ - hw_srcbits = min_t(u32, hw_srcbits, RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAX); srcbits = min_t(u32, hw_srcbits, order_base_2(nr_cpu_ids)); if (srcbits && pdata->bound_cpu < BIT(srcbits)) { rvtrace_encoder_set_srcid(pdata, srcbits); @@ -98,6 +128,15 @@ static int rvtrace_encoder_probe(struct gtrace_component *comp) gtrace_write32(pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET); } dev_set_drvdata(&comp->dev, priv); + + if (boot_enable) { + ret = gtrace_enable_sysfs(comp); + if (ret) { + dev_err(&comp->dev, "failed to enable tracing on boot.\n"); + return -EINVAL; + } + priv->boot_enable = true; + } return 0; }
@@ -117,10 +156,20 @@ static int rvtrace_encoder_start(struct gtrace_component *comp) return ret; }
- /* set mode */ val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET); - val &= ~(RVTRACE_COMPONENT_CTRL_INSTMODE_MASK << RVTRACE_COMPONENT_CTRL_INSTMODE_SHIFT); - val |= (RVTRACE_COMPONENT_CTRL_INSTMODE_OPIT << RVTRACE_COMPONENT_CTRL_INSTMODE_SHIFT); + /* set mode */ + val &= ~RVTRACE_COMPONENT_CTRL_INSTMODE_MASK; + val |= FIELD_PREP(RVTRACE_COMPONENT_CTRL_INSTMODE_MASK, + RVTRACE_COMPONENT_CTRL_INSTMODE_OPIT); + /* set context */ + val &= ~BIT(RVTRACE_COMPONENT_CTRL_CONTEXT_SHIFT); + val |= FIELD_PREP(BIT(RVTRACE_COMPONENT_CTRL_CONTEXT_SHIFT), !!priv->context); + /* set syncmode */ + val &= ~RVTRACE_COMPONENT_CTRL_SYNCMODE_MASK; + val |= FIELD_PREP(RVTRACE_COMPONENT_CTRL_SYNCMODE_MASK, priv->syncmode); + /* set syncmax */ + val &= ~RVTRACE_COMPONENT_CTRL_SYNCMAX_MASK; + val |= FIELD_PREP(RVTRACE_COMPONENT_CTRL_SYNCMAX_MASK, priv->syncmax); gtrace_write32(pdata, val, RVTRACE_COMPONENT_CTRL_OFFSET);
val = gtrace_read32(pdata, RVTRACE_COMPONENT_CTRL_OFFSET); diff --git a/drivers/hwtracing/gtrace/rvtrace-encoder-sysfs.c b/drivers/hwtracing/gtrace/rvtrace-encoder-sysfs.c new file mode 100644 index 000000000000..e973d0e43036 --- /dev/null +++ b/drivers/hwtracing/gtrace/rvtrace-encoder-sysfs.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2026 Qualcomm Technologies, Inc. + */ + +#include <linux/device.h> +#include <linux/gtrace.h> +#include <linux/types.h> +#include "rvtrace.h" +#include "rvtrace-encoder.h" + +struct rvtrace_component_reg { + struct gtrace_component *comp; + u32 offset; + u32 data; +}; + +static void do_smp_cross_read(void *data) +{ + struct rvtrace_component_reg *reg = data; + + reg->data = gtrace_relaxed_read32(reg->comp->pdata, reg->offset); +} + +static u32 rvtrace_cross_read(struct gtrace_component *comp, u32 offset) +{ + struct gtrace_platform_data *pdata = comp->pdata; + struct rvtrace_component_reg reg; + + reg.comp = comp; + reg.offset = offset; + /* + * smp cross call ensures the CPU will be powered up before + * accessing the RISC-V trace core registers + */ + smp_call_function_single(pdata->bound_cpu, do_smp_cross_read, ®, 1); + return reg.data; +} + +static u32 rvtrace_attr_to_offset(struct device_attribute *attr) +{ + struct dev_ext_attribute *eattr; + + eattr = container_of(attr, struct dev_ext_attribute, attr); + return (u32)(unsigned long)eattr->var; +} + +static ssize_t rvtrace_reg_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + u32 val, offset; + struct gtrace_component *comp = to_gtrace_component(dev); + + offset = rvtrace_attr_to_offset(attr); + + val = rvtrace_cross_read(comp, offset); + + return scnprintf(buf, PAGE_SIZE, "0x%x\n", val); +} + +/* + * Macro to set an RO ext attribute with offset and show function. + */ +#define rvtrace_reg_showfn(name, offset, showfn) ( \ + &((struct dev_ext_attribute[]) { \ + { \ + __ATTR(name, 0444, showfn, NULL), \ + (void *)(unsigned long)offset \ + } \ + })[0].attr.attr \ + ) + +/* macro using the default rvtrace_reg_show function */ +#define rvtrace_reg(name, offset) \ + rvtrace_reg_showfn(name, offset, rvtrace_reg_show) + +static ssize_t cpu_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + + return sysfs_emit(buf, "%d\n", comp->pdata->bound_cpu); +} +static DEVICE_ATTR_RO(cpu); + +static struct attribute *rvtrace_encoder_attrs[] = { + &dev_attr_cpu.attr, + NULL, +}; + +static struct attribute *rvtrace_encoder_mgmt_attrs[] = { + rvtrace_reg(control, RVTRACE_COMPONENT_CTRL_OFFSET), + rvtrace_reg(features, RVTRACE_ENCODER_INSTFEAT_OFFSET), + NULL, +}; + +static ssize_t format_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + + return sysfs_emit(buf, "%u\n", priv->format); +} +static DEVICE_ATTR_RO(format); + +static ssize_t has_context_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + + return sysfs_emit(buf, "%u\n", priv->has_context); +} +static DEVICE_ATTR_RO(has_context); + +static ssize_t context_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + + return sysfs_emit(buf, "%u\n", priv->context); +} + +static ssize_t context_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + unsigned long val; + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + + if (!priv->has_context) + return -EINVAL; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + priv->context = !!val; + + return size; +} +static DEVICE_ATTR_RW(context); + +static const char *const syncmodes_str[] = { + [RVTRACE_ENCODER_SYNCMODE_OFF] = "off", + [RVTRACE_ENCODER_SYNCMODE_MESSAGES] = "messages", + [RVTRACE_ENCODER_SYNCMODE_CLOCK] = "clock", + [RVTRACE_ENCODER_SYNCMODE_INSTRUCTION] = "instruction", +}; + +static ssize_t syncmodes_available_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + ssize_t size = 0; + enum rvtrace_encoder_syncmode mode; + + for (mode = RVTRACE_ENCODER_SYNCMODE_OFF; mode < RVTRACE_ENCODER_SYNCMODE_MAX; mode++) { + if (priv->syncmode_hw[mode]) + size += sysfs_emit_at(buf, size, "%s ", + syncmodes_str[mode]); + } + + size += sysfs_emit_at(buf, size, "\n"); + return size; +} +static DEVICE_ATTR_RO(syncmodes_available); + +static ssize_t syncmode_preferred_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + + return sysfs_emit(buf, "%s\n", syncmodes_str[priv->syncmode]); +} + +static ssize_t syncmode_preferred_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + + if (sysfs_streq(buf, syncmodes_str[RVTRACE_ENCODER_SYNCMODE_OFF]) && + priv->syncmode_hw[RVTRACE_ENCODER_SYNCMODE_OFF]) + priv->syncmode = RVTRACE_ENCODER_SYNCMODE_OFF; + else if (sysfs_streq(buf, syncmodes_str[RVTRACE_ENCODER_SYNCMODE_MESSAGES]) && + priv->syncmode_hw[RVTRACE_ENCODER_SYNCMODE_MESSAGES]) + priv->syncmode = RVTRACE_ENCODER_SYNCMODE_MESSAGES; + else if (sysfs_streq(buf, syncmodes_str[RVTRACE_ENCODER_SYNCMODE_CLOCK]) && + priv->syncmode_hw[RVTRACE_ENCODER_SYNCMODE_CLOCK]) + priv->syncmode = RVTRACE_ENCODER_SYNCMODE_CLOCK; + else if (sysfs_streq(buf, syncmodes_str[RVTRACE_ENCODER_SYNCMODE_INSTRUCTION]) && + priv->syncmode_hw[RVTRACE_ENCODER_SYNCMODE_INSTRUCTION]) + priv->syncmode = RVTRACE_ENCODER_SYNCMODE_INSTRUCTION; + else + return -EINVAL; + return size; +} +static DEVICE_ATTR_RW(syncmode_preferred); + +static ssize_t syncmax_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + + return sysfs_emit(buf, "%u\n", priv->syncmax); +} + +static ssize_t syncmax_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + unsigned long val; + int ret; + + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + + if (val > RVTRACE_COMPONENT_CTRL_SYNCMAX_MAX) + return -EINVAL; + + priv->syncmax = val; + return size; +} +static DEVICE_ATTR_RW(syncmax); + +static struct attribute *rvtrace_encoder_control_attrs[] = { + &dev_attr_format.attr, + &dev_attr_has_context.attr, + &dev_attr_context.attr, + &dev_attr_syncmodes_available.attr, + &dev_attr_syncmode_preferred.attr, + &dev_attr_syncmax.attr, + NULL, +}; + +static ssize_t srcbits_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gtrace_component *comp = to_gtrace_component(dev); + struct rvtrace_encoder_priv *priv = dev_get_drvdata(&comp->dev); + + return sysfs_emit(buf, "%u\n", priv->srcbits); +} +static DEVICE_ATTR_RO(srcbits); + +static struct attribute *rvtrace_encoder_features_attrs[] = { + &dev_attr_srcbits.attr, + NULL, +}; + +static const struct attribute_group rvtrace_encoder_group = { + .attrs = rvtrace_encoder_attrs, +}; + +static const struct attribute_group rvtrace_encoder_mgmt_group = { + .attrs = rvtrace_encoder_mgmt_attrs, + .name = "mgmt", +}; + +static const struct attribute_group rvtrace_encoder_control_group = { + .attrs = rvtrace_encoder_control_attrs, + .name = "control", +}; + +static const struct attribute_group rvtrace_encoder_features_group = { + .attrs = rvtrace_encoder_features_attrs, + .name = "features", +}; + +const struct attribute_group *rvtrace_encoder_groups[] = { + &rvtrace_encoder_group, + &rvtrace_encoder_mgmt_group, + &rvtrace_encoder_control_group, + &rvtrace_encoder_features_group, + NULL, +}; +EXPORT_SYMBOL_GPL(rvtrace_encoder_groups); diff --git a/drivers/hwtracing/gtrace/rvtrace-encoder.h b/drivers/hwtracing/gtrace/rvtrace-encoder.h new file mode 100644 index 000000000000..733d44c0e641 --- /dev/null +++ b/drivers/hwtracing/gtrace/rvtrace-encoder.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __RVTRACE_ENCODER_H__ +#define __RVTRACE_ENCODER_H__ + +#define RVTRACE_COMPONENT_CTRL_ITRACE_SHIFT 2 +#define RVTRACE_COMPONENT_CTRL_INSTMODE_MASK GENMASK(6, 4) +#define RVTRACE_COMPONENT_CTRL_INSTMODE_OPIT 0x6 +#define RVTRACE_COMPONENT_CTRL_CONTEXT_SHIFT 9 +#define RVTRACE_COMPONENT_CTRL_INHIBITSRC_SHIFT 15 +#define RVTRACE_COMPONENT_CTRL_SYNCMODE_MASK GENMASK(17, 16) +#define RVTRACE_COMPONENT_CTRL_SYNCMAX_MASK GENMASK(23, 20) +#define RVTRACE_COMPONENT_CTRL_SYNCMAX_MAX 15 +#define RVTRACE_COMPONENT_CTRL_FORMAT_MASK GENMASK(26, 24) +#define RVTRACE_COMPONENT_CTRL_FORMAT_ETRACE 0x0 +#define RVTRACE_COMPONENT_CTRL_FORMAT_NTRACE 0x1 + +#define RVTRACE_ENCODER_INSTFEAT_OFFSET 0x8 +#define RVTRACE_ENCODER_INSTFEAT_SRCID_MASK GENMASK(27, 16) +#define RVTRACE_ENCODER_INSTFEAT_SRCBITS_MASK GENMASK(31, 28) +#define RVTRACE_ENCODER_INSTFEAT_SRCBITS_MAX 12 + +enum rvtrace_encoder_syncmode { + RVTRACE_ENCODER_SYNCMODE_OFF, + RVTRACE_ENCODER_SYNCMODE_MESSAGES, + RVTRACE_ENCODER_SYNCMODE_CLOCK, + RVTRACE_ENCODER_SYNCMODE_INSTRUCTION, + RVTRACE_ENCODER_SYNCMODE_MAX, +}; + +/** + * struct rvtrace_encoder_priv - Private driver data for the rvtrace encoder. + * @syncmode_hw: Hardware capability for synchronization modes. + * @syncmode: Current operational synchronization mode configured in hardware. + * @syncmax: Maximum interval value allowed for synchronization. + * @srcbits: Width of source bits allocated for trace generation. + * @format: Trace format type used by this encoder compinent. + * @has_context: Hardware flag for scontext/mcontext and privilege tracking. + * @context: Current configuration for scontext/mcontext and privilege tracking. + * @boot_enable: Flag to automatically enable tracing on boot. + */ +struct rvtrace_encoder_priv { + bool syncmode_hw[RVTRACE_ENCODER_SYNCMODE_MAX]; + u32 syncmode; + u32 syncmax; + u32 srcbits; + enum gtrace_format format; + bool has_context; + bool context; + bool boot_enable; +}; + +#endif/* __RVTRACE_ENCODER_H__ */ diff --git a/drivers/hwtracing/gtrace/rvtrace-platform.c b/drivers/hwtracing/gtrace/rvtrace-platform.c index e5c1f47388a2..64496a638359 100644 --- a/drivers/hwtracing/gtrace/rvtrace-platform.c +++ b/drivers/hwtracing/gtrace/rvtrace-platform.c @@ -129,6 +129,14 @@ static int rvtrace_platform_probe(struct platform_device *pdev) id.type = gtype; id.version = rvtrace_component_mkversion(major, minor);
+ switch (gtype) { + case GTRACE_RVTRACE_ENCODER: + pdata->groups = rvtrace_encoder_groups; + break; + default: + pdata->groups = NULL; + } + comp = gtrace_register_component(&id, rvtrace_type_name(gtype), pdata); if (IS_ERR(comp)) return PTR_ERR(comp); diff --git a/drivers/hwtracing/gtrace/rvtrace.h b/drivers/hwtracing/gtrace/rvtrace.h index e6be1ce303cc..fee8e2e4f42a 100644 --- a/drivers/hwtracing/gtrace/rvtrace.h +++ b/drivers/hwtracing/gtrace/rvtrace.h @@ -118,4 +118,7 @@ static inline int rvtrace_comp_poll_empty(struct gtrace_component *comp)
extern const struct gtrace_hw_ops rvtrace_hw_ops;
+/* Sysfs attribute groups for RISC-V trace components */ +extern const struct attribute_group *rvtrace_encoder_groups[]; + #endif /* __LINUX_RVTRACE_H__ */