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 #include <linux/unaligned.h>
8
9 #include "intel-thc-dev.h"
10 #include "intel-thc-dma.h"
11
12 #include "quicki2c-dev.h"
13 #include "quicki2c-hid.h"
14 #include "quicki2c-protocol.h"
15
quicki2c_init_write_buf(struct quicki2c_device * qcdev,u32 cmd,int cmd_len,bool append_data_reg,u8 * data,int data_len,u8 * write_buf,int write_buf_len)16 static int quicki2c_init_write_buf(struct quicki2c_device *qcdev, u32 cmd, int cmd_len,
17 bool append_data_reg, u8 *data, int data_len,
18 u8 *write_buf, int write_buf_len)
19 {
20 int buf_len, offset = 0;
21
22 buf_len = HIDI2C_REG_LEN + cmd_len;
23
24 if (append_data_reg)
25 buf_len += HIDI2C_REG_LEN;
26
27 if (data && data_len)
28 buf_len += data_len + HIDI2C_LENGTH_LEN;
29
30 if (buf_len > write_buf_len)
31 return -EINVAL;
32
33 memcpy(write_buf, &qcdev->dev_desc.cmd_reg, HIDI2C_REG_LEN);
34 offset += HIDI2C_REG_LEN;
35 memcpy(write_buf + offset, &cmd, cmd_len);
36 offset += cmd_len;
37
38 if (append_data_reg) {
39 memcpy(write_buf + offset, &qcdev->dev_desc.data_reg, HIDI2C_REG_LEN);
40 offset += HIDI2C_REG_LEN;
41 }
42
43 if (data && data_len) {
44 __le16 len = cpu_to_le16(data_len + HIDI2C_LENGTH_LEN);
45
46 memcpy(write_buf + offset, &len, HIDI2C_LENGTH_LEN);
47 offset += HIDI2C_LENGTH_LEN;
48 memcpy(write_buf + offset, data, data_len);
49 }
50
51 return buf_len;
52 }
53
quicki2c_encode_cmd(struct quicki2c_device * qcdev,u32 * cmd_buf,u8 opcode,u8 report_type,u8 report_id)54 static int quicki2c_encode_cmd(struct quicki2c_device *qcdev, u32 *cmd_buf,
55 u8 opcode, u8 report_type, u8 report_id)
56 {
57 int cmd_len;
58
59 *cmd_buf = FIELD_PREP(HIDI2C_CMD_OPCODE, opcode) |
60 FIELD_PREP(HIDI2C_CMD_REPORT_TYPE, report_type);
61
62 if (report_id < HIDI2C_CMD_MAX_RI) {
63 *cmd_buf |= FIELD_PREP(HIDI2C_CMD_REPORT_ID, report_id);
64 cmd_len = HIDI2C_CMD_LEN;
65 } else {
66 *cmd_buf |= FIELD_PREP(HIDI2C_CMD_REPORT_ID, HIDI2C_CMD_MAX_RI) |
67 FIELD_PREP(HIDI2C_CMD_3RD_BYTE, report_id);
68 cmd_len = HIDI2C_CMD_LEN_OPT;
69 }
70
71 return cmd_len;
72 }
73
write_cmd_to_txdma(struct quicki2c_device * qcdev,int opcode,int report_type,int report_id,u8 * buf,int buf_len)74 static int write_cmd_to_txdma(struct quicki2c_device *qcdev, int opcode,
75 int report_type, int report_id, u8 *buf, int buf_len)
76 {
77 size_t write_buf_len;
78 int cmd_len, ret;
79 u32 cmd;
80
81 cmd_len = quicki2c_encode_cmd(qcdev, &cmd, opcode, report_type, report_id);
82
83 ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, buf ? true : false, buf,
84 buf_len, qcdev->report_buf, qcdev->report_len);
85 if (ret < 0)
86 return ret;
87
88 write_buf_len = ret;
89
90 return thc_dma_write(qcdev->thc_hw, qcdev->report_buf, write_buf_len);
91 }
92
quicki2c_set_power(struct quicki2c_device * qcdev,enum hidi2c_power_state power_state)93 int quicki2c_set_power(struct quicki2c_device *qcdev, enum hidi2c_power_state power_state)
94 {
95 return write_cmd_to_txdma(qcdev, HIDI2C_SET_POWER, HIDI2C_RESERVED, power_state, NULL, 0);
96 }
97
quicki2c_get_device_descriptor(struct quicki2c_device * qcdev)98 int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev)
99 {
100 u32 read_len = 0;
101 int ret;
102
103 ret = thc_tic_pio_write_and_read(qcdev->thc_hw, qcdev->hid_desc_addr,
104 HIDI2C_REG_LEN, NULL, HIDI2C_DEV_DESC_LEN,
105 &read_len, (u32 *)&qcdev->dev_desc);
106 if (ret || HIDI2C_DEV_DESC_LEN != read_len) {
107 dev_err_once(qcdev->dev, "Get device descriptor failed, ret %d, read len %u\n",
108 ret, read_len);
109 return -EIO;
110 }
111
112 if (le16_to_cpu(qcdev->dev_desc.bcd_ver) != HIDI2C_HID_DESC_BCDVERSION)
113 return -EOPNOTSUPP;
114
115 return 0;
116 }
117
quicki2c_get_report_descriptor(struct quicki2c_device * qcdev)118 int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev)
119 {
120 u16 desc_reg = le16_to_cpu(qcdev->dev_desc.report_desc_reg);
121 size_t read_len = le16_to_cpu(qcdev->dev_desc.report_desc_len);
122 u32 prd_len = read_len;
123
124 return thc_swdma_read(qcdev->thc_hw, (u8 *)&desc_reg, HIDI2C_REG_LEN,
125 &prd_len, qcdev->report_descriptor, &read_len);
126 }
127
quicki2c_get_report(struct quicki2c_device * qcdev,u8 report_type,unsigned int reportnum,void * buf,u32 buf_len)128 int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
129 unsigned int reportnum, void *buf, u32 buf_len)
130 {
131 struct hidi2c_report_packet *rpt;
132 size_t write_buf_len, read_len = 0;
133 int cmd_len, rep_type;
134 u32 cmd;
135 int ret;
136
137 if (report_type == HID_INPUT_REPORT) {
138 rep_type = HIDI2C_INPUT;
139 } else if (report_type == HID_FEATURE_REPORT) {
140 rep_type = HIDI2C_FEATURE;
141 } else {
142 dev_err(qcdev->dev, "Unsupported report type for GET REPORT: %d\n", report_type);
143 return -EINVAL;
144 }
145
146 cmd_len = quicki2c_encode_cmd(qcdev, &cmd, HIDI2C_GET_REPORT, rep_type, reportnum);
147
148 ret = quicki2c_init_write_buf(qcdev, cmd, cmd_len, true, NULL, 0,
149 qcdev->report_buf, qcdev->report_len);
150 if (ret < 0)
151 return ret;
152
153 write_buf_len = ret;
154
155 rpt = (struct hidi2c_report_packet *)qcdev->input_buf;
156
157 ret = thc_swdma_read(qcdev->thc_hw, qcdev->report_buf, write_buf_len,
158 NULL, rpt, &read_len);
159 if (ret) {
160 dev_err_once(qcdev->dev, "Get report failed, ret %d, read len (%zu vs %d)\n",
161 ret, read_len, buf_len);
162 return ret;
163 }
164
165 if (HIDI2C_DATA_LEN(le16_to_cpu(rpt->len)) != buf_len || rpt->data[0] != reportnum) {
166 dev_err_once(qcdev->dev, "Invalid packet, len (%d vs %d) report id (%d vs %d)\n",
167 le16_to_cpu(rpt->len), buf_len, rpt->data[0], reportnum);
168 return -EINVAL;
169 }
170
171 memcpy(buf, rpt->data, buf_len);
172
173 return buf_len;
174 }
175
quicki2c_set_report(struct quicki2c_device * qcdev,u8 report_type,unsigned int reportnum,void * buf,u32 buf_len)176 int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
177 unsigned int reportnum, void *buf, u32 buf_len)
178 {
179 int rep_type;
180 int ret;
181
182 if (report_type == HID_OUTPUT_REPORT) {
183 rep_type = HIDI2C_OUTPUT;
184 } else if (report_type == HID_FEATURE_REPORT) {
185 rep_type = HIDI2C_FEATURE;
186 } else {
187 dev_err(qcdev->dev, "Unsupported report type for SET REPORT: %d\n", report_type);
188 return -EINVAL;
189 }
190
191 ret = write_cmd_to_txdma(qcdev, HIDI2C_SET_REPORT, rep_type, reportnum, buf, buf_len);
192 if (ret) {
193 dev_err_once(qcdev->dev, "Set Report failed, ret %d\n", ret);
194 return ret;
195 }
196
197 return buf_len;
198 }
199
200 #define HIDI2C_RESET_TIMEOUT 5
201
quicki2c_reset(struct quicki2c_device * qcdev)202 int quicki2c_reset(struct quicki2c_device *qcdev)
203 {
204 u16 input_reg = le16_to_cpu(qcdev->dev_desc.input_reg);
205 size_t read_len = HIDI2C_LENGTH_LEN;
206 u32 prd_len = read_len;
207 int ret;
208
209 qcdev->reset_ack = false;
210 qcdev->state = QUICKI2C_RESETING;
211
212 ret = write_cmd_to_txdma(qcdev, HIDI2C_RESET, HIDI2C_RESERVED, 0, NULL, 0);
213 if (ret) {
214 dev_err_once(qcdev->dev, "Send reset command failed, ret %d\n", ret);
215 return ret;
216 }
217
218 ret = wait_event_interruptible_timeout(qcdev->reset_ack_wq, qcdev->reset_ack,
219 HIDI2C_RESET_TIMEOUT * HZ);
220 if (qcdev->reset_ack)
221 return 0;
222
223 /*
224 * Manually read reset response if it wasn't received, in case reset interrupt
225 * was missed by touch device or THC hardware.
226 */
227 ret = thc_tic_pio_read(qcdev->thc_hw, input_reg, read_len, &prd_len,
228 (u32 *)qcdev->input_buf);
229 if (ret) {
230 dev_err_once(qcdev->dev, "Read Reset Response failed, ret %d\n", ret);
231 return ret;
232 }
233
234 /*
235 * Check response packet length, it's first 16 bits of packet.
236 * If response packet length is zero, it's reset response, otherwise not.
237 */
238 if (get_unaligned_le16(qcdev->input_buf)) {
239 dev_err_once(qcdev->dev,
240 "Wait reset response timed out ret:%d timeout:%ds\n",
241 ret, HIDI2C_RESET_TIMEOUT);
242 return -ETIMEDOUT;
243 }
244
245 qcdev->reset_ack = true;
246
247 return 0;
248 }
249