xref: /OK3568_Linux_fs/kernel/Documentation/driver-api/pti_intel_mid.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun=============
4*4882a593SmuzhiyunIntel MID PTI
5*4882a593Smuzhiyun=============
6*4882a593Smuzhiyun
7*4882a593SmuzhiyunThe Intel MID PTI project is HW implemented in Intel Atom
8*4882a593Smuzhiyunsystem-on-a-chip designs based on the Parallel Trace
9*4882a593SmuzhiyunInterface for MIPI P1149.7 cJTAG standard.  The kernel solution
10*4882a593Smuzhiyunfor this platform involves the following files::
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun	./include/linux/pti.h
13*4882a593Smuzhiyun	./drivers/.../n_tracesink.h
14*4882a593Smuzhiyun	./drivers/.../n_tracerouter.c
15*4882a593Smuzhiyun	./drivers/.../n_tracesink.c
16*4882a593Smuzhiyun	./drivers/.../pti.c
17*4882a593Smuzhiyun
18*4882a593Smuzhiyunpti.c is the driver that enables various debugging features
19*4882a593Smuzhiyunpopular on platforms from certain mobile manufacturers.
20*4882a593Smuzhiyunn_tracerouter.c and n_tracesink.c allow extra system information to
21*4882a593Smuzhiyunbe collected and routed to the pti driver, such as trace
22*4882a593Smuzhiyundebugging data from a modem.  Although n_tracerouter
23*4882a593Smuzhiyunand n_tracesink are a part of the complete PTI solution,
24*4882a593Smuzhiyunthese two line disciplines can work separately from
25*4882a593Smuzhiyunpti.c and route any data stream from one /dev/tty node
26*4882a593Smuzhiyunto another /dev/tty node via kernel-space.  This provides
27*4882a593Smuzhiyuna stable, reliable connection that will not break unless
28*4882a593Smuzhiyunthe user-space application shuts down (plus avoids
29*4882a593Smuzhiyunkernel->user->kernel context switch overheads of routing
30*4882a593Smuzhiyundata).
31*4882a593Smuzhiyun
32*4882a593SmuzhiyunAn example debugging usage for this driver system:
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun  * Hook /dev/ttyPTI0 to syslogd.  Opening this port will also start
35*4882a593Smuzhiyun    a console device to further capture debugging messages to PTI.
36*4882a593Smuzhiyun  * Hook /dev/ttyPTI1 to modem debugging data to write to PTI HW.
37*4882a593Smuzhiyun    This is where n_tracerouter and n_tracesink are used.
38*4882a593Smuzhiyun  * Hook /dev/pti to a user-level debugging application for writing
39*4882a593Smuzhiyun    to PTI HW.
40*4882a593Smuzhiyun  * `Use mipi_` Kernel Driver API in other device drivers for
41*4882a593Smuzhiyun    debugging to PTI by first requesting a PTI write address via
42*4882a593Smuzhiyun    mipi_request_masterchannel(1).
43*4882a593Smuzhiyun
44*4882a593SmuzhiyunBelow is example pseudo-code on how a 'privileged' application
45*4882a593Smuzhiyuncan hook up n_tracerouter and n_tracesink to any tty on
46*4882a593Smuzhiyuna system.  'Privileged' means the application has enough
47*4882a593Smuzhiyunprivileges to successfully manipulate the ldisc drivers
48*4882a593Smuzhiyunbut is not just blindly executing as 'root'. Keep in mind
49*4882a593Smuzhiyunthe use of ioctl(,TIOCSETD,) is not specific to the n_tracerouter
50*4882a593Smuzhiyunand n_tracesink line discpline drivers but is a generic
51*4882a593Smuzhiyunoperation for a program to use a line discpline driver
52*4882a593Smuzhiyunon a tty port other than the default n_tty:
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun.. code-block:: c
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun  /////////// To hook up n_tracerouter and n_tracesink /////////
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun  // Note that n_tracerouter depends on n_tracesink.
59*4882a593Smuzhiyun  #include <errno.h>
60*4882a593Smuzhiyun  #define ONE_TTY "/dev/ttyOne"
61*4882a593Smuzhiyun  #define TWO_TTY "/dev/ttyTwo"
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun  // needed global to hand onto ldisc connection
64*4882a593Smuzhiyun  static int g_fd_source = -1;
65*4882a593Smuzhiyun  static int g_fd_sink  = -1;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun  // these two vars used to grab LDISC values from loaded ldisc drivers
68*4882a593Smuzhiyun  // in OS.  Look at /proc/tty/ldiscs to get the right numbers from
69*4882a593Smuzhiyun  // the ldiscs loaded in the system.
70*4882a593Smuzhiyun  int source_ldisc_num, sink_ldisc_num = -1;
71*4882a593Smuzhiyun  int retval;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun  g_fd_source = open(ONE_TTY, O_RDWR); // must be R/W
74*4882a593Smuzhiyun  g_fd_sink   = open(TWO_TTY, O_RDWR); // must be R/W
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun  if (g_fd_source <= 0) || (g_fd_sink <= 0) {
77*4882a593Smuzhiyun     // doubt you'll want to use these exact error lines of code
78*4882a593Smuzhiyun     printf("Error on open(). errno: %d\n",errno);
79*4882a593Smuzhiyun     return errno;
80*4882a593Smuzhiyun  }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun  retval = ioctl(g_fd_sink, TIOCSETD, &sink_ldisc_num);
83*4882a593Smuzhiyun  if (retval < 0) {
84*4882a593Smuzhiyun     printf("Error on ioctl().  errno: %d\n", errno);
85*4882a593Smuzhiyun     return errno;
86*4882a593Smuzhiyun  }
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun  retval = ioctl(g_fd_source, TIOCSETD, &source_ldisc_num);
89*4882a593Smuzhiyun  if (retval < 0) {
90*4882a593Smuzhiyun     printf("Error on ioctl().  errno: %d\n", errno);
91*4882a593Smuzhiyun     return errno;
92*4882a593Smuzhiyun  }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun  /////////// To disconnect n_tracerouter and n_tracesink ////////
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun  // First make sure data through the ldiscs has stopped.
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun  // Second, disconnect ldiscs.  This provides a
99*4882a593Smuzhiyun  // little cleaner shutdown on tty stack.
100*4882a593Smuzhiyun  sink_ldisc_num = 0;
101*4882a593Smuzhiyun  source_ldisc_num = 0;
102*4882a593Smuzhiyun  ioctl(g_fd_uart, TIOCSETD, &sink_ldisc_num);
103*4882a593Smuzhiyun  ioctl(g_fd_gadget, TIOCSETD, &source_ldisc_num);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun  // Three, program closes connection, and cleanup:
106*4882a593Smuzhiyun  close(g_fd_uart);
107*4882a593Smuzhiyun  close(g_fd_gadget);
108*4882a593Smuzhiyun  g_fd_uart = g_fd_gadget = NULL;
109