diff mbox series

[v3,01/22] HID: THC: Add documentation

Message ID 20241216014127.3722172-2-even.xu@intel.com (mailing list archive)
State New
Headers show
Series Add Intel Touch Host Controller drivers | expand

Commit Message

Even Xu Dec. 16, 2024, 1:41 a.m. UTC
Add Documentation/hid/intel-thc-hid.rst file to provide hardware
and software detail for intel THC drivers.

Co-developed-by: Sun Xinpeng <xinpeng.sun@intel.com>
Signed-off-by: Sun Xinpeng <xinpeng.sun@intel.com>
Signed-off-by: Even Xu <even.xu@intel.com>
Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 Documentation/hid/index.rst         |   1 +
 Documentation/hid/intel-thc-hid.rst | 568 ++++++++++++++++++++++++++++
 2 files changed, 569 insertions(+)
 create mode 100644 Documentation/hid/intel-thc-hid.rst

Comments

Bagas Sanjaya Dec. 17, 2024, 6:13 a.m. UTC | #1
On Mon, Dec 16, 2024 at 09:41:06AM +0800, Even Xu wrote:
> diff --git a/Documentation/hid/intel-thc-hid.rst b/Documentation/hid/intel-thc-hid.rst
> new file mode 100644
> index 000000000000..e9452c11d8de
> --- /dev/null
> +++ b/Documentation/hid/intel-thc-hid.rst
> @@ -0,0 +1,568 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +=================================
> +Intel Touch Host Controller (THC)
> +=================================
> +
> +Touch Host Controller is the name of the IP block in PCH that interface with Touch Devices (ex:
> +touchscreen, touchpad etc.). It is comprised of 3 key functional blocks:
> +
> +- A natively half-duplex Quad I/O capable SPI master
> +- Low latency I2C interface to support HIDI2C compliant devices
> +- A HW sequencer with RW DMA capability to system memory
> +
> +It has a single root space IOSF Primary interface that supports transactions to/from touch devices.
> +Host driver configures and controls the touch devices over THC interface. THC provides high
> +bandwidth DMA services to the touch driver and transfers the HID report to host system main memory.
> +
> +Hardware sequencer within the THC is responsible for transferring (via DMA) data from touch devices
> +into system memory. A ring buffer is used to avoid data loss due to asynchronous nature of data
> +consumption (by host) in relation to data production (by touch device via DMA).
> +
> +Unlike other common SPI/I2C controllers, THC handles the HID device data interrupt and reset
> +signals directly.
> +
> +1. Overview
> +===========
> +
> +1.1 THC software/hardware stack
> +-------------------------------
> +
> +Below diagram illustrates the high-level architecture of THC software/hardware stack, which is fully
> +capable of supporting HIDSPI/HIDI2C protocol in Linux OS.
> +
> +::
> +
> +  ----------------------------------------------
> + |      +-----------------------------------+   |
> + |      |           Input Device            |   |
> + |      +-----------------------------------+   |
> + |      +-----------------------------------+   |
> + |      |       HID Multi-touch Driver      |   |
> + |      +-----------------------------------+   |
> + |      +-----------------------------------+   |
> + |      |             HID Core              |   |
> + |      +-----------------------------------+   |
> + |      +-----------------------------------+   |
> + |      |    THC QuickSPI/QuickI2C Driver   |   |
> + |      +-----------------------------------+   |
> + |      +-----------------------------------+   |
> + |      |      THC Hardware Driver          |   |
> + |      +-----------------------------------+   |
> + |      +----------------+ +----------------+   |
> + |  SW  | PCI Bus Driver | | ACPI Resource  |   |
> + |      +----------------+ +----------------+   |
> +  ----------------------------------------------
> +  ----------------------------------------------
> + |      +-----------------------------------+   |
> + |  HW  |              PCI Bus              |   |
> + |      +-----------------------------------+   |
> + |      +-----------------------------------+   |
> + |      |           THC Controller          |   |
> + |      +-----------------------------------+   |
> + |      +-----------------------------------+   |
> + |      |              Touch IC             |   |
> + |      +-----------------------------------+   |
> +  ----------------------------------------------
> +
> +Touch IC (TIC), also as known as the Touch devices (touchscreen or touchpad). The discrete analog
> +components that sense and transfer either discrete touch data or heatmap data in the form of HID
> +reports over the SPI/I2C bus to the THC Controller on the host.
> +
> +THC Host Controller, which is a PCI device HBA (host bus adapter), integrated into the PCH, that
> +serves as a bridge between the Touch ICs and the host.
> +
> +THC Hardware Driver, provides THC hardware operation APIs for above QuickSPI/QuickI2C driver, it
> +accesses THC MMIO registers to configure and control THC hardware.
> +
> +THC QuickSPI/QuickI2C driver, also as known as HIDSPI/HIDI2C driver, is registered as a HID
> +low-level driver that manages the THC Controller and implements HIDSPI/HIDI2C protocol.
> +
> +
> +1.2 THC hardware diagram
> +------------------------
> +Below diagram shows THC hardware components::
> +
> +                      ---------------------------------
> +                     |          THC Controller         |
> +                     |  +---------------------------+  |
> +                     |  |     PCI Config Space      |  |
> +                     |  +---------------------------+  |
> +                     |  +---------------------------+  |
> +                     |  +       MMIO Registers      |  |
> +                     |  +---------------------------+  |
> + +---------------+   |  +------------+ +------------+  |
> + | System Memory +---+--+      DMA   | |   PIO      |  |
> + +---------------+   |  +------------+ +------------+  |
> +                     |  +---------------------------+  |
> +                     |  |       HW Sequencer        |  |
> +                     |  +---------------------------+  |
> +                     |  +------------+ +------------+  |
> +                     |  |  SPI/I2C   | |    GPIO    |  |
> +                     |  | Controller | | Controller |  |
> +                     |  +------------+ +------------+  |
> +                      ---------------------------------
> +
> +As THC is exposed as a PCI devices, so it has standard PCI config space registers for PCI
> +enumeration and configuration.
> +
> +MMIO Registers, which provide registers access for driver to configure and control THC hardware,
> +the registers include several categories: Interrupt status and control, DMA configure,
> +PIO (Programmed I/O, defined in section 3.2) status and control, SPI bus configure, I2C subIP
> +status and control, reset status and control...
> +
> +THC provides two ways for driver to communicate with external Touch ICs: PIO and DMA.
> +PIO can let driver manually write/read data to/from Touch ICs, instead, THC DMA can
> +automatically write/read data without driver involved.
> +
> +HW Sequencer includes THC major logic, it gets instruction from MMIO registers to control
> +SPI bus and I2C bus to finish a bus data transaction, it also can automatically handle
> +Touch ICs interrupt and start DMA receive/send data from/to Touch ICs according to interrupt
> +type. That means THC HW Sequencer understands HIDSPI/HIDI2C transfer protocol, and handle
> +the communication without driver involved, what driver needs to do is just configure the THC
> +properly, and prepare the formatted data packet or handle received data packet.
> +
> +As THC supports HIDSPI/HIDI2C protocols, it has SPI controller and I2C subIP in it to expose
> +SPI bus and I2C bus. THC also integrates a GPIO controller to provide interrupt line support
> +and reset line support.
> +
> +2. THC Hardware Interface
> +=========================
> +
> +2.1 Host Interface
> +------------------
> +
> +THC is exposed as "PCI Digitizer device" to the host. The PCI product and device IDs are
> +changed from different generations of processors. So the source code which enumerates drivers
> +needs to update from generation to generation.
> +
> +
> +2.2 Device Interface
> +--------------------
> +
> +THC supports two types of bus for Touch IC connection: Enhanced SPI bus and I2C bus.
> +
> +2.2.1 SPI Port
> +~~~~~~~~~~~~~~
> +
> +When PORT_TYPE = 00b in MMIO registers, THC uses SPI interfaces to communicate with external
> +Touch IC. THC enhanced SPI Bus supports different SPI modes: standard Single IO mode,
> +Dual IO mode and Quad IO mode.
> +
> +In Single IO mode, THC drives MOSI line to send data to Touch ICs, and receives data from Touch
> +ICs data from MISO line. In Dual IO mode, THC drivers MOSI and MISO both for data sending, and
> +also receives the data on both line. In Quad IO mode, there are other two lines (IO2 and IO3)
> +are added, THC drives MOSI (IO0), MISO (IO1), IO2 and IO3 at the same time for data sending, and
> +also receives the data on those 4 lines. Driver needs to configure THC in different mode by
> +setting different opcode.
> +
> +Beside IO mode, driver also needs to configure SPI bus speed. THC supports up to 42MHz SPI clock
> +on Intel Lunar Lake platform.
> +
> +For THC sending data to Touch IC, the data flow on SPI bus::
> +
> + | --------------------THC sends---------------------------------|
> + <8Bits OPCode><24Bits Slave Address><Data><Data><Data>...........
> +
> +For THC receiving data from Touch IC, the data flow on SPI bus::
> +
> + | ---------THC Sends---------------||-----Touch IC sends--------|
> + <8Bits OPCode><24Bits Slave Address><Data><Data><Data>...........
> +
> +2.2.2 I2C Port
> +~~~~~~~~~~~~~~
> +
> +THC also integrates I2C controller in it, it's called I2C SubSystem. When PORT_TYPE = 01, THC
> +is configured to I2C mode. Comparing to SPI mode which can be configured through MMIO registers
> +directly, THC needs to use PIO read (by setting SubIP read opcode) to I2C subIP APB registers'
> +value and use PIO write (by setting SubIP write opcode) to do a write operation.
> +
> +2.2.3 GPIO interface
> +~~~~~~~~~~~~~~~~~~~~
> +
> +THC also includes two GPIO pins, one for interrupt and the other for device reset control.
> +
> +Interrupt line can be configured to either level triggerred or edge triggerred by setting MMIO
> +Control register.
> +
> +Reset line is controlled by BIOS (or EFI) through ACPI _RST method, driver needs to call this
> +device ACPI _RST method to reset touch IC during initialization.
> +
> +3. High level concept
> +=====================
> +
> +3.1 Opcode
> +----------
> +
> +Opcode (operation code) is used to tell THC or Touch IC what the operation will be, such as PIO
> +read or PIO write.
> +
> +When THC is configured to SPI mode, opcodes are used for determining the read/write IO mode.
> +There are some OPCode examples for SPI IO mode:
> +
> +=======   ==============================
> +opcode    Corresponding SPI command
> +=======   ==============================
> +0x0B      Read Single I/O
> +0x02      Write Single I/O
> +0xBB      Read Dual I/O
> +0xB2      Write Dual I/O
> +0xEB      Read Quad I/O
> +0xE2      Write Quad I/O
> +=======   ==============================
> +
> +In general, different touch IC has different OPCode definition. According to HIDSPI
> +protocol whitepaper, those OPCodes are defined in device ACPI table, and driver needs to
> +query those information through OS ACPI APIs during driver initialization, then configures
> +THC MMIO OPCode registers with correct setting.
> +
> +When THC is working in I2C mode, opcodes are used to tell THC what's the next PIO type:
> +I2C SubIP APB register read, I2C SubIP APB register write, I2C touch IC device read,
> +I2C touch IC device write, I2C touch IC device write followed by read.
> +
> +Here are the THC pre-defined opcodes for I2C mode:
> +
> +=======   ===================================================   ===========
> +opcode    Corresponding I2C command                             Address
> +=======   ===================================================   ===========
> +0x12      Read I2C SubIP APB internal registers                 0h - FFh
> +0x13      Write I2C SubIP APB internal registers                0h - FFh
> +0x14      Read external Touch IC through I2C bus                N/A
> +0x18      Write external Touch IC through I2C bus               N/A
> +0x1C      Write then read external Touch IC through I2C bus     N/A
> +=======   ===================================================   ===========
> +
> +3.2 PIO
> +-------
> +
> +THC provides a programmed I/O (PIO) access interface for the driver to access the touch IC's
> +configuration registers, or access I2C subIP's configuration registers. To use PIO to perform
> +I/O operations, driver should pre-program PIO control registers and PIO data registers and kick
> +off the sequencing cycle. THC uses different PIO opcodes to distinguish different PIO
> +operations (PIO read/write/write followed by read).
> +
> +If there is a Sequencing Cycle In Progress and an attempt is made to program any of the control,
> +address, or data register the cycle is blocked and a sequence error will be encountered.
> +
> +A status bit indicates when the cycle has completed allowing the driver to know when read results
> +can be checked and/or when to initiate a new command. If enabled, the cycle done assertion can
> +interrupt driver with an interrupt.
> +
> +Because THC only has 16 FIFO registers for PIO, so all the data transfer through PIO shouldn't
> +exceed 64 bytes.
> +
> +As DMA needs max packet size for transferring configuration, and the max packet size information
> +always in HID device descriptor which needs THC driver to read it out from HID Device (Touch IC).
> +So PIO typical use case is, before DMA initialization, write RESET command (PIO write), read
> +RESET response (PIO read or PIO write followed by read), write Power ON command (PIO write), read
> +device descriptor (PIO read).
> +
> +For how to issue a PIO operation, here is the steps which driver needs follow:
> +
> +- Program read/write data size in THC_SS_BC.
> +- Program I/O target address in THC_SW_SEQ_DATA0_ADDR.
> +- If write, program the write data in THC_SW_SEQ_DATA0..THC_SW_SEQ_DATAn.
> +- Program the PIO opcode in THC_SS_CMD.
> +- Set TSSGO = 1 to start the PIO write sequence.
> +- If THC_SS_CD_IE = 1, SW will receives a MSI when the PIO is completed.
> +- If read, read out the data in THC_SW_SEQ_DATA0..THC_SW_SEQ_DATAn.
> +
> +3.3 DMA
> +-------
> +
> +THC has 4 DMA channels: Read DMA1, Read DMA2, Write DMA and Software DMA.
> +
> +3.3.1 Read DMA Channel
> +~~~~~~~~~~~~~~~~~~~~~~
> +
> +THC has two Read DMA engines: 1st RxDMA (RxDMA1) and 2nd RxDMA (RxDMA2). RxDMA1 is reserved for
> +raw data mode. RxDMA2 is used for HID data mode and it is the RxDMA engine currently driver uses
> +for HID input report data retrieval.
> +
> +RxDMA's typical use case is auto receiving the data from Touch IC. Once RxDMA is enabled by
> +software, THC will start auto-handling receiving logic.
> +
> +For SPI mode, THC RxDMA sequence is: when Touch IC triggers a interrupt to THC, THC reads out
> +report header to identify what's the report type, and what's the report length, according to
> +above information, THC reads out report body to internal FIFO and start RxDMA coping the data
> +to system memory. After that, THC update interrupt cause register with report type, and update
> +RxDMA PRD table read pointer, then trigger a MSI interrupt to notify driver RxDMA finishing
> +data receiving.
> +
> +For I2C mode, THC RxDMA's behavior is little difference, because of HIDI2C protocol difference with
                                     "a little bit different, ..."
> +HIDSPI protocol, RxDMA only be used to receive input report. The sequence is, when Touch IC
> +triggers a interrupt to THC, THC first reads out 2 bytes from input report address to determine the
> +packet length, then use this packet length to start a DMA reading from input report address for
> +input report data. After that, THC update RxDMA PRD table read pointer, then trigger a MSI interrupt
> +to notify driver input report data is ready in system memory.
> +
> +All above sequence is hardware automatically handled, all driver needs to do is configure RxDMA and
> +waiting for interrupt ready then read out the data from system memory.
> +
> +3.3.2 Software DMA channel
> +~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +THC supports a software triggerred RxDMA mode to read the touch data from touch IC. This SW RxDMA
> +is the 3rd THC RxDMA engine with the similar functionalities as the existing two RxDMAs, the only
> +difference is this SW RxDMA is triggerred by software, and RxDMA2 is triggerred by external Touch IC
> +interrupt. It gives a flexiblity to software driver to use RxDMA read Touch IC data in any time.
> +
> +Before software starts a SW RxDMA, it shall stop the 1st and 2nd RxDMA, clear PRD read/write pointer
> +and quiesce the device interrupt (THC_DEVINT_QUIESCE_HW_STS = 1), other operations are the same with
> +RxDMA.
> +
> +3.3.3 Write DMA Channel
> +~~~~~~~~~~~~~~~~~~~~~~~
> +
> +THC has one write DMA engine, which can be used for sending data to Touch IC automatically.
> +According to HIDSPI and HIDI2C protocol, every time only one command can be sent to touch IC, and
> +before last command is completely handled, next command cannot be sent, THC write DMA engine only
> +supports single PRD table.
> +
> +What driver needs to do is, preparing PRD table and DMA buffer, then copy data to DMA buffer and
> +update PRD table with buffer address and buffer length, then start write DMA. THC will
> +automatically send the data to touch IC, and trigger a DMA completion interrupt once transferring
> +is done.
> +
> +3.4 PRD
> +-------
> +
> +Physical Region Descriptor (PRD) provides the memory mapping description for THC DMAs.
> +
> +3.4.1 PRD table and entry
> +~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +In order to improve physical DMA memory usage, modern drivers trend to allocate a virtually
> +contiguous, but physically fragmented buffer of memory for each data buffer. Linux OS also
> +provide SGL (scatter gather list) APIs to support this usage.
> +
> +THC uses PRD table (physical region descriptor) to support the corresponding OS kernel
> +SGL that describes the virtual to physical buffer mapping.
> +
> +::
> +
> +  ------------------------      --------------       --------------
> + | PRD table base address +----+ PRD table #1 +-----+ PRD Entry #1 |
> +  ------------------------      --------------       --------------
> +                                                     --------------
> +                                                    | PRD Entry #2 |
> +                                                     --------------
> +                                                     --------------
> +                                                    | PRD Entry #n |
> +                                                     --------------
> +
> +The read DMA engine supports multiple PRD tables held within a circular buffer that allow the THC
> +to support multiple data buffers from the Touch IC. This allows host SW to arm the Read DMA engine
> +with multiple buffers, allowing the Touch IC to send multiple data frames to the THC without SW
> +interaction. This capability is required when the CPU processes touch frames slower than the
> +Touch IC can send them.
> +
> +To simplify the design, SW assumes worst-case memory fragmentation. Therefore,each PRD table shall
> +contain the same number of PRD entries, allowing for a global register (per Touch IC) to hold the
> +number of PRD-entries per PRD table.
> +
> +SW allocates up to 128 PRD tables per Read DMA engine as specified in the THC_M_PRT_RPRD_CNTRL.PCD
> +register field. The number of PRD tables should equal the number of data buffers.
> +
> +Max OS memory fragmentation will be at a 4KB boundary, thus to address 1MB of virtually contiguous
> +memory 256 PRD entries are required for a single PRD Table. SW writes the number of PRD entries
> +for each PRD table in the THC_M_PRT_RPRD_CNTRL.PTEC register field. The PRD entry's length must be
> +multiple of 4KB except for the last entry in a PRD table.
> +
> +SW allocates all the data buffers and PRD tables only once at host initialization.
> +
> +3.4.2 PRD Write pointer and read pointer
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +As PRD tables are organized as a Circular Buffer (CB), a read pointer and a write pointer for a CB
> +are needed.
> +
> +DMA HW consumes the PRD tables in the CB, one PRD entry at a time until the EOP bit is found set
> +in a PRD entry. At this point HW increments the PRD read pointer. Thus, the read pointer points
> +to the PRD which the DMA engine is currently processing. This pointer rolls over once the circular
> +buffer's depth has been traversed with bit[7] the Rollover bit. E.g. if the DMA CB depth is equal
> +to 4 entries (0011b), then the read pointers will follow this pattern (HW is required to honor
> +this behavior): 00h 01h 02h 03h 80h 81h 82h 83h 00h 01h ...
> +
> +The write pointer is updated by SW. The write pointer points to location in the DMA CB, where the
> +next PRD table is going to be stored. SW needs to ensure that this pointer rolls over once the
> +circular buffer's depth has been traversed with Bit[7] as the rollover bit. E.g. if the DMA CB
> +depth is equal to 5 entries (0100b), then the write pointers will follow this pattern (SW is
> +required to honor this behavior): 00h 01h 02h 03h 04h 80h 81h 82h 83h 84h 00h 01h ..
> +
> +3.4.3 PRD descriptor structure
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Intel THC uses PRD entry descriptor for every PRD entry. Every PRD entry descriptor occupies
> +128 bits memories:
> +
> +===================   ========   ===============================================
> +struct field          bit(s)     description
> +===================   ========   ===============================================
> +dest_addr             53..0      destination memory address, as every entry
> +                                 is 4KB, ignore lowest 10 bits of address.
> +reserved1             54..62     reserved
> +int_on_completion     63         completion interrupt enable bit, if this bit
> +                                 set it means THC will trigger a completion
> +                                 interrupt. This bit is set by SW driver.
> +len                   87..64     how many bytes of data in this entry.
> +end_of_prd            88         end of PRD table bit, if this bit is set,
> +                                 it means this entry is last entry in this PRD
> +                                 table. This bit is set by SW driver.
> +hw_status             90..89     HW status bits
> +reserved2             127..91    reserved
> +===================   ========   ===============================================
> +
> +And one PRD table can include up to 256 PRD entries, as every entries is 4K bytes, so every
> +PRD table can describe 1M bytes memory.
> +
> +.. code-block:: c
> +
> +   struct thc_prd_table {
> +        struct thc_prd_entry entries[PRD_ENTRIES_NUM];
> +   };
> +
> +In general, every PRD table means one HID touch data packet. Every DMA engine can support
> +up to 128 PRD tables (except write DMA, write DMA only has one PRD table). SW driver is responsible
> +to get max packet length from touch IC, and use this max packet length to create PRD entries for
> +each PRD table.
> +
> +4. HIDSPI support (QuickSPI)
> +============================
> +
> +Intel THC is total compatible with HIDSPI protocol, THC HW sequenser can accelerate HIDSPI
> +protocol transferring.
> +
> +4.1 Reset Flow
> +--------------
> +
> +- Call ACPI _RST method to reset Touch IC device.
> +- Read the reset response from TIC through PIO read.
> +- Issue a command to retrieve device descriptor from Touch IC through PIO write.
> +- Read the device descriptor from Touch IC through PIO read.
> +- If the device descriptor is valid, allocate DMA buffers and configure all DMA channels.
> +- Issue a command to retrieve report descriptor from Touch IC through DMA.
> +
> +4.2 Input Report Data Flow
> +--------------------------
> +
> +Basic Flow:
> +
> +- Touch IC interrupts the THC Controller using an in-band THC interrupt.
> +- THC Sequencer reads the input report header by transmitting read approval as a signal
> +  to the Touch IC to prepare for host to read from the device.
> +- THC Sequencer executes a Input Report Body Read operation corresponding to the value
> +  reflected in “Input Report Length” field of the Input Report Header.
> +- THC DMA engine begins fetching data from the THC Sequencer and writes to host memory
> +  at PRD entry 0 for the current CB PRD table entry. This process continues until the
> +  THC Sequencer signals all data has been read or the THC DMA Read Engine reaches the
> +  end of it's last PRD entry (or both).
> +- The THC Sequencer checks for the “Last Fragment Flag” bit in the Input Report Header.
> +  If it is clear, the THC Sequencer enters an idle state.
> +- If the “Last Fragment Flag” bit is enabled the THC Sequencer enters End-of-Frame Processing.
> +
> +THC Sequencer End of Frame Processing:
> +
> +- THC DMA engine increments the read pointer of the Read PRD CB, sets EOF interrupt status
> +  in RxDMA2 register (THC_M_PRT_READ_DMA_INT_STS_2).
> +- If THC EOF interrupt is enabled by the driver in the control register (THC_M_PRT_READ_DMA_CNTRL_2),
> +  generates interrupt to software.
> +
> +Sequence of steps to read data from RX DMA buffer:
> +
> +- THC QuickSPI driver checks CB write Ptr and CB read Ptr to identify if any data frame in DMA
> +  circular buffers.
> +- THC QuickSPI driver gets first unprocessed PRD table.
> +- THC QuickSPI driver scans all PRD entries in this PRD table to calculate the total frame size.
> +- THC QuickSPI driver copies all frame data out.
> +- THC QuickSPI driver checks the data type according to input report body, and calls related
> +  callbacks to process the data.
> +- THC QuickSPI driver updates write Ptr.
> +
> +4.3 Output Report Data Flow
> +---------------------------
> +
> +Generic Output Report Flow:
> +
> +- HID core calls raw_request callback with a request to THC QuickSPI driver.
> +- THC QuickSPI Driver converts request provided data into the output report packet and copies it
> +  to THC's write DMA buffer.
> +- Start TxDMA to complete the write operation.
> +
> +5. HIDI2C support (QuickI2C)
> +============================
> +
> +5.1 Reset Flow
> +--------------
> +
> +- Read device descriptor from Touch IC device through PIO write followed by read.
> +- If the device descriptor is valid, allocate DMA buffers and configure all DMA channels.
> +- Use PIO or TxDMA to write a SET_POWER request to TIC's command register, and check if the
> +  write operation is successfully completed.
> +- Use PIO or TxDMA to write a RESET request to TIC's command register. If the write operation
> +  is successfully completed, wait for reset response from TIC.
> +- Use SWDMA to read report descriptor through TIC's report descriptor register.
> +
> +5.2 Input Report Data Flow
> +--------------------------
> +
> +Basic Flow:
> +
> +- Touch IC asserts the interrupt indicating that it has an interrupt to send to HOST.
> +  THC Sequencer issues a READ request over the I2C bus. The HIDI2C device returns the
> +  first 2 bytes from the HIDI2C device which contains the length of the received data.
> +- THC Sequencer continues the Read operation as per the size of data indicated in the
> +  length field.
> +- THC DMA engine begins fetching data from the THC Sequencer and writes to host memory
> +  at PRD entry 0 for the current CB PRD table entry. THC writes 2Bytes for length field
> +  plus the remaining data to RxDMA buffer. This process continues until the THC Sequencer
> +  signals all data has been read or the THC DMA Read Engine reaches the end of it's last
> +  PRD entry (or both).
> +- THC Sequencer enters End-of-Input Report Processing.
> +- If the device has no more input reports to send to the host, it de-asserts the interrupt
> +  line. For any additional input reports, device keeps the interrupt line asserted and
> +  steps 1 through 4 in the flow are repeated.
> +
> +THC Sequencer End of Input Report Processing:
> +
> +- THC DMA engine increments the read pointer of the Read PRD CB, sets EOF interrupt status
> +  in RxDMA 2 register (THC_M_PRT_READ_DMA_INT_STS_2).
> +- If THC EOF interrupt is enabled by the driver in the control register
> +  (THC_M_PRT_READ_DMA_CNTRL_2), generates interrupt to software.
> +
> +Sequence of steps to read data from RX DMA buffer:
> +
> +- THC QuickI2C driver checks CB write Ptr and CB read Ptr to identify if any data frame in DMA
> +  circular buffers.
> +- THC QuickI2C driver gets first unprocessed PRD table.
> +- THC QuickI2C driver scans all PRD entries in this PRD table to calculate the total frame size.
> +- THC QuickI2C driver copies all frame data out.
> +- THC QuickI2C driver call hid_input_report to send the input report content to HID core, which
> +  includes Report ID + Report Data Content (remove the length field from the original report
> +  data).
> +- THC QuickI2C driver updates write Ptr.
> +
> +5.3 Output Report Data Flow
> +---------------------------
> +
> +Generic Output Report Flow:
> +
> +- HID core call THC QuickI2C raw_request callback.
> +- THC QuickI2C uses PIO or TXDMA to write a SET_REPORT request to TIC's command register. Report
> +  type in SET_REPORT should be set to Output.
> +- THC QuickI2C programs TxDMA buffer with TX Data to be written to TIC's data register. The first
> +  2 bytes should indicate the length of the report followed by the report contents including
> +  Report ID.
> +
> +6. THC Debugging
> +================
> +
> +To debug THC, event tracing mechanism is used. To enable debug logs::
> +
> +  echo 1 > /sys/kernel/debug/tracing/events/intel_thc/enable
> +  cat /sys/kernel/debug/tracing/trace
> +
> +7. Reference
> +============
> +- HIDSPI: https://download.microsoft.com/download/c/a/0/ca07aef3-3e10-4022-b1e9-c98cea99465d/HidSpiProtocolSpec.pdf
> +- HIDI2C: https://download.microsoft.com/download/7/d/d/7dd44bb7-2a7a-4505-ac1c-7227d3d96d5b/hid-over-i2c-protocol-spec-v1-0.docx

The rest looks good.

Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>
Even Xu Dec. 19, 2024, 5:01 a.m. UTC | #2
> From: Bagas Sanjaya <bagasdotme@gmail.com>
> To: Even Xu <even.xu@intel.com>,
> 	jikos@kernel.org, bentiss@kernel.org, corbet@lwn.net,
> 	aaron.ma@canonical.com, rdunlap@infradead.org
> Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
> 	linux-doc@vger.kernel.org, Sun Xinpeng <xinpeng.sun@intel.com>,
> 	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> Subject: Re: [PATCH v3 01/22] HID: THC: Add documentation
> Date: Tue, 17 Dec 2024 13:13:07 +0700	[thread overview]
> Message-ID: <Z2EWcwQhaiep9yC0@archie.me> (raw)
> In-Reply-To: <20241216014127.3722172-2-even.xu@intel.com>
> 
> [-- Attachment #1: Type: text/plain, Size: 30339 bytes --]
> 
> On Mon, Dec 16, 2024 at 09:41:06AM +0800, Even Xu wrote:
> > diff --git a/Documentation/hid/intel-thc-hid.rst b/Documentation/hid/intel-thc-hid.rst
> > new file mode 100644
> > index 000000000000..e9452c11d8de
> > --- /dev/null
> > +++ b/Documentation/hid/intel-thc-hid.rst
> > @@ -0,0 +1,568 @@
> > +.. SPDX-License-Identifier: GPL-2.0
> > +
> > +=================================
> > +Intel Touch Host Controller (THC)
> > +=================================
> > +
> > +Touch Host Controller is the name of the IP block in PCH that interface with Touch Devices (ex:
> > +touchscreen, touchpad etc.). It is comprised of 3 key functional blocks:
> > +
> > +- A natively half-duplex Quad I/O capable SPI master
> > +- Low latency I2C interface to support HIDI2C compliant devices
> > +- A HW sequencer with RW DMA capability to system memory
> > +
> > +It has a single root space IOSF Primary interface that supports transactions to/from touch devices.
> > +Host driver configures and controls the touch devices over THC interface. THC provides high
> > +bandwidth DMA services to the touch driver and transfers the HID report to host system main memory.
> > +
> > +Hardware sequencer within the THC is responsible for transferring (via DMA) data from touch devices
> > +into system memory. A ring buffer is used to avoid data loss due to asynchronous nature of data
> > +consumption (by host) in relation to data production (by touch device via DMA).
> > +
> > +Unlike other common SPI/I2C controllers, THC handles the HID device data interrupt and reset
> > +signals directly.
> > +
> > +1. Overview
> > +===========
> > +
> > +1.1 THC software/hardware stack
> > +-------------------------------
> > +
> > +Below diagram illustrates the high-level architecture of THC software/hardware stack, which is fully
> > +capable of supporting HIDSPI/HIDI2C protocol in Linux OS.
> > +
> > +::
> > +
> > +  ----------------------------------------------
> > + |      +-----------------------------------+   |
> > + |      |           Input Device            |   |
> > + |      +-----------------------------------+   |
> > + |      +-----------------------------------+   |
> > + |      |       HID Multi-touch Driver      |   |
> > + |      +-----------------------------------+   |
> > + |      +-----------------------------------+   |
> > + |      |             HID Core              |   |
> > + |      +-----------------------------------+   |
> > + |      +-----------------------------------+   |
> > + |      |    THC QuickSPI/QuickI2C Driver   |   |
> > + |      +-----------------------------------+   |
> > + |      +-----------------------------------+   |
> > + |      |      THC Hardware Driver          |   |
> > + |      +-----------------------------------+   |
> > + |      +----------------+ +----------------+   |
> > + |  SW  | PCI Bus Driver | | ACPI Resource  |   |
> > + |      +----------------+ +----------------+   |
> > +  ----------------------------------------------
> > +  ----------------------------------------------
> > + |      +-----------------------------------+   |
> > + |  HW  |              PCI Bus              |   |
> > + |      +-----------------------------------+   |
> > + |      +-----------------------------------+   |
> > + |      |           THC Controller          |   |
> > + |      +-----------------------------------+   |
> > + |      +-----------------------------------+   |
> > + |      |              Touch IC             |   |
> > + |      +-----------------------------------+   |
> > +  ----------------------------------------------
> > +
> > +Touch IC (TIC), also as known as the Touch devices (touchscreen or touchpad). The discrete analog
> > +components that sense and transfer either discrete touch data or heatmap data in the form of HID
> > +reports over the SPI/I2C bus to the THC Controller on the host.
> > +
> > +THC Host Controller, which is a PCI device HBA (host bus adapter), integrated into the PCH, that
> > +serves as a bridge between the Touch ICs and the host.
> > +
> > +THC Hardware Driver, provides THC hardware operation APIs for above QuickSPI/QuickI2C driver, it
> > +accesses THC MMIO registers to configure and control THC hardware.
> > +
> > +THC QuickSPI/QuickI2C driver, also as known as HIDSPI/HIDI2C driver, is registered as a HID
> > +low-level driver that manages the THC Controller and implements HIDSPI/HIDI2C protocol.
> > +
> > +
> > +1.2 THC hardware diagram
> > +------------------------
> > +Below diagram shows THC hardware components::
> > +
> > +                      ---------------------------------
> > +                     |          THC Controller         |
> > +                     |  +---------------------------+  |
> > +                     |  |     PCI Config Space      |  |
> > +                     |  +---------------------------+  |
> > +                     |  +---------------------------+  |
> > +                     |  +       MMIO Registers      |  |
> > +                     |  +---------------------------+  |
> > + +---------------+   |  +------------+ +------------+  |
> > + | System Memory +---+--+      DMA   | |   PIO      |  |
> > + +---------------+   |  +------------+ +------------+  |
> > +                     |  +---------------------------+  |
> > +                     |  |       HW Sequencer        |  |
> > +                     |  +---------------------------+  |
> > +                     |  +------------+ +------------+  |
> > +                     |  |  SPI/I2C   | |    GPIO    |  |
> > +                     |  | Controller | | Controller |  |
> > +                     |  +------------+ +------------+  |
> > +                      ---------------------------------
> > +
> > +As THC is exposed as a PCI devices, so it has standard PCI config space registers for PCI
> > +enumeration and configuration.
> > +
> > +MMIO Registers, which provide registers access for driver to configure and control THC hardware,
> > +the registers include several categories: Interrupt status and control, DMA configure,
> > +PIO (Programmed I/O, defined in section 3.2) status and control, SPI bus configure, I2C subIP
> > +status and control, reset status and control...
> > +
> > +THC provides two ways for driver to communicate with external Touch ICs: PIO and DMA.
> > +PIO can let driver manually write/read data to/from Touch ICs, instead, THC DMA can
> > +automatically write/read data without driver involved.
> > +
> > +HW Sequencer includes THC major logic, it gets instruction from MMIO registers to control
> > +SPI bus and I2C bus to finish a bus data transaction, it also can automatically handle
> > +Touch ICs interrupt and start DMA receive/send data from/to Touch ICs according to interrupt
> > +type. That means THC HW Sequencer understands HIDSPI/HIDI2C transfer protocol, and handle
> > +the communication without driver involved, what driver needs to do is just configure the THC
> > +properly, and prepare the formatted data packet or handle received data packet.
> > +
> > +As THC supports HIDSPI/HIDI2C protocols, it has SPI controller and I2C subIP in it to expose
> > +SPI bus and I2C bus. THC also integrates a GPIO controller to provide interrupt line support
> > +and reset line support.
> > +
> > +2. THC Hardware Interface
> > +=========================
> > +
> > +2.1 Host Interface
> > +------------------
> > +
> > +THC is exposed as "PCI Digitizer device" to the host. The PCI product and device IDs are
> > +changed from different generations of processors. So the source code which enumerates drivers
> > +needs to update from generation to generation.
> > +
> > +
> > +2.2 Device Interface
> > +--------------------
> > +
> > +THC supports two types of bus for Touch IC connection: Enhanced SPI bus and I2C bus.
> > +
> > +2.2.1 SPI Port
> > +~~~~~~~~~~~~~~
> > +
> > +When PORT_TYPE = 00b in MMIO registers, THC uses SPI interfaces to communicate with external
> > +Touch IC. THC enhanced SPI Bus supports different SPI modes: standard Single IO mode,
> > +Dual IO mode and Quad IO mode.
> > +
> > +In Single IO mode, THC drives MOSI line to send data to Touch ICs, and receives data from Touch
> > +ICs data from MISO line. In Dual IO mode, THC drivers MOSI and MISO both for data sending, and
> > +also receives the data on both line. In Quad IO mode, there are other two lines (IO2 and IO3)
> > +are added, THC drives MOSI (IO0), MISO (IO1), IO2 and IO3 at the same time for data sending, and
> > +also receives the data on those 4 lines. Driver needs to configure THC in different mode by
> > +setting different opcode.
> > +
> > +Beside IO mode, driver also needs to configure SPI bus speed. THC supports up to 42MHz SPI clock
> > +on Intel Lunar Lake platform.
> > +
> > +For THC sending data to Touch IC, the data flow on SPI bus::
> > +
> > + | --------------------THC sends---------------------------------|
> > + <8Bits OPCode><24Bits Slave Address><Data><Data><Data>...........
> > +
> > +For THC receiving data from Touch IC, the data flow on SPI bus::
> > +
> > + | ---------THC Sends---------------||-----Touch IC sends--------|
> > + <8Bits OPCode><24Bits Slave Address><Data><Data><Data>...........
> > +
> > +2.2.2 I2C Port
> > +~~~~~~~~~~~~~~
> > +
> > +THC also integrates I2C controller in it, it's called I2C SubSystem. When PORT_TYPE = 01, THC
> > +is configured to I2C mode. Comparing to SPI mode which can be configured through MMIO registers
> > +directly, THC needs to use PIO read (by setting SubIP read opcode) to I2C subIP APB registers'
> > +value and use PIO write (by setting SubIP write opcode) to do a write operation.
> > +
> > +2.2.3 GPIO interface
> > +~~~~~~~~~~~~~~~~~~~~
> > +
> > +THC also includes two GPIO pins, one for interrupt and the other for device reset control.
> > +
> > +Interrupt line can be configured to either level triggerred or edge triggerred by setting MMIO
> > +Control register.
> > +
> > +Reset line is controlled by BIOS (or EFI) through ACPI _RST method, driver needs to call this
> > +device ACPI _RST method to reset touch IC during initialization.
> > +
> > +3. High level concept
> > +=====================
> > +
> > +3.1 Opcode
> > +----------
> > +
> > +Opcode (operation code) is used to tell THC or Touch IC what the operation will be, such as PIO
> > +read or PIO write.
> > +
> > +When THC is configured to SPI mode, opcodes are used for determining the read/write IO mode.
> > +There are some OPCode examples for SPI IO mode:
> > +
> > +=======   ==============================
> > +opcode    Corresponding SPI command
> > +=======   ==============================
> > +0x0B      Read Single I/O
> > +0x02      Write Single I/O
> > +0xBB      Read Dual I/O
> > +0xB2      Write Dual I/O
> > +0xEB      Read Quad I/O
> > +0xE2      Write Quad I/O
> > +=======   ==============================
> > +
> > +In general, different touch IC has different OPCode definition. According to HIDSPI
> > +protocol whitepaper, those OPCodes are defined in device ACPI table, and driver needs to
> > +query those information through OS ACPI APIs during driver initialization, then configures
> > +THC MMIO OPCode registers with correct setting.
> > +
> > +When THC is working in I2C mode, opcodes are used to tell THC what's the next PIO type:
> > +I2C SubIP APB register read, I2C SubIP APB register write, I2C touch IC device read,
> > +I2C touch IC device write, I2C touch IC device write followed by read.
> > +
> > +Here are the THC pre-defined opcodes for I2C mode:
> > +
> > +=======   ===================================================   ===========
> > +opcode    Corresponding I2C command                             Address
> > +=======   ===================================================   ===========
> > +0x12      Read I2C SubIP APB internal registers                 0h - FFh
> > +0x13      Write I2C SubIP APB internal registers                0h - FFh
> > +0x14      Read external Touch IC through I2C bus                N/A
> > +0x18      Write external Touch IC through I2C bus               N/A
> > +0x1C      Write then read external Touch IC through I2C bus     N/A
> > +=======   ===================================================   ===========
> > +
> > +3.2 PIO
> > +-------
> > +
> > +THC provides a programmed I/O (PIO) access interface for the driver to access the touch IC's
> > +configuration registers, or access I2C subIP's configuration registers. To use PIO to perform
> > +I/O operations, driver should pre-program PIO control registers and PIO data registers and kick
> > +off the sequencing cycle. THC uses different PIO opcodes to distinguish different PIO
> > +operations (PIO read/write/write followed by read).
> > +
> > +If there is a Sequencing Cycle In Progress and an attempt is made to program any of the control,
> > +address, or data register the cycle is blocked and a sequence error will be encountered.
> > +
> > +A status bit indicates when the cycle has completed allowing the driver to know when read results
> > +can be checked and/or when to initiate a new command. If enabled, the cycle done assertion can
> > +interrupt driver with an interrupt.
> > +
> > +Because THC only has 16 FIFO registers for PIO, so all the data transfer through PIO shouldn't
> > +exceed 64 bytes.
> > +
> > +As DMA needs max packet size for transferring configuration, and the max packet size information
> > +always in HID device descriptor which needs THC driver to read it out from HID Device (Touch IC).
> > +So PIO typical use case is, before DMA initialization, write RESET command (PIO write), read
> > +RESET response (PIO read or PIO write followed by read), write Power ON command (PIO write), read
> > +device descriptor (PIO read).
> > +
> > +For how to issue a PIO operation, here is the steps which driver needs follow:
> > +
> > +- Program read/write data size in THC_SS_BC.
> > +- Program I/O target address in THC_SW_SEQ_DATA0_ADDR.
> > +- If write, program the write data in THC_SW_SEQ_DATA0..THC_SW_SEQ_DATAn.
> > +- Program the PIO opcode in THC_SS_CMD.
> > +- Set TSSGO = 1 to start the PIO write sequence.
> > +- If THC_SS_CD_IE = 1, SW will receives a MSI when the PIO is completed.
> > +- If read, read out the data in THC_SW_SEQ_DATA0..THC_SW_SEQ_DATAn.
> > +
> > +3.3 DMA
> > +-------
> > +
> > +THC has 4 DMA channels: Read DMA1, Read DMA2, Write DMA and Software DMA.
> > +
> > +3.3.1 Read DMA Channel
> > +~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +THC has two Read DMA engines: 1st RxDMA (RxDMA1) and 2nd RxDMA (RxDMA2). RxDMA1 is reserved for
> > +raw data mode. RxDMA2 is used for HID data mode and it is the RxDMA engine currently driver uses
> > +for HID input report data retrieval.
> > +
> > +RxDMA's typical use case is auto receiving the data from Touch IC. Once RxDMA is enabled by
> > +software, THC will start auto-handling receiving logic.
> > +
> > +For SPI mode, THC RxDMA sequence is: when Touch IC triggers a interrupt to THC, THC reads out
> > +report header to identify what's the report type, and what's the report length, according to
> > +above information, THC reads out report body to internal FIFO and start RxDMA coping the data
> > +to system memory. After that, THC update interrupt cause register with report type, and update
> > +RxDMA PRD table read pointer, then trigger a MSI interrupt to notify driver RxDMA finishing
> > +data receiving.
> > +
> > +For I2C mode, THC RxDMA's behavior is little difference, because of HIDI2C protocol difference with
>                                      "a little bit different, ..."

Thanks, will fix it.

> > +HIDSPI protocol, RxDMA only be used to receive input report. The sequence is, when Touch IC
> > +triggers a interrupt to THC, THC first reads out 2 bytes from input report address to determine the
> > +packet length, then use this packet length to start a DMA reading from input report address for
> > +input report data. After that, THC update RxDMA PRD table read pointer, then trigger a MSI interrupt
> > +to notify driver input report data is ready in system memory.
> > +
> > +All above sequence is hardware automatically handled, all driver needs to do is configure RxDMA and
> > +waiting for interrupt ready then read out the data from system memory.
> > +
> > +3.3.2 Software DMA channel
> > +~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +THC supports a software triggerred RxDMA mode to read the touch data from touch IC. This SW RxDMA
> > +is the 3rd THC RxDMA engine with the similar functionalities as the existing two RxDMAs, the only
> > +difference is this SW RxDMA is triggerred by software, and RxDMA2 is triggerred by external Touch IC
> > +interrupt. It gives a flexiblity to software driver to use RxDMA read Touch IC data in any time.
> > +
> > +Before software starts a SW RxDMA, it shall stop the 1st and 2nd RxDMA, clear PRD read/write pointer
> > +and quiesce the device interrupt (THC_DEVINT_QUIESCE_HW_STS = 1), other operations are the same with
> > +RxDMA.
> > +
> > +3.3.3 Write DMA Channel
> > +~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +THC has one write DMA engine, which can be used for sending data to Touch IC automatically.
> > +According to HIDSPI and HIDI2C protocol, every time only one command can be sent to touch IC, and
> > +before last command is completely handled, next command cannot be sent, THC write DMA engine only
> > +supports single PRD table.
> > +
> > +What driver needs to do is, preparing PRD table and DMA buffer, then copy data to DMA buffer and
> > +update PRD table with buffer address and buffer length, then start write DMA. THC will
> > +automatically send the data to touch IC, and trigger a DMA completion interrupt once transferring
> > +is done.
> > +
> > +3.4 PRD
> > +-------
> > +
> > +Physical Region Descriptor (PRD) provides the memory mapping description for THC DMAs.
> > +
> > +3.4.1 PRD table and entry
> > +~~~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +In order to improve physical DMA memory usage, modern drivers trend to allocate a virtually
> > +contiguous, but physically fragmented buffer of memory for each data buffer. Linux OS also
> > +provide SGL (scatter gather list) APIs to support this usage.
> > +
> > +THC uses PRD table (physical region descriptor) to support the corresponding OS kernel
> > +SGL that describes the virtual to physical buffer mapping.
> > +
> > +::
> > +
> > +  ------------------------      --------------       --------------
> > + | PRD table base address +----+ PRD table #1 +-----+ PRD Entry #1 |
> > +  ------------------------      --------------       --------------
> > +                                                     --------------
> > +                                                    | PRD Entry #2 |
> > +                                                     --------------
> > +                                                     --------------
> > +                                                    | PRD Entry #n |
> > +                                                     --------------
> > +
> > +The read DMA engine supports multiple PRD tables held within a circular buffer that allow the THC
> > +to support multiple data buffers from the Touch IC. This allows host SW to arm the Read DMA engine
> > +with multiple buffers, allowing the Touch IC to send multiple data frames to the THC without SW
> > +interaction. This capability is required when the CPU processes touch frames slower than the
> > +Touch IC can send them.
> > +
> > +To simplify the design, SW assumes worst-case memory fragmentation. Therefore,each PRD table shall
> > +contain the same number of PRD entries, allowing for a global register (per Touch IC) to hold the
> > +number of PRD-entries per PRD table.
> > +
> > +SW allocates up to 128 PRD tables per Read DMA engine as specified in the THC_M_PRT_RPRD_CNTRL.PCD
> > +register field. The number of PRD tables should equal the number of data buffers.
> > +
> > +Max OS memory fragmentation will be at a 4KB boundary, thus to address 1MB of virtually contiguous
> > +memory 256 PRD entries are required for a single PRD Table. SW writes the number of PRD entries
> > +for each PRD table in the THC_M_PRT_RPRD_CNTRL.PTEC register field. The PRD entry's length must be
> > +multiple of 4KB except for the last entry in a PRD table.
> > +
> > +SW allocates all the data buffers and PRD tables only once at host initialization.
> > +
> > +3.4.2 PRD Write pointer and read pointer
> > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +As PRD tables are organized as a Circular Buffer (CB), a read pointer and a write pointer for a CB
> > +are needed.
> > +
> > +DMA HW consumes the PRD tables in the CB, one PRD entry at a time until the EOP bit is found set
> > +in a PRD entry. At this point HW increments the PRD read pointer. Thus, the read pointer points
> > +to the PRD which the DMA engine is currently processing. This pointer rolls over once the circular
> > +buffer's depth has been traversed with bit[7] the Rollover bit. E.g. if the DMA CB depth is equal
> > +to 4 entries (0011b), then the read pointers will follow this pattern (HW is required to honor
> > +this behavior): 00h 01h 02h 03h 80h 81h 82h 83h 00h 01h ...
> > +
> > +The write pointer is updated by SW. The write pointer points to location in the DMA CB, where the
> > +next PRD table is going to be stored. SW needs to ensure that this pointer rolls over once the
> > +circular buffer's depth has been traversed with Bit[7] as the rollover bit. E.g. if the DMA CB
> > +depth is equal to 5 entries (0100b), then the write pointers will follow this pattern (SW is
> > +required to honor this behavior): 00h 01h 02h 03h 04h 80h 81h 82h 83h 84h 00h 01h ..
> > +
> > +3.4.3 PRD descriptor structure
> > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +Intel THC uses PRD entry descriptor for every PRD entry. Every PRD entry descriptor occupies
> > +128 bits memories:
> > +
> > +===================   ========   ===============================================
> > +struct field          bit(s)     description
> > +===================   ========   ===============================================
> > +dest_addr             53..0      destination memory address, as every entry
> > +                                 is 4KB, ignore lowest 10 bits of address.
> > +reserved1             54..62     reserved
> > +int_on_completion     63         completion interrupt enable bit, if this bit
> > +                                 set it means THC will trigger a completion
> > +                                 interrupt. This bit is set by SW driver.
> > +len                   87..64     how many bytes of data in this entry.
> > +end_of_prd            88         end of PRD table bit, if this bit is set,
> > +                                 it means this entry is last entry in this PRD
> > +                                 table. This bit is set by SW driver.
> > +hw_status             90..89     HW status bits
> > +reserved2             127..91    reserved
> > +===================   ========   ===============================================
> > +
> > +And one PRD table can include up to 256 PRD entries, as every entries is 4K bytes, so every
> > +PRD table can describe 1M bytes memory.
> > +
> > +.. code-block:: c
> > +
> > +   struct thc_prd_table {
> > +        struct thc_prd_entry entries[PRD_ENTRIES_NUM];
> > +   };
> > +
> > +In general, every PRD table means one HID touch data packet. Every DMA engine can support
> > +up to 128 PRD tables (except write DMA, write DMA only has one PRD table). SW driver is responsible
> > +to get max packet length from touch IC, and use this max packet length to create PRD entries for
> > +each PRD table.
> > +
> > +4. HIDSPI support (QuickSPI)
> > +============================
> > +
> > +Intel THC is total compatible with HIDSPI protocol, THC HW sequenser can accelerate HIDSPI
> > +protocol transferring.
> > +
> > +4.1 Reset Flow
> > +--------------
> > +
> > +- Call ACPI _RST method to reset Touch IC device.
> > +- Read the reset response from TIC through PIO read.
> > +- Issue a command to retrieve device descriptor from Touch IC through PIO write.
> > +- Read the device descriptor from Touch IC through PIO read.
> > +- If the device descriptor is valid, allocate DMA buffers and configure all DMA channels.
> > +- Issue a command to retrieve report descriptor from Touch IC through DMA.
> > +
> > +4.2 Input Report Data Flow
> > +--------------------------
> > +
> > +Basic Flow:
> > +
> > +- Touch IC interrupts the THC Controller using an in-band THC interrupt.
> > +- THC Sequencer reads the input report header by transmitting read approval as a signal
> > +  to the Touch IC to prepare for host to read from the device.
> > +- THC Sequencer executes a Input Report Body Read operation corresponding to the value
> > +  reflected in “Input Report Length” field of the Input Report Header.
> > +- THC DMA engine begins fetching data from the THC Sequencer and writes to host memory
> > +  at PRD entry 0 for the current CB PRD table entry. This process continues until the
> > +  THC Sequencer signals all data has been read or the THC DMA Read Engine reaches the
> > +  end of it's last PRD entry (or both).
> > +- The THC Sequencer checks for the “Last Fragment Flag” bit in the Input Report Header.
> > +  If it is clear, the THC Sequencer enters an idle state.
> > +- If the “Last Fragment Flag” bit is enabled the THC Sequencer enters End-of-Frame Processing.
> > +
> > +THC Sequencer End of Frame Processing:
> > +
> > +- THC DMA engine increments the read pointer of the Read PRD CB, sets EOF interrupt status
> > +  in RxDMA2 register (THC_M_PRT_READ_DMA_INT_STS_2).
> > +- If THC EOF interrupt is enabled by the driver in the control register (THC_M_PRT_READ_DMA_CNTRL_2),
> > +  generates interrupt to software.
> > +
> > +Sequence of steps to read data from RX DMA buffer:
> > +
> > +- THC QuickSPI driver checks CB write Ptr and CB read Ptr to identify if any data frame in DMA
> > +  circular buffers.
> > +- THC QuickSPI driver gets first unprocessed PRD table.
> > +- THC QuickSPI driver scans all PRD entries in this PRD table to calculate the total frame size.
> > +- THC QuickSPI driver copies all frame data out.
> > +- THC QuickSPI driver checks the data type according to input report body, and calls related
> > +  callbacks to process the data.
> > +- THC QuickSPI driver updates write Ptr.
> > +
> > +4.3 Output Report Data Flow
> > +---------------------------
> > +
> > +Generic Output Report Flow:
> > +
> > +- HID core calls raw_request callback with a request to THC QuickSPI driver.
> > +- THC QuickSPI Driver converts request provided data into the output report packet and copies it
> > +  to THC's write DMA buffer.
> > +- Start TxDMA to complete the write operation.
> > +
> > +5. HIDI2C support (QuickI2C)
> > +============================
> > +
> > +5.1 Reset Flow
> > +--------------
> > +
> > +- Read device descriptor from Touch IC device through PIO write followed by read.
> > +- If the device descriptor is valid, allocate DMA buffers and configure all DMA channels.
> > +- Use PIO or TxDMA to write a SET_POWER request to TIC's command register, and check if the
> > +  write operation is successfully completed.
> > +- Use PIO or TxDMA to write a RESET request to TIC's command register. If the write operation
> > +  is successfully completed, wait for reset response from TIC.
> > +- Use SWDMA to read report descriptor through TIC's report descriptor register.
> > +
> > +5.2 Input Report Data Flow
> > +--------------------------
> > +
> > +Basic Flow:
> > +
> > +- Touch IC asserts the interrupt indicating that it has an interrupt to send to HOST.
> > +  THC Sequencer issues a READ request over the I2C bus. The HIDI2C device returns the
> > +  first 2 bytes from the HIDI2C device which contains the length of the received data.
> > +- THC Sequencer continues the Read operation as per the size of data indicated in the
> > +  length field.
> > +- THC DMA engine begins fetching data from the THC Sequencer and writes to host memory
> > +  at PRD entry 0 for the current CB PRD table entry. THC writes 2Bytes for length field
> > +  plus the remaining data to RxDMA buffer. This process continues until the THC Sequencer
> > +  signals all data has been read or the THC DMA Read Engine reaches the end of it's last
> > +  PRD entry (or both).
> > +- THC Sequencer enters End-of-Input Report Processing.
> > +- If the device has no more input reports to send to the host, it de-asserts the interrupt
> > +  line. For any additional input reports, device keeps the interrupt line asserted and
> > +  steps 1 through 4 in the flow are repeated.
> > +
> > +THC Sequencer End of Input Report Processing:
> > +
> > +- THC DMA engine increments the read pointer of the Read PRD CB, sets EOF interrupt status
> > +  in RxDMA 2 register (THC_M_PRT_READ_DMA_INT_STS_2).
> > +- If THC EOF interrupt is enabled by the driver in the control register
> > +  (THC_M_PRT_READ_DMA_CNTRL_2), generates interrupt to software.
> > +
> > +Sequence of steps to read data from RX DMA buffer:
> > +
> > +- THC QuickI2C driver checks CB write Ptr and CB read Ptr to identify if any data frame in DMA
> > +  circular buffers.
> > +- THC QuickI2C driver gets first unprocessed PRD table.
> > +- THC QuickI2C driver scans all PRD entries in this PRD table to calculate the total frame size.
> > +- THC QuickI2C driver copies all frame data out.
> > +- THC QuickI2C driver call hid_input_report to send the input report content to HID core, which
> > +  includes Report ID + Report Data Content (remove the length field from the original report
> > +  data).
> > +- THC QuickI2C driver updates write Ptr.
> > +
> > +5.3 Output Report Data Flow
> > +---------------------------
> > +
> > +Generic Output Report Flow:
> > +
> > +- HID core call THC QuickI2C raw_request callback.
> > +- THC QuickI2C uses PIO or TXDMA to write a SET_REPORT request to TIC's command register. Report
> > +  type in SET_REPORT should be set to Output.
> > +- THC QuickI2C programs TxDMA buffer with TX Data to be written to TIC's data register. The first
> > +  2 bytes should indicate the length of the report followed by the report contents including
> > +  Report ID.
> > +
> > +6. THC Debugging
> > +================
> > +
> > +To debug THC, event tracing mechanism is used. To enable debug logs::
> > +
> > +  echo 1 > /sys/kernel/debug/tracing/events/intel_thc/enable
> > +  cat /sys/kernel/debug/tracing/trace
> > +
> > +7. Reference
> > +============
> > +- HIDSPI: https://download.microsoft.com/download/c/a/0/ca07aef3-3e10-4022-b1e9-c98cea99465d/HidSpiProtocolSpec.pdf
> > +- HIDI2C: https://download.microsoft.com/download/7/d/d/7dd44bb7-2a7a-4505-ac1c-7227d3d96d5b/hid-over-i2c-protocol-spec-v1-0.docx
> 
> The rest looks good.
> 
> Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>

Thank you very much!

Best Regards,
Even Xu

> 
> -- 
> An old man doll... just what I always wanted! - Clara
> 
> [-- Attachment #2: signature.asc --]
> [-- Type: application/pgp-signature, Size: 228 bytes --]
diff mbox series

Patch

diff --git a/Documentation/hid/index.rst b/Documentation/hid/index.rst
index af02cf7cfa82..baf156b44b58 100644
--- a/Documentation/hid/index.rst
+++ b/Documentation/hid/index.rst
@@ -18,4 +18,5 @@  Human Interface Devices (HID)
 
    hid-alps
    intel-ish-hid
+   intel-thc-hid
    amd-sfh-hid
diff --git a/Documentation/hid/intel-thc-hid.rst b/Documentation/hid/intel-thc-hid.rst
new file mode 100644
index 000000000000..e9452c11d8de
--- /dev/null
+++ b/Documentation/hid/intel-thc-hid.rst
@@ -0,0 +1,568 @@ 
+.. SPDX-License-Identifier: GPL-2.0
+
+=================================
+Intel Touch Host Controller (THC)
+=================================
+
+Touch Host Controller is the name of the IP block in PCH that interface with Touch Devices (ex:
+touchscreen, touchpad etc.). It is comprised of 3 key functional blocks:
+
+- A natively half-duplex Quad I/O capable SPI master
+- Low latency I2C interface to support HIDI2C compliant devices
+- A HW sequencer with RW DMA capability to system memory
+
+It has a single root space IOSF Primary interface that supports transactions to/from touch devices.
+Host driver configures and controls the touch devices over THC interface. THC provides high
+bandwidth DMA services to the touch driver and transfers the HID report to host system main memory.
+
+Hardware sequencer within the THC is responsible for transferring (via DMA) data from touch devices
+into system memory. A ring buffer is used to avoid data loss due to asynchronous nature of data
+consumption (by host) in relation to data production (by touch device via DMA).
+
+Unlike other common SPI/I2C controllers, THC handles the HID device data interrupt and reset
+signals directly.
+
+1. Overview
+===========
+
+1.1 THC software/hardware stack
+-------------------------------
+
+Below diagram illustrates the high-level architecture of THC software/hardware stack, which is fully
+capable of supporting HIDSPI/HIDI2C protocol in Linux OS.
+
+::
+
+  ----------------------------------------------
+ |      +-----------------------------------+   |
+ |      |           Input Device            |   |
+ |      +-----------------------------------+   |
+ |      +-----------------------------------+   |
+ |      |       HID Multi-touch Driver      |   |
+ |      +-----------------------------------+   |
+ |      +-----------------------------------+   |
+ |      |             HID Core              |   |
+ |      +-----------------------------------+   |
+ |      +-----------------------------------+   |
+ |      |    THC QuickSPI/QuickI2C Driver   |   |
+ |      +-----------------------------------+   |
+ |      +-----------------------------------+   |
+ |      |      THC Hardware Driver          |   |
+ |      +-----------------------------------+   |
+ |      +----------------+ +----------------+   |
+ |  SW  | PCI Bus Driver | | ACPI Resource  |   |
+ |      +----------------+ +----------------+   |
+  ----------------------------------------------
+  ----------------------------------------------
+ |      +-----------------------------------+   |
+ |  HW  |              PCI Bus              |   |
+ |      +-----------------------------------+   |
+ |      +-----------------------------------+   |
+ |      |           THC Controller          |   |
+ |      +-----------------------------------+   |
+ |      +-----------------------------------+   |
+ |      |              Touch IC             |   |
+ |      +-----------------------------------+   |
+  ----------------------------------------------
+
+Touch IC (TIC), also as known as the Touch devices (touchscreen or touchpad). The discrete analog
+components that sense and transfer either discrete touch data or heatmap data in the form of HID
+reports over the SPI/I2C bus to the THC Controller on the host.
+
+THC Host Controller, which is a PCI device HBA (host bus adapter), integrated into the PCH, that
+serves as a bridge between the Touch ICs and the host.
+
+THC Hardware Driver, provides THC hardware operation APIs for above QuickSPI/QuickI2C driver, it
+accesses THC MMIO registers to configure and control THC hardware.
+
+THC QuickSPI/QuickI2C driver, also as known as HIDSPI/HIDI2C driver, is registered as a HID
+low-level driver that manages the THC Controller and implements HIDSPI/HIDI2C protocol.
+
+
+1.2 THC hardware diagram
+------------------------
+Below diagram shows THC hardware components::
+
+                      ---------------------------------
+                     |          THC Controller         |
+                     |  +---------------------------+  |
+                     |  |     PCI Config Space      |  |
+                     |  +---------------------------+  |
+                     |  +---------------------------+  |
+                     |  +       MMIO Registers      |  |
+                     |  +---------------------------+  |
+ +---------------+   |  +------------+ +------------+  |
+ | System Memory +---+--+      DMA   | |   PIO      |  |
+ +---------------+   |  +------------+ +------------+  |
+                     |  +---------------------------+  |
+                     |  |       HW Sequencer        |  |
+                     |  +---------------------------+  |
+                     |  +------------+ +------------+  |
+                     |  |  SPI/I2C   | |    GPIO    |  |
+                     |  | Controller | | Controller |  |
+                     |  +------------+ +------------+  |
+                      ---------------------------------
+
+As THC is exposed as a PCI devices, so it has standard PCI config space registers for PCI
+enumeration and configuration.
+
+MMIO Registers, which provide registers access for driver to configure and control THC hardware,
+the registers include several categories: Interrupt status and control, DMA configure,
+PIO (Programmed I/O, defined in section 3.2) status and control, SPI bus configure, I2C subIP
+status and control, reset status and control...
+
+THC provides two ways for driver to communicate with external Touch ICs: PIO and DMA.
+PIO can let driver manually write/read data to/from Touch ICs, instead, THC DMA can
+automatically write/read data without driver involved.
+
+HW Sequencer includes THC major logic, it gets instruction from MMIO registers to control
+SPI bus and I2C bus to finish a bus data transaction, it also can automatically handle
+Touch ICs interrupt and start DMA receive/send data from/to Touch ICs according to interrupt
+type. That means THC HW Sequencer understands HIDSPI/HIDI2C transfer protocol, and handle
+the communication without driver involved, what driver needs to do is just configure the THC
+properly, and prepare the formatted data packet or handle received data packet.
+
+As THC supports HIDSPI/HIDI2C protocols, it has SPI controller and I2C subIP in it to expose
+SPI bus and I2C bus. THC also integrates a GPIO controller to provide interrupt line support
+and reset line support.
+
+2. THC Hardware Interface
+=========================
+
+2.1 Host Interface
+------------------
+
+THC is exposed as "PCI Digitizer device" to the host. The PCI product and device IDs are
+changed from different generations of processors. So the source code which enumerates drivers
+needs to update from generation to generation.
+
+
+2.2 Device Interface
+--------------------
+
+THC supports two types of bus for Touch IC connection: Enhanced SPI bus and I2C bus.
+
+2.2.1 SPI Port
+~~~~~~~~~~~~~~
+
+When PORT_TYPE = 00b in MMIO registers, THC uses SPI interfaces to communicate with external
+Touch IC. THC enhanced SPI Bus supports different SPI modes: standard Single IO mode,
+Dual IO mode and Quad IO mode.
+
+In Single IO mode, THC drives MOSI line to send data to Touch ICs, and receives data from Touch
+ICs data from MISO line. In Dual IO mode, THC drivers MOSI and MISO both for data sending, and
+also receives the data on both line. In Quad IO mode, there are other two lines (IO2 and IO3)
+are added, THC drives MOSI (IO0), MISO (IO1), IO2 and IO3 at the same time for data sending, and
+also receives the data on those 4 lines. Driver needs to configure THC in different mode by
+setting different opcode.
+
+Beside IO mode, driver also needs to configure SPI bus speed. THC supports up to 42MHz SPI clock
+on Intel Lunar Lake platform.
+
+For THC sending data to Touch IC, the data flow on SPI bus::
+
+ | --------------------THC sends---------------------------------|
+ <8Bits OPCode><24Bits Slave Address><Data><Data><Data>...........
+
+For THC receiving data from Touch IC, the data flow on SPI bus::
+
+ | ---------THC Sends---------------||-----Touch IC sends--------|
+ <8Bits OPCode><24Bits Slave Address><Data><Data><Data>...........
+
+2.2.2 I2C Port
+~~~~~~~~~~~~~~
+
+THC also integrates I2C controller in it, it's called I2C SubSystem. When PORT_TYPE = 01, THC
+is configured to I2C mode. Comparing to SPI mode which can be configured through MMIO registers
+directly, THC needs to use PIO read (by setting SubIP read opcode) to I2C subIP APB registers'
+value and use PIO write (by setting SubIP write opcode) to do a write operation.
+
+2.2.3 GPIO interface
+~~~~~~~~~~~~~~~~~~~~
+
+THC also includes two GPIO pins, one for interrupt and the other for device reset control.
+
+Interrupt line can be configured to either level triggerred or edge triggerred by setting MMIO
+Control register.
+
+Reset line is controlled by BIOS (or EFI) through ACPI _RST method, driver needs to call this
+device ACPI _RST method to reset touch IC during initialization.
+
+3. High level concept
+=====================
+
+3.1 Opcode
+----------
+
+Opcode (operation code) is used to tell THC or Touch IC what the operation will be, such as PIO
+read or PIO write.
+
+When THC is configured to SPI mode, opcodes are used for determining the read/write IO mode.
+There are some OPCode examples for SPI IO mode:
+
+=======   ==============================
+opcode    Corresponding SPI command
+=======   ==============================
+0x0B      Read Single I/O
+0x02      Write Single I/O
+0xBB      Read Dual I/O
+0xB2      Write Dual I/O
+0xEB      Read Quad I/O
+0xE2      Write Quad I/O
+=======   ==============================
+
+In general, different touch IC has different OPCode definition. According to HIDSPI
+protocol whitepaper, those OPCodes are defined in device ACPI table, and driver needs to
+query those information through OS ACPI APIs during driver initialization, then configures
+THC MMIO OPCode registers with correct setting.
+
+When THC is working in I2C mode, opcodes are used to tell THC what's the next PIO type:
+I2C SubIP APB register read, I2C SubIP APB register write, I2C touch IC device read,
+I2C touch IC device write, I2C touch IC device write followed by read.
+
+Here are the THC pre-defined opcodes for I2C mode:
+
+=======   ===================================================   ===========
+opcode    Corresponding I2C command                             Address
+=======   ===================================================   ===========
+0x12      Read I2C SubIP APB internal registers                 0h - FFh
+0x13      Write I2C SubIP APB internal registers                0h - FFh
+0x14      Read external Touch IC through I2C bus                N/A
+0x18      Write external Touch IC through I2C bus               N/A
+0x1C      Write then read external Touch IC through I2C bus     N/A
+=======   ===================================================   ===========
+
+3.2 PIO
+-------
+
+THC provides a programmed I/O (PIO) access interface for the driver to access the touch IC's
+configuration registers, or access I2C subIP's configuration registers. To use PIO to perform
+I/O operations, driver should pre-program PIO control registers and PIO data registers and kick
+off the sequencing cycle. THC uses different PIO opcodes to distinguish different PIO
+operations (PIO read/write/write followed by read).
+
+If there is a Sequencing Cycle In Progress and an attempt is made to program any of the control,
+address, or data register the cycle is blocked and a sequence error will be encountered.
+
+A status bit indicates when the cycle has completed allowing the driver to know when read results
+can be checked and/or when to initiate a new command. If enabled, the cycle done assertion can
+interrupt driver with an interrupt.
+
+Because THC only has 16 FIFO registers for PIO, so all the data transfer through PIO shouldn't
+exceed 64 bytes.
+
+As DMA needs max packet size for transferring configuration, and the max packet size information
+always in HID device descriptor which needs THC driver to read it out from HID Device (Touch IC).
+So PIO typical use case is, before DMA initialization, write RESET command (PIO write), read
+RESET response (PIO read or PIO write followed by read), write Power ON command (PIO write), read
+device descriptor (PIO read).
+
+For how to issue a PIO operation, here is the steps which driver needs follow:
+
+- Program read/write data size in THC_SS_BC.
+- Program I/O target address in THC_SW_SEQ_DATA0_ADDR.
+- If write, program the write data in THC_SW_SEQ_DATA0..THC_SW_SEQ_DATAn.
+- Program the PIO opcode in THC_SS_CMD.
+- Set TSSGO = 1 to start the PIO write sequence.
+- If THC_SS_CD_IE = 1, SW will receives a MSI when the PIO is completed.
+- If read, read out the data in THC_SW_SEQ_DATA0..THC_SW_SEQ_DATAn.
+
+3.3 DMA
+-------
+
+THC has 4 DMA channels: Read DMA1, Read DMA2, Write DMA and Software DMA.
+
+3.3.1 Read DMA Channel
+~~~~~~~~~~~~~~~~~~~~~~
+
+THC has two Read DMA engines: 1st RxDMA (RxDMA1) and 2nd RxDMA (RxDMA2). RxDMA1 is reserved for
+raw data mode. RxDMA2 is used for HID data mode and it is the RxDMA engine currently driver uses
+for HID input report data retrieval.
+
+RxDMA's typical use case is auto receiving the data from Touch IC. Once RxDMA is enabled by
+software, THC will start auto-handling receiving logic.
+
+For SPI mode, THC RxDMA sequence is: when Touch IC triggers a interrupt to THC, THC reads out
+report header to identify what's the report type, and what's the report length, according to
+above information, THC reads out report body to internal FIFO and start RxDMA coping the data
+to system memory. After that, THC update interrupt cause register with report type, and update
+RxDMA PRD table read pointer, then trigger a MSI interrupt to notify driver RxDMA finishing
+data receiving.
+
+For I2C mode, THC RxDMA's behavior is little difference, because of HIDI2C protocol difference with
+HIDSPI protocol, RxDMA only be used to receive input report. The sequence is, when Touch IC
+triggers a interrupt to THC, THC first reads out 2 bytes from input report address to determine the
+packet length, then use this packet length to start a DMA reading from input report address for
+input report data. After that, THC update RxDMA PRD table read pointer, then trigger a MSI interrupt
+to notify driver input report data is ready in system memory.
+
+All above sequence is hardware automatically handled, all driver needs to do is configure RxDMA and
+waiting for interrupt ready then read out the data from system memory.
+
+3.3.2 Software DMA channel
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+THC supports a software triggerred RxDMA mode to read the touch data from touch IC. This SW RxDMA
+is the 3rd THC RxDMA engine with the similar functionalities as the existing two RxDMAs, the only
+difference is this SW RxDMA is triggerred by software, and RxDMA2 is triggerred by external Touch IC
+interrupt. It gives a flexiblity to software driver to use RxDMA read Touch IC data in any time.
+
+Before software starts a SW RxDMA, it shall stop the 1st and 2nd RxDMA, clear PRD read/write pointer
+and quiesce the device interrupt (THC_DEVINT_QUIESCE_HW_STS = 1), other operations are the same with
+RxDMA.
+
+3.3.3 Write DMA Channel
+~~~~~~~~~~~~~~~~~~~~~~~
+
+THC has one write DMA engine, which can be used for sending data to Touch IC automatically.
+According to HIDSPI and HIDI2C protocol, every time only one command can be sent to touch IC, and
+before last command is completely handled, next command cannot be sent, THC write DMA engine only
+supports single PRD table.
+
+What driver needs to do is, preparing PRD table and DMA buffer, then copy data to DMA buffer and
+update PRD table with buffer address and buffer length, then start write DMA. THC will
+automatically send the data to touch IC, and trigger a DMA completion interrupt once transferring
+is done.
+
+3.4 PRD
+-------
+
+Physical Region Descriptor (PRD) provides the memory mapping description for THC DMAs.
+
+3.4.1 PRD table and entry
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to improve physical DMA memory usage, modern drivers trend to allocate a virtually
+contiguous, but physically fragmented buffer of memory for each data buffer. Linux OS also
+provide SGL (scatter gather list) APIs to support this usage.
+
+THC uses PRD table (physical region descriptor) to support the corresponding OS kernel
+SGL that describes the virtual to physical buffer mapping.
+
+::
+
+  ------------------------      --------------       --------------
+ | PRD table base address +----+ PRD table #1 +-----+ PRD Entry #1 |
+  ------------------------      --------------       --------------
+                                                     --------------
+                                                    | PRD Entry #2 |
+                                                     --------------
+                                                     --------------
+                                                    | PRD Entry #n |
+                                                     --------------
+
+The read DMA engine supports multiple PRD tables held within a circular buffer that allow the THC
+to support multiple data buffers from the Touch IC. This allows host SW to arm the Read DMA engine
+with multiple buffers, allowing the Touch IC to send multiple data frames to the THC without SW
+interaction. This capability is required when the CPU processes touch frames slower than the
+Touch IC can send them.
+
+To simplify the design, SW assumes worst-case memory fragmentation. Therefore,each PRD table shall
+contain the same number of PRD entries, allowing for a global register (per Touch IC) to hold the
+number of PRD-entries per PRD table.
+
+SW allocates up to 128 PRD tables per Read DMA engine as specified in the THC_M_PRT_RPRD_CNTRL.PCD
+register field. The number of PRD tables should equal the number of data buffers.
+
+Max OS memory fragmentation will be at a 4KB boundary, thus to address 1MB of virtually contiguous
+memory 256 PRD entries are required for a single PRD Table. SW writes the number of PRD entries
+for each PRD table in the THC_M_PRT_RPRD_CNTRL.PTEC register field. The PRD entry's length must be
+multiple of 4KB except for the last entry in a PRD table.
+
+SW allocates all the data buffers and PRD tables only once at host initialization.
+
+3.4.2 PRD Write pointer and read pointer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As PRD tables are organized as a Circular Buffer (CB), a read pointer and a write pointer for a CB
+are needed.
+
+DMA HW consumes the PRD tables in the CB, one PRD entry at a time until the EOP bit is found set
+in a PRD entry. At this point HW increments the PRD read pointer. Thus, the read pointer points
+to the PRD which the DMA engine is currently processing. This pointer rolls over once the circular
+buffer's depth has been traversed with bit[7] the Rollover bit. E.g. if the DMA CB depth is equal
+to 4 entries (0011b), then the read pointers will follow this pattern (HW is required to honor
+this behavior): 00h 01h 02h 03h 80h 81h 82h 83h 00h 01h ...
+
+The write pointer is updated by SW. The write pointer points to location in the DMA CB, where the
+next PRD table is going to be stored. SW needs to ensure that this pointer rolls over once the
+circular buffer's depth has been traversed with Bit[7] as the rollover bit. E.g. if the DMA CB
+depth is equal to 5 entries (0100b), then the write pointers will follow this pattern (SW is
+required to honor this behavior): 00h 01h 02h 03h 04h 80h 81h 82h 83h 84h 00h 01h ..
+
+3.4.3 PRD descriptor structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Intel THC uses PRD entry descriptor for every PRD entry. Every PRD entry descriptor occupies
+128 bits memories:
+
+===================   ========   ===============================================
+struct field          bit(s)     description
+===================   ========   ===============================================
+dest_addr             53..0      destination memory address, as every entry
+                                 is 4KB, ignore lowest 10 bits of address.
+reserved1             54..62     reserved
+int_on_completion     63         completion interrupt enable bit, if this bit
+                                 set it means THC will trigger a completion
+                                 interrupt. This bit is set by SW driver.
+len                   87..64     how many bytes of data in this entry.
+end_of_prd            88         end of PRD table bit, if this bit is set,
+                                 it means this entry is last entry in this PRD
+                                 table. This bit is set by SW driver.
+hw_status             90..89     HW status bits
+reserved2             127..91    reserved
+===================   ========   ===============================================
+
+And one PRD table can include up to 256 PRD entries, as every entries is 4K bytes, so every
+PRD table can describe 1M bytes memory.
+
+.. code-block:: c
+
+   struct thc_prd_table {
+        struct thc_prd_entry entries[PRD_ENTRIES_NUM];
+   };
+
+In general, every PRD table means one HID touch data packet. Every DMA engine can support
+up to 128 PRD tables (except write DMA, write DMA only has one PRD table). SW driver is responsible
+to get max packet length from touch IC, and use this max packet length to create PRD entries for
+each PRD table.
+
+4. HIDSPI support (QuickSPI)
+============================
+
+Intel THC is total compatible with HIDSPI protocol, THC HW sequenser can accelerate HIDSPI
+protocol transferring.
+
+4.1 Reset Flow
+--------------
+
+- Call ACPI _RST method to reset Touch IC device.
+- Read the reset response from TIC through PIO read.
+- Issue a command to retrieve device descriptor from Touch IC through PIO write.
+- Read the device descriptor from Touch IC through PIO read.
+- If the device descriptor is valid, allocate DMA buffers and configure all DMA channels.
+- Issue a command to retrieve report descriptor from Touch IC through DMA.
+
+4.2 Input Report Data Flow
+--------------------------
+
+Basic Flow:
+
+- Touch IC interrupts the THC Controller using an in-band THC interrupt.
+- THC Sequencer reads the input report header by transmitting read approval as a signal
+  to the Touch IC to prepare for host to read from the device.
+- THC Sequencer executes a Input Report Body Read operation corresponding to the value
+  reflected in “Input Report Length” field of the Input Report Header.
+- THC DMA engine begins fetching data from the THC Sequencer and writes to host memory
+  at PRD entry 0 for the current CB PRD table entry. This process continues until the
+  THC Sequencer signals all data has been read or the THC DMA Read Engine reaches the
+  end of it's last PRD entry (or both).
+- The THC Sequencer checks for the “Last Fragment Flag” bit in the Input Report Header.
+  If it is clear, the THC Sequencer enters an idle state.
+- If the “Last Fragment Flag” bit is enabled the THC Sequencer enters End-of-Frame Processing.
+
+THC Sequencer End of Frame Processing:
+
+- THC DMA engine increments the read pointer of the Read PRD CB, sets EOF interrupt status
+  in RxDMA2 register (THC_M_PRT_READ_DMA_INT_STS_2).
+- If THC EOF interrupt is enabled by the driver in the control register (THC_M_PRT_READ_DMA_CNTRL_2),
+  generates interrupt to software.
+
+Sequence of steps to read data from RX DMA buffer:
+
+- THC QuickSPI driver checks CB write Ptr and CB read Ptr to identify if any data frame in DMA
+  circular buffers.
+- THC QuickSPI driver gets first unprocessed PRD table.
+- THC QuickSPI driver scans all PRD entries in this PRD table to calculate the total frame size.
+- THC QuickSPI driver copies all frame data out.
+- THC QuickSPI driver checks the data type according to input report body, and calls related
+  callbacks to process the data.
+- THC QuickSPI driver updates write Ptr.
+
+4.3 Output Report Data Flow
+---------------------------
+
+Generic Output Report Flow:
+
+- HID core calls raw_request callback with a request to THC QuickSPI driver.
+- THC QuickSPI Driver converts request provided data into the output report packet and copies it
+  to THC's write DMA buffer.
+- Start TxDMA to complete the write operation.
+
+5. HIDI2C support (QuickI2C)
+============================
+
+5.1 Reset Flow
+--------------
+
+- Read device descriptor from Touch IC device through PIO write followed by read.
+- If the device descriptor is valid, allocate DMA buffers and configure all DMA channels.
+- Use PIO or TxDMA to write a SET_POWER request to TIC's command register, and check if the
+  write operation is successfully completed.
+- Use PIO or TxDMA to write a RESET request to TIC's command register. If the write operation
+  is successfully completed, wait for reset response from TIC.
+- Use SWDMA to read report descriptor through TIC's report descriptor register.
+
+5.2 Input Report Data Flow
+--------------------------
+
+Basic Flow:
+
+- Touch IC asserts the interrupt indicating that it has an interrupt to send to HOST.
+  THC Sequencer issues a READ request over the I2C bus. The HIDI2C device returns the
+  first 2 bytes from the HIDI2C device which contains the length of the received data.
+- THC Sequencer continues the Read operation as per the size of data indicated in the
+  length field.
+- THC DMA engine begins fetching data from the THC Sequencer and writes to host memory
+  at PRD entry 0 for the current CB PRD table entry. THC writes 2Bytes for length field
+  plus the remaining data to RxDMA buffer. This process continues until the THC Sequencer
+  signals all data has been read or the THC DMA Read Engine reaches the end of it's last
+  PRD entry (or both).
+- THC Sequencer enters End-of-Input Report Processing.
+- If the device has no more input reports to send to the host, it de-asserts the interrupt
+  line. For any additional input reports, device keeps the interrupt line asserted and
+  steps 1 through 4 in the flow are repeated.
+
+THC Sequencer End of Input Report Processing:
+
+- THC DMA engine increments the read pointer of the Read PRD CB, sets EOF interrupt status
+  in RxDMA 2 register (THC_M_PRT_READ_DMA_INT_STS_2).
+- If THC EOF interrupt is enabled by the driver in the control register
+  (THC_M_PRT_READ_DMA_CNTRL_2), generates interrupt to software.
+
+Sequence of steps to read data from RX DMA buffer:
+
+- THC QuickI2C driver checks CB write Ptr and CB read Ptr to identify if any data frame in DMA
+  circular buffers.
+- THC QuickI2C driver gets first unprocessed PRD table.
+- THC QuickI2C driver scans all PRD entries in this PRD table to calculate the total frame size.
+- THC QuickI2C driver copies all frame data out.
+- THC QuickI2C driver call hid_input_report to send the input report content to HID core, which
+  includes Report ID + Report Data Content (remove the length field from the original report
+  data).
+- THC QuickI2C driver updates write Ptr.
+
+5.3 Output Report Data Flow
+---------------------------
+
+Generic Output Report Flow:
+
+- HID core call THC QuickI2C raw_request callback.
+- THC QuickI2C uses PIO or TXDMA to write a SET_REPORT request to TIC's command register. Report
+  type in SET_REPORT should be set to Output.
+- THC QuickI2C programs TxDMA buffer with TX Data to be written to TIC's data register. The first
+  2 bytes should indicate the length of the report followed by the report contents including
+  Report ID.
+
+6. THC Debugging
+================
+
+To debug THC, event tracing mechanism is used. To enable debug logs::
+
+  echo 1 > /sys/kernel/debug/tracing/events/intel_thc/enable
+  cat /sys/kernel/debug/tracing/trace
+
+7. Reference
+============
+- HIDSPI: https://download.microsoft.com/download/c/a/0/ca07aef3-3e10-4022-b1e9-c98cea99465d/HidSpiProtocolSpec.pdf
+- HIDI2C: https://download.microsoft.com/download/7/d/d/7dd44bb7-2a7a-4505-ac1c-7227d3d96d5b/hid-over-i2c-protocol-spec-v1-0.docx