1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2023-2025 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <linux/amba/bus.h> 7 #include <linux/bitfield.h> 8 #include <linux/coresight.h> 9 #include <linux/device.h> 10 #include <linux/err.h> 11 #include <linux/fs.h> 12 #include <linux/io.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 18 #include "coresight-priv.h" 19 #include "coresight-tpda.h" 20 #include "coresight-trace-id.h" 21 #include "coresight-tpdm.h" 22 23 static void tpda_clear_element_size(struct coresight_device *csdev) 24 { 25 struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 26 27 drvdata->dsb_esize = 0; 28 drvdata->cmb_esize = 0; 29 } 30 31 static void tpda_set_element_size(struct tpda_drvdata *drvdata, u32 *val) 32 { 33 /* Clear all relevant fields */ 34 *val &= ~(TPDA_Pn_CR_DSBSIZE | TPDA_Pn_CR_CMBSIZE); 35 36 if (drvdata->dsb_esize == 64) 37 *val |= TPDA_Pn_CR_DSBSIZE; 38 else if (drvdata->dsb_esize == 32) 39 *val &= ~TPDA_Pn_CR_DSBSIZE; 40 41 if (drvdata->cmb_esize == 64) 42 *val |= FIELD_PREP(TPDA_Pn_CR_CMBSIZE, 0x2); 43 else if (drvdata->cmb_esize == 32) 44 *val |= FIELD_PREP(TPDA_Pn_CR_CMBSIZE, 0x1); 45 else if (drvdata->cmb_esize == 8) 46 *val &= ~TPDA_Pn_CR_CMBSIZE; 47 } 48 49 /* 50 * Read the element size from the TPDM device. One TPDM must have at least one of the 51 * element size property. 52 * Returns 53 * 0 - The element size property is read 54 * Others - Cannot read the property of the element size 55 */ 56 static int tpdm_read_element_size(struct tpda_drvdata *drvdata, 57 struct coresight_device *csdev) 58 { 59 int rc = -EINVAL; 60 struct tpdm_drvdata *tpdm_data = dev_get_drvdata(csdev->dev.parent); 61 62 if (tpdm_data->dsb) { 63 rc = fwnode_property_read_u32(dev_fwnode(csdev->dev.parent), 64 "qcom,dsb-element-bits", &drvdata->dsb_esize); 65 if (rc) 66 goto out; 67 } 68 69 if (tpdm_data->cmb) { 70 rc = fwnode_property_read_u32(dev_fwnode(csdev->dev.parent), 71 "qcom,cmb-element-bits", &drvdata->cmb_esize); 72 } 73 74 out: 75 if (rc) 76 dev_warn_once(&csdev->dev, 77 "Failed to read TPDM Element size: %d\n", rc); 78 79 return rc; 80 } 81 82 /* 83 * Search and read element data size from the TPDM node in 84 * the devicetree. Each input port of TPDA is connected to 85 * a TPDM. Different TPDM supports different types of dataset, 86 * and some may support more than one type of dataset. 87 * Parameter "inport" is used to pass in the input port number 88 * of TPDA, and it is set to -1 in the recursize call. 89 */ 90 static int tpda_get_element_size(struct tpda_drvdata *drvdata, 91 struct coresight_device *csdev, 92 int inport) 93 { 94 int rc = 0; 95 int i; 96 struct coresight_device *in; 97 98 for (i = 0; i < csdev->pdata->nr_inconns; i++) { 99 in = csdev->pdata->in_conns[i]->src_dev; 100 if (!in) 101 continue; 102 103 /* Ignore the paths that do not match port */ 104 if (inport >= 0 && 105 csdev->pdata->in_conns[i]->dest_port != inport) 106 continue; 107 108 /* 109 * If this port has a hardcoded filter, use the source 110 * device directly. 111 */ 112 if (csdev->pdata->in_conns[i]->filter_src_fwnode) { 113 in = csdev->pdata->in_conns[i]->filter_src_dev; 114 if (!in) 115 continue; 116 } 117 118 if (coresight_device_is_tpdm(in)) { 119 if (drvdata->dsb_esize || drvdata->cmb_esize) 120 return -EEXIST; 121 rc = tpdm_read_element_size(drvdata, in); 122 if (rc) 123 return rc; 124 } else { 125 /* Recurse down the path */ 126 rc = tpda_get_element_size(drvdata, in, -1); 127 if (rc) 128 return rc; 129 } 130 } 131 132 return rc; 133 } 134 135 /* Settings pre enabling port control register */ 136 static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) 137 { 138 u32 val = 0; 139 140 val |= FIELD_PREP(TPDA_CR_ATID, drvdata->atid); 141 if (drvdata->trig_async) 142 val |= TPDA_CR_SRIE; 143 144 if (drvdata->trig_flag_ts) 145 val |= TPDA_CR_FLRIE; 146 147 if (drvdata->trig_freq) 148 val |= TPDA_CR_FRIE; 149 150 if (drvdata->freq_ts) 151 val |= TPDA_CR_FREQTS; 152 153 if (drvdata->cmbchan_mode) 154 val |= TPDA_CR_CMBCHANMODE; 155 156 writel_relaxed(val, drvdata->base + TPDA_CR); 157 158 /* 159 * If FLRIE bit is set, set the master and channel 160 * id as zero 161 */ 162 if (drvdata->trig_flag_ts) 163 writel_relaxed(0x0, drvdata->base + TPDA_FPID_CR); 164 165 /* Initialize with a value of 0 */ 166 val = 0; 167 if (drvdata->syncr_mode) 168 val |= TPDA_SYNCR_MODE_CTRL_MASK; 169 170 if (drvdata->syncr_count > 0 && 171 drvdata->syncr_count < TPDA_SYNCR_COUNT_MASK) 172 val |= drvdata->syncr_count; 173 else 174 /* Program the count to its MAX value by default */ 175 val |= TPDA_SYNCR_COUNT_MASK; 176 177 writel_relaxed(val, drvdata->base + TPDA_SYNCR); 178 } 179 180 static int tpda_enable_port(struct tpda_drvdata *drvdata, int port) 181 { 182 u32 val; 183 int rc; 184 185 val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port)); 186 tpda_clear_element_size(drvdata->csdev); 187 rc = tpda_get_element_size(drvdata, drvdata->csdev, port); 188 if (!rc && (drvdata->dsb_esize || drvdata->cmb_esize)) { 189 tpda_set_element_size(drvdata, &val); 190 /* Enable the port */ 191 val |= TPDA_Pn_CR_ENA; 192 writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port)); 193 } else if (rc == -EEXIST) 194 dev_warn_once(&drvdata->csdev->dev, 195 "Detected multiple TPDMs on port %d", port); 196 else 197 dev_warn_once(&drvdata->csdev->dev, 198 "Didn't find TPDM element size"); 199 200 return rc; 201 } 202 203 static int __tpda_enable(struct tpda_drvdata *drvdata, int port) 204 { 205 int ret; 206 207 CS_UNLOCK(drvdata->base); 208 209 /* 210 * Only do pre-port enable for first port that calls enable when the 211 * device's main refcount is still 0 212 */ 213 lockdep_assert_held(&drvdata->spinlock); 214 if (!drvdata->csdev->refcnt) 215 tpda_enable_pre_port(drvdata); 216 217 ret = tpda_enable_port(drvdata, port); 218 CS_LOCK(drvdata->base); 219 220 return ret; 221 } 222 223 static int tpda_enable(struct coresight_device *csdev, 224 struct coresight_connection *in, 225 struct coresight_connection *out) 226 { 227 struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 228 int ret = 0; 229 230 spin_lock(&drvdata->spinlock); 231 if (in->dest_refcnt == 0) { 232 ret = __tpda_enable(drvdata, in->dest_port); 233 if (!ret) { 234 in->dest_refcnt++; 235 csdev->refcnt++; 236 dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port); 237 } 238 } 239 240 spin_unlock(&drvdata->spinlock); 241 return ret; 242 } 243 244 static void __tpda_disable(struct tpda_drvdata *drvdata, int port) 245 { 246 u32 val; 247 248 CS_UNLOCK(drvdata->base); 249 250 val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port)); 251 val &= ~TPDA_Pn_CR_ENA; 252 writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port)); 253 254 CS_LOCK(drvdata->base); 255 } 256 257 static void tpda_disable(struct coresight_device *csdev, 258 struct coresight_connection *in, 259 struct coresight_connection *out) 260 { 261 struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 262 263 spin_lock(&drvdata->spinlock); 264 if (--in->dest_refcnt == 0) { 265 __tpda_disable(drvdata, in->dest_port); 266 csdev->refcnt--; 267 } 268 spin_unlock(&drvdata->spinlock); 269 270 dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port); 271 } 272 273 static int tpda_trace_id(struct coresight_device *csdev, __maybe_unused enum cs_mode mode, 274 __maybe_unused struct coresight_device *sink) 275 { 276 struct tpda_drvdata *drvdata; 277 278 drvdata = dev_get_drvdata(csdev->dev.parent); 279 280 return drvdata->atid; 281 } 282 283 static const struct coresight_ops_link tpda_link_ops = { 284 .enable = tpda_enable, 285 .disable = tpda_disable, 286 }; 287 288 static const struct coresight_ops tpda_cs_ops = { 289 .trace_id = tpda_trace_id, 290 .link_ops = &tpda_link_ops, 291 }; 292 293 /* Read cross-trigger register member */ 294 static ssize_t tpda_trig_sysfs_show(struct device *dev, 295 struct device_attribute *attr, 296 char *buf) 297 { 298 struct tpda_trig_sysfs_attribute *tpda_attr = 299 container_of(attr, struct tpda_trig_sysfs_attribute, attr); 300 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 301 302 guard(spinlock)(&drvdata->spinlock); 303 switch (tpda_attr->mem) { 304 case FREQTS: 305 return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->freq_ts); 306 case FRIE: 307 return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->trig_freq); 308 case FLRIE: 309 return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->trig_flag_ts); 310 case SRIE: 311 return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->trig_async); 312 case CMBCHANMODE: 313 return sysfs_emit(buf, "%u\n", (unsigned int)drvdata->cmbchan_mode); 314 315 } 316 return -EINVAL; 317 } 318 319 static ssize_t tpda_trig_sysfs_store(struct device *dev, 320 struct device_attribute *attr, 321 const char *buf, 322 size_t size) 323 { 324 struct tpda_trig_sysfs_attribute *tpda_attr = 325 container_of(attr, struct tpda_trig_sysfs_attribute, attr); 326 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 327 unsigned long val; 328 329 if (kstrtoul(buf, 0, &val)) 330 return -EINVAL; 331 332 guard(spinlock)(&drvdata->spinlock); 333 switch (tpda_attr->mem) { 334 case FREQTS: 335 drvdata->freq_ts = !!val; 336 break; 337 case FRIE: 338 drvdata->trig_freq = !!val; 339 break; 340 case FLRIE: 341 drvdata->trig_flag_ts = !!val; 342 break; 343 case SRIE: 344 drvdata->trig_async = !!val; 345 break; 346 case CMBCHANMODE: 347 drvdata->cmbchan_mode = !!val; 348 break; 349 default: 350 return -EINVAL; 351 } 352 353 return size; 354 } 355 356 static ssize_t global_flush_req_show(struct device *dev, 357 struct device_attribute *attr, 358 char *buf) 359 { 360 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 361 unsigned long val; 362 363 if (!drvdata->csdev->refcnt) 364 return -EINVAL; 365 366 guard(spinlock)(&drvdata->spinlock); 367 val = readl_relaxed(drvdata->base + TPDA_CR); 368 /* read global_flush_req bit */ 369 val &= TPDA_CR_FLREQ; 370 371 return sysfs_emit(buf, "%lu\n", val); 372 } 373 374 static ssize_t global_flush_req_store(struct device *dev, 375 struct device_attribute *attr, 376 const char *buf, 377 size_t size) 378 { 379 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 380 unsigned long val; 381 382 if (kstrtoul(buf, 0, &val)) 383 return -EINVAL; 384 385 if (!drvdata->csdev->refcnt || !val) 386 return -EINVAL; 387 388 guard(spinlock)(&drvdata->spinlock); 389 val = readl_relaxed(drvdata->base + TPDA_CR); 390 /* set global_flush_req bit */ 391 val |= TPDA_CR_FLREQ; 392 CS_UNLOCK(drvdata->base); 393 writel_relaxed(val, drvdata->base + TPDA_CR); 394 CS_LOCK(drvdata->base); 395 396 return size; 397 } 398 static DEVICE_ATTR_RW(global_flush_req); 399 400 static ssize_t syncr_mode_show(struct device *dev, 401 struct device_attribute *attr, 402 char *buf) 403 { 404 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 405 unsigned long val, syncr_val; 406 407 if (!drvdata->csdev->refcnt) 408 return -EINVAL; 409 410 guard(spinlock)(&drvdata->spinlock); 411 syncr_val = readl_relaxed(drvdata->base + TPDA_SYNCR); 412 val = FIELD_GET(TPDA_SYNCR_MODE_CTRL_MASK, syncr_val); 413 414 return sysfs_emit(buf, "%lu\n", val); 415 } 416 417 static ssize_t syncr_mode_store(struct device *dev, 418 struct device_attribute *attr, 419 const char *buf, 420 size_t size) 421 { 422 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 423 unsigned long val; 424 425 if (kstrtoul(buf, 0, &val)) 426 return -EINVAL; 427 428 guard(spinlock)(&drvdata->spinlock); 429 /* set the mode when first enabling the device */ 430 drvdata->syncr_mode = !!val; 431 432 return size; 433 } 434 static DEVICE_ATTR_RW(syncr_mode); 435 436 static ssize_t syncr_count_show(struct device *dev, 437 struct device_attribute *attr, 438 char *buf) 439 { 440 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 441 unsigned long val; 442 443 if (!drvdata->csdev->refcnt) 444 return -EINVAL; 445 446 guard(spinlock)(&drvdata->spinlock); 447 val = readl_relaxed(drvdata->base + TPDA_SYNCR); 448 val &= TPDA_SYNCR_COUNT_MASK; 449 450 return sysfs_emit(buf, "%lu\n", val); 451 } 452 453 static ssize_t syncr_count_store(struct device *dev, 454 struct device_attribute *attr, 455 const char *buf, 456 size_t size) 457 { 458 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 459 unsigned long val; 460 461 if (kstrtoul(buf, 0, &val)) 462 return -EINVAL; 463 464 if (val > TPDA_SYNCR_COUNT_MASK) 465 return -EINVAL; 466 467 guard(spinlock)(&drvdata->spinlock); 468 drvdata->syncr_count = val; 469 470 return size; 471 } 472 static DEVICE_ATTR_RW(syncr_count); 473 474 static ssize_t port_flush_req_show(struct device *dev, 475 struct device_attribute *attr, 476 char *buf) 477 { 478 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 479 unsigned long val; 480 481 if (!drvdata->csdev->refcnt) 482 return -EINVAL; 483 484 guard(spinlock)(&drvdata->spinlock); 485 val = readl_relaxed(drvdata->base + TPDA_FLUSH_CR); 486 487 return sysfs_emit(buf, "0x%lx\n", val); 488 } 489 490 static ssize_t port_flush_req_store(struct device *dev, 491 struct device_attribute *attr, 492 const char *buf, 493 size_t size) 494 { 495 struct tpda_drvdata *drvdata = dev_get_drvdata(dev->parent); 496 u32 val; 497 498 if (kstrtou32(buf, 0, &val)) 499 return -EINVAL; 500 501 if (!drvdata->csdev->refcnt || !val) 502 return -EINVAL; 503 504 guard(spinlock)(&drvdata->spinlock); 505 CS_UNLOCK(drvdata->base); 506 writel_relaxed(val, drvdata->base + TPDA_FLUSH_CR); 507 CS_LOCK(drvdata->base); 508 509 return size; 510 } 511 static DEVICE_ATTR_RW(port_flush_req); 512 513 static struct attribute *tpda_attrs[] = { 514 &dev_attr_global_flush_req.attr, 515 &dev_attr_syncr_mode.attr, 516 &dev_attr_syncr_count.attr, 517 &dev_attr_port_flush_req.attr, 518 tpda_trig_sysfs_rw(freq_ts_enable, FREQTS), 519 tpda_trig_sysfs_rw(trig_freq_enable, FRIE), 520 tpda_trig_sysfs_rw(trig_flag_ts_enable, FLRIE), 521 tpda_trig_sysfs_rw(trig_async_enable, SRIE), 522 tpda_trig_sysfs_rw(cmbchan_mode, CMBCHANMODE), 523 NULL, 524 }; 525 526 static struct attribute_group tpda_attr_grp = { 527 .attrs = tpda_attrs, 528 }; 529 530 static const struct attribute_group *tpda_attr_grps[] = { 531 &tpda_attr_grp, 532 NULL, 533 }; 534 535 static int tpda_init_default_data(struct tpda_drvdata *drvdata) 536 { 537 int atid; 538 /* 539 * TPDA must has a unique atid. This atid can uniquely 540 * identify the TPDM trace source connected to the TPDA. 541 * The TPDMs which are connected to same TPDA share the 542 * same trace-id. When TPDA does packetization, different 543 * port will have unique channel number for decoding. 544 */ 545 atid = coresight_trace_id_get_system_id(); 546 if (atid < 0) 547 return atid; 548 549 drvdata->atid = atid; 550 drvdata->freq_ts = true; 551 return 0; 552 } 553 554 static int tpda_probe(struct amba_device *adev, const struct amba_id *id) 555 { 556 int ret; 557 struct device *dev = &adev->dev; 558 struct coresight_platform_data *pdata; 559 struct tpda_drvdata *drvdata; 560 struct coresight_desc desc = { 0 }; 561 void __iomem *base; 562 563 pdata = coresight_get_platform_data(dev); 564 if (IS_ERR(pdata)) 565 return PTR_ERR(pdata); 566 adev->dev.platform_data = pdata; 567 568 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); 569 if (!drvdata) 570 return -ENOMEM; 571 572 drvdata->dev = &adev->dev; 573 dev_set_drvdata(dev, drvdata); 574 575 base = devm_ioremap_resource(dev, &adev->res); 576 if (IS_ERR(base)) 577 return PTR_ERR(base); 578 drvdata->base = base; 579 580 spin_lock_init(&drvdata->spinlock); 581 582 ret = tpda_init_default_data(drvdata); 583 if (ret) 584 return ret; 585 586 desc.name = coresight_alloc_device_name("tpda", dev); 587 if (!desc.name) 588 return -ENOMEM; 589 desc.type = CORESIGHT_DEV_TYPE_LINK; 590 desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG; 591 desc.ops = &tpda_cs_ops; 592 desc.pdata = adev->dev.platform_data; 593 desc.dev = &adev->dev; 594 desc.groups = tpda_attr_grps; 595 desc.access = CSDEV_ACCESS_IOMEM(base); 596 drvdata->csdev = coresight_register(&desc); 597 if (IS_ERR(drvdata->csdev)) 598 return PTR_ERR(drvdata->csdev); 599 600 pm_runtime_put(&adev->dev); 601 602 dev_dbg(drvdata->dev, "TPDA initialized\n"); 603 return 0; 604 } 605 606 static void tpda_remove(struct amba_device *adev) 607 { 608 struct tpda_drvdata *drvdata = dev_get_drvdata(&adev->dev); 609 610 coresight_trace_id_put_system_id(drvdata->atid); 611 coresight_unregister(drvdata->csdev); 612 } 613 614 /* 615 * Different TPDA has different periph id. 616 * The difference is 0-7 bits' value. So ignore 0-7 bits. 617 */ 618 static const struct amba_id tpda_ids[] = { 619 { 620 .id = 0x000f0f00, 621 .mask = 0x000fff00, 622 }, 623 { 0, 0, NULL }, 624 }; 625 626 static struct amba_driver tpda_driver = { 627 .drv = { 628 .name = "coresight-tpda", 629 .suppress_bind_attrs = true, 630 }, 631 .probe = tpda_probe, 632 .remove = tpda_remove, 633 .id_table = tpda_ids, 634 }; 635 636 module_amba_driver(tpda_driver); 637 638 MODULE_LICENSE("GPL"); 639 MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Aggregator driver"); 640