FILE
coresight-tpdm.c
File preview with syntax highlighting.
linux-6.19.14/drivers/hwtracing/coresight/coresight-tpdm.c
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/bitmap.h> 9#include <linux/coresight.h> 10#include <linux/coresight-pmu.h> 11#include <linux/device.h> 12#include <linux/err.h> 13#include <linux/fs.h> 14#include <linux/io.h> 15#include <linux/kernel.h> 16#include <linux/module.h> 17#include <linux/of.h> 18 19#include "coresight-priv.h" 20#include "coresight-tpdm.h" 21 22DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm"); 23 24static bool tpdm_has_dsb_dataset(struct tpdm_drvdata *drvdata) 25{ 26 return (drvdata->datasets & TPDM_PIDR0_DS_DSB); 27} 28 29static bool tpdm_has_cmb_dataset(struct tpdm_drvdata *drvdata) 30{ 31 return (drvdata->datasets & TPDM_PIDR0_DS_CMB); 32} 33 34static bool tpdm_has_mcmb_dataset(struct tpdm_drvdata *drvdata) 35{ 36 return (drvdata->datasets & TPDM_PIDR0_DS_MCMB); 37} 38 39/* Read dataset array member with the index number */ 40static ssize_t tpdm_simple_dataset_show(struct device *dev, 41 struct device_attribute *attr, 42 char *buf) 43{ 44 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 45 struct tpdm_dataset_attribute *tpdm_attr = 46 container_of(attr, struct tpdm_dataset_attribute, attr); 47 48 switch (tpdm_attr->mem) { 49 case DSB_EDGE_CTRL: 50 if (tpdm_attr->idx >= TPDM_DSB_MAX_EDCR) 51 return -EINVAL; 52 return sysfs_emit(buf, "0x%x\n", 53 drvdata->dsb->edge_ctrl[tpdm_attr->idx]); 54 case DSB_EDGE_CTRL_MASK: 55 if (tpdm_attr->idx >= TPDM_DSB_MAX_EDCMR) 56 return -EINVAL; 57 return sysfs_emit(buf, "0x%x\n", 58 drvdata->dsb->edge_ctrl_mask[tpdm_attr->idx]); 59 case DSB_TRIG_PATT: 60 if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT) 61 return -EINVAL; 62 return sysfs_emit(buf, "0x%x\n", 63 drvdata->dsb->trig_patt[tpdm_attr->idx]); 64 case DSB_TRIG_PATT_MASK: 65 if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT) 66 return -EINVAL; 67 return sysfs_emit(buf, "0x%x\n", 68 drvdata->dsb->trig_patt_mask[tpdm_attr->idx]); 69 case DSB_PATT: 70 if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT) 71 return -EINVAL; 72 return sysfs_emit(buf, "0x%x\n", 73 drvdata->dsb->patt_val[tpdm_attr->idx]); 74 case DSB_PATT_MASK: 75 if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT) 76 return -EINVAL; 77 return sysfs_emit(buf, "0x%x\n", 78 drvdata->dsb->patt_mask[tpdm_attr->idx]); 79 case DSB_MSR: 80 if (tpdm_attr->idx >= drvdata->dsb_msr_num) 81 return -EINVAL; 82 return sysfs_emit(buf, "0x%x\n", 83 drvdata->dsb->msr[tpdm_attr->idx]); 84 case CMB_TRIG_PATT: 85 if (tpdm_attr->idx >= TPDM_CMB_MAX_PATT) 86 return -EINVAL; 87 return sysfs_emit(buf, "0x%x\n", 88 drvdata->cmb->trig_patt[tpdm_attr->idx]); 89 case CMB_TRIG_PATT_MASK: 90 if (tpdm_attr->idx >= TPDM_CMB_MAX_PATT) 91 return -EINVAL; 92 return sysfs_emit(buf, "0x%x\n", 93 drvdata->cmb->trig_patt_mask[tpdm_attr->idx]); 94 case CMB_PATT: 95 if (tpdm_attr->idx >= TPDM_CMB_MAX_PATT) 96 return -EINVAL; 97 return sysfs_emit(buf, "0x%x\n", 98 drvdata->cmb->patt_val[tpdm_attr->idx]); 99 case CMB_PATT_MASK: 100 if (tpdm_attr->idx >= TPDM_CMB_MAX_PATT) 101 return -EINVAL; 102 return sysfs_emit(buf, "0x%x\n", 103 drvdata->cmb->patt_mask[tpdm_attr->idx]); 104 case CMB_MSR: 105 if (tpdm_attr->idx >= drvdata->cmb_msr_num) 106 return -EINVAL; 107 return sysfs_emit(buf, "0x%x\n", 108 drvdata->cmb->msr[tpdm_attr->idx]); 109 } 110 return -EINVAL; 111} 112 113/* Write dataset array member with the index number */ 114static ssize_t tpdm_simple_dataset_store(struct device *dev, 115 struct device_attribute *attr, 116 const char *buf, 117 size_t size) 118{ 119 unsigned long val; 120 ssize_t ret = -EINVAL; 121 122 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 123 struct tpdm_dataset_attribute *tpdm_attr = 124 container_of(attr, struct tpdm_dataset_attribute, attr); 125 126 if (kstrtoul(buf, 0, &val)) 127 return ret; 128 129 guard(spinlock)(&drvdata->spinlock); 130 switch (tpdm_attr->mem) { 131 case DSB_TRIG_PATT: 132 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT) { 133 drvdata->dsb->trig_patt[tpdm_attr->idx] = val; 134 ret = size; 135 } 136 break; 137 case DSB_TRIG_PATT_MASK: 138 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT) { 139 drvdata->dsb->trig_patt_mask[tpdm_attr->idx] = val; 140 ret = size; 141 } 142 break; 143 case DSB_PATT: 144 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT) { 145 drvdata->dsb->patt_val[tpdm_attr->idx] = val; 146 ret = size; 147 } 148 break; 149 case DSB_PATT_MASK: 150 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT) { 151 drvdata->dsb->patt_mask[tpdm_attr->idx] = val; 152 ret = size; 153 } 154 break; 155 case DSB_MSR: 156 if (tpdm_attr->idx < drvdata->dsb_msr_num) { 157 drvdata->dsb->msr[tpdm_attr->idx] = val; 158 ret = size; 159 } 160 break; 161 case CMB_TRIG_PATT: 162 if (tpdm_attr->idx < TPDM_CMB_MAX_PATT) { 163 drvdata->cmb->trig_patt[tpdm_attr->idx] = val; 164 ret = size; 165 } 166 break; 167 case CMB_TRIG_PATT_MASK: 168 if (tpdm_attr->idx < TPDM_CMB_MAX_PATT) { 169 drvdata->cmb->trig_patt_mask[tpdm_attr->idx] = val; 170 ret = size; 171 } 172 break; 173 case CMB_PATT: 174 if (tpdm_attr->idx < TPDM_CMB_MAX_PATT) { 175 drvdata->cmb->patt_val[tpdm_attr->idx] = val; 176 ret = size; 177 } 178 break; 179 case CMB_PATT_MASK: 180 if (tpdm_attr->idx < TPDM_CMB_MAX_PATT) { 181 drvdata->cmb->patt_mask[tpdm_attr->idx] = val; 182 ret = size; 183 } 184 break; 185 case CMB_MSR: 186 if (tpdm_attr->idx < drvdata->cmb_msr_num) { 187 drvdata->cmb->msr[tpdm_attr->idx] = val; 188 ret = size; 189 } 190 break; 191 default: 192 break; 193 } 194 195 return ret; 196} 197 198static umode_t tpdm_dsb_is_visible(struct kobject *kobj, 199 struct attribute *attr, int n) 200{ 201 struct device *dev = kobj_to_dev(kobj); 202 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 203 204 if (drvdata && tpdm_has_dsb_dataset(drvdata)) 205 return attr->mode; 206 207 return 0; 208} 209 210static umode_t tpdm_cmb_is_visible(struct kobject *kobj, 211 struct attribute *attr, int n) 212{ 213 struct device *dev = kobj_to_dev(kobj); 214 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 215 216 if (drvdata && drvdata->cmb) 217 return attr->mode; 218 219 return 0; 220} 221 222static umode_t tpdm_dsb_msr_is_visible(struct kobject *kobj, 223 struct attribute *attr, int n) 224{ 225 struct device *dev = kobj_to_dev(kobj); 226 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 227 struct device_attribute *dev_attr = 228 container_of(attr, struct device_attribute, attr); 229 struct tpdm_dataset_attribute *tpdm_attr = 230 container_of(dev_attr, struct tpdm_dataset_attribute, attr); 231 232 if (tpdm_attr->idx < drvdata->dsb_msr_num) 233 return attr->mode; 234 235 return 0; 236} 237 238static umode_t tpdm_cmb_msr_is_visible(struct kobject *kobj, 239 struct attribute *attr, int n) 240{ 241 struct device *dev = kobj_to_dev(kobj); 242 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 243 244 struct device_attribute *dev_attr = 245 container_of(attr, struct device_attribute, attr); 246 struct tpdm_dataset_attribute *tpdm_attr = 247 container_of(dev_attr, struct tpdm_dataset_attribute, attr); 248 249 if (tpdm_attr->idx < drvdata->cmb_msr_num) 250 return attr->mode; 251 252 return 0; 253} 254 255static umode_t tpdm_mcmb_is_visible(struct kobject *kobj, 256 struct attribute *attr, int n) 257{ 258 struct device *dev = kobj_to_dev(kobj); 259 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 260 261 if (drvdata && tpdm_has_mcmb_dataset(drvdata)) 262 return attr->mode; 263 264 return 0; 265} 266 267static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) 268{ 269 if (tpdm_has_dsb_dataset(drvdata)) { 270 memset(drvdata->dsb, 0, sizeof(struct dsb_dataset)); 271 272 drvdata->dsb->trig_ts = true; 273 drvdata->dsb->trig_type = false; 274 } 275 276 if (drvdata->cmb) 277 memset(drvdata->cmb, 0, sizeof(struct cmb_dataset)); 278} 279 280static void set_dsb_mode(struct tpdm_drvdata *drvdata, u32 *val) 281{ 282 u32 mode; 283 284 /* Set the test accurate mode */ 285 mode = TPDM_DSB_MODE_TEST(drvdata->dsb->mode); 286 *val &= ~TPDM_DSB_CR_TEST_MODE; 287 *val |= FIELD_PREP(TPDM_DSB_CR_TEST_MODE, mode); 288 289 /* Set the byte lane for high-performance mode */ 290 mode = TPDM_DSB_MODE_HPBYTESEL(drvdata->dsb->mode); 291 *val &= ~TPDM_DSB_CR_HPSEL; 292 *val |= FIELD_PREP(TPDM_DSB_CR_HPSEL, mode); 293 294 /* Set the performance mode */ 295 if (drvdata->dsb->mode & TPDM_DSB_MODE_PERF) 296 *val |= TPDM_DSB_CR_MODE; 297 else 298 *val &= ~TPDM_DSB_CR_MODE; 299} 300 301static void set_dsb_tier(struct tpdm_drvdata *drvdata) 302{ 303 u32 val; 304 305 val = readl_relaxed(drvdata->base + TPDM_DSB_TIER); 306 307 /* Clear all relevant fields */ 308 val &= ~(TPDM_DSB_TIER_PATT_TSENAB | TPDM_DSB_TIER_PATT_TYPE | 309 TPDM_DSB_TIER_XTRIG_TSENAB); 310 311 /* Set pattern timestamp type and enablement */ 312 if (drvdata->dsb->patt_ts) { 313 val |= TPDM_DSB_TIER_PATT_TSENAB; 314 if (drvdata->dsb->patt_type) 315 val |= TPDM_DSB_TIER_PATT_TYPE; 316 else 317 val &= ~TPDM_DSB_TIER_PATT_TYPE; 318 } else { 319 val &= ~TPDM_DSB_TIER_PATT_TSENAB; 320 } 321 322 /* Set trigger timestamp */ 323 if (drvdata->dsb->trig_ts) 324 val |= TPDM_DSB_TIER_XTRIG_TSENAB; 325 else 326 val &= ~TPDM_DSB_TIER_XTRIG_TSENAB; 327 328 writel_relaxed(val, drvdata->base + TPDM_DSB_TIER); 329} 330 331static void set_dsb_msr(struct tpdm_drvdata *drvdata) 332{ 333 int i; 334 335 for (i = 0; i < drvdata->dsb_msr_num; i++) 336 writel_relaxed(drvdata->dsb->msr[i], 337 drvdata->base + TPDM_DSB_MSR(i)); 338} 339 340static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) 341{ 342 u32 val, i; 343 344 if (!tpdm_has_dsb_dataset(drvdata)) 345 return; 346 347 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++) 348 writel_relaxed(drvdata->dsb->edge_ctrl[i], 349 drvdata->base + TPDM_DSB_EDCR(i)); 350 for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++) 351 writel_relaxed(drvdata->dsb->edge_ctrl_mask[i], 352 drvdata->base + TPDM_DSB_EDCMR(i)); 353 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) { 354 writel_relaxed(drvdata->dsb->patt_val[i], 355 drvdata->base + TPDM_DSB_TPR(i)); 356 writel_relaxed(drvdata->dsb->patt_mask[i], 357 drvdata->base + TPDM_DSB_TPMR(i)); 358 writel_relaxed(drvdata->dsb->trig_patt[i], 359 drvdata->base + TPDM_DSB_XPR(i)); 360 writel_relaxed(drvdata->dsb->trig_patt_mask[i], 361 drvdata->base + TPDM_DSB_XPMR(i)); 362 } 363 364 set_dsb_tier(drvdata); 365 set_dsb_msr(drvdata); 366 367 val = readl_relaxed(drvdata->base + TPDM_DSB_CR); 368 /* Set the mode of DSB dataset */ 369 set_dsb_mode(drvdata, &val); 370 /* Set trigger type */ 371 if (drvdata->dsb->trig_type) 372 val |= TPDM_DSB_CR_TRIG_TYPE; 373 else 374 val &= ~TPDM_DSB_CR_TRIG_TYPE; 375 /* Set the enable bit of DSB control register to 1 */ 376 val |= TPDM_DSB_CR_ENA; 377 writel_relaxed(val, drvdata->base + TPDM_DSB_CR); 378} 379 380static void set_cmb_tier(struct tpdm_drvdata *drvdata) 381{ 382 u32 val; 383 384 val = readl_relaxed(drvdata->base + TPDM_CMB_TIER); 385 386 /* Clear all relevant fields */ 387 val &= ~(TPDM_CMB_TIER_PATT_TSENAB | TPDM_CMB_TIER_TS_ALL | 388 TPDM_CMB_TIER_XTRIG_TSENAB); 389 390 /* Set pattern timestamp type and enablement */ 391 if (drvdata->cmb->patt_ts) 392 val |= TPDM_CMB_TIER_PATT_TSENAB; 393 394 /* Set trigger timestamp */ 395 if (drvdata->cmb->trig_ts) 396 val |= TPDM_CMB_TIER_XTRIG_TSENAB; 397 398 /* Set all timestamp enablement*/ 399 if (drvdata->cmb->ts_all) 400 val |= TPDM_CMB_TIER_TS_ALL; 401 402 writel_relaxed(val, drvdata->base + TPDM_CMB_TIER); 403} 404 405static void set_cmb_msr(struct tpdm_drvdata *drvdata) 406{ 407 int i; 408 409 for (i = 0; i < drvdata->cmb_msr_num; i++) 410 writel_relaxed(drvdata->cmb->msr[i], 411 drvdata->base + TPDM_CMB_MSR(i)); 412} 413 414static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata) 415{ 416 u32 val, i; 417 418 if (!drvdata->cmb) 419 return; 420 421 /* Configure pattern registers */ 422 for (i = 0; i < TPDM_CMB_MAX_PATT; i++) { 423 writel_relaxed(drvdata->cmb->patt_val[i], 424 drvdata->base + TPDM_CMB_TPR(i)); 425 writel_relaxed(drvdata->cmb->patt_mask[i], 426 drvdata->base + TPDM_CMB_TPMR(i)); 427 writel_relaxed(drvdata->cmb->trig_patt[i], 428 drvdata->base + TPDM_CMB_XPR(i)); 429 writel_relaxed(drvdata->cmb->trig_patt_mask[i], 430 drvdata->base + TPDM_CMB_XPMR(i)); 431 } 432 433 set_cmb_tier(drvdata); 434 set_cmb_msr(drvdata); 435 436 val = readl_relaxed(drvdata->base + TPDM_CMB_CR); 437 /* 438 * Set to 0 for continuous CMB collection mode, 439 * 1 for trace-on-change CMB collection mode. 440 */ 441 if (drvdata->cmb->trace_mode) 442 val |= TPDM_CMB_CR_MODE; 443 else 444 val &= ~TPDM_CMB_CR_MODE; 445 446 if (tpdm_has_mcmb_dataset(drvdata)) { 447 val &= ~TPDM_CMB_CR_XTRIG_LNSEL; 448 /* Set the lane participates in the output pattern */ 449 val |= FIELD_PREP(TPDM_CMB_CR_XTRIG_LNSEL, 450 drvdata->cmb->mcmb.trig_lane); 451 452 /* Set the enablement of the lane */ 453 val &= ~TPDM_CMB_CR_E_LN; 454 val |= FIELD_PREP(TPDM_CMB_CR_E_LN, 455 drvdata->cmb->mcmb.lane_select); 456 } 457 458 /* Set the enable bit of CMB control register to 1 */ 459 val |= TPDM_CMB_CR_ENA; 460 writel_relaxed(val, drvdata->base + TPDM_CMB_CR); 461} 462 463/* 464 * TPDM enable operations 465 * The TPDM or Monitor serves as data collection component for various 466 * dataset types. It covers Basic Counts(BC), Tenure Counts(TC), 467 * Continuous Multi-Bit(CMB), Multi-lane CMB(MCMB) and Discrete Single 468 * Bit(DSB). This function will initialize the configuration according 469 * to the dataset type supported by the TPDM. 470 */ 471static void __tpdm_enable(struct tpdm_drvdata *drvdata) 472{ 473 if (coresight_is_static_tpdm(drvdata->csdev)) 474 return; 475 476 CS_UNLOCK(drvdata->base); 477 478 tpdm_enable_dsb(drvdata); 479 tpdm_enable_cmb(drvdata); 480 481 CS_LOCK(drvdata->base); 482} 483 484static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event, 485 enum cs_mode mode, 486 __maybe_unused struct coresight_path *path) 487{ 488 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 489 490 spin_lock(&drvdata->spinlock); 491 if (drvdata->enable) { 492 spin_unlock(&drvdata->spinlock); 493 return -EBUSY; 494 } 495 496 if (!coresight_take_mode(csdev, mode)) { 497 spin_unlock(&drvdata->spinlock); 498 return -EBUSY; 499 } 500 501 __tpdm_enable(drvdata); 502 drvdata->enable = true; 503 spin_unlock(&drvdata->spinlock); 504 505 dev_dbg(drvdata->dev, "TPDM tracing enabled\n"); 506 return 0; 507} 508 509static void tpdm_disable_dsb(struct tpdm_drvdata *drvdata) 510{ 511 u32 val; 512 513 if (!tpdm_has_dsb_dataset(drvdata)) 514 return; 515 516 /* Set the enable bit of DSB control register to 0 */ 517 val = readl_relaxed(drvdata->base + TPDM_DSB_CR); 518 val &= ~TPDM_DSB_CR_ENA; 519 writel_relaxed(val, drvdata->base + TPDM_DSB_CR); 520} 521 522static void tpdm_disable_cmb(struct tpdm_drvdata *drvdata) 523{ 524 u32 val; 525 526 if (!drvdata->cmb) 527 return; 528 529 val = readl_relaxed(drvdata->base + TPDM_CMB_CR); 530 /* Set the enable bit of CMB control register to 0 */ 531 val &= ~TPDM_CMB_CR_ENA; 532 writel_relaxed(val, drvdata->base + TPDM_CMB_CR); 533} 534 535/* TPDM disable operations */ 536static void __tpdm_disable(struct tpdm_drvdata *drvdata) 537{ 538 if (coresight_is_static_tpdm(drvdata->csdev)) 539 return; 540 541 CS_UNLOCK(drvdata->base); 542 543 tpdm_disable_dsb(drvdata); 544 tpdm_disable_cmb(drvdata); 545 546 CS_LOCK(drvdata->base); 547} 548 549static void tpdm_disable(struct coresight_device *csdev, 550 struct perf_event *event) 551{ 552 struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 553 554 spin_lock(&drvdata->spinlock); 555 if (!drvdata->enable) { 556 spin_unlock(&drvdata->spinlock); 557 return; 558 } 559 560 __tpdm_disable(drvdata); 561 coresight_set_mode(csdev, CS_MODE_DISABLED); 562 drvdata->enable = false; 563 spin_unlock(&drvdata->spinlock); 564 565 dev_dbg(drvdata->dev, "TPDM tracing disabled\n"); 566} 567 568static const struct coresight_ops_source tpdm_source_ops = { 569 .enable = tpdm_enable, 570 .disable = tpdm_disable, 571}; 572 573static const struct coresight_ops tpdm_cs_ops = { 574 .source_ops = &tpdm_source_ops, 575}; 576 577static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) 578{ 579 u32 pidr; 580 581 /* Get the datasets present on the TPDM. */ 582 pidr = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0); 583 drvdata->datasets |= pidr & GENMASK(TPDM_DATASETS - 1, 0); 584 585 if (tpdm_has_dsb_dataset(drvdata) && (!drvdata->dsb)) { 586 drvdata->dsb = devm_kzalloc(drvdata->dev, 587 sizeof(*drvdata->dsb), GFP_KERNEL); 588 if (!drvdata->dsb) 589 return -ENOMEM; 590 } 591 if ((tpdm_has_cmb_dataset(drvdata) || tpdm_has_mcmb_dataset(drvdata)) 592 && (!drvdata->cmb)) { 593 drvdata->cmb = devm_kzalloc(drvdata->dev, 594 sizeof(*drvdata->cmb), GFP_KERNEL); 595 if (!drvdata->cmb) 596 return -ENOMEM; 597 } 598 599 tpdm_reset_datasets(drvdata); 600 601 return 0; 602} 603 604static int static_tpdm_datasets_setup(struct tpdm_drvdata *drvdata, struct device *dev) 605{ 606 /* setup datasets for static TPDM */ 607 if (fwnode_property_present(dev->fwnode, "qcom,dsb-element-bits") && 608 (!drvdata->dsb)) { 609 drvdata->dsb = devm_kzalloc(drvdata->dev, 610 sizeof(*drvdata->dsb), GFP_KERNEL); 611 612 if (!drvdata->dsb) 613 return -ENOMEM; 614 } 615 616 if (fwnode_property_present(dev->fwnode, "qcom,cmb-element-bits") && 617 (!drvdata->cmb)) { 618 drvdata->cmb = devm_kzalloc(drvdata->dev, 619 sizeof(*drvdata->cmb), GFP_KERNEL); 620 621 if (!drvdata->cmb) 622 return -ENOMEM; 623 } 624 625 return 0; 626} 627 628static ssize_t reset_dataset_store(struct device *dev, 629 struct device_attribute *attr, 630 const char *buf, 631 size_t size) 632{ 633 int ret = 0; 634 unsigned long val; 635 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 636 637 ret = kstrtoul(buf, 0, &val); 638 if (ret || val != 1) 639 return -EINVAL; 640 641 spin_lock(&drvdata->spinlock); 642 tpdm_reset_datasets(drvdata); 643 spin_unlock(&drvdata->spinlock); 644 645 return size; 646} 647static DEVICE_ATTR_WO(reset_dataset); 648 649/* 650 * value 1: 64 bits test data 651 * value 2: 32 bits test data 652 */ 653static ssize_t integration_test_store(struct device *dev, 654 struct device_attribute *attr, 655 const char *buf, 656 size_t size) 657{ 658 int i, ret = 0; 659 unsigned long val; 660 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 661 662 ret = kstrtoul(buf, 10, &val); 663 if (ret) 664 return ret; 665 666 if (val != 1 && val != 2) 667 return -EINVAL; 668 669 if (!drvdata->enable) 670 return -EINVAL; 671 672 if (val == 1) 673 val = ATBCNTRL_VAL_64; 674 else 675 val = ATBCNTRL_VAL_32; 676 CS_UNLOCK(drvdata->base); 677 writel_relaxed(0x1, drvdata->base + TPDM_ITCNTRL); 678 679 for (i = 0; i < INTEGRATION_TEST_CYCLE; i++) 680 writel_relaxed(val, drvdata->base + TPDM_ITATBCNTRL); 681 682 writel_relaxed(0, drvdata->base + TPDM_ITCNTRL); 683 CS_LOCK(drvdata->base); 684 return size; 685} 686static DEVICE_ATTR_WO(integration_test); 687 688static struct attribute *tpdm_attrs[] = { 689 &dev_attr_reset_dataset.attr, 690 &dev_attr_integration_test.attr, 691 NULL, 692}; 693 694static struct attribute_group tpdm_attr_grp = { 695 .attrs = tpdm_attrs, 696}; 697 698static ssize_t dsb_mode_show(struct device *dev, 699 struct device_attribute *attr, 700 char *buf) 701{ 702 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 703 704 return sysfs_emit(buf, "%x\n", drvdata->dsb->mode); 705} 706 707static ssize_t dsb_mode_store(struct device *dev, 708 struct device_attribute *attr, 709 const char *buf, 710 size_t size) 711{ 712 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 713 unsigned long val; 714 715 if ((kstrtoul(buf, 0, &val)) || (val & ~TPDM_DSB_MODE_MASK)) 716 return -EINVAL; 717 718 spin_lock(&drvdata->spinlock); 719 drvdata->dsb->mode = val & TPDM_DSB_MODE_MASK; 720 spin_unlock(&drvdata->spinlock); 721 return size; 722} 723static DEVICE_ATTR_RW(dsb_mode); 724 725static ssize_t ctrl_idx_show(struct device *dev, 726 struct device_attribute *attr, 727 char *buf) 728{ 729 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 730 731 return sysfs_emit(buf, "%u\n", 732 (unsigned int)drvdata->dsb->edge_ctrl_idx); 733} 734 735/* 736 * The EDCR registers can include up to 16 32-bit registers, and each 737 * one can be configured to control up to 16 edge detections(2 bits 738 * control one edge detection). So a total 256 edge detections can be 739 * configured. This function provides a way to set the index number of 740 * the edge detection which needs to be configured. 741 */ 742static ssize_t ctrl_idx_store(struct device *dev, 743 struct device_attribute *attr, 744 const char *buf, 745 size_t size) 746{ 747 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 748 unsigned long val; 749 750 if ((kstrtoul(buf, 0, &val)) || (val >= TPDM_DSB_MAX_LINES)) 751 return -EINVAL; 752 753 spin_lock(&drvdata->spinlock); 754 drvdata->dsb->edge_ctrl_idx = val; 755 spin_unlock(&drvdata->spinlock); 756 757 return size; 758} 759static DEVICE_ATTR_RW(ctrl_idx); 760 761/* 762 * This function is used to control the edge detection according 763 * to the index number that has been set. 764 * "edge_ctrl" should be one of the following values. 765 * 0 - Rising edge detection 766 * 1 - Falling edge detection 767 * 2 - Rising and falling edge detection (toggle detection) 768 */ 769static ssize_t ctrl_val_store(struct device *dev, 770 struct device_attribute *attr, 771 const char *buf, 772 size_t size) 773{ 774 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 775 unsigned long val, edge_ctrl; 776 int reg; 777 778 if ((kstrtoul(buf, 0, &edge_ctrl)) || (edge_ctrl > 0x2)) 779 return -EINVAL; 780 781 spin_lock(&drvdata->spinlock); 782 /* 783 * There are 2 bit per DSB Edge Control line. 784 * Thus we have 16 lines in a 32bit word. 785 */ 786 reg = EDCR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx); 787 val = drvdata->dsb->edge_ctrl[reg]; 788 val &= ~EDCR_TO_WORD_MASK(drvdata->dsb->edge_ctrl_idx); 789 val |= EDCR_TO_WORD_VAL(edge_ctrl, drvdata->dsb->edge_ctrl_idx); 790 drvdata->dsb->edge_ctrl[reg] = val; 791 spin_unlock(&drvdata->spinlock); 792 793 return size; 794} 795static DEVICE_ATTR_WO(ctrl_val); 796 797static ssize_t ctrl_mask_store(struct device *dev, 798 struct device_attribute *attr, 799 const char *buf, 800 size_t size) 801{ 802 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 803 unsigned long val; 804 u32 set; 805 int reg; 806 807 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) 808 return -EINVAL; 809 810 spin_lock(&drvdata->spinlock); 811 /* 812 * There is 1 bit per DSB Edge Control Mark line. 813 * Thus we have 32 lines in a 32bit word. 814 */ 815 reg = EDCMR_TO_WORD_IDX(drvdata->dsb->edge_ctrl_idx); 816 set = drvdata->dsb->edge_ctrl_mask[reg]; 817 if (val) 818 set |= BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx)); 819 else 820 set &= ~BIT(EDCMR_TO_WORD_SHIFT(drvdata->dsb->edge_ctrl_idx)); 821 drvdata->dsb->edge_ctrl_mask[reg] = set; 822 spin_unlock(&drvdata->spinlock); 823 824 return size; 825} 826static DEVICE_ATTR_WO(ctrl_mask); 827 828static ssize_t enable_ts_show(struct device *dev, 829 struct device_attribute *attr, 830 char *buf) 831{ 832 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 833 struct tpdm_dataset_attribute *tpdm_attr = 834 container_of(attr, struct tpdm_dataset_attribute, attr); 835 ssize_t size = -EINVAL; 836 837 if (tpdm_attr->mem == DSB_PATT) 838 size = sysfs_emit(buf, "%u\n", 839 (unsigned int)drvdata->dsb->patt_ts); 840 else if (tpdm_attr->mem == CMB_PATT) 841 size = sysfs_emit(buf, "%u\n", 842 (unsigned int)drvdata->cmb->patt_ts); 843 844 return size; 845} 846 847/* 848 * value 1: Enable/Disable DSB pattern timestamp 849 */ 850static ssize_t enable_ts_store(struct device *dev, 851 struct device_attribute *attr, 852 const char *buf, 853 size_t size) 854{ 855 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 856 struct tpdm_dataset_attribute *tpdm_attr = 857 container_of(attr, struct tpdm_dataset_attribute, attr); 858 unsigned long val; 859 860 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) 861 return -EINVAL; 862 863 guard(spinlock)(&drvdata->spinlock); 864 if (tpdm_attr->mem == DSB_PATT) 865 drvdata->dsb->patt_ts = !!val; 866 else if (tpdm_attr->mem == CMB_PATT) 867 drvdata->cmb->patt_ts = !!val; 868 else 869 return -EINVAL; 870 871 return size; 872} 873 874static ssize_t set_type_show(struct device *dev, 875 struct device_attribute *attr, 876 char *buf) 877{ 878 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 879 880 return sysfs_emit(buf, "%u\n", 881 (unsigned int)drvdata->dsb->patt_type); 882} 883 884/* 885 * value 1: Set DSB pattern type 886 */ 887static ssize_t set_type_store(struct device *dev, 888 struct device_attribute *attr, 889 const char *buf, size_t size) 890{ 891 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 892 unsigned long val; 893 894 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) 895 return -EINVAL; 896 897 spin_lock(&drvdata->spinlock); 898 drvdata->dsb->patt_type = val; 899 spin_unlock(&drvdata->spinlock); 900 return size; 901} 902static DEVICE_ATTR_RW(set_type); 903 904static ssize_t dsb_trig_type_show(struct device *dev, 905 struct device_attribute *attr, char *buf) 906{ 907 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 908 909 return sysfs_emit(buf, "%u\n", 910 (unsigned int)drvdata->dsb->trig_type); 911} 912 913/* 914 * Trigger type (boolean): 915 * false - Disable trigger type. 916 * true - Enable trigger type. 917 */ 918static ssize_t dsb_trig_type_store(struct device *dev, 919 struct device_attribute *attr, 920 const char *buf, 921 size_t size) 922{ 923 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 924 unsigned long val; 925 926 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) 927 return -EINVAL; 928 929 spin_lock(&drvdata->spinlock); 930 if (val) 931 drvdata->dsb->trig_type = true; 932 else 933 drvdata->dsb->trig_type = false; 934 spin_unlock(&drvdata->spinlock); 935 return size; 936} 937static DEVICE_ATTR_RW(dsb_trig_type); 938 939static ssize_t dsb_trig_ts_show(struct device *dev, 940 struct device_attribute *attr, 941 char *buf) 942{ 943 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 944 945 return sysfs_emit(buf, "%u\n", 946 (unsigned int)drvdata->dsb->trig_ts); 947} 948 949/* 950 * Trigger timestamp (boolean): 951 * false - Disable trigger timestamp. 952 * true - Enable trigger timestamp. 953 */ 954static ssize_t dsb_trig_ts_store(struct device *dev, 955 struct device_attribute *attr, 956 const char *buf, 957 size_t size) 958{ 959 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 960 unsigned long val; 961 962 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) 963 return -EINVAL; 964 965 spin_lock(&drvdata->spinlock); 966 if (val) 967 drvdata->dsb->trig_ts = true; 968 else 969 drvdata->dsb->trig_ts = false; 970 spin_unlock(&drvdata->spinlock); 971 return size; 972} 973static DEVICE_ATTR_RW(dsb_trig_ts); 974 975static ssize_t cmb_mode_show(struct device *dev, 976 struct device_attribute *attr, 977 char *buf) 978{ 979 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 980 981 return sysfs_emit(buf, "%x\n", drvdata->cmb->trace_mode); 982 983} 984 985static ssize_t cmb_mode_store(struct device *dev, 986 struct device_attribute *attr, 987 const char *buf, 988 size_t size) 989{ 990 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 991 unsigned long trace_mode; 992 993 if (kstrtoul(buf, 0, &trace_mode) || (trace_mode & ~1UL)) 994 return -EINVAL; 995 996 spin_lock(&drvdata->spinlock); 997 drvdata->cmb->trace_mode = trace_mode; 998 spin_unlock(&drvdata->spinlock); 999 return size; 1000} 1001static DEVICE_ATTR_RW(cmb_mode); 1002 1003static ssize_t cmb_ts_all_show(struct device *dev, 1004 struct device_attribute *attr, 1005 char *buf) 1006{ 1007 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 1008 1009 return sysfs_emit(buf, "%u\n", 1010 (unsigned int)drvdata->cmb->ts_all); 1011} 1012 1013static ssize_t cmb_ts_all_store(struct device *dev, 1014 struct device_attribute *attr, 1015 const char *buf, 1016 size_t size) 1017{ 1018 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 1019 unsigned long val; 1020 1021 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) 1022 return -EINVAL; 1023 1024 guard(spinlock)(&drvdata->spinlock); 1025 if (val) 1026 drvdata->cmb->ts_all = true; 1027 else 1028 drvdata->cmb->ts_all = false; 1029 1030 return size; 1031} 1032static DEVICE_ATTR_RW(cmb_ts_all); 1033 1034static ssize_t cmb_trig_ts_show(struct device *dev, 1035 struct device_attribute *attr, 1036 char *buf) 1037{ 1038 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 1039 1040 return sysfs_emit(buf, "%u\n", 1041 (unsigned int)drvdata->cmb->trig_ts); 1042} 1043 1044static ssize_t cmb_trig_ts_store(struct device *dev, 1045 struct device_attribute *attr, 1046 const char *buf, 1047 size_t size) 1048{ 1049 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 1050 unsigned long val; 1051 1052 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL)) 1053 return -EINVAL; 1054 1055 guard(spinlock)(&drvdata->spinlock); 1056 if (val) 1057 drvdata->cmb->trig_ts = true; 1058 else 1059 drvdata->cmb->trig_ts = false; 1060 1061 return size; 1062} 1063static DEVICE_ATTR_RW(cmb_trig_ts); 1064 1065static ssize_t mcmb_trig_lane_show(struct device *dev, 1066 struct device_attribute *attr, 1067 char *buf) 1068{ 1069 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 1070 1071 return sysfs_emit(buf, "%u\n", 1072 (unsigned int)drvdata->cmb->mcmb.trig_lane); 1073} 1074 1075static ssize_t mcmb_trig_lane_store(struct device *dev, 1076 struct device_attribute *attr, 1077 const char *buf, 1078 size_t size) 1079{ 1080 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 1081 unsigned long val; 1082 1083 if ((kstrtoul(buf, 0, &val)) || (val >= TPDM_MCMB_MAX_LANES)) 1084 return -EINVAL; 1085 1086 guard(spinlock)(&drvdata->spinlock); 1087 drvdata->cmb->mcmb.trig_lane = val; 1088 1089 return size; 1090} 1091static DEVICE_ATTR_RW(mcmb_trig_lane); 1092 1093static ssize_t mcmb_lanes_select_show(struct device *dev, 1094 struct device_attribute *attr, 1095 char *buf) 1096{ 1097 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 1098 1099 return sysfs_emit(buf, "%u\n", 1100 (unsigned int)drvdata->cmb->mcmb.lane_select); 1101} 1102 1103static ssize_t mcmb_lanes_select_store(struct device *dev, 1104 struct device_attribute *attr, 1105 const char *buf, 1106 size_t size) 1107{ 1108 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent); 1109 unsigned long val; 1110 1111 if (kstrtoul(buf, 0, &val) || (val & ~TPDM_MCMB_E_LN_MASK)) 1112 return -EINVAL; 1113 1114 guard(spinlock)(&drvdata->spinlock); 1115 drvdata->cmb->mcmb.lane_select = val & TPDM_MCMB_E_LN_MASK; 1116 1117 return size; 1118} 1119static DEVICE_ATTR_RW(mcmb_lanes_select); 1120 1121static struct attribute *tpdm_dsb_edge_attrs[] = { 1122 &dev_attr_ctrl_idx.attr, 1123 &dev_attr_ctrl_val.attr, 1124 &dev_attr_ctrl_mask.attr, 1125 DSB_EDGE_CTRL_ATTR(0), 1126 DSB_EDGE_CTRL_ATTR(1), 1127 DSB_EDGE_CTRL_ATTR(2), 1128 DSB_EDGE_CTRL_ATTR(3), 1129 DSB_EDGE_CTRL_ATTR(4), 1130 DSB_EDGE_CTRL_ATTR(5), 1131 DSB_EDGE_CTRL_ATTR(6), 1132 DSB_EDGE_CTRL_ATTR(7), 1133 DSB_EDGE_CTRL_ATTR(8), 1134 DSB_EDGE_CTRL_ATTR(9), 1135 DSB_EDGE_CTRL_ATTR(10), 1136 DSB_EDGE_CTRL_ATTR(11), 1137 DSB_EDGE_CTRL_ATTR(12), 1138 DSB_EDGE_CTRL_ATTR(13), 1139 DSB_EDGE_CTRL_ATTR(14), 1140 DSB_EDGE_CTRL_ATTR(15), 1141 DSB_EDGE_CTRL_MASK_ATTR(0), 1142 DSB_EDGE_CTRL_MASK_ATTR(1), 1143 DSB_EDGE_CTRL_MASK_ATTR(2), 1144 DSB_EDGE_CTRL_MASK_ATTR(3), 1145 DSB_EDGE_CTRL_MASK_ATTR(4), 1146 DSB_EDGE_CTRL_MASK_ATTR(5), 1147 DSB_EDGE_CTRL_MASK_ATTR(6), 1148 DSB_EDGE_CTRL_MASK_ATTR(7), 1149 NULL, 1150}; 1151 1152static struct attribute *tpdm_dsb_trig_patt_attrs[] = { 1153 DSB_TRIG_PATT_ATTR(0), 1154 DSB_TRIG_PATT_ATTR(1), 1155 DSB_TRIG_PATT_ATTR(2), 1156 DSB_TRIG_PATT_ATTR(3), 1157 DSB_TRIG_PATT_ATTR(4), 1158 DSB_TRIG_PATT_ATTR(5), 1159 DSB_TRIG_PATT_ATTR(6), 1160 DSB_TRIG_PATT_ATTR(7), 1161 DSB_TRIG_PATT_MASK_ATTR(0), 1162 DSB_TRIG_PATT_MASK_ATTR(1), 1163 DSB_TRIG_PATT_MASK_ATTR(2), 1164 DSB_TRIG_PATT_MASK_ATTR(3), 1165 DSB_TRIG_PATT_MASK_ATTR(4), 1166 DSB_TRIG_PATT_MASK_ATTR(5), 1167 DSB_TRIG_PATT_MASK_ATTR(6), 1168 DSB_TRIG_PATT_MASK_ATTR(7), 1169 NULL, 1170}; 1171 1172static struct attribute *tpdm_dsb_patt_attrs[] = { 1173 DSB_PATT_ATTR(0), 1174 DSB_PATT_ATTR(1), 1175 DSB_PATT_ATTR(2), 1176 DSB_PATT_ATTR(3), 1177 DSB_PATT_ATTR(4), 1178 DSB_PATT_ATTR(5), 1179 DSB_PATT_ATTR(6), 1180 DSB_PATT_ATTR(7), 1181 DSB_PATT_MASK_ATTR(0), 1182 DSB_PATT_MASK_ATTR(1), 1183 DSB_PATT_MASK_ATTR(2), 1184 DSB_PATT_MASK_ATTR(3), 1185 DSB_PATT_MASK_ATTR(4), 1186 DSB_PATT_MASK_ATTR(5), 1187 DSB_PATT_MASK_ATTR(6), 1188 DSB_PATT_MASK_ATTR(7), 1189 DSB_PATT_ENABLE_TS, 1190 &dev_attr_set_type.attr, 1191 NULL, 1192}; 1193 1194static struct attribute *tpdm_dsb_msr_attrs[] = { 1195 DSB_MSR_ATTR(0), 1196 DSB_MSR_ATTR(1), 1197 DSB_MSR_ATTR(2), 1198 DSB_MSR_ATTR(3), 1199 DSB_MSR_ATTR(4), 1200 DSB_MSR_ATTR(5), 1201 DSB_MSR_ATTR(6), 1202 DSB_MSR_ATTR(7), 1203 DSB_MSR_ATTR(8), 1204 DSB_MSR_ATTR(9), 1205 DSB_MSR_ATTR(10), 1206 DSB_MSR_ATTR(11), 1207 DSB_MSR_ATTR(12), 1208 DSB_MSR_ATTR(13), 1209 DSB_MSR_ATTR(14), 1210 DSB_MSR_ATTR(15), 1211 DSB_MSR_ATTR(16), 1212 DSB_MSR_ATTR(17), 1213 DSB_MSR_ATTR(18), 1214 DSB_MSR_ATTR(19), 1215 DSB_MSR_ATTR(20), 1216 DSB_MSR_ATTR(21), 1217 DSB_MSR_ATTR(22), 1218 DSB_MSR_ATTR(23), 1219 DSB_MSR_ATTR(24), 1220 DSB_MSR_ATTR(25), 1221 DSB_MSR_ATTR(26), 1222 DSB_MSR_ATTR(27), 1223 DSB_MSR_ATTR(28), 1224 DSB_MSR_ATTR(29), 1225 DSB_MSR_ATTR(30), 1226 DSB_MSR_ATTR(31), 1227 NULL, 1228}; 1229 1230static struct attribute *tpdm_cmb_trig_patt_attrs[] = { 1231 CMB_TRIG_PATT_ATTR(0), 1232 CMB_TRIG_PATT_ATTR(1), 1233 CMB_TRIG_PATT_MASK_ATTR(0), 1234 CMB_TRIG_PATT_MASK_ATTR(1), 1235 NULL, 1236}; 1237 1238static struct attribute *tpdm_cmb_patt_attrs[] = { 1239 CMB_PATT_ATTR(0), 1240 CMB_PATT_ATTR(1), 1241 CMB_PATT_MASK_ATTR(0), 1242 CMB_PATT_MASK_ATTR(1), 1243 CMB_PATT_ENABLE_TS, 1244 NULL, 1245}; 1246 1247static struct attribute *tpdm_cmb_msr_attrs[] = { 1248 CMB_MSR_ATTR(0), 1249 CMB_MSR_ATTR(1), 1250 CMB_MSR_ATTR(2), 1251 CMB_MSR_ATTR(3), 1252 CMB_MSR_ATTR(4), 1253 CMB_MSR_ATTR(5), 1254 CMB_MSR_ATTR(6), 1255 CMB_MSR_ATTR(7), 1256 CMB_MSR_ATTR(8), 1257 CMB_MSR_ATTR(9), 1258 CMB_MSR_ATTR(10), 1259 CMB_MSR_ATTR(11), 1260 CMB_MSR_ATTR(12), 1261 CMB_MSR_ATTR(13), 1262 CMB_MSR_ATTR(14), 1263 CMB_MSR_ATTR(15), 1264 CMB_MSR_ATTR(16), 1265 CMB_MSR_ATTR(17), 1266 CMB_MSR_ATTR(18), 1267 CMB_MSR_ATTR(19), 1268 CMB_MSR_ATTR(20), 1269 CMB_MSR_ATTR(21), 1270 CMB_MSR_ATTR(22), 1271 CMB_MSR_ATTR(23), 1272 CMB_MSR_ATTR(24), 1273 CMB_MSR_ATTR(25), 1274 CMB_MSR_ATTR(26), 1275 CMB_MSR_ATTR(27), 1276 CMB_MSR_ATTR(28), 1277 CMB_MSR_ATTR(29), 1278 CMB_MSR_ATTR(30), 1279 CMB_MSR_ATTR(31), 1280 NULL, 1281}; 1282 1283static struct attribute *tpdm_mcmb_attrs[] = { 1284 &dev_attr_mcmb_trig_lane.attr, 1285 &dev_attr_mcmb_lanes_select.attr, 1286 NULL, 1287}; 1288 1289static struct attribute *tpdm_dsb_attrs[] = { 1290 &dev_attr_dsb_mode.attr, 1291 &dev_attr_dsb_trig_ts.attr, 1292 &dev_attr_dsb_trig_type.attr, 1293 NULL, 1294}; 1295 1296static struct attribute *tpdm_cmb_attrs[] = { 1297 &dev_attr_cmb_mode.attr, 1298 &dev_attr_cmb_ts_all.attr, 1299 &dev_attr_cmb_trig_ts.attr, 1300 NULL, 1301}; 1302 1303static struct attribute_group tpdm_dsb_attr_grp = { 1304 .attrs = tpdm_dsb_attrs, 1305 .is_visible = tpdm_dsb_is_visible, 1306}; 1307 1308static struct attribute_group tpdm_dsb_edge_grp = { 1309 .attrs = tpdm_dsb_edge_attrs, 1310 .is_visible = tpdm_dsb_is_visible, 1311 .name = "dsb_edge", 1312}; 1313 1314static struct attribute_group tpdm_dsb_trig_patt_grp = { 1315 .attrs = tpdm_dsb_trig_patt_attrs, 1316 .is_visible = tpdm_dsb_is_visible, 1317 .name = "dsb_trig_patt", 1318}; 1319 1320static struct attribute_group tpdm_dsb_patt_grp = { 1321 .attrs = tpdm_dsb_patt_attrs, 1322 .is_visible = tpdm_dsb_is_visible, 1323 .name = "dsb_patt", 1324}; 1325 1326static struct attribute_group tpdm_dsb_msr_grp = { 1327 .attrs = tpdm_dsb_msr_attrs, 1328 .is_visible = tpdm_dsb_msr_is_visible, 1329 .name = "dsb_msr", 1330}; 1331 1332static struct attribute_group tpdm_cmb_attr_grp = { 1333 .attrs = tpdm_cmb_attrs, 1334 .is_visible = tpdm_cmb_is_visible, 1335}; 1336 1337static struct attribute_group tpdm_cmb_trig_patt_grp = { 1338 .attrs = tpdm_cmb_trig_patt_attrs, 1339 .is_visible = tpdm_cmb_is_visible, 1340 .name = "cmb_trig_patt", 1341}; 1342 1343static struct attribute_group tpdm_cmb_patt_grp = { 1344 .attrs = tpdm_cmb_patt_attrs, 1345 .is_visible = tpdm_cmb_is_visible, 1346 .name = "cmb_patt", 1347}; 1348 1349static struct attribute_group tpdm_cmb_msr_grp = { 1350 .attrs = tpdm_cmb_msr_attrs, 1351 .is_visible = tpdm_cmb_msr_is_visible, 1352 .name = "cmb_msr", 1353}; 1354 1355static struct attribute_group tpdm_mcmb_attr_grp = { 1356 .attrs = tpdm_mcmb_attrs, 1357 .is_visible = tpdm_mcmb_is_visible, 1358}; 1359 1360static const struct attribute_group *tpdm_attr_grps[] = { 1361 &tpdm_attr_grp, 1362 &tpdm_dsb_attr_grp, 1363 &tpdm_dsb_edge_grp, 1364 &tpdm_dsb_trig_patt_grp, 1365 &tpdm_dsb_patt_grp, 1366 &tpdm_dsb_msr_grp, 1367 &tpdm_cmb_attr_grp, 1368 &tpdm_cmb_trig_patt_grp, 1369 &tpdm_cmb_patt_grp, 1370 &tpdm_cmb_msr_grp, 1371 &tpdm_mcmb_attr_grp, 1372 NULL, 1373}; 1374 1375static int tpdm_probe(struct device *dev, struct resource *res) 1376{ 1377 void __iomem *base; 1378 struct coresight_platform_data *pdata; 1379 struct tpdm_drvdata *drvdata; 1380 struct coresight_desc desc = { 0 }; 1381 int ret; 1382 1383 pdata = coresight_get_platform_data(dev); 1384 if (IS_ERR(pdata)) 1385 return PTR_ERR(pdata); 1386 dev->platform_data = pdata; 1387 1388 /* driver data*/ 1389 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); 1390 if (!drvdata) 1391 return -ENOMEM; 1392 drvdata->dev = dev; 1393 dev_set_drvdata(dev, drvdata); 1394 1395 if (res) { 1396 base = devm_ioremap_resource(dev, res); 1397 if (IS_ERR(base)) 1398 return PTR_ERR(base); 1399 1400 drvdata->base = base; 1401 ret = tpdm_datasets_setup(drvdata); 1402 if (ret) 1403 return ret; 1404 1405 if (tpdm_has_dsb_dataset(drvdata)) 1406 of_property_read_u32(drvdata->dev->of_node, 1407 "qcom,dsb-msrs-num", &drvdata->dsb_msr_num); 1408 1409 if (tpdm_has_cmb_dataset(drvdata)) 1410 of_property_read_u32(drvdata->dev->of_node, 1411 "qcom,cmb-msrs-num", &drvdata->cmb_msr_num); 1412 } else { 1413 ret = static_tpdm_datasets_setup(drvdata, dev); 1414 if (ret) 1415 return ret; 1416 } 1417 1418 /* Set up coresight component description */ 1419 desc.name = coresight_alloc_device_name(&tpdm_devs, dev); 1420 if (!desc.name) 1421 return -ENOMEM; 1422 desc.type = CORESIGHT_DEV_TYPE_SOURCE; 1423 desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM; 1424 desc.ops = &tpdm_cs_ops; 1425 desc.pdata = dev->platform_data; 1426 desc.dev = dev; 1427 desc.access = CSDEV_ACCESS_IOMEM(base); 1428 if (res) 1429 desc.groups = tpdm_attr_grps; 1430 drvdata->csdev = coresight_register(&desc); 1431 if (IS_ERR(drvdata->csdev)) 1432 return PTR_ERR(drvdata->csdev); 1433 1434 spin_lock_init(&drvdata->spinlock); 1435 1436 return 0; 1437} 1438 1439static int tpdm_remove(struct device *dev) 1440{ 1441 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev); 1442 1443 coresight_unregister(drvdata->csdev); 1444 1445 return 0; 1446} 1447 1448static int dynamic_tpdm_probe(struct amba_device *adev, 1449 const struct amba_id *id) 1450{ 1451 int ret; 1452 1453 ret = tpdm_probe(&adev->dev, &adev->res); 1454 if (!ret) 1455 pm_runtime_put(&adev->dev); 1456 1457 return ret; 1458} 1459 1460static void dynamic_tpdm_remove(struct amba_device *adev) 1461{ 1462 tpdm_remove(&adev->dev); 1463} 1464 1465/* 1466 * Different TPDM has different periph id. 1467 * The difference is 0-7 bits' value. So ignore 0-7 bits. 1468 */ 1469static const struct amba_id dynamic_tpdm_ids[] = { 1470 { 1471 .id = 0x001f0e00, 1472 .mask = 0x00ffff00, 1473 }, 1474 { 0, 0, NULL }, 1475}; 1476 1477MODULE_DEVICE_TABLE(amba, dynamic_tpdm_ids); 1478 1479static struct amba_driver dynamic_tpdm_driver = { 1480 .drv = { 1481 .name = "coresight-tpdm", 1482 .suppress_bind_attrs = true, 1483 }, 1484 .probe = dynamic_tpdm_probe, 1485 .id_table = dynamic_tpdm_ids, 1486 .remove = dynamic_tpdm_remove, 1487}; 1488 1489static int tpdm_platform_probe(struct platform_device *pdev) 1490{ 1491 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1492 int ret; 1493 1494 pm_runtime_get_noresume(&pdev->dev); 1495 pm_runtime_set_active(&pdev->dev); 1496 pm_runtime_enable(&pdev->dev); 1497 1498 ret = tpdm_probe(&pdev->dev, res); 1499 pm_runtime_put(&pdev->dev); 1500 if (ret) 1501 pm_runtime_disable(&pdev->dev); 1502 1503 return ret; 1504} 1505 1506static void tpdm_platform_remove(struct platform_device *pdev) 1507{ 1508 struct tpdm_drvdata *drvdata = dev_get_drvdata(&pdev->dev); 1509 1510 if (WARN_ON(!drvdata)) 1511 return; 1512 1513 tpdm_remove(&pdev->dev); 1514 pm_runtime_disable(&pdev->dev); 1515} 1516 1517static const struct of_device_id static_tpdm_match[] = { 1518 {.compatible = "qcom,coresight-static-tpdm"}, 1519 {} 1520}; 1521 1522MODULE_DEVICE_TABLE(of, static_tpdm_match); 1523 1524static struct platform_driver static_tpdm_driver = { 1525 .probe = tpdm_platform_probe, 1526 .remove = tpdm_platform_remove, 1527 .driver = { 1528 .name = "coresight-static-tpdm", 1529 .of_match_table = static_tpdm_match, 1530 .suppress_bind_attrs = true, 1531 }, 1532}; 1533 1534static int __init tpdm_init(void) 1535{ 1536 return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver, 1537 THIS_MODULE); 1538} 1539 1540static void __exit tpdm_exit(void) 1541{ 1542 coresight_remove_driver(&dynamic_tpdm_driver, &static_tpdm_driver); 1543} 1544 1545module_init(tpdm_init); 1546module_exit(tpdm_exit); 1547 1548MODULE_LICENSE("GPL"); 1549MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");
~/
Read-only file preview.