Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,231 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2024 Intel Corporation */
#ifndef _QUICKI2C_DEV_H_
#define _QUICKI2C_DEV_H_
#include <linux/hid-over-i2c.h>
#include <linux/workqueue.h>
#define PCI_DEVICE_ID_INTEL_THC_LNL_DEVICE_ID_I2C_PORT1 0xA848
#define PCI_DEVICE_ID_INTEL_THC_LNL_DEVICE_ID_I2C_PORT2 0xA84A
#define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_I2C_PORT1 0xE348
#define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_I2C_PORT2 0xE34A
#define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_I2C_PORT1 0xE448
#define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_I2C_PORT2 0xE44A
#define PCI_DEVICE_ID_INTEL_THC_WCL_DEVICE_ID_I2C_PORT1 0x4D48
#define PCI_DEVICE_ID_INTEL_THC_WCL_DEVICE_ID_I2C_PORT2 0x4D4A
#define PCI_DEVICE_ID_INTEL_THC_NVL_H_DEVICE_ID_I2C_PORT1 0xD348
#define PCI_DEVICE_ID_INTEL_THC_NVL_H_DEVICE_ID_I2C_PORT2 0xD34A
/* Packet size value, the unit is 16 bytes */
#define MAX_PACKET_SIZE_VALUE_LNL 256
/* HIDI2C special ACPI parameters DSD name */
#define QUICKI2C_ACPI_METHOD_NAME_ICRS "ICRS"
#define QUICKI2C_ACPI_METHOD_NAME_ISUB "ISUB"
/* HIDI2C special ACPI parameters DSM methods */
#define QUICKI2C_ACPI_REVISION_NUM 1
#define QUICKI2C_ACPI_FUNC_NUM_HID_DESC_ADDR 1
#define QUICKI2C_ACPI_FUNC_NUM_ACTIVE_LTR_VAL 1
#define QUICKI2C_ACPI_FUNC_NUM_LP_LTR_VAL 2
#define QUICKI2C_SUBIP_STANDARD_MODE_MAX_SPEED 100000
#define QUICKI2C_SUBIP_FAST_MODE_MAX_SPEED 400000
#define QUICKI2C_SUBIP_FASTPLUS_MODE_MAX_SPEED 1000000
#define QUICKI2C_SUBIP_HIGH_SPEED_MODE_MAX_SPEED 3400000
#define QUICKI2C_DEFAULT_ACTIVE_LTR_VALUE 5
#define QUICKI2C_DEFAULT_LP_LTR_VALUE 500
#define QUICKI2C_RPM_TIMEOUT_MS 500
/* PTL Max packet size detection capability is 255 Bytes */
#define MAX_RX_DETECT_SIZE_PTL 255
/* NVL Max packet size detection capability is 64K Bytes */
#define MAX_RX_DETECT_SIZE_NVL 65535
/* Max interrupt delay capability is 2.56ms */
#define MAX_RX_INTERRUPT_DELAY 256
/* Default interrupt delay is 1ms, suitable for most devices */
#define DEFAULT_INTERRUPT_DELAY_US (1 * USEC_PER_MSEC)
/*
* THC uses runtime auto suspend to dynamically switch between THC active LTR
* and low power LTR to save CPU power.
* Default value is 5000ms, that means if no touch event in this time, THC will
* change to low power LTR mode.
*/
#define DEFAULT_AUTO_SUSPEND_DELAY_MS 5000
enum quicki2c_dev_state {
QUICKI2C_NONE,
QUICKI2C_RESETING,
QUICKI2C_RESETED,
QUICKI2C_INITED,
QUICKI2C_ENABLED,
QUICKI2C_DISABLED,
};
enum {
HIDI2C_ADDRESSING_MODE_7BIT,
HIDI2C_ADDRESSING_MODE_10BIT,
};
/**
* struct quicki2c_subip_acpi_parameter - QuickI2C ACPI DSD parameters
* @device_address: I2C device slave address
* @connection_speed: I2C device expected connection speed
* @addressing_mode: I2C device slave address mode, 7bit or 10bit
*
* Those properties get from QUICKI2C_ACPI_METHOD_NAME_ICRS method, used for
* Bus parameter.
*/
struct quicki2c_subip_acpi_parameter {
u16 device_address;
u64 connection_speed;
u8 addressing_mode;
u8 reserved;
} __packed;
/**
* struct quicki2c_subip_acpi_config - QuickI2C ACPI DSD parameters
* @SMHX: Standard Mode (100 kbit/s) Serial Clock Line HIGH Period
* @SMLX: Standard Mode (100 kbit/s) Serial Clock Line LOW Period
* @SMTD: Standard Mode (100 kbit/s) Serial Data Line Transmit Hold Period
* @SMRD: Standard Mode (100 kbit/s) Serial Data Receive Hold Period
* @FMHX: Fast Mode (400 kbit/s) Serial Clock Line HIGH Period
* @FMLX: Fast Mode (400 kbit/s) Serial Clock Line LOW Period
* @FMTD: Fast Mode (400 kbit/s) Serial Data Line Transmit Hold Period
* @FMRD: Fast Mode (400 kbit/s) Serial Data Line Receive Hold Period
* @FMSL: Maximum length (in ic_clk_cycles) of suppressed spikes
* in Standard Mode, Fast Mode and Fast Mode Plus
* @FPHX: Fast Mode Plus (1Mbit/sec) Serial Clock Line HIGH Period
* @FPLX: Fast Mode Plus (1Mbit/sec) Serial Clock Line LOW Period
* @FPTD: Fast Mode Plus (1Mbit/sec) Serial Data Line Transmit HOLD Period
* @FPRD: Fast Mode Plus (1Mbit/sec) Serial Data Line Receive HOLD Period
* @HMHX: High Speed Mode Plus (3.4Mbits/sec) Serial Clock Line HIGH Period
* @HMLX: High Speed Mode Plus (3.4Mbits/sec) Serial Clock Line LOW Period
* @HMTD: High Speed Mode Plus (3.4Mbits/sec) Serial Data Line Transmit HOLD Period
* @HMRD: High Speed Mode Plus (3.4Mbits/sec) Serial Data Line Receive HOLD Period
* @HMSL: Maximum length (in ic_clk_cycles) of suppressed spikes in High Speed Mode
* @FSEN: Maximum Frame Size Feature Enable Control
* @FSVL: Maximum Frame Size Value (unit in Bytes)
* @INDE: Interrupt Delay Feature Enable Control
* @INDV: Interrupt Delay Value (unit in 10 us)
*
* Those properties get from QUICKI2C_ACPI_METHOD_NAME_ISUB method, used for
* I2C timing configure.
*/
struct quicki2c_subip_acpi_config {
u64 SMHX;
u64 SMLX;
u64 SMTD;
u64 SMRD;
u64 FMHX;
u64 FMLX;
u64 FMTD;
u64 FMRD;
u64 FMSL;
u64 FPHX;
u64 FPLX;
u64 FPTD;
u64 FPRD;
u64 HMHX;
u64 HMLX;
u64 HMTD;
u64 HMRD;
u64 HMSL;
u64 FSEN;
u64 FSVL;
u64 INDE;
u64 INDV;
u8 reserved;
};
/**
* struct quicki2c_ddata - Driver specific data for quicki2c device
* @max_detect_size: Identify max packet size detect for rx
* @interrupt_delay: Identify max interrupt detect delay for rx
*/
struct quicki2c_ddata {
u32 max_detect_size;
u32 max_interrupt_delay;
};
struct device;
struct pci_dev;
struct thc_device;
struct hid_device;
struct acpi_device;
/**
* struct quicki2c_device - THC QuickI2C device struct
* @dev: Point to kernel device
* @pdev: Point to PCI device
* @thc_hw: Point to THC device
* @hid_dev: Point to HID device
* @acpi_dev: Point to ACPI device
* @ddata: Point to QuickI2C platform specific driver data
* @state: THC I2C device state
* @mem_addr: MMIO memory address
* @dev_desc: Device descriptor for HIDI2C protocol
* @i2c_slave_addr: HIDI2C device slave address
* @hid_desc_addr: Register address for retrieve HID device descriptor
* @active_ltr_val: THC active LTR value
* @low_power_ltr_val: THC low power LTR value
* @i2c_speed_mode: 0 - standard mode, 1 - fast mode, 2 - fast mode plus
* @i2c_clock_hcnt: I2C CLK high period time (unit in cycle count)
* @i2c_clock_lcnt: I2C CLK low period time (unit in cycle count)
* @report_descriptor: Store a copy of device report descriptor
* @input_buf: Store a copy of latest input report data
* @report_buf: Store a copy of latest input/output report packet from set/get feature
* @report_len: The length of input/output report packet
* @reset_ack_wq: Workqueue for waiting reset response from device
* @reset_ack: Indicate reset response received or not
* @i2c_max_frame_size_enable: Indicate max frame size feature enabled or not
* @i2c_max_frame_size: Max RX frame size (unit in Bytes)
* @i2c_int_delay_enable: Indicate interrupt delay feature enabled or not
* @i2c_int_delay: Interrupt detection delay value (unit in 10 us)
*/
struct quicki2c_device {
struct device *dev;
struct pci_dev *pdev;
struct thc_device *thc_hw;
struct hid_device *hid_dev;
struct acpi_device *acpi_dev;
const struct quicki2c_ddata *ddata;
enum quicki2c_dev_state state;
void __iomem *mem_addr;
struct hidi2c_dev_descriptor dev_desc;
u8 i2c_slave_addr;
u16 hid_desc_addr;
u32 active_ltr_val;
u32 low_power_ltr_val;
u32 i2c_speed_mode;
u32 i2c_clock_hcnt;
u32 i2c_clock_lcnt;
u8 *report_descriptor;
u8 *input_buf;
u8 *report_buf;
size_t report_len;
wait_queue_head_t reset_ack_wq;
bool reset_ack;
u32 i2c_max_frame_size_enable;
u32 i2c_max_frame_size;
u32 i2c_int_delay_enable;
u32 i2c_int_delay;
};
#endif /* _QUICKI2C_DEV_H_ */
@@ -0,0 +1,174 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2024 Intel Corporation */
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/pm_runtime.h>
#include "quicki2c-dev.h"
#include "quicki2c-hid.h"
#include "quicki2c-protocol.h"
/**
* quicki2c_hid_parse() - HID core parse() callback
*
* @hid: HID device instance
*
* This function gets called during call to hid_add_device
*
* Return: 0 on success and non zero on error.
*/
static int quicki2c_hid_parse(struct hid_device *hid)
{
struct quicki2c_device *qcdev = hid->driver_data;
if (qcdev->report_descriptor)
return hid_parse_report(hid, qcdev->report_descriptor,
le16_to_cpu(qcdev->dev_desc.report_desc_len));
dev_err_once(qcdev->dev, "invalid report descriptor\n");
return -EINVAL;
}
static int quicki2c_hid_start(struct hid_device *hid)
{
return 0;
}
static void quicki2c_hid_stop(struct hid_device *hid)
{
}
static int quicki2c_hid_open(struct hid_device *hid)
{
return 0;
}
static void quicki2c_hid_close(struct hid_device *hid)
{
}
static int quicki2c_hid_raw_request(struct hid_device *hid,
unsigned char reportnum,
__u8 *buf, size_t len,
unsigned char rtype, int reqtype)
{
struct quicki2c_device *qcdev = hid->driver_data;
int ret = 0;
ret = pm_runtime_resume_and_get(qcdev->dev);
if (ret)
return ret;
switch (reqtype) {
case HID_REQ_GET_REPORT:
ret = quicki2c_get_report(qcdev, rtype, reportnum, buf, len);
break;
case HID_REQ_SET_REPORT:
ret = quicki2c_set_report(qcdev, rtype, reportnum, buf, len);
break;
default:
dev_err(qcdev->dev, "Not supported request type %d\n", reqtype);
break;
}
pm_runtime_put_autosuspend(qcdev->dev);
return ret;
}
static int quicki2c_hid_power(struct hid_device *hid, int lvl)
{
return 0;
}
static int quicki2c_hid_output_report(struct hid_device *hid, u8 *buf, size_t count)
{
struct quicki2c_device *qcdev = hid->driver_data;
return quicki2c_output_report(qcdev, buf, count);
}
static struct hid_ll_driver quicki2c_hid_ll_driver = {
.parse = quicki2c_hid_parse,
.start = quicki2c_hid_start,
.stop = quicki2c_hid_stop,
.open = quicki2c_hid_open,
.close = quicki2c_hid_close,
.power = quicki2c_hid_power,
.raw_request = quicki2c_hid_raw_request,
.output_report = quicki2c_hid_output_report,
};
/**
* quicki2c_hid_probe() - Register HID low level driver
*
* @qcdev: point to quicki2c device
*
* This function is used to allocate and add HID device.
*
* Return: 0 on success, non zero on error.
*/
int quicki2c_hid_probe(struct quicki2c_device *qcdev)
{
struct hid_device *hid;
int ret;
hid = hid_allocate_device();
if (IS_ERR(hid))
return PTR_ERR(hid);
hid->ll_driver = &quicki2c_hid_ll_driver;
hid->bus = BUS_PCI;
hid->dev.parent = qcdev->dev;
hid->driver_data = qcdev;
hid->version = le16_to_cpu(qcdev->dev_desc.version_id);
hid->vendor = le16_to_cpu(qcdev->dev_desc.vendor_id);
hid->product = le16_to_cpu(qcdev->dev_desc.product_id);
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid",
hid->vendor, hid->product);
strscpy(hid->phys, dev_name(qcdev->dev), sizeof(hid->phys));
ret = hid_add_device(hid);
if (ret) {
hid_destroy_device(hid);
return ret;
}
qcdev->hid_dev = hid;
return 0;
}
/**
* quicki2c_hid_remove() - Destroy HID device
*
* @qcdev: point to quicki2c device
*
* Return: 0 on success, non zero on error.
*/
void quicki2c_hid_remove(struct quicki2c_device *qcdev)
{
hid_destroy_device(qcdev->hid_dev);
}
/**
* quicki2c_hid_send_report() - Send HID input report data to HID core
*
* @qcdev: point to quicki2c device
* @data: point to input report data buffer
* @data_len: the length of input report data
*
* Return: 0 on success, non zero on error.
*/
int quicki2c_hid_send_report(struct quicki2c_device *qcdev,
void *data, size_t data_len)
{
int ret;
ret = hid_input_report(qcdev->hid_dev, HID_INPUT_REPORT, data, data_len, 1);
if (ret)
dev_err(qcdev->dev, "Failed to send HID input report, ret = %d.\n", ret);
return ret;
}
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2024 Intel Corporation */
#ifndef _QUICKI2C_HID_H_
#define _QUICKI2C_HID_H_
struct quicki2c_device;
int quicki2c_hid_send_report(struct quicki2c_device *qcdev,
void *data, size_t data_size);
int quicki2c_hid_probe(struct quicki2c_device *qcdev);
void quicki2c_hid_remove(struct quicki2c_device *qcdev);
#endif /* _QUICKI2C_HID_H_ */
@@ -0,0 +1,265 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2024 Intel Corporation */
#include <linux/bitfield.h>
#include <linux/hid.h>
#include <linux/hid-over-i2c.h>
#include <linux/unaligned.h>
#include "intel-thc-dev.h"
#include "intel-thc-dma.h"
#include "quicki2c-dev.h"
#include "quicki2c-hid.h"
#include "quicki2c-protocol.h"
static ssize_t quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, size_t cmd_len,
bool append_data_reg, u8 *data, size_t data_len,
u8 *write_buf, size_t write_buf_len)
{
size_t buf_len, offset = 0;
buf_len = HIDI2C_REG_LEN + cmd_len;
if (append_data_reg)
buf_len += HIDI2C_REG_LEN;
if (data && data_len)
buf_len += data_len + HIDI2C_LENGTH_LEN;
if (buf_len > write_buf_len)
return -EINVAL;
if (cmd_len) {
memcpy(write_buf, &qcdev->dev_desc.cmd_reg, HIDI2C_REG_LEN);
offset += HIDI2C_REG_LEN;
memcpy(write_buf + offset, &cmd, cmd_len);
offset += cmd_len;
if (append_data_reg) {
memcpy(write_buf + offset, &qcdev->dev_desc.data_reg, HIDI2C_REG_LEN);
offset += HIDI2C_REG_LEN;
}
} else {
memcpy(write_buf, &qcdev->dev_desc.output_reg, HIDI2C_REG_LEN);
offset += HIDI2C_REG_LEN;
}
if (data && data_len) {
put_unaligned_le16(data_len + HIDI2C_LENGTH_LEN, write_buf + offset);
offset += HIDI2C_LENGTH_LEN;
memcpy(write_buf + offset, data, data_len);
}
return buf_len;
}
static size_t quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf,
u8 opcode, u8 report_type, u8 report_id)
{
size_t cmd_len;
*cmd_buf = FIELD_PREP(HIDI2C_CMD_OPCODE, opcode) |
FIELD_PREP(HIDI2C_CMD_REPORT_TYPE, report_type);
if (report_id < HIDI2C_CMD_MAX_RI) {
*cmd_buf |= FIELD_PREP(HIDI2C_CMD_REPORT_ID, report_id);
cmd_len = HIDI2C_CMD_LEN;
} else {
*cmd_buf |= FIELD_PREP(HIDI2C_CMD_REPORT_ID, HIDI2C_CMD_MAX_RI) |
FIELD_PREP(HIDI2C_CMD_3RD_BYTE, report_id);
cmd_len = HIDI2C_CMD_LEN_OPT;
}
return cmd_len;
}
static int write_cmd_to_txdma(struct quicki2c_device *qcdev, int opcode,
int report_type, int report_id, u8 *buf, size_t buf_len)
{
size_t cmd_len;
ssize_t len;
u32 cmd;
cmd_len = quicki2c_encode_cmd(qcdev, &cmd, opcode, report_type, report_id);
len = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf,
buf_len, qcdev->report_buf, qcdev->report_len);
if (len < 0)
return len;
return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, len);
}
int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state)
{
return write_cmd_to_txdma(qcdev, HIDI2C_SET_POWER, HIDI2C_RESERVED, power_state, NULL, 0);
}
int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev)
{
u32 read_len = 0;
int ret;
ret = thc_tic_pio_write_and_read(qcdev->thc_hw, qcdev->hid_desc_addr,
HIDI2C_REG_LEN, NULL, HIDI2C_DEV_DESC_LEN,
&read_len, (u32 *)&qcdev->dev_desc);
if (ret || HIDI2C_DEV_DESC_LEN != read_len) {
dev_err_once(qcdev->dev, "Get device descriptor failed, ret %d, read len %u\n",
ret, read_len);
return -EIO;
}
if (le16_to_cpu(qcdev->dev_desc.bcd_ver) != HIDI2C_HID_DESC_BCDVERSION)
return -EOPNOTSUPP;
return 0;
}
int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev)
{
u16 desc_reg = le16_to_cpu(qcdev->dev_desc.report_desc_reg);
size_t read_len = le16_to_cpu(qcdev->dev_desc.report_desc_len);
u32 prd_len = read_len;
return thc_swdma_read(qcdev->thc_hw, (u8 *)&desc_reg, HIDI2C_REG_LEN,
&prd_len, qcdev->report_descriptor, &read_len);
}
int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
unsigned int reportnum, void *buf, size_t buf_len)
{
struct hidi2c_report_packet *rpt;
size_t cmd_len, read_len = 0;
int rep_type, ret;
ssize_t len;
u32 cmd;
if (report_type == HID_INPUT_REPORT) {
rep_type = HIDI2C_INPUT;
} else if (report_type == HID_FEATURE_REPORT) {
rep_type = HIDI2C_FEATURE;
} else {
dev_err(qcdev->dev, "Unsupported report type for GET REPORT: %d\n", report_type);
return -EINVAL;
}
cmd_len = quicki2c_encode_cmd(qcdev, &cmd, HIDI2C_GET_REPORT, rep_type, reportnum);
len = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0,
qcdev->report_buf, qcdev->report_len);
if (len < 0)
return len;
rpt = (struct hidi2c_report_packet *)qcdev->input_buf;
ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, len, NULL, rpt, &read_len);
if (ret) {
dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %zu)\n",
ret, read_len, buf_len);
return ret;
}
if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len || rpt->data[0] != reportnum) {
dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %zu) report id (%d vs %d)\n",
le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum);
return -EINVAL;
}
memcpy(buf, rpt->data, buf_len);
return buf_len;
}
int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
unsigned int reportnum, void *buf, size_t buf_len)
{
int rep_type;
int ret;
if (report_type == HID_OUTPUT_REPORT) {
rep_type = HIDI2C_OUTPUT;
} else if (report_type == HID_FEATURE_REPORT) {
rep_type = HIDI2C_FEATURE;
} else {
dev_err(qcdev->dev, "Unsupported report type for SET REPORT: %d\n", report_type);
return -EINVAL;
}
ret = write_cmd_to_txdma(qcdev, HIDI2C_SET_REPORT, rep_type, reportnum, buf, buf_len);
if (ret) {
dev_err_once(qcdev->dev, "Set Report failed, ret %d\n", ret);
return ret;
}
return buf_len;
}
int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len)
{
ssize_t len;
int ret;
len = quicki2c_init_write_buf(qcdev, 0, 0, false, buf, buf_len,
qcdev->report_buf, qcdev->report_len);
if (len < 0)
return -EINVAL;
ret = thc_dma_write(qcdev->thc_hw, qcdev->report_buf, len);
if (ret) {
dev_err(qcdev->dev, "Output Report failed, ret %d\n", ret);
return ret;
}
return buf_len;
}
#define HIDI2C_RESET_TIMEOUT 5
int quicki2c_reset(struct quicki2c_device *qcdev)
{
u16 input_reg = le16_to_cpu(qcdev->dev_desc.input_reg);
size_t read_len = HIDI2C_LENGTH_LEN;
u32 prd_len = read_len;
int ret;
qcdev->reset_ack = false;
qcdev->state = QUICKI2C_RESETING;
ret = write_cmd_to_txdma(qcdev, HIDI2C_RESET, HIDI2C_RESERVED, 0, NULL, 0);
if (ret) {
dev_err_once(qcdev->dev, "Send reset command failed, ret %d\n", ret);
return ret;
}
ret = wait_event_interruptible_timeout(qcdev->reset_ack_wq, qcdev->reset_ack,
HIDI2C_RESET_TIMEOUT * HZ);
if (qcdev->reset_ack)
return 0;
/*
* Manually read reset response if it wasn't received, in case reset interrupt
* was missed by touch device or THC hardware.
*/
ret = thc_tic_pio_read(qcdev->thc_hw, input_reg, read_len, &prd_len,
(u32 *)qcdev->input_buf);
if (ret) {
dev_err_once(qcdev->dev, "Read Reset Response failed, ret %d\n", ret);
return ret;
}
/*
* Check response packet length, it's first 16 bits of packet.
* If response packet length is zero, it's reset response, otherwise not.
*/
if (get_unaligned_le16(qcdev->input_buf)) {
dev_err_once(qcdev->dev,
"Wait reset response timed out ret:%d timeout:%ds\n",
ret, HIDI2C_RESET_TIMEOUT);
return -ETIMEDOUT;
}
qcdev->reset_ack = true;
return 0;
}
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2024 Intel Corporation */
#ifndef _QUICKI2C_PROTOCOL_H_
#define _QUICKI2C_PROTOCOL_H_
#include <linux/hid-over-i2c.h>
struct quicki2c_device;
int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state);
int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
unsigned int reportnum, void *buf, size_t buf_len);
int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
unsigned int reportnum, void *buf, size_t buf_len);
int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len);
int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev);
int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev);
int quicki2c_reset(struct quicki2c_device *qcdev);
#endif /* _QUICKI2C_PROTOCOL_H_ */