From 45e92a093099eaf71ff2915a5f6ab5c04c8385e6 Mon Sep 17 00:00:00 2001 From: Even Xu Date: Wed, 14 May 2025 14:19:40 +0800 Subject: HID: Intel-thc-hid: Intel-thc: Introduce max input size control This patch adds support for a new feature, named "Max Input Size Control", allowing driver to set a maximum input size for RxDMA. This enhancement aims to prevent RxDMA buffer overruns caused by data corruption on the I2C bus, thereby improving overall system stability. APIs added: - thc_i2c_set_rx_max_size(): Set the maximum input size for I2C RxDMA. - thc_i2c_rx_max_size_enable(): Enable or disable the max input size control. As this max input size control feature is only applicable to RxDMA and must remain disabled during SWDMA operations, it also involves a change in SWDMA code to record the max input size control feature state before SWDMA and restore the state after SWDMA. Signed-off-by: Even Xu Tested-by: Chong Han Reviewed-by: Andy Shevchenko Signed-off-by: Jiri Kosina --- Documentation/hid/intel-thc-hid.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'Documentation') diff --git a/Documentation/hid/intel-thc-hid.rst b/Documentation/hid/intel-thc-hid.rst index dc9250787fc5..15b04fa215c7 100644 --- a/Documentation/hid/intel-thc-hid.rst +++ b/Documentation/hid/intel-thc-hid.rst @@ -188,6 +188,20 @@ Control register. Reset line is controlled by BIOS (or EFI) through ACPI _RST method, driver needs to call this device ACPI _RST method to reset touch IC during initialization. +2.3 Max input size control +-------------------------- + +This is a new feature introduced in Panther Lake platform, THC hardware allows driver to set +a max input size for RxDMA. After this max size gets set and enabled, for every input report +packet reading, THC hardware sequencer will first read incoming input packet size, then compare +input packet size with the given max size: +- if input packet size <= max size, THC continues using input packet size to finish the reading +- if input packet size > max size, there is potential input data crash risk during + transferring, THC will use max size instead of input packet size for reading + +This feature is used to avoid data corruption which will cause RxDMA buffer overrun issue for +I2C bus, and enhance whole system stability. + 3. High level concept ===================== -- cgit v1.2.3 From 22da60f0304b6bfd2c7cba8ee88086f344ef5206 Mon Sep 17 00:00:00 2001 From: Even Xu Date: Wed, 14 May 2025 14:19:41 +0800 Subject: HID: Intel-thc-hid: Intel-thc: Introduce interrupt delay control This patch adds support for a new feature, named "Interrupt Delay", allowing driver to set a specific delay time for next interrupt detection. It gives driver a capability to control THC waiting time for the next interrupt, to reduce the likelihood of spurious readings. APIs added: - thc_i2c_set_rx_int_delay(): Set I2C Rx input interrupt delay value - thc_i2c_rx_int_delay_enable(): Enable or disable I2C Rx interrupt delay As this interrupt delay feature is only applicable to RxDMA and must remain disabled during SWDMA operations, it also involves a change in SWDMA code to record the max input size control feature state before SWDMA and restore the state after SWDMA. Signed-off-by: Even Xu Tested-by: Chong Han Reviewed-by: Andy Shevchenko Signed-off-by: Jiri Kosina --- Documentation/hid/intel-thc-hid.rst | 13 ++++ .../hid/intel-thc-hid/intel-thc/intel-thc-dev.c | 71 ++++++++++++++++++++++ .../hid/intel-thc-hid/intel-thc/intel-thc-dev.h | 6 ++ .../hid/intel-thc-hid/intel-thc/intel-thc-dma.c | 18 ++++++ .../hid/intel-thc-hid/intel-thc/intel-thc-dma.h | 3 + drivers/hid/intel-thc-hid/intel-thc/intel-thc-hw.h | 2 + 6 files changed, 113 insertions(+) (limited to 'Documentation') diff --git a/Documentation/hid/intel-thc-hid.rst b/Documentation/hid/intel-thc-hid.rst index 15b04fa215c7..23d5110cb871 100644 --- a/Documentation/hid/intel-thc-hid.rst +++ b/Documentation/hid/intel-thc-hid.rst @@ -202,6 +202,19 @@ input packet size with the given max size: This feature is used to avoid data corruption which will cause RxDMA buffer overrun issue for I2C bus, and enhance whole system stability. +2.4 Interrupt delay +------------------- + +Because of MCU performance limitation, some touch devices cannot de-assert interrupt pin +immediately after input data is transferred, which cause an interrupt toggle delay. But THC +always detects next interrupt immediately after last input interrupt is handled. In this +case, the delayed interrupt de-assertion will be recognized as a new interrupt signal by THC, +and causes THC to start an input report reading spuriously. + +In order to avoid this situation, THC introduced interrupt delay new feature in Panther Lake +platform, where THC allows driver to set an interrupt delay. After this feature is enabled, +THC will delay this given time for next interrupt detection. + 3. High level concept ===================== diff --git a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c index 8fc6e8484cd8..6f2263869b20 100644 --- a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c +++ b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c @@ -2,6 +2,7 @@ /* Copyright (c) 2024 Intel Corporation */ #include +#include #include #include "intel-thc-dev.h" @@ -1640,6 +1641,76 @@ int thc_i2c_rx_max_size_enable(struct thc_device *dev, bool enable) } EXPORT_SYMBOL_NS_GPL(thc_i2c_rx_max_size_enable, "INTEL_THC"); +/** + * thc_i2c_set_rx_int_delay - Set I2C Rx input interrupt delay value + * @dev: The pointer of THC private device context + * @delay_us: Interrupt delay value, unit is us + * + * Set @delay_us for I2C RxDMA input interrupt delay feature. + * + * Return: 0 on success, other error codes on failure. + */ +int thc_i2c_set_rx_int_delay(struct thc_device *dev, u32 delay_us) +{ + u32 val; + int ret; + + if (!dev) + return -EINVAL; + + if (!delay_us) + return -EOPNOTSUPP; + + ret = regmap_read(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, &val); + if (ret) + return ret; + + /* THC hardware counts at 10us unit */ + val |= FIELD_PREP(THC_M_PRT_SPI_ICRRD_OPCODE_I2C_INTERVAL, DIV_ROUND_UP(delay_us, 10)); + + ret = regmap_write(dev->thc_regmap, THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET, val); + if (ret) + return ret; + + dev->i2c_int_delay_us = delay_us; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(thc_i2c_set_rx_int_delay, "INTEL_THC"); + +/** + * thc_i2c_rx_int_delay_enable - Enable I2C Rx interrupt delay + * @dev: The pointer of THC private device context + * @enable: Enable interrupt delay or not + * + * Enable or disable I2C RxDMA input interrupt delay feature. + * Input interrupt delay can only be enabled after interrupt delay value + * was set by thc_i2c_set_rx_int_delay(). + * + * Return: 0 on success, other error codes on failure. + */ +int thc_i2c_rx_int_delay_enable(struct thc_device *dev, bool enable) +{ + u32 mask = THC_M_PRT_SPI_ICRRD_OPCODE_I2C_INTERVAL_EN; + u32 val = enable ? mask : 0; + int ret; + + if (!dev) + return -EINVAL; + + if (!dev->i2c_int_delay_us) + return -EOPNOTSUPP; + + ret = regmap_write_bits(dev->thc_regmap, THC_M_PRT_SPI_ICRRD_OPCODE_OFFSET, mask, val); + if (ret) + return ret; + + dev->i2c_int_delay_en = enable; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(thc_i2c_rx_int_delay_enable, "INTEL_THC"); + MODULE_AUTHOR("Xinpeng Sun "); MODULE_AUTHOR("Even Xu "); diff --git a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.h b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.h index 3e0bb0b31ed9..8666e2362e32 100644 --- a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.h +++ b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.h @@ -63,7 +63,9 @@ enum thc_int_type { * @perf_limit: The delay between read operation and write operation * @i2c_subip_regs: The copy of THC I2C sub-system registers for resuming restore * @i2c_max_rx_size: I2C Rx transfer max input size + * @i2c_int_delay_us: I2C input interrupt delay, unit is us * @i2c_max_rx_size_en: Bool value that indicates I2C max input size control enabled or not + * @i2c_int_delay_en: Bool value that indicates I2C input interrupt delay enabled or not */ struct thc_device { struct device *dev; @@ -85,7 +87,9 @@ struct thc_device { u32 *i2c_subip_regs; u32 i2c_max_rx_size; + u32 i2c_int_delay_us; bool i2c_max_rx_size_en; + bool i2c_int_delay_en; }; struct thc_device *thc_dev_init(struct device *device, void __iomem *mem_addr); @@ -119,5 +123,7 @@ int thc_i2c_subip_regs_save(struct thc_device *dev); int thc_i2c_subip_regs_restore(struct thc_device *dev); int thc_i2c_set_rx_max_size(struct thc_device *dev, u32 max_rx_size); int thc_i2c_rx_max_size_enable(struct thc_device *dev, bool enable); +int thc_i2c_set_rx_int_delay(struct thc_device *dev, u32 delay_us); +int thc_i2c_rx_int_delay_enable(struct thc_device *dev, bool enable); #endif /* _INTEL_THC_DEV_H_ */ diff --git a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c index 5bef342cd738..82b8854843e0 100644 --- a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c +++ b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c @@ -725,6 +725,15 @@ static int thc_swdma_read_start(struct thc_device *dev, void *write_buff, dev->dma_ctx->rx_max_size_en = true; } + /* + * Interrupt delay feature is in the same situation with max input size control feature, + * needs record feature state before SWDMA. + */ + if (dev->i2c_int_delay_en) { + thc_i2c_rx_int_delay_enable(dev, false); + dev->dma_ctx->rx_int_delay_en = true; + } + mask = THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_WBC | THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_RX_DLEN_EN; val = FIELD_PREP(THC_M_PRT_RPRD_CNTRL_SW_THC_SWDMA_I2C_WBC, write_len) | @@ -776,6 +785,15 @@ static int thc_swdma_read_completion(struct thc_device *dev) dev->dma_ctx->rx_max_size_en = false; } + /* + * Restore input interrupt delay feature to previous state after SWDMA if it was + * enabled before SWDMA, and reset temp rx_int_delay_en variable for next time. + */ + if (dev->dma_ctx->rx_int_delay_en) { + thc_i2c_rx_int_delay_enable(dev, true); + dev->dma_ctx->rx_int_delay_en = false; + } + thc_reset_dma_settings(dev); dma_set_start_bit(dev, &dev->dma_ctx->dma_config[THC_RXDMA2]); diff --git a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h index 42cfd55c3e2c..78917400492c 100644 --- a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h +++ b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h @@ -123,12 +123,15 @@ struct thc_dma_configuration { * @use_write_interrupts: Indicate TxDMA using interrupt or polling * @rx_max_size_en: Temp flag to indicate THC I2C Rx max input size control feature * enabled or not, only be used during SWDMA operation. + * @rx_int_delay_en: Temp flag to indicate THC I2C Rx interrupt delay feature + * enabled or not, only be used during SWDMA operation. */ struct thc_dma_context { struct thc_dma_configuration dma_config[MAX_THC_DMA_CHANNEL]; u8 use_write_interrupts; bool rx_max_size_en; + bool rx_int_delay_en; }; struct thc_device; diff --git a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-hw.h b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-hw.h index ed8e28858e0c..413730f8e3f7 100644 --- a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-hw.h +++ b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-hw.h @@ -400,6 +400,8 @@ #define THC_M_PRT_SPI_ICRRD_OPCODE_SPI_QIO GENMASK(15, 8) #define THC_M_PRT_SPI_ICRRD_OPCODE_I2C_MAX_SIZE GENMASK(15, 0) +#define THC_M_PRT_SPI_ICRRD_OPCODE_I2C_INTERVAL GENMASK(23, 16) +#define THC_M_PRT_SPI_ICRRD_OPCODE_I2C_INTERVAL_EN BIT(30) #define THC_M_PRT_SPI_ICRRD_OPCODE_I2C_MAX_SIZE_EN BIT(31) #define THC_M_PRT_INT_EN_SIPE BIT(0) -- cgit v1.2.3 From 7852beb143509d407cb8370604bb7bc97955ec84 Mon Sep 17 00:00:00 2001 From: Bagas Sanjaya Date: Fri, 13 Jun 2025 08:43:27 +0700 Subject: HID: intel-thc-hid: Separate max input size control conditional list Stephen Rothwell reports htmldocs warning: Documentation/hid/intel-thc-hid.rst:200: ERROR: Unexpected indentation. [docutils] Separate conditional list for max input size control by a blank line to fix the warning. Fixes: 45e92a093099 ("HID: Intel-thc-hid: Intel-thc: Introduce max input size control") Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/linux-next/20250611142409.7d4683b0@canb.auug.org.au/ Signed-off-by: Bagas Sanjaya Reviewed-by: Even Xu Signed-off-by: Jiri Kosina --- Documentation/hid/intel-thc-hid.rst | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/hid/intel-thc-hid.rst b/Documentation/hid/intel-thc-hid.rst index 23d5110cb871..8b378c57b5aa 100644 --- a/Documentation/hid/intel-thc-hid.rst +++ b/Documentation/hid/intel-thc-hid.rst @@ -195,6 +195,7 @@ This is a new feature introduced in Panther Lake platform, THC hardware allows d a max input size for RxDMA. After this max size gets set and enabled, for every input report packet reading, THC hardware sequencer will first read incoming input packet size, then compare input packet size with the given max size: + - if input packet size <= max size, THC continues using input packet size to finish the reading - if input packet size > max size, there is potential input data crash risk during transferring, THC will use max size instead of input packet size for reading -- cgit v1.2.3