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