1dfd84001SSimon Glass /* 2dfd84001SSimon Glass * (C) Copyright 2015 Google, Inc 3dfd84001SSimon Glass * Written by Simon Glass <sjg@chromium.org> 4dfd84001SSimon Glass * 5dfd84001SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6dfd84001SSimon Glass */ 7dfd84001SSimon Glass 8dfd84001SSimon Glass #include <common.h> 9dfd84001SSimon Glass #include <dm.h> 10dfd84001SSimon Glass #include <usb.h> 11dfd84001SSimon Glass #include <dm/root.h> 12dfd84001SSimon Glass 13dfd84001SSimon Glass DECLARE_GLOBAL_DATA_PTR; 14dfd84001SSimon Glass 1520419987SBin Meng struct sandbox_usb_ctrl { 1620419987SBin Meng int rootdev; 1720419987SBin Meng }; 1820419987SBin Meng 19dfd84001SSimon Glass static void usbmon_trace(struct udevice *bus, ulong pipe, 20dfd84001SSimon Glass struct devrequest *setup, struct udevice *emul) 21dfd84001SSimon Glass { 22dfd84001SSimon Glass static const char types[] = "ZICB"; 23dfd84001SSimon Glass int type; 24dfd84001SSimon Glass 25dfd84001SSimon Glass type = (pipe & USB_PIPE_TYPE_MASK) >> USB_PIPE_TYPE_SHIFT; 26dfd84001SSimon Glass debug("0 0 S %c%c:%d:%03ld:%ld", types[type], 27dfd84001SSimon Glass pipe & USB_DIR_IN ? 'i' : 'o', 28dfd84001SSimon Glass bus->seq, 29dfd84001SSimon Glass (pipe & USB_PIPE_DEV_MASK) >> USB_PIPE_DEV_SHIFT, 30dfd84001SSimon Glass (pipe & USB_PIPE_EP_MASK) >> USB_PIPE_EP_SHIFT); 31dfd84001SSimon Glass if (setup) { 32dfd84001SSimon Glass debug(" s %02x %02x %04x %04x %04x", setup->requesttype, 33dfd84001SSimon Glass setup->request, setup->value, setup->index, 34dfd84001SSimon Glass setup->length); 35dfd84001SSimon Glass } 36dfd84001SSimon Glass debug(" %s", emul ? emul->name : "(no emul found)"); 37dfd84001SSimon Glass 38dfd84001SSimon Glass debug("\n"); 39dfd84001SSimon Glass } 40dfd84001SSimon Glass 41dfd84001SSimon Glass static int sandbox_submit_control(struct udevice *bus, 42dfd84001SSimon Glass struct usb_device *udev, 43dfd84001SSimon Glass unsigned long pipe, 44dfd84001SSimon Glass void *buffer, int length, 45dfd84001SSimon Glass struct devrequest *setup) 46dfd84001SSimon Glass { 4720419987SBin Meng struct sandbox_usb_ctrl *ctrl = dev_get_priv(bus); 48dfd84001SSimon Glass struct udevice *emul; 49dfd84001SSimon Glass int ret; 50dfd84001SSimon Glass 51dfd84001SSimon Glass /* Just use child of dev as emulator? */ 52dfd84001SSimon Glass debug("%s: bus=%s\n", __func__, bus->name); 53*7832d01eSBin Meng ret = usb_emul_find(bus, pipe, udev->portnr, &emul); 54dfd84001SSimon Glass usbmon_trace(bus, pipe, setup, emul); 55dfd84001SSimon Glass if (ret) 56dfd84001SSimon Glass return ret; 5720419987SBin Meng 5820419987SBin Meng if (usb_pipedevice(pipe) == ctrl->rootdev) { 5920419987SBin Meng if (setup->request == USB_REQ_SET_ADDRESS) { 6020419987SBin Meng debug("%s: Set root hub's USB address\n", __func__); 6120419987SBin Meng ctrl->rootdev = le16_to_cpu(setup->value); 6220419987SBin Meng } 6320419987SBin Meng } 6420419987SBin Meng 65dfd84001SSimon Glass ret = usb_emul_control(emul, udev, pipe, buffer, length, setup); 66dfd84001SSimon Glass if (ret < 0) { 67dfd84001SSimon Glass debug("ret=%d\n", ret); 68dfd84001SSimon Glass udev->status = ret; 69dfd84001SSimon Glass udev->act_len = 0; 70dfd84001SSimon Glass } else { 71dfd84001SSimon Glass udev->status = 0; 72dfd84001SSimon Glass udev->act_len = ret; 73dfd84001SSimon Glass } 74dfd84001SSimon Glass 75dfd84001SSimon Glass return ret; 76dfd84001SSimon Glass } 77dfd84001SSimon Glass 78dfd84001SSimon Glass static int sandbox_submit_bulk(struct udevice *bus, struct usb_device *udev, 79dfd84001SSimon Glass unsigned long pipe, void *buffer, int length) 80dfd84001SSimon Glass { 81dfd84001SSimon Glass struct udevice *emul; 82dfd84001SSimon Glass int ret; 83dfd84001SSimon Glass 84dfd84001SSimon Glass /* Just use child of dev as emulator? */ 85dfd84001SSimon Glass debug("%s: bus=%s\n", __func__, bus->name); 86*7832d01eSBin Meng ret = usb_emul_find(bus, pipe, udev->portnr, &emul); 87dfd84001SSimon Glass usbmon_trace(bus, pipe, NULL, emul); 88dfd84001SSimon Glass if (ret) 89dfd84001SSimon Glass return ret; 90dfd84001SSimon Glass ret = usb_emul_bulk(emul, udev, pipe, buffer, length); 91dfd84001SSimon Glass if (ret < 0) { 92dfd84001SSimon Glass debug("ret=%d\n", ret); 93dfd84001SSimon Glass udev->status = ret; 94dfd84001SSimon Glass udev->act_len = 0; 95dfd84001SSimon Glass } else { 96dfd84001SSimon Glass udev->status = 0; 97dfd84001SSimon Glass udev->act_len = ret; 98dfd84001SSimon Glass } 99dfd84001SSimon Glass 100dfd84001SSimon Glass return ret; 101dfd84001SSimon Glass } 102dfd84001SSimon Glass 103b70a3feaSSimon Glass static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev, 104b70a3feaSSimon Glass unsigned long pipe, void *buffer, int length, 105b70a3feaSSimon Glass int interval) 106b70a3feaSSimon Glass { 107b70a3feaSSimon Glass struct udevice *emul; 108b70a3feaSSimon Glass int ret; 109b70a3feaSSimon Glass 110b70a3feaSSimon Glass /* Just use child of dev as emulator? */ 111b70a3feaSSimon Glass debug("%s: bus=%s\n", __func__, bus->name); 112*7832d01eSBin Meng ret = usb_emul_find(bus, pipe, udev->portnr, &emul); 113b70a3feaSSimon Glass usbmon_trace(bus, pipe, NULL, emul); 114b70a3feaSSimon Glass if (ret) 115b70a3feaSSimon Glass return ret; 116b70a3feaSSimon Glass ret = usb_emul_int(emul, udev, pipe, buffer, length, interval); 117b70a3feaSSimon Glass 118b70a3feaSSimon Glass return ret; 119b70a3feaSSimon Glass } 120b70a3feaSSimon Glass 121dfd84001SSimon Glass static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev) 122dfd84001SSimon Glass { 12320419987SBin Meng struct sandbox_usb_ctrl *ctrl = dev_get_priv(dev); 12420419987SBin Meng 12520419987SBin Meng /* 12620419987SBin Meng * Root hub will be the first device to be initailized. 12720419987SBin Meng * If this device is a root hub, initialize its device speed 12820419987SBin Meng * to high speed as we are a USB 2.0 controller. 12920419987SBin Meng */ 13020419987SBin Meng if (ctrl->rootdev == 0) 13120419987SBin Meng udev->speed = USB_SPEED_HIGH; 13220419987SBin Meng 133dfd84001SSimon Glass return 0; 134dfd84001SSimon Glass } 135dfd84001SSimon Glass 136dfd84001SSimon Glass static int sandbox_usb_probe(struct udevice *dev) 137dfd84001SSimon Glass { 138dfd84001SSimon Glass return 0; 139dfd84001SSimon Glass } 140dfd84001SSimon Glass 141dfd84001SSimon Glass static const struct dm_usb_ops sandbox_usb_ops = { 142dfd84001SSimon Glass .control = sandbox_submit_control, 143dfd84001SSimon Glass .bulk = sandbox_submit_bulk, 144b70a3feaSSimon Glass .interrupt = sandbox_submit_int, 145dfd84001SSimon Glass .alloc_device = sandbox_alloc_device, 146dfd84001SSimon Glass }; 147dfd84001SSimon Glass 148dfd84001SSimon Glass static const struct udevice_id sandbox_usb_ids[] = { 149dfd84001SSimon Glass { .compatible = "sandbox,usb" }, 150dfd84001SSimon Glass { } 151dfd84001SSimon Glass }; 152dfd84001SSimon Glass 153dfd84001SSimon Glass U_BOOT_DRIVER(usb_sandbox) = { 154dfd84001SSimon Glass .name = "usb_sandbox", 155dfd84001SSimon Glass .id = UCLASS_USB, 156dfd84001SSimon Glass .of_match = sandbox_usb_ids, 157dfd84001SSimon Glass .probe = sandbox_usb_probe, 158dfd84001SSimon Glass .ops = &sandbox_usb_ops, 15920419987SBin Meng .priv_auto_alloc_size = sizeof(struct sandbox_usb_ctrl), 160dfd84001SSimon Glass }; 161