Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / usb / host / usb-sandbox.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <log.h>
10 #include <usb.h>
11 #include <dm/root.h>
12 #include <linux/usb/gadget.h>
13
14 struct sandbox_udc {
15         struct usb_gadget gadget;
16 };
17
18 struct sandbox_udc *this_controller;
19
20 struct sandbox_usb_ctrl {
21         int rootdev;
22 };
23
24 static 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',
33               dev_seq(bus),
34               (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
46 static 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 {
52         struct sandbox_usb_ctrl *ctrl = dev_get_priv(bus);
53         struct udevice *emul;
54         int ret;
55
56         /* Just use child of dev as emulator? */
57         debug("%s: bus=%s\n", __func__, bus->name);
58         ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
59         usbmon_trace(bus, pipe, setup, emul);
60         if (ret)
61                 return ret;
62
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
70         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
83 static 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);
91         ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
92         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
108 static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev,
109                               unsigned long pipe, void *buffer, int length,
110                               int interval, bool nonblock)
111 {
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);
117         ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
118         usbmon_trace(bus, pipe, NULL, emul);
119         if (ret)
120                 return ret;
121         ret = usb_emul_int(emul, udev, pipe, buffer, length, interval,
122                            nonblock);
123
124         return ret;
125 }
126
127 int usb_gadget_handle_interrupts(int index)
128 {
129         return 0;
130 }
131
132 int usb_gadget_register_driver(struct usb_gadget_driver *driver)
133 {
134         struct sandbox_udc *dev = this_controller;
135
136         return driver->bind(&dev->gadget);
137 }
138
139 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
140 {
141         struct sandbox_udc *dev = this_controller;
142
143         driver->unbind(&dev->gadget);
144
145         return 0;
146 }
147
148 static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev)
149 {
150         struct sandbox_usb_ctrl *ctrl = dev_get_priv(dev);
151
152         /*
153          * Root hub will be the first device to be initailized.
154          * If this device is a root hub, initialize its device speed
155          * to high speed as we are a USB 2.0 controller.
156          */
157         if (ctrl->rootdev == 0)
158                 udev->speed = USB_SPEED_HIGH;
159
160         return 0;
161 }
162
163 static int sandbox_usb_probe(struct udevice *dev)
164 {
165         return 0;
166 }
167
168 static const struct dm_usb_ops sandbox_usb_ops = {
169         .control        = sandbox_submit_control,
170         .bulk           = sandbox_submit_bulk,
171         .interrupt      = sandbox_submit_int,
172         .alloc_device   = sandbox_alloc_device,
173 };
174
175 static const struct udevice_id sandbox_usb_ids[] = {
176         { .compatible = "sandbox,usb" },
177         { }
178 };
179
180 U_BOOT_DRIVER(usb_sandbox) = {
181         .name   = "usb_sandbox",
182         .id     = UCLASS_USB,
183         .of_match = sandbox_usb_ids,
184         .probe = sandbox_usb_probe,
185         .ops    = &sandbox_usb_ops,
186         .priv_auto      = sizeof(struct sandbox_usb_ctrl),
187 };