From b8d7c870bcee6b9a2e76789c47ea94b6f8f183e6 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 20 Oct 2011 09:54:52 +0200 Subject: STM: MIPI System Trace Module char driver Change-Id: I5a53335d41ac1ecda02dc61d68a418a0039ebdff Signed-off-by: Philippe Langlais Signed-off-by: Robert Marklund --- Documentation/trace/stm-trace.txt | 193 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 Documentation/trace/stm-trace.txt (limited to 'Documentation') diff --git a/Documentation/trace/stm-trace.txt b/Documentation/trace/stm-trace.txt new file mode 100644 index 00000000000..cd73c2b87b7 --- /dev/null +++ b/Documentation/trace/stm-trace.txt @@ -0,0 +1,193 @@ + MIPI System Trace Module driver + =============================== + +Copyright (C) ST-Ericsson SA 2011 + Authors: Pierre Peiffer + Philippe Langlais + License: The GNU Free Documentation License, Version 1.2 + (dual licensed under the GPL v2) + +Hardware overview +================= + This hardware collects and provides simple tracepoints, + so a system processor (in our case the main ARM CPU, + or some small CPUs and DSPs) can write some data, + up to 8 bytes, into a register and out comes a log entry + with a time stamp (20ns resolution) on one of 256 channels. Also + hardware tracepoints are supported. + + This module external interface is a pad on the chip + which complies to the MIPI System Trace Protocol v1.0 + (see http://www.mipi.org/specifications/debug) + and the actual trace output can be read by an + electronic probe, not by software so it cannot be intercepted by + the CPU and reach Linux userspace. + + Bandwidth depends on number of lines & bus frequency (for example on ux500 + SoC 4 lines at max 100MHz eg max 400Mbit/s shared between 7 cores). + Transmit FIFO size: 256 samples up to 8 bytes. + On ux500 platform there is 2 contiguous STM blocks (eg 512 channels) + +Software Overview +================= + Write atomicity and write order on STM trace channels is ensured by the fact + we try to allocate one channel by execution thread (no concurrent access). + There is 2 modes one lossless but intrusive aka Software mode and + another lossy mode less intrusive aka Hardware mode, by default + all sources are configured in Hardware mode and enabled. + The end of data packet is marked by a time stamp on latest byte(s) only. + +Kernel API +---------- + Configuration functions: + output trace clock frequency, trace mode, output port configuration + and enable/disable STM trace sources + Expose a debugfs interface too for STM trace control + + Alloc/free STM trace channel functions + + Set of low level atomic trace functions for 1, 2, 4 or 8 bytes + with & w/o time stamp + + Higher level lockless trace functions: + stm_trace_buffer: + allocate a channel in 128 highest channels available + output the trace buffer with arbitrary length + (latest byte(s) automatically time stamped) then free the channel + stm_trace_buffer_onchannel: + use given channel to output the trace buffer + with arbitrary length (latest byte(s) automatically time stamped) + + File IO output console like interface (open, close, write) + + See & drivers/misc/stm.c for more detail + +debugfs API +----------- +clockdiv: + This is used to set or display the current clock divisor + that is configured + +connection: + This is used to set or display the current output connector + that is configured (common values, 0 not connected, 1 for default + connection, 3 on Ux500 for APE MIPI34 connection) + +free_channels: + This is used to display the total number of free channels + +masters_enable: + This sets or displays whether the STM trace sources + are activated. Each bits represent the state of corresponding source: + 0 for disable or 1 to enable it. + +masters_modes: + This sets or displays the STM trace sources modes. + Each bits represent the mode of corresponding source: + 0 for Sofware lossless mode or 1 for Hardware lossy mode. + +User API +-------- + IOCTLs or debugfs for controls + 2 levels API for tracing: + - Standard write function, in this case a channel is automatically + allocated at first write, after you can channel number + with IOCTL STM_GET_CHANNEL_NO + - mmap for direct access of all STM trace channels port plus + a set of IOCTLs for alloc/free channels, in this case you can + write your own lib to easiest its usage + +Examples of using the STM +========================= +First mount debugfs with: +mount -t debugfs none /sys/kernel/debug + +In a shell scipt +---------------- +It's as easy as: + echo "My trace point" > /dev/stm + +To avoid trace overflow, increase STM clock by decreasing the clockdiv with: + echo 1 >/sys/kernel/debug/stm/clockdiv # now use DIV2 instead of default DIV8 +If not enough you can disable some sources with: + echo YourEnableSources > /sys/kernel/debug/stm/masters_enable +If always not enough the ultime intrusive way is to change the sources mode +and set the corresponding sources in Software mode (set corresponding source +bit to 0) with: + echo YourModeSources > /sys/kernel/debug/stm/masters_modes + (be aware some source doesn't support Software mode => keep it in HW mode) + +NB: on Ux500 platform, first you have to configure STM output port to switch +APE tracing on MIPI34 connector with: + echo 3 > /sys/kernel/debug/stm/connection + +In C language +------------- + +The easy way more intrusive (with STM buffer recopy): + +#include + +int fd, i; +char buf[1024]; // Try to align this buffer on 64 bits if possible + + fd = open("/dev/stm", O_WRONLY); + snprintf(buf, 1024, "STM0 Hello world\n"); + write(fd, buf, strlen(buf)); + ioctl(fd, STM_GET_CHANNEL_NO, &i); + snprintf(buf, 1024, "Use channel #%d\n", i); + write(fd, buf, strlen(buf)); + close(fd); + +NB: You can call open("/dev/stm", O_WRONLY) as many times as necessary +to allocate a different channel to avoid concurrency in your +multithreaded application. + +The more efficient way, use mmap'ed STM channels memory (to put in a lib): + +#include + +int fd, i, c, l, maxChannels; +char buf[1024]; // Try to align this buffer on 64 bits if possible +volatile struct stm_channel *channels; // mmap'ed channels area + + fd = open("/dev/stm", O_RDWR); + ioctl(fd0, STM_GET_NB_MAX_CHANNELS, &maxChannels); + channels = (struct stm_channel *)mmap(0, maxChannels*sizeof(*channels), + PROT_WRITE, MAP_SHARED, fd, 0); + assert(channels != MAP_FAILED); + + if (!ioctl(fd, STM_GET_FREE_CHANNEL, &c)) { + l = snprintf(buf, 1024, "STM0 Hello world on channel #%d\n", c); + // lazy implementation you have to send buffer by 8 Bytes when possible + // and be sure you don't share this channel with others threads + for (i=0; i