linux/drivers/hwtracing/coresight/coresight-cti-sysfs.c
<<
>>
Prefs
   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};
1220