Skip to content

Commit ae78def

Browse files
Songwei Chaijiegan0107
authored andcommitted
FROMLIST: coresight-tgu: Add TGU decode support
Decoding is when all the potential pieces for creating a trigger are brought together for a given step. Example - there may be a counter keeping track of some occurrences and a priority-group that is being used to detect a pattern on the sense inputs. These 2 inputs to condition_decode must be programmed, for a given step, to establish the condition for the trigger, or movement to another steps. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-4-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai <quic_songchai@quicinc.com>
1 parent a8d8c11 commit ae78def

3 files changed

Lines changed: 196 additions & 26 deletions

File tree

Documentation/ABI/testing/sysfs-bus-coresight-devices-tgu

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@ KernelVersion 6.15
1414
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Sam Chai (QUIC) <quic_songchai@quicinc.com>
1515
Description:
1616
(RW) Set/Get the sensed signal with specific step and priority for TGU.
17+
18+
What: /sys/bus/coresight/devices/<tgu-name>/step[0:7]_condition_decode/reg[0:3]
19+
Date: February 2025
20+
KernelVersion 6.15
21+
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Sam Chai (QUIC) <quic_songchai@quicinc.com>
22+
Description:
23+
(RW) Set/Get the decode mode with specific step for TGU.

drivers/hwtracing/coresight/coresight-tgu.c

Lines changed: 161 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,35 @@ static int calculate_array_location(struct tgu_drvdata *drvdata,
2121
int step_index, int operation_index,
2222
int reg_index)
2323
{
24-
int ret;
24+
int ret = -EINVAL;
25+
26+
switch (operation_index) {
27+
case TGU_PRIORITY0:
28+
case TGU_PRIORITY1:
29+
case TGU_PRIORITY2:
30+
case TGU_PRIORITY3:
31+
ret = operation_index * (drvdata->max_step) *
32+
(drvdata->max_reg) +
33+
step_index * (drvdata->max_reg) + reg_index;
34+
break;
35+
case TGU_CONDITION_DECODE:
36+
ret = step_index * (drvdata->max_condition_decode) +
37+
reg_index;
38+
break;
39+
default:
40+
break;
41+
}
42+
return ret;
43+
}
2544

26-
ret = operation_index * (drvdata->max_step) *
27-
(drvdata->max_reg) +
28-
step_index * (drvdata->max_reg) + reg_index;
45+
static int check_array_location(struct tgu_drvdata *drvdata, int step,
46+
int ops, int reg)
47+
{
48+
int result = calculate_array_location(drvdata, step, ops, reg);
2949

30-
return ret;
50+
if (result == -EINVAL)
51+
dev_err(&drvdata->csdev->dev, "%s - Fail\n", __func__);
52+
return result;
3153
}
3254

3355
static ssize_t tgu_dataset_show(struct device *dev,
@@ -36,13 +58,33 @@ static ssize_t tgu_dataset_show(struct device *dev,
3658
struct tgu_drvdata *drvdata = dev_get_drvdata(dev->parent);
3759
struct tgu_attribute *tgu_attr =
3860
container_of(attr, struct tgu_attribute, attr);
61+
int ret = 0;
62+
63+
ret = check_array_location(drvdata, tgu_attr->step_index,
64+
tgu_attr->operation_index, tgu_attr->reg_num);
65+
if (ret == -EINVAL)
66+
return ret;
3967

40-
return sysfs_emit(buf, "0x%x\n",
41-
drvdata->value_table->priority[
42-
calculate_array_location(
43-
drvdata, tgu_attr->step_index,
44-
tgu_attr->operation_index,
45-
tgu_attr->reg_num)]);
68+
switch (tgu_attr->operation_index) {
69+
case TGU_PRIORITY0:
70+
case TGU_PRIORITY1:
71+
case TGU_PRIORITY2:
72+
case TGU_PRIORITY3:
73+
return sysfs_emit(buf, "0x%x\n",
74+
drvdata->value_table->priority[calculate_array_location(
75+
drvdata, tgu_attr->step_index,
76+
tgu_attr->operation_index,
77+
tgu_attr->reg_num)]);
78+
case TGU_CONDITION_DECODE:
79+
return sysfs_emit(buf, "0x%x\n",
80+
drvdata->value_table->condition_decode[calculate_array_location(
81+
drvdata, tgu_attr->step_index,
82+
tgu_attr->operation_index,
83+
tgu_attr->reg_num)]);
84+
default:
85+
break;
86+
}
87+
return -EINVAL;
4688
}
4789

4890
static ssize_t tgu_dataset_store(struct device *dev,
@@ -51,20 +93,44 @@ static ssize_t tgu_dataset_store(struct device *dev,
5193
size_t size)
5294
{
5395
unsigned long val;
96+
int ret = -EINVAL;
5497

5598
struct tgu_drvdata *tgu_drvdata = dev_get_drvdata(dev->parent);
5699
struct tgu_attribute *tgu_attr =
57100
container_of(attr, struct tgu_attribute, attr);
58101

59102
if (kstrtoul(buf, 0, &val))
60-
return -EINVAL;
103+
return ret;
61104

62-
guard(spinlock)(&tgu_drvdata->spinlock);
63-
tgu_drvdata->value_table->priority[calculate_array_location(
64-
tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index,
65-
tgu_attr->reg_num)] = val;
105+
ret = check_array_location(tgu_drvdata, tgu_attr->step_index,
106+
tgu_attr->operation_index, tgu_attr->reg_num);
66107

67-
return size;
108+
if (ret == -EINVAL)
109+
return ret;
110+
111+
guard(spinlock)(&tgu_drvdata->spinlock);
112+
switch (tgu_attr->operation_index) {
113+
case TGU_PRIORITY0:
114+
case TGU_PRIORITY1:
115+
case TGU_PRIORITY2:
116+
case TGU_PRIORITY3:
117+
tgu_drvdata->value_table->priority[calculate_array_location(
118+
tgu_drvdata, tgu_attr->step_index,
119+
tgu_attr->operation_index,
120+
tgu_attr->reg_num)] = val;
121+
ret = size;
122+
break;
123+
case TGU_CONDITION_DECODE:
124+
tgu_drvdata->value_table->condition_decode[calculate_array_location(
125+
tgu_drvdata, tgu_attr->step_index,
126+
tgu_attr->operation_index,
127+
tgu_attr->reg_num)] = val;
128+
ret = size;
129+
break;
130+
default:
131+
break;
132+
}
133+
return ret;
68134
}
69135

70136
static umode_t tgu_node_visible(struct kobject *kobject,
@@ -81,34 +147,70 @@ static umode_t tgu_node_visible(struct kobject *kobject,
81147
container_of(dev_attr, struct tgu_attribute, attr);
82148

83149
if (tgu_attr->step_index < drvdata->max_step) {
84-
ret = (tgu_attr->reg_num < drvdata->max_reg) ?
85-
attr->mode :
86-
0;
150+
switch (tgu_attr->operation_index) {
151+
case TGU_PRIORITY0:
152+
case TGU_PRIORITY1:
153+
case TGU_PRIORITY2:
154+
case TGU_PRIORITY3:
155+
ret = (tgu_attr->reg_num < drvdata->max_reg) ?
156+
attr->mode :
157+
0;
158+
break;
159+
case TGU_CONDITION_DECODE:
160+
ret = (tgu_attr->reg_num <
161+
drvdata->max_condition_decode) ?
162+
attr->mode :
163+
0;
164+
break;
165+
default:
166+
break;
167+
}
87168
}
88169
return ret;
89170
}
90171

91-
static void tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
172+
static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
92173
{
93-
int i, j, k;
174+
int i, j, k, ret;
94175

95176
CS_UNLOCK(drvdata->base);
96177

97178
for (i = 0; i < drvdata->max_step; i++) {
98179
for (j = 0; j < MAX_PRIORITY; j++) {
99180
for (k = 0; k < drvdata->max_reg; k++) {
181+
182+
ret = check_array_location(drvdata, i, j, k);
183+
if (ret == -EINVAL)
184+
goto exit;
185+
100186
tgu_writel(drvdata,
101187
drvdata->value_table->priority
102188
[calculate_array_location(
103-
drvdata, i, j, k)],
189+
drvdata, i, j, k)],
104190
PRIORITY_REG_STEP(i, j, k));
105191
}
106192
}
107193
}
108194

195+
for (i = 0; i < drvdata->max_step; i++) {
196+
for (j = 0; j < drvdata->max_condition_decode; j++) {
197+
ret = check_array_location(drvdata, i, TGU_CONDITION_DECODE, j);
198+
if (ret == -EINVAL)
199+
goto exit;
200+
201+
tgu_writel(drvdata,
202+
drvdata->value_table->condition_decode
203+
[calculate_array_location(
204+
drvdata, i,
205+
TGU_CONDITION_DECODE, j)],
206+
CONDITION_DECODE_STEP(i, j));
207+
}
208+
}
109209
/* Enable TGU to program the triggers */
110210
tgu_writel(drvdata, 1, TGU_CONTROL);
211+
exit:
111212
CS_LOCK(drvdata->base);
213+
return ret >= 0 ? 0 : ret;
112214
}
113215

114216
static void tgu_set_reg_number(struct tgu_drvdata *drvdata)
@@ -139,9 +241,21 @@ static void tgu_set_steps(struct tgu_drvdata *drvdata)
139241
drvdata->max_step = num_steps;
140242
}
141243

244+
static void tgu_set_conditions(struct tgu_drvdata *drvdata)
245+
{
246+
int num_conditions;
247+
u32 devid;
248+
249+
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
250+
251+
num_conditions = TGU_DEVID_CONDITIONS(devid);
252+
drvdata->max_condition_decode = num_conditions;
253+
}
254+
142255
static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode,
143256
void *data)
144257
{
258+
int ret = 0;
145259
struct tgu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
146260

147261
spin_lock(&drvdata->spinlock);
@@ -150,11 +264,15 @@ static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode,
150264
spin_unlock(&drvdata->spinlock);
151265
return -EBUSY;
152266
}
153-
tgu_write_all_hw_regs(drvdata);
267+
ret = tgu_write_all_hw_regs(drvdata);
268+
269+
if (ret == -EINVAL)
270+
goto exit;
154271
drvdata->enable = true;
155272

273+
exit:
156274
spin_unlock(&drvdata->spinlock);
157-
return 0;
275+
return ret;
158276
}
159277

160278
static int tgu_disable(struct coresight_device *csdev, void *data)
@@ -271,6 +389,14 @@ static const struct attribute_group *tgu_attr_groups[] = {
271389
PRIORITY_ATTRIBUTE_GROUP_INIT(7, 1),
272390
PRIORITY_ATTRIBUTE_GROUP_INIT(7, 2),
273391
PRIORITY_ATTRIBUTE_GROUP_INIT(7, 3),
392+
CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(0),
393+
CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(1),
394+
CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(2),
395+
CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(3),
396+
CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(4),
397+
CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(5),
398+
CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(6),
399+
CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(7),
274400
NULL,
275401
};
276402

@@ -307,6 +433,7 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
307433

308434
tgu_set_reg_number(drvdata);
309435
tgu_set_steps(drvdata);
436+
tgu_set_conditions(drvdata);
310437

311438
drvdata->value_table =
312439
devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL);
@@ -322,6 +449,15 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
322449
if (!drvdata->value_table->priority)
323450
return -ENOMEM;
324451

452+
drvdata->value_table->condition_decode = devm_kzalloc(
453+
dev,
454+
drvdata->max_condition_decode * drvdata->max_step *
455+
sizeof(*(drvdata->value_table->condition_decode)),
456+
GFP_KERNEL);
457+
458+
if (!drvdata->value_table->condition_decode)
459+
return -ENOMEM;
460+
325461
drvdata->enable = false;
326462
desc.type = CORESIGHT_DEV_TYPE_HELPER;
327463
desc.pdata = adev->dev.platform_data;

drivers/hwtracing/coresight/coresight-tgu.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#define TGU_DEVID_SENSE_INPUT(devid_val) ((int) BMVAL(devid_val, 10, 17))
1717
#define TGU_DEVID_STEPS(devid_val) ((int)BMVAL(devid_val, 3, 6))
18+
#define TGU_DEVID_CONDITIONS(devid_val) ((int)BMVAL(devid_val, 0, 2))
1819
#define NUMBER_BITS_EACH_SIGNAL 4
1920
#define LENGTH_REGISTER 32
2021

@@ -48,6 +49,7 @@
4849
*/
4950
#define STEP_OFFSET 0x1D8
5051
#define PRIORITY_START_OFFSET 0x0074
52+
#define CONDITION_DECODE_OFFSET 0x0050
5153
#define PRIORITY_OFFSET 0x60
5254
#define REG_OFFSET 0x4
5355

@@ -56,6 +58,9 @@
5658
(PRIORITY_START_OFFSET + PRIORITY_OFFSET * priority +\
5759
REG_OFFSET * reg + STEP_OFFSET * step)
5860

61+
#define CONDITION_DECODE_STEP(step, decode) \
62+
(CONDITION_DECODE_OFFSET + REG_OFFSET * decode + STEP_OFFSET * step)
63+
5964
#define tgu_dataset_rw(name, step_index, type, reg_num) \
6065
(&((struct tgu_attribute[]){ { \
6166
__ATTR(name, 0644, tgu_dataset_show, tgu_dataset_store), \
@@ -68,6 +73,9 @@
6873
tgu_dataset_rw(reg##reg_num, step_index, TGU_PRIORITY##priority, \
6974
reg_num)
7075

76+
#define STEP_DECODE(step_index, reg_num) \
77+
tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_DECODE, reg_num)
78+
7179
#define STEP_PRIORITY_LIST(step_index, priority) \
7280
{STEP_PRIORITY(step_index, 0, priority), \
7381
STEP_PRIORITY(step_index, 1, priority), \
@@ -90,18 +98,34 @@
9098
NULL \
9199
}
92100

101+
#define STEP_DECODE_LIST(n) \
102+
{STEP_DECODE(n, 0), \
103+
STEP_DECODE(n, 1), \
104+
STEP_DECODE(n, 2), \
105+
STEP_DECODE(n, 3), \
106+
NULL \
107+
}
108+
93109
#define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\
94110
(&(const struct attribute_group){\
95111
.attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\
96112
.is_visible = tgu_node_visible,\
97113
.name = "step" #step "_priority" #priority \
98114
})
99115

116+
#define CONDITION_DECODE_ATTRIBUTE_GROUP_INIT(step)\
117+
(&(const struct attribute_group){\
118+
.attrs = (struct attribute*[])STEP_DECODE_LIST(step),\
119+
.is_visible = tgu_node_visible,\
120+
.name = "step" #step "_condition_decode" \
121+
})
122+
100123
enum operation_index {
101124
TGU_PRIORITY0,
102125
TGU_PRIORITY1,
103126
TGU_PRIORITY2,
104-
TGU_PRIORITY3
127+
TGU_PRIORITY3,
128+
TGU_CONDITION_DECODE
105129

106130
};
107131

@@ -117,6 +141,7 @@ struct tgu_attribute {
117141

118142
struct value_table {
119143
unsigned int *priority;
144+
unsigned int *condition_decode;
120145
};
121146

122147
/**
@@ -129,6 +154,7 @@ struct value_table {
129154
* @value_table: Store given value based on relevant parameters.
130155
* @max_reg: Maximum number of registers
131156
* @max_step: Maximum step size
157+
* @max_condition_decode: Maximum number of condition_decode
132158
*
133159
* This structure defines the data associated with a TGU device,
134160
* including its base address, device pointers, clock, spinlock for
@@ -144,6 +170,7 @@ struct tgu_drvdata {
144170
struct value_table *value_table;
145171
int max_reg;
146172
int max_step;
173+
int max_condition_decode;
147174
};
148175

149176
#endif

0 commit comments

Comments
 (0)