1=================================
2Intel Integrated Sensor Hub (ISH)
3=================================
4
5A sensor hub enables the ability to offload sensor polling and algorithm
6processing to a dedicated low power co-processor. This allows the core
7processor to go into low power modes more often, resulting in the increased
8battery life.
9
10There are many vendors providing external sensor hubs confirming to HID
11Sensor usage tables, and used in several tablets, 2 in 1 convertible laptops
12and embedded products. Linux had this support since Linux 3.9.
13
14Intel® introduced integrated sensor hubs as a part of the SoC starting from
15Cherry Trail and now supported on multiple generations of CPU packages. There
16are many commercial devices already shipped with Integrated Sensor Hubs (ISH).
17These ISH also comply to HID sensor specification, but the  difference is the
18transport protocol used for communication. The current external sensor hubs
19mainly use HID over i2C or USB. But ISH doesn't use either i2c or USB.
20
211. Overview
22===========
23
24Using a analogy with a usbhid implementation, the ISH follows a similar model
25for a very high speed communication::
26
27	-----------------		----------------------
28	|    USB HID	|	-->	|    ISH HID	     |
29	-----------------		----------------------
30	-----------------		----------------------
31	|  USB protocol	|	-->	|    ISH Transport   |
32	-----------------		----------------------
33	-----------------		----------------------
34	|  EHCI/XHCI	|	-->	|    ISH IPC	     |
35	-----------------		----------------------
36	      PCI				 PCI
37	-----------------		----------------------
38        |Host controller|	-->	|    ISH processor   |
39	-----------------		----------------------
40	     USB Link
41	-----------------		----------------------
42	| USB End points|	-->	|    ISH Clients     |
43	-----------------		----------------------
44
45Like USB protocol provides a method for device enumeration, link management
46and user data encapsulation, the ISH also provides similar services. But it is
47very light weight tailored to manage and communicate with ISH client
48applications implemented in the firmware.
49
50The ISH allows multiple sensor management applications executing in the
51firmware. Like USB endpoints the messaging can be to/from a client. As part of
52enumeration process, these clients are identified. These clients can be simple
53HID sensor applications, sensor calibration application or senor firmware
54update application.
55
56The implementation model is similar, like USB bus, ISH transport is also
57implemented as a bus. Each client application executing in the ISH processor
58is registered as a device on this bus. The driver, which binds each device
59(ISH HID driver) identifies the device type and registers with the hid core.
60
612. ISH Implementation: Block Diagram
62====================================
63
64::
65
66	 ---------------------------
67	|  User Space Applications  |
68	 ---------------------------
69
70  ----------------IIO ABI----------------
71	 --------------------------
72	|  IIO Sensor Drivers	  |
73	 --------------------------
74	 --------------------------
75	|	 IIO core	  |
76	 --------------------------
77	 --------------------------
78	|   HID Sensor Hub MFD	  |
79	 --------------------------
80	 --------------------------
81	|       HID Core	  |
82	 --------------------------
83	 --------------------------
84	|   HID over ISH Client   |
85	 --------------------------
86	 --------------------------
87	|   ISH Transport (ISHTP) |
88	 --------------------------
89	 --------------------------
90	|      IPC Drivers	  |
91	 --------------------------
92  OS
93  ---------------- PCI -----------------
94  Hardware + Firmware
95	 ----------------------------
96	| ISH Hardware/Firmware(FW) |
97	 ----------------------------
98
993. High level processing in above blocks
100========================================
101
1023.1 Hardware Interface
103----------------------
104
105The ISH is exposed as "Non-VGA unclassified PCI device" to the host. The PCI
106product and vendor IDs are changed from different generations of processors. So
107the source code which enumerate drivers needs to update from generation to
108generation.
109
1103.2 Inter Processor Communication (IPC) driver
111----------------------------------------------
112
113Location: drivers/hid/intel-ish-hid/ipc
114
115The IPC message used memory mapped I/O. The registers are defined in
116hw-ish-regs.h.
117
1183.2.1 IPC/FW message types
119^^^^^^^^^^^^^^^^^^^^^^^^^^
120
121There are two types of messages, one for management of link and other messages
122are to and from transport layers.
123
124TX and RX of Transport messages
125...............................
126
127A set of memory mapped register offers support of multi byte messages TX and
128RX (E.g.IPC_REG_ISH2HOST_MSG, IPC_REG_HOST2ISH_MSG). The IPC layer maintains
129internal queues to sequence messages and send them in order to the FW.
130Optionally the caller can register handler to get notification of completion.
131A door bell mechanism is used in messaging to trigger processing in host and
132client firmware side. When ISH interrupt handler is called, the ISH2HOST
133doorbell register is used by host drivers to determine that the interrupt
134is for ISH.
135
136Each side has 32 32-bit message registers and a 32-bit doorbell. Doorbell
137register has the following format:
138Bits 0..6: fragment length (7 bits are used)
139Bits 10..13: encapsulated protocol
140Bits 16..19: management command (for IPC management protocol)
141Bit 31: doorbell trigger (signal H/W interrupt to the other side)
142Other bits are reserved, should be 0.
143
1443.2.2 Transport layer interface
145^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
146
147To abstract HW level IPC communication, a set of callbacks are registered.
148The transport layer uses them to send and receive messages.
149Refer to  struct ishtp_hw_ops for callbacks.
150
1513.3 ISH Transport layer
152-----------------------
153
154Location: drivers/hid/intel-ish-hid/ishtp/
155
1563.3.1 A Generic Transport Layer
157^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
158
159The transport layer is a bi-directional protocol, which defines:
160- Set of commands to start, stop, connect, disconnect and flow control
161(ishtp/hbm.h) for details
162- A flow control mechanism to avoid buffer overflows
163
164This protocol resembles bus messages described in the following document:
165http://www.intel.com/content/dam/www/public/us/en/documents/technical-\
166specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer"
167
1683.3.2 Connection and Flow Control Mechanism
169^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
170
171Each FW client and a protocol is identified by an UUID. In order to communicate
172to a FW client, a connection must be established using connect request and
173response bus messages. If successful, a pair (host_client_id and fw_client_id)
174will identify the connection.
175
176Once connection is established, peers send each other flow control bus messages
177independently. Every peer may send a message only if it has received a
178flow-control credit before. Once it sent a message, it may not send another one
179before receiving the next flow control credit.
180Either side can send disconnect request bus message to end communication. Also
181the link will be dropped if major FW reset occurs.
182
1833.3.3 Peer to Peer data transfer
184^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
185
186Peer to Peer data transfer can happen with or without using DMA. Depending on
187the sensor bandwidth requirement DMA can be enabled by using module parameter
188ishtp_use_dma under intel_ishtp.
189
190Each side (host and FW) manages its DMA transfer memory independently. When an
191ISHTP client from either host or FW side wants to send something, it decides
192whether to send over IPC or over DMA; for each transfer the decision is
193independent. The sending side sends DMA_XFER message when the message is in
194the respective host buffer (TX when host client sends, RX when FW client
195sends). The recipient of DMA message responds with DMA_XFER_ACK, indicating
196the sender that the memory region for that message may be reused.
197
198DMA initialization is started with host sending DMA_ALLOC_NOTIFY bus message
199(that includes RX buffer) and FW responds with DMA_ALLOC_NOTIFY_ACK.
200Additionally to DMA address communication, this sequence checks capabilities:
201if thw host doesn't support DMA, then it won't send DMA allocation, so FW can't
202send DMA; if FW doesn't support DMA then it won't respond with
203DMA_ALLOC_NOTIFY_ACK, in which case host will not use DMA transfers.
204Here ISH acts as busmaster DMA controller. Hence when host sends DMA_XFER,
205it's request to do host->ISH DMA transfer; when FW sends DMA_XFER, it means
206that it already did DMA and the message resides at host. Thus, DMA_XFER
207and DMA_XFER_ACK act as ownership indicators.
208
209At initial state all outgoing memory belongs to the sender (TX to host, RX to
210FW), DMA_XFER transfers ownership on the region that contains ISHTP message to
211the receiving side, DMA_XFER_ACK returns ownership to the sender. A sender
212needs not wait for previous DMA_XFER to be ack'ed, and may send another message
213as long as remaining continuous memory in its ownership is enough.
214In principle, multiple DMA_XFER and DMA_XFER_ACK messages may be sent at once
215(up to IPC MTU), thus allowing for interrupt throttling.
216Currently, ISH FW decides to send over DMA if ISHTP message is more than 3 IPC
217fragments and via IPC otherwise.
218
2193.3.4 Ring Buffers
220^^^^^^^^^^^^^^^^^^
221
222When a client initiate a connection, a ring or RX and TX buffers are allocated.
223The size of ring can be specified by the client. HID client set 16 and 32 for
224TX and RX buffers respectively. On send request from client, the data to be
225sent is copied to one of the send ring buffer and scheduled to be sent using
226bus message protocol. These buffers are required because the FW may have not
227have processed the last message and may not have enough flow control credits
228to send. Same thing holds true on receive side and flow control is required.
229
2303.3.5 Host Enumeration
231^^^^^^^^^^^^^^^^^^^^^^
232
233The host enumeration bus command allow discovery of clients present in the FW.
234There can be multiple sensor clients and clients for calibration function.
235
236To ease in implantation and allow independent driver handle each client
237this transport layer takes advantage of Linux Bus driver model. Each
238client is registered as device on the the transport bus (ishtp bus).
239
240Enumeration sequence of messages:
241
242- Host sends HOST_START_REQ_CMD, indicating that host ISHTP layer is up.
243- FW responds with HOST_START_RES_CMD
244- Host sends HOST_ENUM_REQ_CMD (enumerate FW clients)
245- FW responds with HOST_ENUM_RES_CMD that includes bitmap of available FW
246  client IDs
247- For each FW ID found in that bitmap host sends
248  HOST_CLIENT_PROPERTIES_REQ_CMD
249- FW responds with HOST_CLIENT_PROPERTIES_RES_CMD. Properties include UUID,
250  max ISHTP message size, etc.
251- Once host received properties for that last discovered client, it considers
252  ISHTP device fully functional (and allocates DMA buffers)
253
2543.4 HID over ISH Client
255-----------------------
256
257Location: drivers/hid/intel-ish-hid
258
259The ISHTP client driver is responsible for:
260
261- enumerate HID devices under FW ISH client
262- Get Report descriptor
263- Register with HID core as a LL driver
264- Process Get/Set feature request
265- Get input reports
266
2673.5 HID Sensor Hub MFD and IIO sensor drivers
268---------------------------------------------
269
270The functionality in these drivers is the same as an external sensor hub.
271Refer to
272Documentation/hid/hid-sensor.rst for HID sensor
273Documentation/ABI/testing/sysfs-bus-iio for IIO ABIs to user space
274
2753.6 End to End HID transport Sequence Diagram
276---------------------------------------------
277
278::
279
280  HID-ISH-CLN                    ISHTP                    IPC                             HW
281          |                        |                       |                               |
282          |                        |                       |-----WAKE UP------------------>|
283          |                        |                       |                               |
284          |                        |                       |-----HOST READY--------------->|
285          |                        |                       |                               |
286          |                        |                       |<----MNG_RESET_NOTIFY_ACK----- |
287          |                        |                       |                               |
288          |                        |<----ISHTP_START------ |                               |
289          |                        |                       |                               |
290          |                        |<-----------------HOST_START_RES_CMD-------------------|
291          |                        |                       |                               |
292          |                        |------------------QUERY_SUBSCRIBER-------------------->|
293          |                        |                       |                               |
294          |                        |------------------HOST_ENUM_REQ_CMD------------------->|
295          |                        |                       |                               |
296          |                        |<-----------------HOST_ENUM_RES_CMD--------------------|
297          |                        |                       |                               |
298          |                        |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>|
299          |                        |                       |                               |
300          |                        |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------|
301          |       Create new device on in ishtp bus        |                               |
302          |                        |                       |                               |
303          |                        |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>|
304          |                        |                       |                               |
305          |                        |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------|
306          |       Create new device on in ishtp bus        |                               |
307          |                        |                       |                               |
308          |                        |--Repeat HOST_CLIENT_PROPERTIES_REQ_CMD-till last one--|
309          |                        |                       |                               |
310       probed()
311          |----ishtp_cl_connect--->|----------------- CLIENT_CONNECT_REQ_CMD-------------->|
312          |                        |                       |                               |
313          |                        |<----------------CLIENT_CONNECT_RES_CMD----------------|
314          |                        |                       |                               |
315          |register event callback |                       |                               |
316          |                        |                       |                               |
317          |ishtp_cl_send(
318          HOSTIF_DM_ENUM_DEVICES)  |----------fill ishtp_msg_hdr struct write to HW-----  >|
319          |                        |                       |                               |
320          |                        |                       |<-----IRQ(IPC_PROTOCOL_ISHTP---|
321          |                        |                       |                               |
322          |<--ENUM_DEVICE RSP------|                       |                               |
323          |                        |                       |                               |
324  for each enumerated device
325          |ishtp_cl_send(
326          HOSTIF_GET_HID_DESCRIPTOR|----------fill ishtp_msg_hdr struct write to HW-----  >|
327          |                        |                       |                               |
328          ...Response
329          |                        |                       |                               |
330  for each enumerated device
331          |ishtp_cl_send(
332       HOSTIF_GET_REPORT_DESCRIPTOR|--------------fill ishtp_msg_hdr struct write to HW-- >|
333          |                        |                       |                               |
334          |                        |                       |                               |
335   hid_allocate_device
336          |                        |                       |                               |
337   hid_add_device                  |                       |                               |
338          |                        |                       |                               |
339
340
3413.7 ISH Debugging
342-----------------
343
344To debug ISH, event tracing mechanism is used. To enable debug logs
345echo 1 > /sys/kernel/debug/tracing/events/intel_ish/enable
346cat sys/kernel/debug/tracing/trace
347
3483.8 ISH IIO sysfs Example on Lenovo thinkpad Yoga 260
349-----------------------------------------------------
350
351::
352
353  root@otcpl-ThinkPad-Yoga-260:~# tree -l /sys/bus/iio/devices/
354  /sys/bus/iio/devices/
355  ├── iio:device0 -> ../../../devices/0044:8086:22D8.0001/HID-SENSOR-200073.9.auto/iio:device0
356  │   ├── buffer
357  │   │   ├── enable
358  │   │   ├── length
359  │   │   └── watermark
360  ...
361  │   ├── in_accel_hysteresis
362  │   ├── in_accel_offset
363  │   ├── in_accel_sampling_frequency
364  │   ├── in_accel_scale
365  │   ├── in_accel_x_raw
366  │   ├── in_accel_y_raw
367  │   ├── in_accel_z_raw
368  │   ├── name
369  │   ├── scan_elements
370  │   │   ├── in_accel_x_en
371  │   │   ├── in_accel_x_index
372  │   │   ├── in_accel_x_type
373  │   │   ├── in_accel_y_en
374  │   │   ├── in_accel_y_index
375  │   │   ├── in_accel_y_type
376  │   │   ├── in_accel_z_en
377  │   │   ├── in_accel_z_index
378  │   │   └── in_accel_z_type
379  ...
380  │   │   ├── devices
381  │   │   │   │   ├── buffer
382  │   │   │   │   │   ├── enable
383  │   │   │   │   │   ├── length
384  │   │   │   │   │   └── watermark
385  │   │   │   │   ├── dev
386  │   │   │   │   ├── in_intensity_both_raw
387  │   │   │   │   ├── in_intensity_hysteresis
388  │   │   │   │   ├── in_intensity_offset
389  │   │   │   │   ├── in_intensity_sampling_frequency
390  │   │   │   │   ├── in_intensity_scale
391  │   │   │   │   ├── name
392  │   │   │   │   ├── scan_elements
393  │   │   │   │   │   ├── in_intensity_both_en
394  │   │   │   │   │   ├── in_intensity_both_index
395  │   │   │   │   │   └── in_intensity_both_type
396  │   │   │   │   ├── trigger
397  │   │   │   │   │   └── current_trigger
398  ...
399  │   │   │   │   ├── buffer
400  │   │   │   │   │   ├── enable
401  │   │   │   │   │   ├── length
402  │   │   │   │   │   └── watermark
403  │   │   │   │   ├── dev
404  │   │   │   │   ├── in_magn_hysteresis
405  │   │   │   │   ├── in_magn_offset
406  │   │   │   │   ├── in_magn_sampling_frequency
407  │   │   │   │   ├── in_magn_scale
408  │   │   │   │   ├── in_magn_x_raw
409  │   │   │   │   ├── in_magn_y_raw
410  │   │   │   │   ├── in_magn_z_raw
411  │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_raw
412  │   │   │   │   ├── in_rot_hysteresis
413  │   │   │   │   ├── in_rot_offset
414  │   │   │   │   ├── in_rot_sampling_frequency
415  │   │   │   │   ├── in_rot_scale
416  │   │   │   │   ├── name
417  ...
418  │   │   │   │   ├── scan_elements
419  │   │   │   │   │   ├── in_magn_x_en
420  │   │   │   │   │   ├── in_magn_x_index
421  │   │   │   │   │   ├── in_magn_x_type
422  │   │   │   │   │   ├── in_magn_y_en
423  │   │   │   │   │   ├── in_magn_y_index
424  │   │   │   │   │   ├── in_magn_y_type
425  │   │   │   │   │   ├── in_magn_z_en
426  │   │   │   │   │   ├── in_magn_z_index
427  │   │   │   │   │   ├── in_magn_z_type
428  │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_en
429  │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_index
430  │   │   │   │   │   └── in_rot_from_north_magnetic_tilt_comp_type
431  │   │   │   │   ├── trigger
432  │   │   │   │   │   └── current_trigger
433  ...
434  │   │   │   │   ├── buffer
435  │   │   │   │   │   ├── enable
436  │   │   │   │   │   ├── length
437  │   │   │   │   │   └── watermark
438  │   │   │   │   ├── dev
439  │   │   │   │   ├── in_anglvel_hysteresis
440  │   │   │   │   ├── in_anglvel_offset
441  │   │   │   │   ├── in_anglvel_sampling_frequency
442  │   │   │   │   ├── in_anglvel_scale
443  │   │   │   │   ├── in_anglvel_x_raw
444  │   │   │   │   ├── in_anglvel_y_raw
445  │   │   │   │   ├── in_anglvel_z_raw
446  │   │   │   │   ├── name
447  │   │   │   │   ├── scan_elements
448  │   │   │   │   │   ├── in_anglvel_x_en
449  │   │   │   │   │   ├── in_anglvel_x_index
450  │   │   │   │   │   ├── in_anglvel_x_type
451  │   │   │   │   │   ├── in_anglvel_y_en
452  │   │   │   │   │   ├── in_anglvel_y_index
453  │   │   │   │   │   ├── in_anglvel_y_type
454  │   │   │   │   │   ├── in_anglvel_z_en
455  │   │   │   │   │   ├── in_anglvel_z_index
456  │   │   │   │   │   └── in_anglvel_z_type
457  │   │   │   │   ├── trigger
458  │   │   │   │   │   └── current_trigger
459  ...
460  │   │   │   │   ├── buffer
461  │   │   │   │   │   ├── enable
462  │   │   │   │   │   ├── length
463  │   │   │   │   │   └── watermark
464  │   │   │   │   ├── dev
465  │   │   │   │   ├── in_anglvel_hysteresis
466  │   │   │   │   ├── in_anglvel_offset
467  │   │   │   │   ├── in_anglvel_sampling_frequency
468  │   │   │   │   ├── in_anglvel_scale
469  │   │   │   │   ├── in_anglvel_x_raw
470  │   │   │   │   ├── in_anglvel_y_raw
471  │   │   │   │   ├── in_anglvel_z_raw
472  │   │   │   │   ├── name
473  │   │   │   │   ├── scan_elements
474  │   │   │   │   │   ├── in_anglvel_x_en
475  │   │   │   │   │   ├── in_anglvel_x_index
476  │   │   │   │   │   ├── in_anglvel_x_type
477  │   │   │   │   │   ├── in_anglvel_y_en
478  │   │   │   │   │   ├── in_anglvel_y_index
479  │   │   │   │   │   ├── in_anglvel_y_type
480  │   │   │   │   │   ├── in_anglvel_z_en
481  │   │   │   │   │   ├── in_anglvel_z_index
482  │   │   │   │   │   └── in_anglvel_z_type
483  │   │   │   │   ├── trigger
484  │   │   │   │   │   └── current_trigger
485  ...
486