Skip to content

Commit 7468662

Browse files
Songwei Chaijiegan0107
authored andcommitted
FROMLIST: coresight-tgu: add timer/counter functionality for TGU
Add counter and timer node for each step which could be programed if they are to be utilized in trigger event/sequence. Link: https://lore.kernel.org/all/20250423-tgu_patch-v5-6-3b52c105cc63@quicinc.com/ Signed-off-by: Songwei Chai <quic_songchai@quicinc.com>
1 parent 37fde7d commit 7468662

3 files changed

Lines changed: 204 additions & 3 deletions

File tree

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,18 @@ Date: February 2025
2727
KernelVersion 6.15
2828
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Sam Chai (QUIC) <quic_songchai@quicinc.com>
2929
Description:
30-
(RW) Set/Get the next action with specific step for TGU.
30+
(RW) Set/Get the next action with specific step for TGU.
31+
32+
What: /sys/bus/coresight/devices/<tgu-name>/step[0:7]_timer/reg[0:1]
33+
Date: February 2025
34+
KernelVersion 6.15
35+
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Sam Chai (QUIC) <quic_songchai@quicinc.com>
36+
Description:
37+
(RW) Set/Get the timer value with specific step for TGU.
38+
39+
What: /sys/bus/coresight/devices/<tgu-name>/step[0:7]_counter/reg[0:1]
40+
Date: February 2025
41+
KernelVersion 6.15
42+
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Sam Chai (QUIC) <quic_songchai@quicinc.com>
43+
Description:
44+
(RW) Set/Get the counter value with specific step for TGU.

drivers/hwtracing/coresight/coresight-tgu.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ static int calculate_array_location(struct tgu_drvdata *drvdata,
3939
case TGU_CONDITION_SELECT:
4040
ret = step_index * (drvdata->max_condition_select) + reg_index;
4141
break;
42+
case TGU_COUNTER:
43+
ret = step_index * (drvdata->max_counter) + reg_index;
44+
break;
45+
case TGU_TIMER:
46+
ret = step_index * (drvdata->max_timer) + reg_index;
47+
break;
4248
default:
4349
break;
4450
}
@@ -90,6 +96,16 @@ static ssize_t tgu_dataset_show(struct device *dev,
9096
drvdata, tgu_attr->step_index,
9197
tgu_attr->operation_index,
9298
tgu_attr->reg_num)]);
99+
case TGU_TIMER:
100+
return sysfs_emit(buf, "0x%x\n",
101+
drvdata->value_table->timer[calculate_array_location(
102+
drvdata, tgu_attr->step_index, tgu_attr->operation_index,
103+
tgu_attr->reg_num)]);
104+
case TGU_COUNTER:
105+
return sysfs_emit(buf, "0x%x\n",
106+
drvdata->value_table->counter[calculate_array_location(
107+
drvdata, tgu_attr->step_index, tgu_attr->operation_index,
108+
tgu_attr->reg_num)]);
93109
default:
94110
break;
95111
}
@@ -143,6 +159,18 @@ static ssize_t tgu_dataset_store(struct device *dev,
143159
tgu_attr->reg_num)] = val;
144160
ret = size;
145161
break;
162+
case TGU_TIMER:
163+
tgu_drvdata->value_table->timer[calculate_array_location(
164+
tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index,
165+
tgu_attr->reg_num)] = val;
166+
ret = size;
167+
break;
168+
case TGU_COUNTER:
169+
tgu_drvdata->value_table->counter[calculate_array_location(
170+
tgu_drvdata, tgu_attr->step_index, tgu_attr->operation_index,
171+
tgu_attr->reg_num)] = val;
172+
ret = size;
173+
break;
146174
default:
147175
break;
148176
}
@@ -188,6 +216,24 @@ static umode_t tgu_node_visible(struct kobject *kobject,
188216
attr->mode :
189217
0;
190218
break;
219+
case TGU_COUNTER:
220+
if (drvdata->max_counter == 0)
221+
ret = SYSFS_GROUP_INVISIBLE;
222+
else
223+
ret = (tgu_attr->reg_num <
224+
drvdata->max_counter) ?
225+
attr->mode :
226+
0;
227+
break;
228+
case TGU_TIMER:
229+
if (drvdata->max_timer == 0)
230+
ret = SYSFS_GROUP_INVISIBLE;
231+
else
232+
ret = (tgu_attr->reg_num <
233+
drvdata->max_timer) ?
234+
attr->mode :
235+
0;
236+
break;
191237
default:
192238
break;
193239
}
@@ -246,6 +292,34 @@ static ssize_t tgu_write_all_hw_regs(struct tgu_drvdata *drvdata)
246292
CONDITION_SELECT_STEP(i, j));
247293
}
248294
}
295+
296+
for (i = 0; i < drvdata->max_step; i++) {
297+
for (j = 0; j < drvdata->max_timer; j++) {
298+
ret = check_array_location(drvdata, i, TGU_TIMER, j);
299+
if (ret == -EINVAL)
300+
goto exit;
301+
302+
tgu_writel(drvdata,
303+
drvdata->value_table->timer
304+
[calculate_array_location(drvdata, i,
305+
TGU_TIMER, j)],
306+
TIMER_COMPARE_STEP(i, j));
307+
}
308+
}
309+
310+
for (i = 0; i < drvdata->max_step; i++) {
311+
for (j = 0; j < drvdata->max_counter; j++) {
312+
ret = check_array_location(drvdata, i, TGU_COUNTER, j);
313+
if (ret == -EINVAL)
314+
goto exit;
315+
316+
tgu_writel(drvdata,
317+
drvdata->value_table->counter
318+
[calculate_array_location(drvdata, i,
319+
TGU_COUNTER, j)],
320+
COUNTER_COMPARE_STEP(i, j));
321+
}
322+
}
249323
/* Enable TGU to program the triggers */
250324
tgu_writel(drvdata, 1, TGU_CONTROL);
251325
exit:
@@ -294,6 +368,31 @@ static void tgu_set_conditions(struct tgu_drvdata *drvdata)
294368
drvdata->max_condition_select = num_conditions + 1;
295369
}
296370

371+
static void tgu_set_timer_counter(struct tgu_drvdata *drvdata)
372+
{
373+
int num_timers, num_counters;
374+
u32 devid2;
375+
376+
devid2 = readl_relaxed(drvdata->base + CORESIGHT_DEVID2);
377+
378+
if (TGU_DEVID2_TIMER0(devid2) && TGU_DEVID2_TIMER1(devid2))
379+
num_timers = 2;
380+
else if (TGU_DEVID2_TIMER0(devid2) || TGU_DEVID2_TIMER1(devid2))
381+
num_timers = 1;
382+
else
383+
num_timers = 0;
384+
385+
if (TGU_DEVID2_COUNTER0(devid2) && TGU_DEVID2_COUNTER1(devid2))
386+
num_counters = 2;
387+
else if (TGU_DEVID2_COUNTER0(devid2) || TGU_DEVID2_COUNTER1(devid2))
388+
num_counters = 1;
389+
else
390+
num_counters = 0;
391+
392+
drvdata->max_timer = num_timers;
393+
drvdata->max_counter = num_counters;
394+
}
395+
297396
static int tgu_enable(struct coresight_device *csdev, enum cs_mode mode,
298397
void *data)
299398
{
@@ -447,6 +546,22 @@ static const struct attribute_group *tgu_attr_groups[] = {
447546
CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(5),
448547
CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(6),
449548
CONDITION_SELECT_ATTRIBUTE_GROUP_INIT(7),
549+
TIMER_ATTRIBUTE_GROUP_INIT(0),
550+
TIMER_ATTRIBUTE_GROUP_INIT(1),
551+
TIMER_ATTRIBUTE_GROUP_INIT(2),
552+
TIMER_ATTRIBUTE_GROUP_INIT(3),
553+
TIMER_ATTRIBUTE_GROUP_INIT(4),
554+
TIMER_ATTRIBUTE_GROUP_INIT(5),
555+
TIMER_ATTRIBUTE_GROUP_INIT(6),
556+
TIMER_ATTRIBUTE_GROUP_INIT(7),
557+
COUNTER_ATTRIBUTE_GROUP_INIT(0),
558+
COUNTER_ATTRIBUTE_GROUP_INIT(1),
559+
COUNTER_ATTRIBUTE_GROUP_INIT(2),
560+
COUNTER_ATTRIBUTE_GROUP_INIT(3),
561+
COUNTER_ATTRIBUTE_GROUP_INIT(4),
562+
COUNTER_ATTRIBUTE_GROUP_INIT(5),
563+
COUNTER_ATTRIBUTE_GROUP_INIT(6),
564+
COUNTER_ATTRIBUTE_GROUP_INIT(7),
450565
NULL,
451566
};
452567

@@ -484,6 +599,7 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
484599
tgu_set_reg_number(drvdata);
485600
tgu_set_steps(drvdata);
486601
tgu_set_conditions(drvdata);
602+
tgu_set_timer_counter(drvdata);
487603

488604
drvdata->value_table =
489605
devm_kzalloc(dev, sizeof(*drvdata->value_table), GFP_KERNEL);
@@ -517,6 +633,24 @@ static int tgu_probe(struct amba_device *adev, const struct amba_id *id)
517633
if (!drvdata->value_table->condition_select)
518634
return -ENOMEM;
519635

636+
drvdata->value_table->timer = devm_kzalloc(
637+
dev,
638+
drvdata->max_step * drvdata->max_timer *
639+
sizeof(*(drvdata->value_table->timer)),
640+
GFP_KERNEL);
641+
642+
if (!drvdata->value_table->timer)
643+
return -ENOMEM;
644+
645+
drvdata->value_table->counter = devm_kzalloc(
646+
dev,
647+
drvdata->max_step * drvdata->max_counter *
648+
sizeof(*(drvdata->value_table->counter)),
649+
GFP_KERNEL);
650+
651+
if (!drvdata->value_table->counter)
652+
return -ENOMEM;
653+
520654
drvdata->enable = false;
521655
desc.type = CORESIGHT_DEV_TYPE_HELPER;
522656
desc.pdata = adev->dev.platform_data;

drivers/hwtracing/coresight/coresight-tgu.h

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@
88

99
/* Register addresses */
1010
#define TGU_CONTROL 0x0000
11-
11+
#define CORESIGHT_DEVID2 0xfc0
1212
/* Register read/write */
1313
#define tgu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
1414
#define tgu_readl(drvdata, off) __raw_readl(drvdata->base + off)
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))
1818
#define TGU_DEVID_CONDITIONS(devid_val) ((int)BMVAL(devid_val, 0, 2))
19+
#define TGU_DEVID2_TIMER0(devid_val) ((int)BMVAL(devid_val, 18, 23))
20+
#define TGU_DEVID2_TIMER1(devid_val) ((int)BMVAL(devid_val, 13, 17))
21+
#define TGU_DEVID2_COUNTER0(devid_val) ((int)BMVAL(devid_val, 6, 11))
22+
#define TGU_DEVID2_COUNTER1(devid_val) ((int)BMVAL(devid_val, 0, 5))
23+
1924
#define NUMBER_BITS_EACH_SIGNAL 4
2025
#define LENGTH_REGISTER 32
2126

@@ -51,6 +56,8 @@
5156
#define PRIORITY_START_OFFSET 0x0074
5257
#define CONDITION_DECODE_OFFSET 0x0050
5358
#define CONDITION_SELECT_OFFSET 0x0060
59+
#define TIMER_START_OFFSET 0x0040
60+
#define COUNTER_START_OFFSET 0x0048
5461
#define PRIORITY_OFFSET 0x60
5562
#define REG_OFFSET 0x4
5663

@@ -62,6 +69,12 @@
6269
#define CONDITION_DECODE_STEP(step, decode) \
6370
(CONDITION_DECODE_OFFSET + REG_OFFSET * decode + STEP_OFFSET * step)
6471

72+
#define TIMER_COMPARE_STEP(step, timer) \
73+
(TIMER_START_OFFSET + REG_OFFSET * timer + STEP_OFFSET * step)
74+
75+
#define COUNTER_COMPARE_STEP(step, counter) \
76+
(COUNTER_START_OFFSET + REG_OFFSET * counter + STEP_OFFSET * step)
77+
6578
#define CONDITION_SELECT_STEP(step, select) \
6679
(CONDITION_SELECT_OFFSET + REG_OFFSET * select + STEP_OFFSET * step)
6780

@@ -83,6 +96,12 @@
8396
#define STEP_SELECT(step_index, reg_num) \
8497
tgu_dataset_rw(reg##reg_num, step_index, TGU_CONDITION_SELECT, reg_num)
8598

99+
#define STEP_TIMER(step_index, reg_num) \
100+
tgu_dataset_rw(reg##reg_num, step_index, TGU_TIMER, reg_num)
101+
102+
#define STEP_COUNTER(step_index, reg_num) \
103+
tgu_dataset_rw(reg##reg_num, step_index, TGU_COUNTER, reg_num)
104+
86105
#define STEP_PRIORITY_LIST(step_index, priority) \
87106
{STEP_PRIORITY(step_index, 0, priority), \
88107
STEP_PRIORITY(step_index, 1, priority), \
@@ -122,6 +141,18 @@
122141
NULL \
123142
}
124143

144+
#define STEP_TIMER_LIST(n) \
145+
{STEP_TIMER(n, 0), \
146+
STEP_TIMER(n, 1), \
147+
NULL \
148+
}
149+
150+
#define STEP_COUNTER_LIST(n) \
151+
{STEP_COUNTER(n, 0), \
152+
STEP_COUNTER(n, 1), \
153+
NULL \
154+
}
155+
125156
#define PRIORITY_ATTRIBUTE_GROUP_INIT(step, priority)\
126157
(&(const struct attribute_group){\
127158
.attrs = (struct attribute*[])STEP_PRIORITY_LIST(step, priority),\
@@ -143,13 +174,29 @@
143174
.name = "step" #step "_condition_select" \
144175
})
145176

177+
#define TIMER_ATTRIBUTE_GROUP_INIT(step)\
178+
(&(const struct attribute_group){\
179+
.attrs = (struct attribute*[])STEP_TIMER_LIST(step),\
180+
.is_visible = tgu_node_visible,\
181+
.name = "step" #step "_timer" \
182+
})
183+
184+
#define COUNTER_ATTRIBUTE_GROUP_INIT(step)\
185+
(&(const struct attribute_group){\
186+
.attrs = (struct attribute*[])STEP_COUNTER_LIST(step),\
187+
.is_visible = tgu_node_visible,\
188+
.name = "step" #step "_counter" \
189+
})
190+
146191
enum operation_index {
147192
TGU_PRIORITY0,
148193
TGU_PRIORITY1,
149194
TGU_PRIORITY2,
150195
TGU_PRIORITY3,
151196
TGU_CONDITION_DECODE,
152-
TGU_CONDITION_SELECT
197+
TGU_CONDITION_SELECT,
198+
TGU_TIMER,
199+
TGU_COUNTER
153200
};
154201

155202
/* Maximum priority that TGU supports */
@@ -166,6 +213,8 @@ struct value_table {
166213
unsigned int *priority;
167214
unsigned int *condition_decode;
168215
unsigned int *condition_select;
216+
unsigned int *timer;
217+
unsigned int *counter;
169218
};
170219

171220
/**
@@ -180,6 +229,8 @@ struct value_table {
180229
* @max_step: Maximum step size
181230
* @max_condition_decode: Maximum number of condition_decode
182231
* @max_condition_select: Maximum number of condition_select
232+
* @max_timer: Maximum number of timers
233+
* @max_counter: Maximum number of counters
183234
*
184235
* This structure defines the data associated with a TGU device,
185236
* including its base address, device pointers, clock, spinlock for
@@ -197,6 +248,8 @@ struct tgu_drvdata {
197248
int max_step;
198249
int max_condition_decode;
199250
int max_condition_select;
251+
int max_timer;
252+
int max_counter;
200253
};
201254

202255
#endif

0 commit comments

Comments
 (0)