From nobody Mon Nov 25 23:41:03 2024 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 24AA01AF0CC; Thu, 24 Oct 2024 08:11:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729757506; cv=none; b=GheAd/bxlo5+RpgzM/cO6NhVMbcR+9J1q/Tlz4+7DqvNVPZPyAJKSMB31OJpDxtT3hP97LEMo3ITyaqDYnUyzRJadclUpIiNCz4DMpZ1mWc+PbklG9zPHzBRDJUWHN/FzpoMJJA0uCfNfeNaCtZjXPsXj4Tls8g+qG/KUGvZE/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729757506; c=relaxed/simple; bh=4JywDxId3HX3vAXei1D5IDhxR6fPqSqyA/D35eb3Zg0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qcP7OTuPGdbq5Tt/ufhqLxb4ZYNaXiGQwre7w74SihfWONJmaHU4midFbG3P99cjiq8Yw5V2BEaRjFzqOnAd7c+KmwQjB3envzXR42IyVqTF3bVb+X1Ucy3VCWi71Bj8hu65IX6sBxzO9v6EMmvvH/7Kv8Q311ks4PvodhfcChE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=hOJXMS+7; arc=none smtp.client-ip=198.175.65.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hOJXMS+7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1729757505; x=1761293505; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4JywDxId3HX3vAXei1D5IDhxR6fPqSqyA/D35eb3Zg0=; b=hOJXMS+7nmFqYwUVC+Ono24Ceohu1fW2t92r56rPikH4aDWrYSFS0h4C t2gKKFLCYzx+WsXLGhAlRRH0N6jcimlxeuYCvmBRV2wJKb9XJMSCdjlLC zTxNtg1q88P7ioRNlYG/V8imkDuylvSKF9kFVSxtWi73V6fDPpNzn+nrl VZhdT1rBcUKcv+TY+uu/G/D/m8KqpNIhwzKEzpMfLRttFPBmcWfJrzCGq ZEI9e+kcyyHnqQZHTEiowiT/u+dtJQxlsHXMFvMxk/4Y8QDoCHZ2mwA0H 0qrFL+8i6I1IsujESj+DcCW6AT2YW3CCOfxmTAQiAwCJ/guX/0ApLigTz g==; X-CSE-ConnectionGUID: Sr6bbuySTTWm2WhH6jxSJg== X-CSE-MsgGUID: qqd1kcSpSkW8II360kHNcg== X-IronPort-AV: E=McAfee;i="6700,10204,11222"; a="29501118" X-IronPort-AV: E=Sophos;i="6.11,199,1725346800"; d="scan'208";a="29501118" Received: from orviesa006.jf.intel.com ([10.64.159.146]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Oct 2024 01:11:44 -0700 X-CSE-ConnectionGUID: cX2NypDYSAWbEmnd2dYGQw== X-CSE-MsgGUID: a+CqFW9ZRie55+Bai6L/Rw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.11,228,1725346800"; d="scan'208";a="80690928" Received: from shsensorbuild.sh.intel.com ([10.239.133.18]) by orviesa006.jf.intel.com with ESMTP; 24 Oct 2024 01:11:40 -0700 From: Even Xu To: jikos@kernel.org, bentiss@kernel.org, corbet@lwn.net Cc: linux-input@vger.kernel.or, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Even Xu , Xinpeng Sun , Rui Zhang , Srinivas Pandruvada Subject: [PATCH v1 17/22] HID: intel-thc-hid: intel-quicki2c: Add THC QuickI2C driver skeleton Date: Thu, 24 Oct 2024 16:10:18 +0800 Message-Id: <20241024081023.1468951-18-even.xu@intel.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20241024081023.1468951-1-even.xu@intel.com> References: <20241024081023.1468951-1-even.xu@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Create intel-quicki2c folder and add Kconfig and Makefile for THC QuickI2C driver. Add basic device structure, definitions and probe/remove functions for QuickI2C driver. Co-developed-by: Xinpeng Sun Signed-off-by: Xinpeng Sun Signed-off-by: Even Xu Tested-by: Rui Zhang Reviewed-by: Srinivas Pandruvada --- drivers/hid/intel-thc-hid/Kconfig | 11 + drivers/hid/intel-thc-hid/Makefile | 3 + .../intel-quicki2c/pci-quicki2c.c | 268 ++++++++++++++++++ .../intel-quicki2c/quicki2c-dev.h | 44 +++ 4 files changed, 326 insertions(+) create mode 100644 drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c create mode 100644 drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h diff --git a/drivers/hid/intel-thc-hid/Kconfig b/drivers/hid/intel-thc-hid/= Kconfig index 0d0a3877eeb0..275e42a4f7a1 100644 --- a/drivers/hid/intel-thc-hid/Kconfig +++ b/drivers/hid/intel-thc-hid/Kconfig @@ -28,4 +28,15 @@ config INTEL_QUICKSPI =20 Say Y/M here if you want to support Intel QuickSPI. If unsure, say N. =20 +config INTEL_QUICKI2C + tristate "Intel QuickI2C driver based on Intel Touch Host Controller" + depends on INTEL_THC_HID + help + Intel QuickI2C, uses Touch Host Controller (THC) hardware, implements + HIDI2C (HID over I2C) protocol. It configures THC to work at I2C + mode, and controls THC HW sequencer to accelerate HIDI2C transcation + flow. + + Say Y/M here if you want to support Intel QuickI2C. If unsure, say N. + endmenu diff --git a/drivers/hid/intel-thc-hid/Makefile b/drivers/hid/intel-thc-hid= /Makefile index 2dba4db70c33..4d4f02e1c415 100644 --- a/drivers/hid/intel-thc-hid/Makefile +++ b/drivers/hid/intel-thc-hid/Makefile @@ -14,4 +14,7 @@ intel-quickspi-objs +=3D intel-quickspi/pci-quickspi.o intel-quickspi-objs +=3D intel-quickspi/quickspi-hid.o intel-quickspi-objs +=3D intel-quickspi/quickspi-protocol.o =20 +obj-$(CONFIG_INTEL_QUICKI2C) +=3D intel-quicki2c.o +intel-quicki2c-objs +=3D intel-quicki2c/pci-quicki2c.o + ccflags-y +=3D -I $(src)/intel-thc diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c b/driv= ers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c new file mode 100644 index 000000000000..9daa0ae2055e --- /dev/null +++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2024 Intel Corporation */ + +#include +#include +#include +#include +#include +#include + +#include "intel-thc-dev.h" + +#include "quicki2c-dev.h" + +/** + * quicki2c_irq_quick_handler - The ISR of the quicki2c driver + * + * @irq: The irq number + * @dev_id: pointer to the device structure + * + * Return: IRQ_WAKE_THREAD if further process needed. + */ +static irqreturn_t quicki2c_irq_quick_handler(int irq, void *dev_id) +{ + struct quicki2c_device *qcdev =3D dev_id; + + if (qcdev->state =3D=3D QUICKI2C_DISABLED) + return IRQ_HANDLED; + + /* Disable THC interrupt before current interrupt be handled */ + thc_interrupt_enable(qcdev->thc_hw, false); + + return IRQ_WAKE_THREAD; +} + +/** + * quicki2c_irq_thread_handler - IRQ thread handler of quicki2c driver + * + * @irq: The IRQ number + * @dev_id: pointer to the quicki2c device structure + * + * Return: IRQ_HANDLED to finish this handler. + */ +static irqreturn_t quicki2c_irq_thread_handler(int irq, void *dev_id) +{ + struct quicki2c_device *qcdev =3D dev_id; + int int_mask; + + if (qcdev->state =3D=3D QUICKI2C_DISABLED) + return IRQ_HANDLED; + + int_mask =3D thc_interrupt_handler(qcdev->thc_hw); + + thc_interrupt_enable(qcdev->thc_hw, true); + + return IRQ_HANDLED; +} + +/** + * quicki2c_dev_init - Initialize quicki2c device + * + * @pdev: pointer to the thc pci device + * @mem_addr: The pointer of MMIO memory address + * + * Alloc quicki2c device structure and initialized THC device, + * then configure THC to HIDI2C mode. + * + * If success, enable THC hardware interrupt. + * + * Return: pointer to the quicki2c device structure if success + * or NULL on failed. + */ +static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, voi= d __iomem *mem_addr) +{ + struct device *dev =3D &pdev->dev; + struct quicki2c_device *qcdev; + int ret; + + qcdev =3D devm_kzalloc(dev, sizeof(struct quicki2c_device), GFP_KERNEL); + if (!qcdev) + return ERR_PTR(-ENOMEM); + + qcdev->pdev =3D pdev; + qcdev->dev =3D dev; + qcdev->mem_addr =3D mem_addr; + + /* thc hw init */ + qcdev->thc_hw =3D thc_dev_init(qcdev->dev, qcdev->mem_addr); + if (IS_ERR(qcdev->thc_hw)) { + ret =3D PTR_ERR(qcdev->thc_hw); + dev_err_once(dev, "Failed to initialize THC device context, ret =3D %d.\= n", ret); + return ERR_PTR(ret); + } + + ret =3D thc_port_select(qcdev->thc_hw, THC_PORT_TYPE_I2C); + if (ret) { + dev_err_once(dev, "Failed to select THC port, ret =3D %d.\n", ret); + return ERR_PTR(ret); + } + + thc_interrupt_config(qcdev->thc_hw); + + thc_interrupt_enable(qcdev->thc_hw, true); + + return qcdev; +} + +/** + * quicki2c_dev_deinit - De-initialize quicki2c device + * + * @qcdev: pointer to the quicki2c device structure + * + * Disable THC interrupt and deinitilize THC. + */ +static void quicki2c_dev_deinit(struct quicki2c_device *qcdev) +{ + thc_interrupt_enable(qcdev->thc_hw, false); +} + +/* + * quicki2c_probe: Quicki2c driver probe function + * + * @pdev: point to pci device + * @id: point to pci_device_id structure + * + * Return 0 if success or error code on failed. + */ +static int quicki2c_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct quicki2c_device *qcdev; + void __iomem *mem_addr; + int ret; + + ret =3D pcim_enable_device(pdev); + if (ret) { + dev_err_once(&pdev->dev, "Failed to enable PCI device, ret =3D %d.\n", r= et); + return ret; + } + + pci_set_master(pdev); + + ret =3D pcim_iomap_regions(pdev, BIT(0), KBUILD_MODNAME); + if (ret) { + dev_err_once(&pdev->dev, "Failed to get PCI regions, ret =3D %d.\n", ret= ); + goto disable_pci_device; + } + + mem_addr =3D pcim_iomap_table(pdev)[0]; + + ret =3D dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (ret) { + ret =3D dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err_once(&pdev->dev, "No usable DMA configuration %d\n", ret); + goto unmap_io_region; + } + } + + ret =3D pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); + if (ret < 0) { + dev_err_once(&pdev->dev, + "Failed to allocate IRQ vectors. ret =3D %d\n", ret); + goto unmap_io_region; + } + + pdev->irq =3D pci_irq_vector(pdev, 0); + + qcdev =3D quicki2c_dev_init(pdev, mem_addr); + if (IS_ERR(qcdev)) { + dev_err_once(&pdev->dev, "QuickI2C device init failed\n"); + ret =3D PTR_ERR(qcdev); + goto unmap_io_region; + } + + pci_set_drvdata(pdev, qcdev); + + ret =3D devm_request_threaded_irq(&pdev->dev, pdev->irq, + quicki2c_irq_quick_handler, + quicki2c_irq_thread_handler, + IRQF_ONESHOT, KBUILD_MODNAME, + qcdev); + if (ret) { + dev_err_once(&pdev->dev, + "Failed to request threaded IRQ, irq =3D %d.\n", pdev->irq); + goto dev_deinit; + } + + return 0; + +dev_deinit: + quicki2c_dev_deinit(qcdev); +unmap_io_region: + pcim_iounmap_regions(pdev, BIT(0)); +disable_pci_device: + pci_clear_master(pdev); + pci_disable_device(pdev); + + return ret; +} + +/** + * quicki2c_remove - Device Removal Routine + * + * @pdev: PCI device structure + * + * This is called by the PCI subsystem to alert the driver + * that it should release a PCI device. + */ +static void quicki2c_remove(struct pci_dev *pdev) +{ + struct quicki2c_device *qcdev; + + qcdev =3D pci_get_drvdata(pdev); + if (!qcdev) + return; + + quicki2c_dev_deinit(qcdev); + + pcim_iounmap_regions(pdev, BIT(0)); + pci_clear_master(pdev); + pci_disable_device(pdev); +} + +/** + * quicki2c_shutdown - Device Shutdown Routine + * + * @pdev: PCI device structure + * + * This is called from the reboot notifier + * it's a simplified version of remove so we go down + * faster. + */ +static void quicki2c_shutdown(struct pci_dev *pdev) +{ + struct quicki2c_device *qcdev; + + qcdev =3D pci_get_drvdata(pdev); + if (!qcdev) + return; + + quicki2c_dev_deinit(qcdev); +} + +static const struct pci_device_id quicki2c_pci_tbl[] =3D { + {PCI_VDEVICE(INTEL, THC_LNL_DEVICE_ID_I2C_PORT1), }, + {PCI_VDEVICE(INTEL, THC_LNL_DEVICE_ID_I2C_PORT2), }, + {} +}; +MODULE_DEVICE_TABLE(pci, quicki2c_pci_tbl); + +static struct pci_driver quicki2c_driver =3D { + .name =3D KBUILD_MODNAME, + .id_table =3D quicki2c_pci_tbl, + .probe =3D quicki2c_probe, + .remove =3D quicki2c_remove, + .shutdown =3D quicki2c_shutdown, + .driver.probe_type =3D PROBE_PREFER_ASYNCHRONOUS, +}; + +module_pci_driver(quicki2c_driver); + +MODULE_AUTHOR("Xinpeng Sun "); +MODULE_AUTHOR("Even Xu "); + +MODULE_DESCRIPTION("Intel(R) QuickI2C Driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(INTEL_THC); diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h b/driv= ers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h new file mode 100644 index 000000000000..370faad744f5 --- /dev/null +++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2024 Intel Corporation */ + +#ifndef _QUICKI2C_DEV_H_ +#define _QUICKI2C_DEV_H_ + +#define THC_LNL_DEVICE_ID_I2C_PORT1 0xA848 +#define THC_LNL_DEVICE_ID_I2C_PORT2 0xA84A + +/* Packet size value, the unit is 16 bytes */ +#define MAX_PACKET_SIZE_VALUE_LNL 256 + +enum quicki2c_dev_state { + QUICKI2C_NONE, + QUICKI2C_RESETING, + QUICKI2C_RESETED, + QUICKI2C_INITED, + QUICKI2C_ENABLED, + QUICKI2C_DISABLED, +}; + +struct device; +struct pci_dev; +struct thc_device; + +/** + * struct quicki2c_device - THC QuickI2C device struct + * @dev: point to kernel device + * @pdev: point to PCI device + * @thc_hw: point to THC device + * @driver_data: point to quicki2c specific driver data + * @state: THC I2C device state + * @mem_addr: MMIO memory address + */ +struct quicki2c_device { + struct device *dev; + struct pci_dev *pdev; + struct thc_device *thc_hw; + enum quicki2c_dev_state state; + + void __iomem *mem_addr; +}; + +#endif /* _QUICKI2C_DEV_H_ */ --=20 2.40.1