Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'hid-for-linus-2025012001' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID updates from Jiri Kosina:

- newly added support for Intel Touch Host Controller (Even Xu, Xinpeng
Sun)

- hid-core fix for long-standing syzbot-reported cornercase of
Resolution Multiplier not being present in any of the Logical
Collections in the device HID report descriptor (Alan Stern)

- improvement of behavior for non-standard LED brightness values for
Wacom driver (Jason Gerecke)

- PCI Wacom device support (depends on Intel THC support) (Even Xu)

- SteelSeries Arctis 9 support (Christian Mayer)

- constification of 'struct bin_attribute' in various HID driver
(Thomas Weißschuh)

- other assorted code cleanups / fixes and device ID additions

* tag 'hid-for-linus-2025012001' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (63 commits)
HID: hid-asus: Disable OOBE mode on the ProArt P16
HID: steelseries: remove unnecessary return
HID: steelseries: export model and manufacturer
HID: steelseries: export charging state for the SteelSeries Arctis 9 headset
HID: steelseries: add SteelSeries Arctis 9 support
HID: steelseries: preparation for adding SteelSeries Arctis 9 support
HID: intel-thc-hid: fix build errors in um mode
HID: intel-thc-hid: intel-quicki2c: fix potential memory corruption
HID: intel-thc-hid: intel-thc: Fix error code in thc_i2c_subip_init()
HID: lenovo: Fix undefined platform_profile_cycle in ThinkPad X12 keyboard patch
HID: uclogic: make const read-only array touch_ring_model_params_buf static
HID: hid-steam: Make sure rumble work is canceled on removal
HID: Wacom: Add PCI Wacom device support
HID: intel-thc-hid: intel-quicki2c: Add PM implementation
HID: intel-thc-hid: intel-quicki2c: Complete THC QuickI2C driver
HID: intel-thc-hid: intel-quicki2c: Add HIDI2C protocol implementation
HID: intel-thc-hid: intel-quicki2c: Add THC QuickI2C ACPI interfaces
HID: intel-thc-hid: intel-quicki2c: Add THC QuickI2C driver hid layer
HID: intel-thc-hid: intel-quicki2c: Add THC QuickI2C driver skeleton
HID: intel-thc-hid: intel-quickspi: Add PM implementation
...

+8444 -277
+1
Documentation/hid/index.rst
··· 18 18 19 19 hid-alps 20 20 intel-ish-hid 21 + intel-thc-hid 21 22 amd-sfh-hid
+568
Documentation/hid/intel-thc-hid.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + ================================= 4 + Intel Touch Host Controller (THC) 5 + ================================= 6 + 7 + Touch Host Controller is the name of the IP block in PCH that interface with Touch Devices (ex: 8 + touchscreen, touchpad etc.). It is comprised of 3 key functional blocks: 9 + 10 + - A natively half-duplex Quad I/O capable SPI master 11 + - Low latency I2C interface to support HIDI2C compliant devices 12 + - A HW sequencer with RW DMA capability to system memory 13 + 14 + It has a single root space IOSF Primary interface that supports transactions to/from touch devices. 15 + Host driver configures and controls the touch devices over THC interface. THC provides high 16 + bandwidth DMA services to the touch driver and transfers the HID report to host system main memory. 17 + 18 + Hardware sequencer within the THC is responsible for transferring (via DMA) data from touch devices 19 + into system memory. A ring buffer is used to avoid data loss due to asynchronous nature of data 20 + consumption (by host) in relation to data production (by touch device via DMA). 21 + 22 + Unlike other common SPI/I2C controllers, THC handles the HID device data interrupt and reset 23 + signals directly. 24 + 25 + 1. Overview 26 + =========== 27 + 28 + 1.1 THC software/hardware stack 29 + ------------------------------- 30 + 31 + Below diagram illustrates the high-level architecture of THC software/hardware stack, which is fully 32 + capable of supporting HIDSPI/HIDI2C protocol in Linux OS. 33 + 34 + :: 35 + 36 + ---------------------------------------------- 37 + | +-----------------------------------+ | 38 + | | Input Device | | 39 + | +-----------------------------------+ | 40 + | +-----------------------------------+ | 41 + | | HID Multi-touch Driver | | 42 + | +-----------------------------------+ | 43 + | +-----------------------------------+ | 44 + | | HID Core | | 45 + | +-----------------------------------+ | 46 + | +-----------------------------------+ | 47 + | | THC QuickSPI/QuickI2C Driver | | 48 + | +-----------------------------------+ | 49 + | +-----------------------------------+ | 50 + | | THC Hardware Driver | | 51 + | +-----------------------------------+ | 52 + | +----------------+ +----------------+ | 53 + | SW | PCI Bus Driver | | ACPI Resource | | 54 + | +----------------+ +----------------+ | 55 + ---------------------------------------------- 56 + ---------------------------------------------- 57 + | +-----------------------------------+ | 58 + | HW | PCI Bus | | 59 + | +-----------------------------------+ | 60 + | +-----------------------------------+ | 61 + | | THC Controller | | 62 + | +-----------------------------------+ | 63 + | +-----------------------------------+ | 64 + | | Touch IC | | 65 + | +-----------------------------------+ | 66 + ---------------------------------------------- 67 + 68 + Touch IC (TIC), also as known as the Touch devices (touchscreen or touchpad). The discrete analog 69 + components that sense and transfer either discrete touch data or heatmap data in the form of HID 70 + reports over the SPI/I2C bus to the THC Controller on the host. 71 + 72 + THC Host Controller, which is a PCI device HBA (host bus adapter), integrated into the PCH, that 73 + serves as a bridge between the Touch ICs and the host. 74 + 75 + THC Hardware Driver, provides THC hardware operation APIs for above QuickSPI/QuickI2C driver, it 76 + accesses THC MMIO registers to configure and control THC hardware. 77 + 78 + THC QuickSPI/QuickI2C driver, also as known as HIDSPI/HIDI2C driver, is registered as a HID 79 + low-level driver that manages the THC Controller and implements HIDSPI/HIDI2C protocol. 80 + 81 + 82 + 1.2 THC hardware diagram 83 + ------------------------ 84 + Below diagram shows THC hardware components:: 85 + 86 + --------------------------------- 87 + | THC Controller | 88 + | +---------------------------+ | 89 + | | PCI Config Space | | 90 + | +---------------------------+ | 91 + | +---------------------------+ | 92 + | + MMIO Registers | | 93 + | +---------------------------+ | 94 + +---------------+ | +------------+ +------------+ | 95 + | System Memory +---+--+ DMA | | PIO | | 96 + +---------------+ | +------------+ +------------+ | 97 + | +---------------------------+ | 98 + | | HW Sequencer | | 99 + | +---------------------------+ | 100 + | +------------+ +------------+ | 101 + | | SPI/I2C | | GPIO | | 102 + | | Controller | | Controller | | 103 + | +------------+ +------------+ | 104 + --------------------------------- 105 + 106 + As THC is exposed as a PCI devices, so it has standard PCI config space registers for PCI 107 + enumeration and configuration. 108 + 109 + MMIO Registers, which provide registers access for driver to configure and control THC hardware, 110 + the registers include several categories: Interrupt status and control, DMA configure, 111 + PIO (Programmed I/O, defined in section 3.2) status and control, SPI bus configure, I2C subIP 112 + status and control, reset status and control... 113 + 114 + THC provides two ways for driver to communicate with external Touch ICs: PIO and DMA. 115 + PIO can let driver manually write/read data to/from Touch ICs, instead, THC DMA can 116 + automatically write/read data without driver involved. 117 + 118 + HW Sequencer includes THC major logic, it gets instruction from MMIO registers to control 119 + SPI bus and I2C bus to finish a bus data transaction, it also can automatically handle 120 + Touch ICs interrupt and start DMA receive/send data from/to Touch ICs according to interrupt 121 + type. That means THC HW Sequencer understands HIDSPI/HIDI2C transfer protocol, and handle 122 + the communication without driver involved, what driver needs to do is just configure the THC 123 + properly, and prepare the formatted data packet or handle received data packet. 124 + 125 + As THC supports HIDSPI/HIDI2C protocols, it has SPI controller and I2C subIP in it to expose 126 + SPI bus and I2C bus. THC also integrates a GPIO controller to provide interrupt line support 127 + and reset line support. 128 + 129 + 2. THC Hardware Interface 130 + ========================= 131 + 132 + 2.1 Host Interface 133 + ------------------ 134 + 135 + THC is exposed as "PCI Digitizer device" to the host. The PCI product and device IDs are 136 + changed from different generations of processors. So the source code which enumerates drivers 137 + needs to update from generation to generation. 138 + 139 + 140 + 2.2 Device Interface 141 + -------------------- 142 + 143 + THC supports two types of bus for Touch IC connection: Enhanced SPI bus and I2C bus. 144 + 145 + 2.2.1 SPI Port 146 + ~~~~~~~~~~~~~~ 147 + 148 + When PORT_TYPE = 00b in MMIO registers, THC uses SPI interfaces to communicate with external 149 + Touch IC. THC enhanced SPI Bus supports different SPI modes: standard Single IO mode, 150 + Dual IO mode and Quad IO mode. 151 + 152 + In Single IO mode, THC drives MOSI line to send data to Touch ICs, and receives data from Touch 153 + ICs data from MISO line. In Dual IO mode, THC drivers MOSI and MISO both for data sending, and 154 + also receives the data on both line. In Quad IO mode, there are other two lines (IO2 and IO3) 155 + are added, THC drives MOSI (IO0), MISO (IO1), IO2 and IO3 at the same time for data sending, and 156 + also receives the data on those 4 lines. Driver needs to configure THC in different mode by 157 + setting different opcode. 158 + 159 + Beside IO mode, driver also needs to configure SPI bus speed. THC supports up to 42MHz SPI clock 160 + on Intel Lunar Lake platform. 161 + 162 + For THC sending data to Touch IC, the data flow on SPI bus:: 163 + 164 + | --------------------THC sends---------------------------------| 165 + <8Bits OPCode><24Bits Slave Address><Data><Data><Data>........... 166 + 167 + For THC receiving data from Touch IC, the data flow on SPI bus:: 168 + 169 + | ---------THC Sends---------------||-----Touch IC sends--------| 170 + <8Bits OPCode><24Bits Slave Address><Data><Data><Data>........... 171 + 172 + 2.2.2 I2C Port 173 + ~~~~~~~~~~~~~~ 174 + 175 + THC also integrates I2C controller in it, it's called I2C SubSystem. When PORT_TYPE = 01, THC 176 + is configured to I2C mode. Comparing to SPI mode which can be configured through MMIO registers 177 + directly, THC needs to use PIO read (by setting SubIP read opcode) to I2C subIP APB registers' 178 + value and use PIO write (by setting SubIP write opcode) to do a write operation. 179 + 180 + 2.2.3 GPIO interface 181 + ~~~~~~~~~~~~~~~~~~~~ 182 + 183 + THC also includes two GPIO pins, one for interrupt and the other for device reset control. 184 + 185 + Interrupt line can be configured to either level triggerred or edge triggerred by setting MMIO 186 + Control register. 187 + 188 + Reset line is controlled by BIOS (or EFI) through ACPI _RST method, driver needs to call this 189 + device ACPI _RST method to reset touch IC during initialization. 190 + 191 + 3. High level concept 192 + ===================== 193 + 194 + 3.1 Opcode 195 + ---------- 196 + 197 + Opcode (operation code) is used to tell THC or Touch IC what the operation will be, such as PIO 198 + read or PIO write. 199 + 200 + When THC is configured to SPI mode, opcodes are used for determining the read/write IO mode. 201 + There are some OPCode examples for SPI IO mode: 202 + 203 + ======= ============================== 204 + opcode Corresponding SPI command 205 + ======= ============================== 206 + 0x0B Read Single I/O 207 + 0x02 Write Single I/O 208 + 0xBB Read Dual I/O 209 + 0xB2 Write Dual I/O 210 + 0xEB Read Quad I/O 211 + 0xE2 Write Quad I/O 212 + ======= ============================== 213 + 214 + In general, different touch IC has different OPCode definition. According to HIDSPI 215 + protocol whitepaper, those OPCodes are defined in device ACPI table, and driver needs to 216 + query those information through OS ACPI APIs during driver initialization, then configures 217 + THC MMIO OPCode registers with correct setting. 218 + 219 + When THC is working in I2C mode, opcodes are used to tell THC what's the next PIO type: 220 + I2C SubIP APB register read, I2C SubIP APB register write, I2C touch IC device read, 221 + I2C touch IC device write, I2C touch IC device write followed by read. 222 + 223 + Here are the THC pre-defined opcodes for I2C mode: 224 + 225 + ======= =================================================== =========== 226 + opcode Corresponding I2C command Address 227 + ======= =================================================== =========== 228 + 0x12 Read I2C SubIP APB internal registers 0h - FFh 229 + 0x13 Write I2C SubIP APB internal registers 0h - FFh 230 + 0x14 Read external Touch IC through I2C bus N/A 231 + 0x18 Write external Touch IC through I2C bus N/A 232 + 0x1C Write then read external Touch IC through I2C bus N/A 233 + ======= =================================================== =========== 234 + 235 + 3.2 PIO 236 + ------- 237 + 238 + THC provides a programmed I/O (PIO) access interface for the driver to access the touch IC's 239 + configuration registers, or access I2C subIP's configuration registers. To use PIO to perform 240 + I/O operations, driver should pre-program PIO control registers and PIO data registers and kick 241 + off the sequencing cycle. THC uses different PIO opcodes to distinguish different PIO 242 + operations (PIO read/write/write followed by read). 243 + 244 + If there is a Sequencing Cycle In Progress and an attempt is made to program any of the control, 245 + address, or data register the cycle is blocked and a sequence error will be encountered. 246 + 247 + A status bit indicates when the cycle has completed allowing the driver to know when read results 248 + can be checked and/or when to initiate a new command. If enabled, the cycle done assertion can 249 + interrupt driver with an interrupt. 250 + 251 + Because THC only has 16 FIFO registers for PIO, so all the data transfer through PIO shouldn't 252 + exceed 64 bytes. 253 + 254 + As DMA needs max packet size for transferring configuration, and the max packet size information 255 + always in HID device descriptor which needs THC driver to read it out from HID Device (Touch IC). 256 + So PIO typical use case is, before DMA initialization, write RESET command (PIO write), read 257 + RESET response (PIO read or PIO write followed by read), write Power ON command (PIO write), read 258 + device descriptor (PIO read). 259 + 260 + For how to issue a PIO operation, here is the steps which driver needs follow: 261 + 262 + - Program read/write data size in THC_SS_BC. 263 + - Program I/O target address in THC_SW_SEQ_DATA0_ADDR. 264 + - If write, program the write data in THC_SW_SEQ_DATA0..THC_SW_SEQ_DATAn. 265 + - Program the PIO opcode in THC_SS_CMD. 266 + - Set TSSGO = 1 to start the PIO write sequence. 267 + - If THC_SS_CD_IE = 1, SW will receives a MSI when the PIO is completed. 268 + - If read, read out the data in THC_SW_SEQ_DATA0..THC_SW_SEQ_DATAn. 269 + 270 + 3.3 DMA 271 + ------- 272 + 273 + THC has 4 DMA channels: Read DMA1, Read DMA2, Write DMA and Software DMA. 274 + 275 + 3.3.1 Read DMA Channel 276 + ~~~~~~~~~~~~~~~~~~~~~~ 277 + 278 + THC has two Read DMA engines: 1st RxDMA (RxDMA1) and 2nd RxDMA (RxDMA2). RxDMA1 is reserved for 279 + raw data mode. RxDMA2 is used for HID data mode and it is the RxDMA engine currently driver uses 280 + for HID input report data retrieval. 281 + 282 + RxDMA's typical use case is auto receiving the data from Touch IC. Once RxDMA is enabled by 283 + software, THC will start auto-handling receiving logic. 284 + 285 + For SPI mode, THC RxDMA sequence is: when Touch IC triggers a interrupt to THC, THC reads out 286 + report header to identify what's the report type, and what's the report length, according to 287 + above information, THC reads out report body to internal FIFO and start RxDMA coping the data 288 + to system memory. After that, THC update interrupt cause register with report type, and update 289 + RxDMA PRD table read pointer, then trigger a MSI interrupt to notify driver RxDMA finishing 290 + data receiving. 291 + 292 + For I2C mode, THC RxDMA's behavior is a little bit different, because of HIDI2C protocol difference 293 + with HIDSPI protocol, RxDMA only be used to receive input report. The sequence is, when Touch IC 294 + triggers a interrupt to THC, THC first reads out 2 bytes from input report address to determine the 295 + packet length, then use this packet length to start a DMA reading from input report address for 296 + input report data. After that, THC update RxDMA PRD table read pointer, then trigger a MSI interrupt 297 + to notify driver input report data is ready in system memory. 298 + 299 + All above sequence is hardware automatically handled, all driver needs to do is configure RxDMA and 300 + waiting for interrupt ready then read out the data from system memory. 301 + 302 + 3.3.2 Software DMA channel 303 + ~~~~~~~~~~~~~~~~~~~~~~~~~~ 304 + 305 + THC supports a software triggerred RxDMA mode to read the touch data from touch IC. This SW RxDMA 306 + is the 3rd THC RxDMA engine with the similar functionalities as the existing two RxDMAs, the only 307 + difference is this SW RxDMA is triggerred by software, and RxDMA2 is triggerred by external Touch IC 308 + interrupt. It gives a flexiblity to software driver to use RxDMA read Touch IC data in any time. 309 + 310 + Before software starts a SW RxDMA, it shall stop the 1st and 2nd RxDMA, clear PRD read/write pointer 311 + and quiesce the device interrupt (THC_DEVINT_QUIESCE_HW_STS = 1), other operations are the same with 312 + RxDMA. 313 + 314 + 3.3.3 Write DMA Channel 315 + ~~~~~~~~~~~~~~~~~~~~~~~ 316 + 317 + THC has one write DMA engine, which can be used for sending data to Touch IC automatically. 318 + According to HIDSPI and HIDI2C protocol, every time only one command can be sent to touch IC, and 319 + before last command is completely handled, next command cannot be sent, THC write DMA engine only 320 + supports single PRD table. 321 + 322 + What driver needs to do is, preparing PRD table and DMA buffer, then copy data to DMA buffer and 323 + update PRD table with buffer address and buffer length, then start write DMA. THC will 324 + automatically send the data to touch IC, and trigger a DMA completion interrupt once transferring 325 + is done. 326 + 327 + 3.4 PRD 328 + ------- 329 + 330 + Physical Region Descriptor (PRD) provides the memory mapping description for THC DMAs. 331 + 332 + 3.4.1 PRD table and entry 333 + ~~~~~~~~~~~~~~~~~~~~~~~~~ 334 + 335 + In order to improve physical DMA memory usage, modern drivers trend to allocate a virtually 336 + contiguous, but physically fragmented buffer of memory for each data buffer. Linux OS also 337 + provide SGL (scatter gather list) APIs to support this usage. 338 + 339 + THC uses PRD table (physical region descriptor) to support the corresponding OS kernel 340 + SGL that describes the virtual to physical buffer mapping. 341 + 342 + :: 343 + 344 + ------------------------ -------------- -------------- 345 + | PRD table base address +----+ PRD table #1 +-----+ PRD Entry #1 | 346 + ------------------------ -------------- -------------- 347 + -------------- 348 + | PRD Entry #2 | 349 + -------------- 350 + -------------- 351 + | PRD Entry #n | 352 + -------------- 353 + 354 + The read DMA engine supports multiple PRD tables held within a circular buffer that allow the THC 355 + to support multiple data buffers from the Touch IC. This allows host SW to arm the Read DMA engine 356 + with multiple buffers, allowing the Touch IC to send multiple data frames to the THC without SW 357 + interaction. This capability is required when the CPU processes touch frames slower than the 358 + Touch IC can send them. 359 + 360 + To simplify the design, SW assumes worst-case memory fragmentation. Therefore,each PRD table shall 361 + contain the same number of PRD entries, allowing for a global register (per Touch IC) to hold the 362 + number of PRD-entries per PRD table. 363 + 364 + SW allocates up to 128 PRD tables per Read DMA engine as specified in the THC_M_PRT_RPRD_CNTRL.PCD 365 + register field. The number of PRD tables should equal the number of data buffers. 366 + 367 + Max OS memory fragmentation will be at a 4KB boundary, thus to address 1MB of virtually contiguous 368 + memory 256 PRD entries are required for a single PRD Table. SW writes the number of PRD entries 369 + for each PRD table in the THC_M_PRT_RPRD_CNTRL.PTEC register field. The PRD entry's length must be 370 + multiple of 4KB except for the last entry in a PRD table. 371 + 372 + SW allocates all the data buffers and PRD tables only once at host initialization. 373 + 374 + 3.4.2 PRD Write pointer and read pointer 375 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 376 + 377 + As PRD tables are organized as a Circular Buffer (CB), a read pointer and a write pointer for a CB 378 + are needed. 379 + 380 + DMA HW consumes the PRD tables in the CB, one PRD entry at a time until the EOP bit is found set 381 + in a PRD entry. At this point HW increments the PRD read pointer. Thus, the read pointer points 382 + to the PRD which the DMA engine is currently processing. This pointer rolls over once the circular 383 + buffer's depth has been traversed with bit[7] the Rollover bit. E.g. if the DMA CB depth is equal 384 + to 4 entries (0011b), then the read pointers will follow this pattern (HW is required to honor 385 + this behavior): 00h 01h 02h 03h 80h 81h 82h 83h 00h 01h ... 386 + 387 + The write pointer is updated by SW. The write pointer points to location in the DMA CB, where the 388 + next PRD table is going to be stored. SW needs to ensure that this pointer rolls over once the 389 + circular buffer's depth has been traversed with Bit[7] as the rollover bit. E.g. if the DMA CB 390 + depth is equal to 5 entries (0100b), then the write pointers will follow this pattern (SW is 391 + required to honor this behavior): 00h 01h 02h 03h 04h 80h 81h 82h 83h 84h 00h 01h .. 392 + 393 + 3.4.3 PRD descriptor structure 394 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 395 + 396 + Intel THC uses PRD entry descriptor for every PRD entry. Every PRD entry descriptor occupies 397 + 128 bits memories: 398 + 399 + =================== ======== =============================================== 400 + struct field bit(s) description 401 + =================== ======== =============================================== 402 + dest_addr 53..0 destination memory address, as every entry 403 + is 4KB, ignore lowest 10 bits of address. 404 + reserved1 54..62 reserved 405 + int_on_completion 63 completion interrupt enable bit, if this bit 406 + set it means THC will trigger a completion 407 + interrupt. This bit is set by SW driver. 408 + len 87..64 how many bytes of data in this entry. 409 + end_of_prd 88 end of PRD table bit, if this bit is set, 410 + it means this entry is last entry in this PRD 411 + table. This bit is set by SW driver. 412 + hw_status 90..89 HW status bits 413 + reserved2 127..91 reserved 414 + =================== ======== =============================================== 415 + 416 + And one PRD table can include up to 256 PRD entries, as every entries is 4K bytes, so every 417 + PRD table can describe 1M bytes memory. 418 + 419 + .. code-block:: c 420 + 421 + struct thc_prd_table { 422 + struct thc_prd_entry entries[PRD_ENTRIES_NUM]; 423 + }; 424 + 425 + In general, every PRD table means one HID touch data packet. Every DMA engine can support 426 + up to 128 PRD tables (except write DMA, write DMA only has one PRD table). SW driver is responsible 427 + to get max packet length from touch IC, and use this max packet length to create PRD entries for 428 + each PRD table. 429 + 430 + 4. HIDSPI support (QuickSPI) 431 + ============================ 432 + 433 + Intel THC is total compatible with HIDSPI protocol, THC HW sequenser can accelerate HIDSPI 434 + protocol transferring. 435 + 436 + 4.1 Reset Flow 437 + -------------- 438 + 439 + - Call ACPI _RST method to reset Touch IC device. 440 + - Read the reset response from TIC through PIO read. 441 + - Issue a command to retrieve device descriptor from Touch IC through PIO write. 442 + - Read the device descriptor from Touch IC through PIO read. 443 + - If the device descriptor is valid, allocate DMA buffers and configure all DMA channels. 444 + - Issue a command to retrieve report descriptor from Touch IC through DMA. 445 + 446 + 4.2 Input Report Data Flow 447 + -------------------------- 448 + 449 + Basic Flow: 450 + 451 + - Touch IC interrupts the THC Controller using an in-band THC interrupt. 452 + - THC Sequencer reads the input report header by transmitting read approval as a signal 453 + to the Touch IC to prepare for host to read from the device. 454 + - THC Sequencer executes a Input Report Body Read operation corresponding to the value 455 + reflected in “Input Report Length” field of the Input Report Header. 456 + - THC DMA engine begins fetching data from the THC Sequencer and writes to host memory 457 + at PRD entry 0 for the current CB PRD table entry. This process continues until the 458 + THC Sequencer signals all data has been read or the THC DMA Read Engine reaches the 459 + end of it's last PRD entry (or both). 460 + - The THC Sequencer checks for the “Last Fragment Flag” bit in the Input Report Header. 461 + If it is clear, the THC Sequencer enters an idle state. 462 + - If the “Last Fragment Flag” bit is enabled the THC Sequencer enters End-of-Frame Processing. 463 + 464 + THC Sequencer End of Frame Processing: 465 + 466 + - THC DMA engine increments the read pointer of the Read PRD CB, sets EOF interrupt status 467 + in RxDMA2 register (THC_M_PRT_READ_DMA_INT_STS_2). 468 + - If THC EOF interrupt is enabled by the driver in the control register (THC_M_PRT_READ_DMA_CNTRL_2), 469 + generates interrupt to software. 470 + 471 + Sequence of steps to read data from RX DMA buffer: 472 + 473 + - THC QuickSPI driver checks CB write Ptr and CB read Ptr to identify if any data frame in DMA 474 + circular buffers. 475 + - THC QuickSPI driver gets first unprocessed PRD table. 476 + - THC QuickSPI driver scans all PRD entries in this PRD table to calculate the total frame size. 477 + - THC QuickSPI driver copies all frame data out. 478 + - THC QuickSPI driver checks the data type according to input report body, and calls related 479 + callbacks to process the data. 480 + - THC QuickSPI driver updates write Ptr. 481 + 482 + 4.3 Output Report Data Flow 483 + --------------------------- 484 + 485 + Generic Output Report Flow: 486 + 487 + - HID core calls raw_request callback with a request to THC QuickSPI driver. 488 + - THC QuickSPI Driver converts request provided data into the output report packet and copies it 489 + to THC's write DMA buffer. 490 + - Start TxDMA to complete the write operation. 491 + 492 + 5. HIDI2C support (QuickI2C) 493 + ============================ 494 + 495 + 5.1 Reset Flow 496 + -------------- 497 + 498 + - Read device descriptor from Touch IC device through PIO write followed by read. 499 + - If the device descriptor is valid, allocate DMA buffers and configure all DMA channels. 500 + - Use PIO or TxDMA to write a SET_POWER request to TIC's command register, and check if the 501 + write operation is successfully completed. 502 + - Use PIO or TxDMA to write a RESET request to TIC's command register. If the write operation 503 + is successfully completed, wait for reset response from TIC. 504 + - Use SWDMA to read report descriptor through TIC's report descriptor register. 505 + 506 + 5.2 Input Report Data Flow 507 + -------------------------- 508 + 509 + Basic Flow: 510 + 511 + - Touch IC asserts the interrupt indicating that it has an interrupt to send to HOST. 512 + THC Sequencer issues a READ request over the I2C bus. The HIDI2C device returns the 513 + first 2 bytes from the HIDI2C device which contains the length of the received data. 514 + - THC Sequencer continues the Read operation as per the size of data indicated in the 515 + length field. 516 + - THC DMA engine begins fetching data from the THC Sequencer and writes to host memory 517 + at PRD entry 0 for the current CB PRD table entry. THC writes 2Bytes for length field 518 + plus the remaining data to RxDMA buffer. This process continues until the THC Sequencer 519 + signals all data has been read or the THC DMA Read Engine reaches the end of it's last 520 + PRD entry (or both). 521 + - THC Sequencer enters End-of-Input Report Processing. 522 + - If the device has no more input reports to send to the host, it de-asserts the interrupt 523 + line. For any additional input reports, device keeps the interrupt line asserted and 524 + steps 1 through 4 in the flow are repeated. 525 + 526 + THC Sequencer End of Input Report Processing: 527 + 528 + - THC DMA engine increments the read pointer of the Read PRD CB, sets EOF interrupt status 529 + in RxDMA 2 register (THC_M_PRT_READ_DMA_INT_STS_2). 530 + - If THC EOF interrupt is enabled by the driver in the control register 531 + (THC_M_PRT_READ_DMA_CNTRL_2), generates interrupt to software. 532 + 533 + Sequence of steps to read data from RX DMA buffer: 534 + 535 + - THC QuickI2C driver checks CB write Ptr and CB read Ptr to identify if any data frame in DMA 536 + circular buffers. 537 + - THC QuickI2C driver gets first unprocessed PRD table. 538 + - THC QuickI2C driver scans all PRD entries in this PRD table to calculate the total frame size. 539 + - THC QuickI2C driver copies all frame data out. 540 + - THC QuickI2C driver call hid_input_report to send the input report content to HID core, which 541 + includes Report ID + Report Data Content (remove the length field from the original report 542 + data). 543 + - THC QuickI2C driver updates write Ptr. 544 + 545 + 5.3 Output Report Data Flow 546 + --------------------------- 547 + 548 + Generic Output Report Flow: 549 + 550 + - HID core call THC QuickI2C raw_request callback. 551 + - THC QuickI2C uses PIO or TXDMA to write a SET_REPORT request to TIC's command register. Report 552 + type in SET_REPORT should be set to Output. 553 + - THC QuickI2C programs TxDMA buffer with TX Data to be written to TIC's data register. The first 554 + 2 bytes should indicate the length of the report followed by the report contents including 555 + Report ID. 556 + 557 + 6. THC Debugging 558 + ================ 559 + 560 + To debug THC, event tracing mechanism is used. To enable debug logs:: 561 + 562 + echo 1 > /sys/kernel/debug/tracing/events/intel_thc/enable 563 + cat /sys/kernel/debug/tracing/trace 564 + 565 + 7. Reference 566 + ============ 567 + - HIDSPI: https://download.microsoft.com/download/c/a/0/ca07aef3-3e10-4022-b1e9-c98cea99465d/HidSpiProtocolSpec.pdf 568 + - HIDI2C: https://download.microsoft.com/download/7/d/d/7dd44bb7-2a7a-4505-ac1c-7227d3d96d5b/hid-over-i2c-protocol-spec-v1-0.docx
+6
MAINTAINERS
··· 11918 11918 F: arch/x86/include/asm/intel_telemetry.h 11919 11919 F: drivers/platform/x86/intel/telemetry/ 11920 11920 11921 + INTEL TOUCH HOST CONTROLLER (THC) DRIVER 11922 + M: Even Xu <even.xu@intel.com> 11923 + M: Xinpeng Sun <xinpeng.sun@intel.com> 11924 + S: Maintained 11925 + F: drivers/hid/intel-thc-hid/ 11926 + 11921 11927 INTEL TPMI DRIVER 11922 11928 M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> 11923 11929 L: platform-driver-x86@vger.kernel.org
+3 -1
drivers/hid/Kconfig
··· 787 787 Adds support for the Nintendo Switch Joy-Cons, NSO, Pro Controller. 788 788 All controllers support bluetooth, and the Pro Controller also supports 789 789 its USB mode. This also includes support for the Nintendo Switch Online 790 - Controllers which include the Genesis, SNES, and N64 controllers. 790 + Controllers which include the NES, Genesis, SNES, and N64 controllers. 791 791 792 792 To compile this driver as a module, choose M here: the 793 793 module will be called hid-nintendo. ··· 1385 1385 source "drivers/hid/amd-sfh-hid/Kconfig" 1386 1386 1387 1387 source "drivers/hid/surface-hid/Kconfig" 1388 + 1389 + source "drivers/hid/intel-thc-hid/Kconfig" 1388 1390 1389 1391 endif # HID_SUPPORT
+2
drivers/hid/Makefile
··· 171 171 obj-$(CONFIG_AMD_SFH_HID) += amd-sfh-hid/ 172 172 173 173 obj-$(CONFIG_SURFACE_HID_CORE) += surface-hid/ 174 + 175 + obj-$(CONFIG_INTEL_THC_HID) += intel-thc-hid/
+26
drivers/hid/hid-asus.c
··· 432 432 return ret; 433 433 } 434 434 435 + static int asus_kbd_disable_oobe(struct hid_device *hdev) 436 + { 437 + const u8 init[][6] = { 438 + { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 }, 439 + { FEATURE_KBD_REPORT_ID, 0xBA, 0xC5, 0xC4 }, 440 + { FEATURE_KBD_REPORT_ID, 0xD0, 0x8F, 0x01 }, 441 + { FEATURE_KBD_REPORT_ID, 0xD0, 0x85, 0xFF } 442 + }; 443 + int ret; 444 + 445 + for (size_t i = 0; i < ARRAY_SIZE(init); i++) { 446 + ret = asus_kbd_set_report(hdev, init[i], sizeof(init[i])); 447 + if (ret < 0) 448 + return ret; 449 + } 450 + 451 + hid_info(hdev, "Disabled OOBE for keyboard\n"); 452 + return 0; 453 + } 454 + 435 455 static void asus_schedule_work(struct asus_kbd_leds *led) 436 456 { 437 457 unsigned long flags; ··· 554 534 ret = asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID2); 555 535 if (ret < 0) 556 536 return ret; 537 + 538 + if (dmi_match(DMI_PRODUCT_FAMILY, "ProArt P16")) { 539 + ret = asus_kbd_disable_oobe(hdev); 540 + if (ret < 0) 541 + return ret; 542 + } 557 543 } else { 558 544 /* Initialize keyboard */ 559 545 ret = asus_kbd_init(hdev, FEATURE_KBD_REPORT_ID);
+12 -17
drivers/hid/hid-core.c
··· 1163 1163 while (multiplier_collection->parent_idx != -1 && 1164 1164 multiplier_collection->type != HID_COLLECTION_LOGICAL) 1165 1165 multiplier_collection = &hid->collection[multiplier_collection->parent_idx]; 1166 + if (multiplier_collection->type != HID_COLLECTION_LOGICAL) 1167 + multiplier_collection = NULL; 1166 1168 1167 1169 effective_multiplier = hid_calculate_multiplier(hid, multiplier); 1168 1170 ··· 2176 2174 2177 2175 2178 2176 static ssize_t 2179 - read_report_descriptor(struct file *filp, struct kobject *kobj, 2180 - struct bin_attribute *attr, 2181 - char *buf, loff_t off, size_t count) 2177 + report_descriptor_read(struct file *filp, struct kobject *kobj, 2178 + const struct bin_attribute *attr, 2179 + char *buf, loff_t off, size_t count) 2182 2180 { 2183 2181 struct device *dev = kobj_to_dev(kobj); 2184 2182 struct hid_device *hdev = to_hid_device(dev); ··· 2195 2193 } 2196 2194 2197 2195 static ssize_t 2198 - show_country(struct device *dev, struct device_attribute *attr, 2199 - char *buf) 2196 + country_show(struct device *dev, struct device_attribute *attr, 2197 + char *buf) 2200 2198 { 2201 2199 struct hid_device *hdev = to_hid_device(dev); 2202 2200 2203 2201 return sprintf(buf, "%02x\n", hdev->country & 0xff); 2204 2202 } 2205 2203 2206 - static struct bin_attribute dev_bin_attr_report_desc = { 2207 - .attr = { .name = "report_descriptor", .mode = 0444 }, 2208 - .read = read_report_descriptor, 2209 - .size = HID_MAX_DESCRIPTOR_SIZE, 2210 - }; 2204 + static const BIN_ATTR_RO(report_descriptor, HID_MAX_DESCRIPTOR_SIZE); 2211 2205 2212 - static const struct device_attribute dev_attr_country = { 2213 - .attr = { .name = "country", .mode = 0444 }, 2214 - .show = show_country, 2215 - }; 2206 + static const DEVICE_ATTR_RO(country); 2216 2207 2217 2208 int hid_connect(struct hid_device *hdev, unsigned int connect_mask) 2218 2209 { ··· 2795 2800 &dev_attr_modalias.attr, 2796 2801 NULL, 2797 2802 }; 2798 - static struct bin_attribute *hid_dev_bin_attrs[] = { 2799 - &dev_bin_attr_report_desc, 2803 + static const struct bin_attribute *hid_dev_bin_attrs[] = { 2804 + &bin_attr_report_descriptor, 2800 2805 NULL 2801 2806 }; 2802 2807 static const struct attribute_group hid_dev_group = { 2803 2808 .attrs = hid_dev_attrs, 2804 - .bin_attrs = hid_dev_bin_attrs, 2809 + .bin_attrs_new = hid_dev_bin_attrs, 2805 2810 }; 2806 2811 __ATTRIBUTE_GROUPS(hid_dev); 2807 2812
+2 -1
drivers/hid/hid-ids.h
··· 506 506 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 507 507 508 508 #define I2C_VENDOR_ID_GOODIX 0x27c6 509 - #define I2C_DEVICE_ID_GOODIX_01E0 0x01e0 510 509 #define I2C_DEVICE_ID_GOODIX_01E8 0x01e8 511 510 #define I2C_DEVICE_ID_GOODIX_01E9 0x01e9 512 511 #define I2C_DEVICE_ID_GOODIX_01F0 0x01f0 ··· 1087 1088 1088 1089 #define USB_VENDOR_ID_PRODIGE 0x05af 1089 1090 #define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 1091 + 1092 + #define I2C_VENDOR_ID_QTEC 0x6243 1090 1093 1091 1094 #define USB_VENDOR_ID_QUANTA 0x0408 1092 1095 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000
+17 -20
drivers/hid/hid-input.c
··· 810 810 break; 811 811 } 812 812 813 - if ((usage->hid & 0xf0) == 0x90) { /* SystemControl*/ 814 - switch (usage->hid & 0xf) { 815 - case 0xb: map_key_clear(KEY_DO_NOT_DISTURB); break; 816 - default: goto ignore; 813 + if ((usage->hid & 0xf0) == 0x90) { /* SystemControl & D-pad */ 814 + switch (usage->hid) { 815 + case HID_GD_UP: usage->hat_dir = 1; break; 816 + case HID_GD_DOWN: usage->hat_dir = 5; break; 817 + case HID_GD_RIGHT: usage->hat_dir = 3; break; 818 + case HID_GD_LEFT: usage->hat_dir = 7; break; 819 + case HID_GD_DO_NOT_DISTURB: 820 + map_key_clear(KEY_DO_NOT_DISTURB); break; 821 + default: goto unknown; 822 + } 823 + 824 + if (usage->hid <= HID_GD_LEFT) { 825 + if (field->dpad) { 826 + map_abs(field->dpad); 827 + goto ignore; 828 + } 829 + map_abs(ABS_HAT0X); 817 830 } 818 831 break; 819 832 } ··· 856 843 */ 857 844 if (field->application == HID_GD_SYSTEM_CONTROL) 858 845 goto ignore; 859 - 860 - if ((usage->hid & 0xf0) == 0x90) { /* D-pad */ 861 - switch (usage->hid) { 862 - case HID_GD_UP: usage->hat_dir = 1; break; 863 - case HID_GD_DOWN: usage->hat_dir = 5; break; 864 - case HID_GD_RIGHT: usage->hat_dir = 3; break; 865 - case HID_GD_LEFT: usage->hat_dir = 7; break; 866 - default: goto unknown; 867 - } 868 - if (field->dpad) { 869 - map_abs(field->dpad); 870 - goto ignore; 871 - } 872 - map_abs(ABS_HAT0X); 873 - break; 874 - } 875 846 876 847 switch (usage->hid) { 877 848 /* These usage IDs map directly to the usage codes. */
+108 -1
drivers/hid/hid-lenovo.c
··· 32 32 #include <linux/leds.h> 33 33 #include <linux/workqueue.h> 34 34 35 + #if IS_ENABLED(CONFIG_ACPI_PLATFORM_PROFILE) 36 + #include <linux/platform_profile.h> 37 + #endif /* CONFIG_ACPI_PLATFORM_PROFILE */ 38 + 35 39 #include "hid-ids.h" 36 40 37 41 /* Userspace expects F20 for mic-mute KEY_MICMUTE does not work */ 38 42 #define LENOVO_KEY_MICMUTE KEY_F20 43 + 44 + /* HID raw events for ThinkPad X12 Tabs*/ 45 + #define TP_X12_RAW_HOTKEY_FN_F4 0x00020003 46 + #define TP_X12_RAW_HOTKEY_FN_F8 0x38001003 47 + #define TP_X12_RAW_HOTKEY_FN_F10 0x00000803 48 + #define TP_X12_RAW_HOTKEY_FN_F12 0x00000403 49 + #define TP_X12_RAW_HOTKEY_FN_SPACE 0x18001003 39 50 40 51 struct lenovo_drvdata { 41 52 u8 led_report[3]; /* Must be first for proper alignment */ ··· 81 70 82 71 #define TP10UBKBD_LED_OFF 1 83 72 #define TP10UBKBD_LED_ON 2 73 + 74 + /* Function to report raw_events as key events*/ 75 + static inline void report_key_event(struct input_dev *input, int keycode) 76 + { 77 + input_report_key(input, keycode, 1); 78 + input_report_key(input, keycode, 0); 79 + input_sync(input); 80 + } 84 81 85 82 static int lenovo_led_set_tp10ubkbd(struct hid_device *hdev, u8 led_code, 86 83 enum led_brightness value) ··· 491 472 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 492 473 return lenovo_input_mapping_tp10_ultrabook_kbd(hdev, hi, field, 493 474 usage, bit, max); 475 + case USB_DEVICE_ID_LENOVO_X12_TAB: 476 + case USB_DEVICE_ID_LENOVO_X12_TAB2: 494 477 case USB_DEVICE_ID_LENOVO_X1_TAB: 495 478 case USB_DEVICE_ID_LENOVO_X1_TAB3: 496 479 return lenovo_input_mapping_x1_tab_kbd(hdev, hi, field, usage, bit, max); ··· 603 582 case USB_DEVICE_ID_LENOVO_TPIIBTKBD: 604 583 lenovo_features_set_cptkbd(hdev); 605 584 break; 585 + case USB_DEVICE_ID_LENOVO_X12_TAB: 586 + case USB_DEVICE_ID_LENOVO_X12_TAB2: 606 587 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 607 588 case USB_DEVICE_ID_LENOVO_X1_TAB: 608 589 case USB_DEVICE_ID_LENOVO_X1_TAB3: ··· 703 680 .attrs = lenovo_attributes_cptkbd, 704 681 }; 705 682 683 + /* Function to handle Lenovo Thinkpad TAB X12's HID raw inputs for fn keys*/ 684 + static int lenovo_raw_event_TP_X12_tab(struct hid_device *hdev, u32 raw_data) 685 + { 686 + struct hid_input *hidinput; 687 + struct input_dev *input = NULL; 688 + 689 + /* Iterate through all associated input devices */ 690 + list_for_each_entry(hidinput, &hdev->inputs, list) { 691 + input = hidinput->input; 692 + if (!input) 693 + continue; 694 + 695 + switch (raw_data) { 696 + /* fn-F20 being used here for MIC mute*/ 697 + case TP_X12_RAW_HOTKEY_FN_F4: 698 + report_key_event(input, LENOVO_KEY_MICMUTE); 699 + return 1; 700 + /* Power-mode or Airplane mode will be called based on the device*/ 701 + case TP_X12_RAW_HOTKEY_FN_F8: 702 + /* 703 + * TP X12 TAB uses Fn-F8 calls Airplanemode 704 + * Whereas TP X12 TAB2 uses Fn-F8 for toggling 705 + * Power modes 706 + */ 707 + if (hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB) { 708 + report_key_event(input, KEY_RFKILL); 709 + return 1; 710 + } 711 + #if IS_ENABLED(CONFIG_ACPI_PLATFORM_PROFILE) 712 + else { 713 + platform_profile_cycle(); 714 + return 1; 715 + } 716 + #endif /* CONFIG_ACPI_PLATFORM_PROFILE */ 717 + return 0; 718 + case TP_X12_RAW_HOTKEY_FN_F10: 719 + /* TAB1 has PICKUP Phone and TAB2 use Snipping tool*/ 720 + (hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB) ? 721 + report_key_event(input, KEY_PICKUP_PHONE) : 722 + report_key_event(input, KEY_SELECTIVE_SCREENSHOT); 723 + return 1; 724 + case TP_X12_RAW_HOTKEY_FN_F12: 725 + /* BookMarks/STAR key*/ 726 + report_key_event(input, KEY_BOOKMARKS); 727 + return 1; 728 + case TP_X12_RAW_HOTKEY_FN_SPACE: 729 + /* Keyboard LED backlight toggle*/ 730 + report_key_event(input, KEY_KBDILLUMTOGGLE); 731 + return 1; 732 + default: 733 + break; 734 + } 735 + } 736 + return 0; 737 + } 738 + 706 739 static int lenovo_raw_event(struct hid_device *hdev, 707 740 struct hid_report *report, u8 *data, int size) 708 741 { ··· 775 696 data[1] = 0x00; 776 697 data[2] = 0x01; 777 698 } 699 + 700 + /* 701 + * Lenovo TP X12 Tab KBD's Fn+XX is HID raw data defined. Report ID is 0x03 702 + * e.g.: Raw data received for MIC mute is 0x00020003. 703 + */ 704 + if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB 705 + || hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2) 706 + && size >= 3 && report->id == 0x03)) 707 + return lenovo_raw_event_TP_X12_tab(hdev, le32_to_cpu(*(u32 *)data)); 778 708 779 709 return 0; 780 710 } ··· 864 776 case USB_DEVICE_ID_LENOVO_TPIIUSBKBD: 865 777 case USB_DEVICE_ID_LENOVO_TPIIBTKBD: 866 778 return lenovo_event_cptkbd(hdev, field, usage, value); 779 + case USB_DEVICE_ID_LENOVO_X12_TAB: 780 + case USB_DEVICE_ID_LENOVO_X12_TAB2: 867 781 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 868 782 case USB_DEVICE_ID_LENOVO_X1_TAB: 869 783 case USB_DEVICE_ID_LENOVO_X1_TAB3: ··· 1147 1057 case USB_DEVICE_ID_LENOVO_TPKBD: 1148 1058 lenovo_led_set_tpkbd(hdev); 1149 1059 break; 1060 + case USB_DEVICE_ID_LENOVO_X12_TAB: 1061 + case USB_DEVICE_ID_LENOVO_X12_TAB2: 1150 1062 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 1151 1063 case USB_DEVICE_ID_LENOVO_X1_TAB: 1152 1064 case USB_DEVICE_ID_LENOVO_X1_TAB3: ··· 1335 1243 * We cannot read the state, only set it, so we force it to on here 1336 1244 * (which should be a no-op) to make sure that our state matches the 1337 1245 * keyboard's FN-lock state. This is the same as what Windows does. 1246 + * 1247 + * For X12 TAB and TAB2, the default windows behaviour Fn-lock Off. 1248 + * Adding additional check to ensure the behaviour in case of 1249 + * Thinkpad X12 Tabs. 1338 1250 */ 1339 - data->fn_lock = true; 1251 + 1252 + data->fn_lock = !(hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB || 1253 + hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2); 1254 + 1340 1255 lenovo_led_set_tp10ubkbd(hdev, TP10UBKBD_FN_LOCK_LED, data->fn_lock); 1341 1256 1342 1257 ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tp10ubkbd); ··· 1387 1288 case USB_DEVICE_ID_LENOVO_TPIIBTKBD: 1388 1289 ret = lenovo_probe_cptkbd(hdev); 1389 1290 break; 1291 + case USB_DEVICE_ID_LENOVO_X12_TAB: 1292 + case USB_DEVICE_ID_LENOVO_X12_TAB2: 1390 1293 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 1391 1294 case USB_DEVICE_ID_LENOVO_X1_TAB: 1392 1295 case USB_DEVICE_ID_LENOVO_X1_TAB3: ··· 1476 1375 case USB_DEVICE_ID_LENOVO_TPIIBTKBD: 1477 1376 lenovo_remove_cptkbd(hdev); 1478 1377 break; 1378 + case USB_DEVICE_ID_LENOVO_X12_TAB: 1379 + case USB_DEVICE_ID_LENOVO_X12_TAB2: 1479 1380 case USB_DEVICE_ID_LENOVO_TP10UBKBD: 1480 1381 case USB_DEVICE_ID_LENOVO_X1_TAB: 1481 1382 case USB_DEVICE_ID_LENOVO_X1_TAB3: ··· 1532 1429 USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB) }, 1533 1430 { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, 1534 1431 USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB3) }, 1432 + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, 1433 + USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB) }, 1434 + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, 1435 + USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB2) }, 1535 1436 { } 1536 1437 }; 1537 1438
+6 -2
drivers/hid/hid-magicmouse.c
··· 52 52 MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); 53 53 54 54 #define TRACKPAD2_2021_BT_VERSION 0x110 55 + #define TRACKPAD_2024_BT_VERSION 0x314 55 56 56 57 #define TRACKPAD_REPORT_ID 0x28 57 58 #define TRACKPAD2_USB_REPORT_ID 0x02 ··· 568 567 */ 569 568 if (hdev->vendor == BT_VENDOR_ID_APPLE) { 570 569 if (input->id.version == TRACKPAD2_2021_BT_VERSION) 570 + input->name = "Apple Inc. Magic Trackpad 2021"; 571 + else if (input->id.version == TRACKPAD_2024_BT_VERSION) { 572 + input->name = "Apple Inc. Magic Trackpad USB-C"; 573 + } else { 571 574 input->name = "Apple Inc. Magic Trackpad"; 572 - else 573 - input->name = "Apple Inc. Magic Trackpad 2"; 575 + } 574 576 } else { /* USB_VENDOR_ID_APPLE */ 575 577 input->name = hdev->name; 576 578 }
+6 -5
drivers/hid/hid-multitouch.c
··· 1460 1460 { 1461 1461 if (hdev->vendor == I2C_VENDOR_ID_GOODIX && 1462 1462 (hdev->product == I2C_DEVICE_ID_GOODIX_01E8 || 1463 - hdev->product == I2C_DEVICE_ID_GOODIX_01E9 || 1464 - hdev->product == I2C_DEVICE_ID_GOODIX_01E0)) { 1463 + hdev->product == I2C_DEVICE_ID_GOODIX_01E9)) { 1465 1464 if (rdesc[607] == 0x15) { 1466 1465 rdesc[607] = 0x25; 1467 1466 dev_info( ··· 2085 2086 { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU, 2086 2087 HID_DEVICE(BUS_I2C, HID_GROUP_ANY, I2C_VENDOR_ID_GOODIX, 2087 2088 I2C_DEVICE_ID_GOODIX_01E9) }, 2088 - { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU, 2089 - HID_DEVICE(BUS_I2C, HID_GROUP_ANY, I2C_VENDOR_ID_GOODIX, 2090 - I2C_DEVICE_ID_GOODIX_01E0) }, 2091 2089 2092 2090 /* GoodTouch panels */ 2093 2091 { .driver_data = MT_CLS_NSMU, ··· 2313 2317 { .driver_data = MT_CLS_SIS, 2314 2318 HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_SIS_TOUCH, 2315 2319 HID_ANY_ID) }, 2320 + 2321 + /* Hantick */ 2322 + { .driver_data = MT_CLS_NSMU, 2323 + HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, 2324 + I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288) }, 2316 2325 2317 2326 /* Generic MT device */ 2318 2327 { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
+6 -10
drivers/hid/hid-nintendo.c
··· 456 456 { /* sentinel */ }, 457 457 }; 458 458 459 - /* 460 - * "A", "B", and "C" are mapped positionally, rather than by label (e.g., "A" 461 - * gets assigned to BTN_EAST instead of BTN_A). 462 - */ 463 459 static const struct joycon_ctlr_button_mapping gencon_button_mappings[] = { 464 - { BTN_SOUTH, JC_BTN_A, }, 465 - { BTN_EAST, JC_BTN_B, }, 466 - { BTN_WEST, JC_BTN_R, }, 460 + { BTN_A, JC_BTN_A, }, 461 + { BTN_B, JC_BTN_B, }, 462 + { BTN_C, JC_BTN_R, }, 463 + { BTN_X, JC_BTN_X, }, /* MD/GEN 6B Only */ 464 + { BTN_Y, JC_BTN_Y, }, /* MD/GEN 6B Only */ 465 + { BTN_Z, JC_BTN_L, }, /* MD/GEN 6B Only */ 467 466 { BTN_SELECT, JC_BTN_ZR, }, 468 467 { BTN_START, JC_BTN_PLUS, }, 469 468 { BTN_MODE, JC_BTN_HOME, }, ··· 470 471 { /* sentinel */ }, 471 472 }; 472 473 473 - /* 474 - * N64's C buttons get assigned to d-pad directions and registered as buttons. 475 - */ 476 474 static const struct joycon_ctlr_button_mapping n64con_button_mappings[] = { 477 475 { BTN_A, JC_BTN_A, }, 478 476 { BTN_B, JC_BTN_B, },
+10 -10
drivers/hid/hid-roccat-arvo.c
··· 224 224 } 225 225 226 226 static ssize_t arvo_sysfs_write_button(struct file *fp, 227 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 228 - loff_t off, size_t count) 227 + struct kobject *kobj, const struct bin_attribute *attr, 228 + char *buf, loff_t off, size_t count) 229 229 { 230 230 return arvo_sysfs_write(fp, kobj, buf, off, count, 231 231 sizeof(struct arvo_button), ARVO_COMMAND_BUTTON); 232 232 } 233 - static BIN_ATTR(button, 0220, NULL, arvo_sysfs_write_button, 234 - sizeof(struct arvo_button)); 233 + static const BIN_ATTR(button, 0220, NULL, arvo_sysfs_write_button, 234 + sizeof(struct arvo_button)); 235 235 236 236 static ssize_t arvo_sysfs_read_info(struct file *fp, 237 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 238 - loff_t off, size_t count) 237 + struct kobject *kobj, const struct bin_attribute *attr, 238 + char *buf, loff_t off, size_t count) 239 239 { 240 240 return arvo_sysfs_read(fp, kobj, buf, off, count, 241 241 sizeof(struct arvo_info), ARVO_COMMAND_INFO); 242 242 } 243 - static BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL, 244 - sizeof(struct arvo_info)); 243 + static const BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL, 244 + sizeof(struct arvo_info)); 245 245 246 246 static struct attribute *arvo_attrs[] = { 247 247 &dev_attr_mode_key.attr, ··· 250 250 NULL, 251 251 }; 252 252 253 - static struct bin_attribute *arvo_bin_attributes[] = { 253 + static const struct bin_attribute *const arvo_bin_attributes[] = { 254 254 &bin_attr_button, 255 255 &bin_attr_info, 256 256 NULL, ··· 258 258 259 259 static const struct attribute_group arvo_group = { 260 260 .attrs = arvo_attrs, 261 - .bin_attrs = arvo_bin_attributes, 261 + .bin_attrs_new = arvo_bin_attributes, 262 262 }; 263 263 264 264 static const struct attribute_group *arvo_groups[] = {
+11 -11
drivers/hid/hid-roccat-common.h
··· 46 46 47 47 #define ROCCAT_COMMON2_SYSFS_W(thingy, COMMAND, SIZE) \ 48 48 static ssize_t roccat_common2_sysfs_write_ ## thingy(struct file *fp, \ 49 - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 50 - loff_t off, size_t count) \ 49 + struct kobject *kobj, const struct bin_attribute *attr, \ 50 + char *buf, loff_t off, size_t count) \ 51 51 { \ 52 52 return roccat_common2_sysfs_write(fp, kobj, buf, off, count, \ 53 53 SIZE, COMMAND); \ ··· 55 55 56 56 #define ROCCAT_COMMON2_SYSFS_R(thingy, COMMAND, SIZE) \ 57 57 static ssize_t roccat_common2_sysfs_read_ ## thingy(struct file *fp, \ 58 - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 59 - loff_t off, size_t count) \ 58 + struct kobject *kobj, const struct bin_attribute *attr, \ 59 + char *buf, loff_t off, size_t count) \ 60 60 { \ 61 61 return roccat_common2_sysfs_read(fp, kobj, buf, off, count, \ 62 62 SIZE, COMMAND); \ ··· 68 68 69 69 #define ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(thingy, COMMAND, SIZE) \ 70 70 ROCCAT_COMMON2_SYSFS_RW(thingy, COMMAND, SIZE); \ 71 - static struct bin_attribute bin_attr_ ## thingy = { \ 71 + static const struct bin_attribute bin_attr_ ## thingy = { \ 72 72 .attr = { .name = #thingy, .mode = 0660 }, \ 73 73 .size = SIZE, \ 74 - .read = roccat_common2_sysfs_read_ ## thingy, \ 75 - .write = roccat_common2_sysfs_write_ ## thingy \ 74 + .read_new = roccat_common2_sysfs_read_ ## thingy, \ 75 + .write_new = roccat_common2_sysfs_write_ ## thingy \ 76 76 } 77 77 78 78 #define ROCCAT_COMMON2_BIN_ATTRIBUTE_R(thingy, COMMAND, SIZE) \ 79 79 ROCCAT_COMMON2_SYSFS_R(thingy, COMMAND, SIZE); \ 80 - static struct bin_attribute bin_attr_ ## thingy = { \ 80 + static const struct bin_attribute bin_attr_ ## thingy = { \ 81 81 .attr = { .name = #thingy, .mode = 0440 }, \ 82 82 .size = SIZE, \ 83 - .read = roccat_common2_sysfs_read_ ## thingy, \ 83 + .read_new = roccat_common2_sysfs_read_ ## thingy, \ 84 84 } 85 85 86 86 #define ROCCAT_COMMON2_BIN_ATTRIBUTE_W(thingy, COMMAND, SIZE) \ 87 87 ROCCAT_COMMON2_SYSFS_W(thingy, COMMAND, SIZE); \ 88 - static struct bin_attribute bin_attr_ ## thingy = { \ 88 + static const struct bin_attribute bin_attr_ ## thingy = { \ 89 89 .attr = { .name = #thingy, .mode = 0220 }, \ 90 90 .size = SIZE, \ 91 - .write = roccat_common2_sysfs_write_ ## thingy \ 91 + .write_new = roccat_common2_sysfs_write_ ## thingy \ 92 92 } 93 93 94 94 #endif
+11 -11
drivers/hid/hid-roccat-isku.c
··· 156 156 157 157 #define ISKU_SYSFS_W(thingy, THINGY) \ 158 158 static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj, \ 159 - struct bin_attribute *attr, char *buf, \ 159 + const struct bin_attribute *attr, char *buf, \ 160 160 loff_t off, size_t count) \ 161 161 { \ 162 162 return isku_sysfs_write(fp, kobj, buf, off, count, \ ··· 165 165 166 166 #define ISKU_SYSFS_R(thingy, THINGY) \ 167 167 static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj, \ 168 - struct bin_attribute *attr, char *buf, \ 168 + const struct bin_attribute *attr, char *buf, \ 169 169 loff_t off, size_t count) \ 170 170 { \ 171 171 return isku_sysfs_read(fp, kobj, buf, off, count, \ ··· 178 178 179 179 #define ISKU_BIN_ATTR_RW(thingy, THINGY) \ 180 180 ISKU_SYSFS_RW(thingy, THINGY); \ 181 - static struct bin_attribute bin_attr_##thingy = { \ 181 + static const struct bin_attribute bin_attr_##thingy = { \ 182 182 .attr = { .name = #thingy, .mode = 0660 }, \ 183 183 .size = ISKU_SIZE_ ## THINGY, \ 184 - .read = isku_sysfs_read_ ## thingy, \ 185 - .write = isku_sysfs_write_ ## thingy \ 184 + .read_new = isku_sysfs_read_ ## thingy, \ 185 + .write_new = isku_sysfs_write_ ## thingy \ 186 186 } 187 187 188 188 #define ISKU_BIN_ATTR_R(thingy, THINGY) \ 189 189 ISKU_SYSFS_R(thingy, THINGY); \ 190 - static struct bin_attribute bin_attr_##thingy = { \ 190 + static const struct bin_attribute bin_attr_##thingy = { \ 191 191 .attr = { .name = #thingy, .mode = 0440 }, \ 192 192 .size = ISKU_SIZE_ ## THINGY, \ 193 - .read = isku_sysfs_read_ ## thingy, \ 193 + .read_new = isku_sysfs_read_ ## thingy, \ 194 194 } 195 195 196 196 #define ISKU_BIN_ATTR_W(thingy, THINGY) \ 197 197 ISKU_SYSFS_W(thingy, THINGY); \ 198 - static struct bin_attribute bin_attr_##thingy = { \ 198 + static const struct bin_attribute bin_attr_##thingy = { \ 199 199 .attr = { .name = #thingy, .mode = 0220 }, \ 200 200 .size = ISKU_SIZE_ ## THINGY, \ 201 - .write = isku_sysfs_write_ ## thingy \ 201 + .write_new = isku_sysfs_write_ ## thingy \ 202 202 } 203 203 204 204 ISKU_BIN_ATTR_RW(macro, MACRO); ··· 217 217 ISKU_BIN_ATTR_W(reset, RESET); 218 218 ISKU_BIN_ATTR_R(info, INFO); 219 219 220 - static struct bin_attribute *isku_bin_attributes[] = { 220 + static const struct bin_attribute *const isku_bin_attributes[] = { 221 221 &bin_attr_macro, 222 222 &bin_attr_keys_function, 223 223 &bin_attr_keys_easyzone, ··· 238 238 239 239 static const struct attribute_group isku_group = { 240 240 .attrs = isku_attrs, 241 - .bin_attrs = isku_bin_attributes, 241 + .bin_attrs_new = isku_bin_attributes, 242 242 }; 243 243 244 244 static const struct attribute_group *isku_groups[] = {
+11 -11
drivers/hid/hid-roccat-kone.c
··· 261 261 } 262 262 263 263 static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, 264 - struct bin_attribute *attr, char *buf, 264 + const struct bin_attribute *attr, char *buf, 265 265 loff_t off, size_t count) { 266 266 struct device *dev = kobj_to_dev(kobj)->parent->parent; 267 267 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); ··· 285 285 * case of error the old data is still valid 286 286 */ 287 287 static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, 288 - struct bin_attribute *attr, char *buf, 288 + const struct bin_attribute *attr, char *buf, 289 289 loff_t off, size_t count) { 290 290 struct device *dev = kobj_to_dev(kobj)->parent->parent; 291 291 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); ··· 327 327 328 328 return sizeof(struct kone_settings); 329 329 } 330 - static BIN_ATTR(settings, 0660, kone_sysfs_read_settings, 331 - kone_sysfs_write_settings, sizeof(struct kone_settings)); 330 + static const BIN_ATTR(settings, 0660, kone_sysfs_read_settings, 331 + kone_sysfs_write_settings, sizeof(struct kone_settings)); 332 332 333 333 static ssize_t kone_sysfs_read_profilex(struct file *fp, 334 - struct kobject *kobj, struct bin_attribute *attr, 334 + struct kobject *kobj, const struct bin_attribute *attr, 335 335 char *buf, loff_t off, size_t count) { 336 336 struct device *dev = kobj_to_dev(kobj)->parent->parent; 337 337 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); ··· 351 351 352 352 /* Writes data only if different to stored data */ 353 353 static ssize_t kone_sysfs_write_profilex(struct file *fp, 354 - struct kobject *kobj, struct bin_attribute *attr, 354 + struct kobject *kobj, const struct bin_attribute *attr, 355 355 char *buf, loff_t off, size_t count) { 356 356 struct device *dev = kobj_to_dev(kobj)->parent->parent; 357 357 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); ··· 382 382 return sizeof(struct kone_profile); 383 383 } 384 384 #define PROFILE_ATTR(number) \ 385 - static struct bin_attribute bin_attr_profile##number = { \ 385 + static const struct bin_attribute bin_attr_profile##number = { \ 386 386 .attr = { .name = "profile" #number, .mode = 0660 }, \ 387 387 .size = sizeof(struct kone_profile), \ 388 - .read = kone_sysfs_read_profilex, \ 389 - .write = kone_sysfs_write_profilex, \ 388 + .read_new = kone_sysfs_read_profilex, \ 389 + .write_new = kone_sysfs_write_profilex, \ 390 390 .private = &profile_numbers[number-1], \ 391 391 } 392 392 PROFILE_ATTR(1); ··· 634 634 NULL, 635 635 }; 636 636 637 - static struct bin_attribute *kone_bin_attributes[] = { 637 + static const struct bin_attribute *const kone_bin_attributes[] = { 638 638 &bin_attr_settings, 639 639 &bin_attr_profile1, 640 640 &bin_attr_profile2, ··· 646 646 647 647 static const struct attribute_group kone_group = { 648 648 .attrs = kone_attrs, 649 - .bin_attrs = kone_bin_attributes, 649 + .bin_attrs_new = kone_bin_attributes, 650 650 }; 651 651 652 652 static const struct attribute_group *kone_groups[] = {
+21 -21
drivers/hid/hid-roccat-koneplus.c
··· 128 128 129 129 #define KONEPLUS_SYSFS_W(thingy, THINGY) \ 130 130 static ssize_t koneplus_sysfs_write_ ## thingy(struct file *fp, \ 131 - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 132 - loff_t off, size_t count) \ 131 + struct kobject *kobj, const struct bin_attribute *attr, \ 132 + char *buf, loff_t off, size_t count) \ 133 133 { \ 134 134 return koneplus_sysfs_write(fp, kobj, buf, off, count, \ 135 135 KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \ ··· 137 137 138 138 #define KONEPLUS_SYSFS_R(thingy, THINGY) \ 139 139 static ssize_t koneplus_sysfs_read_ ## thingy(struct file *fp, \ 140 - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 141 - loff_t off, size_t count) \ 140 + struct kobject *kobj, const struct bin_attribute *attr, \ 141 + char *buf, loff_t off, size_t count) \ 142 142 { \ 143 143 return koneplus_sysfs_read(fp, kobj, buf, off, count, \ 144 144 KONEPLUS_SIZE_ ## THINGY, KONEPLUS_COMMAND_ ## THINGY); \ ··· 150 150 151 151 #define KONEPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \ 152 152 KONEPLUS_SYSFS_RW(thingy, THINGY); \ 153 - static struct bin_attribute bin_attr_##thingy = { \ 153 + static const struct bin_attribute bin_attr_##thingy = { \ 154 154 .attr = { .name = #thingy, .mode = 0660 }, \ 155 155 .size = KONEPLUS_SIZE_ ## THINGY, \ 156 - .read = koneplus_sysfs_read_ ## thingy, \ 157 - .write = koneplus_sysfs_write_ ## thingy \ 156 + .read_new = koneplus_sysfs_read_ ## thingy, \ 157 + .write_new = koneplus_sysfs_write_ ## thingy \ 158 158 } 159 159 160 160 #define KONEPLUS_BIN_ATTRIBUTE_R(thingy, THINGY) \ 161 161 KONEPLUS_SYSFS_R(thingy, THINGY); \ 162 - static struct bin_attribute bin_attr_##thingy = { \ 162 + static const struct bin_attribute bin_attr_##thingy = { \ 163 163 .attr = { .name = #thingy, .mode = 0440 }, \ 164 164 .size = KONEPLUS_SIZE_ ## THINGY, \ 165 - .read = koneplus_sysfs_read_ ## thingy, \ 165 + .read_new = koneplus_sysfs_read_ ## thingy, \ 166 166 } 167 167 168 168 #define KONEPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \ 169 169 KONEPLUS_SYSFS_W(thingy, THINGY); \ 170 - static struct bin_attribute bin_attr_##thingy = { \ 170 + static const struct bin_attribute bin_attr_##thingy = { \ 171 171 .attr = { .name = #thingy, .mode = 0220 }, \ 172 172 .size = KONEPLUS_SIZE_ ## THINGY, \ 173 - .write = koneplus_sysfs_write_ ## thingy \ 173 + .write_new = koneplus_sysfs_write_ ## thingy \ 174 174 } 175 175 KONEPLUS_BIN_ATTRIBUTE_W(control, CONTROL); 176 176 KONEPLUS_BIN_ATTRIBUTE_W(talk, TALK); ··· 183 183 KONEPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS); 184 184 185 185 static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, 186 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 187 - loff_t off, size_t count) 186 + struct kobject *kobj, const struct bin_attribute *attr, 187 + char *buf, loff_t off, size_t count) 188 188 { 189 189 struct device *dev = kobj_to_dev(kobj)->parent->parent; 190 190 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ··· 201 201 } 202 202 203 203 static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, 204 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 205 - loff_t off, size_t count) 204 + struct kobject *kobj, const struct bin_attribute *attr, 205 + char *buf, loff_t off, size_t count) 206 206 { 207 207 struct device *dev = kobj_to_dev(kobj)->parent->parent; 208 208 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ··· 219 219 } 220 220 221 221 #define PROFILE_ATTR(number) \ 222 - static struct bin_attribute bin_attr_profile##number##_settings = { \ 222 + static const struct bin_attribute bin_attr_profile##number##_settings = { \ 223 223 .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ 224 224 .size = KONEPLUS_SIZE_PROFILE_SETTINGS, \ 225 - .read = koneplus_sysfs_read_profilex_settings, \ 225 + .read_new = koneplus_sysfs_read_profilex_settings, \ 226 226 .private = &profile_numbers[number-1], \ 227 227 }; \ 228 - static struct bin_attribute bin_attr_profile##number##_buttons = { \ 228 + static const struct bin_attribute bin_attr_profile##number##_buttons = { \ 229 229 .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ 230 230 .size = KONEPLUS_SIZE_PROFILE_BUTTONS, \ 231 - .read = koneplus_sysfs_read_profilex_buttons, \ 231 + .read_new = koneplus_sysfs_read_profilex_buttons, \ 232 232 .private = &profile_numbers[number-1], \ 233 233 }; 234 234 PROFILE_ATTR(1); ··· 321 321 NULL, 322 322 }; 323 323 324 - static struct bin_attribute *koneplus_bin_attributes[] = { 324 + static const struct bin_attribute *const koneplus_bin_attributes[] = { 325 325 &bin_attr_control, 326 326 &bin_attr_talk, 327 327 &bin_attr_macro, ··· 346 346 347 347 static const struct attribute_group koneplus_group = { 348 348 .attrs = koneplus_attrs, 349 - .bin_attrs = koneplus_bin_attributes, 349 + .bin_attrs_new = koneplus_bin_attributes, 350 350 }; 351 351 352 352 static const struct attribute_group *koneplus_groups[] = {
+2 -2
drivers/hid/hid-roccat-konepure.c
··· 47 47 ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(sensor, 0x0f, 0x06); 48 48 ROCCAT_COMMON2_BIN_ATTRIBUTE_W(talk, 0x10, 0x10); 49 49 50 - static struct bin_attribute *konepure_bin_attrs[] = { 50 + static const struct bin_attribute *const konepure_bin_attrs[] = { 51 51 &bin_attr_actual_profile, 52 52 &bin_attr_control, 53 53 &bin_attr_info, ··· 62 62 }; 63 63 64 64 static const struct attribute_group konepure_group = { 65 - .bin_attrs = konepure_bin_attrs, 65 + .bin_attrs_new = konepure_bin_attrs, 66 66 }; 67 67 68 68 static const struct attribute_group *konepure_groups[] = {
+19 -19
drivers/hid/hid-roccat-kovaplus.c
··· 171 171 172 172 #define KOVAPLUS_SYSFS_W(thingy, THINGY) \ 173 173 static ssize_t kovaplus_sysfs_write_ ## thingy(struct file *fp, \ 174 - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 175 - loff_t off, size_t count) \ 174 + struct kobject *kobj, const struct bin_attribute *attr, \ 175 + char *buf, loff_t off, size_t count) \ 176 176 { \ 177 177 return kovaplus_sysfs_write(fp, kobj, buf, off, count, \ 178 178 KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \ ··· 180 180 181 181 #define KOVAPLUS_SYSFS_R(thingy, THINGY) \ 182 182 static ssize_t kovaplus_sysfs_read_ ## thingy(struct file *fp, \ 183 - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 184 - loff_t off, size_t count) \ 183 + struct kobject *kobj, const struct bin_attribute *attr, \ 184 + char *buf, loff_t off, size_t count) \ 185 185 { \ 186 186 return kovaplus_sysfs_read(fp, kobj, buf, off, count, \ 187 187 KOVAPLUS_SIZE_ ## THINGY, KOVAPLUS_COMMAND_ ## THINGY); \ ··· 193 193 194 194 #define KOVAPLUS_BIN_ATTRIBUTE_RW(thingy, THINGY) \ 195 195 KOVAPLUS_SYSFS_RW(thingy, THINGY); \ 196 - static struct bin_attribute bin_attr_##thingy = { \ 196 + static const struct bin_attribute bin_attr_##thingy = { \ 197 197 .attr = { .name = #thingy, .mode = 0660 }, \ 198 198 .size = KOVAPLUS_SIZE_ ## THINGY, \ 199 - .read = kovaplus_sysfs_read_ ## thingy, \ 200 - .write = kovaplus_sysfs_write_ ## thingy \ 199 + .read_new = kovaplus_sysfs_read_ ## thingy, \ 200 + .write_new = kovaplus_sysfs_write_ ## thingy \ 201 201 } 202 202 203 203 #define KOVAPLUS_BIN_ATTRIBUTE_W(thingy, THINGY) \ 204 204 KOVAPLUS_SYSFS_W(thingy, THINGY); \ 205 - static struct bin_attribute bin_attr_##thingy = { \ 205 + static const struct bin_attribute bin_attr_##thingy = { \ 206 206 .attr = { .name = #thingy, .mode = 0220 }, \ 207 207 .size = KOVAPLUS_SIZE_ ## THINGY, \ 208 - .write = kovaplus_sysfs_write_ ## thingy \ 208 + .write_new = kovaplus_sysfs_write_ ## thingy \ 209 209 } 210 210 KOVAPLUS_BIN_ATTRIBUTE_W(control, CONTROL); 211 211 KOVAPLUS_BIN_ATTRIBUTE_RW(info, INFO); ··· 213 213 KOVAPLUS_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS); 214 214 215 215 static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp, 216 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 217 - loff_t off, size_t count) 216 + struct kobject *kobj, const struct bin_attribute *attr, 217 + char *buf, loff_t off, size_t count) 218 218 { 219 219 struct device *dev = kobj_to_dev(kobj)->parent->parent; 220 220 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ··· 231 231 } 232 232 233 233 static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp, 234 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 235 - loff_t off, size_t count) 234 + struct kobject *kobj, const struct bin_attribute *attr, 235 + char *buf, loff_t off, size_t count) 236 236 { 237 237 struct device *dev = kobj_to_dev(kobj)->parent->parent; 238 238 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ··· 249 249 } 250 250 251 251 #define PROFILE_ATTR(number) \ 252 - static struct bin_attribute bin_attr_profile##number##_settings = { \ 252 + static const struct bin_attribute bin_attr_profile##number##_settings = { \ 253 253 .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ 254 254 .size = KOVAPLUS_SIZE_PROFILE_SETTINGS, \ 255 - .read = kovaplus_sysfs_read_profilex_settings, \ 255 + .read_new = kovaplus_sysfs_read_profilex_settings, \ 256 256 .private = &profile_numbers[number-1], \ 257 257 }; \ 258 - static struct bin_attribute bin_attr_profile##number##_buttons = { \ 258 + static const struct bin_attribute bin_attr_profile##number##_buttons = { \ 259 259 .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ 260 260 .size = KOVAPLUS_SIZE_PROFILE_BUTTONS, \ 261 - .read = kovaplus_sysfs_read_profilex_buttons, \ 261 + .read_new = kovaplus_sysfs_read_profilex_buttons, \ 262 262 .private = &profile_numbers[number-1], \ 263 263 }; 264 264 PROFILE_ATTR(1); ··· 379 379 NULL, 380 380 }; 381 381 382 - static struct bin_attribute *kovaplus_bin_attributes[] = { 382 + static const struct bin_attribute *const kovaplus_bin_attributes[] = { 383 383 &bin_attr_control, 384 384 &bin_attr_info, 385 385 &bin_attr_profile_settings, ··· 399 399 400 400 static const struct attribute_group kovaplus_group = { 401 401 .attrs = kovaplus_attrs, 402 - .bin_attrs = kovaplus_bin_attributes, 402 + .bin_attrs_new = kovaplus_bin_attributes, 403 403 }; 404 404 405 405 static const struct attribute_group *kovaplus_groups[] = {
+5 -5
drivers/hid/hid-roccat-lua.c
··· 66 66 67 67 #define LUA_SYSFS_W(thingy, THINGY) \ 68 68 static ssize_t lua_sysfs_write_ ## thingy(struct file *fp, \ 69 - struct kobject *kobj, struct bin_attribute *attr, \ 69 + struct kobject *kobj, const struct bin_attribute *attr, \ 70 70 char *buf, loff_t off, size_t count) \ 71 71 { \ 72 72 return lua_sysfs_write(fp, kobj, buf, off, count, \ ··· 75 75 76 76 #define LUA_SYSFS_R(thingy, THINGY) \ 77 77 static ssize_t lua_sysfs_read_ ## thingy(struct file *fp, \ 78 - struct kobject *kobj, struct bin_attribute *attr, \ 78 + struct kobject *kobj, const struct bin_attribute *attr, \ 79 79 char *buf, loff_t off, size_t count) \ 80 80 { \ 81 81 return lua_sysfs_read(fp, kobj, buf, off, count, \ ··· 85 85 #define LUA_BIN_ATTRIBUTE_RW(thingy, THINGY) \ 86 86 LUA_SYSFS_W(thingy, THINGY) \ 87 87 LUA_SYSFS_R(thingy, THINGY) \ 88 - static struct bin_attribute lua_ ## thingy ## _attr = { \ 88 + static const struct bin_attribute lua_ ## thingy ## _attr = { \ 89 89 .attr = { .name = #thingy, .mode = 0660 }, \ 90 90 .size = LUA_SIZE_ ## THINGY, \ 91 - .read = lua_sysfs_read_ ## thingy, \ 92 - .write = lua_sysfs_write_ ## thingy \ 91 + .read_new = lua_sysfs_read_ ## thingy, \ 92 + .write_new = lua_sysfs_write_ ## thingy \ 93 93 }; 94 94 95 95 LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
+25 -25
drivers/hid/hid-roccat-pyra.c
··· 129 129 130 130 #define PYRA_SYSFS_W(thingy, THINGY) \ 131 131 static ssize_t pyra_sysfs_write_ ## thingy(struct file *fp, \ 132 - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 133 - loff_t off, size_t count) \ 132 + struct kobject *kobj, const struct bin_attribute *attr, \ 133 + char *buf, loff_t off, size_t count) \ 134 134 { \ 135 135 return pyra_sysfs_write(fp, kobj, buf, off, count, \ 136 136 PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \ ··· 138 138 139 139 #define PYRA_SYSFS_R(thingy, THINGY) \ 140 140 static ssize_t pyra_sysfs_read_ ## thingy(struct file *fp, \ 141 - struct kobject *kobj, struct bin_attribute *attr, char *buf, \ 142 - loff_t off, size_t count) \ 141 + struct kobject *kobj, const struct bin_attribute *attr, \ 142 + char *buf, loff_t off, size_t count) \ 143 143 { \ 144 144 return pyra_sysfs_read(fp, kobj, buf, off, count, \ 145 145 PYRA_SIZE_ ## THINGY, PYRA_COMMAND_ ## THINGY); \ ··· 151 151 152 152 #define PYRA_BIN_ATTRIBUTE_RW(thingy, THINGY) \ 153 153 PYRA_SYSFS_RW(thingy, THINGY); \ 154 - static struct bin_attribute bin_attr_##thingy = { \ 154 + static const struct bin_attribute bin_attr_##thingy = { \ 155 155 .attr = { .name = #thingy, .mode = 0660 }, \ 156 156 .size = PYRA_SIZE_ ## THINGY, \ 157 - .read = pyra_sysfs_read_ ## thingy, \ 158 - .write = pyra_sysfs_write_ ## thingy \ 157 + .read_new = pyra_sysfs_read_ ## thingy, \ 158 + .write_new = pyra_sysfs_write_ ## thingy \ 159 159 } 160 160 161 161 #define PYRA_BIN_ATTRIBUTE_R(thingy, THINGY) \ 162 162 PYRA_SYSFS_R(thingy, THINGY); \ 163 - static struct bin_attribute bin_attr_##thingy = { \ 163 + static const struct bin_attribute bin_attr_##thingy = { \ 164 164 .attr = { .name = #thingy, .mode = 0440 }, \ 165 - .size = PYRA_SIZE_ ## THINGY, \ 166 - .read = pyra_sysfs_read_ ## thingy, \ 165 + .size_new = PYRA_SIZE_ ## THINGY, \ 166 + .read_new = pyra_sysfs_read_ ## thingy, \ 167 167 } 168 168 169 169 #define PYRA_BIN_ATTRIBUTE_W(thingy, THINGY) \ 170 170 PYRA_SYSFS_W(thingy, THINGY); \ 171 - static struct bin_attribute bin_attr_##thingy = { \ 171 + static const struct bin_attribute bin_attr_##thingy = { \ 172 172 .attr = { .name = #thingy, .mode = 0220 }, \ 173 173 .size = PYRA_SIZE_ ## THINGY, \ 174 - .write = pyra_sysfs_write_ ## thingy \ 174 + .write_new = pyra_sysfs_write_ ## thingy \ 175 175 } 176 176 177 177 PYRA_BIN_ATTRIBUTE_W(control, CONTROL); ··· 180 180 PYRA_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS); 181 181 182 182 static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, 183 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 184 - loff_t off, size_t count) 183 + struct kobject *kobj, const struct bin_attribute *attr, 184 + char *buf, loff_t off, size_t count) 185 185 { 186 186 struct device *dev = kobj_to_dev(kobj)->parent->parent; 187 187 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ··· 198 198 } 199 199 200 200 static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, 201 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 202 - loff_t off, size_t count) 201 + struct kobject *kobj, const struct bin_attribute *attr, 202 + char *buf, loff_t off, size_t count) 203 203 { 204 204 struct device *dev = kobj_to_dev(kobj)->parent->parent; 205 205 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); ··· 216 216 } 217 217 218 218 #define PROFILE_ATTR(number) \ 219 - static struct bin_attribute bin_attr_profile##number##_settings = { \ 219 + static const struct bin_attribute bin_attr_profile##number##_settings = { \ 220 220 .attr = { .name = "profile" #number "_settings", .mode = 0440 }, \ 221 221 .size = PYRA_SIZE_PROFILE_SETTINGS, \ 222 - .read = pyra_sysfs_read_profilex_settings, \ 222 + .read_new = pyra_sysfs_read_profilex_settings, \ 223 223 .private = &profile_numbers[number-1], \ 224 224 }; \ 225 - static struct bin_attribute bin_attr_profile##number##_buttons = { \ 225 + static const struct bin_attribute bin_attr_profile##number##_buttons = { \ 226 226 .attr = { .name = "profile" #number "_buttons", .mode = 0440 }, \ 227 227 .size = PYRA_SIZE_PROFILE_BUTTONS, \ 228 - .read = pyra_sysfs_read_profilex_buttons, \ 228 + .read_new = pyra_sysfs_read_profilex_buttons, \ 229 229 .private = &profile_numbers[number-1], \ 230 230 }; 231 231 PROFILE_ATTR(1); ··· 235 235 PROFILE_ATTR(5); 236 236 237 237 static ssize_t pyra_sysfs_write_settings(struct file *fp, 238 - struct kobject *kobj, struct bin_attribute *attr, char *buf, 239 - loff_t off, size_t count) 238 + struct kobject *kobj, const struct bin_attribute *attr, 239 + char *buf, loff_t off, size_t count) 240 240 { 241 241 struct device *dev = kobj_to_dev(kobj)->parent->parent; 242 242 struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); ··· 273 273 } 274 274 275 275 PYRA_SYSFS_R(settings, SETTINGS); 276 - static struct bin_attribute bin_attr_settings = 276 + static const struct bin_attribute bin_attr_settings = 277 277 __BIN_ATTR(settings, (S_IWUSR | S_IRUGO), 278 278 pyra_sysfs_read_settings, pyra_sysfs_write_settings, 279 279 PYRA_SIZE_SETTINGS); ··· 334 334 NULL, 335 335 }; 336 336 337 - static struct bin_attribute *pyra_bin_attributes[] = { 337 + static const struct bin_attribute *const pyra_bin_attributes[] = { 338 338 &bin_attr_control, 339 339 &bin_attr_info, 340 340 &bin_attr_profile_settings, ··· 355 355 356 356 static const struct attribute_group pyra_group = { 357 357 .attrs = pyra_attrs, 358 - .bin_attrs = pyra_bin_attributes, 358 + .bin_attrs_new = pyra_bin_attributes, 359 359 }; 360 360 361 361 static const struct attribute_group *pyra_groups[] = {
+2 -2
drivers/hid/hid-roccat-ryos.c
··· 47 47 ROCCAT_COMMON2_BIN_ATTRIBUTE_W(custom_lights, 0x18, 0x14); 48 48 ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(light_macro, 0x19, 0x07d2); 49 49 50 - static struct bin_attribute *ryos_bin_attrs[] = { 50 + static const struct bin_attribute *const ryos_bin_attrs[] = { 51 51 &bin_attr_control, 52 52 &bin_attr_profile, 53 53 &bin_attr_keys_primary, ··· 70 70 }; 71 71 72 72 static const struct attribute_group ryos_group = { 73 - .bin_attrs = ryos_bin_attrs, 73 + .bin_attrs_new = ryos_bin_attrs, 74 74 }; 75 75 76 76 static const struct attribute_group *ryos_groups[] = {
+2 -2
drivers/hid/hid-roccat-savu.c
··· 30 30 ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(info, 0x9, 0x08); 31 31 ROCCAT_COMMON2_BIN_ATTRIBUTE_RW(sensor, 0xc, 0x04); 32 32 33 - static struct bin_attribute *savu_bin_attrs[] = { 33 + static const struct bin_attribute *const savu_bin_attrs[] = { 34 34 &bin_attr_control, 35 35 &bin_attr_profile, 36 36 &bin_attr_general, ··· 42 42 }; 43 43 44 44 static const struct attribute_group savu_group = { 45 - .bin_attrs = savu_bin_attrs, 45 + .bin_attrs_new = savu_bin_attrs, 46 46 }; 47 47 48 48 static const struct attribute_group *savu_groups[] = {
+1
drivers/hid/hid-steam.c
··· 1306 1306 1307 1307 cancel_delayed_work_sync(&steam->mode_switch); 1308 1308 cancel_work_sync(&steam->work_connect); 1309 + cancel_work_sync(&steam->rumble_work); 1309 1310 hid_destroy_device(steam->client_hdev); 1310 1311 steam->client_hdev = NULL; 1311 1312 steam->client_opened = 0;
+110 -10
drivers/hid/hid-steelseries.c
··· 19 19 20 20 #define STEELSERIES_SRWS1 BIT(0) 21 21 #define STEELSERIES_ARCTIS_1 BIT(1) 22 + #define STEELSERIES_ARCTIS_9 BIT(2) 22 23 23 24 struct steelseries_device { 24 25 struct hid_device *hdev; ··· 33 32 struct power_supply *battery; 34 33 uint8_t battery_capacity; 35 34 bool headset_connected; 35 + bool battery_charging; 36 36 }; 37 37 38 38 #if IS_BUILTIN(CONFIG_LEDS_CLASS) || \ ··· 370 368 371 369 hid_hw_stop(hdev); 372 370 kfree(drv_data); 373 - return; 374 371 } 375 372 #endif 376 373 377 374 #define STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS 3000 378 375 379 376 #define ARCTIS_1_BATTERY_RESPONSE_LEN 8 377 + #define ARCTIS_9_BATTERY_RESPONSE_LEN 64 380 378 static const char arctis_1_battery_request[] = { 0x06, 0x12 }; 379 + static const char arctis_9_battery_request[] = { 0x00, 0x20 }; 381 380 382 - static int steelseries_headset_arctis_1_fetch_battery(struct hid_device *hdev) 381 + static int steelseries_headset_request_battery(struct hid_device *hdev, 382 + const char *request, size_t len) 383 383 { 384 384 u8 *write_buf; 385 385 int ret; 386 386 387 387 /* Request battery information */ 388 - write_buf = kmemdup(arctis_1_battery_request, sizeof(arctis_1_battery_request), GFP_KERNEL); 388 + write_buf = kmemdup(request, len, GFP_KERNEL); 389 389 if (!write_buf) 390 390 return -ENOMEM; 391 391 392 - ret = hid_hw_raw_request(hdev, arctis_1_battery_request[0], 393 - write_buf, sizeof(arctis_1_battery_request), 392 + hid_dbg(hdev, "Sending battery request report"); 393 + ret = hid_hw_raw_request(hdev, request[0], write_buf, len, 394 394 HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); 395 - if (ret < (int)sizeof(arctis_1_battery_request)) { 395 + if (ret < (int)len) { 396 396 hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret); 397 397 ret = -ENODATA; 398 398 } 399 + 399 400 kfree(write_buf); 400 401 return ret; 401 402 } ··· 409 404 int ret = 0; 410 405 411 406 if (sd->quirks & STEELSERIES_ARCTIS_1) 412 - ret = steelseries_headset_arctis_1_fetch_battery(hdev); 407 + ret = steelseries_headset_request_battery(hdev, 408 + arctis_1_battery_request, sizeof(arctis_1_battery_request)); 409 + else if (sd->quirks & STEELSERIES_ARCTIS_9) 410 + ret = steelseries_headset_request_battery(hdev, 411 + arctis_9_battery_request, sizeof(arctis_9_battery_request)); 413 412 414 413 if (ret < 0) 415 414 hid_dbg(hdev, ··· 438 429 steelseries_headset_fetch_battery(hdev); 439 430 } 440 431 432 + #define STEELSERIES_PREFIX "SteelSeries " 433 + #define STEELSERIES_PREFIX_LEN strlen(STEELSERIES_PREFIX) 434 + 441 435 static int steelseries_headset_battery_get_property(struct power_supply *psy, 442 436 enum power_supply_property psp, 443 437 union power_supply_propval *val) ··· 449 437 int ret = 0; 450 438 451 439 switch (psp) { 440 + case POWER_SUPPLY_PROP_MODEL_NAME: 441 + val->strval = sd->hdev->name; 442 + while (!strncmp(val->strval, STEELSERIES_PREFIX, STEELSERIES_PREFIX_LEN)) 443 + val->strval += STEELSERIES_PREFIX_LEN; 444 + break; 445 + case POWER_SUPPLY_PROP_MANUFACTURER: 446 + val->strval = "SteelSeries"; 447 + break; 452 448 case POWER_SUPPLY_PROP_PRESENT: 453 449 val->intval = 1; 454 450 break; 455 451 case POWER_SUPPLY_PROP_STATUS: 456 - val->intval = sd->headset_connected ? 457 - POWER_SUPPLY_STATUS_DISCHARGING : 458 - POWER_SUPPLY_STATUS_UNKNOWN; 452 + if (sd->headset_connected) { 453 + val->intval = sd->battery_charging ? 454 + POWER_SUPPLY_STATUS_CHARGING : 455 + POWER_SUPPLY_STATUS_DISCHARGING; 456 + } else 457 + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; 459 458 break; 460 459 case POWER_SUPPLY_PROP_SCOPE: 461 460 val->intval = POWER_SUPPLY_SCOPE_DEVICE; ··· 500 477 } 501 478 502 479 static enum power_supply_property steelseries_headset_battery_props[] = { 480 + POWER_SUPPLY_PROP_MODEL_NAME, 481 + POWER_SUPPLY_PROP_MANUFACTURER, 503 482 POWER_SUPPLY_PROP_PRESENT, 504 483 POWER_SUPPLY_PROP_STATUS, 505 484 POWER_SUPPLY_PROP_SCOPE, ··· 530 505 /* avoid the warning of 0% battery while waiting for the first info */ 531 506 steelseries_headset_set_wireless_status(sd->hdev, false); 532 507 sd->battery_capacity = 100; 508 + sd->battery_charging = false; 533 509 534 510 sd->battery = devm_power_supply_register(&sd->hdev->dev, 535 511 &sd->battery_desc, &battery_cfg); ··· 546 520 INIT_DELAYED_WORK(&sd->battery_work, steelseries_headset_battery_timer_tick); 547 521 steelseries_headset_fetch_battery(sd->hdev); 548 522 523 + if (sd->quirks & STEELSERIES_ARCTIS_9) { 524 + /* The first fetch_battery request can remain unanswered in some cases */ 525 + schedule_delayed_work(&sd->battery_work, 526 + msecs_to_jiffies(STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS)); 527 + } 528 + 549 529 return 0; 530 + } 531 + 532 + static bool steelseries_is_vendor_usage_page(struct hid_device *hdev, uint8_t usage_page) 533 + { 534 + return hdev->rdesc[0] == 0x06 && 535 + hdev->rdesc[1] == usage_page && 536 + hdev->rdesc[2] == 0xff; 550 537 } 551 538 552 539 static int steelseries_probe(struct hid_device *hdev, const struct hid_device_id *id) ··· 587 548 if (ret) 588 549 return ret; 589 550 551 + if (sd->quirks & STEELSERIES_ARCTIS_9 && 552 + !steelseries_is_vendor_usage_page(hdev, 0xc0)) 553 + return -ENODEV; 554 + 590 555 spin_lock_init(&sd->lock); 591 556 592 557 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 558 + if (ret) 559 + return ret; 560 + 561 + ret = hid_hw_open(hdev); 593 562 if (ret) 594 563 return ret; 595 564 ··· 627 580 628 581 cancel_delayed_work_sync(&sd->battery_work); 629 582 583 + hid_hw_close(hdev); 630 584 hid_hw_stop(hdev); 631 585 } 632 586 ··· 647 599 return rdesc; 648 600 } 649 601 602 + static uint8_t steelseries_headset_map_capacity(uint8_t capacity, uint8_t min_in, uint8_t max_in) 603 + { 604 + if (capacity >= max_in) 605 + return 100; 606 + if (capacity <= min_in) 607 + return 0; 608 + return (capacity - min_in) * 100 / (max_in - min_in); 609 + } 610 + 650 611 static int steelseries_headset_raw_event(struct hid_device *hdev, 651 612 struct hid_report *report, u8 *read_buf, 652 613 int size) ··· 663 606 struct steelseries_device *sd = hid_get_drvdata(hdev); 664 607 int capacity = sd->battery_capacity; 665 608 bool connected = sd->headset_connected; 609 + bool charging = sd->battery_charging; 666 610 unsigned long flags; 667 611 668 612 /* Not a headset */ ··· 688 630 } 689 631 } 690 632 633 + if (sd->quirks & STEELSERIES_ARCTIS_9) { 634 + hid_dbg(sd->hdev, 635 + "Parsing raw event for Arctis 9 headset (%*ph)\n", size, read_buf); 636 + if (size < ARCTIS_9_BATTERY_RESPONSE_LEN) { 637 + if (!delayed_work_pending(&sd->battery_work)) 638 + goto request_battery; 639 + return 0; 640 + } 641 + 642 + if (read_buf[0] == 0xaa && read_buf[1] == 0x01) { 643 + connected = true; 644 + charging = read_buf[4] == 0x01; 645 + 646 + /* 647 + * Found no official documentation about min and max. 648 + * Values defined by testing. 649 + */ 650 + capacity = steelseries_headset_map_capacity(read_buf[3], 0x68, 0x9d); 651 + } else { 652 + /* 653 + * Device is off and sends the last known status read_buf[1] == 0x03 or 654 + * there is no known status of the device read_buf[0] == 0x55 655 + */ 656 + connected = false; 657 + charging = false; 658 + } 659 + } 660 + 691 661 if (connected != sd->headset_connected) { 692 662 hid_dbg(sd->hdev, 693 663 "Connected status changed from %sconnected to %sconnected\n", ··· 730 644 "Battery capacity changed from %d%% to %d%%\n", 731 645 sd->battery_capacity, capacity); 732 646 sd->battery_capacity = capacity; 647 + power_supply_changed(sd->battery); 648 + } 649 + 650 + if (charging != sd->battery_charging) { 651 + hid_dbg(sd->hdev, 652 + "Battery charging status changed from %scharging to %scharging\n", 653 + sd->battery_charging ? "" : "not ", 654 + charging ? "" : "not "); 655 + sd->battery_charging = charging; 733 656 power_supply_changed(sd->battery); 734 657 } 735 658 ··· 760 665 HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, 0x12b6), 761 666 .driver_data = STEELSERIES_ARCTIS_1 }, 762 667 668 + { /* SteelSeries Arctis 9 Wireless for XBox */ 669 + HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, 0x12c2), 670 + .driver_data = STEELSERIES_ARCTIS_9 }, 671 + 763 672 { } 764 673 }; 765 674 MODULE_DEVICE_TABLE(hid, steelseries_devices); ··· 782 683 MODULE_LICENSE("GPL"); 783 684 MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>"); 784 685 MODULE_AUTHOR("Simon Wood <simon@mungewell.org>"); 686 + MODULE_AUTHOR("Christian Mayer <git@mayer-bgk.de>");
+8
drivers/hid/hid-thrustmaster.c
··· 170 170 ep = &usbif->cur_altsetting->endpoint[1]; 171 171 b_ep = ep->desc.bEndpointAddress; 172 172 173 + /* Are the expected endpoints present? */ 174 + u8 ep_addr[1] = {b_ep}; 175 + 176 + if (!usb_check_int_endpoints(usbif, ep_addr)) { 177 + hid_err(hdev, "Unexpected non-int endpoint\n"); 178 + return; 179 + } 180 + 173 181 for (i = 0; i < ARRAY_SIZE(setup_arr); ++i) { 174 182 memcpy(send_buf, setup_arr[i], setup_arr_sizes[i]); 175 183
+1 -1
drivers/hid/hid-uclogic-params.c
··· 842 842 __u8 *params_ptr = NULL; 843 843 size_t params_len = 0; 844 844 /* Parameters string descriptor of a model with touch ring (HS610) */ 845 - const __u8 touch_ring_model_params_buf[] = { 845 + static const __u8 touch_ring_model_params_buf[] = { 846 846 0x13, 0x03, 0x70, 0xC6, 0x00, 0x06, 0x7C, 0x00, 847 847 0xFF, 0x1F, 0xD8, 0x13, 0x03, 0x0D, 0x10, 0x01, 848 848 0x04, 0x3C, 0x3E
+11 -1
drivers/hid/i2c-hid/i2c-hid-core.c
··· 51 51 #define I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET BIT(4) 52 52 #define I2C_HID_QUIRK_NO_SLEEP_ON_SUSPEND BIT(5) 53 53 #define I2C_HID_QUIRK_DELAY_WAKEUP_AFTER_RESUME BIT(6) 54 + #define I2C_HID_QUIRK_RE_POWER_ON BIT(7) 54 55 55 56 /* Command opcodes */ 56 57 #define I2C_HID_OPCODE_RESET 0x01 ··· 136 135 I2C_HID_QUIRK_BAD_INPUT_SIZE }, 137 136 { I2C_VENDOR_ID_CIRQUE, I2C_PRODUCT_ID_CIRQUE_1063, 138 137 I2C_HID_QUIRK_NO_SLEEP_ON_SUSPEND }, 138 + /* 139 + * Without additional power on command, at least some QTEC devices send garbage 140 + */ 141 + { I2C_VENDOR_ID_QTEC, HID_ANY_ID, 142 + I2C_HID_QUIRK_RE_POWER_ON }, 139 143 /* 140 144 * Sending the wakeup after reset actually break ELAN touchscreen controller 141 145 */ ··· 1079 1073 return ret; 1080 1074 } 1081 1075 1082 - return 0; 1076 + /* At least some QTEC devices need this after initialization */ 1077 + if (ihid->quirks & I2C_HID_QUIRK_RE_POWER_ON) 1078 + ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON); 1079 + 1080 + return ret; 1083 1081 } 1084 1082 1085 1083 static int i2c_hid_core_probe_panel_follower(struct i2c_hid *ihid)
-21
drivers/hid/intel-ish-hid/ishtp/client-buffers.c
··· 252 252 EXPORT_SYMBOL(ishtp_cl_io_rb_recycle); 253 253 254 254 /** 255 - * ishtp_cl_tx_empty() -test whether client device tx buffer is empty 256 - * @cl: Pointer to client device instance 257 - * 258 - * Look client device tx buffer list, and check whether this list is empty 259 - * 260 - * Return: true if client tx buffer list is empty else false 261 - */ 262 - bool ishtp_cl_tx_empty(struct ishtp_cl *cl) 263 - { 264 - int tx_list_empty; 265 - unsigned long tx_flags; 266 - 267 - spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags); 268 - tx_list_empty = list_empty(&cl->tx_list.list); 269 - spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 270 - 271 - return !!tx_list_empty; 272 - } 273 - EXPORT_SYMBOL(ishtp_cl_tx_empty); 274 - 275 - /** 276 255 * ishtp_cl_rx_get_rb() -Get a rb from client device rx buffer list 277 256 * @cl: Pointer to client device instance 278 257 *
-19
drivers/hid/intel-ish-hid/ishtp/client.c
··· 14 14 #include "hbm.h" 15 15 #include "client.h" 16 16 17 - int ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl) 18 - { 19 - unsigned long tx_free_flags; 20 - int size; 21 - 22 - spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); 23 - size = cl->tx_ring_free_size * cl->device->fw_client->props.max_msg_length; 24 - spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); 25 - 26 - return size; 27 - } 28 - EXPORT_SYMBOL(ishtp_cl_get_tx_free_buffer_size); 29 - 30 - int ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl) 31 - { 32 - return cl->tx_ring_free_size; 33 - } 34 - EXPORT_SYMBOL(ishtp_cl_get_tx_free_rings); 35 - 36 17 /** 37 18 * ishtp_read_list_flush() - Flush read queue 38 19 * @cl: ishtp client instance
-2
drivers/hid/intel-ish-hid/ishtp/client.h
··· 120 120 int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl); 121 121 void ishtp_cl_free_rx_ring(struct ishtp_cl *cl); 122 122 void ishtp_cl_free_tx_ring(struct ishtp_cl *cl); 123 - int ishtp_cl_get_tx_free_buffer_size(struct ishtp_cl *cl); 124 - int ishtp_cl_get_tx_free_rings(struct ishtp_cl *cl); 125 123 126 124 /* DMA I/F functions */ 127 125 void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg,
-30
drivers/hid/intel-ish-hid/ishtp/init.c
··· 15 15 #include "loader.h" 16 16 17 17 /** 18 - * ishtp_dev_state_str() -Convert to string format 19 - * @state: state to convert 20 - * 21 - * Convert state to string for prints 22 - * 23 - * Return: character pointer to converted string 24 - */ 25 - const char *ishtp_dev_state_str(int state) 26 - { 27 - switch (state) { 28 - case ISHTP_DEV_INITIALIZING: 29 - return "INITIALIZING"; 30 - case ISHTP_DEV_INIT_CLIENTS: 31 - return "INIT_CLIENTS"; 32 - case ISHTP_DEV_ENABLED: 33 - return "ENABLED"; 34 - case ISHTP_DEV_RESETTING: 35 - return "RESETTING"; 36 - case ISHTP_DEV_DISABLED: 37 - return "DISABLED"; 38 - case ISHTP_DEV_POWER_DOWN: 39 - return "POWER_DOWN"; 40 - case ISHTP_DEV_POWER_UP: 41 - return "POWER_UP"; 42 - default: 43 - return "unknown"; 44 - } 45 - } 46 - 47 - /** 48 18 * ishtp_device_init() - ishtp device init 49 19 * @dev: ISHTP device instance 50 20 *
-1
drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
··· 57 57 ISHTP_DEV_POWER_DOWN, 58 58 ISHTP_DEV_POWER_UP 59 59 }; 60 - const char *ishtp_dev_state_str(int state); 61 60 62 61 struct ishtp_cl; 63 62
+43
drivers/hid/intel-thc-hid/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Copyright (c) 2024, Intel Corporation. 3 + 4 + menu "Intel THC HID Support" 5 + depends on X86_64 && PCI 6 + 7 + config INTEL_THC_HID 8 + tristate "Intel Touch Host Controller" 9 + depends on ACPI 10 + select HID 11 + help 12 + THC (Touch Host Controller) is the name of the IP block in PCH that 13 + interfaces with Touch Devices (ex: touchscreen, touchpad etc.). It 14 + is comprised of 3 key functional blocks: A natively half-duplex 15 + Quad I/O capable SPI master; a low latency I2C interface to support 16 + HIDI2C compliant devices; a hardware sequencer with Read/Write DMA 17 + capability to system memory. 18 + 19 + Say Y/M here if you want to support Intel THC. If unsure, say N. 20 + 21 + config INTEL_QUICKSPI 22 + tristate "Intel QuickSPI driver based on Intel Touch Host Controller" 23 + depends on INTEL_THC_HID 24 + help 25 + Intel QuickSPI, based on Touch Host Controller (THC), implements 26 + HIDSPI (HID over SPI) protocol. It configures THC to work at SPI 27 + mode, and controls THC hardware sequencer to accelerate HIDSPI 28 + transaction flow. 29 + 30 + Say Y/M here if you want to support Intel QuickSPI. If unsure, say N. 31 + 32 + config INTEL_QUICKI2C 33 + tristate "Intel QuickI2C driver based on Intel Touch Host Controller" 34 + depends on INTEL_THC_HID 35 + help 36 + Intel QuickI2C, uses Touch Host Controller (THC) hardware, implements 37 + HIDI2C (HID over I2C) protocol. It configures THC to work in I2C 38 + mode, and controls THC hardware sequencer to accelerate HIDI2C 39 + transaction flow. 40 + 41 + Say Y/M here if you want to support Intel QuickI2C. If unsure, say N. 42 + 43 + endmenu
+22
drivers/hid/intel-thc-hid/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # Makefile - Intel Touch Host Controller (THC) drivers 4 + # Copyright (c) 2024, Intel Corporation. 5 + # 6 + # 7 + 8 + obj-$(CONFIG_INTEL_THC_HID) += intel-thc.o 9 + intel-thc-objs += intel-thc/intel-thc-dev.o 10 + intel-thc-objs += intel-thc/intel-thc-dma.o 11 + 12 + obj-$(CONFIG_INTEL_QUICKSPI) += intel-quickspi.o 13 + intel-quickspi-objs += intel-quickspi/pci-quickspi.o 14 + intel-quickspi-objs += intel-quickspi/quickspi-hid.o 15 + intel-quickspi-objs += intel-quickspi/quickspi-protocol.o 16 + 17 + obj-$(CONFIG_INTEL_QUICKI2C) += intel-quicki2c.o 18 + intel-quicki2c-objs += intel-quicki2c/pci-quicki2c.o 19 + intel-quicki2c-objs += intel-quicki2c/quicki2c-hid.o 20 + intel-quicki2c-objs += intel-quicki2c/quicki2c-protocol.o 21 + 22 + ccflags-y += -I $(src)/intel-thc
+969
drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #include <linux/acpi.h> 5 + #include <linux/device.h> 6 + #include <linux/dma-mapping.h> 7 + #include <linux/err.h> 8 + #include <linux/interrupt.h> 9 + #include <linux/irqreturn.h> 10 + #include <linux/pci.h> 11 + #include <linux/sizes.h> 12 + #include <linux/pm_runtime.h> 13 + 14 + #include "intel-thc-dev.h" 15 + #include "intel-thc-hw.h" 16 + 17 + #include "quicki2c-dev.h" 18 + #include "quicki2c-hid.h" 19 + #include "quicki2c-protocol.h" 20 + 21 + /* THC QuickI2C ACPI method to get device properties */ 22 + /* HIDI2C device method */ 23 + static guid_t i2c_hid_guid = 24 + GUID_INIT(0x3cdff6f7, 0x4267, 0x4555, 0xad, 0x05, 0xb3, 0x0a, 0x3d, 0x89, 0x38, 0xde); 25 + 26 + /* platform method */ 27 + static guid_t thc_platform_guid = 28 + GUID_INIT(0x84005682, 0x5b71, 0x41a4, 0x8d, 0x66, 0x81, 0x30, 0xf7, 0x87, 0xa1, 0x38); 29 + 30 + /** 31 + * quicki2c_acpi_get_dsm_property - Query device ACPI DSM parameter 32 + * 33 + * @adev: point to ACPI device 34 + * @guid: ACPI method's guid 35 + * @rev: ACPI method's revision 36 + * @func: ACPI method's function number 37 + * @type: ACPI parameter's data type 38 + * @prop_buf: point to return buffer 39 + * 40 + * This is a helper function for device to query its ACPI DSM parameters. 41 + * 42 + * Return: 0 if success or ENODEV on failed. 43 + */ 44 + static int quicki2c_acpi_get_dsm_property(struct acpi_device *adev, const guid_t *guid, 45 + u64 rev, u64 func, acpi_object_type type, void *prop_buf) 46 + { 47 + acpi_handle handle = acpi_device_handle(adev); 48 + union acpi_object *obj; 49 + 50 + obj = acpi_evaluate_dsm_typed(handle, guid, rev, func, NULL, type); 51 + if (!obj) { 52 + acpi_handle_err(handle, 53 + "Error _DSM call failed, rev: %d, func: %d, type: %d\n", 54 + (int)rev, (int)func, (int)type); 55 + return -ENODEV; 56 + } 57 + 58 + if (type == ACPI_TYPE_INTEGER) 59 + *(u32 *)prop_buf = (u32)obj->integer.value; 60 + else if (type == ACPI_TYPE_BUFFER) 61 + memcpy(prop_buf, obj->buffer.pointer, obj->buffer.length); 62 + 63 + ACPI_FREE(obj); 64 + 65 + return 0; 66 + } 67 + 68 + /** 69 + * quicki2c_acpi_get_dsd_property - Query device ACPI DSD parameter 70 + * 71 + * @adev: point to ACPI device 72 + * @dsd_method_name: ACPI method's property name 73 + * @type: ACPI parameter's data type 74 + * @prop_buf: point to return buffer 75 + * 76 + * This is a helper function for device to query its ACPI DSD parameters. 77 + * 78 + * Return: 0 if success or ENODEV on failed. 79 + */ 80 + static int quicki2c_acpi_get_dsd_property(struct acpi_device *adev, acpi_string dsd_method_name, 81 + acpi_object_type type, void *prop_buf) 82 + { 83 + acpi_handle handle = acpi_device_handle(adev); 84 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 85 + union acpi_object obj = { .type = type }; 86 + struct acpi_object_list arg_list = { 87 + .count = 1, 88 + .pointer = &obj, 89 + }; 90 + union acpi_object *ret_obj; 91 + acpi_status status; 92 + 93 + status = acpi_evaluate_object(handle, dsd_method_name, &arg_list, &buffer); 94 + if (ACPI_FAILURE(status)) { 95 + acpi_handle_err(handle, 96 + "Can't evaluate %s method: %d\n", dsd_method_name, status); 97 + return -ENODEV; 98 + } 99 + 100 + ret_obj = buffer.pointer; 101 + 102 + memcpy(prop_buf, ret_obj->buffer.pointer, ret_obj->buffer.length); 103 + 104 + return 0; 105 + } 106 + 107 + /** 108 + * quicki2c_get_acpi_resources - Query all quicki2c devices' ACPI parameters 109 + * 110 + * @qcdev: point to quicki2c device 111 + * 112 + * This function gets all quicki2c devices' ACPI resource. 113 + * 114 + * Return: 0 if success or error code on failed. 115 + */ 116 + static int quicki2c_get_acpi_resources(struct quicki2c_device *qcdev) 117 + { 118 + struct acpi_device *adev = ACPI_COMPANION(qcdev->dev); 119 + struct quicki2c_subip_acpi_parameter i2c_param; 120 + struct quicki2c_subip_acpi_config i2c_config; 121 + u32 hid_desc_addr; 122 + int ret = -EINVAL; 123 + 124 + if (!adev) { 125 + dev_err(qcdev->dev, "Invalid acpi device pointer\n"); 126 + return ret; 127 + } 128 + 129 + qcdev->acpi_dev = adev; 130 + 131 + ret = quicki2c_acpi_get_dsm_property(adev, &i2c_hid_guid, 132 + QUICKI2C_ACPI_REVISION_NUM, 133 + QUICKI2C_ACPI_FUNC_NUM_HID_DESC_ADDR, 134 + ACPI_TYPE_INTEGER, 135 + &hid_desc_addr); 136 + if (ret) 137 + return ret; 138 + 139 + qcdev->hid_desc_addr = (u16)hid_desc_addr; 140 + 141 + ret = quicki2c_acpi_get_dsm_property(adev, &thc_platform_guid, 142 + QUICKI2C_ACPI_REVISION_NUM, 143 + QUICKI2C_ACPI_FUNC_NUM_ACTIVE_LTR_VAL, 144 + ACPI_TYPE_INTEGER, 145 + &qcdev->active_ltr_val); 146 + if (ret) 147 + return ret; 148 + 149 + ret = quicki2c_acpi_get_dsm_property(adev, &thc_platform_guid, 150 + QUICKI2C_ACPI_REVISION_NUM, 151 + QUICKI2C_ACPI_FUNC_NUM_LP_LTR_VAL, 152 + ACPI_TYPE_INTEGER, 153 + &qcdev->low_power_ltr_val); 154 + if (ret) 155 + return ret; 156 + 157 + ret = quicki2c_acpi_get_dsd_property(adev, QUICKI2C_ACPI_METHOD_NAME_ICRS, 158 + ACPI_TYPE_BUFFER, &i2c_param); 159 + if (ret) 160 + return ret; 161 + 162 + if (i2c_param.addressing_mode != HIDI2C_ADDRESSING_MODE_7BIT) 163 + return -EOPNOTSUPP; 164 + 165 + qcdev->i2c_slave_addr = i2c_param.device_address; 166 + 167 + ret = quicki2c_acpi_get_dsd_property(adev, QUICKI2C_ACPI_METHOD_NAME_ISUB, 168 + ACPI_TYPE_BUFFER, &i2c_config); 169 + if (ret) 170 + return ret; 171 + 172 + if (i2c_param.connection_speed > 0 && 173 + i2c_param.connection_speed <= QUICKI2C_SUBIP_STANDARD_MODE_MAX_SPEED) { 174 + qcdev->i2c_speed_mode = THC_I2C_STANDARD; 175 + qcdev->i2c_clock_hcnt = i2c_config.SMHX; 176 + qcdev->i2c_clock_lcnt = i2c_config.SMLX; 177 + } else if (i2c_param.connection_speed > QUICKI2C_SUBIP_STANDARD_MODE_MAX_SPEED && 178 + i2c_param.connection_speed <= QUICKI2C_SUBIP_FAST_MODE_MAX_SPEED) { 179 + qcdev->i2c_speed_mode = THC_I2C_FAST_AND_PLUS; 180 + qcdev->i2c_clock_hcnt = i2c_config.FMHX; 181 + qcdev->i2c_clock_lcnt = i2c_config.FMLX; 182 + } else if (i2c_param.connection_speed > QUICKI2C_SUBIP_FAST_MODE_MAX_SPEED && 183 + i2c_param.connection_speed <= QUICKI2C_SUBIP_FASTPLUS_MODE_MAX_SPEED) { 184 + qcdev->i2c_speed_mode = THC_I2C_FAST_AND_PLUS; 185 + qcdev->i2c_clock_hcnt = i2c_config.FPHX; 186 + qcdev->i2c_clock_lcnt = i2c_config.FPLX; 187 + } else if (i2c_param.connection_speed > QUICKI2C_SUBIP_FASTPLUS_MODE_MAX_SPEED && 188 + i2c_param.connection_speed <= QUICKI2C_SUBIP_HIGH_SPEED_MODE_MAX_SPEED) { 189 + qcdev->i2c_speed_mode = THC_I2C_HIGH_SPEED; 190 + qcdev->i2c_clock_hcnt = i2c_config.HMHX; 191 + qcdev->i2c_clock_lcnt = i2c_config.HMLX; 192 + } else { 193 + return -EOPNOTSUPP; 194 + } 195 + 196 + return 0; 197 + } 198 + 199 + /** 200 + * quicki2c_irq_quick_handler - The ISR of the quicki2c driver 201 + * 202 + * @irq: The irq number 203 + * @dev_id: pointer to the device structure 204 + * 205 + * Return: IRQ_WAKE_THREAD if further process needed. 206 + */ 207 + static irqreturn_t quicki2c_irq_quick_handler(int irq, void *dev_id) 208 + { 209 + struct quicki2c_device *qcdev = dev_id; 210 + 211 + if (qcdev->state == QUICKI2C_DISABLED) 212 + return IRQ_HANDLED; 213 + 214 + /* Disable THC interrupt before current interrupt be handled */ 215 + thc_interrupt_enable(qcdev->thc_hw, false); 216 + 217 + return IRQ_WAKE_THREAD; 218 + } 219 + 220 + /** 221 + * try_recover - Try to recovery THC and Device 222 + * @qcdev: pointer to quicki2c device 223 + * 224 + * This function is a error handler, called when fatal error happens. 225 + * It try to reset Touch Device and re-configure THC to recovery 226 + * transferring between Device and THC. 227 + * 228 + * Return: 0 if successful or error code on failed 229 + */ 230 + static int try_recover(struct quicki2c_device *qcdev) 231 + { 232 + int ret; 233 + 234 + thc_dma_unconfigure(qcdev->thc_hw); 235 + 236 + ret = thc_dma_configure(qcdev->thc_hw); 237 + if (ret) { 238 + dev_err(qcdev->dev, "Reconfig DMA failed\n"); 239 + return ret; 240 + } 241 + 242 + return 0; 243 + } 244 + 245 + static int handle_input_report(struct quicki2c_device *qcdev) 246 + { 247 + struct hidi2c_report_packet *pkt = (struct hidi2c_report_packet *)qcdev->input_buf; 248 + int rx_dma_finished = 0; 249 + size_t report_len; 250 + int ret; 251 + 252 + while (!rx_dma_finished) { 253 + ret = thc_rxdma_read(qcdev->thc_hw, THC_RXDMA2, 254 + (u8 *)pkt, &report_len, 255 + &rx_dma_finished); 256 + if (ret) 257 + return ret; 258 + 259 + if (!pkt->len) { 260 + if (qcdev->state == QUICKI2C_RESETING) { 261 + qcdev->reset_ack = true; 262 + wake_up(&qcdev->reset_ack_wq); 263 + 264 + qcdev->state = QUICKI2C_RESETED; 265 + } else { 266 + dev_warn(qcdev->dev, "unexpected DIR happen\n"); 267 + } 268 + 269 + continue; 270 + } 271 + 272 + /* discard samples before driver probe complete */ 273 + if (qcdev->state != QUICKI2C_ENABLED) 274 + continue; 275 + 276 + quicki2c_hid_send_report(qcdev, pkt->data, 277 + HIDI2C_DATA_LEN(le16_to_cpu(pkt->len))); 278 + } 279 + 280 + return 0; 281 + } 282 + 283 + /** 284 + * quicki2c_irq_thread_handler - IRQ thread handler of quicki2c driver 285 + * 286 + * @irq: The IRQ number 287 + * @dev_id: pointer to the quicki2c device structure 288 + * 289 + * Return: IRQ_HANDLED to finish this handler. 290 + */ 291 + static irqreturn_t quicki2c_irq_thread_handler(int irq, void *dev_id) 292 + { 293 + struct quicki2c_device *qcdev = dev_id; 294 + int err_recover = 0; 295 + int int_mask; 296 + int ret; 297 + 298 + if (qcdev->state == QUICKI2C_DISABLED) 299 + return IRQ_HANDLED; 300 + 301 + ret = pm_runtime_resume_and_get(qcdev->dev); 302 + if (ret) 303 + return IRQ_HANDLED; 304 + 305 + int_mask = thc_interrupt_handler(qcdev->thc_hw); 306 + 307 + if (int_mask & BIT(THC_FATAL_ERR_INT) || int_mask & BIT(THC_TXN_ERR_INT) || 308 + int_mask & BIT(THC_UNKNOWN_INT)) { 309 + err_recover = 1; 310 + goto exit; 311 + } 312 + 313 + if (int_mask & BIT(THC_RXDMA2_INT)) { 314 + err_recover = handle_input_report(qcdev); 315 + if (err_recover) 316 + goto exit; 317 + } 318 + 319 + exit: 320 + thc_interrupt_enable(qcdev->thc_hw, true); 321 + 322 + if (err_recover) 323 + if (try_recover(qcdev)) 324 + qcdev->state = QUICKI2C_DISABLED; 325 + 326 + pm_runtime_mark_last_busy(qcdev->dev); 327 + pm_runtime_put_autosuspend(qcdev->dev); 328 + 329 + return IRQ_HANDLED; 330 + } 331 + 332 + /** 333 + * quicki2c_dev_init - Initialize quicki2c device 334 + * 335 + * @pdev: pointer to the thc pci device 336 + * @mem_addr: The pointer of MMIO memory address 337 + * 338 + * Alloc quicki2c device structure and initialized THC device, 339 + * then configure THC to HIDI2C mode. 340 + * 341 + * If success, enable THC hardware interrupt. 342 + * 343 + * Return: pointer to the quicki2c device structure if success 344 + * or NULL on failed. 345 + */ 346 + static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __iomem *mem_addr) 347 + { 348 + struct device *dev = &pdev->dev; 349 + struct quicki2c_device *qcdev; 350 + int ret; 351 + 352 + qcdev = devm_kzalloc(dev, sizeof(struct quicki2c_device), GFP_KERNEL); 353 + if (!qcdev) 354 + return ERR_PTR(-ENOMEM); 355 + 356 + qcdev->pdev = pdev; 357 + qcdev->dev = dev; 358 + qcdev->mem_addr = mem_addr; 359 + qcdev->state = QUICKI2C_DISABLED; 360 + 361 + init_waitqueue_head(&qcdev->reset_ack_wq); 362 + 363 + /* thc hw init */ 364 + qcdev->thc_hw = thc_dev_init(qcdev->dev, qcdev->mem_addr); 365 + if (IS_ERR(qcdev->thc_hw)) { 366 + ret = PTR_ERR(qcdev->thc_hw); 367 + dev_err_once(dev, "Failed to initialize THC device context, ret = %d.\n", ret); 368 + return ERR_PTR(ret); 369 + } 370 + 371 + ret = quicki2c_get_acpi_resources(qcdev); 372 + if (ret) { 373 + dev_err_once(dev, "Get ACPI resources failed, ret = %d\n", ret); 374 + return ERR_PTR(ret); 375 + } 376 + 377 + ret = thc_interrupt_quiesce(qcdev->thc_hw, true); 378 + if (ret) 379 + return ERR_PTR(ret); 380 + 381 + ret = thc_port_select(qcdev->thc_hw, THC_PORT_TYPE_I2C); 382 + if (ret) { 383 + dev_err_once(dev, "Failed to select THC port, ret = %d.\n", ret); 384 + return ERR_PTR(ret); 385 + } 386 + 387 + ret = thc_i2c_subip_init(qcdev->thc_hw, qcdev->i2c_slave_addr, 388 + qcdev->i2c_speed_mode, 389 + qcdev->i2c_clock_hcnt, 390 + qcdev->i2c_clock_lcnt); 391 + if (ret) 392 + return ERR_PTR(ret); 393 + 394 + thc_int_trigger_type_select(qcdev->thc_hw, false); 395 + 396 + thc_interrupt_config(qcdev->thc_hw); 397 + 398 + thc_interrupt_enable(qcdev->thc_hw, true); 399 + 400 + qcdev->state = QUICKI2C_INITED; 401 + 402 + return qcdev; 403 + } 404 + 405 + /** 406 + * quicki2c_dev_deinit - De-initialize quicki2c device 407 + * 408 + * @qcdev: pointer to the quicki2c device structure 409 + * 410 + * Disable THC interrupt and deinitilize THC. 411 + */ 412 + static void quicki2c_dev_deinit(struct quicki2c_device *qcdev) 413 + { 414 + thc_interrupt_enable(qcdev->thc_hw, false); 415 + thc_ltr_unconfig(qcdev->thc_hw); 416 + 417 + qcdev->state = QUICKI2C_DISABLED; 418 + } 419 + 420 + /** 421 + * quicki2c_dma_init - Configure THC DMA for quicki2c device 422 + * @qcdev: pointer to the quicki2c device structure 423 + * 424 + * This function uses TIC's parameters(such as max input length, max output 425 + * length) to allocate THC DMA buffers and configure THC DMA engines. 426 + * 427 + * Return: 0 if success or error code on failed. 428 + */ 429 + static int quicki2c_dma_init(struct quicki2c_device *qcdev) 430 + { 431 + size_t swdma_max_len; 432 + int ret; 433 + 434 + swdma_max_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len), 435 + le16_to_cpu(qcdev->dev_desc.report_desc_len)); 436 + 437 + ret = thc_dma_set_max_packet_sizes(qcdev->thc_hw, 0, 438 + le16_to_cpu(qcdev->dev_desc.max_input_len), 439 + le16_to_cpu(qcdev->dev_desc.max_output_len), 440 + swdma_max_len); 441 + if (ret) 442 + return ret; 443 + 444 + ret = thc_dma_allocate(qcdev->thc_hw); 445 + if (ret) { 446 + dev_err(qcdev->dev, "Allocate THC DMA buffer failed, ret = %d\n", ret); 447 + return ret; 448 + } 449 + 450 + /* Enable RxDMA */ 451 + ret = thc_dma_configure(qcdev->thc_hw); 452 + if (ret) { 453 + dev_err(qcdev->dev, "Configure THC DMA failed, ret = %d\n", ret); 454 + thc_dma_unconfigure(qcdev->thc_hw); 455 + thc_dma_release(qcdev->thc_hw); 456 + return ret; 457 + } 458 + 459 + return ret; 460 + } 461 + 462 + /** 463 + * quicki2c_dma_deinit - Release THC DMA for quicki2c device 464 + * @qcdev: pointer to the quicki2c device structure 465 + * 466 + * Stop THC DMA engines and release all DMA buffers. 467 + * 468 + */ 469 + static void quicki2c_dma_deinit(struct quicki2c_device *qcdev) 470 + { 471 + thc_dma_unconfigure(qcdev->thc_hw); 472 + thc_dma_release(qcdev->thc_hw); 473 + } 474 + 475 + /** 476 + * quicki2c_alloc_report_buf - Alloc report buffers 477 + * @qcdev: pointer to the quicki2c device structure 478 + * 479 + * Allocate report descriptor buffer, it will be used for restore TIC HID 480 + * report descriptor. 481 + * 482 + * Allocate input report buffer, it will be used for receive HID input report 483 + * data from TIC. 484 + * 485 + * Allocate output report buffer, it will be used for store HID output report, 486 + * such as set feature. 487 + * 488 + * Return: 0 if success or error code on failed. 489 + */ 490 + static int quicki2c_alloc_report_buf(struct quicki2c_device *qcdev) 491 + { 492 + size_t max_report_len; 493 + 494 + qcdev->report_descriptor = devm_kzalloc(qcdev->dev, 495 + le16_to_cpu(qcdev->dev_desc.report_desc_len), 496 + GFP_KERNEL); 497 + if (!qcdev->report_descriptor) 498 + return -ENOMEM; 499 + 500 + /* 501 + * Some HIDI2C devices don't declare input/output max length correctly, 502 + * give default 4K buffer to avoid DMA buffer overrun. 503 + */ 504 + max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_input_len), SZ_4K); 505 + 506 + qcdev->input_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL); 507 + if (!qcdev->input_buf) 508 + return -ENOMEM; 509 + 510 + if (!le16_to_cpu(qcdev->dev_desc.max_output_len)) 511 + qcdev->dev_desc.max_output_len = cpu_to_le16(SZ_4K); 512 + 513 + max_report_len = max(le16_to_cpu(qcdev->dev_desc.max_output_len), 514 + max_report_len); 515 + 516 + qcdev->report_buf = devm_kzalloc(qcdev->dev, max_report_len, GFP_KERNEL); 517 + if (!qcdev->report_buf) 518 + return -ENOMEM; 519 + 520 + qcdev->report_len = max_report_len; 521 + 522 + return 0; 523 + } 524 + 525 + /* 526 + * quicki2c_probe: Quicki2c driver probe function 527 + * 528 + * @pdev: point to pci device 529 + * @id: point to pci_device_id structure 530 + * 531 + * This function initializes THC and HIDI2C device, the flow is: 532 + * - do THC pci device initialization 533 + * - query HIDI2C ACPI parameters 534 + * - configure THC to HIDI2C mode 535 + * - go through HIDI2C enumeration flow 536 + * |- read device descriptor 537 + * |- reset HIDI2C device 538 + * - enable THC interrupt and DMA 539 + * - read report descriptor 540 + * - register HID device 541 + * - enable runtime power management 542 + * 543 + * Return 0 if success or error code on failed. 544 + */ 545 + static int quicki2c_probe(struct pci_dev *pdev, 546 + const struct pci_device_id *id) 547 + { 548 + struct quicki2c_device *qcdev; 549 + void __iomem *mem_addr; 550 + int ret; 551 + 552 + ret = pcim_enable_device(pdev); 553 + if (ret) { 554 + dev_err_once(&pdev->dev, "Failed to enable PCI device, ret = %d.\n", ret); 555 + return ret; 556 + } 557 + 558 + pci_set_master(pdev); 559 + 560 + ret = pcim_iomap_regions(pdev, BIT(0), KBUILD_MODNAME); 561 + if (ret) { 562 + dev_err_once(&pdev->dev, "Failed to get PCI regions, ret = %d.\n", ret); 563 + goto disable_pci_device; 564 + } 565 + 566 + mem_addr = pcim_iomap_table(pdev)[0]; 567 + 568 + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 569 + if (ret) { 570 + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 571 + if (ret) { 572 + dev_err_once(&pdev->dev, "No usable DMA configuration %d\n", ret); 573 + goto unmap_io_region; 574 + } 575 + } 576 + 577 + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 578 + if (ret < 0) { 579 + dev_err_once(&pdev->dev, 580 + "Failed to allocate IRQ vectors. ret = %d\n", ret); 581 + goto unmap_io_region; 582 + } 583 + 584 + pdev->irq = pci_irq_vector(pdev, 0); 585 + 586 + qcdev = quicki2c_dev_init(pdev, mem_addr); 587 + if (IS_ERR(qcdev)) { 588 + dev_err_once(&pdev->dev, "QuickI2C device init failed\n"); 589 + ret = PTR_ERR(qcdev); 590 + goto unmap_io_region; 591 + } 592 + 593 + pci_set_drvdata(pdev, qcdev); 594 + 595 + ret = devm_request_threaded_irq(&pdev->dev, pdev->irq, 596 + quicki2c_irq_quick_handler, 597 + quicki2c_irq_thread_handler, 598 + IRQF_ONESHOT, KBUILD_MODNAME, 599 + qcdev); 600 + if (ret) { 601 + dev_err_once(&pdev->dev, 602 + "Failed to request threaded IRQ, irq = %d.\n", pdev->irq); 603 + goto dev_deinit; 604 + } 605 + 606 + ret = quicki2c_get_device_descriptor(qcdev); 607 + if (ret) { 608 + dev_err(&pdev->dev, "Get device descriptor failed, ret = %d\n", ret); 609 + goto dev_deinit; 610 + } 611 + 612 + ret = quicki2c_alloc_report_buf(qcdev); 613 + if (ret) { 614 + dev_err(&pdev->dev, "Alloc report buffers failed, ret= %d\n", ret); 615 + goto dev_deinit; 616 + } 617 + 618 + ret = quicki2c_dma_init(qcdev); 619 + if (ret) { 620 + dev_err(&pdev->dev, "Setup THC DMA failed, ret= %d\n", ret); 621 + goto dev_deinit; 622 + } 623 + 624 + ret = thc_interrupt_quiesce(qcdev->thc_hw, false); 625 + if (ret) 626 + goto dev_deinit; 627 + 628 + ret = quicki2c_set_power(qcdev, HIDI2C_ON); 629 + if (ret) { 630 + dev_err(&pdev->dev, "Set Power On command failed, ret= %d\n", ret); 631 + goto dev_deinit; 632 + } 633 + 634 + ret = quicki2c_reset(qcdev); 635 + if (ret) { 636 + dev_err(&pdev->dev, "Reset HIDI2C device failed, ret= %d\n", ret); 637 + goto dev_deinit; 638 + } 639 + 640 + ret = quicki2c_get_report_descriptor(qcdev); 641 + if (ret) { 642 + dev_err(&pdev->dev, "Get report descriptor failed, ret = %d\n", ret); 643 + goto dma_deinit; 644 + } 645 + 646 + ret = quicki2c_hid_probe(qcdev); 647 + if (ret) { 648 + dev_err(&pdev->dev, "Failed to register HID device, ret = %d\n", ret); 649 + goto dma_deinit; 650 + } 651 + 652 + qcdev->state = QUICKI2C_ENABLED; 653 + 654 + /* Enable runtime power management */ 655 + pm_runtime_use_autosuspend(qcdev->dev); 656 + pm_runtime_set_autosuspend_delay(qcdev->dev, DEFAULT_AUTO_SUSPEND_DELAY_MS); 657 + pm_runtime_mark_last_busy(qcdev->dev); 658 + pm_runtime_put_noidle(qcdev->dev); 659 + pm_runtime_put_autosuspend(qcdev->dev); 660 + 661 + dev_dbg(&pdev->dev, "QuickI2C probe success\n"); 662 + 663 + return 0; 664 + 665 + dma_deinit: 666 + quicki2c_dma_deinit(qcdev); 667 + dev_deinit: 668 + quicki2c_dev_deinit(qcdev); 669 + unmap_io_region: 670 + pcim_iounmap_regions(pdev, BIT(0)); 671 + disable_pci_device: 672 + pci_clear_master(pdev); 673 + 674 + return ret; 675 + } 676 + 677 + /** 678 + * quicki2c_remove - Device Removal Routine 679 + * 680 + * @pdev: PCI device structure 681 + * 682 + * This is called by the PCI subsystem to alert the driver 683 + * that it should release a PCI device. 684 + */ 685 + static void quicki2c_remove(struct pci_dev *pdev) 686 + { 687 + struct quicki2c_device *qcdev; 688 + 689 + qcdev = pci_get_drvdata(pdev); 690 + if (!qcdev) 691 + return; 692 + 693 + quicki2c_hid_remove(qcdev); 694 + quicki2c_dma_deinit(qcdev); 695 + 696 + pm_runtime_get_noresume(qcdev->dev); 697 + 698 + quicki2c_dev_deinit(qcdev); 699 + 700 + pcim_iounmap_regions(pdev, BIT(0)); 701 + pci_clear_master(pdev); 702 + } 703 + 704 + /** 705 + * quicki2c_shutdown - Device Shutdown Routine 706 + * 707 + * @pdev: PCI device structure 708 + * 709 + * This is called from the reboot notifier 710 + * it's a simplified version of remove so we go down 711 + * faster. 712 + */ 713 + static void quicki2c_shutdown(struct pci_dev *pdev) 714 + { 715 + struct quicki2c_device *qcdev; 716 + 717 + qcdev = pci_get_drvdata(pdev); 718 + if (!qcdev) 719 + return; 720 + 721 + /* Must stop DMA before reboot to avoid DMA entering into unknown state */ 722 + quicki2c_dma_deinit(qcdev); 723 + 724 + quicki2c_dev_deinit(qcdev); 725 + } 726 + 727 + static int quicki2c_suspend(struct device *device) 728 + { 729 + struct pci_dev *pdev = to_pci_dev(device); 730 + struct quicki2c_device *qcdev; 731 + int ret; 732 + 733 + qcdev = pci_get_drvdata(pdev); 734 + if (!qcdev) 735 + return -ENODEV; 736 + 737 + /* 738 + * As I2C is THC subsystem, no register auto save/restore support, 739 + * need driver to do that explicitly for every D3 case. 740 + */ 741 + ret = thc_i2c_subip_regs_save(qcdev->thc_hw); 742 + if (ret) 743 + return ret; 744 + 745 + ret = thc_interrupt_quiesce(qcdev->thc_hw, true); 746 + if (ret) 747 + return ret; 748 + 749 + thc_interrupt_enable(qcdev->thc_hw, false); 750 + 751 + thc_dma_unconfigure(qcdev->thc_hw); 752 + 753 + return 0; 754 + } 755 + 756 + static int quicki2c_resume(struct device *device) 757 + { 758 + struct pci_dev *pdev = to_pci_dev(device); 759 + struct quicki2c_device *qcdev; 760 + int ret; 761 + 762 + qcdev = pci_get_drvdata(pdev); 763 + if (!qcdev) 764 + return -ENODEV; 765 + 766 + ret = thc_port_select(qcdev->thc_hw, THC_PORT_TYPE_I2C); 767 + if (ret) 768 + return ret; 769 + 770 + ret = thc_i2c_subip_regs_restore(qcdev->thc_hw); 771 + if (ret) 772 + return ret; 773 + 774 + thc_interrupt_config(qcdev->thc_hw); 775 + 776 + thc_interrupt_enable(qcdev->thc_hw, true); 777 + 778 + ret = thc_dma_configure(qcdev->thc_hw); 779 + if (ret) 780 + return ret; 781 + 782 + ret = thc_interrupt_quiesce(qcdev->thc_hw, false); 783 + if (ret) 784 + return ret; 785 + 786 + return 0; 787 + } 788 + 789 + static int quicki2c_freeze(struct device *device) 790 + { 791 + struct pci_dev *pdev = to_pci_dev(device); 792 + struct quicki2c_device *qcdev; 793 + int ret; 794 + 795 + qcdev = pci_get_drvdata(pdev); 796 + if (!qcdev) 797 + return -ENODEV; 798 + 799 + ret = thc_interrupt_quiesce(qcdev->thc_hw, true); 800 + if (ret) 801 + return ret; 802 + 803 + thc_interrupt_enable(qcdev->thc_hw, false); 804 + 805 + thc_dma_unconfigure(qcdev->thc_hw); 806 + 807 + return 0; 808 + } 809 + 810 + static int quicki2c_thaw(struct device *device) 811 + { 812 + struct pci_dev *pdev = to_pci_dev(device); 813 + struct quicki2c_device *qcdev; 814 + int ret; 815 + 816 + qcdev = pci_get_drvdata(pdev); 817 + if (!qcdev) 818 + return -ENODEV; 819 + 820 + ret = thc_dma_configure(qcdev->thc_hw); 821 + if (ret) 822 + return ret; 823 + 824 + thc_interrupt_enable(qcdev->thc_hw, true); 825 + 826 + ret = thc_interrupt_quiesce(qcdev->thc_hw, false); 827 + if (ret) 828 + return ret; 829 + 830 + return 0; 831 + } 832 + 833 + static int quicki2c_poweroff(struct device *device) 834 + { 835 + struct pci_dev *pdev = to_pci_dev(device); 836 + struct quicki2c_device *qcdev; 837 + int ret; 838 + 839 + qcdev = pci_get_drvdata(pdev); 840 + if (!qcdev) 841 + return -ENODEV; 842 + 843 + ret = thc_interrupt_quiesce(qcdev->thc_hw, true); 844 + if (ret) 845 + return ret; 846 + 847 + thc_interrupt_enable(qcdev->thc_hw, false); 848 + 849 + thc_ltr_unconfig(qcdev->thc_hw); 850 + 851 + quicki2c_dma_deinit(qcdev); 852 + 853 + return 0; 854 + } 855 + 856 + static int quicki2c_restore(struct device *device) 857 + { 858 + struct pci_dev *pdev = to_pci_dev(device); 859 + struct quicki2c_device *qcdev; 860 + int ret; 861 + 862 + qcdev = pci_get_drvdata(pdev); 863 + if (!qcdev) 864 + return -ENODEV; 865 + 866 + /* Reconfig THC HW when back from hibernate */ 867 + ret = thc_port_select(qcdev->thc_hw, THC_PORT_TYPE_I2C); 868 + if (ret) 869 + return ret; 870 + 871 + ret = thc_i2c_subip_init(qcdev->thc_hw, qcdev->i2c_slave_addr, 872 + qcdev->i2c_speed_mode, 873 + qcdev->i2c_clock_hcnt, 874 + qcdev->i2c_clock_lcnt); 875 + if (ret) 876 + return ret; 877 + 878 + thc_interrupt_config(qcdev->thc_hw); 879 + 880 + thc_interrupt_enable(qcdev->thc_hw, true); 881 + 882 + ret = thc_interrupt_quiesce(qcdev->thc_hw, false); 883 + if (ret) 884 + return ret; 885 + 886 + ret = thc_dma_configure(qcdev->thc_hw); 887 + if (ret) 888 + return ret; 889 + 890 + thc_ltr_config(qcdev->thc_hw, 891 + qcdev->active_ltr_val, 892 + qcdev->low_power_ltr_val); 893 + 894 + thc_change_ltr_mode(qcdev->thc_hw, THC_LTR_MODE_ACTIVE); 895 + 896 + return 0; 897 + } 898 + 899 + static int quicki2c_runtime_suspend(struct device *device) 900 + { 901 + struct pci_dev *pdev = to_pci_dev(device); 902 + struct quicki2c_device *qcdev; 903 + 904 + qcdev = pci_get_drvdata(pdev); 905 + if (!qcdev) 906 + return -ENODEV; 907 + 908 + thc_change_ltr_mode(qcdev->thc_hw, THC_LTR_MODE_LP); 909 + 910 + pci_save_state(pdev); 911 + 912 + return 0; 913 + } 914 + 915 + static int quicki2c_runtime_resume(struct device *device) 916 + { 917 + struct pci_dev *pdev = to_pci_dev(device); 918 + struct quicki2c_device *qcdev; 919 + 920 + qcdev = pci_get_drvdata(pdev); 921 + if (!qcdev) 922 + return -ENODEV; 923 + 924 + thc_change_ltr_mode(qcdev->thc_hw, THC_LTR_MODE_ACTIVE); 925 + 926 + return 0; 927 + } 928 + 929 + static const struct dev_pm_ops quicki2c_pm_ops = { 930 + .suspend = quicki2c_suspend, 931 + .resume = quicki2c_resume, 932 + .freeze = quicki2c_freeze, 933 + .thaw = quicki2c_thaw, 934 + .poweroff = quicki2c_poweroff, 935 + .restore = quicki2c_restore, 936 + .runtime_suspend = quicki2c_runtime_suspend, 937 + .runtime_resume = quicki2c_runtime_resume, 938 + .runtime_idle = NULL, 939 + }; 940 + 941 + static const struct pci_device_id quicki2c_pci_tbl[] = { 942 + {PCI_VDEVICE(INTEL, THC_LNL_DEVICE_ID_I2C_PORT1), }, 943 + {PCI_VDEVICE(INTEL, THC_LNL_DEVICE_ID_I2C_PORT2), }, 944 + {PCI_VDEVICE(INTEL, THC_PTL_H_DEVICE_ID_I2C_PORT1), }, 945 + {PCI_VDEVICE(INTEL, THC_PTL_H_DEVICE_ID_I2C_PORT2), }, 946 + {PCI_VDEVICE(INTEL, THC_PTL_U_DEVICE_ID_I2C_PORT1), }, 947 + {PCI_VDEVICE(INTEL, THC_PTL_U_DEVICE_ID_I2C_PORT2), }, 948 + {} 949 + }; 950 + MODULE_DEVICE_TABLE(pci, quicki2c_pci_tbl); 951 + 952 + static struct pci_driver quicki2c_driver = { 953 + .name = KBUILD_MODNAME, 954 + .id_table = quicki2c_pci_tbl, 955 + .probe = quicki2c_probe, 956 + .remove = quicki2c_remove, 957 + .shutdown = quicki2c_shutdown, 958 + .driver.pm = &quicki2c_pm_ops, 959 + .driver.probe_type = PROBE_PREFER_ASYNCHRONOUS, 960 + }; 961 + 962 + module_pci_driver(quicki2c_driver); 963 + 964 + MODULE_AUTHOR("Xinpeng Sun <xinpeng.sun@intel.com>"); 965 + MODULE_AUTHOR("Even Xu <even.xu@intel.com>"); 966 + 967 + MODULE_DESCRIPTION("Intel(R) QuickI2C Driver"); 968 + MODULE_LICENSE("GPL"); 969 + MODULE_IMPORT_NS("INTEL_THC");
+186
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _QUICKI2C_DEV_H_ 5 + #define _QUICKI2C_DEV_H_ 6 + 7 + #include <linux/hid-over-i2c.h> 8 + #include <linux/workqueue.h> 9 + 10 + #define THC_LNL_DEVICE_ID_I2C_PORT1 0xA848 11 + #define THC_LNL_DEVICE_ID_I2C_PORT2 0xA84A 12 + #define THC_PTL_H_DEVICE_ID_I2C_PORT1 0xE348 13 + #define THC_PTL_H_DEVICE_ID_I2C_PORT2 0xE34A 14 + #define THC_PTL_U_DEVICE_ID_I2C_PORT1 0xE448 15 + #define THC_PTL_U_DEVICE_ID_I2C_PORT2 0xE44A 16 + 17 + /* Packet size value, the unit is 16 bytes */ 18 + #define MAX_PACKET_SIZE_VALUE_LNL 256 19 + 20 + /* HIDI2C special ACPI parameters DSD name */ 21 + #define QUICKI2C_ACPI_METHOD_NAME_ICRS "ICRS" 22 + #define QUICKI2C_ACPI_METHOD_NAME_ISUB "ISUB" 23 + 24 + /* HIDI2C special ACPI parameters DSM methods */ 25 + #define QUICKI2C_ACPI_REVISION_NUM 1 26 + #define QUICKI2C_ACPI_FUNC_NUM_HID_DESC_ADDR 1 27 + #define QUICKI2C_ACPI_FUNC_NUM_ACTIVE_LTR_VAL 1 28 + #define QUICKI2C_ACPI_FUNC_NUM_LP_LTR_VAL 2 29 + 30 + #define QUICKI2C_SUBIP_STANDARD_MODE_MAX_SPEED 100000 31 + #define QUICKI2C_SUBIP_FAST_MODE_MAX_SPEED 400000 32 + #define QUICKI2C_SUBIP_FASTPLUS_MODE_MAX_SPEED 1000000 33 + #define QUICKI2C_SUBIP_HIGH_SPEED_MODE_MAX_SPEED 3400000 34 + 35 + #define QUICKI2C_DEFAULT_ACTIVE_LTR_VALUE 5 36 + #define QUICKI2C_DEFAULT_LP_LTR_VALUE 500 37 + #define QUICKI2C_RPM_TIMEOUT_MS 500 38 + 39 + /* 40 + * THC uses runtime auto suspend to dynamically switch between THC active LTR 41 + * and low power LTR to save CPU power. 42 + * Default value is 5000ms, that means if no touch event in this time, THC will 43 + * change to low power LTR mode. 44 + */ 45 + #define DEFAULT_AUTO_SUSPEND_DELAY_MS 5000 46 + 47 + enum quicki2c_dev_state { 48 + QUICKI2C_NONE, 49 + QUICKI2C_RESETING, 50 + QUICKI2C_RESETED, 51 + QUICKI2C_INITED, 52 + QUICKI2C_ENABLED, 53 + QUICKI2C_DISABLED, 54 + }; 55 + 56 + enum { 57 + HIDI2C_ADDRESSING_MODE_7BIT, 58 + HIDI2C_ADDRESSING_MODE_10BIT, 59 + }; 60 + 61 + /** 62 + * struct quicki2c_subip_acpi_parameter - QuickI2C ACPI DSD parameters 63 + * @device_address: I2C device slave address 64 + * @connection_speed: I2C device expected connection speed 65 + * @addressing_mode: I2C device slave address mode, 7bit or 10bit 66 + * 67 + * Those properties get from QUICKI2C_ACPI_METHOD_NAME_ICRS method, used for 68 + * Bus parameter. 69 + */ 70 + struct quicki2c_subip_acpi_parameter { 71 + u16 device_address; 72 + u64 connection_speed; 73 + u8 addressing_mode; 74 + } __packed; 75 + 76 + /** 77 + * struct quicki2c_subip_acpi_config - QuickI2C ACPI DSD parameters 78 + * @SMHX: Standard Mode (100 kbit/s) Serial Clock Line HIGH Period 79 + * @SMLX: Standard Mode (100 kbit/s) Serial Clock Line LOW Period 80 + * @SMTD: Standard Mode (100 kbit/s) Serial Data Line Transmit Hold Period 81 + * @SMRD: Standard Mode (100 kbit/s) Serial Data Receive Hold Period 82 + * @FMHX: Fast Mode (400 kbit/s) Serial Clock Line HIGH Period 83 + * @FMLX: Fast Mode (400 kbit/s) Serial Clock Line LOW Period 84 + * @FMTD: Fast Mode (400 kbit/s) Serial Data Line Transmit Hold Period 85 + * @FMRD: Fast Mode (400 kbit/s) Serial Data Line Receive Hold Period 86 + * @FMSL: Maximum length (in ic_clk_cycles) of suppressed spikes 87 + * in Standard Mode, Fast Mode and Fast Mode Plus 88 + * @FPHX: Fast Mode Plus (1Mbit/sec) Serial Clock Line HIGH Period 89 + * @FPLX: Fast Mode Plus (1Mbit/sec) Serial Clock Line LOW Period 90 + * @FPTD: Fast Mode Plus (1Mbit/sec) Serial Data Line Transmit HOLD Period 91 + * @FPRD: Fast Mode Plus (1Mbit/sec) Serial Data Line Receive HOLD Period 92 + * @HMHX: High Speed Mode Plus (3.4Mbits/sec) Serial Clock Line HIGH Period 93 + * @HMLX: High Speed Mode Plus (3.4Mbits/sec) Serial Clock Line LOW Period 94 + * @HMTD: High Speed Mode Plus (3.4Mbits/sec) Serial Data Line Transmit HOLD Period 95 + * @HMRD: High Speed Mode Plus (3.4Mbits/sec) Serial Data Line Receive HOLD Period 96 + * @HMSL: Maximum length (in ic_clk_cycles) of suppressed spikes in High Speed Mode 97 + * 98 + * Those properties get from QUICKI2C_ACPI_METHOD_NAME_ISUB method, used for 99 + * I2C timing configure. 100 + */ 101 + struct quicki2c_subip_acpi_config { 102 + u64 SMHX; 103 + u64 SMLX; 104 + u64 SMTD; 105 + u64 SMRD; 106 + 107 + u64 FMHX; 108 + u64 FMLX; 109 + u64 FMTD; 110 + u64 FMRD; 111 + u64 FMSL; 112 + 113 + u64 FPHX; 114 + u64 FPLX; 115 + u64 FPTD; 116 + u64 FPRD; 117 + 118 + u64 HMHX; 119 + u64 HMLX; 120 + u64 HMTD; 121 + u64 HMRD; 122 + u64 HMSL; 123 + }; 124 + 125 + struct device; 126 + struct pci_dev; 127 + struct thc_device; 128 + struct hid_device; 129 + struct acpi_device; 130 + 131 + /** 132 + * struct quicki2c_device - THC QuickI2C device struct 133 + * @dev: point to kernel device 134 + * @pdev: point to PCI device 135 + * @thc_hw: point to THC device 136 + * @hid_dev: point to hid device 137 + * @acpi_dev: point to ACPI device 138 + * @driver_data: point to quicki2c specific driver data 139 + * @state: THC I2C device state 140 + * @mem_addr: MMIO memory address 141 + * @dev_desc: device descriptor for HIDI2C protocol 142 + * @i2c_slave_addr: HIDI2C device slave address 143 + * @hid_desc_addr: Register address for retrieve HID device descriptor 144 + * @active_ltr_val: THC active LTR value 145 + * @low_power_ltr_val: THC low power LTR value 146 + * @i2c_speed_mode: 0 - standard mode, 1 - fast mode, 2 - fast mode plus 147 + * @i2c_clock_hcnt: I2C CLK high period time (unit in cycle count) 148 + * @i2c_clock_lcnt: I2C CLK low period time (unit in cycle count) 149 + * @report_descriptor: store a copy of device report descriptor 150 + * @input_buf: store a copy of latest input report data 151 + * @report_buf: store a copy of latest input/output report packet from set/get feature 152 + * @report_len: the length of input/output report packet 153 + * @reset_ack_wq: workqueue for waiting reset response from device 154 + * @reset_ack: indicate reset response received or not 155 + */ 156 + struct quicki2c_device { 157 + struct device *dev; 158 + struct pci_dev *pdev; 159 + struct thc_device *thc_hw; 160 + struct hid_device *hid_dev; 161 + struct acpi_device *acpi_dev; 162 + enum quicki2c_dev_state state; 163 + 164 + void __iomem *mem_addr; 165 + 166 + struct hidi2c_dev_descriptor dev_desc; 167 + u8 i2c_slave_addr; 168 + u16 hid_desc_addr; 169 + 170 + u32 active_ltr_val; 171 + u32 low_power_ltr_val; 172 + 173 + u32 i2c_speed_mode; 174 + u32 i2c_clock_hcnt; 175 + u32 i2c_clock_lcnt; 176 + 177 + u8 *report_descriptor; 178 + u8 *input_buf; 179 + u8 *report_buf; 180 + u32 report_len; 181 + 182 + wait_queue_head_t reset_ack_wq; 183 + bool reset_ack; 184 + }; 185 + 186 + #endif /* _QUICKI2C_DEV_H_ */
+166
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #include <linux/hid.h> 5 + #include <linux/input.h> 6 + #include <linux/pm_runtime.h> 7 + 8 + #include "quicki2c-dev.h" 9 + #include "quicki2c-hid.h" 10 + #include "quicki2c-protocol.h" 11 + 12 + /** 13 + * quicki2c_hid_parse() - HID core parse() callback 14 + * 15 + * @hid: HID device instance 16 + * 17 + * This function gets called during call to hid_add_device 18 + * 19 + * Return: 0 on success and non zero on error. 20 + */ 21 + static int quicki2c_hid_parse(struct hid_device *hid) 22 + { 23 + struct quicki2c_device *qcdev = hid->driver_data; 24 + 25 + if (qcdev->report_descriptor) 26 + return hid_parse_report(hid, qcdev->report_descriptor, 27 + le16_to_cpu(qcdev->dev_desc.report_desc_len)); 28 + 29 + dev_err_once(qcdev->dev, "invalid report descriptor\n"); 30 + return -EINVAL; 31 + } 32 + 33 + static int quicki2c_hid_start(struct hid_device *hid) 34 + { 35 + return 0; 36 + } 37 + 38 + static void quicki2c_hid_stop(struct hid_device *hid) 39 + { 40 + } 41 + 42 + static int quicki2c_hid_open(struct hid_device *hid) 43 + { 44 + return 0; 45 + } 46 + 47 + static void quicki2c_hid_close(struct hid_device *hid) 48 + { 49 + } 50 + 51 + static int quicki2c_hid_raw_request(struct hid_device *hid, 52 + unsigned char reportnum, 53 + __u8 *buf, size_t len, 54 + unsigned char rtype, int reqtype) 55 + { 56 + struct quicki2c_device *qcdev = hid->driver_data; 57 + int ret = 0; 58 + 59 + ret = pm_runtime_resume_and_get(qcdev->dev); 60 + if (ret) 61 + return ret; 62 + 63 + switch (reqtype) { 64 + case HID_REQ_GET_REPORT: 65 + ret = quicki2c_get_report(qcdev, rtype, reportnum, buf, len); 66 + break; 67 + case HID_REQ_SET_REPORT: 68 + ret = quicki2c_set_report(qcdev, rtype, reportnum, buf, len); 69 + break; 70 + default: 71 + dev_err(qcdev->dev, "Not supported request type %d\n", reqtype); 72 + break; 73 + } 74 + 75 + pm_runtime_mark_last_busy(qcdev->dev); 76 + pm_runtime_put_autosuspend(qcdev->dev); 77 + 78 + return ret; 79 + } 80 + 81 + static int quicki2c_hid_power(struct hid_device *hid, int lvl) 82 + { 83 + return 0; 84 + } 85 + 86 + static struct hid_ll_driver quicki2c_hid_ll_driver = { 87 + .parse = quicki2c_hid_parse, 88 + .start = quicki2c_hid_start, 89 + .stop = quicki2c_hid_stop, 90 + .open = quicki2c_hid_open, 91 + .close = quicki2c_hid_close, 92 + .power = quicki2c_hid_power, 93 + .raw_request = quicki2c_hid_raw_request, 94 + }; 95 + 96 + /** 97 + * quicki2c_hid_probe() - Register HID low level driver 98 + * 99 + * @qcdev: point to quicki2c device 100 + * 101 + * This function is used to allocate and add HID device. 102 + * 103 + * Return: 0 on success, non zero on error. 104 + */ 105 + int quicki2c_hid_probe(struct quicki2c_device *qcdev) 106 + { 107 + struct hid_device *hid; 108 + int ret; 109 + 110 + hid = hid_allocate_device(); 111 + if (IS_ERR(hid)) 112 + return PTR_ERR(hid); 113 + 114 + hid->ll_driver = &quicki2c_hid_ll_driver; 115 + hid->bus = BUS_PCI; 116 + hid->dev.parent = qcdev->dev; 117 + hid->driver_data = qcdev; 118 + hid->version = le16_to_cpu(qcdev->dev_desc.version_id); 119 + hid->vendor = le16_to_cpu(qcdev->dev_desc.vendor_id); 120 + hid->product = le16_to_cpu(qcdev->dev_desc.product_id); 121 + snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid", 122 + hid->vendor, hid->product); 123 + 124 + ret = hid_add_device(hid); 125 + if (ret) { 126 + hid_destroy_device(hid); 127 + return ret; 128 + } 129 + 130 + qcdev->hid_dev = hid; 131 + 132 + return 0; 133 + } 134 + 135 + /** 136 + * quicki2c_hid_remove() - Destroy HID device 137 + * 138 + * @qcdev: point to quicki2c device 139 + * 140 + * Return: 0 on success, non zero on error. 141 + */ 142 + void quicki2c_hid_remove(struct quicki2c_device *qcdev) 143 + { 144 + hid_destroy_device(qcdev->hid_dev); 145 + } 146 + 147 + /** 148 + * quicki2c_hid_send_report() - Send HID input report data to HID core 149 + * 150 + * @qcdev: point to quicki2c device 151 + * @data: point to input report data buffer 152 + * @data_len: the length of input report data 153 + * 154 + * Return: 0 on success, non zero on error. 155 + */ 156 + int quicki2c_hid_send_report(struct quicki2c_device *qcdev, 157 + void *data, size_t data_len) 158 + { 159 + int ret; 160 + 161 + ret = hid_input_report(qcdev->hid_dev, HID_INPUT_REPORT, data, data_len, 1); 162 + if (ret) 163 + dev_err(qcdev->dev, "Failed to send HID input report, ret = %d.\n", ret); 164 + 165 + return ret; 166 + }
+14
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _QUICKI2C_HID_H_ 5 + #define _QUICKI2C_HID_H_ 6 + 7 + struct quicki2c_device; 8 + 9 + int quicki2c_hid_send_report(struct quicki2c_device *qcdev, 10 + void *data, size_t data_size); 11 + int quicki2c_hid_probe(struct quicki2c_device *qcdev); 12 + void quicki2c_hid_remove(struct quicki2c_device *qcdev); 13 + 14 + #endif /* _QUICKI2C_HID_H_ */
+224
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #include <linux/bitfield.h> 5 + #include <linux/hid.h> 6 + #include <linux/hid-over-i2c.h> 7 + 8 + #include "intel-thc-dev.h" 9 + #include "intel-thc-dma.h" 10 + 11 + #include "quicki2c-dev.h" 12 + #include "quicki2c-hid.h" 13 + #include "quicki2c-protocol.h" 14 + 15 + static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int cmd_len, 16 + bool append_data_reg, u8 *data, int data_len, 17 + u8 *write_buf, int write_buf_len) 18 + { 19 + int buf_len, offset = 0; 20 + 21 + buf_len = HIDI2C_REG_LEN + cmd_len; 22 + 23 + if (append_data_reg) 24 + buf_len += HIDI2C_REG_LEN; 25 + 26 + if (data && data_len) 27 + buf_len += data_len + HIDI2C_LENGTH_LEN; 28 + 29 + if (buf_len > write_buf_len) 30 + return -EINVAL; 31 + 32 + memcpy(write_buf, &qcdev->dev_desc.cmd_reg, HIDI2C_REG_LEN); 33 + offset += HIDI2C_REG_LEN; 34 + memcpy(write_buf + offset, &cmd, cmd_len); 35 + offset += cmd_len; 36 + 37 + if (append_data_reg) { 38 + memcpy(write_buf + offset, &qcdev->dev_desc.data_reg, HIDI2C_REG_LEN); 39 + offset += HIDI2C_REG_LEN; 40 + } 41 + 42 + if (data && data_len) { 43 + __le16 len = cpu_to_le16(data_len + HIDI2C_LENGTH_LEN); 44 + 45 + memcpy(write_buf + offset, &len, HIDI2C_LENGTH_LEN); 46 + offset += HIDI2C_LENGTH_LEN; 47 + memcpy(write_buf + offset, data, data_len); 48 + } 49 + 50 + return buf_len; 51 + } 52 + 53 + static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf, 54 + u8 opcode, u8 report_type, u8 report_id) 55 + { 56 + int cmd_len; 57 + 58 + *cmd_buf = FIELD_PREP(HIDI2C_CMD_OPCODE, opcode) | 59 + FIELD_PREP(HIDI2C_CMD_REPORT_TYPE, report_type); 60 + 61 + if (report_id < HIDI2C_CMD_MAX_RI) { 62 + *cmd_buf |= FIELD_PREP(HIDI2C_CMD_REPORT_ID, report_id); 63 + cmd_len = HIDI2C_CMD_LEN; 64 + } else { 65 + *cmd_buf |= FIELD_PREP(HIDI2C_CMD_REPORT_ID, HIDI2C_CMD_MAX_RI) | 66 + FIELD_PREP(HIDI2C_CMD_3RD_BYTE, report_id); 67 + cmd_len = HIDI2C_CMD_LEN_OPT; 68 + } 69 + 70 + return cmd_len; 71 + } 72 + 73 + static int write_cmd_to_txdma(struct quicki2c_device *qcdev, int opcode, 74 + int report_type, int report_id, u8 *buf, int buf_len) 75 + { 76 + size_t write_buf_len; 77 + int cmd_len, ret; 78 + u32 cmd; 79 + 80 + cmd_len = quicki2c_encode_cmd(qcdev, &cmd, opcode, report_type, report_id); 81 + 82 + ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf, 83 + buf_len, qcdev->report_buf, qcdev->report_len); 84 + if (ret < 0) 85 + return ret; 86 + 87 + write_buf_len = ret; 88 + 89 + return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, write_buf_len); 90 + } 91 + 92 + int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state) 93 + { 94 + return write_cmd_to_txdma(qcdev, HIDI2C_SET_POWER, HIDI2C_RESERVED, power_state, NULL, 0); 95 + } 96 + 97 + int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev) 98 + { 99 + u32 read_len = 0; 100 + int ret; 101 + 102 + ret = thc_tic_pio_write_and_read(qcdev->thc_hw, qcdev->hid_desc_addr, 103 + HIDI2C_REG_LEN, NULL, HIDI2C_DEV_DESC_LEN, 104 + &read_len, (u32 *)&qcdev->dev_desc); 105 + if (ret || HIDI2C_DEV_DESC_LEN != read_len) { 106 + dev_err_once(qcdev->dev, "Get device descriptor failed, ret %d, read len %u\n", 107 + ret, read_len); 108 + return -EIO; 109 + } 110 + 111 + if (le16_to_cpu(qcdev->dev_desc.bcd_ver) != HIDI2C_HID_DESC_BCDVERSION) 112 + return -EOPNOTSUPP; 113 + 114 + return 0; 115 + } 116 + 117 + int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev) 118 + { 119 + u16 desc_reg = le16_to_cpu(qcdev->dev_desc.report_desc_reg); 120 + size_t read_len = le16_to_cpu(qcdev->dev_desc.report_desc_len); 121 + u32 prd_len = read_len; 122 + 123 + return thc_swdma_read(qcdev->thc_hw, (u8 *)&desc_reg, HIDI2C_REG_LEN, 124 + &prd_len, qcdev->report_descriptor, &read_len); 125 + } 126 + 127 + int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, 128 + unsigned int reportnum, void *buf, u32 buf_len) 129 + { 130 + struct hidi2c_report_packet *rpt; 131 + size_t write_buf_len, read_len = 0; 132 + int cmd_len, rep_type; 133 + u32 cmd; 134 + int ret; 135 + 136 + if (report_type == HID_INPUT_REPORT) { 137 + rep_type = HIDI2C_INPUT; 138 + } else if (report_type == HID_FEATURE_REPORT) { 139 + rep_type = HIDI2C_FEATURE; 140 + } else { 141 + dev_err(qcdev->dev, "Unsupported report type for GET REPORT: %d\n", report_type); 142 + return -EINVAL; 143 + } 144 + 145 + cmd_len = quicki2c_encode_cmd(qcdev, &cmd, HIDI2C_GET_REPORT, rep_type, reportnum); 146 + 147 + ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0, 148 + qcdev->report_buf, qcdev->report_len); 149 + if (ret < 0) 150 + return ret; 151 + 152 + write_buf_len = ret; 153 + 154 + rpt = (struct hidi2c_report_packet *)qcdev->input_buf; 155 + 156 + ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, write_buf_len, 157 + NULL, rpt, &read_len); 158 + if (ret) { 159 + dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %d)\n", 160 + ret, read_len, buf_len); 161 + return ret; 162 + } 163 + 164 + if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len || rpt->data[0] != reportnum) { 165 + dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %d) report id (%d vs %d)\n", 166 + le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum); 167 + return -EINVAL; 168 + } 169 + 170 + memcpy(buf, rpt->data, buf_len); 171 + 172 + return buf_len; 173 + } 174 + 175 + int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, 176 + unsigned int reportnum, void *buf, u32 buf_len) 177 + { 178 + int rep_type; 179 + int ret; 180 + 181 + if (report_type == HID_OUTPUT_REPORT) { 182 + rep_type = HIDI2C_OUTPUT; 183 + } else if (report_type == HID_FEATURE_REPORT) { 184 + rep_type = HIDI2C_FEATURE; 185 + } else { 186 + dev_err(qcdev->dev, "Unsupported report type for SET REPORT: %d\n", report_type); 187 + return -EINVAL; 188 + } 189 + 190 + ret = write_cmd_to_txdma(qcdev, HIDI2C_SET_REPORT, rep_type, reportnum, buf, buf_len); 191 + if (ret) { 192 + dev_err_once(qcdev->dev, "Set Report failed, ret %d\n", ret); 193 + return ret; 194 + } 195 + 196 + return buf_len; 197 + } 198 + 199 + #define HIDI2C_RESET_TIMEOUT 5 200 + 201 + int quicki2c_reset(struct quicki2c_device *qcdev) 202 + { 203 + int ret; 204 + 205 + qcdev->reset_ack = false; 206 + qcdev->state = QUICKI2C_RESETING; 207 + 208 + ret = write_cmd_to_txdma(qcdev, HIDI2C_RESET, HIDI2C_RESERVED, 0, NULL, 0); 209 + if (ret) { 210 + dev_err_once(qcdev->dev, "Send reset command failed, ret %d\n", ret); 211 + return ret; 212 + } 213 + 214 + ret = wait_event_interruptible_timeout(qcdev->reset_ack_wq, qcdev->reset_ack, 215 + HIDI2C_RESET_TIMEOUT * HZ); 216 + if (ret <= 0 || !qcdev->reset_ack) { 217 + dev_err_once(qcdev->dev, 218 + "Wait reset response timed out ret:%d timeout:%ds\n", 219 + ret, HIDI2C_RESET_TIMEOUT); 220 + return -ETIMEDOUT; 221 + } 222 + 223 + return 0; 224 + }
+20
drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _QUICKI2C_PROTOCOL_H_ 5 + #define _QUICKI2C_PROTOCOL_H_ 6 + 7 + #include <linux/hid-over-i2c.h> 8 + 9 + struct quicki2c_device; 10 + 11 + int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state); 12 + int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type, 13 + unsigned int reportnum, void *buf, u32 buf_len); 14 + int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type, 15 + unsigned int reportnum, void *buf, u32 buf_len); 16 + int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev); 17 + int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev); 18 + int quicki2c_reset(struct quicki2c_device *qcdev); 19 + 20 + #endif /* _QUICKI2C_PROTOCOL_H_ */
+987
drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #include <linux/acpi.h> 5 + #include <linux/bitfield.h> 6 + #include <linux/device.h> 7 + #include <linux/dma-mapping.h> 8 + #include <linux/err.h> 9 + #include <linux/interrupt.h> 10 + #include <linux/irqreturn.h> 11 + #include <linux/pci.h> 12 + #include <linux/pm_runtime.h> 13 + 14 + #include "intel-thc-dev.h" 15 + #include "intel-thc-hw.h" 16 + 17 + #include "quickspi-dev.h" 18 + #include "quickspi-hid.h" 19 + #include "quickspi-protocol.h" 20 + 21 + struct quickspi_driver_data mtl = { 22 + .max_packet_size_value = MAX_PACKET_SIZE_VALUE_MTL, 23 + }; 24 + 25 + struct quickspi_driver_data lnl = { 26 + .max_packet_size_value = MAX_PACKET_SIZE_VALUE_LNL, 27 + }; 28 + 29 + struct quickspi_driver_data ptl = { 30 + .max_packet_size_value = MAX_PACKET_SIZE_VALUE_LNL, 31 + }; 32 + 33 + /* THC QuickSPI ACPI method to get device properties */ 34 + /* HIDSPI Method: {6e2ac436-0fcf-41af-a265-b32a220dcfab} */ 35 + static guid_t hidspi_guid = 36 + GUID_INIT(0x6e2ac436, 0x0fcf, 0x41af, 0xa2, 0x65, 0xb3, 0x2a, 37 + 0x22, 0x0d, 0xcf, 0xab); 38 + 39 + /* QuickSpi Method: {300D35b7-ac20-413e-8e9c-92e4dafd0afe} */ 40 + static guid_t thc_quickspi_guid = 41 + GUID_INIT(0x300d35b7, 0xac20, 0x413e, 0x8e, 0x9c, 0x92, 0xe4, 42 + 0xda, 0xfd, 0x0a, 0xfe); 43 + 44 + /* Platform Method: {84005682-5b71-41a4-0x8d668130f787a138} */ 45 + static guid_t thc_platform_guid = 46 + GUID_INIT(0x84005682, 0x5b71, 0x41a4, 0x8d, 0x66, 0x81, 0x30, 47 + 0xf7, 0x87, 0xa1, 0x38); 48 + 49 + /** 50 + * thc_acpi_get_property - Query device ACPI parameter 51 + * 52 + * @adev: point to ACPI device 53 + * @guid: ACPI method's guid 54 + * @rev: ACPI method's revision 55 + * @func: ACPI method's function number 56 + * @type: ACPI parameter's data type 57 + * @prop_buf: point to return buffer 58 + * 59 + * This is a helper function for device to query its ACPI parameters. 60 + * 61 + * Return: 0 if successful or ENODEV on failed. 62 + */ 63 + static int thc_acpi_get_property(struct acpi_device *adev, const guid_t *guid, 64 + u64 rev, u64 func, acpi_object_type type, void *prop_buf) 65 + { 66 + acpi_handle handle = acpi_device_handle(adev); 67 + union acpi_object *obj; 68 + 69 + obj = acpi_evaluate_dsm_typed(handle, guid, rev, func, NULL, type); 70 + if (!obj) { 71 + acpi_handle_err(handle, 72 + "Error _DSM call failed, rev: %llu, func: %llu, type: %u\n", 73 + rev, func, type); 74 + return -ENODEV; 75 + } 76 + 77 + if (type == ACPI_TYPE_INTEGER) 78 + *(u32 *)prop_buf = (u32)obj->integer.value; 79 + else if (type == ACPI_TYPE_BUFFER) 80 + memcpy(prop_buf, obj->buffer.pointer, obj->buffer.length); 81 + 82 + ACPI_FREE(obj); 83 + 84 + return 0; 85 + } 86 + 87 + /** 88 + * quickspi_get_acpi_resources - Query all quickspi devices' ACPI parameters 89 + * 90 + * @qsdev: point to quickspi device 91 + * 92 + * This function gets all quickspi devices' ACPI resource. 93 + * 94 + * Return: 0 if successful or error code on failed. 95 + */ 96 + static int quickspi_get_acpi_resources(struct quickspi_device *qsdev) 97 + { 98 + struct acpi_device *adev = ACPI_COMPANION(qsdev->dev); 99 + int ret = -EINVAL; 100 + 101 + if (!adev) { 102 + dev_err(qsdev->dev, "no valid ACPI companion\n"); 103 + return ret; 104 + } 105 + 106 + qsdev->acpi_dev = adev; 107 + 108 + ret = thc_acpi_get_property(adev, &hidspi_guid, 109 + ACPI_QUICKSPI_REVISION_NUM, 110 + ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_HDR_ADDR, 111 + ACPI_TYPE_INTEGER, 112 + &qsdev->input_report_hdr_addr); 113 + if (ret) 114 + return ret; 115 + 116 + ret = thc_acpi_get_property(adev, &hidspi_guid, 117 + ACPI_QUICKSPI_REVISION_NUM, 118 + ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_BDY_ADDR, 119 + ACPI_TYPE_INTEGER, 120 + &qsdev->input_report_bdy_addr); 121 + if (ret) 122 + return ret; 123 + 124 + ret = thc_acpi_get_property(adev, &hidspi_guid, 125 + ACPI_QUICKSPI_REVISION_NUM, 126 + ACPI_QUICKSPI_FUNC_NUM_OUTPUT_REP_ADDR, 127 + ACPI_TYPE_INTEGER, 128 + &qsdev->output_report_addr); 129 + if (ret) 130 + return ret; 131 + 132 + ret = thc_acpi_get_property(adev, &hidspi_guid, 133 + ACPI_QUICKSPI_REVISION_NUM, 134 + ACPI_QUICKSPI_FUNC_NUM_READ_OPCODE, 135 + ACPI_TYPE_BUFFER, 136 + &qsdev->spi_read_opcode); 137 + if (ret) 138 + return ret; 139 + 140 + ret = thc_acpi_get_property(adev, &hidspi_guid, 141 + ACPI_QUICKSPI_REVISION_NUM, 142 + ACPI_QUICKSPI_FUNC_NUM_WRITE_OPCODE, 143 + ACPI_TYPE_BUFFER, 144 + &qsdev->spi_write_opcode); 145 + if (ret) 146 + return ret; 147 + 148 + ret = thc_acpi_get_property(adev, &hidspi_guid, 149 + ACPI_QUICKSPI_REVISION_NUM, 150 + ACPI_QUICKSPI_FUNC_NUM_IO_MODE, 151 + ACPI_TYPE_INTEGER, 152 + &qsdev->spi_read_io_mode); 153 + if (ret) 154 + return ret; 155 + 156 + if (qsdev->spi_read_io_mode & SPI_WRITE_IO_MODE) 157 + qsdev->spi_write_io_mode = FIELD_GET(SPI_IO_MODE_OPCODE, qsdev->spi_read_io_mode); 158 + else 159 + qsdev->spi_write_io_mode = THC_SINGLE_IO; 160 + 161 + qsdev->spi_read_io_mode = FIELD_GET(SPI_IO_MODE_OPCODE, qsdev->spi_read_io_mode); 162 + 163 + ret = thc_acpi_get_property(adev, &thc_quickspi_guid, 164 + ACPI_QUICKSPI_REVISION_NUM, 165 + ACPI_QUICKSPI_FUNC_NUM_CONNECTION_SPEED, 166 + ACPI_TYPE_INTEGER, 167 + &qsdev->spi_freq_val); 168 + if (ret) 169 + return ret; 170 + 171 + ret = thc_acpi_get_property(adev, &thc_quickspi_guid, 172 + ACPI_QUICKSPI_REVISION_NUM, 173 + ACPI_QUICKSPI_FUNC_NUM_LIMIT_PACKET_SIZE, 174 + ACPI_TYPE_INTEGER, 175 + &qsdev->limit_packet_size); 176 + if (ret) 177 + return ret; 178 + 179 + if (qsdev->limit_packet_size || !qsdev->driver_data) 180 + qsdev->spi_packet_size = DEFAULT_MIN_PACKET_SIZE_VALUE; 181 + else 182 + qsdev->spi_packet_size = qsdev->driver_data->max_packet_size_value; 183 + 184 + ret = thc_acpi_get_property(adev, &thc_quickspi_guid, 185 + ACPI_QUICKSPI_REVISION_NUM, 186 + ACPI_QUICKSPI_FUNC_NUM_PERFORMANCE_LIMIT, 187 + ACPI_TYPE_INTEGER, 188 + &qsdev->performance_limit); 189 + if (ret) 190 + return ret; 191 + 192 + qsdev->performance_limit = FIELD_GET(PERFORMANCE_LIMITATION, qsdev->performance_limit); 193 + 194 + ret = thc_acpi_get_property(adev, &thc_platform_guid, 195 + ACPI_QUICKSPI_REVISION_NUM, 196 + ACPI_QUICKSPI_FUNC_NUM_ACTIVE_LTR, 197 + ACPI_TYPE_INTEGER, 198 + &qsdev->active_ltr_val); 199 + if (ret) 200 + return ret; 201 + 202 + ret = thc_acpi_get_property(adev, &thc_platform_guid, 203 + ACPI_QUICKSPI_REVISION_NUM, 204 + ACPI_QUICKSPI_FUNC_NUM_LP_LTR, 205 + ACPI_TYPE_INTEGER, 206 + &qsdev->low_power_ltr_val); 207 + if (ret) 208 + return ret; 209 + 210 + return 0; 211 + } 212 + 213 + /** 214 + * quickspi_irq_quick_handler - The ISR of the quickspi driver 215 + * 216 + * @irq: The irq number 217 + * @dev_id: pointer to the device structure 218 + * 219 + * Return: IRQ_WAKE_THREAD if further process needed. 220 + */ 221 + static irqreturn_t quickspi_irq_quick_handler(int irq, void *dev_id) 222 + { 223 + struct quickspi_device *qsdev = dev_id; 224 + 225 + if (qsdev->state == QUICKSPI_DISABLED) 226 + return IRQ_HANDLED; 227 + 228 + /* Disable THC interrupt before current interrupt be handled */ 229 + thc_interrupt_enable(qsdev->thc_hw, false); 230 + 231 + return IRQ_WAKE_THREAD; 232 + } 233 + 234 + /** 235 + * try_recover - Try to recovery THC and Device 236 + * @qsdev: pointer to quickspi device 237 + * 238 + * This function is a error handler, called when fatal error happens. 239 + * It try to reset Touch Device and re-configure THC to recovery 240 + * transferring between Device and THC. 241 + * 242 + * Return: 0 if successful or error code on failed. 243 + */ 244 + static int try_recover(struct quickspi_device *qsdev) 245 + { 246 + int ret; 247 + 248 + ret = reset_tic(qsdev); 249 + if (ret) { 250 + dev_err(qsdev->dev, "Reset touch device failed, ret = %d\n", ret); 251 + return ret; 252 + } 253 + 254 + thc_dma_unconfigure(qsdev->thc_hw); 255 + 256 + ret = thc_dma_configure(qsdev->thc_hw); 257 + if (ret) { 258 + dev_err(qsdev->dev, "Re-configure THC DMA failed, ret = %d\n", ret); 259 + return ret; 260 + } 261 + 262 + return 0; 263 + } 264 + 265 + /** 266 + * quickspi_irq_thread_handler - IRQ thread handler of quickspi driver 267 + * 268 + * @irq: The IRQ number 269 + * @dev_id: pointer to the quickspi device structure 270 + * 271 + * Return: IRQ_HANDLED to finish this handler. 272 + */ 273 + static irqreturn_t quickspi_irq_thread_handler(int irq, void *dev_id) 274 + { 275 + struct quickspi_device *qsdev = dev_id; 276 + size_t input_len; 277 + int read_finished = 0; 278 + int err_recover = 0; 279 + int int_mask; 280 + int ret; 281 + 282 + if (qsdev->state == QUICKSPI_DISABLED) 283 + return IRQ_HANDLED; 284 + 285 + ret = pm_runtime_resume_and_get(qsdev->dev); 286 + if (ret) 287 + return IRQ_HANDLED; 288 + 289 + int_mask = thc_interrupt_handler(qsdev->thc_hw); 290 + 291 + if (int_mask & BIT(THC_FATAL_ERR_INT) || int_mask & BIT(THC_TXN_ERR_INT)) { 292 + err_recover = 1; 293 + goto end; 294 + } 295 + 296 + if (int_mask & BIT(THC_NONDMA_INT)) { 297 + if (qsdev->state == QUICKSPI_RESETING) { 298 + qsdev->reset_ack = true; 299 + wake_up_interruptible(&qsdev->reset_ack_wq); 300 + } else { 301 + qsdev->nondma_int_received = true; 302 + wake_up_interruptible(&qsdev->nondma_int_received_wq); 303 + } 304 + } 305 + 306 + if (int_mask & BIT(THC_RXDMA2_INT)) { 307 + while (!read_finished) { 308 + ret = thc_rxdma_read(qsdev->thc_hw, THC_RXDMA2, qsdev->input_buf, 309 + &input_len, &read_finished); 310 + if (ret) { 311 + err_recover = 1; 312 + goto end; 313 + } 314 + 315 + quickspi_handle_input_data(qsdev, input_len); 316 + } 317 + } 318 + 319 + end: 320 + thc_interrupt_enable(qsdev->thc_hw, true); 321 + 322 + if (err_recover) 323 + if (try_recover(qsdev)) 324 + qsdev->state = QUICKSPI_DISABLED; 325 + 326 + pm_runtime_mark_last_busy(qsdev->dev); 327 + pm_runtime_put_autosuspend(qsdev->dev); 328 + 329 + return IRQ_HANDLED; 330 + } 331 + 332 + /** 333 + * quickspi_dev_init - Initialize quickspi device 334 + * 335 + * @pdev: pointer to the thc pci device 336 + * @mem_addr: The pointer of MMIO memory address 337 + * @id: point to pci_device_id structure 338 + * 339 + * Alloc quickspi device structure and initialized THC device, 340 + * then configure THC to HIDSPI mode. 341 + * 342 + * If success, enable THC hardware interrupt. 343 + * 344 + * Return: pointer to the quickspi device structure if success 345 + * or NULL on failed. 346 + */ 347 + static struct quickspi_device *quickspi_dev_init(struct pci_dev *pdev, void __iomem *mem_addr, 348 + const struct pci_device_id *id) 349 + { 350 + struct device *dev = &pdev->dev; 351 + struct quickspi_device *qsdev; 352 + int ret; 353 + 354 + qsdev = devm_kzalloc(dev, sizeof(struct quickspi_device), GFP_KERNEL); 355 + if (!qsdev) 356 + return ERR_PTR(-ENOMEM); 357 + 358 + qsdev->pdev = pdev; 359 + qsdev->dev = dev; 360 + qsdev->mem_addr = mem_addr; 361 + qsdev->state = QUICKSPI_DISABLED; 362 + qsdev->driver_data = (struct quickspi_driver_data *)id->driver_data; 363 + 364 + init_waitqueue_head(&qsdev->reset_ack_wq); 365 + init_waitqueue_head(&qsdev->nondma_int_received_wq); 366 + init_waitqueue_head(&qsdev->report_desc_got_wq); 367 + init_waitqueue_head(&qsdev->get_report_cmpl_wq); 368 + init_waitqueue_head(&qsdev->set_report_cmpl_wq); 369 + 370 + /* thc hw init */ 371 + qsdev->thc_hw = thc_dev_init(qsdev->dev, qsdev->mem_addr); 372 + if (IS_ERR(qsdev->thc_hw)) { 373 + ret = PTR_ERR(qsdev->thc_hw); 374 + dev_err(dev, "Failed to initialize THC device context, ret = %d.\n", ret); 375 + return ERR_PTR(ret); 376 + } 377 + 378 + ret = thc_interrupt_quiesce(qsdev->thc_hw, true); 379 + if (ret) 380 + return ERR_PTR(ret); 381 + 382 + ret = thc_port_select(qsdev->thc_hw, THC_PORT_TYPE_SPI); 383 + if (ret) { 384 + dev_err(dev, "Failed to select THC port, ret = %d.\n", ret); 385 + return ERR_PTR(ret); 386 + } 387 + 388 + ret = quickspi_get_acpi_resources(qsdev); 389 + if (ret) { 390 + dev_err(dev, "Get ACPI resources failed, ret = %d\n", ret); 391 + return ERR_PTR(ret); 392 + } 393 + 394 + /* THC config for input/output address */ 395 + thc_spi_input_output_address_config(qsdev->thc_hw, 396 + qsdev->input_report_hdr_addr, 397 + qsdev->input_report_bdy_addr, 398 + qsdev->output_report_addr); 399 + 400 + /* THC config for spi read operation */ 401 + ret = thc_spi_read_config(qsdev->thc_hw, qsdev->spi_freq_val, 402 + qsdev->spi_read_io_mode, 403 + qsdev->spi_read_opcode, 404 + qsdev->spi_packet_size); 405 + if (ret) { 406 + dev_err(dev, "thc_spi_read_config failed, ret = %d\n", ret); 407 + return ERR_PTR(ret); 408 + } 409 + 410 + /* THC config for spi write operation */ 411 + ret = thc_spi_write_config(qsdev->thc_hw, qsdev->spi_freq_val, 412 + qsdev->spi_write_io_mode, 413 + qsdev->spi_write_opcode, 414 + qsdev->spi_packet_size, 415 + qsdev->performance_limit); 416 + if (ret) { 417 + dev_err(dev, "thc_spi_write_config failed, ret = %d\n", ret); 418 + return ERR_PTR(ret); 419 + } 420 + 421 + thc_ltr_config(qsdev->thc_hw, 422 + qsdev->active_ltr_val, 423 + qsdev->low_power_ltr_val); 424 + 425 + thc_interrupt_config(qsdev->thc_hw); 426 + 427 + thc_interrupt_enable(qsdev->thc_hw, true); 428 + 429 + qsdev->state = QUICKSPI_INITED; 430 + 431 + return qsdev; 432 + } 433 + 434 + /** 435 + * quickspi_dev_deinit - De-initialize quickspi device 436 + * 437 + * @qsdev: pointer to the quickspi device structure 438 + * 439 + * Disable THC interrupt and deinitilize THC. 440 + */ 441 + static void quickspi_dev_deinit(struct quickspi_device *qsdev) 442 + { 443 + thc_interrupt_enable(qsdev->thc_hw, false); 444 + thc_ltr_unconfig(qsdev->thc_hw); 445 + 446 + qsdev->state = QUICKSPI_DISABLED; 447 + } 448 + 449 + /** 450 + * quickspi_dma_init - Configure THC DMA for quickspi device 451 + * @qsdev: pointer to the quickspi device structure 452 + * 453 + * This function uses TIC's parameters(such as max input length, max output 454 + * length) to allocate THC DMA buffers and configure THC DMA engines. 455 + * 456 + * Return: 0 if successful or error code on failed. 457 + */ 458 + static int quickspi_dma_init(struct quickspi_device *qsdev) 459 + { 460 + int ret; 461 + 462 + ret = thc_dma_set_max_packet_sizes(qsdev->thc_hw, 0, 463 + le16_to_cpu(qsdev->dev_desc.max_input_len), 464 + le16_to_cpu(qsdev->dev_desc.max_output_len), 465 + 0); 466 + if (ret) 467 + return ret; 468 + 469 + ret = thc_dma_allocate(qsdev->thc_hw); 470 + if (ret) { 471 + dev_err(qsdev->dev, "Allocate THC DMA buffer failed, ret = %d\n", ret); 472 + return ret; 473 + } 474 + 475 + /* Enable RxDMA */ 476 + ret = thc_dma_configure(qsdev->thc_hw); 477 + if (ret) { 478 + dev_err(qsdev->dev, "Configure THC DMA failed, ret = %d\n", ret); 479 + thc_dma_unconfigure(qsdev->thc_hw); 480 + thc_dma_release(qsdev->thc_hw); 481 + return ret; 482 + } 483 + 484 + return ret; 485 + } 486 + 487 + /** 488 + * quickspi_dma_deinit - Release THC DMA for quickspi device 489 + * @qsdev: pointer to the quickspi device structure 490 + * 491 + * Stop THC DMA engines and release all DMA buffers. 492 + * 493 + */ 494 + static void quickspi_dma_deinit(struct quickspi_device *qsdev) 495 + { 496 + thc_dma_unconfigure(qsdev->thc_hw); 497 + thc_dma_release(qsdev->thc_hw); 498 + } 499 + 500 + /** 501 + * quickspi_alloc_report_buf - Alloc report buffers 502 + * @qsdev: pointer to the quickspi device structure 503 + * 504 + * Allocate report descriptor buffer, it will be used for restore TIC HID 505 + * report descriptor. 506 + * 507 + * Allocate input report buffer, it will be used for receive HID input report 508 + * data from TIC. 509 + * 510 + * Allocate output report buffer, it will be used for store HID output report, 511 + * such as set feature. 512 + * 513 + * Return: 0 if successful or error code on failed. 514 + */ 515 + static int quickspi_alloc_report_buf(struct quickspi_device *qsdev) 516 + { 517 + size_t max_report_len; 518 + size_t max_input_len; 519 + 520 + qsdev->report_descriptor = devm_kzalloc(qsdev->dev, 521 + le16_to_cpu(qsdev->dev_desc.rep_desc_len), 522 + GFP_KERNEL); 523 + if (!qsdev->report_descriptor) 524 + return -ENOMEM; 525 + 526 + max_input_len = max(le16_to_cpu(qsdev->dev_desc.rep_desc_len), 527 + le16_to_cpu(qsdev->dev_desc.max_input_len)); 528 + 529 + qsdev->input_buf = devm_kzalloc(qsdev->dev, max_input_len, GFP_KERNEL); 530 + if (!qsdev->input_buf) 531 + return -ENOMEM; 532 + 533 + max_report_len = max(le16_to_cpu(qsdev->dev_desc.max_output_len), 534 + le16_to_cpu(qsdev->dev_desc.max_input_len)); 535 + 536 + qsdev->report_buf = devm_kzalloc(qsdev->dev, max_report_len, GFP_KERNEL); 537 + if (!qsdev->report_buf) 538 + return -ENOMEM; 539 + 540 + return 0; 541 + } 542 + 543 + /* 544 + * quickspi_probe: Quickspi driver probe function 545 + * 546 + * @pdev: point to pci device 547 + * @id: point to pci_device_id structure 548 + * 549 + * This function initializes THC and HIDSPI device, the flow is: 550 + * - do THC pci device initialization 551 + * - query HIDSPI ACPI parameters 552 + * - configure THC to HIDSPI mode 553 + * - go through HIDSPI enumeration flow 554 + * |- reset HIDSPI device 555 + * |- read device descriptor 556 + * - enable THC interrupt and DMA 557 + * - read report descriptor 558 + * - register HID device 559 + * - enable runtime power management 560 + * 561 + * Return 0 if success or error code on failure. 562 + */ 563 + static int quickspi_probe(struct pci_dev *pdev, 564 + const struct pci_device_id *id) 565 + { 566 + struct quickspi_device *qsdev; 567 + void __iomem *mem_addr; 568 + int ret; 569 + 570 + ret = pcim_enable_device(pdev); 571 + if (ret) { 572 + dev_err(&pdev->dev, "Failed to enable PCI device, ret = %d.\n", ret); 573 + return ret; 574 + } 575 + 576 + pci_set_master(pdev); 577 + 578 + ret = pcim_iomap_regions(pdev, BIT(0), KBUILD_MODNAME); 579 + if (ret) { 580 + dev_err(&pdev->dev, "Failed to get PCI regions, ret = %d.\n", ret); 581 + goto disable_pci_device; 582 + } 583 + 584 + mem_addr = pcim_iomap_table(pdev)[0]; 585 + 586 + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 587 + if (ret) { 588 + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 589 + if (ret) { 590 + dev_err(&pdev->dev, "No usable DMA configuration %d\n", ret); 591 + goto unmap_io_region; 592 + } 593 + } 594 + 595 + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 596 + if (ret < 0) { 597 + dev_err(&pdev->dev, 598 + "Failed to allocate IRQ vectors. ret = %d\n", ret); 599 + goto unmap_io_region; 600 + } 601 + 602 + pdev->irq = pci_irq_vector(pdev, 0); 603 + 604 + qsdev = quickspi_dev_init(pdev, mem_addr, id); 605 + if (IS_ERR(qsdev)) { 606 + dev_err(&pdev->dev, "QuickSPI device init failed\n"); 607 + ret = PTR_ERR(qsdev); 608 + goto unmap_io_region; 609 + } 610 + 611 + pci_set_drvdata(pdev, qsdev); 612 + 613 + ret = devm_request_threaded_irq(&pdev->dev, pdev->irq, 614 + quickspi_irq_quick_handler, 615 + quickspi_irq_thread_handler, 616 + IRQF_ONESHOT, KBUILD_MODNAME, 617 + qsdev); 618 + if (ret) { 619 + dev_err(&pdev->dev, 620 + "Failed to request threaded IRQ, irq = %d.\n", pdev->irq); 621 + goto dev_deinit; 622 + } 623 + 624 + ret = reset_tic(qsdev); 625 + if (ret) { 626 + dev_err(&pdev->dev, "Reset Touch Device failed, ret = %d\n", ret); 627 + goto dev_deinit; 628 + } 629 + 630 + ret = quickspi_alloc_report_buf(qsdev); 631 + if (ret) { 632 + dev_err(&pdev->dev, "Alloc report buffers failed, ret= %d\n", ret); 633 + goto dev_deinit; 634 + } 635 + 636 + ret = quickspi_dma_init(qsdev); 637 + if (ret) { 638 + dev_err(&pdev->dev, "Setup THC DMA failed, ret= %d\n", ret); 639 + goto dev_deinit; 640 + } 641 + 642 + ret = quickspi_get_report_descriptor(qsdev); 643 + if (ret) { 644 + dev_err(&pdev->dev, "Get report descriptor failed, ret = %d\n", ret); 645 + goto dma_deinit; 646 + } 647 + 648 + ret = quickspi_hid_probe(qsdev); 649 + if (ret) { 650 + dev_err(&pdev->dev, "Failed to register HID device, ret = %d\n", ret); 651 + goto dma_deinit; 652 + } 653 + 654 + qsdev->state = QUICKSPI_ENABLED; 655 + 656 + /* Enable runtime power management */ 657 + pm_runtime_use_autosuspend(qsdev->dev); 658 + pm_runtime_set_autosuspend_delay(qsdev->dev, DEFAULT_AUTO_SUSPEND_DELAY_MS); 659 + pm_runtime_mark_last_busy(qsdev->dev); 660 + pm_runtime_put_noidle(qsdev->dev); 661 + pm_runtime_put_autosuspend(qsdev->dev); 662 + 663 + dev_dbg(&pdev->dev, "QuickSPI probe success\n"); 664 + 665 + return 0; 666 + 667 + dma_deinit: 668 + quickspi_dma_deinit(qsdev); 669 + dev_deinit: 670 + quickspi_dev_deinit(qsdev); 671 + unmap_io_region: 672 + pcim_iounmap_regions(pdev, BIT(0)); 673 + disable_pci_device: 674 + pci_clear_master(pdev); 675 + 676 + return ret; 677 + } 678 + 679 + /** 680 + * quickspi_remove - Device Removal Routine 681 + * 682 + * @pdev: PCI device structure 683 + * 684 + * This is called by the PCI subsystem to alert the driver 685 + * that it should release a PCI device. 686 + */ 687 + static void quickspi_remove(struct pci_dev *pdev) 688 + { 689 + struct quickspi_device *qsdev; 690 + 691 + qsdev = pci_get_drvdata(pdev); 692 + if (!qsdev) 693 + return; 694 + 695 + quickspi_hid_remove(qsdev); 696 + quickspi_dma_deinit(qsdev); 697 + 698 + pm_runtime_get_noresume(qsdev->dev); 699 + 700 + quickspi_dev_deinit(qsdev); 701 + 702 + pcim_iounmap_regions(pdev, BIT(0)); 703 + pci_clear_master(pdev); 704 + } 705 + 706 + /** 707 + * quickspi_shutdown - Device Shutdown Routine 708 + * 709 + * @pdev: PCI device structure 710 + * 711 + * This is called from the reboot notifier 712 + * it's a simplified version of remove so we go down 713 + * faster. 714 + */ 715 + static void quickspi_shutdown(struct pci_dev *pdev) 716 + { 717 + struct quickspi_device *qsdev; 718 + 719 + qsdev = pci_get_drvdata(pdev); 720 + if (!qsdev) 721 + return; 722 + 723 + /* Must stop DMA before reboot to avoid DMA entering into unknown state */ 724 + quickspi_dma_deinit(qsdev); 725 + 726 + quickspi_dev_deinit(qsdev); 727 + } 728 + 729 + static int quickspi_suspend(struct device *device) 730 + { 731 + struct pci_dev *pdev = to_pci_dev(device); 732 + struct quickspi_device *qsdev; 733 + int ret; 734 + 735 + qsdev = pci_get_drvdata(pdev); 736 + if (!qsdev) 737 + return -ENODEV; 738 + 739 + ret = quickspi_set_power(qsdev, HIDSPI_SLEEP); 740 + if (ret) 741 + return ret; 742 + 743 + ret = thc_interrupt_quiesce(qsdev->thc_hw, true); 744 + if (ret) 745 + return ret; 746 + 747 + thc_interrupt_enable(qsdev->thc_hw, false); 748 + 749 + thc_dma_unconfigure(qsdev->thc_hw); 750 + 751 + return 0; 752 + } 753 + 754 + static int quickspi_resume(struct device *device) 755 + { 756 + struct pci_dev *pdev = to_pci_dev(device); 757 + struct quickspi_device *qsdev; 758 + int ret; 759 + 760 + qsdev = pci_get_drvdata(pdev); 761 + if (!qsdev) 762 + return -ENODEV; 763 + 764 + ret = thc_port_select(qsdev->thc_hw, THC_PORT_TYPE_SPI); 765 + if (ret) 766 + return ret; 767 + 768 + thc_interrupt_config(qsdev->thc_hw); 769 + 770 + thc_interrupt_enable(qsdev->thc_hw, true); 771 + 772 + ret = thc_dma_configure(qsdev->thc_hw); 773 + if (ret) 774 + return ret; 775 + 776 + ret = thc_interrupt_quiesce(qsdev->thc_hw, false); 777 + if (ret) 778 + return ret; 779 + 780 + ret = quickspi_set_power(qsdev, HIDSPI_ON); 781 + if (ret) 782 + return ret; 783 + 784 + return 0; 785 + } 786 + 787 + static int quickspi_freeze(struct device *device) 788 + { 789 + struct pci_dev *pdev = to_pci_dev(device); 790 + struct quickspi_device *qsdev; 791 + int ret; 792 + 793 + qsdev = pci_get_drvdata(pdev); 794 + if (!qsdev) 795 + return -ENODEV; 796 + 797 + ret = thc_interrupt_quiesce(qsdev->thc_hw, true); 798 + if (ret) 799 + return ret; 800 + 801 + thc_interrupt_enable(qsdev->thc_hw, false); 802 + 803 + thc_dma_unconfigure(qsdev->thc_hw); 804 + 805 + return 0; 806 + } 807 + 808 + static int quickspi_thaw(struct device *device) 809 + { 810 + struct pci_dev *pdev = to_pci_dev(device); 811 + struct quickspi_device *qsdev; 812 + int ret; 813 + 814 + qsdev = pci_get_drvdata(pdev); 815 + if (!qsdev) 816 + return -ENODEV; 817 + 818 + ret = thc_dma_configure(qsdev->thc_hw); 819 + if (ret) 820 + return ret; 821 + 822 + thc_interrupt_enable(qsdev->thc_hw, true); 823 + 824 + ret = thc_interrupt_quiesce(qsdev->thc_hw, false); 825 + if (ret) 826 + return ret; 827 + 828 + return 0; 829 + } 830 + 831 + static int quickspi_poweroff(struct device *device) 832 + { 833 + struct pci_dev *pdev = to_pci_dev(device); 834 + struct quickspi_device *qsdev; 835 + int ret; 836 + 837 + qsdev = pci_get_drvdata(pdev); 838 + if (!qsdev) 839 + return -ENODEV; 840 + 841 + ret = thc_interrupt_quiesce(qsdev->thc_hw, true); 842 + if (ret) 843 + return ret; 844 + 845 + thc_interrupt_enable(qsdev->thc_hw, false); 846 + 847 + thc_ltr_unconfig(qsdev->thc_hw); 848 + 849 + quickspi_dma_deinit(qsdev); 850 + 851 + return 0; 852 + } 853 + 854 + static int quickspi_restore(struct device *device) 855 + { 856 + struct pci_dev *pdev = to_pci_dev(device); 857 + struct quickspi_device *qsdev; 858 + int ret; 859 + 860 + qsdev = pci_get_drvdata(pdev); 861 + if (!qsdev) 862 + return -ENODEV; 863 + 864 + ret = thc_interrupt_quiesce(qsdev->thc_hw, true); 865 + if (ret) 866 + return ret; 867 + 868 + /* Reconfig THC HW when back from hibernate */ 869 + ret = thc_port_select(qsdev->thc_hw, THC_PORT_TYPE_SPI); 870 + if (ret) 871 + return ret; 872 + 873 + thc_spi_input_output_address_config(qsdev->thc_hw, 874 + qsdev->input_report_hdr_addr, 875 + qsdev->input_report_bdy_addr, 876 + qsdev->output_report_addr); 877 + 878 + ret = thc_spi_read_config(qsdev->thc_hw, qsdev->spi_freq_val, 879 + qsdev->spi_read_io_mode, 880 + qsdev->spi_read_opcode, 881 + qsdev->spi_packet_size); 882 + if (ret) 883 + return ret; 884 + 885 + ret = thc_spi_write_config(qsdev->thc_hw, qsdev->spi_freq_val, 886 + qsdev->spi_write_io_mode, 887 + qsdev->spi_write_opcode, 888 + qsdev->spi_packet_size, 889 + qsdev->performance_limit); 890 + if (ret) 891 + return ret; 892 + 893 + thc_interrupt_config(qsdev->thc_hw); 894 + 895 + thc_interrupt_enable(qsdev->thc_hw, true); 896 + 897 + /* TIC may lose power, needs go through reset flow */ 898 + ret = reset_tic(qsdev); 899 + if (ret) 900 + return ret; 901 + 902 + ret = thc_dma_configure(qsdev->thc_hw); 903 + if (ret) 904 + return ret; 905 + 906 + thc_ltr_config(qsdev->thc_hw, 907 + qsdev->active_ltr_val, 908 + qsdev->low_power_ltr_val); 909 + 910 + thc_change_ltr_mode(qsdev->thc_hw, THC_LTR_MODE_ACTIVE); 911 + 912 + return 0; 913 + } 914 + 915 + static int quickspi_runtime_suspend(struct device *device) 916 + { 917 + struct pci_dev *pdev = to_pci_dev(device); 918 + struct quickspi_device *qsdev; 919 + 920 + qsdev = pci_get_drvdata(pdev); 921 + if (!qsdev) 922 + return -ENODEV; 923 + 924 + thc_change_ltr_mode(qsdev->thc_hw, THC_LTR_MODE_LP); 925 + 926 + pci_save_state(pdev); 927 + 928 + return 0; 929 + } 930 + 931 + static int quickspi_runtime_resume(struct device *device) 932 + { 933 + struct pci_dev *pdev = to_pci_dev(device); 934 + struct quickspi_device *qsdev; 935 + 936 + qsdev = pci_get_drvdata(pdev); 937 + if (!qsdev) 938 + return -ENODEV; 939 + 940 + thc_change_ltr_mode(qsdev->thc_hw, THC_LTR_MODE_ACTIVE); 941 + 942 + return 0; 943 + } 944 + 945 + static const struct dev_pm_ops quickspi_pm_ops = { 946 + .suspend = quickspi_suspend, 947 + .resume = quickspi_resume, 948 + .freeze = quickspi_freeze, 949 + .thaw = quickspi_thaw, 950 + .poweroff = quickspi_poweroff, 951 + .restore = quickspi_restore, 952 + .runtime_suspend = quickspi_runtime_suspend, 953 + .runtime_resume = quickspi_runtime_resume, 954 + .runtime_idle = NULL, 955 + }; 956 + 957 + static const struct pci_device_id quickspi_pci_tbl[] = { 958 + {PCI_DEVICE_DATA(INTEL, THC_MTL_DEVICE_ID_SPI_PORT1, &mtl), }, 959 + {PCI_DEVICE_DATA(INTEL, THC_MTL_DEVICE_ID_SPI_PORT2, &mtl), }, 960 + {PCI_DEVICE_DATA(INTEL, THC_LNL_DEVICE_ID_SPI_PORT1, &lnl), }, 961 + {PCI_DEVICE_DATA(INTEL, THC_LNL_DEVICE_ID_SPI_PORT2, &lnl), }, 962 + {PCI_DEVICE_DATA(INTEL, THC_PTL_H_DEVICE_ID_SPI_PORT1, &ptl), }, 963 + {PCI_DEVICE_DATA(INTEL, THC_PTL_H_DEVICE_ID_SPI_PORT2, &ptl), }, 964 + {PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_SPI_PORT1, &ptl), }, 965 + {PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_SPI_PORT2, &ptl), }, 966 + {} 967 + }; 968 + MODULE_DEVICE_TABLE(pci, quickspi_pci_tbl); 969 + 970 + static struct pci_driver quickspi_driver = { 971 + .name = KBUILD_MODNAME, 972 + .id_table = quickspi_pci_tbl, 973 + .probe = quickspi_probe, 974 + .remove = quickspi_remove, 975 + .shutdown = quickspi_shutdown, 976 + .driver.pm = &quickspi_pm_ops, 977 + .driver.probe_type = PROBE_PREFER_ASYNCHRONOUS, 978 + }; 979 + 980 + module_pci_driver(quickspi_driver); 981 + 982 + MODULE_AUTHOR("Xinpeng Sun <xinpeng.sun@intel.com>"); 983 + MODULE_AUTHOR("Even Xu <even.xu@intel.com>"); 984 + 985 + MODULE_DESCRIPTION("Intel(R) QuickSPI Driver"); 986 + MODULE_LICENSE("GPL"); 987 + MODULE_IMPORT_NS("INTEL_THC");
+172
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _QUICKSPI_DEV_H_ 5 + #define _QUICKSPI_DEV_H_ 6 + 7 + #include <linux/bits.h> 8 + #include <linux/hid-over-spi.h> 9 + #include <linux/sizes.h> 10 + #include <linux/wait.h> 11 + 12 + #include "quickspi-protocol.h" 13 + 14 + #define PCI_DEVICE_ID_INTEL_THC_MTL_DEVICE_ID_SPI_PORT1 0x7E49 15 + #define PCI_DEVICE_ID_INTEL_THC_MTL_DEVICE_ID_SPI_PORT2 0x7E4B 16 + #define PCI_DEVICE_ID_INTEL_THC_LNL_DEVICE_ID_SPI_PORT1 0xA849 17 + #define PCI_DEVICE_ID_INTEL_THC_LNL_DEVICE_ID_SPI_PORT2 0xA84B 18 + #define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_SPI_PORT1 0xE349 19 + #define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_SPI_PORT2 0xE34B 20 + #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_SPI_PORT1 0xE449 21 + #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_SPI_PORT2 0xE44B 22 + 23 + /* HIDSPI special ACPI parameters DSM methods */ 24 + #define ACPI_QUICKSPI_REVISION_NUM 2 25 + #define ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_HDR_ADDR 1 26 + #define ACPI_QUICKSPI_FUNC_NUM_INPUT_REP_BDY_ADDR 2 27 + #define ACPI_QUICKSPI_FUNC_NUM_OUTPUT_REP_ADDR 3 28 + #define ACPI_QUICKSPI_FUNC_NUM_READ_OPCODE 4 29 + #define ACPI_QUICKSPI_FUNC_NUM_WRITE_OPCODE 5 30 + #define ACPI_QUICKSPI_FUNC_NUM_IO_MODE 6 31 + 32 + /* QickSPI device special ACPI parameters DSM methods */ 33 + #define ACPI_QUICKSPI_FUNC_NUM_CONNECTION_SPEED 1 34 + #define ACPI_QUICKSPI_FUNC_NUM_LIMIT_PACKET_SIZE 2 35 + #define ACPI_QUICKSPI_FUNC_NUM_PERFORMANCE_LIMIT 3 36 + 37 + /* Platform special ACPI parameters DSM methods */ 38 + #define ACPI_QUICKSPI_FUNC_NUM_ACTIVE_LTR 1 39 + #define ACPI_QUICKSPI_FUNC_NUM_LP_LTR 2 40 + 41 + #define SPI_WRITE_IO_MODE BIT(13) 42 + #define SPI_IO_MODE_OPCODE GENMASK(15, 14) 43 + #define PERFORMANCE_LIMITATION GENMASK(15, 0) 44 + 45 + /* Packet size value, the unit is 16 bytes */ 46 + #define DEFAULT_MIN_PACKET_SIZE_VALUE 4 47 + #define MAX_PACKET_SIZE_VALUE_MTL 128 48 + #define MAX_PACKET_SIZE_VALUE_LNL 256 49 + 50 + /* 51 + * THC uses runtime auto suspend to dynamically switch between THC active LTR 52 + * and low power LTR to save CPU power. 53 + * Default value is 5000ms, that means if no touch event in this time, THC will 54 + * change to low power LTR mode. 55 + */ 56 + #define DEFAULT_AUTO_SUSPEND_DELAY_MS 5000 57 + 58 + enum quickspi_dev_state { 59 + QUICKSPI_NONE, 60 + QUICKSPI_RESETING, 61 + QUICKSPI_RESETED, 62 + QUICKSPI_INITED, 63 + QUICKSPI_ENABLED, 64 + QUICKSPI_DISABLED, 65 + }; 66 + 67 + /** 68 + * struct quickspi_driver_data - Driver specific data for quickspi device 69 + * @max_packet_size_value: identify max packet size, unit is 16 bytes 70 + */ 71 + struct quickspi_driver_data { 72 + u32 max_packet_size_value; 73 + }; 74 + 75 + struct device; 76 + struct pci_dev; 77 + struct thc_device; 78 + struct hid_device; 79 + struct acpi_device; 80 + 81 + /** 82 + * struct quickspi_device - THC QuickSpi device struct 83 + * @dev: point to kernel device 84 + * @pdev: point to PCI device 85 + * @thc_hw: point to THC device 86 + * @hid_dev: point to hid device 87 + * @acpi_dev: point to ACPI device 88 + * @driver_data: point to quickspi specific driver data 89 + * @state: THC SPI device state 90 + * @mem_addr: MMIO memory address 91 + * @dev_desc: device descriptor for HIDSPI protocol 92 + * @input_report_hdr_addr: device input report header address 93 + * @input_report_bdy_addr: device input report body address 94 + * @output_report_bdy_addr: device output report address 95 + * @spi_freq_val: device supported max SPI frequnecy, in Hz 96 + * @spi_read_io_mode: device supported SPI read io mode 97 + * @spi_write_io_mode: device supported SPI write io mode 98 + * @spi_read_opcode: device read opcode 99 + * @spi_write_opcode: device write opcode 100 + * @limit_packet_size: 1 - limit read/write packet to 64Bytes 101 + * 0 - device no packet size limiation for read/write 102 + * @performance_limit: delay time, in ms. 103 + * if device has performance limitation, must give a delay 104 + * before write operation after a read operation. 105 + * @active_ltr_val: THC active LTR value 106 + * @low_power_ltr_val: THC low power LTR value 107 + * @report_descriptor: store a copy of device report descriptor 108 + * @input_buf: store a copy of latest input report data 109 + * @report_buf: store a copy of latest input/output report packet from set/get feature 110 + * @report_len: the length of input/output report packet 111 + * @reset_ack_wq: workqueue for waiting reset response from device 112 + * @reset_ack: indicate reset response received or not 113 + * @nondma_int_received_wq: workqueue for waiting THC non-DMA interrupt 114 + * @nondma_int_received: indicate THC non-DMA interrupt received or not 115 + * @report_desc_got_wq: workqueue for waiting device report descriptor 116 + * @report_desc_got: indicate device report descritor received or not 117 + * @set_power_on_wq: workqueue for waiting set power on response from device 118 + * @set_power_on: indicate set power on response received or not 119 + * @get_feature_cmpl_wq: workqueue for waiting get feature response from device 120 + * @get_feature_cmpl: indicate get feature received or not 121 + * @set_feature_cmpl_wq: workqueue for waiting set feature to device 122 + * @set_feature_cmpl: indicate set feature send complete or not 123 + */ 124 + struct quickspi_device { 125 + struct device *dev; 126 + struct pci_dev *pdev; 127 + struct thc_device *thc_hw; 128 + struct hid_device *hid_dev; 129 + struct acpi_device *acpi_dev; 130 + struct quickspi_driver_data *driver_data; 131 + enum quickspi_dev_state state; 132 + 133 + void __iomem *mem_addr; 134 + 135 + struct hidspi_dev_descriptor dev_desc; 136 + u32 input_report_hdr_addr; 137 + u32 input_report_bdy_addr; 138 + u32 output_report_addr; 139 + u32 spi_freq_val; 140 + u32 spi_read_io_mode; 141 + u32 spi_write_io_mode; 142 + u32 spi_read_opcode; 143 + u32 spi_write_opcode; 144 + u32 limit_packet_size; 145 + u32 spi_packet_size; 146 + u32 performance_limit; 147 + 148 + u32 active_ltr_val; 149 + u32 low_power_ltr_val; 150 + 151 + u8 *report_descriptor; 152 + u8 *input_buf; 153 + u8 *report_buf; 154 + u32 report_len; 155 + 156 + wait_queue_head_t reset_ack_wq; 157 + bool reset_ack; 158 + 159 + wait_queue_head_t nondma_int_received_wq; 160 + bool nondma_int_received; 161 + 162 + wait_queue_head_t report_desc_got_wq; 163 + bool report_desc_got; 164 + 165 + wait_queue_head_t get_report_cmpl_wq; 166 + bool get_report_cmpl; 167 + 168 + wait_queue_head_t set_report_cmpl_wq; 169 + bool set_report_cmpl; 170 + }; 171 + 172 + #endif /* _QUICKSPI_DEV_H_ */
+165
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-hid.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #include <linux/hid.h> 5 + #include <linux/input.h> 6 + #include <linux/pm_runtime.h> 7 + 8 + #include "quickspi-dev.h" 9 + #include "quickspi-hid.h" 10 + 11 + /** 12 + * quickspi_hid_parse() - HID core parse() callback 13 + * 14 + * @hid: HID device instance 15 + * 16 + * This function gets called during call to hid_add_device 17 + * 18 + * Return: 0 on success and non zero on error. 19 + */ 20 + static int quickspi_hid_parse(struct hid_device *hid) 21 + { 22 + struct quickspi_device *qsdev = hid->driver_data; 23 + 24 + if (qsdev->report_descriptor) 25 + return hid_parse_report(hid, qsdev->report_descriptor, 26 + le16_to_cpu(qsdev->dev_desc.rep_desc_len)); 27 + 28 + dev_err(qsdev->dev, "invalid report descriptor\n"); 29 + return -EINVAL; 30 + } 31 + 32 + static int quickspi_hid_start(struct hid_device *hid) 33 + { 34 + return 0; 35 + } 36 + 37 + static void quickspi_hid_stop(struct hid_device *hid) 38 + { 39 + } 40 + 41 + static int quickspi_hid_open(struct hid_device *hid) 42 + { 43 + return 0; 44 + } 45 + 46 + static void quickspi_hid_close(struct hid_device *hid) 47 + { 48 + } 49 + 50 + static int quickspi_hid_raw_request(struct hid_device *hid, 51 + unsigned char reportnum, 52 + __u8 *buf, size_t len, 53 + unsigned char rtype, int reqtype) 54 + { 55 + struct quickspi_device *qsdev = hid->driver_data; 56 + int ret = 0; 57 + 58 + ret = pm_runtime_resume_and_get(qsdev->dev); 59 + if (ret) 60 + return ret; 61 + 62 + switch (reqtype) { 63 + case HID_REQ_GET_REPORT: 64 + ret = quickspi_get_report(qsdev, rtype, reportnum, buf); 65 + break; 66 + case HID_REQ_SET_REPORT: 67 + ret = quickspi_set_report(qsdev, rtype, reportnum, buf, len); 68 + break; 69 + default: 70 + dev_err_once(qsdev->dev, "Not supported request type %d\n", reqtype); 71 + break; 72 + } 73 + 74 + pm_runtime_mark_last_busy(qsdev->dev); 75 + pm_runtime_put_autosuspend(qsdev->dev); 76 + 77 + return ret; 78 + } 79 + 80 + static int quickspi_hid_power(struct hid_device *hid, int lvl) 81 + { 82 + return 0; 83 + } 84 + 85 + static struct hid_ll_driver quickspi_hid_ll_driver = { 86 + .parse = quickspi_hid_parse, 87 + .start = quickspi_hid_start, 88 + .stop = quickspi_hid_stop, 89 + .open = quickspi_hid_open, 90 + .close = quickspi_hid_close, 91 + .power = quickspi_hid_power, 92 + .raw_request = quickspi_hid_raw_request, 93 + }; 94 + 95 + /** 96 + * quickspi_hid_probe() - Register HID low level driver 97 + * 98 + * @qsdev: point to quickspi device 99 + * 100 + * This function is used to allocate and add HID device. 101 + * 102 + * Return: 0 on success, non zero on error. 103 + */ 104 + int quickspi_hid_probe(struct quickspi_device *qsdev) 105 + { 106 + struct hid_device *hid; 107 + int ret; 108 + 109 + hid = hid_allocate_device(); 110 + if (IS_ERR(hid)) 111 + return PTR_ERR(hid); 112 + 113 + hid->ll_driver = &quickspi_hid_ll_driver; 114 + hid->bus = BUS_PCI; 115 + hid->dev.parent = qsdev->dev; 116 + hid->driver_data = qsdev; 117 + hid->version = le16_to_cpu(qsdev->dev_desc.version_id); 118 + hid->vendor = le16_to_cpu(qsdev->dev_desc.vendor_id); 119 + hid->product = le16_to_cpu(qsdev->dev_desc.product_id); 120 + snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quickspi-hid", 121 + hid->vendor, hid->product); 122 + 123 + ret = hid_add_device(hid); 124 + if (ret) { 125 + hid_destroy_device(hid); 126 + return ret; 127 + } 128 + 129 + qsdev->hid_dev = hid; 130 + 131 + return 0; 132 + } 133 + 134 + /** 135 + * quickspi_hid_remove() - Destroy HID device 136 + * 137 + * @qsdev: point to quickspi device 138 + * 139 + * Return: 0 on success, non zero on error. 140 + */ 141 + void quickspi_hid_remove(struct quickspi_device *qsdev) 142 + { 143 + hid_destroy_device(qsdev->hid_dev); 144 + } 145 + 146 + /** 147 + * quickspi_hid_send_report() - Send HID input report data to HID core 148 + * 149 + * @qsdev: point to quickspi device 150 + * @data: point to input report data buffer 151 + * @data_len: the length of input report data 152 + * 153 + * Return: 0 on success, non zero on error. 154 + */ 155 + int quickspi_hid_send_report(struct quickspi_device *qsdev, 156 + void *data, size_t data_len) 157 + { 158 + int ret; 159 + 160 + ret = hid_input_report(qsdev->hid_dev, HID_INPUT_REPORT, data, data_len, 1); 161 + if (ret) 162 + dev_err(qsdev->dev, "Failed to send HID input report, ret = %d.\n", ret); 163 + 164 + return ret; 165 + }
+14
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-hid.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _QUICKSPI_HID_H_ 5 + #define _QUICKSPI_HID_H_ 6 + 7 + struct quickspi_device; 8 + 9 + int quickspi_hid_send_report(struct quickspi_device *qsdev, 10 + void *data, size_t data_size); 11 + int quickspi_hid_probe(struct quickspi_device *qsdev); 12 + void quickspi_hid_remove(struct quickspi_device *qsdev); 13 + 14 + #endif /* _QUICKSPI_HID_H_ */
+414
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright © 2024 Intel Corporation */ 3 + 4 + #include <linux/acpi.h> 5 + #include <linux/bitfield.h> 6 + #include <linux/delay.h> 7 + #include <linux/hid.h> 8 + 9 + #include "intel-thc-dev.h" 10 + #include "intel-thc-dma.h" 11 + 12 + #include "quickspi-dev.h" 13 + #include "quickspi-hid.h" 14 + #include "quickspi-protocol.h" 15 + 16 + /* THC uses HW to accelerate HID over SPI protocol, THC_M_PRT_DEV_INT_CAUSE 17 + * register is used to store message header and body header, below definition 18 + * let driver retrieve needed data filed easier from THC_M_PRT_DEV_INT_CAUSE 19 + * register. 20 + */ 21 + #define HIDSPI_IN_REP_BDY_HDR_REP_TYPE GENMASK(7, 0) 22 + 23 + static int write_cmd_to_txdma(struct quickspi_device *qsdev, 24 + int report_type, int report_id, 25 + u8 *report_buf, const int report_buf_len) 26 + { 27 + struct output_report *write_buf; 28 + int write_buf_len; 29 + int ret; 30 + 31 + write_buf = (struct output_report *)qsdev->report_buf; 32 + 33 + write_buf->output_hdr.report_type = report_type; 34 + write_buf->output_hdr.content_len = cpu_to_le16(report_buf_len); 35 + write_buf->output_hdr.content_id = report_id; 36 + 37 + if (report_buf && report_buf_len > 0) 38 + memcpy(write_buf->content, report_buf, report_buf_len); 39 + 40 + write_buf_len = HIDSPI_OUTPUT_REPORT_SIZE(report_buf_len); 41 + 42 + ret = thc_dma_write(qsdev->thc_hw, write_buf, write_buf_len); 43 + if (ret) 44 + dev_err_once(qsdev->dev, "DMA write failed, ret = %d\n", ret); 45 + 46 + return ret; 47 + } 48 + 49 + static int quickspi_get_device_descriptor(struct quickspi_device *qsdev) 50 + { 51 + u8 read_buf[HIDSPI_INPUT_DEVICE_DESCRIPTOR_SIZE]; 52 + struct output_report output_rep; 53 + u32 input_len, read_len = 0; 54 + u32 int_cause_val; 55 + u8 input_rep_type; 56 + int ret; 57 + 58 + output_rep.output_hdr.report_type = DEVICE_DESCRIPTOR; 59 + output_rep.output_hdr.content_len = 0; 60 + output_rep.output_hdr.content_id = 0; 61 + 62 + qsdev->nondma_int_received = false; 63 + 64 + ret = thc_tic_pio_write(qsdev->thc_hw, qsdev->output_report_addr, 65 + HIDSPI_OUTPUT_REPORT_SIZE(0), (u32 *)&output_rep); 66 + if (ret) { 67 + dev_err_once(qsdev->dev, 68 + "Write DEVICE_DESCRIPTOR command failed, ret = %d\n", ret); 69 + return ret; 70 + } 71 + 72 + ret = wait_event_interruptible_timeout(qsdev->nondma_int_received_wq, 73 + qsdev->nondma_int_received, 74 + QUICKSPI_ACK_WAIT_TIMEOUT * HZ); 75 + if (ret <= 0 || !qsdev->nondma_int_received) { 76 + dev_err_once(qsdev->dev, "Wait DEVICE_DESCRIPTOR timeout, ret:%d\n", ret); 77 + return -ETIMEDOUT; 78 + } 79 + qsdev->nondma_int_received = false; 80 + 81 + int_cause_val = thc_int_cause_read(qsdev->thc_hw); 82 + input_len = FIELD_GET(HIDSPI_INPUT_HEADER_REPORT_LEN, int_cause_val); 83 + 84 + input_len = input_len * sizeof(u32); 85 + if (input_len != HIDSPI_INPUT_DEVICE_DESCRIPTOR_SIZE) { 86 + dev_err_once(qsdev->dev, "Receive wrong DEVICE_DESCRIPTOR length, len = %u\n", 87 + input_len); 88 + return -EINVAL; 89 + } 90 + 91 + ret = thc_tic_pio_read(qsdev->thc_hw, qsdev->input_report_bdy_addr, 92 + input_len, &read_len, (u32 *)read_buf); 93 + if (ret || read_len != input_len) { 94 + dev_err_once(qsdev->dev, "Read DEVICE_DESCRIPTOR failed, ret = %d\n", ret); 95 + dev_err_once(qsdev->dev, "DEVICE_DESCRIPTOR expected len = %u, actual read = %u\n", 96 + input_len, read_len); 97 + return ret; 98 + } 99 + 100 + input_rep_type = ((struct input_report_body_header *)read_buf)->input_report_type; 101 + 102 + if (input_rep_type == DEVICE_DESCRIPTOR_RESPONSE) { 103 + memcpy(&qsdev->dev_desc, 104 + read_buf + HIDSPI_INPUT_BODY_HEADER_SIZE, 105 + HIDSPI_DEVICE_DESCRIPTOR_SIZE); 106 + 107 + return 0; 108 + } 109 + 110 + dev_err_once(qsdev->dev, "Unexpected intput report type: %d\n", input_rep_type); 111 + return -EINVAL; 112 + } 113 + 114 + int quickspi_get_report_descriptor(struct quickspi_device *qsdev) 115 + { 116 + int ret; 117 + 118 + ret = write_cmd_to_txdma(qsdev, REPORT_DESCRIPTOR, 0, NULL, 0); 119 + if (ret) { 120 + dev_err_once(qsdev->dev, 121 + "Write REPORT_DESCRIPTOR command failed, ret = %d\n", ret); 122 + return ret; 123 + } 124 + 125 + ret = wait_event_interruptible_timeout(qsdev->report_desc_got_wq, 126 + qsdev->report_desc_got, 127 + QUICKSPI_ACK_WAIT_TIMEOUT * HZ); 128 + if (ret <= 0 || !qsdev->report_desc_got) { 129 + dev_err_once(qsdev->dev, "Wait Report Descriptor timeout, ret:%d\n", ret); 130 + return -ETIMEDOUT; 131 + } 132 + qsdev->report_desc_got = false; 133 + 134 + return 0; 135 + } 136 + 137 + int quickspi_set_power(struct quickspi_device *qsdev, 138 + enum hidspi_power_state power_state) 139 + { 140 + u8 cmd_content = power_state; 141 + int ret; 142 + 143 + ret = write_cmd_to_txdma(qsdev, COMMAND_CONTENT, 144 + HIDSPI_SET_POWER_CMD_ID, 145 + &cmd_content, 146 + sizeof(cmd_content)); 147 + if (ret) { 148 + dev_err_once(qsdev->dev, "Write SET_POWER command failed, ret = %d\n", ret); 149 + return ret; 150 + } 151 + 152 + return 0; 153 + } 154 + 155 + void quickspi_handle_input_data(struct quickspi_device *qsdev, u32 buf_len) 156 + { 157 + struct input_report_body_header *body_hdr; 158 + struct input_report_body *input_body; 159 + u8 *input_report; 160 + u32 input_len; 161 + int ret = 0; 162 + 163 + input_body = (struct input_report_body *)qsdev->input_buf; 164 + body_hdr = &input_body->body_hdr; 165 + input_len = le16_to_cpu(body_hdr->content_len); 166 + 167 + if (HIDSPI_INPUT_BODY_SIZE(input_len) > buf_len) { 168 + dev_err_once(qsdev->dev, "Wrong input report length: %u", 169 + input_len); 170 + return; 171 + } 172 + 173 + switch (body_hdr->input_report_type) { 174 + case REPORT_DESCRIPTOR_RESPONSE: 175 + if (input_len != le16_to_cpu(qsdev->dev_desc.rep_desc_len)) { 176 + dev_err_once(qsdev->dev, "Unexpected report descriptor length: %u\n", 177 + input_len); 178 + return; 179 + } 180 + 181 + memcpy(qsdev->report_descriptor, input_body->content, input_len); 182 + 183 + qsdev->report_desc_got = true; 184 + wake_up_interruptible(&qsdev->report_desc_got_wq); 185 + 186 + break; 187 + 188 + case COMMAND_RESPONSE: 189 + if (body_hdr->content_id == HIDSPI_SET_POWER_CMD_ID) { 190 + dev_dbg(qsdev->dev, "Receive set power on response\n"); 191 + } else { 192 + dev_err_once(qsdev->dev, "Unknown command response type: %u\n", 193 + body_hdr->content_id); 194 + } 195 + 196 + break; 197 + 198 + case RESET_RESPONSE: 199 + if (qsdev->state == QUICKSPI_RESETING) { 200 + qsdev->reset_ack = true; 201 + wake_up_interruptible(&qsdev->reset_ack_wq); 202 + dev_dbg(qsdev->dev, "Receive HIR reset response\n"); 203 + } else { 204 + dev_info(qsdev->dev, "Receive DIR\n"); 205 + } 206 + break; 207 + 208 + case GET_FEATURE_RESPONSE: 209 + case GET_INPUT_REPORT_RESPONSE: 210 + qsdev->report_len = sizeof(body_hdr->content_id) + input_len; 211 + input_report = input_body->content - sizeof(body_hdr->content_id); 212 + 213 + memcpy(qsdev->report_buf, input_report, qsdev->report_len); 214 + 215 + qsdev->get_report_cmpl = true; 216 + wake_up_interruptible(&qsdev->get_report_cmpl_wq); 217 + 218 + break; 219 + 220 + case SET_FEATURE_RESPONSE: 221 + case OUTPUT_REPORT_RESPONSE: 222 + qsdev->set_report_cmpl = true; 223 + wake_up_interruptible(&qsdev->set_report_cmpl_wq); 224 + 225 + break; 226 + 227 + case DATA: 228 + if (qsdev->state != QUICKSPI_ENABLED) 229 + return; 230 + 231 + if (input_len > le16_to_cpu(qsdev->dev_desc.max_input_len)) { 232 + dev_err_once(qsdev->dev, "Unexpected too large input report length: %u\n", 233 + input_len); 234 + return; 235 + } 236 + 237 + input_len = sizeof(body_hdr->content_id) + input_len; 238 + input_report = input_body->content - sizeof(body_hdr->content_id); 239 + 240 + ret = quickspi_hid_send_report(qsdev, input_report, input_len); 241 + if (ret) 242 + dev_err_once(qsdev->dev, "Failed to send HID input report: %d\n", ret); 243 + 244 + break; 245 + 246 + default: 247 + dev_err_once(qsdev->dev, "Unsupported input report type: %u\n", 248 + body_hdr->input_report_type); 249 + break; 250 + } 251 + } 252 + 253 + static int acpi_tic_reset(struct quickspi_device *qsdev) 254 + { 255 + acpi_status status = 0; 256 + acpi_handle handle; 257 + 258 + if (!qsdev->acpi_dev) 259 + return -ENODEV; 260 + 261 + handle = acpi_device_handle(qsdev->acpi_dev); 262 + status = acpi_execute_simple_method(handle, "_RST", 0); 263 + if (ACPI_FAILURE(status)) { 264 + dev_err_once(qsdev->dev, 265 + "Failed to reset device through ACPI method, ret = %d\n", status); 266 + return -EIO; 267 + } 268 + 269 + return 0; 270 + } 271 + 272 + int reset_tic(struct quickspi_device *qsdev) 273 + { 274 + u32 actual_read_len, read_len = 0; 275 + u32 input_report_len, reset_response, int_cause_val; 276 + u8 input_rep_type; 277 + int ret; 278 + 279 + qsdev->state = QUICKSPI_RESETING; 280 + 281 + qsdev->reset_ack = false; 282 + 283 + /* First interrupt uses level trigger to avoid missing interrupt */ 284 + thc_int_trigger_type_select(qsdev->thc_hw, false); 285 + 286 + ret = acpi_tic_reset(qsdev); 287 + if (ret) 288 + return ret; 289 + 290 + ret = thc_interrupt_quiesce(qsdev->thc_hw, false); 291 + if (ret) 292 + return ret; 293 + 294 + ret = wait_event_interruptible_timeout(qsdev->reset_ack_wq, 295 + qsdev->reset_ack, 296 + QUICKSPI_ACK_WAIT_TIMEOUT * HZ); 297 + if (ret <= 0 || !qsdev->reset_ack) { 298 + dev_err_once(qsdev->dev, "Wait RESET_RESPONSE timeout, ret:%d\n", ret); 299 + return -ETIMEDOUT; 300 + } 301 + 302 + int_cause_val = thc_int_cause_read(qsdev->thc_hw); 303 + input_report_len = FIELD_GET(HIDSPI_INPUT_HEADER_REPORT_LEN, int_cause_val); 304 + 305 + read_len = input_report_len * sizeof(u32); 306 + if (read_len != HIDSPI_INPUT_BODY_SIZE(0)) { 307 + dev_err_once(qsdev->dev, "Receive wrong RESET_RESPONSE, len = %u\n", 308 + read_len); 309 + return -EINVAL; 310 + } 311 + 312 + /* Switch to edge trigger matching with HIDSPI protocol definition */ 313 + thc_int_trigger_type_select(qsdev->thc_hw, true); 314 + 315 + ret = thc_tic_pio_read(qsdev->thc_hw, qsdev->input_report_bdy_addr, 316 + read_len, &actual_read_len, 317 + (u32 *)&reset_response); 318 + if (ret || actual_read_len != read_len) { 319 + dev_err_once(qsdev->dev, "Read RESET_RESPONSE body failed, ret = %d\n", ret); 320 + dev_err_once(qsdev->dev, "RESET_RESPONSE body expected len = %u, actual = %u\n", 321 + read_len, actual_read_len); 322 + return ret; 323 + } 324 + 325 + input_rep_type = FIELD_GET(HIDSPI_IN_REP_BDY_HDR_REP_TYPE, reset_response); 326 + 327 + if (input_rep_type == RESET_RESPONSE) { 328 + dev_dbg(qsdev->dev, "RESET_RESPONSE received\n"); 329 + } else { 330 + dev_err_once(qsdev->dev, 331 + "Unexpected input report type: %d, expect RESET_RESPONSE\n", 332 + input_rep_type); 333 + return -EINVAL; 334 + } 335 + 336 + qsdev->state = QUICKSPI_RESETED; 337 + 338 + ret = quickspi_get_device_descriptor(qsdev); 339 + if (ret) 340 + return ret; 341 + 342 + return 0; 343 + } 344 + 345 + int quickspi_get_report(struct quickspi_device *qsdev, 346 + u8 report_type, unsigned int report_id, void *buf) 347 + { 348 + int rep_type; 349 + int ret; 350 + 351 + if (report_type == HID_INPUT_REPORT) { 352 + rep_type = GET_INPUT_REPORT; 353 + } else if (report_type == HID_FEATURE_REPORT) { 354 + rep_type = GET_FEATURE; 355 + } else { 356 + dev_err_once(qsdev->dev, "Unsupported report type for GET REPORT: %d\n", 357 + report_type); 358 + return -EINVAL; 359 + } 360 + 361 + ret = write_cmd_to_txdma(qsdev, rep_type, report_id, NULL, 0); 362 + if (ret) { 363 + dev_err_once(qsdev->dev, "Write GET_REPORT command failed, ret = %d\n", ret); 364 + return ret; 365 + } 366 + 367 + ret = wait_event_interruptible_timeout(qsdev->get_report_cmpl_wq, 368 + qsdev->get_report_cmpl, 369 + QUICKSPI_ACK_WAIT_TIMEOUT * HZ); 370 + if (ret <= 0 || !qsdev->get_report_cmpl) { 371 + dev_err_once(qsdev->dev, "Wait Get Report Response timeout, ret:%d\n", ret); 372 + return -ETIMEDOUT; 373 + } 374 + qsdev->get_report_cmpl = false; 375 + 376 + memcpy(buf, qsdev->report_buf, qsdev->report_len); 377 + 378 + return qsdev->report_len; 379 + } 380 + 381 + int quickspi_set_report(struct quickspi_device *qsdev, 382 + u8 report_type, unsigned int report_id, 383 + void *buf, u32 buf_len) 384 + { 385 + int rep_type; 386 + int ret; 387 + 388 + if (report_type == HID_OUTPUT_REPORT) { 389 + rep_type = OUTPUT_REPORT; 390 + } else if (report_type == HID_FEATURE_REPORT) { 391 + rep_type = SET_FEATURE; 392 + } else { 393 + dev_err_once(qsdev->dev, "Unsupported report type for SET REPORT: %d\n", 394 + report_type); 395 + return -EINVAL; 396 + } 397 + 398 + ret = write_cmd_to_txdma(qsdev, rep_type, report_id, buf + 1, buf_len - 1); 399 + if (ret) { 400 + dev_err_once(qsdev->dev, "Write SET_REPORT command failed, ret = %d\n", ret); 401 + return ret; 402 + } 403 + 404 + ret = wait_event_interruptible_timeout(qsdev->set_report_cmpl_wq, 405 + qsdev->set_report_cmpl, 406 + QUICKSPI_ACK_WAIT_TIMEOUT * HZ); 407 + if (ret <= 0 || !qsdev->set_report_cmpl) { 408 + dev_err_once(qsdev->dev, "Wait Set Report Response timeout, ret:%d\n", ret); 409 + return -ETIMEDOUT; 410 + } 411 + qsdev->set_report_cmpl = false; 412 + 413 + return buf_len; 414 + }
+25
drivers/hid/intel-thc-hid/intel-quickspi/quickspi-protocol.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _QUICKSPI_PROTOCOL_H_ 5 + #define _QUICKSPI_PROTOCOL_H_ 6 + 7 + #include <linux/hid-over-spi.h> 8 + 9 + #define QUICKSPI_ACK_WAIT_TIMEOUT 5 10 + 11 + struct quickspi_device; 12 + 13 + void quickspi_handle_input_data(struct quickspi_device *qsdev, u32 buf_len); 14 + int quickspi_get_report(struct quickspi_device *qsdev, u8 report_type, 15 + unsigned int report_id, void *buf); 16 + int quickspi_set_report(struct quickspi_device *qsdev, u8 report_type, 17 + unsigned int report_id, void *buf, u32 buf_len); 18 + int quickspi_get_report_descriptor(struct quickspi_device *qsdev); 19 + 20 + int quickspi_set_power(struct quickspi_device *qsdev, 21 + enum hidspi_power_state power_state); 22 + 23 + int reset_tic(struct quickspi_device *qsdev); 24 + 25 + #endif /* _QUICKSPI_PROTOCOL_H_ */
+1578
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #include <linux/bitfield.h> 5 + #include <linux/regmap.h> 6 + 7 + #include "intel-thc-dev.h" 8 + #include "intel-thc-hw.h" 9 + 10 + static int thc_regmap_read(void *context, unsigned int reg, 11 + unsigned int *val) 12 + { 13 + struct thc_device *thc_ctx = context; 14 + void __iomem *base = thc_ctx->mmio_addr; 15 + 16 + *val = ioread32(base + reg); 17 + return 0; 18 + } 19 + 20 + static int thc_regmap_write(void *context, unsigned int reg, 21 + unsigned int val) 22 + { 23 + struct thc_device *thc_ctx = context; 24 + void __iomem *base = thc_ctx->mmio_addr; 25 + 26 + iowrite32(val, base + reg); 27 + return 0; 28 + } 29 + 30 + static const struct regmap_range thc_rw_ranges[] = { 31 + regmap_reg_range(0x10, 0x14), 32 + regmap_reg_range(0x1000, 0x1320), 33 + }; 34 + 35 + static const struct regmap_access_table thc_rw_table = { 36 + .yes_ranges = thc_rw_ranges, 37 + .n_yes_ranges = ARRAY_SIZE(thc_rw_ranges), 38 + }; 39 + 40 + static const struct regmap_config thc_regmap_cfg = { 41 + .name = "thc_regmap_common", 42 + .reg_bits = 32, 43 + .val_bits = 32, 44 + .reg_stride = 4, 45 + .max_register = 0x1320, 46 + .reg_read = thc_regmap_read, 47 + .reg_write = thc_regmap_write, 48 + .cache_type = REGCACHE_NONE, 49 + .fast_io = true, 50 + .rd_table = &thc_rw_table, 51 + .wr_table = &thc_rw_table, 52 + .volatile_table = &thc_rw_table, 53 + }; 54 + 55 + /** 56 + * thc_clear_state - Clear THC hardware state 57 + * 58 + * @dev: The pointer of THC device structure 59 + */ 60 + static void thc_clear_state(const struct thc_device *dev) 61 + { 62 + u32 val; 63 + 64 + /* Clear interrupt cause register */ 65 + val = THC_M_PRT_ERR_CAUSE_INVLD_DEV_ENTRY | 66 + THC_M_PRT_ERR_CAUSE_FRAME_BABBLE_ERR | 67 + THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR | 68 + THC_M_PRT_ERR_CAUSE_PRD_ENTRY_ERR; 69 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_ERR_CAUSE_OFFSET, val, val); 70 + 71 + /* Clear interrupt error state */ 72 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 73 + THC_M_PRT_READ_DMA_CNTRL_IE_STALL, 74 + THC_M_PRT_READ_DMA_CNTRL_IE_STALL); 75 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET, 76 + THC_M_PRT_READ_DMA_CNTRL_IE_STALL, 77 + THC_M_PRT_READ_DMA_CNTRL_IE_STALL); 78 + 79 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 80 + THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS, 81 + THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS); 82 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 83 + THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS, 84 + THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS); 85 + 86 + val = THC_M_PRT_INT_EN_TXN_ERR_INT_EN | 87 + THC_M_PRT_INT_EN_FATAL_ERR_INT_EN | 88 + THC_M_PRT_INT_EN_BUF_OVRRUN_ERR_INT_EN; 89 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_EN_OFFSET, val, val); 90 + 91 + val = THC_M_PRT_SW_SEQ_STS_THC_SS_ERR | 92 + THC_M_PRT_SW_SEQ_STS_TSSDONE; 93 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, val, val); 94 + 95 + /* Clear RxDMA state */ 96 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 97 + THC_M_PRT_READ_DMA_CNTRL_IE_EOF, 0); 98 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET, 99 + THC_M_PRT_READ_DMA_CNTRL_IE_EOF, 0); 100 + 101 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, 102 + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS, 103 + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS); 104 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_2_OFFSET, 105 + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS, 106 + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS); 107 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, 108 + THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS, 109 + THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS); 110 + 111 + /* Clear TxDMA state */ 112 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_DMA_CNTRL_OFFSET, 113 + THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL, 114 + THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL); 115 + 116 + val = THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ERROR_STS | 117 + THC_M_PRT_WRITE_INT_STS_THC_WRDMA_IOC_STS | 118 + THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS; 119 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_INT_STS_OFFSET, val, val); 120 + 121 + /* Reset all DMAs count */ 122 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_DB_CNT_1_OFFSET, 123 + THC_M_PRT_DB_CNT_1_THC_M_PRT_DB_CNT_RST, 124 + THC_M_PRT_DB_CNT_1_THC_M_PRT_DB_CNT_RST); 125 + 126 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_DEVINT_CNT_OFFSET, 127 + THC_M_PRT_DEVINT_CNT_THC_M_PRT_DEVINT_CNT_RST, 128 + THC_M_PRT_DEVINT_CNT_THC_M_PRT_DEVINT_CNT_RST); 129 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 130 + THC_M_PRT_READ_DMA_CNTRL_TPCPR, 131 + THC_M_PRT_READ_DMA_CNTRL_TPCPR); 132 + 133 + /* Reset THC hardware sequence state */ 134 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRAME_DROP_CNT_1_OFFSET, 135 + THC_M_PRT_FRAME_DROP_CNT_1_RFDC, 136 + THC_M_PRT_FRAME_DROP_CNT_1_RFDC); 137 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRAME_DROP_CNT_2_OFFSET, 138 + THC_M_PRT_FRAME_DROP_CNT_2_RFDC, 139 + THC_M_PRT_FRAME_DROP_CNT_2_RFDC); 140 + 141 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRM_CNT_1_OFFSET, 142 + THC_M_PRT_FRM_CNT_1_THC_M_PRT_FRM_CNT_RST, 143 + THC_M_PRT_FRM_CNT_1_THC_M_PRT_FRM_CNT_RST); 144 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRM_CNT_2_OFFSET, 145 + THC_M_PRT_FRM_CNT_2_THC_M_PRT_FRM_CNT_RST, 146 + THC_M_PRT_FRM_CNT_2_THC_M_PRT_FRM_CNT_RST); 147 + 148 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_RXDMA_PKT_CNT_1_OFFSET, 149 + THC_M_PRT_RXDMA_PKT_CNT_1_THC_M_PRT_RXDMA_PKT_CNT_RST, 150 + THC_M_PRT_RXDMA_PKT_CNT_1_THC_M_PRT_RXDMA_PKT_CNT_RST); 151 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_RXDMA_PKT_CNT_2_OFFSET, 152 + THC_M_PRT_RXDMA_PKT_CNT_2_THC_M_PRT_RXDMA_PKT_CNT_RST, 153 + THC_M_PRT_RXDMA_PKT_CNT_2_THC_M_PRT_RXDMA_PKT_CNT_RST); 154 + 155 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SWINT_CNT_1_OFFSET, 156 + THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST, 157 + THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST); 158 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SWINT_CNT_1_OFFSET, 159 + THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST, 160 + THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST); 161 + 162 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_TX_FRM_CNT_OFFSET, 163 + THC_M_PRT_TX_FRM_CNT_THC_M_PRT_TX_FRM_CNT_RST, 164 + THC_M_PRT_TX_FRM_CNT_THC_M_PRT_TX_FRM_CNT_RST); 165 + 166 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_TXDMA_PKT_CNT_OFFSET, 167 + THC_M_PRT_TXDMA_PKT_CNT_THC_M_PRT_TXDMA_PKT_CNT_RST, 168 + THC_M_PRT_TXDMA_PKT_CNT_THC_M_PRT_TXDMA_PKT_CNT_RST); 169 + 170 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_UFRM_CNT_1_OFFSET, 171 + THC_M_PRT_UFRM_CNT_1_THC_M_PRT_UFRM_CNT_RST, 172 + THC_M_PRT_UFRM_CNT_1_THC_M_PRT_UFRM_CNT_RST); 173 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_UFRM_CNT_2_OFFSET, 174 + THC_M_PRT_UFRM_CNT_2_THC_M_PRT_UFRM_CNT_RST, 175 + THC_M_PRT_UFRM_CNT_2_THC_M_PRT_UFRM_CNT_RST); 176 + 177 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_PRD_EMPTY_CNT_1_OFFSET, 178 + THC_M_PRT_PRD_EMPTY_CNT_1_RPTEC, 179 + THC_M_PRT_PRD_EMPTY_CNT_1_RPTEC); 180 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_PRD_EMPTY_CNT_2_OFFSET, 181 + THC_M_PRT_PRD_EMPTY_CNT_2_RPTEC, 182 + THC_M_PRT_PRD_EMPTY_CNT_2_RPTEC); 183 + } 184 + 185 + /** 186 + * thc_dev_init - Allocate and initialize the THC device structure 187 + * 188 + * @device: The pointer of device structure 189 + * @mem_addr: The pointer of MMIO memory address 190 + * 191 + * Return: The thc_device pointer on success, NULL on failed. 192 + */ 193 + struct thc_device *thc_dev_init(struct device *device, void __iomem *mem_addr) 194 + { 195 + struct thc_device *thc_dev; 196 + int ret; 197 + 198 + thc_dev = devm_kzalloc(device, sizeof(*thc_dev), GFP_KERNEL); 199 + if (!thc_dev) 200 + return ERR_PTR(-ENOMEM); 201 + 202 + thc_dev->dev = device; 203 + thc_dev->mmio_addr = mem_addr; 204 + thc_dev->thc_regmap = devm_regmap_init(device, NULL, thc_dev, &thc_regmap_cfg); 205 + if (IS_ERR(thc_dev->thc_regmap)) { 206 + ret = PTR_ERR(thc_dev->thc_regmap); 207 + dev_err_once(device, "Failed to init thc_regmap: %d\n", ret); 208 + return ERR_PTR(ret); 209 + } 210 + 211 + thc_clear_state(thc_dev); 212 + 213 + mutex_init(&thc_dev->thc_bus_lock); 214 + init_waitqueue_head(&thc_dev->write_complete_wait); 215 + init_waitqueue_head(&thc_dev->swdma_complete_wait); 216 + 217 + thc_dev->dma_ctx = thc_dma_init(thc_dev); 218 + if (!thc_dev->dma_ctx) { 219 + dev_err_once(device, "DMA context init failed\n"); 220 + return ERR_PTR(-ENOMEM); 221 + } 222 + 223 + return thc_dev; 224 + } 225 + EXPORT_SYMBOL_NS_GPL(thc_dev_init, "INTEL_THC"); 226 + 227 + static int prepare_pio(const struct thc_device *dev, const u8 pio_op, 228 + const u32 address, const u32 size) 229 + { 230 + u32 sts, ctrl, addr, mask; 231 + 232 + regmap_read(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, &sts); 233 + 234 + /* Check if THC previous PIO still in progress */ 235 + if (sts & THC_M_PRT_SW_SEQ_STS_THC_SS_CIP) { 236 + dev_err_once(dev->dev, "THC PIO is still busy!\n"); 237 + return -EBUSY; 238 + } 239 + 240 + /* Clear error bit and complete bit in state register */ 241 + sts |= THC_M_PRT_SW_SEQ_STS_THC_SS_ERR | 242 + THC_M_PRT_SW_SEQ_STS_TSSDONE; 243 + regmap_write(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, sts); 244 + 245 + /* Set PIO data size, opcode and interrupt capability */ 246 + ctrl = FIELD_PREP(THC_M_PRT_SW_SEQ_CNTRL_THC_SS_BC, size) | 247 + FIELD_PREP(THC_M_PRT_SW_SEQ_CNTRL_THC_SS_CMD, pio_op); 248 + if (dev->pio_int_supported) 249 + ctrl |= THC_M_PRT_SW_SEQ_CNTRL_THC_SS_CD_IE; 250 + 251 + mask = THC_M_PRT_SW_SEQ_CNTRL_THC_SS_BC | 252 + THC_M_PRT_SW_SEQ_CNTRL_THC_SS_CMD | 253 + THC_M_PRT_SW_SEQ_CNTRL_THC_SS_CD_IE; 254 + regmap_write_bits(dev->thc_regmap, 255 + THC_M_PRT_SW_SEQ_CNTRL_OFFSET, mask, ctrl); 256 + 257 + /* Set PIO target address */ 258 + addr = FIELD_PREP(THC_M_PRT_SW_SEQ_DATA0_ADDR_THC_SW_SEQ_DATA0_ADDR, address); 259 + mask = THC_M_PRT_SW_SEQ_DATA0_ADDR_THC_SW_SEQ_DATA0_ADDR; 260 + regmap_write_bits(dev->thc_regmap, 261 + THC_M_PRT_SW_SEQ_DATA0_ADDR_OFFSET, mask, addr); 262 + return 0; 263 + } 264 + 265 + static void pio_start(const struct thc_device *dev, 266 + u32 size_in_bytes, const u32 *buffer) 267 + { 268 + if (size_in_bytes && buffer) 269 + regmap_bulk_write(dev->thc_regmap, THC_M_PRT_SW_SEQ_DATA1_OFFSET, 270 + buffer, size_in_bytes / sizeof(u32)); 271 + 272 + /* Enable Start bit */ 273 + regmap_write_bits(dev->thc_regmap, 274 + THC_M_PRT_SW_SEQ_CNTRL_OFFSET, 275 + THC_M_PRT_SW_SEQ_CNTRL_TSSGO, 276 + THC_M_PRT_SW_SEQ_CNTRL_TSSGO); 277 + } 278 + 279 + static int pio_complete(const struct thc_device *dev, 280 + u32 *buffer, u32 *size) 281 + { 282 + u32 sts, ctrl; 283 + 284 + regmap_read(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, &sts); 285 + if (sts & THC_M_PRT_SW_SEQ_STS_THC_SS_ERR) { 286 + dev_err_once(dev->dev, "PIO operation error\n"); 287 + return -EBUSY; 288 + } 289 + 290 + if (buffer && size) { 291 + regmap_read(dev->thc_regmap, THC_M_PRT_SW_SEQ_CNTRL_OFFSET, &ctrl); 292 + *size = FIELD_GET(THC_M_PRT_SW_SEQ_CNTRL_THC_SS_BC, ctrl); 293 + 294 + regmap_bulk_read(dev->thc_regmap, THC_M_PRT_SW_SEQ_DATA1_OFFSET, 295 + buffer, *size / sizeof(u32)); 296 + } 297 + 298 + sts |= THC_M_PRT_SW_SEQ_STS_THC_SS_ERR | THC_M_PRT_SW_SEQ_STS_TSSDONE; 299 + regmap_write(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, sts); 300 + return 0; 301 + } 302 + 303 + static int pio_wait(const struct thc_device *dev) 304 + { 305 + u32 sts = 0; 306 + int ret; 307 + 308 + ret = regmap_read_poll_timeout(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, sts, 309 + !(sts & THC_M_PRT_SW_SEQ_STS_THC_SS_CIP || 310 + !(sts & THC_M_PRT_SW_SEQ_STS_TSSDONE)), 311 + THC_REGMAP_POLLING_INTERVAL_US, THC_PIO_DONE_TIMEOUT_US); 312 + if (ret) 313 + dev_err_once(dev->dev, "Timeout while polling PIO operation done\n"); 314 + 315 + return ret; 316 + } 317 + 318 + /** 319 + * thc_tic_pio_read - Read data from touch device by PIO 320 + * 321 + * @dev: The pointer of THC private device context 322 + * @address: Slave address for the PIO operation 323 + * @size: Expected read data size 324 + * @actual_size: The pointer of the actual data size read from touch device 325 + * @buffer: The pointer of data buffer to store the data read from touch device 326 + * 327 + * Return: 0 on success, other error codes on failed. 328 + */ 329 + int thc_tic_pio_read(struct thc_device *dev, const u32 address, 330 + const u32 size, u32 *actual_size, u32 *buffer) 331 + { 332 + u8 opcode; 333 + int ret; 334 + 335 + if (size <= 0 || !actual_size || !buffer) { 336 + dev_err(dev->dev, "Invalid input parameters, size %u, actual_size %p, buffer %p\n", 337 + size, actual_size, buffer); 338 + return -EINVAL; 339 + } 340 + 341 + if (mutex_lock_interruptible(&dev->thc_bus_lock)) 342 + return -EINTR; 343 + 344 + opcode = (dev->port_type == THC_PORT_TYPE_SPI) ? 345 + THC_PIO_OP_SPI_TIC_READ : THC_PIO_OP_I2C_TIC_READ; 346 + 347 + ret = prepare_pio(dev, opcode, address, size); 348 + if (ret < 0) 349 + goto end; 350 + 351 + pio_start(dev, 0, NULL); 352 + 353 + ret = pio_wait(dev); 354 + if (ret < 0) 355 + goto end; 356 + 357 + ret = pio_complete(dev, buffer, actual_size); 358 + 359 + end: 360 + mutex_unlock(&dev->thc_bus_lock); 361 + return ret; 362 + } 363 + EXPORT_SYMBOL_NS_GPL(thc_tic_pio_read, "INTEL_THC"); 364 + 365 + /** 366 + * thc_tic_pio_write - Write data to touch device by PIO 367 + * 368 + * @dev: The pointer of THC private device context 369 + * @address: Slave address for the PIO operation 370 + * @size: PIO write data size 371 + * @buffer: The pointer of the write data buffer 372 + * 373 + * Return: 0 on success, other error codes on failed. 374 + */ 375 + int thc_tic_pio_write(struct thc_device *dev, const u32 address, 376 + const u32 size, const u32 *buffer) 377 + { 378 + u8 opcode; 379 + int ret; 380 + 381 + if (size <= 0 || !buffer) { 382 + dev_err(dev->dev, "Invalid input parameters, size %u, buffer %p\n", 383 + size, buffer); 384 + return -EINVAL; 385 + } 386 + 387 + if (mutex_lock_interruptible(&dev->thc_bus_lock)) 388 + return -EINTR; 389 + 390 + opcode = (dev->port_type == THC_PORT_TYPE_SPI) ? 391 + THC_PIO_OP_SPI_TIC_WRITE : THC_PIO_OP_I2C_TIC_WRITE; 392 + 393 + ret = prepare_pio(dev, opcode, address, size); 394 + if (ret < 0) 395 + goto end; 396 + 397 + pio_start(dev, size, buffer); 398 + 399 + ret = pio_wait(dev); 400 + if (ret < 0) 401 + goto end; 402 + 403 + ret = pio_complete(dev, NULL, NULL); 404 + 405 + end: 406 + mutex_unlock(&dev->thc_bus_lock); 407 + return ret; 408 + } 409 + EXPORT_SYMBOL_NS_GPL(thc_tic_pio_write, "INTEL_THC"); 410 + 411 + /** 412 + * thc_tic_pio_write_and_read - Write data followed by read data by PIO 413 + * 414 + * @dev: The pointer of THC private device context 415 + * @address: Slave address for the PIO operation 416 + * @write_size: PIO write data size 417 + * @write_buffer: The pointer of the write data buffer 418 + * @read_size: Expected PIO read data size 419 + * @actual_size: The pointer of the actual read data size 420 + * @read_buffer: The pointer of PIO read data buffer 421 + * 422 + * Return: 0 on success, other error codes on failed. 423 + */ 424 + int thc_tic_pio_write_and_read(struct thc_device *dev, const u32 address, 425 + const u32 write_size, const u32 *write_buffer, 426 + const u32 read_size, u32 *actual_size, u32 *read_buffer) 427 + { 428 + u32 i2c_ctrl, mask; 429 + int ret; 430 + 431 + if (dev->port_type == THC_PORT_TYPE_SPI) { 432 + dev_err(dev->dev, "SPI port type doesn't support pio write and read!"); 433 + return -EINVAL; 434 + } 435 + 436 + if (mutex_lock_interruptible(&dev->thc_bus_lock)) 437 + return -EINTR; 438 + 439 + /* Config i2c PIO write and read sequence */ 440 + i2c_ctrl = FIELD_PREP(THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_THC_PIO_I2C_WBC, write_size); 441 + mask = THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_THC_PIO_I2C_WBC; 442 + 443 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_OFFSET, 444 + mask, i2c_ctrl); 445 + 446 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_OFFSET, 447 + THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_THC_I2C_RW_PIO_EN, 448 + THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_THC_I2C_RW_PIO_EN); 449 + 450 + ret = prepare_pio(dev, THC_PIO_OP_I2C_TIC_WRITE_AND_READ, address, read_size); 451 + if (ret < 0) 452 + goto end; 453 + 454 + pio_start(dev, write_size, write_buffer); 455 + 456 + ret = pio_wait(dev); 457 + if (ret < 0) 458 + goto end; 459 + 460 + ret = pio_complete(dev, read_buffer, actual_size); 461 + 462 + end: 463 + mutex_unlock(&dev->thc_bus_lock); 464 + return ret; 465 + } 466 + EXPORT_SYMBOL_NS_GPL(thc_tic_pio_write_and_read, "INTEL_THC"); 467 + 468 + /** 469 + * thc_interrupt_config - Configure THC interrupts 470 + * 471 + * @dev: The pointer of THC private device context 472 + */ 473 + void thc_interrupt_config(struct thc_device *dev) 474 + { 475 + u32 mbits, mask, r_dma_ctrl_1; 476 + 477 + /* Clear Error reporting interrupt status bits */ 478 + mbits = THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS | 479 + THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS; 480 + regmap_write_bits(dev->thc_regmap, 481 + THC_M_PRT_INT_STATUS_OFFSET, 482 + mbits, mbits); 483 + 484 + /* Enable Error Reporting Interrupts */ 485 + mbits = THC_M_PRT_INT_EN_TXN_ERR_INT_EN | 486 + THC_M_PRT_INT_EN_FATAL_ERR_INT_EN | 487 + THC_M_PRT_INT_EN_BUF_OVRRUN_ERR_INT_EN; 488 + regmap_write_bits(dev->thc_regmap, 489 + THC_M_PRT_INT_EN_OFFSET, 490 + mbits, mbits); 491 + 492 + /* Clear PIO Interrupt status bits */ 493 + mbits = THC_M_PRT_SW_SEQ_STS_THC_SS_ERR | 494 + THC_M_PRT_SW_SEQ_STS_TSSDONE; 495 + regmap_write_bits(dev->thc_regmap, 496 + THC_M_PRT_SW_SEQ_STS_OFFSET, 497 + mbits, mbits); 498 + 499 + /* Read Interrupts */ 500 + regmap_read(dev->thc_regmap, 501 + THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 502 + &r_dma_ctrl_1); 503 + /* Disable RxDMA1 */ 504 + r_dma_ctrl_1 &= ~THC_M_PRT_READ_DMA_CNTRL_IE_EOF; 505 + regmap_write(dev->thc_regmap, 506 + THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 507 + r_dma_ctrl_1); 508 + 509 + /* Ack EOF Interrupt RxDMA1 */ 510 + mbits = THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS; 511 + /* Ack NonDMA Interrupt */ 512 + mbits |= THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS; 513 + regmap_write_bits(dev->thc_regmap, 514 + THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, 515 + mbits, mbits); 516 + 517 + /* Ack EOF Interrupt RxDMA2 */ 518 + regmap_write_bits(dev->thc_regmap, 519 + THC_M_PRT_READ_DMA_INT_STS_2_OFFSET, 520 + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS, 521 + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS); 522 + 523 + /* Write Interrupts */ 524 + /* Disable TxDMA */ 525 + regmap_write_bits(dev->thc_regmap, 526 + THC_M_PRT_WRITE_DMA_CNTRL_OFFSET, 527 + THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL, 528 + 0); 529 + 530 + /* Clear TxDMA interrupt status bits */ 531 + mbits = THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ERROR_STS; 532 + mbits |= THC_M_PRT_WRITE_INT_STS_THC_WRDMA_IOC_STS; 533 + regmap_write_bits(dev->thc_regmap, 534 + THC_M_PRT_WRITE_INT_STS_OFFSET, 535 + mbits, mbits); 536 + 537 + /* Enable Non-DMA device inband interrupt */ 538 + r_dma_ctrl_1 |= THC_M_PRT_READ_DMA_CNTRL_IE_NDDI; 539 + regmap_write(dev->thc_regmap, 540 + THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 541 + r_dma_ctrl_1); 542 + 543 + if (dev->port_type == THC_PORT_TYPE_SPI) { 544 + /* Edge triggered interrupt */ 545 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_TSEQ_CNTRL_1_OFFSET, 546 + THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN, 547 + THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN); 548 + } else { 549 + /* Level triggered interrupt */ 550 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_TSEQ_CNTRL_1_OFFSET, 551 + THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN, 0); 552 + 553 + mbits = THC_M_PRT_INT_EN_THC_I2C_IC_MST_ON_HOLD_INT_EN | 554 + THC_M_PRT_INT_EN_THC_I2C_IC_SCL_STUCK_AT_LOW_DET_INT_EN | 555 + THC_M_PRT_INT_EN_THC_I2C_IC_TX_ABRT_INT_EN | 556 + THC_M_PRT_INT_EN_THC_I2C_IC_TX_OVER_INT_EN | 557 + THC_M_PRT_INT_EN_THC_I2C_IC_RX_FULL_INT_EN | 558 + THC_M_PRT_INT_EN_THC_I2C_IC_RX_OVER_INT_EN | 559 + THC_M_PRT_INT_EN_THC_I2C_IC_RX_UNDER_INT_EN; 560 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_EN_OFFSET, 561 + mbits, mbits); 562 + } 563 + 564 + thc_set_pio_interrupt_support(dev, false); 565 + 566 + /* HIDSPI specific settings */ 567 + if (dev->port_type == THC_PORT_TYPE_SPI) { 568 + mbits = FIELD_PREP(THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_OFFSET, 569 + THC_BIT_OFFSET_INTERRUPT_TYPE) | 570 + FIELD_PREP(THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_LEN, 571 + THC_BIT_LENGTH_INTERRUPT_TYPE) | 572 + FIELD_PREP(THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_EOF_OFFSET, 573 + THC_BIT_OFFSET_LAST_FRAGMENT_FLAG) | 574 + FIELD_PREP(THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_DATA_VAL, 575 + THC_BITMASK_INVALID_TYPE_DATA); 576 + mask = THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_OFFSET | 577 + THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_LEN | 578 + THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_EOF_OFFSET | 579 + THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_DATA_VAL; 580 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_DEVINT_CFG_1_OFFSET, 581 + mask, mbits); 582 + 583 + mbits = FIELD_PREP(THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_OFFSET, 584 + THC_BIT_OFFSET_MICROFRAME_SIZE) | 585 + FIELD_PREP(THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_LEN, 586 + THC_BIT_LENGTH_MICROFRAME_SIZE) | 587 + FIELD_PREP(THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_UNIT, 588 + THC_UNIT_MICROFRAME_SIZE) | 589 + THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_IGNORE | 590 + THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_VAL; 591 + mask = THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_OFFSET | 592 + THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_LEN | 593 + THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_UNIT | 594 + THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_IGNORE | 595 + THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_VAL; 596 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_DEVINT_CFG_2_OFFSET, 597 + mask, mbits); 598 + } 599 + } 600 + EXPORT_SYMBOL_NS_GPL(thc_interrupt_config, "INTEL_THC"); 601 + 602 + /** 603 + * thc_int_trigger_type_select - Select THC interrupt trigger type 604 + * 605 + * @dev: the pointer of THC private device context 606 + * @edge_trigger: determine the interrupt is edge triggered or level triggered 607 + */ 608 + void thc_int_trigger_type_select(struct thc_device *dev, bool edge_trigger) 609 + { 610 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_TSEQ_CNTRL_1_OFFSET, 611 + THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN, 612 + edge_trigger ? THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN : 0); 613 + } 614 + EXPORT_SYMBOL_NS_GPL(thc_int_trigger_type_select, "INTEL_THC"); 615 + 616 + /** 617 + * thc_interrupt_enable - Enable or disable THC interrupt 618 + * 619 + * @dev: the pointer of THC private device context 620 + * @int_enable: the flag to control THC interrupt enable or disable 621 + */ 622 + void thc_interrupt_enable(struct thc_device *dev, bool int_enable) 623 + { 624 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_EN_OFFSET, 625 + THC_M_PRT_INT_EN_GBL_INT_EN, 626 + int_enable ? THC_M_PRT_INT_EN_GBL_INT_EN : 0); 627 + } 628 + EXPORT_SYMBOL_NS_GPL(thc_interrupt_enable, "INTEL_THC"); 629 + 630 + /** 631 + * thc_interrupt_quiesce - Quiesce or unquiesce external touch device interrupt 632 + * 633 + * @dev: the pointer of THC private device context 634 + * @int_quiesce: the flag to determine quiesce or unquiesce device interrupt 635 + * 636 + * Return: 0 on success, other error codes on failed 637 + */ 638 + int thc_interrupt_quiesce(const struct thc_device *dev, bool int_quiesce) 639 + { 640 + u32 ctrl; 641 + int ret; 642 + 643 + regmap_read(dev->thc_regmap, THC_M_PRT_CONTROL_OFFSET, &ctrl); 644 + if (!(ctrl & THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN) && !int_quiesce) { 645 + dev_warn(dev->dev, "THC interrupt already unquiesce\n"); 646 + return 0; 647 + } 648 + 649 + if ((ctrl & THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN) && int_quiesce) { 650 + dev_warn(dev->dev, "THC interrupt already quiesce\n"); 651 + return 0; 652 + } 653 + 654 + /* Quiesce device interrupt - Set quiesce bit and waiting for THC HW to ACK */ 655 + if (int_quiesce) 656 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_CONTROL_OFFSET, 657 + THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN, 658 + THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN); 659 + 660 + ret = regmap_read_poll_timeout(dev->thc_regmap, THC_M_PRT_CONTROL_OFFSET, ctrl, 661 + ctrl & THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_HW_STS, 662 + THC_REGMAP_POLLING_INTERVAL_US, THC_QUIESCE_EN_TIMEOUT_US); 663 + if (ret) { 664 + dev_err_once(dev->dev, 665 + "Timeout while waiting THC idle, target quiesce state = %s\n", 666 + int_quiesce ? "true" : "false"); 667 + return ret; 668 + } 669 + 670 + /* Unquiesce device interrupt - Clear the quiesce bit */ 671 + if (!int_quiesce) 672 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_CONTROL_OFFSET, 673 + THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN, 0); 674 + 675 + return 0; 676 + } 677 + EXPORT_SYMBOL_NS_GPL(thc_interrupt_quiesce, "INTEL_THC"); 678 + 679 + /** 680 + * thc_set_pio_interrupt_support - Determine PIO interrupt is supported or not 681 + * 682 + * @dev: The pointer of THC private device context 683 + * @supported: The flag to determine enabling PIO interrupt or not 684 + */ 685 + void thc_set_pio_interrupt_support(struct thc_device *dev, bool supported) 686 + { 687 + dev->pio_int_supported = supported; 688 + } 689 + EXPORT_SYMBOL_NS_GPL(thc_set_pio_interrupt_support, "INTEL_THC"); 690 + 691 + /** 692 + * thc_ltr_config - Configure THC Latency Tolerance Reporting(LTR) settings 693 + * 694 + * @dev: The pointer of THC private device context 695 + * @active_ltr_us: active LTR value, unit is us 696 + * @lp_ltr_us: low power LTR value, unit is us 697 + */ 698 + void thc_ltr_config(struct thc_device *dev, u32 active_ltr_us, u32 lp_ltr_us) 699 + { 700 + u32 active_ltr_scale, lp_ltr_scale, ltr_ctrl, ltr_mask, orig, tmp; 701 + 702 + if (active_ltr_us >= THC_LTR_MIN_VAL_SCALE_3 && 703 + active_ltr_us < THC_LTR_MAX_VAL_SCALE_3) { 704 + active_ltr_scale = THC_LTR_SCALE_3; 705 + active_ltr_us = active_ltr_us >> 5; 706 + } else if (active_ltr_us >= THC_LTR_MIN_VAL_SCALE_4 && 707 + active_ltr_us < THC_LTR_MAX_VAL_SCALE_4) { 708 + active_ltr_scale = THC_LTR_SCALE_4; 709 + active_ltr_us = active_ltr_us >> 10; 710 + } else if (active_ltr_us >= THC_LTR_MIN_VAL_SCALE_5 && 711 + active_ltr_us < THC_LTR_MAX_VAL_SCALE_5) { 712 + active_ltr_scale = THC_LTR_SCALE_5; 713 + active_ltr_us = active_ltr_us >> 15; 714 + } else { 715 + active_ltr_scale = THC_LTR_SCALE_2; 716 + } 717 + 718 + if (lp_ltr_us >= THC_LTR_MIN_VAL_SCALE_3 && 719 + lp_ltr_us < THC_LTR_MAX_VAL_SCALE_3) { 720 + lp_ltr_scale = THC_LTR_SCALE_3; 721 + lp_ltr_us = lp_ltr_us >> 5; 722 + } else if (lp_ltr_us >= THC_LTR_MIN_VAL_SCALE_4 && 723 + lp_ltr_us < THC_LTR_MAX_VAL_SCALE_4) { 724 + lp_ltr_scale = THC_LTR_SCALE_4; 725 + lp_ltr_us = lp_ltr_us >> 10; 726 + } else if (lp_ltr_us >= THC_LTR_MIN_VAL_SCALE_5 && 727 + lp_ltr_us < THC_LTR_MAX_VAL_SCALE_5) { 728 + lp_ltr_scale = THC_LTR_SCALE_5; 729 + lp_ltr_us = lp_ltr_us >> 15; 730 + } else { 731 + lp_ltr_scale = THC_LTR_SCALE_2; 732 + } 733 + 734 + regmap_read(dev->thc_regmap, THC_M_CMN_LTR_CTRL_OFFSET, &orig); 735 + ltr_ctrl = FIELD_PREP(THC_M_CMN_LTR_CTRL_ACT_LTR_VAL, active_ltr_us) | 736 + FIELD_PREP(THC_M_CMN_LTR_CTRL_ACT_LTR_SCALE, active_ltr_scale) | 737 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_REQ | 738 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_EN | 739 + FIELD_PREP(THC_M_CMN_LTR_CTRL_LP_LTR_VAL, lp_ltr_us) | 740 + FIELD_PREP(THC_M_CMN_LTR_CTRL_LP_LTR_SCALE, lp_ltr_scale) | 741 + THC_M_CMN_LTR_CTRL_LP_LTR_REQ; 742 + 743 + ltr_mask = THC_M_CMN_LTR_CTRL_ACT_LTR_VAL | 744 + THC_M_CMN_LTR_CTRL_ACT_LTR_SCALE | 745 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_REQ | 746 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_EN | 747 + THC_M_CMN_LTR_CTRL_LP_LTR_VAL | 748 + THC_M_CMN_LTR_CTRL_LP_LTR_SCALE | 749 + THC_M_CMN_LTR_CTRL_LP_LTR_REQ | 750 + THC_M_CMN_LTR_CTRL_LP_LTR_EN; 751 + 752 + tmp = orig & ~ltr_mask; 753 + tmp |= ltr_ctrl & ltr_mask; 754 + 755 + regmap_write(dev->thc_regmap, THC_M_CMN_LTR_CTRL_OFFSET, tmp); 756 + } 757 + EXPORT_SYMBOL_NS_GPL(thc_ltr_config, "INTEL_THC"); 758 + 759 + /** 760 + * thc_change_ltr_mode - Change THC LTR mode 761 + * 762 + * @dev: The pointer of THC private device context 763 + * @ltr_mode: LTR mode(active or low power) 764 + */ 765 + void thc_change_ltr_mode(struct thc_device *dev, u32 ltr_mode) 766 + { 767 + if (ltr_mode == THC_LTR_MODE_ACTIVE) { 768 + regmap_write_bits(dev->thc_regmap, THC_M_CMN_LTR_CTRL_OFFSET, 769 + THC_M_CMN_LTR_CTRL_LP_LTR_EN, 0); 770 + regmap_write_bits(dev->thc_regmap, THC_M_CMN_LTR_CTRL_OFFSET, 771 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_EN, 772 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_EN); 773 + return; 774 + } 775 + 776 + regmap_write_bits(dev->thc_regmap, THC_M_CMN_LTR_CTRL_OFFSET, 777 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_EN, 0); 778 + regmap_write_bits(dev->thc_regmap, THC_M_CMN_LTR_CTRL_OFFSET, 779 + THC_M_CMN_LTR_CTRL_LP_LTR_EN, 780 + THC_M_CMN_LTR_CTRL_LP_LTR_EN); 781 + } 782 + EXPORT_SYMBOL_NS_GPL(thc_change_ltr_mode, "INTEL_THC"); 783 + 784 + /** 785 + * thc_ltr_unconfig - Unconfigure THC Latency Tolerance Reporting(LTR) settings 786 + * 787 + * @dev: The pointer of THC private device context 788 + */ 789 + void thc_ltr_unconfig(struct thc_device *dev) 790 + { 791 + u32 ltr_ctrl, bits_clear; 792 + 793 + regmap_read(dev->thc_regmap, THC_M_CMN_LTR_CTRL_OFFSET, &ltr_ctrl); 794 + bits_clear = THC_M_CMN_LTR_CTRL_LP_LTR_EN | 795 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_EN | 796 + THC_M_CMN_LTR_CTRL_LP_LTR_REQ | 797 + THC_M_CMN_LTR_CTRL_ACTIVE_LTR_REQ; 798 + 799 + ltr_ctrl &= ~bits_clear; 800 + 801 + regmap_write(dev->thc_regmap, THC_M_CMN_LTR_CTRL_OFFSET, ltr_ctrl); 802 + } 803 + EXPORT_SYMBOL_NS_GPL(thc_ltr_unconfig, "INTEL_THC"); 804 + 805 + /** 806 + * thc_int_cause_read - Read interrupt cause register value 807 + * 808 + * @dev: The pointer of THC private device context 809 + * 810 + * Return: The interrupt cause register value 811 + */ 812 + u32 thc_int_cause_read(struct thc_device *dev) 813 + { 814 + u32 int_cause; 815 + 816 + regmap_read(dev->thc_regmap, 817 + THC_M_PRT_DEV_INT_CAUSE_REG_VAL_OFFSET, &int_cause); 818 + 819 + return int_cause; 820 + } 821 + EXPORT_SYMBOL_NS_GPL(thc_int_cause_read, "INTEL_THC"); 822 + 823 + static void thc_print_txn_error_cause(const struct thc_device *dev) 824 + { 825 + bool known_error = false; 826 + u32 cause = 0; 827 + 828 + regmap_read(dev->thc_regmap, THC_M_PRT_ERR_CAUSE_OFFSET, &cause); 829 + 830 + if (cause & THC_M_PRT_ERR_CAUSE_PRD_ENTRY_ERR) { 831 + dev_err(dev->dev, "TXN Error: Invalid PRD Entry\n"); 832 + known_error = true; 833 + } 834 + if (cause & THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR) { 835 + dev_err(dev->dev, "TXN Error: THC Buffer Overrun\n"); 836 + known_error = true; 837 + } 838 + if (cause & THC_M_PRT_ERR_CAUSE_FRAME_BABBLE_ERR) { 839 + dev_err(dev->dev, "TXN Error: Frame Babble\n"); 840 + known_error = true; 841 + } 842 + if (cause & THC_M_PRT_ERR_CAUSE_INVLD_DEV_ENTRY) { 843 + dev_err(dev->dev, "TXN Error: Invalid Device Register Setting\n"); 844 + known_error = true; 845 + } 846 + 847 + /* Clear interrupt status bits */ 848 + regmap_write(dev->thc_regmap, THC_M_PRT_ERR_CAUSE_OFFSET, cause); 849 + 850 + if (!known_error) 851 + dev_err(dev->dev, "TXN Error does not match any known value: 0x%X\n", 852 + cause); 853 + } 854 + 855 + /** 856 + * thc_interrupt_handler - Handle THC interrupts 857 + * 858 + * THC interrupts include several types: external touch device (TIC) non-DMA 859 + * interrupts, PIO completion interrupts, DMA interrtups, I2C subIP raw 860 + * interrupts and error interrupts. 861 + * 862 + * This is a help function for interrupt processing, it detects interrupt 863 + * type, clear the interrupt status bit and return the interrupt type to caller 864 + * for future processing. 865 + * 866 + * @dev: The pointer of THC private device context 867 + * 868 + * Return: The combined flag for interrupt type 869 + */ 870 + int thc_interrupt_handler(struct thc_device *dev) 871 + { 872 + u32 read_sts_1, read_sts_2, read_sts_sw, write_sts; 873 + u32 int_sts, err_cause, seq_cntrl, seq_sts; 874 + int interrupt_type = 0; 875 + 876 + regmap_read(dev->thc_regmap, 877 + THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, &read_sts_1); 878 + 879 + if (read_sts_1 & THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS) { 880 + dev_dbg(dev->dev, "THC non-DMA device interrupt\n"); 881 + 882 + regmap_write(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, 883 + NONDMA_INT_STS_BIT); 884 + 885 + interrupt_type |= BIT(THC_NONDMA_INT); 886 + 887 + return interrupt_type; 888 + } 889 + 890 + regmap_read(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, &int_sts); 891 + 892 + if (int_sts & THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS) { 893 + dev_err(dev->dev, "THC transaction error, int_sts: 0x%08X\n", int_sts); 894 + thc_print_txn_error_cause(dev); 895 + 896 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 897 + TXN_ERR_INT_STS_BIT); 898 + 899 + interrupt_type |= BIT(THC_TXN_ERR_INT); 900 + 901 + return interrupt_type; 902 + } 903 + 904 + regmap_read(dev->thc_regmap, THC_M_PRT_ERR_CAUSE_OFFSET, &err_cause); 905 + regmap_read(dev->thc_regmap, 906 + THC_M_PRT_READ_DMA_INT_STS_2_OFFSET, &read_sts_2); 907 + 908 + if (err_cause & THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR || 909 + read_sts_1 & THC_M_PRT_READ_DMA_INT_STS_STALL_STS || 910 + read_sts_2 & THC_M_PRT_READ_DMA_INT_STS_STALL_STS) { 911 + dev_err(dev->dev, "Buffer overrun or RxDMA engine stalled!\n"); 912 + thc_print_txn_error_cause(dev); 913 + 914 + regmap_write(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_2_OFFSET, 915 + THC_M_PRT_READ_DMA_INT_STS_STALL_STS); 916 + regmap_write(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, 917 + THC_M_PRT_READ_DMA_INT_STS_STALL_STS); 918 + regmap_write(dev->thc_regmap, THC_M_PRT_ERR_CAUSE_OFFSET, 919 + THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR); 920 + 921 + interrupt_type |= BIT(THC_TXN_ERR_INT); 922 + 923 + return interrupt_type; 924 + } 925 + 926 + if (int_sts & THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS) { 927 + dev_err_once(dev->dev, "THC FATAL error, int_sts: 0x%08X\n", int_sts); 928 + 929 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 930 + TXN_FATAL_INT_STS_BIT); 931 + 932 + interrupt_type |= BIT(THC_FATAL_ERR_INT); 933 + 934 + return interrupt_type; 935 + } 936 + 937 + regmap_read(dev->thc_regmap, 938 + THC_M_PRT_SW_SEQ_CNTRL_OFFSET, &seq_cntrl); 939 + regmap_read(dev->thc_regmap, 940 + THC_M_PRT_SW_SEQ_STS_OFFSET, &seq_sts); 941 + 942 + if (seq_cntrl & THC_M_PRT_SW_SEQ_CNTRL_THC_SS_CD_IE && 943 + seq_sts & THC_M_PRT_SW_SEQ_STS_TSSDONE) { 944 + dev_dbg(dev->dev, "THC_SS_CD_IE and TSSDONE are set\n"); 945 + interrupt_type |= BIT(THC_PIO_DONE_INT); 946 + } 947 + 948 + if (read_sts_1 & THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS) { 949 + dev_dbg(dev->dev, "Got RxDMA1 Read Interrupt\n"); 950 + 951 + regmap_write(dev->thc_regmap, 952 + THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, read_sts_1); 953 + 954 + interrupt_type |= BIT(THC_RXDMA1_INT); 955 + } 956 + 957 + if (read_sts_2 & THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS) { 958 + dev_dbg(dev->dev, "Got RxDMA2 Read Interrupt\n"); 959 + 960 + regmap_write(dev->thc_regmap, 961 + THC_M_PRT_READ_DMA_INT_STS_2_OFFSET, read_sts_2); 962 + 963 + interrupt_type |= BIT(THC_RXDMA2_INT); 964 + } 965 + 966 + regmap_read(dev->thc_regmap, 967 + THC_M_PRT_READ_DMA_INT_STS_SW_OFFSET, &read_sts_sw); 968 + 969 + if (read_sts_sw & THC_M_PRT_READ_DMA_INT_STS_DMACPL_STS) { 970 + dev_dbg(dev->dev, "Got SwDMA Read Interrupt\n"); 971 + 972 + regmap_write(dev->thc_regmap, 973 + THC_M_PRT_READ_DMA_INT_STS_SW_OFFSET, read_sts_sw); 974 + 975 + dev->swdma_done = true; 976 + wake_up_interruptible(&dev->swdma_complete_wait); 977 + 978 + interrupt_type |= BIT(THC_SWDMA_INT); 979 + } 980 + 981 + regmap_read(dev->thc_regmap, 982 + THC_M_PRT_WRITE_INT_STS_OFFSET, &write_sts); 983 + 984 + if (write_sts & THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS) { 985 + dev_dbg(dev->dev, "Got TxDMA Write complete Interrupt\n"); 986 + 987 + regmap_write(dev->thc_regmap, 988 + THC_M_PRT_WRITE_INT_STS_OFFSET, write_sts); 989 + 990 + dev->write_done = true; 991 + wake_up_interruptible(&dev->write_complete_wait); 992 + 993 + interrupt_type |= BIT(THC_TXDMA_INT); 994 + } 995 + 996 + if (int_sts & THC_M_PRT_INT_STATUS_DEV_RAW_INT_STS) { 997 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 998 + THC_M_PRT_INT_STATUS_DEV_RAW_INT_STS); 999 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1000 + } 1001 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_UNDER_INT_STS) { 1002 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1003 + THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_UNDER_INT_STS); 1004 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1005 + } 1006 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_OVER_INT_STS) { 1007 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1008 + THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_OVER_INT_STS); 1009 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1010 + } 1011 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_FULL_INT_STS) { 1012 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1013 + THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_FULL_INT_STS); 1014 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1015 + } 1016 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_OVER_INT_STS) { 1017 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1018 + THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_OVER_INT_STS); 1019 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1020 + } 1021 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_EMPTY_INT_STS) { 1022 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1023 + THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_EMPTY_INT_STS); 1024 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1025 + } 1026 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_ABRT_INT_STS) { 1027 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1028 + THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_ABRT_INT_STS); 1029 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1030 + } 1031 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_ACTIVITY_INT_STS) { 1032 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1033 + THC_M_PRT_INT_STATUS_THC_I2C_IC_ACTIVITY_INT_STS); 1034 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1035 + } 1036 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_SCL_STUCK_AT_LOW_INT_STS) { 1037 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1038 + THC_M_PRT_INT_STATUS_THC_I2C_IC_SCL_STUCK_AT_LOW_INT_STS); 1039 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1040 + } 1041 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_STOP_DET_INT_STS) { 1042 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1043 + THC_M_PRT_INT_STATUS_THC_I2C_IC_STOP_DET_INT_STS); 1044 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1045 + } 1046 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_START_DET_INT_STS) { 1047 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1048 + THC_M_PRT_INT_STATUS_THC_I2C_IC_START_DET_INT_STS); 1049 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1050 + } 1051 + if (int_sts & THC_M_PRT_INT_STATUS_THC_I2C_IC_MST_ON_HOLD_INT_STS) { 1052 + regmap_write(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, 1053 + THC_M_PRT_INT_STATUS_THC_I2C_IC_MST_ON_HOLD_INT_STS); 1054 + interrupt_type |= BIT(THC_I2CSUBIP_INT); 1055 + } 1056 + 1057 + if (!interrupt_type) 1058 + interrupt_type |= BIT(THC_UNKNOWN_INT); 1059 + 1060 + return interrupt_type; 1061 + } 1062 + EXPORT_SYMBOL_NS_GPL(thc_interrupt_handler, "INTEL_THC"); 1063 + 1064 + /** 1065 + * thc_port_select - Set THC port type 1066 + * 1067 + * @dev: The pointer of THC private device context 1068 + * @port_type: THC port type to use for current device 1069 + * 1070 + * Return: 0 on success, other error codes on failed. 1071 + */ 1072 + int thc_port_select(struct thc_device *dev, enum thc_port_type port_type) 1073 + { 1074 + u32 ctrl, mask; 1075 + 1076 + if (port_type == THC_PORT_TYPE_SPI) { 1077 + dev_dbg(dev->dev, "Set THC port type to SPI\n"); 1078 + dev->port_type = THC_PORT_TYPE_SPI; 1079 + 1080 + /* Enable delay of CS assertion and set to default value */ 1081 + ctrl = THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_EN | 1082 + FIELD_PREP(THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_VAL, 1083 + THC_CSA_CK_DELAY_VAL_DEFAULT); 1084 + mask = THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_EN | 1085 + THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_VAL; 1086 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SPI_DUTYC_CFG_OFFSET, 1087 + mask, ctrl); 1088 + } else if (port_type == THC_PORT_TYPE_I2C) { 1089 + dev_dbg(dev->dev, "Set THC port type to I2C\n"); 1090 + dev->port_type = THC_PORT_TYPE_I2C; 1091 + 1092 + /* Set THC transition arbitration policy to frame boundary for I2C */ 1093 + ctrl = FIELD_PREP(THC_M_PRT_CONTROL_THC_ARB_POLICY, 1094 + THC_ARB_POLICY_FRAME_BOUNDARY); 1095 + mask = THC_M_PRT_CONTROL_THC_ARB_POLICY; 1096 + 1097 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_CONTROL_OFFSET, mask, ctrl); 1098 + } else { 1099 + dev_err(dev->dev, "unsupported THC port type: %d\n", port_type); 1100 + return -EINVAL; 1101 + } 1102 + 1103 + ctrl = FIELD_PREP(THC_M_PRT_CONTROL_PORT_TYPE, port_type); 1104 + mask = THC_M_PRT_CONTROL_PORT_TYPE; 1105 + 1106 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_CONTROL_OFFSET, mask, ctrl); 1107 + 1108 + return 0; 1109 + } 1110 + EXPORT_SYMBOL_NS_GPL(thc_port_select, "INTEL_THC"); 1111 + 1112 + #define THC_SPI_FREQUENCY_7M 7812500 1113 + #define THC_SPI_FREQUENCY_15M 15625000 1114 + #define THC_SPI_FREQUENCY_17M 17857100 1115 + #define THC_SPI_FREQUENCY_20M 20833000 1116 + #define THC_SPI_FREQUENCY_25M 25000000 1117 + #define THC_SPI_FREQUENCY_31M 31250000 1118 + #define THC_SPI_FREQUENCY_41M 41666700 1119 + 1120 + #define THC_SPI_LOW_FREQUENCY THC_SPI_FREQUENCY_17M 1121 + 1122 + static u8 thc_get_spi_freq_div_val(struct thc_device *dev, u32 spi_freq_val) 1123 + { 1124 + int frequency[] = { 1125 + THC_SPI_FREQUENCY_7M, 1126 + THC_SPI_FREQUENCY_15M, 1127 + THC_SPI_FREQUENCY_17M, 1128 + THC_SPI_FREQUENCY_20M, 1129 + THC_SPI_FREQUENCY_25M, 1130 + THC_SPI_FREQUENCY_31M, 1131 + THC_SPI_FREQUENCY_41M, 1132 + }; 1133 + u8 frequency_div[] = { 1134 + THC_SPI_FRQ_DIV_2, 1135 + THC_SPI_FRQ_DIV_1, 1136 + THC_SPI_FRQ_DIV_7, 1137 + THC_SPI_FRQ_DIV_6, 1138 + THC_SPI_FRQ_DIV_5, 1139 + THC_SPI_FRQ_DIV_4, 1140 + THC_SPI_FRQ_DIV_3, 1141 + }; 1142 + int size = ARRAY_SIZE(frequency); 1143 + u32 closest_freq; 1144 + u8 freq_div; 1145 + int i; 1146 + 1147 + for (i = size - 1; i >= 0; i--) 1148 + if ((int)spi_freq_val - frequency[i] >= 0) 1149 + break; 1150 + 1151 + if (i < 0) { 1152 + dev_err_once(dev->dev, "Not supported SPI frequency %d\n", spi_freq_val); 1153 + return THC_SPI_FRQ_RESERVED; 1154 + } 1155 + 1156 + closest_freq = frequency[i]; 1157 + freq_div = frequency_div[i]; 1158 + 1159 + dev_dbg(dev->dev, 1160 + "Setting SPI frequency: spi_freq_val = %u, Closest freq = %u\n", 1161 + spi_freq_val, closest_freq); 1162 + 1163 + return freq_div; 1164 + } 1165 + 1166 + /** 1167 + * thc_spi_read_config - Configure SPI bus read attributes 1168 + * 1169 + * @dev: The pointer of THC private device context 1170 + * @spi_freq_val: SPI read frequecy value 1171 + * @io_mode: SPI read IO mode 1172 + * @opcode: Read opcode 1173 + * @spi_rd_mps: SPI read max packet size 1174 + * 1175 + * Return: 0 on success, other error codes on failed. 1176 + */ 1177 + int thc_spi_read_config(struct thc_device *dev, u32 spi_freq_val, 1178 + u32 io_mode, u32 opcode, u32 spi_rd_mps) 1179 + { 1180 + bool is_low_freq = false; 1181 + u32 cfg, mask; 1182 + u8 freq_div; 1183 + 1184 + freq_div = thc_get_spi_freq_div_val(dev, spi_freq_val); 1185 + if (freq_div == THC_SPI_FRQ_RESERVED) 1186 + return -EINVAL; 1187 + 1188 + if (spi_freq_val < THC_SPI_LOW_FREQUENCY) 1189 + is_low_freq = true; 1190 + 1191 + cfg = FIELD_PREP(THC_M_PRT_SPI_CFG_SPI_TCRF, freq_div) | 1192 + FIELD_PREP(THC_M_PRT_SPI_CFG_SPI_TRMODE, io_mode) | 1193 + (is_low_freq ? THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN : 0) | 1194 + FIELD_PREP(THC_M_PRT_SPI_CFG_SPI_RD_MPS, spi_rd_mps); 1195 + mask = THC_M_PRT_SPI_CFG_SPI_TCRF | 1196 + THC_M_PRT_SPI_CFG_SPI_TRMODE | 1197 + THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN | 1198 + THC_M_PRT_SPI_CFG_SPI_RD_MPS; 1199 + 1200 + regmap_write_bits(dev->thc_regmap, 1201 + THC_M_PRT_SPI_CFG_OFFSET, mask, cfg); 1202 + 1203 + if (io_mode == THC_QUAD_IO) 1204 + opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_QIO, opcode); 1205 + else if (io_mode == THC_DUAL_IO) 1206 + opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_DIO, opcode); 1207 + else 1208 + opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_SIO, opcode); 1209 + 1210 + regmap_write(dev->thc_regmap, THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET, opcode); 1211 + regmap_write(dev->thc_regmap, THC_M_PRT_SPI_DMARD_OPCODE_OFFSET, opcode); 1212 + 1213 + return 0; 1214 + } 1215 + EXPORT_SYMBOL_NS_GPL(thc_spi_read_config, "INTEL_THC"); 1216 + 1217 + /** 1218 + * thc_spi_write_config - Configure SPI bus write attributes 1219 + * 1220 + * @dev: The pointer of THC private device context 1221 + * @spi_freq_val: SPI write frequecy value 1222 + * @io_mode: SPI write IO mode 1223 + * @opcode: Write opcode 1224 + * @spi_wr_mps: SPI write max packet size 1225 + * @perf_limit: Performance limitation in unit of 10us 1226 + * 1227 + * Return: 0 on success, other error codes on failed. 1228 + */ 1229 + int thc_spi_write_config(struct thc_device *dev, u32 spi_freq_val, 1230 + u32 io_mode, u32 opcode, u32 spi_wr_mps, 1231 + u32 perf_limit) 1232 + { 1233 + bool is_low_freq = false; 1234 + u32 cfg, mask; 1235 + u8 freq_div; 1236 + 1237 + freq_div = thc_get_spi_freq_div_val(dev, spi_freq_val); 1238 + if (freq_div == THC_SPI_FRQ_RESERVED) 1239 + return -EINVAL; 1240 + 1241 + if (spi_freq_val < THC_SPI_LOW_FREQUENCY) 1242 + is_low_freq = true; 1243 + 1244 + cfg = FIELD_PREP(THC_M_PRT_SPI_CFG_SPI_TCWF, freq_div) | 1245 + FIELD_PREP(THC_M_PRT_SPI_CFG_SPI_TWMODE, io_mode) | 1246 + (is_low_freq ? THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN : 0) | 1247 + FIELD_PREP(THC_M_PRT_SPI_CFG_SPI_WR_MPS, spi_wr_mps); 1248 + mask = THC_M_PRT_SPI_CFG_SPI_TCWF | 1249 + THC_M_PRT_SPI_CFG_SPI_TWMODE | 1250 + THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN | 1251 + THC_M_PRT_SPI_CFG_SPI_WR_MPS; 1252 + 1253 + regmap_write_bits(dev->thc_regmap, 1254 + THC_M_PRT_SPI_CFG_OFFSET, mask, cfg); 1255 + 1256 + if (io_mode == THC_QUAD_IO) 1257 + opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_QIO, opcode); 1258 + else if (io_mode == THC_DUAL_IO) 1259 + opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_DIO, opcode); 1260 + else 1261 + opcode = FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_SPI_SIO, opcode); 1262 + 1263 + regmap_write(dev->thc_regmap, THC_M_PRT_SPI_WR_OPCODE_OFFSET, opcode); 1264 + 1265 + dev->perf_limit = perf_limit; 1266 + 1267 + return 0; 1268 + } 1269 + EXPORT_SYMBOL_NS_GPL(thc_spi_write_config, "INTEL_THC"); 1270 + 1271 + /** 1272 + * thc_spi_input_output_address_config - Configure SPI input and output addresses 1273 + * 1274 + * @dev: the pointer of THC private device context 1275 + * @input_hdr_addr: input report header address 1276 + * @input_bdy_addr: input report body address 1277 + * @output_addr: output report address 1278 + */ 1279 + void thc_spi_input_output_address_config(struct thc_device *dev, u32 input_hdr_addr, 1280 + u32 input_bdy_addr, u32 output_addr) 1281 + { 1282 + regmap_write(dev->thc_regmap, 1283 + THC_M_PRT_DEV_INT_CAUSE_ADDR_OFFSET, input_hdr_addr); 1284 + regmap_write(dev->thc_regmap, 1285 + THC_M_PRT_RD_BULK_ADDR_1_OFFSET, input_bdy_addr); 1286 + regmap_write(dev->thc_regmap, 1287 + THC_M_PRT_RD_BULK_ADDR_2_OFFSET, input_bdy_addr); 1288 + regmap_write(dev->thc_regmap, 1289 + THC_M_PRT_WR_BULK_ADDR_OFFSET, output_addr); 1290 + } 1291 + EXPORT_SYMBOL_NS_GPL(thc_spi_input_output_address_config, "INTEL_THC"); 1292 + 1293 + static int thc_i2c_subip_pio_read(struct thc_device *dev, const u32 address, 1294 + u32 *size, u32 *buffer) 1295 + { 1296 + int ret; 1297 + 1298 + if (!size || *size == 0 || !buffer) { 1299 + dev_err(dev->dev, "Invalid input parameters, size %p, buffer %p\n", 1300 + size, buffer); 1301 + return -EINVAL; 1302 + } 1303 + 1304 + if (mutex_lock_interruptible(&dev->thc_bus_lock)) 1305 + return -EINTR; 1306 + 1307 + ret = prepare_pio(dev, THC_PIO_OP_I2C_SUBSYSTEM_READ, address, *size); 1308 + if (ret < 0) 1309 + goto end; 1310 + 1311 + pio_start(dev, 0, NULL); 1312 + 1313 + ret = pio_wait(dev); 1314 + if (ret < 0) 1315 + goto end; 1316 + 1317 + ret = pio_complete(dev, buffer, size); 1318 + if (ret < 0) 1319 + goto end; 1320 + 1321 + end: 1322 + mutex_unlock(&dev->thc_bus_lock); 1323 + 1324 + if (ret) 1325 + dev_err_once(dev->dev, "Read THC I2C SubIP register failed %d, offset %u\n", 1326 + ret, address); 1327 + 1328 + return ret; 1329 + } 1330 + 1331 + static int thc_i2c_subip_pio_write(struct thc_device *dev, const u32 address, 1332 + const u32 size, const u32 *buffer) 1333 + { 1334 + int ret; 1335 + 1336 + if (size == 0 || !buffer) { 1337 + dev_err(dev->dev, "Invalid input parameters, size %u, buffer %p\n", 1338 + size, buffer); 1339 + return -EINVAL; 1340 + } 1341 + 1342 + if (mutex_lock_interruptible(&dev->thc_bus_lock)) 1343 + return -EINTR; 1344 + 1345 + ret = prepare_pio(dev, THC_PIO_OP_I2C_SUBSYSTEM_WRITE, address, size); 1346 + if (ret < 0) 1347 + goto end; 1348 + 1349 + pio_start(dev, size, buffer); 1350 + 1351 + ret = pio_wait(dev); 1352 + if (ret < 0) 1353 + goto end; 1354 + 1355 + ret = pio_complete(dev, NULL, NULL); 1356 + if (ret < 0) 1357 + goto end; 1358 + 1359 + end: 1360 + mutex_unlock(&dev->thc_bus_lock); 1361 + 1362 + if (ret) 1363 + dev_err_once(dev->dev, "Write THC I2C SubIP register failed %d, offset %u\n", 1364 + ret, address); 1365 + 1366 + return ret; 1367 + } 1368 + 1369 + #define I2C_SUBIP_CON_DEFAULT 0x663 1370 + #define I2C_SUBIP_INT_MASK_DEFAULT 0x7FFF 1371 + #define I2C_SUBIP_RX_TL_DEFAULT 62 1372 + #define I2C_SUBIP_TX_TL_DEFAULT 0 1373 + #define I2C_SUBIP_DMA_TDLR_DEFAULT 7 1374 + #define I2C_SUBIP_DMA_RDLR_DEFAULT 7 1375 + 1376 + static int thc_i2c_subip_set_speed(struct thc_device *dev, const u32 speed, 1377 + const u32 hcnt, const u32 lcnt) 1378 + { 1379 + u32 hcnt_offset, lcnt_offset; 1380 + u32 val; 1381 + int ret; 1382 + 1383 + switch (speed) { 1384 + case THC_I2C_STANDARD: 1385 + hcnt_offset = THC_I2C_IC_SS_SCL_HCNT_OFFSET; 1386 + lcnt_offset = THC_I2C_IC_SS_SCL_LCNT_OFFSET; 1387 + break; 1388 + 1389 + case THC_I2C_FAST_AND_PLUS: 1390 + hcnt_offset = THC_I2C_IC_FS_SCL_HCNT_OFFSET; 1391 + lcnt_offset = THC_I2C_IC_FS_SCL_LCNT_OFFSET; 1392 + break; 1393 + 1394 + case THC_I2C_HIGH_SPEED: 1395 + hcnt_offset = THC_I2C_IC_HS_SCL_HCNT_OFFSET; 1396 + lcnt_offset = THC_I2C_IC_HS_SCL_LCNT_OFFSET; 1397 + break; 1398 + 1399 + default: 1400 + dev_err_once(dev->dev, "Unsupported i2c speed %d\n", speed); 1401 + ret = -EINVAL; 1402 + return ret; 1403 + } 1404 + 1405 + ret = thc_i2c_subip_pio_write(dev, hcnt_offset, sizeof(u32), &hcnt); 1406 + if (ret < 0) 1407 + return ret; 1408 + 1409 + ret = thc_i2c_subip_pio_write(dev, lcnt_offset, sizeof(u32), &lcnt); 1410 + if (ret < 0) 1411 + return ret; 1412 + 1413 + val = I2C_SUBIP_CON_DEFAULT & ~THC_I2C_IC_CON_SPEED; 1414 + val |= FIELD_PREP(THC_I2C_IC_CON_SPEED, speed); 1415 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_CON_OFFSET, sizeof(u32), &val); 1416 + if (ret < 0) 1417 + return ret; 1418 + 1419 + return 0; 1420 + } 1421 + 1422 + static u32 i2c_subip_regs[] = { 1423 + THC_I2C_IC_CON_OFFSET, 1424 + THC_I2C_IC_TAR_OFFSET, 1425 + THC_I2C_IC_INTR_MASK_OFFSET, 1426 + THC_I2C_IC_RX_TL_OFFSET, 1427 + THC_I2C_IC_TX_TL_OFFSET, 1428 + THC_I2C_IC_DMA_CR_OFFSET, 1429 + THC_I2C_IC_DMA_TDLR_OFFSET, 1430 + THC_I2C_IC_DMA_RDLR_OFFSET, 1431 + THC_I2C_IC_SS_SCL_HCNT_OFFSET, 1432 + THC_I2C_IC_SS_SCL_LCNT_OFFSET, 1433 + THC_I2C_IC_FS_SCL_HCNT_OFFSET, 1434 + THC_I2C_IC_FS_SCL_LCNT_OFFSET, 1435 + THC_I2C_IC_HS_SCL_HCNT_OFFSET, 1436 + THC_I2C_IC_HS_SCL_LCNT_OFFSET, 1437 + THC_I2C_IC_ENABLE_OFFSET, 1438 + }; 1439 + 1440 + /** 1441 + * thc_i2c_subip_init - Initialize and configure THC I2C subsystem 1442 + * 1443 + * @dev: The pointer of THC private device context 1444 + * @target_address: Slave address of touch device (TIC) 1445 + * @speed: I2C bus frequency speed mode 1446 + * @hcnt: I2C clock SCL high count 1447 + * @lcnt: I2C clock SCL low count 1448 + * 1449 + * Return: 0 on success, other error codes on failed. 1450 + */ 1451 + int thc_i2c_subip_init(struct thc_device *dev, const u32 target_address, 1452 + const u32 speed, const u32 hcnt, const u32 lcnt) 1453 + { 1454 + u32 read_size = sizeof(u32); 1455 + u32 val; 1456 + int ret; 1457 + 1458 + ret = thc_i2c_subip_pio_read(dev, THC_I2C_IC_ENABLE_OFFSET, &read_size, &val); 1459 + if (ret < 0) 1460 + return ret; 1461 + 1462 + val &= ~THC_I2C_IC_ENABLE_ENABLE; 1463 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_ENABLE_OFFSET, sizeof(u32), &val); 1464 + if (ret < 0) 1465 + return ret; 1466 + 1467 + ret = thc_i2c_subip_pio_read(dev, THC_I2C_IC_TAR_OFFSET, &read_size, &val); 1468 + if (ret < 0) 1469 + return ret; 1470 + 1471 + val &= ~THC_I2C_IC_TAR_IC_TAR; 1472 + val |= FIELD_PREP(THC_I2C_IC_TAR_IC_TAR, target_address); 1473 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_TAR_OFFSET, sizeof(u32), &val); 1474 + if (ret < 0) 1475 + return ret; 1476 + 1477 + ret = thc_i2c_subip_set_speed(dev, speed, hcnt, lcnt); 1478 + if (ret < 0) 1479 + return ret; 1480 + 1481 + val = I2C_SUBIP_INT_MASK_DEFAULT; 1482 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_INTR_MASK_OFFSET, sizeof(u32), &val); 1483 + if (ret < 0) 1484 + return ret; 1485 + 1486 + val = I2C_SUBIP_RX_TL_DEFAULT; 1487 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_RX_TL_OFFSET, sizeof(u32), &val); 1488 + if (ret < 0) 1489 + return ret; 1490 + 1491 + val = I2C_SUBIP_TX_TL_DEFAULT; 1492 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_TX_TL_OFFSET, sizeof(u32), &val); 1493 + if (ret < 0) 1494 + return ret; 1495 + 1496 + val = THC_I2C_IC_DMA_CR_RDMAE | THC_I2C_IC_DMA_CR_TDMAE; 1497 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_DMA_CR_OFFSET, sizeof(u32), &val); 1498 + if (ret < 0) 1499 + return ret; 1500 + 1501 + val = I2C_SUBIP_DMA_TDLR_DEFAULT; 1502 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_DMA_TDLR_OFFSET, sizeof(u32), &val); 1503 + if (ret < 0) 1504 + return ret; 1505 + 1506 + val = I2C_SUBIP_DMA_RDLR_DEFAULT; 1507 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_DMA_RDLR_OFFSET, sizeof(u32), &val); 1508 + if (ret < 0) 1509 + return ret; 1510 + 1511 + ret = thc_i2c_subip_pio_read(dev, THC_I2C_IC_ENABLE_OFFSET, &read_size, &val); 1512 + if (ret < 0) 1513 + return ret; 1514 + 1515 + val |= THC_I2C_IC_ENABLE_ENABLE; 1516 + ret = thc_i2c_subip_pio_write(dev, THC_I2C_IC_ENABLE_OFFSET, sizeof(u32), &val); 1517 + if (ret < 0) 1518 + return ret; 1519 + 1520 + dev->i2c_subip_regs = devm_kzalloc(dev->dev, sizeof(i2c_subip_regs), GFP_KERNEL); 1521 + if (!dev->i2c_subip_regs) 1522 + return -ENOMEM; 1523 + 1524 + return 0; 1525 + } 1526 + EXPORT_SYMBOL_NS_GPL(thc_i2c_subip_init, "INTEL_THC"); 1527 + 1528 + /** 1529 + * thc_i2c_subip_regs_save - Save THC I2C sub-subsystem register values to THC device context 1530 + * 1531 + * @dev: The pointer of THC private device context 1532 + * 1533 + * Return: 0 on success, other error codes on failed. 1534 + */ 1535 + int thc_i2c_subip_regs_save(struct thc_device *dev) 1536 + { 1537 + int ret; 1538 + u32 read_size = sizeof(u32); 1539 + 1540 + for (int i = 0; i < ARRAY_SIZE(i2c_subip_regs); i++) { 1541 + ret = thc_i2c_subip_pio_read(dev, i2c_subip_regs[i], 1542 + &read_size, (u32 *)&dev->i2c_subip_regs + i); 1543 + if (ret < 0) 1544 + return ret; 1545 + } 1546 + 1547 + return 0; 1548 + } 1549 + EXPORT_SYMBOL_NS_GPL(thc_i2c_subip_regs_save, "INTEL_THC"); 1550 + 1551 + /** 1552 + * thc_i2c_subip_regs_restore - Restore THC I2C subsystem registers from THC device context 1553 + * 1554 + * @dev: The pointer of THC private device context 1555 + * 1556 + * Return: 0 on success, other error codes on failed. 1557 + */ 1558 + int thc_i2c_subip_regs_restore(struct thc_device *dev) 1559 + { 1560 + int ret; 1561 + u32 write_size = sizeof(u32); 1562 + 1563 + for (int i = 0; i < ARRAY_SIZE(i2c_subip_regs); i++) { 1564 + ret = thc_i2c_subip_pio_write(dev, i2c_subip_regs[i], 1565 + write_size, (u32 *)&dev->i2c_subip_regs + i); 1566 + if (ret < 0) 1567 + return ret; 1568 + } 1569 + 1570 + return 0; 1571 + } 1572 + EXPORT_SYMBOL_NS_GPL(thc_i2c_subip_regs_restore, "INTEL_THC"); 1573 + 1574 + MODULE_AUTHOR("Xinpeng Sun <xinpeng.sun@intel.com>"); 1575 + MODULE_AUTHOR("Even Xu <even.xu@intel.com>"); 1576 + 1577 + MODULE_DESCRIPTION("Intel(R) Intel THC Hardware Driver"); 1578 + MODULE_LICENSE("GPL");
+116
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _INTEL_THC_DEV_H_ 5 + #define _INTEL_THC_DEV_H_ 6 + 7 + #include <linux/cdev.h> 8 + #include <linux/mutex.h> 9 + #include <linux/workqueue.h> 10 + 11 + #include "intel-thc-dma.h" 12 + 13 + #define THC_REGMAP_COMMON_OFFSET 0x10 14 + #define THC_REGMAP_MMIO_OFFSET 0x1000 15 + 16 + /* 17 + * THC Port type 18 + * @THC_PORT_TYPE_SPI: This port is used for HIDSPI 19 + * @THC_PORT_TYPE_I2C: This port is used for HIDI2C 20 + */ 21 + enum thc_port_type { 22 + THC_PORT_TYPE_SPI = 0, 23 + THC_PORT_TYPE_I2C = 1, 24 + }; 25 + 26 + /** 27 + * THC interrupt flag 28 + * @THC_NONDMA_INT: THC non-DMA interrupt 29 + * @THC_RXDMA1_INT: THC RxDMA1 interrupt 30 + * @THC_RXDMA2_INT: THC RxDMA2 interrupt 31 + * @THC_SWDMA_INT: THC SWDMA interrupt 32 + * @THC_TXDMA_INT: THC TXDMA interrupt 33 + * @THC_PIO_DONE_INT: THC PIO complete interrupt 34 + * @THC_I2CSUBIP_INT: THC I2C subsystem interrupt 35 + * @THC_TXN_ERR_INT: THC transfer error interrupt 36 + * @THC_FATAL_ERR_INT: THC fatal error interrupt 37 + */ 38 + enum thc_int_type { 39 + THC_NONDMA_INT = 0, 40 + THC_RXDMA1_INT = 1, 41 + THC_RXDMA2_INT = 2, 42 + THC_SWDMA_INT = 3, 43 + THC_TXDMA_INT = 4, 44 + THC_PIO_DONE_INT = 5, 45 + THC_I2CSUBIP_INT = 6, 46 + THC_TXN_ERR_INT = 7, 47 + THC_FATAL_ERR_INT = 8, 48 + THC_UNKNOWN_INT 49 + }; 50 + 51 + /** 52 + * struct thc_device - THC private device struct 53 + * @thc_regmap: MMIO regmap structure for accessing THC registers 54 + * @mmio_addr: MMIO registers address 55 + * @thc_bus_lock: mutex locker for THC config 56 + * @port_type: port type of THC port instance 57 + * @pio_int_supported: PIO interrupt supported flag 58 + * @dma_ctx: DMA specific data 59 + * @write_complete_wait: signal event for DMA write complete 60 + * @swdma_complete_wait: signal event for SWDMA sequence complete 61 + * @write_done: bool value that indicates if DMA write is done 62 + * @swdma_done: bool value that indicates if SWDMA swquence is done 63 + * @perf_limit: the delay between read operation and write operation 64 + * @i2c_subip_regs: the copy of THC I2C sub-system registers for resuming restore 65 + */ 66 + struct thc_device { 67 + struct device *dev; 68 + struct regmap *thc_regmap; 69 + void __iomem *mmio_addr; 70 + struct mutex thc_bus_lock; 71 + enum thc_port_type port_type; 72 + bool pio_int_supported; 73 + 74 + struct thc_dma_context *dma_ctx; 75 + 76 + wait_queue_head_t write_complete_wait; 77 + wait_queue_head_t swdma_complete_wait; 78 + bool write_done; 79 + bool swdma_done; 80 + 81 + u32 perf_limit; 82 + 83 + u32 *i2c_subip_regs; 84 + }; 85 + 86 + struct thc_device *thc_dev_init(struct device *device, void __iomem *mem_addr); 87 + int thc_tic_pio_read(struct thc_device *dev, const u32 address, 88 + const u32 size, u32 *actual_size, u32 *buffer); 89 + int thc_tic_pio_write(struct thc_device *dev, const u32 address, 90 + const u32 size, const u32 *buffer); 91 + int thc_tic_pio_write_and_read(struct thc_device *dev, const u32 address, 92 + const u32 write_size, const u32 *write_buffer, 93 + const u32 read_size, u32 *actual_size, u32 *read_buffer); 94 + void thc_interrupt_config(struct thc_device *dev); 95 + void thc_int_trigger_type_select(struct thc_device *dev, bool edge_trigger); 96 + void thc_interrupt_enable(struct thc_device *dev, bool int_enable); 97 + void thc_set_pio_interrupt_support(struct thc_device *dev, bool supported); 98 + int thc_interrupt_quiesce(const struct thc_device *dev, bool int_quiesce); 99 + void thc_ltr_config(struct thc_device *dev, u32 active_ltr_us, u32 lp_ltr_us); 100 + void thc_change_ltr_mode(struct thc_device *dev, u32 ltr_mode); 101 + void thc_ltr_unconfig(struct thc_device *dev); 102 + u32 thc_int_cause_read(struct thc_device *dev); 103 + int thc_interrupt_handler(struct thc_device *dev); 104 + int thc_port_select(struct thc_device *dev, enum thc_port_type port_type); 105 + int thc_spi_read_config(struct thc_device *dev, u32 spi_freq_val, 106 + u32 io_mode, u32 opcode, u32 spi_rd_mps); 107 + int thc_spi_write_config(struct thc_device *dev, u32 spi_freq_val, 108 + u32 io_mode, u32 opcode, u32 spi_wr_mps, u32 perf_limit); 109 + void thc_spi_input_output_address_config(struct thc_device *dev, u32 input_hdr_addr, 110 + u32 input_bdy_addr, u32 output_addr); 111 + int thc_i2c_subip_init(struct thc_device *dev, const u32 target_address, 112 + const u32 speed, const u32 hcnt, const u32 lcnt); 113 + int thc_i2c_subip_regs_save(struct thc_device *dev); 114 + int thc_i2c_subip_regs_restore(struct thc_device *dev); 115 + 116 + #endif /* _INTEL_THC_DEV_H_ */
+969
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #include <linux/bitfield.h> 5 + #include <linux/delay.h> 6 + #include <linux/overflow.h> 7 + #include <linux/regmap.h> 8 + #include <linux/scatterlist.h> 9 + 10 + #include "intel-thc-dev.h" 11 + #include "intel-thc-dma.h" 12 + #include "intel-thc-hw.h" 13 + 14 + static void dma_set_prd_base_addr(struct thc_device *dev, u64 physical_addr, 15 + struct thc_dma_configuration *dma_config) 16 + { 17 + u32 addr_high, addr_low; 18 + 19 + if (!dma_config->is_enabled) 20 + return; 21 + 22 + addr_high = upper_32_bits(physical_addr); 23 + addr_low = lower_32_bits(physical_addr); 24 + 25 + regmap_write(dev->thc_regmap, dma_config->prd_base_addr_high, addr_high); 26 + regmap_write(dev->thc_regmap, dma_config->prd_base_addr_low, addr_low); 27 + } 28 + 29 + static void dma_set_start_bit(struct thc_device *dev, 30 + struct thc_dma_configuration *dma_config) 31 + { 32 + u32 ctrl, mask, mbits, data, offset; 33 + 34 + if (!dma_config->is_enabled) 35 + return; 36 + 37 + switch (dma_config->dma_channel) { 38 + case THC_RXDMA1: 39 + case THC_RXDMA2: 40 + if (dma_config->dma_channel == THC_RXDMA2) { 41 + mbits = FIELD_PREP(THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_DATA_VAL, 42 + THC_BITMASK_INTERRUPT_TYPE_DATA); 43 + mask = THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_DATA_VAL; 44 + regmap_write_bits(dev->thc_regmap, 45 + THC_M_PRT_DEVINT_CFG_1_OFFSET, mask, mbits); 46 + } 47 + 48 + mbits = THC_M_PRT_READ_DMA_CNTRL_IE_EOF | 49 + THC_M_PRT_READ_DMA_CNTRL_SOO | 50 + THC_M_PRT_READ_DMA_CNTRL_IE_STALL | 51 + THC_M_PRT_READ_DMA_CNTRL_IE_ERROR | 52 + THC_M_PRT_READ_DMA_CNTRL_START; 53 + 54 + mask = THC_M_PRT_READ_DMA_CNTRL_TPCWP | mbits; 55 + mask |= THC_M_PRT_READ_DMA_CNTRL_INT_SW_DMA_EN; 56 + ctrl = FIELD_PREP(THC_M_PRT_READ_DMA_CNTRL_TPCWP, THC_POINTER_WRAPAROUND) | mbits; 57 + offset = dma_config->dma_channel == THC_RXDMA1 ? 58 + THC_M_PRT_READ_DMA_CNTRL_1_OFFSET : THC_M_PRT_READ_DMA_CNTRL_2_OFFSET; 59 + regmap_write_bits(dev->thc_regmap, offset, mask, ctrl); 60 + break; 61 + 62 + case THC_SWDMA: 63 + mbits = THC_M_PRT_READ_DMA_CNTRL_IE_DMACPL | 64 + THC_M_PRT_READ_DMA_CNTRL_IE_IOC | 65 + THC_M_PRT_READ_DMA_CNTRL_SOO | 66 + THC_M_PRT_READ_DMA_CNTRL_START; 67 + 68 + mask = THC_M_PRT_READ_DMA_CNTRL_TPCWP | mbits; 69 + ctrl = FIELD_PREP(THC_M_PRT_READ_DMA_CNTRL_TPCWP, THC_POINTER_WRAPAROUND) | mbits; 70 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_SW_OFFSET, 71 + mask, ctrl); 72 + break; 73 + 74 + case THC_TXDMA: 75 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_INT_STS_OFFSET, 76 + THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS, 77 + THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS); 78 + 79 + /* Select interrupt or polling method upon Write completion */ 80 + if (dev->dma_ctx->use_write_interrupts) 81 + data = THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL; 82 + else 83 + data = 0; 84 + 85 + data |= THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_START; 86 + mask = THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL | 87 + THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_START; 88 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_DMA_CNTRL_OFFSET, 89 + mask, data); 90 + break; 91 + 92 + default: 93 + break; 94 + } 95 + } 96 + 97 + static void dma_set_prd_control(struct thc_device *dev, u8 entry_count, u8 cb_depth, 98 + struct thc_dma_configuration *dma_config) 99 + { 100 + u32 ctrl, mask; 101 + 102 + if (!dma_config->is_enabled) 103 + return; 104 + 105 + if (dma_config->dma_channel == THC_TXDMA) { 106 + mask = THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_PTEC; 107 + ctrl = FIELD_PREP(THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_PTEC, entry_count); 108 + } else { 109 + mask = THC_M_PRT_RPRD_CNTRL_PTEC | THC_M_PRT_RPRD_CNTRL_PCD; 110 + ctrl = FIELD_PREP(THC_M_PRT_RPRD_CNTRL_PTEC, entry_count) | 111 + FIELD_PREP(THC_M_PRT_RPRD_CNTRL_PCD, cb_depth); 112 + } 113 + 114 + regmap_write_bits(dev->thc_regmap, dma_config->prd_cntrl, mask, ctrl); 115 + } 116 + 117 + static void dma_clear_prd_control(struct thc_device *dev, 118 + struct thc_dma_configuration *dma_config) 119 + { 120 + u32 mask; 121 + 122 + if (!dma_config->is_enabled) 123 + return; 124 + 125 + if (dma_config->dma_channel == THC_TXDMA) 126 + mask = THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_PTEC; 127 + else 128 + mask = THC_M_PRT_RPRD_CNTRL_PTEC | THC_M_PRT_RPRD_CNTRL_PCD; 129 + 130 + regmap_write_bits(dev->thc_regmap, dma_config->prd_cntrl, mask, 0); 131 + } 132 + 133 + static u8 dma_get_read_pointer(struct thc_device *dev, 134 + struct thc_dma_configuration *dma_config) 135 + { 136 + u32 ctrl, read_pointer; 137 + 138 + regmap_read(dev->thc_regmap, dma_config->dma_cntrl, &ctrl); 139 + read_pointer = FIELD_GET(THC_M_PRT_READ_DMA_CNTRL_TPCRP, ctrl); 140 + 141 + dev_dbg(dev->dev, "THC_M_PRT_READ_DMA_CNTRL 0x%x offset 0x%x TPCRP 0x%x\n", 142 + ctrl, dma_config->dma_cntrl, read_pointer); 143 + 144 + return read_pointer; 145 + } 146 + 147 + static u8 dma_get_write_pointer(struct thc_device *dev, 148 + struct thc_dma_configuration *dma_config) 149 + { 150 + u32 ctrl, write_pointer; 151 + 152 + regmap_read(dev->thc_regmap, dma_config->dma_cntrl, &ctrl); 153 + write_pointer = FIELD_GET(THC_M_PRT_READ_DMA_CNTRL_TPCWP, ctrl); 154 + 155 + dev_dbg(dev->dev, "THC_M_PRT_READ_DMA_CNTRL 0x%x offset 0x%x TPCWP 0x%x\n", 156 + ctrl, dma_config->dma_cntrl, write_pointer); 157 + 158 + return write_pointer; 159 + } 160 + 161 + static void dma_set_write_pointer(struct thc_device *dev, u8 value, 162 + struct thc_dma_configuration *dma_config) 163 + { 164 + u32 ctrl, mask; 165 + 166 + mask = THC_M_PRT_READ_DMA_CNTRL_TPCWP; 167 + ctrl = FIELD_PREP(THC_M_PRT_READ_DMA_CNTRL_TPCWP, value); 168 + regmap_write_bits(dev->thc_regmap, dma_config->dma_cntrl, mask, ctrl); 169 + } 170 + 171 + static size_t dma_get_max_packet_size(struct thc_device *dev, 172 + struct thc_dma_configuration *dma_config) 173 + { 174 + return dma_config->max_packet_size; 175 + } 176 + 177 + static void dma_set_max_packet_size(struct thc_device *dev, size_t size, 178 + struct thc_dma_configuration *dma_config) 179 + { 180 + if (size) { 181 + dma_config->max_packet_size = ALIGN(size, SZ_4K); 182 + dma_config->is_enabled = true; 183 + } 184 + } 185 + 186 + static void thc_copy_one_sgl_to_prd(struct thc_device *dev, 187 + struct thc_dma_configuration *config, 188 + unsigned int ind) 189 + { 190 + struct thc_prd_table *prd_tbl; 191 + struct scatterlist *sg; 192 + int j; 193 + 194 + prd_tbl = &config->prd_tbls[ind]; 195 + 196 + for_each_sg(config->sgls[ind], sg, config->sgls_nent[ind], j) { 197 + prd_tbl->entries[j].dest_addr = 198 + sg_dma_address(sg) >> THC_ADDRESS_SHIFT; 199 + prd_tbl->entries[j].len = sg_dma_len(sg); 200 + prd_tbl->entries[j].hw_status = 0; 201 + prd_tbl->entries[j].end_of_prd = 0; 202 + } 203 + 204 + /* Set the end_of_prd flag in the last filled entry */ 205 + if (j > 0) 206 + prd_tbl->entries[j - 1].end_of_prd = 1; 207 + } 208 + 209 + static void thc_copy_sgls_to_prd(struct thc_device *dev, 210 + struct thc_dma_configuration *config) 211 + { 212 + unsigned int i; 213 + 214 + memset(config->prd_tbls, 0, array_size(PRD_TABLE_SIZE, config->prd_tbl_num)); 215 + 216 + for (i = 0; i < config->prd_tbl_num; i++) 217 + thc_copy_one_sgl_to_prd(dev, config, i); 218 + } 219 + 220 + static int setup_dma_buffers(struct thc_device *dev, 221 + struct thc_dma_configuration *config, 222 + enum dma_data_direction dir) 223 + { 224 + size_t prd_tbls_size = array_size(PRD_TABLE_SIZE, config->prd_tbl_num); 225 + unsigned int i, nent = PRD_ENTRIES_NUM; 226 + dma_addr_t dma_handle; 227 + void *cpu_addr; 228 + size_t buf_sz; 229 + int count; 230 + 231 + if (!config->is_enabled) 232 + return 0; 233 + 234 + memset(config->sgls, 0, sizeof(config->sgls)); 235 + memset(config->sgls_nent, 0, sizeof(config->sgls_nent)); 236 + 237 + cpu_addr = dma_alloc_coherent(dev->dev, prd_tbls_size, 238 + &dma_handle, GFP_KERNEL); 239 + if (!cpu_addr) 240 + return -ENOMEM; 241 + 242 + config->prd_tbls = cpu_addr; 243 + config->prd_tbls_dma_handle = dma_handle; 244 + 245 + buf_sz = dma_get_max_packet_size(dev, config); 246 + 247 + /* Allocate and map the scatter-gather lists, one for each PRD table */ 248 + for (i = 0; i < config->prd_tbl_num; i++) { 249 + config->sgls[i] = sgl_alloc(buf_sz, GFP_KERNEL, &nent); 250 + if (!config->sgls[i] || nent > PRD_ENTRIES_NUM) { 251 + dev_err_once(dev->dev, "sgl_alloc (%uth) failed, nent %u\n", 252 + i, nent); 253 + return -ENOMEM; 254 + } 255 + count = dma_map_sg(dev->dev, config->sgls[i], nent, dir); 256 + 257 + config->sgls_nent[i] = count; 258 + } 259 + 260 + thc_copy_sgls_to_prd(dev, config); 261 + 262 + return 0; 263 + } 264 + 265 + static void thc_reset_dma_settings(struct thc_device *dev) 266 + { 267 + /* Stop all DMA channels and reset DMA read pointers */ 268 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 269 + THC_M_PRT_READ_DMA_CNTRL_START, 0); 270 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET, 271 + THC_M_PRT_READ_DMA_CNTRL_START, 0); 272 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_SW_OFFSET, 273 + THC_M_PRT_READ_DMA_CNTRL_START, 0); 274 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_DMA_CNTRL_OFFSET, 275 + THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_START, 0); 276 + 277 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 278 + THC_M_PRT_READ_DMA_CNTRL_TPCPR, 279 + THC_M_PRT_READ_DMA_CNTRL_TPCPR); 280 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET, 281 + THC_M_PRT_READ_DMA_CNTRL_TPCPR, 282 + THC_M_PRT_READ_DMA_CNTRL_TPCPR); 283 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_SW_OFFSET, 284 + THC_M_PRT_READ_DMA_CNTRL_TPCPR, 285 + THC_M_PRT_READ_DMA_CNTRL_TPCPR); 286 + } 287 + 288 + static void release_dma_buffers(struct thc_device *dev, 289 + struct thc_dma_configuration *config) 290 + { 291 + size_t prd_tbls_size = array_size(PRD_TABLE_SIZE, config->prd_tbl_num); 292 + unsigned int i; 293 + 294 + if (!config->is_enabled) 295 + return; 296 + 297 + for (i = 0; i < config->prd_tbl_num; i++) { 298 + if (!config->sgls[i] | !config->sgls_nent[i]) 299 + continue; 300 + 301 + dma_unmap_sg(dev->dev, config->sgls[i], 302 + config->sgls_nent[i], 303 + config->dir); 304 + 305 + sgl_free(config->sgls[i]); 306 + config->sgls[i] = NULL; 307 + } 308 + 309 + memset(config->prd_tbls, 0, prd_tbls_size); 310 + 311 + if (config->prd_tbls) { 312 + dma_free_coherent(dev->dev, prd_tbls_size, config->prd_tbls, 313 + config->prd_tbls_dma_handle); 314 + config->prd_tbls = NULL; 315 + config->prd_tbls_dma_handle = 0; 316 + } 317 + } 318 + 319 + struct thc_dma_context *thc_dma_init(struct thc_device *dev) 320 + { 321 + struct thc_dma_context *dma_ctx; 322 + 323 + dma_ctx = devm_kzalloc(dev->dev, sizeof(*dma_ctx), GFP_KERNEL); 324 + if (!dma_ctx) 325 + return NULL; 326 + 327 + dev->dma_ctx = dma_ctx; 328 + 329 + dma_ctx->dma_config[THC_RXDMA1].dma_channel = THC_RXDMA1; 330 + dma_ctx->dma_config[THC_RXDMA2].dma_channel = THC_RXDMA2; 331 + dma_ctx->dma_config[THC_TXDMA].dma_channel = THC_TXDMA; 332 + dma_ctx->dma_config[THC_SWDMA].dma_channel = THC_SWDMA; 333 + 334 + dma_ctx->dma_config[THC_RXDMA1].dir = DMA_FROM_DEVICE; 335 + dma_ctx->dma_config[THC_RXDMA2].dir = DMA_FROM_DEVICE; 336 + dma_ctx->dma_config[THC_TXDMA].dir = DMA_TO_DEVICE; 337 + dma_ctx->dma_config[THC_SWDMA].dir = DMA_FROM_DEVICE; 338 + 339 + dma_ctx->dma_config[THC_RXDMA1].prd_tbl_num = PRD_TABLES_NUM; 340 + dma_ctx->dma_config[THC_RXDMA2].prd_tbl_num = PRD_TABLES_NUM; 341 + dma_ctx->dma_config[THC_TXDMA].prd_tbl_num = 1; 342 + dma_ctx->dma_config[THC_SWDMA].prd_tbl_num = 1; 343 + 344 + dma_ctx->dma_config[THC_RXDMA1].prd_base_addr_high = THC_M_PRT_RPRD_BA_HI_1_OFFSET; 345 + dma_ctx->dma_config[THC_RXDMA2].prd_base_addr_high = THC_M_PRT_RPRD_BA_HI_2_OFFSET; 346 + dma_ctx->dma_config[THC_TXDMA].prd_base_addr_high = THC_M_PRT_WPRD_BA_HI_OFFSET; 347 + dma_ctx->dma_config[THC_SWDMA].prd_base_addr_high = THC_M_PRT_RPRD_BA_HI_SW_OFFSET; 348 + 349 + dma_ctx->dma_config[THC_RXDMA1].prd_base_addr_low = THC_M_PRT_RPRD_BA_LOW_1_OFFSET; 350 + dma_ctx->dma_config[THC_RXDMA2].prd_base_addr_low = THC_M_PRT_RPRD_BA_LOW_2_OFFSET; 351 + dma_ctx->dma_config[THC_TXDMA].prd_base_addr_low = THC_M_PRT_WPRD_BA_LOW_OFFSET; 352 + dma_ctx->dma_config[THC_SWDMA].prd_base_addr_low = THC_M_PRT_RPRD_BA_LOW_SW_OFFSET; 353 + 354 + dma_ctx->dma_config[THC_RXDMA1].prd_cntrl = THC_M_PRT_RPRD_CNTRL_1_OFFSET; 355 + dma_ctx->dma_config[THC_RXDMA2].prd_cntrl = THC_M_PRT_RPRD_CNTRL_2_OFFSET; 356 + dma_ctx->dma_config[THC_TXDMA].prd_cntrl = THC_M_PRT_WRITE_DMA_CNTRL_OFFSET; 357 + dma_ctx->dma_config[THC_SWDMA].prd_cntrl = THC_M_PRT_RPRD_CNTRL_SW_OFFSET; 358 + 359 + dma_ctx->dma_config[THC_RXDMA1].dma_cntrl = THC_M_PRT_READ_DMA_CNTRL_1_OFFSET; 360 + dma_ctx->dma_config[THC_RXDMA2].dma_cntrl = THC_M_PRT_READ_DMA_CNTRL_2_OFFSET; 361 + dma_ctx->dma_config[THC_TXDMA].dma_cntrl = THC_M_PRT_WRITE_DMA_CNTRL_OFFSET; 362 + dma_ctx->dma_config[THC_SWDMA].dma_cntrl = THC_M_PRT_READ_DMA_CNTRL_SW_OFFSET; 363 + 364 + /* Enable write DMA completion interrupt by default */ 365 + dma_ctx->use_write_interrupts = 1; 366 + 367 + return dma_ctx; 368 + } 369 + 370 + /** 371 + * thc_dma_set_max_packet_sizes - Set max packet sizes for all DMA engines 372 + * 373 + * @dev: The pointer of THC private device context 374 + * @mps_read1: RxDMA1 max packet size 375 + * @mps_read2: RxDMA2 max packet size 376 + * @mps_write: TxDMA max packet size 377 + * @mps_swdma: Software DMA max packet size 378 + * 379 + * If mps is not 0, it means the corresponding DMA channel is used, then set 380 + * the flag to turn on this channel. 381 + * 382 + * Return: 0 on success, other error codes on failed. 383 + */ 384 + int thc_dma_set_max_packet_sizes(struct thc_device *dev, size_t mps_read1, 385 + size_t mps_read2, size_t mps_write, 386 + size_t mps_swdma) 387 + { 388 + if (!dev->dma_ctx) { 389 + dev_err_once(dev->dev, 390 + "Cannot set max packet sizes because DMA context is NULL!\n"); 391 + return -EINVAL; 392 + } 393 + 394 + dma_set_max_packet_size(dev, mps_read1, &dev->dma_ctx->dma_config[THC_RXDMA1]); 395 + dma_set_max_packet_size(dev, mps_read2, &dev->dma_ctx->dma_config[THC_RXDMA2]); 396 + dma_set_max_packet_size(dev, mps_write, &dev->dma_ctx->dma_config[THC_TXDMA]); 397 + dma_set_max_packet_size(dev, mps_swdma, &dev->dma_ctx->dma_config[THC_SWDMA]); 398 + 399 + return 0; 400 + } 401 + EXPORT_SYMBOL_NS_GPL(thc_dma_set_max_packet_sizes, "INTEL_THC"); 402 + 403 + /** 404 + * thc_dma_allocate - Allocate DMA buffers for all DMA engines 405 + * 406 + * @dev: The pointer of THC private device context 407 + * 408 + * Return: 0 on success, other error codes on failed. 409 + */ 410 + int thc_dma_allocate(struct thc_device *dev) 411 + { 412 + int ret, chan; 413 + 414 + for (chan = 0; chan < MAX_THC_DMA_CHANNEL; chan++) { 415 + ret = setup_dma_buffers(dev, &dev->dma_ctx->dma_config[chan], 416 + dev->dma_ctx->dma_config[chan].dir); 417 + if (ret < 0) { 418 + dev_err_once(dev->dev, "DMA setup failed for DMA channel %d\n", chan); 419 + goto release_bufs; 420 + } 421 + } 422 + 423 + return 0; 424 + 425 + release_bufs: 426 + while (chan--) 427 + release_dma_buffers(dev, &dev->dma_ctx->dma_config[chan]); 428 + 429 + return ret; 430 + } 431 + EXPORT_SYMBOL_NS_GPL(thc_dma_allocate, "INTEL_THC"); 432 + 433 + /** 434 + * thc_dma_release - Release DMA buffers for all DMA engines 435 + * 436 + * @dev: The pointer of THC private device context 437 + */ 438 + void thc_dma_release(struct thc_device *dev) 439 + { 440 + int chan; 441 + 442 + for (chan = 0; chan < MAX_THC_DMA_CHANNEL; chan++) 443 + release_dma_buffers(dev, &dev->dma_ctx->dma_config[chan]); 444 + } 445 + EXPORT_SYMBOL_NS_GPL(thc_dma_release, "INTEL_THC"); 446 + 447 + static int calc_prd_entries_num(struct thc_prd_table *prd_tbl, 448 + size_t mes_len, u8 *nent) 449 + { 450 + *nent = DIV_ROUND_UP(mes_len, THC_MIN_BYTES_PER_SG_LIST_ENTRY); 451 + if (*nent > PRD_ENTRIES_NUM) 452 + return -EMSGSIZE; 453 + 454 + return 0; 455 + } 456 + 457 + static size_t calc_message_len(struct thc_prd_table *prd_tbl, u8 *nent) 458 + { 459 + size_t mes_len = 0; 460 + unsigned int j; 461 + 462 + for (j = 0; j < PRD_ENTRIES_NUM; j++) { 463 + mes_len += prd_tbl->entries[j].len; 464 + if (prd_tbl->entries[j].end_of_prd) 465 + break; 466 + } 467 + 468 + *nent = j + 1; 469 + 470 + return mes_len; 471 + } 472 + 473 + /** 474 + * thc_dma_configure - Configure DMA settings for all DMA engines 475 + * 476 + * @dev: The pointer of THC private device context 477 + * 478 + * Return: 0 on success, other error codes on failed. 479 + */ 480 + int thc_dma_configure(struct thc_device *dev) 481 + { 482 + struct thc_dma_context *dma_ctx = dev->dma_ctx; 483 + int chan; 484 + 485 + thc_reset_dma_settings(dev); 486 + 487 + if (!dma_ctx) { 488 + dev_err_once(dev->dev, "Cannot do DMA configure because DMA context is NULL\n"); 489 + return -EINVAL; 490 + } 491 + 492 + for (chan = 0; chan < MAX_THC_DMA_CHANNEL; chan++) { 493 + dma_set_prd_base_addr(dev, 494 + dma_ctx->dma_config[chan].prd_tbls_dma_handle, 495 + &dma_ctx->dma_config[chan]); 496 + 497 + dma_set_prd_control(dev, PRD_ENTRIES_NUM - 1, 498 + dma_ctx->dma_config[chan].prd_tbl_num - 1, 499 + &dma_ctx->dma_config[chan]); 500 + } 501 + 502 + /* Start read2 DMA engine */ 503 + dma_set_start_bit(dev, &dma_ctx->dma_config[THC_RXDMA2]); 504 + 505 + dev_dbg(dev->dev, "DMA configured successfully!\n"); 506 + 507 + return 0; 508 + } 509 + EXPORT_SYMBOL_NS_GPL(thc_dma_configure, "INTEL_THC"); 510 + 511 + /** 512 + * thc_dma_unconfigure - Unconfigure DMA settings for all DMA engines 513 + * 514 + * @dev: The pointer of THC private device context 515 + */ 516 + void thc_dma_unconfigure(struct thc_device *dev) 517 + { 518 + int chan; 519 + 520 + for (chan = 0; chan < MAX_THC_DMA_CHANNEL; chan++) { 521 + dma_set_prd_base_addr(dev, 0, &dev->dma_ctx->dma_config[chan]); 522 + dma_clear_prd_control(dev, &dev->dma_ctx->dma_config[chan]); 523 + } 524 + 525 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, 526 + THC_M_PRT_READ_DMA_CNTRL_START, 0); 527 + 528 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET, 529 + THC_M_PRT_READ_DMA_CNTRL_START, 0); 530 + } 531 + EXPORT_SYMBOL_NS_GPL(thc_dma_unconfigure, "INTEL_THC"); 532 + 533 + static int thc_wait_for_dma_pause(struct thc_device *dev, enum thc_dma_channel channel) 534 + { 535 + u32 ctrl_reg, sts_reg, sts; 536 + int ret; 537 + 538 + ctrl_reg = (channel == THC_RXDMA1) ? THC_M_PRT_READ_DMA_CNTRL_1_OFFSET : 539 + ((channel == THC_RXDMA2) ? THC_M_PRT_READ_DMA_CNTRL_2_OFFSET : 540 + THC_M_PRT_READ_DMA_CNTRL_SW_OFFSET); 541 + 542 + regmap_write_bits(dev->thc_regmap, ctrl_reg, THC_M_PRT_READ_DMA_CNTRL_START, 0); 543 + 544 + sts_reg = (channel == THC_RXDMA1) ? THC_M_PRT_READ_DMA_INT_STS_1_OFFSET : 545 + ((channel == THC_RXDMA2) ? THC_M_PRT_READ_DMA_INT_STS_2_OFFSET : 546 + THC_M_PRT_READ_DMA_INT_STS_SW_OFFSET); 547 + 548 + ret = regmap_read_poll_timeout(dev->thc_regmap, sts_reg, sts, 549 + !(sts & THC_M_PRT_READ_DMA_INT_STS_ACTIVE), 550 + THC_DEFAULT_RXDMA_POLLING_US_INTERVAL, 551 + THC_DEFAULT_RXDMA_POLLING_US_TIMEOUT); 552 + 553 + if (ret) { 554 + dev_err_once(dev->dev, 555 + "Timeout while waiting for DMA %d stop\n", channel); 556 + return ret; 557 + } 558 + 559 + return 0; 560 + } 561 + 562 + static int read_dma_buffer(struct thc_device *dev, 563 + struct thc_dma_configuration *read_config, 564 + u8 prd_table_index, void *read_buff) 565 + { 566 + struct thc_prd_table *prd_tbl; 567 + struct scatterlist *sg; 568 + size_t mes_len, ret; 569 + u8 nent; 570 + 571 + if (prd_table_index >= read_config->prd_tbl_num) { 572 + dev_err_once(dev->dev, "PRD table index %d too big\n", prd_table_index); 573 + return -EINVAL; 574 + } 575 + 576 + prd_tbl = &read_config->prd_tbls[prd_table_index]; 577 + mes_len = calc_message_len(prd_tbl, &nent); 578 + if (mes_len > read_config->max_packet_size) { 579 + dev_err(dev->dev, 580 + "Message length %zu is bigger than buffer length %lu\n", 581 + mes_len, read_config->max_packet_size); 582 + return -EMSGSIZE; 583 + } 584 + 585 + sg = read_config->sgls[prd_table_index]; 586 + ret = sg_copy_to_buffer(sg, nent, read_buff, mes_len); 587 + if (ret != mes_len) { 588 + dev_err_once(dev->dev, "Copied %zu bytes instead of requested %zu\n", 589 + ret, mes_len); 590 + return -EIO; 591 + } 592 + 593 + return mes_len; 594 + } 595 + 596 + static void update_write_pointer(struct thc_device *dev, 597 + struct thc_dma_configuration *read_config) 598 + { 599 + u8 write_ptr = dma_get_write_pointer(dev, read_config); 600 + 601 + if (write_ptr + 1 == THC_WRAPAROUND_VALUE_ODD) 602 + dma_set_write_pointer(dev, THC_POINTER_WRAPAROUND, read_config); 603 + else if (write_ptr + 1 == THC_WRAPAROUND_VALUE_EVEN) 604 + dma_set_write_pointer(dev, 0, read_config); 605 + else 606 + dma_set_write_pointer(dev, write_ptr + 1, read_config); 607 + } 608 + 609 + static int is_dma_buf_empty(struct thc_device *dev, 610 + struct thc_dma_configuration *read_config, 611 + u8 *read_ptr, u8 *write_ptr) 612 + { 613 + *read_ptr = dma_get_read_pointer(dev, read_config); 614 + *write_ptr = dma_get_write_pointer(dev, read_config); 615 + 616 + if ((*read_ptr & THC_POINTER_MASK) == (*write_ptr & THC_POINTER_MASK)) 617 + if (*read_ptr != *write_ptr) 618 + return true; 619 + 620 + return false; 621 + } 622 + 623 + static int thc_dma_read(struct thc_device *dev, 624 + struct thc_dma_configuration *read_config, 625 + void *read_buff, size_t *read_len, int *read_finished) 626 + { 627 + u8 read_ptr, write_ptr, prd_table_index; 628 + int status; 629 + 630 + if (!is_dma_buf_empty(dev, read_config, &read_ptr, &write_ptr)) { 631 + prd_table_index = write_ptr & THC_POINTER_MASK; 632 + 633 + status = read_dma_buffer(dev, read_config, prd_table_index, read_buff); 634 + if (status <= 0) { 635 + dev_err_once(dev->dev, "read DMA buffer failed %d\n", status); 636 + return -EIO; 637 + } 638 + 639 + *read_len = status; 640 + 641 + /* Clear the relevant PRD table */ 642 + thc_copy_one_sgl_to_prd(dev, read_config, prd_table_index); 643 + 644 + /* Increment the write pointer to let the HW know we have processed this PRD */ 645 + update_write_pointer(dev, read_config); 646 + } 647 + 648 + /* 649 + * This function only reads one frame from PRD table for each call, so we need to 650 + * check if all DMAed data is read out and return the flag to the caller. Caller 651 + * should repeatedly call thc_dma_read() until all DMAed data is handled. 652 + */ 653 + if (read_finished) 654 + *read_finished = is_dma_buf_empty(dev, read_config, &read_ptr, &write_ptr) ? 1 : 0; 655 + 656 + return 0; 657 + } 658 + 659 + /** 660 + * thc_rxdma_read - Read data from RXDMA buffer 661 + * 662 + * @dev: The pointer of THC private device context 663 + * @dma_channel: The RXDMA engine of read data source 664 + * @read_buff: The pointer of the read data buffer 665 + * @read_len: The pointer of the read data length 666 + * @read_finished: The pointer of the flag indicating if all pending data has been read out 667 + * 668 + * Return: 0 on success, other error codes on failed. 669 + */ 670 + int thc_rxdma_read(struct thc_device *dev, enum thc_dma_channel dma_channel, 671 + void *read_buff, size_t *read_len, int *read_finished) 672 + { 673 + struct thc_dma_configuration *dma_config; 674 + int ret; 675 + 676 + dma_config = &dev->dma_ctx->dma_config[dma_channel]; 677 + 678 + if (!dma_config->is_enabled) { 679 + dev_err_once(dev->dev, "The DMA channel %d is not enabled", dma_channel); 680 + return -EINVAL; 681 + } 682 + 683 + if (!read_buff || !read_len) { 684 + dev_err(dev->dev, "Invalid input parameters, read_buff %p, read_len %p\n", 685 + read_buff, read_len); 686 + return -EINVAL; 687 + } 688 + 689 + if (dma_channel >= THC_TXDMA) { 690 + dev_err(dev->dev, "Unsupported DMA channel for RxDMA read, %d\n", dma_channel); 691 + return -EINVAL; 692 + } 693 + 694 + ret = thc_dma_read(dev, dma_config, read_buff, read_len, read_finished); 695 + 696 + return ret; 697 + } 698 + EXPORT_SYMBOL_NS_GPL(thc_rxdma_read, "INTEL_THC"); 699 + 700 + static int thc_swdma_read_start(struct thc_device *dev, void *write_buff, 701 + size_t write_len, u32 *prd_tbl_len) 702 + { 703 + u32 mask, val, data0 = 0, data1 = 0; 704 + int ret; 705 + 706 + ret = thc_interrupt_quiesce(dev, true); 707 + if (ret) 708 + return ret; 709 + 710 + if (thc_wait_for_dma_pause(dev, THC_RXDMA1) || thc_wait_for_dma_pause(dev, THC_RXDMA2)) 711 + return -EIO; 712 + 713 + thc_reset_dma_settings(dev); 714 + 715 + mask = THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_WBC | 716 + THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_RX_DLEN_EN; 717 + val = FIELD_PREP(THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_WBC, write_len) | 718 + ((!prd_tbl_len) ? THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_RX_DLEN_EN : 0); 719 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_RPRD_CNTRL_SW_OFFSET, 720 + mask, val); 721 + 722 + if (prd_tbl_len) { 723 + mask = THC_M_PRT_SW_DMA_PRD_TABLE_LEN_THC_M_PRT_SW_DMA_PRD_TABLE_LEN; 724 + val = FIELD_PREP(THC_M_PRT_SW_DMA_PRD_TABLE_LEN_THC_M_PRT_SW_DMA_PRD_TABLE_LEN, 725 + *prd_tbl_len); 726 + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SW_DMA_PRD_TABLE_LEN_OFFSET, 727 + mask, val); 728 + } 729 + 730 + if (write_len <= sizeof(u32)) { 731 + for (int i = 0; i < write_len; i++) 732 + data0 |= *(((u8 *)write_buff) + i) << (i * 8); 733 + 734 + regmap_write(dev->thc_regmap, THC_M_PRT_SW_SEQ_DATA0_ADDR_OFFSET, data0); 735 + } else if (write_len <= 2 * sizeof(u32)) { 736 + data0 = *(u32 *)write_buff; 737 + regmap_write(dev->thc_regmap, THC_M_PRT_SW_SEQ_DATA0_ADDR_OFFSET, data0); 738 + 739 + for (int i = 0; i < write_len - sizeof(u32); i++) 740 + data1 |= *(((u8 *)write_buff) + sizeof(u32) + i) << (i * 8); 741 + 742 + regmap_write(dev->thc_regmap, THC_M_PRT_SW_SEQ_DATA1_OFFSET, data1); 743 + } 744 + dma_set_start_bit(dev, &dev->dma_ctx->dma_config[THC_SWDMA]); 745 + 746 + return 0; 747 + } 748 + 749 + static int thc_swdma_read_completion(struct thc_device *dev) 750 + { 751 + int ret; 752 + 753 + ret = thc_wait_for_dma_pause(dev, THC_SWDMA); 754 + if (ret) 755 + return ret; 756 + 757 + thc_reset_dma_settings(dev); 758 + 759 + dma_set_start_bit(dev, &dev->dma_ctx->dma_config[THC_RXDMA2]); 760 + 761 + ret = thc_interrupt_quiesce(dev, false); 762 + 763 + return ret; 764 + } 765 + 766 + /** 767 + * thc_swdma_read - Use software DMA to read data from touch device 768 + * 769 + * @dev: The pointer of THC private device context 770 + * @write_buff: The pointer of write buffer for SWDMA sequence 771 + * @write_len: The write data length for SWDMA sequence 772 + * @prd_tbl_len: The prd table length of SWDMA engine, can be set to NULL 773 + * @read_buff: The pointer of the read data buffer 774 + * @read_len: The pointer of the read data length 775 + * 776 + * Return: 0 on success, other error codes on failed. 777 + */ 778 + int thc_swdma_read(struct thc_device *dev, void *write_buff, size_t write_len, 779 + u32 *prd_tbl_len, void *read_buff, size_t *read_len) 780 + { 781 + int ret; 782 + 783 + if (!(&dev->dma_ctx->dma_config[THC_SWDMA])->is_enabled) { 784 + dev_err_once(dev->dev, "The SWDMA channel is not enabled"); 785 + return -EINVAL; 786 + } 787 + 788 + if (!read_buff || !read_len) { 789 + dev_err(dev->dev, "Invalid input parameters, read_buff %p, read_len %p\n", 790 + read_buff, read_len); 791 + return -EINVAL; 792 + } 793 + 794 + if (mutex_lock_interruptible(&dev->thc_bus_lock)) 795 + return -EINTR; 796 + 797 + dev->swdma_done = false; 798 + 799 + ret = thc_swdma_read_start(dev, write_buff, write_len, prd_tbl_len); 800 + if (ret) 801 + goto end; 802 + 803 + ret = wait_event_interruptible_timeout(dev->swdma_complete_wait, dev->swdma_done, 1 * HZ); 804 + if (ret <= 0 || !dev->swdma_done) { 805 + dev_err_once(dev->dev, "timeout for waiting SWDMA completion\n"); 806 + ret = -ETIMEDOUT; 807 + goto end; 808 + } 809 + 810 + ret = thc_dma_read(dev, &dev->dma_ctx->dma_config[THC_SWDMA], read_buff, read_len, NULL); 811 + if (ret) 812 + goto end; 813 + 814 + ret = thc_swdma_read_completion(dev); 815 + 816 + end: 817 + mutex_unlock(&dev->thc_bus_lock); 818 + return ret; 819 + } 820 + EXPORT_SYMBOL_NS_GPL(thc_swdma_read, "INTEL_THC"); 821 + 822 + static int write_dma_buffer(struct thc_device *dev, 823 + void *buffer, size_t buf_len) 824 + { 825 + struct thc_dma_configuration *write_config = &dev->dma_ctx->dma_config[THC_TXDMA]; 826 + struct thc_prd_table *prd_tbl; 827 + struct scatterlist *sg; 828 + unsigned long len_left; 829 + size_t ret; 830 + u8 nent; 831 + int i; 832 + 833 + /* There is only one PRD table for write */ 834 + prd_tbl = &write_config->prd_tbls[0]; 835 + 836 + if (calc_prd_entries_num(prd_tbl, buf_len, &nent) < 0) { 837 + dev_err(dev->dev, "Tx message length too big (%zu)\n", buf_len); 838 + return -EOVERFLOW; 839 + } 840 + 841 + sg = write_config->sgls[0]; 842 + ret = sg_copy_from_buffer(sg, nent, buffer, buf_len); 843 + if (ret != buf_len) { 844 + dev_err_once(dev->dev, "Copied %zu bytes instead of requested %zu\n", 845 + ret, buf_len); 846 + return -EIO; 847 + } 848 + 849 + prd_tbl = &write_config->prd_tbls[0]; 850 + len_left = buf_len; 851 + 852 + for_each_sg(write_config->sgls[0], sg, write_config->sgls_nent[0], i) { 853 + if (sg_dma_address(sg) == 0 || sg_dma_len(sg) == 0) { 854 + dev_err_once(dev->dev, "SGList: zero address or length\n"); 855 + return -EINVAL; 856 + } 857 + 858 + prd_tbl->entries[i].dest_addr = 859 + sg_dma_address(sg) >> THC_ADDRESS_SHIFT; 860 + 861 + if (len_left < sg_dma_len(sg)) { 862 + prd_tbl->entries[i].len = len_left; 863 + prd_tbl->entries[i].end_of_prd = 1; 864 + break; 865 + } 866 + 867 + prd_tbl->entries[i].len = sg_dma_len(sg); 868 + prd_tbl->entries[i].end_of_prd = 0; 869 + 870 + len_left -= sg_dma_len(sg); 871 + } 872 + 873 + dma_set_prd_control(dev, i, 0, write_config); 874 + 875 + return 0; 876 + } 877 + 878 + static void thc_ensure_performance_limitations(struct thc_device *dev) 879 + { 880 + unsigned long delay_usec = 0; 881 + /* 882 + * Minimum amount of delay the THC / QUICKSPI driver must wait 883 + * between end of write operation and begin of read operation. 884 + * This value shall be in 10us multiples. 885 + */ 886 + if (dev->perf_limit > 0) { 887 + delay_usec = dev->perf_limit * 10; 888 + udelay(delay_usec); 889 + } 890 + } 891 + 892 + static void thc_dma_write_completion(struct thc_device *dev) 893 + { 894 + thc_ensure_performance_limitations(dev); 895 + } 896 + 897 + /** 898 + * thc_dma_write - Use TXDMA to write data to touch device 899 + * 900 + * @dev: The pointer of THC private device context 901 + * @buffer: The pointer of write data buffer 902 + * @buf_len: The write data length 903 + * 904 + * Return: 0 on success, other error codes on failed. 905 + */ 906 + int thc_dma_write(struct thc_device *dev, void *buffer, size_t buf_len) 907 + { 908 + bool restore_interrupts = false; 909 + u32 sts, ctrl; 910 + int ret; 911 + 912 + if (!(&dev->dma_ctx->dma_config[THC_TXDMA])->is_enabled) { 913 + dev_err_once(dev->dev, "The TxDMA channel is not enabled\n"); 914 + return -EINVAL; 915 + } 916 + 917 + if (!buffer || buf_len <= 0) { 918 + dev_err(dev->dev, "Invalid input parameters, buffer %p\n, buf_len %zu\n", 919 + buffer, buf_len); 920 + return -EINVAL; 921 + } 922 + 923 + regmap_read(dev->thc_regmap, THC_M_PRT_WRITE_INT_STS_OFFSET, &sts); 924 + if (sts & THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ACTIVE) { 925 + dev_err_once(dev->dev, "THC TxDMA is till active and can't start again\n"); 926 + return -EBUSY; 927 + } 928 + 929 + if (mutex_lock_interruptible(&dev->thc_bus_lock)) 930 + return -EINTR; 931 + 932 + regmap_read(dev->thc_regmap, THC_M_PRT_CONTROL_OFFSET, &ctrl); 933 + 934 + ret = write_dma_buffer(dev, buffer, buf_len); 935 + if (ret) 936 + goto end; 937 + 938 + if (dev->perf_limit && !(ctrl & THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_HW_STS)) { 939 + ret = thc_interrupt_quiesce(dev, true); 940 + if (ret) 941 + goto end; 942 + 943 + restore_interrupts = true; 944 + } 945 + 946 + dev->write_done = false; 947 + 948 + dma_set_start_bit(dev, &dev->dma_ctx->dma_config[THC_TXDMA]); 949 + 950 + ret = wait_event_interruptible_timeout(dev->write_complete_wait, dev->write_done, 1 * HZ); 951 + if (ret <= 0 || !dev->write_done) { 952 + dev_err_once(dev->dev, "timeout for waiting TxDMA completion\n"); 953 + ret = -ETIMEDOUT; 954 + goto end; 955 + } 956 + 957 + thc_dma_write_completion(dev); 958 + mutex_unlock(&dev->thc_bus_lock); 959 + return 0; 960 + 961 + end: 962 + mutex_unlock(&dev->thc_bus_lock); 963 + 964 + if (restore_interrupts) 965 + ret = thc_interrupt_quiesce(dev, false); 966 + 967 + return ret; 968 + } 969 + EXPORT_SYMBOL_NS_GPL(thc_dma_write, "INTEL_THC");
+146
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _INTEL_THC_DMA_H_ 5 + #define _INTEL_THC_DMA_H_ 6 + 7 + #include <linux/bits.h> 8 + #include <linux/dma-mapping.h> 9 + #include <linux/sizes.h> 10 + #include <linux/time64.h> 11 + #include <linux/types.h> 12 + 13 + #define THC_POINTER_MASK GENMASK(6, 0) 14 + #define THC_POINTER_WRAPAROUND 0x80 15 + #define THC_WRAPAROUND_VALUE_ODD 0x10 16 + #define THC_WRAPAROUND_VALUE_EVEN 0x90 17 + #define THC_MIN_BYTES_PER_SG_LIST_ENTRY SZ_4K 18 + 19 + #define THC_DEFAULT_RXDMA_POLLING_US_INTERVAL 100 20 + #define THC_DEFAULT_RXDMA_POLLING_US_TIMEOUT (10 * USEC_PER_MSEC) 21 + 22 + /* 23 + * THC needs 1KB aligned address, dest_addr is 54 bits, not 64, 24 + * so don't need to send the lower 10-bits of address. 25 + */ 26 + #define THC_ADDRESS_SHIFT 10 27 + 28 + /** 29 + * THC DMA channels: 30 + * @THC_RXDMA1: legacy channel, reserved for raw data reading 31 + * @THC_RXDMA2: DMA to read HID data from touch device 32 + * @THC_TXDMA: DMA to write to touch device 33 + * @THC_SWDMA: SW triggered DMA to write and read from touch device 34 + */ 35 + enum thc_dma_channel { 36 + THC_RXDMA1 = 0, 37 + THC_RXDMA2 = 1, 38 + THC_TXDMA = 2, 39 + THC_SWDMA = 3, 40 + MAX_THC_DMA_CHANNEL 41 + }; 42 + 43 + /** 44 + * THC DMA Physical Memory Descriptor (PRD) 45 + * @dest_addr: bit[53:0], destination address in system memory 46 + * @int_on_completion: bit[63], if set, thc will trigger interrupt to driver 47 + * @len: bit[87:64], length of this entry 48 + * @end_of_prd: bit[88], if set, this entry is last one of current PRD table 49 + * @hw_status: bit[90:89], hw status bits 50 + */ 51 + struct thc_prd_entry { 52 + u64 dest_addr : 54; 53 + u64 reserved1 : 9; 54 + u64 int_on_completion : 1; 55 + u64 len : 24; 56 + u64 end_of_prd : 1; 57 + u64 hw_status : 2; 58 + u64 reserved2 : 37; 59 + }; 60 + 61 + /* 62 + * Max OS memory fragmentation will be at a 4KB boundary, thus to address 1MB 63 + * of virtually contiguous memory 256 PRD entries are required for a single 64 + * PRD Table. SW writes the number of PRD Entries for each PRD table in the 65 + * THC_M_PRT_RPRD_CNTRL.PTEC register field. The PRD entry's length must be 66 + * multiple of 4KB except for the last entry in a PRD table. 67 + * This is the max possible number of etries supported by HW, in practise we 68 + * there will be less entries in each prd table(the actual number will be 69 + * given by scatter-gather list allocation). 70 + */ 71 + #define PRD_ENTRIES_NUM 16 72 + 73 + /* 74 + * Number of PRD tables equals to number of data buffers. 75 + * The max number of PRD tables supported by the HW is 128, 76 + * but we allocate only 16. 77 + */ 78 + #define PRD_TABLES_NUM 16 79 + 80 + /* THC DMA Physical Memory Descriptor Table */ 81 + struct thc_prd_table { 82 + struct thc_prd_entry entries[PRD_ENTRIES_NUM]; 83 + }; 84 + 85 + #define PRD_TABLE_SIZE sizeof(struct thc_prd_table) 86 + 87 + /** 88 + * struct thc_dma_configuration - THC DMA configure 89 + * @dma_channel: DMA channel for current DMA configuration 90 + * @prd_tbls_dma_handle: DMA buffer handle 91 + * @dir: direction of DMA for this config 92 + * @prd_tbls: PRD tables for current DMA 93 + * @sgls: array of pointers to scatter-gather lists 94 + * @sgls_nent: actual number of entries per sg list 95 + * @prd_tbl_num: actual number of PRD tables 96 + * @max_packet_size: size of the buffer needed for 1 DMA message (1 PRD table) 97 + * @prd_base_addr_high: High 32bits memory address where stores PRD table 98 + * @prd_base_addr_low: low 32bits memory address where stores PRD table 99 + * @prd_cntrl: PRD control register value 100 + * @dma_cntrl: DMA control register value 101 + */ 102 + struct thc_dma_configuration { 103 + enum thc_dma_channel dma_channel; 104 + dma_addr_t prd_tbls_dma_handle; 105 + enum dma_data_direction dir; 106 + bool is_enabled; 107 + 108 + struct thc_prd_table *prd_tbls; 109 + struct scatterlist *sgls[PRD_TABLES_NUM]; 110 + u8 sgls_nent[PRD_TABLES_NUM]; 111 + u8 prd_tbl_num; 112 + 113 + size_t max_packet_size; 114 + u32 prd_base_addr_high; 115 + u32 prd_base_addr_low; 116 + u32 prd_cntrl; 117 + u32 dma_cntrl; 118 + }; 119 + 120 + /* 121 + * THC DMA context 122 + * Store all THC Channel configures 123 + */ 124 + struct thc_dma_context { 125 + struct thc_dma_configuration dma_config[MAX_THC_DMA_CHANNEL]; 126 + u8 use_write_interrupts; 127 + }; 128 + 129 + struct thc_device; 130 + 131 + int thc_dma_set_max_packet_sizes(struct thc_device *dev, 132 + size_t mps_read1, size_t mps_read2, 133 + size_t mps_write, size_t mps_swdma); 134 + int thc_dma_allocate(struct thc_device *dev); 135 + int thc_dma_configure(struct thc_device *dev); 136 + void thc_dma_unconfigure(struct thc_device *dev); 137 + void thc_dma_release(struct thc_device *dev); 138 + int thc_rxdma_read(struct thc_device *dev, enum thc_dma_channel dma_channel, 139 + void *read_buff, size_t *read_len, int *read_finished); 140 + int thc_swdma_read(struct thc_device *dev, void *write_buff, size_t write_len, 141 + u32 *prd_tbl_len, void *read_buff, size_t *read_len); 142 + int thc_dma_write(struct thc_device *dev, void *buffer, size_t buf_len); 143 + 144 + struct thc_dma_context *thc_dma_init(struct thc_device *dev); 145 + 146 + #endif /* _INTEL_THC_DMA_H_ */
+881
drivers/hid/intel-thc-hid/intel-thc/intel-thc-hw.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2024 Intel Corporation */ 3 + 4 + #ifndef _INTEL_THC_HW_H_ 5 + #define _INTEL_THC_HW_H_ 6 + 7 + #include <linux/bits.h> 8 + 9 + /* THC registers offset */ 10 + /* Touch Host Controller Control Register */ 11 + #define THC_M_PRT_CONTROL_OFFSET 0x1008 12 + /* THC SPI Bus Configuration Register */ 13 + #define THC_M_PRT_SPI_CFG_OFFSET 0x1010 14 + /* THC SPI Bus Read Opcode Register */ 15 + #define THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET 0x1014 16 + /* THC SPI Bus Read Opcode Register */ 17 + #define THC_M_PRT_SPI_DMARD_OPCODE_OFFSET 0x1018 18 + /* THC SPI Bus Write Opcode Register */ 19 + #define THC_M_PRT_SPI_WR_OPCODE_OFFSET 0x101C 20 + /* THC Interrupt Enable Register */ 21 + #define THC_M_PRT_INT_EN_OFFSET 0x1020 22 + /* THC Interrupt Status Register */ 23 + #define THC_M_PRT_INT_STATUS_OFFSET 0x1024 24 + /* THC Error Cause Register */ 25 + #define THC_M_PRT_ERR_CAUSE_OFFSET 0x1028 26 + /* THC SW sequencing Control */ 27 + #define THC_M_PRT_SW_SEQ_CNTRL_OFFSET 0x1040 28 + /* THC SW sequencing Status */ 29 + #define THC_M_PRT_SW_SEQ_STS_OFFSET 0x1044 30 + /* THC SW Sequencing Data DW0 or SPI Address Register */ 31 + #define THC_M_PRT_SW_SEQ_DATA0_ADDR_OFFSET 0x1048 32 + /* THC SW sequencing Data DW1 */ 33 + #define THC_M_PRT_SW_SEQ_DATA1_OFFSET 0x104C 34 + /* THC SW sequencing Data DW2 */ 35 + #define THC_M_PRT_SW_SEQ_DATA2_OFFSET 0x1050 36 + /* THC SW sequencing Data DW3 */ 37 + #define THC_M_PRT_SW_SEQ_DATA3_OFFSET 0x1054 38 + /* THC SW sequencing Data DW4 */ 39 + #define THC_M_PRT_SW_SEQ_DATA4_OFFSET 0x1058 40 + /* THC SW sequencing Data DW5 */ 41 + #define THC_M_PRT_SW_SEQ_DATA5_OFFSET 0x105C 42 + /* THC SW sequencing Data DW6 */ 43 + #define THC_M_PRT_SW_SEQ_DATA6_OFFSET 0x1060 44 + /* THC SW sequencing Data DW7 */ 45 + #define THC_M_PRT_SW_SEQ_DATA7_OFFSET 0x1064 46 + /* THC SW sequencing Data DW8 */ 47 + #define THC_M_PRT_SW_SEQ_DATA8_OFFSET 0x1068 48 + /* THC SW sequencing Data DW9 */ 49 + #define THC_M_PRT_SW_SEQ_DATA9_OFFSET 0x106C 50 + /* THC SW sequencing Data DW10 */ 51 + #define THC_M_PRT_SW_SEQ_DATA10_OFFSET 0x1070 52 + /* THC SW sequencing Data DW11 */ 53 + #define THC_M_PRT_SW_SEQ_DATA11_OFFSET 0x1074 54 + /* THC SW sequencing Data DW12 */ 55 + #define THC_M_PRT_SW_SEQ_DATA12_OFFSET 0x1078 56 + /* THC SW sequencing Data DW13 */ 57 + #define THC_M_PRT_SW_SEQ_DATA13_OFFSET 0x107C 58 + /* THC SW sequencing Data DW14 */ 59 + #define THC_M_PRT_SW_SEQ_DATA14_OFFSET 0x1080 60 + /* THC SW sequencing Data DW15 */ 61 + #define THC_M_PRT_SW_SEQ_DATA15_OFFSET 0x1084 62 + /* THC SW sequencing Data DW16 */ 63 + #define THC_M_PRT_SW_SEQ_DATA16_OFFSET 0x1088 64 + /* THC Write PRD Base Address Register Low */ 65 + #define THC_M_PRT_WPRD_BA_LOW_OFFSET 0x1090 66 + /* THC Write PRD Base Address Register High */ 67 + #define THC_M_PRT_WPRD_BA_HI_OFFSET 0x1094 68 + /* THC Write DMA Control */ 69 + #define THC_M_PRT_WRITE_DMA_CNTRL_OFFSET 0x1098 70 + /* THC Write Interrupt Status */ 71 + #define THC_M_PRT_WRITE_INT_STS_OFFSET 0x109C 72 + /* THC Write DMA Error Register */ 73 + #define THC_M_PRT_WRITE_DMA_ERR_OFFSET 0x10A0 74 + /* THC device address for the bulk write */ 75 + #define THC_M_PRT_WR_BULK_ADDR_OFFSET 0x10B4 76 + /* THC Device Interrupt Cause Register Address */ 77 + #define THC_M_PRT_DEV_INT_CAUSE_ADDR_OFFSET 0x10B8 78 + /* THC Device Interrupt Cause Register Value */ 79 + #define THC_M_PRT_DEV_INT_CAUSE_REG_VAL_OFFSET 0x10BC 80 + /* THC TXDMA Frame Count */ 81 + #define THC_M_PRT_TX_FRM_CNT_OFFSET 0x10E0 82 + /* THC TXDMA Packet Count */ 83 + #define THC_M_PRT_TXDMA_PKT_CNT_OFFSET 0x10E4 84 + /* THC Device Interrupt Count on this port */ 85 + #define THC_M_PRT_DEVINT_CNT_OFFSET 0x10E8 86 + /* Touch Device Interrupt Cause register Format Configuration Register 1 */ 87 + #define THC_M_PRT_DEVINT_CFG_1_OFFSET 0x10EC 88 + /* Touch Device Interrupt Cause register Format Configuration Register 2 */ 89 + #define THC_M_PRT_DEVINT_CFG_2_OFFSET 0x10F0 90 + /* THC Read PRD Base Address Low for the 1st RXDMA */ 91 + #define THC_M_PRT_RPRD_BA_LOW_1_OFFSET 0x1100 92 + /* THC Read PRD Base Address High for the 1st RXDMA */ 93 + #define THC_M_PRT_RPRD_BA_HI_1_OFFSET 0x1104 94 + /* THC Read PRD Control for the 1st RXDMA */ 95 + #define THC_M_PRT_RPRD_CNTRL_1_OFFSET 0x1108 96 + /* THC Read DMA Control for the 1st RXDMA */ 97 + #define THC_M_PRT_READ_DMA_CNTRL_1_OFFSET 0x110C 98 + /* THC Read Interrupt Status for the 1st RXDMA */ 99 + #define THC_M_PRT_READ_DMA_INT_STS_1_OFFSET 0x1110 100 + /* THC Read DMA Error Register for the 1st RXDMA */ 101 + #define THC_M_PRT_READ_DMA_ERR_1_OFFSET 0x1114 102 + /* Touch Sequencer GuC Tail Offset Address Low for the 1st RXDMA */ 103 + #define THC_M_PRT_GUC_OFFSET_LOW_1_OFFSET 0x1118 104 + /* Touch Sequencer GuC Tail Offset Address High for the 1st RXDMA */ 105 + #define THC_M_PRT_GUC_OFFSET_HI_1_OFFSET 0x111C 106 + /* Touch Host Controller GuC Work Queue Item Size for the 1st RXDMA */ 107 + #define THC_M_PRT_GUC_WORKQ_ITEM_SZ_1_OFFSET 0x1120 108 + /* Touch Host Controller GuC Control register for the 1st RXDMA */ 109 + #define THC_M_PRT_GUC_WORKQ_SZ_1_OFFSET 0x1124 110 + /* Touch Sequencer Control for the 1st DMA */ 111 + #define THC_M_PRT_TSEQ_CNTRL_1_OFFSET 0x1128 112 + /* Touch Sequencer GuC Doorbell Address Low for the 1st RXDMA */ 113 + #define THC_M_PRT_GUC_DB_ADDR_LOW_1_OFFSET 0x1130 114 + /* Touch Sequencer GuC Doorbell Address High for the 1st RXDMA */ 115 + #define THC_M_PRT_GUC_DB_ADDR_HI_1_OFFSET 0x1134 116 + /* Touch Sequencer GuC Doorbell Data */ 117 + #define THC_M_PRT_GUC_DB_DATA_1_OFFSET 0x1138 118 + /* Touch Sequencer GuC Tail Offset Initial Value for the 1st RXDMA */ 119 + #define THC_M_PRT_GUC_OFFSET_INITVAL_1_OFFSET 0x1140 120 + /* THC Device Address for the bulk/touch data read for the 1st RXDMA */ 121 + #define THC_M_PRT_RD_BULK_ADDR_1_OFFSET 0x1170 122 + /* THC Gfx/SW Doorbell Count from the 1st Stream RXDMA on this port */ 123 + #define THC_M_PRT_DB_CNT_1_OFFSET 0x11A0 124 + /* THC Frame Count from the 1st Stream RXDMA on this port */ 125 + #define THC_M_PRT_FRM_CNT_1_OFFSET 0x11A4 126 + /* THC Micro Frame Count from the 1st Stream RXDMA on this port */ 127 + #define THC_M_PRT_UFRM_CNT_1_OFFSET 0x11A8 128 + /* THC Packet Count from the 1st Stream RXDMA on this port */ 129 + #define THC_M_PRT_RXDMA_PKT_CNT_1_OFFSET 0x11AC 130 + /* 131 + * THC Software Interrupt Count from the 1st Stream RXDMA 132 + * on this port 133 + */ 134 + #define THC_M_PRT_SWINT_CNT_1_OFFSET 0x11B0 135 + /* Touch Sequencer Frame Drop Counter for the 1st RXDMA */ 136 + #define THC_M_PRT_FRAME_DROP_CNT_1_OFFSET 0x11B4 137 + /* THC Coaescing 1 */ 138 + #define THC_M_PRT_COALESCE_1_OFFSET 0x11B8 139 + /* THC Read PRD Base Address Low for the 2nd RXDMA */ 140 + #define THC_M_PRT_RPRD_BA_LOW_2_OFFSET 0x1200 141 + /* THC Read PRD Base Address High for the 2nd RXDMA */ 142 + #define THC_M_PRT_RPRD_BA_HI_2_OFFSET 0x1204 143 + /* THC Read PRD Control for the 2nd RXDMA */ 144 + #define THC_M_PRT_RPRD_CNTRL_2_OFFSET 0x1208 145 + /* THC Read DMA Control for the 2nd RXDMA */ 146 + #define THC_M_PRT_READ_DMA_CNTRL_2_OFFSET 0x120C 147 + /* THC Read Interrupt Status for the 2nd RXDMA */ 148 + #define THC_M_PRT_READ_DMA_INT_STS_2_OFFSET 0x1210 149 + /* THC Read DMA Error Register for the 2nd RXDMA */ 150 + #define THC_M_PRT_READ_DMA_ERR_2_OFFSET 0x1214 151 + /* Touch Sequencer GuC Tail Offset Address Low for the 2nd RXDMA */ 152 + #define THC_M_PRT_GUC_OFFSET_LOW_2_OFFSET 0x1218 153 + /* Touch Sequencer GuC Tail Offset Address High for the 2nd RXDMA */ 154 + #define THC_M_PRT_GUC_OFFSET_HI_2_OFFSET 0x121C 155 + /* Touch Host Controller GuC Work Queue Item Size for the 2nd RXDMA */ 156 + #define THC_M_PRT_GUC_WORKQ_ITEM_SZ_2_OFFSET 0x1220 157 + /* Touch Host Controller GuC Control register for the 2nd RXDMA */ 158 + #define THC_M_PRT_GUC_WORKQ_SZ_2_OFFSET 0x1224 159 + /* Touch Sequencer Control for the 2nd DMA */ 160 + #define THC_M_PRT_TSEQ_CNTRL_2_OFFSET 0x1228 161 + /* Touch Sequencer GuC Doorbell Address Low for the 2nd RXDMA */ 162 + #define THC_M_PRT_GUC_DB_ADDR_LOW_2_OFFSET 0x1230 163 + /* Touch Sequencer GuC Doorbell Address High for the 2nd RXDMA */ 164 + #define THC_M_PRT_GUC_DB_ADDR_HI_2_OFFSET 0x1234 165 + /* Touch Sequencer GuC Doorbell Data for PRD2 */ 166 + #define THC_M_PRT_GUC_DB_DATA_2_OFFSET 0x1238 167 + /* Touch Sequencer GuC Tail Offset Initial Value for the 2nd RXDMA */ 168 + #define THC_M_PRT_GUC_OFFSET_INITVAL_2_OFFSET 0x1240 169 + /* THC Device Address for the bulk/touch data read for the 2nd RXDMA */ 170 + #define THC_M_PRT_RD_BULK_ADDR_2_OFFSET 0x1270 171 + /* THC Gfx/SW Doorbell Count from the 2nd Stream RXDMA on this port */ 172 + #define THC_M_PRT_DB_CNT_2_OFFSET 0x12A0 173 + /* THC Frame Count from the 2nd Stream RXDMA on this port */ 174 + #define THC_M_PRT_FRM_CNT_2_OFFSET 0x12A4 175 + /* THC Micro Frame Count from the 2nd Stream RXDMA on this port */ 176 + #define THC_M_PRT_UFRM_CNT_2_OFFSET 0x12A8 177 + /* THC Packet Count from the 2nd Stream RXDMA on this port */ 178 + #define THC_M_PRT_RXDMA_PKT_CNT_2_OFFSET 0x12AC 179 + /* 180 + * THC Software Interrupt Count from the 2nd Stream RXDMA 181 + * on this port 182 + */ 183 + #define THC_M_PRT_SWINT_CNT_2_OFFSET 0x12B0 184 + /* Touch Sequencer Frame Drop Counter for the 2nd RXDMA */ 185 + #define THC_M_PRT_FRAME_DROP_CNT_2_OFFSET 0x12B4 186 + /* THC Coaescing 2 */ 187 + #define THC_M_PRT_COALESCE_2_OFFSET 0x12B8 188 + /* THC SPARE REGISTER */ 189 + #define THC_M_PRT_SPARE_REG_OFFSET 0x12BC 190 + /* THC Read PRD Base Address Low for the SW RXDMA */ 191 + #define THC_M_PRT_RPRD_BA_LOW_SW_OFFSET 0x12C0 192 + /* THC Read PRD Base Address High for the SW RXDMA */ 193 + #define THC_M_PRT_RPRD_BA_HI_SW_OFFSET 0x12C4 194 + /* THC Read PRD Control for the SW RXDMA */ 195 + #define THC_M_PRT_RPRD_CNTRL_SW_OFFSET 0x12C8 196 + /* THC Read DMA Control for the SW RXDMA */ 197 + #define THC_M_PRT_READ_DMA_CNTRL_SW_OFFSET 0x12CC 198 + /* THC Read Interrupt Status for the SW RXDMA */ 199 + #define THC_M_PRT_READ_DMA_INT_STS_SW_OFFSET 0x12D0 200 + /* Touch Sequencer Control for the SW DMA */ 201 + #define THC_M_PRT_TSEQ_CNTRL_SW_OFFSET 0x12D4 202 + /* Address for the bulk read for SW DMA engine */ 203 + #define THC_M_PRT_RD_BULK_ADDR_SW_OFFSET 0x12D8 204 + /* THC Frame Count from the SW RXDMA on this port */ 205 + #define THC_M_PRT_FRM_CNT_SW_OFFSET 0x12DC 206 + /* THC Packet Count from the SW RXDMA on this port */ 207 + #define THC_M_PRT_RXDMA_PKT_CNT_SW_OFFSET 0x12E0 208 + /* SW DMA PRD Table Length */ 209 + #define THC_M_PRT_SW_DMA_PRD_TABLE_LEN_OFFSET 0x12E4 210 + /* THC timing based Frame/Interrupt caolescing control register for 1st RXDMA */ 211 + #define THC_M_PRT_COALESCE_CNTRL_1_OFFSET 0x12E8 212 + /* THC timing based Frame/Interrupt caolescing control register for 2nd RXDMA */ 213 + #define THC_M_PRT_COALESCE_CNTRL_2_OFFSET 0x12EC 214 + /* Touch Sequencer PRD Table Empty Counter for the 1st RXDMA */ 215 + #define THC_M_PRT_PRD_EMPTY_CNT_1_OFFSET 0x12F0 216 + /* Touch Sequencer PRD Table Empty Counter for the 2nd RXDM */ 217 + #define THC_M_PRT_PRD_EMPTY_CNT_2_OFFSET 0x12F4 218 + /* THC coalescing status to reflect the current coalescing FSM state for 1st RXDMA */ 219 + #define THC_M_PRT_COALESCE_STS_1_OFFSET 0x12F8 220 + /* THC coalescing status to reflect the current coalescing FSM state for 2nd RXDMA */ 221 + #define THC_M_PRT_COALESCE_STS_2_OFFSET 0x12FC 222 + /* THC Register for the SPI Port Duty Cycle Configuration */ 223 + #define THC_M_PRT_SPI_DUTYC_CFG_OFFSET 0x1300 224 + /* THC Register for SW I2C Wtite Sequecning control */ 225 + #define THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_OFFSET 0x1304 226 + /* THC current Timestamp Register for RXDMA1 */ 227 + #define THC_M_PRT_TIMESTAMP_1_OFFSET 0x1308 228 + /* THC current Timestamp Register for RXDMA2 */ 229 + #define THC_M_PRT_TIMESTAMP_2_OFFSET 0x130C 230 + /* Current SYNC Event Timestamp Register */ 231 + #define THC_M_PRT_SYNC_TIMESTAMP_OFFSET 0x1310 232 + /* THC Display Sync Register */ 233 + #define THC_M_PRT_DISP_SYNC_OFFSET 0x1314 234 + /* THC Display Sync Register */ 235 + #define THC_M_PRT_DISP_SYNC_2_OFFSET 0x1318 236 + /* THC Register for SW I2C Wtite Sequecning control */ 237 + #define THC_M_PRT_I2C_CFG_OFFSET 0x131C 238 + 239 + /* THC register bits definition */ 240 + #define TXN_ERR_INT_STS_BIT BIT(28) 241 + #define TXN_FATAL_INT_STS_BIT BIT(30) 242 + 243 + #define NONDMA_INT_STS_BIT BIT(4) 244 + #define EOF_INT_STS_BIT BIT(5) 245 + 246 + #define THC_CFG_DID_VID_VID GENMASK(15, 0) 247 + #define THC_CFG_DID_VID_DID GENMASK(31, 16) 248 + 249 + #define THC_CFG_STS_CMD_IOSE BIT(0) 250 + #define THC_CFG_STS_CMD_MSE BIT(1) 251 + #define THC_CFG_STS_CMD_BME BIT(2) 252 + #define THC_CFG_STS_CMD_SPCYC BIT(3) 253 + #define THC_CFG_STS_CMD_MWRIEN BIT(4) 254 + #define THC_CFG_STS_CMD_VGAPS BIT(5) 255 + #define THC_CFG_STS_CMD_PERRR BIT(6) 256 + #define THC_CFG_STS_CMD_SERREN BIT(8) 257 + #define THC_CFG_STS_CMD_FBTBEN BIT(9) 258 + #define THC_CFG_STS_CMD_INTD BIT(10) 259 + #define THC_CFG_STS_CMD_INTS BIT(19) 260 + #define THC_CFG_STS_CMD_CAPL BIT(20) 261 + #define THC_CFG_STS_CMD_MCAP BIT(21) 262 + #define THC_CFG_STS_CMD_FBTBC BIT(23) 263 + #define THC_CFG_STS_CMD_MDPE BIT(24) 264 + #define THC_CFG_STS_CMD_DEVT GENMASK(26, 25) 265 + #define THC_CFG_STS_CMD_STA BIT(27) 266 + #define THC_CFG_STS_CMD_RTA BIT(28) 267 + #define THC_CFG_STS_CMD_RMA BIT(29) 268 + #define THC_CFG_STS_CMD_SSE BIT(30) 269 + #define THC_CFG_STS_CMD_DPE BIT(31) 270 + 271 + #define THC_CFG_CC_RID_RID GENMASK(7, 0) 272 + #define THC_CFG_CC_RID_PI GENMASK(15, 8) 273 + #define THC_CFG_CC_RID_SCC GENMASK(23, 16) 274 + #define THC_CFG_CC_RID_BCC GENMASK(31, 24) 275 + 276 + #define THC_CFG_BIST_HTYPE_LT_CLS_CLSZ GENMASK(7, 0) 277 + #define THC_CFG_BIST_HTYPE_LT_CLS_LT GENMASK(15, 8) 278 + #define THC_CFG_BIST_HTYPE_LT_CLS_HTYPE GENMASK(22, 16) 279 + #define THC_CFG_BIST_HTYPE_LT_CLS_MFD BIT(23) 280 + 281 + #define THC_CFG_BAR0_LOW_MEMSPACE BIT(0) 282 + #define THC_CFG_BAR0_LOW_TYP GENMASK(2, 1) 283 + #define THC_CFG_BAR0_LOW_PREFETCH BIT(3) 284 + #define THC_CFG_BAR0_LOW_MEMSIZE GENMASK(14, 4) 285 + #define THC_CFG_BAR0_LOW_MEMBAR GENMASK(31, 15) 286 + #define THC_CFG_BAR0_HI_MEMBAR GENMASK(31, 0) 287 + 288 + #define THC_CFG_SID_SVID_SSVID GENMASK(15, 0) 289 + #define THC_CFG_SID_SVID_SSID GENMASK(31, 16) 290 + 291 + #define THC_CFG_CAPP_CP GENMASK(7, 0) 292 + 293 + #define THC_CFG_INT_ILINE GENMASK(7, 0) 294 + #define THC_CFG_INT_IPIN GENMASK(15, 8) 295 + 296 + #define THC_CFG_UR_STS_CTL_URRE BIT(0) 297 + #define THC_CFG_UR_STS_CTL_URD BIT(1) 298 + #define THC_CFG_UR_STS_CTL_FD BIT(2) 299 + 300 + #define THC_CFG_MSIMC_MSINP_MSICID_CAPID GENMASK(7, 0) 301 + #define THC_CFG_MSIMC_MSINP_MSICID_NXTP GENMASK(15, 8) 302 + #define THC_CFG_MSIMC_MSINP_MSICID_MSIE BIT(16) 303 + #define THC_CFG_MSIMC_MSINP_MSICID_MMC GENMASK(19, 17) 304 + #define THC_CFG_MSIMC_MSINP_MSICID_MMEN GENMASK(22, 20) 305 + #define THC_CFG_MSIMC_MSINP_MSICID_XAC BIT(23) 306 + #define THC_CFG_MSIMC_MSINP_MSICID_PVMC BIT(24) 307 + #define THC_CFG_MSIMA_MADDR GENMASK(31, 2) 308 + #define THC_CFG_MSIMUA_MAUDDR GENMASK(31, 0) 309 + #define THC_CFG_MSIMD_MDAT GENMASK(15, 0) 310 + 311 + #define THC_CFG_PMCAP_PMNP_PMCID_CAPP GENMASK(7, 0) 312 + #define THC_CFG_PMCAP_PMNP_PMCID_NXTP GENMASK(15, 8) 313 + #define THC_CFG_PMCAP_PMNP_PMCID_VER GENMASK(18, 16) 314 + #define THC_CFG_PMCAP_PMNP_PMCID_PMECLK BIT(19) 315 + #define THC_CFG_PMCAP_PMNP_PMCID_DSI BIT(21) 316 + #define THC_CFG_PMCAP_PMNP_PMCID_AUXC GENMASK(24, 22) 317 + #define THC_CFG_PMCAP_PMNP_PMCID_D1S BIT(25) 318 + #define THC_CFG_PMCAP_PMNP_PMCID_D2S BIT(26) 319 + #define THC_CFG_PMCAP_PMNP_PMCID_PMES GENMASK(31, 27) 320 + 321 + #define THC_CFG_PMD_PMCSRBSE_PMCSR_PWRST GENMASK(1, 0) 322 + #define THC_CFG_PMD_PMCSRBSE_PMCSR_NSR BIT(3) 323 + #define THC_CFG_PMD_PMCSRBSE_PMCSR_PMEEN BIT(8) 324 + #define THC_CFG_PMD_PMCSRBSE_PMCSR_DSEL GENMASK(12, 9) 325 + #define THC_CFG_PMD_PMCSRBSE_PMCSR_DS GENMASK(14, 13) 326 + #define THC_CFG_PMD_PMCSRBSE_PMCSR_PMESTS BIT(15) 327 + 328 + #define THC_CFG_DEVIDLE_CAPPID GENMASK(7, 0) 329 + #define THC_CFG_DEVIDLE_NCAPPP GENMASK(15, 8) 330 + #define THC_CFG_DEVIDLE_LENGTH GENMASK(23, 16) 331 + #define THC_CFG_DEVIDLE_REV GENMASK(27, 24) 332 + #define THC_CFG_DEVIDLE_VID GENMASK(31, 28) 333 + 334 + #define THC_CFG_VSHDR_VSECID GENMASK(15, 0) 335 + #define THC_CFG_VSHDR_VSECR GENMASK(19, 16) 336 + #define THC_CFG_VSHDR_VSECL GENMASK(31, 20) 337 + 338 + #define THC_CFG_SWLTRPTR_VALID BIT(0) 339 + #define THC_CFG_SWLTRPTR_BARNUM GENMASK(3, 1) 340 + #define THC_CFG_SWLTRPTR_SWLTRLOC GENMASK(31, 4) 341 + 342 + #define THC_CFG_DEVIDLEPTR_VALID BIT(0) 343 + #define THC_CFG_DEVIDLEPTR_BARNUM GENMASK(3, 1) 344 + #define THC_CFG_DEVIDLEPTR_DEVIDLELOC GENMASK(31, 4) 345 + #define THC_CFG_DEVIDLEPOL_POLV GENMASK(9, 0) 346 + #define THC_CFG_DEVIDLEPOL_POLS GENMASK(12, 10) 347 + 348 + #define THC_CFG_PCE_SPE BIT(0) 349 + #define THC_CFG_PCE_I3E BIT(1) 350 + #define THC_CFG_PCE_D3HE BIT(2) 351 + #define THC_CFG_PCE_SE BIT(3) 352 + #define THC_CFG_PCE_HAE BIT(5) 353 + 354 + #define THC_CFG_MANID_PROC GENMASK(7, 0) 355 + #define THC_CFG_MANID_MID GENMASK(15, 8) 356 + #define THC_CFG_MANID_MSID GENMASK(23, 16) 357 + #define THC_CFG_MANID_DOT GENMASK(27, 24) 358 + 359 + #define THC_M_CMN_DEVIDLECTRL_CIP BIT(0) 360 + #define THC_M_CMN_DEVIDLECTRL_IR BIT(1) 361 + #define THC_M_CMN_DEVIDLECTRL_DEVIDLE BIT(2) 362 + #define THC_M_CMN_DEVIDLECTRL_RR BIT(3) 363 + #define THC_M_CMN_DEVIDLECTRL_IRC BIT(4) 364 + 365 + #define THC_M_CMN_LTR_CTRL_OFFSET 0x14 366 + #define THC_M_CMN_LTR_CTRL_ACTIVE_LTR_REQ BIT(0) 367 + #define THC_M_CMN_LTR_CTRL_ACTIVE_LTR_EN BIT(1) 368 + #define THC_M_CMN_LTR_CTRL_LP_LTR_REQ BIT(2) 369 + #define THC_M_CMN_LTR_CTRL_LP_LTR_EN BIT(3) 370 + #define THC_M_CMN_LTR_CTRL_LP_LTR_SCALE GENMASK(6, 4) 371 + #define THC_M_CMN_LTR_CTRL_LP_LTR_VAL GENMASK(16, 7) 372 + #define THC_M_CMN_LTR_CTRL_ACT_LTR_SCALE GENMASK(19, 17) 373 + #define THC_M_CMN_LTR_CTRL_ACT_LTR_VAL GENMASK(29, 20) 374 + #define THC_M_CMN_LTR_CTRL_LAST_LTR_SENT GENMASK(31, 30) 375 + 376 + #define THC_M_PRT_CONTROL_TSFTRST BIT(0) 377 + #define THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_EN BIT(1) 378 + #define THC_M_PRT_CONTROL_THC_DEVINT_QUIESCE_HW_STS BIT(2) 379 + #define THC_M_PRT_CONTROL_DEVRST BIT(3) 380 + #define THC_M_PRT_CONTROL_THC_DRV_LOCK_EN BIT(13) 381 + #define THC_M_PRT_CONTROL_THC_INSTANCE_INDEX GENMASK(18, 16) 382 + #define THC_M_PRT_CONTROL_PORT_INDEX GENMASK(22, 20) 383 + #define THC_M_PRT_CONTROL_THC_ARB_POLICY GENMASK(25, 24) 384 + #define THC_M_PRT_CONTROL_THC_BIOS_LOCK_EN BIT(27) 385 + #define THC_M_PRT_CONTROL_PORT_SUPPORTED BIT(28) 386 + #define THC_M_PRT_CONTROL_SPI_IO_RDY BIT(29) 387 + #define THC_M_PRT_CONTROL_PORT_TYPE GENMASK(31, 30) 388 + 389 + #define THC_M_PRT_SPI_CFG_SPI_TRDC GENMASK(1, 0) 390 + #define THC_M_PRT_SPI_CFG_SPI_TRMODE GENMASK(3, 2) 391 + #define THC_M_PRT_SPI_CFG_SPI_TCRF GENMASK(6, 4) 392 + #define THC_M_PRT_SPI_CFG_SPI_RD_MPS GENMASK(15, 7) 393 + #define THC_M_PRT_SPI_CFG_SPI_TWMODE GENMASK(19, 18) 394 + #define THC_M_PRT_SPI_CFG_SPI_TCWF GENMASK(22, 20) 395 + #define THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN BIT(23) 396 + #define THC_M_PRT_SPI_CFG_SPI_WR_MPS GENMASK(31, 24) 397 + 398 + #define THC_M_PRT_SPI_ICRRD_OPCODE_SPI_SIO GENMASK(31, 24) 399 + #define THC_M_PRT_SPI_ICRRD_OPCODE_SPI_DIO GENMASK(23, 16) 400 + #define THC_M_PRT_SPI_ICRRD_OPCODE_SPI_QIO GENMASK(15, 8) 401 + 402 + #define THC_M_PRT_INT_EN_SIPE BIT(0) 403 + #define THC_M_PRT_INT_EN_SBO BIT(1) 404 + #define THC_M_PRT_INT_EN_SIDR BIT(2) 405 + #define THC_M_PRT_INT_EN_SOFB BIT(3) 406 + #define THC_M_PRT_INT_EN_INVLD_DEV_ENTRY_INT_EN BIT(9) 407 + #define THC_M_PRT_INT_EN_FRAME_BABBLE_ERR_INT_EN BIT(10) 408 + #define THC_M_PRT_INT_EN_BUF_OVRRUN_ERR_INT_EN BIT(12) 409 + #define THC_M_PRT_INT_EN_PRD_ENTRY_ERR_INT_EN BIT(13) 410 + #define THC_M_PRT_INT_EN_DISP_SYNC_EVT_INT_EN BIT(14) 411 + #define THC_M_PRT_INT_EN_DEV_RAW_INT_EN BIT(15) 412 + #define THC_M_PRT_INT_EN_FATAL_ERR_INT_EN BIT(16) 413 + #define THC_M_PRT_INT_EN_THC_I2C_IC_RX_UNDER_INT_EN BIT(17) 414 + #define THC_M_PRT_INT_EN_THC_I2C_IC_RX_OVER_INT_EN BIT(18) 415 + #define THC_M_PRT_INT_EN_THC_I2C_IC_RX_FULL_INT_EN BIT(19) 416 + #define THC_M_PRT_INT_EN_THC_I2C_IC_TX_OVER_INT_EN BIT(20) 417 + #define THC_M_PRT_INT_EN_THC_I2C_IC_TX_EMPTY_INT_EN BIT(21) 418 + #define THC_M_PRT_INT_EN_THC_I2C_IC_TX_ABRT_INT_EN BIT(22) 419 + #define THC_M_PRT_INT_EN_THC_I2C_IC_SCL_STUCK_AT_LOW_DET_INT_EN BIT(24) 420 + #define THC_M_PRT_INT_EN_THC_I2C_IC_STOP_DET_INT_EN BIT(25) 421 + #define THC_M_PRT_INT_EN_THC_I2C_IC_START_DET_INT_EN BIT(26) 422 + #define THC_M_PRT_INT_EN_THC_I2C_IC_MST_ON_HOLD_INT_EN BIT(27) 423 + #define THC_M_PRT_INT_EN_TXN_ERR_INT_EN BIT(29) 424 + #define THC_M_PRT_INT_EN_GBL_INT_EN BIT(31) 425 + 426 + #define THC_M_PRT_INT_STATUS_DISP_SYNC_EVT_INT_STS BIT(14) 427 + #define THC_M_PRT_INT_STATUS_DEV_RAW_INT_STS BIT(15) 428 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_UNDER_INT_STS BIT(17) 429 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_OVER_INT_STS BIT(18) 430 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_RX_FULL_INT_STS BIT(19) 431 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_OVER_INT_STS BIT(20) 432 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_EMPTY_INT_STS BIT(21) 433 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_TX_ABRT_INT_STS BIT(22) 434 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_ACTIVITY_INT_STS BIT(23) 435 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_SCL_STUCK_AT_LOW_INT_STS BIT(24) 436 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_STOP_DET_INT_STS BIT(25) 437 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_START_DET_INT_STS BIT(26) 438 + #define THC_M_PRT_INT_STATUS_THC_I2C_IC_MST_ON_HOLD_INT_STS BIT(27) 439 + #define THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS BIT(28) 440 + #define THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS BIT(30) 441 + 442 + #define THC_M_PRT_ERR_CAUSE_INVLD_DEV_ENTRY BIT(9) 443 + #define THC_M_PRT_ERR_CAUSE_FRAME_BABBLE_ERR BIT(10) 444 + #define THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR BIT(12) 445 + #define THC_M_PRT_ERR_CAUSE_PRD_ENTRY_ERR BIT(13) 446 + #define THC_M_PRT_ERR_CAUSE_FATAL_ERR_CAUSE GENMASK(23, 16) 447 + 448 + #define THC_M_PRT_SW_SEQ_CNTRL_TSSGO BIT(0) 449 + #define THC_M_PRT_SW_SEQ_CNTRL_THC_SS_CD_IE BIT(1) 450 + #define THC_M_PRT_SW_SEQ_CNTRL_THC_SS_CMD GENMASK(15, 8) 451 + #define THC_M_PRT_SW_SEQ_CNTRL_THC_SS_BC GENMASK(31, 16) 452 + #define THC_M_PRT_SW_SEQ_STS_TSSDONE BIT(0) 453 + #define THC_M_PRT_SW_SEQ_STS_THC_SS_ERR BIT(1) 454 + #define THC_M_PRT_SW_SEQ_STS_THC_SS_CIP BIT(3) 455 + #define THC_M_PRT_SW_SEQ_DATA0_ADDR_THC_SW_SEQ_DATA0_ADDR GENMASK(31, 0) 456 + #define THC_M_PRT_SW_SEQ_DATA1_THC_SW_SEQ_DATA1 GENMASK(31, 0) 457 + 458 + #define THC_M_PRT_WPRD_BA_LOW_THC_M_PRT_WPRD_BA_LOW GENMASK(31, 12) 459 + #define THC_M_PRT_WPRD_BA_HI_THC_M_PRT_WPRD_BA_HI GENMASK(31, 0) 460 + 461 + #define THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_START BIT(0) 462 + #define THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_ERROR BIT(1) 463 + #define THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC BIT(2) 464 + #define THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL BIT(3) 465 + #define THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_UHS BIT(23) 466 + #define THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_PTEC GENMASK(31, 24) 467 + 468 + #define THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS BIT(0) 469 + #define THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ERROR_STS BIT(1) 470 + #define THC_M_PRT_WRITE_INT_STS_THC_WRDMA_IOC_STS BIT(2) 471 + #define THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ACTIVE BIT(3) 472 + 473 + #define THC_M_PRT_WR_BULK_ADDR_THC_M_PRT_WR_BULK_ADDR GENMASK(31, 0) 474 + 475 + #define THC_M_PRT_DEV_INT_CAUSE_ADDR_THC_M_PRT_DEV_INT_CAUSE_ADDR GENMASK(31, 0) 476 + #define THC_M_PRT_DEV_INT_CAUSE_REG_VAL_INTERRUPT_TYPE GENMASK(3, 0) 477 + #define THC_M_PRT_DEV_INT_CAUSE_REG_VAL_MICRO_FRAME_SIZE GENMASK(23, 4) 478 + #define THC_M_PRT_DEV_INT_CAUSE_REG_VAL_BEGINNING_OF_FRAME BIT(29) 479 + #define THC_M_PRT_DEV_INT_CAUSE_REG_VAL_END_OF_FRAME BIT(30) 480 + #define THC_M_PRT_DEV_INT_CAUSE_REG_VAL_FRAME_TYPE BIT(31) 481 + 482 + #define THC_M_PRT_TX_FRM_CNT_THC_M_PRT_TX_FRM_CNT GENMASK(30, 0) 483 + #define THC_M_PRT_TX_FRM_CNT_THC_M_PRT_TX_FRM_CNT_RST BIT(31) 484 + 485 + #define THC_M_PRT_TXDMA_PKT_CNT_THC_M_PRT_TXDMA_PKT_CNT GENMASK(30, 0) 486 + #define THC_M_PRT_TXDMA_PKT_CNT_THC_M_PRT_TXDMA_PKT_CNT_RST BIT(31) 487 + 488 + #define THC_M_PRT_DEVINT_CNT_THC_M_PRT_DEVINT_CNT GENMASK(30, 0) 489 + #define THC_M_PRT_DEVINT_CNT_THC_M_PRT_DEVINT_CNT_RST BIT(31) 490 + 491 + #define THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_OFFSET GENMASK(4, 0) 492 + #define THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_LEN GENMASK(9, 5) 493 + #define THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_EOF_OFFSET GENMASK(14, 10) 494 + #define THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_SEND_ICR_US_EN BIT(15) 495 + #define THC_M_PRT_DEVINT_CFG_1_THC_M_PRT_INTTYP_DATA_VAL GENMASK(31, 16) 496 + 497 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_OFFSET GENMASK(4, 0) 498 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_LEN GENMASK(9, 5) 499 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_UFSIZE_UNIT GENMASK(15, 12) 500 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_IGNORE BIT(16) 501 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_FTYPE_VAL BIT(17) 502 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_RXDMA_ADDRINC_DIS BIT(24) 503 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_TXDMA_ADDRINC_DIS BIT(25) 504 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_RXDMA_PKT_STRM_EN BIT(26) 505 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_TXDMA_PKT_STRM_EN BIT(27) 506 + #define THC_M_PRT_DEVINT_CFG_2_THC_M_PRT_DEVINT_POL BIT(28) 507 + 508 + #define THC_M_PRT_RPRD_BA_LOW_1_THC_M_PRT_RPRD_BA_LOW GENMASK(31, 12) 509 + #define THC_M_PRT_RPRD_BA_HI_1_THC_M_PRT_RPRD_BA_HI GENMASK(31, 0) 510 + 511 + #define THC_M_PRT_RPRD_CNTRL_PCD GENMASK(6, 0) 512 + #define THC_M_PRT_RPRD_CNTRL_PTEC GENMASK(15, 8) 513 + #define THC_M_PRT_RPRD_CNTRL_PREFETCH_WM GENMASK(19, 16) 514 + 515 + #define THC_M_PRT_READ_DMA_CNTRL_START BIT(0) 516 + #define THC_M_PRT_READ_DMA_CNTRL_IE_ERROR BIT(1) 517 + #define THC_M_PRT_READ_DMA_CNTRL_IE_IOC BIT(2) 518 + #define THC_M_PRT_READ_DMA_CNTRL_IE_STALL BIT(3) 519 + #define THC_M_PRT_READ_DMA_CNTRL_IE_NDDI BIT(4) 520 + #define THC_M_PRT_READ_DMA_CNTRL_IE_EOF BIT(5) 521 + #define THC_M_PRT_READ_DMA_CNTRL_IE_DMACPL BIT(7) 522 + #define THC_M_PRT_READ_DMA_CNTRL_TPCRP GENMASK(15, 8) 523 + #define THC_M_PRT_READ_DMA_CNTRL_TPCWP GENMASK(23, 16) 524 + #define THC_M_PRT_READ_DMA_CNTRL_INT_SW_DMA_EN BIT(28) 525 + #define THC_M_PRT_READ_DMA_CNTRL_SOO BIT(29) 526 + #define THC_M_PRT_READ_DMA_CNTRL_UHS BIT(30) 527 + #define THC_M_PRT_READ_DMA_CNTRL_TPCPR BIT(31) 528 + 529 + #define THC_M_PRT_READ_DMA_INT_STS_DMACPL_STS BIT(0) 530 + #define THC_M_PRT_READ_DMA_INT_STS_ERROR_STS BIT(1) 531 + #define THC_M_PRT_READ_DMA_INT_STS_IOC_STS BIT(2) 532 + #define THC_M_PRT_READ_DMA_INT_STS_STALL_STS BIT(3) 533 + #define THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS BIT(4) 534 + #define THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS BIT(5) 535 + #define THC_M_PRT_READ_DMA_INT_STS_ACTIVE BIT(8) 536 + 537 + #define THC_M_PRT_READ_DMA_ERR_1_DLERR BIT(0) 538 + 539 + #define THC_M_PRT_GUC_OFFSET_LOW_1_THC_M_PRT_GUC_OFFSET_LOW GENMASK(31, 3) 540 + #define THC_M_PRT_GUC_OFFSET_HI_1_THC_M_PRT_GUC_OFFSET_HI GENMASK(31, 0) 541 + #define THC_M_PRT_GUC_WORKQ_ITEM_SZ_1_WORKQ_ITEM_SZ GENMASK(23, 0) 542 + #define THC_M_PRT_GUC_WORKQ_SZ_1_WORKQ_SZ GENMASK(23, 0) 543 + #define THC_M_PRT_GUC_WORKQ_SZ_1_FCD GENMASK(27, 24) 544 + #define THC_M_PRT_GUC_WORKQ_SZ_1_GIC GENMASK(31, 28) 545 + 546 + #define THC_M_PRT_TSEQ_CNTRL_1_RGD BIT(2) 547 + #define THC_M_PRT_TSEQ_CNTRL_1_EGP BIT(3) 548 + #define THC_M_PRT_TSEQ_CNTRL_1_RTO BIT(4) 549 + #define THC_M_PRT_TSEQ_CNTRL_1_EWOG BIT(5) 550 + #define THC_M_PRT_TSEQ_CNTRL_1_RWOGC BIT(6) 551 + #define THC_M_PRT_TSEQ_CNTRL_1_RX_DATA_FIFO_WR_WM GENMASK(25, 16) 552 + #define THC_M_PRT_TSEQ_CNTRL_1_RESET_PREP_CHICKEN BIT(30) 553 + #define THC_M_PRT_TSEQ_CNTRL_1_INT_EDG_DET_EN BIT(31) 554 + 555 + #define THC_M_PRT_GUC_DB_ADDR_LOW_1_GUC_DB_ADDR_LOW GENMASK(31, 2) 556 + #define THC_M_PRT_GUC_DB_ADDR_HI_1_GUC_DB_ADDR_HI GENMASK(31, 0) 557 + #define THC_M_PRT_GUC_DB_DATA_1_GUC_DB_DATA GENMASK(31, 0) 558 + #define THC_M_PRT_GUC_OFFSET_INITVAL_1_THC_M_PRT_GUC_OFFSET_INITVAL GENMASK(31, 0) 559 + 560 + #define THC_M_PRT_RD_BULK_ADDR_1_THC_M_PRT_RD_BULK_ADDR GENMASK(31, 0) 561 + 562 + #define THC_M_PRT_DB_CNT_1_THC_M_PRT_DB_CNT GENMASK(30, 0) 563 + #define THC_M_PRT_DB_CNT_1_THC_M_PRT_DB_CNT_RST BIT(31) 564 + 565 + #define THC_M_PRT_FRM_CNT_1_THC_M_PRT_FRM_CNT GENMASK(30, 0) 566 + #define THC_M_PRT_FRM_CNT_1_THC_M_PRT_FRM_CNT_RST BIT(31) 567 + 568 + #define THC_M_PRT_UFRM_CNT_1_THC_M_PRT_UFRM_CNT GENMASK(30, 0) 569 + #define THC_M_PRT_UFRM_CNT_1_THC_M_PRT_UFRM_CNT_RST BIT(31) 570 + 571 + #define THC_M_PRT_RXDMA_PKT_CNT_1_THC_M_PRT_RXDMA_PKT_CNT GENMASK(30, 0) 572 + #define THC_M_PRT_RXDMA_PKT_CNT_1_THC_M_PRT_RXDMA_PKT_CNT_RST BIT(31) 573 + 574 + #define THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT GENMASK(30, 0) 575 + #define THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST BIT(31) 576 + 577 + #define THC_M_PRT_FRAME_DROP_CNT_1_NOFD GENMASK(30, 0) 578 + #define THC_M_PRT_FRAME_DROP_CNT_1_RFDC BIT(31) 579 + 580 + #define THC_M_PRT_COALESCE_1_COALESCE_TIMEOUT GENMASK(6, 0) 581 + 582 + #define THC_M_PRT_RPRD_BA_LOW_2_THC_M_PRT_RPRD_BA_LOW GENMASK(31, 12) 583 + #define THC_M_PRT_RPRD_BA_HI_2_THC_M_PRT_RPRD_BA_HI GENMASK(31, 0) 584 + 585 + #define THC_M_PRT_READ_DMA_ERR_2_DLERR BIT(0) 586 + 587 + #define THC_M_PRT_GUC_OFFSET_LOW_2_THC_M_PRT_GUC_OFFSET_LOW GENMASK(31, 3) 588 + #define THC_M_PRT_GUC_OFFSET_HI_2_THC_M_PRT_GUC_OFFSET_HI GENMASK(31, 0) 589 + 590 + #define THC_M_PRT_GUC_WORKQ_ITEM_SZ_2_WORKQ_ITEM_SZ GENMASK(23, 0) 591 + #define THC_M_PRT_GUC_WORKQ_SZ_2_WORKQ_SZ GENMASK(23, 0) 592 + #define THC_M_PRT_GUC_WORKQ_SZ_2_FCD GENMASK(27, 24) 593 + #define THC_M_PRT_GUC_WORKQ_SZ_2_GIC GENMASK(31, 28) 594 + 595 + #define THC_M_PRT_TSEQ_CNTRL_2_RGD BIT(2) 596 + #define THC_M_PRT_TSEQ_CNTRL_2_EGP BIT(3) 597 + #define THC_M_PRT_TSEQ_CNTRL_2_RTO BIT(4) 598 + 599 + #define THC_M_PRT_GUC_DB_ADDR_LOW_2_GUC_DB_ADDR_LOW GENMASK(31, 2) 600 + #define THC_M_PRT_GUC_DB_ADDR_HI_2_GUC_DB_ADDR_HI GENMASK(31, 0) 601 + 602 + #define THC_M_PRT_GUC_DB_DATA_2_GUC_DB_DATA GENMASK(31, 0) 603 + 604 + #define THC_M_PRT_GUC_OFFSET_INITVAL_2_THC_M_PRT_GUC_OFFSET_INITVAL GENMASK(31, 0) 605 + 606 + #define THC_M_PRT_RD_BULK_ADDR_2_THC_M_PRT_RD_BULK_ADDR GENMASK(31, 0) 607 + 608 + #define THC_M_PRT_DB_CNT_2_THC_M_PRT_DB_CNT GENMASK(30, 0) 609 + #define THC_M_PRT_DB_CNT_2_THC_M_PRT_DB_CNT_RST BIT(31) 610 + 611 + #define THC_M_PRT_FRM_CNT_2_THC_M_PRT_FRM_CNT GENMASK(30, 0) 612 + #define THC_M_PRT_FRM_CNT_2_THC_M_PRT_FRM_CNT_RST BIT(31) 613 + 614 + #define THC_M_PRT_UFRM_CNT_2_THC_M_PRT_UFRM_CNT GENMASK(30, 0) 615 + #define THC_M_PRT_UFRM_CNT_2_THC_M_PRT_UFRM_CNT_RST BIT(31) 616 + 617 + #define THC_M_PRT_RXDMA_PKT_CNT_2_THC_M_PRT_RXDMA_PKT_CNT GENMASK(30, 0) 618 + #define THC_M_PRT_RXDMA_PKT_CNT_2_THC_M_PRT_RXDMA_PKT_CNT_RST BIT(31) 619 + 620 + #define THC_M_PRT_SWINT_CNT_2_THC_M_PRT_SWINT_CNT GENMASK(30, 0) 621 + #define THC_M_PRT_SWINT_CNT_2_THC_M_PRT_SWINT_CNT_RST BIT(31) 622 + 623 + #define THC_M_PRT_FRAME_DROP_CNT_2_NOFD GENMASK(30, 0) 624 + #define THC_M_PRT_FRAME_DROP_CNT_2_RFDC BIT(31) 625 + 626 + #define THC_M_PRT_COALESCE_2_COALESCE_TIMEOUT GENMASK(6, 0) 627 + 628 + #define THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_THC_I2C_RW_PIO_EN BIT(23) 629 + #define THC_M_PRT_SW_SEQ_I2C_WR_CNTRL_THC_PIO_I2C_WBC GENMASK(31, 26) 630 + 631 + #define THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_RX_DLEN_EN BIT(23) 632 + #define THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_WBC GENMASK(31, 26) 633 + 634 + #define THC_M_PRT_PRD_EMPTY_CNT_1_RPTEC BIT(31) 635 + #define THC_M_PRT_PRD_EMPTY_CNT_2_RPTEC BIT(31) 636 + 637 + #define THC_M_PRT_SW_DMA_PRD_TABLE_LEN_THC_M_PRT_SW_DMA_PRD_TABLE_LEN GENMASK(23, 0) 638 + 639 + #define THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_VAL GENMASK(3, 0) 640 + #define THC_M_PRT_SPI_DUTYC_CFG_SPI_CSA_CK_DELAY_EN BIT(25) 641 + 642 + /* CS Assertion delay default value */ 643 + #define THC_CSA_CK_DELAY_VAL_DEFAULT 4 644 + 645 + /* ARB policy definition */ 646 + /* Arbiter switches on packet boundary */ 647 + #define THC_ARB_POLICY_PACKET_BOUNDARY 0 648 + /* Arbiter switches on Micro Frame boundary */ 649 + #define THC_ARB_POLICY_UFRAME_BOUNDARY 1 650 + /* Arbiter switches on Frame boundary */ 651 + #define THC_ARB_POLICY_FRAME_BOUNDARY 2 652 + 653 + #define THC_REGMAP_POLLING_INTERVAL_US 10 /* 10us */ 654 + #define THC_PIO_DONE_TIMEOUT_US USEC_PER_SEC /* 1s */ 655 + 656 + /* Default configures for HIDSPI */ 657 + #define THC_BIT_OFFSET_INTERRUPT_TYPE 4 658 + /* input_report_type is 4 bits for HIDSPI */ 659 + #define THC_BIT_LENGTH_INTERRUPT_TYPE 4 660 + /* Last fragment indicator is bit 15 for HIDSPI */ 661 + #define THC_BIT_OFFSET_LAST_FRAGMENT_FLAG 22 662 + #define THC_BIT_OFFSET_MICROFRAME_SIZE 8 663 + /* input_report_length is 14 bits for HIDSPI */ 664 + #define THC_BIT_LENGTH_MICROFRAME_SIZE 14 665 + /* MFS unit in power of 2 */ 666 + #define THC_UNIT_MICROFRAME_SIZE 2 667 + #define THC_BITMASK_INTERRUPT_TYPE_DATA 1 668 + #define THC_BITMASK_INVALID_TYPE_DATA 2 669 + 670 + /* Interrupt Quiesce default timeout value */ 671 + #define THC_QUIESCE_EN_TIMEOUT_US USEC_PER_SEC /* 1s */ 672 + 673 + /* LTR definition */ 674 + /* 675 + * THC uses scale to calculate final LTR value. 676 + * Scale is geometric progression of 2^5 step, starting from 2^0. 677 + * For example, THC_LTR_SCALE_2(2) means 2^(5 * 2) = 1024, unit is ns. 678 + */ 679 + #define THC_LTR_SCALE_0 0 680 + #define THC_LTR_SCALE_1 1 681 + #define THC_LTR_SCALE_2 2 682 + #define THC_LTR_SCALE_3 3 683 + #define THC_LTR_SCALE_4 4 684 + #define THC_LTR_SCALE_5 5 685 + #define THC_LTR_MODE_ACTIVE 0 686 + #define THC_LTR_MODE_LP 1 687 + #define THC_LTR_MIN_VAL_SCALE_3 BIT(10) 688 + #define THC_LTR_MAX_VAL_SCALE_3 BIT(15) 689 + #define THC_LTR_MIN_VAL_SCALE_4 BIT(15) 690 + #define THC_LTR_MAX_VAL_SCALE_4 BIT(20) 691 + #define THC_LTR_MIN_VAL_SCALE_5 BIT(20) 692 + #define THC_LTR_MAX_VAL_SCALE_5 BIT(25) 693 + 694 + /* 695 + * THC PIO opcode default value 696 + * @THC_PIO_OP_SPI_TIC_READ: THC opcode for SPI PIO read 697 + * @THC_PIO_OP_SPI_TIC_WRITE: THC opcode for SPI PIO write 698 + * @THC_PIO_OP_I2C_SUBSYSTEM_READ: THC opcode for read I2C subsystem registers 699 + * @THC_PIO_OP_I2C_SUBSYSTEM_WRITE: THC opcode for write I2C subsystem registers 700 + * @THC_PIO_OP_I2C_TIC_READ: THC opcode for read I2C device 701 + * @THC_PIO_OP_I2C_TIC_WRITE: THC opcode for write I2C device 702 + * @THC_PIO_OP_I2C_TIC_WRITE_AND_READ: THC opcode for write followed by read I2C device 703 + */ 704 + enum thc_pio_opcode { 705 + THC_PIO_OP_SPI_TIC_READ = 0x4, 706 + THC_PIO_OP_SPI_TIC_WRITE = 0x6, 707 + THC_PIO_OP_I2C_SUBSYSTEM_READ = 0x12, 708 + THC_PIO_OP_I2C_SUBSYSTEM_WRITE = 0x13, 709 + THC_PIO_OP_I2C_TIC_READ = 0x14, 710 + THC_PIO_OP_I2C_TIC_WRITE = 0x18, 711 + THC_PIO_OP_I2C_TIC_WRITE_AND_READ = 0x1C, 712 + }; 713 + 714 + /** 715 + * THC SPI IO mode 716 + * @THC_SINGLE_IO: single IO mode, 1(opcode) - 1(address) - 1(data) 717 + * @THC_DUAL_IO: dual IO mode, 1(opcode) - 2(address) - 2(data) 718 + * @THC_QUAD_IO: quad IO mode, 1(opcode) - 4(address) - 4(data) 719 + * @THC_QUAD_PARALLEL_IO: parallel quad IO mode, 4(opcode) - 4(address) - 4(data) 720 + */ 721 + enum thc_spi_iomode { 722 + THC_SINGLE_IO = 0, 723 + THC_DUAL_IO = 1, 724 + THC_QUAD_IO = 2, 725 + THC_QUAD_PARALLEL_IO = 3, 726 + }; 727 + 728 + /** 729 + * THC SPI frequency divider 730 + * 731 + * This DIV final value is determined by THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN bit. 732 + * If THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN isn't be set, THC takes the DIV value directly; 733 + * If THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN is set, THC takes the DIV value multiply by 8. 734 + * 735 + * For example, if THC input clock is 125MHz: 736 + * When THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN isn't set, THC_SPI_FRQ_DIV_3 means DIV is 3, 737 + * THC final clock is 125 / 3 = 41.667MHz; 738 + * When THC_M_PRT_SPI_CFG_SPI_LOW_FREQ_EN is set, THC_SPI_FRQ_DIV_3 means DIV is 3 * 8, 739 + * THC final clock is 125 / (3 * 8) = 5.208MHz; 740 + */ 741 + enum thc_spi_frq_div { 742 + THC_SPI_FRQ_RESERVED = 0, 743 + THC_SPI_FRQ_DIV_1 = 1, 744 + THC_SPI_FRQ_DIV_2 = 2, 745 + THC_SPI_FRQ_DIV_3 = 3, 746 + THC_SPI_FRQ_DIV_4 = 4, 747 + THC_SPI_FRQ_DIV_5 = 5, 748 + THC_SPI_FRQ_DIV_6 = 6, 749 + THC_SPI_FRQ_DIV_7 = 7, 750 + }; 751 + 752 + /* THC I2C sub-system registers */ 753 + #define THC_I2C_IC_CON_OFFSET 0x0 754 + #define THC_I2C_IC_TAR_OFFSET 0x4 755 + #define THC_I2C_IC_SAR_OFFSET 0x8 756 + #define THC_I2C_IC_HS_MADDR_OFFSET 0xC 757 + #define THC_I2C_IC_DATA_CMD_OFFSET 0x10 758 + #define THC_I2C_IC_SS_SCL_HCNT_OFFSET 0x14 759 + #define THC_I2C_IC_UFM_SCL_HCNT_OFFSET 0x14 760 + #define THC_I2C_IC_SS_SCL_LCNT_OFFSET 0x18 761 + #define THC_I2C_IC_UFM_SCL_LCNT_OFFSET 0x18 762 + #define THC_I2C_IC_FS_SCL_HCNT_OFFSET 0x1C 763 + #define THC_I2C_IC_UFM_TBUF_CNT_OFFSET 0x1C 764 + #define THC_I2C_IC_FS_SCL_LCNT_OFFSET 0x20 765 + #define THC_I2C_IC_HS_SCL_HCNT_OFFSET 0x24 766 + #define THC_I2C_IC_HS_SCL_LCNT_OFFSET 0x28 767 + #define THC_I2C_IC_INTR_STAT_OFFSET 0x2C 768 + #define THC_I2C_IC_INTR_MASK_OFFSET 0x30 769 + #define THC_I2C_IC_RAW_INTR_STAT_OFFSET 0x34 770 + #define THC_I2C_IC_RX_TL_OFFSET 0x38 771 + #define THC_I2C_IC_TX_TL_OFFSET 0x3C 772 + #define THC_I2C_IC_CLR_INTR_OFFSET 0x40 773 + #define THC_I2C_IC_CLR_RX_UNDER_OFFSET 0x44 774 + #define THC_I2C_IC_CLR_RX_OVER_OFFSET 0x48 775 + #define THC_I2C_IC_CLR_TX_OVER_OFFSET 0x4C 776 + #define THC_I2C_IC_CLR_RD_REQ_OFFSET 0x50 777 + #define THC_I2C_IC_CLR_TX_ABRT_OFFSET 0x54 778 + #define THC_I2C_IC_CLR_RX_DONE_OFFSET 0x58 779 + #define THC_I2C_IC_CLR_ACTIVITY_OFFSET 0x5C 780 + #define THC_I2C_IC_CLR_STOP_DET_OFFSET 0x60 781 + #define THC_I2C_IC_CLR_START_DET_OFFSET 0x64 782 + #define THC_I2C_IC_CLR_GEN_CALL_OFFSET 0x68 783 + #define THC_I2C_IC_ENABLE_OFFSET 0x6C 784 + #define THC_I2C_IC_STATUS_OFFSET 0x70 785 + #define THC_I2C_IC_TXFLR_OFFSET 0x74 786 + #define THC_I2C_IC_RXFLR_OFFSET 0x78 787 + #define THC_I2C_IC_SDA_HOLD_OFFSET 0x7C 788 + #define THC_I2C_IC_TX_ABRT_SOURCE_OFFSET 0x80 789 + #define THC_I2C_IC_SLV_DATA_NACK_ONLY_OFFSET 0x84 790 + #define THC_I2C_IC_DMA_CR_OFFSET 0x88 791 + #define THC_I2C_IC_DMA_TDLR_OFFSET 0x8C 792 + #define THC_I2C_IC_DMA_RDLR_OFFSET 0x90 793 + #define THC_I2C_IC_SDA_SETUP_OFFSET 0x94 794 + #define THC_I2C_IC_ACK_GENERAL_CALL_OFFSET 0x98 795 + #define THC_I2C_IC_ENABLE_STATUS_OFFSET 0x9C 796 + #define THC_I2C_IC_FS_SPKLEN_OFFSET 0xA0 797 + #define THC_I2C_IC_UFM_SPKLEN_OFFSET 0xA0 798 + #define THC_I2C_IC_HS_SPKLEN_OFFSET 0xA4 799 + #define THC_I2C_IC_CLR_RESTART_DET_OFFSET 0xA8 800 + #define THC_I2C_IC_SCL_STUCK_AT_LOW_TIMEOUT_OFFSET 0xAC 801 + #define THC_I2C_IC_SDA_STUCK_AT_LOW_TIMEOUT_OFFSET 0xB0 802 + #define THC_I2C_IC_CLR_SCL_STUCK_DET_OFFSET 0xB4 803 + #define THC_I2C_IC_DEVICE_ID_OFFSET 0xB8 804 + #define THC_I2C_IC_SMBUS_CLK_LOW_SEXT_OFFSET 0xBC 805 + #define THC_I2C_IC_SMBUS_CLK_LOW_MEXT_OFFSET 0xC0 806 + #define THC_I2C_IC_SMBUS_THIGH_MAX_IDLE_COUNT_OFFSET 0xC4 807 + #define THC_I2C_IC_SMBUS_INTR_STAT_OFFSET 0xC8 808 + #define THC_I2C_IC_SMBUS_INTR_MASK_OFFSET 0xCC 809 + #define THC_I2C_IC_SMBUS_RAW_INTR_STAT_OFFSET 0xD0 810 + #define THC_I2C_IC_CLR_SMBUS_INTR_OFFSET 0xD4 811 + #define THC_I2C_IC_OPTIONAL_SAR_OFFSET 0xD8 812 + #define THC_I2C_IC_SMBUS_UDID_LSB_OFFSET 0xDC 813 + #define THC_I2C_IC_SMBUS_UDID_WORD0_OFFSET 0xDC 814 + #define THC_I2C_IC_SMBUS_UDID_WORD1_OFFSET 0xE0 815 + #define THC_I2C_IC_SMBUS_UDID_WORD2_OFFSET 0xE4 816 + #define THC_I2C_IC_SMBUS_UDID_WORD3_OFFSET 0xE8 817 + #define THC_I2C_IC_COMP_PARAM_1_OFFSET 0xF4 818 + #define THC_I2C_IC_COMP_VERSION_OFFSET 0xF8 819 + #define THC_I2C_IC_COMP_TYPE_OFFSET 0xFC 820 + 821 + /** 822 + * THC I2C sub-system supported speed mode 823 + */ 824 + enum THC_I2C_SPEED_MODE { 825 + THC_I2C_STANDARD = 1, 826 + THC_I2C_FAST_AND_PLUS = 2, 827 + THC_I2C_HIGH_SPEED = 3, 828 + }; 829 + 830 + /* THC I2C sub-system register bits definition */ 831 + #define THC_I2C_IC_ENABLE_ENABLE BIT(0) 832 + #define THC_I2C_IC_ENABLE_ABORT BIT(1) 833 + #define THC_I2C_IC_ENABLE_TX_CMD_BLOCK BIT(2) 834 + #define THC_I2C_IC_ENABLE_SDA_STUCK_RECOVERY_ENABLE BIT(3) 835 + #define THC_I2C_IC_ENABLE_SMBUS_CLK_RESET BIT(16) 836 + #define THC_I2C_IC_ENABLE_SMBUS_SUSPEND_EN BIT(17) 837 + #define THC_I2C_IC_ENABLE_SMBUS_ALERT_EN BIT(18) 838 + 839 + #define THC_I2C_IC_CON_MASTER_MODE BIT(0) 840 + #define THC_I2C_IC_CON_SPEED GENMASK(2, 1) 841 + #define THC_I2C_IC_CON_IC_10BITADDR_SLAVE BIT(3) 842 + #define THC_I2C_IC_CON_IC_10BITADDR_MASTER BIT(4) 843 + #define THC_I2C_IC_CON_IC_RESTART_EN BIT(5) 844 + #define THC_I2C_IC_CON_IC_SLAVE_DISABLE BIT(6) 845 + #define THC_I2C_IC_CON_STOP_DET_IFADDRESSED BIT(7) 846 + #define THC_I2C_IC_CON_TX_EMPTY_CTRL BIT(8) 847 + #define THC_I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL BIT(9) 848 + #define THC_I2C_IC_CON_STOP_DET_IF_MASTER_ACTIVE BIT(10) 849 + #define THC_I2C_IC_CON_BUS_CLEAR_FEATURE_CTRL BIT(11) 850 + #define THC_I2C_IC_CON_OPTIONAL_SAR_CTRL BIT(16) 851 + #define THC_I2C_IC_CON_SMBUS_SLAVE_QUICK_EN BIT(17) 852 + #define THC_I2C_IC_CON_SMBUS_ARP_EN BIT(18) 853 + #define THC_I2C_IC_CON_SMBUS_PERSISTENT_SLV_ADDR_EN BIT(19) 854 + 855 + #define THC_I2C_IC_TAR_IC_TAR GENMASK(9, 0) 856 + #define THC_I2C_IC_TAR_GC_OR_START BIT(10) 857 + #define THC_I2C_IC_TAR_SPECIAL BIT(11) 858 + #define THC_I2C_IC_TAR_IC_10BITADDR_MASTER BIT(12) 859 + #define THC_I2C_IC_TAR_DEVICE_ID BIT(13) 860 + #define THC_I2C_IC_TAR_SMBUS_QUICK_CMD BIT(16) 861 + 862 + #define THC_I2C_IC_INTR_MASK_M_RX_UNDER BIT(0) 863 + #define THC_I2C_IC_INTR_MASK_M_RX_OVER BIT(1) 864 + #define THC_I2C_IC_INTR_MASK_M_RX_FULL BIT(2) 865 + #define THC_I2C_IC_INTR_MASK_M_TX_OVER BIT(3) 866 + #define THC_I2C_IC_INTR_MASK_M_TX_EMPTY BIT(4) 867 + #define THC_I2C_IC_INTR_MASK_M_RD_REQ BIT(5) 868 + #define THC_I2C_IC_INTR_MASK_M_TX_ABRT BIT(6) 869 + #define THC_I2C_IC_INTR_MASK_M_RX_DONE BIT(7) 870 + #define THC_I2C_IC_INTR_MASK_M_ACTIVITY BIT(8) 871 + #define THC_I2C_IC_INTR_MASK_M_STOP_DET BIT(9) 872 + #define THC_I2C_IC_INTR_MASK_M_START_DET BIT(10) 873 + #define THC_I2C_IC_INTR_MASK_M_GEN_CALL BIT(11) 874 + #define THC_I2C_IC_INTR_MASK_M_RESTART_DET BIT(12) 875 + #define THC_I2C_IC_INTR_MASK_M_MASTER_ON_HOLD BIT(13) 876 + #define THC_I2C_IC_INTR_MASK_M_SCL_STUCK_AT_LOW BIT(14) 877 + 878 + #define THC_I2C_IC_DMA_CR_RDMAE BIT(0) 879 + #define THC_I2C_IC_DMA_CR_TDMAE BIT(1) 880 + 881 + #endif /* _INTEL_THC_HW_H_ */
+8
drivers/hid/wacom.h
··· 218 218 return value & (1 << (n - 1)) ? value & (~(~0U << n)) : value; 219 219 } 220 220 221 + static inline u32 wacom_rescale(u32 value, u32 in_max, u32 out_max) 222 + { 223 + if (in_max == 0 || out_max == 0) 224 + return 0; 225 + value = clamp(value, 0, in_max); 226 + return DIV_ROUND_CLOSEST(value * out_max, in_max); 227 + } 228 + 221 229 extern const struct hid_device_id wacom_ids[]; 222 230 223 231 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
+28 -15
drivers/hid/wacom_sys.c
··· 1084 1084 mutex_lock(&wacom->lock); 1085 1085 1086 1086 *dest = value & 0x7f; 1087 + for (unsigned int i = 0; i < wacom->led.count; i++) { 1088 + struct wacom_group_leds *group = &wacom->led.groups[i]; 1089 + 1090 + for (unsigned int j = 0; j < group->count; j++) { 1091 + if (dest == &wacom->led.llv) 1092 + group->leds[j].llv = *dest; 1093 + else if (dest == &wacom->led.hlv) 1094 + group->leds[j].hlv = *dest; 1095 + } 1096 + } 1097 + 1087 1098 err = wacom_led_control(wacom); 1088 1099 1089 1100 mutex_unlock(&wacom->lock); ··· 1313 1302 struct wacom *wacom = led->wacom; 1314 1303 1315 1304 if (wacom->led.max_hlv) 1316 - return led->hlv * LED_FULL / wacom->led.max_hlv; 1305 + return wacom_rescale(led->hlv, wacom->led.max_hlv, LED_FULL); 1317 1306 1318 1307 if (wacom->led.max_llv) 1319 - return led->llv * LED_FULL / wacom->led.max_llv; 1308 + return wacom_rescale(led->llv, wacom->led.max_llv, LED_FULL); 1320 1309 1321 1310 /* device doesn't support brightness tuning */ 1322 1311 return LED_FULL; ··· 1348 1337 goto out; 1349 1338 } 1350 1339 1351 - led->llv = wacom->led.llv = wacom->led.max_llv * brightness / LED_FULL; 1352 - led->hlv = wacom->led.hlv = wacom->led.max_hlv * brightness / LED_FULL; 1340 + led->llv = wacom->led.llv = wacom_rescale(brightness, LED_FULL, wacom->led.max_llv); 1341 + led->hlv = wacom->led.hlv = wacom_rescale(brightness, LED_FULL, wacom->led.max_hlv); 1353 1342 1354 1343 wacom->led.groups[led->group].select = led->id; 1355 1344 ··· 1381 1370 if (!name) 1382 1371 return -ENOMEM; 1383 1372 1384 - if (!read_only) { 1385 - led->trigger.name = name; 1386 - error = devm_led_trigger_register(dev, &led->trigger); 1387 - if (error) { 1388 - hid_err(wacom->hdev, 1389 - "failed to register LED trigger %s: %d\n", 1390 - led->cdev.name, error); 1391 - return error; 1392 - } 1393 - } 1394 - 1395 1373 led->group = group; 1396 1374 led->id = id; 1397 1375 led->wacom = wacom; ··· 1395 1395 led->cdev.default_trigger = led->cdev.name; 1396 1396 } else { 1397 1397 led->cdev.brightness_set = wacom_led_readonly_brightness_set; 1398 + } 1399 + 1400 + if (!read_only) { 1401 + led->trigger.name = name; 1402 + if (id == wacom->led.groups[group].select) 1403 + led->trigger.brightness = wacom_leds_brightness_get(led); 1404 + error = devm_led_trigger_register(dev, &led->trigger); 1405 + if (error) { 1406 + hid_err(wacom->hdev, 1407 + "failed to register LED trigger %s: %d\n", 1408 + led->cdev.name, error); 1409 + return error; 1410 + } 1398 1411 } 1399 1412 1400 1413 error = devm_led_classdev_register(dev, &led->cdev);
+5
drivers/hid/wacom_wac.c
··· 4946 4946 HID_DEVICE(BUS_I2C, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ 4947 4947 .driver_data = (kernel_ulong_t)&wacom_features_##prod 4948 4948 4949 + #define PCI_DEVICE_WACOM(prod) \ 4950 + HID_DEVICE(BUS_PCI, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ 4951 + .driver_data = (kernel_ulong_t)&wacom_features_##prod 4952 + 4949 4953 #define USB_DEVICE_LENOVO(prod) \ 4950 4954 HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ 4951 4955 .driver_data = (kernel_ulong_t)&wacom_features_##prod ··· 5119 5115 5120 5116 { USB_DEVICE_WACOM(HID_ANY_ID) }, 5121 5117 { I2C_DEVICE_WACOM(HID_ANY_ID) }, 5118 + { PCI_DEVICE_WACOM(HID_ANY_ID) }, 5122 5119 { BT_DEVICE_WACOM(HID_ANY_ID) }, 5123 5120 { } 5124 5121 };
+117
include/linux/hid-over-i2c.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright 2024 Intel Corporation */ 3 + 4 + #include <linux/bits.h> 5 + 6 + #ifndef _HID_OVER_I2C_H_ 7 + #define _HID_OVER_I2C_H_ 8 + 9 + #define HIDI2C_REG_LEN sizeof(__le16) 10 + 11 + /* Input report type definition in HIDI2C protocol */ 12 + enum hidi2c_report_type { 13 + HIDI2C_RESERVED = 0, 14 + HIDI2C_INPUT, 15 + HIDI2C_OUTPUT, 16 + HIDI2C_FEATURE, 17 + }; 18 + 19 + /* Power state type definition in HIDI2C protocol */ 20 + enum hidi2c_power_state { 21 + HIDI2C_ON, 22 + HIDI2C_SLEEP, 23 + }; 24 + 25 + /* Opcode type definition in HIDI2C protocol */ 26 + enum hidi2c_opcode { 27 + HIDI2C_RESET = 1, 28 + HIDI2C_GET_REPORT, 29 + HIDI2C_SET_REPORT, 30 + HIDI2C_GET_IDLE, 31 + HIDI2C_SET_IDLE, 32 + HIDI2C_GET_PROTOCOL, 33 + HIDI2C_SET_PROTOCOL, 34 + HIDI2C_SET_POWER, 35 + }; 36 + 37 + /** 38 + * struct hidi2c_report_packet - Report packet definition in HIDI2C protocol 39 + * @len: data field length 40 + * @data: HIDI2C report packet data 41 + */ 42 + struct hidi2c_report_packet { 43 + __le16 len; 44 + u8 data[]; 45 + } __packed; 46 + 47 + #define HIDI2C_LENGTH_LEN sizeof(__le16) 48 + 49 + #define HIDI2C_PACKET_LEN(data_len) ((data_len) + HIDI2C_LENGTH_LEN) 50 + #define HIDI2C_DATA_LEN(pkt_len) ((pkt_len) - HIDI2C_LENGTH_LEN) 51 + 52 + #define HIDI2C_CMD_MAX_RI 0x0F 53 + 54 + /** 55 + * HIDI2C command data packet - Command packet definition in HIDI2C protocol 56 + * @report_id: [0:3] report id (<15) for features or output reports 57 + * @report_type: [4:5] indicate report type, reference to hidi2c_report_type 58 + * @reserved0: [6:7] reserved bits 59 + * @opcode: [8:11] command operation code, reference to hidi2c_opcode 60 + * @reserved1: [12:15] reserved bits 61 + * @report_id_optional: [23:16] appended 3rd byte. 62 + * If the report_id in the low byte is set to the 63 + * sentinel value (HIDI2C_CMD_MAX_RI), then this 64 + * optional third byte represents the report id (>=15) 65 + * Otherwise, not this 3rd byte. 66 + */ 67 + 68 + #define HIDI2C_CMD_LEN sizeof(__le16) 69 + #define HIDI2C_CMD_LEN_OPT (sizeof(__le16) + 1) 70 + #define HIDI2C_CMD_REPORT_ID GENMASK(3, 0) 71 + #define HIDI2C_CMD_REPORT_TYPE GENMASK(5, 4) 72 + #define HIDI2C_CMD_OPCODE GENMASK(11, 8) 73 + #define HIDI2C_CMD_OPCODE GENMASK(11, 8) 74 + #define HIDI2C_CMD_3RD_BYTE GENMASK(23, 16) 75 + 76 + #define HIDI2C_HID_DESC_BCDVERSION 0x100 77 + 78 + /** 79 + * struct hidi2c_dev_descriptor - HIDI2C device descriptor definition 80 + * @dev_desc_len: The length of the complete device descriptor, fixed to 0x1E (30). 81 + * @bcd_ver: The version number of the HIDI2C protocol supported. 82 + * In binary coded decimal (BCD) format. 83 + * @report_desc_len: The length of the report descriptor 84 + * @report_desc_reg: The register address to retrieve report descriptor 85 + * @input_reg: the register address to retrieve input report 86 + * @max_input_len: The length of the largest possible HID input (or feature) report 87 + * @output_reg: the register address to send output report 88 + * @max_output_len: The length of the largest output (or feature) report 89 + * @cmd_reg: the register address to send command 90 + * @data_reg: the register address to send command data 91 + * @vendor_id: Device manufacturers vendor ID 92 + * @product_id: Device unique model/product ID 93 + * @version_id: Device’s unique version 94 + * @reserved0: Reserved and should be 0 95 + * @reserved1: Reserved and should be 0 96 + */ 97 + struct hidi2c_dev_descriptor { 98 + __le16 dev_desc_len; 99 + __le16 bcd_ver; 100 + __le16 report_desc_len; 101 + __le16 report_desc_reg; 102 + __le16 input_reg; 103 + __le16 max_input_len; 104 + __le16 output_reg; 105 + __le16 max_output_len; 106 + __le16 cmd_reg; 107 + __le16 data_reg; 108 + __le16 vendor_id; 109 + __le16 product_id; 110 + __le16 version_id; 111 + __le16 reserved0; 112 + __le16 reserved1; 113 + } __packed; 114 + 115 + #define HIDI2C_DEV_DESC_LEN sizeof(struct hidi2c_dev_descriptor) 116 + 117 + #endif /* _HID_OVER_I2C_H_ */
+155
include/linux/hid-over-spi.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright 2024 Intel Corporation */ 3 + 4 + #ifndef _HID_OVER_SPI_H_ 5 + #define _HID_OVER_SPI_H_ 6 + 7 + #include <linux/bits.h> 8 + #include <linux/types.h> 9 + 10 + /* Input report type definition in HIDSPI protocol */ 11 + enum input_report_type { 12 + INVALID_INPUT_REPORT_TYPE_0 = 0, 13 + DATA = 1, 14 + INVALID_TYPE_2 = 2, 15 + RESET_RESPONSE = 3, 16 + COMMAND_RESPONSE = 4, 17 + GET_FEATURE_RESPONSE = 5, 18 + INVALID_TYPE_6 = 6, 19 + DEVICE_DESCRIPTOR_RESPONSE = 7, 20 + REPORT_DESCRIPTOR_RESPONSE = 8, 21 + SET_FEATURE_RESPONSE = 9, 22 + OUTPUT_REPORT_RESPONSE = 10, 23 + GET_INPUT_REPORT_RESPONSE = 11, 24 + INVALID_INPUT_REPORT_TYPE = 0xF, 25 + }; 26 + 27 + /* Output report type definition in HIDSPI protocol */ 28 + enum output_report_type { 29 + INVALID_OUTPUT_REPORT_TYPE_0 = 0, 30 + DEVICE_DESCRIPTOR = 1, 31 + REPORT_DESCRIPTOR = 2, 32 + SET_FEATURE = 3, 33 + GET_FEATURE = 4, 34 + OUTPUT_REPORT = 5, 35 + GET_INPUT_REPORT = 6, 36 + COMMAND_CONTENT = 7, 37 + }; 38 + 39 + /* Set power command ID for output report */ 40 + #define HIDSPI_SET_POWER_CMD_ID 1 41 + 42 + /* Power state definition in HIDSPI protocol */ 43 + enum hidspi_power_state { 44 + HIDSPI_ON = 1, 45 + HIDSPI_SLEEP = 2, 46 + HIDSPI_OFF = 3, 47 + }; 48 + 49 + /** 50 + * Input report header definition in HIDSPI protocol 51 + * Report header size is 32bits, it includes: 52 + * protocol_ver: [0:3] Current supported HIDSPI protocol version, must be 0x3 53 + * reserved0: [4:7] Reserved bits 54 + * input_report_len: [8:21] Input report length in number bytes divided by 4 55 + * last_frag_flag: [22]Indicate if this packet is last fragment. 56 + * 1 - indicates last fragment 57 + * 0 - indicates additional fragments 58 + * reserved1: [23] Reserved bits 59 + * @sync_const: [24:31] Used to validate input report header, must be 0x5A 60 + */ 61 + #define HIDSPI_INPUT_HEADER_SIZE sizeof(u32) 62 + #define HIDSPI_INPUT_HEADER_VER GENMASK(3, 0) 63 + #define HIDSPI_INPUT_HEADER_REPORT_LEN GENMASK(21, 8) 64 + #define HIDSPI_INPUT_HEADER_LAST_FLAG BIT(22) 65 + #define HIDSPI_INPUT_HEADER_SYNC GENMASK(31, 24) 66 + 67 + /** 68 + * struct input_report_body_header - Input report body header definition in HIDSPI protocol 69 + * @input_report_type: indicate input report type, reference to enum input_report_type 70 + * @content_len: this input report body packet length 71 + * @content_id: indicate this input report's report id 72 + */ 73 + struct input_report_body_header { 74 + u8 input_report_type; 75 + __le16 content_len; 76 + u8 content_id; 77 + } __packed; 78 + 79 + #define HIDSPI_INPUT_BODY_HEADER_SIZE sizeof(struct input_report_body_header) 80 + 81 + /** 82 + * struct input_report_body - Input report body definition in HIDSPI protocol 83 + * @body_hdr: input report body header 84 + * @content: input report body content 85 + */ 86 + struct input_report_body { 87 + struct input_report_body_header body_hdr; 88 + u8 content[]; 89 + } __packed; 90 + 91 + #define HIDSPI_INPUT_BODY_SIZE(content_len) ((content_len) + HIDSPI_INPUT_BODY_HEADER_SIZE) 92 + 93 + /** 94 + * struct output_report_header - Output report header definition in HIDSPI protocol 95 + * @report_type: output report type, reference to enum output_report_type 96 + * @content_len: length of content 97 + * @content_id: 0x00 - descriptors 98 + * report id - Set/Feature feature or Input/Output Reports 99 + * command opcode - for commands 100 + */ 101 + struct output_report_header { 102 + u8 report_type; 103 + __le16 content_len; 104 + u8 content_id; 105 + } __packed; 106 + 107 + #define HIDSPI_OUTPUT_REPORT_HEADER_SIZE sizeof(struct output_report_header) 108 + 109 + /** 110 + * struct output_report - Output report definition in HIDSPI protocol 111 + * @output_hdr: output report header 112 + * @content: output report content 113 + */ 114 + struct output_report { 115 + struct output_report_header output_hdr; 116 + u8 content[]; 117 + } __packed; 118 + 119 + #define HIDSPI_OUTPUT_REPORT_SIZE(content_len) ((content_len) + HIDSPI_OUTPUT_REPORT_HEADER_SIZE) 120 + 121 + /** 122 + * struct hidspi_dev_descriptor - HIDSPI device descriptor definition 123 + * @dev_desc_len: The length of the complete device descriptor, fixed to 0x18 (24). 124 + * @bcd_ver: The version number of the HIDSPI protocol supported. 125 + * In binary coded decimal (BCD) format. Must be fixed to 0x0300. 126 + * @rep_desc_len: The length of the report descriptor 127 + * @max_input_len: The length of the largest possible HID input (or feature) report 128 + * @max_output_len: The length of the largest output (or feature) report 129 + * @max_frag_len: The length of the largest fragment, where a fragment represents 130 + * the body of an input report. 131 + * @vendor_id: Device manufacturers vendor ID 132 + * @product_id: Device unique model/product ID 133 + * @version_id: Device’s unique version 134 + * @flags: Specify flags for the device’s operation 135 + * @reserved: Reserved and should be 0 136 + */ 137 + struct hidspi_dev_descriptor { 138 + __le16 dev_desc_len; 139 + __le16 bcd_ver; 140 + __le16 rep_desc_len; 141 + __le16 max_input_len; 142 + __le16 max_output_len; 143 + __le16 max_frag_len; 144 + __le16 vendor_id; 145 + __le16 product_id; 146 + __le16 version_id; 147 + __le16 flags; 148 + __le32 reserved; 149 + }; 150 + 151 + #define HIDSPI_DEVICE_DESCRIPTOR_SIZE sizeof(struct hidspi_dev_descriptor) 152 + #define HIDSPI_INPUT_DEVICE_DESCRIPTOR_SIZE \ 153 + (HIDSPI_INPUT_BODY_HEADER_SIZE + HIDSPI_DEVICE_DESCRIPTOR_SIZE) 154 + 155 + #endif /* _HID_OVER_SPI_H_ */
+1
include/linux/hid.h
··· 218 218 #define HID_GD_DOWN 0x00010091 219 219 #define HID_GD_RIGHT 0x00010092 220 220 #define HID_GD_LEFT 0x00010093 221 + #define HID_GD_DO_NOT_DISTURB 0x0001009b 221 222 /* Microsoft Win8 Wireless Radio Controls CA usage codes */ 222 223 #define HID_GD_RFKILL_BTN 0x000100c6 223 224 #define HID_GD_RFKILL_LED 0x000100c7
-1
include/linux/intel-ish-client-if.h
··· 100 100 int ishtp_cl_send(struct ishtp_cl *cl, uint8_t *buf, size_t length); 101 101 int ishtp_cl_flush_queues(struct ishtp_cl *cl); 102 102 int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb); 103 - bool ishtp_cl_tx_empty(struct ishtp_cl *cl); 104 103 struct ishtp_cl_rb *ishtp_cl_rx_get_rb(struct ishtp_cl *cl); 105 104 void *ishtp_get_client_data(struct ishtp_cl *cl); 106 105 void ishtp_set_client_data(struct ishtp_cl *cl, void *data);
+5
include/linux/platform_data/x86/asus-wmi.h
··· 186 186 }, 187 187 { 188 188 .matches = { 189 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ProArt P16"), 190 + }, 191 + }, 192 + { 193 + .matches = { 189 194 DMI_MATCH(DMI_BOARD_NAME, "GA403U"), 190 195 }, 191 196 },
+1
tools/testing/selftests/hid/.gitignore
··· 1 1 bpftool 2 2 *.skel.h 3 + /host-tools 3 4 /tools 4 5 hid_bpf 5 6 hidraw