1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
6 #include <linux/amba/bus.h>
7 #include <linux/bitfield.h>
8 #include <linux/bitmap.h>
9 #include <linux/coresight.h>
10 #include <linux/coresight-pmu.h>
11 #include <linux/device.h>
12 #include <linux/err.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
19 #include "coresight-priv.h"
20 #include "coresight-tpdm.h"
22 DEFINE_CORESIGHT_DEVLIST(tpdm_devs
, "tpdm");
24 /* Read dataset array member with the index number */
25 static ssize_t
tpdm_simple_dataset_show(struct device
*dev
,
26 struct device_attribute
*attr
,
29 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
30 struct tpdm_dataset_attribute
*tpdm_attr
=
31 container_of(attr
, struct tpdm_dataset_attribute
, attr
);
33 switch (tpdm_attr
->mem
) {
35 if (tpdm_attr
->idx
>= TPDM_DSB_MAX_EDCR
)
37 return sysfs_emit(buf
, "0x%x\n",
38 drvdata
->dsb
->edge_ctrl
[tpdm_attr
->idx
]);
39 case DSB_EDGE_CTRL_MASK
:
40 if (tpdm_attr
->idx
>= TPDM_DSB_MAX_EDCMR
)
42 return sysfs_emit(buf
, "0x%x\n",
43 drvdata
->dsb
->edge_ctrl_mask
[tpdm_attr
->idx
]);
45 if (tpdm_attr
->idx
>= TPDM_DSB_MAX_PATT
)
47 return sysfs_emit(buf
, "0x%x\n",
48 drvdata
->dsb
->trig_patt
[tpdm_attr
->idx
]);
49 case DSB_TRIG_PATT_MASK
:
50 if (tpdm_attr
->idx
>= TPDM_DSB_MAX_PATT
)
52 return sysfs_emit(buf
, "0x%x\n",
53 drvdata
->dsb
->trig_patt_mask
[tpdm_attr
->idx
]);
55 if (tpdm_attr
->idx
>= TPDM_DSB_MAX_PATT
)
57 return sysfs_emit(buf
, "0x%x\n",
58 drvdata
->dsb
->patt_val
[tpdm_attr
->idx
]);
60 if (tpdm_attr
->idx
>= TPDM_DSB_MAX_PATT
)
62 return sysfs_emit(buf
, "0x%x\n",
63 drvdata
->dsb
->patt_mask
[tpdm_attr
->idx
]);
65 if (tpdm_attr
->idx
>= drvdata
->dsb_msr_num
)
67 return sysfs_emit(buf
, "0x%x\n",
68 drvdata
->dsb
->msr
[tpdm_attr
->idx
]);
70 if (tpdm_attr
->idx
>= TPDM_CMB_MAX_PATT
)
72 return sysfs_emit(buf
, "0x%x\n",
73 drvdata
->cmb
->trig_patt
[tpdm_attr
->idx
]);
74 case CMB_TRIG_PATT_MASK
:
75 if (tpdm_attr
->idx
>= TPDM_CMB_MAX_PATT
)
77 return sysfs_emit(buf
, "0x%x\n",
78 drvdata
->cmb
->trig_patt_mask
[tpdm_attr
->idx
]);
80 if (tpdm_attr
->idx
>= TPDM_CMB_MAX_PATT
)
82 return sysfs_emit(buf
, "0x%x\n",
83 drvdata
->cmb
->patt_val
[tpdm_attr
->idx
]);
85 if (tpdm_attr
->idx
>= TPDM_CMB_MAX_PATT
)
87 return sysfs_emit(buf
, "0x%x\n",
88 drvdata
->cmb
->patt_mask
[tpdm_attr
->idx
]);
90 if (tpdm_attr
->idx
>= drvdata
->cmb_msr_num
)
92 return sysfs_emit(buf
, "0x%x\n",
93 drvdata
->cmb
->msr
[tpdm_attr
->idx
]);
98 /* Write dataset array member with the index number */
99 static ssize_t
tpdm_simple_dataset_store(struct device
*dev
,
100 struct device_attribute
*attr
,
105 ssize_t ret
= -EINVAL
;
107 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
108 struct tpdm_dataset_attribute
*tpdm_attr
=
109 container_of(attr
, struct tpdm_dataset_attribute
, attr
);
111 if (kstrtoul(buf
, 0, &val
))
114 guard(spinlock
)(&drvdata
->spinlock
);
115 switch (tpdm_attr
->mem
) {
117 if (tpdm_attr
->idx
< TPDM_DSB_MAX_PATT
) {
118 drvdata
->dsb
->trig_patt
[tpdm_attr
->idx
] = val
;
122 case DSB_TRIG_PATT_MASK
:
123 if (tpdm_attr
->idx
< TPDM_DSB_MAX_PATT
) {
124 drvdata
->dsb
->trig_patt_mask
[tpdm_attr
->idx
] = val
;
129 if (tpdm_attr
->idx
< TPDM_DSB_MAX_PATT
) {
130 drvdata
->dsb
->patt_val
[tpdm_attr
->idx
] = val
;
135 if (tpdm_attr
->idx
< TPDM_DSB_MAX_PATT
) {
136 drvdata
->dsb
->patt_mask
[tpdm_attr
->idx
] = val
;
141 if (tpdm_attr
->idx
< drvdata
->dsb_msr_num
) {
142 drvdata
->dsb
->msr
[tpdm_attr
->idx
] = val
;
147 if (tpdm_attr
->idx
< TPDM_CMB_MAX_PATT
) {
148 drvdata
->cmb
->trig_patt
[tpdm_attr
->idx
] = val
;
152 case CMB_TRIG_PATT_MASK
:
153 if (tpdm_attr
->idx
< TPDM_CMB_MAX_PATT
) {
154 drvdata
->cmb
->trig_patt_mask
[tpdm_attr
->idx
] = val
;
159 if (tpdm_attr
->idx
< TPDM_CMB_MAX_PATT
) {
160 drvdata
->cmb
->patt_val
[tpdm_attr
->idx
] = val
;
165 if (tpdm_attr
->idx
< TPDM_CMB_MAX_PATT
) {
166 drvdata
->cmb
->patt_mask
[tpdm_attr
->idx
] = val
;
171 if (tpdm_attr
->idx
< drvdata
->cmb_msr_num
) {
172 drvdata
->cmb
->msr
[tpdm_attr
->idx
] = val
;
183 static umode_t
tpdm_dsb_is_visible(struct kobject
*kobj
,
184 struct attribute
*attr
, int n
)
186 struct device
*dev
= kobj_to_dev(kobj
);
187 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
189 if (drvdata
&& tpdm_has_dsb_dataset(drvdata
))
195 static umode_t
tpdm_cmb_is_visible(struct kobject
*kobj
,
196 struct attribute
*attr
, int n
)
198 struct device
*dev
= kobj_to_dev(kobj
);
199 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
201 if (drvdata
&& tpdm_has_cmb_dataset(drvdata
))
207 static umode_t
tpdm_dsb_msr_is_visible(struct kobject
*kobj
,
208 struct attribute
*attr
, int n
)
210 struct device
*dev
= kobj_to_dev(kobj
);
211 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
212 struct device_attribute
*dev_attr
=
213 container_of(attr
, struct device_attribute
, attr
);
214 struct tpdm_dataset_attribute
*tpdm_attr
=
215 container_of(dev_attr
, struct tpdm_dataset_attribute
, attr
);
217 if (tpdm_attr
->idx
< drvdata
->dsb_msr_num
)
223 static umode_t
tpdm_cmb_msr_is_visible(struct kobject
*kobj
,
224 struct attribute
*attr
, int n
)
226 struct device
*dev
= kobj_to_dev(kobj
);
227 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
229 struct device_attribute
*dev_attr
=
230 container_of(attr
, struct device_attribute
, attr
);
231 struct tpdm_dataset_attribute
*tpdm_attr
=
232 container_of(dev_attr
, struct tpdm_dataset_attribute
, attr
);
234 if (tpdm_attr
->idx
< drvdata
->cmb_msr_num
)
240 static void tpdm_reset_datasets(struct tpdm_drvdata
*drvdata
)
242 if (tpdm_has_dsb_dataset(drvdata
)) {
243 memset(drvdata
->dsb
, 0, sizeof(struct dsb_dataset
));
245 drvdata
->dsb
->trig_ts
= true;
246 drvdata
->dsb
->trig_type
= false;
250 memset(drvdata
->cmb
, 0, sizeof(struct cmb_dataset
));
253 static void set_dsb_mode(struct tpdm_drvdata
*drvdata
, u32
*val
)
257 /* Set the test accurate mode */
258 mode
= TPDM_DSB_MODE_TEST(drvdata
->dsb
->mode
);
259 *val
&= ~TPDM_DSB_CR_TEST_MODE
;
260 *val
|= FIELD_PREP(TPDM_DSB_CR_TEST_MODE
, mode
);
262 /* Set the byte lane for high-performance mode */
263 mode
= TPDM_DSB_MODE_HPBYTESEL(drvdata
->dsb
->mode
);
264 *val
&= ~TPDM_DSB_CR_HPSEL
;
265 *val
|= FIELD_PREP(TPDM_DSB_CR_HPSEL
, mode
);
267 /* Set the performance mode */
268 if (drvdata
->dsb
->mode
& TPDM_DSB_MODE_PERF
)
269 *val
|= TPDM_DSB_CR_MODE
;
271 *val
&= ~TPDM_DSB_CR_MODE
;
274 static void set_dsb_tier(struct tpdm_drvdata
*drvdata
)
278 val
= readl_relaxed(drvdata
->base
+ TPDM_DSB_TIER
);
280 /* Clear all relevant fields */
281 val
&= ~(TPDM_DSB_TIER_PATT_TSENAB
| TPDM_DSB_TIER_PATT_TYPE
|
282 TPDM_DSB_TIER_XTRIG_TSENAB
);
284 /* Set pattern timestamp type and enablement */
285 if (drvdata
->dsb
->patt_ts
) {
286 val
|= TPDM_DSB_TIER_PATT_TSENAB
;
287 if (drvdata
->dsb
->patt_type
)
288 val
|= TPDM_DSB_TIER_PATT_TYPE
;
290 val
&= ~TPDM_DSB_TIER_PATT_TYPE
;
292 val
&= ~TPDM_DSB_TIER_PATT_TSENAB
;
295 /* Set trigger timestamp */
296 if (drvdata
->dsb
->trig_ts
)
297 val
|= TPDM_DSB_TIER_XTRIG_TSENAB
;
299 val
&= ~TPDM_DSB_TIER_XTRIG_TSENAB
;
301 writel_relaxed(val
, drvdata
->base
+ TPDM_DSB_TIER
);
304 static void set_dsb_msr(struct tpdm_drvdata
*drvdata
)
308 for (i
= 0; i
< drvdata
->dsb_msr_num
; i
++)
309 writel_relaxed(drvdata
->dsb
->msr
[i
],
310 drvdata
->base
+ TPDM_DSB_MSR(i
));
313 static void tpdm_enable_dsb(struct tpdm_drvdata
*drvdata
)
317 if (!tpdm_has_dsb_dataset(drvdata
))
320 for (i
= 0; i
< TPDM_DSB_MAX_EDCR
; i
++)
321 writel_relaxed(drvdata
->dsb
->edge_ctrl
[i
],
322 drvdata
->base
+ TPDM_DSB_EDCR(i
));
323 for (i
= 0; i
< TPDM_DSB_MAX_EDCMR
; i
++)
324 writel_relaxed(drvdata
->dsb
->edge_ctrl_mask
[i
],
325 drvdata
->base
+ TPDM_DSB_EDCMR(i
));
326 for (i
= 0; i
< TPDM_DSB_MAX_PATT
; i
++) {
327 writel_relaxed(drvdata
->dsb
->patt_val
[i
],
328 drvdata
->base
+ TPDM_DSB_TPR(i
));
329 writel_relaxed(drvdata
->dsb
->patt_mask
[i
],
330 drvdata
->base
+ TPDM_DSB_TPMR(i
));
331 writel_relaxed(drvdata
->dsb
->trig_patt
[i
],
332 drvdata
->base
+ TPDM_DSB_XPR(i
));
333 writel_relaxed(drvdata
->dsb
->trig_patt_mask
[i
],
334 drvdata
->base
+ TPDM_DSB_XPMR(i
));
337 set_dsb_tier(drvdata
);
338 set_dsb_msr(drvdata
);
340 val
= readl_relaxed(drvdata
->base
+ TPDM_DSB_CR
);
341 /* Set the mode of DSB dataset */
342 set_dsb_mode(drvdata
, &val
);
343 /* Set trigger type */
344 if (drvdata
->dsb
->trig_type
)
345 val
|= TPDM_DSB_CR_TRIG_TYPE
;
347 val
&= ~TPDM_DSB_CR_TRIG_TYPE
;
348 /* Set the enable bit of DSB control register to 1 */
349 val
|= TPDM_DSB_CR_ENA
;
350 writel_relaxed(val
, drvdata
->base
+ TPDM_DSB_CR
);
353 static void set_cmb_tier(struct tpdm_drvdata
*drvdata
)
357 val
= readl_relaxed(drvdata
->base
+ TPDM_CMB_TIER
);
359 /* Clear all relevant fields */
360 val
&= ~(TPDM_CMB_TIER_PATT_TSENAB
| TPDM_CMB_TIER_TS_ALL
|
361 TPDM_CMB_TIER_XTRIG_TSENAB
);
363 /* Set pattern timestamp type and enablement */
364 if (drvdata
->cmb
->patt_ts
)
365 val
|= TPDM_CMB_TIER_PATT_TSENAB
;
367 /* Set trigger timestamp */
368 if (drvdata
->cmb
->trig_ts
)
369 val
|= TPDM_CMB_TIER_XTRIG_TSENAB
;
371 /* Set all timestamp enablement*/
372 if (drvdata
->cmb
->ts_all
)
373 val
|= TPDM_CMB_TIER_TS_ALL
;
375 writel_relaxed(val
, drvdata
->base
+ TPDM_CMB_TIER
);
378 static void set_cmb_msr(struct tpdm_drvdata
*drvdata
)
382 for (i
= 0; i
< drvdata
->cmb_msr_num
; i
++)
383 writel_relaxed(drvdata
->cmb
->msr
[i
],
384 drvdata
->base
+ TPDM_CMB_MSR(i
));
387 static void tpdm_enable_cmb(struct tpdm_drvdata
*drvdata
)
391 if (!tpdm_has_cmb_dataset(drvdata
))
394 /* Configure pattern registers */
395 for (i
= 0; i
< TPDM_CMB_MAX_PATT
; i
++) {
396 writel_relaxed(drvdata
->cmb
->patt_val
[i
],
397 drvdata
->base
+ TPDM_CMB_TPR(i
));
398 writel_relaxed(drvdata
->cmb
->patt_mask
[i
],
399 drvdata
->base
+ TPDM_CMB_TPMR(i
));
400 writel_relaxed(drvdata
->cmb
->trig_patt
[i
],
401 drvdata
->base
+ TPDM_CMB_XPR(i
));
402 writel_relaxed(drvdata
->cmb
->trig_patt_mask
[i
],
403 drvdata
->base
+ TPDM_CMB_XPMR(i
));
406 set_cmb_tier(drvdata
);
407 set_cmb_msr(drvdata
);
409 val
= readl_relaxed(drvdata
->base
+ TPDM_CMB_CR
);
411 * Set to 0 for continuous CMB collection mode,
412 * 1 for trace-on-change CMB collection mode.
414 if (drvdata
->cmb
->trace_mode
)
415 val
|= TPDM_CMB_CR_MODE
;
417 val
&= ~TPDM_CMB_CR_MODE
;
418 /* Set the enable bit of CMB control register to 1 */
419 val
|= TPDM_CMB_CR_ENA
;
420 writel_relaxed(val
, drvdata
->base
+ TPDM_CMB_CR
);
424 * TPDM enable operations
425 * The TPDM or Monitor serves as data collection component for various
426 * dataset types. It covers Basic Counts(BC), Tenure Counts(TC),
427 * Continuous Multi-Bit(CMB), Multi-lane CMB(MCMB) and Discrete Single
428 * Bit(DSB). This function will initialize the configuration according
429 * to the dataset type supported by the TPDM.
431 static void __tpdm_enable(struct tpdm_drvdata
*drvdata
)
433 CS_UNLOCK(drvdata
->base
);
435 tpdm_enable_dsb(drvdata
);
436 tpdm_enable_cmb(drvdata
);
438 CS_LOCK(drvdata
->base
);
441 static int tpdm_enable(struct coresight_device
*csdev
, struct perf_event
*event
,
443 __maybe_unused
struct coresight_trace_id_map
*id_map
)
445 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(csdev
->dev
.parent
);
447 spin_lock(&drvdata
->spinlock
);
448 if (drvdata
->enable
) {
449 spin_unlock(&drvdata
->spinlock
);
453 if (!coresight_take_mode(csdev
, mode
)) {
454 spin_unlock(&drvdata
->spinlock
);
458 __tpdm_enable(drvdata
);
459 drvdata
->enable
= true;
460 spin_unlock(&drvdata
->spinlock
);
462 dev_dbg(drvdata
->dev
, "TPDM tracing enabled\n");
466 static void tpdm_disable_dsb(struct tpdm_drvdata
*drvdata
)
470 if (!tpdm_has_dsb_dataset(drvdata
))
473 /* Set the enable bit of DSB control register to 0 */
474 val
= readl_relaxed(drvdata
->base
+ TPDM_DSB_CR
);
475 val
&= ~TPDM_DSB_CR_ENA
;
476 writel_relaxed(val
, drvdata
->base
+ TPDM_DSB_CR
);
479 static void tpdm_disable_cmb(struct tpdm_drvdata
*drvdata
)
483 if (!tpdm_has_cmb_dataset(drvdata
))
486 val
= readl_relaxed(drvdata
->base
+ TPDM_CMB_CR
);
487 /* Set the enable bit of CMB control register to 0 */
488 val
&= ~TPDM_CMB_CR_ENA
;
489 writel_relaxed(val
, drvdata
->base
+ TPDM_CMB_CR
);
492 /* TPDM disable operations */
493 static void __tpdm_disable(struct tpdm_drvdata
*drvdata
)
495 CS_UNLOCK(drvdata
->base
);
497 tpdm_disable_dsb(drvdata
);
498 tpdm_disable_cmb(drvdata
);
500 CS_LOCK(drvdata
->base
);
503 static void tpdm_disable(struct coresight_device
*csdev
,
504 struct perf_event
*event
)
506 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(csdev
->dev
.parent
);
508 spin_lock(&drvdata
->spinlock
);
509 if (!drvdata
->enable
) {
510 spin_unlock(&drvdata
->spinlock
);
514 __tpdm_disable(drvdata
);
515 coresight_set_mode(csdev
, CS_MODE_DISABLED
);
516 drvdata
->enable
= false;
517 spin_unlock(&drvdata
->spinlock
);
519 dev_dbg(drvdata
->dev
, "TPDM tracing disabled\n");
522 static const struct coresight_ops_source tpdm_source_ops
= {
523 .enable
= tpdm_enable
,
524 .disable
= tpdm_disable
,
527 static const struct coresight_ops tpdm_cs_ops
= {
528 .source_ops
= &tpdm_source_ops
,
531 static int tpdm_datasets_setup(struct tpdm_drvdata
*drvdata
)
535 /* Get the datasets present on the TPDM. */
536 pidr
= readl_relaxed(drvdata
->base
+ CORESIGHT_PERIPHIDR0
);
537 drvdata
->datasets
|= pidr
& GENMASK(TPDM_DATASETS
- 1, 0);
539 if (tpdm_has_dsb_dataset(drvdata
) && (!drvdata
->dsb
)) {
540 drvdata
->dsb
= devm_kzalloc(drvdata
->dev
,
541 sizeof(*drvdata
->dsb
), GFP_KERNEL
);
545 if (tpdm_has_cmb_dataset(drvdata
) && (!drvdata
->cmb
)) {
546 drvdata
->cmb
= devm_kzalloc(drvdata
->dev
,
547 sizeof(*drvdata
->cmb
), GFP_KERNEL
);
551 tpdm_reset_datasets(drvdata
);
556 static ssize_t
reset_dataset_store(struct device
*dev
,
557 struct device_attribute
*attr
,
563 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
565 ret
= kstrtoul(buf
, 0, &val
);
569 spin_lock(&drvdata
->spinlock
);
570 tpdm_reset_datasets(drvdata
);
571 spin_unlock(&drvdata
->spinlock
);
575 static DEVICE_ATTR_WO(reset_dataset
);
578 * value 1: 64 bits test data
579 * value 2: 32 bits test data
581 static ssize_t
integration_test_store(struct device
*dev
,
582 struct device_attribute
*attr
,
588 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
590 ret
= kstrtoul(buf
, 10, &val
);
594 if (val
!= 1 && val
!= 2)
597 if (!drvdata
->enable
)
601 val
= ATBCNTRL_VAL_64
;
603 val
= ATBCNTRL_VAL_32
;
604 CS_UNLOCK(drvdata
->base
);
605 writel_relaxed(0x1, drvdata
->base
+ TPDM_ITCNTRL
);
607 for (i
= 0; i
< INTEGRATION_TEST_CYCLE
; i
++)
608 writel_relaxed(val
, drvdata
->base
+ TPDM_ITATBCNTRL
);
610 writel_relaxed(0, drvdata
->base
+ TPDM_ITCNTRL
);
611 CS_LOCK(drvdata
->base
);
614 static DEVICE_ATTR_WO(integration_test
);
616 static struct attribute
*tpdm_attrs
[] = {
617 &dev_attr_reset_dataset
.attr
,
618 &dev_attr_integration_test
.attr
,
622 static struct attribute_group tpdm_attr_grp
= {
626 static ssize_t
dsb_mode_show(struct device
*dev
,
627 struct device_attribute
*attr
,
630 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
632 return sysfs_emit(buf
, "%x\n", drvdata
->dsb
->mode
);
635 static ssize_t
dsb_mode_store(struct device
*dev
,
636 struct device_attribute
*attr
,
640 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
643 if ((kstrtoul(buf
, 0, &val
)) || (val
< 0) ||
644 (val
& ~TPDM_DSB_MODE_MASK
))
647 spin_lock(&drvdata
->spinlock
);
648 drvdata
->dsb
->mode
= val
& TPDM_DSB_MODE_MASK
;
649 spin_unlock(&drvdata
->spinlock
);
652 static DEVICE_ATTR_RW(dsb_mode
);
654 static ssize_t
ctrl_idx_show(struct device
*dev
,
655 struct device_attribute
*attr
,
658 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
660 return sysfs_emit(buf
, "%u\n",
661 (unsigned int)drvdata
->dsb
->edge_ctrl_idx
);
665 * The EDCR registers can include up to 16 32-bit registers, and each
666 * one can be configured to control up to 16 edge detections(2 bits
667 * control one edge detection). So a total 256 edge detections can be
668 * configured. This function provides a way to set the index number of
669 * the edge detection which needs to be configured.
671 static ssize_t
ctrl_idx_store(struct device
*dev
,
672 struct device_attribute
*attr
,
676 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
679 if ((kstrtoul(buf
, 0, &val
)) || (val
>= TPDM_DSB_MAX_LINES
))
682 spin_lock(&drvdata
->spinlock
);
683 drvdata
->dsb
->edge_ctrl_idx
= val
;
684 spin_unlock(&drvdata
->spinlock
);
688 static DEVICE_ATTR_RW(ctrl_idx
);
691 * This function is used to control the edge detection according
692 * to the index number that has been set.
693 * "edge_ctrl" should be one of the following values.
694 * 0 - Rising edge detection
695 * 1 - Falling edge detection
696 * 2 - Rising and falling edge detection (toggle detection)
698 static ssize_t
ctrl_val_store(struct device
*dev
,
699 struct device_attribute
*attr
,
703 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
704 unsigned long val
, edge_ctrl
;
707 if ((kstrtoul(buf
, 0, &edge_ctrl
)) || (edge_ctrl
> 0x2))
710 spin_lock(&drvdata
->spinlock
);
712 * There are 2 bit per DSB Edge Control line.
713 * Thus we have 16 lines in a 32bit word.
715 reg
= EDCR_TO_WORD_IDX(drvdata
->dsb
->edge_ctrl_idx
);
716 val
= drvdata
->dsb
->edge_ctrl
[reg
];
717 val
&= ~EDCR_TO_WORD_MASK(drvdata
->dsb
->edge_ctrl_idx
);
718 val
|= EDCR_TO_WORD_VAL(edge_ctrl
, drvdata
->dsb
->edge_ctrl_idx
);
719 drvdata
->dsb
->edge_ctrl
[reg
] = val
;
720 spin_unlock(&drvdata
->spinlock
);
724 static DEVICE_ATTR_WO(ctrl_val
);
726 static ssize_t
ctrl_mask_store(struct device
*dev
,
727 struct device_attribute
*attr
,
731 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
736 if ((kstrtoul(buf
, 0, &val
)) || (val
& ~1UL))
739 spin_lock(&drvdata
->spinlock
);
741 * There is 1 bit per DSB Edge Control Mark line.
742 * Thus we have 32 lines in a 32bit word.
744 reg
= EDCMR_TO_WORD_IDX(drvdata
->dsb
->edge_ctrl_idx
);
745 set
= drvdata
->dsb
->edge_ctrl_mask
[reg
];
747 set
|= BIT(EDCMR_TO_WORD_SHIFT(drvdata
->dsb
->edge_ctrl_idx
));
749 set
&= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata
->dsb
->edge_ctrl_idx
));
750 drvdata
->dsb
->edge_ctrl_mask
[reg
] = set
;
751 spin_unlock(&drvdata
->spinlock
);
755 static DEVICE_ATTR_WO(ctrl_mask
);
757 static ssize_t
enable_ts_show(struct device
*dev
,
758 struct device_attribute
*attr
,
761 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
762 struct tpdm_dataset_attribute
*tpdm_attr
=
763 container_of(attr
, struct tpdm_dataset_attribute
, attr
);
764 ssize_t size
= -EINVAL
;
766 if (tpdm_attr
->mem
== DSB_PATT
)
767 size
= sysfs_emit(buf
, "%u\n",
768 (unsigned int)drvdata
->dsb
->patt_ts
);
769 else if (tpdm_attr
->mem
== CMB_PATT
)
770 size
= sysfs_emit(buf
, "%u\n",
771 (unsigned int)drvdata
->cmb
->patt_ts
);
777 * value 1: Enable/Disable DSB pattern timestamp
779 static ssize_t
enable_ts_store(struct device
*dev
,
780 struct device_attribute
*attr
,
784 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
785 struct tpdm_dataset_attribute
*tpdm_attr
=
786 container_of(attr
, struct tpdm_dataset_attribute
, attr
);
789 if ((kstrtoul(buf
, 0, &val
)) || (val
& ~1UL))
792 guard(spinlock
)(&drvdata
->spinlock
);
793 if (tpdm_attr
->mem
== DSB_PATT
)
794 drvdata
->dsb
->patt_ts
= !!val
;
795 else if (tpdm_attr
->mem
== CMB_PATT
)
796 drvdata
->cmb
->patt_ts
= !!val
;
803 static ssize_t
set_type_show(struct device
*dev
,
804 struct device_attribute
*attr
,
807 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
809 return sysfs_emit(buf
, "%u\n",
810 (unsigned int)drvdata
->dsb
->patt_type
);
814 * value 1: Set DSB pattern type
816 static ssize_t
set_type_store(struct device
*dev
,
817 struct device_attribute
*attr
,
818 const char *buf
, size_t size
)
820 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
823 if ((kstrtoul(buf
, 0, &val
)) || (val
& ~1UL))
826 spin_lock(&drvdata
->spinlock
);
827 drvdata
->dsb
->patt_type
= val
;
828 spin_unlock(&drvdata
->spinlock
);
831 static DEVICE_ATTR_RW(set_type
);
833 static ssize_t
dsb_trig_type_show(struct device
*dev
,
834 struct device_attribute
*attr
, char *buf
)
836 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
838 return sysfs_emit(buf
, "%u\n",
839 (unsigned int)drvdata
->dsb
->trig_type
);
843 * Trigger type (boolean):
844 * false - Disable trigger type.
845 * true - Enable trigger type.
847 static ssize_t
dsb_trig_type_store(struct device
*dev
,
848 struct device_attribute
*attr
,
852 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
855 if ((kstrtoul(buf
, 0, &val
)) || (val
& ~1UL))
858 spin_lock(&drvdata
->spinlock
);
860 drvdata
->dsb
->trig_type
= true;
862 drvdata
->dsb
->trig_type
= false;
863 spin_unlock(&drvdata
->spinlock
);
866 static DEVICE_ATTR_RW(dsb_trig_type
);
868 static ssize_t
dsb_trig_ts_show(struct device
*dev
,
869 struct device_attribute
*attr
,
872 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
874 return sysfs_emit(buf
, "%u\n",
875 (unsigned int)drvdata
->dsb
->trig_ts
);
879 * Trigger timestamp (boolean):
880 * false - Disable trigger timestamp.
881 * true - Enable trigger timestamp.
883 static ssize_t
dsb_trig_ts_store(struct device
*dev
,
884 struct device_attribute
*attr
,
888 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
891 if ((kstrtoul(buf
, 0, &val
)) || (val
& ~1UL))
894 spin_lock(&drvdata
->spinlock
);
896 drvdata
->dsb
->trig_ts
= true;
898 drvdata
->dsb
->trig_ts
= false;
899 spin_unlock(&drvdata
->spinlock
);
902 static DEVICE_ATTR_RW(dsb_trig_ts
);
904 static ssize_t
cmb_mode_show(struct device
*dev
,
905 struct device_attribute
*attr
,
908 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
910 return sysfs_emit(buf
, "%x\n", drvdata
->cmb
->trace_mode
);
914 static ssize_t
cmb_mode_store(struct device
*dev
,
915 struct device_attribute
*attr
,
919 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
920 unsigned long trace_mode
;
922 if (kstrtoul(buf
, 0, &trace_mode
) || (trace_mode
& ~1UL))
925 spin_lock(&drvdata
->spinlock
);
926 drvdata
->cmb
->trace_mode
= trace_mode
;
927 spin_unlock(&drvdata
->spinlock
);
930 static DEVICE_ATTR_RW(cmb_mode
);
932 static ssize_t
cmb_ts_all_show(struct device
*dev
,
933 struct device_attribute
*attr
,
936 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
938 return sysfs_emit(buf
, "%u\n",
939 (unsigned int)drvdata
->cmb
->ts_all
);
942 static ssize_t
cmb_ts_all_store(struct device
*dev
,
943 struct device_attribute
*attr
,
947 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
950 if ((kstrtoul(buf
, 0, &val
)) || (val
& ~1UL))
953 guard(spinlock
)(&drvdata
->spinlock
);
955 drvdata
->cmb
->ts_all
= true;
957 drvdata
->cmb
->ts_all
= false;
961 static DEVICE_ATTR_RW(cmb_ts_all
);
963 static ssize_t
cmb_trig_ts_show(struct device
*dev
,
964 struct device_attribute
*attr
,
967 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
969 return sysfs_emit(buf
, "%u\n",
970 (unsigned int)drvdata
->cmb
->trig_ts
);
973 static ssize_t
cmb_trig_ts_store(struct device
*dev
,
974 struct device_attribute
*attr
,
978 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(dev
->parent
);
981 if ((kstrtoul(buf
, 0, &val
)) || (val
& ~1UL))
984 guard(spinlock
)(&drvdata
->spinlock
);
986 drvdata
->cmb
->trig_ts
= true;
988 drvdata
->cmb
->trig_ts
= false;
992 static DEVICE_ATTR_RW(cmb_trig_ts
);
994 static struct attribute
*tpdm_dsb_edge_attrs
[] = {
995 &dev_attr_ctrl_idx
.attr
,
996 &dev_attr_ctrl_val
.attr
,
997 &dev_attr_ctrl_mask
.attr
,
998 DSB_EDGE_CTRL_ATTR(0),
999 DSB_EDGE_CTRL_ATTR(1),
1000 DSB_EDGE_CTRL_ATTR(2),
1001 DSB_EDGE_CTRL_ATTR(3),
1002 DSB_EDGE_CTRL_ATTR(4),
1003 DSB_EDGE_CTRL_ATTR(5),
1004 DSB_EDGE_CTRL_ATTR(6),
1005 DSB_EDGE_CTRL_ATTR(7),
1006 DSB_EDGE_CTRL_ATTR(8),
1007 DSB_EDGE_CTRL_ATTR(9),
1008 DSB_EDGE_CTRL_ATTR(10),
1009 DSB_EDGE_CTRL_ATTR(11),
1010 DSB_EDGE_CTRL_ATTR(12),
1011 DSB_EDGE_CTRL_ATTR(13),
1012 DSB_EDGE_CTRL_ATTR(14),
1013 DSB_EDGE_CTRL_ATTR(15),
1014 DSB_EDGE_CTRL_MASK_ATTR(0),
1015 DSB_EDGE_CTRL_MASK_ATTR(1),
1016 DSB_EDGE_CTRL_MASK_ATTR(2),
1017 DSB_EDGE_CTRL_MASK_ATTR(3),
1018 DSB_EDGE_CTRL_MASK_ATTR(4),
1019 DSB_EDGE_CTRL_MASK_ATTR(5),
1020 DSB_EDGE_CTRL_MASK_ATTR(6),
1021 DSB_EDGE_CTRL_MASK_ATTR(7),
1025 static struct attribute
*tpdm_dsb_trig_patt_attrs
[] = {
1026 DSB_TRIG_PATT_ATTR(0),
1027 DSB_TRIG_PATT_ATTR(1),
1028 DSB_TRIG_PATT_ATTR(2),
1029 DSB_TRIG_PATT_ATTR(3),
1030 DSB_TRIG_PATT_ATTR(4),
1031 DSB_TRIG_PATT_ATTR(5),
1032 DSB_TRIG_PATT_ATTR(6),
1033 DSB_TRIG_PATT_ATTR(7),
1034 DSB_TRIG_PATT_MASK_ATTR(0),
1035 DSB_TRIG_PATT_MASK_ATTR(1),
1036 DSB_TRIG_PATT_MASK_ATTR(2),
1037 DSB_TRIG_PATT_MASK_ATTR(3),
1038 DSB_TRIG_PATT_MASK_ATTR(4),
1039 DSB_TRIG_PATT_MASK_ATTR(5),
1040 DSB_TRIG_PATT_MASK_ATTR(6),
1041 DSB_TRIG_PATT_MASK_ATTR(7),
1045 static struct attribute
*tpdm_dsb_patt_attrs
[] = {
1054 DSB_PATT_MASK_ATTR(0),
1055 DSB_PATT_MASK_ATTR(1),
1056 DSB_PATT_MASK_ATTR(2),
1057 DSB_PATT_MASK_ATTR(3),
1058 DSB_PATT_MASK_ATTR(4),
1059 DSB_PATT_MASK_ATTR(5),
1060 DSB_PATT_MASK_ATTR(6),
1061 DSB_PATT_MASK_ATTR(7),
1063 &dev_attr_set_type
.attr
,
1067 static struct attribute
*tpdm_dsb_msr_attrs
[] = {
1103 static struct attribute
*tpdm_cmb_trig_patt_attrs
[] = {
1104 CMB_TRIG_PATT_ATTR(0),
1105 CMB_TRIG_PATT_ATTR(1),
1106 CMB_TRIG_PATT_MASK_ATTR(0),
1107 CMB_TRIG_PATT_MASK_ATTR(1),
1111 static struct attribute
*tpdm_cmb_patt_attrs
[] = {
1114 CMB_PATT_MASK_ATTR(0),
1115 CMB_PATT_MASK_ATTR(1),
1120 static struct attribute
*tpdm_cmb_msr_attrs
[] = {
1156 static struct attribute
*tpdm_dsb_attrs
[] = {
1157 &dev_attr_dsb_mode
.attr
,
1158 &dev_attr_dsb_trig_ts
.attr
,
1159 &dev_attr_dsb_trig_type
.attr
,
1163 static struct attribute
*tpdm_cmb_attrs
[] = {
1164 &dev_attr_cmb_mode
.attr
,
1165 &dev_attr_cmb_ts_all
.attr
,
1166 &dev_attr_cmb_trig_ts
.attr
,
1170 static struct attribute_group tpdm_dsb_attr_grp
= {
1171 .attrs
= tpdm_dsb_attrs
,
1172 .is_visible
= tpdm_dsb_is_visible
,
1175 static struct attribute_group tpdm_dsb_edge_grp
= {
1176 .attrs
= tpdm_dsb_edge_attrs
,
1177 .is_visible
= tpdm_dsb_is_visible
,
1181 static struct attribute_group tpdm_dsb_trig_patt_grp
= {
1182 .attrs
= tpdm_dsb_trig_patt_attrs
,
1183 .is_visible
= tpdm_dsb_is_visible
,
1184 .name
= "dsb_trig_patt",
1187 static struct attribute_group tpdm_dsb_patt_grp
= {
1188 .attrs
= tpdm_dsb_patt_attrs
,
1189 .is_visible
= tpdm_dsb_is_visible
,
1193 static struct attribute_group tpdm_dsb_msr_grp
= {
1194 .attrs
= tpdm_dsb_msr_attrs
,
1195 .is_visible
= tpdm_dsb_msr_is_visible
,
1199 static struct attribute_group tpdm_cmb_attr_grp
= {
1200 .attrs
= tpdm_cmb_attrs
,
1201 .is_visible
= tpdm_cmb_is_visible
,
1204 static struct attribute_group tpdm_cmb_trig_patt_grp
= {
1205 .attrs
= tpdm_cmb_trig_patt_attrs
,
1206 .is_visible
= tpdm_cmb_is_visible
,
1207 .name
= "cmb_trig_patt",
1210 static struct attribute_group tpdm_cmb_patt_grp
= {
1211 .attrs
= tpdm_cmb_patt_attrs
,
1212 .is_visible
= tpdm_cmb_is_visible
,
1216 static struct attribute_group tpdm_cmb_msr_grp
= {
1217 .attrs
= tpdm_cmb_msr_attrs
,
1218 .is_visible
= tpdm_cmb_msr_is_visible
,
1222 static const struct attribute_group
*tpdm_attr_grps
[] = {
1226 &tpdm_dsb_trig_patt_grp
,
1230 &tpdm_cmb_trig_patt_grp
,
1236 static int tpdm_probe(struct amba_device
*adev
, const struct amba_id
*id
)
1239 struct device
*dev
= &adev
->dev
;
1240 struct coresight_platform_data
*pdata
;
1241 struct tpdm_drvdata
*drvdata
;
1242 struct coresight_desc desc
= { 0 };
1245 pdata
= coresight_get_platform_data(dev
);
1247 return PTR_ERR(pdata
);
1248 adev
->dev
.platform_data
= pdata
;
1251 drvdata
= devm_kzalloc(dev
, sizeof(*drvdata
), GFP_KERNEL
);
1254 drvdata
->dev
= &adev
->dev
;
1255 dev_set_drvdata(dev
, drvdata
);
1257 base
= devm_ioremap_resource(dev
, &adev
->res
);
1259 return PTR_ERR(base
);
1261 drvdata
->base
= base
;
1263 ret
= tpdm_datasets_setup(drvdata
);
1267 if (drvdata
&& tpdm_has_dsb_dataset(drvdata
))
1268 of_property_read_u32(drvdata
->dev
->of_node
,
1269 "qcom,dsb-msrs-num", &drvdata
->dsb_msr_num
);
1271 if (drvdata
&& tpdm_has_cmb_dataset(drvdata
))
1272 of_property_read_u32(drvdata
->dev
->of_node
,
1273 "qcom,cmb-msrs-num", &drvdata
->cmb_msr_num
);
1275 /* Set up coresight component description */
1276 desc
.name
= coresight_alloc_device_name(&tpdm_devs
, dev
);
1279 desc
.type
= CORESIGHT_DEV_TYPE_SOURCE
;
1280 desc
.subtype
.source_subtype
= CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM
;
1281 desc
.ops
= &tpdm_cs_ops
;
1282 desc
.pdata
= adev
->dev
.platform_data
;
1283 desc
.dev
= &adev
->dev
;
1284 desc
.access
= CSDEV_ACCESS_IOMEM(base
);
1285 desc
.groups
= tpdm_attr_grps
;
1286 drvdata
->csdev
= coresight_register(&desc
);
1287 if (IS_ERR(drvdata
->csdev
))
1288 return PTR_ERR(drvdata
->csdev
);
1290 spin_lock_init(&drvdata
->spinlock
);
1292 /* Decrease pm refcount when probe is done.*/
1293 pm_runtime_put(&adev
->dev
);
1298 static void tpdm_remove(struct amba_device
*adev
)
1300 struct tpdm_drvdata
*drvdata
= dev_get_drvdata(&adev
->dev
);
1302 coresight_unregister(drvdata
->csdev
);
1306 * Different TPDM has different periph id.
1307 * The difference is 0-7 bits' value. So ignore 0-7 bits.
1309 static struct amba_id tpdm_ids
[] = {
1317 static struct amba_driver tpdm_driver
= {
1319 .name
= "coresight-tpdm",
1320 .suppress_bind_attrs
= true,
1322 .probe
= tpdm_probe
,
1323 .id_table
= tpdm_ids
,
1324 .remove
= tpdm_remove
,
1327 module_amba_driver(tpdm_driver
);
1329 MODULE_LICENSE("GPL");
1330 MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");