linux/drivers/hwtracing/coresight/coresight-tmc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
   3 *
   4 * Description: CoreSight Trace Memory Controller driver
   5 */
   6
   7#include <linux/kernel.h>
   8#include <linux/init.h>
   9#include <linux/types.h>
  10#include <linux/device.h>
  11#include <linux/idr.h>
  12#include <linux/io.h>
  13#include <linux/err.h>
  14#include <linux/fs.h>
  15#include <linux/miscdevice.h>
  16#include <linux/mutex.h>
  17#include <linux/property.h>
  18#include <linux/uaccess.h>
  19#include <linux/slab.h>
  20#include <linux/dma-mapping.h>
  21#include <linux/spinlock.h>
  22#include <linux/pm_runtime.h>
  23#include <linux/of.h>
  24#include <linux/coresight.h>
  25#include <linux/amba/bus.h>
  26
  27#include "coresight-priv.h"
  28#include "coresight-tmc.h"
  29
  30void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
  31{
  32        /* Ensure formatter, unformatter and hardware fifo are empty */
  33        if (coresight_timeout(drvdata->base,
  34                              TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
  35                dev_err(drvdata->dev,
  36                        "timeout while waiting for TMC to be Ready\n");
  37        }
  38}
  39
  40void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
  41{
  42        u32 ffcr;
  43
  44        ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
  45        ffcr |= TMC_FFCR_STOP_ON_FLUSH;
  46        writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
  47        ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
  48        writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
  49        /* Ensure flush completes */
  50        if (coresight_timeout(drvdata->base,
  51                              TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
  52                dev_err(drvdata->dev,
  53                "timeout while waiting for completion of Manual Flush\n");
  54        }
  55
  56        tmc_wait_for_tmcready(drvdata);
  57}
  58
  59void tmc_enable_hw(struct tmc_drvdata *drvdata)
  60{
  61        writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
  62}
  63
  64void tmc_disable_hw(struct tmc_drvdata *drvdata)
  65{
  66        writel_relaxed(0x0, drvdata->base + TMC_CTL);
  67}
  68
  69static int tmc_read_prepare(struct tmc_drvdata *drvdata)
  70{
  71        int ret = 0;
  72
  73        switch (drvdata->config_type) {
  74        case TMC_CONFIG_TYPE_ETB:
  75        case TMC_CONFIG_TYPE_ETF:
  76                ret = tmc_read_prepare_etb(drvdata);
  77                break;
  78        case TMC_CONFIG_TYPE_ETR:
  79                ret = tmc_read_prepare_etr(drvdata);
  80                break;
  81        default:
  82                ret = -EINVAL;
  83        }
  84
  85        if (!ret)
  86                dev_dbg(drvdata->dev, "TMC read start\n");
  87
  88        return ret;
  89}
  90
  91static int tmc_read_unprepare(struct tmc_drvdata *drvdata)
  92{
  93        int ret = 0;
  94
  95        switch (drvdata->config_type) {
  96        case TMC_CONFIG_TYPE_ETB:
  97        case TMC_CONFIG_TYPE_ETF:
  98                ret = tmc_read_unprepare_etb(drvdata);
  99                break;
 100        case TMC_CONFIG_TYPE_ETR:
 101                ret = tmc_read_unprepare_etr(drvdata);
 102                break;
 103        default:
 104                ret = -EINVAL;
 105        }
 106
 107        if (!ret)
 108                dev_dbg(drvdata->dev, "TMC read end\n");
 109
 110        return ret;
 111}
 112
 113static int tmc_open(struct inode *inode, struct file *file)
 114{
 115        int ret;
 116        struct tmc_drvdata *drvdata = container_of(file->private_data,
 117                                                   struct tmc_drvdata, miscdev);
 118
 119        ret = tmc_read_prepare(drvdata);
 120        if (ret)
 121                return ret;
 122
 123        nonseekable_open(inode, file);
 124
 125        dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
 126        return 0;
 127}
 128
 129static inline ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata,
 130                                          loff_t pos, size_t len, char **bufpp)
 131{
 132        switch (drvdata->config_type) {
 133        case TMC_CONFIG_TYPE_ETB:
 134        case TMC_CONFIG_TYPE_ETF:
 135                return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp);
 136        case TMC_CONFIG_TYPE_ETR:
 137                return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp);
 138        }
 139
 140        return -EINVAL;
 141}
 142
 143static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
 144                        loff_t *ppos)
 145{
 146        char *bufp;
 147        ssize_t actual;
 148        struct tmc_drvdata *drvdata = container_of(file->private_data,
 149                                                   struct tmc_drvdata, miscdev);
 150        actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp);
 151        if (actual <= 0)
 152                return 0;
 153
 154        if (copy_to_user(data, bufp, actual)) {
 155                dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
 156                return -EFAULT;
 157        }
 158
 159        *ppos += actual;
 160        dev_dbg(drvdata->dev, "%zu bytes copied\n", actual);
 161
 162        return actual;
 163}
 164
 165static int tmc_release(struct inode *inode, struct file *file)
 166{
 167        int ret;
 168        struct tmc_drvdata *drvdata = container_of(file->private_data,
 169                                                   struct tmc_drvdata, miscdev);
 170
 171        ret = tmc_read_unprepare(drvdata);
 172        if (ret)
 173                return ret;
 174
 175        dev_dbg(drvdata->dev, "%s: released\n", __func__);
 176        return 0;
 177}
 178
 179static const struct file_operations tmc_fops = {
 180        .owner          = THIS_MODULE,
 181        .open           = tmc_open,
 182        .read           = tmc_read,
 183        .release        = tmc_release,
 184        .llseek         = no_llseek,
 185};
 186
 187static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid)
 188{
 189        enum tmc_mem_intf_width memwidth;
 190
 191        /*
 192         * Excerpt from the TRM:
 193         *
 194         * DEVID::MEMWIDTH[10:8]
 195         * 0x2 Memory interface databus is 32 bits wide.
 196         * 0x3 Memory interface databus is 64 bits wide.
 197         * 0x4 Memory interface databus is 128 bits wide.
 198         * 0x5 Memory interface databus is 256 bits wide.
 199         */
 200        switch (BMVAL(devid, 8, 10)) {
 201        case 0x2:
 202                memwidth = TMC_MEM_INTF_WIDTH_32BITS;
 203                break;
 204        case 0x3:
 205                memwidth = TMC_MEM_INTF_WIDTH_64BITS;
 206                break;
 207        case 0x4:
 208                memwidth = TMC_MEM_INTF_WIDTH_128BITS;
 209                break;
 210        case 0x5:
 211                memwidth = TMC_MEM_INTF_WIDTH_256BITS;
 212                break;
 213        default:
 214                memwidth = 0;
 215        }
 216
 217        return memwidth;
 218}
 219
 220#define coresight_tmc_reg(name, offset)                 \
 221        coresight_simple_reg32(struct tmc_drvdata, name, offset)
 222#define coresight_tmc_reg64(name, lo_off, hi_off)       \
 223        coresight_simple_reg64(struct tmc_drvdata, name, lo_off, hi_off)
 224
 225coresight_tmc_reg(rsz, TMC_RSZ);
 226coresight_tmc_reg(sts, TMC_STS);
 227coresight_tmc_reg(trg, TMC_TRG);
 228coresight_tmc_reg(ctl, TMC_CTL);
 229coresight_tmc_reg(ffsr, TMC_FFSR);
 230coresight_tmc_reg(ffcr, TMC_FFCR);
 231coresight_tmc_reg(mode, TMC_MODE);
 232coresight_tmc_reg(pscr, TMC_PSCR);
 233coresight_tmc_reg(axictl, TMC_AXICTL);
 234coresight_tmc_reg(devid, CORESIGHT_DEVID);
 235coresight_tmc_reg64(rrp, TMC_RRP, TMC_RRPHI);
 236coresight_tmc_reg64(rwp, TMC_RWP, TMC_RWPHI);
 237coresight_tmc_reg64(dba, TMC_DBALO, TMC_DBAHI);
 238
 239static struct attribute *coresight_tmc_mgmt_attrs[] = {
 240        &dev_attr_rsz.attr,
 241        &dev_attr_sts.attr,
 242        &dev_attr_rrp.attr,
 243        &dev_attr_rwp.attr,
 244        &dev_attr_trg.attr,
 245        &dev_attr_ctl.attr,
 246        &dev_attr_ffsr.attr,
 247        &dev_attr_ffcr.attr,
 248        &dev_attr_mode.attr,
 249        &dev_attr_pscr.attr,
 250        &dev_attr_devid.attr,
 251        &dev_attr_dba.attr,
 252        &dev_attr_axictl.attr,
 253        NULL,
 254};
 255
 256static ssize_t trigger_cntr_show(struct device *dev,
 257                                 struct device_attribute *attr, char *buf)
 258{
 259        struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
 260        unsigned long val = drvdata->trigger_cntr;
 261
 262        return sprintf(buf, "%#lx\n", val);
 263}
 264
 265static ssize_t trigger_cntr_store(struct device *dev,
 266                             struct device_attribute *attr,
 267                             const char *buf, size_t size)
 268{
 269        int ret;
 270        unsigned long val;
 271        struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
 272
 273        ret = kstrtoul(buf, 16, &val);
 274        if (ret)
 275                return ret;
 276
 277        drvdata->trigger_cntr = val;
 278        return size;
 279}
 280static DEVICE_ATTR_RW(trigger_cntr);
 281
 282static ssize_t buffer_size_show(struct device *dev,
 283                                struct device_attribute *attr, char *buf)
 284{
 285        struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
 286
 287        return sprintf(buf, "%#x\n", drvdata->size);
 288}
 289
 290static ssize_t buffer_size_store(struct device *dev,
 291                                 struct device_attribute *attr,
 292                                 const char *buf, size_t size)
 293{
 294        int ret;
 295        unsigned long val;
 296        struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
 297
 298        /* Only permitted for TMC-ETRs */
 299        if (drvdata->config_type != TMC_CONFIG_TYPE_ETR)
 300                return -EPERM;
 301
 302        ret = kstrtoul(buf, 0, &val);
 303        if (ret)
 304                return ret;
 305        /* The buffer size should be page aligned */
 306        if (val & (PAGE_SIZE - 1))
 307                return -EINVAL;
 308        drvdata->size = val;
 309        return size;
 310}
 311
 312static DEVICE_ATTR_RW(buffer_size);
 313
 314static struct attribute *coresight_tmc_attrs[] = {
 315        &dev_attr_trigger_cntr.attr,
 316        &dev_attr_buffer_size.attr,
 317        NULL,
 318};
 319
 320static const struct attribute_group coresight_tmc_group = {
 321        .attrs = coresight_tmc_attrs,
 322};
 323
 324static const struct attribute_group coresight_tmc_mgmt_group = {
 325        .attrs = coresight_tmc_mgmt_attrs,
 326        .name = "mgmt",
 327};
 328
 329const struct attribute_group *coresight_tmc_groups[] = {
 330        &coresight_tmc_group,
 331        &coresight_tmc_mgmt_group,
 332        NULL,
 333};
 334
 335static inline bool tmc_etr_can_use_sg(struct tmc_drvdata *drvdata)
 336{
 337        return fwnode_property_present(drvdata->dev->fwnode,
 338                                       "arm,scatter-gather");
 339}
 340
 341/* Detect and initialise the capabilities of a TMC ETR */
 342static int tmc_etr_setup_caps(struct tmc_drvdata *drvdata,
 343                             u32 devid, void *dev_caps)
 344{
 345        int rc;
 346
 347        u32 dma_mask = 0;
 348
 349        /* Set the unadvertised capabilities */
 350        tmc_etr_init_caps(drvdata, (u32)(unsigned long)dev_caps);
 351
 352        if (!(devid & TMC_DEVID_NOSCAT) && tmc_etr_can_use_sg(drvdata))
 353                tmc_etr_set_cap(drvdata, TMC_ETR_SG);
 354
 355        /* Check if the AXI address width is available */
 356        if (devid & TMC_DEVID_AXIAW_VALID)
 357                dma_mask = ((devid >> TMC_DEVID_AXIAW_SHIFT) &
 358                                TMC_DEVID_AXIAW_MASK);
 359
 360        /*
 361         * Unless specified in the device configuration, ETR uses a 40-bit
 362         * AXI master in place of the embedded SRAM of ETB/ETF.
 363         */
 364        switch (dma_mask) {
 365        case 32:
 366        case 40:
 367        case 44:
 368        case 48:
 369        case 52:
 370                dev_info(drvdata->dev, "Detected dma mask %dbits\n", dma_mask);
 371                break;
 372        default:
 373                dma_mask = 40;
 374        }
 375
 376        rc = dma_set_mask_and_coherent(drvdata->dev, DMA_BIT_MASK(dma_mask));
 377        if (rc)
 378                dev_err(drvdata->dev, "Failed to setup DMA mask: %d\n", rc);
 379        return rc;
 380}
 381
 382static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 383{
 384        int ret = 0;
 385        u32 devid;
 386        void __iomem *base;
 387        struct device *dev = &adev->dev;
 388        struct coresight_platform_data *pdata = NULL;
 389        struct tmc_drvdata *drvdata;
 390        struct resource *res = &adev->res;
 391        struct coresight_desc desc = { 0 };
 392        struct device_node *np = adev->dev.of_node;
 393
 394        if (np) {
 395                pdata = of_get_coresight_platform_data(dev, np);
 396                if (IS_ERR(pdata)) {
 397                        ret = PTR_ERR(pdata);
 398                        goto out;
 399                }
 400                adev->dev.platform_data = pdata;
 401        }
 402
 403        ret = -ENOMEM;
 404        drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
 405        if (!drvdata)
 406                goto out;
 407
 408        drvdata->dev = &adev->dev;
 409        dev_set_drvdata(dev, drvdata);
 410
 411        /* Validity for the resource is already checked by the AMBA core */
 412        base = devm_ioremap_resource(dev, res);
 413        if (IS_ERR(base)) {
 414                ret = PTR_ERR(base);
 415                goto out;
 416        }
 417
 418        drvdata->base = base;
 419
 420        spin_lock_init(&drvdata->spinlock);
 421
 422        devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
 423        drvdata->config_type = BMVAL(devid, 6, 7);
 424        drvdata->memwidth = tmc_get_memwidth(devid);
 425        /* This device is not associated with a session */
 426        drvdata->pid = -1;
 427
 428        if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 429                if (np)
 430                        ret = of_property_read_u32(np,
 431                                                   "arm,buffer-size",
 432                                                   &drvdata->size);
 433                if (ret)
 434                        drvdata->size = SZ_1M;
 435        } else {
 436                drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
 437        }
 438
 439        desc.pdata = pdata;
 440        desc.dev = dev;
 441        desc.groups = coresight_tmc_groups;
 442
 443        switch (drvdata->config_type) {
 444        case TMC_CONFIG_TYPE_ETB:
 445                desc.type = CORESIGHT_DEV_TYPE_SINK;
 446                desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
 447                desc.ops = &tmc_etb_cs_ops;
 448                break;
 449        case TMC_CONFIG_TYPE_ETR:
 450                desc.type = CORESIGHT_DEV_TYPE_SINK;
 451                desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
 452                desc.ops = &tmc_etr_cs_ops;
 453                ret = tmc_etr_setup_caps(drvdata, devid,
 454                                         coresight_get_uci_data(id));
 455                if (ret)
 456                        goto out;
 457                idr_init(&drvdata->idr);
 458                mutex_init(&drvdata->idr_mutex);
 459                break;
 460        case TMC_CONFIG_TYPE_ETF:
 461                desc.type = CORESIGHT_DEV_TYPE_LINKSINK;
 462                desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
 463                desc.ops = &tmc_etf_cs_ops;
 464                break;
 465        default:
 466                pr_err("%s: Unsupported TMC config\n", pdata->name);
 467                ret = -EINVAL;
 468                goto out;
 469        }
 470
 471        drvdata->csdev = coresight_register(&desc);
 472        if (IS_ERR(drvdata->csdev)) {
 473                ret = PTR_ERR(drvdata->csdev);
 474                goto out;
 475        }
 476
 477        drvdata->miscdev.name = pdata->name;
 478        drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
 479        drvdata->miscdev.fops = &tmc_fops;
 480        ret = misc_register(&drvdata->miscdev);
 481        if (ret)
 482                coresight_unregister(drvdata->csdev);
 483        else
 484                pm_runtime_put(&adev->dev);
 485out:
 486        return ret;
 487}
 488
 489static const struct amba_id tmc_ids[] = {
 490        CS_AMBA_ID(0x000bb961),
 491        /* Coresight SoC 600 TMC-ETR/ETS */
 492        CS_AMBA_ID_DATA(0x000bb9e8, (unsigned long)CORESIGHT_SOC_600_ETR_CAPS),
 493        /* Coresight SoC 600 TMC-ETB */
 494        CS_AMBA_ID(0x000bb9e9),
 495        /* Coresight SoC 600 TMC-ETF */
 496        CS_AMBA_ID(0x000bb9ea),
 497        { 0, 0},
 498};
 499
 500static struct amba_driver tmc_driver = {
 501        .drv = {
 502                .name   = "coresight-tmc",
 503                .owner  = THIS_MODULE,
 504                .suppress_bind_attrs = true,
 505        },
 506        .probe          = tmc_probe,
 507        .id_table       = tmc_ids,
 508};
 509builtin_amba_driver(tmc_driver);
 510