blob: 3d4f8d653b5d214041dc531537250d9b4372fcc9 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassdfd84002015-03-25 12:22:41 -06002/*
3 * (C) Copyright 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glassdfd84002015-03-25 12:22:41 -06005 */
6
7#include <common.h>
8#include <dm.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -06009#include <log.h>
Simon Glassdfd84002015-03-25 12:22:41 -060010#include <usb.h>
11#include <dm/root.h>
Patrice Chotard4c3dc6f2021-09-10 16:16:22 +020012#include <linux/usb/gadget.h>
13
14struct sandbox_udc {
15 struct usb_gadget gadget;
16};
17
18struct sandbox_udc *this_controller;
Simon Glassdfd84002015-03-25 12:22:41 -060019
Bin Meng813f74e2017-10-01 06:19:38 -070020struct sandbox_usb_ctrl {
21 int rootdev;
22};
23
Simon Glassdfd84002015-03-25 12:22:41 -060024static void usbmon_trace(struct udevice *bus, ulong pipe,
25 struct devrequest *setup, struct udevice *emul)
26{
27 static const char types[] = "ZICB";
28 int type;
29
30 type = (pipe & USB_PIPE_TYPE_MASK) >> USB_PIPE_TYPE_SHIFT;
31 debug("0 0 S %c%c:%d:%03ld:%ld", types[type],
32 pipe & USB_DIR_IN ? 'i' : 'o',
Simon Glass8b85dfc2020-12-16 21:20:07 -070033 dev_seq(bus),
Simon Glassdfd84002015-03-25 12:22:41 -060034 (pipe & USB_PIPE_DEV_MASK) >> USB_PIPE_DEV_SHIFT,
35 (pipe & USB_PIPE_EP_MASK) >> USB_PIPE_EP_SHIFT);
36 if (setup) {
37 debug(" s %02x %02x %04x %04x %04x", setup->requesttype,
38 setup->request, setup->value, setup->index,
39 setup->length);
40 }
41 debug(" %s", emul ? emul->name : "(no emul found)");
42
43 debug("\n");
44}
45
46static int sandbox_submit_control(struct udevice *bus,
47 struct usb_device *udev,
48 unsigned long pipe,
49 void *buffer, int length,
50 struct devrequest *setup)
51{
Bin Meng813f74e2017-10-01 06:19:38 -070052 struct sandbox_usb_ctrl *ctrl = dev_get_priv(bus);
Simon Glassdfd84002015-03-25 12:22:41 -060053 struct udevice *emul;
54 int ret;
55
56 /* Just use child of dev as emulator? */
57 debug("%s: bus=%s\n", __func__, bus->name);
Bin Meng84aa8532017-10-01 06:19:39 -070058 ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
Simon Glassdfd84002015-03-25 12:22:41 -060059 usbmon_trace(bus, pipe, setup, emul);
60 if (ret)
61 return ret;
Bin Meng813f74e2017-10-01 06:19:38 -070062
63 if (usb_pipedevice(pipe) == ctrl->rootdev) {
64 if (setup->request == USB_REQ_SET_ADDRESS) {
65 debug("%s: Set root hub's USB address\n", __func__);
66 ctrl->rootdev = le16_to_cpu(setup->value);
67 }
68 }
69
Simon Glassdfd84002015-03-25 12:22:41 -060070 ret = usb_emul_control(emul, udev, pipe, buffer, length, setup);
71 if (ret < 0) {
72 debug("ret=%d\n", ret);
73 udev->status = ret;
74 udev->act_len = 0;
75 } else {
76 udev->status = 0;
77 udev->act_len = ret;
78 }
79
80 return ret;
81}
82
83static int sandbox_submit_bulk(struct udevice *bus, struct usb_device *udev,
84 unsigned long pipe, void *buffer, int length)
85{
86 struct udevice *emul;
87 int ret;
88
89 /* Just use child of dev as emulator? */
90 debug("%s: bus=%s\n", __func__, bus->name);
Bin Meng84aa8532017-10-01 06:19:39 -070091 ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
Simon Glassdfd84002015-03-25 12:22:41 -060092 usbmon_trace(bus, pipe, NULL, emul);
93 if (ret)
94 return ret;
95 ret = usb_emul_bulk(emul, udev, pipe, buffer, length);
96 if (ret < 0) {
97 debug("ret=%d\n", ret);
98 udev->status = ret;
99 udev->act_len = 0;
100 } else {
101 udev->status = 0;
102 udev->act_len = ret;
103 }
104
105 return ret;
106}
107
Simon Glassb70a3fe2015-11-08 23:48:05 -0700108static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev,
109 unsigned long pipe, void *buffer, int length,
Michal Suchanek34371212019-08-18 10:55:27 +0200110 int interval, bool nonblock)
Simon Glassb70a3fe2015-11-08 23:48:05 -0700111{
112 struct udevice *emul;
113 int ret;
114
115 /* Just use child of dev as emulator? */
116 debug("%s: bus=%s\n", __func__, bus->name);
Bin Meng84aa8532017-10-01 06:19:39 -0700117 ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
Simon Glassb70a3fe2015-11-08 23:48:05 -0700118 usbmon_trace(bus, pipe, NULL, emul);
119 if (ret)
120 return ret;
Michal Suchanek34371212019-08-18 10:55:27 +0200121 ret = usb_emul_int(emul, udev, pipe, buffer, length, interval,
122 nonblock);
Simon Glassb70a3fe2015-11-08 23:48:05 -0700123
124 return ret;
125}
126
Marek Vasut7307b122023-09-01 11:49:48 +0200127#if CONFIG_IS_ENABLED(DM_USB_GADGET)
128int dm_usb_gadget_handle_interrupts(struct udevice *dev)
129{
130 return 0;
131}
132#else
Patrice Chotard4c3dc6f2021-09-10 16:16:22 +0200133int usb_gadget_register_driver(struct usb_gadget_driver *driver)
134{
135 struct sandbox_udc *dev = this_controller;
136
137 return driver->bind(&dev->gadget);
138}
139
140int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
141{
142 struct sandbox_udc *dev = this_controller;
143
144 driver->unbind(&dev->gadget);
145
146 return 0;
147}
Marek Vasut7307b122023-09-01 11:49:48 +0200148#endif
Patrice Chotard4c3dc6f2021-09-10 16:16:22 +0200149
Simon Glassdfd84002015-03-25 12:22:41 -0600150static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev)
151{
Bin Meng813f74e2017-10-01 06:19:38 -0700152 struct sandbox_usb_ctrl *ctrl = dev_get_priv(dev);
153
154 /*
155 * Root hub will be the first device to be initailized.
156 * If this device is a root hub, initialize its device speed
157 * to high speed as we are a USB 2.0 controller.
158 */
159 if (ctrl->rootdev == 0)
160 udev->speed = USB_SPEED_HIGH;
161
Simon Glassdfd84002015-03-25 12:22:41 -0600162 return 0;
163}
164
165static int sandbox_usb_probe(struct udevice *dev)
166{
167 return 0;
168}
169
170static const struct dm_usb_ops sandbox_usb_ops = {
171 .control = sandbox_submit_control,
172 .bulk = sandbox_submit_bulk,
Simon Glassb70a3fe2015-11-08 23:48:05 -0700173 .interrupt = sandbox_submit_int,
Simon Glassdfd84002015-03-25 12:22:41 -0600174 .alloc_device = sandbox_alloc_device,
175};
176
177static const struct udevice_id sandbox_usb_ids[] = {
178 { .compatible = "sandbox,usb" },
179 { }
180};
181
182U_BOOT_DRIVER(usb_sandbox) = {
183 .name = "usb_sandbox",
184 .id = UCLASS_USB,
185 .of_match = sandbox_usb_ids,
186 .probe = sandbox_usb_probe,
187 .ops = &sandbox_usb_ops,
Simon Glass41575d82020-12-03 16:55:17 -0700188 .priv_auto = sizeof(struct sandbox_usb_ctrl),
Simon Glassdfd84002015-03-25 12:22:41 -0600189};