]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
HID: intel-thc-hid: Add basic THC driver skeleton
authorXinpeng Sun <xinpeng.sun@intel.com>
Mon, 6 Jan 2025 02:31:31 +0000 (10:31 +0800)
committerJiri Kosina <jkosina@suse.com>
Thu, 9 Jan 2025 09:14:14 +0000 (10:14 +0100)
Create intel-thc-hid folder and add Kconfig and Makefile for THC drivers.
Add basic THC device context structure, definitions and related
initialization APIs for THC Hardware layer driver. Also initialize
regmap struct for future THC registers access.

Co-developed-by: Even Xu <even.xu@intel.com>
Signed-off-by: Even Xu <even.xu@intel.com>
Signed-off-by: Xinpeng Sun <xinpeng.sun@intel.com>
Tested-by: Rui Zhang <rui1.zhang@intel.com>
Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Tested-by: Aaron Ma <aaron.ma@canonical.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
MAINTAINERS
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/intel-thc-hid/Kconfig [new file with mode: 0644]
drivers/hid/intel-thc-hid/Makefile [new file with mode: 0644]
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c [new file with mode: 0644]
drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.h [new file with mode: 0644]

index f4d652f310e87297c7ca4e9957acf4d1f909fd19..ec8b6aa11d89d5afe8dac0084a543c6397b9d304 100644 (file)
@@ -11873,6 +11873,12 @@ S:     Maintained
 F:     arch/x86/include/asm/intel_telemetry.h
 F:     drivers/platform/x86/intel/telemetry/
 
+INTEL TOUCH HOST CONTROLLER (THC) DRIVER
+M:     Even Xu <even.xu@intel.com>
+M:     Xinpeng Sun <xinpeng.sun@intel.com>
+S:     Maintained
+F:     drivers/hid/intel-thc-hid/
+
 INTEL TPMI DRIVER
 M:     Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
 L:     platform-driver-x86@vger.kernel.org
index 4d2a89d65b6584d4da575e4c86449ddd484056c8..c57927529f8a4414ac4afc54044bd29d5858876d 100644 (file)
@@ -1386,4 +1386,6 @@ source "drivers/hid/amd-sfh-hid/Kconfig"
 
 source "drivers/hid/surface-hid/Kconfig"
 
+source "drivers/hid/intel-thc-hid/Kconfig"
+
 endif # HID_SUPPORT
index 24de45f3677d1693ff234018d56b7931d60b3de5..482b096eea28087b01d667c0e2c83382c132f017 100644 (file)
@@ -171,3 +171,5 @@ obj-$(INTEL_ISH_FIRMWARE_DOWNLOADER)        += intel-ish-hid/
 obj-$(CONFIG_AMD_SFH_HID)       += amd-sfh-hid/
 
 obj-$(CONFIG_SURFACE_HID_CORE)  += surface-hid/
+
+obj-$(CONFIG_INTEL_THC_HID)     += intel-thc-hid/
diff --git a/drivers/hid/intel-thc-hid/Kconfig b/drivers/hid/intel-thc-hid/Kconfig
new file mode 100644 (file)
index 0000000..dc7c5a2
--- /dev/null
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2024, Intel Corporation.
+
+menu "Intel THC HID Support"
+       depends on X86_64 && PCI
+
+config INTEL_THC_HID
+       tristate "Intel Touch Host Controller"
+       select HID
+       help
+         THC (Touch Host Controller) is the name of the IP block in PCH that
+         interfaces with Touch Devices (ex: touchscreen, touchpad etc.). It
+         is comprised of 3 key functional blocks: A natively half-duplex
+         Quad I/O capable SPI master; a low latency I2C interface to support
+         HIDI2C compliant devices; a hardware sequencer with Read/Write DMA
+         capability to system memory.
+
+         Say Y/M here if you want to support Intel THC. If unsure, say N.
+
+endmenu
diff --git a/drivers/hid/intel-thc-hid/Makefile b/drivers/hid/intel-thc-hid/Makefile
new file mode 100644 (file)
index 0000000..bebb60b
--- /dev/null
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile - Intel Touch Host Controller (THC) drivers
+# Copyright (c) 2024, Intel Corporation.
+#
+#
+
+obj-$(CONFIG_INTEL_THC_HID) += intel-thc.o
+intel-thc-objs += intel-thc/intel-thc-dev.o
+
+ccflags-y += -I $(src)/intel-thc
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
new file mode 100644 (file)
index 0000000..de7a0ed
--- /dev/null
@@ -0,0 +1,219 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2024 Intel Corporation */
+
+#include <linux/regmap.h>
+
+#include "intel-thc-dev.h"
+
+static int thc_regmap_read(void *context, unsigned int reg,
+                          unsigned int *val)
+{
+       struct thc_device *thc_ctx = context;
+       void __iomem *base = thc_ctx->mmio_addr;
+
+       *val = ioread32(base + reg);
+       return 0;
+}
+
+static int thc_regmap_write(void *context, unsigned int reg,
+                           unsigned int val)
+{
+       struct thc_device *thc_ctx = context;
+       void __iomem *base = thc_ctx->mmio_addr;
+
+       iowrite32(val, base + reg);
+       return 0;
+}
+
+static const struct regmap_range thc_rw_ranges[] = {
+       regmap_reg_range(0x10, 0x14),
+       regmap_reg_range(0x1000, 0x1320),
+};
+
+static const struct regmap_access_table thc_rw_table = {
+       .yes_ranges = thc_rw_ranges,
+       .n_yes_ranges = ARRAY_SIZE(thc_rw_ranges),
+};
+
+static const struct regmap_config thc_regmap_cfg = {
+       .name = "thc_regmap_common",
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .max_register = 0x1320,
+       .reg_read = thc_regmap_read,
+       .reg_write = thc_regmap_write,
+       .cache_type = REGCACHE_NONE,
+       .fast_io = true,
+       .rd_table = &thc_rw_table,
+       .wr_table = &thc_rw_table,
+       .volatile_table = &thc_rw_table,
+};
+
+/**
+ * thc_clear_state - Clear THC hardware state
+ *
+ * @dev: The pointer of THC device structure
+ */
+static void thc_clear_state(const struct thc_device *dev)
+{
+       u32 val;
+
+       /* Clear interrupt cause register */
+       val = THC_M_PRT_ERR_CAUSE_INVLD_DEV_ENTRY |
+             THC_M_PRT_ERR_CAUSE_FRAME_BABBLE_ERR |
+             THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR |
+             THC_M_PRT_ERR_CAUSE_PRD_ENTRY_ERR;
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_ERR_CAUSE_OFFSET, val, val);
+
+       /* Clear interrupt error state */
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET,
+                         THC_M_PRT_READ_DMA_CNTRL_IE_STALL,
+                         THC_M_PRT_READ_DMA_CNTRL_IE_STALL);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET,
+                         THC_M_PRT_READ_DMA_CNTRL_IE_STALL,
+                         THC_M_PRT_READ_DMA_CNTRL_IE_STALL);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET,
+                         THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS,
+                         THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET,
+                         THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS,
+                         THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS);
+
+       val = THC_M_PRT_INT_EN_TXN_ERR_INT_EN |
+             THC_M_PRT_INT_EN_FATAL_ERR_INT_EN |
+             THC_M_PRT_INT_EN_BUF_OVRRUN_ERR_INT_EN;
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_EN_OFFSET, val, val);
+
+       val = THC_M_PRT_SW_SEQ_STS_THC_SS_ERR |
+             THC_M_PRT_SW_SEQ_STS_TSSDONE;
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, val, val);
+
+       /* Clear RxDMA state */
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET,
+                         THC_M_PRT_READ_DMA_CNTRL_IE_EOF, 0);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET,
+                         THC_M_PRT_READ_DMA_CNTRL_IE_EOF, 0);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_1_OFFSET,
+                         THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS,
+                         THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_2_OFFSET,
+                         THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS,
+                         THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_1_OFFSET,
+                         THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS,
+                         THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS);
+
+       /* Clear TxDMA state */
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_DMA_CNTRL_OFFSET,
+                         THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL,
+                         THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL);
+
+       val = THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ERROR_STS |
+             THC_M_PRT_WRITE_INT_STS_THC_WRDMA_IOC_STS |
+             THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS;
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_INT_STS_OFFSET, val, val);
+
+       /* Reset all DMAs count */
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_DB_CNT_1_OFFSET,
+                         THC_M_PRT_DB_CNT_1_THC_M_PRT_DB_CNT_RST,
+                         THC_M_PRT_DB_CNT_1_THC_M_PRT_DB_CNT_RST);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_DEVINT_CNT_OFFSET,
+                         THC_M_PRT_DEVINT_CNT_THC_M_PRT_DEVINT_CNT_RST,
+                         THC_M_PRT_DEVINT_CNT_THC_M_PRT_DEVINT_CNT_RST);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET,
+                         THC_M_PRT_READ_DMA_CNTRL_TPCPR,
+                         THC_M_PRT_READ_DMA_CNTRL_TPCPR);
+
+       /* Reset THC hardware sequence state */
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRAME_DROP_CNT_1_OFFSET,
+                         THC_M_PRT_FRAME_DROP_CNT_1_RFDC,
+                         THC_M_PRT_FRAME_DROP_CNT_1_RFDC);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRAME_DROP_CNT_2_OFFSET,
+                         THC_M_PRT_FRAME_DROP_CNT_2_RFDC,
+                         THC_M_PRT_FRAME_DROP_CNT_2_RFDC);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRM_CNT_1_OFFSET,
+                         THC_M_PRT_FRM_CNT_1_THC_M_PRT_FRM_CNT_RST,
+                         THC_M_PRT_FRM_CNT_1_THC_M_PRT_FRM_CNT_RST);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRM_CNT_2_OFFSET,
+                         THC_M_PRT_FRM_CNT_2_THC_M_PRT_FRM_CNT_RST,
+                         THC_M_PRT_FRM_CNT_2_THC_M_PRT_FRM_CNT_RST);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_RXDMA_PKT_CNT_1_OFFSET,
+                         THC_M_PRT_RXDMA_PKT_CNT_1_THC_M_PRT_RXDMA_PKT_CNT_RST,
+                         THC_M_PRT_RXDMA_PKT_CNT_1_THC_M_PRT_RXDMA_PKT_CNT_RST);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_RXDMA_PKT_CNT_2_OFFSET,
+                         THC_M_PRT_RXDMA_PKT_CNT_2_THC_M_PRT_RXDMA_PKT_CNT_RST,
+                         THC_M_PRT_RXDMA_PKT_CNT_2_THC_M_PRT_RXDMA_PKT_CNT_RST);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_SWINT_CNT_1_OFFSET,
+                         THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST,
+                         THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_SWINT_CNT_1_OFFSET,
+                         THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST,
+                         THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_TX_FRM_CNT_OFFSET,
+                         THC_M_PRT_TX_FRM_CNT_THC_M_PRT_TX_FRM_CNT_RST,
+                         THC_M_PRT_TX_FRM_CNT_THC_M_PRT_TX_FRM_CNT_RST);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_TXDMA_PKT_CNT_OFFSET,
+                         THC_M_PRT_TXDMA_PKT_CNT_THC_M_PRT_TXDMA_PKT_CNT_RST,
+                         THC_M_PRT_TXDMA_PKT_CNT_THC_M_PRT_TXDMA_PKT_CNT_RST);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_UFRM_CNT_1_OFFSET,
+                         THC_M_PRT_UFRM_CNT_1_THC_M_PRT_UFRM_CNT_RST,
+                         THC_M_PRT_UFRM_CNT_1_THC_M_PRT_UFRM_CNT_RST);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_UFRM_CNT_2_OFFSET,
+                         THC_M_PRT_UFRM_CNT_2_THC_M_PRT_UFRM_CNT_RST,
+                         THC_M_PRT_UFRM_CNT_2_THC_M_PRT_UFRM_CNT_RST);
+
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_PRD_EMPTY_CNT_1_OFFSET,
+                         THC_M_PRT_PRD_EMPTY_CNT_1_RPTEC,
+                         THC_M_PRT_PRD_EMPTY_CNT_1_RPTEC);
+       regmap_write_bits(dev->thc_regmap, THC_M_PRT_PRD_EMPTY_CNT_2_OFFSET,
+                         THC_M_PRT_PRD_EMPTY_CNT_2_RPTEC,
+                         THC_M_PRT_PRD_EMPTY_CNT_2_RPTEC);
+}
+
+/**
+ * thc_dev_init - Allocate and initialize the THC device structure
+ *
+ * @device: The pointer of device structure
+ * @mem_addr: The pointer of MMIO memory address
+ *
+ * Return: The thc_device pointer on success, NULL on failed.
+ */
+struct thc_device *thc_dev_init(struct device *device, void __iomem *mem_addr)
+{
+       struct thc_device *thc_dev;
+       int ret;
+
+       thc_dev = devm_kzalloc(device, sizeof(*thc_dev), GFP_KERNEL);
+       if (!thc_dev)
+               return ERR_PTR(-ENOMEM);
+
+       thc_dev->dev = device;
+       thc_dev->mmio_addr = mem_addr;
+       thc_dev->thc_regmap = devm_regmap_init(device, NULL, thc_dev, &thc_regmap_cfg);
+       if (IS_ERR(thc_dev->thc_regmap)) {
+               ret = PTR_ERR(thc_dev->thc_regmap);
+               dev_err_once(device, "Failed to init thc_regmap: %d\n", ret);
+               return ERR_PTR(ret);
+       }
+
+       thc_clear_state(thc_dev);
+
+       return thc_dev;
+}
+EXPORT_SYMBOL_NS_GPL(thc_dev_init, "INTEL_THC");
+
+MODULE_AUTHOR("Xinpeng Sun <xinpeng.sun@intel.com>");
+MODULE_AUTHOR("Even Xu <even.xu@intel.com>");
+
+MODULE_DESCRIPTION("Intel(R) Intel THC Hardware Driver");
+MODULE_LICENSE("GPL");
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
new file mode 100644 (file)
index 0000000..7060f0a
--- /dev/null
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2024 Intel Corporation */
+
+#ifndef _INTEL_THC_DEV_H_
+#define _INTEL_THC_DEV_H_
+
+#include <linux/cdev.h>
+
+#define THC_REGMAP_COMMON_OFFSET  0x10
+#define THC_REGMAP_MMIO_OFFSET    0x1000
+
+/**
+ * struct thc_device - THC private device struct
+ * @thc_regmap: MMIO regmap structure for accessing THC registers
+ * @mmio_addr: MMIO registers address
+ */
+struct thc_device {
+       struct device *dev;
+       struct regmap *thc_regmap;
+       void __iomem *mmio_addr;
+};
+
+struct thc_device *thc_dev_init(struct device *device, void __iomem *mem_addr);
+
+#endif /* _INTEL_THC_DEV_H_ */