]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/i2c/busses/i2c-ljca.c
Revert "UBUNTU: SAUCE: i2c-ljca: fix a potential issue"
[mirror_ubuntu-jammy-kernel.git] / drivers / i2c / busses / i2c-ljca.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Intel La Jolla Cove Adapter USB-I2C driver
4 *
5 * Copyright (c) 2021, Intel Corporation.
6 */
7
8 #include <linux/acpi.h>
9 #include <linux/i2c.h>
10 #include <linux/mfd/ljca.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13
14 /* I2C commands */
15 enum i2c_cmd {
16 I2C_INIT = 1,
17 I2C_XFER,
18 I2C_START,
19 I2C_STOP,
20 I2C_READ,
21 I2C_WRITE,
22 };
23
24 enum i2c_address_mode {
25 I2C_ADDRESS_MODE_7BIT,
26 I2C_ADDRESS_MODE_10BIT,
27 };
28
29 enum xfer_type {
30 READ_XFER_TYPE,
31 WRITE_XFER_TYPE,
32 };
33
34 #define DEFAULT_I2C_CONTROLLER_ID 1
35 #define DEFAULT_I2C_CAPACITY 0
36 #define DEFAULT_I2C_INTR_PIN 0
37
38 /* I2C r/w Flags */
39 #define I2C_SLAVE_TRANSFER_WRITE (0)
40 #define I2C_SLAVE_TRANSFER_READ (1)
41
42 /* i2c init flags */
43 #define I2C_INIT_FLAG_MODE_MASK (0x1 << 0)
44 #define I2C_INIT_FLAG_MODE_POLLING (0x0 << 0)
45 #define I2C_INIT_FLAG_MODE_INTERRUPT (0x1 << 0)
46
47 #define I2C_FLAG_ADDR_16BIT (0x1 << 0)
48
49 #define I2C_INIT_FLAG_FREQ_MASK (0x3 << 1)
50 #define I2C_FLAG_FREQ_100K (0x0 << 1)
51 #define I2C_FLAG_FREQ_400K (0x1 << 1)
52 #define I2C_FLAG_FREQ_1M (0x2 << 1)
53
54 /* I2C Transfer */
55 struct i2c_xfer {
56 u8 id;
57 u8 slave;
58 u16 flag; /* speed, 8/16bit addr, addr increase, etc */
59 u16 addr;
60 u16 len;
61 u8 data[];
62 } __packed;
63
64 /* I2C raw commands: Init/Start/Read/Write/Stop */
65 struct i2c_rw_packet {
66 u8 id;
67 __le16 len;
68 u8 data[];
69 } __packed;
70
71 #define LJCA_I2C_MAX_XFER_SIZE 256
72 #define LJCA_I2C_BUF_SIZE \
73 (LJCA_I2C_MAX_XFER_SIZE + sizeof(struct i2c_rw_packet))
74
75 struct ljca_i2c_dev {
76 struct platform_device *pdev;
77 struct ljca_i2c_info *ctr_info;
78 struct i2c_adapter adap;
79
80 u8 obuf[LJCA_I2C_BUF_SIZE];
81 u8 ibuf[LJCA_I2C_BUF_SIZE];
82 };
83
84 static u8 ljca_i2c_format_slave_addr(u8 slave_addr, enum i2c_address_mode mode)
85 {
86 if (mode == I2C_ADDRESS_MODE_7BIT)
87 return slave_addr << 1;
88
89 return 0xFF;
90 }
91
92 static int ljca_i2c_init(struct ljca_i2c_dev *ljca_i2c, u8 id)
93 {
94 struct i2c_rw_packet *w_packet = (struct i2c_rw_packet *)ljca_i2c->obuf;
95
96 memset(w_packet, 0, sizeof(*w_packet));
97 w_packet->id = id;
98 w_packet->len = cpu_to_le16(1);
99 w_packet->data[0] = I2C_FLAG_FREQ_400K;
100
101 return ljca_transfer(ljca_i2c->pdev, I2C_INIT, w_packet,
102 sizeof(*w_packet) + 1, NULL, NULL);
103 }
104
105 static int ljca_i2c_start(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr,
106 enum xfer_type type)
107 {
108 struct i2c_rw_packet *w_packet = (struct i2c_rw_packet *)ljca_i2c->obuf;
109 struct i2c_rw_packet *r_packet = (struct i2c_rw_packet *)ljca_i2c->ibuf;
110 int ret;
111 int ibuf_len;
112
113 memset(w_packet, 0, sizeof(*w_packet));
114 w_packet->id = ljca_i2c->ctr_info->id;
115 w_packet->len = cpu_to_le16(1);
116 w_packet->data[0] =
117 ljca_i2c_format_slave_addr(slave_addr, I2C_ADDRESS_MODE_7BIT);
118 w_packet->data[0] |= (type == READ_XFER_TYPE) ?
119 I2C_SLAVE_TRANSFER_READ :
120 I2C_SLAVE_TRANSFER_WRITE;
121
122 ret = ljca_transfer(ljca_i2c->pdev, I2C_START, w_packet,
123 sizeof(*w_packet) + 1, r_packet, &ibuf_len);
124
125 if (ret || ibuf_len < sizeof(*r_packet))
126 return -EIO;
127
128 if ((s16)le16_to_cpu(r_packet->len) < 0 ||
129 r_packet->id != w_packet->id) {
130 dev_err(&ljca_i2c->adap.dev,
131 "i2c start failed len:%d id:%d %d\n",
132 (s16)le16_to_cpu(r_packet->len), r_packet->id,
133 w_packet->id);
134 return -EIO;
135 }
136
137 return 0;
138 }
139
140 static int ljca_i2c_stop(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr)
141 {
142 struct i2c_rw_packet *w_packet = (struct i2c_rw_packet *)ljca_i2c->obuf;
143 struct i2c_rw_packet *r_packet = (struct i2c_rw_packet *)ljca_i2c->ibuf;
144 int ret;
145 int ibuf_len;
146
147 memset(w_packet, 0, sizeof(*w_packet));
148 w_packet->id = ljca_i2c->ctr_info->id;
149 w_packet->len = cpu_to_le16(1);
150 w_packet->data[0] = 0;
151
152 ret = ljca_transfer(ljca_i2c->pdev, I2C_STOP, w_packet,
153 sizeof(*w_packet) + 1, r_packet, &ibuf_len);
154
155 if (ret || ibuf_len < sizeof(*r_packet))
156 return -EIO;
157
158 if ((s16)le16_to_cpu(r_packet->len) < 0 ||
159 r_packet->id != w_packet->id) {
160 dev_err(&ljca_i2c->adap.dev,
161 "i2c stop failed len:%d id:%d %d\n",
162 (s16)le16_to_cpu(r_packet->len), r_packet->id,
163 w_packet->id);
164 return -EIO;
165 }
166
167 return 0;
168 }
169
170 static int ljca_i2c_pure_read(struct ljca_i2c_dev *ljca_i2c, u8 *data, int len)
171 {
172 struct i2c_rw_packet *w_packet = (struct i2c_rw_packet *)ljca_i2c->obuf;
173 struct i2c_rw_packet *r_packet = (struct i2c_rw_packet *)ljca_i2c->ibuf;
174 int ibuf_len;
175 int ret;
176
177 if (len > LJCA_I2C_MAX_XFER_SIZE)
178 return -EINVAL;
179
180 memset(w_packet, 0, sizeof(*w_packet));
181 w_packet->id = ljca_i2c->ctr_info->id;
182 w_packet->len = cpu_to_le16(len);
183 ret = ljca_transfer(ljca_i2c->pdev, I2C_READ, w_packet,
184 sizeof(*w_packet) + 1, r_packet, &ibuf_len);
185 if (ret) {
186 dev_err(&ljca_i2c->adap.dev, "I2C_READ failed ret:%d\n", ret);
187 return ret;
188 }
189
190 if (ibuf_len < sizeof(*r_packet))
191 return -EIO;
192
193 if ((s16)le16_to_cpu(r_packet->len) != len ||
194 r_packet->id != w_packet->id) {
195 dev_err(&ljca_i2c->adap.dev,
196 "i2c raw read failed len:%d id:%d %d\n",
197 (s16)le16_to_cpu(r_packet->len), r_packet->id,
198 w_packet->id);
199 return -EIO;
200 }
201
202 memcpy(data, r_packet->data, len);
203
204 return 0;
205 }
206
207 static int ljca_i2c_read(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr, u8 *data,
208 u8 len)
209 {
210 int ret;
211
212 ret = ljca_i2c_start(ljca_i2c, slave_addr, READ_XFER_TYPE);
213 if (ret)
214 return ret;
215
216 ret = ljca_i2c_pure_read(ljca_i2c, data, len);
217 if (ret) {
218 dev_err(&ljca_i2c->adap.dev, "i2c raw read failed ret:%d\n",
219 ret);
220
221 return ret;
222 }
223
224 return ljca_i2c_stop(ljca_i2c, slave_addr);
225 }
226
227 static int ljca_i2c_pure_write(struct ljca_i2c_dev *ljca_i2c, u8 *data, u8 len)
228 {
229 struct i2c_rw_packet *w_packet = (struct i2c_rw_packet *)ljca_i2c->obuf;
230 struct i2c_rw_packet *r_packet = (struct i2c_rw_packet *)ljca_i2c->ibuf;
231 int ret;
232 int ibuf_len;
233
234 if (len > LJCA_I2C_MAX_XFER_SIZE)
235 return -EINVAL;
236
237 memset(w_packet, 0, sizeof(*w_packet));
238 w_packet->id = ljca_i2c->ctr_info->id;
239 w_packet->len = cpu_to_le16(len);
240 memcpy(w_packet->data, data, len);
241
242 ret = ljca_transfer(ljca_i2c->pdev, I2C_WRITE, w_packet,
243 sizeof(*w_packet) + w_packet->len, r_packet,
244 &ibuf_len);
245
246 if (ret || ibuf_len < sizeof(*r_packet))
247 return -EIO;
248
249 if ((s16)le16_to_cpu(r_packet->len) != len ||
250 r_packet->id != w_packet->id) {
251 dev_err(&ljca_i2c->adap.dev,
252 "i2c write failed len:%d id:%d/%d\n",
253 (s16)le16_to_cpu(r_packet->len), r_packet->id,
254 w_packet->id);
255 return -EIO;
256 }
257
258 return 0;
259 }
260
261 static int ljca_i2c_write(struct ljca_i2c_dev *ljca_i2c, u8 slave_addr,
262 u8 *data, u8 len)
263 {
264 int ret;
265
266 if (!data)
267 return -EINVAL;
268
269 ret = ljca_i2c_start(ljca_i2c, slave_addr, WRITE_XFER_TYPE);
270 if (ret)
271 return ret;
272
273 ret = ljca_i2c_pure_write(ljca_i2c, data, len);
274 if (ret)
275 return ret;
276
277 return ljca_i2c_stop(ljca_i2c, slave_addr);
278 }
279
280 static int ljca_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg,
281 int num)
282 {
283 struct ljca_i2c_dev *ljca_i2c;
284 struct i2c_msg *cur_msg;
285 int i, ret;
286
287 ljca_i2c = i2c_get_adapdata(adapter);
288 if (!ljca_i2c)
289 return -EINVAL;
290
291 for (i = 0; !ret && i < num; i++) {
292 cur_msg = &msg[i];
293 dev_dbg(&adapter->dev, "i:%d msg:(%d %d)\n", i, cur_msg->flags,
294 cur_msg->len);
295 if (cur_msg->flags & I2C_M_RD)
296 ret = ljca_i2c_read(ljca_i2c, cur_msg->addr,
297 cur_msg->buf, cur_msg->len);
298
299 else
300 ret = ljca_i2c_write(ljca_i2c, cur_msg->addr,
301 cur_msg->buf, cur_msg->len);
302
303 if (ret)
304 return ret;
305 }
306
307 return num;
308 }
309
310 static u32 ljca_i2c_func(struct i2c_adapter *adap)
311 {
312 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
313 }
314
315 static const struct i2c_adapter_quirks ljca_i2c_quirks = {
316 .max_read_len = LJCA_I2C_MAX_XFER_SIZE,
317 .max_write_len = LJCA_I2C_MAX_XFER_SIZE,
318 };
319
320 static const struct i2c_algorithm ljca_i2c_algo = {
321 .master_xfer = ljca_i2c_xfer,
322 .functionality = ljca_i2c_func,
323 };
324
325 static void try_bind_acpi(struct platform_device *pdev,
326 struct ljca_i2c_dev *ljca_i2c)
327 {
328 struct acpi_device *parent, *child;
329 struct acpi_device *cur = ACPI_COMPANION(&pdev->dev);
330 const char *hid1;
331 const char *uid1;
332 char uid2[2] = { 0 };
333
334 if (!cur)
335 return;
336
337 hid1 = acpi_device_hid(cur);
338 uid1 = acpi_device_uid(cur);
339 snprintf(uid2, sizeof(uid2), "%d", ljca_i2c->ctr_info->id);
340
341 dev_dbg(&pdev->dev, "hid %s uid %s new uid%s\n", hid1, uid1, uid2);
342 /*
343 * If the pdev is bound to the right acpi device, just forward it to the
344 * adapter. Otherwise, we find that of current adapter manually.
345 */
346 if (!strcmp(uid1, uid2)) {
347 ACPI_COMPANION_SET(&ljca_i2c->adap.dev, cur);
348 return;
349 }
350
351 parent = ACPI_COMPANION(pdev->dev.parent);
352 if (!parent)
353 return;
354
355 list_for_each_entry(child, &parent->children, node) {
356 if (acpi_dev_hid_uid_match(child, hid1, uid2)) {
357 ACPI_COMPANION_SET(&ljca_i2c->adap.dev, child);
358 return;
359 }
360 }
361 }
362
363 static int ljca_i2c_probe(struct platform_device *pdev)
364 {
365 struct ljca_i2c_dev *ljca_i2c;
366 struct ljca_platform_data *pdata = dev_get_platdata(&pdev->dev);
367 int ret;
368
369 ljca_i2c = devm_kzalloc(&pdev->dev, sizeof(*ljca_i2c), GFP_KERNEL);
370 if (!ljca_i2c)
371 return -ENOMEM;
372
373 ljca_i2c->pdev = pdev;
374 ljca_i2c->ctr_info = &pdata->i2c_info;
375
376 ljca_i2c->adap.owner = THIS_MODULE;
377 ljca_i2c->adap.class = I2C_CLASS_HWMON;
378 ljca_i2c->adap.algo = &ljca_i2c_algo;
379 ljca_i2c->adap.dev.parent = &pdev->dev;
380
381 try_bind_acpi(pdev, ljca_i2c);
382
383 ljca_i2c->adap.dev.of_node = pdev->dev.of_node;
384 i2c_set_adapdata(&ljca_i2c->adap, ljca_i2c);
385 snprintf(ljca_i2c->adap.name, sizeof(ljca_i2c->adap.name), "%s-%s-%d",
386 "ljca-i2c", dev_name(pdev->dev.parent),
387 ljca_i2c->ctr_info->id);
388
389 platform_set_drvdata(pdev, ljca_i2c);
390
391 ret = ljca_i2c_init(ljca_i2c, ljca_i2c->ctr_info->id);
392 if (ret) {
393 dev_err(&pdev->dev, "i2c init failed id:%d\n",
394 ljca_i2c->ctr_info->id);
395 return -EIO;
396 }
397
398 return i2c_add_adapter(&ljca_i2c->adap);
399 }
400
401 static int ljca_i2c_remove(struct platform_device *pdev)
402 {
403 struct ljca_i2c_dev *ljca_i2c = platform_get_drvdata(pdev);
404
405 i2c_del_adapter(&ljca_i2c->adap);
406
407 return 0;
408 }
409
410 static struct platform_driver ljca_i2c_driver = {
411 .driver.name = "ljca-i2c",
412 .probe = ljca_i2c_probe,
413 .remove = ljca_i2c_remove,
414 };
415
416 module_platform_driver(ljca_i2c_driver);
417
418 MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>");
419 MODULE_AUTHOR("Zhang Lixu <lixu.zhang@intel.com>");
420 MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-I2C driver");
421 MODULE_LICENSE("GPL v2");
422 MODULE_ALIAS("platform:ljca-i2c");