Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

intel_th: Add switch triggering support

Add support for asserting window switch trigger when tracing to MSU output
ports. This allows for software controlled switching between windows of
the MSU buffer, which can be used for double buffering while exporting the
trace data further from the MSU.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alexander Shishkin and committed by
Greg Kroah-Hartman
8116db57 9958e025

+85 -2
+23 -2
drivers/hwtracing/intel_th/core.c
··· 430 430 .nres = 1, 431 431 .res = { 432 432 { 433 - /* Handle TSCU from GTH driver */ 433 + /* Handle TSCU and CTS from GTH driver */ 434 434 .start = REG_GTH_OFFSET, 435 - .end = REG_TSCU_OFFSET + REG_TSCU_LENGTH - 1, 435 + .end = REG_CTS_OFFSET + REG_CTS_LENGTH - 1, 436 436 .flags = IORESOURCE_MEM, 437 437 }, 438 438 }, ··· 986 986 return 0; 987 987 } 988 988 EXPORT_SYMBOL_GPL(intel_th_trace_enable); 989 + 990 + /** 991 + * intel_th_trace_switch() - execute a switch sequence 992 + * @thdev: output device that requests tracing switch 993 + */ 994 + int intel_th_trace_switch(struct intel_th_device *thdev) 995 + { 996 + struct intel_th_device *hub = to_intel_th_device(thdev->dev.parent); 997 + struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver); 998 + 999 + if (WARN_ON_ONCE(hub->type != INTEL_TH_SWITCH)) 1000 + return -EINVAL; 1001 + 1002 + if (WARN_ON_ONCE(thdev->type != INTEL_TH_OUTPUT)) 1003 + return -EINVAL; 1004 + 1005 + hubdrv->trig_switch(hub, &thdev->output); 1006 + 1007 + return 0; 1008 + } 1009 + EXPORT_SYMBOL_GPL(intel_th_trace_switch); 989 1010 990 1011 /** 991 1012 * intel_th_trace_disable() - disable tracing for an output device
+37
drivers/hwtracing/intel_th/gth.c
··· 308 308 iowrite32(0, gth->base + REG_GTH_SCR); 309 309 iowrite32(0xfc, gth->base + REG_GTH_SCR2); 310 310 311 + /* setup CTS for single trigger */ 312 + iowrite32(CTS_EVENT_ENABLE_IF_ANYTHING, gth->base + REG_CTS_C0S0_EN); 313 + iowrite32(CTS_ACTION_CONTROL_SET_STATE(CTS_STATE_IDLE) | 314 + CTS_ACTION_CONTROL_TRIGGER, gth->base + REG_CTS_C0S0_ACT); 315 + 311 316 return 0; 312 317 } 313 318 ··· 600 595 } 601 596 602 597 /** 598 + * intel_th_gth_switch() - execute a switch sequence 599 + * @thdev: GTH device 600 + * @output: output device's descriptor 601 + * 602 + * This will execute a switch sequence that will trigger a switch window 603 + * when tracing to MSC in multi-block mode. 604 + */ 605 + static void intel_th_gth_switch(struct intel_th_device *thdev, 606 + struct intel_th_output *output) 607 + { 608 + struct gth_device *gth = dev_get_drvdata(&thdev->dev); 609 + unsigned long count; 610 + u32 reg; 611 + 612 + /* trigger */ 613 + iowrite32(0, gth->base + REG_CTS_CTL); 614 + iowrite32(CTS_CTL_SEQUENCER_ENABLE, gth->base + REG_CTS_CTL); 615 + /* wait on trigger status */ 616 + for (reg = 0, count = CTS_TRIG_WAITLOOP_DEPTH; 617 + count && !(reg & BIT(4)); count--) { 618 + reg = ioread32(gth->base + REG_CTS_STAT); 619 + cpu_relax(); 620 + } 621 + if (!count) 622 + dev_dbg(&thdev->dev, "timeout waiting for CTS Trigger\n"); 623 + 624 + intel_th_gth_stop(gth, output, false); 625 + intel_th_gth_start(gth, output); 626 + } 627 + 628 + /** 603 629 * intel_th_gth_assign() - assign output device to a GTH output port 604 630 * @thdev: GTH device 605 631 * @othdev: output device ··· 813 777 .unassign = intel_th_gth_unassign, 814 778 .set_output = intel_th_gth_set_output, 815 779 .enable = intel_th_gth_enable, 780 + .trig_switch = intel_th_gth_switch, 816 781 .disable = intel_th_gth_disable, 817 782 .driver = { 818 783 .name = "gth",
+19
drivers/hwtracing/intel_th/gth.h
··· 49 49 REG_GTH_SCRPD3 = 0xec, /* ScratchPad[3] */ 50 50 REG_TSCU_TSUCTRL = 0x2000, /* TSCU control register */ 51 51 REG_TSCU_TSCUSTAT = 0x2004, /* TSCU status register */ 52 + 53 + /* Common Capture Sequencer (CTS) registers */ 54 + REG_CTS_C0S0_EN = 0x30c0, /* clause_event_enable_c0s0 */ 55 + REG_CTS_C0S0_ACT = 0x3180, /* clause_action_control_c0s0 */ 56 + REG_CTS_STAT = 0x32a0, /* cts_status */ 57 + REG_CTS_CTL = 0x32a4, /* cts_control */ 52 58 }; 53 59 54 60 /* waiting for Pipeline Empty bit(s) to assert for GTH */ ··· 62 56 63 57 #define TSUCTRL_CTCRESYNC BIT(0) 64 58 #define TSCUSTAT_CTCSYNCING BIT(1) 59 + 60 + /* waiting for Trigger status to assert for CTS */ 61 + #define CTS_TRIG_WAITLOOP_DEPTH 10000 62 + 63 + #define CTS_EVENT_ENABLE_IF_ANYTHING BIT(31) 64 + #define CTS_ACTION_CONTROL_STATE_OFF 27 65 + #define CTS_ACTION_CONTROL_SET_STATE(x) \ 66 + (((x) & 0x1f) << CTS_ACTION_CONTROL_STATE_OFF) 67 + #define CTS_ACTION_CONTROL_TRIGGER BIT(4) 68 + 69 + #define CTS_STATE_IDLE 0x10u 70 + 71 + #define CTS_CTL_SEQUENCER_ENABLE BIT(0) 65 72 66 73 #endif /* __INTEL_TH_GTH_H__ */
+6
drivers/hwtracing/intel_th/intel_th.h
··· 164 164 struct intel_th_device *othdev); 165 165 void (*enable)(struct intel_th_device *thdev, 166 166 struct intel_th_output *output); 167 + void (*trig_switch)(struct intel_th_device *thdev, 168 + struct intel_th_output *output); 167 169 void (*disable)(struct intel_th_device *thdev, 168 170 struct intel_th_output *output); 169 171 /* output ops */ ··· 230 228 void intel_th_driver_unregister(struct intel_th_driver *thdrv); 231 229 232 230 int intel_th_trace_enable(struct intel_th_device *thdev); 231 + int intel_th_trace_switch(struct intel_th_device *thdev); 233 232 int intel_th_trace_disable(struct intel_th_device *thdev); 234 233 int intel_th_set_output(struct intel_th_device *thdev, 235 234 unsigned int master); ··· 310 307 /* Timestamp counter unit (TSCU) */ 311 308 REG_TSCU_OFFSET = 0x2000, 312 309 REG_TSCU_LENGTH = 0x1000, 310 + 311 + REG_CTS_OFFSET = 0x3000, 312 + REG_CTS_LENGTH = 0x1000, 313 313 314 314 /* Software Trace Hub (STH) [0x4000..0x4fff] */ 315 315 REG_STH_OFFSET = 0x4000,