coresight-cti-sysfs.c (33232B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2019 Linaro Limited, All rights reserved. 4 * Author: Mike Leach <mike.leach@linaro.org> 5 */ 6 7#include <linux/atomic.h> 8#include <linux/coresight.h> 9#include <linux/device.h> 10#include <linux/io.h> 11#include <linux/kernel.h> 12#include <linux/spinlock.h> 13#include <linux/sysfs.h> 14 15#include "coresight-cti.h" 16 17/* 18 * Declare the number of static declared attribute groups 19 * Value includes groups + NULL value at end of table. 20 */ 21#define CORESIGHT_CTI_STATIC_GROUPS_MAX 5 22 23/* 24 * List of trigger signal type names. Match the constants declared in 25 * include\dt-bindings\arm\coresight-cti-dt.h 26 */ 27static const char * const sig_type_names[] = { 28 "genio", /* GEN_IO */ 29 "intreq", /* GEN_INTREQ */ 30 "intack", /* GEN_INTACK */ 31 "haltreq", /* GEN_HALTREQ */ 32 "restartreq", /* GEN_RESTARTREQ */ 33 "pe_edbgreq", /* PE_EDBGREQ */ 34 "pe_dbgrestart",/* PE_DBGRESTART */ 35 "pe_ctiirq", /* PE_CTIIRQ */ 36 "pe_pmuirq", /* PE_PMUIRQ */ 37 "pe_dbgtrigger",/* PE_DBGTRIGGER */ 38 "etm_extout", /* ETM_EXTOUT */ 39 "etm_extin", /* ETM_EXTIN */ 40 "snk_full", /* SNK_FULL */ 41 "snk_acqcomp", /* SNK_ACQCOMP */ 42 "snk_flushcomp",/* SNK_FLUSHCOMP */ 43 "snk_flushin", /* SNK_FLUSHIN */ 44 "snk_trigin", /* SNK_TRIGIN */ 45 "stm_asyncout", /* STM_ASYNCOUT */ 46 "stm_tout_spte",/* STM_TOUT_SPTE */ 47 "stm_tout_sw", /* STM_TOUT_SW */ 48 "stm_tout_hete",/* STM_TOUT_HETE */ 49 "stm_hwevent", /* STM_HWEVENT */ 50 "ela_tstart", /* ELA_TSTART */ 51 "ela_tstop", /* ELA_TSTOP */ 52 "ela_dbgreq", /* ELA_DBGREQ */ 53}; 54 55/* Show function pointer used in the connections dynamic declared attributes*/ 56typedef ssize_t (*p_show_fn)(struct device *dev, struct device_attribute *attr, 57 char *buf); 58 59/* Connection attribute types */ 60enum cti_conn_attr_type { 61 CTI_CON_ATTR_NAME, 62 CTI_CON_ATTR_TRIGIN_SIG, 63 CTI_CON_ATTR_TRIGOUT_SIG, 64 CTI_CON_ATTR_TRIGIN_TYPES, 65 CTI_CON_ATTR_TRIGOUT_TYPES, 66 CTI_CON_ATTR_MAX, 67}; 68 69/* Names for the connection attributes */ 70static const char * const con_attr_names[CTI_CON_ATTR_MAX] = { 71 "name", 72 "in_signals", 73 "out_signals", 74 "in_types", 75 "out_types", 76}; 77 78/* basic attributes */ 79static ssize_t enable_show(struct device *dev, 80 struct device_attribute *attr, 81 char *buf) 82{ 83 int enable_req; 84 bool enabled, powered; 85 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 86 87 enable_req = atomic_read(&drvdata->config.enable_req_count); 88 spin_lock(&drvdata->spinlock); 89 powered = drvdata->config.hw_powered; 90 enabled = drvdata->config.hw_enabled; 91 spin_unlock(&drvdata->spinlock); 92 93 if (powered) 94 return sprintf(buf, "%d\n", enabled); 95 else 96 return sprintf(buf, "%d\n", !!enable_req); 97} 98 99static ssize_t enable_store(struct device *dev, 100 struct device_attribute *attr, 101 const char *buf, size_t size) 102{ 103 int ret = 0; 104 unsigned long val; 105 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 106 107 ret = kstrtoul(buf, 0, &val); 108 if (ret) 109 return ret; 110 111 if (val) 112 ret = cti_enable(drvdata->csdev); 113 else 114 ret = cti_disable(drvdata->csdev); 115 if (ret) 116 return ret; 117 return size; 118} 119static DEVICE_ATTR_RW(enable); 120 121static ssize_t powered_show(struct device *dev, 122 struct device_attribute *attr, 123 char *buf) 124{ 125 bool powered; 126 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 127 128 spin_lock(&drvdata->spinlock); 129 powered = drvdata->config.hw_powered; 130 spin_unlock(&drvdata->spinlock); 131 132 return sprintf(buf, "%d\n", powered); 133} 134static DEVICE_ATTR_RO(powered); 135 136static ssize_t ctmid_show(struct device *dev, 137 struct device_attribute *attr, char *buf) 138{ 139 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 140 141 return sprintf(buf, "%d\n", drvdata->ctidev.ctm_id); 142} 143static DEVICE_ATTR_RO(ctmid); 144 145static ssize_t nr_trigger_cons_show(struct device *dev, 146 struct device_attribute *attr, 147 char *buf) 148{ 149 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 150 151 return sprintf(buf, "%d\n", drvdata->ctidev.nr_trig_con); 152} 153static DEVICE_ATTR_RO(nr_trigger_cons); 154 155/* attribute and group sysfs tables. */ 156static struct attribute *coresight_cti_attrs[] = { 157 &dev_attr_enable.attr, 158 &dev_attr_powered.attr, 159 &dev_attr_ctmid.attr, 160 &dev_attr_nr_trigger_cons.attr, 161 NULL, 162}; 163 164/* register based attributes */ 165 166/* macro to access RO registers with power check only (no enable check). */ 167#define coresight_cti_reg(name, offset) \ 168static ssize_t name##_show(struct device *dev, \ 169 struct device_attribute *attr, char *buf) \ 170{ \ 171 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \ 172 u32 val = 0; \ 173 pm_runtime_get_sync(dev->parent); \ 174 spin_lock(&drvdata->spinlock); \ 175 if (drvdata->config.hw_powered) \ 176 val = readl_relaxed(drvdata->base + offset); \ 177 spin_unlock(&drvdata->spinlock); \ 178 pm_runtime_put_sync(dev->parent); \ 179 return sprintf(buf, "0x%x\n", val); \ 180} \ 181static DEVICE_ATTR_RO(name) 182 183/* coresight management registers */ 184coresight_cti_reg(devaff0, CTIDEVAFF0); 185coresight_cti_reg(devaff1, CTIDEVAFF1); 186coresight_cti_reg(authstatus, CORESIGHT_AUTHSTATUS); 187coresight_cti_reg(devarch, CORESIGHT_DEVARCH); 188coresight_cti_reg(devid, CORESIGHT_DEVID); 189coresight_cti_reg(devtype, CORESIGHT_DEVTYPE); 190coresight_cti_reg(pidr0, CORESIGHT_PERIPHIDR0); 191coresight_cti_reg(pidr1, CORESIGHT_PERIPHIDR1); 192coresight_cti_reg(pidr2, CORESIGHT_PERIPHIDR2); 193coresight_cti_reg(pidr3, CORESIGHT_PERIPHIDR3); 194coresight_cti_reg(pidr4, CORESIGHT_PERIPHIDR4); 195 196static struct attribute *coresight_cti_mgmt_attrs[] = { 197 &dev_attr_devaff0.attr, 198 &dev_attr_devaff1.attr, 199 &dev_attr_authstatus.attr, 200 &dev_attr_devarch.attr, 201 &dev_attr_devid.attr, 202 &dev_attr_devtype.attr, 203 &dev_attr_pidr0.attr, 204 &dev_attr_pidr1.attr, 205 &dev_attr_pidr2.attr, 206 &dev_attr_pidr3.attr, 207 &dev_attr_pidr4.attr, 208 NULL, 209}; 210 211/* CTI low level programming registers */ 212 213/* 214 * Show a simple 32 bit value if enabled and powered. 215 * If inaccessible & pcached_val not NULL then show cached value. 216 */ 217static ssize_t cti_reg32_show(struct device *dev, char *buf, 218 u32 *pcached_val, int reg_offset) 219{ 220 u32 val = 0; 221 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 222 struct cti_config *config = &drvdata->config; 223 224 spin_lock(&drvdata->spinlock); 225 if ((reg_offset >= 0) && cti_active(config)) { 226 CS_UNLOCK(drvdata->base); 227 val = readl_relaxed(drvdata->base + reg_offset); 228 if (pcached_val) 229 *pcached_val = val; 230 CS_LOCK(drvdata->base); 231 } else if (pcached_val) { 232 val = *pcached_val; 233 } 234 spin_unlock(&drvdata->spinlock); 235 return sprintf(buf, "%#x\n", val); 236} 237 238/* 239 * Store a simple 32 bit value. 240 * If pcached_val not NULL, then copy to here too, 241 * if reg_offset >= 0 then write through if enabled. 242 */ 243static ssize_t cti_reg32_store(struct device *dev, const char *buf, 244 size_t size, u32 *pcached_val, int reg_offset) 245{ 246 unsigned long val; 247 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 248 struct cti_config *config = &drvdata->config; 249 250 if (kstrtoul(buf, 0, &val)) 251 return -EINVAL; 252 253 spin_lock(&drvdata->spinlock); 254 /* local store */ 255 if (pcached_val) 256 *pcached_val = (u32)val; 257 258 /* write through if offset and enabled */ 259 if ((reg_offset >= 0) && cti_active(config)) 260 cti_write_single_reg(drvdata, reg_offset, val); 261 spin_unlock(&drvdata->spinlock); 262 return size; 263} 264 265/* Standard macro for simple rw cti config registers */ 266#define cti_config_reg32_rw(name, cfgname, offset) \ 267static ssize_t name##_show(struct device *dev, \ 268 struct device_attribute *attr, \ 269 char *buf) \ 270{ \ 271 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \ 272 return cti_reg32_show(dev, buf, \ 273 &drvdata->config.cfgname, offset); \ 274} \ 275 \ 276static ssize_t name##_store(struct device *dev, \ 277 struct device_attribute *attr, \ 278 const char *buf, size_t size) \ 279{ \ 280 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \ 281 return cti_reg32_store(dev, buf, size, \ 282 &drvdata->config.cfgname, offset); \ 283} \ 284static DEVICE_ATTR_RW(name) 285 286static ssize_t inout_sel_show(struct device *dev, 287 struct device_attribute *attr, 288 char *buf) 289{ 290 u32 val; 291 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 292 293 val = (u32)drvdata->config.ctiinout_sel; 294 return sprintf(buf, "%d\n", val); 295} 296 297static ssize_t inout_sel_store(struct device *dev, 298 struct device_attribute *attr, 299 const char *buf, size_t size) 300{ 301 unsigned long val; 302 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 303 304 if (kstrtoul(buf, 0, &val)) 305 return -EINVAL; 306 if (val > (CTIINOUTEN_MAX - 1)) 307 return -EINVAL; 308 309 spin_lock(&drvdata->spinlock); 310 drvdata->config.ctiinout_sel = val; 311 spin_unlock(&drvdata->spinlock); 312 return size; 313} 314static DEVICE_ATTR_RW(inout_sel); 315 316static ssize_t inen_show(struct device *dev, 317 struct device_attribute *attr, 318 char *buf) 319{ 320 unsigned long val; 321 int index; 322 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 323 324 spin_lock(&drvdata->spinlock); 325 index = drvdata->config.ctiinout_sel; 326 val = drvdata->config.ctiinen[index]; 327 spin_unlock(&drvdata->spinlock); 328 return sprintf(buf, "%#lx\n", val); 329} 330 331static ssize_t inen_store(struct device *dev, 332 struct device_attribute *attr, 333 const char *buf, size_t size) 334{ 335 unsigned long val; 336 int index; 337 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 338 struct cti_config *config = &drvdata->config; 339 340 if (kstrtoul(buf, 0, &val)) 341 return -EINVAL; 342 343 spin_lock(&drvdata->spinlock); 344 index = config->ctiinout_sel; 345 config->ctiinen[index] = val; 346 347 /* write through if enabled */ 348 if (cti_active(config)) 349 cti_write_single_reg(drvdata, CTIINEN(index), val); 350 spin_unlock(&drvdata->spinlock); 351 return size; 352} 353static DEVICE_ATTR_RW(inen); 354 355static ssize_t outen_show(struct device *dev, 356 struct device_attribute *attr, 357 char *buf) 358{ 359 unsigned long val; 360 int index; 361 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 362 363 spin_lock(&drvdata->spinlock); 364 index = drvdata->config.ctiinout_sel; 365 val = drvdata->config.ctiouten[index]; 366 spin_unlock(&drvdata->spinlock); 367 return sprintf(buf, "%#lx\n", val); 368} 369 370static ssize_t outen_store(struct device *dev, 371 struct device_attribute *attr, 372 const char *buf, size_t size) 373{ 374 unsigned long val; 375 int index; 376 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 377 struct cti_config *config = &drvdata->config; 378 379 if (kstrtoul(buf, 0, &val)) 380 return -EINVAL; 381 382 spin_lock(&drvdata->spinlock); 383 index = config->ctiinout_sel; 384 config->ctiouten[index] = val; 385 386 /* write through if enabled */ 387 if (cti_active(config)) 388 cti_write_single_reg(drvdata, CTIOUTEN(index), val); 389 spin_unlock(&drvdata->spinlock); 390 return size; 391} 392static DEVICE_ATTR_RW(outen); 393 394static ssize_t intack_store(struct device *dev, 395 struct device_attribute *attr, 396 const char *buf, size_t size) 397{ 398 unsigned long val; 399 400 if (kstrtoul(buf, 0, &val)) 401 return -EINVAL; 402 403 cti_write_intack(dev, val); 404 return size; 405} 406static DEVICE_ATTR_WO(intack); 407 408cti_config_reg32_rw(gate, ctigate, CTIGATE); 409cti_config_reg32_rw(asicctl, asicctl, ASICCTL); 410cti_config_reg32_rw(appset, ctiappset, CTIAPPSET); 411 412static ssize_t appclear_store(struct device *dev, 413 struct device_attribute *attr, 414 const char *buf, size_t size) 415{ 416 unsigned long val; 417 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 418 struct cti_config *config = &drvdata->config; 419 420 if (kstrtoul(buf, 0, &val)) 421 return -EINVAL; 422 423 spin_lock(&drvdata->spinlock); 424 425 /* a 1'b1 in appclr clears down the same bit in appset*/ 426 config->ctiappset &= ~val; 427 428 /* write through if enabled */ 429 if (cti_active(config)) 430 cti_write_single_reg(drvdata, CTIAPPCLEAR, val); 431 spin_unlock(&drvdata->spinlock); 432 return size; 433} 434static DEVICE_ATTR_WO(appclear); 435 436static ssize_t apppulse_store(struct device *dev, 437 struct device_attribute *attr, 438 const char *buf, size_t size) 439{ 440 unsigned long val; 441 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 442 struct cti_config *config = &drvdata->config; 443 444 if (kstrtoul(buf, 0, &val)) 445 return -EINVAL; 446 447 spin_lock(&drvdata->spinlock); 448 449 /* write through if enabled */ 450 if (cti_active(config)) 451 cti_write_single_reg(drvdata, CTIAPPPULSE, val); 452 spin_unlock(&drvdata->spinlock); 453 return size; 454} 455static DEVICE_ATTR_WO(apppulse); 456 457coresight_cti_reg(triginstatus, CTITRIGINSTATUS); 458coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS); 459coresight_cti_reg(chinstatus, CTICHINSTATUS); 460coresight_cti_reg(choutstatus, CTICHOUTSTATUS); 461 462/* 463 * Define CONFIG_CORESIGHT_CTI_INTEGRATION_REGS to enable the access to the 464 * integration control registers. Normally only used to investigate connection 465 * data. 466 */ 467#ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS 468 469/* macro to access RW registers with power check only (no enable check). */ 470#define coresight_cti_reg_rw(name, offset) \ 471static ssize_t name##_show(struct device *dev, \ 472 struct device_attribute *attr, char *buf) \ 473{ \ 474 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \ 475 u32 val = 0; \ 476 pm_runtime_get_sync(dev->parent); \ 477 spin_lock(&drvdata->spinlock); \ 478 if (drvdata->config.hw_powered) \ 479 val = readl_relaxed(drvdata->base + offset); \ 480 spin_unlock(&drvdata->spinlock); \ 481 pm_runtime_put_sync(dev->parent); \ 482 return sprintf(buf, "0x%x\n", val); \ 483} \ 484 \ 485static ssize_t name##_store(struct device *dev, \ 486 struct device_attribute *attr, \ 487 const char *buf, size_t size) \ 488{ \ 489 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \ 490 unsigned long val = 0; \ 491 if (kstrtoul(buf, 0, &val)) \ 492 return -EINVAL; \ 493 \ 494 pm_runtime_get_sync(dev->parent); \ 495 spin_lock(&drvdata->spinlock); \ 496 if (drvdata->config.hw_powered) \ 497 cti_write_single_reg(drvdata, offset, val); \ 498 spin_unlock(&drvdata->spinlock); \ 499 pm_runtime_put_sync(dev->parent); \ 500 return size; \ 501} \ 502static DEVICE_ATTR_RW(name) 503 504/* macro to access WO registers with power check only (no enable check). */ 505#define coresight_cti_reg_wo(name, offset) \ 506static ssize_t name##_store(struct device *dev, \ 507 struct device_attribute *attr, \ 508 const char *buf, size_t size) \ 509{ \ 510 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); \ 511 unsigned long val = 0; \ 512 if (kstrtoul(buf, 0, &val)) \ 513 return -EINVAL; \ 514 \ 515 pm_runtime_get_sync(dev->parent); \ 516 spin_lock(&drvdata->spinlock); \ 517 if (drvdata->config.hw_powered) \ 518 cti_write_single_reg(drvdata, offset, val); \ 519 spin_unlock(&drvdata->spinlock); \ 520 pm_runtime_put_sync(dev->parent); \ 521 return size; \ 522} \ 523static DEVICE_ATTR_WO(name) 524 525coresight_cti_reg_rw(itchout, ITCHOUT); 526coresight_cti_reg_rw(ittrigout, ITTRIGOUT); 527coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL); 528coresight_cti_reg_wo(itchinack, ITCHINACK); 529coresight_cti_reg_wo(ittriginack, ITTRIGINACK); 530coresight_cti_reg(ittrigin, ITTRIGIN); 531coresight_cti_reg(itchin, ITCHIN); 532coresight_cti_reg(itchoutack, ITCHOUTACK); 533coresight_cti_reg(ittrigoutack, ITTRIGOUTACK); 534 535#endif /* CORESIGHT_CTI_INTEGRATION_REGS */ 536 537static struct attribute *coresight_cti_regs_attrs[] = { 538 &dev_attr_inout_sel.attr, 539 &dev_attr_inen.attr, 540 &dev_attr_outen.attr, 541 &dev_attr_gate.attr, 542 &dev_attr_asicctl.attr, 543 &dev_attr_intack.attr, 544 &dev_attr_appset.attr, 545 &dev_attr_appclear.attr, 546 &dev_attr_apppulse.attr, 547 &dev_attr_triginstatus.attr, 548 &dev_attr_trigoutstatus.attr, 549 &dev_attr_chinstatus.attr, 550 &dev_attr_choutstatus.attr, 551#ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS 552 &dev_attr_itctrl.attr, 553 &dev_attr_ittrigin.attr, 554 &dev_attr_itchin.attr, 555 &dev_attr_ittrigout.attr, 556 &dev_attr_itchout.attr, 557 &dev_attr_itchoutack.attr, 558 &dev_attr_ittrigoutack.attr, 559 &dev_attr_ittriginack.attr, 560 &dev_attr_itchinack.attr, 561#endif 562 NULL, 563}; 564 565/* CTI channel x-trigger programming */ 566static int 567cti_trig_op_parse(struct device *dev, enum cti_chan_op op, 568 enum cti_trig_dir dir, const char *buf, size_t size) 569{ 570 u32 chan_idx; 571 u32 trig_idx; 572 int items, err = -EINVAL; 573 574 /* extract chan idx and trigger idx */ 575 items = sscanf(buf, "%d %d", &chan_idx, &trig_idx); 576 if (items == 2) { 577 err = cti_channel_trig_op(dev, op, dir, chan_idx, trig_idx); 578 if (!err) 579 err = size; 580 } 581 return err; 582} 583 584static ssize_t trigin_attach_store(struct device *dev, 585 struct device_attribute *attr, 586 const char *buf, size_t size) 587{ 588 return cti_trig_op_parse(dev, CTI_CHAN_ATTACH, CTI_TRIG_IN, 589 buf, size); 590} 591static DEVICE_ATTR_WO(trigin_attach); 592 593static ssize_t trigin_detach_store(struct device *dev, 594 struct device_attribute *attr, 595 const char *buf, size_t size) 596{ 597 return cti_trig_op_parse(dev, CTI_CHAN_DETACH, CTI_TRIG_IN, 598 buf, size); 599} 600static DEVICE_ATTR_WO(trigin_detach); 601 602static ssize_t trigout_attach_store(struct device *dev, 603 struct device_attribute *attr, 604 const char *buf, size_t size) 605{ 606 return cti_trig_op_parse(dev, CTI_CHAN_ATTACH, CTI_TRIG_OUT, 607 buf, size); 608} 609static DEVICE_ATTR_WO(trigout_attach); 610 611static ssize_t trigout_detach_store(struct device *dev, 612 struct device_attribute *attr, 613 const char *buf, size_t size) 614{ 615 return cti_trig_op_parse(dev, CTI_CHAN_DETACH, CTI_TRIG_OUT, 616 buf, size); 617} 618static DEVICE_ATTR_WO(trigout_detach); 619 620 621static ssize_t chan_gate_enable_store(struct device *dev, 622 struct device_attribute *attr, 623 const char *buf, size_t size) 624{ 625 int err = 0, channel = 0; 626 627 if (kstrtoint(buf, 0, &channel)) 628 return -EINVAL; 629 630 err = cti_channel_gate_op(dev, CTI_GATE_CHAN_ENABLE, channel); 631 return err ? err : size; 632} 633 634static ssize_t chan_gate_enable_show(struct device *dev, 635 struct device_attribute *attr, 636 char *buf) 637{ 638 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 639 struct cti_config *cfg = &drvdata->config; 640 unsigned long ctigate_bitmask = cfg->ctigate; 641 int size = 0; 642 643 if (cfg->ctigate == 0) 644 size = sprintf(buf, "\n"); 645 else 646 size = bitmap_print_to_pagebuf(true, buf, &ctigate_bitmask, 647 cfg->nr_ctm_channels); 648 return size; 649} 650static DEVICE_ATTR_RW(chan_gate_enable); 651 652static ssize_t chan_gate_disable_store(struct device *dev, 653 struct device_attribute *attr, 654 const char *buf, size_t size) 655{ 656 int err = 0, channel = 0; 657 658 if (kstrtoint(buf, 0, &channel)) 659 return -EINVAL; 660 661 err = cti_channel_gate_op(dev, CTI_GATE_CHAN_DISABLE, channel); 662 return err ? err : size; 663} 664static DEVICE_ATTR_WO(chan_gate_disable); 665 666static int 667chan_op_parse(struct device *dev, enum cti_chan_set_op op, const char *buf) 668{ 669 int err = 0, channel = 0; 670 671 if (kstrtoint(buf, 0, &channel)) 672 return -EINVAL; 673 674 err = cti_channel_setop(dev, op, channel); 675 return err; 676 677} 678 679static ssize_t chan_set_store(struct device *dev, 680 struct device_attribute *attr, 681 const char *buf, size_t size) 682{ 683 int err = chan_op_parse(dev, CTI_CHAN_SET, buf); 684 685 return err ? err : size; 686} 687static DEVICE_ATTR_WO(chan_set); 688 689static ssize_t chan_clear_store(struct device *dev, 690 struct device_attribute *attr, 691 const char *buf, size_t size) 692{ 693 int err = chan_op_parse(dev, CTI_CHAN_CLR, buf); 694 695 return err ? err : size; 696} 697static DEVICE_ATTR_WO(chan_clear); 698 699static ssize_t chan_pulse_store(struct device *dev, 700 struct device_attribute *attr, 701 const char *buf, size_t size) 702{ 703 int err = chan_op_parse(dev, CTI_CHAN_PULSE, buf); 704 705 return err ? err : size; 706} 707static DEVICE_ATTR_WO(chan_pulse); 708 709static ssize_t trig_filter_enable_show(struct device *dev, 710 struct device_attribute *attr, 711 char *buf) 712{ 713 u32 val; 714 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 715 716 spin_lock(&drvdata->spinlock); 717 val = drvdata->config.trig_filter_enable; 718 spin_unlock(&drvdata->spinlock); 719 return sprintf(buf, "%d\n", val); 720} 721 722static ssize_t trig_filter_enable_store(struct device *dev, 723 struct device_attribute *attr, 724 const char *buf, size_t size) 725{ 726 unsigned long val; 727 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 728 729 if (kstrtoul(buf, 0, &val)) 730 return -EINVAL; 731 732 spin_lock(&drvdata->spinlock); 733 drvdata->config.trig_filter_enable = !!val; 734 spin_unlock(&drvdata->spinlock); 735 return size; 736} 737static DEVICE_ATTR_RW(trig_filter_enable); 738 739static ssize_t trigout_filtered_show(struct device *dev, 740 struct device_attribute *attr, 741 char *buf) 742{ 743 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 744 struct cti_config *cfg = &drvdata->config; 745 int size = 0, nr_trig_max = cfg->nr_trig_max; 746 unsigned long mask = cfg->trig_out_filter; 747 748 if (mask) 749 size = bitmap_print_to_pagebuf(true, buf, &mask, nr_trig_max); 750 return size; 751} 752static DEVICE_ATTR_RO(trigout_filtered); 753 754/* clear all xtrigger / channel programming */ 755static ssize_t chan_xtrigs_reset_store(struct device *dev, 756 struct device_attribute *attr, 757 const char *buf, size_t size) 758{ 759 int i; 760 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 761 struct cti_config *config = &drvdata->config; 762 763 spin_lock(&drvdata->spinlock); 764 765 /* clear the CTI trigger / channel programming registers */ 766 for (i = 0; i < config->nr_trig_max; i++) { 767 config->ctiinen[i] = 0; 768 config->ctiouten[i] = 0; 769 } 770 771 /* clear the other regs */ 772 config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0); 773 config->asicctl = 0; 774 config->ctiappset = 0; 775 config->ctiinout_sel = 0; 776 config->xtrig_rchan_sel = 0; 777 778 /* if enabled then write through */ 779 if (cti_active(config)) 780 cti_write_all_hw_regs(drvdata); 781 782 spin_unlock(&drvdata->spinlock); 783 return size; 784} 785static DEVICE_ATTR_WO(chan_xtrigs_reset); 786 787/* 788 * Write to select a channel to view, read to display the 789 * cross triggers for the selected channel. 790 */ 791static ssize_t chan_xtrigs_sel_store(struct device *dev, 792 struct device_attribute *attr, 793 const char *buf, size_t size) 794{ 795 unsigned long val; 796 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 797 798 if (kstrtoul(buf, 0, &val)) 799 return -EINVAL; 800 if (val > (drvdata->config.nr_ctm_channels - 1)) 801 return -EINVAL; 802 803 spin_lock(&drvdata->spinlock); 804 drvdata->config.xtrig_rchan_sel = val; 805 spin_unlock(&drvdata->spinlock); 806 return size; 807} 808 809static ssize_t chan_xtrigs_sel_show(struct device *dev, 810 struct device_attribute *attr, 811 char *buf) 812{ 813 unsigned long val; 814 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 815 816 spin_lock(&drvdata->spinlock); 817 val = drvdata->config.xtrig_rchan_sel; 818 spin_unlock(&drvdata->spinlock); 819 820 return sprintf(buf, "%ld\n", val); 821} 822static DEVICE_ATTR_RW(chan_xtrigs_sel); 823 824static ssize_t chan_xtrigs_in_show(struct device *dev, 825 struct device_attribute *attr, 826 char *buf) 827{ 828 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 829 struct cti_config *cfg = &drvdata->config; 830 int used = 0, reg_idx; 831 int nr_trig_max = drvdata->config.nr_trig_max; 832 u32 chan_mask = BIT(cfg->xtrig_rchan_sel); 833 834 for (reg_idx = 0; reg_idx < nr_trig_max; reg_idx++) { 835 if (chan_mask & cfg->ctiinen[reg_idx]) 836 used += sprintf(buf + used, "%d ", reg_idx); 837 } 838 839 used += sprintf(buf + used, "\n"); 840 return used; 841} 842static DEVICE_ATTR_RO(chan_xtrigs_in); 843 844static ssize_t chan_xtrigs_out_show(struct device *dev, 845 struct device_attribute *attr, 846 char *buf) 847{ 848 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 849 struct cti_config *cfg = &drvdata->config; 850 int used = 0, reg_idx; 851 int nr_trig_max = drvdata->config.nr_trig_max; 852 u32 chan_mask = BIT(cfg->xtrig_rchan_sel); 853 854 for (reg_idx = 0; reg_idx < nr_trig_max; reg_idx++) { 855 if (chan_mask & cfg->ctiouten[reg_idx]) 856 used += sprintf(buf + used, "%d ", reg_idx); 857 } 858 859 used += sprintf(buf + used, "\n"); 860 return used; 861} 862static DEVICE_ATTR_RO(chan_xtrigs_out); 863 864static ssize_t print_chan_list(struct device *dev, 865 char *buf, bool inuse) 866{ 867 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 868 struct cti_config *config = &drvdata->config; 869 int size, i; 870 unsigned long inuse_bits = 0, chan_mask; 871 872 /* scan regs to get bitmap of channels in use. */ 873 spin_lock(&drvdata->spinlock); 874 for (i = 0; i < config->nr_trig_max; i++) { 875 inuse_bits |= config->ctiinen[i]; 876 inuse_bits |= config->ctiouten[i]; 877 } 878 spin_unlock(&drvdata->spinlock); 879 880 /* inverse bits if printing free channels */ 881 if (!inuse) 882 inuse_bits = ~inuse_bits; 883 884 /* list of channels, or 'none' */ 885 chan_mask = GENMASK(config->nr_ctm_channels - 1, 0); 886 if (inuse_bits & chan_mask) 887 size = bitmap_print_to_pagebuf(true, buf, &inuse_bits, 888 config->nr_ctm_channels); 889 else 890 size = sprintf(buf, "\n"); 891 return size; 892} 893 894static ssize_t chan_inuse_show(struct device *dev, 895 struct device_attribute *attr, 896 char *buf) 897{ 898 return print_chan_list(dev, buf, true); 899} 900static DEVICE_ATTR_RO(chan_inuse); 901 902static ssize_t chan_free_show(struct device *dev, 903 struct device_attribute *attr, 904 char *buf) 905{ 906 return print_chan_list(dev, buf, false); 907} 908static DEVICE_ATTR_RO(chan_free); 909 910static struct attribute *coresight_cti_channel_attrs[] = { 911 &dev_attr_trigin_attach.attr, 912 &dev_attr_trigin_detach.attr, 913 &dev_attr_trigout_attach.attr, 914 &dev_attr_trigout_detach.attr, 915 &dev_attr_trig_filter_enable.attr, 916 &dev_attr_trigout_filtered.attr, 917 &dev_attr_chan_gate_enable.attr, 918 &dev_attr_chan_gate_disable.attr, 919 &dev_attr_chan_set.attr, 920 &dev_attr_chan_clear.attr, 921 &dev_attr_chan_pulse.attr, 922 &dev_attr_chan_inuse.attr, 923 &dev_attr_chan_free.attr, 924 &dev_attr_chan_xtrigs_sel.attr, 925 &dev_attr_chan_xtrigs_in.attr, 926 &dev_attr_chan_xtrigs_out.attr, 927 &dev_attr_chan_xtrigs_reset.attr, 928 NULL, 929}; 930 931/* Create the connections trigger groups and attrs dynamically */ 932/* 933 * Each connection has dynamic group triggers<N> + name, trigin/out sigs/types 934 * attributes, + each device has static nr_trigger_cons giving the number 935 * of groups. e.g. in sysfs:- 936 * /cti_<name>/triggers0 937 * /cti_<name>/triggers1 938 * /cti_<name>/nr_trigger_cons 939 * where nr_trigger_cons = 2 940 */ 941static ssize_t con_name_show(struct device *dev, 942 struct device_attribute *attr, 943 char *buf) 944{ 945 struct dev_ext_attribute *ext_attr = 946 container_of(attr, struct dev_ext_attribute, attr); 947 struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; 948 949 return sprintf(buf, "%s\n", con->con_dev_name); 950} 951 952static ssize_t trigin_sig_show(struct device *dev, 953 struct device_attribute *attr, 954 char *buf) 955{ 956 struct dev_ext_attribute *ext_attr = 957 container_of(attr, struct dev_ext_attribute, attr); 958 struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; 959 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 960 struct cti_config *cfg = &drvdata->config; 961 unsigned long mask = con->con_in->used_mask; 962 963 return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max); 964} 965 966static ssize_t trigout_sig_show(struct device *dev, 967 struct device_attribute *attr, 968 char *buf) 969{ 970 struct dev_ext_attribute *ext_attr = 971 container_of(attr, struct dev_ext_attribute, attr); 972 struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; 973 struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); 974 struct cti_config *cfg = &drvdata->config; 975 unsigned long mask = con->con_out->used_mask; 976 977 return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max); 978} 979 980/* convert a sig type id to a name */ 981static const char * 982cti_sig_type_name(struct cti_trig_con *con, int used_count, bool in) 983{ 984 int idx = 0; 985 struct cti_trig_grp *grp = in ? con->con_in : con->con_out; 986 987 if (used_count < grp->nr_sigs) 988 idx = grp->sig_types[used_count]; 989 return sig_type_names[idx]; 990} 991 992static ssize_t trigin_type_show(struct device *dev, 993 struct device_attribute *attr, 994 char *buf) 995{ 996 struct dev_ext_attribute *ext_attr = 997 container_of(attr, struct dev_ext_attribute, attr); 998 struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; 999 int sig_idx, used = 0; 1000 const char *name; 1001 1002 for (sig_idx = 0; sig_idx < con->con_in->nr_sigs; sig_idx++) { 1003 name = cti_sig_type_name(con, sig_idx, true); 1004 used += sprintf(buf + used, "%s ", name); 1005 } 1006 used += sprintf(buf + used, "\n"); 1007 return used; 1008} 1009 1010static ssize_t trigout_type_show(struct device *dev, 1011 struct device_attribute *attr, 1012 char *buf) 1013{ 1014 struct dev_ext_attribute *ext_attr = 1015 container_of(attr, struct dev_ext_attribute, attr); 1016 struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var; 1017 int sig_idx, used = 0; 1018 const char *name; 1019 1020 for (sig_idx = 0; sig_idx < con->con_out->nr_sigs; sig_idx++) { 1021 name = cti_sig_type_name(con, sig_idx, false); 1022 used += sprintf(buf + used, "%s ", name); 1023 } 1024 used += sprintf(buf + used, "\n"); 1025 return used; 1026} 1027 1028/* 1029 * Array of show function names declared above to allow selection 1030 * for the connection attributes 1031 */ 1032static p_show_fn show_fns[CTI_CON_ATTR_MAX] = { 1033 con_name_show, 1034 trigin_sig_show, 1035 trigout_sig_show, 1036 trigin_type_show, 1037 trigout_type_show, 1038}; 1039 1040static int cti_create_con_sysfs_attr(struct device *dev, 1041 struct cti_trig_con *con, 1042 enum cti_conn_attr_type attr_type, 1043 int attr_idx) 1044{ 1045 struct dev_ext_attribute *eattr; 1046 char *name; 1047 1048 eattr = devm_kzalloc(dev, sizeof(struct dev_ext_attribute), 1049 GFP_KERNEL); 1050 if (eattr) { 1051 name = devm_kstrdup(dev, con_attr_names[attr_type], 1052 GFP_KERNEL); 1053 if (name) { 1054 /* fill out the underlying attribute struct */ 1055 eattr->attr.attr.name = name; 1056 eattr->attr.attr.mode = 0444; 1057 1058 /* now the device_attribute struct */ 1059 eattr->attr.show = show_fns[attr_type]; 1060 } else { 1061 return -ENOMEM; 1062 } 1063 } else { 1064 return -ENOMEM; 1065 } 1066 eattr->var = con; 1067 con->con_attrs[attr_idx] = &eattr->attr.attr; 1068 /* 1069 * Initialize the dynamically allocated attribute 1070 * to avoid LOCKDEP splat. See include/linux/sysfs.h 1071 * for more details. 1072 */ 1073 sysfs_attr_init(con->con_attrs[attr_idx]); 1074 1075 return 0; 1076} 1077 1078static struct attribute_group * 1079cti_create_con_sysfs_group(struct device *dev, struct cti_device *ctidev, 1080 int con_idx, struct cti_trig_con *tc) 1081{ 1082 struct attribute_group *group = NULL; 1083 int grp_idx; 1084 1085 group = devm_kzalloc(dev, sizeof(struct attribute_group), GFP_KERNEL); 1086 if (!group) 1087 return NULL; 1088 1089 group->name = devm_kasprintf(dev, GFP_KERNEL, "triggers%d", con_idx); 1090 if (!group->name) 1091 return NULL; 1092 1093 grp_idx = con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1; 1094 ctidev->con_groups[grp_idx] = group; 1095 tc->attr_group = group; 1096 return group; 1097} 1098 1099/* create a triggers connection group and the attributes for that group */ 1100static int cti_create_con_attr_set(struct device *dev, int con_idx, 1101 struct cti_device *ctidev, 1102 struct cti_trig_con *tc) 1103{ 1104 struct attribute_group *attr_group = NULL; 1105 int attr_idx = 0; 1106 int err = -ENOMEM; 1107 1108 attr_group = cti_create_con_sysfs_group(dev, ctidev, con_idx, tc); 1109 if (!attr_group) 1110 return -ENOMEM; 1111 1112 /* allocate NULL terminated array of attributes */ 1113 tc->con_attrs = devm_kcalloc(dev, CTI_CON_ATTR_MAX + 1, 1114 sizeof(struct attribute *), GFP_KERNEL); 1115 if (!tc->con_attrs) 1116 return -ENOMEM; 1117 1118 err = cti_create_con_sysfs_attr(dev, tc, CTI_CON_ATTR_NAME, 1119 attr_idx++); 1120 if (err) 1121 return err; 1122 1123 if (tc->con_in->nr_sigs > 0) { 1124 err = cti_create_con_sysfs_attr(dev, tc, 1125 CTI_CON_ATTR_TRIGIN_SIG, 1126 attr_idx++); 1127 if (err) 1128 return err; 1129 1130 err = cti_create_con_sysfs_attr(dev, tc, 1131 CTI_CON_ATTR_TRIGIN_TYPES, 1132 attr_idx++); 1133 if (err) 1134 return err; 1135 } 1136 1137 if (tc->con_out->nr_sigs > 0) { 1138 err = cti_create_con_sysfs_attr(dev, tc, 1139 CTI_CON_ATTR_TRIGOUT_SIG, 1140 attr_idx++); 1141 if (err) 1142 return err; 1143 1144 err = cti_create_con_sysfs_attr(dev, tc, 1145 CTI_CON_ATTR_TRIGOUT_TYPES, 1146 attr_idx++); 1147 if (err) 1148 return err; 1149 } 1150 attr_group->attrs = tc->con_attrs; 1151 return 0; 1152} 1153 1154/* create the array of group pointers for the CTI sysfs groups */ 1155static int cti_create_cons_groups(struct device *dev, struct cti_device *ctidev) 1156{ 1157 int nr_groups; 1158 1159 /* nr groups = dynamic + static + NULL terminator */ 1160 nr_groups = ctidev->nr_trig_con + CORESIGHT_CTI_STATIC_GROUPS_MAX; 1161 ctidev->con_groups = devm_kcalloc(dev, nr_groups, 1162 sizeof(struct attribute_group *), 1163 GFP_KERNEL); 1164 if (!ctidev->con_groups) 1165 return -ENOMEM; 1166 return 0; 1167} 1168 1169int cti_create_cons_sysfs(struct device *dev, struct cti_drvdata *drvdata) 1170{ 1171 struct cti_device *ctidev = &drvdata->ctidev; 1172 int err, con_idx = 0, i; 1173 struct cti_trig_con *tc; 1174 1175 err = cti_create_cons_groups(dev, ctidev); 1176 if (err) 1177 return err; 1178 1179 /* populate first locations with the static set of groups */ 1180 for (i = 0; i < (CORESIGHT_CTI_STATIC_GROUPS_MAX - 1); i++) 1181 ctidev->con_groups[i] = coresight_cti_groups[i]; 1182 1183 /* add dynamic set for each connection */ 1184 list_for_each_entry(tc, &ctidev->trig_cons, node) { 1185 err = cti_create_con_attr_set(dev, con_idx++, ctidev, tc); 1186 if (err) 1187 break; 1188 } 1189 return err; 1190} 1191 1192/* attribute and group sysfs tables. */ 1193static const struct attribute_group coresight_cti_group = { 1194 .attrs = coresight_cti_attrs, 1195}; 1196 1197static const struct attribute_group coresight_cti_mgmt_group = { 1198 .attrs = coresight_cti_mgmt_attrs, 1199 .name = "mgmt", 1200}; 1201 1202static const struct attribute_group coresight_cti_regs_group = { 1203 .attrs = coresight_cti_regs_attrs, 1204 .name = "regs", 1205}; 1206 1207static const struct attribute_group coresight_cti_channels_group = { 1208 .attrs = coresight_cti_channel_attrs, 1209 .name = "channels", 1210}; 1211 1212const struct attribute_group * 1213coresight_cti_groups[CORESIGHT_CTI_STATIC_GROUPS_MAX] = { 1214 &coresight_cti_group, 1215 &coresight_cti_mgmt_group, 1216 &coresight_cti_regs_group, 1217 &coresight_cti_channels_group, 1218 NULL, 1219};