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 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