]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/usb/intel_ulpss/ulpss_bridge.c
UBUNTU: SAUCE: IPU driver release WW48 with MCU
[mirror_ubuntu-jammy-kernel.git] / drivers / usb / intel_ulpss / ulpss_bridge.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Intel LPSS USB driver
4 *
5 * Copyright (c) 2020, Intel Corporation.
6 */
7
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/kfifo.h>
11 #include <linux/kthread.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/slab.h>
15 #include <linux/uaccess.h>
16 #include <linux/usb.h>
17
18 #include "diag_stub.h"
19 #include "i2c_stub.h"
20 #include "mng_stub.h"
21 #include "ulpss_bridge.h"
22
23 /* Define these values to match your devices */
24 #define USB_BRIDGE_VENDOR_ID 0x8086
25 #define USB_BRIDGE_PRODUCT_ID 0x0b63
26
27 /* table of devices that work with this driver */
28 static const struct usb_device_id intel_ulpss_bridge_table[] = {
29 { USB_DEVICE(USB_BRIDGE_VENDOR_ID, USB_BRIDGE_PRODUCT_ID) },
30 {} /* Terminating entry */
31 };
32 MODULE_DEVICE_TABLE(usb, intel_ulpss_bridge_table);
33
34 static void intel_ulpss_bridge_read_cb(struct urb *urb)
35 {
36 struct usb_bridge *intel_ulpss_dev;
37 struct bridge_msg msg;
38 unsigned long flags;
39 bool need_sched;
40 int ret;
41
42 intel_ulpss_dev = urb->context;
43 BUG_ON(!intel_ulpss_dev);
44 dev_dbg(&intel_ulpss_dev->intf->dev,
45 "%s bulk read urb got message from fw, status:%d data_len:%d\n",
46 __func__, urb->status, urb->actual_length);
47
48 if (urb->status || intel_ulpss_dev->errors) {
49 /* sync/async unlink faults aren't errors */
50 if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
51 urb->status == -ESHUTDOWN) {
52 dev_dbg(&intel_ulpss_dev->intf->dev,
53 "%s read bulk urb unlink: %d %d\n", __func__,
54 urb->status, intel_ulpss_dev->errors);
55 return;
56 } else {
57 dev_err(&intel_ulpss_dev->intf->dev,
58 "%s read bulk urb transfer failed: %d %d\n",
59 __func__, urb->status, intel_ulpss_dev->errors);
60 goto resubmmit;
61 }
62 }
63
64 msg.len = urb->actual_length;
65 memcpy(msg.buf, intel_ulpss_dev->bulk_in_buffer, urb->actual_length);
66
67 spin_lock_irqsave(&intel_ulpss_dev->msg_fifo_spinlock, flags);
68 need_sched = kfifo_is_empty(&intel_ulpss_dev->msg_fifo);
69
70 if (kfifo_put(&intel_ulpss_dev->msg_fifo, msg)) {
71 if (need_sched)
72 schedule_work(&intel_ulpss_dev->event_work);
73 } else {
74 dev_err(&intel_ulpss_dev->intf->dev,
75 "%s put msg faild full:%d\n", __func__,
76 kfifo_is_full(&intel_ulpss_dev->msg_fifo));
77 }
78
79 spin_unlock_irqrestore(&intel_ulpss_dev->msg_fifo_spinlock, flags);
80
81 resubmmit:
82 /* resubmmit urb to receive fw msg */
83 ret = usb_submit_urb(intel_ulpss_dev->bulk_in_urb, GFP_KERNEL);
84 if (ret) {
85 dev_err(&intel_ulpss_dev->intf->dev,
86 "%s failed submitting read urb, error %d\n", __func__,
87 ret);
88 }
89 }
90
91 static int intel_ulpss_bridge_read_start(struct usb_bridge *intel_ulpss_dev)
92 {
93 int ret;
94
95 /* prepare a read */
96 usb_fill_bulk_urb(
97 intel_ulpss_dev->bulk_in_urb, intel_ulpss_dev->udev,
98 usb_rcvbulkpipe(intel_ulpss_dev->udev,
99 intel_ulpss_dev->bulk_in_endpointAddr),
100 intel_ulpss_dev->bulk_in_buffer, intel_ulpss_dev->bulk_in_size,
101 intel_ulpss_bridge_read_cb, intel_ulpss_dev);
102
103 /* submit read urb */
104 ret = usb_submit_urb(intel_ulpss_dev->bulk_in_urb, GFP_KERNEL);
105 if (ret) {
106 dev_err(&intel_ulpss_dev->intf->dev,
107 "%s - failed submitting read urb, error %d\n", __func__,
108 ret);
109 }
110 return ret;
111 }
112
113 static void intel_ulpss_bridge_write_cb(struct urb *urb)
114 {
115 struct usb_bridge *intel_ulpss_dev;
116
117 intel_ulpss_dev = urb->context;
118
119 if (!intel_ulpss_dev)
120 return;
121
122 if (urb->status) {
123 /* sync/async unlink faults aren't errors */
124 if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
125 urb->status == -ESHUTDOWN) {
126 dev_warn(&intel_ulpss_dev->intf->dev,
127 "%s write bulk urb unlink: %d\n", __func__,
128 urb->status);
129 } else {
130 dev_err(&intel_ulpss_dev->intf->dev,
131 "%s write bulk urb transfer failed: %d\n",
132 __func__, urb->status);
133
134 intel_ulpss_dev->errors = urb->status;
135 }
136 }
137
138 /* free up our allocated buffer */
139 usb_free_coherent(urb->dev, urb->transfer_buffer_length,
140 urb->transfer_buffer, urb->transfer_dma);
141
142 dev_dbg(&intel_ulpss_dev->intf->dev, "%s write callback out\n",
143 __func__);
144 }
145
146 ssize_t intel_ulpss_bridge_write(struct usb_interface *intf, void *data,
147 size_t len, unsigned int timeout)
148 {
149 struct urb *urb = NULL;
150 struct usb_bridge *intel_ulpss_dev = usb_get_intfdata(intf);
151 char *buf = NULL;
152 int time;
153 int ret;
154
155 if (!len || len > MAX_PACKET_SIZE) {
156 dev_err(&intf->dev, "%s write len not correct len:%ld\n",
157 __func__, len);
158 return -EINVAL;
159 }
160
161 mutex_lock(&intel_ulpss_dev->write_mutex);
162 usb_autopm_get_interface(intf);
163
164 if (intel_ulpss_dev->errors) {
165 dev_err(&intf->dev, "%s dev error %d\n", __func__,
166 intel_ulpss_dev->errors);
167 intel_ulpss_dev->errors = 0;
168 ret = -EINVAL;
169 goto error;
170 }
171
172 /* create a urb, and a buffer for it, and copy the data to the urb */
173 urb = usb_alloc_urb(0, GFP_KERNEL);
174 if (!urb) {
175 ret = -ENOMEM;
176 goto error;
177 }
178
179 buf = usb_alloc_coherent(intel_ulpss_dev->udev, len, GFP_KERNEL,
180 &urb->transfer_dma);
181
182 if (!buf) {
183 ret = -ENOMEM;
184 goto error;
185 }
186
187 memcpy(buf, data, len);
188
189 if (intel_ulpss_dev->disconnected) { /* disconnect() was called */
190 ret = -ENODEV;
191 goto error;
192 }
193
194 /* initialize the urb properly */
195 usb_fill_bulk_urb(
196 urb, intel_ulpss_dev->udev,
197 usb_sndbulkpipe(intel_ulpss_dev->udev,
198 intel_ulpss_dev->bulk_out_endpointAddr),
199 buf, len, intel_ulpss_bridge_write_cb, intel_ulpss_dev);
200 urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
201
202 usb_anchor_urb(urb, &intel_ulpss_dev->write_submitted);
203 /* send the data out the bulk port */
204 ret = usb_submit_urb(urb, GFP_KERNEL);
205 if (ret) {
206 dev_err(&intel_ulpss_dev->intf->dev,
207 "%s - failed submitting write urb, error %d\n",
208 __func__, ret);
209 goto error_unanchor;
210 }
211
212 /*
213 * release our reference to this urb, the USB core will eventually free
214 * it entirely
215 */
216 usb_free_urb(urb);
217
218 time = usb_wait_anchor_empty_timeout(&intel_ulpss_dev->write_submitted,
219 timeout);
220 if (!time) {
221 usb_kill_anchored_urbs(&intel_ulpss_dev->write_submitted);
222 dev_err(&intel_ulpss_dev->intf->dev,
223 "%s waiting out urb sending timeout, error %d %d\n",
224 __func__, time, timeout);
225 }
226
227 usb_autopm_put_interface(intf);
228 mutex_unlock(&intel_ulpss_dev->write_mutex);
229 return len;
230
231 error_unanchor:
232 usb_unanchor_urb(urb);
233 error:
234 if (urb) {
235 /* free up our allocated buffer */
236 usb_free_coherent(urb->dev, urb->transfer_buffer_length,
237 urb->transfer_buffer, urb->transfer_dma);
238 usb_free_urb(urb);
239 }
240
241 usb_autopm_put_interface(intf);
242 mutex_unlock(&intel_ulpss_dev->write_mutex);
243 return ret;
244 }
245
246 static void intel_ulpss_bridge_delete(struct usb_bridge *intel_ulpss_dev)
247 {
248 usb_free_urb(intel_ulpss_dev->bulk_in_urb);
249 usb_put_intf(intel_ulpss_dev->intf);
250 usb_put_dev(intel_ulpss_dev->udev);
251 kfree(intel_ulpss_dev->bulk_in_buffer);
252 kfree(intel_ulpss_dev);
253 }
254
255 static int intel_ulpss_bridge_init(struct usb_bridge *intel_ulpss_dev)
256 {
257 mutex_init(&intel_ulpss_dev->write_mutex);
258 init_usb_anchor(&intel_ulpss_dev->write_submitted);
259 init_waitqueue_head(&intel_ulpss_dev->bulk_out_ack);
260 INIT_LIST_HEAD(&intel_ulpss_dev->stubs_list);
261 INIT_KFIFO(intel_ulpss_dev->msg_fifo);
262 spin_lock_init(&intel_ulpss_dev->msg_fifo_spinlock);
263
264 intel_ulpss_dev->state = USB_BRIDGE_INITED;
265
266 return 0;
267 }
268
269 static ssize_t cmd_store(struct device *dev, struct device_attribute *attr,
270 const char *buf, size_t count)
271 {
272 struct usb_interface *intf = to_usb_interface(dev);
273 struct usb_stub *mng_stub = usb_stub_find(intf, MNG_CMD_TYPE);
274 struct usb_stub *diag_stub = usb_stub_find(intf, DIAG_CMD_TYPE);
275 int ret;
276
277 dev_dbg(dev, "%s:%u %s\n", __func__, __LINE__, buf);
278 if (sysfs_streq(buf, "dfu")) {
279 ret = mng_set_dfu_mode(mng_stub);
280 } else if (sysfs_streq(buf, "reset")) {
281 ret = mng_reset(mng_stub);
282 } else if (sysfs_streq(buf, "debug")) {
283 ret = diag_set_trace_level(diag_stub, 3);
284 }
285
286 return count;
287 }
288
289 static ssize_t cmd_show(struct device *dev, struct device_attribute *attr,
290 char *buf)
291 {
292 dev_dbg(dev, "%s:%u \n", __func__, __LINE__);
293
294 return sprintf(buf, "%s\n", "supported cmd: [dfu, reset, debug]");
295 }
296 static DEVICE_ATTR_RW(cmd);
297
298 static ssize_t version_show(struct device *dev, struct device_attribute *attr,
299 char *buf)
300 {
301 struct usb_interface *intf = to_usb_interface(dev);
302 struct usb_stub *mng_stub = usb_stub_find(intf, MNG_CMD_TYPE);
303
304 dev_dbg(dev, "%s:%u\n", __func__, __LINE__);
305 return mng_get_version_string(mng_stub, buf);
306 }
307 static DEVICE_ATTR_RO(version);
308
309 static ssize_t log_show(struct device *dev, struct device_attribute *attr,
310 char *buf)
311 {
312 int ret;
313 ssize_t len;
314 struct usb_interface *intf = to_usb_interface(dev);
315 struct usb_stub *diag_stub = usb_stub_find(intf, DIAG_CMD_TYPE);
316
317 ret = diag_get_fw_log(diag_stub, buf, &len);
318 dev_dbg(dev, "%s:%u len %ld\n", __func__, __LINE__, len);
319
320 if (ret)
321 return ret;
322 else
323 return len;
324 }
325 static DEVICE_ATTR_RO(log);
326
327 static ssize_t coredump_show(struct device *dev, struct device_attribute *attr,
328 char *buf)
329 {
330 int ret;
331 ssize_t len;
332 struct usb_interface *intf = to_usb_interface(dev);
333 struct usb_stub *diag_stub = usb_stub_find(intf, DIAG_CMD_TYPE);
334
335 ret = diag_get_coredump(diag_stub, buf, &len);
336 dev_dbg(dev, "%s:%u len %ld\n", __func__, __LINE__, len);
337
338 if (ret)
339 return ret;
340 else
341 return len;
342 }
343 static DEVICE_ATTR_RO(coredump);
344
345 static struct attribute *intel_ulpss_bridge_attrs[] = {
346 &dev_attr_version.attr,
347 &dev_attr_cmd.attr,
348 &dev_attr_log.attr,
349 &dev_attr_coredump.attr,
350 NULL,
351 };
352 ATTRIBUTE_GROUPS(intel_ulpss_bridge);
353
354 static int intel_ulpss_bridge_probe(struct usb_interface *intf,
355 const struct usb_device_id *id)
356 {
357 struct usb_bridge *intel_ulpss_dev;
358 struct usb_endpoint_descriptor *bulk_in, *bulk_out;
359 struct usb_stub *stub;
360 int ret;
361
362 /* allocate memory for our device state and initialize it */
363 intel_ulpss_dev = kzalloc(sizeof(*intel_ulpss_dev), GFP_KERNEL);
364 if (!intel_ulpss_dev)
365 return -ENOMEM;
366
367 intel_ulpss_bridge_init(intel_ulpss_dev);
368 intel_ulpss_dev->udev = usb_get_dev(interface_to_usbdev(intf));
369 intel_ulpss_dev->intf = usb_get_intf(intf);
370
371 /* set up the endpoint information */
372 /* use only the first bulk-in and bulk-out endpoints */
373 ret = usb_find_common_endpoints(intf->cur_altsetting, &bulk_in,
374 &bulk_out, NULL, NULL);
375 if (ret) {
376 dev_err(&intf->dev,
377 "Could not find both bulk-in and bulk-out endpoints\n");
378 goto error;
379 }
380
381 intel_ulpss_dev->bulk_in_size = usb_endpoint_maxp(bulk_in);
382 intel_ulpss_dev->bulk_in_endpointAddr = bulk_in->bEndpointAddress;
383 intel_ulpss_dev->bulk_in_buffer =
384 kzalloc(intel_ulpss_dev->bulk_in_size, GFP_KERNEL);
385 if (!intel_ulpss_dev->bulk_in_buffer) {
386 ret = -ENOMEM;
387 goto error;
388 }
389 intel_ulpss_dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
390 if (!intel_ulpss_dev->bulk_in_urb) {
391 ret = -ENOMEM;
392 goto error;
393 }
394 intel_ulpss_dev->bulk_out_endpointAddr = bulk_out->bEndpointAddress;
395
396 dev_dbg(&intf->dev, "bulk_in size:%ld addr:%d bulk_out addr:%d\n",
397 intel_ulpss_dev->bulk_in_size,
398 intel_ulpss_dev->bulk_in_endpointAddr,
399 intel_ulpss_dev->bulk_out_endpointAddr);
400
401 /* save our data pointer in this intf device */
402 usb_set_intfdata(intf, intel_ulpss_dev);
403
404 ret = intel_ulpss_bridge_read_start(intel_ulpss_dev);
405 if (ret) {
406 dev_err(&intf->dev, "%s bridge read start failed ret %d\n",
407 __func__, ret);
408 goto error;
409 }
410
411 ret = usb_stub_init(intf);
412 if (ret) {
413 dev_err(&intf->dev, "%s usb stub init failed ret %d\n",
414 __func__, ret);
415 usb_set_intfdata(intf, NULL);
416 goto error;
417 }
418
419 ret = mng_stub_init(intf, NULL, 0);
420 if (ret) {
421 dev_err(&intf->dev, "%s register mng stub failed ret %d\n",
422 __func__, ret);
423 return ret;
424 }
425
426 ret = diag_stub_init(intf, NULL, 0);
427 if (ret) {
428 dev_err(&intf->dev, "%s register diag stub failed ret %d\n",
429 __func__, ret);
430 return ret;
431 }
432
433 stub = usb_stub_find(intf, MNG_CMD_TYPE);
434 if (!stub) {
435 ret = -EINVAL;
436 return ret;
437 }
438
439 ret = mng_stub_link(intf, stub);
440 if (intel_ulpss_dev->state != USB_BRIDGE_STARTED) {
441 dev_err(&intf->dev, "%s mng stub link done ret:%d state:%d\n",
442 __func__, ret, intel_ulpss_dev->state);
443 return ret;
444 }
445
446 usb_enable_autosuspend(intel_ulpss_dev->udev);
447 dev_info(&intf->dev, "intel_ulpss USB bridge device init success\n");
448 return 0;
449
450 error:
451 /* this frees allocated memory */
452 intel_ulpss_bridge_delete(intel_ulpss_dev);
453
454 return ret;
455 }
456
457 static void intel_ulpss_bridge_disconnect(struct usb_interface *intf)
458 {
459 struct usb_bridge *intel_ulpss_dev;
460
461 intel_ulpss_dev = usb_get_intfdata(intf);
462 intel_ulpss_dev->disconnected = 1;
463
464 usb_kill_urb(intel_ulpss_dev->bulk_in_urb);
465 usb_kill_anchored_urbs(&intel_ulpss_dev->write_submitted);
466
467 usb_stub_cleanup(intf);
468 intel_ulpss_dev->state = USB_BRIDGE_STOPPED;
469
470 cancel_work_sync(&intel_ulpss_dev->event_work);
471
472 usb_set_intfdata(intf, NULL);
473 /* decrement our usage len */
474 intel_ulpss_bridge_delete(intel_ulpss_dev);
475
476 dev_dbg(&intf->dev, "USB bridge now disconnected\n");
477 }
478
479 static void intel_ulpss_bridge_draw_down(struct usb_bridge *intel_ulpss_dev)
480 {
481 int time;
482
483 time = usb_wait_anchor_empty_timeout(&intel_ulpss_dev->write_submitted,
484 1000);
485 if (!time)
486 usb_kill_anchored_urbs(&intel_ulpss_dev->write_submitted);
487 usb_kill_urb(intel_ulpss_dev->bulk_in_urb);
488 }
489
490 static int intel_ulpss_bridge_suspend(struct usb_interface *intf,
491 pm_message_t message)
492 {
493 struct usb_bridge *intel_ulpss_dev = usb_get_intfdata(intf);
494 dev_dbg(&intf->dev, "USB bridge now suspend\n");
495
496 intel_ulpss_bridge_draw_down(intel_ulpss_dev);
497 return 0;
498 }
499
500 static int intel_ulpss_bridge_resume(struct usb_interface *intf)
501 {
502 int ret;
503 struct usb_bridge *intel_ulpss_dev = usb_get_intfdata(intf);
504 dev_dbg(&intf->dev, "USB bridge now resume\n");
505
506 ret = intel_ulpss_bridge_read_start(intel_ulpss_dev);
507 if (ret) {
508 dev_err(&intf->dev, "%s bridge read start failed ret %d\n",
509 __func__, ret);
510 }
511 return ret;
512 }
513 static struct usb_driver bridge_driver = {
514 .name = "intel_ulpss",
515 .probe = intel_ulpss_bridge_probe,
516 .disconnect = intel_ulpss_bridge_disconnect,
517 .suspend = intel_ulpss_bridge_suspend,
518 .resume = intel_ulpss_bridge_resume,
519 .id_table = intel_ulpss_bridge_table,
520 .dev_groups = intel_ulpss_bridge_groups,
521 .supports_autosuspend = 1,
522 };
523
524 module_usb_driver(bridge_driver);
525
526 MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>");
527 MODULE_AUTHOR("Zhang Lixu <lixu.zhang@intel.com>");
528 MODULE_DESCRIPTION("Intel LPSS USB driver");
529 MODULE_LICENSE("GPL v2");