1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Intel La Jolla Cove Adapter USB driver |
4 | * |
5 | * Copyright (c) 2023, Intel Corporation. |
6 | */ |
7 | |
8 | #include <linux/acpi.h> |
9 | #include <linux/auxiliary_bus.h> |
10 | #include <linux/dev_printk.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/mod_devicetable.h> |
13 | #include <linux/module.h> |
14 | #include <linux/mutex.h> |
15 | #include <linux/slab.h> |
16 | #include <linux/spinlock.h> |
17 | #include <linux/types.h> |
18 | #include <linux/usb.h> |
19 | #include <linux/usb/ljca.h> |
20 | |
21 | #include <asm/unaligned.h> |
22 | |
23 | /* command flags */ |
24 | #define LJCA_ACK_FLAG BIT(0) |
25 | #define LJCA_RESP_FLAG BIT(1) |
26 | #define LJCA_CMPL_FLAG BIT(2) |
27 | |
28 | #define LJCA_MAX_PACKET_SIZE 64u |
29 | #define LJCA_MAX_PAYLOAD_SIZE \ |
30 | (LJCA_MAX_PACKET_SIZE - sizeof(struct ljca_msg)) |
31 | |
32 | #define LJCA_WRITE_TIMEOUT_MS 200 |
33 | #define LJCA_WRITE_ACK_TIMEOUT_MS 500 |
34 | #define LJCA_ENUM_CLIENT_TIMEOUT_MS 20 |
35 | |
36 | /* ljca client type */ |
37 | enum ljca_client_type { |
38 | LJCA_CLIENT_MNG = 1, |
39 | LJCA_CLIENT_GPIO = 3, |
40 | LJCA_CLIENT_I2C = 4, |
41 | LJCA_CLIENT_SPI = 5, |
42 | }; |
43 | |
44 | /* MNG client commands */ |
45 | enum ljca_mng_cmd { |
46 | LJCA_MNG_RESET = 2, |
47 | LJCA_MNG_ENUM_GPIO = 4, |
48 | LJCA_MNG_ENUM_I2C = 5, |
49 | LJCA_MNG_ENUM_SPI = 8, |
50 | }; |
51 | |
52 | /* ljca client acpi _ADR */ |
53 | enum ljca_client_acpi_adr { |
54 | LJCA_GPIO_ACPI_ADR, |
55 | LJCA_I2C1_ACPI_ADR, |
56 | LJCA_I2C2_ACPI_ADR, |
57 | LJCA_SPI1_ACPI_ADR, |
58 | LJCA_SPI2_ACPI_ADR, |
59 | LJCA_CLIENT_ACPI_ADR_MAX, |
60 | }; |
61 | |
62 | /* ljca cmd message structure */ |
63 | struct ljca_msg { |
64 | u8 type; |
65 | u8 cmd; |
66 | u8 flags; |
67 | u8 len; |
68 | u8 data[] __counted_by(len); |
69 | } __packed; |
70 | |
71 | struct ljca_i2c_ctr_info { |
72 | u8 id; |
73 | u8 capacity; |
74 | u8 intr_pin; |
75 | } __packed; |
76 | |
77 | struct ljca_i2c_descriptor { |
78 | u8 num; |
79 | struct ljca_i2c_ctr_info info[] __counted_by(num); |
80 | } __packed; |
81 | |
82 | struct ljca_spi_ctr_info { |
83 | u8 id; |
84 | u8 capacity; |
85 | u8 intr_pin; |
86 | } __packed; |
87 | |
88 | struct ljca_spi_descriptor { |
89 | u8 num; |
90 | struct ljca_spi_ctr_info info[] __counted_by(num); |
91 | } __packed; |
92 | |
93 | struct ljca_bank_descriptor { |
94 | u8 bank_id; |
95 | u8 pin_num; |
96 | |
97 | /* 1 bit for each gpio, 1 means valid */ |
98 | __le32 valid_pins; |
99 | } __packed; |
100 | |
101 | struct ljca_gpio_descriptor { |
102 | u8 pins_per_bank; |
103 | u8 bank_num; |
104 | struct ljca_bank_descriptor bank_desc[] __counted_by(bank_num); |
105 | } __packed; |
106 | |
107 | /** |
108 | * struct ljca_adapter - represent a ljca adapter |
109 | * |
110 | * @intf: the usb interface for this ljca adapter |
111 | * @usb_dev: the usb device for this ljca adapter |
112 | * @dev: the specific device info of the usb interface |
113 | * @rx_pipe: bulk in pipe for receive data from firmware |
114 | * @tx_pipe: bulk out pipe for send data to firmware |
115 | * @rx_urb: urb used for the bulk in pipe |
116 | * @rx_buf: buffer used to receive command response and event |
117 | * @rx_len: length of rx buffer |
118 | * @ex_buf: external buffer to save command response |
119 | * @ex_buf_len: length of external buffer |
120 | * @actual_length: actual length of data copied to external buffer |
121 | * @tx_buf: buffer used to download command to firmware |
122 | * @tx_buf_len: length of tx buffer |
123 | * @lock: spinlock to protect tx_buf and ex_buf |
124 | * @cmd_completion: completion object as the command receives ack |
125 | * @mutex: mutex to avoid command download concurrently |
126 | * @client_list: client device list |
127 | * @disconnect: usb disconnect ongoing or not |
128 | * @reset_id: used to reset firmware |
129 | */ |
130 | struct ljca_adapter { |
131 | struct usb_interface *intf; |
132 | struct usb_device *usb_dev; |
133 | struct device *dev; |
134 | |
135 | unsigned int rx_pipe; |
136 | unsigned int tx_pipe; |
137 | |
138 | struct urb *rx_urb; |
139 | void *rx_buf; |
140 | unsigned int rx_len; |
141 | |
142 | u8 *ex_buf; |
143 | u8 ex_buf_len; |
144 | u8 actual_length; |
145 | |
146 | void *tx_buf; |
147 | u8 tx_buf_len; |
148 | |
149 | spinlock_t lock; |
150 | |
151 | struct completion cmd_completion; |
152 | struct mutex mutex; |
153 | |
154 | struct list_head client_list; |
155 | |
156 | bool disconnect; |
157 | |
158 | u32 reset_id; |
159 | }; |
160 | |
161 | struct ljca_match_ids_walk_data { |
162 | const struct acpi_device_id *ids; |
163 | const char *uid; |
164 | struct acpi_device *adev; |
165 | }; |
166 | |
167 | static const struct acpi_device_id ljca_gpio_hids[] = { |
168 | { "INTC1074" }, |
169 | { "INTC1096" }, |
170 | { "INTC100B" }, |
171 | { "INTC10D1" }, |
172 | {}, |
173 | }; |
174 | |
175 | static const struct acpi_device_id ljca_i2c_hids[] = { |
176 | { "INTC1075" }, |
177 | { "INTC1097" }, |
178 | { "INTC100C" }, |
179 | { "INTC10D2" }, |
180 | {}, |
181 | }; |
182 | |
183 | static const struct acpi_device_id ljca_spi_hids[] = { |
184 | { "INTC1091" }, |
185 | { "INTC1098" }, |
186 | { "INTC100D" }, |
187 | { "INTC10D3" }, |
188 | {}, |
189 | }; |
190 | |
191 | static void ljca_handle_event(struct ljca_adapter *adap, |
192 | struct ljca_msg *) |
193 | { |
194 | struct ljca_client *client; |
195 | |
196 | list_for_each_entry(client, &adap->client_list, link) { |
197 | /* |
198 | * Currently only GPIO register event callback, but |
199 | * firmware message structure should include id when |
200 | * multiple same type clients register event callback. |
201 | */ |
202 | if (client->type == header->type) { |
203 | unsigned long flags; |
204 | |
205 | spin_lock_irqsave(&client->event_cb_lock, flags); |
206 | client->event_cb(client->context, header->cmd, |
207 | header->data, header->len); |
208 | spin_unlock_irqrestore(lock: &client->event_cb_lock, flags); |
209 | |
210 | break; |
211 | } |
212 | } |
213 | } |
214 | |
215 | /* process command ack and received data if available */ |
216 | static void ljca_handle_cmd_ack(struct ljca_adapter *adap, struct ljca_msg *) |
217 | { |
218 | struct ljca_msg * = adap->tx_buf; |
219 | u8 ibuf_len, actual_len = 0; |
220 | unsigned long flags; |
221 | u8 *ibuf; |
222 | |
223 | spin_lock_irqsave(&adap->lock, flags); |
224 | |
225 | if (tx_header->type != header->type || tx_header->cmd != header->cmd) { |
226 | spin_unlock_irqrestore(lock: &adap->lock, flags); |
227 | dev_err(adap->dev, "cmd ack mismatch error\n" ); |
228 | return; |
229 | } |
230 | |
231 | ibuf_len = adap->ex_buf_len; |
232 | ibuf = adap->ex_buf; |
233 | |
234 | if (ibuf && ibuf_len) { |
235 | actual_len = min(header->len, ibuf_len); |
236 | |
237 | /* copy received data to external buffer */ |
238 | memcpy(ibuf, header->data, actual_len); |
239 | } |
240 | /* update copied data length */ |
241 | adap->actual_length = actual_len; |
242 | |
243 | spin_unlock_irqrestore(lock: &adap->lock, flags); |
244 | |
245 | complete(&adap->cmd_completion); |
246 | } |
247 | |
248 | static void ljca_recv(struct urb *urb) |
249 | { |
250 | struct ljca_msg * = urb->transfer_buffer; |
251 | struct ljca_adapter *adap = urb->context; |
252 | int ret; |
253 | |
254 | switch (urb->status) { |
255 | case 0: |
256 | /* success */ |
257 | break; |
258 | case -ENOENT: |
259 | /* |
260 | * directly complete the possible ongoing transfer |
261 | * during disconnect |
262 | */ |
263 | if (adap->disconnect) |
264 | complete(&adap->cmd_completion); |
265 | return; |
266 | case -ECONNRESET: |
267 | case -ESHUTDOWN: |
268 | case -EPIPE: |
269 | /* rx urb is terminated */ |
270 | dev_dbg(adap->dev, "rx urb terminated with status: %d\n" , |
271 | urb->status); |
272 | return; |
273 | default: |
274 | dev_dbg(adap->dev, "rx urb error: %d\n" , urb->status); |
275 | goto resubmit; |
276 | } |
277 | |
278 | if (header->len + sizeof(*header) != urb->actual_length) |
279 | goto resubmit; |
280 | |
281 | if (header->flags & LJCA_ACK_FLAG) |
282 | ljca_handle_cmd_ack(adap, header); |
283 | else |
284 | ljca_handle_event(adap, header); |
285 | |
286 | resubmit: |
287 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
288 | if (ret && ret != -EPERM) |
289 | dev_err(adap->dev, "resubmit rx urb error %d\n" , ret); |
290 | } |
291 | |
292 | static int ljca_send(struct ljca_adapter *adap, u8 type, u8 cmd, |
293 | const u8 *obuf, u8 obuf_len, u8 *ibuf, u8 ibuf_len, |
294 | bool ack, unsigned long timeout) |
295 | { |
296 | unsigned int msg_len = sizeof(struct ljca_msg) + obuf_len; |
297 | struct ljca_msg * = adap->tx_buf; |
298 | unsigned int transferred; |
299 | unsigned long flags; |
300 | int ret; |
301 | |
302 | if (adap->disconnect) |
303 | return -ENODEV; |
304 | |
305 | if (msg_len > adap->tx_buf_len) |
306 | return -EINVAL; |
307 | |
308 | mutex_lock(&adap->mutex); |
309 | |
310 | spin_lock_irqsave(&adap->lock, flags); |
311 | |
312 | header->type = type; |
313 | header->cmd = cmd; |
314 | header->len = obuf_len; |
315 | if (obuf) |
316 | memcpy(header->data, obuf, obuf_len); |
317 | |
318 | header->flags = LJCA_CMPL_FLAG | (ack ? LJCA_ACK_FLAG : 0); |
319 | |
320 | adap->ex_buf = ibuf; |
321 | adap->ex_buf_len = ibuf_len; |
322 | adap->actual_length = 0; |
323 | |
324 | spin_unlock_irqrestore(lock: &adap->lock, flags); |
325 | |
326 | reinit_completion(x: &adap->cmd_completion); |
327 | |
328 | ret = usb_autopm_get_interface(intf: adap->intf); |
329 | if (ret < 0) |
330 | goto out; |
331 | |
332 | ret = usb_bulk_msg(usb_dev: adap->usb_dev, pipe: adap->tx_pipe, data: header, |
333 | len: msg_len, actual_length: &transferred, LJCA_WRITE_TIMEOUT_MS); |
334 | |
335 | usb_autopm_put_interface(intf: adap->intf); |
336 | |
337 | if (ret < 0) |
338 | goto out; |
339 | if (transferred != msg_len) { |
340 | ret = -EIO; |
341 | goto out; |
342 | } |
343 | |
344 | if (ack) { |
345 | ret = wait_for_completion_timeout(x: &adap->cmd_completion, |
346 | timeout); |
347 | if (!ret) { |
348 | ret = -ETIMEDOUT; |
349 | goto out; |
350 | } |
351 | } |
352 | ret = adap->actual_length; |
353 | |
354 | out: |
355 | spin_lock_irqsave(&adap->lock, flags); |
356 | adap->ex_buf = NULL; |
357 | adap->ex_buf_len = 0; |
358 | |
359 | memset(header, 0, sizeof(*header)); |
360 | spin_unlock_irqrestore(lock: &adap->lock, flags); |
361 | |
362 | mutex_unlock(lock: &adap->mutex); |
363 | |
364 | return ret; |
365 | } |
366 | |
367 | int ljca_transfer(struct ljca_client *client, u8 cmd, const u8 *obuf, |
368 | u8 obuf_len, u8 *ibuf, u8 ibuf_len) |
369 | { |
370 | return ljca_send(adap: client->adapter, type: client->type, cmd, |
371 | obuf, obuf_len, ibuf, ibuf_len, ack: true, |
372 | LJCA_WRITE_ACK_TIMEOUT_MS); |
373 | } |
374 | EXPORT_SYMBOL_NS_GPL(ljca_transfer, LJCA); |
375 | |
376 | int ljca_transfer_noack(struct ljca_client *client, u8 cmd, const u8 *obuf, |
377 | u8 obuf_len) |
378 | { |
379 | return ljca_send(adap: client->adapter, type: client->type, cmd, obuf, |
380 | obuf_len, NULL, ibuf_len: 0, ack: false, LJCA_WRITE_ACK_TIMEOUT_MS); |
381 | } |
382 | EXPORT_SYMBOL_NS_GPL(ljca_transfer_noack, LJCA); |
383 | |
384 | int ljca_register_event_cb(struct ljca_client *client, ljca_event_cb_t event_cb, |
385 | void *context) |
386 | { |
387 | unsigned long flags; |
388 | |
389 | if (!event_cb) |
390 | return -EINVAL; |
391 | |
392 | spin_lock_irqsave(&client->event_cb_lock, flags); |
393 | |
394 | if (client->event_cb) { |
395 | spin_unlock_irqrestore(lock: &client->event_cb_lock, flags); |
396 | return -EALREADY; |
397 | } |
398 | |
399 | client->event_cb = event_cb; |
400 | client->context = context; |
401 | |
402 | spin_unlock_irqrestore(lock: &client->event_cb_lock, flags); |
403 | |
404 | return 0; |
405 | } |
406 | EXPORT_SYMBOL_NS_GPL(ljca_register_event_cb, LJCA); |
407 | |
408 | void ljca_unregister_event_cb(struct ljca_client *client) |
409 | { |
410 | unsigned long flags; |
411 | |
412 | spin_lock_irqsave(&client->event_cb_lock, flags); |
413 | |
414 | client->event_cb = NULL; |
415 | client->context = NULL; |
416 | |
417 | spin_unlock_irqrestore(lock: &client->event_cb_lock, flags); |
418 | } |
419 | EXPORT_SYMBOL_NS_GPL(ljca_unregister_event_cb, LJCA); |
420 | |
421 | static int ljca_match_device_ids(struct acpi_device *adev, void *data) |
422 | { |
423 | struct ljca_match_ids_walk_data *wd = data; |
424 | const char *uid = acpi_device_uid(adev); |
425 | |
426 | if (acpi_match_device_ids(device: adev, ids: wd->ids)) |
427 | return 0; |
428 | |
429 | if (!wd->uid) |
430 | goto match; |
431 | |
432 | if (!uid) |
433 | /* |
434 | * Some DSDTs have only one ACPI companion for the two I2C |
435 | * controllers and they don't set a UID at all (e.g. Dell |
436 | * Latitude 9420). On these platforms only the first I2C |
437 | * controller is used, so if a HID match has no UID we use |
438 | * "0" as the UID and assign ACPI companion to the first |
439 | * I2C controller. |
440 | */ |
441 | uid = "0" ; |
442 | else |
443 | uid = strchr(uid, wd->uid[0]); |
444 | |
445 | if (!uid || strcmp(uid, wd->uid)) |
446 | return 0; |
447 | |
448 | match: |
449 | wd->adev = adev; |
450 | |
451 | return 1; |
452 | } |
453 | |
454 | /* bind auxiliary device to acpi device */ |
455 | static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap, |
456 | struct auxiliary_device *auxdev, |
457 | u64 adr, u8 id) |
458 | { |
459 | struct ljca_match_ids_walk_data wd = { 0 }; |
460 | struct device *dev = adap->dev; |
461 | struct acpi_device *parent; |
462 | char uid[4]; |
463 | |
464 | parent = ACPI_COMPANION(dev); |
465 | if (!parent) |
466 | return; |
467 | |
468 | /* |
469 | * Currently LJCA hw doesn't use _ADR instead the shipped |
470 | * platforms use _HID to distinguish children devices. |
471 | */ |
472 | switch (adr) { |
473 | case LJCA_GPIO_ACPI_ADR: |
474 | wd.ids = ljca_gpio_hids; |
475 | break; |
476 | case LJCA_I2C1_ACPI_ADR: |
477 | case LJCA_I2C2_ACPI_ADR: |
478 | snprintf(buf: uid, size: sizeof(uid), fmt: "%d" , id); |
479 | wd.uid = uid; |
480 | wd.ids = ljca_i2c_hids; |
481 | break; |
482 | case LJCA_SPI1_ACPI_ADR: |
483 | case LJCA_SPI2_ACPI_ADR: |
484 | wd.ids = ljca_spi_hids; |
485 | break; |
486 | default: |
487 | dev_warn(dev, "unsupported _ADR\n" ); |
488 | return; |
489 | } |
490 | |
491 | acpi_dev_for_each_child(adev: parent, fn: ljca_match_device_ids, data: &wd); |
492 | if (wd.adev) { |
493 | ACPI_COMPANION_SET(&auxdev->dev, wd.adev); |
494 | return; |
495 | } |
496 | |
497 | parent = ACPI_COMPANION(dev->parent->parent); |
498 | if (!parent) |
499 | return; |
500 | |
501 | acpi_dev_for_each_child(adev: parent, fn: ljca_match_device_ids, data: &wd); |
502 | if (wd.adev) |
503 | ACPI_COMPANION_SET(&auxdev->dev, wd.adev); |
504 | } |
505 | |
506 | static void ljca_auxdev_release(struct device *dev) |
507 | { |
508 | struct auxiliary_device *auxdev = to_auxiliary_dev(dev); |
509 | |
510 | kfree(objp: auxdev->dev.platform_data); |
511 | } |
512 | |
513 | static int ljca_new_client_device(struct ljca_adapter *adap, u8 type, u8 id, |
514 | char *name, void *data, u64 adr) |
515 | { |
516 | struct auxiliary_device *auxdev; |
517 | struct ljca_client *client; |
518 | int ret; |
519 | |
520 | client = kzalloc(size: sizeof *client, GFP_KERNEL); |
521 | if (!client) { |
522 | kfree(objp: data); |
523 | return -ENOMEM; |
524 | } |
525 | |
526 | client->type = type; |
527 | client->id = id; |
528 | client->adapter = adap; |
529 | spin_lock_init(&client->event_cb_lock); |
530 | |
531 | auxdev = &client->auxdev; |
532 | auxdev->name = name; |
533 | auxdev->id = id; |
534 | |
535 | auxdev->dev.parent = adap->dev; |
536 | auxdev->dev.platform_data = data; |
537 | auxdev->dev.release = ljca_auxdev_release; |
538 | |
539 | ret = auxiliary_device_init(auxdev); |
540 | if (ret) { |
541 | kfree(objp: data); |
542 | goto err_free; |
543 | } |
544 | |
545 | ljca_auxdev_acpi_bind(adap, auxdev, adr, id); |
546 | |
547 | ret = auxiliary_device_add(auxdev); |
548 | if (ret) |
549 | goto err_uninit; |
550 | |
551 | list_add_tail(new: &client->link, head: &adap->client_list); |
552 | |
553 | return 0; |
554 | |
555 | err_uninit: |
556 | auxiliary_device_uninit(auxdev); |
557 | |
558 | err_free: |
559 | kfree(objp: client); |
560 | |
561 | return ret; |
562 | } |
563 | |
564 | static int ljca_enumerate_gpio(struct ljca_adapter *adap) |
565 | { |
566 | u32 valid_pin[LJCA_MAX_GPIO_NUM / BITS_PER_TYPE(u32)]; |
567 | struct ljca_gpio_descriptor *desc; |
568 | struct ljca_gpio_info *gpio_info; |
569 | u8 buf[LJCA_MAX_PAYLOAD_SIZE]; |
570 | int ret, gpio_num; |
571 | unsigned int i; |
572 | |
573 | ret = ljca_send(adap, type: LJCA_CLIENT_MNG, cmd: LJCA_MNG_ENUM_GPIO, NULL, obuf_len: 0, ibuf: buf, |
574 | ibuf_len: sizeof(buf), ack: true, LJCA_ENUM_CLIENT_TIMEOUT_MS); |
575 | if (ret < 0) |
576 | return ret; |
577 | |
578 | /* check firmware response */ |
579 | desc = (struct ljca_gpio_descriptor *)buf; |
580 | if (ret != struct_size(desc, bank_desc, desc->bank_num)) |
581 | return -EINVAL; |
582 | |
583 | gpio_num = desc->pins_per_bank * desc->bank_num; |
584 | if (gpio_num > LJCA_MAX_GPIO_NUM) |
585 | return -EINVAL; |
586 | |
587 | /* construct platform data */ |
588 | gpio_info = kzalloc(size: sizeof *gpio_info, GFP_KERNEL); |
589 | if (!gpio_info) |
590 | return -ENOMEM; |
591 | gpio_info->num = gpio_num; |
592 | |
593 | for (i = 0; i < desc->bank_num; i++) |
594 | valid_pin[i] = get_unaligned_le32(p: &desc->bank_desc[i].valid_pins); |
595 | bitmap_from_arr32(bitmap: gpio_info->valid_pin_map, buf: valid_pin, nbits: gpio_num); |
596 | |
597 | return ljca_new_client_device(adap, type: LJCA_CLIENT_GPIO, id: 0, name: "ljca-gpio" , |
598 | data: gpio_info, adr: LJCA_GPIO_ACPI_ADR); |
599 | } |
600 | |
601 | static int ljca_enumerate_i2c(struct ljca_adapter *adap) |
602 | { |
603 | struct ljca_i2c_descriptor *desc; |
604 | struct ljca_i2c_info *i2c_info; |
605 | u8 buf[LJCA_MAX_PAYLOAD_SIZE]; |
606 | unsigned int i; |
607 | int ret; |
608 | |
609 | ret = ljca_send(adap, type: LJCA_CLIENT_MNG, cmd: LJCA_MNG_ENUM_I2C, NULL, obuf_len: 0, ibuf: buf, |
610 | ibuf_len: sizeof(buf), ack: true, LJCA_ENUM_CLIENT_TIMEOUT_MS); |
611 | if (ret < 0) |
612 | return ret; |
613 | |
614 | /* check firmware response */ |
615 | desc = (struct ljca_i2c_descriptor *)buf; |
616 | if (ret != struct_size(desc, info, desc->num)) |
617 | return -EINVAL; |
618 | |
619 | for (i = 0; i < desc->num; i++) { |
620 | /* construct platform data */ |
621 | i2c_info = kzalloc(size: sizeof *i2c_info, GFP_KERNEL); |
622 | if (!i2c_info) |
623 | return -ENOMEM; |
624 | |
625 | i2c_info->id = desc->info[i].id; |
626 | i2c_info->capacity = desc->info[i].capacity; |
627 | i2c_info->intr_pin = desc->info[i].intr_pin; |
628 | |
629 | ret = ljca_new_client_device(adap, type: LJCA_CLIENT_I2C, id: i, |
630 | name: "ljca-i2c" , data: i2c_info, |
631 | adr: LJCA_I2C1_ACPI_ADR + i); |
632 | if (ret) |
633 | return ret; |
634 | } |
635 | |
636 | return 0; |
637 | } |
638 | |
639 | static int ljca_enumerate_spi(struct ljca_adapter *adap) |
640 | { |
641 | struct ljca_spi_descriptor *desc; |
642 | struct ljca_spi_info *spi_info; |
643 | u8 buf[LJCA_MAX_PAYLOAD_SIZE]; |
644 | unsigned int i; |
645 | int ret; |
646 | |
647 | /* Not all LJCA chips implement SPI, a timeout reading the descriptors is normal */ |
648 | ret = ljca_send(adap, type: LJCA_CLIENT_MNG, cmd: LJCA_MNG_ENUM_SPI, NULL, obuf_len: 0, ibuf: buf, |
649 | ibuf_len: sizeof(buf), ack: true, LJCA_ENUM_CLIENT_TIMEOUT_MS); |
650 | if (ret < 0) |
651 | return (ret == -ETIMEDOUT) ? 0 : ret; |
652 | |
653 | /* check firmware response */ |
654 | desc = (struct ljca_spi_descriptor *)buf; |
655 | if (ret != struct_size(desc, info, desc->num)) |
656 | return -EINVAL; |
657 | |
658 | for (i = 0; i < desc->num; i++) { |
659 | /* construct platform data */ |
660 | spi_info = kzalloc(size: sizeof *spi_info, GFP_KERNEL); |
661 | if (!spi_info) |
662 | return -ENOMEM; |
663 | |
664 | spi_info->id = desc->info[i].id; |
665 | spi_info->capacity = desc->info[i].capacity; |
666 | |
667 | ret = ljca_new_client_device(adap, type: LJCA_CLIENT_SPI, id: i, |
668 | name: "ljca-spi" , data: spi_info, |
669 | adr: LJCA_SPI1_ACPI_ADR + i); |
670 | if (ret) |
671 | return ret; |
672 | } |
673 | |
674 | return 0; |
675 | } |
676 | |
677 | static int ljca_reset_handshake(struct ljca_adapter *adap) |
678 | { |
679 | __le32 reset_id = cpu_to_le32(adap->reset_id); |
680 | __le32 reset_id_ret = 0; |
681 | int ret; |
682 | |
683 | adap->reset_id++; |
684 | |
685 | ret = ljca_send(adap, type: LJCA_CLIENT_MNG, cmd: LJCA_MNG_RESET, obuf: (u8 *)&reset_id, |
686 | obuf_len: sizeof(__le32), ibuf: (u8 *)&reset_id_ret, ibuf_len: sizeof(__le32), |
687 | ack: true, LJCA_WRITE_ACK_TIMEOUT_MS); |
688 | if (ret < 0) |
689 | return ret; |
690 | |
691 | if (reset_id_ret != reset_id) |
692 | return -EINVAL; |
693 | |
694 | return 0; |
695 | } |
696 | |
697 | static int ljca_enumerate_clients(struct ljca_adapter *adap) |
698 | { |
699 | struct ljca_client *client, *next; |
700 | int ret; |
701 | |
702 | ret = ljca_reset_handshake(adap); |
703 | if (ret) |
704 | goto err_kill; |
705 | |
706 | ret = ljca_enumerate_gpio(adap); |
707 | if (ret) { |
708 | dev_err(adap->dev, "enumerate GPIO error\n" ); |
709 | goto err_kill; |
710 | } |
711 | |
712 | ret = ljca_enumerate_i2c(adap); |
713 | if (ret) { |
714 | dev_err(adap->dev, "enumerate I2C error\n" ); |
715 | goto err_kill; |
716 | } |
717 | |
718 | ret = ljca_enumerate_spi(adap); |
719 | if (ret) { |
720 | dev_err(adap->dev, "enumerate SPI error\n" ); |
721 | goto err_kill; |
722 | } |
723 | |
724 | return 0; |
725 | |
726 | err_kill: |
727 | adap->disconnect = true; |
728 | |
729 | usb_kill_urb(urb: adap->rx_urb); |
730 | |
731 | list_for_each_entry_safe_reverse(client, next, &adap->client_list, link) { |
732 | auxiliary_device_delete(auxdev: &client->auxdev); |
733 | auxiliary_device_uninit(auxdev: &client->auxdev); |
734 | |
735 | list_del_init(entry: &client->link); |
736 | kfree(objp: client); |
737 | } |
738 | |
739 | return ret; |
740 | } |
741 | |
742 | static int ljca_probe(struct usb_interface *interface, |
743 | const struct usb_device_id *id) |
744 | { |
745 | struct usb_device *usb_dev = interface_to_usbdev(interface); |
746 | struct usb_host_interface *alt = interface->cur_altsetting; |
747 | struct usb_endpoint_descriptor *ep_in, *ep_out; |
748 | struct device *dev = &interface->dev; |
749 | struct ljca_adapter *adap; |
750 | int ret; |
751 | |
752 | adap = devm_kzalloc(dev, size: sizeof(*adap), GFP_KERNEL); |
753 | if (!adap) |
754 | return -ENOMEM; |
755 | |
756 | /* separate tx buffer allocation for alignment */ |
757 | adap->tx_buf = devm_kzalloc(dev, LJCA_MAX_PACKET_SIZE, GFP_KERNEL); |
758 | if (!adap->tx_buf) |
759 | return -ENOMEM; |
760 | adap->tx_buf_len = LJCA_MAX_PACKET_SIZE; |
761 | |
762 | mutex_init(&adap->mutex); |
763 | spin_lock_init(&adap->lock); |
764 | init_completion(x: &adap->cmd_completion); |
765 | INIT_LIST_HEAD(list: &adap->client_list); |
766 | |
767 | adap->intf = usb_get_intf(intf: interface); |
768 | adap->usb_dev = usb_dev; |
769 | adap->dev = dev; |
770 | |
771 | /* |
772 | * find the first bulk in and out endpoints. |
773 | * ignore any others. |
774 | */ |
775 | ret = usb_find_common_endpoints(alt, bulk_in: &ep_in, bulk_out: &ep_out, NULL, NULL); |
776 | if (ret) { |
777 | dev_err(dev, "bulk endpoints not found\n" ); |
778 | goto err_put; |
779 | } |
780 | adap->rx_pipe = usb_rcvbulkpipe(usb_dev, usb_endpoint_num(ep_in)); |
781 | adap->tx_pipe = usb_sndbulkpipe(usb_dev, usb_endpoint_num(ep_out)); |
782 | |
783 | /* setup rx buffer */ |
784 | adap->rx_len = usb_endpoint_maxp(epd: ep_in); |
785 | adap->rx_buf = devm_kzalloc(dev, size: adap->rx_len, GFP_KERNEL); |
786 | if (!adap->rx_buf) { |
787 | ret = -ENOMEM; |
788 | goto err_put; |
789 | } |
790 | |
791 | /* alloc rx urb */ |
792 | adap->rx_urb = usb_alloc_urb(iso_packets: 0, GFP_KERNEL); |
793 | if (!adap->rx_urb) { |
794 | ret = -ENOMEM; |
795 | goto err_put; |
796 | } |
797 | usb_fill_bulk_urb(urb: adap->rx_urb, dev: usb_dev, pipe: adap->rx_pipe, |
798 | transfer_buffer: adap->rx_buf, buffer_length: adap->rx_len, complete_fn: ljca_recv, context: adap); |
799 | |
800 | usb_set_intfdata(intf: interface, data: adap); |
801 | |
802 | /* submit rx urb before enumerate clients */ |
803 | ret = usb_submit_urb(urb: adap->rx_urb, GFP_KERNEL); |
804 | if (ret) { |
805 | dev_err(dev, "submit rx urb failed: %d\n" , ret); |
806 | goto err_free; |
807 | } |
808 | |
809 | ret = ljca_enumerate_clients(adap); |
810 | if (ret) |
811 | goto err_free; |
812 | |
813 | usb_enable_autosuspend(udev: usb_dev); |
814 | |
815 | return 0; |
816 | |
817 | err_free: |
818 | usb_free_urb(urb: adap->rx_urb); |
819 | |
820 | err_put: |
821 | usb_put_intf(intf: adap->intf); |
822 | |
823 | mutex_destroy(lock: &adap->mutex); |
824 | |
825 | return ret; |
826 | } |
827 | |
828 | static void ljca_disconnect(struct usb_interface *interface) |
829 | { |
830 | struct ljca_adapter *adap = usb_get_intfdata(intf: interface); |
831 | struct ljca_client *client, *next; |
832 | |
833 | adap->disconnect = true; |
834 | |
835 | usb_kill_urb(urb: adap->rx_urb); |
836 | |
837 | list_for_each_entry_safe_reverse(client, next, &adap->client_list, link) { |
838 | auxiliary_device_delete(auxdev: &client->auxdev); |
839 | auxiliary_device_uninit(auxdev: &client->auxdev); |
840 | |
841 | list_del_init(entry: &client->link); |
842 | kfree(objp: client); |
843 | } |
844 | |
845 | usb_free_urb(urb: adap->rx_urb); |
846 | |
847 | usb_put_intf(intf: adap->intf); |
848 | |
849 | mutex_destroy(lock: &adap->mutex); |
850 | } |
851 | |
852 | static int ljca_suspend(struct usb_interface *interface, pm_message_t message) |
853 | { |
854 | struct ljca_adapter *adap = usb_get_intfdata(intf: interface); |
855 | |
856 | usb_kill_urb(urb: adap->rx_urb); |
857 | |
858 | return 0; |
859 | } |
860 | |
861 | static int ljca_resume(struct usb_interface *interface) |
862 | { |
863 | struct ljca_adapter *adap = usb_get_intfdata(intf: interface); |
864 | |
865 | return usb_submit_urb(urb: adap->rx_urb, GFP_KERNEL); |
866 | } |
867 | |
868 | static const struct usb_device_id ljca_table[] = { |
869 | { USB_DEVICE(0x8086, 0x0b63) }, |
870 | { /* sentinel */ } |
871 | }; |
872 | MODULE_DEVICE_TABLE(usb, ljca_table); |
873 | |
874 | static struct usb_driver ljca_driver = { |
875 | .name = "ljca" , |
876 | .id_table = ljca_table, |
877 | .probe = ljca_probe, |
878 | .disconnect = ljca_disconnect, |
879 | .suspend = ljca_suspend, |
880 | .resume = ljca_resume, |
881 | .supports_autosuspend = 1, |
882 | }; |
883 | module_usb_driver(ljca_driver); |
884 | |
885 | MODULE_AUTHOR("Wentong Wu <wentong.wu@intel.com>" ); |
886 | MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>" ); |
887 | MODULE_AUTHOR("Lixu Zhang <lixu.zhang@intel.com>" ); |
888 | MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB driver" ); |
889 | MODULE_LICENSE("GPL" ); |
890 | |