blob: be3b6b9f32e845dea3b927de4d1db8f5844cb0b0 [file] [log] [blame]
Rui Miguel Silvafb0c70c2022-06-29 11:06:14 +01001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Common code for usb urb handling, based on the musb-new code
4 *
5 * Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
6 *
7 */
8
9#include <dm/device.h>
10#include <dm/device_compat.h>
11#include <linux/usb/usb_urb_compat.h>
12
13#include <time.h>
14#include <usb.h>
15
16#if CONFIG_IS_ENABLED(DM_USB)
17struct usb_device *usb_dev_get_parent(struct usb_device *udev)
18{
19 struct udevice *parent = udev->dev->parent;
20
21 /*
22 * When called from usb-uclass.c: usb_scan_device() udev->dev points
23 * to the parent udevice, not the actual udevice belonging to the
24 * udev as the device is not instantiated yet.
25 *
26 * If dev is an usb-bus, then we are called from usb_scan_device() for
27 * an usb-device plugged directly into the root port, return NULL.
28 */
29 if (device_get_uclass_id(udev->dev) == UCLASS_USB)
30 return NULL;
31
32 /*
33 * If these 2 are not the same we are being called from
34 * usb_scan_device() and udev itself is the parent.
35 */
36 if (dev_get_parent_priv(udev->dev) != udev)
37 return udev;
38
39 /* We are being called normally, use the parent pointer */
40 if (device_get_uclass_id(parent) == UCLASS_USB_HUB)
41 return dev_get_parent_priv(parent);
42
43 return NULL;
44}
45#else
46struct usb_device *usb_dev_get_parent(struct usb_device *udev)
47{
48 return udev->parent;
49}
50#endif
51
52static void usb_urb_complete(struct urb *urb)
53{
54 urb->dev->status &= ~USB_ST_NOT_PROC;
55 urb->dev->act_len = urb->actual_length;
56
57 if (urb->status == -EINPROGRESS)
58 urb->status = 0;
59}
60
61void usb_urb_fill(struct urb *urb, struct usb_host_endpoint *hep,
62 struct usb_device *dev, int endpoint_type,
63 unsigned long pipe, void *buffer, int len,
64 struct devrequest *setup, int interval)
65{
66 int epnum = usb_pipeendpoint(pipe);
67 int is_in = usb_pipein(pipe);
68 u16 maxpacketsize = is_in ? dev->epmaxpacketin[epnum] :
69 dev->epmaxpacketout[epnum];
70
71 memset(urb, 0, sizeof(struct urb));
72 memset(hep, 0, sizeof(struct usb_host_endpoint));
73 INIT_LIST_HEAD(&hep->urb_list);
74 INIT_LIST_HEAD(&urb->urb_list);
75 urb->ep = hep;
76 urb->complete = usb_urb_complete;
77 urb->status = -EINPROGRESS;
78 urb->dev = dev;
79 urb->pipe = pipe;
80 urb->transfer_buffer = buffer;
81 urb->transfer_dma = (unsigned long)buffer;
82 urb->transfer_buffer_length = len;
83 urb->setup_packet = (unsigned char *)setup;
84
85 urb->ep->desc.wMaxPacketSize = __cpu_to_le16(maxpacketsize);
86 urb->ep->desc.bmAttributes = endpoint_type;
87 urb->ep->desc.bEndpointAddress = ((is_in ? USB_DIR_IN : USB_DIR_OUT) |
88 epnum);
89 urb->ep->desc.bInterval = interval;
90}
91
92int usb_urb_submit(struct usb_hcd *hcd, struct urb *urb)
93{
94 const struct usb_urb_ops *ops = hcd->urb_ops;
95 unsigned long timeout;
96 int ret;
97
98 if (!ops)
99 return -EINVAL;
100
101 ret = ops->urb_enqueue(hcd, urb, 0);
102 if (ret < 0) {
103 printf("Failed to enqueue URB to controller\n");
104 return ret;
105 }
106
107 timeout = get_timer(0) + USB_TIMEOUT_MS(urb->pipe);
108 do {
109 if (ctrlc())
110 return -EIO;
111 ops->isr(0, hcd);
112 } while (urb->status == -EINPROGRESS && get_timer(0) < timeout);
113
114 if (urb->status == -EINPROGRESS)
115 ops->urb_dequeue(hcd, urb, -ETIME);
116
117 return urb->status;
118}
119
120int usb_urb_submit_control(struct usb_hcd *hcd, struct urb *urb,
121 struct usb_host_endpoint *hep,
122 struct usb_device *dev, unsigned long pipe,
123 void *buffer, int len, struct devrequest *setup,
124 int interval, enum usb_device_speed speed)
125{
126 const struct usb_urb_ops *ops = hcd->urb_ops;
127
128 usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_CONTROL, pipe, buffer,
129 len, setup, 0);
130
131 /* Fix speed for non hub-attached devices */
132 if (!usb_dev_get_parent(dev)) {
133 dev->speed = speed;
134 if (ops->hub_control)
135 return ops->hub_control(hcd, dev, pipe, buffer, len,
136 setup);
137 }
138
139 return usb_urb_submit(hcd, urb);
140}
141
142int usb_urb_submit_bulk(struct usb_hcd *hcd, struct urb *urb,
143 struct usb_host_endpoint *hep, struct usb_device *dev,
144 unsigned long pipe, void *buffer, int len)
145{
146 usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_BULK, pipe, buffer, len,
147 NULL, 0);
148
149 return usb_urb_submit(hcd, urb);
150}
151
152int usb_urb_submit_irq(struct usb_hcd *hcd, struct urb *urb,
153 struct usb_host_endpoint *hep, struct usb_device *dev,
154 unsigned long pipe, void *buffer, int len, int interval)
155{
156 usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_INT, pipe, buffer, len,
157 NULL, interval);
158
159 return usb_urb_submit(hcd, urb);
160}