linux/drivers/hwtracing/intel_th/intel_th.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Intel(R) Trace Hub data structures
   4 *
   5 * Copyright (C) 2014-2015 Intel Corporation.
   6 */
   7
   8#ifndef __INTEL_TH_H__
   9#define __INTEL_TH_H__
  10
  11#include <linux/irqreturn.h>
  12
  13/* intel_th_device device types */
  14enum {
  15        /* Devices that generate trace data */
  16        INTEL_TH_SOURCE = 0,
  17        /* Output ports (MSC, PTI) */
  18        INTEL_TH_OUTPUT,
  19        /* Switch, the Global Trace Hub (GTH) */
  20        INTEL_TH_SWITCH,
  21};
  22
  23struct intel_th_device;
  24
  25/**
  26 * struct intel_th_output - descriptor INTEL_TH_OUTPUT type devices
  27 * @port:       output port number, assigned by the switch
  28 * @type:       GTH_{MSU,CTP,PTI}
  29 * @scratchpad: scratchpad bits to flag when this output is enabled
  30 * @multiblock: true for multiblock output configuration
  31 * @active:     true when this output is enabled
  32 * @wait_empty: wait for device pipeline to be empty
  33 *
  34 * Output port descriptor, used by switch driver to tell which output
  35 * port this output device corresponds to. Filled in at output device's
  36 * probe time by switch::assign(). Passed from output device driver to
  37 * switch related code to enable/disable its port.
  38 */
  39struct intel_th_output {
  40        int             port;
  41        unsigned int    type;
  42        unsigned int    scratchpad;
  43        bool            multiblock;
  44        bool            active;
  45};
  46
  47/**
  48 * struct intel_th_drvdata - describes hardware capabilities and quirks
  49 * @tscu_enable:        device needs SW to enable time stamping unit
  50 * @has_mintctl:        device has interrupt control (MINTCTL) register
  51 * @host_mode_only:     device can only operate in 'host debugger' mode
  52 */
  53struct intel_th_drvdata {
  54        unsigned int    tscu_enable        : 1,
  55                        has_mintctl        : 1,
  56                        host_mode_only     : 1;
  57};
  58
  59#define INTEL_TH_CAP(_th, _cap) ((_th)->drvdata ? (_th)->drvdata->_cap : 0)
  60
  61/**
  62 * struct intel_th_device - device on the intel_th bus
  63 * @dev:                device
  64 * @drvdata:            hardware capabilities/quirks
  65 * @resource:           array of resources available to this device
  66 * @num_resources:      number of resources in @resource array
  67 * @type:               INTEL_TH_{SOURCE,OUTPUT,SWITCH}
  68 * @id:                 device instance or -1
  69 * @host_mode:          Intel TH is controlled by an external debug host
  70 * @output:             output descriptor for INTEL_TH_OUTPUT devices
  71 * @name:               device name to match the driver
  72 */
  73struct intel_th_device {
  74        struct device           dev;
  75        struct intel_th_drvdata *drvdata;
  76        struct resource         *resource;
  77        unsigned int            num_resources;
  78        unsigned int            type;
  79        int                     id;
  80
  81        /* INTEL_TH_SWITCH specific */
  82        bool                    host_mode;
  83
  84        /* INTEL_TH_OUTPUT specific */
  85        struct intel_th_output  output;
  86
  87        char            name[];
  88};
  89
  90#define to_intel_th_device(_d)                          \
  91        container_of((_d), struct intel_th_device, dev)
  92
  93/**
  94 * intel_th_device_get_resource() - obtain @num'th resource of type @type
  95 * @thdev:      the device to search the resource for
  96 * @type:       resource type
  97 * @num:        number of the resource
  98 */
  99static inline struct resource *
 100intel_th_device_get_resource(struct intel_th_device *thdev, unsigned int type,
 101                             unsigned int num)
 102{
 103        int i;
 104
 105        for (i = 0; i < thdev->num_resources; i++)
 106                if (resource_type(&thdev->resource[i]) == type && !num--)
 107                        return &thdev->resource[i];
 108
 109        return NULL;
 110}
 111
 112/*
 113 * GTH, output ports configuration
 114 */
 115enum {
 116        GTH_NONE = 0,
 117        GTH_MSU,        /* memory/usb */
 118        GTH_CTP,        /* Common Trace Port */
 119        GTH_LPP,        /* Low Power Path */
 120        GTH_PTI,        /* MIPI-PTI */
 121};
 122
 123/**
 124 * intel_th_output_assigned() - if an output device is assigned to a switch port
 125 * @thdev:      the output device
 126 *
 127 * Return:      true if the device is INTEL_TH_OUTPUT *and* is assigned a port
 128 */
 129static inline bool
 130intel_th_output_assigned(struct intel_th_device *thdev)
 131{
 132        return thdev->type == INTEL_TH_OUTPUT &&
 133                (thdev->output.port >= 0 ||
 134                 thdev->output.type == GTH_NONE);
 135}
 136
 137/**
 138 * struct intel_th_driver - driver for an intel_th_device device
 139 * @driver:     generic driver
 140 * @probe:      probe method
 141 * @remove:     remove method
 142 * @assign:     match a given output type device against available outputs
 143 * @unassign:   deassociate an output type device from an output port
 144 * @enable:     enable tracing for a given output device
 145 * @disable:    disable tracing for a given output device
 146 * @irq:        interrupt callback
 147 * @activate:   enable tracing on the output's side
 148 * @deactivate: disable tracing on the output's side
 149 * @fops:       file operations for device nodes
 150 * @attr_group: attributes provided by the driver
 151 *
 152 * Callbacks @probe and @remove are required for all device types.
 153 * Switch device driver needs to fill in @assign, @enable and @disable
 154 * callbacks.
 155 */
 156struct intel_th_driver {
 157        struct device_driver    driver;
 158        int                     (*probe)(struct intel_th_device *thdev);
 159        void                    (*remove)(struct intel_th_device *thdev);
 160        /* switch (GTH) ops */
 161        int                     (*assign)(struct intel_th_device *thdev,
 162                                          struct intel_th_device *othdev);
 163        void                    (*unassign)(struct intel_th_device *thdev,
 164                                            struct intel_th_device *othdev);
 165        void                    (*enable)(struct intel_th_device *thdev,
 166                                          struct intel_th_output *output);
 167        void                    (*trig_switch)(struct intel_th_device *thdev,
 168                                               struct intel_th_output *output);
 169        void                    (*disable)(struct intel_th_device *thdev,
 170                                           struct intel_th_output *output);
 171        /* output ops */
 172        irqreturn_t             (*irq)(struct intel_th_device *thdev);
 173        void                    (*wait_empty)(struct intel_th_device *thdev);
 174        int                     (*activate)(struct intel_th_device *thdev);
 175        void                    (*deactivate)(struct intel_th_device *thdev);
 176        /* file_operations for those who want a device node */
 177        const struct file_operations *fops;
 178        /* optional attributes */
 179        struct attribute_group  *attr_group;
 180
 181        /* source ops */
 182        int                     (*set_output)(struct intel_th_device *thdev,
 183                                              unsigned int master);
 184};
 185
 186#define to_intel_th_driver(_d)                                  \
 187        container_of((_d), struct intel_th_driver, driver)
 188
 189#define to_intel_th_driver_or_null(_d)          \
 190        ((_d) ? to_intel_th_driver(_d) : NULL)
 191
 192/*
 193 * Subdevice tree structure is as follows:
 194 * + struct intel_th device (pci; dev_{get,set}_drvdata()
 195 *   + struct intel_th_device INTEL_TH_SWITCH (GTH)
 196 *     + struct intel_th_device INTEL_TH_OUTPUT (MSU, PTI)
 197 *   + struct intel_th_device INTEL_TH_SOURCE (STH)
 198 *
 199 * In other words, INTEL_TH_OUTPUT devices are children of INTEL_TH_SWITCH;
 200 * INTEL_TH_SWITCH and INTEL_TH_SOURCE are children of the intel_th device.
 201 */
 202static inline struct intel_th_device *
 203to_intel_th_parent(struct intel_th_device *thdev)
 204{
 205        struct device *parent = thdev->dev.parent;
 206
 207        if (!parent)
 208                return NULL;
 209
 210        return to_intel_th_device(parent);
 211}
 212
 213static inline struct intel_th *to_intel_th(struct intel_th_device *thdev)
 214{
 215        if (thdev->type == INTEL_TH_OUTPUT)
 216                thdev = to_intel_th_parent(thdev);
 217
 218        if (WARN_ON_ONCE(!thdev || thdev->type == INTEL_TH_OUTPUT))
 219                return NULL;
 220
 221        return dev_get_drvdata(thdev->dev.parent);
 222}
 223
 224struct intel_th *
 225intel_th_alloc(struct device *dev, struct intel_th_drvdata *drvdata,
 226               struct resource *devres, unsigned int ndevres);
 227void intel_th_free(struct intel_th *th);
 228
 229int intel_th_driver_register(struct intel_th_driver *thdrv);
 230void intel_th_driver_unregister(struct intel_th_driver *thdrv);
 231
 232int intel_th_trace_enable(struct intel_th_device *thdev);
 233int intel_th_trace_switch(struct intel_th_device *thdev);
 234int intel_th_trace_disable(struct intel_th_device *thdev);
 235int intel_th_set_output(struct intel_th_device *thdev,
 236                        unsigned int master);
 237int intel_th_output_enable(struct intel_th *th, unsigned int otype);
 238
 239enum th_mmio_idx {
 240        TH_MMIO_CONFIG = 0,
 241        TH_MMIO_SW = 1,
 242        TH_MMIO_RTIT = 2,
 243        TH_MMIO_END,
 244};
 245
 246#define TH_POSSIBLE_OUTPUTS     8
 247/* Total number of possible subdevices: outputs + GTH + STH */
 248#define TH_SUBDEVICE_MAX        (TH_POSSIBLE_OUTPUTS + 2)
 249#define TH_CONFIGURABLE_MASTERS 256
 250#define TH_MSC_MAX              2
 251
 252/* Maximum IRQ vectors */
 253#define TH_NVEC_MAX             8
 254
 255/**
 256 * struct intel_th - Intel TH controller
 257 * @dev:        driver core's device
 258 * @thdev:      subdevices
 259 * @hub:        "switch" subdevice (GTH)
 260 * @resource:   resources of the entire controller
 261 * @num_thdevs: number of devices in the @thdev array
 262 * @num_resources:      number of resources in the @resource array
 263 * @irq:        irq number
 264 * @id:         this Intel TH controller's device ID in the system
 265 * @major:      device node major for output devices
 266 */
 267struct intel_th {
 268        struct device           *dev;
 269
 270        struct intel_th_device  *thdev[TH_SUBDEVICE_MAX];
 271        struct intel_th_device  *hub;
 272        struct intel_th_drvdata *drvdata;
 273
 274        struct resource         resource[TH_MMIO_END];
 275        int                     (*activate)(struct intel_th *);
 276        void                    (*deactivate)(struct intel_th *);
 277        unsigned int            num_thdevs;
 278        unsigned int            num_resources;
 279        int                     irq;
 280
 281        int                     id;
 282        int                     major;
 283#ifdef CONFIG_MODULES
 284        struct work_struct      request_module_work;
 285#endif /* CONFIG_MODULES */
 286#ifdef CONFIG_INTEL_TH_DEBUG
 287        struct dentry           *dbg;
 288#endif
 289};
 290
 291static inline struct intel_th_device *
 292to_intel_th_hub(struct intel_th_device *thdev)
 293{
 294        if (thdev->type == INTEL_TH_SWITCH)
 295                return thdev;
 296        else if (thdev->type == INTEL_TH_OUTPUT)
 297                return to_intel_th_parent(thdev);
 298
 299        return to_intel_th(thdev)->hub;
 300}
 301
 302/*
 303 * Register windows
 304 */
 305enum {
 306        /* Global Trace Hub (GTH) */
 307        REG_GTH_OFFSET          = 0x0000,
 308        REG_GTH_LENGTH          = 0x2000,
 309
 310        /* Timestamp counter unit (TSCU) */
 311        REG_TSCU_OFFSET         = 0x2000,
 312        REG_TSCU_LENGTH         = 0x1000,
 313
 314        REG_CTS_OFFSET          = 0x3000,
 315        REG_CTS_LENGTH          = 0x1000,
 316
 317        /* Software Trace Hub (STH) [0x4000..0x4fff] */
 318        REG_STH_OFFSET          = 0x4000,
 319        REG_STH_LENGTH          = 0x2000,
 320
 321        /* Memory Storage Unit (MSU) [0xa0000..0xa1fff] */
 322        REG_MSU_OFFSET          = 0xa0000,
 323        REG_MSU_LENGTH          = 0x02000,
 324
 325        /* Internal MSU trace buffer [0x80000..0x9ffff] */
 326        BUF_MSU_OFFSET          = 0x80000,
 327        BUF_MSU_LENGTH          = 0x20000,
 328
 329        /* PTI output == same window as GTH */
 330        REG_PTI_OFFSET          = REG_GTH_OFFSET,
 331        REG_PTI_LENGTH          = REG_GTH_LENGTH,
 332
 333        /* DCI Handler (DCIH) == some window as MSU */
 334        REG_DCIH_OFFSET         = REG_MSU_OFFSET,
 335        REG_DCIH_LENGTH         = REG_MSU_LENGTH,
 336};
 337
 338/*
 339 * Scratchpad bits: tell firmware and external debuggers
 340 * what we are up to.
 341 */
 342enum {
 343        /* Memory is the primary destination */
 344        SCRPD_MEM_IS_PRIM_DEST          = BIT(0),
 345        /* XHCI DbC is the primary destination */
 346        SCRPD_DBC_IS_PRIM_DEST          = BIT(1),
 347        /* PTI is the primary destination */
 348        SCRPD_PTI_IS_PRIM_DEST          = BIT(2),
 349        /* BSSB is the primary destination */
 350        SCRPD_BSSB_IS_PRIM_DEST         = BIT(3),
 351        /* PTI is the alternate destination */
 352        SCRPD_PTI_IS_ALT_DEST           = BIT(4),
 353        /* BSSB is the alternate destination */
 354        SCRPD_BSSB_IS_ALT_DEST          = BIT(5),
 355        /* DeepSx exit occurred */
 356        SCRPD_DEEPSX_EXIT               = BIT(6),
 357        /* S4 exit occurred */
 358        SCRPD_S4_EXIT                   = BIT(7),
 359        /* S5 exit occurred */
 360        SCRPD_S5_EXIT                   = BIT(8),
 361        /* MSU controller 0/1 is enabled */
 362        SCRPD_MSC0_IS_ENABLED           = BIT(9),
 363        SCRPD_MSC1_IS_ENABLED           = BIT(10),
 364        /* Sx exit occurred */
 365        SCRPD_SX_EXIT                   = BIT(11),
 366        /* Trigger Unit is enabled */
 367        SCRPD_TRIGGER_IS_ENABLED        = BIT(12),
 368        SCRPD_ODLA_IS_ENABLED           = BIT(13),
 369        SCRPD_SOCHAP_IS_ENABLED         = BIT(14),
 370        SCRPD_STH_IS_ENABLED            = BIT(15),
 371        SCRPD_DCIH_IS_ENABLED           = BIT(16),
 372        SCRPD_VER_IS_ENABLED            = BIT(17),
 373        /* External debugger is using Intel TH */
 374        SCRPD_DEBUGGER_IN_USE           = BIT(24),
 375};
 376
 377#endif
 378