xref: /linux/Documentation/hid/intel-ish-hid.rst (revision 3f41368fbfe1b3d5922d317fe1a0a0cab6846802)
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 increased
8battery life.
9
10There are many vendors providing external sensor hubs conforming to HID
11Sensor usage tables. These may be found in tablets, 2-in-1 convertible laptops
12and embedded products. Linux has 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
21Overview
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 applications or sensor firmware
54update applications.
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
61ISH 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
99High level processing in above blocks
100=====================================
101
102Hardware 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 enumerates drivers needs to update from generation to
108generation.
109
110Inter Processor Communication (IPC) driver
111------------------------------------------
112
113Location: drivers/hid/intel-ish-hid/ipc
114
115The IPC message uses memory mapped I/O. The registers are defined in
116hw-ish-regs.h.
117
118IPC/FW message types
119^^^^^^^^^^^^^^^^^^^^
120
121There are two types of messages, one for management of link and another for
122messages 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 firmware.
130Optionally the caller can register handler to get notification of completion.
131A doorbell 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::
138
139  Bits 0..6: fragment length (7 bits are used)
140  Bits 10..13: encapsulated protocol
141  Bits 16..19: management command (for IPC management protocol)
142  Bit 31: doorbell trigger (signal H/W interrupt to the other side)
143  Other bits are reserved, should be 0.
144
145Transport layer interface
146^^^^^^^^^^^^^^^^^^^^^^^^^
147
148To abstract HW level IPC communication, a set of callbacks is registered.
149The transport layer uses them to send and receive messages.
150Refer to struct ishtp_hw_ops for callbacks.
151
152ISH Transport layer
153-------------------
154
155Location: drivers/hid/intel-ish-hid/ishtp/
156
157A Generic Transport Layer
158^^^^^^^^^^^^^^^^^^^^^^^^^
159
160The transport layer is a bi-directional protocol, which defines:
161- Set of commands to start, stop, connect, disconnect and flow control
162(see ishtp/hbm.h for details)
163- A flow control mechanism to avoid buffer overflows
164
165This protocol resembles bus messages described in the following document:
166http://www.intel.com/content/dam/www/public/us/en/documents/technical-\
167specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer"
168
169Connection and Flow Control Mechanism
170^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
171
172Each FW client and a protocol is identified by a UUID. In order to communicate
173to a FW client, a connection must be established using connect request and
174response bus messages. If successful, a pair (host_client_id and fw_client_id)
175will identify the connection.
176
177Once connection is established, peers send each other flow control bus messages
178independently. Every peer may send a message only if it has received a
179flow-control credit before. Once it has sent a message, it may not send another one
180before receiving the next flow control credit.
181Either side can send disconnect request bus message to end communication. Also
182the link will be dropped if major FW reset occurs.
183
184Peer to Peer data transfer
185^^^^^^^^^^^^^^^^^^^^^^^^^^
186
187Peer to Peer data transfer can happen with or without using DMA. Depending on
188the sensor bandwidth requirement DMA can be enabled by using module parameter
189ishtp_use_dma under intel_ishtp.
190
191Each side (host and FW) manages its DMA transfer memory independently. When an
192ISHTP client from either host or FW side wants to send something, it decides
193whether to send over IPC or over DMA; for each transfer the decision is
194independent. The sending side sends DMA_XFER message when the message is in
195the respective host buffer (TX when host client sends, RX when FW client
196sends). The recipient of DMA message responds with DMA_XFER_ACK, indicating
197the sender that the memory region for that message may be reused.
198
199DMA initialization is started with host sending DMA_ALLOC_NOTIFY bus message
200(that includes RX buffer) and FW responds with DMA_ALLOC_NOTIFY_ACK.
201Additionally to DMA address communication, this sequence checks capabilities:
202if the host doesn't support DMA, then it won't send DMA allocation, so FW can't
203send DMA; if FW doesn't support DMA then it won't respond with
204DMA_ALLOC_NOTIFY_ACK, in which case host will not use DMA transfers.
205Here ISH acts as busmaster DMA controller. Hence when host sends DMA_XFER,
206it's request to do host->ISH DMA transfer; when FW sends DMA_XFER, it means
207that it already did DMA and the message resides at host. Thus, DMA_XFER
208and DMA_XFER_ACK act as ownership indicators.
209
210At initial state all outgoing memory belongs to the sender (TX to host, RX to
211FW), DMA_XFER transfers ownership on the region that contains ISHTP message to
212the receiving side, DMA_XFER_ACK returns ownership to the sender. A sender
213need not wait for previous DMA_XFER to be ack'ed, and may send another message
214as long as remaining continuous memory in its ownership is enough.
215In principle, multiple DMA_XFER and DMA_XFER_ACK messages may be sent at once
216(up to IPC MTU), thus allowing for interrupt throttling.
217Currently, ISH FW decides to send over DMA if ISHTP message is more than 3 IPC
218fragments and via IPC otherwise.
219
220Ring Buffers
221^^^^^^^^^^^^
222
223When a client initiates a connection, a ring of RX and TX buffers is allocated.
224The size of ring can be specified by the client. HID client sets 16 and 32 for
225TX and RX buffers respectively. On send request from client, the data to be
226sent is copied to one of the send ring buffer and scheduled to be sent using
227bus message protocol. These buffers are required because the FW may have not
228have processed the last message and may not have enough flow control credits
229to send. Same thing holds true on receive side and flow control is required.
230
231Host Enumeration
232^^^^^^^^^^^^^^^^
233
234The host enumeration bus command allows discovery of clients present in the FW.
235There can be multiple sensor clients and clients for calibration function.
236
237To ease implementation and allow independent drivers to handle each client,
238this transport layer takes advantage of Linux Bus driver model. Each
239client is registered as device on the transport bus (ishtp bus).
240
241Enumeration sequence of messages:
242
243- Host sends HOST_START_REQ_CMD, indicating that host ISHTP layer is up.
244- FW responds with HOST_START_RES_CMD
245- Host sends HOST_ENUM_REQ_CMD (enumerate FW clients)
246- FW responds with HOST_ENUM_RES_CMD that includes bitmap of available FW
247  client IDs
248- For each FW ID found in that bitmap host sends
249  HOST_CLIENT_PROPERTIES_REQ_CMD
250- FW responds with HOST_CLIENT_PROPERTIES_RES_CMD. Properties include UUID,
251  max ISHTP message size, etc.
252- Once host received properties for that last discovered client, it considers
253  ISHTP device fully functional (and allocates DMA buffers)
254
255HID over ISH Client
256-------------------
257
258Location: drivers/hid/intel-ish-hid
259
260The ISHTP client driver is responsible for:
261
262- enumerate HID devices under FW ISH client
263- Get Report descriptor
264- Register with HID core as a LL driver
265- Process Get/Set feature request
266- Get input reports
267
268HID Sensor Hub MFD and IIO sensor drivers
269-----------------------------------------
270
271The functionality in these drivers is the same as an external sensor hub.
272Refer to
273Documentation/hid/hid-sensor.rst for HID sensor
274Documentation/ABI/testing/sysfs-bus-iio for IIO ABIs to user space.
275
276End to End HID transport Sequence Diagram
277-----------------------------------------
278
279::
280
281  HID-ISH-CLN                    ISHTP                    IPC                             HW
282          |                        |                       |                               |
283          |                        |                       |-----WAKE UP------------------>|
284          |                        |                       |                               |
285          |                        |                       |-----HOST READY--------------->|
286          |                        |                       |                               |
287          |                        |                       |<----MNG_RESET_NOTIFY_ACK----- |
288          |                        |                       |                               |
289          |                        |<----ISHTP_START------ |                               |
290          |                        |                       |                               |
291          |                        |<-----------------HOST_START_RES_CMD-------------------|
292          |                        |                       |                               |
293          |                        |------------------QUERY_SUBSCRIBER-------------------->|
294          |                        |                       |                               |
295          |                        |------------------HOST_ENUM_REQ_CMD------------------->|
296          |                        |                       |                               |
297          |                        |<-----------------HOST_ENUM_RES_CMD--------------------|
298          |                        |                       |                               |
299          |                        |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>|
300          |                        |                       |                               |
301          |                        |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------|
302          |       Create new device on in ishtp bus        |                               |
303          |                        |                       |                               |
304          |                        |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>|
305          |                        |                       |                               |
306          |                        |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------|
307          |       Create new device on in ishtp bus        |                               |
308          |                        |                       |                               |
309          |                        |--Repeat HOST_CLIENT_PROPERTIES_REQ_CMD-till last one--|
310          |                        |                       |                               |
311       probed()
312          |----ishtp_cl_connect--->|----------------- CLIENT_CONNECT_REQ_CMD-------------->|
313          |                        |                       |                               |
314          |                        |<----------------CLIENT_CONNECT_RES_CMD----------------|
315          |                        |                       |                               |
316          |register event callback |                       |                               |
317          |                        |                       |                               |
318          |ishtp_cl_send(
319          HOSTIF_DM_ENUM_DEVICES)  |----------fill ishtp_msg_hdr struct write to HW-----  >|
320          |                        |                       |                               |
321          |                        |                       |<-----IRQ(IPC_PROTOCOL_ISHTP---|
322          |                        |                       |                               |
323          |<--ENUM_DEVICE RSP------|                       |                               |
324          |                        |                       |                               |
325  for each enumerated device
326          |ishtp_cl_send(
327          HOSTIF_GET_HID_DESCRIPTOR|----------fill ishtp_msg_hdr struct write to HW-----  >|
328          |                        |                       |                               |
329          ...Response
330          |                        |                       |                               |
331  for each enumerated device
332          |ishtp_cl_send(
333       HOSTIF_GET_REPORT_DESCRIPTOR|--------------fill ishtp_msg_hdr struct write to HW-- >|
334          |                        |                       |                               |
335          |                        |                       |                               |
336   hid_allocate_device
337          |                        |                       |                               |
338   hid_add_device                  |                       |                               |
339          |                        |                       |                               |
340
341
342ISH Firmware Loading from Host Flow
343-----------------------------------
344
345Starting from the Lunar Lake generation, the ISH firmware has been divided into two components for better space optimization and increased flexibility. These components include a bootloader that is integrated into the BIOS, and a main firmware that is stored within the operating system's file system.
346
347The process works as follows:
348
349- Initially, the ISHTP driver sends a command, HOST_START_REQ_CMD, to the ISH bootloader. In response, the bootloader sends back a HOST_START_RES_CMD. This response includes the ISHTP_SUPPORT_CAP_LOADER bit. Subsequently, the ISHTP driver checks if this bit is set. If it is, the firmware loading process from the host begins.
350
351- During this process, the ISHTP driver first invokes the request_firmware() function, followed by sending a LOADER_CMD_XFER_QUERY command. Upon receiving a response from the bootloader, the ISHTP driver sends a LOADER_CMD_XFER_FRAGMENT command. After receiving another response, the ISHTP driver sends a LOADER_CMD_START command. The bootloader responds and then proceeds to the Main Firmware.
352
353- After the process concludes, the ISHTP driver calls the release_firmware() function.
354
355For more detailed information, please refer to the flow descriptions provided below:
356
357::
358
359  +---------------+                                                    +-----------------+
360  | ISHTP Driver  |                                                    | ISH Bootloader  |
361  +---------------+                                                    +-----------------+
362          |                                                                     |
363          |~~~Send HOST_START_REQ_CMD~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
364          |                                                                     |
365          |<--Send HOST_START_RES_CMD(Includes ISHTP_SUPPORT_CAP_LOADER bit)----|
366          |                                                                     |
367  ****************************************************************************************
368  * if ISHTP_SUPPORT_CAP_LOADER bit is set                                               *
369  ****************************************************************************************
370          |                                                                     |
371          |~~~start loading firmware from host process~~~+                      |
372          |                                              |                      |
373          |<---------------------------------------------+                      |
374          |                                                                     |
375  ---------------------------                                                   |
376  | Call request_firmware() |                                                   |
377  ---------------------------                                                   |
378          |                                                                     |
379          |~~~Send LOADER_CMD_XFER_QUERY~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
380          |                                                                     |
381          |<--Send response-----------------------------------------------------|
382          |                                                                     |
383          |~~~Send LOADER_CMD_XFER_FRAGMENT~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
384          |                                                                     |
385          |<--Send response-----------------------------------------------------|
386          |                                                                     |
387          |~~~Send LOADER_CMD_START~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>|
388          |                                                                     |
389          |<--Send response-----------------------------------------------------|
390          |                                                                     |
391          |                                                                     |~~~Jump to Main Firmware~~~+
392          |                                                                     |                           |
393          |                                                                     |<--------------------------+
394          |                                                                     |
395  ---------------------------                                                   |
396  | Call release_firmware() |                                                   |
397  ---------------------------                                                   |
398          |                                                                     |
399  ****************************************************************************************
400  * end if                                                                               *
401  ****************************************************************************************
402          |                                                                     |
403  +---------------+                                                    +-----------------+
404  | ISHTP Driver  |                                                    | ISH Bootloader  |
405  +---------------+                                                    +-----------------+
406
407ISH Debugging
408-------------
409
410To debug ISH, event tracing mechanism is used. To enable debug logs::
411
412  echo 1 > /sys/kernel/tracing/events/intel_ish/enable
413  cat /sys/kernel/tracing/trace
414
415ISH IIO sysfs Example on Lenovo thinkpad Yoga 260
416-------------------------------------------------
417
418::
419
420  root@otcpl-ThinkPad-Yoga-260:~# tree -l /sys/bus/iio/devices/
421  /sys/bus/iio/devices/
422  ├── iio:device0 -> ../../../devices/0044:8086:22D8.0001/HID-SENSOR-200073.9.auto/iio:device0
423  │   ├── buffer
424  │   │   ├── enable
425  │   │   ├── length
426  │   │   └── watermark
427  ...
428  │   ├── in_accel_hysteresis
429  │   ├── in_accel_offset
430  │   ├── in_accel_sampling_frequency
431  │   ├── in_accel_scale
432  │   ├── in_accel_x_raw
433  │   ├── in_accel_y_raw
434  │   ├── in_accel_z_raw
435  │   ├── name
436  │   ├── scan_elements
437  │   │   ├── in_accel_x_en
438  │   │   ├── in_accel_x_index
439  │   │   ├── in_accel_x_type
440  │   │   ├── in_accel_y_en
441  │   │   ├── in_accel_y_index
442  │   │   ├── in_accel_y_type
443  │   │   ├── in_accel_z_en
444  │   │   ├── in_accel_z_index
445  │   │   └── in_accel_z_type
446  ...
447  │   │   ├── devices
448  │   │   │   │   ├── buffer
449  │   │   │   │   │   ├── enable
450  │   │   │   │   │   ├── length
451  │   │   │   │   │   └── watermark
452  │   │   │   │   ├── dev
453  │   │   │   │   ├── in_intensity_both_raw
454  │   │   │   │   ├── in_intensity_hysteresis
455  │   │   │   │   ├── in_intensity_offset
456  │   │   │   │   ├── in_intensity_sampling_frequency
457  │   │   │   │   ├── in_intensity_scale
458  │   │   │   │   ├── name
459  │   │   │   │   ├── scan_elements
460  │   │   │   │   │   ├── in_intensity_both_en
461  │   │   │   │   │   ├── in_intensity_both_index
462  │   │   │   │   │   └── in_intensity_both_type
463  │   │   │   │   ├── trigger
464  │   │   │   │   │   └── current_trigger
465  ...
466  │   │   │   │   ├── buffer
467  │   │   │   │   │   ├── enable
468  │   │   │   │   │   ├── length
469  │   │   │   │   │   └── watermark
470  │   │   │   │   ├── dev
471  │   │   │   │   ├── in_magn_hysteresis
472  │   │   │   │   ├── in_magn_offset
473  │   │   │   │   ├── in_magn_sampling_frequency
474  │   │   │   │   ├── in_magn_scale
475  │   │   │   │   ├── in_magn_x_raw
476  │   │   │   │   ├── in_magn_y_raw
477  │   │   │   │   ├── in_magn_z_raw
478  │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_raw
479  │   │   │   │   ├── in_rot_hysteresis
480  │   │   │   │   ├── in_rot_offset
481  │   │   │   │   ├── in_rot_sampling_frequency
482  │   │   │   │   ├── in_rot_scale
483  │   │   │   │   ├── name
484  ...
485  │   │   │   │   ├── scan_elements
486  │   │   │   │   │   ├── in_magn_x_en
487  │   │   │   │   │   ├── in_magn_x_index
488  │   │   │   │   │   ├── in_magn_x_type
489  │   │   │   │   │   ├── in_magn_y_en
490  │   │   │   │   │   ├── in_magn_y_index
491  │   │   │   │   │   ├── in_magn_y_type
492  │   │   │   │   │   ├── in_magn_z_en
493  │   │   │   │   │   ├── in_magn_z_index
494  │   │   │   │   │   ├── in_magn_z_type
495  │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_en
496  │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_index
497  │   │   │   │   │   └── in_rot_from_north_magnetic_tilt_comp_type
498  │   │   │   │   ├── trigger
499  │   │   │   │   │   └── current_trigger
500  ...
501  │   │   │   │   ├── buffer
502  │   │   │   │   │   ├── enable
503  │   │   │   │   │   ├── length
504  │   │   │   │   │   └── watermark
505  │   │   │   │   ├── dev
506  │   │   │   │   ├── in_anglvel_hysteresis
507  │   │   │   │   ├── in_anglvel_offset
508  │   │   │   │   ├── in_anglvel_sampling_frequency
509  │   │   │   │   ├── in_anglvel_scale
510  │   │   │   │   ├── in_anglvel_x_raw
511  │   │   │   │   ├── in_anglvel_y_raw
512  │   │   │   │   ├── in_anglvel_z_raw
513  │   │   │   │   ├── name
514  │   │   │   │   ├── scan_elements
515  │   │   │   │   │   ├── in_anglvel_x_en
516  │   │   │   │   │   ├── in_anglvel_x_index
517  │   │   │   │   │   ├── in_anglvel_x_type
518  │   │   │   │   │   ├── in_anglvel_y_en
519  │   │   │   │   │   ├── in_anglvel_y_index
520  │   │   │   │   │   ├── in_anglvel_y_type
521  │   │   │   │   │   ├── in_anglvel_z_en
522  │   │   │   │   │   ├── in_anglvel_z_index
523  │   │   │   │   │   └── in_anglvel_z_type
524  │   │   │   │   ├── trigger
525  │   │   │   │   │   └── current_trigger
526  ...
527  │   │   │   │   ├── buffer
528  │   │   │   │   │   ├── enable
529  │   │   │   │   │   ├── length
530  │   │   │   │   │   └── watermark
531  │   │   │   │   ├── dev
532  │   │   │   │   ├── in_anglvel_hysteresis
533  │   │   │   │   ├── in_anglvel_offset
534  │   │   │   │   ├── in_anglvel_sampling_frequency
535  │   │   │   │   ├── in_anglvel_scale
536  │   │   │   │   ├── in_anglvel_x_raw
537  │   │   │   │   ├── in_anglvel_y_raw
538  │   │   │   │   ├── in_anglvel_z_raw
539  │   │   │   │   ├── name
540  │   │   │   │   ├── scan_elements
541  │   │   │   │   │   ├── in_anglvel_x_en
542  │   │   │   │   │   ├── in_anglvel_x_index
543  │   │   │   │   │   ├── in_anglvel_x_type
544  │   │   │   │   │   ├── in_anglvel_y_en
545  │   │   │   │   │   ├── in_anglvel_y_index
546  │   │   │   │   │   ├── in_anglvel_y_type
547  │   │   │   │   │   ├── in_anglvel_z_en
548  │   │   │   │   │   ├── in_anglvel_z_index
549  │   │   │   │   │   └── in_anglvel_z_type
550  │   │   │   │   ├── trigger
551  │   │   │   │   │   └── current_trigger
552  ...
553